deng-1.9.0-beta6.9+dfsg1/0000755000175000017500000000000011523517366013255 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/0000755000175000017500000000000011523516243015065 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/Doxyfile0000644000175000017500000002254211357170240016576 0ustar keeskees# Doxyfile 1.4.7 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = deng PROJECT_NUMBER = OUTPUT_DIRECTORY = ./doxygen/all CREATE_SUBDIRS = YES OUTPUT_LANGUAGE = English USE_WINDOWS_ENCODING = NO BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = YES INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO BUILTIN_STL_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES ALIASES += "kludge=\xrefitem kludges \"Kludges\" \"Kludge List\"" ALIASES += "fixme=\xrefitem fixme \"FIXME\" \"FIXME List\"" #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = YES EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = YES FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = doxy-warnings.txt #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = ./ FILE_PATTERNS = *.c \ *.cpp \ *.h \ *.m \ *.C \ *.CPP \ *.H \ *.M RECURSIVE = YES EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = */external/libcurl/* \ */external/libpng/* \ */external/zlib/* \ */doxygen/* \ */packs/* \ */build/* \ */.svn/* EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = YES INLINE_SOURCES = YES STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = YES REFERENCES_RELATION = YES REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = ./doxygen/header.html HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = YES TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = __JDOOM__:=1 \ __JHERETIC__:=1 \ __JHEXEN__:=1 \ __JDOOM64__:=1 \ UNIX:=1 \ WIN32:=1 \ MACOSX:=1 \ USE_MULTITEXTURE:=1 EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = YES CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = YES CALLER_GRAPH = YES GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = MAX_DOT_GRAPH_WIDTH = 1024 MAX_DOT_GRAPH_HEIGHT = 1024 MAX_DOT_GRAPH_DEPTH = 1000 DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO deng-1.9.0-beta6.9+dfsg1/doomsday/build/0000755000175000017500000000000011523516205016162 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/0000755000175000017500000000000011523516205020272 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/dpdehread.cbp0000644000175000017500000000454511357170240022710 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/dpexample.cbp0000644000175000017500000000467111357170240022747 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/dpwadmapconverter.cbp0000644000175000017500000000566011357170240024514 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/dswinmm.cbp0000644000175000017500000000566011357170240022445 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/jdoom.cbp0000644000175000017500000003606211357170240022077 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/jdoom64.cbp0000644000175000017500000003530311357170240022246 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/dsdirectsound.cbp0000644000175000017500000000543211357170240023636 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/jhexen.cbp0000644000175000017500000004052611357170240022250 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/jheretic.cbp0000644000175000017500000003150311357170240022557 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/dsopenal.cbp0000644000175000017500000000530411357170240022567 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/doomsday.cbp0000644000175000017500000010620211357170240022600 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/codeblocks/doomsday.workspace0000644000175000017500000000224111357170240024030 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/README0000644000175000017500000001407111357170240017045 0ustar keeskeesTHE DOOMSDAY ENGINE =================== by Jaakko Keranen $Date$ INTRODUCTION ------------ This document contains brief notes about the Linux version of the Doomsday Engine. See the main Doomsday Readme in the Doc directory for more information about the engine itself. COMPILING --------- Compiling instructions can be found in Build/COMPILING. If you are not familiar with compiling programs in a Unix environment, see the generic instructions in the INSTALL file. Also carefully study the requirements listed in Build/COMPILING and make sure you have installed all the needed development resources and packages that your Linux distribution provides. Note that binaries are available for certain platforms: http://deng.sourceforge.net/dew/Engine/InstallUpgrade REQUIREMENTS ------------ In addition to the libraries needed to build Doomsday, you will need one or more IWAD files from a supported game. For example, DOOM.WAD from Ultimate Doom would be suitable. If you don't own any of the original games (Doom, Heretic or Hexen), you can always use the shareware/demo versions. You won't be able to play without an IWAD file! ADDITIONAL RESOURCE PACKS ------------------------- There is a wealth of additional resource packs for Doomsday on the internet. One starting point is Doomsday HQ (http://www.doomsdayhq.com/). I recommend also visiting the DHQ Forums for the latest community buzz. The must-have packs are the 3D models and detail textures. You might also wish to download a music pack (e.g., http://www.sycraft.org/). If you prefer to launch the game from the command line or using a custom shell script, there are two ways you can load PK3s and WADs: 1) Use the special automatic resource directories. You have two options: the user-specific Auto directory, or the system-wide Auto directory. The user-specific Auto directory is located in the runtime directory. The -userdir option defines the runtime directory. By default the current directory is used. Let's say you have installed Doomsday into the directory PREFIX. You will find the subdirectory "share/deng/Data/" under PREFIX. If you have a resource pack for jDoom, placing it into the system-wide Auto directory "PREFIX/share/deng/Data/jDoom/Auto/" will cause it to be automatically loaded when any user starts jDoom. Note the capital "A" in Auto. 2) Use the "-file" command line option when you start Doomsday. If you e.g. have the resource pack ~/mydir/model.pk3, just use "-file ~/mydir/model.pk3". MIDI MUSIC ---------- Doomsday can play MIDI music using a program of your choosing. The environment variable DENG_MIDI_CMD determines the command that will be used when starting playback of a MIDI music file. I recommend using MIDI only with sound cards that have hardware support for playing MIDI music (e.g. SB Live). Otherwise, it is advisable to just disable music playback with the "-nomusic" option. For example, the DENG_MIDI_CMD environment variable could be set like this: export DENG_MIDI_CMD="aplaymidi -p 65:0" The default program for MIDI playback is "timidity". Note, however, that music playback may become choppy since timidity plays music entirely in software. It is best to experiment with different timidity settings (e.g., buffering and process niceness) if you would like to reduce any artifacts in software music playback. GLBSP ----- Beginning with version 1.8.1, Doomsday can generate glBSP data automatically. It is no longer necessary to run glBSP separately on your WADs. However, if you need it, you can get glBSP from glbsp.sourceforge.net. RUNNING THE GAME ---------------- These instructions apply to the Linux version of Doomsday. The Snowberry launcher is available for Linux. If you prefer launching from the command line, I recommend creating your own startup scripts for jDoom, jHeretic and jHexen. In them, you can specify any command line options you wish to use. Below is a simple example. #!/bin/sh /usr/local/bin/doomsday -game jdoom -file ~/wads/doom.wad \ -userdir ~/doomsday/jdoom Before running this script you will need to create the runtime directory ~/doomsday/jdoom. All savegame files, message logs and other such files will be stored in this directory. The default location for the doomsday executable is /usr/local/bin, but that can be changed by providing your own prefix for the configure script (see Build/COMPILING). RUNNING A DEDICATED SERVER -------------------------- You can give the option "--without-opengl" to the configure script if you don't want to compile the OpenGL renderer at all. Start the game as you normally would, but use the "-dedicated" command line option. This will make Doomsday run in a text-only console mode. For more instructions on how to configure the server, see Doc/Network.txt. Brief instructions: 1. Start with the "-dedicated" command line option. 2. Configure the TCP (cvar "net-port-control") and UDP (cvar "net-port-data") port numbers. The TCP port is used for accepting new clients. The UDP port is used for data traffic. The default port number is 13209 for both TCP and UDP. This step has to be done only once because the port numbers are saved automatically into the game config file. You may also wish to write your own .cfg startup script that executes all the necessary commands. 3. "net init tcpip" 4. "net server start" 5. The current map can be changed with the "setmap" console command. 6. The server can be stopped with the command "net server stop". If you wish to exit the program completely, use the command "quit". Even briefer instructions: 1. Make sure you have already configured the TCP/UDP port numbers. 2. Start with the command line options "-dedicated -server". DOCUMENTATION ------------- It is always a good idea to glance through the engine readme: http://www.doomsdayhq.com/doc_readme.php The Doc directory contains various documentation about the engine and the available command line options. The documents are also available online: http://www.doomsdayhq.com/ deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/0000755000175000017500000000000011523516243017126 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/jheretic_cl.rsp0000644000175000017500000000544511357170241022136 0ustar keeskees .\..\..\plugins\common\src\d_netsv.c .\..\..\plugins\common\src\d_netcl.c .\..\..\plugins\common\src\d_net.c .\..\..\plugins\common\src\dmu_lib.c .\..\..\plugins\common\src\m_multi.c .\..\..\plugins\common\src\hu_menu.c .\..\..\plugins\common\src\p_xgsec.c .\..\..\plugins\common\src\p_xgsave.c .\..\..\plugins\common\src\p_xgline.c .\..\..\plugins\common\src\p_xgfile.c .\..\..\plugins\common\src\p_view.c .\..\..\plugins\common\src\p_user.c .\..\..\plugins\common\src\p_inventory.c .\..\..\plugins\common\src\p_tick.c .\..\..\plugins\common\src\p_switch.c .\..\..\plugins\common\src\p_svtexarc.c .\..\..\plugins\common\src\p_start.c .\..\..\plugins\common\src\p_mapsetup.c .\..\..\plugins\common\src\p_mapspec.c .\..\..\plugins\common\src\p_saveg.c .\..\..\plugins\common\src\p_terraintype.c .\..\..\plugins\common\src\p_plat.c .\..\..\plugins\common\src\p_iterlist.c .\..\..\plugins\common\src\p_map.c .\..\..\plugins\common\src\p_floor.c .\..\..\plugins\common\src\p_door.c .\..\..\plugins\common\src\p_ceiling.c .\..\..\plugins\common\src\p_actor.c .\..\..\plugins\common\src\p_automap.c .\..\..\plugins\common\src\p_player.c .\..\..\plugins\common\src\x_hair.c .\..\..\plugins\common\src\r_common.c .\..\..\plugins\common\src\rend_automap.c .\..\..\plugins\common\src\m_ctrl.c .\..\..\plugins\common\src\m_fixed.c .\..\..\plugins\common\src\hu_pspr.c .\..\..\plugins\common\src\hu_inventory.c .\..\..\plugins\common\src\g_defs.c .\..\..\plugins\common\src\g_eventsequence.c .\..\..\plugins\common\src\g_controls.c .\..\..\plugins\common\src\g_game.c .\..\..\plugins\common\src\g_update.c .\..\..\plugins\common\src\f_infine.c .\..\..\plugins\common\src\hu_stuff.c .\..\..\plugins\common\src\st_lib.c .\..\..\plugins\common\src\hu_lib.c .\..\..\plugins\common\src\hu_log.c .\..\..\plugins\common\src\hu_msg.c .\..\..\plugins\common\src\am_map.c .\..\..\plugins\jheretic\src\g_ctrl.c .\..\..\plugins\jheretic\src\h_api.c .\..\..\plugins\jheretic\src\h_refresh.c .\..\..\plugins\jheretic\src\h_main.c .\..\..\plugins\jheretic\src\h_console.c .\..\..\plugins\jheretic\src\p_telept.c .\..\..\plugins\jheretic\src\p_spec.c .\..\..\plugins\jheretic\src\p_sound.c .\..\..\plugins\jheretic\src\p_setup.c .\..\..\plugins\jheretic\src\p_pspr.c .\..\..\plugins\jheretic\src\p_oldsvg.c .\..\..\plugins\jheretic\src\p_mobj.c .\..\..\plugins\jheretic\src\p_maputl.c .\..\..\plugins\jheretic\src\p_lights.c .\..\..\plugins\jheretic\src\p_inter.c .\..\..\plugins\jheretic\src\p_enemy.c .\..\..\plugins\jheretic\src\m_cheat.c .\..\..\plugins\jheretic\src\tables.c .\..\..\plugins\jheretic\src\st_stuff.c .\..\..\plugins\jheretic\src\m_random.c .\..\..\plugins\jheretic\src\in_lude.c .\..\..\plugins\jheretic\src\acfnlink.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/dsopenal_cl.rsp0000644000175000017500000000005611357170241022137 0ustar keeskees .\..\..\plugins\openal\src\driver_openal.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/jdoom_cl.rsp0000644000175000017500000000526311357170241021447 0ustar keeskees .\..\..\plugins\common\src\d_netsv.c .\..\..\plugins\common\src\d_netcl.c .\..\..\plugins\common\src\d_net.c .\..\..\plugins\common\src\dmu_lib.c .\..\..\plugins\common\src\m_multi.c .\..\..\plugins\common\src\hu_menu.c .\..\..\plugins\jdoom\src\g_ctrl.c .\..\..\plugins\jdoom\src\d_api.c .\..\..\plugins\jdoom\src\d_refresh.c .\..\..\plugins\jdoom\src\d_main.c .\..\..\plugins\jdoom\src\d_console.c .\..\..\plugins\common\src\p_xgsec.c .\..\..\plugins\common\src\p_xgsave.c .\..\..\plugins\common\src\p_xgline.c .\..\..\plugins\common\src\p_xgfile.c .\..\..\plugins\common\src\p_view.c .\..\..\plugins\common\src\p_user.c .\..\..\plugins\common\src\p_tick.c .\..\..\plugins\jdoom\src\p_telept.c .\..\..\plugins\common\src\p_switch.c .\..\..\plugins\common\src\p_svtexarc.c .\..\..\plugins\common\src\p_start.c .\..\..\plugins\common\src\p_terraintype.c .\..\..\plugins\common\src\p_mapsetup.c .\..\..\plugins\common\src\p_mapspec.c .\..\..\plugins\jdoom\src\p_spec.c .\..\..\plugins\jdoom\src\p_sound.c .\..\..\plugins\jdoom\src\p_setup.c .\..\..\plugins\common\src\p_saveg.c .\..\..\plugins\jdoom\src\p_pspr.c .\..\..\plugins\common\src\p_plat.c .\..\..\plugins\jdoom\src\p_oldsvg.c .\..\..\plugins\jdoom\src\p_mobj.c .\..\..\plugins\jdoom\src\p_maputl.c .\..\..\plugins\common\src\p_iterlist.c .\..\..\plugins\common\src\p_map.c .\..\..\plugins\jdoom\src\p_lights.c .\..\..\plugins\jdoom\src\p_inter.c .\..\..\plugins\common\src\p_floor.c .\..\..\plugins\jdoom\src\p_enemy.c .\..\..\plugins\common\src\p_door.c .\..\..\plugins\common\src\p_ceiling.c .\..\..\plugins\common\src\p_actor.c .\..\..\plugins\common\src\p_automap.c .\..\..\plugins\common\src\p_player.c .\..\..\plugins\common\src\x_hair.c .\..\..\plugins\jdoom\src\wi_stuff.c .\..\..\plugins\jdoom\src\st_stuff.c .\..\..\plugins\common\src\st_lib.c .\..\..\plugins\common\src\hu_stuff.c .\..\..\plugins\common\src\hu_pspr.c .\..\..\plugins\common\src\hu_log.c .\..\..\plugins\common\src\hu_lib.c .\..\..\plugins\common\src\hu_msg.c .\..\..\plugins\common\src\f_infine.c .\..\..\plugins\common\src\am_map.c .\..\..\plugins\jdoom\src\tables.c .\..\..\plugins\common\src\r_common.c .\..\..\plugins\common\src\rend_automap.c .\..\..\plugins\jdoom\src\m_random.c .\..\..\plugins\common\src\m_fixed.c .\..\..\plugins\jdoom\src\m_cheat.c .\..\..\plugins\common\src\m_ctrl.c .\..\..\plugins\common\src\g_defs.c .\..\..\plugins\common\src\g_eventsequence.c .\..\..\plugins\common\src\g_controls.c .\..\..\plugins\common\src\g_game.c .\..\..\plugins\common\src\g_update.c .\..\..\plugins\jdoom\src\d_items.c .\..\..\plugins\jdoom\src\acfnlink.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/dpexample_cl.rsp0000644000175000017500000000005611357170241022311 0ustar keeskees .\..\..\plugins\exampleplugin\src\example.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/dswinmm_cl.rsp0000644000175000017500000000017411357170241022011 0ustar keeskees .\..\..\plugins\winmm\src\cdaudio.cpp .\..\..\plugins\winmm\src\midistream.cpp .\..\..\plugins\winmm\src\dswinmm.cpp deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/dsdirectsound_cl.rsp0000644000175000017500000000007211357170241023202 0ustar keeskees .\..\..\plugins\directsound\src\driver_directsound.cpp deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/dpdehread_cl.rsp0000644000175000017500000000005011357170241022244 0ustar keeskees .\..\..\plugins\dehread\src\dehmain.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/doomsday_cl.rsp0000644000175000017500000001474311357170241022161 0ustar keeskees .\..\..\engine\portable\src\def_read.c .\..\..\engine\portable\src\def_main.c .\..\..\engine\portable\src\def_data.c .\..\..\engine\portable\src\ui_panel.c .\..\..\engine\portable\src\ui_mpi.c .\..\..\engine\portable\src\ui_main.c .\..\..\engine\portable\src\tab_tables.c .\..\..\engine\portable\src\m_vector.c .\..\..\engine\portable\src\m_string.c .\..\..\engine\portable\src\m_nodepile.c .\..\..\engine\portable\src\m_filehash.c .\..\..\plugins\common\src\m_fixed.c .\..\..\engine\portable\src\m_gridmap.c .\..\..\engine\portable\src\m_huffman.c .\..\..\engine\portable\src\m_md5.c .\..\..\engine\portable\src\m_misc.c .\..\..\engine\portable\src\m_mus2midi.c .\..\..\engine\portable\src\m_bams.c .\..\..\engine\portable\src\m_decomp64.c .\..\..\engine\portable\src\m_args.c .\..\..\engine\portable\src\m_linkedlist.c .\..\..\engine\portable\src\m_binarytree.c .\..\..\engine\portable\src\m_stack.c .\..\..\engine\portable\src\s_wav.c .\..\..\engine\portable\src\s_sfx.c .\..\..\engine\portable\src\s_mus.c .\..\..\engine\portable\src\s_main.c .\..\..\engine\portable\src\s_logic.c .\..\..\engine\portable\src\s_environ.c .\..\..\engine\portable\src\s_cache.c .\..\..\engine\portable\src\gl_defer.c .\..\..\engine\portable\src\gl_texmanager.c .\..\..\engine\portable\src\gl_tga.c .\..\..\engine\portable\src\gl_tex.c .\..\..\engine\portable\src\gl_png.c .\..\..\engine\portable\src\gl_pcx.c .\..\..\engine\portable\src\gl_main.c .\..\..\engine\portable\src\gl_hq2x.c .\..\..\engine\portable\src\gl_font.c .\..\..\engine\portable\src\gl_draw.c .\..\..\engine\portable\src\rend_console.c .\..\..\engine\portable\src\rend_bias.c .\..\..\engine\portable\src\edit_bias.c .\..\..\engine\portable\src\edit_map.c .\..\..\engine\portable\src\rend_sprite.c .\..\..\engine\portable\src\rend_sky.c .\..\..\engine\portable\src\rend_shadow.c .\..\..\engine\portable\src\rend_particle.c .\..\..\engine\portable\src\rend_model.c .\..\..\engine\portable\src\rend_main.c .\..\..\engine\portable\src\rend_list.c .\..\..\engine\portable\src\rend_halo.c .\..\..\engine\portable\src\rend_fakeradio.c .\..\..\engine\portable\src\rend_dyn.c .\..\..\engine\portable\src\rend_decor.c .\..\..\engine\portable\src\rend_clip.c .\..\..\engine\portable\src\r_world.c .\..\..\engine\portable\src\r_util.c .\..\..\engine\portable\src\r_things.c .\..\..\engine\portable\src\r_sky.c .\..\..\engine\portable\src\r_shadow.c .\..\..\engine\portable\src\r_model.c .\..\..\engine\portable\src\r_main.c .\..\..\engine\portable\src\r_extres.c .\..\..\engine\portable\src\r_draw.c .\..\..\engine\portable\src\r_data.c .\..\..\engine\portable\src\r_lgrid.c .\..\..\engine\portable\src\r_lumobjs.c .\..\..\engine\portable\src\p_bmap.c .\..\..\engine\portable\src\p_ticker.c .\..\..\engine\portable\src\p_think.c .\..\..\engine\portable\src\p_sight.c .\..\..\engine\portable\src\p_particle.c .\..\..\engine\portable\src\p_control.c .\..\..\engine\portable\src\p_cmd.c .\..\..\engine\portable\src\p_players.c .\..\..\engine\portable\src\p_mobj.c .\..\..\engine\portable\src\p_maputil.c .\..\..\engine\portable\src\p_material.c .\..\..\engine\portable\src\p_materialmanager.c .\..\..\engine\portable\src\p_intercept.c .\..\..\engine\portable\src\p_data.c .\..\..\engine\portable\src\p_dmu.c .\..\..\engine\portable\src\p_linedef.c .\..\..\engine\portable\src\p_objlink.c .\..\..\engine\portable\src\p_plane.c .\..\..\engine\portable\src\p_polyob.c .\..\..\engine\portable\src\p_sector.c .\..\..\engine\portable\src\p_seg.c .\..\..\engine\portable\src\p_sidedef.c .\..\..\engine\portable\src\p_subsector.c .\..\..\engine\portable\src\p_surface.c .\..\..\engine\portable\src\p_vertex.c .\..\..\engine\portable\src\dam_main.c .\..\..\engine\portable\src\dam_file.c .\..\..\engine\portable\src\dam_blockmap.c .\..\..\engine\portable\src\bsp_edge.c .\..\..\engine\portable\src\bsp_intersection.c .\..\..\engine\portable\src\bsp_map.c .\..\..\engine\portable\src\bsp_main.c .\..\..\engine\portable\src\bsp_node.c .\..\..\engine\portable\src\bsp_superblock.c .\..\..\engine\portable\src\sv_sound.c .\..\..\engine\portable\src\sv_pool.c .\..\..\engine\portable\src\sv_missile.c .\..\..\engine\portable\src\sv_main.c .\..\..\engine\portable\src\sv_frame.c .\..\..\engine\portable\src\cl_world.c .\..\..\engine\portable\src\cl_oldworld.c .\..\..\engine\portable\src\cl_sound.c .\..\..\engine\portable\src\cl_player.c .\..\..\engine\portable\src\cl_mobj.c .\..\..\engine\portable\src\cl_main.c .\..\..\engine\portable\src\cl_frame.c .\..\..\engine\portable\src\cl_oldframe.c .\..\..\engine\portable\src\net_ping.c .\..\..\engine\portable\src\net_msg.c .\..\..\engine\portable\src\net_main.c .\..\..\engine\portable\src\net_event.c .\..\..\engine\portable\src\net_demo.c .\..\..\engine\portable\src\net_buf.c .\..\..\engine\win32\src\sys_audiod_loader.c .\..\..\engine\portable\src\sys_audiod_dummy.c .\..\..\engine\portable\src\sys_audiod_sdlmixer.c .\..\..\engine\portable\src\sys_opengl.c .\..\..\engine\portable\src\sys_timer.c .\..\..\engine\portable\src\sys_system.c .\..\..\engine\portable\src\sys_sock.c .\..\..\engine\portable\src\sys_network.c .\..\..\engine\portable\src\sys_master.c .\..\..\engine\win32\src\sys_input.c .\..\..\engine\win32\src\sys_findfile.c .\..\..\engine\portable\src\sys_filein.c .\..\..\engine\portable\src\sys_direc.c .\..\..\engine\win32\src\sys_console.c .\..\..\engine\portable\src\b_context.c .\..\..\engine\portable\src\b_command.c .\..\..\engine\portable\src\b_device.c .\..\..\engine\portable\src\b_main.c .\..\..\engine\portable\src\b_util.c .\..\..\engine\portable\src\con_busy.c .\..\..\engine\portable\src\con_data.c .\..\..\engine\portable\src\con_buffer.c .\..\..\engine\portable\src\con_main.c .\..\..\engine\portable\src\con_config.c .\..\..\engine\portable\src\con_bar.c .\..\..\engine\portable\src\dd_zone.c .\..\..\engine\portable\src\dd_zip.c .\..\..\engine\win32\src\dd_winit.c .\..\..\engine\win32\src\sys_window.c .\..\..\engine\portable\src\dd_wad.c .\..\..\engine\portable\src\dd_plugin.c .\..\..\engine\portable\src\dd_pinit.c .\..\..\engine\portable\src\dd_main.c .\..\..\engine\portable\src\dd_loop.c .\..\..\engine\portable\src\dd_input.c .\..\..\engine\portable\src\dd_help.c .\..\..\engine\portable\src\dgl_common.c .\..\..\engine\portable\src\dgl_draw.c .\..\..\engine\portable\src\dgl_texture.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/jhexen_cl.rsp0000644000175000017500000000567111357170241021623 0ustar keeskees .\..\..\plugins\common\src\d_netsv.c .\..\..\plugins\common\src\d_netcl.c .\..\..\plugins\common\src\d_net.c .\..\..\plugins\common\src\dmu_lib.c .\..\..\plugins\common\src\m_multi.c .\..\..\plugins\common\src\hu_menu.c .\..\..\plugins\common\src\g_update.c .\..\..\plugins\common\src\p_view.c .\..\..\plugins\common\src\p_tick.c .\..\..\plugins\common\src\p_svtexarc.c .\..\..\plugins\common\src\p_start.c .\..\..\plugins\common\src\p_mapsetup.c .\..\..\plugins\common\src\p_actor.c .\..\..\plugins\common\src\p_automap.c .\..\..\plugins\common\src\p_player.c .\..\..\plugins\common\src\p_user.c .\..\..\plugins\common\src\p_inventory.c .\..\..\plugins\common\src\p_switch.c .\..\..\plugins\common\src\p_terraintype.c .\..\..\plugins\common\src\p_mapspec.c .\..\..\plugins\common\src\p_plat.c .\..\..\plugins\common\src\p_iterlist.c .\..\..\plugins\common\src\p_map.c .\..\..\plugins\common\src\p_floor.c .\..\..\plugins\common\src\p_door.c .\..\..\plugins\common\src\p_ceiling.c .\..\..\plugins\common\src\x_hair.c .\..\..\plugins\common\src\r_common.c .\..\..\plugins\common\src\rend_automap.c .\..\..\plugins\common\src\m_ctrl.c .\..\..\plugins\common\src\m_fixed.c .\..\..\plugins\common\src\hu_pspr.c .\..\..\plugins\common\src\g_defs.c .\..\..\plugins\common\src\g_eventsequence.c .\..\..\plugins\common\src\g_controls.c .\..\..\plugins\common\src\g_game.c .\..\..\plugins\common\src\f_infine.c .\..\..\plugins\common\src\p_saveg.c .\..\..\plugins\common\src\hu_stuff.c .\..\..\plugins\common\src\hu_log.c .\..\..\plugins\common\src\hu_lib.c .\..\..\plugins\common\src\hu_msg.c .\..\..\plugins\common\src\hu_inventory.c .\..\..\plugins\common\src\st_lib.c .\..\..\plugins\common\src\am_map.c .\..\..\plugins\jhexen\src\g_ctrl.c .\..\..\plugins\jhexen\src\x_api.c .\..\..\plugins\jhexen\src\hrefresh.c .\..\..\plugins\jhexen\src\hconsole.c .\..\..\plugins\jhexen\src\h2_main.c .\..\..\plugins\jhexen\src\p_things.c .\..\..\plugins\jhexen\src\p_telept.c .\..\..\plugins\jhexen\src\p_sound.c .\..\..\plugins\jhexen\src\p_spec.c .\..\..\plugins\jhexen\src\p_setup.c .\..\..\plugins\jhexen\src\p_pillar.c .\..\..\plugins\jhexen\src\p_pspr.c .\..\..\plugins\jhexen\src\p_mobj.c .\..\..\plugins\jhexen\src\p_mapinfo.c .\..\..\plugins\jhexen\src\p_maputl.c .\..\..\plugins\jhexen\src\p_lights.c .\..\..\plugins\jhexen\src\p_inter.c .\..\..\plugins\jhexen\src\p_enemy.c .\..\..\plugins\jhexen\src\p_anim.c .\..\..\plugins\jhexen\src\p_acs.c .\..\..\plugins\jhexen\src\p_waggle.c .\..\..\plugins\jhexen\src\m_cheat.c .\..\..\plugins\jhexen\src\tables.c .\..\..\plugins\jhexen\src\sn_sonix.c .\..\..\plugins\jhexen\src\sc_man.c .\..\..\plugins\jhexen\src\po_man.c .\..\..\plugins\jhexen\src\m_random.c .\..\..\plugins\jhexen\src\in_lude.c .\..\..\plugins\jhexen\src\st_stuff.c .\..\..\plugins\jhexen\src\acfnlink.c .\..\..\plugins\jhexen\src\a_action.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/installerbg.bmp0000644000175000017500000045566011357170241022153 0ustar keeskeesBM[6(:  ("(".#',#'(",#&+!&+"&)!$) #,#&)!$)!$)!$) #("&!) #&")!$2'+'"+!$'") $(".$'("+"&+!%0%)4(,+!&-#'/%)+!%/$)+!%,#&0&*1&*0&**!%,!&-#&+!%+!&.$'.$(.$(1&+/%)1&+3(,0&*+"&0&)/$)1'*1'+1&*1',2'+,"&,"'3(,.$).$),"&1&*3)-6+/6*/3',.$).$),#&.$)/%*3'+0%*3',2&+2&+6*/3',.#'7,08,16*/4)-3(,9,19,1/$)1&*6+/9,11%)1&*6*/.$(+!%5*.0%)* $,"&1'*1',1'*1'*/$(/$(+!%+"&.#'.#'4(-3',-#'1'+/&*0&*.$)-$'0&*.$(-$'-$',#&+!%)$,#&(#+"&4)-(#+#&("* $("-$'("+!&* $/$(1&*) $+!&,#'("+"&(") #,#&,#',#&&!("("&!&!)#) #(#&!*!$,#&) #0%*/$(+!&.#(,#&*!$) #*!$*!%,#&+!&*!%* #&!#+!&-#'.#(0&*(#+"%,"&+"&* $/%)/%(-#(2'+-#'-#'(#/$)-$(* $-$(-#&-#'-#'-#'/%(+!%.#(/%(+!&0&)0&),"&/%).#(/$(0&)1'*/$(0%)3(-2(+5*.7+0-"&*!%/$(.$)5*/2&*2&+.$(3(+:-23(,0%)/#(/%)/%)3'+3'+/%)0&*/%)-#'4)-5*.0%*4(-;.33'+8,14(,2&+4)-3',.$(5*.4)-7+0/$)1&*3(+2(,:,27+0@27-#(2'+1'+1'+1'+0&)4)-3(-4(-/$(,"&0&)2(,/$(7*04(-0%*4(,1&+.%(-#&-$'.$(0&)/$)-#(,"&(#% -#(/%(/%)2&+(#+"%+"&+"&* #.#(-#'+"&0%)*!%*!$%!+!&*!$&!*!$) #) #) #) #*!$&!) #) #&!) #(#'!(#*!$3',2'+*!%,#&,#&(#*!%) #*!%-#',#&% &!*"%* $/$(,#',"&-#(+"%-$(-#'* $'"/%)1%*.$)0%*/%)-#',"%/$)/%)-"&.$)1'*/%)-$'/%)-#&-#'-#'-#'/%*0&).#(/%)* #1'+-#'2'+4)-5)/-#(1'*4(-@176*/5*/4(.3(,-#(1&*/%)-$(1%*2'+6*/7,07+02'+2'+1%*3'+2'+3'+2'+5*/6*/3(,/$)2'++"%/$(/$(2'+9-20%*3',7,04)-7,05*/2'*1&*4).5*/3(-8+09,2056+/4).7+03),,"%-"'3',.$)5)..$).$)6*08,15*/0&*4)-4(-5*.5*.3(,3(,6+/3(,-"'/#(,"&3',3',4),7+05*/5)/4).."'.$)2'++"&+"%8,16+/2'+-$';.32'*3(-2',7+05).2'*3',0&)1'*1&*0&*2',2',.$'/$(,"&5).3(-2'+3',2',0%*-$') $0&*/$),#&.$),"&,#',"%0%)-$(.%)+"%0%)+"%%("* $-$'.$)+"%*!$+!%)!$.$(,#'*!%+"&+"&,"'+!%) $,#'+"&*!$*!$+!%*!$*!$+"&* $+"&+!&+!&.$(+"&-#(*!$*!$*!$% * $'"*!%*!$* $.$(+"&.$(/$)/%)+#&0%)'"-#(+!$-$(+!%-#(-#(,"&+!%-#&4(-2'+-"&1&+0%*1&+/%).%(2(+/&)0&)/%(/%)/$(.#(0&)-#'1&):,2-#(2(+.#(1&*1&)6*//$(3(-2&+9,0>053'+4).7,02'+7+02&+4)-8,09,2:-21&*1&+1&+.#'0%)1&+1&+5*-6+/6+/5*-4(,6*/6*/7+08-19,24)-7,04*-2'+2'+2'+2&+2&+2'+6*/,"&-#'2&+3(-2'+1'*2(+5*.3(-1&)+"&0%)1&*0&)2',/%)1&+1&+0&*4(-1&+2',/%(-$'.%(("-#'*!$-$(-#&+!&1&*-#(0%)0%)0&*,#&0%)'"-#(* $-#'* $+"&+"&*!$)"* $1%*/$()#-#'+"&,#'*!%*!$-#'*!%*!%*!$*!$+"%+"%.#('") #*"%) #*!$) #+"%*!$-#',"&'"*!$) #+"%+"%) #*!%*!%%!0%*1'+0%*0%*'#( #) #(#'#,#&) $,#&,"&* %.$(2'+.$'8+05).1&*4).2(,0%)/%(0&)2&+3)-3',2'+0%*,#'*!%3',4(-6*/9-11%*3(,5).3)-2&*7+07+06*/<.35).5)..%)7+05*.0%*6*.4)-5)-5)-4(,5*./%)3',5*.4)-8+05*.7+07+04(,0%*4(,5)-5)-4)-8+04(-8-17+15*.3'+3),3',2'+-#(/%)2(+5).5).7+02(,2'*5).2'+5*.3(-0&*2'+2'+4).,"&.$(0&).#(/%(.#'0%).$(2'+0%**!%-#',"&.$(.$'+!%,"&,"&'"2'+2',0%*0%*'#(#(#'"&!*"%'#*"%* #'"+"%.#(*!$3',0%*,"&/%)-#'*"%*!$*"%,"&-#''"*!$.$(*!$)#) #*!$-"'* $* $)#*!$* $)#+"%+"%,"&+ $-"') #+"%&!% /%).$(1&+/$(+!%(#'!(#-#&-#'.$'-#'-"&) $+!%/%(;.3:,21&*3(,3(,/$'1&*/&)1&+4).4)-,"&,"'2'+1&*7+04(-3(,5).3(,6+/6*/1&*.$(8,19,16+08,18,16*.3(,8+08+04(-7*09-18,15*-7+/4(-1&+1&*1&+6*.8,04)-7,0-$)0&*2&+1&+5)-6+/4(-6*/1&+8+05*.6*.6*.4)-3'+2&+0%)3(,3(+8,16+/1&*/$)6*03(,1&+3(,4(-1&*1&*1&)4).0&).#'/$(/%)2&+/$(/$(-"'.$'.$'-"&/%).$(/$)-#'/$)+!%-#&'#&!0&*/$)1&+.$(+!%'"%!'"+"%+"%+"%+ $) #&!'"+"%6*/4(-,"&-$'-$') #+"%*!$+"%.$(*!$(","&-#(* $*!$(".$(*!$,"&*!$,"&-#'+"%,"&,"&,"&.#'.#(.#(+"%.#((#* $,#&'"(#(#("(#,#&,!%-#',"&.%(1'+2'+-#'.#(,!&6*/4).3(,5).4).3',0%),"&4).3',2'+4(-1'*2(+2'*5+/5).5).2(+8,13),,!&0%*2'+7+09,15*.4)-6*.4)-;.39-16+/9+19,19-28+05).;.38+14(,6+.9,18,05).5).6+.8+18+15)-9,17+05).5*.2&+7+05+.4)-6*.0%*4(,3',.%)3',5).4).0%).$(+"&-#(3),2'+2&*2'*1&*1'*1'*3',3)./%(0&),#&3),/%(0&*/%(1%*2&+/%(0%)0%*0%)0%*0%*0%*-#&0%)) $+!$,#&'"(#(#'"'"+"%* $+!%*!$,"%.$(.$(* $*!$("1&*/%).$(/%).$(-#'*!$&".$(("*!$+"%,"&.$(,"&("0%*+"%-#',"&.$(.$(.$(0%*-#(-#'+!$* $*!$+"%0%*(#,"%/%)( $.#(* $,#&'"0%*0%*.$(0%*.%(.$'2'+.$(1',0%*1%*5).2'+4)-0&*0%)0&)+!&0&*/$(2',1'*0%)5*.3(,8+07+/7+04)-8+0.$(7*/2'+7*/2'+7*/6*.5(-3'+5)-?06059-24(,6+.=05;.48+06*.7)/6).5)-7*/7+07)..%)2&*3),2'+2'*4(-3',.#(1'*2'*2'+4)-2'*,#&6*/0&*2'+1&*2(,3',3',4)-1&+0%*.$',!&,"&-#&2'+* $,#&0%*( $.#()$,"%&!.$(.#(,#&.#(,"%*!$.$(*!$-#(,"&,"&/%)-#'.$(+"%*!$*!$&!*!$) $,"&+"%,"&+"%+"%'"*!$+"%-"',"&.$(.$(0%)-#'+"%.$(/$).$(+"%+"%+"%&!'!) %'#+"%( #-#'*!%*"%+"%) $-$'-$'.$'2(+*!%.$'0&).$'/%).$(1&+0&)4)-3',,"'1&*0&)3(-4(-1'+1&*2(+-$(:-2:,19,1:,1.$)0&+0&+/&*.$)4)-0&+5*-4),1',7+/<.36*.B3:?16:,1>16=.48,/8,08,1:-2?1616:-2<.49,15*-3(-1'+;-28+06*./%).#'8*/6*/;.45)-4)-3(+6*/9,11&*2'+4(-1'+.$)1&*2'+1&)1'*+"&/%(/&)1&+1&*3(,3(,5(-1&+.$'1'+1'+1&*-$'-$'-$''"("*!%'#+"%(#,"%) $) $) $'#+"%+!$+"%.$('"*!$,"&*!$+"%) $,"&+"%.$(-"''"+"%+"%.#(,"&,"&,"&,"&*!$+"%*!$-"'*!$+"%+"%+"%+"%,"&-"''") $*!%+"%/%)+!%(#+"%,"%,"%*!%("-$'-$'.$'* $.$(+"&+"&2',.%(+"&,#'/%(2',0&)0&)-$(0&*0%).$(2',3(,5).3(,5).1'*2(+-#(,"'7+07*/;-37+03(,0%*.#(/%*5)-5*-6+.5*.5)-0&*2(,7+/G7=F6;9,1=/4;/36*.8,08,09-1=05B292',2',7+/;-37+/7+/8,07+.5*.:-39,2.#(0&*7+/.$(5*.9+05)-,"&.#(4),7+02(,5)-7*/3(,9+07+02'*0&*2'+2(,3(,3(,2',2',2'+0%)0&*/%(2'+/%(/%(/%(/%(.%(0%*0%** %+"&,"&-#&1'*,"&) #,"%,"%,"%* %'!,"%,"%,"%'#,"%( #( #.$(+"%'#( #+"%.#(+"%+"%( #+"%*!$( #,"&*!$*!$,#&+"%*!$-#&*!$+"%+"%*!$-#&-#&*!$-#&-#&+"%+"%/#(-#',#&)!$+"%( $*!$.$(*!%/$(-#&(#-$'1%*3',*!$.$(/%(+#&1%+4(-,#'/%(-#'3)-1'*3',1'+2(+3(-2(+3(,5*/6).6+/6).6*/3)-6*//%)2'+3(+.#(/%)/%)/$(/%)5*-3(-6*-4)-7+/:.2:.35*-6+/3(-@17=/4;/4?16056*.7,/7,/7,/7+/3(-1'+3(-9,15*-0%*/$(4)-1(,7+/8,11&+5*-9-18-16*.8*/4*-5*-5*-:.4:,11&+2(+1&*2(+3(+1'+0&)3(+0%)1&*0&)/$(1'+1&+/%(1&*1&*/%(/%(1&+0%).$(+"&-#&*!%*!%/$(*!%.$(,#&("-#&/$(1%*(#,#&,"%( $-#'0%)( $+"%( $/%(,#&-#',#&-#&-#',#&-#&&!) $*!%+"%+"%+"%.#'+"%-#'+"%'"'"'"*!%,#&.$)-#'1%*/$)) $/$)/$)&!,"%,#&-$'.$'.$') $)#) %0%)/%).$(0&)2&+3&,3',7*/3(--$'7+12'+4(-4(-5*.7*/9,1<.46+/6).4)-2'*2'+5).;.30%)4),7+10&+7+01',5*-/$(9-29,17+/:,17+/6+.;/37+.:.3:,2:-2?05;.3?059-17,03(-2&,;.37+/8,0:.28,07,03(-B29;.43).:-21&+7+/>05@172',5*-:,10&*7+/=05<.3;.38+1;-2:-25*.5*.0&+2'+:,13(,7+02'*0&*0&*1&)2'*1'*3(,1&*3',0%)+"&+"&+"&.$(0&)3',0&)4(-2&++"%1&+1&*'"-#&-#&.$'-$'-$')#'"(#.$'-$',#&.#'.$(.$(.$(2&+.$)) $2',-#'.$(.$(/%)0%)2&+4(-!(#'"'#(#) $,#'*!%-#',#',#'+"%(#'#'","%+"%+!%0&*/%)*!%/%(/%(-#(*!%* $,"&-#&* $-#'* %2',0%*1&*/%)2'-0&*3(,0&*1'*+!%0%)1'+4)-5*.9,17*/:-28+04)-9,09,16+/4(-4)-4)-.$(.$(1'+/$)4)-1%*5*/1'+2',2'-1&*6+/6*-6+/;/42'+6*.9,16+/6+/4).8,18,0?06:-22%*4)-9,2/53',8,08,09,19-2:.2054(-8,14)-=159,1=04;.29-19-2;.315A49;.27,/6+/0%);.34).1%*1%);.39,19,1>/43(-6+/7,0>05<.46*/7+/9,19-16+/8,015>15>26H8?M;BB39>26B4:=/4;.2@17D4;4(-7,02(-:-2069-19-19,1=/49,115B49D5;C4:K:@I:@E615G8=;.3:-15*.<.49,1063(-5).9,16*.7+/2(,7+06*.;.39-16+/.$(0%)0%)0%(0%)5).1'+-$(1&+4(-1'*0%*.%)3(,.%(-$(2&+4(-1&*0%(-"&( #1&*.%(0%)/%(0%(2'+.%(/%(0%*0%(/%(-#&.$(-#&.#',"%.$(-#'-#'0%*2'+-#'0%).$(/%(0%*,"%*!%*!%(#) #*!%,#&.$(-#&+"&+"&+"&,#&*!%*!%) #* $(#2',-#&1&),#&* $1&*/%).#&0%)+!&/%)1&),"&,#&.$(1&*3(,4)-.$)1&*2'+1&+3(,.#(.%)4(,4),4),4(,2'*5)-9,2:-20&*7+/7+/5)-7*/7+/7+/:-36*.6*.5)-5*-5*.8+01&*9,19,1:-19,18,0;-2?17=04H9?B4:?16C49G8>J9?=04B39>05?17>06A398,0A38>06:-2:-1=058,09,1>06:-25*-16?178+07+06*-06057+/?16;.3?163(-0&+9-2:-28,01&*2(,7+/;.29-1;/25*/=/4A29=/5C49>05;.3;/2:-105?26B49?26E5:?26;/25*.2'+6+05).:.2=/4>05?17;.2;.2C39C4:?169,1:-29-26+.8+0;.26*.A288+07+04(-4(,/%(3(,6).0'+0&+0&+2'+5).1'+1&+3(+/%)0&*4(,.%)4(-4)-2'+2&+2'+*!%4(,0&)-#'3(,.%(.%(.%(0%)0%)'"&!*!$$ (#-#&-$'0%)/%(.$(.$(0%)/%(0&*0%)/%(/%(3(,3(,(","&-#&,"&) $+"%-#&-#&+"%-#&,"&-#&.$(/%),"&.$'.$(.#&/%)2',-#'+"%1&)0%)0&).%(2&*,"&1&*7+04),4)-5).0&)1&)1&)6)/8,03(,1&*5)-4(,5)-2'+3(+3(,0&*2(,9-0<049-15),2(,+"%8,05)-9-09-08,0=056+/9,1:-2:-29-14)-8,09-1<.35*006C5:15@27=/4=/4?16J9?=05=04068+/=069.29,0@17:/3;/36*/5(-=06B4:;.3=03?17C4:B49<03=06=03:-2?17H8>=04=04A39A39A39?27C5:A39D5;F6;D4;E6;L;@J9?=16=03>07;-2@38?1705/%(7+05).3(,06B393',3(,;/34(,<.3=14<04?28B49=04B49C5:=15?27F625C6:A39C6:G6=?28A39?28C5:=/5>26>15?28?16<04A39F6=C4:=057*02'+7*/8+0;/3:.13)-069.20%)5*.5*.:/36*.6*/4)-;/216=05@38;-26*/B3:D5;@28C4;>16A3:>26>268+1?26>15>16?36=/4C5;E6;G7=I9?A39>15?27@27A39>26B4:=15?168+1=14L05?17>05?06=/3M=BG6=?16A38>04>04>15?269-2?15C49H8>L:AM;BA38B38C4:D6;B28:-2?15H9>B5:B38>04?17G6=D5:>14B49?05@38D5:?06;.3;.39,0:/2:,15*/4(-9,03',3(-5).:-18,0<04<044(,7+/7,/6,/6+/:.37,/5(-;.3=048,17+/7*/6*/8,14',3(,,"&3'+4)-4(-.$(5).0%).#(-#'.#'-#'1&*3',6*/2'*0&)1'*5).3',1'*2'+0%)0%)0&)+"%,"&,"&0&)2'+0%)0&)-#'.$'3',+"&/$() #,#'0&)0%)0&)3(,3(,0&).$'/$(0$(+!%.$'-$'4)-5)/4(--#'2(+3'+1%)/$(3(,/%)0%)8-16*..$)7*/7*/8,1=.47+01'+0&*4(,5)-7+/5)-6).8+08+07*/=.4=/4;.2;.3B38=1606B39<.28,18,17+0H8>B39J8@L;B>25>26F6;C5;B39@36E7;H8>M;BE7;C4;G7047+0B39D5:=/4J9?J9?E6;I8>A38G6=A38?27=04E7D5;B48B38?16=/3@37C5;A38F515?27?15>15?16F6=<03A48F7=;03:-2?17F5=;03<04:.29+09+0=064)-9-1;.37*/4(-/%(-#',#&-$'1',5(-/$(5*-8+05)-1&*5*-7*/5(-2&*-#'-"'2&+7,04),/%(2'+1&*0%(1%),#'-$(5)-5)-0%(/%(-#'2'+1'*3',/%()"+"&+"&+"&-#'/$()"* $+ $+!%+ $+"&+!%0&)) #+"&+"&+"&+"&+!%+ $) #,#'0&)-$(1&)0&)1'*1&),#'-$(3(,4)-4)-2'*5).4)-6+/4),2'+1&*1&+8,08,14),8,06+.9,15*-8,06,/6+.1&+1%)6,/8,07,/15>15:.3=14J9@C6;B38E714<04=14>157,1<04>15E5:F6;6*/16>165*/8-13(-<037,05*/@274(-;/2?16=04>14>15?26?15B38C3:?36:.36*/9-3D4;8-1:.3K:@H7=E506B39;/48,0B38?15A38G6=E6<:.3F605<04?06;/2B38=/46+0<.38-09-19-08-08-07,/1'*1%*2'+2',2',7+/9,19-36+.3(,/%*-#(/%)5*.4),2(+.$)' ".$(9,05).3),7,06)/2'*2'*,#',"&3'+4).1'*,"&-$(2'*4(-0&)3',0&)1'*1'*5*.2'++!%.$(1'**!%/%).$(3(,+"%& & ) $+"%.$(1'*/%).$(1'*2'+4(,3(,3(,3(,2(+4),.#'-"&.$(/%)0%)=/49-29-2?06>055*-6*.4),4),1&*7+/8,19,18,0;/4;.29,16*/6*/;/34(,:.1=/4G6=H8?B5:=/4?28;.2;.27,18-1?16=05A49?16@17?15@27A27A28F7=J:?C6:B59:,27,1F7=A38;/3;-2G7>E716J:AE715A27=/59,1D605?16;.2=05<03>057,1@2915G7=C5;=04=04=15=047,1>1515A37:-2?15?26B38C4:I9@D5:A48C49A48I9@I9@D6;B38?26C49C49E7==057*/6*/;-3?25=14A27?16@27@17>15?16=15=146*/5(-4)-4)-6*.6*.;/2<.3;.3>156*.6*.5*.7,/:.2:-26*.6+.9-1=158,17+/8,0>168,07+/6*-8-1=043),7,17,05)-6*-1'+-"&7,17+14)-2(+5*-2(+3'+9,15*-0&)3(,3(,0&)6*/6*/6*/7+03(,0&)3(,0&)+"&+"&* $) #) #1'*.$(,#'.$(-#'.%(2'+5*/3(,5*.3(,3(,6*/1'*1'*7,03(,8,15).8,17,03(+3(+6*/6+/9,06*.9-29,0?17;.45*-4).7,/9,19,09,09-1<04<04>17;.37,/<.3>058+/>16@27E615C5;@27B4:A489.3@27>15@26A48D6;H8>B49B49I:@E7=L;AG8>O=EF714B49>159,1@27@27A49>058,1=048,06*/6*/7+/@389,1;.36+/6+/3(-5*/@279,19,116D4:I9?I9?>15D5:E6;F715B3805;.2B39>16=/45*/3',9-19-1;.2;.19-1:.12&*0%)9-1:-1?17>06>169-13',3(-9,1:.27+/8,07+0?16=/51&+5).15?16?16=04;/305>16E6;H9>H9>G9=?17=04D5;;.3@26;.3C4:C4:D5:E7059-19,19-18,08,02(+4(,058,1=05E6=9-2@27F7=E6=B49I8>C5:G7>G8>B48C49C59C5:E6;?26B48G7>B48B489+17*/9,1<.49,1:,127D5:B59@37E5;F7<@27A479-2B49@37C4:B48G7=B49A47B37?26E6<6*/:/39,1:-2=04?26;/48+05)-2(+7*/?16=04>056*.6*.3',3(-6+/;.2=04;.3;.39-19-19,19,0?17:.2;/39,08+/=05B387*.9-17+/>057*/0'+0'+6*.>169,25*-5*-:.39-2=058+04)-/%)1'*5*-7*/4)-6*.4)-4)-4)-9-24)-3(,1'*2(+/%):-28+06+.3(,8+03(,8+07+/6+.4)-=/57+/4)-8+02'*4)-7+/3),2(+4),;/43),7+/0'+6*.6*.9-14*-7+.7+/9,016;/2?16:.3;.3=15D5;A38F7=A38F606=/4>05>/5:.2;.29.18-0<.3@2805>05>/4>16?16;.3>14=/3=03D5;C49C59F716D6;F705C5:9.2@27?27>046+06+.@27=/3A49E6<>04=/3;.27,16+03(,<.35*/;.2<.3<.3:.1B39=049-17,/>16058,1:.2A296+/7+08,1?17?16FF8=D5;B58B59E6;>16H9>H9>H:?O=CF716C59E6;;/4B58D5;=15B48I9?C5:<14@26I9@>15A27?15;/4:/49-38-26+.7+09.3>14>15156+/;/39.19-19-13',3(-5*/;.39-15).<048,16+.:.29-1=043(,8,05*-9.21&*0&*6*.8-14(+6)-6*.0&*5)-5)-6)-4(,+"%/%)8,12'*3(+4(,5)-6*.4(,8,1/%)5)-6*..%)4(,6*.3'+2'*4(,3'+9-10&*0&*A38B48?177*/3'+4),0&*6*-5*-9-2:.21'*6)-7+/4(,6+.:-29,17+/3',=05;.4:,19+08+06+.9-29+08,1A38F7=?367+0=05?279,05(-:,1:,1;/36+/1'*3'+=/5E5:05>05A486+/7+/@38D5::.3<04A279,05*-;-2F7;B39F7;C6:P?EC49F7;J9?J9@I8>K:AD5:?38=17@38E7;E7;K:@F8J9@F7;J9?:.2<-2A28>16B39M05@179,08,//48,18,18+/B49E6;/48-1<.3?16B27B49C49@27F8G9=F717E605=04=/49,0=/4:-37,/3)-5*.5+/8,0A37:-2B4:F615=04@17B28B38C393'+5(-6+/;03C39<03;.3=14:-26+0?16F8J:AI9>E5;F717A38=/3>16A27I9>@27D4:J:AO=DF8269.1@27B38?36G6=E6;:.2;/39,17+07,0=25?26>2616C59F7;=26=26I9?<16@26@26D49E6;=16C39E5:A37P>EI9>F8<@38@38D49@37>06>06:.2;/3D4:J9@I8>K058-16*.<.3>25@36B38=04<14<0416165)-5*-3'+0&*0&*6+.7+/6+.4(,5*-5)-6+.4(,3'+5)-0&*1&*:.23'+6+.1&*3'+1&*-#&5*-9,18+0;.36*.6+.8,07,/:,2;.3;.3=04<.39-1;.38-0;.2:.2;/3>16D6;C5:@37@37E725<.3?26@27:-1?15?26;.2:.2@48>/4K;@O=DM;A>16C6:?16A38;/4A38@28@27:.3;/4:.3:,1;/3?16>/4:.2?16@37@37@37F7=9,19,1B5::-1=148+09,07+/2'*;/2?16=/5?27:-19-1;.3:.1;.305:.2:.2?168+04(,5*-6+.4(,6+.4(,6+.7+/1&*5*-9,11&*9,1<.37+/,"%3'+:.26+.7+/5*-1&*/%)1&*/%)1&*6*-;/38,0:-2:-2:,28,06*.3(,?069-1=158-0=05=/59,1056).8,1:-2>05@26A48C49C5915D59D5:I:@B38G8=MB38F705A38B38E6;?06A38>17A38E6;G9>G8=E6;I9@J05D6:B48@27@16A479-29-29+0:.2A47D5:F7<>15D6:@273'+;-2C59=14>1516:.23'+0&*4(,5*-8+05)-.#'7+/16=0415A39D4:16:.1@37I9>4(,>059-29,1;/3=04B49@27:-29,1A27A38?26A37D5:C49=05C49F7<;/4C59A38F705>05>05B4:@27F7;J:?I9>J;@G8=>16D6:H8=D6:H8=M=DR@GG7056+/E6:C49C49B49@2615B38B49A37?16C4:D5;7+/D5:;/2A38169-0;/3;.38,/:.2<04:-22'+5*.>16=05;.39-1=05:.2=05?167+/9-14),8,04),9-1@27.$'6*.1'+1&*3(,4),8,00&*;.31415A38D6:;/4A27G8>I9?B38<05C499,0<.3G8=>16>16>17A38I9?G716B49B5:=05A27D6;J:?J:?H8=J;@G8==/5A27H8=?06D69F6F7H8?B48B38F7<>15>15@27<03B498,0;/2;/2;.2?1615=05=04:.27+/7+.7+.0&*6+.9,15*.=/48,09-1=059,15+.@27:-26+.5+.8,01'+0&*3)-8,04*-5+.3)-5+./$(2(,>15;/41&*5*-2(,7,09.29.2;/46+/5*-6+.4)-6+/2'+3'+0%)8-10%)3(,;/47,09.2?166+/4(,?275*/5+/6+/8-1<04A398-16+/?26@276+/>15>15=148-19.39.3?169/3=14@27D6:=15B48E6;H8>G7=B49F7=A48=16D5:K;A>16B48A38F7E7;H8>N1604B4:F7;A38E7;A49G7=C5:H8=?16<04G8=G8EB486+.A48F7<=14D5:C49?16<15?26A38A27B48G8>I9?E6<9.2=149.3?26A48A38C4:=04:/2;038-2164)-3)-3)-6+.8-1=054)-2'+9.29.21&*7,07,06+/2'+2(,2(,6+/2(,5*-5*-1&*1&*?16@27=057+/6+.2(,?16067+/:.2?16:-17+/9-1A499-0@27:.3:.3@27?26A27?25I:?<05A38E7E7;>27D6;B59F8K<@D7;A4:A49I:?M@28F8?26>159.2G8=C5;A48?16C5;=04A49A28@28>15G8??1715=05?16E615?25?26D6:7+0@36D5:B48E6;J:@E6;D5:G8=I:?E6;C59G8=@38E7;C5:H9>UBJO>ELDK;@O>DC6;C6;K;@C5;C5;C5;C5;A28B5:F8;J:?I:?A49KH9>H9=I:?E7:P>DQ?E9,1;.3=/5H9>@38A47=059-2:.3D6;C59B38?26A38C5:E6;@27=04;/3166+.;/36*-5*-7+/16:.22'+5*-8,08,07+/?16?16/%)5*-6*-8,08,09-1>057+.;/3;/3@278,/:-2:-2?16=04B49?26I8?A39=047,0;/2=04?16>05>15Q>EO>DH8>F7=K;AK:@A27B49@37G8>B38F716?17N=CLD6;R@GM=BVCJTAHK;@C5;B38F7=K;@L;@J:?F7=?17I9?K;@C5;B49B5:H9>H8>I:?D5;G8=F8;H9>@39L;AF7C5:9-1<03?26?16=05F716;/3D5;=/58,02(,5*-7+/8,07+/7+/G7=E6;?16=05A38@277+/-#'/$(5*-1&*A38:.2A389-18,06+.:.2?165*->16;.38,0;.38+/158,0A38A38A39C4:>05;/2>15A38A48<03L;BP?EH8>C5:K;AN=DA27B49D6:C59H8>I:@D5:I9?K;AK;AF8P>EI:?G8G9=Q?FQ@GLCF7=?16>05A38C5;G8J:?H8>I9>G8=G8=>16<.305>05<05=058,1=/46+/;/4:-2<.3?27B49K;A@37C49I:@D6;A38D5;J:?A48@27=14B49G7=;/2E705A2806;/35*.=05=05=/5=058,05*-8,0:.2:.25*-C4:F705<046*.3(,@27>05<046)-2'+<05<058,0:.1A38>268,09,0E6;:-2?16=04;/3;03=14@28A28B59?269,1;.2G7=9-2A38R@FS@FI9>D5;I9?E6G9=P>ELCWCKMD6;B5:J:?B5:D5;G7<@17A49B5:A28G8J;@L=CG9=A39F8<@38>26>05;.2<.3<.3;.3:.18,0;-2>16L;AC6:C69F7=D6:C5:A47@37J:@;.3?36D5:>25F626B49?265*.:.2>169-1?27G7=;03>15<038,0=04?26C5:25A38G7=O>EO=DH8>M;BK;AMDQ?ES@GJ9@H:=M=CK:AL;BMH9>@27J;?C6;J;?O=DD5;H8=JC4:C4:H9=B49F7;G7=?16LF8<;/2>05B39=/5>27?16<05C6:9-18,/B49B58J9?G9>I9?C5:9.2;.3B49D5;?26A38@37H9?H8=9,1=14F7=;.2A495*/:-2?176+/:/2?37C5:?275*.9.1=058+/=05C4:8-0:.28,/3(,7,/9-1<046*.;.37,/9-1>05E605B39@271'+7,/7,/7,/?168-09-1:-29-19-13(,5)->059-19-17+/>05?06@27B59H8>E7EF7<@38C4:K;@N>EN>EO=DI9?C5;J9?B5:G7=?26K=@L=BO>DLH:>C4:I;>G9=B49F6;@39?27=/4D5::.1;.2@27?27;.3>168,0A27<04C59<05=05D6:A48F8=E606<03:/2B38>069,08,07+/;/3;.3=/4?16?16B49=05:-2>05;.3;/4;.3;.38-08-07,/<04L;A;.3A38A38-#'7+/9-19-1A38:-2;.39-17,/>05B397,/;.38-0@278-03(,4(,:.2B49=15:.2;.3A38@27D5:?2705?38=15E6I8>J:@J9?F7=SAHMKJ;@F7L=BJ;?N=CI;?H8=D5;I:>F6<@49@38@27A49F705<.4=169.23)-;.38,0;-2C69F7=C6:D6;B58A48B59A47H8>C4:D5;A48?26G615B39>25G7=>258,08,0>15F7<@48=04<04C49A38D5;?26;/35)-5)-;.3<05:.2A38?067,/9-1?169-18-0<04<04;/4<047,/L;AH8=>05>051&*5)-;.3/%(8-09-17+/9-17,/;.37,/;/49-12(,;.3C4:D4:6)-8,0:.2<05=/4=/58+0>26B38>17:.2>164(-:-1D5:=15>15<03@176+/=14E5;=05@37C5;D6;I9??16P>EXDKL;AJ:?A48G9>C69O=DN=CH9?H8>L;AP?EO>DG8=KMDI9>J;?H9>H8>H8=I;?=04=04C5:?16>04C4:F716:-1C69H8>=05D6;J9?L;AF6<25B5:@278,1A38J9@I9@:-1169.1=053'+7+/@27:.2:.28,/:-21'+7,/>057+/9-1;/4<04@277+/E6059-1;.3B397,/9-1:-2B38C4:A498-0=15;.3B5:05A28>27C49<04;/2;/3@27@38@39G8=>25>25C5:B39>15C4:@36B49A48J:?E8G7=N=CL;AI:?L;AI:@M;AM;BH8>S@GNF6CF7I:>KDJ:?D6;H7=K=@H9>D5;@17C5;H8=I9>JC6:D6;B58L;AG9=D5;@27D5;D5;D6<@47G6<@37B49J9@=14?26@27G8=H8>E7=;03@48>05D6;=05>27>05A27=16A38;.38-08-0056*.3(,5)-7,/8-05)-9-1?167,/>053(,:-26*.;.31'+1'+7*.K;@26;/39.1;/2;/3:/2@37@37;/3=15A48?17<03A49D7:C5:D5:M;AI9?>27E7;TAIK:@G9=F7DI;?D5;H8=I:>B5:F6;@38B4:>05@17A49B49@39?27A38C49?28;.2<.3F8<:.29.1;-2>25F6<9-1A2805?3716>158-0:.2=15;-37,/;/46*.;.3;.39-1?16<04;.38-09-1;.39-17,/9-16+.0&*6+.3(,8,08,02'+9-1?27?279-15*.3(,?27>169-17+.3(,4*.<04=04>06<04D5:?1615H9>B39?26A48E7DJ:AF7G9=F8CL=BK;@L=BH9=D5;D727=05D6:>16G9=L16E7<>05:.3=057+09-2C5:C5:E7;B49A37:-1A48H9>G9>@37;/39,1F7=D6;>16;/26*/7,1?37?26@27=15E6;?17;/3;/39-1=057,/9-17,/:.2C5:16@27>16H8>169-1;/3:.27,/:.28,08,09-18,0=05@27H8>0&*6+.@27@27?27:.29-1>168-0?17;/3<04?16@2815A39E6;F725A48F7=B49B49B59F7=B49@37KEF8R@GVCJI:>KCD7=P?FR@HH:>D7=L=BH9=I;?I;?C6?27J;@F805>27E7<>27@37D6;D6:A48B49E7P?E5*/<03F7=F715<04B49;/2A38<04=05?17@27;/35*/169-18,06+.8,01'+3)-@27B49A38@27;/36+.:.28,09,0:.2?27A38?1616?278-0C5:C5;B49J:@B59F7==14>15;/4B49G8>@37J;AG8=D6:D6:D6;D6;L=CE7G9=J;@K;@H9>H9>Q@FYELSAGM=CM=BJ;@F8CG9=L17B49B5:@27@27=/4=05@49:-2@39159-1:-2A48H9>=/4C5:C59=16G8>?25A378-1:/4I9>K;@I9?H8=B49<03@37=04=04>15C5:E6;A39>15?27@389-0;/3<04A495*.:.29-16+/>16=/5C49=05=05;/3B49;/3>166+.6+.3)-9-1=057,/?27B498,0:.216=05A38>167,/>16=05069-1?27A38=04A49E6;?26A39E6;=15<034).<03H8>C5;D5;C5:?16@37E6G8=G9=TAIZGMK<@N=DLDP?FK;@Q?FQ?FM=CH9=N=CL=BL=BL=BTBIK;@N>CH9>K;@L05E6;I9?>05C5:A37B58A483(-C5:;/3A38E6<>159-19,1F7=E6K;AVCIH9?B58G8=C5:E7;A38K;AF7EJ;@J:?J:?SAGKCN>CL=BK;@G8=K;@C6K;@@38B5;>17B5:E6;=/5=16A38=/4;/4>16:-2=16;/4?38>05>27E715:/3>25@37K:AC4:>15?26A38>15=04:.206>16:.2?16D4:@386+09.1A38=156*.?26C5::/4;.3:-2A38G8>K;ATBIM;AD6:G8=D6;E7;B48E6;ML;@K;@L=BK;@LB49C5:G817>16=16?27=06?26<05@49:-2>16;/4?38?168,1>16=/4=16A37I9?D6:C5:C5:E7;B49B49;.3D6:C5:?26>15F715?26?379-1@27?27;.3?17D49?275*/8,/9-19-19-1@27B386+.=05A38:.27,/0%)8,0;/33)-3(,2'+8,0=05@270%)1&*;.3:.24)-8-0?162'+8-00505;/3<14@27?16=15?26?26A394(-6*.@37>25=059-1?26@26I9?H8>:-2C5:G9>H:>P?FTCJN>DK;AN?D=/4D7:@27F8DTCIMEN=CP?EM=CK<@N>CTBHUBHL=@N>CP?FO>DP?EK<@K<@I9>G8=LI;?D5;A38J;?C5:C5:H8=B49B49>05>05=05A38?27>05D5:05=05B38D7:C69:-1@47D5;>15:.3C6;L;BH9?>25=14G8=>25?26E6;@27>15@48;/3?17>05:/2;03>06=/4:/2;/3;/3=/50%)1&*:.28-07+/3(,8,08,0@27?162'+:.2=15=156*.,#&3(,8,04)-4)-:.27+/8-09.19.12'+2'+2'+?16B499.1:.2@27;/3;/3:/2267+/B5;C4:K:AG7=MJO>DH9>L=BO=CO>DL;BTBHQ@FSCIG7DNDWFLRBGN>CN>CN>CP?FC49I9?M=CI9>G8=J;?H8>H8>I;>@17C5:F6;C5:A38F726>25D5;?26>16=14>15E7<;/3=04:.2;03:/2>17=/4:/27+/@27A389.12'+<054)-0%)16@37D715>25F7N=DJ;AK;AMDO>DN>DO?DL;AJH9>J9?K;AM>CI:?TBHK:AM=DK;@I;?Q?FO@EB49I;?LI9?C49I9?E605E6;?16>16D5:;.3@27G8=I9?D7:H:@G7=N=CH:?C6:B58I9?A48C5:>05:.29,1B49@476).0&*4)-3(,=04=14E615:.2D5:?27@38D6;>279,1=/5?26=05>26=05>26169,0;03>16=04;/2<04>16@27E6<>16B59A4:G8=B4:B499-2=04B39>05H9>E8F8>D6;C69K:@N=CL;AO?EMLMI;>R@FI:?J:?H9>O>EM=BD7<@37P@GF7=H9>K=@L;@N>CWDKP?FO=DE7F7C5;I:>C5:H:=J;@F705?27>27>27B49>16E7;G8=E8;L;A>16C69E7;M258-19-1@27<14@49@39:.2<14?27=04:/2;03=05>06C49;/3>26=16B49<0506:-26+/6+/<03=05G8=>15@27D5:<148,1A39E6;@37B49F7F7=H9>I9?D6;L;AC69G8>I9@L;AUCIWELP>EQ@FNDC6;LCN>CL>BTBHSBGL=AK<@K<@JJ:?F705E7;C49D7:C5:H8>B38@27D6;E626?27=14<14=15<03@27;/37+/7+/;03<04E7<05@279.15*.=/5?16:.215A38C5:>15?16=05>15?16:.26*.7+/>156*.2(,8-0;.32(,8-07+/3)-;.37+/8,0:.2K;@B59A48H9>B58F6DQAGP>EP?EI9?L;BLCMCQ?FK;@N>CR@GN=CO=DL=AE6H:=@27B49B49;/2?27?27E6;=/4>05D5:E7;D7:C49C6:<05D7:;/4A38A27:/3A48D5;:.3@47>15:.3B49=05>15@37B499-1?27E616=/5>05@27:/29.1?26158-04)-.$(1&*9-1;/3:.2:.27+/7+/3(,4)-4)->169-11&*=05:.2;.3:.2C5:B49>15:-1@38<04@27=04=05@38>15;.215B4:C4:B59E6DN>DLH9>J;?G9=I:?K;@F6ETBIM=BP>EQ@FLCL=BL=BO?DLE6<@28C4:H8>D5;F706H9>?16@27@27F705@27C5:H9>?27H:?D6;G9>D6:=05C5:E7;C5:C5:?16?16:-2;.3:.3E715G8=F7<@37;/3B49=05@28=04<04?2706=05<04>16=05?27C5:9-1<049-18,0=05<04<04>16?27K;A3(,:.2:.2:.2:.29-1=05;/3<047+/9-17+/4)-2'+4)-2&*1'*5*.;/3:.215A49F8=?26F7=I:?=05A48B49D6;G8>A48C5:H9?F8=C5:I:@E7;J:@J;ALKKEN>DJ;@R@GK;@KP@EP@EWDK@37H9>F7=J:?O?DN>CN>CR@GI9?I9?J:?E6H8>J;@D5;F705@27@27G8=?27:.1L05@27=049-27+/9-15).4),8,1>16=04>159,126<04=05?169-1;/3:.2=05@389-1?27B497+/:.2:.2<04>169-1:.2>16<049-1A38E6169-18-0<048-04)-=05:.2:.2:.26+/<044)-1'+5)-0&*2(,;/3;/3>16<04=15;/3H9>K;AL;AH8>I:@LDM=CJ:@LH9>J;?I:?I:?MCM=BLM=CI;?N=CB49C6;H:?I:?K=@K=@N>CSAHQ@GM=CI:>G9>D8D7C?38B49A39?27A38D6<>16E7;?27A38>27@49E7;>16?38L=CF7I:@I:?B59A48E7<@47;/4E616>15@37=15>2616@388-07,/9-14*.>16>16:.29-1?27>16>16A38A38=05B497,/:.2:.2?27=059-1;/39-19-1:.29-1=054*.:.24*.6+/;.3;/39.1:.2>159-05)-B5:=04?27>26=15?26=04=058-2C5;B4:G8=D6;>254).B59A48F7=G8=E7;H:?K;AH9?H9?F8=LDSAHN=CI:?I:?I;@M>DP?EN>DTBHR@FI:?I:?K<@SAGP?EG9F7=J;?P@FLD7::.3>16>16?38E7;K;AI9@C69E7;D6;D6;I:@G8>B49D6;A48A38B49@37D6;:/3@379.3;/3?27?26<14=05@37:/26*/C6;=04?26=15<04=05:.2:.25+/?27>06B38>168-0/%);/3:.2>16>16<04?27A38>16>16<041'+6+/:.28-09-1:.2=05;/39-12(,7,/4*.9-1:.2=053(,9-1:-25+/5*.5+/@27A499-1;/39.1=0415@48=15=14>158,09.3=14>25J:@>15@37H9>B59C5:C5:I:@I:@F8=LJ:@P@ESAHJ:@I:?G8=M>DH9>M=CM=CKP?FQAGLCN>CJ;@F8>N>CXFL[GOI:>P@E[GOLCF9>J;?I;?M=CM=CM=BO?EJ;?H:>N?DJ;@F8=L=BC6;C6;E725:/4@27A38C5;8,0>16>158.28,18-1B4:C5::/2168-08-0=04:.2=049-1:.2;.2=04=04>164)-9-19-09.19.1-$(:.24)-6+0?26;/315?27<03>25A37A38D6:A48?36C49F7;G8>B49B49D6:M>DMMQ@FR@FL;@L;AO>CJ;@P>DP?DNQ?EQ?FM=C\HPXELL=BL=B?27;/5H:?L=BP?DR@EQ@ELKJ;@G9=F8=I:?I:?I:?F816=14=14<14/&*=045*/7,1@37169-19-1:.2B5:8,0=16=165*.7+/:/2=058,09.1B69E7DJ;?G:=N?DH:>H:>G8=R@FLCK<@KD6;?277+/VCJL=BL=AQAHK;@KBH8=J<@E7;E6;H9=LB49E6;?16A48>16D5:C5:G8=?27F805?16D5;G7=A48C6;@38=04=255)-6+/?26:-2;.35*.@27;/3?27=05:/26+/:/2=05A383(,3(,3(,9-1=05267+/=05;/3=059.1;/39.19.13(,8,09-19-1A389.19-18,09-1;/39-1:/29.1;/38,0:-2?37;03;03=04?38@48B495*.A49;.3@38B59B5:7+/=15>25@38>26?36?26=04D6;H8>B59K;AD6:L=CF9>B59H:?E7<=05F8DH:>Q?FLBP@GK;@K=AQAGL=AL=AL=A^JRSCHJ:?J:?:/2L>BJ9?LBJ;@J<@M=CG7=A39I;?H:>F6B5:B59A38A49?16A48A38D5:C5:G8=C59G8>;.3I;?B69B49K;AA58A48@26@37B59@27A48?36A48=04>15C6;?36>36?26A49B59C5:5*.A48:.2?27@48@374)-:.2:/226;/38,0;/33)-8,0:/24*.;/3;/3@27@277+/=05=0515@39:-2;/38-1D5;>36<04E605>15?279.2:/4@37A38A48E6DI;?B49C49I:@O>DMDVCJQ@FQ@FM>BUBHUBHP?EMDLF8=J:?UCIUCII9?WDKZGNJ:?C5::/2D7=G8>L=AK;@L=AN>CKG8=G8=B5:G7F7F7;E6;E6;H:>E8>15E615@37?368-1=04>25<14A59>15@389-1:-27+/B38;039-1A38B49@278,08,09-13)-4*.9-19-19-126:/29.1>268,0>26>26>268,0267+/=0515=14?27<147-1=149-19-2H8>>25A38@47A48>15@37B59E616D7;H9?C49F8=G8=D7;H9>JM>DK<@N=DI;?LEI9>O>EJ;@J<@K<@L>BN>CI9>L=AG8=O?DVCJO?DR@GM>B>15B39G8>D716G8>H:?H:>@37E6;G9=>15E615?36H9>D7;7+0=25=15>25>25;/3<04>15=14>16;036+/:/26+/6+/C5::.2;/3:/2;/38,09.1;/3=05;/39.1:/2;/37+/5*.:/27+/;/3?27;/2=058,0>16;/3;/3C5:;/3=05:.106C5:@38<03;/2B5:=15>16>15=03A49@38<04C5;4),7+06*/B4:@26@36@36>156+.A47B47:/3F7=F7=D6;C59A38E7MCR@GO>DQ?FM=ASAHK;@TCIR@GTCJ^JRVDLB59=/5G8>N=AK;@LCM=AB49K;@L<@I9>K<@O>EG7=LO?EI:=H9=N>DH916G8F8=E7:D6:C5:F7=A38H9>D6;D6:LD6;?36>14D6;>26?27>15=03@38?27;.3A381'*4)-3(,>06:.1:.1:.18,00&):.1:.13)-=05=05;/3:.18,0;/3=0515F8=I9?>15F8=9.29.3D5;B48@27A48E6EK;AJ:@L;BK;AJ;@J;@O?EVDKO>EQ@FUCIH9>O>EN=CI9>L<@H8>N>CSBIN>CP?EM=ATCIR@GTCJK;@H9>G9>B59D5;N=AM=AQ@GM=AQ?FJ:?H8>I:?H8=J;@O>EH9>H9=F714>14@38=04?17=03@38<037+/B49C5:;/2;/2:-2@38B498,0?273)-3)-16;/38,0:.29-1>269-16+/<04?267+/<049-1@377+/8,0?37<04>15I:??26B5:9-1@27K;AL15D7;D5:I:?M=CTBHJ;@J;@C5:C5:N>DLCLG8>I9?LCN>CLCM>CE7I:?I:?J;@E6;L=BI:?F8?27@38?16B49B59E715@37>16B5:=049-2?37A498-1=15:-2@386+/7,0>26;.3;/3E7<;/3>265)-:.2D6;E6<8,0=155*.4)-9-1;/3<04=15?27<04>16=15=15>16<04=15;/3;/3=15;/3A38=15;/38-09.1;/38-0:.25)-<045*.5*.9.14(,=157-1=04A396*.=156*/7,07+/<14@37?27=148,0H8>C5:A38D7:E7;J;@I:?H9>TAGJ;@J;@K;@G9=D7L=BKSBHSBHO?EYFMQAGM=CP@EP@FXFL\HOTBIK=@G:?G8>G9?L=AM=CQAFN>CN>CJ;?M>CLDM>CC6;A39M=CN>DI:?K25@279-1@378,18,0<035).>268-2=04A385*.<045)-5*.4)-9.1<04;.38-03(,A38<04:.25*.2'+5+/9.1;/3;/3:.24)->16;/38-0:.2=15;/3;/3?27A38<04;/39.15+/:.2<04>165+/=15;.3>26=15>26C497+/;03:/27-1@38A49=15>15=14?37A488,1@38G8=>25A48B49E77,0<049-1?37F9=K;A>16H:>G9=K;AKLF8CM=BM=BO?DK<@O?DO?DN>CO?DUCJF7=G:?J;@G9?QAGM=CN>CSBIP@FLCJ<@KCLP?FK;@?16B6;F8H:>E816?271'*5*.2'+7,0=15A385*.=15>15=048-005>15<044*.4*.E6;8,1?26@26>16B48<049-1E7<>25B48E7;E7J:?G8=F7;J;AJ;AG8N=CJ:?LMCSAGH:=LCP>DLCN>CQ?EO>CWDKO?DI;@G8>L>BN>CZHNN>CJ;@G8>D7CN=BO>CL=BP?FMDC5:MF804;/3>158-15)-?278-015>16?27A38>16=044)-5+/15?2715268-2>15>15F7<@37G7=:.2D6;>25>25E7;MD@47=26>27D6:A48D6;F816B5:D7:H9>H:>I:?MEN=CK;@R@GO>DUDJWELMCM=BO>CI;>Q@EO>CR@FRAGM=BQ@EQ@ESAHG8>J;@G:?N>CR@FK=@G8>I;@G9?M=CI:?M=BK<@R@FQ@EM=BN=BM=BH:>UCIP?EP@FS@GC6;C6;B6;B6;A38H9>@27G8=D7:@49@49D7;E7C59D6::.2@37I9?B38?27@37?26=159.2>15B48A48A386+/=157,1168-08-0>15E6<>15A38=04C6;8-05+/5+/:.27,02'+5+/>15156,0>05;03;03B49=04A48:/3?26=14;/4A37:/3<04<04D6;F7=F8=E7;B59G9>B49D6:H:?H9=A48=05H8=?38C69E7<<05F7D7:E7;D6;E8;B5:M=BN=CJ;@L;@P?FLCM=BRAGP?DK<@N=CK=@SBGJ;@M>BN>CN>CJ;@R@EP?DQ@EJCL27A38H9>E7;G8=D7:D7:@49J;@E7J:?<05A38>25=15@37E716?27?27>15;/3?27:.2;/3?27>158-04)-=046+/2'+2(,4)-:.2:.2;/3:.14)-2(,>1616?27;/2@38;/2;/2A38@28@38>26>14>15?37C5:A38?27@27>05>15A38F9=C5:J:?Q@GF7=G:?M=CK;A:/3?27C59>16E7:@27D6:H9>I9?G8=I:?E6;G8;F7DKEP?EO?DN=CD7=N>CD7=N>CR@GL=@N>BP?EL<@Q@GF8=KF8=?16E7;G8>D69D6;?27D6:C5:D6;C58;/49-2F7=C5:C5:<04?25?25>14?27@37B49C5:>14B49<03=05>27C5:A382(,6+/8,06+/6+/4)-5*.4)-167,03)-;.27+/<03@27?26B49@37D7<;/3B39H8>9-2<04C5:G9>=15G8=N>DE6C5:F7=;/4?26;/4G8>D69A49E7:B49F7;G8K;AN=CC5:D6;I:>H9=I:=LO>EUBII:?O>DN>CM=BM=BWDKM=CP?EG8>N>BP?FI:?R@GL=@K;@K;@K;@M=CM=ARAGN>CO>DF8>J;>J;>K;ATBHH9=MDD6;I:?>27N?DN?DG8>L06=04>16<04@487+/16D6;16:.236>25=04:.3C5:E716D6;G8=?27<05G8>B49A38A48A48E7E8G9=F7H:>F7;G8=KDI;?K=@J<@D6;K;@I:?L>BRAGUBIL>BLBP@EE7CVDJI:?L=BP@FL=BN?CM?CK;@M>BRAGL>BR@GN?DRAHK=AK;AK=AC5:C5:E7A49I;?C6;C5:B5:@27G:=E7I9?D6:D8;F8=B59?27J;?D7;>16=15@37A58C6:<049-2@37>16A49;/3A48>16>255).8,1=255*.8-15*.=25<04:.27,0?27A48=059-1>16@379-16+/?27:.29-19-19-1<048,0=05;03E7<5+/<04?27<038,0;/2:.2=05<048,05+/D6;B5:4*.8,0<04=05:.2>164)-B49?174(,>26>14?259-2?37;/3B4:9.3B49B4:G9>A37A47B59B48C69C6:B49@26=16>16E7;?27D6:E7;G9=G9>E7D6;C6R@GRAGRAGM=CLBRAGP?FR@GJ;@N>BN>CL=ATCIL<@E7I:?H9>D6;?16J;>I:>H9>@48H:=D6:E7;H:?D6;I9??38C5:D6;E7:A38D6:C5:F7=D6;?26<05L05B49A49>15B497+/D614?258-1>26:-1@276,0>16>16B5:;/2;/2<04;/2<03<04:.28,05+/6+/<036+/:.2;/2@38@38=05@38=05:.28,0;/2;/2?27>169-18,0@38>168,0<04=05<03A492(,5+/@38>25;/37-14)-@38=15<04=04=05<04A48:/3B49C5:A47C59@27<05B49@26B59D6:C5:I:@B59D6;C5:H9?G9>G8F8DF7L<@M=CO>EL=AE8=N>DF8>K;@D8CP@DN>CP@DP@EO?CN>BRAGO?CO?DQ@FN>DN>BK;AL=AI:?H8=L=BG8=LJ;AP@F?16H:=E7F8;I:@F8C5:A37D6:D69H9>F7=@37?16G9>E6<>05B49A49@36E7<5*.7-1B49?36264)-@385*.5)-6+/?37A496+/8,07+0<048-11'+4),8,1@37@37?37=15C6;;/3@27B59A48C5:A38=05@37A38D6:D6;D6;E8M=CP@EM>CPAFI9>QAFLCRBGRBGTCJXELQAFM=BPAFQAG@37I:?J:@I:?LC59F8:.29-1:.2C6:E7<9-19.28,1=059-11'+3),7+0>16>15<04:.2?377+/:.2<04;/3<04:.26+/9-19-1;/3;/3;/3<04<049-1E7<6+/9-1<04C5:6+/<04<04?279-1;/3:.2>26<042(+5*.5*.=056+/;/37,0A38?378,1=15;/35*.6*.8,16*/@37B59A48A48>15>16?26C6;B49F8=A48=15=15D6:C5:D6;?27E7;C5:@38F8J;@D6;LO?DN>CO?EC5:G8=P@ESCHK;@L=BRBGQ@FP@FO?DO?DLCO?ETCJO?DQBFVELQAFK;AQAGN?DLBF7F8L=B?27E72615>26=15=15:-29-19-1=15;/3?27:.26+/6+/;/3:.2;/36+/;/39-1SBHI:@@38<04D6;G8>:/26,0>26B49<046,06,09.16,0:/2/&);/3:/2;036+/6+/B5:<14<14>15?27I:?@48<14@37<05A48=15@38>26>26?36:.2<16@47=15A48B69G:>H:>E8F8=F8F8=H9>I;@J;@G9=F8CKK<@H:>I;?I;?I;?E7;L=BJ<@F8>G:?G:?G:?G:?H;@M?CO@EN?DP@FP@FO?DL>BN?DN?CL=AN?DN?DO?EK=ASCJQBGN?DPAFM>CM>CQAGKG9>G9>C5:C6;C7F9=H:?H9>G9>G9>I;@F8=M=BRAHC6:>37G9>K;AD6;=16<16?37<15@473*-?37>25?369-19-1D6;=25=25>15?26H9>?37;/3>159.2=159.226>26<04=15<04% WDKD5:<049.1E716>26A498.2;/3<04<14<14:/38,0C6:A48E7<@37A48C6;<15<16C6:@47C5:@48D6;E7I;@G:>H:>J;AH;>J;@KJ<@I;?F9>F8=B49F8=F8>K<@L>BG:?G:?H;@D5;H9?H;@G9>N?DN?CK=BP@FL>BH;@KDD6;E7;K;AM=CJ:@C6:G9>B59A48A385+.:.2=25@484*-@37?37B5:9.2:/3;03;03;/37-15*.?37=15@38:/2;/3=156,06,0<049.1;/38-1;/3<04<04>26;/3+#%/&)C5:5*.;/36,0G8>F7=?27=04@38?26B49D7<<04I:@;/34(,;032(,9.20'*8-1;03F716D6;B59B59B69C6:C6:@49?27A59D7;I:?E8D7CID7=H;@H;@K>BN?DN?DN?DK=AK=AM>CQAERBFSCIL>CVEKUCITCIJ=ATCHP@ESBHB5:D8@38H:?H9>F8=F8E7;?38RAHP?FH9?E6;H:?G8=J:@L=CB59P@FA388,0?365*.<052),9/3<14G8=M=C1(+8-13(,=05:/27,0<04<04167,0:.13)-;/2@48@48=05;/3=05G7=E6;6*.<046+/?273)-8,03(,I9>B49:.26*.4)-7-1>14;/4;04?25A49A388-29/3?27E7<>16G9>B48?27D6:D6:D7:@38D6:F8;J:@E7:B59@37G9>F8K<@J;?E7E8=C6;@38D8BN?CN?CM>BO@DN?CK<@L=AP?ERCIO?EL>BG9=@38O?EH:>L=BL=BJH:=F8=F8=G9B5:G8167,0?27:.17,0;/2;/2;/27,0:.1=057,0=05J:@@48@48:.1;/35*.5*.=05E7<3)-;/37,0;/2?27;.2<03:.2A594*.7+/5)-5*.8-1:.2:.36+06,0@37=05;047,1>15A38A48C5;=15B59@37D6;L16D6:C59D7;D7;>16?26>27E8=D7;B5:E8;F8F9>M>BM>BN?CI;?M=@K<@H;@J<@H:>WFKO?EQCHE8=B5;RCHO?EL=BP@ED7E7;E7;G9>@38A49I;@E8=E8;B5:J=BK=AJC9.2B49=15A47E715:.28-14*.:-2;/3;/3=057,0;/39-1<04C5:6+/;/2:.1;/3;/35*.D6;:.2+"%5*.A48:.25*.?27C5:5*.;03=15=15J;@@38=15=15268-14)-E6;@38<047,0=048,0C6;7+05*/9-1:.3?26@47;/3>16A58E6B69B69C6:L=CC6:D7;B5:D8;D8;C6;A49A49D7B59F9=E8E7;F9=H:>F9=L=BK<@H;?G9>G:>I;?H:>I;?K=AI;?G9>L=BL=BPAEE8BJ<@H:>I;?F9=D7E9C6:C6:@38B5:;047+/G9>B49=158,0=047,0B5:6*/4)-6+/7,0;/3<147+/9-1;03>16@38;03;03;03D6;;/3;03:.2;03;03:.2H9?;03-$'/&)3(,9-1?27?27B496+/A485*.4)-G8>G8>@38K;@6*.8-1<042(,C5915?27A38?26B69D715D8;D727B59H:>JF9=H;?L>BH;?M>BF9=M>BM>BK=AI;?F8=G9>F8L=AJ<@VEJVEJL?BO@DRCH@48K=AF9BI<@H:>IJ<@H<@I<@D7;F:=D7D7;E9G:?J;@=15I;?DN>EF8>PAF:.2<04@375*.E7<>15>268,016>16?276+/9-17,0;/3;035*.;03;/3A49=14C6;6,0?27=15?27=14:.2;/3N=C=14:.25+/A49?27I9?I:@;/3K25=15?25@385)-:/39/3;/3;/4B59B5:A48?279-2A58C7:=16B69D7;C6:B59?37E9<>27E8;D7;@49>38?59A59H;?E8E7;C6:E9=E9=F9>H;?D7;QBEB59E7I;?I;?K=AH;?G;?L>BL=AE9=G:>J;?I;?QBGN@DN?B@36H:>E815A6:F8H:>E8D7=N>DM>D?26O@EL26?25@374)-9-28-18-18-1>26>26=04:.24)-<03=147,0<03=14<03:.27,0=145+/<03;/3E716B5:@38=15=15?27M25<049.2?25B5:@47:/3A49;/4A47?26A48D7<@37=15?27:.2:.3D7B59A48D8;C69D7;F9;@48>37=15>15D7:B6:?26I;>C6:@37I;>JF:>F:>J<@J<@L>BOACOACQCFM?BG;?PACI;?F:>I;?H;?H;?H;?N@BN@BG:>RCGQCGM>AJ<@O@EF9=K<@C6:K=@E8J<@G:=B6:E8BI;@E816?27:.29-1<03:.2;/35*.7,07,0/%)7,09-1>267,0A497,0:.2=15O?DI:@>26@38=15:-2I:@B5:F7<;/3>16=15<04=045*.:.39-2<04=04>16=156+0<04C6:C6:C6;<15C7;@48=26D837?37?37D7;B59@48F9=D7;@48B59D7;=15>15C6:@37A58D7;D7;C6:C6;E8K=AF9=L>AOADN@CSEHQCFVGKM?BM?BK=AK=AI;?N@CH;?H;?D6;PBEJD7;F937I;@=26A48D7;WFKPAFD715M>CE8=I:>>15@37>26=05=045*.9.28,1;.3:.2;/3:.23)-8,0=15=15=157,0=15:.27,0=15@38?377,07,07,0;/3:.2;/3=153(,;/3;/3A49>26:.23(,7,03(,E6;M=BH9?I:@=15D6;G9>F727B6:G9>G9>@37C7;D7;<15:/3G:>J<@D7;>26<04@48@48@48C69D7;G:>>26F8B59@37D7;C6:B59E8AG;>K=AJH;>L>BK=@N@CB6:IIBK=@B69F:=E9;G;>K=AC6:M?BPCFF:=H;>C7:E8<04D7:C7;JA599-1=268-1L=AUDHO?EO@EB6:H:>K=AI:?E8=A49>15F815?26@38>15:.2;/3A49E7<<04>15>157,09-1E7F8=B5:B5:B5:26D7;B59B59C69@47>25@48C69G9=G:>D7:K=@J=@A69C7:C8:F9<@48C7:C7:A58C79IE8HF9AM?BM?BM?BK>AG:>HE9F:I<@E9;C7:<14A48G9=A59A58H:>?37G:>H:=C69C7;JBRCHVFJL>BJ=AJ<@E815C6:=05=04?26B59@37=05>15;/37,07,04),3),:.2;/3:.2;/3<047,02),7,0<04:.2:.2:.27,0?26?26@385*.7-1@38>157,0@38A49<04>15:/2<04>15K;A>15=05A48A48A49?26B59B59<149/3@38J;?C6:A489.2B58B58D7;?483*-8-18-1E8;@58A69A58=25>47B69C7:>26F9=E8@K>@O@CJ>@F;>F:=GBHG;>K?BPAENACG;>OAEQBFH=@NACN@DD79C7:J=AK?AG:=E9@O@DQBFO@CD8;O@CM?BJ=@M>AK>AN@CG;=I35G;=F:<=25D9;@69G:>>26?58I;@G9<>36H:?I;@C6:E7;@58B59D6:QBGC69@48D7;D7:D7;A48C6:C6:=25:/3@37I:>B59@377,0?26?26A48<04/&)4)-4)-?26:/2;03:/27,07-1:/2;036+/=15<04>15?26A49<04>15@37>15;03A49A497-17-1<04<047-1F8=N>D8,0A49>26>26@379.3<14E7;9/3>27?48=36D7;B59:05B58D7<>37=269.2?46A58N@CG9=G:>G9M?BPADK>AI=?L>BL>BO@DO@DL?AG:=?47F9=J=AD79E9K>BNACK?BG;>G;>I>AOAEI>AM@BM@BNACG:>F:=L?AC7:C79I=AGPBEPADK>@J>@A57D9=J=@M>AG;=G;=H<>H<>H36?47@59G:=IBTEJ;04D726?37=25C6;@378.2?26A49;/39.25*.:/2;03G8=@37@38?26>15:/2<04:/27-17,0=15B59<04>16B596+/8-1<04<04A49@38=153)-;/2<03@38I:?=04@38;/39.28.2=155*/=26=14@38B6:>37A48A49B59B59B5:G:=C6:@46A58F9=N@DF9=D8;B68D8:E9C7:F:J=@J=@QCGE9N@DL?BL>@M?AK=AG;>K=AM?AF:=D9OAEO@BSCGN@BJ>AM>BOACD8;E:=F:=C9;E9=H@E9@J=>M?CRDGM>BK>AH;=G:=I<>F9G:36L?A>36@58D8;D8:I<@G;>D7;8.1A47A57E8=OAE@47C6;>26;04;04?365+0>37=14@37A5:=26?38?27?27?27?27C6:>16;/2<04@38G9>?27=15;/2<04=15<04<04>16:.2=15>16:.2@38A49;/2@38<03<03@387,0B59;035+/6+/4*.:.29-2@49@49G:>?26=15A59A598.2>26<04>37D7;C6;E8F:=E9BF9;G;HBD8;F:=J<>A69M?CPAEG;>J<@E9J=@G:>M?BE:=N@BPAEN@BOACN@BN@BRBGPBFM?AQBFIG;>UEJRDHK>AK>AM?CVFJOAEJ=@I<>H;=J=@H<=B79I36J<@C79I<@D8:D79H;?=25I=?B68:03;038.2?26<14D726;04=26B6:A48A5:F9=;0316?27=15<04:.2D6;@38=25A49@38;/3C5:2(,<04F9><04B59C6;=25?27;/3?38@49@48?37D7;C69?48=26=36>26B5:<04<14?46>25A68>25A69?47:/2<14@57:/29.1<14<14?47?47>36D8;D9;E:<=25:03>36B79@47@58H<>C8;A69@57>47H;>L?BK@AH;>JJ<@F:=L>ATEIMACM?BM?BQCFPCEJ=@J=@HJ>ASDHSDGQDFN@CG:>J=@SDHTDIM?BOCEF9=G;>E9PAFSEHK>AK?AM@COAFM@BI<>E9G:=?47?47E9;>36G;>C8:L>B9.2D8:PBFC7:I=?K=AC8:E8<@57E9E936>47>26B59;04;04=36<04=36:/3=36;/46+/7,0;/35*.4)-6+/6+/8-18-17,0<04<14<145*.?27:.2>26C5::.2>26@388-1;/3<14<04<04B5:A59B59=26B58A59;048.2>37G9>A59?48@48@47H;?B6::038.1@58=258-1;03D8;?369.2@57;03;04>36=35:02>36B69>46>36?47C7::03;25=25;14@58G:=K>AHH;>E9@M@BIARCHPCEOCEIHAO@CG;>OCESDIOBDN@CHK=@IC7:J>@G:=C8:K=AG:==25?47?47A69C79G;>I<@?57C79C8:C7:B79J<@H<>I36:/35+/7-1?379.24*.;/36+/6+/8-17,04)-7,0:.27,06+/7,0:.2D7<=14;/36+/8-18-1:.2=25>268-1?27=26C735>35D7;=14B5:E935>36>359.1<14B68=25@57A58C89E9;E:B=24D8:N@DG;G:=H<>@58K>AM?DA69@58H;>I<>M@BF:=M@CF:=C79G;>PAFPBFL?BF:=E9AQCEJ>AQCERDFSDHPBDRDFF:=H;>IAM?BK>AG;>M@BG;>D8;J=?C7:H;>K>@G:=I<@J=?N@DK>@I=>G:=J=@I=@I=>E9;HBF:=HC8:E9A;14A57A69@46?46E8<=14B59D7;>357,0<04;04:/35+/8-1<147-1:/3:/3<14=25>26<14<14<14B5:5*.;/3C6;D6;=15@48;/3:.2>26>268-1:.2=26?48:/3<15=26C6:E8?46C8:<25A68D8;B69C8:E9APBEHHAJ=@QBFM@CM@CL?BI;?C7:F:ANADG:=G;>QCFK=AM?BPBEJ=@PBFN@CJ>AJ>AJ>AM?BN@CJ>AIBPBFI=@E9AH;>G;>M@CG;>F:=L?BD9;F:=NADK>AI<@D9;K?AF9AK?BE9;G;=C79G;>G;=?57A68F:A68C8:D9;J=@L?BF:=A69I36:/2>36B6:;04>377-1;04=26;04<15=26=26?37=15;/3C6;@48A49D7<=15>26B5:C6;8-1>26=15<15<15<15?48@48@489.2:/3:/3B59<04=25=25F8<14C7:<13<13:/3>36C8:>35B79@57;13A69B79=35B7:C8:C8:F:==35?47E9G;>QBEOAESEIQCFJ>AL@BN@DF9M@CE9NADQDGF:AOBEPBFM@CQDGPCFPCFJ>AL?BPCFPCFM@CPBFQDGREHRDHI=@K=AM@CL?BM?CNADN@DK>AG;>K=@I;?J=?M@CIAK>AL?BI@58D8;@68G;>E:H;?H;?@47@57@57G;?@58A69A68J36<147-0=26<157-1<15<15<15>376,07-1<15:.2=15>26>26E7;=15<04=15<047,0@49=26<159.2:/3>26=26E8<7-1;03>25=25?36A59;03;037-0A68<14A68=24<13<14>46D8:@58C79@57<249/1B79?46B7:A58C8:G:=A58B69>36D8;E:L?BN@DM?BL>AQBGI=@J=@C7:J=@M?BL?BIM?COADG;>RDHVGKNADPBESEHC8:IAJ>AJ>AJ=@L>BNADSDHN@DL?BOAEM@CK>AL?BOBEJ<@L>BOADNADN@CH;>L?BIJ=@OADM?BI=@J>@L>AH46:02C79=25B79=24<13;03=25B79>35?46<148.15*-<149.2<15:/3<15?379.2:/36,0;04<15A48@37;/3;/3?26=15@48:/3<15@48:/3>26;046,0@48E825=257-0?46D8;?46A68>35C8;9/2<14?46?47:03:03>35=24;14C79A69C8:D8:<14<24B69C8:H;>D8;D9;C79E9F:=G;=HJ=@L>AM@COBFL?BD8;D9;C8:K>AJ=@M@CD9;F:=M?COADG;>I<@OBEL?BHAI=@OBFOBFM@DQCFL?BL?BNADK>AHAK>AIH;>J=@G:=H;>L?AHB79?47D8;D8:F:=J=@C7:G:=C7:=35H;>M@CM@DE8;C8:<25D8:I36>256,/6,/;04<15@48<15<15:/3<15<15=26<15=15C6;A5:8.2>26C6:?37>26A59A59<15@48>25H:>K=AA59>35>35;03?46>36<246,/=35<24;14D846=35C79B69:03C79@57A69B79A78<24A68>47B89E:A69IE:=D9BRDFRDFMBDQCEMACJ?BH=AH=@H=@J>AJ>AL@BOADL?CF;>K?AL@CJ>AK?BG;>D:=J=@J=@I=@G;=HAJ=@A69D9;L?CIBJ>AD9;I26<15<15<15<158.2>26=26E826C6:<14=25=25@47E946?57:147-0?46;14A68?56A69@57=35=46@58>47D8;F:?47B8:J=?J=@J=@NAEJ>ANADK?AM@CI>@G<>I>@PBEK?BQCEQCEQDGVFJRDFRDHSDHQCFSEGTEITEIG;>D9;I>BF:=F:=PCFPCFSDFPCGPCFI>AJ?BMACK@CRDFMBDMBDTEHJ?BC8;G@QDGL?CM@CI=?K?BJ>@J>@J>ANADM@CH=?H=>C8:B8;D9@IM?CRCHG:>F:=A69G;>A68D8:D8;B68C79>46?47>35>469036,.=248.1=25;13=25:027-07.19/27.2<14>25<15:03>26=26@489/3>26<14@48@48;03A59<15>26<14C6:=25?37<14<14B79I<@@58C79=25A69A69@58E835?45A68?46=35<24A57B78A67A58A68A68II<@H;?H;?H<>B7:?47G;>NBDHD9;C8:E:=I=?L@CK?BM@CQCFUFJOAERDGQCGMACNACOCEUGJVHJD9NACJ>ARDGTFIH=@RDHNADD9@A78N@DIAJ>ANAEJ?AK>BJ>AD9G;=I<@E9;K>AF:=H;>E9D8;C8:J=@QBGG:>HH;?F:26?37>26>26=26;04>37<25<15@48=36C6:>36@48B79C7:@58C7:=35E9=35A68:02?67G:=I<@E:=C8:<35A79?47=36>46B8:C9:C9:A68D8;K>AL?AG<>I=AI=APBFM@CMAC;25E:=MADPBEM@DD9J>@J?AMACI=?J=@I=?F;>REHLACOCERDHSDHNBDNACQDFTEIOBDG;=GPBEODFODFTFIOCEPDFXHLL@BF:K@BC8:H@J?AD9AI>AG;>I=@G;=J>AG<>M?CG<>I<@K>AL>BH;?K=AD:;L?BJ<@E9<@58A69E946A699/2>46E9C7:?579/2=35;038.18.1<24<24<24:/2<14B69B69>36@48@48E836:/2<25?47<14@58C7:;03<24<24A69C7:>46=359/2?57?579/2=25B7:=35>35;13>46A78E9=F;=D8;<35F9=F:=C9:<14B7:E:AL?CJ>ANADPBESEHQCFG<>A68A68F;>G;=B79C8;A69H<>QDFL@CJ@AE:=J=@J>@C8;PBFGAH<>H<>H<>N@BPCEPCENADREGODFSEIOCESDHF;>F;>ODEH=@SDHNCEMBDK>ALACOBEA69MACK?AB7:I=?HE9AF;>G<>G<=GBB79C9:C9:H46>36:13=35?57C8;D8:@589/2A69A69=356,/<14>36>36<24<24>36A69C6:A59D7;E8:/38.1<14<14=24A69>36A69=24=24=24>36>36=24=24G;>A58A69?57@58C8;H:>:03=35=35G:>=24>46:13?46B7:C89B78C8;C89F:=A68>46D9:H<@D8;C7:F;=HAC8:M@CJ>@MACTFJOCDM@BPCDQDGI>@G<>C9REFRDEWILSEHQDETEIUFJSEIUFJPCDQDGB9;>57H=@OBCPCEK?AK?AG<>OBCQCFNADMACNAEH<>D9@C8:F;>C8;I>AH<>E:J>AE:K=@;24>46>46G;>=24=35902=25@57?46>35?57>35A58;138.1=24A69<14;03>36@58@58?47B6:H:?G:>A59>36=24=24>35@58<14<14<14=24?477-0<24=24=24B7:F9@68:13?56@56>36A78?57D8;B79D8;B78C8;?47F:=F:>E9;B69E:ARDFE:=L?BJ>@F:@REHJ=@F;=MABF;=G<>=56?58G<>L?BH=@H<>PCDG;=E:C8:L@AH<>PCGJ>@J>@D9?I=?G<>G<=G<>I=@E:>46C8:D9:D8:H<@L>BD9;@57G;?I35@67>46B7:@56@58>35?57;03A58@58>35;13>46A69=24E9<@58E9<14@588.1:/2<14>36@58>36>36>46@68B7:B7:@68:02=35E8;C8;902>46=35?46H;>B8:G:=:13;13;14?57A68>35C8:B79A69=36<25>46C8;D9;B79I>AF;=NACM@CK?BPCFPBEG@F;=L@BK?AD9;H=?OBDG<>I=@L?AI>@OBDOBEQDFTFIPCENADPCEPDFSEHUHJH<>NACQDFREGTGIQDGL?APCETFJZLOSFHNBDG@H=?G;=J>@H=@H=?K@CB7:C8;E:=GAG<>F;>F;=H=?I>AI=@G<>@57C8:J=AH;13:13:13>46?57<13?57>46=359/27-08.1=35=35;13B7:>46E936H;?7-0=25>36=25;03>36=25=35<24>46?57@68?57<24=35:02C7:C8;?57A79902@57?57D947B79D9@M@CH=@L@BG@@68F;=MACC9F;=TFJQDFOCEF;=L@BOCEK?A?57H=?PDFPCEL?AQEGTGIQDFOCEREGTGITGISFHPDFNBDTGIH<>J>AG<>REGZLObSVVILPCEPDFSFHQEGG;=G@NADSEIPDFNBDOCEK?ANBDI=?LACJ>@L@BLACI>@B8;H<>H=?G<>D9H=?F;>C8:C8;@57G<@GB8:E9=<24:13>46>35<24=35;138.17-03*-:028.1;13=35=35;13@58D8;?47B7:>36@58:/2;03@57;03=25=25:02:02?46A68=35=35=35@57D8;A69E8;A68@57@57@57?46:03F:=H;>D8:E:=>46;24;24E:46@57=36F:G<>J?AK?@I=?TEHK?ANADK>@I=?NACWILD9;H<>@69K?AE:@MACOBDPCENBDVIKOBDD9;G<>VILI=@H=?UHKUHJREGQDFSFHWJMVHJSFHSFHQDFI>@QDFG<>QDFUHKn\_`PSPCEUHKSFHL?AG;=NBDNACUHKMACE:@NACM@BOBDJ?AI=?C9@K>@E:@D9;F;=F;=B7:B7:G;=I=?E:@G;>J=AE:I46A68B797.08/1:027-0?46=35>468.1=35?46>36A68A68?466,/>36?46A68A68=35<24<24;13<24=35A68?46=35?46A68=35B7:>46@57C8;JAH46>58G;=E:=B8:C:;?79J>?@69F;=I<>I=?L@BPBEJ>@H=?MADNBDTGJI>?C8:H=>E:@MACNACQDFG>@SGIYLOSFHG<>MABQDFMBCSFHREGWJMQFGNCDPDEVIJQEGNCDUILPDEQDFI=?G<>;24`PShX[bRUYKNLABH>@HJ>@M@BB8:F<>H=?A79I=?J=?K?AK?@F;=D;B7:C8:F;>M?BE9;;35;14@58E9=J=@G;>:03B68>46>46913B79=35;238/1802@57>46;13<248/2A688.1=35?46?468.18/2;13>46A69=35:03;13?46>46?46A69A68A68;23;23:13?57A68=45B79F9=G;>D9<=45D8:?57G;>HH=46D9;E:<:02>46A89A89F:@J?AK?@G<>H=?L@BJ>@E:@TGINACSFHA68@78C8:I?@PCEE:I?@K?AL?AA68F<>A79D:G<>@78@78@58D9;E9;@78E:56D9;?56F:=G;>F:=F9=@57C8;913?57A575,-8/1;23;23?46;13?468/2?46A68A68A68=259/28.1;13<13>46@58?47<13=35?47@58B7:C8:@58@58<23>46>45@58A69B7:?46F:=I=@B7:E:=?46J>AF;=C8;A68H<>C8;E9<=36I=?C9AG<>F;@OCED:@TGISFHOCESGIG<>E:ODEMBBNCCNCCRFHYKMYKMYLMUIKODDYLMQEEUIKPEFK@BNCCPEFSGISGIODEJ?AD9G<>B79C8:OCEOCEF;=H<>OCEJ>@B8:I=?A79E:I=@HH<>I>@J>@F;=F:=A78D9;B89C8;D9J>AC8;F;=?45I=@E:46=35902?47=34=35;13;13=24A69>46=24=358.19/2>469/29/2A69B7:=35902A69?47A69B7:A69C8:;13=35?57>45D9;@58=24>45C8;HA69E:=>46F;==47A78G;>C8:C9:C9;;14>58F;=G;>D9:C8:F;@OBDNBDPCEJ>AH=?L@BJ?AJ>?C8:SGIUHJPDFRGHJ>?G<>G<>SHIQFHNCDSGIUIJD9;G<>NCDD9:PEFMBBE:AODDTHJQEGF;=B89PDFPDFI>@J?AOCEH=?RFHF;=K?@K???67F<=K?@C9:@68J>@NBEI>>I=?A79A79B8:H=?B8:B8:J?AK?BE;=@79I=@F;=H=?I=@G@@68B8:D9;B79G46?47<13;13=24@58D8;?46<13A69=24>35C8;E935<23<23>35?47>35C7:?46B7:D9<@588/1?56=35@57A69@58B7:B79902:02C8:=46?57902A78F:=I>@I=@C9:?68@68?57C89E;MACG<J@ATHJSFHI?@LACG=>XKME;=ODDSFHWJLQEFVIKQEFSFGC::C::QEFH>?PDEODDPDEB99D::NCCPDEC89G<>K@AI>@PDFNBCSGIH=?D9;MADK??K?@J?@E:?J?@J>@F;46A68A69@57A69A688.07.0@58:13<246,.<23@58C8;B7:=349029028/1;13=34?47>35>35?47>358.1?57?579/2?57>45>45<24=35?57902>45>45902?57?578.1>46<24>46@56A78;24>46C8;B8:F;>J=@9137/1<46;35H=?@69A79=46D9:MACD:;?68@68F;;E:?F;?PEERGID:;G=>NDDMBDQFHODEPEED;=PEFKABI@AKABWJLRFFKAB>67MBDH>?=45NCEODESGHMBDQFHF<=G=>LBCF<=F<=H>?QFHPDFF<=LBBLBBMBDK@AI>@K@@J@@I>@A78D:I>>B89J>@I>@B8:H=?G<?68D:;D:;>57D:=D:<;24A7:?57A79A79B89<35?57D945F:=>45902902>45=35?56@58?57?57<24>35<24@57B69=35A58C8;A58>45@57=35<24<24=35@57?56=35?567.0C8;:13C79F;>GE:=E:C8:E:;F;K?AK@AJ>?K?AG<>I??F;=J?@I>?MACI>@SGIXKLMBCRFHJ@AXLNUIKREFMBBVIKPEFREFF=?XKLREFPFFG>@SFGODEJ@AF<=C:;F=>TGHH?@KABODEODFODEH?@THHOCDA89JABSGGVIKPEEUIKMBCF=>H?@F<=LACKABTHJVIKJ@AODELBBG=>F==F<=F<=J@@KAALABI??H=?K@AH>>H<>J?@L@BF;=J>@MACI>?F;D:<46E:D945@57B69B69@57A58@57>35E9RDHF;=E9I=>K?AK@AJ?@L@BF;=H=>F;=G=>NBDLABH>?G=>OCEVJKPDEI?@OCCQFHUIJMBBRFGJ?ASFHF=?LACTGHMBCNDDQFFD;?NCDNCEH>?E;WKMJABJABNCDNCDWJLUHIOEDODD]OPNDDMCDKABNCCMCCREFaSUJ@AI?@QDEJ@AF<=MBCKAAI?@KAAG=>B8:H>>F;=J?@LACJ>?K@AK?AK?BI=?E:;K?BI=?G;=F;QCGE:=C8;F:=?676-/7.0>467.0A588/18/1B69C8;@57902@57@57B69B69A58B69;13<24G;>E9<<24C8;B79B7:@57>46C8;@57@57?57>46<24902?57:13?57N@C:13A79:24=46;24E;>;35C8:@68K?AQDFA79F;AMACK?B@68C89D9;A79A89F;=H>?H>?MBCI?@MCCODFLABC:;J@AH>?LBCNCDKABOCCMCDD;?H>?D;?H?@D;>RFHJ@A@78C:;KABNCDLBCMBCG>?G=>A89C:;C:;B99?67MBDE:F;46C9;=46B8:RDG<35B8:;35>57;24E:=:24B79?57H46B79D9<<24B7:;13>46C8;E946<24902@57C8;=35K=AHC8;?57>46?57A68C8;B79A68>469024,-B79D9@:24A79C9;C8:>57HF;F:A89F<=G=>B9:J?@I@AC:;H?@E<=G=>J@AKBCG=>H>?PEFNCDRGIWKLD;?G>?SGILABLABG>?ODE\OQPEEI@AG>?H?@I?@NCDOCDI@AKAAI@AF<?THHQEFVJLJ?@QFFRGHPDDYMNWKLdVXF==NCDMBCMBCMBCJ@AOEFODFODFK@AB99B9:LABF<=UGIQFHJ?AODFJ?BF<=E:@H<>F;HD946>46=35=35?57902=35>46902>35=24:02=24?57PAENADA69D9;D9;=24@58>46@58D9D9J>@I>?E:56LBCE;LAAI??G=>K@@MBBTHJWLLVJLNCCNCCLAAOCDNBBODDNBCTHITHJPDDH??NBCA99H>>H>>NCCZMOK@@ODDVKKPFFVKKTHIMABLAASGITIIQEFUIJYMO^QRVJKTHIKAAJABODFJ@AG<=LBCJ@AMBDH>?F<=E:;I??ZLNXLNI?ALBCLABC8:F;>D:;F;=K?AJ?@;24=46E9D9D9<>46913F;=H35A69D9;A69>46@58=24=24=24=24@58@58B7:B7:=24>35:02H468/1D9;B7:>46C8;?57?68>57F:=C9@A8:6-/<35@56H=>J>AD9;B8:E:@E;?H??J@AJ?AG<=K@BD:;THIOEFA88ODEMBCKAAE<=SHH_RSTIIRFHUIJNDDB99D;;NCCG=>SGHG>>G>?UIKXLMTHJJ@@QFFPEESGHSHHODDPDDTHJPDDD;;G==D::OCDOCDPEFUIKTHITHIRFGE;;G>>MABB9:A88XLNRGHWKMLAA\OQLBBODENCDVJKRGGJ@@LABH==NCEH>?I@AKABC::F<@D:;=46J?@HB8:C9;B8:I=?E:=G<=@79J>@A795-/;24>46E:46F;>D9;@58B7:B7:C8;A69>35D9;B7:?57?57A69?57>46B7:>45B7:A69A69F:=B7:D946?576-/=45:13@58>57=45E:B79HE<=LBCH>?H>?F=>G>?F==E<=H?@D;KA@J@@SHHG>>OCELBAWKM_STNCBRFHUJJMCBTIKLBBOEEWLLXLMYMMKABLBBLBBF==I@@LBCLBCQFGRHHSHIQFGOEDSGHSGHUIJWLLXLMOEEUJKPFFMCBMCBMCBMBASGIQFGUIJNDDE<@E:56C9<>45A7:@69>56=35=45I=@F;><34D9;B7:C8;@58>46D9;@58@58>46>46@58@58F:=:13=34@57=34?46=34@58?46D956>566./I=?I>@I=?I>@:13;35<45:23901C89=45C8:B88?67E;=LACE;;THJPEGI?@PDELBCH>>G==H>>J@ANDELBCJ@AH?>C:;?77MBCNDETHIXLMJ@?NCCODEOCDKA@TIJTIJRGH[OPPEFPEFG=>SHJQFGI@@RFGPEEQEFQEFOEDQFFF==NDDRFGPEDUJKRFGSHISHIOEDI?@OEDQEFQEFOEDTIKOEDVKMTIKPEGMCBNCDPEFTIKTIJXLLSGHPDFODEUIJMBBMBCODESGIH?>J??K@@G>=G==NDEC:;E<?E;;G==D;;G=>E<@J>@913:24;359036.0?57913?57=45:13@58E:=?46L@CH=@B7:G;>D9<@57?46@57A69D9<:13?46F:=?46<24=34?46B7:>45=45<24?46=45<24?58?57A68>56A7:<35?576.05-.G<>D9;J>@D:?KBCLBCD;;H>?G==I??QEFNDEA88B9:K@@J??THINDEMBCODFLBBSHIPEGI??E<>KBBJAAOEDRHHNDCRFGJAASHJQEFPEGPEFNCDLBAODDODETIJNCDLBBMCCF=>LBBI@?K@@K@@K@@J??D;>D;C99F;=@67C899016/0I=@E:@D9<>569137./802?57?57@68>56<347/1:13@57QDFOBDA69D956@68>56A69B7:?67?68@69A68B8;B8;B8:?67C8;:13=46@78801:12:13912:23B89@67B99A89E;;I?@I@AB9:D;;@78QEFNDDKBCODEOCDJ@AF=>@88NDEKAAJAAMBCJ@?KBAKA@QFGODEODFLBAUJKNDC?89G>>KAASHIWKKOFFNEDPGFOEDZNNVLLQGGTJJTJJVLLSIIPFF[OOTJJNDDRHGUJJTJJPEEOEERHGTJJTJJOEEUJJRHHOEEPFEJAARHHQGFOEDPGFH?@MCCLBBE<>H??G==I??MCCE<=G>>B9:LBCF==G>?F<?H>?F<G=>G=>F;>C99E;=<34>56A88901913913802902@67<35>57=46@78D9;C9<<35>46:13I=?F;>D9E:=B7:>468/1D9<:13?56@67@68D9<@68:13G;=?67B7:A69D9F<=D;;F=>E;;D::I@AD;;I?@G=>G>?NDDI?@NCDH?>G>=G>>>77H??E<>PEFLBBTIJQGHSHIMCCTIJD;;PFFJAAQGGKAAPGGOFFMDDKBBMDD^QR[ONMDCWMMTJJWMMRHHQGFXNNTJJRHGPGGTIINEEPEEVKKRHGSIIUKKOEESIIUJJ[OOZOO]QQVLLMCCPGF[OOZNMRHHOFEPFFOFFLCBNDDJ@@D;;ODFODFODEWKLTHIJA@MCDC;I@@MCDI@@B9:PEEG?>I?@H>?JABLBCLACNBCH?@F=?D::@78A88C99J?A=45B88G<>;23C8;;34@787.0D956C9<>56B8;A69A69F;>B7:E:=@67?56?567.0?56<24A68?56A68?56@678/1=35>56A69A68C956D9;D:57?576./7.0;34801>46:13A88=45=45=56;34C::B99D::I@A=45C::G==C:;E<=MCCK@@?88G>>F==LABLABH??H>>I@@B:;UKKTJJTIIUKKD;;G>>G>>F==D;;MDCG>>NEDLCCI@@RGGXMMPFEcVV^RRUJJ]RRZOOSIHTIHTIHVKK]RRYONNDDRHGKBBRGFTIHMDDWMMYNN]RRUKKYONTIIOEDKBBI@@WLLSHHPFEE<J@@H?>H@??78E<?H>>JABJABMCCH>?D;;I?@H?@G=>C99B99A89701801<45901>45912?67;24;24:24802?67=46>56C9<7/1<35@68=35>46<24A68>56D946?56C7:A68A68A68A68=35>56=35A69<35>56=46>56>56@68B688/1:24<35=45E:==45912=45?56?57<45801B88A89B99;34C::>57?67H?@C:;?67@88D;=E<>JA@A99?88QHHPEEWLKQFFJA@F==B::E<>I@@QGFh[[fYYTIIYNNXNMOEESIHSIHTIH[OPaTTH@@H@@PGGVKKQGFPFFSHGOFFNDDUKKTIIB::F>>QGGC;;NEDRHHMDC?77B::LCBQFFVKJXMMbVVVLLPGHVLLMCCKBAPEFMBCMBCKA@J@@J@?I@@E<=D;;I>?D;;E<56@77A88H>??66:23>56?57?56;347.0@77?56>57802?67:13913B8;=46802913=46B7:>46>56:13>56=35:13A68<24=35@68?57=35A68=35>46>57;24@68@68<35@68@68>57>57C9;A79?67:23>45;24;34C89<34C::?67912B99F==I?@=45B9:D;;?67G==LAB@78E<>J@?H??I??KA@I@@J@@LCDMCCNEFNDDNDDKBBOEEE==G>>I@?C::E==D<=G>>C::F==F==D;>E<56801@78D9;F;=913>57?68913A79E:<913>57913C9<@68B79@68A68B79@68A685-/;13=24>35?57?46B7:>46@69=358027/17/1<24?68C9;A68F;=C9;:23C9;D9<6-.?56?66A77A89A89;34912;23D;?H?@H??NDDJAA@88QFGH>?KABKABNDCODEQHHWLLOEEMDDKBBG>>H>>LCCUKKE==KBBQHHF==PFFG>>LCCB:9SJJSIHOFFTJIPGFOFFVMKOFFVLLTJJTJJZPOVLKZOOSJIQGEKBBG??UKKPFERIHTJJRIHRHGKBB`TTWMMKBBTJJH@@PGFYON\RRH@@MDCTJIF>>PGGXNMUKJUKJQHHYON[PQLCCF==XNN[POSIIOFFSJJMDDF<?>56F=>F=>7/0@77@77A78A88@78:238/1801A79@78?57A79C8:B8:B8:G<>C9<:13H=?@69B8;C8;E:46=35=34E;56@77;34@77<34H?@D;<55D;;G>>KABMCCPGGNEESJJPFFJAAPGGQGGNEEJA@JAAJAAA99A99F==B::JA@E==LCCG>>H??H??F>>NEEMDCOFFVMKH??NECSIHNECNECKBAQHGPGEZOOTJJF=>MDDSJJOFGNEEI??KBBD;;?77@88A99B::H??D::H??G>>G>>D::>77<56;44C:;B99A77I@@F=>>56E<=D;=B99=45;23?55?66:23?56912E;57@696.0=35?68B8;D:AE:=6-/7.0902:139026.0?68>56:24=45<35>56>57B8::24>57@67;34>55?66A79D:<@78@78@77A77?67A89:23B99B9:C::C::C:;E<I?@C::E=>G>=E<=G?>H?>JAARHHJB@D<>NEDIAAH@@TJJNECH@@JA@OFDWMMPHFRJHLCCRJHOGEJA@WMLXONWMLbWV]RQQHGXOMG>=RIGSIIOFDWMLVLLOFEVMKZONVLKQGGMDBH@AH@@OFFRHGNEDPFFTJIQHHIA?RIHRHHNEETJINEEG>=A99A::B::A99>66H??F>B99B99A88A88?66@78912@78@67?67?67?67A79E:;B8:B8:@68B8:<35>56>57@69=45>57>56=35=458/1=45=458/19138026.0>56:24>57<35>57A79C9;>56=44A68B8:G<>C9;C:;B89F==A89@78@66?67A89912<44B99D;=G?=I@@F>=H@@NEEKBBIA@E==I@?F>>F>>MDDG??NEEJA@C;;MDCPFEVKJD<>LCCQHGJAAJBAOFFF>=G>=G>=A99B::@99>66F>?J@AD;;B:9E<=F==LAAF=>F=>D;?C::A89@77?66@78801:13@66A79B8:>55=45:23>56D:57A7:A7:@69B8;@69>56>56@686./902902=45:24:24913=45<35>56?57A79?57B8:D:D;??66;23@88B99@87=55A98A98B::C;:E<=B:9H??MCCKBBNEEI@AKBBF==D<RIGULLMECLDBQHGQHGLDBULLRIHKCATKJTKJNECJA@NEDOEEE==I@?LCCNEEJA@I@?JA@D<C;:I@@F=>F=>A88G>?E<=I???67;23@77A88?66;23>55>55?66?66A68=44B8:F;=D:B8:C956:235./A89?66A88@78B88D;PGFOFELCBF>>C:9G??KBAE==KBAG??WMLPHFPHFPHEULKPHFTKJPHFUKJE>;MECULKVLK]SP`VS^TRh\[g\[`VTcXWbVUWNMSKJXONVLKdYXRJIQIGKCBSIHPHFSJJIBAYONMDCRIIWMLH@@D;:OFEOFFSJINEDLCBD<=LCCLCCF>>E==@99D<;H@>E<56@77>56@77=45@78?66?66C9;F;=?67B8:@79A7:C9<=46:24;248.0902:24=46@78>57<35<35<35=46:24:238019127./F;=>56C:;=45912C:;B99?67A99;34A98B::<45<56@88C<?@89D<;E=>?77@99G??G?=G?>G?>E==H@@OFFPGFC<;KBBLCCH@@KCBKCCLCBPGFJBBKBAJA@JA@JAAMECD<:OGEOGEPHFOGEMFDPIGXNLSJIRIHQIHWNMJCBIBAPHFNFDNFDRJGRJGF?=F?=VMLdYWeZX\SQWNM]SPcXVf[YSJI\ROUKJWMLULK\RPNFEZPNULLPHFPHFVLKOGEOGEMECSJIMDCF>>LCBH?>QHHUKJMDCKCBG??G>>LCCH@?KBBH@>D<;D<77?77<44KBBC;;G>>@89<55F==C<<@88C;:<45A99B99;34<45?67B99C:;D;<=45@77A77?66@78912:23@79@78@78?67=46@79F;=F;=:24?67802:24<35913913?67:24802<35:23=45:23C8:6./D:;24C:;A98=55B::@99A99812701@88E<<=66B::H??G>>F>=>66>77@99D<KBBF>=H@?RHGSJJKBAH?>MCBMCBWLLTKJOFFQHHSJIMECKCAG@?IA?OFEC<:D=;KCBRHFRIHKCAKDBIBAQIF[RPVML[RQOGFTKITKIWNMTKISKHWNMD>=OFDHA?TKH^TRWNMVMKPHG[RP]TRF?=OGFJCBQIFPHESJIRIGLECOGDSIHNGDRIHTKJWMLOFEMECMECI@?KBAH?>NEDVMLOEDJB@NECIA@OFFA99D<B::?88C;:A99D;;@99I@@;44JAAI@AD<;F==701812J@@<55E;;B:9=56B:9@78@788/15./=45B99:23>56C8:B79@77801801:23=46@78C9;>57@78H=?I>@A79<35:13=46902:24:24<35@79<35<35>56:23<34A78:12B99D::@78@78A89801D;<@78<45E<<@77?78?88B::D;;6/06//<554..;44B::C;;H?>G>>E==F>>I@@H??KBBJAAH@@JA@PGEQGFRIHPGFG??ULKRIHTKJKDBVLKQHGVMLF@?C<:NFEOGELECC<:F?=LDBPHGNFDRIGJCATKIXOMTKI\SQULJQIGPHGOGERJHRJHSKJXOMULJWNK[ROWNL]TRWNLRJHKDBE?>JCBIA?OGETKITLJVMKPIGQHGVMLSJHNFDTKI_USQIG<76G@?SIHF>=MDCF>>C;;B;;D<;H@@C;;C;:E==@99B::G>>?77H?>H??D<>A99<56F==@78@77?77A89C::4-.3-.9121+,8/1=45>56B89A78?67?67B8:A79C9;B8:@79A79F;=F;=6.0<35=46<35802:24=46=46:24=45<34=45?67@78<34>56@77>56@78D;<=45;22C::A99A99?77B;;;44B::KAAG>>G>=H??A99B::B::I@@LCCE==B::G?>F>=H??C;;E==:54LDBH@>MECMECKDBSJIIBAMECOGEPGENFDF?=LDBMFDQIGIBARIGRIHRIGRJHVMKSJHSJHPHGULJ\SQRJH\SQZPN_VTZPN[RORJHSKJWNLPHGMECSJHYPNRJHIB@JCAMECOHFQIGQHGIB@NGDQIGLECWNMXONB;9D=;KDBKDBMECQHHQHGIB@MECJA@G>=H?>F>>A98B;;E=>B99C;;D<56>56=45D:;F;=?67<34@78?67A79<35=46=46902<35C9;6.0;24>46B8::24:24=357/1;23>45;23?56?67>55=44>55C:;B9:<34@78E<=@77A99:34<55=55F>?D;;H??H@@D<?H??D<C;:H??E<;F==?98QIGOGFLECPHGE>OGENGEMFDMECD>G?=D<77B::E<;A99E<C::G>>G>>B9:H>>D;?C:;E<46>46>46:24913913F;=;24802?57:24;24:24912=34=34;23;23>55?67@78?67?66C:;@78;34F=>I@AE=>:34C::?66B;;B::F==OFFKBBMDDMDDF==G??I@@G??KBBLCCIAALCCA99H??H@?B::F=>86G@>C<:F?=F?=F?=JB@OGFKCAF?=H@>JCAH@>E>C;;C;;B;:A99D;:D;:A99A99D;:E=>D<>D<<>77I@AKBBG>?;45D;;?66B:;A99D<=MCDI@AJ@@I@AB9:D;46>46B8:7/17/1913;24>46:24@79801=34;23?67?67>55>55?67>55;23=44@77A99@77D;66F==G>?JA@G??E==H??H@@KBBD<;MDBOEDJAAF>>B::A99C;:C<;C<;D=;SJITKJKCBOGFRIG?86IA?F?=E>NFESKITKHKDBF?=JB@JCAMEDD=;D=;F>>F>=D;;D;:E=?H??>66822:34@77=55A99>66<55C:;D;C9;?67:23912;24;24;24;245-/7/1802;246.0:23912C9;;23>45?67?67:23=44>55;23>55@78>55C:;A9:C:;A::@99>66B:;;44=66B98>66C<>F>>H??JBANDCC;:E<;F>=F=>G?>A:9C<:IB@G@=?98@:9IB@G@>IA?RIGKDB?97F?=F?=NEDG@>G@>E?=MFDPHFRKIPIGUMKMEBGA?XOLZQNTMKYPLRKIVOMRKIRKIJCARKIQJHQJHSLJPHEXQO[RO^TQ`WTVOMQJHVOLKDBOGDQJHNFCOHFMFCJCAOHFQJHVNL\TQLDBTLJNGEMEBE?=MFDJB@LECKDBULINFEJCAJCAKDBIB@D=;E>76B;;A:9KBBB::E<;F>=F>=@98B:9C::@87B:9D<<@88F=>E<66@88<55A99@88<44B9:C:;C:;E<>55?66?67?56?56?67912;23@79?577/1=46?67:24@68;34;34@67@67D:55F=>H>?C:;B9:A89C:;F=>?77@88701@87B:;B:;;45E<=?77=77<66>77A99D<;F>?KBBF>>D<;F==MDCI@@G>>IAAI@@H@?G@>A:9A;:C=KDBB<:VMKPHGG@>SJIWNLC=;IB@?97LDBGA?OGEHB@KDAHB@PHFRKIPIGRKHOHDd[X[ROQJHTMKPIFPIFQIFSKHKDBRJGVOM]TQbYVcZWTLIVNKVOMYROUMJQJGSLJQIFOHEMFCJCAOHEPHEJDBQIFOHEICANGEKDBGA?GA?QIFOGEMECNFDLDBGA?QIHQJHIB?E?>D>=B<;A;9C=H@>LDCH??D=;NEDOFEI@@F>>F==H??IABD<;C;::33B;:D;?B9:@77A88F=>C:;A89B9:?66?66@67912:23;35@68B8:@78B8:?68>57C8:912>567/0:23@77?67@77C:;C:;?77=45>66?77700;45:34E;D;;:44B:9A::?88=77B::>77?87F==H??>77H??G?>I@?NEDJA@H@?HA?LDCHA?G@>B<;@:9>86LDBC=C=;A;9GA?RJGWOLGA?D=;D=;F@>QJHLECHB@A:8@97D>=C=F>=F?=JA@JA@G?>>76C;:C;:;42?87=77G>>G>?E<<;55A::A99D;;>77A99<55;45E=>C:::23C99B99C:;G>?B99:23901=45>56@77;349127/0C8:>57D9;A89?678/05./3,.3,.4-.:23=455./?67F=>B9:=55;34923922;45811811?88F>>C;:=66A::@99A99B::G>><54B:9KBBC;:C;:@98G?>E>LDCF?=HA?G@>A;:B<;C=<<75@97@97D>=A;9<64HB?VNKOGD>97:53:53LECKDBF@>HB@GA?PIEOHDMFCOHEPIEG@=RKHWPMNGD^VS_VRVOLZROTMJXQNNHDOHEUNJUNISMIWOLRLHUNJQKGPIFPIFQKGD?F@>QJGD=:KDBLECKDBD>=B<9JCAMFCTLIJCALEBKDBE?=HA?B<:D><@97<65943933:44A:9D=;;53F>=E=77:33:34D;;D;;?77>66;34B99A88C:;B9:8/0912901912;34;345./8/1:24913;34>56912>565./9129129129018/08/0;34F=>?77=55923:34@88>77:33:33B;:D;:D;;@99D<;F==F>?KBBE=;D<:D=;H@@I@?D<JB@KDCJBAG@>HA??86?86>86A;:?97?97IC@GA?:43JD@LFBZQOLEBA;8<75C<9QJGKDAKDBF?=GA?F@>HB@TMK^UQTMJHA>QKHHB@NHE\TQXQNSMISMIVOKTMIUNJWOLWOLRLHLFCNHERLHPIFLFDGA>JDBOIEQKGRLHPJFPJFNGDPIFGA?MFCTMKICASLJLEBNGDJC@GA?C<:B<9B;9WOLJDAIB@E?=F@>B<:B<;?97A:8@97F?=;64@:9@:8?98?98B;:KDCE>77>77E<=D::>66B9:B99B99@77A88B99;347/08/08/09128/0>57>57912D9;;34?678/07//912901912=45=45:23B9:>66C99;45;45?88A99?77;552,+:33I@@D<>IAAD<;F>=JBBG@>C<;E>E?=?97\SP[SPTMJ?:8C<9HB@LEBKDAG@>IC@KDAFA>KEBRKGZSOWPMXQNHB?GA>VOKYROYROMGEUNJVNK]UR]UR\TQ\UQTMHMGDRLHSMIWPLSMILFCPJFRLHLFDLFCHB@JDBE@=FA>HBAICAHB@GA?ICAKDAGA?B<9C<9NGDB;9B;9C=;C=;G@>E?=B<:KDAD><@:8F?=?86=75@:8?86@:9F?=QHGE>=D<:D<:>77F>?D<;D<;@99C;;922B;:E<56>56=457/0A8:@787/0;23B89D:;>566/03,-7/0>56B99D;;A99=55:33H>?G>>B::=66;44?77E==A::?88=66D<G@>MEDPHGNFEYPNGA?GA?>86@:8F@>KDBMFCLEBF@>NGELFDUNKXQNUNKQJGMFCNGDNHDLFDMGDUNJQKIZSONHEQKHWQNTNKRLJXSONHFbZV]WT`YUTNK^WTVPMXSOXSOVQMUOL_XUWRNTNLTNLVPMQKINHDNHENHFOIFNHEMGCUOLPJHNHENHEMGDHCAE?=GA>F@=KECE@>OGDSLIE?=E?=F@>E>OGFNGE=65C<;C;:E=66C;;A98=77C<>C;;A99;45=66;45@99:34@88;34B99@78B99A89C::@78?67E:<@78;34;34;23>56801:12801A897/0;23B99@78C::B99B99D;;QEF701=66I@@I@@G>>B::A99G>>@99F==C;;E==H??H@@E=NHEHB?NHELEBD?=E?=B=;HBAIC@NGEE?=F?=B<:TMKMECTMKJB@IB@E>JB@E>=I@@H@?B:9E=77D;;@88D;56=45?67@78?67?67<34@78?56B8:C:;KABD;IC@HA>PIGJCATLIQJGMGEOHENHFOIGUNKPJHTNKRMKQLITNKOIGOIGQKIPJHOIGOIFUOLZSQVOMSNKMGDPKHMGDLFCTNLRNLNHEPKHPLISNKKFCHCAKFCVPLTNLUOLYRNUOLTNLEA>LFCMGDPKIKEBKEAHDBEA>HDAIC@FB@OIGJDAEA>JDBD>GA?F@>EA>C=;E?=F?=QIFC=;GA?KDBGA?OFELECD=;A;9PGEMDCKDBA:8B;9F>>H??D<;D=>A98B::@87=66=66A99@88D<=A::B:;@88@99=55@88A99@78B9:B9:A89B9:@77B9:@78D:<@67@67@67I?@<34?66801<34@77@78B9:B9:C:;E==J@@G==@77H>>F>>D<>A98H@?JA@D<HB@OHEG@>NGEIB?OHFLFCPJHXQNOHEQJHUNJMHFOJHNHGSMIJDBNHEMGDLFCKFDUNLXRPLHFMJGKGEMHGJFDLGFHECRLINIGOJGKGDPKHPKHMHGIEBMHGLGELGFLGERLHJGDMHGHDAJGCKGDGC@GC@EB?EB?HECC@=GB?GC@EA>DA>D@>JEBJEBB>;D?=D>OFEC<:KDBIBAE>55B9:E<=G<>B89:23?66?66@77>56>568/0A88D;<>66<45?77A9:LABD<=@87B::D<G@>KDBRIHLECJCAHA?KDBE@>JDALEBLFDTMJQJGTMJYSPPKIJFBMGFKEBKECE@?NIFJDAHB?JGEHC@GCAMGFTOLNIFC@=IEDIECKFDHDBIEBKGEHCAGBAGBANIGIDBLHFIECOKGIEBIEBQMIIEBIECIECIDBGCADB?FB?FB@FB?EB@GCA@=:B@=@=;B?=DB?B@=IEDA>;B>=@<:C?=GC@JDAJEBLFDIDAMGEHCAMGFMHELFCIC@IC@JDAKDAKDBJCAJCAC=;D>F?=LDCIBAD<;E==F>>E==C;:C;:G??=76C;;?88?77B::D<66G>>B9:D;E;=801:23:23@77E<=B99<45C:;912;34D;>C;>G??C;:G??LCBIAAA:9B;9E>=F?==77E><@::F?=LFDRJGICBHB>@:8KDAMGFFA?E@>D?=KDAOJHQKHUNKQKGJDBKECIC@A=;?<9KGDDA>EA?@=;EB?@=;A?EA@GC@B@<@>;?<9@=:B@C@>@=;>;9D@?<96@><@=;C@>D@?DA>C@>A=;@<:C>MGEEA?FA?D?>MGENGELECICAQIGTLIHA?KDBG@>IBAF?=D=;C<:E>=HA@F>>C;;?87E==@98B::C;:E==<66C::A99<66<66<66E<66B99A88?77D;56@88?77@88D;;>77;45D<=LCCI@AB;:A:9JAA@99B:8F>>D<=F?=C=;C=IDBICARKHPJGC>DB@HDBFCAFC@JFBDA?IEBC@>GCAJFCKHEEA?DA>C@>>;9FB?EA>FB?DA>DA>EA>IEBIEBDA>DA>FB?EA>DA>A>DA>><:C@=A><:=:8A>A>=:7=:7@=;@<;?<:FB@FB@C>E?=HB@D>>C<:E=><65C;;A:9A:9@99911?77923;45D;;@88@88A99?77@88A88?67B99A88B99;34;34:238/0@78<45A99C::?77A99D;;@88A99923923922G>?KBBB;:B;:E==@87A:9D<;A98F==B<:C;:?87>87@:9E>;<97@=:B?<=:7A>;B@==:7643.,)'&###"###&(*- -/!/0!.. *+*)+*,,,-,,,,)()(*(+)-,11 78#78%55"41!64"13"/0!00 -,-,-- ))&%'())#++'21-631?<:A>97C?=IDCGC@C>JDBLECD>C;;C;;E<77>77923D;;?77D;901>56B99:23@78?67A99C::<45E<>D;;A99@888114..710600@99A:9C;:=65A:9@98A98D<;H?>B;9@:8C=;E><<76C=;E?=GA@GA?>97IC@B=;FA?HB@OHFMFDLGDEA?JDBD?=D?;88537421/,*)&## !(+.2!47$7=&47#56!;<$56 --,--/+++)))&$'$(&'%%#&$,).,+(.)/,-,,-+++()'-,003330200///.-+)'''& )($+*'/-+742=:8?=:=;8B><=:8;86FA@IDBEA?D@>D?=HC@NHFFA?IDBHCAICAC>=JDAC=;@;:D>>C;;A:9C:9C::@88G>>:34D;;>77C::E<=F=>:23@78B99C::;23@78C::<45912>56?77E<<:33;45OEEPFFLBCB::?88=66;55A::<55?87E===65A:9C<;?87C;;G@>E>87LECIBAJCAHB@HB@MFDICAIDBLFDB=HCAFA?ICAB>=:8B><<98;76854863863/-,'%$   #!,,223465:8 BB%@>!<:>< 87/+4.:56/7/4,0(.(.&/(.(-(/)/,3/0.-)/+.)/+0-.,2./-.+/-/-.+,).-..((%%#"%% 0.,42/;86=;9=;:><:GC@A><<97A=;?;9C>FA?B<:G@>F?=IB@JBA@98G?>G?>D<;E=77B::>77E<56912A99B::812B::I@@;45A::G>>B::?77E==F>>B;:C;:C;;B;:E=88IB@GA@NGEA;9E@>E?=KECICAHCAIDBEA?;76953:64=99854:7563230.+*("" '&3/85>!F@#KD#I@!F> C<=5=5>6?5?4;00'/'-'.'3,5/:38374:64/4,4,4,4.2,4/506242320/.,,)'&'&('+)-- ,- '(*+%10,975=:8?==;86><:A>=GB@GB@E@>ICBIDBKECJDBHB?LECKDBJCBD>=E?>G@?B;9G@>E==C;:A:9C<;G??H??;43A::A::A99@99>77=66B::;45;45701912<44A89:23?67912B9:D;<<34C:;A88@77=55@88?77@88@99C;<@99@99G>>G>>A99A99@87B;:D<<@87A98C;:A:8D=HBAGA?GB@HB@NGEF@>HB@GCAEA@B=:!IE'E@%D?$D?#DB$E?#G@#F?#C>!FB$KJ'GC#B= F?!>84-2+0)6060:3:4=:@B!;67/6.4+4-3-5/82:07-6/3-0,3/-(($'$$ &$(&,-..//!-.!,,$.-)975=;9><:>:8?<;=97>:8D@>D?=FA@MHFF@>HBAKFDICALFDE?=JCBB==A:8C;:F>>B;:I@@D<>B::;44;44?77C;66=55A88=45C:;A89912A89B9:A88A88A99D;66;44:33@88A::B::A::>77@99@:9A;:D<>D<8$B=&>8!D?&B=%ED'IF(OI)QL+SO,RL+QO-QQ,JJ(JC%GB%D=$>7 ;4=6:673<6>=!@C$;7;37/2,5.603-8/4)3+5-3-0+0)2)0(,&+%'#%$%#%$('+(//33#/1#-.)433;87?=;?=;A>=A>?87G??G??G??=65A:9C;;JAAA99A::G>=822933<55@99H>>@99@77B::?66;23@77701=45A88=45@77B99A99A99@88E=>:34<55;55@99G??C<F@>F?=GA?KEDJDDHB@KECE?=ICAHDBD@?GB@E?><75;75732('+ # ! !# '%)).- 00!0+2.75$;7%C>)D?)JI.MJ.VR3YU4\T3bW4f^7_W4\V3_\5b^6YU2QL.OI,C?&C>%D>%FC(DB'D?&FB'FE(C>$:482;3<6<:846/4-0,0,4.5/4-0)0)/&/'.(,'($(%'%'%'&-,0056#77%/1%..,<9:=98>;:B>>@<:A=HA?F@>G@>E?=E@?E>>E==C;;@87E==D<?>67A::<55>67<56712@9:B<A:9B;:D<GA@GA?JDCICAHA?HBAD?=F@>E?=C>ICBD@>@=&:5!:3;4B=$>:!:450?8!@>$<: :482;3733/4.4-/+2-.)-)-),(,)+(-+/.0/54#7:&37%/0*986=;:=;9@<;@<:B>=B>=FB@B=;D?=F@?GB@IBAICBJDBKDBHBAE?=F?>D<;D<>JAAC;;E>>E>>JAAB;;>77@99A::?77B::?77C::C:;=45B99E<==56E<=H?@B:;6/0>77F>@A:;A::@9:;67944;66944;65A;;F@?B<>E@?F@?E?=C<:@;:MFDGA?JDCD>?:8?:9>98<76<86953233## &%&%'&(&'&'%('))+(,)/, /- 2/$0.#65'76':4'83%:4&;5'<8(GE3MO:ML6]\@dhIb]Ch_DifIppMnnNccFmlN_bFUV?TS=QM:NN:JQ;JL7JG3OS;LQ7GE0C@-?;(=6%=6$70;5#>:$D>'B?'B=%=7 >8#<5:4=:!:6:485420..,-)/+.+-(0+3-3//-0/34 48%58'360;:9>;:>:8:75<86@;9D@?B>=F@?GA@FAAGB@E>?@;:B;@::B<><67:46?77A99D;<@88912C:;H?@:23<45@88E=>F>?:34E>?>88D<>?::C<=C=>@;:F?=HA?F@>?98C=B<:D?=?:9?:9?;:943433 $#'&)(,(,(., ,+,+ -+/.#2/$//$33'32%43(64)<=0BC6@>3GD7LF:VN@_YIjfRehmzu|yrsmjmfyz_m}anpVffOd]IWQ>NF6MF5MF5JD2NK4II2FD-B>)C@)@>'><%?;$<7!<7 <7!87 6644200.3-2-2/635/3.40302257!57#43"01*666<86965@<;>:8A<;B==HBAGA?@::C=>IABE>?HAAG@@?87@9:F?@F?@A:;C<=IAA712@99<56;45>77?77D;<;34G>?H?@?77?77C::?77E<<;45?88>87>88C;(@?(@B)>?&;;#65:7 87;; ;: 86624-82;5844255 46!58$45$/0(565<97?;9<86B>=GBA@;:C>?HABG@AD=>=77>88?9:?9:B;<:56935=78D;;?77@88?77@88901=56JABG>>:34?88<56B::E<?@::>89?99=77?:9:77;88844A>=;43>87HA?C>=F@>ICB>:8965B=;731621410024 $! $%&&&(+, .3%08)4<-27+77,;7.?<0JG>$:8 634/73;6:372846556!45#6:&12".0.;97>98?;:B>=C?>HDCF@>JDBB<;?:9LFDA<;A;:@:9A;:D>>D>?A;:?;9B==A<<=78B;?D<?E??E@AC?@NGFHA?F?=JDBB<;D>;E?>?:8:54:53>97323$)) $&&')),, ))++ ,,#/2'<@4GNBR]M^eUmp_u}jpudzzjvzumreqqdyvlxxm{ry{ntsfvriyy{|ͫϫƤЫͩŤtvj}h}hx{pjzyatx^vi{jptZkkTmkRjjOjmOhlNckK]fEYaBOV:EI/>='75 52:7 76:57485:5:6:8 87 0227$5;&//#243>:9?;:>:8D@?D??D>=B=MFDD>89E=>F>?JBBB;<<56<56A99@99A99=56=56911<56C;;A::>77:33821;45A;99HA?D>=B<;>98B<;B<;@;9965:531.-,13 ! !!%')-#-2$.0$/0%..%02)680?D;OTG_fYmte{svntzyz{nzxqrtixvmy|q|}syzsy{ny}zˮ˪ãƣȨͫ˩Ťzy|zvltzumyybyi|nyjr{blv]js[js[iiRfiOpy[jrUkqSciM\bEMO7CB->>)=<&<;%;:#=:#;8!8564;6 ;8 88!55!5:%3:&02!/1+=<;<86>97>:8A<;@;:C><=87E@?HB@LDCD>=JBBLCBD@@?;;E?@A;<@:;B;>E==G>>D<=HBA@;9A<;?:8@:9732621%,-! !!!!##&')-!,2%-0$/2'4:/OO8FF0BD.=?)45!43 66 86 64 87!:8#34 26#37%46%12$055=97>:8B=;=98A<;B=D=<=88?99@::B;<@:;@::QGHNFGKAAI??LCCKBBA::701912@88;44MCCE=>LCCD<IAA?88H@AF?@B<98>:9942732976!&$# #$&')())+ ,0%04(48-8=3FJ?Y_Sepbirejtihqhhqhkxnmzqkrmsnrpqrsyzksiq|rstss}}zv{vz|v{||tym{qvnslq{hkt_elYdiVfmWdqZ]hTbhT\eQY_M^eQ[_MWZGY\G^bKZ^F[cFKQ8CD.=>);<'88$75!64 56 68!57#48$25#58'67%.42:76<87B>=A<;?:9FA@FA@B<;KDBIDBJDBIAAC=<@99B<D==?88MEEPHHJAAE=>MCCODEA::912;45=66@88?77KAA=66B::E==A::G@@F???88<66JBBHABHAAA:9;65F@?F@>?98=87?;:;65100!#%$!$%( )-$-0&26)38.;B6NUG[dUbk]jselshntjpypkypl{scqjbnhkunkzupznvxxyuxyz}kulqzptxqxuyuuxnssj{yvu}}|}|uu{jtxxstmrxffl\hp^kzdes_]fU]dSW^NY]MZcST\LT[KRWI[bN\cO[_JY\FVZCQV?KQ8@C/<<):;&68$68$6:%68$77%04#2:(8=,260975:65C?>=98C>=B<IBBIA@IAAD==>76@87HAA;67B;;RHISIIJAAE=>JAAE=>A88=66B::B::;45=66C;;E==B::B;;C;;JBBIAA=77B;;KBAA:9IBA<76?97A<;942:54;65655!$ %&)$)/'-5-2:2:C8EOCUbUcrcmppsl{phukivmkxnitkjyrf{sh|ucxscqll|usurzyyu{ryryq}ttyx{zu}uptltzqz|zx|rzyzzx|uuy}yzu}|vsksdjqbn|kx{mn^k\]fV[bSZbT[hWZiYWbSVaRT^ORYKRZJRZFT[GS[GQZDSZCOU?DI5>D/8<)7<(6<'7=(7=(38'2:)7=,36,644;76>:9=87C>=KDBB=F?>A:9D=>A::B:;I@@PGGPEFI@@NCDKAA<45B::B::B::JAAC;;D;;E<77G@@C<88943721111 $%')!-3)0;2;G>N[Rathh}rmyn|l|qkycyqdzrevpdumj{tezsi|hd|xcspm}rty|z|zutx{v{u{nzqq|srxxx{u}qvzmtp{urtxrp|}{zvyktijmbr|mttl|kbrdbp_^iZ_j]fre^pa]pa[l^S_UQ\QQ[OIRFQ\MO\LR_NTcNR^KOZFMWCLW?BL7=G3:D/;D-6=(25%/5&7=,23'644<87=98A<;D>=FA@MFDJCCG??KDDH@@H@@F??F>>C;;C;;B::G??XMLF==MCCMCC6/0A99D;;D;;MCCE<>D<;KCCC=<>76<76A;:F?=>87721+-.!#&)!,2(:@7KUJ\k^ktqrrlhhlkkfyf{vf}xh|npkifryv{x|vyxu}rtvtql|uryu|uturszmu{mzt}s{}lrrvtcyxez{xn|sjukvyvksjylj|npvnvh|qdul[icSb[Rc[IWQK]TNaWNcYUl^Vk\RcURcSTeU[r[YmTOaIDQ:98A<;@;:HBAJCBE>>LDDF>>E=>G??B::XMLSHII@@I@@:34?88F==922C;;D;;A:9D;;B::E==B:9E>?D<<=76F??NEENGF=76=86;54:54./0 #$&(-$/6,BJ>]fYjykfynf|uh|fhpplifijfdjjjklhfqyyvz}y|yyvrrqplsrpyqukxnn}rr}ppvhqtdtqbyzjtvflm_ifW}úØÛØȿǟȟƟÛ͠ȡȜǞɒ{|umx}|m|qtzqjzbzu\tpWrmVnjTnhTskQqiTpfUpiVtkVrfUmb]ye^{bZqVVhLKV=>F06<(26$/4!.2!26&13&133844@;:>98A;:B=;G?>>98E>=LDCC<:D==G??H@@KBBA:9PGGXLMMDDJAAD;;701A99@88B::E<>C;;H@@C;;F>>NEEC;:D==C=98A<;C>=LEDE>=G?>JCCH@@D<;F>>D<87E==A:9E>>;54832:54GA?721#!&'03(GK?dm\vptyd}pVhaSd^ThbOfbOkhSrpZ|}ainxzyvvtrkdeheikstvx}}{ytrrquvzztrppnmd|rcvlcujanc\f[ZeZ{ʒ|z}yyupmijmjf_]W|vSumLe]MdWQjYWs\YvZWmOYpMO]?CL27>'28$04 /3 7=)-/%302;75@;:@;:A<:GA@C=KBBH@@F==C<;D<>868320-,%%! ''.0(OQDnucsrrrfuj\rfQcZNaZQhaLeaG_]Ic_NnmSyyZ_kvؕtpnmnnqv{}|}}{|}|}ƀƁÂ|}zxtmm^vnQ^^by{˕ߌ}xtsssnnpmmplklnpqnmkkirqlhc[SvrMidMe_K_WG[QLaRL^NQbMQbJWkLOcCJV:EK2;>'28#0237$8?+),!410<87D?>D==GA@LDCNEDMDDULLG??D<>D<>J@@C<>E==A::E==B;;B;;D<;B;:G??LCBTKJ:32>86F?=B<:<65/,+ $')!45,RTGck]kmi}kixhfuhYi^JYRIWRFVSI\Y@TRE^\IeeKklRy{ZfrϏeYVRRSRWfsxsqrmmmiiilpsv}ނՈъΊΊɈƄ{lKhlpdZVYZZ[[\]emmjfdd_bba\Z[VUVUTTVWWVRRT_kmd_WxvQpkRjeF[UCTMEVNDSJETGGYIJ\IJ[EO]DTeFO]>KT8EL3=C+35#23 6;&:@,''!?:9@;:A;9?:9FA?JBAIA@F@?F?>B<;D<>H@@G?@J@@D<76KBBMDDMDCKBAE==>76=8772120/#"#$)-$;>5RUI[bU^j]apbcqcapbWf[O^TFRK=KE>LG=LI;LJ?UTC^^GffOtvYdnzŅܑM7n;VY:KJ5C>6B=4EC;RRGj_huule\|U}rN}rDsj6db8jm6mz;{BJRZdp|ތْؒ׏҃iv{I3h}6W^=UUFWQL\QQbTTiZK\TBQNDaYO|r]_^V}SxN{qOzpQynJri@e];\U:ZR0OL0GF3ED3GE.DC.>@3@C:GK:IL7DI3>B0?F3Vk@^e_WsrRjhNicMc[GVN@LD>J@?K??K>@K=@L=FA@G@@PGFIBBLCCB;:B::>77C<G??E==C<=<64@:8:54(& #%)+!6<;,>E7=K<=C687)7<0[؞؂taOzt,><)EE2NS>UYD^]I^bJQQ>BI<_{smkli[Z^]zrTiaIVOE<>E<=G<=I;?I<>F8=D5CN
KaDJ]@IVF.6<(04!/2 7?)$(2.-:65E>=E??HBAIBBF?>G@?KCBG??B;;:33F>>B;;G?@F>?D<=D<>F>>>77D<>A98>76B:9C<B5[iW\k\R^RMWLR]RIUJGQFIRG=E=7?87E>7E?:LF?UN;SNBZYIhhSxyW_mxЉ[78262&>?5@K?@K>8:-CZRv{tmkkjpt{ރzfN}tvGThxyucFLSB8=B7=C8=G;24;/;E6BQ=G\DNfIFU<@J4)4;&24#47$27&&&";87>;:IB@G@@G@@F>=HA@A:9D==G??F>>KBBH@@KBBD<>F>>C;:A98G??A:9?88732(',.$;I?;JB>ULB[SFd]Gc_LiiVzz[^nvΉe=E>:5(65+>B6BJ<@B4Nrlqib[\[W]al|yZBRE68(65&;G>>aeCNUSEDYMTYCZ^GdeMimThpYrxarzaYU@Sρvy|zxvqmlprrjejljc^cmstuxFGCNSIGNCEJ@?C8;?66=47@53=22>22:/7B3BS>BS>JcGLhI?N78B.3;'27%48&04!5:&*."3/.=:9E?>C>=C<;=76F?>IAA@99>77<55C;;H@@KBB923:34F==E<<>77C;;IAA<65C;:F>>A98=65C<?980.,,- ;>2LTDMZLKZLGSF?G<;D;6>6;I=;J>>MC;K@=NF=SJFZSD[VC][IeeTyy\blxъf;D=88)66,;>3??5=<.Ntqއsb|vUf_Qd\N\UQb[Ob]Kc_NkfUyuYZesͅuOj^<00-?@;DF>?>7@C;>C:6=54=32;02:06?45?3:D598A;:A;:@:9E>=F>=LDDJBB<66E<77>77D<J=;E::C85@65<3.5.2=40<@4>C7==6@B8?C:?C:DMB=I=7<36<35<35<07>2:B4=F6?K8E_D?Z=6G24D-0;&.5#.3!37$%'0-,>98B;;LDDKCCQHHJBBNFFNEEC;;E<78:33G>>A:9@99D<<@98=76:43C;;A985/.-('+('26&IT@Q^KGUFFYI@SD:J=8E:4>54@6-4,4=4;D;DOC?K@MYORbWN_VI\TE[TBYTGa]RpnZyybclxˋߏk;E>==.BI8IN?IM>EF7Svs؅rd}zYibQ[SMYNO\OQ[MSaSRaRNZLOYLOZLJUJGVLJYOMd[Sup[n_:C6>3ED6SUETWG\_Nx}hxvyjdmYUT?[}hyr^e^ch^jshithipddla^dZ[[SYWNWWNZ[QTSIQNELLDQTMW\Sjkarthmpchh[ii\hi\ddW_^T[[O[YNZ\QUVLTTJJLBGNCDK@DE=BG=BI=>D8:D838/08.:E7;F7;B4=G7DY@D_C>W;:O40?(.8$/6!06#-0 $" 953>87H@@LDCSJJOGGPHHOFFG>>G>>C;;G>>H??RHI>88B;;D=<>88C<;D=>=76>76<65=6540/*+%?F5OaKIWGCRCDSDCRC=I<6B75D80=35>5<0DD7OVE]cRiq]qzex}{lckTTU@Utdpicf^hmbmshptfmpcii^caV\[RZVM[YN[WNTQGRSISVMY]T[[R][Oji\mpcik^ik_hj^dbVa_UccW_fY^dVZ\OSTINVJS^QKSFBD;FK@LYKISF;@75:05=38C6:D6=G8@N<@N;F]C?\>;Q63B+0=',5!-0.2 510;76D<>H??H??NEETJJMDDA::JAAC<;E>>=76F>>B<:B;:@87:4383303&IT?M^KJ]JBVEFUE?O@?M>@J=>N@:I<7D:5F;FVJM[NI_RF^SLaVFWOJ\UMhbNsmRvs[^dmyы|JcVD>0KL6:=5=D8CQB=I:=O>C<78701;44C<>C==D<<@98?87;43;54832?87)/)3=-K>JWKScUTaTT^TNZQBKERe\?TM@SNF]ZTqnZ||dlr{LJؓGq_?I5DR>N\KVaRSREc؋|iauq[f^V\SW\RUZOY\QW\OW\OZ]SW^SY^R\dVZaT^eW^eW[aR]cU[_R[bSeqbd|tvqZZKvm}zptcfkY]_NNK>Q>DbJGeI@U;?Y;6J03B))2%,%)%$!>87E==LDDD?>JBAF?>D==H@@G??G??I@@KAAWMM=66D==D==D<>C<4DJ?MVKIQEMVLGMD=D?S::N46K04D+)3 !($(##B<;>87D==E?>JBBLDCE>>F>>IAAG??C<>A98<54E==@99=76945), ,5)3=/:G8CR?GWDJYE@K=;F7/5+.5+4;28<4?C:LUIKTGLRGKNFCIC:D=>KEGVQL[YKa_QpnZ|{\fszŅ֗^sLWERYKVWLY\N]^Rk}mezr_mcZeYU\QU\RV[O]bU[]SVYNZ_S[aUYdV[_S]bU_q_aiZafYbhZbk\dh\dj^tvnyh\dUZ^QWWG\}uy}x}sst|ptymy|qv{mtvkrqelj]_\RVRKTMFTOFUSIYYM_aU^_UaeZ^cWTSIZYO]bU]eUZ_QU_QT[MORGRZMUbTO]OR]ONYLIMCBI?DLBDLCFOE=F=F:?N??R?BS@@V?C[?@\>7N42B+'0 !'#%!!621D=E>=LCCKCBJBBLCCLCCH@@NDDB::E==E==KBBG??B;:D<L/6,/4+,/&25->F<@QDDUGFQEGOFKWM=IB=GB@NIFYUKcaVxuUxxbfr{ɋޚczQWJT\OT^OT_Q\bTnςtfzq]j_^k]T\OU^SW[O]aV_bVY]Q[cV^eY^h\_dY]cV^i[bn_^hZai[_i[bi]epdv|u׺Ǭkuf]fWV]QVWIbڅuqyzsts}rnyls{pv}qsvkqvjppceeZZZQQLESQITUKWZO^aV__U\_U]^T[ZOTUJW[OY]N\fVTdTR\NOVKR]OS\OKQFLRGLWMEODDK@COE?MCCQF?J?6<3;>4=C6K:>L:@R=?U=>Y=8N50=(&. %!$"!1-,@:9C<>D<37J:>LLFDTNMa\Qhdc}fiqvϊޛ_}tVUKSWMW_SZbU[\Nlސˁvj|s_k_]bVYZMY\OWZOZ\RZ[OY[O[cV[dV\^S^cW^fZ]cY]h[^hZch\^bW\cWdlauxȱtvdma[_SVZNVWJ_܃xstp|rmzqlvllulksjmtkmsjimdbe^[c]Vc_Ued[ji]b^[\TZYNWSJSLDTUJSYLTWKSRGZaSRZMQYKQUJNSINSIQQIKOFJRGCK@?J?>B;?D55>4BN?BS@;K8;N;@[@>[>7Q6,;'%- % # 831H@@A:9D=F?>F??KBBKBBH??B::F==F==JAAC;;B::E==B;:C<<@87?87=65:66-7)-8,3>3;R?MIAAJBBE==D<O=M<=C4;>28B33:.6<0;?3UaNZmVGUEFKBUbWTj]O_VO_WK^VUhc[zudlklyÍԕcyVVLRRGROFZ\Qa_UrŁ{qyjujinaadV]]RWTJ[YN\ZN]ZObdW^bVY^S]aU]\R[\S]bW\_T^aV]^U]_Uhmcr{q׳|}kvi_i[[aTZ\N[urv}}zytmmkb\TKEhvFdnZsrcZxuUlhSeaN]WKYSN]WMYSJWQKVNJTLFLEFIBIG@JLD?D<E=7=8262,2,,.(,)$8;26=2:E77G8:M<8J7=Z>;V<->)'/ '# 843B;:D<>H??D<65655%),6+/8-6D5=MMWKUl_TsfVtfRlcWpia{qyqlxŗޕi^_UadZWWLWYM_]RsߐŁ|uzmshlk^feW]VLYTI[YM[WL[YM]WN_^S[]RWVM[[O_cYej]_dY\aV]bY_cZryntus}ͪ}tpvvtuhrd_i\\cUZ^R\i[_qʀ}zukfc^SQ|tQpeJ[QDI>=6-6, 6)8, >GE^pZ}SrnSlhSniUniTjdM_YIUNEQJEOIDKD@F??B;?C<6>75@84?73;4060,.(&&!+,%5:/6?33<00;.3?/7K54F0+5$%, '#732B;:I@?E>=NEEF??NFFIAAD<>E=<;54?88978&) )3()4(2=/6D4=F6;F6BS>5=.37+=D5=E6=B5JO?YaN\bOJQBEOBMZONe[RpbYpe^vp_xnytt{ؘhYYO[YQcbUa]RcYMvّxtvqthhaSh_Sd\O]\N[ZMYSGYUKZULa^SddY]]SYYN[[OdfZcj_bh]ae\ntk{xrxmmxrǣ{nuintinzmfnb\bU\cU]eVaiZ_m_xvuxsqle_chkpcZyxYtrTsmSskQlfJ_WFVNDMG?GB?F?;B;;@:5:36:3572./)22++.'(,%/2(.4)2:/-7,3?/2C/0=+.>)%.# :53944=76B=;D>FM;>D5CE6QG;D<462/2,-.(//(++%)+$.0',/&.5+-:-/;..7)2?..;)-:'%+$!$#:43?98C>G??A::?99E>=A::F>>JAAE>=H??A::F>>C;:B:9H@??87?87942,-+)2&(3(.8,:J8G5EK8FN;BK7GK;IQ>MYCWcNS]KVYIWbOUbQ[aSepaj{jfvelntxzٙrVYNYZOfaSnhZsj\Ɍ|xutshtnbpiZjcTiaUc[Na]QaaSZVK\WL][O__T[WMUSJY[Q\]S_dZdk_nrhsvkjldcnmܘuyhj]di]cj^ai\al]\fVUWIcrefe^a]\[{|Z|\}^}ZxzUuvVxyWxzZyzVttSjjM_^ESOEOMFQLLTQOVSNVRKUQJOLMSMMUNISMGRLFRJDOFDRIDSI:@803.28304.24-.2+-3+03+.3)0;./=/.8,-7+/=,/:+)0! '#*03;54610B<:D>=>87H@@H@@G??D=>H@@G??E>>D==D==E==KBBA:9A:9?87@98E=<:43202)/#(.%+4(2B0:G6=I5IRLO=MS@NVBRVDOUDZ]LZfR]p[iuanvfr}pprk{trq|˒؜raeY_cVnl]tp_yiߜɍzxusitl^pj[idVhcUeaS^ZN\[NWWKZWL[ZN\YM][OVWLVWM^^Tdl_hqclshrymkpiduyvrmsekrehpdfl_fqb_k[\_Ojl_{tavnd|rbrf]h]Ze[S\SV[QW]T[aV_cYch[]eYYbUVZQ]bWZcVW[OWWMUUKSVKQYLMOFJG?IJ@JNDEI?B?8EC:DF<@E;?D:>C7BG;BK?8>444-36/02+0/(22+00(36,5=C<;D==H@@F>>C<>G?@F>?LCCNEEE>>C==H@@@87D<76=76?98845-4''-#)3&6D38E3@R;LW?ObEQcFOU@V_IYhOY]JSUEY\Kk|ckhdr^q|kk|lqxnqnr|͗ݔݜqhi^kj_rl^{sepΓ{xtrhtk^rk]nk]lhZfdVc^S]VL[YM\ZO\ZMYTK^ZO_bUZ]R^cVinbinbhlbpvlnzy{npcszllrffmbbfZhrdfrchjZnq_tn]jc[f]W^TYaVZeZZj]WbTZ\Qfk]qvfheThiWddUb^S\ZN^^SVYMVVKYZNT[ONQGJI@MMEJMDEG=FE;D@7B>5CE:IQCDL??C7@B6@B6=B656.22+00)-)#-)#.+$32(7:.8:.35)+/$'.#)3%)4%%.!) ?:<=75E>=?87>76D<;G??G??H@@JBBG??IAAH@AH@AIAAG??H@@F>>D==E==B::E==A::>77:43932-2*(/$)3&/<,7D0?R;M\BLcEUtQ^nQ[bJ]fOhkTaaNimZu||y{{}}֜spfsmc}sfuiqʘ}sum_qhZni[kfYhcUhaTc[Na]QZYLUSIWVL\ZN_aTdeZhi]fi]jlbih^kpjslk_imahpb_h\Z_T[dUai[bbTll_up[f_Ze[YcWW]R[eWcreftenqarxlq]diYacTceY\]RZWMVTKTRGNLBONDNNEJI@KKBORGJK@FF=EE;C@6B?5EC7@B5>?487<54@98D<;F>>F>>D==>77IAAG>>C;;E==I@@G>>G>>IAAH@@C<76932<54<65577,0$+3'-7(5@/LODQNDIF=NODSWJMOCIJ>EB7@>3B@5?=3@@5==2;=0<>3>E==C;;D<77610732,4'-5(-5'0;+=I4KZ?WhJYiLueerTahQju\sesȨºſͳ޺ܦſnzxfuqbnfYpfZnk]tseuqcspbrpcb_Thl^fk]bdY]]Rhd[lqfi{v탈|znjlbcf\ej_^cY^cW\cWZ_TccVum\xrZkcU_VZf[YhZ_nbhzkysv}kyqus{mnrbifYacUVUKWWLVVJRQDUWKW\NUTGQOEQSFS]LMSDFF;DB6B=3=:/?=3??5@@4<7-;7-=;/??3=>3;J87=/27,/7).4',4%'2$&-#& 4/-@98E==G@?IAAKCCIAAG??>77@99G>>I@@JBBG>>E==@99D<>B::C<775//942041-3%.5'2;,>J4JY>TbFVbFbjMhuVs_xerʯͳdzǹޣ{p{j{sdzsd|vh|myv|yqx}m{}qqvinsfhpfl}ϣx}tnqfcf\ch][^USUKVYO]]Ua_Tuma|[rjUd[Wf]cyjlrsyqvlvfnqay|ipmj[kq_im^_eT]bRVWIZ^OcjZ]\NMJ>JK?NTEIM>EI;CF8CD6CC6B<2@<0BB3BB4?=2?=0:8-87-:/3;,.6'+3$)/!$( $# ;53>76E>>NFFG??JBBG??NFFC;;@99@99E==B::;45@99I@@G>>E==B::E==E==C;:F>>E>>:33=65:42711235.4%,/$.5':E0DO7OY?\iKkuUlzZzi}jzƱʷͿ˗uyk}n{kquzy|r{zx{qxkfmcbh]]_VVWOVYO^aVjj_rfa|saxmf{qv}zx{q}uqraij[jeVmkZtr_qk[d^Rf]Q]dRKQ@GKG??G??E=>JBBI@@C;;>77H??@99;45<56>88E==E==F>>C;;<65932C;;@88>77821932720,85.2$+0$4=,?J4LR;W^DmzZr]|jmltưͽ˟uqs{u|ézsmrffj_df]_cYaf[ek_tvkrikm|rzx{׻Զ}plk[urbzisyq_f]OUOC]ZJW[IKN>C?4DB5EJ;BF7?@4><0<7.?;/=08>/77+7:-07(,2#,2#(,#%('#=75=75>76C;:H@@E==KBBSJJG??IAANEELCC<66@99B;;@9:@9:>88?99>88G>>D==@:9@97A98@99821832721832456/4%,3%/6';D/MU=/>/87D==IAA?:9H@@PGGG>>I@@E==G>><56B;;?89G>>E==@::@::KBBF>>?98=87?97@88?888325//94272004408&.6(6<,IR8T^@bnOpzW{ah|ƱªװǷ{vxyruxmtvkvuiûΉøŬ°ɯspmZfeRabNRO@OL=EE8::.;8.@?4EG8LQ?GL;DF6=>2;:.=<.88,8=.;>/:=.7;-47+36)38).4&27'06%-/ ((0.+?98=86E>>B;;H??F>>QGG?89G>>JAAF>>B;;E==D=>D<?/BE4BG66;.47,37(05'07'05$.0!()&% >87E?=@98B;9C<>@::D=>D>>H@@F>=?98=76C<<@98932<64;6474366/4:+>E3KT;UW?fjLppT}apѿݻͶƴƹ˾ʺ¸ݺ|ȿѐŏáДȧب٪ňpr^WUF_]KTT@TUCTTBJK;MQ>QS?FF7BB4<;-75(>=.<<.BD3=<->>/CI7?G77@/3:+.3%06&-3#'(""50/@:8;54C<;E=>D==JAAC<>JAAB;;C<=/GF5IJ6@C2@C2==-;?/=C<;?98C<;C<>E>>E>>F??G??C<>B;:70/821820<764//94240/:8.?E4KS=RY?^cGllR}|c|˺·ѽ޻ǤŞʲfeR]ZIUWERVDRQ>OK;KG7LF6KJ7GG6LL8SS=ML7CE4CK6@I5@L:7E2),!,-!+. ')""41/@;:@:9B<;A:8A:8A:9F>>E=>E==F>>A::F>>D<<_STUJKKCDG??PFFRIIE==A::IAALDDF>>@98>87@88<65?762,+<65:539433..4/.;8/BI7KQ97C<:A98A98B:9=65@98C<;@99D<>H??LDDOGGKCCE>=H@@C;;A98?973/.610943<640+*:54971CK:MS?WYEihR}f}޴ڳܮԫϫͬͮ˪ʪΫͩǛލh{VYMSQBJK:CD4@=/=:,D=/GB3LI6NM8JL8KL7IK7@F55;,.0$,0#()(& 832=76;55932D>>@98@:9G??D<>C;;F>>H??H??JAAF>>5..923OEE?88F>>A::RIJQHIKBBG??KCCH@@LCCMEED<;NFF@:8710=763..832/+*610831?:6FJ;NR@[\ImlWs˽ݽպϰǬƮéû{ys{xڔȋ|}|}unptb{Qd[FMBBE7??0B=.E@/@=.JG5QO:KJ6EE3=@/25',.#+/#(+'&62050/?98?86;54A;:C<;D=;@87<54E==F??D<>D<C@3EB2DC0JL7LK7GF4:;-56(,, &(().,&83151/610943?97<76=87B;9E==D<;<54=65B;:H@@A::IAAD<>?88?88G??OGG=65E>=@98C;:G>>@:8@:8<75C=;50/6103/-2.,50/630DC8X\LfiY}|mºɻŸysq՞ؠٟٞژѕԗϐʓ΋ɉǏɐ΃rfa}tZqiUleSiaVh^Wka^ujjvh}p^mbUd\ViaVj_\pd^vi_xj_ujhtlxdxl_rj]qjUmhUslUrlYtnWqjQcZKTGKN>II7DF4CE388+./$()''&&,*$832:53<65832932C=;?97?87<54B:9D=>A:9F>=C;;G??NEE@99E==D<>F>>?88PFFE<<4--?88LCCD<>G??G??ULLIAAF>>F==C;:C=<<65621F@>@:8:5450/94351/>87A@9Z_Qhl_tʾymvxfz|ykby\xmWncRaZSe[Uh[R^TWi\cuhYh[VdWTbUNZQN\QSdVVj\Wk\Wi\TdYWdY[i[TbWQ\SO^SMbUJ\TL^USj^YseWmaQ_RGRB:@204(-/$')%&++ 3/+741>86:54E>=943843;54=76B<:E=>F>>F>>OFFE==F>>D<>F>>D<>700923<56C;;JAAJAAMDD@99LCC?88=76RIIRIIIAAULK>87?98B;9621E?==86=7672194240/2.-<76<;5UZPfqe|zʾ´un||xnih}hd|_{qQh\N\RNWMQ[NO^OMZKYcSYcUMRGDK@JUGNWKM[MOYKMVJO\MMYKLZKMYKMTGS[LNZJOZJOZJNYIR]MUcSSeTM^QDUJ?OE3@6.6,(.$')!62-954>97:53=86932732D><<65<65D=;D=;B;:D<;D<;C;:G?>H@@H@@JAA@99C;;A::E==F>>?88F>>E==LCDH??OEE@9:JAAH??JAAG??D==YOOG??D=86>87>872..732620954MQIhriͽvpy{t}yt{v|t|hsbxjauf_vhUmaLZNNZMNSFJNBGRCOYITYJMOCFG=>@6DILL?OUCKQ@IL=EF:FL98>98?99@:9F>>G??F?>D=;=76F>=G??A;;F>>G??F>>D=>E==QGGLCDLCDD<86;55>96@:8<76842=76732B?<\aWv{r½ózr}|ux{z}|qppkhrblveYiYQ\OTcSR_QLUIFL?FGW^EVdKO\DIQ=DJ8=C4:@22:.-4+,/(?<7JEBJDB@;9A<9@;9@:8=98C=;F@?D?=?;:G@?@;:F>=C>JAAD=;A;:C<<=77=77H??I@@JAAD<>D<H@@>66E>>E>>LCCIAAD===66A::=66OFFXNMSJJTKKH@@NEDRIHPGFLDBIB@C=97:64842953<75953;64@<8XULvrfyŻλǴîxx}urxpu|ey}eqv]hhRZWF[YG]]IVZFUYEZaJQUBRM=OMKN;GL8JJ7KJ7GC4C>/D?/C<.B:,GF4EI4EI5JJ6ML8RW?QZBGQ:@F47;,24'13'65,EA=A<:F@>KDBICAGA?C>;@;:JCAHA@ICAC=<@;9C==B<;E>=H@@KCCKCCD==H@@H@@@99>77JBBLCCF??@99?77B:;I@AJABLCDI@AF==F>>LDEPFFG??H@@H@@B;;D<:`\RykyξʾѾȴ«»ztvyqriivbfiQ\\GWS@RO=ST?UU@TV?QS=WYBLL8JF5EC4ED4GJ6WZ@JJ6RM8MJ6QK6QK6IB0JB0C;-?8+=6(=7)@>-?@/DF3BC2BB0BF3-6:+23&0.$>;7MHFRLJKEBKEBJDBGBAHCAHBBB=;HBAD=IA@F>=A:9A:9>76=65E==F>>E==F>>G??B;;<56A::G??E==F==F==C;;JABJABLCD@88C;;KCDH@AA::KCDLDEG??H@@E==G??H@@ULLH@AH@?KCCKCCLDDJBBLEDKDBF?=B<;GA?OHFFA@C><;65B=;A<:C=;>962-+62072/?:9GB=g`UvitȸƷҺʲ¨{ulhf|y_}b{y]}^qmR\VBRN;QL:QK7QO:GG5LI5MI6JG4JG3EB2>=.=<-CC0NJ6SL7TK6SK6RK6OJ5NG4LC0IC0FB/E?/B>.@=.;;,67)8:+78)7:)46'36(32(:85>:7B<:C>HCAICBE>821>77>77IAAE==F>>E==A::B;;E==F>>A99I@@H??I@AJABMDEH??I@AKBCI@@F>>MDDLDDB;;B;;G??G??B;;QIIZPOB;:LDDIA@IA@KCCD=OHFC=>97D=>97=85832=75>96HC@B=:OJCjbU|ud|kru{ƺǶ˻һζ˱˯ˮztp}d{a}z^utZrqUqpSqqRfcI]Z@YV>MG5GC0GC0JD2C>-B>-BD0EB/D?.@=-GD2C?.E?.MG3OJ5^T97C=:B=;?98OHFUMK?:8JDBFA>GA?IB@B<;E>=NHFC==D<;?88E==F>>RIIKBBLCCJAAI@@E==H??F==C;;B9:I@@MDEH??I@AMDEA99B;;G??G??LCCKBBH@@<66E==F>>JBBTKKG?>JBBE=87IBAF@?JCAKEDHA?HB@G@?F@>E?=D>;IDAA=9@;8=97MKBfbTsn]{tcucyekqxƻDZɲδγ˲ɰƬƽxqjjdzuZurVuzZszYquUihKcaE^Z?TQ:WU,?<+><+DB.><+E@.MI3QJ4]U;8C>;GB@FA>D?<953B<:C=:IBARKIE>=ICAD>;B=87IB@G@?KDCMEDIA@JBBJBBJAAIAAIAAMEEI@@E==G??KBBRIIJAAH@@E==G??H@@H??H??I@AE<>E>>JBB@::LDDF>>?88@99>77D<;C<;KCCKCCSJJJBBH@?MDCMEDC=IB@MFDKDDLECPIGB=:B<:?98:53:53;64@:8?96>97?:8@;8?;9EC=WRGfaQohWsl[ul[xn]|tavc|hlruz}|vnk}cupVyqVuY|rVrqSrWauZhmKihF_]?WT;OK4JG2NO5KF0ID.F?-C<+JD.F@.JF2KJ4ST:SS8RO7YV=^]BVR;KF3ID2B=,@=-;:);8(73%50$85);80?;7>:8FA?B=:B=;GB?>97JDBD>;>87?:8=86D>;C=;LECLECSLKJCAIB@MFDLEDC==IA@MEELDDMDDRIIF>=F>>C;;>77>77@99F>>E==E==G??G??I@AJABI@@H??E<>RIIE>>LDDNFFH@@JAAE==KBBKCCKCCJBBQHHNFFJBBH@?IAAIB@MFDG@>G@>JCAHA?JDBE?=HB@C>=8ONB_ZIhcNjdRhbQibQleRmfTskVzr\x_}dimmmkihihhfdddc{^z\xsWrnTidMc^GaU@i\DhbFefIeeIjmKiqKadB_a?c_@_W=F>=IA@G?>IA@E=>A99A::E==>77=66@99@99B;;B;;B::G>>H??H???67KABE<>E>>NEELDDNEEI@@NEELDDF>>C<;JAASJJLDDKBALCCKDCULKMFEE?=C=A;9D>97=86?:8=86943=86?:7<75;64<75?:7632766<<:FF>PNBXTE[VF\VF_[Je_MhbNleOqiSskUvpWzuZ|vZ|x\{vZxsWyuYyuZzuZyqVunTtlRynTnkQlkQklOeiM_^G\WBUOa]C_^CilKmySipL]^@a\@c_CUT;VT;[\@VT;YY=SZ=MN6LI3JE2EB/@>-@<,?;+75'43%0/#-+/,3/!53)873AA?B>:D?;C>:E@=B=:FA?IDAA;:D?F@=F@=OHENHFQIGKDBOIGNHFGA?E?>LECUMKNGELECMEDLDBTLJMDDD=77E==@99@99B;;A::=66B::E<IDAD?=F?=E?FA>GA>D>;HC@;63@;9IDAB=:B=:C>;A<:B>;;97B@=GC>-<;*==-<;,86)41&3/#1/#/-%53-656987EA=C>;FA>D?;A<:@;8A<:B=;D>;HB?JDAD>F>=E==?88C<F??H@@MEEQHHMDDH@@OFFF>>QHHJBBF>=C<;KBBE==LCBF?=NGFKDBHA?MFDQJIIB@MFDE@>IC@KEBHB?HB@ICAIC@IC@F@=D>;LFCGB@ICALFDF@=GA?C>=EBOK?QO?TP?VR?YU@[VB[VB\U@_VC_WC]WC^[Ea^G\]FZYCUR>NL:FD5D@2@?/?=-==-==-??/EF3IG4KI4NN7TS;RR;KK6GG4II5JI5GG3EC/D@/FD3BA2?<0A<295.971@=8?>=B?<@<9HB?HB?@;9D?GB>FA?GB>GB?F@=E?=KDBJDAD>=KCCE=>JAAC;;F>>H@@F>>G??I@@I@@JABH??F==OEFKBCLCDPFGH>?I@@NDEOEFC:;I@@H??H??G??G??JBCKCCKCCC<NFFG?>G?>E>=IBAOGEIB@MFDKDBE?>LECKECGA?KECKEBKDBMFDC=;D>IB@FA>OIFMGCPJGMGDGB?ICAJDBB=:D?;HB@@;9EB?GB>C>:C?9FDUU@UU@TU@RS?LL:IG7@@2:7)64'43%54&53&85(<9+A@1LI8NP=NN;OL9KH6II6HH6IG6DC5BA7A?9@=:CA>D@GB?HC@FA>KECMGDFA>E@=HC@HC@FA=HB?IDAGB>GA>KEBJDAKDBLEBKECPIGRKIQKIIC@JCAKDBSKJKDBLECLECTMLTMKVMLH@@OGGG?>G?>D=?G=>H??G>>A9:LCDI@@H??E<=E==H@AG@@QGGB;;F>>I@@I@@JAAMDDF>>F>>B;;KCCG?>LCCH@?G?>G?>IAAOGEKDBMFDKDBF@?C=GB>@<:FA>HB?GB?E@;FB?HD@B>;KFCMJDEC=FDGB?JEAFA=GB>JEBIEAJEAE@IDAFA>HC@MGDLFCKEBGB?GB?JEAHB?F@>IC@IC@F@>QJHMGDMFDJCAKECPIGNHEYQNHB@LECOGFNGENGEQJHJCAIBAD>=NEDH@@LDDH@?G?>F>=H@?LDDIAAJAAG??B<>H??KBCKABF==F=>J@AH?@LCCF=>H?@LCCF=>JAAG??B::KCCQGGQHHIAAHAAC<=H@?JCBKCBF?>F??IBAIB@G@@NGELFENHFOHFGA?GA?MGEMGERKHNHFNHFLFDMGEMGDLGEJECKEBKEDNHEJDBKEBLGCLGDNHFKFCC>;C>;B=:HC@GB@IDAB=:B>=HCAJEBD@=EA>JEBHCAD@=KEBEA=A=9EA>HCAEA>D@=HD@FB?KFBJEBJFCGB?KFDEC?FC@KGDKGDIEBMGDHDAHDAJFCHDAEA?HCAHCAGB?GB@EA>KECLFCGB?GB?IDAGB?HC@LGCHC@MGEKFCHC@GB@HBAHCAJDBMHELGENHESLJMGEQJHMGEHB@SLIYPNYQOPIGNHGHBAOHFTLJNGEPIGLDCQHGF??IA@KCBJCBE>=D>>G@@F??C==JBBHAAIBBJAAA::A::F??G@@LCCH@@H?@F=>H?@H?@I@AH?@H?@PDFNCEC;OGGOFFJBBIAANFEMEDF?=NGEKEDMGEMGELFEGA?LFDICBNHFPJHPJGOIFOIGOIFNIFIDBPIFGB@MHFNGEQJHPJGKFCNIEQKHRKHNIFE@=E@=HC@JEBHC@IDAJDBLGCLGCEA>NIEPJGKFBMHDKFCD@=C?>C;MCDKBBH?@JAAOEFH?@IAAIAALCCQGGWLMLCCMDDHAANEEHAALCBMEEKCCLDCIAAJCBJBAKCCF??C;;KCBG??MFDKDBMGEKECHB@HBBKECICBOIGQJHPJHNHFRKIQKHTMKMGDRKJHB@KEDQKHPJGPJGTMKOIFQKHNIEPJGLFDIDAKEDPKHLGDPKGPKGPJGSMIPKGPKHQKHOIFPKFQKHQKHFA>B=:HC@E@>F@=NIENIDPKFOJFOJGICAIDBLGEKFCPKGMHENIERMIKFCE@=IDAIDBLGDLGDLGDRMINIFOJGLGDNIFMGEMHEOIFSMIRMINHGQKHQJHPJGJC@QKIZSP\TQOHFVOMTMKQKHRKIXPMPJHPJHPJHSLJXPN^UTRKIRJINGESKIMEDOGFOGGMEDNFEJBBKCBIBAJBBD>>A::HAAC<>B;;B;JAAI@ALCCE<=J@AH>?MBDMBDG=>MDEI@@JABI@@OFGJAAKBCI@@I@@MEFUJKLCCNFGIAAMDDMDDLCCQHHRIIOGGQIIRIIJBAOGGNFFIA@JBAMEDJBAIB@HA?LECMFDLECLECLECLECTMKUMLPIFTLIUNLTMKUMJTMKMFDJC@SLIYROSLIRKHICARLHOIEIDAHC@JDBMHDQKGOIFPKGSMJVPNQKHSMIRLHOJFNHEPJGTNLUOLF@>E@TMINIEKECOIFQLHRLHVOLSMIUNKTMKUNK[TQQJGNGDVOLXQOQIGWPNRKHTMKQJHYQPRKISKJPIGOHFUNL\SRRKITLKNGERIHQHHPGFTKJTKKQIIRJJRIIJBBNFFMDDG??H@@JA@F>>D==C<>G??G>>F==F==F==LCDLCDH??JABLBCKABK@BJ@AG=>K@BI?@H>?MBDJAAPFGJABLCDNEFOFGLCDOFGJAAQHHOFFLBCG??H@@MDDH?>LCCTKKSJJH@?LDDE>=KCCSJJULLPHHOFEIA@MEEJCBJCAICAOHFOHFOHFLECOHFVONVPNTKIVOMWOL]USYRPYRPGA?QJHZSP\URYROOIGQKHOHEPJGSMISMIUNKPJFPJFNHELFDVPMQLHTMJUOLVPLQLHPJGSMJVPLPKGJEAIDALGCPJGHC@PJGPJFVPLVPMUOKLGCRMITNKTNKXRNSNJTOK\VRQKGJEBNHFQKHSNJPJGNIFGA?LFCVOMMGDQLHWPMNGDRKIUNKUNKWPMTMJOIGUNLOHFXPMUMKRKHVNLSLJZRPTKIUMLVONXPOTLKWONPIGXPOVNLQIHLCBLDDQHHJBBNEEVMMULLIA@MDDE==KBBQHHSJJNFFLBBD==IAAF>>D<LACMBDI?@K@BF<=I@@LBCH??LCDOFGG>>I@@I@@MDEOFFKABIAAD==KBBKBBE==H@@NEEI@?IAAF??IA@MEDPHHQIJPGFIA@RIHRIHOHFG@>NFDQIHQIHPIGPIGSKIUNMYQPVOM[TR]US_WT^VTTMJLFCKECRKISLJNGDOIGLEBSLI]VSXQNVOLPIFSMJTMIKEBXRNOIGYRNWQMZTQ\URVOLWPNXRN\VSSMJHC@ID@PJGMHDLGCMHDRMIUOKUOJTMIXRNVPLZSPUPLYSONIEOIEXQMQKH[UQXQNXQMUNKXRNZSPKECYROVOLMFCUNKUMJTMJYQNWPMZSPWPMOIGQJGTMKWOLQJHQIGQJHPHFRKHUMKPIFUMLXPOMFDOHFOHFSLKVMLPGGNFEIA@OFEOFFH@?JBAOGGIA@IA@F??I@?LCBNFFOGHMCCD==MDDMDDJAAA99H??JABJABI@@I@@JABMDEPFGMCEQFHRGITHJF<>D;=H>?H>?I?@NCEKABNDEI@@I@@I@@JABJABI@@I@@TJJMDDMDDKBBLCCPFFSJJE>>H@@I@?SIIH@?IA@F>=JBANEENFEMEDPGFNFESJILDCJCBOHFTMKOHFNGDSKIUMLVNLUMLYQOaXVaYV[SPZROKEBTLJOIGSLJTMKSLJPIFLECZROYROZSPZROQJGXQNUNJWPLMHEXQMUNJWPM^WTXRNVOLYRNZSPRMIPKGLFDMHEPKGZSOZSO`XU\URZSN]VS_WU^VS_XTZTP\URMGEICATNK[TP\UQWPMWPMTMJ[UQ^WT[TQZSP[TQTMJQJGUMJWPMVOMSLJVOL^VSUNKWOM]URWOLVNKTMKRKIWNMTLKWONQJGQJHPIGRJHRIHOHFOGF[RQSJIRIHPGFPGGSJJWNMG@?IAAIA@SJJH@@I@?D==H@@LCCKBBIAAKBBIAAMDEG>>D<>JABMCDMCDLACODFVJLUIKNCEK@BI?@I?@J@AMBDH>?H??H??I@@KBCC:;H??I@@I@@NEFRHHKBBG??OFFRGHTJJLCCE>>KBBKCCJA@LDDJBBPGGMEDPGGMEDPGFJBBSJISJIPHGMFDRIHUMLPIGZQPUML[RP[RPWNMZQPaXVXPO_WTRJHZROXPMRKH]UR]VS]VS`XU[SPTMJWPM`XUVOLTMJYROSLIUNKJDBKECSLIXQMUOKTNJ\UQSMIPJGMGEMGEZSOOIFLFD^WS^WS`XUZSOWQM`YU`XUd\YbZWUOLPJFZSO^VSe]Z]VS]UR\TQ\TQZSP[SP]UR^VSXQNSLIOHFSLJPIGTMKVNLNGEVNLZRO[SPaYVYPNSLJQIGULKUMLQIGPIGPIFQJHSKJJCBOGEOGFOGFULKXOMPGFKCBSJJULKWNMNEEG??LCCLCBIAALCCIAANEEKCCMCCIAAKBBG>>MDELCDJAAG>>JABMDEI@@QGHMCDQFHPEGMBDODFUIKH>@MBDC:?J@AMBDJ@AKABKABLCDNEFNEFLCDF==I@@QGGOFGD==IAAI@@JBBTJJNEERIIE==E>>G??JBBLDCIA@OFFMEDLDDIAAG??JBAOGFOGFNFDWNMSJIZQPZQPXPO^UT]TRTLJaXWYQP[SQOHFOHFYQNNHFZRO^VSd[XTLJUMJTMJPIG`XUe\YZSPWOLRKHYROXQNPIFVOL\TQSLIWPMYQNVOL\TQ\UR^WSaZW]VR[TQ]VS]VSaYVc[XTNJ[TQ^WS`XUbZW^WTYQN\URaZWia^`YV[SPUNK`XURKHYROZSP`YV^WTXQOZROXPNUMKWOMVNLTLJWOMUNKWNMXOMYPOMFDPHFQJHSLJVNMRKISKJSKIUMKWNMVNLTKJLCBNFFWNMTKKIA@MEDLDCLDCVMMPGGSJJE>>E==F>>IAAJBBG??LBBIAAI@@E==C::D;>NEFKABQGHPEGODFTHJSGIJ@AVJLB9;I?AJ@BI?AG=>J@AI?@I?@H>?JAALBCLCDKBCH??I@@F==OFGOFGKBBMDDD==LCCJBBPGGRIINEEQHII@?G??LCBKCBJBBLDCJBAG?>G??C<>IAAIAAH??I@@G>>C;;C::>67F==D;>I@@I@@G=>MBDPEGLACNDFK@BMBDE<>F=?KACF=?H?AH?@E<=E<=J@ALBCH?@H?@H?@KBBOEFLCDPFFLCCKBBJBBKBBIBBD==QGGSIINFFPGHIAAF??F@@PGGPHGMEEPGGQIHG??IBAKCCH@@QHGPHGQIIKDDQJHSKISLJUNLVOLTMK`WVWOMZRQVNLUNLYROdZXOIGSMKLECWPNQJHXQORLJQJHVOMYRP[TR\TQZSQd[X[TRQJHSLJc[XUNKTMJcZWbZW^WT]VS`XUe\Zc[X_XU`XU^VSUNK]VSTMJ]VScZW|qmmda\USbZW`XUXQOSLIZSQZSQcZWYRPQJH_WUd[XVOMZRO[SPWQOUNLYQOSLJOHF[RQ^USQJHQJHVOLPIGRKIRKINGFNGESJIULKPHHPHGOGGRIHWMLSJJVLKPHGNFFNFEOFELDDF>>SIISJJOFEPGGH@@D=>D=>MEEMDDIAALCCMDDC::C;?G=>G=>F<=G=>H??LBCI@AH??I@AKBCH?@MDEI@@JABOEEVKLMDDD==D==JBBPGHWMMTJJE>>NEFMDCLDCH@@QHHMEDKCBHA@IAARIHPHGMEDOFEKCCUMKLECRJHTKJTLKXPO\SQVMLTLJZQP[RQ`WUTLJNHGTLJPJHLFDVNLXPNZRPUMJYQOYQN]USTMK`XVf]Z`WTSLJXQO]URYQN`WT^VSd\Y^VSZRO\TQcZW^VS[SPd[X\TQ]URTNLSLJF@>mcavlioecf]ZXPMTMKSMK[SP^VT`XVYQOYQN[SQ\TRZROXPNZQPZQPPIGTLJWOMOHFUNKZQPQIGSKIULKWNMVNLRJHPHFPGFNFEOFEPGFTKIQHHNFEPGGRIIMEDRIILDDNEERIIYOOOFFF>>E>>KBBPGGVLLRHHC<=LCCI@@I@@D;C:;LACB:@J?AJ?AB9;C:I?AMBDH>@E;56B9:F==F==J?AF<=J?AC:;J?ALACLACLACH>@C:I?AJ@BI?AF<=H>?I?AJ@BLBDMDEJABJABF==I@AH??JABKBCLCDJAAPGGTIILCDOGHI@@UKKPHINEEKBASJJNEEOFGG??SJJNFFNEEIAAPGGNEEPGGMDCMDCPGFULLSJIQHGSKIQIGZQPWONUMKYQPOHFVOMVNL`WV_VUYQQ`WVQJHOHFXPNYPNVNKWOMTLJOHEOHFLECYQNSKI\TQYQNYQNYQN_WTf][f^[f^[bZW[SPe][\TQbZW]URWPNZRO]UR_WU_WU\TQVNLPHF[SP^VSZROZROVNLOHFNGDRKIRKIMFDNFEZQPYQQPIGVNL\TSLECSLJUNMLECTLJUMLMFEPHFSJITKKSJIOFEQHGQIIRIITKKTLLQHHPHHKCBOFELCCNEFOFFPGGLCBSIIUKKMDEPGHH@@TJJOFGLCDI@@PFFJABKBCC:;NEFI@@H??C:;I?AG=>H>?E;@A9;B:@B:@K@BLACKABMCDD;>I@@G>>MDEJ@@F=>F>>MCCSIINEEH@?LBCPGGRHHKBAOFFF??PGGG@@KCBQHHLDCMECNEEE>=IAAPGGRIHNFDMEEOGFTKJZPOYPO[QPULKSKIWNMUMKSLJMFD_VS`WUZQP]TRTMJRKIRKI_VU\SRZQO^UT`WUNHFQJHYQNOGE\SQYQNPIGYQNbYWh_\]URbZWd[Y`XU_VT^VSZRO[SPZROZROTNLZRO`WU]TRQJHLFD\SQ[RQTMKUNLZQPSLJ\SRQJHUNKTMJHB@QJHTMJPIGNHGWNMQJHSKISKIQIGJCBPHGSJIH@@LDDULKVMLPGGKCCTKJQHHSJISJJRIISJJJBBMDCMDDKCBQHIMDDH@@H@@NEETJJOEEG??KABOEEPFFI@@LBBC;>67A9:H>?I>@E<=D;=F=>J?AOCEH>@E;=K@BF<>G=?MBDOCELACB9;E;E;I?@G>>LBCH??KBCMDEJ@@B99H??F==I@@KBBJAALBCKBBB::B;;MDDF>>I@?C;;KBAPGGSJJSJJLDCIA@IAAH@@LCCOFESIHQHFQHGSKIVMLRJHWNMPHFULK[RQbXWYPONGEOHFVMK_VTe\ZbYWNGE\SQXOMWOMPHG_VT[RPSLJQIHTLJ_VU^USTLJWNLRJHcZXQHFYQN_VScZX[SPbYW\SQ]URMGEMGE[SQRJI[RPYQO[RPLECNGEXPN[RPMFDQJHULJTKJe\[bYVlb_PIGKDB[QPSKIQIGWNMPHFLDBIA@RIHLDCPGFJBAIAAKCCVMLYONVMLJBBMDDOFELCCKCBNEDOFFMDCQHILCCPGGQHINDDC<>JAALBBJAAKABJAAA89A88J@AC:;E<I>@G=?G=?I>@G=?A8:H>AH>AB9;H>@G=?G=?E;=F<>H>@B9:G=>G=>B9:H?@I?AA89G>>E<>I@@JAAD<>MDEKBBOGHSIIB::?89F>>E=>RIIJAAKBAG??MDDVMMNEEIAAIAAOFFNFEQHHSJJRIIRIIPGEOFDPGFTKJULKRJHZQQ\SR_UT[RQSKIYQQVNL_VUbXUaXWaXVYQP`WVSKI[RP]TSMECQIHYPNXON\SRZQO[RPNGE[RPVNLUMKVNLbYX]TRWNLGA?XOMRJHE?>YPNZQO^UTXOM\SROGEPHFWNMPIGPIGQJHYPNWNLYPOi_]]UTh^]RJHTLJVNLPHFTLJUMKXONNEDOGEKBAMEDJBAPGFKCCRIIPGGPGGMDDNEEPGGIAANEENEDH@@NEFNEEE==KBBI??JAAKBBLCCE==H??MDEKBCOFGRGGA89>56C:;B9:MDEF==F<ODFG=>B9:B9;G=?F<>H>@I?AH>AH>AE;=G<>D:@LACI>@F<>H=?E;=D:;D:;E;F<>>67KBCB9:KBCNEFPFFD;;I@@NDD^RSPGGOEENDDMBCC;;I@@F>>D<@J?AI>@D:H=?J?AJ?AH=?I>@H=@G<>MBDJ@CH=?J?AJ?AJ@BI>@E;=KACJ?AH=?H=?I>@H=?E:;J@AA89PGHKBC>55KBCI@AH??B99PFF[OPNFGNDDQGHKBB@88A9:JAAD<>F>>QHHSJJPGGI@@QGGQHHTJJTKKSJJULLOFEQHHPGFPGEWNMVLKQHFPGFXON_VUYPORJHXNM[RR_UTVNL\RQSKI]SRPIGVMK^TRVMLXOM[RPLFDPHFWNLXOMRJHNGDWNLXOM[RPZQO_VTRJHOGFbYXTLKTLKWNLWNLaWV_USYPNYPNf\ZXOMWNLRJHULJQIGdZYqedSKIUMK\SRQIGLCBTKJXNMKCBSJIPGELDDRIHXOO]SRPGFPGFTKKTJJSJJRHHMDDSJKQHHOFFNEEOFFNDEJ@@ODEE==VKLOFF?88NDDKABI@@B::OFGZNOMDEKBCNEFH??=55>56F<=@67I>@@78@78J?AKACH=?A8:H=?H=?J?AJ?AI>@J?AC9;D:@J?AG=?E<=K@BG=?G=?F==E<?JBBD==JBAZNPD<=IAAC;;G>>C;PFGUIKE<=I>@LACD:;J?AB9:E<=K@BMACK@B@8:B9;C:<@8:@8:D;=E<=D9;A79GANBDJ@BE<>D;=E<>G=?J@AH>@H=@E;?MDELCCLDDLCBLCCOFEI@@MDDNFEIAAQHHPHHKBBPGGNEDOFFQIISJJPGFQHFXONVML[RP_UTKBAH@@PGFOFE\SRTKITLJOFEWNMdYXXONRJHOFEPHFQHGWNLWNLQIGRJHQIGNEDZQP[RPTKJYONf[ZWNLaVUXPNUKJYPOWMLOFE[RRXOO_TSQHGSKIVNLWNMcXW_UTma`MDCULKULLTKKTKKQIIXONWNNXNNNEDULLSJJMDCLCCWMLXNNQHIWMMSJIMEELCCLDDNEEQHHNEFMDDI@@B:;<55KBCNEEPEETIID;;I@@JABH?@E<56H>@F<>@79F<>D;=D;=D:@79D:J?AJ?AB9;F<>D;L@BJ?A=45?78G=>D;>LCDKABF==A89PEERGHNDDQFFOEFKBBH??NDEODEJAAODERHHOEELDBOFEKBBLCBLCBLCCQGGPHFMEDPGFE==TJIKCCUKJYON[PPLDESJIXNMk`_[QPZPOYOOWNLMEETKIPHHMEESJITLJ\QP_UT^SRUMKUMKSJIVNLULKVNLUMK\RQ\SQWNLPGFUMKIA@OGEOGEUMKcXWRIHVNL_TSXPN^TS[PPTKITKIZPO[QPXNM`UTaWVf[[_TS\QQRJHRIHVLLPGGKCCVLKRIHJBBIAAMDDC<C9:H=?H=?C:J?AG<>D;B9;B9;C9;C9;G<>F;>H=@H=@C8:D9;@68NBDLACI?BLACK@BG=?D:<=46I?AG=?E:;H>@E;>PEFH??:34A89D:;KACMBDF<>E;E:;MACI?AE;=G=?G=@H>AFF;>K@BG<>J?AD:68F:LACLACMCDG=>MDE?68J@AE;;KABE<F==H??VKLSIIH??QFGODEQFGNCDLBBSHINEENEELCCMDCKCAKBBNEDJBBOEE^TTKCCRHHKCCPGFOFEYONLDDUKJRIH^TSf[ZSJIXNM\RQSJH[QQRIIULJ]SS_UT`UUQHGQIIQIILCAOFFRIHRIHXOMYONZONWNLULJZOOZOO\QQ^TS_UTVMK\QQWMLSJHSJHRIHRIHRIGSJHYOOH??IAAQHGUKJRHGQGGTJIXNMSJJOFESIINEDULLTJJPFFKCALCCLCBODEUJKPFFSIILBBJAAKBB@99H@?D<=K@AH??F>=OEEJ@ANDENDENEFH>?NDE?67I?@C::I>@C99G<>F;=C::A8:C9:OCFLACA89I>@G<>H=?E:AE:=E:=D9;D9;E:=E:=J>A?57B79D:@E;>=46B9;A79E:57G>>B99H??F==D;;JABQEFI@@ZNPWKLNEEUJJRHGLCCLCCMDDOFFSJIQHIOFGMDCH??C<F===45PEFPFGNCENCD?66?67@78>56<34C:;>56C:57D:@B9;REHNBDF@D:I>@>57C8:I>AC8:@68@78C8:F;>A89A89?68B8:A89?68D9;C9;F:67=44?68F==F=>H??F==E<>OEENDDXNNSJJRHHTJJQGGWMMUKJNDDJAAZPO\RQXNM[QPZPPUKKQHGXNNYONTKIXNN\RRZPOULJXNMTKIOFFNEENEEWMKYONTKIYNNJAALCCPGGOFFULJXMMSJHWMLNFFYONUKKVLKUKKTIHPGFOFELDDRHHRGGYOOYOONEDOFERHHULMQGGMECNDDH@@PFFOEDNDDODEI@@IA@KAAOEEJA@I@@G>>I@@H??F==J@@I@@K@AG==J@AD;;F===45:23LBDI?@NCEI>@C99=56;13=45C9:C9;D:AB8:>46E:=G46H=?B8:D9B9;C9F<>F<>B9;G56A78D:;<34>46>56<45>56E<=C::E<=E<>D;;UJJSGHPFFSHHSGHOEFKA@D;;RHHPEFNEERGHMDDNEENEEUKKSJJSJJOFFZONQHHC<45=45;34<45C9;@68B8:A79C:G=?@68A79=46LACJ>@H=?J>@I=?F;>B79<24H=?=46B79C8:C8;G@C8:E:=D9@E;>E:67C9:I>@>56F<>?78E:;<33J@AH?AF=?I@AG>>F=>LCDG>>LCDJABJABRGHMCDRGGKAAJ@@KA@A99KAAI??NCDLBBKBATIJOEFWLMUJKWMMPGGXMMH??TJJNEDTKKOEDTJJSIIQGFOEEQHGbUT^SRQGFZQQXNN[QQVLLUJJ\RRXNNUKJTJIWMLRIITIHYOOUKJVLLYOOSIHWMMXNN_SS]SSaUUZPPQGFTII_SR]QQVLLSIISJJSJJRGGULLJABOEEQHHLBBUJKVKLYMNSHIVKLOEFLBBLBAMCCQGHLBBE==THIKAAMCDKABNDEPEFOEFQEFKBCJ@AF==C:;D::F<57F;>>67C9::02GC9AE:=H=@C8:B79B79902B79>46C8:A78C8:A78B89:02?57@78C8;C8:F;>E;>H=?D9;@78F;=F56F<>E<>IAAJAAI@@E<>H@?K@AJ@@MCDLCDOEFJ@AF==KBCJACI?@E;;D;;C:;923:23>67;12@67;35A8:=57=46<46:24A89?68A78E;>913>57C8:?57@68>46C8:A78F;>C8;:13@68@68D946?57G<>?57;35?57A67A68>56912C9:C8:D9:>56E<<@78A88JABE;>E<>F<=F==F==G=>H>@>57@78B78C89J?@A67<45@67A68A67=46802A8:A67@68:24@79<35;24D:=?57;24<24@57D9<@57@68<24@68?46<24B7:=35>46A78@67>46A79>46?57@67=35A79A79>46A79A79?67@67C9J?B=45C9;E;;@78G=?MBDA89F==A8:LBCH??J@AI??I@AKAAJA@JABNDENCDQFGODEODEMCBPEFE=>I@@KAAD::E==F<JAAF==G>>H>>D;;H?@H??D;;G>?G>>F<67A79=45=56D:<=46C9;?68902A89D9913?68@78:24B7:F;>;24?67;24E:=A78B7:A78A79B7:A78A795-/;13=24>35?57?46B7:?46A69>359028/18/1=24@68D9?KABKABNDDODFRGHWKMPEENCDLABH>>I>>MBCVJKF=>LBBRGHG=>QEGH>>MCDB::TIJSHIPFFTIJQGFPEFWLLPFFVKMTIKTIK[OPVKL[OOSIIRFFLBCH??VJKQEFRHHTIKRHHRGHLBBaTUWLNLABTIKI@@PFFZNO]QRI@@MCCTIJG>>QFGYMNVJKVJKTIIUIJJ??I>>WKLYMOD;J@AG==H?@E;;@78>56>56C99F==J?AF;>J?BH=?>56G<>G<>7/0A67@68A68A79@79:248/2802A7:@79?57A7:C8;C8;C8;G46?67:24@67;23H=@D9;E9<34D::G=>J@ALBCQEFODFSHJQEFJ?AQFGRFGMCDJ??K@@K@@A89A89F=>B99J@@D<=MBBF==H??H??F==OCDMCBODDVKLG>>NDCRFGNDCNDCKABQFFPFE[OOSHIG=>ODEODEI??OEFJ?@A89@78B9:H>?C:;G=>G=>G==D::>56<35;23C99B88@68I>@F;>=56D:46>56913>56802D:=@69A69@57C8;@57B7:?46@586-/=34@57B7:D9F:=I=@F:=4,.6-/7.08/17.06-/?56=35902<24;13=35>45A69902=45>56:03=35=46@68C79?67?67>57?57=35@78913A78A79B89B88B89E:;I=@H<>G<>F;C:;F<F=>I??RFGI??B9:H>>I??I??F=>A89LBBLAALBBE<=NCBH??G=>SGHMBBF==H>?MBCUIKODDRGFJAARGFODDH??VJKWKMVJKaST\PQQFEWKMF==RGFRGGMBCUIKTHJODCUIKYMNUIJPEEKAAG>?G>>ODDQEFNCCOCDRFGWKLMBBI??G>?=46LABC:;>56>56E<=A89?67>56G==E<<@78C::B79D9;D::H=?>56C99D::=46@68A79D9:E:56>56>56A68C8;A69A69@57A69;13=35>45@57<24>45=35;13<246-/;23;236-/8/17.05,.<34802=35:13=35@57A69=35;23?46A68E:=B79A79@57C957=45<36?687.0913?68C89D9:?67>57<46B89H=?G<=K@BD9;G<=G<>F<=I??G==E<?E;;G=>LACJ?@H>?C:?A89KAANBCTHIB9:JAALCCH?@QEFVJKG>?ODDH>?UIKODDTIIQFFPEEPEERFGTHH]QRUIK^PQSHHVJL\OQQFFLCCKABA99RFGH@AC::C::RGGODDOCDTHJF>?JAALBBVJKSGHKABLAARFGWILB9:G==@78I?@LBCE<@E:;E:;B79E:=A79?68=46<35>576-08/2=45@57A68<34;14802=35B7:A68E9<=35@57@57?46A68?46<34<34>463+-6-/6-/;138/18/17.0;13:02<24=34?47=34@58B7:B7:?47=35C8;A69A69=24C957@67>46:13>57?57@68@68C9;@67F:=K?AI=@MACH<>H=@E:;B79@68>56@78I?ALBDH>>QEFK@BB9:LACMCD<35F<=G=>I?@J@@KA@B9:A89C:;MCCMBBJ?@NDDRGHQEGSGIYLNUIKG==[OPPEFPEEVJLVJLVJLdVWj[\\NOVJL\NORFHQFFXKM]PQF<?KABPDFMBDZMOJ@AI??B9:J?AG==I>A?67D:;@78@68?57C8:B78C9:D::F:=C99F;=H=?HD9;D9;>46E:=C8:G;=<247/1=46>56=258/1<24<24=35=35>46;13@58D8;B7:E9<@58A69=34:028/16-/8/1@583*,6-/7.0=359/15,.9/1=35:029/17.0>357.07.0<24@57<24;038/13+,?46<13>46=35=46B79=36>57B79@68A68=46@68>46@68?46C89A79B8:G;>J>@C8:H<>F:?C::?67C:;G=>B9:H=>D;?PEFTGHD;<@78KABMBCODFLABRFGXKM\NOLABRFHKAALBCK@BNBD@68G<=B78=35A68E;46;245-/B79=35?57=46>57B8:=35>46A68?57?46;13=35;13=35:02>35<24<24@58C7:<24@57>35?46@58:027.07.04*-5+.7.0:02<34;139/19/19/1:027.07.05,.6-/4+-B69;13@58:026-/@58?46<14>568/1=45>578/2913=35@69C8:D9;=35?68A89@78C8:;24=35D9;C::C::C99B79F;?H>>LACG=>G=>F<=F<=G==H??@78JAALABLBCJAAJ?AMCDTGHPDFOCENDDTHHG=>F<=LACJ?AJ?AMCCMDDB9;C9:RFI`QRaRTXJLTGIYKM_QRcTVPDFXJLQEGSGGRFGXKLJ@AVIJRFFMBCLBCREFKABKABJ@@QDEG=?K@BOCESGI?56G==A79G=>E;@68C8:E;@57D9;=358/2C8:@69=35>678/2>46>568/1902<14?46@58A69:02<34<34;23=356-/7.0=35<34<34;23:02=35B69B697.0;135+.6,/8.06-/6-/;136-/4+-8.06-/9/16-/>462)+@58A58<14=351)*2)+C798.0?57=358/1?47=35<354+.3+-;14@68:13=36C9;B8:A79:13:13<24@57C9;G;>B79D:;MABNBDF;H=>REGPCDK@BLACOCEH>?F<=B99D:;I?@>45@67F<=LBCNCDF<=F<=D;?D9F;=B79A68>46>46C8:=46;13?46<35?57;24D:<6-/F:=E:469/1?46<24<244*,2)+9/1=357.0:/2>46=35<245,.5,.6-/9/1<24?47:02<24D7:D8;<247-05+.8.04*-5,/5-/7.0;137.07.09015-/7.0<135,.=24>35;03;13<243+-?46;137.1@57:12:12;13=35?462*,2*+7.10()6.0<35>56C79B68@68@68D8:C79F:AB88PDFLABNBDE:?G==>56@78G==J?AI??L@AD;LABLACREGSFGNBDG<>QEGL@BNBDF;=?46>67B88A78<24=46=46?57C8:>57>46@68;24=35B68:13B79C8:>47>46?575-/A69<34802A68:12:12:12<24=250(*/()4,.-&'3*,8/0901=24<13:02:02=24<13>35=24;13<13A58A581'*7-/8.07-/3),5+.8.08.05,.8.07-/8.0:01;127-/9/1:019.1;12?478.04,.=25<23<23:02=346-/<34D9<@58A69B79<24<24<25C8;F:=@57=24A78A67B79>35?57@57:24?46G;=L@BH<>B78?465,.G;=B78G<>H<>G;@H==@78F;=H=>J?AD9;K@AK@BKABLAAPDFLACLACJ?ANBDUIKLAAUIKSFHYKMSFHTHJLAAMBBRFHMBCXKLREGTHJLAAC:I>?J?AJ??4+,<35\MPPEGQEGE:;K?AOCERFHJ>@TGIG;46@67A68<24>46?46<24>45B7:;036.0?46<34<34;02>345-/<23C8;?36>36?479/19.18.0>36@58:017-/;12:01;137-/8.08.03*-7-/=251'*4+.7-/<134*-4*-6,/1(+4,.7./4,.8/09/17./6-/7./=24<035-/:02>36901;035+.6.06.0?48>35A69A69>35E9;A68A69=36G;>B79D8;F:56>56?56<24;13;13MADE9:L?A>35:02J>AI>?F;?>46G<=F:<>47?57E::I>>I=?J>?B79G<=G<=H=?K?@I>@I>@H=>OCDOCDH=>@57UGIWJLQEGE;=QDEQDDMABPDEK?AJ?ANBC[LOK@AL@AI>@K@AK?@L@ANCEI>@H=>1*,;14=46TFIVIKH=>H==L@BMACI>?SEHSFIG:45:24>56?46<34;24<34B79?47902>35A69;23=246,/7.17.0?47=24@58@58=13B69>35>35:/2C69=24>36@47<13:026-/;027-/7-/7-/4*-3),3),?364*-2(+8.03*-4*-3*-2),6,.6,.4+-4+-7-/8/09018/08.0<049014,.@47C69>474+.<248.0<23;13?47H:>D8;F:AH=>H=?2*+6-.L?AC79J?@F;G<=A68>46K?BPCEG;=I>?L@CRDFPCEH=>K@AI=>F;?I>?OBDOBDOBDMABQEFOBDSEGUGIREGUGI\LO[KNK@AI=>L@BF;@C8:F:E956=45=25?47<347.1C79D8;@585,/=359.0<23:12>36G9=C69C7:C7:;13=15<25;03=35?36<14=354+-:029/13*-7-/7-/;031'*0'*2(+3*-6,.3),9/11(+5+.3*-8.08.06-.6-.8.06-.3+-5,.8./:028/0<24>255,.2(*3+-8/06-/;038.16.0>35?57A69@57>36@58A68C7:<34D9;F:=B79?469039/2:24:24;25;25K=@L@BC8:G;>J>@7.0A78>57=24H<>A68I=?G;=I=?OBE<35<35G;==35F;L@BNBDH=>OBDPDGI=?K?ATFHK?ALABNBDJ>@QDFNBDPDFTFHLABMBCLABPDGH==J>@J>@L@BJ?@H<>MADSGIQCFJ=?@79<13@68K>ASEHSEHNADF:@G<>G;=D9;I=?C8:B78<25;35?56;14A688/2<25:14?46>46<24<24>36;238/2:02;23>35;23?57?486.03)+4+-9/05-/:027-05,.<13<24>36<24:/2;13;13=257./>36?47;138.03),2(+3*-3*-3*-3*--$'0&)1'*3),/%(2(+1'*;033),6,.7-/7-/2(+5+-6,.3*,6,.8./6,.;03:02<03:029017-/:123*,6,.:026-/<23;137-0>35>36@47B79E8;<13=25=45>35>35>568.0:03@68?468.09/2A78@46A68J35>35F:@H<>K?BE8:?45NADPCEL?BOBDJ>@MADI>?I>?A57J>?I=>I>>J?@H;=OBFRDFTFIUHJNACI=>K?AL?AM@CJ>@NBDH=>K>@A69H<=YJMXJM[KMJ>BI<>>36=24C79H;=?46@57C89E9;G:=G;>A68E8;A789/29/2;146,/9/28.1C7:903=24=45=458.0;02<138.1;02<23:/1>36=25=25;23:128-/;123*,5,.9.15+-9018/04+-:02;/3;03<24?366,.7-/7-/7-/7-/7-/1'*3),8.07,/0&)4*-6,.2(+7,/2),2),7-/7-/;038.05+-=25?36:029/18.0:02=157./8.00(*7./:/2:024+-=247-/5,.5+.5-/5-/:02>35A6:=24<13>35C7:@58>36@57<34<34>369.09/2913?46B799/2L?BG:=>35I47B78>57F:E:;ZKMPCEH<>K?AF;M@BSEHXILZJLK>@L?AM@BOBEL?AB8:I<>TGIM@CL?AF;PCFOBDH;=M@CG;=K>ANBDG;=F:C8:A68?57:03@57:14:13?46?46C79?47;23D8;F9;@58?46>35?47@59;12;133*,:01;13;135+-=246-/4,.4*,4+-3+-7./:02>369.17-/8.0=25:028.09/16,.6,.7-/1'*2(+2),7,/9.16+.6,.2(+4),9.10'*5*-.%(1(+6,.6,.6,.:/2:/26,.4*,5+-6+-/'(3*,2*,<03<15;032*,8/09.07,.5+.9/15,.6,.@57=244,.>25>35?47D8;>367.06,/;02<14=45:/28.16,.B69903D9AG<>4,.<25B68E9;C8:C8:E:;F:@C79?47@57=46RDGK>@SEHWHKF;AI=>PBESEHYILOBDM@BPBENBDF9;G<=SFISEHH==K>AM@BJ=@N@CK>@J=@E8;J@57M?BA68L>AE8;@46?57;03<14B688.1=245+-8/1<34=24=24@47@47<239.1:/1:/12)*6,/5,.>25>36<143*,9/08.06,.4*,8-/3*,3*,<249/11(*9.18.0:/2>258.01(+0&)4*,5*-6,.2(+0'*.%(9.1.%)4*-/&*1(+.%(,#&*"%*"%+#&1'*3),,#&5+-;147.03),1'*/&)0(*2*,/')/')6,-<148/13+-7./6-.6,/6./3*,5+-=24=248/08/06-/<14<14=25:022)+6,/6,/6-/8/28/24*-6,/6-/9037.12*+=34I;>B794,.1**2**@57?56<14<25<14D8:C79A68D79D7:;14G;=K=AB79RDGRDGL>BOADH;=M?B@46<14@69PBEPBFK>@H;=H;=E9:B79H;=K=@G:BD8:F9;E9;E9:E8:N@CC69L>AD79C79C79G:>TEHB68@57F9<:03@58@576-0=247.19036,/3*,1(*0()1)*7-09/22(+:12A58=247.16,.3*-3*-5,/2)+1(+6./=259/23+-6./6-.5+.6,-1(*2)+9029025*,4*,1(+6-/6-/7.04*,,#&0&)/&)0&)1(+1(+,#&.%),#&-#&,#&.$'-#&3(++"%.%(.%(.%(.$'-#&,#%+"$/&)3)+.%(-#&/&)5+-4*,/')/')7-/8.08.06+-9.18/0<038./2)+7,/8,/=26>158-0=14;12@57>36;12=247-/3)+4*,3*+6,/5*-4+,>35<140()>45@57L=A?566,./')7-0D8;?36@46903;24:03<25G;>PADG:>;14D9:<25B68PADI@QBED9:JARCGF:A58B89A57A68E8<@46@57D8;F;=TEGJC7:A69?46C9;G;>5+-6+-4+,6+.5*-;022(*5,.5+.4+.4*,3)+1(*0'(4+.8-02*,1'*2),8.07,.1)+1(+8/09.19.05+-8.07-/:.25,-/&)4*,4*,9.28-03)+7,/5+-9/18-04*,6+.0&),#&-#&,#&.%)-#&/&*1(+.%(.%(,#'1(+,#&,"%-$'-$'-$'0'*-$'+"%,"%-$'-$'4)+2(+3)+4*,2(+-&(&!-%(<038-/7,/;039/17,.6,-1(*/')9.0>268-03),4),:/2<247,/5+.;03=356+.9/08.02(+3(+9.1;02:/28.11(+O@DP@DG9<3),6,/:03<24<149.1;13<257-0<25C7:K<@H:=H:=:/26,/<14F:<;02<03@68;03F9;A67E8:E8:B7:?57A67D7:<249/2D7:@56I:>L>A8.1<25K=@B79F8<<259.1=35A58@57<14F935<25B69?587.0;017,/7,.3),9/02)+2(+4),2),2)+6,.3(+/')0')1(+0(+8-/5+-6,.7,.4+,/'*' "-&(<047-/6,.:/28-04*,3)+.%(-$'5*,9.13)+.%(.%(4),6+.0'*.&)4),6+..%(1(+0'*+"&/%)1(++!%0&*.%)3),+"&&!&!)!$+"%.%(1(*0'),#&-$')!$3)+0'*-$'/&)2)+4*,,"%-#&.&(/')0')>256,.5+-1)+3*-0(+6,.5+-9-00')0(+2*,:.1:/24+.9.07,/9/01(*2(+3*-0'*3)+4+.7-/=259.1=24E946?46D69C58?57G9=7,/7,0F:B:/2<25D79G;=B68@57=36<25?57E8;D6:D7;?46>46L=AD7:G946:03;23=35<34@36>35<34=36:/2=25=25:/16-/:021(+8-05,.;031)++$$+$$/&(0(*3+-7-.6,.0(*1)+-$'7-.3*-0')1)+5+-5,.-$&-$&.&(/')/&)<145+-2)+/&)0'*.%(2(*0')3),+"%,#&-$'3),4*-.%(1(+0&)1(++!$+!%-#',#'/%(*!%,#'5+/2(,/%(0%(*!$-$'-$'-$',$'0%(+#&1&)-$'4*.2),2),1(*.%(1&(2)+,#&/%(/&(*#%8.0;/26,/4+,5,./&(/&)*#$;036,.-%'7-/7,/7-/1),1'*3*,6+.-%'/&(1'*0&(3)+4+.2(+9.16,/6,/7,/4*-6,/;13?47<24:/1<24=35=13=356,/>35?47A59@47?479/2?46@58C8;@47D825@57>249/3@48TDHPAEJ;?K35:/36+.7,/0&(3),2),2)+1)+5*-0')5+.1(*8-06,/5,/4+,0')1'*3*,,#&/%(/%(*"$7-/9-13*-1(*2)+,$'+#&'"6,/1'))!$1(*1')1'),$(+"%-$'/%(("* #*!%* $* $'"&!% /&)+"&'#+"%.%(+"%'") #/&(-$'.%'1&)3)+/&(0&)0&),#&0&(4*-0&)-$',#&.%'%"9-04*,2)+6,/2),2)*,$'2)*6,/,$&2)+3*+/&)3),1(+1'*6,.7-/4+-:.12(*6,.3*-1'*3(+4*-8.07-/7-/5,/4*-3*-9/3<148.08.06,/;143),9/1>35A68@486,/:/1<145+.;13B79<13>35=24=258.1B686,/?46>36<246,/5*-<14A57;136,/=24M>B:02@47?476-0B58B48C7:>35C69;149/19/2:037-/;024+.8.19/1>151'*1')-%'+%%*"$6,.1(*,$&1'*4*,1')+#&-%(4+,1(+2)*5+-6,/1(*2),2)+.%(1')5,.1&)-$',#&-$'%!7,/1(*0&)3)-0&)/%') #.%'1'*( #-$'.%(*!%-$'+#'+"&/&)0&*-$(1'+(#,#'*!$) $(#) $(#(#) $( $-$'+"&+"&.%')!$( ##!)!$-$'/&(-$'/%'+!$/&(+#&,$'1')# 0')/&)1')/&)+"$$ +"%.&(-%'2(*7+/8.07,/3)+3*+.$'/&)8.28,00'*5+-/&)0'*/&)/&)0&)3*-0&).&'2)+4*-4*.4+.4+.7-/5+.1'*5,/4*.3)-8/19/2<144*-:02?36;022(+8.14*-4*-<13=366,/A696,/9/2<13=245+.4),<24=25@478.14*->25<148/1=364*-8.0;02:/2:/2?36@37<159/2=244*-;/37-/1(*8./:.2/%(4*-/')/&)-%'.&(-$'.$'.%(-%'3)+/')/')3*+-%',$&& #+#%/&)1')/&)/&)+"%/&(+#&,$'0')"/&(.%'/&(-$') #"("*!$)!$-$'1&*2(+1&*-$'-$'(#*!$1'+0&)+!%+!%*!%,"&-#'*!%*!%+"%'!-#''!'"+"%,"%+"%*!$+"%'!'!(".&(-#&)!$*"%'!-#&.&(+"%&!!( "+"%4*-2),4*-$!#4)-.%'1&)*"$375+/2(+5+.5+.:029/15*.:03<16901<255+.8-08-0<142)+9.2;038.08-07-05*-7-/5+.9-15+-7,01'*0'*3),4),0&)0&)2'*,#%2)++#%,"%0&)1')0&).%'/&(*!#*!#+"$1(*/&(+"%+#&'!.$&/&(+"%&!!'")!$2(+0&*1'+#"/&)*!$,"%&!5).*!%.%)2'+-$') $) $-$''!deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/dpwadmapconverter_cl.rsp0000644000175000017500000000014311357170241024054 0ustar keeskees .\..\..\plugins\wadmapconverter\src\wadmapconverter.c .\..\..\plugins\wadmapconverter\src\load.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/0000755000175000017500000000000011357170241017645 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/dswinmm.vcproj0000644000175000017500000004557311357170241022566 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/jdoom.vcproj0000644000175000017500000011403211357170241022203 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/dpwadmapconverter.vcproj0000644000175000017500000005214311357170241024624 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/doomsday.vcproj0000644000175000017500000027416711357170241022732 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/runtime/0000755000175000017500000000000011357170241021330 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/runtime/README0000644000175000017500000000047211357170241022213 0ustar keeskeesUse this folder as the debug runtime folder in the IDE. Run packres.py to create the resource PK3s here, then use this kind of command line options: -game jdoom -iwad d:\wads\doom\doom2.wad -nomouse -wnd -file doomsday.pk3 jdoom.pk3 The debug executable (command) can be: ..\bin\debug\Doomsday.exe deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/dsopenal.vcproj0000644000175000017500000005517211357170241022711 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/dpexample.vcproj0000644000175000017500000004750511357170241023064 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/doomsday.sln0000644000175000017500000005017711357170241022214 0ustar keeskeesMicrosoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Doomsday", "doomsday.vcproj", "{65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jDoom", "jdoom.vcproj", "{A36C0FB9-8186-4747-A5D9-D7B659B9F39F}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jHeretic", "jheretic.vcproj", "{7D03FB13-8674-4473-BD32-83C43188B2D2}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jHexen", "jhexen.vcproj", "{060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpDehRead", "dpdehread.vcproj", "{EF5A1023-13BF-475D-B978-7ED12CD9553A}" ProjectSection(ProjectDependencies) = postProject {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} = {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dsDirectSound", "dsdirectsound.vcproj", "{1D7A3D67-B874-4844-BA4E-8DA934AF993C}" ProjectSection(ProjectDependencies) = postProject {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} = {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dsOpenAL", "dsopenal.vcproj", "{0324DC98-86C1-40F5-B3B0-35A057F6173C}" ProjectSection(ProjectDependencies) = postProject {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} = {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jDoom64", "jdoom64.vcproj", "{CA7A0565-5F80-4E69-A3C2-12B81FC35768}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpExample", "dpexample.vcproj", "{DC664B00-A393-4B3C-A847-C192E29D053E}" ProjectSection(ProjectDependencies) = postProject {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} = {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dpWadMapConverter", "dpwadmapconverter.vcproj", "{1687EE67-7C95-4A57-B891-3136065823EC}" ProjectSection(ProjectDependencies) = postProject {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} = {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dsWinMM", "dswinmm.vcproj", "{1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}" ProjectSection(ProjectDependencies) = postProject {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} = {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A} EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug x64|Win32 = Debug x64|Win32 Debug x64|x64 = Debug x64|x64 Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Mesa Release|Win32 = Mesa Release|Win32 Mesa Release|x64 = Mesa Release|x64 Release x64|Win32 = Release x64|Win32 Release x64|x64 = Release x64|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug x64|Win32.Build.0 = Debug x64|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug x64|x64.ActiveCfg = Debug x64|x64 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug x64|x64.Build.0 = Debug x64|x64 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug|Win32.ActiveCfg = Debug|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug|Win32.Build.0 = Debug|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug|x64.ActiveCfg = Debug|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Debug|x64.Build.0 = Debug|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Mesa Release|Win32.ActiveCfg = Release|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Mesa Release|Win32.Build.0 = Release|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Mesa Release|x64.ActiveCfg = Release|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Mesa Release|x64.Build.0 = Release|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release x64|Win32.ActiveCfg = Release x64|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release x64|Win32.Build.0 = Release x64|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release x64|x64.ActiveCfg = Release x64|x64 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release x64|x64.Build.0 = Release x64|x64 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release|Win32.ActiveCfg = Release|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release|Win32.Build.0 = Release|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release|x64.ActiveCfg = Release|Win32 {65AA7CE4-1A37-454A-8D2B-F00C99DCEA9A}.Release|x64.Build.0 = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug x64|Win32.Build.0 = Debug x64|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug x64|x64.ActiveCfg = Debug x64|x64 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug x64|x64.Build.0 = Debug x64|x64 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug|Win32.ActiveCfg = Debug|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug|Win32.Build.0 = Debug|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug|x64.ActiveCfg = Debug|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Debug|x64.Build.0 = Debug|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Mesa Release|Win32.ActiveCfg = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Mesa Release|Win32.Build.0 = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Mesa Release|x64.ActiveCfg = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Mesa Release|x64.Build.0 = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release x64|Win32.ActiveCfg = Release x64|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release x64|Win32.Build.0 = Release x64|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release x64|x64.ActiveCfg = Release x64|x64 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release x64|x64.Build.0 = Release x64|x64 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release|Win32.ActiveCfg = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release|Win32.Build.0 = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release|x64.ActiveCfg = Release|Win32 {A36C0FB9-8186-4747-A5D9-D7B659B9F39F}.Release|x64.Build.0 = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug x64|Win32.Build.0 = Debug x64|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug x64|x64.ActiveCfg = Debug x64|x64 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug x64|x64.Build.0 = Debug x64|x64 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug|Win32.ActiveCfg = Debug|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug|Win32.Build.0 = Debug|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug|x64.ActiveCfg = Debug|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Debug|x64.Build.0 = Debug|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Mesa Release|Win32.ActiveCfg = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Mesa Release|Win32.Build.0 = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Mesa Release|x64.ActiveCfg = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Mesa Release|x64.Build.0 = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release x64|Win32.ActiveCfg = Release x64|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release x64|Win32.Build.0 = Release x64|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release x64|x64.ActiveCfg = Release x64|x64 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release x64|x64.Build.0 = Release x64|x64 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release|Win32.ActiveCfg = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release|Win32.Build.0 = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release|x64.ActiveCfg = Release|Win32 {7D03FB13-8674-4473-BD32-83C43188B2D2}.Release|x64.Build.0 = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug x64|Win32.Build.0 = Debug x64|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug x64|x64.ActiveCfg = Debug x64|x64 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug x64|x64.Build.0 = Debug x64|x64 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug|Win32.ActiveCfg = Debug|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug|Win32.Build.0 = Debug|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug|x64.ActiveCfg = Debug|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Debug|x64.Build.0 = Debug|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Mesa Release|Win32.ActiveCfg = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Mesa Release|Win32.Build.0 = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Mesa Release|x64.ActiveCfg = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Mesa Release|x64.Build.0 = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release x64|Win32.ActiveCfg = Release x64|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release x64|Win32.Build.0 = Release x64|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release x64|x64.ActiveCfg = Release x64|x64 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release x64|x64.Build.0 = Release x64|x64 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release|Win32.ActiveCfg = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release|Win32.Build.0 = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release|x64.ActiveCfg = Release|Win32 {060CA7D4-CEF4-4F36-8950-55A3E5C46C4C}.Release|x64.Build.0 = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug x64|Win32.Build.0 = Debug x64|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug x64|x64.ActiveCfg = Debug x64|x64 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug x64|x64.Build.0 = Debug x64|x64 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug|Win32.ActiveCfg = Debug|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug|Win32.Build.0 = Debug|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug|x64.ActiveCfg = Debug|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Debug|x64.Build.0 = Debug|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Mesa Release|Win32.ActiveCfg = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Mesa Release|Win32.Build.0 = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Mesa Release|x64.ActiveCfg = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Mesa Release|x64.Build.0 = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release x64|Win32.ActiveCfg = Release x64|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release x64|Win32.Build.0 = Release x64|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release x64|x64.ActiveCfg = Release x64|x64 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release x64|x64.Build.0 = Release x64|x64 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release|Win32.ActiveCfg = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release|Win32.Build.0 = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release|x64.ActiveCfg = Release|Win32 {EF5A1023-13BF-475D-B978-7ED12CD9553A}.Release|x64.Build.0 = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug x64|Win32.Build.0 = Debug x64|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug x64|x64.ActiveCfg = Debug x64|x64 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug x64|x64.Build.0 = Debug x64|x64 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug|Win32.ActiveCfg = Debug|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug|Win32.Build.0 = Debug|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug|x64.ActiveCfg = Debug|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Debug|x64.Build.0 = Debug|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Mesa Release|Win32.ActiveCfg = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Mesa Release|Win32.Build.0 = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Mesa Release|x64.ActiveCfg = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Mesa Release|x64.Build.0 = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release x64|Win32.ActiveCfg = Release x64|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release x64|Win32.Build.0 = Release x64|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release x64|x64.ActiveCfg = Release x64|x64 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release x64|x64.Build.0 = Release x64|x64 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release|Win32.ActiveCfg = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release|Win32.Build.0 = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release|x64.ActiveCfg = Release|Win32 {1D7A3D67-B874-4844-BA4E-8DA934AF993C}.Release|x64.Build.0 = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug x64|Win32.Build.0 = Debug x64|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug x64|x64.ActiveCfg = Debug x64|x64 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug x64|x64.Build.0 = Debug x64|x64 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug|Win32.ActiveCfg = Debug|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug|Win32.Build.0 = Debug|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug|x64.ActiveCfg = Debug|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Debug|x64.Build.0 = Debug|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Mesa Release|Win32.ActiveCfg = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Mesa Release|Win32.Build.0 = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Mesa Release|x64.ActiveCfg = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Mesa Release|x64.Build.0 = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release x64|Win32.ActiveCfg = Release x64|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release x64|Win32.Build.0 = Release x64|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release x64|x64.ActiveCfg = Release x64|x64 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release x64|x64.Build.0 = Release x64|x64 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release|Win32.ActiveCfg = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release|Win32.Build.0 = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release|x64.ActiveCfg = Release|Win32 {0324DC98-86C1-40F5-B3B0-35A057F6173C}.Release|x64.Build.0 = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug x64|Win32.Build.0 = Debug x64|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug x64|x64.ActiveCfg = Debug x64|x64 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug x64|x64.Build.0 = Debug x64|x64 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug|Win32.ActiveCfg = Debug|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug|Win32.Build.0 = Debug|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug|x64.ActiveCfg = Debug|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Debug|x64.Build.0 = Debug|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Mesa Release|Win32.ActiveCfg = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Mesa Release|Win32.Build.0 = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Mesa Release|x64.ActiveCfg = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Mesa Release|x64.Build.0 = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release x64|Win32.ActiveCfg = Release x64|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release x64|Win32.Build.0 = Release x64|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release x64|x64.ActiveCfg = Release x64|x64 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release x64|x64.Build.0 = Release x64|x64 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release|Win32.ActiveCfg = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release|Win32.Build.0 = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release|x64.ActiveCfg = Release|Win32 {CA7A0565-5F80-4E69-A3C2-12B81FC35768}.Release|x64.Build.0 = Release|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Debug x64|x64.ActiveCfg = Debug x64|x64 {DC664B00-A393-4B3C-A847-C192E29D053E}.Debug|Win32.ActiveCfg = Debug|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Debug|x64.ActiveCfg = Debug|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Mesa Release|Win32.ActiveCfg = Release|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Mesa Release|Win32.Build.0 = Release|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Mesa Release|x64.ActiveCfg = Release|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Mesa Release|x64.Build.0 = Release|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Release x64|Win32.ActiveCfg = Release x64|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Release x64|x64.ActiveCfg = Release x64|x64 {DC664B00-A393-4B3C-A847-C192E29D053E}.Release|Win32.ActiveCfg = Release|Win32 {DC664B00-A393-4B3C-A847-C192E29D053E}.Release|x64.ActiveCfg = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug x64|Win32.Build.0 = Debug x64|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug x64|x64.ActiveCfg = Debug x64|x64 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug x64|x64.Build.0 = Debug x64|x64 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug|Win32.ActiveCfg = Debug|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug|Win32.Build.0 = Debug|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug|x64.ActiveCfg = Debug|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Debug|x64.Build.0 = Debug|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Mesa Release|Win32.ActiveCfg = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Mesa Release|Win32.Build.0 = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Mesa Release|x64.ActiveCfg = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Mesa Release|x64.Build.0 = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Release x64|Win32.ActiveCfg = Release x64|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Release x64|Win32.Build.0 = Release x64|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Release x64|x64.ActiveCfg = Release x64|x64 {1687EE67-7C95-4A57-B891-3136065823EC}.Release x64|x64.Build.0 = Release x64|x64 {1687EE67-7C95-4A57-B891-3136065823EC}.Release|Win32.ActiveCfg = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Release|Win32.Build.0 = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Release|x64.ActiveCfg = Release|Win32 {1687EE67-7C95-4A57-B891-3136065823EC}.Release|x64.Build.0 = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug x64|Win32.ActiveCfg = Debug x64|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug x64|Win32.Build.0 = Debug x64|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug x64|x64.ActiveCfg = Debug x64|x64 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug x64|x64.Build.0 = Debug x64|x64 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug|Win32.ActiveCfg = Debug|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug|Win32.Build.0 = Debug|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug|x64.ActiveCfg = Debug|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Debug|x64.Build.0 = Debug|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Mesa Release|Win32.ActiveCfg = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Mesa Release|Win32.Build.0 = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Mesa Release|x64.ActiveCfg = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Mesa Release|x64.Build.0 = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release x64|Win32.ActiveCfg = Release x64|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release x64|Win32.Build.0 = Release x64|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release x64|x64.ActiveCfg = Release x64|x64 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release x64|x64.Build.0 = Release x64|x64 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release|Win32.ActiveCfg = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release|Win32.Build.0 = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release|x64.ActiveCfg = Release|Win32 {1E0FBD00-C82C-47DF-88FC-9EFCDD659A3F}.Release|x64.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/jdoom64.vcproj0000644000175000017500000011264711357170241022367 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/jhexen.vcproj0000644000175000017500000011657511357170241022372 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/jheretic.vcproj0000644000175000017500000011426611357170241022701 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/dsdirectsound.vcproj0000644000175000017500000005264111357170241023754 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vs8/dpdehread.vcproj0000644000175000017500000005233411357170241023021 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/jdoom64_cl.rsp0000644000175000017500000000526411357170241021622 0ustar keeskees .\..\..\plugins\common\src\am_map.c .\..\..\plugins\common\src\d_net.c .\..\..\plugins\common\src\d_netcl.c .\..\..\plugins\common\src\d_netsv.c .\..\..\plugins\common\src\dmu_lib.c .\..\..\plugins\common\src\f_infine.c .\..\..\plugins\common\src\g_controls.c .\..\..\plugins\common\src\g_defs.c .\..\..\plugins\common\src\g_game.c .\..\..\plugins\common\src\g_update.c .\..\..\plugins\common\src\hu_lib.c .\..\..\plugins\common\src\hu_log.c .\..\..\plugins\common\src\hu_menu.c .\..\..\plugins\common\src\hu_msg.c .\..\..\plugins\common\src\hu_pspr.c .\..\..\plugins\common\src\hu_stuff.c .\..\..\plugins\common\src\m_ctrl.c .\..\..\plugins\common\src\m_fixed.c .\..\..\plugins\common\src\m_multi.c .\..\..\plugins\common\src\p_actor.c .\..\..\plugins\common\src\p_automap.c .\..\..\plugins\common\src\p_ceiling.c .\..\..\plugins\common\src\p_door.c .\..\..\plugins\common\src\p_floor.c .\..\..\plugins\common\src\p_inventory.c .\..\..\plugins\common\src\p_iterlist.c .\..\..\plugins\common\src\p_map.c .\..\..\plugins\common\src\p_mapsetup.c .\..\..\plugins\common\src\p_mapspec.c .\..\..\plugins\common\src\p_plat.c .\..\..\plugins\common\src\p_player.c .\..\..\plugins\common\src\p_saveg.c .\..\..\plugins\common\src\p_start.c .\..\..\plugins\common\src\p_svtexarc.c .\..\..\plugins\common\src\p_switch.c .\..\..\plugins\common\src\p_terraintype.c .\..\..\plugins\common\src\p_tick.c .\..\..\plugins\common\src\p_user.c .\..\..\plugins\common\src\p_view.c .\..\..\plugins\common\src\p_xgfile.c .\..\..\plugins\common\src\p_xgline.c .\..\..\plugins\common\src\p_xgsave.c .\..\..\plugins\common\src\p_xgsec.c .\..\..\plugins\common\src\r_common.c .\..\..\plugins\common\src\rend_automap.c .\..\..\plugins\common\src\st_lib.c .\..\..\plugins\common\src\x_hair.c .\..\..\plugins\jdoom64\src\acfnlink.c .\..\..\plugins\jdoom64\src\d_api.c .\..\..\plugins\jdoom64\src\d_console.c .\..\..\plugins\jdoom64\src\d_items.c .\..\..\plugins\jdoom64\src\d_main.c .\..\..\plugins\jdoom64\src\d_refresh.c .\..\..\plugins\jdoom64\src\g_ctrl.c .\..\..\plugins\jdoom64\src\m_cheat.c .\..\..\plugins\jdoom64\src\m_random.c .\..\..\plugins\jdoom64\src\p_enemy.c .\..\..\plugins\jdoom64\src\p_inter.c .\..\..\plugins\jdoom64\src\p_lights.c .\..\..\plugins\jdoom64\src\p_maputl.c .\..\..\plugins\jdoom64\src\p_mobj.c .\..\..\plugins\jdoom64\src\p_pspr.c .\..\..\plugins\jdoom64\src\p_telept.c .\..\..\plugins\jdoom64\src\p_setup.c .\..\..\plugins\jdoom64\src\p_sound.c .\..\..\plugins\jdoom64\src\p_spec.c .\..\..\plugins\jdoom64\src\st_stuff.c .\..\..\plugins\jdoom64\src\tables.c .\..\..\plugins\jdoom64\src\wi_stuff.c deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vcconfig-example.bat0000644000175000017500000000265011357170241023047 0ustar keeskeesREM Build configuration (example). REM Modify and save as "vcconfig.bat". SET ROOT_DIR=D:\deng\svn\trunk\doomsday SET BIN_DIR=.\bin\release SET OBJ_DIR=.\obj\release REM -=- Requirements for Doomsday.exe -=- REM REM ---- Platform SDK: SET PLATFORM_INC=C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include SET PLATFORM_LIB=C:\Program Files\Microsoft SDKs\Windows\v6.0A\Lib SET LIBCI_LIB=C:\Program Files\Microsoft SDKs\Windows\v6.0A\Include REM ---- Python Interpreter SET PYTHON_DIR=C:\Python25 REM ---- DirectX: SET DX_INC=C:\Program Files\Microsoft DirectX SDK (March 2009)\Include SET DX_LIB=C:\Program Files\Microsoft DirectX SDK (March 2009)\Lib REM ---- Creative Labs EAX: SET EAX_INC=D:\sdk\Creative Labs\EAX 2.0 Extensions SDK\Include SET EAX_LIB=D:\sdk\Creative Labs\EAX 2.0 Extensions SDK\Libs SET EAX_DLL=D:\sdk\Creative Labs\EAX 2.0 Extensions SDK\dll REM ---- SDL: SET SDL_INC=D:\sdk\SDL-1.2.14\include SET SDL_LIB=D:\sdk\SDL-1.2.14\lib REM ---- SDL_net: SET SDLNET_INC=D:\sdk\SDL_net-1.2.7\include SET SDLNET_LIB=D:\sdk\SDL_net-1.2.7\lib REM ---- SDL_mixer: SET SDLMIXER_INC=D:\sdk\SDL_mixer-1.2.11\include SET SDLMIXER_LIB=D:\sdk\SDL_mixer-1.2.11\lib REM -=- Requirements for drOpenGL.dll -=- REM REM ---- OpenGL (GL\gl.h, GL\glext.h, GL\glu.h): SET GL_INC=D:\sdk\OpenGL REM -=- Requirements for dsOpenAL.dll -=- REM REM ---- OpenAL: SET OPENAL_INC=D:\sdk\OpenAL 1.1 SDK\include SET OPENAL_LIB=D:\sdk\OpenAL 1.1 SDK\libs deng-1.9.0-beta6.9+dfsg1/doomsday/build/win32/vcbuild.bat0000644000175000017500000004452711357170241021261 0ustar keeskees@ECHO OFF IF "%1" == "" GOTO Help IF "%1" == "help" GOTO Help GOTO SetPaths :Help cls ECHO $Id$ ECHO. ECHO This build script compiles the Doomsday Engine and the associated ECHO libraries. ECHO. ECHO Microsoft Visual C++ Toolkit is the minimum requirement. If you ECHO want to compile the engine itself, you will also need the Platform ECHO SDK, which can be downloaded from Microsoft's website. The DirectX ECHO SDK is also required for compiling the engine. This means you can ECHO compile everything using tools that can be downloaded for free, but ECHO all the SDKs will add up to several hundred megabytes. ECHO. ECHO On the bright side, you only need the Visual C++ Toolkit in order to ECHO compile a game DLL. The game DLLs' only dependency is Doomsday.lib, ECHO which is included in the Doomsday source code package. ECHO. IF EXIST vcconfig.bat GOTO FoundConfig :MissingConfig ECHO IMPORTANT: ECHO In order to use this batch file you'll first need to configure the ECHO include paths to any dependancies of the code you wish to compile. ECHO For example if you want to compile Doomsday.exe (Engine) you'll need ECHO to set up the path to your Platform SDK (amongst others). ECHO. ECHO Open the file "vcconfig-example.bat", edit the paths appropriately ECHO and then save your changes into a new file called: ECHO. ECHO vcconfig.bat ECHO. GOTO TheRealEnd :FoundConfig ECHO Throughout this batch file there are targets that can be given as ECHO arguments on the command line. For example, to compile jDoom you ECHO would use the "jdoom" target: ECHO. ECHO vcbuild jdoom ECHO. ECHO The "all" target compiles everything in the appropriate order: ECHO. ECHO vcbuild all ECHO. ECHO Build Tip: ECHO To output the messages produced during compilation to a log file, ECHO append the build target with the redirection character ">" followed ECHO by a filename: ECHO. ECHO vcbuild doomsday^>buildlog.txt GOTO TheRealEnd :SetPaths :: -- Set up paths. IF NOT EXIST vcconfig.bat GOTO MissingConfig CALL vcconfig.bat SET SOMETHING_FAILED=0 SET DENG_ENGINE_DIR=.\..\..\engine SET DENG_ENGINE_API_DIR=.\..\..\engine\api SET DENG_PLUGINS_DIR=.\..\..\plugins SET DENG_EXTERNAL_DIR=.\..\..\external :: -- Make sure the output directories exist. IF NOT EXIST %BIN_DIR% md %BIN_DIR% IF NOT EXIST %OBJ_DIR% md %OBJ_DIR% :: -- Compiler and linker options. SET DEFINES=/D "ZLIB_DLL" /D "WIN32_GAMMA" /D "NORANGECHECKING" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_CRT_SECURE_NO_DEPRECATE" SET DLLDEFINES=/D "_USRDLL" /D "_WINDLL" %DEFINES% SET INCS_ENGINE_API=%DENG_ENGINE_API_DIR% SET INCS_ENGINE_PORTABLE=%DENG_ENGINE_DIR%\portable\include SET INCS_ENGINE_WIN32=%DENG_ENGINE_DIR%\win32\include SET INCS_LZSS_PORTABLE=%DENG_EXTERNAL_DIR%\lzss\portable\include SET INCS_LIBPNG_PORTABLE=%DENG_EXTERNAL_DIR%\libpng\portable\include SET INCS_ZLIB=%DENG_EXTERNAL_DIR%\zlib\portable\include SET INCS_LIBCURL=%DENG_EXTERNAL_DIR%\libcurl\portable\include SET INCS_PLUGIN_COMMON=%DENG_PLUGINS_DIR%\common\include SET LIBS=/libpath:".\lib" /libpath:"%SDL_LIB%" /libpath:"%SDLNET_LIB%" /libpath:"%SDLMIXER_LIB%" /libpath:"%BIN_DIR%" SET LFLAGS=/incremental:NO /subsystem:WINDOWS /machine:I386 :: -- Iterate through all command line arguments. :Looper IF "%1" == "" GOTO TheEnd GOTO %1 :: *** Build options :_D SET DEBUGDEFINES=/D "_DEBUG" GOTO Done :_P SET PROFILEDEFINES=/D "DD_PROFILE" GOTO Done :: *** Cleanup and build all targets. :All CALL vcbuild.bat cleanup res dmt doomsday dpdehread dpwadmapconverter dsopenal dswinmm dsdirectsound jdoom jheretic jhexen jdoom64 copydep GOTO Done :: *** Clean the output directories. :Cleanup rd/s/q %BIN_DIR% rd/s/q %OBJ_DIR% md %BIN_DIR% md %OBJ_DIR% GOTO Done :: *** Resources :: Requires rc.exe and cvtres.exe from the Platform SDK. :Res ECHO *************************************************************************** ECHO ****************** Generating resources from rc scripts ******************* ECHO *************************************************************************** ECHO Processing doomsday.rc... rc /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_ENGINE_DIR%\win32\res\doomsday.rc" ECHO Processing jdoom.rc... rc /D "__JDOOM__" /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\jdoom\res\jdoom.rc" ECHO Processing jdoom64.rc... rc /D "__JDOOM64__" /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\jdoom64\res\jdoom64.rc" ECHO Processing jheretic.rc... rc /D "__JHERETIC__" /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\jheretic\res\jheretic.rc" ECHO Processing jhexen.rc... rc /D "__JHEXEN__" /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\jhexen\res\jhexen.rc" ECHO Processing dehread.rc... rc /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\dehread\res\dehread.rc" ECHO Processing directsound.rc... rc /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\directsound\res\directsound.rc" ECHO Processing openal.rc... rc /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\openal\res\openal.rc" ECHO Processing wadmapconverter.rc... rc /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\wadmapconverter\res\wadmapconverter.rc" ECHO Processing winmm.rc... rc /i "%PLATFORM_INC%" /i "%PLATFORM_INC%\mfc" "%DENG_PLUGINS_DIR%\winmm\res\winmm.rc" ECHO *************************************************************************** ECHO ********************* Converting resources to objects ********************* ECHO *************************************************************************** ECHO Processing Doomsday.res... md %OBJ_DIR% cvtres /out:"%OBJ_DIR%\doomsday_res.obj" /MACHINE:X86 "%DENG_ENGINE_DIR%\win32\res\doomsday.res" ECHO Processing jDoom.res... md %OBJ_DIR%\jdoom cvtres /out:"%OBJ_DIR%\jdoom\jdoom_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\jdoom\res\jdoom.res" ECHO Processing jDoom64.res... md %OBJ_DIR%\jdoom64 cvtres /out:"%OBJ_DIR%\jdoom64\jdoom64_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\jdoom64\res\jdoom64.res" ECHO Processing jHeretic.res... md %OBJ_DIR%\jheretic cvtres /out:"%OBJ_DIR%\jheretic\jheretic_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\jheretic\res\jheretic.res" ECHO Processing jHexen.res... md %OBJ_DIR%\jhexen cvtres /out:"%OBJ_DIR%\jhexen\jhexen_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\jhexen\res\jhexen.res" ECHO Processing dehread.res... md %OBJ_DIR%\dpdehread cvtres /out:"%OBJ_DIR%\dpdehread\dpdehread_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\dehread\res\dehread.res" ECHO Processing directsound.res... md %OBJ_DIR%\dsdirectsound cvtres /out:"%OBJ_DIR%\dsdirectsound\dsdirectsound_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\directsound\res\directsound.res" ECHO Processing openal.res... md %OBJ_DIR%\dsopenal cvtres /out:"%OBJ_DIR%\dsopenal\dsopenal_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\openal\res\openal.res" ECHO Processing wadmapconverter.res... md %OBJ_DIR%\dpwadmapconverter cvtres /out:"%OBJ_DIR%\dpwadmapconverter\dpwadmapconverter_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\wadmapconverter\res\wadmapconverter.res" ECHO Processing winmm.res... md %OBJ_DIR%\dswinmm cvtres /out:"%OBJ_DIR%\dswinmm\dswinmm_res.obj" /MACHINE:X86 "%DENG_PLUGINS_DIR%\winmm\res\winmm.res" IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** Execute a Python Script :: Requires Python interpreter. :Script ECHO Run Script: %2 SET CURRENTSCRIPT=%2 "%PYTHON_DIR%"\python "%CURRENTSCRIPT%" SHIFT GOTO Done :: *** Copy various files to the build directory, for packaging. :copydep copy "%SDL_LIB%\SDL.dll" . copy "%SDLNET_LIB%\SDL_net.dll" . copy "%SDLMIXER_LIB%\libogg-0.dll" . copy "%SDLMIXER_LIB%\libvorbis-0.dll" . copy "%SDLMIXER_LIB%\libvorbisfile-3.dll" . copy "%SDLMIXER_LIB%\mikmod.dll" . copy "%SDLMIXER_LIB%\SDL_mixer.dll" . copy "%SDLMIXER_LIB%\smpeg.dll" . copy "%EAX_DLL%\eax.dll" . copy "%DENG_ENGINE_DIR%\doc\LICENSE" license.txt GOTO Done :: *** Mapdata type headers :CheckDMT :: First check for their existence IF NOT EXIST "%DENG_ENGINE_API_DIR%\dd_maptypes.h" GOTO DMT IF NOT EXIST "%DENG_ENGINE_DIR%\include\p_maptypes.h" GOTO DMT :: TODO compare creation date&time with that of mapdata.hs :: If mapdata.hs is newer - recreate the headers. ECHO DMT headers are up to date. GOTO TheRealEnd :DMT SET SCRIPTPARAMATERS="%DENG_ENGINE_DIR%\scripts\makedmt.py < %DENG_ENGINE_DIR%\portable\include\mapdata.hs" CALL vcbuild.bat script %SCRIPTPARAMATERS% MOVE /Y dd_maptypes.h "%DENG_ENGINE_API_DIR%\\" MOVE /Y p_maptypes.h "%DENG_ENGINE_DIR%\portable\include\\" GOTO DONE :: *** Doomsday.exe :Doomsday CALL vcbuild.bat checkdmt ECHO *************************************************************************** ECHO ******************** Compiling Doomsday.exe (Engine) ****************** ECHO *************************************************************************** cl /Ob1 /Oi /Ot /Oy /GF /FD /EHsc /MT /GS /Gy /Fo"%OBJ_DIR%\\" /Fd"%OBJ_DIR%\\" /W3 /Gd /Gs /I "%INCS_ENGINE_API%\\" /I "%EAX_INC%" /I "%SDL_INC%" /I "%SDLMIXER_INC%" /I "%SDLNET_INC%" /I "%DX_INC%" /I "%PLATFORM_INC%" /I "%INCS_ENGINE_WIN32%\\" /I "%GL_INC%" /I "%INCS_ENGINE_PORTABLE%\\" /I "%INCS_LZSS_PORTABLE%\\" /I "%INCS_LIBPNG_PORTABLE%\\" /I "%INCS_LIBCURL%\\" /I "%INCS_ZLIB%\\" /I "%INCS_PLUGIN_COMMON%\\" %DEFINES% %DEBUGDEFINES% %PROFILEDEFINES% /D "__DOOMSDAY__" "%OBJ_DIR%\doomsday_res.obj" @doomsday_cl.rsp /link /out:"%BIN_DIR%\Doomsday.exe" /def:"%DENG_ENGINE_API_DIR%\doomsday.def" /implib:"%BIN_DIR%\Doomsday.lib" %LFLAGS% %LIBS% /libpath:"%PLATFORM_LIB%\\" /libpath:"%DX_LIB%\\" "%DENG_EXTERNAL_DIR%\libpng\win32\libpng13.lib" "%DENG_EXTERNAL_DIR%\zlib\win32\zlib1.lib" "%DENG_EXTERNAL_DIR%\lzss\win32\lzss.lib" "%DENG_EXTERNAL_DIR%\libcurl\win32\curllib.lib" sdl_net.lib sdl.lib SDL_mixer.lib wsock32.lib dinput8.lib dsound.lib dxguid.lib winmm.lib opengl32.lib glu32.lib kernel32.lib gdi32.lib ole32.lib user32.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** dpDehRead.dll :dpDehRead ECHO *************************************************************************** ECHO *********** Compiling dpDehRead.dll (Dehacked Reader Plugin) ********** ECHO *************************************************************************** md %OBJ_DIR%\dpDehRead cl /O2 /Ob1 /I "%INCS_ENGINE_API%\\" %DLLDEFINES% /D "DPDEHREAD_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\dpDehRead\\" /Fd"%OBJ_DIR%\dpDehRead\\" /W3 /Gd "%OBJ_DIR%\dpdehread\dpdehread_res.obj" @dpdehread_cl.rsp /link /out:"%BIN_DIR%\dpDehRead.dll" %LFLAGS% /dll /implib:"%BIN_DIR%\dpDehRead.lib" %LIBS% %BIN_DIR%\Doomsday.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** dsOpenAL.dll :dsOpenAL ECHO *************************************************************************** ECHO ************ Compiling dsOpenAL.dll (OpenAL SoundFX driver) *********** ECHO *************************************************************************** md %OBJ_DIR%\dsOpenAL cl /O2 /Ob1 /I "%INCS_ENGINE_API%\\" %DLLDEFINES% /D "DSOPENAL_EXPORTS" /I "%OPENAL_INC%" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\dsOpenAL" /Fd"%OBJ_DIR%\dsOpenAL" /W3 /Gd "%OBJ_DIR%\dsopenal\dsopenal_res.obj" @dsopenal_cl.rsp /link /out:"%BIN_DIR%\dsOpenAL.dll" %LFLAGS% /dll /def:"%DENG_PLUGINS_DIR%\openal\api\dsOpenAL.def" /implib:"%BIN_DIR%\dsOpenAL.lib" %LIBS% /libpath:"%OPENAL_LIB%" %BIN_DIR%\doomsday.lib openal32.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** dsDirectSound.dll :dsDirectSound ECHO *************************************************************************** ECHO ***** Compiling dsDirectSound.dll (DirectSound(3D) SoundFX driver) **** ECHO *************************************************************************** md %OBJ_DIR%\dsDirectSound cl /O2 /Ob1 /I "%INCS_ENGINE_API%\\" /I "%DX_INC%" /I "%EAX_INC%" %DLLDEFINES% /D "DSDIRECTSOUND_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\dsDirectSound" /Fd"%OBJ_DIR%\dsDirectSound" /W3 /Gd "%OBJ_DIR%\dsdirectsound\dsdirectsound_res.obj" @dsdirectsound_cl.rsp /link /out:"%BIN_DIR%\dsDirectSound.dll" %LFLAGS% /dll /def:"%DENG_PLUGINS_DIR%\directsound\api\dsdirectsound.def" /implib:"%BIN_DIR%\dsDirectSound.lib" %LIBS% /libpath:"%DX_LIB%\\" /libpath:"%EAX_LIB%" eax.lib eaxguid.lib dsound.lib dxguid.lib %BIN_DIR%\doomsday.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** dsWinMM.dll :dsWinMM ECHO *************************************************************************** ECHO ******* Compiling dsWinMM.dll (Windows Multimedia Mixing driver) ****** ECHO *************************************************************************** md %OBJ_DIR%\dsWinMM cl /O2 /Ob1 /I "%INCS_ENGINE_API%\\" /I "%DENG_PLUGINS_DIR%\winmm\include" %DLLDEFINES% /D "DSWINMM_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\dswinmm\\" /Fd"%OBJ_DIR%\dswinmm\\" /W3 /Gd "%OBJ_DIR%\dswinmm\dswinmm_res.obj" @dswinmm_cl.rsp /link /out:"%BIN_DIR%\dsWinMM.dll" %LFLAGS% /dll /def:"%DENG_PLUGINS_DIR%\winmm\api\dswinmm.def" /implib:"%BIN_DIR%\dsWinMM.lib" %LIBS% winmm.lib %BIN_DIR%\doomsday.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** dpWadMapConverter.dll :dpWadMapConverter ECHO *************************************************************************** ECHO ***** Compiling dpWadMapConverter.dll (WAD Map converter plugin) ****** ECHO *************************************************************************** md %OBJ_DIR%\dpWadMapConverter cl /O2 /Ob1 /I "%INCS_ENGINE_API%\\" /I "%DENG_PLUGINS_DIR%\wadmapconverter\include" %DLLDEFINES% /D "DPWADMAPCONVERTER_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\dpwadmapconverter\\" /Fd"%OBJ_DIR%\dpWadMapConverter\\" /W3 /Gd "%OBJ_DIR%\dpwadmapconverter\dpwadmapconverter_res.obj" @dpwadmapconverter_cl.rsp /link /out:"%BIN_DIR%\dpWadMapConverter.dll" %LFLAGS% /dll /implib:"%BIN_DIR%\dpwadmapconverter.lib" %LIBS% %BIN_DIR%\doomsday.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** jDoom.dll :jDoom ECHO *************************************************************************** ECHO ************** Compiling jDoom.dll (jDoom Game Library) *************** ECHO *************************************************************************** md %OBJ_DIR%\jDoom cl /O2 /Ob1 /I "%INCS_PLUGIN_COMMON%\\" /I "%INCS_ENGINE_API%\\" /I "%INCS_LZSS_PORTABLE%\\" /I "%DENG_PLUGINS_DIR%\jdoom\include" /D "__JDOOM__" %DLLDEFINES% /D "JDOOM_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\jDoom\\" /Fd"%OBJ_DIR%\jDoom\\" /W3 /Gd "%OBJ_DIR%\jdoom\jdoom_res.obj" @jdoom_cl.rsp /link /out:"%BIN_DIR%\jDoom.dll" %LFLAGS% /libpath:".\Lib" /dll /def:"%DENG_PLUGINS_DIR%\jdoom\api\jdoom.def" /implib:"%BIN_DIR%\jDoom.lib" "%BIN_DIR%\doomsday.lib" "%DENG_EXTERNAL_DIR%\lzss\win32\lzss.lib" IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** jHeretic.dll :jHeretic ECHO *************************************************************************** ECHO *********** Compiling jHeretic.dll (jHeretic Game Library) ************ ECHO *************************************************************************** md %OBJ_DIR%\jHeretic cl /O2 /Ob1 /I "%INCS_PLUGIN_COMMON%\\" /I "%INCS_ENGINE_API%\\" /I "%INCS_LZSS_PORTABLE%\\" /I "%DENG_PLUGINS_DIR%\jheretic\include" /D "__JHERETIC__" %DLLDEFINES% /D "JHERETIC_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\jHeretic\\" /Fd"%OBJ_DIR%\jHeretic\\" /W3 /Gd "%OBJ_DIR%\jheretic\jheretic_res.obj" @jheretic_cl.rsp /link /out:"%BIN_DIR%\jHeretic.dll" %LFLAGS% /libpath:".\Lib" /dll /def:"%DENG_PLUGINS_DIR%\jheretic\api\jheretic.def" /implib:"%BIN_DIR%\jHeretic.lib" %BIN_DIR%\doomsday.lib %DENG_EXTERNAL_DIR%\lzss\win32\lzss.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** jHexen.dll :jHexen ECHO *************************************************************************** ECHO ************* Compiling jHexen.dll (jHexen Game Library) ************** ECHO *************************************************************************** md %OBJ_DIR%\jHexen cl /O2 /Ob1 /I "%INCS_PLUGIN_COMMON%\\" /I "%INCS_ENGINE_API%\\" /I "%INCS_LZSS_PORTABLE%\\" /I "%DENG_PLUGINS_DIR%\jhexen\include" /D "__JHEXEN__" %DLLDEFINES% /D "JHEXEN_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\jHexen\\" /Fd"%OBJ_DIR%\jHexen\\" /W3 /Gd "%OBJ_DIR%\jhexen\jhexen_res.obj" @jhexen_cl.rsp /link /out:"%BIN_DIR%\jHexen.dll" %LFLAGS% /libpath:".\Lib" /dll /def:"%DENG_PLUGINS_DIR%\jhexen\api\jhexen.def" /implib:"%BIN_DIR%\jHexen.lib" %BIN_DIR%\doomsday.lib %DENG_EXTERNAL_DIR%\lzss\win32\lzss.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** jDoom64.dll :jDoom64 ECHO *************************************************************************** ECHO ************ Compiling jDoom64.dll (jDoom64 Game Library) ************* ECHO *************************************************************************** md %OBJ_DIR%\jDoom64 cl /O2 /Ob1 /I "%INCS_PLUGIN_COMMON%\\" /I "%INCS_ENGINE_API%\\" /I "%INCS_LZSS_PORTABLE%\\" /I "%DENG_PLUGINS_DIR%\jdoom64\include" /D "__JDOOM64__" %DLLDEFINES% /D "JDOOM64_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\jDoom64\\" /Fd"%OBJ_DIR%\jDoom64\\" /W3 /Gd "%OBJ_DIR%\jdoom64\jdoom64_res.obj" @jdoom64_cl.rsp /link /out:"%BIN_DIR%\jDoom64.dll" %LFLAGS% /libpath:".\Lib" /dll /def:"%DENG_PLUGINS_DIR%\jdoom64\api\jdoom64.def" /implib:"%BIN_DIR%\jDoom64.lib" %BIN_DIR%\doomsday.lib %DENG_EXTERNAL_DIR%\lzss\win32\lzss.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: *** dpExample.dll :dpExample ECHO *************************************************************************** ECHO ********** Compiling dpExample.dll (Doomsday Example Plugin) ********** ECHO *************************************************************************** md %OBJ_DIR%\dpExample cl /O2 /Ob1 /I "%INCS_ENGINE_API%\\" %DLLDEFINES% /D "EXAMPLE_PLUGIN" /D "DPEXAMPLE_EXPORTS" /GF /FD /EHsc /MT /Gy /Fo"%OBJ_DIR%\dpExample\\" /Fd"%OBJ_DIR%\dpExample\\" /W3 /Gd @dpexample_cl.rsp /link /out:"%BIN_DIR%\dpExample.dll" %LFLAGS% /dll /implib:"%BIN_DIR%\dpExample.lib" %LIBS% %BIN_DIR%\Doomsday.lib IF %ERRORLEVEL% == 0 GOTO Done GOTO Failure :: -- Move to the next argument. :Done SHIFT GOTO Looper :Failure SET SOMETHING_FAILED=1 ECHO. ECHO. ECHO *************************************************************************** ECHO **************************** BUILD FAILED! **************************** ECHO *************************************************************************** ECHO. ECHO. GOTO Done :Failure2 ECHO There were build errors. GOTO TheRealEnd :TheEnd IF %SOMETHING_FAILED% == 1 GOTO Failure2 ECHO All Done! :TheRealEnd deng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/0000755000175000017500000000000011523516205017242 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/FindCURL.cmake0000644000175000017500000000243611357170240021617 0ustar keeskees# - Find curl # Find the native CURL headers and libraries. # # CURL_INCLUDE_DIRS - where to find curl/curl.h, etc. # CURL_LIBRARIES - List of libraries when using curl. # CURL_FOUND - True if curl found. # Look for the header file. FIND_PATH(CURL_INCLUDE_DIR NAMES curl/curl.h PATHS $ENV{LIBCURLDIR}/include /usr/local/include /usr/include) MARK_AS_ADVANCED(CURL_INCLUDE_DIR) # Look for the library. FIND_LIBRARY(CURL_LIBRARY NAMES curl libcurl libcurl-4 PATHS $ENV{LIBCURLDIR}/lib /usr/lib /usr/local/lib ) MARK_AS_ADVANCED(CURL_LIBRARY) # Copy the results to the output variables. IF(CURL_INCLUDE_DIR AND CURL_LIBRARY) SET(CURL_FOUND 1) SET(CURL_LIBRARIES ${CURL_LIBRARY}) SET(CURL_INCLUDE_DIRS ${CURL_INCLUDE_DIR}) ELSE(CURL_INCLUDE_DIR AND CURL_LIBRARY) SET(CURL_FOUND 0) SET(CURL_LIBRARIES) SET(CURL_INCLUDE_DIRS) ENDIF(CURL_INCLUDE_DIR AND CURL_LIBRARY) # Report the results. IF(NOT CURL_FOUND) SET(CURL_DIR_MESSAGE "CURL was not found. Make sure CURL_LIBRARY and CURL_INCLUDE_DIR are set.") IF(NOT CURL_FIND_QUIETLY) MESSAGE(STATUS "${CURL_DIR_MESSAGE}") ELSE(NOT CURL_FIND_QUIETLY) IF(CURL_FIND_REQUIRED) MESSAGE(FATAL_ERROR "${CURL_DIR_MESSAGE}") ENDIF(CURL_FIND_REQUIRED) ENDIF(NOT CURL_FIND_QUIETLY) ENDIF(NOT CURL_FOUND) deng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/FindDIRECTX_DIRECTSOUND.cmake0000644000175000017500000000417011357170240024014 0ustar keeskees# - Try to find DIRECTX_DIRECTSOUND # Once done this will define # # DIRECTX_DIRECTSOUND_FOUND - system has DIRECTX_DIRECTSOUND # DIRECTX_DIRECTSOUND_INCLUDE_DIRS - the DIRECTX_DIRECTSOUND include directory # DIRECTX_DIRECTSOUND_LIBRARIES - Link these to use DIRECTX_DIRECTSOUND # DIRECTX_DIRECTSOUND_DEFINITIONS - Compiler switches required for using DIRECTX_DIRECTSOUND # # Copyright (c) 2007 Jamie Jones # # Redistribution and use is allowed according to the terms of the # GNU GPLv3 license. # if (DIRECTX_DIRECTSOUND_LIBRARIES AND DIRECTX_DIRECTSOUND_INCLUDE_DIRS) # in cache already set(DIRECTX_DIRECTSOUND_FOUND TRUE) else (DIRECTX_DIRECTSOUND_LIBRARIES AND DIRECTX_DIRECTSOUND_INCLUDE_DIRS) find_path(DIRECTX_DIRECTSOUND_INCLUDE_DIR NAMES dsound.h PATHS $ENV{DIRECTXDIR}/include /usr/include /usr/local/include /opt/local/include /sw/include ) find_library(LIBDSOUND_LIBRARY NAMES libdsound PATHS $ENV{DIRECTXDIR}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(DIRECTX_DIRECTSOUND_INCLUDE_DIRS ${DIRECTX_DIRECTSOUND_INCLUDE_DIR} ) set(DIRECTX_DIRECTSOUND_LIBRARIES ${LIBDSOUND_LIBRARY} ) if (DIRECTX_DIRECTSOUND_INCLUDE_DIRS AND DIRECTX_DIRECTSOUND_LIBRARIES) set(DIRECTX_DIRECTSOUND_FOUND TRUE) endif (DIRECTX_DIRECTSOUND_INCLUDE_DIRS AND DIRECTX_DIRECTSOUND_LIBRARIES) if (DIRECTX_DIRECTSOUND_FOUND) if (NOT DIRECTX_DIRECTSOUND_FIND_QUIETLY) message(STATUS "Found DIRECTX_DIRECTSOUND: ${DIRECTX_DIRECTSOUND_LIBRARIES}") endif (NOT DIRECTX_DIRECTSOUND_FIND_QUIETLY) else (DIRECTX_DIRECTSOUND_FOUND) if (DIRECTX_DIRECTSOUND_FIND_REQUIRED) message(FATAL_ERROR "Could not find DIRECTX_DIRECTSOUND") endif (DIRECTX_DIRECTSOUND_FIND_REQUIRED) endif (DIRECTX_DIRECTSOUND_FOUND) # show the DIRECTX_DIRECTSOUND_INCLUDE_DIRS and DIRECTX_DIRECTSOUND_LIBRARIES variables only in the advanced view mark_as_advanced(DIRECTX_DIRECTSOUND_INCLUDE_DIRS DIRECTX_DIRECTSOUND_LIBRARIES) endif (DIRECTX_DIRECTSOUND_LIBRARIES AND DIRECTX_DIRECTSOUND_INCLUDE_DIRS) deng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/FindPNG.cmake0000644000175000017500000000335211357170240021474 0ustar keeskees# - Find the native PNG includes and library # # This module defines # PNG_INCLUDE_DIR, where to find png.h, etc. # PNG_LIBRARIES, the libraries to link against to use PNG. # PNG_DEFINITIONS - You should ADD_DEFINITONS(${PNG_DEFINITIONS}) before compiling code that includes png library files. # PNG_FOUND, If false, do not try to use PNG. # also defined, but not for general use are # PNG_LIBRARY, where to find the PNG library. # None of the above will be defined unles zlib can be found. # PNG depends on Zlib INCLUDE(${CMAKE_SOURCE_DIR}/build/cmake/FindZLIB.cmake) IF(ZLIB_FOUND) FIND_PATH(PNG_PNG_INCLUDE_DIR png.h $ENV{LIBPNGDIR}/include /sw/include /usr/local/include /usr/include ) SET(PNG_NAMES ${PNG_NAMES} png libpng) FIND_LIBRARY(PNG_LIBRARY NAMES ${PNG_NAMES} PATHS $ENV{LIBPNGDIR}/lib /usr/lib /usr/local/lib ) IF (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR) # png.h includes zlib.h. Sigh. SET(PNG_INCLUDE_DIR ${PNG_PNG_INCLUDE_DIR} ${ZLIB_INCLUDE_DIR} ) SET(PNG_LIBRARIES ${PNG_LIBRARY} ${ZLIB_LIBRARY}) SET(PNG_FOUND "YES") IF (CYGWIN) IF(BUILD_SHARED_LIBS) # No need to define PNG_USE_DLL here, because it's default for Cygwin. ELSE(BUILD_SHARED_LIBS) SET (PNG_DEFINITIONS -DPNG_STATIC) ENDIF(BUILD_SHARED_LIBS) ENDIF (CYGWIN) ENDIF (PNG_LIBRARY AND PNG_PNG_INCLUDE_DIR) ENDIF(ZLIB_FOUND) IF (APPLE) #SET(PNG_INCLUDE_DIR "/opt/local/include" ) SET(PNG_LIBRARIES "" ) #SET(PNG_LIBRARY_STATIC "/opt/local/lib/libpng12.a") FIND_LIBRARY(PNG_LIBRARY_STATIC NAMES libpng12.a PATHS /opt/local/lib /sw/lib) SET(PNG_FOUND "YES") ENDIF (APPLE) MARK_AS_ADVANCED(PNG_PNG_INCLUDE_DIR PNG_LIBRARY PNG_LIBRARY_STATIC ) deng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/FindDIRECTX_DIRECTINPUT.cmake0000644000175000017500000000417011357170240024023 0ustar keeskees# - Try to find DIRECTX_DIRECTINPUT # Once done this will define # # DIRECTX_DIRECTINPUT_FOUND - system has DIRECTX_DIRECTINPUT # DIRECTX_DIRECTINPUT_INCLUDE_DIRS - the DIRECTX_DIRECTINPUT include directory # DIRECTX_DIRECTINPUT_LIBRARIES - Link these to use DIRECTX_DIRECTINPUT # DIRECTX_DIRECTINPUT_DEFINITIONS - Compiler switches required for using DIRECTX_DIRECTINPUT # # Copyright (c) 2007 Jamie Jones # # Redistribution and use is allowed according to the terms of the # GNU GPLv3 license. # if (DIRECTX_DIRECTINPUT_LIBRARIES AND DIRECTX_DIRECTINPUT_INCLUDE_DIRS) # in cache already set(DIRECTX_DIRECTINPUT_FOUND TRUE) else (DIRECTX_DIRECTINPUT_LIBRARIES AND DIRECTX_DIRECTINPUT_INCLUDE_DIRS) find_path(DIRECTX_DIRECTINPUT_INCLUDE_DIR NAMES dinput.h PATHS $ENV{DIRECTXDIR}/include /usr/include /usr/local/include /opt/local/include /sw/include ) find_library(LIBDINPUT_LIBRARY NAMES libdinput PATHS $ENV{DIRECTXDIR}/lib /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(DIRECTX_DIRECTINPUT_INCLUDE_DIRS ${DIRECTX_DIRECTINPUT_INCLUDE_DIR} ) set(DIRECTX_DIRECTINPUT_LIBRARIES ${LIBDINPUT_LIBRARY} ) if (DIRECTX_DIRECTINPUT_INCLUDE_DIRS AND DIRECTX_DIRECTINPUT_LIBRARIES) set(DIRECTX_DIRECTINPUT_FOUND TRUE) endif (DIRECTX_DIRECTINPUT_INCLUDE_DIRS AND DIRECTX_DIRECTINPUT_LIBRARIES) if (DIRECTX_DIRECTINPUT_FOUND) if (NOT DIRECTX_DIRECTINPUT_FIND_QUIETLY) message(STATUS "Found DIRECTX_DIRECTINPUT: ${DIRECTX_DIRECTINPUT_LIBRARIES}") endif (NOT DIRECTX_DIRECTINPUT_FIND_QUIETLY) else (DIRECTX_DIRECTINPUT_FOUND) if (DIRECTX_DIRECTINPUT_FIND_REQUIRED) message(FATAL_ERROR "Could not find DIRECTX_DIRECTINPUT") endif (DIRECTX_DIRECTINPUT_FIND_REQUIRED) endif (DIRECTX_DIRECTINPUT_FOUND) # show the DIRECTX_DIRECTINPUT_INCLUDE_DIRS and DIRECTX_DIRECTINPUT_LIBRARIES variables only in the advanced view mark_as_advanced(DIRECTX_DIRECTINPUT_INCLUDE_DIRS DIRECTX_DIRECTINPUT_LIBRARIES) endif (DIRECTX_DIRECTINPUT_LIBRARIES AND DIRECTX_DIRECTINPUT_INCLUDE_DIRS) deng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/FindZLIB.cmake0000644000175000017500000000123511357170240021606 0ustar keeskees# - Find zlib # Find the native ZLIB includes and library # # ZLIB_INCLUDE_DIR - where to find zlib.h, etc. # ZLIB_LIBRARIES - List of libraries when using zlib. # ZLIB_FOUND - True if zlib found. FIND_PATH(ZLIB_INCLUDE_DIR zlib.h $ENV{ZLIBDIR}/include /usr/local/include /usr/include ) SET(ZLIB_NAMES ${ZLIB_NAMES} z zlib zdll) FIND_LIBRARY(ZLIB_LIBRARY NAMES ${ZLIB_NAMES} PATHS $ENV{ZLIBDIR}/lib /usr/lib /usr/local/lib ) IF(ZLIB_INCLUDE_DIR) IF(ZLIB_LIBRARY) SET( ZLIB_LIBRARIES ${ZLIB_LIBRARY} ) SET( ZLIB_FOUND "YES" ) ENDIF(ZLIB_LIBRARY) ENDIF(ZLIB_INCLUDE_DIR) MARK_AS_ADVANCED( ZLIB_LIBRARY ZLIB_INCLUDE_DIR ) deng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/FindEAX.cmake0000644000175000017500000000274411357170240021471 0ustar keeskees# - Try to find EAX # Once done this will define # # EAX_FOUND - system has EAX # EAX_INCLUDE_DIRS - the EAX include directory # EAX_LIBRARIES - Link these to use EAX # EAX_DEFINITIONS - Compiler switches required for using EAX # # Copyright (c) 2007 Jamie Jones # # Redistribution and use is allowed according to the terms of the # GNU GPL v3 # if (EAX_LIBRARIES AND EAX_INCLUDE_DIRS) # in cache already set(EAX_FOUND TRUE) else (EAX_LIBRARIES AND EAX_INCLUDE_DIRS) find_path(EAX_INCLUDE_DIR NAMES eax.h PATHS $ENV{EAXDIR}/include /usr/include /usr/local/include /opt/local/include /sw/include ) find_library(EAX_LIBRARY NAMES eax PATHS $ENV{EAXDIR}/libs /usr/lib /usr/local/lib /opt/local/lib /sw/lib ) set(EAX_INCLUDE_DIRS ${EAX_INCLUDE_DIR} ) set(EAX_LIBRARIES ${EAX_LIBRARY} ) if (EAX_INCLUDE_DIRS AND EAX_LIBRARIES) set(EAX_FOUND TRUE) endif (EAX_INCLUDE_DIRS AND EAX_LIBRARIES) if (EAX_FOUND) if (NOT EAX_FIND_QUIETLY) message(STATUS "Found EAX: ${EAX_LIBRARIES}") endif (NOT EAX_FIND_QUIETLY) else (EAX_FOUND) if (EAX_FIND_REQUIRED) message(FATAL_ERROR "Could not find EAX") endif (EAX_FIND_REQUIRED) endif (EAX_FOUND) # show the EAX_INCLUDE_DIRS and EAX_LIBRARIES variables only in the advanced view mark_as_advanced(EAX_INCLUDE_DIRS EAX_LIBRARIES) endif (EAX_LIBRARIES AND EAX_INCLUDE_DIRS) deng-1.9.0-beta6.9+dfsg1/doomsday/build/cmake/FindOpenAL.cmake0000644000175000017500000000573311357170240022173 0ustar keeskees# - Locate OpenAL # This module defines # OPENAL_LIBRARY # OPENAL_FOUND, if false, do not try to link to OpenAL # OPENAL_INCLUDE_DIR, where to find the headers # # $OPENALDIR is an environment variable that would # correspond to the ./configure --prefix=$OPENALDIR # used in building OpenAL. # # Created by Eric Wing. This was influenced by the FindSDL.cmake module. # On OSX, this will prefer the Framework version (if found) over others. # People will have to manually change the cache values of # OPENAL_LIBRARY to override this selection. # Tiger will include OpenAL as part of the System. # But for now, we have to look around. # Other (Unix) systems should be able to utilize the non-framework paths. FIND_PATH(OPENAL_INCLUDE_DIR al.h $ENV{OPENALDIR}/include ~/Library/Frameworks/OpenAL.framework/Headers /Library/Frameworks/OpenAL.framework/Headers /System/Library/Frameworks/OpenAL.framework/Headers # Tiger /usr/local/include/AL /usr/local/include/OpenAL /usr/local/include /usr/include/AL /usr/include/OpenAL /usr/include /sw/include/AL # Fink /sw/include/OpenAL /sw/include /opt/local/include/AL # DarwinPorts /opt/local/include/OpenAL /opt/local/include /opt/csw/include/AL # Blastwave /opt/csw/include/OpenAL /opt/csw/include /opt/include/AL /opt/include/OpenAL /opt/include ) # I'm not sure if I should do a special casing for Apple. It is # unlikely that other Unix systems will find the framework path. # But if they do ([Next|Open|GNU]Step?), # do they want the -framework option also? IF(${OPENAL_INCLUDE_DIR} MATCHES ".framework") STRING(REGEX REPLACE "(.*)/.*\\.framework/.*" "\\1" OPENAL_FRAMEWORK_PATH_TMP ${OPENAL_INCLUDE_DIR}) IF("${OPENAL_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks" OR "${OPENAL_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks" ) # String is in default search path, don't need to use -F SET (OPENAL_LIBRARY "-framework OpenAL" CACHE STRING "OpenAL framework for OSX") ELSE("${OPENAL_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks" OR "${OPENAL_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks" ) # String is not /Library/Frameworks, need to use -F SET(OPENAL_LIBRARY "-F${OPENAL_FRAMEWORK_PATH_TMP} -framework OpenAL" CACHE STRING "OpenAL framework for OSX") ENDIF("${OPENAL_FRAMEWORK_PATH_TMP}" STREQUAL "/Library/Frameworks" OR "${OPENAL_FRAMEWORK_PATH_TMP}" STREQUAL "/System/Library/Frameworks" ) # Clear the temp variable so nobody can see it SET(OPENAL_FRAMEWORK_PATH_TMP "" CACHE INTERNAL "") ELSE(${OPENAL_INCLUDE_DIR} MATCHES ".framework") FIND_LIBRARY(OPENAL_LIBRARY NAMES openal al OpenAL32 PATHS $ENV{OPENALDIR}/libs/win32 $ENV{OPENALDIR}/lib $ENV{OPENALDIR}/libs /usr/local/lib /usr/lib /sw/lib /opt/local/lib /opt/csw/lib /opt/lib ) ENDIF(${OPENAL_INCLUDE_DIR} MATCHES ".framework") SET(OPENAL_FOUND "NO") IF(OPENAL_LIBRARY) SET(OPENAL_FOUND "YES") ENDIF(OPENAL_LIBRARY) deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/0000755000175000017500000000000011523516205016722 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/dsSDLMixer-Info.plist0000644000175000017500000000125011357170240022644 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable dsSDLMixer CFBundleIdentifier net.sourceforge.deng.dsSDLMixer CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/dpDehRead-Info.plist0000644000175000017500000000124611357170240022513 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable dpDehRead CFBundleIdentifier net.sourceforge.deng.dpDehRead CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/createfont_osx.py0000755000175000017500000003252211357170240022326 0ustar keeskees#!/usr/local/bin/python """ EXPERIMENTAL CODE! Here we load a .TTF font file, and display it in a basic pygame window. It demonstrates several of the Font object attributes. Nothing exciting in here, but it makes a great example for basic window, event, and font management. """ import sys, struct import pygame import math from pygame.locals import * from pygame import Surface from pygame.surfarray import blit_array, make_surface, pixels3d, pixels2d import Numeric from Foundation import * from AppKit import * # Version 1 is the monochrome one. DFN_VERSION = 2 def _getColor(color=None): if color is None: return NSColor.clearColor() return NSColor.colorWithDeviceRed_green_blue_alpha_(*color) #div255 = (0.00390625).__mul__ #if len(color) == 3: # color = tuple(color) + (255.0,) #return NSColor.colorWithDeviceRed_green_blue_alpha_(*color) #*map(div255, color)) def _getBitmapImageRep(size, hasAlpha=True): width, height = map(int, size) return NSBitmapImageRep.alloc().initWithBitmapDataPlanes_pixelsWide_pixelsHigh_bitsPerSample_samplesPerPixel_hasAlpha_isPlanar_colorSpaceName_bytesPerRow_bitsPerPixel_(None, width, height, 8, 4, hasAlpha, False, NSDeviceRGBColorSpace, width*4, 32) def alpha_blend(src, dest): a = src[3]/255.0 inv = 1.0 - a #return src #if src[3] == 0: #return src #print src[3], a, inv, int(a * src[3] + inv * dest[3]) return ( min(255, int(a * 1 * src[0] + inv * dest[0])), min(255, int(a * 1 * src[1] + inv * dest[1])), min(255, int(a * 1 * src[2] + inv * dest[2])), min(255, int(a * src[3] + inv * dest[3])) ) def filter_range(n): offset = 1 # - int(n/5) return range(-n/2 + offset, n/2 + offset) class SysFont(object): def __init__(self, name, size, variant=None): self._font = NSFont.fontWithName_size_(name, size) self._isBold = False self._isOblique = False self._isUnderline = False self._variant = variant self._family = name self._size = size self._setupFont() def _setupFont(self): name = self._family if self._variant: name = '%s-%s' % (name, self._variant) elif self._isBold or self._isOblique: name = '%s-%s%s' % ( name, self._isBold and 'Bold' or '', self._isOblique and 'Oblique' or '') self._font = NSFont.fontWithName_size_(name, self._size) print name, self._font if self._font is None: if self._isBold: self._font = NSFont.boldSystemFontOfSize(self._size) else: self._font = NSFont.systemFontOfSize_(self._size) def get_ascent(self): return self._font.ascender() def get_descent(self): return -self._font.descender() def get_bold(self): return self._isBold def get_height(self): return self._font.defaultLineHeightForFont() def get_italic(self): return self._isOblique def get_linesize(self): pass def get_underline(self): return self._isUnderline def set_bold(self, isBold): if isBold != self._isBold: self._isBold = isBold self._setupFont() def set_italic(self, isOblique): if isOblique != self._isOblique: self._isOblique = isOblique self._setupFont() def set_underline(self, isUnderline): self._isUnderline = isUnderline def size(self, text): return tuple(map(int,map(math.ceil, NSString.sizeWithAttributes_(text, { NSFontAttributeName: self._font, NSUnderlineStyleAttributeName: self._isUnderline and 1.0 or 0, })))) def advancement(self, glyph): return tuple(self._font.advancementForGlyph_(ord(glyph))) def shadow_filter_size(self): filter_size = int(self.get_height() / 5) if filter_size % 2 == 0: filter_size += 1 return int(max(filter_size, 3)) def border_size(self): return self.shadow_filter_size()/2 def render(self, text, antialias = True, forecolor=(255, 255, 255, 255), backcolor=(255, 255, 255, 0)): size = self.size(text) img = NSImage.alloc().initWithSize_(size) img.lockFocus() NSString.drawAtPoint_withAttributes_(text, (0.0, 0.0), { NSFontAttributeName: self._font, NSUnderlineStyleAttributeName: self._isUnderline and 1.0 or 0, NSBackgroundColorAttributeName: _getColor(backcolor),# or None, NSForegroundColorAttributeName: _getColor(forecolor), }) rep = NSBitmapImageRep.alloc().initWithFocusedViewRect_(((0.0, 0.0), size)) img.unlockFocus() if rep.samplesPerPixel() == 4: s = Surface(size, SRCALPHA|SWSURFACE, 32, [-1<<24,0xff<<16,0xff<<8,0xff]) a = Numeric.reshape(Numeric.fromstring(rep.bitmapData(), typecode=Numeric.Int32), (size[1], size[0])) blit_array(s, Numeric.swapaxes(a, 0, 1)) #print "surface size is ", size filter_size = self.shadow_filter_size() border = self.border_size() result = [] result_size = (size[0] + border*2, size[1] + border*2) #print "result size is ", result_size for y in range(result_size[1]): result.append([(0, 0, 0, 0)] * result_size[0]) # Filter the character appropriately. s.lock() for y in range(size[1]): for x in range(size[0]): color = s.get_at((x, y)) s.set_at((x, y), (255, 255, 255, color[3])) if filter_size == 3: factors = [[1, 2, 1], [2, 4, 2], [1, 2, 1]] elif filter_size == 5: factors = [[1, 4, 6, 4, 1], [4, 16, 24, 16, 4], [6, 24, 36, 24, 6], [4, 16, 24, 16, 4], [1, 4, 6, 4, 1]] elif filter_size == 7: factors = [[1, 6, 15, 20, 15, 6, 1], [6, 36, 90, 120, 90, 36, 6], [15, 90, 225, 300, 225, 90, 15], [20, 120, 300, 400, 300, 120, 20], [15, 90, 225, 300, 225, 90, 15], [6, 36, 90, 120, 90, 36, 6], [1, 6, 15, 20, 15, 6, 1]] else: print "factors for filter size", filter_size, "not defined!" factors = 0 # Filter a shadow. for ry in range(result_size[1]): for rx in range(result_size[0]): inpos = (rx - int(border), ry - int(border)) count = 0 colorsum = 0 u = 0 v = 0 for a in filter_range(filter_size): v = 0 for b in filter_range(filter_size): x, y = (inpos[0] + a, inpos[1] + b) factor = factors[u][v] if x >= 0 and y >= 0 and x < size[0] and y < size[1]: colorsum += factor * s.get_at((x, y))[3] count += factor v += 1 u += 1 if count > 0: result_color = (int(colorsum) + count/2) / count else: result_color = 0 result[ry][rx] = (0, 0, 0, min(255, result_color*1.4)) # Blend the glyph itself to the result. for y in range(size[1]): for x in range(size[0]): color = s.get_at((x, y)) result[border + y][border + x] = \ alpha_blend(color, result[border + y][border + x]) result[border + y][border + x] = \ alpha_blend(color, result[border + y][border + x]) #result[border + y][border + x] = \ # alpha_blend(color, result[border + y][border + x]) s.unlock() glyph_rgba = Numeric.array(result, typecode=Numeric.UnsignedInt8) return glyph_rgba, result_size #return s.convert_alpha() class Glyph: def __init__(self, code): self.code = code self.bitmap = None self.pos = (0, 0) self.dims = (0, 0) def pow2(n): i = 1 while i < n: i *= 2 return i def find_pixel(glyphs, x, y): for g in glyphs: lx = x - g.pos[0] ly = y - g.pos[1] if lx >= 0 and ly >= 0 and lx < g.dims[0] and ly < g.dims[1]: # This is the glyph. return g.bitmap[ly][lx] return (0, 0, 0, 0) if __name__=='__main__': if len(sys.argv) < 5: print "usage: " + sys.argv[0] + " (font-name) (font-size) (texture-width) (output-file)" sys.exit(0) out_filename = sys.argv[4] pygame.init() #screen = pygame.display.set_mode((600, 600)) point_size = int(sys.argv[2]) s = SysFont(sys.argv[1], point_size) #s = SysFont('Andale Mono', 24) #done = False # Collect all the glyphs here. glyphs = [] texture_width = int(sys.argv[3]) font_point_height = s.get_height() print "Font texture width =", texture_width print "Line height =", font_point_height, "pt" print "Font size =", point_size, "pt" ascent = s.get_ascent() descent = s.get_descent() print "Ascent =", ascent, "pt Descent =", descent, "pt" print "Shadow filter is sized %i for this font." % s.shadow_filter_size() border_size = s.border_size() print "Glyph borders are %i pixels wide." % border_size rover = (0, 0) line_height = 0 texture_height = 0 used_pixels = 0 # Only the basic ASCII set, and some specific characters. char_range = range(0x20, 0x7F) + [0x96, 0x97, 0xA3, 0xA4, 0xA9, 0xB0, 0xB1] for code in char_range: glyph = Glyph(code) try: glyph.bitmap, glyph.dims = s.render(chr(code)) used_pixels += glyph.dims[0] * glyph.dims[1] line_height = max(line_height, glyph.dims[1]) texture_height = max(line_height, texture_height) # Does if fit here? if rover[0] + glyph.dims[0] > texture_width: # No, move to the new row. rover = (0, rover[1] + line_height) texture_height += line_height print "Finished a %i pixels tall line." % line_height line_height = 0 glyph.pos = rover # Move the rover. rover = (rover[0] + glyph.dims[0], rover[1]) #print "Code %i: Placement =" % code, glyph.pos, " dims =", glyph.dims glyphs.append(glyph) #except Exception, x: except KeyboardInterrupt: print "Code %i: Failed to render." % code print x print "Finished rendering %i glyphs." % len(glyphs) actual_line_height = glyphs[0].dims[1] - border_size*2 print "Actual line height is %i pixels." % actual_line_height print "Size of the finished texture is %i x %i." % (texture_width, texture_height) actual_height = pow2(texture_height) total_pixels = texture_width * actual_height print "Unused texture area: %.2f %%" % (100*(1.0 - used_pixels/float(total_pixels))) print "Writing output to file: %s" % out_filename out = file(out_filename, 'wb') # The DFN format begins with a single byte that declares the version # of the format. out.write(struct.pack('B', DFN_VERSION)) # The header follows: # Pixel format (0 = RGBA, 1 = LA). out.write(struct.pack('B', 0)) # Glyph count, texture width and height (unsigned shorts). out.write(struct.pack(', Daniel Swanson and the deng Team\ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\sb80\sa80\ql\qnatural \cf0 \ \b\fs28 Introduction\ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\ri-180\sb80\sa80\ql\qnatural \b0\fs24 \cf0 The Doomsday Engine is a "source port" of id Software's Doom and Raven Software's Heretic and Hexen, which were popular PC FPSs of the early-to-mid 1990s. Doomsday enhances these classic games with 3D graphics and fully customizable controls, making them more accessible for modern gamers. However, the feel of the original games stays intact, ensuring sublime nostalgia or an exciting introduction into the pioneering games of the genre.\ This disk image contains a Universal build of the Doomsday Engine, jDoom, jHeretic, and jHexen for Mac OS X. The Snowberry frontend is also included.\ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\fi-360\ri-180\sb80\sa80\ql\qnatural \b \cf2 BETA NOTE: \b0 \cf0 This is a \b beta \b0 release. Do not expect all things to work perfectly. Release notes and change log available at:\ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\ri-180\sb80\sa80\ql\qnatural \f1\i \cf0 http://dengine.net/dew/index.php?title=Version_1.9.0-beta6.9\ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\ri-180\sb80\sa80\ql\qnatural \f0\i0 \cf0 The latest version of the Doomsday Engine can be downloaded from:\ \f1\i http://sourceforge.net/projects/deng/ \f0\i0 \ On-line documentation:\ \f1\i http://dew.dengine.net/ \f0\i0\b \ \ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\fi-580\ri-180\sb80\sa80\ql\qnatural \fs28 \cf0 Installation \b0\fs24 \ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\ri-180\sb80\sa80\ql\qnatural \cf0 Drag the \b Doomsday Engine \b0 application to your /Applications folder. \b \ \b0 \ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\fi-580\ri-180\sb80\sa80\ql\qnatural \b\fs28 \cf0 Requirements \b0\fs24 \ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\ri-180\sb80\sa80\ql\qnatural \cf0 At least one IWAD data file from the original Doom, Heretic, or Hexen is required. For example, to play Doom II, you will need a file called DOOM2.WAD from the original game. The shareware versions of Doom and Heretic and the 4-level demo version of Hexen are also supported. \ If you don't own a copy of the original games, shareware versions are still widely available on the net. \b \ \ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\fi-580\ri-180\sb80\sa80\ql\qnatural \fs28 \cf0 Starting the Game \b0 \ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\ri-180\sb80\sa80\ql\qnatural \fs24 \cf0 Open the \b Doomsday Engine \b0 application. The Snowberry frontend application will appear. The first time you start the application, a setup wizard will guide you through setting up some game profiles for launching. \ Press the \b Play \b0 button to launch the selected game, and wait for the game window to appear. \ Your runtime files (savegames, screenshots) are stored into a folder called "~/Library/Application Support/Doomsday Engine/runtime".\ \pard\tx565\tx1133\tx1700\tx2266\tx2832\tx3401\tx3967\tx4535\tx5102\tx5669\tx6235\tx6802\li580\fi-360\ri-180\sb80\sa80\ql\qnatural \b \cf2 BETA NOTE: \b0 \cf0 To see the Doomsday startup messages, view console.log in \b Console.app \b0 . The startup messages will appear in console.log while Doomsday is being loaded.\ }deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/jHexen-Info.plist0000644000175000017500000000124011357170240022106 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable jHexen CFBundleIdentifier net.sourceforge.deng.jHexen CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/jDoom-Info.plist0000644000175000017500000000123611357170240021742 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable jDoom CFBundleIdentifier net.sourceforge.deng.jDoom CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/drOpenGL-Info.plist0000644000175000017500000000124411357170240022343 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable drOpenGL CFBundleIdentifier net.sourceforge.deng.drOpenGL CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/Doomsday.xcodeproj/0000755000175000017500000000000011523516205022475 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/Doomsday.xcodeproj/project.pbxproj0000755000175000017500000101063211357170240025557 0ustar keeskees// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 42; objects = { /* Begin PBXFileReference section */ B01995A40F51619B009020DF /* p_automap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_automap.c; sourceTree = ""; }; B01995A50F51619B009020DF /* rend_automap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_automap.c; sourceTree = ""; }; B079185E0F2E280400A5A0C0 /* m_stack.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_stack.c; sourceTree = ""; }; B079185F0F2E280400A5A0C0 /* p_material.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_material.c; sourceTree = ""; }; B07918600F2E280400A5A0C0 /* p_materialmanager.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_materialmanager.c; sourceTree = ""; }; B07918610F2E280400A5A0C0 /* sys_opengl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_opengl.c; sourceTree = ""; }; B07918630F2E282100A5A0C0 /* m_stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_stack.h; sourceTree = ""; }; B07918640F2E282100A5A0C0 /* p_material.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_material.h; sourceTree = ""; }; B07918650F2E282100A5A0C0 /* p_materialmanager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_materialmanager.h; sourceTree = ""; }; B07918660F2E282100A5A0C0 /* sys_opengl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_opengl.h; sourceTree = ""; }; B086F9660F0B9EDD00955E23 /* dd_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_api.h; sourceTree = ""; }; B086F9670F0B9EDD00955E23 /* dd_maptypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_maptypes.h; sourceTree = ""; }; B086F9680F0B9EDD00955E23 /* dd_plugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_plugin.h; sourceTree = ""; }; B086F9690F0B9EDD00955E23 /* dd_share.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_share.h; sourceTree = ""; }; B086F96A0F0B9EDD00955E23 /* dd_types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_types.h; sourceTree = ""; }; B086F96B0F0B9EDD00955E23 /* doomsday.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doomsday.def; sourceTree = ""; }; B086F96C0F0B9EDD00955E23 /* doomsday.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomsday.h; sourceTree = ""; }; B086F96D0F0B9EDD00955E23 /* sys_audiod.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_audiod.h; sourceTree = ""; }; B086F96E0F0B9EDD00955E23 /* sys_audiod_mus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_audiod_mus.h; sourceTree = ""; }; B086F96F0F0B9EDD00955E23 /* sys_audiod_sfx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_audiod_sfx.h; sourceTree = ""; }; B086F9710F0B9EDD00955E23 /* cphelp.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cphelp.txt; sourceTree = ""; }; B086F9730F0B9EDD00955E23 /* console11.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = console11.dfn; sourceTree = ""; }; B086F9740F0B9EDD00955E23 /* console14.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = console14.dfn; sourceTree = ""; }; B086F9750F0B9EDD00955E23 /* console18.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = console18.dfn; sourceTree = ""; }; B086F9760F0B9EDD00955E23 /* fixed.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = fixed.dfn; sourceTree = ""; }; B086F9770F0B9EDD00955E23 /* normal12.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normal12.dfn; sourceTree = ""; }; B086F9780F0B9EDD00955E23 /* normal18.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normal18.dfn; sourceTree = ""; }; B086F9790F0B9EDD00955E23 /* normal24.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normal24.dfn; sourceTree = ""; }; B086F97A0F0B9EDD00955E23 /* normalbold12.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normalbold12.dfn; sourceTree = ""; }; B086F97B0F0B9EDD00955E23 /* normalbold18.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normalbold18.dfn; sourceTree = ""; }; B086F97C0F0B9EDD00955E23 /* normalbold24.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normalbold24.dfn; sourceTree = ""; }; B086F97D0F0B9EDD00955E23 /* normallight12.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normallight12.dfn; sourceTree = ""; }; B086F97E0F0B9EDD00955E23 /* normallight18.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normallight18.dfn; sourceTree = ""; }; B086F97F0F0B9EDD00955E23 /* normallight24.dfn */ = {isa = PBXFileReference; lastKnownFileType = file; path = normallight24.dfn; sourceTree = ""; }; B086F9800F0B9EDD00955E23 /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = ""; }; B086F9820F0B9EDD00955E23 /* background.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = background.pcx; sourceTree = ""; }; B086F9830F0B9EDD00955E23 /* bbox.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = bbox.pcx; sourceTree = ""; }; B086F9840F0B9EDD00955E23 /* bigflare.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = bigflare.pcx; sourceTree = ""; }; B086F9850F0B9EDD00955E23 /* boxcorner.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = boxcorner.png; sourceTree = ""; }; B086F9860F0B9EDD00955E23 /* boxfill.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = boxfill.png; sourceTree = ""; }; B086F9870F0B9EDD00955E23 /* boxshade.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = boxshade.png; sourceTree = ""; }; B086F9880F0B9EDD00955E23 /* brflare.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = brflare.pcx; sourceTree = ""; }; B086F9890F0B9EDD00955E23 /* dlight.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = dlight.pcx; sourceTree = ""; }; B086F98A0F0B9EDD00955E23 /* flare.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = flare.pcx; sourceTree = ""; }; B086F98B0F0B9EDD00955E23 /* gray.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = gray.png; sourceTree = ""; }; B086F98C0F0B9EDD00955E23 /* hint.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = hint.png; sourceTree = ""; }; B086F98D0F0B9EDD00955E23 /* loading1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = loading1.png; sourceTree = ""; }; B086F98E0F0B9EDD00955E23 /* loading2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = loading2.png; sourceTree = ""; }; B086F98F0F0B9EDD00955E23 /* logo.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = logo.png; sourceTree = ""; }; B086F9900F0B9EDD00955E23 /* missing.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = missing.png; sourceTree = ""; }; B086F9910F0B9EDD00955E23 /* mouse.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mouse.png; sourceTree = ""; }; B086F9920F0B9EDD00955E23 /* radiocc.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = radiocc.pcx; sourceTree = ""; }; B086F9930F0B9EDD00955E23 /* radioco.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = radioco.pcx; sourceTree = ""; }; B086F9940F0B9EDD00955E23 /* radiooe.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = radiooe.pcx; sourceTree = ""; }; B086F9950F0B9EDD00955E23 /* radiooo.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = radiooo.pcx; sourceTree = ""; }; B086F9960F0B9EDD00955E23 /* unknown.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = unknown.png; sourceTree = ""; }; B086F9970F0B9EDD00955E23 /* wallglow.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = wallglow.pcx; sourceTree = ""; }; B086F9980F0B9EDD00955E23 /* zeroth.pcx */ = {isa = PBXFileReference; lastKnownFileType = file; path = zeroth.pcx; sourceTree = ""; }; B086F99A0F0B9EDD00955E23 /* de.dkm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = de.dkm; sourceTree = ""; }; B086F99B0F0B9EDD00955E23 /* default.dkm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = default.dkm; sourceTree = ""; }; B086F99C0F0B9EDD00955E23 /* fi.dkm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = fi.dkm; sourceTree = ""; }; B086F99E0F0B9EDD00955E23 /* doomsday.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doomsday.ded; sourceTree = ""; }; B086F99F0F0B9EDD00955E23 /* flags.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = flags.ded; sourceTree = ""; }; B086F9A00F0B9EDD00955E23 /* xg.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = xg.ded; sourceTree = ""; }; B086F9A30F0B9EDD00955E23 /* beginner.ame */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = beginner.ame; sourceTree = ""; }; B086F9A40F0B9EDD00955E23 /* cmdline.ame */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cmdline.ame; sourceTree = ""; }; B086F9A50F0B9EDD00955E23 /* darktable.ame */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = darktable.ame; sourceTree = ""; }; B086F9A60F0B9EDD00955E23 /* dedref.ame */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dedref.ame; sourceTree = ""; }; B086F9A70F0B9EDD00955E23 /* infine.ame */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = infine.ame; sourceTree = ""; }; B086F9A80F0B9EDD00955E23 /* jake.ah */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jake.ah; sourceTree = ""; }; B086F9A90F0B9EDD00955E23 /* make.bat */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = make.bat; sourceTree = ""; }; B086F9AA0F0B9EDD00955E23 /* readme.ame */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.ame; sourceTree = ""; }; B086F9AB0F0B9EDD00955E23 /* version2.ame */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = version2.ame; sourceTree = ""; }; B086F9AC0F0B9EDD00955E23 /* banner.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = banner.txt; sourceTree = ""; }; B086F9AD0F0B9EDD00955E23 /* changelog.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = changelog.txt; sourceTree = ""; }; B086F9AE0F0B9EDD00955E23 /* cnsname.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cnsname.txt; sourceTree = ""; }; B086F9AF0F0B9EDD00955E23 /* cvars.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = cvars.txt; sourceTree = ""; }; B086F9B00F0B9EDD00955E23 /* deddoc.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = deddoc.txt; sourceTree = ""; }; B086F9B10F0B9EDD00955E23 /* dhistory.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dhistory.txt; sourceTree = ""; }; B086F9B20F0B9EDD00955E23 /* doomsday.6 */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doomsday.6; sourceTree = ""; }; B086F9B30F0B9EDD00955E23 /* dss.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dss.txt; sourceTree = ""; }; B086F9B40F0B9EDD00955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086F9B50F0B9EDD00955E23 /* manpage.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = manpage.xml; sourceTree = ""; }; B086F9B60F0B9EDD00955E23 /* naming.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = naming.txt; sourceTree = ""; }; B086F9B70F0B9EDD00955E23 /* network.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = network.txt; sourceTree = ""; }; B086F9BA0F0B9EDD00955E23 /* DoomsdayRunner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DoomsdayRunner.h; sourceTree = ""; }; B086F9BB0F0B9EDD00955E23 /* SDLMain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDLMain.h; sourceTree = ""; }; B086F9BC0F0B9EDD00955E23 /* StartupWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StartupWindowController.h; sourceTree = ""; }; B086F9BE0F0B9EDD00955E23 /* deng.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = deng.icns; sourceTree = ""; }; B086F9C00F0B9EDD00955E23 /* English */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; B086F9C10F0B9EDD00955E23 /* Startup.nib */ = {isa = PBXFileReference; lastKnownFileType = wrapper.nib; path = Startup.nib; sourceTree = ""; }; B086F9C30F0B9EDD00955E23 /* DoomsdayRunner.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DoomsdayRunner.m; sourceTree = ""; }; B086F9C40F0B9EDD00955E23 /* qt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = qt.c; sourceTree = ""; }; B086F9C50F0B9EDD00955E23 /* SDLMain.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDLMain.m; sourceTree = ""; }; B086F9C60F0B9EDD00955E23 /* StartupWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StartupWindowController.m; sourceTree = ""; }; B086F9C90F0B9EDD00955E23 /* b_command.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b_command.h; sourceTree = ""; }; B086F9CA0F0B9EDD00955E23 /* b_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b_context.h; sourceTree = ""; }; B086F9CB0F0B9EDD00955E23 /* b_device.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b_device.h; sourceTree = ""; }; B086F9CC0F0B9EDD00955E23 /* b_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b_main.h; sourceTree = ""; }; B086F9CD0F0B9EDD00955E23 /* b_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = b_util.h; sourceTree = ""; }; B086F9CE0F0B9EDD00955E23 /* bsp_edge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsp_edge.h; sourceTree = ""; }; B086F9CF0F0B9EDD00955E23 /* bsp_intersection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsp_intersection.h; sourceTree = ""; }; B086F9D00F0B9EDD00955E23 /* bsp_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsp_main.h; sourceTree = ""; }; B086F9D10F0B9EDD00955E23 /* bsp_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsp_map.h; sourceTree = ""; }; B086F9D20F0B9EDD00955E23 /* bsp_node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsp_node.h; sourceTree = ""; }; B086F9D30F0B9EDD00955E23 /* bsp_superblock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bsp_superblock.h; sourceTree = ""; }; B086F9D40F0B9EDD00955E23 /* cl_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_def.h; sourceTree = ""; }; B086F9D50F0B9EDD00955E23 /* cl_frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_frame.h; sourceTree = ""; }; B086F9D60F0B9EDD00955E23 /* cl_mobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_mobj.h; sourceTree = ""; }; B086F9D70F0B9EDD00955E23 /* cl_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_player.h; sourceTree = ""; }; B086F9D80F0B9EDD00955E23 /* cl_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_sound.h; sourceTree = ""; }; B086F9D90F0B9EDD00955E23 /* cl_world.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cl_world.h; sourceTree = ""; }; B086F9DA0F0B9EDD00955E23 /* con_bar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = con_bar.h; sourceTree = ""; }; B086F9DB0F0B9EDD00955E23 /* con_bind.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = con_bind.h; sourceTree = ""; }; B086F9DC0F0B9EDD00955E23 /* con_buffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = con_buffer.h; sourceTree = ""; }; B086F9DD0F0B9EDD00955E23 /* con_busy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = con_busy.h; sourceTree = ""; }; B086F9DE0F0B9EDD00955E23 /* con_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = con_config.h; sourceTree = ""; }; B086F9DF0F0B9EDD00955E23 /* con_decl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = con_decl.h; sourceTree = ""; }; B086F9E00F0B9EDD00955E23 /* con_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = con_main.h; sourceTree = ""; }; B086F9E10F0B9EDD00955E23 /* dam_blockmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dam_blockmap.h; sourceTree = ""; }; B086F9E20F0B9EDD00955E23 /* dam_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dam_file.h; sourceTree = ""; }; B086F9E30F0B9EDD00955E23 /* dam_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dam_main.h; sourceTree = ""; }; B086F9E40F0B9EDD00955E23 /* dam_reject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dam_reject.h; sourceTree = ""; }; B086F9E50F0B9EDD00955E23 /* dd_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_def.h; sourceTree = ""; }; B086F9E60F0B9EDD00955E23 /* dd_help.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_help.h; sourceTree = ""; }; B086F9E70F0B9EDD00955E23 /* dd_input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_input.h; sourceTree = ""; }; B086F9E80F0B9EDD00955E23 /* dd_loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_loop.h; sourceTree = ""; }; B086F9E90F0B9EDD00955E23 /* dd_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_main.h; sourceTree = ""; }; B086F9EA0F0B9EDD00955E23 /* dd_pinit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_pinit.h; sourceTree = ""; }; B086F9EB0F0B9EDD00955E23 /* dd_version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_version.h; sourceTree = ""; }; B086F9EC0F0B9EDD00955E23 /* dd_wad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_wad.h; sourceTree = ""; }; B086F9ED0F0B9EDD00955E23 /* dd_zip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_zip.h; sourceTree = ""; }; B086F9EE0F0B9EDD00955E23 /* dd_zone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_zone.h; sourceTree = ""; }; B086F9EF0F0B9EDD00955E23 /* de_audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_audio.h; sourceTree = ""; }; B086F9F00F0B9EDD00955E23 /* de_base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_base.h; sourceTree = ""; }; B086F9F10F0B9EDD00955E23 /* de_bsp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_bsp.h; sourceTree = ""; }; B086F9F20F0B9EDD00955E23 /* de_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_console.h; sourceTree = ""; }; B086F9F30F0B9EDD00955E23 /* de_dam.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_dam.h; sourceTree = ""; }; B086F9F40F0B9EDD00955E23 /* de_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_defs.h; sourceTree = ""; }; B086F9F50F0B9EDD00955E23 /* de_dgl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_dgl.h; sourceTree = ""; }; B086F9F60F0B9EDD00955E23 /* de_edit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_edit.h; sourceTree = ""; }; B086F9F70F0B9EDD00955E23 /* de_graphics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_graphics.h; sourceTree = ""; }; B086F9F80F0B9EDD00955E23 /* de_misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_misc.h; sourceTree = ""; }; B086F9F90F0B9EDD00955E23 /* de_network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_network.h; sourceTree = ""; }; B086F9FA0F0B9EDD00955E23 /* de_platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_platform.h; sourceTree = ""; }; B086F9FB0F0B9EDD00955E23 /* de_play.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_play.h; sourceTree = ""; }; B086F9FC0F0B9EDD00955E23 /* de_refresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_refresh.h; sourceTree = ""; }; B086F9FD0F0B9EDD00955E23 /* de_render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_render.h; sourceTree = ""; }; B086F9FE0F0B9EDD00955E23 /* de_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_system.h; sourceTree = ""; }; B086F9FF0F0B9EDD00955E23 /* de_ui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = de_ui.h; sourceTree = ""; }; B086FA000F0B9EDD00955E23 /* def_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = def_data.h; sourceTree = ""; }; B086FA010F0B9EDD00955E23 /* def_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = def_main.h; sourceTree = ""; }; B086FA020F0B9EDD00955E23 /* def_share.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = def_share.h; sourceTree = ""; }; B086FA030F0B9EDD00955E23 /* dgl_atiext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dgl_atiext.h; sourceTree = ""; }; B086FA040F0B9EDD00955E23 /* edit_bias.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = edit_bias.h; sourceTree = ""; }; B086FA050F0B9EDD00955E23 /* edit_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = edit_map.h; sourceTree = ""; }; B086FA060F0B9EDD00955E23 /* gl_defer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_defer.h; sourceTree = ""; }; B086FA070F0B9EDD00955E23 /* gl_draw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_draw.h; sourceTree = ""; }; B086FA080F0B9EDD00955E23 /* gl_font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_font.h; sourceTree = ""; }; B086FA090F0B9EDD00955E23 /* gl_hq2x.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_hq2x.h; sourceTree = ""; }; B086FA0A0F0B9EDD00955E23 /* gl_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_main.h; sourceTree = ""; }; B086FA0B0F0B9EDD00955E23 /* gl_model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_model.h; sourceTree = ""; }; B086FA0C0F0B9EDD00955E23 /* gl_pcx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_pcx.h; sourceTree = ""; }; B086FA0D0F0B9EDD00955E23 /* gl_png.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_png.h; sourceTree = ""; }; B086FA0E0F0B9EDD00955E23 /* gl_tex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_tex.h; sourceTree = ""; }; B086FA0F0F0B9EDD00955E23 /* gl_texmanager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_texmanager.h; sourceTree = ""; }; B086FA100F0B9EDD00955E23 /* gl_tga.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gl_tga.h; sourceTree = ""; }; B086FA110F0B9EDD00955E23 /* m_args.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_args.h; sourceTree = ""; }; B086FA120F0B9EDD00955E23 /* m_bams.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_bams.h; sourceTree = ""; }; B086FA130F0B9EDD00955E23 /* m_binarytree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_binarytree.h; sourceTree = ""; }; B086FA140F0B9EDD00955E23 /* m_decomp64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_decomp64.h; sourceTree = ""; }; B086FA150F0B9EDD00955E23 /* m_filehash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_filehash.h; sourceTree = ""; }; B086FA160F0B9EDD00955E23 /* m_gridmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_gridmap.h; sourceTree = ""; }; B086FA170F0B9EDD00955E23 /* m_huffman.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_huffman.h; sourceTree = ""; }; B086FA180F0B9EDD00955E23 /* m_linkedlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_linkedlist.h; sourceTree = ""; }; B086FA190F0B9EDD00955E23 /* m_md5.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_md5.h; sourceTree = ""; }; B086FA1A0F0B9EDD00955E23 /* m_misc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_misc.h; sourceTree = ""; }; B086FA1B0F0B9EDD00955E23 /* m_mus2midi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_mus2midi.h; sourceTree = ""; }; B086FA1C0F0B9EDD00955E23 /* m_nodepile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_nodepile.h; sourceTree = ""; }; B086FA1D0F0B9EDD00955E23 /* m_profiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_profiler.h; sourceTree = ""; }; B086FA1E0F0B9EDD00955E23 /* m_string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_string.h; sourceTree = ""; }; B086FA1F0F0B9EDD00955E23 /* m_vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_vector.h; sourceTree = ""; }; B086FA200F0B9EDD00955E23 /* mapdata.hs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = mapdata.hs; sourceTree = ""; }; B086FA210F0B9EDD00955E23 /* net_buf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = net_buf.h; sourceTree = ""; }; B086FA220F0B9EDD00955E23 /* net_demo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = net_demo.h; sourceTree = ""; }; B086FA230F0B9EDD00955E23 /* net_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = net_event.h; sourceTree = ""; }; B086FA240F0B9EDD00955E23 /* net_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = net_main.h; sourceTree = ""; }; B086FA250F0B9EDD00955E23 /* net_msg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = net_msg.h; sourceTree = ""; }; B086FA260F0B9EDD00955E23 /* p_bmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_bmap.h; sourceTree = ""; }; B086FA270F0B9EDD00955E23 /* p_cmd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_cmd.h; sourceTree = ""; }; B086FA280F0B9EDD00955E23 /* p_control.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_control.h; sourceTree = ""; }; B086FA290F0B9EDD00955E23 /* p_dmu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_dmu.h; sourceTree = ""; }; B086FA2A0F0B9EDD00955E23 /* p_intercept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_intercept.h; sourceTree = ""; }; B086FA2B0F0B9EDD00955E23 /* p_linedef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_linedef.h; sourceTree = ""; }; B086FA2C0F0B9EDD00955E23 /* p_mapdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mapdata.h; sourceTree = ""; }; B086FA2D0F0B9EDD00955E23 /* p_maptypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_maptypes.h; sourceTree = ""; }; B086FA2E0F0B9EDD00955E23 /* p_maputil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_maputil.h; sourceTree = ""; }; B086FA2F0F0B9EDD00955E23 /* p_object.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_object.h; sourceTree = ""; }; B086FA300F0B9EDD00955E23 /* p_objlink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_objlink.h; sourceTree = ""; }; B086FA310F0B9EDD00955E23 /* p_particle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_particle.h; sourceTree = ""; }; B086FA320F0B9EDD00955E23 /* p_plane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_plane.h; sourceTree = ""; }; B086FA330F0B9EDD00955E23 /* p_players.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_players.h; sourceTree = ""; }; B086FA340F0B9EDD00955E23 /* p_polyob.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_polyob.h; sourceTree = ""; }; B086FA350F0B9EDD00955E23 /* p_polyobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_polyobj.h; sourceTree = ""; }; B086FA360F0B9EDD00955E23 /* p_sector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_sector.h; sourceTree = ""; }; B086FA370F0B9EDD00955E23 /* p_seg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_seg.h; sourceTree = ""; }; B086FA380F0B9EDD00955E23 /* p_sidedef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_sidedef.h; sourceTree = ""; }; B086FA390F0B9EDD00955E23 /* p_sight.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_sight.h; sourceTree = ""; }; B086FA3A0F0B9EDD00955E23 /* p_subsector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_subsector.h; sourceTree = ""; }; B086FA3B0F0B9EDD00955E23 /* p_surface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_surface.h; sourceTree = ""; }; B086FA3C0F0B9EDD00955E23 /* p_think.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_think.h; sourceTree = ""; }; B086FA3D0F0B9EDD00955E23 /* p_ticker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_ticker.h; sourceTree = ""; }; B086FA3E0F0B9EDD00955E23 /* p_vertex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_vertex.h; sourceTree = ""; }; B086FA3F0F0B9EDD00955E23 /* r_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_data.h; sourceTree = ""; }; B086FA400F0B9EDD00955E23 /* r_draw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_draw.h; sourceTree = ""; }; B086FA410F0B9EDD00955E23 /* r_extres.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_extres.h; sourceTree = ""; }; B086FA420F0B9EDD00955E23 /* r_lgrid.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_lgrid.h; sourceTree = ""; }; B086FA430F0B9EDD00955E23 /* r_lumobjs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_lumobjs.h; sourceTree = ""; }; B086FA440F0B9EDD00955E23 /* r_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_main.h; sourceTree = ""; }; B086FA450F0B9EDD00955E23 /* r_materials.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_materials.h; sourceTree = ""; }; B086FA460F0B9EDD00955E23 /* r_model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_model.h; sourceTree = ""; }; B086FA470F0B9EDD00955E23 /* r_shadow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_shadow.h; sourceTree = ""; }; B086FA480F0B9EDD00955E23 /* r_sky.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_sky.h; sourceTree = ""; }; B086FA490F0B9EDD00955E23 /* r_things.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_things.h; sourceTree = ""; }; B086FA4A0F0B9EDD00955E23 /* r_util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_util.h; sourceTree = ""; }; B086FA4B0F0B9EDD00955E23 /* r_world.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_world.h; sourceTree = ""; }; B086FA4C0F0B9EDD00955E23 /* rend_bias.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_bias.h; sourceTree = ""; }; B086FA4D0F0B9EDD00955E23 /* rend_clip.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_clip.h; sourceTree = ""; }; B086FA4E0F0B9EDD00955E23 /* rend_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_console.h; sourceTree = ""; }; B086FA4F0F0B9EDD00955E23 /* rend_decor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_decor.h; sourceTree = ""; }; B086FA500F0B9EDD00955E23 /* rend_dyn.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_dyn.h; sourceTree = ""; }; B086FA510F0B9EDD00955E23 /* rend_fakeradio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_fakeradio.h; sourceTree = ""; }; B086FA520F0B9EDD00955E23 /* rend_halo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_halo.h; sourceTree = ""; }; B086FA530F0B9EDD00955E23 /* rend_list.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_list.h; sourceTree = ""; }; B086FA540F0B9EDD00955E23 /* rend_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_main.h; sourceTree = ""; }; B086FA550F0B9EDD00955E23 /* rend_model.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_model.h; sourceTree = ""; }; B086FA560F0B9EDD00955E23 /* rend_particle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_particle.h; sourceTree = ""; }; B086FA570F0B9EDD00955E23 /* rend_shadow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_shadow.h; sourceTree = ""; }; B086FA580F0B9EDD00955E23 /* rend_sky.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_sky.h; sourceTree = ""; }; B086FA590F0B9EDD00955E23 /* rend_sprite.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_sprite.h; sourceTree = ""; }; B086FA5A0F0B9EDD00955E23 /* s_cache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_cache.h; sourceTree = ""; }; B086FA5B0F0B9EDD00955E23 /* s_environ.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_environ.h; sourceTree = ""; }; B086FA5C0F0B9EDD00955E23 /* s_logic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_logic.h; sourceTree = ""; }; B086FA5D0F0B9EDD00955E23 /* s_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_main.h; sourceTree = ""; }; B086FA5E0F0B9EDD00955E23 /* s_mus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_mus.h; sourceTree = ""; }; B086FA5F0F0B9EDD00955E23 /* s_sfx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_sfx.h; sourceTree = ""; }; B086FA600F0B9EDD00955E23 /* s_wav.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_wav.h; sourceTree = ""; }; B086FA610F0B9EDD00955E23 /* sv_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sv_def.h; sourceTree = ""; }; B086FA620F0B9EDD00955E23 /* sv_frame.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sv_frame.h; sourceTree = ""; }; B086FA630F0B9EDD00955E23 /* sv_missile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sv_missile.h; sourceTree = ""; }; B086FA640F0B9EDD00955E23 /* sv_pool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sv_pool.h; sourceTree = ""; }; B086FA650F0B9EDD00955E23 /* sv_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sv_sound.h; sourceTree = ""; }; B086FA660F0B9EDD00955E23 /* sys_audio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_audio.h; sourceTree = ""; }; B086FA670F0B9EDD00955E23 /* sys_audiod_dummy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_audiod_dummy.h; sourceTree = ""; }; B086FA680F0B9EDD00955E23 /* sys_audiod_loader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_audiod_loader.h; sourceTree = ""; }; B086FA690F0B9EDD00955E23 /* sys_audiod_sdlmixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_audiod_sdlmixer.h; sourceTree = ""; }; B086FA6A0F0B9EDD00955E23 /* sys_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_console.h; sourceTree = ""; }; B086FA6B0F0B9EDD00955E23 /* sys_direc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_direc.h; sourceTree = ""; }; B086FA6C0F0B9EDD00955E23 /* sys_file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_file.h; sourceTree = ""; }; B086FA6D0F0B9EDD00955E23 /* sys_findfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_findfile.h; sourceTree = ""; }; B086FA6E0F0B9EDD00955E23 /* sys_input.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_input.h; sourceTree = ""; }; B086FA6F0F0B9EDD00955E23 /* sys_master.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_master.h; sourceTree = ""; }; B086FA700F0B9EDD00955E23 /* sys_mixer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_mixer.h; sourceTree = ""; }; B086FA710F0B9EDD00955E23 /* sys_network.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_network.h; sourceTree = ""; }; B086FA720F0B9EDD00955E23 /* sys_sock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_sock.h; sourceTree = ""; }; B086FA730F0B9EDD00955E23 /* sys_system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_system.h; sourceTree = ""; }; B086FA740F0B9EDD00955E23 /* sys_timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_timer.h; sourceTree = ""; }; B086FA750F0B9EDD00955E23 /* sys_window.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_window.h; sourceTree = ""; }; B086FA760F0B9EDD00955E23 /* tab_anorms.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tab_anorms.h; sourceTree = ""; }; B086FA770F0B9EDD00955E23 /* template.h.template */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = template.h.template; sourceTree = ""; }; B086FA780F0B9EDD00955E23 /* ui_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_main.h; sourceTree = ""; }; B086FA790F0B9EDE00955E23 /* ui_mpi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_mpi.h; sourceTree = ""; }; B086FA7A0F0B9EDE00955E23 /* ui_panel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ui_panel.h; sourceTree = ""; }; B086FA7C0F0B9EDE00955E23 /* b_command.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b_command.c; sourceTree = ""; }; B086FA7D0F0B9EDE00955E23 /* b_context.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b_context.c; sourceTree = ""; }; B086FA7E0F0B9EDE00955E23 /* b_device.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b_device.c; sourceTree = ""; }; B086FA7F0F0B9EDE00955E23 /* b_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b_main.c; sourceTree = ""; }; B086FA800F0B9EDE00955E23 /* b_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = b_util.c; sourceTree = ""; }; B086FA810F0B9EDE00955E23 /* bsp_edge.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsp_edge.c; sourceTree = ""; }; B086FA820F0B9EDE00955E23 /* bsp_intersection.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsp_intersection.c; sourceTree = ""; }; B086FA830F0B9EDE00955E23 /* bsp_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsp_main.c; sourceTree = ""; }; B086FA840F0B9EDE00955E23 /* bsp_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsp_map.c; sourceTree = ""; }; B086FA850F0B9EDE00955E23 /* bsp_node.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsp_node.c; sourceTree = ""; }; B086FA860F0B9EDE00955E23 /* bsp_superblock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bsp_superblock.c; sourceTree = ""; }; B086FA870F0B9EDE00955E23 /* cl_frame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_frame.c; sourceTree = ""; }; B086FA880F0B9EDE00955E23 /* cl_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_main.c; sourceTree = ""; }; B086FA890F0B9EDE00955E23 /* cl_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_mobj.c; sourceTree = ""; }; B086FA8A0F0B9EDE00955E23 /* cl_oldframe.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_oldframe.c; sourceTree = ""; }; B086FA8B0F0B9EDE00955E23 /* cl_oldworld.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_oldworld.c; sourceTree = ""; }; B086FA8C0F0B9EDE00955E23 /* cl_player.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_player.c; sourceTree = ""; }; B086FA8D0F0B9EDE00955E23 /* cl_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_sound.c; sourceTree = ""; }; B086FA8E0F0B9EDE00955E23 /* cl_world.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cl_world.c; sourceTree = ""; }; B086FA8F0F0B9EDE00955E23 /* con_bar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = con_bar.c; sourceTree = ""; }; B086FA900F0B9EDE00955E23 /* con_buffer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = con_buffer.c; sourceTree = ""; }; B086FA910F0B9EDE00955E23 /* con_busy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = con_busy.c; sourceTree = ""; }; B086FA920F0B9EDE00955E23 /* con_config.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = con_config.c; sourceTree = ""; }; B086FA930F0B9EDE00955E23 /* con_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = con_data.c; sourceTree = ""; }; B086FA940F0B9EDE00955E23 /* con_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = con_main.c; sourceTree = ""; }; B086FA950F0B9EDE00955E23 /* dam_blockmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dam_blockmap.c; sourceTree = ""; }; B086FA960F0B9EDE00955E23 /* dam_file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dam_file.c; sourceTree = ""; }; B086FA970F0B9EDE00955E23 /* dam_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dam_main.c; sourceTree = ""; }; B086FA990F0B9EDE00955E23 /* dd_help.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_help.c; sourceTree = ""; }; B086FA9A0F0B9EDE00955E23 /* dd_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_input.c; sourceTree = ""; }; B086FA9B0F0B9EDE00955E23 /* dd_loop.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_loop.c; sourceTree = ""; }; B086FA9C0F0B9EDE00955E23 /* dd_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_main.c; sourceTree = ""; }; B086FA9D0F0B9EDE00955E23 /* dd_pinit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_pinit.c; sourceTree = ""; }; B086FA9E0F0B9EDE00955E23 /* dd_plugin.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_plugin.c; sourceTree = ""; }; B086FA9F0F0B9EDE00955E23 /* dd_wad.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_wad.c; sourceTree = ""; }; B086FAA00F0B9EDE00955E23 /* dd_zip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_zip.c; sourceTree = ""; }; B086FAA10F0B9EDE00955E23 /* dd_zone.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_zone.c; sourceTree = ""; }; B086FAA20F0B9EDE00955E23 /* def_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = def_data.c; sourceTree = ""; }; B086FAA30F0B9EDE00955E23 /* def_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = def_main.c; sourceTree = ""; }; B086FAA40F0B9EDE00955E23 /* def_read.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = def_read.c; sourceTree = ""; }; B086FAA50F0B9EDE00955E23 /* dgl_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dgl_common.c; sourceTree = ""; }; B086FAA60F0B9EDE00955E23 /* dgl_draw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dgl_draw.c; sourceTree = ""; }; B086FAA80F0B9EDE00955E23 /* dgl_texture.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dgl_texture.c; sourceTree = ""; }; B086FAA90F0B9EDE00955E23 /* edit_bias.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = edit_bias.c; sourceTree = ""; }; B086FAAA0F0B9EDE00955E23 /* edit_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = edit_map.c; sourceTree = ""; }; B086FAAB0F0B9EDE00955E23 /* gl_defer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_defer.c; sourceTree = ""; }; B086FAAC0F0B9EDE00955E23 /* gl_draw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_draw.c; sourceTree = ""; }; B086FAAD0F0B9EDE00955E23 /* gl_font.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_font.c; sourceTree = ""; }; B086FAAE0F0B9EDE00955E23 /* gl_hq2x.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_hq2x.c; sourceTree = ""; }; B086FAAF0F0B9EDE00955E23 /* gl_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_main.c; sourceTree = ""; }; B086FAB00F0B9EDE00955E23 /* gl_pcx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_pcx.c; sourceTree = ""; }; B086FAB10F0B9EDE00955E23 /* gl_png.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_png.c; sourceTree = ""; }; B086FAB20F0B9EDE00955E23 /* gl_tex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_tex.c; sourceTree = ""; }; B086FAB30F0B9EDE00955E23 /* gl_texmanager.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_texmanager.c; sourceTree = ""; }; B086FAB40F0B9EDE00955E23 /* gl_tga.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = gl_tga.c; sourceTree = ""; }; B086FAB50F0B9EDE00955E23 /* m_args.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_args.c; sourceTree = ""; }; B086FAB60F0B9EDE00955E23 /* m_bams.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_bams.c; sourceTree = ""; }; B086FAB70F0B9EDE00955E23 /* m_binarytree.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_binarytree.c; sourceTree = ""; }; B086FAB80F0B9EDE00955E23 /* m_decomp64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_decomp64.c; sourceTree = ""; }; B086FAB90F0B9EDE00955E23 /* m_filehash.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_filehash.c; sourceTree = ""; }; B086FABA0F0B9EDE00955E23 /* m_gridmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_gridmap.c; sourceTree = ""; }; B086FABB0F0B9EDE00955E23 /* m_huffman.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_huffman.c; sourceTree = ""; }; B086FABC0F0B9EDE00955E23 /* m_linkedlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_linkedlist.c; sourceTree = ""; }; B086FABD0F0B9EDE00955E23 /* m_md5.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_md5.c; sourceTree = ""; }; B086FABE0F0B9EDE00955E23 /* m_misc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_misc.c; sourceTree = ""; }; B086FABF0F0B9EDE00955E23 /* m_mus2midi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_mus2midi.c; sourceTree = ""; }; B086FAC00F0B9EDE00955E23 /* m_nodepile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_nodepile.c; sourceTree = ""; }; B086FAC10F0B9EDE00955E23 /* m_string.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_string.c; sourceTree = ""; }; B086FAC20F0B9EDE00955E23 /* m_vector.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_vector.c; sourceTree = ""; }; B086FAC30F0B9EDE00955E23 /* net_buf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net_buf.c; sourceTree = ""; }; B086FAC40F0B9EDE00955E23 /* net_demo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net_demo.c; sourceTree = ""; }; B086FAC50F0B9EDE00955E23 /* net_event.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net_event.c; sourceTree = ""; }; B086FAC60F0B9EDE00955E23 /* net_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net_main.c; sourceTree = ""; }; B086FAC70F0B9EDE00955E23 /* net_msg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net_msg.c; sourceTree = ""; }; B086FAC80F0B9EDE00955E23 /* net_ping.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = net_ping.c; sourceTree = ""; }; B086FAC90F0B9EDE00955E23 /* p_bmap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_bmap.c; sourceTree = ""; }; B086FACA0F0B9EDE00955E23 /* p_cmd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_cmd.c; sourceTree = ""; }; B086FACB0F0B9EDE00955E23 /* p_control.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_control.c; sourceTree = ""; }; B086FACC0F0B9EDE00955E23 /* p_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_data.c; sourceTree = ""; }; B086FACD0F0B9EDE00955E23 /* p_dmu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_dmu.c; sourceTree = ""; }; B086FACE0F0B9EDE00955E23 /* p_intercept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_intercept.c; sourceTree = ""; }; B086FACF0F0B9EDE00955E23 /* p_linedef.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_linedef.c; sourceTree = ""; }; B086FAD00F0B9EDE00955E23 /* p_maputil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_maputil.c; sourceTree = ""; }; B086FAD10F0B9EDE00955E23 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mobj.c; sourceTree = ""; }; B086FAD20F0B9EDE00955E23 /* p_objlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_objlink.c; sourceTree = ""; }; B086FAD30F0B9EDE00955E23 /* p_particle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_particle.c; sourceTree = ""; }; B086FAD40F0B9EDE00955E23 /* p_plane.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_plane.c; sourceTree = ""; }; B086FAD50F0B9EDE00955E23 /* p_players.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_players.c; sourceTree = ""; }; B086FAD60F0B9EDE00955E23 /* p_polyob.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_polyob.c; sourceTree = ""; }; B086FAD70F0B9EDE00955E23 /* p_sector.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_sector.c; sourceTree = ""; }; B086FAD80F0B9EDE00955E23 /* p_seg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_seg.c; sourceTree = ""; }; B086FAD90F0B9EDE00955E23 /* p_sidedef.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_sidedef.c; sourceTree = ""; }; B086FADA0F0B9EDE00955E23 /* p_sight.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_sight.c; sourceTree = ""; }; B086FADB0F0B9EDE00955E23 /* p_subsector.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_subsector.c; sourceTree = ""; }; B086FADC0F0B9EDE00955E23 /* p_surface.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_surface.c; sourceTree = ""; }; B086FADD0F0B9EDE00955E23 /* p_think.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_think.c; sourceTree = ""; }; B086FADE0F0B9EDE00955E23 /* p_ticker.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_ticker.c; sourceTree = ""; }; B086FADF0F0B9EDE00955E23 /* p_vertex.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_vertex.c; sourceTree = ""; }; B086FAE00F0B9EDE00955E23 /* r_data.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_data.c; sourceTree = ""; }; B086FAE10F0B9EDE00955E23 /* r_draw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_draw.c; sourceTree = ""; }; B086FAE20F0B9EDE00955E23 /* r_extres.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_extres.c; sourceTree = ""; }; B086FAE30F0B9EDE00955E23 /* r_lgrid.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_lgrid.c; sourceTree = ""; }; B086FAE40F0B9EDE00955E23 /* r_lumobjs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_lumobjs.c; sourceTree = ""; }; B086FAE50F0B9EDE00955E23 /* r_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_main.c; sourceTree = ""; }; B086FAE70F0B9EDE00955E23 /* r_model.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_model.c; sourceTree = ""; }; B086FAE80F0B9EDE00955E23 /* r_shadow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_shadow.c; sourceTree = ""; }; B086FAE90F0B9EDE00955E23 /* r_sky.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_sky.c; sourceTree = ""; }; B086FAEA0F0B9EDE00955E23 /* r_things.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_things.c; sourceTree = ""; }; B086FAEB0F0B9EDE00955E23 /* r_util.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_util.c; sourceTree = ""; }; B086FAEC0F0B9EDE00955E23 /* r_world.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_world.c; sourceTree = ""; }; B086FAED0F0B9EDE00955E23 /* rend_bias.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_bias.c; sourceTree = ""; }; B086FAEE0F0B9EDE00955E23 /* rend_clip.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_clip.c; sourceTree = ""; }; B086FAEF0F0B9EDE00955E23 /* rend_console.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_console.c; sourceTree = ""; }; B086FAF00F0B9EDE00955E23 /* rend_decor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_decor.c; sourceTree = ""; }; B086FAF10F0B9EDE00955E23 /* rend_dyn.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_dyn.c; sourceTree = ""; }; B086FAF20F0B9EDE00955E23 /* rend_fakeradio.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_fakeradio.c; sourceTree = ""; }; B086FAF30F0B9EDE00955E23 /* rend_halo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_halo.c; sourceTree = ""; }; B086FAF40F0B9EDE00955E23 /* rend_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_list.c; sourceTree = ""; }; B086FAF50F0B9EDE00955E23 /* rend_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_main.c; sourceTree = ""; }; B086FAF60F0B9EDE00955E23 /* rend_model.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_model.c; sourceTree = ""; }; B086FAF70F0B9EDE00955E23 /* rend_particle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_particle.c; sourceTree = ""; }; B086FAF80F0B9EDE00955E23 /* rend_shadow.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_shadow.c; sourceTree = ""; }; B086FAF90F0B9EDE00955E23 /* rend_sky.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_sky.c; sourceTree = ""; }; B086FAFA0F0B9EDE00955E23 /* rend_sprite.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rend_sprite.c; sourceTree = ""; }; B086FAFB0F0B9EDE00955E23 /* s_cache.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_cache.c; sourceTree = ""; }; B086FAFC0F0B9EDE00955E23 /* s_environ.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_environ.c; sourceTree = ""; }; B086FAFD0F0B9EDE00955E23 /* s_logic.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_logic.c; sourceTree = ""; }; B086FAFE0F0B9EDE00955E23 /* s_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_main.c; sourceTree = ""; }; B086FAFF0F0B9EDE00955E23 /* s_mus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_mus.c; sourceTree = ""; }; B086FB000F0B9EDE00955E23 /* s_sfx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_sfx.c; sourceTree = ""; }; B086FB010F0B9EDE00955E23 /* s_wav.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = s_wav.c; sourceTree = ""; }; B086FB020F0B9EDE00955E23 /* sv_frame.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sv_frame.c; sourceTree = ""; }; B086FB030F0B9EDE00955E23 /* sv_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sv_main.c; sourceTree = ""; }; B086FB040F0B9EDE00955E23 /* sv_missile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sv_missile.c; sourceTree = ""; }; B086FB050F0B9EDE00955E23 /* sv_pool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sv_pool.c; sourceTree = ""; }; B086FB060F0B9EDE00955E23 /* sv_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sv_sound.c; sourceTree = ""; }; B086FB070F0B9EDE00955E23 /* sys_audiod_dummy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_audiod_dummy.c; sourceTree = ""; }; B086FB080F0B9EDE00955E23 /* sys_audiod_sdlmixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_audiod_sdlmixer.c; sourceTree = ""; }; B086FB090F0B9EDE00955E23 /* sys_direc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_direc.c; sourceTree = ""; }; B086FB0A0F0B9EDE00955E23 /* sys_filein.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_filein.c; sourceTree = ""; }; B086FB0B0F0B9EDE00955E23 /* sys_master.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_master.c; sourceTree = ""; }; B086FB0C0F0B9EDF00955E23 /* sys_network.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_network.c; sourceTree = ""; }; B086FB0D0F0B9EDF00955E23 /* sys_sdl_window.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_sdl_window.c; sourceTree = ""; }; B086FB0E0F0B9EDF00955E23 /* sys_sock.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_sock.c; sourceTree = ""; }; B086FB0F0F0B9EDF00955E23 /* sys_system.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_system.c; sourceTree = ""; }; B086FB100F0B9EDF00955E23 /* sys_timer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_timer.c; sourceTree = ""; }; B086FB110F0B9EDF00955E23 /* tab_tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tab_tables.c; sourceTree = ""; }; B086FB120F0B9EDF00955E23 /* template.c.template */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = template.c.template; sourceTree = ""; }; B086FB130F0B9EDF00955E23 /* ui_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ui_main.c; sourceTree = ""; }; B086FB140F0B9EDF00955E23 /* ui_mpi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ui_mpi.c; sourceTree = ""; }; B086FB150F0B9EDF00955E23 /* ui_panel.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ui_panel.c; sourceTree = ""; }; B086FB170F0B9EDF00955E23 /* apply-style.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "apply-style.sh"; sourceTree = ""; }; B086FB180F0B9EDF00955E23 /* definefinder.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = definefinder.sh; sourceTree = ""; }; B086FB190F0B9EDF00955E23 /* deng-header-style.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "deng-header-style.sh"; sourceTree = ""; }; B086FB1A0F0B9EDF00955E23 /* deng-style.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "deng-style.sh"; sourceTree = ""; }; B086FB1B0F0B9EDF00955E23 /* indent-typenames.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "indent-typenames.sh"; sourceTree = ""; }; B086FB1C0F0B9EDF00955E23 /* licensecheck.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = licensecheck.sh; sourceTree = ""; }; B086FB1D0F0B9EDF00955E23 /* makedmt.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = makedmt.py; sourceTree = ""; }; B086FB1E0F0B9EDF00955E23 /* mass_replace.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = mass_replace.sh; sourceTree = ""; }; B086FB210F0B9EDF00955E23 /* dd_uinit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dd_uinit.h; sourceTree = ""; }; B086FB220F0B9EDF00955E23 /* sys_dylib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_dylib.h; sourceTree = ""; }; B086FB230F0B9EDF00955E23 /* sys_findfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_findfile.h; sourceTree = ""; }; B086FB240F0B9EDF00955E23 /* sys_path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sys_path.h; sourceTree = ""; }; B086FB260F0B9EDF00955E23 /* dd_uinit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dd_uinit.c; sourceTree = ""; }; B086FB270F0B9EDF00955E23 /* sys_audiod_loader.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_audiod_loader.c; sourceTree = ""; }; B086FB280F0B9EDF00955E23 /* sys_console.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_console.c; sourceTree = ""; }; B086FB290F0B9EDF00955E23 /* sys_dylib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_dylib.c; sourceTree = ""; }; B086FB2A0F0B9EDF00955E23 /* sys_findfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_findfile.c; sourceTree = ""; }; B086FB2B0F0B9EDF00955E23 /* sys_input.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_input.c; sourceTree = ""; }; B086FB2C0F0B9EDF00955E23 /* sys_mixer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_mixer.c; sourceTree = ""; }; B086FB2D0F0B9EDF00955E23 /* sys_path.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sys_path.c; sourceTree = ""; }; B086FB450F0B9EDF00955E23 /* curl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = curl.h; sourceTree = ""; }; B086FB460F0B9EDF00955E23 /* curlver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = curlver.h; sourceTree = ""; }; B086FB470F0B9EDF00955E23 /* easy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = easy.h; sourceTree = ""; }; B086FB480F0B9EDF00955E23 /* mprintf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mprintf.h; sourceTree = ""; }; B086FB490F0B9EDF00955E23 /* multi.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multi.h; sourceTree = ""; }; B086FB4A0F0B9EDF00955E23 /* stdcheaders.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stdcheaders.h; sourceTree = ""; }; B086FB4B0F0B9EDF00955E23 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = ""; }; B086FB520F0B9EDF00955E23 /* png.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = png.h; sourceTree = ""; }; B086FB530F0B9EDF00955E23 /* pngconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pngconf.h; sourceTree = ""; }; B086FB5C0F0B9EDF00955E23 /* lzss.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lzss.h; sourceTree = ""; }; B086FB5F0F0B9EDF00955E23 /* lzss.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = lzss.c; sourceTree = ""; }; B086FB6E0F0B9EDF00955E23 /* zconf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zconf.h; sourceTree = ""; }; B086FB6F0F0B9EDF00955E23 /* zlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zlib.h; sourceTree = ""; }; B086FB780F0B9EDF00955E23 /* am_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = am_map.h; sourceTree = ""; }; B086FB7A0F0B9EDF00955E23 /* d_net.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_net.h; sourceTree = ""; }; B086FB7B0F0B9EDF00955E23 /* d_netcl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_netcl.h; sourceTree = ""; }; B086FB7C0F0B9EDF00955E23 /* d_netsv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_netsv.h; sourceTree = ""; }; B086FB7D0F0B9EDF00955E23 /* dmu_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dmu_lib.h; sourceTree = ""; }; B086FB7E0F0B9EDF00955E23 /* f_infine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = f_infine.h; sourceTree = ""; }; B086FB7F0F0B9EDF00955E23 /* g_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_common.h; sourceTree = ""; }; B086FB800F0B9EDF00955E23 /* g_controls.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_controls.h; sourceTree = ""; }; B086FB810F0B9EDF00955E23 /* g_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_defs.h; sourceTree = ""; }; B086FB820F0B9EDF00955E23 /* g_update.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_update.h; sourceTree = ""; }; B086FB830F0B9EDF00955E23 /* hu_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hu_lib.h; sourceTree = ""; }; B086FB840F0B9EDF00955E23 /* hu_log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hu_log.h; sourceTree = ""; }; B086FB850F0B9EDF00955E23 /* hu_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hu_menu.h; sourceTree = ""; }; B086FB860F0B9EDF00955E23 /* hu_msg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hu_msg.h; sourceTree = ""; }; B086FB870F0B9EDF00955E23 /* hu_pspr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hu_pspr.h; sourceTree = ""; }; B086FB880F0B9EDF00955E23 /* hu_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = hu_stuff.h; sourceTree = ""; }; B086FB890F0B9EDF00955E23 /* m_argv.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_argv.h; sourceTree = ""; }; B086FB8A0F0B9EDF00955E23 /* m_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_defs.h; sourceTree = ""; }; B086FB8B0F0B9EDF00955E23 /* p_actor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_actor.h; sourceTree = ""; }; B086FB8C0F0B9EDF00955E23 /* p_ceiling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_ceiling.h; sourceTree = ""; }; B086FB8D0F0B9EDF00955E23 /* p_door.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_door.h; sourceTree = ""; }; B086FB8E0F0B9EDF00955E23 /* p_floor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_floor.h; sourceTree = ""; }; B086FB8F0F0B9EDF00955E23 /* p_inventory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_inventory.h; sourceTree = ""; }; B086FB900F0B9EDF00955E23 /* p_iterlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_iterlist.h; sourceTree = ""; }; B086FB910F0B9EDF00955E23 /* p_map.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_map.h; sourceTree = ""; }; B086FB920F0B9EDF00955E23 /* p_mapsetup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mapsetup.h; sourceTree = ""; }; B086FB930F0B9EDF00955E23 /* p_mapspec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mapspec.h; sourceTree = ""; }; B086FB940F0B9EDF00955E23 /* p_plat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_plat.h; sourceTree = ""; }; B086FB950F0B9EDF00955E23 /* p_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_player.h; sourceTree = ""; }; B086FB960F0B9EDF00955E23 /* p_saveg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_saveg.h; sourceTree = ""; }; B086FB970F0B9EDF00955E23 /* p_start.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_start.h; sourceTree = ""; }; B086FB980F0B9EDF00955E23 /* p_svtexarc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_svtexarc.h; sourceTree = ""; }; B086FB990F0B9EDF00955E23 /* p_switch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_switch.h; sourceTree = ""; }; B086FB9A0F0B9EDF00955E23 /* p_terraintype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_terraintype.h; sourceTree = ""; }; B086FB9B0F0B9EDF00955E23 /* p_tick.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_tick.h; sourceTree = ""; }; B086FB9C0F0B9EDF00955E23 /* p_user.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_user.h; sourceTree = ""; }; B086FB9D0F0B9EDF00955E23 /* p_view.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_view.h; sourceTree = ""; }; B086FB9E0F0B9EDF00955E23 /* p_xg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_xg.h; sourceTree = ""; }; B086FB9F0F0B9EDF00955E23 /* p_xgline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_xgline.h; sourceTree = ""; }; B086FBA00F0B9EDF00955E23 /* p_xgsec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_xgsec.h; sourceTree = ""; }; B086FBA10F0B9EDF00955E23 /* r_common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_common.h; sourceTree = ""; }; B086FBA20F0B9EDF00955E23 /* st_lib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st_lib.h; sourceTree = ""; }; B086FBA30F0B9EDF00955E23 /* x_hair.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_hair.h; sourceTree = ""; }; B086FBA40F0B9EDF00955E23 /* xgclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xgclass.h; sourceTree = ""; }; B086FBA60F0B9EDF00955E23 /* am_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = am_map.c; sourceTree = ""; }; B086FBA80F0B9EDF00955E23 /* d_net.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_net.c; sourceTree = ""; }; B086FBA90F0B9EDF00955E23 /* d_netcl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_netcl.c; sourceTree = ""; }; B086FBAA0F0B9EDF00955E23 /* d_netsv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_netsv.c; sourceTree = ""; }; B086FBAB0F0B9EDF00955E23 /* dmu_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dmu_lib.c; sourceTree = ""; }; B086FBAC0F0B9EDF00955E23 /* f_infine.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = f_infine.c; sourceTree = ""; }; B086FBAD0F0B9EDF00955E23 /* g_controls.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_controls.c; sourceTree = ""; }; B086FBAE0F0B9EDF00955E23 /* g_defs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_defs.c; sourceTree = ""; }; B086FBAF0F0B9EDF00955E23 /* g_game.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_game.c; sourceTree = ""; }; B086FBB00F0B9EDF00955E23 /* g_update.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_update.c; sourceTree = ""; }; B086FBB10F0B9EDF00955E23 /* hu_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hu_lib.c; sourceTree = ""; }; B086FBB20F0B9EDF00955E23 /* hu_log.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hu_log.c; sourceTree = ""; }; B086FBB30F0B9EDF00955E23 /* hu_menu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hu_menu.c; sourceTree = ""; }; B086FBB40F0B9EDF00955E23 /* hu_msg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hu_msg.c; sourceTree = ""; }; B086FBB50F0B9EDF00955E23 /* hu_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hu_pspr.c; sourceTree = ""; }; B086FBB60F0B9EDF00955E23 /* hu_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hu_stuff.c; sourceTree = ""; }; B086FBB70F0B9EDF00955E23 /* m_ctrl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_ctrl.c; sourceTree = ""; }; B086FBB80F0B9EDF00955E23 /* m_fixed.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_fixed.c; sourceTree = ""; }; B086FBB90F0B9EDF00955E23 /* m_multi.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_multi.c; sourceTree = ""; }; B086FBBA0F0B9EDF00955E23 /* p_actor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_actor.c; sourceTree = ""; }; B086FBBB0F0B9EDF00955E23 /* p_ceiling.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_ceiling.c; sourceTree = ""; }; B086FBBC0F0B9EDF00955E23 /* p_door.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_door.c; sourceTree = ""; }; B086FBBD0F0B9EDF00955E23 /* p_floor.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_floor.c; sourceTree = ""; }; B086FBBE0F0B9EDF00955E23 /* p_inventory.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_inventory.c; sourceTree = ""; }; B086FBBF0F0B9EDF00955E23 /* p_iterlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_iterlist.c; sourceTree = ""; }; B086FBC00F0B9EDF00955E23 /* p_map.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_map.c; sourceTree = ""; }; B086FBC10F0B9EDF00955E23 /* p_mapsetup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mapsetup.c; sourceTree = ""; }; B086FBC20F0B9EDF00955E23 /* p_mapspec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mapspec.c; sourceTree = ""; }; B086FBC30F0B9EDF00955E23 /* p_plat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_plat.c; sourceTree = ""; }; B086FBC40F0B9EDF00955E23 /* p_player.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_player.c; sourceTree = ""; }; B086FBC50F0B9EDF00955E23 /* p_saveg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_saveg.c; sourceTree = ""; }; B086FBC60F0B9EDF00955E23 /* p_start.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_start.c; sourceTree = ""; }; B086FBC70F0B9EDF00955E23 /* p_svtexarc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_svtexarc.c; sourceTree = ""; }; B086FBC80F0B9EDF00955E23 /* p_switch.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_switch.c; sourceTree = ""; }; B086FBC90F0B9EDF00955E23 /* p_terraintype.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_terraintype.c; sourceTree = ""; }; B086FBCA0F0B9EDF00955E23 /* p_tick.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_tick.c; sourceTree = ""; }; B086FBCB0F0B9EDF00955E23 /* p_user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_user.c; sourceTree = ""; }; B086FBCC0F0B9EDF00955E23 /* p_view.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_view.c; sourceTree = ""; }; B086FBCD0F0B9EDF00955E23 /* p_xgfile.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_xgfile.c; sourceTree = ""; }; B086FBCE0F0B9EDF00955E23 /* p_xgline.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_xgline.c; sourceTree = ""; }; B086FBCF0F0B9EDF00955E23 /* p_xgsave.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_xgsave.c; sourceTree = ""; }; B086FBD00F0B9EDF00955E23 /* p_xgsec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_xgsec.c; sourceTree = ""; }; B086FBD10F0B9EDF00955E23 /* r_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = r_common.c; sourceTree = ""; }; B086FBD20F0B9EDF00955E23 /* st_lib.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st_lib.c; sourceTree = ""; }; B086FBD30F0B9EDF00955E23 /* x_hair.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x_hair.c; sourceTree = ""; }; B086FBD50F0B9EDF00955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FBD70F0B9EDF00955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086FBD90F0B9EDF00955E23 /* dehmain.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = dehmain.c; sourceTree = ""; }; B086FBE20F0B9EDF00955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FBE40F0B9EDF00955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086FBE50F0B9EDF00955E23 /* readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = readme.txt; sourceTree = ""; }; B086FBE70F0B9EDF00955E23 /* example.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = example.c; sourceTree = ""; }; B086FBEA0F0B9EE000955E23 /* jdoom.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jdoom.def; sourceTree = ""; }; B086FBEB0F0B9EE000955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FBED0F0B9EE000955E23 /* startup.cfg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = startup.cfg; sourceTree = ""; }; B086FBEF0F0B9EE000955E23 /* conhelp.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = conhelp.txt; sourceTree = ""; }; B086FBF10F0B9EE000955E23 /* fonta033.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta033.lmp; sourceTree = ""; }; B086FBF20F0B9EE000955E23 /* fonta034.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta034.lmp; sourceTree = ""; }; B086FBF30F0B9EE000955E23 /* fonta035.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta035.lmp; sourceTree = ""; }; B086FBF40F0B9EE000955E23 /* fonta036.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta036.lmp; sourceTree = ""; }; B086FBF50F0B9EE000955E23 /* fonta037.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta037.lmp; sourceTree = ""; }; B086FBF60F0B9EE000955E23 /* fonta038.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta038.lmp; sourceTree = ""; }; B086FBF70F0B9EE000955E23 /* fonta039.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta039.lmp; sourceTree = ""; }; B086FBF80F0B9EE000955E23 /* fonta040.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta040.lmp; sourceTree = ""; }; B086FBF90F0B9EE000955E23 /* fonta041.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta041.lmp; sourceTree = ""; }; B086FBFA0F0B9EE000955E23 /* fonta042.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta042.lmp; sourceTree = ""; }; B086FBFB0F0B9EE000955E23 /* fonta043.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta043.lmp; sourceTree = ""; }; B086FBFC0F0B9EE000955E23 /* fonta044.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta044.lmp; sourceTree = ""; }; B086FBFD0F0B9EE000955E23 /* fonta045.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta045.lmp; sourceTree = ""; }; B086FBFE0F0B9EE000955E23 /* fonta046.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta046.lmp; sourceTree = ""; }; B086FBFF0F0B9EE000955E23 /* fonta047.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta047.lmp; sourceTree = ""; }; B086FC000F0B9EE000955E23 /* fonta048.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta048.lmp; sourceTree = ""; }; B086FC010F0B9EE000955E23 /* fonta049.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta049.lmp; sourceTree = ""; }; B086FC020F0B9EE000955E23 /* fonta050.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta050.lmp; sourceTree = ""; }; B086FC030F0B9EE000955E23 /* fonta051.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta051.lmp; sourceTree = ""; }; B086FC040F0B9EE000955E23 /* fonta052.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta052.lmp; sourceTree = ""; }; B086FC050F0B9EE000955E23 /* fonta053.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta053.lmp; sourceTree = ""; }; B086FC060F0B9EE000955E23 /* fonta054.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta054.lmp; sourceTree = ""; }; B086FC070F0B9EE000955E23 /* fonta055.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta055.lmp; sourceTree = ""; }; B086FC080F0B9EE000955E23 /* fonta056.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta056.lmp; sourceTree = ""; }; B086FC090F0B9EE000955E23 /* fonta057.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta057.lmp; sourceTree = ""; }; B086FC0A0F0B9EE000955E23 /* fonta058.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta058.lmp; sourceTree = ""; }; B086FC0B0F0B9EE000955E23 /* fonta059.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta059.lmp; sourceTree = ""; }; B086FC0C0F0B9EE000955E23 /* fonta060.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta060.lmp; sourceTree = ""; }; B086FC0D0F0B9EE000955E23 /* fonta061.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta061.lmp; sourceTree = ""; }; B086FC0E0F0B9EE000955E23 /* fonta062.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta062.lmp; sourceTree = ""; }; B086FC0F0F0B9EE000955E23 /* fonta063.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta063.lmp; sourceTree = ""; }; B086FC100F0B9EE000955E23 /* fonta064.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta064.lmp; sourceTree = ""; }; B086FC110F0B9EE000955E23 /* fonta065.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta065.lmp; sourceTree = ""; }; B086FC120F0B9EE000955E23 /* fonta066.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta066.lmp; sourceTree = ""; }; B086FC130F0B9EE000955E23 /* fonta067.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta067.lmp; sourceTree = ""; }; B086FC140F0B9EE000955E23 /* fonta068.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta068.lmp; sourceTree = ""; }; B086FC150F0B9EE000955E23 /* fonta069.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta069.lmp; sourceTree = ""; }; B086FC160F0B9EE000955E23 /* fonta070.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta070.lmp; sourceTree = ""; }; B086FC170F0B9EE000955E23 /* fonta071.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta071.lmp; sourceTree = ""; }; B086FC180F0B9EE000955E23 /* fonta072.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta072.lmp; sourceTree = ""; }; B086FC190F0B9EE000955E23 /* fonta073.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta073.lmp; sourceTree = ""; }; B086FC1A0F0B9EE000955E23 /* fonta074.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta074.lmp; sourceTree = ""; }; B086FC1B0F0B9EE000955E23 /* fonta075.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta075.lmp; sourceTree = ""; }; B086FC1C0F0B9EE000955E23 /* fonta076.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta076.lmp; sourceTree = ""; }; B086FC1D0F0B9EE000955E23 /* fonta077.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta077.lmp; sourceTree = ""; }; B086FC1E0F0B9EE000955E23 /* fonta078.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta078.lmp; sourceTree = ""; }; B086FC1F0F0B9EE000955E23 /* fonta079.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta079.lmp; sourceTree = ""; }; B086FC200F0B9EE000955E23 /* fonta080.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta080.lmp; sourceTree = ""; }; B086FC210F0B9EE000955E23 /* fonta081.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta081.lmp; sourceTree = ""; }; B086FC220F0B9EE000955E23 /* fonta082.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta082.lmp; sourceTree = ""; }; B086FC230F0B9EE000955E23 /* fonta083.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta083.lmp; sourceTree = ""; }; B086FC240F0B9EE000955E23 /* fonta084.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta084.lmp; sourceTree = ""; }; B086FC250F0B9EE000955E23 /* fonta085.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta085.lmp; sourceTree = ""; }; B086FC260F0B9EE000955E23 /* fonta086.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta086.lmp; sourceTree = ""; }; B086FC270F0B9EE000955E23 /* fonta087.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta087.lmp; sourceTree = ""; }; B086FC280F0B9EE000955E23 /* fonta088.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta088.lmp; sourceTree = ""; }; B086FC290F0B9EE000955E23 /* fonta089.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta089.lmp; sourceTree = ""; }; B086FC2A0F0B9EE000955E23 /* fonta090.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta090.lmp; sourceTree = ""; }; B086FC2B0F0B9EE000955E23 /* fonta091.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta091.lmp; sourceTree = ""; }; B086FC2C0F0B9EE000955E23 /* fonta092.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta092.lmp; sourceTree = ""; }; B086FC2D0F0B9EE000955E23 /* fonta093.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta093.lmp; sourceTree = ""; }; B086FC2E0F0B9EE000955E23 /* fonta094.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta094.lmp; sourceTree = ""; }; B086FC2F0F0B9EE000955E23 /* fonta095.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta095.lmp; sourceTree = ""; }; B086FC300F0B9EE000955E23 /* fonta121.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta121.lmp; sourceTree = ""; }; B086FC310F0B9EE000955E23 /* fontb033.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb033.lmp; sourceTree = ""; }; B086FC320F0B9EE000955E23 /* fontb034.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb034.lmp; sourceTree = ""; }; B086FC330F0B9EE000955E23 /* fontb035.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb035.lmp; sourceTree = ""; }; B086FC340F0B9EE000955E23 /* fontb036.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb036.lmp; sourceTree = ""; }; B086FC350F0B9EE000955E23 /* fontb037.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb037.lmp; sourceTree = ""; }; B086FC360F0B9EE000955E23 /* fontb038.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb038.lmp; sourceTree = ""; }; B086FC370F0B9EE000955E23 /* fontb039.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb039.lmp; sourceTree = ""; }; B086FC380F0B9EE000955E23 /* fontb040.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb040.lmp; sourceTree = ""; }; B086FC390F0B9EE000955E23 /* fontb041.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb041.lmp; sourceTree = ""; }; B086FC3A0F0B9EE000955E23 /* fontb042.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb042.lmp; sourceTree = ""; }; B086FC3B0F0B9EE000955E23 /* fontb043.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb043.lmp; sourceTree = ""; }; B086FC3C0F0B9EE000955E23 /* fontb044.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb044.lmp; sourceTree = ""; }; B086FC3D0F0B9EE000955E23 /* fontb045.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb045.lmp; sourceTree = ""; }; B086FC3E0F0B9EE000955E23 /* fontb046.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb046.lmp; sourceTree = ""; }; B086FC3F0F0B9EE000955E23 /* fontb047.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb047.lmp; sourceTree = ""; }; B086FC400F0B9EE000955E23 /* fontb048.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb048.lmp; sourceTree = ""; }; B086FC410F0B9EE000955E23 /* fontb049.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb049.lmp; sourceTree = ""; }; B086FC420F0B9EE000955E23 /* fontb050.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb050.lmp; sourceTree = ""; }; B086FC430F0B9EE000955E23 /* fontb051.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb051.lmp; sourceTree = ""; }; B086FC440F0B9EE000955E23 /* fontb052.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb052.lmp; sourceTree = ""; }; B086FC450F0B9EE000955E23 /* fontb053.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb053.lmp; sourceTree = ""; }; B086FC460F0B9EE000955E23 /* fontb054.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb054.lmp; sourceTree = ""; }; B086FC470F0B9EE000955E23 /* fontb055.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb055.lmp; sourceTree = ""; }; B086FC480F0B9EE000955E23 /* fontb056.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb056.lmp; sourceTree = ""; }; B086FC490F0B9EE000955E23 /* fontb057.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb057.lmp; sourceTree = ""; }; B086FC4A0F0B9EE000955E23 /* fontb058.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb058.lmp; sourceTree = ""; }; B086FC4B0F0B9EE000955E23 /* fontb059.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb059.lmp; sourceTree = ""; }; B086FC4C0F0B9EE000955E23 /* fontb060.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb060.lmp; sourceTree = ""; }; B086FC4D0F0B9EE000955E23 /* fontb061.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb061.lmp; sourceTree = ""; }; B086FC4E0F0B9EE000955E23 /* fontb062.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb062.lmp; sourceTree = ""; }; B086FC4F0F0B9EE000955E23 /* fontb063.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb063.lmp; sourceTree = ""; }; B086FC500F0B9EE000955E23 /* fontb064.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb064.lmp; sourceTree = ""; }; B086FC510F0B9EE000955E23 /* fontb065.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb065.lmp; sourceTree = ""; }; B086FC520F0B9EE000955E23 /* fontb066.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb066.lmp; sourceTree = ""; }; B086FC530F0B9EE000955E23 /* fontb067.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb067.lmp; sourceTree = ""; }; B086FC540F0B9EE000955E23 /* fontb068.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb068.lmp; sourceTree = ""; }; B086FC550F0B9EE000955E23 /* fontb069.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb069.lmp; sourceTree = ""; }; B086FC560F0B9EE000955E23 /* fontb070.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb070.lmp; sourceTree = ""; }; B086FC570F0B9EE000955E23 /* fontb071.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb071.lmp; sourceTree = ""; }; B086FC580F0B9EE000955E23 /* fontb072.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb072.lmp; sourceTree = ""; }; B086FC590F0B9EE000955E23 /* fontb073.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb073.lmp; sourceTree = ""; }; B086FC5A0F0B9EE000955E23 /* fontb074.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb074.lmp; sourceTree = ""; }; B086FC5B0F0B9EE000955E23 /* fontb075.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb075.lmp; sourceTree = ""; }; B086FC5C0F0B9EE000955E23 /* fontb076.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb076.lmp; sourceTree = ""; }; B086FC5D0F0B9EE000955E23 /* fontb077.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb077.lmp; sourceTree = ""; }; B086FC5E0F0B9EE000955E23 /* fontb078.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb078.lmp; sourceTree = ""; }; B086FC5F0F0B9EE000955E23 /* fontb079.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb079.lmp; sourceTree = ""; }; B086FC600F0B9EE000955E23 /* fontb080.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb080.lmp; sourceTree = ""; }; B086FC610F0B9EE000955E23 /* fontb081.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb081.lmp; sourceTree = ""; }; B086FC620F0B9EE000955E23 /* fontb082.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb082.lmp; sourceTree = ""; }; B086FC630F0B9EE000955E23 /* fontb083.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb083.lmp; sourceTree = ""; }; B086FC640F0B9EE000955E23 /* fontb084.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb084.lmp; sourceTree = ""; }; B086FC650F0B9EE000955E23 /* fontb085.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb085.lmp; sourceTree = ""; }; B086FC660F0B9EE000955E23 /* fontb086.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb086.lmp; sourceTree = ""; }; B086FC670F0B9EE000955E23 /* fontb087.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb087.lmp; sourceTree = ""; }; B086FC680F0B9EE000955E23 /* fontb088.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb088.lmp; sourceTree = ""; }; B086FC690F0B9EE000955E23 /* fontb089.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb089.lmp; sourceTree = ""; }; B086FC6A0F0B9EE000955E23 /* fontb090.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb090.lmp; sourceTree = ""; }; B086FC6B0F0B9EE000955E23 /* m_therm2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = m_therm2.lmp; sourceTree = ""; }; B086FC6C0F0B9EE000955E23 /* mapmask.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = mapmask.lmp; sourceTree = ""; }; B086FC6D0F0B9EE000955E23 /* menufog.lmp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = menufog.lmp; sourceTree = ""; }; B086FC6E0F0B9EE000955E23 /* pal18to8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = pal18to8.lmp; sourceTree = ""; }; B086FC6F0F0B9EE000955E23 /* sndcurve.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = sndcurve.lmp; sourceTree = ""; }; B086FC710F0B9EE000955E23 /* anim.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = anim.ded; sourceTree = ""; }; B086FC720F0B9EE000955E23 /* audio.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = audio.ded; sourceTree = ""; }; B086FC740F0B9EE000955E23 /* Readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; B086FC750F0B9EE000955E23 /* details.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = details.ded; sourceTree = ""; }; B086FC760F0B9EE000955E23 /* doom1anim.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom1anim.ded; sourceTree = ""; }; B086FC770F0B9EE000955E23 /* doom1lights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom1lights.ded; sourceTree = ""; }; B086FC780F0B9EE000955E23 /* doom1maps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom1maps.ded; sourceTree = ""; }; B086FC790F0B9EE000955E23 /* doom1music.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom1music.ded; sourceTree = ""; }; B086FC7A0F0B9EE000955E23 /* doom2-plutlights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "doom2-plutlights.ded"; sourceTree = ""; }; B086FC7B0F0B9EE000955E23 /* doom2-plutmaps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "doom2-plutmaps.ded"; sourceTree = ""; }; B086FC7C0F0B9EE000955E23 /* doom2-tntlights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "doom2-tntlights.ded"; sourceTree = ""; }; B086FC7D0F0B9EE000955E23 /* doom2-tntmaps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "doom2-tntmaps.ded"; sourceTree = ""; }; B086FC7E0F0B9EE000955E23 /* doom2anim.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom2anim.ded; sourceTree = ""; }; B086FC7F0F0B9EE000955E23 /* doom2lights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom2lights.ded; sourceTree = ""; }; B086FC800F0B9EE000955E23 /* doom2maps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom2maps.ded; sourceTree = ""; }; B086FC810F0B9EE000955E23 /* doom2music.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = doom2music.ded; sourceTree = ""; }; B086FC820F0B9EE000955E23 /* finales.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = finales.ded; sourceTree = ""; }; B086FC830F0B9EE000955E23 /* jdoom.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jdoom.ded; sourceTree = ""; }; B086FC840F0B9EE000955E23 /* lights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lights.ded; sourceTree = ""; }; B086FC850F0B9EE000955E23 /* maps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = maps.ded; sourceTree = ""; }; B086FC860F0B9EE000955E23 /* objects.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = objects.ded; sourceTree = ""; }; B086FC870F0B9EE000955E23 /* particles.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = particles.ded; sourceTree = ""; }; B086FC880F0B9EE000955E23 /* plutanim.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = plutanim.ded; sourceTree = ""; }; B086FC890F0B9EE000955E23 /* plutfinales.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = plutfinales.ded; sourceTree = ""; }; B086FC8A0F0B9EE000955E23 /* special.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = special.ded; sourceTree = ""; }; B086FC8B0F0B9EE000955E23 /* sprites.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = sprites.ded; sourceTree = ""; }; B086FC8C0F0B9EE000955E23 /* text.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text.ded; sourceTree = ""; }; B086FC8D0F0B9EE000955E23 /* tntfinales.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = tntfinales.ded; sourceTree = ""; }; B086FC8E0F0B9EE000955E23 /* values.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = values.ded; sourceTree = ""; }; B086FC900F0B9EE000955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086FC920F0B9EE000955E23 /* acfnlink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acfnlink.h; sourceTree = ""; }; B086FC930F0B9EE000955E23 /* d_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_api.h; sourceTree = ""; }; B086FC940F0B9EE000955E23 /* d_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_config.h; sourceTree = ""; }; B086FC950F0B9EE000955E23 /* d_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_console.h; sourceTree = ""; }; B086FC960F0B9EE000955E23 /* d_englsh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_englsh.h; sourceTree = ""; }; B086FC970F0B9EE000955E23 /* d_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_event.h; sourceTree = ""; }; B086FC980F0B9EE000955E23 /* d_items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_items.h; sourceTree = ""; }; B086FC990F0B9EE000955E23 /* d_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_main.h; sourceTree = ""; }; B086FC9A0F0B9EE000955E23 /* d_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_player.h; sourceTree = ""; }; B086FC9B0F0B9EE000955E23 /* d_refresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_refresh.h; sourceTree = ""; }; B086FC9C0F0B9EE000955E23 /* d_think.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_think.h; sourceTree = ""; }; B086FC9D0F0B9EE000955E23 /* doomdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomdata.h; sourceTree = ""; }; B086FC9E0F0B9EE000955E23 /* doomdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomdef.h; sourceTree = ""; }; B086FC9F0F0B9EE000955E23 /* doomtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomtype.h; sourceTree = ""; }; B086FCA00F0B9EE000955E23 /* dstrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dstrings.h; sourceTree = ""; }; B086FCA10F0B9EE000955E23 /* g_ctrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_ctrl.h; sourceTree = ""; }; B086FCA20F0B9EE000955E23 /* g_game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_game.h; sourceTree = ""; }; B086FCA30F0B9EE000955E23 /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = info.h; sourceTree = ""; }; B086FCA40F0B9EE000955E23 /* jdoom.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdoom.h; sourceTree = ""; }; B086FCA50F0B9EE000955E23 /* m_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_cheat.h; sourceTree = ""; }; B086FCA60F0B9EE000955E23 /* m_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_menu.h; sourceTree = ""; }; B086FCA70F0B9EE000955E23 /* m_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_random.h; sourceTree = ""; }; B086FCA80F0B9EE000955E23 /* mn_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mn_def.h; sourceTree = ""; }; B086FCA90F0B9EE000955E23 /* oldinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oldinfo.h; sourceTree = ""; }; B086FCAA0F0B9EE000955E23 /* p_enemy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_enemy.h; sourceTree = ""; }; B086FCAB0F0B9EE000955E23 /* p_inter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_inter.h; sourceTree = ""; }; B086FCAC0F0B9EE000955E23 /* p_lights.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_lights.h; sourceTree = ""; }; B086FCAD0F0B9EE000955E23 /* p_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_local.h; sourceTree = ""; }; B086FCAE0F0B9EE000955E23 /* p_maputl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_maputl.h; sourceTree = ""; }; B086FCAF0F0B9EE000955E23 /* p_mobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mobj.h; sourceTree = ""; }; B086FCB00F0B9EE000955E23 /* p_oldsvg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_oldsvg.h; sourceTree = ""; }; B086FCB10F0B9EE000955E23 /* p_pspr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_pspr.h; sourceTree = ""; }; B086FCB20F0B9EE000955E23 /* p_setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_setup.h; sourceTree = ""; }; B086FCB30F0B9EE000955E23 /* p_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_sound.h; sourceTree = ""; }; B086FCB40F0B9EE000955E23 /* p_spec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_spec.h; sourceTree = ""; }; B086FCB50F0B9EE000955E23 /* p_telept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_telept.h; sourceTree = ""; }; B086FCB60F0B9EE000955E23 /* r_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_defs.h; sourceTree = ""; }; B086FCB70F0B9EE000955E23 /* st_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st_stuff.h; sourceTree = ""; }; B086FCB80F0B9EE000955E23 /* tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tables.h; sourceTree = ""; }; B086FCB90F0B9EE000955E23 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; B086FCBA0F0B9EE000955E23 /* wi_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wi_stuff.h; sourceTree = ""; }; B086FCBC0F0B9EE000955E23 /* jdoom.dll.manifest */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = jdoom.dll.manifest; sourceTree = ""; }; B086FCBD0F0B9EE000955E23 /* jdoom.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = jdoom.ico; sourceTree = ""; }; B086FCBE0F0B9EE000955E23 /* jdoom.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jdoom.rc; sourceTree = ""; }; B086FCBF0F0B9EE000955E23 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; B086FCC10F0B9EE000955E23 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acfnlink.c; sourceTree = ""; }; B086FCC20F0B9EE000955E23 /* d_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_api.c; sourceTree = ""; }; B086FCC30F0B9EE000955E23 /* d_console.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_console.c; sourceTree = ""; }; B086FCC40F0B9EE000955E23 /* d_items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_items.c; sourceTree = ""; }; B086FCC50F0B9EE000955E23 /* d_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_main.c; sourceTree = ""; }; B086FCC60F0B9EE000955E23 /* d_refresh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_refresh.c; sourceTree = ""; }; B086FCC70F0B9EE000955E23 /* g_ctrl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_ctrl.c; sourceTree = ""; }; B086FCC80F0B9EE000955E23 /* m_cheat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_cheat.c; sourceTree = ""; }; B086FCC90F0B9EE000955E23 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_random.c; sourceTree = ""; }; B086FCCA0F0B9EE000955E23 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_enemy.c; sourceTree = ""; }; B086FCCB0F0B9EE000955E23 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_inter.c; sourceTree = ""; }; B086FCCC0F0B9EE000955E23 /* p_lights.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_lights.c; sourceTree = ""; }; B086FCCD0F0B9EE000955E23 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_maputl.c; sourceTree = ""; }; B086FCCE0F0B9EE000955E23 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mobj.c; sourceTree = ""; }; B086FCCF0F0B9EE000955E23 /* p_oldsvg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_oldsvg.c; sourceTree = ""; }; B086FCD00F0B9EE000955E23 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_pspr.c; sourceTree = ""; }; B086FCD10F0B9EE000955E23 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_setup.c; sourceTree = ""; }; B086FCD20F0B9EE000955E23 /* p_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_sound.c; sourceTree = ""; }; B086FCD30F0B9EE000955E23 /* p_spec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_spec.c; sourceTree = ""; }; B086FCD40F0B9EE000955E23 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_telept.c; sourceTree = ""; }; B086FCD50F0B9EE000955E23 /* st_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st_stuff.c; sourceTree = ""; }; B086FCD60F0B9EE000955E23 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tables.c; sourceTree = ""; }; B086FCD70F0B9EE000955E23 /* wi_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wi_stuff.c; sourceTree = ""; }; B086FCDA0F0B9EE000955E23 /* jdoom64.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jdoom64.def; sourceTree = ""; }; B086FCDB0F0B9EE000955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FCDD0F0B9EE000955E23 /* startup.cfg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = startup.cfg; sourceTree = ""; }; B086FCDF0F0B9EE000955E23 /* conhelp.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = conhelp.txt; sourceTree = ""; }; B086FCE10F0B9EE000955E23 /* m_therm2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = m_therm2.lmp; sourceTree = ""; }; B086FCE20F0B9EE000955E23 /* mapmask.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = mapmask.lmp; sourceTree = ""; }; B086FCE30F0B9EE000955E23 /* menufog.lmp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = menufog.lmp; sourceTree = ""; }; B086FCE40F0B9EE000955E23 /* pal18to8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = pal18to8.lmp; sourceTree = ""; }; B086FCE50F0B9EE000955E23 /* sndcurve.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = sndcurve.lmp; sourceTree = ""; }; B086FCE70F0B9EE100955E23 /* anim.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = anim.ded; sourceTree = ""; }; B086FCE80F0B9EE100955E23 /* audio.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = audio.ded; sourceTree = ""; }; B086FCEA0F0B9EE100955E23 /* Readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; B086FCEB0F0B9EE100955E23 /* d2_ogg_Audio.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = d2_ogg_Audio.ded; sourceTree = ""; }; B086FCEC0F0B9EE100955E23 /* decorlights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = decorlights.ded; sourceTree = ""; }; B086FCED0F0B9EE100955E23 /* finales.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = finales.ded; sourceTree = ""; }; B086FCEE0F0B9EE100955E23 /* jdoom64.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jdoom64.ded; sourceTree = ""; }; B086FCEF0F0B9EE100955E23 /* lights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lights.ded; sourceTree = ""; }; B086FCF00F0B9EE100955E23 /* maps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = maps.ded; sourceTree = ""; }; B086FCF10F0B9EE100955E23 /* objects.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = objects.ded; sourceTree = ""; }; B086FCF20F0B9EE100955E23 /* particles.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = particles.ded; sourceTree = ""; }; B086FCF30F0B9EE100955E23 /* special.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = special.ded; sourceTree = ""; }; B086FCF40F0B9EE100955E23 /* sprites.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = sprites.ded; sourceTree = ""; }; B086FCF50F0B9EE100955E23 /* text.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text.ded; sourceTree = ""; }; B086FCF60F0B9EE100955E23 /* values.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = values.ded; sourceTree = ""; }; B086FCF80F0B9EE100955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086FCFA0F0B9EE100955E23 /* acfnlink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acfnlink.h; sourceTree = ""; }; B086FCFB0F0B9EE100955E23 /* d_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_api.h; sourceTree = ""; }; B086FCFC0F0B9EE100955E23 /* d_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_config.h; sourceTree = ""; }; B086FCFD0F0B9EE100955E23 /* d_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_console.h; sourceTree = ""; }; B086FCFE0F0B9EE100955E23 /* d_englsh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_englsh.h; sourceTree = ""; }; B086FCFF0F0B9EE100955E23 /* d_items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_items.h; sourceTree = ""; }; B086FD000F0B9EE100955E23 /* d_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_main.h; sourceTree = ""; }; B086FD010F0B9EE100955E23 /* d_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_player.h; sourceTree = ""; }; B086FD020F0B9EE100955E23 /* d_refresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_refresh.h; sourceTree = ""; }; B086FD030F0B9EE100955E23 /* d_think.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = d_think.h; sourceTree = ""; }; B086FD040F0B9EE100955E23 /* doomdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomdef.h; sourceTree = ""; }; B086FD050F0B9EE100955E23 /* doomtype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomtype.h; sourceTree = ""; }; B086FD060F0B9EE100955E23 /* dstrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dstrings.h; sourceTree = ""; }; B086FD070F0B9EE100955E23 /* g_ctrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_ctrl.h; sourceTree = ""; }; B086FD080F0B9EE100955E23 /* g_game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_game.h; sourceTree = ""; }; B086FD090F0B9EE100955E23 /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = info.h; sourceTree = ""; }; B086FD0A0F0B9EE100955E23 /* jdoom64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jdoom64.h; sourceTree = ""; }; B086FD0B0F0B9EE100955E23 /* m_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_cheat.h; sourceTree = ""; }; B086FD0C0F0B9EE100955E23 /* m_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_menu.h; sourceTree = ""; }; B086FD0D0F0B9EE100955E23 /* m_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_random.h; sourceTree = ""; }; B086FD0E0F0B9EE100955E23 /* mn_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mn_def.h; sourceTree = ""; }; B086FD0F0F0B9EE100955E23 /* p_enemy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_enemy.h; sourceTree = ""; }; B086FD100F0B9EE100955E23 /* p_inter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_inter.h; sourceTree = ""; }; B086FD110F0B9EE100955E23 /* p_lights.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_lights.h; sourceTree = ""; }; B086FD120F0B9EE100955E23 /* p_maputl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_maputl.h; sourceTree = ""; }; B086FD130F0B9EE100955E23 /* p_mobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mobj.h; sourceTree = ""; }; B086FD140F0B9EE100955E23 /* p_pspr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_pspr.h; sourceTree = ""; }; B086FD150F0B9EE100955E23 /* p_setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_setup.h; sourceTree = ""; }; B086FD160F0B9EE100955E23 /* p_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_sound.h; sourceTree = ""; }; B086FD170F0B9EE100955E23 /* p_spec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_spec.h; sourceTree = ""; }; B086FD180F0B9EE100955E23 /* p_telept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_telept.h; sourceTree = ""; }; B086FD190F0B9EE100955E23 /* r_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_defs.h; sourceTree = ""; }; B086FD1A0F0B9EE100955E23 /* st_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st_stuff.h; sourceTree = ""; }; B086FD1B0F0B9EE100955E23 /* tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tables.h; sourceTree = ""; }; B086FD1C0F0B9EE100955E23 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; B086FD1D0F0B9EE100955E23 /* wi_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wi_stuff.h; sourceTree = ""; }; B086FD1F0F0B9EE100955E23 /* jdoom64.dll.manifest */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = jdoom64.dll.manifest; sourceTree = ""; }; B086FD200F0B9EE100955E23 /* jdoom64.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = jdoom64.ico; sourceTree = ""; }; B086FD210F0B9EE100955E23 /* jdoom64.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jdoom64.rc; sourceTree = ""; }; B086FD220F0B9EE100955E23 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; B086FD240F0B9EE100955E23 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acfnlink.c; sourceTree = ""; }; B086FD250F0B9EE100955E23 /* d_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_api.c; sourceTree = ""; }; B086FD260F0B9EE100955E23 /* d_console.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_console.c; sourceTree = ""; }; B086FD270F0B9EE100955E23 /* d_items.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_items.c; sourceTree = ""; }; B086FD280F0B9EE100955E23 /* d_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_main.c; sourceTree = ""; }; B086FD290F0B9EE100955E23 /* d_refresh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = d_refresh.c; sourceTree = ""; }; B086FD2A0F0B9EE100955E23 /* g_ctrl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_ctrl.c; sourceTree = ""; }; B086FD2B0F0B9EE100955E23 /* m_cheat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_cheat.c; sourceTree = ""; }; B086FD2C0F0B9EE100955E23 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_random.c; sourceTree = ""; }; B086FD2D0F0B9EE100955E23 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_enemy.c; sourceTree = ""; }; B086FD2E0F0B9EE100955E23 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_inter.c; sourceTree = ""; }; B086FD2F0F0B9EE100955E23 /* p_lights.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_lights.c; sourceTree = ""; }; B086FD300F0B9EE100955E23 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_maputl.c; sourceTree = ""; }; B086FD310F0B9EE100955E23 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mobj.c; sourceTree = ""; }; B086FD320F0B9EE100955E23 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_pspr.c; sourceTree = ""; }; B086FD330F0B9EE100955E23 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_setup.c; sourceTree = ""; }; B086FD340F0B9EE100955E23 /* p_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_sound.c; sourceTree = ""; }; B086FD350F0B9EE100955E23 /* p_spec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_spec.c; sourceTree = ""; }; B086FD360F0B9EE100955E23 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_telept.c; sourceTree = ""; }; B086FD370F0B9EE100955E23 /* st_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st_stuff.c; sourceTree = ""; }; B086FD380F0B9EE100955E23 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tables.c; sourceTree = ""; }; B086FD390F0B9EE100955E23 /* wi_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wi_stuff.c; sourceTree = ""; }; B086FD3C0F0B9EE100955E23 /* jheretic.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jheretic.def; sourceTree = ""; }; B086FD3D0F0B9EE100955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FD3F0F0B9EE100955E23 /* startup.cfg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = startup.cfg; sourceTree = ""; }; B086FD410F0B9EE100955E23 /* conhelp.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = conhelp.txt; sourceTree = ""; }; B086FD430F0B9EE100955E23 /* e2endpcx.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = e2endpcx.lmp; sourceTree = ""; }; B086FD440F0B9EE100955E23 /* fonta59.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta59.lmp; sourceTree = ""; }; B086FD450F0B9EE100955E23 /* fonta60.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta60.lmp; sourceTree = ""; }; B086FD460F0B9EE100955E23 /* fonta61.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta61.lmp; sourceTree = ""; }; B086FD470F0B9EE100955E23 /* fonta62.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta62.lmp; sourceTree = ""; }; B086FD480F0B9EE100955E23 /* fonta63.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta63.lmp; sourceTree = ""; }; B086FD490F0B9EE100955E23 /* fontb59.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb59.lmp; sourceTree = ""; }; B086FD4A0F0B9EE100955E23 /* fontb60.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb60.lmp; sourceTree = ""; }; B086FD4B0F0B9EE100955E23 /* fontb61.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb61.lmp; sourceTree = ""; }; B086FD4C0F0B9EE100955E23 /* fontb62.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb62.lmp; sourceTree = ""; }; B086FD4D0F0B9EE100955E23 /* fontb63.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb63.lmp; sourceTree = ""; }; B086FD4E0F0B9EE100955E23 /* mapmask.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = mapmask.lmp; sourceTree = ""; }; B086FD4F0F0B9EE100955E23 /* menufog.lmp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = menufog.lmp; sourceTree = ""; }; B086FD500F0B9EE100955E23 /* pal18to8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = pal18to8.lmp; sourceTree = ""; }; B086FD520F0B9EE100955E23 /* anim.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = anim.ded; sourceTree = ""; }; B086FD530F0B9EE100955E23 /* audio.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = audio.ded; sourceTree = ""; }; B086FD550F0B9EE100955E23 /* Readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; B086FD560F0B9EE100955E23 /* finales.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = finales.ded; sourceTree = ""; }; B086FD570F0B9EE100955E23 /* jheretic.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jheretic.ded; sourceTree = ""; }; B086FD580F0B9EE100955E23 /* lights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lights.ded; sourceTree = ""; }; B086FD590F0B9EE100955E23 /* maps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = maps.ded; sourceTree = ""; }; B086FD5A0F0B9EE100955E23 /* models.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = models.ded; sourceTree = ""; }; B086FD5B0F0B9EE100955E23 /* objects.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = objects.ded; sourceTree = ""; }; B086FD5C0F0B9EE100955E23 /* special.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = special.ded; sourceTree = ""; }; B086FD5D0F0B9EE100955E23 /* sprites.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = sprites.ded; sourceTree = ""; }; B086FD5E0F0B9EE100955E23 /* text.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text.ded; sourceTree = ""; }; B086FD600F0B9EE100955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086FD610F0B9EE100955E23 /* Models.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Models.txt; sourceTree = ""; }; B086FD630F0B9EE100955E23 /* acfnlink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acfnlink.h; sourceTree = ""; }; B086FD640F0B9EE100955E23 /* doomdata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomdata.h; sourceTree = ""; }; B086FD650F0B9EE100955E23 /* doomdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = doomdef.h; sourceTree = ""; }; B086FD660F0B9EE100955E23 /* dstrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dstrings.h; sourceTree = ""; }; B086FD670F0B9EE100955E23 /* g_ctrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_ctrl.h; sourceTree = ""; }; B086FD680F0B9EE100955E23 /* g_game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_game.h; sourceTree = ""; }; B086FD690F0B9EE100955E23 /* h_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_api.h; sourceTree = ""; }; B086FD6A0F0B9EE100955E23 /* h_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_config.h; sourceTree = ""; }; B086FD6B0F0B9EE100955E23 /* h_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_console.h; sourceTree = ""; }; B086FD6C0F0B9EE100955E23 /* h_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_event.h; sourceTree = ""; }; B086FD6D0F0B9EE100955E23 /* h_items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_items.h; sourceTree = ""; }; B086FD6E0F0B9EE100955E23 /* h_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_main.h; sourceTree = ""; }; B086FD6F0F0B9EE100955E23 /* h_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_player.h; sourceTree = ""; }; B086FD700F0B9EE100955E23 /* h_refresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_refresh.h; sourceTree = ""; }; B086FD710F0B9EE100955E23 /* h_stat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_stat.h; sourceTree = ""; }; B086FD720F0B9EE100955E23 /* h_think.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_think.h; sourceTree = ""; }; B086FD730F0B9EE100955E23 /* h_type.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h_type.h; sourceTree = ""; }; B086FD740F0B9EE100955E23 /* in_lude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = in_lude.h; sourceTree = ""; }; B086FD750F0B9EE100955E23 /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = info.h; sourceTree = ""; }; B086FD760F0B9EE100955E23 /* jheretic.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jheretic.h; sourceTree = ""; }; B086FD770F0B9EE100955E23 /* m_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_cheat.h; sourceTree = ""; }; B086FD780F0B9EE100955E23 /* m_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_menu.h; sourceTree = ""; }; B086FD790F0B9EE100955E23 /* m_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_random.h; sourceTree = ""; }; B086FD7A0F0B9EE100955E23 /* mn_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mn_def.h; sourceTree = ""; }; B086FD7B0F0B9EE100955E23 /* p_enemy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_enemy.h; sourceTree = ""; }; B086FD7C0F0B9EE100955E23 /* p_inter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_inter.h; sourceTree = ""; }; B086FD7D0F0B9EE100955E23 /* p_lights.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_lights.h; sourceTree = ""; }; B086FD7E0F0B9EE100955E23 /* p_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_local.h; sourceTree = ""; }; B086FD7F0F0B9EE100955E23 /* p_maputl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_maputl.h; sourceTree = ""; }; B086FD800F0B9EE100955E23 /* p_mobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mobj.h; sourceTree = ""; }; B086FD810F0B9EE100955E23 /* p_oldsvg.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_oldsvg.h; sourceTree = ""; }; B086FD820F0B9EE100955E23 /* p_pspr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_pspr.h; sourceTree = ""; }; B086FD830F0B9EE100955E23 /* p_setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_setup.h; sourceTree = ""; }; B086FD840F0B9EE100955E23 /* p_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_sound.h; sourceTree = ""; }; B086FD850F0B9EE100955E23 /* p_spec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_spec.h; sourceTree = ""; }; B086FD860F0B9EE100955E23 /* p_telept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_telept.h; sourceTree = ""; }; B086FD870F0B9EE100955E23 /* r_data.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_data.h; sourceTree = ""; }; B086FD880F0B9EE100955E23 /* r_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_defs.h; sourceTree = ""; }; B086FD890F0B9EE100955E23 /* r_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_local.h; sourceTree = ""; }; B086FD8A0F0B9EE100955E23 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; B086FD8B0F0B9EE100955E23 /* st_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st_stuff.h; sourceTree = ""; }; B086FD8C0F0B9EE100955E23 /* tables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tables.h; sourceTree = ""; }; B086FD8D0F0B9EE100955E23 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; B086FD8F0F0B9EE100955E23 /* jheretic.dll.manifest */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = jheretic.dll.manifest; sourceTree = ""; }; B086FD900F0B9EE100955E23 /* jheretic.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = jheretic.ico; sourceTree = ""; }; B086FD910F0B9EE100955E23 /* jheretic.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jheretic.rc; sourceTree = ""; }; B086FD920F0B9EE100955E23 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; B086FD940F0B9EE100955E23 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acfnlink.c; sourceTree = ""; }; B086FD950F0B9EE100955E23 /* g_ctrl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_ctrl.c; sourceTree = ""; }; B086FD960F0B9EE100955E23 /* h_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = h_api.c; sourceTree = ""; }; B086FD970F0B9EE100955E23 /* h_console.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = h_console.c; sourceTree = ""; }; B086FD980F0B9EE100955E23 /* h_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = h_main.c; sourceTree = ""; }; B086FD990F0B9EE100955E23 /* h_refresh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = h_refresh.c; sourceTree = ""; }; B086FD9A0F0B9EE100955E23 /* in_lude.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = in_lude.c; sourceTree = ""; }; B086FD9B0F0B9EE100955E23 /* m_cheat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_cheat.c; sourceTree = ""; }; B086FD9C0F0B9EE100955E23 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_random.c; sourceTree = ""; }; B086FD9D0F0B9EE100955E23 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_enemy.c; sourceTree = ""; }; B086FD9E0F0B9EE100955E23 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_inter.c; sourceTree = ""; }; B086FD9F0F0B9EE100955E23 /* p_lights.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_lights.c; sourceTree = ""; }; B086FDA00F0B9EE100955E23 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_maputl.c; sourceTree = ""; }; B086FDA10F0B9EE100955E23 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mobj.c; sourceTree = ""; }; B086FDA20F0B9EE100955E23 /* p_oldsvg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_oldsvg.c; sourceTree = ""; }; B086FDA30F0B9EE100955E23 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_pspr.c; sourceTree = ""; }; B086FDA40F0B9EE100955E23 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_setup.c; sourceTree = ""; }; B086FDA50F0B9EE100955E23 /* p_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_sound.c; sourceTree = ""; }; B086FDA60F0B9EE100955E23 /* p_spec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_spec.c; sourceTree = ""; }; B086FDA70F0B9EE100955E23 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_telept.c; sourceTree = ""; }; B086FDA80F0B9EE100955E23 /* st_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st_stuff.c; sourceTree = ""; }; B086FDA90F0B9EE100955E23 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tables.c; sourceTree = ""; }; B086FDAC0F0B9EE100955E23 /* jhexen.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jhexen.def; sourceTree = ""; }; B086FDAD0F0B9EE100955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FDAF0F0B9EE100955E23 /* startup.cfg */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = startup.cfg; sourceTree = ""; }; B086FDB10F0B9EE100955E23 /* conhelp.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = conhelp.txt; sourceTree = ""; }; B086FDB30F0B9EE100955E23 /* armslot1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = armslot1.lmp; sourceTree = ""; }; B086FDB40F0B9EE100955E23 /* armslot2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = armslot2.lmp; sourceTree = ""; }; B086FDB50F0B9EE100955E23 /* armslot3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = armslot3.lmp; sourceTree = ""; }; B086FDB60F0B9EE100955E23 /* armslot4.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = armslot4.lmp; sourceTree = ""; }; B086FDB70F0B9EE100955E23 /* chain.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = chain.lmp; sourceTree = ""; }; B086FDB80F0B9EE100955E23 /* chain2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = chain2.lmp; sourceTree = ""; }; B086FDB90F0B9EE100955E23 /* chain3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = chain3.lmp; sourceTree = ""; }; B086FDBA0F0B9EE100955E23 /* fonta59.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta59.lmp; sourceTree = ""; }; B086FDBB0F0B9EE100955E23 /* fonta60.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta60.lmp; sourceTree = ""; }; B086FDBC0F0B9EE100955E23 /* fonta61.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta61.lmp; sourceTree = ""; }; B086FDBD0F0B9EE100955E23 /* fonta62.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta62.lmp; sourceTree = ""; }; B086FDBE0F0B9EE100955E23 /* fonta63.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fonta63.lmp; sourceTree = ""; }; B086FDBF0F0B9EE100955E23 /* fontb59.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb59.lmp; sourceTree = ""; }; B086FDC00F0B9EE100955E23 /* fontb60.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb60.lmp; sourceTree = ""; }; B086FDC10F0B9EE100955E23 /* fontb61.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb61.lmp; sourceTree = ""; }; B086FDC20F0B9EE100955E23 /* fontb62.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb62.lmp; sourceTree = ""; }; B086FDC30F0B9EE100955E23 /* fontb63.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = fontb63.lmp; sourceTree = ""; }; B086FDC40F0B9EE100955E23 /* keyslot1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot1.lmp; sourceTree = ""; }; B086FDC50F0B9EE100955E23 /* keyslot2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot2.lmp; sourceTree = ""; }; B086FDC60F0B9EE100955E23 /* keyslot3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot3.lmp; sourceTree = ""; }; B086FDC70F0B9EE100955E23 /* keyslot4.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot4.lmp; sourceTree = ""; }; B086FDC80F0B9EE100955E23 /* keyslot5.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot5.lmp; sourceTree = ""; }; B086FDC90F0B9EE100955E23 /* keyslot6.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot6.lmp; sourceTree = ""; }; B086FDCA0F0B9EE100955E23 /* keyslot7.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot7.lmp; sourceTree = ""; }; B086FDCB0F0B9EE100955E23 /* keyslot8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot8.lmp; sourceTree = ""; }; B086FDCC0F0B9EE100955E23 /* keyslot9.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslot9.lmp; sourceTree = ""; }; B086FDCD0F0B9EE100955E23 /* keyslota.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslota.lmp; sourceTree = ""; }; B086FDCE0F0B9EE100955E23 /* keyslotb.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = keyslotb.lmp; sourceTree = ""; }; B086FDCF0F0B9EE100955E23 /* lifegem.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegem.lmp; sourceTree = ""; }; B086FDD00F0B9EE100955E23 /* lifegmc1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc1.lmp; sourceTree = ""; }; B086FDD10F0B9EE100955E23 /* lifegmc2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc2.lmp; sourceTree = ""; }; B086FDD20F0B9EE100955E23 /* lifegmc3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc3.lmp; sourceTree = ""; }; B086FDD30F0B9EE100955E23 /* lifegmc4.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc4.lmp; sourceTree = ""; }; B086FDD40F0B9EE200955E23 /* lifegmc5.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc5.lmp; sourceTree = ""; }; B086FDD50F0B9EE200955E23 /* lifegmc6.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc6.lmp; sourceTree = ""; }; B086FDD60F0B9EE200955E23 /* lifegmc7.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc7.lmp; sourceTree = ""; }; B086FDD70F0B9EE200955E23 /* lifegmc8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmc8.lmp; sourceTree = ""; }; B086FDD80F0B9EE200955E23 /* lifegmf2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmf2.lmp; sourceTree = ""; }; B086FDD90F0B9EE200955E23 /* lifegmf3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmf3.lmp; sourceTree = ""; }; B086FDDA0F0B9EE200955E23 /* lifegmf4.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmf4.lmp; sourceTree = ""; }; B086FDDB0F0B9EE200955E23 /* lifegmf5.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmf5.lmp; sourceTree = ""; }; B086FDDC0F0B9EE200955E23 /* lifegmf6.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmf6.lmp; sourceTree = ""; }; B086FDDD0F0B9EE200955E23 /* lifegmf7.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmf7.lmp; sourceTree = ""; }; B086FDDE0F0B9EE200955E23 /* lifegmf8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmf8.lmp; sourceTree = ""; }; B086FDDF0F0B9EE200955E23 /* lifegmm1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm1.lmp; sourceTree = ""; }; B086FDE00F0B9EE200955E23 /* lifegmm2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm2.lmp; sourceTree = ""; }; B086FDE10F0B9EE200955E23 /* lifegmm3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm3.lmp; sourceTree = ""; }; B086FDE20F0B9EE200955E23 /* lifegmm4.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm4.lmp; sourceTree = ""; }; B086FDE30F0B9EE200955E23 /* lifegmm5.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm5.lmp; sourceTree = ""; }; B086FDE40F0B9EE200955E23 /* lifegmm6.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm6.lmp; sourceTree = ""; }; B086FDE50F0B9EE200955E23 /* lifegmm7.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm7.lmp; sourceTree = ""; }; B086FDE60F0B9EE200955E23 /* lifegmm8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = lifegmm8.lmp; sourceTree = ""; }; B086FDE70F0B9EE200955E23 /* mapmask.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = mapmask.lmp; sourceTree = ""; }; B086FDE80F0B9EE200955E23 /* menufog.lmp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = menufog.lmp; sourceTree = ""; }; B086FDE90F0B9EE200955E23 /* pal18to8.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = pal18to8.lmp; sourceTree = ""; }; B086FDEA0F0B9EE200955E23 /* travlpic.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = travlpic.lmp; sourceTree = ""; }; B086FDEB0F0B9EE200955E23 /* wpfull0.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpfull0.lmp; sourceTree = ""; }; B086FDEC0F0B9EE200955E23 /* wpfull1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpfull1.lmp; sourceTree = ""; }; B086FDED0F0B9EE200955E23 /* wpfull2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpfull2.lmp; sourceTree = ""; }; B086FDEE0F0B9EE200955E23 /* wpiecec1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecec1.lmp; sourceTree = ""; }; B086FDEF0F0B9EE200955E23 /* wpiecec2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecec2.lmp; sourceTree = ""; }; B086FDF00F0B9EE200955E23 /* wpiecec3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecec3.lmp; sourceTree = ""; }; B086FDF10F0B9EE200955E23 /* wpiecef1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecef1.lmp; sourceTree = ""; }; B086FDF20F0B9EE200955E23 /* wpiecef2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecef2.lmp; sourceTree = ""; }; B086FDF30F0B9EE200955E23 /* wpiecef3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecef3.lmp; sourceTree = ""; }; B086FDF40F0B9EE200955E23 /* wpiecem1.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecem1.lmp; sourceTree = ""; }; B086FDF50F0B9EE200955E23 /* wpiecem2.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecem2.lmp; sourceTree = ""; }; B086FDF60F0B9EE200955E23 /* wpiecem3.lmp */ = {isa = PBXFileReference; lastKnownFileType = file; path = wpiecem3.lmp; sourceTree = ""; }; B086FDF80F0B9EE200955E23 /* anim.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = anim.ded; sourceTree = ""; }; B086FDF90F0B9EE200955E23 /* audio.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = audio.ded; sourceTree = ""; }; B086FDFB0F0B9EE200955E23 /* Readme.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Readme.txt; sourceTree = ""; }; B086FDFC0F0B9EE200955E23 /* finales.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = finales.ded; sourceTree = ""; }; B086FDFD0F0B9EE200955E23 /* jhexen.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jhexen.ded; sourceTree = ""; }; B086FDFE0F0B9EE200955E23 /* lights.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = lights.ded; sourceTree = ""; }; B086FDFF0F0B9EE200955E23 /* maps.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = maps.ded; sourceTree = ""; }; B086FE000F0B9EE200955E23 /* models.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = models.ded; sourceTree = ""; }; B086FE010F0B9EE200955E23 /* objects.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = objects.ded; sourceTree = ""; }; B086FE020F0B9EE200955E23 /* special.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = special.ded; sourceTree = ""; }; B086FE030F0B9EE200955E23 /* sprites.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = sprites.ded; sourceTree = ""; }; B086FE040F0B9EE200955E23 /* text.ded */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text.ded; sourceTree = ""; }; B086FE060F0B9EE200955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086FE070F0B9EE200955E23 /* Models.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Models.txt; sourceTree = ""; }; B086FE090F0B9EE200955E23 /* a_action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = a_action.h; sourceTree = ""; }; B086FE0A0F0B9EE200955E23 /* acfnlink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = acfnlink.h; sourceTree = ""; }; B086FE0B0F0B9EE200955E23 /* dstrings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dstrings.h; sourceTree = ""; }; B086FE0C0F0B9EE200955E23 /* g_ctrl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_ctrl.h; sourceTree = ""; }; B086FE0D0F0B9EE200955E23 /* g_game.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = g_game.h; sourceTree = ""; }; B086FE0E0F0B9EE200955E23 /* h2def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = h2def.h; sourceTree = ""; }; B086FE0F0F0B9EE200955E23 /* in_lude.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = in_lude.h; sourceTree = ""; }; B086FE100F0B9EE200955E23 /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = info.h; sourceTree = ""; }; B086FE110F0B9EE200955E23 /* jhexen.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = jhexen.h; sourceTree = ""; }; B086FE120F0B9EE200955E23 /* m_cheat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_cheat.h; sourceTree = ""; }; B086FE130F0B9EE200955E23 /* m_menu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_menu.h; sourceTree = ""; }; B086FE140F0B9EE200955E23 /* m_random.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = m_random.h; sourceTree = ""; }; B086FE150F0B9EE200955E23 /* mn_def.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mn_def.h; sourceTree = ""; }; B086FE160F0B9EE200955E23 /* p_acs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_acs.h; sourceTree = ""; }; B086FE170F0B9EE200955E23 /* p_anim.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_anim.h; sourceTree = ""; }; B086FE180F0B9EE200955E23 /* p_enemy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_enemy.h; sourceTree = ""; }; B086FE190F0B9EE200955E23 /* p_inter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_inter.h; sourceTree = ""; }; B086FE1A0F0B9EE200955E23 /* p_lights.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_lights.h; sourceTree = ""; }; B086FE1B0F0B9EE200955E23 /* p_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_local.h; sourceTree = ""; }; B086FE1C0F0B9EE200955E23 /* p_mapinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mapinfo.h; sourceTree = ""; }; B086FE1D0F0B9EE200955E23 /* p_maputl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_maputl.h; sourceTree = ""; }; B086FE1E0F0B9EE200955E23 /* p_mobj.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_mobj.h; sourceTree = ""; }; B086FE1F0F0B9EE200955E23 /* p_pillar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_pillar.h; sourceTree = ""; }; B086FE200F0B9EE200955E23 /* p_pspr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_pspr.h; sourceTree = ""; }; B086FE210F0B9EE200955E23 /* p_setup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_setup.h; sourceTree = ""; }; B086FE220F0B9EE200955E23 /* p_sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_sound.h; sourceTree = ""; }; B086FE230F0B9EE200955E23 /* p_spec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_spec.h; sourceTree = ""; }; B086FE240F0B9EE200955E23 /* p_telept.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_telept.h; sourceTree = ""; }; B086FE250F0B9EE200955E23 /* p_things.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_things.h; sourceTree = ""; }; B086FE260F0B9EE200955E23 /* p_waggle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_waggle.h; sourceTree = ""; }; B086FE270F0B9EE200955E23 /* po_man.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = po_man.h; sourceTree = ""; }; B086FE280F0B9EE200955E23 /* r_defs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_defs.h; sourceTree = ""; }; B086FE290F0B9EE200955E23 /* r_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = r_local.h; sourceTree = ""; }; B086FE2A0F0B9EE200955E23 /* s_sequence.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = s_sequence.h; sourceTree = ""; }; B086FE2B0F0B9EE200955E23 /* sc_man.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sc_man.h; sourceTree = ""; }; B086FE2C0F0B9EE200955E23 /* st_stuff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = st_stuff.h; sourceTree = ""; }; B086FE2D0F0B9EE200955E23 /* textdefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = textdefs.h; sourceTree = ""; }; B086FE2E0F0B9EE200955E23 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; B086FE2F0F0B9EE200955E23 /* x_api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_api.h; sourceTree = ""; }; B086FE300F0B9EE200955E23 /* x_config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_config.h; sourceTree = ""; }; B086FE310F0B9EE200955E23 /* x_console.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_console.h; sourceTree = ""; }; B086FE320F0B9EE200955E23 /* x_event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_event.h; sourceTree = ""; }; B086FE330F0B9EE200955E23 /* x_items.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_items.h; sourceTree = ""; }; B086FE340F0B9EE200955E23 /* x_main.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_main.h; sourceTree = ""; }; B086FE350F0B9EE200955E23 /* x_player.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_player.h; sourceTree = ""; }; B086FE360F0B9EE200955E23 /* x_refresh.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_refresh.h; sourceTree = ""; }; B086FE370F0B9EE200955E23 /* x_state.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_state.h; sourceTree = ""; }; B086FE380F0B9EE200955E23 /* x_think.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x_think.h; sourceTree = ""; }; B086FE390F0B9EE200955E23 /* xddefs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xddefs.h; sourceTree = ""; }; B086FE3B0F0B9EE200955E23 /* jhexen.dll.manifest */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = jhexen.dll.manifest; sourceTree = ""; }; B086FE3C0F0B9EE200955E23 /* jhexen.ico */ = {isa = PBXFileReference; lastKnownFileType = image.ico; path = jhexen.ico; sourceTree = ""; }; B086FE3D0F0B9EE200955E23 /* jhexen.rc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = jhexen.rc; sourceTree = ""; }; B086FE3E0F0B9EE200955E23 /* resource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = resource.h; sourceTree = ""; }; B086FE400F0B9EE200955E23 /* a_action.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = a_action.c; sourceTree = ""; }; B086FE410F0B9EE200955E23 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = acfnlink.c; sourceTree = ""; }; B086FE420F0B9EE200955E23 /* g_ctrl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = g_ctrl.c; sourceTree = ""; }; B086FE430F0B9EE200955E23 /* h2_main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = h2_main.c; sourceTree = ""; }; B086FE440F0B9EE200955E23 /* hconsole.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hconsole.c; sourceTree = ""; }; B086FE450F0B9EE200955E23 /* hrefresh.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = hrefresh.c; sourceTree = ""; }; B086FE460F0B9EE200955E23 /* in_lude.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = in_lude.c; sourceTree = ""; }; B086FE470F0B9EE200955E23 /* m_cheat.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_cheat.c; sourceTree = ""; }; B086FE480F0B9EE200955E23 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = m_random.c; sourceTree = ""; }; B086FE490F0B9EE200955E23 /* p_acs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_acs.c; sourceTree = ""; }; B086FE4A0F0B9EE200955E23 /* p_anim.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_anim.c; sourceTree = ""; }; B086FE4B0F0B9EE200955E23 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_enemy.c; sourceTree = ""; }; B086FE4C0F0B9EE200955E23 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_inter.c; sourceTree = ""; }; B086FE4D0F0B9EE200955E23 /* p_lights.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_lights.c; sourceTree = ""; }; B086FE4E0F0B9EE200955E23 /* p_mapinfo.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mapinfo.c; sourceTree = ""; }; B086FE4F0F0B9EE200955E23 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_maputl.c; sourceTree = ""; }; B086FE500F0B9EE200955E23 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_mobj.c; sourceTree = ""; }; B086FE510F0B9EE200955E23 /* p_pillar.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_pillar.c; sourceTree = ""; }; B086FE520F0B9EE200955E23 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_pspr.c; sourceTree = ""; }; B086FE530F0B9EE200955E23 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_setup.c; sourceTree = ""; }; B086FE540F0B9EE200955E23 /* p_sound.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_sound.c; sourceTree = ""; }; B086FE550F0B9EE200955E23 /* p_spec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_spec.c; sourceTree = ""; }; B086FE560F0B9EE200955E23 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_telept.c; sourceTree = ""; }; B086FE570F0B9EE200955E23 /* p_things.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_things.c; sourceTree = ""; }; B086FE580F0B9EE200955E23 /* p_waggle.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = p_waggle.c; sourceTree = ""; }; B086FE590F0B9EE200955E23 /* po_man.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = po_man.c; sourceTree = ""; }; B086FE5A0F0B9EE200955E23 /* sc_man.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sc_man.c; sourceTree = ""; }; B086FE5B0F0B9EE200955E23 /* sn_sonix.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = sn_sonix.c; sourceTree = ""; }; B086FE5C0F0B9EE200955E23 /* st_stuff.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = st_stuff.c; sourceTree = ""; }; B086FE5D0F0B9EE200955E23 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tables.c; sourceTree = ""; }; B086FE5E0F0B9EE200955E23 /* x_api.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x_api.c; sourceTree = ""; }; B086FE610F0B9EE200955E23 /* dsopenal.def */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = dsopenal.def; sourceTree = ""; }; B086FE620F0B9EE200955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FE640F0B9EE200955E23 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; B086FE660F0B9EE200955E23 /* driver_openal.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = driver_openal.c; sourceTree = ""; }; B086FE680F0B9EE200955E23 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = ""; }; B086FE6A0F0B9EE200955E23 /* wadmapconverter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = wadmapconverter.h; sourceTree = ""; }; B086FE6C0F0B9EE200955E23 /* load.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = load.c; sourceTree = ""; }; B086FE6D0F0B9EE200955E23 /* wadmapconverter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = wadmapconverter.c; sourceTree = ""; }; B0A1E6B10EA9C21A00D85079 /* CMakeLists.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = CMakeLists.txt; path = ../../CMakeLists.txt; sourceTree = SOURCE_ROOT; }; B0A8094D06F1F45D007AEB2E /* Read Me.rtf */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; path = "Read Me.rtf"; sourceTree = ""; }; B0EE23170F52051600D49358 /* p_automap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = p_automap.h; sourceTree = ""; }; B0EE23180F52051600D49358 /* rend_automap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rend_automap.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXGroup section */ 29B97314FDCFA39411CA2CEA /* Doomsday */ = { isa = PBXGroup; children = ( B086F9640F0B9EDD00955E23 /* engine */, B086FB3E0F0B9EDF00955E23 /* external */, B086FB750F0B9EDF00955E23 /* plugins */, B0A1E6B10EA9C21A00D85079 /* CMakeLists.txt */, B0A8094D06F1F45D007AEB2E /* Read Me.rtf */, ); name = Doomsday; sourceTree = ""; }; B086F9640F0B9EDD00955E23 /* engine */ = { isa = PBXGroup; children = ( B086F9650F0B9EDD00955E23 /* api */, B086F9700F0B9EDD00955E23 /* data */, B086F99D0F0B9EDD00955E23 /* defs */, B086F9A10F0B9EDD00955E23 /* doc */, B086F9B80F0B9EDD00955E23 /* mac */, B086F9C70F0B9EDD00955E23 /* portable */, B086FB160F0B9EDF00955E23 /* scripts */, B086FB1F0F0B9EDF00955E23 /* unix */, ); name = engine; path = ../../engine; sourceTree = SOURCE_ROOT; }; B086F9650F0B9EDD00955E23 /* api */ = { isa = PBXGroup; children = ( B086F9660F0B9EDD00955E23 /* dd_api.h */, B086F9670F0B9EDD00955E23 /* dd_maptypes.h */, B086F9680F0B9EDD00955E23 /* dd_plugin.h */, B086F9690F0B9EDD00955E23 /* dd_share.h */, B086F96A0F0B9EDD00955E23 /* dd_types.h */, B086F96B0F0B9EDD00955E23 /* doomsday.def */, B086F96C0F0B9EDD00955E23 /* doomsday.h */, B086F96D0F0B9EDD00955E23 /* sys_audiod.h */, B086F96E0F0B9EDD00955E23 /* sys_audiod_mus.h */, B086F96F0F0B9EDD00955E23 /* sys_audiod_sfx.h */, ); path = api; sourceTree = ""; }; B086F9700F0B9EDD00955E23 /* data */ = { isa = PBXGroup; children = ( B086F9710F0B9EDD00955E23 /* cphelp.txt */, B086F9720F0B9EDD00955E23 /* fonts */, B086F9810F0B9EDD00955E23 /* graphics */, B086F9990F0B9EDD00955E23 /* keymaps */, ); path = data; sourceTree = ""; }; B086F9720F0B9EDD00955E23 /* fonts */ = { isa = PBXGroup; children = ( B086F9730F0B9EDD00955E23 /* console11.dfn */, B086F9740F0B9EDD00955E23 /* console14.dfn */, B086F9750F0B9EDD00955E23 /* console18.dfn */, B086F9760F0B9EDD00955E23 /* fixed.dfn */, B086F9770F0B9EDD00955E23 /* normal12.dfn */, B086F9780F0B9EDD00955E23 /* normal18.dfn */, B086F9790F0B9EDD00955E23 /* normal24.dfn */, B086F97A0F0B9EDD00955E23 /* normalbold12.dfn */, B086F97B0F0B9EDD00955E23 /* normalbold18.dfn */, B086F97C0F0B9EDD00955E23 /* normalbold24.dfn */, B086F97D0F0B9EDD00955E23 /* normallight12.dfn */, B086F97E0F0B9EDD00955E23 /* normallight18.dfn */, B086F97F0F0B9EDD00955E23 /* normallight24.dfn */, B086F9800F0B9EDD00955E23 /* readme.txt */, ); path = fonts; sourceTree = ""; }; B086F9810F0B9EDD00955E23 /* graphics */ = { isa = PBXGroup; children = ( B086F9820F0B9EDD00955E23 /* background.pcx */, B086F9830F0B9EDD00955E23 /* bbox.pcx */, B086F9840F0B9EDD00955E23 /* bigflare.pcx */, B086F9850F0B9EDD00955E23 /* boxcorner.png */, B086F9860F0B9EDD00955E23 /* boxfill.png */, B086F9870F0B9EDD00955E23 /* boxshade.png */, B086F9880F0B9EDD00955E23 /* brflare.pcx */, B086F9890F0B9EDD00955E23 /* dlight.pcx */, B086F98A0F0B9EDD00955E23 /* flare.pcx */, B086F98B0F0B9EDD00955E23 /* gray.png */, B086F98C0F0B9EDD00955E23 /* hint.png */, B086F98D0F0B9EDD00955E23 /* loading1.png */, B086F98E0F0B9EDD00955E23 /* loading2.png */, B086F98F0F0B9EDD00955E23 /* logo.png */, B086F9900F0B9EDD00955E23 /* missing.png */, B086F9910F0B9EDD00955E23 /* mouse.png */, B086F9920F0B9EDD00955E23 /* radiocc.pcx */, B086F9930F0B9EDD00955E23 /* radioco.pcx */, B086F9940F0B9EDD00955E23 /* radiooe.pcx */, B086F9950F0B9EDD00955E23 /* radiooo.pcx */, B086F9960F0B9EDD00955E23 /* unknown.png */, B086F9970F0B9EDD00955E23 /* wallglow.pcx */, B086F9980F0B9EDD00955E23 /* zeroth.pcx */, ); path = graphics; sourceTree = ""; }; B086F9990F0B9EDD00955E23 /* keymaps */ = { isa = PBXGroup; children = ( B086F99A0F0B9EDD00955E23 /* de.dkm */, B086F99B0F0B9EDD00955E23 /* default.dkm */, B086F99C0F0B9EDD00955E23 /* fi.dkm */, ); path = keymaps; sourceTree = ""; }; B086F99D0F0B9EDD00955E23 /* defs */ = { isa = PBXGroup; children = ( B086F99E0F0B9EDD00955E23 /* doomsday.ded */, B086F99F0F0B9EDD00955E23 /* flags.ded */, B086F9A00F0B9EDD00955E23 /* xg.ded */, ); path = defs; sourceTree = ""; }; B086F9A10F0B9EDD00955E23 /* doc */ = { isa = PBXGroup; children = ( B086F9A20F0B9EDD00955E23 /* ame */, B086F9AC0F0B9EDD00955E23 /* banner.txt */, B086F9AD0F0B9EDD00955E23 /* changelog.txt */, B086F9AE0F0B9EDD00955E23 /* cnsname.txt */, B086F9AF0F0B9EDD00955E23 /* cvars.txt */, B086F9B00F0B9EDD00955E23 /* deddoc.txt */, B086F9B10F0B9EDD00955E23 /* dhistory.txt */, B086F9B20F0B9EDD00955E23 /* doomsday.6 */, B086F9B30F0B9EDD00955E23 /* dss.txt */, B086F9B40F0B9EDD00955E23 /* LICENSE */, B086F9B50F0B9EDD00955E23 /* manpage.xml */, B086F9B60F0B9EDD00955E23 /* naming.txt */, B086F9B70F0B9EDD00955E23 /* network.txt */, ); path = doc; sourceTree = ""; }; B086F9A20F0B9EDD00955E23 /* ame */ = { isa = PBXGroup; children = ( B086F9A30F0B9EDD00955E23 /* beginner.ame */, B086F9A40F0B9EDD00955E23 /* cmdline.ame */, B086F9A50F0B9EDD00955E23 /* darktable.ame */, B086F9A60F0B9EDD00955E23 /* dedref.ame */, B086F9A70F0B9EDD00955E23 /* infine.ame */, B086F9A80F0B9EDD00955E23 /* jake.ah */, B086F9A90F0B9EDD00955E23 /* make.bat */, B086F9AA0F0B9EDD00955E23 /* readme.ame */, B086F9AB0F0B9EDD00955E23 /* version2.ame */, ); path = ame; sourceTree = ""; }; B086F9B80F0B9EDD00955E23 /* mac */ = { isa = PBXGroup; children = ( B086F9B90F0B9EDD00955E23 /* include */, B086F9BD0F0B9EDD00955E23 /* res */, B086F9C20F0B9EDD00955E23 /* src */, ); path = mac; sourceTree = ""; }; B086F9B90F0B9EDD00955E23 /* include */ = { isa = PBXGroup; children = ( B086F9BA0F0B9EDD00955E23 /* DoomsdayRunner.h */, B086F9BB0F0B9EDD00955E23 /* SDLMain.h */, B086F9BC0F0B9EDD00955E23 /* StartupWindowController.h */, ); path = include; sourceTree = ""; }; B086F9BD0F0B9EDD00955E23 /* res */ = { isa = PBXGroup; children = ( B086F9BE0F0B9EDD00955E23 /* deng.icns */, B086F9BF0F0B9EDD00955E23 /* InfoPlist.strings */, B086F9C10F0B9EDD00955E23 /* Startup.nib */, ); path = res; sourceTree = ""; }; B086F9C20F0B9EDD00955E23 /* src */ = { isa = PBXGroup; children = ( B086F9C30F0B9EDD00955E23 /* DoomsdayRunner.m */, B086F9C40F0B9EDD00955E23 /* qt.c */, B086F9C50F0B9EDD00955E23 /* SDLMain.m */, B086F9C60F0B9EDD00955E23 /* StartupWindowController.m */, ); path = src; sourceTree = ""; }; B086F9C70F0B9EDD00955E23 /* portable */ = { isa = PBXGroup; children = ( B086F9C80F0B9EDD00955E23 /* include */, B086FA7B0F0B9EDE00955E23 /* src */, ); path = portable; sourceTree = ""; }; B086F9C80F0B9EDD00955E23 /* include */ = { isa = PBXGroup; children = ( B07918630F2E282100A5A0C0 /* m_stack.h */, B07918640F2E282100A5A0C0 /* p_material.h */, B07918650F2E282100A5A0C0 /* p_materialmanager.h */, B07918660F2E282100A5A0C0 /* sys_opengl.h */, B086F9C90F0B9EDD00955E23 /* b_command.h */, B086F9CA0F0B9EDD00955E23 /* b_context.h */, B086F9CB0F0B9EDD00955E23 /* b_device.h */, B086F9CC0F0B9EDD00955E23 /* b_main.h */, B086F9CD0F0B9EDD00955E23 /* b_util.h */, B086F9CE0F0B9EDD00955E23 /* bsp_edge.h */, B086F9CF0F0B9EDD00955E23 /* bsp_intersection.h */, B086F9D00F0B9EDD00955E23 /* bsp_main.h */, B086F9D10F0B9EDD00955E23 /* bsp_map.h */, B086F9D20F0B9EDD00955E23 /* bsp_node.h */, B086F9D30F0B9EDD00955E23 /* bsp_superblock.h */, B086F9D40F0B9EDD00955E23 /* cl_def.h */, B086F9D50F0B9EDD00955E23 /* cl_frame.h */, B086F9D60F0B9EDD00955E23 /* cl_mobj.h */, B086F9D70F0B9EDD00955E23 /* cl_player.h */, B086F9D80F0B9EDD00955E23 /* cl_sound.h */, B086F9D90F0B9EDD00955E23 /* cl_world.h */, B086F9DA0F0B9EDD00955E23 /* con_bar.h */, B086F9DB0F0B9EDD00955E23 /* con_bind.h */, B086F9DC0F0B9EDD00955E23 /* con_buffer.h */, B086F9DD0F0B9EDD00955E23 /* con_busy.h */, B086F9DE0F0B9EDD00955E23 /* con_config.h */, B086F9DF0F0B9EDD00955E23 /* con_decl.h */, B086F9E00F0B9EDD00955E23 /* con_main.h */, B086F9E10F0B9EDD00955E23 /* dam_blockmap.h */, B086F9E20F0B9EDD00955E23 /* dam_file.h */, B086F9E30F0B9EDD00955E23 /* dam_main.h */, B086F9E40F0B9EDD00955E23 /* dam_reject.h */, B086F9E50F0B9EDD00955E23 /* dd_def.h */, B086F9E60F0B9EDD00955E23 /* dd_help.h */, B086F9E70F0B9EDD00955E23 /* dd_input.h */, B086F9E80F0B9EDD00955E23 /* dd_loop.h */, B086F9E90F0B9EDD00955E23 /* dd_main.h */, B086F9EA0F0B9EDD00955E23 /* dd_pinit.h */, B086F9EB0F0B9EDD00955E23 /* dd_version.h */, B086F9EC0F0B9EDD00955E23 /* dd_wad.h */, B086F9ED0F0B9EDD00955E23 /* dd_zip.h */, B086F9EE0F0B9EDD00955E23 /* dd_zone.h */, B086F9EF0F0B9EDD00955E23 /* de_audio.h */, B086F9F00F0B9EDD00955E23 /* de_base.h */, B086F9F10F0B9EDD00955E23 /* de_bsp.h */, B086F9F20F0B9EDD00955E23 /* de_console.h */, B086F9F30F0B9EDD00955E23 /* de_dam.h */, B086F9F40F0B9EDD00955E23 /* de_defs.h */, B086F9F50F0B9EDD00955E23 /* de_dgl.h */, B086F9F60F0B9EDD00955E23 /* de_edit.h */, B086F9F70F0B9EDD00955E23 /* de_graphics.h */, B086F9F80F0B9EDD00955E23 /* de_misc.h */, B086F9F90F0B9EDD00955E23 /* de_network.h */, B086F9FA0F0B9EDD00955E23 /* de_platform.h */, B086F9FB0F0B9EDD00955E23 /* de_play.h */, B086F9FC0F0B9EDD00955E23 /* de_refresh.h */, B086F9FD0F0B9EDD00955E23 /* de_render.h */, B086F9FE0F0B9EDD00955E23 /* de_system.h */, B086F9FF0F0B9EDD00955E23 /* de_ui.h */, B086FA000F0B9EDD00955E23 /* def_data.h */, B086FA010F0B9EDD00955E23 /* def_main.h */, B086FA020F0B9EDD00955E23 /* def_share.h */, B086FA030F0B9EDD00955E23 /* dgl_atiext.h */, B086FA040F0B9EDD00955E23 /* edit_bias.h */, B086FA050F0B9EDD00955E23 /* edit_map.h */, B086FA060F0B9EDD00955E23 /* gl_defer.h */, B086FA070F0B9EDD00955E23 /* gl_draw.h */, B086FA080F0B9EDD00955E23 /* gl_font.h */, B086FA090F0B9EDD00955E23 /* gl_hq2x.h */, B086FA0A0F0B9EDD00955E23 /* gl_main.h */, B086FA0B0F0B9EDD00955E23 /* gl_model.h */, B086FA0C0F0B9EDD00955E23 /* gl_pcx.h */, B086FA0D0F0B9EDD00955E23 /* gl_png.h */, B086FA0E0F0B9EDD00955E23 /* gl_tex.h */, B086FA0F0F0B9EDD00955E23 /* gl_texmanager.h */, B086FA100F0B9EDD00955E23 /* gl_tga.h */, B086FA110F0B9EDD00955E23 /* m_args.h */, B086FA120F0B9EDD00955E23 /* m_bams.h */, B086FA130F0B9EDD00955E23 /* m_binarytree.h */, B086FA140F0B9EDD00955E23 /* m_decomp64.h */, B086FA150F0B9EDD00955E23 /* m_filehash.h */, B086FA160F0B9EDD00955E23 /* m_gridmap.h */, B086FA170F0B9EDD00955E23 /* m_huffman.h */, B086FA180F0B9EDD00955E23 /* m_linkedlist.h */, B086FA190F0B9EDD00955E23 /* m_md5.h */, B086FA1A0F0B9EDD00955E23 /* m_misc.h */, B086FA1B0F0B9EDD00955E23 /* m_mus2midi.h */, B086FA1C0F0B9EDD00955E23 /* m_nodepile.h */, B086FA1D0F0B9EDD00955E23 /* m_profiler.h */, B086FA1E0F0B9EDD00955E23 /* m_string.h */, B086FA1F0F0B9EDD00955E23 /* m_vector.h */, B086FA200F0B9EDD00955E23 /* mapdata.hs */, B086FA210F0B9EDD00955E23 /* net_buf.h */, B086FA220F0B9EDD00955E23 /* net_demo.h */, B086FA230F0B9EDD00955E23 /* net_event.h */, B086FA240F0B9EDD00955E23 /* net_main.h */, B086FA250F0B9EDD00955E23 /* net_msg.h */, B086FA260F0B9EDD00955E23 /* p_bmap.h */, B086FA270F0B9EDD00955E23 /* p_cmd.h */, B086FA280F0B9EDD00955E23 /* p_control.h */, B086FA290F0B9EDD00955E23 /* p_dmu.h */, B086FA2A0F0B9EDD00955E23 /* p_intercept.h */, B086FA2B0F0B9EDD00955E23 /* p_linedef.h */, B086FA2C0F0B9EDD00955E23 /* p_mapdata.h */, B086FA2D0F0B9EDD00955E23 /* p_maptypes.h */, B086FA2E0F0B9EDD00955E23 /* p_maputil.h */, B086FA2F0F0B9EDD00955E23 /* p_object.h */, B086FA300F0B9EDD00955E23 /* p_objlink.h */, B086FA310F0B9EDD00955E23 /* p_particle.h */, B086FA320F0B9EDD00955E23 /* p_plane.h */, B086FA330F0B9EDD00955E23 /* p_players.h */, B086FA340F0B9EDD00955E23 /* p_polyob.h */, B086FA350F0B9EDD00955E23 /* p_polyobj.h */, B086FA360F0B9EDD00955E23 /* p_sector.h */, B086FA370F0B9EDD00955E23 /* p_seg.h */, B086FA380F0B9EDD00955E23 /* p_sidedef.h */, B086FA390F0B9EDD00955E23 /* p_sight.h */, B086FA3A0F0B9EDD00955E23 /* p_subsector.h */, B086FA3B0F0B9EDD00955E23 /* p_surface.h */, B086FA3C0F0B9EDD00955E23 /* p_think.h */, B086FA3D0F0B9EDD00955E23 /* p_ticker.h */, B086FA3E0F0B9EDD00955E23 /* p_vertex.h */, B086FA3F0F0B9EDD00955E23 /* r_data.h */, B086FA400F0B9EDD00955E23 /* r_draw.h */, B086FA410F0B9EDD00955E23 /* r_extres.h */, B086FA420F0B9EDD00955E23 /* r_lgrid.h */, B086FA430F0B9EDD00955E23 /* r_lumobjs.h */, B086FA440F0B9EDD00955E23 /* r_main.h */, B086FA450F0B9EDD00955E23 /* r_materials.h */, B086FA460F0B9EDD00955E23 /* r_model.h */, B086FA470F0B9EDD00955E23 /* r_shadow.h */, B086FA480F0B9EDD00955E23 /* r_sky.h */, B086FA490F0B9EDD00955E23 /* r_things.h */, B086FA4A0F0B9EDD00955E23 /* r_util.h */, B086FA4B0F0B9EDD00955E23 /* r_world.h */, B086FA4C0F0B9EDD00955E23 /* rend_bias.h */, B086FA4D0F0B9EDD00955E23 /* rend_clip.h */, B086FA4E0F0B9EDD00955E23 /* rend_console.h */, B086FA4F0F0B9EDD00955E23 /* rend_decor.h */, B086FA500F0B9EDD00955E23 /* rend_dyn.h */, B086FA510F0B9EDD00955E23 /* rend_fakeradio.h */, B086FA520F0B9EDD00955E23 /* rend_halo.h */, B086FA530F0B9EDD00955E23 /* rend_list.h */, B086FA540F0B9EDD00955E23 /* rend_main.h */, B086FA550F0B9EDD00955E23 /* rend_model.h */, B086FA560F0B9EDD00955E23 /* rend_particle.h */, B086FA570F0B9EDD00955E23 /* rend_shadow.h */, B086FA580F0B9EDD00955E23 /* rend_sky.h */, B086FA590F0B9EDD00955E23 /* rend_sprite.h */, B086FA5A0F0B9EDD00955E23 /* s_cache.h */, B086FA5B0F0B9EDD00955E23 /* s_environ.h */, B086FA5C0F0B9EDD00955E23 /* s_logic.h */, B086FA5D0F0B9EDD00955E23 /* s_main.h */, B086FA5E0F0B9EDD00955E23 /* s_mus.h */, B086FA5F0F0B9EDD00955E23 /* s_sfx.h */, B086FA600F0B9EDD00955E23 /* s_wav.h */, B086FA610F0B9EDD00955E23 /* sv_def.h */, B086FA620F0B9EDD00955E23 /* sv_frame.h */, B086FA630F0B9EDD00955E23 /* sv_missile.h */, B086FA640F0B9EDD00955E23 /* sv_pool.h */, B086FA650F0B9EDD00955E23 /* sv_sound.h */, B086FA660F0B9EDD00955E23 /* sys_audio.h */, B086FA670F0B9EDD00955E23 /* sys_audiod_dummy.h */, B086FA680F0B9EDD00955E23 /* sys_audiod_loader.h */, B086FA690F0B9EDD00955E23 /* sys_audiod_sdlmixer.h */, B086FA6A0F0B9EDD00955E23 /* sys_console.h */, B086FA6B0F0B9EDD00955E23 /* sys_direc.h */, B086FA6C0F0B9EDD00955E23 /* sys_file.h */, B086FA6D0F0B9EDD00955E23 /* sys_findfile.h */, B086FA6E0F0B9EDD00955E23 /* sys_input.h */, B086FA6F0F0B9EDD00955E23 /* sys_master.h */, B086FA700F0B9EDD00955E23 /* sys_mixer.h */, B086FA710F0B9EDD00955E23 /* sys_network.h */, B086FA720F0B9EDD00955E23 /* sys_sock.h */, B086FA730F0B9EDD00955E23 /* sys_system.h */, B086FA740F0B9EDD00955E23 /* sys_timer.h */, B086FA750F0B9EDD00955E23 /* sys_window.h */, B086FA760F0B9EDD00955E23 /* tab_anorms.h */, B086FA770F0B9EDD00955E23 /* template.h.template */, B086FA780F0B9EDD00955E23 /* ui_main.h */, B086FA790F0B9EDE00955E23 /* ui_mpi.h */, B086FA7A0F0B9EDE00955E23 /* ui_panel.h */, ); path = include; sourceTree = ""; }; B086FA7B0F0B9EDE00955E23 /* src */ = { isa = PBXGroup; children = ( B079185E0F2E280400A5A0C0 /* m_stack.c */, B079185F0F2E280400A5A0C0 /* p_material.c */, B07918600F2E280400A5A0C0 /* p_materialmanager.c */, B07918610F2E280400A5A0C0 /* sys_opengl.c */, B086FA7C0F0B9EDE00955E23 /* b_command.c */, B086FA7D0F0B9EDE00955E23 /* b_context.c */, B086FA7E0F0B9EDE00955E23 /* b_device.c */, B086FA7F0F0B9EDE00955E23 /* b_main.c */, B086FA800F0B9EDE00955E23 /* b_util.c */, B086FA810F0B9EDE00955E23 /* bsp_edge.c */, B086FA820F0B9EDE00955E23 /* bsp_intersection.c */, B086FA830F0B9EDE00955E23 /* bsp_main.c */, B086FA840F0B9EDE00955E23 /* bsp_map.c */, B086FA850F0B9EDE00955E23 /* bsp_node.c */, B086FA860F0B9EDE00955E23 /* bsp_superblock.c */, B086FA870F0B9EDE00955E23 /* cl_frame.c */, B086FA880F0B9EDE00955E23 /* cl_main.c */, B086FA890F0B9EDE00955E23 /* cl_mobj.c */, B086FA8A0F0B9EDE00955E23 /* cl_oldframe.c */, B086FA8B0F0B9EDE00955E23 /* cl_oldworld.c */, B086FA8C0F0B9EDE00955E23 /* cl_player.c */, B086FA8D0F0B9EDE00955E23 /* cl_sound.c */, B086FA8E0F0B9EDE00955E23 /* cl_world.c */, B086FA8F0F0B9EDE00955E23 /* con_bar.c */, B086FA900F0B9EDE00955E23 /* con_buffer.c */, B086FA910F0B9EDE00955E23 /* con_busy.c */, B086FA920F0B9EDE00955E23 /* con_config.c */, B086FA930F0B9EDE00955E23 /* con_data.c */, B086FA940F0B9EDE00955E23 /* con_main.c */, B086FA950F0B9EDE00955E23 /* dam_blockmap.c */, B086FA960F0B9EDE00955E23 /* dam_file.c */, B086FA970F0B9EDE00955E23 /* dam_main.c */, B086FA990F0B9EDE00955E23 /* dd_help.c */, B086FA9A0F0B9EDE00955E23 /* dd_input.c */, B086FA9B0F0B9EDE00955E23 /* dd_loop.c */, B086FA9C0F0B9EDE00955E23 /* dd_main.c */, B086FA9D0F0B9EDE00955E23 /* dd_pinit.c */, B086FA9E0F0B9EDE00955E23 /* dd_plugin.c */, B086FA9F0F0B9EDE00955E23 /* dd_wad.c */, B086FAA00F0B9EDE00955E23 /* dd_zip.c */, B086FAA10F0B9EDE00955E23 /* dd_zone.c */, B086FAA20F0B9EDE00955E23 /* def_data.c */, B086FAA30F0B9EDE00955E23 /* def_main.c */, B086FAA40F0B9EDE00955E23 /* def_read.c */, B086FAA50F0B9EDE00955E23 /* dgl_common.c */, B086FAA60F0B9EDE00955E23 /* dgl_draw.c */, B086FAA80F0B9EDE00955E23 /* dgl_texture.c */, B086FAA90F0B9EDE00955E23 /* edit_bias.c */, B086FAAA0F0B9EDE00955E23 /* edit_map.c */, B086FAAB0F0B9EDE00955E23 /* gl_defer.c */, B086FAAC0F0B9EDE00955E23 /* gl_draw.c */, B086FAAD0F0B9EDE00955E23 /* gl_font.c */, B086FAAE0F0B9EDE00955E23 /* gl_hq2x.c */, B086FAAF0F0B9EDE00955E23 /* gl_main.c */, B086FAB00F0B9EDE00955E23 /* gl_pcx.c */, B086FAB10F0B9EDE00955E23 /* gl_png.c */, B086FAB20F0B9EDE00955E23 /* gl_tex.c */, B086FAB30F0B9EDE00955E23 /* gl_texmanager.c */, B086FAB40F0B9EDE00955E23 /* gl_tga.c */, B086FAB50F0B9EDE00955E23 /* m_args.c */, B086FAB60F0B9EDE00955E23 /* m_bams.c */, B086FAB70F0B9EDE00955E23 /* m_binarytree.c */, B086FAB80F0B9EDE00955E23 /* m_decomp64.c */, B086FAB90F0B9EDE00955E23 /* m_filehash.c */, B086FABA0F0B9EDE00955E23 /* m_gridmap.c */, B086FABB0F0B9EDE00955E23 /* m_huffman.c */, B086FABC0F0B9EDE00955E23 /* m_linkedlist.c */, B086FABD0F0B9EDE00955E23 /* m_md5.c */, B086FABE0F0B9EDE00955E23 /* m_misc.c */, B086FABF0F0B9EDE00955E23 /* m_mus2midi.c */, B086FAC00F0B9EDE00955E23 /* m_nodepile.c */, B086FAC10F0B9EDE00955E23 /* m_string.c */, B086FAC20F0B9EDE00955E23 /* m_vector.c */, B086FAC30F0B9EDE00955E23 /* net_buf.c */, B086FAC40F0B9EDE00955E23 /* net_demo.c */, B086FAC50F0B9EDE00955E23 /* net_event.c */, B086FAC60F0B9EDE00955E23 /* net_main.c */, B086FAC70F0B9EDE00955E23 /* net_msg.c */, B086FAC80F0B9EDE00955E23 /* net_ping.c */, B086FAC90F0B9EDE00955E23 /* p_bmap.c */, B086FACA0F0B9EDE00955E23 /* p_cmd.c */, B086FACB0F0B9EDE00955E23 /* p_control.c */, B086FACC0F0B9EDE00955E23 /* p_data.c */, B086FACD0F0B9EDE00955E23 /* p_dmu.c */, B086FACE0F0B9EDE00955E23 /* p_intercept.c */, B086FACF0F0B9EDE00955E23 /* p_linedef.c */, B086FAD00F0B9EDE00955E23 /* p_maputil.c */, B086FAD10F0B9EDE00955E23 /* p_mobj.c */, B086FAD20F0B9EDE00955E23 /* p_objlink.c */, B086FAD30F0B9EDE00955E23 /* p_particle.c */, B086FAD40F0B9EDE00955E23 /* p_plane.c */, B086FAD50F0B9EDE00955E23 /* p_players.c */, B086FAD60F0B9EDE00955E23 /* p_polyob.c */, B086FAD70F0B9EDE00955E23 /* p_sector.c */, B086FAD80F0B9EDE00955E23 /* p_seg.c */, B086FAD90F0B9EDE00955E23 /* p_sidedef.c */, B086FADA0F0B9EDE00955E23 /* p_sight.c */, B086FADB0F0B9EDE00955E23 /* p_subsector.c */, B086FADC0F0B9EDE00955E23 /* p_surface.c */, B086FADD0F0B9EDE00955E23 /* p_think.c */, B086FADE0F0B9EDE00955E23 /* p_ticker.c */, B086FADF0F0B9EDE00955E23 /* p_vertex.c */, B086FAE00F0B9EDE00955E23 /* r_data.c */, B086FAE10F0B9EDE00955E23 /* r_draw.c */, B086FAE20F0B9EDE00955E23 /* r_extres.c */, B086FAE30F0B9EDE00955E23 /* r_lgrid.c */, B086FAE40F0B9EDE00955E23 /* r_lumobjs.c */, B086FAE50F0B9EDE00955E23 /* r_main.c */, B086FAE70F0B9EDE00955E23 /* r_model.c */, B086FAE80F0B9EDE00955E23 /* r_shadow.c */, B086FAE90F0B9EDE00955E23 /* r_sky.c */, B086FAEA0F0B9EDE00955E23 /* r_things.c */, B086FAEB0F0B9EDE00955E23 /* r_util.c */, B086FAEC0F0B9EDE00955E23 /* r_world.c */, B086FAED0F0B9EDE00955E23 /* rend_bias.c */, B086FAEE0F0B9EDE00955E23 /* rend_clip.c */, B086FAEF0F0B9EDE00955E23 /* rend_console.c */, B086FAF00F0B9EDE00955E23 /* rend_decor.c */, B086FAF10F0B9EDE00955E23 /* rend_dyn.c */, B086FAF20F0B9EDE00955E23 /* rend_fakeradio.c */, B086FAF30F0B9EDE00955E23 /* rend_halo.c */, B086FAF40F0B9EDE00955E23 /* rend_list.c */, B086FAF50F0B9EDE00955E23 /* rend_main.c */, B086FAF60F0B9EDE00955E23 /* rend_model.c */, B086FAF70F0B9EDE00955E23 /* rend_particle.c */, B086FAF80F0B9EDE00955E23 /* rend_shadow.c */, B086FAF90F0B9EDE00955E23 /* rend_sky.c */, B086FAFA0F0B9EDE00955E23 /* rend_sprite.c */, B086FAFB0F0B9EDE00955E23 /* s_cache.c */, B086FAFC0F0B9EDE00955E23 /* s_environ.c */, B086FAFD0F0B9EDE00955E23 /* s_logic.c */, B086FAFE0F0B9EDE00955E23 /* s_main.c */, B086FAFF0F0B9EDE00955E23 /* s_mus.c */, B086FB000F0B9EDE00955E23 /* s_sfx.c */, B086FB010F0B9EDE00955E23 /* s_wav.c */, B086FB020F0B9EDE00955E23 /* sv_frame.c */, B086FB030F0B9EDE00955E23 /* sv_main.c */, B086FB040F0B9EDE00955E23 /* sv_missile.c */, B086FB050F0B9EDE00955E23 /* sv_pool.c */, B086FB060F0B9EDE00955E23 /* sv_sound.c */, B086FB070F0B9EDE00955E23 /* sys_audiod_dummy.c */, B086FB080F0B9EDE00955E23 /* sys_audiod_sdlmixer.c */, B086FB090F0B9EDE00955E23 /* sys_direc.c */, B086FB0A0F0B9EDE00955E23 /* sys_filein.c */, B086FB0B0F0B9EDE00955E23 /* sys_master.c */, B086FB0C0F0B9EDF00955E23 /* sys_network.c */, B086FB0D0F0B9EDF00955E23 /* sys_sdl_window.c */, B086FB0E0F0B9EDF00955E23 /* sys_sock.c */, B086FB0F0F0B9EDF00955E23 /* sys_system.c */, B086FB100F0B9EDF00955E23 /* sys_timer.c */, B086FB110F0B9EDF00955E23 /* tab_tables.c */, B086FB120F0B9EDF00955E23 /* template.c.template */, B086FB130F0B9EDF00955E23 /* ui_main.c */, B086FB140F0B9EDF00955E23 /* ui_mpi.c */, B086FB150F0B9EDF00955E23 /* ui_panel.c */, ); path = src; sourceTree = ""; }; B086FB160F0B9EDF00955E23 /* scripts */ = { isa = PBXGroup; children = ( B086FB170F0B9EDF00955E23 /* apply-style.sh */, B086FB180F0B9EDF00955E23 /* definefinder.sh */, B086FB190F0B9EDF00955E23 /* deng-header-style.sh */, B086FB1A0F0B9EDF00955E23 /* deng-style.sh */, B086FB1B0F0B9EDF00955E23 /* indent-typenames.sh */, B086FB1C0F0B9EDF00955E23 /* licensecheck.sh */, B086FB1D0F0B9EDF00955E23 /* makedmt.py */, B086FB1E0F0B9EDF00955E23 /* mass_replace.sh */, ); path = scripts; sourceTree = ""; }; B086FB1F0F0B9EDF00955E23 /* unix */ = { isa = PBXGroup; children = ( B086FB200F0B9EDF00955E23 /* include */, B086FB250F0B9EDF00955E23 /* src */, ); path = unix; sourceTree = ""; }; B086FB200F0B9EDF00955E23 /* include */ = { isa = PBXGroup; children = ( B086FB210F0B9EDF00955E23 /* dd_uinit.h */, B086FB220F0B9EDF00955E23 /* sys_dylib.h */, B086FB230F0B9EDF00955E23 /* sys_findfile.h */, B086FB240F0B9EDF00955E23 /* sys_path.h */, ); path = include; sourceTree = ""; }; B086FB250F0B9EDF00955E23 /* src */ = { isa = PBXGroup; children = ( B086FB260F0B9EDF00955E23 /* dd_uinit.c */, B086FB270F0B9EDF00955E23 /* sys_audiod_loader.c */, B086FB280F0B9EDF00955E23 /* sys_console.c */, B086FB290F0B9EDF00955E23 /* sys_dylib.c */, B086FB2A0F0B9EDF00955E23 /* sys_findfile.c */, B086FB2B0F0B9EDF00955E23 /* sys_input.c */, B086FB2C0F0B9EDF00955E23 /* sys_mixer.c */, B086FB2D0F0B9EDF00955E23 /* sys_path.c */, ); path = src; sourceTree = ""; }; B086FB3E0F0B9EDF00955E23 /* external */ = { isa = PBXGroup; children = ( B086FB410F0B9EDF00955E23 /* libcurl */, B086FB4F0F0B9EDF00955E23 /* libpng */, B086FB590F0B9EDF00955E23 /* lzss */, B086FB6B0F0B9EDF00955E23 /* zlib */, ); name = external; path = ../../external; sourceTree = SOURCE_ROOT; }; B086FB410F0B9EDF00955E23 /* libcurl */ = { isa = PBXGroup; children = ( B086FB420F0B9EDF00955E23 /* portable */, ); path = libcurl; sourceTree = ""; }; B086FB420F0B9EDF00955E23 /* portable */ = { isa = PBXGroup; children = ( B086FB430F0B9EDF00955E23 /* include */, ); path = portable; sourceTree = ""; }; B086FB430F0B9EDF00955E23 /* include */ = { isa = PBXGroup; children = ( B086FB440F0B9EDF00955E23 /* curl */, ); path = include; sourceTree = ""; }; B086FB440F0B9EDF00955E23 /* curl */ = { isa = PBXGroup; children = ( B086FB450F0B9EDF00955E23 /* curl.h */, B086FB460F0B9EDF00955E23 /* curlver.h */, B086FB470F0B9EDF00955E23 /* easy.h */, B086FB480F0B9EDF00955E23 /* mprintf.h */, B086FB490F0B9EDF00955E23 /* multi.h */, B086FB4A0F0B9EDF00955E23 /* stdcheaders.h */, B086FB4B0F0B9EDF00955E23 /* types.h */, ); path = curl; sourceTree = ""; }; B086FB4F0F0B9EDF00955E23 /* libpng */ = { isa = PBXGroup; children = ( B086FB500F0B9EDF00955E23 /* portable */, ); path = libpng; sourceTree = ""; }; B086FB500F0B9EDF00955E23 /* portable */ = { isa = PBXGroup; children = ( B086FB510F0B9EDF00955E23 /* include */, ); path = portable; sourceTree = ""; }; B086FB510F0B9EDF00955E23 /* include */ = { isa = PBXGroup; children = ( B086FB520F0B9EDF00955E23 /* png.h */, B086FB530F0B9EDF00955E23 /* pngconf.h */, ); path = include; sourceTree = ""; }; B086FB590F0B9EDF00955E23 /* lzss */ = { isa = PBXGroup; children = ( B086FB5A0F0B9EDF00955E23 /* portable */, B086FB5D0F0B9EDF00955E23 /* unix */, ); path = lzss; sourceTree = ""; }; B086FB5A0F0B9EDF00955E23 /* portable */ = { isa = PBXGroup; children = ( B086FB5B0F0B9EDF00955E23 /* include */, ); path = portable; sourceTree = ""; }; B086FB5B0F0B9EDF00955E23 /* include */ = { isa = PBXGroup; children = ( B086FB5C0F0B9EDF00955E23 /* lzss.h */, ); path = include; sourceTree = ""; }; B086FB5D0F0B9EDF00955E23 /* unix */ = { isa = PBXGroup; children = ( B086FB5E0F0B9EDF00955E23 /* src */, ); path = unix; sourceTree = ""; }; B086FB5E0F0B9EDF00955E23 /* src */ = { isa = PBXGroup; children = ( B086FB5F0F0B9EDF00955E23 /* lzss.c */, ); path = src; sourceTree = ""; }; B086FB6B0F0B9EDF00955E23 /* zlib */ = { isa = PBXGroup; children = ( B086FB6C0F0B9EDF00955E23 /* portable */, ); path = zlib; sourceTree = ""; }; B086FB6C0F0B9EDF00955E23 /* portable */ = { isa = PBXGroup; children = ( B086FB6D0F0B9EDF00955E23 /* include */, ); path = portable; sourceTree = ""; }; B086FB6D0F0B9EDF00955E23 /* include */ = { isa = PBXGroup; children = ( B086FB6E0F0B9EDF00955E23 /* zconf.h */, B086FB6F0F0B9EDF00955E23 /* zlib.h */, ); path = include; sourceTree = ""; }; B086FB750F0B9EDF00955E23 /* plugins */ = { isa = PBXGroup; children = ( B086FB760F0B9EDF00955E23 /* common */, B086FBD40F0B9EDF00955E23 /* dehread */, B086FBE10F0B9EDF00955E23 /* exampleplugin */, B086FBE80F0B9EDF00955E23 /* jdoom */, B086FCD80F0B9EE000955E23 /* jdoom64 */, B086FD3A0F0B9EE100955E23 /* jheretic */, B086FDAA0F0B9EE100955E23 /* jhexen */, B086FE5F0F0B9EE200955E23 /* openal */, B086FE670F0B9EE200955E23 /* wadmapconverter */, ); name = plugins; path = ../../plugins; sourceTree = SOURCE_ROOT; }; B086FB760F0B9EDF00955E23 /* common */ = { isa = PBXGroup; children = ( B086FB770F0B9EDF00955E23 /* include */, B086FBA50F0B9EDF00955E23 /* src */, ); path = common; sourceTree = ""; }; B086FB770F0B9EDF00955E23 /* include */ = { isa = PBXGroup; children = ( B0EE23170F52051600D49358 /* p_automap.h */, B0EE23180F52051600D49358 /* rend_automap.h */, B086FB780F0B9EDF00955E23 /* am_map.h */, B086FB7A0F0B9EDF00955E23 /* d_net.h */, B086FB7B0F0B9EDF00955E23 /* d_netcl.h */, B086FB7C0F0B9EDF00955E23 /* d_netsv.h */, B086FB7D0F0B9EDF00955E23 /* dmu_lib.h */, B086FB7E0F0B9EDF00955E23 /* f_infine.h */, B086FB7F0F0B9EDF00955E23 /* g_common.h */, B086FB800F0B9EDF00955E23 /* g_controls.h */, B086FB810F0B9EDF00955E23 /* g_defs.h */, B086FB820F0B9EDF00955E23 /* g_update.h */, B086FB830F0B9EDF00955E23 /* hu_lib.h */, B086FB840F0B9EDF00955E23 /* hu_log.h */, B086FB850F0B9EDF00955E23 /* hu_menu.h */, B086FB860F0B9EDF00955E23 /* hu_msg.h */, B086FB870F0B9EDF00955E23 /* hu_pspr.h */, B086FB880F0B9EDF00955E23 /* hu_stuff.h */, B086FB890F0B9EDF00955E23 /* m_argv.h */, B086FB8A0F0B9EDF00955E23 /* m_defs.h */, B086FB8B0F0B9EDF00955E23 /* p_actor.h */, B086FB8C0F0B9EDF00955E23 /* p_ceiling.h */, B086FB8D0F0B9EDF00955E23 /* p_door.h */, B086FB8E0F0B9EDF00955E23 /* p_floor.h */, B086FB8F0F0B9EDF00955E23 /* p_inventory.h */, B086FB900F0B9EDF00955E23 /* p_iterlist.h */, B086FB910F0B9EDF00955E23 /* p_map.h */, B086FB920F0B9EDF00955E23 /* p_mapsetup.h */, B086FB930F0B9EDF00955E23 /* p_mapspec.h */, B086FB940F0B9EDF00955E23 /* p_plat.h */, B086FB950F0B9EDF00955E23 /* p_player.h */, B086FB960F0B9EDF00955E23 /* p_saveg.h */, B086FB970F0B9EDF00955E23 /* p_start.h */, B086FB980F0B9EDF00955E23 /* p_svtexarc.h */, B086FB990F0B9EDF00955E23 /* p_switch.h */, B086FB9A0F0B9EDF00955E23 /* p_terraintype.h */, B086FB9B0F0B9EDF00955E23 /* p_tick.h */, B086FB9C0F0B9EDF00955E23 /* p_user.h */, B086FB9D0F0B9EDF00955E23 /* p_view.h */, B086FB9E0F0B9EDF00955E23 /* p_xg.h */, B086FB9F0F0B9EDF00955E23 /* p_xgline.h */, B086FBA00F0B9EDF00955E23 /* p_xgsec.h */, B086FBA10F0B9EDF00955E23 /* r_common.h */, B086FBA20F0B9EDF00955E23 /* st_lib.h */, B086FBA30F0B9EDF00955E23 /* x_hair.h */, B086FBA40F0B9EDF00955E23 /* xgclass.h */, ); path = include; sourceTree = ""; }; B086FBA50F0B9EDF00955E23 /* src */ = { isa = PBXGroup; children = ( B01995A40F51619B009020DF /* p_automap.c */, B01995A50F51619B009020DF /* rend_automap.c */, B086FBA60F0B9EDF00955E23 /* am_map.c */, B086FBA80F0B9EDF00955E23 /* d_net.c */, B086FBA90F0B9EDF00955E23 /* d_netcl.c */, B086FBAA0F0B9EDF00955E23 /* d_netsv.c */, B086FBAB0F0B9EDF00955E23 /* dmu_lib.c */, B086FBAC0F0B9EDF00955E23 /* f_infine.c */, B086FBAD0F0B9EDF00955E23 /* g_controls.c */, B086FBAE0F0B9EDF00955E23 /* g_defs.c */, B086FBAF0F0B9EDF00955E23 /* g_game.c */, B086FBB00F0B9EDF00955E23 /* g_update.c */, B086FBB10F0B9EDF00955E23 /* hu_lib.c */, B086FBB20F0B9EDF00955E23 /* hu_log.c */, B086FBB30F0B9EDF00955E23 /* hu_menu.c */, B086FBB40F0B9EDF00955E23 /* hu_msg.c */, B086FBB50F0B9EDF00955E23 /* hu_pspr.c */, B086FBB60F0B9EDF00955E23 /* hu_stuff.c */, B086FBB70F0B9EDF00955E23 /* m_ctrl.c */, B086FBB80F0B9EDF00955E23 /* m_fixed.c */, B086FBB90F0B9EDF00955E23 /* m_multi.c */, B086FBBA0F0B9EDF00955E23 /* p_actor.c */, B086FBBB0F0B9EDF00955E23 /* p_ceiling.c */, B086FBBC0F0B9EDF00955E23 /* p_door.c */, B086FBBD0F0B9EDF00955E23 /* p_floor.c */, B086FBBE0F0B9EDF00955E23 /* p_inventory.c */, B086FBBF0F0B9EDF00955E23 /* p_iterlist.c */, B086FBC00F0B9EDF00955E23 /* p_map.c */, B086FBC10F0B9EDF00955E23 /* p_mapsetup.c */, B086FBC20F0B9EDF00955E23 /* p_mapspec.c */, B086FBC30F0B9EDF00955E23 /* p_plat.c */, B086FBC40F0B9EDF00955E23 /* p_player.c */, B086FBC50F0B9EDF00955E23 /* p_saveg.c */, B086FBC60F0B9EDF00955E23 /* p_start.c */, B086FBC70F0B9EDF00955E23 /* p_svtexarc.c */, B086FBC80F0B9EDF00955E23 /* p_switch.c */, B086FBC90F0B9EDF00955E23 /* p_terraintype.c */, B086FBCA0F0B9EDF00955E23 /* p_tick.c */, B086FBCB0F0B9EDF00955E23 /* p_user.c */, B086FBCC0F0B9EDF00955E23 /* p_view.c */, B086FBCD0F0B9EDF00955E23 /* p_xgfile.c */, B086FBCE0F0B9EDF00955E23 /* p_xgline.c */, B086FBCF0F0B9EDF00955E23 /* p_xgsave.c */, B086FBD00F0B9EDF00955E23 /* p_xgsec.c */, B086FBD10F0B9EDF00955E23 /* r_common.c */, B086FBD20F0B9EDF00955E23 /* st_lib.c */, B086FBD30F0B9EDF00955E23 /* x_hair.c */, ); path = src; sourceTree = ""; }; B086FBD40F0B9EDF00955E23 /* dehread */ = { isa = PBXGroup; children = ( B086FBD50F0B9EDF00955E23 /* CMakeLists.txt */, B086FBD60F0B9EDF00955E23 /* doc */, B086FBD80F0B9EDF00955E23 /* src */, ); path = dehread; sourceTree = ""; }; B086FBD60F0B9EDF00955E23 /* doc */ = { isa = PBXGroup; children = ( B086FBD70F0B9EDF00955E23 /* LICENSE */, ); path = doc; sourceTree = ""; }; B086FBD80F0B9EDF00955E23 /* src */ = { isa = PBXGroup; children = ( B086FBD90F0B9EDF00955E23 /* dehmain.c */, ); path = src; sourceTree = ""; }; B086FBE10F0B9EDF00955E23 /* exampleplugin */ = { isa = PBXGroup; children = ( B086FBE20F0B9EDF00955E23 /* CMakeLists.txt */, B086FBE30F0B9EDF00955E23 /* doc */, B086FBE60F0B9EDF00955E23 /* src */, ); path = exampleplugin; sourceTree = ""; }; B086FBE30F0B9EDF00955E23 /* doc */ = { isa = PBXGroup; children = ( B086FBE40F0B9EDF00955E23 /* LICENSE */, B086FBE50F0B9EDF00955E23 /* readme.txt */, ); path = doc; sourceTree = ""; }; B086FBE60F0B9EDF00955E23 /* src */ = { isa = PBXGroup; children = ( B086FBE70F0B9EDF00955E23 /* example.c */, ); path = src; sourceTree = ""; }; B086FBE80F0B9EDF00955E23 /* jdoom */ = { isa = PBXGroup; children = ( B086FBE90F0B9EDF00955E23 /* api */, B086FBEB0F0B9EE000955E23 /* CMakeLists.txt */, B086FBEC0F0B9EE000955E23 /* config */, B086FBEE0F0B9EE000955E23 /* data */, B086FC700F0B9EE000955E23 /* defs */, B086FC8F0F0B9EE000955E23 /* doc */, B086FC910F0B9EE000955E23 /* include */, B086FCBB0F0B9EE000955E23 /* res */, B086FCC00F0B9EE000955E23 /* src */, ); path = jdoom; sourceTree = ""; }; B086FBE90F0B9EDF00955E23 /* api */ = { isa = PBXGroup; children = ( B086FBEA0F0B9EE000955E23 /* jdoom.def */, ); path = api; sourceTree = ""; }; B086FBEC0F0B9EE000955E23 /* config */ = { isa = PBXGroup; children = ( B086FBED0F0B9EE000955E23 /* startup.cfg */, ); path = config; sourceTree = ""; }; B086FBEE0F0B9EE000955E23 /* data */ = { isa = PBXGroup; children = ( B086FBEF0F0B9EE000955E23 /* conhelp.txt */, B086FBF00F0B9EE000955E23 /* lumps */, ); path = data; sourceTree = ""; }; B086FBF00F0B9EE000955E23 /* lumps */ = { isa = PBXGroup; children = ( B086FBF10F0B9EE000955E23 /* fonta033.lmp */, B086FBF20F0B9EE000955E23 /* fonta034.lmp */, B086FBF30F0B9EE000955E23 /* fonta035.lmp */, B086FBF40F0B9EE000955E23 /* fonta036.lmp */, B086FBF50F0B9EE000955E23 /* fonta037.lmp */, B086FBF60F0B9EE000955E23 /* fonta038.lmp */, B086FBF70F0B9EE000955E23 /* fonta039.lmp */, B086FBF80F0B9EE000955E23 /* fonta040.lmp */, B086FBF90F0B9EE000955E23 /* fonta041.lmp */, B086FBFA0F0B9EE000955E23 /* fonta042.lmp */, B086FBFB0F0B9EE000955E23 /* fonta043.lmp */, B086FBFC0F0B9EE000955E23 /* fonta044.lmp */, B086FBFD0F0B9EE000955E23 /* fonta045.lmp */, B086FBFE0F0B9EE000955E23 /* fonta046.lmp */, B086FBFF0F0B9EE000955E23 /* fonta047.lmp */, B086FC000F0B9EE000955E23 /* fonta048.lmp */, B086FC010F0B9EE000955E23 /* fonta049.lmp */, B086FC020F0B9EE000955E23 /* fonta050.lmp */, B086FC030F0B9EE000955E23 /* fonta051.lmp */, B086FC040F0B9EE000955E23 /* fonta052.lmp */, B086FC050F0B9EE000955E23 /* fonta053.lmp */, B086FC060F0B9EE000955E23 /* fonta054.lmp */, B086FC070F0B9EE000955E23 /* fonta055.lmp */, B086FC080F0B9EE000955E23 /* fonta056.lmp */, B086FC090F0B9EE000955E23 /* fonta057.lmp */, B086FC0A0F0B9EE000955E23 /* fonta058.lmp */, B086FC0B0F0B9EE000955E23 /* fonta059.lmp */, B086FC0C0F0B9EE000955E23 /* fonta060.lmp */, B086FC0D0F0B9EE000955E23 /* fonta061.lmp */, B086FC0E0F0B9EE000955E23 /* fonta062.lmp */, B086FC0F0F0B9EE000955E23 /* fonta063.lmp */, B086FC100F0B9EE000955E23 /* fonta064.lmp */, B086FC110F0B9EE000955E23 /* fonta065.lmp */, B086FC120F0B9EE000955E23 /* fonta066.lmp */, B086FC130F0B9EE000955E23 /* fonta067.lmp */, B086FC140F0B9EE000955E23 /* fonta068.lmp */, B086FC150F0B9EE000955E23 /* fonta069.lmp */, B086FC160F0B9EE000955E23 /* fonta070.lmp */, B086FC170F0B9EE000955E23 /* fonta071.lmp */, B086FC180F0B9EE000955E23 /* fonta072.lmp */, B086FC190F0B9EE000955E23 /* fonta073.lmp */, B086FC1A0F0B9EE000955E23 /* fonta074.lmp */, B086FC1B0F0B9EE000955E23 /* fonta075.lmp */, B086FC1C0F0B9EE000955E23 /* fonta076.lmp */, B086FC1D0F0B9EE000955E23 /* fonta077.lmp */, B086FC1E0F0B9EE000955E23 /* fonta078.lmp */, B086FC1F0F0B9EE000955E23 /* fonta079.lmp */, B086FC200F0B9EE000955E23 /* fonta080.lmp */, B086FC210F0B9EE000955E23 /* fonta081.lmp */, B086FC220F0B9EE000955E23 /* fonta082.lmp */, B086FC230F0B9EE000955E23 /* fonta083.lmp */, B086FC240F0B9EE000955E23 /* fonta084.lmp */, B086FC250F0B9EE000955E23 /* fonta085.lmp */, B086FC260F0B9EE000955E23 /* fonta086.lmp */, B086FC270F0B9EE000955E23 /* fonta087.lmp */, B086FC280F0B9EE000955E23 /* fonta088.lmp */, B086FC290F0B9EE000955E23 /* fonta089.lmp */, B086FC2A0F0B9EE000955E23 /* fonta090.lmp */, B086FC2B0F0B9EE000955E23 /* fonta091.lmp */, B086FC2C0F0B9EE000955E23 /* fonta092.lmp */, B086FC2D0F0B9EE000955E23 /* fonta093.lmp */, B086FC2E0F0B9EE000955E23 /* fonta094.lmp */, B086FC2F0F0B9EE000955E23 /* fonta095.lmp */, B086FC300F0B9EE000955E23 /* fonta121.lmp */, B086FC310F0B9EE000955E23 /* fontb033.lmp */, B086FC320F0B9EE000955E23 /* fontb034.lmp */, B086FC330F0B9EE000955E23 /* fontb035.lmp */, B086FC340F0B9EE000955E23 /* fontb036.lmp */, B086FC350F0B9EE000955E23 /* fontb037.lmp */, B086FC360F0B9EE000955E23 /* fontb038.lmp */, B086FC370F0B9EE000955E23 /* fontb039.lmp */, B086FC380F0B9EE000955E23 /* fontb040.lmp */, B086FC390F0B9EE000955E23 /* fontb041.lmp */, B086FC3A0F0B9EE000955E23 /* fontb042.lmp */, B086FC3B0F0B9EE000955E23 /* fontb043.lmp */, B086FC3C0F0B9EE000955E23 /* fontb044.lmp */, B086FC3D0F0B9EE000955E23 /* fontb045.lmp */, B086FC3E0F0B9EE000955E23 /* fontb046.lmp */, B086FC3F0F0B9EE000955E23 /* fontb047.lmp */, B086FC400F0B9EE000955E23 /* fontb048.lmp */, B086FC410F0B9EE000955E23 /* fontb049.lmp */, B086FC420F0B9EE000955E23 /* fontb050.lmp */, B086FC430F0B9EE000955E23 /* fontb051.lmp */, B086FC440F0B9EE000955E23 /* fontb052.lmp */, B086FC450F0B9EE000955E23 /* fontb053.lmp */, B086FC460F0B9EE000955E23 /* fontb054.lmp */, B086FC470F0B9EE000955E23 /* fontb055.lmp */, B086FC480F0B9EE000955E23 /* fontb056.lmp */, B086FC490F0B9EE000955E23 /* fontb057.lmp */, B086FC4A0F0B9EE000955E23 /* fontb058.lmp */, B086FC4B0F0B9EE000955E23 /* fontb059.lmp */, B086FC4C0F0B9EE000955E23 /* fontb060.lmp */, B086FC4D0F0B9EE000955E23 /* fontb061.lmp */, B086FC4E0F0B9EE000955E23 /* fontb062.lmp */, B086FC4F0F0B9EE000955E23 /* fontb063.lmp */, B086FC500F0B9EE000955E23 /* fontb064.lmp */, B086FC510F0B9EE000955E23 /* fontb065.lmp */, B086FC520F0B9EE000955E23 /* fontb066.lmp */, B086FC530F0B9EE000955E23 /* fontb067.lmp */, B086FC540F0B9EE000955E23 /* fontb068.lmp */, B086FC550F0B9EE000955E23 /* fontb069.lmp */, B086FC560F0B9EE000955E23 /* fontb070.lmp */, B086FC570F0B9EE000955E23 /* fontb071.lmp */, B086FC580F0B9EE000955E23 /* fontb072.lmp */, B086FC590F0B9EE000955E23 /* fontb073.lmp */, B086FC5A0F0B9EE000955E23 /* fontb074.lmp */, B086FC5B0F0B9EE000955E23 /* fontb075.lmp */, B086FC5C0F0B9EE000955E23 /* fontb076.lmp */, B086FC5D0F0B9EE000955E23 /* fontb077.lmp */, B086FC5E0F0B9EE000955E23 /* fontb078.lmp */, B086FC5F0F0B9EE000955E23 /* fontb079.lmp */, B086FC600F0B9EE000955E23 /* fontb080.lmp */, B086FC610F0B9EE000955E23 /* fontb081.lmp */, B086FC620F0B9EE000955E23 /* fontb082.lmp */, B086FC630F0B9EE000955E23 /* fontb083.lmp */, B086FC640F0B9EE000955E23 /* fontb084.lmp */, B086FC650F0B9EE000955E23 /* fontb085.lmp */, B086FC660F0B9EE000955E23 /* fontb086.lmp */, B086FC670F0B9EE000955E23 /* fontb087.lmp */, B086FC680F0B9EE000955E23 /* fontb088.lmp */, B086FC690F0B9EE000955E23 /* fontb089.lmp */, B086FC6A0F0B9EE000955E23 /* fontb090.lmp */, B086FC6B0F0B9EE000955E23 /* m_therm2.lmp */, B086FC6C0F0B9EE000955E23 /* mapmask.lmp */, B086FC6D0F0B9EE000955E23 /* menufog.lmp */, B086FC6E0F0B9EE000955E23 /* pal18to8.lmp */, B086FC6F0F0B9EE000955E23 /* sndcurve.lmp */, ); path = lumps; sourceTree = ""; }; B086FC700F0B9EE000955E23 /* defs */ = { isa = PBXGroup; children = ( B086FC710F0B9EE000955E23 /* anim.ded */, B086FC720F0B9EE000955E23 /* audio.ded */, B086FC730F0B9EE000955E23 /* auto */, B086FC750F0B9EE000955E23 /* details.ded */, B086FC760F0B9EE000955E23 /* doom1anim.ded */, B086FC770F0B9EE000955E23 /* doom1lights.ded */, B086FC780F0B9EE000955E23 /* doom1maps.ded */, B086FC790F0B9EE000955E23 /* doom1music.ded */, B086FC7A0F0B9EE000955E23 /* doom2-plutlights.ded */, B086FC7B0F0B9EE000955E23 /* doom2-plutmaps.ded */, B086FC7C0F0B9EE000955E23 /* doom2-tntlights.ded */, B086FC7D0F0B9EE000955E23 /* doom2-tntmaps.ded */, B086FC7E0F0B9EE000955E23 /* doom2anim.ded */, B086FC7F0F0B9EE000955E23 /* doom2lights.ded */, B086FC800F0B9EE000955E23 /* doom2maps.ded */, B086FC810F0B9EE000955E23 /* doom2music.ded */, B086FC820F0B9EE000955E23 /* finales.ded */, B086FC830F0B9EE000955E23 /* jdoom.ded */, B086FC840F0B9EE000955E23 /* lights.ded */, B086FC850F0B9EE000955E23 /* maps.ded */, B086FC860F0B9EE000955E23 /* objects.ded */, B086FC870F0B9EE000955E23 /* particles.ded */, B086FC880F0B9EE000955E23 /* plutanim.ded */, B086FC890F0B9EE000955E23 /* plutfinales.ded */, B086FC8A0F0B9EE000955E23 /* special.ded */, B086FC8B0F0B9EE000955E23 /* sprites.ded */, B086FC8C0F0B9EE000955E23 /* text.ded */, B086FC8D0F0B9EE000955E23 /* tntfinales.ded */, B086FC8E0F0B9EE000955E23 /* values.ded */, ); path = defs; sourceTree = ""; }; B086FC730F0B9EE000955E23 /* auto */ = { isa = PBXGroup; children = ( B086FC740F0B9EE000955E23 /* Readme.txt */, ); path = auto; sourceTree = ""; }; B086FC8F0F0B9EE000955E23 /* doc */ = { isa = PBXGroup; children = ( B086FC900F0B9EE000955E23 /* LICENSE */, ); path = doc; sourceTree = ""; }; B086FC910F0B9EE000955E23 /* include */ = { isa = PBXGroup; children = ( B086FC920F0B9EE000955E23 /* acfnlink.h */, B086FC930F0B9EE000955E23 /* d_api.h */, B086FC940F0B9EE000955E23 /* d_config.h */, B086FC950F0B9EE000955E23 /* d_console.h */, B086FC960F0B9EE000955E23 /* d_englsh.h */, B086FC970F0B9EE000955E23 /* d_event.h */, B086FC980F0B9EE000955E23 /* d_items.h */, B086FC990F0B9EE000955E23 /* d_main.h */, B086FC9A0F0B9EE000955E23 /* d_player.h */, B086FC9B0F0B9EE000955E23 /* d_refresh.h */, B086FC9C0F0B9EE000955E23 /* d_think.h */, B086FC9D0F0B9EE000955E23 /* doomdata.h */, B086FC9E0F0B9EE000955E23 /* doomdef.h */, B086FC9F0F0B9EE000955E23 /* doomtype.h */, B086FCA00F0B9EE000955E23 /* dstrings.h */, B086FCA10F0B9EE000955E23 /* g_ctrl.h */, B086FCA20F0B9EE000955E23 /* g_game.h */, B086FCA30F0B9EE000955E23 /* info.h */, B086FCA40F0B9EE000955E23 /* jdoom.h */, B086FCA50F0B9EE000955E23 /* m_cheat.h */, B086FCA60F0B9EE000955E23 /* m_menu.h */, B086FCA70F0B9EE000955E23 /* m_random.h */, B086FCA80F0B9EE000955E23 /* mn_def.h */, B086FCA90F0B9EE000955E23 /* oldinfo.h */, B086FCAA0F0B9EE000955E23 /* p_enemy.h */, B086FCAB0F0B9EE000955E23 /* p_inter.h */, B086FCAC0F0B9EE000955E23 /* p_lights.h */, B086FCAD0F0B9EE000955E23 /* p_local.h */, B086FCAE0F0B9EE000955E23 /* p_maputl.h */, B086FCAF0F0B9EE000955E23 /* p_mobj.h */, B086FCB00F0B9EE000955E23 /* p_oldsvg.h */, B086FCB10F0B9EE000955E23 /* p_pspr.h */, B086FCB20F0B9EE000955E23 /* p_setup.h */, B086FCB30F0B9EE000955E23 /* p_sound.h */, B086FCB40F0B9EE000955E23 /* p_spec.h */, B086FCB50F0B9EE000955E23 /* p_telept.h */, B086FCB60F0B9EE000955E23 /* r_defs.h */, B086FCB70F0B9EE000955E23 /* st_stuff.h */, B086FCB80F0B9EE000955E23 /* tables.h */, B086FCB90F0B9EE000955E23 /* version.h */, B086FCBA0F0B9EE000955E23 /* wi_stuff.h */, ); path = include; sourceTree = ""; }; B086FCBB0F0B9EE000955E23 /* res */ = { isa = PBXGroup; children = ( B086FCBC0F0B9EE000955E23 /* jdoom.dll.manifest */, B086FCBD0F0B9EE000955E23 /* jdoom.ico */, B086FCBE0F0B9EE000955E23 /* jdoom.rc */, B086FCBF0F0B9EE000955E23 /* resource.h */, ); path = res; sourceTree = ""; }; B086FCC00F0B9EE000955E23 /* src */ = { isa = PBXGroup; children = ( B086FCC10F0B9EE000955E23 /* acfnlink.c */, B086FCC20F0B9EE000955E23 /* d_api.c */, B086FCC30F0B9EE000955E23 /* d_console.c */, B086FCC40F0B9EE000955E23 /* d_items.c */, B086FCC50F0B9EE000955E23 /* d_main.c */, B086FCC60F0B9EE000955E23 /* d_refresh.c */, B086FCC70F0B9EE000955E23 /* g_ctrl.c */, B086FCC80F0B9EE000955E23 /* m_cheat.c */, B086FCC90F0B9EE000955E23 /* m_random.c */, B086FCCA0F0B9EE000955E23 /* p_enemy.c */, B086FCCB0F0B9EE000955E23 /* p_inter.c */, B086FCCC0F0B9EE000955E23 /* p_lights.c */, B086FCCD0F0B9EE000955E23 /* p_maputl.c */, B086FCCE0F0B9EE000955E23 /* p_mobj.c */, B086FCCF0F0B9EE000955E23 /* p_oldsvg.c */, B086FCD00F0B9EE000955E23 /* p_pspr.c */, B086FCD10F0B9EE000955E23 /* p_setup.c */, B086FCD20F0B9EE000955E23 /* p_sound.c */, B086FCD30F0B9EE000955E23 /* p_spec.c */, B086FCD40F0B9EE000955E23 /* p_telept.c */, B086FCD50F0B9EE000955E23 /* st_stuff.c */, B086FCD60F0B9EE000955E23 /* tables.c */, B086FCD70F0B9EE000955E23 /* wi_stuff.c */, ); path = src; sourceTree = ""; }; B086FCD80F0B9EE000955E23 /* jdoom64 */ = { isa = PBXGroup; children = ( B086FCD90F0B9EE000955E23 /* api */, B086FCDB0F0B9EE000955E23 /* CMakeLists.txt */, B086FCDC0F0B9EE000955E23 /* config */, B086FCDE0F0B9EE000955E23 /* data */, B086FCE60F0B9EE000955E23 /* defs */, B086FCF70F0B9EE100955E23 /* doc */, B086FCF90F0B9EE100955E23 /* include */, B086FD1E0F0B9EE100955E23 /* res */, B086FD230F0B9EE100955E23 /* src */, ); path = jdoom64; sourceTree = ""; }; B086FCD90F0B9EE000955E23 /* api */ = { isa = PBXGroup; children = ( B086FCDA0F0B9EE000955E23 /* jdoom64.def */, ); path = api; sourceTree = ""; }; B086FCDC0F0B9EE000955E23 /* config */ = { isa = PBXGroup; children = ( B086FCDD0F0B9EE000955E23 /* startup.cfg */, ); path = config; sourceTree = ""; }; B086FCDE0F0B9EE000955E23 /* data */ = { isa = PBXGroup; children = ( B086FCDF0F0B9EE000955E23 /* conhelp.txt */, B086FCE00F0B9EE000955E23 /* lumps */, ); path = data; sourceTree = ""; }; B086FCE00F0B9EE000955E23 /* lumps */ = { isa = PBXGroup; children = ( B086FCE10F0B9EE000955E23 /* m_therm2.lmp */, B086FCE20F0B9EE000955E23 /* mapmask.lmp */, B086FCE30F0B9EE000955E23 /* menufog.lmp */, B086FCE40F0B9EE000955E23 /* pal18to8.lmp */, B086FCE50F0B9EE000955E23 /* sndcurve.lmp */, ); path = lumps; sourceTree = ""; }; B086FCE60F0B9EE000955E23 /* defs */ = { isa = PBXGroup; children = ( B086FCE70F0B9EE100955E23 /* anim.ded */, B086FCE80F0B9EE100955E23 /* audio.ded */, B086FCE90F0B9EE100955E23 /* Auto */, B086FCEB0F0B9EE100955E23 /* d2_ogg_Audio.ded */, B086FCEC0F0B9EE100955E23 /* decorlights.ded */, B086FCED0F0B9EE100955E23 /* finales.ded */, B086FCEE0F0B9EE100955E23 /* jdoom64.ded */, B086FCEF0F0B9EE100955E23 /* lights.ded */, B086FCF00F0B9EE100955E23 /* maps.ded */, B086FCF10F0B9EE100955E23 /* objects.ded */, B086FCF20F0B9EE100955E23 /* particles.ded */, B086FCF30F0B9EE100955E23 /* special.ded */, B086FCF40F0B9EE100955E23 /* sprites.ded */, B086FCF50F0B9EE100955E23 /* text.ded */, B086FCF60F0B9EE100955E23 /* values.ded */, ); path = defs; sourceTree = ""; }; B086FCE90F0B9EE100955E23 /* Auto */ = { isa = PBXGroup; children = ( B086FCEA0F0B9EE100955E23 /* Readme.txt */, ); path = Auto; sourceTree = ""; }; B086FCF70F0B9EE100955E23 /* doc */ = { isa = PBXGroup; children = ( B086FCF80F0B9EE100955E23 /* LICENSE */, ); path = doc; sourceTree = ""; }; B086FCF90F0B9EE100955E23 /* include */ = { isa = PBXGroup; children = ( B086FCFA0F0B9EE100955E23 /* acfnlink.h */, B086FCFB0F0B9EE100955E23 /* d_api.h */, B086FCFC0F0B9EE100955E23 /* d_config.h */, B086FCFD0F0B9EE100955E23 /* d_console.h */, B086FCFE0F0B9EE100955E23 /* d_englsh.h */, B086FCFF0F0B9EE100955E23 /* d_items.h */, B086FD000F0B9EE100955E23 /* d_main.h */, B086FD010F0B9EE100955E23 /* d_player.h */, B086FD020F0B9EE100955E23 /* d_refresh.h */, B086FD030F0B9EE100955E23 /* d_think.h */, B086FD040F0B9EE100955E23 /* doomdef.h */, B086FD050F0B9EE100955E23 /* doomtype.h */, B086FD060F0B9EE100955E23 /* dstrings.h */, B086FD070F0B9EE100955E23 /* g_ctrl.h */, B086FD080F0B9EE100955E23 /* g_game.h */, B086FD090F0B9EE100955E23 /* info.h */, B086FD0A0F0B9EE100955E23 /* jdoom64.h */, B086FD0B0F0B9EE100955E23 /* m_cheat.h */, B086FD0C0F0B9EE100955E23 /* m_menu.h */, B086FD0D0F0B9EE100955E23 /* m_random.h */, B086FD0E0F0B9EE100955E23 /* mn_def.h */, B086FD0F0F0B9EE100955E23 /* p_enemy.h */, B086FD100F0B9EE100955E23 /* p_inter.h */, B086FD110F0B9EE100955E23 /* p_lights.h */, B086FD120F0B9EE100955E23 /* p_maputl.h */, B086FD130F0B9EE100955E23 /* p_mobj.h */, B086FD140F0B9EE100955E23 /* p_pspr.h */, B086FD150F0B9EE100955E23 /* p_setup.h */, B086FD160F0B9EE100955E23 /* p_sound.h */, B086FD170F0B9EE100955E23 /* p_spec.h */, B086FD180F0B9EE100955E23 /* p_telept.h */, B086FD190F0B9EE100955E23 /* r_defs.h */, B086FD1A0F0B9EE100955E23 /* st_stuff.h */, B086FD1B0F0B9EE100955E23 /* tables.h */, B086FD1C0F0B9EE100955E23 /* version.h */, B086FD1D0F0B9EE100955E23 /* wi_stuff.h */, ); path = include; sourceTree = ""; }; B086FD1E0F0B9EE100955E23 /* res */ = { isa = PBXGroup; children = ( B086FD1F0F0B9EE100955E23 /* jdoom64.dll.manifest */, B086FD200F0B9EE100955E23 /* jdoom64.ico */, B086FD210F0B9EE100955E23 /* jdoom64.rc */, B086FD220F0B9EE100955E23 /* resource.h */, ); path = res; sourceTree = ""; }; B086FD230F0B9EE100955E23 /* src */ = { isa = PBXGroup; children = ( B086FD240F0B9EE100955E23 /* acfnlink.c */, B086FD250F0B9EE100955E23 /* d_api.c */, B086FD260F0B9EE100955E23 /* d_console.c */, B086FD270F0B9EE100955E23 /* d_items.c */, B086FD280F0B9EE100955E23 /* d_main.c */, B086FD290F0B9EE100955E23 /* d_refresh.c */, B086FD2A0F0B9EE100955E23 /* g_ctrl.c */, B086FD2B0F0B9EE100955E23 /* m_cheat.c */, B086FD2C0F0B9EE100955E23 /* m_random.c */, B086FD2D0F0B9EE100955E23 /* p_enemy.c */, B086FD2E0F0B9EE100955E23 /* p_inter.c */, B086FD2F0F0B9EE100955E23 /* p_lights.c */, B086FD300F0B9EE100955E23 /* p_maputl.c */, B086FD310F0B9EE100955E23 /* p_mobj.c */, B086FD320F0B9EE100955E23 /* p_pspr.c */, B086FD330F0B9EE100955E23 /* p_setup.c */, B086FD340F0B9EE100955E23 /* p_sound.c */, B086FD350F0B9EE100955E23 /* p_spec.c */, B086FD360F0B9EE100955E23 /* p_telept.c */, B086FD370F0B9EE100955E23 /* st_stuff.c */, B086FD380F0B9EE100955E23 /* tables.c */, B086FD390F0B9EE100955E23 /* wi_stuff.c */, ); path = src; sourceTree = ""; }; B086FD3A0F0B9EE100955E23 /* jheretic */ = { isa = PBXGroup; children = ( B086FD3B0F0B9EE100955E23 /* api */, B086FD3D0F0B9EE100955E23 /* CMakeLists.txt */, B086FD3E0F0B9EE100955E23 /* config */, B086FD400F0B9EE100955E23 /* data */, B086FD510F0B9EE100955E23 /* defs */, B086FD5F0F0B9EE100955E23 /* doc */, B086FD620F0B9EE100955E23 /* include */, B086FD8E0F0B9EE100955E23 /* res */, B086FD930F0B9EE100955E23 /* src */, ); path = jheretic; sourceTree = ""; }; B086FD3B0F0B9EE100955E23 /* api */ = { isa = PBXGroup; children = ( B086FD3C0F0B9EE100955E23 /* jheretic.def */, ); path = api; sourceTree = ""; }; B086FD3E0F0B9EE100955E23 /* config */ = { isa = PBXGroup; children = ( B086FD3F0F0B9EE100955E23 /* startup.cfg */, ); path = config; sourceTree = ""; }; B086FD400F0B9EE100955E23 /* data */ = { isa = PBXGroup; children = ( B086FD410F0B9EE100955E23 /* conhelp.txt */, B086FD420F0B9EE100955E23 /* lumps */, ); path = data; sourceTree = ""; }; B086FD420F0B9EE100955E23 /* lumps */ = { isa = PBXGroup; children = ( B086FD430F0B9EE100955E23 /* e2endpcx.lmp */, B086FD440F0B9EE100955E23 /* fonta59.lmp */, B086FD450F0B9EE100955E23 /* fonta60.lmp */, B086FD460F0B9EE100955E23 /* fonta61.lmp */, B086FD470F0B9EE100955E23 /* fonta62.lmp */, B086FD480F0B9EE100955E23 /* fonta63.lmp */, B086FD490F0B9EE100955E23 /* fontb59.lmp */, B086FD4A0F0B9EE100955E23 /* fontb60.lmp */, B086FD4B0F0B9EE100955E23 /* fontb61.lmp */, B086FD4C0F0B9EE100955E23 /* fontb62.lmp */, B086FD4D0F0B9EE100955E23 /* fontb63.lmp */, B086FD4E0F0B9EE100955E23 /* mapmask.lmp */, B086FD4F0F0B9EE100955E23 /* menufog.lmp */, B086FD500F0B9EE100955E23 /* pal18to8.lmp */, ); path = lumps; sourceTree = ""; }; B086FD510F0B9EE100955E23 /* defs */ = { isa = PBXGroup; children = ( B086FD520F0B9EE100955E23 /* anim.ded */, B086FD530F0B9EE100955E23 /* audio.ded */, B086FD540F0B9EE100955E23 /* auto */, B086FD560F0B9EE100955E23 /* finales.ded */, B086FD570F0B9EE100955E23 /* jheretic.ded */, B086FD580F0B9EE100955E23 /* lights.ded */, B086FD590F0B9EE100955E23 /* maps.ded */, B086FD5A0F0B9EE100955E23 /* models.ded */, B086FD5B0F0B9EE100955E23 /* objects.ded */, B086FD5C0F0B9EE100955E23 /* special.ded */, B086FD5D0F0B9EE100955E23 /* sprites.ded */, B086FD5E0F0B9EE100955E23 /* text.ded */, ); path = defs; sourceTree = ""; }; B086FD540F0B9EE100955E23 /* auto */ = { isa = PBXGroup; children = ( B086FD550F0B9EE100955E23 /* Readme.txt */, ); path = auto; sourceTree = ""; }; B086FD5F0F0B9EE100955E23 /* doc */ = { isa = PBXGroup; children = ( B086FD600F0B9EE100955E23 /* LICENSE */, B086FD610F0B9EE100955E23 /* Models.txt */, ); path = doc; sourceTree = ""; }; B086FD620F0B9EE100955E23 /* include */ = { isa = PBXGroup; children = ( B086FD630F0B9EE100955E23 /* acfnlink.h */, B086FD640F0B9EE100955E23 /* doomdata.h */, B086FD650F0B9EE100955E23 /* doomdef.h */, B086FD660F0B9EE100955E23 /* dstrings.h */, B086FD670F0B9EE100955E23 /* g_ctrl.h */, B086FD680F0B9EE100955E23 /* g_game.h */, B086FD690F0B9EE100955E23 /* h_api.h */, B086FD6A0F0B9EE100955E23 /* h_config.h */, B086FD6B0F0B9EE100955E23 /* h_console.h */, B086FD6C0F0B9EE100955E23 /* h_event.h */, B086FD6D0F0B9EE100955E23 /* h_items.h */, B086FD6E0F0B9EE100955E23 /* h_main.h */, B086FD6F0F0B9EE100955E23 /* h_player.h */, B086FD700F0B9EE100955E23 /* h_refresh.h */, B086FD710F0B9EE100955E23 /* h_stat.h */, B086FD720F0B9EE100955E23 /* h_think.h */, B086FD730F0B9EE100955E23 /* h_type.h */, B086FD740F0B9EE100955E23 /* in_lude.h */, B086FD750F0B9EE100955E23 /* info.h */, B086FD760F0B9EE100955E23 /* jheretic.h */, B086FD770F0B9EE100955E23 /* m_cheat.h */, B086FD780F0B9EE100955E23 /* m_menu.h */, B086FD790F0B9EE100955E23 /* m_random.h */, B086FD7A0F0B9EE100955E23 /* mn_def.h */, B086FD7B0F0B9EE100955E23 /* p_enemy.h */, B086FD7C0F0B9EE100955E23 /* p_inter.h */, B086FD7D0F0B9EE100955E23 /* p_lights.h */, B086FD7E0F0B9EE100955E23 /* p_local.h */, B086FD7F0F0B9EE100955E23 /* p_maputl.h */, B086FD800F0B9EE100955E23 /* p_mobj.h */, B086FD810F0B9EE100955E23 /* p_oldsvg.h */, B086FD820F0B9EE100955E23 /* p_pspr.h */, B086FD830F0B9EE100955E23 /* p_setup.h */, B086FD840F0B9EE100955E23 /* p_sound.h */, B086FD850F0B9EE100955E23 /* p_spec.h */, B086FD860F0B9EE100955E23 /* p_telept.h */, B086FD870F0B9EE100955E23 /* r_data.h */, B086FD880F0B9EE100955E23 /* r_defs.h */, B086FD890F0B9EE100955E23 /* r_local.h */, B086FD8A0F0B9EE100955E23 /* resource.h */, B086FD8B0F0B9EE100955E23 /* st_stuff.h */, B086FD8C0F0B9EE100955E23 /* tables.h */, B086FD8D0F0B9EE100955E23 /* version.h */, ); path = include; sourceTree = ""; }; B086FD8E0F0B9EE100955E23 /* res */ = { isa = PBXGroup; children = ( B086FD8F0F0B9EE100955E23 /* jheretic.dll.manifest */, B086FD900F0B9EE100955E23 /* jheretic.ico */, B086FD910F0B9EE100955E23 /* jheretic.rc */, B086FD920F0B9EE100955E23 /* resource.h */, ); path = res; sourceTree = ""; }; B086FD930F0B9EE100955E23 /* src */ = { isa = PBXGroup; children = ( B086FD940F0B9EE100955E23 /* acfnlink.c */, B086FD950F0B9EE100955E23 /* g_ctrl.c */, B086FD960F0B9EE100955E23 /* h_api.c */, B086FD970F0B9EE100955E23 /* h_console.c */, B086FD980F0B9EE100955E23 /* h_main.c */, B086FD990F0B9EE100955E23 /* h_refresh.c */, B086FD9A0F0B9EE100955E23 /* in_lude.c */, B086FD9B0F0B9EE100955E23 /* m_cheat.c */, B086FD9C0F0B9EE100955E23 /* m_random.c */, B086FD9D0F0B9EE100955E23 /* p_enemy.c */, B086FD9E0F0B9EE100955E23 /* p_inter.c */, B086FD9F0F0B9EE100955E23 /* p_lights.c */, B086FDA00F0B9EE100955E23 /* p_maputl.c */, B086FDA10F0B9EE100955E23 /* p_mobj.c */, B086FDA20F0B9EE100955E23 /* p_oldsvg.c */, B086FDA30F0B9EE100955E23 /* p_pspr.c */, B086FDA40F0B9EE100955E23 /* p_setup.c */, B086FDA50F0B9EE100955E23 /* p_sound.c */, B086FDA60F0B9EE100955E23 /* p_spec.c */, B086FDA70F0B9EE100955E23 /* p_telept.c */, B086FDA80F0B9EE100955E23 /* st_stuff.c */, B086FDA90F0B9EE100955E23 /* tables.c */, ); path = src; sourceTree = ""; }; B086FDAA0F0B9EE100955E23 /* jhexen */ = { isa = PBXGroup; children = ( B086FDAB0F0B9EE100955E23 /* api */, B086FDAD0F0B9EE100955E23 /* CMakeLists.txt */, B086FDAE0F0B9EE100955E23 /* config */, B086FDB00F0B9EE100955E23 /* data */, B086FDF70F0B9EE200955E23 /* defs */, B086FE050F0B9EE200955E23 /* doc */, B086FE080F0B9EE200955E23 /* include */, B086FE3A0F0B9EE200955E23 /* res */, B086FE3F0F0B9EE200955E23 /* src */, ); path = jhexen; sourceTree = ""; }; B086FDAB0F0B9EE100955E23 /* api */ = { isa = PBXGroup; children = ( B086FDAC0F0B9EE100955E23 /* jhexen.def */, ); path = api; sourceTree = ""; }; B086FDAE0F0B9EE100955E23 /* config */ = { isa = PBXGroup; children = ( B086FDAF0F0B9EE100955E23 /* startup.cfg */, ); path = config; sourceTree = ""; }; B086FDB00F0B9EE100955E23 /* data */ = { isa = PBXGroup; children = ( B086FDB10F0B9EE100955E23 /* conhelp.txt */, B086FDB20F0B9EE100955E23 /* lumps */, ); path = data; sourceTree = ""; }; B086FDB20F0B9EE100955E23 /* lumps */ = { isa = PBXGroup; children = ( B086FDB30F0B9EE100955E23 /* armslot1.lmp */, B086FDB40F0B9EE100955E23 /* armslot2.lmp */, B086FDB50F0B9EE100955E23 /* armslot3.lmp */, B086FDB60F0B9EE100955E23 /* armslot4.lmp */, B086FDB70F0B9EE100955E23 /* chain.lmp */, B086FDB80F0B9EE100955E23 /* chain2.lmp */, B086FDB90F0B9EE100955E23 /* chain3.lmp */, B086FDBA0F0B9EE100955E23 /* fonta59.lmp */, B086FDBB0F0B9EE100955E23 /* fonta60.lmp */, B086FDBC0F0B9EE100955E23 /* fonta61.lmp */, B086FDBD0F0B9EE100955E23 /* fonta62.lmp */, B086FDBE0F0B9EE100955E23 /* fonta63.lmp */, B086FDBF0F0B9EE100955E23 /* fontb59.lmp */, B086FDC00F0B9EE100955E23 /* fontb60.lmp */, B086FDC10F0B9EE100955E23 /* fontb61.lmp */, B086FDC20F0B9EE100955E23 /* fontb62.lmp */, B086FDC30F0B9EE100955E23 /* fontb63.lmp */, B086FDC40F0B9EE100955E23 /* keyslot1.lmp */, B086FDC50F0B9EE100955E23 /* keyslot2.lmp */, B086FDC60F0B9EE100955E23 /* keyslot3.lmp */, B086FDC70F0B9EE100955E23 /* keyslot4.lmp */, B086FDC80F0B9EE100955E23 /* keyslot5.lmp */, B086FDC90F0B9EE100955E23 /* keyslot6.lmp */, B086FDCA0F0B9EE100955E23 /* keyslot7.lmp */, B086FDCB0F0B9EE100955E23 /* keyslot8.lmp */, B086FDCC0F0B9EE100955E23 /* keyslot9.lmp */, B086FDCD0F0B9EE100955E23 /* keyslota.lmp */, B086FDCE0F0B9EE100955E23 /* keyslotb.lmp */, B086FDCF0F0B9EE100955E23 /* lifegem.lmp */, B086FDD00F0B9EE100955E23 /* lifegmc1.lmp */, B086FDD10F0B9EE100955E23 /* lifegmc2.lmp */, B086FDD20F0B9EE100955E23 /* lifegmc3.lmp */, B086FDD30F0B9EE100955E23 /* lifegmc4.lmp */, B086FDD40F0B9EE200955E23 /* lifegmc5.lmp */, B086FDD50F0B9EE200955E23 /* lifegmc6.lmp */, B086FDD60F0B9EE200955E23 /* lifegmc7.lmp */, B086FDD70F0B9EE200955E23 /* lifegmc8.lmp */, B086FDD80F0B9EE200955E23 /* lifegmf2.lmp */, B086FDD90F0B9EE200955E23 /* lifegmf3.lmp */, B086FDDA0F0B9EE200955E23 /* lifegmf4.lmp */, B086FDDB0F0B9EE200955E23 /* lifegmf5.lmp */, B086FDDC0F0B9EE200955E23 /* lifegmf6.lmp */, B086FDDD0F0B9EE200955E23 /* lifegmf7.lmp */, B086FDDE0F0B9EE200955E23 /* lifegmf8.lmp */, B086FDDF0F0B9EE200955E23 /* lifegmm1.lmp */, B086FDE00F0B9EE200955E23 /* lifegmm2.lmp */, B086FDE10F0B9EE200955E23 /* lifegmm3.lmp */, B086FDE20F0B9EE200955E23 /* lifegmm4.lmp */, B086FDE30F0B9EE200955E23 /* lifegmm5.lmp */, B086FDE40F0B9EE200955E23 /* lifegmm6.lmp */, B086FDE50F0B9EE200955E23 /* lifegmm7.lmp */, B086FDE60F0B9EE200955E23 /* lifegmm8.lmp */, B086FDE70F0B9EE200955E23 /* mapmask.lmp */, B086FDE80F0B9EE200955E23 /* menufog.lmp */, B086FDE90F0B9EE200955E23 /* pal18to8.lmp */, B086FDEA0F0B9EE200955E23 /* travlpic.lmp */, B086FDEB0F0B9EE200955E23 /* wpfull0.lmp */, B086FDEC0F0B9EE200955E23 /* wpfull1.lmp */, B086FDED0F0B9EE200955E23 /* wpfull2.lmp */, B086FDEE0F0B9EE200955E23 /* wpiecec1.lmp */, B086FDEF0F0B9EE200955E23 /* wpiecec2.lmp */, B086FDF00F0B9EE200955E23 /* wpiecec3.lmp */, B086FDF10F0B9EE200955E23 /* wpiecef1.lmp */, B086FDF20F0B9EE200955E23 /* wpiecef2.lmp */, B086FDF30F0B9EE200955E23 /* wpiecef3.lmp */, B086FDF40F0B9EE200955E23 /* wpiecem1.lmp */, B086FDF50F0B9EE200955E23 /* wpiecem2.lmp */, B086FDF60F0B9EE200955E23 /* wpiecem3.lmp */, ); path = lumps; sourceTree = ""; }; B086FDF70F0B9EE200955E23 /* defs */ = { isa = PBXGroup; children = ( B086FDF80F0B9EE200955E23 /* anim.ded */, B086FDF90F0B9EE200955E23 /* audio.ded */, B086FDFA0F0B9EE200955E23 /* auto */, B086FDFC0F0B9EE200955E23 /* finales.ded */, B086FDFD0F0B9EE200955E23 /* jhexen.ded */, B086FDFE0F0B9EE200955E23 /* lights.ded */, B086FDFF0F0B9EE200955E23 /* maps.ded */, B086FE000F0B9EE200955E23 /* models.ded */, B086FE010F0B9EE200955E23 /* objects.ded */, B086FE020F0B9EE200955E23 /* special.ded */, B086FE030F0B9EE200955E23 /* sprites.ded */, B086FE040F0B9EE200955E23 /* text.ded */, ); path = defs; sourceTree = ""; }; B086FDFA0F0B9EE200955E23 /* auto */ = { isa = PBXGroup; children = ( B086FDFB0F0B9EE200955E23 /* Readme.txt */, ); path = auto; sourceTree = ""; }; B086FE050F0B9EE200955E23 /* doc */ = { isa = PBXGroup; children = ( B086FE060F0B9EE200955E23 /* LICENSE */, B086FE070F0B9EE200955E23 /* Models.txt */, ); path = doc; sourceTree = ""; }; B086FE080F0B9EE200955E23 /* include */ = { isa = PBXGroup; children = ( B086FE090F0B9EE200955E23 /* a_action.h */, B086FE0A0F0B9EE200955E23 /* acfnlink.h */, B086FE0B0F0B9EE200955E23 /* dstrings.h */, B086FE0C0F0B9EE200955E23 /* g_ctrl.h */, B086FE0D0F0B9EE200955E23 /* g_game.h */, B086FE0E0F0B9EE200955E23 /* h2def.h */, B086FE0F0F0B9EE200955E23 /* in_lude.h */, B086FE100F0B9EE200955E23 /* info.h */, B086FE110F0B9EE200955E23 /* jhexen.h */, B086FE120F0B9EE200955E23 /* m_cheat.h */, B086FE130F0B9EE200955E23 /* m_menu.h */, B086FE140F0B9EE200955E23 /* m_random.h */, B086FE150F0B9EE200955E23 /* mn_def.h */, B086FE160F0B9EE200955E23 /* p_acs.h */, B086FE170F0B9EE200955E23 /* p_anim.h */, B086FE180F0B9EE200955E23 /* p_enemy.h */, B086FE190F0B9EE200955E23 /* p_inter.h */, B086FE1A0F0B9EE200955E23 /* p_lights.h */, B086FE1B0F0B9EE200955E23 /* p_local.h */, B086FE1C0F0B9EE200955E23 /* p_mapinfo.h */, B086FE1D0F0B9EE200955E23 /* p_maputl.h */, B086FE1E0F0B9EE200955E23 /* p_mobj.h */, B086FE1F0F0B9EE200955E23 /* p_pillar.h */, B086FE200F0B9EE200955E23 /* p_pspr.h */, B086FE210F0B9EE200955E23 /* p_setup.h */, B086FE220F0B9EE200955E23 /* p_sound.h */, B086FE230F0B9EE200955E23 /* p_spec.h */, B086FE240F0B9EE200955E23 /* p_telept.h */, B086FE250F0B9EE200955E23 /* p_things.h */, B086FE260F0B9EE200955E23 /* p_waggle.h */, B086FE270F0B9EE200955E23 /* po_man.h */, B086FE280F0B9EE200955E23 /* r_defs.h */, B086FE290F0B9EE200955E23 /* r_local.h */, B086FE2A0F0B9EE200955E23 /* s_sequence.h */, B086FE2B0F0B9EE200955E23 /* sc_man.h */, B086FE2C0F0B9EE200955E23 /* st_stuff.h */, B086FE2D0F0B9EE200955E23 /* textdefs.h */, B086FE2E0F0B9EE200955E23 /* version.h */, B086FE2F0F0B9EE200955E23 /* x_api.h */, B086FE300F0B9EE200955E23 /* x_config.h */, B086FE310F0B9EE200955E23 /* x_console.h */, B086FE320F0B9EE200955E23 /* x_event.h */, B086FE330F0B9EE200955E23 /* x_items.h */, B086FE340F0B9EE200955E23 /* x_main.h */, B086FE350F0B9EE200955E23 /* x_player.h */, B086FE360F0B9EE200955E23 /* x_refresh.h */, B086FE370F0B9EE200955E23 /* x_state.h */, B086FE380F0B9EE200955E23 /* x_think.h */, B086FE390F0B9EE200955E23 /* xddefs.h */, ); path = include; sourceTree = ""; }; B086FE3A0F0B9EE200955E23 /* res */ = { isa = PBXGroup; children = ( B086FE3B0F0B9EE200955E23 /* jhexen.dll.manifest */, B086FE3C0F0B9EE200955E23 /* jhexen.ico */, B086FE3D0F0B9EE200955E23 /* jhexen.rc */, B086FE3E0F0B9EE200955E23 /* resource.h */, ); path = res; sourceTree = ""; }; B086FE3F0F0B9EE200955E23 /* src */ = { isa = PBXGroup; children = ( B086FE400F0B9EE200955E23 /* a_action.c */, B086FE410F0B9EE200955E23 /* acfnlink.c */, B086FE420F0B9EE200955E23 /* g_ctrl.c */, B086FE430F0B9EE200955E23 /* h2_main.c */, B086FE440F0B9EE200955E23 /* hconsole.c */, B086FE450F0B9EE200955E23 /* hrefresh.c */, B086FE460F0B9EE200955E23 /* in_lude.c */, B086FE470F0B9EE200955E23 /* m_cheat.c */, B086FE480F0B9EE200955E23 /* m_random.c */, B086FE490F0B9EE200955E23 /* p_acs.c */, B086FE4A0F0B9EE200955E23 /* p_anim.c */, B086FE4B0F0B9EE200955E23 /* p_enemy.c */, B086FE4C0F0B9EE200955E23 /* p_inter.c */, B086FE4D0F0B9EE200955E23 /* p_lights.c */, B086FE4E0F0B9EE200955E23 /* p_mapinfo.c */, B086FE4F0F0B9EE200955E23 /* p_maputl.c */, B086FE500F0B9EE200955E23 /* p_mobj.c */, B086FE510F0B9EE200955E23 /* p_pillar.c */, B086FE520F0B9EE200955E23 /* p_pspr.c */, B086FE530F0B9EE200955E23 /* p_setup.c */, B086FE540F0B9EE200955E23 /* p_sound.c */, B086FE550F0B9EE200955E23 /* p_spec.c */, B086FE560F0B9EE200955E23 /* p_telept.c */, B086FE570F0B9EE200955E23 /* p_things.c */, B086FE580F0B9EE200955E23 /* p_waggle.c */, B086FE590F0B9EE200955E23 /* po_man.c */, B086FE5A0F0B9EE200955E23 /* sc_man.c */, B086FE5B0F0B9EE200955E23 /* sn_sonix.c */, B086FE5C0F0B9EE200955E23 /* st_stuff.c */, B086FE5D0F0B9EE200955E23 /* tables.c */, B086FE5E0F0B9EE200955E23 /* x_api.c */, ); path = src; sourceTree = ""; }; B086FE5F0F0B9EE200955E23 /* openal */ = { isa = PBXGroup; children = ( B086FE600F0B9EE200955E23 /* api */, B086FE620F0B9EE200955E23 /* CMakeLists.txt */, B086FE630F0B9EE200955E23 /* doc */, B086FE650F0B9EE200955E23 /* src */, ); path = openal; sourceTree = ""; }; B086FE600F0B9EE200955E23 /* api */ = { isa = PBXGroup; children = ( B086FE610F0B9EE200955E23 /* dsopenal.def */, ); path = api; sourceTree = ""; }; B086FE630F0B9EE200955E23 /* doc */ = { isa = PBXGroup; children = ( B086FE640F0B9EE200955E23 /* LICENSE */, ); path = doc; sourceTree = ""; }; B086FE650F0B9EE200955E23 /* src */ = { isa = PBXGroup; children = ( B086FE660F0B9EE200955E23 /* driver_openal.c */, ); path = src; sourceTree = ""; }; B086FE670F0B9EE200955E23 /* wadmapconverter */ = { isa = PBXGroup; children = ( B086FE680F0B9EE200955E23 /* CMakeLists.txt */, B086FE690F0B9EE200955E23 /* include */, B086FE6B0F0B9EE200955E23 /* src */, ); path = wadmapconverter; sourceTree = ""; }; B086FE690F0B9EE200955E23 /* include */ = { isa = PBXGroup; children = ( B086FE6A0F0B9EE200955E23 /* wadmapconverter.h */, ); path = include; sourceTree = ""; }; B086FE6B0F0B9EE200955E23 /* src */ = { isa = PBXGroup; children = ( B086FE6C0F0B9EE200955E23 /* load.c */, B086FE6D0F0B9EE200955E23 /* wadmapconverter.c */, ); path = src; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXLegacyTarget section */ B0100E280EAB844D000291AF /* Make All */ = { isa = PBXLegacyTarget; buildArgumentsString = "$(ACTION)"; buildConfigurationList = B0100E2D0EAB8477000291AF /* Build configuration list for PBXLegacyTarget "Make All" */; buildPhases = ( ); buildToolPath = /usr/bin/make; buildWorkingDirectory = "/Users/jaakko/Projects/deng/release-branch/doomsday/mybuild"; dependencies = ( ); name = "Make All"; passBuildSettingsInEnvironment = 1; productName = "Make All"; }; /* End PBXLegacyTarget section */ /* Begin PBXProject section */ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; buildConfigurationList = B01078300856208A000BF0D8 /* Build configuration list for PBXProject "Doomsday" */; compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 29B97314FDCFA39411CA2CEA /* Doomsday */; projectDirPath = ""; projectRoot = ../..; targets = ( B0100E280EAB844D000291AF /* Make All */, ); }; /* End PBXProject section */ /* Begin PBXVariantGroup section */ B086F9BF0F0B9EDD00955E23 /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( B086F9C00F0B9EDD00955E23 /* English */, ); name = InfoPlist.strings; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ B0100E290EAB844D000291AF /* Development */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; PRODUCT_NAME = "Make All"; }; name = Development; }; B0100E2A0EAB844D000291AF /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_ENABLE_FIX_AND_CONTINUE = NO; PRODUCT_NAME = "Make All"; ZERO_LINK = NO; }; name = Deployment; }; B0100E2B0EAB844D000291AF /* Default */ = { isa = XCBuildConfiguration; buildSettings = { PRODUCT_NAME = "Make All"; }; name = Default; }; B01078310856208A000BF0D8 /* Development */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = ( ppc, i386, ); GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; GCC_WARN_ABOUT_POINTER_SIGNEDNESS = NO; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO; GCC_WARN_UNUSED_LABEL = YES; MACOSX_DEPLOYMENT_TARGET = 10.4; WARNING_CFLAGS = ( "-Wimplicit-function-declaration", "-Wno-four-char-constants", "-Wno-unknown-pragmas", ); }; name = Development; }; B01078320856208A000BF0D8 /* Deployment */ = { isa = XCBuildConfiguration; buildSettings = { GCC_TREAT_WARNINGS_AS_ERRORS = NO; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; GCC_WARN_ABOUT_MISSING_NEWLINE = YES; GCC_WARN_ABOUT_MISSING_PROTOTYPES = NO; GCC_WARN_ABOUT_POINTER_SIGNEDNESS = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ALLOW_INCOMPLETE_PROTOCOL = NO; GCC_WARN_CHECK_SWITCH_STATEMENTS = YES; GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES; GCC_WARN_MISSING_PARENTHESES = YES; GCC_WARN_PEDANTIC = NO; GCC_WARN_SHADOW = NO; GCC_WARN_SIGN_COMPARE = NO; GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VALUE = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.3; }; name = Deployment; }; B01078330856208A000BF0D8 /* Default */ = { isa = XCBuildConfiguration; buildSettings = { MACOSX_DEPLOYMENT_TARGET = 10.3; }; name = Default; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ B0100E2D0EAB8477000291AF /* Build configuration list for PBXLegacyTarget "Make All" */ = { isa = XCConfigurationList; buildConfigurations = ( B0100E290EAB844D000291AF /* Development */, B0100E2A0EAB844D000291AF /* Deployment */, B0100E2B0EAB844D000291AF /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; B01078300856208A000BF0D8 /* Build configuration list for PBXProject "Doomsday" */ = { isa = XCConfigurationList; buildConfigurations = ( B01078310856208A000BF0D8 /* Development */, B01078320856208A000BF0D8 /* Deployment */, B01078330856208A000BF0D8 /* Default */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Default; }; /* End XCConfigurationList section */ }; rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; } deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/Makefile0000644000175000017500000000162111357170240020362 0ustar keeskees.PHONY : fonts FONT_DEST=../Data/Fonts fonts: ./createfont_osx.py "Gill Sans" 12 256 ${FONT_DEST}/normal12.dfn ./createfont_osx.py "Gill Sans" 18 256 ${FONT_DEST}/normal18.dfn ./createfont_osx.py "Gill Sans" 24 256 ${FONT_DEST}/normal24.dfn ./createfont_osx.py "Gill Sans Bold" 12 256 ${FONT_DEST}/normalbold12.dfn ./createfont_osx.py "Gill Sans Bold" 18 256 ${FONT_DEST}/normalbold18.dfn ./createfont_osx.py "Gill Sans Bold" 24 256 ${FONT_DEST}/normalbold24.dfn ./createfont_osx.py "Gill Sans Light" 12 256 ${FONT_DEST}/normallight12.dfn ./createfont_osx.py "Gill Sans Light" 18 256 ${FONT_DEST}/normallight18.dfn ./createfont_osx.py "Gill Sans Light" 24 256 ${FONT_DEST}/normallight24.dfn ./createfont_osx.py "Andale Mono" 11 256 ${FONT_DEST}/console11.dfn ./createfont_osx.py "Andale Mono" 14 256 ${FONT_DEST}/console14.dfn ./createfont_osx.py "Andale Mono" 18 256 ${FONT_DEST}/console18.dfn deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/Info.plist0000644000175000017500000000131211357170240020667 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable Doomsday CFBundleIconFile deng.icns CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.9.0 NSMainNibFile MainMenu NSPrincipalClass NSApplication deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/jHeretic-Info.plist0000644000175000017500000000124411357170240022426 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable jHeretic CFBundleIdentifier net.sourceforge.deng.jHeretic CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/dpWADMapConverter-Info.plist0000644000175000017500000000124711357170240024161 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable dpWADMapLoader CFBundleIdentifier net.sourceforge.deng.dpWADMapLoader CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/jDoom64-Info.plist0000644000175000017500000000124211357170240022111 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable jDoom64 CFBundleIdentifier net.sourceforge.deng.jDoom64 CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/mac/dpMapLoad-Info.plist0000644000175000017500000000124611357170240022534 0ustar keeskees CFBundleDevelopmentRegion English CFBundleExecutable dpMapLoad CFBundleIdentifier net.sourceforge.deng.dpMapLoad CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType APPL CFBundleSignature ???? CFBundleVersion 1.0 CSResourcesFileMapped yes deng-1.9.0-beta6.9+dfsg1/doomsday/build/scripts/0000755000175000017500000000000011523516205017651 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/build/scripts/packres.py0000755000175000017500000000620011357170240021654 0ustar keeskees#!/usr/bin/python # This Python script will create a set of PK3 files that contain the files # that Doomsday needs at runtime. The PK3 files are organized using the # traditional data/ and defs/ structure. import sys, os, os.path, zipfile if len(sys.argv) < 2: print "Usage: %s pk3-target-dir" % sys.argv[0] print "(run in build/scripts/)" sys.exit(0) deng_dir = os.path.join('..', '..') target_dir = sys.argv[1] class Pack: def __init__(self): self.files = [] # tuples def add_files(self, fileNamesArray): self.files += fileNamesArray def create(self, name): full_name = os.path.join(target_dir, name) print "creating %s as %s" % (name, full_name) pk3 = zipfile.ZipFile(full_name, 'w', zipfile.ZIP_DEFLATED) for src, dest in self.files: full_src = os.path.join(deng_dir, src) # Is this a file or a folder? if os.path.isfile(full_src): # Write the file as is. print "writing %s as %s" % (full_src, dest) pk3.write(full_src, dest) elif os.path.isdir(full_src): # Write the contents of the folder recursively. def process_dir(path, dest_path): print "processing", path for file in os.listdir(path): real_file = os.path.join(path, file) if file[0] == '.': continue # Ignore these. if os.path.isfile(real_file): print "writing %s as %s" % (real_file, os.path.join(dest_path, file)) pk3.write(real_file, os.path.join(dest_path, file)) elif os.path.isdir(real_file): process_dir(real_file, os.path.join(dest_path, file)) process_dir(full_src, dest) # Write it out. print "closing", full_name pk3.close() # First up, doomsday.pk3. # Directory contents added recursively. p = Pack() p.add_files( [ ('engine/defs', 'defs'), ('engine/data', 'data') ] ) p.create('doomsday.pk3') # jdoom.pk3 p = Pack() p.add_files( [ ('plugins/jdoom/defs', 'defs/jdoom'), ('plugins/jdoom/data/conhelp.txt', 'data/jdoom/conhelp.txt'), ('plugins/jdoom/data/lumps', '#.basedata') ] ) p.create('jdoom.pk3') # jheretic.pk3 p = Pack() p.add_files( [ ('plugins/jheretic/defs', 'defs/jheretic'), ('plugins/jheretic/data/conhelp.txt', 'data/jheretic/conhelp.txt'), ('plugins/jheretic/data/lumps', '#.basedata') ] ) p.create('jheretic.pk3') # jhexen.pk3 p = Pack() p.add_files( [ ('plugins/jhexen/defs', 'defs/jhexen'), ('plugins/jhexen/data/conhelp.txt', 'data/jhexen/conhelp.txt'), ('plugins/jhexen/data/lumps', '#.basedata') ] ) p.create('jhexen.pk3') # jdoom64.pk3 p = Pack() p.add_files( [ ('plugins/jdoom64/defs', 'defs/jdoom64'), ('plugins/jdoom64/data/conhelp.txt', 'data/jdoom64/conhelp.txt'), ('plugins/jdoom64/data/lumps', '#.basedata') ] ) p.create('jdoom64.pk3') deng-1.9.0-beta6.9+dfsg1/doomsday/build/scripts/wadcompiler.py0000755000175000017500000001651111357170240022540 0ustar keeskees#!/usr/bin/python import sys, os.path, struct def split_name(name): if '@' in name: pos = name.index('@') return (name[:pos], name[pos+1:]) else: return (name, name) def valid_lump_name(name): n = name.upper() if len(n) > 8: # Truncate. n = n[:8] elif len(n) < 8: # Pad with zeroes. n += chr(0) * (8 - len(n)) return n class Lump: def __init__(self, name, data, offset): if chr(0) in name: name = name[:name.index(chr(0))] self.name = name self.data = data self.offset = offset def nice_name(self): return self.name.strip(chr(0)) class Wad: def __init__(self, file_name, mode): self.file_name = file_name self.mode = mode self.file = file(file_name, mode) self.type = 'PWAD' self.lumps = [] if 'r' in mode: # lumps is a dictionary. self.read() def read(self): self.type = self.file.read(4) count = struct.unpack(' pair is two bytes long. If the longest match is no more than two characters, then we send just one character without encoding, and restart the process with the next letter. We must send one extra bit each time to tell the decoder whether we are sending a pair or an unencoded character, and these flags are stored as an eight bit mask every eight items. This implementation uses binary trees to speed up the search for the longest match. Original code by Haruhiko Okumura, 4/6/1989. 12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, Japan. Later modified for use in the Allegro filesystem by Shawn Hargreaves. Later still, modified to function as a stand-alone Win32 DLL by Jaakko Kernen. Currently used as a part of the Doomsday Engine: http://sf.net/projects/deng/ Use, distribute, and modify this code freely. */ /** \file * LZSS compression routines * These are the legacy LZSS compression routines. New code should not * use these routines, and instead should use zlib's deflate routines * if LZSS compression or decompression is required. * * This code does not build on Win32, and uses an inseure temporary * name generation. It is likely to be a possible security hole in future * and as such all code still using this should migrate to zlib's deflate * as soon as possible. * * For now LZSS compression is used by FileReader in engine/portable/src/m_misc.c * by plugins/jhexen/src/sv_save.c in many routines, and by * engine/portable/include/net_main.h in the Demo_* rouines. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #include #include #include #include #include "../../../engine/unix/include/sys_findfile.h" #include "lzss.h" // MACROS ------------------------------------------------------------------ #ifndef WIN32 //Disable this on Win32 builds because of: warning: "O_BINARY" redefined on mingw #define O_BINARY 0 #endif #define FILE_OPEN(filename, handle) handle = open(filename, O_RDONLY | O_BINARY) #define FILE_CREATE(filename, handle) handle = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC, 0664) #define FILE_CLOSE(handle) close(handle) #define FILE_READ(handle, buf, size, sz) sz = read(handle, buf, size) #define FILE_WRITE(handle, buf, size, sz) sz = write(handle, buf, size) #define FILE_SEARCH_STRUCT finddata_t #define FILE_FINDFIRST(filename, attrib, dta) myfindfirst(filename, dta) #define FILE_FINDNEXT(dta) myfindnext(dta) #define FILE_FINDCLOSE(dta) myfindend(dta) #define FILE_ATTRIB attrib #define FILE_SIZE size #define FILE_NAME name #define FILE_DATE date #define FILE_TIME time #define TRUE 1 #define FALSE 0 #ifndef MIN # define MIN(x,y) (((x) < (y)) ? (x) : (y)) # define MAX(x,y) (((x) > (y)) ? (x) : (y)) # define MID(x,y,z) MAX((x), MIN((y), (z))) #endif #define N 4096 /* 4k buffers for LZ compression */ #define F 18 /* upper limit for LZ match length */ #define THRESHOLD 2 /* LZ encode string into pos and length if match size is greater than this */ // TYPES ------------------------------------------------------------------- typedef struct PACK_DATA /* stuff for doing LZ compression */ { int state; /* where have we got to in the pack? */ int i, c, len, r, s; int last_match_length, code_buf_ptr; unsigned char mask; char code_buf[17]; int match_position; int match_length; int lson[N + 1]; /* left children, */ int rson[N + 257]; /* right children, */ int dad[N + 1]; /* and parents, = binary search trees */ unsigned char text_buf[N + F - 1]; /* ring buffer, with F-1 extra bytes for string comparison */ } PACK_DATA; typedef struct UNPACK_DATA /* for reading LZ files */ { int state; /* where have we got to? */ int i, j, k, r, c; int flags; unsigned char text_buf[N + F - 1]; /* ring buffer, with F-1 extra bytes for string comparison */ } UNPACK_DATA; // FUNCTION DECLARATIONS --------------------------------------------------- int FlushBuffer(LZFILE * f, int last); int RefillBuffer(LZFILE * f); // DATA -------------------------------------------------------------------- char thepassword[256] = ""; int _packfile_filesize = 0; int _packfile_datasize = 0; // CODE -------------------------------------------------------------------- /** * Helper function for the lzGetC() macro. */ int _sort_out_getc(LZFILE * f) { if(f->buf_size == 0) { if(f->todo <= 0) f->flags |= LZFILE_FLAG_EOF; return *(f->buf_pos++); } return RefillBuffer(f); } /** * Helper function for the lzPutC() macro. */ int _sort_out_putc(int c, LZFILE * f) { f->buf_size--; if(FlushBuffer(f, FALSE)) return EOF; f->buf_size++; return (*(f->buf_pos++) = c); } /** * For i = 0 to N-1, rson[i] and lson[i] will be the right and left * children of node i. These nodes need not be initialized. Also, dad[i] * is the parent of node i. These are initialized to N, which stands for * 'not used.' For i = 0 to 255, rson[N+i+1] is the root of the tree for * strings that begin with character i. These are initialized to N. Note * there are 256 trees. */ static void pack_inittree(PACK_DATA * dat) { int i; for(i = N + 1; i <= N + 256; i++) dat->rson[i] = N; for(i = 0; i < N; i++) dat->dad[i] = N; } /* pack_insertnode: * Inserts a string of length F, text_buf[r..r+F-1], into one of the trees * (text_buf[r]'th tree) and returns the longest-match position and length * via match_position and match_length. If match_length = F, then removes * the old node in favor of the new one, because the old one will be * deleted sooner. Note r plays double role, as tree node and position in * the buffer. */ static void pack_insertnode(int r, PACK_DATA * dat) { int i, p, cmp; unsigned char *key; unsigned char *text_buf = dat->text_buf; cmp = 1; key = &text_buf[r]; p = N + 1 + key[0]; dat->rson[r] = dat->lson[r] = N; dat->match_length = 0; for(;;) { if(cmp >= 0) { if(dat->rson[p] != N) p = dat->rson[p]; else { dat->rson[p] = r; dat->dad[r] = p; return; } } else { if(dat->lson[p] != N) p = dat->lson[p]; else { dat->lson[p] = r; dat->dad[r] = p; return; } } for(i = 1; i < F; i++) if((cmp = key[i] - text_buf[p + i]) != 0) break; if(i > dat->match_length) { dat->match_position = p; if((dat->match_length = i) >= F) break; } } dat->dad[r] = dat->dad[p]; dat->lson[r] = dat->lson[p]; dat->rson[r] = dat->rson[p]; dat->dad[dat->lson[p]] = r; dat->dad[dat->rson[p]] = r; if(dat->rson[dat->dad[p]] == p) dat->rson[dat->dad[p]] = r; else dat->lson[dat->dad[p]] = r; dat->dad[p] = N; /* remove p */ } /** * Removes a node from a tree. */ static void pack_deletenode(int p, PACK_DATA * dat) { int q; if(dat->dad[p] == N) return; /* not in tree */ if(dat->rson[p] == N) q = dat->lson[p]; else if(dat->lson[p] == N) q = dat->rson[p]; else { q = dat->lson[p]; if(dat->rson[q] != N) { do { q = dat->rson[q]; } while(dat->rson[q] != N); dat->rson[dat->dad[q]] = dat->lson[q]; dat->dad[dat->lson[q]] = dat->dad[q]; dat->lson[q] = dat->lson[p]; dat->dad[dat->lson[p]] = q; } dat->rson[q] = dat->rson[p]; dat->dad[dat->rson[p]] = q; } dat->dad[q] = dat->dad[p]; if(dat->rson[dat->dad[p]] == p) dat->rson[dat->dad[p]] = q; else dat->lson[dat->dad[p]] = q; dat->dad[p] = N; } /** * Called by FlushBuffer(). Packs size bytes from buf, using the pack * information contained in dat. Returns 0 on success. */ static int pack_write(LZFILE * file, PACK_DATA * dat, int size, unsigned char *buf, int last) { int i = dat->i; int c = dat->c; int len = dat->len; int r = dat->r; int s = dat->s; int last_match_length = dat->last_match_length; int code_buf_ptr = dat->code_buf_ptr; unsigned char mask = dat->mask; int ret = 0; if(dat->state == 2) goto pos2; else if(dat->state == 1) goto pos1; dat->code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and code_buf[0] works as eight flags, "1" representing that the unit is an unencoded letter (1 byte), "0" a position-and-length pair (2 bytes). Thus, eight units require at most 16 bytes of code. */ code_buf_ptr = mask = 1; s = 0; r = N - F; pack_inittree(dat); for(len = 0; (len < F) && (size > 0); len++) { dat->text_buf[r + len] = *(buf++); if(--size == 0) { if(!last) { dat->state = 1; goto getout; } } pos1: ; } if(len == 0) goto getout; for(i = 1; i <= F; i++) pack_insertnode(r - i, dat); /* Insert the F strings, each of which begins with one or more 'space' characters. Note the order in which these strings are inserted. This way, degenerate trees will be less likely to occur. */ pack_insertnode(r, dat); /* Finally, insert the whole string just read. match_length and match_position are set. */ do { if(dat->match_length > len) dat->match_length = len; /* match_length may be long near the end */ if(dat->match_length <= THRESHOLD) { dat->match_length = 1; /* not long enough match: send one byte */ dat->code_buf[0] |= mask; /* 'send one byte' flag */ dat->code_buf[code_buf_ptr++] = dat->text_buf[r]; /* send uncoded */ } else { /* send position and length pair. Note match_length > THRESHOLD */ dat->code_buf[code_buf_ptr++] = (unsigned char) dat->match_position; dat->code_buf[code_buf_ptr++] = (unsigned char) (((dat->match_position >> 4) & 0xF0) | (dat->match_length - (THRESHOLD + 1))); } if((mask <<= 1) == 0) { /* shift mask left one bit */ if(*file->password) { dat->code_buf[0] ^= *file->password; file->password++; if(!*file->password) file->password = thepassword; }; for(i = 0; i < code_buf_ptr; i++) /* send at most 8 units of */ lzPutC(dat->code_buf[i], file); /* code together */ if(lzError(file)) { ret = EOF; goto getout; } dat->code_buf[0] = 0; code_buf_ptr = mask = 1; } last_match_length = dat->match_length; for(i = 0; (i < last_match_length) && (size > 0); i++) { c = *(buf++); if(--size == 0) { if(!last) { dat->state = 2; goto getout; } } pos2: pack_deletenode(s, dat); /* delete old strings and */ dat->text_buf[s] = c; /* read new bytes */ if(s < F - 1) dat->text_buf[s + N] = c; /* if the position is near the end of buffer, extend the buffer to make string comparison easier */ s = (s + 1) & (N - 1); r = (r + 1) & (N - 1); /* since this is a ring buffer, increment the position modulo N */ pack_insertnode(r, dat); /* register the string in text_buf[r..r+F-1] */ } while(i++ < last_match_length) { /* after the end of text, */ pack_deletenode(s, dat); /* no need to read, but */ s = (s + 1) & (N - 1); /* buffer may not be empty */ r = (r + 1) & (N - 1); if(--len) pack_insertnode(r, dat); } } while(len > 0); /* until length of string to be processed is zero */ if(code_buf_ptr > 1) { /* send remaining code */ if(*file->password) { dat->code_buf[0] ^= *file->password; file->password++; if(!*file->password) file->password = thepassword; }; for(i = 0; i < code_buf_ptr; i++) { lzPutC(dat->code_buf[i], file); if(lzError(file)) { ret = EOF; goto getout; } } } dat->state = 0; getout: dat->i = i; dat->c = c; dat->len = len; dat->r = r; dat->s = s; dat->last_match_length = last_match_length; dat->code_buf_ptr = code_buf_ptr; dat->mask = mask; return ret; } /** * Called by RefillBuffer(). Unpacks from dat into buf, until either * EOF is reached or s bytes have been extracted. Returns the number of * bytes added to the buffer */ static int pack_read(LZFILE * file, UNPACK_DATA * dat, int s, unsigned char *buf) { int i = dat->i; int j = dat->j; int k = dat->k; int r = dat->r; int c = dat->c; unsigned int flags = dat->flags; int size = 0; if(dat->state == 2) goto pos2; else if(dat->state == 1) goto pos1; r = N - F; flags = 0; for(;;) { if(((flags >>= 1) & 256) == 0) { if((c = lzGetC(file)) == EOF) break; if(*file->password) { c ^= *file->password; file->password++; if(!*file->password) file->password = thepassword; }; flags = c | 0xFF00; /* uses higher byte to count eight */ } if(flags & 1) { if((c = lzGetC(file)) == EOF) break; dat->text_buf[r++] = c; r &= (N - 1); *(buf++) = c; if(++size >= s) { dat->state = 1; goto getout; } pos1: ; } else { if((i = lzGetC(file)) == EOF) break; if((j = lzGetC(file)) == EOF) break; i |= ((j & 0xF0) << 4); j = (j & 0x0F) + THRESHOLD; for(k = 0; k <= j; k++) { c = dat->text_buf[(i + k) & (N - 1)]; dat->text_buf[r++] = c; r &= (N - 1); *(buf++) = c; if(++size >= s) { dat->state = 2; goto getout; } pos2: ; } } } dat->state = 0; getout: dat->i = i; dat->j = j; dat->k = k; dat->r = r; dat->c = c; dat->flags = flags; return size; } /** * Helper for encrypting magic numbers, using the current password. */ long Encrypt(long x) { long mask = 0; int i; for(i = 0; thepassword[i]; i++) mask ^= ((long) thepassword[i] << ((i & 3) * 8)); return x ^ mask; } /** * Reads a 16 bit word from a file, using intel byte ordering. */ int lzGetW(LZFILE * f) { int b1, b2; if((b1 = lzGetC(f)) != EOF) if((b2 = lzGetC(f)) != EOF) return ((b2 << 8) | b1); return EOF; } /** * Reads a 32 bit long from a file, using intel byte ordering. */ long lzGetL(LZFILE * f) { int b1, b2, b3, b4; if((b1 = lzGetC(f)) != EOF) if((b2 = lzGetC(f)) != EOF) if((b3 = lzGetC(f)) != EOF) if((b4 = lzGetC(f)) != EOF) return (((long) b4 << 24) | ((long) b3 << 16) | ((long) b2 << 8) | (long) b1); return EOF; } /** * Writes a 16 bit int to a file, using intel byte ordering. */ int lzPutW(int w, LZFILE * f) { int b1, b2; b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if(lzPutC(b2, f) == b2) if(lzPutC(b1, f) == b1) return w; return EOF; } /** * Writes a 32 bit long to a file, using intel byte ordering. */ long lzPutL(long l, LZFILE * f) { int b1, b2, b3, b4; b1 = (int) ((l & 0xFF000000L) >> 24); b2 = (int) ((l & 0x00FF0000L) >> 16); b3 = (int) ((l & 0x0000FF00L) >> 8); b4 = (int) l & 0x00FF; if(lzPutC(b4, f) == b4) if(lzPutC(b3, f) == b3) if(lzPutC(b2, f) == b2) if(lzPutC(b1, f) == b1) return l; return EOF; } /** * Reads a 16 bit int from a file, using motorola byte-ordering. */ int lzGetWm(LZFILE * f) { int b1, b2; if((b1 = lzGetC(f)) != EOF) if((b2 = lzGetC(f)) != EOF) return ((b1 << 8) | b2); return EOF; } /** * Reads a 32 bit long from a file, using motorola byte-ordering. */ long lzGetLm(LZFILE * f) { int b1, b2, b3, b4; if((b1 = lzGetC(f)) != EOF) if((b2 = lzGetC(f)) != EOF) if((b3 = lzGetC(f)) != EOF) if((b4 = lzGetC(f)) != EOF) return (((long) b1 << 24) | ((long) b2 << 16) | ((long) b3 << 8) | (long) b4); return EOF; } /** * Writes a 16 bit int to a file, using motorola byte-ordering. */ int lzPutWm(int w, LZFILE * f) { int b1, b2; b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if(lzPutC(b1, f) == b1) if(lzPutC(b2, f) == b2) return w; return EOF; } /** * Writes a 32 bit long to a file, using motorola byte-ordering. */ long lzPutLm(long l, LZFILE * f) { int b1, b2, b3, b4; b1 = (int) ((l & 0xFF000000L) >> 24); b2 = (int) ((l & 0x00FF0000L) >> 16); b3 = (int) ((l & 0x0000FF00L) >> 8); b4 = (int) l & 0x00FF; if(lzPutC(b1, f) == b1) if(lzPutC(b2, f) == b2) if(lzPutC(b3, f) == b3) if(lzPutC(b4, f) == b4) return l; return EOF; } /** * Opens a file according to mode, which may contain any of the flags: * 'r': open file for reading. * 'w': open file for writing, overwriting any existing data. * 'p': open file in 'packed' mode. Data will be compressed as it is * written to the file, and automatically uncompressed during read * operations. Files created in this mode will produce garbage if * they are read without this flag being set. * '!': open file for writing in normal, unpacked mode, but add the value * F_NOPACK_MAGIC to the start of the file, so that it can be opened * in packed mode and Allegro will automatically detect that the * data does not need to be decompressed. * * Instead of these flags, one of the constants F_READ, F_WRITE, * F_READ_PACKED, F_WRITE_PACKED or F_WRITE_NOPACK may be used as the second * argument to fopen(). * * On success, fopen() returns a pointer to a file structure, and on error * it returns NULL and stores an error code in errno. An attempt to read a * normal file in packed mode will cause errno to be set to EDOM. */ LZFILE *lzOpen(char *filename, char *mode) { LZFILE *f, *f2; FILE_SEARCH_STRUCT dta; int c; long header = FALSE; errno = 0; if((f = malloc(sizeof(LZFILE))) == NULL) { errno = ENOMEM; return NULL; } f->buf_pos = f->buf; f->flags = 0; f->buf_size = 0; f->filename = NULL; f->password = thepassword; for(c = 0; mode[c]; c++) { switch (mode[c]) { case 'r': case 'R': f->flags &= ~LZFILE_FLAG_WRITE; break; case 'w': case 'W': f->flags |= LZFILE_FLAG_WRITE; break; case 'p': case 'P': f->flags |= LZFILE_FLAG_PACK; break; case '!': f->flags &= ~LZFILE_FLAG_PACK; header = TRUE; break; } } if(f->flags & LZFILE_FLAG_WRITE) { if(f->flags & LZFILE_FLAG_PACK) { /* write a packed file */ PACK_DATA *dat = malloc(sizeof(PACK_DATA)); if(!dat) { errno = ENOMEM; free(f); return NULL; } if((f->parent = lzOpen(filename, F_WRITE)) == NULL) { free(dat); free(f); return NULL; } lzPutLm(Encrypt(F_PACK_MAGIC), f->parent); f->todo = 4; for(c = 0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; f->pack_data = dat; } else { /* write a 'real' file */ f->parent = NULL; f->pack_data = NULL; FILE_CREATE(filename, f->hndl); if(f->hndl < 0) { free(f); return NULL; } errno = 0; f->todo = 0; } if(header) lzPutLm(Encrypt(F_NOPACK_MAGIC), f); } else { /* must be a read */ if(f->flags & LZFILE_FLAG_PACK) { /* read a packed file */ UNPACK_DATA *dat = malloc(sizeof(UNPACK_DATA)); if(!dat) { errno = ENOMEM; free(f); return NULL; } if((f->parent = lzOpen(filename, F_READ)) == NULL) { free(dat); free(f); return NULL; } header = lzGetLm(f->parent); if(header == Encrypt(F_PACK_MAGIC)) { for(c = 0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; f->todo = LONG_MAX; f->pack_data = (char *) dat; } else { if(header == Encrypt(F_NOPACK_MAGIC)) { f2 = f->parent; free(dat); free(f); return f2; } else { lzClose(f->parent); free(dat); free(f); if(errno == 0) errno = EDOM; return NULL; } } } else { /* read a 'real' file */ f->parent = NULL; f->pack_data = NULL; errno = FILE_FINDFIRST(filename, A_RDONLY | A_HIDDEN | A_ARCH, &dta); if(errno != 0) { FILE_FINDCLOSE(&dta); free(f); return NULL; } f->todo = dta.FILE_SIZE; FILE_FINDCLOSE(&dta); FILE_OPEN(filename, f->hndl); if(f->hndl < 0) { errno = f->hndl; free(f); return NULL; } } } return f; } /** * Closes a file after it has been read or written. * Returns zero on success. On error it returns an error code which is * also stored in errno. This function can fail only when writing to * files: if the file was opened in read mode it will always succeed. */ int lzClose(LZFILE * f) { if(f) { if(f->flags & LZFILE_FLAG_WRITE) { if(f->flags & LZFILE_FLAG_CHUNK) return lzClose(lzCloseChunk(f)); FlushBuffer(f, TRUE); } if(f->pack_data) free(f->pack_data); if(f->parent) lzClose(f->parent); else FILE_CLOSE(f->hndl); free(f); return errno; } return 0; } /** * Like the stdio fseek() function, but only supports forward seeks * relative to the current file position. */ int lzSeek(LZFILE * f, int offset) { int i; if(f->flags & LZFILE_FLAG_WRITE) return -1; errno = 0; /* skip forward through the buffer */ if(f->buf_size > 0) { i = MIN(offset, f->buf_size); f->buf_size -= i; f->buf_pos += i; offset -= i; if((f->buf_size <= 0) && (f->todo <= 0)) f->flags |= LZFILE_FLAG_EOF; } /* need to seek some more? */ if(offset > 0) { i = MIN(offset, f->todo); if(f->flags & LZFILE_FLAG_PACK) { /* for compressed files, we just have to read through the data */ while(i > 0) { lzGetC(f); i--; } } else { if(f->parent) { /* pass the seek request on to the parent file */ lzSeek(f->parent, i); } else { /* do a real seek */ lseek(f->hndl, i, SEEK_CUR); } f->todo -= i; if(f->todo <= 0) f->flags |= LZFILE_FLAG_EOF; } } return errno; } /** * Opens a sub-chunk of the specified file, for reading or writing depending * on the type of the file. The returned file pointer describes the sub * chunk, and replaces the original file, which will no longer be valid. * When writing to a chunk file, data is sent to the original file, but * is prefixed with two length counts (32 bit, big-endian). For uncompressed * chunks these will both be set to the length of the data in the chunk. * For compressed chunks, created by setting the pack flag, the first will * contain the raw size of the chunk, and the second will be the negative * size of the uncompressed data. When reading chunks, the pack flag is * ignored, and the compression type is detected from the sign of the * second size value. The file structure used to read chunks checks the * chunk size, and will return EOF if you try to read past the end of * the chunk. If you don't read all of the chunk data, when you call * lzCloseChunk(), the parent file will advance past the unused data. * When you have finished reading or writing a chunk, you should call * lzCloseChunk() to return to your original file. */ LZFILE *lzOpenChunk(LZFILE * f, int pack) { int c; char *name; LZFILE *chunk; if(f->flags & LZFILE_FLAG_WRITE) { /* write a sub-chunk */ name = tmpnam(NULL); chunk = lzOpen(name, (pack ? F_WRITE_PACKED : F_WRITE_NOPACK)); if(chunk) { chunk->filename = malloc(strlen(name) + 1); strcpy(chunk->filename, name); if(pack) chunk->parent->parent = f; else chunk->parent = f; chunk->flags |= LZFILE_FLAG_CHUNK; } } else { /* read a sub-chunk */ _packfile_filesize = lzGetLm(f); _packfile_datasize = lzGetLm(f); if((chunk = malloc(sizeof(LZFILE))) == NULL) { errno = ENOMEM; return NULL; } chunk->buf_pos = chunk->buf; chunk->flags = LZFILE_FLAG_CHUNK; chunk->buf_size = 0; chunk->filename = NULL; chunk->parent = f; chunk->password = f->password; f->password = thepassword; if(_packfile_datasize < 0) { /* read a packed chunk */ UNPACK_DATA *dat = malloc(sizeof(UNPACK_DATA)); if(!dat) { errno = ENOMEM; free(chunk); return NULL; } for(c = 0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; _packfile_datasize = -_packfile_datasize; chunk->todo = _packfile_datasize; chunk->pack_data = (char *) dat; chunk->flags |= LZFILE_FLAG_PACK; } else { /* read an uncompressed chunk */ chunk->todo = _packfile_datasize; chunk->pack_data = NULL; } } return chunk; } /** * Call after reading or writing a sub-chunk. This closes the chunk file, * and returns a pointer to the original file structure (the one you * passed to lzOpenChunk()), to allow you to read or write data * after the chunk. */ LZFILE *lzCloseChunk(LZFILE * f) { LZFILE *parent = f->parent; LZFILE *tmp; char *name = f->filename; int header; if(f->flags & LZFILE_FLAG_WRITE) { /* finish writing a chunk */ _packfile_datasize = f->todo + f->buf_size - 4; if(f->flags & LZFILE_FLAG_PACK) { parent = parent->parent; f->parent->parent = NULL; } else f->parent = NULL; f->flags &= ~LZFILE_FLAG_CHUNK; lzClose(f); tmp = lzOpen(name, F_READ); _packfile_filesize = tmp->todo - 4; header = lzGetLm(tmp); lzPutLm(_packfile_filesize, parent); if(header == Encrypt(F_PACK_MAGIC)) lzPutLm(-_packfile_datasize, parent); else lzPutLm(_packfile_datasize, parent); while(!lzEOF(tmp)) lzPutC(lzGetC(tmp), parent); lzClose(tmp); unlink(name); free(name); } else { /* finish reading a chunk */ while(f->todo > 0) lzGetC(f); parent->password = f->password; if(f->pack_data) free(f->pack_data); free(f); } return parent; } /** * Reads n bytes from f and stores them at memory location p. Returns the * number of items read, which will be less than n if EOF is reached or an * error occurs. Error codes are stored in errno. */ long lzRead(void *p, long n, LZFILE * f) { long c; /* counter of bytes read */ int i; unsigned char *cp = (unsigned char *) p; for(c = 0; c < n; c++) { if(--(f->buf_size) > 0) *(cp++) = *(f->buf_pos++); else { i = _sort_out_getc(f); if(i == EOF) return c; else *(cp++) = i; } } return n; } /** * Writes n bytes to the file f from memory location p. Returns the number * of items written, which will be less than n if an error occurs. Error * codes are stored in errno. */ long lzWrite(void *p, long n, LZFILE * f) { long c; /* counter of bytes written */ unsigned char *cp = (unsigned char *) p; for(c = 0; c < n; c++) { if(++(f->buf_size) >= F_BUF_SIZE) { if(_sort_out_putc(*cp, f) != *cp) return c; cp++; } else *(f->buf_pos++) = *(cp++); } return n; } /** * Reads a line from a text file, storing it at location p. Stops when a * linefeed is encountered, or max characters have been read. Returns a * pointer to where it stored the text, or NULL on error. The end of line * is handled by detecting '\n' characters: '\r' is simply ignored. */ char *lzGetS(char *p, int max, LZFILE * f) { int c; if(lzEOF(f)) { p[0] = 0; return NULL; } for(c = 0; c < max - 1; c++) { p[c] = lzGetC(f); if(p[c] == '\r') c--; else if(p[c] == '\n') break; } p[c] = 0; if(errno) return NULL; else return p; } /** * Writes a string to a text file, returning zero on success, -1 on error. * EOL ('\n') characters are expanded to CR/LF ('\r\n') pairs. */ int lzPutS(char *p, LZFILE * f) { while(*p) { if(*p == '\n') { lzPutC('\r', f); lzPutC('\n', f); } else lzPutC(*p, f); p++; } if(errno) return -1; else return 0; } /** * Refills the read buffer. The file must have been opened in read mode, * and the buffer must be empty. */ int RefillBuffer(LZFILE * f) { int sz; if((f->flags & LZFILE_FLAG_EOF) || (f->todo <= 0)) { /* EOF */ f->flags |= LZFILE_FLAG_EOF; return EOF; } if(f->parent) { if(f->flags & LZFILE_FLAG_PACK) { f->buf_size = pack_read(f->parent, (UNPACK_DATA *) f->pack_data, MIN(F_BUF_SIZE, f->todo), f->buf); } else { f->buf_size = lzRead(f->buf, MIN(F_BUF_SIZE, f->todo), f->parent); } if(f->parent->flags & LZFILE_FLAG_EOF) f->todo = 0; if(f->parent->flags & LZFILE_FLAG_ERROR) goto err; } else { f->buf_size = MIN(F_BUF_SIZE, f->todo); FILE_READ(f->hndl, f->buf, f->buf_size, sz); if(sz != f->buf_size) goto err; } f->todo -= f->buf_size; f->buf_pos = f->buf; f->buf_size--; if(f->buf_size <= 0) if(f->todo <= 0) f->flags |= LZFILE_FLAG_EOF; return *(f->buf_pos++); err: errno = EFAULT; f->flags |= LZFILE_FLAG_ERROR; return EOF; } /** * flushes a file buffer to the disk. The file must be open in write mode. */ int FlushBuffer(LZFILE * f, int last) { int sz; if(f->buf_size > 0) { if(f->flags & LZFILE_FLAG_PACK) { if(pack_write (f->parent, (PACK_DATA *) f->pack_data, f->buf_size, f->buf, last)) goto err; } else { FILE_WRITE(f->hndl, f->buf, f->buf_size, sz); if(sz != f->buf_size) goto err; } f->todo += f->buf_size; } f->buf_pos = f->buf; f->buf_size = 0; return 0; err: errno = EFAULT; f->flags |= LZFILE_FLAG_ERROR; return EOF; } int lzGetC(LZFILE * f) { f->buf_size--; if(f->buf_size > 0) return *(f->buf_pos++); else return _sort_out_getc(f); } int lzPutC(int c, LZFILE * f) { f->buf_size++; if(f->buf_size >= F_BUF_SIZE) return _sort_out_putc(c, f); else return (*(f->buf_pos++) = c); } /** * Sets the password to be used by all future read/write operations. */ void lzPassword(char *password) { if(password) { strncpy(thepassword, password, 255); thepassword[255] = 0; } else thepassword[0] = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/0000755000175000017500000000000011357170242020644 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/api/0000755000175000017500000000000011523516205021413 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/api/lzss.def0000644000175000017500000000057611357170242023100 0ustar keeskeesLIBRARY LZSS DESCRIPTION "Lempel-Ziv Compressed File I/O" EXPORTS lzPassword @1 lzOpen @2 lzClose @3 lzOpenChunk @4 lzCloseChunk @5 lzSeek @6 lzGetW @7 lzGetL @8 lzPutW @9 lzPutL @10 lzGetWm @11 lzGetLm @12 lzPutWm @13 lzPutLm @14 lzRead @15 lzWrite @16 lzGetS @17 lzPutS @18 lzGetC @19 lzPutC @20 deng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/src/0000755000175000017500000000000011357170242021433 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/src/main.c0000644000175000017500000007375511357170242022544 0ustar keeskees/* Lempel-Ziv Compressed File I/O Win32 DLL Original code by Haruhiko Okumura, 4/6/1989. 12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, Japan. Later modified for use in the Allegro filesystem by Shawn Hargreaves. Later still, modified to function as a stand-alone Win32 DLL by Jaakko Kernen. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #include "LZSS.h" #include "find.h" // MACROS ------------------------------------------------------------------ #define TRUE 1 #define FALSE 0 #ifndef MIN #define MIN(x,y) (((x) < (y)) ? (x) : (y)) #define MAX(x,y) (((x) > (y)) ? (x) : (y)) #define MID(x,y,z) MAX((x), MIN((y), (z))) #endif #define N 4096 /* 4k buffers for LZ compression */ #define F 18 /* upper limit for LZ match length */ #define THRESHOLD 2 /* LZ encode string into pos and length if match size is greater than this */ // TYPES ------------------------------------------------------------------- typedef struct PACK_DATA /* stuff for doing LZ compression */ { int state; /* where have we got to in the pack? */ int i, c, len, r, s; int last_match_length, code_buf_ptr; unsigned char mask; char code_buf[17]; int match_position; int match_length; int lson[N+1]; /* left children, */ int rson[N+257]; /* right children, */ int dad[N+1]; /* and parents, = binary search trees */ unsigned char text_buf[N+F-1]; /* ring buffer, with F-1 extra bytes for string comparison */ } PACK_DATA; typedef struct UNPACK_DATA /* for reading LZ files */ { int state; /* where have we got to? */ int i, j, k, r, c; int flags; unsigned char text_buf[N+F-1]; /* ring buffer, with F-1 extra bytes for string comparison */ } UNPACK_DATA; // FUNCTION DECLARATIONS --------------------------------------------------- int FlushBuffer(LZFILE *f, int last); int RefillBuffer(LZFILE *f); // DATA -------------------------------------------------------------------- char thepassword[256] = ""; int _packfile_filesize = 0; int _packfile_datasize = 0; // CODE -------------------------------------------------------------------- /* _sort_out_getc: * Helper function for the lzGetC() macro. */ int _sort_out_getc(LZFILE *f) { if (f->buf_size == 0) { if (f->todo <= 0) f->flags |= LZFILE_FLAG_EOF; return *(f->buf_pos++); } return RefillBuffer(f); } /* _sort_out_putc: * Helper function for the lzPutC() macro. */ int _sort_out_putc(int c, LZFILE *f) { f->buf_size--; if (FlushBuffer(f, FALSE)) return EOF; f->buf_size++; return (*(f->buf_pos++)=c); } /*************************************************** ************ LZSS compression routines ************ *************************************************** This compression algorithm is based on the ideas of Lempel and Ziv, with the modifications suggested by Storer and Szymanski. The algorithm is based on the use of a ring buffer, which initially contains zeros. We read several characters from the file into the buffer, and then search the buffer for the longest string that matches the characters just read, and output the length and position of the match in the buffer. With a buffer size of 4096 bytes, the position can be encoded in 12 bits. If we represent the match length in four bits, the pair is two bytes long. If the longest match is no more than two characters, then we send just one character without encoding, and restart the process with the next letter. We must send one extra bit each time to tell the decoder whether we are sending a pair or an unencoded character, and these flags are stored as an eight bit mask every eight items. This implementation uses binary trees to speed up the search for the longest match. Original code by Haruhiko Okumura, 4/6/1989. 12-2-404 Green Heights, 580 Nagasawa, Yokosuka 239, Japan. Later modified for use in the Allegro filesystem by Shawn Hargreaves. Later still, modified to function as a stand-alone Win32 DLL by Jaakko Kernen. Use, distribute, and modify this code freely. */ /* pack_inittree: * For i = 0 to N-1, rson[i] and lson[i] will be the right and left * children of node i. These nodes need not be initialized. Also, dad[i] * is the parent of node i. These are initialized to N, which stands for * 'not used.' For i = 0 to 255, rson[N+i+1] is the root of the tree for * strings that begin with character i. These are initialized to N. Note * there are 256 trees. */ static void pack_inittree(PACK_DATA *dat) { int i; for (i=N+1; i<=N+256; i++) dat->rson[i] = N; for (i=0; idad[i] = N; } /* pack_insertnode: * Inserts a string of length F, text_buf[r..r+F-1], into one of the trees * (text_buf[r]'th tree) and returns the longest-match position and length * via match_position and match_length. If match_length = F, then removes * the old node in favor of the new one, because the old one will be * deleted sooner. Note r plays double role, as tree node and position in * the buffer. */ static void pack_insertnode(int r, PACK_DATA *dat) { int i, p, cmp; unsigned char *key; unsigned char *text_buf = dat->text_buf; cmp = 1; key = &text_buf[r]; p = N + 1 + key[0]; dat->rson[r] = dat->lson[r] = N; dat->match_length = 0; for (;;) { if (cmp >= 0) { if (dat->rson[p] != N) p = dat->rson[p]; else { dat->rson[p] = r; dat->dad[r] = p; return; } } else { if (dat->lson[p] != N) p = dat->lson[p]; else { dat->lson[p] = r; dat->dad[r] = p; return; } } for (i = 1; i < F; i++) if ((cmp = key[i] - text_buf[p + i]) != 0) break; if (i > dat->match_length) { dat->match_position = p; if ((dat->match_length = i) >= F) break; } } dat->dad[r] = dat->dad[p]; dat->lson[r] = dat->lson[p]; dat->rson[r] = dat->rson[p]; dat->dad[dat->lson[p]] = r; dat->dad[dat->rson[p]] = r; if (dat->rson[dat->dad[p]] == p) dat->rson[dat->dad[p]] = r; else dat->lson[dat->dad[p]] = r; dat->dad[p] = N; /* remove p */ } /* pack_deletenode: * Removes a node from a tree. */ static void pack_deletenode(int p, PACK_DATA *dat) { int q; if (dat->dad[p] == N) return; /* not in tree */ if (dat->rson[p] == N) q = dat->lson[p]; else if (dat->lson[p] == N) q = dat->rson[p]; else { q = dat->lson[p]; if (dat->rson[q] != N) { do { q = dat->rson[q]; } while (dat->rson[q] != N); dat->rson[dat->dad[q]] = dat->lson[q]; dat->dad[dat->lson[q]] = dat->dad[q]; dat->lson[q] = dat->lson[p]; dat->dad[dat->lson[p]] = q; } dat->rson[q] = dat->rson[p]; dat->dad[dat->rson[p]] = q; } dat->dad[q] = dat->dad[p]; if (dat->rson[dat->dad[p]] == p) dat->rson[dat->dad[p]] = q; else dat->lson[dat->dad[p]] = q; dat->dad[p] = N; } /* pack_write: * Called by FlushBuffer(). Packs size bytes from buf, using the pack * information contained in dat. Returns 0 on success. */ static int pack_write(LZFILE *file, PACK_DATA *dat, int size, unsigned char *buf, int last) { int i = dat->i; int c = dat->c; int len = dat->len; int r = dat->r; int s = dat->s; int last_match_length = dat->last_match_length; int code_buf_ptr = dat->code_buf_ptr; unsigned char mask = dat->mask; int ret = 0; if (dat->state==2) goto pos2; else if (dat->state==1) goto pos1; dat->code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and code_buf[0] works as eight flags, "1" representing that the unit is an unencoded letter (1 byte), "0" a position-and-length pair (2 bytes). Thus, eight units require at most 16 bytes of code. */ code_buf_ptr = mask = 1; s = 0; r = N - F; pack_inittree(dat); for (len=0; (len < F) && (size > 0); len++) { dat->text_buf[r+len] = *(buf++); if (--size == 0) { if (!last) { dat->state = 1; goto getout; } } pos1: ; } if (len == 0) goto getout; for (i=1; i <= F; i++) pack_insertnode(r-i,dat); /* Insert the F strings, each of which begins with one or more 'space' characters. Note the order in which these strings are inserted. This way, degenerate trees will be less likely to occur. */ pack_insertnode(r,dat); /* Finally, insert the whole string just read. match_length and match_position are set. */ do { if (dat->match_length > len) dat->match_length = len; /* match_length may be long near the end */ if (dat->match_length <= THRESHOLD) { dat->match_length = 1; /* not long enough match: send one byte */ dat->code_buf[0] |= mask; /* 'send one byte' flag */ dat->code_buf[code_buf_ptr++] = dat->text_buf[r]; /* send uncoded */ } else { /* send position and length pair. Note match_length > THRESHOLD */ dat->code_buf[code_buf_ptr++] = (unsigned char) dat->match_position; dat->code_buf[code_buf_ptr++] = (unsigned char) (((dat->match_position >> 4) & 0xF0) | (dat->match_length - (THRESHOLD + 1))); } if ((mask <<= 1) == 0) { /* shift mask left one bit */ if (*file->password) { dat->code_buf[0] ^= *file->password; file->password++; if (!*file->password) file->password = thepassword; }; for (i=0; icode_buf[i], file); /* code together */ if (lzError(file)) { ret = EOF; goto getout; } dat->code_buf[0] = 0; code_buf_ptr = mask = 1; } last_match_length = dat->match_length; for (i=0; (i < last_match_length) && (size > 0); i++) { c = *(buf++); if (--size == 0) { if (!last) { dat->state = 2; goto getout; } } pos2: pack_deletenode(s,dat); /* delete old strings and */ dat->text_buf[s] = c; /* read new bytes */ if (s < F-1) dat->text_buf[s+N] = c; /* if the position is near the end of buffer, extend the buffer to make string comparison easier */ s = (s+1) & (N-1); r = (r+1) & (N-1); /* since this is a ring buffer, increment the position modulo N */ pack_insertnode(r,dat); /* register the string in text_buf[r..r+F-1] */ } while (i++ < last_match_length) { /* after the end of text, */ pack_deletenode(s,dat); /* no need to read, but */ s = (s+1) & (N-1); /* buffer may not be empty */ r = (r+1) & (N-1); if (--len) pack_insertnode(r,dat); } } while (len > 0); /* until length of string to be processed is zero */ if (code_buf_ptr > 1) { /* send remaining code */ if (*file->password) { dat->code_buf[0] ^= *file->password; file->password++; if (!*file->password) file->password = thepassword; }; for (i=0; icode_buf[i], file); if (lzError(file)) { ret = EOF; goto getout; } } } dat->state = 0; getout: dat->i = i; dat->c = c; dat->len = len; dat->r = r; dat->s = s; dat->last_match_length = last_match_length; dat->code_buf_ptr = code_buf_ptr; dat->mask = mask; return ret; } /* pack_read: * Called by RefillBuffer(). Unpacks from dat into buf, until either * EOF is reached or s bytes have been extracted. Returns the number of * bytes added to the buffer */ static int pack_read(LZFILE *file, UNPACK_DATA *dat, int s, unsigned char *buf) { int i = dat->i; int j = dat->j; int k = dat->k; int r = dat->r; int c = dat->c; unsigned int flags = dat->flags; int size = 0; if (dat->state==2) goto pos2; else if (dat->state==1) goto pos1; r = N-F; flags = 0; for ( ; ; ) { if (((flags >>= 1) & 256) == 0) { if ((c = lzGetC(file)) == EOF) break; if (*file->password) { c ^= *file->password; file->password++; if (!*file->password) file->password = thepassword; }; flags = c | 0xFF00; /* uses higher byte to count eight */ } if (flags & 1) { if ((c = lzGetC(file)) == EOF) break; dat->text_buf[r++] = c; r &= (N - 1); *(buf++) = c; if (++size >= s) { dat->state = 1; goto getout; } pos1: ; } else { if ((i = lzGetC(file)) == EOF) break; if ((j = lzGetC(file)) == EOF) break; i |= ((j & 0xF0) << 4); j = (j & 0x0F) + THRESHOLD; for (k=0; k <= j; k++) { c = dat->text_buf[(i + k) & (N - 1)]; dat->text_buf[r++] = c; r &= (N - 1); *(buf++) = c; if (++size >= s) { dat->state = 2; goto getout; } pos2: ; } } } dat->state = 0; getout: dat->i = i; dat->j = j; dat->k = k; dat->r = r; dat->c = c; dat->flags = flags; return size; } /* Encrypt: * Helper for encrypting magic numbers, using the current password. */ long Encrypt(long x) { long mask = 0; int i; for (i=0; thepassword[i]; i++) mask ^= ((long)thepassword[i] << ((i&3) * 8)); return x ^ mask; } /* lzGetW: * Reads a 16 bit word from a file, using intel byte ordering. */ int LZSSEXPORT lzGetW(LZFILE *f) { int b1, b2; if ((b1 = lzGetC(f)) != EOF) if ((b2 = lzGetC(f)) != EOF) return ((b2 << 8) | b1); return EOF; } /* LZGetL: * Reads a 32 bit long from a file, using intel byte ordering. */ long LZSSEXPORT lzGetL(LZFILE *f) { int b1, b2, b3, b4; if ((b1 = lzGetC(f)) != EOF) if ((b2 = lzGetC(f)) != EOF) if ((b3 = lzGetC(f)) != EOF) if ((b4 = lzGetC(f)) != EOF) return (((long)b4 << 24) | ((long)b3 << 16) | ((long)b2 << 8) | (long)b1); return EOF; } /* lzPutW: * Writes a 16 bit int to a file, using intel byte ordering. */ int LZSSEXPORT lzPutW(int w, LZFILE *f) { int b1, b2; b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if (lzPutC(b2,f)==b2) if (lzPutC(b1,f)==b1) return w; return EOF; } /* lzPutL: * Writes a 32 bit long to a file, using intel byte ordering. */ long LZSSEXPORT lzPutL(long l, LZFILE *f) { int b1, b2, b3, b4; b1 = (int)((l & 0xFF000000L) >> 24); b2 = (int)((l & 0x00FF0000L) >> 16); b3 = (int)((l & 0x0000FF00L) >> 8); b4 = (int)l & 0x00FF; if (lzPutC(b4,f)==b4) if (lzPutC(b3,f)==b3) if (lzPutC(b2,f)==b2) if (lzPutC(b1,f)==b1) return l; return EOF; } /* lzGetWm: * Reads a 16 bit int from a file, using motorola byte-ordering. */ int LZSSEXPORT lzGetWm(LZFILE *f) { int b1, b2; if ((b1 = lzGetC(f)) != EOF) if ((b2 = lzGetC(f)) != EOF) return ((b1 << 8) | b2); return EOF; } /* lzGetLm: * Reads a 32 bit long from a file, using motorola byte-ordering. */ long LZSSEXPORT lzGetLm(LZFILE *f) { int b1, b2, b3, b4; if ((b1 = lzGetC(f)) != EOF) if ((b2 = lzGetC(f)) != EOF) if ((b3 = lzGetC(f)) != EOF) if ((b4 = lzGetC(f)) != EOF) return (((long)b1 << 24) | ((long)b2 << 16) | ((long)b3 << 8) | (long)b4); return EOF; } /* lzPutWm: * Writes a 16 bit int to a file, using motorola byte-ordering. */ int LZSSEXPORT lzPutWm(int w, LZFILE *f) { int b1, b2; b1 = (w & 0xFF00) >> 8; b2 = w & 0x00FF; if (lzPutC(b1,f)==b1) if (lzPutC(b2,f)==b2) return w; return EOF; } /* lzPutLm: * Writes a 32 bit long to a file, using motorola byte-ordering. */ long LZSSEXPORT lzPutLm(long l, LZFILE *f) { int b1, b2, b3, b4; b1 = (int)((l & 0xFF000000L) >> 24); b2 = (int)((l & 0x00FF0000L) >> 16); b3 = (int)((l & 0x0000FF00L) >> 8); b4 = (int)l & 0x00FF; if (lzPutC(b1,f)==b1) if (lzPutC(b2,f)==b2) if (lzPutC(b3,f)==b3) if (lzPutC(b4,f)==b4) return l; return EOF; } /* lzOpen: * Opens a file according to mode, which may contain any of the flags: * 'r': open file for reading. * 'w': open file for writing, overwriting any existing data. * 'p': open file in 'packed' mode. Data will be compressed as it is * written to the file, and automatically uncompressed during read * operations. Files created in this mode will produce garbage if * they are read without this flag being set. * '!': open file for writing in normal, unpacked mode, but add the value * F_NOPACK_MAGIC to the start of the file, so that it can be opened * in packed mode and Allegro will automatically detect that the * data does not need to be decompressed. * * Instead of these flags, one of the constants F_READ, F_WRITE, * F_READ_PACKED, F_WRITE_PACKED or F_WRITE_NOPACK may be used as the second * argument to fopen(). * * On success, fopen() returns a pointer to a file structure, and on error * it returns NULL and stores an error code in errno. An attempt to read a * normal file in packed mode will cause errno to be set to EDOM. */ LZFILE LZSSEXPORT *lzOpen(char *filename, char *mode) { LZFILE *f, *f2; FILE_SEARCH_STRUCT dta; int c; long header = FALSE; errno = 0; if ((f = malloc(sizeof(LZFILE))) == NULL) { errno = ENOMEM; return NULL; } f->buf_pos = f->buf; f->flags = 0; f->buf_size = 0; f->filename = NULL; f->password = thepassword; for (c=0; mode[c]; c++) { switch (mode[c]) { case 'r': case 'R': f->flags &= ~LZFILE_FLAG_WRITE; break; case 'w': case 'W': f->flags |= LZFILE_FLAG_WRITE; break; case 'p': case 'P': f->flags |= LZFILE_FLAG_PACK; break; case '!': f->flags &= ~LZFILE_FLAG_PACK; header = TRUE; break; } } if (f->flags & LZFILE_FLAG_WRITE) { if (f->flags & LZFILE_FLAG_PACK) { /* write a packed file */ PACK_DATA *dat = malloc(sizeof(PACK_DATA)); if (!dat) { errno = ENOMEM; free(f); return NULL; } if ((f->parent = lzOpen(filename, F_WRITE)) == NULL) { free(dat); free(f); return NULL; } lzPutLm(Encrypt(F_PACK_MAGIC), f->parent); f->todo = 4; for (c=0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; f->pack_data = dat; } else { /* write a 'real' file */ f->parent = NULL; f->pack_data = NULL; FILE_CREATE(filename, f->hndl); if (f->hndl < 0) { free(f); return NULL; } errno = 0; f->todo = 0; } if (header) lzPutLm(Encrypt(F_NOPACK_MAGIC), f); } else { /* must be a read */ if (f->flags & LZFILE_FLAG_PACK) { /* read a packed file */ UNPACK_DATA *dat = malloc(sizeof(UNPACK_DATA)); if (!dat) { errno = ENOMEM; free(f); return NULL; } if ((f->parent = lzOpen(filename, F_READ)) == NULL) { free(dat); free(f); return NULL; } header = lzGetLm(f->parent); if (header == Encrypt(F_PACK_MAGIC)) { for (c=0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; f->todo = LONG_MAX; f->pack_data = (char *)dat; } else { if (header == Encrypt(F_NOPACK_MAGIC)) { f2 = f->parent; free(dat); free(f); return f2; } else { lzClose(f->parent); free(dat); free(f); if (errno == 0) errno = EDOM; return NULL; } } } else { /* read a 'real' file */ f->parent = NULL; f->pack_data = NULL; errno = FILE_FINDFIRST(filename, _A_RDONLY | _A_HIDDEN | _A_ARCH, &dta); if (errno != 0) { FILE_FINDCLOSE(&dta); free(f); return NULL; } f->todo = dta.FILE_SIZE; FILE_FINDCLOSE(&dta); FILE_OPEN(filename, f->hndl); if (f->hndl < 0) { errno = f->hndl; free(f); return NULL; } } } return f; } /* lzClose: * Closes a file after it has been read or written. * Returns zero on success. On error it returns an error code which is * also stored in errno. This function can fail only when writing to * files: if the file was opened in read mode it will always succeed. */ int LZSSEXPORT lzClose(LZFILE *f) { if (f) { if (f->flags & LZFILE_FLAG_WRITE) { if (f->flags & LZFILE_FLAG_CHUNK) return lzClose(lzCloseChunk(f)); FlushBuffer(f, TRUE); } if (f->pack_data) free(f->pack_data); if (f->parent) lzClose(f->parent); else FILE_CLOSE(f->hndl); free(f); return errno; } return 0; } /* lzSeek: * Like the stdio fseek() function, but only supports forward seeks * relative to the current file position. */ int LZSSEXPORT lzSeek(LZFILE *f, int offset) { int i; if (f->flags & LZFILE_FLAG_WRITE) return -1; errno = 0; /* skip forward through the buffer */ if (f->buf_size > 0) { i = MIN(offset, f->buf_size); f->buf_size -= i; f->buf_pos += i; offset -= i; if ((f->buf_size <= 0) && (f->todo <= 0)) f->flags |= LZFILE_FLAG_EOF; } /* need to seek some more? */ if (offset > 0) { i = MIN(offset, f->todo); if (f->flags & LZFILE_FLAG_PACK) { /* for compressed files, we just have to read through the data */ while (i > 0) { lzGetC(f); i--; } } else { if (f->parent) { /* pass the seek request on to the parent file */ lzSeek(f->parent, i); } else { /* do a real seek */ lseek(f->hndl, i, SEEK_CUR); } f->todo -= i; if (f->todo <= 0) f->flags |= LZFILE_FLAG_EOF; } } return errno; } /* lzOpenChunk: * Opens a sub-chunk of the specified file, for reading or writing depending * on the type of the file. The returned file pointer describes the sub * chunk, and replaces the original file, which will no longer be valid. * When writing to a chunk file, data is sent to the original file, but * is prefixed with two length counts (32 bit, big-endian). For uncompressed * chunks these will both be set to the length of the data in the chunk. * For compressed chunks, created by setting the pack flag, the first will * contain the raw size of the chunk, and the second will be the negative * size of the uncompressed data. When reading chunks, the pack flag is * ignored, and the compression type is detected from the sign of the * second size value. The file structure used to read chunks checks the * chunk size, and will return EOF if you try to read past the end of * the chunk. If you don't read all of the chunk data, when you call * lzCloseChunk(), the parent file will advance past the unused data. * When you have finished reading or writing a chunk, you should call * lzCloseChunk() to return to your original file. */ LZFILE LZSSEXPORT *lzOpenChunk(LZFILE *f, int pack) { int c; char *name; LZFILE *chunk; if (f->flags & LZFILE_FLAG_WRITE) { /* write a sub-chunk */ name = tmpnam(NULL); chunk = lzOpen(name, (pack ? F_WRITE_PACKED : F_WRITE_NOPACK)); if (chunk) { chunk->filename = malloc(strlen(name) + 1); strcpy(chunk->filename, name); if (pack) chunk->parent->parent = f; else chunk->parent = f; chunk->flags |= LZFILE_FLAG_CHUNK; } } else { /* read a sub-chunk */ _packfile_filesize = lzGetLm(f); _packfile_datasize = lzGetLm(f); if ((chunk = malloc(sizeof(LZFILE))) == NULL) { errno = ENOMEM; return NULL; } chunk->buf_pos = chunk->buf; chunk->flags = LZFILE_FLAG_CHUNK; chunk->buf_size = 0; chunk->filename = NULL; chunk->parent = f; chunk->password = f->password; f->password = thepassword; if (_packfile_datasize < 0) { /* read a packed chunk */ UNPACK_DATA *dat = malloc(sizeof(UNPACK_DATA)); if (!dat) { errno = ENOMEM; free(chunk); return NULL; } for (c=0; c < N - F; c++) dat->text_buf[c] = 0; dat->state = 0; _packfile_datasize = -_packfile_datasize; chunk->todo = _packfile_datasize; chunk->pack_data = (char *)dat; chunk->flags |= LZFILE_FLAG_PACK; } else { /* read an uncompressed chunk */ chunk->todo = _packfile_datasize; chunk->pack_data = NULL; } } return chunk; } /* lzCloseChunk: * Call after reading or writing a sub-chunk. This closes the chunk file, * and returns a pointer to the original file structure (the one you * passed to lzOpenChunk()), to allow you to read or write data * after the chunk. */ LZFILE LZSSEXPORT *lzCloseChunk(LZFILE *f) { LZFILE *parent = f->parent; LZFILE *tmp; char *name = f->filename; int header; if (f->flags & LZFILE_FLAG_WRITE) { /* finish writing a chunk */ _packfile_datasize = f->todo + f->buf_size - 4; if (f->flags & LZFILE_FLAG_PACK) { parent = parent->parent; f->parent->parent = NULL; } else f->parent = NULL; f->flags &= ~LZFILE_FLAG_CHUNK; lzClose(f); tmp = lzOpen(name, F_READ); _packfile_filesize = tmp->todo - 4; header = lzGetLm(tmp); lzPutLm(_packfile_filesize, parent); if (header == Encrypt(F_PACK_MAGIC)) lzPutLm(-_packfile_datasize, parent); else lzPutLm(_packfile_datasize, parent); while (!lzEOF(tmp)) lzPutC(lzGetC(tmp), parent); lzClose(tmp); unlink(name); free(name); } else { /* finish reading a chunk */ while (f->todo > 0) lzGetC(f); parent->password = f->password; if (f->pack_data) free(f->pack_data); free(f); } return parent; } /* lzRead: * Reads n bytes from f and stores them at memory location p. Returns the * number of items read, which will be less than n if EOF is reached or an * error occurs. Error codes are stored in errno. */ long LZSSEXPORT lzRead(void *p, long n, LZFILE *f) { long c; /* counter of bytes read */ int i; unsigned char *cp = (unsigned char *)p; for (c=0; cbuf_size) > 0) *(cp++) = *(f->buf_pos++); else { i = _sort_out_getc(f); if (i == EOF) return c; else *(cp++) = i; } } return n; } /* lzWrite: * Writes n bytes to the file f from memory location p. Returns the number * of items written, which will be less than n if an error occurs. Error * codes are stored in errno. */ long LZSSEXPORT lzWrite(void *p, long n, LZFILE *f) { long c; /* counter of bytes written */ unsigned char *cp = (unsigned char *)p; for (c=0; cbuf_size) >= F_BUF_SIZE) { if (_sort_out_putc(*cp,f) != *cp) return c; cp++; } else *(f->buf_pos++)=*(cp++); } return n; } /* LZGetS: * Reads a line from a text file, storing it at location p. Stops when a * linefeed is encountered, or max characters have been read. Returns a * pointer to where it stored the text, or NULL on error. The end of line * is handled by detecting '\n' characters: '\r' is simply ignored. */ char LZSSEXPORT *lzGetS(char *p, int max, LZFILE *f) { int c; if (lzEOF(f)) { p[0] = 0; return NULL; } for (c=0; cflags & LZFILE_FLAG_EOF) || (f->todo <= 0)) { /* EOF */ f->flags |= LZFILE_FLAG_EOF; return EOF; } if (f->parent) { if (f->flags & LZFILE_FLAG_PACK) { f->buf_size = pack_read(f->parent, (UNPACK_DATA *)f->pack_data, MIN(F_BUF_SIZE, f->todo), f->buf); } else { f->buf_size = lzRead(f->buf, MIN(F_BUF_SIZE, f->todo), f->parent); } if (f->parent->flags & LZFILE_FLAG_EOF) f->todo = 0; if (f->parent->flags & LZFILE_FLAG_ERROR) goto err; } else { f->buf_size = MIN(F_BUF_SIZE, f->todo); FILE_READ(f->hndl, f->buf, f->buf_size, sz); if (sz != f->buf_size) goto err; } f->todo -= f->buf_size; f->buf_pos = f->buf; f->buf_size--; if (f->buf_size <= 0) if (f->todo <= 0) f->flags |= LZFILE_FLAG_EOF; return *(f->buf_pos++); err: errno=EFAULT; f->flags |= LZFILE_FLAG_ERROR; return EOF; } /* FlushBuffer: * flushes a file buffer to the disk. The file must be open in write mode. */ int FlushBuffer(LZFILE *f, int last) { int sz; if (f->buf_size > 0) { if (f->flags & LZFILE_FLAG_PACK) { if (pack_write(f->parent, (PACK_DATA *)f->pack_data, f->buf_size, f->buf, last)) goto err; } else { FILE_WRITE(f->hndl, f->buf, f->buf_size, sz); if (sz != f->buf_size) goto err; } f->todo += f->buf_size; } f->buf_pos = f->buf; f->buf_size = 0; return 0; err: errno=EFAULT; f->flags |= LZFILE_FLAG_ERROR; return EOF; } int LZSSEXPORT lzGetC(LZFILE *f) { f->buf_size--; if (f->buf_size > 0) return *(f->buf_pos++); else return _sort_out_getc(f); } int LZSSEXPORT lzPutC(int c, LZFILE *f) { f->buf_size++; if (f->buf_size >= F_BUF_SIZE) return _sort_out_putc(c, f); else return (*(f->buf_pos++) = c); } /* LZPassword: * Sets the password to be used by all future read/write operations. */ void LZSSEXPORT lzPassword(char *password) { if (password) { strncpy(thepassword, password, 255); thepassword[255] = 0; } else thepassword[0] = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/src/find.c0000644000175000017500000000126111357170242022517 0ustar keeskees#include "Find.h" int lzssfindfirst(char *filename, struct finddata *dta, long attrib) { dta->hFile = _findfirst(filename, &dta->data); dta->date = dta->data.time_write; dta->time = dta->data.time_write; dta->size = dta->data.size; dta->name = dta->data.name; dta->attrib = dta->data.attrib; return dta->hFile<0; } int lzssfindnext(struct finddata *dta) { int r = _findnext(dta->hFile, &dta->data); dta->date = dta->data.time_write; dta->time = dta->data.time_write; dta->size = dta->data.size; dta->name = dta->data.name; dta->attrib = dta->data.attrib; return r; } void lzssfindend(struct finddata *dta) { _findclose(dta->hFile); } deng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/include/0000755000175000017500000000000011523516205022265 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/include/lzss.h0000644000175000017500000000515711357170242023443 0ustar keeskees#ifndef __LZSS_IO_COMPRESSION_H__ #define __LZSS_IO_COMPRESSION_H_ #ifdef __cplusplus extern "C" { #endif #define LZSSEXPORT __stdcall #ifndef EOF #define EOF (-1) #endif #define F_READ "r" /* for use with pack_fopen() */ #define F_WRITE "w" #define F_READ_PACKED "rp" #define F_WRITE_PACKED "wp" #define F_WRITE_NOPACK "w!" #define F_BUF_SIZE 4096 /* 4K buffer for caching data */ #define F_PACK_MAGIC 0x736C6821L /* magic number for packed files */ #define F_NOPACK_MAGIC 0x736C682EL /* magic number for autodetect */ #define F_EXE_MAGIC 0x736C682BL /* magic number for appended data */ #define LZFILE_FLAG_WRITE 1 /* the file is being written */ #define LZFILE_FLAG_PACK 2 /* data is compressed */ #define LZFILE_FLAG_CHUNK 4 /* file is a sub-chunk */ #define LZFILE_FLAG_EOF 8 /* reached the end-of-file */ #define LZFILE_FLAG_ERROR 16 /* an error has occurred */ typedef struct LZFILE { int hndl; /* file handle */ int flags; /* LZFILE_FLAG_* constants */ unsigned char *buf_pos; /* position in buffer */ int buf_size; /* number of bytes in the buffer */ long todo; /* number of bytes still on the disk */ struct LZFILE *parent; /* nested, parent file */ void *pack_data; /* for LZSS compression */ char *filename; /* name of the file */ char *password; /* current encryption position */ unsigned char buf[F_BUF_SIZE]; /* the actual data buffer */ } LZFILE; #define lzEOF(f) ((f)->flags & LZFILE_FLAG_EOF) #define lzError(f) ((f)->flags & LZFILE_FLAG_ERROR) void LZSSEXPORT lzPassword(char *password); LZFILE * LZSSEXPORT lzOpen(char *filename, char *mode); int LZSSEXPORT lzClose(LZFILE *f); LZFILE * LZSSEXPORT lzOpenChunk(LZFILE *f, int pack); LZFILE * LZSSEXPORT lzCloseChunk(LZFILE *f); int LZSSEXPORT lzSeek(LZFILE *f, int offset); int LZSSEXPORT lzGetW(LZFILE *f); long LZSSEXPORT lzGetL(LZFILE *f); int LZSSEXPORT lzPutW(int w, LZFILE *f); long LZSSEXPORT lzPutL(long l, LZFILE *f); int LZSSEXPORT lzGetWm(LZFILE *f); long LZSSEXPORT lzGetLm(LZFILE *f); int LZSSEXPORT lzPutWm(int w, LZFILE *f); long LZSSEXPORT lzPutLm(long l, LZFILE *f); long LZSSEXPORT lzRead(void *p, long n, LZFILE *f); long LZSSEXPORT lzWrite(void *p, long n, LZFILE *f); char * LZSSEXPORT lzGetS(char *p, int max, LZFILE *f); int LZSSEXPORT lzPutS(char *p, LZFILE *f); int LZSSEXPORT lzGetC(LZFILE *f); int LZSSEXPORT lzPutC(int c, LZFILE *f); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/include/find.h0000644000175000017500000000250211357170242023357 0ustar keeskees#ifndef __LZSS_FILEFINDER_H__ #define __LZSS_FILEFINDER_H__ #include #include typedef struct finddata { struct _finddata_t data; long date; long time; long size; char *name; long attrib; long hFile; } finddata; #define FILE_OPEN(filename, handle) handle = open(filename, O_RDONLY | O_BINARY) #define FILE_CREATE(filename, handle) handle = open(filename, O_WRONLY | O_BINARY | O_CREAT | O_TRUNC) #define FILE_CLOSE(handle) close(handle) #define FILE_READ(handle, buf, size, sz) sz = read(handle, buf, size) #define FILE_WRITE(handle, buf, size, sz) sz = write(handle, buf, size) #define FILE_SEARCH_STRUCT struct finddata #define FILE_FINDFIRST(filename, attrib, dta) lzssfindfirst(filename, dta, attrib) #define FILE_FINDNEXT(dta) lzssfindnext(dta) #define FILE_FINDCLOSE(dta) lzssfindend(dta) #define FILE_ATTRIB attrib #define FILE_SIZE size #define FILE_NAME name #define FILE_DATE date #define FILE_TIME time int lzssfindfirst(char *filename, struct finddata *dta, long attrib); int lzssfindnext(struct finddata *dta); void lzssfindend(struct finddata *dta); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/lzss.lib0000644000175000017500000001211411357170242022326 0ustar keeskees! / 1013717188 0 816 ` + ^^ l l  VV**..ff : :__IMPORT_DESCRIPTOR_LZSS__NULL_IMPORT_DESCRIPTORLZSS_NULL_THUNK_DATA__imp__lzPassword@4_lzPassword@4__imp__lzOpen@8_lzOpen@8__imp__lzClose@4_lzClose@4__imp__lzOpenChunk@8_lzOpenChunk@8__imp__lzCloseChunk@4_lzCloseChunk@4__imp__lzSeek@8_lzSeek@8__imp__lzGetW@4_lzGetW@4__imp__lzGetL@4_lzGetL@4__imp__lzPutW@8_lzPutW@8__imp__lzPutL@8_lzPutL@8__imp__lzGetWm@4_lzGetWm@4__imp__lzGetLm@4_lzGetLm@4__imp__lzPutWm@8_lzPutWm@8__imp__lzPutLm@8_lzPutLm@8__imp__lzRead@12_lzRead@12__imp__lzWrite@12_lzWrite@12__imp__lzGetS@12_lzGetS@12__imp__lzPutS@8_lzPutS@8__imp__lzGetC@4_lzGetC@4__imp__lzPutC@8_lzPutC@8/ 1013717188 0 826 `   ^l   V*.f: +          __IMPORT_DESCRIPTOR_LZSS__NULL_IMPORT_DESCRIPTOR__imp__lzClose@4__imp__lzCloseChunk@4__imp__lzGetC@4__imp__lzGetL@4__imp__lzGetLm@4__imp__lzGetS@12__imp__lzGetW@4__imp__lzGetWm@4__imp__lzOpen@8__imp__lzOpenChunk@8__imp__lzPassword@4__imp__lzPutC@8__imp__lzPutL@8__imp__lzPutLm@8__imp__lzPutS@8__imp__lzPutW@8__imp__lzPutWm@8__imp__lzRead@12__imp__lzSeek@8__imp__lzWrite@12_lzClose@4_lzCloseChunk@4_lzGetC@4_lzGetL@4_lzGetLm@4_lzGetS@12_lzGetW@4_lzGetWm@4_lzOpen@8_lzOpenChunk@8_lzPassword@4_lzPutC@8_lzPutL@8_lzPutLm@8_lzPutS@8_lzPutW@8_lzPutWm@8_lzRead@12_lzSeek@8_lzWrite@12LZSS_NULL_THUNK_DATALZSS.dll/ 1013717188 0 707 ` Ll< .debug$S?l@B.idata$2@0.idata$6 @  LZSS.dll( Microsoft (R) LINK LZSS.dll@comp.id .idata$2@h.idata$6.idata$4@h.idata$5@h6L__IMPORT_DESCRIPTOR_LZSS__NULL_IMPORT_DESCRIPTORLZSS_NULL_THUNK_DATA LZSS.dll/ 1013717188 0 248 ` Ll<.debug$S?d@B.idata$3@0 LZSS.dll( Microsoft (R) LINK@comp.id __NULL_IMPORT_DESCRIPTORLZSS.dll/ 1013717188 0 273 ` Ll<.debug$S?@B.idata$5@0.idata$4@0 LZSS.dll( Microsoft (R) LINK@comp.id LZSS_NULL_THUNK_DATA LZSS.dll/ 1013717188 0 40 ` Ll<_lzClose@4LZSS.dllLZSS.dll/ 1013717188 0 45 ` Ll<_lzCloseChunk@4LZSS.dll LZSS.dll/ 1013717188 0 39 ` Ll<_lzGetC@4LZSS.dll LZSS.dll/ 1013717188 0 39 ` Ll<_lzGetL@4LZSS.dll LZSS.dll/ 1013717188 0 40 ` Ll< _lzGetLm@4LZSS.dllLZSS.dll/ 1013717188 0 40 ` Ll<_lzGetS@12LZSS.dllLZSS.dll/ 1013717188 0 39 ` Ll<_lzGetW@4LZSS.dll LZSS.dll/ 1013717188 0 40 ` Ll< _lzGetWm@4LZSS.dllLZSS.dll/ 1013717188 0 39 ` Ll<_lzOpen@8LZSS.dll LZSS.dll/ 1013717188 0 44 ` Ll<_lzOpenChunk@8LZSS.dllLZSS.dll/ 1013717188 0 43 ` Ll<_lzPassword@4LZSS.dll LZSS.dll/ 1013717188 0 39 ` Ll<_lzPutC@8LZSS.dll LZSS.dll/ 1013717188 0 39 ` Ll< _lzPutL@8LZSS.dll LZSS.dll/ 1013717188 0 40 ` Ll<_lzPutLm@8LZSS.dllLZSS.dll/ 1013717188 0 39 ` Ll<_lzPutS@8LZSS.dll LZSS.dll/ 1013717188 0 39 ` Ll< _lzPutW@8LZSS.dll LZSS.dll/ 1013717188 0 40 ` Ll< _lzPutWm@8LZSS.dllLZSS.dll/ 1013717188 0 40 ` Ll<_lzRead@12LZSS.dllLZSS.dll/ 1013717188 0 39 ` Ll<_lzSeek@8LZSS.dll LZSS.dll/ 1013717188 0 41 ` Ll<_lzWrite@12LZSS.dll deng-1.9.0-beta6.9+dfsg1/doomsday/external/lzss/win32/lzss.dll0000755000175000017500000014000011357170242022332 0ustar keeskeesMZ@ !L!This program cannot be run in DOS mode. $5hGTTTH T,K TGHT,K TKTTT;t T;tTRichTPELl<! Pg,(.textt `.rdataZ @@.data$@.reloc @BD$Vt$ VPN VN$3҉ ‰,(^ D$,Q-YD$H uHHH3ҊAHP Vt$ jVN Pt^F N@F D$N%AN^S33҄tVʃ抚3Bu^L$[3VW|$ WtWt  _^_^SUVt$WVt;V؃t.Vt!Vt _ ^ ][_^][S\$Ul$V3WUV;uUWt;u _^][_^][QS\$ Ul$V33ɊD$WUVD$L$ ;u3t$UV;u$t$UV;uUW;u _^][Y_^][YVW|$ WtWȃt _ ^_^SUVt$WVRt?VE؃t2V8t%V+ȃt  _^] [_^][S\$3Ul$VWUW;uUV;u _^][_^][QS\$ Ul$V33ɊD$WϋUVD$ L$;u3t$UV;u$t$UV;uUW;u _^][Y_^][Y4SUV3W\$Sh$H;u9_^ ]3[4F$^F$L^ ^F :tWȽ߃Vw83Ҋ|$h!n$F FF FFD$#ljFAA:uFh\;u#V ,3_^][4$Hh4P;ÉFPh!hlsPKH3Ff]nC$HhQ^^*;É}V3_^][4^9\$tVh.hlsGP_^][4h0;u#V 73_^][4$Hh0R;ÉFuUV3_^][4Ph!hls;u*}3f]Fn_^][4h.hlss;u!~UV_^][4FPEUpVj9u !_^]3[4$HL$j#QW^^j(c9t"T$RMV3_^][4$4L$QF!hW );ÉX V3_^][4}Vt$tFttVu3^jVFt PFtP P'V^Vt$Ft^WL$F ~+;}V ~++ȉV ҉~FF F~\~;}Ft~IV_ Ou_^Ft WPrjWPH N+ϋNF FO_^SUl$ VWEjAD$<u8PV؅?3QЋ3S+ȋD$tK_^iC ]C[C_ kC^][UUh$}3;ul_^ ]3[S$CSs skE C E ;}ch0(Ѓ;uS 3_^][z3f2أCC_ ^CS][Cs_^][UVt$ WF~nFN TFtF@FS^V^h0UVN WRMh!hls;Wu P Q(FuWV P ^tVwUhU [_^]~ V FV W Ft Pl Vc _^]SUl$V3W|$~6t$N IN ~FGOF@FVutGC;|_^][ _^][ SUl$V3W|$~=t$N AN =|3VPO3Ɋ;uVNANGC;|_^][ _^][ Ul$Et D$]3 L$ SV3YW|$~U^ < >uN< tF;|>z #_^[] W|$t(Vt$< Vu j D Vj P6 GGu^0 _Vt$WNFVt=~~$WPFPR=~~$RPWF F@tF@uWF V+HV~F …F F3G~_^=~~$PWQF YAN ;tB F _F^_N^ SUVt$ 3WVFN~^T$D$F L$$D$pt l$D$D$uBD$ P؃T$ B t3@B 8uB ÀD$T$ D$RtB5؃tWD$,\7G@ED$,D$(;sL$$D$D$$tT$ RD$uL$$D$kT$$ȁ уD$D$D$T$$;D$3ہG\2T$,\7BT$,T$(E;|,T$NL$~NF ^V_^][ @D$땐Vt$F ~,Ft9L$ V$QNRPFPQWu5N FFV$F V3^PV$RPON ;tF F^SUVt$,WD$ FN V~^nD$FD$L$N T$L$0tfVF!D$4D$3l$D$}AL$4~9D$8@D$8D$4H2HD$4uD$!F4N8G$ D>!G|$D$0D$0uqD$,P tV!2шV!x Gωx 9u@ L$3~PD>!P:GD$;D$,|@t D$ ?F!D$0D$F83D$;}qL$4~iL$83AD$D$4HL$8D$4uD$!PRD$,@D$G;|L$T$D$NL$V T$0~^nFD$ NV _^][T$WD󫍺D_D$SUVW|$3ɾ8H8Ht<@@@8|@@tHT<ʾH3Ҋ.3Ҋ+uF|;p8~H4p8}륉@@D_^][DDT3;u,9 ح~ ح9 u4 uQYjX US]Vu W}u =ح&tu"t WVSЅt WVSu3NWVSR!E u u7WPStu&WVSu!E } ttWVSЉE E _^[] t u=u t$!hYYW|$j$L$WtAt;u~Ѓ3ƒtAt#ttt͍y yyyL$ tAtdGu~Ѓ3‹tt4t'ttljD$_fD$G_fD$_ÈD$_U$S]lFVW} 4uu~F'!ÍKim։uщ]‹U @EE k<Mk< ХO} }_^U|Mt } u =ԥtEPv#YMt إ[3j9D$hP(tu5$3jXS39U-~DVW=,p h@h6hj6vj5ՃC;|_^5j55$][V505555ȡ^VW=4ġt+t#ttȡt P6Y|5555ȡ_^UEV<ġ4ġu>WjYujYj>YWu 0>Yj Y_68^]UE4ġ<]h@j5uÃ%%jXá  ;sT$+P r3UU MSVA+q ZW΋ziK}D]M Muj?I_M ;v} L;LuHM sL!|D u+M!9$M L! uM!yL|yL|]y]O?vj?_MM+UMj?UIZ;ʉM vU ]]O;v;tkMQ;QuHM sL!TD u+M!$M L! uM!QMQIJMQIJU}u 9} M IJM JQJQJ;JucL MLs%}uM DD )}uOM YO 8]E\ =,H h@SQ׋  P @@HCHyCu `xulSjp סpj5ȡ+ȍLQHQPV!E ;v  E5_^[USVWu;uM; u%MB_^[á VW3;u0DPP5W5H;ta hAj54;ljFt*jh hWD;ljF uvW53N>~F_^UQMSVWqA3ۅ|Cj?iZ0DE@@Jujy hhWDup;wj5Y;YtV)YPhu 3VƃY dt WY3_^Vt$tV@P)YYt VPYY^3^t$ j@t$t$UM S3VWE ]t ]E eEu@u9ttMj^#+tHtHEE@EEt& t0t @utuE E]#ʿ;1t*;t&;ttMu+ELECu>t/t;t#EEE t d#Muj^@t Mt t t؃;uqo *jVuEPuuup;uPYVlu Vh؃uM@ uMVSYYM<ÀM 4e HL0uxtsE tmjjSb Eu8tKS{YXeEjPS u}uuSPYYtjjS t} uE t L0 D0SvY_^[U}M SVWt u-Au3uƋ3u vW0Awڀ!IIG;r_^[]jt$t$t$D$%tU SeVW}wu=~jP YY ÊAtFЀ-uuM+uFuE$wjYu$0t E 2t }w u,9uv'E"tME$ƉEtEEtE؉EE E t83_^[jt$t$t$UV395\uu u3#YYRWjOYMatQAt 9E uq 9E uAujjY_^]VWj33Y95~Jt5PVfYY@ txtP"YG4VYYF;5|jY_^áthhhhjjt$  jjj Wj_9=ut$|Px|$ S\$=u<t" Vq;rtЃ;5s^h$hCYYh,h(2YY[t_t$=@_j Yj YVt$;t$ s tЃ^UHSVWhYuj"Y5 ;sffF $ލEPf}E8X;E;|9=}VhYt< ;s``@ $9=|=3~LEt8t2u Qlt#΋ M  HEFC;|3ۋ ۃ<4uMFujX HPtWlt %>uN@u NNC|5_^[SVWt7;s!_ {tS4$$;r6S&Y|_^[S39VWu 5ܭ3:t<=tGVYtPIY;5uj Y=ܭ8t9UWYE?=t"U;Yuj YW6YY8u]5ܭYܭ_^[UQQS39VWuLhVS58tEPEPSSWMEMPt;ujYEPEPEPVWEH5|_^x[UMESV!uW} Et7} 8"uDP@"t)t%at tF@tՊFt&F8"uF@CtF@at tF@ t t ūuHtfe8 t u@8t7} UE3ۀ8\u@C8"u,u%39}t x"Pu}} 39U‰UKtCt\FKutJ}u t? t:}t.tatF@Fat@@Xt&Ft'E_^[]QQSU-VW333;u3Ջ;t (;;u Ջ;f9t@@f9u@@f9u+Ƌ=SS@SSPVSSD$4׋;t2U;YD$t#SSUPt$$VSSׅut$vY\$\$VSuL;u ;t<8t @8u@8u+@UzY;u3 UWV W3_^][YYjX t u*=u!hYthYUU3ɸ@;t A=Х|V;@u =\hPju\hPpYY\WP\@Y4l;tPVYY5lV @P ;ãlVPW:jV5\#\`>-uEFVY0i Х<+t:|<9F>:uNFVk:u#FVY Хȉ Х:|<9F}tى ХԥtjV5`d` `` WOY_^[Vj t$ j / ^SVW39=ԥu3Lt$j[F;hu ;x9= fQf9=X dQ bQ `Qu \WQ ^Q ZQPS ^QW ZWQPWS,f9=PPP Pu(WP PPvSW,B PWWPvWWWWjWWSjPSSWWWjWWjj vSW{Xl|N;};;;~;}_^[;|;;~;Fk<Fk<i;u3;p3;U} S]VE]eu  ӍHimCWj:%_E_;Uk+EL k+Eȃ}u8}u;~ Eu  M }u+E$ lk<E(hk<E,iE0pUE$ |k<E(k<إE,iE0y \&I\&;|+A |x^[]UWVu M};v;xur)$VǺr $U$V$+~&WPv  ;uF t$F N Ff_^[jYSVWj333Y95~tt_@ tYPV]YYH t0|$uPYtC|$utPYu 4V_YYF;5|j|$Yt_^[QQSUVWjN3Y\$\$u;stFuD~u#j~Yu F P0Fj\Y^ S8FtS<\$E$륃+Ej$Y|$um\$D$ C\$^NVYt> ;s``@ $WOYjY_^][YYËL$V; WsU<4<0u6=S\$utItIuSjSjSj03[ _^ËL$V; WsX<4@t78t2=u3+tItIuPjPjPj 03t r _^ËD$;sȃ Dt0 . ËD$SȃVW4<~u#j~Yu F P0FjYD8 P8_^[ËD$ȃ D P<̋L$tAt@u~Ѓ3ƒtAt2t$tt͍AL$+ÍAL$+ÍAL$+ÍAL$+USV3jVu ;ÉEjVu ;W} +~uSVPhuSE ;}PPu t+~8u s u uYYH}Fju uuPN;u( 8juu _^[Vt$;5s@΋ Dt%WVt$t$V(V_^ ^U e}S] VWEȃ4<ƊHHt@< tMSED0 EjPuR40u9j^;u 0m$PlYUUL0D0t ; u $E ME;ME<< t CEI9MsE@8 uE^ CEsEjPEEjP40u uG}tAD0HtE< t CD1);] u } u jju } t CM9MGt0@u +] ]E3_^[Vt$;5s@΋ Dt%WVmt$t$V(V_^h f ^Vt$WVYu > -t$jt$Pu3t PY΃Ƌ dD_^SVD$ uL$D$3؋D$ Aȋ\$T$D$ ud$ȋD$r;T$wr;D$ vN3ҋ^[SD$ uL$D$ 3D$3Pȋ\$T$ D$ ud$d$r;T$ wr;D$v+D$T$+D$T$ ؃[S39uD$a|YzT [V@WV9<=tVjYj[t$YD$t jYV׋D$_^[UQ=SuEaz ]}(=~ jSYY XukDJte E] j e ]jXMjjjQPEPh5 tuE EM [UQEHw ARV5DV^teMEj eEjXM jjjQPEPjuE #E USVWjuY;DY]u3pV3Ҹ9tt0B=|EPSĐj^;!j@%dY3`9u󫪉D}MA;a@ej@Y3`4R;t,Qt%;wUa@;vAA9uE}rE\PDPYdRAAyGƀa@=rSYd5\%\3P=xtjY_^[ËD$%xux%̐ux%ȐuxËD$-t"t t Ht3øøøøWj@Y3`3PD\d_UEVP5DĐ3@;rEƅ t7SWU ;w+ȍA ˃BBBu_[j5d5DPVPj j5DVPVPV5dd j5DVPVPh5d< \3fta`ta 〠`@AA;rI3ArZwaȀ `arzwa Ȁ `@;r^Ã=ujYUW}3AOE G8t3_Vt$WF @tf VDVV _^Vt$WF t4VTVw v }Ft PkfYf _^UWVu M};v;xur)$kǺr $ j$k$j0j\jj#ъFGFGr$kI#ъFGr$k#ъFGr$kIjjjjjjjjDDDDDDDDDDDDDD$kk k,k@kE^_ÐE^_ÐFGE^_ÍIFGFGE^_Ðt1|9u$r $l$PlIǺr +$k$lkklF#шGNOr$lIF#шGFGr$lF#шGFGFGZ$lITl\ldllltl|lllDDDDDDDDD D DDDD$lllllE^_ÐFGE^_ÍIFGFGE^_ÐFGFGFGE^_S39|VWuBhtԐ;tg5АhhWօ|tPhXWhDW֣tЋ؅ttSЋt$t$t$S|_^[3SUVW|$=~jPYY AtG7G-t+u7G3ۃ=~ jVYY pt \F7Gσ-u_^][̋T$L$u<:u. t&:au% t:Au t:au uҋ3Ð@ËtB:uA ttf:u t:au t댃=SV5Wteu95tYuP5tF\$t>SYt/P;Yv<8=uWSPm tӋD83_^[̋T$ L$tG3D$Wr-كt+шGIuʃttGJuD$_ËD$S\$;VWsr<Ã4D0tRSYD0t)S;YPؐu 3t胹0s SYZ _^[Vt$;5s@΋ Dt%WVt$t$V(VI_^ ^USVW39}}}u3fEE4D0 tjWuF @E 9}E}M+M ;Ms)ME uE @@ȍ+ʁ|̋+EjPWP40tCEE;| E+E ;Er3E;9}tbj^9uuL 0AEǍMWQuu 0t E}EEu!Y,D0@t E 8tr8+E_^[ËD$Vȃ TL%9t$ u |$ @uɀ f%^^Q=L$r-=s+ȋą@PUjhhxdPd%SVWe39=uFWWj[ShVWt"WWShVW"9}~uu YYEuuuuuu u9} uE WWuuE$@Pu ܐ؉];}$eĉE܃MjXËe3}܃M]9}tfSuuuju ܐtMWWSuu uu;t2E t@9};uuuSuu u3eȋMd _^[E6$e܉]MjXËe33ۃMu;tVSuuu ut9}WWuWWuuVSh u ;qlUjhhxdPd%SVWe衸3;u>EPj^VhVtEPVhVSjXu$E;uuuu uP9]uESSuu E @PuܐE;tc]<ǃ$euWSVy jXËe33M;t)uVuu juܐ;tuPVu3e̋Md _^[Vt$F ttvff 3YFF^̋D$L$ ȋL$ u D$S؋D$d$؋D$[U}u3]5Duu uuj5du]Ã]QSUV5W3;tNWWWWjPWjӋ;t>U腱;YD$t/WWUPj6WjӅtWt$\FY;Yu3_^][YÃUV3PPPPPPPPU I tB$uA tF$s ^UWVSM&ً}3ˋu F3:GwtIIы[^_UV3PPPPPPPPU I tB$u t F$sF ^USVWUjjhwu ]_^[]ËL$AtD$T$SVWD$Pjhwd5d%D$ Xp t.;t$$t(4v L$H |uhD@Td _^[3d ywuQ R 9QuSQ SQMKCk Y[VC20XC00USVWU] E@EEEECs {ta v|tEVUkT]^] t3x<{SkVS vjDaC T{ v4롸UkjS]]_^[]UL$)APAPy]UjhhxdPd%0SVWe39 j_u@WPWPSSt= #WPWPSS u;~VuYYu9]~uuYYE uuuVuu u;9] uE ;t 9];uujXx9}~l;AEPu ĐQ;~,}r"E8]tP:tM :r:v@@8uj9]~1}rE8]tP:tM :r:x@@8uzSSVuj u ܐE;]$ eĉE܃MjXËe3ۉ]܃Muj_9]uuVuWu 5ܐօtySSuuj u ֋u;ta}6$e}؃MjXËe33Mu;t-VWuuju ܐtVWuuu u3eMd _^[ËT$D$VJt 8t@Iu8^u+D$ËUQQSVW39}tUj=u<Y;Yut@9ut;38^;u PY;uT9} t9=tt>_^[; j芫;Yt߉89=ujo;Ytĉ8+u=}VuYY|C?t>t24Y3V5Wt-|$WPt$l u 8<=ttFu׋+_^Ë+W|$3Ʌu3_Ã?Gt AuSUVPYuj 萮Y߅tPY&^][_UWVSu }xu; t.F'G8t,A<ɀ A,A<ɀ A8tx@=<j @j#$3ې t'FG8tPS؃8tX u @ j3[^_UWVSM u} xuNAZ I& t! tFG8r8w8r8w8u Iu38@=<j @j3$33ۋ t# tFGQPS؃ Y;u Iu3;t rX u @j4ˋ[^_US]VWuu ӧYu uSxY33j 腯S3YE Y;5wBVSP! t+V[Yt"CH;rPSWSu u@uj^Vj5tCH;rPSW|Su ʯj BY'j 8Yuj^VSj5Hu=PtVYY_^[]U=\SVuu u^YYvjkuYfftJatFFt 9M t9E tFj臮Y3%j{YFjnE Y+#^[]UQ=SVWuEAZ ]j;^}%95~ VSYY X#ƅueDJte jE] X e ]VjMjQPEPW5 t;uE EM _^[̍B[Í$d$3D$ST$t B8tфtQu WV ؋ ~333ƃu%t%uu^_[3ËB8t6t8t't8tt8tt^_B[ÍB^_[ÍB^_[ÍB^_[%t$u3t PݤY3t$Yx,>Jb|—Зޗ*BP`nƘܘ0DVf™ؙ 0@P\nҚ ,>P\n.\runtime error TLOSS error SING error DOMAIN error R6028 - unable to initialize heap R6027 - not enough space for lowio initialization R6026 - not enough space for stdio initialization R6025 - pure virtual function call R6024 - not enough space for _onexit/atexit table R6019 - unable to open console device R6018 - unexpected heap error R6017 - unexpected multithread lock error R6016 - not enough space for thread data abnormal program termination R6009 - not enough space for environment R6008 - not enough space for arguments R6002 - floating point not loaded Microsoft Visual C++ Runtime Library Runtime Error! Program: ...SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDecTZGetLastActivePopupGetActiveWindowMessageBoxAuser32.dllssStWtuuc{g{{{H:mm:ssdddd, MMMM dd, yyyyM/d/yyPMAMDecemberNovemberOctoberSeptemberAugustJulyJuneAprilMarchFebruaryJanuaryDecNovOctSepAugJulJunMayAprMarFebJanSaturdayFridayThursdayWednesdayTuesdayMondaySundaySatFriThuWedTueMonSunx,>Jb|—Зޗ*BP`nƘܘ0DVf™ؙ 0@P\nҚ ,>P\nGetLastErrorFindFirstFileAFindCloseFileTimeToSystemTimeFileTimeToLocalFileTimeHeapFreeHeapAllocGetCommandLineAtGetVersionHeapDestroyHeapCreateVirtualFreeInitializeCriticalSectionUDeleteCriticalSectionfEnterCriticalSectionLeaveCriticalSection}ExitProcessVirtualAllocHeapReAllocGetCurrentThreadIdTlsSetValueTlsAllocTlsFreeqSetLastErrorTlsGetValue GetFileAttributesACloseHandleGetFileType4CreateFileAGetCurrentProcessIdTerminateProcessGetCurrentProcessmSetHandleCountRGetStdHandlePGetStartupInfoA$GetModuleFileNameAFreeEnvironmentStringsAFreeEnvironmentStringsWWideCharToMultiByteGetEnvironmentStringsGetEnvironmentStringsWWriteFilepGetTimeZoneInformation|SetStdHandleaSetEndOfFileReadFilejSetFilePointerInterlockedDecrementInterlockedIncrementGetCPInfoGetACP1GetOEMCP>GetProcAddressLoadLibraryAFlushFileBuffersMultiByteToWideCharLCMapStringALCMapStringWSGetStringTypeAVGetStringTypeW/RtlUnwind!CompareStringA"CompareStringWbSetEnvironmentVariableAKERNEL32.dllWDeleteFileAl<8&P P p  &P&Μ՜ܜ &.5<DKR    LZSS.dlllzCloselzCloseChunklzGetClzGetLlzGetLmlzGetSlzGetWlzGetWmlzOpenlzOpenChunklzPasswordlzPutClzPutLlzPutLmlzPutSlzPutWlzPutWmlzReadlzSeeklzWrite=h>6Frww!wp        ! 5A CPR S WY l m pr   )    F 8 tH  ̒xL|TxDy4z$ pPSTPDTܥ;Zx0Nm:Yw/Ml x  ((((( H .`y!@~ڣ @ڣ AϢ[@~QQ^ _j21~CCC ܕؕԕЕȕ|xtplhd`\TH@8x0(  ДȔ.h,,,,,,,,,p@00M4r4y445h7l7p7t7x759<999::h:o::: ;;3;>;> 1<366666777M8S8[888889&9y9~9999::;;;;;;;;;;<<+<3<9<|<<<==0=]>>>>? ??#?3?:?A?I?p?|????????????????0000'0/0B0J0w0000000000000D3R3X3r3w33333333333344#4)43494I4O4495&71797L7R7h7o7u77777777777O8;<<2<8>>0>6>D>M>^>z>>>>>>>>?5?A?T????@012222=2k2333444455F6M6`6~66666666777$7+757N7V7[7g7l77777 8!8S8Z8o888889/9=9n9t999999:':j:v:::::::;;d;;<<<<<==W====>>1>W>d>r>}>>>>??:?F?b?w??????????Pd00'0-070?0E0S0Z0a0m0u0}0000000000001,1H1d1n11111122#2-2;2x2222222222222333$3,343>3G3O3f3o33344B4M44444444 55)565I5O5U555555555656<6@6D6H6L6P6T6X6666667%7@7G7L7P7T7q77777777777:8@8D8H8L8888839;9d9q9v999I:P:i::::/;D;Q;;;;<<,>>>????p0%00911112222222222383P3p3334y4444444555/5B5Z5z555s66667)88889999999 ::L:g:~::7;;;<~<<<<<<<<===>*>>>> ?Y?????,V00"1(1u1{1111F2~22223334444444444 000 01111222D5L5T5\5d5l5t5|55555555555\6`677;;;;;;;;;;;;;;;;;;;<<< <<<<< <$<(<,<0<4<8<<<@flags & LZFILE_FLAG_EOF) #define lzError(f) ((f)->flags & LZFILE_FLAG_ERROR) void LZSSEXPORT lzPassword(char *password); LZFILE *LZSSEXPORT lzOpen(char *filename, char *mode); int LZSSEXPORT lzClose(LZFILE * f); LZFILE *LZSSEXPORT lzOpenChunk(LZFILE * f, int pack); LZFILE *LZSSEXPORT lzCloseChunk(LZFILE * f); int LZSSEXPORT lzSeek(LZFILE * f, int offset); int LZSSEXPORT lzGetW(LZFILE * f); long LZSSEXPORT lzGetL(LZFILE * f); int LZSSEXPORT lzPutW(int w, LZFILE * f); long LZSSEXPORT lzPutL(long l, LZFILE * f); int LZSSEXPORT lzGetWm(LZFILE * f); long LZSSEXPORT lzGetLm(LZFILE * f); int LZSSEXPORT lzPutWm(int w, LZFILE * f); long LZSSEXPORT lzPutLm(long l, LZFILE * f); long LZSSEXPORT lzRead(void *p, long n, LZFILE * f); long LZSSEXPORT lzWrite(void *p, long n, LZFILE * f); char *LZSSEXPORT lzGetS(char *p, int max, LZFILE * f); int LZSSEXPORT lzPutS(char *p, LZFILE * f); int LZSSEXPORT lzGetC(LZFILE * f); int LZSSEXPORT lzPutC(int c, LZFILE * f); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/doxygen/0000755000175000017500000000000011523516243016542 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/doxygen/header.html0000644000175000017500000000047011357170241020660 0ustar keeskees $title deng-1.9.0-beta6.9+dfsg1/doomsday/engine/0000755000175000017500000000000011523516205016330 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/0000755000175000017500000000000011523516205017101 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/dd_gl.h0000644000175000017500000001700211357170241020324 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_gl.h: Doomsday graphics library. */ #ifndef __DOOMSDAY_GL_H__ #define __DOOMSDAY_GL_H__ enum { // Values DGL_SCISSOR_BOX, DGL_ACTIVE_TEXTURE, DGL_CURRENT_COLOR_R, DGL_CURRENT_COLOR_G, DGL_CURRENT_COLOR_B, DGL_CURRENT_COLOR_A, DGL_CURRENT_COLOR_RGBA, // List modes DGL_COMPILE = 0x3000, DGL_COMPILE_AND_EXECUTE, // Matrices DGL_MODELVIEW = 0x4000, DGL_PROJECTION, DGL_TEXTURE, // Caps DGL_TEXTURING = 0x5000, DGL_SCISSOR_TEST, DGL_FOG, DGL_MODULATE_ADD_COMBINE, DGL_MODULATE_TEXTURE, DGL_LINE_SMOOTH, DGL_POINT_SMOOTH, // Blending functions DGL_ZERO = 0x6000, DGL_ONE, DGL_DST_COLOR, DGL_ONE_MINUS_DST_COLOR, DGL_DST_ALPHA, DGL_ONE_MINUS_DST_ALPHA, DGL_SRC_COLOR, DGL_ONE_MINUS_SRC_COLOR, DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA, DGL_SRC_ALPHA_SATURATE, DGL_ADD, DGL_SUBTRACT, DGL_REVERSE_SUBTRACT, // Miscellaneous DGL_MIN_FILTER = 0xF000, DGL_MAG_FILTER, DGL_ANISO_FILTER, DGL_NEAREST, DGL_LINEAR, DGL_NEAREST_MIPMAP_NEAREST, DGL_LINEAR_MIPMAP_NEAREST, DGL_NEAREST_MIPMAP_LINEAR, DGL_LINEAR_MIPMAP_LINEAR, DGL_CLAMP, DGL_CLAMP_TO_EDGE, DGL_REPEAT, DGL_LINE_WIDTH, DGL_POINT_SIZE }; // Types. typedef unsigned char DGLubyte; typedef unsigned int DGLuint; typedef int DGLsizei; // Texture formats: typedef enum dgltexformat_e { DGL_RGB, DGL_RGBA, DGL_COLOR_INDEX_8, DGL_COLOR_INDEX_8_PLUS_A8, DGL_LUMINANCE, DGL_DEPTH_COMPONENT, DGL_LUMINANCE_PLUS_A8 } dgltexformat_t; typedef enum dglprimtype_e { DGL_LINES, DGL_TRIANGLES, DGL_TRIANGLE_FAN, DGL_TRIANGLE_STRIP, DGL_QUADS, DGL_QUAD_STRIP, DGL_POINTS } dglprimtype_t; #define DDNUM_BLENDMODES 9 typedef enum blendmode_e { BM_ZEROALPHA = -1, BM_NORMAL, BM_ADD, BM_DARK, BM_SUBTRACT, BM_REVERSE_SUBTRACT, BM_MUL, BM_INVERSE, BM_INVERSE_MUL, BM_ALPHA_SUBTRACT } blendmode_t; typedef struct dgl_vertex_s { float xyz[4]; // The fourth is padding. } dgl_vertex_t; typedef struct dgl_texcoord_s { float st[2]; } dgl_texcoord_t; typedef struct dgl_color_s { byte rgba[4]; } dgl_color_t; typedef struct { DGLubyte rgb[3]; } dgl_rgb_t; typedef struct { DGLubyte rgba[4]; } dgl_rgba_t; // A 2-vertex with texture coordinates, using floats typedef struct { float pos[2]; float tex[2]; } dgl_ft2vertex_t; // A 3-vertex with texture coordinates, using floats typedef struct { float pos[3]; float tex[2]; } dgl_ft3vertex_t; // A 3-vertex with texture coordinates and a color, using floats typedef struct { float pos[3]; float tex[2]; float color[4]; } dgl_fct3vertex_t; // A colored 3-vertex, using floats typedef struct { float pos[3]; float color[4]; } dgl_fc3vertex_t; int DGL_Enable(int cap); void DGL_Disable(int cap); boolean DGL_GetIntegerv(int name, int* vec); int DGL_GetInteger(int name); boolean DGL_SetInteger(int name, int value); float DGL_GetFloat(int name); boolean DGL_SetFloat(int name, float value); void DGL_Ortho(float left, float top, float right, float bottom, float znear, float zfar); void DGL_Scissor(int x, int y, int width, int height); void DGL_MatrixMode(int mode); void DGL_PushMatrix(void); void DGL_PopMatrix(void); void DGL_LoadIdentity(void); void DGL_Translatef(float x, float y, float z); void DGL_Rotatef(float angle, float x, float y, float z); void DGL_Scalef(float x, float y, float z); void DGL_Begin(dglprimtype_t type); void DGL_End(void); boolean DGL_NewList(DGLuint list, int mode); DGLuint DGL_EndList(void); void DGL_CallList(DGLuint list); void DGL_DeleteLists(DGLuint list, int range); void DGL_SetMaterial(struct material_s* mat); void DGL_SetNoMaterial(void); void DGL_SetPatch(lumpnum_t lump, int wrapS, int wrapT); void DGL_SetPSprite(struct material_s* mat); void DGL_SetTranslatedSprite(struct material_s* mat, int tclass, int tmap); void DGL_SetRawImage(lumpnum_t lump, boolean part2, int wrapS, int wrapT); void DGL_BlendOp(int op); void DGL_BlendFunc(int param1, int param2); void DGL_BlendMode(blendmode_t mode); void DGL_Color3ub(DGLubyte r, DGLubyte g, DGLubyte b); void DGL_Color3ubv(const DGLubyte* vec); void DGL_Color4ub(DGLubyte r, DGLubyte g, DGLubyte b, DGLubyte a); void DGL_Color4ubv(const DGLubyte* vec); void DGL_Color3f(float r, float g, float b); void DGL_Color3fv(const float* vec); void DGL_Color4f(float r, float g, float b, float a); void DGL_Color4fv(const float* vec); void DGL_TexCoord2f(byte target, float s, float t); void DGL_TexCoord2fv(byte target, float* vec); void DGL_Vertex2f(float x, float y); void DGL_Vertex2fv(const float* vec); void DGL_Vertex3f(float x, float y, float z); void DGL_Vertex3fv(const float* vec); void DGL_Vertices2ftv(int num, const dgl_ft2vertex_t* vec); void DGL_Vertices3ftv(int num, const dgl_ft3vertex_t* vec); void DGL_Vertices3fctv(int num, const dgl_fct3vertex_t* vec); void DGL_DrawLine(float x1, float y1, float x2, float y2, float r, float g, float b, float a); void DGL_DrawRect(float x, float y, float w, float h, float r, float g, float b, float a); void DGL_DrawRectTiled(float x, float y, float w, float h, int tw, int th); void DGL_DrawCutRectTiled(float x, float y, float w, float h, int tw, int th, int txoff, int tyoff, float cx, float cy, float cw, float ch); /** * \todo The following routines should not be necessary once materials can * be created dynamically. */ int DGL_Bind(DGLuint texture); void DGL_DeleteTextures(int num, const DGLuint* names); void DGL_EnableTexUnit(byte id); void DGL_DisableTexUnit(byte id); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/sys_audiod_mus.h0000644000175000017500000000421111357170241022300 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_music.h: Audio Driver - Music interfaces. */ #ifndef __DOOMSDAY_AUDIO_DRIVER_MUSIC_H__ #define __DOOMSDAY_AUDIO_DRIVER_MUSIC_H__ // Music interface properties. enum { MUSIP_ID, // Only for Get()ing. MUSIP_PLAYING, // Is playback in progress? MUSIP_VOLUME }; // Generic driver interface. All other interfaces are based on this. typedef struct audiointerface_music_generic_s { int (*Init) (void); void (*Update) (void); void (*Set) (int prop, float value); int (*Get) (int prop, void *value); void (*Pause) (int pause); void (*Stop) (void); } audiointerface_music_generic_t; // Driver interface for playing music. typedef struct audiointerface_music_s { audiointerface_music_generic_t gen; void* (*SongBuffer) (size_t length); int (*Play) (int looped); int (*PlayFile) (const char *filename, int looped); } audiointerface_music_t; // Driver interface for playing CD tracks. typedef struct audiointerface_cd_s { audiointerface_music_generic_t gen; int (*Play) (int track, int looped); } audiointerface_cd_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/doomsday.h0000644000175000017500000006610011357170241021075 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomsday.h: Doomsday Engine API (Routines exported from Doomsday.exe). * * Games and plugins need to include this to gain access to the engine's * features. */ #ifndef __DOOMSDAY_EXPORTS_H__ #define __DOOMSDAY_EXPORTS_H__ // The calling convention. #if defined(WIN32) # define _DECALL __cdecl #elif defined(UNIX) # define _DECALL #endif #ifdef __cplusplus extern "C" { #endif /** * Public definitions of the internal map data pointers. These can be * accessed externally, but only as identifiers to data instances. * For example, a game could use sector_t to identify to sector to * change with the Map Update API. * * Define __INTERNAL_MAP_DATA_ACCESS__ if access to the internal map data * structures is needed. */ #ifndef __INTERNAL_MAP_DATA_ACCESS__ typedef struct node_s { int type; } node_t; typedef struct vertex_s {int type; } vertex_t; typedef struct linedef_s { int type; } linedef_t; typedef struct sidedef_s { int type; } sidedef_t; typedef struct seg_s { int type; } seg_t; typedef struct subsector_s { int type; } subsector_t; typedef struct sector_s { int type; } sector_t; typedef struct plane_s { int type; } plane_t; typedef struct material_s { int type; } material_t; #endif #include "dd_share.h" #include "dd_plugin.h" // Base. void DD_AddIWAD(const char* path); void DD_AddStartupWAD(const char* file); void DD_SetConfigFile(const char* filename); void DD_SetDefsFile(const char* file); int _DECALL DD_GetInteger(int ddvalue); void DD_SetInteger(int ddvalue, int parm); void DD_SetVariable(int ddvalue, void* ptr); void* DD_GetVariable(int ddvalue); ddplayer_t* DD_GetPlayer(int number); // Base: Definitions. int Def_Get(int type, const char* id, void* out); int Def_Set(int type, int index, int value, const void* ptr); int Def_EvalFlags(char* flags); // Base: Input. void DD_ClearKeyRepeaters(void); int DD_GetKeyCode(const char* name); // Base: WAD. lumpnum_t W_CheckNumForName(const char* name); lumpnum_t W_GetNumForName(const char* name); size_t W_LumpLength(lumpnum_t lump); const char* W_LumpName(lumpnum_t lump); void W_ReadLump(lumpnum_t lump, void* dest); void W_ReadLumpSection(lumpnum_t lump, void* dest, size_t startOffset, size_t length); const void* W_CacheLumpNum(lumpnum_t lump, int tag); const void* W_CacheLumpName(const char* name, int tag); void W_ChangeCacheTag(lumpnum_t lump, int tag); const char* W_LumpSourceFile(lumpnum_t lump); uint W_CRCNumber(void); boolean W_IsFromIWAD(lumpnum_t lump); lumpnum_t W_OpenAuxiliary(const char* fileName); // Base: Zone. void* _DECALL Z_Malloc(size_t size, int tag, void* ptr); void* _DECALL Z_Calloc(size_t size, int tag, void* user); void* Z_Realloc(void* ptr, size_t n, int mallocTag); void* Z_Recalloc(void* ptr, size_t n, int callocTag); void _DECALL Z_Free(void* ptr); void Z_FreeTags(int lowTag, int highTag); void Z_ChangeTag2(void* ptr, int tag); void Z_CheckHeap(void); // Console. int Con_Busy(int flags, const char* taskName, int (*workerFunc)(void*), void* workerData); void Con_BusyWorkerEnd(void); boolean Con_IsBusy(void); void Con_Open(int yes); void Con_SetFont(ddfont_t* cfont); void Con_AddCommand(ccmd_t* cmd); void Con_AddVariable(cvar_t* var); void Con_AddCommandList(ccmd_t* cmdlist); void Con_AddVariableList(cvar_t* varlist); cvar_t* Con_GetVariable(const char* name); byte Con_GetByte(const char* name); int Con_GetInteger(const char* name); float Con_GetFloat(const char* name); char* Con_GetString(const char* name); void Con_SetInteger(const char* name, int value, byte override); void Con_SetFloat(const char* name, float value, byte override); void Con_SetString(const char* name, char* text, byte override); void Con_Printf(const char* format, ...) PRINTF_F(1,2); void Con_FPrintf(int flags, const char* format, ...) PRINTF_F(2,3); int DD_Execute(int silent, const char* command); int DD_Executef(int silent, const char* command, ...); void Con_Message(const char* message, ...) PRINTF_F(1,2); void Con_Error(const char* error, ...) PRINTF_F(1,2); // Console: Bindings. void B_SetContextFallback(const char* name, int (*responderFunc)(event_t*)); int B_BindingsForCommand(const char* cmd, char* buf, size_t bufSize); int B_BindingsForControl(int localPlayer, const char* controlName, int inverse, char* buf, size_t bufSize); // System. void Sys_TicksPerSecond(float num); int Sys_GetTime(void); double Sys_GetSeconds(void); uint Sys_GetRealTime(void); void Sys_Sleep(int millisecs); int Sys_CriticalMessage(char* msg); void Sys_Quit(void); // System: Files. int F_Access(const char* path); unsigned int F_LastModified(const char* fileName); // Map building interface. boolean MPE_Begin(const char* name); boolean MPE_End(void); uint MPE_VertexCreate(float x, float y); boolean MPE_VertexCreatev(size_t num, float* values, uint* indices); uint MPE_SidedefCreate(uint sector, short flags, materialnum_t topMaterial, float topOffsetX, float topOffsetY, float topRed, float topGreen, float topBlue, materialnum_t middleMaterial, float middleOffsetX, float middleOffsetY, float middleRed, float middleGreen, float middleBlue, float middleAlpha, materialnum_t bottomMaterial, float bottomOffsetX, float bottomOffsetY, float bottomRed, float bottomGreen, float bottomBlue); uint MPE_LinedefCreate(uint v1, uint v2, uint frontSide, uint backSide, int flags); uint MPE_SectorCreate(float lightlevel, float red, float green, float blue); uint MPE_PlaneCreate(uint sector, float height, materialnum_t num, float matOffsetX, float matOffsetY, float r, float g, float b, float a, float normalX, float normalY, float normalZ); uint MPE_PolyobjCreate(uint* lines, uint linecount, int tag, int sequenceType, float anchorX, float anchorY); boolean MPE_GameObjProperty(const char* objName, uint idx, const char* propName, valuetype_t type, void* data); // Custom map object data types. boolean P_RegisterMapObj(int identifier, const char* name); boolean P_RegisterMapObjProperty(int identifier, int propIdentifier, const char* propName, valuetype_t type); // Network. void Net_SendPacket(int to_player, int type, void* data, size_t length); int Net_GetTicCmd(void* command, int player); const char* Net_GetPlayerName(int player); ident_t Net_GetPlayerID(int player); // Play. float P_AccurateDistance(float dx, float dy); float P_ApproxDistance(float dx, float dy); float P_ApproxDistance3(float dx, float dy, float dz); int P_PointOnLinedefSide(float x, float y, const struct linedef_s* line); int P_BoxOnLineSide(const float* tmbox, const struct linedef_s* ld); void P_MakeDivline(struct linedef_s* li, divline_t* dl); int P_PointOnDivlineSide(float x, float y, const divline_t* line); float P_InterceptVector(divline_t* v2, divline_t* v1); void P_LineOpening(struct linedef_s* linedef); // Object in bounding box iterators. boolean P_MobjsBoxIterator(const float box[4], boolean (*func) (struct mobj_s*, void*), void* data); boolean P_LinesBoxIterator(const float box[4], boolean (*func) (struct linedef_s*, void*), void* data); boolean P_AllLinesBoxIterator(const float box[4], boolean (*func) (struct linedef_s*, void*), void* data); boolean P_SubsectorsBoxIterator(const float box[4], sector_t* sector, boolean (*func) (subsector_t*, void*), void* data); boolean P_PolyobjsBoxIterator(const float box[4], boolean (*func) (struct polyobj_s*, void*), void* data); // Object type touching mobjs iterators. boolean P_LineMobjsIterator(struct linedef_s* line, boolean (*func) (struct mobj_s*, void *), void* data); boolean P_SectorTouchingMobjsIterator (sector_t* sector, boolean (*func) (struct mobj_s*, void*), void* data); boolean P_PathTraverse(float x1, float y1, float x2, float y2, int flags, boolean (*trav) (intercept_t*)); boolean P_CheckLineSight(const float from[3], const float to[3], float bottomSlope, float topSlope, int flags); // Play: Controls. void P_NewPlayerControl(int id, controltype_t type, const char* name, const char* bindContext); void P_GetControlState(int playerNum, int control, float* pos, float* relativeOffset); int P_GetImpulseControlState(int playerNum, int control); // Play: Setup. boolean P_LoadMap(const char* mapID); // Play: Map Data Updates and Information Access. unsigned int P_ToIndex(const void* ptr); void* P_ToPtr(int type, uint index); int P_Callback(int type, uint index, void* context, int (*callback)(void* p, void* ctx)); int P_Callbackp(int type, void* ptr, void* context, int (*callback)(void* p, void* ctx)); int P_Iteratep(void *ptr, uint prop, void* context, int (*callback) (void* p, void* ctx)); /* dummy functions */ void* P_AllocDummy(int type, void* extraData); void P_FreeDummy(void* dummy); int P_DummyType(void* dummy); boolean P_IsDummy(void* dummy); void* P_DummyExtraData(void* dummy); /* index-based write functions */ void P_SetBool(int type, uint index, uint prop, boolean param); void P_SetByte(int type, uint index, uint prop, byte param); void P_SetInt(int type, uint index, uint prop, int param); void P_SetFixed(int type, uint index, uint prop, fixed_t param); void P_SetAngle(int type, uint index, uint prop, angle_t param); void P_SetFloat(int type, uint index, uint prop, float param); void P_SetPtr(int type, uint index, uint prop, void* param); void P_SetBoolv(int type, uint index, uint prop, boolean* params); void P_SetBytev(int type, uint index, uint prop, byte* params); void P_SetIntv(int type, uint index, uint prop, int* params); void P_SetFixedv(int type, uint index, uint prop, fixed_t* params); void P_SetAnglev(int type, uint index, uint prop, angle_t* params); void P_SetFloatv(int type, uint index, uint prop, float* params); void P_SetPtrv(int type, uint index, uint prop, void* params); /* pointer-based write functions */ void P_SetBoolp(void* ptr, uint prop, boolean param); void P_SetBytep(void* ptr, uint prop, byte param); void P_SetIntp(void* ptr, uint prop, int param); void P_SetFixedp(void* ptr, uint prop, fixed_t param); void P_SetAnglep(void* ptr, uint prop, angle_t param); void P_SetFloatp(void* ptr, uint prop, float param); void P_SetPtrp(void* ptr, uint prop, void* param); void P_SetBoolpv(void* ptr, uint prop, boolean* params); void P_SetBytepv(void* ptr, uint prop, byte* params); void P_SetIntpv(void* ptr, uint prop, int* params); void P_SetFixedpv(void* ptr, uint prop, fixed_t* params); void P_SetAnglepv(void* ptr, uint prop, angle_t* params); void P_SetFloatpv(void* ptr, uint prop, float* params); void P_SetPtrpv(void* ptr, uint prop, void* params); /* index-based read functions */ boolean P_GetBool(int type, uint index, uint prop); byte P_GetByte(int type, uint index, uint prop); int P_GetInt(int type, uint index, uint prop); fixed_t P_GetFixed(int type, uint index, uint prop); angle_t P_GetAngle(int type, uint index, uint prop); float P_GetFloat(int type, uint index, uint prop); void* P_GetPtr(int type, uint index, uint prop); void P_GetBoolv(int type, uint index, uint prop, boolean* params); void P_GetBytev(int type, uint index, uint prop, byte* params); void P_GetIntv(int type, uint index, uint prop, int* params); void P_GetFixedv(int type, uint index, uint prop, fixed_t* params); void P_GetAnglev(int type, uint index, uint prop, angle_t* params); void P_GetFloatv(int type, uint index, uint prop, float* params); void P_GetPtrv(int type, uint index, uint prop, void* params); /* pointer-based read functions */ boolean P_GetBoolp(void* ptr, uint prop); byte P_GetBytep(void* ptr, uint prop); int P_GetIntp(void* ptr, uint prop); fixed_t P_GetFixedp(void* ptr, uint prop); angle_t P_GetAnglep(void* ptr, uint prop); float P_GetFloatp(void* ptr, uint prop); void* P_GetPtrp(void* ptr, uint prop); void P_GetBoolpv(void* ptr, uint prop, boolean* params); void P_GetBytepv(void* ptr, uint prop, byte* params); void P_GetIntpv(void* ptr, uint prop, int* params); void P_GetFixedpv(void* ptr, uint prop, fixed_t* params); void P_GetAnglepv(void* ptr, uint prop, angle_t* params); void P_GetFloatpv(void* ptr, uint prop, float* params); void P_GetPtrpv(void* ptr, uint prop, void* params); uint P_CountGameMapObjs(int identifier); byte P_GetGMOByte(int identifier, uint elmIdx, int propIdentifier); short P_GetGMOShort(int identifier, uint elmIdx, int propIdentifier); int P_GetGMOInt(int identifier, uint elmIdx, int propIdentifier); fixed_t P_GetGMOFixed(int identifier, uint elmIdx, int propIdentifier); angle_t P_GetGMOAngle(int identifier, uint elmIdx, int propIdentifier); float P_GetGMOFloat(int identifier, uint elmIdx, int propIdentifier); // Play: Misc. void P_MergeCommand(ticcmd_t* dest, ticcmd_t* src); // temporary. void P_SpawnDamageParticleGen(struct mobj_s* mo, struct mobj_s* inflictor, int amount); // Play: Mobjs. struct mobj_s* P_MobjCreate(think_t function, float x, float y, float z, angle_t angle, float radius, float height, int ddflags); void P_MobjDestroy(struct mobj_s* mo); void P_MobjSetState(struct mobj_s* mo, int statenum); void P_MobjLink(struct mobj_s* mo, byte flags); int P_MobjUnlink(struct mobj_s* mo); // Mobj linked object iterators. boolean P_MobjLinesIterator(struct mobj_s* mo, boolean (*func) (struct linedef_s*, void*), void*); boolean P_MobjSectorsIterator(struct mobj_s* mo, boolean (*func) (sector_t*, void*), void* data); // Play: Polyobjs. boolean P_PolyobjMove(struct polyobj_s* po, float x, float y); boolean P_PolyobjRotate(struct polyobj_s* po, angle_t angle); void P_PolyobjLink(struct polyobj_s* po); void P_PolyobjUnLink(struct polyobj_s* po); struct polyobj_s* P_GetPolyobj(uint num); void P_SetPolyobjCallback(void (*func)(struct mobj_s*, void*, void*)); // Play: Materials. materialnum_t P_MaterialCheckNumForName(const char* name, material_namespace_t mnamespace); materialnum_t P_MaterialNumForName(const char* name, material_namespace_t mnamespace); materialnum_t P_MaterialCheckNumForIndex(uint idx, material_namespace_t mnamespace); materialnum_t P_MaterialNumForIndex(uint idx, material_namespace_t mnamespace); const char* P_GetMaterialName(material_t* mat); void P_MaterialPrecache(material_t* mat); // Play: Thinkers. void DD_InitThinkers(void); void DD_RunThinkers(void); void DD_ThinkerAdd(thinker_t* th); void DD_ThinkerRemove(thinker_t* th); void DD_ThinkerSetStasis(thinker_t* th, boolean on); boolean DD_IterateThinkers(think_t type, boolean (*func) (thinker_t *th, void*), void* data); // Refresh. int DD_GetFrameRate(void); void R_SetDataPath(const char* path); void R_SetupMap(int mode, int flags); void R_PrecacheMap(void); void R_PrecacheMobjNum(int mobjtypeNum); void R_PrecachePatch(lumpnum_t lump); void R_PrecacheSkinsForState(int stateIndex); void R_RenderPlayerView(int num); void R_SetViewWindow(int x, int y, int w, int h); int R_GetViewPort(int player, int* x, int* y, int* w, int* h); void R_SetBorderGfx(char* lumps[9]); boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* sprinfo); boolean R_GetPatchInfo(lumpnum_t lump, patchinfo_t* info); int R_CreateAnimGroup(int flags); void R_AddToAnimGroup(int groupNum, materialnum_t num, int tics, int randomTics); void R_HSVToRGB(float* rgb, float h, float s, float v); angle_t R_PointToAngle2(float x1, float y1, float x2, float y2); struct subsector_s* R_PointInSubsector(float x, float y); colorpaletteid_t R_CreateColorPalette(const char* fmt, const char* name, const byte* data, size_t num); colorpaletteid_t R_GetColorPaletteNumForName(const char* name); const char* R_GetColorPaletteNameForNum(colorpaletteid_t id); void R_GetColorPaletteRGBf(colorpaletteid_t id, float rgb[3], int idx, boolean correctGamma); // Renderer. void Rend_Reset(void); void Rend_SkyParams(int layer, int param, void* data); // Graphics. void GL_UseFog(int yes); byte* GL_GrabScreen(void); DGLuint GL_LoadGraphics(ddresourceclass_t resClass, const char* name, gfxmode_t mode, int useMipmap, boolean clamped, int otherFlags); DGLuint GL_NewTextureWithParams3(int format, int width, int height, void* pixels, int flags, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT); void GL_SetFilter(boolean enable); void GL_SetFilterColor(float r, float g, float b, float a); // Graphics: 2D drawing. void GL_DrawPatch(int x, int y, lumpnum_t lump); void GL_DrawPatch_CS(int x, int y, lumpnum_t lump); void GL_DrawPatchLitAlpha(int x, int y, float light, float alpha, lumpnum_t lump); void GL_DrawFuzzPatch(int x, int y, lumpnum_t lump); void GL_DrawAltFuzzPatch(int x, int y, lumpnum_t lump); void GL_DrawShadowedPatch(int x, int y, lumpnum_t lump); void GL_DrawRawScreen(lumpnum_t lump, float offx, float offy); void GL_DrawRawScreen_CS(lumpnum_t lump, float offx, float offy, float scalex, float scaley); // Audio. void S_MapChange(void); int S_LocalSoundAtVolumeFrom(int sound_id, struct mobj_s* origin, float* pos, float volume); int S_LocalSoundAtVolume(int soundID, struct mobj_s* origin, float volume); int S_LocalSound(int soundID, struct mobj_s* origin); int S_LocalSoundFrom(int soundID, float* fixedpos); int S_StartSound(int soundId, struct mobj_s* origin); int S_StartSoundEx(int soundId, struct mobj_s* origin); int S_StartSoundAtVolume(int soundID, struct mobj_s* origin, float volume); int S_ConsoleSound(int soundID, struct mobj_s* origin, int targetConsole); void S_StopSound(int soundID, struct mobj_s* origin); int S_IsPlaying(int soundID, struct mobj_s* origin); int S_StartMusic(const char* musicID, boolean looped); int S_StartMusicNum(int id, boolean looped); void S_StopMusic(void); void S_PauseMusic(boolean doPause); // Miscellaneous. size_t M_ReadFile(const char* name, byte** buffer); size_t M_ReadFileCLib(const char* name, byte** buffer); boolean M_WriteFile(const char* name, void* source, size_t length); void M_ExtractFileBase(char* dest, const char* path, size_t len); char* M_FindFileExtension(char* path); boolean M_CheckPath(const char* path); int M_FileExists(const char* file); void M_TranslatePath(char* translated, const char* path, size_t len); const char* M_PrettyPath(const char* path); char* M_SkipWhite(char* str); char* M_FindWhite(char* str); char* M_StrCatQuoted(char* dest, const char* src, size_t len); byte RNG_RandByte(void); float RNG_RandFloat(void); void M_ClearBox(fixed_t* box); void M_AddToBox(fixed_t* box, fixed_t x, fixed_t y); int M_ScreenShot(const char* filename, int bits); int M_CeilPow2(int num); // MiscellaneousL: Time utilities. boolean M_RunTrigger(trigger_t* trigger, timespan_t advanceTime); boolean M_CheckTrigger(const trigger_t* trigger, timespan_t advanceTime); // Miscellaneous: Math. void V2_Rotate(float vec[2], float radians); float M_PointLineDistance(const float* a, const float* b, const float* c); float M_ProjectPointOnLine(const float* point, const float* linepoint, const float* delta, float gap, float* result); binangle_t bamsAtan2(int y, int x); // Miscellaneous: Command line. void _DECALL ArgAbbreviate(const char* longName, const char* shortName); int _DECALL Argc(void); const char* _DECALL Argv(int i); const char** _DECALL ArgvPtr(int i); const char* _DECALL ArgNext(void); int _DECALL ArgCheck(const char* check); int _DECALL ArgCheckWith(const char* check, int num); int _DECALL ArgExists(const char* check); int _DECALL ArgIsOption(int i); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/sys_audiod.h0000644000175000017500000000260111357170241021415 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod.h: Audio Driver. */ #ifndef __DOOMSDAY_AUDIO_DRIVER_H__ #define __DOOMSDAY_AUDIO_DRIVER_H__ typedef enum { AUDIOD_DUMMY, AUDIOD_SDL_MIXER, AUDIOD_OPENAL, #ifdef WIN32 AUDIOD_DSOUND, AUDIOD_WINMM, #endif } audiodriver_e; typedef struct audiodriver_s { int (*Init) (void); void (*Shutdown) (void); void (*Event) (int type); } audiodriver_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/dd_plugin.h0000644000175000017500000000370111357170241021221 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_plugin.h: Plugin Subsystem */ #ifndef __DOOMSDAY_PLUGIN_H__ #define __DOOMSDAY_PLUGIN_H__ #define MAX_HOOKS 8 #define HOOKF_EXCLUSIVE 0x01000000 typedef int (*hookfunc_t) (int type, int parm, void *data); enum // Hook types. { HOOK_STARTUP = 0, // Called ASAP after startup. HOOK_INIT = 1, // Called after engine has been initialized. HOOK_DEFS = 2, // Called after DEDs have been loaded. HOOK_MAP_CONVERT = 3, // Called when a map needs converting. HOOK_TICKER = 4, // Called as part of the run loop. NUM_HOOK_TYPES }; int Plug_AddHook(int hook_type, hookfunc_t hook); int Plug_RemoveHook(int hook_type, hookfunc_t hook); // Plug_DoHook is used by the engine to call all functions // registered to a hook. int Plug_DoHook(int hook_type, int parm, void *data); int Plug_CheckForHook(int hookType); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/dd_api.h0000644000175000017500000001133111357170241020472 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_api.h: Data Structures for the Engine/Game Interface */ #ifndef __DOOMSDAY_GAME_API_H__ #define __DOOMSDAY_GAME_API_H__ #include "dd_share.h" /** * The routines/data exported out of the Doomsday engine: * * This structure contains pointers to routines that can have alternative * handlers in the engine. Also, some select global variables are exported * using this structure (most importantly the map data). */ typedef struct game_import_s { size_t apiSize; // sizeof(game_import_t) int version; // Doomsday Engine version. // // DATA // // Data arrays. mobjinfo_t** mobjInfo; state_t** states; sprname_t** sprNames; ddtext_t** text; // General information. int* validCount; } game_import_t; /** * The routines/data exported from the game DLL. */ typedef struct { size_t apiSize; // sizeof(game_export_t) // Base-level. void (*PreInit) (void); void (*PostInit) (void); void (*Shutdown) (void); void (*UpdateState) (int step); int (*GetInteger) (int id); void *(*GetVariable) (int id); // Networking. int (*NetServerStart) (int before); int (*NetServerStop) (int before); int (*NetConnect) (int before); int (*NetDisconnect) (int before); long int (*NetPlayerEvent) (int playernum, int type, void* data); int (*NetWorldEvent) (int type, int parm, void* data); void (*HandlePacket) (int fromplayer, int type, void* data, size_t length); void *(*NetWriteCommands) (int numCommands, void* data); void *(*NetReadCommands) (size_t pktLength, void* data); // Tickers. void (*Ticker) (timespan_t ticLength); // Responders. boolean (*PrivilegedResponder) (event_t* ev); boolean (*G_Responder) (event_t* ev); boolean (*FallbackResponder) (event_t* ev); // Refresh. void (*BeginFrame) (void); void (*EndFrame) (void); void (*G_Drawer) (int layer); void (*G_Drawer2) (void); void (*ConsoleBackground) (int* width, int* height); // Miscellaneous. void (*MobjThinker) (); float (*MobjFriction) (void* mobj); // Returns a friction factor. // Main structure sizes. size_t ticcmdSize; // sizeof(ticcmd_t) size_t mobjSize; // sizeof(mobj_t) size_t polyobjSize; // sizeof(polyobj_t) // Map data setup // This routine is called before any data is read // (with the number of items to be read) to allow the // game do any initialization it needs (eg create an // array of its own private data structures). void (*SetupForMapData) (int type, uint num); // This routine is called when trying to assign a value read // from the map data (to a property known to us) that we don't // know what to do with. // (eg the side->toptexture field contains a text string that // we don't understand but the game might). // The action code returned by the game depends on the context. int (*HandleMapDataPropertyValue) (uint id, int dtype, int prop, valuetype_t type, void* data); // Post map setup // The engine calls this to inform the game of any changes it is // making to map data object to which the game might want to // take further action. int (*HandleMapObjectStatusReport) (int code, uint id, int dtype, void* data); } game_export_t; typedef game_export_t* (*GETGAMEAPI) (game_import_t *); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/dd_maptypes.h0000644000175000017500000000625511357170241021574 0ustar keeskees/* Generated by .\..\..\engine\scripts\makedmt.py */ #ifndef __DOOMSDAY_PLAY_PUBLIC_MAP_DATA_TYPES_H__ #define __DOOMSDAY_PLAY_PUBLIC_MAP_DATA_TYPES_H__ #define DMT_VERTEX_POS DDVT_FLOAT #define DMT_SEG_SIDEDEF DDVT_PTR #define DMT_SEG_V DDVT_PTR // [Start, End] of the segment. #define DMT_SEG_LINEDEF DDVT_PTR #define DMT_SEG_SEC DDVT_PTR #define DMT_SEG_SUBSECTOR DDVT_PTR #define DMT_SEG_BACKSEG DDVT_PTR #define DMT_SEG_ANGLE DDVT_ANGLE #define DMT_SEG_SIDE DDVT_BYTE // 0=front, 1=back #define DMT_SEG_FLAGS DDVT_BYTE #define DMT_SEG_LENGTH DDVT_FLOAT // Accurate length of the segment (v1 -> v2). #define DMT_SEG_OFFSET DDVT_FLOAT #define DMT_SUBSECTOR_SEGCOUNT DDVT_UINT #define DMT_SUBSECTOR_SEGS DDVT_PTR // [segcount] size. #define DMT_SUBSECTOR_POLYOBJ DDVT_PTR // NULL, if there is no polyobj. #define DMT_SUBSECTOR_SECTOR DDVT_PTR #define DMT_MATERIAL_MNAMESPACE DDVT_INT #define DMT_MATERIAL_FLAGS DDVT_SHORT // MATF_* flags #define DMT_MATERIAL_WIDTH DDVT_SHORT // Defined width & height of the material (not texture!). #define DMT_MATERIAL_HEIGHT DDVT_SHORT #define DMT_SURFACE_FLAGS DDVT_INT // SUF_ flags #define DMT_SURFACE_MATERIAL DDVT_PTR #define DMT_SURFACE_BLENDMODE DDVT_BLENDMODE #define DMT_SURFACE_NORMAL DDVT_FLOAT // Surface normal #define DMT_SURFACE_OFFSET DDVT_FLOAT // [X, Y] Planar offset to surface material origin. #define DMT_SURFACE_RGBA DDVT_FLOAT // Surface color tint #define DMT_PLANE_SOUNDORG DDVT_PTR // Sound origin for plane #define DMT_PLANE_SECTOR DDVT_PTR // Owner of the plane (temp) #define DMT_PLANE_HEIGHT DDVT_FLOAT // Current height #define DMT_PLANE_GLOW DDVT_FLOAT // Glow amount #define DMT_PLANE_GLOWRGB DDVT_FLOAT // Glow color #define DMT_PLANE_TARGET DDVT_FLOAT // Target height #define DMT_PLANE_SPEED DDVT_FLOAT // Move speed #define DMT_SECTOR_VALIDCOUNT DDVT_INT // if == validCount, already checked. #define DMT_SECTOR_LIGHTLEVEL DDVT_FLOAT #define DMT_SECTOR_RGB DDVT_FLOAT #define DMT_SECTOR_MOBJLIST DDVT_PTR // List of mobjs in the sector. #define DMT_SECTOR_LINEDEFCOUNT DDVT_UINT #define DMT_SECTOR_LINEDEFS DDVT_PTR // [lineDefCount+1] size. #define DMT_SECTOR_SSECTORCOUNT DDVT_UINT #define DMT_SECTOR_SSECTORS DDVT_PTR // [ssectorCount+1] size. #define DMT_SECTOR_SOUNDORG DDVT_PTR #define DMT_SECTOR_PLANECOUNT DDVT_UINT #define DMT_SECTOR_REVERB DDVT_FLOAT #define DMT_SIDEDEF_SEGCOUNT DDVT_UINT #define DMT_SIDEDEF_SEGS DDVT_PTR // [segcount] size, segs arranged left>right #define DMT_SIDEDEF_LINE DDVT_PTR #define DMT_SIDEDEF_SECTOR DDVT_PTR #define DMT_SIDEDEF_FLAGS DDVT_SHORT #define DMT_LINEDEF_SEC DDVT_PTR #define DMT_LINEDEF_V DDVT_PTR #define DMT_LINEDEF_SIDEDEFS DDVT_PTR #define DMT_LINEDEF_FLAGS DDVT_INT // Public DDLF_* flags. #define DMT_LINEDEF_SLOPETYPE DDVT_INT #define DMT_LINEDEF_VALIDCOUNT DDVT_INT #define DMT_LINEDEF_DX DDVT_FLOAT #define DMT_LINEDEF_DY DDVT_FLOAT #define DMT_LINEDEF_BBOX DDVT_FLOAT #define DMT_NODE_BBOX DDVT_FLOAT // Bounding box for each child. #define DMT_NODE_CHILDREN DDVT_UINT // If NF_SUBSECTOR it's a subsector. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/sys_audiod_sfx.h0000644000175000017500000001022311357170241022274 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_sfx.h: Audio driver - SFX interface. */ #ifndef __DOOMSDAY_AUDIO_DRIVER_SFX_H__ #define __DOOMSDAY_AUDIO_DRIVER_SFX_H__ // Sfx Buffer Flags. #define SFXBF_PLAYING (0x1) // The buffer is playing. #define SFXBF_3D (0x2) // Otherwise playing in 2D mode. #define SFXBF_REPEAT (0x4) // Buffer will repeat until stopped. #define SFXBF_DONT_STOP (0x8) // Never stop until normal finish. #define SFXBF_RELOAD (0x10000) // Sample must be reloaded before playing. // Events. enum { SFXEV_BEGIN, // An update is about to begin. SFXEV_END // The update is done. }; // Buffer properties. enum { SFXBP_VOLUME, // 0..1 SFXBP_FREQUENCY, // 1 = normal SFXBP_PAN, // -1..1 (2D only) SFXBP_MIN_DISTANCE, // 3D only SFXBP_MAX_DISTANCE, SFXBP_POSITION, SFXBP_VELOCITY, SFXBP_RELATIVE_MODE }; // Listener properties. enum { SFXLP_UPDATE, // Not a real value (commit deferred) SFXLP_PRIMARY_FORMAT, // Arguments are bits and rate. SFXLP_UNITS_PER_METER, SFXLP_DOPPLER, SFXLP_POSITION, SFXLP_VELOCITY, SFXLP_ORIENTATION, SFXLP_REVERB // Use SRD_* for indices. }; typedef struct sfxsample_s { int id; // Id number of the sound sample. void* data; // Actual sample data. unsigned int size; // Size in bytes. int numSamples; // Number of samples. int bytesPer; // Bytes per sample (1 or 2). int rate; // Samples per second. int group; // Exclusion group (0, if none). } sfxsample_t; typedef struct sfxbuffer_s { void* ptr; // Pointer to driver's own buffer object. void* ptr3D; // Pointer to driver's 3D buffer data. struct sfxsample_s* sample; // Source sample data. int bytes; // Bytes per sample (1 or 2). int rate; // Samples per second. int flags; unsigned int length; // Length of the buffer (bytes). unsigned int cursor; // Write cursor position (%length). unsigned int written; // Total bytes written. unsigned int endTime; // System time, milliseconds (if !repeating). unsigned int freq; // Played samples per second (real freq). } sfxbuffer_t; // Generic driver interface. All other interfaces are based on this. typedef struct audiointerface_sfx_generic_s { int (*Init) (void); sfxbuffer_t* (*Create) (int flags, int bits, int rate); void (*Destroy) (sfxbuffer_t* buf); void (*Load) (sfxbuffer_t* buf, struct sfxsample_s* sample); void (*Reset) (sfxbuffer_t* buf); void (*Play) (sfxbuffer_t* buf); void (*Stop) (sfxbuffer_t* buf); void (*Refresh) (sfxbuffer_t* buf); void (*Set) (sfxbuffer_t* buf, int prop, float value); void (*Setv) (sfxbuffer_t* buf, int prop, float* values); void (*Listener) (int prop, float value); void (*Listenerv) (int prop, float* values); int (*Getv) (int prop, void* values); } audiointerface_sfx_generic_t; typedef struct audiointerface_sfx_s { audiointerface_sfx_generic_t gen; } audiointerface_sfx_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/dd_types.h0000644000175000017500000001221311357170241021065 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006-2008 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_types.h: Type Definitions */ #ifndef __DOOMSDAY_TYPES_H__ #define __DOOMSDAY_TYPES_H__ /** In Win32 TCHAR and related macros change size depending on if they are using wide characters (unicode utf-16le) or ansi for functions and strings. on Linux and OSX we use utf-8 by default - which conveniently maps to the CHAR type. As a general guide, any other Win32 T style functions used, should also be re-implemented here in an ANSI style form for use on Linix, OSX, and any other UNIX style operating systems or build environments */ #ifndef WIN32 #define TCHAR CHAR #define _T(__v__) __v__ #endif #ifndef _MSC_VER #include // Not MSVC so use C99 standard header #else /* MSVC must define them ouselves. ISO C9x Integer types - not all of them though, just what we need If we need more the this, best of taking the header from MinGW for MSVC users */ /* 7.18.1.1 Exact-width integer types */ typedef signed char int8_t; typedef unsigned char uint8_t; typedef short int16_t; typedef unsigned short uint16_t; typedef int int32_t; typedef unsigned uint32_t; typedef long long int64_t; typedef unsigned long long uint64_t; /* 7.18.1.2 Minimum-width integer types */ typedef signed char int_least8_t; typedef unsigned char uint_least8_t; typedef short int_least16_t; typedef unsigned short uint_least16_t; typedef int int_least32_t; typedef unsigned uint_least32_t; typedef long long int_least64_t; typedef unsigned long long uint_least64_t; /* 7.18.1.3 Fastest minimum-width integer types * Not actually guaranteed to be fastest for all purposes * Here we use the exact-width types for 8 and 16-bit ints. */ typedef char int_fast8_t; typedef unsigned char uint_fast8_t; typedef short int_fast16_t; typedef unsigned short uint_fast16_t; typedef int int_fast32_t; typedef unsigned int uint_fast32_t; typedef long long int_fast64_t; typedef unsigned long long uint_fast64_t; /* 7.18.1.5 Greatest-width integer types */ typedef long long intmax_t; typedef unsigned long long uintmax_t; #endif // The C_DECL macro, used with functions. #ifndef C_DECL # ifdef WIN32 # define C_DECL __cdecl # endif # ifdef UNIX # define C_DECL # endif #endif #ifndef UNIX typedef unsigned int uint; typedef unsigned short ushort; #else typedef uint32_t uint; typedef uint16_t ushort; #endif typedef int fixed_t; typedef unsigned int angle_t; typedef int spritenum_t; typedef int lumpnum_t; typedef uint32_t materialnum_t; typedef uint32_t ident_t; typedef unsigned short nodeindex_t; typedef unsigned short thid_t; typedef unsigned char byte; typedef double timespan_t; #define FILENAME_T_MAXLEN 256 typedef char filename_t[FILENAME_T_MAXLEN]; #define FILENAME_T_LASTINDEX 255 typedef struct directory_s { int drive; filename_t path; } directory_t; typedef struct trigger_s { timespan_t duration; timespan_t accum; } trigger_t; #ifdef __cplusplus # define boolean int #else // Plain C. # ifndef __BYTEBOOL__ # define __BYTEBOOL__ # endif typedef enum ddboolean_e { false, true } ddboolean_t; # define boolean ddboolean_t #endif #define BAMS_BITS 16 #if BAMS_BITS == 32 typedef unsigned long binangle_t; #elif BAMS_BITS == 16 typedef unsigned short binangle_t; #else typedef unsigned char binangle_t; #endif #define DDMAXCHAR ((char)0x7f) #define DDMAXSHORT ((short)0x7fff) #define DDMAXINT ((int)0x7fffffff) // max pos 32-bit int #define DDMAXLONG ((long)0x7fffffff) #define DDMAXFLOAT ((float)1E+37) #define DDMINCHAR ((char)0x80) #define DDMINSHORT ((short)0x8000) #define DDMININT ((int)0x80000000) // max negative 32-bit integer #define DDMINLONG ((long)0x80000000) #define DDMINFLOAT ((float)-(1E+37)) // Predeclarations for map data types. The contents of these structs is // declared in p_maptypes.h. struct node_s; struct vertex_s; struct linedef_s; struct side_s; struct seg_s; struct subsector_s; struct sector_s; struct polyblock_s; struct polyobj_s; struct plane_s; struct surface_s; struct material_s; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/doomsday.def0000644000175000017500000004572211357170241021413 0ustar keeskeesNAME "DOOMSDAY" ; Highest ordinal is currently ; --> 448 <-- ; Other free ordinals: ; 43 formerly P_RegisterPlayerControl ; 44 formerly B_FormEventString ; 45 formerly B_BindingsForCommand ; 65 formerly P_GetBlockRootIdx ; 68 formerly P_BlockLinesIterator ; 69 formerly P_BlockMobjsIterator ; 70 formerly P_BlockPolyobjsIterator ; 77 formerly P_LoadBlockMap ; 78 formerly P_LoadReject ; 95 formerly R_FlatNumForName ; 96 formerly R_CheckTextureNumForName ; 98 formerly R_TextureNameForNum ; 99 formerly R_MaterialSetTranslation ; 100 formerly R_SetTextureTranslation ; 106 formerly DD_GetDGLProcAddress ; 107 formerly GL_DoUpdate ; 108 formerly GL_ChangeResolution ; 112 formerly GL_TextureFilterMode ; 113 formerly DGL_Color ; 116 formerly GL_SetSprite ; 118 formerly GL_SetTexture ; 131 formerly GL_DrawPSprite ; 143 formerly M_Random ; 144 formerly M_FRandom ; 197 formerly PCX_GetSize ; 198 formerly PCX_Load ; 199 formerly PCX_MemoryLoad ; 200 formerly PNG_Load ; 201 formerly TGA_Save24_rgb565 ; 202 formerly TGA_Save24_rgb888 ; 203 formerly TGA_Save24_rgba8888 ; 204 formerly TGA_Save16_rgb888 ; 205 formerly TGA_GetSize ; 206 formerly GL_Update ; 238 formerly DGL_Color2 ; 255 formerly P_PointToBlock ; 326 formerly PO_Alloc ; 332 formerly P_ControlReset ; 317 formerly P_Copy ; 318 formerly P_Copyp ; 319 formerly P_Swap ; 320 formerly P_Swapp ; 328 formerly P_RegisterCustomMapProperty ; 349 formerly R_MaterialIsCustom ; 375 formerly DGL_MultiTexCoord2f ; 376 formerly DGL_MultiTexCoord2fv EXPORTS ; Plugins. Plug_AddHook @1 NONAME Plug_RemoveHook @2 NONAME Plug_DoHook @3 NONAME ; Base. DD_AddIWAD @4 NONAME DD_AddStartupWAD @5 NONAME DD_SetConfigFile @6 NONAME DD_SetDefsFile @7 NONAME DD_GetInteger @8 NONAME DD_SetInteger @9 NONAME DD_SetVariable @249 NONAME DD_GetVariable @250 NONAME DD_GetPlayer @10 NONAME ; Base: Definitions. Def_Get @11 NONAME Def_Set @111 NONAME Def_EvalFlags @12 NONAME ; Base: Input. DD_ClearKeyRepeaters @13 NONAME DD_GetKeyCode @236 NONAME ; Base: WAD. W_CheckNumForName @14 NONAME W_GetNumForName @15 NONAME W_LumpLength @16 NONAME W_LumpName @17 NONAME W_ReadLump @18 NONAME W_ReadLumpSection @253 NONAME W_CacheLumpNum @19 NONAME W_CacheLumpName @20 NONAME W_ChangeCacheTag @21 NONAME W_LumpSourceFile @22 NONAME W_CRCNumber @23 NONAME W_IsFromIWAD @239 NONAME W_OpenAuxiliary @247 NONAME ; Base: Zone. Z_Malloc @24 NONAME Z_Calloc @211 NONAME Z_Realloc @212 NONAME Z_Recalloc @213 NONAME Z_Free @25 NONAME Z_FreeTags @26 NONAME Z_ChangeTag2 @27 NONAME Z_CheckHeap @28 NONAME ; Base: Misc. dd_snprintf @447 NONAME dd_vsnprintf @448 NONAME ; Console. Con_Open @29 NONAME Con_SetFont @30 NONAME Con_AddCommand @31 NONAME Con_AddVariable @32 NONAME Con_AddCommandList @33 NONAME Con_AddVariableList @34 NONAME Con_GetVariable @35 NONAME Con_GetInteger @226 NONAME Con_GetFloat @227 NONAME Con_GetByte @228 NONAME Con_GetString @229 NONAME Con_SetInteger @230 NONAME Con_SetFloat @231 NONAME Con_SetString @36 NONAME Con_Printf @37 NONAME Con_FPrintf @38 NONAME DD_Execute @39 NONAME DD_Executef @40 NONAME Con_Message @41 NONAME Con_Error @42 NONAME Con_Busy @330 NONAME Con_BusyWorkerEnd @331 NONAME ; Console: Bindings. B_BindingsForCommand @428 NONAME B_BindingsForControl @429 NONAME B_SetContextFallback @440 NONAME ; System. ; Sys_TicksPerSecond @46 NONAME Sys_GetTime @47 NONAME Sys_GetSeconds @48 NONAME Sys_GetRealTime @49 NONAME Sys_Sleep @50 NONAME Sys_CriticalMessage @51 NONAME Sys_Quit @52 NONAME ; System: File I/O. F_Access @245 NONAME F_LastModified @246 NONAME ; Map building interface. MPE_Begin @350 NONAME MPE_End @351 NONAME MPE_VertexCreate @352 NONAME MPE_VertexCreatev @409 NONAME MPE_SidedefCreate @353 NONAME MPE_LinedefCreate @354 NONAME MPE_SectorCreate @355 NONAME MPE_PlaneCreate @408 NONAME MPE_PolyobjCreate @356 NONAME MPE_GameObjProperty @413 NONAME ; Network. Net_SendPacket @53 NONAME Net_GetTicCmd @54 NONAME Net_GetPlayerName @55 NONAME Net_GetPlayerID @56 NONAME ; Play. P_AccurateDistance @57 NONAME P_ApproxDistance @58 NONAME P_ApproxDistance3 @243 NONAME P_PointOnLinedefSide @59 NONAME P_BoxOnLineSide @60 NONAME P_MakeDivline @61 NONAME P_PointOnDivlineSide @62 NONAME P_InterceptVector @63 NONAME P_LineOpening @64 NONAME P_MobjsBoxIterator @346 NONAME P_LinesBoxIterator @435 NONAME P_AllLinesBoxIterator @347 NONAME P_PolyobjsBoxIterator @348 NONAME P_SubsectorsBoxIterator @345 NONAME P_LineMobjsIterator @73 NONAME P_SectorTouchingMobjsIterator @74 NONAME P_PathTraverse @75 NONAME P_CheckLineSight @76 NONAME P_MobjSetState @207 NONAME P_SpawnDamageParticleGen @233 NONAME ; Play: Controls. P_NewPlayerControl @251 NONAME P_GetControlState @252 NONAME P_GetImpulseControlState @339 NONAME ; Play: Setup. P_LoadMap @254 NONAME ; Play: Map Data Updates and Information Access. P_ToIndex @256 NONAME P_ToPtr @257 NONAME P_Callback @258 NONAME P_Callbackp @259 NONAME P_Iteratep @410 NONAME ; dummy objects P_AllocDummy @321 NONAME P_FreeDummy @322 NONAME P_DummyType @323 NONAME P_IsDummy @324 NONAME P_DummyExtraData @325 NONAME ; index-based write functions P_SetBool @260 NONAME P_SetByte @261 NONAME P_SetInt @262 NONAME P_SetFixed @263 NONAME P_SetAngle @264 NONAME P_SetFloat @265 NONAME P_SetPtr @267 NONAME P_SetBoolv @268 NONAME P_SetBytev @269 NONAME P_SetIntv @270 NONAME P_SetFixedv @271 NONAME P_SetAnglev @272 NONAME P_SetFloatv @273 NONAME P_SetPtrv @274 NONAME ; pointer-based write functions P_SetBoolp @275 NONAME P_SetBytep @276 NONAME P_SetIntp @277 NONAME P_SetFixedp @278 NONAME P_SetAnglep @279 NONAME P_SetFloatp @280 NONAME P_SetPtrp @281 NONAME P_SetBoolpv @282 NONAME P_SetBytepv @283 NONAME P_SetIntpv @284 NONAME P_SetFixedpv @285 NONAME P_SetAnglepv @286 NONAME P_SetFloatpv @287 NONAME P_SetPtrpv @288 NONAME ; index-based read functions P_GetBool @289 NONAME P_GetByte @290 NONAME P_GetInt @291 NONAME P_GetFixed @292 NONAME P_GetAngle @293 NONAME P_GetFloat @294 NONAME P_GetPtr @295 NONAME P_GetBoolv @296 NONAME P_GetBytev @297 NONAME P_GetIntv @298 NONAME P_GetFixedv @299 NONAME P_GetAnglev @300 NONAME P_GetFloatv @301 NONAME P_GetPtrv @302 NONAME ; pointer-based read functions P_GetBoolp @303 NONAME P_GetBytep @304 NONAME P_GetIntp @305 NONAME P_GetFixedp @306 NONAME P_GetAnglep @307 NONAME P_GetFloatp @308 NONAME P_GetPtrp @309 NONAME P_GetBoolpv @310 NONAME P_GetBytepv @311 NONAME P_GetIntpv @312 NONAME P_GetFixedpv @313 NONAME P_GetAnglepv @314 NONAME P_GetFloatpv @315 NONAME P_GetPtrpv @316 NONAME P_CountGameMapObjs @414 NONAME P_GetGMOByte @415 NONAME P_GetGMOShort @416 NONAME P_GetGMOInt @417 NONAME P_GetGMOFixed @418 NONAME P_GetGMOAngle @419 NONAME P_GetGMOFloat @420 NONAME ; Play: Misc. P_MergeCommand @333 NONAME P_RegisterMapObj @411 NONAME P_RegisterMapObjProperty @412 NONAME ; Play: Mobjs. P_MobjCreate @357 NONAME P_MobjDestroy @358 NONAME P_MobjLink @66 NONAME P_MobjUnlink @67 NONAME P_MobjLinesIterator @71 NONAME P_MobjSectorsIterator @72 NONAME ; Play: Polyobjs. P_PolyobjMove @79 NONAME P_PolyobjRotate @80 NONAME P_PolyobjLink @82 NONAME P_PolyobjUnLink @81 NONAME P_GetPolyobj @424 NONAME P_SetPolyobjCallback @83 NONAME ; Play: Materials. P_MaterialCheckNumForName @336 NONAME P_GetMaterialName @337 NONAME P_MaterialNumForName @97 NONAME P_MaterialCheckNumForIndex @438 NONAME P_MaterialNumForIndex @437 NONAME P_MaterialPrecache @436 NONAME ; Play: Thinkers. DD_ThinkerAdd @86 NONAME DD_ThinkerRemove @87 NONAME DD_ThinkerSetStasis @426 NONAME DD_RunThinkers @84 NONAME DD_InitThinkers @85 NONAME DD_IterateThinkers @425 NONAME ; Refresh. DD_GetFrameRate @88 NONAME R_SetDataPath @234 NONAME R_SetupMap @89 NONAME R_PrecacheMap @90 NONAME R_PrecacheMobjNum @427 NONAME R_PrecacheSkinsForState @240 NONAME R_PrecachePatch @335 NONAME R_RenderPlayerView @91 NONAME R_SetViewWindow @92 NONAME R_GetViewPort @430 NONAME R_SetBorderGfx @93 NONAME R_GetSpriteInfo @94 NONAME R_GetPatchInfo @237 NONAME R_PointToAngle2 @101 NONAME R_PointInSubsector @102 NONAME R_CreateAnimGroup @241 NONAME R_AddToAnimGroup @242 NONAME R_HSVToRGB @439 NONAME R_CreateColorPalette @444 NONAME R_GetColorPaletteNumForName @446 NONAME R_GetColorPaletteNameForNum @445 NONAME R_GetColorPaletteRGBf @423 NONAME ; DGL. DGL_SetMaterial @117 NONAME DGL_SetNoMaterial @115 NONAME DGL_SetPSprite @114 NONAME DGL_SetPatch @196 NONAME DGL_SetTranslatedSprite @334 NONAME DGL_SetRawImage @119 NONAME DGL_Enable @387 NONAME DGL_Disable @388 NONAME DGL_EnableTexUnit @405 NONAME DGL_DisableTexUnit @406 NONAME DGL_GetIntegerv @392 NONAME DGL_GetInteger @393 NONAME DGL_SetInteger @394 NONAME DGL_GetFloat @399 NONAME DGL_SetFloat @401 NONAME DGL_BlendFunc @389 NONAME DGL_BlendOp @407 NONAME DGL_BlendMode @338 NONAME DGL_MatrixMode @359 NONAME DGL_PushMatrix @360 NONAME DGL_PopMatrix @361 NONAME DGL_LoadIdentity @362 NONAME DGL_Ortho @390 NONAME DGL_Scissor @404 NONAME DGL_Bind @396 NONAME DGL_DeleteTextures @403 NONAME DGL_Begin @363 NONAME DGL_End @364 NONAME DGL_NewList @431 NONAME DGL_EndList @432 NONAME DGL_CallList @433 NONAME DGL_DeleteLists @434 NONAME DGL_Translatef @384 NONAME DGL_Rotatef @385 NONAME DGL_Scalef @386 NONAME DGL_Color3ub @365 NONAME DGL_Color3ubv @366 NONAME DGL_Color4ub @367 NONAME DGL_Color4ubv @368 NONAME DGL_Color3f @369 NONAME DGL_Color3fv @370 NONAME DGL_Color4f @371 NONAME DGL_Color4fv @372 NONAME DGL_TexCoord2f @373 NONAME DGL_TexCoord2fv @374 NONAME DGL_Vertex2f @377 NONAME DGL_Vertex2fv @378 NONAME DGL_Vertex3f @379 NONAME DGL_Vertex3fv @380 NONAME DGL_Vertices2ftv @381 NONAME DGL_Vertices3ftv @382 NONAME DGL_Vertices3fctv @383 NONAME DGL_DrawLine @127 NONAME DGL_DrawRect @128 NONAME DGL_DrawRectTiled @129 NONAME DGL_DrawCutRectTiled @130 NONAME ; Renderer. Rend_Reset @103 NONAME Rend_SkyParams @105 NONAME ; Graphics. GL_UseFog @104 NONAME GL_GrabScreen @109 NONAME GL_LoadGraphics @244 NONAME GL_NewTextureWithParams3 @329 NONAME GL_SetFilter @132 NONAME GL_SetFilterColor @441 NONAME ; Graphics: 2D drawing. GL_DrawPatch @120 NONAME GL_DrawPatch_CS @121 NONAME GL_DrawPatchLitAlpha @122 NONAME GL_DrawFuzzPatch @123 NONAME GL_DrawAltFuzzPatch @124 NONAME GL_DrawShadowedPatch @125 NONAME GL_DrawRawScreen @126 NONAME GL_DrawRawScreen_CS @235 NONAME ; Audio. S_MapChange @225 NONAME S_LocalSoundAtVolumeFrom @221 NONAME S_LocalSoundAtVolume @214 NONAME S_LocalSound @215 NONAME S_LocalSoundFrom @216 NONAME S_StartSound @217 NONAME S_StartSoundEx @327 NONAME S_StartSoundAtVolume @224 NONAME S_ConsoleSound @218 NONAME S_StopSound @223 NONAME S_IsPlaying @110 NONAME S_StartMusic @219 NONAME S_StartMusicNum @222 NONAME S_StopMusic @220 NONAME S_PauseMusic @232 NONAME ; Miscellaneous. M_ReadFile @133 NONAME M_ReadFileCLib @134 NONAME M_WriteFile @135 NONAME M_ExtractFileBase @136 NONAME M_FindFileExtension @137 NONAME M_FileExists @139 NONAME M_CheckPath @138 NONAME M_TranslatePath @140 NONAME M_PrettyPath @421 NONAME M_SkipWhite @141 NONAME M_FindWhite @142 NONAME M_StrCatQuoted @248 NONAME M_ClearBox @208 NONAME M_AddToBox @209 NONAME M_ScreenShot @210 NONAME M_CheckTrigger @340 NONAME M_RunTrigger @341 NONAME M_CeilPow2 @422 NONAME ; Math. ; Binary angles. bamsAtan2 @145 NONAME ; Vectors. V2_Rotate @344 NONAME ; Utilities. M_PointLineDistance @442 NONAME M_ProjectPointOnLine @443 NONAME ; Miscellaneous: Command line. ArgAbbreviate @146 NONAME Argc @147 NONAME Argv @148 NONAME ArgvPtr @149 NONAME ArgNext @150 NONAME ArgCheck @151 NONAME ArgCheckWith @152 NONAME ArgExists @153 NONAME ArgIsOption @154 NONAME ; Doomsday Engine Definitions. DED_Init @155 NONAME DED_Destroy @156 NONAME DED_Read @157 NONAME DED_AddFlag @159 NONAME DED_AddMobj @160 NONAME DED_AddState @161 NONAME DED_AddSprite @162 NONAME DED_AddLight @163 NONAME DED_AddModel @164 NONAME DED_AddSound @165 NONAME DED_AddMusic @166 NONAME DED_AddMapInfo @167 NONAME DED_AddText @168 NONAME DED_AddTextureEnv @169 NONAME DED_AddValue @170 NONAME DED_AddDetail @171 NONAME DED_AddPtcGen @172 NONAME DED_AddSectorType @173 NONAME DED_AddLineType @174 NONAME DED_RemoveFlag @176 NONAME DED_RemoveMobj @177 NONAME DED_RemoveState @178 NONAME DED_RemoveSprite @179 NONAME DED_RemoveLight @180 NONAME DED_RemoveModel @181 NONAME DED_RemoveSound @182 NONAME DED_RemoveMusic @183 NONAME DED_RemoveMapInfo @184 NONAME DED_RemoveText @185 NONAME DED_RemoveTextureEnv @186 NONAME DED_RemoveValue @187 NONAME DED_RemoveDetail @188 NONAME DED_RemovePtcGen @189 NONAME DED_RemoveSectorType @190 NONAME DED_RemoveLineType @191 NONAME DED_NewEntries @192 NONAME DED_NewEntry @193 NONAME DED_DelEntry @194 NONAME DED_DelArray @195 NONAME deng-1.9.0-beta6.9+dfsg1/doomsday/engine/api/dd_share.h0000644000175000017500000012043311357170241021027 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_share.h: Shared Macros and Constants * * Macros and constants used by the engine and games. */ #ifndef __DOOMSDAY_SHARED_H__ #define __DOOMSDAY_SHARED_H__ #ifdef __cplusplus extern "C" { #endif // The C_DECL macro, used with compare functions. #ifndef C_DECL # if defined(WIN32) # define C_DECL __cdecl # elif defined(UNIX) # define C_DECL # else # define C_DECL # endif #endif #include #include #include "../portable/include/dd_version.h" #include "dd_types.h" #include "dd_maptypes.h" #include "dd_gl.h" #include "../portable/include/p_think.h" // \todo Not officially a public header file! #include "../portable/include/def_share.h" // \todo Not officially a public header file! //------------------------------------------------------------------------ // // General Definitions and Macros // //------------------------------------------------------------------------ #define DDMAXPLAYERS 16 // The case-independent strcmps have different names. #if WIN32 # define strcasecmp stricmp # define strncasecmp strnicmp #endif #if UNIX # define stricmp strcasecmp # define strnicmp strncasecmp /** * There are manual implementations for these string handling routines: */ char* strupr(char *string); char* strlwr(char *string); #endif int dd_snprintf(char* str, size_t size, const char* format, ...); int dd_vsnprintf(char* str, size_t size, const char* format, va_list ap); // Format checking for printf-like functions in GCC2 #if defined(__GNUC__) && __GNUC__ >= 2 # define PRINTF_F(f,v) __attribute__ ((format (printf, f, v))) #else # define PRINTF_F(f,v) #endif short ShortSwap(short); long LongSwap(long); float FloatSwap(float); #ifdef __BIG_ENDIAN__ #define SHORT(x) ShortSwap(x) #define LONG(x) LongSwap(x) #define FLOAT(x) FloatSwap(x) #define BIGSHORT(x) (x) #define BIGLONG(x) (x) #define BIGFLOAT(x) (x) // In these, x is evaluated multiple times, so increments and decrements // cannot be used. #define MACRO_SHORT(x) ((short)(( ((short)(x)) & 0xff ) << 8) | (( ((short)(x)) & 0xff00) >> 8)) #define MACRO_LONG(x) ((long)((( ((long)(x)) & 0xff) << 24) | (( ((long)(x)) & 0xff00) << 8) | \ (( ((long)(x)) & 0xff0000) >> 8) | (( ((long)(x)) & 0xff000000) >> 24) )) #else // Little-endian. #define SHORT(x) (x) #define LONG(x) (x) #define FLOAT(x) (x) #define BIGSHORT(x) ShortSwap(x) #define BIGLONG(x) LongSwap(x) #define BIGFLOAT(x) FloatSwap(x) #define MACRO_SHORT(x) (x) #define MACRO_LONG(x) (x) #endif #define USHORT(x) ((unsigned short) SHORT(x)) #define ULONG(x) ((unsigned long) LONG(x)) #define MAX_OF(x, y) ((x) > (y)? (x) : (y)) #define MIN_OF(x, y) ((x) < (y)? (x) : (y)) #define MINMAX_OF(a, x, b) ((x) < (a)? (a) : (x) > (b)? (b) : (x)) #define SIGN_OF(x) ((x) > 0? +1 : (x) < 0? -1 : 0) #define INRANGE_OF(x, y, r) ((x) >= (y) - (r) && (x) <= (y) + (r)) #define ROUND(x) ((int) (((x) < 0.0f)? ((x) - 0.5f) : ((x) + 0.5f))) #define ABS(x) ((x) >= 0 ? (x) : -(x)) // Used to replace /255 as *reciprocal255 is less expensive with CPU cycles. // Note that this should err on the side of being < 1/255 to prevent result // exceeding 255 (e.g. 255 * reciprocal255). #define reciprocal255 0.003921568627f typedef enum // Value types. { DDVT_NONE = -1, // Not a read/writeable value type. DDVT_BOOL, DDVT_BYTE, DDVT_SHORT, DDVT_INT, // 32 or 64 DDVT_UINT, DDVT_FIXED, DDVT_ANGLE, DDVT_FLOAT, DDVT_LONG, DDVT_ULONG, DDVT_PTR, DDVT_BLENDMODE } valuetype_t; enum { // Integer values for Set/Get DD_FIRST_VALUE = -1, DD_NETGAME, DD_SERVER, DD_CLIENT, DD_ALLOW_FRAMES, DD_VIEWWINDOW_X, DD_VIEWWINDOW_Y, DD_VIEWWINDOW_WIDTH, DD_VIEWWINDOW_HEIGHT, DD_CONSOLEPLAYER, DD_DISPLAYPLAYER, DD_MIPMAPPING, DD_SMOOTH_IMAGES, DD_DEFAULT_RES_X, DD_DEFAULT_RES_Y, DD_SKY_DETAIL, DD_SFX_VOLUME, DD_MUSIC_VOLUME, DD_MOUSE_INVERSE_Y, DD_FULLBRIGHT, // Render everything fullbright? DD_CCMD_RETURN, DD_GAME_READY, DD_DEDICATED, DD_NOVIDEO, DD_NUMMOBJTYPES, DD_GOTFRAME, DD_PLAYBACK, DD_NUMSOUNDS, DD_NUMMUSIC, DD_NUMLUMPS, DD_CLIENT_PAUSED, DD_WEAPON_OFFSET_SCALE_Y, // 1000x DD_MONOCHROME_PATCHES, // Convert patch image data to monochrome. 1= linear 2= weighted. DD_GAME_DATA_FORMAT, DD_GAME_DRAW_HUD_HINT, // Doomsday advises not to draw the HUD. DD_UPSCALE_AND_SHARPEN_PATCHES, DD_SYMBOLIC_ECHO, DD_MAX_TEXTURE_UNITS, DD_LAST_VALUE, // General constants (not to be used with Get/Set). DD_NEW = -2, DD_SKY = -1, DD_DISABLE, DD_ENABLE, DD_MASK, DD_YES, DD_NO, DD_MATERIAL, DD_OFFSET, DD_HEIGHT, DD_COLUMNS, DD_ROWS, DD_COLOR_LIMIT, DD_PRE, DD_POST, DD_VERSION_SHORT, DD_VERSION_LONG, DD_HORIZON, DD_GAME_ID, DD_DEF_MOBJ, DD_DEF_MOBJ_BY_NAME, DD_DEF_STATE, DD_DEF_SPRITE, DD_DEF_SOUND, DD_DEF_MUSIC, DD_DEF_MAP_INFO, DD_DEF_TEXT, DD_DEF_VALUE, DD_DEF_LINE_TYPE, DD_DEF_SECTOR_TYPE, DD_PSPRITE_BOB_X, DD_PSPRITE_BOB_Y, DD_DEF_FINALE_AFTER, DD_DEF_FINALE_BEFORE, DD_RENDER_RESTART_PRE, DD_RENDER_RESTART_POST, DD_DEF_SOUND_BY_NAME, DD_DEF_SOUND_LUMPNAME, DD_ID, DD_LUMP, DD_CD_TRACK, DD_SPRITE, DD_FRAME, DD_GAME_MODE, // 16 chars max (swdoom, doom1, udoom, tnt, heretic...) DD_GAME_CONFIG, // String: dm/co-op, jumping, etc. DD_DEF_FINALE, DD_GAME_NAME, // (e.g., jdoom, jheretic etc..., suitable for use with filepaths) DD_GAME_NICENAME, // (e.g., jDoom, MyGame:Episode2 etc..., fancy name) DD_GAME_DMUAPI_VER, // Version of the DMU API the game is using. // Non-integer/special values for Set/Get DD_TRANSLATIONTABLES_ADDRESS, DD_TRACE_ADDRESS, // divline 'trace' used by PathTraverse. DD_SPRITE_REPLACEMENT, // Sprite <-> model replacement. DD_ACTION_LINK, // State action routine addresses. DD_MAP_NAME, DD_MAP_AUTHOR, DD_MAP_MUSIC, DD_MAP_MIN_X, DD_MAP_MIN_Y, DD_MAP_MAX_X, DD_MAP_MAX_Y, DD_WINDOW_WIDTH, DD_WINDOW_HEIGHT, DD_WINDOW_HANDLE, DD_DYNLIGHT_TEXTURE, DD_GAME_EXPORTS, DD_SECTOR_COUNT, DD_LINE_COUNT, DD_SIDE_COUNT, DD_VERTEX_COUNT, DD_SEG_COUNT, DD_SUBSECTOR_COUNT, DD_NODE_COUNT, DD_POLYOBJ_COUNT, DD_MATERIAL_COUNT, DD_XGFUNC_LINK, // XG line classes DD_SHARED_FIXED_TRIGGER, DD_GAMETIC, DD_OPENRANGE, DD_OPENTOP, DD_OPENBOTTOM, DD_LOWFLOOR, DD_VIEW_X, DD_VIEW_Y, DD_VIEW_Z, DD_VIEW_ANGLE, DD_VIEW_PITCH, DD_CPLAYER_THRUST_MUL, DD_GRAVITY, DD_PSPRITE_OFFSET_X, // 10x DD_PSPRITE_OFFSET_Y, // 10x DD_PSPRITE_LIGHTLEVEL_MULTIPLIER, DD_TORCH_RED, DD_TORCH_GREEN, DD_TORCH_BLUE, DD_TORCH_ADDITIVE }; // Bounding box coordinates. enum { BOXTOP = 0, BOXBOTTOM = 1, BOXLEFT = 2, BOXRIGHT = 3, BOXFLOOR = 4, BOXCEILING = 5 }; //------------------------------------------------------------------------ // // Fixed-Point Math // //------------------------------------------------------------------------ #define FRACBITS 16 #define FRACUNIT (1<>FRACBITS) ) #define FLT2FIX(x) ( (fixed_t) ((x)*FRACUNIT) ) #if !defined( NO_FIXED_ASM ) && !defined( GNU_X86_FIXED_ASM ) /* *INDENT-OFF* */ __inline fixed_t FixedMul(fixed_t a, fixed_t b) { __asm { // The parameters in eax and ebx. mov eax, a mov ebx, b // The multiplying. imul ebx shrd eax, edx, 16 // eax should hold the return value. } // A value is returned regardless of the compiler warning. } __inline fixed_t FixedDiv2(fixed_t a, fixed_t b) { __asm { // The parameters. mov eax, a mov ebx, b // The operation. cdq shld edx, eax, 16 sal eax, 16 idiv ebx // And the value returns in eax. } // A value is returned regardless of the compiler warning. } /* *INDENT-ON* */ #else // Don't use inline assembler in fixed-point calculations. // (link with plugins/common/m_fixed.c) fixed_t FixedMul(fixed_t a, fixed_t b); fixed_t FixedDiv2(fixed_t a, fixed_t b); #endif // This one is always in plugins/common/m_fixed.c. fixed_t FixedDiv(fixed_t a, fixed_t b); //------------------------------------------------------------------------ // // Key Codes // //------------------------------------------------------------------------ // Most key data is simple ASCII. #define DDKEY_ESCAPE 27 #define DDKEY_RETURN 13 #define DDKEY_TAB 9 #define DDKEY_BACKSPACE 127 #define DDKEY_EQUALS 0x3d #define DDKEY_MINUS 0x2d #define DDKEY_BACKSLASH 0x5C // Extended keys (above 127). enum { DDKEY_RIGHTARROW = 0x80, DDKEY_LEFTARROW, DDKEY_UPARROW, DDKEY_DOWNARROW, DDKEY_F1, DDKEY_F2, DDKEY_F3, DDKEY_F4, DDKEY_F5, DDKEY_F6, DDKEY_F7, DDKEY_F8, DDKEY_F9, DDKEY_F10, DDKEY_F11, DDKEY_F12, DDKEY_NUMLOCK, DDKEY_SCROLL, DDKEY_NUMPAD7, DDKEY_NUMPAD8, DDKEY_NUMPAD9, DDKEY_NUMPAD4, DDKEY_NUMPAD5, DDKEY_NUMPAD6, DDKEY_NUMPAD1, DDKEY_NUMPAD2, DDKEY_NUMPAD3, DDKEY_NUMPAD0, DDKEY_DECIMAL, DDKEY_PAUSE, DDKEY_RSHIFT, DDKEY_LSHIFT = DDKEY_RSHIFT, DDKEY_RCTRL, DDKEY_LCTRL = DDKEY_RCTRL, DDKEY_RALT, DDKEY_LALT = DDKEY_RALT, DDKEY_INS, DDKEY_DEL, DDKEY_PGUP, DDKEY_PGDN, DDKEY_HOME, DDKEY_END, DDKEY_SUBTRACT, // '-' on numeric keypad. DDKEY_ADD, // '+' on numeric keypad. DD_HIGHEST_KEYCODE }; //------------------------------------------------------------------------ // // Events // //------------------------------------------------------------------------ typedef enum { EV_KEY, EV_MOUSE_AXIS, EV_MOUSE_BUTTON, EV_JOY_AXIS, // Joystick main axes (xyz + Rxyz). EV_JOY_SLIDER, // Joystick sliders. EV_JOY_BUTTON, EV_POV, EV_SYMBOLIC, // Symbol text pointed to by data1+data2. NUM_EVENT_TYPES } evtype_t; typedef enum { EVS_DOWN, EVS_UP, EVS_REPEAT, NUM_EVENT_STATES } evstate_t; typedef struct { evtype_t type; evstate_t state; // Only used with digital controls. int data1; // Keys/mouse/joystick buttons. int data2; // Mouse/joystick x move. int data3; // Mouse/joystick y move. int data4; int data5; int data6; } event_t; // The mouse wheel is considered two extra mouse buttons. #define DD_MWHEEL_UP 3 #define DD_MWHEEL_DOWN 4 #define DD_MICKEY_ACCURACY 1000 // Control classes. typedef enum { CC_AXIS, CC_TOGGLE, CC_IMPULSE, NUM_CONTROL_CLASSES } ctlclass_t; //------------------------------------------------------------------------ // // Purge Levels // //------------------------------------------------------------------------ #define PU_STATIC 1 // Static entire execution time. #define PU_SOUND 2 // Static while playing. #define PU_MUSIC 3 // Static while playing. #define PU_USER1 40 #define PU_USER2 41 #define PU_USER3 42 #define PU_USER4 43 #define PU_USER5 44 #define PU_USER6 45 #define PU_USER7 46 #define PU_USER8 47 #define PU_USER9 48 #define PU_USER10 49 #define PU_MAP 50 // Static until map exited (may still be // freed during the map, though). #define PU_MAPSTATIC 52 // Not freed until map exited. // Tags >= 100 are purgable whenever needed. #define PU_PURGELEVEL 100 #define PU_CACHE 101 // Special purgelevel. #define PU_GETNAME 100000L //------------------------------------------------------------------------ // // Map Data // //------------------------------------------------------------------------ #define DMUAPI_VER 1 // Public DMU API version number. // Requested by the engine during init. // Map Update constants. enum /* Do not change the numerical values of the constants! */ { // Flags. OR'ed with a DMU property constant. The most significant // byte is used for the flags. DMU_FLAG_MASK = 0xff000000, DMU_SIDEDEF1_OF_LINE = 0x80000000, DMU_SIDEDEF0_OF_LINE = 0x40000000, DMU_TOP_OF_SIDEDEF = 0x20000000, DMU_MIDDLE_OF_SIDEDEF = 0x10000000, DMU_BOTTOM_OF_SIDEDEF = 0x08000000, DMU_FLOOR_OF_SECTOR = 0x04000000, DMU_CEILING_OF_SECTOR = 0x02000000, // (1 bits left) DMU_NONE = 0, DMU_VERTEX = 1, DMU_SEG, DMU_LINEDEF, DMU_SIDEDEF, DMU_NODE, DMU_SUBSECTOR, DMU_SECTOR, DMU_PLANE, DMU_SURFACE, DMU_MATERIAL, DMU_LINEDEF_BY_TAG, DMU_SECTOR_BY_TAG, DMU_LINEDEF_BY_ACT_TAG, DMU_SECTOR_BY_ACT_TAG, DMU_X, DMU_Y, DMU_XY, DMU_NORMAL_X, DMU_NORMAL_Y, DMU_NORMAL_Z, DMU_NORMAL_XYZ, DMU_VERTEX0, DMU_VERTEX1, DMU_FRONT_SECTOR, DMU_BACK_SECTOR, DMU_SIDEDEF0, DMU_SIDEDEF1, DMU_FLAGS, DMU_DX, DMU_DY, DMU_DXY, DMU_LENGTH, DMU_SLOPE_TYPE, DMU_ANGLE, DMU_OFFSET, DMU_OFFSET_X, DMU_OFFSET_Y, DMU_OFFSET_XY, DMU_VALID_COUNT, DMU_LINEDEF_COUNT, DMU_COLOR, // RGB DMU_COLOR_RED, // red component DMU_COLOR_GREEN, // green component DMU_COLOR_BLUE, // blue component DMU_ALPHA, DMU_BLENDMODE, DMU_LIGHT_LEVEL, DMT_MOBJS, // pointer to start of sector mobjList DMU_BOUNDING_BOX, // float[4] DMU_SOUND_ORIGIN, DMU_WIDTH, DMU_HEIGHT, DMU_TARGET_HEIGHT, DMU_SPEED, DMU_SEG_COUNT, DMU_NAMESPACE }; // Linedef flags: // For use with P_Set/Get(DMU_LINEDEF, n, DMU_FLAGS). #define DDLF_BLOCKING 0x0001 #define DDLF_DONTPEGTOP 0x0002 #define DDLF_DONTPEGBOTTOM 0x0004 // Sidedef flags // For use with P_Set/Get(DMU_SIDEDEF, n, DMU_FLAGS). #define SDF_BLENDTOPTOMID 0x0001 #define SDF_BLENDMIDTOTOP 0x0002 #define SDF_BLENDMIDTOBOTTOM 0x0004 #define SDF_BLENDBOTTOMTOMID 0x0008 #define SDF_MIDDLE_STRETCH 0x0010 // Stretch the middle surface to reach from floor to ceiling. // Surface flags: // For use with P_Set/Get(DMU_SURFACE, n, DMU_FLAGS). #define DDSUF_GLOW 0x00000001 // Surface glows (fully bright). #define DDSUF_MATERIAL_FLIPH 0x00000002 // Surface material is flipped horizontally. #define DDSUF_MATERIAL_FLIPV 0x00000004 // Surface material is flipped vertically. // Map Update status code constants. // Sent to the game when various map update events occur. enum /* Do NOT change the numerical values of the constants. */ { DMUSC_LINE_FIRSTRENDERED }; // All map think-able objects must use this as a base. Also used for sound // origin purposes for all of: mobj_t, polyobj_t, sector_t/plane_t #define DD_BASE_DDMOBJ_ELEMENTS() \ thinker_t thinker; /* thinker node */ \ float pos[3]; /* position [x,y,z] */ typedef struct ddmobj_base_s { DD_BASE_DDMOBJ_ELEMENTS() } ddmobj_base_t; // Fixed-point vertex position. Utility struct for the game, not used by // the engine. typedef struct ddvertex_s { fixed_t pos[2]; } ddvertex_t; // Floating-point vertex position. Utility struct for the game, not used // by the engine. typedef struct ddvertexf_s { float pos[2]; } ddvertexf_t; // SetupMap modes. enum { DDSMM_AFTER_LOADING, // After loading a savegame... DDSMM_FINALIZE, // After everything else is done. DDSMM_INITIALIZE, // Before anything else if done. DDSMM_AFTER_BUSY // After leaving busy mode, which was used during setup. }; enum // Sector reverb data indices. { SRD_VOLUME, SRD_SPACE, SRD_DECAY, SRD_DAMPING, NUM_REVERB_DATA }; #define DD_MAX_MATERIAL_LAYERS 1 //// \temp typedef struct { fixed_t pos[2], dX, dY; } divline_t; typedef struct { float pos[2], dX, dY; } fdivline_t; // For PathTraverse. #define PT_ADDLINES 1 #define PT_ADDMOBJS 2 #define PT_EARLYOUT 4 typedef enum { ST_HORIZONTAL, ST_VERTICAL, ST_POSITIVE, ST_NEGATIVE } slopetype_t; /** * @defgroup lineSightFlags Line Sight Flags * Flags used to dictate logic within P_CheckLineSight. */ /*@{*/ #define LS_PASSLEFT 0x1 // Ray may cross one-sided linedefs from left to right. #define LS_PASSOVER 0x2 // Ray may cross over sector ceiling height on ray-entry side. #define LS_PASSUNDER 0x4 // Ray may cross under sector floor height on ray-entry side. /*@}*/ // For (un)linking. #define DDLINK_SECTOR 0x1 #define DDLINK_BLOCKMAP 0x2 #define DDLINK_NOLINE 0x4 typedef enum intercepttype_e { ICPT_MOBJ, ICPT_LINE } intercepttype_t; typedef struct intercept_s { float frac; // Along trace line. intercepttype_t type; union { struct mobj_s* mo; struct linedef_s* lineDef; } d; } intercept_t; typedef boolean (*traverser_t) (intercept_t* in); #define NO_INDEX 0xffffffff //------------------------------------------------------------------------ // // Mobjs // //------------------------------------------------------------------------ /** * Linknodes are used when linking mobjs to lines. Each mobj has a ring * of linknodes, each node pointing to a line the mobj has been linked to. * Correspondingly each line has a ring of nodes, with pointers to the * mobjs that are linked to that particular line. This way it is possible * that a single mobj is linked simultaneously to multiple lines (which * is common). * * All these rings are maintained by P_Mobj(Un)Link(). */ typedef struct linknode_s { nodeindex_t prev, next; void* ptr; int data; } linknode_t; // State flags. #define STF_FULLBRIGHT 0x00000001 #define STF_NOAUTOLIGHT 0x00000002 // Don't automatically add light if fullbright. // Doomsday mobj flags. #define DDMF_DONTDRAW 0x00000001 #define DDMF_SHADOW 0x00000002 #define DDMF_ALTSHADOW 0x00000004 #define DDMF_BRIGHTSHADOW 0x00000008 #define DDMF_VIEWALIGN 0x00000010 #define DDMF_FITTOP 0x00000020 // Don't let the sprite go into the ceiling. #define DDMF_NOFITBOTTOM 0x00000040 //#define DDMF_UNUSED1 0x00000080 // Formerly DDMF_NOBLOCKMAP #define DDMF_LIGHTSCALE 0x00000180 // Light scale (0: full, 3: 1/4). #define DDMF_LIGHTOFFSET 0x0000f000 // How to offset light (along Z axis). //#define DDMF_RESERVED 0x00030000 // Don't touch these!! (translation class). #define DDMF_BOB 0x00040000 // Bob the Z coord up and down. #define DDMF_LOWGRAVITY 0x00080000 // 1/8th gravity (predict). #define DDMF_MISSILE 0x00100000 // Client removes mobj upon impact. #define DDMF_FLY 0x00200000 // Flying object (doesn't matter if airborne). #define DDMF_NOGRAVITY 0x00400000 // Isn't affected by gravity (predict). #define DDMF_ALWAYSLIT 0x00800000 // Always process DL even if hidden. #define DDMF_SOLID 0x20000000 // Solid on client side. #define DDMF_LOCAL 0x40000000 #define DDMF_REMOTE 0x80000000 // This mobj is really on the server. // Clear masks (flags the Game DLL is not allowed to touch). #define DDMF_CLEAR_MASK 0xc0000000 #define DDMF_LIGHTSCALESHIFT 7 #define DDMF_LIGHTOFFSETSHIFT 12 #define DDMOBJ_RADIUS_MAX 32 // The high byte of the selector is not used for modeldef selecting. // 1110 0000 = alpha level (0: opaque => 7: transparent 7/8) #define DDMOBJ_SELECTOR_MASK 0x00ffffff #define DDMOBJ_SELECTOR_SHIFT 24 #define VISIBLE 1 #define INVISIBLE -1 enum { MX, MY, MZ }; // Momentum axis indices. // Base mobj_t elements. Games MUST use this as the basis for mobj_t. #define DD_BASE_MOBJ_ELEMENTS() \ DD_BASE_DDMOBJ_ELEMENTS() \ \ nodeindex_t lineRoot; /* lines to which this is linked */ \ struct mobj_s* sNext, **sPrev; /* links in sector (if needed) */ \ \ struct subsector_s* subsector; /* subsector in which this resides */ \ float mom[3]; \ angle_t angle; \ spritenum_t sprite; /* used to find patch_t and flip value */ \ int frame; \ float radius; \ float height; \ int ddFlags; /* Doomsday mobj flags (DDMF_*) */ \ float floorClip; /* value to use for floor clipping */ \ int valid; /* if == valid, already checked */ \ int type; /* mobj type */ \ struct state_s* state; \ int tics; /* state tic counter */ \ float floorZ; /* highest contacted floor */ \ float ceilingZ; /* lowest contacted ceiling */ \ struct mobj_s* onMobj; /* the mobj this one is on top of. */ \ boolean wallHit; /* the mobj is hitting a wall. */ \ struct ddplayer_s* dPlayer; /* NULL if not a player mobj. */ \ float srvo[3]; /* short-range visual offset (xyz) */ \ short visAngle; /* visual angle ("angle-servo") */ \ int selector; /* multipurpose info */ \ int validCount; /* used in iterating */ \ int addFrameCount; \ unsigned int lumIdx; /* index+1 of the lumobj/bias source, or 0 */ \ byte haloFactors[DDMAXPLAYERS]; /* strengths of halo */ \ byte translucency; /* default = 0 = opaque */ \ short visTarget; /* -1 = mobj is becoming less visible, */ \ /* 0 = no change, 2= mobj is becoming more visible */ \ int reactionTime; /* if not zero, freeze controls */ \ int tmap, tclass; // Base polyobj_t elements. Games MUST use this as the basis for polyobj_t. #define DD_BASE_POLYOBJ_ELEMENTS() \ DD_BASE_DDMOBJ_ELEMENTS() \ \ struct subsector_s* subsector; /* subsector in which this resides */ \ unsigned int idx; /* Idx of polyobject. */ \ int tag; /* Reference tag. */ \ int validCount; \ float box[2][2]; \ float dest[2]; /* Destination XY. */ \ angle_t angle; \ angle_t destAngle; /* Destination angle. */ \ angle_t angleSpeed; /* Rotation speed. */ \ unsigned int numSegs; \ struct seg_s** segs; \ struct fvertex_s* originalPts; /* Used as the base for the rotations. */ \ struct fvertex_s* prevPts; /* Use to restore the old point values. */ \ float speed; /* Movement speed. */ \ boolean crush; /* Should the polyobj attempt to crush mobjs? */ \ int seqType; \ struct { \ int index; \ unsigned int lineCount; \ struct linedef_s** lineDefs; \ } buildData; //------------------------------------------------------------------------ // // Refresh // //------------------------------------------------------------------------ #define TICRATE 35 // Number of tics / second. #define TICSPERSEC 35 #define SCREENWIDTH 320 #define SCREENHEIGHT 200 //------------------------------------------------------------------------ // // Sound // //------------------------------------------------------------------------ #define DDSF_FLAG_MASK 0xff000000 #define DDSF_NO_ATTENUATION 0x80000000 #define DDSF_REPEAT 0x40000000 typedef struct { float volume; // 0..1 float decay; // Decay factor: 0 (acoustically dead) ... 1 (live) float damping; // High frequency damping factor: 0..1 float space; // 0 (small space) ... 1 (large space) } reverb_t; // Use with PlaySong(). #define DDMUSICF_EXTERNAL 0x80000000 //------------------------------------------------------------------------ // // Graphics // //------------------------------------------------------------------------ /** * Resource classes. Each has its own subdir under Data\Game\. */ typedef enum ddresourceclass_e { DDRC_NONE = -1, DDRC_FIRST = 0, DDRC_TEXTURE = DDRC_FIRST, DDRC_FLAT, DDRC_PATCH, // Not sprites, mind you. Names == lumpnames. DDRC_LIGHTMAP, DDRC_FLAREMAP, DDRC_MUSIC, // Names == lumpnames. DDRC_SFX, // Names == lumpnames. DDRC_GRAPHICS, // Doomsday graphics. DDRC_MODEL, NUM_RESOURCE_CLASSES } ddresourceclass_t; typedef enum resourcetype_e { RT_UNKNOWN = -1, RT_FIRST = 0, RT_GRAPHIC = RT_FIRST, RT_MODEL, RT_SOUND, RT_MUSIC, NUM_RESOURCE_TYPES } resourcetype_t; /** * Processing modes for GL_LoadGraphics. */ typedef enum gfxmode_e { LGM_NORMAL = 0, LGM_GRAYSCALE = 1, LGM_GRAYSCALE_ALPHA = 2, LGM_WHITE_ALPHA = 3 } gfxmode_t; #define DDMAX_MATERIAL_LAYERS 1 typedef enum material_namespace_e { MN_ANY = -1, MN_FIRST, MN_TEXTURES = MN_FIRST, MN_FLATS, MN_SPRITES, MN_SYSTEM, NUM_MATERIAL_NAMESPACES } material_namespace_t; // Material flags: #define MATF_CUSTOM 0x0001 // Material is not derived from an IWAD resource (directly, at least). #define MATF_NO_DRAW 0x0002 // Material should never be drawn. #define MATF_GLOW 0x0004 // Glowing material. #define MATF_SKYMASK 0x0008 // Sky-mask surfaces using this material. // Animation group flags. #define AGF_SMOOTH 0x1 #define AGF_FIRST_ONLY 0x2 #define AGF_PRECACHE 0x4000 // Group is just for precaching. typedef struct lumppatch_s { short width; // Bounding box size. short height; short leftOffset; // Pixels to the left of origin. short topOffset; // Pixels below the origin. int columnOfs[8]; /* Only [width] used the [0] is &columnofs[width] */ } lumppatch_t; typedef struct { int lump; // Lump number. int realLump; // Real lump number. int flip; int offset; int topOffset; int width; int height; int numFrames; // Number of frames the sprite has. } patchinfo_t; typedef struct { struct material_s* material; int realLump; // Real lump number. int flip; int offset; int topOffset; int width; int height; int numFrames; // Number of frames the sprite has. } spriteinfo_t; typedef unsigned int colorpaletteid_t; //------------------------------------------------------------------------ // // Console // //------------------------------------------------------------------------ // Busy mode flags. #define BUSYF_LAST_FRAME 0x1 #define BUSYF_CONSOLE_OUTPUT 0x2 #define BUSYF_PROGRESS_BAR 0x4 #define BUSYF_ACTIVITY 0x8 // Indicate activity. #define BUSYF_NO_UPLOADS 0x10 // Deferred uploads not completed. #define BUSYF_STARTUP 0x20 // Startup mode: normal fonts, texman not available. #define BUSYF_TRANSITION 0x40 // Do a transition effect when busy mode ends. // These correspond the good old text mode VGA colors. #define CBLF_BLACK 0x00000001 #define CBLF_BLUE 0x00000002 #define CBLF_GREEN 0x00000004 #define CBLF_CYAN 0x00000008 #define CBLF_RED 0x00000010 #define CBLF_MAGENTA 0x00000020 #define CBLF_YELLOW 0x00000040 #define CBLF_WHITE 0x00000080 #define CBLF_LIGHT 0x00000100 #define CBLF_RULER 0x00000200 #define CBLF_CENTER 0x00000400 #define CBLF_TRANSMIT 0x80000000 // If server, sent to all clients. // Font flags. #define DDFONT_WHITE 0x1 // The font data is white, can be colored. typedef struct { int flags; float sizeX, sizeY; // The scale. int height; int (*drawText) (const char* text, int x, int y); int (*getWidth) (const char* text); void (*filterText) (char* text); // Maybe alters text. } ddfont_t; /// Argument type for B_BindingsForControl(). typedef enum bfcinverse_e { BFCI_BOTH, BFCI_ONLY_NON_INVERSE, BFCI_ONLY_INVERSE } bfcinverse_t; // Console command. typedef struct ccmd_s { const char* name; const char* params; int (*func) (byte src, int argc, char **argv); int flags; } ccmd_t; // Command sources (where the console command originated from) // These are sent with every (sub)ccmd so we can decide whether or not to execute. enum { CMDS_UNKNOWN, CMDS_DDAY, // Sent by the engine CMDS_GAME, // Sent by the game dll CMDS_CONSOLE, // Sent via direct console input CMDS_BIND, // Sent from a binding/alias CMDS_CONFIG, // Sent via config file CMDS_PROFILE, // Sent via player profile CMDS_CMDLINE, // Sent via the command line CMDS_DED // Sent based on a def in a DED file eg (state->execute) }; // Helper macro for defining console command functions. #define DEFCC(name) int name(byte src, int argc, char** argv) // Console command flags. #define CMDF_NO_DEDICATED 0x00000001 // Not available in dedicated server mode. // Console command usage flags. // (what method(s) CAN NOT be used to invoke a ccmd (used with the CMDS codes above)). #define CMDF_DDAY 0x00800000 #define CMDF_GAME 0x01000000 #define CMDF_CONSOLE 0x02000000 #define CMDF_BIND 0x04000000 #define CMDF_CONFIG 0x08000000 #define CMDF_PROFILE 0x10000000 #define CMDF_CMDLINE 0x20000000 #define CMDF_DED 0x40000000 #define CMDF_CLIENT 0x80000000 // sent over the net from a client. // Console variable flags. #define CVF_NO_ARCHIVE 0x1 // Not written in/read from the defaults file. #define CVF_PROTECTED 0x2 // Can't be changed unless forced. #define CVF_NO_MIN 0x4 // Don't use the minimum. #define CVF_NO_MAX 0x8 // Don't use the maximum. #define CVF_CAN_FREE 0x10 // The string can be freed. #define CVF_HIDE 0x20 #define CVF_READ_ONLY 0x40 // Can't be changed manually at all // Console variable types. typedef enum { CVT_NULL, CVT_BYTE, CVT_INT, CVT_FLOAT, CVT_CHARPTR // ptr points to a char*, which points to the string. } cvartype_t; // Console variable. typedef struct cvar_s { char* name; int flags; cvartype_t type; void* ptr; // Pointer to the data. float min, max; /* Minimum and maximum values (for ints and floats). */ void (*notifyChanged)(struct cvar_s* cvar); } cvar_t; //------------------------------------------------------------------------ // // Networking // //------------------------------------------------------------------------ /** * Tick Commands. Usually only a part of this data is transferred over * the network. In addition to tick commands, clients will sent 'impulses' * to the server when they want to change a weapon, use an artifact, or * maybe commit suicide. */ typedef struct ticcmd_s { char forwardMove; // *2048 for real move. char sideMove; // *2048 for real move. char upMove; // *2048 for real move. unsigned short angle; // <<16 for angle (view angle). short pitch; // View pitch. short actions; // On/off action flags. } ticcmd_t; // Network Player Events enum { DDPE_ARRIVAL, // A player has arrived. DDPE_EXIT, // A player has exited the game. DDPE_CHAT_MESSAGE, // A player has sent a chat message. DDPE_DATA_CHANGE // The data for this player has been changed. }; // World events (handled by clients) enum { DDWE_HANDSHAKE, // Shake hands with a new player. DDWE_PROJECTILE, // Spawn a projectile. DDWE_SECTOR_SOUND, // Play a sector sound. DDWE_DEMO_END // Demo playback ends. }; /* * Do not modify this structure: Servers send it as-is to clients. * Only add elements to the end. */ typedef struct serverinfo_s { int version; char name[64]; char description[80]; int numPlayers, maxPlayers; char canJoin; char address[64]; int port; unsigned short ping; // Milliseconds. char game[32]; // DLL and version. char gameMode[17]; char gameConfig[40]; char map[20]; char clientNames[128]; unsigned int wadNumber; char iwad[32]; char pwads[128]; int data[3]; } serverinfo_t; typedef struct { int num; // How many serverinfo_t's in data? int found; // How many servers were found? serverinfo_t* data; } serverdataquery_t; // For querying the list of available modems. typedef struct { int num; char** list; } modemdataquery_t; // All packet types handled by the game should be >= 64. #define DDPT_HELLO 0 #define DDPT_OK 1 #define DDPT_CANCEL 2 #define DDPT_COMMANDS 32 #define DDPT_FIRST_GAME_EVENT 64 #define DDPT_MESSAGE 67 // SendPacket flags (OR with to_player). #define DDSP_ORDERED 0x20000000 // Confirm delivery in correct order. #define DDSP_CONFIRM 0x40000000 // Confirm delivery. #define DDSP_ALL_PLAYERS 0x80000000 // Broadcast (for server). // World handshake: update headers. A varying number of // data follows, depending on the flags. Notice: must be not // be padded, needs to be byte-aligned. #pragma pack(1) typedef struct { byte flags; unsigned int sector; } packet_sectorupdate_t; typedef struct { byte flags; unsigned int side; } packet_wallupdate_t; #pragma pack() // World handshake flags. Sent by the game server: // Sector update flags. #define DDSU_FLOOR_HEIGHT 0x01 #define DDSU_FLOOR_MOVING 0x02 // Destination and speed sent. #define DDSU_CEILING_HEIGHT 0x04 #define DDSU_CEILING_MOVING 0x08 // Destination and speed. #define DDSU_FLOORPIC 0x10 // Floorpic changed. #define DDSU_CEILINGPIC 0x20 // Ceilingpic changed. #define DDSU_LIGHT_LEVEL 0x40 // Wall update flags. #define DDWU_TOP 0x01 // Top texture. #define DDWU_MID 0x02 // Mid texture. #define DDWU_BOTTOM 0x04 // Bottom texture. // Missile spawn request flags. #define DDMS_FLAG_MASK 0xc000 #define DDMS_MOVEMENT_XY 0x4000 // XY movement included. #define DDMS_MOVEMENT_Z 0x8000 // Z movement included. //------------------------------------------------------------------------ // // Player Data // //------------------------------------------------------------------------ // Built-in control identifiers. enum { CTL_WALK = 1, ///< Forward/backwards. CTL_SIDESTEP = 2, ///< Left/right sideways movement. CTL_ZFLY = 3, ///< Up/down movement. CTL_TURN = 4, ///< Turning horizontally. CTL_LOOK = 5, ///< Turning up and down. CTL_MODIFIER_1 = 6, CTL_MODIFIER_2 = 7, CTL_MODIFIER_3 = 8, CTL_MODIFIER_4 = 9, CTL_FIRST_GAME_CONTROL = 1000 }; typedef enum controltype_e { CTLT_NUMERIC, CTLT_IMPULSE } controltype_t; // Player flags. #define DDPF_FIXANGLES 0x1 // Server: send angle/pitch to client. #define DDPF_FILTER 0x2 // Server: send filter to client. #define DDPF_FIXPOS 0x4 // Server: send coords to client. #define DDPF_DEAD 0x8 // Cl & Sv: player is dead. #define DDPF_CAMERA 0x10 // Player is a cameraman. #define DDPF_LOCAL 0x20 // Player is local (e.g. player zero). #define DDPF_FIXMOM 0x40 // Server: send momentum to client. #define DDPF_NOCLIP 0x80 // Client: don't clip movement. #define DDPF_CHASECAM 0x100 // Chase camera mode (third person view). #define DDPF_INTERYAW 0x200 // Interpolate view yaw angles (used with locking). #define DDPF_INTERPITCH 0x400 // Interpolate view pitch angles (used with locking). #define DDPF_VIEW_FILTER 0x800 // Cl & Sv: Draw the current view filter. #define PLAYERNAMELEN 81 // Normally one for the weapon and one for the muzzle flash. #define DDMAXPSPRITES 2 enum // Psprite states. { DDPSP_BOBBING, DDPSP_FIRE, DDPSP_DOWN, DDPSP_UP }; /** * @defGroup pspriteFlags PSprite Flags */ /*{*/ #define DDPSPF_FULLBRIGHT 0x1 /*}*/ // Player sprites. typedef struct { state_t* statePtr; int tics; float alpha; float pos[2]; byte flags; // @see pspriteFlags int state; float offset[2]; } ddpsprite_t; // Lookdir conversions. #define LOOKDIR2DEG(x) ((x) * 85.0/110.0) #define LOOKDIR2RAD(x) (LOOKDIR2DEG(x)/180*PI) struct mobj_s; struct polyobj_s; typedef struct fixcounters_s { int angles; int pos; int mom; } fixcounters_t; typedef struct ddplayer_s { ticcmd_t cmd; struct mobj_s* mo; // Pointer to a (game specific) mobj. float lookDir; // For mouse look. int fixedColorMap; // Can be set to REDCOLORMAP, etc. int extraLight; // So gun flashes light up areas. int inGame; // Is this player in game? int inVoid; // True if player is in the void // (not entirely accurate so it shouldn't // be used for anything critical). int flags; float filterColor[4]; // RGBA filter for the camera. fixcounters_t fixCounter; fixcounters_t fixAcked; angle_t lastAngle; // For calculating turndeltas. ddpsprite_t pSprites[DDMAXPSPRITES]; // Player sprites. void* extraData; // Pointer to any game-specific data. } ddplayer_t; #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/0000755000175000017500000000000011523516205017313 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/0000755000175000017500000000000011357170242020104 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/sys_dylib.c0000644000175000017500000001145711357170242022261 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2006 Jamie Jones *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_dylib.c: Dynamic Libraries * * These functions provide roughly the same functionality as the ltdl * library. Since the ltdl library appears to be broken on Mac OS X, * these will be used instead when loading plugin libraries. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "m_args.h" #include "sys_dylib.h" #include #include #include #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static filename_t appDir; // CODE -------------------------------------------------------------------- void lt_dlinit(void) { getcwd(appDir, sizeof(appDir)); } void lt_dlexit(void) { } const char *lt_dlerror(void) { return dlerror(); } void lt_dladdsearchdir(const char *searchPath) { } static void getBundlePath(char *path) { if(ArgCheckWith("-libdir", 1)) { strcpy(path, ArgNext()); } else if(ArgCheckWith("-appdir", 1)) { sprintf(path, "%s/%s", appDir, ArgNext()); } else { #ifdef MACOSX // This is the default location where bundles are. sprintf(path, "%s/Bundles", appDir); #endif #ifdef UNIX #ifdef DENG_LIBRARY_DIR strcpy(path, DENG_LIBRARY_DIR); #else // Assume they are in the cwd. strcpy(path, appDir); #endif #endif } } int lt_dlforeachfile(const char *searchPath, int (*func) (const char *fileName, lt_ptr data), lt_ptr data) { DIR *dir = NULL; struct dirent *entry = NULL; filename_t bundlePath; // This is the default location where bundles are. getBundlePath(bundlePath); if(searchPath == NULL) searchPath = bundlePath; dir = opendir(searchPath); while((entry = readdir(dir)) != NULL) { #ifndef MACOSX if(entry->d_type != DT_DIR && !strncmp(entry->d_name, "libdp", 5)) #endif #ifdef MACOSX if(entry->d_type == DT_DIR && !strncmp(entry->d_name, "dp", 2)) #endif { if(func(entry->d_name, data)) break; } } closedir(dir); return 0; } /** * The base file name should have the ".bundle" file name extension. */ lt_dlhandle lt_dlopenext(const char *baseFileName) { lt_dlhandle handle; filename_t bundleName; #ifdef MACOSX char* ptr; #endif getBundlePath(bundleName); #ifdef MACOSX strcat(bundleName, "/"); strcat(bundleName, baseFileName); strcat(bundleName, "/Contents/MacOS/"); #endif strcat(bundleName, baseFileName); //#ifdef UNIX //#ifndef MACOSX // strcat(bundleName, ".so"); //#endif //#endif /* sprintf(bundleName, "Bundles/%s/Contents/MacOS/%s", baseFileName, baseFileName);*/ #ifdef MACOSX // Get rid of the ".bundle" in the end. if((ptr = strrchr(bundleName, '.')) != NULL) *ptr = 0; #endif handle = dlopen(bundleName, RTLD_NOW); if(!handle) { printf("While opening dynamic library\n%s:\n %s\n", bundleName, dlerror()); } return handle; } lt_ptr lt_dlsym(lt_dlhandle module, const char *symbolName) { return dlsym(module, symbolName); } void lt_dlclose(lt_dlhandle module) { if(module) { dlclose(module); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/sys_path.c0000644000175000017500000001121311357170242022100 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_path.c: File Path Processing */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_console.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Removes references to the current (.) and parent (..) directories. * The given path should be an absolute path. */ void DD_ResolvePath(char *path) { char *ch = path; char *end = path + strlen(path); char *prev = path; // Assume an absolute path. for(; *ch; ch++) { if(ch[0] == '/' && ch[1] == '.') { if(ch[2] == '/') { memmove(ch, ch + 2, end - ch - 1); ch--; } else if(ch[2] == '.' && ch[3] == '/') { memmove(prev, ch + 3, end - ch - 2); // Must restart from the beginning. // This is a tad inefficient, though. ch = path - 1; continue; } } if(*ch == '/') prev = ch; } } /** * Convert the given path to an absolute path. */ char *_fullpath(char *full, const char *original, int maxLen) { ddstring_t dir; char workDir[512]; // Fixed-size array... Str_Init(&dir); // \fixme Check for '~'. if(original[0] != '/') // A relative path? { getcwd(workDir, sizeof(workDir)); // \fixme Check for ERANGE. Str_Set(&dir, workDir); Str_Append(&dir, "/"); Str_Append(&dir, original); } else { Str_Set(&dir, original); } // Remove "."s and ".."s. DD_ResolvePath(Str_Text(&dir)); // Clear the given buffer and copy the full path there. memset(full, 0, maxLen); strncpy(full, Str_Text(&dir), maxLen - 1); Str_Free(&dir); return full; } void strzncpy(char *dest, const char *src, int count) { char *out = dest; const char *in = src; while(count-- > 0) { *out++ = *in++; if(!*in) break; } *out = 0; } void _splitpath(const char *path, char *drive, char *dir, char *name, char *ext) { char *lastPeriod, *lastSlash; if(drive) strcpy(drive, ""); // There is never a drive letter. lastPeriod = strrchr(path, '.'); lastSlash = strrchr(path, '/'); if(lastPeriod < lastSlash) lastPeriod = NULL; if(dir) { if(lastSlash) strzncpy(dir, path, lastSlash - path + 1); else strcpy(dir, ""); } // The name should not include the extension. if(name) { if(lastSlash && lastPeriod) strzncpy(name, lastSlash + 1, lastPeriod - lastSlash - 1); else if(lastSlash) strcpy(name, lastSlash + 1); else strzncpy(name, path, lastPeriod - path); } // Last period gives us the extension. if(ext) { if(lastPeriod) strcpy(ext, lastPeriod); else strcpy(ext, ""); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/dd_uinit.c0000644000175000017500000002635311357170242022060 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_uinit.c: Unix Initialization * * Load libraries and set up APIs. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #ifdef UNIX # include "sys_dylib.h" #endif #include "de_base.h" #include "de_graphics.h" #include "de_console.h" #include "de_system.h" #include "de_play.h" #include "de_refresh.h" #include "de_network.h" #include "de_misc.h" #include "dd_uinit.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- uint windowIDX; // Main window. // PRIVATE DATA DEFINITIONS ------------------------------------------------ application_t app; // CODE -------------------------------------------------------------------- static void determineGlobalPaths(application_t *app) { if(!app) return; #ifndef MACOSX if(getenv("HOME")) { filename_t homeDir; sprintf(homeDir, "%s/.deng", getenv("HOME")); M_CheckPath(homeDir); Dir_MakeDir(homeDir, &ddRuntimeDir); app->userDirOk = Dir_ChDir(&ddRuntimeDir); } #endif // The -userdir option sets the working directory. if(ArgCheckWith("-userdir", 1)) { Dir_MakeDir(ArgNext(), &ddRuntimeDir); app->userDirOk = Dir_ChDir(&ddRuntimeDir); } // The current working directory is the runtime dir. Dir_GetDir(&ddRuntimeDir); /** * The base path is always the same and depends on the build * configuration. Usually this is something like * "/usr/share/deng/". */ #ifdef MACOSX strcpy(ddBasePath, "./"); #else strcpy(ddBasePath, DENG_BASE_DIR); #endif if(ArgCheckWith("-basedir", 1)) { strcpy(ddBasePath, ArgNext()); Dir_ValidDir(ddBasePath, FILENAME_T_MAXLEN); } Dir_MakeAbsolute(ddBasePath, FILENAME_T_MAXLEN); Dir_ValidDir(ddBasePath, FILENAME_T_MAXLEN); printf("determineGlobalPaths: Base path = %s\n", ddBasePath); } static boolean loadGamePlugin(application_t *app, const char *libPath) { if(!libPath || !app) return false; // Load the library and get the API/exports. app->hInstGame = lt_dlopenext(libPath); if(!app->hInstGame) { DD_ErrorBox(true, "loadGamePlugin: Loading of %s failed (%s).\n", libPath, lt_dlerror()); return false; } app->GetGameAPI = (GETGAMEAPI) lt_dlsym(app->hInstGame, "GetGameAPI"); if(!app->GetGameAPI) { DD_ErrorBox(true, "loadGamePlugin: Failed to get address of " "GetGameAPI (%s).\n", lt_dlerror()); return false; } // Do the API transfer. DD_InitAPI(); // Everything seems to be working... return true; } static lt_dlhandle *NextPluginHandle(void) { int i; for(i = 0; i < MAX_PLUGS; ++i) { if(!app.hInstPlug[i]) return &app.hInstPlug[i]; } return NULL; } /* #if 0 int LoadPlugin(const char *pluginPath, lt_ptr data) { filename_t name; lt_dlhandle plugin, *handle; void (*initializer)(void); // What is the actual file name? _splitpath(pluginPath, NULL, NULL, name, NULL); printf("LP: %s => %s\n", pluginPath, name); if(!strncmp(name, "libdp", 5)) { #if 0 filename_t fullPath; #ifdef DENG_LIBRARY_DIR sprintf(fullPath, DENG_LIBRARY_DIR "/%s", name); #else strcpy(fullPath, pluginPath); #endif //if(strchr(name, '.')) strcpy(name, pluginPath); else { strcpy(name, pluginPath); strcat(name, ".dylib"); } #endif // Try loading this one as a Doomsday plugin. if(NULL == (plugin = lt_dlopenext(pluginPath))) { printf("LoadPlugin: Failed to open %s!\n", pluginPath); return 0; } if(NULL == (initializer = lt_dlsym(plugin, "DP_Initialize")) || NULL == (handle = NextPluginHandle())) { printf("LoadPlugin: Failed to load %s!\n", pluginPath); lt_dlclose(plugin); return 0; } // This seems to be a Doomsday plugin. *handle = plugin; printf("LoadPlugin: %s\n", pluginPath); initializer(); } return 0; } #endif */ int LoadPlugin(const char *pluginPath, lt_ptr data) { #ifndef MACOSX filename_t name; #endif lt_dlhandle plugin, *handle; void (*initializer)(void); #ifndef MACOSX // What is the actual file name? _splitpath(pluginPath, NULL, NULL, name, NULL); if(!strncmp(name, "libdp", 5)) #endif { // Try loading this one as a Doomsday plugin. if(NULL == (plugin = lt_dlopenext(pluginPath))) return 0; if(NULL == (initializer = lt_dlsym(plugin, "DP_Initialize")) || NULL == (handle = NextPluginHandle())) { printf("LoadPlugin: Failed to load %s!\n", pluginPath); lt_dlclose(plugin); return 0; } // This seems to be a Doomsday plugin. *handle = plugin; printf("LoadPlugin: %s\n", pluginPath); initializer(); } return 0; } /** * Loads all the plugins from the library directory. */ static boolean loadAllPlugins(void) { // Try to load all libraries that begin with libdp. lt_dlforeachfile(NULL, LoadPlugin, NULL); return true; } static int initTimingSystem(void) { // For timing, we use SDL under *nix, so get it initialized. // SDL_Init() returns zero on success. return !SDL_Init(SDL_INIT_TIMER); } static int initPluginSystem(void) { // Initialize libtool's dynamic library routines. lt_dlinit(); #ifdef DENG_LIBRARY_DIR // The default directory is defined in the Makefile. For // instance, "/usr/local/lib". lt_dladdsearchdir(DENG_LIBRARY_DIR); #endif return true; } static int initDGL(void) { return Sys_PreInitGL(); } int main(int argc, char** argv) { char* cmdLine; int i, length; int exitCode = 0; boolean doShutdown = true; char buf[256]; const char* libName = NULL; app.userDirOk = true; // Assemble a command line string. for(i = 0, length = 0; i < argc; ++i) length += strlen(argv[i]) + 1; // Allocate a large enough string. cmdLine = M_Malloc(length); for(i = 0, length = 0; i < argc; ++i) { strcpy(cmdLine + length, argv[i]); if(i < argc - 1) strcat(cmdLine, " "); length += strlen(argv[i]) + 1; } // Prepare the command line arguments. DD_InitCommandLine(cmdLine); M_Free(cmdLine); cmdLine = NULL; // First order of business: are we running in dedicated mode? if(ArgCheck("-dedicated")) isDedicated = true; DD_ComposeMainWindowTitle(buf); // First we need to locate the game lib name among the command line // arguments. DD_CheckArg("-game", &libName); // Was a game library specified? if(!libName) { DD_ErrorBox(true, "loadGamePlugin: No game library was specified.\n"); } else { char libPath[PATH_MAX]; if(!initPluginSystem()) { DD_ErrorBox(true, "Error initializing plugin system."); } // Determine our basedir, and other global paths. determineGlobalPaths(&app); // Compose the full path to the game library. // Under *nix this is handled a bit differently. #ifdef MACOSX strcpy(libPath, libName); #else sprintf(libPath, "lib%s.so", libName); #endif if(!DD_EarlyInit()) { DD_ErrorBox(true, "Error during early init."); } else if(!initTimingSystem()) { DD_ErrorBox(true, "Error initalizing timing system."); } // Load the rendering DLL. else if(!initDGL()) { DD_ErrorBox(true, "Error initializing DGL."); } // Load the game plugin. else if(!loadGamePlugin(&app, libPath)) { DD_ErrorBox(true, "Error loading game library."); } // Load all other plugins that are found. else if(!loadAllPlugins()) { DD_ErrorBox(true, "Error loading plugins."); } // Init memory zone. else if(!Z_Init()) { DD_ErrorBox(true, "Error initializing memory zone."); } else { if(0 == (windowIDX = Sys_CreateWindow(&app, 0, 0, 0, 640, 480, 32, 0, isDedicated, buf, NULL))) { DD_ErrorBox(true, "Error creating main window."); } else if(!Sys_InitGL()) { DD_ErrorBox(true, "Error initializing OpenGL."); } else { // All initialization complete. doShutdown = false; // Append the main window title with the game name and ensure it // is the at the foreground, with focus. DD_ComposeMainWindowTitle(buf); Sys_SetWindowTitle(windowIDX, buf); // \todo Set foreground window and focus. } } } if(!doShutdown) { // Fire up the engine. The game loop will also act as the message pump. exitCode = DD_Main(); } DD_Shutdown(); // Bye! return exitCode; } /** * Shuts down the engine. */ void DD_Shutdown(void) { int i; // Shutdown all subsystems. DD_ShutdownAll(); SDL_Quit(); // Close the dynamic libraries. lt_dlclose(app.hInstGame); app.hInstGame = NULL; for(i = 0; app.hInstPlug[i]; ++i) lt_dlclose(app.hInstPlug[i]); memset(app.hInstPlug, 0, sizeof(app.hInstPlug)); lt_dlexit(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/sys_findfile.c0000644000175000017500000001046711357170242022736 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_findfile.c: Win32-Style File Finding (findfirst/findnext) */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include "../include/sys_findfile.h" #include "../include/sys_path.h" // MACROS ------------------------------------------------------------------ #define FIND_ERROR -1 // TYPES ------------------------------------------------------------------- typedef struct fdata_s { char *pattern; glob_t buf; int pos; } fdata_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Get the info for the next file. */ static int nextfinddata(finddata_t *fd) { fdata_t *data = fd->finddata; char *fn, *last; char ext[256]; struct stat st; if(data->buf.gl_pathc <= data->pos) { // Nothing was found. return FIND_ERROR; } // Nobody needs these... fd->date = 0; fd->time = 0; // Get the size of the file. fn = data->buf.gl_pathv[data->pos]; if(!stat(fn, &st)) fd->size = st.st_size; else fd->size = 0; if(fd->name) free(fd->name); fd->name = malloc(strlen(fn) + 1); // Is it a directory? last = fn + strlen(fn) - 1; if(*last == '/') { // Return the name of the last directory in the path. char *slash = last - 1; int len; while(*slash != '/' && slash > fn) --slash; len = last - slash - 1; strncpy(fd->name, slash + 1, len); fd->name[len] = 0; fd->attrib = A_SUBDIR; } else { _splitpath(fn, NULL, NULL, fd->name, ext); strcat(fd->name, ext); fd->attrib = 0; } // Advance the position. data->pos++; return 0; } /** * @return @c 0, if successful(!). */ int myfindfirst(const char *filename, finddata_t *fd) { fdata_t *data; // Allocate a new glob struct. fd->finddata = data = calloc(1, sizeof(fdata_t)); fd->name = NULL; // Make a copy of the pattern. data->pattern = malloc(strlen(filename) + 1); strcpy(data->pattern, filename); // Do the glob. glob(filename, GLOB_MARK, NULL, &data->buf); return nextfinddata(fd); /* dta->hFile = _findfirst(filename, &dta->data); dta->date = dta->data.time_write; dta->time = dta->data.time_write; dta->size = dta->data.size; dta->name = dta->data.name; dta->attrib = dta->data.attrib; return dta->hFile<0; */ } /** * @return @c 0, if successful(!). */ int myfindnext(finddata_t *fd) { if(!fd->finddata) return FIND_ERROR; return nextfinddata(fd); } void myfindend(finddata_t *fd) { globfree(&((fdata_t *) fd->finddata)->buf); free(((fdata_t *) fd->finddata)->pattern); free(fd->name); free(fd->finddata); fd->finddata = NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/sys_audiod_loader.c0000644000175000017500000001256411357170242023751 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_loader.c: Loader for ds*.so */ // HEADER FILES ------------------------------------------------------------ #include #ifdef UNIX # include "sys_dylib.h" #endif #include "de_console.h" #include "s_main.h" #include "sys_audiod.h" #include "sys_audiod_sfx.h" #include "sys_audiod_mus.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- audiodriver_t audiodExternal; audiointerface_sfx_t audiodExternalISFX; audiointerface_music_t audiodExternalIMusic; audiointerface_cd_t audiodExternalICD; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static lt_dlhandle handle = NULL; // CODE -------------------------------------------------------------------- static void* Imp(const char* fn) { return lt_dlsym(handle, fn); } void Sys_ShutdownAudioDriver(void) { if(!audioDriver) return; if(audioDriver->Shutdown) audioDriver->Shutdown(); if(audioDriver == &audiodExternal) { lt_dlclose(handle); handle = NULL; } } static audiodriver_t* importExternal(void) { audiodriver_t* d = &audiodExternal; // Clear everything. memset(d, 0, sizeof(*d)); d->Init = Imp("DS_Init"); d->Shutdown = Imp("DS_Shutdown"); d->Event = Imp("DS_Event"); // The driver may provide SFX playback functionality. if(Imp("DS_SFX_Init")) { // The driver offers a SFX playback interface. audiointerface_sfx_t* i = &audiodExternalISFX; i->gen.Init = Imp("DS_SFX_Init"); i->gen.Create = Imp("DS_SFX_CreateBuffer"); i->gen.Destroy = Imp("DS_SFX_DestroyBuffer"); i->gen.Load = Imp("DS_SFX_Load"); i->gen.Reset = Imp("DS_SFX_Reset"); i->gen.Play = Imp("DS_SFX_Play"); i->gen.Stop = Imp("DS_SFX_Stop"); i->gen.Refresh = Imp("DS_SFX_Refresh"); i->gen.Set = Imp("DS_SFX_Set"); i->gen.Setv = Imp("DS_SFX_Setv"); i->gen.Listener = Imp("DS_SFX_Listener"); i->gen.Listenerv = Imp("DS_SFX_Listenerv"); i->gen.Getv = Imp("DS_SFX_Getv"); } // The driver may provide music playback functionality. if(Imp("DM_Music_Init")) { // The driver also offers a music playback interface. audiointerface_music_t* i = &audiodExternalIMusic; i->gen.Init = Imp("DM_Music_Init"); i->gen.Update = Imp("DM_Music_Update"); i->gen.Get = Imp("DM_Music_Get"); i->gen.Set = Imp("DM_Music_Set"); i->gen.Pause = Imp("DM_Music_Pause"); i->gen.Stop = Imp("DM_Music_Stop"); i->SongBuffer = Imp("DM_Music_SongBuffer"); i->Play = Imp("DM_Music_Play"); i->PlayFile = Imp("DM_Music_PlayFile"); } if(Imp("DM_CDAudio_Init")) { // The driver also offers a CD audio (redbook) playback interface. audiointerface_cd_t* i = &audiodExternalICD; i->gen.Init = Imp("DM_CDAudio_Init"); i->gen.Update = Imp("DM_CDAudio_Update"); i->gen.Set = Imp("DM_CDAudio_Set"); i->gen.Get = Imp("DM_CDAudio_Get"); i->gen.Pause = Imp("DM_CDAudio_Pause"); i->gen.Stop = Imp("DM_CDAudio_Stop"); i->Play = Imp("DM_CDAudio_Play"); } return d; } /** * Attempt to load the specified audio driver, import the entry points and * add to the available audio drivers. * * @param name Name of the driver to be loaded e.g., "openal". * @return Ptr to the audio driver interface if successful, * else @c NULL. */ audiodriver_t* Sys_LoadAudioDriver(const char* name) { filename_t fn; #ifdef MACOSX sprintf(fn, "ds%s.bundle", name); #else // Compose the name, use the prefix "ds". sprintf(fn, "libds%s", name); strcat(fn, ".so"); #endif if((handle = lt_dlopenext(fn)) == NULL) { Con_Message("Sys_LoadAudioDriver: Loading of %s failed.\n", fn); return NULL; } return importExternal(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/sys_console.c0000644000175000017500000000744311357170242022620 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_console.c: Text-Mode Console * * Standalone console window handling. Used in dedicated mode. * \fixme Some lazy programming in here... */ // HEADER FILES ------------------------------------------------------------ // Without the following, curses.h defines false 0 and true 1 #define NCURSES_ENABLE_STDBOOL_H 0 #include "de_base.h" #include "de_system.h" #include "de_console.h" #include // MACROS ------------------------------------------------------------------ #define LINELEN 256 // \fixme Lazy: This is the max acceptable window width. // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean conInputInited = false; // CODE -------------------------------------------------------------------- void Sys_ConInputInit(void) { if(conInputInited) return; // Already active. conInputInited = true; } void Sys_ConInputShutdown(void) { if(!conInputInited) return; conInputInited = false; } static int translateKey(int key) { if(key >= 32 && key <= 127) return key; //fprintf(outFile, "key=%i\n", key); switch(key) { case '\r': case '\n': case KEY_ENTER: return DDKEY_RETURN; case KEY_BACKSPACE: case KEY_DC: return DDKEY_BACKSPACE; case '\t': return DDKEY_TAB; case KEY_UP: return DDKEY_UPARROW; case KEY_DOWN: return DDKEY_DOWNARROW; default: // Unknown key. return 0; } } /** * Copy n key events from the console and encode them into given buffer. * * @param evbuf Ptr to the buffer to encode events to. * @param bufsize Size of the buffer. * * @return Number of key events written to the buffer. */ size_t I_GetConsoleKeyEvents(keyevent_t *evbuf, size_t bufsize) { int key; byte ddkey; size_t n; if(!conInputInited) return 0; for(n = 0, key = wgetch(theWindow->console.winCommand); key != ERR && n < bufsize; key = wgetch(theWindow->console.winCommand)) { // Use the table to translate the vKey to a DDKEY. ddkey = translateKey(key); evbuf[n].ddkey = ddkey; evbuf[n].event = IKE_KEY_DOWN; n++; // Release immediately. evbuf[n].ddkey = ddkey; evbuf[n].event = IKE_KEY_UP; n++; } return n; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/src/sys_input.c0000644000175000017500000003255711357170242022321 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 2005 Zachary Keene * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_input.c: Keyboard, mouse and joystick input using SDL * \todo - Unify this with Win32. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define EVBUFSIZE 64 #define KEYBUFSIZE 32 #define CONVCONST ((IJOY_AXISMAX - IJOY_AXISMIN) / 65535.0) // TYPES ------------------------------------------------------------------- typedef struct clicker_s { int down; // Count for down events. int up; // Count for up events. } clicker_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int novideo; // PUBLIC DATA DEFINITIONS ------------------------------------------------- int joydevice = 0; // Joystick index to use. byte usejoystick = false; // Joystick input enabled? // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean initIOk; static byte useMouse, useJoystick; static keyevent_t keyEvents[EVBUFSIZE]; static int evHead, evTail; static clicker_t mouseClickers[IMB_MAXBUTTONS]; static clicker_t joyClickers[IJOY_MAXBUTTONS]; static boolean gotFirstMouseMove = false; static SDL_Joystick *joy; // CODE -------------------------------------------------------------------- void I_Register(void) { C_VAR_INT("input-joy-device", &joydevice, CVF_NO_MAX | CVF_PROTECTED, 0, 0); C_VAR_BYTE("input-joy", &usejoystick, 0, 0, 1); } /** * @return A new key event struct from the buffer. */ keyevent_t *I_NewKeyEvent(void) { keyevent_t *ev = keyEvents + evHead; evHead = (evHead + 1) % EVBUFSIZE; memset(ev, 0, sizeof(*ev)); return ev; } /** * @return The oldest event from the buffer. */ keyevent_t *I_GetKeyEvent(void) { keyevent_t *ev; if(evHead == evTail) return NULL; // No more... ev = keyEvents + evTail; evTail = (evTail + 1) % EVBUFSIZE; return ev; } /** * Translate the SDL symbolic key code to a DDKEY. * \fixme A translation array for these? */ int I_TranslateKeyCode(SDLKey sym) { switch(sym) { case 167: // Tilde return 96; // ASCII: '`' case '\b': // Backspace return DDKEY_BACKSPACE; case SDLK_PAUSE: return DDKEY_PAUSE; case SDLK_UP: return DDKEY_UPARROW; case SDLK_DOWN: return DDKEY_DOWNARROW; case SDLK_LEFT: return DDKEY_LEFTARROW; case SDLK_RIGHT: return DDKEY_RIGHTARROW; case SDLK_RSHIFT: case SDLK_LSHIFT: return DDKEY_RSHIFT; case SDLK_RALT: case SDLK_LALT: return DDKEY_RALT; case SDLK_RCTRL: case SDLK_LCTRL: return DDKEY_RCTRL; case SDLK_F1: return DDKEY_F1; case SDLK_F2: return DDKEY_F2; case SDLK_F3: return DDKEY_F3; case SDLK_F4: return DDKEY_F4; case SDLK_F5: return DDKEY_F5; case SDLK_F6: return DDKEY_F6; case SDLK_F7: return DDKEY_F7; case SDLK_F8: return DDKEY_F8; case SDLK_F9: return DDKEY_F9; case SDLK_F10: return DDKEY_F10; case SDLK_F11: return DDKEY_F11; case SDLK_F12: return DDKEY_F12; case SDLK_NUMLOCK: return DDKEY_NUMLOCK; case SDLK_SCROLLOCK: return DDKEY_SCROLL; case SDLK_KP0: return DDKEY_NUMPAD0; case SDLK_KP1: return DDKEY_NUMPAD1; case SDLK_KP2: return DDKEY_NUMPAD2; case SDLK_KP3: return DDKEY_NUMPAD3; case SDLK_KP4: return DDKEY_NUMPAD4; case SDLK_KP5: return DDKEY_NUMPAD5; case SDLK_KP6: return DDKEY_NUMPAD6; case SDLK_KP7: return DDKEY_NUMPAD7; case SDLK_KP8: return DDKEY_NUMPAD8; case SDLK_KP9: return DDKEY_NUMPAD9; case SDLK_KP_PERIOD: return DDKEY_DECIMAL; case SDLK_KP_PLUS: return DDKEY_ADD; case SDLK_KP_MINUS: return DDKEY_SUBTRACT; case SDLK_KP_DIVIDE: return '/'; case SDLK_KP_MULTIPLY: return '*'; case SDLK_KP_ENTER: return DDKEY_RETURN; case SDLK_INSERT: return DDKEY_INS; case SDLK_DELETE: return DDKEY_DEL; case SDLK_HOME: return DDKEY_HOME; case SDLK_END: return DDKEY_END; case SDLK_PAGEUP: return DDKEY_PGUP; case SDLK_PAGEDOWN: return DDKEY_PGDN; default: break; } return sym; } /** * SDL's events are all returned from the same routine. This function * is called periodically, and the events we are interested in a saved * into our own buffer. */ void I_PollEvents(void) { SDL_Event event; keyevent_t *e; while(SDL_PollEvent(&event)) { switch(event.type) { case SDL_KEYDOWN: case SDL_KEYUP: e = I_NewKeyEvent(); e->event = (event.type == SDL_KEYDOWN ? IKE_KEY_DOWN : IKE_KEY_UP); e->ddkey = I_TranslateKeyCode(event.key.keysym.sym); /*printf("sdl:%i ddkey:%i\n", event.key.keysym.scancode, e->ddkey);*/ break; case SDL_MOUSEBUTTONDOWN: mouseClickers[MIN_OF(event.button.button - 1, IMB_MAXBUTTONS - 1)].down++; break; case SDL_MOUSEBUTTONUP: mouseClickers[MIN_OF(event.button.button - 1, IMB_MAXBUTTONS - 1)].up++; break; case SDL_JOYBUTTONDOWN: joyClickers[MIN_OF(event.jbutton.button, IJOY_MAXBUTTONS - 1)].down++; break; case SDL_JOYBUTTONUP: joyClickers[MIN_OF(event.jbutton.button, IJOY_MAXBUTTONS - 1)].up++; break; case SDL_QUIT: // The system wishes to close the program immediately... Sys_Quit(); break; default: // The rest of the events are ignored. break; } } } void I_InitMouse(void) { if(ArgCheck("-nomouse") || novideo) return; // Init was successful. useMouse = true; gotFirstMouseMove = false; // Grab all input. SDL_WM_GrabInput(SDL_GRAB_ON); } void I_InitJoystick(void) { int joycount; if(ArgCheck("-nojoy")) return; if((joycount = SDL_NumJoysticks()) > 0) { if(joydevice > joycount) { Con_Message("I_InitJoystick: joydevice = %i, out of range.\n", joydevice); joy = SDL_JoystickOpen(0); } else joy = SDL_JoystickOpen(joydevice); } if(joy) { // Show some info. Con_Message("I_InitJoystick: %s\n", SDL_JoystickName(SDL_JoystickIndex(joy))); // We'll handle joystick events manually SDL_JoystickEventState(SDL_ENABLE); if(verbose) { Con_Message("I_InitJoystick: Joystick reports %i axes, %i buttons, %i hats, " "and %i trackballs.\n", SDL_JoystickNumAxes(joy), SDL_JoystickNumButtons(joy), SDL_JoystickNumHats(joy), SDL_JoystickNumBalls(joy)); } useJoystick = true; } else { Con_Message("I_InitJoystick: No joysticks found\n"); useJoystick = false; } } /** * Initialize input. * * @return @c true, if successful. */ boolean I_Init(void) { if(initIOk) return true; // Already initialized. I_InitMouse(); I_InitJoystick(); initIOk = true; return true; } void I_Shutdown(void) { if(!initIOk) return; // Not initialized. if (joy) SDL_JoystickClose(joy); initIOk = false; } boolean I_MousePresent(void) { return useMouse; } boolean I_JoystickPresent(void) { return useJoystick; } size_t I_GetKeyEvents(keyevent_t *evbuf, size_t bufsize) { keyevent_t *e; size_t i = 0; if(!initIOk) return 0; // Get new events from SDL. I_PollEvents(); // Get the events. for(i = 0; i < bufsize; ++i) { e = I_GetKeyEvent(); if(!e) break; // No more events. memcpy(&evbuf[i], e, sizeof(*e)); } return i; } void I_GetMouseState(mousestate_t *state) { Uint8 buttons; int i; memset(state, 0, sizeof(*state)); // Has the mouse been initialized? if(!I_MousePresent() || !initIOk) return; buttons = SDL_GetRelativeMouseState(&state->x, &state->y); // Ignore the first nonzero offset, it appears it's a nasty jump. if(!gotFirstMouseMove && (state->x || state->y)) { gotFirstMouseMove = true; state->x = state->y = 0; } for(i = 0; i < IMB_MAXBUTTONS; ++i) { state->buttonDowns[i] = mouseClickers[i].down; state->buttonUps[i] = mouseClickers[i].up; // Reset counters. mouseClickers[i].down = mouseClickers[i].up = 0; } } void I_GetJoystickState(joystate_t *state) { int i, pov; memset(state, 0, sizeof(*state)); // Initialization has not been done. if(!I_JoystickPresent() || !usejoystick || !initIOk) return; // Update joysticks SDL_JoystickUpdate(); // What do we have available to us? state->numAxes = MIN_OF( SDL_JoystickNumAxes(joy), IJOY_MAXAXES ); state->numButtons = MIN_OF( SDL_JoystickNumButtons(joy), IJOY_MAXBUTTONS ); state->numHats = MIN_OF( SDL_JoystickNumHats(joy), IJOY_MAXHATS ); for(i = 0; i < state->numAxes; ++i) { int value = SDL_JoystickGetAxis(joy, i); // SDL returns a value between -32768 and 32767, but Doomsday is expecting // -10000 to 10000. We'll convert as we go. value = ((value + 32768) * CONVCONST) + IJOY_AXISMIN; state->axis[i] = value; } for(i = 0; i < state->numButtons; ++i) { state->buttonDowns[i] = joyClickers[i].down; state->buttonUps[i] = joyClickers[i].up; // Reset counters. joyClickers[i].down = joyClickers[i].up = 0; } for(i = 0; i < state->numHats; ++i) { pov = SDL_JoystickGetHat(joy, i); /* { // Debug: Simulating the hat with buttons 1-4. int buts[4] = { SDL_JoystickGetButton(joy, 0), SDL_JoystickGetButton(joy, 1), SDL_JoystickGetButton(joy, 2), SDL_JoystickGetButton(joy, 3) }; pov = SDL_HAT_CENTERED; if(buts[0] && !buts[1] && !buts[3]) pov = SDL_HAT_UP; else if(buts[0] && buts[1]) pov = SDL_HAT_RIGHTUP; else if(buts[1] && !buts[2]) pov = SDL_HAT_RIGHT; else if(buts[1] && buts[2]) pov = SDL_HAT_RIGHTDOWN; else if(buts[2] && !buts[3]) pov = SDL_HAT_DOWN; else if(buts[2] && buts[3]) pov = SDL_HAT_LEFTDOWN; else if(buts[3] && !buts[0]) pov = SDL_HAT_LEFT; else if(buts[3] && buts[0]) pov = SDL_HAT_LEFTUP; } */ switch(pov) { case SDL_HAT_UP: state->hatAngle[i] = 0; break; case SDL_HAT_RIGHT: state->hatAngle[i] = 90; break; case SDL_HAT_DOWN: state->hatAngle[i] = 180; break; case SDL_HAT_LEFT: state->hatAngle[i] = 270; break; case SDL_HAT_RIGHTUP: state->hatAngle[i] = 45; break; case SDL_HAT_RIGHTDOWN: state->hatAngle[i] = 135; break; case SDL_HAT_LEFTUP: state->hatAngle[i] = 315; break; case SDL_HAT_LEFTDOWN: state->hatAngle[i] = 225; break; default: state->hatAngle[i] = IJOY_POV_CENTER; } } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/include/0000755000175000017500000000000011523516205020736 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/include/dd_uinit.h0000644000175000017500000000271311357170242022713 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_uinit.h: Unix Initialization. */ #ifndef __DOOMSDAY_UINIT_H__ #define __DOOMSDAY_UINIT_H__ #include "dd_pinit.h" #include "sys_dylib.h" typedef struct { boolean userDirOk; lt_dlhandle hInstGame; // Instance handle to the game library. lt_dlhandle hInstPlug[MAX_PLUGS]; // Instance handle to all other libs. GETGAMEAPI GetGameAPI; } application_t; extern uint windowIDX; // Main window. extern application_t app; void DD_Shutdown(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/include/sys_dylib.h0000644000175000017500000000346611357170242023123 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_dylib.h: Dynamic Libraries * * These functions provide roughly the same functionality as the ltdl * library. Since the ltdl library appears to be broken on Mac OS X, * these will be used instead when loading plugin libraries. */ #ifndef __DOOMSDAY_SYSTEM_DYNAMIC_LIBRARY_H__ #define __DOOMSDAY_SYSTEM_DYNAMIC_LIBRARY_H__ typedef void* lt_dlhandle; typedef void* lt_ptr; void lt_dlinit(void); void lt_dlexit(void); const char *lt_dlerror(void); void lt_dladdsearchdir(const char *searchPath); int lt_dlforeachfile(const char *searchPath, int (*func) (const char *fileName, lt_ptr data), lt_ptr data); lt_dlhandle lt_dlopenext(const char *baseFileName); void *lt_dlsym(lt_dlhandle module, const char *symbolName); void lt_dlclose(lt_dlhandle module); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/include/sys_path.h0000644000175000017500000000245011357170242022744 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_path.h: File Path Processing */ #ifndef __DOOMSDAY_PATHS_H__ #define __DOOMSDAY_PATHS_H__ char *_fullpath(char *full, const char *original, int len); void _splitpath(const char *path, char *drive, char *dir, char *name, char *ext); #endif // __DOOMSDAY_PATHS_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/unix/include/sys_findfile.h0000644000175000017500000000313711357170242023573 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_findfile.h: Win32-Style File Finding */ #ifndef __DOOMSDAY_FILE_FIND_H__ #define __DOOMSDAY_FILE_FIND_H__ // File attributes. #define A_SUBDIR 0x1 #define A_RDONLY 0x2 #define A_HIDDEN 0x4 #define A_ARCH 0x8 typedef struct finddata_s { void *finddata; long date; long time; long size; char *name; long attrib; } finddata_t; /* * The functions return zero if successful. */ int myfindfirst(const char *filename, finddata_t * dta); int myfindnext(finddata_t * dta); void myfindend(finddata_t * dta); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/0000755000175000017500000000000011357170242017274 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/res/0000755000175000017500000000000011523516205020063 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/res/doomsday.rc0000644000175000017500000001110311357170242022226 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomsday.rc: Doomsday.exe resource script. */ #include "../../win32/include/resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../../portable/include/dd_version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../../portable/include/dd_version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""../../win32/res/doomsday.exe.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION DOOMSDAY_VERSION_NUMBER\r\n" "PRODUCTVERSION DOOMSDAY_VERSION_NUMBER\r\n" "# if defined(_DEBUG)\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# elif defined(DOOMSDAY_RELEASE_FULL)\r\n" "FILEFLAGSMASK VS_FF_SPECIALBUILD\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_APP\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", ""Doomsday Engine\0""\r\n" " VALUE ""FileVersion"", DOOMSDAY_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", ""Doomsday Engine\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""Doomsday.exe\0""\r\n" " VALUE ""ProductName"", ""Doomsday Engine\0""\r\n" " VALUE ""ProductVersion"", DOOMSDAY_VERSION_TEXT ""\0""\r\n" "#if !defined(_DEBUG) && !defined(DOOMSDAY_RELEASE_FULL)\r\n" " VALUE ""SpecialBuild"", DOOMSDAY_RELEASE_NAME ""\0""\r\n" "#endif\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif /** * Icons: * Icon with lowest ID value placed first to ensure application icon * remains consistent on all systems. */ IDI_GAME_ICON ICON DISCARDABLE "../../win32/res/doomsday.ico" #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION DOOMSDAY_VERSION_NUMBER PRODUCTVERSION DOOMSDAY_VERSION_NUMBER # if defined(_DEBUG) FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # elif !defined(DOOMSDAY_RELEASE_FULL) FILEFLAGSMASK VS_FF_SPECIALBUILD # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", "Doomsday Engine\0" VALUE "FileVersion", DOOMSDAY_VERSION_TEXT "\0" VALUE "InternalName", "Doomsday Engine\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "Doomsday.exe\0" VALUE "ProductName", "Doomsday Engine\0" VALUE "ProductVersion", DOOMSDAY_VERSION_TEXT "\0" #if !defined(_DEBUG) && !defined(DOOMSDAY_RELEASE_FULL) VALUE "SpecialBuild", DOOMSDAY_RELEASE_NAME "\0" #endif END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/res/doomsday.exe.manifest0000644000175000017500000000062611357170242024220 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/res/doomsday.ico0000644000175000017500000000427611357170242022411 0ustar keeskees ( @ʦ """)))UUUMMMBBB999|PP3f3333f333ff3fffff3f3f̙f3333f3333333333f3333333f3f33ff3f3f3f3333f3333333f3̙33333f333ff3ffffff3f33f3ff3f3f3ffff3fffffffff3fffffff3f̙ffff3ff333f3ff33fff33f3ff̙3f3f3333f333ff3fffff̙̙3̙f̙̙̙3f̙3f3f3333f333ff3fffff3f3f̙3ffffffffff!___www K JJKJ XDJKJC XQJKKKJ XRRKKKKKJ XKKRQKKJDJC XKtKRXJKKKJJ XJKKKKXRKJKKJJ XJKKKtKQXQKKKKKJ XDRJKRKLRXXKKDKK XJKJKKJKKKQXRLJJ XJDJKJKKKJKtXDJ t"CJCJKJKKKK "R CJJCJJDJJJCK "R" 7KQJDJJKKzKK L t *)CCJKzJK L__ L"J+CDJSJK K___FC ><__D" >___<_=<<<<$ =<<<<<<<<<__< =<<<<<<<<<<_< > >< << deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/src/0000755000175000017500000000000011357170242020063 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/src/dd_winit.c0000644000175000017500000003322311357170242022033 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_winit.h: Win32 Initialization * * Create windows, load DLLs, setup APIs. */ // HEADER FILES ------------------------------------------------------------ #define WIN32_LEAN_AND_MEAN #define _WIN32_DCOM #define STRICT #include #include #include #include #include #include #include "resource.h" #include "de_base.h" #include "de_graphics.h" #include "de_console.h" #include "de_system.h" #include "de_play.h" #include "de_refresh.h" #include "de_network.h" #include "de_misc.h" #include "de_ui.h" #include "dd_winit.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- uint windowIDX = 0; // Main window. // PRIVATE DATA DEFINITIONS ------------------------------------------------ application_t app; // CODE -------------------------------------------------------------------- BOOL InitApplication(application_t *app) { WNDCLASSEX wcex; if(GetClassInfoEx(app->hInstance, app->className, &wcex)) return TRUE; // Already registered a window class. // Initialize a window class for our window. ZeroMemory(&wcex, sizeof(wcex)); wcex.cbSize = sizeof(wcex); wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; wcex.lpfnWndProc = (WNDPROC) WndProc; wcex.hInstance = app->hInstance; wcex.hIcon = (HICON) LoadImage(app->hInstance, MAKEINTRESOURCE(IDI_DOOMSDAY_ICON), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE); wcex.hIconSm = (HICON) LoadImage(app->hInstance, MAKEINTRESOURCE(IDI_DOOMSDAY_ICON), IMAGE_ICON, 16, 16, 0); wcex.hCursor = LoadCursor(app->hInstance, IDC_ARROW); wcex.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH); wcex.lpszClassName = app->className; wcex.lpszMenuName = NULL; // Register our window class. return RegisterClassEx(&wcex); } static void determineGlobalPaths(application_t *app) { if(!app) return; // Where are we? #if defined(DENG_LIBRARY_DIR) # if !defined(_DEBUG) #pragma message("!!!WARNING: DENG_LIBRARY_DIR defined in non-debug build!!!") # endif #endif #if defined(DENG_LIBRARY_DIR) _snprintf(ddBinDir.path, 254, "%s", DENG_LIBRARY_DIR); if(ddBinDir.path[strlen(ddBinDir.path)] != '\\') sprintf(ddBinDir.path, "%s\\", ddBinDir.path); Dir_MakeAbsolute(ddBinDir.path); ddBinDir.drive = toupper(ddBinDir.path[0]) - 'A' + 1; #else { char path[256]; GetModuleFileName(app->hInstance, path, 255); Dir_FileDir(path, &ddBinDir); } #endif // The -userdir option sets the working directory. if(ArgCheckWith("-userdir", 1)) { Dir_MakeDir(ArgNext(), &ddRuntimeDir); app->userDirOk = Dir_ChDir(&ddRuntimeDir); } // The current working directory is the runtime dir. Dir_GetDir(&ddRuntimeDir); // The standard base directory is two levels upwards. if(ArgCheck("-stdbasedir")) { strncpy(ddBasePath, "..\\..\\", FILENAME_T_MAXLEN); } if(ArgCheckWith("-basedir", 1)) { strncpy(ddBasePath, ArgNext(), FILENAME_T_MAXLEN); Dir_ValidDir(ddBasePath, FILENAME_T_MAXLEN); } Dir_MakeAbsolute(ddBasePath, FILENAME_T_MAXLEN); Dir_ValidDir(ddBasePath, FILENAME_T_MAXLEN); } static boolean loadGamePlugin(application_t *app, const char *libPath) { if(!libPath || !app) return false; // Now, load the library and get the API/exports. app->hInstGame = LoadLibrary(libPath); if(!app->hInstGame) { DD_ErrorBox(true, "loadGamePlugin: Loading of %s failed (error %i).\n", libPath, (int) GetLastError()); return false; } // Get the function. app->GetGameAPI = (GETGAMEAPI) GetProcAddress(app->hInstGame, "GetGameAPI"); if(!app->GetGameAPI) { DD_ErrorBox(true, "loadGamePlugin: Failed to get address of " "GetGameAPI (error %i).\n", (int) GetLastError()); return false; } // Do the API transfer. DD_InitAPI(); // Everything seems to be working... return true; } /** * Loads the given plugin. * * @return @c true, if the plugin was loaded succesfully. */ static int loadPlugin(application_t *app, const char *filename) { int i; // Find the first empty plugin instance. for(i = 0; app->hInstPlug[i]; ++i); // Try to load it. if(!(app->hInstPlug[i] = LoadLibrary(filename))) return FALSE; // Failed! // That was all; the plugin registered itself when it was loaded. return TRUE; } /** * Loads all the plugins from the startup directory. */ static int loadAllPlugins(application_t *app) { long hFile; struct _finddata_t fd; char plugfn[256]; sprintf(plugfn, "%sdp*.dll", ddBinDir.path); if((hFile = _findfirst(plugfn, &fd)) == -1L) return TRUE; do loadPlugin(app, fd.name); while(!_findnext(hFile, &fd)); return TRUE; } static int initTimingSystem(void) { // Nothing to do. return TRUE; } static int initPluginSystem(void) { // Nothing to do. return TRUE; } static int initDGL(void) { return Sys_PreInitGL(); } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { BOOL doShutdown = TRUE; int exitCode = 0; int lnCmdShow = nCmdShow; memset(&app, 0, sizeof(app)); app.hInstance = hInstance; app.className = TEXT(MAINWCLASS); app.userDirOk = true; if(!InitApplication(&app)) { DD_ErrorBox(true, "Couldn't initialize application."); } else { char buf[256]; const char* libName = NULL; // Initialize COM. CoInitialize(NULL); // Prepare the command line arguments. DD_InitCommandLine(GetCommandLine()); // First order of business: are we running in dedicated mode? if(ArgCheck("-dedicated")) isDedicated = true; DD_ComposeMainWindowTitle(buf); // First we need to locate the game lib name among the command line // arguments. DD_CheckArg("-game", &libName); // Was a game library specified? if(!libName) { DD_ErrorBox(true, "loadGamePlugin: No game library was specified.\n"); } else { char libPath[256]; // Determine our basedir and other global paths. determineGlobalPaths(&app); // Compose the full path to the game library. _snprintf(libPath, 255, "%s%s", ddBinDir.path, libName); if(!DD_EarlyInit()) { DD_ErrorBox(true, "Error during early init."); } else if(!initTimingSystem()) { DD_ErrorBox(true, "Error initalizing timing system."); } else if(!initPluginSystem()) { DD_ErrorBox(true, "Error initializing plugin system."); } else if(!initDGL()) { DD_ErrorBox(true, "Error initializing DGL."); } // Load the game plugin. else if(!loadGamePlugin(&app, libPath)) { DD_ErrorBox(true, "Error loading game library."); } // Load all other plugins that are found. else if(!loadAllPlugins(&app)) { DD_ErrorBox(true, "Error loading plugins."); } // Initialize the memory zone. else if(!Z_Init()) { DD_ErrorBox(true, "Error initializing memory zone."); } else { if(0 == (windowIDX = Sys_CreateWindow(&app, 0, 0, 0, 640, 480, 32, 0, (isDedicated ? WT_CONSOLE : WT_NORMAL), buf, &lnCmdShow))) { DD_ErrorBox(true, "Error creating main window."); } else if(!Sys_InitGL()) { DD_ErrorBox(true, "Error initializing OpenGL."); } else { // All initialization complete. doShutdown = FALSE; // Append the main window title with the game name and ensure it // is the at the foreground, with focus. DD_ComposeMainWindowTitle(buf); Sys_SetWindowTitle(windowIDX, buf); // SetForegroundWindow(win->hWnd); // SetFocus(win->hWnd); } } } } if(!doShutdown) { // Fire up the engine. The game loop will also act as the message pump. exitCode = DD_Main(); } DD_Shutdown(); // No more use of COM beyond this point. CoUninitialize(); // Unregister our window class. UnregisterClass(app.className, app.hInstance); // Bye! return exitCode; } /** * All messages go to the default window message processor. */ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { BOOL forwardMsg = true; LRESULT result = 0; static PAINTSTRUCT ps; switch(msg) { case WM_SIZE: if(!appShutdown) { switch(wParam) { case SIZE_MAXIMIZED: Sys_SetWindow(windowIDX, 0, 0, 0, 0, 0, DDWF_FULLSCREEN, DDSW_NOBPP|DDSW_NOSIZE|DDSW_NOMOVE|DDSW_NOCENTER); forwardMsg = FALSE; break; default: break; } } break; case WM_NCLBUTTONDOWN: switch(wParam) { case HTMINBUTTON: ShowWindow(hWnd, SW_MINIMIZE); break; case HTCLOSE: PostQuitMessage(0); return 0; default: break; } // Un-acquire device when entering menu or re-sizing the mouse // cursor again. //g_bActive = FALSE; //SetAcquire(); break; case WM_CLOSE: PostQuitMessage(0); ignoreInput = TRUE; forwardMsg = FALSE; break; case WM_PAINT: if(BeginPaint(hWnd, &ps)) EndPaint(hWnd, &ps); forwardMsg = FALSE; break; case WM_KEYDOWN: forwardMsg = FALSE; break; case WM_KEYUP: forwardMsg = FALSE; break; case WM_SYSKEYDOWN: forwardMsg = TRUE; break; case WM_SYSKEYUP: forwardMsg = TRUE; break; case WM_HOTKEY: // A hot-key combination we have registered has been used. // Used to override alt+return and other easily misshit combinations, // at the user's request. forwardMsg = FALSE; break; case WM_SYSCOMMAND: switch(wParam) { case SC_SCREENSAVE: // Screensaver about to begin. case SC_MONITORPOWER: // Monitor trying to enter power save. forwardMsg = FALSE; break; default: break; } break; case WM_ACTIVATE: if(!appShutdown) { if(LOWORD(wParam) == WA_ACTIVE || (!HIWORD(wParam) && LOWORD(wParam) == WA_CLICKACTIVE)) { SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS); DD_ClearEvents(); // For good measure. ignoreInput = FALSE; } else { SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS); ignoreInput = TRUE; } } forwardMsg = FALSE; break; default: break; } if(forwardMsg) return DefWindowProc(hWnd, msg, wParam, lParam); return result; } /** * Shuts down the engine. */ void DD_Shutdown(void) { int i; // Shutdown all subsystems. DD_ShutdownAll(); FreeLibrary(app.hInstGame); for(i = 0; app.hInstPlug[i]; ++i) FreeLibrary(app.hInstPlug[i]); app.hInstGame = NULL; memset(app.hInstPlug, 0, sizeof(app.hInstPlug)); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/src/sys_window.c0000644000175000017500000012026711357170242022444 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_window.c: Win32-specific window management. * * This code wraps system-specific window management routines in order to * provide a cross-platform interface and common behavior. * The availabilty of features and behavioral traits can be queried for. */ // HEADER FILES ------------------------------------------------------------ #define WIN32_LEAN_AND_MEAN #define STRICT #include #include #include #include #include #include #include "de_base.h" #include "de_graphics.h" #include "de_console.h" #include "de_system.h" #include "de_refresh.h" #include "de_misc.h" #include "de_ui.h" // MACROS ------------------------------------------------------------------ #define WINDOWEDSTYLE (WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | \ WS_CLIPCHILDREN | WS_CLIPSIBLINGS) #define FULLSCREENSTYLE (WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS) #define LINELEN 80 #define TEXT_ATTRIB (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE) #define CMDLINE_ATTRIB (FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void destroyWindow(ddwindow_t *win); static boolean setDDWindow(ddwindow_t *win, int newX, int newY, int newWidth, int newHeight, int newBPP, int wFlags, int uFlags); static void setConWindowCmdLine(ddwindow_t *win, const char *text, uint cursorPos, int flags); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Currently active window where all drawing operations are directed at. const ddwindow_t* theWindow; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean winManagerInited = false; static uint numWindows = 0; static ddwindow_t **windows = NULL; static int screenWidth, screenHeight, screenBPP; // CODE -------------------------------------------------------------------- static __inline ddwindow_t *getWindow(uint idx) { if(!winManagerInited) return NULL; // Window manager is not initialized. if(idx >= numWindows) return NULL; return windows[idx]; } static void setCmdLineCursor(ddwindow_t *win, int x, int y) { COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(win->console.hcScreen, pos); } static void scrollLine(ddwindow_t *win) { SMALL_RECT src; COORD dest; CHAR_INFO fill; src.Left = 0; src.Right = win->console.cbInfo.dwSize.X - 1; src.Top = 1; src.Bottom = win->console.cbInfo.dwSize.Y - 2; dest.X = 0; dest.Y = 0; fill.Attributes = TEXT_ATTRIB; fill.Char.AsciiChar = ' '; ScrollConsoleScreenBuffer(win->console.hcScreen, &src, NULL, dest, &fill); } static void setAttrib(ddwindow_t *win, int flags) { win->console.attrib = 0; if(flags & CBLF_WHITE) win->console.attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; if(flags & CBLF_BLUE) win->console.attrib = FOREGROUND_BLUE; if(flags & CBLF_GREEN) win->console.attrib = FOREGROUND_GREEN; if(flags & CBLF_CYAN) win->console.attrib = FOREGROUND_BLUE | FOREGROUND_GREEN; if(flags & CBLF_RED) win->console.attrib = FOREGROUND_RED; if(flags & CBLF_MAGENTA) win->console.attrib = FOREGROUND_RED | FOREGROUND_BLUE; if(flags & CBLF_YELLOW) win->console.attrib = FOREGROUND_RED | FOREGROUND_GREEN; if(flags & CBLF_LIGHT) win->console.attrib |= FOREGROUND_INTENSITY; if((flags & CBLF_WHITE) != CBLF_WHITE) win->console.attrib |= FOREGROUND_INTENSITY; SetConsoleTextAttribute(win->console.hcScreen, win->console.attrib); } /** * Writes the text at the (cx,cy). */ static void writeText(ddwindow_t *win, CHAR_INFO *line, int len) { COORD linesize; COORD from = {0, 0}; SMALL_RECT rect; linesize.X = len; linesize.Y = 1; rect.Left = win->console.cx; rect.Right = win->console.cx + len; rect.Top = win->console.cy; rect.Bottom = win->console.cy; WriteConsoleOutput(win->console.hcScreen, line, linesize, from, &rect); } void Sys_ConPrint(uint idx, const char *text, int clflags) { ddwindow_t *win; unsigned int i; int linestart, bpos; const char *ptr = text; char ch; size_t len; CHAR_INFO line[LINELEN]; if(!winManagerInited) return; win = getWindow(idx - 1); if(!win || win->type != WT_CONSOLE) return; if(win->console.needNewLine) { // Need to make some room. win->console.cx = 0; win->console.cy++; if(win->console.cy == win->console.cbInfo.dwSize.Y - 1) { win->console.cy--; scrollLine(win); } win->console.needNewLine = false; } bpos = linestart = win->console.cx; setAttrib(win, clflags); len = strlen(text); for(i = 0; i < len; i++, ptr++) { ch = *ptr; if(ch != '\n' && bpos < LINELEN) { line[bpos].Attributes = win->console.attrib; line[bpos].Char.AsciiChar = ch; bpos++; } // Time for newline? if(ch == '\n' || bpos == LINELEN) { writeText(win, line + linestart, bpos - linestart); win->console.cx += bpos - linestart; bpos = 0; linestart = 0; if(i < len - 1) { // Not the last character. win->console.needNewLine = false; win->console.cx = 0; win->console.cy++; if(win->console.cy == win->console.cbInfo.dwSize.Y - 1) { scrollLine(win); win->console.cy--; } } else { win->console.needNewLine = true; } } } // Something left in the buffer? if(bpos - linestart) { writeText(win, line + linestart, bpos - linestart); win->console.cx += bpos - linestart; } } /** * Set the command line display of the specified console window. * * @param idx Console window identifier. * @param text Text string to copy. * @param cursorPos Position to set the cursor on the command line. * @param flags CLF_* flags control the appearance of the * command line. */ void Sys_SetConWindowCmdLine(uint idx, const char *text, uint cursorPos, int flags) { ddwindow_t *win; if(!winManagerInited) return; win = getWindow(idx - 1); if(!win || win->type != WT_CONSOLE) return; setConWindowCmdLine(win, text, cursorPos, flags); } static void setConWindowCmdLine(ddwindow_t *win, const char *text, uint cursorPos, int flags) { CHAR_INFO line[LINELEN], *ch; uint i; COORD linesize = {LINELEN, 1}; COORD from = {0, 0}; SMALL_RECT rect; // Do we need to change the look of the cursor? if((flags & CLF_CURSOR_LARGE) != (win->console.cmdline.flags & CLF_CURSOR_LARGE)) { CONSOLE_CURSOR_INFO curInfo; curInfo.bVisible = TRUE; curInfo.dwSize = ((flags & CLF_CURSOR_LARGE)? 100 : 10); SetConsoleCursorInfo(win->console.hcScreen, &curInfo); win->console.cmdline.flags ^= CLF_CURSOR_LARGE; } line[0].Char.AsciiChar = '>'; line[0].Attributes = CMDLINE_ATTRIB; for(i = 0, ch = line + 1; i < LINELEN - 1; ++i, ch++) { if(i < strlen(text)) ch->Char.AsciiChar = text[i]; else ch->Char.AsciiChar = ' '; // Gray color. ch->Attributes = CMDLINE_ATTRIB; } rect.Left = 0; rect.Right = LINELEN - 1; rect.Top = win->console.cbInfo.dwSize.Y - 1; rect.Bottom = win->console.cbInfo.dwSize.Y - 1; WriteConsoleOutput(win->console.hcScreen, line, linesize, from, &rect); setCmdLineCursor(win, cursorPos, win->console.cbInfo.dwSize.Y - 1); } /** * Attempt to get the BPP (bits-per-pixel) of the local desktop. * * @param bpp Address to write the BPP back to (if any). * * @return @c true, if successful. */ boolean Sys_GetDesktopBPP(int *bpp) { if(!winManagerInited) return false; if(bpp) { HWND hDesktop = GetDesktopWindow(); HDC desktop_hdc = GetDC(hDesktop); int deskbpp = GetDeviceCaps(desktop_hdc, PLANES) * GetDeviceCaps(desktop_hdc, BITSPIXEL); ReleaseDC(hDesktop, desktop_hdc); *bpp = deskbpp; return true; } return false; } /** * Change the display mode using the Win32 API, the closest available * refresh rate is selected. * * @param width Requested horizontal resolution. * @param height Requested vertical resolution. * @param bpp Requested bits per pixel. * * @return Non-zero= success. */ int Sys_ChangeVideoMode(int width, int height, int bpp) { int res, i; DEVMODE current, testMode, newMode; if(!winManagerInited) return 0; Sys_GetDesktopBPP(&screenBPP); // First get the current settings. memset(¤t, 0, sizeof(current)); current.dmSize = sizeof(DEVMODE); if(EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, ¤t)) { if(!bpp) bpp = current.dmBitsPerPel; } else if(!bpp) { // A safe fallback. bpp = 16; } if(width == current.dmPelsWidth && height == current.dmPelsHeight && bpp == current.dmBitsPerPel) return 1; // No need to change, so success! // Override refresh rate? if(ArgCheckWith("-refresh", 1)) current.dmDisplayFrequency = strtol(ArgNext(), 0, 0); // Clear the structure. memset(&newMode, 0, sizeof(newMode)); newMode.dmSize = sizeof(newMode); // Let's enumerate all possible modes to find the most suitable one. for(i = 0;; i++) { memset(&testMode, 0, sizeof(testMode)); testMode.dmSize = sizeof(DEVMODE); if(!EnumDisplaySettings(NULL, i, &testMode)) break; if(testMode.dmPelsWidth == (unsigned) width && testMode.dmPelsHeight == (unsigned) height && testMode.dmBitsPerPel == (unsigned) bpp) { // This looks promising. We'll take the one that best matches // the current refresh rate. if(abs(current.dmDisplayFrequency - testMode.dmDisplayFrequency) < abs(current.dmDisplayFrequency - newMode.dmDisplayFrequency)) { memcpy(&newMode, &testMode, sizeof(DEVMODE)); } } } if(!newMode.dmPelsWidth) { // A perfect match was not found. Let's try something. newMode.dmPelsWidth = width; newMode.dmPelsHeight = height; newMode.dmBitsPerPel = bpp; newMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL; } if((res = ChangeDisplaySettings(&newMode, 0)) != DISP_CHANGE_SUCCESSFUL) { Con_Message("Sys_ChangeVideoMode: Error %x.\n", res); return 0; // Failed, damn you. } // Update the screen size variables. screenWidth = width; screenHeight = height; if(bpp) screenBPP = bpp; return 1; // Success. } /** * Initialize the window manager. * Tasks include; checking the system environment for feature enumeration. * * @return @c true, if initialization was successful. */ boolean Sys_InitWindowManager(void) { if(winManagerInited) return true; // Already been here. Con_Message("Sys_InitWindowManager: Using Win32 window management.\n"); winManagerInited = true; return true; } /** * Shutdown the window manager. * * @return @c true, if shutdown was successful. */ boolean Sys_ShutdownWindowManager(void) { if(!winManagerInited) return false; // Window manager is not initialized. if(windows) { uint i; for(i = 0; i < numWindows; ++i) { Sys_DestroyWindow(i+1); } M_Free(windows); windows = NULL; } // Go back to normal display settings. ChangeDisplaySettings(0, 0); // Now off-line, no more window management will be possible. winManagerInited = false; return true; } /** * Attempt to acquire a device context for OGL rendering and then init. * * @param window Ptr to the window to attach the context to. * * @return @c true iff successful. */ static boolean createContext(ddwindow_t *window) { HDC hdc; boolean ok = true; Con_Message("createContext: OpenGL.\n"); if(window->type != WT_NORMAL) Sys_CriticalMessage("createContext: Window type does not support " "rendering contexts."); hdc = GetDC(window->hWnd); if(!hdc) { Sys_CriticalMessage("createContext: Failed acquiring device."); ok = false; } // Create the OpenGL rendering context. if(!(window->normal.glContext = wglCreateContext(hdc))) { Sys_CriticalMessage("createContext: Creation of rendering context " "failed."); ok = false; } // Make the context current. else if(!wglMakeCurrent(hdc, window->normal.glContext)) { Sys_CriticalMessage("createContext: Couldn't make the rendering " "context current."); ok = false; } if(hdc) ReleaseDC(window->hWnd, hdc); return ok; } /** * Complete the given wminfo_t, detailing what features are supported by * this window manager implementation. * * @param info Ptr to the wminfo_t structure to complete. * * @return @c true, if successful. */ boolean Sys_GetWindowManagerInfo(wminfo_t *info) { if(!winManagerInited) return false; // Window manager is not initialized. if(!info) return false; // Wha? // Complete the structure detailing what features are available. info->canMoveWindow = true; info->maxWindows = 0; info->maxConsoles = 1; return true; } static ddwindow_t *createGLWindow(application_t *app, uint parentIDX, int x, int y, int w, int h, int bpp, int flags, const char *title) { ddwindow_t *win, *pWin = NULL; HWND phWnd = NULL; boolean ok = true; if(!(bpp == 32 || bpp == 16)) { Con_Message("createWindow: Unsupported BPP %i.\n", bpp); return NULL; } if(parentIDX) { pWin = getWindow(parentIDX - 1); if(pWin) phWnd = pWin->hWnd; } // Allocate a structure to wrap the various handles and state variables // used with this window. if((win = (ddwindow_t*) M_Calloc(sizeof(ddwindow_t))) == NULL) return 0; win->type = WT_NORMAL; // Create the window. win->hWnd = CreateWindowEx(WS_EX_APPWINDOW, MAINWCLASS, title, WINDOWEDSTYLE, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, phWnd, NULL, app->hInstance, NULL); if(!win->hWnd) { win->hWnd = NULL; ok = false; } else // Initialize. { PIXELFORMATDESCRIPTOR pfd; int pixForm = 0; HDC hDC = NULL; // Setup the pixel format descriptor. ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.iPixelType = PFD_TYPE_RGBA; pfd.iLayerType = PFD_MAIN_PLANE; #ifndef DRMESA pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.cColorBits = (bpp == 32? 24 : 16); pfd.cDepthBits = 16; #else /* Double Buffer, no alpha */ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT | PFD_DOUBLEBUFFER | PFD_SWAP_COPY; pfd.cColorBits = 24; pfd.cRedBits = 8; pfd.cGreenBits = 8; pfd.cGreenShift = 8; pfd.cBlueBits = 8; pfd.cBlueShift = 16; pfd.cDepthBits = 16; pfd.cStencilBits = 8; #endif if(ok) { // Acquire a device context handle. hDC = GetDC(win->hWnd); if(!hDC) { Sys_CriticalMessage("DD_CreateWindow: Failed acquiring device context handle."); hDC = NULL; ok = false; } else // Initialize. { // Nothing to do. } } if(ok) { // Choose a suitable pixel format. // If multisampling is available, make use of it. if(GL_state_ext.wglMultisampleARB) { pixForm = GL_state.multisampleFormat; } else { // Request a matching (or similar) pixel format. pixForm = ChoosePixelFormat(hDC, &pfd); if(!pixForm) { Sys_CriticalMessage("DD_CreateWindow: Choosing of pixel format failed."); pixForm = -1; ok = false; } } } if(ok) { // Make sure that the driver is hardware-accelerated. DescribePixelFormat(hDC, pixForm, sizeof(pfd), &pfd); if((pfd.dwFlags & PFD_GENERIC_FORMAT) && !ArgCheck("-allowsoftware")) { Sys_CriticalMessage("DD_CreateWindow: GL driver not accelerated!\n" "Use the -allowsoftware option to bypass this."); ok = false; } } if(ok) { // Set the pixel format for the device context. Can only be done once // (unless we release the context and acquire another). if(!SetPixelFormat(hDC, pixForm, &pfd)) { Sys_CriticalMessage("DD_CreateWindow: Warning, setting of pixel " "format failed."); } } // We've now finished with the device context. if(hDC) ReleaseDC(win->hWnd, hDC); } setDDWindow(win, x, y, w, h, bpp, flags, DDSW_NOVISIBLE | DDSW_NOCENTER | DDSW_NOFULLSCREEN); // Ensure new windows are hidden on creation. ShowWindow(win->hWnd, SW_HIDE); if(!ok) { // Damn, something went wrong... clean up. destroyWindow(win); return NULL; } return win; } static ddwindow_t *createConsoleWindow(application_t *app, uint parentIDX, int x, int y, int w, int h, int bpp, int flags, const char *title) { ddwindow_t *win, *pWin = NULL; uint i; HWND phWnd = NULL; boolean ok = true; HANDLE hcScreen; // We only support one dedicated console. for(i = 0; i < numWindows; ++i) { ddwindow_t *other = windows[i]; if(other && other->type == WT_CONSOLE) { Con_Message("createWindow: maxConsoles limit reached.\n"); return NULL; } } if(parentIDX) { pWin = getWindow(parentIDX - 1); if(pWin) phWnd = pWin->hWnd; } // Allocate a structure to wrap the various handles and state variables // used with this window. if((win = (ddwindow_t*) M_Calloc(sizeof(ddwindow_t))) == NULL) return 0; if(!AllocConsole()) { Con_Error("createWindow: Couldn't allocate a console! error %i\n", GetLastError()); } win->hWnd = GetConsoleWindow(); if(!win->hWnd) { win->hWnd = NULL; ok = false; } else // Initialize. { if(!SetWindowText(win->hWnd, title)) Con_Error("createWindow: Setting console title: error %i\n", GetLastError()); hcScreen = GetStdHandle(STD_OUTPUT_HANDLE); if(hcScreen == INVALID_HANDLE_VALUE) Con_Error("createWindow: Bad output handle\n"); win->type = WT_CONSOLE; win->console.hcScreen = hcScreen; GetConsoleScreenBufferInfo(hcScreen, &win->console.cbInfo); // This is the location of the print cursor. win->console.cx = 0; win->console.cy = win->console.cbInfo.dwSize.Y - 2; setConWindowCmdLine(win, "", 1, 0); // We'll be needing the console input handler. Sys_ConInputInit(); } setDDWindow(win, x, y, w, h, bpp, flags, DDSW_NOVISIBLE | DDSW_NOCENTER | DDSW_NOFULLSCREEN); // Ensure new windows are hidden on creation. ShowWindow(win->hWnd, SW_HIDE); if(!ok) { // Damn, something went wrong... clean up. destroyWindow(win); return NULL; } return win; } /** * Create a new window. * * @param app Ptr to the application structure holding our globals. * @param parentIDX Index number of the window that is to be the parent * of the new window. If @c 0, window has no * parent. * @param x X position (in desktop-space). * @param y Y position (in desktop-space). * @param w Width (client area). * @param h Height (client area). * @param bpp BPP (bits-per-pixel) * @param flags DDWF_* flags, control appearance/behavior. * @param type Type of window to be created (WT_*) * @param title Window title string, ELSE @c NULL,. * @param data Platform specific data. * * @return If @c 0, window creation was unsuccessful, * ELSE 1-based index identifier of the new window. */ uint Sys_CreateWindow(application_t *app, uint parentIDX, int x, int y, int w, int h, int bpp, int flags, ddwindowtype_t type, const char *title, void *data) { ddwindow_t *win = NULL; /* Currently ignored. int nCmdShow = (data? *((int*) data) : 0); */ if(!winManagerInited) return 0; // Window manager not initialized yet. switch(type) { case WT_NORMAL: win = createGLWindow(app, parentIDX, x, y, w, h, bpp, flags, title); break; case WT_CONSOLE: win = createConsoleWindow(app, parentIDX, x, y, w, h, bpp, flags, title); break; default: Con_Error("Sys_CreateWindow: Unknown window type (%i).", (int) type); break; } if(win) { // Success, link it in. uint i = 0; ddwindow_t **newList = M_Malloc(sizeof(ddwindow_t*) * ++numWindows); // Copy the existing list? if(windows) { for(; i < numWindows - 1; ++i) newList[i] = windows[i]; } // Add the new one to the end. newList[i] = win; // Replace the list. if(windows) M_Free(windows); // Free windows? har, har. windows = newList; } else { // Un-successful. return 0; } // Make this the new active window. Sys_SetActiveWindow(numWindows); // index + 1; return numWindows; // index + 1. } static boolean destroyGLWindow(ddwindow_t *window) { // Delete the window's rendering context if one has been acquired. if(window->normal.glContext) { wglMakeCurrent(NULL, NULL); wglDeleteContext(window->normal.glContext); } // Destroy the window and release the handle. if(window->hWnd && !DestroyWindow(window->hWnd)) return false; return true; } static boolean destroyConsoleWindow(ddwindow_t *window) { // We no longer need the input handler. Sys_ConInputShutdown(); // Detach the console for this process. if(!FreeConsole()) return false; return true; } static void destroyWindow(ddwindow_t *window) { boolean ok = true; if(window->flags & DDWF_FULLSCREEN) { // Change back to the desktop before doing anything further to try // and circumvent crusty old drivers from corrupting the desktop. ChangeDisplaySettings(NULL, 0); } switch(window->type) { case WT_NORMAL: ok = destroyGLWindow(window); break; case WT_CONSOLE: ok = destroyConsoleWindow(window); break; default: Con_Error("destroyWindow: Invalid window type %i.", window->type); break; }; // Free any local memory we acquired for managing the window's state, then // finally the ddwindow. M_Free(window); if(!ok) DD_ErrorBox(true, "Error destroying window."); } /** * Destroy the specified window. * * Side-effects: If the window is fullscreen and the current video mode is * not that set as the desktop default: an attempt will be made to change * back to the desktop default video mode. * * @param idx Index of the window to destroy (1-based). * * @return @c true, if successful. */ boolean Sys_DestroyWindow(uint idx) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window) { destroyWindow(window); windows[idx-1] = NULL; return true; } } return false; } /** * Change the currently active window. * * @param idx Index of the window to make active (1-based). * * @return @c true, if successful. */ boolean Sys_SetActiveWindow(uint idx) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window) { theWindow = window; return true; } } return false; } static boolean setDDWindow(ddwindow_t *window, int newX, int newY, int newWidth, int newHeight, int newBPP, int wFlags, int uFlags) { int x, y, width, height, bpp, flags; HWND hWnd; boolean newGLContext = false; boolean updateStyle = false; boolean changeVideoMode = false; boolean changeWindowDimensions = false; boolean noMove = (uFlags & DDSW_NOMOVE); boolean noSize = (uFlags & DDSW_NOSIZE); boolean inControlPanel = false; if(uFlags & DDSW_NOCHANGES) return true; // Nothing to do. // Grab the current values. hWnd = window->hWnd; x = window->x; y = window->y; width = window->width; height = window->height; bpp = window->normal.bpp; flags = window->flags; // Force update on init? if(!window->inited && window->type == WT_NORMAL) { newGLContext = updateStyle = true; } if(window->type == WT_NORMAL) inControlPanel = UI_IsActive(); // Change auto window centering? if(!(uFlags & DDSW_NOCENTER) && (flags & DDWF_CENTER) != (wFlags & DDWF_CENTER)) { flags ^= DDWF_CENTER; } // Change to fullscreen? if(!(uFlags & DDSW_NOFULLSCREEN) && (flags & DDWF_FULLSCREEN) != (wFlags & DDWF_FULLSCREEN)) { flags ^= DDWF_FULLSCREEN; if(window->type == WT_NORMAL) { newGLContext = true; updateStyle = true; changeVideoMode = true; } } // Change window size? if(!(uFlags & DDSW_NOSIZE) && (width != newWidth || height != newHeight)) { width = newWidth; height = newHeight; if(window->type == WT_NORMAL) { if(flags & DDWF_FULLSCREEN) changeVideoMode = true; newGLContext = true; } changeWindowDimensions = true; } if(window->type == WT_NORMAL) { // Change BPP (bits per pixel)? if(!(uFlags & DDSW_NOBPP) && bpp != newBPP) { if(!(newBPP == 32 || newBPP == 16)) Con_Error("Sys_SetWindow: Unsupported BPP %i.", newBPP); bpp = newBPP; newGLContext = true; changeVideoMode = true; } } if(changeWindowDimensions) { // Can't change the resolution while the UI is active. // (controls need to be repositioned). if(inControlPanel) UI_End(); } if(changeVideoMode) { if(flags & DDWF_FULLSCREEN) { if(!Sys_ChangeVideoMode(width, height, bpp)) { Sys_CriticalMessage("Sys_SetWindow: Resolution change failed."); return false; } } else { // Go back to normal display settings. ChangeDisplaySettings(0, 0); } } // Change window position? if(flags & DDWF_FULLSCREEN) { if(x != 0 || y != 0) { // Force move to [0,0] x = y = 0; noMove = false; } } else if(!(uFlags & DDSW_NOMOVE)) { if(flags & DDWF_CENTER) { // Auto centering mode. x = (GetSystemMetrics(SM_CXSCREEN) - width) / 2; y = (GetSystemMetrics(SM_CYSCREEN) - height) / 2; } else if(x != newX || y != newY) { x = newX; y = newY; } // Are we in range here? if(width > GetSystemMetrics(SM_CXSCREEN)) width = GetSystemMetrics(SM_CXSCREEN); if(height > GetSystemMetrics(SM_CYSCREEN)) height = GetSystemMetrics(SM_CYSCREEN); } // Change visibility? if(!(uFlags & DDSW_NOVISIBLE) && (flags & DDWF_VISIBLE) != (wFlags & DDWF_VISIBLE)) { flags ^= DDWF_VISIBLE; } // Hide the window? if(!(flags & DDWF_VISIBLE)) ShowWindow(hWnd, SW_HIDE); // Update the current values. window->x = x; window->y = y; window->width = width; window->height = height; if(window->type == WT_NORMAL) window->normal.bpp = bpp; window->flags = flags; if(!window->inited) window->inited = true; // Do NOT modify ddwindow_t properties after this point. if(updateStyle) { // We need to request changes to the window style. LONG style; if(flags & DDWF_FULLSCREEN) style = FULLSCREENSTYLE; else style = WINDOWEDSTYLE; SetWindowLong(hWnd, GWL_STYLE, style); } if(!(flags & DDWF_FULLSCREEN)) { // We need to have a large enough client area. RECT rect; rect.left = x; rect.top = y; rect.right = x + width; rect.bottom = y + height; AdjustWindowRect(&rect, WINDOWEDSTYLE, false); width = rect.right - rect.left; height = rect.bottom - rect.top; noSize = false; } // Make it so. SetWindowPos(hWnd, 0, x, y, width, height, (noSize? SWP_NOSIZE : 0) | (noMove? SWP_NOMOVE : 0) | (updateStyle? SWP_FRAMECHANGED : 0) | SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOACTIVATE); // Do we need a new GL context due to changes to the window? if(!novideo && newGLContext) { // Maybe requires a renderer restart. extern boolean usingFog; boolean glIsInited = GL_IsInited(); boolean hadFog; if(glIsInited) { // Shut everything down, but remember our settings. hadFog = usingFog; GL_TotalReset(); gx.UpdateState(DD_RENDER_RESTART_PRE); UI_ClearTextures(); wglMakeCurrent(NULL, NULL); wglDeleteContext(window->normal.glContext); } if(createContext(window)) { // We can get on with initializing the OGL state. Sys_InitGLState(); } if(glIsInited) { // Re-initialize. GL_TotalRestore(); GL_InitRefresh(); if(hadFog) GL_UseFog(true); gx.UpdateState(DD_RENDER_RESTART_POST); UI_LoadTextures(); } } // If the window dimensions have changed, update any sub-systems // which need to respond. if(changeWindowDimensions && window->type == WT_NORMAL) { // Update viewport coordinates. R_SetViewGrid(0, 0); if(inControlPanel) // Reactivate the panel? Con_Execute(CMDS_DDAY, "panel", true, false); } // Show the hidden window? if(flags & DDWF_VISIBLE) { ShowWindow(hWnd, SW_SHOW); UpdateWindow(hWnd); } return true; } /** * Attempt to set the appearance/behavioral properties of the given window. * * @param idx Index identifier (1-based) to the window. * @param newX New x position of the left side of the window. * @param newY New y position of the top of the window. * @param newWidth New width to set the window to. * @param newHeight New height to set the window to. * @param newBPP New BPP (bits-per-pixel) to change to. * @param wFlags DDWF_* flags to change other appearance/behavior. * @param uFlags DDSW_* flags govern how the other paramaters should be * interpreted. * * DDSW_NOSIZE: * If set, params 'newWidth' and 'newHeight' are ignored * and no change will be made to the window dimensions. * * DDSW_NOMOVE: * If set, params 'newX' and 'newY' are ignored and no * change will be made to the window position. * * DDSW_NOBPP: * If set, param 'newBPP' is ignored and the no change * will be made to the window color depth. * * DDSW_NOFULLSCREEN: * If set, the value of the DDWF_FULLSCREEN bit in param * 'wFlags' is ignored and no change will be made to the * fullscreen state of the window. * * DDSW_NOVISIBLE: * If set, the value of the DDWF_VISIBLE bit in param * 'wFlags' is ignored and no change will be made to the * window's visibility. * * DDSW_NOCENTER: * If set, the value of the DDWF_CENTER bit in param * 'wFlags' is ignored and no change will be made to the * auto-center state of the window. * * @return @c true, if successful. */ boolean Sys_SetWindow(uint idx, int newX, int newY, int newWidth, int newHeight, int newBPP, uint wFlags, uint uFlags) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window) return setDDWindow(window, newX, newY, newWidth, newHeight, newBPP, wFlags, uFlags); } return false; } /** * Update the contents of the window. */ void Sys_UpdateWindow(uint idx) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window->type == WT_NORMAL) { if(window->normal.glContext) { // Window has a glContext attached, so make the content of the // framebuffer visible. HDC hdc = GetDC(window->hWnd); if(GL_state.forceFinishBeforeSwap) { glFinish(); } // Swap buffers. glFlush(); SwapBuffers(hdc); ReleaseDC(window->hWnd, hdc); } } } } /** * Attempt to set the title of the given window. * * @param idx Index identifier (1-based) to the window. * @param title New title for the window. * * @return @c true, if successful. */ boolean Sys_SetWindowTitle(uint idx, const char *title) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window) { return (SetWindowText(window->hWnd, (title))? true : false); } } return false; } /** * Attempt to get the dimensions (and position) of the given window (client * area) in screen-space. * * @param idx Index identifier (1-based) to the window. * @param x Address to write the x position back to (if any). * @param y Address to write the y position back to (if any). * @param width Address to write the width back to (if any). * @param height Address to write the height back to (if any). * * @return @c true, if successful. */ boolean Sys_GetWindowDimensions(uint idx, int *x, int *y, int *width, int *height) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(!window || (!x && !y && !width && !height)) return false; if(x) *x = window->x; if(y) *y = window->y; if(width) *width = window->width; if(height) *height = window->height; return true; } return false; } /** * Attempt to get the BPP (bits-per-pixel) of the given window. * * @param idx Index identifier (1-based) to the window. * @param bpp Address to write the BPP back to (if any). * * @return @c true, if successful. */ boolean Sys_GetWindowBPP(uint idx, int *bpp) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window) { if(window->type == WT_NORMAL) { if(bpp) { *bpp = window->normal.bpp; return true; } } } } return false; } /** * Attempt to get the fullscreen-state of the given window. * * @param idx Index identifier (1-based) to the window. * @param fullscreen Address to write the fullscreen state back to (if any). * * @return @c true, if successful. */ boolean Sys_GetWindowFullscreen(uint idx, boolean *fullscreen) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window && fullscreen) { *fullscreen = ((window->flags & DDWF_FULLSCREEN)? true : false); } return true; } return false; } /** * Attempt to get a HWND handle to the given window. * * \todo: Factor platform specific design patterns out of Doomsday. * We should not be passing around HWND handles... * * @param idx Index identifier (1-based) to the window. * * @return HWND handle if successful, ELSE @c NULL,. */ HWND Sys_GetWindowHandle(uint idx) { if(winManagerInited) { ddwindow_t *window = getWindow(idx - 1); if(window) { return window->hWnd; } } return NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/src/sys_findfile.c0000644000175000017500000000567311357170242022720 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2008 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_findfile.c: Wrappers for File Finding (Win32) */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "sys_findfile.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct winfinddata_s { struct _finddata_t data; intptr_t handle; } winfinddata_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static void setdata(finddata_t *dta) { winfinddata_t *fd = dta->finddata; dta->date = fd->data.time_write; dta->time = fd->data.time_write; dta->size = fd->data.size; dta->name = fd->data.name; dta->attrib = 0; if(fd->data.attrib & _A_SUBDIR) dta->attrib |= A_SUBDIR; } int myfindfirst(const char *filename, finddata_t *dta) { winfinddata_t *fd; // Allocate a new private finddata struct. dta->finddata = fd = calloc(1, sizeof(winfinddata_t)); // Begin the search. fd->handle = _findfirst(filename, &fd->data); setdata(dta); return (fd->handle == (long) (-1)); } int myfindnext(finddata_t *dta) { int result; winfinddata_t *fd = dta->finddata; result = _findnext(fd->handle, &fd->data); if(!result) setdata(dta); return result != 0; } void myfindend(finddata_t *dta) { _findclose(((winfinddata_t *) dta->finddata)->handle); free(dta->finddata); memset(dta, 0, sizeof(*dta)); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/src/sys_audiod_loader.c0000644000175000017500000001246311357170242023726 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_loader.c: Audio Driver loader, Win32-specific. * * Loader for ds*.dll */ // HEADER FILES ------------------------------------------------------------ #define WIN32_LEAN_AND_MEAN #include #include "de_console.h" #include "s_main.h" #include "sys_audiod.h" #include "sys_audiod_sfx.h" #include "sys_audiod_mus.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- audiodriver_t audiodExternal; audiointerface_sfx_t audiodExternalISFX; audiointerface_music_t audiodExternalIMusic; audiointerface_cd_t audiodExternalICD; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static HINSTANCE hInstExt = NULL; // CODE -------------------------------------------------------------------- static void* Imp(const char* fn) { return GetProcAddress(hInstExt, fn); } void Sys_ShutdownAudioDriver(void) { if(!audioDriver) return; if(audioDriver->Shutdown) audioDriver->Shutdown(); if(audioDriver == &audiodExternal) { FreeLibrary(hInstExt); hInstExt = NULL; } } static audiodriver_t* importExternal(void) { audiodriver_t* d = &audiodExternal; // Clear everything. memset(d, 0, sizeof(*d)); d->Init = Imp("DS_Init"); d->Shutdown = Imp("DS_Shutdown"); d->Event = Imp("DS_Event"); // The driver may provide SFX playback functionality. if(Imp("DS_SFX_Init")) { // The driver offers a SFX playback interface. audiointerface_sfx_t* i = &audiodExternalISFX; i->gen.Init = Imp("DS_SFX_Init"); i->gen.Create = Imp("DS_SFX_CreateBuffer"); i->gen.Destroy = Imp("DS_SFX_DestroyBuffer"); i->gen.Load = Imp("DS_SFX_Load"); i->gen.Reset = Imp("DS_SFX_Reset"); i->gen.Play = Imp("DS_SFX_Play"); i->gen.Stop = Imp("DS_SFX_Stop"); i->gen.Refresh = Imp("DS_SFX_Refresh"); i->gen.Set = Imp("DS_SFX_Set"); i->gen.Setv = Imp("DS_SFX_Setv"); i->gen.Listener = Imp("DS_SFX_Listener"); i->gen.Listenerv = Imp("DS_SFX_Listenerv"); i->gen.Getv = Imp("DS_SFX_Getv"); } // The driver may provide music playback functionality. if(Imp("DM_Music_Init")) { // The driver also offers a music playback interface. audiointerface_music_t* i = &audiodExternalIMusic; i->gen.Init = Imp("DM_Music_Init"); i->gen.Update = Imp("DM_Music_Update"); i->gen.Get = Imp("DM_Music_Get"); i->gen.Set = Imp("DM_Music_Set"); i->gen.Pause = Imp("DM_Music_Pause"); i->gen.Stop = Imp("DM_Music_Stop"); i->SongBuffer = Imp("DM_Music_SongBuffer"); i->Play = Imp("DM_Music_Play"); i->PlayFile = Imp("DM_Music_PlayFile"); } if(Imp("DM_CDAudio_Init")) { // The driver also offers a CD audio (redbook) playback interface. audiointerface_cd_t* i = &audiodExternalICD; i->gen.Init = Imp("DM_CDAudio_Init"); i->gen.Update = Imp("DM_CDAudio_Update"); i->gen.Set = Imp("DM_CDAudio_Set"); i->gen.Get = Imp("DM_CDAudio_Get"); i->gen.Pause = Imp("DM_CDAudio_Pause"); i->gen.Stop = Imp("DM_CDAudio_Stop"); i->Play = Imp("DM_CDAudio_Play"); } return d; } /** * Attempt to load the specified audio driver, import the entry points and * add to the available audio drivers. * * @param name Name of the driver to be loaded e.g., "openal". * @return Ptr to the audio driver interface if successful, * else @c NULL. */ audiodriver_t* Sys_LoadAudioDriver(const char* name) { char fn[256]; // Compose the name, use the prefix "ds". sprintf(fn, "ds%s.dll", name); // Load the DLL. hInstExt = LoadLibrary(fn); if(!hInstExt) { // Load failed. Con_Message("Sys_LoadAudioDriver: Loading of %s failed.\n", fn); return NULL; } return importExternal(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/src/sys_console.c0000644000175000017500000002121211357170242022565 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_console.c: Std input handling - Win32 specific */ // HEADER FILES ------------------------------------------------------------ #define WIN32_LEAN_AND_MEAN #include #include "de_platform.h" #include "de_console.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define MAXRECS 128 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean conInputInited = false; static HANDLE hcInput = NULL; static byte *keymap = NULL; static byte *vKeyDown = NULL; // Used for tracking the state of the vKeys. static INPUT_RECORD *inputBuf = NULL; static DWORD inputBufsize = 0; // CODE -------------------------------------------------------------------- static void initVKeyToDDKeyTlat(void) { if(keymap) return; // Already been here. keymap = M_Calloc(sizeof(byte) * 256); keymap[VK_BACK] = DDKEY_BACKSPACE; // Backspace keymap[VK_TAB ] = DDKEY_TAB; //keymap[VK_CLEAR] = ; keymap[VK_RETURN] = DDKEY_RETURN; keymap[VK_SHIFT] = DDKEY_RSHIFT; keymap[VK_CONTROL] = DDKEY_RCTRL; keymap[VK_MENU] = DDKEY_RALT; keymap[VK_PAUSE] = DDKEY_PAUSE; //keymap[VK_CAPITAL] = ; //keymap[VK_KANA] = ; //keymap[VK_HANGEUL] = ; //keymap[VK_HANGUL] = ; //keymap[VK_JUNJA] = ; //keymap[VK_FINAL] = ; //keymap[VK_HANJA] = ; //keymap[VK_KANJI] = ; keymap[VK_ESCAPE] = DDKEY_ESCAPE; //keymap[VK_CONVERT] = ; //keymap[VK_NONCONVERT] = ; //keymap[VK_ACCEPT] = ; //keymap[VK_MODECHANGE] = ; keymap[VK_SPACE] = ' '; keymap[VK_OEM_PLUS] = '+'; keymap[VK_OEM_COMMA] = ','; keymap[VK_OEM_MINUS] = '-'; keymap[VK_OEM_PERIOD] = '.'; keymap[VK_OEM_1] = ';'; keymap[VK_OEM_2] = '/'; keymap[VK_OEM_3] = '\''; keymap[VK_OEM_4] = '['; keymap[VK_OEM_5] = DDKEY_BACKSLASH; keymap[VK_OEM_6] = ']'; keymap[VK_OEM_7] = '#'; keymap[VK_OEM_8] = '`'; keymap[VK_PRIOR] = DDKEY_PGUP; keymap[VK_NEXT] = DDKEY_PGDN; keymap[VK_END] = DDKEY_END; keymap[VK_HOME] = DDKEY_HOME; keymap[VK_LEFT] = DDKEY_LEFTARROW; keymap[VK_UP] = DDKEY_UPARROW; keymap[VK_RIGHT] = DDKEY_RIGHTARROW; keymap[VK_DOWN] = DDKEY_DOWNARROW; //keymap[VK_SELECT] = ; //keymap[VK_PRINT] = ; //keymap[VK_EXECUTE] = ; //keymap[VK_SNAPSHOT] = ; keymap[VK_INSERT] = DDKEY_INS; keymap[VK_DELETE] = DDKEY_DEL; //keymap[VK_HELP] = ; //keymap[VK_LWIN] = ; //keymap[VK_RWIN] = ; //keymap[VK_APPS] = ; //keymap[VK_SLEEP] = ; keymap[VK_NUMPAD0] = DDKEY_NUMPAD0; keymap[VK_NUMPAD1] = DDKEY_NUMPAD1; keymap[VK_NUMPAD2] = DDKEY_NUMPAD2; keymap[VK_NUMPAD3] = DDKEY_NUMPAD3; keymap[VK_NUMPAD4] = DDKEY_NUMPAD4; keymap[VK_NUMPAD5] = DDKEY_NUMPAD5; keymap[VK_NUMPAD6] = DDKEY_NUMPAD6; keymap[VK_NUMPAD7] = DDKEY_NUMPAD7; keymap[VK_NUMPAD8] = DDKEY_NUMPAD8; keymap[VK_NUMPAD9] = DDKEY_NUMPAD9; keymap[VK_MULTIPLY] = '*'; keymap[VK_ADD] = DDKEY_ADD; //keymap[VK_SEPARATOR] = ; keymap[VK_SUBTRACT] = DDKEY_SUBTRACT; keymap[VK_DECIMAL] = DDKEY_DECIMAL; keymap[VK_DIVIDE] = '/'; keymap[VK_F1] = DDKEY_F1; keymap[VK_F2] = DDKEY_F2; keymap[VK_F3] = DDKEY_F3; keymap[VK_F4] = DDKEY_F4; keymap[VK_F5] = DDKEY_F5; keymap[VK_F6] = DDKEY_F6; keymap[VK_F7] = DDKEY_F7; keymap[VK_F8] = DDKEY_F8; keymap[VK_F9] = DDKEY_F9; keymap[VK_F10] = DDKEY_F10; keymap[VK_F11] = DDKEY_F11; keymap[VK_F12] = DDKEY_F12; keymap[0x30] = '0'; keymap[0x31] = '1'; keymap[0x32] = '2'; keymap[0x33] = '3'; keymap[0x34] = '4'; keymap[0x35] = '5'; keymap[0x36] = '6'; keymap[0x37] = '7'; keymap[0x38] = '8'; keymap[0x39] = '9'; keymap[0x41] = 'a'; keymap[0x42] = 'b'; keymap[0x43] = 'c'; keymap[0x44] = 'd'; keymap[0x45] = 'e'; keymap[0x46] = 'f'; keymap[0x47] = 'g'; keymap[0x48] = 'h'; keymap[0x49] = 'i'; keymap[0x4A] = 'j'; keymap[0x4B] = 'k'; keymap[0x4C] = 'l'; keymap[0x4D] = 'm'; keymap[0x4E] = 'n'; keymap[0x4F] = 'o'; keymap[0x50] = 'p'; keymap[0x51] = 'q'; keymap[0x52] = 'r'; keymap[0x53] = 's'; keymap[0x54] = 't'; keymap[0x55] = 'u'; keymap[0x56] = 'v'; keymap[0x57] = 'w'; keymap[0x58] = 'x'; keymap[0x59] = 'y'; keymap[0x5A] = 'z'; } /** * Convert a VKey (VK_*) to a DDkey (DDKEY_*) constant. */ static byte vKeyToDDKey(byte vkey) { return keymap[vkey]; } void Sys_ConInputInit(void) { if(conInputInited) return; // Already active. /** * For now, always load the U.S. English layout. * * \todo Is this even necessary with virtualkeys? */ LoadKeyboardLayout("00000409", KLF_SUBSTITUTE_OK); // We'll be needing the VKey to DDKey translation table. initVKeyToDDKeyTlat(); // And the down key array; vKeyDown = M_Calloc(sizeof(byte) * 256); hcInput = GetStdHandle(STD_INPUT_HANDLE); if(hcInput == INVALID_HANDLE_VALUE) Con_Error("Sys_ConInit: Bad input handle\n"); conInputInited = true; } void Sys_ConInputShutdown(void) { if(!conInputInited) return; if(inputBuf) { M_Free(inputBuf); inputBuf = NULL; inputBufsize = 0; } M_Free(keymap); keymap = NULL; M_Free(vKeyDown); vKeyDown = NULL; conInputInited = false; } /** * Copy n key events from the console and encode them into given buffer. * * @param evbuf Ptr to the buffer to encode events to. * @param bufsize Size of the buffer. * * @return Number of key events written to the buffer. */ size_t I_GetConsoleKeyEvents(keyevent_t *evbuf, size_t bufsize) { DWORD num; size_t n = 0; if(!conInputInited) return 0; // Check for awaiting unprocessed events. if(!GetNumberOfConsoleInputEvents(hcInput, &num)) Con_Error("Sys_ConPostEvents: error %i\n", (int) GetLastError()); if(num > 0) { DWORD read, min; INPUT_RECORD *ptr; KEY_EVENT_RECORD *key; // Do we need to enlarge the input record buffer? min = MIN_OF((DWORD)bufsize, num); if(min > inputBufsize) { inputBuf = M_Malloc(sizeof(INPUT_RECORD) * min); inputBufsize = min; } // Get the input records. ReadConsoleInput(hcInput, inputBuf, min, &read); // Convert to key events and pack into the supplied buffer. for(ptr = inputBuf; read > 0; read--, ptr++) { if(ptr->EventType != KEY_EVENT) continue; key = &ptr->Event.KeyEvent; // Has the state changed? if((!vKeyDown[key->wVirtualKeyCode] && key->bKeyDown) || (vKeyDown[key->wVirtualKeyCode] && !key->bKeyDown)) { // Use the table to translate the vKey to a DDKEY. evbuf[n].ddkey = vKeyToDDKey(key->wVirtualKeyCode); evbuf[n].event = (key->bKeyDown? IKE_KEY_DOWN : IKE_KEY_UP); // Record the new state of this vKey. vKeyDown[key->wVirtualKeyCode] = (key->bKeyDown? true : false); n++; } } } return n; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/src/sys_input.c0000644000175000017500000007102211357170242022266 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_input.c: Game Controllers * * Keyboard, mouse and joystick input using DirectInput. */ // HEADER FILES ------------------------------------------------------------ #define WIN32_LEAN_AND_MEAN #define DIRECTINPUT_VERSION 0x0800 #include #include #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" #include "dd_winit.h" // MACROS ------------------------------------------------------------------ #define KEYBUFSIZE 32 #define I_SAFE_RELEASE(d) { if(d) { IDirectInputDevice_Release(d); \ (d) = NULL; } } #define I_SAFE_RELEASE2(d) { if(d) { IDirectInputDevice2_Release(d); \ (d) = NULL; } } // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int novideo; // PUBLIC DATA DEFINITIONS ------------------------------------------------- int joydevice = 0; // Joystick index to use. byte usejoystick = false; // Joystick input enabled? // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean initIOk = false; static LPDIRECTINPUT8 dInput; static LPDIRECTINPUTDEVICE8 didKeyb, didMouse; static LPDIRECTINPUTDEVICE8 didJoy; static DIDEVICEINSTANCE firstJoystick; static int counter; // A customizable mapping of the scantokey array. //static char keyMapPath[NUMKKEYS] = "}Data\\KeyMaps\\"; static byte* keymap = NULL; // CODE -------------------------------------------------------------------- void I_Register(void) { C_VAR_INT("input-joy-device", &joydevice, CVF_NO_MAX | CVF_PROTECTED, 0, 0); C_VAR_BYTE("input-joy", &usejoystick, 0, 0, 1); } const char *I_ErrorMsg(HRESULT hr) { return hr == DI_OK ? "OK" : hr == DIERR_GENERIC ? "Generic error" : hr == DI_PROPNOEFFECT ? "Property has no effect" : hr == DIERR_INVALIDPARAM ? "Invalid parameter" : hr == DIERR_NOTINITIALIZED ? "Not initialized" : hr == DIERR_UNSUPPORTED ? "Unsupported" : hr == DIERR_NOTFOUND ? "Not found" : "?"; } static void initDIKeyToDDKeyTlat(void) { if(keymap) return; // Already been here. keymap = M_Calloc(sizeof(byte) * NUMKKEYS); keymap[DIK_0] = '0'; keymap[DIK_1] = '1'; keymap[DIK_2] = '2'; keymap[DIK_3] = '3'; keymap[DIK_4] = '4'; keymap[DIK_5] = '5'; keymap[DIK_6] = '6'; keymap[DIK_7] = '7'; keymap[DIK_8] = '8'; keymap[DIK_9] = '9'; keymap[DIK_A] = 'a'; //keymap[DIK_ABNT_C1] = ; //keymap[DIK_ABNT_C2] = ; keymap[DIK_ADD] = DDKEY_ADD; keymap[DIK_APOSTROPHE] = '\''; //keymap[DIK_APPS] = ; //keymap[DIK_AT] = ; //keymap[DIK_AX] = ; keymap[DIK_B] = 'b'; keymap[DIK_BACK] = DDKEY_BACKSPACE; keymap[DIK_BACKSLASH] = DDKEY_BACKSLASH; keymap[DIK_C] = 'c'; //keymap[DIK_CALCULATOR] = ; //keymap[DIK_CAPITAL] = ; //keymap[DIK_COLON] = ; // On Japanese keyboard keymap[DIK_COMMA] = ','; //keymap[DIK_CONVERT] = ; keymap[DIK_D] = 'd'; keymap[DIK_DECIMAL] = DDKEY_DECIMAL; keymap[DIK_DELETE] = DDKEY_DEL; keymap[DIK_DIVIDE] = '/'; keymap[DIK_DOWN] = DDKEY_DOWNARROW; keymap[DIK_E] = 'e'; keymap[DIK_END] = DDKEY_END; keymap[DIK_EQUALS] = DDKEY_EQUALS; keymap[DIK_ESCAPE] = DDKEY_ESCAPE; keymap[DIK_F] = 'f'; keymap[DIK_F1] = DDKEY_F1; keymap[DIK_F2] = DDKEY_F2; keymap[DIK_F3] = DDKEY_F3; keymap[DIK_F4] = DDKEY_F4; keymap[DIK_F5] = DDKEY_F5; keymap[DIK_F6] = DDKEY_F6; keymap[DIK_F7] = DDKEY_F7; keymap[DIK_F8] = DDKEY_F8; keymap[DIK_F9] = DDKEY_F9; keymap[DIK_F10] = DDKEY_F10; keymap[DIK_F11] = DDKEY_F11; keymap[DIK_F12] = DDKEY_F12; //keymap[DIK_F13] = ; //keymap[DIK_F14] = ; //keymap[DIK_F15] = ; keymap[DIK_G] = 'g'; keymap[DIK_GRAVE] = '`'; keymap[DIK_H] = 'h'; keymap[DIK_HOME] = DDKEY_HOME; keymap[DIK_I] = 'i'; keymap[DIK_INSERT] = DDKEY_INS; keymap[DIK_J] = 'j'; keymap[DIK_K] = 'k'; //keymap[DIK_KANA] = ; //keymap[DIK_KANJI] = ; keymap[DIK_L] = 'l'; keymap[DIK_LBRACKET] = '['; keymap[DIK_LCONTROL] = ']'; keymap[DIK_LEFT] = DDKEY_LEFTARROW; keymap[DIK_LMENU] = DDKEY_LALT; // Left Alt keymap[DIK_LSHIFT] = DDKEY_LSHIFT; //keymap[DIK_LWIN] = ; // Left Windows logo key keymap[DIK_M] = 'm'; //keymap[DIK_MAIL] = ; //keymap[DIK_MEDIASELECT] = ; Media Select key, which displays a selection of supported media players on the system //keymap[DIK_MEDIASTOP] = ; keymap[DIK_MINUS] = '-'; // On main keyboard. keymap[DIK_MULTIPLY] = '*'; // Asterisk (*) on numeric keypad //keymap[DIK_MUTE] = ; //keymap[DIK_MYCOMPUTER] = ; keymap[DIK_N] = 'n'; keymap[DIK_NEXT] = DDKEY_PGDN; // Page down //keymap[DIK_NEXTTRACK] = ; //keymap[DIK_NOCONVERT] = ; // On Japanese keyboard keymap[DIK_NUMLOCK] = DDKEY_NUMLOCK; keymap[DIK_NUMPAD0] = DDKEY_NUMPAD0; keymap[DIK_NUMPAD1] = DDKEY_NUMPAD1; keymap[DIK_NUMPAD2] = DDKEY_NUMPAD2; keymap[DIK_NUMPAD3] = DDKEY_NUMPAD3; keymap[DIK_NUMPAD4] = DDKEY_NUMPAD4; keymap[DIK_NUMPAD5] = DDKEY_NUMPAD5; keymap[DIK_NUMPAD6] = DDKEY_NUMPAD6; keymap[DIK_NUMPAD7] = DDKEY_NUMPAD7; keymap[DIK_NUMPAD8] = DDKEY_NUMPAD8; keymap[DIK_NUMPAD9] = DDKEY_NUMPAD9; //keymap[DIK_NUMPADCOMMA] = ; // On numeric keypad of NEC PC-98 Japanese keyboard //keymap[DIK_NUMPADENTER] = ; //keymap[DIK_NUMPADEQUALS] = ; // On numeric keypad of NEC PC-98 Japanese keyboard keymap[DIK_O] = 'o'; //keymap[DIK_OEM_102] = ; // On British and German keyboards keymap[DIK_P] = 'p'; keymap[DIK_PAUSE] = DDKEY_PAUSE; keymap[DIK_PERIOD] = '.'; //keymap[DIK_PLAYPAUSE] = ; //keymap[DIK_POWER] = ; //keymap[DIK_PREVTRACK] = ; // Previous track; circumflex on Japanese keyboard keymap[DIK_PRIOR] = DDKEY_PGUP; // Page up keymap[DIK_Q] = 'q'; keymap[DIK_R] = 'r'; keymap[DIK_RBRACKET] = ']'; keymap[DIK_RCONTROL] = DDKEY_RCTRL; keymap[DIK_RETURN] = DDKEY_RETURN; // Return on main keyboard keymap[DIK_RIGHT] = DDKEY_RIGHTARROW; keymap[DIK_RMENU] = DDKEY_RALT; // Right alt keymap[DIK_RSHIFT] = DDKEY_RSHIFT; //keymap[DIK_RWIN] = ; // Right Windows logo key keymap[DIK_S] = 's'; keymap[DIK_SCROLL] = DDKEY_SCROLL; keymap[DIK_SEMICOLON] = ';'; keymap[DIK_SLASH] = '/'; //keymap[DIK_SLEEP] = ; keymap[DIK_SPACE] = ' '; //keymap[DIK_STOP] = ; // On NEC PC-98 Japanese keyboard keymap[DIK_SUBTRACT] = DDKEY_SUBTRACT; // On numeric keypad //keymap[DIK_SYSRQ] = ; keymap[DIK_T] = 't'; keymap[DIK_TAB] = DDKEY_TAB; keymap[DIK_U] = 'u'; //keymap[DIK_UNDERLINE] = ; // On NEC PC-98 Japanese keyboard //keymap[DIK_UNLABELED] = ; // On Japanese keyboard keymap[DIK_UP] = DDKEY_UPARROW; keymap[DIK_V] = 'v'; //keymap[DIK_VOLUMEDOWN] = ; //keymap[DIK_VOLUMEUP] = ; keymap[DIK_W] = 'w'; //keymap[DIK_WAKE] = ; //keymap[DIK_WEBBACK] = ; //keymap[DIK_WEBFAVORITES] = ; //keymap[DIK_WEBFORWARD] = ; //keymap[DIK_WEBHOME] = ; //keymap[DIK_WEBREFRESH] = ; //keymap[DIK_WEBSEARCH] = ; //keymap[DIK_WEBSTOP] = ; keymap[DIK_X] = 'x'; keymap[DIK_Y] = 'y'; // keymap[DIK_YEN] = ; keymap[DIK_Z] = 'z'; } /** * Convert a DInput Key (DIK_*) to a DDkey (DDKEY_*) constant. */ static byte dIKeyToDDKey(byte dIKey) { return keymap[dIKey]; } #if 0 // Currently unused. static DFILE *openKeymapFile(const char* fileName) { filename_t path; // Try with and without .DKM. strncpy(path, fileName, FILENAME_T_MAXLEN); if(!F_Access(path)) { // Try the path. M_TranslatePath(path, keyMapPath, FILENAME_T_MAXLEN); strncat(path, fileName, FILENAME_T_MAXLEN); if(!F_Access(path)) { strncpy(path, fileName, FILENAME_T_MAXLEN); strncat(path, ".dkm", FILENAME_T_MAXLEN); if(!F_Access(path)) { M_TranslatePath(path, keyMapPath, FILENAME_T_MAXLEN); strncat(path, fileName, FILENAME_T_MAXLEN); strncat(path, ".dkm", FILENAME_T_MAXLEN); } } } return F_Open(path, "rt"); } static boolean closeKeymapFile(DFILE *file) { if(file) F_Close(file); return true; } static int parseKeymapFile(DFILE *file, const char *fileName) { int warnCount = 0; char buf[512], *ptr; boolean shiftMode = false, altMode = false; int key, mapTo, lineNumber = 0; VERBOSE(Con_Message("parseKeymapFile: Parsing \"%s\"...\n", fileName)); do { lineNumber++; M_ReadLine(buf, sizeof(buf), file); ptr = M_SkipWhite(buf); if(!*ptr || M_IsComment(ptr)) continue; // Modifiers? if(!strnicmp(ptr + 1, "shift", 5)) { shiftMode = (*ptr == '+'); continue; } else if(!strnicmp(ptr + 1, "alt", 3)) { altMode = (*ptr == '+'); continue; } key = DD_KeyOrCode(ptr); if(key < 0 || key > 255) { Con_Message(" #%i: Invalid key %i.\n", lineNumber, key); warnCount++; } ptr = M_SkipWhite(M_FindWhite(ptr)); mapTo = DD_KeyOrCode(ptr); // Check the mapping. if(mapTo < 0 || mapTo > 255) { Con_Message(" #%i: Invalid mapping %i.\n", lineNumber, mapTo); warnCount++; } if(shiftMode) shiftKeyMappings[key] = mapTo; else if(altMode) altKeyMappings[key] = mapTo; else keyMappings[key] = mapTo; } while(!deof(file)); return warnCount; } boolean DD_LoadKeymap(const char *fileName) { DFILE *file; int warnCount; if(!(file = openKeymapFile(fileName))) { Con_Message("DD_LoadKeymap: A keymap file by the name \"%s\" could " "not be found.\n", fileName); return false; } // Any missing entries are set to the default. DD_DefaultKeyMapping(); Con_Message("DD_LoadKeymap: Loading \"%s\"...\n", fileName); warnCount = parseKeymapFile(file, fileName); if(warnCount > 0) Con_Message(" %i: Warnings.\n", warnCount); closeKeymapFile(file); Con_Message(" Loaded keymap \"%s\" successfully.\n", fileName); return true; } /** * Dumps the key mapping table to filename. */ void DD_DumpKeymap(const char *fileName) { int i; FILE *file; file = fopen(fileName, "wt"); for(i = 0; i < 256; ++i) { fprintf(file, "%03i\t", i); fprintf(file, !isspace(keyMappings[i]) && isprint(keyMappings[i]) ? "%c\n" : "%03i\n", keyMappings[i]); } fprintf(file, "\n+Shift\n"); for(i = 0; i < 256; ++i) { if(shiftKeyMappings[i] == i) continue; fprintf(file, !isspace(i) && isprint(i) ? "%c\t" : "%03i\t", i); fprintf(file, !isspace(shiftKeyMappings[i]) && isprint(shiftKeyMappings[i]) ? "%c\n" : "%03i\n", shiftKeyMappings[i]); } fprintf(file, "-Shift\n\n+Alt\n"); for(i = 0; i < 256; ++i) { if(altKeyMappings[i] == i) continue; fprintf(file, !isspace(i) && isprint(i) ? "%c\t" : "%03i\t", i); fprintf(file, !isspace(altKeyMappings[i]) && isprint(altKeyMappings[i]) ? "%c\n" : "%03i\n", altKeyMappings[i]); } fclose(file); Con_Message("DD_DumpKeymap: Current keymap was dumped to \"%s\".\n", fileName); } #endif HRESULT I_SetProperty(void *dev, REFGUID property, DWORD how, DWORD obj, DWORD data) { DIPROPDWORD dipdw; dipdw.diph.dwSize = sizeof(dipdw); dipdw.diph.dwHeaderSize = sizeof(dipdw.diph); dipdw.diph.dwObj = obj; dipdw.diph.dwHow = how; dipdw.dwData = data; return IDirectInputDevice8_SetProperty((LPDIRECTINPUTDEVICE8) dev, property, &dipdw.diph); } HRESULT I_SetRangeProperty(void *dev, REFGUID property, DWORD how, DWORD obj, int min, int max) { DIPROPRANGE dipr; dipr.diph.dwSize = sizeof(dipr); dipr.diph.dwHeaderSize = sizeof(dipr.diph); dipr.diph.dwObj = obj; dipr.diph.dwHow = how; dipr.lMin = min; dipr.lMax = max; return IDirectInputDevice8_SetProperty((LPDIRECTINPUTDEVICE8) dev, property, &dipr.diph); } boolean I_InitMouse(void) { HWND hWnd; HRESULT hr; if(ArgCheck("-nomouse") || novideo) return false; hWnd = Sys_GetWindowHandle(windowIDX); if(!hWnd) { Con_Error("I_InitMouse: Main window not available, cannot init mouse."); return false; } hr = IDirectInput_CreateDevice(dInput, &GUID_SysMouse, &didMouse, 0); if(FAILED(hr)) { Con_Message("I_InitMouse: Failed to create device (0x%x).\n", hr); return false; } // Set data format. hr = IDirectInputDevice_SetDataFormat(didMouse, &c_dfDIMouse2); if(FAILED(hr)) { Con_Message("I_InitMouse: Failed to set data format (0x%x).\n", hr); goto kill_mouse; } // Set behaviour. hr = IDirectInputDevice_SetCooperativeLevel(didMouse, hWnd, DISCL_FOREGROUND | DISCL_EXCLUSIVE); if(FAILED(hr)) { Con_Message("I_InitMouse: Failed to set co-op level (0x%x).\n", hr); goto kill_mouse; } // Acquire the device. IDirectInputDevice_Acquire(didMouse); // Init was successful. return true; kill_mouse: I_SAFE_RELEASE(didMouse); return false; } BOOL CALLBACK I_JoyEnum(LPCDIDEVICEINSTANCE lpddi, void *ref) { // The first joystick is used by default. if(!firstJoystick.dwSize) memcpy(&firstJoystick, lpddi, sizeof(*lpddi)); if(counter == joydevice) { // We'll use this one. memcpy(ref, lpddi, sizeof(*lpddi)); return DIENUM_STOP; } counter++; return DIENUM_CONTINUE; } boolean I_InitJoystick(void) { DIDEVICEINSTANCE ddi; int i, joyProp[] = { DIJOFS_X, DIJOFS_Y, DIJOFS_Z, DIJOFS_RX, DIJOFS_RY, DIJOFS_RZ, DIJOFS_SLIDER(0), DIJOFS_SLIDER(1) }; const char *axisName[] = { "X", "Y", "Z", "RX", "RY", "RZ", "Slider 1", "Slider 2" }; HWND hWnd; HRESULT hr; if(ArgCheck("-nojoy")) return false; hWnd = Sys_GetWindowHandle(windowIDX); if(!hWnd) { Con_Error("I_InitJoystick: Main window not available, cannot init joystick."); return false; } // ddi will contain info for the joystick device. memset(&firstJoystick, 0, sizeof(firstJoystick)); memset(&ddi, 0, sizeof(ddi)); counter = 0; // Find the joystick we want by doing an enumeration. IDirectInput_EnumDevices(dInput, DI8DEVCLASS_GAMECTRL, I_JoyEnum, &ddi, DIEDFL_ALLDEVICES); // Was the joystick we want found? if(!ddi.dwSize) { // Use the default joystick. if(!firstJoystick.dwSize) return false; // Not found. Con_Message("I_InitJoystick: joydevice = %i, out of range.\n", joydevice); // Use the first joystick that was found. memcpy(&ddi, &firstJoystick, sizeof(ddi)); } // Show some info. Con_Message("I_InitJoystick: %s\n", ddi.tszProductName); // Create the joystick device. hr = IDirectInput8_CreateDevice(dInput, &ddi.guidInstance, &didJoy, 0); if(FAILED(hr)) { Con_Message("I_InitJoystick: Failed to create device (0x%x).\n", hr); return false; } // Set data format. if(FAILED(hr = IDirectInputDevice_SetDataFormat(didJoy, &c_dfDIJoystick))) { Con_Message("I_InitJoystick: Failed to set data format (0x%x).\n", hr); goto kill_joy; } // Set behaviour. if(FAILED (hr = IDirectInputDevice_SetCooperativeLevel(didJoy, hWnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND))) { Con_Message("I_InitJoystick: Failed to set co-op level (0x%x: %s).\n", hr, I_ErrorMsg(hr)); goto kill_joy; } // Set properties. for(i = 0; i < sizeof(joyProp) / sizeof(joyProp[0]); i++) { if(FAILED (hr = I_SetRangeProperty(didJoy, DIPROP_RANGE, DIPH_BYOFFSET, joyProp[i], IJOY_AXISMIN, IJOY_AXISMAX))) { if(verbose) Con_Message("I_InitJoystick: Failed to set %s " "range (0x%x: %s).\n", axisName[i], hr, I_ErrorMsg(hr)); } } // Set no dead zone. if(FAILED(hr = I_SetProperty(didJoy, DIPROP_DEADZONE, DIPH_DEVICE, 0, 0))) { Con_Message("I_InitJoystick: Failed to set dead zone (0x%x: %s).\n", hr, I_ErrorMsg(hr)); } // Set absolute mode. if(FAILED (hr = I_SetProperty(didJoy, DIPROP_AXISMODE, DIPH_DEVICE, 0, DIPROPAXISMODE_ABS))) { Con_Message ("I_InitJoystick: Failed to set absolute axis mode (0x%x: %s).\n", hr, I_ErrorMsg(hr)); } // Acquire it. IDirectInputDevice_Acquire(didJoy); // Initialization was successful. return true; kill_joy: I_SAFE_RELEASE(didJoy); return false; } void I_KillDevice(LPDIRECTINPUTDEVICE8 *dev) { if(*dev) IDirectInputDevice8_Unacquire(*dev); I_SAFE_RELEASE(*dev); } static boolean I_InitKeyboard(void) { HWND hWnd; HRESULT hr; hWnd = Sys_GetWindowHandle(windowIDX); if(!hWnd) { Con_Error("I_Init: Main window not available, cannot init keyboard."); return false; } // Create the keyboard device. hr = IDirectInput_CreateDevice(dInput, &GUID_SysKeyboard, &didKeyb, 0); if(FAILED(hr)) { Con_Message("I_Init: Failed to create keyboard device (0x%x).\n", hr); return false; } // Setup the keyboard input device. hr = IDirectInputDevice_SetDataFormat(didKeyb, &c_dfDIKeyboard); if(FAILED(hr)) { Con_Message("I_Init: Failed to set keyboard data format (0x%x).\n", hr); return false; } // Set behaviour. hr = IDirectInputDevice_SetCooperativeLevel(didKeyb, hWnd, DISCL_FOREGROUND | DISCL_NONEXCLUSIVE); if(FAILED(hr)) { Con_Message("I_Init: Failed to set keyboard co-op level (0x%x).\n", hr); return false; } // The input buffer size. hr = I_SetProperty(didKeyb, DIPROP_BUFFERSIZE, DIPH_DEVICE, 0, KEYBUFSIZE); if(FAILED(hr)) { Con_Message("I_Init: Failed to set keyboard buffer size (0x%x).\n", hr); return false; } // We'll be needing the DIKey to DDKey translation table. initDIKeyToDDKeyTlat(); return true; } /** * Initialize input. * * @return @c true, if successful. */ boolean I_Init(void) { HRESULT hr; if(initIOk) return true; // Already initialized. // We'll create the DirectInput object. The only required input device // is the keyboard. The others are optional. dInput = NULL; if(FAILED (hr = CoCreateInstance(&CLSID_DirectInput8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput8, &dInput)) || FAILED(hr = IDirectInput8_Initialize(dInput, app.hInstance, DIRECTINPUT_VERSION))) { Con_Message("I_Init: DirectInput 8 init failed (0x%x).\n", hr); // Try DInput3 instead. // I'm not sure if this works correctly. if(FAILED (hr = CoCreateInstance(&CLSID_DirectInput, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectInput2W, &dInput)) || FAILED(hr = IDirectInput2_Initialize(dInput, app.hInstance, 0x0300))) { Con_Message ("I_Init: Failed to create DirectInput 3 object (0x%x).\n", hr); return false; } Con_Message("I_Init: Using DirectInput 3.\n"); } if(!dInput) { Con_Message("I_Init: DirectInput init failed.\n"); return false; } if(!I_InitKeyboard()) return false; // We must have a keyboard! // Acquire the keyboard. IDirectInputDevice_Acquire(didKeyb); // Create the mouse and joystick devices. It doesn't matter if the init // fails for them. I_InitMouse(); I_InitJoystick(); initIOk = true; return true; } void I_Shutdown(void) { if(!initIOk) return; // Not initialized. // Release all the input devices. I_KillDevice(&didKeyb); I_KillDevice(&didMouse); I_KillDevice(&didJoy); // Release DirectInput. IDirectInput_Release(dInput); dInput = 0; if(keymap) M_Free(keymap); keymap = NULL; initIOk = false; } boolean I_MousePresent(void) { return (didMouse != 0); } boolean I_JoystickPresent(void) { return (didJoy != 0); } /** * Copy n key events from the device and encode them into given buffer. * * @param evbuf Ptr to the buffer to encode events to. * @param bufsize Size of the buffer. * * @return Number of key events written to the buffer. */ size_t I_GetKeyEvents(keyevent_t *evbuf, size_t bufsize) { DIDEVICEOBJECTDATA keyData[KEYBUFSIZE]; DWORD i, num = 0; BYTE tries; BOOL acquired; HRESULT hr; if(!initIOk) return 0; // Try two times to get the data. tries = 1; acquired = FALSE; while(!acquired && tries > 0) { num = KEYBUFSIZE; hr = IDirectInputDevice_GetDeviceData(didKeyb, sizeof(DIDEVICEOBJECTDATA), keyData, &num, 0); if(SUCCEEDED(hr)) { acquired = TRUE; } else if(tries > 0) { // Try to reacquire. IDirectInputDevice_Acquire(didKeyb); tries--; } } if(!acquired) return 0; // The operation is a failure. // Get the events. for(i = 0; i < num && i < bufsize; ++i) { evbuf[i].event = (keyData[i].dwData & 0x80? IKE_KEY_DOWN : IKE_KEY_UP); // Use the table to translate the scancode to a ddkey. evbuf[i].ddkey = dIKeyToDDKey(keyData[i].dwOfs); } return (size_t) i; } void I_GetMouseState(mousestate_t *state) { static BOOL oldButtons[8]; static int oldZ; DIMOUSESTATE2 mstate; DWORD i; BYTE tries; BOOL acquired; HRESULT hr; memset(state, 0, sizeof(*state)); // Has the mouse been initialized? if(!didMouse || !initIOk) return; // Try to get the mouse state. tries = 1; acquired = false; while(!acquired && tries > 0) { hr = IDirectInputDevice_GetDeviceState(didMouse, sizeof(mstate), &mstate); if(SUCCEEDED(hr)) { acquired = true; } else if(tries > 0) { // Try to reacquire. IDirectInputDevice_Acquire(didMouse); tries--; } } if(!acquired) return; // The operation is a failure. // Fill in the state structure. state->x = (int) mstate.lX; state->y = (int) mstate.lY; /** * We need to map the mouse buttons as follows: * DX : Deng * (left) 0 > 0 * (right) 1 > 2 * (center) 2 > 1 * (b4) 3 > 5 * (b5) 4 > 6 * (b6) 5 > 7 * (b7) 6 > 8 * (b8) 7 > 9 */ { static const int buttonMap[] = { 0, 2, 1, 5, 6, 7, 8, 9 }; for(i = 0; i < 8; ++i) { BOOL isDown = (mstate.rgbButtons[i] & 0x80? TRUE : FALSE); int id; id = buttonMap[i]; state->buttonDowns[id] = state->buttonUps[id] = 0; if(isDown && !oldButtons[i]) state->buttonDowns[id] = 1; else if(!isDown && oldButtons[i]) state->buttonUps[id] = 1; oldButtons[i] = isDown; } // Handle mouse wheel (convert to buttons). if(mstate.lZ == 0) { state->buttonDowns[3] = state->buttonDowns[4] = 0; if(oldZ > 0) state->buttonUps[3] = 1; else if(oldZ < 0) state->buttonUps[4] = 1; } else { if(mstate.lZ > 0 && !(oldZ > 0)) { state->buttonDowns[3] = 1; if(state->buttonDowns[4]) state->buttonUps[3] = 1; } else if(mstate.lZ < 0 && !(oldZ < 0)) { state->buttonDowns[4] = 1; if(state->buttonDowns[3]) state->buttonUps[4] = 1; } } oldZ = (int) mstate.lZ; } } void I_GetJoystickState(joystate_t *state) { static BOOL oldButtons[IJOY_MAXBUTTONS]; // Thats a lot of buttons. DWORD tries, i; DIJOYSTATE dijoy; BOOL acquired; HRESULT hr; memset(state, 0, sizeof(*state)); // Initialization has not been done. if(!didJoy || !usejoystick || !initIOk) return; // Some joysticks need to be polled. IDirectInputDevice8_Poll(didJoy); tries = 1; acquired = FALSE; while(!acquired && tries > 0) { hr = IDirectInputDevice8_GetDeviceState(didJoy, sizeof(dijoy), &dijoy); if(SUCCEEDED(hr)) { acquired = TRUE; } else if(tries > 0) { // Try to reacquire. IDirectInputDevice8_Acquire(didJoy); tries--; } } if(!acquired) return; // The operation is a failure. state->numAxes = 8; state->axis[0] = (int) dijoy.lX; state->axis[1] = (int) dijoy.lY; state->axis[2] = (int) dijoy.lZ; state->axis[3] = (int) dijoy.lRx; state->axis[4] = (int) dijoy.lRy; state->axis[5] = (int) dijoy.lRz; state->axis[6] = (int) dijoy.rglSlider[0]; state->axis[7] = (int) dijoy.rglSlider[1]; state->numButtons = 32; for(i = 0; i < IJOY_MAXBUTTONS; ++i) { BOOL isDown = (dijoy.rgbButtons[i] & 0x80? TRUE : FALSE); state->buttonDowns[i] = state->buttonUps[i] = 0; if(isDown && !oldButtons[i]) state->buttonDowns[i] = 1; else if(!isDown && oldButtons[i]) state->buttonUps[i] = 1; oldButtons[i] = isDown; } state->numHats = 4; for(i = 0; i < IJOY_MAXHATS; ++i) { DWORD pov = dijoy.rgdwPOV[i]; if((pov & 0xffff) == 0xffff) state->hatAngle[i] = IJOY_POV_CENTER; else state->hatAngle[i] = pov / 100.0f; } } /** * Console command to write the current keymap to a file. */ #if 0 // Currently unused. D_CMD(DumpKeyMap) { DD_DumpKeymap(argv[1]); return true; } #endif /** * Console command to load a keymap file. */ #if 0 // Currently unsued. D_CMD(KeyMap) { DD_LoadKeymap(argv[1]); return true; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/include/0000755000175000017500000000000011523516205020715 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/include/resource.h0000644000175000017500000000074411357170242022724 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by Doomsday.rc // #define IDI_MAIN 101 #define IDI_DOOMSDAY_ICON 106 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 117 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1005 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/win32/include/dd_winit.h0000644000175000017500000000320011357170242022664 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Kernen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_winit.h: Win32 Initialization. */ #ifndef __DOOMSDAY_WINIT_H__ #define __DOOMSDAY_WINIT_H__ #include "dd_pinit.h" #include #define MAINWCLASS "DoomsdayMainWClass" typedef struct { HINSTANCE hInstance; LPCSTR className; BOOL suspendMsgPump; // Set to true to disable checking windows msgs. BOOL userDirOk; HINSTANCE hInstGame; // Instance handle to the game DLL. HINSTANCE hInstPlug[MAX_PLUGS]; // Instances to plugin DLLs. GETGAMEAPI GetGameAPI; } application_t; extern uint windowIDX; // Main window. extern application_t app; void DD_Shutdown(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/0000755000175000017500000000000011523516205017075 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/network.txt0000644000175000017500000003455411357170241021343 0ustar keeskees Multiplayer Games With Doomsday =============================== by Jaakko Kernen 04/02/2002 For version 1.6.0 of the engine; see end of file for more info. CONTENTS: 1. Using The GUI 2. Using The Console 3. "Net" Console Command 4. Troubleshooting 5. Tips Using DirectPlay, the Doomsday engine is capable of multiplayer games over the Internet, a local area network (LAN), a modem or a serial link. This document describes how to use the Server and Client setup screens and the "net" console command, which can also be used to setup and configure network games. Please make sure your DirectX drivers are recent enough (at least version 6.0). ====================================================================== 1. USING THE GUI The graphical user interface provided by Doomsday offers a simple way to host and join multiplayer games. It can usually be accessed via the "Multiplayer" menu. Use of the setup screens should be self-explanatory. With TCP/IP, use port number zero. If you're behind a firewall, open a port of your choice and set its number in the TCP/IP protocol setup screen. Don't use the same port number that's used by the server you will be connecting to, or the master server's port number (10123). ====================================================================== 2. USING THE CONSOLE OPERATING A NON-DEDICATED SERVER: 1. Configure the server by setting proper values for the console variables "server-name", "server-info", "server-game-map", "server-game-episode", "server-game-skill" etc. 2. Initialize the service provider, i.e. the network protocol. First set the service provider's configuration variables, for example TCP/IP's "net-ip-port". Then give the network initialization command, for instance "net init tcpip". 3. Start the server with the command "net server start". 4. Use the command "setmap" to change the level at any time. "setcolor" will change your player color. I'll let you guess what "setname" does. 5. The command "net server close" will shut down the server and disconnect all clients. DEDICATED SERVERS: You start a dedicated server by using the "-dedicated" command-line option (more information about command line options in CmdLine.txt). The game begins but all you'll see is a text mode representation of the console. You can now start the server exactly like a non- dedicated one, but you don't have to worry about your name and player color because the server naturally hasn't got a player when running in dedicated mode. You can place the init commands in autoexec.cfg for convenience. Note: Player limit is 15 on dedicated servers. CLIENT MODE: Connecting to a server as a client is quite straightforward. Before doing anything it's a good idea to make sure your player name and color are what you want them to be. You can use the commands "setname" and "setcolor" even when off-line. Notice that you can use your player number as a color if you do "setcolor 4" (both Doom and Heretic have four player colors: 0-3). Hexen has eight colors, so you'll need to use "setcolor 8". This means your color will be chosen automatically following the same logic as in the original Doom, Heretic and Hexen. 1. Set the protocol's configuration variables, for example "net-ip-address" and "net-ip-port" with the TCP/IP protocol. TCP/IP notes: The port should be zero if you're not behind a firewall, or some specific port of your choice (you'll need to open it) if you are behind a firewall. You can't use the same port number as the server, nor can you use the master server's port number 10123. 2. Initialize the protocol with the "net init (service)" command. 3. Issue the command "net search" as many times as it takes to see the server you're looking for (usually two times). 4. "net connect (server number)" will connect you to the server. 5. "net disconnect" will disconnect you. ====================================================================== 3. "NET" CONSOLE COMMAND net init (service) ------------------ (service) is one of: tcpip (or tcp/ip), ipx, modem or serial. Initializes the network driver for use with the specified service provider. This command must be given before any of the other network commands. To make things easier, you could for example place a "net init ipx" in your autoexec.cfg so the IPX network driver is automatically initialized when the Doomsday engine is started. If you want to change the service provider at runtime, you must first use "net shutdown" and then initialize the provider you want. net shutdown ------------ Shuts down the network driver. You don't have to use this command unless you mean to change the service provider at runtime. net info -------- Displays the current network settings along with some debug information. net modems ---------- If the Modem service provider is in use, this command displays a list of available modems. Use "net modem (num)" to select one from the list. net tcpip address (addr) ------------------------ Before you can connect to a server using TCP/IP, you need to specify the server's IP address. For example: "net tcp/ip address 127.0.0.1". The program winipcfg can be used to find out your own IP address, if your computer is going to be a server (winipcfg supposedly comes with Windows). If the IP address of the server you frequently connect to doesn't change, it's good to place this command into autoexec.cfg. net tcpip port (num) -------------------- If necessary, this command can be used to set the port to use when connecting. Leave to zero if you know nothing about TCP/IP ports. net modem (num) --------------- Selects the active modem from the list displayed by "net modems". You only need to issue this command if you're using the Modem service provider. net modem phone (num) --------------------- Sets the phone number to dial to if connecting to a server using the Modem service provider. You must set the phone number before using the command "net servers". net serial com (num) -------------------- Sets the COM port to use with the Serial Link service provider. Notice that usually this is the only config command you need to give with the Serial Link service. The other settings are given reasonable defaults when the service is initialized. net serial baud (setting) ------------------------- (setting) is one of: 110, 300, 600, 1200, 2400, 4800, 9600, 14400, 19200, 38400, 56000, 57600, 115200, 128000, 256000. net serial stop (setting) ------------------------- (setting) is 0-2: 0 = one stop bit 1 = 1.5 stop bits 2 = 2 stop bits net serial parity (setting) --------------------------- (setting) is 0-3: 0 = no 1 = odd 2 = even 3 = mark net serial flow (setting) ------------------------- (setting) is 0-4: 0 = no flow control 1 = software flow control (xon/xoff) 2 = hardware flow control with RTS 3 = hardware flow control with DTR 4 = hardware flow control with RTS and DTR net search ---------- If you want to connect to a server and you have configured your service provider with the necessary commands listed above, this command lists all the servers that can be found. Unless you're using the IPX service provider, there will be a slight delay before this command gives you the server list because DirectPlay has to first make the actual connection between the computers. It's best to keep repeating this command until you see the server you want. net connect (server number) --------------------------- Connects to the specified server. Only works after "net search" shows the number of the server (usually zero). net servers ----------- Connects to the master server and retrieves a list of running servers. You must set the console variable "net-master-address" before you can use this command. "net-master-port" should be zero, or a port of your choice (not 10123) if you're behind a firewall. SailorSat's master server IP: 137.226.156.135 net mconnect (server number received from master) ------------------------------------------------- Connects to the specified server. Only works after "net servers" has successfully ended and the list of servers has been printed in the console. net players ----------- When issued on the server, this command displays a list of all the connected players. For clients this command just displays the name of the server player and the client's own name. net disconnect -------------- Disconnects from the server you're currently connected to. Automatically done when you return to the operating system. You will naturally have to disconnect from a server if you want to connect to another one. net server start ---------------- If you want your computer to be a server, use this command after initializing the network driver. It will start the game so other players will be able to join. The server is responsible for choosing the game specific multiplayer settings, such as the map to play in. The server is able to change the current map with the console command "setmap". net server close ---------------- Stops the current game and disconnects all connected players. ====================================================================== 4. TROUBLESHOOTING ** Clients can't find the server (TCP/IP). Make sure the TCP/IP ports have been set correctly on both the server and the client. They must NOT be using the same port number! The exception is port zero, both the clients and the server can use it. Note that if you're behind a firewall, it might be blocking access to the ports DirectPlay uses by default, so specifying a specific port on both the server and the client might help. Again make sure different port numbers are used. ** Clients experience warping. If the server is warping clients back and forth when the clients move around, it might help to increase the maximum allowed coordinate difference on the server. It is controlled with the console variable "server-dif-max". Very large values (more than 128) should not be used. ** Gameplay is very lagged. It might help to increase the value of the console variable "server-frame-interval" on the server. Values from 1 to 3 should still result in a playable game. ====================================================================== 5. TIPS MAP ROTATION: Servers can set up a sequence of maps to cycle through automatically. This is done by defining the cycling rules with the console variable "server-game-mapcycle" and then, after starting the server, issuing the command "startcycle". The command "endcycle" ends map rotation. Note: You must enclose a string in quotes if it contains spaces. For example: > server-game-mapcycle "F:10 22 23" The cycling rules have a very simple format: (rule)[,(rule)] (map) [(map) [...] ] [(rule) ... ] (Brackets [ and ] enclose optional parts here.) (rule) can be either "Frags:X" or "Time:X", where X is either the maximum number of frags or maximum amount of time in minutes. The words "Frags" and "Time" can be abbreviated down to one letter. The comma between rules can be replaced with a semicolon, a plus character, a forward slash or a backslash. Map numbers always consist of two digits. Either or both digits of a map number can be replaced with an asterisk (*), which makes the server replace it with a random number. It's not that difficult, really. Take a look at the examples: "F:10 11 12 13 14 2* T:15,F:5 37" The cycle consists of maps E1M1, E1M2, E1M3, E1M4, a random map from the second episode and E3M7 (assuming this is not Hexen or Doom II). For the first five maps the rule for changing the map is a maximum of 10 frags. The last map (E3M7) will end when either 15 minutes has passed or someone gets 5 frags. "Frag:5 ** 25 24 23 Tim:1 11" The cycle consists of a completely random map, E2M5, E2M4, E2M3 and E1M1. The first four maps will end when someone gets 5 frags. The last map (E1M1) ends after one minute of gameplay. The extra spaces between the map numbers are ignored. REMOTE ACCESS TO SERVER: Clients are able to create a remote connection to the server's console. The server can set a password with the console variable "server-password". When a client issues the "login" console command, a remote connection is started. If the server has a password, it must be given to "login" as an argument, for instance "login foobar". After logging in any consequent commands are executed on the server's console. The remote connection can be terminated with the "logout" command. KICKING CLIENTS OUT: Servers can use the console command "kick" to get rid of unwanted players. The number of the player to kick out is given as an argument, for instance "kick 2". Player numbers can be found out with the "net info" command. USING DMASTER: DMaster is a simple master server program that can be used to keep track of all the running Doomsday servers on the Internet. Clients can ask the master for a list of servers. Use the console variables "net-master-address" and "net-master-port" to define the master server's IP address and TCP/UDP port. Port number zero is DirectPlay's autodetection port, it should work under most conditions. Before starting a server, set the cvar "server-public" to one to allow the server to inform the master of its existance. After "net init (something)", clients can use the console command "net servers" to send a server list request to the master. The returned list of servers has indices, use "net mconnect (index)" to connect to one of the listed servers. ====================================================================== The Doomsday engine is written by Jaakko Kernen, based on the source code of Raven Software's Hexen 1.1. Many thanks to the fine folks at Raven Software and id Software for releasing the source code. http://www.doomsdayhq.com/ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/changelog.txt0000644000175000017500000015014511357170241021574 0ustar keeskees Doomsday Engine Change Log ========================== Legend: + added, - fixed, * improved/changed *** *** -=- THIS CHANGELOG IS DEPRECATED -=- *** *** More recent history is at the Doomsday Engine Wiki: *** http://dengine.net/dew/index.php?title=Category:Releases *** Version 1.9.0 ------------- API: + DMU (Doomsday Map Update): map data objects are no longer directly accessible from plugins; all changes go through DMU, and notifications are routed to the correct places inside the engine for efficient operation User Interface: * tweaks to the console appearance (new defaults for background picture, color, and alpha) + console uses the Doomsday title bar, which is visible in the other UI screens * console: game information texts moved to the title bar + control panel UI fades away to display the game view when adjusting gamma, contrast, and brightness + control panel offers 16:10 resolutions - sliders now eat up/down keys (so the user isn't confused when the focus jumps to some other control when up/down is pressed in a slider) - game view window is now resized in the ticker - cursor offsets in menus, and save/load items + new console controls: F5: Clear console text buffer Alt + C: Clear command line Shift + cursorleft/cursorright: Move cursor to start/end of the command line Delete: Delete the character under the cursor Insert: Toggle character insert input mode. When off - new replaces old Shift + Tab: Use "other" unknown word autocompletion mode Right arrow: a "command history fill" to the command line (ala DOS command prompt) when the cursor is at the end of the command line + cvar 'con-move-speed': (0 - 1.0f) speed of console opening/closing * improved: console history buffer uses different colours for items based on their type (yellow for commands, white for variables) Resources: * removed: Doomsday.wad is obsolete, all data is now loaded from Doomsday.PK3 + new fixed and variable-width fonts (with normal, bold, and light variants) Renderer: + bias lighting: direct sources and smooth sector lighting - fixed usage of GL_ATI_texture_env_combine3 (caused problems with rendering shiny surfaces) * slightly more pronounced fakeradio (default darkness changed from 1.0 to 1.2) + cvar 'rend-bias-grid-multisample': multisample factor used when determining sector to lightgrid mapping. Larger values increase accuracy at the expense of map load times. + light range compression: increase light in dark sectors/decrease light in bright sectors + cvar 'rend-fog-default': default fog algorithm + Flaremaps: loaded from "Data/FlareMaps" - used for custom halos on objects (see Readme for details) + surface colours: individual walls and planes can be given a unqiue color. Wall section surface colors are blended between sections to achieve color fades. Surface colors and fades can be used to accurately recreate Doom64 style lighting. + alpha'd/blended midtextures on twosided linedefs + flag 'LUMF_DONTTURNHALO': disable the view angle rotation of halos and flares for this luminous object. + blendmode: BM_ZEROALPHA (GL_ONE, GL_ZERO) "draw with no translucency" + cvar 'rend-sprite-mode': 1 = draw sprites and masked walls with hard edges - fixed: light & halo not centered to sprite correctly (BatmanTC, wall torches) - fixed: mobj shadows sometimes rendered above the object casting the shadow - fixed: animated textures/flats would flicker after a console RESET - fixed: pegged middle textures "bouncing" on moving planes + cvar 'rend-dev-mobj-bbox': debugging aid - render mobj bounding boxes (sized to match the box used for collision detection) for debug. + cvar 'rend-dev-cull-subsectors': disable non-visible subsector culling for debug. + cvar 'rend-glow-scale': multiplier for wall glow height Map Data: * optimized allocation and handling of runtime map data (zblocks, levelstatic blocks, fast alloc mode), reduced map setup times significantly * changed: expanded map structure element limits. * changed: expanded blockmap limits by enlarging BLOCKMAP data at runtime + ccmd 'listmobjs': print a list of the mobj ids + names (if set via DED) to the console. * changed: BSP data is no longer required to load maps if runtime node building is enabled (cvar 'bsp-build' = 1). This allows playing eg maps created by SLIGE without generating the BSP data prior to loading the map in Doomsday * improved: map load time greatly improved with large maps * improved: emulation of DOOM.exe faked sector-over-sector tricks * improved: sectors now have three sound origins (center, floor, ceiling). Sector sounds are played from the most appropriate source. * improved: fakeradio now handles complex geometry and DOOM.exe tricks better * improved: fakeradio wall shadows are now affected by plane glows and the sky - fixed: missing textures/flats nolonger cause a fatal error. Surfaces with an unknown/missing textures/flats are now rendered with a "Missing" texture + unknown/missing textures/flats are reported in the console after loading a map + cvar 'blockmap-build': when/if new data is generated (default = when needed) Definitions: - removed fixed limit on the number of particle generator stages + Light -> Halo radius : radius of halo + Light -> Flare map: the flare map to use for this light's halo. Either a path and resource name OR a built-in flare resource number + Decoration -> Light -> Flare map: same as above for light decorations. * Decoration -> Light -> Flare texture: is depreciated. Use "Flare map" instead + Flag -> Info: text string containing a comment about this flag + DED reader: the "Copy"/"*" directive (used to initialize the current definition being read with the values of the last) can now be used with Mobj, State, Line and Sector (type) definitions. - fixed: minor memory leaks concerning definition data Engine: * memory zone expands as necessary - removed the "-maxzone" option as obsolete + option '-vdmap': map files in one directory to another directory (virtual directory mapping) + PK3 path mapping: files in 'keyword-named' folders in the root of a PK3 mapped to directories (see Readme for details) + subdirectory "Auto" of the runtime directory mapped automatically to both "Defs//Auto" and "Data//Auto" + new DFN font format that supports RGBA bitmaps + DeHackED patches (.deh files) are now loaded automatically from Data/Game/Auto and from the root folder in PK3/ZIP archives. - removed fixed limit on the number of opened files - less chance of file name collisions thanks to CRC32 in Dir_FileID - fixed: crash during startup when running with extra verbosity - fixed: vsprintf security vulnerabilities (buffer overflow) on all platforms Thanks to the Gentoo crew, Florian Westphal and Alexey Dobriyan for their part in helping to resolve these issues. * changed: always do a full texture reset after using the "lowres" ccmd * changed: cameras can now move above/below the ceiling/floor unrestricted. - fixed: auxiliary lump cache not checked for lump names when searching Input/Controllers: + binding classes: multiple commands can be bound to the same event + ccmd 'enablebindclass': Enable/disable/toggle binding classes or view their status + ccmd 'listbindclasses': Print a list of available binding classes * ccmd 'listbindings': List bindings in a specific binding class (eg 'listbindings map') * ccmd 'bind': Bind a command for a specific binding class to a key/button (eg 'bind map +f follow') * ccmd 'delbind': Delete a binding in a specific binding class (eg 'delbind map mpanup') All Games: + game status cvars read-only cvars that show the status of various player/game values ('player-health' 'map-name' etc) + automap options menu + weapons options menu + customisable weapon change order preferences: via weapons menu and cvars + cvar 'player-weapon-nextmode': use custom order for next/previous weapon cycle * changed: Automatic weapon switching has two modes: 1= If better 2= Always + The level title drawn when entering a map is now drawn with the patch used during intermissions (eg "WILV01") if it has been replaced in a PWAD. These custom patches take priority over patch replacement strings. + The level title patch draw during intermissions is drawn using the name set in the MapInfo defintion for the level. Intermission patches have priority over patch replacement strings. * Improved menu "Patch Replacement" feature to better support PWADS with custom menu patches + menu widget for changing colors + cvars 'msg-color-x': Color used for HUD messages + cvar 'msg-align': Set the horizontal alignment of HUD messages + Fullscreen view with no HUD + Fullscreen view with 'floating' status bar + cvar 'hud-status-alpha': Alpha value of statusbar background + cvar 'hud-status-icon-a': Alpha value of statusbar icons/counters + cvar 'hud-color-a': Alpha value of fullscreen HUD counters + cvar 'hud-icon-alpha': Alpha value of fullscreen HUD icons + cvars 'menu-color2-X': Secondary colors used for menu text + cvar 'menu-slam': 'Slam' menu when opening/closing + cvar 'map-huddisplay': Set the HUD display mode while in the automap (0 = none, 1 = current HUD, 2 = statusbar) + cvar 'menu-quick-ask': Ask me to confirm when quick saving/loading + cvar 'server-game-monster-meleeattack-nomaxz': to disable the fix added in the lxDoom source release to prevent monsters melee attacks having infinite z range. + cvar 'server-game-radiusattack-nomaxz': all radius attacks are infinitely tall in netgames + menu-fog mode 3: "Grey fog" + menu-fog mode 4: "Darken" * cheat 'reveal': 4 = show subsectors in automap * removed fixed limit on the number of active plats * removed fixed limit on the number of active switches * removed MAX_ADJOINING_SECTORS fixed limit * changed cvar 'msg-blink': number of tics to blink before fading to normal * changed cvar 'menu-patch-replacement': 2= Use built-in patch replacement when available * Improved cfg consistency between games * Automap keys are bindable * Automap colors can be customised via console, cfg files and the menu. * Menu navigation keys are bindable * Widget/Message response keys are bindable * Save & Load slots are now sync'd in the menu * changed: cvar 'ctl-look-speed' is now specified using a float value * changed: ccmd 'spawnmobj' now accepts the mobj name as well as the mobj id + cvar 'ctl-turn-speed': controls player turn rate - fixed: alignment in view border patch drawing jDoom: + DOOM.exe compatibility options/fixes maxskulls: remove max LostSoul spawn limit on Pain Elementals (off by default) skullsinwalls: prevent LostSouls from being spawned inside walls (on by default) raiseghosts: prevent Archviles from raising ghosts (on by default) anybossdeath666: The death of ANY boss monster triggers a 666 special (off by default) monsters-stuckindoors: Monsters can get stuck in doortracks (off by default) objects-hangoverledges: Only some objects can hang over tall ledges (on by default) objects-clipping: Use EXACTLY DOOM's clipping code (off by default) zombiescanexit: Zombie players can exit levels (off by default) player-wallrun-northonly: Players can only wallrun North (off by default) objects-falloff: Objects fall under their own weight (on by default) + support for most of jHeretic's MF2_ flags: includes floorclip, floatbob etc + support the "skill 0 trick" + BOOM THING flags: "Not Deathmatch","Not Coop" supported + BOOM LINEDEF flags: "Pass Thru", "Any Trigger" supported "Any Trigger" overrides XG activation type requirements unless the "ltf2_override_any" flag is set in Flags2 + BOOM "ANIMATED" lump support + BOOM "SWITCHES" lump support + ccmd 'suicide': commit suicide in non deathmatch games + ccmd 'exitlevel': exit the current level via the normal exit and go to the intermission + cvar 'map-babykeys': show key locations in the automap on easy skill + cvar 'hud-face': show Doom Guy's face in the fullscreen HUD + cvar 'server-game-mod-damage': Enemy (mob) damage modifier, multiplayer (1..100) + cvar 'server-game-mod-health': Enemy (mob) health modifier, multiplayer (1..20) + cvar 'server-game-respawn-monsters-nightmare': monsters respawn in Nightmare skill + cvar 'server-game-bfg-freeaim': Allow free-aim with BFG in multiplayer games + cvar 'player-berserkswitch': automatically switch to fists when collected + cvar 'player-death-lookup': makes the player look upwards when killed - fixed: automatic weapon switching now works in Co-op games - fixed: voodoo doll spawning bug exhibited on maps such as caesar.wad + Thing -> flags2 'mf2_radiusattacknomaxz': z dimension is ignored when calculating if a radius attack hits a mobj with this attribute (in PIT_RadiusAttack). + DeHackED: 'Misc' patches are fully supported + value 'Player|Green Armor Class': armor class of the Green Armor pickup + value 'Player|Blue Armor Class': armor class of the Blue Armor pickup + value 'Player|God Health': health displayed when in god mode + value 'Player|IDFA Armor': armor given with 'IDFA' cheat + value 'Player|IDKFA Armor': armor given with 'IDKFA' cheat + value 'Player|IDFA Armor Class': armor class given with 'IDFA' cheat + value 'Player|IDKFA Armor Class': armor class given with 'IDKFA' cheat + value 'MegaSphere|Give|Health': health given when MegaSphere collected + value 'SoulSphere|Give|Health': health given when SoulSphere collected + value 'SoulSphere|Give|Health Limit': max health when SoulSphere collected * ccmd 'give': number (0-NUMWEAPONS) = give an individual weapon (as if found) f = give the player the power of flight * removed fixed limit on number of boss brain spawnspots * removed fixed limit on number of archived mobjs - fixed: "Boss Brain doesn't die by rockets as easily" splash damage is considered to be infinetly tall when checking the boss brain - fixed: Doom2 MAP30 could not be completed with game-corpse-time = 1 - fixed: soundtarget data is now saved. Fixes bug where monsters would forget where they heard the player(s) after a save - fixed: tracer data is now saved. Fixes bug where the Archvile fire attack and the Revenant missile would loose their target when saving - fixed: animated textures in TNT and Plutonia were messed up. - fixed: DOOM logic error which prevented the GOTMEDINEED message from ever being used - fixed: DOOM inversed test which prevented the OUCH face from ever being used jHeretic: + Heretic.exe compatibility options/fixes monsters-stuckindoors: Monsters can get stuck in doortracks (off by default) objects-hangoverledges: Only some objects can hang over tall ledges (on by default) objects-clipping: Use EXACTLY DOOM's clipping code (off by default) player-wallrun-northonly: Players can only wallrun North (off by default) objects-falloff: Objects fall under their own weight (on by default) * Uses jDoom's Menu code All features, cvars, ccmds from jDoom supported * Uses jDoom's HUD message code (msg buffer) All features, cvars, ccmds from jDoom supported + BOOM "ANIMATED" lump support + BOOM "SWITCHES" lump support + ccmd 'suicide': commit suicide in non deathmatch games + ccmd 'hereticfont': Use the Heretic font in the console + ccmd 'exitlevel': exit the current level via the normal exit and go to the intermission + cvar 'map-babykeys': show key locations in the automap on easy skill + cvar 'hud-artifact': show the current artifact in the fullscreen HUD + cvar 'hud-keys': show keys in the fullscreen HUD + cvar 'hud-health': show health in the fullscreen HUD + cvar 'server-game-mod-damage': Enemy (mob) damage modifier, multiplayer (1..100) + cvar 'server-game-mod-health': Enemy (mob) health modifier, multiplayer (1..20) + cvar 'hud-inventory-timer': number of tics before the inventory auto-hides + Added patches for missing ASCII characters to jHeretic.wad - fixed: lineattack weapons hit planes - fixed: various alignment glitches in statusbar drawing - fixed: float bobbing would not activate until the player moved in the X/Y dimension(s). - fixed: soundtarget data is now saved. Fixes bug where monsters would forget where they heard the player(s) after a save. + Thing -> flags2 'mf2_radiusattacknomaxz': z dimension is ignored when calculating if a radius attack hits a mobj with this attribute (in PIT_RadiusAttack). * removed fixed limit on number of archived mobjs * changed: command-line option -ravpic is now -devparm jHexen: * Uses jDoom's Menu code All features, cvars, ccmds from jDoom supported * Uses jDoom's HUD message code (msg buffer) All features, cvars, ccmds from jDoom supported + ccmd 'hexenfont': Use the Hexen font in the console + cvar 'hud-artifact': show current artifact in fullscreen HUD + cvar 'hud-health': show health in fullscreen HUD + cvar 'hud-inventory-timer': number of tics before the inventory auto-hides + Added patches for missing ASCII characters to jHexen.wad - fixed: players would continue receiving damage after a telporting out of a damaging sector with a Chaos Device, until they moved. * changed: command-line option -ravpic is now -devparm XG: * changed: the DD_XGDATA lump is now depreciated. + Line (type): XG line type definitions now have alternate names for the iparms. (see wiki for more details - http://dew.dengine.net) + line class "ltc_line_teleport": BOOM-style line->line (silent) teleport + line class "ltc_teleport" * improved: line class "ltc_end_level": specify next level on exit (Ip3) * improved: line classes "ltc_wall_texture" & "ltc_plane_texture": set the surface color, blendmode and alpha properties of the referenced surfaces. * improved: line class "ltc_wall_texture" -> Set Mid If None: add/remove midtextures on twosided linedefs. + Added more XG_Dev messages. Reference types are printed by name instead of ID. * fixed: bug that prevented sector chains from working correctly under certain circumstances (due to dummy activators in sector functions) * fixed: XS_GetPlane - when a act_tag reference was specified it was incorrectly being compared to the regular sector tag during iteration. * fixed: XS_GetPlane was incorrectly referencing sector tag 0 when called during XS_Trav functions which implicitly set ref data to zero when used in conjunction with spref_tagged_ or spref_act_tagged_. Now checked with -1 and an XG_Dev warning message is printed. * changed: ltc_mimic_sector was using the line's Act Tag when the mimic target reference was set to SPREF_ACT_TAGGED_ This is the opposite to the way it works with all other classes which use these data references. New sprefs have been added which retain this functionality. IF YOU'VE USED SPREF_ACT_TAGGED_FLOOR/CEILING AS THE MIMIC TARGET REFERENCE IN YOUR PWAD: Your PWAD will no longer work as expected and you should update and redistribute it. * fixed: XSTrav_PlaneTexture - the XG_Dev message "couldn't find suitable" was printed even when a suitable reference WAS found. * fixed: ltc_plane_move sector type was incorrectly being set to type 0 when the move finished if no end type change was specified. Result was sectors "losing" their type after a plane move. + Line type -> Act type: Set line type on activation + Line type -> Deact type: Set line type on deactivation + Flag 'ltf2_override_any': override BOOM 'Any Trigger' Linedef flag + line->line references (lrefs): lref_none + line->plane references (lprefs): lpref_back_floor lpref_back_ceiling lpref_thing_exist_floors lpref_thing_exist_ceilings lpref_thing_none_floors lpref_thing_none_ceilings + sector->plane references (sprefs): spref_back_floor spref_back_ceiling + line->sector references (lsrefs): lsref_none lsref_back lsref_thing_exist lsref_thing_none + light level reference (lightref): lightref_back Multiplayer: - fixed: skill selection not working via Game Setup menu Linux: + SDL joystick support (by zachkeene) - fixed: disappearing enemies in jHeretic and jHexen (fix by zachkeene) * Build scripts require zip (package zip on Debian/Ubuntu) - fixed: fixed some segfaults caused by missing data in *Nix builds. Mac OS X: * optimized release builds now work correctly - fixed several endianness issues in model rendering, XG, WAV loading, buttons - fixed: network games (now compatible with Win + Linux) - fixed rendering of shiny models (multitex and non-multitex) - fixed many minor compilation issues Security: - fixed: CVE-2006-1618 buffer overflow. Version 1.8.6 ------------- + "Flats" external resource category: defaults to "Data/Game/Flats/" * external flats are searched first from "Data/Game/Flats/" * PK3s can now be compressed (normal ZIP files) * unlimited nesting of autoloads via Auto directory and virtual files + PK3 path mapping: files in the root of a PK3 mapped to the Auto directories (see Readme for details) + lump assembly prefixes (see Readme for details) + Reflection -> Min color: minimum RGB color for the reflection (to make the reflection visible even without regular sector light) - fixed: model file hash reset properly when running 'reset' - fixed: problem with multiple -file options SDL_mixer: * MUS data converted to MIDI is stored in the runtime directory instead of /tmp Mac OS X: + MiniStart launcher * music is played using QuickTime (MIDI problems resolved) - multiple endianness issues fixed in texture/PK3/model handling Version 1.8.5 ------------- + surface reflections (shiny effects) + 'Reflection' definition + cvar 'rend-tex-shiny': enable surface reflections + Model -> Sub -> Shiny reaction: how much shiny textures react to angle changes + cvar 'rend-model-shiny-strength': shininess factor for all models (0..1) + Model -> Sub -> Blending mode: select a blending mode (bm_* flag) + bm_* flags in Flags.ded (blending modes) + ccmds 'conopen', 'conclose', 'contoggle': open/close console prompt * detail textures can now use external resources instead of WAD lumps (Detail -> File) * external resources can be located in relation to Doomsday base path (e.g. Shiny map = "Data/LightMaps/Shine") - fixed: dynamic light clipping in the case where lights are in the same subsector with a polyobj jHexen: + cvar 'hud-scale': scaling factor for HUD graphics and messages Win32: + option '-nostwin': don't show the startup message dialog (quicker startup) * crashes are handled more gracefully - fixed: vcbuild.bat didn't include resources in Doomsday.exe and drD3D.dll, which meant that the startup window and the drD3D config dialog were missing Version 1.8.4 ------------- * shiny texture coordinates are calculated using a simplified algorithm - fixed: shiny texture coordinate 'warparound' artifact - fixed: FakeRadio hanged in maps with some unusual map geometry Win32: + vcbuild.bat: builds everything from the command line * built using Visual C++ Toolkit 2003, available from: http://msdn.microsoft.com/visualc/vctoolkit2003/ Version 1.8.3 ------------- + Generator -> Stage -> Spin resistance { 0 0 }: factors for slowing down particle spinning (0..1) - fixed: model skin wrapping - fixed: halo origin calculation for high-resolution sprites - keycode handling in console/UI didn't always use the keymap jDoom: - fixed: crushed barrels now explode correctly and don't become gibs Linux: * MIDI music player defaults to SDL_mixer's default implementation (DENG_MIDI_CMD can be used to specify an external player) * fixed-point math using inline assembler like in Windows (courtesy of Lukasz Stelmach) Mac OS X: * a native build that runs on Mac OS X 10.3 * now compiles with Xcode - fixed various glitches with regards to loading of plugins Version 1.8.2 ------------- - fixed: segfault when starting a new game during demo playback - fixed: instant camera position changes during demo playback - fixed: console font disappearance + added control panel setting for rend-tex-filter-smart - adjusted particle Z coordinate when touching a plane - fixed fatal error when building GL nodes for a map in the end of the data lump directory Mac OS X: - fixed endianness problem with MUS-to-MIDI conversion Version 1.8.1 ------------- * it is no longer possible to turn off camera smoothing - cvar 'rend-camera-smooth' was hidden - fixed: game event smoothing now operates seamlessly regardless of the framerate - fixed: camera position smoothing wasn't synced correctly to frames - fixed: segfault related to sight checking over large distances (e.g. TNT map 27) + dpMapLoad: glBSP 1.96 as a plugin, run on the fly when necessary + rend-halo-realistic: use only more realistic halos (slightly smaller, dimmer), no secondary lens flares; enabled by default - fixed: Map Info -> Execute - fixed: FakeRadio bug where vertical shadows were rendered above and under the left and right edge of an opening in a straight wall - GL must not be loaded at all in dedicated mode - file finder had problems descending into subdirectories - input events are processed immediately: mouse lag is gone both in the game and in the UI - mouse filter is more careful not to ever lose any mickeys - all pending ticcmds are always processed immediately (excessive buffering no longer a danger) - fixed several endianness issues to allow building on a big endian arch * tuned up handling of ticcmds during transfer from client to server * particle movement is smoothed (except flat particles that contact a surface) * mouse look is always as smooth as it can be * all games use the same keyboard look scheme (jDoom's was different) * framerate is measured more accurately + ccmd 'message': display a local game message Common: * more unified handling of ticcmds + cvar 'player-move-speed': player movement speed modifier (0..1) jDoom: - fixed: '-warp' made fonts disappear jHeretic/jHexen: - fixed: when a demo stops continue with a running InFine sequence Win32: - too many console messages caused a crash during startup (extra verbosity) - crash when starting in dedicated mode Linux: + environment variable DENG_MIDI_CMD: play MIDI music using this program (defaults to "timidity") + '--without-(game)' configuration option skips (game) + '--without-opengl' configuration option removes all OpenGL support from the build (for dedicated servers) - color adjustments are now working (vid-gamma et al.) - demo file names were formed incorrectly Mac OS X: - pretty much everything can be compiled and run on Mac OS X with the help of fink and Apple's X11 server (except netgames, don't go there) Version 1.8.0 ------------- - fixed: game clock must not be running while map is being loaded - fixed: mobj Z coordinate when sector has a fake floor Version 1.8.0-rc3 ----------------- * use TCP connection for sending reliable data (game setup, etc.) - ccmd 'listmaps' was missing - fixed: FakeRadio bug where narrow shadows stretch beyond parent edge - fixed: mouse wheel events in Linux - fixed: opening control panel in dedicated mode InFine: + 'XImage' command: set an external graphics resource to a Rect Version 1.8.0-rc2 ----------------- + control panel text has its own color (not just white) * maximum frame rate limited to 200 * movement of missiles and other such objects is now smoothed * network setup screens revised * modems, serial links and IPX no longer supported (only TCP/IP) - ccmd 'playsound' was missing - things didn't follow moving planes smoothly - fixed an input event processing bug that caused duplicated events Version 1.8.0-rc1 ----------------- ! Release Candidate ! features from alpha-2 and alpha-3 are *not included* * Linux now officially supported (no MIDI music, joysticks) + control panel settings for FakeRadio + rend-fakeradio-darkness * rend-camera-smooth now affects 3D model animation, monster movement * artifact bobbing (Heretic/Hexen) completely smooth * 3D model spinning completely smooth * key repeat uses milliseconds (input-key-delay) * network code uses TCP sockets and UDP packets, DirectPlay ditched - savegame directory creation bug fixed - PK3 reader supports files created with Info-ZIP that contain extra field data - OpenGL display resolution change sometimes didn't update viewport - FakeRadio shadows are not rendered when light amplification is active Version 1.8.alpha-3 ------------------- ! Alpha Release + multiple viewports + local players are automatically assigned to different viewports + ccmd 'viewgrid': set up the viewport grid + clientside turning/looking * basic toggle controls once again included in ticcmds * distinction between stick and pointer controller axes * engine handles all controls Version 1.8.alpha-2 ------------------- ! Alpha Release * controller axes can be bound to specific local players * engine handles all controls (incomplete) * 'walk' and 'sidestep' axis controls can be bound (partially implemented) + 'bindaxis' command: bind a controller axis to an axis control (e.g. "bindaxis mouse-y walk") - fixed: sound system (on Win32), may still crash during shutdown - removed obsolete settings from the Control Panel Version 1.8.alpha-1 ------------------- ! Alpha Release + Linux support + accurate measurement of time (variable-length ticks); game code still untouched, uses 35 Hz legacy timing * independent input->ticcmd generator (stub only) * now uses the SDL library (http://www.libsdl.org/) Renderer: + FakeRadio: simulated radiosity lighting (cvar 'rend-fakeradio') + smart texture filtering (modified hq2x, 'rend-tex-filter-smart') - removed smooth camera hack ('rend-camera-smooth') Network: * portable low-level implementation (TCP/UDP sockets), needs testing! Version 1.7.15 -------------- + merged some interesting stuff from 1.8/nix: FakeRadio, sky color * use the "no compression" hint when loading lightmaps * increased maximum number of particle generators to 256 - fixed State -> Execute definition patching jDoom: + option '-nodefaultfx': skip default Lights.ded and Particles.ded Version 1.7.14-4 ---------------- + cmd 'playsound': play a sound effect locally + Map Info -> Execute: execute a console command after map setup (i.e. also after loading a savegame) + Map Info -> Sky Model -> Execute: execute a console command every time the sky model's frame number changes + State -> Execute: execute a console command when a mobj enters this state (NOTE: player HUD weapons are not real mobjs, so this has no effect with psprite states) Version 1.7.14-3 ---------------- + cmd 'listmaps': print all loaded maps and the WAD files where they are from - fixed: 'df_worldtime' was behaving strangely - fixed: 873878: Ogg/Mp3 in PK3 Virtual Folder Structure Not Playing jDoom: + cvar 'menu-quitsound': play a random sound when quitting Version 1.7.14 -------------- ! Maintenance Release + Model -> Sub -> Skin file: file name of the skin (can be anything; use this if it isn't possible to use the model's skin list) + Map Info -> Sky Model -> Layer: associate sky model with a sky layer; model is hidden if sky layer is not enabled + Generator -> Submodel: submodel # to use as generator origin + particle generator sounds: Sound, Volume, Hit sound, Hit volume added to Generator -> Stage + Generator -> Init Vector Rnd: init-time random component of Vector + Generator -> Stage -> Force: linear force + model flag 'df_notexcomp': disable texture compression for all skins of the associated model + model flag 'df_worldtime': model's interpos depends on world time + generator flag 'gnf_srcdir': rotate particle vector + generator flag 'gnf_extra': additional generator for a mobj state + cvar 'rend-tex-filter': use bilinear filtering on textures * a particle generator can have up to 32 stages * models close to the viewpoint won't disappear * max number of data files increased from 128 to 1024 (-file) - fixed: crash when map doesn't have any REJECT data - fixed: confusion/crash when requesting a lump with no name - fixed: edge artifacts around translucent sprites - fixed: sfx sometimes pop with the default sound driver (DS8) - fixed: loading DEDs from virtual directories - fixed: particle center offset angle - fixed: loading order of 3D models (mixed up demon/spectre skins) - fixed: lighting on vertically inverted models - quietly allow the use of undefined sprite frames (object hidden) jDoom: * "Read This" screens are not affected by menu-scale, skull hidden jHeretic: - game can only be saved during normal game play - fixed: cycling down from Elvenwand skips Staff (bug 813773) jHexen: + lava and fire textures glow * support for the Hexen 4-level demo Version 1.7.13 -------------- ! Maintenance Release * model offset and scale are interpolated (Model -> Offset XYZ, Model -> Scale XYZ) * overridden model defs are no longer loaded at all (bug 760099) * number of screenshots is not limited to 100 * screenshot file names are selected according to game mode - fixed: semicolon in bindings (key name "smcln") - fixed: music volume = zero prevents songs from changing - fixed: halos flicker sometimes through doors - a shadow is not rendered if it would be above the object - fixed: crash when loading external resources of color-mapped sprites Network: - fixed: player gets stuck in enemies - fixed: player gets stuck in a moving plane (elevator, door) - fixed: crash in clmobj handling - fixed: recording demos with multiple local players - fixed: clientside jumping power, jumping enabled - fixed: player start spot selection (especially TNT/Plutonia) - fixed: mobj Z coordinates were sometimes incorrect on clientside - fixed: server didn't increase client's bandwidth rating, ever - fixed: WAD warning box in Client Setup screen was in the wrong place - fixed: halos weren't always displayed correctly on clientside drD3D: + option -triple: enable triple buffering in fullscreen mode XG: - XG should always be disabled on clientside jDoom: + cvar 'map-door-colors': show colors of locked doors in automap + cvar 'map-door-glow': locked doors have a glow around them (1=normal) * Plutonia/TNT will automatically set rend-sky-full - fixed: bullet puffs in face (bug 740767) - fixed: main menu item spacing too tight - fixed: STARMS was used in the status bar when in deathmatch jHeretic: + cvar 'player-jump-power' jHexen: + cvar 'player-jump-power' Version 1.7.12 -------------- + option -leaveramp: don't reset color settings back to previous values at shutdown + JWADs: IWAD supplements (uses normal WAD loading order) + Data\Graphics directory: Doomsday's graphics resources (UI textures) + cvars 'ui-cursor-width', 'ui-cursor-height': UI mouse cursor size + added new cvar controls to the Control Panel (e.g. multitex, HUD mirror) * the first incarnation of the Doomsday UI theme, "Gradient", was replaced with a much more polished theme, "Plastic" * UI mouse cursor size and movement depend on display resolution * music data will not be cached into the memory zone while loading (large MP3s wasted a lot of space) * paths that contain the base path are normally printed without the base - removed obsolete settings from Control Panel - removed detail texture maximum distance cvar and Control Panel slider - removed cvars 'rend-light-clip', 'rend-light-shrink' - fixed: possible crash in Con_Error() Definitions: + DED version 6: semicolons are optional (the default is 6) + added Defs/Doomsday.ded: include definitions shared by all games + 'Top map', 'Bottom map', 'Side map' added to Light defs and Decoration:Light defs (name of lightmap to use; empty means default, "-" is none) + particle types pt_modelNN: use 3D model ID = "ParticleNN" + particle flags ptf_zeroyaw, ptf_zeropitch, ptf_rndyaw, ptf_rndpitch + 'Frame', 'End frame', 'Spin' added to Generator:Stage + up to 32 sky models can be defined in a Map Info definition + added an ID key to the Model definition * flags can be defined using this syntax: Flags = flag1 | flag2 | flag3; (flag prefixes must be omitted) * Defs/Doomsday.ded is always read first * Flag definitions moved to Defs/Flags.ded * XG definitions moved to Defs/XG.ded * maximum number of submodels is now 8 * Map Info definitions can be copied * 'InFine' is an alternative name for the 'Finale' definition Network: - fixed: server increased a client's bandwidth rating too rapidly Sound: * sounds from PWADs are not replaced with automatic external resources Refresh: + named Model definitions (Model:ID), not assigned to any state + lightmap resources are read from the Data\x\LightMaps directory + texture/flat animation sequences defined using Group defs (Anim.ded) + "tgf_smooth": interpolate between steps in texture/flat animation + particle generator flag "gnf_group": triggered by all in the flat's animation group + particle generator flags "gnf_blendsub", "gnf_blendrsub": subtractive blending for particles + particle generator flags "gnf_blendmul", "gnf_blendimul": normal and inverse multiplicative blending for particles + option -nohighpat: disable high-resolution patches * weapon model skins are precached * texture/flat groups can be used purely for precaching * detail texture contrast is preprocessed: there will be multiple instances of the same texture with different contrast levels (needs a bit more memory but allows faster rendering) * 8-bit particle textures are interpreted as pure alpha data * PCX images aren't loaded redundantly from virtual files - fixed: PWAD test when loading highres flats and patches (-pwadtex) - fixed: particles sliding over ledges - fixed: Generator Center angle (Y) offset was ignored with mobj sources Renderer: + sky models + particle models + blending modes: subtract, reverse subtract, multiply, inverse multiply + cvar 'rend-glow-fog-bright': wall glow brightness in fog + cvar 'rend-model-shiny-multitex': render shiny skins using multitexturing + cvar 'rend-model-mirror-hud': mirror HUD weapon models + cvar 'rend-model-spin-speed': rotation speed for models with "df_spin" + cvar 'rend-dev-wireframe': render player view in wireframe mode + cvar 'rend-dev-freeze': stop updating rendering lists (for debugging) * renderer uses multitexturing for detail textures, dynamic lights, interpolated texture animation and model shiny skins * shiny skins are correctly masked by alpha in main skin * plane glow on models is stronger than before * if multitexturing is available, masked walls will get one dynamic light (previously masked walls were not lit by dynlights) * dynamic light polygons are no longer clipped * calculations to determine surfaces affected by a dynamic light are more accurate (light has a better chance to be visible) * light decoration brightness decreases as surface/view angle grows - removed option -maxor: clipper has now unlimited nodes - fixed: leaking lights (impossible route detection) - fixed: stray pixels along polygon edges in dynamically lit areas - fixed: detail texture blending when fog is enabled - fixed: object shadows weren't affected by fog - fixed: skymask holes in skyfixed sectors - fixed: shiny skins on HUD models - fixed: console text gibberish on the first time the console is drawn - fixed: cvar 'rend-tex' (render with textures) - fixed: shadows fade away smoothly at maximum distance drOpenGL: + support for multitexturing + NV_texture_env_combine4 or ATI_texture_env_combine3 required when rendering dynamic lights with multitexturing + support for SGIS_generate_mipmap + support for EXT_blend_subtract + support for EXT_texture_compression_s3tc + option -notexcomp: disable texture compression + option -novtxar: disable vertex arrays + option -nosgm: disable SGIS_generate_mipmap * vertex arrays are disabled by default if driver's OpenGL version is older than 1.3 (otherwise enabled) * texture compression disabled by default (use -texcomp to enable) drD3D: + support for multitexturing Games: + cvar 'server-game-cheat': allow cheat commands "god", "noclip", "give" in netgames jDoom: + "Patch Replacement" strings (see Defs\jDoom\Values.ded) + cvar 'menu-patch-replacement': enable or disable replacement strings + cvar 'menu-glitter': letters glow as they are typed in + fonts precached during startup + crosshair alpha slider added to the HUD menu + some light decorations (Doom1Lights.ded + BSTONE3, BRICKLIT) * titlescreen sequence defined as an InFine script (ID = "title") * menu text has properly sized capital letters - fixed: intermissions/finales in Plut/TNT jHeretic: + some light decorations (based on Isegrim's defs) * player mobj selector is set to match currently used weapon * titlescreen sequence defined as an InFine script (ID = "title") jHexen: + some light decorations (based on Isegrim's defs) * player mobj selector is set to match currently used weapon * titlescreen sequence defined as an InFine script (ID = "title") InFine: + cmd 'startinf (scriptid)' (and 'stopinf') + gradient rectangles + object rotation (pics, text objects, rectangles) + command "ScaleXY (handle) (x) (y)" + command "Rect (handle) (x) (y) (w) (h)" + command "FillColor (h) (TOP/BOTTOM/BOTH) (r) (g) (b) (a)" + command "EdgeColor (h) (TOP/BOTTOM/BOTH) (r) (g) (b) (a)" + condition "MODE:(game-mode)" + command "ELSE" + command "DO" ... ";" (nestable blocks) + command "PlayDemo (filename)" + command "Cmd (console command)" + command "OnKey (key-ident) (marker)": jump to marker when key pressed + command "UnsetKey (key-ident)" + commands "Events", "NoEvents": enable/disable interactive mode + commands "Trigger", "NoTrigger": enable/disable menu triggering mode * generic object commands: "Del", "X", "Y", "Sx", "Sy", "Scale", "Angle" "ScaleXY", "RGB", "Alpha" * old pic/text commands that should no longer be used: "DelPic", "DelText", "TextRGB", "TextAlpha", "Tx", "Ty", "TSx", "TSy", "TextScale" * InFine can run in overlay mode (e.g. during GS_LEVEL) * InFine states are nested (script -> demo -> script -> demo -> etc.) - fixed: "WaitText" timing with \w, \W, \p, \P - fixed: "SoundAt" volume XG: + line class "ltc_mimic_sector" + new sprefs + cvar 'xg-dev': print XG event messages to the console - fixed: sector floor/ceiling chain touch test Version 1.7.11 -------------- ! Bugfixes Only * revised server delta generation: fixed-size frames, prioritized contents, sounds are stored inside frames (not separate packets), redundant missile coordinates not sent * server refuses connection if new client's ID already in use * revised clientside handling of frames: collision detection for movement prediction, missiles hidden on impact * revised low-level networking: implement confirmed/ordered packets manually, detect duplicates, Huffman encoding (60%-70% compression) + cmd 'huffman': print Huffman efficiency and number of bytes sent * mobj translucency 0-255 (selector still overrides) * mobj floatbobbing is done by engine (clientside), DDMF_BOB added * client is allowed some movement while airborne (easier jumping) * by default, external resources are no longer loaded for textures from PWADs; use the -pwadtex option to change this (cvar 'rend-tex-external-always') * console command line cursor can be moved left and right * default key repeat interval is now 3 tics (was 4) * braces { and } are equivalent to quotes, e.g.: "alias init-map03 {after 1 {warp 5}}" * cmd 'listcmds' prints a description for each command + cmd 'toggle': toggle a cvar's value between zero and nonzero + cmd 'if': execute a command if the condition is true (tests cvar values) * max number of light decorations increased to 16 per texture - fixed: occlusion for planes exactly at eye-Z - fixed: client was sending too much data (now it's about 0.3 KB/s) - included DED files are read immediately after the Include directive has been encountered - fixed: pausing the game also stops spinning models, floatbob - external music was not loaded correctly from virtual files - fixed: clientside mobjs and players on moving planes - fixed: external sound resources reloaded every time the sound starts - fixed: tracking of currently playing sounds - fixed: floorclip values were restricted to 64 in mobj deltas - fixed: client stepup limit is now exactly 24 units - fixed: coord/offset problems if same sprite used in game and HUD - missing upper texture in a skyceiling sector replaced with the backsector's ceiling (was just blank white) - fixed: base path validation (could be missing a slash) - fixed: path of CPHelp.txt was sometimes not translated - fixed: mobj translucency didn't affect the shadow - fixed: incoming message queue protected by a mutex - music is not restarted if it's already playing - fixed: finding model files/skins with base-relative paths jDoom: * savegames stored in game mode specific subdirs (mixups now avoided) + cvar 'view-bob-weapon-switch-lower': if zero, HUD weapon is not lowered during a weapon switch + value 'Weapon Info|*|Static': if nonzero, HUD weapon is not lowered during a weapon switch * game-corpse-time: corpses fade smoothly - fixed: button deactivation sound - fixed: crash when "kill" used when not in a map jHeretic: * savegames stored in game mode specific subdirs (mixups now avoided) * game-corpse-time: corpses fade smoothly - fixed: button deactivation sound - fixed: Speed + Use Artifact made the player jump - fixed: on clientside, wind didn't affect player (e.g. E1M1) jHexen: * savegames stored in game mode specific subdirs (mixups now avoided) + option -savedir: set savegame directory - fixed: polyobj destination/speed for sliding doors (e.g. map05) - fixed: restoring polyobjs and hidden mobjs from saved map - fixed: problem with excessive sound sequence repeat (e.g. map12) - fixed: torch light for remote players - fixed: no mobjs spawned when dedicated server starts - clientside powers were not correctly set to zero at death, map change - clientside Wings of Wrath icon didn't rotate when flying - fixed: dedicated server deadlock when monsters don't find any players - fixed: crash when minotaur vanishes and master is dead - fixed: 'use artifact' sounds not audible on clientside - fixed: crash when "kill" used when not in a map - fixed: screen border flicker in fullscreen mode (again) - fixed: floatbobbing objects go through the floor - Deathkings map36: playerstart group >4 accepted InFine: * server sends condition truth values to clients (secret, leavehub) XG: - when loading a savegame, line activators were not correctly restored drD3D: - fixed a problem with mode selection (refresh rates) Installer: - fixed: pressing Enter after typing a path closed the installer dialog - glBSP run with the -fresh option to avoid bad BSP data Version 1.7.10 -------------- + support for ZIP/PK3 files (no compression!), can be loaded like WAD files (-file, load; no unload, though), contents added to the virtual file hierarchy (package root dir => Doomsday base dir) + after runtime directory has been searched, data files are also searched from the default data directory (e.g. Data\jDoom\): "-file Test.wad" will load Data\jDoom\Test.wad + WAD, LMP, PK3 and ZIP files from the Data\Game\Auto directory are always loaded automatically + WAD/PK3 files can be loaded from virtual files (inside PK3s) + IncludeIf and SkipIf directives can also test for game modes, e.g. "SkipIf Not doom1-ultimate" + light decorations (dynlights on textures/flats), "Decoration" defs + cvar group 'rend-light-decor' + sprite frames can be replaced with external resources (Patches) + raw screens can be replaced with external resources (Patches) + -maxtex option: set maximum texture size ("-maxtex 128") + sound flag 'sf_dontstop' (0x20): sound does not stop even if emitter is destroyed (sound cannot be stopped until it finishes normally) * faster 3D model loading during startup * rend-camera-smooth: Z-movement of planes is also smoothed * default dynlight brightness increased to 0.75 (rend-light-bright) * default halo brightness decreased to 35 (rend-halo-bright) - halo distance measured in 3D: no excess brightness when viewed from above/below - fixed: sprites were sometimes clipped by a sky ceiling - fixed: problems with rend-light-num jDoom: + light decorations for all switches, many textures and some flats of Doom 1 * barrel/rocket explosions continue even after barrel/rocket is gone (barexp uses sf_dontstop) * Pause key is now the default binding for pause (was P) jHeretic: - fixed: interlude screen wouldn't show seconds if they're zero jHexen: * Pause key is now the default binding for pause (was P) - fixed: weapon pieces bob only partially - fixed: screen border flicker in fullscreen mode Version 1.7.9 ------------- + external resource locator (in Data\Game\: Textures\, Patches\, Music\ and Sfx\) with game mode subdirs (see readme) + high-resolution patches (e.g. menu graphics, game fonts, background pictures) + netgame server info includes: game mode (e.g. doom1-ultimate, doom2-plut, hexen), game config, IWAD, PWADs, player names + info about network setup added to cphelp.txt, shows up during setup + cvar 'server-player-limit': maximum number of clients + cvar 'rend-light-wall-angle': intensity of angle-based wall lighting + cvar 'input-mouse-filter': average mouse X/Y axis values + model flag 'df_dim' (0x1000000): model is never rendered fullbright + cmds 'movefloor', 'moveceil', 'movesec': move a sector's plane(s) * low-level networking updated to DirectX 8 * improved network setup GUI * client can only connect to servers in the same game mode * cmd 'net' prints usage info * cvar 'net-ip-port' is the local TCP/IP port * "Filter mouse movement" added to Control Panel's Input page * -nohightex now only affects wall textures and flats * crosshair color alpha (cmd "crosshair color", var "view-cross-a") - fixed: client was able to connect to a server running a different game - fixed: aborted client connection crashed the server - potential problem handling client connections fixed - fixed: fullbrightness didn't affect particles - DirectSound 8: fixed a problem with buffer loading; using -csd should no longer be necessary - Sound definition patching fixed (Ext/Group keys were ignored) - fixed bug 712332: when server pauses a netgame, all clients will pause KickStart: * Cheb's KickStart v2.09 replaces the ancient v1.6 jDoom: + game modes: doom1-share, doom1, doom1-ultimate, doom2, doom2-plut, doom2-tnt + automap added to Options -> Controls (under Misc.) + cvar game-corpse-sliding: corpses slide down stairs and ledges (defaults to zero due to some bad behaviour; e.g. exit room of D2/22) * cvar game-corpsetime renamed to game-corpse-time - fixed bug 734892: sides with bogus sectors - A_Tracer() used to spawn puffs that were identical to bullet puffs, this caused complications with particle generators jHeretic: + game modes: heretic-share, heretic (normal registered), heretic-ext (has episodes 4, 5) jHexen: + game modes: hexen, hexen-dk (Death Kings of Dark Citadel) - fixed: sound sequence delays with repeating sounds (sequence updater didn't get correct information about currently playing sound effects) drOpenGL/drD3D: + -refresh option * closest available refresh rate selected Version 1.7.8 ------------- + new master server mechanism (uses HTTP) + cvar net-master-path (default: "/master.php"): location of the master server at 'net-master-address' (default: "www.doomsdayhq.com") + cmd "net announce": send a server announcement to the master (if server-public is nonzero, announcements are made automatically at two minute intervals) * cvar net-master-port (default: 0): usually zero or 80 * clientside player coords override serverside coords under normal circumstances (maxdif checks removed) * if one part of a psprite is fullbright, the whole psprite will be - fixed: psprites were rendered with depth testing enabled; Doom plasma rifle fire anim was broken - fixed: clientside player animation didn't finish anim sequence - fixed: line flags weren't updated on clientside (e.g. in Hexen map13) - fixed: minor edge artifact with multipart psprites (e.g. in jDoom) jDoom: * lineattack weapons hit planes (pistol, shotguns, chaingun) - fixed: lineattack check for hitting sky planes, skyhack walls - map31 and map32 no longer assumed to exist: Doom2.wad "00f6d407" should work - weapon psprite timings (in Objects.ded) adjusted for super shotgun, rocket launcher: muzzle flash was out-of-sync by 1-2 tics jHexen: - fixed: dedicated server tried to draw teleport gfx and crashed - fixed: scripted + yellow messages not shown on clientside - fixed: client crashes when changing level - fixed: status bar flicker jtNet2: - old master server stuff removed Version 1.7.7 ------------- + switch texture pairs (SW1/SW2) are precached at the same time + "Generator:Stage:Radius rnd": Randomness of particle radius + sound-info shows sound names as well as ID numbers + support for textured particles * flat particles stick to planes - high-resolution flats with 4 channels (alpha) were loaded incorrectly - sector lightlevel overflow in sectordelta (e.g. on jHexen map 26) - alternative texture path must be tried first when loading hires images (-texdir2) jDoom: * cvar player-air-movement: player movement speed while airborne (0-32); use only small values in netgames jHeretic: - blinking statbar borders fixed deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/0000755000175000017500000000000011523516205017637 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/make.bat0000755000175000017500000000046211357170241021252 0ustar keeskees@echo off :check IF "%1" == "h" GOTO html IF "%1" == "t" GOTO txt IF "%1" == "" GOTO end :next shift goto check :html for %%f in (*.ame) do amethyst -dHTML -id:\amethyst -eHTML -ohtml\%%f %%f goto next :txt for %%f in (*.ame) do amethyst -dTXT -id:\amethyst -eTXT -otxt\%%f %%f goto next :end deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/version2.ame0000644000175000017500000000433611357170241022101 0ustar keeskees@include{jake.ah} @macro{TITLE}{ Doomsday 2.0 Architecture } @require{amestd} @begin CONTENTS: @contents{1} $---------------------------------------------------------------------- @chapter{ Summary } This document outlines the architecture of Doomsday version 2.0. The primary goals are: @list{ @item The duplication of effort must stop: the merging of common code from the games into the engine will continue. The code in @file{\Src\Common} must disappear. In practice this means moving all play simulation and other central code into the engine. This allows many advanced features, which otherwise would've been cumbersome to implement: @list{ @item Sectors over sectors. @item Floating-point timing. @item Clean client/server networking. The game DLL won't need to worry about netgames vs. singleplayer games any longer. @item Centralized game saving. Also allows the engine to save any necessary data, such as particle generators. } @item A new role for the game DLL. It will only contain things that are not shared with the other games in any fashion, such as action routines. The engine will provide a menu system for the game DLL to use as necessary. @item A more powerful console. It will be possible to interact with play simulation using console commands. The console will also have scripting facilities, so that the net effect is at least the same functionality as is achieved using Hexen's ACS. DED files will be extended to DCSL scripts and CFG files will continue to be command dumps. @item jtNet2 will disappear and become part of the engine's system code. The old routines can still be used, though (or DirectPlay 8). At some point I must move to pure TCP/UDP/IP (to allow porting to other platforms). @item Cleaner handling of game modes (the various DOOMs, Heretic, Hexen). @item Remote data. Clients may download data (maps, gfx...) from the server. @item "High-resolution" resources: images, sounds, music, etc. There will be a uniform way to put things in the @file{ Data\ } directories. In theory any resource can have a high-resolution version, matched by the lump name in the correct subdirectory. @item In short, all of the ugly things in 1.7 must be corrected. } This new design opens many possibilities for further development. deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/darktable.ame0000644000175000017500000000023011357170241022250 0ustar keeskees@ifdef{HTML}{ @format{table}{@< @> } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/dedref.ame0000644000175000017500000001431111357170241021555 0ustar keeskees@include{jake.ah} @macro{TITLE}{ Doomsday Engine Definitions Reference } @macro{VERSION}{ (or "Knee-Deep In The DED") @br Version 1.0 } @include{amestd} @include{darktable} @begin CONTENTS: @contents{1 2} @chapter{ Overview } $ What are DED files, and what can be achieved by them. $ An overview to the way DED files are organized. Doomsday Engine Definition (DED) files use the file name extension @file{.ded}. @section{ Standard DED files } $ The names and uses the DED files in j-ports. Included in the main Game distribution (all of these are in the @file{ Defs\\ } directory): @table{25 75}{ @file{.ded} @tab The primary DED of the Game. Included automatically by default. Includes the other standard DED files. @row @file{Objects.ded} @tab All Thing and State definitions. Defines all @opt{mf_*} (and @opt{mf2_*}) flags. @row @file{Sprites.ded} @tab Sprite definitions. @row @file{Special.ded} @tab Particle generator definitions. Defines @opt{gnf_*} and @opt{ptf_*} flags. @row @file{Lights.ded} @tab Light definitions. Defines @opt{lgf_*} flags. @row @file{Details.ded} @tab Detail texture definitions. @row @file{Audio.ded} @tab Sound, Music and Texture Environment definitions. Defines @opt{sf_*} flags. @row @file{Maps.ded} @tab Map Info definitions. Defines all @opt{mif_*} and @opt{slf_*} flags. @row @file{Finales.ded} @tab Finale/interlude scripts. @row @file{Text.ded} @tab Text definitions. @row @file{Values.ded} @tab Value definitions (custom string pairs). @row @file{Models.ded} @tab Defines model flags (@opt{df_*}) and groups (@opt{mg_*}) and includes the top-level model definition files (e.g. @file{Monsters.ded}, @file{HUDWeapons.ded}). @file{Models.ded} contains nothing else (no actual Model definitions). @row @file{User.ded} @tab Any custom definitions. Not included in regular distributions (so the user's customizations won't be overwritten). } Default grouping of model definitions (really depends on the Game): @table{25 75}{ @file{Monsters.ded} @tab Enemies @row @file{Weapons.ded} @tab Weapons and ammo (items) @row @file{Items.ded} @tab Items @row @file{Players.ded} @tab Players @row @file{HUDWeapons.ded} @tab HUD weapons (psprites) @row @file{Technology.ded} @tab Technology-related decorations @row @file{Nature.ded} @tab Nature decorations: plants, rocks, etc. @row @file{Decorations.ded} @tab Other decorations @row @file{FX.ded} @tab Special (model-related) effects (fire, explo) } @section{ Syntax } $ What Doomsday expects of DED files; what kind of a syntax do DEDs use. @subsec{Comments} There are two kinds of comments: line comments and delimited comments. Line comments begin with a hash character (#) and continue until the end of the line. The parser will skip everything on the line after the # character. Delimited comments begin with a @opt{#>} symbol and continue until a @opt{<#} symbol is found. An example: @code{#> The comment begins... @br And continues @br ...and ends here <#} @subsec{Header block} Use of the Header block is optional but it is recommended that you at least use a version declaration. @code{Header @{ Version = 5; @} } @subsec{Directives} Directives are commands that control the DED reader. They are composed of a keyword and a variable number of parameters. All directives end in a semicolon (;). @code{Include "Models.ded";} @subsec{Definition blocks} A DED file contains a number of directives and definition blocks. A definition block begins with a keyword that determines the block's type, followed by a number of keys and sub-blocks contained in a 'block' of curly brackets @{, @}. Each key and sub-block must end in a semicolon (;) but there mustn't be one after the @} that ends the definition block itself. @ind{@pre{Text @{ ID = "PRESSYN"; Text = "press y or n."; @}}} @subsec{Attributes} Attributes are optional and appear in front of the keywords that begin definition blocks. Currently there is only one attribute, and even it can't be used with all types of definitions: @opt{Copy}. An asterisk (@opt{*}) can be used as an abbreviation of @opt{Copy}, which is convenient with model definitions. @subsec{Keys} Each type of definition is composed of a number of keys, each representing some property of the definition. For example, the Text definition above: @ind{@pre{Text @{ ID = "PRESSYN"; Text = "press y or n."; @}}} The Text definition has the @opt{ID} and @opt{Text} keys. Both take a value of type 'string'. @subsec{String values} Strings begin and end in double quotation marks ("). If newline characters are found inside a string (the string has been divided onto multiple lines) the newline and all following whitespace are skipped, and the actual string continues from the first non-whitespace character that follows. $ Describes each type of definition in detail, discussion about important $ notes and uses. @chapter{ Directives } @code{Include "Other.ded";} The @opt{Include} directive causes the parser to read the given DED file. Included files are read @em{after} the file from which they were included. @code{ IncludeIf -opt "Other.ded"; @br IncludeIf Not -opt "Other.ded"; } The given DED file is included if the option @opt{-opt} is (not) found in the command line. @code{ SkipIf -opt; @br SkipIf Not -opt; } The rest of the file is skipped if the option @opt{-opt} is (not) found in the command line. @code{ModelPath "MD2\Game\Item";} The @opt{ModelPath} directive appends a new path to the list of model search paths. @notice{ This directive has no scope: it affects all the definitions that come before and after it. Also, be careful with backslashes. Since they are used as escape characters in strings you can't for example do this: @opt{"MD2\Game\Path\"}. That would mean the last character of the path is @opt{"} but the string itself doesn't end. You can use forward slashes instead of backslashes.} @chapter{ Objects } @section{ Sprite } @section{ State } @section{ Thing } @section{ Model } @chapter{ Properties } @section{ Light } @section{ Detail } @section{ Texture Environment } @section{ Map Info } @chapter{ Audio } @section{ Sound } @section{ Music } @chapter{ Effects } @section{ Generator } @chapter{ Information } @section{ Text } @section{ Values } @chapter{ Other definitions } @section{ Finale } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/beginner.ame0000644000175000017500000003072111357170241022120 0ustar keeskees@include{jake.ah} @macro{TITLE}{ A Beginner's Guide To Doomsday } @macro{SUBTITLE}{ or "The Apocalypse For First-Timers" } @require{amestd} @include{darktable} @macro{button}{@strong{@arg}} @begin CONTENTS: @contents{1} @chapter{ What do you need? } @list{ @item One of the distribution packages: @table{45 55}{ @header{File name} @tab @header{Contains} @row{single} @file{deng-inst-(version).exe} @tab Installer, jDoom, jHeretic, jHexen (for Windows) @row @file{deng-(version).zip} @tab jDoom, jHeretic, jHexen (for Windows) @row @file{deng-(version).dmg.gz} @tab Compressed disk image containing jDoom, jHeretic, jHexen (for Mac OS X 10.3) @row @file{deng-(version).tar.gz} @tab Source code (for Linux) } The packages can be downloaded from @link{http://sourceforge.net/projects/deng/}. @item 3D models are distributed in separate packages called resource packs. Each resource pack contains a set of 3D models, which will be used to represent objects in the game world. Without a resource pack, objects will be represented with the original 2D graphics ("sprites"). Downloading one or more resource pack is optional. The packages are called jDRP, jHRP, and jXRP. These stand for "jDoom/jHeretic/jHexen Resource Pack". You can download the packs from @link{http://www.doomsdayhq.com/}. @item Windows 98 (or newer), Mac OS X 10.3, or Linux. @item On Windows, DirectX 8.0 (or newer) is required. @item A display adapter capable of 3D hardware acceleration. @item A copy of the original shareware/registered Doom, Doom II, Final Doom, shareware/registered Heretic, Hexen or Hexen: Deathkings of the Dark Citadel, depending on what you're going to play. } @chapter{ Automatical installation } These installation instructions are for the Windows version of Doomsday. The distribution packages have included a special installation wizard since Doomsday 1.7.3. @section{ Installing into a new folder } Execute the distribution package @file{deng-inst-(ver).exe}. Type the path of the folder into the edit box or choose an existing folder using the @button{Browse} button. Example: @file{C:\Games\Doomsday}. There is a button with a folder icon on the left side of the edit box. Click the button. After the files have been extracted, a WAD Files dialog will appear. The dialog lists a number of WAD files from supported games (Doom, Heretic, Hexen). Locate the WAD files you have on your hard drive. It is not necessary to run glBSP on the WADs, so the glBSP option does not need to be checked. Note that the installation wizard can only create shortcuts for the WAD files you locate using this dialog. The shortcut creation dialog will allow you to select a Start Menu program group and gives you the option to automatically create shortcuts for the KickStart launcher. The fast launch shortcuts will be created in the selected Start Menu program group. They allow you to immediately launch the game using a specific WAD and renderer. If you have downloaded any model packs, you may now install them in any order you like. They use the same installation wizard as the main distribution package. @section{ Upgrading an old version } The @button{Upgrade} button is available if you have installed a version of Doomsday in the past using the wizard. Clicking the button will make the installer extract the new files into the folder where you have the older version installed. The WAD files dialog will then appear. If you have already located all of your WAD files in the past, you don't need to enter them again in the dialog. Click @button{Continue} when you're done. If there is no need to create new shortcuts, just bypass the shortcut creation dialog by clicking @button{Continue}. @chapter{ Manual installation } This is the procedure to follow when installing Doomsday 1.7.2 or an older version. @section{ Step 1: Unpack the distribution package } Run the distribution EXE file. A window appears asking you where the files should be extracted. The default folder is @file{C:\Doomsday}. You might want to change it something like @file{C:\Games\Doomsday} or @file{C:\Program@sp{}Files\Doomsday}. Click the @strong{Install} button to begin the installation. When the files have been extracted, you can run the EXE file of the model pack, for instance @file{jdoom_mpack.exe}. Be sure to extract the model files in the same directory as you extracted the distribution. The default is @file{C:\Doomsday} here, as well. The model pack is not required; you don't have to install it at all, or you might install it at some later point in time. Even if you're only going to play one of the games, for example jDoom, it's recommended that you install the files into a folder named @file{Doomsday} (or something similar), not @file{jDoom} because if you later decide to install jHeretic or jHexen they should be installed into the same folder with jDoom. It's possible to install them into separate folders but then you've got multiple copies of the same files on your hard drive. (Assuming you care about a few MBs or the names of your folders.) @section{ Step 2: Copy the WAD files } The only thing you need from the original Doom, Heretic, Hexen, etc. is an IWAD file. It is the large (over 10 MBs) WAD file you can find in the folder where you've got the original game installed. It contains all the game maps, sprites, sounds, graphics and other data. The names of the various IWADs are listed below: @table{18 28 54}{ @header{Game DLL} @tab @header{Original Game} @tab @header{IWAD Files} @row{single} jDoom @tab Shareware Doom @tab @file{DOOM1.WAD} @row jDoom @tab Registered Doom @tab @file{DOOM.WAD} @row jDoom @tab Doom II @tab @file{DOOM2.WAD} @row jDoom @tab Final Doom @tab @file{TNT.WAD} and @file{PLUTONIA.WAD} @row jHeretic @tab Heretic @tab @file{HERETIC.WAD} @row jHexen @tab Hexen @tab @file{HEXEN.WAD} @row jHexen @tab Hexen: Deathkings @tab @file{HEXDD.WAD} (@file{HEXEN.WAD} needed as well) } Let's assume that in Step 1 you extracted the files to @file{C:\Doomsday}. I recommend that you copy (or move if you don't play the original game any more) the IWAD files you need into the appropriate @file{Data} subfolder, in jDoom's case @file{C:\Doomsday\Data\jDoom}. If you don't do this you'll need to specify the IWAD to use when launching the game. @notice{ Make sure you're using the latest version of the original game. See this F.A.Q. entry for more information: @link{http://www.doomsdayhq.com/faq.php?topic=10#question5} } @section{ Step 3: Run glBSP on the WAD files } glBSP (by Andrew Apted) is a program that calculates map data in a way which is more accurate and more useful for 3D rendering than the data found in the original WAD files. Running glBSP will greatly reduce the number of graphics errors like stray pixels and missing floors, ceilings and walls. In most cases all graphics errors can be fixed by running glBSP. Starting with Doomsday 1.8.1, it is no longer necessary to run glBSP manually. Doomsday will calculate the accurate map data on the fly when it becomes necessary. The Doomsday KickStart launcher can automatically check for the existance of data files produced by glBSP and build them if necessary, so you can skip this step if you make sure the option "Check if glBSP needs to be run" is checked on KickStart's "Other" tab. Open the DOS Prompt and change to the folder where you extracted the files in Step 1. All the distributions include a text mode version of glBSP, so all you need to do is give the following commands (for all IWAD files you copied in Step 2): @samp{ @cmd{glbsp data\jdoom\doom.wad @br glbsp data\jdoom\doom2.wad} @br (...etc...) @br @cmd{glbsp data\jhexen\hexdd.wad} } If you didn't copy the IWADs to the Data folder, you must naturally give the full path to glBSP, for example: @samp{@cmd{glbsp d:\games\heretic\heretic.wad}} @notice{ If you have glBSP version 2.00, you need to use the @opt{-fresh} option when you run glBSP. Otherwise the generated data may contain errors. } For the latest version go to @link{http://glbsp.sourceforge.net/}. @section{ Step 4: Create a shortcut for KickStart } The main launcher for games running on the Doomsday Engine is called Doomsday KickStart. It can be found in the folder where you extracted the files in Step 1 (@file{Kicks.exe}). To have a convenient way to start the game create a Windows shortcut for @file{Kicks.exe}. @notice{ If KickStart fails to run, displaying an error message about missing OCX or DLL files, get the "KickStart Full Install" from @link{http://www.doomsdayhq.com/files.php?class=5}. } @chapter{ Starting a game } @section{ Starting with KickStart } Doomsday KickStart is the easiest way to start playing jDoom, jHeretic or jHexen. Select the profile you want from the list and click @button{Play}. To find more information about KickStart, go to: @ind{@link{http://modelyard.newdoom.com/}} @section{ Starting with the Simple Launchers } The Simple Launchers are small EXE files found in the folder where you installed the game (@file{jDoom.exe}, @file{jHeretic.exe}, @file{jHexen.exe}). They can only be run in the root Doomsday folder, which is @file{C:\Doomsday} by default. They just change to the correct runtime folder (e.g. @file{Run\jDoom}) and execute @file{Doomsday.exe} with the appropriate command line options (@opt{-gl}, @opt{-game}, @opt{-userdir}, @opt{-basedir}; see @file{Doc\CmdLine.txt}). The simple launchers have one command line option of their own: @opt{-d3d}. It'll make the game use the Direct3D renderer instead of the OpenGL one, which is used otherwise. @section{ Starting with batch files or from the DOS Prompt } If everything else fails you can always start the game from the DOS Prompt. For an example batch file see @file{Doc\Example.bat}. For information about the handling of file names on the command line see @file{Doc\Readme.txt}. For a list of command line options see @file{Doc\CmdLine.txt}. @section{ jDoom: Options for overriding game detection } If you've got multiple IWADs in your @file{Data\jDoom} folder and you start the game from a batch file or from the DOS Prompt you can use the following command line options to make jDoom use the IWAD you want: @table{30 70}{ @header{Option} @tab @header{Game} @row{single} @opt{-sdoom} @tab Shareware Doom (@file{DOOM1.WAD}) @row @opt{-doom} @tab Registered Doom (@file{DOOM.WAD}) @row @opt{-ultimate} @tab Ultimate Doom (@file{DOOM.WAD}) @row @opt{-doom2} @tab Doom II (@file{DOOM2.WAD}) @row @opt{-tnt} @tab Final Doom (@file{TNT.WAD}) @row @opt{-plutonia} @tab Final Doom (@file{PLUTONIA.WAD}) } If you don't use one of these options and you don't specify an IWAD with the @opt{-iwad} command line option, jDoom will use the first IWAD it comes across. The folders searched are @file{Data\jDoom}, @file{Data}, the root Doomsday folder and @file{Run\jDoom}. @chapter{ Loading WADs } There are two kinds of WAD files: IWADs and PWADs. IWADs are usually large and contain all kinds of data like maps, sprites, sounds and graphics. PWADs (Patch WADs) are smaller and in addition to new data they may contain data that will replace some parts of an IWAD, for instance a single map. Both IWADs and PWADs consist of one or more named blocks of data called lumps. KickStart won't start a game unless an IWAD file is listed and checked in the WAD Files list. @section{ Loading in KickStart } Click the @strong{Add} and @strong{Remove} buttons under the WAD Files list to add and remove WAD files. All the checked files will be loaded when you start the game. @section{ Loading in the console } It's possible to load WAD files at runtime in the console. When you've got the game running, open the console with the @kbd{Tilde} key. To load the WAD file @file{COOL.WAD} from the runtime folder (e.g. @file{Run\jDoom}), use the following command: @samp{@cmd{load cool.wad}} You can also give the full path of the file: @samp{@cmd{load d:\games\doom\super.wad}} The command @cmd{listfiles} will print a list of all the currently loaded data files. You can unload files that have been loaded at runtime with the @cmd{unload} command, for example: @samp{@cmd{unload cool.wad}} @section{ Loading with command line options } If you have the file @file{COOL.WAD} in the runtime folder (e.g. @file{Run\jDoom}), you can use the command line option @samp{@opt{-file cool.wad}} to load @file{COOL.WAD} at startup. Note that you can only use the @opt{-file} option once, so if you want to load multiple files you need to do the following: @samp{@opt{-file file1.wad file2.wad file3.wad}} For detailed information about the handling of file names on the command line see @file{Doc\Readme.txt}. deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/readme.ame0000644000175000017500000011215211357170241021563 0ustar keeskees@include{jake.ah} @macro{TITLE}{ The Doomsday Engine } @macro{VERSION}{ Version 1.9.0 } @require{amestd} @include{darktable} @begin CONTENTS: @contents{1} @chapter{ Introduction } The Doomsday Engine is an enhanced Doom source port for the Windows, Mac OS X, and Linux platforms. It is based on the source code of id Software's Doom and Raven Software's Heretic and Hexen. The Doomsday Engine and the associated ports of Doom, Heretic and Hexen have been under development since 1999. The first versions were released in late 1999 and early 2000. Most of the development work has been done by Jaakko Kernen (skyjake). Several other people have also been involved in the project (see @ref{acks}{Acknowledgements}). The purpose of the project is to create versions of Doom, Heretic and Hexen that feel the same as the original games but are implemented using modern techniques such as 3D graphics and client/server networking. A lot of emphasis is placed on good-looking graphics. @section{ Features } Graphics: @list/thin{ @item Supports both OpenGL and Direct3D @item Dynamic lights @item Lens flares @item High-resolution textures (PNG, TGA, PCX) @item Particle effects @item Detail textures @item Shiny surfaces @item 3D models (uses Quake II's MD2 format) @item Simple environmental mapping for 3D models (shiny effects) @item MD2 skymodels and skyboxes @item Actor (monster) movement smoothing @item Simulated radiosity shadowing system for the environment @item Simple shadows for objects @item Fog @item Glowing surfaces @item Smart texture filtering using a modified hq2x algorithm @item Runs glBSP automatically when needed (using a plugin) } Sound: @list/thin{ @item Plays music using standard Windows MIDI routines @item Win32: supports DirectSound, DirectSound3D, EAX 2.0 and A3D 3.0 @item Mac: QuickTime @item Linux: SDL_mixer, OpenAL @item Uses FMOD (@link{http://www.fmod.org/}) to play music files such as MP3 @item 3D sound effects @item Environmental (reverb) effects @item Runtime sound effect resamping to 22/44 KHz with 8/16 bits } Networking: @list/thin{ @item TCP/UDP-based client/server networking @item Up to 16 players @item Clients can join games in progress @item Dedicated mode for servers } Other: @list/thin{ @item Console @item Control Panel @item Plain text definition files for game objects and other data @item Files can be loaded from WAD files (see @file{wadtool}) @item Doomsday KickStart (on Win32): a launcher for games running on Doomsday } @section{ Requirements } @list{ @item Pentium 166 (or equivalent) with 64Mb of RAM (providing that 3D models and special effects are disabled) @item Windows 98 (or newer), Mac OS X 10.3, or Linux @item DirectX 8 (or newer) on Windows @item A display adapter capable of 3D hardware acceleration @item At least one WAD file from the original Doom, Heretic, Hexen, etc. } $ An overview of the Doomsday docs. @chapter{ Documentation } Additional documentation is available in the @file{ Doc\ } folder: @deflist{ @item{ @file{Beginner.txt} } A Beginner's Guide to Doomsday. Installation instructions and basic usage information for a first-time user. @item{ @file{CmdLine.txt} } Doomsday command line options. A quick reference listing all the command line options recognized by Doomsday, with a short explanation for each. @item{ @file{DEDDoc.txt} } Doomsday Engine Definition reference. An in-depth look into the syntax and uses of DED files. @item{ @file{InFine.txt} } InFine scripts reference. InFine scripts are used to define interludes and finale animations. @item{ @file{DHistory.txt} } Doomsday version history. @item{ @file{DSS.txt} } Doomsday directory structure standard. Mod-makers and other developers are encouraged to follow the structure described here. @item{ @file{Network.txt} } Multiplayer games with Doomsday. Some details about network games running on Doomsday. @item{ @file{Example.bat} } Example batch file for launching. } An up-to-date version history of the Doomsday engine should be available at: @ind{@link{http://www.doomsdayhq.com/changes.php}} The Extended General Line And Sector Type Reference (XGRef) can be downloaded from: @ind{@link{http://iki.fi/code/files/XGRef.pdf}} @chapter{ Running from the Command Line } @section{ File Paths on the Command Line } There are a few things you should know about the handling of relative paths. First of all, these are the directories that the engine is working with: @list{ @item Doomsday root/base directory (for example @file{ C:\Doomsday\ }). Everything relating to the Doomsday engine is under this directory. @item Working/runtime directory (for example @file{ C:\Doomsday\Run\x\ }). This is the directory where the engine spends it time when a game is running. @item Data directory (for example @file{ C:\Doomsday\Data\x\ }). WAD files and external resources are loaded from here. } The @opt{-basedir} option tells the engine where the base directory is in relation to the runtime directory (or it's the the absolute path of the base directory, e.g. @file{ C:\Doomsday\ }). The principle is that @opt{-basedir} only affects built-in default paths and relative paths in DED files. @opt{-basedir} does not affect relative paths in command line options. If a relative path is given on the command line, it is first searched in relation to the runtime directory. For example, the option @opt{-file doom.wad} will make the engine read the file @file{doom.wad}, which is located in the runtime directory. In the default configuration this is @file{ C:\Doomsday\Run\jDoom\ }. If the file is not found in the runtime directory, the data directory is searched instead. KickStart automatically uses a @opt{-basedir} of @file{..\..}, which means the root directory is the 'grandparent' of the runtime directory. The option @opt{-sbd} (@opt{-stdbasedir}) is the equivalent of @opt{-basedir ..\..}. There is one exception, though. With the @opt{-file} (and @opt{-iwad}) options a relative path can begin with a greater-than character (>) or a closing brace character (@}). When the engine loads the WAD file in question, the > or @} character is replaced with the path specified by @opt{-basedir}. For example, @opt{-file >Data\Doom.wad} would make the engine load a WAD named @file{ C:\Doomsday\Data\Doom.wad } (assuming the default Doomsday root @file{ C:\Doomsday\ }). Note that if you're executing @file{Doomsday.exe} from the command line or from a DOS batch file, you must enclose the file names that contain a > character in quotes or otherwise DOS will think you're trying to redirect output. In response files it doesn't matter if there are quotes or not. (If you really are trying to redirect output, you should use the @opt{-out} option.) The default launch method (used by KickStart 1.6) is a runtime directory oriented approach. KickStart will change the current working directory to the Game's runtime folder and execute @file{Doomsday.exe} from there, with the @opt{-basedir ..\..} option. This way the engine will use the appropriate runtime folder as the working directory, but will also know where the Doomsday root directory is by adding the base directory's @file{..\..} to default path names (like fonts and definitions files). There is an alternative approach, which could be called an executable oriented approach. @file{Doomsday.exe} is executed in the @file{Bin} directory, with the options @opt{-userdir -basedir }. @file{} can be a relative or an absolute path to the correct runtime directory. Again, @opt{-basedir} tells the engine where the root directory is, using an absolute path or in relation to @file{}. @opt{-userdir} will make the engine run in the given directory, i.e. it specifies the runtime directory. Note that @opt{-game} and @opt{-gl} work a bit differently because their arguments are directly passed on to the Win32 routine @cmd{LoadLibrary}. You should either omit the path entirely (e.g. @opt{-game jHeretic.dll}) or use a full path to the DLL (e.g. @opt{-game C:\Doomsday\Bin\jHeretic.dll}), no matter where you're executing @file{Doomsday.exe}. The default place where you should put your IWADs is @file{ Data\\ }. jDoom, jHeretic and jHexen will by default look for IWADs in @file{ Data\\ }, @file{ Data\ }, the base directory and the runtime directory, in that order. @section{ The @opt{-file} Option } @a{fileopt} The @opt{-file} option is used to load WAD files and other data files from the command line. @opt{-file} has two aliases: the abbreviation @opt{-f} and @opt{-iwad}. Both of these are just aliases; they are treated like they were in fact @opt{-file}. In addition to normal WAD files, the @opt{-file} option can be used to load any type of data files, for instance PCX images. An example: @samp{@opt{-file image.pcx}} This would load the file @file{image.pcx} from the runtime directory (or the data directory). When loading files in this manner, the engine will treat the file as if it was a WAD file with a single data lump. The lump gets its name from the base of the file name, which in the example's case would be @file{IMAGE}. Anyone can then refer to the data lump using that name, just as if it was included in a WAD file. Any file loaded with the @opt{-file} option can't be unloaded from memory at runtime using the @cmd{unload} command. This is mainly a precaution, since unloading the main WAD file of the game or any data related to it would lead to fatal errors. @chapter{ Data and Definitions Files } @section{ PK3 Files } Doomsday supports the PK3 (i.e. ZIP) format. Compression is allowed, but encryption is not. If you try to load an encrypted or password protected ZIP/PK3 file, you will get an error message. PK3 files are loaded using the @opt{-file} option. For example, @opt{-file some.pk3} will try loading @file{some.pk3} first from the runtime directory and then from the data directory. A PK3 contains a set of files organized into directories. When a PK3 is loaded, all of them become virtual files that Doomsday can access just like the regular files on your hard drive. The end result is the same as if you had unpacked the PK3 into your Doomsday base directory. (Don't worry, no actual unpacking is done.) For example, the PK3 could have the file @file{Data\jDoom\Auto\Superb.wad}. PK3 files can be created with just about any ZIP program, such as WinZip. Just make sure all the files have the correct paths, or otherwise Doomsday may not be able to find them. Version 1.8.6 introduces enhancements to PK3 path handling. @list{ @item Files in the root of a PK3 are subject to automatic relocation based on file name extension: PK3/ZIP/LMP/WAD are mapped to @file{Data\\Auto\} and DED goes to @file{Defs\\Auto\}. For example, placing @file{test.ded} into the root of a PK3 has the same end result as placing @file{test.ded} into @file{Defs\\Auto\}. @item Since the automatic mapping described above only affects single files, it is also possible to request mapping manually by adding a special prefix character to the name of a directory in the root of a PK3. If the directory begins with @file{#}, it is mapped into @file{Data\\Auto\}; if it begins with @file{@@}, it is mapped into @file{Defs\\Auto\}. @samp{@file{#CoolStuff/Some.pk3} => @file{Data//Auto/CoolStuff/Some.pk3}} } @section{ Definitions and Files in WADs } After all DED files have been processed, the engine will check through all the loaded WAD files for lumps named @file{DD_DEFNS}. All the lumps with that name are processed just as if they were DED files, i.e. they should contain a DED file in plain text format. The @file{DD_DEFNS} lumps are applied in the order in which they have been loaded. Another special lump used by Doomsday is @file{DD_DIREC}. It contains a table that translates file paths to lump names. An example is shown below: @samp{ @pre{FILE001 /Md2/jDoom/Some.md2 FILE002 Another.ded} } Each line in @file{DD_DIREC} contains a lump/path pair. The paths that begin with a (back)slash are interpreted as paths that start from the Doomsday base directory (set with @opt{-basedir}; e.g. @file{C:\Doomsday}) and paths that don't begin with a (back)slash are located in the runtime directory. The engine will first search the @file{DD_DIREC}@nsp{s} before opening any file for reading. Note, however, that all kinds of files are not loaded using the @file{DD_DIREC}@nsp{s}: for instance demos (which are compressed with the LZSS library) must always be loaded from real files. I've written a simple utility for automatically creating a WAD file that contains the current directory and all its subdirectories plus a @file{DD_DIREC} lump that has (with a high probability) a unique lump name for each file. You could invoke the utility like this: @samp{@cmd{ wadtool myfiles.wad /Data/jDoom/Textures/ }} This would create a WAD file that contains all the files from the current directory. When writing the @file{DD_DIREC} table, the prefix "/Data/jDoom/Textures/" would be added to each file name. @section{ Automatical Loading of Data and Definitions } All WAD, PK3, ZIP and LMP files placed in the @file{ Data\\Auto\ } directory will be automatically loaded at startup. The data files are loaded in alphabetical order, including all the subdirectories of the @file{Auto} directory. All DED files placed in the @file{ Defs\\Auto\ } directory will be automatically read at startup. The definition files are also loaded in alphabetical order, including all the subdirectories of the @file{Auto} directory. Virtual files (from a PK3 or a WAD) in the @file{Auto} directories will also be loaded. @section{ Virtual Directory Mapping } Version 1.8.7 introduces virtual directory mappings, which allows you to make the contents of one directory appear inside another directory at runtime. For example, you could have a directory called @file{MyAuto} with a set of data files somewhere on your hard drive. You could map this directory to @file{Data//Auto}, which would cause @file{MyAuto} to behave as though it was an auto-loading directory. A virtual directory mapping is defined using the @opt{-vdmap} option. It takes the source and destination directories as parameters. For example: @samp{@cmd{-vdmap "D:\Games\MyAuto" "C:\Doomsday\Data\jDoom\Auto"}} You can define an unlimited number of virtual directory mappings using multiple @opt{-vdmap} options. Note, however, that @opt{-vdmap} only affects real files. It does not affect virtual files in PK3s or anywhere else. The virtual directory mappings are tried when all other methods of finding a file fail. So, all real files and virtual files override @opt{-vdmap}. @section{ Lump Assemblies instead of WADs } The automatic loading of data files can be utilised to load directories that contain individual data lumps. This kind of a directory is called a "lump assembly" and it can be used instead of a WAD file. Note that a lump assembly can only be loaded via the autoload mechanism (but it can be inside of a PK3 that is loaded manually). By default the contents of a lump assembly are loaded in alphabetical order. However, some kinds of data require that the lumps are in a specific order (for instance map data). You have two options if you want to enforce a specific order: @list{ @item You can use name prefixes that are used to sort the lumps but are ignored when the lump names are determined. The length of the prefix can be 1..9 characters long. You specify the length of the prefix by adding an extension to the name of the directory that contains the lumps. An example that uses a prefix with 3 characters: @samp{@file{Data\Game\Auto\DirWithPrefix.3\01_LUMPNAME.lmp}} The first three characters of the file name are ignored (@file{01_}) and @file{LUMPNAME} becomes the name of the lump. @item You can put a WAD inside the assembly. } The assembly can be built using a hierarchy of directories. For example the contents of the PK3 might be: @samp{@pre{#assembly/ data1.lmp data2.lmp powerplant.2/ a-E2M3.lmp b-THINGS.lmp xyz.lmp }} @file{#assembly} would be mapped to @file{ Data\\Auto\assembly\ }. @chapter{ Graphics } @section{ 3D Models as Particles } 3D models can be used as particles in a particle generator. There are two things that need to be done. In the particle generator definition, set the particle stage's type to one of the @opt{pt_model} flags. The following would make the stage use particle model number 13: @code{Type = "pt_model13";} In the particle stage definition, remember to set a color for the stage. If the color is not specified, the default values will result in a completely transparent particle model. The model definition must have a matching ID. For example, particle model number 13 uses the following ID: @code{ID = "Particle13";} For further details see the DED Reference. @section{ Detail Textures } Detail textures are grayscale images that are rendered on top of normal textures when walls and planes are viewed from close by. A signed-add blending is used, which lets the detail texture either darken or brighten the underlying texture: black => dark, gray => no change, white => bright. Detail textures can be assigned to specific wall textures and flats using Detail definitions (@file{Details.ded}). The definition is described in the Doomsday Engine Definitions Reference (@file{DEDDoc.txt}). Detail textures can be loaded from external image resources (from the @file{Textures} directory), or PCX images and raw image data stored inside a WAD lump. When using the @opt{-file} option to load detail texture lumps, the file names of the images become lump names (see @ref{fileopt}{@opt{-file} option}). If an external resource is used as the detail texture, its dimensions must be powers of two (for example 128x64 or 256x256). The image file must be in one of the supported image file formats. PCX images used as detail textures must have a color depth of 8 bits and their width and height must be powers of two. The palette should be a grayscale one. It is possible to use other colors but the result can be weird due to the way the blending of detail textures is done. If the source data is a raw image, it must be either 64x64, 128x128 or 256x256 pixels in size. Raw images contain only the pixel values, (one byte per pixel) and have only one color component per pixel (they're black and white images), which means the lump or file that contains the detail texture can either be 4096, 16384 or 65536 bytes long. Using the default scaling, the pixels of detail textures are four times smaller than the pixels of regular textures. The console variables @var{rend-tex-detail}, @var{rend-tex-detail-far}, @var{rend-tex-detail-strength} and @var{rend-tex-detail-scale} control the rendering of detail textures. $ External resource files. @chapter{ Resource Files } Normally all resources such as wall textures, menu graphics and fonts, background music and sound effects are loaded from the WAD files. Doomsday has a mechanism that allows replacing these resources with external resource files placed in specific directories. The files are called 'external' because they are regular files and not part of a WAD file. External resource files are easy to use. They do not require making changes to any configuration or definition files. As long as a resource file is placed in the correct directory, Doomsday will load and use it automatically. External resources are divided into a number of classes. Each class has its own subdirectory under the @file{ Data\\ } directory. The table below lists the resource classes and gives a brief description of each. @table{25 75}{ @header{Resource Class} @tab @header{Description} @row{single} Textures @tab Textures for walls and flats (floors and ceilings) @row Flats @tab Textures just for flats (floors and ceilings) @row Patches @tab Graphics for menus, fonts and sprite frames @row LightMaps @tab Textures for dynamic lights @row Music @tab Background music @row Sfx @tab Sound effects } For example, sound effects for jDoom would be placed in the directory @file{ Data\jDoom\Sfx\ }. @section{ Game Modes } One Game DLL, such as jDoom, is able to run in many different modes. Each mode emulates a specific version of the original game and typically has its own IWAD file. In some cases two modes can have a resource with the same name. This is a problem if the same resource file can't be used by both modes. The resource class directory can have a subdirectory for each game mode. When Doomsday looks for an external resource, it first checks the current game mode's subdirectory. If no suitable resource is found there, the class directory is searched instead. Below is a list of all the game modes supported by jDoom, jHeretic and jHexen. @table{18 27 55}{ @header{Game} @tab @header{Mode} @tab @header{Description} @row{single} jDoom @tab doom1-share @tab Shareware Doom @row @tab doom1 @tab Registered Doom @row @tab doom1-ultimate @tab Ultimate Doom (has a 4th episode) @row @tab doom2 @tab Doom 2 @row @tab doom2-plut @tab Final Doom: Plutonia Experiment @row @tab doom2-tnt @tab Final Doom: TNT Evilution @row jHeretic @tab heretic-share @tab Shareware Heretic @row @tab heretic @tab Registered Heretic @row @tab heretic-ext @tab Heretic: Shadow of the Serpent Riders (has episodes 4, 5) @row jHexen @tab hexen @tab Hexen @row @tab hexen-dk @tab Hexen: Death Kings of Dark Citadel @row @tab hexen-demo @tab The 4-level Hexen Demo } For example, textures meant only for Final Doom: Plutonia Experiment would be placed in the directory @file{ Data\jDoom\Textures\doom2-plut\ }. @section{ Textures and Flats } Normal wall textures and flats can be replaced with TGA (Truevision Targa), PNG (Portable Network Graphics) or PCX (Zsoft Paintbrush) images. The engine currently supports these image formats: @table{40 20 20 20}{ @header{Pixel size} @tab @header{PCX} @tab @header{PNG} @tab @header{TGA} @row{single} 8-bit (paletted)* @tab Yes @tab Yes @tab - @row 16-bit @tab - @tab - @tab - @row 24-bit @tab - @tab Yes @tab Yes** @row 32-bit (alpha channel) @tab - @tab Yes @tab Yes** } @caption{* = the palette does not have to match the palette of the game @br ** = TGAs must be type 2 (uncompressed, unmapped RGB)} Note that 32-bit images are just 24-bit images with an additional 8 bits per pixel for the alpha channel. Contact me if you feel that it's necessary to add support for other formats. The recommended format for high-resolution textures is paletted PNG. It is the easiest format in which to distribute the textures due to its small size. Since the palette doesn't have to be the same as the game's, it should be enough for many textures. The high-resolution textures can be of any size. The engine will render them scaled so that they fit the size of the original texture. This means the aspect ratio of the new texture doesn't have to be the same as of the original texture. Note that the engine will have to resize all textures so that their dimensions are powers of two (e.g. 32, 64, 128, 256). This means TGA/PNG textures whose width and height are already powers of two can be loaded faster. Color keying is done if the file name of the image ends in "-ck", for example @file{brnbigc-ck.png}. Both cyan (0,255,255) and purple (255,0,255) are used as keys. An alternative way to have transparency is to use an alpha channel. In it, white (255) means opaque and black (0) is fully transparent. All values in between can be used, too, for partly translucent pixels. When using an alpha channel, the "-ck" suffix is not needed. To create a high-resolution texture for the wall texture STARTAN3 you'd place a TGA file named @file{STARTAN3.tga} or a PNG file named @file{STARTAN3.png} into the @file{Textures} directory. The file names of images that replace flats must begin with "Flat-", e.g. to replace the flat FLOOR7_2 you'd need to have a TGA file @file{Flat-FLOOR7_2.tga} in the @file{Textures} directory. If there are both PNG and TGA versions of the same texture, the engine will use the PNG version. Version 1.8.6 added the @file{Flats} external resource directory. In order to replace FLOOR7_2, it is enough to put @file{FLOOR7_2.png} into the @file{Flats} directory; no prefix is necessary. @notice{ The file names of the high-resolution textures must match the @em{texture} names, not the names of the patches that make up the textures. For example: DOOR2_5 is a patch name, DOOR3 is the texture that uses DOOR2_5. } To disable high-resolution textures use the command line option @opt{-nohightex}. The option @opt{-texdir} can be used to change the directory from which the textures are searched. Links to high-resolution texture sites: @ind{ @link{http://switch.to/doom2textures} @br @link{http://switch.to/heretictextures} @br @link{http://switch.to/hexentextures} } More texture-related resources are available at DoomsdayHQ: @ind{@link{http://www.doomsdayhq.com/files.php?class=4&type=3}} @section{ Patches } Patches are images that are commonly used in game menus and intermission screens. Like textures, patches can be replaced with TGA, PNG or PCX images. The @file{Patches} resource class directory is searched using the lump names of the original patches. For example, to replace the Doom menu title, you would place the file @file{m_doom.png} to the @file{Patches} directory. The original data lumps are required even if an external resource is found, because the original data includes information about offsets and the on-screen size of the patch. This means the image from the external resource can be of any arbitrary resolution: it will be scaled to match the original patch. Currently external patch resources are not precached, which may cause slight delays when the patches are first loaded. @section{ Sprite Frames } Sprite frames are patches. They can be replaced with external resources just like all other patches. The same restrictions apply, though: the dimensions of the external resource do not affect the actual size of the sprite frame. This means the external resources must really be @em{high-resolution} versions of the original images. Otherwise the size and/or aspect ratio will not be right for the resource. For example, in order to replace the Doom medikit (lump name MEDIA0), one would place the file @file{media0.png} into the @file{Patches} directory. Color-mapped versions of sprite frames can have external resources, too. To indicate that a resource is color-mapped, its name is formed like this: @ind{@file{(patchName)-table(classNum)(tableNum).ext}} @file{(patchName)} is the sprite frame lump name. @file{(classNum)} is the number of the color translation class. This number is always zero in jDoom and jHeretic. In jHexen, it's the player's class (0=Fighter, 1=Cleric, 2=Mage). @file{tableNum} is the index number of the color translation table. jDoom and jHeretic have 4 tables, jHexen has 8. For example: @file{playa1-table01-ck.png} would be the Doom player sprite frame A1 with color table 1. The @file{-ck} suffix makes the image color keyed (i.e. special colors indicate transparent pixels). @section { Raw Screens } Some background pictures are in the raw screen format, which is used to store 320 x 200 pixel paletted images. A lump containing a raw screen image (for example Heretic's TITLEPIC) is exactly 320 x 200 = 64000 bytes long. Raw screens can be replaced with external resources in the @file{Patches} directory. @section{ Light Maps } Light maps are monochrome images that can be used with dynamic lights. The dimensions of a light map must be powers of two, for example 256 x 256. If the map contains an alpha channel, the actual color values are ignored; only the alpha values are significant. If the map doesn't have an alpha channel, one is generated by averaging the color values of the image. Example: If you assign the light map "Round" to a light source, images with that file name are searched from the @file{LightMaps} directory. The accepted image formats are PCX, TGA and PNG. If @file{Round.pcx}, @file{Round.tga} or @file{Round.png} is found, it will be loaded. @section{ Music } Doomsday can play various external music files using the FMOD library (@link{http://www.fmod.org/}). FMOD supports many music file formats including MP3, OGG, MOD and S3M (mods are a good choice due to their good quality/size ratio). External music files can be played at any time using the @cmd{playext} console command. @notice{ On some systems, using FMOD with Doomsday has caused lock-ups or other unwanted behavior. If this appears to be the case for you, you should disable FMOD with the @opt{-nofmod} option. However, this will also make it impossible to play external music files such as MP3s. } Like other external resources, placing a music file into the @file{Music} resource class directory is enough. The file name must match the lump name of the original music data lump. For example, to replace the music for Doom's first episode's second map, the file @file{d_e1m2.mp3} would be placed in the @file{Music} directory. It is also possible to store music files into a WAD. Again, you must name the lumps so that they match the lumps of the original songs, and are thus loaded instead of them. Any music files supported by FMOD can be loaded from a WAD. Another way to specify an external resource file is to use the @opt{Ext} key of a Music definition (in Audio.ded). An example of editing the definitions: You have a terrific song called @file{song.mp3} and you'd like to hear it instead of Doom's regular "e1m2". @list/enum{ @item The first thing to decide is whether you want to play the song from where it's currently located, or do you want to move it under the Doomsday directory. In the latter case it would be easy to distribute the song and its definition file to others, since they wouldn't have to worry about where the music file is. If you decide to move the song, create a directory under the @file{ Doomsday\Data\jDoom\ } directory called @file{Music}. Another logical choice could be @file{ Doomsday\Music\ }. Then copy the song into the created directory. @item Open @file{Audio.ded} in a text editor. In it, you will find a bunch of Music definitions, including: @code{Music @{ ID = "e1m2"; Lump = "D_E1M2"; @} } In order to make the change persist over version upgrades (each one will overwrite @file{Audio.ded}) copy the definition to @file{User.ded} in the @file{ Defs\jDoom\ } directory, or create a new DED file with any name you like in the @file{ Defs\jDoom\Auto\ } directory. Everything in the @file{Auto} directory will be read automatically. If @file{User.ded} doesn't exist, just create a new file for it. @item Now you have the new Music definition, and the only thing left is to let the engine know which file it should load when the song "e1m2" is played. Edit your definition by adding the @opt{Ext} key: @ind{@pre{Music @{ ID = "e1m2"; Lump = "D_E1M2"; Ext = "Data\jDoom\Music\song.mp3"; @}}} } CD tracks can be associated with songs in a similar fashion, but instead of using the @opt{Ext} key you should use a @opt{CD track} key: @code{CD track = 3;} @section{ Sound Effects } Sound samples can be replaced with WAV files. The supported formats are 8-bit and 16-bit mono PCM with no compression. The @file{Sfx} resource class directory is searched using the lump names of the original samples. For example, to replace jDoom's rocket launcher sound, the file @file{dsrlaunc.wav} would be placed in the @file{Sfx} directory. Another way to specify an external resource file is to use the Sound definition @opt{Ext} key. Doomsday will automatically detect the format of a sample if it's loaded from a WAD file, making it possible to compile a WAD out of WAV samples. @chapter{ Plugins } @section{ glBSP Map Loader } It is no longer necessary to run glBSP manually on WAD files because Doomsday now includes glBSP as a plugin that is run automatically when needed. The glBSP source code is from version 1.96. The following console variables control how dpMapLoad works: @deflist{ @item{ @var{bsp-build} } This is the master switch that either enables or disables the map loader plugin. If set to zero, GL BSP data is read from any loaded GWA files and the glBSP builder in the plugin is not used. @item{ @var{bsp-cache} } Determines if cached BSP data from the @file{bspcache} directory should be used if it passes the last modification time test. If set to one, any suitable data from the @file{bspcache} directory is loaded and no new data needs to be calculated. If set to zero, the plugin will always calculate new BSP data and store it in the cache. @item{ @var{bsp-factor} } Sets the cost glBSP assigns to seg splits. The default value is 7. } The generated GL BSP data is stored in the @file{bspcache} directory. There are subdirectories for each game mode and WAD. You are free to delete the cache directory at any time. @section{ Dehacked Patches } Most features of Dehacked are supported by Doomsday's Dehacked reader. The loader will print a message during startup if an unsupported feature is used. Let's say you have the Dehacked patch @file{file.deh} in your runtime directory. Then you can use the command line option @opt{-deh file.deh} to load it at startup. If a lump named @file{DEHACKED} is found in a WAD, it will be automatically applied when the WAD is loaded. Normally only the last @file{DEHACKED} lump is used if a lump with that name is found in multiple WADs. Use the option @opt{-alldehs} to make the engine apply all found @file{DEHACKED} lumps. @chapter{ Networking } Doomsday uses both TCP and UDP for making network connections. If you are behind a firewall or you are using NAT, you must make sure that other computers are able to send network packets to your computer. This entails opening the appropriate incoming TCP/UDP ports on your firewall and/or configuring the NAT so that the correct ports are routed to your computer. All the TCP/UDP ports that Doomsday will use (in a basic setup where there is either one server or one client on a computer) are visible in the network setup screens. The corresponding console variables are @var{net-port-control} (TCP) and @var{net-port-data} (UDP). @section{Server Settings} The server uses one TCP port for listening to incoming connections. By default this is 13209 (setting the port to zero will mean 13209 will be used instead). This port must be open for incoming TCP traffic. The server also uses one UDP port of listening to incoming data messages from the clients. By default this is port 13209 (the same number as with TCP). This port must be open for incoming and outgoing UDP traffic. @section{Client Settings} The client uses one UDP port for data messages. By default this is 13209 (just like the server). This port must be open for incoming and outgoing UDP traffic. @chapter{ Known Issues } @list{ @item The list of reported bugs is on the deng Project page on SourceForge: @link{http://sourceforge.net/projects/deng/} @item Display color adjustments (gamma, contrast, brightness) are currently not functional in Linux. @item The FMOD library has been known to cause problems on some systems. If you experience sudden crashes or lock-ups, try the @opt{-nofmod} option. It may also be helpful to disable MIDI music entirely with the @opt{-nomusic} option. @item Software gamma doesn't affect MD2 skins. Use hardware gamma correction (@var{vid-gamma}, @var{vid-contrast}, @var{vid-bright}) instead. } @chapter{ Acknowledgements and Thanks } @a{acks} @strong{id Software}, for creating DOOM and then releasing its source code. @strong{Raven Software}, for creating Heretic and Hexen and then releasing their source code. @strong{Daniel Swanson}, for maintaining the jDoom Resource Pack and creating the Doomsday Engine logo. @strong{Abbs}, for maintaining the jDoom model pack and doing wonderful work on the models and particle effects. @strong{Anton Rzheshevski} (aka Cheb), for player weapon 3D models and other MD2 modifications/enhancements, maintaining the jDoom model pack and writing KickStart version 2. @strong{Greg Fisk} (Slyrr), for many excellent 3D models for jHeretic. @strong{Daniel Norton}, for the jDoom detail textures. @strong{Graham Jackson}, for helping me with the source code, fixing some Doom bugs and doing a lot of testing. All authors of the MD2 models and definition files (see the readme files under @file{ Md2\ } for more detailed info). @strong{David Jarvis}, for doing network testing with jDoom and jHeretic and generously contributing essential computer hardware components! :-) @strong{Andrew Apted}, for glBSP (@link{http://glbsp.sourceforge.net/}). @strong{William Mull}, for hosting the j-sites and bearing with me. @strong{James Bunting} and @strong{Patrick Farrell}, for providing FTP space for the Doomsday project. @strong{Darin Petersen}, for the very useful MD2 export tool QTiP. People who have sent bug reports. One can't expect me to keep coding this thing and test every possible level in case something has broken down... (Did you know that Doom, Heretic and Hexen combined have over 220 'official' levels?) By sending bug reports you can be sure I'll at least try to fix it some day. :-) People who have sent ideas for new features. My goal is not to create the most feature-packed, super-customizable FPS extravaganza but to have ports of Doom, Heretic and Hexen that play right and look nice, so I might not think of something you'd very much like to see. All DOOM / Heretic / Hexen fans, for keeping these excellent games alive. Keep on playing! Me, Jaakko Kernen, for writing this stuff! You rule! ;-D deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/cmdline.ame0000644000175000017500000003634211357170241021747 0ustar keeskees@include{jake.ah} @macro{TITLE}{ Doomsday Command Line Options } @require{amestd} @include{darktable} $ Fine-tune the text formatting. @ifdef{TXT}{ @format{!child 1 !child 2 parent thick table}{@< @n} $ Undo the default opt formatting. @format{order 1 parent opt parent !samp}{@=} @format{order -1 parent opt parent !samp}{@=} $ Quote opts in the third column. @format{order 1 parent opt parent child 3 parent2 table}{"@=} @format{order -1 parent opt parent child 3 parent2 table}{@="} } @begin CONTENTS: @contents{1} $-------------------------------------------------------------------- @chapter{ General options } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ @@@nsp{filename} } @tab @tab Response file. The given file is read and its contents are inserted to the command line, replacing the option itself. E.g. @opt{@@@nsp{args.rsp}}. @row @opt{ -- } @tab @tab Stop processing options. Anything after this is discarded. Useful in response files. @row @opt{-verbose} @tab @opt{-v} @tab Be more verbose with console messages. Two @opt{-verbose} options gives even more messages (e.g. @opt{-v -v}). @row @opt{-userdir P} @tab @opt{-ud} @tab Sets the working directory. By default the engine uses the current working directory (the one in which it was started). Relative paths in @opt{-game} and @opt{-gl} are not affected. @row @opt{-basedir P} @tab @opt{-bd} @tab Defines a custom base directory that will be prepended to some relative paths (default fonts path, model search paths, default DED file paths, default WAD file paths). E.g. the standard distribution uses @opt{-basedir ..\..}, which is the relative path from the runtime folders to the Doomsday root folder. @row @opt{-stdbasedir} @tab @opt{-sbd} @tab Use the standard base directory (@file{..\..}). @row @opt{-savedir P} @tab @tab Changes the directory where savegames will be placed. The default is @file{savegame}. @row @opt{-out F} @tab @tab Redirects output to the given file. By default all messages are printed to @file{Doomsday.out}. @row @opt{ -file F } @tab @opt{ -f } @tab Loads in the given WAD file as a startup WAD (i.e. it can't be unloaded with the @cmd{unload} command). You can give more than one WAD file as the parameter. An alternative to @opt{-file} is @opt{-iwad}, which works in the same way. @row @opt{ -game F } @tab @opt{ -g } @tab Specifies the game DLL to use (required). This must either be just the file name (@file{jDoom.dll}) or the full path to the DLL (@file{C:\Doomsday\Bin\jDoom.dll}). @row @opt{ -maxzone N } @tab @opt{ -mem } @tab Specify how much memory will be allocated for the game (@file{N} bytes). E.g. to allocate 32 Mbs: @samp{@opt{-maxzone 32m}} @row @opt{ -playdemo F } @tab @tab After initialization loads the given demo file @file{F} (which resides in the @file{Demo} subdirectory), plays it and then quits. @row @opt{ -timedemo F } @tab @tab After initialization loads the given demo file @file{F} (which resides in the @file{Demo} subdirectory), plays it in singletics mode (i.e. as fast as possible), displays frame count information and quits. @row @opt{-nowsk} @tab @tab Disable Windows system keys (@kbd{Alt-Tab} etc). @row @opt{-nomouse} @tab @tab Don't initialize mouse. @row @opt{-nojoy} @tab @tab Don't initialize joystick. } $-------------------------------------------------------------------- @chapter{ Configuration options } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ -config F } @tab @opt{-cfg} @tab Specifies the CFG file to use (for example @file{jDoom.cfg}). When the game is quit, console variable values and key bindings are written to this file. @row @opt{ -parse F } @tab @opt{-p} @tab After initialization reads the given file and executes the commands in it (by treating each read line as a console command). You can give more than one file as the parameter. @row @opt{ -cparse F } @tab @opt{-cp} @tab Same as @opt{-parse}, but executes the commands before anything is initialized (right after console variable values have been read from the default config file). You can give more than one file as the parameter. @row @opt{ -command S } @tab @opt{-cmd} @tab After initialization executes the console command @opt{S}. Note that if the command includes whitespace characters it must be quoted. E.g. to execute the command: @samp{@cmd{echo "Hello world."}} you must use the option: @samp{@opt{-command "echo ""Hello world."""}} More than one command can be given as a parameter, either as separate command line options (@opt{-cmd S S S}) or separate console commands (@opt{-cmd "S; S; S"}). } $-------------------------------------------------------------------- @chapter{ DED options } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ -def F } @tab @tab Additional Doomsday Engine Definition files to read. The specified files are read in addition to the default DED files. @row @opt{ -defs F } @tab @opt{-d} @tab Specifies the Doomsday Engine Definition files to read. You can give more than one DED file as the parameter. When using this option you must give the name of the primary DED file first (for example @file{jDoom.ded}). } $-------------------------------------------------------------------- @chapter{ Multiplayer options } @section{ Options for a server } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ -dedicated } @tab @tab Run in dedicated mode. No graphics or sounds will be initialized. The game will run in a text mode console. @row @opt{ -server } @tab @tab Start running in server mode right after startup, using TCP/IP as the network protocol. } @section{ Options for a client } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ -connect IP } @tab @tab Connect to a server running at the specified IP address immediately after startup, using TCP/IP. For example: @opt{-connect 127.0.0.1}. The port to use can be included: @opt{-connect 127.0.0.1:12345}. } $-------------------------------------------------------------------- @chapter{ Graphics options } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ -gl F } @tab @opt{ -r } @tab Specifies the rendering DLL to use (@file{drOpenGL.dll} by default). This must either be just the file name (@file{drD3D.dll}) or the full path to the DLL (@file{C:\Doomsday\Bin\drD3D.dll}). @row @opt{ -bpp N } @tab @opt{ -b } @tab Specify the color depth to use. Defaults to desktop color depth. E.g. @opt{-bpp 32} @row @opt{ -refresh N } @tab @tab Specify the refresh rate to use in fullscreen mode. Defaults to the current display refresh rate. E.g. @opt{-refresh 75} @row @opt{ -window } @tab @opt{ -wnd } @tab Start the game in a window. By default the game runs in fullscreen mode. @row @opt{ -width N } @tab @opt{ -w } @tab Game window width or horizontal display resolution. The default value for this is taken from the @var{vid-res-x} console variable. @row @opt{ -height N } @tab @opt{ -h } @tab Game window height or vertical display resolution. The default value for this is taken from the @var{vid-res-y} console variable. @row @opt{ -winsize N N } @tab @opt{ -wh } @tab Game window width and height or display resolution. @row @opt{ -xpos N } @tab @tab Game window X coordinate. @row @opt{ -ypos N } @tab @tab Game window Y coordinate. @row @opt{ -nocenter } @tab @opt{ -noc } @tab Prevents the game window from being centered on screen. @row @opt{ -modeldir P } @tab @opt{ -md } @tab Uses the given search path instead of the one specified in the primary DED file. @row @opt{-fontdir P} @tab @opt{-fd} @tab Looks in the given directory @file{P} for the font files. Defaults to @file{ Data\Fonts\ }. @row @opt{-gdifonts} @tab @tab Use Windows' GDI fonts instead of the DFNs. @row @opt{-novideo} @tab @tab Don't initialize video. @row @opt{-noramp} @tab @tab Don't use hardware color settings (gamma, contrast, brightness). @row @opt{-leaveramp} @tab @tab At shutdown, don't reset color settings (gamma, contrast, brightness) back to the original values. @row @opt{-gfxdir P} @tab @tab Sets the directory where Doomsday graphics resources are loaded. Defaults to @file{Data\Graphics}. } @section{ Textures } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ -outlines } @tab @tab All letters, sprites, etc. will have black outlines. @row @opt{ -bigmtex } @tab @tab If a masked texture has taller patches than the texture's height, the engine will resize the texture so that the largest patch will fit. @row @opt{ -anifilter } @tab @opt{ -ani } @tab Use anisotropic texture filtering. @row @opt{ -paltex } @tab @opt{ -ptx } @tab Use paletted textures (if supported by the hardware). @row @opt{ -maxtex N } @tab @tab Set maximum texture size to N x N. E.g. @opt{-maxtex 128} sets the maximum size to 128 x 128 pixels. @row @opt{ -pwadtex } @tab @tab Allow using external resources with textures/flats whose data is read from a PWAD. By default, external resources are only used with textures from an IWAD. @row @opt{-nohightex}@tab @tab Disable high-resolution (external) textures and flats. @row @opt{-nohighpat}@tab @tab Disable high-resolution (external) patches and sprites. @row @opt{-texdir P}@tab @opt{-td} @tab Loads all high-resolution (PNG, TGA, PCX) textures from the given directory @file{P}. Defaults to @file{Data\\Textures}. @row @opt{-texdir2 P}@tab @opt{-td2} @tab Secondary high-resolution (PNG, TGA, PCX) texture directory. This directory is checked first, so it can be used to override textures in the normal texture directory (@opt{-texdir}). @row @opt{-patdir P} @tab @tab Sets the directory where external resources for patches are loaded. Defaults to @file{Data\\Patches}. @row @opt{-patdir2 P} @tab @tab Secondary directory for searching external resources for patches. This is checked first, so it can be used for overriding resources in the normal @file{Patches} directory. @row @opt{-lmdir P} @tab @tab Sets the directory where light map resources are loaded. Defaults to @file{Data\\LightMaps}. @row @opt{-lmdir2 P} @tab @tab Secondary directory for light maps resources. This is checked first, so it can be used for overriding resources in the normal @file{LightMaps} directory. } @section{ OpenGL renderer } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{-vtxar} @tab @tab Use vertex arrays. Vertex arrays are usually enabled by default. @row @opt{-novtxar} @tab @tab Disable vertex arrays. Try this when experiencing rendering errors. @row @opt{-texcomp} @tab @tab Enable texture compression (if supported by the OpenGL driver). Compression is disabled by default. @row @opt{-nosgm} @tab @tab Disable the SGIS_generate_mipmap extension. Try this when experiencing texture errors. @row @opt{-allowsoftware} @tab @tab Allow using the software renderer if no 3D hardware acceleration is detected (or reported by Windows). @row @opt{-dumptextures} @tab @tab Debug: Writes Targa images out of all the textures that are loaded (mipmap level zero). } @section{ Direct3D renderer } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{-d3dcfg} @tab @tab Display the Direct3D configuration dialog. The dialog is otherwise only shown if @kbd{Ctrl}, @kbd{Shift} or @kbd{Alt} is held down when the game is started. @row @opt{-triple} @tab @tab Enable triple buffering. @row @opt{-texbits N} @tab @tab Set texture bit depth. Won't affect the default configuration in @file{drD3D.ini}. @row @opt{-zbits N} @tab @tab Set Z buffer bit depth. Won't affect the default configuration in @file{drD3D.ini}. @row @opt{-badtexalpha} @tab @tab Use as few bytes for texture alpha data as possible (with 16 bit textures causes that only one bit is used for the alpha data). @row @opt{-nodither} @tab @tab Disable dithering. @row @opt{-diag} @tab @tab Print lots of extra information about Direct3D initialization. } $-------------------------------------------------------------------- @chapter{ Sound options } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{ -csd } @tab @tab Use @file{dsCompat.dll}, the DirectSound 6 sound driver. @row @opt{ -dummy } @tab @tab Use the Dummy sound driver (does nothing). @row @opt{ -sfxchan N } @tab @tab Set the number of sound channels. 16 is the default. @row @opt{-musdir P} @tab @tab Same as @opt{-patdir} but for music resources. @row @opt{-musdir2 P} @tab @tab Same as @opt{-patdir2} but for music resources. @row @opt{-sfxdir P} @tab @tab Same as @opt{-patdir} but for sound effect resources. @row @opt{-sfxdir2 P} @tab @tab Same as @opt{-patdir2} but for sound effect resources. @row @opt{ -mdvol } @tab @tab Multiply the volume of all MIDI notes by two. The volume is still capped to the MIDI maximum of 127, though. @row @opt{ -eaxignore } @tab @tab Ignore any errors that occur with EAX. @row @opt{ -nopsf } @tab @tab Do not set the primary sound buffer format. Try this option if you notice that the audio quality of other applications (including FMOD) degrades when Doomsday is running. @row @opt{ -noeax } @tab @tab Disable EAX. @row @opt{-nopitch} @tab @tab Disable sound effect pitch/frequency changes. @row @opt{-nodop} @tab @tab Disable doppler effect (with 3D sounds). @row @opt{-nosound} @tab @tab Don't initialize sound or music. @row @opt{-nomixer} @tab @tab Don't use Windows' mixer (used for CD volume). @row @opt{-nosfx} @tab @tab Don't initialize sound. @row @opt{-nomusic} @tab @tab Don't initialize music. @row @opt{-nofmod} @tab @tab Don't initialize FMOD (@link{http://www.fmod.org/}). } $-------------------------------------------------------------------- @chapter{ Plugin options } @section{ DeHackEd reader } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{-deh F} @tab @tab Applies the Dehacked patch @file{F}. You can give more than one @file{F} as arguments, e.g. @opt{-deh first.deh second.deh}. @row @opt{-alldehs} @tab @tab Allows the processing of more than one @file{DEHACKED} lump. Otherwise only the @file{DEHACKED} lump that has been loaded last is processed. Does not affect the @opt{-deh} option. } $-------------------------------------------------------------------- @chapter{ Development options } @table/thick{25 12 63}{ @header{Option} @tab @header{Abbr.} @tab @header{Description} @row{single} @opt{-sounddebug} @tab @tab Display lots of sound debug information. @row @opt{-dump S} @tab @tab Writes the specified lump (@file{S}) into a file named @file{(S).DUM} and quits. @row @opt{-dumpfont} @tab @tab When a font is prepared it is written to a file named @file{FONT(id number).DFN}. @row @opt{-dumpwaddir} @tab @tab Prints the names of all the lumps in the loaded WAD files and quits. @row @opt{-dump_pal18to8} @tab @tab Generates a PAL18TO8 palette conversion table. If you don't know what that means you don't have to worry about this option. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/infine.ame0000644000175000017500000005175611357170241021612 0ustar keeskees@include{jake.ah} @macro{TITLE}{ InFine Scripts } @macro{VERSION}{ Version 1.1 } @require{amestd} @include{darktable} @begin CONTENTS: @contents{1} $------------------------------------------------------------------------- @chapter{ What is InFine? } InFine is a very simple scripting language used to describe the animations that are played as interludes and finales in jDoom, jHeretic and jHexen. It can also be used to define introductory animations (InFine scripts can be played before or after any map); briefings and debriefings if you will. Once a script starts playing, its commands will be executed until a wait or a pause command is encountered. The script ends when the last command of the script is executed. This means if you forgot to use any wait or pause commands the script will end immediately. Almost all numeric values (coordinates, colors, scale factors) are interpolated, i.e. their value can change gradually. The @cmd{In} command is used to set the interpolation timer, which will be effective until the next time @cmd{In} is issued. Note that interpolation only occurs while the script is waiting for something. Otherwise the script commands are executed one after another with no delay in between. The player can interact with the animation by pressing a key on the keyboard or a mouse or a joystick button. This will trigger a skip event (see the @cmd{CanSkip}, @cmd{NoSkip} and @cmd{SkipHere} commands). $------------------------------------------------------------------------- @chapter{ Script Syntax } @list{ @item Commands are case-insensitive (some arguments are not, however). @item Whitespace (spaces, tabs, newlines) is ignored. @item Comments are ignored. Comments are lines that begin with the hash character (#), or anything that begins with #> and ends in <#. @item The general syntax of a command is: @samp{(command) (arg-1) ... (arg-N) } Some commands don't need any arguments. Note that only whitespace separates the arguments. All commands have a fixed number of arguments. @item Semicolons (;) are used to mark the end of a compound. Don't use semicolons elsewhere. An example of how semicolons are used: @samp{@pre{IF commercial DO MusicOnce "dm2ttl" Wait 13 ;}} @item Strings can be split onto multiple lines (like in DED files, see Text definitions in the DED Reference). } $------------------------------------------------------------------------- @chapter{ Coordinates and Values } The whole screen is thought to be 320 pixels wide and 200 pixels tall, regardless of the actual display resolution. You can freely use fractional pixels (e.g. 104.5) for more accurate placement of objects. Color values are floating-point numbers, and must be between zero and one. An alpha value of zero means fully transparent and one means opaque. Time is generally specified in seconds. $------------------------------------------------------------------------- @chapter{ Drawing Order } @list{ @item Background flat (or a single-color background). @item Picture objects (globally offseted with @cmd{OffX} and @cmd{OffY}), in the order in which they were created. @item Text objects, in the order in which they were created. @item Filter. } Restrictions imposed by this order: @list{ @item Text can't be hidden behind pictures. @item Background flat can't be scrolled. @item Filter always affects everything. } $------------------------------------------------------------------------- @chapter{ Commands } $------------------------------------------------------------------------- @section{ Run Control } @deflist{ @item{ @cmd{DO} } Begin a compound. A semicolon ends the compound. @samp{@pre{IF commercial DO #> Here can be multiple commands spanning multiple lines. <# ; ELSE DO # More commands. ;}} @item{ @cmd{END} } End the script immediately. Normally a script ends when there are no more commands to execute. @item{ @cmd{IF} (condition) } The command following @cmd{IF} and its condition are only executed if the condition evaluates to true. The condition can be one of the following: @table{28 72}{ MODE:(game-mode) @tab True if the current game mode is (game-mode). The possible game mode strings are listed in the Doomsday Readme. For example: @cmd{MODE:doom2-plut} @row secret @tab True when a level was exited through a secret exit button. @row netgame @tab True in multiplayer games. @row deathmatch @tab True in deathmatch games. @row shareware @tab True when a shareware WAD is being used (DOOM 1, Heretic). Always false for DOOM II, Final DOOM and Hexen. @row ultimate @tab True if the game mode is "doom1-ultimate" (Doom). @row commercial @tab True if the game mode is "doom2" (Doom). @row leavehub @tab True if a hub has just been exited (Hexen). @row fighter @tab True if the player's class is Fighter (Hexen). @row cleric @tab True if the player's class is Cleric (Hexen). @row mage @tab True if the player's class is Mage (Hexen). } @item{ @cmd{IFNOT} (condition) } The command following @cmd{IFNOT} and its condition are only executed if the condition evaluates to false. The same conditions are used as with @cmd{IF}. @item{ @cmd{ELSE} } Use with @cmd{IF} and @cmd{IFNOT} to provide an alternative execution path. @item{ @cmd{MARKER} (marker-id) } Marks a position in the script that can be jumped to with the @cmd{goto} command. Don't use duplicate marker IDs. @item{ @cmd{GOTO} (marker-id) } Jumps to the given marker. The marker is searched starting from the beginning of the script, so jumps can be made both forward and backward. If the given marker is not found, the script ends. @item{ @cmd{Pause} } Pauses the execution of the script and starts waiting for the player to press a key or a button. This command is not affected by the @cmd{CanSkip} and @cmd{NoSkip} commands. When a script is paused and the player causes a skip event, only the pause mode ends, no actual skipping happens. @item{ @cmd{In} (time-sec) } Sets the interpolation timer, which is used by many commands (color settings, coordinates, etc.) to determine how quickly the changes will be effective. Example: @code{In 2 Filter 0 0 0 1 @br Wait 2} The interpolation timer is set to two seconds with the @cmd{In} command. The @cmd{Filter} command changes the screen filter to opaque black but because the interpolation timer is set to a non-zero value, the change will be gradual. In this case it will take two seconds. The @cmd{Wait} command pauses the script for two seconds, during which the filter will have time to interpolate to its destination color, i.e. opaque black. @item{ @cmd{Tic} } Pauses the script for one tic, i.e. 28.6 milliseconds (1/35 sec). @item{ @cmd{Wait} (time-sec) } Pauses the script for the specified number of seconds. @item{ @cmd{WaitAnim} (pic-id) } Pauses the script until the specified picture finishes its animation sequence. @item{ @cmd{WaitText} (text-id) } Pauses the script until the specified text object has finished typing its text. @item{ @cmd{CanSkip} } Allows the player to skip in the script by pressing a key or a button. When skipping, if no @cmd{SkipHere} is encountered, all the commands from the current position to the end of the script are ignored and the execution of the script ends. @cmd{CanSkip} is the default mode. @item{ @cmd{NoSkip} } Disable skipping. The execution of the script will continue non- interactively. Nothing happens even if the player presses a key or a button. @item{ @cmd{SkipHere} } This command only has an effect when a skip is in progress (the player has pressed a key or a button and skipping is enabled). The skipping will stop at this command and the execution of the script continues normally from the command following @cmd{SkipHere}. Note that all the skipped commands were ignored. @item{ @cmd{Events} } Enable interactive mode. After the @cmd{Events} command has been executed, the script will begin tracking input events. @item{ @cmd{NoEvents} } Disable interactive mode. This is the default. When the script is not interactive, any input events will be ignored. @item{ @cmd{OnKey} (key-name) (marker) } When a keyboard input event is detected, execution will jump to (marker). This command will only have an effect in interactive mode. Note that input events are only detected during wait periods. (key-name) must be one of the symbolic key names used by the console command @cmd{bind}. @item{ @cmd{UnsetKey} (key-name) } Clear the marker name bound to the key. (key-name) must be one of the symbolic key names used by the console command @cmd{bind}. } $------------------------------------------------------------------------- @section{ Game Control } @deflist{ @item{ @cmd{PlayDemo} (filename) } Play back a demo file. After the demo ends, the InFine script resumes execution. @item{ @cmd{Cmd} (console-command) } Execute a console command. @item{ @cmd{Trigger} } When the trigger is enabled, any input events detected during the execution of the script will activate the game menu. The trigger is enabled by default. @item{ @cmd{NoTrigger} } Disable the trigger. Input events detected during the execution of the script won't activate the game menu. } $------------------------------------------------------------------------- @section{ Audio } @deflist{ @item{ @cmd{Sound} (sound-id) } Play the specified sound. There must be a Sound definition with the given ID. @item{ @cmd{SoundAt} (sound-id) (volume) } Play a sound at the specified volume. The volume must be between zero and one, one being the maximum. @item{ @cmd{SeeSound} (thing-type) } Play the "see" sound of the given thing. There must be a Thing definition with a matching ID. @item{ @cmd{DieSound} (thing-type) } Play the "death" sound of the given thing. There must be a Thing definition with a matching ID. @item{ @cmd{Music} (music-id) } Start playing a song. There must a Music definition with a matching ID. (Except in Hexen, where songs are identified by their lump names.) The song is played in looped mode. @item{ @cmd{MusicOnce} (music-id) } Same as @cmd{music}, but (if possible) plays the song only once. @item{ @cmd{NoMusic} } Stop the currently playing song. } $------------------------------------------------------------------------- @section{ Screen Control } @deflist{ @item{ @cmd{Color} (red) (green) (blue) } Set the background color. If no background flat is specified, the whole screen is filled with this color. The color values are given as floating-point numbers, and must be between zero and one. The default background color is white (@cmd{Color 1 1 1}). @item{ @cmd{ColorAlpha} (red) (green) (blue) (alpha) } Set the background color and alpha. Set alpha to zero to make the background fully transparent. @item{ @cmd{Flat} (flat-lump) } Set the flat that is used as a tiled background. Give the name of the flat as an argument, for example: @code{flat FLOOR4_8} The flat will be tinted with the background color. @item{ @cmd{NoFlat} } Clears the currently selected background flat. @item{ @cmd{OffX} (pixels) } A general X offset that affects all pictures. @cmd{OffX 160} would appear to move the origin of the screen 160 pixels to the right (half a screen). Note that only picture objects are affected. @item{ @cmd{OffY} (pixels) } A general Y offset that affects all pictures. @item{ @cmd{Filter} (red) (green) (blue) (alpha) } Set the screen filter. The alpha value defines how strong the filter appears, the following would make the whole screen red: @code{Filter 1 0 0 1} } $------------------------------------------------------------------------- @section{ Objects } @deflist{ @item{ @cmd{Del} (object-id) } Delete an object. @item{ @cmd{X} (object-id) (x) } Move the specified object to the given X coordinate. @item{ @cmd{Y} (object-id) (y) } Move the specified object to the given Y coordinate. @item{ @cmd{Angle} (object-id) (degrees) } Rotate the specified object. Positive angles rotate the object in the clockwise direction. @item{ @cmd{Sx} (object-id) (scale) } Scale the specified object with the given horizontal scaling factor. @item{ @cmd{Sy} (object-id) (scale) } Scale the specified object with the given vertical scaling factor. @item{ @cmd{Scale} (object-id) (scale) } Scale the specified object with the given scaling factor. @item{ @cmd{ScaleXY} (object-id) (x-scale) (y-scale) } Scale the specified object with the given horizontal and vertical scaling factors. @item{ @cmd{RGB} (object-id) (red) (green) (blue) } Set the specified object's color. The color values are floating-point numbers between zero and one. @item{ @cmd{Alpha} (object-id) (alpha) } Set the specified object's alpha level. The alpha level is a floating- point number between zero and one, zero being fully transparent and one fully opaque. } $------------------------------------------------------------------------- @subsec{ Rectangles } @deflist{ @item{ @cmd{Rect} (rect-id) (x) (y) (width) (height) } Create a rectangle object. @item{ @cmd{XImage} (rect-id) (external-gfx-resource) } Change the background of a rectangle object to the specified graphics resource. Do not use a file name extension (for example, @cmd{XImage R "Mouse"}). @item{ @cmd{FillColor} (rect-id) (@cmd{TOP}|@cmd{BOTTOM}|@cmd{BOTH}) (r) (g) (b) (a)} Change the fill color of a rectangle object. You can create a gradient by setting the @cmd{TOP} and @cmd{BOTTOM} colors to different values. @item{ @cmd{EdgeColor} (rect-id) (@cmd{TOP}|@cmd{BOTTOM}|@cmd{BOTH}) (r) (g) (b) (a)} Change the edge color of a rectangle object. You can create a gradient by setting the @cmd{TOP} and @cmd{BOTTOM} colors to different values. } $------------------------------------------------------------------------- @subsec{ Pictures } @deflist{ @item{ @cmd{Image} (pic-id) (image-lump) } Create a picture object. It will be associated with the ID of your choosing. The ID can be any text string but naturally it's best to use descriptive IDs like "back". The (image-lump) is the name of a lump that contains a 320x200 raw image. Raw images are usually exactly 64000 bytes long. You can also insert a PCX image directly into a WAD file and specify its lump name; the @cmd{Image} command accepts PCX images as well as normal raw images. @item{ @cmd{ImageAt} (pic-id) (x) (y) (image-lump) } Works like "image", but lets you specify the initial location of the image. This is not usually needed since the default initial location is (0,0) and images cover the whole screen (320x200). @item{ @cmd{Patch} (pic-id) (x) (y) (patch-lump) } Create a picture object out of a patch image. Patches are the internal image format of DOOM. It's most commonly used by the sprites (all sprite frames as patches). Patches can have transparent pixels (e.g. all the characters of the DOOM font are patches). (pic-id) is a text string of your choosing. (patch-lump) is the name of the lump that contains the patch image. @item{ @cmd{Set} (pic-id) (patch-lump) } Set the patch of an existing picture object. Only the patch lump of the picture object is changed, other parameters like position and scaling remain the same. @item{ @cmd{ClrAnim} (pic-id) } Clear the specified picture object's animation sequence. @item{ @cmd{Anim} (pic-id) (patch-lump) (time-sec) } Append a new frame to the picture's animation sequence. (time-sec) is the number of seconds that the new frame will last. @item{ @cmd{ImageAnim} (pic-id) (image-lump) (time-sec) } Append a new frame to the picture's animation sequence. The frame is a raw image (320x200 fullscreen image, can also be a PCX image). You can't use @cmd{Anim} and @cmd{ImageAnim} in the same picture's animation. @item{ @cmd{PicSound} (pic-id) (sound-id) } Associate a sound with the last frame of the specified picture's animation sequence. A sound definition with (sound-id) must exist. @item{ @cmd{Repeat} (pic-id) } End the picture's animation sequence in a repeat marker. When the repeat marker is reached, the animation will continue from the first frame of the sequence. @item{ @cmd{States} (pic-id) (state-id) (count) } Append (count) frames to the specified picture's animation sequence, starting from the the state (state-id). For example: @code{States mo BOSS_RUN1 12} This will append 12 frames starting from the state BOSS_RUN1 to the animation sequence of the picture object named "mo". } $------------------------------------------------------------------------- @subsec{ Text } @deflist{ @item{ @cmd{Text} (text-id) (initial-x) (initial-y) (string) } Create a text object with the ID (text-id). The ID is a text string of your choosing. You will need it when you later refer to the text object. The text object's upper left corner is placed at the given initial coordinates. In jDoom the text is red by default. In jHeretic and jHexen the default color is white. Escape sequences that can be used in the text string: @table{20 80}{ \n @tab Newline @row \" @tab Double quote (") @row \_ @tab Space @row \w @tab Pause of 0.5 seconds @row \W @tab Pause of 1 second @row \p @tab Pause of 5 seconds @row \P @tab Pause of 10 seconds @row \0 @tab Text color changed to the text object's color @row \1 @tab Predefined color 1 @row \2 @tab Predefined color 2 @row : @tab @row \9 @tab Predefined color 9 } @item{ @cmd{TextDef} (text-id) (initial-x) (initial-y) (def-id) } Create a text object with the ID (text-id). Works like @cmd{Text}, but the text itself is taken from the Text definition with the ID (def-id). @item{ @cmd{TextLump} (text-id) (initial-x) (initial-y) (lump) } Create a text object with the ID (text-id). Works like @cmd{Text}, but the text itself is taken from the lump named (lump). @item{ @cmd{SetText} (text-id) (string) } Change a text object's text to the given string. No other properties of the object are modified. @item{ @cmd{SetTextDef} (text-id) (text-id) } Change a text object's text to the string from the Text definition with the ID (text-id). @item{ @cmd{PreColor} (color-number) (red) (green) (blue) } Modify a predefined color. The color values must be floating-point values between zero and one. There are nine color settings you can use as (color-number): 1-9. For example, this'll change the predefined color number 4 to bright green. @code{PreColor 4 0 1 0} By default all the predefined colors are set to white (1 1 1). Use the escape sequences \1...\9 in the text string of a text object to force the text to be drawn using a predefined color. @item{ @cmd{Center} (text-id) } The text of the specified text object will be drawn centered horizontally around the X coordinate of the object. 160 is the middle of the screen. @item{ @cmd{NoCenter} (text-id) } The text of the specified text object will be drawn in the normal fashion, flushed to the left. The X coordinate of the object specifies the left edge of the text. @item{ @cmd{Scroll} (text-id) (speed) } Set a scrolling speed for the specified text object. Scrolling means that the object is automatically moved upwards. (speed) is the number of 35 Hz tics in which the object moves upward one pixel. If (speed) is zero, the scrolling is stopped. At the speed of 1, the object will move upwards 35 pixels per second. That is the fastest speed you can achieve using this command. Note that you can scroll the text however you want with the @cmd{In} and @cmd{Y} commands. @item{ @cmd{Pos} (text-id) (type-pos) } Set the text object's cursor to the given position. The cursor is actually a counter that counts how many characters of the text object's text string are visible. The command @code{Pos mytext 0} would rewind the text object "mytext" so that it would start typing its text from the beginning. @item{ @cmd{Rate} (text-id) (rate-tics) } Set the typing speed of the specified text object. The typing rate is given as the number of 35 Hz tics to wait after typing each character. This means at the rate of 1 the text is typed at 35 characters per second. At rate 2 the speed would be 17 characters per second, and so on. 35 characters per second is the fastest speed possible. At rate zero the whole text is immediately visible. @item{ @cmd{FontA} (text-id) } Set a text object's font to Font A, which is the smaller of the available fonts. The line height is modified to match the font. @item{ @cmd{FontB} (text-id) } Set a text object's font to Font B, which is the larger of the available fonts. The line height is modified to match the font. Note that jHeretic and jHexen have only colored versions of Font B (jHeretic: green, jHexen: red), which rather limits the set of colors you can use with this font. @item{ @cmd{LineHgt} (text-id) (pixels) } Set the line height of a text object. The default setting depends on the game you're using. } $------------------------------------------------------------------------- @chapter{ Links } Doomsday Engine: @link{http://www.doomsdayhq.com/} deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/ame/jake.ah0000644000175000017500000000036311357170241021066 0ustar keeskees$ My contact info. @macro{AUTHOR}{ Jaakko Kernen } @macro{EMAIL}{ skyjake@@doomsdayhq.com } @macro{LINK}{ http://www.doomsdayhq.com/ } @macro{LINK2}{ http://deng.sourceforge.net/ } @macro{HTMLHEADER}{ @tag{}@apply{@n}{.} } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/deddoc.txt0000644000175000017500000016132411357170241021070 0ustar keeskees Doomsday Engine Definitions Reference (or "Knee-Deep In The DED") ===================================== $Id$ Contact if you have any questions. --------------------------------------------------------------------------- GENERAL SYNTAX --------------------------------------------------------------------------- Elements of a DED file: * Comments There are two kinds of comments: single-line and multi-line. Single line comments begin with a hash character (#) and continue until end of line. The parser will skip everything on the line after the # character. Multi- line comments begin with #> and continue until <# is found. An example: #> The comment begins... And continues ...and ends here <# * Header block Use of the Header block is optional. For example: Header { Version = 6; } In DED version 5, there must be a semicolon after each statement, including blocks inside definition blocks. In version 6, semicolons are optional. If you don't include a version declaration, version 6 is assumed. * Directives * Definition blocks * Attributes The "Copy" attribute can be replaced with an asterisk (*). * Keys * String values Strings begin and end in double quotation marks ("). If newline characters are found inside a string (the string has been divided into multiple lines) the newline and all following whitespace are skipped, and the actual string continues from the first non- whitespace character that follows. --------------------------------------------------------------------------- DIRECTIVES --------------------------------------------------------------------------- ........................................................................... Include "Other.ded"; # The Include directive causes the parser to read the specified DED # file. The contents of the included file are read immediately after # the directive has been parsed. IncludeIf -option "Other.ded"; # The specified DED file is included if the option "-option" is (not) # found in the command line. Alternatively "-option" can be a game # mode string: IncludeIf doom1-ultimate "Other.ded"; # The specified DED file is included if the string matches (or does # not match) the current game mode. SkipIf -option; # The rest of the file is skipped if the option "-option" is (not) # found in the command line. Alternatively "-option" can be a game # mode string. SkipIf doom1-ultimate; # The rest of the file is skipped if the string matches (or does not # match) the current game mode. ModelPath "MD2\Game\Item"; # The ModelPath directive appends a new path to the list of model # search paths. NOTE: This directive has no scope: it affects all the # definitions that come before and after it. Also, be careful with # backslashes. Since they are used as escape characters in strings you # can't for example do this: "MD2\Game\Path\". That would mean the last # character of the path is " but the string itself doesn't end. You can # use forward slashes instead of backslashes. ........................................................................... --------------------------------------------------------------------------- THING DEFINITIONS --------------------------------------------------------------------------- ........................................................................... Thing { ID = ""; DoomEd number = 0; Name = ""; # The real name of this thing, for example "Bag of Holding". # Currently not used by the engine. Spawn state = ""; See state = ""; Pain state = ""; Melee state = ""; Missile state = ""; Crash state = ""; Death state = ""; Xdeath state = ""; Raise state = ""; See sound = ""; Attack sound = ""; Pain sound = ""; Death sound = ""; Active sound = ""; Reaction time = 0; Pain chance = 0; Spawn health = 0; Speed = 0.0; Radius = 0.0; Height = 0.0; Mass = 0; Damage = 0; Flags = ""; Flags2 = ""; Flags3 = ""; Misc1 = 0; Misc2 = 0; Misc3 = 0; Misc4 = 0; } ........................................................................... --------------------------------------------------------------------------- STATE DEFINITIONS --------------------------------------------------------------------------- ........................................................................... State { ID = ""; # Identifier of this state. Flags = ""; Sprite = ""; Frame = 0; # Sprite frame. OR with 0x8000 (32768) to make fullbright. Tics = 0; Action = ""; # Name of the action function of this state. Next state = ""; Misc1 = 0; Misc2 = 0; Misc3 = 0; } ........................................................................... --------------------------------------------------------------------------- SPRITE DEFINITIONS --------------------------------------------------------------------------- ........................................................................... Sprite { ID = ""; # Name of the sprite. Must be four characters long. Sprite # frame lump names always begin with a sprite ID. } ........................................................................... --------------------------------------------------------------------------- LIGHT DEFINITIONS --------------------------------------------------------------------------- The engine usually calculates the properties of dynamic lights based on the sprite frame of the light source. Any zero values in the Light definition will be replaced by these automatic calculations (zero is the default for all keys). ........................................................................... Light { # If "Copy" is found all the data of the previous definition is # copied to this one as defaults. For the first definition in a # file "Copy" has no effect. State = ""; # The State with which the light properties defined here will # be used. Flags = ""; # lgf_nohalo: No lens flare (halo) is rendered. X Offset = 0.0; # In pixels, offset from the center of the source. The offset # is parallel with the view plane. Y Offset = 0.0; # In pixels, offset from the top of the source object. Size = 0.0; # Size (strength) of the light. Should be between 0 and 1. Red = 0.0; # Red color component (0-1). Green = 0.0; # Green color component (0-1). Blue = 0.0; # Blue color component (0-1). Color { 0.0 0.0 0.0 }; # Sets all three color components at the same time. Top map = ""; Bottom map = ""; Side map = ""; # Name of the light map to use. The top map is used for ceiling # planes, the bottom map for floors and the side map for walls. # If left blank (the default), the standard round dynlight texture # is used. Use "-" to disable a map entirely. No light will then be # cast in the direction. } ........................................................................... --------------------------------------------------------------------------- DECORATION DEFINITIONS --------------------------------------------------------------------------- You can define multiple Decorations for the same texture/flat, but only the latest one that passes the conditions will be used. By default (if you specify no usage flags), a Decoration is only used with resources loaded from an IWAD. ........................................................................... Decoration { # If "Copy" is found all the data of the previous definition is # copied to this one as defaults. For the first definition in a # file "Copy" has no effect. Texture = ""; # Name of the texture with which this decoration is used. Flat = ""; # Name of the flat with which this decoration is used. You can # only specify either a Texture or a Flat, not both. Flags = ""; # dcf_noiwad: Don't use this decoration if the resource is loaded # from an IWAD. # # dcf_pwad: This decoration can be used with PWAD resources (for # example custom textures). # # dcf_ext: This decoration can be used with external resources. Light { # Each decoration can specify up to 8 lights. Offset { 0.0 0.0 }; # Origin of the light in texture coordinates. Distance = 1.0; # Distance between the origin of the light and the surface. Color { 0.0 0.0 0.0 }; # RGB color (values 0-1) of the light. Color (0,0,0) marks # the end of the light definitions. Any lights that follow are # not rendered. Radius = 1.0; # Radius of the dynamic light. Halo radius = 0.0; # Radius of the halo. Zero means no halo is rendered. Note # that halo radius 1.0 produces quite a large flare. Flare texture = 0; # Texture to use for the primary flare (i.e. the halo itself): # 0 = Texture chosen automatically. # 1 = Default dynamic light texture. # 2 = FLARE. # 3 = BRFLARE. # 4 = BIGFLARE. Top map = ""; Bottom map = ""; Side map = ""; # Name of the light map to use. The top map is used for ceiling # planes, the bottom map for floors and the side map for walls. # If left blank (the default), the standard round dynlight # texture is used. Use "-" to disable a map entirely. No light # will then be cast in the direction. Levels { 0 0 }; # Two integers (0-255) that mark the sector light levels where # the light is at zero and maximum brightness, respectively. # For example, the levels { 100 200 } mean that the light is # not visible under light level 100, fades gradually to full # brightness when nearing light level 200, and stays full # bright over 200. The first level can be higher than the # second. The behaviour is then reversed: the light is at full # brightness only below the lower light level. Pattern skip { 0 0 }; # Normally the light is repeated on a surface as many times as # the texture or flat repeats. The pattern skip values allow # sparser repeats for horizontal and vertical patterns, # respectively. For example, the skips { 1 2 } will make the # light only appear on every second horizontal repeat and # every third vertical repeat. Pattern offset { 0 0 }; # Used with pattern skip to offset the origin of the pattern. # For example, the offset { 1 0 } will shift the origin of the # pattern one full horizontal repeat. }; } ........................................................................... --------------------------------------------------------------------------- DETAIL TEXTURE DEFINITIONS --------------------------------------------------------------------------- General detail texture strength, scaling and maximum distance can modified with the "detail" console command. One Detail definition can be used to assign a detail texture to one wall texture and/or one flat picture. ........................................................................... Detail { # If "Copy" is found all the data of the previous definition is # copied to this one as defaults. For the first definition in a # file "Copy" has no effect. Wall = ""; # Name of the wall texture which this detail texture should be # associated with. Flat = ""; # Name of the flat which this detail texture should be # associated with. Lump = ""; # Lump name of the detail texture (e.g. "DTLROUGH"). This must # be a 64x64, 128x128 or 256x256 raw image with one color # component (a black and white image). This means the size of # the lump can be either 4096, 16384 or 65536 bytes. Scale = 1.0; # Relative scaling for the detail texture. Actual scaling is # calculated with (Scale)*(common-scaling-factor). The default # value for the common scaling factor is 4 (which means one # world unit corresponds four detail texture pixels). Strength = 1.0; # Relative intensity factor. Actual strength is calculated # with (Strength)*(common-strength-factor). The default value # for the common strength factor is 0.5. Distance = 0.0; # Maximum distance at which the detail texture is visible. If # left at zero, the common maximum distance is used (default: # 256). Smaller maximum distances may cause problems with # floors and ceilings, where big polygons cause inaccuracies # in the calculation of eye -> vertex distance. } ........................................................................... --------------------------------------------------------------------------- REFLECTION DEFINITIONS --------------------------------------------------------------------------- ........................................................................... Reflection { Texture = ""; # The wall texture this reflection will be associated with. A # reflection can only be associated with either a texture or a # flat, not both. Flat = ""; # The flat this reflection will be associated with. Blending mode = add; # One of the bm_* flags defined in Flags.ded. By default # reflections use additive blending. Shininess = 1.0; # Strength of the shiny effect. 1.0 is the maximum value. This # is used as the alpha component when doing blending. Min color { 0.0 0.0 0.0 } # By default the shiny effect uses sector light as the basic color # of the effect. The Min color RGB values (0..1) can be used to # set a minimum light level for the effect so it'll show up even # in very dark sectors. Shiny map = ""; # Name of the external resource that is used as the shiny map for # this reflection. By default the resource is searched in the # LightMaps resource directory. The shiny map is mapped onto # reflecting surfaces using a mapping that resembles cylindrical # environment mapping. The dimensions of the map must be powers # of two, for example 128 x 64 or 32 x 128. Mask map = ""; # Name of the external resource that is used to mask out the # shininess of a surfaces. The mask map is mapped onto surfaces # using the same texture coordinates that are used for mapping # regular textures. The darker the texel in the mask, the fainter # the reflection becomes. The dimensions of the map must be powers # of two, for example 128 x 64 or 32 x 128. Mask width = 1.0; # A factor for the width of the mask. This can be used to make the # mask span beyond the mapping of the regular texture of the # surface. For example, consider a surface with a texture that is # 64 texels wide. Regardless of the mask's horizontal resolution, # the mask is always mapped onto the regular texture so that their # edges overlap. If the mask width value is 1.0, the mask is as # wide as the 64 texel original texture. If mask width is increased # to 2.0, the mask is mapped so that it is as wide as a 128 texel # texture. Mask height = 1.0; # A factor for the height of the mask. } ........................................................................... --------------------------------------------------------------------------- GENERATOR DEFINITIONS --------------------------------------------------------------------------- A particle generator must always be triggered somehow to be spawned. There are four types of triggers available: State, Type, Flat and Map. The trigger also determines the generator's source, from which the generator's particles seem to originate. A generator must have a source to be able to create new particles. If the source of a generator is destroyed before the generator dies, the only result will be that no new particles are created. Any existing particles created prior to the removal of the source will live on. State triggering means that the generator is spawned when any mobj enters the state the generator has been associated with. The mobj in question will become the source of the generator. State triggering is especially useful with "one time" effects such as explosions. State triggering should be avoided with mobjs that have a loop of states (if the gnf_spawn flag is not used). This can lead to generators being spawned more frequently than necessary. All Type triggered generators are spawned at the beginning of a level. Each Type triggered Generator definition gets its own particle generator entity. Type triggering makes the generator multi-sourced: all mobjs in the level with one of the types associated with the generator will act as particle sources. The effect is similar to having a separate generator for each mobj. Note, however, that you need to allocate a fairly large number of particles in the definition since all the mobjs use the same generator. Flat triggering works a bit differently. The level is periodically checked for any planes with the specified flat as texture (floors and ceilings). A generator is spawned for all planes that match the associated flat. The sector to which the plane belongs will become the source of the generator. The origin of the particles can be the ceiling or floor plane, or the space in between. The default behaviour can be modified using the gnf_floor, gnf_ceiling and gnf_space flags. Each plane can have only one generator, i.e. each sector can have up to two generators. Map triggered generators are all spawned in the beginning of a level, but only if the level has a map ID that matches the generator's. Map triggered generators use the Center key to define their origin because they haven't got an object as a source. The Center is interpreted as world coordinates (X,Y,Z). When using map triggered generators it's probably best to set the Max age and Spawn age keys to -1, to allow the generator to operate indefinitely. There is a limit to the number of active particle generator entities in the level (currently 96). If the maximum number is reached, existing non-static generators will be destroyed to make room for any new generators. ........................................................................... Generator { State = ""; # Particle generators can be either State, Flat or Type # triggered. Whenever a mobj is set to this state, a new # particle generator is spawned. If the gnf_spawn flag is set, # the generator is only spawned when the source mobj itself is # being spawned; handy if the mobj has a loop of states and # the generator should only be spawned when the state is first # set. Flat = ""; # Makes this a Flat triggered generator. Each plane with the # given flat receives its own generator. The gnf_* flags can # be used to control where the particles are actually spawned. Mobj = ""; # Makes this a Type triggered generator. The value must be a # defined thing ID (e.g. "PLAYER"). All Type triggered generators # are spawned in the beginning of a level, and they create # particles using all mobjs of the given type as sources. Use the # gnf_static flag to prevent the generator from being removed by # later generators (could happen when the maximum number of # generators is reached). Alt mobj = ""; # Alternate mobj type for Type triggered generators. Damage mobj = ""; # Makes this a Damage triggered generator. They are spawned when a # mobj of the specified type receives damage. The initial movement # direction is calculated from the positions of the mobjs involved # in the operation, so that positive speed values will make the # particles move away from the inflictor (in the direction of the # damage). # # NOTE: Damage triggered particle generators currently do not work # on the clientside (netgames and demos). Map = ""; # Makes this a Map triggered generator. The generator is spawned # only in the specified map (e.g. "E2M3"). The Center key defines # the spawn origin. Flags = ""; # gnf_static: Generator will not be removed until it times # out. Otherwise it might get replaced by newer # generators if there are too many active generators. # # gnf_extra: (State triggered) This generator is to be spawned # simultaneously with the previously defined generator. This # allows having multiple generators assigned to the same # state. If this flag is not used, all the previously # defined generators associated with the state are ignored. # # gnf_srcvel: (State/Type triggered) Particles inherit their # source's velocity (in addition to spawn velocity). # # gnf_srcdir: (State/Type triggered) Particle movement vector # is rotated using source's direction angle. # # gnf_spawn: Generator is only spawned if the source mobj is # being spawned. # # gnf_blendadd: Particles of the generator are rendered using # additive blending ('gnf_blend' is an alias for this). # # gnf_blendrsub: Particles of the generator are rendered using # reverse subtractive blending (framebuffer - particle). # # gnf_blendsub: Particles of the generator are rendered using # subtractive blending (particle - framebuffer). # # gnf_blendmul: Particles of the generator are rendered using # multiplicative blending (particle * framebuffer). # # gnf_blendimul: Particles of the generator are rendered using # inverse multiplicative blending ((1-ptc) * framebuffer). # # gnf_modelonly: The particle generator will only be active # if the source is represented by a 3D model. # # gnf_floor: (Flat triggered) Particles of the generator will # be created on the floor of the source sector. # # gnf_ceiling: (Flat triggered) Particles of the generator # will be created in the ceiling of the source sector. # # gnf_space: (Flat triggered) Particles of the generator will # be spawned at a random height in the sector. # # gnf_density: (Flat triggered) The "Particles" key specifies # the maximum density of particles per block (128x128) # rather than the maximum number of particles for the # generator. Speed = 0.0; # Initial speed for new particles. Speed Rnd = 0.0; # Randomness of initial particle speed (between 0 and 1): # 0 = Not random at all. # 1 = Randomly scaled between zero and the value of "Speed". Vector { 0.0 0.0 0.0 }; # Initial movement direction for new particles. Vector Rnd = 0.0; # Randomness of initial particle direction. Random components # of the given value are added to "Vector". For example, if # "Vector Rnd" is 2, a random vector with components ranging # from -2 to 2 is added to "Vector". Init Vector Rnd = 0.0; # One-time random component applied to "Vector" when the generator # is spawned. Works as Vector Rnd, but only applied once. Center { 0.0 0.0 0.0 }; # (State/Type triggered) An offset to the source coordinates. # X = Distance on the XY plane (world units), rotated using # source angle. # Y = Source angle offset (degrees). # Z = Z distance (positive is upwards, world units). # # (Map triggered) Coordinates of the origin (X, Y, Z). Submodel = -1; # (State/Type triggered) If the source is represented by a 3D # model, this submodel's center will be used as the origin of the # generator. If less than zero, the source's actual coordinates # are used and the model has no effect on the origin's position. Spawn radius = 0.0; # Particles will be spawned at a random distance from the center of # the source, at a distance of at most this many units. A flat # distribution inside a cube is used if the Min spawn radius is # zero. Min spawn radius = 0.0; # Particles will be spawned at least this many units away from the # center of the source. Setting this to a nonzero value will enable # the more advanced algorithm for choosing particle spawn # coordinates: a random point is chosen inside a sphere with the # radius of Spawn radius, but not closer than Min spawn radius. Distance = 0.0; # Maximum distance at which the particles of the generator are # visible. If zero, there is no distance limitation. Spawn age = 0; # Number of tics that the generator will create new particles # after having been spawned. If -1, the generator will # continue creating new particles until destroyed. Max age = 0; # Maximum generator lifetime, in tics. If -1, the generator # will not be destroyed until either replaced by a newer # generator or the level ends. Particles = 0; # Maximum number of particles that the generator can have, or # the maximum density of particles per 128x128 block (with # Flat triggered generators using the gnf_density flag). Spawn rate = 0.0; # Number of new particles spawned per game tic. Fractional # values are allowed (< 1.0). Spawn Rnd = 0.0; # Randomness of spawn rate (between 0 and 1): # 0 = Not random. # 1 = Spawn rate is randomly scaled between zero and the value # of "Spawn rate". Presim = 0; # Number of tics to "think ahead" when the generator is # spawned. Useful for Flat triggered generators that are # visible right after starting a level. Alt start = 0; # Index number of the alternative particle start stage. By # default all particles start from stage zero. Alt Rnd = 0.0; # Randomness of initial particle stage (between 0 and 1): # 0 = Default stage (zero) is always used. # 0.5 = 50% chance of starting with Alt start. # 1 = Always start from Alt start. Force = 0.0; # Strength of the sphere force that pulls or pushes particles # towards the surface of the sphere. In most cases the value should # be less than one. Force radius = 0.0; # Radius of the sphere for sphere force. The force will push or # pull particles to the surface of this sphere, centered around the # center of the generator (with the offset specified with Force # origin applied). Force origin { 0.0 0.0 0.0 }; # Defines the coordinates for the force sphere in relation to the # center of the source. Force axis { 0.0 0.0 0.0 }; # The sphere force can also rotate particles around an axis. The # length of the axis defines how strong the rotation is. Stage { # Each generator can have up to 32 particle stages. Each # particle will go through the defined stages starting from # zero or the alternative start stage. Type = ""; # pt_point: Render particle as a point. # # pt_line: Render particle as a line. The length of the # line depends on the speed of the particle. # # pt_texNN: Use Data\\Textures\ParticleNN. # # pt_modelNN: Use Model definition with ID "ParticleNN". Tics = 0; # Number of tics that the particle will spend in this # stage. Rnd = 0.0; # Randomness of stage tics (between 0 and 1). Color { 0.0 0.0 0.0 0.0 }; # RGBA color of the stage (components between 0 and 1). # The fourth component of the color vector is the alpha # component: 1 = opaque, 0 = fully transparent. Radius = 0.0; # Radius of the particle at this stage, in world units. # The visible radius is interpolated between the radii of # the current stage and the next one. Radius Rnd = 0.0; # Randomness of particle radius. The radius of a particle will # be randomly chosen from the range: # (1 - RadiusRnd)*Radius ... Radius Flags = ""; # ptf_stagetouch: When touching a wall or a plane, the # particle will immediately skip to the next stage. # # ptf_stagevtouch: Only applies to walls. # # ptf_stagehtouch: Only applies to planes. # # ptf_dietouch: Particle will die when it touches a wall # or a plane. # # ptf_bright: Particle's color is not affected by the # light level of the sector it's in. # # ptf_flat: When touching a wall or a plane, the particle # is rendered flat against the surface. # # ptf_vflat: Only applies to walls. # # ptf_hflat: Only applies to planes. # # ptf_force: Particle is affected by the sphere force. # # ptf_zeroyaw: Set particle yaw to zero. # # ptf_zeropitch: Set particle pitch to zero. # # ptf_rndyaw: Set particle yaw to a random value. # # ptf_rndpitch: Set particle pitch to a random value. Bounce = 0.0; # Determines how 'bouncy' the particle is (0..1): # (particles will only collide with walls and planes) # 0 = Particle loses all its momentum when it hits # something (in the direction of the collision). # 1 = Particle retains all its momentum and continues # moving in the opposite direction after a collision. # >1 = Particle gains extra speed in collisions. Gravity = 0.0; # Determines how strong an effect gravity has on the # particle. Normal mobjs have a Gravity factor of 1.0. Force { 0.0 0.0 0.0 }; # A linear force that affects the particle during this stage. # Gravity = 1 would correspond Force { 0 0 -1 }. This force is # applied independently of sphere force. Resistance = 0.0; # Air resistance for the particle (between 0 and 1): # 0 = Particle moves without friction. # 0.5 = Particle loses half of its momentum each tic. # 1 = All movement of the particle will stop in one tic. Spin resistance { 0 0 } # Factors for slowing down particle spinning (0..1). Frame = ""; # First model frame in the animation sequence of a model # particle. The animation will interpolate through all the # frames between Frame and End frame. End frame = ""; # Last model frame in the animation sequence of a model # particle. Spin { 0.0 0.0 }; # Model particle spinning velocity (yaw and pitch, # respectively) in degrees per second. Each particle will # randomly change the sign of the spinning velocity when the # particle is first spawned. Sound = ""; # ID of the sound to play when a particle enters this stage. # Sound will use the particle's coordinates as its origin. Use # carefully: starting a lot of sounds is a heavy operation. Volume = 1.0; # Volume of "Sound" (0...1). Hit sound = ""; # ID of the sound to play when a particle hits a surface while # in this stage. Sound will use the particle's coordinates as # its origin. Use carefully: starting a lot of sounds is a # heavy operation. Hit volume = 1.0; # Volume of "Hit sound" (0...1). }; } ........................................................................... --------------------------------------------------------------------------- SOUND DEFINITIONS --------------------------------------------------------------------------- ........................................................................... Sound { ID = ""; Lump = ""; Name = ""; Link = ""; Link pitch = 0; Link volume = 0; Priority = 0; Max channels = 0; Flags = ""; Ext = ""; File = ""; # Same as "Ext" File name = ""; # Same as "Ext" # External sound file. Must be a mono WAV file with no # compression. If specified, this sound file will be played # instead of the sound data in Lump (if a Lump is defined). # Relative paths are interpreted in relation to the base path, so # "Sound/Kaboom.wav" becomes "/Sound/Kaboom.wav". } ........................................................................... --------------------------------------------------------------------------- MUSIC DEFINITIONS --------------------------------------------------------------------------- ........................................................................... Music { ID = ""; # The ID of the song. Lump = ""; # Name of a lump containing a MUS song. Ext = ""; File = ""; # Same as "Ext" File name = ""; # Same as "Ext" # External music file. Played using FMod. This can either be a # file name (e.g. "c:\music\song.mp3") or a CD track (e.g. # "cd:8"). Supports many kinds of music files, see # http://www.fmod.org/ for details. Relative paths are # interpreted in relation to the base path, so "Music/Rock.mp3" # becomes "/Music/Rock.mp3". CD track = 0; # Overrides "cd:" in the Ext key. } ........................................................................... --------------------------------------------------------------------------- TEXTURE ENVIRONMENT DEFINITIONS --------------------------------------------------------------------------- The Texture Environment definitions are used to calculate the 3D sound characteristics of the sectors in a map. ........................................................................... Texture Environment { ID = ""; # Identifier of this environment. Must be either "Metal", # "Rock", Wood" or "Cloth". Texture { # There can be any number of Texture blocks inside a Texture # Environment definition. ID = ""; # Name of a wall texture (e.g. "STARTAN3"). } } ........................................................................... --------------------------------------------------------------------------- MAP INFO DEFINITIONS --------------------------------------------------------------------------- ........................................................................... Map Info { # If the "Copy" attribute is used, all the data of the previous # definition is copied to this one. For the first definition in a file # "Copy" has no effect. ID = ""; # Map identifier. Could be "ExMy" or "MAPxy" depending on the # game. Example: if this map info is meant for the first map # of the second episode, the ID is "E2M1". If the ID is "*" # (asterisk), this definition will be used for all maps that # don't have a definition of their own. Name = ""; # Name of the map. Displayed e.g. in the automap and in the # console when the map is loaded. Author = ""; # Author of the map. Displayed e.g. in the console when the # map is loaded. Flags = ""; # mif_fog: Enable fog in the map. # # mif_sphere: Draw the sky sphere even when sky models have been # set up. Music = ""; # Identifier of the song to play during this map. Notice that # this is the identifier of the Music definition, not the # actual MUS lump found in a WAD file. Par time = 0.0; # Par time of the map, in seconds. Fog color R = 0.0; # Red color component (0-1) of the fog used in the map. Fog color G = 0.0; # Green color component (0-1) of the fog used in the map. Fog color B = 0.0; # Blue color component (0-1) of the fog used in the map. Fog start = 0.0; # (Linear fog) Fog start distance, in world units. Fog end = 0.0; # (Linear fog) Fog end distance, in world units. Fog density = 0.0; # Used in exponential(2) fog mode. Ambient light = 0.0; # Minimum light level (0-1) of all sectors in the map. Gravity = 1.0; # Gravity in the map. Sky height = 0.666667; # Height of the sky sphere (0-1). The real height is an angle # determined using Pi/2 * (sky height), which means if the sky # height is 1, the sphere covers the whole sky. Horizon offset = 0.0; # Angle offset to sky vertices, in radians. Negative angles # move the horizon downwards. Sky Layer 1 { Flags = ""; # slf_enable: Enable layer. By default the layer is # disabled and will not be rendered. # # slf_mask: Layer texture's color zero should be masked. Texture = ""; # Name of the texture to use for this layer. Offset = 0.0; # A horizontal offset applied to the texture coordinates # of the layer. Color limit = 0.0; # Specifies how small an intensity (0-1) the sky fadeout # color (top line of the texture) can have before the # fadeout color is reduced to black. }; Sky Layer 2 { Flags = ""; Texture = ""; Offset = 0.0; Color limit = 0.0; }; Sky Model { # There can be up to 32 Sky Model blocks in a Map Info definition. # Each block defines one a sky model. ID = ""; # Identifier of the Model definition that describes the 3D # model. If left empty, this sky model will be disabled. Layer = 0; # The sky layer this model is associated with. Valid values # are 1 and 2. If zero, model does not depend on the sky # layers. If set to nonzero, the sky model is hidden when the # associated layer is hidden (i.e. not enabled). Frame interval = 1.0; # The number of seconds between frame changes. Sky model # animation is interpolated. The model is animated by going # through all its frames one by one. Color { 1.0 1.0 1.0 1.0 }; # RGBA color for the model. Offset factor { 0.0 0.0 0.0 }; # The position of the sky model may depend on the coordinates # of the camera. The Offset factor key sets a factor for each # axis (X, Y, Z) separately. Small factors (< 1.0) can be used # to create the illusion that the sky model is larger than it # really is. If the factors are zero, the sky model's origin # will be positioned at the camera's viewpoint. Rotate { 0.0 0.0 }; # Additional rotation around the X and Z axes, respectively (in # degrees). These are applied after normal rotation. Yaw = 0.0; # Initial rotation around the Y axis (in degrees). Yaw speed = 0.0; # Angular velocity around the Y axis (in degrees per second). }; } ........................................................................... --------------------------------------------------------------------------- FINALE DEFINITIONS --------------------------------------------------------------------------- The Finale definition is used to define intros, interludes and finale animations. All of these are called "finales" in this reference. The finales of the original DOOM, Heretic and Hexen typically have a tiled flat as the background and text that is slowly typed onto the screen. ........................................................................... Finale { Before = ""; # Identifier of the map before which this finale should be # played. The precise form of the identifier depends on the # Game, but the two commonly used ones are "ExMy" and "MAPxy", # where "x" and "y" denote episode and map numbers; "E2M3". After = ""; # Identifier of the map after which this finale should be # played. Normally it's useful to only use either one of the # Before and After keys, though both can be set at the same # time. Game = 0; # Game selector. Currently only used by jDoom to separate # Plutonia (Game=1) and TNT (Game=2) from Doom II (Game=0). # IncludeIf/SkipIf and game mode strings could also be used for # this purpose. Script { }; # An InFine script that defines what the finale does. The same # parsing rules are used when reading the script and the DED # file itself, so for instance strings can be split onto # multiple lines (see Text definitions). See the InFine # Scripts reference for more information. } ........................................................................... --------------------------------------------------------------------------- TEXT DEFINITIONS --------------------------------------------------------------------------- Do not change the order of existing Text definitions; always add new definitions to the end of the list. This is because Games access strings using the index numbers of the strings, and the indices are assigned based on the order of the Text definitions. ........................................................................... Text { ID = ""; # Identifier of the text string. Text = ""; # The string itself. Backslash (\) is used as an escape # character: \n = newline. Quotes (") must be escaped or the # parser will think the string ends ("Say \"Hello!\""). The # string can be divided onto multiple lines, in which case the # parser will skip to the first non-space character of the # next line when it encounters an end of line. For example # the following two strings are identical: # # "This is a long # string?" # # "This is a longstring?" # # The escape sequence \_ translates to a normal space # character, so these two strings are also identical: # # "This is another long # \_string." # # "This is another long string." # } ........................................................................... --------------------------------------------------------------------------- VALUE DEFINITIONS --------------------------------------------------------------------------- The engine itself doesn't use the values for anything. You can think of the Values definition as a registry of nested string pairs (a bit like Windows' registry). Internally the hierarchy levels are separated with the | (vertical line) character, so you can't use it in the key names. ........................................................................... Values { Key1 = "Example"; My block { Nested key = "This is a string"; Other key = "Hello"; }; # The definitions above would create the following entries: # # Key1 Example # My block|Nested key This is a string # My block|Other key Hello } ........................................................................... --------------------------------------------------------------------------- MODEL DEFINITIONS --------------------------------------------------------------------------- A 'Model' can be thought of as a collection of one to eight MD2 models. Each MD2 file assigned to a Model is called a submodel. Thus a Model can have up to eight submodels. In the Model definition the submodels are defined sequentially starting from zero. The engine handles the submodels separately, which makes it possible to interpolate the animation of each submodel independently of the other submodels. An example of the structure of a Model definition is given below: Model { Md2 { }; # 1st submodel (submodel 0). Md2 { }; # 2nd submodel (submodel 1). Md2 { }; # 3rd submodel (submodel 2). Md2 { }; # 4th submodel (submodel 3). } One Md2 block is required, the rest should be omitted if the Model has only one MD2 file. You can set flags in both the main Model definition and the submodel Md2 definitions. * Flags defined in the main definition affect all the submodels, for example: Model { Flags = "df_shadow1"; } This means the flag will affect all the submodels of the model. * If the Flags key is placed in a Model:Md2 definition, for example: Model { Md2 { Flags = "df_shadow1"; }; } it only affects the single submodel. NOTE: a XOR operation is done so that using Model:Md2:Flags will reverse any flags set in Model\Flags. This way Model:Md2:Flags can be used to either turn off or on single flags that affect the whole model (depending on whether the flag is set in Model:Flags or not). For instance: Model { Flags = "df_shadow1"; Md2 { Flags = "df_shadow1"; }; # Not shadowed at all. Md2 { Flags = "df_fullbright"; }; # Shadowed and fullbright. Md2 { }; # Just shadowed. } Inter and Interpolate can be used together. You can for example assign two model frames to span across three states: : (Frame 1) : (Frame 2) : : : : +-----------+-----------+-----------+ Time--> | (State 1) | (State 2) | (State 3) | |0 1|0 0.5 1|0 1| Inter (0..1) D1----------D2----D3----D4----------+ : : : : : : : 4th defn: S3, Inter=0, Interpolate {0.333 1} : : : : : 3rd defn: S2, Inter=0.5, Interpolate {-0.333 0.333} : : : 2nd defn: S2, Inter=0, Interpolate {0.666 1.333} : 1st definition: S1, Inter=0, Interpolate {0 0.666} Note the 2nd definition's Interpolate end marker (1.333) and 3rd definition's Interpolate start marker (-0.333). This is needed because the 2nd definition only extends from Inter=0 to Inter=0.5, but we want that at Inter=0.5 the interpolation visually reaches its end (frame 1 ends and frame 2 begins): point 0.5 in the range {0.666 1.333} is one. The 3rd definition's case is similar, but this time the definition begins really from Inter=0.5 and visually from the beginning (i.e. zero). When 0.5 is scaled to the range {-0.333 0.333} we get the zero we wanted. ........................................................................... Model { # If "Copy" is found, all the data of the previous definition is # copied to this one as defaults. For the first definition in a # file "Copy" has no effect. ID = ""; # The identifier of this definition. You can only set either the ID # key or the State key, not both. Models with an ID can't be # assigned to Thing States. State = ""; # The State this model will be used with. You can only set either # the ID key or the State key, not both. Off = 0; # Offset to state index. Use carefully! If State indices # change you'll be in a lot of trouble. Group = ""; # One or more group IDs (mg_*). Optional. Selector = 0; # A custom value which can be used by the Game for various # purposes, like alternative models for some objects. Inter = 0.0; # Possible values: 0-1. Determines the point during the # interpolation between states when this definition becomes # valid. Can be used to assign several different model frames # to a single State. # NOTE: When defining models that use Inter, the definitions # must be given in an ascending order; the definition # with the lowest Inter comes first. Interpolate { 0.0 1.0 }; # Range of interpolation. Specifies the range of the visual # interpolation of the model during the State. Can be used to # extend the interpolation of one model frame onto multiple # States (by defining a sub-0..1 range). Always define full # ranges that begin from zero and end to one. # # When the "df_worldtime" flag is used, this key has a different # meaning: # # Interpolate { } # # is the number of seconds it takes for one # animation cycle to run from start to finish (Inter 0...1). # is added to the Inter calculated from world # time and (offset should be 0...1). If the offset # is -1, a random offset is used for each object. Flags = ""; # Flags for the whole model, including all the submodels. # # df_fullbright: The model is rendered with the maximum light # level (corresponds sector light level 255) regardless # of the sector it's currently in. # # df_shadow1: The model is rendered with 33% (?) translucency. # When using this flag the value of the "Transparent" # key is ignored. # # df_shadow2: The model is rendered with 66% (?) translucency. # When using this flag the value of the "Transparent" # key is ignored. # # df_brightshadow # df_brightshadow2 # df_darkshadow # df_movpitch # df_movyaw # df_spin # df_skintrans # df_autoscale # # df_nointerpol: Disable model vertex interpolation. # # df_alignyaw # df_alignpitch # df_idskin # # df_noz: The model is rendered with Z-buffer writes disabled. # # df_nomaxz: Model is used at all distances regardless of the # model visibility settings. # # df_selskin # # df_ptoffsub1: The center of submodel #1 is the spawn origin # for particle generators. # # df_noptc # df_specular # df_litshiny # # df_idframe: An offset derived from the ID number of the object # is added to the current frame index of the object. Frame # range must also be set. # # df_idangle: The model gets a unique yaw angle offset calculated # from the ID number of the object. # # df_notexcomp: Disable texture compression of all the skins of # the model associated with this definition. # # df_worldtime: Model's animation becomes a function of world # time. Changes the meaning of the Interpolate key. This is # supposed to make it easier to animate objects with just # one State. Skin tics = 0; # Skin cycle: this many tics for each skin. Scale = 1.0; # Scaling factor for the whole model (all submodels affected). # Uniformly sets *all* components of "Scale XYZ" to the specified # scaling factor. Scale XYZ { 1.0 1.0 1.0 }; # Scaling factors for the whole model (all submodels affected). Resize = 0; # Automatic resizing to the given height. The whole model will # be scaled (only along the Y axis). Offset = 0.0; # Offset to model Y coordinate, applied when rendering. # Affects all submodels. Modifies the Y component of "Offset # XYZ". Offset XYZ { 0.0 0.0 0.0 }; # Offset to model X, Y and Z coordinates, applied when # rendering. Affects all submodels. Sprite = ""; Sprite frame = 0; # For autoscaling: specifies the sprite and frame to scale # things by. If not given, autoscaling is done based on the # sprite and frame associated with the State of this model. Shadow radius = 0; # With the default value of zero the shadow radius is # automatically calculated. Sub # Or Md2 { # There can be eight Sub blocks in a Model definition. # Each block defines a submodel. You can use the keyword "Md2" # instead of Sub to begin the block. File = ""; # MD2 file, e.g. "Monst\Trooper.md2". The given file name # is searched from all the directories specified in the # model search path. The skin of the model should reside # in the same directory with the model (not required, # though: it's enough that the skin is on the model path # as well). Frame = ""; # Name of the MD2 frame to use. Frame range = 0; # Used with the df_idframe flag. Defines how many consecutive # frames make up the range for the frame index offset, which # is calculated from the object's ID. Flags = ""; # Flags (df_*) that affect this submodel only. A XOR # operation is done with the flags that affect the whole # model. Blending mode = normal; # Blending mode for this submodel. One of the bm_* flags. # Note that blending modes set by the flags override this # setting. Shiny reaction = 1.0; # A factor that modifies how shiny coordinates are # calculated for the submodel. Values below 1.0 will reduce # the effect rotation of the model has on the shiny # coordinates. Skin = 0; # The index number of the skin to use. Skin range = 0; # Size of the skin cycling range. The first skin in the # range is the one specified by Skin, and the last one is # (Skin) + (Skin range) - 1. Skin file = ""; # Optional: File name of the skin. This can be any image file # on the model path. If a skin file is specified, the skin # number is ignored. Offset XYZ { 0.0 0.0 0.0 }; # Offset to submodel X, Y and Z coordinates, within the # model. Transparent = 0.0; # Translucency of the submodel: 0=opaque, 1=transparent. # The level of translucency defined here is not used with # df_shadow1/2 or dr_brightshadow. Shiny skin = ""; Shiny = 0.0; Shiny color { 1.0 1.0 1.0 }; Selskin mask = 0; # df_selskin chooses the skin to use by looking at the # high byte of the selector integer. The selskin mask # specifies which bits of the selector special byte should # be considered for df_selskin. Selskin shift = 0; # After doing an AND operation with the selskin mask, the # resulting value is shifted to the right this many bits. # Negative values shift to the left. Selskins { 0 0 0 0 0 0 0 0 }; # At most 8 skin numbers for df_selskin. After the special # byte is AND'd with the selskin mask and shifted, the # result is an index to this list. If the df_selskin flag # is set for the model, the skins in this list are used. Parm = 0.0; # Custom parameter. }; } ........................................................................... Shortcuts: * Use "Copy Model" (or "*Model") whenever possible. * Use hyphens (-) to indicate that the previous value of the same Key should be used (if "Copy" was not used). * Use ModelPath to add new model search paths. This makes it unnecessary to include the path in Model:Md2:File (or skin file names). --------------------------------------------------------------------------- Doomsday Engine Definitions Reference deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/doomsday.60000644000175000017500000001031411357170241021003 0ustar keeskees.\"Generated by db2man.xsl. Don't modify this, modify the source. .de Sh \" Subsection .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Ip \" List item .br .ie \\n(.$>=3 .ne \\$3 .el .ne 3 .IP "\\$1" \\$2 .. .TH "DOOMSDAY" 6 "August 17, 2005" "" "" .SH NAME doomsday \- Doomsday Engine - For Doom/Heretic/Hexen .SH "SYNOPSIS" .ad l .hy 0 .HP 9 \fBdoomsday\fR [\fB\fIOPTIONS\fR\fR] [\fBGAME\fR] [\fBWADS\fR] .ad .hy .SH "DESCRIPTION" .PP This manual page documents briefly the \fBdoomsday\fR command .PP This manual page was written for the Debian(tm)/GNU and Ubuntu(tm) distributions because the original program does not have a manual page\&. Instead, it has documentation in plain text format .PP \fBdoomsday\fR is an enhanced Doom(tm)/Heretic(tm)/Hexen(tm) engine, capable of running Doom 1, Doom 2, Evilution, Plutonia, Heretic, Hexen and Hexen: Deathkings\&. It currently CAN NOT run Freedoom, and does not support Boom features\&. .PP \fBdoomsday\fR supports high\-resolution textures and 3D models\&. Currently many of these can be found at http://eyagi\&.bpa\&.nu/~jamie/doomsday\&.html .PP These programs follow the Windows(tm) command line syntax\&. A summary of options is included below\&. For a complete description, see the text files and http://www\&.doomsdayhq\&.com\&. .SH "OPTIONS" .TP \fB\-dedicated\fR Run in dedicated server mode\&. No graphics or sounds will be initialized\&. The game will run in a text mode console\&. .TP \fB\-bpp\fR Specify the color depth to use\&. Defaults to desktop color depth\&. E\&.g\&. "\-bpp 32" .TP \fB\-wnd\fR Start the game in a window\&. By default the game runs in fullscreen mode\&. .TP \fB\-paltex\fR Use paletted textures (if supported by the hardware)\&. .TP \fB\-playdemo\fR After initialization loads the given demo file (which resides in the Demo subdirectory), plays it and then quits\&. .TP \fB\-timedemo\fR After initialization loads the given demo file (which resides in the Demo subdirectory), plays it in singletics mode (i\&.e\&. as fast as possible), displays frame count information and quits\&. .TP \fB\-nosound\fR Don't initialize sound or music\&. .TP \fB\-nomouse\fR Don't initialize mouse\&. .TP \fB\-texdir\fR Loads all high\-resolution (PNG,TGA,PCX) textures from the given directory\&. Defaults to "Data\\\\Textures"\&. .TP \fB\-texdir2\fR Secondary high\-resolution (PNG,TGA,PCX) texture directory\&. Defaults to ""\&. This directory is checked first, so it can be used to override textures in the normal texture directory (\-texdir)\&. .TP \fB\-userdir\fR Sets the working directory\&. By default the engine uses the current working directory (the one in which it was started)\&. On Debian/GNU and Ubuntu systems doomsday is run in a shell wrapper that sets \-userdir to $HOME/\&.deng automatically\&. .TP \fB\-verbose\fR Be more verbose with console messages\&. .TP \fB\-texcomp\fR Use texture compression (if supported by the OpenGL driver)\&. .TP \fB\-deh\fR Applies the Dehacked patch\&. You can give more than one as arguments, e\&.g\&. "\-deh first\&.deh second\&.deh"\&. .TP \fB\-alldehs\fR Allows the processing of more than one DEHACKED lump\&. Otherwise only the DEHACKED lump that has been loaded last is processed\&. Does not affect the \-deh option\&. .SH "GAME" .TP \fB\-game\fR Specifies the game to use (required)\&. This must be one of either jdoom, jheretic or jhexen eg "\-game jdoom" .SH "WADS" .TP \fB\-file\fR Specifies the wad file to use (required)\&. You can give more than one WAD file as the parameter eg "\-file /user/share/games/deng/Data/jDoom/doom2\&.wad" .SH "EXAMPLES" .PP "/usr/games/doomsday \-anifilter \-texcomp \-game jdoom \-file /user/share/games/deng/Data/jDoom/doom2\&.wad" .SH "AUTHOR" .PP This manual page was written by Jamie Jones for the Debian/GNU and Ubuntu systems (but may be used by others)\&. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 published by the Free Software Foundation\&. .PP On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common\-licenses/GPL\&. .SH AUTHOR Jamie Jones. deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/cnsname.txt0000644000175000017500000000224611357170241021267 0ustar keeskees Doomsday Console Variable Naming Convention =========================================== Version 1.0 -- 03/27/2002 General format of a console variable name: [Class]-[Subclass]<<-[Subclass2]>>-[ID] ---------------------------------------------------------------------- CLASSES Classes of the engine: Con(sole) File Vid(eo) High-level graphics system (resolution, gamma etc.) - Res Rend(er) Rendering options. - Sprite - Model - HUD - Glow - Light - Flare - Camera - Texture - Sky - Mobj - Particle Net(work) - TCP - IPX - Serial - Modem Server Client Sound - 3D Music Input - Joy - Mouse - Key Games have the classes (in addition to the above ones): Ctl Controls. Map Menu HUD Cross Crosshair. Msg Player Player options (eyeheight, etc.) Game Game options (nomonsters, etc.) ------------- * Console commands are lower case and short, e.g. "setmap", "noclip". deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/dss.txt0000644000175000017500000001317011357170241020432 0ustar keeskees Doomsday Directory Structure Standard ===================================== $Revision$ -- $Date$ Contact if you have any questions. WHY A STANDARD STRUCTURE? --------------------------------------------------------------------------- * Different games are allowed to co-exist. * Extendable: TCs and other projects may add their own subdirectories. * KickStart is the primary way to launch the games. TCs and other projects may provide a profile for easy use. RECOMMENDATIONS AND GUIDELINES --------------------------------------------------------------------------- * The runtime directory is under [Run]. For jDoom it's [Run\jDoom]. * Do not create new subdirectories under the base directory [Doomsday], only under [Run], [Data], [Defs], [Doc], etc. * Not too exhaustive; no need to have a separate directory for each type of file. * File names should not include spaces or underscores (_). E.g. "Trooper.ded" is an acceptable file name but "My Cool Trooper.ded" is not. If you feel that you *must* use a separator, use a hyphen (for instance "Cool-Trooper.ded"). ........................................................................... Definition Files (DED) * With Model definitions, the primary DED file (e.g. jDoom.ded) includes only Models.ded. Models.ded will in turn include the rest of the model definitions. * Be very careful with Include "*.ded"; * Games and patches should place DED files in the [Auto] directory only when there is no chance of a conflict. ........................................................................... Model Files (MD2, DMD, PCX, TGA, PNG) * Use simple and intuitive names for model files. E.g. you should name monster models based on the names that appear in the game. No spaces! * When possible use the same name for a model and its skins. E.g. "Trooper.md2" and "Trooper.pcx". * With submodels, use a hyphen to separate the name of the submodel from the base name (i.e. the name of the main model). For example, if a Cacodemon model would be named "Caco.md2" and it had a submodel for a glowing eye, the eye could be named "Caco-Eye.md2". Following this logic, a player model's submodel for the weapon could be named "Marine-Wpn.md2". If there is no suitable name for the submodel, use "Sub1", "Sub2", etc. For example: "Caco-Sub1.md2". * Begin words in file names with a capital letter. (Looks nicer. :-)) DIRECTORY STRUCTURE --------------------------------------------------------------------------- [Doomsday] Kicks.exe - Doomsday KickStart jDoom.exe - Simple launchers jHeretic.exe jHexen.exe [Bin] - Doomsday Engine and game binaries, libraries Doomsday.exe *.dll - Includes games and plugins *.exe - Other executables [Run] - Runtime files (mostly generated stuff) [jDoom] - ...for jDoom [Demo] - Demos (CDM) [Savegame] - Savegames (DSG) jDoom.cfg - Main jDoom config file Autoexec.cfg Doomsday.out - Console dump and startup messages *.tga - Screenshots *.wad - One place to put (custom) WADs [jHeretic] [jHexen] [Data] - Data files *.wad - Standard WADs like Doomsday.wad [Fonts] - DFN files (-fontdir option) [KeyMaps] - Keyboard mappings (DKM) [jDoom] - jDoom.wad, default place for IWADs [Textures] - TGA/PNG/PCX textures for Doom (-texdir) [Music] - Custom/external music files (e.g. MP3) [Models] - 3D models (no definitions) [jHeretic] - jHeretic.wad, default place for Heretic.wad [jHexen] - jHexen.wad, default place for Hexen.wad [Defs] - Doomsday Engine Definition files Doomsday.ded - Primary DED file, always read Flags.ded - Flag values XG.ded - Extended General (XG) related flag definitions [jDoom] jDoom.ded - Game's main DED file, includes "Auto\*.ded" Audio.ded - Sounds, Music and Texture Environments Details.ded - Detail textures Finales.ded - InFine scripts Lights.ded - Lights Maps.ded - Map Info Models.ded - Includes definitions from the Models subdir Objects.ded - Things, States Special.ded - Particle generators Sprites.ded - Sprites Text.ded - Text Values.ded - Values *.ded - Some other/custom definition files [Models] - Model definitions [Auto] - DED files to include automatically [jHeretic] [Models] - jHeretic model pack definitions [Actors] - Players and enemies *.ded - One DED file per object [Decor] - Decorations [HUD] - HUD models (player weapons) [Items] - Pick-up items ........................................................................... NOTE: The directory structure under [Defs\Game\Models] should match the structure under [Data\Game\Models]. If there is "Defs\Game\Models\Actors\Bobby.ded" then the model's data files must be in the directory "Data\Game\Models\Actors\Bobby\". ........................................................................... [jHexen] [Doc] - Documentation [jDoom] - jDoom specific documentation [jHeretic] [jHexen] [Src] - Source files [Include] deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/manpage.xml0000644000175000017500000001734211357170241021237 0ustar keeskees
jamie_jones_au@yahoo.com.au
Jamie Jones 2005 Jamie Jones August 17, 2005
doomsday 6 doomsday Doomsday Engine - For Doom/Heretic/Hexen doomsday DESCRIPTION This manual page documents briefly the doomsday command This manual page was written for the Debian(tm)/GNU and Ubuntu(tm) distributions because the original program does not have a manual page. Instead, it has documentation in plain text format doomsday is an enhanced Doom(tm)/Heretic(tm)/Hexen(tm) engine, capable of running Doom 1, Doom 2, Evilution, Plutonia, Heretic, Hexen and Hexen: Deathkings. It currently CAN NOT run Freedoom, and does not support Boom features. doomsday supports high-resolution textures and 3D models. Currently many of these can be found at http://eyagi.bpa.nu/~jamie/doomsday.html These programs follow the Windows(tm) command line syntax. A summary of options is included below. For a complete description, see the text files and http://www.doomsdayhq.com. OPTIONS Run in dedicated server mode. No graphics or sounds will be initialized. The game will run in a text mode console. Specify the color depth to use. Defaults to desktop color depth. E.g. "-bpp 32" Start the game in a window. By default the game runs in fullscreen mode. Use paletted textures (if supported by the hardware). After initialization loads the given demo file (which resides in the Demo subdirectory), plays it and then quits. After initialization loads the given demo file (which resides in the Demo subdirectory), plays it in singletics mode (i.e. as fast as possible), displays frame count information and quits. Don't initialize sound or music. Don't initialize mouse. Loads all high-resolution (PNG,TGA,PCX) textures from the given directory. Defaults to "Data\<Game>\Textures". Secondary high-resolution (PNG,TGA,PCX) texture directory. Defaults to "". This directory is checked first, so it can be used to override textures in the normal texture directory (-texdir). Sets the working directory. By default the engine uses the current working directory (the one in which it was started). On Debian/GNU and Ubuntu systems doomsday is run in a shell wrapper that sets -userdir to $HOME/.deng automatically. Be more verbose with console messages. Use texture compression (if supported by the OpenGL driver). Applies the Dehacked patch. You can give more than one as arguments, e.g. "-deh first.deh second.deh". Allows the processing of more than one DEHACKED lump. Otherwise only the DEHACKED lump that has been loaded last is processed. Does not affect the -deh option. GAME Specifies the game to use (required). This must be one of either jdoom, jheretic or jhexen eg "-game jdoom" WADS Specifies the wad file to use (required). You can give more than one WAD file as the parameter eg "-file /user/share/games/deng/Data/jDoom/doom2.wad" EXAMPLES "/usr/games/doomsday -anifilter -texcomp -game jdoom -file /user/share/games/deng/Data/jDoom/doom2.wad" AUTHOR This manual page was written by Jamie Jones jamie_jones_au@yahoo.com.au for the Debian/GNU and Ubuntu systems (but may be used by others). Permission is granted to copy, distribute and/or modify this document under the terms of the GNU General Public License, Version 2 published by the Free Software Foundation. On Debian systems, the complete text of the GNU General Public License can be found in /usr/share/common-licenses/GPL.
deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/naming.txt0000644000175000017500000000772111357170241021117 0ustar keeskees Doomsday Function Naming Convention =================================== The most abstract class in each category is marked with an asterisk. +--------------------------------------------------------------------+ | BASE-LEVEL (the heart of the engine) | +--------------------------------------------------------------------+ CP Control Panel DD * Base-level/general (D[OOM] to the 2nd power) DED DED handling Def Definitions (don't use DD) MPI Multi-Player Interface Plug Plugin UI User Interface Z Memory zone W WAD +--------------------------------------------------------------------+ | CONSOLE | +--------------------------------------------------------------------+ B Bindings Con * Console (i.e. the future brains of the engine) +--------------------------------------------------------------------+ | SYSTEM (general interface to the operating system/platform) | +--------------------------------------------------------------------+ Dir Directory/filename handling DM Low-level Music driver (Windows Multimedia, FMOD) DS Low-level Sound driver (DSound+EAX, A3D) F File access (input) I Input N Low/system level networking (DPlay) Sys * System (e.g. timing, Windows console; win32) SW Startup window +--------------------------------------------------------------------+ | NETWORK (and communications) | +--------------------------------------------------------------------+ Cl Specific to Client Demo Specific to demos Msg Network message handling Net * General (high level) networking Sv Specific to Server +--------------------------------------------------------------------+ | PLAYSIM & WORLD (the game world) | +--------------------------------------------------------------------+ Arc Archiving (savegames, for the future) P * Playsim, playworld ("laws of physics") PO Poly Object +--------------------------------------------------------------------+ | RENDERER (drawing views of the world; built on top of refresh) | +--------------------------------------------------------------------+ C Clipper (engine-internal) DL Dynamic Lighting (engine-internal) H Halos (lens flares, engine-internal) PG Particle Generator Rend * Renderer RL Rendering List (engine-internal) +--------------------------------------------------------------------+ | REFRESH (and resource management) | +--------------------------------------------------------------------+ R * Refresh/Resources (handling of textures, models, etc.) +--------------------------------------------------------------------+ | GRAPHICS (graphics tasks, DGL) | +--------------------------------------------------------------------+ FR Font Renderer (engine-internal) GL * Graphics Library (simple drawing routines, textures) PCX PCX handling PNG PNG handling TGA Targa handling +--------------------------------------------------------------------+ | AUDIO | +--------------------------------------------------------------------+ Chn Channel in the Sfx module S * Sound and Music (high-level interface, exported) Sfx Sound Effects module Mus Music module +--------------------------------------------------------------------+ | MISCELLANEOUS | +--------------------------------------------------------------------+ Arg Command line arguments (no underscore) bams Trigonometry with binary angles (no underscore) M * Miscellaneous utilities (don't fit in any other category) NP Node Pile Str Dynamic strings U Utilities (other "pure" utils, not DD specific) deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/LICENSE0000644000175000017500000003545111357170241020113 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/dhistory.txt0000644000175000017500000007530311357170241021514 0ustar keeskees Doomsday Engine Version History =============================== Legend: + added, - fixed, * improved/changed Version 1.7.7 ------------- + switch texture pairs (SW1/SW2) are precached at the same time + "Generator:Stage:Radius rnd": Randomness of particle radius + sound-info shows sound names as well as ID numbers + support for textured particles * flat particles stick to planes - high-resolution flats with 4 channels (alpha) were loaded incorrectly - sector lightlevel overflow in sectordelta (e.g. on jHexen map 26) - alternative texture path must be tried first when loading hires images (-texdir2) Version 1.7.6 ------------- + cvar rend-hud-fov-shift: HUD weapon model moved down if FOV > 90, defaults to 45 + dsCompat: DirectSound 6 sound driver, tries to be as compatible as possible + -csd: use dsCompat.dll as the sound driver + "Generator:Min spawn radius": minimum distance from the generator source for new particles, a nonzero value uses a more sophisticated algorithm that chooses the particle's coordinates somewhere from the surface of a sphere + "Generator:Damage mobj" creates a damage-triggered generator + ptf_force (stage flag 0x100): particle is affected by a sphere force, which attracts the particle toward the surface of a sphere while also rotating around an arbitrary axis + "Generator:Force axis": a 3D vector around which sphere force rotates particles, also sets the strength of the rotation + "Generator:Force radius": radius for sphere force + "Generator:Force": strength of the radial force that pushes or pulls particles towards the surface of the sphere + ptf_hflat (stage flag 0x10): render particle touching a plane as flat + ptf_vflat (stage flag 0x80): render particle touching a wall as flat + ptf_flat: horiz and vert flags combined + ptf_stagevtouch, ptf_stagehtouch (stage flags 0x20, 0x40): wall/flat- specific stagetouch for particles + gnf_scalerate: use damage as a factor for damage ptcgen spawn rate + df_idangle: random fixed angle offset for a model * EAX errors ignored after first report (if property unsupported) * non-moving particles contacting a wall (assumed stuck) are destroyed if the wall becomes an opening * -noeax recognized by dsCompat * smaller button steps for panel controls * sound buffer loaded before setting properties (needed by dsCompat) - absolute demo paths aren't prefixed with "demo\" - mixer is more careful about a failed init (div-by-zero was possible) - camera filter (pain/bonus) cleared at level exit - win32 CD player didn't stop track at shutdown - flat precacher used wrong indices; some raw screens (Heretic's FINAL*) were displayed as garbage Version 1.7.5 ------------- + console command "init-(levelid)" executed after level setup; for example "init-e2m3" could be aliased to do something useful + ccmd write: saves console variables, bindings and aliases to a file + -nopsf: don't set the primary sound buffer format + "Model:Sub:Frame range" added, works with df_idframe * model loader will automatically load a DMD if it exists, even if def uses MD2 * memory zone no longer used in texture processing (malloc only) * MIDI volume: channel volumes not set separately, more compatible * sounds stop playing based on time, not buffer position * -verbose (-v) prints all command line options to Doomsday.out * game window is not forced to be the topmost window - client didn't play sounds without an origin - -noeax option caused a crash at startup - FMOD: MIDI/etc music looping fixed, again - fixed a crash when lights, halos and lit sprites were all off - fixed: game window must not be shown in dedicated mode - crashing at startup was likely when lots of models/skins were missing - a minor correction to data\cphelp.txt Version 1.7.4 ------------- + minimizing possible in windowed mode + identification number always printed for loaded IWAD - Direct3D: depth buffer mode verified to work correctly - mouse wheel was confused with mouse buttons 5 and 6 - Control Panel yes/no buttons didn't reflect changes to cvars - dpDehRead: bad memory allocation led to heap corruption at shutdown - FMOD: MIDI/etc music looping fixed - fixed a rare potential crashing bug in the clipper (C_AddRange) Version 1.7.3 ------------- + startup message window + support for up to six mouse buttons + support for rotational joystick axes and two sliders + each joystick axis can be inverted (input-joy-*-inverse) + all textures in an animation sequence are precached at the same time + popup help window for (some) Control Panel options + ui-panel-help, ui-panel-tips * GL not inited until engine init is complete (no more -fullstart) * game window hidden until GL init begins * FMOD v3.6 * mixer used to set MIDI volume * Doomsday handles the deadzone of the joystick * brighter background for options frame in Control Panel - halos weren't affected by object movement smoothing - music was played even if music volume was set to zero - EAX initialization was sloppy - FMOD/CD: original volume restored correctly at shutdown - dedicated mode text console problems on WinXP (presumably Win2k, too) - OpenGL: mipmapped paletted textures had palette problems Version 1.7.2 ------------- + A3D support with the -a3d option (dsA3D.dll; also needs A3DAPI.dll) + -oal option for OpenAL support + -vtxar option: make the OpenGL renderer use vertex buffers + -anifilter option: use anisotropic texture filtering + -diag option: print lots of debug info about Direct3D * OpenGL renderer defaults to not using vertex buffers * slightly larger Z bias for dynamic light polys * detail textures can be PCX images * model skin dimensions are allowed to differ from what models expect * sounds are uncached after one minute of not being played * sounds prefer channels already loaded with the same sample - texture height queries weren't returned in fixed point Version 1.7.1 ------------- * multiple -command/-cmd options are allowed * console command line cleared when console closed * DED loader reallocates memory fewer times, faster performance - music def loading: later defs didn't patch earlier ones - WAV loader: confused all chunk lengths, loading failed - WAV loader: header read incorrectly, loading failed - if music volume was set to zero, it wasn't updated at startup and music played with full volume - -bpp was set after first GL init, caused WGL to choke on the second time (error 2000) - Direct3D renderer tried initing with bit depth zero, caused D3DERR_INVALIDCALL Version 1.7.0 ------------- * engine source code reorganized * games, renderers and plugins all use the same API to access engine routines + keymaps (DKM files in the Data\KeyMaps\ directory); default.dkm and fi.dkm included in the release * multiple -file options allowed + -iwad <=> -file * particle generators can be triggered by the map ID (Center = origin XYZ) + linelinks * safe P_(Un)LinkMobj * enhanced mobj/line/sector iterators - minor bugfixes Sound: + revised sound system; now completely handled by the engine + new sound flags (Audio.ded): sf_shift, sf_shift2, sf_repeat, sf_nodist, sf_exclude + sound exclusion groups (Sound:Group) + sounds can have external resources (mono PCM WAV, 8/16 bits, 11/22/44 KHz), using the Sound:Ext key + revised music system; completely handled by the engine, each interface (MUS/Ext/CD) can run a different driver, Win32 and FMOD implemented * no more A3D support Renderer: * interface between the rendering DLL and Doomsday revised (old rendering DLLs are now incompatible) * Direct3D renderer rewritten to use DirectX 8 * rendering DLL handles the creation of mipmaps * rendering lists moved into the engine, now independent of the rendering DLL * halos/flares don't read from the Z-buffer any more (source point clipped by geometry, resulting halo rendered sorted during DrawMasked) * halos can't be occluded by their source (yay!) * halos appear and disappear gradually (rend-halo-occlusion controls speed) + cvar rend-camera-smooth: filter camera movement between tics (removes FPS limit for camera movement) + DMD2 model format (MD2 with detail levels) + LOD rendering for DMD models + cvar rend-model-lod: distance to LOD level zero + mobj shadows (extremely simple, unclipped) + cvars rend-shadow, rend-shadow-darkness, rend-shadow-far, rend-shadow- radius-max + Model:Shadow radius (overrides automatic calculation) * changing the resolution shuts down and re-inits the renderer (will work with Direct3D, now) + clipper maintains information about planes that occlude visibility (occlusion ranges); -maxor command line option - clipper allows zero-length solid segments now, fixes a few clipping problems - fog is disabled while psprites are rendered Console: * new UI color scheme (blue/gray) + ccmd uicolor: change UI colors + Startup.cfg: startup script for configuring UI colors, the console font and keymap + Control Panel (quickly accessed with Shift-Esc) for easy configuration + Shift-Tilde (or Shift-[console activation key]) will toggle between fullscreen and halfscreen console modes + aliases are automatically saved to the default config file + horizontal rulers in the console + console text can be centered on a line * message produced by ccmd help updated Networking: + -server option: equals to "net init tcpip; net server start" right after startup + -connect option: after startup, connects to a server at the given IP address (e.g. "-connect 127.0.0.1") + ccmd connect: connects to a server at the specified IP address (synchronously; the connection is formed in startup mode) + the font console command can now change the console font (e.g. "font name fixed12"), can be done from startup.cfg/user.cfg * server does not halt while UI is active - clients don't expect to receive cmd info of remote players any more - clients update visible mobj angles and remote player selector - clients update player mobj states - visangles (rend-mobj-smooth-turn) won't be used in netgames or demos Input: * input code updated to work with DirectInput 8 Version 1.6.1 ------------- * model skins are precached by default (rend-model-precache) * precacher also binds all textures to make sure they'll be ready * one skin can be shared by many models (internal skin list) * when looking for a skin, the model's home directory is searched first (where the model is in) * reports of missing model files are summed up and shown only once * console line length adjusted to fit the game window (used to be 70) + rend-light-shrink: dynlight polys are shrunk horizontally so the case when they overlap and produce bright stray pixels is (mostly) gone + rend-particle-diffuse: if a particle is closer than the diffuse factor times its radius, it will receive extra alpha and disappear when close enough + rend-particle-visible-near: if a particle is closer than this, it won't be rendered at all + ccmd stopfinale: stops the currently playing interlude + view-bob-height: camera height bobbing factor (1=normal) + view-bob-weapon: player weapon bobbing factor (1=normal) - progress bar doesn't make the screen flicker any more with page flipping * clients remove mobjs automatically when mobjs reach the null state - fixed particle generation in demos/netgames Version 1.6.0 ------------- + definitions re-inited when (un)loading WADs + definitions can be read from WADs (DD_DEFNS lump, contains a DED file) + virtual files in WADs (translated using a DD_DIREC lump; use wadtool) + virtual files support: 3D models, image loaders (PNG, TGA, PCX), definitions, CFG files, DFN fonts * console variables renamed (old names work, too) * cvar con-completion: mode zero completes the unambiguous part * high-res textures and model skins can be PNG, TGA or PCX + color-keying for PNG, TGA, PCX ("filename-ck.png") + MD2 shiny skins (approximated cylindrical environment mapping) + "Shiny skin", "Shiny", "Shiny Color" added to Model\Md2 defn + "Color" added to Light defn ("Red", "Green", "Blue" combined) + "Finale" definitions + -texdir2: secondary hi-res texture directory (textures in the secondary directory override any textures in the normal hi-res texture directory) + -nopitch: disable sound effect pitch alterations + -nodop: disable 3D sounds' doppler effect * raw images (fullscreen 320x200 textures) deleted at level changes + client setup screen shows a warning about different IWADs + cvar client-pos-interval: number of tics between coordinate reports + cvar con-progress: progress indicator enabled/disabled + cvar rend-info-tris: (OpenGL) display rendering list triangle count - fixed sector lightlevel overflow (>255), caused black planes in bright sectors - sight blockmap traverser sometimes misses the target block, caused crashes in netgames (server) in certain maps - server was mixing up player deltas, fixed - negative player turndeltas became positive, fixed - server was not predicting clientside mobj animation, which prevented the server from correctly sending mobj state deltas - server destroyed a broadcasted chat message before it was relayed to everybody - client updated the wrong mobj when a new client joined; the new client was left invisible - absolute camera coordinates written in demos - very little plane movement speeds were truncated to zero - fixed a display gamma conflict with the D3D renderer - mobj-triggered particle generators restored after loading a saved game + KickStart: default profiles (KSS), option to run glBSP, quick resolutions list, updated options Version 1.5.5 ------------- + cvars "vid_Gamma", "vid_Contrast", "vid_Bright" + cmd "setvidramp": update display's hardware gamma ramp + Flags key added to the Light definition + lgf_nohalo (0x100): dynamic light is rendered with no halo (lens flare) + PNG support (using libpng) for high-resolution textures - df_autoscale was broken - masked textures are no longer clamped vertically - KickStart: fixed a problem with WAD paths - progress bar caused a div-by-zero when map had less than 10 sectors - footclipping is now done for models, too (standing in water) Version 1.5.4 ------------- + custom music formats detected (MP3, MOD, IT, XM, etc. can now be put in WAD files) + TGA images can be used to replace textures and flats (Data\*\Textures) + OpenGL: -texcomp option enables texture compression (OpenGL chooses the compression method) + df_selskin: model skin selection based on selector special byte + custom translucency can be set with three highest bits of the selector + cvars "net_MinSecUpdate", "net_FullSecUpdate", "net_MaxSecUpdate" * sector deltas cover a larger area (cvars "net_*SecUpdate") * EXT_texture_env_combine is accepted as well * KickStart: standard profiles are listed in a fixed order * internal handling of missing walls * 32 MB of RAM allocated by default - fixed -maxzone (-mem) - fixed the case where invis-plane hack created looped plane links (the "linked to self" error) - maximum number of rendering lists increased to 1024 - rendering lists cleared properly at level changes (not clearing leads to missing textures and messed up walls) - fixed sky fadeout color calculation (alpha was expected) - F_SKY1 was being bound repeatedly even if it's never used anywhere - reseting messed up detail textures (e.g. cmds "load", "unload") - dynamic lights weren't processed for subsectors that had no visible planes, even if the subsector had visible walls - dynamic light intensity diminishes gradually for lights that are on the "wrong" side of a floor/ceiling - dynamic lights on two-sided middle textures are now properly clipped - fixed a bug with animated textures - KickStart: -basedir is now quoted like other paths Version 1.5.3 ------------- ! BETA RELEASE + a simple plugin system (dp*.dll) + Dehacked reader plugin (dpDehRead.dll), reads .DEH files and DEHACKED lumps from loaded WADs + -bigmtex option: enlarge masked textures to fit patches that are too big (e.g. Aliens TC) + server can send lump name mappings to clients * better IWAD loading (IWAD always loaded first) * small changes in engine initialization * df_darkshadow affected by alpha (Model\Md2\Transparent) - relative paths with command line options fixed - clients sometimes displayed invalid plane textures (flats) - server/client crashed when psprite->state == NULL - sky fadeout color was incorrect in the first map that was played Version 1.5.2 ------------- ! BETA RELEASE + particle generators: "Generator" definition, vars: UseParticles, MaxParticles, PtcSpawnRate + detail textures: "Detail" definition, "detail" console command + OpenGL support for detail texture rendering (ARB_texture_env_combine) + "Light" definitions: customize dynamic lighting for specific States + CD-support for Music definitions (e.g. Ext = "cd:9";) with FMod + "IncludeIf", "ModelPath" DED directives + mobj selectors * directory structure reorganized (Doc\DSS.txt) * Short-Range Visual Offsets: smooth actor movement and turning, vars: r_UseSRVO and r_UseVisAngle * 3D models associated with States instead of Sprite/Frame pairs * "Model" definition restructured (no more Frames), see Doc\DEDDoc.txt * rewritten command line handling (see Doc\CmdLine.txt) * server sends mobj states instead of sprites and frames * "UseModels" can be used to disable specific model groups * server & client setup screens have better default buttons - sprite lumps must reside inside a S_START/S_END block or the sprite loader will ignore them (used to be a bit too liberal!) - model interpolation in netgames - A3D support should be working again - minor bugs Version 1.05 (= 1.5.0) ------------ * netframes are deltas * client state is persistent between frames - when there are duplicate model definitions, the last one will be used + OpenGL: support for GL_EXT_paletted_texture (-paltex) + 'setres': change display mode resolution or window size Version 1.04 ------------ + MIDI files embedded in WADs can be played (not looped) + ccmds 'login' and 'logout': remote access to the server + 'net_Password': password for remote access with 'login' * if DirectInput 5 init fails, DirectInput 3 is tried instead + DEDMan 1.13: DEH: initial player health, initial bullets, BFG cells/shot * new version of fmod.dll Version 1.03 ------------ + display warning when no IWAD has been loaded + inter-frames (Inter in Model definition) * UI uses Small Fonts in low-res modes - translated sprites had invalid texture coordinates (all zero) + DEDMan 1.11: "Model/Inter", skin ranges, "Model/Skin tics", won't write "Line Type/Ap9" twice - jtNet2: tried to access null pointer - DLaunch 1.04: no more directory mixups Version 1.02 ------------ + 'settics': set the number of game tics per second + 'repeat': repeats a command at given intervals + 'r_NoSpriteZ': disable Z writes for sprites + 'net_DontSleep': don't sleep while waiting for tics (redraw screen instead) + 'net_FrameInterval': minimum number of tics between sent frames + external music files (played with FMod: http://fmod.org/, which supports MOD, S3M, XM, IT, MID, RMI, SGT (DirectMusic segment), RAW, WAV, MP2, MP3, OGG, WMA and ASF) + 'playext': play a music file + DED Manager 1.1: (slightly limited) DeHackEd support + Line Type and Sector Type definitions in DED files (v3) + Music definitions can have a "File name" property + 'ConsoleKey': keycode of the console activation key (default is 96) + 'ConsoleShowKeys': show keycodes of all pressed keys in the console + -renorm option: recalculate all MD2 vertex normals when loading, takes some time but fixes models with incorrect normals + colored sector lighting + new model flags: df_movyaw (0x100) aligns model yaw angle with movement, df_nointerpol (0x200) disables interpolation for the frame, df_brightshadow2 (0x400) renders with additive blending and alpha=1, df_alignyaw (0x800) aligns model yaw angle with camera, df_alignpitch (0x1000) aligns model pitch angle with camera * server version incremented to 4 (old demos incompatible) * client interpolates demo view angles * flats (floor/ceiling textures) handling revised, now it's possible to use any loaded lump as a flat * size, color and Y offset of dynamic lights and flares are determined by analyzing the source sprite (adjust with r_dlMaxRad and r_dlRadFactor) * psprite models drawn differently, now won't go inside walls * sprites won't be stretched to fit whole texture, makes them sharper * model spin gets an offset based on thing type - client moves mobjs within sector when sector height changes - midtexture placement for segs with a missing toptexture - joystick init stopped at failed axis range setup - OpenGL: didn't make sure projected points were on the screen - sky mask wasn't applied to walls with zero-height backsector - there was a floorclip related bug in client's mobj unpacker Version 1.01a ------------- * large textures are allowed to have one alpha pixel (ZZZFACE3!) - midtexture placement in sectors that have an invisible floor - multi-pass skyfix Version 1.01 ------------ + when a 2-sided line's upper texture is missing, the middle texture (if present) is extended to full height + plane linking: for sectors whose all lines' both sidedefs point to self, planes are linked to surrounding sector + 'FlareZOffset': lens flare Z offset multiplier, greater values move flares nearer the camera (in Z buffer), also affects flare size + DED v2: a Values block for free-form string definitions + player sprites (HUD weapons) can be replaced with models + 'r_WeaponOffsetScale': multiplier for psprite (x,y) offsets with models * when a sector is missing lower textures for all its lines, the floor of the sector is drawn at the height of the surrounding sector's floor * masked polygons (sprites, masked walls, models) always drawn with Z writes enabled * Z bias of drOpenGL and drD3D slightly increased * WAD loading messages are a bit clearer - -paltex uploaded MD2 skins in the wrong format - newline no longer required after last line in .cfg files - if .GWA doesn't exist W_AddFile() isn't called for it - Y offset of middle textures of 2-sided lines was incorrect in some cases Version 1.0 ----------- + all new network code (complete client/server) + dedicated server (runs in a text mode console) + MD2 support (replace specific frames of sprites) + MD2s lit with dynamic lights + frame interpolation for MD2s + dynamic light blending mode zero (multiply) + configuration dialog for D3D renderer (driver, color/texture/Z depth) + new vertices are inserted in wall segments if needed, reduces stray pixels + subsector planes rendered as a triangle fan around midpoint, if necessary + Doomsday Engine Definition (DED) files + DED files can Include with wildcards (checks for recursion) + definitions in DEDs are mostly patchable (same ID overwrites old def) + Map Info definitions (map name, author, fog, gravity, sky, etc.) + Map Info with ID '*' will be used for maps that do not have Map Info + command-line option -out redirects output to a given file (Doomsday.out by default) + command-line option -defs specifies the main definition file + mouse-driven user interface routines + network service provider/protocol and server setup using graphical UI + client setup and connecting to servers using graphical UI + background for startup messages + startup messages rendered with shadows + console text rendered with shadows + 'ModelMaxZ': farther than this things are always rendered as sprites + copies of P_XYMovement and P_ZMovement used for client-side mov prediction + Pause key can be used in bindings (as 'pause') + network settings stored in console variables (npt_Active, npt_IPAddress, npt_IPPort, npt_Modem, npt_PhoneNum, npt_SerialPort, npt_SerialBaud, npt_SerialStopBits, npt_SerialParity, npt_SerialFlowCtrl) + 'r_FullSky': if nonzero, whole sky sphere is rendered if sky is visible + MFF_SKINTRANS uses sprite color translation as a skin index for MD2s + demo recording and playback done in the engine (demos are recorded server->client traffic) + demo recording can be started and stopped at any time + commands 'playdemo', 'recorddemo', 'stopdemo' and 'demolump' + subdirectories for DEDs and demos (defs\ and demo\) + each Doomsday client has a unique (random) ID number (in Client.ID) + LZSS compression used for demos (LZSS.DLL), demo file extension is .CDM + invisible floor/ceiling hack: if a sector has a missing lower/upper texture in all its lines, the floor/ceiling of the sector will be drawn at the same height with the surrounding sector's corresponding plane + planes with glowing textures cast dynamic lights on walls and things + 'WallGlow' and 'GlowHeight' control wall glow rendering + 'i_JoyDevice' chooses the joystick to use if there are many + 'ModelAspectMod' scales models vertically; the default value of .833334 negates the VGA aspect ratio used for the world + 'net_MSQ': keep monitoring the network send queue, print in console + 'net_Latencies': (for server) show client information (timing and ticcmd buffering) + 'net_Dev': (for server) show the net_Latencies info on-screen + 'net_StressMargin': (for server) max value for client lag stress, if stress becomes greater, move client's ticcmd run time forward or backward + 'net_StressDampen': (for server) tic interval at which client lag stress reduces by one unit + 'net_SkewDampen': (for client) max number of frames to allow time interpolation of frames, after this the frame continuum is reset + 'net_ShowSkew': (for client) print time skew details in console (delta of last frame and the current skew, in tics to interpolate the frame forward or backward in time) + 'kick' forces the given client to disconnect (for server) + 'ping': clients can ping the server, the server can ping any client + 'sv_MasterAware': (for server) if nonzero, TCP/IP servers inform DMaster that they're running + 'MasterAddress': TCP/IP address of the master server + 'MasterPort': TCP/IP port of the master server + DED Manager 1.0, a Windows app for doing DED related stuff, and most importantly, exporting Info.h, Sounds.h and action function link files + DMaster 0.1, a really simple master server (in fact a DirectPlay Lobby) * default memory zone increased to 24 megs (shown as Mb in startup) * command-line option -window is the same as -nofullscreen * Game DLL API changed * MIDI player uses MIDI streams, not single commands * wall orientation affects lighting (lighter walls facing east) * -maxzone accepts K and M as suffixes (kilobytes and megabytes) * fog on sky sphere ('r_SkyDist' sets sky sphere radius) * source code rearranged into a more logical directory structure * subsector visibility tests are more accurate, reduces stray pixels * masked walls sorted together with sprites and models * modeldef.txt no longer used, models defined with DEDs * textypes.txt no longer used, texture environments defined with DEDs * sprite lump handling much more relaxed, sprites can be patched * DDMF_SHADOW(2) flags result in more translucent sprites/models * only visible models rendered * dlBlend 1 is always used with fog (dlFactor multiplied by 0.6) * bamsAtan2 uses 64-bit integers to allow larger numbers as arguments * jtNet2 compiles the list of available modems during startup * buffering of local ticcmds no longer uses maketic (maketic has been removed) * all new input code (keyboard, mouse, joystick) * flares and dynamic lights are much brighter * renderers modify viewport Z range instead of scaling projection matrix to do Z bias, reduces stray pixels * some default values changed: dlFactor=0.6, dlBlend=0, FlareIntensity=50, r_FlareMinSize=300, r_dlMaxRad=256, r_dlRadFactor=3 * dynamic light texture made a bit more realistic * 'net connect' uses an index number to identify servers * 'net mconnect' connects to a server received from the master * .CFG file includes the Game DLL version string on the first line * 'load', 'unload' and 'reset' go to startup screen mode to show progress information * secondary lens flares diminish as they approach view borders - pitch bend in MIDI songs - skywalls (invisible Z buffer masks) no longer have dynamic lights on them - no more "long debug message has overwritten memory" errors - subsector plane vertices are verified for correct rendering (zero area) - lens flares won't be occluded by their source - font renderer character coordinates (rendered wrong at least with my TNT) - renderers no longer use whichever Doomsday window they happen to find - texcoords of masked textures clamped vertically, reduces gfx errors - texcoords of masked textures clamped horizontally when necessary - D3D renderer sometimes set the wrong texture parameters - sounds have proper handles, prevents mixups with is-playing tests - a division by zero was made if a texture was fully transparent - minor jtNet2 bugs Version 0.99.6 -------------- * game DLL API changed: old DLLs are incompatible * DLaunch: disabled parent -> children skipped (example: JHeretic's -warp option) + DLaunch: modifying an option's value checks the option + per mobj dl scaling: 1, .75, .5 or .25 to dl radius (won't affect flares) + spralign 3: align sprites to view plane, but not fully - console border + cvar consoleDump: all console text is dumped to Doomsday.out * numpad keys have their own key codes (apart from /,*,-,+ and enter) + scroll lock and num lock can be used in bindings (scrlock and numlock) - cvar i_mouseInvY: for some reason this wasn't a cvar earlier + mouse wheel support (cvar i_mWheelSensi controls sensitivity) * CalcSectorReverbs() and texture type handling moved into the engine Version 0.99.5 -------------- + console commands can set a return value (DD_CCMD_RETURN) * rendquad_t is 4 bytes smaller and doesn't use a nameless union/struct - jtNet displayed serial link config dialog (sheesh...) - netgame events that arrive during rendering are now handled correctly (could cause a crash when starting a netgame) + option -nowsk: disable Alt-Tab, Alt-Esc and Ctrl-Alt-Del + cvar r_dlMaxRad: maximum radius of a dynamic light + cvar r_dlRadFactor: a multiplier for dynamic light radii - clipping bug that sometimes caused subsectors to disappear when the camera was exactly atop one of their edges * view borders drawn using the actual width of the patches (Hexen and Heretic have view borders that are 4 pixels thick, Doom uses 3 pixels) Version 0.99.4 -------------- - "bind (event)" clears all +(event), -(event) and *(event) - 2-sided middle textures are rendered correctly - flares from sprites aligned to the viewplane won't flicker at certain angles + D3D: gamma correction using DirectDraw's gamma control (fast!) + option -nogamma: disable DirectDraw gamma, modify texture colors manually + cvar r_flareminsize: the minimum size for flares that can have secondary flares (200 is pretty good) + light source vertical offsets * ccmd listbindings can take a search parameter: "listbindings a" will list all bindings to events that begin with A * faster dynamic lights (better algorithm + clipping) + cvar dlclip: dynlights are clipped (subsector polygons *not* used when rendering floors/ceilings) * spralign 2: attempts to hide sprite flatness (like spralign 0, but stops slanting sprites if angle > r_maxSpriteAngle) + cvar r_maxSpriteAngle deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/banner.txt0000644000175000017500000000141111357170241021101 0ustar keeskees/* DE1: $Id$ * Copyright (C) 2003 Jaakko Kernen * * 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: http://www.opensource.org/ */ /* * : * * */ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/doc/cvars.txt0000644000175000017500000000706611357170241020766 0ustar keeskeesQuick Reference: Console Variables ================================== by Sapiens Command: con-flat # Default: con-flat 10 Notes: The number of the flat (texture) to use for the console background. Valid settings range from 1 to the highest flat number present. Command: con-zoom # Default: con-zoom 1 Notes: The zoom factor for the console background. Valid settings range from 0.1 to 100. Command: ctl-use-dclick 0|1 Notes: 1 = Double-clicking your forward/strafe key equals clicking your use key. Command: game-corpse-sliding 0|1 Notes: 1 = Corpses slide down stairs and ledges. Command: game-corpse-time # Default: game-corpse-time 0 Notes: Corpse vanish time in seconds. Command: game-fastmonsters 0|1 Notes: 1 = Monsters attack more quickly during non-demo single player games. Command: hud-scale # Default: hud-scale 0.6 Notes: Scaling for HUD info. Valid settings range from 0.1 to 1. Command: hud-status-size force # Default: hud-status-size force 20 Notes: Status bar size. Valid settings range from 1 to 20. Command: hud-title 0|1 Notes: 1 = Show level title and author in the beginning. Command: hud-title-noidsoft 0|1 Notes: 1 = Don't show map author if it's "id Software". Command: map-alpha # Default: map-alpha 0.6 Notes: Alpha level of the automap background. Valid settings range from 0 to 1. Command: map-alpha-lines # Default: map-alpha-lines 1 Notes: Alpha level of automap lines. Valid settings range from 0 to 1. Command: map-cheat-counter # Default: map-cheat-counter 0 Notes: Automap kills/items/secrets counter bitfield. Valid settings range from 0 to 63. Command: menu-effect 0|1|2 Notes: Disable menu effects. 1 = Type-in, 2 = All. Command: map-rotate 0|1 Notes: 1 = Automap turns with player. Up equals forward. Command: menu-fog 0|1 Notes: Menu fog mode. 0 = Blue vertical, 1 = Black smoke. Command: menu-glitter # Default: menu-glitter 0.5 Notes: Strength of type-in glitter. Valid settings range from 0 to 1. Command: menu-scale # Default: menu-scale 0.9 Notes: Scaling for menus. Valid settings range from 0.1 to 1. Command: menu-turningskull 0|1 Notes: 1 = Menu skull turns at slider items. Command: msg-blink 0|1 Notes: 1 = HUD messages blink when they're printed. Command: msg-count # Default: msg-count 4 Notes: Number of HUD messages displayed at the same time. Valid settings range from 0 to 8. Command: msg-scale # Default: msg-scale 0.8 Notes: Scaling factor for HUD messages. Valid settings range from 0.1 to 1. Command: msg-secret 0|1 Notes: 1 = Announce the discovery of secret areas. Command: msg-uptime # Default: msg-uptime 175 Notes: Number of tics to keep HUD messages on screen. Valid settings are greater than 35. Command: player-autoswitch 0|1 Notes: 1 = Change weapon automatically when picking one up. Command: player-eyeheight # Default: player-eyeheight 41 Notes: Player eye height. (Duh.) Valid settings range from 41 to 54. Command: player-jump-power # Default: player-jump-power 9 Notes: Jump power. (Duh again.) Valid settings range from 0 to 100. Command: rend-dev-wireframe 0|1 Notes: 1 = Render player view in wireframe mode. Command: server-game-cheat 0|1 Notes: 1 = Allow cheating in multiplayer games (god, noclip, give). Command: view-bob-height # Default: view-bob-height 1 Notes: Scale for viewheight bobbing. Valid settings range from 0 to 1. Command: view-bob-weapon # Default: view-bob-weapon 1 Notes: Scale for player weapon bobbing. Valid settings range from 0 to 1. Command: view-bob-weapon-switch-lower 0|1 Notes: 1 = HUD weapon lowered during weapon switching deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/0000755000175000017500000000000011523516205017241 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/0000755000175000017500000000000011523516205021041 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/loading1.png0000644000175000017500000002664311357170241023261 0ustar keeskeesPNG  IHDR\rf pHYs  wiCCPPhotoshop ICC profilex}AHSq?oZF̌"?X''OMLYkjHm{\%" Pnevԡ 22+*E X^JanhNNͲLLֵcuoG=K;Vw4:YɎx,#/'_;vu?^ݲ]ttP|@yrA >{8e8xۣc㠘/Uˀ/^[/\PUOk P>- Gπgo;P@D\0eEظ(OJ+}Ηғ[_P3oãki[k WRw1 /vE`j~n|{Pؼ5_i֕\`κh+ں:_j,S`.cMYEh)l#vaKGyh%cN['@b%dOoI'~0,iu~np)I֌ x>,yV-7+;޲~N;-r1(33%3`gq" I L]7& 88M`+uEWoWIC_[#ĮU\ҷ59٨ő8LacGb wm,+VjO,{_\z'KQS: BgAMAaLA cHRMmsdpt>1qun*IDATxwV?,e)TA#;^ƞ_4&&1bk{nT!, K?fއn3>} $99sfӬDIxŋdezk; \j ҫ%P_ s-5X~.v?E ߩ/ltStyNsjL S`瀔YP`0qվUX| Qr, ?q 5mꟅY|L&'k' l+|iEt%'E]t_Px Wdz1 RC`4}ux-Ҏ!a@J"^I a3`?u FOO A pk^I
@.889 H 9# 5H?! - g )` P/~+~: _7#@Cg\t.p-0\^G "%7Lީ7+_\("l N%(:O95),?zR#(aRPj0UWֿw@ND:8%>N.60)-9nzP2(C%fݾx3@ab[* $e 60K<+U T6Cʟ'9ˀ[;Y@9iZD!]`[#fCQI!x5z lc:$'"Xyz;R6ݟtR-E U ҄8U9Ә]uː62x ~ lYGXs~sj%p<%s nlܦ+I)P hZX`sbs;p!N\Hp$7OF*^FE8LOsi@)@[w$6xA=E[y_LG$k0y,@联{uooN?TI#3 lyAG@RoWHrWRw#iցbj|I#ۑs D1 t͸SKW uWW?2"~1Tw_N W H`gGs৺5:{H D"Zq}D="j HR}z/A u=Ww#u[4~="O uJAkħp h qUYVHu1o55xw ơ+F}!HT!q,,gh7W!'*6َ1kpHWڴᚘ O _ q;0,xuRtoVH 5rVvFT|+սjZ/@b!$QhN2/s"2.$ŠGpIHMծNƯTh&R0 IvAϠpvC[9g6"Q7.:܃xJ2]ղ9ڊ>_"Gŗ'XD~#04[tn@4>C4G#y~45<>5&0 ` $e=fꏙ#RqGE>T2zy D`U1^`{LĔp=e5B=gvހHb"!x H}W)6Gd!"ZKS<#IiMeERދ$x 5)uCć!sŌϑ,/R:ɷNob # @+0Cy>frON8xɛ$_ L+<Ui>~,zDWཔmnY6r~'c8 q?t;Ѭ h*;j˵?q5Wpp+R7FSR }]`ˑ0Gcקh[nW<7HB"=wtMCJj]?0I'R4 Zum&O/40GHf( W=!($# 1\SJ[ggo?$p<XE?ٝ'g1"t6iH`-({dzT-̘Ys xܵJ,IDK˨U! $.Ӓ/Cto fHܕY",w@'}u[ybR/GrUuE]m6B8IwQҳCVp7o.3p >ǒLhO$ۚ:V WDӑdH}]qt" YwQr"8[W$9xr$,@ou76#`o9 H3Cm$m6>P`{mG HCRqDN*Nw R-r+t3,jz\ ?]K; (Kp>!gI)xD'L^2m AxW?, {"--G&9<[UwZ!N߂%GTweF_qcHXZ\ (do>ZKx\ %h[c$:'58W=Jcg#o}cD]?I 0UMNtDJ771|H6TZ~' W%$a$U+n,64D2.(◇wag"?a/x i8*>@PDo8Ry7g,CoYǦ^<]u{2wH7[+ٟý@R㌯&X&R=FZ<,j~ilcF/=5)d ƿX'6Ex<}&~dFr| 4aQ)^ G){1b>PO`fL b`8H@əQ=_ uWg0Bg"^t`'-Aė)R啺:>)gc8os>W $e pNV$s+tѕ{/d,BNfNUBiL\0T2Vm,ݾˉ{ߪ?Ȼ~MQ{;n .RSV/hb3Cn`8ts*}ikj8p#-Fҭc!ؖ.@~W_NZag 4wO9|lKt m8A$c_i3,Sԣ "Lmv Mmh,Vo UB|8eXA_qEIdAt!r%]רwO"fA=1EjP.0p-"Ǒ6V8Fl,Xꔗc_>[:!c&:#'Es%=YaS$NXVDRc%rd2҃K"x8p] CZH1I@zPty܁X8}'#0К# 0o{K"w:`) ]%#!  %KXo~w=`gwe4؞$CJ?Ny;`|6 6z|{F㕪'y7Sb W@%-W6 XlKoGN}<1I@3ڄvG,0 E0xńž,o6tC5=Hp>4/BwR9GOB= Urd%uJcũ #*?xdy1+m !Q `'_C}x5rFo Aɧ"RfH<b's}U솝\ҿ_0# 6dXL4QO?-vӁ7|lߴyh5628C·=ƺQ@z_s{u5E{a8 i񅝅͹D|&*$7`X./LGmY`,u.·f~D+~ o`l^Sd[$̵+vL"1^82/=Wcvnz^xXh4ލ%^F7%&jϱm 8oA^m-6j(6{ YŁ{9k?8ϗPmAPB#`X_:# ݆]v@1FQ1ܓ|mvZ=Jk:6ӀGMyutL!ͨX87cz6rO+`CcA晏`Q[F30_" 5lC&:MJ^/`z1Jt1DlrS 93 É{)lM3ӱّU>%R`q?`}׼@cl]|M,6R6ŮxҌ(42k@v3U;bwt`.~hi=x<|PqV^5=;9iEWc쌝t~ML&ցk&FMe>Xd^MB@D/,¦.(z HŸuDۣ6u)#H˼v^DƷ@) {X |4cRAmPf,QF@/[1ȃZ q4zq /G5= NT@#(w$/xt+[=1TMm{hK;8:èins쪻7xY~Z0-hI{ J+я)@` \r#Xi=d4yN/ [2}= >0ëm*ldt1`5#@@OjdYs b" l"[zV'-|/3`;֢4؋ls>R4,(+7P*ۨk=vj^[.mGV̫M gT@klU>(5|÷LPXnz$ JPZ9 VK1[@1 ؜ k5-<|HJmē]Ri_A`sbe[#DZ4O!pi'Ob~ :",IPR}@ha@ ',1s `Գ–QU|0?̀Y{o<]uj~pV5?,L9&x/B 0nHutfEK (L5(/h@TS8]+M:u@$ʀ_X%p J08h' 9j~kl BAkRCB )V忓&%:loN؝^A@<8hPZ*uCƻCl҃=?6 n%FcU7gPS Rlr;셯Z5:D?lh ڰ7v)HFodp1pK042-,'g.6OЀ@%A!suύcSsRv@J,)Â@F.Wůam/.a`LgLC삁`w&[F=DW HNG1:ϻx`eC `H+b$; ,у@w1O4.4fPlQný^Q`@p.6~'c[%ZD斸Q̉1 +A14HC32$Hxtn-pBK/>6<زs[-OʑDՋ}A8cDtpz<ŀֺz x9FƲ쏷0~K$El3"oSO`X7#'f0;|;sȱ%&)i.Hd!:o czwa'ewD?V!Bb-'?B1%ʼn4HmWㇾʩ#rN|BB%C#AWS܏_'d>WWeB w9=<{=%G>y@`0 ɧ9l$K)|r|rN>Jgb_ xKGRaՈq=LPxIE;v2rdP;!*Sϐ\Gm5 iˈl:~೐CYH)[sJiD Dt1N! ٴwB" rR\W]5)ȑ":~Dγ"{?r#Im$+tT '6/!|S<PAp6hz.GnɀatU8 [/GTSG;CI=dR(2!g3b0maH6 :q,RaI/E]&$>ECq"V8c78) Q-ny.AZTF"SW ;pMHb'-dڣO3NF2*%R]9Hop(w'mB ؏~AaUQu#%C(u@N:*T"פBGHB$8ɲ3BAs$}u$kunE:"RO#uGh PTh$<OUcF^D=NA[p5Hm (\ Dj2M)i|i&Iٯ7#Rrh!55/%;/f4t=r} FxHy,Í@$`?E[ž]]]>I|eC{U?אLf@JG]fˑտm!MA$S 9YyYY#UBrƗ0dб1[4&n7*ҲH6$w; ܊$UK=$*mJ 9W#ʻIaҺ_@&p*RCTK2 $H.9 $yc 4UZF_f!HS)jQ= |D3_CR("}_V<d8A ?9bz^Ӣ%ď?":R0H sO ^Ah坈('oyW`PhÑHi1RyqEvOPwe2l.dB%ݼ ҆tQ|S?I^S6HJѥ)|]E$`:YT$CҺA2:ۧtĞ7 @ rԀNf"6U~wFӌHVe6" ml_PT,_a"PI! 3*A6HƎj]IymxJE1@#'ff!Ӕ g9J{Nz<}nޖ<,FtPb~ r߫jUvC B,mt/#ǬȁTFP~ԭAw #-(PHjX,#01[ >RҜ#@z RyPxjRyC#3c%hN$" @PT[la4ݟ^G UKտ 0 m!^%GpHįPx x\^G 8 /8uo^IlceH=z[^^@ԘgW  EQP?=KO@ʀ=CJ/hDSq"R X)hHaHj= `I6;FRǪk. mFR ş~@BDC/G K(CwҶ}Xh,B'!5 HQ_n#׸:#Y>Q*g 743 @@h:6z֘BgUk-ԁ_Kt_>_ReS O $oHIENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/boxshade.png0000644000175000017500000002321311357170241023346 0ustar keeskeesPNG  IHDR>a :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:oIDATxb?(ԀJ`hbᣀzZ\xb*2( o@) "lzC\ jMMQbbPMr >ԴuJ x@ @n[IPJFNZ#F-65r4T=#Rdbb`Tm4mj%BF.~`NrSZOLDP5PR [fܒ[5#lBf㣷@!гV!^Ʉ 5JPg @!jaSmČ"ȦaahzbOb$ bلq!G2rcMD@i$#я^GHuzD)M@4GN`@ DB)#\"GĀ %t5HfWmp>@#PQELO8\O(Q`KĶK4,dh0ԫĘEn" VzD/HD L !D@O#&qE:D zb@ ^!# 0XHjb Q~ xt{Հ-u&)jyY-9 9I-pr9zRNr//Lz" h0Ք' d6O(U06>2@L|r#]=.|\w* a`BqE>.>k" 4@B7'G?1§/cb1z>m9A7@Q+8CW}HH>as#zQnFghF46RdžX @Hr8)jq%t1|E$%L}H-E8_x|[ui8@Ѫ İ6q܆r 5# `[·#J*8 JE?O$5 2zbπ۱ݝȆ<6݂#% 0 JO'%KN=amhF(MG`s@'5F4>|0G0Ā-!`˽ȹ}#Dj \Jr+%9@(Z\N#6caJt bℐEhPN#X;a Wc>|>Ɩ U 00F4,#mBCp6@bǥYǦ[Dh\Ͱ?]J I~rT zc+qLhd6."ч>o h@b<.Ԃ1lėr?+a'd|d>Hl6?ADn 69jRb6u눍|lx|Wg`@~d`@.pE02gz\9Y6bKb2M_"V?/." 7`4_$#M E>A&f$;1Zh|X8W@Q{.\Kn5@ll@6b#'O,F7 /``^ 7m—Hll9AD>1\bKbf܏(p%f4=|\~ b[AN 4 jCV-q%:Bj]r20ʑ͇̀ 8 j `ӏ!d&pq%@d>9F$9F9=~\%X` /ɓRf"_NU|r/2۱Jxltf•ŸEFWKh .7[J-ұu5A'z#Je jⳌ+REt1.t$ 5# ǀZcngc ( $TY_ ȍ-F܇-pE2337} ' 2@;H**qE".yd9|ӹu"=q%flE>!6܏`f^BJ\Qƥ_'&Rus'!" j#G&1-ґ6ت|BOxbr09[ BK@(#G&4:f( ˀi7_q%l I) p2>sI @JgDb ̂dZPf%kE1;Ӈ/g_d#E8 2UFoFa JQ+qAjÖ ыzB =k["`q#`[~d7 JGa⸊Rlz pA66+a|ll@"=cs+ff$B~GD`bظJHJtq|U>\O/,G" O"!"f(bPqV+ ݽb 8\-G<,Bq0v=lvb` @|>2=–hdl?+׳0N U?$6@t; VDr".5|Bb{B [øZJ\u>=#/܎Rad9\fpv\WnU"P# p5% qސĚB''cS/! +Ǖ-Ygb̭CA4lPϽX@sIn"=ٸ|؊yl W+7+p r"fD8WqOL5Bl㲋آ["qE6b3bXh |00]D7`|0>1CI`t%(Bf`r9jVc+αE/~dfakK"e:AuMTDP5K W񎯎GpK+ׂaʀ G@xd=t|I p\ό[5Վ8G/)uKd!7a6LDN@ߎ="pu"j|E<98Ā^ XB؀r_w; UjD>g`r8rS kaX\%R3_ jU>5V\hǖ`l)HFjYaF[ ; }$>jWDk32`F rx`+`l䳁E>p Ą.@!u ̀GpcPy葍-W+ڱhl, Wra6űU BqYcqUcK }l*Rar@zV10`{0 \zD".+0r#"Ԩ#&*pc@R+Qa B\ h0,G F$bP=''uq?2P\Ula<r"1 _b`FѸo1 >\>\8p^`Da䰩#TGaK(<'6`\%~7z)CLCLE 3أbq+'Ӈ $T P D+p#[JY^\P@ &B>܄-qr<5|bJ _M/0y8@@L D/*&|~HEU}|B>>?ă-Q@3H`K}R=6>ĕ|\|Hõ؃~lUDD('#L @&_MtEPA#kE>)9W"' |>܈jl ȧ [.ĕ+ EL'{܃˽+g!5." TzH\6P3%Ụ_?2 <* hyH"\@ >Ѓv\-Up@H\a3@Qre &_G0l`\F\L32`OJB%|ታd rN!T#O(#YB [ъ+#%#܆f18 rzr2.~l _Nŗq"\ld oŧW#O [TjE>6s>3_aOv@Qx\4؊{\45#r7L3Q01 ]-WbGV/`SC(8ň#@ϭ"6l܏.=Џ n >1\M[[N~lu3\N(l$F‰M*߾l9:t6198@N"[nÖ˱E>zDC!G>\2'h&AEl3!)R!2H)ЋH\E&/9"[}O@O| pȹN!d=X@1px|?Dq">>1Wd㪾--11y"[K?Al+S< ^H0j \ `_q/#6*% X&gb'R 8\;JlX9lpeV#G>RW"BΝJ|y49\#:WLfb1Y[ %!Ѱ0,&"$%Q˓Q\Õ pCcF3q ď/!" @N8+l9y\45z^B ibs5>A#  J~d B%:(&10lcׇf&>w da Jzp@lŗ#Ff/&U`\a˝"=O܉D^ǧ>X3H1pdyE0م~M;B`s/YHr?,rAH {@rN .q" W=l"]=OF8:zeb..7 G&fNd*Ea o D$ɀH@Q lė P=2܊L E:zn%PذDaCDŽdzY,ŠrX1 #'X)^`k "lrr-#yt5|v dt7 *,БőXE^Ɍd:n8۱ s+.y}w>,w DvJ3XaoNPa8ڥLMM0I]dܥ9>c5։E<ӓ3v5OwO dqB$=m|0t5a$UxX dl\b:MLi"PpaG4DCO@znL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:opIDATx˜.(骒"F <2FHȀ38K1K !%3.z3’*@1AXpJ($( ̌T 48VyH7P e`+F78d h96F[&V;o:!VNLd`dLpfcRL?8$!?(ׁ\`KIENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/hint.png0000644000175000017500000001263111357170241022515 0ustar keeskeesPNG  IHDR@@iq :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:o IDATxb?H2Fb @\`B3bGgiL#a~V!&$̈$F6 #P=@Q jLPsA43j0#CY\05Lhj`G 0O0r 0"Gv#G01`@DDi,ac@x؇y9[";?69#@v=+#;Pc3"3#y&PR@ <Ĭ ̀=|d!!{/\3!@Ӝ85?z!-Oc Z` KhPa@-S"6@긁 qvD` <"yI j` `@BiX \f`%P{a b#w#l X<πHa@.= O[y?D#W聀ry9 R`HG#`dO̅8,vaEn3 *L @,?aY][豎D"whP01X9#R  X2 R,/4UyȞaz=KqTČE He!΀B Ky\Bﬠ4z@fBf x= 9 b J}l\dga4z֟;=籕 ` Ÿ<\#{f`&̡P9da"0ȅ( XOya.GX 09a1 3؆=-?b ~>9 ҰyA3BIF(6O\ǚ ֵEE9a+iyW=eA' `0JAv$տC  .,+ X!E p ` 7(`@^`UrL,F@(`!; Pu 3O< L#Sٝnc` @<a@ <cKみh䔀(ȞFOY=0N@ybusa"}dГ&ra|9A#6r aг @y6G`o$h=PЧϐ 9*_Ս300#{=~1?(ȁKȞG80fг̣# `1<?F#X gX [5=f}a *k;1XXElTuL3!XȝC/İ6z 8S@!ϲ~d@d@s N"{[GNJ xkBYY JCG<䏭>4Sr-J\ M f?Tn>SV@V|C X <(hD_WDت? lRFv0,`@ERC$lՑ"0@Z% V,kzaO id09 %c/y6 bV`@`Y^Ke,@΀$ص K>#@/al-A5@Zd7&-=ˣg '瑻x@Ȟ@ãoaP@A\1^E3 @n@, {?@/ MˀFϯ:6z "# b_R@#fObg]V`c{Z~ RS!->ئg|9Wad&67@Qk W9bl4mtw 0: ( |`CfpqM|ي hBUz:] @ U  e'TIENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/radiooo.pcx0000644000175000017500000000222111357170241023207 0ustar keeskees ??HH @иаШШϣѢѣϢߔҕϔ||vwvpplkfgaa^]YXTTOOLKHGHDD??=<=989663300--*+('(%%$#$# !     !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/missing.png0000644000175000017500000026532611357170241023237 0ustar keeskeesPNG  IHDR?1 :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:o`IDATxsNXR%67֖zt <8nۛ=Ïn<Oa] vM)Xɥ-\["jm:cA DLxy#"&}^D:@!4Eu9sJR2c h@✟c Fn_a1,@ ۖSR6;xǸbeXʍSG.R f\x;#D^L#ጃ\d5s4%H'ѣxϛrNf{b`V!P-$E !Xbi՗oMjcm= M>1ҙחg,MrLLMN` DU)Jp!,z,69 6Ъi_,"3^=<>=J6We h DvH<ސ;_b(H/7 [pLe=/DÄR~u!MC1ZE<.-FU\"ucbljmhCC ҮGG\CSs*.PHRx_)N`k?M!_b5/Ob[ We^%INr3X~q*]Nx޸P )ހgc_OD1󧊧 Ԏ8 d( APqD;B15  ϣqi_MsE U'ZU7ӝr|xJلGh+?y!LfH>91l ٍMT3NOw0.q $8ض=x~K~Kb\#Qq p9a3'5%֛֍Z KA8zP"ϧ0GX2ʄ1l9QG>ǝ$*AHK)n=]Q)>Dէ);d֦9vZ>`t))ʲ  (/ڍXo-`TlC_r叨,<q-e0 8IJD%3R7afCwmŲ"9'P7Rcֆ C|h]?Yg7QAA 4u%&)L9_NZeV?I9uAgu)MF]Fj{bb؎ e+4DM^֦ViD/g{ ^1Y? jƑu fztGg>3'vHWeB(GLR控Y*zc >{F2j%Dhgw6YeP՟4@ A2tb8{ѵ%kiAhZ<RRuf^̾Q# X/Q􅺡=ʬF\ޥmlR {;^vڤp'Kk:b1@Қ6~%`lx&$*LOB:@%1:l'ԐeyRZ Y1~0&v>#6kb+=pL%V]!M[H3RCΫ@ޏQUes{}/.>|{i%0nIObD]Gf?G*N8v`uR||s[Bh )( dExf 8} Fs?7e-T-KtuV~@9yL95cqD?rc364DN+& SuzL!V$Mx7a"ı=,ūEM_4ytXԜ)Zwgfv\<5UjGdluAZnPF ͟<$9'k]S.Q&AM,;JT0l .峟k!l2 ݘ+?)kff ;O@9ާrWc iN @& C1-t]jTӤ&MLwAզ9c;szzJyswߴ;Mf|K!uFGQ_,Ӫv2;ϕ1}AeX<SH@l: NP!IjثtȂU-"K15Ӥ@¢b!T:ot &~,[8ƅ`_}gY*uz(X|2'>pV;XS~Z.JzJyאLe#̶ n9}!t^bI&cX\ 'Sfӛ0 THTU(5Mtgz?f?>MQ' 2Xϒ79^%'M4MHuxլ3B.2[ăMG:75x5Ch=*4!j :_M$6 qJ-)YKU\ܰpx'FV- /rNzji穒*Ҏ_9C5f6ByZ(qO' qVdpqI)B41v  u)Bˠٝ |yzI9Ibsa;U֧)U1o(2s|ܖ' EhmGJz[nӹ`̒:8aK W_'T6'^Q/~p3_)pcyrm(&.k Kt=Dުdq6пw-yf`t^!AY% ^Lӵ:FVsGX ږ<IDhlo)9Gq9%sAtΥ`.3J3U~-;QWL\tn/,tR9'8|iBQ fɣfONP] ^%k ܯf&^  \pEc*S- aeQT4v!l=tyeζ"S!!嵸['f!e1&'Ͼx1YcF`5$@hgƗ׷-eڷ.z(ӱ(Wa>$gfo&+ƛls\AdoHVSe3F_7D[K/Tƃ}ٓnyaHpwF)LzػBk>CRnx4ՍFbsE˲?տU +!kln`.k]($^ho>Ql-s[Qr@c@RUe 8ƣ?Ĵ IіZG[Ţ%5;CNmq|*l LJ6b|#mՙSw ( @8Эč;XuGx>'D jȱ33vf* r#=@ 3ұNqv ўOhOQ]Wr `chqLϰkt'-g>&03Sf{j &I %bN>y^S.;@ݠwTkl+0t.x0(~c؟BxMs#1 &S0@C(gPT`j , Z3\\wCwd 0WE@!4:]BmD+N6 E*嚓gHw&eY/*}Q Rb'aNIsi :Z{(萂H枳Y*;;ۗ7悢9_뀶 IRi%6_ONѣ V:ڝS3}8poHd눷ӕ6f)gz8nI8 g͛|ɻg?({gͿKل`!6E-W2]nY\+Z3i;W߮oQ/Gsd0ihV- ??ÉLMB̾:RXqP`乸ܐ6-d5:2K7$NRIb労".-Q@DvU?4h5t58O,zdrPFd"`/C`@nwAD@;|` yj_{K9"_@ѫv4Y+Kb"5(*S%*jsU̠>5:5vOu ݯ;?LONڊK."VŠݯ%XE>FqvCyh1On2CqqYu9hr; \(k=I*)t9/*1Uw9FcV%?5hl}NYMvWԡe^,5T+r$V0Z[K1R 6@tCH9?Jҙy9 v=c@y3ׯEkPS<Uҽ4IWJӱ@]!Yo 9/* 2,=i|53Rǂ3;/xKP4NNr#zcx1꿧*b3[zmD` 2a蔍vnrօ"y牽ߖVöz#Gw9J犥.SY|ݵ!~٣ΎoןSaKI iA<%U`s]BC઒(lNpG}{ V2[aSo<9VTb]\d;o@v yӤGi"Ho}pk{;?> U DouS,C /yRg S/ b?%fXD$"n09zI۾|,n V٘au%˗>;;7%Y*k G]QL'}Z}6rWcfPC8`6̺Eƒ?Ջ+baYH ch}|̾TET!áNL FP>-;3ĉP=P6"ysWAqZB G+QlA^o7ZAal&Qb hY$&@K @KwmkmbѤR=DU[5B cfO|tyX?߄OQ@\F:b.oB5v9$tx>JT< RAqq10+#%mՎg?QpP]-L;Z᱔]vU igUMF":vtgM⍳xu䝺 УB\X ytihv iŜ6̿w> "i~sIrPN_os=${DI6QQ 'Ķ }Im2R{aӅ.r:ﭱ !(@]"R˾vrez^E}nLKgv;j w60r 1 ?V Dwn*F!yǼ-WI,ds eEu]Nxwv~_[w:/RD>蚰h R/w$ۤk H8p^2?Lz#pgǙgjBY늌U U7o'*p)DTF$֩Oc2{UQJt6Ąz/`u٤$Jas'AcRh =WTE2u@PK)r|nsrlr QA|65w2ⓨj}nd#yfOIs3 զ.K/MO}g6FM 6U[luֆSg)Ʒ˄2 >h+Ci+ϣ?w1ˎ{ i^Rbr)zZ]N}StT^dy/ 0HT{4 61B7;Z$QSt̒%*J|`Ws,q1$l;i(Iq= A A 4ћ'?ĉ4~3h 7[G? dZZXgZ98 aNA?X:vZY7լmPNHvNi0}xNׯcR*`wEvggNwY 8KζW *NP@B xK [C]?iח5ꊄ"E>K~b5RN*y)T}[DT-muiq /dܡ 6"'ǟR\ і OmWz@j˅@d%9)9u cmT@J2.g{pYϣ{@ ,]ּkI 9TJw Hj\MGaeHzT@n_r`SJTT\>pq6;@ncgO^}7DDq PZ;;|Na(uXi_C j SF8!h@|Oh7H#n J3Į' 4~nW fn74QuͳC`a/Ϣ" 'ϯ{i ͣ$a1b%ٮ+NLhx$(2fiUkvꇶK@aX9D}Fv3M hZ &4>hH**:;.U , +#dZF$`) ӧ#UH 7_{`Jeu8FnXZ'gݾ֩A6 vvĬ<S+0!bS98kg $qvqڼ\͟lj*P-3 5" (lzIbScHC(Q.SMI _Ƒ[ά ^aXnUw`q3n'˓n#6a2sKO*W(,tHPs15,ڼu9^m}Fn,c8x@Ź& AԲ|.UֹP$HSUo[?Tu|"[~SFLJ $O&2gPj1ese${tat!m>1;ý͍HbCb RQ'j>Ɗo<ΚڮuVq7?lu.H:ٮ8};k,%enq1VUnF-)Uu<D%>q߃EӊQ1=\j~!QKh̾D+̜Na߼Js%fyH0+Ll4J]EYib 9Le3*@qKh =`lv F4q!fhnU}=0{1mq%2tL@q}Y;>RWbSq)3YCGβp2$>*&oԷu҂싸A] ^Z׋|r=u,pVomUg ~ qqVeWj==5&>-ߝ}湳_&XA eGJ)R"K1y( ݝyCL˶% $^%B"PjDe!5vm?r7͉E|:ue">ӱx'wa gYIRƯZ!!wf}NYǖX8Ƌ+wbzKhYf\0tKEPwg,I0Y:PZtPE]do[b `|W{:ٖY{y}GO2-`;:q<ȧvZN7&rX&ibޞ\o˾?JTGe`KNϪ*::,PF|z_$y!)mpYR(LIŜVqG,Gtz Am0`lt<FԷ/mYNCsWAsMjAw5i{lGqeExgcKIҶ&F"pNyLMLp޲Xx _hђ@ o;)v61+SRZ|qjÙ^f_{C͚q6( 0UA.y_R HMH}9 |C*mYsAHb;D`IJp TGk+m hTgnT`^+ˤ'_R 1:W2I0\%1,7'Q`ua 'EH3$DRB{9bao9]ow;ݎ-h8\*+yw vsR2ٸߞ,- G}*DF-wW<5S"TfH|S !Q4W(WX•-8n4^20G a?쪛?D$a0T-O醷 QңW4g~N @YFpPj s$NbaCurXMĢFmo,Qq-.X#9~縇)5𽞏]< +AT #mei=:|qz<-㮟 ]-C ʰ"1( b.p!]HksΞ0r3ڢY&qɋmgm[ ="N7Bw~ڮ z˳K H*l':aeu'.snĆ\Qw$0O48ޡMT\+58)ۈ<2=Q$/PHS&7I?TV9?- gwNvH8k8] ٥T{)ݎjgBN./fpyJъ,G$(.BJ3-@ it9xtj5v_ B㺐2JŮˁ__Νa*@w1  )}R!8wOc4cH,dR:; @'6Bt+2݌u=~?v[ c? \̵-NU쌆zoE+vj1;=o)X!h4KNCJ㒃u9^\LPvO΅ 7/Dnbt!9>d|ۂ\i/m~J@M022Dl!)6N#=1Hتyka1d\.AiAD6.aT~<u A ,5*EgK\Bvv<)_?"J/ "|Ű @ScUH53^)ƼܳvU;=iFyO9>5)2$5?WZ7wܯ.oeQ[b6ȩVOSju{˨;5+֬fpQF`+7y7hKDIAюR&;U?AkewL|oW:h*lSM#MKS#ii|mp$̌Nf}1e-^7I י,8:Q؃1ha¹`mǛzWa۲wL"I;%!9SP"F+#S0XO.<H_~oN2.JWUz|2%`a%( ݬ̕,ul&u]KQBbR(rj{^ώKoٻЅ,Y$tEFEc_An8&ij}/;ʖ [!w?&2 _nai!:RAEٜLrr:FK5i\Q8}&ĭJa )ۗ(5VC M ?ol'IkM@SA,Jeiִ|$|*fXdA4z۪/J 5r̚1vvR'& im5-trfZ5u #Y&]jk0`8Q4Ʌz!=9 +}齶#*[\׌lL-RfkAI 0t`Bbb?D4YecA QB{\oreRT%b8} u@0pK&*cȫ{͔TLd8`&=@ 8- U 9.^y ; 07(^ќM*AW}Nd@PNu_W63zޣ)n!olLU>|gz-N:-bt٨8oq#/Έ0 #܄mk&<@]0!iZ> pgc"gy8)F^aEQs}S\Mi:L@ C7Ga8(8:fH֓ 5^ɒ6:V n8 vѱ31sY2P&bou7K!*?,M@XkàVUꍎ`QԶBe59mRA"&~_\mW0l Ai?0:g.牏2 4|11{#+S@Ea~YXReLH8yD*W%gPUi& Vp`PFw@n7eGWsȜqN]_l\y@U/FI)iܡz.ӹvQ~T1y΅r nA<:sb J[PROe\=upK3}ow6<ݲvn L28LwM!7\PX֔cj#Q~$ =zk%_P4"CZ L/#8qelK 0?)4@!I :9b>$it ?%I}rcct灄Ͷ[nHy\uÕٻXЩQQfjRZl3C7h䈰%" .|ԭ"d@K=ЖߟUgW OϯF11_j ǗGB=_ekuU-lV ^<|<"bii|(Xb̬@%U (s3zlQqO \ψ%Ux5R`n,Ԋ8z`t4V%= HLs;|mރ$ q=JbKՌ2 QS ͌ҵBƉR/%#8!]wέC>m!U_꺎gBʼn^\ow6]Rn#wL0)g</ BճJvMEDžk?rZ@^?ؼojq^rR^W6[<6fjCӣ+.#Te C̎䃘4;鄇g220~S!Ѱ= kv6+S|1l `ٔOi-򺄧4Ċk|-Aoる H?Vc mww oMhʆ) sڙ.Xl0), ռ>3ެhɻk Su;U*Ns%oix)jD#G%?|%?TW>x:PPAp$^!R̷zbߙ$Ҷe =Y96x;5?|8,݄%-).㬢j0 I(l]b?: LWT91=xan[ŗv!F*Pw4)G p1ob2E VZXd궤,Jxk:Ac4'~h3޽ w0B~{J9' ycx~J{ Az c0H;cדf*Rݔ0סQ Rtsaa(M/:MThjY]`g! MΤ.eLpQU~$Ssy(QRg)ge GBZy .8&0-.h oTI-*ǃ&'nPx VdJ5ǚr DH98уTErSa<-fCk=@ 4l[L\0$9O`E1^$G\ҙ W1|NŮb3#XD!4Kitq؟@'~]x.d޾jBI~Bs^c!wt6ztn;0 6n!^_7*]IDZ7 ,7e@FV^G7X1ϐ8w=*'?hd!@mT>hVs0ŧ@3g({Ie*zz.X 7zN*긻DNdgwMW,ގZÖKЬ3OU&487RD5lr*`n*]x2!Uap`!$GDQڤxKeٞdO=1EtQJ"mZElЕ+_ ÏIǪ5'Yj)*Dvhӗ\mIK=Mǧז6TIN:Sb|#`X׃t0]|aro5۔x*SJpmGA,]6-KFa-+LzQi|zB_`^hy#oiezA'sO7+bˬ^5--T ‰}&7|`G=A_ΥA Ht1 .BWmgiB$mڢ/[yvrR{gg)V#\g+mtγ<›v 3<$*ql%z46~цe:*v OGù"(+P "7iDԖڗ0s8*PNH֭h$ߟ%oĶmML: zl:{*ȳ1+!B@MScQ K);LX9jڴD &v/_B)bx? ?!$N,jwYN X0Ŕ5X;,U~pu> A_"- 7UJ^&|K73PN)~Հ~ERx|W$C5YFŝ?b$*Ď-)*R.ElvA(1HPjj|[Vo%=v4nqX!(XŠLZ/{cf{vCWK(b9*.TGL,q\: *; #9i<\#Oj@,i|dVFf}f́ϣҭWNcXSkY45'&.*/Aj'T MtqgS=t $AcnG7B 2~ i ;IVm}'h,>>ZB27f= Iu@n{ݴu/d|xE@CrS詣 '+7#AKCXZ_~{Ű;]"*yީ6ncZp;]:A `;e$E]l,5Ԕ̹~s:S`|@PSCԀܺ` ~[$?5a!:CS ^3d9VaE;*vfBύ6'F9Yi{k'{+L?} >y%Hf6 :|<a ?F xo /b+Ѕf]Ag4 9̘FԔbT@/Y _ iCЮh RZCRaAπt [ #:&)+'N:2ڔ.zv!8LC{ͺ- & n 3}*.!' `-t p8#jHQ򂯧Knz>`>(**L, =Npy]P d !Μ|}l) G9|35E쬓Jg_={ R#:sSvMްe79`< C^| :Q2Z ;zȝ@ݺ<Iǐ: |f|S0 UTb 6Hx2 du#uH6 ܇[YBB:decC8٬۸?:`\CBSdd=dN R@r<%<y+8ghN]3#!z;7i&t~6Qjo O?h^?뮏?AY~7K:13^ي̴:h>Z; ৈǬ~@ղ0SOOjuNաU[Z\P~N[R_/bc`:6ׇb.tц)g@pn:hlڋ.@(e߾$"!t 6gzo1y mCmMiaCc@ !=Y1 rr$A gQRO_2,aZõC63 d3U" 2W 1a 5h#jѲuo!!zC?}4uR-nvq@cmi) x!:oъKnv1 ԙZm=θ!M 6氋0@T$Ȳ,{!6:!|^rHya3C.o%Gw6A$ƆAe'3.LKT )s)2D\? ="F]E=޽~paO Ug0DacP A\$ WI+PapDf߷J\Y=wfg07O,M#EJinnY|dCiRᖑ=*KgW`F}2v(>&欤dqHi'U5&&/I_wE)e[LfS9$w{#O2 ±M\J1T8;[>quTVהKMpXIB-Gχ'awJ} OtH'Y=Aћeeh~jX#*O. g~@:BňW VF'~1r88>Bsn5}s+&A ~ :G]\u{$#g7r=Yțtc~/L;! - G_* JeՓ]E$nT Pdofrc%$U>gSxWi n\ VB*-4o`o,R0h#$j ft[.ݹw93RY|Lh(@aM! ׆$3ѩBebtRE\rR5Փ|ȇH k 6QL|6,ғD >vTd5Z=,-iAܡ9pr>9 }=@ W~ عr?wן!?x|67@F 4 C*u>[xrl$h5m#\,g3Y'OCLTΐՠ a=L<YλHVD M/P/판.?PovX3 t/|q(hg &eB2 l α U/`'<%iPH+x"+xz|%%Op1C2_@yVo@ _z z6Rк]{3[&NYxϾXAdH#2^o0CAF޾(qrOd\ /bH?a$)HXb}+5_UYp9 iӖ6\֝𥝿a3`.R PuBȿ#Pn#2a=rp9#v*r X{'o2k^a Lm{ X Lh 8E YP iC 5xЛBA~C>m6!'!eP"{͍[w5Ԕ$ded#"PV]UEFZ94shHclWvda 6 0ZCT{z/h79R!:кWck)3؛ǘ\l~^JIY؟??>&A71'x5LL\ḱԙ \[}ɆU0pcqtmx"?,!J w H; <=ȃT{>)&3+(A>{ 1͌ c] +)tGАxx:|u/N @S_|an`]Y díKF9d59nXB xf=9yE: eB*OptCXY9`@+7@@ N'e4Щ:b2=ߴ墳CN#=9V8` I{},8>PE?pg))ۃKM^V4t >t<1 !KtTMLHd<rPژA H4FͿTJA w RVVP x)^[TϾEE7Ѓh1d.{jiZ3I$},΅ >U2K.|:GiM_3@5eEn# &1bMxđEEޢRX$h~ZkRuȋkuuK2&)LW{v텥j+TGw $nBa;f gVǧhgum2: Te˥yi<ږ[]y=I]Tںכ~a*MTmms#i %cLc1e_g|#k[-k3GOF^q‘?:݄_ȉ2G`@OˡaH?-AZ,(6;[%F.^~(lP.C:O`~Z|1oT#̅"];ښamGA)v展&y~]d5"hxsd*2q4 WFtJA3U2^;\Yޥx͵pu: DAf)Xh,hH2@lxJ›X%,=6nvwܙ9gΤ/ Ď!>S^=HPU& ?,xŊL0h`H¦ p0G:?ݩc I-S{v,< h7bM+s=ZD\(siont&5.MX7ʼxTf&u*WvT*vւbIZUسj ?Djꖸsie1ϸ]֛ױ3)^*bx:yy^SղȊŽ(>w Pbj`a5. K[1<-)ӕJr Pu* A\ј">Nce%&y IX)"ڈ&`!7͑wsVgwP>@&FU &Lf";/Y:4LhTM !$8Izz.Lڎ_c5AuLƼ./F[Ӑ SdX;Z=I5-/c 0:c WQB!@4BA$"V *)_,LBDͮwߑyMFIbaM9!rl4|G"oXa:lo"Qn,N3* `|a#"/6tM;xnP!1Cj'V7 #+ג5O`sDzuXತb+F[^RUKa Z0c}u렰ZƏM#Q ]ݒW$H ăA 4tj`wQ t _Y|=' iN@q)lEsijQ4 pJFùA"%8,(!CAErO(jkE.Oeƙ8B .MNp/Aa\j>JABnbkQ4u:$srte@'֎wnķ`L'W }f5Xl)p5!;L2k_ 읓HhdgbIQM|Jfg7LV:ΧIJF[\D,sz|͸z|T@jyܒ)BTǰgI s`zMƾ]oT c TWmE$L>V?pGeHKM9Z˕y>dn3Nf NNLpЯʟ!9q"my1 1iDsr+kk#RjOp\e$ AX a{,Tu|tx0e~K«kuɬ9G㻨 ]saѹmF MY)IMp8ڈZU9c˽+i_:kk)lkd$^>v̸ Z(%zlw i^ܮ%?I̕Qw"j)%+趸r?ޥ%s 险; 4;C(MH\ښA:^` U0R+NH3EԎJ?HN,f\嬶 |Xǩx)( A219Uw[ǘwT:G,I]۬r}KyY_O1V\[<P7Oq^-jVCi6K UOK#"Q ?TNe͡GN/)1S_ ԈPl3Ah i(ho μ5F+{rM4 1|(D,Qt7nyH8DJ14$y Np] j" % C@Ä #qnp$Ix@slfqIDu/߯$ 9̿rֆs?!tM׎;SޡQj/e=6VOv56mPMe+_x pNC} 8C3E7b1cFa-T͞(I"`ngѺ G]bawS  cZ ~l0޸cq,E,)"η&*^ʿM*PVa j;,)e`Xjz̑RqGL?B*[i!q!BviIx"qC] v7p4L$jc<zw#8]£f:~H t;;S&&Yѐ/OcQ7gKf0\yW PΪӾ;FP3.彲թ] +37X5/j2yx)_ڹ!uz'3%W.u,,CDlv:bϯ<;0DD8%?),6e)†SRdP qb \$;D~~'/5һ2oXk^]-ǧ(>S~БhTS-m[U`gPUW0T?<+P"%/=}/tΜsz|?>^j%[pk^t-Vm0~mʁ[n4O8FlNŞf2XyfB͂^2֛.Cγ^@<oQNR Y׿DA 0 Y+2Qţ'1nm%y//W?9Mo]Ng;/d2"r+0&Ԙ\0)mlY) 䄡TuXhб;h@=Taw`x2զ}/ %>`} 5+F Iڏ6f w LrjlIϤ">b6v1 UaEC}"f?ɤËFm{6 u^Xɋۘ8>Q7DX'$n1 k_0;`و'{#"DXD*a:A[A G JK'HRHL0 D00 $D{vTMKU-[}M7[ll!VtVӣD6r٩6<#Or 62CUa H78E,B鱝Lz>ͧw\#t.90!P\_  *|+ڋ/N_N;N&${\ [-Lf6$[҃QP<:/WDn a3\!J\U(]Z1:0H}Y Amȹё' vu6(c ڮ젯ԓ:?}NuFI 5ʹO?{iط$,PHh&זK'_ݽ59)|B6arGO6$mMi\=;0.NX4r H8KERjy=KVfL' od0xH\/]4#mh $wwB8>g2Ss8ϫI)]F¾ӧWڠ{ya#Vg|ADMF[TYv/(wG@sMi.0k`'`|KQ}hܩ'x0ޏ? YQƛ lvahn! K3Ҧ4Mۙ; cw -Ͻc%"3h4,44a#S9K7~;S~yjˉh^uYBr0ҿmv"Fj(gd0١xJ~G_=`:y/xWݝK@HL.I yಥOsI~Չ`Pɞ/dir֤f%dtTf-L2RG)u>9(}UjMqɑ, >*$Vk~ixʞ5ܸVz& x,6x+ػѵ|A0M GLHL'$(s6 U|>*ĒjwqW_I;u,b'VgA2qq̑@ .w+ev`nMSuJht١t%qB-%gTNًSd,B 5v.ua9Oƿfq 8MZ!IѠj"Cv@\&Ntf /eqR&`F}yT %iD!?0HF45^TVFmk sV/TqXg{( 42 C!},TmXu؁%dmb& ~"x:aJ#`Ŗ JK/Dcי=|!L$tXi|!{^1Ԙ 5/\h=P~Ln2Njԇ0s\*V*c#Y&I];bCnPZkJk[V #V_U7ȰbY ԥ|nRZ&0[ $E5@)c-!6cmLF1jl}k["pQ~ϗ+NJwmgrc[VN*+cgH~VrEYJAY>7!c:eNn&Ib.:Фh҉|0!+A)~(TbdX/S҂@ a*ŋW|ܭ| " ]MLR Q%}2U0!&Y|n4lnw,UP+uTSkd`H@RH!>o K5g~9I@>)k xOCT:H Pr hTd=qsSMK=67[j0a_$>;a+5qgERߢ8YXK7FMjՒSx JBlCM#AhA,4y6 @1pmW`ƀ͖ VYR%⡎Ǫ&ݨ7l%K_[Ǧ<0 DFOcBbD9c6J:ΎRO=3csQCo֎jӆ'ze?lo}K3uz (XHIr,,MߞZ(fc뢗|b\ ywSL X!FmD rWhf!Aٜb9DNBe#pR < Lu2|pfJIqQpU7;ĸc!CYID˯a \칥ZK :$5h#!qŢY"e0؈9kWղaX"(F==E`V zX2 0u:0bBB,<(, , `;W0$in5/ p3%6Px!*Mdsvޯq7Fs;Y8ڥ& 9o,82Օ۩{2jC B; 8=,^Qݺuyå׎ cHo,GG/Vm )$[O:d~v OGйH;0u|I/ڻQG~7Zs{'M)@REQd>YG I=kRǡTlDoe{nŤ(֬#b3"I͡[9b^.zH_?}N$dsϪ,qqkAMڪTⱰ?ĈH M|)k%8}\o-xͬf/GBv"<j)Q &Yoѫ v>">15(yc3mo " WOȍ0+.i`=(F!KExD$!2FO tT5 g2<;i&[2lv#Ʒf=rbVi/A )u∴邥AT mM 39]Eڄ P4c?8'kpgPkeuwAgKՆ1Yϴ0?ʸ;5O׏Va(^5ebgsʖA,!ovhGd̋J#u}Zx8MLir)H` :8hq]au+&r\|x=@"‡y6ŭZXHY@kqLYߒL ⅜0.ܴyZtx_~qŸag9 U"XBߤp,<Ӆ~BS85 K5w8>r %ANG  ~;kǛ?:]^( _<i>&;xX"N<^@׎zr R#%5qn"e8Hɚvv ]9-Eh5ri6Aؓ^+#\zK p5Ӯǩ9xs6M:m!:$Xb C3=+#iދ.֮o3qG#,NKv]ݽ@Ev$n\BF>ȜjʑV]ykJY%۾ZR*цM6MZגLuI{֮gNWH!W'[PX6;|IO dbQjQǦÌxϊEu`&'H„[8z`Lk- UKT="$c!" @d͒>@ݢJ%mEj1i0)ɢW8Lrc7ZEfT@6ZeCU j3XBbhKqx*yI=l6sPCy}-Eج֊Vr+ጹ̕N̈&HVZN}խC#jS!@CP,Mn5Vz%i *v4GF["?]T].qA,gԪ ؅R9J TRҒA !*SK6\hcš?p++P`@{NRI-O9-.-X ºۀ#y<М]tc$3L0)WY8)(3[}pؤKvfm~`ub:CAq*P%778㹺"Q(ܱCXt)hqu_K:/wݣ](=)Ta/6΃Z`uEx2#Q>f tJ$ݠq)0VFfR'L^j}A^"8զ0I1$i+Ye VQQhZ,jlOڱF"J Tqmf/#M5@_kK*=ZCΚqh{4 8I6I]q?} PSF' %3FQ%1KR t9/m?:EA#MY`v3m!ԧd 1&C`A)aڧ#§~trMyEð 0Ud] "p4"*D.4aIϻh&_rVpZA섢0?G1̪S^㥌@֔m۠5P U5 ;O f%nPsl6=(){i_IXZɉꡨo ^(J_ҁSςWNP.a`d᣸f\GU]?KSgK n5IQg괥 @ՙ& QX}n&sLEV2WtfW }kYB l;!w]E 5.^ aŴeuY=5.?fY9c;v o`UI2+Pp9*ʁɃG9 Ld MAznB[' T}1sL!57wJ2<M`CE0NUh~pEw,rV)]Q5 uFxq^E֌T>Y*In"jNYBp}^}  4fMw q^<͔Th?!7v,A8xȨOyN9ig2 =m{mxj6u'1=vz<_ khA>y?z9@ >%|[D[?nBGAdxBZSJCd2na'utM|-O8)N36>ldU^ᒓrt8I'R]#B&>~"-dAWBVgK5ЉZ.bdR輅MPZ\KMdK(3drCؽRuO'Ic.eN 㬐!"65YzRr|ode h4J}O;c/}PaU]L:1 ٝ/ ֥9s&+1ٲ̻R'L 2 [s= 5/ljT;Q\J6ݙ|0Z2 @`""JnpX '9k<$ɩRTl@>X5ܘ^=/ū]*hi qXbJS \--m`|C'L0D#*Bt X[)Vl֛6Og]" 2/GLUɣRWŧ%^ ȅ*M$K8ְjwSv6^9qnbzkQ% 1끩6[~O (.ʘJ _c UB$:^cZ9ʫaհI,RuYCRSLVs_ q BK d\ "*)194zщ+{RORF֨vP(6[\FmDĐJ`To_ ٗ®0UQTLے"JZ, xzOY ٦H7E.ǂ|.m DzΟÙGRVȯ!INu980>,ڤ}^--?E+Ů/c¯`S)ڔ?fs SeXpȫA?ngLtk6Hd>0u= 0 .ċCbiBC?1zNΎ&ym2H0LrJ_LyCR[&5SR$B5دX }o7kSI/+ҌvnieATNA 錃:MIg:M%dN/R.oyPqt|CC^7F. x9;]s~=oEn%6|x9 qO2싧q9KꕙR] N2F<'"?lqm@z0GÙ1 eQկ67 gKe +h'.oԴ%k21!*[g #4 l}D7BccaD l}?f vٱŭWQ [JW )82`*tHkLGMg9٫%#C] ގtNRqS7Mi;h+] ԎÌ|Slcuj6iSZIE{mRSrv{7$R<5[L0☆}tѬ+"~9^V6>NLTC\AkQ_,[F[jpP/3I>;A.zEeR6_3zYLMRV˛C e1Ң}g;XK|,`vb `LAg[xAv"/<SvзY%/cݥrmK̴yqOp7W4A=c5,McW} tKdܴKY [(=[!U YB9*Ѷ8[1J!gz+@֘Lƒ+j"D!7n+k]/WТDB{snB> &x$hQ;Yɚ-cB-,!NJE;rEqФC<4yʼQT]/ mw{< |UAwHvlPx0C =eS[5\2lQ:ބa':*L$X;?vwT9q#%RʋA8)j{)rȆ ji/ zʪ0ֲߊއ[㴟9Yo/=#9{- (;&613:lOӌž0C~6^[ ]!)U6jv&ueU}L?VawrRzptfMRH¼?x<܅C9H]H0_(^t[묠+ p,Y'A ˻N@v/!R&gIV\|4~vqzvϏP _ea(U7 WBQkr&W|`fdfĐ 2&G ۇ+s<6*v.ɦ}Z&=)!K*R{Rܮ'W)"΅P @܉hXf.+x+p}"L*8Һ|q+.cOi-tJF=Ɇ%)^>Dt0t-|f%zФi%LCu-rWt 椘z>v3j+X*a F~'c o dó8 ׾6x"{Ԩ! @do>0u:@ %mQ+U,ms* U,p*FJ'ɒ[/v LsξVكHJ[$"ǕUL)q3'p)<2l2G v3P2уBupC$2(  t Wh "X0%9 ~"BV;«8;?+Յ̬!)RJf͹Ly~7$|ޯ`ꂨ7wRfpâ\F'rÆI*a&~cJcW Vb $rJ?B!uvy&л^#vh?S%NV-c5A^_; -J{qJ#GGz'nI[>Rb1!rZ2OCO{G;z(iZ/?L dU2c;FzHNl|}J1|~PR{K`ぎS{I=c1g/,| zCb?ӾW/&4k e\P_÷s#j͂|?I+N=|l=r$:Y|kL\q9M{i&G9<ךTPs י APDD 1^HPmk$'۝=f2@:GRnAh[ Ym·M:-|*$ Wqo%YKIL Eg(c(]?.ldİ6|e SUdCX13K C{/Ʒ#@]UM2w7( ǘj%rF+Wg}0neS\5Vo>lgg4<}&cxPa*gxp;i._juvxؤ34Γx ,# 9>VQp.%-ֶ8h'0¶;Hҗ-$k ]:wl'åϼ6;1 й΅xfp3${ֲ5.\j KfAPc B<,gζ3Yg)& <}]4Mv\`6 kF"cOo+d;k+,<%IvA}˕n_〕=&|PܻRĺ|АMbysOo:]/ "U5'Kl.Lf( uY}W{Nr֒`}j?1 h _ұa @e_{⾈7jG7ɪڏsA]93:cd%6vS t} !~n3G dcוMTjmDL^mmu:@ J@ǂ@I]R5?lGH/tmrx 4k/< 0 jɜH)H*j-=NCB{T.f/2 _ẘ"oV;;9{r&:ƵxT\RnVEph99oru΍J|+:S27a`unǛ>kLbiq|rEs `=ꦴ*l+&pK et D E@ad93Ja36P ƜTLm G& AȦϯ=|UajW?x:a &M" w.\&Eh37~i3j狍 ί sS 9:Nn,j,dt NEs*T {sŸ_yR@J&i䙟2 ĔF[1Io۬W|(bYgSpb5acAwI soqMf> Sa+yͬk\LY>4H .(ӣ[ҚcJƛ5Dt|ùi`H]0[l94fpvGAXCV|ܰ=T,~l#_f Aµ0<á@+oN4?fzɺ=5tލ A !+ԣ4KC?aHU1U)+woU)]X.\j( fba2RBwlsq:6dtAz׉u3½3*g=mF+ 8{['Шezvpxiy'q1iHEĊ8Y=Rӝ*9UԆ́5H}$KQHGW-4|5•>#Y>F(5@WYz1WB չ AISq BaX oqxWg~H]>_$! 6b/RPς&?ʜᩍ2^ʌkn -VԒ.ỈmigGgaZK7(n+#lYp}u'l9׿3N6T'[G%bR;eM9/|pNkVSYp7T8~F ~PJ笡PR3Z9%Uܰ=>p(=>ɖn;3ߧB@1_:ca&M; $$vF*hrʎؾw|/ s9TkJ` Ɗd%}H0x9"+QuI o?Z%js{3 ڠ¶,k*Ws?Ɗ\r97g|r)*<ZY赖@_M0Ye.L#y<ݘ =Uzem byd`[sGQEYn6'Tӏ$o3#kB]= sL.N_1ȅr+0$6ԈT_:%A[yiypdU%M#!_r/3V!pDa L{`]Bol_t+} Ҙ|GV̵a.u喰l(ȍo{ܰ[r J ypitL_\:a*914D :hRO'"J>g ]:Kcc[-K%d8Ţ]Ɏ">V5pyYa?rS²!ǧƀUj3-vaۄE ֆryA$?|z`oFI[/Ϯ_~Gw\v!Vyۚ2+*X7"L`yOCCx ӹ-!0Q/(6'Yibp9re.wW/$Z:8N(.fk0iyn1&*s=j(S@vtOkG35+׵O_ZGMycxkҚyO^qCFxbdre-G1 ` bۘ.G#FƲ}:6Ԝ-߅I9L+s;K;^8^*nQA_0u.90ͯ$,XsA"yv 5z?S97Q#zBA7xҞLrNR#zUȎA(Eڅse#DDz2R,9#u;/Uf ?KK "ˣ%cHDvنmVtw..^]gD⌈MhRBtǢ?إiuTUV!'+4#Lڡ9Ep(<oO am8oBmwj{ 5(^J^w7 Y+ b Mؿ^."T=%NaVj V_<}I0>!eƐj wN(Q7+4@Psl97HvP V",CRdY,]$w1a2}3+{qzӢd{Jyad/ 7'x-6o'@ ᯼n=׿!(`EF:I&ۿI{bww몛!' rJQ a -<ƝV2JId_7h.2b^<U5wbq- /}.^ݰ@, [pr*g$H+{U1%F(I.0&IEDc_Agx"/fU u.|WCHh<mM U^F3Йa8n*ZN9SYe?hh."~2Y8T!bt>QJ (c oht|7HEU#?6̱/oEtF{v(oKjz4a"Œ̧t+@#T8 @ԙ @4K+QC/q*$<;ܫ:23B'ьCJ$>TrciPz0sD؀- "|zsiP2zP U~?YBndU**}㠇Ix5CW_|f0api[̞3F#)jy(dx"%VR S+^:" Է W$@QN^04`䑊>A#?fU=&A"!^2sb r0:hw4l$UJBC$5tdDj nNAp vLPw6L hڎ|5mܦL"kiA8b[BJdď†k5-y K߃ H fYuA EPGT(LhՎ:"3;Z)GV,\)!9i9? `(_<,$+!}*8KЅabNQyj&sF:oҋuK=f"o(b4s]CI$)XC4ѧ/J_臓$ENl9țIZ9k-lW#&ʎHhF8. h`rb:UiD>KN%$ئ2y:'E(#|p#V9@%mC F [#]ؒXsfP5eMS i< f>_*HD~ QUdB6j_ZK D!gȟz(޳L~!MƛJ9Eãb+||.*?pGfi϶d)]c4gT%cɖwgl؀,ꋟ_ aI!-wZޥyGB F0`ti,Bsg3q?>L @ D+GSDmͼҫ Bkd2`? DiS,D=| C;s:"IɊ~廯3jڐVT%ZsM'UPz]?.&FlLdK69oY v pB)ӼHUY`⤛>s NPp_9TJ7i |GJ>](\ ٰ_l"ǣݔ2аa::Ԕ8/9Q7(9qO-Km0,A3VV%,@~/S璃0 |T(`φ 'bUv~DŽ>_zrDiGMǟ 8Z[كq?h0湁X5"ۮO;IvɊ,|'*f1s^<΍l7eȌ. #q$6nΌ1 0 N#79 mTVS1Ifk'3$'xoB~~tř^K`J&^u-0Ս1q(0MSm\C\+\$" k:jJiΪ?:w$gGa$ddC,ؖd~YW e=xI(GYz:Tgj!b2_[ aԈ>@{k5ah]lrs{ܘ17!8I˽OWVZhgTJASl:jaT9uuk$}dF#> nHt=;KE:/>7Pni۠/,Dw'#cըVbz(*sb>ݠVeIsޟ јn*ż(xnF?+Qg0 ta H8P <;Qt3.FZd $Nj49@r)_ ̟NR*M":t ag@3S-Mv(h=|b,vcn\%Rb}@rm:oz}j,4ڷI4u!279&ēCqE"'&]4cLƖ24헊eSI[(_:a7e5wv Hܡ?NNat-nNiFV1*Z@@zǬl9/& &f86pe3z;t[ðsb}rm0 C8ngB(}O.jV 4߰RZdHhx>hsW} /F޷E1["=ӷfpuB ߢ?CTߺKO톎=n%l 1; OKGZ,MWq ߰'w\`V4Za4=4I3H3$`O- @Aax_:|vh,k8NL%̱ʒ/ujZ:3~Pk7Ϫ/,Mt15j."lgV B,Q(">,y΂e8{/C`3J(er}إZ{V"GAEHН;iӆ>dII,n<fz՞F(IQT\Zt1hy0B̑6}sw7ý vV/y~Ey9"H)v%#hKY?qxX,Zc5sAbhƀaW_0>i;ϩzl֦ěE00Qr4@f[6M$.'= g2~FTCq|7[Z D6 -+3|Xp($+R|* QiIc*p &X:7z#J{n;nVMJQS 6ẅ́/Y~~=T^2tb*eԉ=ʪtJxqA,̎ 'AL9fA/U1^h` "9_: %1N%DYdzZn+ۙ饨4" mB2vg7>7BY٘s|zkb2hNI8=(ROÿ=g&S]DPtɞX1h?vBco*Osu ,:a_K2#RM8$ G*S/;h{B#+nFl5٥쿬SgsYARBAt;_8' *C{tƵ̋J_醶^GawKEG0_^|3#R-d [h{8$vnY$5k:Q0 өFаm(k)>ٴ0ȫ^y&Hr$oK&&3U#MfcN}{t')]V@P@OnDZ[pYzޭ\Ԗ8v)!q:SO܈]WsjDux+ʇe{Zfta" &=PqCCi,+r ۊKɰ80u*A΅"(;l;Iw҄͞sni  39vx޷7z%hgj2P*o>X_H?.F*ah ΀*K4oQE?\>N!RjWh`M16=`BzӿW~iMpe=J?p E?w" Q?Sډv V idSV+]Br"+\OwrO2D Z8wG lGȀz'ԉn^J{^*iP>&m63i`k? i7Y]1 ԙ @!()CgA -^㱧( 8^4"N99/W%:.2;O`jF(j,3. B]wҹW;idvXP\t$K2IA6Qtbo6䷖V`GT7S2:|b]7dIw ,:V$x/1@lKB%O2c잤՘']^_HjT$5$&9lvkE[]Bޡ΢my{3ӟ c6 2¦VWeDѓ N5^) Q1/fuK0m(|_#2:" 6zP!fwN ܪ$3z} D]`r0΁[U @N|Tfe4bxX>4X' ?OgAܤ-2(*_QyA?&ew\-LTI7Ǟy&h6ܳXϺ(ʱR[ì$ њQCnneVmo2 ZT!O*Ub :jIOf9mׯR]Z7?P4x1u|  ;/Z{Jۡ}yF R8|Z#3[AI+UDA`kS3KAh|\PxEө>Q|Bgjӝ))6."6Ug󇁾cF@_6 S7w8m:AYNQSMͻ{o@Abm^mАP$%%Ożr9#eL.{03tN8 c/)Hڜb;"eU[lՅX t7.'2kEPi+p>)~δ|Li,˟ cCꚳE`2<ʘ:@RkQ?:a ZC(>REmg&WKrY#H.˼|Jf4,Q^詯KK-)u:o?sҷ!Hɺߐj0sjv~R0!twD>|]iӌʁ&JI"^-gIt&ZF9fKI.&Mũp2j3e*lN!h`]WsO؉1~oG4@ f6(ᇍi ۹GyD!2oP_if&6Ev]-=sS'VM*~"_$'Lřsxxy{Wp c7bl 9!϶6lcX"Whb!-<#9 .u,di0eT>W~msKAhP{o-Ajsgy1. |wi0cXD.c~P"Zs]lS?_E|}2WiJyLxIkE %^ݴe̯/דz#Y.܁=w*5#k&S7~dlIfds!#<B|# xYd6Ń^Ey]S7vbΩRv #}dw7tq ƸWɸix}R5J3`]l?+Ӛxv[W2M!:/F~$z,u:@ nZTXyaCbbuH 9йܟ&!~.aT_@v1-3zl+I2*5oqoRkR=D^&eD/8r^9F寃: c"~vFΆM[1^Zi!fG/sdI>Re 0 C|*kdi F S*aȣh@gٚr 1 V}^x#=/J.ZC,?!,' (a[^VE k؏ǔ+.=Ubg@]Lv[yJj~Pu.;1 ܾPKE)K@Ĥ?h)ޥu9¡=Q,_.%OQߚ3 > ,۱M()ns֧$݌խkGL΂8S补F'\KLa2ըTp~"hl`zUXK?5pr36K;O:[l'ǟt8{!rUfe,Tjx2Q zgjiF^f7rZzL0 DӦ Ā+Y ʀD8~wOKIዟ8nI$sbnGH`XZ׎ڥO7Wם̭>wT;:2p,k˾"#Zlo&FcE=ӎ+%;5Gw|"&SǠn57+Tk{GW_GzO^0UIږ"ޥ9WDXJ."'8b0ܜ)+5/Lr1*Rm8Ry%1=wG lu ӲLMhVdn}o9'ail҂ Vͧ m…xğ5xer) Mx߅fZ!`egޜ;:aIKJMJEm}CGe[fIb(1'Ͷd*!™Kr: ]euٜ޵ϏР(|֮O~i^Cca"B,ӕOd:\:aouʦLB2Vmͥ{HI?EIƭTzG'he:6xZ$,E$0Est 4P*hC Rdu/gO 4ݒ5OmEH&hqŌ3clx5 %E»#E lٕ0'O\ƻt|<_/x{ V!Ѿ6[:+( sJW)։dm?czÏ-5QoP_>Uъs)5G"[UPk{9,yiWh́Nsۜg{Qækzi v L1iFkoA0=3WըQMտGa1BLO4lN}sLMƢ.OZY)q̘IB m`#fs$H;'2zkF,;?ӏ@jo5h>LdټKhQ&KZ0S ջĈRvl.CUOX+#YLHC[.~q ܵM8;_&9D!pX?爳޻96+zoۃ-ĸfzgxQ抂H-v掔/9x'xp@Y.7ǐڜ`,l#Y %|P(\KYVAp#E4 ZxXzj6dZ\uس̮҇4*f502֔|{g0*2$'HP p]AXa8XMbP#.h9)]ޮ۩G, 1&ףte,h“W%vnТ6isҲXJ7\/o2_;n('/ |`Y,ٺ2%E82d\_$Q$CE9CSRlum~#Ɠ"K͔rZj~VVQщ u uRP d4|\gLgڢp ,#,/t5WGXY!oDtO?"[.-2ܢP6ӧP~姻@6(Pw0߲Ԟe20Qw9%f %oELrt\/ǑbXvn8Y:G>xT#lc *^S[3Q)ث+W };4ugP!Q<ԜAap4H\xDBZ|v9ikqhzXD&NIP PH2)PHL\Mxn̅x:y=86ҕb'9*W 𥃯h#]%vp @MN&)W&tŔ5{GJn y`֯w!X)pdm9Q̎).S5~_Q[l]%X99rp!)!NA‰P2k 21bUZ&ߜ#5zTJFX`< -jUԙ0¥;,^W ݢ-B ϠW0ڷ k"HJE?!_cHIadM1 `cOrgEV7 aKNh2!W`apشSW  q(aѡWtbϗK.Fφ <>g1Z܊v?\ Pwղk/ w /\vH xF*H=)NQz Ӯ #gNq+; fX+@(f/yp`X1lGm+TwN^Q2Ѩ'6^ZJ%){٪[r X04f8 pG$B{*R3X0u|&+N ¸iy3aa`K7i4!ƘF}v>-ɔBZOeZJ3`GGf`0tŌ1Wveّ bP+ v/yҿE9zim5 40ܫ {q%zoӓa Iɸf@?zo 029:R@} ~Kj/VLĽPDndShX&S&7朮X8LKNF_hP,&+Lm"p, KPe9ɨ~bԚ=>;*OnA&18&DOڵ==QZM5-^o^! NnMp:\U½jiRV(XI{zl4p&2}qԐ x0[Y*fɥ.|84mKҝ~ LjgML,fM|8L]_fE wXkmja=ySdd991I#j)}6 @VeTqY=˃cpݮPq)V>ĉKv%ufmwdqAj)4q U%.K5]Ŧ/ DM֍׊kB^\_lPTz<=Mj9Jk5[\Hᒑ31H|riR$>ɡDLA+R6 wmqtnMpȰ qazFQZ8#^#7#ayePLOHM2"'lkf"Zh9+zQHO4MVzLeaè)~ȟT0 DiRТĉ9 TV4%ϛ-G.Js>΃-\zO,U>j7yJq7:àwUh2ks5:ytz)Βk<2v\'Y2{pcz]P蠟S9c[1-S e1vuL,1яEdU L&z :2+avjqk–!PN{#lF~f=Yay`TO߶ צRzQ>k6v+{v?{]cI;<* $>=?-Sg0C +âR[*Eu*4_?i.$\^:-NžTnt,@ X=zޢ'"@4#t9"F5j4X5a' &V/Z.K}QX&wb5+^8phfX&&ɬu>%yԄ12oϥQv'MnPtLd/InQ|QGSu!obc"\C` ;TpQ-iPmhhY. DLz{D3GP!N 9 ~']}sπU#qWmScnfn=ctUد&cc( #y _fX2ڮz >O'i*9e %6BoGPIz1>fFAT Lr'SQVE!*u$g8xX1nsOEb2l*h(1$̑(rRD_m!p ,݈9^)!U$x4 8|:A3^\NrkP[rڌImv]{۸RB:BU"\ W pq : مqkNz"yy+NX2g,'#ldgT̀ nܼ{[<1>-96PCM ] YϜܼ㇏>~v/x]8ɠ\xܜ MҦГ .Pt֟‚.ޮv*h.w;|Թ^ àh9K 4ܿ}-M #r:zt….XCJ@Hw *L. ><!@hl~)F!7 dGHk|xw [<|B@Ƨ!N&ؙH;؎YXHU"8/Ϧm 3@/Cnn 9Tk)jCsa Aq 9Y]Ryy ue 6{{ GCC}Pˋ5e 2sѬ { ߐ2`k)Z1 ff;hU"'&ܴ7X?v d㻗"h<`!Mv*FȀd xmsAN Vg[Z|sH3 <]o'H -?c,T{[_Xa!9 qI\|oFؙ mJ4v4X Q b՜v,i 'xMt \@[8ne]: |6@͐ml,#,mG pҊۏߐC-!)߯Bh\Yh?6i +.gl>}]v̇@ŁDFZg<5[ Sxgâ|͹~_p#;X)I w;? E,\e3pǜx.`oQ`. v@HKq=@>I zg/ *LD=n+:nBAK'!wT~dW,ld Rt7!:mH ,M,8[S?`ϟׇqNMzX@J 0T-u] x_Kӊ ?| 3aC s3$3~7o,mz6$ 75OE@r`Xy6ȎO_1ˀpp J0Cš3Vnf\CiL5/a7dB WWӒ@Eʂ̊pAEiBTmۢeFD@i jMh{{Hdp7{;4fX!Rce8E;zD&6: ҄iKK_Ӳ?,>ChI*rZ 6,Ú0[e*]g8nlqgho]yMnnMJV]*+O) drkPi"v0 ]#6Bzςr$tTjQ([VDS! l^HL`mV Oɱ bv\(?7kPdsgAxnKǧo'x"p88:mW군(q(Uc"Ǒnvt~[(>bqDY)@޳U8@@SAo\rJ

^j 4Ԕ⢂ 2sM $' JHxTOP;D?d/8+P-&P4v 4ypu, A#,"0r,K!b?aqΤXY6̇圙7.ݙyofj-T.rmoTE2b2L'B .8l߯݀4YWĦ)#mP'%S;LSK)2F(i_^Ȱ_.(@E_?gh7nXRav-䠵p=YS5"mq->TرϙK?| K8)W"Po*cEü) ԟG:vcV`JlmoH V 妨~02bК3I]: &a%  g/E ,Upu= & QD`O qBAcD +ZnAH)tVqw?7x.rU*EhhC[d@,q7% {@SǢy ÕM;eA`dܤ$mjU K;gr$iΦo#a <=`D*H7RA2ZNNl,[SЪ;ُS˗| 5_^sJ׉})(Lu+lڥE]Qʔ!z5bLu>pVYlގroZr9*帊}ƘaGαH߀fZ\x6[;@Z kSCdHn: Ï/i=;'/Ob1I+E8*Ǚ;Gf~*qqFI^;:~7[7)C'D ߇"ԙd;~dܛ8q1 z|Y 1;vy [ZXXZvZNYRAhT ("Ȟ\N"p,ewfZNg0[`0 zV_,h+Z,2X} ++{;Cꮜ`f]L\O-d@DW]>INKysˋl(ՏjcʬZcvH 77֝qYZMd|Y#/S.jmeIH=<҈>V{O"3yL4ޭA1d{4RҘ(kK-R<#[!2eW׽igRc17ӮQFsDXx.8iehPxyC|uz0}+1MW>î3]b*gM 'Dv6V` MRXiaRX  9,EHμSkyy?*|r+2V-d$}]A]ZZE"u(MŠ' ~ awCyuf8:~ Jo#),p :aA>&|.VSSځ\_np(nl ҁ*^tv{< ͸?P^^Ct~!dIfDmy~2ņUgdxG^}mBʼnM }8s澜/F,{(ؖX8Ux6qU?Ҏj0%?jHńaMt: BbJJA$^Pi!K׬ 7\Y]י7o>6|$*M;'2\L%崧)`j7 BJAc` yh r:_?8kT@Uh dPhhUA%=`B:^ fMrgOd69bOq( #Z{t*OaeʨoS63F~[JZ:1}m2m1đ, Af' ׇRּB . sS`]J2/r'nn/^jASߦ`4:>JO=x&4YrجA=xfaӞ @ @_O;x+qۘ_ x9éw!fL:uS k+C̾=?_xdC̚,}0]9K21,^׈t+|O4OAo[Z8f30ᒭ m[tk /LzdlvIw!;Ĝ[K$ My 4#jtݵϝc96B9u0{9 );#UfQIѪDt_BwOiJQ1W%aq) '`Ò J)q7,@&$vϛ&x:k/2!#Z.'ӝ,U3f;@Ѳ-2u C8z@.Iݨ.̢D"i VVщ}IÖ;W2q2b4I校 7ೣ660`fN~Fݰst,rj$\ЖcK(,йv⊷<:Ufi-$,'Lڷ, nJvFl$IwL6m'hɴ6Kt4;R~Fӵ[#ꮮ/& .`la BAozЁgP~I JKi6ϑtɥ#%Yr]tBJw69n~>yYiR|LD p6J2X(mȯsrCuhK4a8a{M@F} Efhrzߙh2WauTIKy:_Y_v⥕OlzQKh ֪qE%JDdE ^ ю$E =P$P7K?wL M߯o8紈H@(l5{2Vlzl\OM1 \gԀ#J%seQ21,bh} va(ڤ8btݨq4I\7tϙ*~>yZ$6do'maKFpz܋Yt+Z,>@u-F9mPɥNz-2\=Y|ٜ Cay+=Hi@|/x= E5YD"_! Kd 0MWqj<(oa(|^p?*{Y{ w$"g hcV JVNZ!SB + 6> IXWc^=M> oFw'0Ln0u& 0L8G6KRҰ?`Wk7)(iK=3Vָ3mwjAc19[dv(#Įs9Y2B)t: xɚd-0X/k̅-md=O_eIн嵓\'w;Qm0^0 ~9Aknނ{<6qHzwf yi<]༖gidUyNשr ,}G( >)%8cHh_joMԌ5.8% K ^Yc۷N8mSNK]%ċP?:!Z},վ^ >II*e-KtvQ.jjn8Ne >q:_>+vGY(&ѯ&NZ }8szyR<& 6R~u:0Mt FVӘ+ٮ\7=%gΎ.p/Ύ|ph8mg-LKjkΆI[Azjՠ巼G۹pN^u۩j9ɕl9,X-"g]'hw`} +L0I|잆N)}U5ONVTt|4RlzU9+}bԵ[2tםdTY_KHLV~-!DV/I2|9l]`f] t:HXzF4WZ gz.I4+X+tdcc- JS5NٜW %s$V O&mRG]PImAJP?EP wIdQ_Wa6\`jrAp!Oq(3eEF1}ya PBL,Ă ! }600:6Iٹכmy|GSS&γ<[1-_Gweps!y]ez$]jeJgTnԆ ۈ3cA.qeEѰ 7 ) &=XD?7JCy mmM[+ h<[hhºuEwvU>N~ƒ*C31{v魸X#X| P>k&XNSFZX%L.BS^c<'0m8Xcc^ ݹ9T$7~'/m z(FHD Xe}9lT;;o޼+H!cg3)iY6$%ϲvu{N̐1UI2w(y%K"^4:TQ҄mTP8# +OnZw`AhUI\ =Qŀ/dKڲp9Umd&D s_hjvkMaL6+E7"jΝ&R+ l4ĮJ>/2jpQST]zVA;ˮl͎Z@ jqsAhĂ?" DŦ`ϳSP@ 3cY^6"灉+Ӗgtt.ςy Zġy6̳)OlyV?&p:RMP$;7*#| ާB|KΖ N{c tvH !Ev+mD0;>15iT&eٶi0 Km7'-d\٣[òc@Σ 7^8_,F՗eQ^iP d;.0RVssǗB=3:>YQ 3A(M[!@ UBE! 9yQ-_,ºʔ8Ngu;"h1ή8fgưIdB_LqvhtK82,aOΚ7-Fe;GiI}I"#9L3owB  .YTȀ5ϋAs! #]2h(%UZ>m۴Y۲_-SƅHac wK |OG(_?~$-ĭ:a`x\Gpq\8I![LϗG(ak4`| /ՠ#K}qIV?mYQШ^dvVhAr6}q2nσ?' /Cԥ#_y9DDTvm qtRUÙHV H]*voZ)nNj$| m*-n)TSN5i\pspϲU[/bDyF!(ڟPKꑊ&<6ѵK]r/EFN`xl[?{ $?LC`ž#ΕJ[*<9wڃ~/#5̐x;,af$o06`0$?vU; @ٴ @V('x4ou57Y.b+t gYobk{]d,_ԥ̼Zϟd0 ^ygD&`!nihN +8#WE ͟(pmq6֢~p>H)AA#/>e]]KOX3X6yݙ1 sS8#}n4_μdx6d-͑l:+<jf;, _^M]lA}IpA&/(+rL)LGyc!ɲAb2IMzlABl}9c(1`EUlrKqBBݳ99^?0u+0ZpA7ne kit&IyX!0|'u3E@>mjSz_17`gYG]ye6(6osPbrKx̎1ukⓈJ}WSgtTdct>e-[_xJ.Mf*ԦpD5D(0nRĝoBԺTuM0ٝ%ǖW LHQr1-TS˟K;x:5Qxi Ż6VC{Pb`91.r >lOkh;6jR/(U|;b5D0 &ԅ*mRIܝ/vWAI*2%g(9 ķ05f4v$a`&:"=@qKƮQJ3L{ZW YE!x~=eǽ_OJh+j"|8Y`@E -ZޝG#GݣC\K6سk \l_sWŷ/A?Hݴlf@.EӈW.@dJ2 Ue۞f; v+G H;J[>`x#9*TL2"l%65Ǹxc^e(?:aw?%$.6:N؎#K;vC 7d`_QveۇEFH[H-g PJF!4.*}sHJεH&0yܞ}c\eD)q\{<'Z- *A! jU56n ˒t^Zu&Y3C&- $B5KS&?1]!l_eBin$c|NZt,&_ɷ:di L2Vˏݲ@;?=ײ "Q}Gګ;fڠy3\Apl )ʆt6]#ԦirwI2 n4_q(W[uxSML*Lx!(Q$IRs=ݲ΢?>A\N65;oluZxr@qH¾N,EJvWƚmǔyݤK;6`_4hܨt,ZD ! fnNkq\p9bIR^%C\5+qWn.MߺFJ, 2CX:MsoiBqp n`׾AlЅiTiG, k'уgd,;~`\ra ;aRycTm$3|*?XHMU  |+aYiEgbE 'e\jEpޮ//@Iw{f#fK[{E>au tVR Auq[ot<f B ຄcԷTKיp/g j*մ vW9f8CS"XlsŒoT# rte K`)o]FkkЗ3T؅TU\Yu:3'Sg0 6p VHؖ%9?_.jD{ߜW"f 47joC`{Dg"'!Iřnn *؎u4#[V]NZ&Hvô=W6rY k2{C7BĐ8,$3}ݑDKL͛2iEQˆ;)!(?,T|ccK|Kf^t0>dJDzw@\j &[-^ƭEq|33ms% Dе ת11g!2<9S~8f6e؄tTejǞA[Y9V^@ (rÁ3JBb(HKm$ھKDƍ`_q[7߱~֞}G;Oiچ%I s& bk};} AI6l(Jdr,J]I iٹn*n:n/E +'=bMq_y C;\$Ѹ&ߡ hp7C|.B2P;]['VqzV} , ˿ #vx(7#C$yEb ,dfYZ*UD]Cah2ӅNA 9ayZe13͋iwnh:U,1&V6'>-PI#^L |"z`K1b qHm޻ c3$s/Ya *-Q,— )a@*|\agDrVw &97cqF#McrM9O!=MWS)1{怷)~,`-S{*h3 PBP-ԫSD}ԣ*v:UnZn!2gE\b9[+S]haPWṧ I]ʅ>MY[)eAKM&?6a9ý\}Iβ;њplm`zaqe^4\؎7#GR]ݴ6ɥHR1G]AS'<63˜(J!NrqvdzbN@Z^>G$'sApҖ!!66C Ržc;5i<5 #y/>%--eF6iTRhBU a&$Sj'Fi%$>|UWhmD6MȮtۿSBAn #!Aug%T,blO?d1KDAPD,(Z$W'3YvdGp @M/FP շߩ"Zzp)U]G a=o6e_Us^`{:aGxGDBЍƟS8s@ںql'rնqrd7OfuG̊q zePZ xLv#U}DDʓR]?òDcŁ4CF3ޏ.Wk'RH_L@ qRWF < dHsNQfS1u+ۣn|u:|b'28XV/rnٵYQ,@^ ˽/E?:ZrpMߎQϘF:N4AKl21Ċl_\@D=.+WgԂ0 2E?PPD}=6^/ɡƢ<*hiVXX6!x^1Rڶ+dY#iT!`7T,GVw(IY-Y `~JC)fWĢ:VUx"+2ZFqhq8REB(.v)T uDٷ*\L=ېODk]˄-Ϡ᤿,*suK}D溍LFtB;+p(6)Z"`EH.m>SJJ#9鬨Fz6C#l2P3_[֪ X2vj~t: 1 !zttԱp? w$cٽ+ ɥ;-HVZkYȉ5 z5sXS{D4W\lnq Jir'K>2tQa8)Iʊzt}f3rzڻt(N(>4\7%>}kv"+f8meļ|i<_y4%s/8OmWd`Ʊ]@29V'9-;j J,|VR#q@Կ#лQ9_Tib5o+-R|Y5ڃ2$ #mh$k0u6+1nk(x_QP{ح|ś -L&yE{r*hK;sҷrA2#\胿WH}G M19pMe e;ϙE6+pNi,D"Ȓ ^YI$?a( y _8Q[+fVs5`,`NThLx e?Lf']懱 `}h & c}-pp8INbfHCu¾E6APzU]Y}cVI\0&$K&9Z6w 9솿y i3e> vb  vv5YL`Vd0+#{O`&_% ,=hgvy.im^R+<錧0HaFc[{,M*w Pƣh o &Ah>ǒIxIJddmB1ރ$oX>k좃XȌNlu}F?p爷%7Äĵ/gGЩivH37Y-d4 Ve Todv˟,VQ"ZِHh q1H 3?n-.}c^JFS!! H33Aah(b)^DBP"Kʕjaq8v$ΘgJC]ҸƵyWĆ E`! Qw]t_+$M 9Nyq6oa\YaםtOL 3 b/ h1˜ X"_SDѐQ 4-r; 8QGpfLU?:ae .\$. $i_R Ck؎\o5~Q#b@mL&R> .g<^ljzs읱^_"z dxAϾ%P3yT~Z |59A| yk" !eFRSs<\t!X>MOR:yNPlF0C3ͨIIzu+5/LEpj_LJ >qXq_') 3pDdb 5^͡@uCYI\'56޺ U]< P2ȏEˢ'SΛ@ a#wSIagwBegC&.OO؂@3rP޸ :y,;jɺ<6>̻T;Xa *b^56ʓϾmä2wHAWYtQ,sX]NRvCJZ?ܴx::۶ǧR?TiC*5| U^!ӷ~׾%̾[pg-2B^Ct|Vk&.7׎Z6uH)_^$ 贓z4n_ ϓdy~t b59̒ nSRxxHUc Z< S )e67ھxIniX.D 0@T[m4uQW-WW~g 3r˱V-)m._fF>)k4@VeRjy9LI"sT7g%5jՅQA^ wfK&`@д\iB($ҧ,Õ4%;T ;݄.ĉ"Z::b):if8Z%Q޶إJe&IHOlԙ5uMr?s _݅%n2__b4Іz Tk|#>^>#J<2~ |'Qg0aȨ3uƋS|Rfٵ]E#[J\lb㓯+(:bBĚފYe'^pObMohbz+nJ ?1+ mT&*+INoie][-;.G'XL09''>oxqiH3an x]7eI7vXзhZ:=lgg<Z~ d9%:|;JUz[LH\ |F \z<ݨtwg?\aUR]yY׏,;LK @ /E 5;ߤҦl2CifTLuӼNfa"mˑ=x<_ԛ4/y!b{TAȍt$oMըCDTJ`Ӈ6iUj53{R2ExE8t [oO:"w͉XpĦKĖ߯>':z> GTx~7uW]sĎn.orʫؖ/3Qq ʳRv0uf;1 jb|'h{Oy#0eV-֑c/p8>y(RۙqJ\f#lti' 6! VUșE`9XfVd4QF1E1SDjhцTjZt*\\?/[.΃tѻCH&uZS:0YڋufʥD D|@)SEY|􁫪 Bll~T@QVx,`>\^ɢ.5/@fgtD()}b7Pk)SOƓ ]H*/muI=֖DS.OeAIpcB@NiJ4Plu cq>sikl֮NP~ٓCϗZT`Zz<1= `%sI-ОliW$wOKrɀb-H+UIԱ#KrZ!uE9q<ƒv`Rb}Y.1QtgF7bz.;A/35N1Jןn' 56"i`u#QQ% CyߵUږ9 JS8^f mT7r @ @t"I<)ƣ xkSϥtfI2q_rmrT,Ph3G[-釫q`s|&{>n@u^np^X0@_fQ 葊0Jd&af7f5GLO HhDz1< novR5&>Z{ԇxګQ&x=0g8d\PSXWXhAzaDg2 /lW".dbAHSP]ÀKD60n5hL2{ٯ@X $) "횔eRIENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/flare.pcx0000644000175000017500000001116611357170241022654 0ustar keeskees ??HH @ 'O|ϓQ0  QΥd( 2ɕCAļ½԰R .·ƳΗB\­«Ĭ¯q"|Ÿ Ӕ7 9•—ҨM DŽÍм[ DžĄл[ 8Ľ~{z{}~лQ #Ļ{xvsqopqsuxz}Э>|ƽ~zupnkjhijijmptx|Қ" ]ztpkjgecacefimtz~|/}vplieb_\ZXWXVXZ\]aehmnv|J ú|unjfb\YVSRQOPRVZ\afhmrzҦAƾ{unid^YUROMKJHGIGJLOQSY]dhlszf|tmgd]WSOKIECA@ABDGJNSV\agmqzѼ!2Ž~umhb\VQLHDA<:9:9:>?CGKPUZagmr|\ vnjd\WPJFA<:865656789BGKPV\cjnwѿCƽvnhd]YSNIEB?=:;:;?AFIMQW\bfmt}wù~voje_XTPMJGFCBCBDFJMOTY^cgmt|0R}vokfa\VSQNLJKJKMNQSWZ_fimuzԀ ż~wqlhc`]XVTRSQRTUW[^cgkpu|ӹ+Bysnigdb^\Z[Y]`dgjmrw~` r|wqnkigecdcdfhkmrt{Ԗȿ{xsomlklklosv{ӯ77}zwxtsrtuvz|ѽQMƿ~~f [ƿ†‡n [»Đp Qƿ›Ӿe >½â­ԯQ#}Ŀ­­Օ7 Jµµչ`f½¿¿Ȁ+ !\վw1 9̟M &Yˌh1    !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/brflare.pcx0000644000175000017500000001036011357170241023173 0ustar keeskees ??HH @ "!#"%#"!!#%&'&('&%"!%&'(*)()*)*'&%"!"%&(')*+*+.-+*+)*'&%!!%')*+,-./0/.-*+)*'&#! "&'*)+-./4243454323/.+)'&! !&'(+./325686530/-*()'&# !%&*-/45468:<;:8634/.,*('&%! !&')*+./23689>L[Ÿ`QC;87434.-)'%" &')*./3578:Ft}ljk{{O?98543/.,*)&%!"%')*-.358:J|re\WPNMORX`oS?98630.,*)&%!%'*-/3468>ik\QLIJILJIHMTbwM:864.+('&"%&)*-.357:Gn\OJKMONPQPONMHKReW>864.*)'&!  "&')+.3469PeRHJMOPRSTVTURQPNJMXb?8640.+*'%!!%&)+.3469Q_MJMOQTVXZ[\ZXUSPNMJQud@852/-*)&%"&)*./368O\JKOPSVX[]_abca`^\YWUROMJOrd>842.-)(& !&')+/358A\JNQSY[_acdghihfeb`\[WTPMHOtX<854.+)'% %&(+.348>aIJNRVY]`dgimoqprqpokhfc_ZXRPMIRM964/-)'&!!&()-/369]iNKNRVZ_beiorvwyzyxwuqngda\XTPMHWr@854/+('%#&*.348?xUJMRTY_cfmrvy}Ã|wvokfa]XROLIhT:63/-*(%!%')+/379`cKLPSZ^chnrw}Œ{wrlfa[WRNJQuA84.*)&" &*+-/38?uSJMRX]bgnsy}wrjd`ZUPLHcS:63.+)(%!&)*.468NfJLPTZ`emty¨}wqic^WRNJRh=84/-*'%"%')+/469wXJNRX\chpw|ungaYTPLH952.+)&!%'*./48>wPJOTY`enu|Ľxpic\WSMHdR853.)&!&')-/48CgLQV[ahowĻ|ume_ZTOJS^;63.+)'# !&(*.258KaIMQX\dkrzĺwogaZSOMOd=830+)(% !&*).348c[IMRY_elv}ypibZVPLMz@830-*'%!&)*.458gXHNRX`enuƵ|sjc\VQNIA84/-)'%!&)+.47:jYIOTY`fovȸ|ric\WQMIF84-('%"!&(*/268hWHOTX`fovǹ}sjc[WQMJC83-)(%!!&)*.358gYINTY_emw~ĵzric[VQNKA84/-)'% &)*.368T^IMRX]dmv|˼zqibZTQLMm?83/-)'% "&)*.358JcJMQW[diqz¶voga[TOKPb=83/+*'" &'(-/48AiMLPT\ahow{smd_XTMIV[873.,*'# %')-.26;RJOSY_emsz¿woic]WQMHsP842.*&##')+.469`[IMQW\bhou}±zsle`[SPMyC953.+*&!#&*+.48FlNLOUY_dkqw~{upgb\XSMIW^;72/-)'%"%(-/47;WJNQV[`flsx~˜{wpid^ZSPLKyN964.,)'# %'(+.358LgNKOSX]bfmpw{~yupjd`ZWROITc>843-*&#"&)*./48=~ZHMPTY\bfipuwz}€|yvrnid`\WSOJNO963/-)'% !&'*,.259IvQHMQTY\adhloqwvwvpnkfc_[VSOLId_=853.)&# #&*+-/37:_hMIMRTXZ_cehjmpomifda_ZWROMJYrG853/,)(&" %&(+.468=vcNJLPSXY\_bdegfeca_\XTROLITP974/-*)& #&)*-/258A}dMIMORTVY[\_a`_^\ZWUSQNMIWU:852.+*'%!!%')+.468CnQJLNPRSVXYZYXWTQONIK`T<8520-()&"  !&')*./469AhZLHMNOPRSRSTRPONJIPvwR:8540-*)'%!"&(+.3568=ZgTLHJMNONMLJN^hK:853/-*)'&!%&)*+./358:JosYPJIJIHIMRiyXA9853/-+)(&"%'*(+./258>Oqf[WSRSZd|yZI:863/-+)'&""%')*,.3589=KYvzaSC98753.-+)(&# !%&*)-./3589>FNTY\][YSLB;986542/+)'&! !%&')+./045689:;:98563.-*()'!!&')()+/234565676530.-*'&%" !%&'*)*+-./.34232320.-+*)(&%! !%&)*,.-./0/.-+()'&%! !#%&')()+*+,*,*+*)'%!  "%&'*)()*)*()('&"! !"%&'&%#!  "!#"#"!     !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/boxfill.png0000644000175000017500000000743211357170241023215 0ustar keeskeesPNG  IHDR@@iq :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:o_IDATxb?H4h@#>h@2@cG>+P K@w i, bU :Kx$P@K8 9i0^ ğe(@1 Kڃ@A%w35R/b ʣ$(L Di"   @@|5yx;k@@]7b' >BF"'@U"R5j  ~B&"5@PL*ZԈ2a @az n$)P@y #U @fP (z@)"61 σ I"j!2h)1)*Ρ?ل2 JT-jS@R4Pm PD $@ W*:d>I IPC 3H" P%@` : p)K F\/7> @xK m8dNL-K< H#I#4 B' @`2P`>I"f@ @ -vP $2DLSA f1ј b'F@ck g "3jMEt D6aPMp3Xđ* RA`ASDOZCpq@ZB"g@:L&C- d]!P#apP_Z)@.Sb%A1O@Q:&iHrh$h=E7DA@l F))^< @^, /fS{XT0@T[5@Z.3& !0;HXlܼugZJ=3& !02& -8DTezȰqcVG<1# *6@P_q̷{k_RE:.!%2@>=:50*$  &,/2321-*#  %&%        !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/bigflare.pcx0000644000175000017500000002574011357170241023341 0ustar keeskees HH   !  $&.58;952.*%#!"   &+48BGLRSUY^bdgjknptvxz‹|{yrsqmleca^ZTQOG9 &4BCFJPTUX_bghjnpqw{©¸„|zxtsgca]YTQJ< %5@BDHKRTY[acegjkoswzŠ®®}{wvqsoifcb`ZTQOI;"%1;:?EJKQSUW\_bcedfkjloq•Ÿ”‹‰{wxsqmlngfe`^]WSQKJC5*549?CGIOQRTYWX\^`bfgfg{xwx|þ}|}onkghfb`^\XWTQLHDB91%234:@DHGIQRSTYX\^`bcbqpmqsw|{}Š|{xwsrswehgedb_]\ZWSOJHFB:4("().3:;BDGHGHMQRSRSUYZgnehnlrqtwz|´ù|zwqrpljhfoj]`[YUXTRQMQLJHC?:34.$ %&.3:>BEGEHJLJKS`|i`ekjprux|ž˻zwtpqlhgfecb^g|aTRTSQRLILIHIDB?:82.*& "%&.489;BCEGEJKJIKQTqj\_`egosx|¿ï|wrolihfecb`]ZYhrUKQKHIJFIEBC<:;953)&! &.2595;:9B:CFCIJIHKknZY`chlow|}ztronhgb[XYSRSg|fJHEGDBD>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/radiooe.pcx0000644000175000017500000000606511357170241023207 0ustar keeskees ??,, @Ŀ}zwtqmifb^[XUSPNLJHEB?<:63.)#}zwuqnjfc_[XURPLJHFDA><963/+& ½~{yvtpmjfb^[WTQNKHFDB@=;851.+'#½~|ywtqnkhda]YVROLIFCA?=;8631.*'$~{yvtqnkhea^ZWSPMJGC@?<:7520-+(%!Ŀ~{xvspnkheb^[WTPLIFC@>;9641/,*'$!~|yvspmjgda^ZWSPLIEB?<:7531.,*(&" |yvspmjgda^ZWSPLIEB>;8631/-+)'%"  }zwtpmjfc`]ZWSPLIEB>;8520-+)'%#! ±~{xuqnkgc`\YVSPMIFB?;852/-*(&$"  ª|yurolhda]YVROLIFC?<952/-*(%#! £}zwsplieb^[WSPLIFC@=:630-*(%#! œ|xuqnjgc_\XUQNJGDA>;851.+(&#! ~zvsolhda]YVROLHEB?<9630-*'$" |yuqmjfb^[WTPMJGC@>;852/,)&#  ‰}zwsplhda]YUROKHEB?<:741.+(%" ~|zwtqnjgc_[XTPMJGDA>;9630-*'$! ~}|{ywtrolieb^ZVSOKHEC@=:752/,)&#! yxwvtqoljgd`]YUQNJGDA><9641.+(%#  tsrqoljgeb_[XTPMIFC@=:8520-*'%" onmljgeb`]ZVSOLHEA>;9641/,)'$! jihgeb`][XURNKGD@=:7520-+(&#  edcb`][XVSPMJFC?<9631.,)'$" `_^][XVSQNKHEB>;852/-*(%#! [ZYXVTQOLIFC@=:741.+)'$" VUTSQOMJGEB?<9630-*(%#! QPOMKIFCA>;852/,)'$" MLKIGEB@=:741.+(&#! IHGECA?<9741.+(%"  EDCA?=;9631.+(%" A@?=<:8630.+(%" =<;:97530-+(%" 9876420-+(&#  65431/-+(&#! 3210.,*(&$! 0/.-,*(&$" -,+*(&$"  +*)(&$"  ('&$"! &%$"! $#"! "!                  !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/logo.png0000644000175000017500000032161111357170241022514 0ustar keeskeesPNG  IHDR\rf :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:oIDATxb?(`dbhQ0 h0 F4ZQ0@``@(#h0 F4ZQ0@``@(#h0 F4ZQ0@``@(#h0 F4ZQ0@``@(#h0 F4ZQ0@``@Q0`9GO X,@څh!2@'/G A hx'F, &3㓢v ͈&E +bp -@ ?w*IjGɕg/ L+T4ZPFlRt(h@9 TĸB, it( 4 ئ<.̄τC .66>q\~l#CcCfBG @D LFрb2;`˔ș<_!EΆHdža/z8!>[@Ii< S p5FB Zc˜bfc+ hltz\d56LL%AFF023@24)(qV cm)L+ SnI,ܰy4ܸglG 9WMCY7)$AIYk۸R\ԣx&Y]Q R6y*8ȩ evt63Ћ-+)HcLPB3>X A[puGLKF#1,V"[r `+#@#gbjx\[&gAc Ĵ (mRgv̎/ACV /48[ 1 Av-;ⅾ(Bl0ğE46YuM%bֶD9_Sc*?_ĸ"?Y8M1-w RFPJi<c MVoW"b@YV2g gyAtZ$]f{*jWdY; >~=Qx ldXel̺ Y>l}(L3SUX-6xFB`yUiaJ J% 2+P7D v`m h$aH ِIRA.-~NUP{* s:vHjWk^]ct߬߼%qpzʵmHZv%5M ]1\_toTv K )f0 ᫝ dc TVAǂX0mddKQ峇ߖ%SϭE>ӽ}*;C{Nbb|]zPVI]46NJ@ *D3$DX BkBPXcȟ7UVǭZClېn\4 .YBp!~|_G_4-w[*֣ ʪS1a{~}| װ >AG[~b9G[_voGZO^]aN|AUU$ څ6K?jEFm<%;sg;IIה| rXKM0/ i<5υ ۮPˇbuoMKD^!򘬁cy k(~+7rLq@^߃8$G|/P-T\G8d H{a"EĽowR_S:P@2Ҟ]d:Qkw_}Z5ChN& `l爡4٘ };Ca_N!seL.] ˤ?j @q(iU9 n*E$PwfS!rЕ[x#x{=nWhVi$Pi( x<%!SeبVga2}OW"xFhXV) D%<3ߟĜs:?G9cnE$cEGt3Eeϱ1pё7Brgz@VN!' 1\5uqܩ#=LH{D5M@cn]}W7u & bh'O0dQ}?kw)eo}!/ 3ER<yn}hBjN&MS`9P!k=TTŘCs·g a4MMKiU`'d{ _6:q}SG!&1 X\ 8 o/ u9pj5= `6*A-ы7ozG&ƫ1:Y;f!A9X1mQ$wuWձaz|~[r 5F zcv>wp+֛MnNVZ xJʡRyf"1Aաފk! |Gx:544PJE.klY Jfp Enח}$&]OOaj\@ H#X;#pb.tHbzUki8A%MXtG[ , 4?7/-uPUdŕ̛g~*'ˇ%1ѧЇsGCAk0Q fԱq˱$wt1Az6 O ϋJ`ŗ90c࿹ #CIj#g !V oF8:&6/xi5_T"ӹʺ+L)}[-IL!M)DD'0r b 'c^ҕlr\aC* Q YDq~!j'ܯs1<0g>"wӾ/O ړjm(o Ht KVAO!4g?H} 4 QI& qcV85w`BSZތCYR%vS3sJ'(6IFQ9Ooؾ~LLlECͩyu*Wەs;vU?- }zUD9֏F/ÑKA1Q<~<7.֔=hlS%#? 8-7kN3xT7v, !ZDՊU a+֫1'W#HK@t &'R+YPǷ;Ix~\03ب Db'͂DC9zCG r 8Aq|N'_F8Jf)04u ӑ2[Zp;%; Co_620 b seQյ&}љl^_\7VRkIj3 H *[q#'x Oʝ7p& _`~ d!UTH2 C~o%[;LBu WAY~@ Af~;S%aɎgat i\UUnmk"/e^L/O'gW?)+=6] .!HԁE\l|Y :Ѹ:nOlc4cjDg;7}SjKe. OTHYRg2` s HBr*'!?~0=A6,Eb±`#7\Q(othB3E9@_ *DZ1ʀ؃:IFG*"(XJD*lk"RrL܇ 6yjV q5PPXdШZA7& Y46oUI66Tۻ~'fML>%Ü,f|=mxk%)_(:t( %%; .ĵ?B+#A ڴϹmImbbҴp{3sL*@,IV.d9$ =/\oqsk!XR 0_=̯Eu>_# q&lvAZ˕UHع9! ҭ7uCpNa+dNd4}mF(imKtޣOFMPg|Q"ķV ),%p(Q!> m@b@NA4_0X H q Xyt4`_1)m|yߺ'vC-3iTIc E4!DN.v ,mP@kAM{񱘿=!ߟ RX_$PUPUYx.@] k" n3b+q2(ΗI&=+7 =>= Ł*_*JUG]q L VBb%VXbOؒ J]`yDIHf.\(pc+qzsνhx* 0A1OZN0:~nŪ9>nn,'?E:`-k^k1JEx:olEC{z!tF>#EiݓccPl:Oő8DKrB>i Km. =_e Z'էw0UOi6%؋AKk!=˲ LAr# 'ܘN|(pHߠAjsyk3e[R!VQp*o SX ):wbj$Ai4L)8vvDO${4z~cqn]\3j^ 5^=v#&,Pig4vQ/Y \}G^1;G=\_yՔ &@ǜ.ZZWxp(뙉籤$[қ<Y9;!&iC Y]\RС?7nA!E[$7i=yon 6S$9|[s!C7˃B8Νw'39xzLaC3`C=*o>{{,Ѵ~hTm [K}g/޽!V-`/c)c$xq`'I8 @ي{ASq$VZ |gX*.\ L#,1q:4.<(Jn6 q/ NʜT Ӄp $ 1!A,Zq"yֈ<տB\\Mi+o/ϥAo8E%XTu u&݁{4'p9uY!ue߂$pC53q;rSjH* )9TX|~6 O^hM4FK":\@*ljʝAP-㢚ЫZO&̇3`jߞ̶v_wgQ6Pƭʲu38CAyd4T cA&Gdٕ MK\M*ULǪ.jpqq<dc__4GڑvM4- eGc˺ ="k^w΃- 9<->l#[P?d-snP8icLqbʍow/%cV(^ @H Dћғtڂd 2Y~B\W*tusn.J5ԽSZu [z.ݍ,>,{j'O1gt$R*EO| XЋ.U1l8UK8Oj$ta>2Et$]#ƣ+ɭ{G&cBIHE D$@^e5\&"r M@Tٽ(ry߄]Ł xqK{ =q'YY[i}ەBt Vy4Q]v-8j d1xOzBj[Ic}H`$ ).g[[j &PL ]%/K1_\)@Qdgr辰4D>JciHAJY UVGHb Ya@fޛgtbOJNE1f:t4'!}tuAN6p+jom8W=t->Y<#4ń% c!g A¿iVB)qSSρ:hMYEm moȚRDu,/+V4DwNk')mT|\8p詪8_@‐@"9CAEB(j8w7[D(Ɩ]7opZ XWtI$> ^bvxCoX"ڍDl_kI3z+ڳO%= {}2B{޻{5@(>}o!i,EWr?C-@":z|dcg{M'lEw_8 :{glvw9>kzA}j;w`su7@{baN8$] Cq?&8pQ.XhgӰΖL ƛ9x6 sB4nh =݊lsrm~FqBT$hH*XXmG c [}]:/C96[iE^PQ"rfEJK '\}G4]FGsK1E7I 7i.4βx)vX˥ĮE[0kh vl OJN hѰNGF'xf\<rSQu*;~n,>bpg'Sq4ƋD[R>{\ךGNeʼn ֣:k&F088 Y\ P(&k0$~yM\8K S՝s{ύ> =4vw4kYDܾRXۉy^-j:KYouB ~HMoKgC¹0?VD6휝N}6sFF6 - t!DňɐbML<-&7E)cpkޝ% + = i~i׮=J%hք%ptQwZa>L34],1UҦxLXzŠB P \t0`{,<6546Z;TesWÉy20x~%WڰlU3GpWXBIC d Hހ sLFQ4{ Wz';J*Ř; a8a\"B-IK9VՏlv n-E$H):S8yO+ka|ŏxn --NJi\E1Pj`q&y!ӬEMˌ6G'oIqTo\]>#n">NesMeQոaw^ S={$v(#)ײ"5EJ*5툣000F;?31.DqHtOs*2!ysϹV.k<>>mKLy"bz4O4oR=Z~ު^ nlEbgM>jV BfZ\l̝<=g>|3Z&Sob^n(=:tu~gϯ޺^uQ8:jF:?1q+S{,3"NRlpsr!p8Sܹ8$-q vC`=B$:0$AG 3G=$ڮR=/iC[]סJ̭hBuuwB8}: 6z\@f`Tv9 VdS9ep`AWf^ `^wI( F\d:k iqƩEԄ_&cNCQ3Gv}I1gEœz ANx Pi "Ǣ(hu|)SH]60Z˲Q6J OLqC_!Wu;N/0ǫyp4P=s)vZ?1jUD۪yfe_\n@όLH@H_jQٵf6((,*(?gs RU!bdl{ιΛQaGM/8Ԩ=y0-<*e2z-OE=.'2r^RVB?^A)`7wҤlSDz-1UWyaW=QG8+k׍|l3VM pskb<\[Vk2s5|pй@{)~AS>XLX8H6wܑQ`KR z>JF=yY\X)x/g9eՐ8ɚ y h*0!^ZD,gO!_M>ePYA5N$pD- {t^GU`/%f<_ҵq.|r]lܬݒ讥mS[22_J{:2Kt4Zt~./{ϓ+5oE\͐NNu;ɜx-`w¿Fw?^jz`NZʢEBpO#n{r@ (Uq۸ 3/C$=o޼y>i6ܜ.Ҁ~cTO@i_^rQK}q?S]աO^#cgٓd]Cks7?ՀtZp` Eaa}(TXEk0XācKճ6Ǐ<{r~Пuy'\"bScH:eY%ϩcb9;?@opNfh:'쀑%gdnò18F|RIG mSNG^h8'be+әd!҄Ħ$t HU7}\DYvBNOXg4`#a_P7HΦ3s,18+/ yءHA x.z˱r}:HdE@J 'aWl̵@!KUه~"ln) ]"Ҋ)i VAE@-Jl9cMgδj]Y5 iտ]&=nt2i9Qay2)(^>|Й .prauxuLAsS۾y-WhS l|mxfL)efb19'`"lJԉi"GNd{ޛ͸7LJ:0pɏ= xBE dqz}>M$-tŅf"[/Fl\h}XMtю&bfm S`ּNr-q5C>t,t"5~APbUx5:?-iNlO87N"1N](s֔C)L  w!_R uFE qe(G1C@B) P_; Q21hY`D`gQzQl=NX.k'a&{s 4XHi4<֟K 2fiGVaPZ؂Dむc̓k-)ޱu)GXd?w{ .RP?N,̰ƃ1:4[j?tX-Mqi!5(Hw VϖuPiL,sDzB 2>EXeX1{7;dF+W߽Yxfp_? ?>n u^k $DH./+(mH[s di/Ϯs~jR> SG>[SZt^syaPm;vh|lUȞFzp& 1uJfrj㼠j QkWT8>s`&V+`U2mJJC9lcgr$׋D^9݉2@dL{f v50+L ϬT|ƍG&3_/Ȧq rFˆ=ƄfwrrOȬ u~2oFG#Yk2_=ckvMކw3D8DTFӅہ@80ĜATh1r\\D- )gԘ1 ړYFqRp;@WˈQv.ftDJ(Jlw͛7/pֿ<^?j̫ω↓ wZ{lhײe^;;*H҆ه3n[sMn8bχ>6eU,!6C/.<}2Hb7-, "yQ܀>FO-B<Q1l[1hJ߈Xj%8aCBYHQ >JMD+>- 5[A&uޞE+$y$anA2)tU}Klxq 焸j$Ј{63PB"h!PLu98`s(pyvfp'k PJXJp>j/p s۶cIl~65xV."8H!?[%!Z%M|U^1ǷWߦkCz>M<B-9B\@{) !6P\qX7rAig{]}E2}Iuiؼ-Sx0˽u_'vٜyKv rWEilĖ{ǐ]W4ΔͮE*l̲}p \W^}= 8 g"Lg{T |7鰨@46SiR zPj (lOA8.> ꠬k!$h?9Şm7X̀,Ias~Z"=̘lX-bi~a5s4+mW4׻ƎD *q# C_B-@)+iֻ6=T\Qb~77>}ѿx1Mc <5~^X|{X w6{ߚ^Q̐|ZmʪW%nc!0d'{/^٧[ 񾧯}e@B}.af 87vO: ;me2Lez*?7fM1ʳ,MP9%6}sc0ԤD]!9jE'.KGsv'%P)4"G.to2E4%6T["t=a!N$&- O b#1)F]ת\Z~{ \"=:r^L #Bm="܉GPnݻS$S]wh.}? |]n@=ŧhpvTAԍ_`@,YK$/;sT,@)Nw{3<~Tk}$3d9B@dp6p|M/W>Vriᢹ湵"ސ%>5k5ΗvLNVrY;LRjw[]vsl34瀨¶t,r3|8NPp H" AsH3BL-Nvܛof_gw4i,3SqwZW9y{C z ʠ;5(aR0 =@0A!iNDb0N+˟UZ|'Wڮ]a cq8! AIKMOP|@A$6ϗcg6Ai(۝ IjD=>VkfR ȇ[o>Xr{5NaZ\*DbnhӃ.$O >L?er3xHe13? / :?TH}:|Ahw` 3yO)<0O^Hw_ e0>75a㺀 C񞬫!7e ^; a=-bĖ{8ݑ Uȵ[7,ȌfK A4d57ə4bdYD>f Ofgs y0̜Y$E] Q"fզhgr!I@ _ t6V=v^sLUh>W):F3A)k)]mأj ~:=D5mҺv*$L>A;y:H_F?v-; QS-TDʕnܻt' !1@-3xϹƥ$)dҦsܳϟw qfOӌ@Aw;MK5'!vށvǎ6ԪqɈÛgR<99`aP F&OА@h4~ޭ 1ˤO `SO!Z >? ʌ=r1U%A\L)Tdqg .`` ,jIN =j1R1W" (jX<_E_b C$Z@oYB \ n U VM:zpeem"#W;d^Y:1Q٣5_v5- AtIwMo=՟<]PU4&iyoZ=x1d_/TR5Og^=oCts?[ycsEQ{xPxm'D3,/Ɇ-J}sxzFV$@Ph"-d:fuytdqcMHż.a_o(E=o4aq*XRc2Ȃ|$eA"[ *#0]O_J<|Rc8 < 0TtB 齦2?^iV*z4 !nmNe`|`67(?X,}2R9HQ{-/ϑ} ?E4V՘Ԕ+ӱ]]K.F]YV zAT ٧=(Eޘfry@I"M:/ 6& Gt%z6YFYoQ-@% B5)c"O~&%mW0 'O2PR`x;ތ CIwgjȎ;%ec xI fП߯~8C } 9]!LliίfǧflhO5eFU7Kjr)xΓM OHIa_`Eia_ 1YL z4+W;d;E 6!a,z7:zʺn)3r=Cc}W+8!1viy'bj%P[1\F~;sG@YQ[ 0Og8/Dt.և}g5g\l!L\l~7m@$ J-OL gzxB`m3UNF$};3ǚG{x=>T-wuDU dw-9cT;]mwUDM8=K׷u(8<]h:dCzr)ƙ^M/ 糩E:KЧ8Te,l'<8!{)w[t.U <8 6lxgG&}b XuZKr sC 4=E6O51r)6 j^#בjY~f9Har PZBNt|mBL l-|lI=3>CuM þuTQ #3gh$/OO#l{Я垡P5qؖ jУ h^ !-`3Hu%R\U rfx"}ojL?{b߉@v5- AtIUA)xJu xO[K ̼y. `+sXqo*O+/?U5MQE "5b^:s&.=v'\Rt@,d+2)r&ױ*TSVC:٢m^kE7+FnYY/>KˊY3tV\Ez|TO.+u\ qyX;.ck"X ,Ak `rlʗg=8O>hn*m$#obUZVx4(}zߤEnmjͪ)ITg7\|>{xASٝr6{]M, \e)Oh0JK[ Uyrf/GN)=p""`sMaǵb!=hlcBZ,Ǒz9(= lAũgc V'6agV6.35?xs{/Fn67ڲ,P&Sb a q0!;rpp-K{f&/@bamC Vy6#{Es#QւdPs7Zd8PpPEq˖k}&'rOAf_v{l[o^BSI[w%D??^B+Yi =ӓ̒TPA "+(;=1L^U~Ȃ/nû(-F"oNRk+nl^ QUF.^^^݀n`&V֨lMdMJO?Pb+R`Pgg {tV W~_?}X0MfcR* uN{p *v= ]O piiT&eKv1j4 ic (e$ebg2 &vջ11e픕 ODd3Ĺ#SdcMq{9.mS@ o+~>jZ&&4"*(Ic7I[TM䭱 SO{dgsja!,p93a)!~H!C߉r.᷃@C~sOYyΤ+u a`ez@6:vmRGRH7of5ZzÆ_Gz;z0: MaN^)cprPFYvCtq,J D+?XV}V<4^YwnF dXc(<]CyrZ^D sD)ԑ>̅bAE{Q}=JCqPx !A+*Mv^Eg&SYt:N e HXx sFR5MWѳQ_ ?&^&QةV^5eܟ#P֋a{B HB)*܇%z~k$gG! 97۶Z1#qPuvWB !eR};k68&[Ɯ+~WU $.o91Hr.@~>a9vup:Ab`FS#\^zK/9:8תĜ/ J'<h%ҫ>/, --*I3-½veF YanX zld]j:*E[J }Yjv~| @,'At]P j K=@|v~#Q*#%)Xfzvz/GT'Dq,%]6ǤqVK<lG==6h4x#NDs"3j}Xך -TZkE]~.؋q?-r2|H [ནv {Dv`8dvaǤĔ;)8fltd{+][lL0F7$t:cOڞLG Vɤ1rF}l* &+\`uU(bTS3tZSWn> u 7qV .-(i*ݗ̹t s0t4v{-2,,{Bt WrΥʔ$;TR<"<ŖJt(A vl޴pD;wo`ϋaN ~3Er+.g8%)@hJm}|sȯQ>~9;` $H{H֐!kiNI&M? cc$Z MjvzACٙ?GzvPKѽҹSxqQ%PyA7`v+wP#G |FN[nz@ ꛖF*ḫ+Y8!)|SgTdT8ڡ߰*w9t`i:)Pq:R2ZE]8M9LIe]Zy0Kr&d \En4o"jfP@m`J,@ 68d58XHKfG\^"+p +ws=\IjgjYR i3OYjId`x}v9_ x{̒oL~x6ŏruwD}Up>AZ\ES)tESm%%=䩽ӐvJX| znpSHO~sګG&bee^l[0VBh)%нb6s-~@ !p0VLv)1HM[{[Xu p;,]^?1d,N_XE8yQ#?;k|ӝLEgAV0r|!)IQo@`!TVxvֶw__ ӧ%OOw; '^^,^ R(-y,"iC"c!'3SS]/ F QV[j6A<ϛCmϋyu/7]K6[( 1%"s1k QNlp U{lPO]߻[O<4^V ή9iHfk5aoe86SOA#O.O{A3^Y{lDQYZLmq?@Fn- q^\οF Ff~^&}HzOn]~^J2h,V] dd}< *7d5}@=s;dPR사+ *#5`IapI]^_ chrګr~G#qz8y׺]qldXraagB*à=f갶)@>KB'zXϱi>z+5$Lr.a sYiMnhj/ B'ȁ_ 3uTwgkDtЙPg7SH8?yU+.^wm -r]6M/W'%Nf;4G8ӟvkRiiAw| -}b|xtw7f'g()'| bA'Xa1HAa{~W)B(@XEzZVH`G[KԞeݻ@!mf]MFn>P0`ƺҙUeF@mu{d[\Lٸ0'mX#p]EJ/1z]985zvk2[0>2'+7^Ȥ8 c%e_?ɠb1J5<oF S5cJb@Mx x]2vgcNz*eN<TC^kWo`pRc`^.I I-\7)~tcKA|01qzt:_<=9Fԩ+( ߭]NPRX ?oU#ҖBm;c$Irvwf0@@G@z IW]?+@( o4[?Z g4Wnuaf=# Dg\hJ5a̾H3FÌ" v1v]QSwdzYu7a;vjҔxGn]! Hm[9:J!|$P00FzWEqmP`@Q1Wh#;8s~o*-.r9ncYךAfm"ɀ'BhV%YA,`öㆄATƓؚb4 lyUPo UTV%h>AL`c_"Rl*)eDӬHPg%YZ˫ZzTU 6l9hgDb{q,NmJ9@H֢BV_Ho>ZCx[b0FgD$9Q ZϬDuw8, v Ap G$H*-R(D % 4>3k: lfwf%_?[N-:ʰu(ttmfO$JvQhkM:=]=:@ɗf}ƅBhcJ! 4Bܸxdփw,f="o q+m1!,h~ u x~vDerPˋT*pBTe Vm*RZ!C]Ν X V׭#㏂fi)k ΟXFwy|5J FUo()Mu%zReȃThQ>j(}930Y/[B$:IxCKi$l.*E>e_'ӯROvx88$*k+8#,*$'#F ٳ:Xp"6 etBƆTH /+I1gulrFLwx%jq9yHP 5Kd@,lOƮ%(7qFMHjkU~?.E BpM0{}BDD;!s|Iws쇀899)CAFyjsCS*@6KR3,im\gp'2$5Ay& @~1ml# 6"ӮwHVjcj~ƈv$Oa6RL;rU %[b)ӭ {妢YXq* c쨨[Ā=f6Yh~2uk2[YN֌}:#A:xԇ0@$\QBaHٕD>!+T$k 0z];t:|JSki"0  @ˌݠ^ ,VPbҗٽPnfXii6!\lR\$7䨞{*hEb^&eMhr; 4&^ԡ%+ @hv"iͰtg5hF;5*MLhrߥ]MoPvc'MܺH NܹU\?.RJ !c?ff8U-'ݝ7\`0c(IgS gT'ȓ\h}U;K!l@!K>ɄԊa.[\;;ȃ^ƫ4@ 16/.x>ut.{rWu'Ȱ׹RrAf:RqGDB 2I:dl;UiuH#3WYhS|T_<QN9 dn:IHc6In{ oW׷v-H^{H>ڮ,J[T ,7<צa$<ȶP:Uo"zX딁=uk!Rz'/'y>p&SWyg{\-Ў_圙`q 0Y<[+ldW7%#[}am[V6t:e.W ӽFIr^(-ݮ7r,wp&~1Ί|X^BDu4T߇f SNYT]ۊP'NLL6+ŖBL"Lc4z:P ξֿlW B-L"}(Қ]÷1f‹f?vFտ h( !^BA6;|Q! ˌ k7nԐw4`&u>ش64F*cw뽧sB~"r>MmQq\ٹHQ8JFCb#j{ !#' `Ő:A@qTm vEI.6Ֆ(9FL3)$RsP8?-pQc*r-]WŐe#Ll-L,P GR|{Yв!&bDIP2ؗKM>Ùހ a=R\$YYVLXI22JyxX|!AW\>5}KV4we:yDQV#2ڰgcy=4]хwJϣ4[Y̰n}gFO!h'DwpYWG®mi(q]+W5D%@P+SAUh\ @lf8~KΙݝT Kg;X=p}I9)~(lUir 9N;Դ;R YbP8U[2']h%-;׷t<{룛69P]5pw 8ͻ68 @97Vvii\fI*ċLhWx}Qg #غ!(gk/+˹$VL&:qn~aYzdg~` xxWZ.ԝp!B UI^M\c;yRjS56{I5UVkCHy2i$ONǧ-8?DQDErN@6 )RlU);!xnxׁF{wbw65@V4Ջ^OʹDZ]|On.no:2=vR9stJ1VRfo@LTl[Z&( VOZvؽidhAǠQɈHǫvlz^^]~@\ݲd ,l]n@\c0N1QTKGPU0uf\UU6÷;7;Fk3|[ն:iewFnͲ$Ih$hXȋX2ܠ3I@G)86H8g&fQ O)+o 04iv;? 2rqX{s5\XGe~A^@DXHHIG*Xөv:-m:زxB-5ݏC8ʼ52YcX|QGTKq Si9 "ϑN^'l_dz8{Z6*a@Rs'w+ 9B#MDl~7 o?\QɜU!WHr})qξ9R?0}2hK5\mofN(-FO5=GYbfX,Xo -@2_Av~-Rvr eCc0(@jH,~gaDx:D}g9&| `WrOAT j(xR>3zϛb!f=B5?)""#]W׫4RPpի1`|׍/~!XZ_^G􉧆r3;g}7&ۄ纉7@gWp[J,{\UlA41K@T#-I4p E(C%GSiwa\PR;[[3-b34OuyFi2mkԼqGs _6@tJ׮1]X/o*뇼P"c)<#HR>G+GZnlL֛Z>R7P[LS03X\/@OA_w|5:H2{#0d*/=Y ťеT90+M!'4ӐZ 7#yqdz@~8O7 Yr8t-w Q{jEN |6hKƥ2R'@sFPNݾF]rIZB&xɫgT;'VGyp4e] 1U DJ34E<:~bq4[(6}l؎F8_T+nV)EHjd9`ԙһ{RdG~@۶ |-lA0umMCApɭiAT?7| ?Nclj̮#>!K;ٝtOпס?@tԇ  />|r _"wDC Pj"r//V#P715dǽȷYoF!NP":> (хcrIP4|UwE)@צ_+B;_KO4@9k?&U)N+azQ|B'0V.J GB\,4K~9o?o ˛:!]eLrt(FxVsJ5!wU4 v&Pu-3l᭑Nf1|>V {ww u`,toEG 1|jLJ gFm\$G%;0BڹG3}|xPYN*)pgd#_#IK/nu#p7}eZa!mƌ4$`4kgpBxAgA#8U)B [dܳ8D{ ?R.s\'*ƩX:bO$t9_|:,1u4|- 'R? kqGy'YBB\Z6KobIXz \O+`L\ @vL ?yEyeakS9{2 2<}IPv:ΜDsq2ǹ 'lη8Q#]?jKVDA !e {}f\ /S+o[2(ܬ{kvQnLDJ2H+|Aҍ0h-)4ǰ"Ӿ}-C}N͹0(mN֪c~aO˪| P$ Ѽ}rVzQ(=$|j?Cy<)ΡLP"~mUZX[Yr&kv"@NP4!3Mt=|e}L ~>`vۄq1 Hm^+KV!c0;sH)O~̾5/I/{lֈAEHG1+W:EPPkb@N?t;@&r1b5Q}GA7]U@\4AA}_x}({5f۱Ơ`[amZr c>i})HU fV3PEril|6]VIU9e$``gd\t&7Zfq{tYG֧)]/d^@hxS֍<DzV< ͚[0wq}_E u=x+#Ok#@_!5Z"@ JuӛXХ&\0s7mr2ViPtqj( [DѴ<,}yZwh$?EX D_E\D@z{8 . X8h$B;u6?iИUHc G\X d!ނda%~<p[,Sҗc~XH!rPBL;fy +_W8D+q$A,a0_H; Mz9%${#4ϊ?06?}Lߏ4^}Nesfb!3\tpS~BL1|r1(QBiYDT}77MP}>~f^^CB8L:~x2Z:H&_(5 ; j0j^9ySC@_jhxyu>ҦC.gFȉWZ @zNZjky&z#˧C9YԢ+Ub%705WFG<ˬ0a6;p/1 P1,rqʯIWGiL"/E#E8TjMØsыe־OѲp1Ӌ=FiLKe'G#͟eg[4bVd[&[h6jnTno,JϿZMI9ό2DM{t{%pE~أ,\:XVH~K&;wVb'G"kq蓔,,fO}8x K2lOZgKFF?=}s X 1BSEAY×Q %; $}Ajheq<|x,=;5i)lqEʜX^ A1y~lE=_Jgo$D8Xk1Rh73stuXo/ C ԏDžkԽUu|gcB!0d(H2-!U|p1q S1tRyxVYUǼ6H BbDtpl?kFu}g  Y/ڇ@ A'T zDU_hkbc\;HmsGX73Bu6f gI2{{2F71G2zT([w=1$WC  NSL9gG[7qM#Dw'5W[߮shPfㅽս9DM?T~QvPSkkͮ^k3@!!Ё[Yq "m5Gn뭕_0v*ڰ? ,%ގCꔏ;mx^Ui118_-'Z^C ͍RC``elURM*U^+w iMowKʲ.J}[qֵp=W)<}WRЗ4'![ew%vg*+ʡw^++ oM1ߨ(.v7f,~f#w$#d>2ZMul֙39 tj JQP٫FLaZ\)[{QjKԮ$˘"ǿ^p"mv2rXݐԅN8\T_ C9J';L( <{Wn1E12 HJ{1VU kn{Q L|F^^pZz߉¹6^AYMx,O#ZqAj hI_֕D+MqhIڈ]\<s\~H겂,ăpзK:,+Ef4Do%Mggn/ɩ||d|~4=p8_2c_Q ϳO|h(f$ѩ5ɮն35&)2QYIA 2pN@ݣbo 5ȲRjM( e Ů;9 j l4`/Vt}F[i1~f*# P*sum; CA((+QhRpNJ/i¥=\-?-pja2J_~h căP[UDIt;RIbhlowӊ( PӎqM8~p"kmRQ.*QW?z}KnͨD=p~ذ?1\ $KLW<޳Ν,1!Ȩ/Y5_޻j=jP*$xgtdVeÞʯZ.?XLr5g*>q6c0x4~RI` ZO%{#3+Q=.JPu~d2ԦڸPk&$uEĶ)ŏ0iD4)Cb' d4ʢAp}9[<Ԇ!2U1mJj%Y9$An^n@X3: ӏ' @a"{o|cKG:f7w8O=P:XEH% Iu\؜YTb"F^?2z( s t\[{ƺtu~/]6(A_L_QIJh|ؐɓ CINPz+dKcomA{!C|[FSAfE' :Ӱz^]wPbu) *9dW e7M]h\{; dng `FmZ'1)i=Z΃IJtZ8tw?Ah/a-(3nPJu{ۆ]4u \RT[6ճ³WqpWٷ`q^ȫ+:]Bm /6ғ0KO0pr}iE Lq.`"y6QJ,[4U5ćwJPN]#H̓~cwϞuuMAp뚨u4j+$_XAq\s63sxپb~aZ㔍(?A:M#U捛E>;F^jQ>yhy}لWyQ/(EV?5mpQ0AMQVѲSPEP`"HrID=JMP ZK mvcs>t;B9'6Kl(_l>(GϢ8*%}; ن.MSf{QMK҇׏j飐mEiז^B ^wYv6dJ@I(ԗ] dN{́Ay8!۾UKrQi Ypr#%c;X^jvP-D4þdaftȎFBi!ݹ"oTR{xok{RrtҪMTSUϴމ#} -=6J]Y],箙<3sMl e⟝, Ga` ٺL?[.1*yzq1ca6[ EpV!ЌX|lKoPol7MJMꆠ†5b] - uMZ\cR,9sfΤCF™C ,&~t^}~}-ʭ|s1{csF p>n2c{Q :e oB8TZƟyvv@{m]K>hP&LUg;9wnc%Nܮ?Ewh$xR'<-I<_4ju~H̻H+!Qwr sۀI]7r4I?لEYkdQ|v>\- C~E!jT=YəLp, Ԟg {o{K$ G0j-r>Ҏt'gYV'h[a INn&(ьqß^p: Z Ƿ?t6lkE b0HeF˵;2c4L*>1D w ;&f-P^쟴|_\7ԢUt:bCaOqV$a?D_9L$(wÉ Kɒv FgJO/#rvֲDvӆ lS$Pn(y~H + c~:,(7Q93;We1\s-5oƟVJt x&D׋MƮ F ⎦ì&gr$40(2yU}i.mauPv_䆮 T^\ dQW vl۫9lE]\Щ$mMOe)4m%VbڑTyeJ_j/t>ɧ6iuҘT [~3f &ϱ\L]I1نooks)e~+H) 5Wl$Usd$0(޶o:~3:gx@s@HN2A{blY 3so6eO 'c;֧zpBؔ&aYϳ;}ߙ%:& 5X 69q)XW˵JLvϑ :(sFc/N ?BW\9Nv:+dG`a5{,6|<v 礋9ȴK~V S ϲ=6Q‚ xrj];dͽ]Bi4f_@hH~Wέ'a «K)O>l)Ec XJ u3k!;;s9Id?gK=Ftyq5:;fU =.yH{[]$:b,.N=oD'#< <1[ieP n C $kmz*z Ay.ꥐiJ ~ߒ"`OߊSҸR/bYɢ NW:xS24!ZtĂd4)̩mH MɂhH}|u}a~ ,Xa2^v 07H$@82ɛaCni7&6726'bNòQbik$hAn8oa Yj3uO7;|8{I<,t+U)0rܶoi;,X [(ǮZdhB=xdYiWZfg${mJ5Mrqϴk64fnO#I(6D%4ʻHZ6P+mX vu,l:c[PCB зu5_@+Wg4D$ NjHp'@S8dc;'=fff߼yf/ePzB5 Tg}|j@i.\a})BL~Gb{M]N0dA 2PU!Em'J|,`Z#/H1Fڅ 0g(15:V=@uMdBQnk=ļcL!LwdPtoI c "LiNK(➛..s}Ai cCa;&x 8 _h1c9$XO'_GOzDPWUg>1_ΝA+W|L$ {a!1˽c-`4ɂt%LdȦP'ֵΦXD flͮ-Cii? AɻJVm f\;/ȻʨSP ?A$NM3H^'b/9fHhw@:*<$I0}¥On7m Ħ&!Q{Vm/zWD)&47!^vΜ=g&;9?hP ֒.&x|nȠ́"ڌΕ$Q 8NR#Yc*zNJر,%?¤u]Ò&,wԧ-P^PDZʒʃ`Q{ hP}}g6V_Υ+q DÙp9ftq'1QDvL}ЍK6;GսU|-{ӝzg_Ÿ꺞s,`;f} %[)A)/>x}¯}RvD>"嗉lHieNƺ|tK ,vc-TMȢ҇4{pRH Paf$~iܥ ڿ&̞-ldfugo=b8?ʴ15vm:)Vk&dbԁaZ*ۖt(iZDnD<"!gJt]Գ_-M# 'lSvz*E"CX\hp+-[95gyU}{T r g"L^ݨqhFS0 XFV[5.Q,z$Q @Q>l Bca.]m9{" (nj 7mSfj[=mAY?hh \$34gsn!=+p{N1Ƙ)2@;JHtii9/wv>/5I `<:8(k>deM2…}m,8cTIR 2m}<,lMTͦCQ}&A+Y L&O5t1 vEFS ;#[Z fz:8 wa<~rn 8Z" RSp9eO_Z^j:Q\FtMHܢ\~)>ʳ77)GG ,%>2R\.ZyKC+ >x H UyxIKX j<5p62^SP] C_;7Ghy('MV2. fߌOQW fMM4 n̸(ݳg,D &G7ccb99"G8 ν}q RzϾ}0(V)|bV>U#F3J.0syev//uJkda8Ԕ  Ezp0fxmgY@:QwidPޭnWM5g"*\'VgM7:L2*UF1(3s9!ఓ:DD̙Fbu9 @1E($Yޞ0}n O|7G (T~F4nEeOp{c¸;?9ۊpSkZ(X`@ݸ^Z"ێuؐ$q9{Ro#$!["J48 -w2mq͸*v E+li`?ssQ.*U_ޞ&(o;@'I! IEe zC@N{@izG΂p@jHIbBWO=? `Kik k웙7YiuU]{J@=&ڂ\ IYEi=?x3CE};ӿڗ0u.; A)JEq c'(-V;…!H ˙3X0"lٓ=U(*k.3k4B9A[M]DvWnv tG]%H8Zր\n`ڇrUH Iǒv)vZj 0Zh{̜sgiEDRr,yxy^jagE wt=pg}ւ%PؗE0􍱷υV~)?hU\zP]TIބw$92`^I0i%:c R/j],\M09O uf+1Dm#׈Sݛ(p _cW^ٙ `SZ,Hل"zuvnT7[V%^NDv~no%Z$6ZC Ҁe K4G?PN荩ҥӋvpDOWκ>%c#g0t}4BDL]*aڷg R#hY9uN @ ^[ tM d$)5\S}z~ &ώ*{vvT\r(cZU [`RK`$y\=^gֵ(2KwL?}o=RV@QYc Z ϫJ1WXn/YڭK?&Zsl6˺y;8Ԫt s) 6@/yqFh()0Y2/1DîDkw:00tizt`Yb*TC8Ό]'L |EabAAMSBGPnbQ0΂dqgZ̢ԍ&~zL߾Zϔtp ڮV[RF0*cp=2%8ؘ%*޽;G{#6W3Z=/Yxٴ!~Sʴj'"1V pV pʩ6j}bK.Ih"\7v (5?Cen:| \/@ؒ RZwDoT/cO,?ٿ8=Pu6; 1v6 pā#CiS/*ig3LkP|sYR?ȕl(8i߾O\rZlmsTPr׺gF~~cZZOxA>[|{5CҪ*Tx2ugKp, 5< d0dnNE$UC2]&o9?'zثug]*|g33q&=KvPsQKgż&ms7HD~ )#0#%oɸi\=N+΀ozƋ5R@hHF,ޑۂ4HsC Y Wi{(t@ c(<O7$JtzbN.=xF܎0A j]s=;2SC3P4)dZ3Qv b3%6q?+ZL9>ٿWf'a(·KA4=+QmZZ;qAҴw93#!3 pwjJWFVB3YJG>ese Y0'cn dWR\"|}B>[Ch:,4GP8B8L^u[/: u"21TQC4=8Q7vOIz{.Ѥseb!nu]sm-I:WNLz(= !I6JWkmm;N6ueZ=XF~Zw?h!ȼHpy;XNpA|PH{c >35$+~DI.hizE|~ka$Ze*\<+C응Kɩ[EwccUyx, !$M3l.e2Ø32D]:]VL[-#:-$85'( '"Eg] 1Cg&[}nQ$k5e)@ 6{¶BkA#dĎL+pvItɬ9YЫT]=TNyS NU'MqǬߺ]eNjxsG]e}gs0XQp\ݬ3TcM SG,4Y2]?hϠ7 @&Qx,se^L -B"hbU;s9= -?v{f$$!%25ADU)`O^F0U0/ 4(cW}yT̅MW]cCZ n d\x?ku n2xG 9N4Nʐ`[&sѲoR޼N%q2 e |2FbҪw?([4rQ .1vK.EZ)9]?~הSϢcvk)8D5%ݮęN fPй)Q *6r$6nF^* A$t31Yd7:˾H ~QNj E ^ YnKk&^gǦ=(_Dnt .iƈtg_0?渨uVjnDn]qm8mjvkJ­J⊌%Ku(ݼۄi{Y!0un= CAn[z <2|A4r֊z^fggZhEA=$߂EWU17hE`0%RE4Zyv^`BD qq NW}9@m" %Tw_1R$^`< U|Լb >p)#$L ;( 8pIktc*v,=0alAn)yɪf ;Z;;o!F6{hQii.m 4BhsX:~O Bj|n/k|62I&Uebq5Rv}x}_jc\ @3\@dhaFY^]h"5=-uR[r `;"ͮin9V&Ȓѷ$8ElJJt"z?:DOC3_Uȗrqƹ^8ld)6J[b 4Y4$do]ͦ QGun&:^OϥVX Fv>TkLWƵc| d^oz5&=̳CM:!@X^cL Na=sƟRp84ޝ|+ Dd%Ve`/e !Y9ʛ"+4f3IXmMCO)V2ЂᖾNHSN<6d# g΍;cp.@w7N J83h_x:a ʀ.2Ntϑo /ei.Q#2Uf5W X5hi0 )ҾbhG*蕭(Ei9. 暨AN%}M9. 9Ү=S91տi|NOozZTaq>eڱ0xdMewpLExv.RkЊقfMj'C] ) lY6?0 5Ȍ㚴aj0GC \pC깐\Q7ʶK!#G<7x]?!c~c? @PPh[+6w躓`{ُu!x:Ncblxb=(H).F[s+/Sh3jn325Yn؈nkj7Ϩt4kLCQ*l;-X3Xq@ Q(OuʆqIBN3'> dm3n%:zNqd8!U-D[o@p VCЪ0|g Eew̙s (( 9KkDdX󿓭wleǾ_GrPAnhI{4˰L! tgm9CuwoϿZ\dQ[mliڻC*˂@L_j3B,,iEӖJ-L^@>UMِs>z DL6ŀ匿`KpOK!ٮ;!Q=D4$ҍ%H etӊtWuu1H4PK PA +?\<%ӈTdȘ*hm?Bu̓ຍvU(>JZPun; QzT(` $>B|6FYᅐ23gٗ (R(U=%WU8mួi.Ɠ~ƄgMٕ\31]#~<*5-Ot/c[>z`!A&cOK_w}50FuS'[>%<|P v ]VOu<1CupkmMIQ+x\ 3&,`p-EOL%CY 3s~Ģc ; pv6faUER_)7[N~tjӳ@+s)y;ch^{ZzR\*խ8.c\/lX@MC\^H̢+Ϟ)~&jd̽nn-Z\%Hi8c`Ii$g}{؏vhlU#cbjWA 5ZV3SXƌ9Ӏ\J)|6|j|mš"'ig88ž 47 PX5IdBRf \RRڱ8g&3ޕVzS$.s8m6m Yism8LnEw0DThơfj#/<[/,CHȵ*~{s JUe:]P,Ѐ9-J0X3PGuge.hlM708{X4 ֝Z FkS"NEnVﺬH!@v"#uaŬ)EP*4~gMQf"ABaAlWuC2=d0^?~>}w/8;ǚv)8A)mIg8HC aP)S5޾{ob?<ط^V1HA'ޯ46ZD1C1 ;|zUkb}q?2WL~֩-<(v f6lL0cIKspLKSШ=hmJ`#'}?{Glg~_L[O@ }j41r-wy%\ww̙3gE+yv%;8Q@fC -;\8N+Sà8F9-OT(>\u{ `(+s'}ׅb7/vݳEgKl[KqPϥf-EӇ:Pd]Ev +x[#.? r# 78}_Ri-cedn_)o2z[[M)#8ٟ#e6/l: mU$SfwUjXĭHNT`(rbJAH*?NU,1 | A} B) KƬ弖|}~~ol(eb4$7&kة)B &N'Ϸ}ws:Oyx൦i0=xv'Q*Zm0,}%%D14|#RnO.?m6x4 jiuh\[~k]usi|!HSpNL> @-Q_~-\މ 'Qѷ9˨5e0 ]d,J)KHs OTf.C>}hYס1e=3~C޸6H t,^9Cߢb[+3Ɉ =u o$JI: t6iA_B\)<@ zT%Z6068'lߝݝ ZK0MXg$7=aPWcDԛC̉dujYE/5{  kMɌЍKnq㋍Uek;4ªԁ6;zՈ&/S1{'0 S% !pB͗ZƅG͙\-4) 'X!SV^'!ŀ y0(>vn1f؂e0P zp`t$_Fr:Y4n}һ g8{ϡ Tp HQ9kualT][,wtBt8Xϳ?eB?{+/xm0}՟Z^$-vA~IO>r7o3{Z~/5Xk6b' Iv=;Z앙wZx~=]UP_+~B0$%CaWo_ g_  d"ASo߂7ܿHx30d-0R(\F«j>҆.4f3}XY,"WR-$)lfvʛag-]sP% ǂ/Jtw׷Bm~'*ؕ3:xO;iA,Fݳ4FAuPd1n T >Ԋ&I G2VSz8WlSbZ4$~ 9mw{Th9jAphfYbvzzV/sƮ\_c\o K3;@8.-^HBOf4٥9QG`VQ0R*~*sk+t:&ީWqMN'cǹQkrs;7mTOk8N.6(4M!&vN+T y]GF\Dg*Oc1"̈Wzk~* &"y Ur֥ox:;I "d/ HmÞrk%_3RS-~?@8Y!x}*}!p&k#&)jQW㨀C#A⸽fv+Fd`̮3MKd>u6Dxʕrnu_`_>I8B_dBܥ] ߦiߋWgshG/G*H"<)ڟu.;5ziK:IJɛV,a O'1e],EOφ`dR9n@%d2A~RL x{Q Y\ }`$5~JkECɝvIی[O"Θ`yY˅^*{zL=yafwrkN8 )OHKNg\2 61AA!x[[lՔv`MW%cۛ3ssnvV߻{[2<}`OրU=HJ$W?Ϥ_(Pꄶoy~~7!a] )1NC‚JE+n["ƈhd1+ n~BrnGCu~KΝa k81  " pLl߬iSỽٙY\6(^T6\e1D 1&IH#jRNOǘҍSluXA/rz-Wrm*$V8X%rnP~5tvPV>31ٸX]t+fYrd1s-I Kʱ,> 4fI{I19@ggʼH?*!)v"6(o~"@a a`K 9Uya2B&=!Y,ZXE0"@ŔS&p&-ke]yRTZ[ټI~Lb)CVoO^>lvswۅĤDK7N'!ʋnJᇬp9'Sޮy]m=.ϓ߮${xl:J/URA7[ӈC79~K$B-Z}#g%zVڋ?=6LS{}oMYkJˈ O9Hӵq/ }6Z !P5 t +O疔0ћLHCKpk%h` &' i/`0P3 yX)|!=7bíΌqk (WNP'[:9Y#*1]{bsZ5\sK܋܃(FkjpKbH۫4ص'`A(ӯ(+)顣,d y̅MM1| ВR<6zKbd6}NDH!ԅG?$pɲeKI &Q XOB 81CN\}Mj^ƴ}ygYj y2L%T NᶮY&j^nAdiʐ.l&1DGʼn6;ĻO3idj3ۈ_*{2T9iX-m#ol.3U>7I$y?~9u80E9 $t3i4$c`gF vLyDZw?F5_J C۹4?oDdf'CI\ _H fw:ÒM~\zb 8<ڭzCp!( IIo9R yسq:3!Js9"EX!,VneilqOkM3S""\[hi~zz}bg8л6]"Aqu|,_: 2bUԜglLReV2nhH u"WCl.TazT:+v8 q^CUF[k#M9s LC^-$JI]#Hۇ{sQ}||ِ<ɡeVe UĤt6h;G2KBMb#v8ӔQe͋4PXH+Sm iQ( 1J][PBw='H4E~[̙fp.w$긄OKpi~PQ!H\=KQ0x1wme̷Anѧ`j|yJ!ɍdO ɥ!BVTul#?:0 B-DmbM>%( me:;}M8_έ?)~ER~ϹTA8 L41 _K4B0]S3d g [fu? Qӊ:vIu k3mOez)K6/}YD%Z Hc6xaq'=Ċ'ņ,h|^pmEaMkU;9@M|֬9hl6?/5ryi^ \sOAF~+c8bwT\*h4QAفV+dDoTU|4U'c\-5%A};hRfz<`US3r؈}vHu(iS X<Fo0M/84d:p$bk}w"#c¯$-p1*Lp$Qorr"W@g;}9Z2GH78X62m5tYYWx~y4L_ݾp|;gI*OP:(Sl 8 g/xFuMRMh :**EEp醎]GRMMZf+^7}7n.iy<೐sů$,5~_$ M!wilH**=cV_olEg̉A<j Y(vG:WWep0$D9$>w-Zgjdfu %ؔbOeF%ȡ##&*a )[ l?h:&,KoPZ9R$MoxAڲ0q:PHO2WȅdվL\?I=5 9(1چb4ʩ*DVIY AP7JDlr{<|b iH NPD(sT O% >.uoVNLݚ3`Ֆ\|bQy ( 7]n0t0J6Mb#dg@,_KK/p*'[@2J]r:[ ӝ9i3`6$Zp;{ ){psh6e|֕1D> Z2˅2Kb9^{LD0^AFdR)e0DK*) S ]FZBw0er˳'kjR4|&3{-O=ܺ?$ZLsLݨnrT\` lюE/2 Kn!~\Z<+]$=.[qzAó@DZ"@pnFbFvTssu6= Q0څ&w.5A+ȹw6!0<}gv a)ˆ.Ϗs?*Y!ͽgRiPǝ@h;,C%% @d 8~ڈ8߀L`r=X$&"xsR:(4f@I9D^*Qu &eȐbA "x .cVmMY/.g}U nmo6,,i0 r/aSFcZSXѸ+,ykDGGr9GdDe%k\w9R^Ը+M0 $ HHgH<k4׻3%, s Sp9V2,Fu`M91P]gYsDnߕ14SyHvo*kE)V(,RXNU$Fc 8Eq(+08u}{[= ΐb) 0(LJ- Jk'X;J{ Jib9y = є``!"M6rh@V9!ɶ-Pɡ?߄͢vПAK: g\l}w>>#,H?n@8np4 e)#}̢(\`Bt8Pn{J>E݄{'2!)6ruK0Ĥ6x%EiZvf! A3m=L~T==xH[璁oS(0=gpw$)=18J=Rݚ,ܷ8c)vA1[􂕋euvbrQb1su~"kɗb\1v` BJ)-!+ˑ!ĹS @$ DQ W,L W#X:aa 63w? ?8N%s ;0/UD H1`X&F]?O67 u;fz~؇"9}͎_uf8 CP|:P<u qȁ!!rČ]7Ua0 o2ژtf72r v|~OI9vXN<ˈ)iZքЈ:D=j/" u5TdkӍ:,9%؂4V:_E;o!>x q:tmﳷ*V 6f{t@D{MJ.N/N2[Q*^0dTW]dIx| \y_#ϥ`'D5Uu  ,1E# ǡQyi'gM _0LQ%nR69Œ^0YlyHgQ.J5췹y{UDxl8>N=Ҷ( awQ-3Y>C\ Ű)?K)lMs9y#X C*} u%8^DT Ad65Aek@")#C72,*GZT\HJ_h'a Ə}4Q Hwۭ=gʃHawfg޹_ 7/Ux9L8ԨP`)T"38ן,>W=jcci _.ɩ0`.J@i/'z鍙VP@..BR3\H ȔFR^]!ɪ{T]у~{=jz:uBy#L鲔э@@ TX]$wLa AhC.WOQVʝfOE#`*Ō1dzJD \Zˎ U ߣPEjKV/ӡz^߾U889ͺ$YU`X=LBhr#+s ԯ/u {W:Rn5X1Ѓ{s6a-nV^LVI Rւ$4S/NgoI6Ъ܆*/p܅ A/ G(oSLGdea?`pu tnTW\ݰъ)Tn:]J^|=6߄N<ܬf ^O%a 1!E {vIرf ` u(+Sd%tϿ͎ v" pJ}|R"lv"*Ԃ̙s}@>#"X{;H[U0Z{ -yCݨHVXL+<E < JBl}N#LAnYh ph/",)FJu%]$bfII16'[W{vKmtp'bXܐ@NgX# "9IbRڦ&/i@.׵(dMVoUTˡ'׫[[]V*eƍV;^4(=nHm/R4KS0SKe8_;+n]BDQRwN`Wj 8%T 1Va/b"FFZQRң ^9I%GInM]d}>5=cI)Sɮt&F TVy<u(B|%6_Yeӑu?TZݯӫH|T/OvvLH-L_Li4LP5yAk/eFGۆI.LDТ gkȤe|giejIϯ-L,w {hc@2  I+Jdt#sCAj٨m.Unr)e:JGg/da~\ͶI% Dql\cp * eZ[{%ˬ"aMgG] x7xGϧ~}.1O2v]Az=a (Dpzé8NMeHJ) irLc:3eC)+nk ͬDw~/55.(@Ch: P0Ŀɏ7~/ʃOHi=gB읹~͗h d|!odOyQ C3 7Nv%h sBd)O7] ѿJOAKr?6Jn3̨q% q3͙O2bG] eэqwY2HSZHfAJp\=|ꍅJ+q vRXTgnJk,w,006 (WCS9]9H |(}WO}^_{mmS.XܘQKj6]$լkEσT/ލ PmazMSOr)_#ݎ)/ q3ӳ7ފsщ Aw>2u7aoVWE$Ffxz>!&V"Yk,]r\ {.RAST& F`0gtk6+mp{ F"M1 gQU]bPaz=Ej!VOn'a m5 _+xEDӺle;3gΜS8pPaFi+2Sf" VVA]diLLffSoO_L"y.в4dR-zGxZzT8)E!Epş"jp$M#\ϙv)AnI:ʢm9LT4nI+X*Ѧ\,;#^`af豛n*܁^1=}҅ aJEǣAe/ fT3)Os747rQn|- @+zXb H& St; CApKPh`?œA&&J-ﵾY8B¾=## PoF `)C +Of 6N .ʠ[pkRueۃeo[,89-%\(o|"ycJ)g`y |J& QkA6kS8v1DAO EڻjK+;w\֊<%)lj߱|5VI\+ 5?c!!c<:I%iuX q8f, ^$$.Wtt_ +&|LP32DJ̵D"3?I,y˧-b/zK`ß z^T d7u^4rj "_''Xk! S6DSjNso֖[զ+1NzD7ZNJ2mffZԧ.DwGKKV4b!gK sEK*,\蚣ls/' QsSJXK7V^_P!>eJ],Wm"NCfB10_^0[0#ۏ!DmJi"`VcL,o]5:~Ұ9jTG%ߗ,\Ȯg۵^{HPM)qlBZagbnG 9nj>!<=^pp7?>Wԡ<Ҹؘy\&)`2.VL ӓ1^_aK`eC y-`7L{pf5 B6!*fI71=GD\}IL3WQݴ /8|;ܲ<7 [>~%E6IWUbj}:9, +eLIu|;Em& R&C ¦ծOE8BʬwNHX^1GKDIhzN}FcËА9w4kfTDXF# RC٨ye's;\m/ %uhD8H3Mh"CGz}~dH5E 5K{Q3IT i~EHc]"U #ĞU(di2%!:9T<"No;`l<2iZEC B5j IGir5Ӱ4 I]X2 d[7XL,Zak+Dl$hS+z6#9֒t@\+F 8n͞{Y'ߡ рٯ<]Nh)&pћFϞG1%)ug`e;; Amݴ^\oXW8s O fłѐ%DXrl  Y Ct5 Gx ji1r{Giy@ v^B,+AtT/r _78Uy;s%z4K^z !ОQ; ̖Js> *\/ w cрv.E&S2C L nln,UfW/=(3ۛvj(gYBr `i7w8H`<㯡 w\sF,<( HM:1 S6/dLtl hR*JRq6Wd=:қ<\Qj{h\H;S}>D< =y剃_5V (m<0 ӹ$AxvQ|E?CݛHe7GuU1H6e*b`l!yۄ45ͫUmNjnm.NU؆MTg E0KQaG&^hǓ7\8 QກSW\=>D@魗iJ:iFYtz3-)[ i{7T.P/eX.ڇJVvwvF#LgIDʾ51.YTLJpsw' <^F1xRI"<Bag\9Wb0hm!5xW#1-5Fi (>]{.A?FY`Tݻ:< :唎iD6s#pC-I(Dh\;+-"ϔe-`r݄yzOǃ:1ˑ QLK$ "!f3 e-D>w2d"$J}bj7Ʈx{E s(,%srl4QdC;R ?{io`2t J_-=Yq; y'Lor &.G8rZuI `w92Atħɽ+RbOo,U@ʹk7+m Pj,i4TGei( um@ЮB~$ذEU(8I['ͽu˺wk}H7)Etd( bxEwM[j0I%9(,(ңgVYT$5ނ3]YMGfB\@a6`7p1 OL>DF9jSOM-?L,lR(0a&L%d0C=[ vlܶQJ 7?loiS闻y&N凹yHᎃBa^zQ!wq_O-"IVaTMnNyZѣ572>|^6iMaLb):2˭D0#Qe\je&/jT aFA d2Lxonq h~fwDn`)` P=- }ժޒ&Rz"8qo֨H\al7;su e5,dUEF?%N/~ˣODFZ]=b=q }x@ÁCT术Rk==L3x\U x% u @"=h)tR]= *@n*$ AќHgg.N>M!>K)38Ȉ$Sad][IJ٪V*٬Cn=emƃouSkg9l?nvs~= ԙcFk}&a[;8ڶ rnJk1|}7t$U?c7i?5b2I &s\{6l<c+4*Bjo'+|!WDBS-tXb%C$ϟ4l$AgB <>CfZÝ=i¨vS6Xk(]EZm{W]gW!bPR+z2};MeqhHQQ}=\BO{a4!IZ~ fNcͩ#*%S/7 +FX‘md Ugjjl%ٜip ]`@=CDA(T#ƾ[k=MRSa_N}:ZbY N6]mˍf:eYAZ@ҾS!)z7&WQm̔&"IÛA⺧hyq_N'4[մNKvĪ2G +jސ,0uT(g ZO=(Kw?]eq+ϧOv~^PQ*RđU4ϽI(+ q\MBݳc}W*nsNF!Wn.TR,ktE!ݴ 6@ZJ^_;|Cj.cl8;CggwgM bJ8x5VNCI|jTh_Q08]VYCY\kD{]3`LbVtI ec}0{ؘ(w 3-ೊpH*g"zJ\丣ux6?A \xŸXh~C?]𛼖Qh+f%Vq5h۵F ]0H>T v2DABvD6Y.ٽ<2r{=ɤd@"5X$8G|ڕϽJdt#e8k2qӅm+Ra+8j77.yfO=SY@G`Y]{Sցà'msDpbX%4lM\F[_8 gkm$m1kI{OuQCVj33\SV%N Re(DN?ʯR.ofmYƜ9=Zybzo Cfh4 A%h,Wt<ŝFsefhRR{xi kNsќDA s^3^" LHH0؎svؙ T"'l͛BjCKhZTĭʪkGR2 .푼.h|A A `H+vk >w*ysUJ8ET-y4 :S4v! P^I셪?vtߣ Xq8KTY恹yL-yZ5B%&k?qk7C~0_#=1f%Joay gb,̄'N;s.Gb " 7 |AJ?'HTwV lR|1oKOG\O|ť0>v,% 8GGU#2 jE`ܲ1n/n|.ǁȟ/tHj\p?lG)[]F~;/Ȩ-HZԗѩhjPJt8b"K{KB4~d [3 6n[_gԫ@`폟O:ݦ N~6Xy+^n Eرob8R,"י{9t<0GC ΦT YQky^A?qIWk5?Q/Zg R<> I+%r\Ǧ+FXĠ H>ʑj LR󠏂CŋRtcAne?0$#jsVHg1Ӱ8 .n==f~5P6Z>Զ"jt$G!#Gy!Yn.ө~FOhl/?&_GlVfI1ijiIx&e~]&P8nط1QN~ هK}cٷ[[,:ϣ_*"ڂ r`Dtn~=ƌHPPF6Bz[/H"W>Zg?FdeBxtar¡۷3ϯ|չ}.S#:dM![BR:MZ}F vS鉆`K%CG-@.Ax8-jR)X YBuut@H2 ~vBYuC>Dxa.?oOOma(ns6(Ҋ>  E(UM1)'Il*T %'lfwgg?_Z͏ 4R9UQB 0R "SqhPW!k3Kr>NȊl<;2Ju!c D 5@,B*3Qbeh &BLaG#{a[>)eQwϹhWU v^RzBНnꐣ"]+$s70kpWʎi< Gr_̮22:v)BMb|͆M?҃度PuMR%|0>ńj8wӶ'nh r.5ixV\\V/L~]<7P /S<յȶSsD!_A!ɱulU\) zyMFm*zQ,9I~YfqP PمDql†4)s]==i:V*r|:R@ނIBt$7Q3:/[s`xnп@B`Wġ~6 um'?~RŅ+9!ZhBiRn} N)ݝݙ+g3h!hfTacdA02.i>&ADyYϩV3iNVK'4nb,Bwǫ8NO!$IS|5>e!65v.^}DvLV6wrT[7-}ZGce>2k-)09\%eQڦJwS`e ش}dqHϼ,Ϭ!%n5C!_GYk )lj4$lD;ΧĜۦAXOe*='tK5RX$BE 0aȜ4dWDWjM36mo+Y,<]kIЂV#(ߣ 7Xs6fzl,D2`b pj+B QO]R@y_wlvAc3f%u"@$/3Fz8&8BȋhQ48XbRz])2JA:ʚ )vCG< 2R'4r:÷;v9K:IܡaauH(M`@o7Ff]4qFC&#Ff_(|(v1`./KMomb 'f(nl&2{2tkn,h$ ⭈TE޷~WH%HH),M0Lk#,tCh)$E?KblocuJ 13qBC/?dJ~ ls·v)$IlV" Mā~p&cH$1K/Kd~cx31WĈ }wpШ'%?+RjCYr\VyQJEe_7"Ud2k=vws;1yF*r-r6&R7]3.獤|@N-Q8nsoh+DUA,A$?DK ۿn0$HB5fyKGG 6Pn6Սa vc0uhm"?7^ Y;oAJ:I>k'cg0 $$!TAEmvoꡧr^gwE x~3!S:uЬ]魈}sb{u)(hD (i+3BX&)}d.0!8~hVO ,_rhڮ3Krpa۶dP~ NEJWYY?B倓3wd{ڕ0Ha.b( B<ɪ `1Ob1 ~DfA!WTEu^P^qkYJ7-mDr@?3d%לsΰ5 my\$.2aa.eUKe?"Dg~^~>^#`1g<2~/pgs&3KO(^3a(C:[D'L vBص&fY.?GAIl@&|bͦfj4CUgAB zfwIRT= {^n`-QWN$EM$k~_-JL31zge2 */HK{E y;;5Q2ԑV-t%0>RiDH}orҋI6zxudd *%Wab@QLVH9b^ ?A蔭7W#UF7wN0XP ൘uT-󡁽ާ~Kr_$( 0"']0 8ς(pw.NHP&5ͬPCi45;cg^0~6AϽd+kb>æ6?ezu%{'ޫnsmP#HKNN>.j{6: bΙQfR% D ydo~n+5}7;qe1b‹3ΐED}LI/D4YŊ8[윟֥zҐ'T?IeTx]v>2.nH1PXī>zJnFH5IK*6۝֍!u{!=zB=ιv&* rVWAngcxOp8 S..luŝ_RPu(bp!D3J}ŭ||YB+4wC6@tN؀`>*2|rVؕnc[cF q$bKo8,JJupByjEJ"2G21_k [#<m޾Lv :cG'!YHoC1 H"'vwuuu6!^_K ڰ1Vjb'2r&(}bldԲMeEj4IiN,_d˅.@>+KJ{ e2d ;QWMCHϭ>V˩*osAb6Ʊ`(eg׺Zp P 2tnkov1A<:5/,yr c,#jNHD ,{a6 4[jWQ0J>5Y|F?Xvjw~e ~ƿۢjL#)a 06K7TWbthqM#ZA1V&jtNt9:͢h| eCj'̬Vņ &yjc:s,P°!jLOu$I3OUϷ|N08)D8WUaBR5RɎgv/)wO:lwn㫰j1ߟ$YY]},*1c %R~@cQDeW)/DbY$=l6kfJ&ȍQ؁Ë  _&]fR39"c:"uD'zu+R 6 MJP ,|o2rSу3X{QӋ}^oyARcG ^<V`0ܗ9}D8g&JppM&WC*\XGQ& ̩6+i2b埀 N^ OZ,tg|valFǠy}HF$5ac5?puU monT'].Ɂ:e{v(m Fvq VZB9yDw7G陸y|.Q̍Z$R @ @uÁTU%Ae6U:dfBi͏'>vFx1w ^_)>M?k&,3M!Z_a f;I_Kp I8q찒\ mzWJa?b,76uYޏ9Ji rZ >ORi4$;@$C3mo/tg 9yV v$OJVLTU*E>_\ hx+a)JvK`es߅7`ݗԜJ~>٣K5GxY -_g@ ᶻ* wFC@_o@҅t:眙p _ eޗvTnm*prr XI}9Z5VvV]Q2JH@~іڢRCY]K%FcQ8J2ʖѬxP7TjPCX]LBq8:YhүD#ڍ`qiVZL&AQ_5 .;0IA$s#¹R&pY$ϓT[uHG#zөiF+kI -r鮌0f ;YnݶJ{ i4JO% @+Q;ž1X(ރ 0':?Ba|1l6i7a7,UpDjQ >N ;d+Ȯ3$$ZXPU,\M:--CVWuZTӦT_Zǵ巖J־NEJVނcEcQʪAmBϙ__B.}˟r&Ǹ!}\n%s޴M^[]w~iixw % qF 9mM0ދۙM]<9C<4 ]Pcn%nιc3衪6b힉}:  ,J=ԓ xToٸ_O*ٝLŹm{Zӏe2b~s,m)F ˇ\!d*^"*7P]9rξB!DW&<'T]gDh*Ҏ~Fi68l>[t^6z80ԳrmrՅ Re Sڌa%G#fS0Dي4’) 샼o7qv%|ilKuJE+c13 LCoӂ^01 ([p"6G !wf~xlq0v8o6G'8?JsU8_=efԵo}Zu: A;G !Q"|6 EQHc8;3{hҥq,ٙsM0{y$qz6PE$`>:A(s+X2%rR3䣽@*3<{D'u,Wd=( AqђtSL繀 CH-,$p91J.NqfgULY2p5ףqh` uDZ \. F 4zzƌM\PWYɴDbH>Dg˜f1%ĺ88~\ΦQfv)AntKǧk΂)wrwl c3&2hV_E AETL՚Y"3-ml;);we~ߕlomi<{>?r ] 69 * D- !2kf.$Q3;;[XHx3g3{)W{gsiVdG<) ܶm?K-D]˪2 ԧt 3!' .|WKs5[t_O &,01:5Vw֫2=AI.Wsj*;-JK.\]t1g:l֒Di(S1@[3XNMKMcts\f;d2lZ9Zd3$Ʈр2d,Q)InMWar<ޑS嶢: 0|`{V_E-JhtEzTob%D&0:6$40z} <`,\KU>͈,%8@dV@Ud h[(8Hp]x h (Aカ*ކg~#*t{4FTDϏOQ5]%־HuwZJU-Ƈ"|9|+vO}z[?}Ǔh4n4]]ܛAѯt]MO@ 5Q&<rC1(h)mY֝yD5}o͛y"Ln>7_b 2j=,r'HH1סIOW~l6AE ~!X͸/)rމ"̏ 57)Vy JN8\0(ᐁӈrZ@TaPF 1kjG1bI(  Qd<`:N\h"ehЈ%<F-Xfv؉UPB t!rm$i׊YyÃXF``wM7A9J C)0[Pqp{EsldϪ9mL| o -<+FXy &]m( 0FBciS c2)*J% tre0RI@ jyEoMj9zZ4L$pρ  cV.qV/~ !js#dMX\K,ŪjC+"Aajmeq+qT7L1pyq4z_J2DN|vA{!Q@XvU.*G޹{@vaB*Lp8ѣ΂^L8iTo0VzVUv6?d3.IdU,\y(k;K7-N#Kr37ݺo~ ֵF CQۉ3 :E̦(߁Ğ{$v\٦=QBI_Ttm4rhC"gW'q {G}HSD=ˏ0Ƈ*At}4w*=n3/?WWۦ_EGJ&Gr[^JS)μ,|Ʃy(Ax]Z'/.V:٧?' <~_v妡 zUkK0c삉'E&_'dW 4in&H6YĞ)R؅G?{sz3oO 3ӢrS#}7}}4dv֕#2n+;8 M_}i{Fo"`iJbFMrnCMuh3=q{{P99euSŖ4L,.tL<.rHL {5$x,W$dơCtj+墔g$8ݫ8 z_^cFE9>~:bp HFu Qx^\'jrNa&p`;3K\`RG+%-~#jF2adMgR۱@;Pv 1a4 0yXjCE\ez:0C:xqd$IT4" Lۦp޽N6<ܳ:vtvmFo_Տz9/2>)Zjc5By}{Um'ah764%&Hg ^zo?~% ͒$E?J?غݨ 83~_EaD9Q>/s$8!EBD9$^{LU{8^eoTWWw @ x;3޵_5u2qa_tb[D!=$6?D^| +N ֟jqۦj#7ļh&yn4ǖVrS"yϘE"33 >O[*DPF"/&ѣgB]c}L5\GȄϟfc@ 3сVY6WYRv[-SVX;,+ W27T^2p_A\a)8="$4}pg[8%WqNӘ77>!2sAv#5PJ8 qnB(ʪ6QgFSDw!䙊0KBY;?4 CVNRQ$@श9UiŐt %+P?_Ӡ_,6\_D!dk;kAz׍髃>)evY/ۥ/9 P-c7HZـՀ(IG%i xdɒlMgaǂpl)RepR )ei{ ˚~/eϋ-vNt>(mx1?A"K~;wi;6nL4)C0 }?4Õ(A Aő'PCe<r/ c-(lL@v N MPaUb[i+L'5ƀ ^[\? 6 .I?P&*hRbyj!pz/`*ԍ^@N~~>5㓲K砉j43U5 GAV" g#/tloޙ<2S6/Y,}s߅op*~x 'U޶*5rAf).b?uQAtׇ'GhEB @D"-M$H)sGַ ޝ}3o|^E m%/.Vc9aTW$`fVh=HujcQfjxjs/X"Qa!X 4Q-ps`VɁ5@}4AUg sU@i .' 0XA#$ 9S7W -vr/~sY)ϯQS4S"ؓZ Pڵ>RwU}Hvm/~m/FNH[ N&Tz͹; e\(N^NY02"8ExXܡMw29TU:n"ĵ $q]}lVvjRBn 4{mIwZ.Cwޥ 2XX˒ưh<~9e3=yoNOjv:d!@6 Y٦q *TU=TB{OkP%Z9PD㶉i{kErݝyocAuL ]+ZfNruQwϓ'=*h/Ve gN4^&ӹEXLfHk]xE2qq ҆%L״%1Q'_B1w h:!q+ri9V|Q9_Q0E2/G0RƲ@>jahғX֥)<0D,RVmVB8 !Y7}?޳]!-*xMhUsg":!4 9gT_#Ң8hZ&d\lH'ߤ![Z{NDЖ[cr1˕9&91v@(!ZOOu"G_%1=9k(F>uQ{Pvr)\ %Γ`mL6Md:)V}Aw_'_ A嬩]0yaX.fQw^]w{#`+|:/͡ANL/p3Y{3o>2F .6),7XJHB(DQQÒٝw; v.s='c~:j'1ߜ:6xi/}zd>(=-Rd"/2_;6|:f{DCI0〘B:̩B iGYȑHCQJ8?Ϥ~̲! *|VU6 #Xjo3Q(aLr:"ۀ/'t\S1 "K]LoI{Vr$uE MKpzr`C).zvt&dvt6ڗm +~0pwHG(k#)%Mltp x_w# ، ;۪̀8iǃeJ$G߼ ' ^;]!t* l@*"щ>R9LXW7S"5J}\kvI] ʜπq`F$e7uc2 eKHG~PPA:ͨǀ~9pft̀f%+uQUK#;cldOCޤ6kׇu a;;v!?}ZP|:.<.O|7>9ژQi߼?j?%+xtNPo@AZ>+E7>;]֘h #Ar3`+ ܟsg|{) ^,~Zs|ѵ۾=;:ﱽ`R}{8pޢSFV_6K/75W p:N[ӲGEw~6qpHj݆(F^[]oMyR[Nm8Zg7,~($lN_$ :jA&Ci.r5`7҃{lV@*7XeeRcQC [=t-'X27a/dZӠUѢŕR\An9xr }{lRWH{)PE 4~LP.g` Xgwa|)_tHνDzB+L(WMKy,>Y3.UwP}?%8aYYt^6bEgi0\[-@Τ Wu,̮~^E8t}lԌR/%Nd˹='_ryDZSlӊ8݈eYFu24 - 5)O)µ@o_TvoRzl75y4JF-28#2rbSsh$p,ZJpcP\(hVdyN! ]'59+cݰ!3$J1 `ߜNgdߒ!=-[?o;ȆRdDeqg(2/q ^:#U=2=+a~߽ri+IuuMQpws[h(,PMR#((EFݻcfZIY,{oL2 }VN 6'mCn}p? p}ێK@vvb$#W8\~)k1+. Xs 5cUja9.$~9JG>n"EZ8NfSh0&攍lj0|؎N3D"17]Ll2L"6؀^lgsAX?yƩg R*)焬_s2:b:F+fr/"33itBfo&LC \7G(!<}}]{ko͛ۿޟsoo˥O`ZO\җʝDW7}YQKouO}^LT{pߌ)Ep)aז0 MhBH r$j*&mf UJg׻3:>0:S'IC)"1Qb!h @^bЖ̦ylcF>f lҨ+ɝI ( ]CB#Wƒ'$AL+6qgIZ992VV]߬M}VG2Aή8KdžP|A3&"QW5$1ɬ gǒnV&˅OZՇioN؏%7-%۹a<. %F>L4U&7wZWYԹfc],w ҰKиh#LCI*n[ rdf9Uىty&/\|;:7h x$ѥ-/̩,=4wΔywfb&SSW(3ZY v _^Kt~ٓIEM^»C&R2UlDФ1E?|b@}cjlZ[۽:{w$A|܅ˊIWp8" e]OeKV=ңLDIS{#4]d[EXC=Ϣ& wgRD{dSec` `. М1Sce{ȱ rzog eYyWQ ,(!:~?8S|iZkI; 84Wٹe(C9gr0Wpcdp O/|>ݦyYڷ .+bc/$]7*F3bO#)A>(M'l3OdG#kg D-bDc|CFMcc; 1Mbp% ;3;s_ @MM4|5 #'8s3M ߶9 6À!P$e2 }}0 ͒G=S.LJH"˥Z\RX '(zr֯claûouwJ0HC-H]+B-D߈ψZ՜:k4M8!=޿`j!׆_չ̏Z:C'A}TR ^5 ְ2}b񣿆Ÿ<{.]'eE\I L9,dZ'ڎ D4 %]beb`pnoD'R#ת#t\dP--6ΪMnVk4U'JLgi/< M6F;[$+Ovp=d_2(Isj%E42 ]n`3SVYٜFAh.0ɭgf%"w,Ff;b*@ G@֔aJ"d8cOICǼ6N\A˸V2jY\|Iwi񶸌7j,yK|R' ֛8֡xD8>9}? woY{[i iZćE  4fqs"[h ^| : =8j[^eK2S_F 8/9rД_7X<1S n7k!q%ZtEN܄40g'jSV~gYAgR ʐmoWrԠ%eLd͝^J\&'%7hD@p7tʮKn ]4 , ~tk)B4lٹԚ+[k/M=B82#6[筒M;}6Ɠ53x';AI4rpQżVms\h^Aσ+|\+<ΩDXr~}aᗲc7}ȧ,[E6zݟrS9[3 զ4 MckG C0AD4m^̾&O!m)ikvׂO1_^',.L'82P< 8Ȉ`cWu>=q'3uj hA_GKРYiD=0(nTpL(,%n nΨ I*-5I* Z bIspBtA:-0*H^R*עޢ7Μy*ITNXQSA+ol:Ͷւ\ 'K,R{ⴀr~W83 znx$Z:Eqԙ-?]`/a@m <@[ QWؽzyo|fP@[~`4^BA?& |sZ6{#eWך07BWO}E,=Iewnwgہ^ Lo @0sHt>$;vlt|a4^EZqHW@yiiŏW(Z#$.a(:֬32G;u!3A!D6a$G dTk;`HQWsitU{3ҍa}[W,adPlv uRkW9)k~ظqT.Ӥ 0 HهfeΘZ#n[1U7r/J9H`Y=K܎$\"a{b VgTan+:=?m<Իx # ?lMi_@g=NAW^9ugɶvjC {;S@ٵ4 AAR%G|P I`gƕ RQgڑkzֻ3aaG_;^'#Пr OњB0\x&"@̀ w![WfV<1z6QjxG9j(VOc_߶66p('G{n~?Wnҵ.>l yb(| B -X@B SrE~߻Moߖf\_A V*W ~,"NՅQ,FMdZKuCP)N8T.YPuklRNizFW᩻c \86!:G5;j_(Nz\FJMӋke@RSv.Ivs+я6r`E<$X# Jđ]u'6>KT@šZO%BiRSp *93+ZWP9hʞtfova\jniқ=Wї2_ǢB NFyܻpou_?b̝MjAaLa 'w "I}*&n+Q{ܻ٭?xr?F]KhVbN ¬}q!.tŠmjo/Î^Me(t$i`e)$";\Z.v[dI@MoVS.Y_7lC̪.pJ|@l9OE 7ʪZxO% >RmE44UFA:8}6fl|klRU\u[ GzIPňhL,y UoFRJ˝^:'M1^fXl>t:w %gYY9~:竡n##kg0DM*O{cHP'1Mwf!`ز!?3;;̙~.Cӆ;s_N\7 ¥t$A/]sC  IZVT.5$wf Ni3Q{ ;I3>>pՓ|"vawUG&@ (X=/}~xhTDa7 G='2 5DAN {sQ9/wlI4ȃ7y-M6]$O{77yonc_kyq0w6; 1lRJx!ޜ7)P!m(Mx.P)T!IxK ?%h`,ىY&`ofXű.~ȯr@Qr C(}l%E$ĻνP`(00!O-~͍m^AX, ΥД2]6b著0+fm{z F3*K}r0.{np)<8Qԩ;!Wۍj|u8&96SATu>D6aK;N^}a+R(+/!BѲPе/`#$/~² 7& <qO{>?`r l%Jz½ UUB~Fj$B<z3z})x~]{5,Pk[ -D5)4:$##qw%z1]nb3ǃʮOu 9D؛ F' n i|VRi{5OޑDŽnrx&h% hL1ndo!Up$)D^ vm@0 08hq! u 7r=U C *@Piې\Q= t hF_DR ds~9~[;RyT, G4=b f1V2vm&,J}]Zbj,̔Q`ښv?jw/}!o;PJz(x&f]`NʜGwC(7aE@ _p$vH7[K|_F3ݙxU@pDs D\Fa"q}Bנ  Iԁ@Z>$QXYYNJnWI =_?B'6.Up[XGonB@|7'9fG[*}(B4|l )(C(8}lˋh#Yk;:\ Gtl ln<) &z6Rj 9%ǭDNlar92žߓ~sDz|t*@ I2@[NE~gH?>ߪgy*&%wg aJD4,E#AZlk|4!<&Owgg~3z5:`@ 療_߶;z@oo vdJ4Dd%' jDXr [ lK1.e8krgꋈJ$ޜ2qau-K_ #i>%(Q \`S|t(w#,e1B$voPч?=%nMQ;{' ߢ|v~uWe3zBZߪ oІ_G$A `Ѕq)MܺpcL8 m_h a!M:Dկ_}4px:Q`=rK_31 6@&3y=75d3B&KI4v t1YpbkGҏ-㑯N8-OuX4Y]X܏Oc` y`{W(><(h @Y_J;x@޹ @4jĒ q3p*mqš5dկH=q_uu|riF=qnÐ\\ ۏ B38)x.Trs/x㳽sB#1aHMiHXI}0g/rhYҏEz#A!!IBZxS6V*£N! q O(@ bR\"1Ow[ ًi*oBEyר_EE~ً5r]L qrqx$0|Zˇdz_~o;{ J4vxXx |,=( _'r|#B>W'GUP-!eħB  tZ2A9 AgUp .0x_ (dIǚgq+}(7O3.>֞RP3zCPfw-yg aƵ+m< `&8ߴ1@ }v:݋([urPEy#mvPhYƮ 9}@W#)@fwh}DnPA!M?~P(;k?—^&&A*і̸B zG Q k|/Q4 C4=ȸgYyM [c?] hPsM=? ݌83KS͔uys) |ƾ ފQrZSYu+<ǮbG AvFo&?G#n+ 4!P$t;۶gߟ/ dY8ԠBB@Rd 0QO ` LA >H`5S=p9~weJ{|zn 1aFY2ahfy`MOQq~2=޵c Gᥗ4ƾ ŃVJ|0%=ֿ‰l6iۖ "0ߞYll/p\q+ ZA 6(fYЎәz7d, aƿ߃Cu&8 d:£فPQj{~Jrl YMLR3{oTȪ2So:',TC84$@K.T;jRqLץXuIykJ-Y ޡet,g~#ˏc+akːt~MW2` ^[  8eHҍu5l^RJ1^H0c8 '0cfJVK C'DǐA0+6 MJF:3Z#U-x,AM:rw(=fxRwrIKS” wy'4?Lg{ˏ5k?nżvЮbػa}h]ڇnAZKbxѰ? 4qRYE fe@8>N2t@R S!B1|I$K;~\ ~Etc,M/xDQf#ykJzG^Թs{] ){ז ['-z|5HF0*#fvV@}AKga#f<'ZXR'1v@>v@п, ]dL_^ܜvUt ]T?ƥe` h& O'uv?L#[%oMހ_]I LUfzٹIp9;dW)3fsΙM99w_}f6>^7&1ٔ58w(fADS݈9 $ ^KPJi]м~Hlh&4ZPP@fpG.XYz3FX!?JGu+ApXGcHdb30+Ow8a\ @jsR F l2_ dg8rĀV .t,Ɔ# hI=t*j_?~39%Ć!w/裙 F lMntql!E?'7uj~8dW``]̍Z&gfx- Oc@l0!12H`ՠ Faښ}4h08x FPŖt4Z n/~;JLOhF F 2G3ĈRlQ0r@1V2 F( F Q0 F0` h`-F( F Q0 F0` h`-F( F Q0 F0` h`-F( F Q0 F0` h`-F( F Q0 F0` h`-F( IENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/boxcorner.png0000644000175000017500000001563211357170241023560 0ustar keeskeesPNG  IHDR@@iq :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:oIDATxb?H4h@#>h@ Z܀UR/f)@ r#@1RzZHeq AVPP`URR%$$(//O@@߿ ~bz ۽{Xn޼p,b tsj @+1@<^cgpssohh}@wƏ?2{СC'Od޻w/Ç`FRH@zD&XFFCff&.L )_@RXnzÇ,'Nݿ?fx 9@u(r<E R ~\\0%|_= 74 *5C%X XyΝ;9g={ (̿ę@?#Dv=`:LPdkH<yP GP5 O#(UqCO.7ydwJ c 9 ^ Ub3444QƒȂ7 ؾ W pB@ avd`AɉdO/I @z~;'ND((Ukrh a??{ Fw_yyy3''[$MF I H  *c6mC^^L NG4ߡg H (@Uq%TwP*ի).AAHN,?58$APJ/D VX(@!~נ◐ tk j`'Dz3Գ ,T/ ~>?/㯾.^^އHN^ t=1~ 4d с[<`P2~(r ?zAYT?(0@*233{ׯ_|?PC <3ng'?"&` <#3(| ]P,f@dHf zߡj?B`[-㟀@۷oY(0[GuH /  Ag e YI&!{+Al@ y`1 P,~b@-,KTVVm>/_-oB" @>?"=5aU"K@ ǿ~EPF0,P@񛍍#0; _@ g@z uuu<,3@r78S A#R@!<($$$c߿_e7y@0=*V@R@+ͅ2 >VJvXyTj4X (إ~l_`*^SL9T@XRW޾}4 V(yϠ$(HuRNCDd0iK _fV+%@ra3 pł0x{AcҠDV [AP5*:X=o|a f?`6fN|Pn+@CY N0@A*};P>((;A@oʚБ"Po 4O`9FH+Ɉ ObV7(@YT σ< +i @ ؠ J1`C鏚k!!!h8b @8E---Ay yPl<J >(σ< 8( 0 CPA*Us416;AY?abv` 0@ Z{:(X2 9#~1 BzP uqpqq}ĭ p,IP>.A-[Ȓ V-Úlׯ)+>+ yԎU aPzg{϶B 8eL? \q + e%-,y6j3 GBqka`  PT0A- ?dOXu@ `LY ?Aa\1N-TK)x™H`T[{P:+LLq) lCB4FJȣ)m|ROQvf+N@@<L D  `a@ 4&P #**'p+߿3hȖex\2a! ! 2@plx py'0]r4i 8?u-a@ σfx%m`9ƃU`zٳge~2ء 2dZ}~)))`RlfL:7oٲe?>@nORaM444}&c.l"@/z'00XoݺSиl` @c2 8Y^SSNa`V mf@AQjAgΜ18q0EVf 8prr-,,KG#M,J*P`GSPPPƍ!?FFlf* V&L O~6 z//5kihhg9r7fbeZ0Եk`Bp@ZIu@Xo>}Gv` 0:a@5j666Q-"0b@n σ(y$V`q@8dҪ* ]LMM=cA{e @=jX@7 S‘#G I2 - \&"""U[` L\ v2 БfT\ J|AU |||De0 %3C%]wsf6܁1/qAEXՁ `h#D5X&(H|!P2`&&&R[ @wg>@\#?mpss??MGfdЬ ۠M P%CCC^y.^MʒDp,(nd&}`򋟟2h:ԱT0 A#G#K $xPUuP>JWSS } <dSQk A|`6P@gu<\@bP?h=P>;Hyl&(̐# , *CBBdUŔP4 1~ AI=`8 4 ``^#,cyP uP^b@`^E58v Vh~ a < w5?R hغ!ب-8"o PaM,,,e޼y~9.oZ[C܅T A񧨨y`U۷?Ae(P{%کl L<.-=>?ABCBDHIJOSZ\`dmtª©{pj`\ROIHDB@?=;89898:;<;<:;:7534568;?@CFHLNQZalv¥unb]TPID?;:97454320./01343659;<@BEIKU[fmy{nh]VOIB?:8765421/,+)(*+-/1024698:?CDMT]eq{š}sjd[SJE?;87621/.+*)(&$&()+,.0./1347:>@GKU]ktulc]SKB=75230.+*)'&$"!!#$&')*+-.1479@BLVckxzqj`WLE>731-,+('&#"  "$%'*)+*-0249?HQ]dpwxrjcZQFA83,*('&'$#!!"$&'&(*-27?HS]irz~yrld\TLC;5/)(&#! !"!#$&(-08?LXciw|}xrkc\UNF=6/,(#!  !$'*09CP\bnv~{yxple^VPGB70*&" !$+2?HSZfmwz~utpid\VNIA;3-$"      '/9BNT^eosyomjb]TPHB<7/)"  $*4=IOW`hnqjgc\VNJA<61,&   "&/8BIS[bhkda\UPHC=84.'"  #,4;CLT]bf\XSMGB=53/)"  '.6:3/,(%!  $(-2:@GNRHC?94/*&$    #).5;BILDA;50+)%"  !%+16>EIA<70+&"   &,3;@F=93-)$!  #+08@D;6/*%   &-5;B82-'#  #*2:?4/)#  '17;1,&  %,4:,(!  !*28)$  (/4%   $*1!   &,  "(  &  "               !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/dlight.pcx0000644000175000017500000001041711357170241023034 0ustar keeskees ??,,@            !"#$#"!   !"$%&'(*('&%$"!  !#$'*+,./020/.,+*'$#!   #%'*-/23567876532/-*'%#   !$'*-0368;<=>?@?>=<;8630-*'$!  "%*,0479=?ABEFGFEBA?=9740,*%"   #&*.36;>@DFHKMOPOMKHFD@>;63.*&#    #'+/48=@EGKNQRTVWXWVTRQNKGE@=84/+'#   #'+059?BGKORVXZ\]_]\ZXVROKGB?950+'#  "&+05;@EJNRVY\`bcfgfcb`\YVRNJE@;50+&"  !%*/5;@EKPTY\`cgklnonlkgc`\YTPKE@;5/*%!   $*.49@EKPVZ_cglotvwxwvtolgc_ZVPKE@94.*$   #',38?EKPV[afkotx|ā|xtokfa[VPKE?83,'#  !%*06=BJPV[agmsw}‹}wsmga[VPJB=60*%!  #'-4;@GNTZagmty•ytmgaZTNG@;4-'#  !$*07>EKRY_fmtyŸytmf_YRKE>70*$!  "'-39@GOV\cksy©yskc\VOG@93-'"  $*/6=DKRY`gow²wog`YRKD=6/*$   %+28?FNV\clt}»}tlc\VNF?82+%   !&,3;AHQX`goxxog`XQHA;3,&!  "'.5FOV]fnwwnf]VOF>70*$  $*08?GPW_goxĺxog_WPG?80*$ $*28@GPX_goxƻxog_XPG@82*$ $*28@GPX_goxƻxog_XPG@82*$ $*08?GPW_goxĺxog_WPG?80*$  $*07>FOV]fnwwnf]VOF>70*$  #(/6=EMT\clvĻvlc\TME=6/(#  "'.5EKRY_fmtyŸytmf_YRKE>70*$!  #'-4;@GNTZagmty•ytmgaZTNG@;4-'#  !%*06=BJPV[agmsw}‹}wsmga[VPJB=60*%!  #',38?EKPV[afkotx|ā|xtokfa[VPKE?83,'#   $*.49@EKPVZ_cglotvwxwvtolgc_ZVPKE@94.*$   !%*/5;@EKPTY\`cgklnonlkgc`\YTPKE@;5/*%!  "&+05;@EJNRVY\`bcfgfcb`\YVRNJE@;50+&"  #'+059?BGKORVXZ\]_]\ZXVROKGB?950+'#   #'+/48=@EGKNQRTVWXWVTRQNKGE@=84/+'#    #&*.36;>@DFHKMOPOMKHFD@>;63.*&#   "%*,0479=?ABEFGFEBA?=9740,*%"  !$'*-0368;<=>?@?>=<;8630-*'$!   #%'*-/23567876532/-*'%#   !#$'*+,./020/.,+*'$#!  !"$%&'(*('&%$"!   !"#$#"!               !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/loading2.png0000644000175000017500000001410211357170241023245 0ustar keeskeesPNG  IHDR\rf pHYs  wiCCPPhotoshop ICC profilex}AHSq?oZF̌"?X''OMLYkjHm{\%" Pnevԡ 22+*E X^JanhNNͲLLֵcuoG=K;Vw4:YɎx,#/'_;vu?^ݲ]ttP|@yrA >{8e8xۣc㠘/Uˀ/^[/\PUOk P>- Gπgo;P@D\0eEظ(OJ+}Ηғ[_P3oãki[k WRw1 /vE`j~n|{Pؼ5_i֕\`κh+ں:_j,S`.cMYEh)l#vaKGyh%cN['@b%dOoI'~0,iu~np)I֌ x>,yV-7+;޲~N;-r1(33%3`gq" I L]7& 88M`+uEWoWIC_[#ĮU\ҷ59٨ő8LacGb wm,+VjO,{_\z'KQS: BgAMAaLA cHRMmsdpt>1qun5IDATxy՝? ݨH*AQQqTe&nQOFh4KD518QLDDb$7AQPdhwo{sN8poZ]~K:IK=!$B B !$B B !$B B !$B B !$B B !$B B !$B B !$B B !$B(#v݁n@X x]8-G:N@_`7 {Sˀ7br`^@K%08 #s0x= N`60|'~vq}0p0w^sRP-p;}ߒMJϻ\`^@|1A^u5zRf+`$7 hSk<@4B`0 | (%:ypl0 `Fa澠Cp- 1sW?W1Cl>'H~gp2p<#;4.RJhSOs_Pt`(W,+g,-pGafqY=G! ͷM׺/5cK(en\Ki7qp(:¹nU3K;h māw '>R1J p6+~m}G例p{Gj3==ƣN57E/MCq>3L ,|1*(\Olg L?K_#8yUֿR1v:aۇЅ(zPl(/q6pj=ƼKf'>.l;`k%3KThc6Ø>k 1TgqX"1݆i-)Ju:fgAv-p4yfb..B.. ⷊx|#F$,w'OO?Ի Kx*Gf頖0 (l EpunTXX #H/pXQ<~W,H{ @(bc{T_J-3BXtq[JaYez?92GVadB3̮t_~u0HخFAxJl*0˼#w/zL8p*:fyW{aJ+ᩤT?4by CC!H(~w`I&Dy 7B0 b*H ˀ/=L܃EpK^g,\+ @x [ɕv%ŗO1d #Qc9]sKJXvL% ͔Y |'JYGsI *5Nٯ7g#(/X,ND#0sTR Azb9n/^\E#i/'B7q%+Qaɹ9L;5"yp9sKh D^ЧM5gj DzY1|4"L lh@S\ #"_nq'iI- 8m1)84@EHxt!c-p02ӱxi\0/q\YZa&Á݇s9\!೴X ^s*H',(Ȳ,LZ`r NX>PU^X(\9Bd@{tѫ"PPO Bd@v1ބ$T_>L<)& ~ e"gp3L² Q *0?n4G%Yԙ6(0,!@;ogHpRM+1nufcf+E؈ ̫0qjI]cWE8!tu_ 7LO^W[f;rO 6 ȁ<˯($ݪ\>Dh%Xd! I/>4C%%=TZQ$m"ij|.hXR[E` @zY Q 5C8UYB,@z 6u`(4u[u¢VUHZK"1ó|;,fe 7鎿,-BЈ\S-RmPŞ(W@kMBSj=t!!AI F u^ͳSAQDj]o5K,!߰_/ ,,! 7iD6z֩4OX5j"@Td,J0E8x[Nx)@R,.nŶM>^ƜH<˷v>tI7U;4"7v! /_8P*%Bh#Z䱐J*"IBrYHd0 %"̱X$D  #݀igf$]tT˩ T" \yx1ith\ [q}<"ds&k,;c6Qf?VM@00U Ο6̋>rR9qv>+2 7k "~Ώk+ti `f@j"G2x-MŢ R9,t) @0 8*gbDiˀ/|({y~ : aOg篟#9PXo[aS @Jqf,0ig5DZh /nb<]ͨTa{1 0!gaZD<jR :cvoj~-ys=)Ai o¢A5ڽ1of-0,7:G/iPO{Tb9G"?| p#f?Ez|4XH7 Disl@6qj%`! ;ewXXN?l~=`k=Nb(#sFh:a`q2K+hИ;8XG$0WKc{x%b:3>F5zߠ3pak3B3b O1lBM%_< =j @01o"fVʴNrCci>0K(a@Ռ%Q%==s 4;g`{}.x78̍],bl l4_mo{y8{.9JL\٘Ungqwwaވc:2i \ = e :/cN)!+1-#WbN?c5L./;ur)Ͽƍ,n%Yz%|He. Z7'^Fk0lt?`+kg1[?}ϫI@c )?uD_~S{ "cY!> ֘9j\xvX|roWb>QRxM{ Ls$[|ãN﹑X;L6,|s#T5 /M#@7P ,r맸T3H6a{tMU؂npr5f;Q&PqYkb3.IL zaۥ]w} hX4> Qnn. 4 cLjo 4(I:`cÀ}X^ùQQ[l!m/w m<;aS@$J^ s l%Ea7| `rS:V*72Fm8L7aNBb sbA2m@e>)!$B B !$B B !$B B !$B B !$B B !$B B !$B B !$B i5fUgdBIENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/background.pcx0000644000175000017500000076102111357170241023704 0ustar keeskees HHXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffgggJIL>AIM>:F\FA>=?CKHKI@JYHCEDCK?@2JEL?>BD@:;:37<=AB=A1528>?A?ELCG@EKI@GKHBFIFSWOHEJVELBGFAEGCHAFKILTQGEHUEKBGDBDFAJ>@KI?BAE;:8.4:<;A;>=IHGH@HNKHBHZI@?=?@B?@>@FA@B>=<>=:27J=D:;B>=75>=8><:;697845236381*2,/'()20*+10-*-32573),0+'&/1)'),2/-1*,-+)%(*()$" #!!' %)*.-/./&-/,-('0&2976+2C85 ),/-,754321249869;?:B=+753504:97609A<=CDJK:M:G@BA$@<5=F:EL[QM7BDGMGHCLA;89<9607;9;>EG?AC=GB>GEDFD<-608?;8?>A:92BFC@CA>BA?>=@A@94CF<;@9@F@=6>D>=;9A>:85:?;83545/-2-04*56302730179:=6535420/5/0-.52+06,*-,-0.,(+)($'%#! "&-,/-/74/47'-/*1056-@56/79B5,5-57320.576525><:;>6878736:94/04;59:=AJEJE@=@>BSN?GCGFKE?B@DAOJHFBCBFDG:>A@B8N@5?76DNXB@<=GFEJ\AHFJ?<8<8:/7;<7;?A@78>C?<;?@FEDA@JOC5=E>CQ@=AGHEBEGKXOCJ[SOIC5BF@6?9379HKCEGEBJM>HJKJBIcYQOIDASI@CA.7B>6A=B=A<>39>;D`<1C?<;@QJB>KEDFIGOKNEHMHELJMEA?KFEGBJIOFGJIHFKMEB>KDFI=KBEOE@9B?B@>C?>@C@EBFRGD=@=IPXRHCGADFDBC=>=98<;>AD@<>?LH?@=<;A:=:;>?8:85396363:5476246153967=84698915654140254262-,254/-,(,%+%"  #,*1*,/0/626-,2.46753;894:890/76;530296:58=:<=:0:?>937;:505635:>AHF@=;?A?KL>B>;97;70:9?@<=>9:8=?B7><;=GHGFI>BJHE@A?>KI>:BCJOKFKOEHQ@LDJ=;>F:DFHOFE>5>E@/B=@MT6B=_kY[YPFLHBA>=9=JEG;I=89<@>@;=858?=<4=?<83965R?$5A=@EJDIQSMHFQSNQLJKHDGBHBLECAEILKMIKJKIEFAI@BJDB>CEAE8C@?C@DIHIGDE>JE?IWXQKEHEADA?<>AB@A;=@<657<;=:<9?;@798<;65483=>CBA=@;9H`LKH:<@CSJIBD7BSQBEC@KGCDAI?D=@<9:;=:5/5:>AC?A>?A=?B=7A>AFGFADGDNQIPHDFG@B?BCEHJOHFDPTP6IA9;94E@7;093968;C=:>:AFEF?<>6=AGEYM(?EBFK?=KTZHMPMR^RJTOLKIGDAGBDHBFKJQTMIMOLKIGEAH?CGAFHJGCRHD7@FAB>;><>D=EKILJAIDHOPRQJBC>EA?>=>=?F>?BA?A?C@=GD;=DLKCD@BDBEHA?=?@?>?;797478=:=;8:9D<7AEHA?DFH<>36*31/<;53158:61>;3240,-.*&$#(-*/1-46>5.-2/*4+65;9;<629>@C:79?7AC>;=?:7:67M>@=@?:<;4:;?A@B8?JLCOQ@B:GRIG@B?FRV8JBG@BC=@HIHBF@=?@D@AFJ<>CA<;CACDC?>FEOTGISUPAI8?EC@IKGFLD?GQK79D>A6-?=CMPFIOE@ED=NGC@D=EAGEG?NQGHCGBGCI640/18:=@EG>A;<:>CHOLR?2?D@CMHK\JECFCM[UKTLHRMIMLFOKLJHJDNILSJNIHNHLNEMLKJIKCQIDNJF:D@BC?>?@>B>A=?D?CA>ADHNODG?A@C?C?>C@:;=A=:>8BA<:9:B;>@?HGHSMHBI?G9=9056967286;=;46859895/0-&%$./2146,2,345/5070/:427?97=>@547@?86:<=?<=?C@<>=<@<;83DRAB>:B@?:8=?;>:CA=ED;=BCFDFHFYH>J[HIDAG<>HB>GAINPFOQ>?5BFAF@NM:DFJLAHFJB;+[kQ>KJFMICAC?GCI=5PJ>HJD[C?S_M\EAE3:9BGB9FADB@=B>609<9?;FDN>7@=DJHDATNJF@AIKRTNPLJNKWULJLGC;FHJKLKJLJKUVKMIJMF8CE@>?ABD=:B8A?<9<>=B@A>@B?ADFEF@A>CFGJPKDA=DCB=@G@<=?=?=?=B>:=DLKJNKUPRO;?>364:C2:=>=@9516:;91-*(-2646746;:976348575;?<797=<9<8:=C@>?AC@>7>LB9C;>FB=?:BA@<9:BFCGHD*=HA?IFH=DBJKHGD;>SI@E?E@DBC>DCHA@A?=>@><=DAG98;9824847:;=@IFEA@<:RVK?@FGNJHFTPC=JGI<:@=EFJ6B?CLEJOFE<:LrQOF;CIAWGJDG9=ORCIF=I@HCLV(0?IME=VX=C?:?>:973;<29386;=<=<9>@YOI4ADCNK@?EKOHMJMFLKNTNRNKLNIJCAJNJDECNJMKPLKJLMIKCBGOJC?RIDEDGBC=AB>CBHNHGCKNTRTLEFGKHPK?IKC?>=><>=?A@ADB>@FIFHE@?@BCDHKD:@A?>=?@D?B=@?9>DA3@DJEFA8365;=;84/-3473579=@=>=678<184869;9<>AD@>507865BC=<=C<:<;<@>A@?>:=A;6;?;BCDI@D<;=A@DGF>ADA6C8?CGKJGM@HNEFBDFG@BE>E?BCIHADGDCBCI>4=>546<:594=?BCA=?=:GZIKF?DHCFNIFELRH?ABC<7?EGLTSNQJB>QI:54=9;95<:9@?VO5@HJDG?=JFELJGFKCKPDJKNPULQKIHD;CNFBFMHGIKLRMNLHF;BNEBEFDMKDFCEDIBL=BINILDHPQTEGDHLNIBE@;>?BA>CAFJECDECGDE@MKHDBDBA>BE?A=;?>=<=AB>?;A?B@ELB@QMEMZR\STA;F6>6<6;A>IKGFC9-47897;F@<=?<;=<;<9BA>B=:;?>A?FKCDC>?=@ED<@HDL=;A?5;>?AFGKJEBK?CJCEKF?:ED>CFEQTFCJBAB=<24E>A=>=9:9:3:;A?B9AFEGBAECKTXWUTJDAMWG@FNA<82?:>:7@9>F>HN@>QPEFAJNA>B@JOI>NF:BCEA:0HYK?7HPBJR?<3AB5.>=E<=DGBAB?=@B;<@?8=:;3238564@B@A>DOE2HEFIABF?ADHGJH@QRKMJQILFJ>?>D@BCGDFEND@C@DHLQBKMEACD?@?@?=;:=A?B>BHNJTOHS`XTGD>C/5/@;KFHOQD7.)-?DEG=;635325351879>@<98>;<>:98;<9A>?DFHF92>@?:@BA>=<;<>;:;><=CBBA=ED@:BIKGBF@>?ACE?=?GBF6;@?C@ACMFHJFGEBFGBKEC@ALEHFB@VIHDB@C?<74AOA>;B@?>;9=<:;><>A@=EK@>LMEFCEOFOXABF@AHFIBDJEOQP`WGC?GDBEH@<7F@B=14ALDHML?-DJCBHJHD@7CE9B?@=;BCE9CAIOHNMQE=G<6CEBNQEAFIPLQI@FCJHDJFJLDGEFHJLGB@EDIEILFILDIFEDCEAEGBFMHLSMIEOEJKGLPEB>GMGDBDCFDA?:896?B=@C=CNJIEHIF@FDGHFHLFBEH@D?=?=:E;7?>B>:@CE<;BFADBJELNOUROSbZQCRI=>C:4;AQNIJQSJ-21@GFEC:=79=8:;8<8>CA9=;89:8;>=>FJIH;79B<8A?>?=58<;:;:<=A?>BAC>?E=>@DE@CEFB;?AG?DEBEGEKIAFE?E>DE:DYCE@DJE?MTKINID@B?=8>MF<:AFBFHB2AIDGEGQJAIEDCA@HPBLH:GFDNRT_Y?8@95CJB>:CDJQHLI1469BCFIHD2BGDAH97:A;:5;=AC@>IHNZPRH?B6;GD?DUTFIJF;>ERJIJ?HFLKGKMJNDFMDA?AKIGJ?HGLKHKNJLEDNEB?>BGDCGIFOMGKMSEIFIFEIHIJCBD@DAB>?<>9BEA;?DBFIMCMFE@CKBB:@:@?DE?=B@DC@HGDODFBLK@Z[]VKL=IQH:35@A?>;=;EA?=>=>25@<6=9?:7<9=;:;@BEHGEHAF@?>?>B?D?898:<=@B>@>9?>AB?BFBFCA?BDGHOME>@>@ADBA=ACF@C=A?BC@BDKIPEROB9C@CBPLEBLHA>B=SKFKJGC@;>D@9:@4<6>HG=DIGM=:B@47>?=CGHD?RB@JD>JECqSQY@LK>@;0A@:JBCOBEDBA@;@=A8FHDKOIK7BCHAC\[OVYQMKJRKIHGJFMFMJNJRUNMKQMHIFIHPHEPMI;FJOKHMKSOKPODFLBC;FBJPJKFD@EBA@?:=:DC>CBEGHJFGFEGHNJGB?DMEGAE@IGD<6<=C8?>C:@QOHCBF>@A:B?GKNQXITOWYUS[IPJUC@768@JIRTH<(15@EA?>GD<7GF?=A?=A;=@>A@EB>=FGJHG@>?BECDHGC=@CE<>=A@=FLEC>@=@E>BIGNA?HEAOVMJMQTSJA@MFHJG<>ME=B;DEJRMKFLO1267>E>;>K@F8=@>;C=ADMGOIFGA=HBOIE=J@MBFIEI69JPYcb[SFKG@HDEHBI?GHJHMPUPMKHIBGEICIAFHKHMNRIFEIDGFJIHIKLMNGILHGLDMDGITODJEDFDBD>;BA>AD=DEFGINSFGEDADBEIJIMECGBECD=A;:KH?DCBFGAOPHDORIG]cY^KETL\@HK1;,9B@CJB=CGBC;>FB<>A=FJ@A>BD@J@=FHMHEJFELKNEF@DBDMJ@AB?;><;:;=;:?BA?BCBEKHDFDCDCGCEBHFICBDB@A@EG;?DC?>?A@EDMGHN8AKEGIBJKNOLCDBDKHDGD?ABDBD?D?AB>DC@KDI?BGDIZTKJGFGCGCBEFC7:?BHBCDCHFHFHCDEBE@GB>EGHLBGMHKCA?I:B@35?CAEAHF?ADHDAEB9@DEF>BFLFDB>:FJDHIGBCJLQH?ABD7=G>EIPIHJKSXRPEK=6G?CHGECIDLGILMLKFHB:GBHGFDHEKGHIKJIGDHBHFCEIKMLIFKG@NLDBILPICDCFDBE?FDBCHAFJNPKIHJNCA@IEHGQSJIGJ@CGF<=:89A=:4@=BDLBDOVFNJNHELeQAH@LFNZBG7*:B?HCBA@BC8GM=?GC?C@BGFHFEDEGIKOMKJDLHJFDCMEAECFJ?@AB?=?;:;:<=>=CA@ACEGFEKG@BADFKNRGDIFDAEA?@?CD@7?HA<@:?8DADFKDCFG5CQIHLEJHEJICHCAHFE=>@ACDB@?E?@>E?;CNMLFCA>DFD?>BFE?BDCQZIDJH@E@KABACDF;?DFDCHMLOJ?CG?LDF69;DFBAC?KRHMBIGCT=FEF>FA?ACDAJHFEDB=@DCEHB>B@>=@>?>AM?BEAHODBDCLJFHGF?A@6EC=GA=FED=OPRED@GEDHJKDFHFGCDCFLKGHBMKFIPNKFRGJAJEUPDFEGDEGD@<86;724BEHFDFCFGD<>B?GEBFSUWNUHMWPVURHEGDFKSPS40G:?;-+159<:>AC@BCBABIBAJEDCBEACGBNKPQLGKHJHJFIKNI@?CIGACAB@>=7;79>E=;?8?ADECKHGOJRFI?BDBFEBAA>?BDBA=CF@D@ABNHFEOD@HEA>ECD;B=AIB:?EDBC@BADEABAFJKLHSF>@GHDHI@DC?J?FD8CE7A8FBCODLEDE?@BGJ@AEA@>HEC<@FSDJIF?EJCEADALJHD?:=>HDA;?NRMF=HIBICDBOJGOTSeOTHZA?6<:FO^C80M1;+*126>@BEIBEFEBHKHIAJH@?=@JAECFJGKPJHKRIDIKILHEGEKEABA@B>?=;=>DC<=CBCGMGHG@IF;CBKM=DKHFIE>?BFEGHGDB<@BF<=;>FGBDBCGNBJEHTOI>B?EI>@BDB?BCEGQIJIHQ98=LGFJCL=:8;G>AD:?CDA85?4?BF=BAFCRCGDNE>EAD?CH@AHEID@BMIGMEJPNIA8CEBGC:BLG@J@HKTKHRPIGFJDFEDCJHAKDILPMGRNLGHKFGDLHGCKHEFDEJF:SKLQH@FKAJCHIHMI@BDC=B?IMJMEFKDKBFAHGCIFODFNLGOG=;=A?;6:EG=BUaIPCLRNOIOIGHITOb?BIBAG>7VG2/8F-3+>G8?>@>FOJBGFJFHGLHDKPEGIMRDLCEBFBCIHDEGECBAF@BAKDICBC@?BAFJ?DABGCHWNOHN>DCAFAMA@CGHFNSNJEDNDCLG?5DB;>@B>B=;?=?BA6?G@;?IHKGFDEZcaXVMFHIQIJINMLJQPSU?D>9DH84>C>*)L:-$8C@?:9B;GIBFGEBFC@GJLKNPMFBHCIHMHIMNOHIFMJEIBPGHDREHFDCBC?8AC;BC>AEGKRKFCGEBDCDHIGLGBEGBA:<>BA=@3628?CBFJBG@FKI?FKHBFIHGSXOIDKTEKAFE@DCF@CDFJIFGDACBFGIJPEDKFC@E@>@=@B8>EA?DJPMT?JFMIO>@=6B=?BCAF;FCA?=H@9ADC5?LA<;9@G@=@7=;BAFHKA@D:LOHMNHPI;EGAEJRC@EMG@FIFACGDAJPQJKB>AB9DBCJNKQYKFAKJFABD@EDCGLGAPRB:5@GbYQIFBN>;=9BEB7=FC@JGFKBJKFDKHIGFACIHAFEFKEIMGHIMNLIEFKMOLCAHCFCLFD<@D?CEGCGHGKLKIHCGCFHDCHKNKHIJIEGSGE@HGRNDEGBE@BHEAHADEIONKHJI?@DEFGOQMHFJC>?><><@=A@<92=AB_VBC?D@?HND9CGFJGKGOKODPGHGCHE:DCGDHIGEDGMFADAFEIPODEFCBA@?AHD@ADINJPIEVJGPH=B;A>967<-/0;GFAKG@HA8>D;>?98;5>?DC=9:>AEDFEJPHLNCJAFAEGIF@IFGICHJ:E@GJDHBKVTQ?HIFCHIGKMQPSQJOHIJMG=@MC8>DCINO>A?A@NSOMJCAH@=HRJ3.2B6G8B3BHKOEA?CB?FD@FEIKGIHFLHMHJGEAEIJOKFGC>CDFJINECDGFCBECEIMIGCHNJHIKONFKIDIBSTEDFIBCBC?;=A<@;=4:>:G[83C?<9ARHA@NEGHPKPEGOHFKJKDAGDEDLIHGIA@HE>FCIL>CHGDFD=>G?BA=?J>:ECD<:;:ED>BGD>96:;6:AEABFHDFRMHJGIA>B>FNMGFE@AEBE@DCFGLILOMIGJNEIDCFDHFJLKLD@F@?FLFHNKBJGIEIGFGKHC?CGEB;;AOGDC?CBHIJOHE=GODCGFDCK@B@0IBF?A?A>?=46;>BA>A7;67<>?;CHEFG>FLJAGJHCFIHIPQKLJMODBDC@;@:AHA?7>D?MB3>FI?MPIMEGQMJCBJEDCQPGLYO=;AGLEGENJME-6JC/NOCAFGH8DKICGBGA@KG6DFCGHIDBFQTDJIJGILHKJHDHGHIKED@8FGFHBGIDJTKVJMFJSHPLPVKNCDEJP[JDHJB@ACGAD>CKQCLHCAEOBKFB?OMFG>HFC>CDGLALELUYQACP=HG,LWMHMAJ:8>DLC6/0EIKNICKGEDCFEFIGMHFDJLJFBEBC@?=7?CGEWL+@FCGK>BA=A7=:=?GB=BM_FEGFC;6CH>bPUJH?@BFDIEFCBDGODGDLF=EFDA=AGC8=?QNGF@CDNK@J@MQJLHQIDK(+NUCJ4EQHE>D8:37=MFGDB@FEFDCLGIKGDHMHGHGJQHFHPQMJD?FIF:AMEGFCG@BMCHCDHMHFC>ABHELJLHGOICKIBHLIJQM?HIJAFLGFC?FA;C<>?CIMJM<5?A?DMIL\IDFALZSKTLHSLIMLHPKMIGIGOKMIFI?ABEINQPJFJA=B>:@<6?>A:=2@BHOJF[NKOMCBXJ>G-2DB?:A;E@>DB?<>3=GDC:;/,3:5A29@:>ON>9GB@FKILHKDIFIPHKQFHPDMJIHLBNG@KMG5ECFHDGFLMHNMNKNUQMKFDGMJHPO@/9DIH=@AIA?>EAGOGFH>FPA?AE>=D;C>?A@A@4[RIN:7?71=FEJGKLGKHUDEMC?GFAFJKJDIKUQHQOJAJKSRTN=IFHKEBFEIJIFC5@DIG@CIHELKIAHA5?=?1<>ACAHEM<8A@>FIGBSOJFABIKRTMPLJMKLVTKLIGFGHIONFEKHIBSVGEFIB?@A>;7;B=C=A7;AEBP?SiZTPFDGBA<6EBE7F?<7;B?D<:454=:;A?@>:84;:72<5;RB&7C>;8@DHDB@BIGHBJPTQHFE:EQPOG@:DEH>@KDIDJ?BHGKC?EBC@:>@?BDCWMF6AECNK?A@FLOHLKMFLJOSOSNLMHICAJKGHGJLQLKFRHEAFSPCBADBEC@=6=>=<;74:;?I>@\YIWXJGJC9?7;2;495:9;@D=C>;=>5:><@X<%?A?DHA=LQYLPNJP[ROKTEDEGHPFLHFNEDBEHJF@H?SOCB=EDGCLIEROY\^_UMKHIAEHDAIGSL5+<;>:;CB?A?KFB@=MLC>A?;>7AE?CFDKD<4"4H@8C4BCD;:?;KQMFRPEDIKDLEJIGDJNSKOLJKLJLKF;AJHKMNJFGNMKLMLCENRTDSTKNAHKMRTNADKBGDJKMQJQFJRBFB=CAOH^cPR=C@GDOWXHC>EHGBECBHJFCDCREGHJLIJKLNIMJKMHKBGMVBFBCHBEFHJHJEJUQNJGE6KRPLID:DHJNHJBHGB?=C?BC?C=?CDEBARL7CFGF>?JDEKIFKAMPDJLMUKQKHC=DKEHIHKIHFEBDFEIMEABGFEFBAC@C?<>7?A<7:679<524639=;<;?GB;8@=;>6?@ELME@:53H:969CBJKXUKOHGHLDTBFJGFAJdINSKNPCBUNE?DCDFGEFC>IN9AFEBFKG@ELSIFKJHIKMHJKHGEIFLIL@D9AICICFHIFGPWKSNKJCSKNMNVPLI?DJXOKGHLGBBEFC7D>FEAGME5GDGMBDE>ADEHKHAQRMOJQIKEFI;>PIDJFHKHCJHBFKHPM?IFGCGFDFC@DE?@;<;?DINJMSEAJZVf[DBE9;>CFC;B;FE@=B>7:A>6985/3,-85:;@3;<;@ENMPTLMEK=FGEC@IPLE@5FB@FKE@KC8?MIJLKGRWV\bYOIEOIQIKFHZO:'E>?G?<94=>5<>AF>=:>KDFDF;B>3A7296B46BCD@IH;IEFMJRNIGKSJHRVCFUKLQLOKZMIXOHBJEIHIJMJLIHIJOQFKHEMONKUIHGLJMH:CINOMKDFSJGAEFDCFOSJHMUF:?FLGCD@CFGJDC@G97CEBOQEAEIPLQH>?FCKHELIFJECDEFGKDIPLPLEHEDFAFDEC<>@4;<=;B:@CMDB;MPX>BHA<93>8BABAIJ>B9?A:75.0<;28056:;<;><96>BVJQ5;<;9?=?:=@BG@DAD=D:<-76C;13>?@25=KGCPOKPOMIRMJGEHMHMORMG@HIF;DBICFHFNHIVOJNJQUIFSQLJHKVLS]KEBILNMKJQHEDKRG?HKGQHFKGLOUC>EC?ADECGEABCKHCLILSEBOLIVQYSXUPVTOG@JKSGFC:EDFKJHQEKLHSL?LE@DGCBKJIHEJUVIPQMEGIOSU?ABJCFJHIHMLUNL]OCQGNMNPRIFJEKHKDHACFDFKHC?NH?8;=>@GBIMQLPG>D7=IC?FTSDIF9=GRIKLAIGLHKIPGJHC>DGH?BOFGCH=?MDFAJBC@=><87>@VIL<@ERMIE;GD6GLEJLB<>@;:<;<=984<6:989>=9;:=DFJKB?AFE@C;HKEFIGFDA=NHNKQSUP^ZMPVLEVODKFEWXPR>(8@CEGJBG>B9=><;98<5>BEB@HD=BFB?=>AEIQPIT;@HCAFPLPUYQSFC=GHEJH@KD>GJDHGOFLHCKTK>GIDFKIDGKMIORMNBJLHNJF=LKNJNOJFIJMLQMNLRCBNRTKSRQMCLNKQKEBEIDEFJICIA@:2=C@A64<>@BVO6;:52:975@B?=ENF3NGDG>=FD?BEGFIH;TQGKLHGWNMJHCIHCD9?859=8;>4849@>CBDA:9A;8>B>B?5>BCGQRD65?ABFB?763AGBHANTMHMJEDKPNRJKEIENJBADHIKNBNQRWRTKMKIHFMLQNQI@IG@CEFHCJDLIQZSLKJGIFGIFEGKP@6@>@:=CA?BAGA>@FIFOSKFI9PCJFHIDP]PGRFMHGAJPF?IAGBE>FRNIJVFCGLFBJHGIJHDJLTLNLOJLIMJKJ8?GNELQNMHGFMNIQJLH?O[HMRLOHCJKSTPCDGOQIBDCBFILGL<5:CHNLJGA<@;8JEJKNI@JOXb_XREKE?HCDGDH@IKJMSRMJ@JKWOLFI>=F@>;<>@;7B?>;EME7HIJPH?937RF/3=CA5BDF;BA>A@;ACF;=B@:;:276246@CA@JNEAIMFAH?8CEDLOECINRMNMH_PIFGKDB<507FGFEGIEKOFNJINMQPNQWQLJKJHKDMLJQCHL8:AFKJB>@94658935:<7=CJ@9@DGPRKRKGCIHIJCJHKADK=FKLINHIMQNTUTOLJHGKIGFMQMGBKESMEA@FDFEMFHQMV[XWNKIHGBCHCBFLE:JDA@BEB?=:7>BAF@IEGHTOLQ;EQGBJFZEPHMJ;>ACGBF?JI>?:EJHLOMHMIJGJNFDKNLILHKMSNMVNG?GKMKLMIDFIMHFGHMONGIRMERQMQCIKHLDAMIQGHLD@?IA@AFMNGK;9=AELEGACBD7?G>DINGIGJIPTQOFK=6F@DHECIDMHJLJLDFLKWEDBAICDFCF@?<>;@CB@IMGHLNOLHB7;4COB9BEFDA=:9@:47B:8CAESRJHF@CHNKF@6GHDC>BF;DAONFIKJLEDGRNTSJKFNMJQOVSLKHICEKUNMGFGF37DFHEB<9?<653:4:@39=B<:=FJB<;9D695>BA41A4-3=ACKPMIMJEAH@=81:<>A?@ACKSJFHKLJLALCS^IG\XHKHMHQH@GDGLIAGFAFEGLIPSMJHGSMGMYHARNLNMJVTJSUL@HFHJHKMLHKIJIMOJKGLPNLQMKHKJNI;BFKFMNBKIA?>BECMJLGDOA49:@EBEAC@6DB>;G@=GEC>OQEB@;EADGDABGELHKLHDIDLHL@E:>JAIDABA?AB>@<@C@>HJNMROPF@A5UKQ>G;BA:GBHCNXEQTGHMLGONO^SXTGMIER]YNOFSPNMHDFH/=HIFNIC<9;6C5;09:8C:B5;@B=9?B>CBA>LONM<01/TWET]JZW=:CD872=573*7@JONRFHKBCAQGCGCJIDC:@KEIFDNMOSOMHCHDGLHGICIDHCGFKCN<:DKIFMJGTSQVXZRJIELFMJLIJIPH>5HKJFE=?B@?=@89?<>IS[M@ADFHMEJEIaSEOVJDPMKILFDISOI@AFE97LECORLOMQFSQKIKEMGMORMOACKGBHKLKICJGIBAIORNOMP@39=FGEBA@<=<>=<@AKAEBIHOLMLDKILILE>@?BGBGDCGBEHDBDBEC@AGDMJIFCA<:ABGD<76GHEACDGC@EDA<@D?E>;KBHGDAB@JNQPHJ@9@:=PGJIHE7JQW]Z[RFKd\HGDKFHGFGFH@ITOLCQKQWXTQPQIQ]f\SOQBFKMSLGBE?5CJHQOCE@A?;@DI<5989<919:?><>C?=CEPMNBE59LYTLWPUD?16=>BG;8;AHEDKIKORQPIDCFIANJHIDEPQC?FNWGBICECI>D8CLDKUKMPNMTQKSOGPSL;GEFHEFGKNJPMBIGKFIOLI@:CEBGA;CJDAJ@KIPKIOKFGKSRUD@CHBEIHIGNLNCHCFGDB@=ESNEIE@C=;NA?@20AEBEAG?ABEGEC?;AEFE=EGHJGFD@;HJCIJH@ACMOTGM;ACE7GBJLTLMGKQ_[SLFNZCE@FE<@7;FLQDMKJTNQSDAKWUYNMOZYUSLKJHNMLJDCJ;CDMH@F9B@?AB=479=84:?4=<;@;37IHOJ>EJROIG@85CGHEHBHMDGIFKHPKMKJID?@GEGEADEGEHFDEIGEFBACIHONQVQOLFLHFOGKGETNLB@9JMFHIFHIDBD@:<:6:EJPDOCI@BL@=PFD;PAJNQMSLZUHSLF@?HEGCB981;GBICGRQLJLFEFNMRNJEFNCOC@ADFJFSDJSOYVRXMLMLJIGKPQRLO=DJGC;GDHECJCKJPH=?CA7=@BFGAJTONE@ECD@<9;AIBJIHGIKDEIFKJI@HJLGJPIFGOJGEBIHDHF?@AOUOH>AFDBE=HB>ECBAGFIFA?CHCDHD>DB@A@BCFAG>@GEGJECEDLIGFBABA8F>IC@HEFERQRHFI4D>D>C;-@DMSLJOLGMJQN;:8?6>37493?;=8LCD;>EKLWGQH\NEQLJMEFECA9:84>;?BJGMRMNLHFGKGNIFLG@JC@AMJKRJIPRWVPRKHJLKLIFKRPROKEJCRMFCAFDBGIRQONDAGBE>H@THD3=@EACBCDMLB=:@AF\RPHFDL@>FAIGFHDIHKI?CBIEKPIJHCHLFDAEDBDGFDACMJFJFBADBAEDBAGIC@BDA>EAB;@EQAJLD>CLGEACMKFGB=?>:@=A?I=@FBAIANRF0=BCEDF>MVJQKNMKJGIJFNB;IKOUDMU]XPFBOYV]YL[ZJAHKJKWHLJDC@CA:><>:46>9:0434378:9?B>CGP?=83BESG?C@*/>7-;:=EC><>8=@ICIERUFQKGJHIDHGJKIGFCF@EGLHDGIEKCAB;>ACEFDJIFIGFLHNJLMH@EKHIFJKLCHF?GHGE@C@BHEAI@MGJHIWTGFQVPLCABF6-@9.02:?DFPNINJHCECAFEGFCHAEIFIKGJSPRVPOJMKEIKIJHJLMPSHFJOAIME@FKLEOGOSLKGHEFJC?;LD9>?BAB?CAFIGFAB@A@KIOJIFBHC?>IOH514=DECACDINHOPJDJDHIQRJFCDJ@>?AC@;?CE?BEICELFB?B@>9A9=EIKDKAKENGEDA@BCDEFAC@EFRCIFJDAH@D?ACJIDCGAEA@CFHFLDHJGEH@FIKFLDF@CAIHGTRKHNISOAFESENL:?G=>RcYOIAJNO\agRX`]B8OF@?CEHGMD547418;368937;7>=D=:D:=/08?HDB;34=A<169B?@A=:OVSHFG?CFJKGJHEG?EOIM@CGCKJLIBACHJIEA@H@>@IB<=@B9C>?@AKC4EGHGEKJKbUNQW]XKEFGB7/>54+4=GLMRHJECDAJIDEDGHGB?CDADACHFAEB?DBCJHEGHKD@CB?BGB7145>GEHIBCBIGJOLFKG?BCDEGHEFDCDKE@97?CE@DFHA:BEBEDCGEDGFEFHECDORWQR;?AEFBCECBGIM>GDJF<>ECDBCDGJKCF><8CDEJMDFTOLGAFMJEHMHLAI@AQUGLGBIRJS=KXMGVWGFAIQRfMJGCKIKOhSLSQSGEPMPIPJFAB?C:8:342103:746027;@CEC?=?4:'+@>KFB527A@<@8@>HQR@B@ID@C=@;GJGCHEHJKGKIACDMJHIGKMHKGKF>?;?@ADBDFBKLEGHJDFHKNKLI@B@BCJLIHLQEWIGID=BEDE?<7HC@JHA7:7>A37JHF827DA7DGHDHBDENLSPNcY]TGAD?CAD@7BABCGLHPRQJGDGFICLIJFAORI9ILNROPUOLINOJKGJFHJDCGEFEFCECBEHCHFCDHE<9EC?G?;?B@?=D?5=I@7JOGEHFDBEHFOD@?;A8GH@CDLMIGEA9;9>BAEC@>EJDCA;?@DHIHGDICBNPKOHPG?BD>IEBAHJIJPIFA@JIDBCECEIDFJGE>JLB98CDC@F^TMFIEJ@>E@UKLHF9LWUHOFKXMLORTOMBAXQMIMBDIYIPMLINbNQOQVNKQKEFCOLGI:>;=<7:2/.8:18=9@?@E>?:=19?QJQSCA?D;<356?93<>748:<;FM?@BD?=G5.7DRDMJODEFHCAHOKIJHFKSJKI>BGABCEKD?@B=@=@B9A3:?:CG=&/AH>OEDEB9@BIVR\_[SM@G@E?EA?04GKLCAIPQKGF959NBADB@ACBCDABGBA?AEC=9@A=WILHFABCDIJKQA@H@;?EHNRQNIDC<;:;AF?>CGDK?@BH?C;@BCEGDJDJNEHCLRSP@?E>DGHJKPSVRIKFMKHJO>?IB=@ADGJHGOLK>@9>BCKUMKFED@JIRQFD?DW^MFMIQRMNHKHJSWNOTNBCLJOHMKIQOPONLQZPJBQGHKA=OLPL9A?9=;438;7/729@<>BD@B;96LKQNMGFKC:>5467=6:4>@63=F@F@>LRILJGPECBCHOEDCEAEPMGCJC?ECA?ACJIDGDEFIHBAENKJBKNFIFKGFIGILJLJGJKNIELCFDA=E@E?8B8>@8>7IA7=?5/A=AJIFJFBANBGRPWTVSMJA@GF@=B686>HCEKIHC?;HEGHKJGEFNJNFEJDKHJGIKF>KNGIJIFHEGHGIHFBMPI9IJLOKHKIED?5OA@;F?>=A;9<:AB@DA@=@=BFABDFIC@GHBCA?BACA@8NIH>=ABFI=CEJ@EFNMOTMFHA564;B@6;@BDC>?FH?;CHIEGEKGIH?KEIPLF?IJOLHLFHLZSQGMKJGHJMEBEP?;CEFDGIMKJIDEDEDPKILGHCBFBEHIJBDAIS@QSFDKNQOIDJOSGPQUIMGJKIUPKJLUORSEJHES]IQNILAD?>?;D?>14=D<4;8:F@?@>:ADKFGAEB>?9B?@=543=9;>A;?=AE>H?IALWIKFKFKEJCBDCGJD6?A>;?JLHDIFB?DFJEH>?DFHDFHIBAFIFGHOKJLFBJKHAIJFGHIHMTHIHSHDFABGMHCEDCB=@C:DCFIJIB?@?>5AD=@BCBGEBIPGAELSQLJSHEAGA9?7>7F;BGKB=>IEGELYIMOIJGFKJOHIHFIECDJHFMJIOINKIDB:=C@C<7@AFDFEHDHCBFDBA@A@EDAB@9:DJC>FBCFDMK?FJKFHGCJILNFDB856G;6=ABG?EGMGFMJILDAHIEIGIGECBCAI9@DAOSDAL@MNOMQHGIJDNKLQZOIJFITKBMHJSIDCFIZXFQSPLBDG=@=;>:<;7;8<>539:=>@B@G?=@B=ACD?FA@CA52BOC646594=JH;=CFHFBCFBDSJHCDHGE=E@ID9:@?@EFOLTIGDFJKCB;ABAFACADEAGKFEIJCH>=HFLKHJA?@>A@DBCBF>CDIGMQL9BIPRQRJOTOIGFGBC?@<8FZOMDF?BCHILFKLDLEBKNLGAJDIMLGC@AECJIGFIMKCPHDEBEIGFHGDCELJKHEHDGFDFBE?B<=HBFA=206=;9>@?B?=7@A=UW>@FC>DHB78?ADADACB?8=G@AD@FJHF@GHIGE@BDBDEC@>;4:3=HD;=;=AC@DCEADSQLKIJN@CJUKFIDIPJINJNP\I=CHEDCAGFHFBEINEJDEFGFDA@>A:AHLMNPLIT_MNTNOPHIOTHLJLJKSNOLMWPNTLWMCHKLIONDJKMA?B=9@B@>=?BCJF>;D?:HG>EHEPID>4?@65=;OFA?;ANBRHJHKC=NUHKIBILBICGFIDFE7ADEDCDIMJLFIRI=;?EBIBGAH>E>IKI9?E?;QND?MJFHJAPMRLGINJGLNEDCLCFH@FGEGDAFLHJSPNF:@:?>FBDB?EFGTJLBFJTQOHKQYSDCEF?=<>=FSTFC>EIADB>FGLDHEHKOHLDACMKIAIMFIFHIHIEGLFIKLGKQIGHJHDJHGOHKEACB>=BEC<=979=:967?@<;7B6@QA1B=?NE?@BFJFAEIH@=ACDCDAC?A9595>C<:<;:@=BDBFDCB8@EQKGFMIOIBFHF@FHUPQHLOEDPQJNLPNFDKGKNJ?6=FHG?ABGDGEDA@HLJHFEFHLEF@?7FBAEA;9E>AG>BEGDBF?>B;=E7<;COACG>=>COMJEG@MAIFDGBFICGJ>;EA?DF@MKTOLKHOUONLTLHLFA@C>FEAB:;<8767<;AD>?<>?;<@;=>57<5ID+1A=BAE?JIMKFIGFHE>BD@FBED9A@KDFBCCDK:AHJGHBGJ@CAHG3GQPKHXHKQBFXMKVUG=IMXLNKONSnWT\TQOJL>HDJHIF@EGC7;:=>258249=A>C@BD7;DG:B>@D@IE<@>?DFAD;5:@?CB=GJBG?GQGFEDFKP?@:AEGHAQOGPI7CGECAHJCB@DHFIEJIHJ?DGEILMDGQ^UOMURTQRLJGDG@6>?>?<3>?@CDE:BYJPJIPJFDFD@MJRMJHDI@CKJE9HFIHIJMJGKHQEJGILFHJE@CJIJK@AFBA;>575:;574=5<:ADKA>=?<>@NGQP6>DCDJB?FNPHIEHFECDEFIGIIA<848?IGE@>OKJOKOIFDFHD@=BEC?B>ACB;EIFCIDC@B=FABC<5BDAFHACGBDFCDC@=DB?8A=BA@C?GERLFIO@;JKLHCLFD?BADABCJHBDHGCDJFGIHFKRQLHNQKNPGHIF@ACB?=;=:E@F@HEGZQJLHLGAEAEKM8;A?=9ISH;DJADKEMKLHFGNJIGNKJDCGICELGLFADFA:<@;?9>741.48;<@C=<>A>NEQ;8BA>CJH@WJFDA@CBEGIBFC=EGOJBMIEFNOGJFHD>@DB@>9865068:;B6?DICADF>BPIBDQKIHIUOLCJDKJGDAEHIAGIODK]KB?F>@OHMC78@CD@=AI@EGHBGIW^LHGAFGA<>9;DF8?=GFILTASL?FIVEKGLKHFIFGCRaSTW^WKDHLHJLOLONIH?<>;=@7=@>?>?BC=A;54:?=;9>B@B>EFHLHCGD@?AB@?D=>:BGCEGA=>C@EAJ@BADCGCDGQFCEC@>C@9=?=>CAGOMKL?GIDGLEGQKFDCF>BHEDFC@HFDJAE=KJMGIEDHKORSKMJKMSJFLMHI?EFEDGEJEJKJFHEFCEADEDEDEKOLHBEJKNLFONLTPRHGEJIAFM?FID:;:?A?CAEG;@DGAIGICFMBF>PI?IEACBE=;=6;9:9=@E;CGIKMLDHJDGH:EMKFDGC:JLCGDEGFEDAIBKNGIOHLKLQKMLHIACLGCFBMKGEBGHCAIGJIFHCFDJD?>EGECJIOLKIFDPFHFEFKGEHD@;BMBMNINFG9HWSIPEHRKLFKQGIN@9ECIF@BF>PMAGIKHELAEPGJKDCAKHG><5@GIEAIDPEKJ@CGY>E@E>A?D@CDGF=@>8?NS?EHSK@CELEJOFIMO\N?CHGf[VRFGIJGFJHIGA>IBHJOA;:?=6:DBA?@?FHAGIJBDHGFMIABEMIGABC?C@C>@HDIGICG=HBFEKFHJEIE=IKBFDHA;?>8=>;=@;=GKHIPAHLIDBTM@A@ADCEGDGJCHGCF@FAGEHJGFRFGHMGMJKGI:@RDHICHIKJHECFEHNLGFEIGEGQKC@DC?A>EGIOKCHB@?AEFEFHEIGBF@=;APOPGD=CZ\PFIFTJLDKFMFSJ>@EB@IJEWRKDEGU\NLTILRINGPDHLDGKD:CD?EBD?OM=>J@F8?FG@FIFEJDEHCBCED*8@<@FACHSN=;?EFGHAGD<98<727<:;?=>B><@=;?ECKG;@EOECIOKGDIFTPIUQIKENJDH=3=@DGDH;BJC?B?<>CHPQHD@A?AKE@>IFEIDHEJKFCIDE=G>ACFECDKGECDKJAGCIHED@HMIEFKOIC?>?21:=;>@BEHL@8;BEOHJUIB@AGFCGIFGECIEDBACDBFBGILHNJQNILHECGF5LNBGLFGFBGBEGEGEIONJEICBCINGEC?AGEKIKJGOH@HE?HNIJPLAGFEMECAGSMIDGBIQ`@NWKHLIJEALQ;>E>=GJK=MQOIHA?EKNQULPMJLMXOMKLILC9EDF@?FIB9;5065362=BAD@CNG;GEGYHFNE=:=8;037;9;9=DC95=B;BAGFCDCB>JNK4=G?QD=BFJG@BHTDHUROAI8CFD;BAJI;?0AGD8;9CIa]@C?GC@A<>9BEC?9>WOCFTJLGLGUGLEN@KCBEHBFAIJ?A>@FBFCBF@A@:>IEA7247CBA>;8C@C\G3@<=;HMC6EF>AKEMIJCFHIKGFCHE8GBC?DFHJEDEGFCGIHE=KEJEBHBEKLF;@ADA?A@?>C@CFERED=?=@FMXTLBFCEGFDCEFLHFMHI=@GHJMNIJGJIOMKD=BGEIFJKEHLFIGEFDFGHFELKPJFHMIEGFMIQJIFKGDHFACEIMAHPJONGE@AKFGLND;?D?NTD@REBFKNFDILJB@GHJM6C:FKLIMJIHMLRTMPMJLMLECLKJF>DEBDGDHFA=CF=>BFEB=;9;?3.96>@DAHMLWLRL7E>6BCIQNFEBFE?JND8?MG@>?HGU?A?@A@>GQ>CA<:64;9:/:5=?9>=;:5;=A<=<;DGIFJA@FIGD9JMA:?BEFLJFLUECOXBKDEF<>K>?JFMHFB5?DB0=A8>NYC>@B@9E629BJEF8SD@CFJCD98D?HDG;HCBLFGH?D?A@;FD?DBC?AB=?B=?AD@625?><8@8NE-2C>;=ANBFHUKJHGIRNPIJKOLGFCKBCFGD@CAEGHKHGHJIEDCHBEHIFAFDIAEG>=@F;C>@BA@ACHGPCG>IF@FSYQLEHECECBD@BDHKLHECHEGKLHKHIBEQKJNFGIJHLJIGFIHFGEJKIHIKOKNECHIKJCMPSPHFG=DNIJG@>CID>EIDGJMCEG?ACEFHFADGONIGEFZOKLHFELNJ7HEHC@KAFMEGFMBMIGIPRULOJIJ?@GJFGC@GFBGDEDIHGLCDAHEF@;:;>=<:?>DAC>EHJMUPOI@?=9FGAFPQDFHCD=GIHB9CHGC?6ACH@CE@B@CD?=:;:>;7029<@C@A>?<=A?7?@>BIHCDGCHRLJPHIFAIAB;DBDHMPGIDIWQ@=JFG8;JEDEBAD:DJIGE:FJLKRHMEJCK>:C@A9?5:9<=>@=>?:;>H@RF+;C@CJ@?CQYMNKOYSOKPRJIDC@H@CHBDAFGIOJHIPJIED?EAEI@HBJHAKIE9?E@CA=>=>=D=CJLKJFH@LCHKQSRLCD?BCB?CDGFHGIHGHKLIHFJLNJMSLKNJKMIHLFJKJLJGHJFJKNHEDEFKPNFJSPOIFD7DHEFC>CECA@CDEFDGKFDK?BFDEB?DBEKLKOGOWNHKJHEJHD@GHEFBDCB@BFDFDEPONLILNKIEIJ7ERFGHDCGFE?GEFDHE@?GDAE?:C>AB7BGDHEBAENLQHMD=><@GEPJI8/8>=?>A?@CH?>BC<9CACEDA=DEKSKPTODH>ECAEKGDNEDCQR?9C?A9/9?CHMRJINEBCEAFEDBC<@>AF>G=H@HRHGEJEDJ@KI9KHA9:;JIJEALMLJKJHFLN;:AGB=@D@96=7?;@<9858:=@CA@<=<>CETGVA2@EABMFDYNMDGEJYKQNJPNIKCINHIGCHIJPLJIGNOHIMDHLGIHFKOFHPH>ABE@?>=@=>@JQSUVPADEGJIHFBDB8?CEA>KBHFCDFA;ICGLB@GOSPHI>@B>6AFNSAMGNRTGBDJC@HN@C=B@AG@<@EBC;<989895<4:<:=DADGD>AB>@D>BCECHETP?HXQJF@I;GC@FBIJPDKODB3>G?DBCK=CGKODGIGC@5FcX?=IJFJGD@C?@QGEFBABADB=EDB>4FJKEHKLNIHGNTNSGAC@ED>A?A:A><89;6174/769:>29<;A?CFGI4=A<>HLI?YNKHG=@JLPQKNLJKRXLPJHKFG=BIHJLKJLPVMQJHLGK;?HBC9D?E@;C7@>;9AFKLPQSYSMFAFC@?HCJB<>?ADHGMKELPSRTSKMLJIJHJLJMJNMG@FHD=DBJHEFHKGNIHIHEDGHNPENPDGHKLAC=98EBFNFBPUTJ?=DK@A<:BF@DBH>BDCIH?B?5BLEIGFCFEGIMJED=CD:?M=?A<;C@E?5<:;9321;579<=>IFB<=;FUN=>EFMNIHIDQOJ?HB:GD@HKSOKIY<8=A;Cj[PF;EP>VIJGF@5JRFH=BEA4@>BFE@485686><>=9>:>@TNO9@>DJI6@HNIOKLGLOTOPNKJLNKLFDFONED>NIHNMKIHLMKLGDPDC;OGDHC>;D=A?EKJGCIPUSRMHFGLHLK?ILEA?AC>9DJCJLFKLKEKMJHF:=KIKMOPOLFEVSOIHFJHEDFEFHALXPLYNMLHRFJEFIMLIJIA=AGEGJCACA>:?;>:@MHBMH@=CUBCAIMGFM=@A6@B;@AD=423;75787<@BC=?=;DZMIG>EJBFJKHCHSLD?BC>73=CEGRPLPN=EB?C=KM=D>1B@GEJHCF:M`LJN=:5DQMIA8FVSACBCHCD=DBCF?=9<;?<85<8<;89<>:7;>=@A>TQ?2ILCLB;FMEOFIKFOGJQRUQOMJG;AKFBDHCOKFHKMQMIFH;@JGBCGCMPDF?ACF@M@?JIPIGLGFHKR[ICDCGJRNBEFA<@BHEHIGNTPRWSRMJIFIJKHJMSLFHKFQKB@AFGHKPCORSXRSNIGDFEDHBADBCKJKISRC?=ACTM[OGBJF?9BLT@81?@>HDECHENMIPLCBFLHNPLOFCEIPFBAIFC@EQDCAINQPOKDGBAECB@DA>FHJLMIDAEHEFDC@DBDAGFD?ACOLFKGAFECBCAHIHBC;>?>=B?DIBEFGBAEFD>=E@EHIYHALDAD>32A?B=?;=>5983:ABA>A;9FQFHJAB@GFQHEHQN>DCGC=ADGKWZQXN?EGWH@ATC<>3>:><=B@>DIB@BF@B=>ACLEUFIGFCBC?DCEB=AB>ACF?@A9>@>?;?=7:=;=839793>C@B>@PK6EFGFB=DBCGHK>LRILKIQIMGEJD8LS@FJDFJFGHKHMKGEJF7JU?EJGDGDCEJGIKECGHIMKLEKHMKFCPEGIGJI@DE?:?>B?=?HKD+0*5EKIHDCIRHQIBFGLKPFJELMGFKNFJEDEDBAGHLJFBD>?CBE@EFHIGHEIHMKLF?=C>CBDCH@AGCNDEDKG@G@ADBFDFLBEB<:JFHMGMPLHDEACGIMDJEFCAPOHGDFABA<:3:MB?BA;CID=INE@DKRFLWF@FBAHGBKEQSQZXODAGIFEFD?=52A@A=313BAMNABF>ACBD>D9;B?N`LG@KGEDJ@HDB>?D;@ED=?@?@:>BG=;@C@A;6:3074>B@FOGHLGNJ=HA6BECJLQHBHIQMQOKEAGDGICPHFLFHIKIECFDGJEBOIELGFECBGBDGCBMJQLGLGKHKGILPG@?ELIBDEDB?;<;9:HL?B>;CB=?;7=B?<:?EBCHID3?JEGEFNDGKCE?CNEI=DIBKQR]\E8?=8;KE=>A?GOHJ626=CDFKIG0=FE@G@F;>CEKMHMB@FNECD7D;?HAWYCFAIG=A@HDAGACD7GDCEBDABFGBACGBF?CFB>;78?=73:8@AB?EIMLZSPNB>8AF@ARTJIEB@CQLHJ;FKFKMJLHDLFBA@IKFI>EGJKGKOIJICKGA>@IBEDFJGKPIJSGIEJGEHFKEBCBC@A<;>FD?FKHNPVNPSPNFBDMIJKEJGHJFKFEFEJHED=BKFHFNPQRVSOLFMDENGKLJMWD@DIG@BILFIAIHSN@LAHE=?<=>:DF2BAEG6@FHJIFSKAGCSJC@USDEA=EDBPOPYV7DN?<>GF@?AGLJEFGJEAIFAC?8A<=6S]PU]MPLQPHMHELHBIFLJPXMOKMORHLHGMJDJMJ:EHKMKHMIRPJMRQGDIFC=BHJMNLIE?EBC;>BGBNHDJFJGIKMKABKGIHGJFHDKIKIGNOEAHNLPQOPSTQLKLSLGNJIGJOMC;CIHFA>HC@F>BPODH?LK?>B;C:J?A;G?;MhHQC>A?>ACB?EFDMQCNT[YWNJKCDC?G?@CAELIJEQRD?>C@EDCDHIEAIJORPC?JOLFOLKJKQOPGQNGJKLK=@NF;:FBAFINL@EFB@HREIHIDCFGHJPN@FWMIHGCEDB@A:7?@;@AB=AKCE>?>@DE@DGIF?GCFXNFLOXTNHIB=HJHKJC8NF;A:;BDGRILEGQ5074CKGMNGDF>DJCI954@BC:CJGEBDMBGJ:?>AE>AFI>@DCA>CAD@A@DAG@?=E?FB6HDEHGB>GOSGMB9>QF>=C=HCBDJMKJCEHGCEJKHDFBHEILB9HDI@BGCES[NJHJHE:?>BC:=?GDEIC>@IMJMI>DGLNPO65BGD>=@FDF6:>@IEBCKFHGDHBFDBF78=EC7BEB?IGDIFB?KE?BAG>FCB>@DEFADB9=EDG>@HDKJADBGEFGHGEJLHORPIHDGIGHKNDLGJHIKLD;?>;=9=@G@C>HPH>ADL?BA@8D@IDEICB5'-DJ=A?>@CDHEIKNVQTYSUOIJEJHLJNAEHKFEIKNHK:BGDFGJFD?AEARH:=HJCMOHNECINPFAKFIBMLTJMXYA:>DLGECHIMFK>KIMKCFBFEFCECA@FAEKDG@?=ABCBA?DA@>DFA9AKLJFDA?>CEF@>@GCH?BEDN_KFI?C>LEBE@DF?=AFEDABGKMOE:A@BHBIH:6:9CHCA>BEGA?DCB?EHFOJEKD>C?ENI@PGCJPFC=BEB@BDECA>?EDHD?@B?A?@?ACFA?@FEBGOCECIHEG?B5DI9?CH=CGFD@IPRGHA:C@BIDB@FDKIGHFMKHE@DBAHEDAFEJIGIGFLHLGJGFAFIKMJGFD=FBEHJMQIEFIHIJMHGHFCIHMHFDCHIFKFGHLIEHMDFHNLCA=@IVQTKPC?JMKHGLAEJIMGLIHJH>;@BFA:?@;?A=?@;8<:=A:7987237:CBGQC87*@A;9FLJEICHGOGBTOD=DHMLKLJOEJIQNINRINDIKIPVM=6AHDC>CDEBEBFIMIAH@DFGHFGCB@AE@DEB?:@ACDBE?@D?ABAC?BJMG=@><@CDA?BEGABA@KOFCNHCIBC?ABC@B=@HE?AGDMJOA>B>?G@LCE4<>DFAD?B?BDB@ABJKOESL@;A@2PGNLIED?JHOXFDVH>@?ECDGFEGCG?=DID@?EA@BRGFKG>CFKCBDAJHID9<>:?<@H>?CABH=CGMDL:CFDC@B@FLHLMIGMJEJABFDEADCGKHLOKIGKMEIECFDHGJLJKD@G@BHMIKJGKJIGKLMNKFKHBGLOMJFHNCJIJEGJIMJIFIHJL>AVUTONGPFSYVTLNAIHINHEKFHB=:DBE@=@=AC;:51374851/3560,0-38<@B8?564649:=7?A<>ECFILNPNMJINGCJCGFCFID@AC>@?@A?DA@HBC>BGFNCFG?DEGHFGACAECD@=;:C?@CEC?ABFDFB>@AECEFEA=DGBDBEKEBIGENPG@@GJOXQPF@CEDE@IDQG;5>BADC=@>BHB@BC?CEQKGOA9:EC1=BYXD:=@ECJSVQRF@HCIEBEFBI?GLIF:9C>@AEDI?B?DBQGHFKDBDAE@BHDBDGCDEA=KFGJDJIE9AGDM8@KI?GBDJQPGROLFJFDHBJIAGEFKMPHQOPFIJIEDHGDJIGHDHI?MRN@LKCGFIKJNPCFGCJKLMNJKCNKABGJGHKGOLIFCDG;QH?MYqWXCJIML]VXV]NUBKBAHBADA?;<@:AFE@;:6?@D=BACGEFHCO;@HOED=?D>GIJHDJHJKAHGKQZ[VKLJLJKCHKDBQON/6:894>AJCE?JOHKBDKJDBFDEB>CFDHLACDC?CADB@?DFDCEC@A=B?>DAFA?AF?C?CHD@CBGEPQIHSDCA?HAJBACFEBOPRPHGCLFCKIA;@G@9@?B?<>?=CD9>FA=>B@KO\PX>=9>@FDA@EDB@JDO=FCJF;@FBE?CDLIGA?<6:BGOCAVQRG;@DH@98ED>;KAILGCGPIDIEHEDGFDCKFIJGEHMIFIGIHJQHFJPNIDAFKEJKECA?9F>:C=B<;59=:94713<521,*%!(!$##$(,20+0)015:62/@:9B;3:2=:9623=4>I@7>=689:;,23=A84A@:9EH9<:>=BGNLGCFHNIFRURWTMIJLCDHI?IQKU<-;BCD@:C?BACGCDIGD@=@EDADFAABGF@B@DAIE=CGA=BA?=AD:=CABHOQMSDHDKEOB>@6B?@DGDFDLFDADE7@FD:8KC95J@?:<8B@FKOD@AD8BJB:;XVIPIPEFELNGNG:D@FEG;C@GKNRNEMFJMKILFIEPRKDEADBS]YHIEQMBLD@BHPHCMUOE?ScPLFKR?HSPGJHDGBG<;93>09643230-($!   "("&*03-3-358702.-76BIK9761<:181.06=738@<72;J@;8:@7=FCFEGLGIGHMLONOJAEIJNKIFKFSO>2CGJH@?EHACE@EBA=DGM8<>?:AB>BDGEAD>AB;>?DBAB?CHF>=;=?DKICAEB?=CBA?FA?G@?<;B:9=7@AGPQSOJFBIB=8EP:52?HBDAHBQG@GEICBDFE@ECBIDMJAIKJLFGEHMNMIKTQNIDBNLTSMIHDJPKNOMRUSKGDLQV[TGDFNLNELOEHGDABMECD`eZEMDH;@I@CHFDOLB?C=:=79@/+)()'(# #(1+(#*237A?32/16734835452029734DLE6;45828B8<@>@GCBCBDFHLIA=?EHJFJGEKSA58MOKGDECBDB@EDA@DC@8AB>?DC?>=BFD@>:D@A?>BDACE?;AC=C@BD;A?C?A?AB=>FIF@DINWHFCBCFID=75;?EB3;?@52GB>=<@FGEFGIKCAFGCDMPGIHF?CA>AJI>,1-5IHGA@DMD@BEHGHEADBAHJFACEODFHIJKLHLKPJNGHJWUWJKIFKLQLNQNJRTXVSTSKE_c\WJMCJMVMLIFPOKIKIK>@DE`MKHAH;ACJIDIC61.+)'%$&"$&$ "!!#!$!"%$%#')3102431:56570/31H<:63272C>;DC@>@?@CBFBA?B=?>CF>@>?@CK@=@A@AEDB=@DC:=HDHBE@FHKPHE9>MDCGEAIC6>N@D@?8<:B>C<>8:9=@<>EFDE@BJI@EDF@>9JVQNO?IFJLDCLbFNKGHANIACGA9IH9:AJ?LQJMIDGLSMHCMFCQKPFJR?24DK2LME@DGB7AIHCEDED?GK>CEBCEFIEBFKPEJLJKLNKJLFCGSQLEIFGPNLQVHPLSZRUWT?>WVNHFLCPOHKXDEHFMJIJOMK:@98:74-4""!" "$#$&'&"! #%&$#" #"   !#!$&%  %!!##!)$!$%/3987+/.1?30,-2538<:87>:A/5>3;9@=BA>=BCENSIOE?@FMJMKGHBF?DBFDCGJ@=A@DFA?AE<@?@>CEB?:=;BC=;9>AB<=E?GbCED>FAHGJDKD3:5;=:>A>B4:08@AKQIHAEC@BJD<@FB?G5MQJMNECPJAIfeXTQFGAIGAFB7HLE8?HLHLOIKAESMC?GKJLEGLJP\T=<@HIE>BDIEG@JGRKEHCIDBA>EC5AIGPMQLHBC58GJFEH@CGHLHCDFGECABGKIHOJLMLMNIGHDEPLKGKL73NL;V_KPQ?HIRJELM@9=9WN@?@I=:/%#&! "$#$'*'$'&%('&'%&$#%$ #(+/,%"&("%*%" #&!! ! $)(%+*>=0/:5:7419!+5:14>?8C>A:?>967:;>9:B?JHFHE@EGIGE@AG>CAGBECIF?:DLQOLIBACACB=>=>=;AB>EBC@D?8<>@A@CFD=;<7;JA>=BACB8<6=@GJHCPVFMJG@SJ@GL62AFD>@>BDBC@;/.18=8:B>C@84?>;fR7@?>=;EL>5>@=I-8GQFE6BPC57cfW\PEPK>?E@FTI>@BFHCHJMHPJLJKTOPHGBLIOM@86DJI@?E;ABEBFRLKHDKGA@FE@D?DB@D:UXHMA=@>3ZM<5>DF?BFGFCA@=@A=A@?EJBA?<9BGJIFJHAC>=<@C=CB=A>@:A>A>D@=>E@;@>@:94CI:=?@AC:?>3AB>3C?:;ABC?<584=<9=>?>9649@?=9:39>6JR/.D?9:AM>OHEF@H3GQP?@/@GICRmNKO\REB?<>A:6EFA8DMC@O@IOIJPYRHJHJHIGLHGPU-9B@A=EAHAG@IMKHC@FHBA@2BARB:C<=?CFBDFEFC@>@EIE=8HE=?=9:<;7<=?A@D?=6;D;7REBE@=C?89C;6;BHC=WYLRWMGNI;>;?AO=5=?<6<587:;;?A9A?:=>869:7S<%8?;?D?;=HQPIMGEJ7LCMVQCPNGZeTDPc]HCAE@?HB=EHC@FKELKST^]XJGHAFECGIPMB-=;:;:CD@FBMLKGACKJKEFHGBCMDGFEIEB9.9JG=D:10'$ $#$#$#&%&(-*+)()-,+(*)'),+(&%$%$! !!$%&'&%'$&*&$#%()&#()%!%'!:86:80647638787=7>757;>78<@=?8:>@>C?=?BE>?@>;=GE83>EJ@?<=;9:<89:89>A:=@=>B89=A?;<;7A?:C:89=EOGHVGFRXOEB?>AB:EFB@?KH=>A>=9>4:7<9757;87<;AFKE@<=:ADPIUJ0=EABH>;IFJBDNCH+DUWB4BMJMFAX^JNLGA@5>ABE>:?DMEJMKHBECECAGFIJAJQKLKNGBHDJROEOPOKFVZKQHRNI]ZXBJOPIUPDFOKC.')%!" " #%$#$%&')'&')+,)'(,*,+*)+,*+)($#$&%"!$#"%"!#&%"!!$&'$!01;2/9435423429:8:<76578-29784<=8979:;<=;=:<:9=6>?@;=@;76348:8:;=>;<8@=;9:;4@A78;A>GIA@MQKE?FB=>:4<=MQPIGEMY\WFCBA?BFG@D;DHB@BA<;?=;9=8513.76;:?C7<;<9?>CHI89<=@B?O@FBA;ME1ER[Z-2BDT>DTZRA<>CD:ACDGCFDINMJHB@A>DBEKGLOCGCPFDH=ILGIXR_Xc[PMRjRQ`YSFKNCIMIDOXNTL\MJ=>P>.3.&! !#$%'%&'('('*+,)',-*+*)+,./.,-'$%$#" !$#!"$'&(*,)&" !%$ ! !  ##%/03;51210495:571)/42526;<489=;:8:;<9:567E>580B7126-47:=A=D=A;78I=9CB=98<9@GDBD]HNBAC@=<8>CKSCIGB?7@:854;:281274:8<>7=<:7A?7:>EFEBJD>N>'RakM=ZQB@=SACKC@F9/7>4=9AEHFUJCIQRTLJQNGEMGJEIEUK[LA0BJDCFIBCEB?>BEFCE?ELECEFBAGCDCLJIGCDGF@AB=EC@><>GDG?=?HGBJH?DCGIJEB@M?BFCHKD>?F=BG@ELOQkKVQR]KHPQYSOMHBG@=EPDEcCBA2/,""!"$#$%&')('),+)*+.-+,+,/./-+-./01/-,+&$%$"   !"$!&)*)%!$"! $ $#"$"!!%!'#  $(25/*-*0-.'04261#2087<:9247:@?8:@<8294659<2-)210734=;?J>A:7@:39=>=<;:8=8TSHJ>?=B=<=D@CAE<;>HLIC>@H?=B67DEGHKDB>A@=;?>=;94;8:8:<=;:;=:;?=UM>1BC>HA7;=AKD=PNJHT<M4D)>WL@;JXJPa9>3?P5+=?D7:KFDFHMTKJIMGLJCEDVEUC:;DFGHBEH@AED@=FHOLEHFCDFGADGRPMILKBAKAJFJHD>DABFDFEHGBCI1DCFL@RPHFJDQS\RSNQOTVLB>@>DA6@E/#! ! !"%&%&(*-),+-.-,+*,-.,-,-.,-./,-,+,/-)'(*'()$! ##!"$#%'$#$%'&%"&'%! !#"# #&$&$ "  %'+.)*.+),1<84,1,1459=<>9:7<;7;G?;9842@:3@78)+H5&.4:5/=CA?>B8<4=9>@=8:;CM7LDAC=A@>=:=>LC=:CD@:>=;AEBAELGFE?@B=@><@B>9><=:43;7>@=?=:NUIVQKE@>CA?IKGDQ9597@:7A.5/%6K/)50:;.7>?DEHG@1J7DKB@?>B>?KHFCDEQND>CFEJIB;>;BA;?DKACLBEGBD@>=BA=@=:;468385=@B>BG=7>?B?:@73;<8AILNXSTS9 A#?sN`RIXMFC82;7EF@FC@9HEBCF?DSRGHSPOLACEC@D@JLHBH:BDJFLKICBFDHD@BHFTIJFQOSNGZMHIJEDEIGFCDIOKJNOIE=?@=BAFACF><=?CFGH@GHCMHBD?FJFJHE>OJGKFPCA\LGYVTW>BHA80395=572,1.96794.;94:6?=DF>9=@>B/28410;65D=2B7/DC>B@B@>?@FCACFOH>CEIMGFCB>EA?@CF?D>DCHGEGEC@>@>;:9><7298=ABACDC?JCB;8:37:4;AGNOQLPF(4EGqNP[EMG>D1)=>9K=>@=CD?@CB>=JKFTHQKDEB:9ECGPI?CF;LDCFLGHJGI=@=<>ADFGB@LCFD?B76@?=OABC@HJBFCB:SWIKHaKVR?CA4:-(%  "$&()*),-+-+,.,./.,././10353242458=80/1543/,+('*,*&$%('%#$" $%(-.+-/,-0.,.)*/.24.,(#%)&"&*,'$#$#! ! !$#&.15:;20.-206794-,656743.+.0,>415-683278:6DF=:E<>B25+'48<;?15B+@G98C?@DED<=:?DHDC>B@MIMIED@ECAEBDBA=>AHJKNJEC@?:=<=:;:=?@CACAF@<7968:5HCIFHJIGHEG;@EHFHMKFXMVTNKUKMKLIOFKTMGAB@:GSZSNMKHKHDG?>6;>?=@AB>ACGBIG8>7@I?9?$.AGK=DJA?GXA8RWPWSIGFC&# !"$#$%'+-120.-.-.0-0/0-/012324598647987878<=7458<63-(-.+&%).+*'('$# $*'&*-,-179898740-/-+-)+0*,)&$!%!$)+)*,-*,0'"$"  $/8020123472,+(035487/0'+92+1/615:67:E=:C?>CA<:8@,4DEA>:9A;1C:;=<=@JNKIDEACA>C=>:7B@A?@>@CA?B:1;<;0>?FINOKQP:%9EMTVFCFUGHA?R+=?/8?@A=@B@IHIBDFBMGDEN[N?]<;<-)"$! $"$"$&$%)+.2/31/1/.2/1./321/295797:897:32787;:7578=;431.48930/-+*,*()*)'&'+*&$#%')*-1048;<:3.*'(-0-0-/.)#(,()+(&('()04(%#  #$-:7/4/+,/.0/.%.4143<46./71)1+#6023/9;40:78>C=2H71;=7GE83>4>;9>=9=>=@9B?A=;=>BCFB@BA=<:?><947/@FB43;BJOM%+;P_EM=CDF=`;@HJ7B5?JLC=PDEADNICOWHAGHBDOBOVM:BJ>:=L:9?FDC@DBD>C6PTHFERLBO]K?@*$#$" #+&%$%#&%&*+,/304304202013454567;:5376:<964.,-+*+-./,/+!&+/4931203;A=94.-.3CB>7,*.-+1-.2-*-,),/1/.#     %+/.+)*(*/.+,/'(27-126/92+54+; 07=3/@97:5:78@<6<06=8>VL80=:-3=;34DA4>GA8<@>8?47<9=EA@:649H@=ECA:!G7>FCU?@?ON8BLSECIAPMSTO9:LDB;=F?A>;=C7:=?;DFA:%F9?>FZB@ALT5/($#&%'&%&#&'(+,./46401242146469;89;?>?=;:;98LF749?);7I73?L=>FB:9A<><=>A;AF=@ABA?DBGA69<=@:<>?=@B:>??9BU3:><4/Q6LHGQO?IDIHCGSU>LKN[MXQE0GK:FMKCLUMDUSFHKQELEKHUTNUTKLOHPMGFJVSWRSUNJEBLCGCBNIDAB@AB;DEG8;=8>5;<=9:E5:AC?4.U4MKFVPAJEH@A5%#$')'(+-+-,./102575768;9<=?@A@=BCBA@=<:<>@?@<:9;<>=;<>;:>9845852120.2.-+)'$'*,/451./04>A<>A>9<:3-,-./01.-+(%#)1,)'%$'*1.($"#"$%$!$!%$%*'*(*(/0.),+1+*-1/$&:(4;3F<69:8;9<@D;7B:NCASC=#2?3,A?;<=:CDBFD?BFACFA?@HLKHKHE@>AB@A=IGKB?@>@B?=?C@<;9:9;:;756028>DCABKFHF!+)&2FB=,EL4?;KJHFGQSAGIJIDIMDJCMFDJOUOIUVRLISOGJFNOTU[ICDCGKLTPAMNGAEACB=?CG?=4+%(',/0/),./.,-./2121247478789:;=B?=?BCB@?EDEC?<==@CB?<>?><:>;7>A>=;612787476340/31+*'&$#%(*13.,)+/19A>6:><972.,+,+.1.)'('+1+'#$)*%'-/+(" #%!&%!"#(*+%)*-0,*),0)*-.1.434L;,7*34B<:@=@I>7?BD3:<3 ,.-4?<:8@D:5:>=9:B9>8;=7;>BFD@EJHCAF@C@AFGKQF>@@C@;=?A=;9:@981780503,'4CAC>=?BEKFEC?#)&;IJ<59^]-NKYUKHWXT@E4B<:DMFSCaSEFRC4@'/06F?9CUNFMJKBDMNFE@C@AKGMNMNMPGIUXLILHKNFMJUOMCIELHIKJFCEICDC=?A>6B94=?>74@8?@524GMA?>?BCB?@BD@<;=>8<8528<97548541./1-+(&$&+,-3-+/,-37958=;5/+),/-./1/+$!"$%-4*(,.,('()('$",& $#$#"  & #$& '*'#-3-.67?71:IA60.2*5746;?<;4862=:;A?>?C>:FJF?ADAEB@B@>7>95;:<70<676:3+/+3.)59759BJI?97)>:FKIB2EHGP)C;XYKDXOD>HGIL>YVJE;E>GPNFUJ$>8:B8MXQDGACA@GJFEKJLJCMJEH[RLUPGUMBMRKRJNITIJEDIS@BHNC>MHMFPGD@><:8=787@EB5A?;=?L1C7QXJAVO?=BC5($&(-*14140-,01231234234656789<=>@ADFGHJGECDGABDFCA?@A@A@?DFIFAB>=?@BEC=869<;758965/-32,/.(%#(/1-,/313+)+,1:<;60215.243+/+,')&,1-,)*(')&%!"# %(-&  #%!#! !"$%).3(+(5A9/;C125954=C<84:68AD@BM*,1,509DH7956/8;87<@>7=;:7CE=BCFAF@EBF@B@>H?8=?DE8EFJDKIFC@><98;64:@=74:=<*-52.*%3(4178;ACA@33?FQKAGJH51>_]9GLKW>GFHOLC>?ATOQIDEFEFEGOMINPSLELSTS=;<;9782,-/+*)'.30-/23.031/-,07;60,)('*+.23874+'!$)-.-421)'$" )/,)',&$%&$%,0)'(-, ! %'(&),%/.M*.2792N-41.?:058428:AG4;=2163B?D<;978797=>=;>AD>;7@E?:1=CGBC?D?ILI;:A>9D=?:<8:;8+1EDKGICDMA26\AN=C;>EG>C?=HGSMQ]ONPFJ?GE@PJLOEPDMGAC;BIJCDROGBCFNBE7>:<@7>;3:AB?AG?1VB;=G9;1,%$')+1/23435623134/3464568;<>?@BADFHGMKLNIMOMHIHGFHKHGHKJLIJIFDBCEFHLEDEBCFCA?>;<;7431/-/./235621/-0/1230/0+(+*)*,+*0'#"+0+*)+*)(&()&#$)%!$"%')14,'&'""$!#"#!"+*$%54(.1/.+(3-,3.-:6:6;AFAG@<9;5;C;C8:<:?29/38<7?<64;934:C=C>?>BHM@:@A>=>CDBGA?CABCD<@9:<;=:8=748<96;8<>;AB<80=>?>;23;=<7649/9DLJREFDK@>5AVEUHL+KA?75:EKCJBLPFHSGEFBELRFHYMQJCJDH?@AAD=?1;R?LAH&)&'(+./1359564346568978989=ABCDFEGLMKJNOPRQOQROMPOJLKNPLKOMLIHJIKMQRUSOLHFIFIHC@?=<=;87897101247863032015647<810313/020+*),0+$!#%"!*,*(%#"  "'&',+,*$ "+(%$!%#"&(#!  &'"%5+4/7".%.($).78943=8:;?8?8:=I>9EC@B5989527.7B<6>?9>85485<:8=F=A@BCGEC=A>;6A?AJNGECH@CEB9<:>A81696548<6467BE@A?:=>FCMHIDH:7?KNCHQOJKJFIMJHMOXYMKFSMPHFKLGLREJAHJXNCIHFHGKGCB>9=08<:09;=?=;5CB=@26<697'27?;5?A:?8=9;:<>HJCA:BC?@DA=J?D;B>NM?CAFBEDFAD<;<;32<:468;>;@53A;02;@DKF>I?/2/2>8?EAF?LFGD?B>UG+AEGSH6-;C<0CF1:;7EBGHB=@CNADGJIP>JPKGPAHJOKAEKEHGJKUO?=AKNIBEMOMKFKECAOMIKGD=8,4>28@;9:;>BC;8?7IE-/)'(+.2467:8689:9<;:=?@ACDEFGJHLNOPQSWVXWXYXUWXWXZXVUVWYZWXYXZ[ZXTSTUYZYWPQRQOMKFCFED@:457879;=;5238=>?;9=;3<=>75<8:8:;9@A51:A<9;:=B:<>?BHF=>=<=>ILFGJB@;/23>49;?97=@PO;-9@FJIHGFLJH57-&01E19BKJI9;?SG8-E9SA1/940,\U72;6>=;@A?A@E>?F@JIdIHAGIRHWQC?@6-95;>5<=<3,7;C@38C@=?ADEFGLNLMNOSUTSVWYZ]\]_]_b_^`a`_`_`bca`^]\^`]\Y]_^\]^]YVWTUVPNKIJLIHGEA=7=:9;=>?@:79=CABACFB;58<;40-*)(+& "(+(' ! !$&!"!"%'&*& !).1-(1-""&#(6"&,B+1+1-'01735;347<4RC969B8C854.5:<7;J@583=A>B<9>8:4:8><@C@J?@HGBMFA<76?>.1=1A9;?<>)5KB68SJ@JIGFCFMOMJ<6*%A82GA?9;3>89=@40?<2,=4:0)'),1247678:;:><=<=?=<;@?@F?:;>=0./*.04047>7@B=87EG-549=97=?=96967FCLB@?:;7;?A?C>A@LB@IC5(+B:?IDSLGCADB:7AN2'81/@=43HBANBF\@FQOMNSKHGHJOMEJLNXQOKJOBIJF;@BDJC7UKGQE?DJ=O>IHGL8=40:1,2-;86742,*+/0367;9;<=>?BEFGJIHINOPQRQSTSUY[^]^_`bcfgcdfijikmklonqnkijihfgfedbdcelolhbed`_[_Z\WTPROMJFD@>ABJKEA@FA<;>=?BHMJD;764231/+)&('&%"%($"#$# $! !"%,'#"*0*,*(.'+')(/4-,/)%'&*'" #&%$)/1.'13-,:43=?:7@>70:F:07?A:BA=:9=?4;7@?G8;C9<=;198;?@4BF?DA:=C;E?HBGA>AIFB@C@=<90<9164=DIDA>32=>2'SD@9?B1*4>9,-?@ABCEGHILKJOQSWUVW[]^`bdbabcdefhikmomonosrprtqptsponmkjihghjnokgifdbcb`_^ZYWTSQPMIHFBEHJLFABD@:<;<=CGFDA?82/./3530,)%&%$%#"%"#%$ !!"# &$%&#"'+)-,1=7./)'&+)+,&0+"# "&##(3' *4/)/:279>@=;:389?8:6=FGK4:8.;CB@923:=?1:?:B@;@9>K>EC@H8CFEA<>8735=52:2)156495<6:>9DIHU;HN?>E7.HL@BA@DIC83*21LKE+358/3FG;2NDCAH8NF@HNONIFMPMSCIFAKSVKLGSYLTHI:APQPJILE?=NGTVHEGN;=FGE?DHFIC@431'*/*.;1,'+,-/01347<>?>?>?@ABCDGHIKMNQPRWTXZ[\^`adghfeghjklnqstsrtuyxuvzytuwtstponpsqpmonljlmljhedeb^_^ZXWVRPLJGFILKHGDA?;>;>=?><;72/-*-23.*'%)%"#"  ! !()$ %'4728960(.0&'%*%$'-&# $)!"&#$)3.)&0,:93;/1637?=>=6<=<=67;25CBA?A><;2C@GLD@B>F<9>FB?@DHGCD;48.-806@?9(,<:@<@8697@KEFDKG4=D81=EC)53BA1,8;08PWB $*5FE>?@AIM>9AGRTIMPTORIKD@DNHMDN[ONYJODOPKPOSVK?FILZcKJFQL:>@E?;ACGIEAGA71,#'-<2/)*,03547:>?A@CBAC@ACFILNPRWZYVY[\^`adcfgkonljmnoqsrstwyxz}~}{}~|zxzyvxywsutvroqopqolnopmife`bZVRPNOLMLIHGDA?=:>AB=;?B=9397/2=<>9:BET7=;:E<@?BKBA<:=DH]FBADL>4?@>8=BMEF@9;6+03EB:@B5?4;57:IGLKJID;69;40AFAD=FJ?5:<;3837=23:A:/4853:CFE79FKEINJQOKSQD?MSLHXSObILVOLFLMKMLKF?HBKTF>P9JLJA@?@ED@DBFA:;8>8'%)-,)+0478:>ABDCECDIJNMRQSUVYZY]abdghihilmpqnoqstuvwxwy~|}~}z{}{vywuwxsqstsqrstplkjgded]XWXWTSTVWPNLIEB@?:8;=?<;9:98;863135/)&%$%-0&#"&$"%" ! ! $/0).-*(087>?1%$! !*-'#$"  #%(%#$406;20-)582,4894>9;D7A9630<>D8D:aO4B=;9A<@A>?5=:ADK2D=AC>H@KF@>@DB42869;FJAB:53?EPEDLM=:43;E7@L;ACE@B>:A47%/A@4/<97EJ>+9N?5NPBDEF+1@CJCQNIOIUB0:9?JHFGNUI\_?LPNHPNQPROLHA<@:AM?2TDFJB?F=@>C:67:0,.5470,)+.13678;@BDEGHILMPSWXZ[\Z^agfegklmnptusqtvwxz{~}~‚ƒ€}z{|{|zywxwvtsvupomhigfdba^_^ZYZYXTPNMNKJDC?<>?B>;989:89853152,)'$'/45&!%!$ " $!#$ "')-/(,/5,27,%'($ %)43*$" (+, !+,5<7/5273".293=9E=?Y61A9@>ABD?>;4:46C?.DM:KC?A<=D@:=;B793C19=@GL?>F91<>301<.?F5C>@=CE:8@8G25;AD@9:BF;fPSKC:=5&5HDHMOMKSUXO@7F;EIPDNKB@9=@AFC>;:8;:76502.+)$!*69+"  '$!! ! "! &-&%&(,-262+,.(#"&-,/)%! #$# )''+'.8<3,-/&497><7@?H@>629>8;@><>F+&?BDB>ECB>8@?FC;=7;:C6;>?A?2*.3>:C>;CHACKD:>28FD;8>A@?6MJO93>3.;CDIMIMINRORU=INICKQLPLN8ILWTIVUNM@JOKLQGAHJOIRJKB39?A9>@<>1-)+.(-*,/1369:>ACEHJLMLMNPQSTWX]_`abeghmnortuxyxwy{|…ËŽŽ‹‰‡ƒ‚~|{xzyxwuwxutronqmjeda_\[ZYXTPORUSPONHDADA@?>=:676541230.,*(*),%!"#&'"  !$!$"  !%$"(/.2.'%&%$#&373)$ !%$'" '%(*&+7-<,'+,'(218;9<7D=D87A?8:?B;?=@.+@AH9BF=A78C@AEC7C>HELHICA76>D9BECD@65:<74AHEAEC<>JIB;QF:><05/@7<87/69N?=E7KUG@>?@FG@4,4NMP4?>J8FD?B?<+)BM>4H.;>?>FMEHOTFS[GIVPCOMIMRMS>RVHNTJEMQBE@BJLCGQFIEA5>9D;@:?<7.,0-+*,13689;?CEGHJLMOPQRTVX\^`cdcdeginoqrtuwy{}|}„Ê‹“ė•’đ†~{|{z{}|zwtrmkhefba_\[YXVUTSWXURLFEFCA@>?=9757:9795320/.)("" #! ")'!"!$! #%$ %1286)&!&+-+& #!")'# ! %)%#'51&/)'-0-1953=@F=;BE@A8=E;<6;>FBAKHFI=;E@DHD<:C=@=:.@N6<@9?>:GFIA16>3ABC98>;MTMCYRIPJDIPLONGLHTSOUOPTVTZURTKFLX^KUNDI8D?4<@9A>97:=A@<40/+*+&!$'&!# !" % "%# $')12-),&!$&*+&#!"&(# #  %'(#!0/%*&,12-'-7A:7=G8=?:9=<>:;=3@AB>D?BDCEKEH=BIXIQMEFA=E8:F?G6;@>9<:=;>7=J@E?CNJE@95F869BE;=A:6@;DL=6FA?<;?HNEPJKDCGHNFWRUI:F?;BEG=BNG@G=<3>5AG=D@DACG:89C;:9:?IEF9<14;2# DL?=?;!9JF?5/>/9?@GD3E@FKHXTOLKJM\PITZ?DWOM\VWUZQR\ZNVSKLSROSOCA9>9820/987)+-1478<=ADHIKNPTVXY[\`abfhilnpqstxz}~…–™œĞ¡¡ġŸÞ›•ˆÂ}{yzvropokifgb`_^_^YXUTRPOPLHEDCBFB><;<=;879;90+*+('#"&'('%&!#)(  #! "!#! #!#&# $,/(  $(&+,& #!#! $%$  %'!(!,+.,42%89;53AD=?;87HE8=K7-B?BIDCGCAKIFDGDCLPLPVFA?EA;:AGQIF>9:8<@C@DH@MI?=FG8EBCADB?>@>;<:3.+*%! ! !$#"#%-92% " %+& #   !$#%(&#"!   " $%"!$&(&! "%!$!+, "()*$I31<:;A9?7C?:=<42?EGFCGD@CA?B?ABGAGHUQIKDEI?C:DIPE;7AEDM;CKEAFNF?D>@?8LB?;@FENSHA>83B-HSA>BKB:EBGXPMI?3 TJ;2?>DFA4><;EDE>FA:E;J;E:2;=9?:56A=EHDNDGSJEJPFAH^]cVRNPTLRSKREPHKFORFA;?23')*.589;>CEGJLOQWXZ^_bdfhjmpruxzy|}~ž¢¤¥¦˧ä¢ÞŽŠ~}|zurpqolkidfgeca\ZYZVSTROMIGFDHJFCBDFGDABGFE@<3.+($!"$"%'"!%/'!"#!'0.$ &$!"!  "!%&)(')*.'$%$ # " #!#" !/*0*!$+&*$+)3:6=<19=98@:64DKIB@?BC?@ECB@EHDJWKMNAJ>?@A8JONEF@ACDJCNLJGCEDHE>8=COC:;@GLPF??8?HNDE97ER95/CA@MC:3D:9=@?B=5;?CEVPA89@?ACA=40/>E@D@QKOHTLDFL\UZJNLJMDJRJKLIGOIKEA38*-.)(+/379;@AEGKLOQSW[]acdgiloqtvz|‰¦اæ¢ĠÄ}{xutsrqnpmhgihgeb`_]^\XZXTQLHFEFEDCBCDHGFDA@BD>:2*),+*'&(*%&()*$ ! "&(#!&" #"!(030(),)-*!"&("  &3;/%#',*-,+&)A;61:<;<@798FEG>=<:B:AF>AB?G@JLGQDGC?F<9<>CHQNDCGDF=IMTKHJIMOE;>ED?96DFOFC;A@?=10A=8ODAEHPD:G=KUJ>=@LD79DAF2=:;C745AEC?=8/0.0.*(&#"#&)&  !&"  $&%'! $*3/( "'%()&%)&#   -("'$'( #''"*.1/9?=D;823EAE?BG;?C>D8?=AFEILOCAFAKMD@BFEJPOMHIHEDITNF>@JI=>I=>B9>?@JHG=LJK>856'=GAO^=G?9CNA2KAG:DFRFSJ>4C:E?79=END79*BTCEGJMOPQUY\`edhlnqtxz{¥駦¢à~}|{wvwusqlifedb`^ZYWUX[XTUWVOJIJKJHECDLKLID;:<>CA93/,/1*(" $('%!#'%$)+*%! $+' #"!(.-%%$"!""&(*&( #$ ! $ " $+&"$(-#(!!/=@;39482=A@;=<>=@@EFERPNIQ?COC8AJ=FAMKPNJCAKIOCGECJBIA?=:7A?KIJGDGAK057AH+MJBJ6?O(8<=C=5:LBCGCI9BAB8:29592*4?IM_LJLG>PZHQFSIPRPJRSCHKJLT@IKH039/%',/17:=?BEGKNQRSX[_cefkortv|~‹¡ž‘}zyzxrqpolihgedb_]ZXWVWXURUWQPKJMORNJHIPMIFD<>=ADB:61/32)/0/'#$&*'%$)/-+-'&$(+('#! %"!'/-&#$# #*,'%"! # $# .%&')%" $"%%45;E=9:857D<@8A=FAKQEMWB?LCG>BN>OABGON?BHE@?C>?;>B=]R>=B>5D;>JKBIA:FDSPMR@B29KWSOTNE79;17>:AE879JA@G>HQZYQSOAQWJOSQRHLKJ@9GQMRICDB725)$(-328<=@CFILOQSWY\`dglortx}—¢𧥤—“Ë~|{zyxtqpomkihgfc`^]\ZYZYXVTSUTMLJKPSTSQMKIJOKBC>@GCAFE?A:65/(.3/-)$&'#%(,+'*&%()(%$"# $ $' "'*()! #&%&"#!%'"   "! #  !  "#%*'" %+/+0,6@A?8B;C=G?G>?DC=4;IDTOCKJH3?>;5DH8?;7>F>6FC6=B<7<9489?IE*C@AHGA=B?BFJOQRSVZ^adhlquxz—œ˜Ó‹ƒ}{zxvtqrspokiheca`_^\[\[YWTPNQOUSOMJGHJE@DILID?;?><;4-,.-.1/&!$(,.-*'#%"$')+,('&$#!#%"!"#!)*&$" #$')%"$&" ! !%# !# #"" !"%!! !#%'%&'(-0(5=>8B3;<7ABG@><:@>=;=E@HBLDJHKFHCQC@HIUQR[WVGOBN:A=46BE=;5;>@C?8?=;@<59?ADE@,R:98>LC>=MBEFE>:AEDGPNVD1+JEXJLBJ106*046EC9392:+5BDLIMLH>?KIJOGJBIEIBH=9?9<;/&),149;=CDFKRTUW[_cfjnrvz|¤ž›˜“}|{ywvwtqpqnkjijieda^\][XVWTPOQPQXUPNLFEGDCFMPKG@>8=>:9625/.0.*%&.52/-(%($"$'(*/,(%!%"!%"! "-%"*,"!"$'$&!"#!" #$#%&$# $)'! $%#"! #$&%)%#&*%" $'! "(,-2917:43.7;D5;=>A>829;>BHRNFAC?>A?#F9>E8D1?8,@JCB98ABSAN@;DC>IFW9;468;89?AHSP&2ARNMERMOWJQHMOKHVE@JD=:CA0)('-1*-.-+)'#%#&)+),&!&%#$"3:2(% #&*)% !"#$ "&% # !" $*%" # #%&(%$"*31)#+,)( "!! %).89&*:;3=?DC@A?BDJI>@HM?OIKMKE@Q?G=ATLGPObOYP9743=9>AH->DMIF86878@BIHJIFC?97#.7=KC0<0@:,bMNI?9=@MC>ODJGKA<>C=<@AFG?3)"(+&$'&',('(%&+,%$#!#$"  .8/+)! "&$.+)*&%&$!#%'#!"$"   &# &,43/-% ($ !#"&*)"$+,2=:C?>F>EDA@END@IFKBLIJC?OECQPGL]TaZE=D4C=2<=>KDAC:;.376?GNPECB<>89FCJ@9;>EMG06'2CBND@;J:=963=718?<8:EKJFSNLGRUMPUOPGC<98FHA9- "$+.458:@DBA<98521)%'*)'*(./3.+'%*,(! !&'#"$+1+*%#')(*1+'(')&!#" #"# !" ! !%$%)*0+,#! &"("&'($+570:<78>@LCBCIH>?89DQJHBENDKCGEKPDEZRGR]WYKJ>;H58.?;KDJMOPE:1(/@1*5O@=J:=A@A7;*=DUMSODC>?902=61:;1689A9:7=ADAJCBNMDK\KOGTI=@>BDB:5(!&*/128<@BHKNRY^_dfhlptuw|ŧ£ •}{yxvsrqomkjkiljedb`\YWUTRPQNLMIFHIHEDGDABA=@ILGC>@CD@874-).0&"#$)/631,+%#$!!(+&()-1*%#$'(-(&'&#%$%#$"  "! ! %#$#%,/.+% "!  #'+*12,5:4HA>D;=;5EDJeY>TD0DA=>;@B;>D91$ !',.27=?BHMNRZ_adijnruyzǧ£œ~}~|xwuspnlilkikgca_[WUSTVSRQRQLJLKLMJGFHFECMND><@KPIE?ITRC8?A5.42(" '(/61+') !"!"#)+'%+120/+%$('('+.)'"#$%#!#!" "&#!"&-+-)%$%#   !"('%)'*-3746;68C>BCA=JDHFHODPIJEQFIHQMFX][THPBDIF?72>?NPGLPQ='4EBCF>H@CHJA;>!:?@4B@?2>91TF;A9=6.-,716>?8:=5;>581?KABJ?KGCK?A8;=78,#"(,-/18:@BGLORY^adhlosuzȧ~}~|wvuspokfikjie`a_[XTSTVURQTURLIKOMOMKIKJKLHGDCHLKDACHMIFJS`VA:BH>731-& (.560)'$!"  "#"&'#)+-'$&+-*()/-)'!$%(! #$!#%&)+*$"%*&$ !  "#"!$#%23/:46?:=D=<:@A?AKDAFH>HAEIROVGOLJYVTPWIHIRE=/5:>GIKTJ@*,1>=CI=@G>CLPLIAB17/*3*39?1QU\Q>=7-B-&+:OJB>EH9BE9+74?A<86:CB;0BDBC:<;AB@($(,-0387>BEKPRW^`djlruwz~ɧ¥~}~|zvutrpmiehjihd`_^[WUTUSQPQROLNSPNOMLKIGEIHKIHA?IHEFGHOcn[IAG73-)(*/32.(&!#!$#!#$"! !#!!#(+(&(.(*#" $# !!   # !%$#'#%'(&#&)'&%$#!  (,&!&1,181895<97RIJLFMXPKUd_bVEWGYADM3:CMOYOCA#4?@>EOC8CREDTNMAC0?./N8?;F@LV[R=KE>H4$@SRI?3C24KC;DIGTGD<>157<,+*/>34&!-<:Q@;<:C;?CB>:@;H8ABCA<:<3,$!(+,1376=AHKPSW`aejotwzʧ¥‘}|wtrqpnlihiklnmhfba_^]_\XTSPMLNOQTPMLMKNHCFMKEBADJI=;A@HOSLE?B>:3/*('*/76)#$#!%"$%#"! "! " $&*(#(%&#% " ! "! ! %-' "$!*+#&'$&%&)&)$#$%  $&#)-,(-.4059@9=8;ADICBCIQCFKO]GHPF?EhYEK7HIQ\AH9*=@>HD:6,6;A>B@JB@CICIQLKE<%0;2ND7F:E>MUT=@?>AC6ED@>;9A1=@;>?EC:?C<>@5GADF=?@B=E@?97=<=;698950-*&*1,+'$%!"%$#&$! !  %)%&$&"$&#!"!"#$# #+)&!# !$%$'&'+,-)%'%" "$+',*/05/:5=10879@I98=<@FELAEXURHUJKPOU[LADJCJTJK2+=6;8-+1262;@AKFHKGA.<:9>G>:>9BCB?51@D58>4+/$69;39?>E@;A@CD?=BF@9:@ADA=;45894/+/.5;8+)%#"!$#$'#"$#" "!#%&!%')!!" "! !!" %&%"!%" "(352,)*'  !  )&(*/1.68C0798=A;>CGENBE@ABQOSLQMQaPUJYGB=AHOZM60O6?3#*136>?<>EIENMJ@JE?CBDC7=JG@A)GDCTEA<>BD<:-IN@E8KD@A>3AC>=B>8D=>E9A<:8BD<4>1 !#%*-./69=@CGLSW^ekmrx~ͧ£¡•Ž|}{xvspomnmhgedbca_]Z[WRPMKNOQNIHIKHGEDFHIHC=>?CG?9?FJKEFC:/1:=60287:;9/+&# "$&'&$&'$ "!"#(% #& " ! !'%""'$"%.10643-)&%!#!      "$*,-0(9:?2?<><7<:IWVNCNEKGRVQdDHIP@;C<=SP63H.6)1=4:@>;ADLRSNB@J>FIGFC IHJ?@>ANH>=9;28:<76:UHB=-ILGHGA5H85AC9:A9<@?:BR@7:8684>8)128=68;8>:;>B:@=@76." %)+-/39=?BGMSY^eknrx~̧¤Ÿ~}~{wvuqnlklmlgdec`a`^_]ZYSQOPRNKMLJEHLIHFHFJKHA?AC@?:=AED>;84/7@=5.6;643/,+*(%$%(,+)%#  !$')#!$#"%!"!"!"#&" !#$#"%.,+/01-+&%$#    $(&+-205684=:48@4=G-#D>+$0BC;:6A9AF@KXVJBPQHEDB<RMC@ALID?BB?;F=CB:HG>@A67:<871%5/6.8E6>62' !"(+,/34=?BELSY_elot{¦˧¦¤á‡~}{wusqnlnmjfdbdec_\^]\^][\XRPOPQNKIGFDFIHGDGDCBE@HD@:759<:;8632.3<:7=741/,/-,.*)-,+($ !#$!$#!"#)#" &%+'&!#'# ! "'" !#$#%#"#&-/+&+-&(/'#%#!    #%-,08712198658=F$ER3;4EC>B<>7NLFJD>JONCEAQC>@QJTOFGC58B=OP;:5Q@I?CSMN?@BE537@?J>;=FB7;07F?:4;><;891:3;71?;:=FD;<8<29' #(+,+049>AFNSZ`emrx}¥̧¥¢~}|zxvurpomnkhed^\]\^_]_[VPNMHJFDCBACEFED><=A<:@B?=605;9864:D>2024KB;7941-./,)*,(# $%)&"$!%# &$,)'&# ! " "%"! "#!# !),&#&)%!$"%,0)$)(&(/.+&"$% "   (0*,4'285<96AFHIKITNJHPSKSPWUCF?BA@=6E6:+BR=4>7DCHC+4>CM@EA@SND96CB8>A6@;86L?:IC=7D=>B<8@>9B>=.LK;249<;=7,4:9>:179679:5:D><@?ACHID;:@<>?=:9468;8:945CVK:71,09741/02/,)'(*+'&(%# $&$&'#" ! !"#%*)'*"%#$  $"! "$" $1.&"#"$&!%  #',-,'('(',-*%$&$%"$#   ')-.5807:F=BC;>:0DG8B@JN[V[\]WMKA?KA@C7LAJC>:6BABKH@8$;@SFKAEOIBJRTH:<51@J@A:A>@:>657;<67?GBH<5?JZ\O>56SL95:2$.,48=59C6/:>;25<92<=9>CB<)%$*)*+.479<@IMRV\dks{Χ£‹}|{|{xuvrpojghihijhdbacaba\WZYSNPOJGHGCA@<9;?AFHB<==5641:;8=CH?B@FIUQB<;GPH=A<2%&-.5:5683,>=985:;@A:'"'*),03479?GNPU]djq{ך ‹~}{zywtrtokjgfhfefgcabceb`_^]YW]ZTPSTLJIGCA@>:?>=;:87964;COG=ABDENM?L@MSPOELAK2(PXHK=DQCBAF<8/49IGHG@E=C9<;<7486:4>6D><>:AC=?=?=:8:;:9<:768:65:@I>57=?HG>950/-./0#%-/+,',),(#"! "!$&#"%$#"$'(01,%$%"#!!#$#&$! $)  )&" ##%' )'!"!"#"!"%)&$%$! #$   ,87/279636;=DPHLH5?CKHADGKJFOKIADA/:DG454JLPCH5L@106FSND4&:AK@ST\MHBPM6-8BC:>;B:?B5839<48A.434:?@>B;AE:=;8$/5@RJTG8##"%(&+,.257<@KMX\ahnu}Χ£›˜„~|xutusnokifefecdb`_\]_b_^]^ZRKJLEA@>;?B@?=>;534=:9?@<854=C>32/647>@:>C=73.-+-1.$)-.)-+,*(+&%#$"!"%#$%('%'"# &$&-2.*%"!$(%$%&$!#,& #")(&%$ #'#$##%'+$  !!!"#&*&"$"#!   +2+1475=F<:?AB;/GJMH?HEHGDKQKSI9;068@LPUK?-498@>IaZ^F=+GS@BWMSKT^]W8BG@CB>89;7>9428587684=6;@?@K?:F:AFGEHKRMI;FP=76;>793+,0-3/81(78=?7/  #%+)+)-1467@?>?>98=?>=><61:962145;2>NCQZKM692DEKZdUH?-=D687;:725438>05=@9:;>FC:><6AO>H?FGMDG;AD?09LJ;31*-3024;/4=:60 # %()*+,0356;?IMS[adkrzמ›šŠ~|zwusqrqmijhfcbadeda][]_\Z^c_Y[^\WRMIGFEC=<=<87=<9697/384./3:EB;<346256/.0-+*,*/,*)+$%')#$%##  ',')'#$%$%+,.'%"'%)%$%$&'(%'(&"($"'&')'$! #&($ !#!! &,.2,#"   )(0:=<>?7?E=H?GJ=CLKRQJPIDIM?REGIEHMj[QUGNPHCVQK?B?8JSRNJFKNUQJGI,9@?;?:;<58485<3<18>6?EA:?7AHG?<9;8:<9:@A?=9:81016;6/2,6DNK?>6734501/*(-+-1,*),&'$#$%#%$"! "&)*)!!*%'%.-*')$"#"()$!#$ &'(%'%'*)*($)(*%#" !#%&!""!#%+,+($#  (647:>=8<:;BMH@;HEDB>?<:;>;>BC>;:<835469678AMKD=?>A<:943/0,-0-/-()+,()(&#'*)'#!"$&'+&$#%*'(*,51)()(&%+*%$#$#!"$%$%'&(+&()&('% ! !$&%$!"  "!$"!'%($  "    -17?>989?EAKH?>AJKFLMPFBPLKPKZVRWQMQRQLA?IKUJH@F358:;:49?69:7:8:;<@?:@?=@?:98<:7978:C;576032-103,),+*)'&%+*'$" " #',(&#)%&()1:4*')*&)(,&%" ""!#!'(%)&)*&($ !$#%*&$!!"! !  !$'#"$"  ,:?:4=A>B?D=?A?JNHNMOLV@=KEBJQRUQURGB8FLFNICOC8;>2:4=8:69;4=74<.?89@563=;:@>9GHB7$"6:09;>.69C5MS<4>:&!"%$'+,/135:DHLV[ails}ך|{|{wtrsplkigeda_`_\YWXZ]a_[XUQLJKJIE?<:9=?@A>=>B@<>:;<;78757;98:96=5,.48586;5-203232/+)./)*('*)*&$ ! #+(&$ !%-0871/)'*)&%$!# $#&')(*%(+*)'&)*/*'$!"%!$ "!$" !"  0>1:;9ELG>OF9LTJ@BDIMLPKJLDG<=F7:62145378;846?8<16352745359F=598:><>LA<=.497@A701:6&L;UJ?% !$&'*.01248CGJQZ_ekr}ͧ¦£”•|{z{ztqonlihgfecbcb^_^\ZXVWVY[_^YWSNKILPOLIGEBA?=@?:8:=<>@BAB?<;>=68985890',-*),0-+*.-.124.,+(/'+()+*,)%$%&%!"!%"!$"%+/27;6)+,'! !& "!"  &"()+)('+()!#$,-/1,.0.)#$&($! "!"! !   #86<=<7CDLEGRJQKLGMHESACQGK>K@MYIHFM>FEMSEDJ4K[KI7CHIFNMIMOPHI49;D8=6,1;>462821863642.50278=858:8=9>GHF:@>517+579@;*"#$&',/21267378@G@;7<6DID7C<>@C9/32%:69?+"!"#').124;CFMU[ainw~̧£€}zyzxwtmjkjgedcb^_`a[Z[XWXYWVSRSXWXZYZYTPLKLKGHIJIFB?<97568:8;=<>@<:C<954304:65.',0/-,-*',/,4961,&(,('.)%$! $" "$&! "'$!%,',47:-+'*)"$ $%(%$%'*%)%(,*+(!(0340/(#"!')' ! %'$!#  "1675:9F@CFDAJQZRCAFMKMIGHF\VDLXRCNPKSJCLSQWMGSPULQLOQJMJIK)=BK=830/348610.+.8:246376@GE@49;7@?4DE8LG@=4<8GF?4/873650. !#&*+01249BFLRW]fmr{̧͋~}{xvwtsojhjgeca`^\^_YZ\XTUXUTQTWUTUQPOKGEGIJEA?;6565869<57B@<9843/8?:6/,.861*&'*,-326964*'.-(#%&#"!$ # #$&$!&(&)-01.485.50-)'%"')'%*-'*&)+,*'%(01/.+.-)#$$(&" $!    #! !'#$"  '0347;FAFCFKS^TFGECJC?DLTIKSO>CKNVBIKDRWMHMURNSMYQJKXPFGC!<:=51)/05;3420/45304,3>97=GFO?8<6578;=O<6GD@8;?)8>63=>715- "&*+-04;@CGNUZakrzͧˆ}{ywtsrponkecdec`\^][\^]Z\]XSVYUTSOQTUSTUTRQPRNIEFJKHGJKEA@;8676579:>94QZcFPSAKFBPA;LGCAXDFMPRMWQIUQH@>QIO[Y\UNSIA?996>2423.52647@/-@C8.97568E@DFGF4;<6494BF6,@DJPT]enz}ͧ…‘zwurpomkjic_b^Z]^[YZYWXVSWYTSQNPRTVYVRSMHFEGJGKLD@A<;96579;=@>85?<97684210892:=CH:345.-*&%)%)*)/+&$()*$'*#%+(" %+&#'+028;:;/(*/2*%('-/74*!$%#)(&.),-,+0-*26<:3/*.+'"#&*(""# ! !"(" &$&$  +/7=:AC@IHFT\RNLK:AC:AUDH8=AMKVGWEZWFMIOYQZXOFNMGYRHEGEAKBKL=<+*'4.3242.4@;:68:6765878:14935?>FD=:2-,&#(##%')%#$)/+()*)'" '&(%$"!$)$%+.05:<7)+'0,'10/450#%/&+7)/02.*3.+053101-/2+-%.4*$#!!"! #$"#'"'&  68@5>@9;>=EHM^HDENLPJB)?C?>EBLIMTHIT\GFV\VSNLNDIPKNUQRL<59H<@B590*+37-(04>:52*+)319A4<6:64.5<=9?D2143857/+-9(/,&+  "%*,+-149@FHNU\cjt~Χ¤˜„}ytomnmkhg`^]\YWXY[ZTSTQOSPLJIHLRXVRPKHIF@BDFGHIKH?BC;6578=;9687<:986572/5:547@B=DFD<51/+%($ #),.-&%'./+0.*'($!&#&'$#$ (&"'*$+3689,)-'%-.-42140'+-)0314.21(1./24.-20.1*'+2-'# "## !  $!"(*# $! 6@?FC=>8GBJEI6DJaUJ<2OG5CLELFIFJKbQMLV`YSPSNMNUOTNILEDLZ5973.045,.74E4;2(*(5638:=>=;@=;79;5?;A965687/07*/% "$&-/*,/37>DHMRY_glxΧ¢†~}{yvrpomjkgfgd]\[YX[XQRQPONQONKLINSVQMJGDFBFGBCDEGHIG?:46858<;94789<:6578136=525C@CIK=61/1,)($)*-10+,(+-.14.*)&%#(#&%)#"(%"!)&$276/-&.-.,284767/()&+5;/+1(,1,-1621)/.-,2-(-,&('%!!" "  %*'$ #$#$"  $>A<>B@EB<@EO6@TZN?6IH?EDADFD=95678<;<;694595658:8950/,030&(#%$%"!"!  ! !&(%*)    -42-0<,=>IB3@JD6@F5KCJTL]m\[WgRPJQXYURM^EKQ<653.-25-1)$QG/05@74A>97;65<;8>;68:89363#-74"-(#!"!"'),/05<>EJX\`cip{᧦ǞƟàơàŸžžÝ„|{y|wqopmlihda`_`aZTUZUWVTVZVRQRQMLNPTVOJMLHMGCA@>?><=>=<=>=753145784686524252465356974:9;9671,-2,&*-(+-0)$*-012.0.+*(#&-,)*+&(*+,)+'345-+-090.*.4:<91.1-/,/=;<267982/8(-846-152*'%+$!# "%&$&#" ! !)+$"#)"  (6387/H8B7DHJC7EUALIJNHIGKQV>DRWQJfey^OS[XINPUM[R9RQ+5>.+1)-6.-&),/:0&+/02121482/.579>64@6862/462(*5:4*6."%"!'(*-/4:=<7/010/.0./0/./././-.-/2101/0/-+.-*,)('(+,-.-.+)*(+)*+*(')*-,+*,-+)-+/.+*-./+0640397:351,03621-.94+)(' #$%'+.&# !  !$! !!")(# !$%!   +7931A75:EF@EBUNFILEGDNQKSV08GQTRHSejbQZPOSNSFe`H9XM684,.3,2A6,0-"&(+*-$(3.'&/843>2:6/16C625/3642.362;&&'!$%)+-09;@FISW[ahlt᧦KMNPQPRVWY[^_adhihgda\YWTQPMKHGDCBCBCDBABCDBCJILORY]glnjihkjlkb[XY\YUTSQPRSNOPMJKLMNPOLQTRHDFHFGIGBA@>?@?:37898679;97676786986565654565434354320120123452101310/132/./0./4/,-21.-./.-./0/173719:7:<;41.-5721/6;2-/,)&$&(+-13' "$ #""(!! ! #!$,+)$" #%   !6-,47;B5=9:ANKRQEHIPViWR4/1.71/<=7.5+,+074/*/4&!/&27:6B3:A976>?45@6>29=621+ &(&!($'*+/2:=DFKPV[djnw⧓`_bdcehikmnrtvyzxvusqkjhfdca^\[XVTSQONMLJGFDB@?=<>=:6DHJLKLKHFGJIFECEIHEDEIGCDEFEDBDFDCA@?@B?CECB@ACDCEDA=ABCA?<>A>;B>:9=;:<9:9;8:89A?ACA>@BED;=9=A=9;@B>784/120138=:-!# "&)(!"$ ! ! "#"$*)&$#!#$"!$!    %1+,2<8:>7BDKDMNTLA@JD[]IL:JVZU\U_nwpeZYVTMOXUVWNUSP>04:37>698.1253/23/2010,12965E<=<9;D?=>646<4+ &*("'%',.38=<:;BGIJNMNSZUTVUPSNOPKIKMLKJKQOHCBCBA@>ADA?>:;9N\^ac`d_^Z^XVWYVTUTSXYUVTYWYZYTSYRQSQRQPWVONRURYSOPQTX]VQPNOVUSVOPMPRKMOLJIJONHFGHKIKGFEJMABDJKTSNIHLJNOHGIJKGBGKFDB;6;:;@FIF2#$#"$(!$"!  ! !"#%$')+%$!%(#$)(#   #.:78=8@F8=JLRFHRO`gGBHhc\bnjruriZQPSOQVRPSE[PZ457962645-;4+./,4,&)380+/2(4?81?E?5@<@=CD5/.)31 $*'#'(*,027;ADMQXZcimu⧦~’˜‚€zvwvurpkigcb_ZVUSQPLJIGCDA?><=@ABAEHLOQNOJHIKMLJILPMGCBA?>CDB?<;>=Lmpwtrtmkjptigdba`^`hbaiheb_`dfldadc\`a_blb\]\b`b[YZ\aine]\_^_e_^aZ[gcY^ZUWUVZ_VYWPOQMPTWONTVQJKMQSZf\PKPURYPJPSRJLTULPLJF@DAFQTP>'#!'*'%$#$%!"#!"&%#*)%#&'!$%#(!   )@6&-+6AE64ESCEBGFJHZE!7PX]Z^bh~pyc]Zg_JQFNSUY]FWP[A0.2,/40)$&")&'+0#%+->?7-17:89259892:@7?BIPRV^fkow䧐¢¡§Ÿ˜“’Ì|{|urolmjgfd^ZXUSQPLGEC?:;9;?CGIHIMLKONKGEDBA?@BDB?AEBA@:=?=Dr|zxwvu~olqnmosjmsopkilopokikfeomhmnlmgfhlnflojhgehp}xlfigfknqmdedejwebjidajfZ`YZ[VT[YWUX]^T[`e^b[TV_db`c\VTUc`WVPKHRUYVF-+)'*-/23#%'"#%# $%&"$&)&*#"$(&#&"   >%#3+4571HLBMGOPVE<2,8HWFNYwp{kZnZ_ZL[SX\R_[TQPU..,35/152')-,/-'06A832>6=8.9:292585B2+% "#%&'-0/18;<@ELPZ`fmsy䧟åا¤£ĜŒ}|yz}ztqngecb\XTOKHGA><;:9<>AFIKLKMJHFDA@ACB@BA?=;>@>GJAGC;2*LhUJXO[Sbv_V^P]PSZXa^]VTN;32727134/'*,01+&-38:246304147:3<85<539=:9<32<0+ !#"$%&),./38:=DGINW^bhot䧢০禧¦†{xtomljc`[WSQPLGEB?=:987;=BFIMKEDEBABA@A@>@=:@CBA@ADBA?A?>AB><=?C;H{wzy{rwqrupmrqzuplmomv|smokrhlmgiehjmqhafhikjlkihijpkckpkiroigbhcbco_X[Ycac_pflnf_duwhihdrqzvwujedlsmlfic_[ZVWVWKTX[aJ5*#'-.#-067/'(% !#" ! " #$"$%+,)')'%#"$($ *#"  )#'.>.0?JBED@C=MC90(%+,$,+/50*'()% "!&$"#$+.,+)&$)$#!'%"')!$"!"  &A647HLHFCDH5>FGVR_VNQTR[YWFRVZ^MQYZQZ\RPZ_&/1.:2=1635:4/*/-.#"/./+,$5.26-3>9;37109832" /(%&)*./14698=FKOUW_dfnx秓æꧥç¢ç¡‚~wsrtsrnmqkfb]ZWQMHC>974347=EGE@AD@<:>DHFCB>dwqnlopsuqpkinmjv}mdhlfgh^abk]boijkcfik`fedlmhm~{uikqrojmutj^aejijdgmbfb^QOb`hajf\jb`p~nzhtojio{lmYRKIWadaF;5*)*!-2+.+')%*)$# $# #*+*+)&$&%$" $#'+"(&#)  ?7036FD:<@JLNVM>ETSVQS[Y_eVW[U_OGKQOKLd`ejmzM>+-82;5:4.461/(,4-,%52-/53,&6C:943/:8>B;! (,+'%)+1024:7CKLTWZbcjrz秡䧦矜{xz~|wty|xqsmhopj`[WRIFC@9326=>?@DHFA=9;AFHFD@>S~x}tqmtrptosmsusqm~|nijf^pofbgoaghgcejtwjgdgwrkoungklwzrqgknuelegbfafqwnphU]`akpjieN]twtutqy|vefsfZci^\WRV^a^OD@3+2%*20'%)+()(&'&'$ ##%$#!$'+-,')&!# !%'!(!',*%  2,037J?ED?C@IS<;L]YM]Qbge\Zhz^TYITVW]umsnj|PJ;"-51502-/67+'!.29+-,.4:46*18E=28:/3-3@7:<, "('%&*,-02459>FHGEC?=Hy~{}wvomuzqsnzx|xqsnfhg_]cdb_bi`^chedemyxjklklxyqxyvlklntvyxlgkget{otkgaer|qpkmfja`jldU[nvxs{ztoywkioedmaX_abgbcUC61694+03/.,+*('$&(%"%#$%!"#$'+-*)$#$!"!#'!"(&$(&!  )0496459:?D;J>?RYWSdbguksea\WTNTSOTWPOY]WadnV+,50.03.4/+/3105.6254*(-0-*-,-+)-+/+172.,% ",-+&-(-.036:;B?FNU_\bjtvy觝¢ާ¥ˆ‹|zxurtsutqpt{wsw|xuwytrqosi]XQLE<6214<@A>964Pz~ztuwystwumonjdc`agb_`eag^Y`hf^X\`cfvyrmu~vyuz}zxqp{tfgnup}vwebeimugdbiqmgdtyz}{}sltu~dangigZY_iaS@<:47<;1-,)+.,-0*+*,'%'&()'#*"$&!$"!#*%$% !$  "!!  $;4:;=CD=A;BMR^S]XazijZ[OVW_SK[Y[XUYOW\]J371/,+153/+103/30742,-0+&)+.+/0/-,+/'*(),+#+)2-18:rz|yz|vpnztomkniehilfjg[X[]Y_djcWXdkfi|rv~ˆċ~~x}hjuw{b^\]_ab`hks||{wkrm|h}pbfd^fXB29/16763,*&)/,0.+)%&*+'($'%"$($# "&% !$  7;?C8DB@;CFZQ_RWTbsh[YMXZmQ[VUc`drc`WT_K@G/05:;6-/32-2:4,0,1/14(.-,3,*07,/.0+/5.*%)("%3/7.058:@F>EILKTYbkrx駣ߧ䢝š˜~|}|zyz~yuxsuvwrpsxwy{wy~}xtwoi`\WMD=61.1686:C:?A:EHFGQT\`gnsw~駒ۧ}zvuqof`a`ded_dilqsw‹Œ~}ywxuw|{wz~|x{zyzywutvwtstgd_\TI?@GMev~{}uqpknrunkbdcmpkbd^Z[b\YUXTWZX^hgn{yH=C>@B?<:79;=BCGMHIJHIHIOLPMQVaeZSPJOQUNVUT]ejkrqz~}{pfcb[`hibgjcZY`em^E;<:6+,+9;5)-*#-)*+*$#&$%,)&"&#"#"! #$  !%(!   *8:@FDMPQU]_flosy駟ۧ{xurpoh`ca][_`didhikw’}vwxvxwyx{v~wv|zvz}yzywswxz{tpompgZOKR^kv~vt}um}|vkmehchgd`]YXWXVSPRMRXTNYgcer}yHALJCA<89:=?@ECHPQTX\dhkqz¤触~ۧ}{yusqoqle`^bd^WY\^afgaY[`fjfgp{zv|yw{}{vz{ww|wu}|}{y|{|xvtv~nge_dmx}uomukjyqedefhec][YZUWTUTPKHLOUT[`gx~vD=;9>89>?BEHFJGFLPRORU_j_aWOJRLSPLIKVaiednXYegdckmswjokmf_dnkJCIC7C1'*454,!"*20)/0)&),%()/10(%$!!# !  "!"("$! 546985?B@MBIPMSPLWTXT`h[NS\XRWSKUQXNG='0)+5.*1.0.-31,-2"-./)&6,63+,$$%+&)($.1(*,)3854:;=?=DADKQUVZWZcfjp{ħy¦ۧ}ztrmkb_\`aWTWXY^`aZT`fkle[Z\[_kw~||x~|wuvz|xy|}vtvquvyuuikpzwtmoqnfiojdeha_`^ZYXRWSPOIJNRVYUY[_ciuoA>FC<@=@;=:CDFEFILGHJOSUQS[jlhj_^RNLHRLNUX^`]`ri`dli_edlt~zyxz~|zlmf^_hnlTFKH?JH-$'+&.20)-0.+-6+&-*#"&*/-(& "#"#  !(+(  )7454@FEFIKLFKUNOMSgnbZ[\SPONIGVTRHB@$1,.2-20.-0*).2(-.)*1.2502)$$()/A:!$1)(+,963=?>B@CGKSVXWT]bejty§¤קæڧ~|xqprnjljc_[\ZTVTUZ[VkuqjaY\Z[cd`cs|{wxtuz{vyvx~yqmpz}yuwx|nimrwunhvyngnqga_]_`e`\ZR[XPMNJLNWTQX[igcnmC@B?>=?BFMLHKMGKLUWY^gkgdZSIOKER[X\bjpvtg]f`fn}rielsutzqoebkprePIEFP<+)'*').31)!#*'()'"#)&%# !  "(+('  98:?LMECDULBKDJTHLW`SY[X]OTSPJGJQRNKB-.0,+*.0/.-'*+)(=3/.:31951,&+#'<=1!)/&+)5752A>?C=ABCBLTWYTX^_biu|¤קڧ~zytpqlilfb_[ZWVRTURTVUTSWjtrje`]bdc_[]gt|xuvz|vtwz}w{yv|}sqsoqrzwzsuqjmqrtqjfnpkiurbZVZ`df[]ZXW]ZOPHNKUNXZlhfmjDE?BELPOLRSPJIKVTW\_ei[cohZNPUIQUZVRMT^_br{umrjdgk}yg`_\Zgjcmorytp\VMJEKF0*731,-53,#$'$"!!$'&#"#   &#"%&   +3*36-.,-/.2/(# %'(93-3437*%'! (-64" ./+,')74;@;?@>@A@OSYWT\_Zamw{ŸŸ ¡æէ٧zvtqpojiga]YWTSQSQSVUPScjmkidacbceca^Z^cdn~‡~x{}vtuv{zuw|yv{~xqrvrtw|rsrmqrtpojhjferpd[YS[][WZYTMCEGJGLMKNSX^`eliHDEA=>A>A>FUSWVZY[\JPUMXS[ZMRVKB'-1,201574)'*)+*.0"*-54295(,.*$)2(4:,%0-)$047C;9=>@BD@GPRXUWa`^jstwלßէ٧yspoqojghd\[ZWURSRPUXVOMQX^dgjge`\_a_Zab[R[bi}‡yzvwutzvwrqrvysoruvtovrormntqlskhd`d_ZYWR`e\XWZ[XVLFJDFGEMIFJPQTX]gxmIDA@AD=BDCEJLPTZWSRSPUXd_[ZOb_POWYX`bdb_ROX^`]`yyke^[h~|fmdbX^\[gacncRNEKE>)BC:5-&$%&'#& ! &! #&!#$(+%)$%#" !  >K@42+>HBGRTILJXc\YJ^WTc\c_STRPFC%130,204-),-*%)'+-*-1913960(*2*4&:6")(&+(+34;B;9:>=ACDENRUVW[b`fqmnsš™ž¦ħЧ¦٧{~xsomhfgc]ZVUSRSUVTMNOQW_cdhga_^\[YWY_XTZYXYd{}wv~zusrvuqsuwqkmrwigulnuor|sqd`h]URS[_ZRPSTSXSPMKEFHKMDHLTSU[`q|pH@B<>CBDEJNSVQPSPVRPMWU[SZ`]ZdZ]_^[kghcFUig_lslfaYiwp}hka^q_Ze`kZd]QWUDIGPO<431) #%!"#$&"!$&%'#!   24:18@;71,6=FTUNRXhY]\[`[cY^UODLOYM/6,/01-.-+*0(+$0-2;76:60,&-,'+4+#$#&)+/0;CB8;?>ADHIKIQPSRSNVUXTOTXVZ\Z_fhgdadkmh^XipvwtpicdmgvokameVX`Z`QTXS\MHELF64/31'#'%&$' %#"$(6*#'$!%  ! %&-'97@C37?>CVXJKZ]cfd^VRUWURZPAFDL?/3'2-.,02+)/)4(*,.583238:5-+'*7;42!#%)-013=A63<>CA@DFGNVQS\WZcgfensu~•–¡̧٧vwuspjfdb]\]Z\[USTUSQOPOPQRTSQOW`bdgfe_WVYTZ_]WUVSTas{~}y{zxspsojkpnkjmgchnqmfdac^c`]USONMJHPNLKIEBGHFADBDJNMT\dgpjC>@79HMJMUNHQ[WchdWS\WOJQOPED?>451'3'0754,.,).(5912/69;0,0+(%654*%&-14/2;906ADCGFCDOTXT^b`_dnmt~‰•ͧҧŧtvtspngedb\]Z\]WPQUVURORWVSUSQPNKR[_dgfa[ZYTRV][USUTMKLRex{~}xwsrputwpighigcaijhbgi_[][YWTRPQSLMKGMHMNIDC@CEGE@AEGFMSXgsiB=;BEA<=AEGJQS[hjwiE<7@?ACGENJIPKHLJONPXQLPNPOWZWfmfpqgT_tjo~pvyopi`lc][b`fUQUTURTZWS^D<1-3.>:045.*)*/3% " "!%&-,$!#$ #!  *.-3/9EC?=D?@BJHQJIKLGHJIKMSMOLJPNPQSfmieqok_nofmcsyvwnpz}wm[YN^iXgjfaZSTad`]W>;748;:13:10/*"*% " $%" !$'%'##!   +,/,4D;C?=KIH79?=9>?BEIPKNRZjkgykC?B=;C=DFLMKLKHDGEFHIGOPMKPRMUW\bgibyqnjnfo}g\`julstia_aQThe_WKQbY`mjcGD<6FA845/5-12$".)"%" !" #"!  '#/*5>6?>EBHMBAEOFNRPVRVQEH?BKB05:1.-.802A45=61+"3=921.1.-3/,*(# #$,3*)',3<:;@D>AEDGOY[ZXVSMN\`cfjoqy}|‹ŠŠŽÜ¦ƧͧœÎ~orspkdb_cb^\[XTRSPMLHEJMOPQPMLQX]^Z_^\[VOY[VUYXY_cbZTROJKRn~vkli^`ehjlid^c]WY]_\ca_SGCEG@:ADC=><=;=A<@BEJQMNSWgjquhD>@;9:<=BFHGJDFJIKMGLIKIJPRO`aVUYZ`dezsteks}xma_ehzyz{nd][^cXWSLU]SWZMA@<>A7/,&*'-$& '-& &!(, !$%"!"! !   !&+0179@FDPLGCMQDMSPQIOSUQTMNKC/8?1,'/;-3?<=5,'>D51564/3-&'!$&+.,*.9ABDBACBEKGJIEB>CHMROVgbU\Y[X\lo}tzpa`jpx]ag\GFRKT[RLFOL>;7@E?93.$"&$%)*)'*($!%&)/(*"!$#  !  ,0:+5@>;BMGCJDHJE[PNJPSQ]`VNLHAR87?316<4.637F>=:2+'A;/,51563-,'*'"#%'(,-+.29;EB>@AIMEHQLHIQ\`cfgjosxzyz}~}ƒ‹§ɧ“›}psqlga_]_^[USTQOPMJLNMJKPNSVTV\b[VY[YUW]YUV[^`_e`[UMJFB>CFGVt~xuomiaejkoe^[_YTZ`\VQONOICIGC=?E@BA<;89:9:<>ACGJLUSZ\`hf=63759863:=>A?A?@A@CEJID?FPZPGLPW[^SLKMHGH!673/8712-28>57.=B/,'3161+')* !#"&)(+,/69=I?=BMOAJCFADGHTY\dfgelqsvuxz}À‰ˆŽ¡ǧÉ}npkecac`[YVRSTRSRNQPJHJNJIMQPNPTWTSV_^VTUTSUWTSYdnopodXUMDA=?CB=?Ib|{wrnjifmklka`b\XY\b[WQMJGKIA<=:>@;43179;>@CGIHGMU]fqh@9875:512:98>B@A>;@BDEFCDNSNOU]`YXVMIHP[Tcz{md\feaZ_aXMIDB=@>BJGDJU_fMQLJ<:5,/)&')1/'% &"!!$(" "#  "  $49A<=ACLPFI?DQOICATU_SOIOMLK<30-A7589:A6.;2=B:24585*)*.(#&+'*+.9;DCGIJHS[cmvhC9=8<91/0409@EBHIE@EBPKMLMSRWYTQNU^Zkw}dfdmfcYRQMOFB>=H@D:NZfUNQM>;=-,+. ',*1.)!%&)$ !%"#! !#"%  '0>94/4BC7;J@BI?JMPZYVK]Y[JD@F32:4BL2<2-6>4*><59/68@7>60,.*-3("#$'(.01:FE<:>@JOLGBFREFLFJPVbchkcdjlpvqloruv{yx|}|„ÎŽ˜~œħ˜‰{lnifdc_YXVTNMNQNHMLHKLJIFKOQOTWVUVTUYVTVY[ajsmlj^]UDB?>?@B@Rzw{u|vskjhig`VZVXNPTRMOMIEA68:702.039?=?F@CKHFABFHOZVTRST[XWOMTZebjm|gm^gX]W[WSUO@HA<498@B6BXNCHD?=:94,0)*6324.*03($#$!!"$"#"& %  # !  -5-46?B=F@A>LM\^_WTVNZ7/4,235-3;<:@C?J=;7831/0(029OE:8,"$"$! #"#% !  !" "  (%(/-1.4:7:BH=;NUOXMLPHN@GF[Z>?75/3:2-623TE4352,8-198454,)*&"!""&*'-326AD9:=>BFNG>EJERPJNKSa_b_gfghfhinstplrqmturwz{}{z‚À}‰–|ž£†vgfc][]\Z[^XSNLPQONKIKLHGHJMNIFIKNPQOLPUSRUY_dknpsf\]YZVNGECACHBEA>?CPpywrpomec][RPS[WRUWYXUNFC@?@=;9;:6503-+35;87;@BCBITcvte<2),14765267@A?8;BGHQNLTXWSTYVQLNTUONTbhqt{k_\VZ^UWYW_dY?8:01.79@851@H>EFKF96-.4532CE?30*&'+#! #"#$#%&$&" !#!&"  !"%38+210;>HB;YZGJMCAHEAGIQZS59756:952729P;>F7/*B-:6251.-+-! "! '(,+14.:@?:9<@HJDBJHGWPRPKYc^`_]\c`bcdfhnokjnmklsqptuws{~~|x…ˆ~œyfd_[W\]\^\VONMNQNMJFJLKJGINQGCJLMNPNLMRTUTY\[^ghjld^\WYVPMLDCFGCF@=@Gf{xyrnkc[TQR[UQRTXVTLGA=@A>;864210.0104656=CEA@O_mse8*(03<434387=:;8:?GEKLGNSTWQX[ZSRUSQF@KY[evum[X_g\QT^bRMTJ>4120:@B?<:IK7@IJ><90/07<32.('$%'($#$+%$#$"!   &#!% !(.0,-+37=EAPLHBEDMKAIORTVP5I0.058:265.2A>72<5654.+,+) !" "(*+-/.0:9:7:=@ILHJFIQR\RM]c`_[WX_\]_defjkdegkmpmotvrptwz}y{}zty{‚…~xeb_ZUZ^\][TNOPNPNKFEKJHGHGKNOFELKILMONOTX[Y\cfehib`_VRNMB?BAGFDA>=<;Arx~zpnld\ZV[]TRSUTMHB?C?>=:84651.1/3456@HFEPdnhkd7*139?;53<=329:;@IKRSWUPS[\VZYRKA=KSMWfijS]^]fXT[TCE;:<=?GD?=9CK?,><@9/=74-18:>0)%"&'$%#+,*#&%$#$ !  %("%   +&*#,249:>?<@>?ERfaZRUPLOM*:15;9,7)5/&9>76.-3A1:0/*-*#!&',)./;5689:6>BDOPIGCGLX\TMY^`]VRX_\]afehe_acbhkigjpsomnqstyxutz|}~z~~}~|}vba\WU[][Z\YRMQOLMONIEHKHEDHEHJLGFKJGIHKNOJIST\WS[agmlfdaYQPK@?DKICEDABA:75@Yv~roja[\cYQY[VTRKGHC@>=648791-3,-2-+1353=AEDHVdea5,216<678?=AGJPQSPL[`YSQPB?INTXaV^[VMUSXYNG74<=A\>68308L7@F@8+<@;57(1)62*VBD?6023=2/74632*#+(+2157198:7;H@?JBCB@MUZXSP[\]WKP[d]_klkhb\`afhigebdgnjgjmpmpuqpxvswyz~Ãw~À{vy{zxyz{~{z}t`\YWYXWUPNPMGKNMIGHLKHGFHIJIGBEHIGBDIONHGKQVON\Y\lkaWONOGBHMHMLDAC:4259dvsvrd\]^WRQTORSMIFAD>:717;6;02*/+.131498:;87;?;59;:5026;B=3FOH4-BF?=?94357Epwstqjc`XUROPJLMKGB>A96<>:34/,/+)+35203856?JQUYa`631789714:268;610369=BELNMKLRSKJMLF>:?BICMPV\fuji`NHB>968;EP62:8=5B<6-+)17;A56;1.*%#)0+*($%"$" !"!#$"! ! "!#$ ! ! &"!%#(#!%!"  ' -.6>FJ>72+-?KP\PYTRKHLE?>:8692.-28($.54($-B/)25+-,& #(*)-/310/0/34369@CA@D@DIKGJPTQHNWXbdmxpmaY[a^]^`]^aejlfhmplfgkhp|ukfimsvw}|{sx†|wtuponmlmpsutsqpqvzp\XWXZYRSQPNMJIQVRLIMSQNGFJGEDEFGECBEJFAFSXSOTYTPUVMKOJKFJMJG<>?@=98418:;9P~zsrqjeXSRPNJKHFC?>7<9?<7415/,*+/24637927?ENT^`[=9;467/2871651/+254;@HGHEHISPHGE<79?L@85790<83-,/045694>?/+)*"*0-.0)+($" !#$"'#" "#  %(&!%$ # %353=I@)'(8OQVUKQPRKJNFMF"<759523.565630@BRSJLNOKMJCADCBADHFIC>;>=;:64:>99<6:472.)+06<46;:289BOYjna;:764;126202612.,*38749<832F<8*0:3,3$#")'-023-+.786:2:<@G@>GJDHNRQTPU_babmplpn`U[_[RTOUaglibekhe_X\efjh][cglnjklmrwsks~|vsnkmnkibdjhefikjotxulYSX\ZTSQONMQRMJNQPIJFGJGDB?B?B=AEDEJFJLFDFHEB>:9;<@CDB<;:=:5:56786767A<><96/+,20<1/12687@ECFTbsyk@9686:;64241572-)+/3<48;BCA@EKHLJCFD<>?E>NPVQKUK?:58>G?8795142*+)('*025870-'*$&')-,+)%$%&$"!!   !#" !"(0*+" "&$ %.8A7.$,;=:9469<=;94=bqnkjef`PORHJIHD?876;:9=5830/.87<./373;BCDLQWdod>;357<84580.3:30+-167.85CACGFGFCBGFA?HLFBJFTNGAKRG>@74B=026143)-,)/+(')'/@6;=137.+'&-,*-.+&%"#! ! # $!  "#$ !! %)+*0+(#"%  #<92++:;?GWI?NbRQc\]\NP)5')A/74?8BLOE4?927-+2?<30#('*'/126,+/5BRMD4964;7=A>@DKORUXd`]jhnr`XWYZNFOUPW^]YWVY[WVTUT\[\ZUX[]^_dc^acdehe^ixywvtrmhfdfebcfcY[Y\adcegjmpqtj[Y[\XQPQPOPSROJLNKJFECDFEC?9;<=>=?BH@CB@>=?EI@<587?<98?=72647:=865;<83Bdowxid]YSNIGHEC<:976<98:5962/6102369;:=FKSVZ8264;75960/473.,.142595>=7@DFPOLIEGADHGIKOQGCFG<>A?E;<161*,42,/.(%&0.2@<5:2'+*'#(+*.,+)(!"  "!" !$!"" %20.($ $!-/8ANHNTMV^WPF+)3*A91>3?6EJK465678).75/-' #$#')/50/(.3?DC>AC@>?AE@=6547D@84:;310169;:<;:9<87;Mkyml`XUKONKGC<=<659>;?<3238;86457217;=5HJN<>:A47)/>63.!" !#%'/?/024:AKRQ74,.0-49?>?BHEMPT`iXgh\VSMPJDIVSPXURMRTVJEMSQWXW^\^_^_\Z\`dfd`ZX_rvqnkfa`^_XVUTPUWY^]\]cfhejosgYXYWVRQSWTRPLJLOPMHGB?@B=A>:8:;=989=@?;:=B?=<>=>65=C>93594/-+/579=:79>Urxove[WLQMLGC;>98:EJIRYdZ.+(1:9763,+/3/2.5;:732:;?>JOPJFBHKLRTVOHKUN=>@;23630)+,-/020.+.,'+03-.,&,161+&.46;21-0)'$#" #! !  !  !%& %&%"  !-349DKJVWVJVOINORP!06B=8$A<;J<835:30'=?/51  "#5?-189=EFMNOUb_\mbcdWTNLKBDIRMOUMLKNOPEGQPLJLRTU\^_[Z[]_b^XVUYosokhb^_\YUSRQPTVY[Z[^dbilnbXWTSV[ZSOKIKMLJFCD@>@A;9:<;5/27>?>97431-.4548@<:9;?@bkikd^WPNJILH@D>:?>=@B;767=;948564578<9=AIW^dX/+,3784:52-,1623525;<;<759>=<;ANJIGJKHOSWb[PBYV@8>BC873564+-),*.1+*'/)#!%*')/')0,&)+35-1-1('%'$!  & &!%!    %#%.19@KTYVIHVHQUW[R'@>8:7=E@6535-24.-0F932."#"$(5:,47?BNHJ972*2/626;=69DIOLP]^fe`e[ONOICHIMLNOGHIHKLDLNGHFJLQW[][^YXY\]XRTRVknjlf^[^VSRQPNORSVWYZ[_ca^`fi`WVTSTW[YPKHIMHEDA>=>@>:;?<:;8754368:8638=:769;=:9123:;:81./139<747=:>@98>?=Jgfdc_XUNMIGDCJE@>?:8C=74796:8657989726=L^`i^8-146374601/469<979;:=9IY[RQ]\SMQUI#GCE=;9=8>7.1:141( #"'-37+/;LKFD><57*(286.7:29DLNITZ_hbijONJNRLIKINLHBEFCGFEDLFDFA?DFKQUPSYVRS[QLVQUhe`XVXSNLJMNMPTUWXZ^Z[_cgh`UTQOPQSWVQKHGLIFD@=>=<86;>=:436437=:39=87:9542,/0256518;2/49597569<=;D><;Bcocb`][URMHFOFC>;6>?9:;9854752589;<97>HRQSfb;57936:963231402439264058ESOEJGMeif[\[Y\PXMCA?@62394-36:64/1/)-2/+-/.,*# %'142)#)+%&,',)-+'&"!"#"% #!!" #(!#!('%#  %$%! #"!)"%*)@?GDEX`VIML]LEDFBJF>@<04>6FG450E6?>463/# %!%+85,2FNF>7923(.24850436>BJGFORfifihWPJLOSQKJNGHFBDBAED?@EFE@;>CHLPMKPWVPNPSMOTKPceb^ZVUMGJGEFDIKLPTUWZXZ_bgh^RTRONPSPLMKIMJGFA@BC>867=@>9765678656:;6301/.-,-046945862489:56;5AD]WH=HRUQD4(ALB<3:63?>39=1;41/@210*'!"&!)/190.1AC5:893/,/574/329=CBDHPfcibUMGHIROKNJAFGEFA?CE=?BFG@<:<@EKMHLRWTNKPOJLQSJPca]YTSRJHD@B@CHJMPNRVWZ\abg_RUTONPMILKPMIGECFDA:68<@=7676578;:76148953,-+,0/247968625797985;:=<7:;9;A?Ud`_\UQTJDAC>?<=?:9=;7325/615697:7<646414130/379<831636>=?AIKMIFONJUZVJKIBE=B@98369=671./0.0.+*"(*),%"*)(&$##+-,.+('*)&'*%! "# !!&!  $ " !#! "% % '$"+=B8@>CNFAGW`PBD;57?:=7=9;6:7<5>4:3+'&#!!#"!*024.+9<@56=@4/.-4540243:26:>AEJQ[ZY_YQEFPLMOF@HKFGD@HI@BEB89:;>DKHMRTOIKOJGKRIQdfe]WQRMHJGA>?@CHIKLKJORUYZ\`ae^TWTNLONMJHIJPMHGHGDA?;89=?;6587547:8>9624763.,(+1/,2685756:;9758:=?9;<:;8:?@Hghg^\TPZYQE><6@><:5362847365:8:;BPW_gY968578324302,279891467@AIKD@DHAKW^\QNCBD?@:832579:8730,1-/*)$(),+*)+)+)(& #)$&),.+('(%'" #"!  " #%!# (!".54:8ABEHN^\TLPWVP*5:876:?<9=<2463*)&#" %*+-0-*):<:>;A75-/4642/3178CIKMNKFILHFLQOHRcgd[UQOIGLE@?CFHGFGLOQTVY\b]TXTLILMKJIHGLKJLGEHD@;:<=<:58:9879:895346575.0(+01.+1.1256456:;98>@<@;?>=BAbh`]\SQRXPC;5>=>=A=<879817;789=<9=;9APTUcZ608-2432420./,45675634;>?FHF?HC@?HMS[PL?=?C;626961,*,0/-./,-.+()'&*)()'&$!%-/52-*'#%$&#! " "% !$"("! ! !0/=4-6;EOXh[PM>ESE9D69=@89<;A9A5767/*-)-%! !.+&.*)':7@?8654-0.359852*.354:FRQPXHFILEJG@FG?DMIFHGCD@;:;94369>GIHMNLKLHDHFKNLERb`ZVUQKEFHA=>DECEDEGKLOSVWXZb]RTQKILKJIGFGIFECDA=9:;=>?<9<=;9875325201+,0320413-/54789:><@=;8;<=FEHCJ^[ZWSRQIC@?;:;6128:<:;<67;=EFJRQ434.1-.1/1,+/1/20321253130-1<;68AC9>BD]bTG;:A;98;6:8350,'3/+&./0/0.)#')-&%&(')&%',-)*('%!&"$! "$!"!#'  $&%(*#""'+! ,82;4*&3?OBagjWQM[V;+5A7;8?7=?25058.1:$(&# !&0*#1'*+*53:?9-0.1.4597/).4-37BRMRSOD@AB?AB@=HE?;HLGCEDB:757;92147:9=?=<:98523421310203+*-/,-,*23145789=><;>:8>?9:9@CDHGBQZYTVPHG?<8C@<;=A?:87517:<84<8?@LQW]K6=?2;6:8954197/025*.12.020&%$%0,(-+*)'+'&2,*%'%$"#%"  #"  %"$!" $"   *@?I70!7P?BNgYSL\ig`A<67895;71/3/0.*%"!" )0)$6.10/526820*.,0265?:5/+,.-04>JLSLG@;7:@:@IA9?@ABCEGJOUXTVX]_\OMLIJKJDED@?CEB=9:?;:;:><;:8765464012/10/1/.*/6579:;:<;8;?;=@>97:=B@GIAGY][SURHA8>E=536732<>BFID404;3/13/.*,*)"13,.*+'&'%$/><,*'%"#!"!#%'(,(#!! "#$  '5?970'+@QIL_NSFL^c[Z/?@60.3751/2789<>=ABCGLQVXSRT[^[NKLMLKJIHCA@ACB?<:<@=<:;=<;>?<97468520./132/1.0/,*/47568698:9>@?=A><=>BECKHA<:X[ZUYWKE@=<547;?>A>=<=>=8<@JQSO1,48=:8752/10.3474303-347;<:>A?:47:3,5:@LHEM<;1387:9:98C@5308C121-0,-0*+;2/*).*$'"$*5-&%&#"#$& #$#!"'0.,&*#!! !#  0-,-/-(8GHJIGEWPMN/8@>:@:<47162<08+04*2! "  &*'*,*3<-()*(+32.64/0.)(*&*/14:AI@;82/29:;@;539ED9:<5/158532369:=6;BF?IZXSM?;:=><=<:?ABDHLOSTPRU[`[MHJNMNJIFC@B@<:>@<>:=?>;<97598623/.10130-0401./7545842368<>?@?@?@DEKG@<7QXWTXPHCB@7@FGK?E;=>;6:?C?E><=:;@HGKOM758:8531010563020345:BA?87;3-4:@LF7+%'&(,9-60,*'&'(&*+/13=D;9;607:68<;324;D?424;6127=4148;>;79ACBGOJD<:839A9EXYWPI?;:=;756;>BDFJLJNOMRY_`ZLGJMLOIGEB?@AB@=:;<@?;<:?@>;:976;75370/10/./4.4521021:64340/.138<=<=?=>@>CEGOID??@DMHGB@:A?>?9>9@H@?;>=9<=DNMVO675>8:4201232353052684365:>5652;0/56=D:6@>3?B>5+0121-,:1383/.3/:@;60+,-)(')('('&'$&# !$ #$&,(&'%('&!"%" "$!  ! '$)1( 1@HACBNP^PJLJ%DCE>B;9B8><8=>E<,-.(!"! $)%&+1.&*15,# %(+14*-4,+&$%&%()&),0:@78:=4:;:@:/+29=C;,3@;547=>=;@=:39:;>CHKHKLKMSY\[WHDHJGHKHGFEAB@BA?<=A@<8;89:98676962/0/2/5/2/:80-02/1?:620-+-.249;9;=>=AD?>ABLQEA?>=PRYOD@=@DMXKC>9CIB;:<9@AB@A;BA=?8BGNUWL402AB7502+016/124519;:848751*-7,.43:=?>@HTfXOMB==@3;:2<37013)*$"! -,#(-0(-1,%#"#%'*(&,2&%)%"%'%-,'-+/<9:=9A4=?@B60/5;>417@H>89<=54=A@A;9;<9?FGD=5684695-AVZVOHBA?A=968=@=>DHGLKJNUYUGEJCECDED@C@=>?A?;<:;CGBDKLIC>8;9HTWIFABAEQNKHE8=?>C?E<8=F@=EA@DFC202875/.13/25759@87353159820/(')02'.1/130253BD?37>520-+0514.0/,-.)2,4&,103/.*'('+'&'*)(%"! "!#"&%!  !$% !",%2CJKNKMOHLA@AK;>953872693-5,/'"!#)'!#01().,&)%$&$#&-+"!*"(*%-/2+/8:;9:>6;=A98:<=A@:9;<9=EF?825973/BVXZQJE?A@=869@?=@>?<=>=<;978:9;754.2430.-.643.-/2320-.1036767?EA?;@B?DJIGB>8346?ROEDEDCJEDC?9BD@?;=B@;>:;:787ADGDELH524630/312469@?=863156/.*%*'/,-2,0375123><@>@52/+&(37.*.(&/0+0&*/"4+*.10/,'$'&)(')('" "#&"(#!%!%!!$$! !    !%(>3*6>AJLJMQGK5=G;C:916A4/32,).,.! %($1-'$-/),&'*( )+' #0.%,)$+/64,/257586<29B<9=;6=8;C?93-3;<;87FXWUPLI@A=86;B@?9<@EGJMLPTV\XMIHEGJGEDCDCBAGC>?><=<=>87;87852321020.,0/312-030342./,013468;BADB>ACDJEC>:;2404PKFGHD@CE>;EDA@?@B=;A?<:3427<8=AFEIKLOUYNKJGHGFCBA?B>A?;:;<=<;8735879543210212/0+,.,0.121-24202/.2459;?A@CDBD?:;452/MKMKJA>EH?><@AIC;>?575/3032:DGAHEJOIMJG*DHRE=84587;60.*'$,- #"#%! '($'$*,(-#&)%+&)'$(-6/-.-'),0./10-,07/073-2?G=85>?B<@FE??;HZXRQPIA@6/,.39769=AEGFKRV[^\OLKJHGHIHD@A@=>=?B>:><;8:859865630143534-31-.102-/2540/.026325689>?<@C?CADC?<6:86.CIMNH?BJMF@<;8:?8:@A;7;?>=:2790/79>?@:2531542342128>B?;86421750530(23/-1/.4341.-,-,/-/.42/15.56,/2(-1'+6,08-(+.()%'%(*)('$"&"&'#"!)$!#)&!$)' &.'%&'"  *1+.-5=C:<9067;@353-*/-*&""$!&+ %"&('(#$&!&#$-'&'(+-0.-12)(*+*-./)+02/03.+5?><40=CGC<>JE=;EG<79;6,-9<7246/(19>=86FZROMIA@<4.),-376;>@ACABIPSTZ\XLMJKGEFKIDC?<=?@?>;9?=:9<7:783543042435140-./1065101/-.0265/47:<9>:;:597;<789:<9<893/.38;?FE:153465787415;CD?;76717863261/./-/23./1313.,*,/.10-3861369797-)2),4,-91%,0,(+(*&)$#&)'(#!#& # "$!%"#$#! $+!&'$"%  +*'%&7946@LSQIMF><8!A?H:>:4>8:7:?,*;3,$"%&%"!(- !#")'(% &%*&$',/,-/95,'*(*.*,./1)+(/6;710<@F@<>LF:;C?86=>4+.:37/&3<;8<:54FZYSNKF@A;0-.15968=;>@DFJSTYZYLHGEGHFC?=<>?@?:<@>?=@?AECA96416:6FGIGFHJD<=;:7;:589=:928-/73;@H;23137463528?>;:979215<7-/21.-,+3/,1210+*,+,0*,*.-+0/,+'"(*4.+,'*,(&%$!&)&')%'!%!$#$&%'#! "$"#&($$,%&"!!  &%,63;<93=>56;<8CA3-497058:4,+9?7487G\[USMC?A8/0421349;878@ADFGMSY[YLHGFGDECAB>@A?>=:@>;=>=9697878931546:653-0310525735310/./01241634698?=;@HCBD?:6:<5EJRQNIC;=<:=8;=A9<;<>@83.0/457>=DB:2+('&$&$(')'#$&(&$!"!"  !  ! ! !$&%'$!"!#%#$&(%')%()($"%)%#%),$  ')!!  *2./06/5>CKIKE;8:N9HK=D:45?B1,-,:92*%  "#+)!!$#"'%" #)"&#!" )*&'75.-),/3*#,.03*$'+.7<94*->B@:13>:647>=?;C639;6/7=A;1/9<53578F[\WRK@;:303742/38976<=CEFNUX[XJGFHFCBED@>AB@=<=;=<;=?96579873154534./+.162014240.*-.12323897<>?JEFEA><7;7DNTQOFA>?>=:873-+*-6537;>@>9,'#"  ')&#%#"$#$("!('&%#&'&%'*&"#(#&(%.+% !*30.0289=EAJFAE<=HU2EBC>98@?1/D39, ")&!# "+*"!'-(&! (&!(85*(/25)2*078+$,/2:9@?1(-;?<:76>:<8=F><;B>7?629EHB738141026EXTOMA:723761./37856768=;8:;>@9756986510231/.06941046970.,-./2345479<9>@FMJDHFDA?:;3@KOKGDCBFHB@<969;:70-095128KIENU2@BI?B<>9;A745:;858AID9751-01/03DZTMLD=43274/-24578:7;=ACDKRTSREA?A?ADE@A@?>=;=:9<>=9897543/0301210475212/1034685.,.0137868:79?;8@IKICFDEA?>;3=JIDCDGFBCB@<96:876:;863/4042368F@98<=42369876;=>850.,-./54F\[VKC?505.47647867;?DMPVXTGD@BECA@?=:>=?:<89;<87;=:8741010/0-03265/-/5951*)/3565<975798=;?BNKJDFD?F=94=GIHD?BGJB@CA;95424;:8753894852+-169=;<973/3432323631360.02-,/68.+,-+*0-*+()*.-(),)(')*&%&%&(%$&%#"%&')7E9+('&(%#$!&)%)+*#&1*-'(',$)('%!$+(/,'#  $  9./097=B8=0)+:8=;<:;@><789;768786520/3420/./-.0203420364510./*-248:89;=;=CKNDCJG@CD?@6=JKGCGHEA=;CA>=<:8=;79761505414897:<=95478;:85<;965894675030.0341./02.0-/,20+,-,*(+*'(+,)+,(&(+%'()(*1@MC.(&*('%'%)&%()'$1.+1,)/(#&*!#$'- !$% $  25G5.2;<4:>E@DM@5XH'BJ85=58F;9/02:=.#&'# #% #%+)(/'#$!&$+)&#(50+'()34+#!#%),-3152+,2010252549:?A;86125423,.*(.13.14F[`YPKA52654/,/5:747821:8;BLNSWTFC?CEAB?@><9=5=HINHLOJD>?@A>A@CE=675473536<8;79;?B@:67<:AC65:;989:7;@=50:4.472/-124240.073,-,-/,+()(%(+-,/.('*)-./+,6@TD794'+*+'( #"#$#"%&-1" "&( )+% (51/+-+(.(# (*./30/*,32034045BABE:63*-.142+-/,058956F\b[TQD64861/-05937315:6;DMNRWSF?>BD?@EC?<=;<@?<8534676723-),-/0/0/423657;9730210267:7:9:9:7;:=:?HLPLIPJBEGA@FGFE;916965739>8;:;867<;96454;<=;257;@?9659;7081*2;.+,+./.021.-.+)+.+)'%$#"%)(&(%'),.5GF3%')+.%()(')*+24+032431,.-+%&%$+%"!'&)# (0=?701:046:A@ST@ISC5;<:FC314;4) " #&$#$+/(" %#(,%)85/-*'$! '4,+104012,.14.28GCBE864,*(.2/,0,1:<;8:8F^_ZURC879543.1574532/398:>FMPUSC=BCB>=CHD<;<;>=:9:9?;:8<9Ja]\UJ><7103464542-0478?BKMLPUPA=EC?=>@B<:<@B>A;=8325645632010201-0/2/0/279>810.102148>:?<>:;7;=?>@FPVPHGC?A?<4:HNHGIFAJLEB@FGFH@>878643548>:9852/454798<853.1419:681/2.-)04%!+'&%&$')$ '(!"$(&$#!!" !!"#*)+,)1AJ7&%&()'()(*,+3,03/86.-'&.&"#!$&'!" "!!#% !%"$ ):J>80,.38<=@E8LCM-CEHA=DAB5Q@353.8*!#$%#!"'$"%!" "'+$)2;=0$ !49.1.0,/:65/67/05<@68?6;@84-(*,+(&*/6=;:6587Jac[H>=9641564596234:<>BFLQVUN@>A@B=EHA=@?=@=7846457410203-/12021020/367<:86./0101257:<9?=><87;7689=>@NGEF@DC@4:GLKGCFIEBHJIJDA>9;:9754/48?;7894254276:9:51.4561392*(+(,)&+,$"('$*')&%'%#-.*(+'!$'$!!&+/->J=0&('+*-*("&'(*,/(*.-+20/-%&+-'-*& "#)" &$## "!&!" #  #7>0/@:+3.5=@GL:HAL7=9>8<@;5/,$/-.2#!  $ #$"!! "%&(-65><,& #& &9*+,124765/,12/45;>A>?8?80/)',*,-.36:85659?=7218758104637<;<@ELUVPNA@A?A?@EC?@=;868565410/010/.1430201.14898540/02/12068:=89;>;69685;7>LJNQHECED?<:;=676346379<87346878:B60/,-1(,-*,53/+'&-*#$'"'*)(&'$"#'*,28D;0,)*$')+*)(,/)+.+-/.0.'),-#)%'+&*%! "#%   #% !!% !$"$(# 'J4*;094-95;A=JICAG'<9A@C;A?>?><;9:97450.-./1430.0,0,./3565940/.101239<;:78:467:73:86576985;BD?9=959=<5303:60+-45<;4,+/0*)/2(%)/)"(" !!$"%(,/04>F:0+*,*&+/-),+,/,1+,4.,(+*(,*%*%#$()&!#%#!$%#"   !#&.%  !C0*0(3*-146@AJKFE>/A@G?E=AE?534368,%*+ "#&-&$!*!!( ")-1B>;@>)!#'%.&1/5,16@C9<0+01)(0.2736@LQI>EF8*(&(,+(/./5:=<46369F`aYRGA>:68=?965,*+-05689>EHJMPUEDHMNKFC@AC?@CADA@<:;<><9720-.-,/23130/.10105380.-0356=:=;86756:757>=?LMLHECIK?LMOPTVOKLOJHMKMNHDA<:9:7942159EDB@<>:>985496;8315826:6.,(/7/.1('-"%$"!"')'*./0;B90-.+,.0,),/+.51041/2-./,-,*,'%&$%$&"&$ !$  "! #  #(&  2(+*&*&+7/3EDFJE<&CB?>A>FB;/*147+%/,  !&#'($(%"  & -39GA8G=/#)#',%26>7<4?;48+*+,($25<13>GNG@MD7&)%&*&'1/18;6489E`_UNE>=:549>;43.*'(+2457;@CEGLQBDIMLFA?=>;=EID@A=<:<;8;8943/.*.010.3/-252312-01340348:=9758653496367@BDLHEGKIBALORQPOLMLNHJSURJFDB>?9<9;6418946:><:;>;E?>;:=>?<7656;6513:845651.)-2341,*#%+*###"(*)-+,1B:.2101-0.&'*,.-.1454/04-*'()$)$*&('$!$(" !!#! !  !   %'( & #),),32163CN>A=2"#$%)-,8;A;?020/-&('&%-28<501;EB>G=0$(%&%(1237894346B^]WQF>:757;4-+)*.40367;>@GLPTRDBEGKF?=?>?<=?>7987320-.142-/35345101024130247<8:5356745658135<:EJMFDHIJFHIJKOXNIMSTIN\[YXPOIHF=9;4702530573;@;:<=A<>C@?<;@FB96767:;:753487:510,26240,*#'-+(%#!"$&),/3?J:.,./*,(*.'*'&(0-),*-&'$(*$(+'%!&!$#!"'"!$# "!"$# '(*   !&).&,27;7:EG@KP=@=NCQCJCGJ@:/2.1 $+*&("#+.$! ! !-.'.8:8+)(*%!%$ %(,1981/+:?35>6-#%'054312532563>Z^ZRIC856:1%$#%).-46568>?FTPVWFACEGC?@CB:CJFGH@;><;:<;7346320/-02131-1762524693/30/-303103985437424895308>:EHJFGKHJQEHFHPWPX[^TU\Y\^SJKE>;5782147;=:9<=?CGEIKJKIABFHD@>:9;?@<68747:;57428542101*,-*+'! %',-027DC91+,+-1+(&%*)-)%$&,*.+-)"$#$*$()"#%!$#%'$" "#! !"! +.% &$,# $+,+.FHNTZf<979JICLFME>CD;6+5*%$,&$&#"*'%"'#%" %&*89:01*% #'*0-6581)"$%+#!(%!'*+2.-.0><-.:6-(%$%(-3531.142143?Z^YOG<5/473)"$'.17898:@?ALTRZWGFDFGEBCBCGENWROPLSPILIBDGDC@?=;:769859623465841/0/1/)1-*& %#"%()/215>6-,.630/,%)-/()('(.+('&)'&$'"#"'#!! !'*)$  &($" ! "!  #$#&# #/,/'  .:),&*$-02;PMVRe>?30?HAG?E<@E20*!040 %3+'#%"!%'%$"$!&24.,($"!$#+3-1*,$#$&/)&)'+,(+/*,-2=7+282.-+'*,01.-.+./1/21B`a[RI;3-/61+(&*-,-05767:>BDBKQU[WILKLHDA?@ACBA@<;=869=;952353/+,/24531437;=862187:;546:50763437414541/18>;?FDFKOROUFNUW^ce^Z[ULZ\WMJIJB?=:6437691-13=<@>?;7963678>840.0/-,3/-*')'(&$#"#"&),153ND>=?>3,-81/"&3*(&!$&*%&! %*0,6+$ !#!'-,*#'-$#$&,/*)*-*'-+./292/:.*.()-*%)-+*('+*-.,B]`_ZPB8.,3-),*,./17578:>@KOU_YKNLEGC@=BJKA@?@?87:752135675.,-215341/169AD?:7678>96:8310746756<79;857514;9CFLPUaSIU]Y[cbh^V^bZ_`\XRG=:82467;/.17=<87:;9:<793/1/040-+(&(*'%&!&+,07E;6969<=<=>EJOP^fTNY^\dfe_Ygh`fhYVPHIC79642357/,38:=>CJAG>?GILDEKJFKHINLKJLIJKHGJOQLJHC>;=:>868302/+*)(*(&('!%'(*+/@G>@G945<2/8)'! )6+&# '"(*,#$% " &0,:6# ")/3+()5'"#!!'&.-(*(%&#*+0;*")# "'.-10,+,2*'*@Y^ZM95*'*')-1./2-/56=A>9=FQPWc`URNICDA@BAGEJHA9=85401052-)02/.-./1404;=5238;7874*415635764:;96967?=A?<;9DIKJ`jYM[aYZciaefh_ahi\WNEA964286/.54.'3679BP<=<;BKBIJHKRMOKMKJEFHMDGAFCDB?AEIMLMFHGAFB563.*)+'%$%),4@A.,).7341,0,7*!&"&,/+'#-3/-)/856.4*,+&'%)'%)>;-12/(*% )"!#&*()*.%'&*-3*,),31/40-$% %#%+%"%67:8>9BGM>*LKB>9;BMI>6;95*3,("! %/'#&$'$(+,'"#& 2>9A?1+ &.1,)'#&,*##%(+%(%)'%(.-8<)"'"!&-01.-+(%)*AZ^XG420+2.-.1.1/.5896:=:9APVZb]KGFCDBDGDEFIFA;<9861210/0340-020/021218CD=5649312+/569646518;<98:;9<=9?>?<=<>FIOTmrWI]_^Zehckib_ch^]RME>=72327;93/476>I;AFCAEJLNMH9>;301,-*).)&'&'&).7E@43,30321*)( %*(&,20('()-%&+.049362-/1-.-)*302.)*>7040*(.'(#'!% $,- &$'%'&(-.-#"#-/-,0-( $#/ )():;@IAB<>L;/?A@HQRI<@EH;6;?61/"""+'%'$&(&-(&"&)!8OPN;0-'1+)($('&" #$&("(*),27A?,()%!&+1.,+),*+)'%<^gaTD043,.-*+-2/8:;876;FLRV`d[EBDC@DADNJKEBA:?>=93631/0/42031.461213438CA=47<942/59?:649:=?8507;9:8986>?>:;>@FITb`lQKZ\e`chakri\h_XMGID=?6.-.12986:405878=C>FIGCJLMKEKNLIDCFMIF@BC@<@HEDED@B?A;<954/0,.-)-+'&'&+4=A=73982.251,-+()/0121,)#(/.13/*-+)-+2-,12).1.0%')31,.1-),&!$"%$%+""&-*"$'('(+($!*-*.-(   "�*2949;AB0>D>-EBFHGFE<9C2*8D=@3)!  '(#',&0%$#"%("!7JWV0'*$*.%(%"%*&"!"&%$&'"'.-/:?2(*%"&*/.+*,*+,0/0,)'"<`i\TE430,.1,)-+/49;:659:@JMOX`XBAC@DFAGJCGD@ED;@>=6041.+/.1-.1/03210436:97576720147<;678=A>6757;:9786<=;9:@FLS[`bGQXhaeifpgkd_n]XNIJA:=61,.016121/1387;>BFDBCEJQOLJLKIKMLICFDEJE@BA@B?A@B?EDB;<615;584683+-+(&0;52-231/,*/()(-4121,).37=>3-'*+,),3,-.0'*,30'%)21+0-'")'#*% "##!+%!#+##',+'%'('&"%*-*-+ '$)('/69254<;016KR@#NJQJMB7C901?<150%"!%&'$'0+-&! #$"/:2/21-*0-175635783=FJNW`W@>@AFKGJGBEDIB:=?<750,+10./0.01454141/154385424636135978;:65:964:8<;9654975<>FJOS[_=DLRYewtusqielXVOKFE=842010/02/-/34367>@=?CDADEILIJIKHMNJECBCFAB?CBCEBA=B@?@FEBA<:75=6,2364351/-.)+.8=3-/,0*,1-,$+-(.-(,-21-+-,1<;89.)-+/.,1/.20(*04-+&*21/*&$'#%#$#!$ #'*#(- ##+0-&"'%!$#%(+-/-,)," /,)&+18/.,02424>GEMHCHMOGK9BEA1/@5+,0& " " '%$%"&1,+%!!$")>G;1*3060*&)&03.&"!$""$"'&! (/,171,&(,2+/-,(&()+.02/*$&+'<\_ZVM:4242/,2.356324208CMNXbXA@BELOMGDBCLD<:;851.042.1024.023204314574985732345;CD=U7<=32=AE>"#920,-+!%*&#&!%.' %# %%=;:-,483*)&)&.($&$!" "%#('&$+46.)&)2=420)$!&)-./.*'$'-)Af`XOF3-151/4358732/157:ISQWb[B?CLGF?AHI<9<49891.2596/.076+-.030./1821245=7635348<;86;806:9:9;<98:90127:=CEIGFPTG5BOZS\fnmtp|aeVTJOD9<7B10+65-1.-4679@?ADJGDFHLFEBEGDA?B@FGCBCEB?@DAEADGE?@;:C8361.2-,$"$*+568610365)143.4-*.1.0;?9:90,-/-*,0/2.*01/15,0*),'&#)01',)",3*'(-'),(%" %"')$ !   $,)()(),)%(.,-.1,-+$)  -72'#"'0:<9CHB6:2*1(1=1ARMHA7:7+'& .'(#)$()#$".!$! ##GF.'654/$"%#&#&)#"*($+3,'$&-.0.'$ "),+)'&(,+*AifWE89;5/-30.-5356517@>HOR\`XDGLHFBCABEC?7<;9;72.67:-/-16234213-.5(/2569A>61854=;7365;757CFHGHPQN:1=L[^j{opz}ke`RSGC>;:?;/+/2165+0439B@=CBGKIEHJGECA>CHGEGA@AEDBDCB>AIGB?AC?:A?@B?<469351,'$+&-0$-,*+60.610-.2,+&/7,20,*,.51)'-23.1243./1)-*.)1-,(+&(3*+/)+(%"! %'"#$*' !"#  '*(),'$&$"(,.,.-/'&   *8.$%+*,1/,.9D:=@:=83213<;9+01238624845:4)/1529@<84:9:=97452976>CFB;>:8:7:735;<;CGHNRNMK71@JMQd~y|pfmd`XHC@?@<202/763035<>=;A>AHJFLKIG@ACFJKHDCEHDA@ECFIGDBCA>=>@?C@;64:235)('*(1'$+016=:3/72-/3652.-*.3.1/.32640234,-3.'*04-1)-*(')+%*(&+'('&%#&!%/)" #!*()'+(#%$%(')-)(+-'%$ ;91)'),-+->;<9>< C=>F58@:82@8:/ 2/1!$&' %(#'! 12#$-'&"%1*",+-)(,$)' (!$ !%(/.)#$!).)% &%&)(#%$*-(&:U`^QFB=<63/,7:40421649;?><:APX_d_NOQTPJA?A@>B>?:5137<=5.0103561/4679791.14:=;56:;8:646;97=DB:=A@>ADHIPRI/3CHGM`~}ymotsjcMEGCB=412140/-2586:87>=BJDIKHKFDAELNQKHEFJMKE@EGHIJFGCBDEA@<87483-,(*)*,/*(,.460;=:342:>68145213/,-*.312./6;B676=2-/-+0)30+1+-.('-+,*,#%!%(&(,!",% $"&/3'"! '&#%$&""#')'*(%*%#$" 0'(%$'$,-(+/76=D;6/:1+=6.2<52$%( $,'#&0-#'6+!$%'" %(%'+# )%) !#$(0,'!"'*%(&*&!(*+*'"$8[naTUOB:340*587264.36@>@FPZgbQRTPJGCDECA?:4/3:<821/361.0236<>64658;96:;:8:3249=<9;@B?96:;:=:<;7?@A?AFIPUSD,7BDGSbq}tux~vjbPHBFE;63435121.+256:975;8BGCHEC?@ACOPLMDMNH>IDINPLKGCHFDBA<;:9762-*(*-.+)-/23409;715768<5130/02,052/.3=A>7<727/+0/010814<0,($-/432%*&%*0&(1)&+.01&& !#$"%+)'*&'+,&%&$# )&! #$+/023:0=F4*;9;2+2:6QK7%.-9>/.*$%$%&#(.,%#)& +8(%"'*#(&# #,($'#" !#$"$*%!! &)%"%('%'+'"#*)+*#"8]i\WB965/(/62,52.326;=C@FQO`i`POQTPNHECFGD?;<7503=93420.0131.147957353458746<>76:3/26>9>;976979;?=:7:><>?GLNS8+8>ACPVkwrnuhgVMLGH@7:5432103-+356=<639<@?GDBCA?=>BLOTJGA@FEMEAIDBFKLICGEGECB>=;821+-*$,1.-./.25147436485678=/.0.*3:324>=<>732/030/:<4:8.082&.1.7<6.2+,%&)+',4+!%,/(0+! !()!!$#&*.','+),.)%#! (#&'+"'+'696@CBED<;2GAJ@8*4;WJB40:@.2,' !$&)*+/0$ '% #,!0&'*! "!$! '#%&"! !#!$( #)&!"&($%'$)$!"9]c\WM95<60+%&)$-1.21,/36:AMWV[a\LJMTNLDCB@>=6<8454;A9764/0-1254/.07874560246:74278452789:@9527872469<8>?A9689;CGKMO+,8;?BEL^pkjljkjlfZPKJQGB<;50/7238.*+-2586749:CLMOK@CEFBGEHFGJIDFDEB?<:86/,2-,0,2-+,1.20-0.31367;52581,0-)5<46153126384,02-/,04178/90,).8@91./,+!#('/3*")=3$/)!$""+$#$'-*(*-.(),*,20+#%! #,6./"3/0D;I@GFD?D/?>E@KT>`VSOI>1627(& #'"!%'+/10.&$-.(%$ "A*"&%#$#&#$(!%# $!$#(%#%#!%)(&'#"$ %<^`^]M:768).0.*+,/1027537;@LUSW[XGEFKMGB@C@?>=@8568:531023542-/2<8523102373276<:@767459=<868;:898:<7;@FE:76;?FD@GFKOH@EKNMBC@DGFEFHECBFA?>=<954/21*,-.3-+1/0.,-134851014<82+&*02.8;45<6;1/4,-512/0.1+&./-7@631/+$(1-),/%"#)-(-,#$'21'1*(+"#!$!'!$'*,/)%),+('+/*,41*)(    2H2:2174:D9DB<2FDGO-2:CB>73.(+"%# #'+.4-+$'1/&$! !" (>)$!+.-&#&) $$! $!')*#!%!#"#&($&( " !"%:\bgeWB4*.-0686),/41/875:;=CKM[_[GDHKLJBAB@?B@=:6383210143541056<=65/013857:<;9;42/347<>=898:6=;@D>86;?JMRO3'/8=AB?L_qtihks{ztb_ZLAB>745301464,-.4951/3298:=@AC@>@ACBDJKEFGKFCBAGIFLIKHC@BGEB>@?=;962310./,(*,)+./248612595;A7:AGLU^WDBEHJGBDCAB?98489767:9;9:;>GLFC&)38;=:9Kafohfejqsj`\SMFB=741.053-+)0410.14;9>@BA@?>;?CDAEFDBDFEFKGFNKIHBCGD@>?=<9521/.*)+-+)(*-/0347;637=?CEA5<6,/141023485-/:8/*0+*.-5/1-/49:24.'&#'"#%$%&"%)#')$&%'& !'$*,'()')(+,*)10(0,%$("  .:>MG>67@=9A04/3103+1432/.:95;>AHQRUB@BFBFCE>=<>?;867434250-/10131/34101/-.36453.1352/3/3:@BC@=767<;97:9848789:>DHG6!,69>:8DRQc_^Ydjnhf[QRNA;94.-083-.)+-,1529=>?7:A>@D9=BEK%7D;9BCIC>;3<@>7578137495.,-13/13231275-.1685653201310,-42?ABA=9:@>=:7946469>GC&"29@=@DJIEFIGDFA@CFCACDEHB@EAGE@<;9753./-,*',(,*-0/.1,-37846972/37319(14721/8=<=@<42534861.)*/-131,8/328:81*(*)("$('$)(,&(*)*&"!$!(.1.,(%#()'2)-,*+&#"'#    (537B<=;?:>@C?7;DAIDKCA<2<910*$$$-,/0,-(/25%2+"+"!4'! +/*)()/%!* "#(/,'$# "'# "%&'&$' ,&(0-*+,)'#%8ZblkUI;=0/312'-,/46867:=?OS[^U@?>@=@CDCHA;=A>638:43023.)0.,+-2/17121532-3562410235:839:69:?=;8:<9;79214376:>AFB3&16@K=<@FOHUb^ZWinf^[WMHA@72176/.,1/17<2;:79;<:AFHEGFCBFCBE@ACFLIECBCB?=9?@=;<61-0,&*+,*(.-+580206<9678:5121015-,41.5=>C?=<><7310-*(.+/*,)+,.0+01)(,/&-0/)-52)'+-)&-,/,.'$ %"% #)*+,*(+)%&"&5*)'&%!#'#   -12%2:65>6437?DJ,?9;>A=C?B:<40>+0,& !($" $-34-*431!&1+*$",# 08.('$" ,' (20,%" " #&'&#"&%$'*%)*,0*%"&*+)6T`hZK;8.,0-'$(+18<:8526=FMUTR@C@?<@HJEDC@?C>92561+20,-*+)'*.104.019521-245013145686468757>798;687:5636569:?>=:!+0297-4A:6:73/,.1+/0231754597;@FCEBFBE@BEFE@CIMKJD@?>=:9;<>=;8432-,*+/./)-*-./1473:7678/0123/)+30+7:8?>9>586362-*+1080+,12,)'(*.+#+/-*.2+#'),(03-/( #!$')# !$)&%,)+($"(4)(&#%$%#   #$%#(?N=:6@50;47?C87>;C@?>;954<.4.+.)"'%# #,0392-2/,0"*().*!'#63$&"+,&+'$(,"! 27)%"!"!#)'%&"!"%()*.+)#%$)*)%4RZ\OB:<.,/0/,)%*19898532.3:CJIL@CB>=CKFAGA>@><61/13/,-+,)'*.0/131346321045431358:75675747;75;5026545676;@>;,$,572/,06=?GJQSUOLYiodPNCB?859?:3/-+*'()+0/12163054864>A<@B?A>BDEBEFJIFA@?<:;9:;9;843+*)&%&,*/*)*201346036543:2037;981482-48:<>:6<96541213*+01/*'*(+/+,*0-&"(+$*'(% $ # #"%+)*+*'&$&.2*(#$#!&%!    '"&-/BC>E=?:@8B<=7;:E;@:259410.-+,.21042014321496425:93575287:8954810545659:;=AB;94(.9;41025:B@A@CDCEFEDFHIED?B@A?><9<87698410/*&).+(-21421369756:3/46427516326=85743764212464.)03,-+,),-+&),&,.*&%)(+&)(*+)#(,"%'! ! $.-*'(&')+.72.(%' !%*! !%-69A75>=7298B8;@AD'3;:9>7;=;?6<3452/,$&%#'+.6D>6,13+,*70"(!'"1%#0@=:5'!01 $04*" !(+&%$!")+&'%*#"*)'"%(# 3PXUME5,#(#%&',/287641+*/5>EGPTL>A@=CFAGDFC=;A=<90891/0102+020240/0.-061/3863412:537635:98741756723579;?@=9(!*/5357348:@Pd`]USTUaXTR><;4=:;20-,'"',/4104276789689<@>DEIHDFECB@A@A?>=<7:;974101.0*'21.,*&,/013587:=745759853530/)2856>6434975.,3424030*/2-+-+,),/*$)-'&,/6232*+" &, %& #$+*)',(,/7:=32('($#.- !-12;7*'!$#(*-/70697)67/9L9<9B;47B7>9501%"$&(&)20-4@;6.32*,0)35*""%*%""'$"$(.7=:85696,1*1313/50.01/,101(32520532/1/3:4798542:878546;8;751578588D>0-)*#$(+20.321626268547:;?=?<@EIECBCDBA@B@B=>=9:=94120,+#%-+$&(*,-.5-23:<=>743:346530.1.)589@926921'(*/23/0+*./%&).-/././&#)-*-;<52174,)'$!'%%' #()%&+',1>A=50*-)6-!! (2C76"&#  .0% *294-*)-09=>DGIU^RIHJXe\TM?7>8;50*&($&%/302.-34@>86758:;:;=98;:;735-+')0-(#-$(1/13.4897>=634<;3/2542.64251.&$ $!"(%"%!%&"!%*&+,4574-*-,.03.!   51$""&/)(5+0+/9@? 8?8475<80:C316/-0%&#!!$%(,0+2C<4.)'&*,4=(#/'1$'&$/D101",'*,;K8-,/$%,%-53!!"#& ()*0-'1+0/*'(.-+&%"$&2Ob`ZC-)(%&%)%&',/205735?9869;8501-/./,270145805871301-5/238@:65710/2=742303978302479?:9847652.)&*215120,+.42*%/.0-.1246038321., "!"!%#&%$ !&,)*).0/)*)(-0+#   '-+/+0163/.AHB;'7<9798;5:>8/:3.1)%  "%',30-6@21,%(*-05A()$#"&)("+C1'(") (+;F9+01*+,(202(#"#!!%'& ",-01,&'+(,('*.,')(%(.(1KVUMB0/&$(,.),*,1813;:ALIQUJ;>?ABCGJHGF>85397671231./0.610563=<;85141752149?>:5461343156<8675102042589>6#).3/)+)%&34.3=E=CIHUgb_VMF980450-'1+)('*-7430102578:=>@CBADCGCBCB>=>?>=>=74785741,*&+&*(+%)0*+0./5847:6;5@E;<769537423;5684142.,1620.*.12+*/03523/484+/.+),)%!'('('#!%)-)+)10.+-./&.0*%    "12+).3/.6@?B; ?:=<84>:9?1.:/%#!"&).2309C?0-2(+218C+*%"%$# .*"$=4+)*-!%*4=6(16-+*(30+*% ! ")+&$*/-($%)*-*.40-)+*(!'-*2LQPLG=4%$%(&$&,2,+171059=EFJPL=ABADGCA=:5465353.021.-2420-025;764324640139<747303565235;=8576323748<6 &-31,)(/)'&/0/8>F9;KEIVl]YSEJ>;9513*(#&)('('*/8:96202/634368<=@ABADABC@>@A>?<>:946431,+'%'&*.-1,/-&+2*15/5=DE<>LEA:598313./8H>85726435;<3:6412.,+1/230-021/.4-).,(!! #&(&%#%$&()*530.2,'.,/)% ",(.3,0,2:9=:-.'&"%!)().01:952143238<@A=ABCEFEA@><=>?>?:56472-2.#%(&%-1)*+0-)047569B@KQHC=898321-03BG79574230./752/512.*1/3712/0,-+*2),.*-& (# $$'&'%$#$&%)59:2/0&(+*'&# "$+$ #$*3-/*05/15:BE;4HA>6=5849>C@75(34.,5)"%(1/23-4>:2,+)+4310/0)!#!0.&#"'$)%+1%5,$3(*(&+2'#'("$#"!!+0.)"#10+&" "#(),0-*'(-*'+)7MPNLA2'&$" )$,321/.1039=NIOVQGEJKLJHBC=FWZcTOL=?A>;47+3)%'*)(,.5?63201346:>@?A?BGFGE=:<;<>=<979:61.0.4-'(,%(,*&*/01/+105865398CLDK?<8:945675130214240+-13?537512/4/*.1042.13/-+-(-('-+$!&""!! '*+)% ")+(&.8/0(&,(&#"%+$35-.)-*&,35:<87*FE;A:?780C=:&-3BIC;2496:724236353-6942601014737:6467324121.24;:568654<8:9:,'/0-("$%1*-.,*,3036?AID?>=>=:87674/202/1*)%&%1/*,1/1*/0185@76465:562:40/192756353/20310148<3724:67537213/267;98654:<;<7-#*,*'!'&-&(,+2382:EOMS`e[XDG>:=CF97,)%($#(,./;7514203231458:ADC?A@BGFB?:<;9867631020-%$(+)(*($-+(-102/+.-46?;5@76@?:A;:7578:?:76826=>=>8679621-+),1,*.0-1,*+,/,+&-0,)'(%$&%&'(3/+,.*%$&+%(.+(/0*.&%$!# #,'&()/-+(,/28=8:<6DADIHDA@:<>:95;6762871296840;57:3453613:;3545:;794652453204696548:98."(,-)#  (%$" !)/(-16:8@LZORZmbVQRCABIF<4()#)'&),./.2=85351/02568>DE@?@C@>?><8;:97985762121,.*-+&,*,%*,%,1-23.2.2=>2;8<>428J264.%/, "/3+/5201.+)'+,&#&")#!&)('$"$#"#& #('20#(0/,)+/*)' #%*'+*&)"$,/)(*(-/($"&)*)*.-12+*'3ESA4*!&" "'*-(*.2-('(48=<9<;8654<735986,.56:54857843/341219:<954750151/0354842342473+%(*,/(! "!"$-*(45>DHS[NJVjhWV\LH?962,*&*'%(/,(+-2986310.10/1458=BEB@?@A@=?A=9;:67:8521010+.*,.,2*+,.%*5/).,.4/4?=6;6>;:;=<=;<9635645;>=B;=>6@<=27OM@=9/-%.*" *4-350.1+)'*+-&'( &)! %'.-% #$!""!$(%(,$*0,*-+)+'("%*%$&% ()().,+)&" %'%&)*+-/.,-(5HNI@;1)' !" "')023,'*(.5CEK967;<:8=53842.-.02<83234:942-,.10979:524/020103213202*-*+%# $"!$&(-.(,56AIFHQMPRUknWRUSL?>53.-04'"%'*'(-4:97573.0-/0368;@?<>B@B=?:7:987:4031.-0.0-2+/.,/.)/8+-074=;49?29>C86CB:=D=598945237578<;=634620-.*)+-,/1/,+"$+/,12/+$'.,*0,%# " $%! #%#!%/&$&'*.23(%'&  %""%&'-,+4/0,/67=2H/9A9-5A6,+KQAE:/71$ $3/24+,+%(0(+*"%)! "&)-"%# ""&('%'%*(')0,*/*$ '(!&+ $"($'.'%)'%$ !(+,)+./-,&6IQH>8-+)$!".0.,*/,+6;DBF=@>FRGLDFKD:9:;@82/378<40-.1<520149>96512035689803./2/-.-+,01313/.($,+(+' " #$&+/-.73:?;6573,)/./12679==:7643.1/-20.043)(')1.0/B3/1802970/>63A@B897:5410/.),.-+26-( !"%.1.*,150+$" "!%!!%"!$*$#&*.-.1-',&  # " #&'/)35-,-1BD=C;F&:CA6%39;5@U;8;E=/+&+-.50+,-'%&,),+&$% %"("! #%"+0*$%$#),+*)./'% $&('&$#"#$#$)"!$#"#%#"+.*(*)()(%3ELJ>2)!! "+,*'%'&*'%-4:=EQH<>G@CNDCFA;7<87326<:=542067:354/16>:4523626537841/,/,*,/21042/-$#(+*'(%"$*0234A=@A?EHJKQ[VOQN@?:;840)$'($#(-2;:3510/-/./3756;<>?>=;<=:9586963/20143,01-*.,.32/,6-/8./,),*326>B@<>EG79A@;:A=8676794:?:9;6475-/(*/20+.-()"!(0139=*'#!" %+)%)'!"%)+./,),+% & #)'-241-*5@H=FC?C.>6@OB6A?:JPE37>@IC@OR\_QJQKFA;76420)$(&$"$%*4><963/20,-02148;<;=EDA>;<:6467321/01./03121.,-.-30/*)-/735?0.086?GA>?<8:>:86:6753813587<94321/2+*+/3450-)&!#!%+230($#$#! %!"'%,*"!*-.42)',+& +!#"%2)3531,/28A=K:?!78EL6'5>NHC;B5613.-031/4.353642068/.0/32-,-,+),'),-,/'%,/.*'&'%  $)132352:>=;?AQ_c`XVLFA9840.+%$(*,098<20./-,./.047;:FK%&68D36BG>,2-8)&% (.45-)+3+-.(,4,&'$%&%# "!'(-!"'$,52.+,.&!#-+#!% $! "$#%&"&$#$'*)+'('"7CGI=("%&*'!%*+'$*12AKMG;EBA>CL=?;A;3436/-,.,.2/20295323254.,-0.261020,*('+)-)+*,.,. "'*+%#"!! #*+15210273:A?BIXc`U\TMG?@960+2%'.1219<89<42/,-.-0347:;@=<:=<@96353012/21,0/30-52*-&-*$&)2140428?:>=;846<;641284./1.+,.,(,-/2/0/.(%!#%$#!$"#%&#!!%$"!"&%!%0+/2.-,&(%"!  $(-+*.89@9HA;L: DGOB(LC652D54235, $& !$+,4:3+,3014)*0/%#"!#(# "!"!'&' #+*%$'25/'&+'%'*$ !#"!$%')'%#&%!!%'&,)+*("5AGF4##$"%$)(%'+-+%!%04CPSNF:=GB:98:32/04131/0*-0724-3902347540.1/.01.-)*+*%(*')*,/-)*!('%"!  "#(*.30-*.05GMKHRZKQTPWOHC91),1,(%+.1:=98<510,0/)*-235:;:8:<942370.-041010-.-(*(-,&#" ")%" !"# "*'" !"%"!"&%+/*/.1-)&(&#!  %$#$'&)20,.9C84NMFER9C2:&5KA4/=H98J/10$-8 "! &*067-*+1*)(/%!!"&  ! "('$"+73/+./1)$#+/*&#%#  !&# !%+*&"# "#%+()*)7BC>3%"#(,.&"-(%)18BFBED9D@;=@=><03420303.(/+)1/431.*/13202310-1.-*.+$*,-01,')-/,-.,($!&-*(%$! "%$#$(*/2)'-0299;<61+0,'+/125:;:9;?4;:6431/0+.2+-,.+*&%-,&).*+.0/16<:=B?F149B?7@9<420202.0306/,+,+/)(*$%$# !)&!,3$!$&+.$#%(! "#$%" #"!$&'/2*/0.)&'&#"$ !"#3.,+*+-/80LVFJSNF6*1'?68UICD>8@+/%'8A$ (,/4/'*'*/,)&+)&"#%# '(*&%*76420/'&%*&! " $##&(!" "!#%)+(&!9A?:."#%)+#!&%#!*/@B?>HE8?:;85<7;D:693-,*.) (,01+,).+076386-*-.-*,-*,*+,/,(*)+*0.*"#%'$#"$+"#)')-.'+0/06=GQPYRWJD;?FL>3,32+*)'$%*,8>?;>9;40/.20.06:@>@AD=6:8676545420326801/.-./+$'%'&$')*" % &(&#!! "$%&"! !"$#(461/+)'+'#%# " "&,(,2),571fBNH>J@86/-/+54,/)%& #)+1,(-(*-)/+&$%"! '&'&"#&$-26?1.&'&%"!   ')!#($&$#""! #*+('%"?>=954/-/./.-0279:7A;=648:<742.+*01,)/-.1+0/'*'"&/,+051;?>CIE:?EF8E?:53245438:2-.3750.*)-/+&$&!$#$!#%$!$'!(+*"!!$"$!#"$-3/.,+%&%#  +)! '(+0,21,8;BNPJMA",=;eECN5A;37879<98:910,'*+*$ *06/)*&,/1656/*020,-,',-,/-('()&'%# "$('&! #%& " " '#*.0/+./48AKDR[RV\V]PGBHK;2-&-*)$#&)*0>8<><45/1/.-/032474@;B<9676874324/.,+.3/.+)+/*(+(#,2+"$.03;9;@=<>A?AD?>97465238:1/-,.,)*,-+*)(!"!"%("("!%&)*.# !  #!#"!"'.20,-+%&!"$" +#! "!%'&*-57-87+0)39.*&%&(!#),*+,(*-*32#$'#!"&% !'( #$!!)3/&(%# #" ! "#$"$#$&%&%'+,*#!$;B@;6,%'$!$%+&(&*/-8>895?:6:97>C>7-*,"%*+-.6;7>;=;545402/+015368?>?95745475/-/12-.,060-*./0+,*'-#(0379>9?;:FL>@=J>;701C#.!$('"(# ',(*+/*+01,4/%"'! !#!!'*! %+%",0/)-%%&!! #  "$#$#('(&#"%,-+'(%';8:<9;9A?74?=/2-4/-*',.&)$*)'*,1.10/+0-./,.1,*.-/,+  #.40+'%"!$#$"!"! "&"%').535249TUIMLNTYa^OA971-.-"!%&-26:;=<65210./10/37;8>=85678:851021/13041/30,2/,*4+&*),+(!-1*9<9;9=A9>CDB=?CA;870369613:@9410)*,' !$#"!#(*.) !"   #"#%'0,/)$!# *,& " #&10102&=E@0:?DIE!&5@FBG9?<@2J/3<>*3(,45+#/& !0+)./,-340/,&#&'"! !"!&)"&'!%.,(.)!$!# !" "$#$!#)%')%"+,*+,+(!*:>=8.! !"/6:>@=D=:8?>A@>7B:6.-3214-'%&)#%(+)&')(./20-,/./2*212/,-+,"!%'/)%!"#"! "&)#!"$#&+'$-,78>:518FDJTJUa\UNCB8/+.)%#"!"#)04;@?>E576310475347<=@=7;5:856212041-/0.04-+17/+/).)+0.-<48;>=E=@983,068625?<6/,%! %&""#%!" !$#"&% "!$#%'1010-&#" '# "%'%#%-3(#%4873:85-4)+(/*6# (.)+.+42+-'&%'& "$!$##'.*#'-$&+"  !  %$!"&$(&%#$(+(+)& +:@=7+! !# %!&39MSWU^UWcYPGE62.2'($!!%(+2=@?<=457:73/21545=?A@;979769:50./62.01,(*.-16+,+.+0,.,/8;B98:63<@>B@?AB82/-5:?>549<45)"($"%"'"!%"%  !" #%'#'/21-($# $%")")%)/.6>*LHD@BJKH@#$5,3,18:57@/4782)$?(94173#  +*.,/31-43+*$'""$$!$')%! #")*&! !" &+! "#% #&#("#$"%'*+(#-=JF>2# #$!,5<@F8=A?GHE?57E<3.0/012/-+)$%'+#"$!')-,-*-,*-*(32' "'('+,+)'!&#"!$"&%'(*)()-2-/.2/15:8=NMOQWJOSND=C@;:4*.)&)+/8>=<>:5:><40/.023257:B>;=8534:;72/0/10.150-.582*)'&,./4/,0?>7?16:B94:;830.101249?=;6;437?;64254140/3430.252.-1'),./230.:;894:<:6:@BA?F>49:3+)'%#,1)(# &$)()"! !  #"&*%#'*,/,+%  &!#%"&*CJOICBACIDC@: 369:CF935OK9EALG>;EHC.0(# *+*,.0+,15/$"!%$&($&%(#$&##%&!"!"#"!!" !+#$&$#$"$#! " # $%'%&18?A@5("#*""$&(3?<4A?ELJA8E916786/1()$!+',('$#( #!$'-0( "'*,+(#$% !$+&% $&(+-*&(*.)'(*,/),/3)039HJBF@IRUKM<;RMA?B5'$%'$#'4;@<828942/.-/,34=:>:8:;3469?<67651753251,251+/1,*,-/.1.2/045786>67:@<@F6.-)" -2,(" #$.-%$!    "# $&"!&*/3.,-& " "#179:AFE;65'>;DED>1BEDK1>5L?:KA5-3/.#. !*+.0)02-/&$!#$'(#%)$" "%"!#$$'#!" *% (% !!%"##  #&)+(2>:72,&"!!$'")+/2HA=;><2421(*0(&40*+7,$')'#"!#&(& "(')(,*%! "%#$')*+),)'(,+*,570/-5@ABA?HTQIE:8547;3-13530:1,*123,'),*12345873769:69=:32,*% $0.("#&" !$ !%  #"&$%&$!#/135,+)$!'#$'((,2@=;@A>;D,1-.04  $+-./+.0.0,('"#&$#"(!"$ $#" "(*& #%'#+*#%"! ! !$! %&%*%3?=:6.'&)##&##$(+1/1=9:;4?DE9G@A=@EA=5/27:./'580/3*%$&+&"$!"&,*($'*#!%"&('(+*.+*'()*,+,*+):6.49>?ADKD@9CMWJC8/+! $&*+/;3@B?696730/.,(/5<8;>79;@;879749<:37341/40432302054-,+,+(*,.03.:><>9=<0)&"#31*'"('#$%!   "$%*(+'$%-971*'%$.$-& $'"'(26++BLEA:7(,@>DF?BK@34T987B362'+0/& (*+0+/5,-,-/($#"%$(*$" "#)" $"# $%'+&!!%#$#$ #$!#!"%#!$ 4?A>;3($"!$&%#%!'(,+47567-9;D<8?;?:G<@;147:71)'+61/&" '% !#%')'%"$! #"! "!&'&%'),+.*(*+*'&(*)-0-*(*,;6/+.75>=?@?<7=FI@<47*$"$&(&+8=:8>;397872/-*-0178;=;?7=@:=?>901./+,0,/102104592,/+0)'+)+-20*+$ !.3*)')" !%""!"!"/6+)%&*39751*%" !"!#"'+(-,*,(57:7/&(0@I@715,5?FDMBH=;3@?=8,"'*(%#&!&35;6-;>QEF@:<=?=9<458963-(,16-+&! $&$'+('$#"# !" &$'),.-/)*)('*)-0-+053-572<7=97349?F@B?452-"'(%"$*7623=A9:8=872.0./0.59<9>:6;>A@?=541-),0+,.012040/1*%$&( #! )2/*+0/-.-("$# "$"!  &24.('+39:53.%$!"$"%-.8757<@,9;*).?A?89CH:D@K:C3ZUAM<16P6-%,0-) ")./1>53-025-'*-).2/+'#*%! !" !#!"("!#$# !# %' !$&(%" #$4;:786- !)+'#" .14=80=;EH?:<>@>;54736.+)(%&% $&%*.,'%" !" ! #$"'$&(+*+*)+('('()+().%')*,:0301301=GJKFB73,(*')&%&%$'57=8>98:=:<83/-*1417:=:<;68?;=DCB43-/()$&'$%#"#! $120./)0/-+% #"%!"# ! "$+/-)*1<813,%#!  "&#& !)(%./75:=EA:E<'$%/@6;@=A;313153,26,31-*&!),)$ ! !&$%$!  #"!  %!"'57843/(!$(&"%'&%#&"#,3:3/-:5FB<7;B<>:90,& "#&)'&"$%$ #"$'&$%')+,-*+.*')&'%)*(&'#,*101+4/.103>=DE60-+($!#$'*% &768:7:7=:<:3/-02/3;78;46343,.1.,*     .6/)(*'()*)($)&!%'&"#$#" #*)%')*3;:70-'&"  $'#!'%.4+';:>BCBGEC.- *,.B/5>GFE7:=PE5)@0J<(1(83"  (+1ED719073*+.1+*'&!$,-%#"$!"$%#  !$"  "!$*67<63.&'%#%+()$+21.(,;DGNPC152)'#"#$&%$#$# !!%&$%'('(),/1/*,-*%'%&*'%*53,($%)36124590=8=6+/<, !#*51643<89202+$! " ! #41(%'*&'$%"$"!$#%)&$ #$*'"!%/8901-(&$ !  #"&#& #03+5KA9DBCA@CIKJD6.>5/D>8F?DA;EC8:E B&*0%"(1"&($  #-1B@E:538243'+5:3,*'('*&+' $"! !$"   ! ,57;>5+#!+/*%#),10,#$!! "!%)('&'$%&! !$&%$&)+1+1/&$(%'%&'+'+/(')'-41.-.976=?>50+-' &    !".2.'(%&! !$)'$&!# !$&$&'&  $(#&+6<0+1*&#!$!   '&$'*")(*547@A9>:=;I>=D@6"@84861.,),562-3-(+-+)$%$#"" !.679@B7*  % #$+(#! $'-/32( "!#*'$&$%*)'&$#!#"!'&%&)*)'('+./,+12.=:+ +$&$%'-+&(,%')&%20*.-437=7:563-&%('"$ %#     *6)&%)'#%#$%'!" "  #')"  '+)(.5;-)-('%#!  $#&0 # *,1;<=9=AMB=@H?/';?@A@<;AED@<31:.$H<5.0.%#'+$ &729G:52-,-/46,-37-0,+2+&$)'"#  !"18;>@;4-#"("!)*)'"!'0.1-( ! #"$#&('*-+&('('#%" $"#)'&'()./0/5@DI6& ' &$%&)'&%&$"&#"$3-(.245/7687;9-)/&!  &5&)'(%'%'$"!& !#  !$()"!#$#"!!#)+*)/496*+-)(&%"$   # $)+-)3697/=DQ8DK;9C3'GJ?A?=@AGA72*1.D4;394!*&$() ,.7JB51/.0/8<8-*31-04-)4.'%#(.*%$"!! &28EA93427560=3*:;512-%./0(%"#$%#! "!*276540,%$%##,5+"',&,16019/0./-*.0/+(')+$" "(!    $%&'+.),/+1.24?OVRC9402.)!%$!" ! "&*+-,-4/10/40%"&#""#2/('('*($"!"!"!(&#'$()$&'  & $'(*./.-,-/,).,# " !(1703*34.334$->9=JB>743(!)$+,$ (/374016;8346=6);?4671+-.10()%'&"$"!!"  ! /56:?=973.*&#)+%$!$#&-0/2-.+*-01,-52./(&'+&$%#"# '%#%$%&(*)*,(+)'./;LPWRA3:9.3.-! &%!$'(&%$ %!"(,.2-2542?1'% ! -2)'%$'-.-+-'*&!$&$ "*)'#!%('(&$"#!"')*($'+/0-./'(,&#$   !#*($.4.@E;D90>=/,.9,BJ7C=?:AD96?6F/3:9CD35+7C)"+'+&  %.341016<7205>9.>=1?G941010*+(&!  " !:>9=BCA:60/)& $(+!!!'#/-0*-*/.*.0.5-+).)"')(!#!,# !'$!"$'%&%')*-.,+-429>EQTL@7485412) %+,&%)+(&! $')*+/1-/-.04/-"   "  "1*'# '.*0*0.+&(')" !"! "#'$%&%"!$)/0-)()+,-/-*+#%'" " '*#%+'!)9/-,/0>A8(;7512.)"GB4F8AJHG;>96;0BF84-7GE,+1&0"&! &12/3237:456=64?B6E5ISF@=?<;@=>=D?4*2JH*2/,5#.*$   +12367<967=?;:AC2052/+*&%" ! '26232/19@521.+($.(* )*,)&)%,1+%("#*(*#")!*/)&!%$),&%+0/,*.,+,(-87@<8=:@?<:<;A1/7<7.*'$"! #!!*01270/234>=2-( %#*-$%&'*.-')%'$"& %($"'"'.0+)-$"&#&(,)*(')+.5/,2024@PSUTG;8310407IRXWK;3.0143>=<6354#%  #!# !#$!"#$&!%(&)*/*'+,('! "&# *1()(!# %(%$'*## #"!$'&$#'&)('+04+()23402/')("! !! !")#*).16,$12149B<928,/7." FN@=>LH@5,7(14.9,.+*!&  *0,25:=ARKLI@<@K<4;C:.,+*)&"%&" $*&#!%.6@?42<83:<5420-1/+,&*+-5,($&'*+.*-/31-0204-(%+.-2.-*,20-+)*+)+/(+1)'.-*-+./,0-+-,/08@805>ELTUPF91.2,324.12:67=:7120- ! $&#!( !'! !$%(&'%&.0)#%$#%" !"   " #"#*1(&'%(%&#!"&!"%#$#!"# %&$&"#"%'+('%053*&'/3.,02/+&,&,&!&!   "&$',1-;:2.4<04>;=39ED:84612762/-/21.2./24041/.-41.-/49451,*,131./4/+19/<8/32-/26989;CPOMQTQLB9.1-/+/32453427894<7683/+" #)'!)(!(-$!#"%#$&+,&+,'$%!#'$ !" "  "#!!"  &#+3+"#%"#%&%#"$ %&"#'"!!"%$"#$!%($(,-*(*/1-*(/454/.)&'$"   !'%,+1;718256/D;95;?>GKB;940?,KVC?CLD;GEJ\TQLC70WO=3>@7:L9565721420/./261263012140/,0.21./-19636/.0+063+4JA024704>=CMPROGE@93/.,.03.0243;<7398<=63"!% #$! #("+3%!"%#"$&%$%&%$&%!#$!!"$%& #! %02&$&# $"!"!$%(! #&#"#"#&)*+0+/*()-4245/-/.(%#! " !&#-./0/45:93/4;F=5:?DH@96:758HKD?LI?A;BLRIJ<;KU<80DA?H=0*6*')*')!   &2/8BC?@=8=;<0/+04-&$'+,*$ $' "#$" $/498?B767?=5798<67:41234546>9:?4/0638;9871:257930-3723./5/./0<:/09A:4?DHLKPUNKJG?=9513513.0.-/43.,12435769?8231 #!#!"&+$ & $#&%#&#$%)'%$'$'$"!$#" #""! !   #!#$#$" !".3+$ "'##!"#%& "%'+ "%"&(*)'+/3)'*14242.+),%$#! ! &!!&*2./4;?913=:30=?F><5:8/.D?:RHDGLTI>L@NYO@?@KD4<7;&#*'(*  "+3;A@>?C?;@GBC8:?97BGB@=6=D9@?@:92<;>58606859;:>QA=GIGEO\ZVPMD7576.1/432324.4,-.1010/96735365=E>:4'"#$&%(-#&%!$*),)()*,-0.*)+*,'!$)& &+'&%!")$&%$!#"%" " #"  "!""$"# #)%'()&#&!#-53%# !$#"$&'()()!$% $#" "&') #%-)()$&*01)'(1302.+*,&'$#!  $'# $&#"'2/,(,6801=34:28:C@6DBC8412$@LDRcBKC=HTF8PEL?IJWIUL<0>4=5)*2;-  ,6:?CECKLGC?7;@8A;10,0.-/30/*$!"!" !  !:IUWVTOW\YZTMQ]VQSPNVW_[T^KIY`RTFGTOLKITb]WHBNMCLFMFBMNSJBUZMSPQZXY]ZRTMLDA75424,-1/04347640105/./.201620843487849:>A:3$+0/12041-.542-/189021079>7;8/2<681*143.,.654.&)/(*(*+'%&.'.7+&($%&()'%(,+*$"!#+)"(&(*,',$#(/(+$!)%(.,-'$*-()-,+(),&#)/%$"!#$&,4*('"!"$%+,+&(,+#!"&'%#%&% !#&'(%(,*)+&)543/)-+(%'%# #"$%&!*,4+2/8:4<75421;EC?=@;C,13=C(QNDO:BV*;?AF@;?SFHLHMJHSQMEB@9@7-/+-+-15)&('&#$ "!$#$ "  -Pdklkicejklmigfhghgfdfea`e^bfb_]a^]_`aXUVUTQPSUTUVTQSUTSQPILKG?<=7205435/0103-.-1/3745747203/1.0301/9:9341467A45-(2=?BAFGEA<=B@>=A;<@=;=98;6;BA@<67:@B>7:=9<968423+*'$"#$'&%&'%! ! !!$&%"!&(&(&*('-,0,/04/.1-(&%$  "#%$'(&(.)-,0529<1=?8=>8;4;/54D1QFE;>L@7EBCbXB@GC9I?ONDH@5A=IFED2,"29  2:@A;FTOKDID@?6<=7/,-+)+,52*(+)'$"('$!$($! $" $!+,/.0/06=9631546868767124648:8785896567?B>78476976;536.1602562873103/-/.1246:636/-0./3:247A@?<5743645639.#'.+-.-/15237436=>:689=?BCD?=@B=?>8:;>;=A=><@=?@A@?=>;>?<;?9787=<;8;@<9;65469=:;<8;958:5:9<;>CECH@?<:;9615:94/,+)(*&%#"%&#$"#%#!&(*(*'%" !"$#$$'&*+*)')/121543120)(&$! ""%+$##"!,5*1/-36>70@>07<4154/34:EA'HFCDNLEAGAIhOS\J?9X:MGCHG@A?I>HDQH+'#%43%  #0;:8?NFGIKIB?<8<83.,.,*,.1/,-*)('%#"!#&,)'#()(&%!#! $!"(%&(,+/246;897/42157546:8351215854>@;9684:>98:9BEHFPQONJFCA=>=DE@?@69<@BE@BC@?>858296;=:?BFHFEFIA@CEC<:04=:3)($"%# #)(&'('#%-*&*-*'#!&# %'(&'*-0+,-31-29;4265/('$! * !,)*!&&$!*1.+049=:2;97598604:D?AOQIDG?:;:3./2.,-01-+20+)(&%#"%(,*+'.-+)%!$# #'&%# &'$(/1-34767:7*101414291853769:869<:879<8?DEM<935<6171/0-+*3*/-1/1264212024<9:;:83/3231275<:9:53060.31672470&/)0.-+'+/54578679?@;=?DIKOIEHKJC=><;DEIJHF@EAEGKHGHGEFHMECFLGIC>=DCDEIHTULHD?@7<=CEFDGEC>878726469;?FDEG?=DG@;:6?91*'%#"%" $+)%# "%&(,(%&+-'%"%(&% "%'&-0-03;2,0781260-)%$" !*"$),),!(%"!')1)/1356750568=?IF>;=;:=;"LE=F.*"'+4A4,)  !".9@?:=IOLGHB><94/3/-.51,(10,),'%$&(,(&*,'&$($$&'&#()$(+,749727135-64239=46<36;9:6569=>=8=B=7@?AHMFGH@;:369=6:6/040+-2)-/0/*1253543/5378=595/./010.236375:8;9631204086376123/,.,/+/,/32785>IE>@B?FCOPHGFDIHA?>;<=GHIAAFE@?EGC=5/4?81/.,+'%(#%$(&"&$%(%'$"*-$&$&(&"$&*-0/3589=41.03120-)&$#" )$#%3(/) #+/6%29A?<;1/3;;75 19?NF2@4F?/kVNC>CBVKANIOJNCB?BH@C?>;69;898620201,+(1-*0101626796>530123+12437145;<7.3041735257630,+013).14;:87>?:;>A@KE@?CGKCEA?<:<;6AK@G@KDCFGHIJGKIHIVMLJF@BIMRLMJNOE@97C@:>8<=B>AFMB?:76:7:=9:9GFEA;?EIHFCLI?<81+47/1/.,)%&($&(&%'"!&*%)/*(#)0,$"$"%'+,/6:;5341.162-('#"% !% .,932# $'$&%-.0=?;76+1218?EG>=;8:47KEMC<=@DMWPB]hbI>Qc>MLANF?=/5%7=4@5-(5   .87?IG?EOKIB@6013/1-).,')+.1/,/,+-/,+),*+'&#%'&($(*)/453<95@C978;86057@685078;:;74:;=?;AD>;<5@BGHFBAHB>75475430*10*)73245153/547:5376;50+053.367658636,.156/168423863-*-0-+1465B>=8:>=8?;>HFDFEA@H?>:8;98BJHODEMIDGIKMKGPOLNIJOJPI>:BAEGPINPQFTME=:AD8<=;789?HC>AB@=@;:?=@AHJKC>FBHNMEADC<:;93240/0(%)*,('+-%*0(#"!#$)-,')+/-&$%'"$'%&*-1273/+371-%# *&!%212' )"(-:7=CD<71+18<=HH:1;EH91JGJF95;@9731+,0,(*+,-/,+,/2-.-)(),.*(+(+,()*+321351:7:=>8357563.2:92.26;:;>A75>?79GJH;2<8GCDCG@?:BC?9:;643-)56-2,84268623<8;:;<;876.+38462<89858:5423.426128545761671,-*-89=CAC=>CG@>C?@DEIHGHAC@?=BFKNVCFOLENTOLFMKLKIHJKQLH?9B=@DJEONGQGB5=C?;B=;759=HB@BFEB@?;:=72021/'%*-2+)+0*.92! $#&)'%'*+($"'%!#&%04.,.3461+.561-(! $&%71(##"(,<=/(' !#&2DF;9;F@=9436;EDBJB?;8:;=39414,&(-0$/46-*4,"&%$# !$&(*+)$#%(#$%+45+(.521*-01/-'  "%# $*& '"&*+&"!+*8C4\NB\QRIF5ND;KAIEA=AFN@?=34+)(%*!  "%5E:@BGKG=:AKH?582132+./-0/-2032-0-*+./.*),./1593167<>HE8?9<8650,76054679:?A=;>;?>=<:;AD@?BCDCFJD;:=@<=B836748;8@2,215609=7:8?;DF=<=?5:9:6>:9;74545789;676:608:8642.-/;8;>BCB>@BG?DPUMEKLFGQNLRNOIODBIGLALPLKNVTSOQNKOSGCF@<;@;153465.(&,-!'146.,+)%(%"!$#')+('$(*(%$)140,)0710*,/+.+" -#$""$")%'+3+%#*+3;=E?7'&+7=A69?6:CFBA:;270+6.8>E6W^dYED=75#!:ATMHDKM9?6:>;<@/03498:8>?9E=HGJD@A@?<:;718:=?BFA?A:7678:9=>:9;<62762/8<6>AFEB@BDHBKWVMOMPMJSPGONFKDJFJBIDF:RWVOPVRLVRPXTUPJLJED?@9ACDJEJMHJFINLIFA=><7;7>CDGKD>?9:<:G=2-O;C@MFS^c\DSMDH0:H\]RG9I7NE:CGBO?;/.#  &2:=>IKH=A?9896064354120/85352-/10+12/./03/1/353646:=>BK=<;G=;30;=369620-6>EB?=@BC;8ITL9=AD=;GDK@ICA@A>CGAF>9<9<96)9@:>@:.65<@;<>6797:;:;<9<@7;<67284-/<7=><@FD?CGLDFQROIHIKLQHPNPOIJGPHJKRHYVTRSKFJLPXPSTONKIKBD?@?7.9=B@>FOHE;9;>;ADEBEDB@B?8?=;72/14.)/10*(,#&'&'(-*,+%!$#" $(*%(&#%&*)*,2/201.+*')! #7/$((*0:*#&51.953/%13<7:8A:8<@<@FB<6 1;2PG9L?MDU\CFEDGH0@NMFA>G6@D<=@EB6:;0)'    &+16CA@?9=A;767861431/039:365130/01/0/532143487686=8>H<6>ED<71;<5;>:;92/7<@A?;?D<:@B<=:9GA8>EBCABEMBEFDJDMC=9;916>=?A6;867BEFH=<=<965696<967><;7867:9<8;5379<@5>B;9325;=>?DGC?EGMDNITJFBDCJHORMJILGHFMJLMYQPQNLNGOKMKMPVQONFE=:;?GKJNJKILOHGMPLB=A=>;9/8?A@=HLF<:;8;DE<=;@CLGC@:A=80121/-*.-/.+*,'&*',+)'*&%"#('(%'&#&)&)/2310321.-+*-&" '" "(/& #)+&-94'")5(-/)+-.0+3489C?B>4=@<953/);6LBKE;LAW[`INGSF3EYQP?DEI1?<;?>I>6928950-! "   $,46;>@;7>C?6D>639B=8D@<>:;:7<>?@?FMFC<=FKE>CHAEBC?6D?A=JI?IFCJAE?E>?;C;>:>:<:9?6;614=>=>9;:;31:7>:948?>=:=87:4:986:=EH@=AB=:;76:?@?DHJORKFD@OLGC@BEMJQPQLJGIJQNIJIKOMPRJFRIKLIHKROMIGEC><=;674;BA=?IOG@;:979EA=8<8;42101/+-'*,)+)$)')(&'&)%#!$"%(%$&'(#%&-340,-0/,)&*' $"%#%/%*%/%"&.>C,(0>)2,"*-*.4535=?;CB@7@;698:94316)&,-2    #),49746@=;?>A?5046:7;>936<;69<6:?8498:;7:=649;=C=:DG>6-9?A<>@<@=>E70=@BACSQHNDEFPNCAKGMEAFEBICDF?CICDACBF>A=K@;89?:65=;=<:2@=;A=@:8>?D:59=;769=;<>?@FNHA?CA>;7>A>AEKONUKIHKEMIHFHLKGFTRUSMLIOMOSFCDGUVSQNGPJPKEHNOJHFEHB?<@=BEMQGEHJDAHMFGBA=;417BHDGEMQMA<9456A:97:;?EAHB:5785101,(&'+&%)'(%&,&$'%&)&')%(&%&(&"%&$&.21-*(,+(&# &)&3 #$*!&#-?3%+/8&,$)5,./538;BGHC97?5;=<;9GIAB@CTMD>A8>AD>CbTLG3RVONKC6L:7BC74713/)6=*  !$,7254545489;=9?@6898:8<=AE:=HA@7?A?A?<=FEDC4:AEFNXQXPHJGOF>@NUQDIHPLCNMH?FBAGDEAD@B?8;>=>956?H>9;?H>;:C@AE@F956:9=@879310.,/.)'-)#&%)*)&)*)'&#%-*)+(#&'*%#%$#(/0/,&'(+('$ !"!&%-! $*$*1.#70"!)592.-506;6@KI?8CE=;:783OLMDBCPOJEHAJMD;=@NQWKPGV^SFJPHE>?D@9<26485*57, &01875<>9:99;=8CECF?:>@B=B;9?=C=9BG@=HJ@BHBA?CDC=;5EKMRXVQWHGCEI?AHWXMPIJAGDFHLA@ABFIF=8=8:FDAEK>?HL@;>?@;A?ADFB>BGI?9;7><>C>BEDKIKFEFC>A@89;?C?HLPRPRQIRQIKXWMLROQPEM\YKNKMINUSY[RBDESVQZTVOWMHJQHICFHA?B<79A@DHECGCGNJAECADI>?830.6@=:B9<;=@98?9673/-*-)*)+,#$%$#'#&()'(+-)+*$%$%&%&%#(,/)'&%# !"$+'+*" %.*$(09>(.)7679.03.A@:?:5>B;7D745OHTPIHF7B;BDFHEA9<:=78<@9=DJBADKLH@;<@=A;8?JPKNLPOIE=ABFENHIW_MNOHAGABAEGCDBC@JHLC:89=KAFJL@EGPB8<7=:@EB?AEA?@=F8;A>@<;GC>CTEFKFBCHFLYSRJHJEA:@;CHEKLWVOPLNTMQWQLSTIJKPFBNLMQNQLQTMDBAUVSRWPNR_XFGFDIAGEIEFD?58<=@A?@CECMF?GKBEA=>:31;C<@GMTWK>?=85756<74,%ISJE9@:7GH=DH=HC@>[JLDVNF?LDH@;ED;B;<1DC1&+-+'     %!#)3:989<>=;>CE>:=95=?76?CHOFCD@?AC<;:785:C;:DA@>HKIKG?;7>EFAGE?@CI>:A=>;EC?AKDACA7A7?B@@ACFGMPRHEILECA;4-6<89=>=AFPF<@?:364-758=<;9>203.,0/-*%")(*'&"',&%#$#'(+)-%'(#"%'$#"$'*+$&)+$  ,%$)(&" '"'*&1+6.-*435>A:-.3DE7<68@;7=CG=02+)(@LB;CDBE>CJANDIH?>@AFE>FOIN@8EHPRE:98ME/-*   "&,56:>?=ABA=<=?<8:@<;@HLGH@B?B>;:;=<8A=9=OLJWNC<>?H?DMILIB@LMTYWJ<=>DHDEFACFD?@F@AE<1<7DBELOLHEFDHKLP\XPOMGE?>EOKGKTOKQNRQLPQRSLJCGHJNPONLPNLRTGC@EMOMLPIGCKIJGFLMIGKNGILF@?CKJEIRVJFILFDC=;427:8=>9>BEF>=947858:785:B?=9142/0.+(%(-+$# "#)#$#$&(,+*('$#%#"%*%#&*%   $&!$!")'"&!)!'+(8329-2(,/7@<'/:>:97589>@CHE>7;?:0:B>?=<=?@?C<>BC?>@AGIJMKGABAE;:;<=;@DCE=@;>GHACLHBA@FB;918DNBEFHIJD9AION?;CBABE@A57?;FH@EDFHLJDGMOJHMPHJPHC@CJGEMPQEGKNFDCDA?;65:ABAF=K@PHEAHJ@LG97EIBC?>)"  !$0A<>=>?<:>=9?C@?CGF@=?@BNEHADBF?956@CGDGENKFCEOKOLG?<5JIFLRDFYRCDBCEFHFLC?=DAB?GADONJGIONIGMOJIKGBINKPNHIHNGCAB?=139<>;=>=;768:8374378;983;:5<753/*,)*)+(%( $($#'(%'+*+/1,')%'%#!&')%#"  "&'"*%!+&%"&,0%'&6:=47*<0")6A;>;0*26@7DFLA<7C?-.9D;@>F>DI;ACO7?>FKMHNCKM@DC@A@KNSQGN>:$($&" #    $06?<=87<><=>CIGEDA=9=:8<=:=BF>=78?ICD=DCE=86CBGDEGMJOUSHKJUJCOBKLTODARUB8ECDJGIFCIJ<:DGEA=8;45>=BMC=8@ABLJE?AC?CKJLHEBKOXMFKJFJDJFLRY`ZUZRLOMOLNJFPNPQVPRJUOLNB=TPOUKQVIKUOKOMUOHRSOSQHFLMCDIDCGLJMSJGFJIFGKQSNLE@ABGNJOVWMLEFCBCB=<8.5=A@=537=:5/.2469=?92157:6:43,+0/.,&-%!"()+*(&$'+)-.,&'$%'#! #$#" !',(%#)$'&$).(/+!& %',8<>:0$(+'0/8JHM95!0D69I@F?GNJ/DICECA;=?@=FB=GB:9>?A@:>A=<=52@D@ICDGEOISNRXTPIDSVSDHMQLODK?5>GEDKIH@FOSF=FECF<>;7BCKJHE@BJPVHCAF?=>FKCGFJ[YTJMLGJNMPLKQRPVW_Y\SRQNPGNKHQMLNOMQPEPOHQJM\DLSUWRLGPLNKHPLOWKHIJGECAFHEFNQONKFCJHAOROULKDE@GJZYORJIGD@A:8417=;:BFB?;=93254231.3.15869.078236:2/30*,*+,6+ %-2,&(&('(+(%('"# !"#! ($)& (/10+.#)0*$%' )+90:C79)+%459GMH;3'&?H?L7?@AJNGF"BC?E89;=CL;?KNDEFJSPCFD=IWDNDKJMBF6=87#.;+"    #$)/27<=>BIEFDGOIEGA?:=;@?AC@>?=;:?:9;@G@>A@>A><96EIGDILTRKOXJICK][LGPUHAIBEDAB>C@DFDBGOYPKDI@DHD>@A=>JHNJCFK[UMEHA=@BFAEDKHPYQJIPQLPQNLRMOWRSU`XYVRIDLJMKRPOPNMPLRSRPOSTFKPXPLSLKIKJMQLHCHDFGEDF?ADGPNPORLHPOQTKFEBC>DCIMPOZVRLKGCB<8736:86CFKHA=C632013.+),(+12032142.39134/(&)(*-*/*%#$(,.)%&'-'(+%$%#  '##!)#0/71-8)$)-$2+-02039OE=@6<>73C@;345-6B?<=9>AHD=<>%;BAA:=:@=F=G;CLBMHRFDKSODI?HQOAHINH@>:=<8"/63&"#   !"%(-6=?>@C?=B=:;@=C@=9DGHLIJMPJMJOT`VKHIDCF>DCFLPOXVRMOIGC=8626:<:FIHSKJ?>B:753/3/*(.)+461367/010-,.-,*+'*(,)&%&),0*%',%(%'*%&%!  *"$+%)+,-=40'%,/(345-5=19>54938@:478*8:D?<:7=:E>?:7A9?9@>?BQNG=DEDLHI=BHMFDEIDRNKHDE?QCEIJMGC);2.+,'.&'    ! #,48<9BDCACJC>FD>?<=@BA=?A;=>CGE=<@FEB?A=><;AHCEIQONIOCDNTHR]PITMI:8>?HDEGCHFJAFVJGNHDA>=:8DFIKINTOMNW]VQJLIF@D?@CFJHSWRQMHCAB>8428=;BHKTNOA;:7842102./12025/260,+-.-1/*-#%$!'+)&%)*)'&'(#%'+*%#&$ '#$)('(6'.60/0&"/.20<;:=87;<90/79A89825.9@D<;87@BO@9<:9CD?B?;DDCB=IC>I:&C1-3*+*")4    !%'.9:6=@FA@DABFH?A@?A=>=<>@ID;BDGAB@BD@C=8@EDBGHMQNINODCKRTKQUQURMCD=>ABGKAIFB=D>FDCOBEFBDEA>@9>A@ABEKJDFEKPOHGFGDP_TWRHLOKNPSPWUTSTPRSPTNQOS\eab`\YRU[TOHMQNJPMPNMOTUKX^`PTZOVSVNIMR]UPQOQSOCKOIFB@EFWSMPSVMJUWTQIECEA@D?GSKLTNQHBDE?743;@;@?EIXWNE;536212152701.+-31-+.,+.-1+(*/$'%)$!*(%#%(&'%"$.,&%$ "%#)+#4-:52-5+*)0169:<:><40)496;84<4/:?C<:7;DRF=<41<@;?@AD8AC<>JCGBEH@KC?J9NDM?9DB@?>DB>8HB>"23(/1!'+7    $#$&25;>A?DJALM>@NC>7:EBCD>@E>=?B@A@9@OIKRJFMFDMOJMGJIQTPNIJVNIPVSUWSVXMPXVQTUX\bed^\U\]ULHJKHIPOPTNRSY^Z[NYZX]UOLJQMY]KNKJMXO@IKCKE?HJH[bX\RMLNJLVSNKIFJKIDEF@EMPKSQLGHFGCD@84:?A<@=@?K_UE8540123154/.1,/2./1.,-,*)+.*&(+)!(-'%$%'(&!&+%# -*&"#)0/'"7=6-'.,)*,+824=D;6@5784/5:61=7-9@A:1259>B><=79/?H:?;787<=;ADGB?BOEJ;B?B>D?=?BRE:>=A=?MB>?*#04076-%&/';  !$*-7=>B>?A>?:=@BA?B?<;BCBCG@?>?=6;DA;ESRWXQNMGIKDFMLJKEIDLF?K>?PG9AF@?<@C?=>G?E?B?;>=?@N]RTQDHKHMONJEGSLMJKIPSOSPVXWY]XSRXRSZWZX\_]`d]b`YWRJHFLQRT[]SQ]UTRTZTYWNMJPL`QHPKISLIOLFHADELQXTWPJLMIKPNLINJKMICEAEAFKJIOMJHDEGAD?6743428.54;@659)9F;9*376;=:=?A:;*;>H=FC>CA>:@:=BCH@<=?F60;585,(/!('    !$*5;B?=>;<=DC>=>?>BE;ACJE@?A=;:>@>AJLQ[RIJFIKHELSPRJA@KLDUAHXOC8><9<:AD=CFJCA;9?BCNRLIFGOJEJTPNPKEKTRNLMKOS`XPXb`b_WVWZVZYUY`_[\cejhe]XWZNKMRUVWb^WVZXUSZaZb[PRNRUTcTMQNQPNQUTSKEOHAQONKJLQMIJNOQJPMLFA?;@EIHFJOJLIDCD@A?<;978:>?>C@?;9325041/-+-/*027;3/1/30-*()*-/+.1.,0,+-/,',+),*)%'% #!('(%1-*&0*#,;420'030*417G;0@984./232687ABC=;836"<8C:F=>7>B?=<89<9BGABCA9=B>DMI>9<>FKB=9=76EJF7A:9;?4),**-*   #%,5;898>@;=>AC>:9<@FIDA<@DKC><>8:<;=AEAHJKQVIECDJIDBQURUFA7GTAJPVPOG><9=>?BHGCAIJ@EFGBF?::09;9@83:@=B;6><@:>:=?9=;87!@DOA>97<;=B@<:8:FH?BAC?COVRL4<6DC;0*32+,-%&%   ! %*1536=;7:<=97=@FNIBABAD@>=:7:>BDAEDKOPNKFDIG=BQJIJC:A\J=IS[JDJF?=?@AEHEGDFNG:FCABC@;CPKCDGFJNTOV\]^VTNYOQOQWUQSgnel_`]^a]ece\b\^comi`cgkhric`]\R[^]Y[`c_edZXVYace\VPUTXY]QRZWVZSMIN[SNKORQVOLJNRSLNQPNKOKGIGB>DC@<30<945?@<=:=43103160.0,-.0.0,*%')')(,231.-+/.)(,/&$"! ",%*'#*,'*0.15@;/-.,1,16<4:7,/69=1684@C;7:A=;@:B>9:>;32@>B9;7/78>E=?>=:A@>B9BPIDLKWT]I?C<;=>P?7HEA9=?)7=<3093+1* %   #&+27<;879:>EKE@A@BA@>?>@<9;86>ACB@AIMKJHEBD>@NIAEIADOQ>AGOIC?9:>FESJFA?N@EKOC?FA?AGOLGDELPRNW[_a]YUKRONUVP]\YZfigoabeahdc^kc[irki\cjkbqmnfa\Xe`a`Z_fdi`ZcgcVQVSdb^QSUYVSPWSQILPNQPKSPTQKJHNUSMRPVQOWOGJF<@CACA@FIFMHFA?C@95084254:;7;8>73203201/+'(-,/-*&%*()*+-/52341/2-(&()('& (-*,/%-,$*.)-)9?D05:,3214>-63/->0167:<8@=7A=620<=7<@?CN;8PJC;KEFVMRUTR;BC<9<7BI9-@A?C>?BA:868@HBFA?CGFHKEBID=BJB?FJBRTSFSFPJDB789CD^LAC>ABD>EDCDAEGJD=<=<=842456867D7469831341./-.+./,-,*'*.-/05010+52(#"$("  "#,$,+-/0/(31=78ANFJCG?JKROKNCK@B;C75=AJ10AD;957/13)5(/7:0/-+%     !&3=:;:8D><:8:36<8:@>90-=.HI;A812=AB614EID?=:7C?FN=F?B<919A=;@F3256:8;2./>+30+1-,)*-/5     "-6>=89:;=?B?B=:;BEFCG@CDGFEHCBID>=FIGBHbSINEJNHJ?<>?BS@9BAGBLQRIEGOILKGKJFGIMHOYWVSW[WVU]VNOTNXg_lchbkfgieca[^`epqbcdfkcadgenf`algib`a]a`[_`\UWSPT^V[aX]jYZX[XSQMNQOSNTPOP\RMLGR^RQT^V\TRNGMIGBABEGDBCBC@?@=89:487128;7:72512584,.2/,/2350/.+)*010/)+*/520,# %&('/<.<;01-43,(40625'26F=8,62$/50518415F:7=E?;<;=9:@;?:78017D)@?;6:?A47;9TEL@0A94EF@GFIHEBFB?;=?8@>B:89<45>/5,9.)*0,.5#      (.3;>=<:@=;=?>;:9CIEDBC?GEDFB@BAFGIKNGE?BV^MFYPHRIC?9?>KP<@DMGXNKGBFGFMNQPGHJKHIWQURSXZXURWSJNRU_^emhjgldktn^[Xcakifmruicbadgmcbfnfie]\Z]Y[XWUQNPVZQZ^kfaj`cTSOMRQTSRMRQRNKVNKNIJWYTVOZ]Z[VMNHLJFHKJEABDFDA=?>@<>:34>6947;969217872).832;8/.,+)*+,0/+*-(+.,.'  *&$)21256/150.01042-14<(1@D;2&"/3+23/9;68C<8DBF?8;8@:=:8?53;:8?D'?E>:=18:=8:4:9HB-=8@IAMA>BDB;=EJC:874><;74:57:3:05-41-')2+0+)&!   !%+8;=:><=9=?:9ADERNMJ=EL^TGOZORM@>?=@IFVH?BCHNKGQNHJHKTVMHJHEOUNUQWPRVWXUMHJTSY^_g_kidlnv~tafdfepe`px{kgbgjgemfijk`fme^]`a\W\Z[YZ]X^a_\R\]^j\ajd`RKRSPVRMNMONOMKIHMJN[UTVQWUXTQMKLKELHNGBFKJI@=@<67>;86458<47:25;8:93+/49<8?95*(-.,*0.-*-)&(&"  '0+1821537,83.010:,51;08M86!.8/)81401.+01:A=?JCFA2:795:6<:45=<4@<'@LDC?573:A:97/:;B=AFS=@?F:I;G?B:9=@8:7575,286=20,59.,-*+*+'"%   #&(15:86;=<78?GEBC@<>HFADCEBGFEHJAEVX\GLVNPADACIMPBAFLFCEKHKIJIGENRHIJILQLSVYXONPTXQPHMVUX]^gbokjqntelgehrhywx|~njekngnqotlhelfa`_b]\Z\]^_gc_]^ec`ZVZbcYRTPVSVZYOQPIENPKECIOKRYRUXQVMTSQSHMIBCJKHCLGBPMNF?F@?A@?:85323<:23504A=97A92>;,@>86<@8=5./D][<=>DC9;>;=6;8)2@=+820.>?8263,4%)-+#&    #%-589748>=E?9=AJCBFCDHF?CFIEBQNOKGSLNYM>DAEHIGRCBDIMFHBLMGFIEPGFIPHFIKILPIOR[RQPLM]Y]^YXZY\[_lyugj}xolhfcqos~vopiprpurxoknqopa_`]\c^_\W^`^Wmc]dleZQX_b\WNPLUV\WRJMIK[SPFILHUTPXTWOSOMLGKHDAECDFJINCHJQNKD>DCA@ED856312761316@F?;4510.14.40.+-3,+&')%! "#3(-1,.>6-32%01-2043+?18/6=>2&/=17463232476)4C<45GVB6:?=479<75>5-G;?J72;26B98/5AB;63;=>C;7C:;:738:8,0>EA5I6>0?A:05.1635-*"#    "&+-/68=<9<@E?BDB>CMD?@FHFGPLHCUSNWYNF?AHDNTLDEGLEBIAGFEHCIMKRPLMLOFIPUSMNPNXfX_ZPRTS_Zfjp{xlpnqptdkfoguqz}t}vvmv|tsrporsmb_\]Y]YXb^_d^`afdZTaZYQIQUWTLU[Z\aUW^PNPKNOTWOULMFHLJIEA?A=DLJFDINJDB@BE@EDC=96843-3957=?96971.+2,460-)-'(.)#%   ("4!)*,=>37,+0)3/682/=259:3-)>:3451.6939< (084608DHBC7=97:691EB2,G5%D>67=5;QB8<:-2539.5@=134=B=;D8A;239G:6:48:949=C>AX@2=E?;4)1284/.&'1&   #'+-6;68<9=?@?B@<=EGBC@CFDPLHFEH\ST^TJABAD?>B>69=301,48<:947:95218583-,*0+%'*'! %)(,+04,14&+-13>=<0/58C451.89<;:9126:@:#*/;5414COLE<:=145694D37B7+:<9B:9HKD:C878AC=I9?E=9AC9D;@AFIA@DMHCFKYXa\TI@?BF`UEIKFD?BELECEBHTNRUQJFGFJMOTVRSW[fc]WFPKZ^\dou|~uihihusgkjabhjlpiszu}usmnzsimprovuoqkZWSZ^`fe\[`fdb\bca[STPOQKQMKROPRQXUPK?IFHKNGQOSTPJNOLD?>?D?DKNMHABGDAHA;CEA>E@A989620125=>;9;?:898>?843-*).,&" &*%+-*3460),1,'2+5:7=81.5;?:606<6:9;6.-307414)587;8?IQNC<;:946;9:5=86,;@H>CLDIH;?@AEA;>?;=<817>:9H?A?@IDCD=E?>AHEB>GPNPFGOPRZ]STHCB?NVIAFJFCF=>BKNDCDANKQONEBGEILNTVRTVT[`_YPLWea[irx{}{nhfhmngjdclhlrniv}wvrqsq|vsztzqtrpf[VW\`bec]bc\bmhgb\bgha^WUNMOMLKLQMNQKOTQG<@HC=?DA=9CBA:854135:><>;>9:96;=:21*&$" &+)/2-#-*1/./,6,/:15@568@E>/7<;/178;38478023HC;CIGMNYLE<65746:757/<5=%ADGB=CAD:KC9=9B913@?E;589-:D=5BIB:DGAEGCJL>96D6>,DGF?-D@ELF@CHLMFLRFIDECOJIQMOPROT\^QTLWb`\epy{vtztnluxvniksftvjrqunrtvuvzxyqspmnaZXcdidbcjkakplf_cfka_TWVULNMRKMKPDJWNCGCGLJLYMQXQNIPOJAGBAIMEHIGB?EF?=?>9:5?BA>;9724=;:>B=9389647<742* ".5+25-/.2/06703627343<@>615/48:.<9>7;A<5.2-6358?./57KLD7;AD?@78=<=6>G>BN@LB:IF6H:?;%LIMBHIDBG6*-8/8?528-    !$%-3=DIKEABKPTMELNLDBCFCGJHOJNMSNKVQYJS_Ufny}tu{s{zytljijflmhmzqlmtsr{wrsrtuwjghd]_aidb_^jqmkjiknhc\d\`aYSTRJKQRSQSVRNAHNHIEFKRPFTSWRPJMQLKCB?AEI?ILMJEB=9<=@515:;=<>:765=>DE@:1597;6520-'%# %2)315=85<93026,1./157569@8?<(.3,):;2959:<1*'.7=25=PJUYF;H;=:2;7:=6>;754996?@A:K?G@2ACGH=1@C>7?:>CBQ@CANF8VCFLADC@0;71810,/1542,+     "$*6BPONLPKBABLVW_SOPNGLIGNZSUNG?@874)>E>E=AD>38;@B:39@G=@CB<9=8FEA>B4G5/:0,)+.31+.&%      #"%'/68:BEKLDAHPVQEHMCFPLPWPNXRMB=>=AFDGHGJGFGJHMIADE?ABCGIMSPRVMJPQPOMJOKMWM^ovx~zp}zsrpqjfhzqnlqoulz{xuqnsjglfd_cdbc^_ihikfnlb`dhfaWRSRcaNGLOMLW\UKEKGDH@BICFOWY\Y[VNMOJKLD=BACFAINMHGNI=;:7896868453<986@C?<=<517>1(  " $$#"%(5167:240>5241;69@A7>AE>B")5=3*45/135/40.)94569189=7925=79E@=@:921@?>=B>DA;/-6A=CICHEJG3=1)'-*-)+(&!    "#$&'('(01>=?GOTNB?HC>HLKXRJKOMK>;=9@BCGBFCFIJDECEBEBALOSP[XVMPWKQSVUQSYN]gsx}u|v|vovzvpum}rpwyup|…{|zywsmkhkecdgd`aZhqhmsc]gmhg\RZ]e`JKLMJO[_UKIPFCE>DB>CMQX^UVRMKFEI@=B@?>IFMNKLF<;8687<;7439D?8:>7484.+31("   &$&"'!")106232,+51/64@5<@;8>=:85+3=-6<46512-5-(*>35<9;3/<:;578:;7@;9<469306 D?7>;@?:?C>A6+<(=C@<72)0)C@8>?;8>;?;CJMIN:;?D;=GKJHI>:24A;@C682.&2*3'.('(      #%$"'+(,8BLD:6?A7;ACGOGHNHIA?A=E=>D@BEDFBEJFDCFHC?GIMNTdWQMWTIMR\_\V`\Y^Ycoxquxww{vspiskmuwrqw‰|tprtwrnsqtnhgda^`aZfmadkf\dokq^[TY]^`NSQPLWU\ZPLTHAFHGJ?>?HEWVPWPRQIEHDA;=@>@=ECGNJB;>958:768427;?680,-/.+'$(/*& "% ('$)$"+.7/2,+.+,-7525>98;810,-C843=:75'+*23<8@;686;:9/69;>3;C?<54;<64<@;=:J@O@GADLD>7>:=/,;:9;15(?8<@6<9E?D:=3>RSOHPWXEGDGI?0/03<6.+&!2&#       !#$ $)(2:35;?C?9?EJIB;@;EB=A>ABECJNJFCAC?=>;:9B9;9?4.276.,7;CGHU4-67GIAMGMD5:G:8/C<7;87BA>=2*)?LBA=9ENVUKN>:6D=RLDOTWXGSNZUM5215.60'/'+4"$"      $)'28?<5:>B?CBCBDFIFAJG>;CEDNYXWRMRMRUOSQSNQYc\ekfdx}nbjkurmpoktmntqwrzlqmsosrurfgkmefc\]ekacdbeb[\[\ZMO\YTN\TMRSRONFCDECKROEJLCPLKSWPBMHLHDE8;7?@9?B@=9?@634568;851,'$$"#),'%"#*-+  5%-(4-&$('*3'(-63:;783@<=8B:BW@/&5?7AFB=;EQ?>9:/8702GCLJIW64-(7D?G?>B;8?NEJWT\P:;B8CATQEPSLVO`VB,82-/3)/3;7)&)40,1       "#(-+)*9<=945468;?A@FJHC@CFBC@?=JOA?ADCKOQPTOSMNONORTNMWcahlqvxjekmuvpkiwosy‚|svlukpny|lejhjdch]Z`edfd`beZYWTUKV^WSM\YRKPQRNHCFBCAHKJEMIHLKPOIDFLMID;:9B?7=?<:6=>=979:8650,+("!# " " !"#&!&.( )%$+694!&#")'1;=84;EICKPG=9CPN.(;F@4598:@;13410$7>?68?>CIF=>BL>G<@<47DCE@BK,A*IJ?>@<>JA<>A:68HCH5;>DAIBALJQC>;>URIOMWM]REQN.7;8B?8C=934968621,*(&" !""$" .$%)#)5!#.+(.,+2>:@6AEDJOQHFE>@HB.=D>D8>8<7:3463+0238=71?CAKONF>:<:<9:;:7KB8=A9@D@H-;=BD;:@G@7@H>;2BAC829=8><=1)9@;KGBPNKNXcWAGCEF@?AFJLE?EMHFSLPKFADMGINOSQNPRM^dlmgotqxqsnusrir{jkvw~ywtsqldjtklnkjknc_eX_a^a`b`cbcXYUXcXSN\MKLTY_RLKIJCABC<:;<=BDBCHDHJIBECEKB@B?:<7=5>;61461+,+(&%#%$"%# !$*%+,'%+!",+/2-3LG>78JFJTISIAGB@CH3E;?7<9;473.:14;?>:GBGTKQEA=;:5858;76=A:@FD@;3*3;36/*'&     &'028NHB<@C@A?9;=AGJCHE@AB?B=<986.274-(+*('#$! "%!"  ") (%03"&#&(04/.-9B?95CHISDJAE@?A:>6>RTH6:;@932=;>=;>9?CF7#DF<897;?GA:8?5C?LGA15:0&/185;=<=;:@8<;?5.*&#     "*6345:?;6:<>EGB?LKEABCGA@BGQOLQWSLKH^Xgegfdqpoiclyvyxhnuwpupustvxyrmkimipkhihb[dgca_VQ]VTW\_YXUV^QW\TPNPWXNcTN?CBNB@>?B>=>ABA78BMC@?<8>56983,+'# %$%&"!"#!  #$!#*# $960/53:)+(6ANI?DGBC@GAGDO\FQ<8DA?>2;865.4@I=G=@8CXK?=4;:H7>;9AENDC>;CE>9E8A689/52=43=E:@=?GHA@>CD<;=B@=EMPLJLKW`oh^bdgdabcu{txtehqwyqjmorsr|{roidgpskcb[WYa`]b]XUYRZWYWYTUX]QY]NMGLONJWOHCBAHNCDGD?64=B>869CG@B@><>:74./+'$%#"$!! ),0"#!$# '&.;3,)'$-*% 40>IGKNB5*-76A6:1AB;6CA@:8=>;C>?DWPFISQC;EONDBGHE@;LMES5IH@=6G>E4>95<*+315*,2"'"     $"$# !%,2154@>IJKOJRej_`bheh`io|qustnfiot~tqklnqtsndknohabWX`dedaXSXTXSUWVXQTXYNW`UQMPJCGOL>@B?LNB>=:>:76C?PBGPBHBD:BCT@EL?D?@;@<21=G@?=B;?>?B9C?@E@F@E?125DL= G=@?H?4>5/5ABGPA@JFIBAG>?BI;QDAE:IDOSM?4:945-30-),#&-+   %&"#&,3+/16A98=AC=CAD;<96;?<=A:=7A>@>9A6,-IE$CI7+B=;:953A>?=G?:;E?GDH?@EA0;@@J?3841.01+*"+('%&(%$! #%&)!$!) #"'/,'3,7234;:NHEA@;=?:AB8;C=64D94>FC>CK=?HCA:=89?;8:<@9O87932/48=@8&%>;(?E2%;>MLC7BD:7516,8;=>978UYU][adghkge\]lhglmfixrje_jwocd_beba[Y[RZWX]S\STVX[WUMOMNKICRbd^IFLKEG@B@?>94,*+'$%#&%" " #'%!    "' &"$&'-!+*,$0=9393>JCHF9=<;14;C@;:AE>73,$:18<.=BDC>BC97:JB6C9?:<:DA=58?>;6DC<=5IQ9B7HC=C?E86HBA?EKIKPR\^Y]WYacmi`kyxnfinsofdehnh`bZa`\ZVROWQWPUWXVNLJTJH>Xg]ZE=E@;<351-(%$ #)&"!!" ! '"!&'&'!*$*'&>-.1<8=354:GHOBDA<8;=G?=EA947>7=>29=>E;@?IBEB>JKF@:7AGNHKZb_SQ[b^RMUXZYUS[URJUQGIFGDE?DFHEGC?:<5926=91*-,1)&+("!" &%!   %,*&,2-%)".*&BKD:D?/4:<53GMNSD?BGBP@L?AE<5=JDJ9JB?FAFC=>A=A;318>329>@3=C:@PVJBC=;:;:4B=<8;8!>7:?)'0<:53B<@:+?@UD<;FA7BF@C93-5C=DPJB.JAF@JE>?FCQI[RTPHAGLHCLFMK@PBEDA<;29+/)3.).%-%'.$*"      " &56)*-,*)'-6;656179<3;CB349>=626784370+-3,/+.)*(,(*,+*)%)+),2/*('&,#"%)&#!" #.-)'&2#-/&$.,-.86>96028:54EFIN6CAEBICG>IA>=DFDCBAE>ED?><;=:?;?>A:@>6IM?CDCD9>=<437<9<9B=864:065-67;A?6:LHNE;=PBAMDB=6-@6<]O+=@:;8ORH7CIDGE8IDA85KX?JHBACI[NEGNSMNGHEH>@EA36?15,*+$)!%#&$     &4,#"%$*$1;94/23706:@5;B=414897357*&+.)+',(%$#$)&$)('#%$%(.-')'%#(#! "  &4*#!.(1+%*-'*/;/030/6=@357>E;9+;:K?CNL@AFNEI@C>=>;=>C3;@=@DEDA@>:A>=<:<4>DC4+56/(/:1CB93<6AJABC=@GEBHJ:;580<+IO*(A;:A?NAJE\RPL;@SJD:AOUKFENJRSKXJIGKJMHJMN@F>874;:4315.-.%*%$"(%!#     &.%"!&%&$06:73.,10.,/.26/7B=6-27:5487($,'#%&%#!"(%!%'&%#!")*%$  "  !$('&4645# 2/,)"5<8;128?>;B<69-0-7HJDFO@=ABKDH;>@C;:HC>=654;540AFJHEFDGIJ:FGBED<8.@79@MAC@>=GFCJSD5=@:4=LEQW5EBCKC>T]ULQHL]TRKC[LPRPJIGAEOYFRVK`[VTITFB<3:8>/6:;,*1(/##&.&%       (% !()#*2310.,121,/*/+0;@0,(/.28728;*$+$"#$)#"' $'&%$"('%$ "$ %$)1#35;-7/)3827,3879<76;<39CB=E<>DJLFKGMFA=FDB:CEMF;>DC>8ADN6EFMF:>=9C;0147>HECA/>;@=CKCUQJMJ@GPFMPHCB:;D=YEYA5>C>?JE`QLDG@IYeLOPBQTIKULPSMOHA@?VgJPLM_DAPEM9LAKA1",4;761&+'#-+-5-      !$"$"%"131,+,-2-+,417.(-)18;,)$().=3/4*(0('(&%*"#$#$ !"%'#%   !   "$+<02:.*+*6A:490/=63?9C<>6;<:>7CGZGFJBYNBVHKGJROSC17AMJIL:G>EIDLJMIG:9?F?;5BA=>AGLC=A=?EDJNTGEB9@>9HEL3;E>?JFI:NQPLI@HGEPWYHJKLIDQi]F;HIBFPb^LN_SBJ@BAB>DK=JA=82.A7?6=+,1*5,$&"       "$(#'&0-.0,/2+1390+,/685&%#%('5.+)'&'*(&#%#" "!" #'#!   ! %"/85$%4.0*-/02D?B?>HILHGFDCWid`[KFCHOMP@4FAC@">:=?8=@?CA@FCT?8@DGPVNPMTKB:=>PWP5@?FIJK6F=IOKJOKNPWRVRHIGPW>1B^XLRIWXWSZSHNILE?PCD?P745:C731/+0,6)!1+,     "&#'$&*/,-.10+93-/5,')02,+)('1+*'&$# #!  "! "# !"#   (2"$('18+("/1.17258>;EJNLSMFKFMQEBNUKMFHQNADOTFJ>BEFJ>MOIFHFG?NCLFIafoc[NKSMHNFJI>:8AE,?<@:8<=@BGECQE?BJWVYMQOUMBF>=QRG/KCI?>CL@HNFEHLBSJKMPM\ZGHIKI&1QSLPKUQRUNMKCLHA?AKEBDJAG43;AF.76+&3)/".42     !  ! "&'&'&+(#(%(.0+.40'+3+'+(-/-*)('(/+-+*'&%$#!"  $#!!  $  65"*)+-)($0.-4,9289@L856=?$*6H>B=IFIKEKCDNA>LGIKNKCA?PXEDKG6FHFE=GNOSIGC?;ILHLONHMIW[]WTSJINHIJ=>BDI$4?=:=BD>FBH>DABAPQEQMD@;>SJ=7FIEGBDBACAHJKDKPURGJTUL@CHGL]JQXIVRGSOHNCMEKE8CD@QFBC<270,:4-.!!"&"&$(    !"$"&)($&%(/)()'.+/.30,&,01-(&.0+'&*-,)1,'#'"# " #!"#!  '   .6(*)312'',/020.<=<=75@K=3178EC?KAEJ@FM@HBCHOGF3@HCNQGHG>7D=JIBAGC<=B>D@EBO>DGFACKRJFHFWTP\XVQRJLJIHC?>D@KD@BG@H43+;GJCHIHEQXJPQISP8FD3>EFPTHCDFMSPQB6=AILGRYKP\SZILNFMHV7@964386/.,$&-& "*-"(   "  "$&%#'"+1,0,*,',-2.+/2.0+#&./*(&*-.+&(&"!&#!! "%#$! #"#    %.<9+4046*-/&+*768/.26:<=B>-./7<82A>AIMATBG?9@AHFD@4M@CNIXG>C?IO=A@EF@>NGOPCN?JMJHFBJ@:9;<;?9/39<8O>9=576EBEKIH>OGbOL@5:A=BFGJADBGETBGDNF=FCF@9:@DC2:C@?=<8AGC9IC@F?@HLADG@EHENIFGIGKC?>=?GEQKJ@>CGI=M[LVA42-720).*(-(-!$&%    "!%$!#()%&$)'*)'*-,(+($&*+*+/-*1-+#" #'#$!!     $*)/)/&-67-(%)1-523(12807QLCVM:D@EFCJGEAHLSAEBHBGBNE@?FQ\Z4@;:FEF@CKGDGJHI:GEID=>GFHLI?AEHMKIBG?AEHIDCGB@ADFJSMKFA=JIREJ@=>8@IEMKM=KZ]pb`MQUG?IEFOCDILZPLANPCI?GK>DIN?KLQHILH94.7430;2687,( ')*&#"  !#'%$&%)&(-0/)./*%&$&)-/*(-)+$#$ #     ).2/4,%&,>73*'%) 5.347318@GTME>H:.87>=?6BADBLQOBADQCEAB8GEDENPORZLFACKJIFABFECKFJLKGMDEMJAG=?DCE%4;:9NCPWRJ<>@8:<=@<87;02/)+),# !    " "% !$"&%&#')*,&*-,&$"#%()%$&%'!   "      '*,2/3)%#0.=+-(*,!$1,0694<6;ELFCM.%:-6ABFABE:<;<;&187A?@DL@EDGLGC@A9DFCJNMJDGEC@EICBJ<@B7>F:@>I:>LFBAER[SQ>CHCTLC=MLNRTWNFLGEONOB>FHGF@MCIOA<@FCFEDCIA6DC<750)-0)($#!       "!#&$&$!#$%'#$&$!"#$!"!" "  "%     !)-0-*,-/2(+1-$& #*)",-)5.96562ADK@=?4?6CB=3>HDLKQJDCHEHNP?@>LCEJ;MBIR>;>PEPRNSQFHR^VUJQHIHJFJDEL<;HJRIOAEHJF65>HF?9AC;?)'359AFIFH@:?;?MGMJHA>IPTXLTNDC39:=;9CED@CABHF6HWL>Y@ENUQEHJTVTRUWNFHC>D:?B@L?:6CE>FE?9?E<@GA@B>1;51*0+)026*)*'    "  "# !#'&#!"%&#! "#" !     ! *.'/24.+*&.02-/1)&"$(+%*/8-5326?+5DI3@E4AEK8?HNKNONDCDA;@9@I?>7=DB@LA3=GI?NOJMEFHTLIBCHEDQRMHMZL=;FOGK@JPMRB>I;?57=C&3>BDE=6=KLRAL4AC49GDKNTFQKOS[XLDEP?GC=7OHILURF9?DIC?YB@FWEDWK@NUF>:CGIFD=E791/94+5809-,/-/.,()        " $%$!!"%'&$#      '0+'&26.*(1:83*3-6,-+0574:EKQGC_IB:EJOLJMHBEJWI@FKIQJFEIMR^G9=EHI@AMOCE>C@B>83GNI>&AFDEACEDEGFA;BA?8IB@>LB@KGEHFLNOHC=B>74ABDKDE[TVJBFMIAFD>;F56;K;DQMKYLNUKJTIOJHMEQABLC>C@C?>?E?@0.:8B=?25,-50,0,#$&$)#      !    )26&*+4341-+*.*30.012.(2-*$-13894CLGC96D=9;:6(62-2><5JFKNHLOGOEOKLIGLBQF@LKF4ECFHDGFMHMNKOTQKLEHLIPM?,:CI;ECOLIE=8DJGF?DGIKGLBAG79FJHB8KTL=5;AD@CQlQSDHR9BHEKM9>BK39MQRSKWKJULJKJIMC<:E?B?=D>?:A>A573D7+DOKIOLJGFTLKFLGHLDE3EGE@=FEICALALJIR[XSLKHKIHJGFQVD&:7<3-@?H?DE=9=<4;?=AHA.AGLGDHLSWRNGBJ8D<>=CHEKFILKH9@HCHJXQCDBADBDYJYQMLGLECJDRZYIFULDKFMNMVFPMKMCBGEKC@FEQGA>C@AG/1853E@MGEB>A9;?:FOLE:HI@GJE)@GKDHIHNMOMJHJ=E685CEKLDJYTQF>JIEHQPJK7APJEIZIOFQCGEBGKEKJGIHD>GHAFQJHFLRICNEKQJDMDBKFCDGJIKDH9HJPTPQLA?A=59-3/)0,+'*')%!&!-'1$     "'"! !   #)1?3'$*570".4.-0*0=;9@.7237=B>C-1D=;?8;A?=AE,?NB?HD@DAGIGC;6ORA37DEC=EmVSGHKT8CKPLJP9IUSMEOFPJG?7@GD2;>FDAIE?;EQHDPEJAD^QKC8AD>HG>CN6:DFGAFCDRNO[YXM=B:B?>:71:185-"+'*(%('"%,(%*!()$    #$!        )*13CB."(0:2.-1602.)+021781;*05I@>B63IECE=;34?9134=;@A@:7GFC@KOLD?5G@BFKD@L@8AMIHMKFTWV]bXNJHEPIQIKEJI[K9#ACND=@GLCG@8=5:79*8C9EI'IQ?FDGN>BGBCMUDIEKSWI@J@GF@;:@GE:CFHPFCA8HEBDACB=BFAGCBOQKS[FEDN?8JC=;>98;8('.04'+&'#$',($#+#(.-"     #       ,121:7G6(#,8@58;0.132&20,45;/ BG=9<;IC9?8?>909<=?67>=@FC<=64AIHEJIDHNEB8;GDEDEDEADHKELGNYSV`SLIWNBNSHKJGOM^E1-BNQFJHBADBGD=8;<;:@98GH8DIKOK?AGO4B=QCEFDIFAC=;BAGCENKNO\MGLKM>CL?:@6>O;@5/(.,)-*,.7#')*,-%#)&)+!          1+2.-?I>?-'-16;B583*0-5.4238A318D857D?JF9=?6HL5626:=87>CHB;83DFJLA@BFCAB;IFEFIFGDA@MIMKQSUP_XMQPVLFVNCLEFZURP;(:@CIKQHMEF;C>A>8;=@D9J@!GFAS[SPIBRCDGQOJS9@SRKFSIMGIEFIC=OBOBIfPN7<9?ERB>ABF614>LEH@B2SJSXQPJFHME64:DIBLFEF@CMG=:FEINOKNUXMKLJOCDH>=;HI=>610-.0.).+)0+0&+$,+()!%!"           +37*3,5C@>3-&*-;A;:24-*3/519/3BC:65C8C>:^KI71498HD7:<;@8.'5A@B:?0AHDWONIHCIHBC9>HDLGHDBSPG9MNVWTX_UOPTNJNLCKDQZMNF:;=ALOGIEIG99QTIKFGUMALBIGDC>BEB=AFIBK^G=DD=9;A<>;6?PMQNHFA>CPG@EDFVUKEJBPM=@=BCHI?BEGJ<:>E>TKHSAHR@G9O>?IHC?I:>ACOAEIGID>@EHIJA?BGCJNPLHECA>?IEA;@>2+*4/6/5/+(*0'*-&,*0&'*),'/.%!      !    (2:4125-.2>78231*#(27;=83+6324.267(9G=>7D7@B=-;84?K;0-4865@5IHBHBD5G?7HDB>D>DARNFJKDEGROSTIJFNLKQPVSKHICEKUNLGEHF17EFJHD=7F@AC;BIHDLC9FQMOILKHJCBS@IEBbOR=7=D:QJAHKEDBJAGUFJPFCBHD67=4:BD@=C@CRDQG?AU^DG=G=@?B?DBSP>ICAGFI@FMPMJECEBCUWPKLGBNGDG9>@4)654=752-(12+*5/4*)+).):75$!)            )(5EI<98/87675.3):;9B@:4542186491/MLOE7@H;9LE?JA@?7D>;.8319=?/C7JKACHLHDEIYLHYRLNBND?E;.=;?@6C+ALH>97BHFE8<='37:5@>2:2,0+./057030%&)!BQA=AEHEBDGJXPBIZRPJAF4@G?5A:8:20,6*0(*7J6<3( &!-'!-)'         ,>B614EMC91/1.596519/267A?6<1?=>964=QIOL@8A=KN:@MOKF;E37@>7;6=C83'2=>70:2;C]ZAE@ED>@57;HMPDMLJSNPOBDKVTYNLNOYXSQJKJIMKJDI?EA/A?=@JR9?>C>8<>B;:;7542<8<9:1.05-.0,2?7416*'$)!%'%!"        ,CGDG.*/=ML:),-67D@3?>7653D>D;93:8JCD=;:;<8@HIDOGF?H>@EL=BA>B65C9;I=GCB?17D9.BENRKMNJHLIRL>KW_YLHOVZVNFMLQOXRFTNIHBEPJNFEC?CEQLNEFHB@D8A=@A>D:,9?@JFCJQMHDELFPTKPRGJFEH@D?BCFGHPHGDLUQ=?GC@289CBO@DGRS@>EHOPROJHVJE9>C;C>9A8637-4=9427;51.+-,+,0C?7214+(!"-&"          ()"'%*3<'/5C>)"05CAHG9GI;3;>@=LAD>A;C@>@<:9?GKGEGPGB=PI@5@?<3-6?:?OKIDA@9@B+9?IF@GHPMB@HGPXHJRVROBI7>DCBGLHENCADRN68E=B8-=>BMPQFHQD@EDEAGD:?BG+H=/?92BO[HF>=KINQgINR\G78<898<9:8>72/1>8/7<;19=038/-05>=F7'3*%!+) %$               #. )4./-!.% 1FC6-!.8BGC78ED8?B9=?@=BEF?D?KGHTQKJKGNHRL@FERFPJ;CF>AQ_TMHBKNOZa^PV]WB@NHF@EGJIPH@APFBEFA>A>73C>AEH*:HLEABEKGJHJHZI;J[JHDAH=;IB?G@INQFOS>5BF@ECKO;DIMBGIC<.TlV?=JMEMIF@D:BSEF?>GDG@6JN@9AOE=<=@MV@A@AEAQ^CROIG=9@CH>CVI:D=9<=@=;=?@516=:>A=L:>?GJ@?EAB;18j_?6CNCJNHNAJ?ASGLGBJOJO?NVKLGRSGICJPN]IHGEJKObNURWKONTINIKFDFBHB?GDHE@A8:FDBJLUNHR<8?@=EDFJ6?ABMEIOF;8JoSNH9AJ@VHJEF:9PRDHF=IJ@GCKDI=>:7328=:<:9B>9=9;25DM$)-7/*)0#&($ +%$#&')#          (-/<515<34*'>8305.-2@5<79;8;>SBEKEBFD<@=HEDG78>9;?I<8AD92B6JBAJDA8@>7B=AF?;?CAFGFJOHAOJGDLTGA@BD>76?DGLSTNRK=6FQKH@B:GT=ECKCDB@B=CIDHD?:>BF@BCDEGIHDMI@<>E=@6<>=;<;:8C<16>:2BC83!*$'"! .*#"!$&)',/-*'          !8/604824.20.18>89=8,/5;3:7A?ACDCEOGD;GCAEA8IHNJ9@B<=@>=8@FX^JGLHQOLMILHIOPJMOKBEGHJDIKFLKOKLOSKIGTIKH?KGRK?DHFDGHFD;=:478@EGC@ECIJUWTUNCJVJADOA<:/>:?86>:B?IOJ=NG:BACFBC>EHDC>EOLT>B;@KJCEA=A=<;>8C?:>798;6;=@C1XSZF>=-.,8-$&4&!" "!"&+0;5./ %'*%         )7:,7;-(23463,289=1;=C484786DA=:EDGM>D@IREMHFCJ?B>=>;CB?:>9;ABDLKBDA=C?AEB?FGLA?>CE>;FRJ<>9?EKIEHDA<;:8489B=5?;89;>=?4:K@WVLKB=.*+-&+-)'&!)($%+713!! #        (1#$2:/)1&057060/27/786=G=89:8:FB8?>?LE?BDSQCJLJHABG;><=?>BA<>9@EKRQ\_K!+6?9<>?9;3:?8;,%*7DAKND14HCADNOH;@DBPSCBI@LKMLOJGKGOPTPOPIJCGDOHCLFKOJHDBERFIYIGPDCBJKMRLFMAC<=<:=B67:AIECHFPDERMCHFDA?HPDJ:FGCLRS]\A7@96@MC=F@BAFDGACFGCAGQR;>@CAD?@FC:<9<;049;9>CBHAHFGKCMTFTVUKO9&(!#4-#&),183/0),7693$"-.*%          #)(*3*-+/1945+0A59589;32;@79;:9:E@E>@MECFDOJ?HJFHPLBJIBAB>9ABACDKIJEIBHQU]f@$'%(?A6;7>HIGCB0(07@?HGE3@JBFBC>DFA>JFMHDM>4;6>GHPC?ID>JFB:ED@=C@EGLYI@CNEBJB=,4:=;980A@AG=>8>CEFEANTKMgWTSJ0>A.%$-1/-9497-2.,-9=<9(&1#$#"'.0'($&/        ,4,:"-*( $/,23'3C(/516E3/+;6->6?D?BGDEAUVT^2>O6+&.>?>CGH>A<1/6@H:HGHJL@UAIHGHQC@HDE>KIKI=WVMDIJNHDM\LDFNM;FIEID8=AB19MJMJUKDHLNTKMDAI:HPHGPHFQ\PILPTRKIB?@=>@?>JGJG>C=;CEJRMLFKR126>D@;=IAG8=@>=A>@DMGLJGFB>FIBMIF=GHKBJDFDAUNHFJCDC@806>A@E?>C?GB;@?CA<=?;=9=;74:)*.7:98/%)-%"$+);4/.1$!() %,+      !+!#*-*+&*8<6.<.-8+,<42B>2*3=@=29@?E;:8CB,:5GRNJHTFJLAEQGINMDCGIMK@EJFGK_UGFHFEGFRIUNIPEDCHFOQRFBPI=@JHRQIMCKFMO@HJBILBQPJKIPHK^ZLIGFCHE=A@BD<=?GEFHB=CLMJOH=DEIMLOMNH376DHD>=AFED7:?@IBCDCGFHFGHBDFBE@FC>CDTJDEIF?EVHLNIBAC@;=@JHFBCB@>AK@>?>@C@;?CAEF<8:FNPOMC=9;JA7&!'.,7&&-%$.3073-1314801;0(38CA9<@=>O[RVKA?JE?FOQLBA:C?=E:DFCB>AFBDFG@JLJKPJ0@LJBC<9BCKJEB<*-*5FB84=@I836:E>:=EHFJGDLIGIHIGHMGEKTME@GIEIVTOJGILIFKUIRJREHAEGJDJOLGKOGDGBFMOMEPOJCIAFJK:KEJHIJCQbJCJIBF>KBABDG<>DGDBCILMOJ@BH@IDG69;:BFCA=BDG@BD>KHMAHCBC=QIHPNHC@A=CHICGCBA:EFB@ED?>;=>8?B>C?=:A=@E?H>NSOSDCBDJE84)156@3876,13@A@870575*&"'%2+)-*!"*:1)+()02*')&" $       (#*,(A2%)'+-3*%)-,)'+*/.15<-97+-32>0126968;:G[OQOXRH?LMOSRMJHJHK?1;A64<;C@?=0,3,;J@:8:AB><@>?8?>HFHKPDQF9CDGLBH[SJFHM@DLROLN?LTMKJOIQLG?EFA:AEDAGHB@CD@HFACNKEME@HEA>D@FBNED4<=?BG=>:>EAC@C@DEAEJNGSG>@GIDEGIKFIQK?DGVKIGIEHDCGB?HDJH@DBPHDCFB>=>@:2<5<:;@=87BAF?EGM=,.1<8H9E:;.:;:><>72793  %/':+5/!$&#,2*)-+(.,10-/*(' (4/()-'&"  $# (&#-$.*+/# *4#*).+02/30/.#'-9803<2:6.6353?394?B;6>:WZNRDGKLDILP[LFENKG>32,:EDA=?A>BCGJ?>@FBDKOD@GJD73:@>D>B<>121BHF?:ADGFLGC@7BOENIFL^?GA0?BD=EMGEDCIPCAKEGURI>;GDE9C>CH>?@GLU\PCADBGFAHFPH39@CBEA>B?EI?BDB>BDFRIJIGP>8:KGFKBLOPRCBDBLMDKHBEDBH?GIKJM@C@INEFDB?A>4:8=?A8<:8=?A?AQJBALCQGJQG=263:L;=>;@590#&)(<.?/8,/'+3*.+.3/&+-./+%.%"&03!$'0' $"$"$*!$  $*!)%+701),'!$1+5./(+ (0(0 "(.20#,/50-:0)(8=,/4<:+23925=46=@ME8><\XPF?FK@D;I=AG@;?H<@EHEMID6@ICHMLEF@8:9;K@H>A:>325=8=9;?@=4=@ACA:F@8BMPAGKSHBEICD[HSOJNHFC=SFEBJCI^KMEFHRH;57=EHDFIPJKDA@AC3EIGPJ=?GV2F=:QC@C?NI?EAKDIYQMHO?DABG@KBABCFHGDOQOJEDCNECLH?5BCB>B6>HA;?=;95D?<9<9B?<:DBJICPMHUJN5DB@;CAD@ECFKNRM;KHCMHTGEDE@?KF>@384823:6<;:?:>A8BGJBE@F>6FD=8GJQJ?EQKFHUJLMFNHDCS?K@L_M2<>CRBACDBF2/CLSMSAJGMHP?=6B<>AC@E>BD@>FB9@EC6H?=@8=:CAEFKA@CENE>7879><=9>7=;B7;5;,738;=9@?GK9=CBA;<@Ya`FJDCE@<=BABCA=59EDF>C?IVETHDKRQHNGLA=AC<5:?K@ILIALO_fSFIBNID10'BJHGBALGMFABGLQMOKEUKGLJ=B<@87586<=./0;B<:CE?;FEBHG@HC8>C=?97<4>DB>9:>BDEFEIOJIRBE=CDG@=;9:F@BHKBLABC>ACF@>;:8E<>CDG=>@8:974<8?>E?BIOL9LHGNCHPJ?>F?>?AC@B76:6@F41?87104851/1/-35484./737167(&8-*,)%%"'%"($#*&)+'#"%&')("#%$')('!"&%! !"! '!$%+0*15.15(%,05-(4/6&*394.$"#'+)/.4/*-5398;>0+@;565241/.273,74=6>@A9<>:@M]O@ADCMN?7BIPHQRHGFBFCAD@?8;:3743:>;9?9;?B@BAFH7=RECEKHCFADRQJBJBKH?A>BEDEDBAFIQ98>@?GP926>9BA57I>:68=6:@FBA>AJGBFCFGIJEJBEJDGHJMAFC?EBHGF@FKEFIEFIKAC=D@ECA;=EFBA56594859BEDCE:7:;38;18K=>8@?7;957/2<=62382=92.(24+6/,*'( '+*)"*+,/*1/-%)%&)%'*)$*$&*)(%$&*)$"#!# "  ($)-3*-34-7.)-,-6+.769/1B:6,$(,*'/451-062?=84/8?7>610232058;84,59=AFAFB?G9<=B@4@?>?FN6@=@15CANIBLBC=BAGI5>LOPJFCGQRFACGEGD@A@<78<;87=?:AC?FC?<8IEAHCJCDAFLITBAD@RI@EFHDFGK?EPEJFE@;CIG596<>E=DRO?IEDHIGN?BGJB8AQFDB?AHJNIG=ERECGFEBKABA2ELBG=@>=56<=B=B6:57;>?;AIEFG@ELJAGICEJHPRPJEHTHNCFHBEGBIBEHIKQPIFGRGNCGFDF@I>FG@DAG>89149JHJLMCINJAVKB@?@AD>A?AGBCD=;<:93HN96;=5486952/16254,2.-'&/.*(0/-,.0354(+-*(%-./)'*)1,.*+*)'(&(%" #! &%()./.-0),4/*-*(0'0:78-2D97"&-.-+65641/25498568@:A@-652303;:8509A=>?BHM97EA@8:94F=K;EB@BC&?A>AI>EHTRP;:BDHFHIGAGB=98<;828;:;?=?B?<@=<;?GCKF:JFJ@E]PM=>9@FNCJMJECDIFUPGUOKIAMFA?81<9?A:D1BJM?B<>Big`IHBEB=@FEHECB7>LJPFIENF>CIeDG=L@FHIDKA9DZNIB=FL=@D@B5:09CBRZIFAGCAELG>AKJGHFIGQRNMERLEH@HI?CFJKGHFIPRPJFPNEH@HIABCGNG@HLMLA<:515;<>?ADFGKA6=DJOIKVWEB=@GB@CD=?EA?><58B?;=:@?;859?<725641-1-3(03/121532/5:9=74121-.5/-+,31*-8*(.,+-+,*%)('$%#"%*-,/-/50-/8(,/+0.04+@7:039D8/(4-36231/476325>9:@;7957468794235<5:=@HCIGBEBHD:<8:037:9;8:?DB98>B@;JTG7;I>?QC?CHIE?CGJTUEGYXQLBE6AEA3?9HA+;'AHF4;7;CS`]ADBI@=?:>:DHDBC?DJL9JDLJE[SKOMLE@WK>G.2BA?7@39GBC:;1,3:5;C=C>A47@=@=@C>DFQEC<>=>JOXUIAEAEDCD=?=>@?@>?=8=@;7:<>CFB@97407452652=635236052597<6568915471713861820,10564/-,'+$+($#+(2)+./.:3:0+0,.14;92<523=:>1,752784202843837?:<:/8:@;725;7014745:<>@KIHBA=;7UbP>=KMDOIFAC8CUDEF=?HCH>6LN@7CNE?=?AJLS>?>B?A>MP9:5;=C9=;:AFH@;A:=L>;>CEGLJEMXBR[BJAGB9AH:>BDOF<0=CB-?=8>T`;C>D<8C,*3AROAMIN?GKADTDC=Zn^[VQEHEFCA=65ECE;6F?<7;A@C=<:464<;<@?@>;84;?><:73:96PG&3D>?EA@ADHDGNHF?GE=JVXPKFICFBA@=:AEA@?A@?A:9;?<@B?=?HLDAB?B=D@AB>9=9:>:75675956>737696>7;A45<@<2562123/342691-68360,+,)"#()-/-01412/3-+.40?>=415@?7636=;>;<;?<6@;>E;4<=456<:595>@BCB=?<9GcNLG:@GAVHKDF:=PRCGE>IAGCKBH=3FG@C>5BFGBEG>B?EC?<:<>:3048>AC=B>?<>A?6@>CIHBEGBIRHLQGECHA?=EBCLOHGBMUQ=?KFI1<9A;NQKIEA?AJ>5H?C?<=0B;E>D<;JNFHGDMB?:@D>C?;=>69=?>XC$=B?DIA>IRYLPOKO\SPKSQKJIED?FBCJBDEGIMQLILQKJFE>G?CI@CBEFAKGB8?DC>B><>=>E=ELMLEFG@MDEMTUQLCD?CA@><>=@F?ACA@A?A@A=GD=>DILDBECDECEFCA@?=@>?;68567>9;698B?8>CIA=AEG>34,420/<;164237;70<:1260+-.*'"!"'/+.1-45960/12)4-32<8<=628;=894:;A?B8DEHGDHC>BABCDABA;?98;<9708>=?@?@CH=?CA;:C@CFCA>EFKTJITRLOBJ>?EB?HJEMFAGROA9D@5-=BGMRKGOG@CEBGBEB8@NVEJBICGCF=JF:JIJSg]FK_aQFB=B>A@;GC>8ANE>?B<96;698=6523548;?=>?@BKQRTWMADFMHIFBC@9?@=<;=>D=@>@C?C@?@E>?>HD<>HOMLEF@CBEF?C>CB<=A@<9=89A?=BAB?>;B@?><:=<:;><=A@B?JOH>NE8BCFADGDAC@EFE=AB=BA>?BCEBCGEWL@IYMLHAH8?GB?HEIKODHNDB3?F@D=CI;DJMAIHB?3OcP?JGIJGAB@ARGF@AEDGB7QCLJDaRBL[Yd^ECE:<=AFD9C;E@>B?79A?=9785/4,849;A2:<=:@CMPSNMNKMKTULNJHLF>GJIKJLKLKLSVLOJILEI=BGA?;=@FKMQVYQKEAHA?BGEFA;=:<=@<@>D@?CFBDAC>BFHLRND@B>ECDC>C@GA;=>?>:9ADB>BJLMNSONP>D@6398@39;=>?D?7;MI;C;<:AFBFIJA,@KC@HKH>;BAFMJCD?;MG@EA=D?BDB?EGKA?=>B@<;C@E=8;:824:58:<=@JEFBA=>:KRHA;750/;<281565;:=:><96=@VLQ6>?BJNE;DMGECNPXQPIHFNELG?JMC@?>?<@>?>@?ACA=?DJID>@BCFHIJE8@B?>=<>?E@C>=@?9=F<=CBE?:9D=D;AKGE6465<=<>;94/-+0492658>@?>=48<063547:;=D<:;<=@=@A@>9;B?89@ABDB>;E[LD?FJBGMJGEHROA@C=75=CDGQPLPL=G?=C=GKEGOBC<=@<9=;<=:74<8;968=9:=<>B?XQ68HNDMC9KIHRLGFLIHMFKRTVNQLJGE;?LHADGFPJGILPSPMJFG:?KHABFDQOCF>AEBO>@JPIHKEHKS]FBCFGNRNBFB<@<;<=:;?A@>DCDJFCEFECAECBA@MIKDBCA?@B>BG?@<9<=?=A@<@C?CMD@NLELZQ^WXD=D4A:;3;=52/27143;:<>:?<58;6=:A=<=:AEDHD>-:=87:GB<>;><:=9B=8??=@E=AHFM>9A@46?CFHIE?PA@JD?KFA:FDA=23B>B=><=<8782;CA@>B:IRFI?ACGFREFGRO:>EBF@4?8=<>E?@EH;GMC@SRCF?IQE@BGP9PK>C@ADC99H\L@7EP@DM@A?37>70@=9DA?BGEAB@8>@>?>7;6294?B?@=BPH3LGFG@=EC@BDGFHI;QSFKLIHRHMHFK??;7?=>CA?BAIGIEJCACBEJOAKPECFABA@>?B@B?=FB:;AB@=;<@=B>BINGFWPGS]WXJI>;G480>;KDJNOQE92*1;ABI>?723243.36:A=<7;:>89:=:B?@DHIDC71>?=8>D@=>=;=;:>=EC=@>CBC?C>A@A>DCAHAG9=@>B>@DMGHMIGFB>GHBLHE=>HIJCIDFDAVMGDFAC?<73?A:CIB@NMCE?ENPEPWBDBDHGFIFCKGPTP\UJFAKICIA?<32B>A8.3/>ICFMN<3HLFDGJH<;>ABOJ?FE>DCED>=HFOCORPTR:746NK10>=C5@EF;BA>@A;@CF;A>@D>CIJGCFHLBCFKOLBHJB@DA=>=C:8@B?;BA@AF>;:@FACAGDJMPTQLSd[QDJE@?7=6:>?OLHMPTI1/.8FHD;67;679687=9EH<6;A>:BAB?=<8:=;:;<=B@>?B@A@?E?@>E?:CMLFDA>=CFE?>BEFC9:?AHBCDCFEHFHBEAE@FD=DUHCEJE?FTHJKFA@C?=8;K>C?:6?A=<9?DADHI@5DJEGFGQKDJLBCD?DLCJH=@AFOFHF327=FDHJHC-AHC@HAG9>DKHJC>FNGCD@BC-[BPXMVRSKD3:5AND9:=AIDABC>DEB?DFCE?BDFEA<:79@:539;@CA?GINMZQL@<9BD@CTSJHGE?CFQLHE=GELJGLKIOFDLDBKJGF>FKJGLHLGCMEBA@CFCEDEGJFMOIJSEIHKIKJIEGDHKDCBAC?<:>CB;?CBCHOFLFG@AKB@CFJH>GKBHA?;:@;BEB@<@?D@IGDNEHGPMEY]\TIPAEJG>73>NQFLPQ<)6EBCA:=:BA>=;<=5@>6>:<97:8<=<;A@=A>C?689:;?B>@>:@?AC>AE@CBABFKOF>B?>BDBA=BCG@A<@?A@DA@ADIHPFKNC:C?C?LIKAIDBAC=RNHGMKFB@<=CD<:AFCEPOQZR7FK<9BGD?;HGNLFMC2:6;EF@EHFE?>CA;7@<=CGIHG@NGBHE?GEFi\M]BLQA@2=@7IECQDCBCA9?=AJKJEGHJDADHEBC?9@;>9;=MQIAC@?>A;BADJQOXFONLXWTQYJSF=06:>IJMUJ?,.3?=>CD:=B?C@>EC<5AC>=@CDBADIOLHFGHGACE<@C@<>;=?>A>@?D@>CFJG@>?BFEGHGDB;>EDBCACAEABAEKJKNGSE>AHJDEHKFJQK?EDHWJIGDECAB?@:7>?;A<=CLGBD<>5@<@BJGNJEFEDBG?BDAD@<>E?E?7KBGHEB?INPRGL@8?;=NGHJIH7IQY`]UHKOFGEFJAI>FIKJMPUMJIMGHFGKBI@DIKJLMSHEAKEFIKJKOMPGHFKJBFAQGEHTQEJEDBC>8@?=BC=DCDGMUFHCEFCEDHFLCEDED?B;:<>AC:>=ABB=I@<:;<=;9@AB@?CEAJHDEGECBAF@BAKDJCBC@>B@FI>?BDB>ABCDFRHJIGP<8CBA>ABH?EB?=@DA<>LDI?BGCEWXMLHLJFD8?A:=@HCGKC9BIMHJF>GFMPOQMPM274CGC<=@FED5:@AGDBCMFIGCGDBEAJA@DAFJBCFMKA?9I@>?1->EBF@GF?BDFEBC@8?EF=BGFLIEDA@BE76EAIMSOJP]^SPCL<5IACGEIDIEKLQLEHB9GDBGHEIEIEKLKIJFCHAGEHKMLIGMICQTFD>KSIDFEDGFAE>FDAG?FHMOPOKGNC@?EBHORNJFK?DE:79=:AG@BCA>B?EDJCKM\GJHPF@FhXEL9IJR\AI9,IB97.8;@>B?GBA@DE:CP=>E>B@CHJIEBDHIMIJDJKJCALECICEJB>@A>?=?BA6>H@;?<@8EBCHDH4>PIFJCHFEIDGF@IE@?=ABCABA?E@A=FE>:CMLIE?>DFE>AGDG>CFQ]JFHGAGFECB@HOJNPC:B@CI@NFH75:;FGC@=EDG@>CEAGCID=BA@ABEBG>?FEDGLECECJIHFD@AB6FG<>FE?FD@NPQG@9D>DIE@GCOHGFHLKJGD@EABIECAFELIGHGKHLFIFGF@GILMIHEDC;H?DEFGKJCDEFDFBECDJKEGCJKNFGNOMDKENEIETREGFHCHGA=<75=952CDEBHDA?CI?CBA@?>=9;:;@?>E>BFKFDCGMGAD@FEKPOEFCBA@HD?9?G?=@8=;CAEI@DE=KLHMOIQHEJCBFADFDC?:@CAEDBE?AE?ABCBA@ELOF?C?>CEC@>DGAB@AONFCPGCHBC>B@D?D;AID>CHEFLJPN>=CAE>@;@DEAC?B?ADBA@EGKNFTJ?=EDCFLGDF@GC@EK8DCE<@=BIHEACBLGHFC;=>;@=?J;?DBAH9HIPBDH=EDEBAGFLHNLGHGOIFHACDEDBCGFKHMJIGLMFHFBEGHLMIJC?F>BCKHIJGIGFIHFGKH@?GJEBFOJHLRKGIPDEBHIQMCBABDEIGEC?@:4519?GE?AIOLF=EG@IBCDPOQLQORbPVKZFA<=@GO\K71O6>2$*137>?=@DF@DFDBIJDGKBIG@A?AIADFBELIKPLHPJHFJKMKGEDKEBA@AC?=:<;AC=AC@EMKHGIA?HF>GCIM?CHGDFE=>E>87:3>?CB=9;?BEDEJOHJPCBD=CFDG@;<:BCGFKIFBA<@BE>?;?DFAEBFNBCIHFJKH?=HD7A?CI>=AIJNWOQD?FDEBFIOG89>ABDC:;I>@D;=CDB<3?38EGNCL?IDOIFD>GLJLGKHKBGAEDGJHNDBDIJFOG>=>C>657ABG>=?M]LOCGQMLHMGFJGRWQdCGIOA@=DBFD>:6:=7:AGB=BKHCFCGHIFKIBGKDGHKMAGB@DBECEBABGHFGCADBKDHC@BCB=A?DIB@DBCHFPNJIRCEA?HBK@ABCGDMRQHIBKEBLGA;EF?9?B?B??CD9?FB=?>BBEDA@FCAIFN?KAILIDGPJDIEHFEFECMEJKIEGNJFJGIGIQHFKMNLHBGJC:JLDJDCEBDLCHCGHMHCA?AFELHPGDMEBHLIKJBIHIDJGMG>@>?=DGIEGDBCWcYWQMIGLQLJKNMIPX*#1BC=:9BOIGEPRGIFCBCB?8>A:BC?ACBCFIPLFCFGCGEFEGDJFBCEABC:;<=B=A4847<>;CJEG?FLJAGJHBFIHQTOJEITFMBEFADEBF@BCFJKGDCFGHFLDEKGC@E@=?>CD8=CA@EINRMWAHCKEK@?B7B?AEGEI@LIGD@HC;AFE7OQLPGOF;A9FC@?FLINTKE@=JIJBADCDBIECGLGDb[PIGBM>;?7;@C9=GBKJGHKDFNHECKHIFGBHJDGEGJGFMIFIMNMIFEILOM@9EAFE9G?MBLGEDIciYXLFQGKGJEHJNXRZTGAAE@CDIEIGFJNMNIKGCGCEHEDGLNLHIJMHXJG=LFUNDEDFEHBF?@GE@E?CFKNOPNIEIJ?@ACDINPJFIA=B>:@<7>?@A7:/;DBWZHE@GBAFLGB;:>8?ED=;BGJPQTXKLFJKJK>HC;>BCFJIHOQ=>;@>@JNXQJDBMA<9DSO927A=?HBDAHBQEAHGJHJHCBEHD?FEDCKDQHBLJMHEHONJKTMJFBCLNTOJHGIF;=EHEGBLSPREFG;GSPLD?EIG;ELEIECF=CLCGBHOFOHJG?6E6<,BP=5?9ECHC,8?FLCEA>CA?E@EGJLEGFMGJGHDIGBCJNMGHFC?D@CHDJKMDACDEDEBCGDFMGFCEMIHIPNFEKHIBSWGDGIB?@A><7:B=C=@38?OL@:HDAEKHOILDHOEHELHJF@;HDBCNKIHGKB?GEBJDHL@BFCD<>=@AE?D=BC9CEME@HKPTFDF@DEFD;935;>?D?1;:A=35F@=@L>;HCBF=:;:GE=?KC>96762;@C@?:>GCDEABHLJCKJBJDIEJFDBDGDIMKED8KAFH=KCJRID;HIPLQMFIMXRSHOMJGJHLC@CP>9BFGCGHJL?AFDCSMIJGIB>C?=BLI;),6JIGE?A>JC@EFHJICAEB@KEBDCIMDFJIMKJIJNMILKMIJ@JHKTSBHBHF@FDIHIELWMPEG<:MQNHAGEDE8FELNKHFAKCABECEDJDI?@CHCGMJHJFVPOTRHMJ>DBHKYTZ[\WOKB?KA@CB7NBJC>;6B@BLH?9(<=FOCFOSKMIEMRPRKJKLGEHFIBJEDCGFJGIHFBFKH;?AJL?EIFEIB>=:ED=@IDB<=ABA9B>C?C=?9:=@;?FGEG>GOJAFHIDFHJKJIJLJPLJBEFECBF;AFEA=BAH@KG5:CL@MRKNHEFQTPIEOEPKLFKQM;CIHDFCFDAHJ>DGBDFHIEDFNSEIKLJIKMIJIEFIGLMF@B;EFGDIHFISUIUJLFGQLQMPWNMDBJNWLKFGIE=>AGAC>CIPALJC?CPGKFCBROIOEHEAEDEKDOGNTUQCAO?EG.EVMGN>D68DHLJFLJHGEFADFEIJMEABFEFBAB?C?;=>6;?AYC&>C@EI@>KRYKOPKP\RQKTPKIFC?FCHCDFHIMKGEGEIHDBKGDCEACD<=C<@<>FD<@K\GBCJWJFC@GI>@B6NEKA@E>4;5<;A@?4719BALMHAHD@FKI=EKIEGHIGSTKSQHJMKHGBCD=F>@F;DBJG@TLD6CJMHMLKIADHVIAFILIEIKP`N=;AIE=FHIG@LIRFEFCIFB;@>:@=OKECACDL@K@LSPNFNLBL1(PXHMB?8?<8?@?A7<3?AIHDVRHKHFASK@GJ23EHD?A=BDABA@:,/2:=8:C=D?45?CeLA=>KNA7EDCFKHKGLGLJGJOGIQFGL@IOFGHIBNPDJTJ8CDEJFILGNKMILTQMKFCEMIPN>59DJI?@?HA@D?FQMH@DNB>C>CB3iUML>;=8.=IFJHKLFKNGXBJC@FAEJLJEIKVSIOQNKCHJTQTQ?AJFBFJGKHMNULO`JHQFMKOLQOIFGHFKHIB6CJCIBFDACGJG=EID<>IEFC@ACDHLKFE7@CIHACHKJFOKI@D@0HKEHEDGHMGMGEJIEHFHACEFGLEHQLPLFEGFDGAGDED<>@4;<=:@;DMA7?;BJLFDXLIGE>CKLQSMJNKVULOIGIFIGHGMLG@BJHCQVJFGJB=?<=89BBC:4C?@9;CAE><386?;8?<=<95:A?=9:2<9=1BES:4F68=@CBHCDKJGKDGOSH>IGBIJIBHJKHIQRNI@MIQNE>LOLHPKIFJLJRMLRLAHNROSLURQHELMIQID=BDHDFCKJHKRHC=AHJECBAFDGPHNHDFGDFA7EHLG?HEFIGCKQLTI:LSNMIGHI<>AIEGAKPSQIFH@BQMED;EH?BOFGCH=?KEBAJBC@?=><87=AXMP5?ACKNB<:EIPHQIMELQVLQKJKLOJKFDJMIHFIKPMFULG>HDWRCBFBECA;79?><895;=AF@=\`MXMHPG;=9?;?A5A=:=>5:3;V3">MNF?AC>A9=E>FBHB<09IB8G1AC<>C>KROEQRC@KMCBNDHIKHJELOUJNMOKJLKIG8=JIMOKHGEOPNMLDMU[EQSKNDHJQRVRBDEKFJEILMSLQCJITGA?5?>ODS[KN7;5DJX\OEC>EIGADBAFJGECBDBTDEHKMJHKQILJKPILDEHKM[GHCFIABEFIJDIRSPGEB2JQNPJ@FAG;@FOMGJ>GI@CAC?CB?<;><>B@WP49=>67;?>;7:286;648=69=;BHKC@=><7BHNMYI/BFCGL@SUREKLQY\NTISD;BAJLDJIHFGFBJPGDEM@NQBABEIMFUDIVT`Y`PLMNKEHKDBKGXJ0/>DFC:=A@;B?@?<@>=JD<:A<;85BA@FINF?:10H<9?CE;8;B@DF>CBJSRJPHEIM@RDGIHEFNjXQUHOPGBVPJ?BCAFGEAGL@BGDCELGDFKQJGLJNIJHCJENKM=F@?:>@;7AB@>DOG2KFEH@>EB@CDGI=RHKMIHRHMGFJ>=MJDIJGHIDIGDEHGFLKBKFECIHEFCADFB@<=<=CHOKPXNCFV]eWEBCA=@BDF=?6FI?B@96=;<:@>IGNF:;?>AGLGLYKE@ITPMUKJDF?FIDBHLHGC;JH@FMH=ID<@NJMPJIKTUX`_[UJIJRKQJFIGQS?,9BJC>:CBA=D?>C>;95>@>8:>@B?:9=ECDHAC?5?6:97>57BDA@EG?IGJMIPQNJHJQISTEFSLNJMKZOJXTIBGJKJNHJGIJKMNIMLFPRJRLKILJKLKJ7@HKHMOMGFESPKGHICEHKLHKPF:>GLIEF@CDID@=BEHUQMKGEKJI@PMKOBJRDOSEDKEKQKCAFBGFICDLK=AFGEFDGCAFONFGHINMPKJEIJHKIJG@A?<=9@CA@IOFEKJNF?H>7CECLPEBHLQMPOIDCGCIHAGLGHJGDFHGFKFMKJHDFEGAFDED?=@A7=;<9A=DFMF?3<9CA>HFA?A7>B<:61:916/2659:=6<:9>?OGP7;BACKFB>DMOIMFDKLRVKODKFDIEFLJEC<5;ECFEDBGBAELEJMGJXVU_ZRMTMDHTILILDLKaJ7'@INABA?C=>B?<;8:>;DDHGMGFHMHKPXD>?EGEC@DFDIFBAHDJKLPFBPLKQLZVRXQORQKA?IKTIHC=FCFJKFNEJNHPJ?JEACFBJKIGFISTLNQMLFEIOTRCA@FHCEHGIMJUQK\TDRHKJNLNQJICIDLHM@E9;KBJEBDC?AC>9>@D@?HINZPRJ?A9DC@DTSIHF>BFQKIE>GFLJGLKHOHGD?EHI@EQHBFA@IEDCBICA?;=<97?=OFN>?ASNC9GD8;A36?>FMHFHB@C=<9<:=5?:F=;=@?=FHKJL][SKRNHMVEATOLOIXOHURK?JEHIHJMLJKIJHNQRGKCAHKGKOK?8=CFEBHE=AGB?FKGMLOKV@=KEBIQRUQTRFA7GLFLHBJA?HGKFCGDPFHKGITK?EHDEKJIDJKJHPRMNAHMIOSM;HLNHLMJEJIKJNOMUBDORKUKTQMCLHMIKF?>CICGEDJDFIE@BAFCABGEPJNKHC@B7FGCJNKN:BAD8=XZOXYPMKSLIGHKGMG=DAI=?FCMKEJ<9<;>CAYP;7FJDEGAD@709<2A=6CGBAIFAB@6=:5=>926?;:93;<96?A>CPJ4MHDF?9CI@CFGEGJ9SPCILIHSGMHEHCD<>JHFGED:95;=8C=CE>9:?97@C6:3CHCK@KVLHKFCINMRJKEGLGSKB>DFELPBMSYTVMNMLIHFHLIRNTMK=EIF=@CGIECJBNIGIVQKIHIJHIJFGHKTC4@>AEBFB=>FGFOVMFL7LCDGEPGIU_QIXHLKE?GLG>JE?DHAFROJHXE>HPF?KIDGKIKEMVLMRLMGNIL7;FQDKQNJGELRSRJRHLJ=NO`KQLNKDHMVUTD@BHKCGJIJIKOREBHCHFAB?JNRQHJ@9@;NGIJG9JRZca\TGJKCGDEHBH=HKLOTUMI@;JLTOHGK>8:F@?<:>B<7AB?>AC;?CG=<>C64598797=6=?>BJ@?C>;F<:;>C?<59AC=VN?;?AB@<8649B@EB?=?B?8ELHJMPHLHIHIJLJECHLMJOIKJNKROG=FJKJMOMJDGIMHGMNMFEQOMCRSMQBELIMLG=JPJLSMHJQOMEJDIABCKNSGK=@BE78F@HKRLKIJO[\SPDL;5JADGHFEKELHLPKLGAGK[JGCKDAFCFA@=>=98ACB?IMFAJKNPMD;52@RD59=AF?>DC;DB@CB@DJPMXOQ>?A7>DCRQMFCEDIJONFM>GHDGCBD:?:GJEFIJKHEGSMWLIMGMLKROTSMKJIEHISNKHEHK69CGIEB=<@<945749>16>@:;S>7ECF?68?B=23C7.54>CAGPOJPJFAG?DCIG@FJ;@GHIHIHLTPRWPLJEIKJHIJMRNLEGMCNLC@DFHLHRCLSQ[USWMJMGEJBCHFOD;?RIDFG?@=917GED?NPQF@:E?DHFABGEOHKLHIBIDMJO?C;>IBJECDA@AB<>9=?DB?GKOVPRKCA98A8IGAIB?DGD432,8@HOPGIKBCE?LEGCHGECA?<9@9:@=>FMVMA@EJLHGHF\UELYQCNPKQHBIMLJCAHG;>=IGEPSLKMFTPIJPFCOIMQRLSFENJEB=;HCHFDABHOI@;@:ALEKHG7GJQPQ[THN[ZEFCIDGHIFJKDKEAITNLCQLS\XZTNOPIMZf[ROSFMNSLGCDB1BKINPFC@=:=ED;4:8><;18<@=;>D?@BDMQOMFC45D[UGXU[RJA3;?@?C78:@A=@GKNOROJDGEKBLJHJGDLMCAHLKNPNOSTOKJIOKIMIHEIGECGFEGCDG@CGHFJFLSPSWNMIMIAJKDILFIGSF;>PLMIMD@CEGAG=:<=>?DLWMCECDBIB>DLSHKSP>CKNVBHKCNRJC?B?>=6OEIMHMSFQIPKIKHBLOMNONGH@NIHDIFGCBKDKJKUYTONOHKUMANSNKRLKRVJOWO@FGFJHKLMGLIKHJMLJFAFBE?@CIBGBFAC@BHFMDIKIGC9BCGBIF:CKG@HAIJQMKPMFIMRSRF@DHCFHIHIJMQEAFCHGDABAHONOGJD?@:JD?A3-BDAB?=?CEA@=268:=83:@7:;:?=;DALIKZ:?.9JRTXPM()238A9@E<:48OJN@FIRPKJB:6CHIJEDGAJQDADLGMNVOROMIA@KIJKEHIHIHJHDEDJIGC;>GJGHFMNROURQMEJFDOFGLHCRLKD?6FMFGIJB@C:<:7<:FNWBJM@IHEBO@;KGB@YCGNQRNWSHTPE:;GCFB@7>4@IDLEDSQJILGEDMNQNLFCNDSQCA8HB=?KBJKJHJPECLIPSL>FKPIJQLHJIMLMGCJCIJI@BLPSHKAE?>F8IB7BA?DHE=@ACJBHD'1?MVNHPTPFNMPO:FXb^MHU[^ZQFKOMXOGTHEGD>QIKDA@;>673;0@:<@6E@+/*,6B38BPD@GNMIHA>:GECGKJFEHLMKDHIDJGIHKBKLGIHJIHGIEGDKIEBPRG9ILPROSUPLHIONHMJFIHMTNJCDCRLHLICJLJD=<=6:=BCBKRKJHF9AB9ATDH8AMLNRMGFIMLQLFELJ?HFCAOKMUHLDONWTRUKIMLJEJTPRPLFGASJHEIFEDCJELJNX_YSJHGIFECDBHEDGKGF=ORC84A@=EeYQHGBN<;?6>B8>GDKIJKHGNIJ9;BQCLQOQMGDLUQLEJFEGIHECFDJHIGEACE?DE>CD@DEDOHGDGB;@EIE@?C?<9B=>8>CR>IMC<@LEABCMDHJD=@>8B=@D?BKQH?8-HFXIEDF*'9:,89ED;7=7?4B;BIK@>@JAHFPWGNLIKGDIKJKLHEGILDEKEHLJNHNKGD@AGFGEFGCFMGCFKFLKPNMNMJ@AIHJFELNQDE?EKFGBCABHIDBCDRCAIHLH@)?B>EALHLRHT[ESVNKBCBC21A>/25:@CMPJPKIDCDAEDEGICBJ@=CJGHKIHTRVUTMLKFHKIKHLMOSJGODLPEA@CGJERFGTOZWRYQJKIEFCAGC<@CEJIHOPO=?<@?@KNXPJCBJ@FIKHMQKLCDGQHE@DIFABKJFABCKEHFC>=>A?6A79FBGNCNAHDGEDFD=@ACBCBICD>BGSCJFHCDJ?EABJGDE>?<>@?@DK?GFDEKBGJMGL;EADBHGEYSJMKLMIOLDGFOAFJ;?IE>Ra_RJ@FMO\_bUV`\D9OHBCKGIJKC=AD<;7:8318954626;D=F036=AKD=61;B:098CD@><:MUNIEI:@DGILFQMEMEFMKNBFIEMLNKEB>ADKIHFKMKFTECE@FGFHFDGLJLHEHEKJIFILD@LNGIHGKILEGE@IEG?AC>FD=>DAB?D7@AUKD94KE5CJDJEIGJ_RLMT[UKDE9->51-6=FKPHJFCEAGDFEFC?BFJEJHMRNTNKFKIEMKIJHFKIMLDFML>HF@>MINOKJIQRQXUSRJGKMILFLA=EGCGJK?AFDSKIJFJA?B>=BJG8*-9KIHGBDOJQLDCGHLJIKLEIHMHGIKIJFCGAF@BIED@C=@ABE@A@BEFIJDCAOLXPO:9=>ABCE@BGFP?FDME;ADCABEFBFKCG@?:DFGHLEHSOJF@FKEILHAFDCMTJLHEHPISDFQJPHVUCDBCKTfPJGBLKLTh\MVWD@PJEJHJFEC>A>:8231.5951/17=AC><@38&(=?HCD>I;9;:>427BADKJNSNMJFDFDJFIHGJGCJEFCGDJDKMGJLOLKLIJG@BFEBCDEDHIE?>DHDGFIHFCGA@ILKRLRK:?@:FCA>EIHNJECH?59@BECXUMHDIDBEBTIOGH9FUVHQFGUNKSLTUOB=XTJGLEGL^JOKHIOhPOMQWPJRMHIJOJDE;:?9<;690,.9:05695843<=95;:=;IRF@CABFCKHEFKMIATFDEAEHB@9;DCDLFC>?@D?@?B9@59?9AI?A)->I?;LDECBFA;18HKIKFBJPRMH<:?HIKGEGCDQJC=MHKNSORMCBHLJKHEJHIGJDEGIHC>=BNCKGIMSNUSRMFIHBLJGKHTOA@BGFE=FHIFGAKIRECHFB8@=FE;5AJ@TOTJHCAE>BFDHEFD@KDJT\VRIHFIGEBCEDHDCFJH>JID=D@FGDHEGIGEDPTRD=@BC9AEDHOLPTZKHBILIK>FB>ABDHKHFKQP>:7@?@FJ]ONFDE>=IFRGC?A[\REIFSUMPELFDNVSPWPB>LJTGINKPNMLPKU^QLBLIGI?;QSUO5@C=6:851564.5+5@87>?BAHA8-KMWSQHJ?7:812<782<@51<9?>?3@=D@DB7BTGQKHTGEDFCEMHSNLHIHBDLID=JIHGJGLONGHLMEIDHJLGIJDABNJIBJNEIEJIHIFILFGKJGJPIELCBFEA8B>EA:B7>A69,FA5;@?6(=BA;@LJFLG@:JCISMY]QPHK@AFDBAD64:APGABLRMHC@:6@EFJIEGNHNDELEKFJIKLG>GMHIHIGIHGHJIGCKPK8IJLMRQOQWQOINOHJLFJGKOI?=EGIA@I@?C@FQLGI?EOA>?C>?@BA3fSKJ>?@A?AD?BDGERHFTPZYSYRKHJGBFC@DC>@BDHJHFNON?>?DCDE=NDH>IDLRSM:DMPHKMLGKMSOSGKQKGIJOBDA?A;C?>@13=B9.97=DBF>J><><2AIKMEHICJIA18;><320>;8;CA>6;7;H?M@?=5?E=BDCFDCHPNADNUSLHVUVHC?FH?7=5@1>9/?EP?9D;?@JHNPIKEOQOVTSVKGOKLFDEMA:CEDAHJIJBEGFG@IHJECH?KCIM68DPALRMPLEFT[UQKPDGIKGHFI:=GOFGDKIN>JHGHNIFIJHEDEBCECG8>C@LUD>REGNTJGHGCMPKOU`NKGILHNYNAJLGSNEDE^]ITOGEF<>=;A<=:279@25/8<=:>:B<@>B=>EJ=DB@?>214ANB731047GH:;ABEGLEADCFETOMKFIHLIM?CG>NK;4B@:@;DB@?D?ACIGNM9AILQNOLNQNIHEGDC?A:9DWHLEH>?@IGMDNRCOKDIMLHCJFIOMIA@CBJGHMNESIEAGFEGHGFCEMIOFDKEIHJGIKI=HOHIGIHLI?=@:?9<=DC@A?PHGC@>ME?A>@9?E?DFCHB<1!:ICHDFDGIBD@CEAKA8CIELKJCEIUHC@EGJFEMQLKP`J=:AIDFBKJIJEAOJNEFGCDEBDA>=E;8>A?84.,+54379B@C=9B=5EG9@HCIHD84.;C?.-20:3LE98BNBSJMJGD:L[JLMCHRHPGDLPBKJ7>DACJBACRWNMLNXUOLQSKJKGAJABG@GIJ9=C@=;KQG;GIBEKDOLOJGHMHGHMKGD?JBGAFGFIHECBGHPMLH=?=>@FCDCD>EGUMK?EJTROLJPYRFDF?@<;>;GWUID@DHCEFBFGIFDCJMGEKCDFMKGH@FKEIGFGIKFEMGEGHKIJMIFGFDJHNHJGFHFBCIEMKHNJKMJHMB?@DFC:>AHC<:@<;76B@?FLMF?;3H<;<;?BEC@EFHLROTQKGKIBKLGKJRK@BGEAIFBKHMFGFEFKJDHTH?AEIMJHJMKFHLRIGLOIOGDFKILQTB7FDCEBGNLDGCACFGE?A>9B=HIJQES^KINLTLHCMKN?NFMPMiZMNVZRXVNHGDJIGIKDGLPJEAB=>2<5<;?;D=<2 .-,815=>A@>7A6;H?=;39B1269@UA@C8:?BWOFG9G[ZIKIGUQJFPEPGRI9BFBCLFCXNDHFJX[MOKONIJLFIMCGJBJLB:DC?ABKDJGTNKHJTOQLOKILFCG@EFHD@BCDCDFA@LKIORGFED>:D@CADCADBLOJNBKRQSNOUZSFACD?;9>;KRNFMNIFKIJI=AJOLJAJNIGKEHGHKNOHJHILHEGKJIAIEGMKMHCA@DBJGFHMLDNKF?EAGA=E?@D><:5>?>6;>@C>;:>FCEDH>C?5@7:;:A:=D@FEIJOUQPKILFKGJHIQJ?>DGHCA?GCDCDCHMKHEIHIAIHCACHDA>GELHCFK@CEIGED@BDE2GLOJHYJGTFAVNLU[IHDHIBDGFH8>CEGC;=47<>9/64$.-6;3>:>9:;A/:9;A=LE7>;:C08<=:BG>JN=B;GWMDEBJXaC>?GKJ=ZMKG=@KMOQSLNLKMNULMJMJHM@;BG<>B@9:@?CBE86PHOLINKHEFDAOILOLGLDCIJI@>=<8:><@B?:=@AFGBDA?D;AE791.=;C=6?DGIFKJPQLPDBFLIKDKOUI7@BE?BDHEB>GFHGBFCIHD@JKIDFJGJFCJGKILW\WSNLIMHFEHFEFQP?-;6849>GHDCASHKECFLEDBDEC?@DEC9FMJHCGMHNUPIRC@HNUXLPOMIG[e^`[UJMTGIKYbUZQI;7FLD?;B?C=;6:-96467698BG:6?@4A@8=?@9@?;IAB;/64FA@F;3CNEFMO@;=E?RBFSE>IKJNEBMIKAB?FJK5A?IMJMKFKLNUONLJMNLMFEOKE:GFAIDXLGCDCEUYKMTHLRHKQDIOILKJEJMGBGHKIGKHQGIKJIAFIA?=<=:=6>;F<;=A@=;@9B=FDFAIC?E5G4=FD?=?AC@EIJLI@GMGHGIK@=A9=7;?FBARIDAFIHFJGYUHEDGDJQDLTS]WZSNJMJBCLBAOGVI04@BFB;?CA?C@BEBHGEC=>BEBAFD@=@C:K@0867<5765=C<>5INFIB=2DC<@D=7@:@IEGAJFAHDFAEDFAHFKGHLJIEFEFC>ADEGEINLHBJLMLEMOQMTMGEIJABK@<@CBFJEABAIFLQNKHENGOF=F;NOB3@A<;@?<>A476:A@?D?CE?9:@8@CA?@B@ACAEGHFJNLMLKGPLMQHJEOQTZWXULELQKLIEJEGWC4>BJHC:FE@GBC@BDLA7?=@:=C?>DB.:ARGINODUO?KFIODSHIFLOKBJD`eUWUXZTKRSCQUIJPTOI@C>@7@HB;@CB8=>DBC.H7@DIKOISFTZMJMIMKIKIKRHLKHQILHFJF9ISCGFECGH?FAJLJHKLHKLMOQNOMJLJDCMKEFALJGDFCEHCAHJGIDFCEDICA@FJIGECJLMKIMIETKCELGCJH?:CKCKLIMCI:EURHMEDNLJL@IOCJL:6D@HEC=QRUMNKTWONLULJKHECFCECFEK@:B@9ERI=BJBDIGKMKLFHLFGEMJIC>BD?><=;:>7?CI@>B>C>:6:C=RK@>ABFE@=?EFDA9?=90.170".6;<@JLE>ADCG<8:=@=J>;A@7@?:>D?G;:DOIGOPJISCFQIJRKFGIHKFLK>HB6AECILQHBHIQNQMLFBHEGJDBNJGJCHEGA@EHBIJEIKFQHINKOQKLH;@LGCFHCJIGHGHGCDGHLKFDHFDFNKC?ACA@=CFJLMFIEBAGCFGEGHIFAE>BANMIF@?UZQHKEQUJLGLIOHNLA?FCJIBMSRHFHJT\SMSJOKILHFMEIBHLG:@E@?IFESOKMHFQOMKILFCHEDBAGB=<=<>@7:?B=>DGC=;:EBGA?:A@DGIHLHFIGAFGIBADCADB@BECBHKJLQLKGHGIKJIMONSWNMGOLCONDGLPLVA6?GLILFEHDCBE@ADBJA<@PGDG?@=8>5@FB4BHUFBHGAID@MLQDIFN\TOIAE@A8;<5A?3AFUJHKDNKGKPOFMIFIMYTNMCESMLEAGT`EJRJLKLIHGAMJS@E>=@<@?D;=BE@;>A=@BA24/PVCOWFVP=BCHJLMOKGBGIJEFEFCDA@EACGILMQMJGICIMKLMJKNQOHLKRHEQF@HKQRPIE@DHMKJGFBEAEDEFCHF>7GJIHDF@?A?=<6WQA@QKQHPMYJEMAHGDGBFSBC@K@HFDJBDEC=BQLA=IGL?3089FEB=@J`<4J?=;753452<:85>?:H:9A>BQI;:&IK89>;929>HB87=EKGMWAOKAHAKMCFJOMKJD@A9CHDFNLN>AB?5Q]PT]KNLNQHLHIGMIFKGH>?FHIHLQIHGMOMLC@BECHFKFGLHIGFGCEGHECJNKHGKGCEHLGNHFEIDGEHACGEKCEOKNKGEGECMHGFJPED?BDOPNMFC48G\THWS\NGB6=@CAD=@B?EGIJLMQKIDMGHEGIHDABFHA?DHCIJKPQLIKJMIJLJLJMLGKIGIEGIDCIHJQHGJEFHLMLFGC@HB?BGFBDNC<>OKLINC@CEGA4QG?BJPDBA<6A8IFL;I>?JGBL@G?CHDPMHAK?AMORN@FEDL?),.*9>?@?9HQY45?Ti^QB6CSD9@?;7697>;=IHFLJI7FOY]b\YHJPDFHBHACILNFD>IHDFMNJMIHAMJHLACHJHLJIEJHDCADJLHGHLNKQGBJIBMQROIFIACQONFD=9058:6;9<=AB8?AFK=F87BCGE@C;128:=9=C@EAB<:48RXJCPHWHFKFHFDKHMQLJD=BE:6D@FKQREOHOXaSRDJA6DCAGFHDHFIFIJIGHGDHGIHBAFGKENVLSLJGLEIHLJHJLKEIKHKJINJFCDIMNFJSTOGEB2JONOK@FAH;BGENHI@GI?BCFE?D@CILKJSHL[UHLNKLIMID@KHBG:?F>BFGFJDATJIJMHLNJFIK:BSGFIEBGFHJAEAGJMFLJKHMLQTKOKJKLHGDAKGCBDFCAC>@?<:>9B>@6<@EDMK[I+1CASK?G=/1+.9LHA;=LPMQLIJT9>@B?:ADA;C9CECEHE@CFE@7/0:=AC=CMUHF/8JCD;86<697;6D>=:A8=?;@514AJDGIC6169@A38=ADBDKEBECFHDEB<>9=:<:9?D>CJPD?7/FWGD)*;9-:;FD=:A=C=GBELPDEOFIHMFJIFGEGAGHIHEFGJCEKFILJLPJOKGEABFHKHIFKIGIJFKHLEJMLJBGFEFCEHJLBE?EIEFGADABHGCA78318>28@JKUDC@4=@<;897526<@?ADA?@DOIGB@A>?;=A8;GIB@>HA9?QF:DMJOIPJPFDHDEJHDE:=>9?:@G?>CBG=CHOEDK:CFC@B@FLHLMJHEILEHGFHEJFKNQMJIHDAEJDCEBCFJHIKHGFGLJGHFEGILOENVRQWIOINENJMPJLDCGLKXFDCAHCFDFCFAFEHOJIFKHKJGKRIJMHFGMSVLRJ9C:DAJSPIHDFADMNKH>CHGKGJNHLBIBD@AGACDFIGOMJKLGINHIEFH:APGDIGCFECBDCA=>:=<:=C>:E@KD?<42AC>FD<=?9@>@FEAB>;=EB98-=6430747;AI=;B9ALCGAFILF9AB@:>?:6?IC=I:<;9=427BA>CDCEA>7FC@HJG;=EIDIB:19@TKD9IQE-.3*,2740/854=EH?9@84@K;BAGDF?48>A:=?89:;>DF;-LMABGABFE6EHJC>ACELIHA?;6:CGODBURGCKEMIG>?JUW]Z^NJPJHGEGFG?HKNKLMJF;CJDGJQMIMLHBILHC@GFIGKIKEFIDB?ADEG?@C>CABCE?<9=.18KIPVB@>G:<434?953<=:5<>ENMJFELDIJCFIHNSEGHNIFDLJLEJCKMJDEADHDJGDEJLG@QECD@BEGBA?9=D@5><6>K67A>E05;>;@F@FA82DNDRC?IXF>983)-2./51;37=?:7;=:NE?CE?LFA>AD:;D@76>@=D@01CN7FP@FI=>CEHEGDCIHKIJ=JPH:4>@A?A[bOLFCID8?:8?C:9EHAJMDHKFCMKDELNPKIHKNI@DGJMHDJTKLBDA@NJNLKAFGFHKJKIAKIDHORJOIMJ>MN^LKOLNKDHMVUTD@BHKCEHGHJOKFLKEQOHJLOMLKIGEILQPIL8BDA3H@EFIEHFGKJKHFHDFHGIE?FGICGVOLQOMLJFPHIHJHJHFKIEDFEBCECBACFA@97/NWROFIJ@5;5213<583=A53><@?>?4B>FBGC>ITINJHQECEFCEKISMJGHFBDMHB=JHGIGJGLMLIHMLEIEHJKHJDCDMJICKOEJFJHFHFIKGIJIGKQHIFLCBGDA9C?F@C=:?AFXHMBPJHFGCN@J@?>D?7>?>47:89?<0B?;40B7AFI?;:=?:>JH5:>UFELI94/8602587376;:=<@>BC<=FIA:=3?<8:=89?AHCN7EHD=9>EIE@HFELHJQ@?>@8DOQ=53@>=HBC@HAQH?GLGFIQNMCBGEFOLGHGPSFPIJHDKLNJKPJIFEHMKLNJLSIBIKMJOMNGEONMDNOMPCEKIMLG=IJOJKQKFGHKLIJNBALFKHSJEGIEJHEIJG?CB;M>?KFEDCQKJB<>B>GE?DHMFGDJEHJHIHDAKMSXQRJGIFEKHDAE@EHJMFGDEADFEFBE@H?=?<3AGLKEGIBIF@A2:;?<20=:H@K>JAOZINGNIKGKCFDNI6?A?H?XaID?GJABAIF@KGI7AGMHFHA<;=6:8A?>B:>?;F@G9DPFNFK;4.2067:752=3<97=76;>=;>?=<5@D=85/:A9427;C:9>:@?HF<;ANMCFEFHGFGHJLJB@FGCNRGJIGF>B?=@I?'.*3HIGFA?CPDADGIHIEINRJKJEFDJILEORKPRFNKIKGLGMLGHEJKMJKMKJIDCJNMLKNKNPLKLKJKHKIKJ9>DNDMQMOHFEJMLHNIHFBKGKIQILIKFGFEHIHFI;>?:>@9BAG;@FCBC>JMKCE@AFBF@B@EFJHJMKGFKHGHDJFINSNKJGH@BLEDECBGCJFIHIHGCBCEB@A=C>@?CDOEHIULKIGITNPKMKLKGIEIAEFHGOFGFEF@DNJ@;IDFKGJHKMLIJILFJDG@DAGOHECFH8=:=ECVH?ODNF?B@GC>@BC9J;=FJGMCD;<5@7.05783741282<67956>?7:>=:>GFB;617>09<>=5=93>BAFEA;AJGFJDCEGIKGFKLJH7JKIJILEKGE><@=<@<./CK0KPE?CDIC6AKIEGFIJGLKD?@AFGLHTLJ\JFOMGHIKLMIGFEIGIHJHJIMLNMJNLIMFIHPMJSPHEB?=GCHGFHIEA=AF?Q>?HJCBD@HKRIMNQGHFKCDCHFDFHKIKJMFCDICIFDAEHEJFHEFIGFHCDEA@?AB>:B;4GF9AICKHD97.;A?.1:5NID:8CNBSHKIGB;KVHLKBIQGNFGKPCK7?EBDJB@ERZLNMLOYTOLPSKGBKAGAHKJ:>D@=FHGOE@6:;?C=@:<>81675=:7?6C>;B@F<0=D:397;1.41323.2/357;=:7:6:;9CIJA?=68=DEF<2;@:@EB@B@DFMNDELA@ADF?DHKEH@KFTJAHAHGC:EC/>HEKORNGBC14GLGHABKIOI<:@AGFEHMOJMPBHMOJOINPNHDJGKHJHGIKJFHMRKJXPDMOLOILRINVNAEFGJHKLMGLHIKNMLGJGMLJKIHCEHGHEA?DEGHK@E?96GCFKHDLTRI?;CIBA?8?GC;FCLJGLJIFHEFLIFGIKIOEDJLFHGBKJNGFEGFELKHEHEA?EC@=?A?9A5=AEDCH=<2:B1328ATAD78>BTNLDF9IWVGIGHSMJIFNDNGRH8BFBLGE[MKDHEJYLPOJONIJMFJMDHJCIKA:DB>BCJBKITNLKHKTOLOKHLFBF?EFD>BDCG529C8@BE?HFHF=NIE>?MAC8F=;A+:4FLEC5=IA8:DA9?<;79;:8BCE97D;PENKIOGCDGJ?@AHA@?E>DQKLECALF>=B@;D?>F>@5=CB=KgPQEFCJ7?29BA8AIEFMDIJAINDEGMNLGHGHNJE?CDFHNICHNRKFBD=LKNLCBEGDCGECEB=A=DBPYKIMNR[VNLTKMIGBI@CG@ICKE@MDFB XXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/radioco.pcx0000644000175000017500000000565511357170241023211 0ustar keeskees ??,, @¶‘|wvulib]WOG@;7' ľyxtqmligeb[\XSKCA;434$ Ŀ¸¯}zvrpmicb`^\ZXSRNJGA@820.- ý|yvsnkhdb_ZWUSPNMIEB@><:3/,(%!ƿ¥|xtnkfc`]YWSPLJHGEA?;972+)$#þ~zwsqlid`\YVSOLIFB@>=9853.-,'$! Ž{yvsnlgb\[VTPMIEA?<;:631.,&$! ſ~zxurnkfd^YSPNKGC?<87652.,+'$"! ÿ}zvspmhe_\XRNJHDA?9721/.-('$# ž¢~{vqnkfd^YTQLJD@>=850.-*'$! ~yvplec^[URMJFC?;630.,+)%! ~zuokgaZXRPLHEA>:62/,*(%! ƒ|xwrmhc[XQMHDC@<751.*(&$# }{vrlkec^XSNJIFB<;940.+*$# zurmida]ZTRLIFB>972/,*(%"! }vsmjd`[VROLHFDC@;810-*('#! |xrqje^[UQLIFCA@=:62-,)'%! }ztpmhc`XTOIDB?>;74/,)&$" ~xrnkgc[YTPHD><:8731+(#"! }zrmif_\WTNHB>986531.*'$" ~ytnhc_ZWSNIC<;7510,+(&$  wrmhc\XTPKG@<8751,('$#$ ~tmhd_XTMJF@;852/.+'"! vmfd`\UQHD>:741/+(&  sgcaZWQLFA;821/-(#! ka][VQLG@<73.+*)$ ud[YVQKFB<920,)&#! k_XSPJD@<85/-)%! f[SNLE?;730+($  _VMJE?:42/+(%  [PIFA<71.*'%" WJD@;62-+'$  PD><63.+'$# NC942.*&#  G>51.+'$! D9/-*&%  ?2-)'$" ;/)'$! 7-&$" 7)"!  2&  /$ (  "            !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/mouse.png0000644000175000017500000001134211357170241022701 0ustar keeskeesPNG  IHDR @{u :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:o'IDATxb diip]#v0220R 0 oCb0CTT@G:"^ &P<???deeG8 ///իWRhG#Ξ= rl#ri´ .^Ƞ? & 3};$ @,߾} /_-/JGxt r  ]\\ Rr #be-X8AC&L`8rb`2!8 9@>%a 9Xq0qg@}@a[@  x]+zA jA511a*/@A@U>,A =,\p:9ݻw`yP<1'1(/ 17 bj;u <޸q!)) 8('*CXXfA ='ԁ,Py &\J 9re{ܻ;vxj.((w ĿaDD3Cp: 8A@`|3P!ЛSN7@!J Pi3@GH9x-׆ ϝ;ǐ` PvXs :77D_ ~I ?POۃ2,7G .jjj  r@+T/Ȝ@?(-/%(2@! :Ç @HF`Gbz# T/>B}/Xl9(˂r 2JI]!J  @a*5dcfoC18wipaz p;._#bAq^-]5sLˁ 1B@1B}*Ʉ4A t!ǏAӧOAP-ub@ bHؠ|*^/]^an ,@3 J?@BTs0@Ov8, J9V:Plƭ>|08;TNy ӑ "4D`EDfPd9ȎkJ'X !&./!J P@Ҁ,l%K744r$+<"-1 FDm\faP 3@l<q1 r[hhj@?h} )P:b 2C (/ P%\Pŗ X J_>Yu(i@ ,X jdDx@PN`5  RB5@ Z*: Hr4`mP40B-bZ+Q0"5@ P ~#QA(99 0!!DE@1Yij 0%>p#,@d9!(j"P5@ h@pЀ; 4w@ h@pЀ; &eDIENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/cphelp.txt0000644000175000017500000010072111357170241021257 0ustar keeskees# Doomsday Control Panel Help. # # [ID] # Key = ... # Key = ... # # Values can be split on multiple lines like this: # Key = begins... \ # ...and continues \ # like so. # # VIDEO # [Gamma correction] cvar = vid-gamma def = 1.0 desc = Smaller values result in a darker picture. In order for this setting to work your display adapter must support color adjustments. You should lower the gamma correction value until dark areas in maps become sufficiently dark. Note that with some monitors different resolutions require different gamma correction levels.\bUse the -noramp option to disable all color adjustments. [Display contrast] cvar = vid-contrast def = 1.0 desc = Modifies the steepness of the gamma ramp. Values greater than 1.0 result in a more colorful picture but since the colors are clamped, some are lost in both the bright and dark ends of the ramp. Values less than 1.0 fade the picture towards gray. In order for this setting to work your display adapter must support color adjustments.\bUse the -noramp option to disable all color adjustments. [Display brightness] cvar = vid-bright def = 0.0 desc = Applies an offset to the gamma ramp. Positive values make the picture lighter, negative ones darker. For the best results, use a small positive brightness value with dark gamma and slightly increased contrast. In order for this setting to work your display adapter must support color adjustments.\bUse the -noramp option to disable all color adjustments. # # AUDIO # [Preferred music source] cvar = music-source def = External files desc = There can be a WAD lump, external file and a CD track associated with each song. This setting controls which of these resources is actually played when the song is started. If the selected resource is not available, one that is will be chosen instead. [16-bit sound effects] cvar = sound-16bit def = No desc = When this setting is activated, 8-bit sounds are converted to 16-bit before playing. In order for this to be effective you must also choose a sample rate higher than 11025 Hz. [Sound effects sample rate] cvar = sound-rate def = 11025 Hz desc = The minimum sample rate for all sound effects. Samples with a smaller rate will be resampled to this rate before playing. To increase the quality of the resampling, activate the 16-bit sound effects option. [Show status of channels] cvar = sound-info def = No desc = The status of all sound channels is drawn on screen. This is intended for debugging. The displayed information consists of sample cache size, channel flags, volume, frequency, latest start time, cursor positions, buffer flags and sample information.\bO = Origin, A = Attenuated, E = Emitter, 3 = 3D, P = Playing, R = Repeat, L = Reload. # # GRAPHICS # [Field Of View angle] cvar = rend-camera-fov def = 90 desc = Adjust the camera's Field Of View angle according to your monitor configuration. If you have a large monitor and view it close by, using a larger FOV angle (around 100 degrees) will result in a more natural game view. With small monitors it's best to stick to 90 degrees or else the fish eye effect may become distracting. [Sky sphere radius] cvar = rend-sky-distance def = 1600 desc = The sky is composed of two capped hemispheres rendered around the camera location. The sky sphere radius is the radius of these hemispheres. The primary purpose of this setting is to determine how large an impact fog has on the sky. Larger radii will result in a sky with heavier fog. [Always render full sky] cvar = rend-sky-full def = No desc = Always render both the upper and lower sky hemispheres, even if one of them might be fully occluded by world geometry. If your video card has sufficient fill rate, keeping this set to Yes is a good idea. In some maps there may be a hall-of-mirrors effect visible in the sky when this is set to No. [Shadow visible distance] cvar = rend-shadow-far def = 1000 desc = Maximum distance at which shadows under objects are visible. If the object is farther than this, no shadow will be drawn. Since the shadows are extremely simple, posing little fear of performance loss, it's safe to increase this value as needed. # # GRAPHICS: LIGHTS # [Blending mode] cvar = rend-light-blend def = Multiply desc = The method used to draw dynamic lights. In the Multiply mode, color from dynamic lights is multiplied with the underlying surface pixels. This allows dark areas to be correctly lit up by the lights. The Add mode is faster but doesn't look as realistic.\bThe third mode, Process wo/rendering, is for debugging. In it, all dynamic light polygons are calculated but none are rendered. [Dynamic light radius factor] cvar = rend-light-radius-scale def = 3 desc = The radius of all dynamic lights is multiplied by this factor. Lights are never larger than the Maximum dynamic light radius, though. [Maximum dynamic light radius] cvar = rend-light-radius-max def = 256 desc = The maximum radius a dynamic light can have. This is just a limit: to make the lights larger, you also need to increase the Dynamic light radius factor. [Light range compression] cvar = rend-light-compression def = 0 desc = Sector light range compression. Positive values will brighten dark areas while negative values will darken light areas of the map. [Floor/ceiling glow on walls] cvar = rend-glow-wall def = Yes desc = Glowing floor and ceiling textures will cast a dynamic light on surrounding walls. # # GRAPHICS: HALOS # [Number of flares per halo] cvar = rend-halo def = 5 desc = Maximum number of lens flares originating from a luminous object. To disable lens flares, set this to None (zero). [Use realistic halos] cvar = rend-halo-realistic def = Yes desc = When enabled, halos are rendered in a more true-to-life way. This also means that secondary lens flares are disabled. [Occlusion fade speed] cvar = rend-halo-occlusion def = 48 desc = The rate at which a halo changes state from "visible" to "occluded" and vice versa. A small fade speed results in halos that appear and disappear softly, but are visible through walls for a short while before disappearing. [Flare visibility limitation] cvar = rend-halo-secondary-limit def = 1 desc = Controls when secondary lens flares become visible. They are only visible when the light source is close enough to the camera. The larger the number, the farther away secondary flares are visible. [Z magnification divisor] cvar = rend-halo-zmag-div def = 100 desc = The higher the number, the smaller lens flares become when the source is far away. Normally halos grow slightly larger as they move away from the camera. # # GRAPHICS: TEXTURES # [Texture quality] cvar = rend-tex-quality def = 8 desc = Depending on your system configuration, some textures must be resized so that their dimensions are powers of two. In these instances, this setting controls whether the higher or smaller matching power of two is chosen. At quality zero, all textures are reduced in size, to match the largest power of two smaller than the original size. At quality 8, the resizing is always done upwards. [Smart texture filtering] cvar = rend-tex-filter-smart def = No desc = When enabled the hq2x texture filtering algorithm is used to enlarge all textures as opposed to linear scaling. [Bilinear filtering] desc = Controls which class(es) of graphics receive bilinear filtering. Disabling bilinear filtering results in "pixelated" textures when up close. [Anisotropic filtering] cvar = rend-tex-filter-anisotropic def = Best desc = When textures are drawn onto surfaces at high angles compared to the camera, bluring is introduced which reduces the overall quality of the visual. Anisotropic filtering can be used to help reduce this bluring. Sample multiplier: 0= Disabled, 1=2x, 2=4x, 3=8x, 4=16x. # # GRAPHICS: OBJECTS # [3D model visibility limit] cvar = rend-model-distance def = 1500 desc = Objects farther than this will never be rendered as 3D models. [Align sprites to...] cvar = rend-sprite-align def = Camera desc = This setting controls which direction sprites face. Aligning to camera means the sprites are always upright (to make them appear more 3D) but they will turn to face the camera coordinates. Aligning to view plane resembles the way the sprites were drawn in software. The "limited" options restrict how much the sprite can tilt vertically. [LOD level zero distance] cvar = rend-model-lod def = 256 desc = The distance where LOD level zero becomes LOD level one. Only affects 3D models that have Level Of Detail information (DMDs). # # GRAPHICS: PARTICLES # [Near diffusion factor] cvar = rend-particle-diffuse def = 4 desc = Particles may cause excessive overdraw if many are visible just in front of the camera. This setting makes large particles near the camera more transparent and ultimately invisible. The larger the diffuse factor, the smaller particles will be affected. The end result is that particles will not be visible near the camera. Increase the setting if framerate drops alarmingly when in smoke. [Near clip distance] cvar = rend-particle-visible-near def = Disabled desc = Particles that are closer to the camera than this are not drawn at all. # # NETWORK # [Cl-to-sv pos transmit tics] cvar = client-pos-interval def = 10 desc = The client periodically sends its coordinates to the server in order to keep it synchronized with the player position the client perceives as correct. The interval between the coordinate transmissions as a number of 35 Hz tics. Use a larger interval with low-bandwidth connections (can lead to more warping, though). [Server login password] cvar = server-password desc = If a client wishes to make a remote console connection to the server it must specify this password. If the password is empty, clients can issue console commands on the server without specifying a password. Clients use the "login" and "logout" commands to begin and end a remote connection. [Frame interval tics] cvar = server-frame-interval def = 1 desc = Number of 35 Hz ticks between frames sent to clients. Only for the server. Small intervals require more bandwidth but result in smoother animation and other world events. Use larger intervals (2..5) with low-bandwidth connections. # # CONSOLE # [Silent console variables] cvar = con-var-silent def = No desc = Normally when the value of a console variable is changed, its name and the new value get printed in the console. If the variables are silent, this will not happen and the value can be changed without anything being printed as a confirmation. [Command completion with Tab] cvar = con-completion def = List with values desc = The Tab key is used to complete words in the console. The console knows how to complete command, variable and alias names. The completion can work in two ways. In the "List with values" mode, pressing Tab will complete the unambiguous part of the word and print a list of possible completions. Variables will be printed with their values. In the "Cycle" mode, Tab is used to cycle through all the choices. # # CONSOLE COMMANDS # [add] desc = Add something to a cvar. [after] desc = Execute the specified command after a delay. inf = Params: after (tics) (cmd)\nFor example, 'after 35 "echo End"'. [alias] desc = Create aliases for a (set of) console commands. [bgturn] desc = Set console background rotation speed. inf = Params: bgturn (speed)\nFor example, 'bgturn 20'.\nNegative speeds are allowed. [bindevent] desc = Bind a console command to an event. inf = Params: bindevent (event-descriptor) (command)\nExamples:\n bindevent "key-M-down" {print "M was pressed"}\n bindevent "mouse-right-up + key-shift" {print "RMB released while Shift down"} [bindcontrol] desc = Bind an input device to a player control. [bledit] desc = Enter bias light edit mode. [blquit] desc = Exit bias light edit mode. [blclear] desc = Delete all lights. [blsave] desc = Write the current lights to a DED file. [blnew] desc = Allocate new light and grab it. [bldel] desc = Delete current/specified light. [bllock] desc = Lock current/specified light. [blunlock] desc = Unlock current/specified light. [blgrab] desc = Grab current/specified light, or ubgrab. [bldup] desc = Duplicate current/specified light, grab it. [blc] desc = Set color of light at cursor. inf = Params: blc (red) (green) (blue)\nFor example, 'blc 1 0.5 0.2'. [bli] desc = Set intensity of light at cursor. [blhue] desc = Show/hide the hue circle for color selection. [blmenu] desc = Show/hide the bias menu. [chat] desc = Broadcast a chat message. [chatnum] desc = Send a chat message to the specified player. [chatto] desc = Send a chat message to the specified player. [clear] desc = Clear the console buffer. [clearbinds] desc = Deletes all existing bindings. [conclose] desc = Close the console prompt. [conlocp] desc = Connect a local player. inf = Params: conlocp (playernum)\nFor example, 'conlocp 1'. [connect] desc = Connect to a server using TCP/IP. [conopen] desc = Open the console prompt. [contoggle] desc = Open/close the console prompt. [dec] desc = Subtract 1 from a cvar. [delbind] desc = Deletes all bindings to the given console command. [demolump] desc = Write a reference lump file for a demo. inf = Params: demolump (demofile) (lumpfile)\nFor example, 'demolump demo1.dmo DEMO1'. [dir] desc = Print contents of directories. inf = Params: dir (dirs) ...\nFor example, 'dir data\'.\nVirtual files are listed, too.\nPaths are relative to the base path. [dump] desc = Dump a data lump currently loaded in memory. inf = Params: dump (name)\nFor example, 'dump PLAYPAL'. [listinputdevices] desc = List all currently active input devices and their controls. [dumpkeymap] desc = Write the current keymap to a file. inf = Params: dumpkeymap (file)\nFor example, 'dumpkeymap finnish.dkm'. [echo] desc = Echo the parameters on separate lines. inf = Params: echo (cmd) ...\nFor example, 'echo "hello world"'. [exec] desc = Loads and executes a file containing console commands. inf = Params: exec (file) ...\nFor example, 'exec "myconfig.cfg"'. [flareconfig] desc = Configure lens flares. [fog] desc = Modify fog settings. [font] desc = Modify console font settings. [help] desc = Show information about the console. [huffman] desc = Print Huffman efficiency and number of bytes sent. [if] desc = Execute a command if the condition is true. [inc] desc = Add 1 to a cvar. [keymap] desc = Load a DKM keymap file. inf = Params: keymap (dkm-file)\nFor example, 'keymap finnish'. [kick] desc = Kick client out of the game (server only). inf = Params: kick (playernum)\nFor example, 'kick 1'. [listcontrols] desc = List the names of all player controls. [listaliases] desc = List all aliases and their expanded forms. [listbindings] desc = List all event bindings. [listbindclasses] desc = List all event binding classes. [listcmds] desc = List all console commands. [listfiles] desc = List all the loaded data files and show information about them. [listmaterials] desc = List all known surface materials. [listmobjtypes] desc = List all known mobj types. [listvars] desc = List all console variables and their values. [load] desc = Load data file(s) (a WAD or a lump). inf = Params: load (file) ...\nFor example, 'load mylevel.wad'. [login] desc = Log in to server console. [logout] desc = Terminate remote connection to server console. [lowres] desc = Select the poorest rendering quality. [ls] desc = Print contents of directories. inf = Params: ls (dirs) ...\nFor example, 'ls data\'.\nVirtual files are listed, too.\nPaths are relative to the base path. [mipmap] desc = Set the mipmapping mode. inf = Params: mipmap (0-5)\n0 = GL_NEAREST\n1 = GL_LINEAR\n2 = GL_NEAREST_MIPMAP_NEAREST\n3 = GL_LINEAR_MIPMAP_NEAREST\n4 = GL_NEAREST_MIPMAP_LINEAR\n5 = GL_LINEAR_MIPMAP_LINEAR [net] desc = Network setup and control. [panel] desc = Open the Doomsday Control Panel. [pausedemo] desc = Pause/resume demo recording. [pausemusic] desc = Pause the currently playing music track. [ping] desc = Ping the server (or a player if you're the server). [playdemo] desc = Play a demo. inf = Params: playdemo (fileName)\nFor example, 'playdemo demo1.dmo'. [playmusic] desc = Play a music track, music lump, external file or a CD track. [playsound] desc = Play a sound effect. [quit!] desc = Exit the game immediately. [recorddemo] desc = Start recording a demo. [repeat] desc = Repeat a command at given intervals. inf = Params: repeat (count) (interval) (cmd)\nFor example, 'repeat 10 35 "screenshot"'. [reset] desc = Reset the data files into what they were at startup. [safebind] desc = Bind a command to an unless the event is already bound. [safebindr] desc = Bind a command to an unless the event is already bound. [say] desc = Broadcast a chat message. [saynum] desc = Send a chat message to the specified player. [sayto] desc = Send a chat message to the specified player. [setcon] desc = Set console and viewplayer. inf = Params: setcon (playernum)\nFor example, 'setcon 1'. [setname] desc = Set your name. inf = Params: setname (name)\nFor example, 'setname "my name"'. [setres] desc = Change video mode resolution or window size. inf = Params: setres (width) (height)\nFor example, 'setres 1024 768'. [setbpp] desc = Change color depth (bits per pixel), either 16 or 32. inf = Params: setbpp (bits)\nFor example, 'setbpp 32'. [togglefullscreen] desc = Toggle between fullscreen and windowed video modes. [settics] desc = Set number of game tics per second (default: 35). inf = Params: settics (tics)\nFor example, 'settics 15'. [setvidramp] desc = Update display's hardware gamma ramp. [skydetail] desc = Set the number of sky sphere quadrant subdivisions. inf = Params: skydetail (num)\nFor example, 'skydetail 4'. [skyrows] desc = Set the number of sky sphere rows. inf = Params: skyrows (num)\nFor example, 'skyrows 8'. [smoothscr] desc = Set the rendering mode of fullscreen images. inf = Params: smoothscr (0-1)\n0 = GL_NEAREST\n1 = GL_LINEAR [stopdemo] desc = Stop currently playing demo. [stopmusic] desc = Stop any currently playing music. [sub] desc = Subtract something from a cvar. [texreset] desc = Force a texture reload. [toggle] desc = Toggle the value of a cvar between zero and nonzero. inf = Params: toggle (cvar)\nFor example, 'toggle rend-light'. [uicolor] desc = Change Doomsday user interface colors. inf = Params: uicolor (object) (red) (green) (blue)\nFor example, 'uicolor text 1 1 1'.\nPossible objects are:\n text, shadow, bglight, bgmed, bgdark,\n borhigh, bormed, borlow, help [unload] desc = Unload a data file from memory. inf = Params: unload (file) ...\nFor example, 'unload mylevel.wad'. [version] desc = Show detailed version information. [write] desc = Write bindings and aliases to a file. inf = Params: write (filename)\nFor example, 'write myconfig.cfg'. # # CONSOLE VARIABLES # [con-alpha] desc = Console background translucency. [con-light] desc = Console background light level. [con-completion] desc = How to complete words when pressing Tab: 0=Show completions, 1=Cycle through them. [con-dump] desc = 1=Dump all console messages to Doomsday.out. [con-key-activate] desc = Key to activate the console (ASCII code, default is tilde, 96). [con-var-silent] desc = 1=Don't show the value of a cvar when setting it. [con-fps] desc = 1=Show FPS counter on screen. [con-move-speed] desc = Speed of console opening/closing. [con-text-shadow] desc = 1=Text in the console has a shadow (might be slow). [con-transition] desc = Transition effect used when leaving busy mode: 0=Crossfade, 1=DOOM (smooth), 2=DOOM [con-transition-tics] desc = Duration of transition effect in tics. 0= Disabled. [ui-panel-help] desc = 1=Enable help window in Control Panel. [ui-panel-tips] desc = 1=Show help indicators in Control Panel. [ui-cursor-width] desc = Mouse cursor width. [ui-cursor-height] desc = Mouse cursor height. [vid-res-x] desc = Default resolution (X). [vid-res-y] desc = Default resolution (Y). [vid-gamma] desc = Display gamma correction factor: 1=normal. [vid-contrast] desc = Display contrast: 1=normal. [vid-bright] desc = Display brightness: -1=dark, 0=normal, 1=light. [rend-dev-wireframe] desc = 1=Render player view in wireframe mode. [rend-dev-framecount] desc = Frame counter. [rend-dev-lums] desc = 1=Display lumobj debug display. [rend-dev-generator-show-indices] desc = 1=Display particle generator indices. [rend-dev-blockmap-debug] desc = Enable drawing of the blockmap debug display: 1=Mobjs, 2=Linedefs, 3=Subsectors. [rend-dev-blockmap-debug-size] desc = Scale multiplier for the blockmap debug display. [rend-dev-nosprite] desc = 1=Disable drawing of all sprites and masked walls. [rend-info-lums] desc = 1=Print lumobj count after rendering a frame. [rend-info-rendpolys] desc = 1=Print rendpoly pool state after rendering a frame. [rend-light] desc = 1=Render dynamic lights. 2=Process without rendering. [rend-light-ambient] desc = Ambient light level. [rend-light-attenuation] desc = Maximum light attentuation distance, in map units (default: 1024). [rend-light-blend] desc = Dynamic lights color blending mode: 0=normal, 1=additive, 2=no blending. [rend-light-bright] desc = Intensity factor for dynamic lights. [rend-light-fog-bright] desc = Brightness of dynamic lights when fog is enabled. [rend-light-num] desc = The maximum number of dynamic lights. 0=no limit. [rend-light-radius-scale] desc = A multiplier for dynlight radii (default: 1). [rend-light-radius-max] desc = Maximum radius of dynamic lights (default: 128). [rend-light-radius-min-bias] desc = Minimum dynamic light radius to convert to BIAS light source. [rend-light-wall-angle] desc = Intensity of angle-based wall lighting delta. [rend-light-wall-angle-smooth] desc = 1=Enable smoothing of angle-based wall lighting. [rend-light-multitex] desc = 1=Use multitexturing when rendering dynamic lights. [rend-light-decor] desc = 1=Enable surface light decorations. [rend-light-decor-far] desc = Maximum distance at which light decorations are visible. [rend-light-decor-bright] desc = Brightness of light decorations. [rend-light-decor-angle] desc = Reduce brightness if surface/view angle too steep. [rend-light-sky] desc = 1=Use special light color in sky sectors. [rend-glow] desc = 1=Enable glowing textures. [rend-glow-wall] desc = 1=Render glow on walls. [rend-glow-height] desc = Max height of wall glow (default: 100). [rend-glow-scale] desc = A multiplier for glow height (default: 1). [rend-halo] desc = Number of flares to draw per light. [rend-halo-realistic] desc = 1=Use more realistic halo effects. [rend-halo-bright] desc = Halo/flare brightness. [rend-halo-occlusion] desc = Rate at which occluded halos fade. [rend-halo-size] desc = Size of halos. [rend-halo-secondary-limit] desc = Minimum halo size. [rend-halo-fade-far] desc = Distance at which halos are no longer visible. [rend-halo-fade-near] desc = Distance to begin fading halos. [rend-tex] desc = 1=Render with textures. 2=Render with gray texture. [rend-tex-gamma] desc = Texture gamma correction factor. [rend-tex-mipmap] desc = The mipmapping mode for textures. [rend-tex-paletted] desc = 1=Use the GL_EXT_shared_texture_palette extension. [rend-tex-external-always] desc = 1=Always use external texture resources (overrides -pwadtex). [rend-tex-quality] desc = The quality of textures (0-8). [rend-tex-filter-sprite] desc = 1=Render smooth sprites. [rend-tex-filter-raw] desc = 1=Fullscreen images (320x200) use linear interpolation. [rend-tex-filter-smart] desc = 1=Use hq2x-filtering on all textures. [rend-tex-filter-mag] desc = 1=Use bilinear filtering for texture magnification. [rend-tex-filter-anisotropic] desc = Default level of anisotropic texture filtering -1=Best available, 0=Off, 1=2x, 2=4x, 3=8x, 4=16x. [rend-tex-detail] desc = 1=Render with detail textures. [rend-tex-detail-scale] desc = Global detail texture factor. [rend-tex-detail-strength] desc = Global detail texture strength factor. [rend-tex-detail-multitex] desc = 1=Use multitexturing when rendering detail textures. [rend-sky-detail] desc = Number of sky sphere quadrant subdivisions. [rend-sky-rows] desc = Number of sky sphere rows. [rend-sky-distance] desc = Sky sphere radius. [rend-sky-full] desc = 1=Always render the full sky sphere. [rend-sky-simple] desc = Sky rendering mode: 0=normal, 1=quads. [rend-sprite-align] desc = 1=Always align sprites with the view plane. 2=Align to camera, unless slant > r_maxSpriteAngle. [rend-sprite-align-angle] desc = Maximum angle for slanted sprites (spralign 2). [rend-sprite-alpha] desc = 1=Enable variable translucency on sprites. [rend-sprite-blend] desc = 1=Use additive blending for explosions. [rend-sprite-lights] desc = Maximum number of light sources on sprites. [rend-sprite-mode] desc = 1=Draw sprites and masked walls with hard edges. [rend-sprite-noz] desc = 1=Don't write sprites in the Z buffer. [rend-sprite-precache] desc = 1=Precache sprites at level setup (slow). [rend-model] desc = Render using 3D models when possible. [rend-model-lights] desc = Maximum number of light sources on models. [rend-model-inter] desc = 1=Interpolate frames. [rend-model-aspect] desc = Scale for MD2 z-axis when model is loaded. [rend-model-distance] desc = Farther than this models revert back to sprites. [rend-model-precache] desc = 1=Precache 3D models at level setup (slow). [rend-model-lod] desc = Custom level of detail factor. 0=LOD disabled, 1=normal. [rend-model-mirror-hud] desc = 1=Mirror HUD weapon models. [rend-model-spin-speed] desc = Speed of model spinning, 1=normal. [rend-model-shiny-multitex] desc = 1=Enable multitexturing with shiny model skins. [rend-hud-offset-scale] desc = Scaling of player weapon (x,y) offset. [rend-hud-fov-shift] desc = When FOV > 90 player weapon is shifted downward. [rend-mobj-light-auto] desc = 1=Enable automatically calculated lights on mobjs. [rend-mobj-smooth-move] desc = 1=Use short-range visual offsets for models. 2=Use SRVO for sprites, too (unjags actor movement). [rend-mobj-smooth-turn] desc = 1=Use separate visual angle for mobjs (unjag actors). [rend-particle] desc = 1=Render particle effects. [rend-particle-max] desc = Maximum number of particles to render. 0=no limit. [rend-particle-rate] desc = Particle spawn rate multiplier (default: 1). [rend-particle-diffuse] desc = Diffuse factor for particles near the camera. [rend-particle-visible-near] desc = Minimum visible distance for a particle. [rend-shadow] desc = 1=Render shadows under objects. [rend-shadow-darkness] desc = Darkness factor for object shadows. [rend-shadow-far] desc = Maximum distance where shadows are visible. [rend-shadow-radius-max] desc = Maximum radius of object shadows. [server-name] desc = The name of this computer if it's a server. [server-info] desc = The description given of this computer if it's a server. [server-public] desc = 1=Send info to master server. [net-name] desc = Your name in multiplayer games. [net-master-address] desc = Master server IP address / name. [net-master-port] desc = Master server TCP/IP port. [net-master-path] desc = Master server path name. [sound-volume] desc = Sound effects volume (0-255). [sound-info] desc = 1=Show sound debug information. [sound-rate] desc = Sound effects sample rate (11025, 22050, 44100). [sound-16bit] desc = 1=16-bit sound effects/resampling. [sound-3d] desc = 1=Play sound effects in 3D. [sound-reverb-volume] desc = Reverb effects general volume (0=disable). [music-volume] desc = Music volume (0-255). [music-source] desc = Preferred music source: 0=Original MUS, 1=External files, 2=CD. [file-startup] desc = The list of WADs to be loaded at startup. [blockmap-build] desc = Automatically generate blockmap data when necessary, 0=Never, 1=When needed, 2=Always. [reject-build] desc = Automatically generate reject data when necessary, 0=Never, 1=When needed, 2=Always. [refresh-rate-maximum] desc = Maximum limit for the frame rate (default: 200). [input-key-delay1] desc = The number of milliseconds to wait before first key repeat. [input-key-delay2] desc = The number of milliseconds to wait between key repeats. [input-mouse-filter] desc = Filter strength for mouse movement. [input-mouse-frequency] desc = Mouse input polling frequency (events per second). 0=unlimited. [input-joy-device] desc = ID of joystick to use (if more than one). [input-joy] desc = 1=Enable joystick input. [net-ip-address] desc = TCP/IP address for searching servers. [net-ip-port] desc = TCP port to use for control connections. [net-port-control] desc = TCP port to use for control connections. [net-port-data] desc = UDP port to use for client data traffic. [net-queue-show] desc = Monitor send queue. [net-dev] desc = Network development mode. [net-nosleep] desc = 1=Don't sleep while waiting for tics. [client-pos-interval] desc = Number of tics between client coord packets. [client-connect-timeout] desc = Maximum number of seconds to attempt connecting to a server. [server-password] desc = Password for remote login. [server-latencies] desc = Show client latencies. [server-frame-interval] desc = Minimum number of tics between sent frames. [server-player-limit] desc = Maximum number of players on the server. [rend-bias-grid] desc = 1=Smooth sector lighting is enabled. [rend-bias-grid-debug] desc = 1=Show the light grid (for debugging). [rend-bias-grid-debug-size] desc = Size of a grid block in the light grid debug display. [rend-bias-grid-blocksize] desc = Size of a grid block in the light grid (default: 31). [rend-bias-grid-multisample] desc = Sector to grid block, conversion accuracy multiplier. [rend-info-tris] desc = 1=Print triangle count after rendering a frame. [rend-info-frametime] desc = 1=Print frame time offsets. [rend-camera-smooth] desc = 1=Filter camera movement between game tics (OBSOLETE). [bsp-cache] desc = 1=Load generated GL nodes data from the bspcache directory. 0=Always generate new GL data. [bsp-factor] desc = glBSP: changes the cost assigned to SEG splits (default: 7). [con-show-during-setup] desc = 1=Show console when a map is being loaded. [rend-fakeradio] desc = 1=Enable simulated radiosity lighting. 2=Process without rendering. [rend-fakeradio-darkness] desc = Darkness of simulated radiosity shadows. [rend-halo-zmag-div] desc = Halo Z magnification. [rend-halo-radius-min] desc = Minimum halo radius. [rend-halo-dim-near] desc = Halo dimming relative start distance. [rend-halo-dim-far] desc = Halo dimming relative end distance. [rend-dev-freeze] desc = 1=Stop updating rendering lists. [rend-dev-cull-subsectors] desc = 1=Disable non-visible subsector culling. [rend-dev-mobj-bbox] desc = 1=Render mobj bounding boxes (as used for collision detection). [rend-dev-polyobj-bbox] desc = 1=Render polyobj bounding boxes. [rend-dev-sky] desc = 1=Render the sky as a solid surface. 2= Draw sky surface planes. [rend-dev-sky-always] desc = 1=Always render the sky, even if there are no sky surfaces visible. [rend-dev-tex-showfix] desc = 1=Render the missing texture instead of fixing with a suitable game texture. [rend-camera-fov] desc = Field of view. [rend-tex-anim-smooth] desc = 1=Enable interpolated texture animation. [rend-tex-shiny] desc = 1=Enable shiny textures on surfaces of the map. [rend-light-compression] desc = Sector light range compression (brighten dark areas / darken light areas). [rend-dev-light-mod] desc = Show the light-level mod range. [rend-dev-surface-show-normals] desc = 1=Enable drawing of world surface normals, for debug. [rend-dev-vertex-show-indices] desc = 1=Enable drawing of vertex indices, for debug. [rend-dev-vertex-show-bars] desc = 1=Enable drawing of vertex z axis bars, for debug. [rend-model-shiny-strength] desc = General strength of model shininess effects. [edit-bias-blink] desc = 1=Blink the cursor. [edit-bias-grab-distance] desc = Distance to the grabbed bias light. [edit-bias-red] desc = Red component of the bias light color. [edit-bias-green] desc = Green component of the bias light color. [edit-bias-blue] desc = Blue component of the bias light color. [edit-bias-intensity] desc = Intensity of the bias light. [edit-bias-hide] desc = 1=Hide bias light editor's HUD. [edit-bias-show-sources] desc = 1=Show all light sources. [edit-bias-show-indices] desc = 1=Show source indices in 3D view. [rend-fog-default] desc = Default fog mode: 0=linear, 1=exp, 2=exp2. [rend-bias] desc = 1=Enable the experimental shadow bias test setup. [rend-bias-min] desc = Sector lightlevel that is biased completely to zero. [rend-bias-max] desc = Sector lightlevel that retains its normal color. [rend-bias-lightspeed] desc = Milliseconds it takes for light changes to become effective. [rend-dev-bias-sight] desc = 1=Enable the use of line-of-sight checking with shadow bias. [rend-dev-bias-affected] desc = 1=Keep track which sources affect which surfaces. [ctl-info] desc = 1=Show player control state debugging information. [vid-fullscreen] desc = 1=Default to fullscreen. [vid-bpp] desc = Default color depth (bits per pixel), 16 or 32. deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/0000755000175000017500000000000011523516205020372 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/readme.txt0000644000175000017500000000076011357170241022374 0ustar keeskeesThese fonts are the equivalent of the following standard Windows fonts: fixed.dfn Fixedsys fixed12.dfn Fixedsys (12pt) system.dfn System system12.dfn System (12pt) large.dfn MS Sans Serif (18pt) small7.dfn Small Fonts (7pt) small8.dfn Small Fonts (8pt) small10.dfn Small Fonts (10pt) The -gdifonts option forces Doomsday to use the original GDI fonts instead. The -fontdir option can be used to specify a different DFN directory (default is "fonts\"). deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normalbold18.dfn0000644000175000017500000064601611357170241023403 0ustar keeskeesf ! " #!$2%B&U'h (r )} *+, - . /012345-6<7K8Z9i:x ; <=>? @AB<C<D$<E7<FG<GW<Hj<I~< J< K<L<M<N<O<PZQZR%ZS7ZTGZUYZVmZWZXZYZZZ[Z \Z]Z ^x_x `x a'xb6xcFxdTxedxfsx g~xhxix jx kxlx mxnxopq r0 s= tJ uWvgwvxyz{ | } ~/BS   !,!        DWP,Cbi]U]jcF3FFFI333E,#>FFFO(((E$ A jhC +Rb cO( *NP78[ hidK% 1VfX3 FVG$$GVF!1 NM3 FYL* .T ficH$ 2VdO' G(((c( >C (iii\VKˌC 5f{Л|j>,k k1/n֑#Kol+%`f($bߦFGߦc%,^j,#AA#Q]]]G:333mn. 'f(((K333YG V[ R|֞Q2RRRf9 Ukmb :yV3y8_ߨH J` *Jm;;;(((i J, G G3;;;vU1;;;li!6z;;;b(((iVTX3b߰bWR(((buuu y3 [;;;_2z5K{*, |J T(((333]]]Q!;;;^;;;_dFFFu5]˓D :~;;;h!333gV @ ˒C $cp*(((cFFFRRRRRRK333`(((iiiRRRuDc;;;`$;;;iFFFi'1;;;suuuxADz333r/%uv*8333w;;;w9 $MbN$#(((mF J i2v]]]uuu9EEFclnkW6D˔K8v;;;xn;;;h! :~;;;i!Os! HˣJ,n֝N+Qtiii߮;;;d81{ ,/xFFFt.2quuuj*!\˞֕.GG Au+%wu$8y;;;vmFFFg! :~;;;i! C333x%ls''Tt;;;^FRRR^( Ri!5s;;;l$'333rq/;;;K;;;s]]]T#% I e f I%#H\M( R~6!G\K% N֞yA 5;;;߫;;;d :~;;;i!Q֟3333'or'C;;;z ;;;FFFd #k߰FFFߦ> (((dRRR A2z;;;m%*;;;sp. +N333F:9333F M1<333{333{<Wh( >l*RV. yj(]]]h֥e :~;;;i!333XN`߰c6[333\Q˒߰ߧC ;;;^iii@+iiik]]]s16x;;;l$  ;;;_;;;_.zNC`npkV5'f|/\RRRv8 _ߧH :~;;;h!333[NM˔|}˔T MJ/]]]f;;;xjsq2Te (((fJOd G G.|f *s}1,RRRi\ 2;;;ln$6z;;;bJ]]]b1 =֗MSiii[(( `|Y  6|J+TߥT*h֜ާ*Vq sO#AA# fb Y(((V2 f+:333jm/ 'f(((K G^T2!C(((O >#* E(((I1 CpRRR]]]~q>$333B333L> D_333aaG  #F`jlh_Ybkm_=1FFFquuuy@D{(((q+ T(((H  'OaQ* CZP, ,QgjcH% 2VdO'    #EG#   O֝y'+|GYl%  $#iD H`bxd,  +kC Fߦd',C9  $HVF#$GVG!            !C` jh_@ %Kejh]>>]`F 'OipppiM#@V\> 'OipppppiO% :\ hj fU18Y hieN*  !K df]< 8Vhjl kdK*%NipiN%(e˒[ 333P[ RˏC 333JK$]~ B333J333EQvRRRi=Ouuuo m83553O~F5fq(((nJ __NߦF.yHFw\333c` _ߨx333]Y >RRRg.Gː333l.   ,MsoCCosM.  cuuu`%CRRRl֛\  _ a*s`9;;;uc 333iKO˓{Q;;;JA ^O#;;;cV FYH#  FYH# !>d333wߨ\#KgnnnnnngK#\ߨ;;;uf@#au2Am(((֣֛MjkJˑ;;;d5VFFF] 1 yc 333iX' 6]]]pY# *Nht#(((`RRR]3333`P UP U*Ou|KFEK| tQ+9|.1;;;l֤(((֞;;;uuuiiiFFFj. 9iiivuuuv: $333:A9i˚;;;b5 liii`'rc 333iuuuz uKc[   K;;;˔Ha߰ Q8|uuu333g%dz,%dz,.FFF^RRRrY$HH$XRRRpFFF_.ib[ߪ(((Ncdb֣` @]]]T];;;k333cr>(iiigHYw'[ A /w߯]]]333e'mp,'mp,Niii`8 /333X333w333~333~333~333~333~333~333w333X/ 6]iiiNd z1 %FFFf֣d3FFFwRRRu59}> A` 9z5 ;;;P;;;^!3zт ^,(((wQiJ _fZ[Z[ORRR\3 .^^. 2YFFFP333e:6y֡` h\uuu]]]] 1y. ,Ai FFFi'Q333K (Xyx15uRRR(((hR(((w,(k]]]˞ [ /lMFKFN1]]]`ߨ;;;sV$GG$U;;;q֞iiia2 + ˜x# Fuuu U< ~˗;;;_/333w;;;w1 ,xV(  9ߟ(((q֘1HFFFM(((B333uuuz3.w;;;_(wX1pRRRRRR`2uq(W][m*.UwKEEKwV/ FRRRu5 J(((~FFFRViiiߦF UX'p;;;JVFFFk(';;;J]]]b]]]i]]]qRRR]]]y< 333Wiiif( cY D֜;;;w1+u֥FFF(((^%m˙iiio<'f|/,tN%CiFFFt\$KelllllleK$\FFFtiC%XR @|((( ֤ i'* v}x|(((w+M;;;[RY $'8xm333OY@zRRRi2 F]`H.rG*s}1,{f /OtrDDrtO/ (((WU.k߮uuuuM AߦtC8AqߪD T(((K 1iii_֜h*CA 5]]]b֜g(Hiiil333j< 1c]]]`1 ,jߧwX #;;;Pː]]]lF Y(((V db 5665 Fk6 iiiiiiiRRRW( @333c.,333`@ ,RinppppiO' .OfllbD# C``C.QfnlbD! 3VhlfN+1MK/ $GcjmiY: $F\S3 'OaQ* T(((H   C]V6Fˑiii ]]]iiiv(((uuutiiiy333ě333<!JfiR,  +RigJ!      Yl%   i333FFF֘> bxd,  ,mːY,C9  %Q(((nˑ֜ nG 'D_k kj kk_F'                           A`mpppngR2%Gb jj kj[=A`mppnk`K/A`mppppnbCA`mppppkX3(Hc jllldK*A`iV21VgX5A`iV2 'OgcFA`iV2+Rjm\:A`iV2A`j\:1UicFA`j\:#MiiM#%Gb jlifO/ =iiikJ@n֝޿K =ߨ]]]n_. =@ =f(D oߨߨ]]]]/ =a'%`l* =a'(((KC =a26u% =a' =xJ9FFFjC =zOKK>l֝RRRnU$ V= Jv1Vs3 VRV}3NSV85z: V8333c\V_{ `V8ViiiqA6|\V{QggFqf$]\ 9o: ] p']A ]f( :s`]HF> ]>  333ic](((w6 ]> ](((~`c]zO1tn 5]]]mQ_a]ߪ;;;z y(((y}._RRRM_Y$_rC^}M_|ONy> _>  333id_]]]s>_> _d_wcn\֡iii~RRRh*_߰ U$333lc2!*@H 3_T+K333f_]]]uuu}uuuxj K_333;;;;;;vFFFb D$333mRRRX@Ri|y>_˕˕> _>  333id_O_> _d_n#333jRRRbAU˓C _(((X.s(  _@ {;;;c_~,_}+/ty.DH_> _>  333id_._> _d_n,o{% \R_RRRi..s{#  _> y m_}+_}+1yx2\;;;[_> _>  333id_333@_A _d_n,oy$ [Q_֧߮K$;;;jRRRU(%:G3_R(F;;;__߰ {hG_(((333o333f;;;U ;%FFFj;;;_q;;;g _iiiuuuruuuqiii> _>  333id_|5 _\( _((((((]]] d_((( n#333jFFF[9M> _;;;X \wzw}._;;;\_xU%_\*a iii;;;i!_j86d> _>  333id_RRR}1 _ 333o333h333c(((K'_;;;v_]]]grg333{d_;;;u[(((yn]FFF;;;i']uuuK 9o9 ]iiim6 ]H]@  :r;;;e ]D@> ]> !333jd]t']N];;;j22A66333mc];;;j1<(((vn 6iiilOVFFFd,Jv/VvHV^V8MzFFFOV85z: V8 2333zcVTc֝KVaV;;;c! 333c\V;;;c!9(((vgGrf# =(((j8@ m֝ާxI =ߨ n@ =K =a'A k˔֝RRR]3  =a'%`l* =a'$g_ =a.*buuuI =K =333J JC =333J9(((pK=k˓RRRnU$ A`mppppndK*'GblmnjX9A`mppppmbH'A`mpppppiM#A`iV2%F`lmnk`G(A`iV21VgX5A`iV2JNA`iV2 !FcmiQ* A`mpppppiM#A`gO' %NgcFA`gO' .TjiM#$D`kolfO/                dq5        d_G޴d*D\V<                 A`mpppndN,%Gb jlifO/A`mpppnfO.:\ hj jbF$ 2VkppppppppkV2DcgO' A`iV2 HfjV2 HfjX3!JfjU1 'OdY5$MijR+ <]mm`@ <\mm_>Fdk\9 +RjjU/ 'Oipppppppm`ACbnpndF D[P/CbnpncF =FFFiA>l֝RRRnU$  =FFFiAQv֜ ]''fa' A(((K =a' >iiib1 Qp  @]]]`. _h6 YiiiK(֚V/N* 5xF/ o]333J. >@ 5333f. =C Vo9 Fqf$Vl8 >J5x~6Y;;;bV8 @֛[,(((u333a  AߦVAf!3RRRr^ a|]]]|c!/iiif;;;zXtX333^;;;d(XJ/RRRl`F\][ 5]]]mQ]]_V,w._;;;h!]> (v(((y:TߨX* wwCrRRRwG\˔G 5 w333u8 R˔z1 ;;;MJ_ߧ_/ \iiiv: ._c_333c\֡iii~FFFi*_ ;;;b bA  ;iiiZiiii]]]uuuu]]]viiiiiiiZ=_;;;i!_> Rߩp ;;;w1Xuuu}w':;;;siiirA!jiiit@ .RRRORRRdRRRnFFFuuuf_r@'. ym'@qd_ 333a!333iRRRbAU˓D _ ;;;``V%!(>@*!_;;;i!_> ,(((w]2FFFvQA]]]uO .{˔R '@߭{,_GN֞|CCd_W+m{% \V_[ @ˏf'rr_;;;l$`= YRRRu5c(((w,g+ 9;;;vk!HyRRRt<_> %uu% :~d_RRRf2 ,ry$ [X_A !\xHnn];;;9n62FFFvc :uuuvY'v9 N3  5(((y˕T_> C|֝N :~d_˕uuuka3#333lFFF[9M˔F _ˣJ'Uxuuu_nnVvAO FFFo*biiiv9 mRRRt3[֞y. +(((ym'uA$ _> m v, :~d_|M<, [FFFiiii,_ q$G dnn Aߧ߫FFFiii(((b 8]]]vj Az`dNr* 333jc[(((333q333i333c(((K'_> :]]]vY :~d]H  6iiilU]g˔G` ]nn$jMix= !tn+K˔uuuv: Cuuusg! 333icAvN_> `FFFu5 :~dV8Gr߭5VFJ{ _Sˏ@ gg 5333nj$ % uk+FFFc \֚C333c\# ca_> 1(((yT :~d =a'>r333U$ =a+#`R/]]]^oOKK3i]]]oX' _p: $a_Fߤp: 3]]]h=2u]]]?(((KC (K_FKߤ]]]FCdA`iV2*[uuus3338A`iV2 %NijT,+MdlnhX6#MiiM# >\jllgR2%NdY8 *OaN%A[V8FcnkV2 +RjngN'  'OgcF<]mppppppppiM#_p<$AYL* #:nc  :m|:         _ћzZ.  +uuuUyc >gRRRrwQYJF\ 1Nb U< AA >C  DcnpndG FcnpndG  C\\D    Db_A 3T 'OcO( Db`C.T fcL# 'OcO( 9PJ$9PJ$ 'OcO( #MdX5OߤJ,iii_RRRn2(((K;;;J @@  2333hK(((K;;;J/w M/w M(((K;;;JKl*2;;;u v,>;;;oA   333c;;;l1  #d[   aY  333c;;;e+  @(((] @(((]333c;;;c   g:      _V6ar2  =Vfi]A!  333i(((i\C# 'F]gcQ12Obpc'F]f`J*>|F,CRYYYUA  333i333d_fV5 Fuuu~u Fuuu~u 333i;;;j.*FVU>n>  ATNDJ\bR8+:Tc\C!  ATNDJ]fU2 6RRRv333w/ /* ,]˒e( 333i֜ h/ >333g֝ςd2Miiikd@333g֜;;;g>,333f]]]2$U]]]j֜B 333ilDRuuug*Ruuug* 333i;;;rTl4 n> D]]]iiiww֛c%D]]]iiii@f֩\333IT 333ij% sk8 K/TFFFM 333iuuui2c6c6 333i333ˌ8 n> ;;;\M;;;\]]]f.2uuum ;;;FFFm.;;;P333;;;` 333i֦JdF (((d߯d(((`(((֩]Ju($iiicN 333iQm= m=  333iRRRߨ]n>  333hh 333hM 8fj5  C}]]];;;h  333iFFFc/x߭rcG!1xd/sRRRFFF^*vG*mw:  333i`n> n>  333iv(n>  333iFFF(((h 333i_!D``H*+Lc_D M;;;;;;l$ 333i;;;V߯j6|(((]3* 8|333]d6|FFFVGz!#]]]^h( 333i;;;[dn> n>  333iiii`n>  333i;;;Xyi֞;;;g  333i;;;Xyc$]]]\ˢuuu3338  333i]]]g/w֤teF!2yd/s;;;RRRRRRRRR{Y <oQ֟V 333i;;;n9gdn> n>  333i333z:n>  333i;;;m8cnR};;;h! 333i;;;m8cd2~ ഴ֡(((T 333iOfF#;;;dc(((a333iii֢333R :~n1 ߰;;;t3  333i;;;i3bcn> n>  333i333֥z3 n>  333i;;;i3bmN~;;;h! 333i;;;i3bc,uˈ*333c(((m+=tRMY@yFFFM6zg/333z֧;;;nH333a;;;b/[[g9 o> 333c;;;b g9 333a;;;b/[cFy;;;b333a;;;b/[[V߬]]]S!(((K333i8F]]]jˌ: !\> G]]]kގi:'fKV|8  J333J#A@ Kf( }> (((K;;;QDs'Kf( J333J#AF1\(((K J333J#A@ <SWWWWWS<#HdigdijhR, 'OipppngQ,1Tglk]<@_iijkm`A1TgllhU52VdM#5sT%NcO'C``C#MdX39]]]z9 'OcO**Oik]<#MdX3%NcO'C``C1UdO' %NcO'C``C,,      G߰FFFX Ul,  <SWWWWWS< <֙ߥ@ []Vː[ >֘333i2 >_ hjjj`A? WT/      #DUH<AA*  (Nea I! GY J$$ KceN' !`ߨ uuuO#DRRR>'' gF CLK f% @ߥFFF\          (fߥY                    KT[h\H R [%D[fcT9  AVXV]d]D# 3Qb`YXXN3 ATK>G[Y< #D]f_G' *md>!DTC <QH+=TR: @RG(<QN52H@#'GUD# 9RXK1*FUN58OT>=QK1*HXYYYYXM2dߤ> _nFc (kiii [@(((i֜ϛxc. D˙֜i2Quuum˙6 D(((ˌ9 +c֜ߦFFFX+#g?  F E A΂X$ <ߣJ,V΂Q 9HFr]A(((\FFF@.uuuifs'/U/Q˄%!uuuT֐%nFFFT_n \RRRk !>QN:#G߬]]]iiimA>s n(;;;\ k+JߦT;;;\M PG 9N333^;;;^1a~6 C(((zix;;;X A֟W+c333FFFW#3xuRRRze(,w]]]Y$x~%_n+333sw( `ː|s_[in1 ;;;[]]]f. dM 333hO#;;;cb 333h> (((aRRRF 5ˌ߯˕֔: 333h;;;g6o= /;;;s߬U/;;;uuuuuuuNOuuup>!pg!uuuT˓M@k_n(((e>KO 333hM1~d 333i]]]g2yd 333i߭uuuY 333Wˢ(((9 bX3 333i;;;j:t> ]֩;;;w1b;;;u. gVGx= ,[m#.]]]e__ncFFFg.R֣L 333i_8|333_m 333i;;;V߯j8|333\d 333iQ=$ J֛ːG A8 333i;;;wQ> 3FFFw] :uuuvbAD#tmF;;; =KQ_nTK 3˃ocfwߦ _+ 333i;;;Xyc/se 333iFFFd1yd 333iFFF> >ˡ [:~ y I* 333hiiiuuu> bFFFv3muuuv: Vk#Gy> *wFFFV, G֡T_nU֡H!%>TVD$  333i;;;m8cd(((a߯N 333i˟K!(((f֦d 333i;;;m%333I RRR[3FFFJ(((c> 8]]]v_ DnCuuut˔T%|n_΂X$(ja_nd߫i(   333i;;;i3bc@y q* 333il(Jߦd333c;;;c;;;QY#FFF]FFFXX: fFFFu3# q˔k}D *;;;d(((j1j֥z> 5rz2 5n_n g3 333a;;;b/[[G]]]k֝ j1  333i(((j5  Yd(((K333J Cߣ i.=kH.(((jl* 5iiieUD֘`2Kߤ_!2 vkq6 !yn 9l(u}#_n*333qs J333J#A@ 1TgnlbF#  333i333mgO+>]izd 'OcO' AblneO+6YilfH!.U fjd_diX53VbH!>YN(A[N( FciR/!8YjdG >z|@ GdnppppkX5n;;;N_nYFFFl%NcO'C``C  333i;;;s5 'nc      jo  e9 _n Cf333c;;;cY\/uuuj{@ OQ[h[M(((K;;;J AC 1`+ gF CLKh( 'OcO( Db`F@`gN% ,Thb I! GY J$$ KcfQ*  <X]F!    'HH( Dˍ(((5 !DabP( 2Xflh_> #D_cfdT3333J;;;J%ns5  +j֜ c!9RRRhM9 hː]]]lV% 333d;;;c >uuuxT!jˏ= FFFXk*@iiif߬k(  5333w;;;v8,j;;;O! J֝< .o, 5RRRg (((](% (AVV=#KjRRR]]]jK#@(((l֞Лyd. 2{RRR}J 5{(((߬WbFFF(((˙s: =FFFTe]]]^u֖֙QFE>s n(:r˚: ARRRQ1o 趎Y 5qz8 HH dM(u1[(((q2 A tj֗uuu_eN]]]uuuN*FFFLFFFd;;;|;;;};;;eFFFJ(1~d.|~,;;;^߰FFF^ GߥNjjxgJ ˚H #A(((333C# 8|333_m!{((( Q*(((huuuj+ >ˎ֚֗d,RRRZuuu_. *333i;;;h+ /semiii }^7(((\iiiuuuˎ1,iiie¿} U.OWVNVRRR]ߣߣ]]]Z</@UVA/(((a߯No~,Hˣ;;;j%]uuuiiik5*==( 9ˈˈ8 @y q*;;;b8 !`_ 1333i˛RRRߦR SSG]]]k֝ j1 uuuQu+5t]]]K:FFFgߦ_#HH1TgnlbF# ,OdggkniY6GFFFK3ez333lM!#MippppppiM#    ]ˣH  =YijbK+iiiXr3 ArM9\ hj j]=  deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normal12.dfn0000644000175000017500000024201611357170241022524 0ustar keeskeesPf !" # $ %" &, '6(:)@*F+M ,V-[.a/f0k1s2{3456789:;< = > ?@A B C  D EF&G. H9 IDJIKN LXM` Nk Ov PQ R ST U V WX Y Z [\]^(_( `(a(b(c&(d-(e5(f=(gB(hI(iQ(jV(k[(lc(mh( ns(o{( p(q(r(s(t(u(v(w( x(y(z({(|(}(~( (<  <<< #< .< / - ? B 7(2C( FK( /,<' / 8#,/ !RRR7!,$JJ%/1CXFCXH!,8TYC2 'KYXU> .OQ31OM+ CDCZRRRWiii[]]]Z W52/A333F!C=(((<2˄]]]> [֞PFFFVr>[8I֚ϴ|9 C(g%,uuu\$333< 333A*DC'gk(15333R;;;e9uuug#;;;`=52liiiO_58ˎߦA@֙}5  6 T cߦY=ߥ5X;;;[ %ЛRqtk i Q9:οiiiˏ1+֛߰f%|U_e333g[*/?>_X W֤߬(((YFKF/֕iiiHhNM˙r[$ aFFFM FFF>|,]]]Y˛i!o˚iii^2fˋW>JHJ>Wˋ f3 *! c ;;;F f ` X;;;\ uuuWݛ{:$f˔.q3333@ާRRR\ 8rg@3ߦDOˑ/(+]]uuufH%|}+HN]]]:HJ]]]|Y#KRRRY QKQ(((F:333w#!Te o%6x$#21:j֜WiiiNuuuRW֜h<{#=߬;;;RRR]1˒}*X;;;\ !59-/3i5!a]]]f +;;;b' '2Us$,N.. , N333333 O/ =￧v*@QMCHN FFFvW333cU5NMÛwR _GU:kuuux+333(uuuR@333C333CM}Z$uuuQX$Yx M$tRRRaVt豿%\֣VW;;;YqRRR߫vJb%K߮M!9 ˇ/333W;;;bRRRf]RRRDRRRElw88X(((^ JQHHHNND/T]]]l~5Gr Tiiip;;;j|z333T! FFFJADDˈ`GK]ˈJG 333_Hpqx+#t333iiipG J]]]k֡FFF}]]]dMuuuD333iˢuuu_!]]]c= 333[((([ 333^;;;W2v2 + M N- uuuRuuuR (((]XDQMDHN%o]]]h(((`Y2.8`uuu;;;X%}]]]]]]*JK*+ KRRR;;;`,/ Bߧ(((b. ]e ,(((aߧB L kk(((fYwiδz!KG1RRRR82+RRR7 WW XH6]]]iii.333[ ] 333^333X  OP$3cc%%p>+}˓.HNl˙\6Q(((333TDX z֤ | !,8;;;Z !|9333luuur!<< C($3 +Xuuuoo (((6emlme(((7 euuuoX+ 8vJu w2(((| (((333X333i˛qq333jAFFFI 9}G*yH5֟A(((X;;;^ ]]]i],v+[A'KK'RRRI8Fނg(((Y֤߭333[GM\ˡuuuU;;;BJ+}Tgߥ JRRRZ֢y$8X(((((Ih]]]N:[G#QRRRQFFF8  ;;;4RRRPQ#:֘e ;;;`ߪFFFːG 5ߨk i8 >uuuQRRR@: AC J]]]d  4333[=uuu`uuu_!(((]RRR}uuuJ Quuuq$3˒H  jWb=@K(kk*38֓* ERRRce<iiiRuuug%1vG <}+ JK ]]]J333fc=hFFFV  9*L333˙]]]vW:u('p<2#$,@FFFst .!HH!DVD'.<!,R`uuum!]]]RC'3-%JJ%351OYYU:DXG$/ HXH! (KQ66+ 5QR83'3 NH=8#uuub˘ a6( '5#FFF7 Y]]]ZmO!2 -(FFFa]]]a/(((I֎%ߝOJ(((^uuubiiiciii_(((]K DYT9DXXJ* DYYT=DYYM+ DYYFDXXJ* 1%3111=@15$6( 3 +# $JYXDDYV@$JXVDDYQ38TO. =VXVXYC/$/3%.3$ +86( 3< ,8>: ,8 (KYYXVJ'CYC/CYC(((DY 3]]]i|+(((Diiif9 (((Do(((D;;;9 3]]]h|+(((D(((EcA(((D(((E(((D(((E(((D(((Ec.(((D(((E(((Dk'eo(((Diiif$5ァk>p]]]i3 (((D333`>p]]]i3 (((DߦQHˌ,,3333ECe<% (((Xߪc' :: 333[333r*,fߪ ] 333[(((2 333[;;;^ [ߪ_2[333;;;^ 333[333h 1~Y 333[;;;\ 333[;;;\ 333[(((]]]vk 333[333u+ 333[;;;\N޴( 333[Y Dߨ|';;;^֠]$(kS 333[d ;;;\֠]$'iS 333[333ut`;;;0@H;;;YX;;;\ ;;;W;;;{/ gG1˕TAߩ6 c;;;j'uuul˕dX;;;[ /iii|: X;;;\ FFF_O 333[Y333[֤uuu|m2ːuuuxuuurߩ9333[֤uuuu/333[֤uuurh]]]M333[;;;[ 1ˏ]]]tRRRp߬FFFS 333[;;;[ #{Y333[;;;[ 333[;;;\ 333[;;;^2]]]ih333[߮vnuuuW 333[;;;Z M޴(333[Y[(9ߦiiiwy, 333[Y6֛iiiwxx*333[;;;[#(((m֜1~RRR֡KX;;;[ HzRRRvr% i*iiin333jAR333iT(;;;j8X;;;\ 333iuuuuuukuuuic;;;<X;;;\ ]X 333[Y(((D< =sˎ.(((D]]]f5 (((D+(((D333F :uuulߦ 8(((D333FcA(((D333F 333^;;;Y (((D333F (]]]g'(((D/(((D(((E8ʹu(((DChxAs]]]i3 333EC@suuux (((D333F .}9;;;Rn'A333Fas8CP MGiiiSs+/c*i=A;;;G*yX;;;[ @@333[YDYYM+ %JXXO. DYYU>DYYV=1!HXXQ31%31 RRRvY1D=DYYX@1.' .6+ %JXVD/%Uiiis /1 +6FXK'/9RXK'+, A@$3/=VYYYYN, X333=(<(((Y>G NFFFc|;;;RL,+N3ߡ Z,~'%t+ + *   3' /*+# (6///';;;IFFFB,FFF@;;;H' ,C=,Gw( 5;;;X333B=5ァk*u9333EA*;;;8 -3338333EA333EAuuu['AC%uuu\%,FFFiV*j, ;;;XUM޴(P֜1 333[YR/b/ 333[Y 333[Y*$}pXYi޿'*讴'@iiik%1%JR9 ;;;YS< ,NS8 +L( /NN, FFFu$8TYC 333[S: D(((\1 F _/ 333[\9( 333[YFYPDCODFYS:!HV>%JYJ%%JYK'@OK6DWCb |A//6( /3% 293@=A@6+ /@XYYC(z6XY2},+nfkJ%i= 333[J813}~'9ˍ/:3 G@ 333[@333FD333FC 333[|FFFcg 333[Y333Eߩ T333E@*uuufdcm1/mi333E+333R</.333EAC;;;G9u<333XC:kAiiiaOH#/nv+9|>333[C/15~+XY(z8 :mx;;;b_U;;;3333E@!ߢU Y333E3;;;R 333[ruuu_˙uuuuߡ.]]]\˗333(iii^ Y .w%nG 333[iii;;;U 333[Y 333[Y 333[;;;M 333[Y 333[FFF! 333[iii;;;URRRW赂H#{߫uuuciii`uuu' 333[ﴴˈ(}iii6.֝]]]P 333[YY;;;\ 2֜ߩJ5ߧuuuxRRRi;;;gi2֜JiiiOiii]]]nt| XYsxrˇ 333[iii;;;UFFF<333A$iiiB &\ 333\ 333Yqgߨ6 vx'##rb޴(!zd(((jivô, 333[qm;;;\ 333[Y 333[Y 333[ 333[Y 333[qp333zb貴~+ 333[qm;;;\ $6;;;W%|tq93ߨxk޴( 333[ 6# uuu\*(((nm 333[YY;;;\  ft%(((j߯R.uuuyFFFy$fq$ >, yXYx/uuuDUis J 333[qm;;;\  $i֤333d 333Xgc6!zu #n`޴(!z333333f333e= 333[YFFFb]]]R 333[YY;;;\ 333[Y 333[Y 333[ 333[Y 333[YX;;;[9z+ 333[YY;;;\ (ˑu(333X%|b\<6d\޴( 333[YAFFF| I;;;Xn 333\hk;;;\ >^FFFFt%/x]]]t'5֞X<333lnXYi;;;m  92 333[YY;;;\ :֦z'333YRRRhc˘FFFsk(RRRY333(uuu_333ߣ;;;;333[Y nJ 333[YY;;;\ 333[Y 333[Y 333[j 333[Y 333YXY;;;[3w, 333[YY;;;\ iii_˗FFF I%|;;;}m!j ( 333[YcvFFFRUa%;;;T]]];;;\ FFFl֞2iiipu^;;;h߭333g(((y*FFFmRRR]]]N<*XY%yˏ> 333[YY;;;\ 't3(((D::6/po8?(((DC.t(333EAC;;;G333EA 333^Y333E\l.333EA333C@A333F%nx!333EAC;;;G3v;;;c%|ˎ=<ˎ(333ECuuuQA83@;;;GJ WM R,aߢ3/jk/+}_ ,1*z6XY2}.333EAC;;;GCYYYYYC (KYYCDXN, ,MXC'KYK( ,NXD.N K///!]]]tV/@A/,/ // (MXF%|N/ /N*/!HT:5QC:TYF.,$@==@\˒1@XYYC#}pXYk޿'////DЎ~D<@!|KK%na]]]W*SS(iiiYFFFH;;;^;;;\;;;\;;;\;;;\;;;G Sˎ֙(((S,|333ORRRG֒/,˅]]]H!˅u,'RRRMiiiL88]]]HRRRM( +:.   #  ! 3%'H=3QC3QYO/ OY,r/6ߤBYߥˏX,_M;;;c›l$ QRRRB[((( 333Y  >@AA+kR<v!(((\333M8(((ˏ/Luuu]d u Vig*uuufdAFFFkoT֝Χo OG֢ߪ9 1]]]Viiiiii]]]W2 RRRW赂H;;;B<2ߧU Yq$:8kY333TQcm$6;;;WZuuun#9˜ uY {G333IR{XGߩ= (M N+ (ˑu(333XU˟i$ kFFF֢(H]]]˕}lyCE333S[gˌ֗Okkiii_˗FFF I Xiiipu+Jo iii_RRRuuuiiiiii;;;[ %' 2iiiYuuuuuuiiiY2 3v;;;c333B6th/hϿiii^%dd (MXFCTVXC(uuuZX%OiiiV_]]]VN! (KYYYK( FFFB߬D5ˌ;;;U (.deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normallight12.dfn0000644000175000017500000024201611357170241023554 0ustar keeskeesPf !" # $% &* '3(8)>*D+L ,V-Z.`/d0i1q2y3456789:;< = > ?@ A BC D EF%G, H7 IBJFKJLRMZ Ne Op P|Q R ST U V WX Y Z [\]^( _ (`(a(b(c'(d.(e6(f>(gC(hJ(iR(jV(kZ(la(me( np(ox( p(q(r(s(t(u(v(w( x(y(z({(|(}(~( (( <  << < '<      18  ## 33  ,=( (=1 $31  153.55!<21+CD.  333+]]]6'\333Wx,%T("uuu;Rj}]* Kߢ;;;QH֍ 5RRRQ_ F 1w, N%%OGuuuO@0 %P%Q OFFF2RRR6 :ˈݴxG$zߢP CJ,}֕֒]+]]]Guuu>]֖֒֓ˍa(((O(((O6eRuuuN]]]U(Pˇ֔O$RRRM]]]M[˄*AiiiN (((EQiiiJw#333Eb<ݛs333uOYFFFM*˔FFFFMNMFFFYFFFXKH趴2D;;;'JH HmiiikI $|ˆ'tˇ o8 %v azGc(K;;;lFFF>333+'uuu_ ;333+FFF?FFFB333qzCiiimiiilB'n(((ptD'QRRRE   !RRRHR%tFFFxG/kiiidvo]]]duuu_#KM;;;Fˆ15֔uuuvHT{֞֜o/!siiiu q * Mu֛ ロm.< T NJ%i>=谎h%uuuW˔4+˃FFF< VH!gA>yn%*x. #% vRu T A.St 333Y _ jd 333M_[ߥRRRM C333s.[FFFM   5Wk.]]]:RRRARRR?RRR?RRRA]]]91fU2 rVRRR[FFFiߡp;;;lRRRz J ;;;cFFFb ;;;=˅1RRR0AuuuH!-2rߥ]]]~>3谛uD1}֝uuuM'Q%J h fJ (((O2C{ˑFFFscD'hn(@;;;T333SC(w,\T:RRRuO6zߥ(((ˉ1GziiiVCH(((g/ 'mߣ5 T (((T5ߣsjFFFN M^M^ Zߦˊ^CˀpoopˀF`֖֛[ iiic>D z333eˏuuui]]]]p!FFFFu;;;xG ;;;9˂+  ?ߣFFFs5  Wˌ@ O_`` M333Tiii;Miii;M3334V<JGFH<[;;;4F bJ w(r i333E˄/ m(((m FFF,uuu@RRRr;;;uuuy;;;d=RRRxˌ.+x5%i;;;u,RTQP9FFF7/+CyˑRRRrdD333%NM !VNM;;;T 333RK(w,`W6 yN,ߡ*(((U333R((( vq$]]]a>333\ ;;;ZFm(((N!FFF^lY6 WWVUQU9Zr;;;^!333BF=ˉ Qau;;;P˅(6ߦ9  ! 6˖ߠ%%;;;H~OUFFFFG333v>{tQRQP+xFFF=  RRR.mw;;;' uuuY~./ˉiii^$$iii^ˉ/(w,Vޛp*RRRRQ =RY;;;oU[FFFT ;;;HH((((q9K333coߦKA~fh$  @\֖) VQOOPN+ˋ[<:֒5D(((U*iiilRRRO \ PP ^;;;0]]]83kj֜333j2$RRRfRRRu˓FFFD=ߣr zD@݂vjk$UXXVTFFF, FFF0]]]7##FFF/]]]6@(((Q(((M{{333N'v+@֞\8 C\ I FFF<˄/ ;;;,L`333yJB |rˏ(333cK;;;TFFFSVߥ@FFF/]]]6FFF0]]]72Y]" "VX/:}:F;;;;;;uFFFk\2֗z,*sߣ3]r$ߛ3334F=333N(((V uuuIN(RRRT1;;;Uk}3Jf hJe˄%]r>C+jk+[bV!(((/e(333,s#MFFFV%`K ']]]S3ˌ֗6!֗K]re˄%  66'kiiiΛ}˄9N L:  +N]]]jߤc /GR6FWJ$.$f@@ホi%Mb  +'KJ' %JYYT8DWJ% $JWF$JV@( .OO1/+  Mb,@((( ֝K ,,#KRRRZRRRZM    :FFFZ݂_G P%% P>QOA!## %3' (@=' '361 %36/'36* (@='             (DC% '3/ (A@$ '3,99(53135(         15533(*1(1 .ˈ֖ˇ(((LPエvG 3ˉ֕֓ߠ_M.ˈ֕֓ߞiii8  3ˉ֕֓ߜ Pエv H ,Z'(a( ,Z'&Y',Z'O˄+ ,Z' 0zG%iiiL]]]@ /pC FFF2RRR6OxݧrO 3ˉ֖֓]DRͧrO 3ˉ֖֓iiiW<%]]]ViiiO֎֖֓֕֓֎ ]]]3&Y',w2+k+,v1 0iiiC ]]]:t;;;GSߞ*$֏OSߞ(]֑֓֓֔ˏ֗ 24֕ߠuuu>.֏2֎֔g#K333vp(((QFFFWˌ(((X;;;R+;;;P333n333AFFFS333XK333n;;;A;;;9;;;P333o;;;A;;;4FFFWˌ(((X;;;Qx-;;;MKJJ;;;MKJJ;;;L[X1;;;MK333O֝@333c%333N˓=$|ˆ';;;W֗(((]333^ Z;;;P333pFFFS:FFFX֗((([333[(((Y;;;P333qRRRWߣ3FFFMRRRjRRR](;;;3;;;BRRRj333m;;;?3330 FFF9֐+JJ<;;;Y TA>(((V'uMKGRRRK ]cˋ'!x] \$ ';;;;;;;A;;;A(((i> ;;;F;;;^ ":(((LFFF4;;;_9R_[ˋ NFFFk8.5 ;;;Y] GuuupHRY  ;;;Y] LFFFk8.6 333\YUU 333\YUU 333X[ 333\Y 333YkF d֠. 333Yk,*x.J]]]k<FqJ ;;;Y_UJ]]]k<FqH ;;;Y_'QqQ( \Y  ;;;?ˆ2UU]]]a>,x+%hߣ5N333`(((`J*uuudomN JK  #n f ;;;B~= uuuZ. Fߠ<SuuubaG 333[XTFFFM SUH$ 333[X@]J 333[TTUR 333[YST333W֦\ 333[Y ;;;W]]]s(((lˇ/ ;;;WRRR\!+w,uuu_QXFFFM 333[Y;;;zHuuu_QXFFFN 333[gvCh|@RR ;;;=˅1RRR \R Y YV;;;^]]]:5ߣh%6߬Y[Yciii`$ ;;;<˅/VN:ߟ:X s$o1 333[Y6vFFFDXJ 333[* i֗6!C @ 333[Q 333[YST((([ 333[Y 333Yr;;;[ߥM;;;B˅1 333Yq((([((([Aw,$@9wFFFG 333[iiiZ %@9wFFFG 333[ v=(((VST ;;;<˅/TR+xNiiia<8谂fbiiibr]\Yx# ~\5 ;;;=˅1HW :ߟ:V_iiisCu8 333[Y>ߢFFFG VTG$ 333[X@lˍ<H@ 333[SSVR 333[YST 333Y￿G 333[Y 333[\$]]]E<;;;=˅1 333[[#]]]^y,iˏAAFFFH 333YRG qːACFFFG 333[ ~333i ,\yHST ;;;B9 WM Y;;;_333_T8֖uiiiv8(uuujK YYDߦO ;;;=˅1'hn(:ߟ:RRfV Tr 333\Y pIRR 333\Y Sp!S 333\YUT 333\YST ;;;Y֛N 333\Y 333\Y  ;;;=˅1 333\Y/p֣+ QplH 333YX Sp! kH 333\[ FFFbV iFFFSST333Oi.i֗2<߮MKː/](((` FFF\o{<XY.q` ;;;=˅1 VH:ߟ:S]333yF3֘(((m\\ b֐$ ;;;ZY`RRRgz,SYK( ;;;XV/(((l\[ K ;;;XVRR ;;;XVST ;;;Wkc1 ;;;ZYR5 ;;;XV ;;;<˅/ ;;;XV=x%/333i]`FFFhg' ;;;WU/333l]`RRRgf% ;;;XV<ˍ.uuu@iiiTf MRRG֜n`FFFl(((M333hp##qhFN((([;;;[di%XYFFFj pYYJ$ ;;;=˅1NM:ߟ:@RRRW>gs!(((ERRR^2 @a(((A= 6iii`ˋ/(((A=<<(((A=YU(((A=]3(((E(((A=;;;.s#(((A= K诛c 6iii`RRR\,(((A= :fFFF{G(((A=W9 ;;;>j(:<ZFFFX GOH>uuuVd'.iii[%]3AA/J ;;;<˅/,v,:ߟ:CYYG$JWXM+ DYYYGCYYK( ( HXXO. ('(333jH($DYYR5( ('  HXXG($M {iiiqv(,FYK''8RWF,'2 .,CXVXYYJ$ ;;;B~>   Hߠ<1a$H;;;Y֓\ ;;;EFFFZ((("RRR8RRR]93334(%1ˈ֓iii8 ֎ˇ_!','.     #      $iiiRRRRM !vK RRR/]]]2Q( RRR/iii1iii1 (((iii7,_uuuC&Y' uuuB_.CSR> =o ,(((Y[$ˈ8 FFF7֏( FFF8֐+Ad FFF8֏*(((M333M RRR(RRR) FFF9֐,$J$;;;C(((I JJHFFFE -. n9Y r333oY Cy+CU: ;;;B|uO5$JO1!Hb333nˈ/ (KJ%} .OYC ;;;EyJ( '(FFF)RRR,/ ;;;?ˆ23OF(/M@AXK(  HU:DYK( $JYJ%*C=DO1vz#  '$,''$3MRO5 333F<UU8wFFFG/{RRR f! i֛''iiiV%+a$ 19 333RC *a֐(uuu^|+2re(*6ˊ9 333Sq*333+]333+]FFF'RRR-1333X. ;;;=˅13337֘FFFpK (((Bq*%iii[W(((Bs6+b^3334/H֑,uuuD 333(TS333(9A5ߞ38<C֒1RRR5+FFFT$+uuuX#3G >9 iiiOˆ,ST*{iiiOE333OR<25(((Am*%iii[U+!+333PFFFL 333Tpߤ+FFFMsU 2FFFM rqz,]]]X(((S  zt[˕ˑ< 333S I FFF<˄. FFF<˄. FFF3;;;XRRRm(((V ;;;=˅1 333G 333yߦˎ}# 333P I;;;J qm@ ;;;Ltd#RRRO rqy* 333LFFFq333B ˈ}RRR>$ ;;;9˃,*xFFF: :RRR\+WC<333WAWKD(((V(((rRRRj R,ˊxF;;;^>3e b9l STlˋ:(((/uuuh;;;4 333O G;;;J od@*(((Oˏ;;;Q ;;;Eˉ<fK'ˆ]]]X%(ˇiii](333Eˆ/ oVST {]]]hkRRRl֕, ;;;B<<ˉRRRD ;;;>˅1 ;;;>˅1 ;;;Kw ;;;=˅1 FFF5]]]G'Vl#333Kˇ/ ;;;B:<ˉRRRD %|iiiY' kW ;;;A}6!;;;lG+ˇ]]]Z%333Eˆ/ ;;;F֖FZuuujNOP ;;;?|3,yFFF=333_yˋe%FFFYiiii|G 333lo W333` Xi' RRRT] ST ^FFFV @U[uuuZ֔]]]P$ ;;;B:<ˉRRRD %|iiiY' kWuuu\FFFy֛FFFQ ;;;>ˆ2 kJ(|RRRW!*ˇiii]';;;B˅/$]]]ykNN+ST(((WiiiP ;;;<˅/.zFFF? ;;;=˅1 ;;;=˅1 ;;;H333m* ;;;=˅1FFF)RRR-NN ;;;=˅1 ;;;<˅/.zFFF?(ˇRRRZ$fY ;;;=˅1;;;hJ1ߡ;;;W;;;A˅/ ;;;>ˆ2+333Y=OO ;;;H@9FFFD J;;;SKߪuuu_!(((n r*x@6ˎF ]]]T _ ST _uuuZ% ;;;<˅/.zFFF?(ˇRRRZ$fY2RRRo' ;;;E֙uާs(uuuW|U9]]]S yjl+iiiT{bRRRI(((#RR]x9 ;;;<˄/+yFFF< ;;;<˅/ ;;;=˅1 FFF0;;;Mpe% ;;;<˅/FFF(RRR,ML FFF=˅/ ;;;<˄/+yFFF< ]]]RzgvD ;;;F֙vΛm'avduuuj, ;;;<˄/ )dMM<;;;J ;;;T RRRfː1%q;;;`]R[333siiinY n333pRRRmb5ˌ> 9ˌ$2rk5z4:<pߢ]]]O;;;,h h;;;,;;;.s# ;;;=˅1 FFF RRR##`3;;;.s# FFF!RRR$ 87333,s#;;;,h h;;;,2r[ 333M֗=>ߣ|+;;;,h Rˋ.3$<333FKWPH'_,.iiiZ+5o$333dG1uuuRˇ,ST({uuuR;;;,h h;;;,2r[usrrsu GVXCDXN/ /NT: (MWM( +MXD'D~_FFFmG  ;;;P˅* ,  $   (MXD ;;;FˎO13N_;;;jˈ/ %JN/ 6N::SYF-, 2  $.H;;;bCXVQ5;;;H:ST8wFFFH  (MXDQVUUVQDiiis \333rF5iiiR FFF:֐, FFF9˃+ ;;;PJ;;;H Q JJ OFFFH Lߡ;;;K,֏8(((#uuu>(((#CK;;;?3ˆY*u+Rˆ51C3    !    %2 (8! /MR UHCt333.1x݂]$RˌRRR[+ 3֙;;;Y;;;L2J a$D;;;' Sp 333V|6#e]]]\EDST`kiC+˃FFF< Oˑuuuv<(((bz> Dxiii^y _֎]ˊRRRG G5C{ˑFFFscD% 52֗ˎ9Ou˅RRR[(!@UߠFFFE333TO(((.(((.!uuul(((pFiiiVAuiii_v jjˊRRRG G˕ߨ=CyˑRRRrdD$uuu_z5.ˍFFFqˇ%!dqE G;;;U_h֗֗M+xFFF=@uuu}mYM* R賎aJ a$((DtuFFFlcD>kXbRˌRRR[+(((.(((.CYYYK+ =Y /K P RHDXVXYD;;;8 G1iiiV! *8deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/console11.dfn0000644000175000017500000021201611357170241022672 0ustar keeskeesDf  ! " # $$ %- &6 '? (H )Q *Z +c ,l -u .~ / 0 1 2 3 4 5 6 7 8 9 : ; < =  > ? @$ A- B6 C? DH EQ FZ Gc Hl Iu J~ K L M N O P Q R S T U V W X" Y " Z" [" \$" ]-" ^6" _?" `H" aQ" bZ" cc" dl" eu" f~" g" h" i" j" k" l" m" n" o" p" q" r" s" t3 u 3 v3 w3 x$3 y-3 z63 {?3 |H3 }Q3 ~Z3 c3 l3 u3 ~3 3 3 3   ,+,+ !YxX'JC% +LG ,. $(#.FU=6<=TO1=TO15<'KYC=TECYYU:!GVA#HP6333C@(((=(((t@(nV;;;I(FFFZ(((.'ke\ +x]]]M333E@](((7xߡ<5seK333BFFFYQ JC(֘5(֗3<Af, UFFF4++ iii]O #uuu_D 333YX333O333Vm z<@ˣ{K333ߩ]]] [K ]]]xˈ';;;WXF޿1 T]]]b 333:33RRRdMJ|*zY(((<]333333R ;\((( QFFFdY'|ߨ B.ˏ DB Yt!H|tGiiivg 2/ 333[YE AH :AާRHFFFߧ6J]]]ߧv1 HDRRR[b FFFhJ ˞N kfCuuug#(((WUiiiyH ,Y`FFFX 1333UTY(|q(O333`. i^J]]]ߩ XrF֚5 iiiH8FFF>8 333XT .2+1yFFF]]]s!uuu^(((y  iiiZ9D;;;Oj-.8_ Y߫3339dvP=G5aV ;;;Viii]]]TXY qP|\%mYul,XˎL8֙29}uGzG 3338x, 3w, FFFC= `FFFq333W 3O$2d(f6A|(((B 'G :pcD S}' P(((d<֙9  iiiWKe63FFFTFFFYQ kk6FFF4-r.GF(ˌ3X333WFFFCJ*r W+f*T2iiiWK (5,++< jˊQ,$HDDWJ:D<!iii]2iiiK\]]]OC (5/FU= +MYM+ CYYFCWK( ,=UN/ @VF/ (KWD@VJ%%3]]]OC *]]]>  FFF,811 :US:CUC$3CYV=FWR5CYJ$8TYF8TYM+ FWR5,  +MYC,,1*2.3/*!GWC8TV=!GWDCYV=GWD +MYYYF,  .#/,# *%> WW!h MA M 333\!Af16FFF46k;;;\!ACdx!l,333C@AC ]FFF:<;;;B(((DRRR\J֙=AFFF_!;;;B=!iii^]6[!iii^]A QFFFX(((/k3330ACdx!.ݎc$D;;;B>;;;C1֓UcߡFFF9 '%% *uuueJ9V(((SFFFFwyFFF}CFuuuk XϿ!HpS3338Xuuurg#Oiii}e DO]]]~d M+ HqS3338XY(w, 8iii{ 333YXXq fv/R;;;W 333[TXM333YVL}ߦ3O]]]~ =L}ߦ3X֙/Aq C *X]]]DXY(w,#mH aYJ;;;[R;;;[:RRRb @!vjgg^iiiW^#~QRRRQr;;;M ]ˠDXx!333Wk X`<GQ333T:R333w=(333Wn Xq+ 333_Y 333[YX֜C T;;;X 333YQX n(((jY ;;;Xi$333rQR333jR]]]M ;;;Xi$333rQXuV:D|R 333^YXY*w, a _1x@5wKFFF:v333V*ߤ]]]yO #Y_]]uuuJ!biiiSYߥ5$˅iii}RRRA !q_X(((qFFFZUXY(((hWM(((.O贿֐%FFFZ](G8X* 333[Y 333[YX|T;;;X ;;;V޿OX(((XFFF\U333[YN޴uuunˍ.FFF\U333[YX}uuub uuu^(((Y  333[YXY*w,Huuufkiiif#sv~ \*֘FFF|K #uuuQiii[iiiYiiiXiiiH!_uuuV1ˏK'h 333=CuuujX333;;;uߦ5]]][UXY dYNާFFF^]]]G O˕f\ !]]][gc6XFFF y賴}* 333[Y 333[YX]]]j T;;;X 333WˈFFFTX T]]]\U((([YMߤa< ]]]\U(((\YX߭J#[ˑFFFQ 333[YXY*w+$l]FFFSU6;;;` 6!ˁrppiiiiN[#/{M#v˘˙= _]]]~;;;g֞AXc3 M 333Yj  X^/qJR333h R333l+ 333YuCuuuyQX`5z+ 333_Y333gTXw gT;;;\ 333[f$333fXX֜O ;;;Zd(((nQQ333w< ;;;Zd 333nRXg_֞ˌ% 333\YWh<|y* ]ˠ@333T333OUb333+$+(( ˁ333U=1a333C]ߩFFFY kVkZX s=HmWiiiCX]]]nf$Oiii}e K( R;;;V H|]]]MXY(w, 6iii{ Bv˓:X`JMOiii}e M, ;;;YX ;;;YXXghMKwߥ3R;;;V Kw5XaXߦ8333<Ys ;;;ZXH}޴yFiiii]A  3oHuuu~333i 0+͛i'DFFFDAZ333[ߟ#Ae16a<;;;B333\,ACdx!l,(((/;;;UACbY6v(((C@(((C@AC88 ]]][W<;;;B ]]][(AC a333<'H 333E@!uuu`R #kKA333TCߢx'6+ R*,#/CYU:FWQ3CYJ$8TYK( *FWN, ,  +MYCDXF,5%8TYN, ++,13 GV@*M;;;w0,1:US8,#HWC%5/'# 8Q= 333I;;;G'5/'5.CYYU:FC/ +H:Q֔=333>?,  CL, ,//,=Q8aT\ :aM Z :++333E,3RRRVl9Duuud#/6AAdw! GvAA.FFF7.FFF7AC'6Vwx֚3Yiiilbߥ5Bbq 333Y$jC 5RRRyR]]]d333[`4$JXDXTD:TJ%!Hu~+DR8Ky֤OGVR=XQD%c;;;d8%c;;;d8XY3+ GRRR}QANGK86FODFT::MRD!HYJ%>RH( FXD;;;d]%p;;; c+zR 333XVYa 333]XK;;;eTߤ֘1#OO X\]R#uuu_* ZF$J]]]Y+X֣ NR ER EXrd˄ 333]X(((B֠8@֟ NFFFYU@^#uuu_c(((BbFFFX.C֠RRRo#V, a333g 333YX2֘ˌ/ 333[Y iiiC:V9]]]9333X´| X˖ߩ>CߨqI (Kuuux*Gߛv% _ߪ߫l$G]]]~ (((uXߨ#'FFFW 'FFFW X(((K 333[Y 333PiiiSVߨ#Iw5V˖ߩ=Kuuux' 333Y˘333] . :PA˘RRRr##iiiuk :: 333[YcX 333[Y$,G;;;Us(Xq$;;;lVYu333Xf:w+W3.z2O]]]333JXxAˌ,X;;;Z X;;;Z Xr 333YX ;;;B YXxAˌ,333Wg!;;;nRXq$;;;lV333Wf:w+ ;;;[t/֘ˎ(((S#;;;d` 333^V333li 333[YFuuuh# 333\Y5uuu|д(Xn!;;;iUYq ;;;X`8}+W;;; W SA(w,G֡RRRc*XY+x,T;;;X T;;;X X֩;;;g 333XV ;;;:z {YXY+x,333Xb;;;jRXn!;;;jV333X`8}+ 333\Y8333XːRRRQUw{ߦ6 ;;;YVF߮ M, 333YXRRRfM ;;;ZYFiii,X֞<D˕rN +  NFFF| (GrP+ (v+O߰uuum333KXY(w,T;;;W T;;;Y Xp a 333Y ;;;:z {YXY(w, K]]]v6X֞> NFFF| ( 333XV=iЧp`Q^(((;333E@Av 333YuK333B((((Y,ߢ'A Y _k*ro(((\adm YDACdx!>333CUFFFW AJ<.333E,;;;-s ]CACdx!#uuu_YX [+yz(333A=(L %2/,CYYN, ;;;I#.uuuIF5DCCC>* ,LVN2CYWDDWL+ (KXM( FWK(  URRRF,  ,AZ, ,8FC#++,,  #HWCXYD +Lv+*=VW@%iiiOiiiJ ,]]]Q333I(ˁ=RRRW,CCC x˄$ RRRAFFFOFFFMFFFMFFFMFFFI3333> T WHDVD , !#    3:,': $CJ::(((. +LL+  HWD3KLA!uuuF(3ߣ,333E@]iiiSO(((5Ep+ykiiiY(((/ DߣRRR\!j;;;{K* ,' %/ $%,'CXUF$P u ;;;ZXD֘(#iiiWH,o|M;;;}R+ >uuu~rB.ˋߩ֡(((K* $D@33#(((/@@Rb333@D!iiiU*Je(< ; :aJ~֐333@D!iiiU*.ZYZ 333\YFFFTˋ9@˘ WFFF_U lgD˗n3J(((P]]]]˅'(((LuuujRRRnC kf uQVW'u+R333aXk FFFRj5rV3֚RRR RR333aXk B|R  yQ 333[Y ;;;Qc !HK' Sߨ#Iw5-RRRmA˕ߤF N(((<(((Lˆ/<ݛ;;;iiiSdvPV;;;_XY(w,3֛֙^(((Qς;;;VkFFFk 3֛֙^j]]]e! C֟> 333[Y \ uuuRp n[333*XxAˌ,333Wg!;;;nR8 'Ny C uuugl{#=ݛ;;;iiiS!m~`T;;;\W_8w+(((b˞9XK c333p(((b˞9 Oː9Aߩ@ 333[Y \ ֏(((a333f 4XY+x,333Xb;;;jR' %Dߧ֠# iii[֟J 333O͂lFFFoA nj Fuuux\* QFFF (J;;;dV֟8+wZJ;;;d( W( |Q 333[Y ;;;Qf :R@XY(w, K]]]v6/ː qU#Uߤ(((d%333SοO.#$C=G֝C$el1֗o uuufH=]]]^N֕t!5bYߟ3~Q5aYb 333\YFFFYˌ9ACdx!#uuu_Y5{25;;;Z 3>( ;;;1+%JM+ 1OYK( !2+$! ..,%rv(CYYK( J]]]j ;;;[YG﾿$,  #HWC16DUC B[;;;WFXVXCQO 'k/333FCP333M-D' ID'5/#2E WWCdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/fixed.dfn0000644000175000017500000002301011357170241022157 0ustar keeskees %.7@IR[dmv %.7@IR[dmv! !!!%!.!7!@!I!R![!d!m!v!!!!!!!!!!!!!!!1 111%1.171@1I1R1[1d1m1v111111111111111A AAA%A.A7A@AIARA[AdAmAvAAAAAAAAAAAAAAAQ QQQ%Q.Q7Q@QIQRQ[QdQmQvQQQQQQQQQQQQQQQa aaa%a.a7a@aIaRa[adamavaaaaaaaaaaaaaaaq qqq%q.q7q@qIqRq[qdqmqvqqqqqqqqqqqqqqq %.7@IR[dmv ~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~?~? ?`66``0x<?636`apf`?0`lf?6080 ?`6  0~0 ?`6 08003?0l0`f??`6300f ?`6``0< ` ` 03``fa caf3cf3`30fac1f3f3; g1`3f3 m1`?ǃf>7m1n3f030gc1f3 f0`3```caf3 cf0`0?>3c<0 `?31<0 ```< 31 00` 1 0<xf  ư0f3c0`f ` ư00 `3c0`l ` Ʊ```0 `3c0`x ` c0`0`3c0`l ` c0`0f3c0`f ` c0`0<1f?0`0`<~?~?a~?~?>c3a~?~?3k3`~?~?3k0~?~?3k ~?~?3ak0~?~?3ax63`~?~?>063`~?~?0`00<?08~?~?0<?`8~?~?0f3`?p~?~?x`?p0~?~?``3?~?~?`3?~?~?``?~?~?``3`?~?~?`x?~?~?00```  333>` 03| &Gr 1l3`)LJ a3`(G3J`03`)@`0r|an?&O0J<3y3`0` f3`0 0>03` <f f <30xf`` <33`f  `03`0f3 ~x<f3c` af3#1f33c` 1f3cqf33` 1f3qf33| f3f3 `?` 1f3ñf3 `3c` 1f3cf3`3c` af3#1f3 `3~x<x< 8880N1a0xf6l   0  ``f#28` <x6x``06f3``0c13``06`3``03c1~7``?`03c1?`3c1`0 `03c1;`3c1f0 `03c13`<~x> deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normalbold12.dfn0000644000175000017500000024201611357170241023365 0ustar keeskeesPf !" # $ %( &4 '@(E)L*S +\ ,f-l.t/y0 1 2 3 4 5 6 7 8 9 :;< = > ? @A B+ C6 DA EM FW G` Hl IyJK L M N O P Q R S T U( V ( W(X'( Y3( Z>( [I(\P(]X(^_( _i(`q(aw( b( c(d( e( f(g( h( i(j(k( l(m(n( o( p< q < r<s<t$<u,< v6< w?< xK< yT< z]< {f<|m<}s<~z< < < < < < < <  DC:OGFN: 08% 3A]]]PK!:SD$ 66RVA (KCEB @A' 6C BGWJ$5N: /NWG8TWG (H=CYYYCCH% (KYYYV='KWO1%KWK( 333PD68,ˎXuuu\ B333\߂l8 H]8fFFF= JboC FFFf/8h2e;;;U* ? @Q:FFFdk*183ːFFFd8FFFd2y9AC;;;eco.+s֛>.oz81<x XFJ: Tvfˣˑ5!~<$|Y(((i333n+V RRRDˎRRR;<@$u֞1 U;;;dFM;;;IG=F#]]]kKYC jFFFWxu# (((Vf]]]do#>1>1!G g˕FFFGDXXXXF yV2˘6'*z߰qtiiiY '֛uuuDjFR/ \,iFFFB99 ^d$|(((:HN;;;9֕UMˣR iKY dTy! ,LYk 8߰A]]]^֚1]]]^֚1Pr G;;;;FFF<RRRbR >iiiRDCiiiR AFFF_߯߯FFFa;;;TRRRV O [!';;;;;;e C 0iiiT333Jjh !]]]vR DFFF 3(((@(((@CXXA.{'=MHN2FFFN,Mc߰OOuuui'!sRRRbi( oFFFn3(((J'@'>(((E nH8}}8`߬A  (((e˟֧(((f(;;;h֚.>{uuud# R0 (O 333a;;;W1iii(333B333B#CC$iX>MHNd+,V3ˣ u<֘333K:FFFA+` RRRnw%333[3X˒uuug'Y˓iiii'333EmD 4jiii{iiiyiiiyiiizuuug 4 k߬C++ (RRRYFnHt;;;333z.֝N RRR[333[(((LuuuTUj MCCQ֙g(AC Qߤuuu_!<]]]p%} :HNVJ "FFFNuuu333V:/RRRD;;;niii;;;Y 3ߩF `.3śAicX]]]f%\˓uuuj+ R{D;;;8FFF9r N֣@;;;?8`֩֩Nd߰(((~#{Y333n W  <@+(((LCYYC*F;;;lF UFFFcFMF<;;;C IA Wy֥x~ JRRR^(} c (֩6 Iuuuj$*D+(((L %M333h֞FFFDDYYYYEFFFRCBuuu^Yˎ,1\ߡiCˎ/>֛ -333^333o2˕G ? @iiinFFFWe=*(((` RRRek*18^9=iiif$!l:(((Liiif$+lA i֚2 JߧYRRRAiiii,e=iiinFFFW3<FC 3#8. ,{RRRo@ 3= . M M/ 1OXTNTYC=Gs]]]jJ$F=<AGWJ$5N:'KYYYU:<UXH 'G:<UXH $JWN, 'A13QWT8AD!$F=J/dl!:˒8aa_.:ݴC 1515361( ES< (MWWR65RR5CYYYU<'KWWU<CYYYR9CYYYYCCYYYYC'KYWVACM+ CT8CM+ :R=CM+ DYCCM+ CU:FM+ CU:8TC'KWWO/ CYYYT9'KWWO/ CYYYU<'KWV@8TYYYYYYC:1333T?U|]88A(((`Kz=AFFFa.ACACNzRRRQAxA5Ax69Aw6i/AxAUFFFdxA_3AFx˔[A_Fx˔[Ab+s;;;P6C;;;E˕(((hJ#~;;;Tj˚RRRFFF333ci gXDF;;;Q Xt(XCXCHX*[KX(HKXRRRiX(X֟_s(X_XY>X XC>X XF 333R<F FtR J333NO 賿H6ߩߩ6XOuuucxf333p;;;>X}(((|UX.X,uuudFFFypxFFFd]]]GXyZNX(HMXu,X(X(XY]]]_uuu{iiiy*X֩Y]]]_uuu{iiiy*X߰Uuuu_uuumuuuL(((DFFFY;;;]]];;;^;;;GH n333F8/uuui(((YeˡhX֥N!zFFF|. 'X+!;;;zkX@XC!z;;;{CRRRRnuuum]]]V#XNX(HNX˞RX(X(XY#;;;}/' FXѿG#;;;}/' FXѿLL]]]wJ UdDm;;;GJ֣V 9֞iiiriiiFFFX 1˕uuuiii֞3XFFF_#{333%X*(((y X<XC!z333{TAXNX(HNXuX.X֩(XY$333|'GX]]]e#{333|'GX=%qˏ+HYD| T hMCΎ333uR˗ { R a c XRRRˎ!fFFFva jˉ3337Xyy;;;`X}.XtUAuuuc333333QXxYNX(HNX֥bX֥x Y(((G Xq(XYiiibRRRw;;;v˓,XyWHuuubRRRw;;;v֝.X [ .j;;;@HY;;;C֞333iO' zRRRR3ߤ֟FFFː1+;;;d;;;b,Xiii`HFFFM X=X333EX(FDX(YKX(MNX}J XFFFH X=3%`(X=nYCY X*D^XV{';;;H1GY<3333RH]]]ciii֢16RO8A5M} >AMA333EAoM}Ђe#AoA5AoMAo/fgA333FAoAoAohAHx˔ZAoHy;;;_Ao'T5 <T3AFCMiii333((( OCX@@XCCYYYYM+ 'JVXT9CYYYXJ* CYYYYFCK( 'JVXUA CK( CT8CK( C<CK( @XK( CYYYYFCK( CK( CK( =VC%HVXO/ CK( (f.CK( CYC9TXR58TCjߩ֞:K]]]a9c gJFFFdˑ賧z[/ 'hx333T$.NC,@D:#  #%DK'CM+ CYCCYCCYCCG1OC8TV=:UU:CYCDYC'KYYYYYK'CYYC?B:UYK( DD!˅~]]]V %G=FCFB%G=>:>:%G=FC(((DiAx6N K96KT]]]a2֚@!`]$/h.g/i`AA,333a2o(((`_hKc9333EC;;;eAc9B2B2c9333EC333['X((uuuq<]]]o˕/+]]]nFM^Ad˝f333j;;;lxNX@;;;nJ/ߤ(C=/]]]j333B1MUD##|Q<>TM, $F[(((Y>TJ* YQ<JJD/#|yKH%Z߬DZ߬D#|T$DA 333[Y>D@NG((GN1>D@OJ$>TO5 333[(X( ^ f a ]]]o lk(qz, 0;;;P333q kX=֟Fb]]]l XYi[ H(G=|J%}JFFFY6iiiaYiii_ߧ28Adߧ.%}J333YW333YW%}uuu֝9 333[Y!z;;;[!zHRRR]H333WDw( ch fˡu$#FFFw|5mt8˔< XY.*H((((@]Z:333PRRRiiiY%}333;;;X+֜Y@1ߨ333Y/ߨC ]]]v!rˣ333l%};;;Y 333[Y 333[Y%}f 333[Y%};;;iiiy %};;;Y1(((FFFY Ruuu{(((}w3֞ߩ6=]]]uX333hp,KN!]]]m((( d N / XY ]eH(C@>@iiid~%};;;;;;Y+֜ [ ?2ߨFFFY.֧֝>Y;;;^ FFF_G%}[333]Y 333[Y 333[Y%}z 333[Y%}Y333]c](%}Y333]Y/֝(((FFFY /ˑU g i;;;lN6֞(lFFF]]]iGKe XY#uuus֞1H(+֩<#| JFFF\:hY]]]]Ĵ:X;;;[ `ߎ2#|T333[Y 333[Y 333[Y#|;;;c 333[Y#|T333[YY'#|T333[Yiii_ J (usrrsuGVVXV@%JXVVG!HWR5 ,NWYYC!HXXK'CF1֩RRR %F:DCFC:U%F:$JT8FC%F:DCCK'%F:DC$JXU>P:3$QVUUVQ2ѴgG:2ߤ֠֠ߣ3*x֞֠ߦiiiN J賂g2+y֙U*66* !26/ %=D8 !%  $$  %'DL- 7- BR98qr{s /333Rˇ$ /NC H WU:%KWV@+ˊ֖.#FFF9# T C C=_;;;CDˋ% D˒Z!iiif@Dn333]$GG@MNQ=$FTRO:<98G82NQ5%FFFj;;;wG#>2><:C% A<8@!39@>6J9#D@5F.A>.FJHKA ~sX*C;;;T3n˙uuu˛U up.֔GFFFH>;;;FFF֣]]]^ (!GGDDuuuW333_2o=uuuWߪ5 Dߧ6]]]e333B\ߥ6(((B<3ާvFRRR`31ނg\ZW@'u3*֚J333]:*֗uuuM /= X(|;;;_FVR8(*uuuY踴߂m$']]]`]$ |1[߰=]]]_FFFL$uuuW;;;cRRRi]]]W;;;!z IfV!z:r֩A.333B#zO333XV,˓֝/+˒(((H333^q% q8,K \;;;dX(Diiiy/Eߩ]]]~FFF>!yHRRR^H^R h߫]<ΎuuukFFFY HFFF;;;D4ˌˌ 5%}FFF;;;Y2ߨ;;;Y%}˛iiiiFFFH`тA333J%}\(((eY f fhu$%RRRxJX(((l>l,˓ YX(/˕uuu_FFFC(((B%};;;Y1(((FFFY u@w6FFFF}g(((f;;;\ FFFF{uuuvC$jm$%}333;;;X1ߨ;;;Y%}r ViiiRRRQ W]]][, !zY3֞˕1<[ 333V $u=1]]]f6bX((iii|53=S VG%}Y333]Y/֝(((FFFY q֩Zp]]]M/֘֞]]]} 333W333Eb[ g(((T={߬}>%}JiiicY#|Mu߰iii[JuuudYf d333m(((.j,f(((lFFFl;;;GxFFFX X(<˗G #|T333[Yiii_ JuuufFFFH O: Tuuu֠˙RRRD  <<(((B333E%};;;e5Yc6iiiVD%muuu\HC2֛ː/AWNU +8d=/;;;GG;;;qX(Q333lc=(((DC.m(((bl;;;H$|(((!RRR\˘g333C;;;E%}WF +Mb;;;Y%F: HXT:%JXH!=UXVXC1F. =A=@@U=#5RC!uuut(((lCYYYYF/O X(333s;;;X%F:DC$JXU> (HTVXD3ߥ߫nTnˌ֗]]]aKFYYYYF!}D ;;;RPA=nˌ U%@L2 ?< @F AP BZ Cd Dn Ex F G H I J K L M N O P Q R, S , T, U, V(, W2, X<, YF, ZP, [Z, \d, ]n, ^x, _, `, a, b, c, d, e, f, g, h, i, j, kB l B mB nB o(B p2B q<B rFB sPB tZB udB vnB wxB xB yB zB {B |B }B ~B B B B B B X  X !5      =?3*% - 1% -Huuur333o2 '(((LFFFWH 0 KFFFX(((Q5 + 6A<(((5%- B333=GFFFY]]][ M%M C . OFFFY;;;YH + NFFFY333XHDD C X X M/ #LFFFY;;;Y GB X X X X FH;;;YFFFY M$9@>w _CDWV333BL˃ d_333^333>FFFS֙1wAj(3339uuub'D(((v= J( XFFFd%m;;;Hn [d XT;;;GC˃#iiid2.FFFE Ri$KQK|(((yY* |;;;tq 1>߫ 333@#O#VOj.y333f;;;9+ 5˃.;;;j333p/˒iii{ K3;;;\ FFF7FFFQiuuu}֝1 0RRRMh]]]ˑ('x;;;\ XFFF(((]333O 3[ z]]]]ID(((X(((X Uy]]]HGN6֘zSFFF<֧߮*!FFFVF˛ j!߫F]]]_N%s s MHG# ;;;RO9JOߪK*333yFFFc G(((;;;\  ]C 1f߰;;;\ Xy!,˓  iߩ6'ˑfS9ߩORuuuGO8Q2iii\|+ˎߨ8 kFFFj9/(((:֑1J֟>333o(((`  A֖#FcFFFN, auuun!W} dRRRM! 333[;;;\ b˔1 ]߫uuul8ߧ ;;;\ XlS C RRRZ(((T6$t(((jiiif踧>+}M!$߿]]]K/q f >n߰[( 333w֥g333aAW%]k0~RRRRRR|V3334xCYYF*|YXRRR]]]( 333[;;;\ %sRRRb;;;4333muuun|;;;[ ARRRcCߥ8OFRRR2$y> . 333iii N,;;;|D!xt( SAYRRRnX% 9\6#]]]ORRRiRRR]]]W 65;;;;U.XFFF;;;' 333[;;;\  o@ 333Y֡ߧ1H333*B[ DDRRRw˗333^FFFl]]]o8}(((~JuuuKx%y. 333TiiiY$pôKq{(((tYtY!  (((ic+x1]]]meVgH~s333[;;;Z `djJ;;;PuuuU8VA]r}=TRH z;;;Y RZ! MB+(((i;;;Y[߰;;;Yux9 |Q1aFFFc;;;EC5= (*! 8=D@H]5iiiv(((b #(((u(((w# K 2 jH:ߪߨ]]]OT߫N'}}2xuuuggy'U˚Q* ~;;;Y 6C31RRRBˍD'v֡uuuQuuu^ߪ(((֠55ߧ\$uuupT//G3C eRRRl%uRRRG)h֥߭d$'uuumiiiR$rl;;;s֠+/::333|%iiiFq333rˑ/ UFFFS/˓^ >RRRI6C/ʹwiFFFSYe5mJeߤ36~uuux}< bw.p֛2.' /%RRRRod5'$JO3 +LWH+,5+xFFFSA],J:> ,72O WFFYYYC8TYYV=6RWN, /'KWP3FWJ%91<T WH+ C֕y ?iQD%$ /       JFFFYRRRZK(N;;;Y;;;XJ8 S333WO, @ C= U X XJ%<333TFFFY(((YH= U XP3 D X X XB D X X X C>333UFFFY(((YH<= / D X X M-  /<=C@ / BB ,?+ ?A /JFFFZ]]]\O$ D X XK'JFFFYFFFYL$ ^e#![(((T Nz5A;;;T9l'U33399ߧ[;;;G.;;;G.V33399=;;;GC;;;3w;;;GC9=k/;;;GCCN1w<QC;;;G duuug$;;;Gr+ duuug$6;;; @ %, '.CRRR`*3338h% 0]]]Od #/ˎj333ziiib b/J FFFtN3ߧki}0J(((G 333\FFF(((\(((Y E 333\FFF(((\(((Y(((D3ߧki}0JN 333[Y d߭(((0 333\YJbg(((i 333\YXuuuon}%Jw%X;;;\ <]]]{V 333\FFFFFFt333M<]]]{V NQ*iiivW(z8(z= 1l%$iiiR]]]c]]]b]]]b]]]ciiiY 7?rR v%R f]]][ qF#sRHiN]]];;;UV֟F  H_={iiic 333[k  333[c V֟F  HY(((jY,X 333[YH333h 333[YX333}%FU];;;\ Y˕:xr 333[b%;;;[ Y˕:xrMtDFFF;;;Y 2>1 > Dː(((m1 3334xXFFFbN֞RRRZ 333W (((XF;;;333fHiii~U;;;VFFFkHNd$ 333[RRR(((^333XD 333[ ZM. ;;;VFFFkHRRRRRRhY%{T 333[YGFFFt! 333[YX(Hiiilx;;;\ ;;;V;;;jX' 333[j;;;W;;;V;;;jX'1֜趧;;;\  ? ?? A֨ (ir@ >@6ߦn,a˔;;; Y a.H˜N ];;;\ HNT޴( 333[. 333[˃ ];;;\ @ W M+ HY%{T 333[YF} 333[YX;;;uuu(Mޛ߬;;;\  ];;;\ Q޴( 333[F ];;;\ Q޴(K֛;;;\ FFFSvO /ˊRRR@ *h8 Ru2%uЎs (((V!tNH l]]]]333X333` HNX( 333[(((ZWB 333[]]];;;_FFFS4333X333`8xHbRRRY%{T 333[YG@ 333[YX(((tFFFW~ (Nާ(((iii;;;\ 333Y;;;^ Q޴( 333[|uuueK333Y;;;^ Q޴(1Oq;;;;;;X`֜(((d6W/uRRRj@333EO!uЂћ@Cu˛(((dHNp#(((Wiiir HM q! 333[\ 333[d (((Wiiir8ERRR(HO 333^Y$zT333cYHߪiiio! 333[YX;;;^d(N޴q;;;\ 333W]]]o\$ 333[y$333W]]]o\%_O8=5=6333o1>ONNOD$FFF<[ >h<;;;Y˝;;;W _|=#r,Hj8 Qf$8 Hrcߪ;;;^ 333[r 333[YQg#t*HN 333[Y9f 1xXH\ch 333[rX;;;\ X(N޴Hiiiq;;;\ TT.FFFwuuug 333[YTT.FFFwmFFF>p;;;zq%2A/GK;;;B :. [a P]]]RRRj(((f]]]aY$mc =MF(((T+333wuuuuiiiOFߦ9 333[op\$ 333[Y+333z#GK333[Y'k|(((7 1֕]]]mRRR|FGKRRRm8 333[oqa%Y;;;\ W'N޴,U;;;[ 1֜FFFP 333[Y1֜FFFVg92CFFFI 1sA333E2333EA >(((O35(((DC(((4e9FFFc356ˏ=333E3A;;;GCi:ݧl%m333FR333f333EAOiiiR (KYL+ 8<,J$ :' C}˅28!25RYU= +LYVD5RYJ%FYYYC/ +LYT@22.DYYK( CY WG22 .9FYYYC/5'1% %69S WF/6^y*QD +MWO. 5ow$ !3%  1: = U X XJ%A(((WFFFY333P2 + M X X X X XB<= /:> *58.  -#:(C B#8%B BC X X X X F + M F 2333< D WA5֛_iiiAu M<= / .(((M;;;Y F<= ;;;=3  ;;;=3 9l( N˃l.9=;;;GC*G'v@>ˎ,333EC uuuNr( Y/ iiiKj$ V1.FFFDwFFF5}O;;;3=333jA ;;;B@9<;;;FC(|/9=333:˅333:˅J FFFr Mvuuu~g N 2 ,L y֥;;;[CJO 333\Yiiin(((eKADG333`YGjC;;;nN[5FFFpD(((X(((\ O%} } fuuun!e֣QVFFF]]]k f;;;? (GT@JOC9TT83NQ(((Y FQ6 r߰l( ,KKF@$J{JF 6p~(((O6p~(((OHV.333FFFX##*|_HN 333[Y[, bt!,b9</uuugXj(((֝6FFFn@#;;;zw%%|X9J+}R(wjN` 1.{333`G߮FFFc(((`1Oߧ֧Y.uuuf]Q.=߬[Guuue#1ߧD1ߧDHwߪP]]]Z;;;rC$|YHN 333[Y>O$ta rn{U'tb@ jVU%{T;;;j333i%{T=},dˉ3338˔FF T 333`23ߧ֢Yuuug§FiiiHߩ˖֔*n֣333N FH-֕߫;;;T -֕߫;;;T H{*.oe%}YHN 333[YuuumdOG333e ]]]Hciii. j֞5'yFFFp%{TOߧ6%{T)]< FFFDiiiCGYtRRRYG< r<1++Q֠[K~YCuuu;;;XrߧX',˓(((!GD;;;}Y*;;;\ *;;;\ Hf %\@%}YHN 333[Y^zx%333WѴ2 t֟<<֡ pd>%{T$q_ %{T   UxߨYHQ\'R8XRRRj (((cYUFFFJ N޴($(((iii;;;RHO 333\YX;;;\ X;;;\ H333s :}W%}YGO333cYAuuub ]FFFw@;;;n'{Y5֜h%{T\w'%{TRRR[ߩYHO['R6X;;;j (((cYV;;;RRR]FFF_RRRM$N޴( u@HN 333[YX;;;\ X;;;\ H_ hY !5]]]Y%}Y<m8yY oGTqx333gRRRoX $|Y(((iH %{T1˒R%{T/uuuZHx,r@u SC<|YG}%!#N޴(r]]]XHN 333[YX;;;\ X;;;\ GK'v+RRRD֗;;;quuuxD#|Y pFFFF _z%K`G;;;WTV'RRRn}(#|Y5tqh+%zR gRRRl$zT*˒uuuYF;;; W uuug333w;;;gs*%JWT>%39S WG:@6:!2$65<%3:UYYYF#y˔2870ːH  F WRJ<5RYWH#$K WYCD WXVA (M WYC1% Mn#/1./ #=;;;Z Z333< 7ˌ+FFFHFFF^FFF^FFF^FFF^FFF^FFF_RRRJ=˘˔(((Uh(((L!DC<C* /1 Qϴ W[ϛn+CYYYYYYC (A@'  <=#    <= + M W@  DD *6 BG D RKC0'uuuYr$H;;;X;;;YFD(((XFFFY333V >$N;;;Z]]]YW:9=l=+w 0GFFF9wA.]]]V <#;;;^* R1 R%/f_JO$1 +j˛Q3FD8<= !.6JF 'KR6 '=FOC3OJ<.%+:N=%HXJ$x333zC !! %**(%,#+** '=A>=1333Wv*%|U{% Qߧ oQ˞ uiii~iRRRG~RRRdT<!uuubiii@HYAq(((3*}R>߬ߪ;;;Q'w֜uuue# =s _'z߫FFFcNߦ96诂}ߩ=6qUuuuLᅡO*+>9 <;;;VK333> A=W51͛m+333_(((; <;;;VK333>{ߪ5 333[f%{TR3(|˘]]]o! ={ _:\  333FHiii}豿}MH֜.%{T333V(@H,߫O@ T 1֛֣UR߭@f֡uuuwˍuuuLRRRB֛iiiFDH ;;;VUM9#sT;;;T [5|N,֚(((y|AM9#sTaߥ֟<333iY%{T=ߩG@G,߫Ov$wRRRf9Y޴b%F}:G߰w< %{T 333[>HD;;;}YMߪ\:;;;|jH= rOߪ]K~YX K:w kG |(((9JO 333\Y.ZKF]333nFFFV~tD_l.ZKF8qlJN%{T$%KUO1/HD;;;}YMߪ\:;;;|j2Q$w֚2Y˗y<Q֓<Fi %{T 333[zKHO 333\YYRRRn_%HQ\'XRRRm (((cYX3333PގsJX;;;Z HN 333[Y f]]]n xuuuo U;;;uuu´, zuuuu( f]]]n xuuuo ]]]iq''֙8%{T(((hC$g˒ n333w@HO 333\YYRRRn_%*;;;< @v֡ PHiiizMGFFFs%zR 333[}{NHN 333[YYFFFk[(HO[(X;;;i (((cYX(V:X;;;[ HN 333_YJ߬\Ji~RRR|$J߬\iJ%ˎ6%{T iA1333w=HN 333[YYFFFk[( fj:RRRv]]]W iiibFFF]]]]]]=Hk%z_ 333[}{NHN 333[YR˖F'xHx,xS@<|YX( 9֧SX333n$ @b8iiizY#pߨ6:333_ Ke$sߨ6K( GM%{T$3./Q333V(((U@HN 333[YR˖F'xp366(((bT/i`Fckc%|iiiy(((5333[|yKFK333[Y6FFF U G;;;W 16FFFd on(((D[_p515(((DCVFFFdFj% dYCiV;;;c6 7333RC6HuuuZM ]]]_C3ˍ6(h333<RR,2 333\`%{TJ޿315(((DCVFFFd/nsRRRx|+ tJ /1>5 (KM+ .#.$22/1.9S WGHWJ$D W` Y5'%JWWF6RWDFWTK<5<!219. $5<+:UYYYC;;;WRRRu$%|U~$/1.9S WG*$!>SM+ 1=5m֣HDF ;;;VV3339Y GFFF8 zJ.iiiW%ϧ+*ˉ+ A<:333\G;;;F!;;;=^'333CI#uuuZނj: #$ (66@RD!  AG! 5˃. @t~o vuuue! ;;;RO.ˏHFcFFFN, GY3334x9֧U#]]]ORRRiRRR]]]W 6;;;Zy|: (((hcFJ,1 K333S>333YY#iiiR]]]g{]]]xiiiY 5 (((3mDYYYYM+ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normallight24.dfn0000644000175000017500000104401611357170241023560 0ustar keeskeesf## '! '" '#'$3'%D'&Y''l '(v ') '*'+', '- '. '/ '0'1'2''3''4 ''50''6@''7P''8`''9p'':' ';' '<''=''>''?' '@''AN'BN'C&N'D;N'EQN'FaN'GpN'HN'IN 'JN 'KN'LN'MN'NN'Ou'Pu'Q)u'RAu'SSu'Tcu'Uuu'Vu'Wu'Xu'Yu'Zu'[ '\ '] '^#'_7'`G 'aS'bb'cs'd'e'f 'g'h'i 'j 'k'l 'm'n'o''p9'qJ'r[ 'sg 'tt 'u'v'w'x'y'z'{ '| '} '~ ' '0'B'T'b'z''            :=! $@A=JF#3* %1  .HK9! 'J] ]X=.=/191  %A:.E==E.  ,# !6.3Ta _U366 =G(((GKFV! #FFFL >:_333riiisjT/ . gV:]]]]v<_s}s]9333F>  5;;;`..;;;`6  3<P;;;H=:. Nw$D]]]fiiifF <= Vc333^g!(((]uuu\'>|ZNrRRR[.^˒]]]zߣD 2oV=nf8 333_X* kg##g k*>]]]g333ye# 5 //]]]cRRR[%>mm>TV]i 333en3j c U] =}iii߭uuu֞C8|iiiybMtߧ(((U (mo/ 333YRRRxiiixU 333eYXv6  6 sXO333333]+Ay,Kߥd((((h(((}\[(((e(\__k333a֟i Y֜v.+tߨ\[ gi6 Jߦ{(8 };;;[9[RRRi<.nFFF|Q2_}FFFY333a˒M 8]]]kHJ]]]l8  .g {>Uݴz: cNKuuuuGD]]]tߦH\`]i333Xb#Hmty(((x+(((aߩqVxh*$(My(9 }(((jcs~J2o {8M]]]y;;;[333W}> _n!#o_iiiCߧ˗﾿x(Yݴ{< .FFFhiiii3cnia\`XhHurG33373339333\֡|bza 9}iiixbNx ;;;|\(uuub`G|WHh+/RRRiFFRRRi/RRR>˓֨˃(]ݴ|AH֚i;;;[H D;;;[\`M֛d! 465B? 4ˇ߭˚ˉ 4Uo `˒]]]{֟m(`iii ˍA! 4.Kߦp''sߦK *b((({@'/1Cާf91/'cT!333_;;;j/,;;;g;;;_$\` @y` 9vXT@.(((hN  , d yF  V333˒\% ,% `cb`N(((333a+(((6]dfluuu{ifd]6*333im8(;;;c;;;`%!333^RRRb,\` :u]Yߧm#$n֜U2kߦh6 %GZdp֞uuu{jdX:6 x߮6%N譛]$h˒NM˒h=RRRh333w^!ih Di!.qiii]% 333]2\` :u] (tu2< vuuuwR  $N֤]]]e<'Tq˖rU  / k´;;;}ORsv+;;;Z~= $333c;;;i..;;;i;;;`%\`,zFFFF5FFF1 y k%;;;\D F;;;\\`<;;;A*  . vFFF(((m333f333(((333]333A%  }[ `;;;qmy39z26w;;;w9 Y 2;;;Z|96u;;;[Vݴz<  #DZ``Y@ Y_agjc\`!HN* ky38Y'  (;;;>D2NzrNRNoMJwx(.}{56wFFF|FT >aJ GaMݴv5 :=!:=!!jD KRRRuAC]]]tK\` =HdU'333d]]]e/;;;B֙ ~s9 >iiijX!2riiiv\@b{]]]`(+jUH_333{x1 c\[c 5ߝ[$ =H =G9o333i**333fVV(((h*\_O\Zv<1h_ G֧߬['ek' ]FFFtV]w˖`Qp oT($UcO\MbAr~~r@UX >H;;;?FFFL! .ߞH'[uuulu\%2j1  .hf++k333lO>b֘%6luuun: 9iiinp8Vg >HCߡ@ JjjH =@ <>! #0% 3 8!6[ k< = F, +NY [YJ'  $H^ a a`M, >M8ecbhN}Z<>! :96U _ _U668   Fvh%     @yiiin<  :]]]nA @@      #uuuM<fn''ng (hC$+ 5FFFh֙OO֙RRRg6 Fxx$$xyF>iiiLIIiiiL>                #D\bbX:=Yab`N,'3# A]giidR/ %A@!.QdiiiiiifT/6UaaV81Rad^N,$K^ZD!*F[] Y[ [YH+' _֙tY#E;;;e> 5 d;;;E >\ 1m >V`JuuuikOARRRf333f<L\  %M(((iߤ333fK$ Dޛ|Vv޴{h6  .z;;;^V]]]G 2v@ ]]]F߭(((a@}ˎD 8h賎zߨ]]]d5 #   R}֙C 2iߥiiif333_333]RRRdˏߤg. >]]]ffNVo64RRRI[MKi]]]zY%i;;;e!\cURC% +q_# %CRUUUYx V ^ [[ (((a! XFFFzcMbFFFz_+KdhFFF<RRR;[bF'iii8333E`_ 3 j֚x\G:5:Rwˑh%31: Q!]FFFYXߥ;;;c!\k! bY# X֜FFFo2.r]]]tFFRRRv{3$;;;byTRf, 8Y(((nߥv $%%%%%%%%$lˏnT2 %ui(i]]]n`MVdfYFAXiii|O j_JRRR|;;;\Jx ;;;^!\i H֛\ !o_2j z,+|}:+q]]]k5*u}9  %DguuulFFF^<2RRRKRRRWRRR[RRR[RRR[RRR[RRR[RRR[RRR[RRR[RRRWRRRJ 1=iii`RRRjc>!tcT;;;sUNlߥ|ˌ333j.c_/q[=]]]i}333u;;;Z!\X:$,333ij(  Azuuun9 ,miiisHG]]]tt2'RRRa]]]wH .> $ B;;;B'$ B;;;B' 1QlmO,rr2V n֚tjJ+5;;;uN/;;;j]QRRRivK qQ#O֞J 5 opH333_;;;Y!X߫ߧ(((eJ!RQ.! ii ]cc(((`  ]D+:k= DHDH.]FFFpiiikgC%.H X [ [ [ [ [ [ [ [ XH/*Hinߦ(((tX+ bFFFk.KwT333ouuuuj[}ߪb]] 9iiinm8 ?, .v H>333g;;;e1  Dߥ_! k߮FFFi]]]]RRR[[< 9uuunzA J|֠˗OFߤ]]]s o]]]n8GLGL RRRQ֟ z\8   <c;;;vߩ;;;P :oT\`k|R 3GCu`cg(((A߬/d(((n{333;;;g/ Ebiq;;;zߥG2twO_m!G(((RRRO [ˏiiii+*iiiLW/ *iiiLW/ $|p<   Cy߰ˆ$Yu(_RRRi[]]]kq!kFFFm/2333h^AuuupA %UT/ߡT>(((Y DRRRn sx}> 2FFFmːG#d(((f(C]]]]\iii_;;;niHrːnT3  2=>>>>>>>>=19\333mߦlF ;;;[uuunA];;;eg{D io#3uuue^ 1tg 2rFFFb%'gˎːˏˏ˓֘RRRAD]]]t;;;c%RRRRd8/N [Un' @ˏz[,+VuuuxF $2Y;;;ߦJ:bRRRj]]]jfA$FFF<~}~~~~~~~~}}3339'Fhuuum;;;l]8$uuu\m$\iiicv333q+!wc!Gz]$k;;;n5  :333y|5*<CDDHb(((333V# *333hp+U}( RFFFZ+(((nOV{%$|Y 1x g' 2Tlˏ nK$ aY 'Onˏ lN. 333U Y]333n;;;i% @vߨR,iOX֛ːN.;;;l|6 +333`;;;`+ 6333rFFFb' Jߦv# <333z;;;^ Mߦ333n,\pr] (ktA  'Fhn(((H.N`cccccccc_N,333IiiilgA$K;;;E]]]]n;;;x5 'xuHMuuuo]]]h3Jut.   Nvuuue+ 333Y;;;Y!%! %f333[5riiisGY;;;Z%mYQ 98R +kY:=!:=!:];;;l˂!  !w֙(((mX6 Am[%Xːߩg.,`˕333f w[A]]]svQHF9 1KM@@\333~] 333Y;;;Y!4֑ k[GKpQ a(((}YHbRRRzX C]]]m56oTRs9 *mj% =G =H .HH32 GD*O@ D֘FFF{>,RRRa˓ːːˏ֕RRRA wߥuuuupߧp: 333T;;;T;;;A|xj* :k˓uuuv]]]d3 TcY{\En, O\Uc   ;;;VQ((((fߧx֢}FFFI(  2b;;;HFFFhC333>(((@ 5bߥi1 CRRRg;;;g=333@c8 %]ˏb'FFF@֘d+  >HVg H@ Kߤ}333ߦ֙FFFdrFFFnߦq3338 GdmkgfdfbO/ 'J] _a_Q1 !/ 2Rad^\F$ 2T _ a _Q/ #71>Y ` `[A  %@= <>!N}Z $A=$g˔}jT:/>Yk|i5          @@   .jiiitydUQ\m smH(hC 'Viiij֚֚ f>8\FFFdˎ￿]]]aaH( +AQVUN>,                    @A! %McgfbO2$C]bbbcYA' %Mcgfdff`M2  %Mcgffff_F  %McgfffbO.#A\bbbd\D( /! 5, /! !6+ /! >H2 /!  $@= (HF# #<666QT(((Hiiik[( @ lː޿333cD(((Hiiijb6(((H7 (((HZA kː333eG(((?333>Ca((((?333> C['(((?333>#\֘˂ (((?333>(((HߤX+oK(((G{N <= .333u;;;s/333\˓f##Yu˒wߡ6 333\˔ːː˒]]]kM333\˔ːːːːˎˆ3 333\˔ːːːˏ֕RRR@%\z˒w9 333S;;;T\z9 333S;;;T333Xz8333S;;;T!_֜X333S;;;T333`~K!gg333_sDTVRT 333]333dRdߦF [iiisnQCGVk;;;n8  333]333dJFGObyߧˏO 333]333dJGGGC1 333]333dJGGF9 _uuuspQCFVk;;;o:  333Y;;;Y!b~>  333Y;;;Y! 333_>  333Y;;;Y! [ˑv.  333Y;;;Y! 333e]]]m=R˒k 333fFFFn<\_(p q* 333Y;;;_,> bD }A /C: 333Y;;;_, ,X]]]tn:  333Y;;;_,  333Y;;;_, F ~C /D< 333Y;;;Y!b~>  333Y;;;Y! 333_>  333Y;;;Z' Vz2  333Y;;;Y! 333` r5 Coˢg 333c r6 \`J֛;;;;;;ߦM 333Y;;;Y!xi%m 8  333Y;;;Y!H]]]vd 333Y;;;Y! 333Y;;;Y!'l9  333Y;;;Y!b~>  333Y;;;Y! 333_>  333Y;;;^<T|x3  333Y;;;Y! 333\(((iiis.9333o c 333](((w1 \`# nvv p$ 333Y;;;[$ /c CߥzG 333Y;;;Y!]l/ 333Y;;;[# 333Y;;;_,  DߦH 333Y;;;[$d~>  333Y;;;Y! 333_>  333Y;;;npw u5  333Y;;;Y! 333Y;;;lt˒qR z]]]pv|a 333Y;;;nv˒r*\` CuuunCCuuunF 333\333oC,CxJ [|$ 333Y;;;Y!3;;;sD  333[333n>!  333]333bFCC<*\~% 333\333oA$!!!!!!8}>  333Y;;;Y! 333_>  333](((t5 333Y;;;Y! 333Y;;;^Ci˘|TOwa 333Y;;;^Cgd!\`kj! in  333_333q;;;es8 fk 333Y;;;Y!lU 333_(((q333Y333X333X333X333R > 333a¿ˌ`(fm 333_;;;n;;;[;;;X;;;X;;;X;;;X;;;X;;;Y;;;g]]]>  333Y;;;Y! 333_>  333c ~: 333Y;;;Y! 333Y;;;Z*.t]'@wa 333Y;;;Z*,qˑV\` >u](([~x@  333aFFFQhi 333Y;;;Y!n] 333a, 333c/hgC\fcK# 333a>  333Y;;;Y! 333_>  333fr# 333Y;;;Y! 333Y;;;Y#3wr( 333^;;;}fdcY=fj 3J 333^uuu} v[YZZZZZl(((>  333Y;;;Y! 333_>  333c;;;vA 333Y;;;Y! 333Y;;;Y!<]]]c o2 :wa 333Y;;;Y! 5siiil@#_` 8iiiquuur9  333[333l< /T Y`y! 333Y;;;Y!1333uD  333[333l< 333[;;;e5[|$ ,guc 333[;;;i:/u>  333Y;;;Y! 333_>  333](((FFFRRRiA 333Y;;;Y! 333Y;;;Y!,9'  :wa 333Y;;;Y!:;;;m333oKj`_RRR(((l333Y333X333X333Y(((lRRRb 333Y;;;Z#XFFFb$ JuC 333Y;;;Y!Yp1 333Y;;;Z# 333Y;;;Y! DߦzF(>nd 333Y;;;Z#c~>  333Y;;;Y! 333_>  333Y;;;i`FFFl]]]jD 333Y;;;Y! 333Y;;;Y!  :wa 333Y;;;Y!Auuum`2FFFob+ +_ߧRRRn5 333Y;;;Y!Fiiiwl** q3  333Y;;;Y!CFFFwg 333Y;;;Y! 333Y;;;Y!'l6Dyc 333Y;;;Y!b~>  333Y;;;Y! 333_>  333Y;;;[3>;;;luuukH 333Y;;;Y! 333Y;;;Y! :wa 333Y;;;Y!M|`V(((q., s[ 333Y;;;^+ (jߨ;;;b#K֛}> .A< 333Y;;;_+ 'Q;;;wq<  333Y;;;^+  333Y;;;Y!F|@ Qzd 333Y;;;Y!b~>  333Y;;;Y! 333_>  333Y;;;Z$:(((noM 333Y;;;_+  333Y;;;Y! :wa 333Y;;;Y!Y֜`+(((pVU333o, 333]333\CDRu~W!f]]]rjK=ARj333q<  333]333]A>AJ\xˑ֚R 333]333\A>>><. 333Y;;;Y!\iiirmM:9F`a 333Y;;;Y!b~>  333Y;;;Y! 333_>  333Y;;;Y!8 quN 333]333]A>>>=2  333Y;;;Y! :va 333Y;;;Y!$ib CFFFl11;;;mD 333[ߪ˒FFFc1  (cozߧ: 333[赴~uuulQ333[ߪ~~~|{ 1 333T;;;T#YumkK333S;;;T\{: 333T;;;T 333_~> 333T;;;T6rr3333[赴~~~}};;;;333T;;;T6s\333T;;;T +x[ @QQ? (((Hާyd3Fk֛֚333gJ(((HΎqf9(((H3335333>333@@ jlY%(((?333>Cg*333>333@!333`}9333>333@5 n8 (((Ha333>333@'`C333>333@ 2uC  @@  @@  %MbdccbU< 'F] ` ` ae_G* %McfccddbR8  %Mbdcccc]G# !/! #A\ ` _aabQ5 /! 5. !/! *333ih/ !/!  *F@ %Mcfcccc`N. !/! +5 !/!  *G@          Jv;;;b$      , oZ @ˌ@ 5ߞ]]][H(%                #A\d a acV:  %Mcgff`M/$D]dbbcX<  %Mcgfd]G* $F]dd`H'  F_fffgiifffd[>8= !6+ =:/8#  <8 #/ >=6K<+HD!AH++HA,Nbfffffddfgg\>=lrd3(((HRRRiT$@ lːvf6(((Hߦ333hH /kߦ(((V% 9/ <ߡG C[' AG 6`333@D֕A#TOO< $ߝˌT 3m8 8k3  2l8 R/ Tq֜wwFFFjC333\˔ː]#YuߧwwRRRjG333\˔ˑ֝֘K( k˓9 2ˆˎːː˓߬˙˒ːːˌg*Uc333Xz8Hl'`VOj Fː]]]l3.FFFh֘>  \{M 1y|9 2ku.  ,tk2;;;<֔ˏːːːːːː˒f,U֚ytRACXz˒nC 333]333dJM`= [~uUCDXz֜xG 333]333dMTmFFF{iiic,M֠XTfFFF^w. 1CGG[VGF>+]i 333_> 2RRRnːG1FFFnːF :ss< nVO(((n* 3suuumC*rߧ\Tˑj$$i֜V 8DGGGGGNm˓R@u(((wH! 'T]]]r;;;l3  333Y;;;_,A[C(((yJ# (U]]]sRRRj5  333Y;;;_,M]]]y֛G d5$# #ti _k 333_> fkR o( o_8uuurr'# n]:FFFlFFFl<$fj%#f֜Y X֜g# (fߨg!# l(((z=Juuuu_ 333Y;;;Y! {e$l333y>Kuuuub 333Y;;;Y!*Tn| j__k 333_> @{p: $oXN333o,[D @wp: Cuuum s<+\֜t+ +tw[[wt, Hwt+ @ː˒Odiiif+ 333Y;;;Z# .b @ː֜Rduuug, 333Y;;;\'A333KdAj__k 333_> # n_ C]]]n5.;;;nߦM*(((nhcnM| yw1  3uRRRFFFu3  Mߦ333p.ig`m J֛RRRvviiin6/FFFnߦKY֜ߛt5 9;;;n;;;n9 3tFFFn<iq lR 333_}s [d]]]kg'ir lT 333`]]]oiiicuuunߨߦQ'mRRRnc9j__k 333_> ,333oN 6iiimC =ws< lk@pYO333o,%n;;;AGxxG+twGlpn[ 333ag2 lpp\ 333a}+ ,bqmOj_\i 333_~= ] o$Yo$!p_ :pDU q,' n_Y;;;2!vx!!f֜Xiq kR 333_(((q333[333X333Y_J' iq lU 333^]]]yh y*9](((rߧˎDj_Ti!333`{6 :p|G6(((nRN333pAbp% 3]]]nːRMwq:  5 }VbcTˑj$[(5;;;vA  333[333n>!Y( 8FFFuA  333[;;;g83mߨ֛O .[]]]y333\j_ F}m,333j;;;e*ktc֛FFFn1/;;;oߧx(((}Ui}l  .vsG\`Cov.  A֚M`uuug, 333Y;;;[# @ːMfiiif+ 333Y;;;Z! *r;;;q6 [uuug.j_8}FFFn2G;;;^ Gː]]]~cc֡]]]n3 D]]]333ߦM(nmT u]]]k>\`8333o s5 %l }<Giiit` 333Y;;;Y!# n }<Mv` 333Y;;;Y! 6333uk!  >;;;}3j_(]]]c\%t]'o跂s= >xi'o333o,!cn*Uz֜sF 333Y;;;Y!$o333p1 <ˍvVMdRRR{]j` 5]]]gumJ>Oy˓h%3RRRs֝JOv'5]]]tx< Jwz3 M|u/ \_]֥\D>>>>>>8%#Yuˑno֜RRRiF333T;;;T%_tzߩiiijG333S;;;T :]]]nM =ߧzl: dYCj}uuuo333h5 g(((t+/FFFnVhp .iiia r6Y֛YUX6w˟~~~~~~}yY(@jːzg6333>333@G(((l￿zD (((?333>QD!UsRRRgCH@ =jh2 :pOO]]]W. =ˈD 5FFFd9#_˂  =@ 9/ $D] `b^b[>  !/! *Jf}qKA6 /! <>!<Ybe _R1!@<(H_^b^\A 28  2*12AJ/!AK368 GcifdcccccccbY>   .[iiip֜uuupu1            8dmZ, 8Tb;;;YFFFL6           1UficK$ >@# Hbig]A #>< @F*35*31MB 35+3+335*3%_333< :M =@ $bV 6(((b/ := %YAd֚d% :wa :wa1]]]gRRRh/\`    ;F5.M~9\iii}V(:c Fߥ}`. ''Hd1 1peQ;;;kFJ|> %r}QX=8qm \d1.b;;;b$ \v#Ciiirk/]p$`u'Dzch n [ ^|]]]Qc~> fߨ\@(((~FFFX]+.333lo2 :wa :wa[]'  :wa :waQd\`/[]]]eߤ> \c%l}9 dM bT `˕i%Nuuut((([\fh}< :wa :waYf% :wa :wa5uuuj;;;g*\`.(((c> \`$k}9;;;YC ;;;\֛M :va333^ ` X Y [ _ \E b~> MRRR}nf T\`c~> :wa :waYiiif%  :wa :wa hD \`Siiiti]> \`@]]]sk/fT f˕] ,sߨ]]]_2 \`b~> :wa :wa[ `*  :wa :waV_\`;;;Y{_+5|J\j 5(((b [3  X= NzdY9  32b~> _uuu~_6\`b~> :wa :wa[p2 :wa :wa :p(((i'\`;;;Y]]]d@_]]]~r+ [O=RN @N=FG/ 8mXARh  V˙xU3\_b~> :va :wa\j>cː r6 :va :wa#hv9 \`Ruuuw;;;sߦFFF=Kxuuun˒k% c}iiioe!Tߥ֜uuureYuuur9 \{:  333a}n`C! UX[z86sZ :waUY!Tq333](6sZ :waM9 \`   3]]]^֖<+RRRZvb+  (buuuQ  RuuulK#XqoT Ch* :ˏa( =@ AZ''`C :wa =@FFFFf2'`C :wa#A>\`=RUUUUUUUUR=1R]]YX]Z@+M_aa _Y< >[ _ `_Q.8V ` `afcK#:X _baX:5.'hϧ~sO683++5 =xc681J@+5 :wd`` ==          F(((mH@U֡ [   K}c   b#6 Q [ [ V B% @ T [ ^ [G# D ]]]]\dduuu_ _Q+(uuuIM*   %,.(  1NG#3*9]]]cDAU%#+'333`F[z8*FFFN: Cߥuuuc%b~> KXT}*b~> $/1$ ,1(!.2( !,/,! *22' %12*  $*  */*  'ty/             Xߨkb~> # C VdFFF]rnRRR`X<CYkouuub[, !B(((Qb333]lnuuubZ1 (Q333_kiiiek333_Q( !D((([ liii`nniiia\3.YRRR`nniii` l g333F'#A(((GM[]]]\iRRRM*2Zcmuuu`T3!;;;I333333333] >#A(((?$$;;;73$;;;= B!3FFF9( $;;;;>.;;;8/ >;;;;$333=;;;KD +N;;;H 1#333= B( =FFF<&  0;;;H333V333X333X333\333a333a;;;O 1[ib~> Fuuuui*D333d/ .ll/  DRRRg> 3nNFC1RRR^Y# .,FJG{. @N 5aRRRD @G,RRR[]]][.H@ .֘Y  .ok 9]Fߡ(((?r]_ib~> Y~ ~ߩOY֛ y}V#h vo vh$Y rlwߧRRRg2 'j wn q˔dYFFFw(((u: Q;;;v nソv$Kb=[]]|< @֘(((l+]X Aߣ l$QR%lߤA !cX(2p~G2iiifyA'lG/ H V Z g ߮Qfeb~> ][/Av:9{ a]c/.b;;;`# D֚i3!3jߦF ]6 /_yXKj3 1ne] zF3/a{<29+!nr(]`c~> (nߥK1FFFju> +(((mA# q p!D(((m+ .ruːY`n#J֙(((n, 'Qu*(}[b~> ]}'Y֞8 Ap;;;[]+.333lk1]v(  *y^\f d;;;_  `u( Cyc\RRRy@YX2]`\`b~> Q l$Ql!Xf%Ax߰s>'gX 1wߦ_! 6RRRmJ3 nR(o333p6 !`ːA b~> \f Awk(333d;;;Z!\fh}:bNO d\` 8FFFq]]]b*;;;Z|G :wa\q <ߦ;;;jR' \`\`b~> /;;;lG3lߥJ6iiik]]]lKidNuuumiiil6 <r(\~mː333l.[vF C{'b~> \` ;;;Z|D D|;;;Y\`+333iq, a333r5 :va\bGRRRhf%\`\cc~> \udː(((n+f333|(((}g.uuu`2FFFkUFv\Jtb~> \` :va 333Y;;;Y!\`b~> g˓XVg\` >]]]q;;;c%;;;YsC  8iiil}Y C֡pK o(((A R;;;q<X333p/ 6333oo(/FFFgRRRm1b~> \` :wa 333Y;;;Y!\`b~> X : 9 V\n .u [ ]r* Mxc\` $F_\k M.DFFF{> fߎiiil6%mT%Y o$Fo333 q61333yX+u(((y> >Nb~> \_ :va 333Y;;;Y!\_b~> 8m R@R m8 ]Y>K{֞ߥHHqA5K֡g[_ ';;;BYMX[XU<! 6rqKX> >xgO]]]r39tO>]]]j vDK]]]k t1  x333w/duuuOA=2pcb~> UX6sZ333S;;;TUX[z8RߥiiiqߥR]˒uuuozf#%huuupRRRi|kTXFFF<x֘A F֡x333<^uuux˒~8!pA /FFFpkr;;;r.(333` q6Gq\( yY 8~~}};;;:cib~> =@ '`C(((?333> =@ AZ' RuuukuuukR ]c*  .g֙i :> 9ˍV%c(((@ .f(((]'C֖ ] T֖A FT2FFFb9Nz֏!Gˏ;;;m1 :Y_kb~> 68+5 /! 683+8V _d _V8\oa _Y@  #CZ ]^ee56<Yb _Y> *O _ ]K%  (K] `]THA,: >% #=8:>#@J/9G3$mV Hdjgccc_N,_kb~>        \m(  Kza         F;;;l1 \pb~> \` :va#mYQ:c~> []9u] =FFFk2 9y333_(]}= HJ.sJ @T^7 K|/'FFFB]]]E(3335uuuE( +TE% (Xiii[Y+ *J8    #      #@Ydfd]F(!FM1 8C/5U_S66Va^O,A k֚(((jM$ C]]]c:8X_K1%/3M֖ˁ Jiiii֐(Ck333`. (]z֜˒ߦm1  D;;;_( 8qFFFn}333q>=iiikSJ~ߧpb$.iiib}K%g]]]txf_cr(((} p/  5 /#buuu~ߦF  KG$ho2  6iiii(((}\=% G `f| >V[Ygni[Vtg! Ay,*Y<v u(((^+ 5 k8c y> N. 6<! 8iiilyTit֙nOgːG  6JK6Uݴz: m_.D@@Uqy`2'M]]]\mN!6uuul|J @֙;;;|A Y |Mg|֝_>nc .Te`F.5`sᅴs]'Yݴ{< j_  #G(((Xg333_nskh6 (Q333`oRRRro333eR( Vp#/ ~}8!333_|TNz֞yVgx˃,=FFFru3.(((f֜X]ݴ|Aj`<Y]]\D' *!D333d/ .ll/ 3t֝] 8v:,uuuc333g:_1 AuuuL9!oG S uuue*'/1Cާf91/'efGzˏnVAJiˆMY֛ y}V#h vn vh$H]]]x6YFFFi=3sg1e֞\iV;;;Z˙HVRRR~8(((6]dfluuu{ifd]6Y}($pvyuuurvp#]c/.b;;;`# D֚i3!3jߦF 5k(]]]`]]]yFFFi95id/g˕V i[333`uuu}t,>]]]o< ih @~`! RsdKH_333mnF]+.333lk1]v(  *y^/i߫Ч;;;<5|FK]]]lj*1rg5bm/FFFB @ kߧO333X 333bp|3.K\_mf_\K.%|D  ' ,J^((([ [Y9\fh}:bNO dT333uuuy`5 5|{5GiiipM%;;;bRRRpHTFFFyJ(= q95 z~< K(((`! (j޴O  rJ \`c~> ;;;Z|D D|;;;YJo( (]]]a֜]!#d֞`[pH(((iRRRty ]]]cC[ߦRRRa(#Xuߥ֙;;;dYbst>Yݴ{= /FFFnRRRf/\`b~> g˓XVg\`XyU/[c Dːz]R]]]fˍ\T;;;vV3C='< []]]]]]]^Z<Xݴz: N@\`b~> X : 9 V k˓]# ,mrY#iiiitfYifuk g``(((y(((j.  !!  Vx= cp\_b~> 8m R@R m8 2iiil]]]mdYJDH> 6 o˙֙C  2333h˒`URU_vuj> 2=>Jpˍuuuh_D>=1icUX[z8RߥiiiqߥR CߦːuːA5 ty%8o|333jj(((lsFFFiAFFF<~}~~}}3339j_ =@ AZ' RuuukuuukR  <֝֝A2y֢d/dvˏi5aYj_683+8V _d _V8CYYRR[cd a ]J#5d =[ _]]]Y;;;^]]]Z333]_C! .N`cccccccc_N,q]    $Quuuy333[ #$#   :T!uuuKzR9]z(((\*;;;^z: +֓FFF|T 9^Wuuub5 +Yiii[X(  *U]]]]euuu_W6 #$+' deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/console18.dfn0000644000175000017500000053601611357170241022712 0ustar keeskeesf !"#-$<%K&Z'i(x)*+,-./01234-5<6K7Z8i9x:;<=>?@AB:C:D:E-:F<:GK:HZ:Ii:Jx:K:L:M:N:O:P:Q:R:SWTWUWV-WW<WXKWYZWZiW[xW\W]W^W_W`WaWbWcWdtetftg-th<tiKtjZtkitlxtmtntotptqtrtstttuvwx-y<zK{Z|i}x~     /=5        :A% !>@6<8!<9'+3!  $T;;;siiiqd3 %M]YF#.9% 2U_ ]H#+6# *:.9C* #.! *=7 'K^a [C =333GH|@ JYRRRU333A%fe  YXKuuu_]]]C 5iiibU%Z333C6(((bl /l1 +A(((V`@% '(((Y,(i֙YV;;;^cX$eː(((\N]]]K 9uuuoUSr.5s;;;X.m333P+uuu`k$ /˄y;;;诂R# !.! KߥFFFd*VˏC];;;e!g_,V]]]xRRR(`RRR(((c+ Mq=  b߬~95z;;;[ _RRRn:M}ߦN 9֓*333>333>!oc+RRRht f];;;e!_U 7ex߮v : 333^ ;;;j/ M֩g333^uuuz5(FFF^(((U 9oߧV j333j*2uuur$$333X;;;X% >ws= D֛{X8d֝i,Y;;;c Dlfߠߟ9 iFFF9Y333|9 9}uuur< be51/;;;BC[|, 9RRRtߦJ 5iiil333d( /N(((}(((Q. do Xm`n]]]z< Nߦ(((b42+2/1 _ ʹiii_'  5uuug֢x3Z|1`uuuUYp8  !, cku` 6֦*'uuuNcuuur˙߫uuusaRRRE$ 2RRRm֛Jbˑ G Awg  F ˙ == y m. $Kj]]] bF 1{vA  ;;;bYgi Ag(((v W9 1/ 1O a d] F!T(((n*cFFF(((M5y\2 l S% @(((U= NY߭ r+ 333cNbk2iii>/ @Y xiiiuuu{WA l: %oYb֜ G %iiiPFkFFF4$333cFFFeMߧuuu_'%]]]`֠]]]xA333cߧRdk  8333j333j9RRRDߢ֛֚֙֓3  Fiiim6Yp ]q]]]{~: FR5Dz]]]߮߬iiirV, /333e(((333_*ou3,kdR .333`cod333S;;;Q   #<JKG3 $ji Gߦuuu{X9d֝uuug+/RRRToH,333~K$!Eq(((`O p3(fq(((Tcy#.(((wT =>%(((La N#  +FFFOsD8uuumC .RRRit fJ}*!;;;[vf@ˎ@ !333\˒uuu_'\ގߢ: DːvDTߧuuum5+ DF H~+O o$Y֚DGd'uuuK333TXG @|T#˂]FeN .h= #j t.9333u`MQFk((((@G*n֙[#HL5'5*':<  HriiisFFFlJ1<'(N\ZF  *N _ c [K:CRF! 9iiiiU$i(((n1 CFFF~< !GL6%>= (N_ fYC    6</  Jze2iiid= 3V   @uuuJ 3#FFF@RRRI98:             *KXD%MbebV2!Jac cU28TH#2VikgT1/Tac]C/TgkkkfN'  *N `c^F! .TbaW6C\ a_Y<<S[ZH' DT=9 jC  A]]]e9ARRRe9=qK'e^ 8333h9 X333I+ lߥb# 1 jiC <|F U f/ J֗@ $][A333\!Cδ;;;Z!' rg6wuuuO+ k: uuuN;;;[UH^˙]]]h3   1K>!!=H, >΂wuuu_'Nߣ֚ }s a$!mg%p`#DU]ߪ5!CU\˙3Qߧl :yq\K+RyXQ>+K\db(((`} c*m{uuu}[2:' 1=*%Q333o:  : qK#  ANMmuuu|21iiicqTd(((ߤD :vFFFp.0\_H]]]z= *c]]]~62333pk :x~=# lA$ Y˔}@ 333]˚\g3liiiyN2t(((f  5}]]]M  3uiiiU(@rߦw3  @ T Z Z Z Z Z T? 5ːn<RFFFk/Ntep[X߰֜J $t_ Dz~8 +[uuud*b(((i:xtV5,kt_D#  np!WiiiV3r{T1iiiii, C}( A5'`u oC /. D(((nuuupY#6 |;;;Z ]}333333W p ij_diiid*]]]K֢j =uuuoߨi3uuuugD5֛g+ =u֜KJ;;;@ +n  8 1e;;;H/]FFFR% Muuuzd/(RRRJRRR`RRReRRReRRReRRReRRRe]]]^333G$2j}G/ kD;;;V ߨ]]];;;X 8r˚;;;o+j_>]]]r\ e߬u$!m r!iiiR˕ߪuuug36uuut]f(((p*Xuuu{F]: ,5! +8';;;OuuuC%RqvvvvvjHHOY|T 333X ;;;X Vſ˓H j_ 1x333m13dRRR|ˏ> A8*FUqV5z}p.3RRRpY.g333]]]((([ +h֛z3  >} rA 9ߡߧߧߧߧߧ豴r,Fuo8 %iii]Y 333Y333| 333Vqgj_(mqC M(((VV֤֡iiiP /h/rn2X:X]]]o5 FߦRRRQ3il. #D`v֦;;;l%AptV  :/ X p=%p(((W' 333YFFF]]] V6uuupߴ333q+ %vk `˔f*=\Hz#1d! m|6R}:* sgM333F(_}3%He   +VRRRn<  Gbggggf[= :FFFoT(H YA;;;WFFF< TFFF`Ji~˒G 6bQFˑ߰}Y9 *GT[֠J #KeiuD#CTVuO[p.J֛x@ @ߥph+!DT[J'333G]]]O ;%(((La N#9i9  6̧sf6$(((Pp333S([ߥXmo#+sf/ˆ? 333R֓2 RRRG賿 g('io D;;;d+2FFFi߫a [n %(((c˙]Cl%D|( DF  6622  9C G`, *uuudN]333` 2@333F5 iiiJ i5 =H A;;;g9>]]]f333f2 iiiIˊ@8FFFgj,C n1  @c%MQ   6= %eRRR{zuuu`Q''˄]]]W+ 8pX>]jnnfJ! 'Nfkkj_A +Q a f `O+:=!%M ` faT/2UbbT. (@81Vb h `M( #K `c^N* CK2 CFFF~< @MC 3 f(2@+3@+     3V.T;;;XRRRYFFFVS9  8: #                       'Ogmi\@  !D]` daK%  'Oik_C! #Mgmkj_A#MgmkkdJ! !D]` daK%  #8,:@$ =]kniN' !@< #8, %DJ,!@>@TC DN31H=+6#  +Qac ]G# #Mgmj_C!  +Qae ]G#  'Ogmi\@ 333Ic('d֚;;;B333Iːk2K6 K@(g֛;;;B333Ba(=(((H1333AH@ 333Ba*+k[HC =J#Ol*'eߣG'Z333B /mf%Kːg+ /mf%333Ic(333`T[]]]F333`(((l1 eߠ3 e? ]]]]F333Y|9V;;;^.ˇ(((BdY333Y|A1mOd[UuJ(((r9 6zs/:s;;;XeTe]eT333`T 333c};;;^5uuum]QY F+  333cbkm]T:km_[C8p]QY F+  333_>_;;;e!=333b'j` 333_bnr*j`\= :~֞TJx;;;^! =|nFFFj,ko, =|nFFFj, 333c|;;;^ 333afM;;;_T]]]zF  333`T>o6k|6%! ku/V]]]zF  333`R1q;;;e!H|;;;h. j_ 333_֝y1 j_]> :~~_y;;;^![FFF}A!OߦG jq<n˙u5[FFF}A!OߦG  333`U:}߬;;;e  333c˚uuu [ez  333_@AuuuwOkqcX<kVF9# gz! 333c;;;g! :w;;;^!j_ 333a5 j__ˣˣ> :|}|;;;^!hy*333pYkOu/hy*333pY 333akY333` 333fFFFOkk 333_>$ r_mߠ2 m˛˒ˏ֕]]]Ekm!(! 333f;;;h! :x;;;^!j_ 333f333Tj__(((]]]> :ziii;;;^!kmp_mFFFRRRwߩ ^kmp_ 333e]]]T 333e߬ߩbki 333_> tbm2 mv!km*5iiiSiii_iiiX ; 333e;;;h! :x;;;^!j_ 333hߩ_j__ > :x(((uuu;;;_!kim_muuue9 kim_ 333f߫v+ 333cq w6kk 333_># q_ktf[=kqaP3kq3t/ 333cp;;;g! :x;;;^!j_ 333fiiiq>j__ ]iiiV d(((z> :w333~ ߴ;;;b!kmp_mFFFRRRfFFF\Z5kmo_ 333dRRR(((U 333`M%K;;;Ngz! 333_@@iiiwQkp% kq( g|58;;;^=  333`M+k;;;e! :w;;;^!k_ 333c v,j__s,2333e> :w;;;lp;;;e!hy*333pYk|5 hy*333pV 333`q# 333`N'NRRRQViiiyH 333`R=}s8jm# j_ViiizM*G(((@  333_>_;;;e!H{;;;h,  (z] 333`dr`jm#_k!333_> :w;;;dN(((y;;;h![FFF}A!OߦG jb[FFF}A!OD  333_byM 333cu< 8p`V`FFFL5 333cdkm_X>j_8pcn333=  333_>];;;e!<333`%:RVkFFFR 333_G9xuCkm_[F!]i 333_> :w;;;_6_;;;i! =|p FFFk,j_ =|p uuug, 333_H@;;;u333u3 333_c]˕˔x!333_333i2 e< cY_˖˖2333Y|9V;;;^.}(((A1ߠ˔֟r6 333Y|:Ar a!e ?Vc333X|: 6t;;;Y'6RRRs;;;beVcYec333Y|<Q֜V333Id+ (g֛(((K333I֛j3K= HA *iߦS333Ba(=(((H 1;;;A1֓ˎO333Ba( V'K333> =H(((Ch*'a333CX333J /mj'HA /m\333Ba( #guuuL 'Ogki\@  !D]b f_K%  'Ogk_D# #MgmkkdH!!@= #F]b d`H#  #8,:@$ >_kngN' <[ db\@ #8, CQ9#MgmkkfM% :=! #8.,8# #FG'  +Qa g]J$ !@= +Rm;;;ˉ5  #8, (JM+                 !N}(((6  < WYF$             <J6     #F^a `R2 $JcjmmkicJ$ #8,:@$ 3@+5@*:>! #8, %GF%  %FF$$FF$ 'GD# %MfkkkfN' 2VcM% %===]dN' H֘u@#iiiGiiiVP*  !6,%dߦe 333<(((;333Ba(=(((H*֑RRRW* 9wuuuN :J333Ea';;;?b b(((?(((A\!b ?333@333I'e333=(((AH/(((K1(((rq*._(((Ba(N]]]I:ߧ߫ߩߦ:333Y|9V;;;^,gߦK_(((aK ^%333ax2MK#KHQt@JˑF  A;;;Y6x>R p$+r;;;^_֧V[ߥ/  333X}D cdMC(<V333nQ< 333_>];;;e! oh% qc D|;;;b'6o]]]d,. s ~c ~t+5RRRptJwv+#G]miiiX :z333\! :pC 8v;;;b! >o˕FFFo6  %Vuߝ+ =Xf`F#  333`f`J' +Kcg\=;;;^@ Gz;;;g/  333_>_;;;e!X;;;n+>|F 5uFFFjFAJ>Rz;;;`!HxD\ߩ֜M5333u2 :x;;;g,mgFz;;;_!$ouQwi,+!R}ߦd% 333d踿 j,>333g֕8 Z˗{C  :w;;;^! 333_>_;;;e! :s˒H \(((r('333gxߤq֝ h if/(((uRRR q%KˑߧR :w;;;^!Gː]]]m3 :w;;;^! >֘uuum=Fzv8  2M 333g] _;;;e!!pj9qd333_h 8((((((6 RF,v r' :x;;;^!'pV :x;;;^! ;V_9 $RRRD333\ud 333f;;;}uuuj/`uuu{yg` D!: i k. :x;;;^! 333_>_;;;e![333vcuF i(((d'%*yo![}D :x;;;^!U q* :x;;;^!!?@! %DA ,G\{l 333c˕b,Kiiiy֜H 2v˔_%(RU :x;;;^! 333_>_;;;e! 333R֖@MMFFFB\\FFFB%Z333B%d333> :    @> !H`ddddddd_G    8=!.R_ _J# !6,#DD##DD# !6,!HcdK#  <ߡG+;;;_<(((Ba(FDFD(((Ba( <K %6/!`c  Y߬A  333X|CRHRH333X{9   9e          ;;;Ks8 (Mbmk9XcU6Mr6  $F_c[UJ/ 333`u`bO* 'Jqt9  'Jqt9  333_@#:: Hk5HTUHGTN.3<FYbO* A\dX98FO_`J%  (Mb]NC32:G\bG  =YfcM* Q(((J'  /il VskM;߯ߡ= *eߦ֟`# 333c f,iiiIߨߨ< iiiIߨߨ<  333_M<hߣFFF7jk >访ߩ;;;333c+Aiiiuy f,*fsV B͛|˔l+ /i= AFFF} ?%_iiiI 9ߢ߫iiiI enM@ (((<: Rd# 333fR dR dR 333_u }>_k]M;;;YRbM;;;Z] e];;;YANiiiI ˠ;;;e$%yq%(((b߫FFFd% 333cg6fh 'y_ 'y_ 333f`#_kk;;;` 333cg6fhU333C$MxA  333c˕b,Kiiiy˒G X;;;C2{k 333e|5  \iiidA .333lQ fvckQr$j_ ] (((Y 333`FF|dj_j_ 333h@_kk;;;u_ 333`FF|dgx' sV 333`|D' sXgxck 333aM A֘iiigK 333_> grfkQ˜RRRx]]]a]]]`]]]biiiV:j_c֡u=  333_>=xaj_j_ 333f֞__ij~;;;o_ 333_>=xafu%tX 333`A%(((pXgtfk 333_@ F333fˑˍ>  333_> [3+|n @uuuu@55,j_e֥uuu} w]/ 333_>:waj_j_ 333c|M_u#j~;;;o_ 333_>:waY8Giiix˒G  333c[%Fiiiw˒G [8,|n 333_>  5Riii] 333`J  C֚|rRRRn*]]]d]KOD#j`;;;^(((;;;vRRRf((([> 333_>:vaj`j_ 333_y;;;wiiimA]V' j};;;o_ 333_>:va @ːguuui/ 333fpuuuj/ C֛ߩtRRRn 333_> !AOOmc333`}T@!$ dߪ֠gRwߥAd[ k9 333X{96s\d[j_333X|KMo;;;`*ViiiJcy;;;hY333X{96s\! dд] 333h_%(((c߫֠n333Y{8Cߥr|M333Vˑ?9iiidK$`ːCHC %~˗|z֣T(((Ba( '`CJC k_(((Ba,M|2 =d Hg_333N`A (((Ba( '`C 2 il+ 333f k/ :iiidl333B['Cߥc%Dߣ >3U_ afcK# A\_a_J#!@>1|]]]c}U !6,+5!@> 2] !6,:QA@_fT1!@>.16*+A= !6,+5,Q_ f ]J%  333c jaT.3U_ nk #6+#J___]F# A [a_J#   1z{;;;}ˎ=     'RRRD qFFFR         333]N  'jg   (((T֙V3334s6 ;;;O~2KV +Wuuub||faD +uuuRs{]]]ZA 6ˁ;;;?+iiiNx5  +88.$33$!  #          2QJ% +6! /NM+.QYG96( + NiiiViiiD C] daK# 'J`a `S38T [X YO/ 3iiic333@%Z(((C^(((d+(;;;Z 讴k! b*YߤC+ hn!OjFFFdA         WD6s;;;XRRRNQ :uuuU! >֗˒] >AUiiiLOߣFFF]]]n@   !.! ,# #*23'2# .(*//8% .5 23'2# <NRRQM9;;;\ߪy+ :w;;;^! 8e>iiic(((iii` (n賴\#];;;jTC!(((`fMA( 6i˘֝333d+ (%'C[U5333>333>=]]]H! !uuuL9 6ߟH ,]]]T]]]D="Z//Z >(֐(((]2AiFFF< 8ߠH ,]]]T]]]D:ߦߧߩߧ:  333`~K :x;;;^!ikH]]] s/*jwV ky'  b_2R֝ aH5333Tfiii`q}ːuuue:$333X;;;X%;;;Tx52pU ARRRf/TRRRWZRTY*dx[;;;qI DRRRf/TRRRW333<F$333e}< :x;;;^![n;;;XRbM(y%bnN% ]]]]zJ3X|Y*iiiZ333Y! /N(((}(((Q.  333^~=:v`2]]]mR2pcdxMMO{gX˙;;;l23iiimR2pc $KiRRRn2=FFFuo2 :x;;;^!N/  $%  333duuu}e9ux FFFd(RFFF J cl*_(((f. Jy\ C֚]]]RRR{3'uuuNcuuur˙߫uuusaRRRE$ 333_>:waky\yD _֛c*uMmy\yD ,kߩ˒Q+x;;;c$ :x;;;^!8y˖i$8 Yiii^uuu`(((aY<,57#  333cg6fhU333C$MxA // $FFFbRRRuuuT\yFFFL @fˑV K ~9 1/  333_>iiinj#Jg :x;;;^!%A /cuuuoy]]]jFFF? 333`FF|dgx' sV!333OuuuRRRRRRM$1|j(((aMiߣA :RRRs/ @Y xiiiuuu{WA 333_>@yc+333oY =|D ={$+333oY .q r2 Jg :x;;;^!%@ 9iiirFFFtߦ C 333_>=xafu%tX 2, .u {߮;;;^,;;;d333iii333333 d$ WFFFZ9333i333j9 333`|M*_e`uuuq8,]]]m o2 gvD`uuuq8 fyR +x;;;c$ :x;;;^!8y˖g#!(((?Q@:N ghhV(  333_>:waY8Giiix˒G .2^˞`>g˗֠;;;d5  (O^ YJK(((\zsZ*  +;;;Z;;;Y+;;;^˗nFFFi ={o!333j˗;;;l$J߫t. >{oG߯pR:=FFFuo2 :x;;;^!N /  .5.  333_>:va @ːguuui/J֝~pon/ +dN< cߤˎd3 /. 5K` _G/W˙ߨd! qߧKi vMx h(;;;`~jyQ${ߨMFFFV߬8 $333e}: :x;;;^![n333X{96s\! dд]333MD CmiiiyM'D[bY@!  5֓ߥߧ֟˙֟ߧߤq, >G+!@= <>!<G. !AF(  =d/UjmjibH!;;;[֠u(        #333E s<  YC9u;;;[ RRRNR    0ngrH  4[ 5uuud333>+rFFFG^333d,;;;; j' +VyhV%3QJ%  1;;;9( 1OO. /iiiUˍߦߥuuuh], %2+   '>JC/ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normal18.dfn0000644000175000017500000055201611357170241022536 0ustar keeskeesf ! " #$-%;&L'\(d )n *x +,- ./ 0 1 2 3 4 5 6  7 8' 94 :A;I <R=a>p? @ABCDE F G<H<I$< J-< K6<LF< MS<Nf<Oy<P<Q<R<S< T<U<V<WZXZY(ZZ7Z[GZ \QZ ][Z ^eZ _rZ`Z aZ bZ cZ dZeZ fZ gZ hZ iZjZkx l xmxn'x o4xpBx qOx r\x shx tsx u}x vx wxxx yx zx {x |x }x ~x  ) 5GX     598</        $91 5,       3=. Aʹ|FFFoʹu5 69 829 QP: D^eT,1E?1FH6  FFFMͿ~6 *@6<E(  Jg.$ CA#:Zc[=/@1:\heU.@^geY318% 2iZ';;;XR =ߠ@F˄+1c]]]wiiiwi9Rߤl9\qfA#  NCJsN'cj*=u(((m3  8֕iiif<Cf;;;FM~8 333d跧[]R. cr3/333hm3 3uy(((h*FT3~_`e#,;;;hX 6 333=!@(((A* !lK 9mq< 6v}: ;;;Oc  @;;;_$ ;;;[RRRO AnY;;;z(((>VH FߦߩJ auuu;;;^(FFFgT >sHXiiin9 6ID;;;J8nn8c߫e :z> ;;;G} < (iiiK333`333:  5z;;;h!Y>  Mu3'uuuNiiikiii{iiiyFFFN (((a(((˂t9 @]]] f 333^333a M9  nw%1333vd,xJ%k;;;m5Rl!*iiifYuuuj, :z> )RRR?C<q˚O %=D  /z;;;h!Q= 'FFF<>@FFF<6 1'((([ˣ\9(FFFYw3 dd% (FFF<6 <Vjuuuj..ˇD $JpRRR`Ai[5~ߩ[%Yߩ= :z>  \J  %];;;9(r;;;l' @|}5 !X˙GGw=1WnFFFd2 g(((| Y> Xv: Q˕D (˂֗RRR9333<3  /RRRiz> 8rDC|ߧH :z> '|o3D/`333G,uuubFFF_'Rx FFFt9 T]]]s]]]e3  <n]]]]]]miii_W8=FFFu.i333s( FV+AdU8;ߧ߭ߩ豴r.2UjiO' J֛(((m'8u~DCߧH :z> T˓dCuuuw: 9ߴŽe, NO 2֔߫ˎ\!.VY 2 ve3%FFF_Ѵ(((h'l;;;j# Dߧ`'3335 3 <\333mK1 !a;;;Cdd5x֞X$X֟> :z> AiiiqFFFo6 (YQ <5 DuuuQA 9ˁ$.Rp;;;^]FFFRRRR =֚_k;;;l$ C_  _;;;e+ $=6![333C'(((m֛J*uuugUk. :z>  8(((yd*38A|[ Gdlw]]]] %FFFOmY((߬rR/;;;I]]]eAsY @ 333˛k fRRRo. HT :֔ H Q֕A1TgfN'  /]]]L]]]L/  >zRRRi/d֢֢e :z> .{ Y8?iiim ;;;K(q;;;r/  <@ b[6fnC 333JN$c}qC +]]]d}9 T> X> 8=# * Y ;;;G;;;GQh :pp: 6v}: U{(P333g*X;;;_ 8֕9 Be2;;;>333I 1;;;`ߧf%+RRR`<1d_!Dr(((ߧ(((78sߨXp;;;i' %FFFi(((^ FGFGKssK'cj*\j' >ߣ;;;i9 >333G@O= 4/# /$ +[ U# 9D/ $H`_F! 9[hdM31GXG#jq%3FFFrVkV %GG%!?=9YgY9/@1/TjpppkX5A`lhT.<A%     XX     @zHY;;;l/(((?333Y.        #DD#c f!.FFFd֙M 2' .e' 3`#  (?3<A%           9Vink`D$    'OipkX33 @3 'OipppnfH  !Fah cN'  'N ch^A2MV99gsˑlA +JH% DcnnfO. A`hl kdK*Dcnpnk_G*DcnppkX5DcnppiM#333Ib$Huuuie1333E= $dߦm+,mː]!  *FFF\p=NuuulzX!% b` ARRRf>2kFFF\. A֜333mN# Aj% AD333`q%Hs< ;;;Eː= N[_K ,JY B#  *(((DU<  3(((\N;;;(((ߩߦUMߨ{@ Yuuuf16(((pKYb!Yr'YE 333d˛tW6 :iiim n( + M d sˣ v%333\uuuRRRg%*k]]] g  <`333pߦ= =QUUUUTJ2;;;CtpO/  Ug%   6RRRe## j333xߪx [Fv= _;;;\x[Q333Q* 3J @#_;;;s9 9pFFFl._;;;K/+#_333Q3.!333`uuu};;;gU* JߨX+ 9]]]vt(333^RRRFFFh%.|p2 F CDFFFG 1;;;`uuuoi>333<3 %T qy X$K ` Dː~uuuo{˓;;;`! r˟k_FFFQd]]]~G_;;;e! 'qJ _;;;kdN' _uuu ~e[D!;;;Lm( c g1 cߨOj߬r `n+(((B(((DF]]]I;;;HtF$ /`xT$2[(((@ *333iw> _FFF|333~]guuuwXRRRrd( @| uuuw< _U;;;e~#_;;;e!H~]_333C_9  /]]]P;;;r˕N;;;c]6RRRu s* vz# 1 i j  (E E( %E(((G.  Guuu~|X2 .333N(((i(((n(((n(((n(((n(((n(((eL% Ck(((: @`e֞ߨR5(((~qRuuuoiiia(k333333g_(((p.333gz _;;;e!H__333C_ÿ˅2 #6iiiie n }2bR/w ~2+XU   '[RRRpRRRgN;;;4/  +ZzqG @s.;;;\(((z1@]]]yߨjnߨ333`  :uuuu]]]u8 _;;;yQ(((a333A _;;;e# 'pM_;;;kdN' _333bF@/...[;;;i;;;c]֥95RRRs(((u,6{[߮:8}֢333p.#!::1Q nw9  *uuuOiii\iii`iii`iii`iii`iii_iiiYFFFC#333BFFFmdA$+RRRTwU333^(((F:}uuuiiiyXciiiyuuuhuuuhiiizb_;;;}M=qFFFbT G$/D>!_;;;s9 8kRRRl/_;;;K/+$_;;;l,  ;333qFFFX];;;v/[V.viiiRRR}2$ixF 3aW2 DI#>b333nߣ6  *+++++' (((@ooO/  [h]]]X1jRRR333r9 2FFFs G//HFFFu3_]]]~FFFT, o| |tu;;;vߦD_iiiqtRRRwߦQ_iiiplbF_;;;e!;;;Kuuuj5 D֚`RRRY333u/_ ` 8ˑU(((L(((H;;;Viii^! +<5 #:6!$kK[ iii}t: JߧQRMX]]]f1:RRRiKX֛]!X: X;;;_ BRRRiAVl, RRRJR . kj/ ,iii[xU(((EH cuuuc$   iiiRG 333f:6 k˒RRR[. >֜333jK  >9 >333GDblhU1=\hdJ%  *HA! 'KdjdK' /D8 'GF$X˒ W.KG#bv`guuuZ#!FJ+  +KG#CbnpncK( #D`knldM*Cbnpnk_F(Cbnppm`A<A%      C%  'HF#>C% >C% >C% 5TR2>C% AR=:UJ#@O:#FF# %Hcgpe`A #Mippj[9 %Gchji`A CbnncH% +R fidH!FcnpppppncF#FF# %C>!FJ+ .KD!2kߦ;;;Z, A333G(((KK A333G A333G A333IDuuujw A333G AˏRHxK >QKK9 oߧj2KrR9 oߧk2 >i1 .k I << KK333GC C(((`',FFF_@  5(((nHY;;;_333cgY;;;_Y;;;_Y;;;b2GiiioUY;;;_YwH>]]]rgXzNgg>]]]k r5 g֙C >]]]k(((p6 Xd#]FFFS == gg333`\ JOXD ( qtv333w֚C_;;;e! 333in_;;;e!_;;;e!_;;;uc]]]pq*_;;;e!_RRRrJG(((yn_tHnn1;;;m ~y o'n]]]֣d1;;;m ~yo(_FFFRRR֛A (uuuf333yFFFDEdz˞udFnn 333gc1FFFsu' ,(((v(((u+N K%,A=!_;;;q53333un_;;;e!_;;;e!_(((;;;t, _;;;e!_n_iiipCnnYJ%*R;;;}Kn;;;OXFFF^YJ%*Q333N_;;;{[O+uUA<$ (rR nn 333gdb˓J QY fiii|G!_;;;kjk;;;n_;;;e!_;;;e!_֩y. _;;;e!_iiin_RRRp>(qn333`;;;AK|gn;;; d333c;;;AK|h_333ߧD  333]T,_> nn 333gd 9iiitxJyFFFt2333e# %JdeO( _n_;;;e!_;;;e!_G_;;;e!_333 (((n_333 ;;;rR}n(((j|%(((enH!;;;i|%(((e_333o+>r֜j1 _> no 333gdj˖c333f| 333<;;;J_n_;;;e!_;;;e!__!_;;;e!_;;;qY(((tFFFo\333vn_;;;qY y n(((j{$(((enާyY!#]]]e{$(((e_q C(((nh'_> nr#333jd >wuuut: e;;;A;߫;;;b_FFFpnp;;;n_;;;e!_;;;e!_FFFb' _;;;e#_;;;g15(((LFFFL81333ln_;;;g1<(((v(((n;;;_(((>Huuu{hnFFFjX:333e(((=Huuu{g_;;;;;;z: !8`RRR|G _> mw% 5;;;z`omUF*6b;;;g!_;;;r65333vn_;;;e!_;;;e!_;;;֝m, _;;;s9_;;;e$ #333in_;;;e$<;;;rn[F#'M Nn;;;s6 [D#'N K_;;;sTvv((((2 CA>mFFFY_> `iiiU%.k֠Q DA .(((nzx(((;;;d _;;;e! 333in_;;;e!_;;;e!_;;;lD_x2 _iii o l cH!_;;;e! 333in_;;;e!>FFFrn2FFFlz~v ~o(n;;;i!1;;;lz~v o'_;;;e+2~[*ruuus˛R]> Gߧ~v˖uuul5#us!:FFFkFFFRX;;;_333agX;;;_`;;;e!X;;;_%!Ruf#X@ X;;;_333cgX;;;_A]]]qg>]]]k r5 g;;;b333G JK >333Gg;;;g! >333GG]]]k. >= >333G(((KK >333GDuuukK9 n֜xg1K(((K6 l֜֩q5 >333GV6 JwoH =e( ,fuuumT $YW# !A_jolfO/<A% %GF#<A% !};;;g <A% 3U]ACbnppndF<A%  'HF#<A% 5QH# $Fbjni[< #FH'  $Hu{赴}s<A%  DXD<\ki[8=H1 @_inhV6 #2#     =y;;;`       Ap333E      TX !Ab(((eiii\O+ Hi,   #CH*               !FJ* #HX@2MA9VQ/5RN,FYF! %K[D2VkppppppiO+ A`miM##@A$#MikY6#GM/ @ H6!@=:A% D WG$!A@F ^$UߤF 3uuub: $ߞ333l8@uuuhT 6\ 'i3 $auuuJ =F AQFu+XRRRa/ 3d3 HA =333GRߤGHC $DD#%FD#M֜J1FFFr r$_: ` z5<;;;sN1hT3`RRRb+$hNVF Fߥ(((i%F: 3RRRr[+;;;cNcYV;;;^5oHd[EDDD5]]]ss#UD/;;;ss% 2 z\r(R]]]}vG5Vkoux*]T#1]]]kz> #T> \333s/Ck > jn'  'p;;;e!  Vr*  jm%JK IKj{D2vn.TQ8(((v|1  c֝X 1p֡ z5 _Qj[M> /;;;qߧT19!#G`gX6kucM(  C]hcH#>[r;;;g! !D_f]@,߮(((Y'H`ig[=kmbO+G FG D Aub˓uuuw_|333s.=FFFu}5 *uj#Fuiiiq@_> U l  U s* Lk<mj. 'cːB#];;;h!'d֛ˏ\! Hd! 1(((a/m߭ g,QQQQ!s]]]]`(((N 6 .  8333u˒R_> :quuuk5 :z> #(((dycߥC %q(((\naXFFFBNߪ֥;;;h!U˞G HZ (((Uo1nTeefeK֝ÂvM333wRRRiiir8$n֣VmR .zg!_> #mO :z> $֑C, ]> !Uhk,mu.(]]]e rb(((E( 333_333x;;;g!#;;;g  \,>(i֥ }!m uhnnnn* sG#]kUuuupC`@ $ky, _> ]h :z> 5G8'FC!K}ww6kr5bu65~˙j% #]]]bu8k;;;e!,wFFFIgs'uuue]]]\kq6qlnnnnX u$ 6]]]uA MxߪFFFq=_> V֝(((N$ _> AFFFj, :z>   *;;;_A kr9i˗x33~֡r. !FFFcy>q;;;e!*uuuj wp@_ion8 j`%bknnnn3RRRuߨNj r#Duuuq˓`Cr(((u6 ]> DuomiW6_> (333lːG :z> @uuuק[jRRRiiic'%FFFdn J* \]]];;;g!(((c ߡ?_ijˢuuuwKj_$_knnnng(((t+ >wߦM+RRRac#,xb!V9 (333dq%_> dY :z> =ߥ߿g#aUQFFFDAˎ;;;bHߦGXc!|߰]]]_, cY!Xcggnn 9iMV(((V% 3i' 2w* =e(/b$_> AߡD $(((]uuuT Db%$_(((ENm333J [ːr6 >H =wa%HA>HKKon/6 1$ DYH$  +OY>=H1CbnppppppkX3_Q9>#N>  +QdikeT/Dcli_@@]jhO' 6XjniO' A_kk\9<>![]]]D !@= <>!#FF# |k    ]T# #R> BY______YB       fiiiO  6RRRxdUFD: 55 Q߫: JK <ߢDCl*+_gkkkkkkg_+*exQ =f(>]jdK#!JfiV3%25333352% %H`hg[<=D*        !FXD AXH##FF##FF#[= ,8#  :]KKKK <> 'a333C =ˏ> gggg Uuuu_!6t;;;Y ]iiiVnonn    .:2     _* :w;;;^!(cnp'/MG% nn!H]_`_RDK]bN( !Jbff`N* 1M\\M1%MdgbQ65QbgdM% !CQR\_H!>]f]@AFFFiFFFvj=!@< !CD#!DJ+.JA!DH(3D2*HD!CT>%GT=!DK,/MD =[fggcN( dn :x;;;^!ni #%  nT;;;hRRR<nnJ֠(((ߦf(Jh+N]]]g]]]gM Jςn\'#Xm(((KHiii BF֘ߡ: /uuue1 H@JK @(((a15FFF_: Ca/>ni=1aA 3ˎcKr+ @333c69RRRa> 2]]]Dri :x;;;^!iu/ Wiii_iiic333edNFN333=$n;;;=nnf˘NfRJߤ֙G333`[T;;;`e BFFFYˡ> :֓/cY%eg Cinˏ< H֜i{{jߧF +RRR^˗b# Cvy֚@ 2ߠN@ \ :x;;;^!] @ ]]]O˓iiiyDnuuu˓\nnm{((( enyh#RRR^RRRvxiii~333c# 333g(((k,(uuud;;;;;;e!njFFFG* ]]]Z;;; g1 +333m:j`*nn+ v 333 u%1;;;suuu333s.@RRRp v6 (uFFFRRRu'=kw,*]]]_F :x;;;^! D]]]`+%y˓Dn߯1 nnkq:}}@}nn|:vl1r˘k*,t˚}2 333gr6c95yߪm9n;;;e!n 6 T|9 i;;;o1kd+onUߧN]Y[iii(((OHߨNG333iiir>5= :x;;;^! <8  2ITTc iuuuek]]]^T$n>nnj`*oo.onno+dk1v˙q/2{}2 333gr8f85˙m8n;;;e!ns@Y];;;s6my@n.333sv*5RRRsFFFt2cX#uv($rߪk*!f֟O :x;;;^!N֠f$*,$n v9nnj`(nn.nnnn*`k#FFFa333e# 333gFFFh+(iiidFFF;;;g!noiiiJ|k$V]]](((H%h;;;nYRcbJxqFOߨOT֞]3 1d :x;;;^!d2 g333`(ggd['gg+gggg%XcMK 333h[V;;;h!gg%r;;;\ AߥGTg1;;;s(((u, 8]]]twDu]]]s8 .iiic]]]a,Mw(,]]]fh$nl :x;;;^!kpKV>p2KKHCKKKKKK>H XvsV  333h֛g('d֛;;;h!KK N|A!aF,lKRNX֖DAˋX 5ˎ[=_֙3 kߨO2a$dn :x;;;^!nd#FF$%JYD#FF#!@> #FF##FF##FF# <>!<\kk[: 333gw_D!  !D_t;;;g!#FF# %Mfk\: %MeeM#,TghgdK# =<#<9 6<!CT>@UC 9iiitv(DcnppkV2_+ :x;;;^!*_     333gr(  'q;;;e!      cߨO T]# :x;;;^! [uuu~U333_\[;;;_+RRRhv* 9|: 8u;;;Y 8: (((HC C333I.JKn谿}2 (h;;;C/s谧sN %C?@D' =P@1>2.7$ />2           CXQF:# : K@ <ZWA %M_aM#8U ]a]\C# DFFF333@ :y2Ny֖: #cN *\mˏf3 333I(((ITh'@v; DFFFT*j˕]]]~;;;e8  (FFFHY3Fߡuuuzߦm=333JuuujK% q N#[֞ H]߫ uuuk, !8NO6KFFFQ(by=9n`3O֝9fuuuV( :rߨ333T6 QRRRW333XdpprJ *r333v9Jj,N]]]i]]]gMFFFFXu]]]zV VߩFFFo}333c$2e˔֞s6  $Df |ZBfRJߤ֙G 8֖O,lyHb=>QNMwz3MuuuM;;;52 nyh#RRR^RRRvxiii~333c# C;;;B6xFFFiiii2buuuyq(,MOGv|8JH  0hr߬wliiiL'n|:vl1r˘k*,t˚}25RRRc( 1|֣T]_k֗r(((~i..]]]Zuuu_.(F(((T3!no+dk1v˙q/2{}2.(((A#  c`Muuu}a/OWVNVRRR[֖֗RRRW: ,n;;;n:nn*`k#FFFa333e# @((( urk333F'CT.;;;gRRR֙F(99' %Nr dDgg%XcMKRG[֝]]]v6F}RRRf! (((C: KK>H XvsV DE2v#Mmg+ (((C9 #FF# <>!<\kk[:!H`dgkngM#$Ny(((h:cjߥ貧w eK$  %NinnnnmbC   J֧FFF\ 2GQK9#UV  <333f/<\gU. deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normallight18.dfn0000644000175000017500000053601611357170241023570 0ustar keeskeesf ! " #$,%:&K'[(c )m *w +,- ./ 0 1 2 3 4 5 6  7 8' 94 :A;I<Q=a>q? @ABCDE F G:H:I":J*:K2:L@: MM:N`:Or:P:Q:R:S: T:U:V:WWXWY(WZ7W[GW \QW ][W ^eW_uW `W aW bWcW dWeW fW gW hW iWjWkt l tmtn&t o3tpAtqOtr]t sgt trt u|t vt wtxt yt zt {t |t}t ~t  ) 5HY                 . ,<>=.**$/$>NG/=T WM, %>61A>(68 %A<<A% '/% '/5QZQ6,8T\WF% 2O\]R3*2=333>'` h* 3xߜ1+FFFI>@(((`{֛]]]eQ$Q֕333[.'`' OgߣRRR[< =@ !\//\!:V333]i333<#  (]]]N9 FgkF ==8|b**auuucA9FFF_D(((P;;;R6s{: QAGzQ@ˉ> 6RFFFw]]]^(161FN+mh\;;;X!.mu1< eiiiiii ~333˗ h$*c;;;hH1TjR(((|mA333V;;;m֜HJKNYYNR/ [ݴ|>,FFFb c *iii_(((r63 siii_* 333WZ  $p1 (rߩT!]]]]a[;;;X! >ߝj֐(((?(,%_FFF;;;e1 <ˋ]]]tߦ333TY]]]x:+PP+!aRRRg55RRRga!=;;;zRRRRRR[( #8vާ].! D֗T5zgfz6 333WZh]]]_* $V ˎ@ Mˌ(((][;;;W!'*% H OT;;;\% URRR{< Yuuud:.5khgk5 5g߯Z#FFFBRRRURRRcFFF;;;RRR^RRRR;;;=\o: 9u\\ݴ|<  333WZ2;;;j_RRRC}*CkRRRrp333sk$[;;;U .vmqu. ']֜f1!CVi aO1 /yc \ : GߤYVߤJ(ߜr(((< -* (333ae$ 9u[Yݴ|<  333WZXTuuuL+*;;;b֡]]]KU WNFFF˙F O (((`(%Q]]]liii˕uuu\5  Y֢NOˎJJˏX*:(((D˂T:@VkdT:,HWU= @|X 9u\\ݴ|<  333WZ<]]]hiiie5 .fuuuzߤC 3'AC,'#m(((J 2iiiis֚U3t333~dt֥HRߤ}C Dy\ (k޴Q f+ X|@ 5zggz6 333WZ .pT %k֝YD ] a ]t]]](((K +]]];+ (;;;hiii]]]{˙iiia;;;> .g;;;sY'iߧpQa( F֙u/68 QˎKJˏXVݴz:   /333E(((U(((Q(((<   $e333a(*iii_(((q55(((qiii_* 333WZ%gm+ ]ߧ^8333gm% . ;.f˕xi]]]y}9 uuuBuuuQn333QT{xߧpQd( DGG֣]]]}JGߤYXߤJCz, %3330$   %3330$  :o\\mKn\ 333WZ_֝FFF_2!,1+>R 333X\;;;;FFF=UtJMˌTbޛߩc2 3i;;;b@Driiis֚U/e;;;sFFFq߫RRR[+3hihk5! 50;;;?FFFB;;;;FFF=K֖C 8i֛ߦi8 333PU>;;;RRRiRRR[RRRP(((; 1ﻂb(((f;;;oe3 333RU ;333:?FFFH,<z5 FFFM%FkrH ==]]]?% 2uuubA333== /! /$3/2` ]]]~j52/>SVN/9T][Q5!,C=M\\OY;;;P /! /%6P\R8, 'Mfib]\R9<U\\Q3 ,   N;;;L'      +(((diiif==iiig333e.3339A      -! Fˌ c%%f֗H+  X//\! #>:<A%                  1Q__XA  $>:8R\]]`cX88RZT9,M\]O2,JSA$@UWYWUA$88>X_]R9 =U\\\VA# >X_\\]VA$>X_]\XA!>Y_]\V>%](((.  .f3 %֒(HqxJ 2333_iii`>  #iiiLJ9a֗ߢ_6HJ <uX$1b|ˌ Q# <ˍd@ <;;;/ =,5t]]]}]]]d]]]W]]]G& *huuu\,333:]]]R]]][]]]\]]]aRRR|߫]]]b( 8mː(((ːr9 XRRRt333y]]]_/ 9M; <M8'ﺎiiii{uuu_*Dduuum vpt]]]niii]9%o o(T333]]]lK 5333e֙;;;g(((c]]]d֙1 T333zFFF];;;\RRRdˎ|OT333{FFF]FFFYFFFTFFFB% T333|FFF^FFFYFFFS;;;?! 9ux<'[333j= #'*:xߩbUߨxMt֝U1xMC{M(Fdk/%2666665/  /uuugcC'*H6=p{tp};;;[,Dˏ֚GYݧ|]Cj|;;;U(h uO/'2HU;;;=!Yݧ|Y+%1Kw|>Yݧ|Y,#! Yݧ|[,#   9ur2CFFFg> *lm< ]֝b1\^8up%Nuuut\, ,  3R g֖֗ O#'bloooooojK%333PˌgO1  +uz3' awFFF M!e f#Xݴ|CAFFFr;;;YJy< Xݴ|> 1q cXݴ|@Xݴ|D 8u(((333`U6' fwb. DˍdQdT1xF5f]]]a:(((::(((:<g]]]jkdD# +֍#'J fuRRRjc6 @o333_$ D RRRrFFFw  V >v |@ YݴY:dz(((X \zKXݴz<  6 yr1YݴU$ Yާ~d9.$*rhC G֛333o333YS2 gC <]]]tuuuuuut@  Y333wwa;;;?FFF@;;;?FFF@ 5xFFFqb< 5HMMMMMKD.#@dRRRrc/ dOU]]]s{KOv;;;Udߥcb֙f\ߩ333p˓ߩi;;;W;;;e+Xݴ{< i|: \ߩ_WS >#[uuuxgaX + 5Og uiiib1_iii_6  =qh$ < =  6]]]^V.] -.] - <|F!  %((((((% $J 8 8 l*Y]]]t|J!urk;;;V  :onm r< \ }1 333Y(((`#Xݴ{< `޴}= \;;;- [3333 :}Mfxw(((y\bKQ;;;333R1R]}= %Y333iX8 > QYYYYYY Q=:]FFFgwY#GァsFY q'o_k;;;V b֟֘֘֞c[˕j rwQ;;;W333f+Xݴ{< j|: [˕aYU@ Y޴bVC!R~[cFFFY.D y2 6iiii(((j+^iiiuT,MRRRs] 1jˑ d! Adjuuug]6*+<dliiifc> D;;;W,Yve 6FFFp]]]jYs333T3RRRmߪ֖֖֚֚ߪ]]]l6YݴQ#%RRRRu;;;W \zJXݴz<  8(((wm/YݴQ Xݴ~N  VX]FFFuD't|9[U(((W]]]m>6333nFFFTGjn<      9\;;;gh+ < R X X X X X XR> 3ˆ(((jV6  5nb%Y~v1*jr֘QXRCCR[Xݴ|>6;;;Z Ky< Xݴ|> /r aXݴ|> Xݴ{< .A<1GF Qt@Nr/.;;;hRRRh3Yg@]w XDiiifT %3330$  %3330$  /Nhˉ.  6y hK, 3] Y1 T]]]~iiixtq~tRRRc9 .333iuuulA@iiil;;;i.Yݧ|Y.5cy;;;U(g uN/'2HX]]]A$Yݧ{Y+$/Jw|>Yݧ{X*! Xݴz< up(((n]]]nc' 3uuub(((z]]]s[ C] Aߢ }zC/hb%;;;;FFF=;;;?FFFB$6288# @D @֗uu< Cc`C U(((~FFF_FFFhߥK8FFFcˎ;;;g333`]]]e֙2 U(((};;;^FFFYFFFdQU(((};;;\;;;X;;;UFFFG -Qݴw8 (((E c2 Cd(((a/ :\3 Uˋ֖V  3֕](  ;333< T;;;T   9= # `˖˖333zRRRy((((((b =f8 6`< >nV#3dˌ Q$ >֘ eC >\ :̧e' #DX]YJ*3Q]ZM+2,=T\U>99  /! Y;;;P68 5iii^{cjuuu{K5/.5@Y_][Q8 >UZ]]XA# @Y_\\]VC'@Y_\\XH+.(      3339A 9(((cuuukRRRduuuf֘X%        +.V]]]_uuu`[=.DTVRF1                    =U\\\VA# ,''..(,'.'/<(,'<A%  $@<9<# 22 <U\[]T8>Y_]YK. =U\]]T9>X_]YG* $DX]YC >V]`ffb]XH*, ,'2*112c|ˌ Q$ 8ﻧd'%]: :̧e' 8ﻧd' 9̛]' CaQ 8ﻧd' >j*%fA =c% :: /`vk\,  =]]]_C1c}m],  <333`9(c > .T=333= 8ﻧd' =iiiV1 >ߟ.6;;;d֙;;;g(((c]]]d֙2 Oݴw6 5pTQݴw8 Oݴw6 Qݴw9CuuugGOݴw6 V` YߧYVߧ[RU 3 gFFFh g]]]h j. T333|;;;eiiilm6  3(((fRRRg g]]]ii/ T333{;;;gq]]]_/O|333rpFFF<!FFF@FFFSFFF]333~;;;FFFbFFFVFFFG ,U;;;ROݴw6 FV! ci1(g(((tQ1'2HVRRR?#Xݴz< 9u\Xݴz< Xݴz< Xݴ|NJ]]]fc$Xݴz< \MGx_\K[_% g;;;rU3(8]iiiocYݧ|[2CU'fFFFpX5*8]iiioc Yݧ{[3KM;;;Uiiiv\9<<#  !,[x6![;;;X!Xݴz< 2]]]f333g+ >ve Kz= Xݴ|>    9u\[;;;X!Xݴ{< >vh! 3]]]f333g+333W333i.\ߩ(((](((V(((W(((V(((]֟\Xݴ{< Xݴ{< [{2 Xݴ{< Xݴ}gz xix\Xݴ}gxq3]`333W333n2 =r^[֟ g333l< 333W333o3 >s^\333;;;lw]]]c.Goe< 9u\[;;;X!Xݴ{< # gq=RY ]RRR[% >TWD$\]Xݴ{< Xݴ{< [;;;`Xݴ{< Xݴ|H@(((n;;;lAGu\Xݴ{H=pp@f` ]b+2333n^\sM ^c+3333o`\]]]\ RuuujvN 9u\[;;;Z#Yݴ{< Kd>iuuuh8 ;;;V333i.+G[˕bYYYb]Xݴ{< Xݴ{< Yv8Xݴ{< Xݴ{>9iiiT]<s^[֟bZT9;;;W333p5 @s^[޿yuuuv`8_333v{9 9u\];;;d,\ݴ|< .;;;hRRRpuc[M?m]]]xZYݴQ  Nz]Xݴ{< Xݴ{< Xޛ m8Xݴz< Xݴ{< :u\Xݴ{< >iiig_]ːR`VYݴR! ]֚TdVYݴQ.Qruuuj< =T 9u\\yDj{8]ˍDHx= >333n]Xݴ{= :u\Xݴ{< Xݴ{< Xݴp z n8Xݴ|> Xݴ{<  9u\Xݴ{< Jw]F333sAJ]]]q}= Xݴ|= G333uA Nuuurx= Xݴ{=]l'  g\ 9u\Op( =333vd+ r :̧e'%^= :̧e' +m@ 1b|m],  :̧e'3f֘|C :̧e'Y/ 2_fD%^=!Tl d8%(((TQ <TZ\\YG*.((..(f޴{9 .( (D=@Y_\\YJ..((/.( 'A< =UZ]ZT9.( #C`{P(((+.( #>93R]]R5(/8T[]YH* $/    /(((nq/          2`uuumH       9 U6U ^^uuuP2(RL*   '!             2( #,528A* <<9: +=.+HY\\\]`gdJ!#H_\J+2,@X\J% !:91>,, , 2J=, , , @RRRS,$(((QGD+(g5#Y2 3X 6333_v]= G] :]1 /333E![ߢR!˂FFF\5 =(((?=333= 6_/=(((?8333983339NOH֚(((l(%eb,![t2 U֙k3 /bˍQ3pV.FFFHFFFVFFFYFFFYFFFYFFFd(((ߥ> ]RRRliiiO1 @ߢO$]]]E]]]_RRR|;;;VNˍuF Ub U;;;QU;;;R(((T֙(((T$U;;;Q8;;;98;;;9 :nj$o˒G Ae 6333jp/ KxˎQNˎnOAro1 !#$/Y k#]333rH#.RRRad 8r;;;W Ai]]]|xiiia< /j+ [;;;^/  *h;;;X!  5j9  [;;;^/ !5' !5%  f}@ 9ohcߤH>]]]itbuuul_!!_RRR};;;j9 /us. [;;;[%`uuud3Y;;;T .FFF\z]b֗(((`*+ Diii?,JXQ6]333|iYUA# 2O]V</M]q;;;\!8T]O2 b5  6MX[Q3]333|k\R6 1# 1# Jߤ`Yk93]]]f333h+Gr֟RRRj(*nlC#d333l6 [;;;X!KKV;;;T 8U$'_8  (iiiPo=cߣa*Diiibߠ6 ARRR`333c NnuuubD1(((: %Vr֑$cmF:(((;: ;,;;;gRRRg63333hiiitY(R[Y2  3 RT֙uuujA[;;;X!2iiic`V;;;T  -jH# 'La+  /ˊ;;;wFFFX#gFFFrqY 9ruuutw8 8luuuu|;;;b!A֗iiin8 *]]]`uuuo6 Mzߨ333f%g]]]{h5 R;;;PR;;;P]\YߤkQiiii(((mNmm: J n U*DoˎO[;;;X!dRRRa.V;;;T  =Tf{5d֞rCR;;;xk3 WߦtJA9 XvKX;;;\!_߬VR{q!;;;R dynd{V{O[;;;W![;;;W! =r ˎG*c֛f  +rFFFq= >yg9;;;j`![;;;X!QߣGV;;;T @`(((miii= _333o8!mK'FFF_ x3 (]]]^ z5!f;;;Y!(f֛ߣ֜(((M .iii__!=RRRiM6rZ3r(((;;;i;;;Y;;;X;;;X;;;X;;;R;;;A# [;;;X! >zOV;;;T (hFFF ߨ֕,V(((t(((n֚TJ o;;;^w. A֖333q333w;;;ZDߢߥ(((r;;;jߢ3 5qUYuGU;;;Q;;;PTU;;;R[;;;X! 9tߠ>O Q 3d(CeR%YA 9333, [;;;X!!(((L<V;;;T Oe( >\%#Yˌ(((4Nn(((HRzuuuW+%^=#xL=(((?333<==333=[;;;X!+.- =A% 1=**3Gcib\\\\\VA [;;;[% #-Y;;;T <SWWWWWS<#DWZ`cU3>X]ZU==T\WD!8R\``M% :R\\O1(/ :ˍ˖]]]qRRRn˓y6 ,  +, `;;;X!   ]333rH$  9t;;;W ,,        J֟\`D (r;;;U\]]]kiiiP 1$]]]Fiiia]]]{;;;W<SWWWWWS< AFFFz opux6 :֕PF] /333E$ YK 8uuuW2 !G]\J+@Y]J%  $CUYYQ91+     *, 9=$ *% $=9<<=333= J֕;;;< 6諧c';;;<֕JRSU;;;R %FFF0!'`CNݴw6  Ca(XY [;;;X!        $;;;JQ    3s.Vݴz< ,|{8XY %8.[;;;X!2CR[O8/AUU=5FR[R6.M\YD% !H`c`T82Q]]XF#/6@NC 1O[K,U333N'#,! $'+  *%+35 !5..'''/JUVXU@ 9k`Xݴ{< b޴}@  X\'5a֎![;;;X!=;;;FFFwˎˌQ?iiixmF@FFFba3HpT GiiidߧH@u@ 3iii[]]]Q( 1. 9:(((55 = O$ 1Tߜ,<M! MG /uuuT2 /֓U#,_ߜ$ 6]]]Q1 8n֎'!ˀ< A|TXݴ{< [ːJ 'GXT=#YlR(((hP[;;;X![uuu}{֝< \]]]{h5 6gvy333a,`~uuuuK=zuuuuz;;;Z^~> Qߧiiiy1 (uuuYiii|uuuT' R;;;O;;;LOJߢGX֔5JˋAAFFFd.X: +]֘_Hm333O >\% _e+iiiBku}߬A TߤNXݴ{< VY'(((U|jXV [Z*\RRRuk. [;;;X!bߧvc(((`u֛UcyV{O U{NR N`;;;`Kt֜RRR]']yMX;;;\!g[=  iiiXx[A<(((tv1[;;;W! 333VY 8h f+5RRRce% :nc6g֜O<;;;e(((h*FpFFFd6* giiifFK_ 3Up'#qF Xݴ{< Hߥt$ 5w֚豿6 bp/ [;;;X!]x5'm˓]#:]]]f\_333r<Cr[%FFF_y8Giiip]\;;;_,1}6+j |6!f;;;Y!buuusK ;;;P}]5#333Y][;;;X! 333W[b|Q[Q!euuuifFFFqsfVUiiipCM|{n= O~RRRf9Czn5Xݴ{< 3kzC'M[OQhpˌ T#dX[;;;X!Y^[ݴ}A$333]\\;;;[$*;;;`\.wj,;;;e333U[;;;X!d޴|< 3hg[;;;X!\333c(9e c* 333V[[;;;X!#333[\ @{|RRRc1Gߣiiivuuue6  9** f]]]b 8FFFgHFFFI*Xݴ{< (FFFI 9OT@! `RRRs:[;;;X!XYXݴ{= 333XZ[;;;X!!333Y\(]]]^w, >;;;s \\;;;[% $nz62xp#`;;;X![;;;X!AkuM 333W_\333c,8333n\# f]]]]+333eRRRs贛`O~RRRs@Kߥx= +pc#Jiiik2Xݴ{< 1]]]kH  [ FFFc=[;;;X!XYXݴz< 333WZ[;;;X! 333W[Xd9AyR_333wJ2Uiiipuuu_*%RRR\]]]rR,@;;;[![;;;W!*CUFFFZ 333Yt3YuuuqX@p]Hߥy= XqNRRRl@ @uuug֝(((l5 ,n `O( +}֚F Xݴ{< F֙}+RaGk\,U;;;RRSOݴw6 333RUU;;;Q;;;PT@֖ߥ333rFFFriiia2dFFFsrRRt q333rߨ;;;`!U;;;QRRRRj(((O;;;U]]]xRRRVFFF3Huuur ~ߧY*(((q o# 6uuulO*in$*FFFZiOv]!({D6w(((;;;d;;;T;;;>!YVXݴ{< U[<=(Y2 =333=<< 8ﻧd'(((===(((?333<=NnRRRa>fˌ\%'_ߣ;;;`!=(((?;;;BRRRZ/I^%_@QHRFFFT*@֕J 2c*3 j* =ph! 9, F\Xݴ{< Y޴H *55, *,' ,,  +8R][O1`333v]T>  !AU\n;;;\!,  'J\\N.#HWJ, %GW[[Q<!=: 1'58<@%  *A9bz@ Gbf`\V> =vbXݴ{< _ݴ}>   \;;;b5  +j;;;Y!        ?;;;>uuuGS RFFF9=ݿx+;;;8R+ ,!  %2# #AA$ 2+ $AA#          '<JMC/   #>< !ATL11OZQ6 %M333`ˌuuub[22KWYQE / X3 %]ߣ~1iiiZs3  /gːRRRa@ '_y֏#>ˊuuu\.V;;;X4Q 7( fiiivh< ,aiiiB  .諧t333(((O !RRRIuuueG 9kuuunV*^iii{kN]]]>% ORRRmˎߦ d( 6NN3J}2 /`{@/XxRRRux<\Yb˕k/ 'RRR[]]]t{|豎tk}G2P;;;VWVclގiD[ݴ|>Ciii}rN@FFFbg58FFFl(((y9 j~U  9t}kiY333_DNiiikW.iii\˖f2 #8vާ].! \]]]{h5 6guy333a,5x֟@%sR Dߤp;;;cs/.9(1333`\K ߫ߪM#FFFBRRRURRRcFFF;;;RRR^RRRR;;;=cyV{O U{NR Nk_ 9ˌˌJG֙n333fk##1$.;;;[\T333FFF{R -*_333r<Cr[%FFF_y8Giiip]P;;;Z 0 Fߤniiib2 >x333hFFFqH5U@C333m\ C߭(((ˎ@ @VkdT:\;;;[$*;;;`\.wj,;;;e333UGuuusx/ >ߣTvO/k (((YiR# ](((333333W$(j޴O [;;;X!!333Y\(]]]^w, >;;;s \N\(FFF]{˔[` ˍFFFxk9  %J]Q:>YeeU. Yݴz= [;;;X! 333W[Xd9AyRcuuuxD1(% AoM 9i֜RRRlRRRj|FFF\ ((  1g|Q( U;;;Q;;;PT@֖ߥ333rFFFriiia2(((^d333aFFFXa'Jr;;;r2HsRRRw֛h+ 333=;;;Q;;;^333y{333p;;;Z;;;P(((<=(((?333<=NnRRRa>iiiL. JiiipuC;;;cu], +*,  +8R][O1 *M[YY\\R< (Yy f.M Y(((V(((V WU:>V\]__]\T< #FFF:K]FFFS  5֛R.[^3 2QYO2  deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normal24.dfn0000644000175000017500000104401611357170241022530 0ustar keeskeesf## '! '" '##'$6'%H'&]''p '(y ') '*'+', '- '. '/ '0'1'2''3''4 ''50''6@''7P''8`''9p'':' ';' '<''=''>''?' '@''AN'BN'C'N'D<N'ERN'FbN'GrN'HN'IN 'JN 'KN'LN'MN'Nu'Ou'P/u'Q@u'RXu'Sku'Tzu'Uu'Vu'Wu'Xu'Yu'Z'[ '\ ']+ '^7'_G'`Y 'af'bu'c'd'e'f 'g'h'i 'j 'k'l 'm'n1'oA'pS'qc'rs's't 'u'v'w'x'y'z'{ '| '} '~#'5'E'W'h'v'''    8C61=>'      9C/    AC!    DI/ @豧s quuuR#+9(#>9$D WP2  (Me f[8 *I J. 1:8( ?豧o3 :D/<G2JJ: G33X g gY6 'HH' K]]]^+^333}5*uuuWuuuNL8  #J{˓ c9 . lpJ (lP9 fs]]]h\+ ^QKˌm,iiic=(59nn85+  @֖˅'C]]]kuuulH(((K333JcKm(((= G֚RRR[!';;;eD  .k֝qJ`p:!YU :jo'm\ 9]]]n]%i s2 %uuuT(((rw诛e133c]]]f(>0%]]]_˝FFF;;;u6 (uuug [ =ߡ M F˓w .FFFtuuus6 Xuuur]]]rT5333v;;;u6l333p';;;d֟QQ֟;;;g! 333i;;;i! oK1<*%:># =>Qu( J֚333֝Q d|A 9@$ f]rT 9ˡ߰8 FdpFFFRRRqdG +;;;qk'333riiit36tRRRo, 333i;;;i!n@   >cg`uuutD .FFFj _+M]]]fߦ賿x.U֟jC@6 $333mF _j 8x|6 @A DQ1u333p%'333q5 333i;;;i!g5. zp%#g(((t2>iiijs6+CRk(((]]]gF:+ +tf]]]bߤߡ(((:1uiiiq2M˖333f>MMz|NM>FG`uuuq56|;;;j#!333lw9 333i;;;i!X;;;l' F;;;}˙t59<6k(((n.*puuuugX%%k M =;;;n% @;;;l$ QR *]]]Oiuuupuuu|֥֥uuu}uuupi]]]O* 'OippiM# qq 2z;;;n'%333q5 333i;;;i! Ad']]]KFFFw߬FFFRRRgRRRmiiiRRRRRRf]]]J+  $cXFz`O֜F G˕;;;i! <iiik*'333C333C' *2N(((333O2* (((IJ5uuuq`(333siiit55uuutRRRn+ 333i;;;i!%RRRNF :FFF:,$C((((((c.yiii:  ;;;c(((r t$ H;;;i! <r+  %333n;;;l';;;VYQD ;;;e֟OQ֟;;;g! 333i;;;i!9 C. .gxv֤ypi2 ?iKVͧ;;;e`֥Q,miiib8b(((]]]Q A;;;j# >333q'333c;;;c(1# GAj;;;q*f}//}f 333i;;;i! + T ^KC GGO6(^uuu}(((d@tiiixV/xi֤_6;;;s+ H;;;e 333K;;;K 5_֗;;;X,!CV[YT=HWM%(333qmM{{K 333i;;;i! Q= 3]]]m˒MpnaX'uU_(((;;;G $RRRd֣uF(RRRl= [ k (GG*  RU  FO AT*333l֥֥(((m* 333i;;;i!uuu]M >iiif/ aXG333m/Fg%/;;;g(((h(URRRFFFc+mUm\ 333W(((aWFFFWTo6Cws@333c;;;c Oߢ: < O]]]H8  O;;;oߩ m8;;;=(((h/ :FFFh333j8%dˑpRk3 Tp' w> ThFOGWJnuuulH333J;;;J 'M U@ AA'  '<4,Q[* % FI./ThgR. C_ hj_@!#FbbF3]]]sFFFu1 D p! AYG YN$# C F( 8YiiY6 'JJ(    Dzd   dTn˒G =]]]c2  !iiiP֔: 6RRRpw, @uo# /ߜ;;;P9'=5R֜M hRRRo9 $  #giiiK*ߟˍK (OS3331]]]@iiiND               .H`knnj]D' @_ij`F#  Hdl keN+.GA @_jjji_A6A/#Kdjjjjjji_C @]ijbG$  $Gbji\<: U[@<fRRRn֝˒ rO' 'c֜k.  I(((m9 5(((mD == #Yu]]]_2 J8  *dߧm1  1mߧx[$ :tY *`v p8Om%;;;VFFFj1 .|]VH$cߨDZˏ:  go**o[ *(%( OߦD +riiists r333vRRRl=cJ;;;HU$md]֦֛֠֞u2 \ߨߤ? Du% C˒֣߬OR֣x< $Djuuue֒5   2˄uuudjF%uuuF֘d f(((iK<3/6T;;;n3 Xjye (CRK]iX֞d_[KC.H|XAY__jQ]RRRpk(((i(((a bi]]]] /R vM(:ACCCCCCA<*HuT1  !M333`J֟}Y]l i(((c\HRu(((k  6ߝX/(n(((f$r֥nFwd_u(/333rzR ,{333v.h,*x;;;b333g˚c $ni!! :c;;;vA .de1 @;;;wf= %}n,(((r˖qXyߧFFFRRR> !O;;;d6h9;;;sc_M([˙m/6]]]v\d=8i333g˛g##d;;;e Huuu\]]]P1 Iuuu\uuuY= #FovRRRoR  DGQRRRnyrG# 3 \R}U zvm\[m M~߫U 1 z c_߮˓FFFjU( .333viJ% ]RRRw5Q߬ [(((a333nk;;;g >333L :b%'\˒xV2 9ߡ< 1Uw˒\'d> !oRRR{Vp˗߫\@333|k'|_ C: 'rFFFmYo+ K o5.333vi6(((]]]~= R(((h D333T @x*HiiixJ'>\giiiiiig]@'HxiiiH ' tpO˕> M < ]@ A]`(((n/Qy> 28*ok,iii[ߢC(;;;[ TQFFF]/$3999999993$/]FFFR_iiir: O\k|*O;;;q*t;;;b 5 n  3q[ 9yg'D`nm/i߬Y'wqNR 1l֜U,C:*FA#  8z tQ. ';;;J]]]aRRRiRRRiRRRiRRRiRRRiRRRiRRRiRRRiRRRa;;;I% .O t9 ;;;bߩY_sQ(((mJ Fp$(((pp#puuut< 5c(((;;;` D,*`˔G nmj;;;`H˔F (((a;;;yx;;;333a #Fdiiit6  <ny;;;u_3DD1]333wyo=;;;`},d333uM;;;q333|/Vߩb>]]]|dR˕\ b;;;h  /dyyyy;;;K2Tn߮r%Y;;;h  s u$'RRRib$#\]]]j(']g =fFFFuuuuc2 AA /iii`FFFvg= RVd333vQriiik*$y֞Q1qK>]]]t:#' `;;;h '5988M+ #!HFFFNh{(V;;;h  @|ߨN*p[Tiiiv,CRRRt]]]r8  !1( 1Uv˔N GdnnnnnnnndG J˔wV2  2]]]QFFFS9btX333u;;;<OuuuxUb;;;n, 3}j\F# 1puuudr`j;;;`ug 6˄kcUd 9 Vuuum`;;;`k w*!333i b`;;;i$GRRRtߨU#N[N$+333X֗`9'GqwG DxrH'(\lW( Tf(((nuCURRRzߨQ%t(((EN߬YncSпh 6uuup߬Y5iiisXY˚˚[ 5pn$MNO;;;[!<TD$!AT<  AM >q֡ ˣy1D;;;XK(((n/gYRuuuj9 U q. AFFFu2/333lRRRi2 =x. _(((XV}/  RRRRW'333m}p zpM*333<333I+FFF]l5K> 2iiia o=!Xt o31dX5 nߧo9.FFF_ߦn. JO Ao, >ߣOX p iiiyロ[$MgnpppppiO' *Mdl jcJ% #K[A/QglldM*:\ h jcJ% 3OG$ $Gb j kdK(.GA# !K \N$. dA WM%.(((q(((ytukQ56Tnvt|;;;P     +c֘F Aq֟ kK2$%5Mip=#ˀ]JDRRRnuuut(((qp k333ptiiinG#%6mߧ p: Cjiiioߨ֝uuun kJ%  1Kbkmmi]J1              2QK(  'Ndjji_J, !@]kmmk`H, %Mdjjjig]J1  'NdjjjjjfN'  %Mdjjjjj_A !@]l kmlbJ, 'HJ' >TA 'HH'  'HH'  'HH' :Y_F 'HJ' 1RV:C[M' 1iiic_!333IߨRRRiN>o֞RRRnX$(((KߨiiipiA333I333G(((K= =o֞FFFoV$333J333J =@ (((K333J(((K333J(((K333JNy4 333J333J$\xHXߦ(((K\F333cߦT!VuM333a`%333cFFFR333aJ TrK333c;;;bV[333c;;;b333c;;;b333c;;;bJvuuue/333c;;;b5y]]]q>K;;;b.333vp  333i֣߫p3[ߧп^ 333i֢ߩߩߪ` 333i֢֟֞֞֝ߢ@ 333i֛֡֟֞֞m2 V֜֟uuuyw] 333i;;;i!]c 333i;;;i! 333i;;;i! 333i;;;i$CiiiqzK 333i;;;i! :~{5 =RRRs;;;h!Qy>  333i333m`NDcNKXp333zJ 333i333iQQXg ֟G 333i333iNKKH8 333i333gNKJC,@xߩT<9Hb{G 333i;;;i!_d 333i;;;i! 333i;;;i! 333i;;;j2ARRRrU 333i;;;i! :~x,5{;;;i!$ ui 333i;;;o/<Y%sk2.F?! 333i;;;o.+[uuu{(((n' 333i;;;o.  333i;;;q/ # ob+  '=:  333i;;;i!_d 333i;;;i! 333i;;;i! 333i;;;s[333w֞_  333i;;;i! :~pM};;;i! C]]]v6 333i;;;s5!J(((N Dߧm%   333i;;;i![֟֝G  333i;;;r2  333i333{< @˒i#  333i;;;r2#md 333i;;;i! 333i;;;i! 333i(((i$ 333i;;;i! :~Ѵ;;;i!mFFF] 333i;;;|333r5\ 3  333i;;;i!+` 333i333yb__[C 333i m j j bH#X(((3  333i333yb____md 333i;;;i! 333i;;;i! 333it* 333i;;;i! :~(((;;;;;;i!6iiiuߩiu333v. 333i˟|(gr 333i;;;i!kl 333iD 333iDgv 2=@=/ 333id 333i;;;i! 333i;;;i! 333i9  333i;;;i! :~;;;wi|FFFyt;;;i!\bk]]]Q 333i;;;Dkj 333i;;;i!fn 333iU 333iDknFFFDˉ; 333id 333i;;;i! 333i;;;i! 333i9  333i;;;i! :~;;;l<_ߩ{RN;;;i!+(((wuuuzuuu}u% 333i֡iiii3 ho 333i;;;i!pk 333i@ 333i333;;;j;;;i;;;h;;;_ I$gs+w;;;W 333id 333i;;;i! 333i;;;i! 333ix.  333i;;;i! :~;;;i((n[%@;;;i!NߨF 333i333fO[[] . 333i;;;i!.b 333i333qXUUQ< 333i333A$!!\/%d;;;e  333i333yb____md 333i;;;i! 333i;;;i! 333i(((]]]y1  333i;;;i! :~;;;i# + XsT#<~;;;i!# rp  333i;;;o,1(((d D˓ߩ]  333i;;;i!_ߩH  333i;;;q/  333i;;;j$ Dߧ_3Y;;;;;;i! 333i;;;r2#md 333i;;;i! 333i;;;i! 333i;;;zf]]]r{2  333i;;;i! :~;;;i! ! :~;;;i! Arnns֣y>  333i;;;n,,;;;c% o|\( *A;! 333i;;;o, +]}t( 333i;;;n,  333i;;;i!((((puuu{X% C333;;;i! 333i;;;i!_d 333i;;;i! 333i;;;i! 333i;;;l5DRRRr}3  333i;;;o.  :~;;;i! :~;;;i!k |38}i 333i333bJTuiiihH˓֟V@=Mf}֛J 333i333cJKUg ֟˒H 333i333cHGGF9!  333i;;;i!M֝{M52AmFFF;;;i! 333i;;;i!_d 333i;;;i! 333i;;;i! 333i;;;i$@FFFr3  333i333iNKKJC, :~;;;i! :~;;;i!5]]]uߩNT]]]u5 333iĿ֠M gߪ|{˖^ 333iĿ˕˕ߪ_ 333iĿ˕˕˕˔֘RRRI 333i;;;i!!g]]]v]]]s;;;d 333i;;;i!_c 333i;;;i! 333j;;;i! 333i;;;i!>;;;s3  333i֢֛֟֟֟֞n2 :~;;;i! :~;;;h!M333r+.333uN333cn' *kM333cx[$333c.333c;;;b (d;;;L333c;;;bX\333c;;;b$333o;;;i!333c;;;b<333ue!333cJ6z;;;b6z;;;bFQOA333Juuup]*  $O(((q֝uuup[%333Isi>333Je'333J333JGq˓ϛx\, 333J333J >C 333J333J,iiin;;;i!333J333J:(((p+333J> %`333J'f(((K!K]H! G]K# 'OipnnkdQ3(Gbj l llfQ3 'NgmmmmkdQ6  'OipppppkX3 'HJ' %D` j l lniV:  'HJ' AVC 'HJ'  @;;;h! 'HJ' .Ti`@ 'OipppppncD1OK' 2QK'      f˚;;;e   =aXKOj% ,uuuP(((^Q'                   'JQ3 'HH' (Hc jomj_@! 1VjppniV9(Hc j l lj_C#  %MdjjgY= (KdljcG$ A`mpppppppppiO' >XJ##K[A!HXA *NT5#J[C#J_M%@YJ#/TbN(  %K`U2F_U3 %J`U3(((Kiiii>333J(((K !J rߨo=%`ގuc,  !J rߨp>(((K޴j69 mߧa' <333G <ߣKK> DH% b{$GGV]FߤE]p, 'jm 9iiig=%gx333c333v9333c;;;b +j˓rT6zm% ,j˓uV!333a]]]g6 1FFFiJFFFFQUggYM r(Kߨ]]]d%Qq$3]]]qt: # qRVk$`Z5w y5 Yߨ[ 333i|5  333i;;;h!%m赛֜U :~ѿ˘K'n赛ߧX 333i߫ dXߎV/eː˔˕￿˕˕˓֕=]nnc6iiit֝J!tg :vC X` Av: / z֞XNx2 ]v+Fw333u5  333iz.  333i;;;i!R֟YFHbu=  :~333fRn;;;gU֟YFHbx@  333i{dx1iTOrs@*>FHc((({OGD3_nndms  @|}@ rk'v(((w+gr:;;;uwH#A]]]sRRRr=(umT333zwF 333iq' 333i;;;i!/;;;suuu{[( 2p֠m  :~;;;o,(y333c1FFFruuu{[( 2n˗ l! 333iH#MFFF: ;;;cn% 53 +333pH _nnd Cz> it!J֞]]]t3 F֞J/FFFu֞JDu;;;|k {J 3|ߩ[ 333ib  333i;;;i!O֟[ *u< :~;;;q/,} gQ֟[ (r<  333iM'Riii8l(((K  333i> _nnd$ tg 3RRRuߨM+(((wVm r Q(((w+U˔;;;ߨ\@iiirq% 333i(((;;;T 333i;;;i!f + :FFFT :~333q]yiiiff, 9FFF}T 333ivuuui*U|j6 333i> _nndNߩRRRu5X(((w+`w.:iiiu˘˗w>, t`!ip%Q{1  333i;;;wduuuuwG#333i;;;i!lk{` :~߬߫Jmp{` 333i`,tFFFtN 333i> _nnd,333u]< w\ :wVf {Q|kU}w:  15 !jRRRw= 333i;;;l8RRRRr@/333j;;;i!ndpc :~k$nipc 333i 8 5 tˑX 333i> _nnd] t֟iiiu8r\'Y333r#y߯߯' 9333˙_ 333i;;;i'!_ߩ(((yV333s;;;i!nk{` :~˓RRRjV' mm{b 333i2 +_iiivA  333i> ]onc8iiiu˛kJ֞;;;iiiu85iiit֦(((֞JCiiix{H$333nD  333i;;;i! %m(((;;;i!g* 9FFF}T :~;;;}cVC+d( :FFFT 333i;;;[ ={_ 333i> [tr`kˣD +(((wmm(((v* 8(((y;;;v: 333i>  333i;;;i! ,yRRR;;;i!T˖V%p< :~;;;s3 NT(tz:  333iYK ~uuut> ,t;;;l$ 333i> N {+* U At$`F  F] 1|˚{3  333i>  333i;;;i! 3 |;;;i!2RRRr]]]|U% /j l! :~;;;i!.;;;qRRR|R$ /k˗l 333iACiiiww( .kK'J(((u* 333i> 9}Y  X= # rR :wv''vuuuu8(r{Kqx* 333i>  333i;;;i!8(((y;;;i!Y|T@A[ x@  :~;;;i!R{R@A[s=  333i>]VR˒{KDr;;;l$ 333i> #(((juuu~mD6Ckuuu~(((l$Nߨ;;;w/rXXo`|1,yd  333i>  333i;;;i!>]]]q;;;i!(s֠|}֜U :~;;;i!$k֠{˒R 333i> ,wRRRu9 b]]]\ 333i> Mޛ]]]x}M+(((wcJ֞]]]t55]]]u˔HN(((y8  5{Q 333i> 333c;;;bHw;;;b /pߨuuurR6z;;;b +i֝xV 333c8D{^Nx= 333a: #cc#[t< *(((rjj s(.iiieiiiq@=RRRruuug/333a: 333J333JQ333J $O(((tl:'f333J !M333p߰r<333Ja'\x'b]]]lG Jl* #Q;;;qFFFoR# 1iii[WNw< =M 5xJFs6  Jl* 'HJ' =XM' +Kd j l ki[= 2QK' +Ny~֤iiiz nRRRG$  'KQ2!H`V3 A_j khU3%JR5.Nd k l kdN.+6!8239F`[:9Y`F%JR5   !Ft4           (Orh'%A]j(((`S,              'OipppppppppnfJ##Kdji_AA I/A_jjdK#:TG!6RO2>R@1OH#=UG#=Q>  (((H:K= %`KUJ <ߢ> .A61A3;;;P֚> gD >ːߧM Dg oRRRr2_\VY6zg AːVUY._֖= 6p￿9 <֕˓˕˕˕˕˕˙p#nтoiiiR+,FFFpi*iiiRon @|Y 1xFFF] ]c :~n `= ]c DVNO3DGGGHViii|3 nj6 o(((q% 6ink(((v+:]]]`^_fAn%333nX_f 9֖K CD >vCnDXy< An 9iiiu;;;ߨN.=,#15,_}@5. %12*'2>in '22'Dz =   _x9/.!Mj],'YoY'$q[n> $ so :~n/;;;vuuuw]}D Jw>_N:;;;ll* 5 qn9FFFj n1 MH#_ːFFFE_ߥO+uHGG=]]]t333w6 n> gRRRp/ :~nRo/Vm;;;V d _r: ,333jy2%ln+(((lhJGJ(((I_h+9z]\] . yJn> K֝֝J :~na˒G1FFFrk/;;;K~2_]R }z֕^% Jv˞nNuuu= *y˝\#a8 _|RRRC <}c_c icn> /]]]of :~nY ^#U/ -iiiIVNm}9_3.k;;;b g6 '/$c8#OnhTJ~%(((e;;;]]333FFFh#_2.}U :}c_cNx+n> qs# :~n.NK* #HV>=`s{{< _g 8;;;;;;h 333e]]]CmT <n(((fT <oeiii||uuu333c_gf` :}d_d :FFFuFFFu: n> [u9 :~n   1m= _c,333w;;;h!(((j3333nF :~n;;;c֖< :~nV֤֣Y_c`c :}d_d+zY n> >}U :~n]]]]> _gHuuu~;;;d;;;bR i˙\>non]_gjR% :~n8RRRf2 _c_d :}d_dbdGCCCCA3n> '(((rn :~n.rxM_AKad(((U69C9YQ8_n]333fFKd k\1 :~n*§ k8_d_d :}d_dG|ﴴ֕=n> jFFFo+ :~n3;;;]]](((i+]FFFߧH F֜FFF}uuuv< 8uuupRRRv;;;n >FFF}uuuxK :~n2;;;K# ]c_c :}c_d%333cFFFQn> N= :~n'uuubC Nj#!gKQ֛g`G6zgORRR˕RRRob5V[X[6y\_d,333Gn> .uuu_: :~nJˎ֢= /uuu`~d*  *d~8 MRRRmK%_}_%%`K1;;;oiiie5 =@ >@ 'eC _d>_mppppppppppiO' n> 2HB  <n>]hfbg gaC1Tim l h]>>] h lj]:1QfnppiM#=]imk_A 1OH#U֣W>TAAUA2KA`cnU   Rn !!!!!!!!!!         juuu]b;;;b      p`n֦iI! Gh˞n%;;;G;;;^;;;c;;;c;;;c;;;c;;;c;;;c;;;c;;;c;;;c;;;c;;;[(((E#grt;;;_2(((RgC @h @: NV G{9 NC AN 9ߦߧߧߧߧߧߧߧߧߧߧߥs1 'hj+ >`% I d j j bH##H b j j d I%9MQOOOOOOOOOG1 $J fRRReuuuiuuui]]]fiO( KuuuWR'  $*+%    =RA1J> <ߢ@ 'e@ U[6y[]c :}c  _d :}d/;;;7)_d   :}d'1.+2+ %.,  ! (* +2, @FFFf;;;[8          _d<333S333\;;;C# :}d$ H;;;\ivRRRhsv bJGdjzm_1#H;;;\ gvRRRgrm(((cF !Dc;;;b nFFFceO*$ H;;;^333i333i;;;g333edH$  %Je;;;eFFFf333j333h333` H# 8;;;P333T\ gkl _<9amum(((iR$@RRRp(((~;;;W:#H;;;V G$$ H;;;V H$$333F;;;Y M( :;;;P;;;O 4%;;;G;;;YM' G;;;U(((K* A;;;R;;;K- #;;;C333];;;XF +S;;;^333W(((:%;;;F333[(((L* =;;;Q;;;R9#I;;;^333i333i333i333i333i333g333\(((@_g(Gp3 :}dGiii]]](((l.G֚N ,k˒o8Gߧ l3 2oG+vRRRu+ 5iJ+RRRb|*GGGG =_ 6kg AYJ`Aˎ]]]I 3֚V$/r' >d:q֒% C._uT]]]qj( :}d\X\h+$m;;;l1 \(((l.+n]9|ˋ1XZ 5r(\]\] :u<!bf A֛FFFs5+ uu=(o\'j|iy` <D(kj  @ l$_;;;FFFr< :}d_RRR(((d_]]]C Hߧ;;; `_ FFF|VR;;;c <RRR}\giiiuC \RRRiii\6_c_c$ tjG;;;x֞K( v`UjRx|@ 9333v]]]|. #tyYiiixߨO H a o xC_uuusD :}d_15d,G]]]~;;;g _3.|Ud>$5tiiii*_v2:|;;;_ b=1tc :~X2:=$ \iG! .333v;;;w8 _c_cNߨFFF v*X333s Aiiir{5 G v*'\b_[ :}d_frD%333p;;;h!_gd`;;;ciiiG 3 5_c=;;;;;;h 333gRRRA`d :~ (  =RRRtQ 333i;;;i!_c_d+(((vX2FFFwRRR֦333˔HVFFFF$u]]]U, zz._;;;U :}d_cn> 333i;;;i!_c_c m3333!v8_c+333w;;;h! 333i333z._d :~rRuy@ 333i;;;i!]c`dYRRRu3fw'K< H˔333v._|F_蹂;;;u= :}d_cn> 333i;;;i!_c_d;;;bO< 3_fFiii~;;;e;;;diii~Gbd :~o1U(((b  333i;;;m( Ykmd3RRRug =xߪ]]]V,|n%% uY >uuuun% _;;;s> :}d_dn> 333i;;;i!_d_da T8J]]]f'_9C _`A5xd :~n 0uuuPiiuuuw.333h333U>8Mߩ>Fdgz> o333wGpFFFw2!iߩ_Q˖FFFv2'yg@3%]}c{FFFq= :}c_cn> 333i;;;i!]c_c @;;;\_iiiFFFKJߧFFFFFFd :~n;;;Kiii ˟v.333a333vF9֣(((c =xr  F`!A}fT˔O @;;;bUyu_1 Vb.RFFFa*6y\X[g9 333c;;;bV\X[]p,_n%$ld6zg333O_VY (((`[m˒G%suuus9 !su< 1j|DF333vuuuf/Tߩiiiv9 +RRRfN =CQz2 'eC >@ Kf((((K333J =C >@ #Xuuurj/ _j,  ,id'fK $G`U12U`FH˔x= A`mpppppiM#            _t*  (qc      #tn_c`cD|@ ]_\_ep JJJK!jA(RRRKuuu^FFFL''FFFLuuu^RRRK(;;;:uuuZ_G #  # #!   A__D5U]D       Y֚< !DG% 'jߦ]=QG32<2$LYD!6YdS1 'Mdi]>!@\iljgV8  @ː@ J(((K(u֛C OߤߧRRRwߟ2 X 4 KuuumFFFb.,mˍA@oނqg6_]]]}S#e;;;b C]]]r_,hߣ9 1FFFqiiig1F{J\333V Vz]]]jC%HH' kiiiRn;;;h!KRRRl1;;;[% G֜T1333r￿=%iiid RRRFFFTT֛333]]]uuul@  J(((Kn333u*n;;;i!'333qo333=]]]Ock(((miiid333U2 @c$]֡Y@ .oqߢߡC>s |(((r sߪ333o2  6JK6333a;;;bo;;;i!n;;;i! 333ip  /53=MM85[_A!/FFFrv. .s;;;YA5$l} ֟`.Te`F.5`sᅴs]'!333j;;;j#r;;;h!n;;;i! 333im'8<3$ #I;;;^ jxRRRhso(((dG !Fi;;;l yFFFgfO*RFFF< 1(((< Dˑm]]]n1.(((f֜X =(((333> !333l;;;g n;;;i!;;;e;;;l#!QRRRfw333mb>'+D]]]B,G֚N ,k˒o8<+ C}~3 _q˒ ]]~MNuuuvMS uuue*#H(((a(((l (((l(((aH#=;;;333dn;;;i! fFFF>K{ FFFL\h+$m;;;l1 333>kuuu{@ _{/ kuiiizG3(((GF'*ub;;;Z˙HVRRR~8DD5_n;;;i!]5;;;WFFFY_]]]C Hߧ;;; `+vFFFM$;;;jRRRk myy|#qj333`uuu}t,>]]]o< CC !]]]W{@ n;;;i! >{RRRW!;;;Lߧ uuux P_3.|Ud>$5tiiii*'n333F*uA m{{|#35 rj333X 333bp|3# Icm uuu mc I#+/n;;;i!/, -OM1'<_333m|˓֛iiik['_gd`;;;ciiiG 3 5O(((߭U( %;;;l;;;t_kuiiizGMˊC5v_K(((`!9333z333{:333Xy> n;;;i! =uuuy]]]X# $6A=,_c_c m3333!v8 =iiiyiiiwAet k](((t fmFFF(((\YyߦH #Xuߥ֙;;;dYbst> 333i;;;i! 2]n;;;i!\5 _c_d;;;bO< 3Nߩ2 O 333a @˘yFFFl,3C='< []]]]]]]^Z< #333e;;;e$ =;;; fn;;;i!hFFF>_d_da T8J]]]f'ivYHAF= *q֦g!j ֝[  !!  .5FxwG5. !333l;;;g n;;;i!;;;e(((n!]c_c @;;;\$ sп}G8;;;rM 9iiil˗(((v(((vs.*iiiPmswwsmiiiR+r;;;h!n;;;i! 333irV\X[]p,2s]>RRRr.KiiiRRRj: CFo;;;i!n;;;i! 333jo =C >@ #Xuuurj/ /KNxyKiiil(((n< <@ n333u*n;;;i!(333rn@UCAUA8Yi l h_@ <[b__dkn kfM# 5Fp֠(((f8fuuunߧFFFm\.CbnppppppndFkiiiTn;;;i!O]]]l      R֖yu j 5QfnmcK._iii{T$n;;;i!Ciiis] 8ߣ ((((((a  @ː@ j;;;e (uːA <ߥTXː< SFFFR'j֚Y%;;;\m+@]`D /uuuQ[45V\A/ZiiicuuuhRRRb[,      $(!deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/fonts/normalbold24.dfn0000644000175000017500000116201611357170241023372 0ustar keeskees8f## '! '"'#('$='%P'&h'' '(')'*'+', '-'. '/''0''1$''27''3J''4]''5p''6''7''8''9'':' ';' '<''=N'>N'?*N'@8N'ATN'BlN'CN'DN'EN'FN'GN'Hu'Iu'J(u'K6u'LNu'Mbu'N}u'Ou'Pu'Qu'Ru'S'T'U*'VC'WZ!'X{'Y'Z'['\']'^'_'`$ 'a0'bB'cV'dg'e{'f 'g'h'i 'j 'k'l 'm'n'o0'pD'qX'rl's|'t'u'v'w'x'y'z'{'|  '},'~:'O'c'w'''''  !'        %K`T.+HXXH53GVXH+$ K] J# @VN. DiiiZq W6  %HciX6.R[> :XimfN/!CV[T= %JccG#McT.#Kd\<$g333h/#Xiiib]]]a΂X$QG>ߣuuuQ %K o]]]~333hD!  1joO 3333j+ /dyRRRlMGC /q6 H s:Iˊ3  JX3w~6!(((lV#](((e /m˒ c(%jːD'r(((e%+ q֚M;;;^` /yj1Q;;;r: *cK 7 T ] I!c;;;_9}= Av˗Y5yw#lO H(((b3XߨGT]]]j/333hk%q˕U5]]]o(((t3 ' NiiiYkiiim[RRRM9+uGm(((l6|:#Gd֤iiiy(((2 FߧgbFFFoc]]]vfe߯J 333egVp$Qp$Rɂuuud/9{]n;;;g .nFFF;;;q/ H(((L_֧;;;ceuuuy/;;;d]]]RlU 8]]]s3336 $uߨO ^ˣH <ci;;;e k (((l!333[;;;[eiiixuuunEX蹛;;;vC(((c333֦֜A [}< g`D(((u,(((PC  Qu*] lQ\\Q;;;JFFFL[֥cR@! 8uﴴ_[p2 9;;;V!6uuusiiiv8$ yN 2\quuuuuu߰]]]uuuzi;;;J$Fblt{lbF F`#MigJ((JgiM# * T֤RRR((( Y*  =t<T֚iiiA D333;;;}b\gfO* :\gQ* Uu _l3d]]]K#  DD '588883%,RRRo˕G 2|߮RRR\Y3333`(((n3 F dnv]]]yRRR t h[8\iii;;; iiiI i` CRRRl( 5]]]iiiiYXX6fuyyyxu_1 l]]]n. (\333֩Z(  %\tc .An֩iiinHTW;;;d˖N.RRRr5Hu$GG;;;QUYv 333J;;;J *Ck(((9 :(((}裏q9 =iiir9 333hA #333n}9 @r(((y333U#G(((a(((i(((n ֦((((((u(((i(((aG#333fi bRRR֧+333];;;\#(((@R=<|߰M#pRRR\]˛X(((l> !333lx9Uo;;;[:Ql2 'Vy/J333]RRR` [@;;;_dJ333]RRR`[< 9rN333N333JG333{p333MQ˔(((ej˝.;;;dF '333r53<( =A(  =cJCLGHu9 Y;;;Z 5FFF]]]qO' []]]֩<  9FFFu(((FFFaeuuu / nU8vRRRo,  9|];;;Z(((e!%MdjjjibG (((]Zf(((ey |9X~KR333c$'v(((yHkdOߩb dkO֟;;;e ,wH333d5;;;`eT Whf$T;;;l% 3np>MHDː֛D *mˏ@K{'m` ;iiiYiii_333K%(((U< YX/;;;e|= ]]]NGGT9kw(((m@uuuL`\ߦ_  /i˕(((]]]?,333uF 1;;;zy= !#  uuur~6 #q֝TEf$ Nq% Cߦi#333<ߥ;;;lQ# Rx9 Km*  #@C+F]]]_˅1 3spY'  %8<.+6,               .TdT. :Xij]C# !DXXH*2OfmiV9 >YjniV9/KXO56QYYYYYYU@ @TK1 @UYYYYYYYYXH*(HbmnfQ2$C]kmcJ*.;;;dW /fy˒ k6 FuuuU#._]]]pގvc, (\ގvc, =uuueϿ6 6ˉC ,iˑRRRp\.C΂V @(((lߨiiinX%<l˓ߨ333lG`^. tRRRj9;;;^~6+333dq'Op' 6(((vURa /vSak'Atb DoQ+JZ333B$ 9]]]vC d m* 333h= MNcN+yb]e(rߥHgl*333lˑA 5]]]lw>    8](((wߨHio  :uO 333i> ]hS֡ gdd_L]֟c#N֞K GFFF^\h 6>1 6>1%Fnuuuu[ YFFF~ ;;;e /^gXcFFFbMd_iiiwqhK$ @w֥<'333J333c333i333j333z;;; v*Yl 333gFFFt1(aߦrV (aߦrV  3VxKmm evt/ 333i> @vd96r֣;;;g !%G(((ciRRRuߧ(((]( @yiiiv:  ;;;gmR=  333i> 55 N;;;c !N(((y߬V 1 z߰d_￿|(((jO%  CTTFFFw2 Cߧ;;;X(j333RGN;;;_a;;;_a#YyysK%  of%333p\CzJ  333i>  Ud C 9#nd_h'bF$tg+]]]~= !333i֣H ;;;`f;;;`f F;;;xc= DRRRv6 'kX=(((Q 333i> %z֝G O9 O֝n[V333e;;;c# Dy= ': ^9VOVOY R($t_$333o_AsM 333i> Os$ :֗]%]]]b(((=Diiif*#333n(((8mq @\ 8oFFFl'/333e f(/333f f(K }U1 J˔;;;v2 333ijM~@  333i>   3|֢p1 +6,#2v39|6# CYF./`333˓C #333mRRRXH֝D `w%!;;;g;;;N@D <fuuuuy=  Q333hRRRjgA!R;;;gRRRm fF %Kt}~ [$N֞(((w.b n# 333i>  ,ymW8'g z_]s3.w/FFFFyri֤>  f߬9.333wT%hFFFQCK+i;;;gHu9 JC!@gFFFvH*wT AX 333i> 'm~,6w赧uuuh*((( `ߩ< 9{\$,..C{%X c2FFFpR gb[g!+333eRRRo<;;;`e;;;b5%FmiiivM'(((l֝M 2(((prC333c9 =ˎ9 +wuuuj8 k\ @RRRi5 Gzk%huuut9 /333jl:  1RRRo@YX(((U<  8Y333\uuuO*, f$3 nߧ;;;lA(((Kf((((8f(A]]]f(((m=K> O]]]l k9C333mu`* 9;;;b˔\3l˓(((l=#Suuuo(((r= \ dO*  $Gc j keO, 'OikX3#JfnpppppppkX3.Mdn l kdM*#Mim`A1Oflm jcJ'+Md k khY:'F[I% !C`j l lldJ( 6T_R/9Z dV3#v333h$         ,OEf$333<ߥ;;;lQ#  #@C+              (Oim`F# !9TfnpndO3  AUY[XD#!CV[YYYYYVM:$ 9Tfnnj_K5 !CV[YYYYVQC1 !CV[YYYYYY[VD!!CV[YYYYYYYR9$=XinpniYC+ $(((]֜ h. +RqzuuurkCVZG货}333hN# #HlzߩriGG˓qlT,G FG֖:  %NpпRRRlW( $333B XK+  G֜ c @sf*  =u}@ ;;;\`  /n֝A ;;;\(((qA;;;\;;;^;;;\V2r333K Hߨ(((y_9\9Kq˗n'im 333h֛A +t[ 333hsF 333h;;;` 333h[ /s;;;cA`mppppppppnbC[uuuvoG'333CG GwRRRyjbfv\6]]]viiiv9  333iuuu~˘]_b 333i]]]n6  333i333J 333iC f;;;d  =A K˔wX3  %Q˓C 5RRRn ~;;;rFFFn333lx} u< ]b 333iOd(((d6uuur˖RRRt(((w]]]t֟Y 333iu˗g 333ixxxqU*  333itrrgG :wFFF|yqqxuuuxFFFMUX((((]ߧRRRui@ _r1iߨb.333v;;;v/ 333i=QVVQ1(2Ow>  333i~,,`t8 333ibNNNH6 333iO<<<6%Yn8!*A\RRRI/JK %Ksy~]$j\ 4`mqqof(((A/CJJJJJJJJJJC/'O [6|{.  g;;;˘mT r=y: Fvr˔H 333iiii~K;;;e333z. 333in z˚˚|@  333i~]]]Xmp(  ** 333in]֡b 333i333{kkjdK$ 333iiiiFFFvRRRiRRRiRRRiRRRa;;;I%mߪc#;;;M> XY$ [~}tK% Q;;;12q@ vVX333n$ij 333i1(\;;;i\˗r<!'Aguuueߟ8  333i}+$M(((N 333iA.,,*  333i:%%%! [d=H(((n333> DFHRRRui@!2iiijZ3z(((z]]]|<9FFF}]]]yg c5RRRw]]]v6 333i61fiiik ={]]]z yt(((v~U 333i}r~iiio2 333ir```]M+ 333ip EblmmmmmmmmmdH YvV3 U]]]h*.n333]=v z= [˚˕˕˕˕˚] 333i;;;(((z333y_ib 333i\ 333iuuuW$ 333ing> JuuuvnF'`֘2#333luuu ֢iiif+(((w]]]gKGGKgRRR333v, 333i˒C 1 r\ 333i t+ 333i~5 333in /w: (uuuN333\\9 OFFFd%gA Cߦn$ #mD 333ad 5 tC 333as3 333a8333ag5tn*  +(((fߤKJߨߪkG  @u: :u@  JiiipY'  +YFFFpߨ˔FFFjN JRRRp\, Jf( JK,[;;;sߨ贎ua9,Te^C( qiii;;;˓(((wv˒˓xFFF8 !Jfnk[99[kngJ!%NipppppppngR3,Kcl l lmj\D*%NipppppppndM/%NippppppppkX3%NipiM#,Jcl l lmkcO6 FnU@=J\jyr5     [ߧ֠RRRz |utv |;;;{Y!Vu}[#=m֝qC >] nFFFkswiiik mdG% %2:=<5*                             !CV[U@8Q[XD#@U[VC!3NYXH+!CV[U@8QY[VA !CV[U@!CV[UA#  #CUYU@!CV[UC# *HY[R9 :Ugnnj\D*!CV[YYYYYVK6  :Ugnnj\D+!CV[YYYYYXO:!GC 8֕(((ECG 5w΂X$GCM :GCGg**gCGk, !]]]Q֖:  #H oz˔;;;o[/G賛wiA #H oz˔FFFo_1GlA;;;\aT;;;^a;;;^R~6;;;\aDsC ;;;\a;;;\g!!ga;;;\q* 3}V .k֝(((q=;;;\O .k֝333q>;;;\M 333hl];;;h!m;;;h!]=  333hn$9333wt' 333hl 333h˔TU˔l 333hj% :}b'qiiil< 333hv< 'qiiil= 333ho9  333in_;;;i!n;;;i!_>  333iyG z z5  333in 333iuuuuF$Gun 333iߩb!<dX q+ 333i_X(((n+ 333i\ 333i|(#m;;;i!n;;;i!_>  333iiiis@ 333in 333i333n;;;|n 333i˔['Ad2]]]o֢߬T 333i{;;;c2]]]o֢߬T 333i}˛333d 333iq___m;;;i!n;;;i!_>  333i߬Q 333in 333iFFFn 333i\UdR`[r]]](((i  333i>OFFFf!R`[r]]](((i  333i@Q;;;g  333i;;;i!n;;;i!_>  333iˣg  333in 333in 333i~dhy1Oiiiq/ 333it;;;dhy1Oiiiq/ 333ir;;;b 333i;;;i!n;;;i!_>  333i6  333in 333in 333iiiid iFFF= #:  333ia iFFF= #: 333i\ 333i;;;i!n;;;i!_>  333i3 333in 333in 333id;;;e;;;s*r@  333i@ 333g;;;s*r>  333iuuur9  333i;;;i!n;;;i!_>  333i` 333in 333i֥(((n 333id(((h;;;8 |=  333i֛Y333e;;;8 |<  333iq  333i˟;;;i!n;;;i!_>  333iK 333ir 333i333n 333idkm( F;;;5 333iϿ(((lHlm( F;;;z2 333iˣ* 333iVCCCQ;;;i!n;;;i!_>  333iRRRs= 333i>+++*! 333izN(((y |O333qn 333izJdUxNF_ 333m$ 333iud`U>%YxNF_ o# 333iߨN 333iv! g;;;i!n;;;i!_>  333iv{5  333i]]]viiiliiiliiiliiiiiii[ = 333ip'>uuue;;;e:.333jn 333io$5 }d6uuur[ 333i|*  9tY 333iz=jt' 333in_;;;i!n;;;i!_>  333iv>rx+ 333i/ 333io/=+!333in 333in6zd_;;;o1 333inc;;;q1 333io 3333z֞K 333in_;;;i!n;;;h!_>  333io!1 zf 333i<  333in  333in 333in9(((wc+uwF 333in, u|F 333in]u#333agX;;;cg;;;bk> 333ag9;;;s< 333a: 333ag333ag333ag<;;;s\ 2 roK333ag 2s]]]c*333ag5]]]r9  JK >;;;JK(((K>=  JKAl 8 Jl* JK JK JK>]]]iC  *X333sߨςth9 JK (X;;;z \< JKX9 %NipiM#CbniO( #MipiO' 3h8%NipiM#6YkpnfJ#%NippppppppkX5%NipiM#%NipiM#%NipiM#2VkncF+Jcl l l kgT8 %NipiM#8q֝ߡ 6%NipiM##KgnndFXuuuj+    #M vAkd+T vߨr(il8 *Kpuuusn. MFFFkA5Rd YJ$ #M fjfR/                           %D]knj\D(!CV[YYYYYYYYYYYYR9!CX[R9@U[VC!:RYYO51MX[U><RYYN3<TXJ+AU[XG' ,JXY[XH* %FVYYXK.:RYYR9<R[YR<@UYYYYYYYYYYYYU>!DV[YY[XD#=_fO' +HXYYYYU@@(((i˓˓;;;jM F֖:  F֖: CG 6ϴy< 6g= 8ϧr9 JFFF^,RiiiJl j3 .lοw 1ˍMQ֙3 D8  F(((E,c$XCCtA 333^V333^Va;;;^ =icJ @f,333pX3iiin;;;YSx1,p(((T1suuur@Dv5aߤ< ;;;^;;;Z*RRRgF2ua*RRRd\333f_333hbm;;;h!+333ruuuu81FFFu]]]t5.;;;sRRRt2O w*XY 6FFFoyrߩ]]]o: _|<= {djo# 333hFFFO]u$,wl F֝`;;;XQ 333idn;;;i!]\TjcR$ u֞J%tiiiu8FuiiiN,zx/ WFFFv9  333iuuuvuuuj[ 32333w˔K333=auuumuuu{nX~N>ߢ˓˕˖˜˞˖˕˕֛m2  333icn;;;i!6]]]v v,*uz>  6u֞R 333iC,#Vw(%/M(((nV iKQ_V, 6FGO{VGG@, 333icn;;;i!j˔TQp p{Yv{XtC !fv*Q˔ߩV+:>@Ju333r$ 333is, wߨQ%333mn A˒֞xU9$ Fk  333ico;;;i! @}FH˔uuuRRR u$*x|3 #mt% /}333y6  333inQߨ w, 333in%333d˔o5 :~c 333ifr;;;i!!s]]]FFFu%'w ;;;Q 9 FFFD 1z(((y5 UߩM 333in(xV 333inY333d2FFFw]]]v6 A[=(((ym 1 ztD <c=iiiuJ/++( 333in#sc 333inJ֞ y|8 :~d_]]]˘Mfi#u;;;u1[C 'r;;;u: :~c*x֩RRRiiiqiiiliiiliiiliiifiiiR,  333in A|]]]w9  333in]r. :~d =x333n+ =xz> Nߩ_ 5RRRw u$_FFF|5  :~d]R 333inpj 333inYb :~c[Fop ,333viiiu8iQKYK(((yy+ :~c@vi 333in >xx=  333in AFFFj3 5y\$_˒sN DF_i =x333u.,RRRdb @iiiqR6z[ag 333inj_ 333inNFFFk֝֝i6$\C Gnޛzl<!aa! 3uuuek8 ^T 3m(JxU'f@ #֑K 333in 5iiifW 333in+G`k k ljbF$ 1UjncF#@\j k l khX:  * M g g M* 5 U d W8 'M f dK#FcnpngN( :\kppjR,2VknbC6[kppppppppppppiM# 333i}*3 T c Q. 2333un            333iyfN'   1Tg333n 333i333J%`n333e;;;^3wh;;;MFFFN+vO .RRRORRRdRRRiRRRiRRRiRRRiRRRe]]]Q0 9RRRWRRRfRRRiRRRiRRRiRRRiRRRcFFFM* $%%%%$$%%%%#     :RYU@            #DXU>.X8RYQ6*HYXC! =[jgM#8RYQ6C\N( C\N( 8R[R9+HXT= ]U']]]XyA 8֕ˊ8 !iiiRG +f~M 8֕ˊ8 G WG W 8֖֕: #XCFs< :(((tiTU2w;;;^!jdTU333X|.333X|.TV3w`#tm8 y֒' ]f   A;;;h!  C˒\]c ;;;Yr/;;;Yr/]b :}lGx= /\uuubuuu];;;> /=GH>+_MFC3!5DJF9$ .@GJk;;;i! 3CHC2k˞ˌ>  %+....,%_v99FF5 \ߩ o*\ߩ o*_d *..*  :~n#tm$$1Yno֞ߨ˒]]]k`1_FFF֝֝vhA (Q mw֝֞֝FFF_?2biiil֜֞֝iii߰;;;i! *Rns֝֞֜siDT߰t.8](((h]]]huuuluuumuuumuuumuuumuuuka(((@_;;;v֝ߧze1(((Uuuuiiik8 (((Uuuuiiik8 _f$6FFFVjuuumuuuluuubuuuL# :~nGx= 2]]]c333i/_O /q.9FFFj;;;i! 2 qːVG֘> Jo/_(((j,.yS.yS_qJ333p. :~n#tFFFmUY_w= #l: *p;;;i!'pF`T :t1_U9|i9|i_d  :~nGx= d›;;;`_h F֝|5N;;;i!M]]] k$TK]˞˚;;;W _ d <n <n_|/  :~nfT[]S {;;;h _ o,d333{RRRn֕uuuO!huuu;;;i! fˣ@ /a߂RRRS((((d(((}G_333;;;e :~n :~n_ˣ y6  :~n y`(.FFF_R 2b}}]]]};;;i!_v3Nuuu~9;;;c>%+/! ;;;dp5T;;;i!;;;dߛV6f' (((fX: _NV~;;;h! :~n :~n_RRRF :~n 4 T f dM+ 1 O e e O.%[(((~ߩ;;;i!_c+ }<  333i[ 333iN=;;;i! 333i[rD _;;;~2_p +333u;;;i! :~n :~n_3 :~n   =s;;;i!_n'<333~: ;;;e߬k'333h\'K;;;i!333hGn> M c _d!333j;;;i! :~n :~n_V :~nX߮333y2 _g5 diiixcg_(((D#333dg֤;;;i!(((dv2n> 'rk<_c 333i;;;i! :~n :~n_֩uD :~n;;;c333uuub'_ߛFFFj'XHb;;;i![(((333x1n> J趧tC_d 333i;;;i! :~n <n_;;;u: :~n;;;bK_\2RRRl\ A;;;h! 5]]]m~8n> Mt@_c 333i;;;i! :~n An_{2  :~n WTXr.DqQc;;;bGuw,g9 fuuumMX[333c;;;b6zgNߩnXiJ333v]6zg   2FFFfn8 >֤ߧ l3@(((mނd2'b}(((KA(((lߨRRRfAKf( 5= >@333J333J'fKbn >C@uuuj˃ 'fK=RUUUUUUUUR=1V g li`U\ d kiY6Cbnmfbf j jbG$ (Jd j lmhU2=]j jhdfkniO' (Hc j l lldM,#MikX3 _]CbkbC 'OiiO' 2VkiM#%nCbkbC5XkpkY52VkiM# ==      +pi  D˓e    @@ /s c\O!HciiiiiiiicH!$iii]HY;;;j,Crߧc# :tuuuj>9b333lsw]]]i gG! Juuugb8 #2<><3(((    #6, ,iݴq*         +r> +.+$ (9D>. /AF<' +.+$ (:GD3  2AHF9'  +.+'*8DD5  .>D:+%*.,! +.*%:C5 ':FF:( *qf6% +,%$,,! +.+  (.+  ,/+ %* #,,$*..*  *.,# *.,#%., *]]]OiuuunlRRRex;;;n֝˒mc@Aen֜֝ːFFFfK*]]]OiuuunlRRRex;;;n֝ߧuc/  (Q ks˓֞֝FFFk`5*]]]OiuuumlFFFm֝֝ziF5cuuul˒֝;;;uzkuuumuuuj[3*]]]OiuuumiRRRYc(((l֚֜Z' *X;;;l֝֝RRRiX(  *niiiuuuoa333> .uuuUuuuiuuula333> >`uuukuuujY/ *uuuRuuuguuumuuuiuuuX5 '(((OhuuumuuuguuuR**uuuRiuuunj]]]R.GcuuuhuuuY6@_uuukuuuj] 6%uuuNuuueuuumuuumjRRRU65FFFSjuuumuuuhX -!]]]Geuuumuuuk`C JfuuumuuuhW,KRRRߦOKk* 1q]]]lDKːU=]]]jFFFQKuuuG'n(((L#i1R1,wS @(((c'X@ @`(G֙333c1<n s}mr  suuu~F  6 z֞VYFFFx v*_;;;\_333 ;;;eb y3_]]]333s/g;;;i!_iho;!YrX5n>:~nH˔iiiFK֞]]] u'Auuuum$2FFFvU_OX֡kGc_OY;;;h!;;;dr6N]]]˔D _|8Oiii:;;;et9[;;;i!_;;;r֓<URRRu8$|Q n><n'wĴ u$+(((w\X֟2 c;;;u/_q ,333v3335gd_p ,333v;;;i! 333iN(|ߩO_d+ }=  333iN>;;;i!_]]]~N,/+1FFFjf n@ nDAnQߨN`uuuu81m :uuuv]_d!333j;;;l$`d_d!333j;;;i!333h\!8(((O_j#9333< 333gY#F;;;i!_x F {֛@ nV  nߪ_/`n.333v w* :w߰o : 3 mRRRu5_c 333i;;;i!_d_c 333i;;;i!(((dc{֢> _Yy3 fYv;;;i!_f!Kq(((Vnqh]]]H*lyFFFn]Xr˕H%rm# @|d_d 333i;;;i!_d_d 333i;;;i!\;;;j'_]]]߬333j$\RRR;;;i!_cD;;;[gPb˞n6]]]vFFFv2J֞;;;}ߩ(((u([ߩ˕T suuuv: _c 333i;;;i!_c_c 333i;;;i! 6iiimR_U :u;;;i!_cYKRd Jߨnjb* wkD333w\Fx踎iiis=QkX[333c;;;bX[X[333c;;;bJzm%_ q*Y;;;i!X[MFFFd,/RRRhV*;;;gg >{iiit8 [x> _uuus8(;;;dc!Nz> >@333J333J>@ >@333J333JC333jߨuuur_* _֝l1 #Yu;;;i! >@ ,RRR[333i9=RRRiςe3 >kiiiK`\1iiib] 3uuue\1]]]f@8 n(moCbkbC 'OiiO' CbkbCCbkbC 'OiiO' *Jc jo khU6_w k jbF# :\ h l p;;;i!CbkbC*KdloieO+1U fj kgR16[ h li[FG\kiM# %NiiN$2VdN% 3XdN%CbnkV2*Qjpm]< 9iiivD  _q(   M;;;i!   ct#_c :~;;;i!5RRRu˔H\]9|;;;d Ru'HH,vFFFM;;;EJ%;;;IRRRaRRRhRRR`333I%:RRRVRRRfRRRdRRRO/  -]]]ORRRdRRRh]]]\H !%! $$ $%     6KJ6%+>C( 8OYUA     3U]C5TggM##MbO' Dcj\@ Rx賎u֛]]]OFˌ(((3 5RfdJ! >\jnk]C#  :Ugnk]D'(l@ OpKK(((K Ad( @ˏk'1333rx5  '[uuupX1h˒f2 A kx˓(((pQ' 8z[ @ˏgg;;;bXY[(((dTuuuqJ(miiir8 , m333_% (`}s3 :~bbcn;;;h!TRRRh' N֣KiiiO;;;wG]URߦ= %j˗FFF333s2   Mq' !,........* 333dFn;;;i! :֗6 'V]]]h]]]qv(((]]]333y9. ]]]]w]]]k9  :tRRRDg߬> Xn#  6JK6@_jqxj_A3Zuuujuuumuuumuuumuuumuuumuuumuuumuuumg]]]K%333hUn;;;i!G=  *]]]Ouuumiii{iiiyFFFt;;;}֡zh/  (Q nv˗FFFm`5gtK( i֥RRR[( 6]]]riii~RRR֜J.Te`F.5`sᅴs]' => ;;;P5  333ir n;;;i!R> /Rfh]A$#'Kk* 1q]]]lD CRRRzF duuuh5\ g!.(((f֜XTV333_ n(%333pbn;;;i! <F GFFFntQ31N333_8 ]Q%on:  (S 6 j֥FFFc+ 333e333߬uz6S uuue*HM;;;JHARRR\n;;;i!9}b 9ߩFFFz T_fKi333KR/ ~ߨg'(RRRj(((yK_ߥ M_˓H ;;;Z˙HVRRR~8(]]]Olswysm]]]P* ( M j i>ߨK n;;;i!2y MTX_333 ;;;eb y3333_cQ[1s|333wj#MdQ.CxU333`uuu}t,>]]]o<  ,3<gD3. %Yuuu|1 5sq3n;;;i!#;;;e֙? Uuuu~uuu}A _OY;;;h!;;;dr6N]]]˔D ;;;ROe333q55s֠y333wcG]H*>iiitY333X 333bp|3Ag, y|FRun;;;i!Y^ =uuugcCA](((vߨwV_p ,333v;;;i! 333iN(|ߩO Aiii}FFFrFFFM*nn|O1w;;;sy5O֘ˌGURK(((`!9|_`p(Y˞mn;;;i!M333g1. +Jch h\<_d!333j;;;i!333h\!8(((O,V5$e dnRRR[$;;;jFFF e|> #Xuߥ֙;;;dYbst> 5{RCyuOA, FFFFl+n;;;i!`O  _c 333i;;;i!(((dc{֢> 3uuur;;;FFFroth(((C#Q{Yd~RRR333n'3C='< []]]]]]]^Z< %+/GFFFbiiilU3+% .{˘˕֛m2 !]֝F n;;;i!$;;;j˙e*_d 333i;;;i!\;;;j' J֞G,333lJ CFFFY  !! 'FFFLiiiciiikiiiliiip]]]}RRRRRRRRRiiisiiimiiikiiicFFFL'cQ!c֡Yn;;;i!2z|, _c 333i;;;i! 6iiimR_]@333J333JC333jߨuuur_*  GC  JiiiiiiJ8 suuumF @A A`mpppppppnbC 333i* n;;;i!]= CbkbC 'OiiO' *Jc jo khU6%Kdd]]bjnm kbFH333a;;;oR1gwm:CbnppppppppnbC333g `'n;;;i!!V;;;9  A]]]\ <]lFFFd;;;hFFFd gbC!  eNn;;;i!Guuuk,VT  !  Xdk;;;e Y`J9 1FFFfWYFFFTNv= %hR2]]]]h{u6 8~=._uuukb= 'Ojuuul{]]]i dA (59+,9.'89, ,8<5(   deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/keymaps/0000755000175000017500000000000011357170241020713 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/keymaps/default.dkm0000644000175000017500000000430011357170241023031 0ustar keeskees000 000 001 027 002 1 003 2 004 3 005 4 006 5 007 6 008 7 009 8 010 9 011 0 012 - 013 = 014 127 015 009 016 q 017 w 018 e 019 r 020 t 021 y 022 u 023 i 024 o 025 p 026 [ 027 ] 028 013 029 159 030 a 031 s 032 d 033 f 034 g 035 h 036 j 037 k 038 l 039 ; 040 ' 041 ` 042 158 043 \ 044 z 045 x 046 c 047 v 048 b 049 n 050 m 051 , 052 . 053 / 054 158 055 * 056 160 057 032 058 000 059 132 060 133 061 134 062 135 063 136 064 137 065 138 066 139 067 140 068 141 069 144 070 145 071 146 072 147 073 148 074 - 075 149 076 150 077 151 078 + 079 152 080 153 081 154 082 155 083 156 084 000 085 000 086 000 087 142 088 143 089 000 090 000 091 000 092 \ 093 000 094 000 095 000 096 000 097 000 098 000 099 000 100 000 101 000 102 000 103 000 104 000 105 000 106 000 107 000 108 000 109 000 110 000 111 000 112 000 113 000 114 000 115 000 116 000 117 000 118 000 119 000 120 000 121 000 122 000 123 000 124 000 125 000 126 000 127 000 128 000 129 000 130 000 131 000 132 000 133 000 134 000 135 000 136 000 137 000 138 000 139 000 140 000 141 000 142 000 143 000 144 000 145 000 146 000 147 000 148 000 149 000 150 000 151 000 152 000 153 000 154 000 155 000 156 013 157 159 158 000 159 000 160 000 161 000 162 000 163 000 164 000 165 000 166 000 167 000 168 000 169 000 170 000 171 000 172 000 173 000 174 000 175 000 176 000 177 000 178 000 179 000 180 000 181 / 182 000 183 000 184 160 185 000 186 000 187 000 188 000 189 000 190 000 191 000 192 000 193 000 194 000 195 000 196 000 197 157 198 000 199 165 200 130 201 163 202 000 203 129 204 000 205 128 206 000 207 166 208 131 209 164 210 161 211 162 212 000 213 000 214 000 215 000 216 000 217 000 218 000 219 000 220 000 221 000 222 000 223 000 224 000 225 000 226 000 227 000 228 000 229 000 230 000 231 000 232 000 233 000 234 000 235 000 236 000 237 000 238 000 239 000 240 000 241 000 242 000 243 000 244 000 245 000 246 000 247 000 248 000 249 000 250 000 251 000 252 000 253 000 254 000 255 000 +Shift ' " , < - _ . > / ? 0 ) 1 ! 2 @ 3 # 4 $ 5 % 6 ^ 7 & 8 * 9 ( ; : = + A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z [ { \ | ] } a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/keymaps/fi.dkm0000644000175000017500000000033511357170241022007 0ustar keeskees012 + 013 026 027 ^ 039 040 043 ' 053 - 086 < 092 \ +Shift ` ' * ^ ~ , ; . : - _ < > 0 = 1 ! 2 " 3 # 4 5 % 6 & 7 / 8 ( 9 ) ; : + ? -Shift +Alt + \ 7 { 0 } 8 [ 9 ] < | 2 @ 3 4 $ ^ ~ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/keymaps/de.dkm0000644000175000017500000000073411357170241022004 0ustar keeskees012 013 021 z 026 027 + 039 040 041 ^ 043 # 044 y 053 - 086 < +Shift ^ 0 = 1 ! 2 " 3 4 $ 5 % 6 & 7 / 8 ( 9 ) ? ` + * # ' < > , ; . : - _ -Shift +Alt 2 3 7 { 8 [ 9 ] 0 } \ q @ + ~ < | m -Alt deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/0000755000175000017500000000000011523516205020140 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/0000755000175000017500000000000011357170242020731 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/def_read.c0000644000175000017500000024252211357170242022635 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * def_read.c: Doomsday Engine Definition File Reader * * A GHASTLY MESS!!! This should be rewritten. * * You have been warned! * * At the moment the idea is that a lot of macros are used to read a more * or less fixed structure of definitions, and if an error occurs then * "goto out_of_here;". It leads to a lot more code than an elegant parser * would require. * * The current implementation of the reader is a "structural" approach: * the definition file is parsed based on the structure implied by * the read tokens. A true parser would have syntax definitions for * a bunch of tokens, and the same parsing rules would be applied for * everything. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" #include "de_refresh.h" #include "de_defs.h" // XGClass.h is actually a part of the engine. #include "../../../plugins/common/include/xgclass.h" // MACROS ------------------------------------------------------------------ #define MAX_RECUR_DEPTH 30 #define MAX_TOKEN_LEN 128 // Some macros. #define STOPCHAR(x) (isspace(x) || x == ';' || x == '#' || x == '{' \ || x == '}' || x == '=' || x == '"' || x == '*' \ || x == '|') #define ISTOKEN(X) (!stricmp(token, X)) #define READSTR(X) if(!ReadString(X, sizeof(X))) { \ SetError("Syntax error in string value."); \ retVal = false; goto ded_end_read; } #define MISSING_SC_ERROR SetError("Missing semicolon."); \ retVal = false; goto ded_end_read; #define CHECKSC if(source->version <= 5) { ReadToken(); if(!ISTOKEN(";")) { MISSING_SC_ERROR; } } #define FINDBEGIN while(!ISTOKEN("{") && !source->atEnd) ReadToken(); #define FINDEND while(!ISTOKEN("}") && !source->atEnd) ReadToken(); #define ISLABEL(X) (!stricmp(label, X)) #define READLABEL if(!ReadLabel(label)) { retVal = false; goto ded_end_read; } \ if(ISLABEL("}")) break; #define READLABEL_NOBREAK if(!ReadLabel(label)) { retVal = false; goto ded_end_read; } #define FAILURE retVal = false; goto ded_end_read; #define READBYTE(X) if(!ReadByte(&X)) { FAILURE } #define READINT(X) if(!ReadInt(&X, false)) { FAILURE } #define READUINT(X) if(!ReadInt(&X, true)) { FAILURE } #define READFLT(X) if(!ReadFloat(&X)) { FAILURE } #define READNBYTEVEC(X,N) if(!ReadNByteVector(X, N)) { FAILURE } #define READFLAGS(X,P) if(!ReadFlags(&X, P)) { FAILURE } #define READBLENDMODE(X) if(!ReadBlendmode(&X)) { FAILURE } #define RV_BYTE(lab, X) if(ISLABEL(lab)) { READBYTE(X); } else #define RV_INT(lab, X) if(ISLABEL(lab)) { READINT(X); } else #define RV_UINT(lab, X) if(ISLABEL(lab)) { READUINT(X); } else #define RV_FLT(lab, X) if(ISLABEL(lab)) { READFLT(X); } else #define RV_VEC(lab, X, N) if(ISLABEL(lab)) { int b; FINDBEGIN; \ for(b=0; blineClass].iparm[IP].flagPrefix && \ xgClassLinks[l->lineClass].iparm[IP].flagPrefix[0]) { \ if(!ReadFlags(&I, xgClassLinks[l->lineClass].iparm[IP].flagPrefix)) { \ FAILURE } } \ else { if(!ReadString(S,sizeof(S))) { \ I = strtol(token,0,0); } } } else // TYPES ------------------------------------------------------------------- typedef struct dedsource_s { char* buffer; char* pos; boolean atEnd; int lineNumber; const char* fileName; int version; // v6 does not require semicolons. } dedsource_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // the actual classes are game-side extern xgclass_t* xgClassLinks; // PUBLIC DATA DEFINITIONS ------------------------------------------------- char dedReadError[512]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static dedsource_t sourceStack[MAX_RECUR_DEPTH]; static dedsource_t* source; // Points to the current source. static char token[MAX_TOKEN_LEN+1]; static char unreadToken[MAX_TOKEN_LEN+1]; // CODE -------------------------------------------------------------------- static char* sdup(const char* str) { char* newstr; if(!str) return NULL; newstr = M_Malloc(strlen(str) + 1); strcpy(newstr, str); return newstr; } static void SetError(char* str) { sprintf(dedReadError, "Error in %s:\n Line %i: %s", source ? source->fileName : "?", source ? source->lineNumber : 0, str); } static void SetError2(char* str, char* more) { sprintf(dedReadError, "Error in %s:\n Line %i: %s (%s)", source ? source->fileName : "?", source ? source->lineNumber : 0, str, more); } /** * Reads a single character from the input file. Increments the line * number counter if necessary. */ static int FGetC(void) { int ch = (unsigned char) *source->pos; if(ch) source->pos++; else source->atEnd = true; if(ch == '\n') source->lineNumber++; if(ch == '\r') return FGetC(); return ch; } /** * Undoes an FGetC. */ static int FUngetC(int ch) { if(source->atEnd) return 0; if(ch == '\n') source->lineNumber--; if(source->pos > source->buffer) source->pos--; return ch; } /** * Reads stuff until a newline is found. */ static void SkipComment(void) { int ch = FGetC(); boolean seq = false; if(ch == '\n') return; // Comment ends right away. if(ch != '>') // Single-line comment? { while(FGetC() != '\n' && !source->atEnd); } else // Multiline comment? { while(!source->atEnd) { ch = FGetC(); if(seq) { if(ch == '#') break; seq = false; } if(ch == '<') seq = true; } } } static int ReadToken(void) { int ch; char* out = token; // Has a token been unread? if(unreadToken[0]) { strcpy(token, unreadToken); strcpy(unreadToken, ""); return true; } ch = FGetC(); if(source->atEnd) return false; // Skip whitespace and comments in the beginning. while((ch == '#' || isspace(ch))) { if(ch == '#') SkipComment(); ch = FGetC(); if(source->atEnd) return false; } // Always store the first character. *out++ = ch; if(STOPCHAR(ch)) { // Stop here. *out = 0; return true; } while(!STOPCHAR(ch) && !source->atEnd) { // Store the character in the buffer. ch = FGetC(); *out++ = ch; } *(out - 1) = 0; // End token. // Put the last read character back in the stream. FUngetC(ch); return true; } static void UnreadToken(const char* token) { // The next time ReadToken() is called, this is returned. strcpy(unreadToken, token); } /** * Current pos in the file is at the first ". * Does not expand escape sequences, only checks for \". * * @return @c true, if successful. */ static int ReadStringEx(char* dest, int maxlen, boolean inside, boolean doubleq) { char* ptr = dest; int ch, esc = false, newl = false; if(!inside) { ReadToken(); if(!ISTOKEN("\"")) return false; } // Start reading the characters. ch = FGetC(); while(esc || ch != '"') // The string-end-character. { if(source->atEnd) return false; // If a newline is found, skip all whitespace that follows. if(newl) { if(isspace(ch)) { ch = FGetC(); continue; } else { // End the skip. newl = false; } } // An escape character? if(!esc && ch == '\\') esc = true; else { // In case it's something other than \" or \\, just insert // the whole sequence as-is. if(esc && ch != '"' && ch != '\\') *ptr++ = '\\'; esc = false; } if(ch == '\n') newl = true; // Store the character in the buffer. if(ptr - dest < maxlen && !esc && !newl) { *ptr++ = ch; if(doubleq && ch == '"') *ptr++ = '"'; } // Read the next character, please. ch = FGetC(); } // End the string in a null. *ptr = 0; return true; } static int ReadString(char* dest, int maxlen) { return ReadStringEx(dest, maxlen, false, false); } /** * Read a string of (pretty much) any length. */ static int ReadAnyString(char** dest) { char buffer[0x20000]; if(!ReadString(buffer, sizeof(buffer))) return false; // Get rid of the old string. if(*dest) M_Free(*dest); // Make sure it doesn't overflow. buffer[sizeof(buffer) - 1] = 0; // Make a copy. *dest = M_Malloc(strlen(buffer) + 1); strcpy(*dest, buffer); return true; } static int ReadNByteVector(unsigned char* dest, int max) { int i; FINDBEGIN; for(i = 0; i < max; ++i) { ReadToken(); if(ISTOKEN("}")) return true; dest[i] = strtoul(token, 0, 0); } FINDEND; return true; } /** * @return @c true, if successful. */ static int ReadByte(unsigned char* dest) { ReadToken(); if(ISTOKEN(";")) { SetError("Missing integer value."); return false; } *dest = strtoul(token, 0, 0); return true; } /** * @return @c true, if successful. */ static int ReadInt(int* dest, int unsign) { ReadToken(); if(ISTOKEN(";")) { SetError("Missing integer value."); return false; } *dest = unsign ? strtoul(token, 0, 0) : strtol(token, 0, 0); return true; } /** * @return @c true, if successful. */ static int ReadFloat(float* dest) { ReadToken(); if(ISTOKEN(";")) { SetError("Missing float value."); return false; } *dest = (float) strtod(token, 0); return true; } static int ReadFlags(int* dest, const char* prefix) { char flag[1024]; // By default, no flags are set. *dest = 0; ReadToken(); UnreadToken(token); if(ISTOKEN("\"")) { // The old format. if(!ReadString(flag, sizeof(flag))) return false; *dest = Def_EvalFlags(flag); return true; } for(;;) { // Read the flag. ReadToken(); if(prefix) { strcpy(flag, prefix); strcat(flag, token); } else { strcpy(flag, token); } *dest |= Def_EvalFlags(flag); if(!ReadToken()) break; if(!ISTOKEN("|")) // | is required for multiple flags. { UnreadToken(token); break; } } return true; } static int ReadBlendmode(blendmode_t* dest) { char flag[1024]; blendmode_t bm; // By default, the blendmode is "normal". *dest = BM_NORMAL; ReadToken(); UnreadToken(token); if(ISTOKEN("\"")) { // The old format. if(!ReadString(flag, sizeof(flag))) return false; bm = (blendmode_t) Def_EvalFlags(flag); if(bm != BM_NORMAL) *dest = bm; return true; } // Read the blendmode. ReadToken(); strcpy(flag, "bm_"); strcat(flag, token); bm = (blendmode_t) Def_EvalFlags(flag); if(bm != BM_NORMAL) *dest = bm; return true; } /** * @return @c true, if successful. */ static int ReadLabel(char* label) { strcpy(label, ""); for(;;) { ReadToken(); if(source->atEnd) { SetError("Unexpected end of file."); return false; } if(ISTOKEN("}")) // End block. { strcpy(label, token); return true; } if(ISTOKEN(";")) { if(source->version <= 5) { SetError("Label without value."); return false; } continue; // Semicolons are optional in v6. } if(ISTOKEN("=") || ISTOKEN("{")) break; if(label[0]) strcat(label, " "); strcat(label, token); } return true; } static void DED_Include(const char* fileName, directory_t* dir) { filename_t tmp, path; M_TranslatePath(tmp, fileName, FILENAME_T_MAXLEN); if(!Dir_IsAbsolute(tmp)) { dd_snprintf(path, FILENAME_T_MAXLEN, "%s%s", dir->path, tmp); } else { strncpy(path, tmp, FILENAME_T_MAXLEN); } Def_ReadProcessDED(path); strncpy(token, "", MAX_TOKEN_LEN); } static void DED_InitReader(char* buffer, const char* fileName) { if(source && source - sourceStack >= MAX_RECUR_DEPTH) { Con_Error("DED_InitReader: Include recursion is too deep.\n"); } if(!source) { // This'll be the first source. source = sourceStack; } else { // Take the next entry in the stack. source++; } source->pos = source->buffer = buffer; source->atEnd = false; source->lineNumber = 1; source->fileName = fileName; source->version = DED_VERSION; } static void DED_CloseReader(void) { if(source == sourceStack) { source = NULL; } else { memset(source, 0, sizeof(*source)); source--; } } /** * @param cond Condition token. Can be a command line option * or a game mode. * @return @c true if the condition passes. */ static boolean DED_CheckCondition(const char* cond, boolean expected) { boolean value = false; if(cond[0] == '-') { // It's a command line option. value = (ArgCheck(token) != 0); } else if(isalnum(cond[0])) { // Then it must be a game mode. value = !stricmp(cond, (char *) gx.GetVariable(DD_GAME_MODE)); } return value == expected; } /** * Reads definitions from the given buffer. * The definition is being loaded from @sourcefile (DED or WAD). * * @param buffer The data to be read, must be null-terminated. * @param sourceFile Just FYI. */ static int DED_ReadData(ded_t* ded, char* buffer, const char* sourceFile) { char dummy[128], label[128], tmp[256]; int dummyInt, idx, retVal = true; int prevMobjDefIdx = -1; // For "Copy". int prevStateDefIdx = -1; // For "Copy" int prevLightDefIdx = -1; // For "Copy". int prevMaterialDefIdx = -1; // For "Copy". int prevModelDefIdx = -1; // For "Copy". int prevMapInfoDefIdx = -1; // For "Copy". int prevSkyDefIdx = -1; // For "Copy". int prevDetailDefIdx = -1; // For "Copy". int prevGenDefIdx = -1; // For "Copy". int prevDecorDefIdx = -1; // For "Copy". int prevRefDefIdx = -1; // For "Copy". int prevLineTypeDefIdx = -1; // For "Copy". int prevSectorTypeDefIdx = -1; // For "Copy". int depth; char* rootStr = 0, *ptr; int bCopyNext = 0; directory_t fileDir; memset(&fileDir, 0, sizeof(fileDir)); // For including other files -- we must know where we are. Dir_FileDir(sourceFile, &fileDir); // Get the next entry from the source stack. DED_InitReader(buffer, sourceFile); while(ReadToken()) { if(ISTOKEN("Copy") || ISTOKEN("*")) { bCopyNext = true; continue; // Read the next token. } if(ISTOKEN(";")) { // Unnecessary semicolon? Just skip it. continue; } if(ISTOKEN("SkipIf")) { boolean expected = true; ReadToken(); if(ISTOKEN("Not")) { expected = false; ReadToken(); } if(DED_CheckCondition(token, expected)) { // Ah, we're done. Get out of here. goto ded_end_read; } CHECKSC; } if(ISTOKEN("Include")) { // A new include. READSTR(tmp); CHECKSC; DED_Include(tmp, &fileDir); strcpy(label, ""); } if(ISTOKEN("IncludeIf")) // An optional include. { boolean expected = true; ReadToken(); if(ISTOKEN("Not")) { expected = false; ReadToken(); } if(DED_CheckCondition(token, expected)) { READSTR(tmp); CHECKSC; DED_Include(tmp, &fileDir); strcpy(label, ""); } else { // Arg not found; just skip it. READSTR(tmp); CHECKSC; } } if(ISTOKEN("ModelPath")) { // A new model path. Append to the list. READSTR(label); CHECKSC; Dir_ValidDir(label, 128); R_AddClassDataPath(DDRC_MODEL, label, true); } if(ISTOKEN("Header")) { FINDBEGIN; for(;;) { READLABEL; if(ISLABEL("Version")) { READINT(ded->version); source->version = ded->version; } else RV_STR("Thing prefix", dummy) RV_STR("State prefix", dummy) RV_STR("Sprite prefix", dummy) RV_STR("Sfx prefix", dummy) RV_STR("Mus prefix", dummy) RV_STR("Text prefix", dummy) RV_STR("Model path", ded->modelPath) RV_FLAGS("Common model flags", ded->modelFlags, "df_") RV_FLT("Default model scale", ded->modelScale) RV_FLT("Default model offset", ded->modelOffset) RV_END CHECKSC; } } if(ISTOKEN("Flag")) { // A new flag. idx = DED_AddFlag(ded, "", "", 0); FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", ded->flags[idx].id) RV_UINT("Value", ded->flags[idx].value) RV_STR("Info", ded->flags[idx].text) RV_END CHECKSC; } } if(ISTOKEN("Thing")) { ded_mobj_t* mo; // A new thing. idx = DED_AddMobj(ded, ""); mo = &ded->mobjs[idx]; if(prevMobjDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(mo, ded->mobjs + prevMobjDefIdx, sizeof(*mo)); } FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", mo->id) RV_INT("DoomEd number", mo->doomEdNum) RV_STR("Name", mo->name) RV_STR("Spawn state", mo->states[SN_SPAWN]) RV_STR("See state", mo->states[SN_SEE]) RV_STR("Pain state", mo->states[SN_PAIN]) RV_STR("Melee state", mo->states[SN_MELEE]) RV_STR("Missile state", mo->states[SN_MISSILE]) RV_STR("Crash state", mo->states[SN_CRASH]) RV_STR("Death state", mo->states[SN_DEATH]) RV_STR("Xdeath state", mo->states[SN_XDEATH]) RV_STR("Raise state", mo->states[SN_RAISE]) RV_STR("See sound", mo->seeSound) RV_STR("Attack sound", mo->attackSound) RV_STR("Pain sound", mo->painSound) RV_STR("Death sound", mo->deathSound) RV_STR("Active sound", mo->activeSound) RV_INT("Reaction time", mo->reactionTime) RV_INT("Pain chance", mo->painChance) RV_INT("Spawn health", mo->spawnHealth) RV_FLT("Speed", mo->speed) RV_FLT("Radius", mo->radius) RV_FLT("Height", mo->height) RV_INT("Mass", mo->mass) RV_INT("Damage", mo->damage) RV_FLAGS("Flags", mo->flags[0], "mf_") RV_FLAGS("Flags2", mo->flags[1], "mf2_") RV_FLAGS("Flags3", mo->flags[2], "mf3_") RV_INT("Misc1", mo->misc[0]) RV_INT("Misc2", mo->misc[1]) RV_INT("Misc3", mo->misc[2]) RV_INT("Misc4", mo->misc[3]) RV_END CHECKSC; } prevMobjDefIdx = idx; } if(ISTOKEN("State")) { ded_state_t* st; // A new state. idx = DED_AddState(ded, ""); st = &ded->states[idx]; if(prevStateDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(st, ded->states + prevStateDefIdx, sizeof(*st)); } FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", st->id) RV_FLAGS("Flags", st->flags, "statef_") RV_STR("Sprite", st->sprite.id) RV_INT("Frame", st->frame) RV_INT("Tics", st->tics) RV_STR("Action", st->action) RV_STR("Next state", st->nextState) RV_INT("Misc1", st->misc[0]) RV_INT("Misc2", st->misc[1]) RV_INT("Misc3", st->misc[2]) RV_ANYSTR("Execute", st->execute) RV_END CHECKSC; } prevStateDefIdx = idx; } if(ISTOKEN("Sprite")) { // A new sprite. idx = DED_AddSprite(ded, ""); FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", ded->sprites[idx].id) RV_END CHECKSC; } } if(ISTOKEN("Light")) { ded_light_t* lig; // A new light. idx = DED_AddLight(ded, ""); lig = &ded->lights[idx]; if(prevLightDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(lig, ded->lights + prevLightDefIdx, sizeof(*lig)); } FINDBEGIN; for(;;) { READLABEL; RV_STR("State", lig->state) RV_STR("Map", lig->uniqueMapID) RV_FLT("X Offset", lig->offset[VX]) RV_FLT("Y Offset", lig->offset[VY]) RV_VEC("Origin", lig->offset, 3) RV_FLT("Size", lig->size) RV_FLT("Intensity", lig->size) RV_FLT("Red", lig->color[0]) RV_FLT("Green", lig->color[1]) RV_FLT("Blue", lig->color[2]) RV_VEC("Color", lig->color, 3) if(ISLABEL("Sector levels")) { int b; FINDBEGIN; for(b = 0; b < 2; ++b) { READFLT(lig->lightLevel[b]) lig->lightLevel[b] /= 255.0f; if(lig->lightLevel[b] < 0) lig->lightLevel[b] = 0; else if(lig->lightLevel[b] > 1) lig->lightLevel[b] = 1; } ReadToken(); } else RV_FLAGS("Flags", lig->flags, "lgf_") RV_STR("Top map", lig->up.id) RV_STR("Bottom map", lig->down.id) RV_STR("Side map", lig->sides.id) RV_STR("Flare map", lig->flare.id) RV_FLT("Halo radius", lig->haloRadius) RV_END CHECKSC; } prevLightDefIdx = idx; } if(ISTOKEN("Material")) { int stage = 0; uint layer = 0; ded_material_t* mat; // A new material. idx = DED_AddMaterial(ded, ""); mat = &ded->materials[idx]; if(prevMaterialDefIdx >= 0 && bCopyNext) { uint i; // Should we copy the previous definition? memcpy(mat, ded->materials + prevMaterialDefIdx, sizeof(*mat)); // Duplicate the stage arrays. for(i = 0; i < DED_MAX_MATERIAL_LAYERS; ++i) { ded_material_layer_t* l = &ded->materials[prevMaterialDefIdx].layers[i]; if(l->stages) { mat->layers[i].stages = M_Malloc(sizeof(ded_material_layer_stage_t) * mat->layers[i].stageCount.max); memcpy(mat->layers[i].stages, l->stages, sizeof(ded_material_layer_stage_t) * mat->layers[i].stageCount.num); } } } FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", mat->id.name) RV_FLAGS("Namespace", mat->id.mnamespace, "mn_") RV_FLAGS("Flags", mat->flags, "matf_") RV_FLT("Width", mat->width) RV_FLT("Height", mat->height) if(ISLABEL("Layer")) { if(layer >= DED_MAX_MATERIAL_LAYERS) Con_Error("DED_ReadData: Too many material layers " "(%s).\n", mat->id.name); FINDBEGIN; for(;;) { READLABEL; if(ISLABEL("Stage")) { ded_material_layer_stage_t* st = NULL; if(stage >= mat->layers[layer].stageCount.num) { // Allocate new stage. stage = DED_AddMaterialLayerStage(&mat->layers[layer]); } st = &mat->layers[layer].stages[stage]; FINDBEGIN; for(;;) { READLABEL; if(ISLABEL("Texture") || ISLABEL("Flat") || ISLABEL("Sprite") || ISLABEL("System")) { st->type = ( ISLABEL("Texture")? GLT_DOOMTEXTURE : ISLABEL("Flat")? GLT_FLAT : ISLABEL("Sprite")? GLT_SPRITE : GLT_SYSTEM); READSTR(st->name); } else RV_INT("Tics", st->tics) RV_FLT("Rnd", st->variance) RV_END CHECKSC; } stage++; } else RV_END CHECKSC; } layer++; } else RV_END CHECKSC; } prevMaterialDefIdx = idx; } if(ISTOKEN("Model")) { uint sub = 0; ded_model_t* mdl, *prevModel = NULL; // A new model. idx = DED_AddModel(ded, ""); mdl = &ded->models[idx]; if(prevModelDefIdx >= 0) { prevModel = ded->models + prevModelDefIdx; // Should we copy the previous definition? if(bCopyNext) memcpy(mdl, prevModel, sizeof(*mdl)); } FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", mdl->id) RV_STR("State", mdl->state) RV_INT("Off", mdl->off) RV_STR("Sprite", mdl->sprite.id) RV_INT("Sprite frame", mdl->spriteFrame) RV_FLAGS("Group", mdl->group, "mg_") RV_INT("Selector", mdl->selector) RV_FLAGS("Flags", mdl->flags, "df_") RV_FLT("Inter", mdl->interMark) RV_INT("Skin tics", mdl->skinTics) RV_FLT("Resize", mdl->resize) if(ISLABEL("Scale")) { READFLT(mdl->scale[1]); mdl->scale[0] = mdl->scale[2] = mdl->scale[1]; } else RV_VEC("Scale XYZ", mdl->scale, 3) RV_FLT("Offset", mdl->offset[1]) RV_VEC("Offset XYZ", mdl->offset, 3) RV_VEC("Interpolate", mdl->interRange, 2) RV_FLT("Shadow radius", mdl->shadowRadius) if(ISLABEL("Md2") || ISLABEL("Sub")) { if(sub >= DED_MAX_SUB_MODELS) Con_Error("DED_ReadData: Too many submodels (%s).\n", mdl->state); FINDBEGIN; for(;;) { READLABEL; RV_STR("File", mdl->sub[sub].filename.path) RV_STR("Frame", mdl->sub[sub].frame) RV_INT("Frame range", mdl->sub[sub].frameRange) RV_BLENDMODE("Blending mode", mdl->sub[sub].blendMode) RV_INT("Skin", mdl->sub[sub].skin) RV_STR("Skin file", mdl->sub[sub].skinFilename.path) RV_INT("Skin range", mdl->sub[sub].skinRange) RV_VEC("Offset XYZ", mdl->sub[sub].offset, 3) RV_FLAGS("Flags", mdl->sub[sub].flags, "df_") RV_FLT("Transparent", mdl->sub[sub].alpha) RV_FLT("Parm", mdl->sub[sub].parm) RV_BYTE("Selskin mask", mdl->sub[sub].selSkinBits[0]) RV_BYTE("Selskin shift", mdl->sub[sub].selSkinBits[1]) RV_NBVEC("Selskins", mdl->sub[sub].selSkins, 8) RV_STR("Shiny skin", mdl->sub[sub].shinySkin) RV_FLT("Shiny", mdl->sub[sub].shiny) RV_VEC("Shiny color", mdl->sub[sub].shinyColor, 3) RV_FLT("Shiny reaction", mdl->sub[sub].shinyReact) RV_END CHECKSC; } sub++; } else RV_END CHECKSC; } // Some post-processing. No point in doing this in a fancy way, // the whole reader will be rewritten sooner or later... if(prevModel) { int i; if(!strcmp(mdl->state, "-")) strcpy(mdl->state, prevModel->state); if(!strcmp(mdl->sprite.id, "-")) strcpy(mdl->sprite.id, prevModel->sprite.id); //if(!strcmp(mdl->group, "-")) strcpy(mdl->group, prevModel->group); //if(!strcmp(mdl->flags, "-")) strcpy(mdl->flags, prevModel->flags); for(i = 0; i < DED_MAX_SUB_MODELS; ++i) { if(!strcmp(mdl->sub[i].filename.path, "-")) strcpy(mdl->sub[i].filename.path, prevModel->sub[i].filename.path); if(!strcmp(mdl->sub[i].frame, "-")) strcpy(mdl->sub[i].frame, prevModel->sub[i].frame); //if(!strcmp(mdl->sub[i].flags, "-")) strcpy(mdl->sub[i].flags, prevModel->sub[i].flags); } } prevModelDefIdx = idx; } if(ISTOKEN("Sound")) { // A new sound. ded_sound_t* snd; idx = DED_AddSound(ded, ""); snd = &ded->sounds[idx]; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", snd->id) RV_STR("Lump", snd->lumpName) RV_STR("Name", snd->name) RV_STR("Link", snd->link) RV_INT("Link pitch", snd->linkPitch) RV_INT("Link volume", snd->linkVolume) RV_INT("Priority", snd->priority) RV_INT("Max channels", snd->channels) RV_INT("Group", snd->group) RV_FLAGS("Flags", snd->flags, "sf_") RV_STR("Ext", snd->ext.path) RV_STR("File", snd->ext.path) RV_STR("File name", snd->ext.path) RV_END CHECKSC; } } if(ISTOKEN("Music")) { // A new music. ded_music_t* mus; idx = DED_AddMusic(ded, ""); mus = &ded->music[idx]; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", mus->id) RV_STR("Lump", mus->lumpName) RV_STR("File name", mus->path.path) RV_STR("File", mus->path.path) RV_STR("Ext", mus->path.path) // Both work. RV_INT("CD track", mus->cdTrack) RV_END CHECKSC; } } if(ISTOKEN("Sky")) { // A new sky definition. uint sub; ded_sky_t* sky; idx = DED_AddSky(ded, ""); sky = &ded->skies[idx]; if(prevSkyDefIdx >= 0 && bCopyNext) { int m; // Should we copy the previous definition? memcpy(sky, ded->skies + prevSkyDefIdx, sizeof(*sky)); for(m = 0; m < NUM_SKY_MODELS; ++m) { sky->models[m].execute = sdup(sky->models[m].execute); } } prevSkyDefIdx = idx; sub = 0; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", sky->id) RV_FLAGS("Flags", sky->flags, "sif_") RV_FLT("Height", sky->height) RV_FLT("Horizon offset", sky->horizonOffset) RV_VEC("Light color", sky->color, 3) if(ISLABEL("Layer 1") || ISLABEL("Layer 2")) { ded_skylayer_t *sl = sky->layers + atoi(label+6) - 1; FINDBEGIN; for(;;) { READLABEL; if(ISLABEL("Texture") || ISLABEL("Flat") || ISLABEL("Sprite") || ISLABEL("System")) { sl->material.mnamespace = ( ISLABEL("Texture")? MN_TEXTURES : ISLABEL("Flat")? MN_FLATS : ISLABEL("Sprite")? MN_SPRITES : MN_SYSTEM); READSTR(sl->material.name); } else RV_FLAGS("Flags", sl->flags, "slf_") RV_FLT("Offset", sl->offset) RV_FLT("Color limit", sl->colorLimit) RV_END CHECKSC; } } else if(ISLABEL("Model")) { ded_skymodel_t *sm = &sky->models[sub]; if(sub == NUM_SKY_MODELS) { // Too many! SetError("Too many sky models."); retVal = false; goto ded_end_read; } sub++; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", sm->id) RV_INT("Layer", sm->layer) RV_FLT("Frame interval", sm->frameInterval) RV_FLT("Yaw", sm->yaw) RV_FLT("Yaw speed", sm->yawSpeed) RV_VEC("Rotate", sm->rotate, 2) RV_VEC("Offset factor", sm->coordFactor, 3) RV_VEC("Color", sm->color, 4) RV_ANYSTR("Execute", sm->execute) RV_END CHECKSC; } } else RV_END CHECKSC; } } if(ISTOKEN("Map")) // Info { // A new map info. uint sub; ded_mapinfo_t* mi; idx = DED_AddMapInfo(ded, ""); mi = &ded->mapInfo[idx]; if(prevMapInfoDefIdx >= 0 && bCopyNext) { int m; // Should we copy the previous definition? memcpy(mi, ded->mapInfo + prevMapInfoDefIdx, sizeof(*mi)); mi->execute = sdup(mi->execute); for(m = 0; m < NUM_SKY_MODELS; ++m) { mi->sky.models[m].execute = sdup(mi->sky.models[m].execute); } } prevMapInfoDefIdx = idx; sub = 0; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", mi->id) RV_STR("Name", mi->name) RV_STR("Author", mi->author) RV_FLAGS("Flags", mi->flags, "mif_") RV_STR("Music", mi->music) RV_FLT("Par time", mi->parTime) RV_FLT("Fog color R", mi->fogColor[0]) RV_FLT("Fog color G", mi->fogColor[1]) RV_FLT("Fog color B", mi->fogColor[2]) RV_FLT("Fog start", mi->fogStart) RV_FLT("Fog end", mi->fogEnd) RV_FLT("Fog density", mi->fogDensity) RV_FLT("Ambient light", mi->ambient) RV_FLT("Gravity", mi->gravity) RV_ANYSTR("Execute", mi->execute) RV_STR("Sky", mi->skyID) RV_FLT("Sky height", mi->sky.height) RV_FLT("Horizon offset", mi->sky.horizonOffset) RV_VEC("Sky light color", mi->sky.color, 3) if(ISLABEL("Sky Layer 1") || ISLABEL("Sky Layer 2")) { ded_skylayer_t *sl = mi->sky.layers + atoi(label+10) - 1; FINDBEGIN; for(;;) { READLABEL; if(ISLABEL("Texture") || ISLABEL("Flat") || ISLABEL("Sprite") || ISLABEL("System")) { sl->material.mnamespace = ( ISLABEL("Texture")? MN_TEXTURES : ISLABEL("Flat")? MN_FLATS : ISLABEL("Sprite")? MN_SPRITES : MN_SYSTEM); READSTR(sl->material.name); } else RV_FLAGS("Flags", sl->flags, "slf_") RV_FLT("Offset", sl->offset) RV_FLT("Color limit", sl->colorLimit) RV_END CHECKSC; } } else if(ISLABEL("Sky Model")) { ded_skymodel_t *sm = &mi->sky.models[sub]; if(sub == NUM_SKY_MODELS) { // Too many! SetError("Too many sky models."); retVal = false; goto ded_end_read; } sub++; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", sm->id) RV_INT("Layer", sm->layer) RV_FLT("Frame interval", sm->frameInterval) RV_FLT("Yaw", sm->yaw) RV_FLT("Yaw speed", sm->yawSpeed) RV_VEC("Rotate", sm->rotate, 2) RV_VEC("Offset factor", sm->coordFactor, 3) RV_VEC("Color", sm->color, 4) RV_ANYSTR("Execute", sm->execute) RV_END CHECKSC; } } else RV_END CHECKSC; } } if(ISTOKEN("Text")) { // A new text. ded_text_t* txt; idx = DED_AddText(ded, ""); txt = &ded->text[idx]; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", txt->id) if(ISLABEL("Text")) { // Allocate a 'huge' buffer. char* temp = M_Malloc(0x10000); if(ReadString(temp, 0xffff)) { size_t len = strlen(temp) + 1; txt->text = M_Realloc(temp, len); //memcpy(ded->text[idx].text, temp, len); } else { M_Free(temp); SetError("Syntax error in text value."); retVal = false; goto ded_end_read; } } else RV_END CHECKSC; } } if(ISTOKEN("Texture")) // Environment { // A new texenv. ded_tenviron_t* tenv; idx = DED_AddTextureEnv(ded, ""); tenv = &ded->textureEnv[idx]; FINDBEGIN; for(;;) { ded_materialid_t* mn; READLABEL; RV_STR("ID", tenv->id) if(ISLABEL("Texture") || ISLABEL("Flat") || ISLABEL("Sprite") || ISLABEL("System")) { // A new material name. mn = DED_NewEntry((void**)&tenv->materials, &tenv->count, sizeof(*mn)); mn->mnamespace = (ISLABEL("Texture")? MN_TEXTURES : ISLABEL("Flat")? MN_FLATS : ISLABEL("Sprite")? MN_SPRITES : MN_SYSTEM); FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", mn->name) RV_END CHECKSC; } } else RV_END CHECKSC; } } if(ISTOKEN("Values")) // String Values { depth = 0; rootStr = M_Calloc(1); // A null string. FINDBEGIN; for(;;) { // Get the next label but don't stop on }. READLABEL_NOBREAK; if(strchr(label, '|')) { SetError("Value labels can't include | characters (ASCII 124)."); retVal = false; goto ded_end_read; } if(ISTOKEN("=")) { // Define a new string. char* temp = M_Malloc(0x1000); // A 'huge' buffer. if(ReadString(temp, 0xffff)) { ded_value_t* val; // Resize the buffer down to actual string length. temp = M_Realloc(temp, strlen(temp) + 1); // Get a new value entry. idx = DED_AddValue(ded, 0); val = &ded->values[idx]; val->text = temp; // Compose the identifier. val->id = M_Malloc(strlen(rootStr) + strlen(label) + 1); strcpy(val->id, rootStr); strcat(val->id, label); } else { M_Free(temp); SetError("Syntax error in string value."); retVal = false; goto ded_end_read; } } else if(ISTOKEN("{")) { // Begin a new group. rootStr = M_Realloc(rootStr, strlen(rootStr) + strlen(label) + 2); strcat(rootStr, label); strcat(rootStr, "|"); // The separator. // Increase group level. depth++; continue; } else if(ISTOKEN("}")) { size_t len; // End group. if(!depth) break; // End root depth. // Decrease level and modify rootStr. depth--; len = strlen(rootStr); rootStr[len-1] = 0; // Remove last |. ptr = strrchr(rootStr, '|'); if(ptr) { ptr[1] = 0; rootStr = M_Realloc(rootStr, strlen(rootStr) + 1); } else { // Back to level zero. rootStr = M_Realloc(rootStr, 1); *rootStr = 0; } } else { // Only the above characters are allowed. SetError("Illegal token."); retVal = false; goto ded_end_read; } CHECKSC; } M_Free(rootStr); rootStr = 0; } if(ISTOKEN("Detail")) // Detail Texture { ded_detailtexture_t* dtl; idx = DED_AddDetail(ded, ""); dtl = &ded->details[idx]; if(prevDetailDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(dtl, ded->details + prevDetailDefIdx, sizeof(*dtl)); } FINDBEGIN; for(;;) { READLABEL; RV_FLAGS("Flags", dtl->flags, "dtf_") if(ISLABEL("Texture")) { READSTR(dtl->material1.name) dtl->material1.mnamespace = MN_TEXTURES; } else if(ISLABEL("Wall")) // Alias { READSTR(dtl->material1.name) dtl->material1.mnamespace = MN_TEXTURES; } else if(ISLABEL("Flat")) { READSTR(dtl->material2.name) dtl->material2.mnamespace = MN_FLATS; } else if(ISLABEL("Lump")) { READSTR(dtl->detailLump.path) dtl->isExternal = false; } else if(ISLABEL("File")) { READSTR(dtl->detailLump.path) dtl->isExternal = true; } else RV_FLT("Scale", dtl->scale) RV_FLT("Strength", dtl->strength) RV_FLT("Distance", dtl->maxDist) RV_END CHECKSC; } prevDetailDefIdx = idx; } if(ISTOKEN("Reflection")) // Surface reflection { ded_reflection_t *ref = NULL; idx = DED_AddReflection(ded); ref = &ded->reflections[idx]; if(prevRefDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(ref, ded->reflections + prevRefDefIdx, sizeof(*ref)); } FINDBEGIN; for(;;) { READLABEL; RV_FLAGS("Flags", ref->flags, "rff_") RV_FLT("Shininess", ref->shininess) RV_VEC("Min color", ref->minColor, 3) RV_BLENDMODE("Blending mode", ref->blendMode) RV_STR("Shiny map", ref->shinyMap.path) RV_STR("Mask map", ref->maskMap.path) RV_FLT("Mask width", ref->maskWidth) RV_FLT("Mask height", ref->maskHeight) if(ISLABEL("Texture")) { READSTR(ref->material.name) ref->material.mnamespace = MN_TEXTURES; } else if(ISLABEL("Flat")) { READSTR(ref->material.name) ref->material.mnamespace = MN_FLATS; } else RV_END CHECKSC; } prevRefDefIdx = idx; } if(ISTOKEN("Generator")) // Particle Generator { int sub = 0; ded_ptcgen_t* gen; idx = DED_AddPtcGen(ded, ""); gen = &ded->ptcGens[idx]; if(prevGenDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(gen, &ded->ptcGens[prevGenDefIdx], sizeof(*gen)); // Duplicate the stages array. if(ded->ptcGens[prevGenDefIdx].stages) { gen->stages = M_Malloc(sizeof(ded_ptcstage_t) * gen->stageCount.max); memcpy(gen->stages, ded->ptcGens[prevGenDefIdx].stages, sizeof(ded_ptcstage_t) * gen->stageCount.num); } } FINDBEGIN; for(;;) { READLABEL; RV_STR("State", gen->state) if(ISLABEL("Flat")) { READSTR(gen->material.name) gen->material.mnamespace = MN_FLATS; } else if(ISLABEL("Texture")) { READSTR(gen->material.name) gen->material.mnamespace = MN_TEXTURES; } else RV_STR("Mobj", gen->type) RV_STR("Alt mobj", gen->type2) RV_STR("Damage mobj", gen->damage) RV_STR("Map", gen->map) RV_FLAGS("Flags", gen->flags, "gnf_") RV_FLT("Speed", gen->speed) RV_FLT("Speed Rnd", gen->speedVariance) RV_VEC("Vector", gen->vector, 3) RV_FLT("Vector Rnd", gen->vectorVariance) RV_FLT("Init vector Rnd", gen->initVectorVariance) RV_VEC("Center", gen->center, 3) RV_INT("Submodel", gen->subModel) RV_FLT("Spawn radius", gen->spawnRadius) RV_FLT("Min spawn radius", gen->spawnRadiusMin) RV_FLT("Distance", gen->maxDist) RV_INT("Spawn age", gen->spawnAge) RV_INT("Max age", gen->maxAge) RV_INT("Particles", gen->particles) RV_FLT("Spawn rate", gen->spawnRate) RV_FLT("Spawn Rnd", gen->spawnRateVariance) RV_INT("Presim", gen->preSim) RV_INT("Alt start", gen->altStart) RV_FLT("Alt Rnd", gen->altStartVariance) RV_VEC("Force axis", gen->forceAxis, 3) RV_FLT("Force radius", gen->forceRadius) RV_FLT("Force", gen->force) RV_VEC("Force origin", gen->forceOrigin, 3) if(ISLABEL("Stage")) { ded_ptcstage_t *st = NULL; if(sub >= gen->stageCount.num) { // Allocate new stage. sub = DED_AddPtcGenStage(gen); } st = &gen->stages[sub]; FINDBEGIN; for(;;) { READLABEL; RV_FLAGS("Type", st->type, "pt_") RV_INT("Tics", st->tics) RV_FLT("Rnd", st->variance) RV_VEC("Color", st->color, 4) RV_FLT("Radius", st->radius) RV_FLT("Radius rnd", st->radiusVariance) RV_FLAGS("Flags", st->flags, "ptf_") RV_FLT("Bounce", st->bounce) RV_FLT("Gravity", st->gravity) RV_FLT("Resistance", st->resistance) RV_STR("Frame", st->frameName) RV_STR("End frame", st->endFrameName) RV_VEC("Spin", st->spin, 2) RV_VEC("Spin resistance", st->spinResistance, 2) RV_STR("Sound", st->sound.name) RV_FLT("Volume", st->sound.volume) RV_STR("Hit sound", st->hitSound.name) RV_FLT("Hit volume", st->hitSound.volume) RV_VEC("Force", st->vectorForce, 3) RV_END CHECKSC; } sub++; } else RV_END CHECKSC; } prevGenDefIdx = idx; } if(ISTOKEN("Finale") || ISTOKEN("InFine")) { ded_finale_t* fin; idx = DED_AddFinale(ded); fin = &ded->finales[idx]; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", fin->id) RV_STR("Before", fin->before) RV_STR("After", fin->after) RV_INT("Game", dummyInt) if(ISLABEL("Script")) { // Allocate an "enormous" 64K buffer. char *temp = M_Calloc(0x10000), *ptr; if(fin->script) M_Free(fin->script); FINDBEGIN; ptr = temp; ReadToken(); while(!ISTOKEN("}") && !source->atEnd) { if(ptr != temp) *ptr++ = ' '; strcpy(ptr, token); ptr += strlen(token); if(ISTOKEN("\"")) { ReadStringEx(ptr, 0x10000 - (ptr-temp), true, true); ptr += strlen(ptr); // Continue from the null. *ptr++ = '"'; } ReadToken(); } fin->script = M_Realloc(temp, strlen(temp) + 1); } else RV_END CHECKSC; } } if(ISTOKEN("Decoration")) { uint sub; ded_decor_t *decor; idx = DED_AddDecoration(ded); decor = &ded->decorations[idx]; sub = 0; if(prevDecorDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(decor, ded->decorations + prevDecorDefIdx, sizeof(*decor)); } FINDBEGIN; for(;;) { READLABEL; RV_FLAGS("Flags", decor->flags, "dcf_") if(ISLABEL("Texture")) { READSTR(decor->material.name) decor->material.mnamespace = MN_TEXTURES; } else if(ISLABEL("Flat")) { READSTR(decor->material.name) decor->material.mnamespace = MN_FLATS; } else if(ISLABEL("Model")) { ded_decormodel_t *dm = &decor->models[sub]; if(sub == DED_DECOR_NUM_MODELS) { SetError("Too many models in decoration."); retVal = false; goto ded_end_read; } FINDBEGIN; for(;;) { READLABEL; RV_VEC("Offset", dm->pos, 2) RV_FLT("Distance", dm->elevation) RV_IVEC("Pattern offset", dm->patternOffset, 2) RV_IVEC("Pattern skip", dm->patternSkip, 2) if(ISLABEL("Levels")) { int b; FINDBEGIN; for(b = 0; b < 2; ++b) { READFLT(dm->lightLevels[b]) dm->lightLevels[b] /= 255.0f; if(dm->lightLevels[b] < 0) dm->lightLevels[b] = 0; else if(dm->lightLevels[b] > 1) dm->lightLevels[b] = 1; } ReadToken(); } else RV_STR("ID", dm->id) RV_FLT("Frame interval", dm->frameInterval) RV_END CHECKSC; } sub++; } else if(ISLABEL("Light")) { ded_decorlight_t *dl = &decor->lights[sub]; if(sub == DED_DECOR_NUM_LIGHTS) { SetError("Too many lights in decoration."); retVal = false; goto ded_end_read; } FINDBEGIN; for(;;) { READLABEL; RV_VEC("Offset", dl->pos, 2) RV_FLT("Distance", dl->elevation) RV_VEC("Color", dl->color, 3) RV_FLT("Radius", dl->radius) RV_FLT("Halo radius", dl->haloRadius) RV_IVEC("Pattern offset", dl->patternOffset, 2) RV_IVEC("Pattern skip", dl->patternSkip, 2) if(ISLABEL("Levels")) { int b; FINDBEGIN; for(b = 0; b < 2; ++b) { READFLT(dl->lightLevels[b]) dl->lightLevels[b] /= 255.0f; if(dl->lightLevels[b] < 0) dl->lightLevels[b] = 0; else if(dl->lightLevels[b] > 1) dl->lightLevels[b] = 1; } ReadToken(); } else RV_INT("Flare texture", dl->flareTexture) RV_STR("Flare map", dl->flare.id) RV_STR("Top map", dl->up.id) RV_STR("Bottom map", dl->down.id) RV_STR("Side map", dl->sides.id) RV_END CHECKSC; } sub++; } else RV_END CHECKSC; } prevDecorDefIdx = idx; } if(ISTOKEN("Group")) { int sub; ded_group_t* grp; idx = DED_AddGroup(ded); grp = &ded->groups[idx]; sub = 0; FINDBEGIN; for(;;) { READLABEL; if(ISLABEL("Texture") || ISLABEL("Flat") || ISLABEL("Sprite") || ISLABEL("System")) { ded_group_member_t* memb; if(sub >= grp->count.num) { // Allocate new stage. sub = DED_AddGroupMember(grp); } memb = &grp->members[sub]; memb->material.mnamespace = ( ISLABEL("Texture")? MN_TEXTURES : ISLABEL("Flat")? MN_FLATS : ISLABEL("Sprite")? MN_SPRITES : MN_SYSTEM); FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", memb->material.name) RV_FLT("Tics", memb->tics) RV_FLT("Random", memb->randomTics) RV_END CHECKSC; } ++sub; } else RV_FLAGS("Flags", grp->flags, "tgf_") RV_END CHECKSC; } } /*if(ISTOKEN("XGClass")) // XG Class { // A new XG Class definition idx = DED_AddXGClass(ded); xgc = ded->xgClasses + idx; sub = 0; FINDBEGIN; for(;;) { READLABEL; RV_STR("ID", xgc->id) RV_STR("Name", xgc->name) if(ISLABEL("Property")) { ded_xgclass_property_t *xgcp = NULL; if(sub >= xgc->properties_count.num) { // Allocate new property sub = DED_AddXGClassProperty(xgc); } xgcp = &xgc->properties[sub]; FINDBEGIN; for(;;) { READLABEL; RV_FLAGS("ID", xgcp->id, "xgcp_") RV_FLAGS("Flags", xgcp->flags, "xgcpf_") RV_STR("Name", xgcp->name) RV_STR("Flag Group", xgcp->flagprefix) RV_END CHECKSC; } sub++; } else RV_END CHECKSC; } }*/ if(ISTOKEN("Line")) // Line Type { ded_linetype_t* l; // A new line type. idx = DED_AddLineType(ded, 0); l = &ded->lineTypes[idx]; if(prevLineTypeDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(l, ded->lineTypes + prevLineTypeDefIdx, sizeof(*l)); } FINDBEGIN; for(;;) { READLABEL; RV_INT("ID", l->id) RV_STR("Comment", l->comment) RV_FLAGS("Flags", l->flags[0], "ltf_") RV_FLAGS("Flags2", l->flags[1], "ltf2_") RV_FLAGS("Flags3", l->flags[2], "ltf3_") RV_FLAGS("Class", l->lineClass, "ltc_") RV_FLAGS("Type", l->actType, "lat_") RV_INT("Count", l->actCount) RV_FLT("Time", l->actTime) RV_INT("Act tag", l->actTag) RV_INT("Ap0", l->aparm[0]) RV_INT("Ap1", l->aparm[1]) RV_INT("Ap2", l->aparm[2]) RV_INT("Ap3", l->aparm[3]) RV_FLAGS("Ap4", l->aparm[4], "lref_") RV_INT("Ap5", l->aparm[5]) RV_FLAGS("Ap6", l->aparm[6], "lref_") RV_INT("Ap7", l->aparm[7]) RV_INT("Ap8", l->aparm[8]) RV_STR("Ap9", l->aparm9) RV_INT("Health above", l->aparm[0]) RV_INT("Health below", l->aparm[1]) RV_INT("Power above", l->aparm[2]) RV_INT("Power below", l->aparm[3]) RV_FLAGS("Line act lref", l->aparm[4], "lref_") RV_INT("Line act lrefd", l->aparm[5]) RV_FLAGS("Line inact lref", l->aparm[6], "lref_") RV_INT("Line inact lrefd", l->aparm[7]) RV_INT("Color", l->aparm[8]) RV_STR("Thing type", l->aparm9) RV_FLT("Ticker start time", l->tickerStart) RV_FLT("Ticker end time", l->tickerEnd) RV_INT("Ticker tics", l->tickerInterval) RV_STR("Act sound", l->actSound) RV_STR("Deact sound", l->deactSound) RV_INT("Event chain", l->evChain) RV_INT("Act chain", l->actChain) RV_INT("Deact chain", l->deactChain) RV_FLAGS("Wall section", l->wallSection, "lws_") if(ISLABEL("Act texture")) { READSTR(l->actMaterial.name) l->actMaterial.mnamespace = MN_TEXTURES; } else if(ISLABEL("Act material")) // Alias { READSTR(l->actMaterial.name) l->actMaterial.mnamespace = MN_ANY; } else if(ISLABEL("Deact texture")) { READSTR(l->deactMaterial.name) l->deactMaterial.mnamespace = MN_TEXTURES; } else if(ISLABEL("Deact material")) // Alias { READSTR(l->deactMaterial.name) l->deactMaterial.mnamespace = MN_ANY; } else RV_INT("Act type", l->actLineType) RV_INT("Deact type", l->deactLineType) RV_STR("Act message", l->actMsg) RV_STR("Deact message", l->deactMsg) RV_FLT("Texmove angle", l->materialMoveAngle) RV_FLT("Materialmove angle", l->materialMoveAngle) // Alias RV_FLT("Texmove speed", l->materialMoveSpeed) RV_FLT("Materialmove speed", l->materialMoveSpeed) // Alias RV_STR_INT("Ip0", l->iparmStr[0], l->iparm[0]) RV_STR_INT("Ip1", l->iparmStr[1], l->iparm[1]) RV_STR_INT("Ip2", l->iparmStr[2], l->iparm[2]) RV_STR_INT("Ip3", l->iparmStr[3], l->iparm[3]) RV_STR_INT("Ip4", l->iparmStr[4], l->iparm[4]) RV_STR_INT("Ip5", l->iparmStr[5], l->iparm[5]) RV_STR_INT("Ip6", l->iparmStr[6], l->iparm[6]) RV_STR_INT("Ip7", l->iparmStr[7], l->iparm[7]) RV_STR_INT("Ip8", l->iparmStr[8], l->iparm[8]) RV_STR_INT("Ip9", l->iparmStr[9], l->iparm[9]) RV_STR_INT("Ip10", l->iparmStr[10], l->iparm[10]) RV_STR_INT("Ip11", l->iparmStr[11], l->iparm[11]) RV_STR_INT("Ip12", l->iparmStr[12], l->iparm[12]) RV_STR_INT("Ip13", l->iparmStr[13], l->iparm[13]) RV_STR_INT("Ip14", l->iparmStr[14], l->iparm[14]) RV_STR_INT("Ip15", l->iparmStr[15], l->iparm[15]) RV_STR_INT("Ip16", l->iparmStr[16], l->iparm[16]) RV_STR_INT("Ip17", l->iparmStr[17], l->iparm[17]) RV_STR_INT("Ip18", l->iparmStr[18], l->iparm[18]) RV_STR_INT("Ip19", l->iparmStr[19], l->iparm[19]) RV_FLT("Fp0", l->fparm[0]) RV_FLT("Fp1", l->fparm[1]) RV_FLT("Fp2", l->fparm[2]) RV_FLT("Fp3", l->fparm[3]) RV_FLT("Fp4", l->fparm[4]) RV_FLT("Fp5", l->fparm[5]) RV_FLT("Fp6", l->fparm[6]) RV_FLT("Fp7", l->fparm[7]) RV_FLT("Fp8", l->fparm[8]) RV_FLT("Fp9", l->fparm[9]) RV_FLT("Fp10", l->fparm[10]) RV_FLT("Fp11", l->fparm[11]) RV_FLT("Fp12", l->fparm[12]) RV_FLT("Fp13", l->fparm[13]) RV_FLT("Fp14", l->fparm[14]) RV_FLT("Fp15", l->fparm[15]) RV_FLT("Fp16", l->fparm[16]) RV_FLT("Fp17", l->fparm[17]) RV_FLT("Fp18", l->fparm[18]) RV_FLT("Fp19", l->fparm[19]) RV_STR("Sp0", l->sparm[0]) RV_STR("Sp1", l->sparm[1]) RV_STR("Sp2", l->sparm[2]) RV_STR("Sp3", l->sparm[3]) RV_STR("Sp4", l->sparm[4]) if(l->lineClass) { // IpX Alt names can only be used if the class is defined first! // they also support the DED v6 flags format RV_XGIPARM(xgClassLinks[l->lineClass].iparm[0].name, l->iparmStr[0], l->iparm[0], 0) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[1].name, l->iparmStr[1], l->iparm[1], 1) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[2].name, l->iparmStr[2], l->iparm[2], 2) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[3].name, l->iparmStr[3], l->iparm[3], 3) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[4].name, l->iparmStr[4], l->iparm[4], 4) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[5].name, l->iparmStr[5], l->iparm[5], 5) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[6].name, l->iparmStr[6], l->iparm[6], 6) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[7].name, l->iparmStr[7], l->iparm[7], 7) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[8].name, l->iparmStr[8], l->iparm[8], 8) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[9].name, l->iparmStr[9], l->iparm[9], 9) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[10].name, l->iparmStr[10], l->iparm[10], 10) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[11].name, l->iparmStr[11], l->iparm[11], 11) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[12].name, l->iparmStr[12], l->iparm[12], 12) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[13].name, l->iparmStr[13], l->iparm[13], 13) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[14].name, l->iparmStr[14], l->iparm[14], 14) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[15].name, l->iparmStr[15], l->iparm[15], 15) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[16].name, l->iparmStr[16], l->iparm[16], 16) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[17].name, l->iparmStr[17], l->iparm[17], 17) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[18].name, l->iparmStr[18], l->iparm[18], 18) RV_XGIPARM(xgClassLinks[l->lineClass].iparm[19].name, l->iparmStr[19], l->iparm[19], 19) RV_END } else RV_END CHECKSC; } prevLineTypeDefIdx = idx; } if(ISTOKEN("Sector")) // Sector Type { ded_sectortype_t* sec; // A new sector type. idx = DED_AddSectorType(ded, 0); sec = &ded->sectorTypes[idx]; if(prevSectorTypeDefIdx >= 0 && bCopyNext) { // Should we copy the previous definition? memcpy(sec, ded->sectorTypes + prevSectorTypeDefIdx, sizeof(*sec)); } FINDBEGIN; for(;;) { READLABEL; RV_INT("ID", sec->id) RV_STR("Comment", sec->comment) RV_FLAGS("Flags", sec->flags, "stf_") RV_INT("Act tag", sec->actTag) RV_INT("Floor chain", sec->chain[0]) RV_INT("Ceiling chain", sec->chain[1]) RV_INT("Inside chain", sec->chain[2]) RV_INT("Ticker chain", sec->chain[3]) RV_FLAGS("Floor chain flags", sec->chainFlags[0], "scef_") RV_FLAGS("Ceiling chain flags", sec->chainFlags[1], "scef_") RV_FLAGS("Inside chain flags", sec->chainFlags[2], "scef_") RV_FLAGS("Ticker chain flags", sec->chainFlags[3], "scef_") RV_FLT("Floor chain start time", sec->start[0]) RV_FLT("Ceiling chain start time", sec->start[1]) RV_FLT("Inside chain start time", sec->start[2]) RV_FLT("Ticker chain start time", sec->start[3]) RV_FLT("Floor chain end time", sec->end[0]) RV_FLT("Ceiling chain end time", sec->end[1]) RV_FLT("Inside chain end time", sec->end[2]) RV_FLT("Ticker chain end time", sec->end[3]) RV_FLT("Floor chain min interval", sec->interval[0][0]) RV_FLT("Ceiling chain min interval", sec->interval[1][0]) RV_FLT("Inside chain min interval", sec->interval[2][0]) RV_FLT("Ticker chain min interval", sec->interval[3][0]) RV_FLT("Floor chain max interval", sec->interval[0][1]) RV_FLT("Ceiling chain max interval", sec->interval[1][1]) RV_FLT("Inside chain max interval", sec->interval[2][1]) RV_FLT("Ticker chain max interval", sec->interval[3][1]) RV_INT("Floor chain count", sec->count[0]) RV_INT("Ceiling chain count", sec->count[1]) RV_INT("Inside chain count", sec->count[2]) RV_INT("Ticker chain count", sec->count[3]) RV_STR("Ambient sound", sec->ambientSound) RV_FLT("Ambient min interval", sec->soundInterval[0]) RV_FLT("Ambient max interval", sec->soundInterval[1]) RV_FLT("Floor texmove angle", sec->materialMoveAngle[0]) RV_FLT("Floor materialmove angle", sec->materialMoveAngle[0]) // Alias RV_FLT("Ceiling texmove angle", sec->materialMoveAngle[1]) RV_FLT("Ceiling materialmove angle", sec->materialMoveAngle[1]) // Alias RV_FLT("Floor texmove speed", sec->materialMoveSpeed[0]) RV_FLT("Floor materialmove speed", sec->materialMoveSpeed[0]) // Alias RV_FLT("Ceiling texmove speed", sec->materialMoveSpeed[1]) RV_FLT("Ceiling materialmove speed", sec->materialMoveSpeed[1]) // Alias RV_FLT("Wind angle", sec->windAngle) RV_FLT("Wind speed", sec->windSpeed) RV_FLT("Vertical wind", sec->verticalWind) RV_FLT("Gravity", sec->gravity) RV_FLT("Friction", sec->friction) RV_STR("Light fn", sec->lightFunc) RV_INT("Light fn min tics", sec->lightInterval[0]) RV_INT("Light fn max tics", sec->lightInterval[1]) RV_STR("Red fn", sec->colFunc[0]) RV_STR("Green fn", sec->colFunc[1]) RV_STR("Blue fn", sec->colFunc[2]) RV_INT("Red fn min tics", sec->colInterval[0][0]) RV_INT("Red fn max tics", sec->colInterval[0][1]) RV_INT("Green fn min tics", sec->colInterval[1][0]) RV_INT("Green fn max tics", sec->colInterval[1][1]) RV_INT("Blue fn min tics", sec->colInterval[2][0]) RV_INT("Blue fn max tics", sec->colInterval[2][1]) RV_STR("Floor fn", sec->floorFunc) RV_FLT("Floor fn scale", sec->floorMul) RV_FLT("Floor fn offset", sec->floorOff) RV_INT("Floor fn min tics", sec->floorInterval[0]) RV_INT("Floor fn max tics", sec->floorInterval[1]) RV_STR("Ceiling fn", sec->ceilFunc) RV_FLT("Ceiling fn scale", sec->ceilMul) RV_FLT("Ceiling fn offset", sec->ceilOff) RV_INT("Ceiling fn min tics", sec->ceilInterval[0]) RV_INT("Ceiling fn max tics", sec->ceilInterval[1]) RV_END CHECKSC; } prevSectorTypeDefIdx = idx; } bCopyNext = false; } ded_end_read: M_Free(rootStr); // Free the source stack entry we were using. DED_CloseReader(); return retVal; } /* *INDENT-ON* */ /** * @return @c true, if the file was successfully loaded. */ int DED_Read(ded_t* ded, const char* sPathName) { DFILE* file; char* defData; size_t len; int result; filename_t translated; M_TranslatePath(translated, sPathName, FILENAME_T_MAXLEN); if((file = F_Open(translated, "rb")) == NULL) { SetError("File can't be opened for reading."); return false; } // Allocate a large enough buffer and read the file. F_Seek(file, 0, SEEK_END); len = F_Tell(file); F_Rewind(file); defData = M_Calloc(len + 1); F_Read(defData, len, file); F_Close(file); // Parse the definitions. result = DED_ReadData(ded, defData, translated); // Now we can free the buffer. M_Free(defData); return result; } /** * Reads definitions from the given lump. */ int DED_ReadLump(ded_t* ded, lumpnum_t lump) { size_t lumpLength; if(lump < 0 || lump >= numLumps) { SetError("Bad lump number."); return false; } if((lumpLength = W_LumpLength(lump)) > 0) { void* buf = M_Calloc(lumpLength + 1); int result = DED_ReadData(ded, buf, W_LumpSourceFile(lump)); M_Free(buf); return result; } return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/b_context.c0000644000175000017500000006115711357170241023073 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_context.c: Bindings Contexts. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_misc.h" #include "b_main.h" #include "b_context.h" #include "p_control.h" #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int bindContextCount; static bcontext_t** bindContexts; // CODE -------------------------------------------------------------------- /** * Destroy all binding contexts and the bindings within the contexts. * Called at shutdown time. */ void B_DestroyAllContexts(void) { int i; if(bindContexts) { // Do not use the global bindContextCount to control the loop; it is // changed as a sideeffect of B_DestroyContext() and also, the // bindContexts array itself is shifted back to idx 0 afterwards. int numBindClasses = bindContextCount; for(i = 0; i < numBindClasses; ++i) { B_DestroyContext(bindContexts[0]); } M_Free(bindContexts); } bindContexts = NULL; bindContextCount = 0; } /** * Marks all device states with the highest-priority binding context to * which they have a connection via device bindings. This ensures that if a * high-priority context is using a particular device state, lower-priority * contexts will not be using the same state for their own controls. * * Called automatically whenever a context is activated or deactivated. */ void B_UpdateDeviceStateAssociations(void) { int i, j; uint k; bcontext_t* bc; evbinding_t* eb; controlbinding_t* conBin; dbinding_t* db; I_ClearDeviceContextAssociations(); // We need to iterate through all the device bindings in all context. for(i = 0; i < bindContextCount; ++i) { bc = bindContexts[i]; // Skip inactive contexts. if(!(bc->flags & BCF_ACTIVE)) continue; // Mark all event bindings in the context. for(eb = bc->commandBinds.next; eb != &bc->commandBinds; eb = eb->next) { inputdev_t* dev = I_GetDevice(eb->device, false); switch(eb->type) { case E_TOGGLE: if(!dev->keys[eb->id].assoc.bContext) dev->keys[eb->id].assoc.bContext = bc; break; case E_AXIS: if(!dev->axes[eb->id].assoc.bContext) dev->axes[eb->id].assoc.bContext = bc; break; case E_ANGLE: if(!dev->hats[eb->id].assoc.bContext) dev->hats[eb->id].assoc.bContext = bc; break; case E_SYMBOLIC: break; default: Con_Error("B_UpdateDeviceStateAssociations: Invalid value, " "eb->type = %i.", (int) eb->type); break; } } // All controls in the context. for(conBin = bc->controlBinds.next; conBin != &bc->controlBinds; conBin = conBin->next) { for(k = 0; k < DDMAXPLAYERS; ++k) { // Associate all the device bindings. for(db = conBin->deviceBinds[k].next; db != &conBin->deviceBinds[k]; db = db->next) { inputdev_t* dev = I_GetDevice(db->device, false); switch(db->type) { case CBD_TOGGLE: if(!dev->keys[db->id].assoc.bContext) dev->keys[db->id].assoc.bContext = bc; break; case CBD_AXIS: if(!dev->axes[db->id].assoc.bContext) dev->axes[db->id].assoc.bContext = bc; break; case CBD_ANGLE: if(!dev->hats[db->id].assoc.bContext) dev->hats[db->id].assoc.bContext = bc; break; default: Con_Error("B_UpdateDeviceStateAssociations: Invalid value, " "db->type = %i.", (int) db->type); break; } } } } // If the context have made a broad device acquisition, mark all // relevant states. if(bc->flags & BCF_ACQUIRE_KEYBOARD) { inputdev_t* dev = I_GetDevice(IDEV_KEYBOARD, false); for(k = 0; k < dev->numKeys; ++k) { if(!dev->keys[k].assoc.bContext) dev->keys[k].assoc.bContext = bc; } } if(bc->flags & BCF_ACQUIRE_ALL) { int j; for(j = 0; j < NUM_INPUT_DEVICES; ++j) { inputdev_t* dev = I_GetDevice(j, true); if(!dev) continue; for(k = 0; k < dev->numKeys; ++k) { if(!dev->keys[k].assoc.bContext) dev->keys[k].assoc.bContext = bc; } for(k = 0; k < dev->numAxes; ++k) { if(!dev->axes[k].assoc.bContext) dev->axes[k].assoc.bContext = bc; } for(k = 0; k < dev->numHats; ++k) { if(!dev->hats[k].assoc.bContext) dev->hats[k].assoc.bContext = bc; } } } } // Now that we know what are the updated context associations, let's check // the devices and see if any of the states need to be expired. for(i = 0; i < NUM_INPUT_DEVICES; ++i) { inputdev_t* dev = I_GetDevice(i, false); // Keys. for(j = 0; j < dev->numKeys; ++j) { if(dev->keys[j].assoc.bContext != dev->keys[j].assoc.prevBContext && dev->keys[j].isDown) { // No longer valid. dev->keys[j].assoc.flags |= IDAF_EXPIRED; } } // Axes. for(j = 0; j < dev->numAxes; ++j) { if(dev->axes[j].assoc.bContext != dev->axes[j].assoc.prevBContext && dev->axes[j].position != 0) { // No longer valid. dev->axes[j].assoc.flags |= IDAF_EXPIRED; } } // Hats. for(j = 0; j < dev->numHats; ++j) { if(dev->hats[j].assoc.bContext != dev->hats[j].assoc.prevBContext && dev->hats[j].pos >= 0) { // No longer valid. dev->hats[j].assoc.flags |= IDAF_EXPIRED; } } } } static void B_SetContextCount(int count) { bindContexts = M_Realloc(bindContexts, sizeof(bcontext_t*) * count); bindContextCount = count; } static void B_InsertContext(bcontext_t* bc, int contextIdx) { B_SetContextCount(bindContextCount + 1); if(contextIdx < bindContextCount - 1) { // We need to make room for this new binding context. memmove(&bindContexts[contextIdx + 1], &bindContexts[contextIdx], sizeof(bcontext_t*) * (bindContextCount - 1 - contextIdx)); } bindContexts[contextIdx] = bc; } static void B_RemoveContext(bcontext_t* bc) { int contextIdx = B_GetContextPos(bc); if(contextIdx >= 0) { memmove(&bindContexts[contextIdx], &bindContexts[contextIdx + 1], sizeof(bcontext_t*) * (bindContextCount - 1 - contextIdx)); B_SetContextCount(bindContextCount - 1); } } /** * Creates a new binding context. The new context has the highest priority * of all existing contexts, and is inactive. */ bcontext_t* B_NewContext(const char* name) { bcontext_t* bc = M_Calloc(sizeof(bcontext_t)); bc->name = strdup(name); B_InitCommandBindingList(&bc->commandBinds); B_InitControlBindingList(&bc->controlBinds); B_InsertContext(bc, 0); return bc; } void B_DestroyContext(bcontext_t* bc) { if(!bc) return; B_RemoveContext(bc); M_Free(bc->name); B_ClearContext(bc); M_Free(bc); } void B_ClearContext(bcontext_t* bc) { B_DestroyCommandBindingList(&bc->commandBinds); B_DestroyControlBindingList(&bc->controlBinds); } void B_ActivateContext(bcontext_t* bc, boolean doActivate) { if(!bc) return; VERBOSE( Con_Message("B_ActivateContext: %s context \"%s\".\n", doActivate? "Activating" : "Deactivating", bc->name) ); bc->flags &= ~BCF_ACTIVE; if(doActivate) bc->flags |= BCF_ACTIVE; B_UpdateDeviceStateAssociations(); if(bc->flags & BCF_ACQUIRE_ALL) { int i; for(i = 0; i < NUM_INPUT_DEVICES; ++i) { I_DeviceReset(i); } } } void B_AcquireKeyboard(bcontext_t* bc, boolean doAcquire) { bc->flags &= ~BCF_ACQUIRE_KEYBOARD; if(doAcquire) bc->flags |= BCF_ACQUIRE_KEYBOARD; B_UpdateDeviceStateAssociations(); } void B_AcquireAll(bcontext_t* bc, boolean doAcquire) { bc->flags &= ~BCF_ACQUIRE_ALL; if(doAcquire) bc->flags |= BCF_ACQUIRE_ALL; B_UpdateDeviceStateAssociations(); } void B_SetContextFallback(const char* name, int (*responderFunc)(event_t*)) { bcontext_t *ctx = B_ContextByName(name); if(!ctx) return; ctx->fallbackResponder = responderFunc; } bcontext_t* B_ContextByName(const char* name) { int i; for(i = 0; i < bindContextCount; ++i) { if(!strcasecmp(name, bindContexts[i]->name)) return bindContexts[i]; } return NULL; } bcontext_t* B_ContextByPos(int pos) { if(pos < 0 || pos >= bindContextCount) return NULL; return bindContexts[pos]; } int B_ContextCount(void) { return bindContextCount; } int B_GetContextPos(bcontext_t* bc) { int i; for(i = 0; i < bindContextCount; ++i) { if(bindContexts[i] == bc) return i; } return -1; } void B_ReorderContext(bcontext_t* bc, int pos) { B_RemoveContext(bc); B_InsertContext(bc, pos); } controlbinding_t* B_NewControlBinding(bcontext_t* bc) { int i; controlbinding_t* conBin = M_Calloc(sizeof(controlbinding_t)); conBin->bid = B_NewIdentifier(); for(i = 0; i < DDMAXPLAYERS; ++i) { B_InitDeviceBindingList(&conBin->deviceBinds[i]); } // Link it in. conBin->next = &bc->controlBinds; conBin->prev = bc->controlBinds.prev; bc->controlBinds.prev->next = conBin; bc->controlBinds.prev = conBin; return conBin; } controlbinding_t* B_FindControlBinding(bcontext_t* bc, int control) { controlbinding_t* i; for(i = bc->controlBinds.next; i != &bc->controlBinds; i = i->next) { if(i->control == control) return i; } return NULL; } controlbinding_t* B_GetControlBinding(bcontext_t* bc, int control) { controlbinding_t* b = B_FindControlBinding(bc, control); if(!b) { // Create a new one. b = B_NewControlBinding(bc); b->control = control; } return b; } void B_DestroyControlBinding(controlbinding_t* conBin) { int i; if(!conBin) return; assert(conBin->bid != 0); // Unlink first, if linked. if(conBin->prev) { conBin->prev->next = conBin->next; conBin->next->prev = conBin->prev; } for(i = 0; i < DDMAXPLAYERS; ++i) { B_DestroyDeviceBindingList(&conBin->deviceBinds[i]); } M_Free(conBin); } void B_InitControlBindingList(controlbinding_t* listRoot) { memset(listRoot, 0, sizeof(*listRoot)); listRoot->next = listRoot->prev = listRoot; } void B_DestroyControlBindingList(controlbinding_t* listRoot) { while(listRoot->next != listRoot) { B_DestroyControlBinding(listRoot->next); } } /** * @return @c true, if the binding was found and deleted. */ boolean B_DeleteBinding(bcontext_t* bc, int bid) { int i; evbinding_t* eb = 0; controlbinding_t* conBin = 0; dbinding_t* db = 0; // Check if it is one of the command bindings. for(eb = bc->commandBinds.next; eb != &bc->commandBinds; eb = eb->next) { if(eb->bid == bid) { B_DestroyCommandBinding(eb); return true; } } // How about one of the control bindings? for(conBin = bc->controlBinds.next; conBin != &bc->controlBinds; conBin = conBin->next) { if(conBin->bid == bid) { B_DestroyControlBinding(conBin); return true; } // It may also be a device binding. for(i = 0; i < DDMAXPLAYERS; ++i) { for(db = conBin->deviceBinds[i].next; db != &conBin->deviceBinds[i]; db = db->next) { if(db->bid == bid) { B_DestroyDeviceBinding(db); return true; } } } } return false; } boolean B_TryEvent(ddevent_t* event) { int i; evbinding_t* eb; event_t ev; DD_ConvertEvent(event, &ev); for(i = 0; i < bindContextCount; ++i) { bcontext_t* bc = bindContexts[i]; if(!(bc->flags & BCF_ACTIVE)) continue; // See if the command bindings will have it. for(eb = bc->commandBinds.next; eb != &bc->commandBinds; eb = eb->next) { if(B_TryCommandBinding(eb, event, bc)) return true; } // Try the fallback. if(bc->fallbackResponder && bc->fallbackResponder(&ev)) return true; } // Nobody used it. return false; } /** * Looks through the bindings to find the ones that are bound to the * specified command. The result is a space-separated list of bindings * such as (idnum is the binding ID number): * * idnum@@game:key-space-down idnum@@game:key-e-down * * @param cmd Command to look for. * @param buf Output buffer for the result. * @param bufSize Size of output buffer. * * @return Number of bindings found for the command. */ int B_BindingsForCommand(const char* cmd, char* buf, size_t bufSize) { ddstring_t result; ddstring_t str; bcontext_t* bc; int i; int numFound = 0; Str_Init(&result); Str_Init(&str); for(i = 0; i < bindContextCount; ++i) { evbinding_t* e; bc = bindContexts[i]; for(e = bc->commandBinds.next; e != &bc->commandBinds; e = e->next) { if(strcmp(e->command, cmd)) continue; // It's here! if(numFound) { Str_Append(&result, " "); } numFound++; B_EventBindingToString(e, &str); Str_Appendf(&result, "%i@%s:%s", e->bid, bc->name, Str_Text(&str)); } } // Copy the result to the return buffer. memset(buf, 0, bufSize); strncpy(buf, Str_Text(&result), bufSize - 1); Str_Free(&result); Str_Free(&str); return numFound; } /** * Looks through the bindings to find the ones that are bound to the * specified control. The result is a space-separated list of bindings. * * @param localPlayer Number of the local player (first one always 0). * @param controlName Name of the player control. * @param inverse One of BFCI_*. * @param buf Output buffer for the result. * @param bufSize Size of output buffer. * * @return Number of bindings found for the command. */ int B_BindingsForControl(int localPlayer, const char* controlName, int inverse, char* buf, size_t bufSize) { ddstring_t result; ddstring_t str; bcontext_t* bc; int i; int numFound = 0; if(localPlayer < 0 || localPlayer >= DDMAXPLAYERS) return 0; Str_Init(&result); Str_Init(&str); for(i = 0; i < bindContextCount; ++i) { controlbinding_t* c; dbinding_t* d; bc = bindContexts[i]; for(c = bc->controlBinds.next; c != &bc->controlBinds; c = c->next) { const char* name = P_PlayerControlById(c->control)->name; if(strcmp(name, controlName)) continue; // Wrong control. for(d = c->deviceBinds[localPlayer].next; d != &c->deviceBinds[localPlayer]; d = d->next) { if(inverse == BFCI_BOTH || (inverse == BFCI_ONLY_NON_INVERSE && !(d->flags & CBDF_INVERSE)) || (inverse == BFCI_ONLY_INVERSE && (d->flags & CBDF_INVERSE))) { // It's here! if(numFound) { Str_Append(&result, " "); } numFound++; B_DeviceBindingToString(d, &str); Str_Appendf(&result, "%i@%s:%s", d->bid, bc->name, Str_Text(&str)); } } } } // Copy the result to the return buffer. memset(buf, 0, bufSize); strncpy(buf, Str_Text(&result), bufSize - 1); Str_Free(&result); Str_Free(&str); return numFound; } boolean B_FindMatchingBinding(bcontext_t* bc, evbinding_t* match1, dbinding_t* match2, evbinding_t** evResult, dbinding_t** dResult) { evbinding_t* e; controlbinding_t* c; dbinding_t* d; int i; *evResult = NULL; *dResult = NULL; for(e = bc->commandBinds.next; e != &bc->commandBinds; e = e->next) { // TODO: A bit lazy here, should also match all the conditions. // Now we just consider all bindings with conditions unique... if(e->numConds) continue; if(match1 && match1->bid != e->bid) { if(match1->device == e->device && match1->id == e->id && match1->type == e->type && match1->state == e->state) { *evResult = e; return true; } } if(match2) { if(match2->device == e->device && match2->id == e->id && match2->type == e->type) { *evResult = e; return true; } } } for(c = bc->controlBinds.next; c != &bc->controlBinds; c = c->next) { for(i = 0; i < DDMAXPLAYERS; ++i) { for(d = c->deviceBinds[i].next; d != &c->deviceBinds[i]; d = d->next) { // Should also match all the conditions, now we just // consider all bindings with conditions unique... if(d->numConds) continue; if(match1) { if(match1->device == d->device && match1->id == d->id && match1->type == d->type) { *dResult = d; return true; } } if(match2 && match2->bid != d->bid) { if(match2->device == d->device && match2->id == d->id && match2->type == d->type) { *dResult = d; return true; } } } } } // Nothing found. return false; } void B_PrintContexts(void) { int i; bcontext_t* bc; Con_Printf("%i binding contexts defined:\n", bindContextCount); for(i = 0; i < bindContextCount; ++i) { bc = bindContexts[i]; Con_Printf("[%3i] \"%s\" (%s)\n", i, bc->name, (bc->flags & BCF_ACTIVE)? "active" : "inactive"); } } void B_PrintAllBindings(void) { int i, k, count; bcontext_t* bc; evbinding_t* e; controlbinding_t* c; dbinding_t* d; ddstring_t* str = Str_New(); Con_Printf("%i binding contexts defined.\n", bindContextCount); #define BIDFORMAT "[%3i]" for(i = 0; i < bindContextCount; ++i) { bc = bindContexts[i]; Con_Printf("Context \"%s\" (%s):\n", bc->name, (bc->flags & BCF_ACTIVE)? "active" : "inactive"); // Commands. for(count = 0, e = bc->commandBinds.next; e != &bc->commandBinds; e = e->next, count++); if(count) Con_Printf(" %i event bindings:\n", count); for(e = bc->commandBinds.next; e != &bc->commandBinds; e = e->next) { B_EventBindingToString(e, str); Con_Printf(" "BIDFORMAT" %s : %s\n", e->bid, Str_Text(str), e->command); } // Controls. for(count = 0, c = bc->controlBinds.next; c != &bc->controlBinds; c = c->next, count++); if(count) Con_Printf(" %i control bindings.\n", count); for(c = bc->controlBinds.next; c != &bc->controlBinds; c = c->next) { const char* controlName = P_PlayerControlById(c->control)->name; Con_Printf(" Control \"%s\" "BIDFORMAT":\n", controlName, c->bid); for(k = 0; k < DDMAXPLAYERS; ++k) { for(count = 0, d = c->deviceBinds[k].next; d != &c->deviceBinds[k]; d = d->next, count++); if(!count) continue; Con_Printf(" Local player %i has %i device bindings for \"%s\":\n", k + 1, count, controlName); for(d = c->deviceBinds[k].next; d != &c->deviceBinds[k]; d = d->next) { B_DeviceBindingToString(d, str); Con_Printf(" "BIDFORMAT" %s\n", d->bid, Str_Text(str)); } } } } Str_Delete(str); } void B_WriteContextToFile(const bcontext_t* bc, FILE* file) { evbinding_t* e; controlbinding_t* c; dbinding_t* d; int k; ddstring_t* str = Str_New(); // Commands. for(e = bc->commandBinds.next; e != &bc->commandBinds; e = e->next) { B_EventBindingToString(e, str); fprintf(file, "bindevent \"%s:%s\" \"", bc->name, Str_Text(str)); M_WriteTextEsc(file, e->command); fprintf(file, "\"\n"); } // Controls. for(c = bc->controlBinds.next; c != &bc->controlBinds; c = c->next) { const char* controlName = P_PlayerControlById(c->control)->name; for(k = 0; k < DDMAXPLAYERS; ++k) { for(d = c->deviceBinds[k].next; d != &c->deviceBinds[k]; d = d->next) { B_DeviceBindingToString(d, str); fprintf(file, "bindcontrol local%i-%s \"%s\"\n", k + 1, controlName, Str_Text(str)); } } } Str_Delete(str); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_ticker.c0000644000175000017500000001006611357170242022700 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_ticker.c: Timed Playsim Events */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_network.h" #include "de_refresh.h" #include "de_render.h" #include "de_play.h" #include "de_misc.h" #include "r_sky.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- boolean P_MobjTicker(thinker_t* th, void* context) { uint i; mobj_t* mo = (mobj_t*) th; for(i = 0; i < DDMAXPLAYERS; ++i) { int f; byte* haloFactor = &mo->haloFactors[i]; // Set the high bit of halofactor if the light is clipped. This will // make P_Ticker diminish the factor to zero. Take the first step here // and now, though. if(mo->lumIdx == 0 || LO_IsClipped(mo->lumIdx, i)) { if(*haloFactor & 0x80) { f = (*haloFactor & 0x7f); // - haloOccludeSpeed; if(f < 0) f = 0; *haloFactor = f; } } else { if(!(*haloFactor & 0x80)) { f = (*haloFactor & 0x7f); // + haloOccludeSpeed; if(f > 127) f = 127; *haloFactor = 0x80 | f; } } // Handle halofactor. f = *haloFactor & 0x7f; if(*haloFactor & 0x80) { // Going up. f += haloOccludeSpeed; if(f > 127) f = 127; } else { // Going down. f -= haloOccludeSpeed; if(f < 0) f = 0; } *haloFactor &= ~0x7f; *haloFactor |= f; } return true; // Continue iteration. } boolean PIT_ClientMobjTicker(clmobj_t *cmo, void *parm) { P_MobjTicker((thinker_t*) &cmo->mo, NULL); // Continue iteration. return true; } /** * Doomsday's own play-ticker. */ void P_Ticker(timespan_t time) { static trigger_t fixed = { 1.0 / 35, 0 }; P_ControlTicker(time); P_MaterialManagerTicker(time); if(!P_ThinkerListInited()) return; // Not initialized yet. if(!M_RunTrigger(&fixed, time)) return; // New ptcgens for planes? P_CheckPtcPlanes(); R_SkyTicker(); // Check all mobjs (always public). P_IterateThinkers(gx.MobjThinker, 0x1, P_MobjTicker, NULL); // Check all client mobjs. Cl_MobjIterator(PIT_ClientMobjTicker, NULL); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_system.c0000644000175000017500000002031111357170242023314 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_system.c: */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # include # include #endif #include #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_audio.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- //int systics = 0; // System tics (every game tic). int novideo; // if true, stay in text mode for debugging // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- #ifdef WIN32 /** * Borrowed from Lee Killough. */ static void C_DECL handler(int s) { signal(s, SIG_IGN); // Ignore future instances of this signal. Con_Error(s==SIGSEGV ? "Segmentation Violation\n" : s==SIGINT ? "Interrupted by User\n" : s==SIGILL ? "Illegal Instruction\n" : s==SIGFPE ? "Floating Point Exception\n" : s==SIGTERM ? "Killed\n" : "Terminated by signal\n"); } #endif /** * Initialize machine state. */ void Sys_Init(void) { if(!isDedicated) { Con_Message("Sys_Init: Initializing keyboard, mouse and joystick.\n"); if(!I_Init()) Con_Error("Sys_Init: Failed to initialize input.\n"); } // Virtual devices need to be created even in dedicated mode. I_InitVirtualInputDevices(); Sys_InitTimer(); S_Init(); Huff_Init(); N_Init(); #if defined(WIN32) && !defined(_DEBUG) // Register handler for abnormal situations (in release build). signal(SIGSEGV, handler); signal(SIGTERM, handler); signal(SIGILL, handler); signal(SIGFPE, handler); signal(SIGILL, handler); signal(SIGABRT, handler); #endif #ifndef WIN32 // We are not worried about broken pipes. When a TCP connection closes, // we prefer to receive an error code instead of a signal. signal(SIGPIPE, SIG_IGN); #endif } /** * Return to default system state. */ void Sys_Shutdown(void) { Sys_ShutdownTimer(); if(gx.Shutdown) gx.Shutdown(); Net_Shutdown(); Huff_Shutdown(); // Let's shut down sound first, so Windows' HD-hogging doesn't jam // the MUS player (would produce horrible bursts of notes). S_Shutdown(); GL_Shutdown(); DD_ClearEvents(); I_ShutdownInputDevices(); I_Shutdown(); } int Sys_CriticalMessage(char *msg) { #ifdef WIN32 char buf[256]; int ret; HWND hWnd = Sys_GetWindowHandle(windowIDX); if(!hWnd) { suspendMsgPump = true; MessageBox(HWND_DESKTOP, ("Sys_CriticalMessage: Main window not available."), NULL, MB_ICONERROR | MB_OK); suspendMsgPump = false; return false; } ShowCursor(TRUE); ShowCursor(TRUE); suspendMsgPump = true; GetWindowText(hWnd, buf, 255); ret = (MessageBox(hWnd, (msg), (buf), MB_OK | MB_ICONEXCLAMATION) == IDYES); suspendMsgPump = false; ShowCursor(FALSE); ShowCursor(FALSE); return ret; #else fprintf(stderr, "--- %s\n", msg); return 0; #endif } void Sys_Sleep(int millisecs) { #ifdef WIN32 Sleep(millisecs); #endif #ifdef UNIX // Not guaranteed to be very accurate... SDL_Delay(millisecs); #endif } void Sys_ShowCursor(boolean show) { #ifdef WIN32 ShowCursor(show); #endif #ifdef UNIX SDL_ShowCursor(show ? SDL_ENABLE : SDL_DISABLE); #endif } void Sys_HideMouse(void) { #ifdef WIN32 if(novideo) return; ShowCursor(FALSE); #endif #ifdef UNIX Sys_ShowCursor(false); #endif } /** * Called when Doomsday should quit (will be deferred until convienent). */ void Sys_Quit(void) { appShutdown = true; } void Sys_MessageBox(const char *msg, boolean iserror) { #ifdef WIN32 char title[300]; HWND hWnd = Sys_GetWindowHandle(windowIDX); if(!hWnd) { suspendMsgPump = true; MessageBox(HWND_DESKTOP, "Sys_MessageBox: Main window not available.", NULL, MB_ICONERROR | MB_OK); suspendMsgPump = false; return; } suspendMsgPump = true; GetWindowText(hWnd, title, 300); MessageBox(hWnd, msg, title, MB_OK | (iserror ? MB_ICONERROR : MB_ICONINFORMATION)); suspendMsgPump = false; #endif #ifdef UNIX fprintf(stderr, "%s %s\n", iserror ? "**ERROR**" : "---", msg); #endif } /** * Opens the given file in a suitable text editor. */ void Sys_OpenTextEditor(const char *filename) { #ifdef WIN32 // Everybody is bound to have Notepad. spawnlp(P_NOWAIT, "notepad.exe", "notepad.exe", filename, 0); #endif } /** * Utilises SDL Threads on ALL systems. * Returns the SDL_thread structure as handle to the started thread. */ thread_t Sys_StartThread(systhreadfunc_t startpos, void *parm) { SDL_Thread* thread = SDL_CreateThread(startpos, parm); if(thread == NULL) { Con_Message("Sys_StartThread: Failed to start new thread (%s).\n", SDL_GetError()); return 0; } return thread; } /** * Suspends or resumes the execution of a thread. */ void Sys_SuspendThread(thread_t handle, boolean dopause) { Con_Error("Sys_SuspendThread: Not implemented.\n"); } /** * @return The return value of the thread. */ int Sys_WaitThread(thread_t thread) { int result = 0; SDL_WaitThread(thread, &result); return result; } /** * @return The identifier of the current thread. */ uint Sys_ThreadID(void) { return SDL_ThreadID(); } mutex_t Sys_CreateMutex(const char *name) { return (mutex_t) SDL_CreateMutex(); } void Sys_DestroyMutex(mutex_t handle) { if(!handle) return; SDL_DestroyMutex((SDL_mutex *) handle); } void Sys_Lock(mutex_t handle) { if(!handle) return; SDL_mutexP((SDL_mutex *) handle); } void Sys_Unlock(mutex_t handle) { if(!handle) return; SDL_mutexV((SDL_mutex *) handle); } /** * Create a new semaphore. * * @return New handle. */ sem_t Sem_Create(uint32_t initialValue) { return (sem_t) SDL_CreateSemaphore(initialValue); } void Sem_Destroy(sem_t semaphore) { if(semaphore) { SDL_DestroySemaphore((SDL_sem *) semaphore); } } /** * "Proberen" a semaphore. Blocks until the successful. */ void Sem_P(sem_t semaphore) { if(semaphore) { SDL_SemWait((SDL_sem *) semaphore); } } /** * "Verhogen" a semaphore. Returns immediately. */ void Sem_V(sem_t semaphore) { if(semaphore) { SDL_SemPost((SDL_sem *) semaphore); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_sound.c0000644000175000017500000002200411357170241022700 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_sound.c: Clientside Sounds */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_play.h" #include "de_audio.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Read a sound delta from the message buffer and play it. * Only used with PSV_FRAME2 packets. */ void Cl_ReadSoundDelta2(deltatype_t type, boolean skip) { int sound = 0, soundFlags = 0; byte flags = 0; clmobj_t *cmo = NULL; thid_t mobjId = 0; sector_t *sector = NULL; polyobj_t *poly = NULL; mobj_t *emitter = NULL; float volume = 1; if(type == DT_SOUND) { // Delta ID is the sound ID. sound = Msg_ReadShort(); } else if(type == DT_MOBJ_SOUND) { if((cmo = Cl_FindMobj(mobjId = Msg_ReadShort())) != NULL) { if(cmo->flags & CLMF_HIDDEN) { // We can't play sounds from hidden mobjs, because we // aren't sure exactly where they are located. cmo = NULL; } else { emitter = &cmo->mo; } } } else if(type == DT_SECTOR_SOUND) { uint index = (ushort) Msg_ReadShort(); if(index < numSectors) { sector = SECTOR_PTR(index); } else { Con_Message("Cl_ReadSoundDelta2: DT_SECTOR_SOUND contains " "invalid sector num %u. Skipping.\n", index); skip = true; } } else /* DT_POLY_SOUND */ { uint index = (ushort) Msg_ReadShort(); if(index < numPolyObjs) { poly = polyObjs[index]; emitter = (mobj_t *) poly; } else { Con_Message("Cl_ReadSoundDelta2: DT_POLY_SOUND contains " "invalid polyobj num %u. Skipping.\n", index); skip = true; } } flags = Msg_ReadByte(); if(type != DT_SOUND) { // The sound ID. sound = Msg_ReadShort(); } if(type == DT_SECTOR_SOUND) { // Should we use a specific origin? if(flags & SNDDF_FLOOR) emitter = (mobj_t *) §or->planes[PLN_FLOOR]->soundOrg; else if(flags & SNDDF_CEILING) emitter = (mobj_t *) §or->planes[PLN_CEILING]->soundOrg; else emitter = (mobj_t *) §or->soundOrg; } if(flags & SNDDF_VOLUME) { byte b = Msg_ReadByte(); if(b == 255) { // Full volume, no attenuation. soundFlags |= DDSF_NO_ATTENUATION; } else { volume = b / 127.0f; } } if(flags & SNDDF_REPEAT) { soundFlags |= DDSF_REPEAT; } // The delta has been read. Are we skipping? if(skip) return; // Now the entire delta has been read. // Should we start or stop a sound? if(volume > 0 && sound > 0) { // Do we need to queue this sound? if(type == DT_MOBJ_SOUND && !cmo) { // Create a new Hidden clmobj. cmo = Cl_CreateMobj(mobjId); cmo->flags |= CLMF_HIDDEN | CLMF_SOUND; cmo->sound = sound; cmo->volume = volume; /*#ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Queueing: id=%i snd=%i vol=%.2f\n", type, mobjId, sound, volume); #endif */ // The sound will be started when the clmobj is unhidden. return; } // We will start a sound. if(type != DT_SOUND && !emitter) { // Not enough information. #ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Insufficient data, snd=%i\n", type, sound); #endif return; } // Sounds originating from the viewmobj should really originate // from the real player mobj. if(cmo && cmo == clPlayerStates[consolePlayer].cmo) { /*#ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): ViewMobj sound...\n", type); #endif */ emitter = ddPlayers[consolePlayer].shared.mo; } // First stop any sounds originating from the same emitter. // We allow only one sound per emitter. if(type != DT_SOUND && emitter) { S_StopSound(0, emitter); } S_LocalSoundAtVolume(sound | soundFlags, emitter, volume); /*# ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Start snd=%i [%x] vol=%.2f", type, sound, flags, volume); if(cmo) Con_Printf(", mo=%i\n", cmo->mo.thinker.id); else if(sector) Con_Printf(", sector=%i\n", GET_SECTOR_IDX(sector)); else if(poly) Con_Printf(", poly=%i\n", GET_POLYOBJ_IDX(poly)); else Con_Printf("\n"); #endif */ } else if(sound >= 0) { // We must stop a sound. We'll only stop sounds from // specific sources. if(emitter) { S_StopSound(sound, emitter); /* #ifdef _DEBUG Con_Printf("Cl_ReadSoundDelta2(%i): Stop sound %i", type, sound); if(cmo) Con_Printf(", mo=%i\n", cmo->mo.thinker.id); else if(sector) Con_Printf(", sector=%i\n", GET_SECTOR_IDX(sector)); else if(poly) Con_Printf(", poly=%i\n", GET_POLYOBJ_IDX(poly)); else Con_Printf("\n"); #endif */ } } } /** * Called when a PSV_FRAME sound packet is received. */ void Cl_Sound(void) { int sound, volume = 127; float pos[3]; byte flags; uint num; mobj_t *mo = NULL; flags = Msg_ReadByte(); // Sound ID. if(flags & SNDF_SHORT_SOUND_ID) { sound = Msg_ReadShort(); } else { sound = Msg_ReadByte(); } // Is the ID valid? if(sound < 1 || sound >= defs.count.sounds.num) { Con_Message("Cl_Sound: Out of bounds ID %i.\n", sound); return; // Bad sound ID! } #ifdef _DEBUG Con_Printf("Cl_Sound: %i\n", sound); #endif if(flags & SNDF_VOLUME) { volume = Msg_ReadByte(); if(volume > 127) { volume = 127; sound |= DDSF_NO_ATTENUATION; } } if(flags & SNDF_ID) { thid_t sourceId = Msg_ReadShort(); clmobj_t *cmo = Cl_FindMobj(sourceId); if(cmo) { S_LocalSoundAtVolume(sound, &cmo->mo, volume / 127.0f); } } else if(flags & SNDF_SECTOR) { num = (ushort) Msg_ReadPackedShort(); if(num >= numSectors) { Con_Message("Cl_Sound: Invalid sector number %i.\n", num); return; } mo = (mobj_t *) &SECTOR_PTR(num)->soundOrg; //S_StopSound(0, mo); S_LocalSoundAtVolume(sound, mo, volume / 127.0f); } else if(flags & SNDF_ORIGIN) { pos[VX] = Msg_ReadShort(); pos[VY] = Msg_ReadShort(); pos[VZ] = Msg_ReadShort(); S_LocalSoundAtVolumeFrom(sound, NULL, pos, volume / 127.0f); } else if(flags & SNDF_PLAYER) { S_LocalSoundAtVolume(sound, ddPlayers[(flags & 0xf0) >> 4].shared.mo, volume / 127.0f); } else { // Play it from "somewhere". #ifdef _DEBUG Con_Printf("Cl_Sound: NULL orig sound %i\n", sound); #endif S_LocalSoundAtVolume(sound, NULL, volume / 127.0f); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_misc.c0000644000175000017500000011207211357170242022347 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_misc.c: Miscellanous Routines */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if defined(WIN32) # include # include # include #endif #if defined(UNIX) # include # include #endif #include #include #include #include "de_platform.h" #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_misc.h" #include "de_play.h" #include "lzss.h" // MACROS ------------------------------------------------------------------ #define MALLOC_CLIB 1 #define MALLOC_ZONE 2 // TYPES ------------------------------------------------------------------- typedef struct file_identifier_s { byte hash[16]; } file_identifier_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static size_t FileReader(char const *name, byte **buffer, int mallocType); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static uint numReadFiles = 0; static uint maxReadFiles = 0; static file_identifier_t *readFiles = NULL; // CODE -------------------------------------------------------------------- void *M_Malloc(size_t size) { return malloc(size); } void *M_Calloc(size_t size) { return calloc(size, 1); } void *M_Realloc(void *ptr, size_t size) { return realloc(ptr, size); } void M_Free(void *ptr) { free(ptr); } /** * Resets the array of known file IDs. The next time M_CheckFileID() is * called on a file, it passes. */ void M_ResetFileIDs(void) { numReadFiles = 0; } /** * Maintains a list of identifiers already seen. * * @return @c true, if the given file can be read, or * @c false, if it has already been read. */ boolean M_CheckFileID(const char *path) { byte id[16]; uint i; boolean alreadySeen; if(!F_Access(path)) { if(verbose) Con_Message("CheckFile: %s not found.\n", path); return false; } // Calculate the identifier. Dir_FileID(path, id); alreadySeen = false; i = 0; while(i < numReadFiles && !alreadySeen) { if(!memcmp(readFiles[i].hash, id, 16)) { // This identifier has already been encountered. alreadySeen = true; } i++; } if(alreadySeen) return false; // Allocate a new entry. numReadFiles++; if(numReadFiles > maxReadFiles) { if(!maxReadFiles) maxReadFiles = 16; else maxReadFiles *= 2; readFiles = M_Realloc(readFiles, sizeof(readFiles[0]) * maxReadFiles); } memcpy(readFiles[numReadFiles - 1].hash, id, 16); return true; } char* M_SkipWhite(char* str) { while(*str && ISSPACE(*str)) str++; return str; } char* M_FindWhite(char* str) { while(*str && !ISSPACE(*str)) str++; return str; } char* M_SkipLine(char* str) { while(*str && *str != '\n') str++; // If the newline was found, skip it, too. if(*str == '\n') str++; return str; } char* M_LimitedStrCat(char* buf, const char* str, size_t maxWidth, char separator, size_t bufLength) { boolean isEmpty = !buf[0]; size_t length; // How long is this name? length = MIN_OF(maxWidth, strlen(str)); // A separator is included if this is not the first name. if(separator && !isEmpty) ++length; // Does it fit? if(strlen(buf) + length < bufLength) { if(separator && !isEmpty) { char sepBuf[2]; sepBuf[0] = separator; sepBuf[1] = 0; strcat(buf, sepBuf); } strncat(buf, str, length); } return buf; } void M_ExtractFileBase(char* dest, const char* path, size_t len) { M_ExtractFileBase2(dest, path, len, 0); } /** * This has been modified to work with filenames of all sizes. */ void M_ExtractFileBase2(char* dest, const char* path, size_t max, int ignore) { const char* src; src = path + strlen(path) - 1; // Back up until a \ or the start. while(src != path && *(src - 1) != '\\' && *(src - 1) != '/') { src--; } // Copy up to eight characters. while(*src && *src != '.' && max-- > 0) { if(ignore-- > 0) { src++; // Skip chars. max++; // Doesn't count. } else *dest++ = toupper((int) *src++); } if(max > 0) // Room for a null? { // End with a terminating null. *dest++ = 0; } } void M_ReadLine(char* buffer, size_t len, DFILE *file) { size_t p; char ch; boolean isDone; memset(buffer, 0, len); p = 0; isDone = false; while(p < len - 1 && !isDone) // Make the last null stay there. { ch = F_GetC(file); if(ch != '\r') { if(deof(file) || ch == '\n') isDone = true; else buffer[p++] = ch; } } } boolean M_IsComment(const char* buffer) { int i = 0; while(isspace((unsigned char) buffer[i]) && buffer[i]) i++; if(buffer[i] == '#') return true; return false; } /** * Can the given string be interpreted as a valid integer? */ boolean M_IsStringValidInt(const char *str) { size_t i, len; const char *c; boolean isBad; if(!str) return false; len = strlen(str); if(len == 0) return false; for(i = 0, c = str, isBad = false; i < len && !isBad; ++i, c++) { if(i != 0 && *c == '-') isBad = true; // sign is in the wrong place. else if(*c < '0' || *c > '9') isBad = true; // non-numeric character. } return !isBad; } /** * Can the given string be interpreted as a valid byte? */ boolean M_IsStringValidByte(const char *str) { if(M_IsStringValidInt(str)) { int val = atoi(str); if(!(val < 0 || val > 255)) return true; } return false; } /** * Can the given string be interpreted as a valid float? */ boolean M_IsStringValidFloat(const char *str) { size_t i, len; const char *c; boolean isBad, foundDP = false; if(!str) return false; len = strlen(str); if(len == 0) return false; for(i = 0, c = str, isBad = false; i < len && !isBad; ++i, c++) { if(i != 0 && *c == '-') isBad = true; // sign is in the wrong place. else if(*c == '.') { if(foundDP) isBad = true; // multiple decimal places?? else foundDP = true; } else if(*c < '0' || *c > '9') isBad = true; // other non-numeric character. } return !isBad; } // This is the new flat distribution table static unsigned char rngTable[256] = { 201, 1, 243, 19, 18, 42, 183, 203, 101, 123, 154, 137, 34, 118, 10, 216, 135, 246, 0, 107, 133, 229, 35, 113, 177, 211, 110, 17, 139, 84, 251, 235, 182, 166, 161, 230, 143, 91, 24, 81, 22, 94, 7, 51, 232, 104, 122, 248, 175, 138, 127, 171, 222, 213, 44, 16, 9, 33, 88, 102, 170, 150, 136, 114, 62, 3, 142, 237, 6, 252, 249, 56, 74, 30, 13, 21, 180, 199, 32, 132, 187, 234, 78, 210, 46, 131, 197, 8, 206, 244, 73, 4, 236, 178, 195, 70, 121, 97, 167, 217, 103, 40, 247, 186, 105, 39, 95, 163, 99, 149, 253, 29, 119, 83, 254, 26, 202, 65, 130, 155, 60, 64, 184, 106, 221, 93, 164, 196, 112, 108, 179, 141, 54, 109, 11, 126, 75, 165, 191, 227, 87, 225, 156, 15, 98, 162, 116, 79, 169, 140, 190, 205, 168, 194, 41, 250, 27, 20, 14, 241, 50, 214, 72, 192, 220, 233, 67, 148, 96, 185, 176, 181, 215, 207, 172, 85, 89, 90, 209, 128, 124, 2, 55, 173, 66, 152, 47, 129, 59, 43, 159, 240, 239, 12, 189, 212, 144, 28, 200, 77, 219, 198, 134, 228, 45, 92, 125, 151, 5, 53, 255, 52, 68, 245, 160, 158, 61, 86, 58, 82, 117, 37, 242, 145, 69, 188, 115, 76, 63, 100, 49, 111, 153, 80, 38, 57, 174, 224, 71, 231, 23, 25, 48, 218, 120, 147, 208, 36, 226, 223, 193, 238, 157, 204, 146, 31 }; static int rngIndex = 0, rngIndex2 = 0; byte RNG_RandByte(void) { if(rngIndex > 255) { rngIndex = 0; rngIndex2++; } return rngTable[(++rngIndex) & 0xff] ^ rngTable[rngIndex2 & 0xff]; } float RNG_RandFloat(void) { return (RNG_RandByte() | (RNG_RandByte() << 8)) / 65535.0f; } void RNG_Reset(void) { rngIndex = 0, rngIndex2 = 0; } /** * Finds the power of 2 that is equal to or greater than the specified * number. */ int M_CeilPow2(int num) { int cumul; for(cumul = 1; num > cumul; cumul <<= 1); return cumul; } /** * Finds the power of 2 that is less than or equal to the specified number. */ int M_FloorPow2(int num) { int fl = M_CeilPow2(num); if(fl > num) fl >>= 1; return fl; } /** * Finds the power of 2 that is nearest the specified number. In ambiguous * cases, the smaller number is returned. */ int M_RoundPow2(int num) { int cp2 = M_CeilPow2(num), fp2 = M_FloorPow2(num); return ((cp2 - num >= num - fp2) ? fp2 : cp2); } /** * Weighted rounding. Weight determines the point where the number is still * rounded down (0..1). */ int M_WeightPow2(int num, float weight) { int fp2 = M_FloorPow2(num); float frac = (num - fp2) / (float) fp2; if(frac <= weight) return fp2; else return (fp2 << 1); } /** * @return value mod length (length > 0). */ float M_CycleIntoRange(float value, float length) { if(value < 0) { return value - ((int) (value / length) - 1) * length; } if(value > length) { return value - ((int) (value / length)) * length; } return value; } /** * Translate (dx, dy) into an angle value (degrees). */ double M_SlopeToAngle(double dx, double dy) { double angle; if(dx == 0) return (dy > 0? 90.0 : 270.0); angle = atan2((double) dy, (double) dx) * 180.0 / PI_D; if(angle < 0) angle += 360.0; return angle; } double M_Length(double x, double y) { return sqrt(x * x + y * y); } int M_NumDigits(int value) { return floor(log10(abs(value))) + 1; } /** * Normalize a vector. * * @return The former length. */ float M_Normalize(float *a) { float len = sqrt(a[VX] * a[VX] + a[VY] * a[VY] + a[VZ] * a[VZ]); if(len) { a[VX] /= len; a[VY] /= len; a[VZ] /= len; } return len; } /** * For convenience. */ float M_Distance(const float *a, const float *b) { float delta[3]; int i; for(i = 0; i < 3; ++i) delta[i] = b[i] - a[i]; return M_Normalize(delta); } float M_DotProduct(const float *a, const float *b) { return a[VX] * b[VX] + a[VY] * b[VY] + a[VZ] * b[VZ]; } void M_Scale(float *dest, const float *a, float scale) { dest[VX] = a[VX] * scale; dest[VY] = a[VY] * scale; dest[VZ] = a[VZ] * scale; } /** * Cross product of two vectors. */ void M_CrossProduct(const float *a, const float *b, float *out) { out[VX] = a[VY] * b[VZ] - a[VZ] * b[VY]; out[VY] = a[VZ] * b[VX] - a[VX] * b[VZ]; out[VZ] = a[VX] * b[VY] - a[VY] * b[VX]; } /** * Cross product of two vectors composed of three points. */ void M_PointCrossProduct(const float *v1, const float *v2, const float *v3, float *out) { float a[3], b[3]; int i; for(i = 0; i < 3; i++) { a[i] = v2[i] - v1[i]; b[i] = v3[i] - v1[i]; } M_CrossProduct(a, b, out); } /** * Area of a triangle. */ float M_TriangleArea(const float *v1, const float *v2, const float *v3) { float a[2], b[2]; float area; a[VX] = v2[VX] - v1[VX]; a[VY] = v2[VY] - v1[VY]; b[VX] = v3[VX] - v1[VX]; b[VY] = v3[VY] - v1[VY]; area = (a[VX] * b[VY] - b[VX] * a[VY]) / 2; if(area < 0) return -area; else return area; } /** * First yaw, then pitch. Two consecutive 2D rotations. * Probably could be done a bit more efficiently. */ void M_RotateVector(float vec[3], float degYaw, float degPitch) { float radYaw = degYaw / 180 * PI, radPitch = degPitch / 180 * PI; float Cos, Sin, res[3]; // Yaw. if(radYaw != 0) { Cos = cos(radYaw); Sin = sin(radYaw); res[VX] = vec[VX] * Cos + vec[VY] * Sin; res[VY] = vec[VX] * -Sin + vec[VY] * Cos; vec[VX] = res[VX]; vec[VY] = res[VY]; } // Pitch. if(radPitch != 0) { Cos = cos(radPitch); Sin = sin(radPitch); res[VZ] = vec[VZ] * Cos + vec[VX] * Sin; res[VX] = vec[VZ] * -Sin + vec[VX] * Cos; vec[VZ] = res[VZ]; vec[VX] = res[VX]; } } /** * Line a -> b, point c. The line must be exactly one unit long! */ float M_PointUnitLineDistance(const float *a, const float *b, const float *c) { return fabs(((a[VY] - c[VY]) * (b[VX] - a[VX]) - (a[VX] - c[VX]) * (b[VY] - a[VY]))); } /** * Line a -> b, point c. */ float M_PointLineDistance(const float *a, const float *b, const float *c) { float d[2], len; d[VX] = b[VX] - a[VX]; d[VY] = b[VY] - a[VY]; len = sqrt(d[VX] * d[VX] + d[VY] * d[VY]); // Accurate. if(!len) return 0; return fabs(((a[VY] - c[VY]) * (b[VX] - a[VX]) - (a[VX] - c[VX]) * (b[VY] - a[VY])) / len); } /** * Gap is the distance left between the line and the projected point. */ float M_ProjectPointOnLine(const float* point, const float* linepoint, const float* delta, float gap, float* result) { #define DOTPROD(a,b) (a[VX]*b[VX] + a[VY]*b[VY]) float pointvec[2]; float div = DOTPROD(delta, delta); float diff[2], dist; if(!div) return 0; pointvec[0] = point[VX] - linepoint[VX]; pointvec[1] = point[VY] - linepoint[VY]; div = DOTPROD(pointvec, delta) / div; if(!result) return div; result[VX] = linepoint[VX] + delta[VX] * div; result[VY] = linepoint[VY] + delta[VY] * div; // If a gap should be left, there is some extra math to do. if(gap) { diff[VX] = result[VX] - point[VX]; diff[VY] = result[VY] - point[VY]; if((dist = M_ApproxDistancef(diff[VX], diff[VY])) != 0) { int i; for(i = 0; i < 2; i++) result[i] -= diff[i] / dist * gap; } } return div; } void M_ProjectViewRelativeLine2D(const float center[2], boolean alignToViewPlane, float width, float offset, float start[2], float end[2]) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); float sinrv, cosrv; if(alignToViewPlane) { // Should be fully aligned to view plane. sinrv = -viewData->viewCos; cosrv = viewData->viewSin; } else { float trx, try, thangle; // Transform the origin point. trx = center[VX] - viewData->current.pos[VX]; try = center[VY] - viewData->current.pos[VY]; thangle = BANG2RAD(bamsAtan2(try * 10, trx * 10)) - PI / 2; sinrv = sin(thangle); cosrv = cos(thangle); } start[VX] = center[VX]; start[VY] = center[VY]; start[VX] -= cosrv * ((width / 2) + offset); start[VY] -= sinrv * ((width / 2) + offset); end[VX] = start[VX] + cosrv * width; end[VY] = start[VY] + sinrv * width; } /** * Compute the parallel distance from a partition line to a point. */ double M_ParallelDist(double lineDX, double lineDY, double linePara, double lineLength, double x, double y) { return (x * lineDX + y * lineDY + linePara) / lineLength; } /** * Compute the perpendicular distance from a partition line to a point. */ double M_PerpDist(double lineDX, double lineDY, double linePerp, double lineLength, double x, double y) { return (x * lineDY - y * lineDX + linePerp) / lineLength; } float M_BoundingBoxDiff(const float in[4], const float out[4]) { return in[BOXLEFT] - out[BOXLEFT] + in[BOXBOTTOM] - out[BOXBOTTOM] + out[BOXRIGHT] - in[BOXRIGHT] + out[BOXTOP] - in[BOXTOP]; } void M_ClearBox(fixed_t *box) { box[BOXTOP] = box[BOXRIGHT] = DDMININT; box[BOXBOTTOM] = box[BOXLEFT] = DDMAXINT; } void M_AddToBox(fixed_t *box, fixed_t x, fixed_t y) { if(x < box[BOXLEFT]) box[BOXLEFT] = x; else if(x > box[BOXRIGHT]) box[BOXRIGHT] = x; if(y < box[BOXBOTTOM]) box[BOXBOTTOM] = y; else if(y > box[BOXTOP]) box[BOXTOP] = y; } void M_JoinBoxes(float bbox[4], const float other[4]) { if(other[BOXLEFT] < bbox[BOXLEFT]) bbox[BOXLEFT] = other[BOXLEFT]; if(other[BOXRIGHT] > bbox[BOXRIGHT]) bbox[BOXRIGHT] = other[BOXRIGHT]; if(other[BOXTOP] > bbox[BOXTOP]) bbox[BOXTOP] = other[BOXTOP]; if(other[BOXBOTTOM] < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = other[BOXBOTTOM]; } void M_CopyBox(fixed_t dest[4], const fixed_t src[4]) { dest[BOXLEFT] = src[BOXLEFT]; dest[BOXRIGHT] = src[BOXRIGHT]; dest[BOXBOTTOM] = src[BOXBOTTOM]; dest[BOXTOP] = src[BOXTOP]; } #ifndef O_BINARY # define O_BINARY 0 #endif boolean M_WriteFile(const char *name, void *source, size_t length) { int handle; size_t count; handle = open(name, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0666); if(handle == -1) return false; count = write(handle, source, length); close(handle); if(count < length) return false; return true; } /** * Read a file into a buffer allocated using Z_Malloc(). */ size_t M_ReadFile(const char *name, byte **buffer) { return FileReader(name, buffer, MALLOC_ZONE); } /** * Read a file into a buffer allocated using M_Malloc(). */ size_t M_ReadFileCLib(const char *name, byte **buffer) { return FileReader(name, buffer, MALLOC_CLIB); } static size_t FileReader(const char *name, byte **buffer, int mallocType) { int handle; size_t count, length; struct stat fileinfo; byte *buf; LZFILE *file; // First try with LZSS. if((file = lzOpen((char *) name, "rp")) != NULL) { #define BSIZE 1024 byte rbuf[BSIZE]; // Read 1kb pieces until file ends. length = 0; buf = 0; while(!lzEOF(file)) { count = lzRead(rbuf, BSIZE, file); // Allocate more memory. if(mallocType == MALLOC_ZONE) { byte *newbuf = Z_Malloc(length + count, PU_STATIC, 0); if(buf) { memcpy(newbuf, buf, length); Z_Free(buf); } buf = newbuf; } else { byte *newbuf = M_Realloc(buf, length + count); if(newbuf == NULL) Con_Error("FileReader: realloc failed."); buf = newbuf; } // Copy new data to buffer. memcpy(buf + length, rbuf, count); length += count; } lzClose(file); *buffer = buf; return length; } handle = open(name, O_RDONLY | O_BINARY, 0666); if(handle == -1) { Con_Error("FileReader: Couldn't read file %s\n", name); } if(fstat(handle, &fileinfo) == -1) { Con_Error("FileReader: Couldn't read file %s\n", name); } length = fileinfo.st_size; if(mallocType == MALLOC_ZONE) { // Use zone memory allocation buf = Z_Malloc(length, PU_STATIC, NULL); } else { // Use c library memory allocation buf = M_Malloc(length); if(buf == NULL) { Con_Error("FileReader: Failed on allocation of %lu bytes for file %s.\n", (unsigned long) length, name); } } count = read(handle, buf, length); close(handle); if(count < length) { Con_Error("FileReader: Couldn't read file %s\n", name); } *buffer = buf; return length; } /** * Change string to uppercase. */ void M_ForceUppercase(char *text) { char c; while((c = *text) != 0) { if(c >= 'a' && c <= 'z') { *text++ = c - ('a' - 'A'); } else { text++; } } } void M_WriteCommented(FILE *file, const char* text) { char* buff = M_Malloc(strlen(text) + 1), *line; strcpy(buff, text); line = strtok(buff, "\n"); while(line) { fprintf(file, "# %s\n", line); line = strtok(NULL, "\n"); } M_Free(buff); } /** * The caller must provide the opening and closing quotes. */ void M_WriteTextEsc(FILE* file, const char* text) { size_t i; for(i = 0; i < strlen(text) && text[i]; ++i) { if(text[i] == '"' || text[i] == '\\') fprintf(file, "\\"); fprintf(file, "%c", text[i]); } } /** * Gives an estimation of distance (not exact) */ #if 0 fixed_t M_AproxDistance(fixed_t dx, fixed_t dy) { dx = abs(dx); dy = abs(dy); if(dx < dy) return dx + dy - (dx >> 1); return dx + dy - (dy >> 1); } #endif float M_ApproxDistancef(float dx, float dy) { dx = fabs(dx); dy = fabs(dy); if(dx < dy) return dx + dy - dx / 2; return dx + dy - dy / 2; } float M_ApproxDistance3(const float delta[3]) { return M_ApproxDistancef( M_ApproxDistancef(delta[0], delta[1]), delta[2]); } float M_ApproxDistance3f(float dx, float dy, float dz) { return M_ApproxDistancef(M_ApproxDistancef(dx, dy), dz); } /** * Writes a Targa file of the specified depth. */ int M_ScreenShot(const char* filename, int bits) { byte* screen = 0; if(bits != 16 && bits != 24) return false; // Grab that screen! screen = GL_GrabScreen(); if(bits == 16) TGA_Save16_rgb888(filename, theWindow->width, theWindow->height, screen); else TGA_Save24_rgb888(filename, theWindow->width, theWindow->height, screen); M_Free(screen); return true; } void M_PrependBasePath(char* newpath, const char* path, size_t len) { filename_t buf; if(Dir_IsAbsolute(path)) { // Can't prepend to absolute paths. strncpy(newpath, path, len); } else { dd_snprintf(buf, FILENAME_T_MAXLEN, "%s%s", ddBasePath, path); strncpy(newpath, buf, len); } } /** * If the base path is found in the beginning of the path, it is removed. */ void M_RemoveBasePath(char* newPath, const char* absPath, size_t len) { if(!strnicmp(absPath, ddBasePath, strlen(ddBasePath))) { // This makes the new path relative to the base path. strncpy(newPath, absPath + strlen(ddBasePath), len); } else { // This doesn't appear to be the base path. strncpy(newPath, absPath, len); } } /** * Expands >. */ void M_TranslatePath(char* translated, const char* path, size_t len) { filename_t buf; if(path[0] == '>' || path[0] == '}') { path++; if(!Dir_IsAbsolute(path)) M_PrependBasePath(buf, path, FILENAME_T_MAXLEN); else strncpy(buf, path, FILENAME_T_MAXLEN); strncpy(translated, buf, len); } else if(translated != path) { strncpy(translated, path, len); } Dir_FixSlashes(translated, len); } /** * Also checks for '>'. * The file must be a *real* file! */ int M_FileExists(const char* file) { filename_t buf; M_TranslatePath(buf, file, FILENAME_T_MAXLEN); return !access(buf, 4); // Read permission? } /** * Check that the given directory exists. If it doesn't, create it. * The path must be relative! * * @return @c true, if the directory already exists. */ boolean M_CheckPath(const char* path) { filename_t full, buf; char* ptr, *endptr; // Convert all backslashes to normal slashes. strncpy(full, path, FILENAME_T_MAXLEN); Dir_FixSlashes(full, FILENAME_T_MAXLEN); if(!access(full, 0)) return true; // Quick test. // Check and create the path in segments. ptr = full; memset(buf, 0, sizeof(buf)); do { endptr = strchr(ptr, DIR_SEP_CHAR); if(!endptr) strncat(buf, ptr, FILENAME_T_MAXLEN); else strncat(buf, ptr, endptr - ptr); if(access(buf, 0)) { // Path doesn't exist, create it. #if defined(WIN32) mkdir(buf); #elif defined(UNIX) mkdir(buf, 0775); #endif } strncat(buf, DIR_SEP_STR, FILENAME_T_MAXLEN); ptr = endptr + 1; } while(endptr); return false; } /** * The dot is not included in the returned extension. * The extension can be at most 10 characters long. */ void M_GetFileExt(char* ext, const char* path, size_t len) { char* ptr = strrchr(path, '.'); *ext = 0; if(!ptr) return; strncpy(ext, ptr + 1, len); strlwr(ext); } char* M_FindFileExtension(char* path) { if(path && path[0]) { size_t len = strlen(path); char* p = NULL; p = path + len - 1; if(p - path > 1 && *p != DIR_SEP_CHAR && *p != DIR_WRONG_SEP_CHAR) { do { if(*(p - 1) == DIR_SEP_CHAR || *(p - 1) == DIR_WRONG_SEP_CHAR) break; if(*p == '.') return p - path < len - 1? p + 1 : NULL; } while(--p > path); } } return NULL; // Not found. } /** * The new extension must not include a dot. */ void M_ReplaceFileExt(char* path, const char* newext, size_t len) { char* ptr = M_FindFileExtension(path); if(!ptr) { strncat(path, ".", FILENAME_T_MAXLEN); strncat(path, newext, FILENAME_T_MAXLEN); } else { strncpy(ptr, newext, FILENAME_T_MAXLEN); } } /** * Return a prettier copy of the original path. */ const char* M_PrettyPath(const char* path) { #define MAX_BUFS 8 static filename_t buffers[MAX_BUFS]; static uint index = 0; char* str; size_t len = path? strlen(path) : 0; if(len > 0 && !strnicmp(path, ddBasePath, len)) { str = buffers[index++ % MAX_BUFS]; M_RemoveBasePath(str, path, FILENAME_T_MAXLEN); Dir_FixSlashes(str, FILENAME_T_MAXLEN); return str; } // We don't know how to make this prettier. return path; } /** * Concatenates src to dest as a quoted string. " is escaped to \". * Returns dest. */ char* M_StrCatQuoted(char* dest, const char* src, size_t len) { size_t k = strlen(dest) + 1, i; strncat(dest, "\"", len); for(i = 0; src[i]; i++) { if(src[i] == '"') { strncat(dest, "\\\"", len); k += 2; } else { dest[k++] = src[i]; dest[k] = 0; } } strncat(dest, "\"", len); return dest; } /** * Somewhat similar to strtok(). */ char* M_StrTok(char** cursor, char* delimiters) { char* begin = *cursor; while(**cursor && !strchr(delimiters, **cursor)) (*cursor)++; if(**cursor) { // Stop here. **cursor = 0; // Advance one more so we'll start from the right character on // the next call. (*cursor)++; } return begin; } /** * Advances time and return true if the trigger is triggered. * * @param trigger Time trigger. * @param advanceTime Amount of time to advance the trigger. * * @return @c true, if the trigger has accumulated enough time * to fill the trigger's time threshold. */ boolean M_RunTrigger(trigger_t *trigger, timespan_t advanceTime) { // Either use the trigger's duration, or fall back to the default. timespan_t duration = (trigger->duration? trigger->duration : 1.0f/35); trigger->accum += advanceTime; if(trigger->accum >= duration) { trigger->accum -= duration; return true; } // It wasn't triggered. return false; } /** * Advances time and return true if the trigger is triggered. * * @param trigger Time trigger. * @param advanceTime Amount of time to advance the trigger. * * @return @c true, if the trigger has accumulated enough time * to fill the trigger's time threshold. */ boolean M_CheckTrigger(const trigger_t *trigger, timespan_t advanceTime) { // Either use the trigger's duration, or fall back to the default. timespan_t duration = (trigger->duration? trigger->duration : 1.0f/35); return (trigger->accum + advanceTime>= duration); } /** * Calculate CRC-32 for an arbitrary data buffer. */ uint M_CRC32(byte *data, uint length) { /* ====================================================================== */ /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ /* code or tables extracted from it, as desired without restriction. */ /* */ /* First, the polynomial itself and its table of feedback terms. The */ /* polynomial is */ /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ /* */ /* Note that we take it "backwards" and put the highest-order term in */ /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ /* the MSB being 1. */ /* */ /* Note that the usual hardware shift register implementation, which */ /* is what we're using (we're merely optimizing it by doing eight-bit */ /* chunks at a time) shifts bits into the lowest-order term. In our */ /* implementation, that means shifting towards the right. Why do we */ /* do it this way? Because the calculated CRC must be transmitted in */ /* order from highest-order term to lowest-order term. UARTs transmit */ /* characters in order from LSB to MSB. By storing the CRC this way, */ /* we hand it to the UART in the order low-byte to high-byte; the UART */ /* sends each low-bit to hight-bit; and the result is transmission bit */ /* by bit from highest- to lowest-order term without requiring any bit */ /* shuffling on our part. Reception works similarly. */ /* */ /* The feedback terms table consists of 256, 32-bit entries. Notes: */ /* */ /* The table can be generated at runtime if desired; code to do so */ /* is shown later. It might not be obvious, but the feedback */ /* terms simply represent the results of eight shift/xor opera- */ /* tions for all combinations of data and CRC register values. */ /* */ /* The values must be right-shifted by eight bits by the "updcrc" */ /* logic; the shift must be unsigned (bring in zeroes). On some */ /* hardware you could probably optimize the shift in assembler by */ /* using byte-swap instructions. */ /* polynomial $edb88320 */ /* */ /* -------------------------------------------------------------------- */ static unsigned long crc32_tab[] = { 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL }; unsigned int i; unsigned long crc32 = 0; for(i = 0; i < length; ++i) { crc32 = crc32_tab[(crc32 ^ data[i]) & 0xff] ^ (crc32 >> 8); } return crc32; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_linkedlist.c0000644000175000017500000006174711357170242023572 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_linkedlist.c: A pretty simple linked list implementation. * * Supports single, double and ring lists. */ // HEADER FILES ------------------------------------------------------------ #include #include #ifndef NDEBUG #include // For debug message output. #endif #include "m_linkedlist.h" // MACROS ------------------------------------------------------------------ #define COMPARETYPERELATIVE(type) \ ((*(type *)a < *(type *)b) - (*(type *)a > *(type *)b)) #define COMPAREFUNCTYPERELATIVE(name, type) \ COMPAREFUNC(name) \ { \ return COMPARETYPERELATIVE(type); \ } // TYPES ------------------------------------------------------------------- typedef struct listnode_s { struct listnode_s *next, *prev; void *data; } listnode_t; typedef struct liststate_s { int flags; listindex_t numElements; int lastError; } liststate_t; typedef struct linkedlist_s { // List state: liststate_t *state; // List structure: listnode_t *headptr, *tailptr; listnode_t *unused; // Misc: comparefunc funcCompare; } list_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static __inline listnode_t *allocNode(void) { return malloc(sizeof(listnode_t)); } static __inline void freeNode(listnode_t *node) { free(node); } static __inline listnode_t *newNode(list_t *list) { listnode_t *n; // Do we have any unused nodes we can reuse? if(list->unused != NULL) { n = list->unused; list->unused = n->next; } else { // Allocate another node. n = allocNode(); } if(!n) { list->state->lastError = LL_ERROR_OUT_OF_MEMORY; return NULL; } n->next = n->prev = n->data = NULL; return n; } static __inline void moveNodeForReuse(list_t *list, listnode_t *node) { if(list->unused != NULL) node->next = list->unused; else node->next = NULL; node->prev = NULL; list->unused = node; } static __inline void insertNodeAfter(list_t *list, listnode_t *node, listnode_t *newnode) { newnode->prev = node; newnode->next = node->next; if(list->tailptr == node) { list->tailptr = newnode; if(list->state->flags & LCF_CIRCULAR) list->headptr->prev = newnode; } else node->next->prev = newnode; node->next = newnode; } static __inline void insertNodeBefore(list_t *list, listnode_t *node, listnode_t *newnode) { newnode->prev = node->prev; newnode->next = node; if(list->headptr == node) { list->headptr = newnode; if(list->state->flags & LCF_CIRCULAR) list->tailptr->next = newnode; } else node->prev->next = newnode; node->prev = newnode; } static __inline void insertNodeAtStart(list_t *list, listnode_t *newnode) { if(list->headptr == NULL) { list->headptr = list->tailptr = newnode; if(list->state->flags & LCF_CIRCULAR) newnode->prev = newnode->next = newnode; else newnode->prev = newnode->next = NULL; } else insertNodeBefore(list, list->headptr, newnode); } static __inline void insertNodeAtEnd(list_t *list, listnode_t *newnode) { if(list->tailptr == NULL) { list->headptr = list->tailptr = newnode; if(list->state->flags & LCF_CIRCULAR) newnode->prev = newnode->next = newnode; else newnode->prev = newnode->next = NULL; } else insertNodeAfter(list, list->tailptr, newnode); } static __inline void removeNode(list_t *list, listnode_t *node) { if(list->state->flags & LCF_CIRCULAR) { if(node->next == node) { list->headptr = list->tailptr = NULL; } else { node->next->prev = node->prev; node->prev->next = node->next; if(node == list->tailptr) list->tailptr = node->prev; if(node == list->headptr) list->headptr = node->next; } } else { if(node->prev == NULL) list->headptr = node->next; else node->prev->next = node->next; if(node->next == NULL) list->tailptr = node->prev; else node->next->prev = node->prev; } moveNodeForReuse(list, node); } static listindex_t findByData(const list_t *list, const void *data) { if(list->state->numElements > 0) { listnode_t *n; listindex_t idx; int found; n = list->headptr; idx = 0; found = 0; do { if(!list->funcCompare(n->data, data)) { found = 1; } else { n = n->next; idx++; } } while(n != ((list->state->flags & LCF_CIRCULAR)? list->headptr : NULL) && !found); if(found) return idx; } list->state->lastError = LL_ERROR_UNDERFLOW; return -1; } static listnode_t *findAtPosition(const list_t *list, listindex_t position) { if(list->state->numElements > 0) { listindex_t id; listnode_t *n; int found = 0; if(position < 0) { list->state->lastError = LL_ERROR_UNDERFLOW; return NULL; } if(position >= list->state->numElements) { list->state->lastError = LL_ERROR_OVERFLOW; return NULL; } if(position == 0) return list->headptr; if(position == list->state->numElements - 1) return list->tailptr; id = 0; n = list->headptr; found = 0; do { if(id == position) { found = 1; } else { id++; n = n->next; } } while(n != ((list->state->flags & LCF_CIRCULAR)? list->headptr : NULL) && !found); if(found) return n; } list->state->lastError = LL_ERROR_UNDERFLOW; return NULL; } static __inline void* getAt(const list_t *list, listindex_t position) { void *data = NULL; listnode_t *n; if((n = findAtPosition(list, position)) != NULL) { data = n->data; } return data; } static __inline void* extractAt(list_t *list, listindex_t position) { void *data = NULL; listnode_t *n; if((n = findAtPosition(list, position)) != NULL) { data = n->data; removeNode(list, n); list->state->numElements--; } return data; } static __inline int exchangeElements(list_t *list, listindex_t positionA, listindex_t positionB) { listnode_t *a, *b; void *tmp; if((a = findAtPosition(list, positionA)) == NULL) return 0; if((b = findAtPosition(list, positionB)) == NULL) return 0; // Do the exchange. tmp = a->data; a->data = b->data; b->data = tmp; return 1; // Success! } static __inline void clear(list_t *list) { if(list->state->numElements > 0) { listnode_t *n, *np; // Free the list contents. n = list->headptr; do { np = n->next; moveNodeForReuse(list, n); n = np; } while(n != ((list->state->flags & LCF_CIRCULAR)? list->headptr : NULL)); list->state->numElements = 0; list->headptr = list->tailptr = NULL; } } static __inline void clearUnused(list_t *list) { listnode_t *n, *np; // Free any unused nodes. n = list->unused; while(n != NULL) { np = n->next; freeNode(n); n = np; } list->unused = NULL; } /** * Merge left and right lists into a new list. */ static listnode_t *mergeLists(listnode_t *left, listnode_t *right, comparefunc funcCompare) { listnode_t tmp, *np; np = &tmp; tmp.next = np; while(left != NULL && right != NULL) { if(funcCompare(left->data, right->data) <= 0) { np->next = left; np = left; left = left->next; } else { np->next = right; np = right; right = right->next; } } // At least one of these lists is now empty. if(left) np->next = left; if(right) np->next = right; // Is the list empty? if(tmp.next == &tmp) return NULL; return tmp.next; } /** * Split the given list into two. * * @return Ptr to the head of the new list. */ static listnode_t *splitList(listnode_t *list) { listnode_t *lista, *listb, *listc; if(!list) return NULL; lista = listb = listc = list; do { listc = listb; listb = listb->next; lista = lista->next; if(lista != NULL) lista = lista->next; } while(lista); listc->next = NULL; return listb; } static listnode_t *doMergeSort(listnode_t *list, comparefunc funcCompare) { listnode_t *p; if(list->next) { p = splitList(list); // Sort both halves and merge them back. list = mergeLists(doMergeSort(list, funcCompare), doMergeSort(p, funcCompare), funcCompare); } return list; } static void mergeSort(list_t *list) { if(list->state->numElements > 1) { listnode_t *n, *last; if(list->state->flags & LCF_CIRCULAR) { // Break the ring so we can sort more easily. list->tailptr->next = NULL; list->headptr->prev = NULL; } list->headptr = doMergeSort(list->headptr, list->funcCompare); // Only singly linked atm, we need to be doubly linked. last = list->headptr; n = last->next; do { n->prev = last; last = n; n = n->next; } while(n != NULL); list->tailptr = last; // Circularly linked? if(list->state->flags & LCF_CIRCULAR) { // Link the ring back. list->tailptr->next = list->headptr; list->headptr->prev = list->tailptr; } else { list->tailptr->next = NULL; list->headptr->prev = NULL; } } } static linklist_t *createList(int flags, comparefunc cFunc) { list_t *list = malloc(sizeof(list_t)); liststate_t *state = malloc(sizeof(liststate_t)); list->headptr = list->tailptr = NULL; list->unused = NULL; list->funcCompare = cFunc; list->state = state; list->state->numElements = 0; list->state->flags = flags; list->state->lastError = LL_NO_ERROR; return (linklist_t*) list; } /** * Create a new (empty) linked list, with default paramaters. * * @return Ptr to the newly created list. */ linklist_t *List_Create(void) { return createList(0, compareAddress); } /** * Create a new (empty) linked list, with paramaters. * * @param flags Creation flags specify list behavior: * LCF_CIRCULAR: * The list forms a ring of items, as opposed to the * default linear list. * @param cFunc If @c NULL, the default compare function (compare by * address) will be set. * @return Ptr to the newly created list. */ linklist_t *List_Create2(int flags, comparefunc cFunc) { return createList(flags, (!cFunc? compareAddress : cFunc)); } /** * Destroy a linked list. * * @param llist Ptr to the list to be destroyed. */ void List_Destroy(linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; clear(list); clearUnused(list); free(list->state); free(list); return; } } /** * Insert data as a new element at the beginning of the given list. * * @param llist Ptr to the list being added to. * @param data Ptr to the element being added. * @return Non-zero, iff successfull. */ int List_InsertFront(linklist_t *llist, const void *data) { if(llist) { list_t *list = (list_t*) llist; listnode_t *n; n = newNode(list); n->data = (void*) data; list->state->numElements++; // Link it in. insertNodeAtStart(list, n); return 1; } return 0; } /** * Insert data as a new element at the end of the given list. * * @param llist Ptr to the list being added to. * @param data Ptr to the element being added. * @return Non-zero iff successfull. */ int List_InsertBack(linklist_t *llist, const void *data) { if(llist) { list_t *list = (list_t*) llist; listnode_t *n; n = newNode(list); n->data = (void *) data; list->state->numElements++; // Link it in. insertNodeAtEnd(list, n); return 1; } return 0; } /** * Extract the element currently at the front of the given list. * * @param llist Ptr to the list to remove an element from. * @return Ptr to the extracted element if found and removed * successfully. */ void *List_ExtractFront(linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; return extractAt(list, 0); } return NULL; } /** * Extract the element currently at the back of the given list. * * @param llist Ptr to the list to remove an element from. * @return Ptr to the extracted element if found and removed * successfully. */ void *List_ExtractBack(linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; return extractAt(list, list->state->numElements - 1); } return NULL; } /** * Extract an element from the list at the given position. * \note An O(n) opperation. * * @param llist Ptr to the list to extract an element from. * @param position Position of the element to be extracted. * @return Ptr to the extracted element if found and removed * successfully. */ void *List_ExtractAt(linklist_t *llist, listindex_t position) { if(llist) { list_t *list = (list_t*) llist; return extractAt(list, position); } return NULL; } /** * Retrieve a ptr to the element at the front of a linked list. * * @param llist Ptr to the list to retrieve the element from. * @return @c true, iff an element was found at front of the list. */ void *List_GetFront(const linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; return getAt(list, 0); } return NULL; } /** * Retrieve a ptr to the element at the back of a linked list. * * @param llist Ptr to the list to retrieve the element from. * @return @c true, iff an element was found at back of the list. */ void *List_GetBack(const linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; return getAt(list, list->state->numElements - 1); } return NULL; } /** * Retrieve a ptr to an element at the given position in a linked list. * \note An O(n) opperation. * * @param llist Ptr to the list to retrieve the element from. * @param position Position of the element to be retrieved. * @return Ptr to the element if found at the given position. */ void *List_GetAt(const linklist_t *llist, listindex_t position) { if(llist) { list_t *list = (list_t*) llist; return getAt(list, position); } return NULL; } /** * Exchange two elements in the linked list. * \note An O(n+n) opperation! * * @param llist Ptr to the list to exchange the elements of. * @param positionA Position of the first element being exchanged. * @param positionB Position of the send element being exchanged. * @return Non-zero if successfull. */ int List_Exchange(linklist_t *llist, listindex_t positionA, listindex_t positionB) { if(llist) { list_t *list = (list_t*) llist; return exchangeElements(list, positionA, positionB); } return 0; } /** * Search the link list for a specific element. * \note An O(n) opperation. * * @param llist Ptr to the list to be searched. * @return Index of the element in the list if found, else @c <0. */ listindex_t List_Find(const linklist_t *llist, const void *data) { if(llist) { list_t *list = (list_t*) llist; return findByData(list, data); } return -1; } /** * Sort the elements of the given list using a recursive mergesort * algorithm. * * Time: Average O(nlogn), Best O(nlogn), Worst: O(nlogn) * Space: Constant * Stability: Stable * * @param llist Ptr to the list to be sorted. */ void List_Sort(linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; mergeSort(list); return; } } /** * Clears the given linked list. All elements are removed from the list but * data items attached to elements will persist. * * @param llist Ptr to the list to be cleared. */ void List_Clear(linklist_t *llist) { if(llist) { clear((list_t*) llist); return; } } /** * How many elements are there in the given list? * * @param llist Ptr to the list to test. * @return @c >= 0, Number of elements in the list else, * @c <0, if error. */ listindex_t List_Count(const linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; return list->state->numElements; } return -1; } /** * Set the compare func used when sorting and searching for list elements. * * @param llist Ptr to the list to change the compare func of. * @param func Ptr to the compare func to use. Note: If @ NULL, the * default compareAddress will be assigned. */ void List_SetCompareFunc(linklist_t *llist, comparefunc func) { if(llist) { list_t *list = (list_t*) llist; if(!func) list->funcCompare = compareAddress; else list->funcCompare = func; return; } } /** * Calls func for all elements in the given list, if a callback returns * zero; iteration is stopped immediately. * * @param llist Ptr to the list to process. * @param iterateFlags * LIF_REVERSE: * Iteration will proceed from tail to head. * @param data Ptr to pass to the callback. * @param func Callback to make for each object. * * @return @c <0, if error else, * @c >0, iff every callback returns non-zero else, * @c == 0, if iteration was ended by the callback. */ int List_Iterate(const linklist_t *llist, int iterateFlags, void *data, int (*callback) (void *element, void *data)) { if(llist) { list_t *list = (list_t*) llist; int retVal = 1; if(list->state->numElements > 0) { listnode_t *n; int isDone; if(iterateFlags & LIF_REVERSE) n = list->tailptr; else n = list->headptr; isDone = 0; do { if(!callback(n->data, data)) { retVal = 0; isDone = 1; } else { if(iterateFlags & LIF_REVERSE) n = n->prev; else n = n->next; } } while(n && !isDone); } return retVal; } return -1; } /** * Retrieve the last error reported by the given list. * * @param llist Ptr to the list to process. * @return Last error reported by the list. */ int List_GetError(const linklist_t *llist) { if(llist) { list_t *list = (list_t*) llist; return list->state->lastError; } return PTR_NOT_LIST; } /** * Compare (int) elements by their numerical relativity. */ COMPAREFUNCTYPERELATIVE(compareInt, int) /** * Compare (unsigned int) elements by their numerical relativity. */ COMPAREFUNCTYPERELATIVE(compareUInt, unsigned int) /** * Compare (float) elements by their numerical relativity. */ COMPAREFUNCTYPERELATIVE(compareFloat, float) /** * Compare (double) elements by their numerical relativity. */ COMPAREFUNCTYPERELATIVE(compareDouble, double) /** * Compare ptr elements by their memory address relativity. */ COMPAREFUNCTYPERELATIVE(compareAddress, void*) /** * Compare (c-string) elements by their lexical relativity (case-sensitive). */ COMPAREFUNC(compareString) { return strcmp(b, a); } #ifndef NDEBUG int printInt(void *element, void *data) { int value = *(const int*) element; printf(" value = %i\n", value); return 1; // Continue iteration. } static int checkError(linklist_t *list) { int error; if((error = List_GetError(list)) != LL_NO_ERROR) printf("List error: %i!\n", error); return error; } static void testList(int cFlags) { linklist_t *list; int *data, i, count; int integers[10] = {2456, 12, 76889, 45, 2, 0, -45, 680, -4005, 89}; if(cFlags < 0) list = List_Create(); else list = List_Create2(cFlags, NULL); checkError(list); if(List_Count(list) != 0) printf("ERROR: List not empty on create!\n"); for(i = 0; i < 10; ++i) { List_InsertFront(list, &integers[i]); checkError(list); } if((count = List_Count(list)) != 10) printf("Error: List miscounted!\n"); data = List_GetFront(list); checkError(list); if(!data || *data != 89) printf("ERROR: Incorrect first element!\n"); data = List_GetBack(list); checkError(list); if(!data || *data != 2456) printf("ERROR: Incorrect last element!\n"); //printf(" Set list compare to: compareInt\n"); List_SetCompareFunc(list, compareInt); checkError(list); //printf(" Sort list contents.\n"); List_Sort(list); checkError(list); if((count = List_Count(list)) != 10) printf("Error: List miscounted!\n"); data = List_GetFront(list); checkError(list); if(!data || *data != 76889) printf("ERROR: Incorrect first element!\n"); data = List_GetBack(list); checkError(list); if(!data || *data != -4005) printf("ERROR: Incorrect last element!\n"); data = List_ExtractFront(list); checkError(list); if(!data || *data != 76889) printf("ERROR: Incorrect first element!\n"); data = List_ExtractBack(list); checkError(list); if(!data || *data != -4005) printf("ERROR: Incorrect last element!\n"); if((count = List_Count(list)) != 8) printf("Error: List miscounted!\n"); List_Exchange(list, 1, 7); checkError(list); data = List_GetAt(list, 1); checkError(list); if(!data || *data != -45) printf("ERROR: Incorrect element #1!\n"); data = List_GetAt(list, 7); checkError(list); if(!data || *data != 680) printf("ERROR: Incorrect element #7!\n"); //printf(" Clearing list\n"); List_Clear(list); checkError(list); if((count = List_Count(list)) != 0) printf("Error: List miscounted!\n"); List_Destroy(list); } /** * Dry run the basic list operations to test it is functioning expectedly. */ void List_Test(void) { printf("\n\nTesting list operations...\n"); printf("Linear list...\n"); testList(-1); // Linear list. printf("Circular list...\n"); testList(LCF_CIRCULAR); // Circular (ring) list. printf("...complete.\n"); } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_world.c0000644000175000017500000015740711357170242022563 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_world.c: World Setup and Refresh */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_play.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_audio.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // $smoothplane: Maximum speed for a smoothed plane. #define MAX_SMOOTH_PLANE_MOVE (64) // $smoothmatoffset: Maximum speed for a smoothed material offset. #define MAX_SMOOTH_MATERIAL_MOVE (8) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int rendSkyLight = 1; // cvar. float rendLightWallAngle = 1.2f; // Intensity of angle-based wall lighting. byte rendLightWallAngleSmooth = true; boolean firstFrameAfterLoad; boolean ddMapSetup; nodeindex_t* linelinks; // Indices to roots. skyfix_t skyFix[2]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean noSkyColorGiven; static float skyColorRGB[4], balancedRGB[4]; static float skyColorBalance; static surfacelistnode_t* unusedSurfaceListNodes = NULL; // CODE -------------------------------------------------------------------- /** * Allocate a new surface list node. */ static surfacelistnode_t* allocListNode(void) { surfacelistnode_t* node = Z_Calloc(sizeof(*node), PU_STATIC, 0); return node; } /** * Free all memory acquired for the given surface list node. */ static void freeListNode(surfacelistnode_t* node) { if(node) Z_Free(node); } surfacelistnode_t* R_SurfaceListNodeCreate(void) { surfacelistnode_t* node; // Is there a free node in the unused list? if(unusedSurfaceListNodes) { node = unusedSurfaceListNodes; unusedSurfaceListNodes = node->next; } else { node = allocListNode(); } node->data = NULL; node->next = NULL; return node; } void R_SurfaceListNodeDestroy(surfacelistnode_t* node) { // Move it to the list of unused nodes. node->data = NULL; node->next = unusedSurfaceListNodes; unusedSurfaceListNodes = node; } /** * Adds the surface to the given surface list. * * @param sl The surface list to add the surface to. * @param suf The surface to add to the list. */ void R_SurfaceListAdd(surfacelist_t* sl, surface_t* suf) { surfacelistnode_t* node; if(!sl || !suf) return; // Check whether this surface is already in the list. node = sl->head; while(node) { if((surface_t*) node->data == suf) return; // Yep. node = node->next; } // Not found, add it to the list. node = R_SurfaceListNodeCreate(); node->data = suf; node->next = sl->head; sl->head = node; sl->num++; } boolean R_SurfaceListRemove(surfacelist_t* sl, const surface_t *suf) { surfacelistnode_t* last, *n; if(!sl || !suf) return false; last = sl->head; if(last) { n = last->next; while(n) { if((surface_t*) n->data == suf) { last->next = n->next; R_SurfaceListNodeDestroy(n); sl->num--; return true; } last = n; n = n->next; } } return false; } /** * Iterate the list of surfaces making a callback for each. * * @param sl The surface list to iterate. * @param callback The callback to make. Iteration will continue * until a callback returns a zero value. * @param context Is passed to the callback function. */ boolean R_SurfaceListIterate(surfacelist_t* sl, boolean (*callback) (surface_t* suf, void*), void* context) { boolean result = true; surfacelistnode_t* n, *np; if(sl) { n = sl->head; while(n) { np = n->next; if((result = callback((surface_t*) n->data, context)) == 0) break; n = np; } } return result; } boolean updateMovingSurface(surface_t* suf, void* context) { // X Offset suf->oldOffset[0][0] = suf->oldOffset[0][1]; suf->oldOffset[0][1] = suf->offset[0]; if(suf->oldOffset[0][0] != suf->oldOffset[0][1]) if(fabs(suf->oldOffset[0][0] - suf->oldOffset[0][1]) >= MAX_SMOOTH_MATERIAL_MOVE) { // Too fast: make an instantaneous jump. suf->oldOffset[0][0] = suf->oldOffset[0][1]; } // Y Offset suf->oldOffset[1][0] = suf->oldOffset[1][1]; suf->oldOffset[1][1] = suf->offset[1]; if(suf->oldOffset[1][0] != suf->oldOffset[1][1]) if(fabs(suf->oldOffset[1][0] - suf->oldOffset[1][1]) >= MAX_SMOOTH_MATERIAL_MOVE) { // Too fast: make an instantaneous jump. suf->oldOffset[1][0] = suf->oldOffset[1][1]; } return true; } /** * $smoothmatoffset: Roll the surface material offset tracker buffers. */ void R_UpdateMovingSurfaces(void) { if(!movingSurfaceList) return; R_SurfaceListIterate(movingSurfaceList, updateMovingSurface, NULL); } boolean resetMovingSurface(surface_t* suf, void* context) { // X Offset. suf->visOffsetDelta[0] = 0; suf->oldOffset[0][0] = suf->oldOffset[0][1] = suf->offset[0]; // Y Offset. suf->visOffsetDelta[1] = 0; suf->oldOffset[1][0] = suf->oldOffset[1][1] = suf->offset[1]; Surface_Update(suf); R_SurfaceListRemove(movingSurfaceList, suf); return true; } boolean interpMovingSurface(surface_t* suf, void* context) { // X Offset. suf->visOffsetDelta[0] = suf->oldOffset[0][0] * (1 - frameTimePos) + suf->offset[0] * frameTimePos - suf->offset[0]; // Y Offset. suf->visOffsetDelta[1] = suf->oldOffset[1][0] * (1 - frameTimePos) + suf->offset[1] * frameTimePos - suf->offset[1]; // Visible material offset. suf->visOffset[0] = suf->offset[0] + suf->visOffsetDelta[0]; suf->visOffset[1] = suf->offset[1] + suf->visOffsetDelta[1]; Surface_Update(suf); // Has this material reached its destination? if(suf->visOffset[0] == suf->offset[0] && suf->visOffset[1] == suf->offset[1]) R_SurfaceListRemove(movingSurfaceList, suf); return true; } /** * $smoothmatoffset: interpolate the visual offset. */ void R_InterpolateMovingSurfaces(boolean resetNextViewer) { if(!movingSurfaceList) return; if(resetNextViewer) { // Reset the material offset trackers. R_SurfaceListIterate(movingSurfaceList, resetMovingSurface, NULL); } // While the game is paused there is no need to calculate any // visual material offsets. else //if(!clientPaused) { // Set the visible material offsets. R_SurfaceListIterate(movingSurfaceList, interpMovingSurface, NULL); } } void R_AddWatchedPlane(watchedplanelist_t *wpl, plane_t *pln) { uint i; if(!wpl || !pln) return; // Check whether we are already tracking this plane. for(i = 0; i < wpl->num; ++i) if(wpl->list[i] == pln) return; // Yes we are. wpl->num++; // Only allocate memory when it's needed. if(wpl->num > wpl->maxNum) { wpl->maxNum *= 2; // The first time, allocate 8 watched plane nodes. if(!wpl->maxNum) wpl->maxNum = 8; wpl->list = Z_Realloc(wpl->list, sizeof(plane_t*) * (wpl->maxNum + 1), PU_MAP); } // Add the plane to the list. wpl->list[wpl->num-1] = pln; wpl->list[wpl->num] = NULL; // Terminate. } boolean R_RemoveWatchedPlane(watchedplanelist_t *wpl, const plane_t *pln) { uint i; if(!wpl || !pln) return false; for(i = 0; i < wpl->num; ++i) { if(wpl->list[i] == pln) { if(i == wpl->num - 1) wpl->list[i] = NULL; else memmove(&wpl->list[i], &wpl->list[i+1], sizeof(plane_t*) * (wpl->num - 1 - i)); wpl->num--; return true; } } return false; } /** * $smoothplane: Roll the height tracker buffers. */ void R_UpdateWatchedPlanes(watchedplanelist_t *wpl) { uint i; if(!wpl) return; for(i = 0; i < wpl->num; ++i) { plane_t *pln = wpl->list[i]; pln->oldHeight[0] = pln->oldHeight[1]; pln->oldHeight[1] = pln->height; if(pln->oldHeight[0] != pln->oldHeight[1]) if(fabs(pln->oldHeight[0] - pln->oldHeight[1]) >= MAX_SMOOTH_PLANE_MOVE) { // Too fast: make an instantaneous jump. pln->oldHeight[0] = pln->oldHeight[1]; } } } /** * $smoothplane: interpolate the visual offset. */ void R_InterpolateWatchedPlanes(watchedplanelist_t *wpl, boolean resetNextViewer) { uint i; plane_t *pln; if(!wpl) return; if(resetNextViewer) { // $smoothplane: Reset the plane height trackers. for(i = 0; i < wpl->num; ++i) { pln = wpl->list[i]; pln->visHeightDelta = 0; pln->oldHeight[0] = pln->oldHeight[1] = pln->height; if(pln->type == PLN_FLOOR || pln->type == PLN_CEILING) { R_MarkDependantSurfacesForDecorationUpdate(pln); } if(R_RemoveWatchedPlane(wpl, pln)) i = (i > 0? i-1 : 0); } } // While the game is paused there is no need to calculate any // visual plane offsets $smoothplane. else //if(!clientPaused) { // $smoothplane: Set the visible offsets. for(i = 0; i < wpl->num; ++i) { pln = wpl->list[i]; pln->visHeightDelta = pln->oldHeight[0] * (1 - frameTimePos) + pln->height * frameTimePos - pln->height; // Visible plane height. pln->visHeight = pln->height + pln->visHeightDelta; if(pln->type == PLN_FLOOR || pln->type == PLN_CEILING) { R_MarkDependantSurfacesForDecorationUpdate(pln); } // Has this plane reached its destination? if(pln->visHeight == pln->height) if(R_RemoveWatchedPlane(wpl, pln)) i = (i > 0? i-1 : 0); } } } /** * Called when a floor or ceiling height changes to update the plotted * decoration origins for surfaces whose material offset is dependant upon * the given plane. */ void R_MarkDependantSurfacesForDecorationUpdate(plane_t* pln) { linedef_t** linep; if(!pln || !pln->sector->lineDefs) return; // Mark the decor lights on the sides of this plane as requiring // an update. linep = pln->sector->lineDefs; while(*linep) { linedef_t* li = *linep; if(!li->L_backside) { if(pln->type != PLN_MID) Surface_Update(&li->L_frontside->SW_surface(SEG_MIDDLE)); } else if(li->L_backsector != li->L_frontsector) { byte side = (li->L_frontsector == pln->sector? FRONT : BACK); Surface_Update(&li->L_side(side)->SW_surface(SEG_BOTTOM)); Surface_Update(&li->L_side(side)->SW_surface(SEG_TOP)); if(pln->type == PLN_FLOOR) Surface_Update(&li->L_side(side^1)->SW_surface(SEG_BOTTOM)); else Surface_Update(&li->L_side(side^1)->SW_surface(SEG_TOP)); } *linep++; } } /** * Create a new plane for the given sector. The plane will be initialized * with default values. * * Post: The sector's plane list will be replaced, the new plane will be * linked to the end of the list. * * @param sec Sector for which a new plane will be created. * * @return Ptr to the newly created plane. */ plane_t* R_NewPlaneForSector(sector_t* sec) { surface_t* suf; plane_t* plane; subsector_t** ssecPtr; if(!sec) return NULL; // Do wha? //if(sec->planeCount >= 2) // Con_Error("P_NewPlaneForSector: Cannot create plane for sector, " // "limit is %i per sector.\n", 2); // Allocate the new plane. plane = Z_Malloc(sizeof(plane_t), PU_MAP, 0); // Resize this sector's plane list. sec->planes = Z_Realloc(sec->planes, sizeof(plane_t*) * (++sec->planeCount + 1), PU_MAP); // Add the new plane to the end of the list. sec->planes[sec->planeCount-1] = plane; sec->planes[sec->planeCount] = NULL; // Terminate. // Setup header for DMU. plane->header.type = DMU_PLANE; // Initalize the plane. plane->surface.owner = (void*) plane; plane->glowRGB[CR] = plane->glowRGB[CG] = plane->glowRGB[CB] = 1; plane->glow = 0; plane->sector = sec; plane->height = plane->oldHeight[0] = plane->oldHeight[1] = 0; plane->visHeight = plane->visHeightDelta = 0; plane->soundOrg.pos[VX] = sec->soundOrg.pos[VX]; plane->soundOrg.pos[VY] = sec->soundOrg.pos[VY]; plane->soundOrg.pos[VZ] = sec->soundOrg.pos[VZ]; memset(&plane->soundOrg.thinker, 0, sizeof(plane->soundOrg.thinker)); plane->speed = 0; plane->target = 0; plane->type = PLN_MID; plane->planeID = sec->planeCount-1; // Initialize the surface. memset(&plane->surface, 0, sizeof(plane->surface)); suf = &plane->surface; suf->header.type = DMU_SURFACE; // Setup header for DMU. suf->normal[VZ] = suf->oldNormal[VZ] = 1; // \todo The initial material should be the "unknown" material. Surface_SetMaterial(suf, NULL); Surface_SetMaterialOffsetXY(suf, 0, 0); Surface_SetColorRGBA(suf, 1, 1, 1, 1); Surface_SetBlendMode(suf, BM_NORMAL); /** * Resize the biassurface lists for the subsector planes. * If we are in map setup mode, don't create the biassurfaces now, * as planes are created before the bias system is available. */ ssecPtr = sec->ssectors; while(*ssecPtr) { subsector_t* ssec = *ssecPtr; biassurface_t** newList; uint n = 0; newList = Z_Calloc(sec->planeCount * sizeof(biassurface_t*), PU_MAP, NULL); // Copy the existing list? if(ssec->bsuf) { for(; n < sec->planeCount - 1; ++n) { newList[n] = ssec->bsuf[n]; } Z_Free(ssec->bsuf); } if(!ddMapSetup) { uint i; biassurface_t* bsuf = SB_CreateSurface(); bsuf->size = ssec->numVertices; bsuf->illum = Z_Calloc(sizeof(vertexillum_t) * bsuf->size, PU_MAP, 0); for(i = 0; i < bsuf->size; ++i) SB_InitVertexIllum(&bsuf->illum[i]); newList[n] = bsuf; } ssec->bsuf = newList; *ssecPtr++; } return plane; } /** * Permanently destroys the specified plane of the given sector. * The sector's plane list is updated accordingly. * * @param id The sector, plane id to be destroyed. * @param sec Ptr to sector for which a plane will be destroyed. */ void R_DestroyPlaneOfSector(uint id, sector_t* sec) { uint i; plane_t* plane, **newList = NULL; subsector_t** ssecPtr; if(!sec) return; // Do wha? if(id >= sec->planeCount) Con_Error("P_DestroyPlaneOfSector: Plane id #%i is not valid for " "sector #%u", id, (uint) GET_SECTOR_IDX(sec)); plane = sec->planes[id]; // Create a new plane list? if(sec->planeCount > 1) { uint n; newList = Z_Malloc(sizeof(plane_t**) * sec->planeCount, PU_MAP, 0); // Copy ptrs to the planes. n = 0; for(i = 0; i < sec->planeCount; ++i) { if(i == id) continue; newList[n++] = sec->planes[i]; } newList[n] = NULL; // Terminate. } // If this plane is currently being watched, remove it. R_RemoveWatchedPlane(watchedPlaneList, plane); // If this plane's surface is in the moving list, remove it. R_SurfaceListRemove(movingSurfaceList, &plane->surface); // If this plane's surface if in the deocrated list, remove it. R_SurfaceListRemove(decoratedSurfaceList, &plane->surface); // Destroy the biassurfaces for this plane. ssecPtr = sec->ssectors; while(*ssecPtr) { subsector_t* ssec = *ssecPtr; SB_DestroySurface(ssec->bsuf[id]); if(id < sec->planeCount) memmove(ssec->bsuf + id, ssec->bsuf + id + 1, sizeof(biassurface_t*)); *ssecPtr++; } // Destroy the specified plane. Z_Free(plane); sec->planeCount--; // Link the new list to the sector. Z_Free(sec->planes); sec->planes = newList; } surfacedecor_t* R_CreateSurfaceDecoration(decortype_t type, surface_t *suf) { uint i; surfacedecor_t *d, *s, *decorations; if(!suf) return NULL; decorations = Z_Malloc(sizeof(*decorations) * (++suf->numDecorations), PU_MAP, 0); if(suf->numDecorations > 1) { // Copy the existing decorations. for(i = 0; i < suf->numDecorations - 1; ++i) { d = &decorations[i]; s = &suf->decorations[i]; memcpy(d, s, sizeof(*d)); } Z_Free(suf->decorations); } // Add the new decoration. d = &decorations[suf->numDecorations - 1]; d->type = type; suf->decorations = decorations; return d; } void R_ClearSurfaceDecorations(surface_t *suf) { if(!suf) return; if(suf->decorations) Z_Free(suf->decorations); suf->decorations = NULL; suf->numDecorations = 0; } void R_UpdateSkyFixForSec(const sector_t* sec) { boolean skyFloor, skyCeil; if(!sec) return; // Wha? skyFloor = R_IsSkySurface(&sec->SP_floorsurface); skyCeil = R_IsSkySurface(&sec->SP_ceilsurface); if(!skyFloor && !skyCeil) return; if(skyCeil) { mobj_t* mo; // Adjust for the plane height. if(sec->SP_ceilvisheight > skyFix[PLN_CEILING].height) { // Must raise the skyfix ceiling. skyFix[PLN_CEILING].height = sec->SP_ceilvisheight; } // Check that all the mobjs in the sector fit in. for(mo = sec->mobjList; mo; mo = mo->sNext) { float extent = mo->pos[VZ] + mo->height; if(extent > skyFix[PLN_CEILING].height) { // Must raise the skyfix ceiling. skyFix[PLN_CEILING].height = extent; } } } if(skyFloor) { // Adjust for the plane height. if(sec->SP_floorvisheight < skyFix[PLN_FLOOR].height) { // Must lower the skyfix floor. skyFix[PLN_FLOOR].height = sec->SP_floorvisheight; } } // Update for middle textures on two sided linedefs which intersect the // floor and/or ceiling of their front and/or back sectors. if(sec->lineDefs) { linedef_t** linePtr = sec->lineDefs; while(*linePtr) { linedef_t* li = *linePtr; // Must be twosided. if(li->L_frontside && li->L_backside) { sidedef_t* si = li->L_frontsector == sec? li->L_frontside : li->L_backside; if(si->SW_middlematerial) { if(skyCeil) { float top = sec->SP_ceilvisheight + si->SW_middlevisoffset[VY]; if(top > skyFix[PLN_CEILING].height) { // Must raise the skyfix ceiling. skyFix[PLN_CEILING].height = top; } } if(skyFloor) { float bottom = sec->SP_floorvisheight + si->SW_middlevisoffset[VY] - si->SW_middlematerial->height; if(bottom < skyFix[PLN_FLOOR].height) { // Must lower the skyfix floor. skyFix[PLN_FLOOR].height = bottom; } } } } *linePtr++; } } } /** * Fixing the sky means that for adjacent sky sectors the lower sky * ceiling is lifted to match the upper sky. The raising only affects * rendering, it has no bearing on gameplay. */ void R_InitSkyFix(void) { uint i; skyFix[PLN_FLOOR].height = DDMAXFLOAT; skyFix[PLN_CEILING].height = DDMINFLOAT; // Update for sector plane heights and mobjs which intersect the ceiling. for(i = 0; i < numSectors; ++i) { R_UpdateSkyFixForSec(SECTOR_PTR(i)); } } /** * @return Ptr to the lineowner for this line for this vertex * else @c NULL. */ lineowner_t* R_GetVtxLineOwner(const vertex_t *v, const linedef_t *line) { if(v == line->L_v1) return line->L_vo1; if(v == line->L_v2) return line->L_vo2; return NULL; } void R_SetupFog(float start, float end, float density, float *rgb) { Con_Execute(CMDS_DDAY, "fog on", true, false); Con_Executef(CMDS_DDAY, true, "fog start %f", start); Con_Executef(CMDS_DDAY, true, "fog end %f", end); Con_Executef(CMDS_DDAY, true, "fog density %f", density); Con_Executef(CMDS_DDAY, true, "fog color %.0f %.0f %.0f", rgb[0] * 255, rgb[1] * 255, rgb[2] * 255); } void R_SetupFogDefaults(void) { // Go with the defaults. Con_Execute(CMDS_DDAY,"fog off", true, false); } void R_SetupSky(ded_sky_t* sky) { int i; int skyTex; int ival = 0; float fval = 0; if(!sky) { // Go with the defaults. fval = .666667f; Rend_SkyParams(DD_SKY, DD_HEIGHT, &fval); Rend_SkyParams(DD_SKY, DD_HORIZON, &ival); Rend_SkyParams(0, DD_ENABLE, NULL); ival = P_MaterialNumForName("SKY1", MN_TEXTURES); Rend_SkyParams(0, DD_MATERIAL, &ival); ival = DD_NO; Rend_SkyParams(0, DD_MASK, &ival); fval = 0; Rend_SkyParams(0, DD_OFFSET, &fval); Rend_SkyParams(1, DD_DISABLE, NULL); // There is no sky color. noSkyColorGiven = true; return; } Rend_SkyParams(DD_SKY, DD_HEIGHT, &sky->height); Rend_SkyParams(DD_SKY, DD_HORIZON, &sky->horizonOffset); for(i = 0; i < 2; ++i) { ded_skylayer_t* layer = &sky->layers[i]; if(layer->flags & SLF_ENABLED) { skyTex = P_MaterialNumForName(layer->material.name, layer->material.mnamespace); if(!skyTex) { Con_Message("R_SetupSky: Invalid/missing texture \"%s\"\n", layer->material.name); skyTex = P_MaterialNumForName("SKY1", MN_TEXTURES); } Rend_SkyParams(i, DD_ENABLE, NULL); Rend_SkyParams(i, DD_MATERIAL, &skyTex); ival = ((layer->flags & SLF_MASKED)? DD_YES : DD_NO); Rend_SkyParams(i, DD_MASK, &ival); Rend_SkyParams(i, DD_OFFSET, &layer->offset); Rend_SkyParams(i, DD_COLOR_LIMIT, &layer->colorLimit); } else { Rend_SkyParams(i, DD_DISABLE, NULL); } } // Any sky models to setup? Models will override the normal // sphere. R_SetupSkyModels(sky); // How about the sky color? noSkyColorGiven = true; for(i = 0; i < 3; ++i) { skyColorRGB[i] = sky->color[i]; if(sky->color[i] > 0) noSkyColorGiven = false; } // Calculate a balancing factor, so the light in the non-skylit // sectors won't appear too bright. if(sky->color[0] > 0 || sky->color[1] > 0 || sky->color[2] > 0) { skyColorBalance = (0 + (sky->color[0] * 2 + sky->color[1] * 3 + sky->color[2] * 2) / 7) / 1; } else { skyColorBalance = 1; } } /** * Returns pointers to the line's vertices in such a fashion that verts[0] * is the leftmost vertex and verts[1] is the rightmost vertex, when the * line lies at the edge of `sector.' */ void R_OrderVertices(const linedef_t *line, const sector_t *sector, vertex_t *verts[2]) { byte edge; edge = (sector == line->L_frontsector? 0:1); verts[0] = line->L_v(edge); verts[1] = line->L_v(edge^1); } /** * A neighbour is a line that shares a vertex with 'line', and faces the * specified sector. */ linedef_t *R_FindLineNeighbor(const sector_t *sector, const linedef_t *line, const lineowner_t *own, boolean antiClockwise, binangle_t *diff) { lineowner_t *cown = own->link[!antiClockwise]; linedef_t *other = cown->lineDef; if(other == line) return NULL; if(diff) *diff += (antiClockwise? cown->angle : own->angle); if(!other->L_backside || other->L_frontsector != other->L_backsector) { if(sector) // Must one of the sectors match? { if(other->L_frontsector == sector || (other->L_backside && other->L_backsector == sector)) return other; } else return other; } // Not suitable, try the next. return R_FindLineNeighbor(sector, line, cown, antiClockwise, diff); } linedef_t* R_FindSolidLineNeighbor(const sector_t* sector, const linedef_t* line, const lineowner_t* own, boolean antiClockwise, binangle_t* diff) { lineowner_t* cown = own->link[!antiClockwise]; linedef_t* other = cown->lineDef; int side; if(other == line) return NULL; if(diff) *diff += (antiClockwise? cown->angle : own->angle); if(!(other->buildData.windowEffect && other->L_frontsector != sector)) { if(!other->L_frontside || !other->L_backside) return other; if(!LINE_SELFREF(other) && (other->L_frontsector->SP_floorvisheight >= sector->SP_ceilvisheight || other->L_frontsector->SP_ceilvisheight <= sector->SP_floorvisheight || other->L_backsector->SP_floorvisheight >= sector->SP_ceilvisheight || other->L_backsector->SP_ceilvisheight <= sector->SP_floorvisheight || other->L_backsector->SP_ceilvisheight <= other->L_backsector->SP_floorvisheight)) return other; // Both front and back MUST be open by this point. // Check for mid texture which fills the gap between floor and ceiling. // We should not give away the location of false walls (secrets). side = (other->L_frontsector == sector? 0 : 1); if(other->sideDefs[side]->SW_middlematerial) { float oFCeil = other->L_frontsector->SP_ceilvisheight; float oFFloor = other->L_frontsector->SP_floorvisheight; float oBCeil = other->L_backsector->SP_ceilvisheight; float oBFloor = other->L_backsector->SP_floorvisheight; if((side == 0 && ((oBCeil > sector->SP_floorvisheight && oBFloor <= sector->SP_floorvisheight) || (oBFloor < sector->SP_ceilvisheight && oBCeil >= sector->SP_ceilvisheight) || (oBFloor < sector->SP_ceilvisheight && oBCeil > sector->SP_floorvisheight))) || ( /* side must be 1 */ ((oFCeil > sector->SP_floorvisheight && oFFloor <= sector->SP_floorvisheight) || (oFFloor < sector->SP_ceilvisheight && oFCeil >= sector->SP_ceilvisheight) || (oFFloor < sector->SP_ceilvisheight && oFCeil > sector->SP_floorvisheight))) ) { if(!Rend_DoesMidTextureFillGap(other, side)) return 0; } } } // Not suitable, try the next. return R_FindSolidLineNeighbor(sector, line, cown, antiClockwise, diff); } /** * Find a backneighbour for the given line. * They are the neighbouring line in the backsector of the imediate line * neighbor. */ linedef_t *R_FindLineBackNeighbor(const sector_t *sector, const linedef_t *line, const lineowner_t *own, boolean antiClockwise, binangle_t *diff) { lineowner_t *cown = own->link[!antiClockwise]; linedef_t *other = cown->lineDef; if(other == line) return NULL; if(diff) *diff += (antiClockwise? cown->angle : own->angle); if(!other->L_backside || other->L_frontsector != other->L_backsector || other->buildData.windowEffect) { if(!(other->L_frontsector == sector || (other->L_backside && other->L_backsector == sector))) return other; } // Not suitable, try the next. return R_FindLineBackNeighbor(sector, line, cown, antiClockwise, diff); } /** * A side's alignneighbor is a line that shares a vertex with 'line' and * whos orientation is aligned with it (thus, making it unnecessary to have * a shadow between them. In practice, they would be considered a single, * long sidedef by the shadow generator). */ linedef_t *R_FindLineAlignNeighbor(const sector_t *sec, const linedef_t *line, const lineowner_t *own, boolean antiClockwise, int alignment) { #define SEP 10 lineowner_t *cown = own->link[!antiClockwise]; linedef_t *other = cown->lineDef; binangle_t diff; if(other == line) return NULL; if(!LINE_SELFREF(other)) { diff = line->angle - other->angle; if(alignment < 0) diff -= BANG_180; if(other->L_frontsector != sec) diff -= BANG_180; if(diff < SEP || diff > BANG_360 - SEP) return other; } // Can't step over non-twosided lines. if((!other->L_backside || !other->L_frontside)) return NULL; // Not suitable, try the next. return R_FindLineAlignNeighbor(sec, line, cown, antiClockwise, alignment); #undef SEP } void R_InitLinks(gamemap_t *map) { uint i; uint starttime; Con_Message("R_InitLinks: Initializing\n"); // Initialize node piles and line rings. NP_Init(&map->mobjNodes, 256); // Allocate a small pile. NP_Init(&map->lineNodes, map->numLineDefs + 1000); // Allocate the rings. starttime = Sys_GetRealTime(); map->lineLinks = Z_Malloc(sizeof(*map->lineLinks) * map->numLineDefs, PU_MAPSTATIC, 0); for(i = 0; i < map->numLineDefs; ++i) map->lineLinks[i] = NP_New(&map->lineNodes, NP_ROOT_NODE); // How much time did we spend? VERBOSE(Con_Message ("R_InitLinks: Allocating line link rings. Done in %.2f seconds.\n", (Sys_GetRealTime() - starttime) / 1000.0f)); } /** * Create a list of vertices for the subsector which are suitable for * use as the points of single a trifan. * * We are assured by the node building process that subsector->segs has * been ordered by angle, clockwise starting from the smallest angle. * So, most of the time, the points can be created directly from the * seg vertexes. * * However, we do not want any overlapping tris so check the area of * each triangle is > 0, if not; try the next vertice in the list until * we find a good one to use as the center of the trifan. If a suitable * point cannot be found use the center of subsector instead (it will * always be valid as subsectors are convex). */ static void triangulateSubSector(subsector_t *ssec) { uint baseIDX = 0, i, n; boolean found = false; // We need to find a good tri-fan base vertex, (one that doesn't // generate zero-area triangles). if(ssec->segCount <= 3) { // Always valid. found = true; } else { // Higher vertex counts need checking, we'll test each one and pick // the first good one. #define TRIFAN_LIMIT 0.1 fvertex_t *base, *a, *b; baseIDX = 0; do { seg_t *seg = ssec->segs[baseIDX]; base = &seg->SG_v1->v; i = 0; do { seg_t *seg2 = ssec->segs[i]; if(!(baseIDX > 0 && (i == baseIDX || i == baseIDX - 1))) { a = &seg2->SG_v1->v; b = &seg2->SG_v2->v; if(TRIFAN_LIMIT >= M_TriangleArea(base->pos, a->pos, b->pos)) { base = NULL; } } i++; } while(base && i < ssec->segCount); if(!base) baseIDX++; } while(!base && baseIDX < ssec->segCount); if(base) found = true; #undef TRIFAN_LIMIT } ssec->numVertices = ssec->segCount; if(!found) ssec->numVertices += 2; ssec->vertices = Z_Malloc(sizeof(fvertex_t*) * (ssec->numVertices + 1),PU_MAP, 0); // We can now create the subsector fvertex array. // NOTE: The same polygon is used for all planes of this subsector. n = 0; if(!found) ssec->vertices[n++] = &ssec->midPoint; for(i = 0; i < ssec->segCount; ++i) { uint idx; seg_t *seg; idx = baseIDX + i; if(idx >= ssec->segCount) idx = idx - ssec->segCount; seg = ssec->segs[idx]; ssec->vertices[n++] = &seg->SG_v1->v; } if(!found) ssec->vertices[n++] = &ssec->segs[0]->SG_v1->v; ssec->vertices[n] = NULL; // terminate. if(!found) ssec->flags |= SUBF_MIDPOINT; } /** * Polygonizes all subsectors in the map. */ void R_PolygonizeMap(gamemap_t *map) { uint i; uint startTime; startTime = Sys_GetRealTime(); // Polygonize each subsector. for(i = 0; i < map->numSSectors; ++i) { subsector_t *sub = &map->ssectors[i]; triangulateSubSector(sub); } // How much time did we spend? VERBOSE(Con_Message ("R_PolygonizeMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); #ifdef _DEBUG Z_CheckHeap(); #endif } /** * The test is done on subsectors. */ #if 0 /* Currently unused. */ static sector_t *getContainingSectorOf(gamemap_t* map, sector_t* sec) { uint i; float cdiff = -1, diff; float inner[4], outer[4]; sector_t* other, *closest = NULL; memcpy(inner, sec->bBox, sizeof(inner)); // Try all sectors that fit in the bounding box. for(i = 0, other = map->sectors; i < map->numSectors; other++, ++i) { if(!other->lineDefCount || (other->flags & SECF_UNCLOSED)) continue; if(other == sec) continue; // Don't try on self! memcpy(outer, other->bBox, sizeof(outer)); if(inner[BOXLEFT] >= outer[BOXLEFT] && inner[BOXRIGHT] <= outer[BOXRIGHT] && inner[BOXTOP] <= outer[BOXTOP] && inner[BOXBOTTOM]>= outer[BOXBOTTOM]) { // Sec is totally and completely inside other! diff = M_BoundingBoxDiff(inner, outer); if(cdiff < 0 || diff <= cdiff) { closest = other; cdiff = diff; } } } return closest; } #endif void R_BuildSectorLinks(gamemap_t *map) { #define DOMINANT_SIZE 1000 uint i; for(i = 0; i < map->numSectors; ++i) { sector_t *sec = &map->sectors[i]; if(!sec->lineDefCount) continue; // Is this sector large enough to be a dominant light source? if(sec->lightSource == NULL && sec->planeCount > 0 && sec->bBox[BOXRIGHT] - sec->bBox[BOXLEFT] > DOMINANT_SIZE && sec->bBox[BOXTOP] - sec->bBox[BOXBOTTOM] > DOMINANT_SIZE) { if(R_SectorContainsSkySurfaces(sec)) { uint k; // All sectors touching this one will be affected. for(k = 0; k < sec->lineDefCount; ++k) { linedef_t* lin = sec->lineDefs[k]; sector_t *other; other = lin->L_frontsector; if(other == sec) { if(lin->L_backside) other = lin->L_backsector; } if(other && other != sec) other->lightSource = sec; } } } } #undef DOMINANT_SIZE } static __inline void initSurfaceMaterialOffset(surface_t *suf) { if(!suf) return; suf->visOffset[VX] = suf->oldOffset[0][VX] = suf->oldOffset[1][VX] = suf->offset[VX]; suf->visOffset[VY] = suf->oldOffset[0][VY] = suf->oldOffset[1][VY] = suf->offset[VY]; } /** * Called by the game at various points in the map setup process. */ void R_SetupMap(int mode, int flags) { uint i; switch(mode) { case DDSMM_INITIALIZE: // Switch to fast malloc mode in the zone. This is intended for large // numbers of mallocs with no frees in between. Z_EnableFastMalloc(false); // A new map is about to be setup. ddMapSetup = true; return; case DDSMM_AFTER_LOADING: { // Update everything again. Its possible that after loading we // now have more HOMs to fix, etc.. R_InitSkyFix(); // Set intial values of various tracked and interpolated properties // (lighting, smoothed planes etc). for(i = 0; i < numSectors; ++i) { uint j; sector_t *sec = SECTOR_PTR(i); R_UpdateSector(sec, false); for(j = 0; j < sec->planeCount; ++j) { plane_t *pln = sec->SP_plane(j); pln->visHeight = pln->oldHeight[0] = pln->oldHeight[1] = pln->height; initSurfaceMaterialOffset(&pln->surface); } } for(i = 0; i < numSideDefs; ++i) { sidedef_t *si = SIDE_PTR(i); initSurfaceMaterialOffset(&si->SW_topsurface); initSurfaceMaterialOffset(&si->SW_middlesurface); initSurfaceMaterialOffset(&si->SW_bottomsurface); } P_MapInitPolyobjs(); return; } case DDSMM_FINALIZE: { gamemap_t *map = P_GetCurrentMap(); // We are now finished with the game data, map object db. P_DestroyGameMapObjDB(&map->gameObjData); // Init server data. Sv_InitPools(); // Recalculate the light range mod matrix. Rend_CalcLightModRange(NULL); // Update all sectors. Set intial values of various tracked // and interpolated properties (lighting, smoothed planes etc). for(i = 0; i < numSectors; ++i) { uint l; sector_t *sec = SECTOR_PTR(i); R_UpdateSector(sec, true); for(l = 0; l < sec->planeCount; ++l) { plane_t *pln = sec->SP_plane(l); pln->visHeight = pln->oldHeight[0] = pln->oldHeight[1] = pln->height; initSurfaceMaterialOffset(&pln->surface); } } for(i = 0; i < numSideDefs; ++i) { sidedef_t* si = SIDE_PTR(i); initSurfaceMaterialOffset(&si->SW_topsurface); initSurfaceMaterialOffset(&si->SW_middlesurface); initSurfaceMaterialOffset(&si->SW_bottomsurface); } P_MapInitPolyobjs(); // Run any commands specified in Map Info. { ded_mapinfo_t* mapInfo = Def_GetMapInfo(P_GetMapID(map)); if(mapInfo && mapInfo->execute) Con_Execute(CMDS_DED, mapInfo->execute, true, false); } // The map setup has been completed. Run the special map setup // command, which the user may alias to do something useful. if(mapID && mapID[0]) { char cmd[80]; sprintf(cmd, "init-%s", mapID); if(Con_IsValidCommand(cmd)) { Con_Executef(CMDS_DED, false, cmd); } } // Clear any input events that might have accumulated during the // setup period. DD_ClearEvents(); // Now that the setup is done, let's reset the tictimer so it'll // appear that no time has passed during the setup. DD_ResetTimer(); // Kill all local commands and determine the invoid status of players. for(i = 0; i < DDMAXPLAYERS; ++i) { player_t *plr = &ddPlayers[i]; ddplayer_t *ddpl = &plr->shared; clients[i].numTics = 0; // Determine if the player is in the void. ddpl->inVoid = true; if(ddpl->mo) { subsector_t *ssec = R_PointInSubsector(ddpl->mo->pos[VX], ddpl->mo->pos[VY]); //// \fixme $nplanes if(ssec && ddpl->mo->pos[VZ] > ssec->sector->SP_floorvisheight + 4 && ddpl->mo->pos[VZ] < ssec->sector->SP_ceilvisheight - 4) ddpl->inVoid = false; } } // Reset the map tick timer. ddMapTime = 0; // We've finished setting up the map. ddMapSetup = false; // Inform the timing system to suspend the starting of the clock. firstFrameAfterLoad = true; // Switch back to normal malloc mode in the zone. Z_Malloc will look // for free blocks in the entire zone and purge purgable blocks. Z_EnableFastMalloc(false); return; } case DDSMM_AFTER_BUSY: { gamemap_t *map = P_GetCurrentMap(); ded_mapinfo_t *mapInfo = Def_GetMapInfo(P_GetMapID(map)); // Shouldn't do anything time-consuming, as we are no longer in busy mode. if(!mapInfo || !(mapInfo->flags & MIF_FOG)) R_SetupFogDefaults(); else R_SetupFog(mapInfo->fogStart, mapInfo->fogEnd, mapInfo->fogDensity, mapInfo->fogColor); break; } default: Con_Error("R_SetupMap: Unknown setup mode %i", mode); } } void R_ClearSectorFlags(void) { uint i; sector_t *sec; for(i = 0; i < numSectors; ++i) { sec = SECTOR_PTR(i); // Clear all flags that can be cleared before each frame. sec->frameFlags &= ~SIF_FRAME_CLEAR; } } /** * Is the specified plane glowing (it glows or is a sky mask surface)? * * @return @c true, if the specified plane is non-glowing, * i.e. not glowing or a sky. */ boolean R_IsGlowingPlane(const plane_t* pln) { material_t* mat = pln->surface.material; return ((mat && (mat->flags & MATF_NO_DRAW)) || pln->glow > 0 || R_IsSkySurface(&pln->surface)); } /** * Does the specified sector contain any sky surfaces? * * @return @c true, if one or more surfaces in the given sector * use the special sky mask material. */ boolean R_SectorContainsSkySurfaces(const sector_t* sec) { uint i; boolean sectorContainsSkySurfaces; // Does this sector feature any sky surfaces? sectorContainsSkySurfaces = false; i = 0; do { if(R_IsSkySurface(&sec->SP_planesurface(i))) sectorContainsSkySurfaces = true; else i++; } while(!sectorContainsSkySurfaces && i < sec->planeCount); return sectorContainsSkySurfaces; } /** * Given a sidedef section, look at the neighbouring surfaces and pick the * best choice of material used on those surfaces to be applied to "this" * surface. * * Material on back neighbour plane has priority. * Non-animated materials are preferred. * Sky materials are ignored. */ static material_t* chooseFixMaterial(sidedef_t* s, segsection_t section) { material_t* choice1 = NULL, *choice2 = NULL; if(section == SEG_BOTTOM || section == SEG_TOP) { byte sid = (s->line->L_frontside == s? 0 : 1); sector_t* frontSec = s->line->L_sector(sid); sector_t* backSec = s->line->L_sector(sid^1); surface_t* suf; if(backSec) { suf = &backSec->SP_plane(section == SEG_BOTTOM? PLN_FLOOR : PLN_CEILING)->surface; if(suf->material && !R_IsSkySurface(suf)) choice1 = suf->material; } suf = &frontSec->SP_plane(section == SEG_BOTTOM? PLN_FLOOR : PLN_CEILING)->surface; if(suf->material && !R_IsSkySurface(suf)) choice2 = suf->material; } if(choice1 && !choice1->inAnimGroup) return choice1; if(choice2 && !choice2->inAnimGroup) return choice2; if(choice1) return choice1; if(choice2) return choice2; return NULL; } static void updateSidedefSection(sidedef_t* s, segsection_t section) { surface_t* suf; if(section == SEG_MIDDLE) return; // Not applicable. suf = &s->sections[section]; if(!suf->material /*&& !R_IsSkySurface(&s->sector-> SP_plane(section == SEG_BOTTOM? PLN_FLOOR : PLN_CEILING)-> surface)*/) { Surface_SetMaterial(suf, chooseFixMaterial(s, section)); suf->inFlags |= SUIF_MATERIAL_FIX; } } void R_UpdateLinedefsOfSector(sector_t* sec) { uint i; for(i = 0; i < sec->lineDefCount; ++i) { linedef_t* li = sec->lineDefs[i]; sidedef_t* front, *back; sector_t* frontSec, *backSec; if(!li->L_frontside || !li->L_backside) continue; if(LINE_SELFREF(li)) continue; front = li->L_frontside; back = li->L_backside; frontSec = front->sector; backSec = li->L_backside? back->sector : NULL; /** * Do as in the original Doom if the texture has not been defined - * extend the floor/ceiling to fill the space (unless it is skymasked), * or if there is a midtexture use that instead. */ // Check for missing lowers. if(frontSec->SP_floorheight < backSec->SP_floorheight) updateSidedefSection(front, SEG_BOTTOM); else if(frontSec->SP_floorheight > backSec->SP_floorheight) updateSidedefSection(back, SEG_BOTTOM); // Check for missing uppers. if(backSec->SP_ceilheight < frontSec->SP_ceilheight) updateSidedefSection(front, SEG_TOP); else if(backSec->SP_ceilheight > frontSec->SP_ceilheight) updateSidedefSection(back, SEG_TOP); } } boolean R_UpdatePlane(plane_t* pln, boolean forceUpdate) { boolean changed = false; boolean hasGlow = false; sector_t* sec = pln->sector; // Update the glow properties. hasGlow = false; if(pln->PS_material && ((pln->surface.flags & DDSUF_GLOW) || (pln->PS_material->flags & MATF_GLOW))) { material_snapshot_t ms; Material_Prepare(&ms, pln->PS_material, true, NULL); pln->glowRGB[CR] = ms.color[CR]; pln->glowRGB[CG] = ms.color[CG]; pln->glowRGB[CB] = ms.color[CB]; hasGlow = true; changed = true; } if(hasGlow) { pln->glow = 4; // Default height factor is 4 } else { pln->glowRGB[CR] = pln->glowRGB[CG] = pln->glowRGB[CB] = 0; pln->glow = 0; } // Geometry change? if(forceUpdate || pln->height != pln->oldHeight[1]) { uint i; subsector_t** ssecp; sidedef_t* front = NULL, *back = NULL; // Check if there are any camera players in this sector. If their // height is now above the ceiling/below the floor they are now in // the void. for(i = 0; i < DDMAXPLAYERS; ++i) { player_t* plr = &ddPlayers[i]; ddplayer_t* ddpl = &plr->shared; if(!ddpl->inGame || !ddpl->mo || !ddpl->mo->subsector) continue; //// \fixme $nplanes if((ddpl->flags & DDPF_CAMERA) && ddpl->mo->subsector->sector == sec && (ddpl->mo->pos[VZ] > sec->SP_ceilheight || ddpl->mo->pos[VZ] < sec->SP_floorheight)) { ddpl->inVoid = true; } } // Update the z position of the degenmobj for this plane. pln->soundOrg.pos[VZ] = pln->height; // Inform the shadow bias of changed geometry. ssecp = sec->ssectors; while(*ssecp) { subsector_t* ssec = *ssecp; seg_t** segp = ssec->segs; while(*segp) { seg_t* seg = *segp; if(seg->lineDef) { for(i = 0; i < 3; ++i) SB_SurfaceMoved(seg->bsuf[i]); } *segp++; } SB_SurfaceMoved(ssec->bsuf[pln->planeID]); *ssecp++; } // We need the decorations updated. Surface_Update(&pln->surface); changed = true; } return changed; } #if 0 /** * Stub. */ boolean R_UpdateSubSector(subsector_t* ssec, boolean forceUpdate) { return false; // Not changed. } #endif boolean R_UpdateSector(sector_t* sec, boolean forceUpdate) { uint i; boolean changed = false, planeChanged = false; // Check if there are any lightlevel or color changes. if(forceUpdate || (sec->lightLevel != sec->oldLightLevel || sec->rgb[0] != sec->oldRGB[0] || sec->rgb[1] != sec->oldRGB[1] || sec->rgb[2] != sec->oldRGB[2])) { sec->frameFlags |= SIF_LIGHT_CHANGED; sec->oldLightLevel = sec->lightLevel; memcpy(sec->oldRGB, sec->rgb, sizeof(sec->oldRGB)); LG_SectorChanged(sec); changed = true; } else { sec->frameFlags &= ~SIF_LIGHT_CHANGED; } // For each plane. for(i = 0; i < sec->planeCount; ++i) { if(R_UpdatePlane(sec->planes[i], forceUpdate)) { planeChanged = true; } } if(planeChanged) { sec->soundOrg.pos[VZ] = (sec->SP_ceilheight - sec->SP_floorheight) / 2; R_UpdateLinedefsOfSector(sec); S_CalcSectorReverb(sec); changed = true; } return planeChanged; } /** * Stub. */ boolean R_UpdateLinedef(linedef_t* line, boolean forceUpdate) { return false; // Not changed. } /** * Stub. */ boolean R_UpdateSidedef(sidedef_t* side, boolean forceUpdate) { return false; // Not changed. } /** * Stub. */ boolean R_UpdateSurface(surface_t* suf, boolean forceUpdate) { return false; // Not changed. } /** * All links will be updated every frame (sectorheights may change at * any time without notice). */ void R_UpdatePlanes(void) { // Nothing to do. } /** * The DOOM lighting model applies distance attenuation to sector light * levels. * * @param distToViewer Distance from the viewer to this object. * @param lightLevel Sector lightLevel at this object's origin. * @return The specified lightLevel plus any attentuation. */ float R_DistAttenuateLightLevel(float distToViewer, float lightLevel) { if(distToViewer > 0 && rendLightDistanceAttentuation > 0) { float real, minimum; real = lightLevel - (distToViewer - 32) / rendLightDistanceAttentuation * (1 - lightLevel); minimum = lightLevel * lightLevel + (lightLevel - .63f) * .5f; if(real < minimum) real = minimum; // Clamp it. return real; } return lightLevel; } /** * The DOOM lighting model applies a light level delta to everything when * e.g. the player shoots. * * @return Calculated delta. */ float R_ExtraLightDelta(void) { return extraLightDelta; } /** * @return @c > 0, if the sector lightlevel passes the * limit condition. */ float R_CheckSectorLight(float lightlevel, float min, float max) { // Has a limit been set? if(min == max) return 1; // Apply adaptation Rend_ApplyLightAdaptation(&lightlevel); return MINMAX_OF(0, (lightlevel - min) / (float) (max - min), 1); } /** * Sector light color may be affected by the sky light color. */ const float *R_GetSectorLightColor(const sector_t *sector) { if(!rendSkyLight || noSkyColorGiven) return sector->rgb; // The sector's real color. if(!R_SectorContainsSkySurfaces(sector)) { sector_t *src; // A dominant light source affects this sector? src = sector->lightSource; if(src && src->lightLevel >= sector->lightLevel) { // The color shines here, too. return R_GetSectorLightColor(src); } return sector->rgb; /* // Return the sector's real color (balanced against sky's). if(skyColorBalance >= 1) { return sector->rgb; } else { int c; for(c = 0; c < 3; ++c) balancedRGB[c] = sector->rgb[c] * skyColorBalance; return balancedRGB; } */ } // Return the sky color. return skyColorRGB; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dgl_draw.c0000644000175000017500000003004511357170242022662 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dgl_draw.c: Drawing Operations and Vertex Arrays. * * Get OpenGL header files from: * http://oss.sgi.com/projects/ogl-sample/ */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define MAX_ARRAYS (2 + MAX_TEX_UNITS) // TYPES ------------------------------------------------------------------- typedef struct array_s { boolean enabled; void* data; } array_t; // FUNCTION PROTOTYPES ----------------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int polyCounter; // Triangle counter, really. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static array_t arrays[MAX_ARRAYS]; static int primLevel = 0; static DGLuint inList = 0; #ifdef _DEBUG static boolean inPrim = false; #endif // CODE -------------------------------------------------------------------- void GL_InitArrays(void) { double version = strtod((const char*) glGetString(GL_VERSION), NULL); // If the driver's OpenGL version is older than 1.3, disable arrays // by default. GL_state.noArrays = (version < 1.3); // Override the automatic selection? if(ArgExists("-vtxar")) GL_state.noArrays = false; if(ArgExists("-novtxar")) GL_state.noArrays = true; if(!GL_state.noArrays) return; memset(arrays, 0, sizeof(arrays)); } boolean GL_NewList(DGLuint list, int mode) { // We enter a New/End list section. #ifdef _DEBUG if(inList) Con_Error("OpenGL: already inList"); Sys_CheckGLError(); #endif if(list) { // A specific list id was requested. Is it free? if(glIsList(list)) { #if _DEBUG Con_Error("OpenGL: List %u already in use.", (unsigned int) list); #endif return false; } } else { // Just get a new list id, it doesn't matter. list = glGenLists(1); } glNewList(list, mode == DGL_COMPILE? GL_COMPILE : GL_COMPILE_AND_EXECUTE); inList = list; return true; } DGLuint GL_EndList(void) { DGLuint currentList = inList; glEndList(); #ifdef _DEBUG inList = 0; Sys_CheckGLError(); #endif return currentList; } void GL_CallList(DGLuint list) { if(!list) return; // We do not consider zero a valid list id. glCallList(list); } void GL_DeleteLists(DGLuint list, int range) { glDeleteLists(list, range); } void GL_EnableArrays(int vertices, int colors, int coords) { int i; if(vertices) { if(GL_state.noArrays) arrays[AR_VERTEX].enabled = true; else glEnableClientState(GL_VERTEX_ARRAY); } if(colors) { if(GL_state.noArrays) arrays[AR_COLOR].enabled = true; else glEnableClientState(GL_COLOR_ARRAY); } for(i = 0; i < GL_state.maxTexUnits && i < MAX_TEX_UNITS; i++) { if(coords & (1 << i)) { if(GL_state.noArrays) { arrays[AR_TEXCOORD0 + i].enabled = true; } else { #ifndef UNIX if(glClientActiveTextureARB) #endif glClientActiveTextureARB(GL_TEXTURE0 + i); glEnableClientState(GL_TEXTURE_COORD_ARRAY); } } } #ifdef _DEBUG Sys_CheckGLError(); #endif } void GL_DisableArrays(int vertices, int colors, int coords) { int i; if(vertices) { if(GL_state.noArrays) arrays[AR_VERTEX].enabled = false; else glDisableClientState(GL_VERTEX_ARRAY); } if(colors) { if(GL_state.noArrays) arrays[AR_COLOR].enabled = false; else glDisableClientState(GL_COLOR_ARRAY); } for(i = 0; i < GL_state.maxTexUnits && i < MAX_TEX_UNITS; i++) { if(coords & (1 << i)) { if(GL_state.noArrays) { arrays[AR_TEXCOORD0 + i].enabled = false; } else { #ifndef UNIX if(glClientActiveTextureARB) #endif glClientActiveTextureARB(GL_TEXTURE0 + i); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, NULL); } } } #ifdef _DEBUG Sys_CheckGLError(); #endif } /** * Enable, set and optionally lock all enabled arrays. */ void GL_Arrays(void *vertices, void *colors, int numCoords, void **coords, int lock) { int i; if(vertices) { if(GL_state.noArrays) { arrays[AR_VERTEX].enabled = true; arrays[AR_VERTEX].data = vertices; } else { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(3, GL_FLOAT, 16, vertices); } } if(colors) { if(GL_state.noArrays) { arrays[AR_COLOR].enabled = true; arrays[AR_COLOR].data = colors; } else { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(4, GL_UNSIGNED_BYTE, 0, colors); } } for(i = 0; i < numCoords && i < MAX_TEX_UNITS; ++i) { if(coords[i]) { if(GL_state.noArrays) { arrays[AR_TEXCOORD0 + i].enabled = true; arrays[AR_TEXCOORD0 + i].data = coords[i]; } else { #ifndef UNIX if(glClientActiveTextureARB) #endif glClientActiveTextureARB(GL_TEXTURE0 + i); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, coords[i]); } } } #ifndef UNIX if(glLockArraysEXT) #endif if(!GL_state.noArrays && lock > 0) { // 'lock' is the number of vertices to lock. glLockArraysEXT(0, lock); } #ifdef _DEBUG Sys_CheckGLError(); #endif } void GL_UnlockArrays(void) { if(!GL_state.noArrays) { #ifndef UNIX if(glUnlockArraysEXT) #endif glUnlockArraysEXT(); } #ifdef _DEBUG Sys_CheckGLError(); #endif } void GL_ArrayElement(int index) { if(!GL_state.noArrays) { glArrayElement(index); } else { int i; for(i = 0; i < GL_state.maxTexUnits && i < MAX_TEX_UNITS; ++i) { if(arrays[AR_TEXCOORD0 + i].enabled) { glMultiTexCoord2fvARB(GL_TEXTURE0 + i, ((dgl_texcoord_t *) arrays[AR_TEXCOORD0 + i].data)[index].st); } } if(arrays[AR_COLOR].enabled) glColor4ubv(((dgl_color_t *) arrays[AR_COLOR].data)[index].rgba); if(arrays[AR_VERTEX].enabled) glVertex3fv(((dgl_vertex_t *) arrays[AR_VERTEX].data)[index].xyz); } } void GL_DrawElements(dglprimtype_t type, int count, const uint *indices) { GLenum primType = (type == DGL_TRIANGLE_FAN ? GL_TRIANGLE_FAN : type == DGL_TRIANGLE_STRIP ? GL_TRIANGLE_STRIP : GL_TRIANGLES); if(!GL_state.noArrays) { glDrawElements(primType, count, GL_UNSIGNED_INT, indices); } else { int i; glBegin(primType); for(i = 0; i < count; ++i) { GL_ArrayElement(indices[i]); } glEnd(); } #ifdef _DEBUG Sys_CheckGLError(); #endif } void DGL_Color3ub(DGLubyte r, DGLubyte g, DGLubyte b) { glColor3ub(r, g, b); } void DGL_Color3ubv(const DGLubyte* vec) { glColor3ubv(vec); } void DGL_Color4ub(DGLubyte r, DGLubyte g, DGLubyte b, DGLubyte a) { glColor4ub(r, g, b, a); } void DGL_Color4ubv(const DGLubyte* vec) { glColor4ubv(vec); } void DGL_Color3f(float r, float g, float b) { glColor3f(r, g, b); } void DGL_Color3fv(const float* vec) { glColor3fv(vec); } void DGL_Color4f(float r, float g, float b, float a) { glColor4f(r, g, b, a); } void DGL_Color4fv(const float* vec) { glColor4fv(vec); } void DGL_TexCoord2f(byte target, float s, float t) { if(target == 0) glTexCoord2f(s, t); else glMultiTexCoord2fARB(GL_TEXTURE0 + target, s, t); } void DGL_TexCoord2fv(byte target, float* vec) { if(target == 0) glTexCoord2fv(vec); else glMultiTexCoord2fvARB(GL_TEXTURE0 + target, vec); } void DGL_Vertex2f(float x, float y) { glVertex2f(x, y); } void DGL_Vertex2fv(const float* vec) { glVertex2fv(vec); } void DGL_Vertex3f(float x, float y, float z) { glVertex3f(x, y, z); } void DGL_Vertex3fv(const float* vec) { glVertex3fv(vec); } void DGL_Vertices2ftv(int num, const dgl_ft2vertex_t* vec) { for(; num > 0; num--, vec++) { glTexCoord2fv(vec->tex); glVertex2fv(vec->pos); } } void DGL_Vertices3ftv(int num, const dgl_ft3vertex_t* vec) { for(; num > 0; num--, vec++) { glTexCoord2fv(vec->tex); glVertex3fv(vec->pos); } } void DGL_Vertices3fctv(int num, const dgl_fct3vertex_t* vec) { for(; num > 0; num--, vec++) { glColor4fv(vec->color); glTexCoord2fv(vec->tex); glVertex3fv(vec->pos); } } void DGL_Begin(dglprimtype_t mode) { // We enter a Begin/End section. primLevel++; #ifdef _DEBUG if(inPrim) Con_Error("OpenGL: already inPrim"); inPrim = true; Sys_CheckGLError(); #endif glBegin(mode == DGL_POINTS ? GL_POINTS : mode == DGL_LINES ? GL_LINES : mode == DGL_TRIANGLES ? GL_TRIANGLES : mode == DGL_TRIANGLE_FAN ? GL_TRIANGLE_FAN : mode == DGL_TRIANGLE_STRIP ? GL_TRIANGLE_STRIP : mode == DGL_QUAD_STRIP ? GL_QUAD_STRIP : GL_QUADS); } void DGL_End(void) { if(primLevel > 0) { primLevel--; glEnd(); } #ifdef _DEBUG inPrim = false; Sys_CheckGLError(); #endif } boolean DGL_NewList(DGLuint list, int mode) { return GL_NewList(list, mode); } DGLuint DGL_EndList(void) { return GL_EndList(); } void DGL_CallList(DGLuint list) { GL_CallList(list); } void DGL_DeleteLists(DGLuint list, int range) { GL_DeleteLists(list, range); } void DGL_DrawLine(float x1, float y1, float x2, float y2, float r, float g, float b, float a) { GL_DrawLine(x1, y1, x2, y2, r, g, b, a); } void DGL_DrawRect(float x, float y, float w, float h, float r, float g, float b, float a) { GL_DrawRect(x, y, w, h, r, g, b, a); } void DGL_DrawRectTiled(float x, float y, float w, float h, int tw, int th) { GL_DrawRectTiled(x, y, w, h, tw, th); } void DGL_DrawCutRectTiled(float x, float y, float w, float h, int tw, int th, int txoff, int tyoff, float cx, float cy, float cw, float ch) { GL_DrawCutRectTiled(x, y, w, h, tw, th, txoff, tyoff, cx, cy, cw, ch); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_network.c0000644000175000017500000012667711357170242023507 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_network.c: Low-Level Sockets Networking * * TCP sockets are periodically polled for activity (Net_Update -> * N_Listen). */ // HEADER FILES ------------------------------------------------------------ #ifdef MACOSX # include #else # include #endif #include #include "de_base.h" #include "de_network.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ /** * The randomized transmitted is only used for simulating a poor * network connection. */ #undef TRANSMIT_RANDOMIZER #define RANDOMIZER_DROP_PERCENT 25 #define RANDOMIZER_MAX_DELAY 500 /** * Defining PRINT_PACKETS will cause the UDP transmitter and receiver * to print a message each time they send or receive a packet. */ #undef PRINT_PACKETS #define MAX_NODES 32 #define MAX_DATAGRAM_SIZE 1300 #define DEFAULT_TRANSMISSION_SIZE 4096 // TYPES ------------------------------------------------------------------- /** * Each network node has a send queue. The queue contains a number of * sqpacks. */ typedef struct sqpack_s { struct sqpack_s *next; struct netnode_s *node; UDPpacket *packet; #ifdef TRANSMIT_RANDOMIZER // The packet won't be sent until this time. uint dueTime; #endif } sqpack_t; /** * On serverside, each client has its own network node. A node * represents the TCP connection between the client and the server. On * clientside, the node zero is used always. */ typedef struct netnode_s { TCPsocket sock; char name[128]; // The node is owned by a client in the game. This becomes true // when the client issues the JOIN request. boolean hasJoined; // This is the UDP address that the client listens to. IPaddress addr; // Send queue statistics. long mutex; uint numWaiting; uint bytesWaiting; } netnode_t; typedef struct sendqueue_s { long waiting; long mutex; sqpack_t *first, *last; boolean online; // Set to false to make transmitter stop. } sendqueue_t; typedef struct foundhost_s { boolean valid; serverinfo_t info; IPaddress addr; } foundhost_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void N_IPToString(char *buf, IPaddress *ip); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- size_t maxDatagramSize = MAX_DATAGRAM_SIZE; char *nptIPAddress = ""; int nptIPPort = 0; // This is the port *we* use to communicate. int nptUDPPort = 0; int defaultTCPPort = DEFAULT_TCP_PORT; int defaultUDPPort = DEFAULT_UDP_PORT; // Operating mode of the currently active service provider. boolean netIsActive = false; boolean netServerMode = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static TCPsocket serverSock; static volatile UDPsocket inSock; static Uint16 recvUDPPort; static mutex_t mutexInSock; static netnode_t netNodes[MAX_NODES]; static SDLNet_SocketSet sockSet; static thread_t hTransmitter; static thread_t hReceiver; static sendqueue_t sendQ; static foundhost_t located; static volatile boolean stopReceiver; static byte* transmissionBuffer; static size_t transmissionBufferSize; // CODE -------------------------------------------------------------------- void N_Register(void) { C_VAR_CHARPTR("net-ip-address", &nptIPAddress, 0, 0, 0); C_VAR_INT("net-ip-port", &nptIPPort, CVF_NO_MAX, 0, 0); C_VAR_INT("net-port-control", &nptIPPort, CVF_NO_MAX, 0, 0); C_VAR_INT("net-port-data", &nptUDPPort, CVF_NO_MAX, 0, 0); } /** * Free any packets still waiting in the queue. */ static void N_ClearQueue(sendqueue_t *q) { sqpack_t *pack; while((pack = q->first) != NULL) { q->first = pack->next; SDLNet_FreePacket(pack->packet); M_Free(pack); } } /** * Send the packet using UDP. If the packet is associated with no * node, nothing will be sent because we don't know the destination * address. */ static void N_UDPSend(sqpack_t *pack) { if(!pack->node) return; #ifdef PRINT_PACKETS { char buf[80]; N_IPToString(buf, &pack->packet->address); Con_Message("Send: len=%i to %s\n", pack->packet->len, buf); } #endif if(pack->node->hasJoined) { // Commence sending. SDLNet_UDP_Send(inSock, -1, pack->packet); } // Update the node's counters. Sem_P(pack->node->mutex); pack->node->numWaiting--; pack->node->bytesWaiting -= pack->packet->len; Sem_V(pack->node->mutex); } #ifdef TRANSMIT_RANDOMIZER /** * The randomized version of the UDP transmitter. This can be used to * simulate a real-life connection where UDP packets are received * sometimes in the wrong order or get lost entirely. */ static int C_DECL N_UDPTransmitter(void *parm) { sendqueue_t *q = parm; sqpack_t *pack; uint nowTime = 0; // When using the randomized transmitter, the send queue is always // sorted by the due times. while(q->online) { // If there are packets waiting, see if they should be sent now. Sem_P(q->mutex); nowTime = Sys_GetRealTime(); while((pack = q->first) != NULL) { if(pack->dueTime > nowTime) { // Too early. break; } // Remove the packet from the queue. q->first = pack->next; N_UDPSend(pack); // Now that the packet has been sent, we can discard the data. SDLNet_FreePacket(pack->packet); M_Free(pack); } Sem_V(q->mutex); // Sleep for a short while before starting another loop. Sys_Sleep(2); } N_ClearQueue(q); return 0; } #else /* !TRANSMIT_RANDOMIZER */ /** * A UDP transmitter thread takes messages off a network node's send * queue and sends them one by one. On serverside, each client has its * own transmitter thread. * * 'parm' is a pointer to the network node of this transmitter. */ static int C_DECL N_UDPTransmitter(void *parm) { sendqueue_t *q = parm; sqpack_t *pack; while(q->online) { // We will wait until there are messages to send. The // semaphore is incremented when a new message is added to the // queue. Waiting for this semaphore causes us to sleep // until there are messages to send. Sem_P(q->waiting); // Lock the send queue. Sem_P(q->mutex); // There should be a message waiting. if(!q->online || !q->first) { Sem_V(q->mutex); continue; } // Extract the next message from the FIFO queue. pack = q->first; q->first = q->first->next; if(!q->first) q->last = NULL; // Release the send queue. Sem_V(q->mutex); N_UDPSend(pack); // Now that the packet has been sent, we can discard the data. SDLNet_FreePacket(pack->packet); M_Free(pack); } // Free any packets still waiting in the queue. N_ClearQueue(q); return 0; } #endif /** * The UDP receiver thread waits for UDP packets and places them into * the incoming message buffer. The UDP receiver is started when the * TCP/IP service is initialized. The thread is stopped when the * service is shut down. */ static int C_DECL N_UDPReceiver(void *parm) { SDLNet_SocketSet set; UDPpacket *packet = NULL; // Put the UDP socket in our socket set so we can wait for it. set = SDLNet_AllocSocketSet(1); SDLNet_UDP_AddSocket(set, inSock); while(!stopReceiver) { // Most of the time we will be sleeping here, waiting for // incoming packets. while(SDLNet_CheckSockets(set, 250) > 0) { // There is activity on the socket. Allocate a new packet // to store the data into. The packet will be released later, // in N_ReturnBuffer. if(!packet) { // Allocate a new packet. packet = SDLNet_AllocPacket((int) maxDatagramSize); } // The mutex will prevent problems when new channels are // bound to the socket. Sys_Lock(mutexInSock); if(SDLNet_UDP_Recv(inSock, packet) > 0) { netmessage_t *msg = NULL; Sys_Unlock(mutexInSock); #ifdef PRINT_PACKETS { char buf[80]; N_IPToString(buf, &packet->address); Con_Message("Recv: ch=%i len=%i %s\n", packet->channel, packet->len, buf); } #endif // If we don't know the sender, discard the packet. if(packet->channel < 0) continue; // Successfully received a packet. msg = (netmessage_t *) M_Calloc(sizeof(netmessage_t)); msg->sender = packet->channel; msg->data = packet->data; msg->size = packet->len; msg->handle = packet; // The message queue will handle the message from now on. N_PostMessage(msg); // This packet has now been used. packet = NULL; } else { Sys_Unlock(mutexInSock); continue; } } } if(packet) SDLNet_FreePacket(packet); SDLNet_FreeSocketSet(set); return 0; } /** * Free a message buffer. */ void N_ReturnBuffer(void *handle) { if(!handle) return; SDLNet_FreePacket(handle); } /** * Read a packet from the TCP connection and put it in the incoming * packet queue. This function blocks until the entire packet has * been read, so large packets should be avoided during normal * gameplay. * * Returns true if a packet was successfully received. */ boolean N_ReceiveReliably(nodeid_t from) { ushort size = 0; TCPsocket sock = netNodes[from].sock; UDPpacket *packet = NULL; int bytes = 0; boolean error, read; // \todo What if we get one byte? How come we are here if there's nothing to receive? if((bytes = SDLNet_TCP_Recv(sock, &size, 2)) != 2) { int number = errno; Con_Message("N_ReceiveReliably: Packet header was truncated. Got %i bytes.\n", bytes); Con_Message(" Error: %s (%s)\n", SDLNet_GetError(), strerror(number)); return false; } size = SHORT(size); // Read the entire packet's data. packet = SDLNet_AllocPacket(size); bytes = 0; read = false; error = false; while(!read) { int received = SDLNet_TCP_Recv(sock, packet->data + bytes, size); if(received == -1) { SDLNet_FreePacket(packet); Con_Message("N_ReceiveReliably: Error during TCP recv.\n %s (%s)", SDLNet_GetError(), strerror(errno)); error = true; read = true; } bytes += received; if(!(bytes < size)) read = true; } if(error) return false; // Post the received message. { netmessage_t *msg = M_Calloc(sizeof(netmessage_t)); msg->sender = from; msg->data = packet->data; msg->size = size; msg->handle = packet; #ifdef _DEBUG VERBOSE2(Con_Message("N_ReceiveReliably: Posting message, from=%i, size=%i\n", from, size)); #endif // The message queue will handle the message from now on. N_PostMessage(msg); } return true; } /** * Send the data buffer over the control link, which is a TCP * connection. */ void N_SendDataBufferReliably(void *data, size_t size, nodeid_t destination) { int result; netnode_t *node = &netNodes[destination]; if(size == 0 || !node->sock || !node->hasJoined) return; if(size > DDMAXSHORT) { Con_Error("N_SendDataBufferReliably: Trying to send a too large data " "buffer.\n Attempted size is %lu bytes.\n", (unsigned long) size); } // Compose the entire message in the transmission buffer. if(transmissionBufferSize < size + 2) { transmissionBufferSize = size + 2; transmissionBuffer = M_Realloc(transmissionBuffer, size + 2); } if(size > sizeof(short)) Con_Error("N_SendDataBufferReliably: Tried to send %lu bytes " "(max pkt size %lu).\n", (unsigned long) size, (unsigned long) sizeof(short)); { short packetSize = SHORT(size); memcpy(transmissionBuffer, &packetSize, 2); } memcpy(transmissionBuffer + 2, data, size); result = SDLNet_TCP_Send(node->sock, transmissionBuffer, (int) size + 2); #ifdef _DEBUG VERBOSE2( Con_Message("N_SendDataBufferReliably: Sent %ul bytes, result=%ul\n", (unsigned long) (size + 2), result) ); #endif if(result != size + 2) perror("Socket error"); /* result = SDLNet_TCP_Send(node->sock, data, (int) size); #ifdef _DEBUG Con_Message("N_SendDataBufferReliably: Sent data, result=%i\n", result); if(result != size) perror("System error"); #endif*/ } /** * Send the buffer to the destination. For clients, the server is the only * possible destination (doesn't depend on the value of 'destination'). */ void N_SendDataBuffer(void *data, size_t size, nodeid_t destination) { sqpack_t *pack; UDPpacket *p; netnode_t *node; // If the send queue is not active, we can't send anything. if(!sendQ.online) return; #ifdef TRANSMIT_RANDOMIZER // There is a chance that the packet is dropped. if(RNG_RandFloat() < RANDOMIZER_DROP_PERCENT / 100.0) { VERBOSE( Con_Message("N_SendDataBuffer: Randomizer dropped packet to %i " "(%lu bytes).\n", destination, (unsigned long) size) ); return; } #endif if(size > maxDatagramSize) { Con_Error("N_SendDataBuffer: Too large packet (%lu), risk of " "fragmentation (MTU=%lu).\n", (unsigned long) size, (unsigned long) maxDatagramSize); } // This memory is freed after the packet is sent. pack = M_Malloc(sizeof(sqpack_t)); p = pack->packet = SDLNet_AllocPacket((int) size); // The destination node. pack->node = node = netNodes + destination; // Init the packet's data. p->channel = -1; memcpy(p->data, data, (int) size); p->len = (int) size; memcpy(&p->address, &node->addr, sizeof(p->address)); #ifdef TRANSMIT_RANDOMIZER pack->dueTime = Sys_GetRealTime() + RNG_RandFloat() * RANDOMIZER_MAX_DELAY; #endif // Add the packet to the send queue. Sem_P(sendQ.mutex); #ifndef TRANSMIT_RANDOMIZER if(!sendQ.first) { sendQ.first = sendQ.last = pack; } else { sendQ.last->next = pack; sendQ.last = pack; } pack->next = NULL; #else // Insertion sort. if(sendQ.first) { // Does the new packet come before all others? if(pack->dueTime < sendQ.first->dueTime) { pack->next = sendQ.first; sendQ.first = pack; } else { // Find the packet after which the new packet belongs. sqpack_t *i = sendQ.first; for(; i; i = i->next) { if(!i->next || i->next->dueTime >= pack->dueTime) { // Add after this one. pack->next = i->next; i->next = pack; break; } } } } else { sendQ.first = pack; pack->next = NULL; } #endif Sem_V(sendQ.mutex); // Increment the statistics. Sem_P(node->mutex); node->numWaiting++; node->bytesWaiting += (uint) size; Sem_V(node->mutex); // Signal the transmitter to start working. Sem_V(sendQ.waiting); } /** * @return The number of messages waiting in the player's send * queue. */ uint N_GetSendQueueCount(int player) { netnode_t *node = netNodes + player; uint count; Sem_P(node->mutex); count = node->numWaiting; Sem_V(node->mutex); return count; } /** * @return The number of bytes waiting in the player's send * queue. */ uint N_GetSendQueueSize(int player) { netnode_t *node = netNodes + player; uint bytes; Sem_P(node->mutex); bytes = node->bytesWaiting; Sem_V(node->mutex); return bytes; } /** * Blocks until all the send queues have been emptied. */ void N_FlushOutgoing(void) { int i; boolean allClear = false; while(!allClear) { allClear = true; for(i = 0; i < DDMAXPLAYERS; ++i) if(netNodes[i].hasJoined && N_GetSendQueueCount(i)) allClear = false; Sys_Sleep(5); } } /** * Initialize the transmitter thread and the send queue. */ static void N_StartTransmitter(sendqueue_t *q) { q->online = true; q->waiting = Sem_Create(0); q->mutex = Sem_Create(1); q->first = NULL; q->last = NULL; hTransmitter = Sys_StartThread(N_UDPTransmitter, q); } /** * Blocks until the transmitter thread has been exited. */ static void N_StopTransmitter(sendqueue_t *q) { uint i; if(!hTransmitter) return; // Tell the transmitter to stop sending. q->online = false; // Increment the semaphore without adding a new message: this'll // make the transmitter "run dry." for(i = 0; i < 10; ++i) Sem_V(q->waiting); // Wait until the transmitter thread finishes. Sys_WaitThread(hTransmitter); hTransmitter = NULL; // Destroy the semaphores. Sem_Destroy(q->waiting); Sem_Destroy(q->mutex); } /** * Start the UDP receiver thread. */ static void N_StartReceiver(void) { stopReceiver = false; mutexInSock = Sys_CreateMutex("UDPIncomingMutex"); hReceiver = Sys_StartThread(N_UDPReceiver, NULL); } /** * Blocks until the UDP receiver thread has exited. */ static void N_StopReceiver(void) { // Wait for the receiver thread the stop. stopReceiver = true; Sys_WaitThread(hReceiver); hReceiver = 0; // Close the incoming UDP socket. SDLNet_UDP_Close(inSock); inSock = NULL; Sys_DestroyMutex(mutexInSock); mutexInSock = 0; } /** * Bind or unbind the address to/from the incoming UDP socket. When * the address is bound, packets from it will be accepted. */ void N_BindIncoming(IPaddress *addr, nodeid_t id) { if(!inSock) return; Sys_Lock(mutexInSock); if(addr) { SDLNet_UDP_Bind(inSock, id, addr); } else { SDLNet_UDP_Unbind(inSock, id); } Sys_Unlock(mutexInSock); } /** * Initialize the low-level network subsystem. This is called always * during startup (via Sys_Init()). */ void N_SystemInit(void) { // The MTU can be customized. if(ArgCheckWith("-mtu", 1)) { maxDatagramSize = (size_t) strtol(ArgNext(), NULL, 0); Con_Message("N_SystemInit: Custom MTU: %lu bytes.\n", (unsigned long) maxDatagramSize); } // Allocate the transmission buffer. transmissionBufferSize = DEFAULT_TRANSMISSION_SIZE; transmissionBuffer = M_Malloc(transmissionBufferSize); } /** * Shut down the low-level network interface. Called during engine * shutdown (not before). */ void N_SystemShutdown(void) { M_Free(transmissionBuffer); transmissionBuffer = NULL; transmissionBufferSize = 0; N_ShutdownService(); } /** * Convert an IPaddress to a string. */ void N_IPToString(char *buf, IPaddress *ip) { uint host = SDLNet_Read32(&ip->host); sprintf(buf, "%i.%i.%i.%i:%i", host >> 24, (host >> 16) & 0xff, (host >> 8) & 0xff, host & 0xff, SDLNet_Read16(&ip->port)); } /** * Opens an UDP socket. The used port number is returned. If the * socket cannot be opened, 'sock' is set to NULL. 'defaultPort' * should never be zero. */ Uint16 N_OpenUDPSocket(UDPsocket *sock, Uint16 preferPort, Uint16 defaultPort) { Uint16 port = (!preferPort ? defaultPort : preferPort); *sock = NULL; if((*sock = SDLNet_UDP_Open(port)) != NULL) return port; #ifdef _DEBUG Con_Message("N_OpenUDPSocket: Failed to open UDP socket %i.\n", port); Con_Message(" (%s)\n", SDLNet_GetError()); #endif return 0; // Failure! } /** * Initialize the chosen service provider each in server or client * mode. If a service provider has already been initialized, it will * be shut down first. Returns true if successful. */ boolean N_InitService(boolean inServerMode) { IPaddress ip; Uint16 port; if(N_IsAvailable() && netServerMode == inServerMode) { // Nothing to change. return true; } // Get rid of the currently active service provider. N_ShutdownService(); if(!SDLNet_Init()) { VERBOSE(Con_Message("N_InitService: SDLNet_Init OK\n")); } else { Con_Message("N_InitService: SDLNet_Init %s\n", SDLNet_GetError()); } if(inServerMode) { port = (!nptIPPort ? defaultTCPPort : nptIPPort); Con_Message("N_InitService: Listening TCP socket on port %i.\n", port); // Open a listening TCP socket. It will accept client // connections. if(SDLNet_ResolveHost(&ip, NULL, port)) { Con_Message("N_InitService: %s\n", SDLNet_GetError()); return false; } if(!(serverSock = SDLNet_TCP_Open(&ip))) { Con_Message("N_InitService: %s\n", SDLNet_GetError()); return false; } // Allocate a socket set, which we'll use for listening to the // client sockets. if(!(sockSet = SDLNet_AllocSocketSet(MAX_NODES))) { Con_Message("N_InitService: %s\n", SDLNet_GetError()); return false; } } else { // Let's forget about servers found earlier. located.valid = false; } // Open the socket that will be used for UDP communications. recvUDPPort = N_OpenUDPSocket((UDPsocket *) &inSock, nptUDPPort, defaultUDPPort); Con_Message("N_InitService: In/out UDP port %i.\n", recvUDPPort); // Success. netIsActive = true; netServerMode = inServerMode; // Did we fail in opening the UDP port? if(!inSock) { Con_Message("N_InitService: Failed to open in/out UDP port.\n"); Con_Message(" %s\n", SDLNet_GetError()); N_ShutdownService(); return false; } // Start the UDP receiver right away. N_StartReceiver(); // Start the UDP transmitter. N_StartTransmitter(&sendQ); return true; } /** * Shut down the TCP/IP network services. */ void N_ShutdownService(void) { uint i; if(!N_IsAvailable()) return; // Nothing to do. if(netGame) { // We seem to be shutting down while a netGame is running. Con_Execute(CMDS_DDAY, isServer ? "net server close" : "net disconnect", true, false); } // Any queued messages will be destroyed. N_ClearMessages(); // Kill the transmission threads. N_StopTransmitter(&sendQ); N_StopReceiver(); if(netServerMode) { // Close the listening socket. SDLNet_TCP_Close(serverSock); serverSock = NULL; // Clear the client nodes. for(i = 0; i < MAX_NODES; ++i) N_TerminateNode(i); // Free the socket set. SDLNet_FreeSocketSet(sockSet); sockSet = NULL; } else { // Let's forget about servers found earlier. located.valid = false; } SDLNet_Quit(); netIsActive = false; netServerMode = false; } /** * Returns true if the low-level network routines have been initialized * and are expected to be working. */ boolean N_IsAvailable(void) { return netIsActive; } /** * Returns true if the internet is available. */ boolean N_UsingInternet(void) { return netIsActive; } boolean N_GetHostInfo(int index, struct serverinfo_s *info) { if(!located.valid || index != 0) return false; memcpy(info, &located.info, sizeof(*info)); return true; } int N_GetHostCount(void) { return located.valid ? 1 : 0; } const char *N_GetProtocolName(void) { return "TCP/IP"; } /** * Returns the player name associated with the given network node. */ boolean N_GetNodeName(nodeid_t id, char *name) { if(!netNodes[id].sock) { strcpy(name, "-unknown-"); return false; } strcpy(name, netNodes[id].name); return true; } /** * The client is removed from the game immediately. This is used when * the server needs to terminate a client's connection abnormally. */ void N_TerminateNode(nodeid_t id) { netnode_t *node = &netNodes[id]; netevent_t netEvent; sqpack_t *i; if(!node->sock) return; // There is nothing here... if(netServerMode && node->hasJoined) { // This causes a network event. netEvent.type = NE_CLIENT_EXIT; netEvent.id = id; N_NEPost(&netEvent); } // Remove the node from the set of active sockets. SDLNet_TCP_DelSocket(sockSet, node->sock); // Close the socket and forget everything about the node. SDLNet_TCP_Close(node->sock); // Remove the address binding from the incoming UDP socket. This // means we'll reject all packets from the address. N_BindIncoming(NULL, id); // Cancel this node's packets in the send queue by setting their // node pointers to NULL. if(sendQ.first != sendQ.last) { Sem_P(sendQ.mutex); for(i = sendQ.first; i; i = i->next) if(i->node == node) i->node = NULL; Sem_V(sendQ.mutex); } // Clear the node's data. Sem_Destroy(node->mutex); memset(node, 0, sizeof(*node)); } /** * Registers a new TCP socket as a client node. There can only be a * limited number of nodes at a time. This is only used by a server. */ static boolean N_RegisterNewSocket(TCPsocket sock) { uint i; netnode_t *node; boolean found; // Find a free node. for(i = 1, node = netNodes + 1, found = false; i < MAX_NODES && !found; ++i, node++) if(!node->sock) { // This'll do. node->sock = sock; // We don't know the name yet. memset(node->name, 0, sizeof(node->name)); // Add this socket to the set of client sockets. SDLNet_TCP_AddSocket(sockSet, sock); found = true; } return found; } /** * A network node wishes to become a real client. Returns true if we * allow this. */ static boolean N_JoinNode(nodeid_t id, Uint16 port, const char *name) { netnode_t *node; netevent_t netEvent; IPaddress *ip; // If the server is full, attempts to connect are canceled. if(Sv_GetNumConnected() >= svMaxPlayers) return false; node = &netNodes[id]; // The UDP address where we should be sending data. if(!(ip = SDLNet_TCP_GetPeerAddress(node->sock))) { // This is a strange situation... return false; } memcpy(&node->addr, ip, sizeof(IPaddress)); SDLNet_Write16(port, &node->addr.port); if(verbose) { char buf[80]; N_IPToString(buf, &node->addr); Con_Message("N_JoinNode: Node %i listens at %s (UDP).\n", id, buf); } // Convert the network node into a real client node. node->hasJoined = true; // \fixme We should use more discretion with the name. It has // been provided by an untrusted source. strncpy(node->name, name, sizeof(node->name) - 1); // Prepare the transmission stats for the node. node->numWaiting = 0; node->bytesWaiting = 0; node->mutex = Sem_Create(1); // Bind the address to the incoming UDP socket, so we'll recognize // the sender. N_BindIncoming(&node->addr, id); // Inform the higher levels of this occurence. netEvent.type = NE_CLIENT_ENTRY; netEvent.id = id; N_NEPost(&netEvent); return true; } #ifdef LOOK_TIMEOUT // Untested -- may cause memory a segfault. typedef struct socket_timeout_s { TCPsocket sock; int seconds; boolean abort; } socket_timeout_t; /** * Closes the socket specified with parm after SOCKET_TIMEOUT seconds. */ static int C_DECL N_SocketTimeOut(void *parm) { volatile socket_timeout_t* p = parm; timespan_t elapsed = 0; while(elapsed < p->seconds && !p->abort) { // Check periodically for abortion. Sys_Sleep(100); elapsed += .1; } if(!p->abort) { // Time to close the socket. SDLNet_TCP_Close(p->sock); } return 0; } #endif /** * Maybe it would be wisest to run this in a separate thread? */ boolean N_LookForHosts(const char *address, int port) { TCPsocket sock; char buf[256]; ddstring_t *response; boolean isDone; #ifdef LOOK_TIMEOUT socket_timeout_t timeout; void *timeoutThread; #endif // We must be a client. if(!N_IsAvailable() || netServerMode) return false; if(!port) port = DEFAULT_TCP_PORT; // Get rid of previous findings. memset(&located, 0, sizeof(located)); #ifdef LOOK_TIMEOUT memset(&timeout, 0, sizeof(timeout)); #endif // Let's determine the address we will be looking into. SDLNet_ResolveHost(&located.addr, address, port); // I say, anyone there? sock = SDLNet_TCP_Open(&located.addr); if(!sock) { Con_Message("N_LookForHosts: No reply from %s (port %i).\n", address, port); return false; } // Send an INFO query. SDLNet_TCP_Send(sock, "INFO\n", 5); Con_Message("Send INFO query.\n"); #ifdef LOOK_TIMEOUT // Setup a timeout. timeout.seconds = 5; timeoutThread = Sys_StartThread(N_SocketTimeOut, &timeout); #endif // Let's listen to the reply. memset(buf, 0, sizeof(buf)); response = Str_New(); isDone = false; while(!isDone) { int result; if(!strstr(Str_Text(response), "END\n")) { memset(buf, 0, sizeof(buf)); Con_Message("Waiting for response.\n"); result = SDLNet_TCP_Recv(sock, buf, sizeof(buf) - 1); if(result > 0) { Str_Appendf(response, "%s", buf); Con_Message("Append to response: %s.\n", buf); } else // Terminated. { isDone = true; Con_Message("result <= 0 (%i)\n", result); } } else isDone = true; } #ifdef LOOK_TIMEOUT timeout.abort = true; Con_Message("Waiting for timeout thread to return.\n"); Sys_WaitThread(timeoutThread); Con_Message("Timeout thread stopped.\n"); #endif // Close the connection; that was all the information we need. SDLNet_TCP_Close(sock); // Did we receive what we expected to receive? if(strstr(Str_Text(response), "BEGIN\n")) { const char *ch; ddstring_t *line; located.valid = true; // Convert the string into a serverinfo_s. line = Str_New(); ch = Str_Text(response); do { ch = Str_GetLine(line, ch); Sv_StringToInfo(Str_Text(line), &located.info); } while(*ch); Str_Delete(line); Str_Delete(response); // Show the information in the console. Con_Message("%i server%s been found.\n", N_GetHostCount(), N_GetHostCount() != 1 ? "s have" : " has"); Net_PrintServerInfo(0, NULL); Net_PrintServerInfo(0, &located.info); return true; } else { Str_Delete(response); Con_Message("N_LookForHosts: Reply from %s (port %i) was invalid.\n", address, port); return false; } } /** * Connect a client to the server identified with 'index'. We enter * clientside mode during this routine. */ boolean N_Connect(int index) { netnode_t *svNode; foundhost_t *host; char buf[128], *pName; if(!N_IsAvailable() || netServerMode || index != 0) return false; Demo_StopPlayback(); // Call game DLL's NetConnect. gx.NetConnect(true); host = &located; // We'll use node number zero for all communications. svNode = &netNodes[0]; if(!(svNode->sock = SDLNet_TCP_Open(&host->addr))) { N_IPToString(buf, &host->addr); Con_Message("N_Connect: No reply from %s.\n", buf); return false; } memcpy(&svNode->addr, &located.addr, sizeof(IPaddress)); // Connect by issuing: "JOIN (my-udp) (myname)" pName = playerName; if(!pName || !pName[0]) pName = "Anonymous"; sprintf(buf, "JOIN %04x %s\n", recvUDPPort, pName); SDLNet_TCP_Send(svNode->sock, buf, (int) strlen(buf)); VERBOSE(Con_Message("N_Connect: %s", buf)); // What is the reply? memset(buf, 0, sizeof(buf)); if(SDLNet_TCP_Recv(svNode->sock, buf, 64) <= 0 || strncmp(buf, "ENTER ", 6)) { SDLNet_TCP_Close(svNode->sock); memset(svNode, 0, sizeof(svNode)); Con_Message("N_Connect: Server refused connection.\n"); if(buf[0]) Con_Message(" Reply: %s", buf); return false; } VERBOSE(Con_Message(" Server responds: %s", buf)); // The server tells us which UDP port we should send packets to. SDLNet_Write16(strtol(buf + 6, NULL, 16), &svNode->addr.port); // Bind the server's address to our incoming UDP port, so we'll // recognize the packets from the server. N_BindIncoming(&svNode->addr, 0); // Put the server's socket in a socket set so we may listen to it. sockSet = SDLNet_AllocSocketSet(1); SDLNet_TCP_AddSocket(sockSet, svNode->sock); // Clients are allowed to send packets to the server. svNode->hasJoined = true; allowSending = true; handshakeReceived = false; netGame = true; // Allow sending/receiving of packets. isServer = false; isClient = true; // Call game's NetConnect. gx.NetConnect(false); // G'day mate! The client is responsible for beginning the // handshake. Cl_SendHello(); return true; } /** * Disconnect from the server. */ boolean N_Disconnect(void) { netnode_t *svNode; if(!N_IsAvailable()) return false; // Tell the Game that a disconnection is about to happen. if(gx.NetDisconnect) gx.NetDisconnect(true); Net_StopGame(); N_ClearMessages(); // Tell the Game that the disconnection is now complete. if(gx.NetDisconnect) gx.NetDisconnect(false); // This'll prevent the sending of further packets. svNode = &netNodes[0]; svNode->hasJoined = false; N_BindIncoming(NULL, 0); // Close the control connection. This will let the server know // that we are no more. SDLNet_TCP_Close(svNode->sock); SDLNet_FreeSocketSet(sockSet); sockSet = NULL; return true; } boolean N_ServerOpen(void) { if(!N_IsAvailable()) return false; Demo_StopPlayback(); // Let's make sure the correct service provider is initialized // in server mode. if(!N_InitService(true)) { Con_Message("N_ServerOpen: Failed to initialize server mode.\n"); return false; } // The game module may have something that needs doing before we // actually begin. if(gx.NetServerStart) gx.NetServerStart(true); Sv_StartNetGame(); // The game DLL might want to do something now that the // server is started. if(gx.NetServerStart) gx.NetServerStart(false); if(masterAware && N_UsingInternet()) { // Let the master server know that we are running a public server. N_MasterAnnounceServer(true); } return true; } boolean N_ServerClose(void) { if(!N_IsAvailable()) return false; if(masterAware && N_UsingInternet()) { // Bye-bye, master server. N_MAClear(); N_MasterAnnounceServer(false); } if(gx.NetServerStop) gx.NetServerStop(true); Net_StopGame(); // Exit server mode. N_InitService(false); if(gx.NetServerStop) gx.NetServerStop(false); return true; } /** * Validate and process the command, which has been sent by a remote * agent. Anyone is free to connect to a server using telnet and issue * queries. * * If the command is invalid, the node is immediately closed. We don't * have time to fool around with badly behaving clients. */ static boolean N_DoNodeCommand(nodeid_t node, const char *input, int length) { char command[80], *ch, buf[256]; const char *in; TCPsocket sock = netNodes[node].sock; serverinfo_t info; ddstring_t msg; Uint16 port; // If the command is too long, it'll be considered invalid. if(length >= 80) { N_TerminateNode(node); return false; } // Make a copy of the command. memset(command, 0, sizeof(command)); for(ch = command, in = input; *in && *in != '\r' && *in != '\n' && in - input < length;) *ch++ = *in++; Con_Message("N_DoNodeCommand: %s\n", command); // Status query? if(!strcmp(command, "INFO")) { int result = 0; Sv_GetInfo(&info); Str_Init(&msg); Str_Appendf(&msg, "BEGIN\n"); Sv_InfoToString(&info, &msg); Str_Appendf(&msg, "END\n"); Con_Message("Sending: %s\n", Str_Text(&msg)); result = SDLNet_TCP_Send(sock, Str_Text(&msg), (int) Str_Length(&msg)); Con_Message("Result = %i\n", result); Str_Free(&msg); } else if(!strncmp(command, "JOIN ", 5) && length > 10) { // Which UDP port does the client use? memset(buf, 0, 5); strncpy(buf, command + 5, 4); port = strtol(buf, &ch, 16); if(*ch || !port) { N_TerminateNode(node); return false; } // Read the client's name and convert the network node into a // real client network node (which has a transmitter). if(N_JoinNode(node, port, command + 10)) { // Successful! Send a reply. sprintf(buf, "ENTER %04x\n", recvUDPPort); SDLNet_TCP_Send(sock, buf, (int) strlen(buf)); } else { // Couldn't join the game, so close the connection. SDLNet_TCP_Send(sock, "BYE\n", 4); N_TerminateNode(node); } } else if(!strcmp(command, "TIME")) { sprintf(buf, "%.3f\n", Sys_GetSeconds()); SDLNet_TCP_Send(sock, buf, (int) strlen(buf)); } else if(!strcmp(command, "BYE")) { // Request for the server to terminate the connection. N_TerminateNode(node); } else { // Too bad, scoundrel! Goodbye. SDLNet_TCP_Send(sock, "Huh?\n", 5); N_TerminateNode(node); return false; } // Everything was OK. return true; } /** * Poll all TCP sockets for activity. Client commands are processed. * The logic ain't very pretty, but hopefully functional. */ void N_Listen(void) { TCPsocket sock; int i, result; char buf[256]; netnode_t *node; if(netServerMode) { // Any incoming connections on the listening socket? // \fixme Include this in the set of sockets? while((sock = SDLNet_TCP_Accept(serverSock)) != NULL) { // A new client is attempting to connect. Let's try to // register the new socket as a network node. if(!N_RegisterNewSocket(sock)) { // There was a failure, close the socket. SDLNet_TCP_Close(sock); } } // Any activity on the client sockets? (Don't wait.) if(SDLNet_CheckSockets(sockSet, 0) > 0) { for(i = 0; i < MAX_NODES; ++i) { node = netNodes + i; // Does this socket have got any activity? if(SDLNet_SocketReady(node->sock)) { if(!node->hasJoined) { result = SDLNet_TCP_Recv(node->sock, buf, sizeof(buf)); if(result <= 0) { // Close this socket & node. VERBOSE2(Con_Message ("N_Listen: Connection closed on " "node %i.\n", i)); N_TerminateNode(i); } else { /** \fixme Read into a buffer, execute when newline * received. * * Process the command; we will need to answer, or * do something else. */ N_DoNodeCommand(i, buf, result); } } else { if(!N_ReceiveReliably(i)) { Con_Message("N_Listen: Connection closed on " "node %i.\n", i); N_TerminateNode(i); } } } } } } else { // Clientside listening. On clientside, the socket set only // includes the server's socket. if(sockSet && SDLNet_CheckSockets(sockSet, 0) > 0) { if(!N_ReceiveReliably(0)) { netevent_t nev; Con_Message("N_Listen: N_ReceiveReliably failed. Terminating!\n"); nev.id = 0; nev.type = NE_END_CONNECTION; N_NEPost(&nev); } } } } /** * Called from "net info". */ void N_PrintInfo(void) { // \todo Print information about send queues, ports, etc. #ifdef TRANSMIT_RANDOMIZER Con_Message("Randomizer enabled: max delay = %i ms, dropping %i%%.\n", RANDOMIZER_MAX_DELAY, RANDOMIZER_DROP_PERCENT); #endif N_PrintBufferInfo(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_bias.c0000644000175000017500000010616711357170242023036 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_bias.c: Light/Shadow Bias * * Calculating macro-scale lighting on the fly. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_edit.h" #include "de_system.h" #include "de_graphics.h" #include "de_render.h" #include "de_refresh.h" #include "de_defs.h" #include "de_misc.h" #include "p_sight.h" #include // MACROS ------------------------------------------------------------------ BEGIN_PROF_TIMERS() PROF_BIAS_UPDATE END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- typedef struct affection_s { float intensities[MAX_BIAS_AFFECTED]; int numFound; biasaffection_t* affected; } affection_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void SB_EvalPoint(float light[4], vertexillum_t* illum, biasaffection_t* affectedSources, const float* point, const float* normal); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int useBias = false; int numSources = 0; uint currentTimeSB; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static source_t sources[MAX_BIAS_LIGHTS]; static int numSourceDelta = 0; static int useSightCheck = true; static float biasMin = .85f; static float biasMax = 1.f; static int doUpdateAffected = true; static float biasIgnoreLimit = .005f; static int lightSpeed = 130; static uint lastChangeOnFrame; /** * BS_EvalPoint uses these, so they must be set before it is called. */ static biastracker_t trackChanged; static biastracker_t trackApplied; static float biasAmount; // Head of the biassurface list for the current map. static biassurface_t* surfaces = NULL; static zblockset_t* biasSurfaceBlockSet = NULL; // CODE -------------------------------------------------------------------- /** * Register console variables for Shadow Bias. */ void SB_Register(void) { C_VAR_INT("rend-bias", &useBias, 0, 0, 1); C_VAR_FLOAT("rend-bias-min", &biasMin, 0, 0, 1); C_VAR_FLOAT("rend-bias-max", &biasMax, 0, 0, 1); C_VAR_INT("rend-bias-lightspeed", &lightSpeed, 0, 0, 5000); // Development variables. C_VAR_INT("rend-dev-bias-sight", &useSightCheck, CVF_NO_ARCHIVE, 0, 1); C_VAR_INT("rend-dev-bias-affected", &doUpdateAffected, CVF_NO_ARCHIVE, 0, 1); /* C_VAR_INT("rend-dev-bias-solo", &editSelector, CVF_NO_ARCHIVE, -1, 255);*/ } static __inline biassurface_t* allocBiasSurface(void) { if(biasSurfaceBlockSet) { // Use the block allocator. biassurface_t* bsuf = Z_BlockNewElement(biasSurfaceBlockSet); memset(bsuf, 0, sizeof(*bsuf)); return bsuf; } return M_Calloc(sizeof(biassurface_t)); } static __inline void freeBiasSurface(biassurface_t* bsuf) { if(biasSurfaceBlockSet) { // Ignore, it'll be free'd along with the block allocator. return; } M_Free(bsuf); } biassurface_t* SB_CreateSurface(void) { biassurface_t* bsuf = allocBiasSurface(); // Link it in to the global list. bsuf->next = surfaces; surfaces = bsuf; return bsuf; } void SB_DestroySurface(biassurface_t* bsuf) { if(!bsuf) return; // Unlink this surface from the global list. if(surfaces) { if(bsuf == surfaces) { surfaces = surfaces->next; } else if(surfaces->next) { biassurface_t* p = surfaces->next, *last = surfaces; do { if(p == bsuf) { last->next = p->next; break; } last = p; p = p->next; } while(p); } } Z_Free(bsuf->illum); Z_Free(bsuf); } /** * Creates a new bias light source and sets the appropriate properties to * the values of the passed parameters. The id of the new light source is * returned unless there are no free sources available. * * @param x X coordinate of the new light. * @param y Y coordinate of the new light. * @param z Z coordinate of the new light. * @param size Size (strength) of the new light. * @param minLight Lower sector light level limit. * @param maxLight Upper sector light level limit. * @param rgb Ptr to float[3], the color for the new light. * * @return The id of the newly created bias light source else -1. */ int SB_NewSourceAt(float x, float y, float z, float size, float minLight, float maxLight, float* rgb) { source_t* src; if(numSources == MAX_BIAS_LIGHTS) return -1; src = &sources[numSources++]; // New lights are automatically locked. src->flags = BLF_CHANGED | BLF_LOCKED; src->pos[VX] = x; src->pos[VY] = y; src->pos[VZ] = z; SB_SetColor(src->color,rgb); src->primaryIntensity = src->intensity = size; src->sectorLevel[0] = minLight; src->sectorLevel[1] = maxLight; // This'll enforce an update (although the vertices are also // STILL_UNSEEN). src->lastUpdateTime = 0; return numSources; // == index + 1; } /** * Same as above really but for updating an existing source. */ void SB_UpdateSource(int which, float x, float y, float z, float size, float minLight, float maxLight, float *rgb) { source_t* src; if(which < 0 || which >= numSources) return; src = &sources[which]; // Position change? src->pos[VX] = x; src->pos[VY] = y; src->pos[VZ] = z; SB_SetColor(src->color, rgb); src->primaryIntensity = src->intensity = size; src->sectorLevel[0] = minLight; src->sectorLevel[1] = maxLight; } /** * @return Ptr to the bias light source for the given id. */ source_t* SB_GetSource(int which) { return &sources[which]; } /** * Convert bias light source ptr to index. */ int SB_ToIndex(source_t* source) { if(!source) return -1; else return (source - sources); } /** * Removes the specified bias light source from the map. * * @param which The id of the bias light source to be deleted. */ void SB_Delete(int which) { int i; if(which < 0 || which >= numSources) return; // Very odd... // Do a memory move. for(i = which; i < numSources; ++i) sources[i].flags |= BLF_CHANGED; if(which < numSources) memmove(&sources[which], &sources[which + 1], sizeof(source_t) * (numSources - which - 1)); sources[numSources - 1].intensity = 0; // Will be one fewer very soon. numSourceDelta--; } /** * Removes ALL bias light sources on the map. */ void SB_Clear(void) { while(numSources-- > 0) sources[numSources].flags |= BLF_CHANGED; numSources = 0; } /** * Initializes the bias lights according to the loaded Light * definitions. */ void SB_InitForMap(const char* uniqueID) { uint startTime = Sys_GetRealTime(); int i; ded_light_t* def; // Start with no sources whatsoever. numSources = 0; if(biasSurfaceBlockSet) Z_BlockDestroy(biasSurfaceBlockSet); biasSurfaceBlockSet = Z_BlockCreate(sizeof(biassurface_t), 512, PU_STATIC); surfaces = NULL; // Check all the loaded Light definitions for any matches. for(i = 0; i < defs.count.lights.num; ++i) { def = &defs.lights[i]; if(def->state[0] || stricmp(uniqueID, def->uniqueMapID)) continue; if(SB_NewSourceAt(def->offset[VX], def->offset[VY], def->offset[VZ], def->size, def->lightLevel[0], def->lightLevel[1], def->color) == -1) break; } // Create biassurfaces for all current worldmap surfaces. { uint i; size_t numVertIllums = 0; vertexillum_t* illums; // First, determine the total number of vertexillum_ts we need. for(i = 0; i < numSegs; ++i) if(segs[i].lineDef) numVertIllums++; numVertIllums *= 3 * 4; for(i = 0; i < numSectors; ++i) { sector_t* sec = §ors[i]; subsector_t** ssecPtr = sec->ssectors; while(*ssecPtr) { subsector_t* ssec = *ssecPtr; numVertIllums += ssec->numVertices * sec->planeCount; *ssecPtr++; } } for(i = 0; i < numPolyObjs; ++i) { polyobj_t* po = polyObjs[i]; numVertIllums += po->numSegs * 3 * 4; } // Allocate and initialize the vertexillum_ts. illums = Z_Calloc(sizeof(vertexillum_t) * numVertIllums, PU_MAP, 0); for(i = 0; i < numVertIllums; ++i) SB_InitVertexIllum(&illums[i]); // Allocate bias surfaces and attach vertexillum_ts. for(i = 0; i < numSegs; ++i) { seg_t* seg = &segs[i]; int j; if(!seg->lineDef) continue; for(j = 0; j < 3; ++j) { biassurface_t* bsuf = SB_CreateSurface(); bsuf->size = 4; bsuf->illum = illums; illums += 4; seg->bsuf[j] = bsuf; } } for(i = 0; i < numSectors; ++i) { sector_t* sec = §ors[i]; subsector_t** ssecPtr = sec->ssectors; while(*ssecPtr) { subsector_t* ssec = *ssecPtr; uint j; for(j = 0; j < sec->planeCount; ++j) { biassurface_t* bsuf = SB_CreateSurface(); bsuf->size = ssec->numVertices; bsuf->illum = illums; illums += ssec->numVertices; ssec->bsuf[j] = bsuf; } *ssecPtr++; } } for(i = 0; i < numPolyObjs; ++i) { polyobj_t* po = polyObjs[i]; uint j; for(j = 0; j < po->numSegs; ++j) { seg_t* seg = po->segs[j]; int k; for(k = 0; k < 3; ++k) { biassurface_t* bsuf = SB_CreateSurface(); bsuf->size = 4; bsuf->illum = illums; illums += 4; seg->bsuf[k] = bsuf; } } } } // How much time did we spend? VERBOSE(Con_Message("SB_InitForMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } void SB_SetColor(float* dest, float* src) { int i; float largest = 0; // Amplify the color. for(i = 0; i < 3; ++i) { dest[i] = src[i]; if(largest < dest[i]) largest = dest[i]; } if(largest > 0) { for(i = 0; i < 3; ++i) dest[i] /= largest; } else { // Replace black with white. dest[0] = dest[1] = dest[2] = 1; } } static void SB_AddAffected(affection_t* aff, uint k, float intensity) { uint i, worst; if(aff->numFound < MAX_BIAS_AFFECTED) { aff->affected[aff->numFound].source = k; aff->intensities[aff->numFound] = intensity; aff->numFound++; } else { // Drop the weakest. worst = 0; for(i = 1; i < MAX_BIAS_AFFECTED; ++i) { if(aff->intensities[i] < aff->intensities[worst]) worst = i; } aff->affected[worst].source = k; aff->intensities[worst] = intensity; } } void SB_InitVertexIllum(vertexillum_t* villum) { int i; villum->flags |= VIF_STILL_UNSEEN; for(i = 0; i < MAX_BIAS_AFFECTED; ++i) villum->casted[i].source = -1; } void SB_SurfaceInit(biassurface_t* bsuf) { uint i; for(i = 0; i < bsuf->size; ++i) { SB_InitVertexIllum(&bsuf->illum[i]); } } void SB_SurfaceMoved(biassurface_t* bsuf) { int i; for(i = 0; i < MAX_BIAS_AFFECTED && bsuf->affected[i].source >= 0; ++i) { sources[bsuf->affected[i].source].flags |= BLF_CHANGED; } } static float SB_Dot(source_t* src, const vectorcomp_t* point, const vectorcomp_t* normal) { float delta[3]; // Delta vector between source and given point. V3_Subtract(delta, src->pos, point); // Calculate the distance. V3_Normalize(delta); return V3_DotProduct(delta, normal); } static void updateAffected(biassurface_t* bsuf, const fvertex_t* from, const fvertex_t* to, const vectorcomp_t* normal) { int i, k; vec2_t delta; source_t* src; float distance = 0, len; float intensity; affection_t aff; // If the data is already up to date, nothing needs to be done. if(bsuf->updated == lastChangeOnFrame) return; bsuf->updated = lastChangeOnFrame; aff.affected = bsuf->affected; aff.numFound = 0; memset(aff.affected, -1, sizeof(bsuf->affected)); for(k = 0, src = sources; k < numSources; ++k, ++src) { if(src->intensity <= 0) continue; // Calculate minimum 2D distance to the seg. for(i = 0; i < 2; ++i) { if(!i) V2_Set(delta, from->pos[VX] - src->pos[VX], from->pos[VY] - src->pos[VY]); else V2_Set(delta, to->pos[VX] - src->pos[VX], to->pos[VY] - src->pos[VY]); len = V2_Normalize(delta); if(i == 0 || len < distance) distance = len; } if(M_DotProduct(delta, normal) >= 0) continue; if(distance < 1) distance = 1; intensity = src->intensity / distance; // Is the source is too weak, ignore it entirely. if(intensity < biasIgnoreLimit) continue; SB_AddAffected(&aff, k, intensity); } } static void updateAffected2(biassurface_t* bsuf, const struct rvertex_s* rvertices, size_t numVertices, const vectorcomp_t* point, const vectorcomp_t* normal) { int i; uint k; vec2_t delta; source_t* src; float distance = 0, len, dot; float intensity; affection_t aff; // If the data is already up to date, nothing needs to be done. if(bsuf->updated == lastChangeOnFrame) return; bsuf->updated = lastChangeOnFrame; aff.affected = bsuf->affected; aff.numFound = 0; memset(aff.affected, -1, sizeof(aff.affected)); for(i = 0, src = sources; i < numSources; ++i, ++src) { if(src->intensity <= 0) continue; // Calculate minimum 2D distance to the ssec. // \fixme This is probably too accurate an estimate. for(k = 0; k < bsuf->size; ++k) { V2_Set(delta, rvertices[k].pos[VX] - src->pos[VX], rvertices[k].pos[VY] - src->pos[VY]); len = V2_Length(delta); if(k == 0 || len < distance) distance = len; } if(distance < 1) distance = 1; // Estimate the effect on this surface. dot = SB_Dot(src, point, normal); if(dot <= 0) continue; intensity = /*dot * */ src->intensity / distance; // Is the source is too weak, ignore it entirely. if(intensity < biasIgnoreLimit) continue; SB_AddAffected(&aff, i, intensity); } } /** * Sets/clears a bit in the tracker for the given index. */ void SB_TrackerMark(biastracker_t* tracker, uint index) { // Assume 32-bit uint. if(index >= 0) { tracker->changes[index >> 5] |= (1 << (index & 0x1f)); } /*else { tracker->changes[(-index) >> 5] &= ~(1 << ((-index) & 0x1f)); }*/ } /** * Checks if the given index bit is set in the tracker. */ int SB_TrackerCheck(biastracker_t* tracker, uint index) { // Assume 32-bit uint. return (tracker->changes[index >> 5] & (1 << (index & 0x1f))) != 0; } /** * Copies changes from src to dest. */ void SB_TrackerApply(biastracker_t* dest, const biastracker_t* src) { uint i; for(i = 0; i < MAX_BIAS_TRACKED; ++i) { dest->changes[i] |= src->changes[i]; } } /** * Clears changes of src from dest. */ void SB_TrackerClear(biastracker_t* dest, const biastracker_t* src) { uint i; for(i = 0; i < MAX_BIAS_TRACKED; ++i) { dest->changes[i] &= ~src->changes[i]; } } /** * Tests against trackChanged. */ static boolean SB_ChangeInAffected(biasaffection_t* affected, biastracker_t* changed) { uint i; for(i = 0; i < MAX_BIAS_AFFECTED; ++i) { if(affected[i].source < 0) break; if(SB_TrackerCheck(changed, affected[i].source)) return true; } return false; } /** * Do initial processing that needs to be done before rendering a * frame. Changed lights cause the tracker bits to the set for all * segs and planes. */ void SB_BeginFrame(void) { int l; source_t* s; biastracker_t allChanges; #ifdef DD_PROFILE static int i; if(++i > 40) { i = 0; PRINT_PROF( PROF_BIAS_UPDATE ); } #endif if(!useBias) return; BEGIN_PROF( PROF_BIAS_UPDATE ); // The time that applies on this frame. currentTimeSB = Sys_GetRealTime(); // Check which sources have changed. memset(&allChanges, 0, sizeof(allChanges)); for(l = 0, s = sources; l < numSources; ++l, ++s) { if(s->sectorLevel[1] > 0 || s->sectorLevel[0] > 0) { float minLevel = s->sectorLevel[0]; float maxLevel = s->sectorLevel[1]; sector_t* sector; float oldIntensity = s->intensity; sector = R_PointInSubsector(s->pos[VX], s->pos[VY])->sector; // The lower intensities are useless for light emission. if(sector->lightLevel >= maxLevel) { s->intensity = s->primaryIntensity; } if(sector->lightLevel >= minLevel && minLevel != maxLevel) { s->intensity = s->primaryIntensity * (sector->lightLevel - minLevel) / (maxLevel - minLevel); } else { s->intensity = 0; } if(s->intensity != oldIntensity) sources[l].flags |= BLF_CHANGED; } if(sources[l].flags & BLF_CHANGED) { SB_TrackerMark(&allChanges, l); sources[l].flags &= ~BLF_CHANGED; // This is used for interpolation. sources[l].lastUpdateTime = currentTimeSB; // Recalculate which sources affect which surfaces. lastChangeOnFrame = frameCount; } } // Apply to all surfaces. { biassurface_t* bsuf = surfaces; for(bsuf = surfaces; bsuf; bsuf = bsuf->next) { SB_TrackerApply(&bsuf->tracker, &allChanges); // Everything that is affected by the changed lights will need an // update. if(SB_ChangeInAffected(bsuf->affected, &allChanges)) { uint i; // Mark the illumination unseen to force an update. for(i = 0; i < bsuf->size; ++i) bsuf->illum[i].flags |= VIF_STILL_UNSEEN; } } } END_PROF( PROF_BIAS_UPDATE ); } void SB_EndFrame(void) { if(numSourceDelta != 0) { numSources += numSourceDelta; numSourceDelta = 0; } // Update the editor. SBE_EndFrame(); } void SB_AddLight(float dest[4], const float *color, float howMuch) { int i; float newval, amplified[3], largest = 0; if(color == NULL) { for(i = 0; i < 3; ++i) { amplified[i] = dest[i]; if(i == 0 || amplified[i] > largest) largest = amplified[i]; } if(largest == 0) // Black! { amplified[0] = amplified[1] = amplified[2] = 1; } else { for(i = 0; i < 3; ++i) { amplified[i] = amplified[i] / largest; } } } for(i = 0; i < 3; ++i) { newval = dest[i] + ((color ? color : amplified)[i] * howMuch); if(newval > 1) newval = 1; dest[i] = newval; } } #if 0 /** * Color override forces the bias light color to override biased * sectorlight. */ static boolean SB_CheckColorOverride(biasaffection_t *affected) { int i; for(i = 0; affected[i].source >= 0 && i < MAX_BIAS_AFFECTED; ++i) { // If the color is completely black, it means no light was // reached from this affected source. if(!(affected[i].rgb[0] | affected[i].rgb[1] | affected[i].rgb[2])) continue; if(sources[affected[i].source].flags & BLF_COLOR_OVERRIDE) return true; } return false; } #endif /** * Surface can be a either a wall or a plane (ceiling or a floor). * * @param colors Array of colors to be written to. * @param bsuf Bias data for this surface. * @param vertices Array of vertices to be lit. * @param numVertices Number of vertices (in the array) to be lit. * @param normal Surface normal. * @param sectorLightLevel Sector light level. * @param mapObject Ptr to either a seg or subsector. * @param elmIdx Used with subsectors to select a specific plane. * @param isSeg @c true, if surface is to a seg ELSE a subsector. */ void SB_RendPoly(struct rcolor_s* rcolors, biassurface_t* bsuf, const struct rvertex_s* rvertices, size_t numVertices, const vectorcomp_t* normal, float sectorLightLevel, void* mapObject, uint elmIdx, boolean isSeg) { uint i; boolean forced; // Apply sectorlight bias. Note: Distance darkening is not used // with bias lights. if(sectorLightLevel > biasMin && biasMax > biasMin) { biasAmount = (sectorLightLevel - biasMin) / (biasMax - biasMin); if(biasAmount > 1) biasAmount = 1; } else { biasAmount = 0; } memcpy(&trackChanged, &bsuf->tracker, sizeof(trackChanged)); memset(&trackApplied, 0, sizeof(trackApplied)); // Has any of the old affected lights changed? forced = false; if(doUpdateAffected) { /** * \todo This could be enhanced so that only the lights on the * right side of the surface are taken into consideration. */ if(isSeg) { seg_t* seg = (seg_t*) mapObject; updateAffected(bsuf, &seg->SG_v1->v, &seg->SG_v2->v, normal); } else { subsector_t* ssec = (subsector_t*) mapObject; vec3_t point; V3_Set(point, ssec->midPoint.pos[VX], ssec->midPoint.pos[VY], ssec->sector->planes[elmIdx]->height); updateAffected2(bsuf, rvertices, numVertices, point, normal); } } for(i = 0; i < numVertices; ++i) SB_EvalPoint(rcolors[i].rgba, &bsuf->illum[i], bsuf->affected, rvertices[i].pos, normal); // colorOverride = SB_CheckColorOverride(affected); SB_TrackerClear(&bsuf->tracker, &trackApplied); } /** * Interpolate between current and destination. */ void SB_LerpIllumination(vertexillum_t* illum, float* result) { uint i; if(!(illum->flags & VIF_LERP)) { // We're done with the interpolation, just use the // destination color. result[CR] = illum->color[CR]; result[CG] = illum->color[CG]; result[CB] = illum->color[CB]; } else { float inter = (currentTimeSB - illum->updatetime) / (float)lightSpeed; if(inter > 1) { illum->flags &= ~VIF_LERP; illum->color[CR] = illum->dest[CR]; illum->color[CG] = illum->dest[CG]; illum->color[CB] = illum->dest[CB]; result[CR] = illum->color[CR]; result[CG] = illum->color[CG]; result[CB] = illum->color[CB]; } else { for(i = 0; i < 3; ++i) { result[i] = (illum->color[i] + (illum->dest[i] - illum->color[i]) * inter); } } } } /** * @return Light contributed by the specified source. */ float* SB_GetCasted(vertexillum_t* illum, int sourceIndex, biasaffection_t* affectedSources) { int i, k; boolean inUse; for(i = 0; i < MAX_BIAS_AFFECTED; ++i) if(illum->casted[i].source == sourceIndex) return illum->casted[i].color; // Choose an array element not used by the affectedSources. for(i = 0; i < MAX_BIAS_AFFECTED; ++i) { inUse = false; for(k = 0; k < MAX_BIAS_AFFECTED; ++k) { if(affectedSources[k].source < 0) break; if(affectedSources[k].source == illum->casted[i].source) { inUse = true; break; } } if(!inUse) { illum->casted[i].source = sourceIndex; illum->casted[i].color[CR] = illum->casted[i].color[CG] = illum->casted[i].color[CB] = 0; return illum->casted[i].color; } } Con_Error("SB_GetCasted: No light casted by source %i.\n", sourceIndex); return NULL; } /** * Add ambient light. */ void SB_AmbientLight(const float* point, float* light) { // Add grid light (represents ambient lighting). float color[3]; LG_Evaluate(point, color); SB_AddLight(light, color, 1.0f); } /** * Applies shadow bias to the given point. If 'forced' is true, new * lighting is calculated regardless of whether the lights affecting the * point have changed. This is needed when there has been world geometry * changes. 'illum' is allowed to be NULL. * * \fixme Only recalculate the changed lights. The colors contributed * by the others can be saved with the 'affected' array. */ void SB_EvalPoint(float light[4], vertexillum_t* illum, biasaffection_t* affectedSources, const float* point, const float* normal) { #define COLOR_CHANGE_THRESHOLD 0.1f float newColor[3]; float dot; vec3_t delta, surfacePoint; float distance; float level; uint i; int idx; boolean illuminationChanged = false; unsigned int latestSourceUpdate = 0; source_t* s; float* casted; struct { int index; //uint affNum; // Index in affectedSources. source_t* source; biasaffection_t* affection; boolean changed; boolean overrider; } affecting[MAX_BIAS_AFFECTED + 1], *aff; // Vertices that are rendered for the first time need to be fully // evaluated. if(illum->flags & VIF_STILL_UNSEEN) { illuminationChanged = true; illum->flags &= ~VIF_STILL_UNSEEN; } // Determine if any of the affecting lights have changed since // last frame. aff = affecting; if(numSources > 0) { for(i = 0; affectedSources[i].source >= 0 && i < MAX_BIAS_AFFECTED; ++i) { idx = affectedSources[i].source; // Is this a valid index? if(idx < 0 || idx >= numSources) continue; aff->index = idx; //aff->affNum = i; aff->source = &sources[idx]; aff->affection = &affectedSources[i]; aff->overrider = (aff->source->flags & BLF_COLOR_OVERRIDE) != 0; if(SB_TrackerCheck(&trackChanged, idx)) { aff->changed = true; illuminationChanged = true; SB_TrackerMark(&trackApplied, idx); // Keep track of the earliest time when an affected source // was changed. if(latestSourceUpdate < sources[idx].lastUpdateTime) { latestSourceUpdate = sources[idx].lastUpdateTime; } } else { aff->changed = false; } // Move to the next. aff++; } } aff->source = NULL; if(!illuminationChanged && illum != NULL) { // Reuse the previous value. SB_LerpIllumination(illum, light); SB_AmbientLight(point, light); return; } // Init to black. newColor[CR] = newColor[CG] = newColor[CB] = 0; // Calculate the contribution from each light. for(aff = affecting; aff->source; aff++) { if(illum && !aff->changed) //SB_TrackerCheck(&trackChanged, aff->index)) { // We can reuse the previously calculated value. This can // only be done if this particular light source hasn't // changed. continue; } s = aff->source; if(illum) casted = SB_GetCasted(illum, aff->index, affectedSources); else casted = NULL; V3_Subtract(delta, s->pos, point); V3_Copy(surfacePoint, delta); V3_Scale(surfacePoint, 1.f / 100); V3_Sum(surfacePoint, surfacePoint, point); if(useSightCheck && !P_CheckLineSight(s->pos, surfacePoint, -1, 1, 0)) { // LOS fail. if(casted) { // This affecting source does not contribute any light. casted[CR] = casted[CG] = casted[CB] = 0; } continue; } else { distance = V3_Normalize(delta); dot = V3_DotProduct(delta, normal); // The surface faces away from the light. if(dot <= 0) { if(casted) { casted[CR] = casted[CG] = casted[CB] = 0; } continue; } level = dot * s->intensity / distance; } if(level > 1) level = 1; for(i = 0; i < 3; ++i) { // The light casted from this source. casted[i] = s->color[i] * level; } // Are we already fully lit? /*if(!(newColor[CR] < 1 && newColor[CG] < 1 && new.rgba[2] < 1)) break;*/ } if(illum) { //Con_Message("\n"); boolean willOverride = false; // Combine the casted light from each source. for(aff = affecting; aff->source; aff++) { float *casted = SB_GetCasted(illum, aff->index, affectedSources); if(aff->overrider && (casted[CR] > 0 || casted[CG] > 0 || casted[CB] > 0)) willOverride = true; /* if(!(casted[3] > 0)) { int n; Con_Message("affected: "); for(n = 0; n < MAX_BIAS_AFFECTED; ++n) Con_Message("%i ", affectedSources[n].source); Con_Message("\n"); Con_Error("not updated: s=%i\n", aff->index); } */ /* if(editSelector >= 0 && aff->index != editSelector) continue;*/ /* { int n; printf("affected: "); for(n = 0; n < MAX_BIAS_AFFECTED; ++n) printf("%i ", affectedSources[n].source); printf("casted: "); for(n = 0; n < MAX_BIAS_AFFECTED; ++n) printf("%i ", illum->casted[n].source); printf("%i:(%g %g %g) ", aff->index, casted[CR], casted[CG], casted[CB]); printf("\n"); }*/ for(i = 0; i < 3; ++i) { newColor[i] = MINMAX_OF(0, newColor[i] + casted[i], 1); } } /*if(biasAmount > 0) { SB_AddLight(&new, willOverride ? NULL : biasColor, biasAmount); }*/ // Is there a new destination? if(!(illum->dest[CR] < newColor[CR] + COLOR_CHANGE_THRESHOLD && illum->dest[CR] > newColor[CR] - COLOR_CHANGE_THRESHOLD) || !(illum->dest[CG] < newColor[CG] + COLOR_CHANGE_THRESHOLD && illum->dest[CG] > newColor[CG] - COLOR_CHANGE_THRESHOLD) || !(illum->dest[CB] < newColor[CB] + COLOR_CHANGE_THRESHOLD && illum->dest[CB] > newColor[CB] - COLOR_CHANGE_THRESHOLD)) { if(illum->flags & VIF_LERP) { // Must not lose the half-way interpolation. float mid[3]; SB_LerpIllumination(illum, mid); // This is current color at this very moment. illum->color[CR] = mid[CR]; illum->color[CG] = mid[CG]; illum->color[CB] = mid[CB]; } // This is what we will be interpolating to. illum->dest[CR] = newColor[CR]; illum->dest[CG] = newColor[CG]; illum->dest[CB] = newColor[CB]; illum->flags |= VIF_LERP; illum->updatetime = latestSourceUpdate; } SB_LerpIllumination(illum, light); } else { light[CR] = newColor[CR]; light[CG] = newColor[CG]; light[CB] = newColor[CB]; } SB_AmbientLight(point, light); #undef COLOR_CHANGE_THRESHOLD } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_dmu.c0000644000175000017500000015421611357170242022212 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * Doomsday Map Update API * * The Map Update API is used for accessing and making changes to map data * during gameplay. From here, the relevant engine's subsystems will be * notified of changes in the map data they use, thus allowing them to * update their status whenever needed. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_play.h" #include "de_refresh.h" #include "de_audio.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct dummyline_s { linedef_t line; // Line data. void* extraData; // Pointer to user data. boolean inUse; // true, if the dummy is being used. } dummyline_t; typedef struct dummysector_s { sector_t sector; // Sector data. void *extraData; // Pointer to user data. boolean inUse; // true, if the dummy is being used. } dummysector_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- uint dummyCount = 8; // Number of dummies to allocate (per type). // PRIVATE DATA DEFINITIONS ------------------------------------------------ static dummyline_t* dummyLines; static dummysector_t* dummySectors; static int usingDMUAPIver; // Version of the DMU API the game expects. // CODE -------------------------------------------------------------------- /** * Convert DMU enum constant into a string for error/debug messages. */ const char* DMU_Str(uint prop) { static char propStr[40]; struct prop_s { uint prop; const char* str; } props[] = { { DMU_NONE, "(invalid)" }, { DMU_VERTEX, "DMU_VERTEX" }, { DMU_SEG, "DMU_SEG" }, { DMU_LINEDEF, "DMU_LINEDEF" }, { DMU_SIDEDEF, "DMU_SIDEDEF" }, { DMU_NODE, "DMU_NODE" }, { DMU_SUBSECTOR, "DMU_SUBSECTOR" }, { DMU_SECTOR, "DMU_SECTOR" }, { DMU_PLANE, "DMU_PLANE" }, { DMU_MATERIAL, "DMU_MATERIAL" }, { DMU_LINEDEF_BY_TAG, "DMU_LINEDEF_BY_TAG" }, { DMU_SECTOR_BY_TAG, "DMU_SECTOR_BY_TAG" }, { DMU_LINEDEF_BY_ACT_TAG, "DMU_LINEDEF_BY_ACT_TAG" }, { DMU_SECTOR_BY_ACT_TAG, "DMU_SECTOR_BY_ACT_TAG" }, { DMU_X, "DMU_X" }, { DMU_Y, "DMU_Y" }, { DMU_XY, "DMU_XY" }, { DMU_NORMAL_X, "DMU_NORMAL_X" }, { DMU_NORMAL_Y, "DMU_NORMAL_Y" }, { DMU_NORMAL_Z, "DMU_NORMAL_Z" }, { DMU_NORMAL_XYZ, "DMU_NORMAL_XYZ" }, { DMU_VERTEX0, "DMU_VERTEX0" }, { DMU_VERTEX1, "DMU_VERTEX1" }, { DMU_FRONT_SECTOR, "DMU_FRONT_SECTOR" }, { DMU_BACK_SECTOR, "DMU_BACK_SECTOR" }, { DMU_SIDEDEF0, "DMU_SIDEDEF0" }, { DMU_SIDEDEF1, "DMU_SIDEDEF1" }, { DMU_FLAGS, "DMU_FLAGS" }, { DMU_DX, "DMU_DX" }, { DMU_DY, "DMU_DY" }, { DMU_DXY, "DMU_DXY" }, { DMU_LENGTH, "DMU_LENGTH" }, { DMU_SLOPE_TYPE, "DMU_SLOPE_TYPE" }, { DMU_ANGLE, "DMU_ANGLE" }, { DMU_OFFSET, "DMU_OFFSET" }, { DMU_OFFSET_X, "DMU_OFFSET_X" }, { DMU_OFFSET_Y, "DMU_OFFSET_Y" }, { DMU_OFFSET_XY, "DMU_OFFSET_XY" }, { DMU_BLENDMODE, "DMU_BLENDMODE" }, { DMU_VALID_COUNT, "DMU_VALID_COUNT" }, { DMU_LINEDEF_COUNT, "DMU_LINEDEF_COUNT" }, { DMU_COLOR, "DMU_COLOR" }, { DMU_COLOR_RED, "DMU_COLOR_RED" }, { DMU_COLOR_GREEN, "DMU_COLOR_GREEN" }, { DMU_COLOR_BLUE, "DMU_COLOR_BLUE" }, { DMU_ALPHA, "DMU_ALPHA" }, { DMU_LIGHT_LEVEL, "DMU_LIGHT_LEVEL" }, { DMT_MOBJS, "DMT_MOBJS" }, { DMU_BOUNDING_BOX, "DMU_BOUNDING_BOX" }, { DMU_SOUND_ORIGIN, "DMU_SOUND_ORIGIN" }, { DMU_WIDTH, "DMU_WIDTH" }, { DMU_HEIGHT, "DMU_HEIGHT" }, { DMU_TARGET_HEIGHT, "DMU_TARGET_HEIGHT" }, { DMU_SEG_COUNT, "DMU_SEG_COUNT" }, { DMU_SPEED, "DMU_SPEED" }, { DMU_NAMESPACE, "DMU_NAMESPACE" }, { 0, NULL } }; uint i; for(i = 0; props[i].str; ++i) if(props[i].prop == prop) return props[i].str; sprintf(propStr, "(unnamed %i)", prop); return propStr; } /** * Determines the type of the map data object. * * @param ptr Pointer to a map data object. */ static int DMU_GetType(const void* ptr) { int type; type = P_DummyType((void*)ptr); if(type != DMU_NONE) return type; type = ((const runtime_mapdata_header_t*)ptr)->type; // Make sure it's valid. switch(type) { case DMU_VERTEX: case DMU_SEG: case DMU_LINEDEF: case DMU_SIDEDEF: case DMU_SUBSECTOR: case DMU_SECTOR: case DMU_PLANE: case DMU_NODE: case DMU_MATERIAL: return type; default: // Unknown. break; } return DMU_NONE; } /** * Initializes a setargs struct. * * @param type Type of the map data object. * @param args Ptr to setargs struct to be initialized. * @param prop Property of the map data object. */ static void initArgs(setargs_t* args, int type, uint prop) { memset(args, 0, sizeof(*args)); args->type = type; args->prop = prop & ~DMU_FLAG_MASK; args->modifiers = prop & DMU_FLAG_MASK; } /** * Initializes the dummy arrays with a fixed number of dummies. */ void P_InitMapUpdate(void) { // Request the DMU API version the game is expecting. usingDMUAPIver = gx.GetInteger(DD_GAME_DMUAPI_VER); if(!usingDMUAPIver) Con_Error("P_InitMapUpdate: Game dll is not compatible with " "Doomsday " DOOMSDAY_VERSION_TEXT "."); if(usingDMUAPIver > DMUAPI_VER) Con_Error("P_InitMapUpdate: Game dll expects a latter version of the\n" "DMU API then that defined by Doomsday " DOOMSDAY_VERSION_TEXT ".\n" "This game is for a newer version of Doomsday."); // A fixed number of dummies is allocated because: // - The number of dummies is mostly dependent on recursive depth of // game functions. // - To test whether a pointer refers to a dummy is based on pointer // comparisons; if the array is reallocated, its address may change // and all existing dummies are invalidated. dummyLines = Z_Calloc(dummyCount * sizeof(dummyline_t), PU_STATIC, NULL); dummySectors = Z_Calloc(dummyCount * sizeof(dummysector_t), PU_STATIC, NULL); } /** * Allocates a new dummy object. * * @param type DMU type of the dummy object. * @param extraData Extra data pointer of the dummy. Points to * caller-allocated memory area of extra data for the * dummy. */ void* P_AllocDummy(int type, void* extraData) { uint i; switch(type) { case DMU_LINEDEF: for(i = 0; i < dummyCount; ++i) { if(!dummyLines[i].inUse) { dummyLines[i].inUse = true; dummyLines[i].extraData = extraData; dummyLines[i].line.header.type = DMU_LINEDEF; dummyLines[i].line.L_frontside = dummyLines[i].line.L_backside = NULL; return &dummyLines[i]; } } break; case DMU_SECTOR: for(i = 0; i < dummyCount; ++i) { if(!dummySectors[i].inUse) { dummySectors[i].inUse = true; dummySectors[i].extraData = extraData; dummySectors[i].sector.header.type = DMU_SECTOR; return &dummySectors[i]; } } break; default: Con_Error("P_AllocDummy: Dummies of type %s not supported.\n", DMU_Str(type)); } Con_Error("P_AllocDummy: Out of dummies of type %s.\n", DMU_Str(type)); return 0; } /** * Frees a dummy object. */ void P_FreeDummy(void* dummy) { int type = P_DummyType(dummy); switch(type) { case DMU_LINEDEF: ((dummyline_t*)dummy)->inUse = false; break; case DMU_SECTOR: ((dummysector_t*)dummy)->inUse = false; break; default: Con_Error("P_FreeDummy: Dummy is of unknown type.\n"); break; } } /** * Determines the type of a dummy object. For extra safety (in a debug build) * it would be possible to look through the dummy arrays and make sure the * pointer refers to a real dummy. */ int P_DummyType(void* dummy) { // Is it a line? if(dummy >= (void*) &dummyLines[0] && dummy <= (void*) &dummyLines[dummyCount - 1]) { return DMU_LINEDEF; } // A sector? if(dummy >= (void*) &dummySectors[0] && dummy <= (void*) &dummySectors[dummyCount - 1]) { return DMU_SECTOR; } // Unknown. return DMU_NONE; } /** * Determines if a map data object is a dummy. */ boolean P_IsDummy(void* dummy) { return P_DummyType(dummy) != DMU_NONE; } /** * Returns the extra data pointer of the dummy, or NULL if the object is not * a dummy object. */ void* P_DummyExtraData(void* dummy) { switch(P_DummyType(dummy)) { case DMU_LINEDEF: return ((dummyline_t*)dummy)->extraData; case DMU_SECTOR: return ((dummysector_t*)dummy)->extraData; default: break; } return NULL; } /** * Convert pointer to index. */ uint P_ToIndex(const void* ptr) { if(!ptr) { return 0; } switch(DMU_GetType(ptr)) { case DMU_VERTEX: return GET_VERTEX_IDX((vertex_t*) ptr); case DMU_SEG: return GET_SEG_IDX((seg_t*) ptr); case DMU_LINEDEF: return GET_LINE_IDX((linedef_t*) ptr); case DMU_SIDEDEF: return GET_SIDE_IDX((sidedef_t*) ptr); case DMU_SUBSECTOR: return GET_SUBSECTOR_IDX((subsector_t*) ptr); case DMU_SECTOR: return GET_SECTOR_IDX((sector_t*) ptr); case DMU_NODE: return GET_NODE_IDX((node_t*) ptr); case DMU_PLANE: return GET_PLANE_IDX((plane_t*) ptr); case DMU_MATERIAL: return P_ToMaterialNum((material_t*) ptr); default: Con_Error("P_ToIndex: Unknown type %s.\n", DMU_Str(DMU_GetType(ptr))); } return 0; } /** * Convert index to pointer. */ void* P_ToPtr(int type, uint index) { switch(type) { case DMU_VERTEX: return VERTEX_PTR(index); case DMU_SEG: return SEG_PTR(index); case DMU_LINEDEF: return LINE_PTR(index); case DMU_SIDEDEF: return SIDE_PTR(index); case DMU_SUBSECTOR: return SUBSECTOR_PTR(index); case DMU_SECTOR: return SECTOR_PTR(index); case DMU_NODE: return NODE_PTR(index); case DMU_PLANE: Con_Error("P_ToPtr: Cannot convert %s to a ptr (sector is unknown).\n", DMU_Str(type)); break; case DMU_MATERIAL: return P_ToMaterial(index); default: Con_Error("P_ToPtr: unknown type %s.\n", DMU_Str(type)); } return NULL; } int P_Iteratep(void *ptr, uint prop, void* context, int (*callback) (void* p, void* ctx)) { int type = DMU_GetType(ptr); switch(type) { case DMU_SECTOR: switch(prop) { case DMU_LINEDEF: { sector_t* sec = (sector_t*) ptr; int result = 1; if(sec->lineDefs) { linedef_t** linePtr = sec->lineDefs; while(*linePtr && (result = callback(*linePtr, context)) != 0) *linePtr++; } return result; } case DMU_PLANE: { sector_t* sec = (sector_t*) ptr; int result = 1; if(sec->planes) { plane_t** planePtr = sec->planes; while(*planePtr && (result = callback(*planePtr, context)) != 0) *planePtr++; } return result; } case DMU_SUBSECTOR: { sector_t* sec = (sector_t*) ptr; int result = 1; if(sec->ssectors) { subsector_t** ssecPtr = sec->ssectors; while(*ssecPtr && (result = callback(*ssecPtr, context)) != 0) *ssecPtr++; } return result; } default: Con_Error("P_Iteratep: Property %s unknown/not vector.\n", DMU_Str(prop)); } break; case DMU_SUBSECTOR: switch(prop) { case DMU_SEG: { subsector_t* ssec = (subsector_t*) ptr; int result = 1; if(ssec->segs) { seg_t** segPtr = ssec->segs; while(*segPtr && (result = callback(*segPtr, context)) != 0) *segPtr++; } return result; } default: Con_Error("P_Iteratep: Property %s unknown/not vector.\n", DMU_Str(prop)); } break; default: Con_Error("P_Iteratep: Type %s unknown.\n", DMU_Str(type)); break; } return true; // Successfully completed. } /** * Call a callback function on a selection of map data objects. The * selected objects will be specified by 'type' and 'index'. * @param context Is passed to the callback function. * * @return @c true if all the calls to the callback function * return @c true. * @c false is returned when the callback function * returns @c false; in this case, the iteration is * aborted immediately when the callback function * returns @c false. */ int P_Callback(int type, uint index, void* context, int (*callback)(void* p, void* ctx)) { switch(type) { case DMU_VERTEX: if(index < numVertexes) return callback(VERTEX_PTR(index), context); break; case DMU_SEG: if(index < numSegs) return callback(SEG_PTR(index), context); break; case DMU_LINEDEF: if(index < numLineDefs) return callback(LINE_PTR(index), context); break; case DMU_SIDEDEF: if(index < numSideDefs) return callback(SIDE_PTR(index), context); break; case DMU_NODE: if(index < numNodes) return callback(NODE_PTR(index), context); break; case DMU_SUBSECTOR: if(index < numSSectors) return callback(SUBSECTOR_PTR(index), context); break; case DMU_SECTOR: if(index < numSectors) return callback(SECTOR_PTR(index), context); break; case DMU_PLANE: Con_Error("P_Callback: %s cannot be referenced by id alone (sector is unknown).\n", DMU_Str(type)); break; case DMU_MATERIAL: if(index < numMaterialBinds) return callback(P_ToMaterial(index), context); break; case DMU_LINEDEF_BY_TAG: case DMU_SECTOR_BY_TAG: case DMU_LINEDEF_BY_ACT_TAG: case DMU_SECTOR_BY_ACT_TAG: Con_Error("P_Callback: Type %s not implemented yet.\n", DMU_Str(type)); /* for(i = 0; i < numLineDefs; ++i) { if(!callback(LINE_PTR(i), context)) return false; } */ break; default: Con_Error("P_Callback: Type %s unknown (index %i).\n", DMU_Str(type), index); } // Successfully completed. return true; } /** * Another version of callback iteration. The set of selected objects is * determined by 'type' and 'ptr'. Otherwise works like P_Callback. */ int P_Callbackp(int type, void* ptr, void* context, int (*callback)(void* p, void* ctx)) { switch(type) { case DMU_VERTEX: case DMU_SEG: case DMU_LINEDEF: case DMU_SIDEDEF: case DMU_NODE: case DMU_SUBSECTOR: case DMU_SECTOR: case DMU_PLANE: case DMU_MATERIAL: // Only do the callback if the type is the same as the object's. if(type == DMU_GetType(ptr)) { return callback(ptr, context); } #if _DEBUG else { Con_Message("P_Callbackp: Type mismatch %s != %s\n", DMU_Str(type), DMU_Str(DMU_GetType(ptr))); } #endif break; // \todo If necessary, add special types for accessing multiple objects. default: Con_Error("P_Callbackp: Type %s unknown.\n", DMU_Str(type)); } return true; } /** * Sets a value. Does some basic type checking so that incompatible types are * not assigned. Simple conversions are also done, e.g., float to fixed. */ void DMU_SetValue(valuetype_t valueType, void* dst, const setargs_t* args, uint index) { if(valueType == DDVT_FIXED) { fixed_t* d = dst; switch(args->valueType) { case DDVT_BYTE: *d = (args->byteValues[index] << FRACBITS); break; case DDVT_INT: *d = (args->intValues[index] << FRACBITS); break; case DDVT_FIXED: *d = args->fixedValues[index]; break; case DDVT_FLOAT: *d = FLT2FIX(args->floatValues[index]); break; default: Con_Error("SetValue: DDVT_FIXED incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_FLOAT) { float* d = dst; switch(args->valueType) { case DDVT_BYTE: *d = args->byteValues[index]; break; case DDVT_INT: *d = args->intValues[index]; break; case DDVT_FIXED: *d = FIX2FLT(args->fixedValues[index]); break; case DDVT_FLOAT: *d = args->floatValues[index]; break; default: Con_Error("SetValue: DDVT_FLOAT incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_BOOL) { boolean* d = dst; switch(args->valueType) { case DDVT_BOOL: *d = args->booleanValues[index]; break; default: Con_Error("SetValue: DDVT_BOOL incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_BYTE) { byte* d = dst; switch(args->valueType) { case DDVT_BOOL: *d = args->booleanValues[index]; break; case DDVT_BYTE: *d = args->byteValues[index]; break; case DDVT_INT: *d = args->intValues[index]; break; case DDVT_FLOAT: *d = (byte) args->floatValues[index]; break; default: Con_Error("SetValue: DDVT_BYTE incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_INT) { int* d = dst; switch(args->valueType) { case DDVT_BOOL: *d = args->booleanValues[index]; break; case DDVT_BYTE: *d = args->byteValues[index]; break; case DDVT_INT: *d = args->intValues[index]; break; case DDVT_FLOAT: *d = args->floatValues[index]; break; case DDVT_FIXED: *d = (args->fixedValues[index] >> FRACBITS); break; default: Con_Error("SetValue: DDVT_INT incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_SHORT) { short* d = dst; switch(args->valueType) { case DDVT_BOOL: *d = args->booleanValues[index]; break; case DDVT_BYTE: *d = args->byteValues[index]; break; case DDVT_INT: *d = args->intValues[index]; break; case DDVT_FLOAT: *d = args->floatValues[index]; break; case DDVT_FIXED: *d = (args->fixedValues[index] >> FRACBITS); break; default: Con_Error("SetValue: DDVT_SHORT incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_ANGLE) { angle_t* d = dst; switch(args->valueType) { case DDVT_ANGLE: *d = args->angleValues[index]; break; default: Con_Error("SetValue: DDVT_ANGLE incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_BLENDMODE) { blendmode_t* d = dst; switch(args->valueType) { case DDVT_INT: if(args->intValues[index] > DDNUM_BLENDMODES || args->intValues[index] < 0) Con_Error("SetValue: %d is not a valid value for DDVT_BLENDMODE.\n", args->intValues[index]); *d = args->intValues[index]; break; default: Con_Error("SetValue: DDVT_BLENDMODE incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_PTR) { void** d = dst; switch(args->valueType) { case DDVT_PTR: *d = args->ptrValues[index]; break; default: Con_Error("SetValue: DDVT_PTR incompatible with value type %s.\n", value_Str(args->valueType)); } } else { Con_Error("SetValue: unknown value type %d.\n", valueType); } } /** * Only those properties that are writable by outside parties (such as games) * are included here. Attempting to set a non-writable property causes a * fatal error. * * When a property changes, the relevant subsystems are notified of the change * so that they can update their state accordingly. */ static int setProperty(void* obj, void* context) { setargs_t* args = (setargs_t*) context; sector_t* updateSector1 = NULL, *updateSector2 = NULL; plane_t* updatePlane = NULL; linedef_t* updateLinedef = NULL; sidedef_t* updateSidedef = NULL; surface_t* updateSurface = NULL; // subsector_t* updateSubSector = NULL; /** * \algorithm: * * When setting a property, reference resolution is done hierarchically so * that we can update all owner's of the objects being manipulated should * the DMU object's Set routine suggests that a change occured which other * DMU objects may wish/need to respond to. * * 1) Collect references to all current owners of the object. * 2) Pass the change delta on to the object. * 3) Object responds: * @c true = update owners, ELSE @c false. * 4) If num collected references > 0 * recurse, Object = owners[n] */ // Dereference where necessary. Note the order, these cascade. if(args->type == DMU_SUBSECTOR) { // updateSubSector = (subsector_t*) obj; if(args->modifiers & DMU_FLOOR_OF_SECTOR) { obj = ((subsector_t*) obj)->sector; args->type = DMU_SECTOR; } else if(args->modifiers & DMU_CEILING_OF_SECTOR) { obj = ((subsector_t*) obj)->sector; args->type = DMU_SECTOR; } } if(args->type == DMU_SECTOR) { updateSector1 = (sector_t*) obj; if(args->modifiers & DMU_FLOOR_OF_SECTOR) { sector_t *sec = (sector_t*) obj; obj = sec->SP_plane(PLN_FLOOR); args->type = DMU_PLANE; } else if(args->modifiers & DMU_CEILING_OF_SECTOR) { sector_t *sec = (sector_t*) obj; obj = sec->SP_plane(PLN_CEILING); args->type = DMU_PLANE; } } if(args->type == DMU_LINEDEF) { updateLinedef = (linedef_t*) obj; if(args->modifiers & DMU_SIDEDEF0_OF_LINE) { obj = ((linedef_t*) obj)->L_frontside; args->type = DMU_SIDEDEF; } else if(args->modifiers & DMU_SIDEDEF1_OF_LINE) { linedef_t *li = ((linedef_t*) obj); if(!li->L_backside) Con_Error("DMU_setProperty: Linedef %i has no back side.\n", P_ToIndex(li)); obj = li->L_backside; args->type = DMU_SIDEDEF; } } if(args->type == DMU_SIDEDEF) { updateSidedef = (sidedef_t*) obj; if(args->modifiers & DMU_TOP_OF_SIDEDEF) { obj = &((sidedef_t*) obj)->SW_topsurface; args->type = DMU_SURFACE; } else if(args->modifiers & DMU_MIDDLE_OF_SIDEDEF) { obj = &((sidedef_t*) obj)->SW_middlesurface; args->type = DMU_SURFACE; } else if(args->modifiers & DMU_BOTTOM_OF_SIDEDEF) { obj = &((sidedef_t*) obj)->SW_bottomsurface; args->type = DMU_SURFACE; } } if(args->type == DMU_PLANE) { updatePlane = (plane_t*) obj; switch(args->prop) { case DMU_MATERIAL: case DMU_OFFSET_X: case DMU_OFFSET_Y: case DMU_OFFSET_XY: case DMU_NORMAL_X: case DMU_NORMAL_Y: case DMU_NORMAL_Z: case DMU_NORMAL_XYZ: case DMU_COLOR: case DMU_COLOR_RED: case DMU_COLOR_GREEN: case DMU_COLOR_BLUE: case DMU_ALPHA: case DMU_BLENDMODE: case DMU_FLAGS: obj = &((plane_t*) obj)->surface; args->type = DMU_SURFACE; break; default: break; } } if(args->type == DMU_SURFACE) { updateSurface = (surface_t*) obj; /* // Resolve implicit references to properties of the surface's material. switch(args->prop) { case UNKNOWN1: obj = &((surface_t*) obj)->material; args->type = DMU_MATERIAL; break; default: break; }*/ } switch(args->type) { case DMU_SURFACE: Surface_SetProperty(obj, args); break; case DMU_PLANE: Plane_SetProperty(obj, args); break; case DMU_VERTEX: Vertex_SetProperty(obj, args); break; case DMU_SEG: Seg_SetProperty(obj, args); break; case DMU_LINEDEF: Linedef_SetProperty(obj, args); break; case DMU_SIDEDEF: Sidedef_SetProperty(obj, args); break; case DMU_SUBSECTOR: Subsector_SetProperty(obj, args); break; case DMU_SECTOR: Sector_SetProperty(obj, args); break; case DMU_MATERIAL: Material_SetProperty(obj, args); break; case DMU_NODE: Con_Error("SetProperty: Property %s is not writable in DMU_NODE.\n", DMU_Str(args->prop)); break; default: Con_Error("SetProperty: Type %s not writable.\n", DMU_Str(args->type)); } if(updateSurface) { if(R_UpdateSurface(updateSurface, false)) { switch(DMU_GetType(updateSurface->owner)) { case DMU_SIDEDEF: updateSidedef = updateSurface->owner; break; case DMU_PLANE: updatePlane = updateSurface->owner; break; default: Con_Error("SetPropert: Internal error, surface owner unknown.\n"); } } } if(updateSidedef) { if(R_UpdateSidedef(updateSidedef, false)) updateLinedef = updateSidedef->line; } if(updateLinedef) { if(R_UpdateLinedef(updateLinedef, false)) { updateSector1 = updateLinedef->L_frontside->sector; updateSector2 = updateLinedef->L_backside->sector; } } if(updatePlane) { if(R_UpdatePlane(updatePlane, false)) updateSector1 = updatePlane->sector; } if(updateSector1) { R_UpdateSector(updateSector1, false); } if(updateSector2) { R_UpdateSector(updateSector2, false); } /* if(updateSubSector) { R_UpdateSubSector(updateSubSector, false); } */ return true; // Continue iteration. } /** * Gets a value. Does some basic type checking so that incompatible types * are not assigned. Simple conversions are also done, e.g., float to * fixed. */ void DMU_GetValue(valuetype_t valueType, const void* src, setargs_t* args, uint index) { if(valueType == DDVT_FIXED) { const fixed_t* s = src; switch(args->valueType) { case DDVT_BYTE: args->byteValues[index] = (*s >> FRACBITS); break; case DDVT_INT: args->intValues[index] = (*s >> FRACBITS); break; case DDVT_FIXED: args->fixedValues[index] = *s; break; case DDVT_FLOAT: args->floatValues[index] = FIX2FLT(*s); break; default: Con_Error("GetValue: DDVT_FIXED incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_FLOAT) { const float* s = src; switch(args->valueType) { case DDVT_BYTE: args->byteValues[index] = *s; break; case DDVT_INT: args->intValues[index] = (int) *s; break; case DDVT_FIXED: args->fixedValues[index] = FLT2FIX(*s); break; case DDVT_FLOAT: args->floatValues[index] = *s; break; default: Con_Error("GetValue: DDVT_FLOAT incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_BOOL) { const boolean* s = src; switch(args->valueType) { case DDVT_BOOL: args->booleanValues[index] = *s; break; default: Con_Error("GetValue: DDVT_BOOL incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_BYTE) { const byte* s = src; switch(args->valueType) { case DDVT_BOOL: args->booleanValues[index] = *s; break; case DDVT_BYTE: args->byteValues[index] = *s; break; case DDVT_INT: args->intValues[index] = *s; break; case DDVT_FLOAT: args->floatValues[index] = *s; break; default: Con_Error("GetValue: DDVT_BYTE incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_INT) { const int* s = src; switch(args->valueType) { case DDVT_BOOL: args->booleanValues[index] = *s; break; case DDVT_BYTE: args->byteValues[index] = *s; break; case DDVT_INT: args->intValues[index] = *s; break; case DDVT_FLOAT: args->floatValues[index] = *s; break; case DDVT_FIXED: args->fixedValues[index] = (*s << FRACBITS); break; default: Con_Error("GetValue: DDVT_INT incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_SHORT) { const short* s = src; switch(args->valueType) { case DDVT_BOOL: args->booleanValues[index] = *s; break; case DDVT_BYTE: args->byteValues[index] = *s; break; case DDVT_INT: args->intValues[index] = *s; break; case DDVT_FLOAT: args->floatValues[index] = *s; break; case DDVT_FIXED: args->fixedValues[index] = (*s << FRACBITS); break; default: Con_Error("GetValue: DDVT_SHORT incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_ANGLE) { const angle_t* s = src; switch(args->valueType) { case DDVT_ANGLE: args->angleValues[index] = *s; break; default: Con_Error("GetValue: DDVT_ANGLE incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_BLENDMODE) { const blendmode_t* s = src; switch(args->valueType) { case DDVT_INT: args->intValues[index] = *s; break; default: Con_Error("GetValue: DDVT_BLENDMODE incompatible with value type %s.\n", value_Str(args->valueType)); } } else if(valueType == DDVT_PTR) { const void* const* s = src; switch(args->valueType) { case DDVT_INT: // Attempt automatic conversion using P_ToIndex(). Naturally only // works with map data objects. Failure leads into a fatal error. args->intValues[index] = P_ToIndex(*s); break; case DDVT_PTR: args->ptrValues[index] = (void*) *s; break; default: Con_Error("GetValue: DDVT_PTR incompatible with value type %s.\n", value_Str(args->valueType)); } } else { Con_Error("GetValue: unknown value type %d.\n", valueType); } } static int getProperty(void* obj, void* context) { setargs_t* args = (setargs_t*) context; // Dereference where necessary. Note the order, these cascade. if(args->type == DMU_SUBSECTOR) { if(args->modifiers & DMU_FLOOR_OF_SECTOR) { obj = ((subsector_t*) obj)->sector; args->type = DMU_SECTOR; } else if(args->modifiers & DMU_CEILING_OF_SECTOR) { obj = ((subsector_t*) obj)->sector; args->type = DMU_SECTOR; } } if(args->type == DMU_SECTOR) { if(args->modifiers & DMU_FLOOR_OF_SECTOR) { sector_t *sec = (sector_t*) obj; obj = sec->SP_plane(PLN_FLOOR); args->type = DMU_PLANE; } else if(args->modifiers & DMU_CEILING_OF_SECTOR) { sector_t *sec = (sector_t*) obj; obj = sec->SP_plane(PLN_CEILING); args->type = DMU_PLANE; } } if(args->type == DMU_LINEDEF) { if(args->modifiers & DMU_SIDEDEF0_OF_LINE) { obj = ((linedef_t*) obj)->L_frontside; args->type = DMU_SIDEDEF; } else if(args->modifiers & DMU_SIDEDEF1_OF_LINE) { linedef_t *li = ((linedef_t*) obj); if(!li->L_backside) Con_Error("DMU_setProperty: Linedef %i has no back side.\n", P_ToIndex(li)); obj = li->L_backside; args->type = DMU_SIDEDEF; } } if(args->type == DMU_SIDEDEF) { if(args->modifiers & DMU_TOP_OF_SIDEDEF) { obj = &((sidedef_t*) obj)->SW_topsurface; args->type = DMU_SURFACE; } else if(args->modifiers & DMU_MIDDLE_OF_SIDEDEF) { obj = &((sidedef_t*) obj)->SW_middlesurface; args->type = DMU_SURFACE; } else if(args->modifiers & DMU_BOTTOM_OF_SIDEDEF) { obj = &((sidedef_t*) obj)->SW_bottomsurface; args->type = DMU_SURFACE; } } if(args->type == DMU_PLANE) { switch(args->prop) { case DMU_MATERIAL: case DMU_OFFSET_X: case DMU_OFFSET_Y: case DMU_OFFSET_XY: case DMU_NORMAL_X: case DMU_NORMAL_Y: case DMU_NORMAL_Z: case DMU_NORMAL_XYZ: case DMU_COLOR: case DMU_COLOR_RED: case DMU_COLOR_GREEN: case DMU_COLOR_BLUE: case DMU_ALPHA: case DMU_BLENDMODE: case DMU_FLAGS: obj = &((plane_t*) obj)->surface; args->type = DMU_SURFACE; break; default: break; } } /* if(args->type == DMU_SURFACE) { // Resolve implicit references to properties of the surface's material. switch(args->prop) { case UNKNOWN1: obj = &((surface_t*) obj)->material; args->type = DMU_MATERIAL; break; default: break; } } */ switch(args->type) { case DMU_VERTEX: Vertex_GetProperty(obj, args); break; case DMU_SEG: Seg_GetProperty(obj, args); break; case DMU_LINEDEF: Linedef_GetProperty(obj, args); break; case DMU_SURFACE: Surface_GetProperty(obj, args); break; case DMU_PLANE: Plane_GetProperty(obj, args); break; case DMU_SECTOR: Sector_GetProperty(obj, args); break; case DMU_SIDEDEF: Sidedef_GetProperty(obj, args); break; case DMU_SUBSECTOR: Subsector_GetProperty(obj, args); break; case DMU_MATERIAL: Material_GetProperty(obj, args); break; default: Con_Error("GetProperty: Type %s not readable.\n", DMU_Str(args->type)); } // Currently no aggregate values are collected. return false; } void P_SetBool(int type, uint index, uint prop, boolean param) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_BOOL; // Make sure invalid values are not allowed. param = (param? true : false); args.booleanValues = ¶m; P_Callback(type, index, &args, setProperty); } void P_SetByte(int type, uint index, uint prop, byte param) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_BYTE; args.byteValues = ¶m; P_Callback(type, index, &args, setProperty); } void P_SetInt(int type, uint index, uint prop, int param) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_INT; args.intValues = ¶m; P_Callback(type, index, &args, setProperty); } void P_SetFixed(int type, uint index, uint prop, fixed_t param) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_FIXED; args.fixedValues = ¶m; P_Callback(type, index, &args, setProperty); } void P_SetAngle(int type, uint index, uint prop, angle_t param) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_ANGLE; args.angleValues = ¶m; P_Callback(type, index, &args, setProperty); } void P_SetFloat(int type, uint index, uint prop, float param) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_FLOAT; args.floatValues = ¶m; P_Callback(type, index, &args, setProperty); } void P_SetPtr(int type, uint index, uint prop, void* param) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_PTR; args.ptrValues = ¶m; P_Callback(type, index, &args, setProperty); } void P_SetBoolv(int type, uint index, uint prop, boolean* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_BOOL; args.booleanValues = params; P_Callback(type, index, &args, setProperty); } void P_SetBytev(int type, uint index, uint prop, byte* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_BYTE; args.byteValues = params; P_Callback(type, index, &args, setProperty); } void P_SetIntv(int type, uint index, uint prop, int* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_INT; args.intValues = params; P_Callback(type, index, &args, setProperty); } void P_SetFixedv(int type, uint index, uint prop, fixed_t* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_FIXED; args.fixedValues = params; P_Callback(type, index, &args, setProperty); } void P_SetAnglev(int type, uint index, uint prop, angle_t* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_ANGLE; args.angleValues = params; P_Callback(type, index, &args, setProperty); } void P_SetFloatv(int type, uint index, uint prop, float* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_FLOAT; args.floatValues = params; P_Callback(type, index, &args, setProperty); } void P_SetPtrv(int type, uint index, uint prop, void* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_PTR; args.ptrValues = params; P_Callback(type, index, &args, setProperty); } /* pointer-based write functions */ void P_SetBoolp(void* ptr, uint prop, boolean param) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BOOL; // Make sure invalid values are not allowed. param = (param? true : false); args.booleanValues = ¶m; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetBytep(void* ptr, uint prop, byte param) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BYTE; args.byteValues = ¶m; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetIntp(void* ptr, uint prop, int param) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_INT; args.intValues = ¶m; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetFixedp(void* ptr, uint prop, fixed_t param) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FIXED; args.fixedValues = ¶m; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetAnglep(void* ptr, uint prop, angle_t param) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_ANGLE; args.angleValues = ¶m; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetFloatp(void* ptr, uint prop, float param) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FLOAT; args.floatValues = ¶m; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetPtrp(void* ptr, uint prop, void* param) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_PTR; args.ptrValues = ¶m; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetBoolpv(void* ptr, uint prop, boolean* params) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BOOL; args.booleanValues = params; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetBytepv(void* ptr, uint prop, byte* params) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BYTE; args.byteValues = params; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetIntpv(void* ptr, uint prop, int* params) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_INT; args.intValues = params; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetFixedpv(void* ptr, uint prop, fixed_t* params) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FIXED; args.fixedValues = params; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetAnglepv(void* ptr, uint prop, angle_t* params) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_ANGLE; args.angleValues = params; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetFloatpv(void* ptr, uint prop, float* params) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FLOAT; args.floatValues = params; P_Callbackp(args.type, ptr, &args, setProperty); } void P_SetPtrpv(void* ptr, uint prop, void* params) { setargs_t args; initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_PTR; args.ptrValues = params; P_Callbackp(args.type, ptr, &args, setProperty); } /* index-based read functions */ boolean P_GetBool(int type, uint index, uint prop) { setargs_t args; boolean returnValue = false; initArgs(&args, type, prop); args.valueType = DDVT_BOOL; args.booleanValues = &returnValue; P_Callback(type, index, &args, getProperty); return returnValue; } byte P_GetByte(int type, uint index, uint prop) { setargs_t args; byte returnValue = 0; initArgs(&args, type, prop); args.valueType = DDVT_BYTE; args.byteValues = &returnValue; P_Callback(type, index, &args, getProperty); return returnValue; } int P_GetInt(int type, uint index, uint prop) { setargs_t args; int returnValue = 0; initArgs(&args, type, prop); args.valueType = DDVT_INT; args.intValues = &returnValue; P_Callback(type, index, &args, getProperty); return returnValue; } fixed_t P_GetFixed(int type, uint index, uint prop) { setargs_t args; fixed_t returnValue = 0; initArgs(&args, type, prop); args.valueType = DDVT_FIXED; args.fixedValues = &returnValue; P_Callback(type, index, &args, getProperty); return returnValue; } angle_t P_GetAngle(int type, uint index, uint prop) { setargs_t args; angle_t returnValue = 0; initArgs(&args, type, prop); args.valueType = DDVT_ANGLE; args.angleValues = &returnValue; P_Callback(type, index, &args, getProperty); return returnValue; } float P_GetFloat(int type, uint index, uint prop) { setargs_t args; float returnValue = 0; initArgs(&args, type, prop); args.valueType = DDVT_FLOAT; args.floatValues = &returnValue; P_Callback(type, index, &args, getProperty); return returnValue; } void* P_GetPtr(int type, uint index, uint prop) { setargs_t args; void *returnValue = NULL; initArgs(&args, type, prop); args.valueType = DDVT_PTR; args.ptrValues = &returnValue; P_Callback(type, index, &args, getProperty); return returnValue; } void P_GetBoolv(int type, uint index, uint prop, boolean* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_BOOL; args.booleanValues = params; P_Callback(type, index, &args, getProperty); } void P_GetBytev(int type, uint index, uint prop, byte* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_BYTE; args.byteValues = params; P_Callback(type, index, &args, getProperty); } void P_GetIntv(int type, uint index, uint prop, int* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_INT; args.intValues = params; P_Callback(type, index, &args, getProperty); } void P_GetFixedv(int type, uint index, uint prop, fixed_t* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_FIXED; args.fixedValues = params; P_Callback(type, index, &args, getProperty); } void P_GetAnglev(int type, uint index, uint prop, angle_t* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_ANGLE; args.angleValues = params; P_Callback(type, index, &args, getProperty); } void P_GetFloatv(int type, uint index, uint prop, float* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_FLOAT; args.floatValues = params; P_Callback(type, index, &args, getProperty); } void P_GetPtrv(int type, uint index, uint prop, void* params) { setargs_t args; initArgs(&args, type, prop); args.valueType = DDVT_PTR; args.ptrValues = params; P_Callback(type, index, &args, getProperty); } /* pointer-based read functions */ boolean P_GetBoolp(void* ptr, uint prop) { setargs_t args; boolean returnValue = false; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BOOL; args.booleanValues = &returnValue; P_Callbackp(args.type, ptr, &args, getProperty); } return returnValue; } byte P_GetBytep(void* ptr, uint prop) { setargs_t args; byte returnValue = 0; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BYTE; args.byteValues = &returnValue; P_Callbackp(args.type, ptr, &args, getProperty); } return returnValue; } int P_GetIntp(void* ptr, uint prop) { setargs_t args; int returnValue = 0; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_INT; args.intValues = &returnValue; P_Callbackp(args.type, ptr, &args, getProperty); } return returnValue; } fixed_t P_GetFixedp(void* ptr, uint prop) { setargs_t args; fixed_t returnValue = 0; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FIXED; args.fixedValues = &returnValue; P_Callbackp(args.type, ptr, &args, getProperty); } return returnValue; } angle_t P_GetAnglep(void* ptr, uint prop) { setargs_t args; angle_t returnValue = 0; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_ANGLE; args.angleValues = &returnValue; P_Callbackp(args.type, ptr, &args, getProperty); } return returnValue; } float P_GetFloatp(void* ptr, uint prop) { setargs_t args; float returnValue = 0; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FLOAT; args.floatValues = &returnValue; P_Callbackp(args.type, ptr, &args, getProperty); } return returnValue; } void* P_GetPtrp(void* ptr, uint prop) { setargs_t args; void *returnValue = NULL; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_PTR; args.ptrValues = &returnValue; P_Callbackp(args.type, ptr, &args, getProperty); } return returnValue; } void P_GetBoolpv(void* ptr, uint prop, boolean* params) { setargs_t args; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BOOL; args.booleanValues = params; P_Callbackp(args.type, ptr, &args, getProperty); } } void P_GetBytepv(void* ptr, uint prop, byte* params) { setargs_t args; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_BYTE; args.byteValues = params; P_Callbackp(args.type, ptr, &args, getProperty); } } void P_GetIntpv(void* ptr, uint prop, int* params) { setargs_t args; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_INT; args.intValues = params; P_Callbackp(args.type, ptr, &args, getProperty); } } void P_GetFixedpv(void* ptr, uint prop, fixed_t* params) { setargs_t args; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FIXED; args.fixedValues = params; P_Callbackp(args.type, ptr, &args, getProperty); } } void P_GetAnglepv(void* ptr, uint prop, angle_t* params) { setargs_t args; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_ANGLE; args.angleValues = params; P_Callbackp(args.type, ptr, &args, getProperty); } } void P_GetFloatpv(void* ptr, uint prop, float* params) { setargs_t args; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_FLOAT; args.floatValues = params; P_Callbackp(args.type, ptr, &args, getProperty); } } void P_GetPtrpv(void* ptr, uint prop, void* params) { setargs_t args; if(ptr) { initArgs(&args, DMU_GetType(ptr), prop); args.valueType = DDVT_PTR; args.ptrValues = params; P_Callbackp(args.type, ptr, &args, getProperty); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/b_main.c0000644000175000017500000017510711357170241022334 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_main.c: Event/Command Binding */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_console.h" #include "de_misc.h" #include "de_play.h" #include "b_command.h" #include "p_control.h" #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { int key; // DDKEY char* name; } keyname_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(BindEventToCommand); D_CMD(BindControlToDevice); D_CMD(ListBindings); D_CMD(ListBindingContexts); //D_CMD(ClearBindingContexts); D_CMD(ClearBindings); D_CMD(DeleteBindingById); D_CMD(ActivateBindingContext); D_CMD(DefaultBindings); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int symbolicEchoMode = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int bindingIdCounter; static const keyname_t keyNames[] = { {DDKEY_PAUSE, "pause"}, {DDKEY_ESCAPE, "escape"}, {DDKEY_ESCAPE, "esc"}, {DDKEY_RIGHTARROW, "right"}, {DDKEY_LEFTARROW, "left"}, {DDKEY_UPARROW, "up"}, {DDKEY_DOWNARROW, "down"}, {DDKEY_RETURN, "return"}, {DDKEY_TAB, "tab"}, {DDKEY_RSHIFT, "shift"}, {DDKEY_RCTRL, "ctrl"}, {DDKEY_RCTRL, "control"}, {DDKEY_RALT, "alt"}, {DDKEY_INS, "insert"}, {DDKEY_INS, "ins"}, {DDKEY_DEL, "delete"}, {DDKEY_DEL, "del"}, {DDKEY_PGUP, "pageup"}, {DDKEY_PGUP, "pgup"}, {DDKEY_PGDN, "pagedown"}, {DDKEY_PGDN, "pgdown"}, {DDKEY_PGDN, "pgdn"}, {DDKEY_HOME, "home"}, {DDKEY_END, "end"}, {DDKEY_BACKSPACE, "backspace"}, {DDKEY_BACKSPACE, "bkspc"}, {'/', "slash"}, {DDKEY_BACKSLASH, "backslash"}, {'[', "sqbracketleft"}, {']', "sqbracketright"}, {'+', "plus"}, {'-', "minus"}, {'+', "plus"}, {'=', "equals"}, {' ', "space"}, {';', "semicolon"}, {',', "comma"}, {'.', "period"}, {'\'', "apostrophe"}, {DDKEY_F10, "f10"}, {DDKEY_F11, "f11"}, {DDKEY_F12, "f12"}, {DDKEY_F1, "f1"}, {DDKEY_F2, "f2"}, {DDKEY_F3, "f3"}, {DDKEY_F4, "f4"}, {DDKEY_F5, "f5"}, {DDKEY_F6, "f6"}, {DDKEY_F7, "f7"}, {DDKEY_F8, "f8"}, {DDKEY_F9, "f9"}, {'`', "tilde"}, {DDKEY_NUMLOCK, "numlock"}, {DDKEY_SCROLL, "scrlock"}, {DDKEY_NUMPAD0, "pad0"}, {DDKEY_NUMPAD1, "pad1"}, {DDKEY_NUMPAD2, "pad2"}, {DDKEY_NUMPAD3, "pad3"}, {DDKEY_NUMPAD4, "pad4"}, {DDKEY_NUMPAD5, "pad5"}, {DDKEY_NUMPAD6, "pad6"}, {DDKEY_NUMPAD7, "pad7"}, {DDKEY_NUMPAD8, "pad8"}, {DDKEY_NUMPAD9, "pad9"}, {DDKEY_DECIMAL, "padcomma"}, {DDKEY_SUBTRACT, "padminus"}, // not really used {DDKEY_ADD, "padplus"}, // not really used {0, NULL} // The terminator }; // CODE -------------------------------------------------------------------- void B_Register(void) { #define PROTECTED_FLAGS (CMDF_NO_DEDICATED|CMDF_DED|CMDF_CLIENT) C_CMD_FLAGS("bindevent", "ss", BindEventToCommand, PROTECTED_FLAGS); C_CMD_FLAGS("bindcontrol", "ss", BindControlToDevice, PROTECTED_FLAGS); C_CMD_FLAGS("listbcontexts", NULL, ListBindingContexts, PROTECTED_FLAGS); C_CMD_FLAGS("listbindings", NULL, ListBindings, PROTECTED_FLAGS); C_CMD_FLAGS("clearbindings", "", ClearBindings, PROTECTED_FLAGS); //C_CMD_FLAGS("clearbcontexts", "", ClearBindingContexts, PROTECTED_FLAGS); C_CMD_FLAGS("delbind", "i", DeleteBindingById, PROTECTED_FLAGS); C_CMD_FLAGS("defaultbindings", "", DefaultBindings, PROTECTED_FLAGS); C_CMD_FLAGS("activatebcontext", "s", ActivateBindingContext, PROTECTED_FLAGS); C_CMD_FLAGS("deactivatebcontext", "s", ActivateBindingContext, PROTECTED_FLAGS); #undef PROTECTED_FLAGS } /** * Called once on init. */ void B_Init(void) { bcontext_t* bc = 0; if(isDedicated) { // Why sir, we are but poor folk! Them bindings are too good for us. return; } B_NewContext(DEFAULT_BINDING_CONTEXT_NAME); // Game contexts. // FIXME: Obviously belong to the game, so shouldn't be here. B_NewContext("map"); B_NewContext("map-freepan"); B_AcquireAll(B_NewContext("menu"), true); B_NewContext("gameui"); B_NewContext("shortcut"); B_AcquireKeyboard(B_NewContext("chat"), true); B_AcquireAll(B_NewContext("message"), true); // Binding context for the console. bc = B_NewContext(CONSOLE_BINDING_CONTEXT_NAME); bc->flags |= BCF_PROTECTED; // Only we can (de)activate. B_AcquireKeyboard(bc, true); // Console takes over all keyboard events. // UI doesn't let anything past it. B_AcquireAll(B_NewContext(UI_BINDING_CONTEXT_NAME), true); /* B_BindCommand("joy-hat-angle3", "print {angle 3}"); B_BindCommand("joy-hat-center", "print center"); B_BindCommand("game:key-m-press", "print hello"); B_BindCommand("key-codex20-up", "print {space released}"); B_BindCommand("key-up-down + key-shift + key-ctrl", "print \"shifted and controlled up\""); B_BindCommand("key-up-down + key-shift", "print \"shifted up\""); B_BindCommand("mouse-left", "print mbpress"); B_BindCommand("mouse-right-up", "print \"right mb released\""); B_BindCommand("joy-x-neg1.0 + key-ctrl-up", "print \"joy x negative without ctrl\""); B_BindCommand("joy-x- within 0.1 + joy-y-pos1", "print \"joy x centered\""); B_BindCommand("joy-x-pos1.0", "print \"joy x positive\""); B_BindCommand("joy-x-neg1.0", "print \"joy x negative\""); B_BindCommand("joy-z-pos1.0", "print \"joy z positive\""); B_BindCommand("joy-z-neg1.0", "print \"joy z negative\""); B_BindCommand("joy-w-pos1.0", "print \"joy w positive\""); B_BindCommand("joy-w-neg1.0", "print \"joy w negative\""); */ /*B_BindControl("turn", "key-left-staged-inverse"); B_BindControl("turn", "key-right-staged"); B_BindControl("turn", "mouse-x"); B_BindControl("turn", "joy-x + key-shift-up + joy-hat-center + key-code123-down"); */ // Bind all the defaults (of engine & game, everything). Con_Executef(CMDS_DDAY, false, "defaultbindings"); // Enable the contexts for the initial state. B_ActivateContext(B_ContextByName(DEFAULT_BINDING_CONTEXT_NAME), true); } void B_BindDefaults(void) { // Engine's highest priority context: opening control panel, opening the console. // Console bindings (when open). // Bias editor. } /** * Deallocates the memory for the commands and bindings. */ void B_Shutdown(void) { B_DestroyAllContexts(); } /** * @return Never returns zero, as that is reserved for list roots. */ int B_NewIdentifier(void) { int id = 0; while(!id) { id = ++bindingIdCounter; } return id; } const char* B_ParseContext(const char* desc, bcontext_t** bc) { ddstring_t* str = Str_New(); *bc = 0; if(!strchr(desc, ':')) { // No context defined. return desc; } desc = Str_CopyDelim(str, desc, ':'); *bc = B_ContextByName(Str_Text(str)); Str_Delete(str); return desc; } void B_DeleteMatching(bcontext_t* bc, evbinding_t* eventBinding, dbinding_t* deviceBinding) { dbinding_t* devb = NULL; evbinding_t* evb = NULL; while(B_FindMatchingBinding(bc, eventBinding, deviceBinding, &evb, &devb)) { // Only either evb or devb is returned as non-NULL. int bid = (evb? evb->bid : (devb? devb->bid : 0)); if(bid) { Con_Message("B_BindCommand: Deleting binding %i, it has been overridden by " "binding %i.\n", bid, eventBinding? eventBinding->bid : deviceBinding->bid); B_DeleteBinding(bc, bid); } } } evbinding_t* B_BindCommand(const char* eventDesc, const char* command) { bcontext_t* bc; evbinding_t* b; if(isDedicated) return NULL; // The context may be included in the descriptor. eventDesc = B_ParseContext(eventDesc, &bc); if(!bc) { bc = B_ContextByName(DEFAULT_BINDING_CONTEXT_NAME); } if((b = B_NewCommandBinding(&bc->commandBinds, eventDesc, command)) != NULL) { /** * \todo: In interactive binding mode, should ask the user if the * replacement is ok. For now, just delete the other binding. */ B_DeleteMatching(bc, b, NULL); B_UpdateDeviceStateAssociations(); } return b; } dbinding_t* B_BindControl(const char* controlDesc, const char* device) { bcontext_t* bc = 0; int localNum = 0; controlbinding_t* conBin = 0; dbinding_t* devBin = 0; ddstring_t* str = 0; const char* ptr = 0; playercontrol_t* control = 0; boolean justCreated = false; if(isDedicated) return NULL; // The control description may begin with the local player number. str = Str_New(); ptr = Str_CopyDelim(str, controlDesc, '-'); if(!strncasecmp(Str_Text(str), "local", 5) && Str_Length(str) > 5) { localNum = strtoul(Str_Text(str) + 5, NULL, 10) - 1; if(localNum < 0 || localNum >= DDMAXPLAYERS) { Con_Message("B_BindControl: Local player number %i is invalid.\n", localNum); goto finished; } // Skip past it. controlDesc = ptr; } // The next part must be the control name. controlDesc = Str_CopyDelim(str, controlDesc, '-'); control = P_PlayerControlByName(Str_Text(str)); if(!control) { Con_Message("B_BindControl: Player control \"%s\" not defined.\n", Str_Text(str)); goto finished; } bc = B_ContextByName(control->bindContextName); if(!bc) { bc = B_ContextByName(DEFAULT_BINDING_CONTEXT_NAME); } VERBOSE( Con_Message("B_BindControl: Control '%s' in context '%s' of local player %i to be " "bound to '%s'.\n", control->name, bc->name, localNum, device) ); if((conBin = B_FindControlBinding(bc, control->id)) == NULL) { justCreated = true; conBin = B_GetControlBinding(bc, control->id); } if(!(devBin = B_NewDeviceBinding(&conBin->deviceBinds[localNum], device))) { // Failure in the parsing. if(justCreated) { B_DestroyControlBinding(conBin); } conBin = 0; goto finished; } /** * \todo: In interactive binding mode, should ask the user if the * replacement is ok. For now, just delete the other binding. */ B_DeleteMatching(bc, NULL, devBin); B_UpdateDeviceStateAssociations(); finished: Str_Delete(str); return devBin; } dbinding_t* B_GetControlDeviceBindings(int localNum, int control, bcontext_t** bContext) { playercontrol_t* pc; bcontext_t* bc; if(localNum < 0 || localNum >= DDMAXPLAYERS) return NULL; pc = P_PlayerControlById(control); bc = B_ContextByName(pc->bindContextName); if(bContext) *bContext = bc; if(bc) return &B_GetControlBinding(bc, control)->deviceBinds[localNum]; return NULL; } boolean B_Delete(int bid) { int i; for(i = 0; i < B_ContextCount(); ++i) { if(B_DeleteBinding(B_ContextByPos(i), bid)) return true; } return false; } D_CMD(BindEventToCommand) { evbinding_t* b = B_BindCommand(argv[1], argv[2]); if(b) { VERBOSE( Con_Printf("Binding %i created.\n", b->bid) ); } return (b != NULL); } D_CMD(BindControlToDevice) { dbinding_t* b = B_BindControl(argv[1], argv[2]); if(b) { VERBOSE( Con_Printf("Binding %i created.\n", b->bid) ); } return (b != NULL); } D_CMD(ListBindingContexts) { B_PrintContexts(); return true; } D_CMD(ListBindings) { B_PrintAllBindings(); return true; } /* D_CMD(ClearBindingContexts) { B_DestroyAllContexts(); return true; } */ D_CMD(ClearBindings) { int i; for(i = 0; i < B_ContextCount(); ++i) { Con_Printf("Clearing binding context \"%s\"...\n", B_ContextByPos(i)->name); B_ClearContext(B_ContextByPos(i)); } // We can restart the id counter, all the old bindings were destroyed. bindingIdCounter = 0; return true; } D_CMD(DeleteBindingById) { int bid = strtoul(argv[1], NULL, 10); if(B_Delete(bid)) { Con_Printf("Binding %i deleted successfully.\n", bid); } else { Con_Printf("Cannot delete binding %i, it was not found.\n", bid); } return true; } D_CMD(DefaultBindings) { if(isDedicated) return false; B_BindDefaults(); // Set the game's default bindings. Con_Executef(CMDS_DDAY, false, "defaultgamebindings"); return true; } D_CMD(ActivateBindingContext) { boolean doActivate = !stricmp(argv[0], "activatebcontext"); bcontext_t* bc = B_ContextByName(argv[1]); if(!bc) { Con_Printf("Binding context '%s' does not exist.\n", argv[1]); return false; } if(bc->flags & BCF_PROTECTED) { Con_Message("Binding Context '%s' is protected. " "It can not be manually %s.\n", bc->name, doActivate? "activated" : "deactivated"); return false; } B_ActivateContext(bc, doActivate); return true; } #if 0 #if _DEBUG const char* EventType_Str(evtype_t type) { static char typeStr[40]; struct evnttype_s { int type; const char* str; } evnts[] = { { EV_KEY, "key"}, { EV_MOUSE_AXIS, "mouse axis"}, { EV_MOUSE_BUTTON, "mouse button"}, { EV_JOY_AXIS, "joy axis"}, { EV_JOY_SLIDER, "joy slider"}, { EV_JOY_BUTTON, "joy button"}, { EV_POV, "pov"}, { 0, NULL} }; uint i; boolean found; i = 0; found = false; while(evnts[i].str && !found) { if(evnts[i].type == type) found = true; else i++; } if(found) return evnts[i].str; sprintf(typeStr, "(unnamed %i)", type); return typeStr; } #endif static uint searchBindListForControlID(binding_t** list, uint num, int controlID) { uint i; boolean found; i = 0; found = false; while(i < num && !found) { // \fixme Use a faster than O(n) linear search. if(controlID == (*list)[i].controlID) found = true; else i++; } if(found) return i+1; // Index + 1. return 0; } static binding_t __inline* bindingForEvent(ddevent_t* ev) { uint num, idx; binding_t** list; devcontrolbinds_t* devBinds = &devCtrlBinds[ev->device]; list = &devBinds->binds[ev->isAxis? BL_AXES : BL_KEYS]; num = devBinds->numBinds[ev->isAxis? BL_AXES : BL_KEYS]; idx = searchBindListForControlID(list, num, (int) ev->obsolete.controlID); if(idx != 0) return &(*list)[idx-1]; // 1 based index. return NULL; } /** * Search event-type-specific binding array for a command which matches the * search critera. * * @param event The event to find the command for. * * @return Ptr to the found bindcontrol_t ELSE @c NULL,. */ static bindcontrol_t* B_GetBindControlForEvent(ddevent_t* ev) { uint i; binding_t* bnd; bindcontrol_t* ctrl = NULL; boolean found; if(!I_GetDevice(ev->device, true)) return NULL; bnd = bindingForEvent(ev); if(bnd == NULL) return NULL; found = false; if(!ev->noclass) // Use a specific context? (active or not) { // \note These kind of events aren't sent via direct user input. // Only by "us" when we need to switch binding classes and a // current input is active eg; a key is held down during the // switch that has commands in multiple binding classes. ctrl = &bnd->binds[ev->useclass]; switch(ctrl->type) { case BND_AXIS: if(ctrl->data.axiscontrol.playercontrol != -1) found = true; break; case BND_COMMAND: if(ctrl->data.command.command[ev->data1]) found = true; break; case BND_UNUSED: default: break; } } else { uint idx; boolean done; // Loop backwards through the active binding classes, the // command in the highest binding context slot that is currently // active is executed. i = 0; done = false; while(i < numBindClasses && !done) { idx = numBindClasses - 1 - i; if(bindContexts[idx].active == 1) { ctrl = &bnd->binds[idx]; switch(ctrl->type) { case BND_AXIS: if(ctrl->data.axiscontrol.playercontrol != -1) { found = true; done = true; } break; case BND_COMMAND: { bindcommand_t *cmd = &ctrl->data.command; if(cmd->command[ev->data1]) { found = true; done = true; } else { // RULE: If a repeat event does not have a // binding in BINDCLASS (k) we should ignore // commands in all lower classes IF there is NOT // a down binding for this event in this context. if(ev->data1 == EVS_REPEAT && cmd->command[EVS_DOWN]) done = true; // Do nothing. } break; } case BND_UNUSED: default: break; } if(!done) { // Should we ignore commands in lower classes? if(bindContexts[idx].flags & BCF_ABSOLUTE) done = true; } } if(!done) i++; } } if(found) return ctrl; return NULL; } #endif /** * Checks to see if we need to respond to the given input event in some way * and then if so executes the action associated to the event. * * @param ev ddevent_t we may need to respond to. * * @return @c true, If an action was executed. */ boolean B_Responder(ddevent_t* ev) { if(symbolicEchoMode && ev->type != E_SYMBOLIC) { // Make an echo. ddstring_t name; ddevent_t echo; // Axis events need a bit of filtering. if(ev->type == E_AXIS) { float pos = I_TransformAxis(I_GetDevice(ev->device, false), ev->axis.id, ev->axis.pos); if(ev->axis.type == EAXIS_ABSOLUTE && fabs(pos) < .5f || ev->axis.type == EAXIS_RELATIVE && fabs(pos) < .02f) { // Not significant enough for an echo. return B_TryEvent(ev); } } Str_Init(&name); Str_Set(&name, "echo-"); B_AppendEventToString(ev, &name); echo.device = ev->device; echo.type = E_SYMBOLIC; echo.symbolic.id = 0; echo.symbolic.name = Str_Text(&name); VERBOSE( Con_Message("B_Responder: Symbolic echo: %s\n", echo.symbolic.name) ); DD_PostEvent(&echo); Str_Free(&name); return true; } return B_TryEvent(ev); } #if 0 /** * Retrieve a binding for the given device control. * * @param deviceID Device ident for the binding. * @param controlID Device control index for the binding, either a * key/button number or axis index number. * @param isAxis If @c true, @param controlID is an axis * index number. * @param createNew If @c true, a new binding_t will be * allocated if an existing one cannot be found. * * @return Binding for the given event OR @c NULL, */ static binding_t *B_GetBinding(uint deviceID, uint controlID, boolean isAxis, boolean createNew) { uint i, *num, idx; binding_t *newb, **list; devcontrolbinds_t *devBinds = &devCtrlBinds[deviceID]; list = &devBinds->binds[isAxis? BL_AXES : BL_KEYS]; num = &devBinds->numBinds[isAxis? BL_AXES : BL_KEYS]; // We'll first have to search through the existing bindings // to see if there already is one for this event. idx = searchBindListForControlID(list, *num, (int) controlID); if(idx != 0) return &(*list)[idx-1]; // 1 based index. // If we arn't creating a new one, we've nothing more to do. if(!createNew) return NULL; // Hmm, no luck there. Let's create a new binding_t. *list = M_Realloc((*list), sizeof(binding_t) * ++(*num)); newb = (*list) + (*num) - 1; // Initalize the binding. newb->controlID = controlID; newb->binds = M_Calloc(sizeof(bindcontrol_t) * maxBindClasses); for(i = 0; i < numBindClasses; ++i) newb->binds[i].type = BND_UNUSED; return newb; } static void B_DeleteBindingIdx(uint deviceID, uint index, boolean isAxis) { uint i, k, *num; devcontrolbinds_t *devBinds = &devCtrlBinds[deviceID]; binding_t *bnd, **list; list = &devBinds->binds[isAxis? BL_AXES : BL_KEYS]; num = &devBinds->numBinds[isAxis? BL_AXES : BL_KEYS]; if(index > (*num) - 1) return; // What? bnd = &(*list)[index]; for(i = 0; i < numBindClasses; ++i) { if(bnd->binds[i].type == BND_COMMAND) for(k = 0; k < NUM_EVENT_STATES; ++k) { bindcommand_t *com = &bnd->binds[i].data.command; if(com->command[k]) { M_Free(com->command[k]); com->command[k] = NULL; } } } M_Free(bnd->binds); if(index < (*num) - 1) // If not the last one, do some rollback. { memmove((*list) + index, (*list) + index + 1, sizeof(binding_t) * ((*num) - index - 1)); } (*list) = M_Realloc((*list), sizeof(binding_t) * --(*num)); } static void freeBindList(binding_t *list, uint num) { uint i, j, k; binding_t *bnd; bindcontrol_t *ctrl; if(!list) return; for(i = 0, bnd = list; i < num; ++i, bnd++) { for(j = 0; j < numBindClasses; ++j) { ctrl = &bnd->binds[j]; if(ctrl->type == BND_COMMAND) { bindcommand_t *com = &ctrl->data.command; for(k = 0; k < NUM_EVENT_STATES; ++k) if(com->command[k]) M_Free(com->command[k]); } } M_Free(bnd->binds); bnd->binds = NULL; } } /** * Clears all bindings for all devices, commands and axes. * * @param active If @c true, clear those from active lists. * @param default If @c true, clear those from defaults lists. */ void B_ClearBindings(boolean active, boolean defaults) { uint d, l; devcontrolbinds_t *devBinds; uint *num; binding_t **bnd; if(!active && !defaults) return; // Nothing to do... for(d = 0; d < NUM_INPUT_DEVICES; ++d) { devBinds = &devCtrlBinds[d]; for(l = 0; l < NUM_BIND_LISTS; ++l) { /* // Only clearing selected lists? if((!active && (l == BL_KEYS || l == BL_AXES)) || (!defaults && (l == BL_KEYSD || l == BL_AXESD))) continue; */ bnd = &devBinds->binds[l]; num = &devBinds->numBinds[l]; if(*bnd) { freeBindList(*bnd, *num); M_Free(*bnd); (*bnd) = NULL; (*num) = 0; } } } } /** * Binds the given event to the command. Also rebinds old bindings. * * 1) Binding to NULL without specifying a context: deletes the binding. * * 2) Bindind to NULL and specifying a context: clears the command and * if no more commands exist for this binding - will delete it */ binding_t *B_Bind(ddevent_t *ev, char *command, int control, uint bindContext) { uint i; binding_t *bnd; bindcommand_t *com; bindaxis_t *ctrl; inputdev_t *device; boolean removing = (ev->isAxis? (control < 0):(!command)); bnd = B_GetBinding(ev->device, ev->obsolete.controlID, ev->isAxis, !removing); if(removing) { uint k, count = 0; boolean unused; if(!bnd) return NULL; // Can't remove a binding that doesn't exist. // Clear the command in bindContext only. for(i = 0; i < numBindClasses; ++i) { if(bnd->binds[i].type == BND_UNUSED) continue; if(i == bindContext) { unused = true; // Implicit; axis bindings which match bindContext are unused. // Command bindings need to be checked as each has // multiple states. if(bnd->binds[i].type == BND_COMMAND) { for(k = 0; k < NUM_EVENT_STATES; ++k) { com = &bnd->binds[i].data.command; if(com->command[k]) { if((int) k == ev->data1) { M_Free(com->command[k]); com->command[k] = NULL; } else unused = false; } } if(!unused) count++; } if(unused) bnd->binds[i].type = BND_UNUSED; } else count++; } if(count == 0) { // There are no more controls/commands for this binding so delete. devcontrolbinds_t *devBinds = &devCtrlBinds[ev->device]; uint idx = bnd - devBinds->binds[ev->isAxis? BL_AXES : BL_KEYS]; B_DeleteBindingIdx(ev->device, idx, ev->isAxis); } return NULL; } if(bnd->binds[bindContext].type == BND_COMMAND) { // If, changing from a command to an axis bind, free all commands // in all states. Else, just free the command in the state being // updated (if one already present). com = &bnd->binds[bindContext].data.command; for(i = 0; i < NUM_EVENT_STATES; ++i) { if(!ev->isAxis && (int) i != ev->data1) continue; if(com->command[i]) { M_Free(com->command[i]); com->command[i] = NULL; } } } // Set the control device = I_GetDevice(ev->device, false); bnd->binds[bindContext].type = (ev->isAxis? BND_AXIS : BND_COMMAND); if(bnd->binds[bindContext].type == BND_AXIS) { ctrl = &bnd->binds[bindContext].data.axiscontrol; ctrl->playercontrol = control; //#if _DEBUG //Con_Printf("B_Bind: (%s) axis '%s' ctrl: '%s'\n", // device->name, I_GetAxisByID(device, bnd->obsolete.controlID)->name, // P_ControlGetAxisName(control)); //#endif } else { com = &bnd->binds[bindContext].data.command; com->command[ev->data1] = M_Malloc(strlen(command) + 1); strcpy(com->command[ev->data1], command); //#if _DEBUG //Con_Printf("B_Bind: (%s) state: %i ctrlID: %d cmd: \"%s\"\n", // device->name, ev->data1, // bnd->obsolete.controlID, com->command[ev->data1]); //#endif } return bnd; } #endif const char *B_ShortNameForKey(int ddkey) { uint idx; static char nameBuffer[40]; for(idx = 0; keyNames[idx].key; ++idx) { if(ddkey == keyNames[idx].key) return keyNames[idx].name; } if(isalnum(ddkey)) { // Printable character, fabricate a single-character name. nameBuffer[0] = tolower(ddkey); nameBuffer[1] = 0; return nameBuffer; } return NULL; } int B_KeyForShortName(const char *key) { uint idx; for(idx = 0; keyNames[idx].key; ++idx) { if(!stricmp(key, keyNames[idx].name)) return keyNames[idx].key; } if(strlen(key) == 1 && isalnum(key[0])) { // ASCII char. return tolower(key[0]); } return 0; } #if 0 // Currently unused. static int getButtonNumber(int flags) { uint idx; boolean found; idx = 0; found = false; while(idx < 32 && !found) { if(flags & (1 << idx)) found = true; else idx++; } if(found) return idx; return -1; } #endif #if 0 /** * Converts a textual representation of an event to the real thing. * Buff must be valid source buffer ev a valid destination. * * @param buff Src buffer containing the textual event string. * @param ev The destination event to be updated. */ static boolean eventBuilder(char *buff, ddevent_t *ev) { char prefix; char *begin; int key; prefix = buff[0]; begin = buff; if(strlen(buff) > 1) { if(prefix != '+' && prefix != '-' && prefix != '*') prefix = '+'; // 'Down' by default. begin = buff + 1; } else prefix = '+'; // First check the obvious cases. if(!strnicmp(begin, "mb", 2)) // Mouse button? { ev->device = IDEV_MOUSE; ev->isAxis = false; ev->data1 = (prefix == '+' ? EVS_DOWN : EVS_UP); ev->obsolete.controlID = 1 << (atoi(begin + 2) - 1); return true; } else if(!strnicmp(begin, "mw", 2)) // Mouse wheel? { ev->device = IDEV_MOUSE; ev->isAxis = false; // mouse wheel is translated to keys. ev->data1 = (prefix == '+' ? EVS_DOWN : EVS_UP); ev->obsolete.controlID = !stricmp(begin + 2, "up") ? DD_MWHEEL_UP : DD_MWHEEL_DOWN; return true; } else if(!strnicmp(begin, "jb", 2)) // Joystick button? { ev->device = IDEV_JOY1; ev->isAxis = false; ev->data1 = (prefix == '+' ? EVS_DOWN : EVS_UP); ev->obsolete.controlID = 1 << (atoi(begin + 2) - 1); return true; } else if(!strnicmp(begin, "pov", 3)) // A POV angle? { uint idx; boolean found; ev->device = IDEV_JOY1; ev->isAxis = false; ev->data1 = (prefix == '+' ? EVS_DOWN : EVS_UP); ev->obsolete.controlID = 0; idx = 0; found = false; while(povDirNames[idx] && !found) { if(!stricmp(begin + 3, povDirNames[idx])) { ev->obsolete.controlID = idx; found = true; } else idx++; } return true; } else { ev->device = IDEV_KEYBOARD; ev->isAxis = false; ev->data1 = (prefix == '+' ? EVS_DOWN : (prefix == '*' ? EVS_REPEAT : EVS_UP)); if((key = getByShortName(begin))) ev->obsolete.controlID = key; else ev->obsolete.controlID = begin[0]; return true; } } /** * Forms a textual representation for an input event. * * @param buff Destination buffer to hold the formed string. * @param deviceID Device ID the event is for (e.g. IDEV_KEYBOARD = keyboard). * @param controlID Usage depends on @c type, eg keynumber. * @param isAxis If @c true, @param controlID is treated * as a device axis id. * @param state The event state (EVS_DOWN/EVS_UP/EVS_REPEAT). * Only used with keys (not with axis controls). */ void formEventString(char *buff, uint deviceID, int controlID, boolean isAxis, evstate_t state) { inputdev_t *device = I_GetDevice(deviceID, false); char *begin; if(!device) Con_Error("formEventString: bad device id (%i)\n", deviceID); if(isAxis) { sprintf(buff, "%s-%s", device->name, device->axes[controlID].name); } else { if(state > EVS_REPEAT) Con_Error("formEventString: bad event state (%d)\n", state); switch(deviceID) { case IDEV_KEYBOARD: if((begin = B_ShortNameForKey(controlID))) { sprintf(buff, "%c%s", evStatePrefixes[state], begin); } else if(controlID > 32 && controlID < 128) { sprintf(buff, "%c%c", evStatePrefixes[state], controlID); } break; case IDEV_MOUSE: if(controlID & (DD_MWHEEL_UP | DD_MWHEEL_DOWN)) sprintf(buff, "%cMW%s", evStatePrefixes[state], controlID & DD_MWHEEL_UP ? "up" : "down"); else sprintf(buff, "%cMB%d", evStatePrefixes[state], buttonNumber(controlID) + 1); break; case IDEV_JOY1: sprintf(buff, "%cJB%d", evStatePrefixes[state], buttonNumber(controlID) + 1); break; default: break; // impossible. } } } /** * Forms a textual representation for an input event, translates from the * game's event_t format to our internal ddevent_t format. * Part of the Doomsday public API. */ void B_FormEventString(char *buff, evtype_t type, evstate_t state, int data1) { uint deviceID = 0; boolean isAxis = false; // These are the same translation rules as used in DD_ProcessEvents() // except inverted as we are translating from event_t to ddevent_t. switch(type) { case EV_KEY: deviceID = IDEV_KEYBOARD; isAxis = false; break; case EV_MOUSE_AXIS: deviceID = IDEV_MOUSE; isAxis = true; break; case EV_MOUSE_BUTTON: deviceID = IDEV_MOUSE; isAxis = false; break; case EV_JOY_AXIS: deviceID = IDEV_JOY1; isAxis = true; break; case EV_JOY_SLIDER: deviceID = IDEV_JOY1; isAxis = true; break; case EV_JOY_BUTTON: deviceID = IDEV_JOY1; isAxis = false; break; default: Con_Error("B_FormEventString: Unknown event type %i.", type); } formEventString(buff, deviceID, data1, isAxis, state); } /** * Retrieve the id of the named bind context. * * @param The symbolic bind context name to search for OR identifier * in the form "bdc#" where '#' = bind context id. * * @return @c true, if one is found. */ static boolean B_GetBindClassIDbyName(const char *name, uint *id) { uint i; boolean found = false; if(!name || !name[0]) return false; // By bindContext id first. if(!strnicmp(name, "bdc", 3)) { uint idx = (uint) atoi(name+3); i = 0; while(i < numBindClasses && !found) { if(idx == bindContexts[i].id) { *id = idx; found = true; } else ++i; } } if(!found) { // Not found, now check the names. i = 0; while(i < numBindClasses && !found) { if(!stricmp(name, bindContexts[i].name)) { if(id) *id = bindContexts[i].id; found = true; } else ++i; } } return found; } #endif /* static void queEventsForHeldControls(uint deviceID, uint classID) { uint l, i, k, count; binding_t *bind; boolean isDone; devcontrolbinds_t *dCBinds = &devCtrlBinds[deviceID]; inputdev_t *dev = I_GetDevice(deviceID, true); if(!dev) return; for(l = 0; l < NUM_BIND_LISTS; ++l) { // Skip default lists. // if(l == BL_KEYSD || l == BL_AXESD) // continue; for(i = 0, bind = dCBinds->binds[l]; i < dCBinds->numBinds[l]; ++i, bind++) { bindcommand_t *com; bindaxis_t *axis; switch(bind->binds[classID].type) { case BND_UNUSED: continue; case BND_COMMAND: com = &bind->binds[classID].data.command; // We're only interested in bindings for down events currently // being pressed that have a binding in the context being // enabled/disabled (classID) if(!(com->command[EVS_DOWN] != NULL && bind->controlID >= 0 && I_IsDeviceKeyDown(deviceID, (uint) bind->controlID))) continue; break; case BND_AXIS: axis = &bind->binds[classID].data.axiscontrol; // We're only interested in bindings for axes which are // currently outside their dead zone, that have a binding in the // context being enabled/disabled (classID) // \fixme Actually check the zone! if(!dev->axes[axis->playercontrol].position) continue; break; }; // Iterate all commands for this binding, count the number of // commands for this binding that are for currently active bind // classes with a lower id than the context being enabled/disabled // (classID). count = 0; k = 0; isDone = false; while(k < numBindClasses && !isDone) { if(bindContexts[k].active && bind->binds[k].type != BND_UNUSED) { boolean ignore = false; if(bind->binds[k].type == BND_COMMAND) { com = &bind->binds[k].data.command; if(!com->command[EVS_DOWN]) ignore = true; } if(!ignore) { // If there is a command for this event binding in a // context that is currently active (current is k), that // has a greater id than the context being enabled/disabled // (classID) then we don't need to que any extra events // at all as that will have been done when the binding // context with the higher id was enabled. The commands in // the lower classes can't have been active (for this // event), as the highest context command is ALWAYS // executed unless a specific context is requested. if(k > classID) { // Don't need to que any extra events. count = 0; isDone = true; } else count++; } } if(!isDone) k++; } if(count > 0) { // We need to send either up or axis center events, specifing a // bind context for all the bind classes with a lower id than the // context being enabled/disabled (classID) that are also active // (note the order does not matter). for(k = 0; k < classID; ++k) { if(bindContexts[k].active && bind->binds[k].type != BND_UNUSED) { boolean ignore = false; if(bind->binds[k].type == BND_COMMAND) { com = &bind->binds[k].data.command; if(!com->command[EVS_UP]) ignore = true; } if(!ignore) { // Que an up/center event for this. ddevent_t ev; ev.deviceID = deviceID; ev.obsolete.controlID = bind->controlID; if(bind->binds[k].type == BND_AXIS) { ev.isAxis = true; ev.data1 = 0; } else { ev.isAxis = false; ev.data1 = EVS_UP; } // Specify a bind context. ev.useclass = bindContexts[k].id; ev.noclass = false; DD_PostEvent(&ev); } } } } // Also send an up/center event for this binding if the currently // active command is in the context being disabled and it has the // highest id of the active bindContext commands for this binding. k = 0; isDone = false; while(k < numBindClasses && !isDone) { uint idx = numBindClasses - 1 - k; if(idx < classID) { isDone = true; } else { boolean present = false; switch(bind->binds[idx].type) { case BND_COMMAND: com = &bind->binds[idx].data.command; if(com->command[EVS_DOWN]) present = true; break; case BND_AXIS: present = true; break; default: break; }; if(present) if(idx > classID && bindContexts[idx].active) { isDone = true; } else { if(!bindContexts[idx].active) { // Que an up/center event for this. ddevent_t ev; ev.deviceID = deviceID; ev.obsolete.controlID = bind->controlID; if(bind->binds[idx].type == BND_AXIS) { ev.isAxis = true; ev.data1 = 0; } else { ev.isAxis = false; ev.data1 = EVS_UP; } // Specify a bind context. ev.useclass = bindContexts[idx].id; ev.noclass = false; DD_PostEvent(&ev); } } } k++; } } } } */ #if 0 /** * Enables/disables binding classes * Ques extra input events as required */ boolean B_SetBindClass(unsigned int classID, unsigned int type) { uint g; // Change the active state of the bindContext. switch(type) { case 0: // implicitly set case 1: bindContexts[classID].active = type? 1 : 0; break; case 2: // toggle bindContexts[classID].active = bindContexts[classID].active? 0 : 1; break; default: Con_Error("B_SetBindClass: Unknown state change value %i", type); } VERBOSE2(Con_Printf("B_SetBindClass: %s %s %s.\n", bindContexts[classID].name, (type==2)? "TOGGLE" : "SET", bindContexts[classID].active? "ON" : "OFF")); // Now we need to do a check in case there are keys currently // being pressed that should be released if the event binding they are // bound too has commands in the bind context being enabled/disabled. // Also, if there are any axes which are outside their dead zone and // if there axis bindings in the bind context being enabled/disabled, we // need to send centering events for them. for(g = 0; g < NUM_INPUT_DEVICES; ++g) queEventsForHeldControls(g, classID); return true; } #endif /* static uint writeBindList(FILE *file, binding_t *list, uint num, uint deviceID, uint bindContext) { uint i, j, count = 0; binding_t *bnd; bindcontrol_t *ctrl; char buffer[20]; for(i = 0, bnd = list; i < num; ++i, bnd++) { ctrl = &bnd->binds[bindContext]; switch(ctrl->type) { case BND_AXIS: { bindaxis_t *axis = &ctrl->data.axiscontrol; formEventString(buffer, deviceID, bnd->controlID, true, 0); // \fixme Using "after" is a hack... fprintf(file, "after 1 { bindaxis %s %s ", bindContexts[bindContext].name, buffer); if(axis->invert) fprintf(file, "-"); fprintf(file, "%s", P_ControlGetAxisName(axis->playercontrol)); if(axis->localPlayer > 0) fprintf(file, "/%i", axis->localPlayer); fprintf(file, " }\n"); count++; break; } case BND_COMMAND: { bindcommand_t *com = &ctrl->data.command; for(j = 0; j < NUM_EVENT_STATES; ++j) { formEventString(buffer, deviceID, bnd->controlID, false, j); if(com->command[j]) { fprintf(file, "bind "); fprintf(file, "%s ", bindContexts[bindContext].name); fprintf(file, "%s", buffer); fprintf(file, " \""); M_WriteTextEsc(file, com->command[j]); fprintf(file, "\"\n"); count++; } } break; } case BND_UNUSED: default: break; } } return count; } */ /** * Dump all the bindings to a text (cfg) file. Outputs console commands. */ void B_WriteToFile(FILE* file) { int i; // Start with a clean slate when restoring the bindings. fprintf(file, "clearbindings\n\n"); for(i = 0; i < B_ContextCount(); ++i) { B_WriteContextToFile(B_ContextByPos(i), file); } } /** * Return the key code that corresponds the given key identifier name. * Part of the Doomsday public API. */ int DD_GetKeyCode(const char* key) { int code = B_KeyForShortName(key); return (code ? code : key[0]); } /* static uint printBindList(char *searchKey, uint deviceID, int bindContext, binding_t *list, uint num) { uint i, j, k, count; binding_t *bnd; bindcontrol_t *ctrl; boolean noMatch; char buffer[40]; count = 0; for(i = 0, bnd = list; i < num; ++i, bnd++) { for(j = 0; j < numBindClasses; ++j) { ctrl = &bnd->binds[j]; switch(ctrl->type) { case BND_COMMAND: { bindcommand_t *com = &ctrl->data.command; // for each event state. for(k = 0; k < NUM_EVENT_STATES; ++k) { if(com->command[k]) { formEventString(buffer, deviceID, bnd->controlID, (ctrl->type == BND_AXIS), k); // Does this event match the search pattern? noMatch = false; if(bindContext >= 0) { if(j != (uint) bindContext) noMatch = true; } if(!noMatch) if(searchKey && strnicmp(buffer + 1, searchKey, strlen(searchKey))) noMatch = true; if(!noMatch) { if(bindContext >= 0) Con_Printf("%-8s : %s\n", buffer, com->command[k]); else Con_Printf("%-8s : %-8s : %s\n", buffer, bindContexts[j].name, com->command[k]); count++; } } } break; } case BND_AXIS: { bindaxis_t *ctl = &ctrl->data.axiscontrol; formEventString(buffer, deviceID, bnd->controlID, (ctrl->type == BND_AXIS), 0); // Does this device control match the search pattern? noMatch = false; if(bindContext >= 0) { if(j != (uint) bindContext) noMatch = true; } if(!noMatch) if(searchKey && strnicmp(buffer, searchKey, strlen(searchKey))) noMatch = true; if(!noMatch) { const char *axisName = P_ControlGetAxisName(ctl->playercontrol); if(bindContext >= 0) Con_Printf("%-8s : %s%s\n", buffer, (ctl->invert? "-" : ""), axisName); else Con_Printf("%-8s : %-8s : %s%s\n", buffer, bindContexts[j].name, (ctl->invert? "-" : ""), axisName); count++; } break; } case BND_UNUSED: default: break; } } } return count; }*/ #if 0 /** * The "bindaxis" console command creates and deletes axis bindings. * * Example: bindaxis bindcontext mouse-y (-)look/2 */ D_CMD(BindAxis) { uint i; uint deviceID, axis; boolean invert = false; const char *name; char *ptr, ctlName[20]; int local = 0; binding_t *bind; uint ctlidx, bc = 0; const char *axisptr = argv[2]; const char *ctrlptr = argv[3]; boolean bindContextGiven = false; bindaxis_t *ctrl; if(argc < 3 || argc > 4) { Con_Printf("Usage: %s (context) (device-axis) (control)\n", argv[0]); Con_Printf("Binding Classes:\n"); for(i = 0; i < numBindClasses; ++i) Con_Printf(" %s\n", bindContexts[i].name); return true; } // Check for a specified binding context. bindContextGiven = B_GetBindClassIDbyName(argv[1], &bc); if(argc == 4 && !bindContextGiven) { Con_Printf("'%s' is not a valid bindContext name/id.\n", argv[1]); return false; } // Has a binding context been specified? if(!bindContextGiven) { // No it hasn't! default to normal bc = DDBC_NORMAL; axisptr = argv[1]; ctrlptr = argv[2]; } // Get the device and the axis. if(!I_ParseDeviceAxis(axisptr, &deviceID, &axis)) { Con_Printf("'%s' is not a valid device or device axis.\n", axisptr); return false; } // If no control is given, delete the binding. if(argc == 3 && bindContextGiven) { ddevent_t ev; ev.deviceID = deviceID; ev.obsolete.controlID = axis; ev.isAxis = true; B_Bind(&ev, NULL, -1, bc); return true; } name = ctrlptr; // A minus in front of the control name means inversion. if(name[0] == '-') { invert = true; name = &name[1]; } memset(ctlName, 0, sizeof(ctlName)); strncpy(ctlName, name, sizeof(ctlName) - 1); ptr = strchr(ctlName, '/'); if(ptr) { local = strtol(ptr + 1, NULL, 10); if(local < 0 || local >= DDMAXPLAYERS) local = 0; *ptr = 0; } ctlidx = P_ControlFindAxis(ctlName); if(ctlidx == 0) { Con_Printf("'%s' is not a valid axis control.\n", ctlName); return false; } // Create the binding. { ddevent_t ev; ev.deviceID = deviceID; ev.obsolete.controlID = axis; ev.isAxis = true; bind = B_Bind(&ev, NULL, ctlidx - 1, bc); ctrl = &bind->binds[bc].data.axiscontrol; ctrl->localPlayer = local; ctrl->invert = invert; } return true; } /** * (safe)bind(r) bindcontext +space +jump */ D_CMD(Bind) { boolean prefixGiven = true; boolean bindContextGiven = false; char validEventName[16], buff[80]; char prefix = '+', *begin; char *evntptr = argv[2]; char *cmdptr = argv[3]; ddevent_t event; int repeat = !stricmp(argv[0], "bindr") || !stricmp(argv[0], "safebindr"); int safe = !strnicmp(argv[0], "safe", 4); uint bc = 0; uint i; binding_t *existing; if(argc < 2 || argc > 4) { Con_Printf("Usage: %s (context) (event) (cmd)\n", argv[0]); Con_Printf("Binding Classes:\n"); for(i = 0; i < numBindClasses; ++i) Con_Printf(" %s\n", bindContexts[i].name); return true; } // Check for a specified binding context bindContextGiven = B_GetBindClassIDbyName(argv[1], &bc); // Has a binding context been specified? if(!bindContextGiven) { if(argc == 4) { Con_Printf("'%s' is not a valid bindContext name/id.\n", argv[1]); return false; } // No it hasn't! default to normal bc = DDBC_NORMAL; evntptr = argv[1]; cmdptr = argv[2]; } begin = evntptr; if(strlen(evntptr) > 1) // Can the event have a prefix? { prefix = evntptr[0]; begin = evntptr + 1; if(prefix != '+' && prefix != '-' && prefix != '*') { begin = evntptr; prefix = '+'; prefixGiven = false; } } else prefixGiven = false; if((argc == 3 && bindContextGiven) || (argc == 2 && !bindContextGiven)) { // We're clearing a binding. // If no prefix has been given event states (+,-,*) are cleared. if(!prefixGiven) { uint i; for(i = 0; i < NUM_EVENT_STATES; ++i) { sprintf(buff, "%c%s", evStatePrefixes[i], evntptr); eventBuilder(buff, &event); B_Bind(&event, NULL, -1, bc); } } else { eventBuilder(evntptr, &event); B_Bind(&event, NULL, -1, bc); } return true; } if(argc == 4 || (argc == 3 && !bindContextGiven)) { char cprefix = cmdptr[0]; if(cprefix != '+' && cprefix != '-' && begin == evntptr) { // Bind both the + and -. sprintf(validEventName, "-%s", evntptr); sprintf(buff, "-%s", cmdptr); if(P_IsValidControl(buff)) { eventBuilder(validEventName, &event); if(safe && (existing = B_GetBinding(event.deviceID, event.controlID, false, false))) { bindcommand_t *com = &existing->binds[bc].data.command; if(com->command[event.data1]) return false; } B_Bind(&event, buff, -1, bc); sprintf(validEventName, "+%s", evntptr); sprintf(buff, "+%s", cmdptr); eventBuilder(validEventName, &event); B_Bind(&event, buff, -1, bc); return true; } } } sprintf(validEventName, "%c%s", prefix, begin); //Con_Printf("Binding %s : %s.\n", validEventName, // argc==2? "(nothing)" : cmdptr); // Convert the name to an event. eventBuilder(validEventName, &event); if(safe && (existing = B_GetBinding(event.deviceID, event.controlID, false, false))) { bindcommand_t *com = &existing->binds[bc].data.command; if(com->command[event.data1]) return false; } // Now we can create a binding for it. if((argc == 2 && !bindContextGiven && !prefixGiven) || (argc == 3 && bindContextGiven)) B_Bind(&event, NULL, -1, bc); else B_Bind(&event, cmdptr, -1, bc); // A repeater? if(repeat && event.deviceID == IDEV_KEYBOARD && event.data1 == EVS_DOWN) { event.data1 = EVS_REPEAT; if((argc == 2 && !bindContextGiven && !prefixGiven) || (argc == 3 && bindContextGiven)) B_Bind(&event, NULL, -1, bc); else B_Bind(&event, cmdptr, -1, bc); }*/ return true; } D_CMD(DeleteBind) { Con_Printf("%s is not currently implemented\n", argv[0]); return true; } D_CMD(ListBindClasses) { uint k; // Show the available binding classes Con_Printf("Binding Classes:\n"); for(k = 0; k < numBindClasses; ++k) Con_Printf(" %s\n", bindContexts[k].name); return true; } /** * List all control bindings for all devices (including inactive devices). */ D_CMD(ListBindings) { uint i, g, comcount, bindContext = 0; char *searchKey; uint *num; binding_t **list; uint totalBinds; devcontrolbinds_t *devBinds; inputdev_t *device; boolean inClassOnly = false; // Are we showing bindings in a particular context only? searchKey = NULL; if(argc >= 2) { for(i = 0; i < numBindClasses; ++i) if(!stricmp(argv[1], bindContexts[i].name)) { // Only show bindings in this context. bindContext = bindContexts[i].id; inClassOnly= true; } if(!inClassOnly) searchKey = argv[1]; else if(argc >= 3) searchKey = argv[2]; } totalBinds = 0; comcount = 0; for(g = 0; g < NUM_INPUT_DEVICES; ++g) { uint l; device = I_GetDevice(g, false); if(!device) continue; devBinds = &devCtrlBinds[g]; for(l = 0; l < NUM_BIND_LISTS; ++l) { // Skip the default binds. // if(l == BL_KEYSD || l == BL_AXESD) // continue; list = &devBinds->binds[l]; num = &devBinds->numBinds[l]; totalBinds += *num; if(*list) comcount += printBindList(searchKey, g, (inClassOnly? bindContext:-1), *list, *num); } } if(inClassOnly) { Con_Printf("Showing %i (%s context) commands from %i bindings.\n", comcount, bindContexts[bindContext].name, totalBinds); } else { Con_Printf("Showing %i commands from %i bindings.\n", comcount, totalBinds); } return true; } /** * Enables/disables binding classes. * Ques extra input events as required. */ D_CMD(EnableBindContext) { uint i, idx = 0; boolean found; if(argc < 2 || argc > 3) { for(i = 0; i < numBindClasses; ++i) Con_Printf("%d: %s is %s\n", i, bindContexts[i].name, (bindContexts[i].active)? "On" : "Off"); Con_Printf("Usage: %s (binding context) (1=On, 0=Off (omit to toggle))\n", argv[0]); return true; } // Look for a binding context with a name that matches the argument. i = 0; found = false; while(i < numBindClasses && !found) { if(!(stricmp(argv[1], bindContexts[i].name))) { idx = bindContexts[i].id; found = true; } else i++; } if(!found || idx >= numBindClasses) { Con_Printf("Not a valid binding context. Enter listbindcontextes.\n"); return false; } if(B_SetBindClass(idx, (argc == 3)? atoi(argv[2]) : 2)) return true; return false; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_png.c0000644000175000017500000001664511357170242022357 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_png.c: PNG Images * * Portable Network Graphics high-level handling. * You'll need libpng and zlib. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_console.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void PNGAPI user_error_fn(png_structp png_ptr, png_const_charp error_msg) { Con_Message("PNG-Error: %s\n", error_msg); } void PNGAPI user_warning_fn(png_structp png_ptr, png_const_charp warning_msg) { VERBOSE(Con_Message("PNG-Warning: %s\n", warning_msg)); } /** * libpng calls this to read from files. */ void PNGAPI my_read_data(png_structp read_ptr, png_bytep data, png_size_t length) { F_Read(data, length, png_get_io_ptr(read_ptr)); } /** * Reads the given PNG image and returns a pointer to a planar RGB or * RGBA buffer. Width and height are set, and pixelSize is either 3 (RGB) * or 4 (RGBA). The caller must free the allocated buffer with Z_Free. * width, height and pixelSize can't be NULL. Handles 1-4 channels. */ unsigned char *PNG_Load(const char *fileName, int *width, int *height, int *pixelSize) { DFILE *file; png_structp png_ptr = 0; png_infop png_info = 0, end_info = 0; png_bytep *rows, pixel; unsigned char *retbuf = 0; // The return buffer. int i, k, off; if((file = F_Open(fileName, "rb")) == NULL) return NULL; // Init libpng. png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, user_error_fn, user_warning_fn); if(png_ptr) { png_info = png_create_info_struct(png_ptr); if(png_info) { end_info = png_create_info_struct(png_ptr); if(end_info) { if(!setjmp(png_jmpbuf(png_ptr))) { boolean canLoad; //png_init_io(png_ptr, file); png_set_read_fn(png_ptr, file, my_read_data); png_read_png(png_ptr, png_info, PNG_TRANSFORM_IDENTITY, NULL); // Check if it can be used. canLoad = true; if(png_info->bit_depth != 8) { Con_Message("PNG_Load: \"%s\": Bit depth must be 8.\n", fileName); canLoad = false; } else if(!png_info->width || !png_info->height) { Con_Message("PNG_Load: \"%s\": Bad file? Size is zero.\n", fileName); canLoad = false; } else if(png_info->channels <= 2 && png_info->color_type == PNG_COLOR_TYPE_PALETTE && !png_get_valid(png_ptr, png_info, PNG_INFO_PLTE)) { Con_Message("PNG_Load: \"%s\": Palette is invalid.\n", fileName); canLoad = false; } if(canLoad) { // Information about the image. *width = png_info->width; *height = png_info->height; *pixelSize = png_info->channels; // Paletted images have three color components // per pixel. if(*pixelSize == 1) *pixelSize = 3; if(*pixelSize == 2) *pixelSize = 4; // With alpha channel. // OK, let's copy it into Doomsday's buffer. // \fixme Why not load directly into it? retbuf = M_Malloc(4 * png_info->width * png_info->height); rows = png_get_rows(png_ptr, png_info); for(i = 0; i < *height; ++i) { if(png_info->channels >= 3) { memcpy(retbuf + i * (*pixelSize) * png_info->width, rows[i], (*pixelSize) * png_info->width); } else // Paletted image. { for(k = 0; k < *width; ++k) { pixel = retbuf + ((*pixelSize) * (i * png_info->width + k)); off = k * png_info->channels; if(png_info->color_type == PNG_COLOR_TYPE_PALETTE) { pixel[0] = png_info->palette[rows[i][off]].red; pixel[1] = png_info->palette[rows[i][off]].green; pixel[2] = png_info->palette[rows[i][off]].blue; } else { // Grayscale. pixel[0] = pixel[1] = pixel[2] = rows[i][off]; } if(png_info->channels == 2) // Alpha data. { pixel[3] = rows[i][off + 1]; } } } } } } } } } // Shutdown. png_destroy_read_struct(&png_ptr, &png_info, &end_info); F_Close(file); return retbuf; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_control.c0000644000175000017500000003347211357170242023105 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_control.c: Player Controls */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_play.h" // for P_LocalToConsole() #include "de_network.h" #include "de_misc.h" #include "de_system.h" #include "de_graphics.h" #include "b_main.h" #include "b_device.h" // MACROS ------------------------------------------------------------------ /* // Number of triggered impulses buffered into each player's control state // table. The buffer is emptied when a ticcmd is built. #define MAX_IMPULSES 8 #define MAX_DESCRIPTOR_LENGTH 20 #define SLOW_TURN_TIME (6.0f / 35) */ // TYPES ------------------------------------------------------------------- /** * The control descriptors contain a mapping between symbolic control * names and the identifier numbers. */ /* typedef struct controldesc_s { char name[MAX_DESCRIPTOR_LENGTH + 1]; } controldesc_t; typedef struct controlclass_s { uint count; controldesc_t *desc; } controlclass_t; */ /** * Each player has his own control state table. */ /*typedef struct controlstate_s { // The axes are updated whenever their values are needed, // i.e. during the call to P_BuildCommand. controlaxis_t *axes; // The toggles are modified via console commands. controltoggle_t *toggles; // The triggered impulses are stored into a ring buffer. uint head, tail; impulse_t impulses[MAX_IMPULSES]; } controlstate_t; */ typedef enum doubleclickstate_s { DBCS_NONE, DBCS_POSITIVE, DBCS_NEGATIVE } doubleclickstate_t; /** * Double-"clicks" actually mean double activations that occur within the double-click * threshold. This is to allow double-clicks also from the numeric controls. */ typedef struct doubleclick_s { boolean triggered; // True if double-click has been detected. uint previousClickTime; // Previous time an activation occurred. doubleclickstate_t lastState; // State at the previous time the check was made. doubleclickstate_t previousClickState; // Previous click state. When duplicated, triggers // the double click. } doubleclick_t; typedef struct controlcounter_s { int control; short impulseCounts[DDMAXPLAYERS]; doubleclick_t doubleClicks[DDMAXPLAYERS]; } controlcounter_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(ListPlayerControls); D_CMD(ClearControlAccumulation); D_CMD(Impulse); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- /* // Control class names - [singular, plural]. const char *ctlClassNames[NUM_CONTROL_CLASSES][NUM_CONTROL_CLASSES] = { {{"Axis"}, {"Axes"}}, {{"Toggle"}, {"Toggles"}}, {{"Impulse"}, {"Impulses"}} };*/ // PRIVATE DATA DEFINITIONS ------------------------------------------------ static playercontrol_t* playerControls; static controlcounter_t** controlCounts; static int playerControlCount; static int doubleClickThresholdMilliseconds = 300; // CODE -------------------------------------------------------------------- static playercontrol_t* P_AllocPlayerControl(void) { playerControls = M_Realloc(playerControls, sizeof(playercontrol_t) * ++playerControlCount); controlCounts = M_Realloc(controlCounts, sizeof(controlcounter_t*) * playerControlCount); memset(&playerControls[playerControlCount - 1], 0, sizeof(playercontrol_t)); controlCounts[playerControlCount - 1] = NULL; return &playerControls[playerControlCount - 1]; } /** * Register the console commands and cvars of the player controls subsystem. */ void P_ControlRegister(void) { C_CMD("listcontrols", "", ListPlayerControls); C_CMD("impulse", NULL, Impulse); C_CMD("resetctlaccum", "", ClearControlAccumulation); C_VAR_INT("input-doubleclick-threshold", &doubleClickThresholdMilliseconds, 0, 0, 2000); } /** * This function is exported, so that plugins can register their controls. */ void P_NewPlayerControl(int id, controltype_t type, const char *name, const char* bindContext) { playercontrol_t *pc = P_AllocPlayerControl(); pc->id = id; pc->type = type; pc->name = strdup(name); pc->bindContextName = strdup(bindContext); // Also allocate the impulse and double-click counters. controlCounts[pc - playerControls] = M_Calloc(sizeof(controlcounter_t)); } playercontrol_t* P_PlayerControlById(int id) { int i; for(i = 0; i < playerControlCount; ++i) { if(playerControls[i].id == id) return playerControls + i; } return NULL; } int P_PlayerControlIndexForId(int id) { playercontrol_t* pc = P_PlayerControlById(id); if(!pc) { return -1; } return pc - playerControls; } playercontrol_t* P_PlayerControlByName(const char* name) { int i; for(i = 0; i < playerControlCount; ++i) { if(!strcasecmp(playerControls[i].name, name)) return playerControls + i; } return NULL; } void P_ControlShutdown(void) { int i; if(playerControls) { for(i = 0; i < playerControlCount; ++i) { M_Free(playerControls[i].name); M_Free(playerControls[i].bindContextName); M_Free(controlCounts[i]); } playerControlCount = 0; M_Free(playerControls); } playerControls = 0; M_Free(controlCounts); controlCounts = 0; } /** * Updates the double-click state of a control and marks it as double-clicked * when the double-click condition is met. * * @param playerNum Player/console number. * @param control Index of the control. * @param pos State of the control. */ void P_MaintainControlDoubleClicks(int playerNum, int control, float pos) { doubleclickstate_t newState = DBCS_NONE; uint nowTime = 0; doubleclick_t* db = 0; if(!controlCounts || !controlCounts[control]) { return; } db = &controlCounts[control]->doubleClicks[playerNum]; if(doubleClickThresholdMilliseconds <= 0) { // Let's not waste time here. db->triggered = false; db->previousClickTime = 0; db->previousClickState = DBCS_NONE; return; } if(pos > .5) { newState = DBCS_POSITIVE; } else if(pos < -.5) { newState = DBCS_NEGATIVE; } else { // Release. db->lastState = newState; return; } // But has it actually changed? if(newState == db->lastState) { return; } // We have an activation! nowTime = Sys_GetRealTime(); if(newState == db->previousClickState && nowTime - db->previousClickTime < (uint) MAX_OF(0, doubleClickThresholdMilliseconds)) { ddevent_t event; ddstring_t* symbolicName = Str_New(); db->triggered = true; switch(newState) { case DBCS_POSITIVE: Str_Append(symbolicName, "control-doubleclick-positive-"); break; case DBCS_NEGATIVE: Str_Append(symbolicName, "control-doubleclick-negative-"); break; } // Compose the name of the symbolic event. Str_Append(symbolicName, playerControls[control].name); VERBOSE( Con_Message("P_MaintainControlDoubleClicks: Triggered plr %i, ctl %i, " "state %i - threshold %i (%s)\n", playerNum, control, newState, nowTime - db->previousClickTime, Str_Text(symbolicName)) ); event.device = 0; event.type = E_SYMBOLIC; event.symbolic.id = playerNum; event.symbolic.name = Str_Text(symbolicName); DD_PostEvent(&event); Str_Delete(symbolicName); } db->previousClickTime = nowTime; db->previousClickState = newState; db->lastState = newState; } void P_GetControlState(int playerNum, int control, float* pos, float* relativeOffset) { float tmp; struct bcontext_s* bc = 0; struct dbinding_s* binds = 0; int localNum; #if _DEBUG // Check that this is really a numeric control. { playercontrol_t* pc = P_PlayerControlById(control); assert(pc); assert(pc->type == CTLT_NUMERIC); } #endif // Ignore NULLs. if(!pos) pos = &tmp; if(!relativeOffset) relativeOffset = &tmp; // Bindings are associated with the ordinal of the local player, not // the actual console number (playerNum) being used. That is why // P_ConsoleToLocal() is called here. localNum = P_ConsoleToLocal(playerNum); binds = B_GetControlDeviceBindings(localNum, control, &bc); B_EvaluateDeviceBindingList(localNum, binds, pos, relativeOffset, bc); // Mark for double-clicks. P_MaintainControlDoubleClicks(playerNum, P_PlayerControlIndexForId(control), *pos); } /** * @return Number of times the impulse has been triggered since the last call. */ int P_GetImpulseControlState(int playerNum, int control) { playercontrol_t* pc = P_PlayerControlById(control); short *counter; int count = 0; assert(pc != 0); #if _DEBUG // Check that this is really an impulse control. assert(pc->type == CTLT_IMPULSE); #endif if(!controlCounts[pc - playerControls]) return 0; counter = &controlCounts[pc - playerControls]->impulseCounts[playerNum]; count = *counter; *counter = 0; return count; } int P_GetControlDoubleClick(int playerNum, int control) { playercontrol_t* pc = P_PlayerControlById(control); doubleclick_t *doubleClick = 0; int triggered = false; if(!pc || playerNum < 0 || playerNum >= DDMAXPLAYERS) return 0; if(controlCounts[pc - playerControls]) { doubleClick = &controlCounts[pc - playerControls]->doubleClicks[playerNum]; if(doubleClick->triggered) { triggered = true; doubleClick->triggered = false; } } return triggered; } void P_Impulse(int playerNum, int control) { playercontrol_t* pc = P_PlayerControlById(control); assert(pc); // Check that this is really an impulse control. if(pc->type != CTLT_IMPULSE) { Con_Message("P_Impulse: Control '%s' is not an impulse control.\n", pc->name); return; } if(playerNum < 0 || playerNum >= DDMAXPLAYERS) return; control = pc - playerControls; controlCounts[control]->impulseCounts[playerNum]++; // Mark for double clicks. P_MaintainControlDoubleClicks(playerNum, control, 1); P_MaintainControlDoubleClicks(playerNum, control, 0); } void P_ImpulseByName(int playerNum, const char* control) { playercontrol_t* pc = P_PlayerControlByName(control); if(pc) { P_Impulse(playerNum, pc->id); } } void P_ControlTicker(timespan_t time) { // Check for triggered double-clicks, and generate the appropriate impulses. } D_CMD(ClearControlAccumulation) { int i, p; playercontrol_t* pc; for(i = 0; i < playerControlCount; ++i) { pc = &playerControls[i]; for(p = 0; p < DDMAXPLAYERS; ++p) { if(pc->type == CTLT_NUMERIC) P_GetControlState(p, pc->id, NULL, NULL); else if(pc->type == CTLT_IMPULSE) P_GetImpulseControlState(p, pc->id); // Also clear the double click state. P_GetControlDoubleClick(p, pc->id); } } return true; } /** * Prints a list of the registered control descriptors. */ D_CMD(ListPlayerControls) { /* uint i, j; char buf[MAX_DESCRIPTOR_LENGTH+1]; Con_Message("Player Controls:\n"); for(i = 0; i < NUM_CONTROL_CLASSES; ++i) { controlclass_t *cClass = &ctlClass[i]; if(cClass->count > 0) { Con_Message("%i %s:\n", cClass->count, ctlClassNames[i][cClass->count > 1]); for(j = 0; j < cClass->count; ++j) { strncpy(buf, cClass->desc[j].name, sizeof(buf) - 1); strlwr(buf); buf[strlen(cClass->desc[j].name)] = 0; Con_Message(" %s\n", buf); } } }*/ return true; } D_CMD(Impulse) { int playerNum = consolePlayer; if(argc < 2 || argc > 3) { Con_Printf("Usage:\n %s (impulse-name)\n %s (impulse-name) (player-ordinal)\n", argv[0], argv[0]); return true; } if(argc == 3) { // Convert the local player number to an actual player console. playerNum = P_LocalToConsole(strtoul(argv[2], NULL, 10)); } P_ImpulseByName(playerNum, argv[1]); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_tex.c0000644000175000017500000010155211357170242022363 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_tex.c: Image manipulation algorithms. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_base.h" #include "de_console.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define MINTEXWIDTH 8 #define MINTEXHEIGHT 8 // TYPES ------------------------------------------------------------------- // posts are runs of non masked source pixels typedef struct { byte topdelta; // -1 is the last post in a column byte length; // length data bytes follows } post_t; // column_t is a list of 0 or more post_t, (byte)-1 terminated typedef post_t column_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static byte *scratchBuffer = NULL; static size_t scratchBufferSize = 0; // CODE -------------------------------------------------------------------- /** * Provides a persistent scratch buffer for use by texture manipulation * routines e.g. scaleLine(). */ static byte *GetScratchBuffer(size_t size) { // Need to enlarge? if(size > scratchBufferSize) { scratchBuffer = Z_Realloc(scratchBuffer, size, PU_STATIC); scratchBufferSize = size; } return scratchBuffer; } /** * Copies a rectangular region of the source buffer to the destination * buffer. Doesn't perform clipping, so be careful. * Yeah, 13 parameters... */ void pixBlt(byte *src, int srcWidth, int srcHeight, byte *dest, int destWidth, int destHeight, int alpha, int srcRegX, int srcRegY, int destRegX, int destRegY, int regWidth, int regHeight) { int y; // Y in the copy region. int srcNumPels = srcWidth * srcHeight; int destNumPels = destWidth * destHeight; for(y = 0; y < regHeight; ++y) // Copy line by line. { // The color index data. memcpy(dest + destRegX + (y + destRegY) * destWidth, src + srcRegX + (y + srcRegY) * srcWidth, regWidth); if(alpha) { // Alpha channel data. memcpy(dest + destNumPels + destRegX + (y + destRegY) * destWidth, src + srcNumPels + srcRegX + (y + srcRegY) * srcWidth, regWidth); } } } /** * in/out format: * 1 = palette indices * 2 = palette indices followed by alpha values * 3 = RGB * 4 = RGBA */ void GL_ConvertBuffer(int width, int height, int informat, int outformat, byte *in, byte *out, colorpaletteid_t palid, boolean gamma) { if(informat == outformat) { // No conversion necessary. memcpy(out, in, width * height * informat); return; } // Conversion from pal8(a) to RGB(A). if(informat <= 2 && outformat >= 3) { GL_PalettizeImage(out, outformat, R_GetColorPalette(palid), gamma, in, informat, width, height); } // Conversion from RGB(A) to pal8(a), using pal18To8. else if(informat >= 3 && outformat <= 2) { GL_QuantizeImageToPalette(out, outformat, R_GetColorPalette(palid), in, informat, width, height); } else if(informat == 3 && outformat == 4) { int i, numPixels = width * height, inSize = (informat == 2 ? 1 : informat), outSize = (outformat == 2 ? 1 : outformat); for(i = 0; i < numPixels; ++i, in += inSize, out += outSize) { memcpy(out, in, 3); out[3] = 0xff; // Opaque. } } } /** * Len is measured in out units. Comps is the number of components per * pixel, or rather the number of bytes per pixel (3 or 4). The strides must * be byte-aligned anyway, though; not in pixels. * * \fixme Probably could be optimized. */ static void scaleLine(byte *in, int inStride, byte *out, int outStride, int outLen, int inLen, int comps) { int i, c; float inToOutScale = outLen / (float) inLen; if(inToOutScale > 1) { // Magnification is done using linear interpolation. fixed_t inPosDelta = (FRACUNIT * (inLen - 1)) / (outLen - 1); fixed_t inPos = inPosDelta; byte *col1, *col2; int weight, invWeight; // The first pixel. memcpy(out, in, comps); out += outStride; // Step at each out pixel between the first and last ones. for(i = 1; i < outLen - 1; ++i, out += outStride, inPos += inPosDelta) { col1 = in + (inPos >> FRACBITS) * inStride; col2 = col1 + inStride; weight = inPos & 0xffff; invWeight = 0x10000 - weight; out[0] = (byte)((col1[0] * invWeight + col2[0] * weight) >> 16); out[1] = (byte)((col1[1] * invWeight + col2[1] * weight) >> 16); out[2] = (byte)((col1[2] * invWeight + col2[2] * weight) >> 16); if(comps == 4) out[3] = (byte)((col1[3] * invWeight + col2[3] * weight) >> 16); } // The last pixel. memcpy(out, in + (inLen - 1) * inStride, comps); } else if(inToOutScale < 1) { // Minification needs to calculate the average of each of // the pixels contained by the out pixel. uint cumul[4] = { 0, 0, 0, 0 }, count = 0; int outpos = 0; for(i = 0; i < inLen; ++i, in += inStride) { if((int) (i * inToOutScale) != outpos) { outpos = (int) (i * inToOutScale); for(c = 0; c < comps; ++c) { out[c] = (byte)(cumul[c] / count); cumul[c] = 0; } count = 0; out += outStride; } for(c = 0; c < comps; ++c) cumul[c] += in[c]; count++; } // Fill in the last pixel, too. if(count) for(c = 0; c < comps; ++c) out[c] = (byte)(cumul[c] / count); } else { // No need for scaling. if(comps == 3) { for(i = outLen; i > 0; --i, out += outStride, in += inStride) { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; } } else if(comps == 4) { for(i = outLen; i > 0; i--, out += outStride, in += inStride) { out[0] = in[0]; out[1] = in[1]; out[2] = in[2]; out[3] = in[3]; } } } } void GL_ScaleBuffer32(byte *in, int inWidth, int inHeight, byte *out, int outWidth, int outHeight, int comps) { int i; int stride; uint inOffsetSize, outOffsetSize; byte *inOff, *outOff; byte *buffer; buffer = GetScratchBuffer(outWidth * inHeight * comps); // First scale horizontally, to outWidth, into the temporary buffer. inOff = in; outOff = buffer; inOffsetSize = inWidth * comps; outOffsetSize = outWidth * comps; for(i = 0; i < inHeight; ++i, inOff += inOffsetSize, outOff += outOffsetSize) { scaleLine(inOff, comps, outOff, comps, outWidth, inWidth, comps); } // Then scale vertically, to outHeight, into the out buffer. inOff = buffer; outOff = out; stride = outWidth * comps; inOffsetSize = comps; outOffsetSize = comps; for(i = 0; i < outWidth; ++i, inOff += inOffsetSize, outOff += outOffsetSize) { scaleLine(inOff, stride, outOff, stride, outHeight, inHeight, comps); } } /** * Works within the given data, reducing the size of the picture to half * its original. Width and height must be powers of two. */ void GL_DownMipmap32(byte *in, int width, int height, int comps) { byte *out; int x, y, c, outW = width >> 1, outH = height >> 1; if(width == 1 && height == 1) { #if _DEBUG Con_Error("GL_DownMipmap32 can't be called for a 1x1 image.\n"); #endif return; } if(!outW || !outH) // Limited, 1x2|2x1 -> 1x1 reduction? { int outDim = (width > 1 ? outW : outH); out = in; for(x = 0; x < outDim; ++x, in += comps * 2) for(c = 0; c < comps; ++c, out++) *out = (byte)((in[c] + in[comps + c]) >> 1); } else // Unconstrained, 2x2 -> 1x1 reduction? { out = in; for(y = 0; y < outH; ++y, in += width * comps) for(x = 0; x < outW; ++x, in += comps * 2) for(c = 0; c < comps; ++c, out++) *out = (byte)((in[c] + in[comps + c] + in[comps * width + c] + in[comps * (width + 1) + c]) >> 2); } } /** * Determine the optimal size for a texture. Usually the dimensions are * scaled upwards to the next power of two. * * @param noStretch If @c true, the stretching can be skipped. * @param isMipMapped If @c true, we will require mipmaps (this has * an affect on the optimal size). */ boolean GL_OptimalSize(int width, int height, int *optWidth, int *optHeight, boolean noStretch, boolean isMipMapped) { if(GL_state.textureNonPow2 && !isMipMapped) { *optWidth = width; *optHeight = height; } else if(noStretch) { *optWidth = M_CeilPow2(width); *optHeight = M_CeilPow2(height); // MaxTexSize may prevent using noStretch. if(*optWidth > GL_state.maxTexSize || *optHeight > GL_state.maxTexSize) { noStretch = false; } } else { // Determine the most favorable size for the texture. if(texQuality == TEXQ_BEST) // The best quality. { // At the best texture quality *opt, all textures are // sized *upwards*, so no details are lost. This takes // more memory, but naturally looks better. *optWidth = M_CeilPow2(width); *optHeight = M_CeilPow2(height); } else if(texQuality == 0) { // At the lowest quality, all textures are sized down // to the nearest power of 2. *optWidth = M_FloorPow2(width); *optHeight = M_FloorPow2(height); } else { // At the other quality *opts, a weighted rounding // is used. *optWidth = M_WeightPow2(width, 1 - texQuality / (float) TEXQ_BEST); *optHeight = M_WeightPow2(height, 1 - texQuality / (float) TEXQ_BEST); } } // Hardware limitations may force us to modify the preferred // texture size. if(*optWidth > GL_state.maxTexSize) *optWidth = GL_state.maxTexSize; if(*optHeight > GL_state.maxTexSize) *optHeight = GL_state.maxTexSize; // Some GL drivers seem to have problems with VERY small textures. if(*optWidth < MINTEXWIDTH) *optWidth = MINTEXWIDTH; if(*optHeight < MINTEXHEIGHT) *optHeight = MINTEXHEIGHT; if(ratioLimit) { if(*optWidth > *optHeight) // Wide texture. { if(*optHeight < *optWidth / ratioLimit) *optHeight = *optWidth / ratioLimit; } else // Tall texture. { if(*optWidth < *optHeight / ratioLimit) *optWidth = *optHeight / ratioLimit; } } return noStretch; } /** * Modified to allow taller masked textures - GMJ Aug 2002 * * Warning: The buffer must have room for the new alpha data! * * @param buffer The destination buffer to draw the patch in to. * @param texwidth Width of the dst buffer in pixels. * @param texheight Height of the dst buffer in pixels. * @param patch Ptr to the patch structure to draw to the dst buffer. * @param origx X coordinate in the dst buffer to draw the patch too. * @param origy Y coordinate in the dst buffer to draw the patch too. * @param maskZero Used with sky textures. * @param checkForAlpha If @c true, the composited image will be * checked for alpha pixels and will return accordingly * if present. * * @return If @c checkForAlpha == false,, will return * @c false,. Else, @c true, if the * buffer really has alpha information. */ int DrawRealPatch(byte* buffer, int texwidth, int texheight, const lumppatch_t* patch, int origx, int origy, boolean maskZero, boolean checkForAlpha) { int count, col = 0; int x = origx, y, top; // Keep track of pos (clipping). int w = SHORT(patch->width); size_t bufsize = texwidth * texheight; const column_t* column; const byte* source; byte* dest1, *dest2, *destTop = buffer + origx, *destAlphaTop = buffer + origx + bufsize; for(; col < w; ++col, destTop++, destAlphaTop++, ++x) { column = (const column_t*) ((const byte*) patch + LONG(patch->columnOfs[col])); top = -1; // Step through the posts in a column while(column->topdelta != 0xff) { source = (byte *) column + 3; if(x < 0 || x >= texwidth) break; // Out of bounds. if(column->topdelta <= top) top += column->topdelta; else top = column->topdelta; if((count = column->length) > 0) { y = origy + top; dest1 = destTop + y * texwidth; dest2 = destAlphaTop + y * texwidth; while(count--) { byte palidx = *source++; // Is the destination within bounds? if(y >= 0 && y < texheight) { if(!maskZero || palidx) *dest1 = palidx; if(maskZero) *dest2 = (palidx ? 0xff : 0); else *dest2 = 0xff; } // One row down. dest1 += texwidth; dest2 += texwidth; y++; } } column = (column_t *) ((byte *) column + column->length + 4); } } if(checkForAlpha) { int i; boolean allowSingleAlpha = (texwidth < 128 || texheight < 128); // Scan through the RGBA buffer and check for sub-0xff alpha. source = buffer + texwidth * texheight; for(i = 0, count = 0; i < texwidth * texheight; ++i) { if(source[i] < 0xff) { //----- ----- // 'Small' textures tolerate no alpha. if(allowSingleAlpha) return true; // Big ones can have a single alpha pixel (ZZZFACE3!). if(count++ > 1) return true; // Has alpha data. //----- ----- } } } return false; // Doesn't have alpha data. } /** * Translate colors in the specified patch. */ void GL_TranslatePatch(lumppatch_t *patch, byte *transTable) { int count; int col = 0; column_t *column; byte *source; int w = SHORT(patch->width); for(; col < w; ++col) { column = (column_t *) ((byte *) patch + LONG(patch->columnOfs[col])); // Step through the posts in a column while(column->topdelta != 0xff) { source = (byte *) column + 3; count = column->length; while(count--) { *source = transTable[*source]; source++; } column = (column_t *) ((byte *) column + column->length + 4); } } } /** * Converts the image data to grayscale luminance in-place. */ void GL_ConvertToLuminance(image_t *image) { int p, total = image->width * image->height; byte *ptr = image->pixels; if(image->pixelSize == 1) { // No need to convert anything. return; } // Average the RGB colors. for(p = 0; p < total; ++p, ptr += image->pixelSize) { image->pixels[p] = (ptr[0] + ptr[1] + ptr[2]) / 3; } image->pixelSize = 1; } void GL_ConvertToAlpha(image_t *image, boolean makeWhite) { int p, total = image->width * image->height; GL_ConvertToLuminance(image); for(p = 0; p < total; ++p) { // Move the average color to the alpha channel, make the // actual color white. image->pixels[total + p] = image->pixels[p]; if(makeWhite) image->pixels[p] = 255; } image->pixelSize = 2; } boolean ImageHasAlpha(image_t *img) { uint i, size; boolean hasAlpha = false; byte *in; if(img->pixelSize == 4) { size = img->width * img->height; for(i = 0, in = img->pixels; i < size; ++i, in += 4) if(in[3] < 255) { hasAlpha = true; break; } } return hasAlpha; } int LineAverageRGB(byte *imgdata, int width, int height, int line, byte *rgb, byte *palette, boolean hasAlpha) { byte *start = imgdata + width * line; byte *alphaStart = start + width * height; int i, c, count = 0; int integerRGB[3] = { 0, 0, 0 }; byte col[3]; for(i = 0; i < width; ++i) { // Not transparent? if(alphaStart[i] > 0 || !hasAlpha) { count++; // Ignore the gamma level. memcpy(col, palette + 3 * start[i], 3); for(c = 0; c < 3; ++c) integerRGB[c] += col[c]; } } // All transparent? Sorry... if(!count) return 0; // We're going to make it! for(c = 0; c < 3; ++c) rgb[c] = (byte) (integerRGB[c] / count); return 1; // Successful. } /** * Fills the empty pixels with reasonable color indices in order to get rid * of black outlines caused by texture filtering. * * \fixme Not a very efficient algorithm... */ void ColorOutlines(byte *buffer, int width, int height) { int i, k, a, b; byte *ptr; const int numpels = width * height; for(k = 0; k < height; ++k) for(i = 0; i < width; ++i) // Solid pixels spread around... if(buffer[numpels + i + k * width]) { for(b = -1; b <= 1; ++b) for(a = -1; a <= 1; ++a) { // First check that the pixel is OK. if((!a && !b) || i + a < 0 || k + b < 0 || i + a >= width || k + b >= height) continue; ptr = buffer + i + a + (k + b) * width; if(!ptr[numpels]) // An alpha pixel? *ptr = buffer[i + k * width]; } } } /** * The given RGB color is scaled uniformly so that the highest component * becomes one. */ static void amplify(float *rgb) { int i; float max = 0; for(i = 0; i < 3; ++i) if(rgb[i] > max) max = rgb[i]; if(!max || max == 1) return; if(max) { for(i = 0; i < 3; ++i) rgb[i] = rgb[i] / max; } } /** * Used by flares and dynamic lights. The resulting average color is * amplified to be as bright as possible. */ void averageColorIdx(rgbcol_t col, byte* data, int w, int h, colorpaletteid_t palid, boolean hasAlpha) { int i; uint count; const int numpels = w * h; byte* alphaStart = data + numpels; DGLubyte rgbUBV[3]; float r, g, b; DGLuint pal = R_GetColorPalette(palid); // First clear them. for(i = 0; i < 3; ++i) col[i] = 0; r = g = b = count = 0; for(i = 0; i < numpels; ++i) { if(!hasAlpha || alphaStart[i]) { count++; GL_GetColorPaletteRGB(pal, rgbUBV, data[i]); // Ignore the gamma level. r += rgbUBV[CR] / 255.f; g += rgbUBV[CG] / 255.f; b += rgbUBV[CB] / 255.f; } } // All transparent? Sorry... if(!count) return; col[0] = r / count; col[1] = g / count; col[2] = b / count; // Make it glow (average colors are used with flares and dynlights). amplify(col); } int lineAverageColorIdx(rgbcol_t col, byte* data, int w, int h, int line, colorpaletteid_t palid, boolean hasAlpha) { int i; uint count; const int numpels = w * h; byte* start = data + w * line; byte* alphaStart = data + numpels + w * line; DGLubyte rgbUBV[3]; float r, g, b; DGLuint pal = R_GetColorPalette(palid); // First clear them. for(i = 0; i < 3; ++i) col[i] = 0; r = g = b = count = 0; for(i = 0; i < w; ++i) { if(!hasAlpha || alphaStart[i]) { count++; GL_GetColorPaletteRGB(pal, rgbUBV, start[i]); // Ignore the gamma level. r += rgbUBV[CR] / 255.f; g += rgbUBV[CG] / 255.f; b += rgbUBV[CB] / 255.f; } } // All transparent? Sorry... if(!count) return 0; col[0] = r / count; col[1] = g / count; col[2] = b / count; return 1; // Successful. } int lineAverageColorRGB(rgbcol_t col, byte* data, int w, int h, int line) { int i; float culmul[3]; for(i = 0; i < 3; ++i) culmul[i] = 0; *data += 3 * w * line; for(i = 0; i < w; ++i) { culmul[CR] += (*data++) / 255.f; culmul[CG] += (*data++) / 255.f; culmul[CB] += (*data++) / 255.f; } col[CR] = culmul[CR] / w; col[CG] = culmul[CG] / w; col[CB] = culmul[CB] / w; return 1; // Successful. } void averageColorRGB(rgbcol_t col, byte *data, int w, int h) { uint i; const uint numpels = w * h; float cumul[3]; if(!numpels) return; for(i = 0; i < 3; ++i) cumul[i] = 0; for(i = 0; i < numpels; ++i) { cumul[0] += (*data++) / 255.f; cumul[1] += (*data++) / 255.f; cumul[2] += (*data++) / 255.f; } for(i = 0; i < 3; ++i) col[i] = cumul[i] / numpels; amplify(col); } /** * Calculates a clip region for the buffer that excludes alpha pixels. * NOTE: Cross spread from bottom > top, right > left (inside out). * * @param buffer Image data to be processed. * @param width Width of the src buffer. * @param height Height of the src buffer. * @param pixelsize Pixelsize of the src buffer. Handles 1 (==2), 3 and 4. * * @returnval region Ptr to int[4] to write the resultant region to. */ void GL_GetNonAlphaRegion(byte *buffer, int width, int height, int pixelsize, int *region) { int k, i; int myregion[4]; byte *src = buffer; byte *alphasrc = NULL; myregion[0] = width; myregion[1] = 0; myregion[2] = height; myregion[3] = 0; if(pixelsize == 1) // In paletted mode, the alpha channel follows the actual image. alphasrc = buffer + width * height; // \todo This is not very efficent. Better to use an algorithm which works on full rows and full columns. for(k = 0; k < height; ++k) for(i = 0; i < width; ++i, src += pixelsize, alphasrc++) { // Alpha pixels don't count. if(pixelsize == 1) { if(*alphasrc < 255) continue; } else if(pixelsize == 4) { if(src[3] < 255) continue; } if(i < myregion[0]) myregion[0] = i; if(i > myregion[1]) myregion[1] = i; if(k < myregion[2]) myregion[2] = k; if(k > myregion[3]) myregion[3] = k; } memcpy(region, myregion, sizeof(myregion)); } /** * Calculates the properties of a dynamic light that the given sprite frame * casts. Crop a boundary around the image to remove excess alpha'd pixels * from adversely affecting the calculation. * Handles pixel sizes; 1 (==2), 3 and 4. */ void GL_CalcLuminance(byte* buffer, int width, int height, int pixelSize, colorpaletteid_t palid, float* brightX, float* brightY, rgbcol_t* color, float* lumSize) { DGLuint pal = (pixelSize == 1? R_GetColorPalette(palid) : 0); int i, k, x, y, c, cnt = 0, posCnt = 0; byte rgb[3], *src, *alphaSrc = NULL; int limit = 0xc0, posLimit = 0xe0, colLimit = 0xc0; int avgCnt = 0, lowCnt = 0; float average[3], lowAvg[3]; int region[4]; for(i = 0; i < 3; ++i) { average[i] = 0; lowAvg[i] = 0; } src = buffer; if(pixelSize == 1) { // In paletted mode, the alpha channel follows the actual image. alphaSrc = buffer + width * height; } GL_GetNonAlphaRegion(buffer, width, height, pixelSize, ®ion[0]); if(region[2] > 0) { src += pixelSize * width * region[2]; alphaSrc += width * region[2]; } (*brightX) = (*brightY) = 0; for(k = region[2], y = 0; k < region[3] + 1; ++k, ++y) { if(region[0] > 0) { src += pixelSize * region[0]; alphaSrc += region[0]; } for(i = region[0], x = 0; i < region[1] + 1; ++i, ++x, src += pixelSize, alphaSrc++) { // Alpha pixels don't count. if(pixelSize == 1) { if(*alphaSrc < 255) continue; } else if(pixelSize == 4) { if(src[3] < 255) continue; } // Bright enough? if(pixelSize == 1) { GL_GetColorPaletteRGB(pal, (DGLubyte*) rgb, *src); } else if(pixelSize >= 3) { memcpy(rgb, src, 3); } if(rgb[0] > posLimit || rgb[1] > posLimit || rgb[2] > posLimit) { // This pixel will participate in calculating the average // center point. (*brightX) += x; (*brightY) += y; posCnt++; } // Bright enough to affect size? if(rgb[0] > limit || rgb[1] > limit || rgb[2] > limit) cnt++; // How about the color of the light? if(rgb[0] > colLimit || rgb[1] > colLimit || rgb[2] > colLimit) { avgCnt++; for(c = 0; c < 3; ++c) average[c] += rgb[c] / 255.f; } else { lowCnt++; for(c = 0; c < 3; ++c) lowAvg[c] += rgb[c] / 255.f; } } if(region[1] < width - 1) { src += pixelSize * (width - 1 - region[1]); alphaSrc += (width - 1 - region[1]); } } if(!posCnt) { (*brightX) = region[0] + ((region[1] - region[0]) / 2.0f); (*brightY) = region[2] + ((region[3] - region[2]) / 2.0f); } else { // Get the average. (*brightX) /= posCnt; (*brightY) /= posCnt; // Add the origin offset. (*brightX) += region[0]; (*brightY) += region[2]; } // Center on the middle of the brightest pixel. (*brightX) += .5f; (*brightY) += .5f; // The color. if(!avgCnt) { if(!lowCnt) { // Doesn't the thing have any pixels??? Use white light. for(c = 0; c < 3; ++c) (*color)[c] = 1; } else { // Low-intensity color average. for(c = 0; c < 3; ++c) (*color)[c] = lowAvg[c] / lowCnt; } } else { // High-intensity color average. for(c = 0; c < 3; ++c) (*color)[c] = average[c] / avgCnt; } #ifdef _DEBUG VERBOSE2(Con_Message("GL_CalcLuminance: " " width %dpx, height %dpx, bits %d\n" " cell region X[%d, %d] Y[%d, %d]\n" " flare X= %g Y=%g %s\n" " flare RGB[%g, %g, %g] %s\n", width, height, pixelSize, region[0], region[1], region[2], region[3], (*brightX), (*brightY), (posCnt? "(average)" : "(center)"), (*color)[0], (*color)[1], (*color)[2], (avgCnt? "(hi-intensity avg)" : lowCnt? "(low-intensity avg)" : "(white light)"))); #endif // Amplify color. amplify(*color); // How about the size of the light source? *lumSize = MIN_OF(((2 * cnt + avgCnt) / 3.0f / 70.0f), 1); } /** * @return @c true, if the given color is either * (0,255,255) or (255,0,255). */ static boolean ColorKey(byte *color) { return color[CB] == 0xff && ((color[CR] == 0xff && color[CG] == 0) || (color[CR] == 0 && color[CG] == 0xff)); } /** * Buffer must be RGBA. Doesn't touch the non-keyed pixels. */ static void DoColorKeying(byte *rgbaBuf, unsigned int width) { uint i; for(i = 0; i < width; ++i, rgbaBuf += 4) if(ColorKey(rgbaBuf)) rgbaBuf[3] = rgbaBuf[2] = rgbaBuf[1] = rgbaBuf[0] = 0; } /** * Take the input buffer and convert to color keyed. A new buffer may be * needed if the input buffer has three color components. * * @return If the in buffer wasn't large enough will return a * ptr to the newly allocated buffer which must be * freed with M_Free(). */ byte *GL_ApplyColorKeying(byte *buf, uint pixelSize, uint width, uint height) { uint i; byte *ckdest, *in, *out; const uint numpels = width * height; // We must allocate a new buffer if the loaded image has three // color components. if(pixelSize < 4) { ckdest = M_Malloc(4 * width * height); for(in = buf, out = ckdest, i = 0; i < numpels; ++i, in += pixelSize, out += 4) { if(ColorKey(in)) memset(out, 0, 4); // Totally black. else { memcpy(out, in, 3); // The color itself. out[CA] = 255; // Opaque. } } return ckdest; } else // We can do the keying in-buffer. { // This preserves the alpha values of non-keyed pixels. for(i = 0; i < height; ++i) DoColorKeying(buf + 4 * i * width, height); } return NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_maputil.c0000644000175000017500000011064511357170242023076 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputil.c: Map Utility Routines */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_play.h" #include "de_refresh.h" #include "de_misc.h" #include "p_bmap.h" // MACROS ------------------------------------------------------------------ #define ORDER(x,y,a,b) ( (x)<(y)? ((a)=(x),(b)=(y)) : ((b)=(x),(a)=(y)) ) // Linkstore is list of pointers gathered when iterating stuff. // This is pretty much the only way to avoid *all* potential problems // caused by callback routines behaving badly (moving or destroying // mobjs). The idea is to get a snapshot of all the objects being // iterated before any callbacks are called. The hardcoded limit is // a drag, but I'd like to see you iterating 2048 mobjs/lines in one block. #define MAXLINKED 2048 #define DO_LINKS(it, end) for(it = linkstore; it < end; it++) \ if(!func(*it, data)) return false; // TYPES ------------------------------------------------------------------- typedef struct { mobj_t* mo; vec2_t box[2]; } linelinker_data_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float opentop, openbottom, openrange; float lowfloor; divline_t traceLOS; boolean earlyout; int ptflags; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- float P_AccurateDistanceFixed(fixed_t dx, fixed_t dy) { float fx = FIX2FLT(dx), fy = FIX2FLT(dy); return (float) sqrt(fx * fx + fy * fy); } float P_AccurateDistance(float dx, float dy) { return (float) sqrt(dx * dx + dy * dy); } /** * Gives an estimation of distance (not exact). */ float P_ApproxDistance(float dx, float dy) { dx = fabs(dx); dy = fabs(dy); return dx + dy - ((dx < dy ? dx : dy) / 2); } /** * Gives an estimation of 3D distance (not exact). * The Z axis aspect ratio is corrected. */ float P_ApproxDistance3(float dx, float dy, float dz) { return P_ApproxDistance(P_ApproxDistance(dx, dy), dz * 1.2f); } /** * Returns a two-component float unit vector parallel to the line. */ void P_LineUnitVector(linedef_t* line, float* unitvec) { float len = M_ApproxDistancef(line->dX, line->dY); if(len) { unitvec[VX] = line->dX / len; unitvec[VY] = line->dY / len; } else { unitvec[VX] = unitvec[VY] = 0; } } /** * Either end or fixpoint must be specified. The distance is measured * (approximately) in 3D. Start must always be specified. */ float P_MobjPointDistancef(mobj_t* start, mobj_t* end, float* fixpoint) { if(!start) return 0; if(end) { // Start -> end. return M_ApproxDistancef(end->pos[VZ] - start->pos[VZ], M_ApproxDistancef(end->pos[VX] - start->pos[VX], end->pos[VY] - start->pos[VY])); } if(fixpoint) { float sp[3]; sp[VX] = start->pos[VX]; sp[VY] = start->pos[VY], sp[VZ] = start->pos[VZ]; return M_ApproxDistancef(fixpoint[VZ] - sp[VZ], M_ApproxDistancef(fixpoint[VX] - sp[VX], fixpoint[VY] - sp[VY])); } return 0; } /** * Lines start, end and fdiv must intersect. */ #ifdef _MSC_VER # pragma optimize("g", off) #endif float P_FloatInterceptVertex(fvertex_t* start, fvertex_t* end, fdivline_t* fdiv, fvertex_t* inter) { float ax = start->pos[VX], ay = start->pos[VY]; float bx = end->pos[VX], by = end->pos[VY]; float cx = fdiv->pos[VX], cy = fdiv->pos[VY]; float dx = cx + fdiv->dX, dy = cy + fdiv->dY; /* (YA-YC)(XD-XC)-(XA-XC)(YD-YC) r = ----------------------------- (eqn 1) (XB-XA)(YD-YC)-(YB-YA)(XD-XC) */ float r = ((ay - cy) * (dx - cx) - (ax - cx) * (dy - cy)) / ((bx - ax) * (dy - cy) - (by - ay) * (dx - cx)); /* XI = XA+r(XB-XA) YI = YA+r(YB-YA) */ inter->pos[VX] = ax + r * (bx - ax); inter->pos[VY] = ay + r * (by - ay); return r; } /** * @return Non-zero if the point is on the right side of the * specified line. */ int P_PointOnLineSide(float x, float y, float lX, float lY, float lDX, float lDY) { /* (AY-CY)(BX-AX)-(AX-CX)(BY-AY) s = ----------------------------- L**2 If s<0 C is left of AB (you can just check the numerator) If s>0 C is right of AB If s=0 C is on AB */ return ((lY - y) * lDX - (lX - x) * lDY >= 0); } #ifdef _MSC_VER # pragma optimize("", on) #endif /** * Determines on which side of dline the point is. Returns true if the * point is on the line or on the right side. */ int P_PointOnDivLineSidef(fvertex_t* pnt, fdivline_t* dline) { return !P_PointOnLineSide(pnt->pos[VX], pnt->pos[VY], dline->pos[VX], dline->pos[VY], dline->dX, dline->dY); } /** * @return Non-zero if the point is on the right side of the * specified line. */ int P_PointOnLinedefSide(float x, float y, const linedef_t* line) { return !P_PointOnLineSide(x, y, line->L_v1pos[VX], line->L_v1pos[VY], line->dX, line->dY); } /** * Where is the given point in relation to the line. * * @param pointX X coordinate of the point. * @param pointY Y coordinate of the point. * @param lineDX X delta of the line. * @param lineDY Y delta of the line. * @param linePerp Perpendicular d of the line. * @param lineLength Length of the line. * * @return @c <0= on left side. * @c 0= intersects. * @c >0= on right side. */ int P_PointOnLinedefSide2(double pointX, double pointY, double lineDX, double lineDY, double linePerp, double lineLength, double epsilon) { double perp = M_PerpDist(lineDX, lineDY, linePerp, lineLength, pointX, pointY); if(fabs(perp) <= epsilon) return 0; return (perp < 0? -1 : +1); } /** * Check the spatial relationship between the given box and a partitioning * line. * * @param bbox Ptr to the box being tested. * @param lineSX X coordinate of the start of the line. * @param lineSY Y coordinate of the end of the line. * @param lineDX X delta of the line (slope). * @param lineDY Y delta of the line (slope). * @param linePerp Perpendicular d of the line. * @param lineLength Length of the line. * @param epsilon Points within this distance will be considered equal. * * @return @c <0= bbox is wholly on the left side. * @c 0= line intersects bbox. * @c >0= bbox wholly on the right side. */ int P_BoxOnLineSide3(const int bbox[4], double lineSX, double lineSY, double lineDX, double lineDY, double linePerp, double lineLength, double epsilon) { #define IFFY_LEN 4.0 int p1, p2; double x1 = (double)bbox[BOXLEFT] - IFFY_LEN * 1.5; double y1 = (double)bbox[BOXBOTTOM] - IFFY_LEN * 1.5; double x2 = (double)bbox[BOXRIGHT] + IFFY_LEN * 1.5; double y2 = (double)bbox[BOXTOP] + IFFY_LEN * 1.5; if(lineDX == 0) { // Horizontal. p1 = (x1 > lineSX? +1 : -1); p2 = (x2 > lineSX? +1 : -1); if(lineDY < 0) { p1 = -p1; p2 = -p2; } } else if(lineDY == 0) { // Vertical. p1 = (y1 < lineSY? +1 : -1); p2 = (y2 < lineSY? +1 : -1); if(lineDX < 0) { p1 = -p1; p2 = -p2; } } else if(lineDX * lineDY > 0) { // Positive slope. p1 = P_PointOnLinedefSide2(x1, y2, lineDX, lineDY, linePerp, lineLength, epsilon); p2 = P_PointOnLinedefSide2(x2, y1, lineDX, lineDY, linePerp, lineLength, epsilon); } else { // Negative slope. p1 = P_PointOnLinedefSide2(x1, y1, lineDX, lineDY, linePerp, lineLength, epsilon); p2 = P_PointOnLinedefSide2(x2, y2, lineDX, lineDY, linePerp, lineLength, epsilon); } if(p1 == p2) return p1; return 0; #undef IFFY_LEN } /** * Considers the line to be infinite. * * @return @c 0 = completely in front of the line. * @return @c 1 = completely behind the line. * @c -1 = box crosses the line. */ int P_BoxOnLineSide2(float xl, float xh, float yl, float yh, const linedef_t* ld) { int a = 0, b = 0; switch(ld->slopeType) { default: // Shut up compiler. case ST_HORIZONTAL: a = yh > ld->L_v1pos[VY]; b = yl > ld->L_v1pos[VY]; if(ld->dX < 0) { a ^= 1; b ^= 1; } break; case ST_VERTICAL: a = xh < ld->L_v1pos[VX]; b = xl < ld->L_v1pos[VX]; if(ld->dY < 0) { a ^= 1; b ^= 1; } break; case ST_POSITIVE: a = P_PointOnLinedefSide(xl, yh, ld); b = P_PointOnLinedefSide(xh, yl, ld); break; case ST_NEGATIVE: a = P_PointOnLinedefSide(xh, yh, ld); b = P_PointOnLinedefSide(xl, yl, ld); break; } if(a == b) return a; return -1; } int P_BoxOnLineSide(const float* box, const linedef_t* ld) { return P_BoxOnLineSide2(box[BOXLEFT], box[BOXRIGHT], box[BOXBOTTOM], box[BOXTOP], ld); } /** * @return @c 0 if point is in front of the line, else @c 1. */ int P_PointOnDivlineSide(float fx, float fy, const divline_t* line) { fixed_t x = FLT2FIX(fx); fixed_t y = FLT2FIX(fy); if(!line->dX) { return (x <= line->pos[VX])? line->dY > 0 : line->dY < 0; } else if(!line->dY) { return (y <= line->pos[VY])? line->dX < 0 : line->dX > 0; } else { fixed_t dX = x - line->pos[VX]; fixed_t dY = y - line->pos[VY]; // Try to quickly decide by comparing signs. if((line->dY ^ line->dX ^ dX ^ dY) & 0x80000000) { // Left is negative. return ((line->dY ^ dX) & 0x80000000)? 1 : 0; } else { // if left >= right return 1 else 0. return FixedMul(dY >> 8, line->dX >> 8) >= FixedMul(line->dY >> 8, dX >> 8); } } } void P_MakeDivline(const linedef_t* li, divline_t* dl) { const vertex_t* vtx = li->L_v1; dl->pos[VX] = FLT2FIX(vtx->V_pos[VX]); dl->pos[VY] = FLT2FIX(vtx->V_pos[VY]); dl->dX = FLT2FIX(li->dX); dl->dY = FLT2FIX(li->dY); } /** * @return Fractional intercept point along the first divline. */ float P_InterceptVector(const divline_t* v2, const divline_t* v1) { float frac = 0; fixed_t den = FixedMul(v1->dY >> 8, v2->dX) - FixedMul(v1->dX >> 8, v2->dY); if(den) { fixed_t f; f = FixedMul((v1->pos[VX] - v2->pos[VX]) >> 8, v1->dY) + FixedMul((v2->pos[VY] - v1->pos[VY]) >> 8, v1->dX); f = FixedDiv(f, den); frac = FIX2FLT(f); } return frac; } /** * Sets opentop and openbottom to the window through a two sided line. * \fixme $nplanes. */ void P_LineOpening(linedef_t* linedef) { sector_t* front, *back; if(!linedef->L_backside) { // Single sided line. openrange = 0; return; } front = linedef->L_frontsector; back = linedef->L_backsector; if(front->SP_ceilheight < back->SP_ceilheight) opentop = front->SP_ceilheight; else opentop = back->SP_ceilheight; if(front->SP_floorheight > back->SP_floorheight) { openbottom = front->SP_floorheight; lowfloor = back->SP_floorheight; } else { openbottom = back->SP_floorheight; lowfloor = front->SP_floorheight; } openrange = opentop - openbottom; } /** * Two links to update: * 1) The link to us from the previous node (sprev, always set) will * be modified to point to the node following us. * 2) If there is a node following us, set its sprev pointer to point * to the pointer that points back to it (our sprev, just modified). */ boolean P_UnlinkFromSector(mobj_t* mo) { if(!IS_SECTOR_LINKED(mo)) return false; if((*mo->sPrev = mo->sNext)) mo->sNext->sPrev = mo->sPrev; // Not linked any more. mo->sNext = NULL; mo->sPrev = NULL; return true; } /** * Unlinks the mobj from all the lines it's been linked to. Can be called * without checking that the list does indeed contain lines. */ boolean P_UnlinkFromLines(mobj_t* mo) { linknode_t* tn = mobjNodes->nodes; nodeindex_t nix; // Try unlinking from lines. if(!mo->lineRoot) return false; // A zero index means it's not linked. // Unlink from each line. for(nix = tn[mo->lineRoot].next; nix != mo->lineRoot; nix = tn[nix].next) { // Data is the linenode index that corresponds this mobj. NP_Unlink(lineNodes, tn[nix].data); // We don't need these nodes any more, mark them as unused. // Dismissing is a macro. NP_Dismiss(lineNodes, tn[nix].data); NP_Dismiss(mobjNodes, nix); } // The mobj no longer has a line ring. NP_Dismiss(mobjNodes, mo->lineRoot); mo->lineRoot = 0; return true; } /** * Unlinks a mobj from everything it has been linked to. * * @param mo Ptr to the mobj to be unlinked. * @return DDLINK_* flags denoting what the mobj was unlinked * from (in case we need to re-link). */ int P_MobjUnlink(mobj_t* mo) { int links = 0; if(P_UnlinkFromSector(mo)) links |= DDLINK_SECTOR; if(P_BlockmapUnlinkMobj(BlockMap, mo)) links |= DDLINK_BLOCKMAP; if(!P_UnlinkFromLines(mo)) links |= DDLINK_NOLINE; return links; } /** * The given line might cross the mobj. If necessary, link the mobj into * the line's mobj link ring. */ boolean PIT_LinkToLines(linedef_t* ld, void* parm) { linelinker_data_t* data = parm; nodeindex_t nix; if(data->box[1][VX] <= ld->bBox[BOXLEFT] || data->box[0][VX] >= ld->bBox[BOXRIGHT] || data->box[1][VY] <= ld->bBox[BOXBOTTOM] || data->box[0][VY] >= ld->bBox[BOXTOP]) // Bounding boxes do not overlap. return true; if(P_BoxOnLineSide2(data->box[0][VX], data->box[1][VX], data->box[0][VY], data->box[1][VY], ld) != -1) // Line does not cross the mobj's bounding box. return true; // One sided lines will not be linked to because a mobj // can't legally cross one. if(!ld->L_frontside || !ld->L_backside) return true; // No redundant nodes will be creates since this routine is // called only once for each line. // Add a node to the mobj's ring. NP_Link(mobjNodes, nix = NP_New(mobjNodes, ld), data->mo->lineRoot); // Add a node to the line's ring. Also store the linenode's index // into the mobjring's node, so unlinking is easy. NP_Link(lineNodes, mobjNodes->nodes[nix].data = NP_New(lineNodes, data->mo), linelinks[GET_LINE_IDX(ld)]); return true; } /** * \pre The mobj must be currently unlinked. */ void P_LinkToLines(mobj_t* mo) { linelinker_data_t data; vec2_t point; // Get a new root node. mo->lineRoot = NP_New(mobjNodes, NP_ROOT_NODE); // Set up a line iterator for doing the linking. data.mo = mo; V2_Set(point, mo->pos[VX] - mo->radius, mo->pos[VY] - mo->radius); V2_InitBox(data.box, point); V2_Set(point, mo->pos[VX] + mo->radius, mo->pos[VY] + mo->radius); V2_AddToBox(data.box, point); validCount++; P_AllLinesBoxIteratorv(data.box, PIT_LinkToLines, &data); } void P_MobjLinkToRing(mobj_t* mo, linkmobj_t** link) { linkmobj_t* tempLink; if(!(*link)) { // Create a new link at the current block cell. *link = Z_Malloc(sizeof(linkmobj_t), PU_MAP, 0); (*link)->next = NULL; (*link)->prev = NULL; (*link)->mobj = mo; return; } else { tempLink = *link; while(tempLink->next != NULL && tempLink->mobj != NULL) { tempLink = tempLink->next; } } if(tempLink->mobj == NULL) { tempLink->mobj = mo; return; } else { tempLink->next = Z_Malloc(sizeof(linkmobj_t), PU_MAP, 0); tempLink->next->next = NULL; tempLink->next->prev = tempLink; tempLink->next->mobj = mo; } } /** * Unlink the given mobj from the specified block ring (if indeed linked). * * @param mo Ptr to the mobj to unlink. * @return @c true, iff the mobj was linked to the ring and was * successfully unlinked. */ boolean P_MobjUnlinkFromRing(mobj_t* mo, linkmobj_t** list) { linkmobj_t* iter = *list; while(iter != NULL && iter->mobj != mo) { iter = iter->next; } if(iter != NULL) { iter->mobj = NULL; return true; // Mobj was unlinked. } return false; // Mobj was not linked. } /** * Links a mobj into both a block and a subsector based on it's (x,y). * Sets mobj->subsector properly. Calling with flags==0 only updates * the subsector pointer. Can be called without unlinking first. */ void P_MobjLink(mobj_t* mo, byte flags) { sector_t* sec; // Link into the sector. mo->subsector = R_PointInSubsector(mo->pos[VX], mo->pos[VY]); sec = mo->subsector->sector; if(flags & DDLINK_SECTOR) { // Unlink from the current sector, if any. if(mo->sPrev) P_UnlinkFromSector(mo); // Link the new mobj to the head of the list. // Prev pointers point to the pointer that points back to us. // (Which practically disallows traversing the list backwards.) if((mo->sNext = sec->mobjList)) mo->sNext->sPrev = &mo->sNext; *(mo->sPrev = &sec->mobjList) = mo; } // Link into blockmap? if(flags & DDLINK_BLOCKMAP) { // Unlink from the old block, if any. P_BlockmapUnlinkMobj(BlockMap, mo); P_BlockmapLinkMobj(BlockMap, mo); } // Link into lines. if(!(flags & DDLINK_NOLINE)) { // Unlink from any existing lines. P_UnlinkFromLines(mo); // Link to all contacted lines. P_LinkToLines(mo); } // If this is a player - perform addtional tests to see if they have // entered or exited the void. if(mo->dPlayer) { ddplayer_t* player = mo->dPlayer; player->inVoid = true; if(R_IsPointInSector2(player->mo->pos[VX], player->mo->pos[VY], player->mo->subsector->sector) && (player->mo->pos[VZ] < player->mo->subsector->sector->SP_ceilvisheight + 4 && player->mo->pos[VZ] > player->mo->subsector->sector->SP_floorvisheight + 4)) player->inVoid = false; } } /** * The callback function will be called once for each line that crosses * trough the object. This means all the lines will be two-sided. */ boolean P_MobjLinesIterator(mobj_t* mo, boolean (*func) (linedef_t*, void*), void* data) { void* linkstore[MAXLINKED]; void** end = linkstore, **it; nodeindex_t nix; linknode_t* tn = mobjNodes->nodes; if(!mo->lineRoot) return true; // No lines to process. for(nix = tn[mo->lineRoot].next; nix != mo->lineRoot; nix = tn[nix].next) *end++ = tn[nix].ptr; DO_LINKS(it, end); return true; } /** * Increment validCount before calling this routine. The callback function * will be called once for each sector the mobj is touching (totally or * partly inside). This is not a 3D check; the mobj may actually reside * above or under the sector. */ boolean P_MobjSectorsIterator(mobj_t* mo, boolean (*func) (sector_t*, void*), void* data) { void* linkstore[MAXLINKED]; void** end = linkstore, **it; nodeindex_t nix; linknode_t* tn = mobjNodes->nodes; linedef_t* ld; sector_t* sec; // Always process the mobj's own sector first. *end++ = sec = mo->subsector->sector; sec->validCount = validCount; // Any good lines around here? if(mo->lineRoot) { for(nix = tn[mo->lineRoot].next; nix != mo->lineRoot; nix = tn[nix].next) { ld = (linedef_t *) tn[nix].ptr; // All these lines are two-sided. Try front side. sec = ld->L_frontsector; if(sec->validCount != validCount) { *end++ = sec; sec->validCount = validCount; } // And then the back side. if(ld->L_backside) { sec = ld->L_backsector; if(sec->validCount != validCount) { *end++ = sec; sec->validCount = validCount; } } } } DO_LINKS(it, end); return true; } boolean P_LineMobjsIterator(linedef_t* line, boolean (*func) (mobj_t*, void*), void* data) { void* linkstore[MAXLINKED]; void** end = linkstore, **it; nodeindex_t root = linelinks[GET_LINE_IDX(line)], nix; linknode_t* ln = lineNodes->nodes; for(nix = ln[root].next; nix != root; nix = ln[nix].next) *end++ = ln[nix].ptr; DO_LINKS(it, end); return true; } /** * Increment validCount before using this. 'func' is called for each mobj * that is (even partly) inside the sector. This is not a 3D test, the * mobjs may actually be above or under the sector. * * (Lovely name; actually this is a combination of SectorMobjs and * a bunch of LineMobjs iterations.) */ boolean P_SectorTouchingMobjsIterator(sector_t* sector, boolean (*func) (mobj_t*, void*), void* data) { uint i; void* linkstore[MAXLINKED]; void** end = linkstore, **it; mobj_t* mo; linedef_t* li; nodeindex_t root, nix; linknode_t* ln = lineNodes->nodes; // First process the mobjs that obviously are in the sector. for(mo = sector->mobjList; mo; mo = mo->sNext) { if(mo->validCount == validCount) continue; mo->validCount = validCount; *end++ = mo; } // Then check the sector's lines. for(i = 0; i < sector->lineDefCount; ++i) { li = sector->lineDefs[i]; // Iterate all mobjs on the line. root = linelinks[GET_LINE_IDX(li)]; for(nix = ln[root].next; nix != root; nix = ln[nix].next) { mo = (mobj_t *) ln[nix].ptr; if(mo->validCount == validCount) continue; mo->validCount = validCount; *end++ = mo; } } DO_LINKS(it, end); return true; } boolean P_MobjsBoxIterator(const float box[4], boolean (*func) (mobj_t*, void*), void* data) { vec2_t bounds[2]; bounds[0][VX] = box[BOXLEFT]; bounds[0][VY] = box[BOXBOTTOM]; bounds[1][VX] = box[BOXRIGHT]; bounds[1][VY] = box[BOXTOP]; return P_MobjsBoxIteratorv(bounds, func, data); } boolean P_MobjsBoxIteratorv(const arvec2_t box, boolean (*func) (mobj_t*, void*), void* data) { uint blockBox[4]; P_BoxToBlockmapBlocks(BlockMap, blockBox, box); return P_BlockBoxMobjsIterator(BlockMap, blockBox, func, data); } boolean P_PolyobjsBoxIterator(const float box[4], boolean (*func) (struct polyobj_s*, void*), void* data) { vec2_t bounds[2]; bounds[0][VX] = box[BOXLEFT]; bounds[0][VY] = box[BOXBOTTOM]; bounds[1][VX] = box[BOXRIGHT]; bounds[1][VY] = box[BOXTOP]; return P_PolyobjsBoxIteratorv(bounds, func, data); } /** * The validCount flags are used to avoid checking polys that are marked in * multiple mapblocks, so increment validCount before the first call, then * make one or more calls to it. */ boolean P_PolyobjsBoxIteratorv(const arvec2_t box, boolean (*func) (struct polyobj_s*, void*), void* data) { uint blockBox[4]; // Blockcoords to check. P_BoxToBlockmapBlocks(BlockMap, blockBox, box); return P_BlockBoxPolyobjsIterator(BlockMap, blockBox, func, data); } boolean P_LinesBoxIterator(const float box[4], boolean (*func) (linedef_t*, void*), void* data) { vec2_t bounds[2]; bounds[0][VX] = box[BOXLEFT]; bounds[0][VY] = box[BOXBOTTOM]; bounds[1][VX] = box[BOXRIGHT]; bounds[1][VY] = box[BOXTOP]; return P_LinesBoxIteratorv(bounds, func, data); } boolean P_LinesBoxIteratorv(const arvec2_t box, boolean (*func) (linedef_t*, void*), void* data) { uint blockBox[4]; P_BoxToBlockmapBlocks(BlockMap, blockBox, box); return P_BlockBoxLinesIterator(BlockMap, blockBox, func, data); } /** * @return @c false, if the iterator func returns @c false. */ boolean P_SubsectorsBoxIterator(const float box[4], sector_t* sector, boolean (*func) (subsector_t*, void*), void* parm) { vec2_t bounds[2]; bounds[0][VX] = box[BOXLEFT]; bounds[0][VY] = box[BOXBOTTOM]; bounds[1][VX] = box[BOXRIGHT]; bounds[1][VY] = box[BOXTOP]; return P_SubsectorsBoxIteratorv(bounds, sector, func, parm); } /** * Same as the fixed-point version of this routine, but the bounding box * is specified using an vec2_t array (see m_vector.c). */ boolean P_SubsectorsBoxIteratorv(const arvec2_t box, sector_t* sector, boolean (*func) (subsector_t*, void*), void* data) { static int localValidCount = 0; uint blockBox[4]; // This is only used here. localValidCount++; // Blockcoords to check. P_BoxToBlockmapBlocks(SSecBlockMap, blockBox, box); return P_BlockBoxSubsectorsIterator(SSecBlockMap, blockBox, sector, box, localValidCount, func, data); } boolean P_PolyobjLinesBoxIterator(const float box[4], boolean (*func) (linedef_t*, void*), void* data) { vec2_t bounds[2]; bounds[0][VX] = box[BOXLEFT]; bounds[0][VY] = box[BOXBOTTOM]; bounds[1][VX] = box[BOXRIGHT]; bounds[1][VY] = box[BOXTOP]; return P_PolyobjLinesBoxIteratorv(bounds, func, data); } boolean P_PolyobjLinesBoxIteratorv(const arvec2_t box, boolean (*func) (linedef_t*, void*), void* data) { uint blockBox[4]; P_BoxToBlockmapBlocks(BlockMap, blockBox, box); return P_BlockBoxPolyobjLinesIterator(BlockMap, blockBox, func, data); } /** * The validCount flags are used to avoid checking lines that are marked * in multiple mapblocks, so increment validCount before the first call * to P_BlockmapLinesIterator, then make one or more calls to it. */ boolean P_AllLinesBoxIterator(const float box[4], boolean (*func) (linedef_t*, void*), void* data) { vec2_t bounds[2]; bounds[0][VX] = box[BOXLEFT]; bounds[0][VY] = box[BOXBOTTOM]; bounds[1][VX] = box[BOXRIGHT]; bounds[1][VY] = box[BOXTOP]; return P_AllLinesBoxIteratorv(bounds, func, data); } /** * The validCount flags are used to avoid checking lines that are marked * in multiple mapblocks, so increment validCount before the first call * to P_BlockmapLinesIterator, then make one or more calls to it. */ boolean P_AllLinesBoxIteratorv(const arvec2_t box, boolean (*func) (linedef_t*, void*), void* data) { if(numPolyObjs > 0) { if(!P_PolyobjLinesBoxIteratorv(box, func, data)) return false; } return P_LinesBoxIteratorv(box, func, data); } /** * Looks for lines in the given block that intercept the given trace to add * to the intercepts list * A line is crossed if its endpoints are on opposite sides of the trace. * * @return @c true if earlyout and a solid line hit. */ boolean PIT_AddLineIntercepts(linedef_t* ld, void* data) { int s[2]; float frac; divline_t dl; // Avoid precision problems with two routines. if(traceLOS.dX > FRACUNIT * 16 || traceLOS.dY > FRACUNIT * 16 || traceLOS.dX < -FRACUNIT * 16 || traceLOS.dY < -FRACUNIT * 16) { s[0] = P_PointOnDivlineSide(ld->L_v1pos[VX], ld->L_v1pos[VY], &traceLOS); s[1] = P_PointOnDivlineSide(ld->L_v2pos[VX], ld->L_v2pos[VY], &traceLOS); } else { s[0] = P_PointOnLinedefSide(FIX2FLT(traceLOS.pos[VX]), FIX2FLT(traceLOS.pos[VY]), ld); s[1] = P_PointOnLinedefSide(FIX2FLT(traceLOS.pos[VX] + traceLOS.dX), FIX2FLT(traceLOS.pos[VY] + traceLOS.dY), ld); } if(s[0] == s[1]) return true; // Line isn't crossed. // Hit the line. P_MakeDivline(ld, &dl); frac = P_InterceptVector(&traceLOS, &dl); if(frac < 0) return true; // Behind source. // Try to early out the check. if(earlyout && frac < 1 && !ld->L_backside) return false; // Stop iteration. P_AddIntercept(frac, true, ld); return true; // Continue iteration. } boolean PIT_AddMobjIntercepts(mobj_t* mo, void* data) { float x1, y1, x2, y2; int s[2]; divline_t dl; float frac; if(mo->dPlayer && (mo->dPlayer->flags & DDPF_CAMERA)) return true; // $democam: ssshh, keep going, we're not here... // Check a corner to corner crossection for hit. if((traceLOS.dX ^ traceLOS.dY) > 0) { x1 = mo->pos[VX] - mo->radius; y1 = mo->pos[VY] + mo->radius; x2 = mo->pos[VX] + mo->radius; y2 = mo->pos[VY] - mo->radius; } else { x1 = mo->pos[VX] - mo->radius; y1 = mo->pos[VY] - mo->radius; x2 = mo->pos[VX] + mo->radius; y2 = mo->pos[VY] + mo->radius; } s[0] = P_PointOnDivlineSide(x1, y1, &traceLOS); s[1] = P_PointOnDivlineSide(x2, y2, &traceLOS); if(s[0] == s[1]) return true; // Line isn't crossed. dl.pos[VX] = FLT2FIX(x1); dl.pos[VY] = FLT2FIX(y1); dl.dX = FLT2FIX(x2 - x1); dl.dY = FLT2FIX(y2 - y1); frac = P_InterceptVector(&traceLOS, &dl); if(frac < 0) return true; // Behind source. P_AddIntercept(frac, false, mo); return true; // Keep going. } /** * Traces a line from x1,y1 to x2,y2, calling the traverser function for each * Returns true if the traverser function returns true for all lines */ boolean P_PathTraverse(float x1, float y1, float x2, float y2, int flags, boolean (*trav) (intercept_t*)) { float origin[2], dest[2]; uint originBlock[2], destBlock[2]; gamemap_t* map = P_GetCurrentMap(); vec2_t min, max; V2_Set(origin, x1, y1); V2_Set(dest, x2, y2); P_GetBlockmapBounds(map->blockMap, min, max); if(!(origin[VX] >= min[VX] && origin[VX] <= max[VX] && origin[VY] >= min[VY] && origin[VY] <= max[VY])) { // Origin is outside the blockmap (really? very unusual...) return false; } // Check the easy case of a path that lies completely outside the bmap. if((origin[VX] < min[VX] && dest[VX] < min[VX]) || (origin[VX] > max[VX] && dest[VX] > max[VX]) || (origin[VY] < min[VY] && dest[VY] < min[VY]) || (origin[VY] > max[VY] && dest[VY] > max[VY])) { // Nothing intercepts outside the blockmap! return false; } if((FLT2FIX(origin[VX] - min[VX]) & (MAPBLOCKSIZE - 1)) == 0) origin[VX] += 1; // Don't side exactly on a line. if((FLT2FIX(origin[VY] - min[VY]) & (MAPBLOCKSIZE - 1)) == 0) origin[VY] += 1; // Don't side exactly on a line. traceLOS.pos[VX] = FLT2FIX(origin[VX]); traceLOS.pos[VY] = FLT2FIX(origin[VY]); traceLOS.dX = FLT2FIX(dest[VX] - origin[VX]); traceLOS.dY = FLT2FIX(dest[VY] - origin[VY]); /** * It is possible that one or both points are outside the blockmap. * Clip path so that dest is within the AABB of the blockmap (note we * would have already abandoned if origin lay outside. Also, to avoid * potential rounding errors which might occur when determining the * blocks later, we will shrink the bbox slightly first. */ if(!(dest[VX] >= min[VX] && dest[VX] <= max[VX] && dest[VY] >= min[VY] && dest[VY] <= max[VY])) { // Dest is outside the blockmap. float ab; vec2_t bbox[4], point; V2_Set(bbox[0], min[VX] + 1, min[VY] + 1); V2_Set(bbox[1], min[VX] + 1, max[VY] - 1); V2_Set(bbox[2], max[VX] - 1, max[VY] - 1); V2_Set(bbox[3], max[VX] - 1, min[VY] + 1); ab = V2_Intercept(origin, dest, bbox[0], bbox[1], point); if(ab >= 0 && ab <= 1) V2_Copy(dest, point); ab = V2_Intercept(origin, dest, bbox[1], bbox[2], point); if(ab >= 0 && ab <= 1) V2_Copy(dest, point); ab = V2_Intercept(origin, dest, bbox[2], bbox[3], point); if(ab >= 0 && ab <= 1) V2_Copy(dest, point); ab = V2_Intercept(origin, dest, bbox[3], bbox[0], point); if(ab >= 0 && ab <= 1) V2_Copy(dest, point); } if(!(P_ToBlockmapBlockIdx(map->blockMap, originBlock, origin) && P_ToBlockmapBlockIdx(map->blockMap, destBlock, dest))) { // Shouldn't reach here due to the clipping above. return false; } earlyout = flags & PT_EARLYOUT; validCount++; P_ClearIntercepts(); V2_Subtract(origin, origin, min); V2_Subtract(dest, dest, min); if(!P_BlockPathTraverse(BlockMap, originBlock, destBlock, origin, dest, flags, trav)) return false; // Early out. // Go through the sorted list. return P_TraverseIntercepts(trav, 1.0f); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_dyn.c0000644000175000017500000004525511357170242022712 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_dyn.c: Projected lumobjs (dynlight) lists. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include "de_base.h" #include "de_console.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_render.h" #include "de_play.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define LUM_FACTOR(dist, radius) (1.5f - 1.5f*(dist)/(radius)) // TYPES ------------------------------------------------------------------- typedef struct dynnode_s { struct dynnode_s* next, *nextUsed; dynlight_t dyn; } dynnode_t; typedef struct dynlist_s { boolean sortBrightestFirst; dynnode_t* head; } dynlist_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int useDynLights = true, dlBlend = 0; float dlFactor = .7f; float dlFogBright = .15f; int useWallGlow = true; float glowHeightFactor = 3; // Glow height as a multiplier. int glowHeightMax = 100; // 100 is the default (0-1024). // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Dynlight nodes. static dynnode_t* dynFirst, *dynCursor; // Surface light link lists. static uint numDynlightLinkLists = 0, dynlightLinkListCursor = 0; static dynlist_t* dynlightLinkLists; // CODE -------------------------------------------------------------------- void DL_Register(void) { // Cvars C_VAR_INT("rend-glow", &glowingTextures, 0, 0, 1); C_VAR_INT("rend-glow-wall", &useWallGlow, 0, 0, 1); C_VAR_INT("rend-glow-height", &glowHeightMax, 0, 0, 1024); C_VAR_FLOAT("rend-glow-scale", &glowHeightFactor, 0, 0.1f, 10); C_VAR_INT2("rend-light", &useDynLights, 0, 0, 1, LO_UnlinkMobjLumobjs); C_VAR_INT("rend-light-blend", &dlBlend, 0, 0, 2); C_VAR_FLOAT("rend-light-bright", &dlFactor, 0, 0, 1); C_VAR_FLOAT("rend-light-fog-bright", &dlFogBright, 0, 0, 1); C_VAR_INT("rend-light-multitex", &useMultiTexLights, 0, 0, 1); C_VAR_INT("rend-mobj-light-auto", &useMobjAutoLights, 0, 0, 1); LO_Register(); Rend_DecorRegister(); } /** * Initialize the dynlight system in preparation for rendering view(s) of the * game world. Called by R_InitLevel(). */ void DL_InitForMap(void) { dynlightLinkLists = NULL; numDynlightLinkLists = 0, dynlightLinkListCursor = 0; } /** * Moves all used dynlight nodes to the list of unused nodes, so they * can be reused. */ void DL_InitForNewFrame(void) { // Start reusing nodes from the first one in the list. dynCursor = dynFirst; // Clear the surface light link lists. dynlightLinkListCursor = 0; if(numDynlightLinkLists) memset(dynlightLinkLists, 0, numDynlightLinkLists * sizeof(dynlist_t)); } /** * Create a new dynlight list. * * @param sortBrightestFirst Nodes in the list will be auto-sorted when * added by the brightness of the associated dynlight * in descending order. * @return Identifier for the new list. */ static uint newDynlightList(boolean sortBrightestFirst) { dynlist_t* list; // Ran out of light link lists? if(++dynlightLinkListCursor >= numDynlightLinkLists) { uint newNum = numDynlightLinkLists * 2; if(!newNum) newNum = 2; dynlightLinkLists = Z_Realloc(dynlightLinkLists, newNum * sizeof(dynlist_t), PU_MAP); numDynlightLinkLists = newNum; } list = &dynlightLinkLists[dynlightLinkListCursor-1]; list->head = NULL; list->sortBrightestFirst = sortBrightestFirst; return dynlightLinkListCursor - 1; } static dynnode_t* newDynNode(void) { dynnode_t* node; // Have we run out of nodes? if(dynCursor == NULL) { node = Z_Malloc(sizeof(dynnode_t), PU_STATIC, NULL); // Link the new node to the list. node->nextUsed = dynFirst; dynFirst = node; } else { node = dynCursor; dynCursor = dynCursor->nextUsed; } node->next = NULL; return node; } /** * Returns a new dynlight node. If the list of unused nodes is empty, * a new node is created. */ static dynnode_t* newDynLight(float* s, float* t) { dynnode_t* node = newDynNode(); dynlight_t* dyn = &node->dyn; if(s) { dyn->s[0] = s[0]; dyn->s[1] = s[1]; } if(t) { dyn->t[0] = t[0]; dyn->t[1] = t[1]; } return node; } static void linkDynNodeToList(dynnode_t* node, uint listIndex) { dynlist_t* list = &dynlightLinkLists[listIndex]; if(list->sortBrightestFirst && list->head) { float light = (node->dyn.color[0] + node->dyn.color[1] + node->dyn.color[2]) / 3; dynnode_t* last, *iter; last = iter = list->head; do { // Is this brighter than the one being added? if((iter->dyn.color[0] + iter->dyn.color[1] + iter->dyn.color[2]) / 3 > light) { last = iter; iter = iter->next; } else { // Need to insert it here. node->next = last->next; last->next = node; return; } } while(iter); } node->next = list->head; list->head = node; } /** * Blend the given light value with the lumobj's color, apply any global * modifiers and output the result. * * @param outRGB The location the calculated result will be written to. * @param lum Ptr to the lumobj from which the color will be used. * @param light The light value to be used in the calculation. */ static void calcDynLightColor(float* outRGB, const float* inRGB, float light) { uint i; if(light < 0) light = 0; else if(light > 1) light = 1; light *= dlFactor; // In fog, additive blending is used. The normal fog color // is way too bright. if(usingFog) light *= dlFogBright; // Would be too much. // Multiply with the light color. for(i = 0; i < 3; ++i) { outRGB[i] = light * inRGB[i]; } } /** * Project the given planelight onto the specified seg. If it would be lit, * a new dynlight node will be created and returned. * * @param lum Ptr to the lumobj lighting the seg. * @param bottom Z height (bottom) of the section being lit. * @param top Z height (top) of the section being lit. * * @return Ptr to the projected light, ELSE @c NULL. */ static dynnode_t* projectPlaneGlowOnSegSection(const lumobj_t* lum, float bottom, float top) { float glowHeight; float s[2], t[2]; if(bottom >= top) return NULL; // No height. glowHeight = (MAX_GLOWHEIGHT * LUM_PLANE(lum)->intensity) * glowHeightFactor; // Don't make too small or too large glows. if(glowHeight <= 2) return NULL; if(glowHeight > glowHeightMax) glowHeight = glowHeightMax; // Calculate texture coords for the light. if(LUM_PLANE(lum)->normal[VZ] < 0) { // Light is cast downwards. t[1] = t[0] = (lum->pos[VZ] - top) / glowHeight; t[1]+= (top - bottom) / glowHeight; } else { // Light is cast upwards. t[0] = t[1] = (bottom - lum->pos[VZ]) / glowHeight; t[0]+= (top - bottom) / glowHeight; } if(!(t[0] <= 1 || t[1] >= 0)) return NULL; // Is above/below on the Y axis. // The horizontal direction is easy. s[0] = 0; s[1] = 1; return newDynLight(s, t); } /** * Given a normalized normal, construct up and right vectors, oriented to * the original normal. Note all vectors and normals are in world-space. * * @param up The up vector will be written back here. * @param right The right vector will be written back here. * @param normal Normal to construct vectors for. */ static void buildUpRight(pvec3_t up, pvec3_t right, const pvec3_t normal) { const vec3_t rotm[3] = { {0.f, 0.f, 1.f}, {0.f, 0.f, 1.f}, {0.f, 0.f, 1.f} }; int axis = VX; vec3_t fn; V3_Set(fn, fabsf(normal[VX]), fabsf(normal[VY]), fabsf(normal[VZ])); if(fn[VY] > fn[axis]) axis = VY; if(fn[VZ] > fn[axis]) axis = VZ; if(fabsf(fn[VX] - 1.0f) < FLT_EPSILON || fabsf(fn[VY] - 1.0f) < FLT_EPSILON || fabsf(fn[VZ] - 1.0f) < FLT_EPSILON) { // We must build the right vector manually. if(axis == VX && normal[VX] > 0.f) { V3_Set(right, 0.f, 1.f, 0.f); } else if(axis == VX) { V3_Set(right, 0.f, -1.f, 0.f); } if(axis == VY && normal[VY] > 0.f) { V3_Set(right, -1.f, 0.f, 0.f); } else if(axis == VY) { V3_Set(right, 1.f, 0.f, 0.f); } if(axis == VZ) { V3_Set(right, 1.f, 0.f, 0.f); } } else { // Can use a cross product of the surface normal. V3_CrossProduct(right, (const pvec3_t) rotm[axis], normal); V3_Normalize(right); } V3_CrossProduct(up, right, normal); V3_Normalize(up); } /** * Generate texcoords on surface centered on point. * * @param point Point on surface around which texture is centered. * @param scale Scale multiplier for texture. * @param s Texture s coords written back here. * @param t Texture t coords written back here. * @param v1 Top left vertex of the surface being projected on. * @param v2 Bottom right vertex of the surface being projected on. * @param normal Normal of the surface being projected on. * * @return @c true, if the generated coords are within bounds. */ static boolean genTexCoords(const pvec3_t point, float scale, pvec2_t s, pvec2_t t, const pvec3_t v1, const pvec3_t v2, const pvec3_t normal) { vec3_t vToPoint, right, up; buildUpRight(up, right, normal); V3_Subtract(vToPoint, v1, point); s[0] = V3_DotProduct(vToPoint, right) * scale + .5f; t[0] = V3_DotProduct(vToPoint, up) * scale + .5f; V3_Subtract(vToPoint, v2, point); s[1] = V3_DotProduct(vToPoint, right) * scale + .5f; t[1] = V3_DotProduct(vToPoint, up) * scale + .5f; // Would the light be visible? if(!(s[0] <= 1 || s[1] >= 0)) return false; // Is right/left on the X axis. if(!(t[0] <= 1 || t[1] >= 0)) return false; // Is above/below on the Y axis. return true; } typedef struct surfacelumobjiterparams_s { vec3_t v1, v2; vec3_t normal; boolean haveList; uint listIdx; byte flags; // DLF_* flags. } surfacelumobjiterparams_t; boolean DLIT_SurfaceLumobjContacts(void* ptr, void* data) { lumobj_t* lum = (lumobj_t*) ptr; dynnode_t* node = NULL; surfacelumobjiterparams_t* params = data; DGLuint tex = 0; float lightBrightness = 1; float* lightRGB; uint lumIdx; if(!(lum->type == LT_OMNI || lum->type == LT_PLANE)) return true; // Continue iteration. lumIdx = LO_ToIndex(lum); switch(lum->type) { case LT_OMNI: if(LO_IsHidden(lumIdx, viewPlayer - ddPlayers)) return true; if(params->flags & DLF_TEX_CEILING) tex = LUM_OMNI(lum)->ceilTex; else if(params->flags & DLF_TEX_FLOOR) tex = LUM_OMNI(lum)->floorTex; else tex = LUM_OMNI(lum)->tex; lightRGB = LUM_OMNI(lum)->color; if(tex) { vec3_t lumCenter, vToLum; V3_Set(lumCenter, lum->pos[VX], lum->pos[VY], lum->pos[VZ] + LUM_OMNI(lum)->zOff); // On the right side? V3_Subtract(vToLum, params->v1, lumCenter); if(V3_DotProduct(vToLum, params->normal) < 0.f) { float dist; vec3_t point; // Calculate 3D distance between surface and lumobj. V3_ClosestPointOnPlane(point, params->normal, params->v1, lumCenter); dist = V3_Distance(point, lumCenter); if(dist > 0 && dist <= LUM_OMNI(lum)->radius) { lightBrightness = LUM_FACTOR(dist, LUM_OMNI(lum)->radius); // If a max distance limit is set, lumobjs fade out. if(lum->maxDistance > 0) { float distFromViewer = LO_DistanceToViewer(lumIdx, viewPlayer - ddPlayers); if(distFromViewer > lum->maxDistance) lightBrightness = 0; if(distFromViewer > .67f * lum->maxDistance) { lightBrightness *= (lum->maxDistance - distFromViewer) / (.33f * lum->maxDistance); } } if(lightBrightness >= .05f) { vec2_t s, t; float scale = 1.0f / ((2.f * LUM_OMNI(lum)->radius) - dist); if(genTexCoords(point, scale, s, t, params->v1, params->v2, params->normal)) { node = newDynLight(s, t); } } } } } break; case LT_PLANE: if(!(params->flags & DLF_NO_PLANAR)) tex = LUM_PLANE(lum)->tex; if(tex) { lightRGB = LUM_PLANE(lum)->color; node = projectPlaneGlowOnSegSection(lum, params->v2[VZ], params->v1[VZ]); } break; default: Con_Error("DLIT_SegLumobjContacts: Invalid value, lum->type = %i.", (int) lum->type); break; } if(node) { dynlight_t* dyn = &node->dyn; dyn->texture = tex; calcDynLightColor(dyn->color, lightRGB, lightBrightness); // Got a list for this surface yet? if(!params->haveList) { boolean sortBrightestFirst = (params->flags & DLF_SORT_LUMADSC)? true : false; params->listIdx = newDynlightList(sortBrightestFirst); params->haveList = true; } linkDynNodeToList(node, params->listIdx); } return true; // Continue iteration. } static uint processSubSector(subsector_t* ssec, surfacelumobjiterparams_t* params) { // Process each lumobj contacting the subsector. R_IterateSubsectorContacts(ssec, OT_LUMOBJ, DLIT_SurfaceLumobjContacts, params); // Did we generate a light list? if(params->haveList) return params->listIdx + 1; return 0; // Nope. } /** * Project all lumobjs affecting the given quad (world space), calculate * coordinates (in texture space) then store into a new list of dynlights. * * \assume The coordinates of the given quad must be contained wholly within * the subsector specified. This is due to an optimization within the lumobj * management which seperates them according to their position in the BSP. * * @param ssec Subsector within which the quad wholly resides. * @param topLeft Coordinates of the top left corner of the quad. * @param bottomRight Coordinates of the bottom right corner of the quad. * @param normal Normalized normal of the quad. * @param flags DLF_* flags. * * @return Dynlight list name if the quad is lit by one or more * light sources, else @c 0. */ uint DL_ProjectOnSurface(subsector_t* ssec, const vectorcomp_t topLeft[3], const vectorcomp_t bottomRight[3], const vectorcomp_t normal[3], byte flags) { surfacelumobjiterparams_t params; if(!useDynLights && !useWallGlow) return 0; // Disabled. if(!ssec) return 0; V3_Copy(params.v1, topLeft); V3_Copy(params.v2, bottomRight); V3_Set(params.normal, normal[VX], normal[VY], normal[VZ]); params.flags = flags; params.haveList = false; params.listIdx = 0; return processSubSector(ssec, ¶ms); } /** * Calls func for all projected dynlights in the given list. * * @param listIdx Identifier of the list to process. * @param data Ptr to pass to the callback. * @param func Callback to make for each object. * * @return @c true, iff every callback returns @c true. */ boolean DL_ListIterator(uint listIdx, void* data, boolean (*func) (const dynlight_t*, void*)) { dynnode_t* node; boolean retVal, isDone; if(listIdx == 0 || listIdx > numDynlightLinkLists) return true; listIdx--; node = dynlightLinkLists[listIdx].head; retVal = true; isDone = false; while(node && !isDone) { if(!func(&node->dyn, data)) { retVal = false; isDone = true; } else node = node->next; } return retVal; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_pcx.c0000644000175000017500000001411111357170242022347 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1997-2006 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_pcx.c: PCX Images */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- #pragma pack(1) typedef struct { char manufacturer; char version; char encoding; char bits_per_pixel; unsigned short xmin, ymin, xmax, ymax; unsigned short hres, vres; unsigned char palette[48]; char reserved; char color_planes; unsigned short bytes_per_line; unsigned short palette_type; char filler[58]; unsigned char data; // unbounded } pcx_t; #pragma pack() // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static boolean memoryLoad(const byte* imgdata, size_t len, int bufW, int bufH, byte* outBuffer) { const pcx_t* pcx = (const pcx_t*) imgdata; const byte* raw = &pcx->data; byte* palette, *pix; int x, y, dataByte, runLength; short xmax = SHORT(pcx->xmax); short ymax = SHORT(pcx->ymax); if(!outBuffer) return false; // Check the format. if(pcx->manufacturer != 0x0a || pcx->version != 5 || pcx->encoding != 1 || pcx->bits_per_pixel != 8) { //Con_Message("PCX_Load: unsupported format.\n"); return false; } // Check that the PCX is not larger than the buffer. if(xmax >= bufW || ymax >= bufH) { Con_Message("PCX_Load: larger than expected.\n"); return false; } palette = M_Malloc(768); memcpy(palette, ((byte*) pcx) + len - 768, 768); // Palette is in the end. pix = outBuffer; for(y = 0; y <= ymax; ++y, pix += (xmax + 1) * 3) { for(x = 0; x <= xmax;) { dataByte = *raw++; if((dataByte & 0xC0) == 0xC0) { runLength = dataByte & 0x3F; dataByte = *raw++; } else runLength = 1; while(runLength-- > 0) { memcpy(pix + x++ * 3, palette + dataByte * 3, 3); } } } if((size_t) (raw - (byte *) pcx) > len) Con_Error("PCX_Load: Corrupt image!\n"); M_Free(palette); return true; } /** * PCX loader, partly borrowed from the Q2 utils source (lbmlib.c). */ static boolean load(const char* fn, int bufW, int bufH, byte* outBuffer) { DFILE* file; if((file = F_Open(fn, "rb"))) { byte* raw; size_t len; // Load the file. F_Seek(file, 0, SEEK_END); // Seek to end. len = F_Tell(file); // How long? F_Seek(file, 0, SEEK_SET); raw = M_Malloc(len); F_Read(raw, len, file); F_Close(file); // Parse the PCX file. if(!memoryLoad(raw, len, bufW, bufH, outBuffer)) { Con_Message("PCX_Load: Error loading \"%s\".\n", M_PrettyPath(fn)); outBuffer = NULL; } M_Free(raw); return true; } Con_Message("PCX_Load: Can't find %s.\n", fn); return false; } boolean PCX_Load(const char* fn, int bufW, int bufH, byte* outBuffer) { if(!outBuffer) return false; return load(fn, bufW, bufH, outBuffer); } /** * @return @c true, if a PCX image (probably). */ boolean PCX_MemoryLoad(const byte* imgdata, size_t len, int bufW, int bufH, byte* outBuffer) { if(memoryLoad(imgdata, len, bufW, bufH, outBuffer)) return true; return false; } boolean PCX_GetSize(const char* fn, int* w, int* h) { DFILE* file; if((file = F_Open(fn, "rb"))) { pcx_t hdr; size_t read; read = F_Read(&hdr, sizeof(hdr), file); F_Close(file); if(!(read < sizeof(hdr))) return PCX_MemoryGetSize(&hdr, w, h); } return false; } /** * @return @c true, if successful. */ boolean PCX_MemoryGetSize(const void* imageData, int* w, int* h) { const pcx_t* hdr = (const pcx_t*) imageData; if(hdr->manufacturer != 0x0a || hdr->version != 5 || hdr->encoding != 1 || hdr->bits_per_pixel != 8) return false; if(w) *w = SHORT(hdr->xmax) + 1; if(h) *h = SHORT(hdr->ymax) + 1; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_gridmap.c0000644000175000017500000001565411357170242023047 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_gridmap.c: Generalized blockmap */ // HEADER FILES ------------------------------------------------------------ #include "math.h" #include "de_base.h" #include "de_console.h" #include "de_misc.h" #include "de_refresh.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct gridblock_s { void *data; } gridblock_t; typedef struct gmap_s { uint width, height; size_t sizeOfBlock; int memzoneTag; gridblock_t *blocks; } gmap_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static gmap_t *allocGridmap(int tag) { return Z_Calloc(sizeof(gmap_t), tag, 0); } static void freeGridmap(gmap_t *gmap) { Z_Free(gmap->blocks); Z_Free(gmap); } static gridblock_t *getBlock(gmap_t *gmap, uint x, uint y) { if(x < gmap->width && y < gmap->height) { return &gmap->blocks[y * gmap->width + x]; } return NULL; } /** * Create a new gridmap. * * @param width X dimension of the grid. * @param height Y dimension of the grid. * @param sizeOfElement Amount of memory to be allocated for each element. */ gridmap_t *M_GridmapCreate(uint width, uint height, size_t sizeOfElement, int memzoneTag) { gmap_t *gmap = allocGridmap(memzoneTag); gmap->width = width; gmap->height = height; gmap->sizeOfBlock = sizeOfElement; gmap->memzoneTag = memzoneTag; gmap->blocks = Z_Calloc(gmap->width * gmap->height * sizeof(gridblock_t), gmap->memzoneTag, 0); return (gridmap_t*) gmap; } /** * Destroy a gridmap. * * @param gridmap The gridmap to be destroyed. */ void M_GridmapDestroy(gridmap_t *gridmap) { if(gridmap) { uint i, numblocks; gmap_t *gmap = (gmap_t*) gridmap; numblocks = gmap->width * gmap->height; for(i = 0; i < numblocks; ++i) { gridblock_t *block = &gmap->blocks[i]; if(block->data) Z_Free(block->data); } freeGridmap(gmap); } } void *M_GridmapGetBlock(gridmap_t *gridmap, uint x, uint y, boolean alloc) { if(gridmap) { gmap_t *gmap = (gmap_t*) gridmap; gridblock_t *block = getBlock(gmap, x, y); if(block) { if(alloc) { // Allocator mode. // Have we allocated memory for this block yet? if(!block->data) { block->data = Z_Calloc(gmap->sizeOfBlock, gmap->memzoneTag, 0); } return block->data; } else { // Look up mode. if(block->data) return block->data; return NULL; } } } return NULL; } /** * Iterate all the blocks of the gridmap, calling func for each. * * @param gridmap The gridmap being iterated. * @param callback The callback to be made for each block. * @param param Miscellaneous data to be passed in the callback. * * @return @c true, iff all callbacks return @c true; */ boolean M_GridmapIterator(gridmap_t *gridmap, boolean (*callback) (void* p, void* ctx), void* param) { if(gridmap) { gmap_t *gmap = (gmap_t*) gridmap; uint x, y; for(x = 0; x <= gmap->width; ++x) { for(y = 0; y <= gmap->height; ++y) { gridblock_t *block = getBlock(gmap, x, y); if(block && block->data) { if(!callback(block->data, param)) return false; } } } return true; } return false; } /** * Iterate a subset of the blocks of the gridmap and calling func for each. * * @param gridmap The gridmap being iterated. * @param xl Min X * @param xh Max X * @param yl Min Y * @param yh Max Y * @param callback The callback to be made for each block. * @param param Miscellaneous data to be passed in the callback. * * @return @c true, iff all callbacks return @c true; */ boolean M_GridmapBoxIterator(gridmap_t *gridmap, uint xl, uint xh, uint yl, uint yh, boolean (*callback) (void* p, void* ctx), void* param) { if(gridmap) { gmap_t *gmap = (gmap_t*) gridmap; uint x, y; // Kludge: We shouldn't need clamping here! if(xh >= gmap->width) xh = gmap->width -1; if(yh >= gmap->height) yh = gmap->height - 1; for(x = xl; x <= xh; ++x) { for(y = yl; y <= yh; ++y) { gridblock_t *block = getBlock(gmap, x, y); if(block && block->data) { if(!callback(block->data, param)) return false; } } } return true; } return false; } boolean M_GridmapBoxIteratorv(gridmap_t *gridmap, const uint box[4], boolean (*callback) (void* p, void* ctx), void* param) { return M_GridmapBoxIterator(gridmap, box[BOXLEFT], box[BOXRIGHT], box[BOXBOTTOM], box[BOXTOP], callback, param); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_sight.c0000644000175000017500000002353011357170242022535 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1998-2006 James Haley *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sight.c: Line of Sight Testing. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_play.h" #include "de_refresh.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ typedef struct losdata_s { int flags; // LS_* flags @see lineSightFlags divline_t trace; float startZ; // Eye z of looker. float topSlope; // Slope to top of target. float bottomSlope; // Slope to bottom of target. float bBox[4]; float to[3]; } losdata_t; // CODE -------------------------------------------------------------------- static boolean interceptLineDef(const linedef_t* li, losdata_t* los, divline_t* dl) { divline_t localDL, *dlPtr; // Try a quick, bounding-box rejection. if(li->bBox[BOXLEFT] > los->bBox[BOXRIGHT] || li->bBox[BOXRIGHT] < los->bBox[BOXLEFT] || li->bBox[BOXBOTTOM] > los->bBox[BOXTOP] || li->bBox[BOXTOP] < los->bBox[BOXBOTTOM]) return false; if(P_PointOnDivlineSide(li->L_v1pos[VX], li->L_v1pos[VY], &los->trace) == P_PointOnDivlineSide(li->L_v2pos[VX], li->L_v2pos[VY], &los->trace)) return false; // Not crossed. if(dl) dlPtr = dl; else dlPtr = &localDL; P_MakeDivline(li, dlPtr); if(P_PointOnDivlineSide(FIX2FLT(los->trace.pos[VX]), FIX2FLT(los->trace.pos[VY]), dlPtr) == P_PointOnDivlineSide(los->to[VX], los->to[VY], dlPtr)) return false; // Not crossed. return true; // Crossed. } static boolean crossLineDef(const linedef_t* li, byte side, losdata_t* los) { #define RTOP 0x1 #define RBOTTOM 0x2 float frac; byte ranges = 0; divline_t dl; const sector_t* fsec, *bsec; boolean noBack; if(!interceptLineDef(li, los, &dl)) return true; // Ray does not intercept seg on the X/Y plane. if(!li->L_side(side)) return true; // Seg is on the back side of a one-sided window. fsec = li->L_sector(side); bsec = (li->L_backside? li->L_sector(side^1) : NULL); noBack = li->L_backside? false : true; if(!noBack && !(los->flags & LS_PASSLEFT) && (!(bsec->SP_floorheight < fsec->SP_ceilheight) || !(fsec->SP_floorheight < bsec->SP_ceilheight))) noBack = true; if(noBack) { if((los->flags & LS_PASSLEFT) && P_PointOnLinedefSide(FIX2FLT(los->trace.pos[VX]), FIX2FLT(los->trace.pos[VY]), li)) return true; // Ray does not intercept seg from left to right. if(!(los->flags & (LS_PASSOVER | LS_PASSUNDER))) return false; // Stop iteration. } // Handle the case of a zero height backside in the top range. if(noBack) { ranges |= RTOP; } else { if(bsec->SP_floorheight != fsec->SP_floorheight) ranges |= RBOTTOM; if(bsec->SP_ceilheight != fsec->SP_ceilheight) ranges |= RTOP; } if(!ranges) return true; frac = P_InterceptVector(&los->trace, &dl); if((los->flags & LS_PASSOVER) && los->bottomSlope > (fsec->SP_ceilheight - los->startZ) / frac) return true; if((los->flags & LS_PASSUNDER) && los->topSlope < (fsec->SP_floorheight - los->startZ) / frac) return true; if(ranges & RTOP) { float top = (noBack? fsec->SP_ceilheight : fsec->SP_ceilheight < bsec->SP_ceilheight? fsec->SP_ceilheight : bsec->SP_ceilheight); float slope = (top - los->startZ) / frac; if((slope < los->topSlope) ^ (noBack && !(los->flags & LS_PASSOVER)) || (noBack && los->topSlope > (fsec->SP_floorheight - los->startZ) / frac)) los->topSlope = slope; if((slope < los->bottomSlope) ^ (noBack && !(los->flags & LS_PASSUNDER)) || (noBack && los->bottomSlope > (fsec->SP_floorheight - los->startZ) / frac)) los->bottomSlope = slope; } if(ranges & RBOTTOM) { float bottom = (noBack? fsec->SP_floorheight : fsec->SP_floorheight > bsec->SP_floorheight? fsec->SP_floorheight : bsec->SP_floorheight); float slope = (bottom - los->startZ) / frac; if(slope > los->bottomSlope) los->bottomSlope = slope; if(slope > los->topSlope) los->topSlope = slope; } if(los->topSlope <= los->bottomSlope) return false; // Stop iteration. return true; #undef RTOP #undef RBOTTOM } /** * @return @c true iff trace crosses the given subsector. */ static boolean crossSSec(uint ssecIdx, losdata_t* los) { const subsector_t* ssec = &ssectors[ssecIdx]; if(ssec->polyObj) { // Check polyobj lines. polyobj_t* po = ssec->polyObj; seg_t** segPtr = po->segs; while(*segPtr) { seg_t* seg = *segPtr; if(seg->lineDef && seg->lineDef->validCount != validCount) { linedef_t* li = seg->lineDef; li->validCount = validCount; if(!crossLineDef(li, seg->side, los)) return false; // Stop iteration. } *segPtr++; } } { // Check lines. const seg_t** segPtr = ssec->segs; while(*segPtr) { const seg_t* seg = *segPtr; if(seg->lineDef && seg->lineDef->validCount != validCount) { linedef_t* li = seg->lineDef; li->validCount = validCount; if(!crossLineDef(li, seg->side, los)) return false; } *segPtr++; } } return true; // Continue iteration. } /** * @return @c true iff trace crosses the node. */ static boolean crossBSPNode(unsigned int bspNum, losdata_t* los) { while(!(bspNum & NF_SUBSECTOR)) { const node_t* node = &nodes[bspNum]; int side = R_PointOnSide( FIX2FLT(los->trace.pos[VX]), FIX2FLT(los->trace.pos[VY]), &node->partition); // Would the trace completely cross this partition? if(side == R_PointOnSide(los->to[VX], los->to[VY], &node->partition)) { // Yes, decend! bspNum = node->children[side]; } else { // No. if(!crossBSPNode(node->children[side], los)) return 0; // Cross the starting side. else bspNum = node->children[side^1]; // Cross the ending side. } } return crossSSec(bspNum & ~NF_SUBSECTOR, los); } /** * Traces a line of sight. * * @param from World position, trace origin coordinates. * @param to World position, trace target coordinates. * @param flags Line Sight Flags (LS_*) @see lineSightFlags * * @return @c true if the traverser function returns @c true * for all visited lines. */ boolean P_CheckLineSight(const float from[3], const float to[3], float bottomSlope, float topSlope, int flags) { losdata_t los; los.flags = flags; los.startZ = from[VZ]; los.topSlope = to[VZ] + topSlope - los.startZ; los.bottomSlope = to[VZ] + bottomSlope - los.startZ; los.trace.pos[VX] = FLT2FIX(from[VX]); los.trace.pos[VY] = FLT2FIX(from[VY]); los.trace.dX = FLT2FIX(to[VX] - from[VX]); los.trace.dY = FLT2FIX(to[VY] - from[VY]); los.to[VX] = to[VX]; los.to[VY] = to[VY]; los.to[VZ] = to[VZ]; if(from[VX] > to[VX]) { los.bBox[BOXRIGHT] = from[VX]; los.bBox[BOXLEFT] = to[VX]; } else { los.bBox[BOXRIGHT] = to[VX]; los.bBox[BOXLEFT] = from[VX]; } if(from[VY] > to[VY]) { los.bBox[BOXTOP] = from[VY]; los.bBox[BOXBOTTOM] = to[VY]; } else { los.bBox[BOXTOP] = to[VY]; los.bBox[BOXBOTTOM] = from[VY]; } validCount++; return crossBSPNode(numNodes - 1, &los); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dam_file.c0000644000175000017500000010425511357170241022643 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dam_file.c: Doomsday Archived Map (DAM) reader/writer. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_dam.h" #include "de_defs.h" #include "de_misc.h" #include "de_refresh.h" #include "p_mapdata.h" // MACROS ------------------------------------------------------------------ // Global archived map format version identifier. Increment when making // changes to the structure of the format. #define DAM_VERSION 1 #define MAX_ARCHIVED_MATERIALS 2048 #define BADTEXNAME "DD_BADTX" // string that will be written in the texture // archives to denote a missing texture. // TYPES ------------------------------------------------------------------- // Segments of a doomsday archived map file. typedef enum damsegment_e { DAMSEG_END = -1, // Terminates a segment. DAMSEG_HEADER = 100, // File-level meta. DAMSEG_RELOCATIONTABLES, // Tables of offsets to file positions. DAMSEG_SYMBOLTABLES, // Global symbol tables. DAMSEG_MAP = 200, // Start of the map data. DAMSEG_POLYOBJS, DAMSEG_VERTEXES, DAMSEG_LINES, DAMSEG_SIDES, DAMSEG_SECTORS, DAMSEG_SSECTORS, DAMSEG_SEGS, DAMSEG_NODES, DAMSEG_BLOCKMAP, DAMSEG_REJECT } damsegment_t; typedef struct { char name[9]; material_namespace_t mnamespace; } dictentry_t; typedef struct { //// \todo Remove fixed limit. dictentry_t table[MAX_ARCHIVED_MATERIALS]; int count; } materialdict_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static LZFILE *mapFile; static int mapFileVersion; static materialdict_t *materialDict; // CODE -------------------------------------------------------------------- /** * Called for every material in the map before saving by * initMaterialArchives. */ static void addMaterialToDict(materialdict_t* dict, material_t* mat) { #if 0 int c; dictentry_t* e; // Has this already been registered? for(c = 0; c < dict->count; c++) { if(dict->table[c].mnamespace == mat->mnamespace && !stricmp(dict->table[c].name, mat->name)) { // Yes. skip it... return; } } e = &dict->table[dict->count]; dict->count++; strncpy(e->name, mat->name, 8); e->name[8] = '\0'; e->mnamespace = mat->mnamespace; #endif } /** * Initializes the material archives (translation tables). * Must be called before writing the tables! */ static void initMaterialDict(const gamemap_t* map, materialdict_t* dict) { uint i, j; for(i = 0; i < map->numSectors; ++i) { sector_t *sec = &map->sectors[i]; for(j = 0; j < sec->planeCount; ++j) addMaterialToDict(dict, sec->SP_planematerial(j)); } for(i = 0; i < map->numSideDefs; ++i) { sidedef_t *side = &map->sideDefs[i]; addMaterialToDict(dict, side->SW_middlematerial); addMaterialToDict(dict, side->SW_topmaterial); addMaterialToDict(dict, side->SW_bottommaterial); } } static uint searchMaterialDict(materialdict_t *dict, const material_t* mat) { #if 0 int i; for(i = 0; i < dict->count; i++) if(dict->table[i].mnamespace == mat->mnamespace && !stricmp(dict->table[i].name, mat->name)) return i; #endif // Not found?!!! return 0; } /** * @return The archive number of the given texture. */ static uint getMaterialDictID(materialdict_t* dict, const material_t* mat) { return searchMaterialDict(dict, mat); } static material_t* lookupMaterialFromDict(materialdict_t* dict, int idx) { dictentry_t* e = &dict->table[idx]; if(!strncmp(e->name, BADTEXNAME, 8)) return NULL; return P_ToMaterial(P_MaterialNumForName(e->name, e->mnamespace)); } static boolean openMapFile(char* path, boolean write) { mapFile = NULL; mapFileVersion = 0; mapFile = lzOpen(path, (write? F_WRITE_PACKED : F_READ_PACKED)); return ((mapFile)? true : false); } static boolean closeMapFile(void) { return (lzClose(mapFile)? true : false); } static void writeNBytes(void* data, long len) { lzWrite(data, len, mapFile); } static void writeByte(byte val) { lzPutC(val, mapFile); } static void writeShort(short val) { lzPutW(val, mapFile); } static void writeLong(long val) { lzPutL(val, mapFile); } static void writeFloat(float val) { long temp = 0; memcpy(&temp, &val, 4); lzPutL(temp, mapFile); } static void readNBytes(void *ptr, long len) { lzRead(ptr, len, mapFile); } static byte readByte(void) { return lzGetC(mapFile); } static short readShort(void) { return lzGetW(mapFile); } static long readLong(void) { return lzGetL(mapFile); } static float readFloat(void) { long val = lzGetL(mapFile); float returnValue = 0; memcpy(&returnValue, &val, 4); return returnValue; } /** * Exit with a fatal error if the value at the current location in the * map file does not match that associated with the specified segment. * * @param segType Value by which to check for alignment. */ static void assertSegment(damsegment_t segment) { if(readLong() != segment) { Con_Error("assertSegment: Segment [%d] failed alignment check", (int) segment); } } static void beginSegment(damsegment_t segment) { writeLong(segment); } static void endSegment(void) { writeLong(DAMSEG_END); } static void writeVertex(const gamemap_t *map, uint idx) { vertex_t *v = &map->vertexes[idx]; writeFloat(v->V_pos[VX]); writeFloat(v->V_pos[VY]); writeLong((long) v->numLineOwners); if(v->numLineOwners > 0) { lineowner_t *own, *base; own = base = (v->lineOwners)->LO_prev; do { writeLong((long) ((own->lineDef - map->lineDefs) + 1)); writeLong((long) own->angle); own = own->LO_prev; } while(own != base); } } static void readVertex(const gamemap_t *map, uint idx) { uint i; vertex_t *v = &map->vertexes[idx]; v->V_pos[VX] = readFloat(); v->V_pos[VY] = readFloat(); v->numLineOwners = (uint) readLong(); if(v->numLineOwners > 0) { lineowner_t *own; v->lineOwners = NULL; for(i = 0; i < v->numLineOwners; ++i) { own = Z_Malloc(sizeof(lineowner_t), PU_MAP, 0); own->lineDef = &map->lineDefs[(unsigned) (readLong() - 1)]; own->angle = (binangle_t) readLong(); own->LO_next = v->lineOwners; v->lineOwners = own; } own = v->lineOwners; do { own->LO_next->LO_prev = own; own = own->LO_next; } while(own); own->LO_prev = v->lineOwners; } } static void archiveVertexes(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_VERTEXES); else assertSegment(DAMSEG_VERTEXES); if(write) { writeLong((long) map->numVertexes); for(i = 0; i < map->numVertexes; ++i) writeVertex(map, i); } else { map->numVertexes = (uint) readLong(); for(i = 0; i < map->numVertexes; ++i) readVertex(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writeLine(const gamemap_t *map, uint idx) { int i; linedef_t *l = &map->lineDefs[idx]; writeLong((long) ((l->v[0] - map->vertexes) + 1)); writeLong((long) ((l->v[1] - map->vertexes) + 1)); writeLong(l->flags); writeByte(l->inFlags); writeFloat(l->dX); writeFloat(l->dY); writeLong((long) l->slopeType); writeLong((long) (l->sideDefs[0]? ((l->sideDefs[0] - map->sideDefs) + 1) : 0)); writeLong((long) (l->sideDefs[1]? ((l->sideDefs[1] - map->sideDefs) + 1) : 0)); writeFloat(l->bBox[BOXLEFT]); writeFloat(l->bBox[BOXRIGHT]); writeFloat(l->bBox[BOXBOTTOM]); writeFloat(l->bBox[BOXTOP]); writeFloat(l->length); writeLong((long) l->angle); for(i = 0; i < DDMAXPLAYERS; ++i) writeByte(l->mapped[i]? 1 : 0); } static void readLine(const gamemap_t *map, uint idx) { int i; long sideIdx; linedef_t *l = &map->lineDefs[idx]; l->v[0] = &map->vertexes[(unsigned) (readLong() - 1)]; l->v[1] = &map->vertexes[(unsigned) (readLong() - 1)]; l->flags = (int) readLong(); l->inFlags = readByte(); l->dX = readFloat(); l->dY = readFloat(); l->slopeType = (slopetype_t) readLong(); sideIdx = readLong(); l->sideDefs[0] = (sideIdx == 0? NULL : &map->sideDefs[sideIdx-1]); sideIdx = readLong(); l->sideDefs[1] = (sideIdx == 0? NULL : &map->sideDefs[sideIdx-1]); l->bBox[BOXLEFT] = readFloat(); l->bBox[BOXRIGHT] = readFloat(); l->bBox[BOXBOTTOM] = readFloat(); l->bBox[BOXTOP] = readFloat(); l->length = readFloat(); l->angle = (binangle_t) readLong(); for(i = 0; i < DDMAXPLAYERS; ++i) l->mapped[i] = (readByte()? true : false); } static void archiveLines(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_LINES); else assertSegment(DAMSEG_LINES); if(write) { writeLong(map->numLineDefs); for(i = 0; i < map->numLineDefs; ++i) writeLine(map, i); } else { map->numLineDefs = readLong(); for(i = 0; i < map->numLineDefs; ++i) readLine(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writeSide(const gamemap_t *map, uint idx) { uint i; sidedef_t *s = &map->sideDefs[idx]; for(i = 0; i < 3; ++i) { surface_t *suf = &s->sections[3]; writeLong(suf->flags); writeLong(getMaterialDictID(materialDict, suf->material)); writeLong((long) suf->blendMode); writeFloat(suf->normal[VX]); writeFloat(suf->normal[VY]); writeFloat(suf->normal[VZ]); writeFloat(suf->offset[VX]); writeFloat(suf->offset[VY]); writeFloat(suf->rgba[CR]); writeFloat(suf->rgba[CG]); writeFloat(suf->rgba[CB]); writeFloat(suf->rgba[CA]); } writeLong(s->sector? ((s->sector - map->sectors) + 1) : 0); writeShort(s->flags); writeLong((long) s->segCount); for(i = 0; i < s->segCount; ++i) writeLong((s->segs[i] - map->segs) + 1); } static void readSide(const gamemap_t *map, uint idx) { uint i; long secIdx; float offset[2], rgba[4]; sidedef_t *s = &map->sideDefs[idx]; for(i = 0; i < 3; ++i) { surface_t *suf = &s->sections[3]; suf->flags = (int) readLong(); Surface_SetMaterial(suf, lookupMaterialFromDict(materialDict, readLong())); Surface_SetBlendMode(suf, (blendmode_t) readLong()); suf->normal[VX] = readFloat(); suf->normal[VY] = readFloat(); suf->normal[VZ] = readFloat(); offset[VX] = readFloat(); offset[VY] = readFloat(); Surface_SetMaterialOffsetXY(suf, offset[VX], offset[VY]); rgba[CR] = readFloat(); rgba[CG] = readFloat(); rgba[CB] = readFloat(); rgba[CA] = readFloat(); Surface_SetColorRGBA(suf, rgba[CR], rgba[CG], rgba[CB], rgba[CA]); suf->decorations = NULL; suf->numDecorations = 0; } secIdx = readLong(); s->sector = (secIdx == 0? NULL : &map->sectors[secIdx -1]); s->flags = readShort(); s->segCount = (uint) readLong(); s->segs = Z_Malloc(sizeof(seg_t*) * (s->segCount + 1), PU_MAP, 0); for(i = 0; i < s->segCount; ++i) s->segs[i] = &map->segs[(unsigned) readLong() - 1]; s->segs[i] = NULL; // Terminate. } static void archiveSides(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_SIDES); else assertSegment(DAMSEG_SIDES); if(write) { writeLong(map->numSideDefs); for(i = 0; i < map->numSideDefs; ++i) writeSide(map, i); } else { map->numSideDefs = readLong(); for(i = 0; i < map->numSideDefs; ++i) readSide(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writeSector(const gamemap_t *map, uint idx) { uint i; sector_t *s = &map->sectors[idx]; writeFloat(s->lightLevel); writeFloat(s->rgb[CR]); writeFloat(s->rgb[CG]); writeFloat(s->rgb[CB]); writeLong(s->planeCount); for(i = 0; i < s->planeCount; ++i) { plane_t *p = s->planes[i]; writeFloat(p->height); writeFloat(p->glow); writeFloat(p->glowRGB[CR]); writeFloat(p->glowRGB[CG]); writeFloat(p->glowRGB[CB]); writeFloat(p->target); writeFloat(p->speed); writeFloat(p->visHeight); writeFloat(p->visHeightDelta); writeLong((long) p->surface.flags); writeLong(getMaterialDictID(materialDict, p->surface.material)); writeLong((long) p->surface.blendMode); writeFloat(p->surface.normal[VX]); writeFloat(p->surface.normal[VY]); writeFloat(p->surface.normal[VZ]); writeFloat(p->surface.offset[VX]); writeFloat(p->surface.offset[VY]); writeFloat(p->surface.rgba[CR]); writeFloat(p->surface.rgba[CG]); writeFloat(p->surface.rgba[CB]); writeFloat(p->surface.rgba[CA]); writeFloat(p->soundOrg.pos[VX]); writeFloat(p->soundOrg.pos[VY]); writeFloat(p->soundOrg.pos[VZ]); } writeLong(s->flags); writeFloat(s->bBox[BOXLEFT]); writeFloat(s->bBox[BOXRIGHT]); writeFloat(s->bBox[BOXBOTTOM]); writeFloat(s->bBox[BOXTOP]); writeLong(s->lightSource? ((s->lightSource - map->sectors) + 1) : 0); writeFloat(s->soundOrg.pos[VX]); writeFloat(s->soundOrg.pos[VY]); writeFloat(s->soundOrg.pos[VZ]); for(i = 0; i < NUM_REVERB_DATA; ++i) writeFloat(s->reverb[i]); // Lightgrid block indices. writeLong((long) s->changedBlockCount); writeLong((long) s->blockCount); for(i = 0; i < s->blockCount; ++i) writeShort(s->blocks[i]); // Line list. writeLong((long) s->lineDefCount); for(i = 0; i < s->lineDefCount; ++i) writeLong((s->lineDefs[i] - map->lineDefs) + 1); // Subsector list. writeLong((long) s->ssectorCount); for(i = 0; i < s->ssectorCount; ++i) writeLong((s->ssectors[i] - map->ssectors) + 1); // Reverb subsector attributors. writeLong((long) s->numReverbSSecAttributors); for(i = 0; i < s->numReverbSSecAttributors; ++i) writeLong((s->reverbSSecs[i] - map->ssectors) + 1); } static void readSector(const gamemap_t *map, uint idx) { uint i, numPlanes; long secIdx; float offset[2], rgba[4]; sector_t *s = &map->sectors[idx]; s->lightLevel = readFloat(); s->rgb[CR] = readFloat(); s->rgb[CG] = readFloat(); s->rgb[CB] = readFloat(); numPlanes = (uint) readLong(); for(i = 0; i < numPlanes; ++i) { plane_t *p = R_NewPlaneForSector(s); p->height = readFloat(); p->glow = readFloat(); p->glowRGB[CR] = readFloat(); p->glowRGB[CG] = readFloat(); p->glowRGB[CB] = readFloat(); p->target = readFloat(); p->speed = readFloat(); p->visHeight = readFloat(); p->visHeightDelta = readFloat(); p->surface.flags = (int) readLong(); Surface_SetMaterial(&p->surface, lookupMaterialFromDict(materialDict, readLong())); Surface_SetBlendMode(&p->surface, (blendmode_t) readLong()); p->surface.normal[VX] = readFloat(); p->surface.normal[VY] = readFloat(); p->surface.normal[VZ] = readFloat(); offset[VX] = readFloat(); offset[VY] = readFloat(); Surface_SetMaterialOffsetXY(&p->surface, offset[VX], offset[VY]); rgba[CR] = readFloat(); rgba[CG] = readFloat(); rgba[CB] = readFloat(); rgba[CA] = readFloat(); Surface_SetColorRGBA(&p->surface, rgba[CR], rgba[CG], rgba[CB], rgba[CA]); p->soundOrg.pos[VX] = readFloat(); p->soundOrg.pos[VY] = readFloat(); p->soundOrg.pos[VZ] = readFloat(); p->surface.decorations = NULL; p->surface.numDecorations = 0; } secIdx = readLong(); s->flags = readLong(); s->bBox[BOXLEFT] = readFloat(); s->bBox[BOXRIGHT] = readFloat(); s->bBox[BOXBOTTOM] = readFloat(); s->bBox[BOXTOP] = readFloat(); secIdx = readLong(); s->lightSource = (secIdx == 0? NULL : &map->sectors[secIdx - 1]); s->soundOrg.pos[VX] = readFloat(); s->soundOrg.pos[VY] = readFloat(); s->soundOrg.pos[VZ] = readFloat(); for(i = 0; i < NUM_REVERB_DATA; ++i) s->reverb[i] = readFloat(); // Lightgrid block indices. s->changedBlockCount = (uint) readLong(); s->blockCount = (uint) readLong(); s->blocks = Z_Malloc(sizeof(short) * s->blockCount, PU_MAP, 0); for(i = 0; i < s->blockCount; ++i) s->blocks[i] = readShort(); // Line list. s->lineDefCount = (uint) readLong(); s->lineDefs = Z_Malloc(sizeof(linedef_t*) * (s->lineDefCount + 1), PU_MAP, 0); for(i = 0; i < s->lineDefCount; ++i) s->lineDefs[i] = &map->lineDefs[(unsigned) readLong() - 1]; s->lineDefs[i] = NULL; // Terminate. // Subsector list. s->ssectorCount = (uint) readLong(); s->ssectors = Z_Malloc(sizeof(subsector_t*) * (s->ssectorCount + 1), PU_MAP, 0); for(i = 0; i < s->ssectorCount; ++i) s->ssectors[i] = &map->ssectors[(unsigned) readLong() - 1]; s->ssectors[i] = NULL; // Terminate. // Reverb subsector attributors. s->numReverbSSecAttributors = (uint) readLong(); s->reverbSSecs = Z_Malloc(sizeof(subsector_t*) * (s->numReverbSSecAttributors + 1), PU_MAP, 0); for(i = 0; i < s->numReverbSSecAttributors; ++i) s->reverbSSecs[i] = &map->ssectors[(unsigned) readLong() - 1]; s->reverbSSecs[i] = NULL; // Terminate. } static void archiveSectors(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_SECTORS); else assertSegment(DAMSEG_SECTORS); if(write) { writeLong(map->numSectors); for(i = 0; i < map->numSectors; ++i) writeSector(map, i); } else { map->numSectors = readLong(); for(i = 0; i < map->numSectors; ++i) readSector(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writeSubsector(const gamemap_t *map, uint idx) { uint i; subsector_t *s = &map->ssectors[idx]; writeLong((long) s->flags); writeFloat(s->bBox[0].pos[VX]); writeFloat(s->bBox[0].pos[VY]); writeFloat(s->bBox[0].pos[VZ]); writeFloat(s->bBox[1].pos[VX]); writeFloat(s->bBox[1].pos[VY]); writeFloat(s->bBox[1].pos[VZ]); writeFloat(s->midPoint.pos[VX]); writeFloat(s->midPoint.pos[VY]); writeFloat(s->midPoint.pos[VZ]); writeLong(s->sector? ((s->sector - map->sectors) + 1) : 0); writeLong(s->polyObj? (s->polyObj->idx + 1) : 0); // Subsector reverb. for(i = 0; i < NUM_REVERB_DATA; ++i) writeLong((long) s->reverb[i]); // Subsector segs list. writeLong((long) s->segCount); for(i = 0; i < s->segCount; ++i) writeLong((s->segs[i] - map->segs) + 1); } static void readSubsector(const gamemap_t *map, uint idx) { uint i; long obIdx; subsector_t *s = &map->ssectors[idx]; s->flags = (int) readLong(); s->bBox[0].pos[VX] = readFloat(); s->bBox[0].pos[VY] = readFloat(); s->bBox[0].pos[VZ] = readFloat(); s->bBox[1].pos[VX] = readFloat(); s->bBox[1].pos[VY] = readFloat(); s->bBox[1].pos[VZ] = readFloat(); s->midPoint.pos[VX] = readFloat(); s->midPoint.pos[VY] = readFloat(); s->midPoint.pos[VZ] = readFloat(); obIdx = readLong(); s->sector = (obIdx == 0? NULL : &map->sectors[(unsigned) obIdx - 1]); obIdx = readLong(); s->polyObj = (obIdx == 0? NULL : map->polyObjs[(unsigned) obIdx - 1]); // Subsector reverb. for(i = 0; i < NUM_REVERB_DATA; ++i) s->reverb[i] = (uint) readLong(); // Subsector segs list. s->segCount = (uint) readLong(); s->segs = Z_Malloc(sizeof(seg_t*) * (s->segCount + 1), PU_MAP, 0); for(i = 0; i < s->segCount; ++i) s->segs[i] = &map->segs[(unsigned) readLong() - 1]; s->segs[i] = NULL; // Terminate. } static void archiveSubsectors(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_SSECTORS); else assertSegment(DAMSEG_SSECTORS); if(write) { writeLong(map->numSSectors); for(i = 0; i < map->numSSectors; ++i) writeSubsector(map, i); } else { map->numSSectors = readLong(); for(i = 0; i < map->numSSectors; ++i) readSubsector(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writeSeg(const gamemap_t *map, uint idx) { seg_t *s = &map->segs[idx]; writeLong((s->v[0] - map->vertexes) + 1); writeLong((s->v[1] - map->vertexes) + 1); writeFloat(s->length); writeFloat(s->offset); writeLong(s->lineDef? ((s->lineDef - map->lineDefs) + 1) : 0); writeLong(s->sec[FRONT]? ((s->sec[FRONT] - map->sectors) + 1) : 0); writeLong(s->sec[BACK]? ((s->sec[BACK] - map->sectors) + 1) : 0); writeLong(s->subsector? ((s->subsector - map->ssectors) + 1) : 0); writeLong(s->backSeg? ((s->backSeg - map->segs) + 1) : 0); writeLong((long) s->angle); writeByte(s->side); writeByte(s->flags); } static void readSeg(const gamemap_t *map, uint idx) { long obIdx; seg_t *s = &map->segs[idx]; s->v[0] = &map->vertexes[(unsigned) readLong() - 1]; s->v[1] = &map->vertexes[(unsigned) readLong() - 1]; s->length = readFloat(); s->offset = readFloat(); obIdx = readLong(); s->lineDef = (obIdx == 0? NULL : &map->lineDefs[(unsigned) obIdx - 1]); obIdx = readLong(); s->sec[FRONT] = (obIdx == 0? NULL : &map->sectors[(unsigned) obIdx - 1]); obIdx = readLong(); s->sec[BACK] = (obIdx == 0? NULL : &map->sectors[(unsigned) obIdx - 1]); obIdx = readLong(); s->subsector = (obIdx == 0? NULL : &map->ssectors[(unsigned) obIdx - 1]); obIdx = readLong(); s->backSeg = (obIdx == 0? NULL : &map->segs[(unsigned) obIdx - 1]); s->angle = (angle_t) readLong(); s->side = readByte(); s->flags = readByte(); } static void archiveSegs(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_SEGS); else assertSegment(DAMSEG_SEGS); if(write) { writeLong(map->numSegs); for(i = 0; i < map->numSegs; ++i) writeSeg(map, i); } else { map->numSegs = readLong(); for(i = 0; i < map->numSegs; ++i) readSeg(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writeNode(const gamemap_t *map, uint idx) { node_t *n = &map->nodes[idx]; writeFloat(n->partition.x); writeFloat(n->partition.y); writeFloat(n->partition.dX); writeFloat(n->partition.dY); writeFloat(n->bBox[RIGHT][BOXLEFT]); writeFloat(n->bBox[RIGHT][BOXRIGHT]); writeFloat(n->bBox[RIGHT][BOXBOTTOM]); writeFloat(n->bBox[RIGHT][BOXTOP]); writeFloat(n->bBox[LEFT][BOXLEFT]); writeFloat(n->bBox[LEFT][BOXRIGHT]); writeFloat(n->bBox[LEFT][BOXBOTTOM]); writeFloat(n->bBox[LEFT][BOXTOP]); writeLong((long) n->children[RIGHT]); writeLong((long) n->children[LEFT]); } static void readNode(const gamemap_t *map, uint idx) { node_t *n = &map->nodes[idx]; n->partition.x = readFloat(); n->partition.y = readFloat(); n->partition.dX = readFloat(); n->partition.dY = readFloat(); n->bBox[RIGHT][BOXLEFT] = readFloat(); n->bBox[RIGHT][BOXRIGHT] = readFloat(); n->bBox[RIGHT][BOXBOTTOM] = readFloat(); n->bBox[RIGHT][BOXTOP] = readFloat(); n->bBox[LEFT][BOXLEFT] = readFloat(); n->bBox[LEFT][BOXRIGHT] = readFloat(); n->bBox[LEFT][BOXBOTTOM] = readFloat(); n->bBox[LEFT][BOXTOP] = readFloat(); n->children[RIGHT] = (uint) readLong(); n->children[LEFT] = (uint) readLong(); } static void archiveNodes(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_NODES); else assertSegment(DAMSEG_NODES); if(write) { writeLong(map->numNodes); for(i = 0; i < map->numNodes; ++i) writeNode(map, i); } else { map->numNodes = readLong(); for(i = 0; i < map->numNodes; ++i) readNode(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void archiveBlockmap(gamemap_t *map, boolean write) { if(write) beginSegment(DAMSEG_BLOCKMAP); else assertSegment(DAMSEG_BLOCKMAP); if(write) endSegment(); else assertSegment(DAMSEG_END); } static void archiveReject(gamemap_t *map, boolean write) { if(write) beginSegment(DAMSEG_REJECT); else assertSegment(DAMSEG_REJECT); if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writePolyobj(const gamemap_t *map, uint idx) { uint i; polyobj_t *p = map->polyObjs[idx]; writeLong((long) p->idx); writeFloat(p->pos[VX]); writeFloat(p->pos[VY]); writeFloat(p->pos[VZ]); writeLong((long) p->angle); writeLong((long) p->tag); writeFloat(p->box[0][VX]); writeFloat(p->box[0][VY]); writeFloat(p->box[1][VX]); writeFloat(p->box[1][VY]); writeFloat(p->dest[VX]); writeFloat(p->dest[VY]); writeFloat(p->speed); writeLong((long) p->destAngle); writeLong((long) p->angleSpeed); writeByte(p->crush? 1 : 0); writeLong((long) p->seqType); writeLong((long) p->numSegs); for(i = 0; i < p->numSegs; ++i) { seg_t *s = p->segs[i]; writeLong((s->v[0] - map->vertexes) + 1); writeLong((s->v[1] - map->vertexes) + 1); writeFloat(s->length); writeFloat(s->offset); writeLong(s->lineDef? ((s->lineDef - map->lineDefs) + 1) : 0); writeLong(s->sec[FRONT]? ((s->sec[FRONT] - map->sectors) + 1) : 0); writeLong((long) s->angle); writeByte(s->side); writeByte(s->flags); } } static void readPolyobj(const gamemap_t *map, uint idx) { uint i; long obIdx; polyobj_t *p = map->polyObjs[idx]; p->idx = (uint) readLong(); p->pos[VX] = readFloat(); p->pos[VY] = readFloat(); p->pos[VZ] = readFloat(); p->angle = (angle_t) readLong(); p->tag = (int) readLong(); p->box[0][VX] = readFloat(); p->box[0][VY] = readFloat(); p->box[1][VX] = readFloat(); p->box[1][VY] = readFloat(); p->dest[VX] = readFloat(); p->dest[VY] = readFloat(); p->speed = readFloat(); p->destAngle = (angle_t) readLong(); p->angleSpeed = (angle_t) readLong(); p->crush = (readByte()? true : false); p->seqType = (int) readLong(); // Polyobj seg list. p->numSegs = (uint) readLong(); p->segs = Z_Malloc(sizeof(seg_t*) * (p->numSegs + 1), PU_MAP, 0); for(i = 0; i < p->numSegs; ++i) { seg_t *s = Z_Calloc(sizeof(*s), PU_MAP, 0); s->v[0] = &map->vertexes[(unsigned) readLong() - 1]; s->v[1] = &map->vertexes[(unsigned) readLong() - 1]; s->length = readFloat(); s->offset = readFloat(); obIdx = readLong(); s->lineDef = (obIdx == 0? NULL : &map->lineDefs[(unsigned) obIdx - 1]); obIdx = readLong(); s->sec[FRONT] = (obIdx == 0? NULL : &map->sectors[(unsigned) obIdx - 1]); s->angle = (angle_t) readLong(); s->side = (readByte()? 1 : 0); s->flags = readByte(); p->segs[i] = s; } p->segs[i] = NULL; // Terminate. } static void archivePolyobjs(gamemap_t *map, boolean write) { uint i; if(write) beginSegment(DAMSEG_POLYOBJS); else assertSegment(DAMSEG_POLYOBJS); if(write) { writeLong(map->numPolyObjs); for(i = 0; i < map->numPolyObjs; ++i) writePolyobj(map, i); } else { map->numPolyObjs = readLong(); for(i = 0; i < map->numPolyObjs; ++i) readPolyobj(map, i); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static void writeThing(const gamemap_t *map, uint idx) { } static void readThing(const gamemap_t *map, uint idx) { } static void archiveMap(gamemap_t *map, boolean write) { if(write) beginSegment(DAMSEG_MAP); else { assertSegment(DAMSEG_MAP); // Call the game's setup routines. if(gx.SetupForMapData) { gx.SetupForMapData(DMU_VERTEX, map->numVertexes); gx.SetupForMapData(DMU_LINEDEF, map->numLineDefs); gx.SetupForMapData(DMU_SIDEDEF, map->numSideDefs); gx.SetupForMapData(DMU_SECTOR, map->numSectors); } } archivePolyobjs(map, write); archiveVertexes(map, write); archiveLines(map, write); // Must follow vertexes (lineowner nodes). archiveSides(map, write); archiveSectors(map, write); archiveSubsectors(map, write); archiveSegs(map, write); archiveNodes(map, write); archiveBlockmap(map, write); archiveReject(map, write); if(write) endSegment(); else assertSegment(DAMSEG_END); } static void archiveMaterialDict(materialdict_t *dict, boolean write) { int i; if(write) { writeLong((long) dict->count); for(i = 0; i < dict->count; ++i) { writeNBytes(dict->table[i].name, 8); } } else { dict->count = readLong(); for(i = 0; i < dict->count; ++i) { readNBytes(dict->table[i].name, 8); dict->table[i].name[8] = 0; } } } static void archiveSymbolTables(boolean write) { if(write) beginSegment(DAMSEG_SYMBOLTABLES); else assertSegment(DAMSEG_SYMBOLTABLES); archiveMaterialDict(materialDict, write); if(write) endSegment(); else assertSegment(DAMSEG_END); } static void archiveRelocationTables(boolean write) { if(write) beginSegment(DAMSEG_RELOCATIONTABLES); else assertSegment(DAMSEG_RELOCATIONTABLES); if(write) endSegment(); else assertSegment(DAMSEG_END); } static void archiveHeader(boolean write) { if(write) beginSegment(DAMSEG_HEADER); else assertSegment(DAMSEG_HEADER); if(write) { writeLong(DAM_VERSION); } else { mapFileVersion = readLong(); } if(write) endSegment(); else assertSegment(DAMSEG_END); } static boolean doArchiveMap(gamemap_t *map, filename_t path, boolean write) { if(!path) return false; // Open the file. if(!openMapFile(path, write)) return false; // Hmm, invalid path? materialDict = M_Calloc(sizeof(*materialDict)); if(write) initMaterialDict(map, materialDict); archiveHeader(write); archiveRelocationTables(write); archiveSymbolTables(write); archiveMap(map, write); // Close the file. closeMapFile(); M_Free(materialDict); return true; } /** * Load data from a Doomsday archived map file. */ boolean DAM_MapWrite(gamemap_t *map, filename_t path) { return doArchiveMap(map, path, true); } /** * Write the current state of a map into a Doomsday archived map file. */ boolean DAM_MapRead(gamemap_t *map, filename_t path) { Con_Message("DAM_MapRead: Loading cached map. %s\n", path); return doArchiveMap(map, path, false); } /** * Check if archived map file is current. */ boolean DAM_MapIsValid(filename_t cachedMapDataFile, int markerLumpNum) { uint sourceTime, buildTime; // The source data must not be newer than the cached map data. sourceTime = F_LastModified(W_LumpSourceFile(markerLumpNum)); buildTime = F_LastModified(cachedMapDataFile); if(F_Access(cachedMapDataFile) && !(buildTime < sourceTime)) { // Ok, lets check the header. if(openMapFile(cachedMapDataFile, false)) { archiveHeader(false); closeMapFile(); if(mapFileVersion == DAM_VERSION) return true; // Its good. } } return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_polyob.c0000644000175000017500000004132111357170242022721 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_polyob.c: Polygon Objects * * Polyobj translation and rotation. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_play.h" #include "de_refresh.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void updateSegBBox(seg_t* seg); static void rotatePoint(int an, float* x, float* y, float startSpotX, float startSpotY); static boolean CheckMobjBlocking(seg_t* seg, polyobj_t* po); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Called when the polyobj hits a mobj. void (*po_callback) (mobj_t* mobj, void* seg, void* po); polyobj_t** polyObjs; // List of all poly-objects in the map. uint numPolyObjs; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * The po_callback is called when a polyobj hits a mobj. */ void P_SetPolyobjCallback(void (*func) (struct mobj_s*, void*, void*)) { po_callback = func; } /** * Retrieve a ptr to polyobj_t by index or by tag. * * @param num If MSB is set, treat num as an index, ELSE * num is a tag that *should* match one polyobj. */ polyobj_t* P_GetPolyobj(uint num) { if(num & 0x80000000) { uint idx = num & 0x7fffffff; if(idx < numPolyObjs) return polyObjs[idx]; } else { uint i; for(i = 0; i < numPolyObjs; ++i) { polyobj_t* po = polyObjs[i]; if((uint) po->tag == num) { return po; } } } return NULL; } /** * @return @c true, iff this is indeed a polyobj origin. */ boolean P_IsPolyobjOrigin(void* ddMobjBase) { uint i; polyobj_t* po; for(i = 0; i < numPolyObjs; ++i) { po = polyObjs[i]; if(po == ddMobjBase) { return true; } } return false; } static void updateSegBBox(seg_t* seg) { linedef_t* line = seg->lineDef; line->bBox[BOXLEFT] = MIN_OF(seg->SG_v2pos[VX], seg->SG_v1pos[VX]); line->bBox[BOXRIGHT] = MAX_OF(seg->SG_v2pos[VX], seg->SG_v1pos[VX]); line->bBox[BOXBOTTOM] = MIN_OF(seg->SG_v2pos[VY], seg->SG_v1pos[VY]); line->bBox[BOXTOP] = MAX_OF(seg->SG_v2pos[VY], seg->SG_v1pos[VY]); // Update the line's slopetype. line->dX = line->L_v2pos[VX] - line->L_v1pos[VX]; line->dY = line->L_v2pos[VY] - line->L_v1pos[VY]; if(!line->dX) { line->slopeType = ST_VERTICAL; } else if(!line->dY) { line->slopeType = ST_HORIZONTAL; } else { if(line->dY / line->dX > 0) { line->slopeType = ST_POSITIVE; } else { line->slopeType = ST_NEGATIVE; } } } /** * Update the polyobj bounding box. */ void P_PolyobjUpdateBBox(polyobj_t* po) { uint i; vec2_t point; vertex_t* vtx; seg_t** segPtr; segPtr = po->segs; V2_Set(point, (*segPtr)->SG_v1pos[VX], (*segPtr)->SG_v1pos[VY]); V2_InitBox(po->box, point); for(i = 0; i < po->numSegs; ++i, segPtr++) { vtx = (*segPtr)->SG_v1; V2_Set(point, vtx->V_pos[VX], vtx->V_pos[VY]); V2_AddToBox(po->box, point); } } /** * Called at the start of the map after all the structures needed for * refresh have been setup. */ void P_MapInitPolyobjs(void) { uint i; for(i = 0; i < numPolyObjs; ++i) { polyobj_t* po = polyObjs[i]; seg_t** segPtr; subsector_t* ssec; fvertex_t avg; // Used to find a polyobj's center, and hence subsector. avg.pos[VX] = 0; avg.pos[VY] = 0; segPtr = po->segs; while(*segPtr) { seg_t* seg = *segPtr; sidedef_t* side = SEG_SIDEDEF(seg); surface_t* surface = &side->SW_topsurface; side->SW_topinflags |= SUIF_NO_RADIO; side->SW_middleinflags |= SUIF_NO_RADIO; side->SW_bottominflags |= SUIF_NO_RADIO; avg.pos[VX] += seg->SG_v1pos[VX]; avg.pos[VY] += seg->SG_v1pos[VY]; // Set the surface normal. surface->normal[VY] = (seg->SG_v1pos[VX] - seg->SG_v2pos[VX]) / seg->length; surface->normal[VX] = (seg->SG_v2pos[VY] - seg->SG_v1pos[VY]) / seg->length; surface->normal[VZ] = 0; // All surfaces of a sidedef have the same normal. memcpy(side->SW_middlenormal, surface->normal, sizeof(surface->normal)); memcpy(side->SW_bottomnormal, surface->normal, sizeof(surface->normal)); *segPtr++; } avg.pos[VX] /= po->numSegs; avg.pos[VY] /= po->numSegs; ssec = R_PointInSubsector(avg.pos[VX], avg.pos[VY]); if(ssec) { if(ssec->polyObj) { Con_Message("P_MapInitPolyobjs: Warning: Multiple polyobjs in a single subsector\n" " (ssec %i, sector %i). Previous polyobj overridden.\n", GET_SUBSECTOR_IDX(ssec), GET_SECTOR_IDX(ssec->sector)); } ssec->polyObj = po; po->subsector = ssec; } P_PolyobjUnLink(po); P_PolyobjLink(po); } } boolean P_PolyobjMove(struct polyobj_s* po, float x, float y) { uint count; fvertex_t* prevPts; seg_t** segList; seg_t** veryTempSeg; boolean blocked; if(!po) return false; P_PolyobjUnLink(po); segList = po->segs; prevPts = po->prevPts; for(count = 0; count < po->numSegs; ++count, segList++, prevPts++) { seg_t* seg = *segList; seg->lineDef->bBox[BOXTOP] += y; seg->lineDef->bBox[BOXBOTTOM] += y; seg->lineDef->bBox[BOXLEFT] += x; seg->lineDef->bBox[BOXRIGHT] += x; for(veryTempSeg = po->segs; veryTempSeg != segList; veryTempSeg++) { if((*veryTempSeg)->SG_v1 == seg->SG_v1) { break; } } if(veryTempSeg == segList) { seg->SG_v1pos[VX] += x; seg->SG_v1pos[VY] += y; } (*prevPts).pos[VX] += x; // Previous points are unique for each seg. (*prevPts).pos[VY] += y; } segList = po->segs; blocked = false; for(count = 0; count < po->numSegs; ++count, segList++) { if(CheckMobjBlocking(*segList, po)) { blocked = true; } } if(blocked) { count = 0; segList = po->segs; prevPts = po->prevPts; for(count = 0; count < po->numSegs; ++count, segList++, prevPts++) { seg_t* seg = *segList; seg->lineDef->bBox[BOXTOP] -= y; seg->lineDef->bBox[BOXBOTTOM] -= y; seg->lineDef->bBox[BOXLEFT] -= x; seg->lineDef->bBox[BOXRIGHT] -= x; for(veryTempSeg = po->segs; veryTempSeg != segList; veryTempSeg++) { if((*veryTempSeg)->SG_v1 == seg->SG_v1) { break; } } if(veryTempSeg == segList) { seg->SG_v1pos[VX] -= x; seg->SG_v1pos[VY] -= y; } (*prevPts).pos[VX] -= x; (*prevPts).pos[VY] -= y; } P_PolyobjLink(po); return false; } po->pos[VX] += x; po->pos[VY] += y; P_PolyobjLink(po); // A change has occured. P_PolyobjChanged(po); return true; } static void rotatePoint(int an, float* x, float* y, float startSpotX, float startSpotY) { float trx, try, gxt, gyt; trx = *x; try = *y; gxt = trx * FIX2FLT(fineCosine[an]); gyt = try * FIX2FLT(finesine[an]); *x = gxt - gyt + startSpotX; gxt = trx * FIX2FLT(finesine[an]); gyt = try * FIX2FLT(fineCosine[an]); *y = gyt + gxt + startSpotY; } boolean P_PolyobjRotate(struct polyobj_s* po, angle_t angle) { int an; uint count; fvertex_t* originalPts; fvertex_t* prevPts; vertex_t* vtx; seg_t** segList; boolean blocked; if(!po) return false; an = (po->angle + angle) >> ANGLETOFINESHIFT; P_PolyobjUnLink(po); segList = po->segs; originalPts = po->originalPts; prevPts = po->prevPts; for(count = 0; count < po->numSegs; ++count, segList++, originalPts++, prevPts++) { seg_t* seg = *segList; vtx = seg->SG_v1; prevPts->pos[VX] = vtx->V_pos[VX]; prevPts->pos[VY] = vtx->V_pos[VY]; vtx->V_pos[VX] = originalPts->pos[VX]; vtx->V_pos[VY] = originalPts->pos[VY]; rotatePoint(an, &vtx->V_pos[VX], &vtx->V_pos[VY], po->pos[VX], po->pos[VY]); } segList = po->segs; for(count = 0; count < po->numSegs; ++count, segList++) { seg_t* seg = *segList; sidedef_t* side = SEG_SIDEDEF(seg); surface_t* surface = &side->SW_topsurface; updateSegBBox(seg); seg->angle += angle; seg->lineDef->angle += angle >> FRACBITS; // Now update the surface normal. surface->normal[VY] = (seg->SG_v1pos[VX] - seg->SG_v2pos[VX]) / seg->length; surface->normal[VX] = (seg->SG_v2pos[VY] - seg->SG_v1pos[VY]) / seg->length; surface->normal[VZ] = 0; // All surfaces of a sidedef have the same normal. memcpy(side->SW_middlenormal, surface->normal, sizeof(surface->normal)); memcpy(side->SW_bottomnormal, surface->normal, sizeof(surface->normal)); } segList = po->segs; blocked = false; for(count = 0; count < po->numSegs; ++count, segList++) { seg_t* seg = *segList; if(CheckMobjBlocking(seg, po)) { blocked = true; } } if(blocked) { segList = po->segs; prevPts = po->prevPts; for(count = 0; count < po->numSegs; ++count, segList++, prevPts++) { seg_t* seg = *segList; vtx = seg->SG_v1; vtx->V_pos[VX] = prevPts->pos[VX]; vtx->V_pos[VY] = prevPts->pos[VY]; } segList = po->segs; for(count = 0; count < po->numSegs; ++count, segList++) { seg_t* seg = *segList; sidedef_t* side = SEG_SIDEDEF(seg); surface_t* surface = &side->SW_topsurface; updateSegBBox(seg); seg->angle -= angle; seg->lineDef->angle -= angle >> FRACBITS; // Now update the surface normal. surface->normal[VY] = (seg->SG_v1pos[VX] - seg->SG_v2pos[VX]) / seg->length; surface->normal[VX] = (seg->SG_v2pos[VY] - seg->SG_v1pos[VY]) / seg->length; surface->normal[VZ] = 0; // All surfaces of a sidedef have the same normal. memcpy(side->SW_middlenormal, surface->normal, sizeof(surface->normal)); memcpy(side->SW_bottomnormal, surface->normal, sizeof(surface->normal)); } P_PolyobjLink(po); return false; } po->angle += angle; P_PolyobjLink(po); P_PolyobjChanged(po); return true; } void P_PolyobjLinkToRing(polyobj_t* po, linkpolyobj_t** link) { linkpolyobj_t* tempLink; if(!(*link)) { // Create a new link at the current block cell. *link = Z_Malloc(sizeof(linkpolyobj_t), PU_MAP, 0); (*link)->next = NULL; (*link)->prev = NULL; (*link)->polyobj = po; return; } else { tempLink = *link; while(tempLink->next != NULL && tempLink->polyobj != NULL) { tempLink = tempLink->next; } } if(tempLink->polyobj == NULL) { tempLink->polyobj = po; return; } else { tempLink->next = Z_Malloc(sizeof(linkpolyobj_t), PU_MAP, 0); tempLink->next->next = NULL; tempLink->next->prev = tempLink; tempLink->next->polyobj = po; } } void P_PolyobjUnlinkFromRing(polyobj_t* po, linkpolyobj_t** list) { linkpolyobj_t* iter = *list; while(iter != NULL && iter->polyobj != po) { iter = iter->next; } if(iter != NULL) { iter->polyobj = NULL; } } void P_PolyobjUnLink(struct polyobj_s* po) { P_BlockmapUnlinkPolyobj(BlockMap, po); } void P_PolyobjLink(struct polyobj_s* po) { P_BlockmapLinkPolyobj(BlockMap, po); } typedef struct ptrmobjblockingparams_s { boolean blocked; linedef_t* line; seg_t* seg; polyobj_t* po; } ptrmobjblockingparams_t; boolean PTR_CheckMobjBlocking(mobj_t* mo, void* data) { if((mo->ddFlags & DDMF_SOLID) || (mo->dPlayer && !(mo->dPlayer->flags & DDPF_CAMERA))) { float tmbbox[4]; ptrmobjblockingparams_t* params = data; tmbbox[BOXTOP] = mo->pos[VY] + mo->radius; tmbbox[BOXBOTTOM] = mo->pos[VY] - mo->radius; tmbbox[BOXLEFT] = mo->pos[VX] - mo->radius; tmbbox[BOXRIGHT] = mo->pos[VX] + mo->radius; if(!(tmbbox[BOXRIGHT] <= params->line->bBox[BOXLEFT] || tmbbox[BOXLEFT] >= params->line->bBox[BOXRIGHT] || tmbbox[BOXTOP] <= params->line->bBox[BOXBOTTOM] || tmbbox[BOXBOTTOM] >= params->line->bBox[BOXTOP])) { if(P_BoxOnLineSide(tmbbox, params->line) == -1) { if(po_callback) po_callback(mo, params->seg, params->po); params->blocked = true; } } } return true; // Continue iteration. } static boolean CheckMobjBlocking(seg_t* seg, polyobj_t* po) { uint blockBox[4]; vec2_t bbox[2]; linedef_t* ld; ptrmobjblockingparams_t params; params.blocked = false; params.line = ld = seg->lineDef; params.seg = seg; params.po = po; bbox[0][VX] = ld->bBox[BOXLEFT] - DDMOBJ_RADIUS_MAX; bbox[0][VY] = ld->bBox[BOXBOTTOM] - DDMOBJ_RADIUS_MAX; bbox[1][VX] = ld->bBox[BOXRIGHT] + DDMOBJ_RADIUS_MAX; bbox[1][VY] = ld->bBox[BOXTOP] + DDMOBJ_RADIUS_MAX; validCount++; P_BoxToBlockmapBlocks(BlockMap, blockBox, bbox); P_BlockBoxMobjsIterator(BlockMap, blockBox, PTR_CheckMobjBlocking, ¶ms); return params.blocked; } /** * Iterate the linedefs of the polyobj calling func for each. * Iteration will stop if func returns false. * * @param po The polyobj whose lines are to be iterated. * @param func Call back function to call for each line of this po. * @return @c true, if all callbacks are successfull. */ boolean P_PolyobjLinesIterator(polyobj_t* po, boolean (*func) (struct linedef_s*, void*), void* data) { uint i; seg_t** segList; segList = po->segs; for(i = 0; i < po->numSegs; ++i, segList++) { seg_t* seg = *segList; linedef_t* line = seg->lineDef; if(line->validCount == validCount) continue; line->validCount = validCount; if(!func(line, data)) return false; } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_master.c0000644000175000017500000003067711357170242023303 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * sys_master.c: Communication with the Master Server * * Communication with the master server, using TCP and HTTP. * The HTTP requests run in their own threads. * Sockets were initialized by sys_network. */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #ifdef WIN32 # define CURL_STATICLIB #endif #include #include "de_base.h" #include "de_network.h" #include "de_system.h" #include "de_console.h" #include "de_misc.h" #include "r_world.h" // MACROS ------------------------------------------------------------------ // Maximum time allowed time for a master server operation to take (seconds). #define RESPONSE_TIMEOUT 15 // TYPES ------------------------------------------------------------------- typedef struct serverlist_s { struct serverlist_s *next; serverinfo_t info; } serverlist_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void N_MasterClearList(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Master server info. Hardcoded defaults. char *masterAddress = "www.dengine.net"; int masterPort = 0; // Uses 80 by default. char *masterPath = "/master.php"; boolean masterAware = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // This variable will be true while a communication is in progress. static volatile boolean communicating; // A linked list of servers created from info retrieved from the master. static serverlist_t *servers; static int numServers; // CODE -------------------------------------------------------------------- /** * Called by N_Init() while initializing the low-level network subsystem. */ void N_MasterInit(void) { // Initialize libcurl. curl_global_init(CURL_GLOBAL_WIN32); communicating = false; } /** * Called by N_Shutdown() during engine shutdown. */ void N_MasterShutdown(void) { // Free the server list. (What if communicating?) N_MasterClearList(); // Clean up libcurl. curl_global_cleanup(); } /** * Clears our copy of the server list returned by the master. */ static void N_MasterClearList(void) { numServers = 0; while(servers) { serverlist_t *next = servers->next; M_Free(servers); servers = next; } } /** * Creates a new server and links it into our copy of the server list. * * @return Ptr to the newly created server. */ static serverlist_t *N_MasterNewServer(void) { serverlist_t *node; numServers++; node = M_Calloc(sizeof(serverlist_t)); node->next = servers; servers = node; return node; } /** * Callback function that sends outgoing data with libcurl. */ static size_t C_DECL N_MasterReadCallback(void *ptr, size_t size, size_t nmemb, void *stream) { ddstring_t *msg = stream; size_t bytes = size * nmemb; // Don't copy too much. bytes = MIN_OF(bytes, Str_Length(msg)); memcpy(ptr, msg->str, bytes); // Remove the sent portion from the buffer. Str_Set(msg, msg->str + bytes); // Number of bytes written to the buffer. return bytes; } /** * Callback function that receives incoming data from libcurl. */ static size_t C_DECL N_MasterWriteCallback(void *ptr, size_t size, size_t nmemb, void *stream) { ddstring_t* response = stream; size_t bytes = size * nmemb; //size_t pos = Str_Length(response); // Append the new data to the response. Str_Reserve(response, Str_Length(response) + bytes); memcpy(response->str, ptr, bytes); return bytes; } static void N_MasterGetUrl(char* url) { sprintf(url, "http://%s:%i%s", masterAddress, (masterPort? masterPort : 80), masterPath); #ifdef _DEBUG printf("%s\n", url); #endif } /** * Attempts to parses a list of servers from the given text string. * * @param response The string to be parsed. * * @return @c true, if successful. */ static int N_MasterParseResponse(ddstring_t *msg) { ddstring_t line; const char *pos; serverinfo_t *info = NULL; Str_Init(&line); // Clear the list of servers. N_MasterClearList(); // The syntax of the response is simple: // label:value // One or more empty lines separate servers. pos = Str_Text(msg); if(*pos) { boolean isDone = false; while(!isDone) { pos = Str_GetLine(&line, pos); if(Str_Length(&line) && !info) { // A new server begins. info = &N_MasterNewServer()->info; } else if(!Str_Length(&line) && info) { // No more current server. info = NULL; } if(info) Sv_StringToInfo(Str_Text(&line), info); if(!*pos) isDone = true; } } Str_Free(&line); return true; } /** * Send a request for the list of currently available servers. * This function runs as a thread. * * @param parm Not used. * * @return @c true, if the request was sent * successfully. */ static int C_DECL N_MasterSendRequest(void *parm) { ddstring_t response; char masterUrl[200]; char errorBuf[CURL_ERROR_SIZE]; boolean success = true; CURL *session; N_MasterGetUrl(masterUrl); strcat(masterUrl, "?list"); Str_Init(&response); // Prepare the curl session for our HTTP GET request. session = curl_easy_init(); #ifdef _DEBUG curl_easy_setopt(session, CURLOPT_VERBOSE, true); #endif curl_easy_setopt(session, CURLOPT_HEADER, false); curl_easy_setopt(session, CURLOPT_WRITEFUNCTION, N_MasterWriteCallback); curl_easy_setopt(session, CURLOPT_WRITEDATA, &response); curl_easy_setopt(session, CURLOPT_URL, masterUrl); curl_easy_setopt(session, CURLOPT_TIMEOUT, RESPONSE_TIMEOUT); curl_easy_setopt(session, CURLOPT_ERRORBUFFER, errorBuf); // Perform the operation. if(!curl_easy_perform(session)) { #ifdef _DEBUG printf(Str_Text(&response)); #endif // Let's parse the message. N_MasterParseResponse(&response); } else { success = false; fprintf(outFile, "N_MasterSendRequest: %s\n", errorBuf); } // Cleanup the curl session. curl_easy_cleanup(session); session = NULL; // We're done with the parsing. Str_Free(&response); communicating = false; return success; } /** * This function runs as a thread. * * NOTE: The info must be allocated from the heap. We will free it when it's * no longer needed. * * @param parm The announcement info to be sent. * * @return @c true, if the announcement was sent * successfully and the master responds "OK". */ static int C_DECL N_MasterSendAnnouncement(void *parm) { serverinfo_t *info = parm; ddstring_t msg; char masterUrl[200]; char errorBuf[CURL_ERROR_SIZE]; boolean success = true; CURL *session; struct curl_slist* headers = 0; headers = curl_slist_append(0, "Content-Type: application/x-deng-announce"); // Post a server announcement. N_MasterGetUrl(masterUrl); // Convert the serverinfo into plain text. Str_Init(&msg); Sv_InfoToString(info, &msg); // Free the serverinfo, it's no longer needed. M_Free(info); // Prepare the curl session for our HTTP POST request. session = curl_easy_init(); #ifdef _DEBUG curl_easy_setopt(session, CURLOPT_VERBOSE, true); #endif curl_easy_setopt(session, CURLOPT_POST, true); curl_easy_setopt(session, CURLOPT_HTTPHEADER, headers); curl_easy_setopt(session, CURLOPT_HEADER, false); curl_easy_setopt(session, CURLOPT_READFUNCTION, N_MasterReadCallback); curl_easy_setopt(session, CURLOPT_READDATA, &msg); curl_easy_setopt(session, CURLOPT_POSTFIELDSIZE, Str_Length(&msg)); curl_easy_setopt(session, CURLOPT_URL, masterUrl); curl_easy_setopt(session, CURLOPT_TIMEOUT, RESPONSE_TIMEOUT); curl_easy_setopt(session, CURLOPT_ERRORBUFFER, errorBuf); if(curl_easy_perform(session)) { // Failure. success = false; fprintf(outFile, "N_MasterSendAnnouncement: %s\n", errorBuf); } // Write an HTTP POST request with our info. /* N_SockPrintf(s, "POST %s HTTP/1.1\n", masterPath); N_SockPrintf(s, "Host: %s\n", masterAddress); N_SockPrintf(s, "Connection: close\n"); N_SockPrintf(s, \n"); N_SockPrintf(s, "Content-Length: %i\n\n", length); send(s, Str_Text(&msg), length, 0); */ Str_Free(&msg); // Cleanup the curl session. curl_slist_free_all(headers); curl_easy_cleanup(session); session = NULL; // The communication ends. communicating = false; // If the master responds "OK" return true, otherwise false. return success; } /** * Sends a server announcement to the master. The announcement includes our * IP address and other information. * * @param isOpen If @c true, then the server will be * visible on the server list for other clients to * find by querying the server list. */ void N_MasterAnnounceServer(boolean isOpen) { serverinfo_t *info; if(isClient) return; // Must be a server. // Are we already communicating with the master at the moment? if(communicating) { if(verbose) Con_Printf("N_MasterAnnounceServer: Request already in " "progress.\n"); return; } // The communication begins. communicating = true; // The info is not freed in this function, but in // N_MasterSendAnnouncement(). info = M_Calloc(sizeof(serverinfo_t)); // Let's figure out what we want to tell about ourselves. Sv_GetInfo(info); if(!isOpen) info->canJoin = false; Sys_StartThread(N_MasterSendAnnouncement, info); } /** * Requests the list of open servers from the master. */ void N_MasterRequestList(void) { // Are we already communicating with the master at the moment? if(communicating) { if(verbose) Con_Printf("N_MasterRequestList: Request already " "in progress.\n"); return; } // The communication begins. Will be cleared when the list is ready // for use. communicating = true; // Start a new thread for the request. Sys_StartThread(N_MasterSendRequest, NULL); } /** * Returns information about the server #N. * * @return @c 0, if communication with the master * is currently in progress. * If param info is @c NULL,, will return * the number of known servers ELSE, will return * @c not zero, if param index was valid * and the master returned info on the requested * server. */ int N_MasterGet(int index, serverinfo_t *info) { serverlist_t *it; if(communicating) return -1; if(!info) return numServers; // Find the index'th entry. for(it = servers; index > 0 && it; index--, it = it->next); // Was the index valid? if(!it) { memset(info, 0, sizeof(*info)); return false; } // Make a copy of the info. memcpy(info, &it->info, sizeof(*info)); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sv_missile.c0000644000175000017500000001151611357170242023256 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_missile.c: Delta Pool Missile Record */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * @return Pointer to the hash chain. */ mislink_t *Sv_MRHash(pool_t *pool, thid_t id) { return &pool->misHash[(unsigned) id % POOL_MISSILE_HASH_SIZE]; } /** * @return Pointer to the missile record for the specified ID, * else if no record exits; NULL. */ misrecord_t *Sv_MRFind(pool_t *pool, thid_t id) { mislink_t *hash = Sv_MRHash(pool, id); misrecord_t *mis; for(mis = hash->first; mis; mis = mis->next) { if(mis->id == id) { // This is it. return mis; } } return NULL; } /** * Adds an entry for the mobj into the missile record. */ void Sv_MRAdd(pool_t *pool, const mobjdelta_t *delta) { thid_t id = delta->delta.id; mislink_t *hash = Sv_MRHash(pool, id); misrecord_t *mis; #ifdef _DEBUG if(!(delta->mo.ddFlags & DDMF_MISSILE)) { Con_Error("Sv_MRAdd: Not a missile.\n"); } #endif // Try to find an existing entry. mis = Sv_MRFind(pool, id); // Create a new record if necessary. if(!mis) { mis = Z_Malloc(sizeof(misrecord_t), PU_MAP, 0); mis->id = id; // Link it in. mis->next = NULL; mis->prev = hash->last; if(hash->last) hash->last->next = mis; hash->last = mis; if(!hash->first) hash->first = mis; } // Update the momentum. /* mis->momx = delta->mo.momx; mis->momy = delta->mo.momy; mis->momz = delta->mo.momz; */ } /** * Remove the missile from the record. This is called when the missile * mobj is destroyed. */ void Sv_MRRemove(pool_t *pool, thid_t id) { mislink_t *hash = Sv_MRHash(pool, id); misrecord_t *mis; for(mis = hash->first; mis; mis = mis->next) { if(mis->id == id) { // This will be removed. if(hash->first == mis) hash->first = mis->next; if(hash->last == mis) hash->last = mis->prev; if(mis->next) mis->next->prev = mis->prev; if(mis->prev) mis->prev->next = mis->next; // There will be no more records to remove. break; } } } /** * @return The flags that should be excluded from the missile delta. */ int Sv_MRCheck(pool_t *pool, const mobjdelta_t *mobj) { misrecord_t *mis; int exclude = 0; #ifdef _DEBUG if(!(mobj->mo.ddFlags & DDMF_MISSILE)) { Con_Error("Sv_MRCheck: Not a missile.\n"); } #endif if((mis = Sv_MRFind(pool, mobj->delta.id)) == NULL) { // No record for this; no basis for exclusion. return 0; } // Exclude each axis separately. If no change in momentum, exclude coord. if(!(mobj->delta.flags & MDF_MOM_X)) exclude |= MDF_POS_X; if(!(mobj->delta.flags & MDF_MOM_Y)) exclude |= MDF_POS_Y; if(!(mobj->delta.flags & MDF_MOM_Z)) exclude |= MDF_POS_Z; return exclude; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/s_mus.c0000644000175000017500000004060611357170242022231 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_mus.c: Music Subsystem. */ // HEADER FILES ------------------------------------------------------------ #if WIN32 # include // for sqrt() #endif #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_audio.h" #include "de_misc.h" #include "sys_audio.h" #include "r_extres.h" #include "m_mus2midi.h" // MACROS ------------------------------------------------------------------ #define NUM_INTERFACES (sizeof(interfaces)/sizeof(interfaces[0])) // TYPES ------------------------------------------------------------------- typedef struct interface_info_s { audiointerface_music_generic_t** ip; const char* name; } interface_info_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(PlayMusic); D_CMD(PauseMusic); D_CMD(StopMusic); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // Music playback interfaces loaded from a sound driver plugin. extern audiointerface_music_t audiodExternalIMusic; extern audiointerface_cd_t audiodExternalICD; #ifdef MACOSX extern audiointerface_music_t audiodQuickTimeMusic; #endif // PUBLIC DATA DEFINITIONS ------------------------------------------------- int musPreference = MUSP_EXT; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean musAvail = false; static int currentSong = -1; static boolean musicPaused = false; // The interfaces. static audiointerface_music_t* iMusic; static audiointerface_cd_t* iCD; // The interface list. Used to access the common features of all the // interfaces conveniently. static interface_info_t interfaces[] = { {(audiointerface_music_generic_t**) &iMusic, "Music"}, {(audiointerface_music_generic_t**) &iCD, "CD"} }; // CODE -------------------------------------------------------------------- void Mus_Register(void) { // Cvars C_VAR_INT("music-volume", &musVolume, 0, 0, 255); C_VAR_INT("music-source", &musPreference, 0, 0, 2); // Ccmds C_CMD_FLAGS("playmusic", NULL, PlayMusic, CMDF_NO_DEDICATED); C_CMD_FLAGS("pausemusic", NULL, PauseMusic, CMDF_NO_DEDICATED); C_CMD_FLAGS("stopmusic", "", StopMusic, CMDF_NO_DEDICATED); } /** * Initialize the Mus module and choose the interfaces to use. * * @return @c true, if no errors occur. */ boolean Mus_Init(void) { unsigned int i; if(musAvail) return true; // Already initialized. if(isDedicated || ArgExists("-nomusic")) return true; // Use the external music playback facilities, if available. if(audioDriver == &audiod_dummy) { iMusic = NULL; iCD = NULL; } else if(audioDriver == &audiod_sdlmixer) { iMusic = (audiointerface_music_t*) &audiod_sdlmixer_music; iCD = NULL; } else { iMusic = (audiodExternalIMusic.gen.Init ? &audiodExternalIMusic : 0); iCD = (audiodExternalICD.gen.Init ? &audiodExternalICD : 0); } #ifdef MACOSX // On the Mac, just use QuickTime for the music and be done with it. iMusic = &audiodQuickTimeMusic; #endif // Initialize the chosen interfaces. for(i = 0; i < NUM_INTERFACES; ++i) { if(*interfaces[i].ip && !(*interfaces[i].ip)->Init()) { Con_Message("Mus_Init: Failed to initialize %s interface.\n", interfaces[i].name); *interfaces[i].ip = NULL; } } // Print a list of the chosen interfaces. if(verbose) { char buf[40]; Con_Printf("Mus_Init: Interfaces:"); for(i = 0; i < NUM_INTERFACES; ++i) { if(*interfaces[i].ip) { if(!(*interfaces[i].ip)->Get(MUSIP_ID, buf)) strcpy(buf, "?"); Con_Printf(" %s", buf); } } Con_Printf("\n"); } currentSong = -1; musAvail = true; return true; } void Mus_Shutdown(void) { if(!musAvail) return; musAvail = false; // No more interfaces. iMusic = 0; iCD = 0; } /** * Called on each frame by S_StartFrame. */ void Mus_StartFrame(void) { unsigned int i; if(!musAvail) return; // Update all interfaces. for(i = 0; i < NUM_INTERFACES; ++i) { if(*interfaces[i].ip) (*interfaces[i].ip)->Update(); } } /** * Set the general music volume. Affects all music played by all interfaces. */ void Mus_SetVolume(float vol) { unsigned int i; if(!musAvail) return; // Set volume of all available interfaces. for(i = 0; i < NUM_INTERFACES; ++i) { if(*interfaces[i].ip) (*interfaces[i].ip)->Set(MUSIP_VOLUME, vol); } } /** * Pauses or resumes the music. */ void Mus_Pause(boolean doPause) { unsigned int i; if(!musAvail) return; // Pause all interfaces. for(i = 0; i < NUM_INTERFACES; ++i) { if(*interfaces[i].ip) (*interfaces[i].ip)->Pause(doPause); } } void Mus_Stop(void) { unsigned int i; if(!musAvail) return; currentSong = -1; // Stop all interfaces. for(i = 0; i < NUM_INTERFACES; ++i) { if(*interfaces[i].ip) (*interfaces[i].ip)->Stop(); } } /** * @return: @c true, if the specified lump contains a MUS song. */ boolean Mus_IsMUSLump(int lump) { char buf[4]; W_ReadLumpSection(lump, buf, 0, 4); // ASCII "MUS" and CTRL-Z (hex 4d 55 53 1a) return !strncmp(buf, "MUS\x01a", 4); } /** * Check for the existence of an "external" music file. * Songs can be either in external files or non-MUS lumps. * * @return Non-zero if an external file of that name exists. */ int Mus_GetExt(ded_music_t* def, filename_t retPath) { filename_t path; if(!musAvail || !iMusic) return false; // All external music files are specified relative to the base path. if(def->path.path[0]) { M_PrependBasePath(path, def->path.path, DED_PATH_LEN); if(F_Access(path)) { // Return the real file name if not just checking. if(retPath) { strncpy(retPath, path, FILENAME_T_MAXLEN); } return true; } Con_Message("Mus_GetExt: Song %s: %s not found.\n", def->id, def->path.path); } // Try the resource locator. if(R_FindResource(RT_MUSIC, path, def->lumpName, NULL, FILENAME_T_MAXLEN)) { if(retPath) { strncpy(retPath, path, FILENAME_T_MAXLEN); } return true; } return false; } /** * @return: The track number if successful else zero. */ int Mus_GetCD(ded_music_t* def) { if(!musAvail || !iCD) return 0; if(def->cdTrack) return def->cdTrack; if(!strnicmp(def->path.path, "cd:", 3)) return atoi(def->path.path + 3); return 0; } static void composeBufferedMusicFilename(char* path, size_t len, int id, const char* ext) { #define BUFFERED_MUSIC_FILE "dd-buffered-song" if(ext && ext[0]) { dd_snprintf(path, len, "%s%i%s", BUFFERED_MUSIC_FILE, id, ext); return; } dd_snprintf(path, len, "%s%i", BUFFERED_MUSIC_FILE, id); #undef BUFFERED_MUSIC_FILE } /** * Start playing a song. The chosen interface depends on what's available * and what kind of resources have been associated with the song. * Any previously playing song is stopped. * * @return Non-zero if the song is successfully played. */ int Mus_Start(ded_music_t* def, boolean looped) { static int currentBufFile = 0; filename_t path; int i, order[3], songID; if(!musAvail) return false; songID = def - defs.music; // We will not restart the currently playing song. if(songID == currentSong && ((iMusic && iMusic->gen.Get(MUSIP_PLAYING, NULL)) || (iCD && iCD->gen.Get(MUSIP_PLAYING, NULL)))) return false; // Stop the currently playing song. Mus_Stop(); // This is the song we're playing now. currentSong = songID; // Choose the order in which to try to start the song. order[0] = musPreference; switch(musPreference) { case MUSP_CD: order[1] = MUSP_EXT; order[2] = MUSP_MUS; break; case MUSP_EXT: order[1] = MUSP_MUS; order[2] = MUSP_CD; break; default: // MUSP_MUS order[1] = MUSP_EXT; order[2] = MUSP_CD; break; } // Try to start the song. for(i = 0; i < 3; ++i) { boolean canPlayMUS = true; switch(order[i]) { case MUSP_CD: if(Mus_GetCD(def)) return iCD->Play(Mus_GetCD(def), looped); break; case MUSP_EXT: if(Mus_GetExt(def, path)) { // Its an external file. // The song may be in a virtual file, so we must buffer // it ourselves. DFILE* file = F_Open(path, "rb"); size_t len = F_Length(file); if(!iMusic->Play) { // Music interface does not offer buffer playback. // Write to disk and play from there. FILE* outFile; void* buf = malloc(len); filename_t fname; composeBufferedMusicFilename(fname, FILENAME_T_MAXLEN, currentBufFile ^= 1, NULL); if((outFile = fopen(fname, "wb")) == NULL) { Con_Message("Mus_Start: Couldn't open %s for writing. %s\n", fname, strerror(errno)); F_Close(file); return false; } F_Read(buf, len, file); fwrite(buf, 1, len, outFile); fclose(outFile); F_Close(file); return iMusic->PlayFile(fname, looped); } else { // Music interface offers buffered playback. Use it. void* ptr; VERBOSE(Con_Message("Mus_GetExt: Opened Song %s " "(File \"%s\" %u bytes)\n", def->id, M_PrettyPath(path), (unsigned int) len)); ptr = iMusic->SongBuffer(len); F_Read(ptr, len, file); F_Close(file); return iMusic->Play(looped); } } // Next, try non-MUS lumps. canPlayMUS = false; // Fall through. case MUSP_MUS: if(iMusic) { lumpnum_t lump; if((lump = W_CheckNumForName(def->lumpName)) != -1) { filename_t fname; const char* srcFile = NULL; if(Mus_IsMUSLump(lump)) { // Lump is in DOOM's MUS format. void* buf; size_t len; if(!canPlayMUS) break; composeBufferedMusicFilename(fname, FILENAME_T_MAXLEN, currentBufFile ^= 1, ".mid"); srcFile = fname; // Read the lump, convert to MIDI and output to a // temp file in the working directory. Use a // filename with the .mid extension so that the // player knows the format. len = W_LumpLength(lump); buf = M_Malloc(len); W_ReadLump(lump, buf); M_Mus2Midi(buf, len, srcFile); M_Free(buf); } else if(!iMusic->Play) { // Music interface does not offer buffer playback. // Write this lump to disk and play from there. composeBufferedMusicFilename(fname, FILENAME_T_MAXLEN, currentBufFile ^= 1, NULL); srcFile = fname; if(!W_DumpLump(lump, srcFile)) return false; } if(srcFile) return iMusic->PlayFile(srcFile, looped); W_ReadLump(lump, iMusic->SongBuffer(W_LumpLength(lump))); return iMusic->Play(looped); } } break; default: Con_Error("Mus_Start: Invalid value, order[i] = %i.", order[i]); break; } } // The song was not started. return false; } /** * CCmd: Play a music track. */ D_CMD(PlayMusic) { int i; size_t len; void* ptr; filename_t buf; if(!musAvail) { Con_Printf("The Mus module is not available.\n"); return false; } switch(argc) { default: Con_Printf("Usage:\n %s (music-def)\n", argv[0]); Con_Printf(" %s lump (lumpname)\n", argv[0]); Con_Printf(" %s file (filename)\n", argv[0]); Con_Printf(" %s cd (track)\n", argv[0]); break; case 2: i = Def_GetMusicNum(argv[1]); if(i < 0) { Con_Printf("Music '%s' not defined.\n", argv[1]); return false; } Mus_Start(&defs.music[i], true); break; case 3: if(!stricmp(argv[1], "lump")) { i = W_CheckNumForName(argv[2]); if(i < 0) return false; // No such lump. if(iMusic) { Mus_Stop(); ptr = iMusic->SongBuffer(len = W_LumpLength(i)); W_ReadLump(i, ptr); return iMusic->Play(true); } Con_Printf("No music interface available.\n"); return false; } else if(!stricmp(argv[1], "file")) { M_TranslatePath(buf, argv[2], FILENAME_T_MAXLEN); if(iMusic) { Mus_Stop(); return iMusic->PlayFile(buf, true); } Con_Printf("No music interface available.\n"); return false; } else { // Perhaps a CD track? if(!stricmp(argv[1], "cd")) { if(iCD) { Mus_Stop(); return iCD->Play(atoi(argv[2]), true); } Con_Printf("No CDAudio interface available.\n"); return false; } } break; } return true; } D_CMD(StopMusic) { Mus_Stop(); return true; } D_CMD(PauseMusic) { musicPaused = !musicPaused; Mus_Pause(musicPaused); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_lgrid.c0000644000175000017500000007133411357170242022527 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_lgrid.c: Light Grid (Large-Scale FakeRadio) * * Very simple global illumination method utilizing a 2D grid of light * levels. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_misc.h" #include "de_play.h" #include #include // MACROS ------------------------------------------------------------------ #define GRID_BLOCK(x, y) (&grid[(y)*lgBlockWidth + (x)]) #define GBF_CHANGED 0x1 // Grid block sector light has changed. #define GBF_CONTRIBUTOR 0x2 // Contributes light to a changed block. BEGIN_PROF_TIMERS() PROF_GRID_UPDATE END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- typedef struct gridblock_s { struct sector_s *sector; byte flags; // Positive bias means that the light is shining in the floor of // the sector. char bias; // Color of the light: float rgb[3]; float oldRGB[3]; // Used instead of rgb if the lighting in this // block has changed and we haven't yet done a // a full grid update. } gridblock_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ int lgEnabled = false; static boolean lgInited; static boolean needsUpdate = true; static int lgShowDebug = false; static float lgDebugSize = 1.5f; static int lgBlockSize = 31; static float lgOrigin[3]; static int lgBlockWidth; static int lgBlockHeight; static gridblock_t *grid; static int lgMXSample = 1; // Default is mode 1 (5 samples per block) // CODE -------------------------------------------------------------------- /** * Registers console variables. */ void LG_Register(void) { C_VAR_INT("rend-bias-grid", &lgEnabled, 0, 0, 1); C_VAR_INT("rend-bias-grid-debug", &lgShowDebug, 0, 0, 1); C_VAR_FLOAT("rend-bias-grid-debug-size", &lgDebugSize, 0, .1f, 100); C_VAR_INT("rend-bias-grid-blocksize", &lgBlockSize, 0, 8, 1024); C_VAR_INT("rend-bias-grid-multisample", &lgMXSample, 0, 0, 7); } /** * Determines if the index (x, y) is in the bitfield. */ static boolean HasIndexBit(int x, int y, uint *bitfield) { uint index = x + y * lgBlockWidth; // Assume 32-bit uint. return (bitfield[index >> 5] & (1 << (index & 0x1f))) != 0; } /** * Sets the index (x, y) in the bitfield. * Count is incremented when a zero bit is changed to one. */ static void AddIndexBit(int x, int y, uint *bitfield, int *count) { uint index = x + y * lgBlockWidth; // Assume 32-bit uint. if(!HasIndexBit(index, 0, bitfield)) { (*count)++; } bitfield[index >> 5] |= (1 << (index & 0x1f)); } /** * Initialize the light grid for the current map. */ void LG_Init(void) { uint startTime = Sys_GetRealTime(); #define MSFACTORS 7 typedef struct lgsamplepoint_s { float pos[3]; } lgsamplepoint_t; // Diagonal in maze arrangement of natural numbers. // Up to 65 samples per-block(!) static int multisample[] = {1, 5, 9, 17, 25, 37, 49, 65}; float max[3]; float width, height; int i = 0; int a, b, x, y; int count; int changedCount; size_t bitfieldSize; uint *indexBitfield = 0; uint *contributorBitfield = 0; gridblock_t *block; int *sampleResults = 0; int n, size, numSamples, center, best; uint s; float off[2]; lgsamplepoint_t *samplePoints = 0, sample; sector_t **ssamples; sector_t **blkSampleSectors; gamemap_t *map = P_GetCurrentMap(); if(!lgEnabled) { lgInited = false; return; } lgInited = true; // Allocate the grid. P_GetMapBounds(map, &lgOrigin[0], &max[0]); width = max[VX] - lgOrigin[VX]; height = max[VY] - lgOrigin[VY]; lgBlockWidth = ROUND(width / lgBlockSize) + 1; lgBlockHeight = ROUND(height / lgBlockSize) + 1; // Clamp the multisample factor. if(lgMXSample > MSFACTORS) lgMXSample = MSFACTORS; else if(lgMXSample < 0) lgMXSample = 0; numSamples = multisample[lgMXSample]; // Allocate memory for sample points array. samplePoints = M_Malloc(sizeof(lgsamplepoint_t) * numSamples); /** * It would be possible to only allocate memory for the unique * sample results. And then select the appropriate sample in the loop * for initializing the grid instead of copying the previous results in * the loop for acquiring the sample points. * * Calculate with the equation (number of unique sample points): * * ((1 + lgBlockHeight * lgMXSample) * (1 + lgBlockWidth * lgMXSample)) + * (size % 2 == 0? numBlocks : 0) * OR * * We don't actually need to store the ENTIRE sample points array. It * would be sufficent to only store the results from the start of the * previous row to current col index. This would save a bit of memory. * * However until lightgrid init is finalized it would be rather silly * to optimize this much further. */ // Allocate memory for all the sample results. ssamples = M_Malloc(sizeof(sector_t*) * ((lgBlockWidth * lgBlockHeight) * numSamples)); // Determine the size^2 of the samplePoint array plus its center. size = center = 0; if(numSamples > 1) { float f = sqrt(numSamples); if(ceil(f) != floor(f)) { size = sqrt(numSamples -1); center = 0; } else { size = (int) f; center = size+1; } } // Construct the sample point offset array. // This way we can use addition only during calculation of: // (lgBlockHeight*lgBlockWidth)*numSamples if(center == 0) { // Zero is the center so do that first. samplePoints[0].pos[VX] = lgBlockSize / 2; samplePoints[0].pos[VY] = lgBlockSize / 2; } if(numSamples > 1) { float bSize = (float) lgBlockSize / (size-1); // Is there an offset? if(center == 0) n = 1; else n = 0; for(y = 0; y < size; ++y) for(x = 0; x < size; ++x, ++n) { samplePoints[n].pos[VX] = ROUND(x * bSize); samplePoints[n].pos[VY] = ROUND(y * bSize); } } /* #if _DEBUG for(n = 0; n < numSamples; ++n) Con_Message(" %i of %i %i(%f %f)\n", n, numSamples, (n == center)? 1 : 0, samplePoints[n].pos[VX], samplePoints[n].pos[VY]); #endif */ // Acquire the sectors at ALL the sample points. for(y = 0; y < lgBlockHeight; ++y) { off[VY] = y * lgBlockSize; for(x = 0; x < lgBlockWidth; ++x) { int blk = (x + y * lgBlockWidth); int idx; off[VX] = x * lgBlockSize; n = 0; if(center == 0) { // Center point is not considered with the term 'size'. // Sample this point and place at index 0 (at the start // of the samples for this block). idx = blk * (numSamples); sample.pos[VX] = lgOrigin[VX] + off[VX] + samplePoints[0].pos[VX]; sample.pos[VY] = lgOrigin[VY] + off[VY] + samplePoints[0].pos[VY]; ssamples[idx] = R_PointInSubsector(sample.pos[VX], sample.pos[VY])->sector; if(!R_IsPointInSector2(sample.pos[VX], sample.pos[VY], ssamples[idx])) ssamples[idx] = NULL; n++; // Offset the index in the samplePoints array bellow. } count = blk * size; for(b = 0; b < size; ++b) { i = (b + count) * size; for(a = 0; a < size; ++a, ++n) { idx = a + i; if(center == 0) idx += blk + 1; if(numSamples > 1 && ((x > 0 && a == 0) || (y > 0 && b == 0))) { // We have already sampled this point. // Get the previous result. int prevX, prevY, prevA, prevB; int previdx; prevX = x; prevY = y; prevA = a; prevB = b; if(x > 0 && a == 0) { prevA = size -1; prevX--; } if(y > 0 && b == 0) { prevB = size -1; prevY--; } previdx = prevA + (prevB + (prevX + prevY * lgBlockWidth) * size) * size; if(center == 0) previdx += (prevX + prevY * lgBlockWidth) + 1; ssamples[idx] = ssamples[previdx]; } else { // We haven't sampled this point yet. sample.pos[VX] = lgOrigin[VX] + off[VX] + samplePoints[n].pos[VX]; sample.pos[VY] = lgOrigin[VY] + off[VY] + samplePoints[n].pos[VY]; ssamples[idx] = R_PointInSubsector(sample.pos[VX], sample.pos[VY])->sector; if(!R_IsPointInSector2(sample.pos[VX], sample.pos[VY], ssamples[idx])) ssamples[idx] = NULL; } } } } } // We're done with the samplePoints block. M_Free(samplePoints); // Bitfields for marking affected blocks. Make sure each bit is in a word. bitfieldSize = 4 * (31 + lgBlockWidth * lgBlockHeight) / 32; indexBitfield = M_Calloc(bitfieldSize); contributorBitfield = M_Calloc(bitfieldSize); // \todo It would be possible to only allocate memory for the grid // blocks that are going to be in use. // Allocate memory for the entire grid. grid = Z_Calloc(sizeof(gridblock_t) * lgBlockWidth * lgBlockHeight, PU_MAP, NULL); Con_Message("LG_Init: %i x %i grid (%lu bytes).\n", lgBlockWidth, lgBlockHeight, (unsigned long) (sizeof(gridblock_t) * lgBlockWidth * lgBlockHeight)); // Allocate memory used for the collection of the sample results. blkSampleSectors = M_Malloc(sizeof(sector_t*) * numSamples); if(numSamples > 1) sampleResults = M_Calloc(sizeof(int) * numSamples); // Initialize the grid. for(block = grid, y = 0; y < lgBlockHeight; ++y) { off[VY] = y * lgBlockSize; for(x = 0; x < lgBlockWidth; ++x, ++block) { off[VX] = x * lgBlockSize; /** * Pick the sector at each of the sample points. * \todo We don't actually need the blkSampleSectors array * anymore. Now that ssamples stores the results consecutively * a simple index into ssamples would suffice. * However if the optimization to save memory is implemented as * described in the comments above we WOULD still require it. * Therefore, for now I'm making use of it to clarify the code. */ n = (x + y * lgBlockWidth) * numSamples; for(i = 0; i < numSamples; ++i) blkSampleSectors[i] = ssamples[i + n]; block->sector = NULL; if(numSamples == 1) { block->sector = blkSampleSectors[center]; } else { // Pick the sector which had the most hits. best = -1; memset(sampleResults, 0, sizeof(int) * numSamples); for(i = 0; i < numSamples; ++i) if(blkSampleSectors[i]) for(a = 0; a < numSamples; ++a) if(blkSampleSectors[a] == blkSampleSectors[i] && blkSampleSectors[a]) { sampleResults[a]++; if(sampleResults[a] > best) best = i; } if(best != -1) { // Favour the center sample if its a draw. if(sampleResults[best] == sampleResults[center] && blkSampleSectors[center]) block->sector = blkSampleSectors[center]; else block->sector = blkSampleSectors[best]; } } } } // We're done with sector samples completely. M_Free(ssamples); // We're done with the sample results arrays. M_Free(blkSampleSectors); if(numSamples > 1) M_Free(sampleResults); // Find the blocks of all sectors. for(s = 0; s < numSectors; ++s) { sector_t *sector = SECTOR_PTR(s); // Clear the bitfields. memset(indexBitfield, 0, bitfieldSize); memset(contributorBitfield, 0, bitfieldSize); count = changedCount = 0; for(block = grid, y = 0; y < lgBlockHeight; ++y) { for(x = 0; x < lgBlockWidth; ++x, ++block) { if(block->sector == sector) { // \todo Determine min/max a/b before going into the loop. for(b = -2; b <= 2; ++b) { if(y + b < 0 || y + b >= lgBlockHeight) continue; for(a = -2; a <= 2; ++a) { if(x + a < 0 || x + a >= lgBlockWidth) continue; AddIndexBit(x + a, y + b, indexBitfield, &changedCount); } } } } } // Determine contributor blocks. Contributors are the blocks that are // close enough to contribute light to affected blocks. for(y = 0; y < lgBlockHeight; ++y) { for(x = 0; x < lgBlockWidth; ++x) { if(!HasIndexBit(x, y, indexBitfield)) continue; // Add the contributor blocks. for(b = -2; b <= 2; ++b) { if(y + b < 0 || y + b >= lgBlockHeight) continue; for(a = -2; a <= 2; ++a) { if(x + a < 0 || x + a >= lgBlockWidth) continue; if(!HasIndexBit(x + a, y + b, indexBitfield)) { AddIndexBit(x + a, y + b, contributorBitfield, &count); } } } } } /*if _DEBUG Con_Message(" Sector %i: %i / %i\n", s, changedCount, count); #endif*/ sector->changedBlockCount = changedCount; sector->blockCount = changedCount + count; if(sector->blockCount > 0) { sector->blocks = Z_Malloc(sizeof(unsigned short) * sector->blockCount, PU_MAPSTATIC, 0); for(x = 0, a = 0, b = changedCount; x < lgBlockWidth * lgBlockHeight; ++x) { if(HasIndexBit(x, 0, indexBitfield)) sector->blocks[a++] = x; else if(HasIndexBit(x, 0, contributorBitfield)) sector->blocks[b++] = x; } assert(a == changedCount); //assert(b == info->blockCount); } else { sector->blocks = NULL; } } M_Free(indexBitfield); M_Free(contributorBitfield); // How much time did we spend? VERBOSE(Con_Message ("LG_Init: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } /** * Apply the sector's lighting to the block. */ static void LG_ApplySector(gridblock_t *block, const float *color, float level, float factor, int bias) { int i; // Apply a bias to the light level. level -= (0.95f - level); if(level < 0) level = 0; level *= factor; if(level <= 0) return; for(i = 0; i < 3; ++i) { float c = color[i] * level; c = MINMAX_OF(0, c, 1); if(block->rgb[i] + c > 1) { block->rgb[i] = 1; } else { block->rgb[i] += c; } } // Influenced by the source bias. i = block->bias * (1 - factor) + bias * factor; i = MINMAX_OF(-0x80, i, 0x7f); block->bias = i; } /** * Called when a sector has changed its light level. */ void LG_SectorChanged(sector_t *sector) { uint i, j; unsigned short n; if(!lgInited) return; // Mark changed blocks and contributors. for(i = 0; i < sector->changedBlockCount; ++i) { n = sector->blocks[i]; // The color will be recalculated. if(!(grid[n].flags & GBF_CHANGED)) memcpy(grid[n].oldRGB, grid[n].rgb, sizeof(grid[n].oldRGB)); for(j = 0; j < 3; ++j) grid[n].rgb[j] = 0; grid[n].flags |= GBF_CHANGED | GBF_CONTRIBUTOR; } for(; i < sector->blockCount; ++i) { grid[sector->blocks[i]].flags |= GBF_CONTRIBUTOR; } needsUpdate = true; } /** * Called when a setting is changed which affects the lightgrid. */ void LG_MarkAllForUpdate(cvar_t *unused) { uint i; if(!lgInited) return; // Mark all blocks and contributors. for(i = 0; i < numSectors; ++i) { LG_SectorChanged(§ors[i]); } } #if 0 /* * Determines whether it is necessary to recalculate the lighting of a * grid block. Updates are needed when there has been a light level * or color change in a sector that affects the block. */ static boolean LG_BlockNeedsUpdate(int x, int y) { // First check the block itself. gridblock_t *block = GRID_BLOCK(x, y); sector_t *blockSector; int a, b; int limitA[2]; int limitB; blockSector = block->sector; if(!blockSector) { // The sector needs to be determined. return true; } if(SECT_INFO(blockSector)->flags & SIF_LIGHT_CHANGED) { return true; } // Check neighbor blocks as well. // Determine neighbor boundaries. Y coordinate. if(y >= 2) { b = y - 2; } else { b = 0; } if(y <= lgBlockHeight - 3) { limitB = y + 2; } else { limitB = lgBlockHeight - 1; } // X coordinate. if(x >= 2) { limitA[0] = x - 2; } else { limitA[0] = 0; } if(x <= lgBlockWidth - 3) { limitA[1] = x + 2; } else { limitA[1] = lgBlockWidth - 1; } // Iterate through neighbors. for(; b <= limitB; ++b) { a = limitA[0]; block = GRID_BLOCK(a, b); for(; a <= limitA[1]; ++a, ++block) { if(!a && !b) continue; if(block->sector == blockSector) continue; if(SECT_INFO(block->sector)->flags & SIF_LIGHT_CHANGED) { return true; } } } return false; } #endif /** * Update the grid by finding the strongest light source in each grid * block. */ void LG_Update(void) { static const float factors[5 * 5] = { .1f, .2f, .25f, .2f, .1f, .2f, .4f, .5f, .4f, .2f, .25f, .5f, 1.f, .5f, .25f, .2f, .4f, .5f, .4f, .2f, .1f, .2f, .25f, .2f, .1f }; gridblock_t *block, *lastBlock, *other; int x, y, a, b; sector_t *sector; const float *color; int bias; int height; #ifdef DD_PROFILE static int i; if(++i > 40) { i = 0; PRINT_PROF( PROF_GRID_UPDATE ); } #endif if(!lgInited || !needsUpdate) return; BEGIN_PROF( PROF_GRID_UPDATE ); #if 0 for(block = grid, y = 0; y < lgBlockHeight; ++y) { for(x = 0; x < lgBlockWidth; ++x, block++) { if(LG_BlockNeedsUpdate(x, y)) { block->flags |= GBF_CHANGED; // Clear to zero (will be recalculated). memset(block->rgb, 0, sizeof(float) * 3); // Mark contributors. for(b = -2; b <= 2; ++b) { if(y + b < 0 || y + b >= lgBlockHeight) continue; for(a = -2; a <= 2; ++a) { if(x + a < 0 || x + a >= lgBlockWidth) continue; GRID_BLOCK(x + a, y + b)->flags |= GBF_CONTRIBUTOR; } } } else { block->flags &= ~GBF_CHANGED; } } } #endif for(block = grid, y = 0; y < lgBlockHeight; ++y) { for(x = 0; x < lgBlockWidth; ++x, ++block) { boolean isSkyFloor, isSkyCeil; // Unused blocks can't contribute. if(!(block->flags & GBF_CONTRIBUTOR) || !block->sector) continue; // Determine the color of the ambient light in this sector. sector = block->sector; color = R_GetSectorLightColor(sector); height = (int) (sector->SP_ceilheight - sector->SP_floorheight); isSkyFloor = R_IsSkySurface(§or->SP_ceilsurface); isSkyCeil = R_IsSkySurface(§or->SP_floorsurface); if(isSkyFloor && !isSkyCeil) { bias = -height / 6; } else if(!isSkyFloor && isSkyCeil) { bias = height / 6; } else if(height > 100) { bias = (height - 100) / 2; } else { bias = 0; } // \todo Calculate min/max for a and b. for(a = -2; a <= 2; ++a) { for(b = -2; b <= 2; ++b) { if(x + a < 0 || y + b < 0 || x + a > lgBlockWidth - 1 || y + b > lgBlockHeight - 1) continue; other = GRID_BLOCK(x + a, y + b); if(other->flags & GBF_CHANGED) { LG_ApplySector(other, color, sector->lightLevel, factors[(b + 2)*5 + a + 2]/8, bias); } } } } } // Clear all changed and contribution flags. lastBlock = &grid[lgBlockWidth * lgBlockHeight]; for(block = grid; block != lastBlock; ++block) { block->flags = 0; } needsUpdate = false; END_PROF( PROF_GRID_UPDATE ); } /** * Calculate the light level for a 3D point in the world. * * @param point 3D point. * @param color Evaluated color of the point (return value). */ void LG_Evaluate(const float *point, float *color) { int x, y, i; float dz = 0, dimming; gridblock_t *block; if(!lgInited) { memset(color, 0, sizeof(float) * 3); return; } x = ROUND((point[VX] - lgOrigin[VX]) / lgBlockSize); y = ROUND((point[VY] - lgOrigin[VY]) / lgBlockSize); x = MINMAX_OF(1, x, lgBlockWidth - 2); y = MINMAX_OF(1, y, lgBlockHeight - 2); block = &grid[y * lgBlockWidth + x]; if(block->sector) { if(block->bias < 0) { // Calculate Z difference to the ceiling. dz = block->sector->SP_ceilheight - point[VZ]; } else if(block->bias > 0) { // Calculate Z difference to the floor. dz = point[VZ] - block->sector->SP_floorheight; } dz -= 50; if(dz < 0) dz = 0; if(block->flags & GBF_CHANGED) { // We are waiting for an updated value, for now use the old. color[CR] = block->oldRGB[CR]; color[CG] = block->oldRGB[CG]; color[CB] = block->oldRGB[CB]; } else { color[CR] = block->rgb[CR]; color[CG] = block->rgb[CG]; color[CB] = block->rgb[CB]; } } else { // The block has no sector!? // Must be an error in the lightgrid covering sector determination. // Init to black. color[CR] = color[CG] = color[CB] = 0; } // Biased ambient light causes a dimming in the Z direction. if(dz && block->bias) { if(block->bias < 0) dimming = 1 - (dz * (float) -block->bias) / 35000.0f; else dimming = 1 - (dz * (float) block->bias) / 35000.0f; if(dimming < .5f) dimming = .5f; for(i = 0; i < 3; ++i) { // Apply the dimming color[i] *= dimming; // Add the light range compression factor color[i] += Rend_GetLightAdaptVal(color[i]); } } else { // Just add the light range compression factor for(i = 0; i < 3; ++i) color[i] += Rend_GetLightAdaptVal(color[i]); } } /** * Draw the grid in 2D HUD mode. */ void LG_Debug(void) { static int blink = 0; gridblock_t* block; int x, y; int vx, vy; size_t vIdx, blockIdx; ddplayer_t* ddpl = (viewPlayer? &viewPlayer->shared : NULL); if(!lgInited || !lgShowDebug) return; if(ddpl) { blink++; vx = ROUND((ddpl->mo->pos[VX] - lgOrigin[VX]) / lgBlockSize); vy = ROUND((ddpl->mo->pos[VY] - lgOrigin[VY]) / lgBlockSize); vx = MINMAX_OF(1, vx, lgBlockWidth - 2); vy = MINMAX_OF(1, vy, lgBlockHeight - 2); vIdx = vy * lgBlockWidth + vx; } // Go into screen projection mode. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); glDisable(GL_TEXTURE_2D); for(y = 0; y < lgBlockHeight; ++y) { glBegin(GL_QUADS); for(x = 0; x < lgBlockWidth; ++x, ++block) { blockIdx = (lgBlockHeight - 1 - y) * lgBlockWidth + x; block = &grid[blockIdx]; if(ddpl && vIdx == blockIdx && (blink & 16)) { glColor3f(1, 0, 0); } else { if(!block->sector) continue; glColor3fv(block->rgb); } glVertex2f(x * lgDebugSize, y * lgDebugSize); glVertex2f(x * lgDebugSize + lgDebugSize, y * lgDebugSize); glVertex2f(x * lgDebugSize + lgDebugSize, y * lgDebugSize + lgDebugSize); glVertex2f(x * lgDebugSize, y * lgDebugSize + lgDebugSize); } glEnd(); } glEnable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_material.c0000644000175000017500000003255711357170242023226 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_material.c: Materials for world surfaces. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_play.h" #include "de_misc.h" #include "de_defs.h" #include "s_environ.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- #if 0 // Currently unused. void Material_Ticker(material_t* mat, timespan_t time) { uint i; const ded_material_t* def = mat->def; if(!def) return; // Its a system generated material. // Update layers for(i = 0; i < mat->numLayers; ++i) { material_layer_t* layer = &mat->layers[i]; if(!(def->layers[i].stageCount.num > 1)) continue; if(layer->tics-- <= 0) { // Advance to next stage. if(++layer->stage == def->layers[i].stageCount.num) { // Loop back to the beginning. layer->stage = 0; continue; } layer->tics = def->layers[i].stages[layer->stage].tics * (1 - def->layers[i].stages[layer->stage].variance * RNG_RandFloat()) * TICSPERSEC; } } } #endif /** * Subroutine of Material_Prepare(). */ static __inline void setTexUnit(material_snapshot_t* ss, byte unit, blendmode_t blendMode, int magMode, const gltexture_inst_t* texInst, float sScale, float tScale, float sOffset, float tOffset, float alpha) { material_textureunit_t* mtp = &ss->units[unit]; mtp->texInst = texInst; mtp->magMode = magMode; mtp->blendMode = blendMode; mtp->alpha = MINMAX_OF(0, alpha, 1); mtp->scale[0] = sScale; mtp->scale[1] = tScale; mtp->offset[0] = 0; mtp->offset[1] = 0; } byte Material_Prepare(material_snapshot_t* snapshot, material_t* mat, boolean smoothed, material_load_params_t* params) { uint i; byte tmpResult = 0; const gltexture_inst_t* texInst[DDMAX_MATERIAL_LAYERS]; const gltexture_inst_t* detailInst = NULL, *shinyInst = NULL, *shinyMaskInst = NULL; if(!mat) return 0; if(smoothed) mat = mat->current; assert(mat->numLayers > 0); // Ensure all resources needed to visualize this material are loaded. for(i = 0; i < mat->numLayers; ++i) { material_layer_t* ml = &mat->layers[i]; byte result; // Pick the instance matching the specified context. texInst[i] = GL_PrepareGLTexture(ml->tex, params, &result); if(result) tmpResult = result; } if(tmpResult) { // We need to update the assocated enhancements. // Decorations (lights, models, etc). mat->decoration = Def_GetDecoration(mat, tmpResult == 2); // Reflection (aka shiny surface). mat->reflection = Def_GetReflection(mat, tmpResult == 2); // Generator (particles). mat->ptcGen = Def_GetGenerator(mat, tmpResult == 2); // Detail texture. mat->detail = Def_GetDetailTex(mat, tmpResult == 2); } // Do we need to prepare a detail texture? if(mat->detail) { detailtex_t* dTex; lumpnum_t lump = W_CheckNumForName(mat->detail->detailLump.path); const char* external = (mat->detail->isExternal? mat->detail->detailLump.path : NULL); /** * \todo No need to look up the detail texture record every time! * This will change anyway once the gltexture for the detailtex is * linked to (and prepared) via the layers (above). */ if((dTex = R_GetDetailTexture(lump, external))) { float contrast = mat->detail->strength * detailFactor; // Pick an instance matching the specified context. detailInst = GL_PrepareGLTexture(dTex->id, &contrast, NULL); } } // Do we need to prepare a shiny texture (and possibly a mask)? if(mat->reflection) { shinytex_t* sTex; masktex_t* mTex; /** * \todo No need to look up the shiny texture record every time! * This will change anyway once the gltexture for the shinytex is * linked to (and prepared) via the layers (above). */ if((sTex = R_GetShinyTexture(mat->reflection->shinyMap.path))) { // Pick an instance matching the specified context. shinyInst = GL_PrepareGLTexture(sTex->id, NULL, NULL); } if(shinyInst && // Don't bother searching unless the above succeeds. (mTex = R_GetMaskTexture(mat->reflection->maskMap.path))) { // Pick an instance matching the specified context. shinyMaskInst = GL_PrepareGLTexture(mTex->id, NULL, NULL); } } // If we arn't taking a snapshot, get out of here. if(!snapshot) return tmpResult; /** * Take a snapshot: */ // Reset to the default state. for(i = 0; i < DDMAX_MATERIAL_LAYERS; ++i) setTexUnit(snapshot, i, BM_NORMAL, GL_LINEAR, NULL, 1, 1, 0, 0, 0); snapshot->width = mat->width; snapshot->height = mat->height; // Setup the primary texturing pass. if(mat->layers[0].tex) { const gltexture_t* tex = GL_GetGLTexture(mat->layers[0].tex); int c; int magMode = glmode[texMagMode]; if(tex->type == GLT_SPRITE) magMode = filterSprites? GL_LINEAR : GL_NEAREST; setTexUnit(snapshot, MTU_PRIMARY, BM_NORMAL, magMode, texInst[0], 1.f / snapshot->width, 1.f / snapshot->height, 0, 0, 1); snapshot->isOpaque = !(texInst[0]->flags & GLTF_MASKED); /// \fixme what about the other texture types? if(tex->type == GLT_DOOMTEXTURE || tex->type == GLT_FLAT) { for(c = 0; c < 3; ++c) { snapshot->color[c] = texInst[0]->data.texture.color[c]; snapshot->topColor[c] = texInst[0]->data.texture.topColor[c]; } } else { snapshot->color[CR] = snapshot->color[CG] = snapshot->color[CB] = 1; snapshot->topColor[CR] = snapshot->topColor[CG] = snapshot->topColor[CB] = 1; } } /** * If skymasked, we need only need to update the primary tex unit * (this is due to it being visible when skymask debug drawing is * enabled). */ if(!(mat->flags & MATF_SKYMASK)) { // Setup the detail texturing pass? if(detailInst && snapshot->isOpaque) { float width, height, scale; width = GLTexture_GetWidth(detailInst->tex); height = GLTexture_GetHeight(detailInst->tex); scale = MAX_OF(1, mat->detail->scale); // Apply the global scaling factor. if(detailScale > .001f) scale *= detailScale; setTexUnit(snapshot, MTU_DETAIL, BM_NORMAL, GL_LINEAR, detailInst, 1.f / width * scale, 1.f / height * scale, 0, 0, 1); } // Setup the reflection (aka shiny) texturing pass(es)? if(shinyInst) { ded_reflection_t* def = mat->reflection; snapshot->shiny.minColor[CR] = def->minColor[CR]; snapshot->shiny.minColor[CG] = def->minColor[CG]; snapshot->shiny.minColor[CB] = def->minColor[CB]; setTexUnit(snapshot, MTU_REFLECTION, def->blendMode, GL_LINEAR, shinyInst, 1, 1, 0, 0, def->shininess); if(shinyMaskInst) setTexUnit(snapshot, MTU_REFLECTION_MASK, BM_NORMAL, snapshot->units[MTU_PRIMARY].magMode, shinyMaskInst, 1.f / (snapshot->width * maskTextures[ shinyMaskInst->tex->ofTypeID]->width), 1.f / (snapshot->height * maskTextures[ shinyMaskInst->tex->ofTypeID]->height), snapshot->units[MTU_PRIMARY].offset[0], snapshot->units[MTU_PRIMARY].offset[1], 1); } } return tmpResult; } void Material_SetTranslation(material_t* mat, material_t* current, material_t* next, float inter) { if(!mat || !current || !next) { #if _DEBUG Con_Error("Material_SetTranslation: Invalid paramaters."); #endif return; } mat->current = current; mat->next = next; mat->inter = 0; } /** * Retrieve the decoration definition associated with the material. * * @return The associated decoration definition, else @c NULL. */ const ded_decor_t* Material_GetDecoration(material_t* mat) { if(mat) { // Ensure we've already prepared this material. Material_Prepare(NULL, mat, true, NULL); return mat->current->decoration; } return NULL; } /** * Retrieve the ptcgen definition associated with the material. * * @return The associated ptcgen definition, else @c NULL. */ const ded_ptcgen_t* Material_GetPtcGen(material_t* mat) { if(mat) { // Ensure we've already prepared this material. //Material_Prepare(NULL, mat, true, NULL); return mat->ptcGen; } return NULL; } material_env_class_t Material_GetEnvClass(material_t* mat) { if(mat) { if(mat->envClass == MEC_UNKNOWN) { mat->envClass = S_MaterialClassForName(P_GetMaterialName(mat), mat->mnamespace); } if(!(mat->flags & MATF_NO_DRAW)) { return mat->envClass; } } return MEC_UNKNOWN; } /** * Prepares all resources associated with the specified material including * all in the same animation group. * * \note Part of the Doomsday public API. * * \todo What about the load params? By limiting to the default params here, we * may be precaching unused texture instances. */ void Material_Precache(material_t* mat) { if(!mat) return; if(mat->inAnimGroup) { // The material belongs in one or more animgroups, precache the group. R_MaterialsPrecacheGroup(mat); return; } // Just this one material. Material_Prepare(NULL, mat, true, NULL); } void Material_DeleteTextures(material_t* mat) { if(mat) { uint i; for(i = 0; i < mat->numLayers; ++i) GL_ReleaseGLTexture(mat->layers[i].tex); } } /** * Update the material, property is selected by DMU_* name. */ boolean Material_SetProperty(material_t* mat, const setargs_t* args) { switch(args->prop) { default: Con_Error("Material_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } /** * Get the value of a material property, selected by DMU_* name. */ boolean Material_GetProperty(const material_t* mat, setargs_t* args) { switch(args->prop) { case DMU_FLAGS: DMU_GetValue(DMT_MATERIAL_FLAGS, &mat->flags, args, 0); break; case DMU_WIDTH: DMU_GetValue(DMT_MATERIAL_WIDTH, &mat->width, args, 0); break; case DMU_HEIGHT: DMU_GetValue(DMT_MATERIAL_HEIGHT, &mat->height, args, 0); break; case DMU_NAMESPACE: DMU_GetValue(DMT_MATERIAL_MNAMESPACE, &mat->mnamespace, args, 0); break; default: Con_Error("Sector_GetProperty: No property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_mus2midi.c0000644000175000017500000002257611357170242023156 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_mus2midi.c: MUS to MIDI conversion. * * Converts Doom's MUS music format to equivalent MIDI data. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "doomsday.h" // MACROS ------------------------------------------------------------------ // MUS event types. enum { MUS_EV_RELEASE_NOTE, MUS_EV_PLAY_NOTE, MUS_EV_PITCH_WHEEL, MUS_EV_SYSTEM, // Valueless controller. MUS_EV_CONTROLLER, MUS_EV_FIVE, // ? MUS_EV_SCORE_END, MUS_EV_SEVEN // ? }; // MUS controllers. enum { MUS_CTRL_INSTRUMENT, MUS_CTRL_BANK, MUS_CTRL_MODULATION, MUS_CTRL_VOLUME, MUS_CTRL_PAN, MUS_CTRL_EXPRESSION, MUS_CTRL_REVERB, MUS_CTRL_CHORUS, MUS_CTRL_SUSTAIN_PEDAL, MUS_CTRL_SOFT_PEDAL, // The valueless controllers. MUS_CTRL_SOUNDS_OFF, MUS_CTRL_NOTES_OFF, MUS_CTRL_MONO, MUS_CTRL_POLY, MUS_CTRL_RESET_ALL, NUM_MUS_CTRLS }; // TYPES ------------------------------------------------------------------- #pragma pack(1) struct mus_header { char ID[4]; // Identifier "MUS" 0x1A. ushort scoreLen; ushort scoreStart; ushort channels; // Number of primary channels. ushort secondaryChannels; // Number of secondary channels. ushort instrCnt; ushort padding; // The instrument list begins here. }; #pragma pack() typedef struct mus_event_s { byte channel; byte ev; // event. byte last; } mus_event_t; typedef struct midi_event_s { uint deltaTime; byte command; byte size; byte parms[2]; } midi_event_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int readTime; // In ticks. static byte* readPos; static byte chanVols[16]; // Last volume for each channel. static char ctrlMus2Midi[NUM_MUS_CTRLS] = { 0, // Not used. 0, // Bank select. 1, // Modulation. 7, // Volume. 10, // Pan. 11, // Expression. 91, // Reverb. 93, // Chorus. 64, // Sustain pedal. 67, // Soft pedal. // The valueless controllers: 120, // All sounds off. 123, // All notes off. 126, // Mono. 127, // Poly. 121 // Reset all controllers. }; // CODE -------------------------------------------------------------------- static boolean getNextEvent(midi_event_t* ev) { int i; mus_event_t evDesc; byte musEvent; ev->deltaTime = readTime; readTime = 0; musEvent = *readPos++; evDesc.channel = musEvent & 0xf; evDesc.ev = (musEvent >> 4) & 0x7; evDesc.last = (musEvent >> 7) & 0x1; ev->command = 0; ev->size = 0; memset(ev->parms, 0, sizeof(ev->parms)); // Construct the MIDI event. switch(evDesc.ev) { case MUS_EV_PLAY_NOTE: ev->command = 0x90; ev->size = 2; // Which note? ev->parms[0] = *readPos++; // Is the volume there, too? if(ev->parms[0] & 0x80) chanVols[evDesc.channel] = *readPos++; ev->parms[0] &= 0x7f; if((i = chanVols[evDesc.channel]) > 127) i = 127; ev->parms[1] = i; break; case MUS_EV_RELEASE_NOTE: ev->command = 0x80; ev->size = 2; // Which note? ev->parms[0] = *readPos++; break; case MUS_EV_CONTROLLER: ev->command = 0xb0; ev->size = 2; ev->parms[0] = *readPos++; ev->parms[1] = *readPos++; // The instrument control is mapped to another kind of MIDI event. if(ev->parms[0] == MUS_CTRL_INSTRUMENT) { ev->command = 0xc0; ev->size = 1; ev->parms[0] = ev->parms[1]; } else { // Use the conversion table. ev->parms[0] = ctrlMus2Midi[ev->parms[0]]; } break; // 2 bytes, 14 bit value. 0x2000 is the center. // First seven bits go to parm1, the rest to parm2. case MUS_EV_PITCH_WHEEL: ev->command = 0xe0; ev->size = 2; i = *readPos++ << 6; ev->parms[0] = i & 0x7f; ev->parms[1] = i >> 7; break; case MUS_EV_SYSTEM: // Is this ever used? ev->command = 0xb0; ev->size = 2; ev->parms[0] = ctrlMus2Midi[*readPos++]; break; case MUS_EV_SCORE_END: // We're done. return false; default: Con_Error("MUS_SongPlayer: Unknown MUS event %d.\n", evDesc.ev); } // Choose the channel. i = evDesc.channel; // Redirect MUS channel 16 to MIDI channel 10 (percussion). if(i == 15) i = 9; else if(i == 9) i = 15; ev->command |= i; // Check if this was the last event in a group. if(!evDesc.last) return true; // Read the time delta. readTime = 0; do { i = *readPos++; readTime = (readTime << 7) + (i & 0x7f); } while(i & 0x80); return true; } /** * @param data The MUS data to convert. * @param length The length of the data in bytes. * @param outFile Name of the file the resulting MIDI data will be * written to. */ boolean M_Mus2Midi(void* data, size_t length, const char* outFile) { FILE* file; unsigned char buffer[80]; int i, trackSizeOffset, trackSize; midi_event_t ev; struct mus_header* header; if(!outFile || !outFile[0]) return false; if((file = fopen(outFile, "wb")) == NULL) { Con_Message("M_Mus2Midi: Failed opening output file %s.\n", outFile); return false; } // Start with the MIDI header. strcpy((char*)buffer, "MThd"); fwrite(buffer, 4, 1, file); // Header size. memset(buffer, 0, 3); buffer[3] = 6; fwrite(buffer, 4, 1, file); // Format (single track). buffer[0] = 0; buffer[1] = 0; // Number of tracks. buffer[2] = 0; buffer[3] = 1; // Delta ticks per quarter note (140). buffer[4] = 0; buffer[5] = 140; fwrite(buffer, 6, 1, file); // Track header. strcpy((char*)buffer, "MTrk"); fwrite(buffer, 4, 1, file); // Length of the track in bytes. memset(buffer, 0, 4); trackSizeOffset = ftell(file); fwrite(buffer, 4, 1, file); // Updated later. // The first MIDI ev sets the tempo. buffer[0] = 0; // No delta ticks. buffer[1] = 0xff; buffer[2] = 0x51; buffer[3] = 3; buffer[4] = 0xf; // Exactly one second per quarter note. buffer[5] = 0x42; buffer[6] = 0x40; fwrite(buffer, 7, 1, file); header = (struct mus_header *) data; readPos = (byte*)data + USHORT(header->scoreStart); readTime = 0; // Init channel volumes. for(i = 0; i < 16; ++i) chanVols[i] = 64; while(getNextEvent(&ev)) { // Delta time. Split into 7-bit segments. if(ev.deltaTime == 0) { buffer[0] = 0; fwrite(buffer, 1, 1, file); } else { i = -1; while(ev.deltaTime > 0) { buffer[++i] = ev.deltaTime & 0x7f; if(i > 0) buffer[i] |= 0x80; ev.deltaTime >>= 7; } // The bytes are written starting from the MSB. for(; i >= 0; --i) fwrite(&buffer[i], 1, 1, file); } // The ev data. fwrite(&ev.command, 1, 1, file); fwrite(&ev.parms, 1, ev.size, file); } // End of track. buffer[0] = 0; buffer[1] = 0xff; buffer[2] = 0x2f; buffer[3] = 0; fwrite(buffer, 4, 1, file); // All the MIDI data has now been written. Update the track length. trackSize = ftell(file) - trackSizeOffset - 4; fseek(file, trackSizeOffset, SEEK_SET); buffer[3] = trackSize & 0xff; buffer[2] = (trackSize >> 8) & 0xff; buffer[1] = (trackSize >> 16) & 0xff; buffer[0] = trackSize >> 24; fwrite(buffer, 4, 1, file); fclose(file); return true; // Success! } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_vector.c0000644000175000017500000003046511357170242022723 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_vector.c: Vector Math */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "m_vector.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Set the vector's x and y components. */ void V2_Set(pvec2_t vec, vectorcomp_t x, vectorcomp_t y) { vec[VX] = x; vec[VY] = y; } void V2_SetFixed(pvec2_t vec, fixed_t x, fixed_t y) { vec[VX] = FIX2FLT(x); vec[VY] = FIX2FLT(y); } /** * 2-dimensional vector length. */ float V2_Length(const pvec2_t vec) { if(vec[VX] == 0 && vec[VY] == 0) return 0; return sqrt(vec[VX] * vec[VX] + vec[VY] * vec[VY]); } /** * The distance between two points. */ float V2_Distance(const pvec2_t a, const pvec2_t b) { vec2_t vec; V2_Subtract(vec, b, a); return V2_Length(vec); } /** * Normalize a 2-dimensional vector. * * @return The length of the vector. */ float V2_Normalize(pvec2_t vec) { float len = V2_Length(vec); if(len != 0) { vec[VX] /= len; vec[VY] /= len; } return len; } /** * Make a copy of the source vector. */ void V2_Copy(pvec2_t dest, const_pvec2_t src) { dest[VX] = src[VX]; dest[VY] = src[VY]; } /** * Multiply the vector by the scalar. */ void V2_Scale(pvec2_t vec, float scalar) { vec[VX] *= scalar; vec[VY] *= scalar; } /** * Rotate the vector by a radian angle. */ void V2_Rotate(pvec2_t vec, float radians) { const float c = cos(radians); const float s = sin(radians); float x = c * vec[VX] - s * vec[VY]; float y = s * vec[VX] + c * vec[VY]; vec[VX] = x; vec[VY] = y; } /** * Calculate the sum of two 2-dimensional vectors. */ void V2_Sum(pvec2_t dest, const pvec2_t src1, const pvec2_t src2) { dest[VX] = src1[VX] + src2[VX]; dest[VY] = src1[VY] + src2[VY]; } /** * Subtract src1 from src2, return result in 'dest'. */ void V2_Subtract(pvec2_t dest, const pvec2_t src1, const pvec2_t src2) { dest[VX] = src1[VX] - src2[VX]; dest[VY] = src1[VY] - src2[VY]; } /** * Calculate the dot product of the two vectors. */ float V2_DotProduct(const pvec2_t a, const pvec2_t b) { return a[VX] * b[VX] + a[VY] * b[VY]; } /** * Calculate the scalar projection of 'a' onto 'b': dot(a,b)/len(b) */ float V2_ScalarProject(const pvec2_t a, const pvec2_t b) { float dot; float len = V2_Length(b); if(len == 0) return 0; dot = V2_DotProduct(a, b); return dot / len; } /** * Project 'a' onto 'b' and store the resulting vector to 'dest': * dot(a,b)/dot(b,b)*b */ void V2_Project(pvec2_t dest, const pvec2_t a, const pvec2_t b) { float div = V2_DotProduct(b, b); if(div == 0) { dest[VX] = dest[VY] = 0; return; } V2_Copy(dest, b); V2_Scale(dest, V2_DotProduct(a, b) / div); } /** * @return @c true, if the two vectors are parallel. */ boolean V2_IsParallel(const pvec2_t a, const pvec2_t b) { #define EPSILON .9999f float aLen = V2_Length(a); float bLen = V2_Length(b); float dot; // Both must be non-zero vectors. if(aLen == 0 || bLen == 0) return true; dot = V2_DotProduct(a, b) / aLen / bLen; // If it's close enough, we'll consider them parallel. return dot > EPSILON || dot < -EPSILON; #undef EPSILON } /** * @return @c true, if the vector is a zero vector. */ boolean V2_IsZero(const pvec2_t vec) { return vec[VX] == 0 && vec[VY] == 0; } /** * Determine where the two lines cross each other. Notice that the * lines are defined with a point and a vector. * * @return A scaling factor for the first line. */ float V2_Intersection(const pvec2_t p1, const pvec2_t delta1, const pvec2_t p2, const pvec2_t delta2, pvec2_t point) { /* * (YA-YC)(XD-XC)-(XA-XC)(YD-YC) * r = ----------------------------- * (XB-XA)(YD-YC)-(YB-YA)(XD-XC) */ float r, div; int i; div = delta1[VX] * delta2[VY] - delta1[VY] * delta2[VX]; if(div == 0) { // Special case: lines are parallel. r = 0; } else { r = ((p1[VY] - p2[VY]) * delta2[VX] - (p1[VX] - p2[VX]) * delta2[VY]) / div; } /* * XI=XA+r(XB-XA) * YI=YA+r(YB-YA) */ if(point) { // Calculate the intersection point. for(i = 0; i < 2; ++i) point[i] = p1[i] + r * delta1[i]; } // Return the scaling factor. return r; } /** * Intersection of lines a->b and c->d. Unlike V2_Intersection(), the * arguments are all points. */ float V2_Intercept(const pvec2_t a, const pvec2_t b, const pvec2_t c, const pvec2_t d, pvec2_t point) { vec2_t ab, cd; ab[0] = b[VX] - a[VX]; ab[1] = b[VY] - a[VY]; cd[0] = d[VX] - c[VX]; cd[1] = d[VY] - c[VY]; return V2_Intersection(a, ab, c, cd, point); } /** * @return @c true, if the two lines intercept. */ boolean V2_Intercept2(const pvec2_t a, const pvec2_t b, const pvec2_t c, const pvec2_t d, pvec2_t point, float *abFrac, float *cdFrac) { float ab, cd; ab = V2_Intercept(a, b, c, d, point); cd = V2_Intercept(c, d, a, b, NULL); if(abFrac) *abFrac = ab; if(cdFrac) *cdFrac = cd; return (ab >= 0 && ab <= 1 && cd >= 0 && cd <= 1); } /** * Linear interpolation between a and b, by c. */ void V2_Lerp(pvec2_t dest, const pvec2_t a, const pvec2_t b, float c) { uint i; for(i = 0; i < 2; ++i) { dest[i] = a[i] + c * (b[i] - a[i]); } } /** * Left/top is the min-point. Right/bottom is the max-point. */ void V2_InitBox(arvec2_t box, const pvec2_t point) { V2_Copy(box[0], point); V2_Copy(box[1], point); } void V2_AddToBox(arvec2_t box, const pvec2_t point) { if(point[VX] < box[0][VX]) box[0][VX] = point[VX]; if(point[VX] > box[1][VX]) box[1][VX] = point[VX]; if(point[VY] < box[0][VY]) box[0][VY] = point[VY]; if(point[VY] > box[1][VY]) box[1][VY] = point[VY]; } /** * Set the vector's x, y and z components. */ void V3_Set(pvec3_t vec, vectorcomp_t x, vectorcomp_t y, vectorcomp_t z) { vec[VX] = x; vec[VY] = y; vec[VZ] = z; } void V3_SetFixed(pvec3_t vec, fixed_t x, fixed_t y, fixed_t z) { vec[VX] = FIX2FLT(x); vec[VY] = FIX2FLT(y); vec[VZ] = FIX2FLT(z); } /** * 3-dimensional vector length. */ float V3_Length(const pvec3_t vec) { if(vec[VX] == 0 && vec[VY] == 0 && vec[VZ] == 0) return 0; return sqrt(vec[VX] * vec[VX] + vec[VY] * vec[VY] + vec[VZ] * vec[VZ]); } /** * The distance between two points. */ float V3_Distance(const pvec3_t a, const pvec3_t b) { vec3_t vec; V3_Subtract(vec, b, a); return V3_Length(vec); } /** * Normalize a 3-dimensional vector. * * @return The length of the vector. */ float V3_Normalize(pvec3_t vec) { float len = V3_Length(vec); if(len != 0) { vec[VX] /= len; vec[VY] /= len; vec[VZ] /= len; } return len; } /** * Make a copy of the source vector. */ void V3_Copy(pvec3_t dest, const_pvec3_t src) { dest[VX] = src[VX]; dest[VY] = src[VY]; dest[VZ] = src[VZ]; } /** * Multiply the vector by the scalar. */ void V3_Scale(pvec3_t vec, float scalar) { vec[VX] *= scalar; vec[VY] *= scalar; vec[VZ] *= scalar; } /** * Calculate the sum of two 3-dimensional vectors. */ void V3_Sum(pvec3_t dest, const_pvec3_t src1, const_pvec3_t src2) { dest[VX] = src1[VX] + src2[VX]; dest[VY] = src1[VY] + src2[VY]; dest[VZ] = src1[VZ] + src2[VZ]; } /** * Subtract src1 from src2, return result in 'dest'. */ void V3_Subtract(pvec3_t dest, const_pvec3_t src1, const_pvec3_t src2) { dest[VX] = src1[VX] - src2[VX]; dest[VY] = src1[VY] - src2[VY]; dest[VZ] = src1[VZ] - src2[VZ]; } /** * Calculate the dot product of the two vectors. */ float V3_DotProduct(const_pvec3_t a, const_pvec3_t b) { return a[VX] * b[VX] + a[VY] * b[VY] + a[VZ] * b[VZ]; } /** * Calculate the cross product of two vectors. * * @param dest Result will be written back here. * @param src1 First vector. * @param src2 Second vector. */ void V3_CrossProduct(pvec3_t dest, const pvec3_t src1, const pvec3_t src2) { dest[VX] = src1[VY] * src2[VZ] - src1[VZ] * src2[VY]; dest[VY] = src1[VZ] * src2[VX] - src1[VX] * src2[VZ]; dest[VZ] = src1[VX] * src2[VY] - src1[VY] * src2[VX]; } /** * Cross product of two vectors composed of three points. * * @param dest Result will be written back here. * @param v1 First vector. * @param v2 Second vector. * @param v3 Third vector. */ void V3_PointCrossProduct(pvec3_t dest, const pvec3_t v1, const pvec3_t v2, const pvec3_t v3) { vec3_t a, b; V3_Subtract(a, v2, v1); V3_Subtract(b, v3, v1); V3_CrossProduct(dest, a, b); } /** * Find the closest point in the plane, to an arbitary point. * * @param dest Result will be written back here. * @param planeNormal The normalized plane normal. * @param planePoint A point already on the plane. * @param arbPoint The arbitrary point to find the closest point too. * * @return Distance from the closest point on the plane to the * specified arbitary point. */ float V3_ClosestPointOnPlane(pvec3_t dest, const pvec3_t planeNormal, const pvec3_t planePoint, const pvec3_t arbPoint) { vec3_t pvec; float distance; V3_Subtract(pvec, arbPoint, planePoint); distance = V3_DotProduct(planeNormal, pvec); V3_Copy(dest, planeNormal); V3_Scale(dest, distance); V3_Subtract(dest, arbPoint, dest); return distance; } /** * Determine which axis of the given vector is the major. */ int V3_MajorAxis(const pvec3_t vec) { int axis = VX; vec3_t fn; V3_Set(fn, fabsf(vec[VX]), fabsf(vec[VY]), fabsf(vec[VZ])); if(fn[VY] > fn[axis]) axis = VY; if(fn[VZ] > fn[axis]) axis = VZ; return axis; } /** * @return @c true, if the vector is a zero vector. */ boolean V3_IsZero(const pvec3_t vec) { return vec[VX] == 0 && vec[VY] == 0 && vec[VZ] == 0; } /** * Linear interpolation between a and b, by c. */ void V3_Lerp(pvec3_t dest, const pvec3_t a, const pvec3_t b, float c) { uint i; for(i = 0; i < 3; ++i) { dest[i] = a[i] + c * (b[i] - a[i]); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_main.c0000644000175000017500000002625611357170241022511 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_main.c: Network Client */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_graphics.h" #include "de_misc.h" #include "de_play.h" #include "r_main.h" // MACROS ------------------------------------------------------------------ // Clients send commands on every tic. #define CLIENT_TICCMD_INTERVAL 0 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int gotFrame; // PUBLIC DATA DEFINITIONS ------------------------------------------------- ident_t clientID; boolean handshakeReceived = false; int gameReady = false; int serverTime; boolean netLoggedIn = false; // Logged in to the server. int clientPaused = false; // Set by the server. // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void Cl_InitID(void) { int i; FILE* file; if((i = ArgCheckWith("-id", 1)) != 0) { clientID = strtoul(Argv(i + 1), 0, 0); Con_Message("Cl_InitID: Using custom id 0x%08x.\n", clientID); return; } // Read the client ID number file. srand(time(NULL)); if((file = fopen("client.id", "rb")) != NULL) { fread(&clientID, sizeof(clientID), 1, file); clientID = ULONG(clientID); fclose(file); return; } // Ah-ha, we need to generate a new ID. clientID = (ident_t) ULONG(Sys_GetRealTime() * rand() + (rand() & 0xfff) + ((rand() & 0xfff) << 12) + ((rand() & 0xff) << 24)); // Write it to the file. if((file = fopen("client.id", "wb")) != NULL) { fwrite(&clientID, sizeof(clientID), 1, file); fclose(file); } } int Cl_GameReady(void) { return (handshakeReceived && gameReady); } void Cl_CleanUp(void) { Con_Printf("Cl_CleanUp.\n"); clientPaused = false; handshakeReceived = false; Cl_DestroyClientMobjs(); Cl_InitPlayers(); Cl_RemoveMovers(); GL_SetFilter(false); } /** * Sends a hello packet. * PCL_HELLO2 includes the Game ID (16 chars). */ void Cl_SendHello(void) { char buf[256]; Msg_Begin(PCL_HELLO2); Msg_WriteLong(clientID); // The game mode is included in the hello packet. memset(buf, 0, sizeof(buf)); strncpy(buf, (char *) gx.GetVariable(DD_GAME_MODE), sizeof(buf) - 1); #ifdef _DEBUG Con_Message("Cl_SendHello: game mode = %s\n", buf); #endif Msg_Write(buf, 16); Net_SendBuffer(0, SPF_ORDERED); } void Cl_AnswerHandshake(handshake_packet_t* pShake) { int i; handshake_packet_t shake; // Copy the data to a buffer of our own. memcpy(&shake, pShake, sizeof(shake)); shake.playerMask = USHORT(shake.playerMask); shake.gameTime = LONG(shake.gameTime); // Immediately send an acknowledgement. Msg_Begin(PCL_ACK_SHAKE); Net_SendBuffer(0, SPF_ORDERED); // Check the version number. if(shake.version != SV_VERSION) { Con_Message ("Cl_AnswerHandshake: Version conflict! (you:%i, server:%i)\n", SV_VERSION, shake.version); Con_Execute(CMDS_DDAY, "net disconnect", false, false); Demo_StopPlayback(); Con_Open(true); return; } // Update time and player ingame status. gameTime = shake.gameTime / 100.0; for(i = 0; i < DDMAXPLAYERS; ++i) { ddPlayers[i].shared.inGame = (shake.playerMask & (1 << i)) != 0; } consolePlayer = displayPlayer = shake.yourConsole; clients[consolePlayer].numTics = 0; clients[consolePlayer].firstTic = 0; isClient = true; isServer = false; netLoggedIn = false; clientPaused = false; if(handshakeReceived) return; // This prevents redundant re-initialization. handshakeReceived = true; // Soon after this packet will follow the game's handshake. gameReady = false; Cl_InitFrame(); Con_Printf("Cl_AnswerHandshake: myConsole:%i, gameTime:%i.\n", shake.yourConsole, shake.gameTime); /** * Tell the game that we have arrived. The map will be changed when the * game's handshake arrives (handled in the game). */ gx.NetPlayerEvent(consolePlayer, DDPE_ARRIVAL, 0); // Prepare the client-side data. Cl_InitClientMobjs(); Cl_InitMovers(); // Get ready for ticking. DD_ResetTimer(); Con_Executef(CMDS_DDAY, true, "setcon %i", consolePlayer); } void Cl_HandlePlayerInfo(playerinfo_packet_t* info) { player_t* plr; boolean present; Con_Printf("Cl_HandlePlayerInfo: console:%i name:%s\n", info->console, info->name); // Is the console number valid? if(info->console >= DDMAXPLAYERS) return; plr = &ddPlayers[info->console]; present = plr->shared.inGame; plr->shared.inGame = true; strcpy(clients[info->console].name, info->name); if(!present) { // This is a new player! Let the game know about this. gx.NetPlayerEvent(info->console, DDPE_ARRIVAL, 0); } } void Cl_PlayerLeaves(int plrNum) { Con_Printf("Cl_PlayerLeaves: player %i has left.\n", plrNum); ddPlayers[plrNum].shared.inGame = false; gx.NetPlayerEvent(plrNum, DDPE_EXIT, 0); } /** * Client's packet handler. * Handles all the events the server sends. */ void Cl_GetPackets(void) { int i; // All messages come from the server. while(Net_GetPacket()) { // First check for packets that are only valid when // a game is in progress. if(Cl_GameReady()) { boolean handled = true; switch(netBuffer.msg.type) { case PSV_FRAME: Cl_FrameReceived(); break; case PSV_FIRST_FRAME2: case PSV_FRAME2: Cl_Frame2Received(netBuffer.msg.type); break; case PKT_COORDS: Cl_CoordsReceived(); break; case PSV_SOUND: Cl_Sound(); break; case PSV_FILTER: { player_t* plr = &ddPlayers[consolePlayer]; int filter = Msg_ReadLong(); if(filter) plr->shared.flags |= DDPF_VIEW_FILTER; else plr->shared.flags &= ~DDPF_VIEW_FILTER; plr->shared.filterColor[CR] = filter & 0xff; plr->shared.filterColor[CG] = (filter >> 8) & 0xff; plr->shared.filterColor[CB] = (filter >> 16) & 0xff; plr->shared.filterColor[CA] = (filter >> 24) & 0xff; break; } default: handled = false; } if(handled) continue; // Get the next packet. } // How about the rest? switch(netBuffer.msg.type) { case PSV_PLAYER_FIX: Cl_HandlePlayerFix(); break; case PKT_DEMOCAM: case PKT_DEMOCAM_RESUME: Demo_ReadLocalCamera(); break; case PKT_PING: Net_PingResponse(); break; case PSV_SYNC: // The server updates our time. Latency has been taken into // account, so... gameTime = Msg_ReadLong() / 100.0; Con_Printf("PSV_SYNC: gameTime=%.3f\n", gameTime); DD_ResetTimer(); break; case PSV_HANDSHAKE: Cl_AnswerHandshake((handshake_packet_t *) netBuffer.msg.data); break; case PKT_PLAYER_INFO: Cl_HandlePlayerInfo((playerinfo_packet_t *) netBuffer.msg.data); break; case PSV_PLAYER_EXIT: Cl_PlayerLeaves(Msg_ReadByte()); break; case PKT_CHAT: Net_ShowChatMessage(); gx.NetPlayerEvent(netBuffer.msg.data[0], DDPE_CHAT_MESSAGE, netBuffer.msg.data + 3); break; case PSV_SERVER_CLOSE: // We should quit? netLoggedIn = false; Con_Execute(CMDS_DDAY, "net disconnect", true, false); break; case PSV_CONSOLE_TEXT: i = Msg_ReadLong(); Con_FPrintf(i, "%s", (char*)netBuffer.cursor); break; case PKT_LOGIN: // Server responds to our login request. Let's see if we // were successful. netLoggedIn = Msg_ReadByte(); break; default: if(netBuffer.msg.type >= PKT_GAME_MARKER) { gx.HandlePacket(netBuffer.player, netBuffer.msg.type, netBuffer.msg.data, netBuffer.length); } else { #ifdef _DEBUG Con_Printf("Cl_GetPackets: Packet (type %i) was discarded!\n", netBuffer.msg.type); #endif } } } } /** * Client-side game ticker. */ void Cl_Ticker(void) { //static trigger_t fixed = { 1.0 / 35 }; static int ticSendTimer = 0; if(!isClient || !Cl_GameReady() || clientPaused) return; //if(!M_RunTrigger(&fixed, time)) return; Cl_LocalCommand(); Cl_PredictMovement(); //Cl_MovePsprites(); // Clients don't send commands on every tic (over the network). if(++ticSendTimer > CLIENT_TICCMD_INTERVAL) { ticSendTimer = 0; Net_SendCommands(); } } /** * Clients use this to establish a remote connection to the server. */ D_CMD(Login) { // Only clients can log in. if(!isClient) return false; Msg_Begin(PKT_LOGIN); // Write the password. if(argc == 1) Msg_WriteByte(0); // No password given! else Msg_Write(argv[1], strlen(argv[1]) + 1); Net_SendBuffer(0, SPF_ORDERED); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_hq2x.c0000644000175000017500000017107111357170242022450 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson *\author Copyright © 2003 Maxim Stepin * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_hq2x.c: High-Quality 2x Graphics Resizing * * Based on the routine by Maxim Stepin * For more information, see: http://hiend3d.com/hq2x.html * * Now uses 32-bit data and 0xAABBGGRR pixel byte order (little endian). * Alpha is taken into account in the processing to preserve edges. * Not quite as efficient as the original version. */ // HEADER FILES ------------------------------------------------------------ #include "dd_types.h" #include "dd_share.h" #include "de_console.h" #include // MACROS ------------------------------------------------------------------ // Extract a color component. #define COMP(n,c) ((c >> (n << 3)) & 0xFF) // Convert a 32-bit RGBA pixel to 16-bit RGB. #define RGBA32_RGB16(rgba) (((rgba & 0xF8) >> 3) | ((rgba & 0xFC00) >> 5) | \ ((rgba & 0xF80000) >> 8)) #define Ymask ((int)0x00FF0000) #define Umask ((int)0x0000FF00) #define Vmask ((int)0x000000FF) #define trY ((int)0x00300000) #define trU ((int)0x00000700) #define trV ((int)0x00000006) #define PIXEL00_0 *((uint*)(pOut)) = ULONG( c[5] ); #define PIXEL00_10 Interp1(pOut, c[5], c[1]); #define PIXEL00_11 Interp1(pOut, c[5], c[4]); #define PIXEL00_12 Interp1(pOut, c[5], c[2]); #define PIXEL00_20 Interp2(pOut, c[5], c[4], c[2]); #define PIXEL00_21 Interp2(pOut, c[5], c[1], c[2]); #define PIXEL00_22 Interp2(pOut, c[5], c[1], c[4]); #define PIXEL00_60 Interp6(pOut, c[5], c[2], c[4]); #define PIXEL00_61 Interp6(pOut, c[5], c[4], c[2]); #define PIXEL00_70 Interp7(pOut, c[5], c[4], c[2]); #define PIXEL00_90 Interp9(pOut, c[5], c[4], c[2]); #define PIXEL00_100 Interp10(pOut, c[5], c[4], c[2]); #define PIXEL01_0 *((uint*)(pOut+4)) = ULONG( c[5] ); #define PIXEL01_10 Interp1(pOut+4, c[5], c[3]); #define PIXEL01_11 Interp1(pOut+4, c[5], c[2]); #define PIXEL01_12 Interp1(pOut+4, c[5], c[6]); #define PIXEL01_20 Interp2(pOut+4, c[5], c[2], c[6]); #define PIXEL01_21 Interp2(pOut+4, c[5], c[3], c[6]); #define PIXEL01_22 Interp2(pOut+4, c[5], c[3], c[2]); #define PIXEL01_60 Interp6(pOut+4, c[5], c[6], c[2]); #define PIXEL01_61 Interp6(pOut+4, c[5], c[2], c[6]); #define PIXEL01_70 Interp7(pOut+4, c[5], c[2], c[6]); #define PIXEL01_90 Interp9(pOut+4, c[5], c[2], c[6]); #define PIXEL01_100 Interp10(pOut+4, c[5], c[2], c[6]); #define PIXEL10_0 *((uint*)(pOut+BpL)) = ULONG( c[5] ); #define PIXEL10_10 Interp1(pOut+BpL, c[5], c[7]); #define PIXEL10_11 Interp1(pOut+BpL, c[5], c[8]); #define PIXEL10_12 Interp1(pOut+BpL, c[5], c[4]); #define PIXEL10_20 Interp2(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_21 Interp2(pOut+BpL, c[5], c[7], c[4]); #define PIXEL10_22 Interp2(pOut+BpL, c[5], c[7], c[8]); #define PIXEL10_60 Interp6(pOut+BpL, c[5], c[4], c[8]); #define PIXEL10_61 Interp6(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_70 Interp7(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_90 Interp9(pOut+BpL, c[5], c[8], c[4]); #define PIXEL10_100 Interp10(pOut+BpL, c[5], c[8], c[4]); #define PIXEL11_0 *((uint*)(pOut+BpL+4)) = ULONG( c[5] ); #define PIXEL11_10 Interp1(pOut+BpL+4, c[5], c[9]); #define PIXEL11_11 Interp1(pOut+BpL+4, c[5], c[6]); #define PIXEL11_12 Interp1(pOut+BpL+4, c[5], c[8]); #define PIXEL11_20 Interp2(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_21 Interp2(pOut+BpL+4, c[5], c[9], c[8]); #define PIXEL11_22 Interp2(pOut+BpL+4, c[5], c[9], c[6]); #define PIXEL11_60 Interp6(pOut+BpL+4, c[5], c[8], c[6]); #define PIXEL11_61 Interp6(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_70 Interp7(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_90 Interp9(pOut+BpL+4, c[5], c[6], c[8]); #define PIXEL11_100 Interp10(pOut+BpL+4, c[5], c[6], c[8]); // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int RGBtoYUV[65536]; static int YUV1, YUV2; // CODE -------------------------------------------------------------------- static void LerpColor(unsigned char *out, uint c1, uint c2, uint c3, uint f1, uint f2, uint f3) { int i, total = f1 + f2 + f3; for(i = 0; i < 4; i++) { out[i] = (f1 * COMP(i, c1) + f2 * COMP(i, c2) + f3 * COMP(i, c3)) / total; } } static void Interp1(unsigned char *pc, uint c1, uint c2) { LerpColor(pc, c1, c2, 0, 3, 1, 0); } static void Interp2(unsigned char *pc, uint c1, uint c2, uint c3) { LerpColor(pc, c1, c2, c3, 2, 1, 1); } static void Interp6(unsigned char *pc, uint c1, uint c2, uint c3) { LerpColor(pc, c1, c2, c3, 5, 2, 1); } static void Interp7(unsigned char *pc, uint c1, uint c2, uint c3) { LerpColor(pc, c1, c2, c3, 6, 1, 1); } static void Interp9(unsigned char *pc, uint c1, uint c2, uint c3) { LerpColor(pc, c1, c2, c3, 2, 3, 3); } static void Interp10(unsigned char *pc, uint c1, uint c2, uint c3) { LerpColor(pc, c1, c2, c3, 14, 1, 1); } /** * Initialize the lookup tables used in the hq2x algorithm. */ void GL_InitSmartFilter(void) { int i, j, k, r, g, b, Y, u, v; // RGB -> Yuv conversion lookup table. for(i = 0; i < 32; i++) for(j = 0; j < 64; j++) for(k = 0; k < 32; k++) { r = i << 3; g = j << 2; b = k << 3; Y = (r + g + b) >> 2; u = 128 + ((r - b) >> 2); v = 128 + ((-r + 2 * g - b) >> 3); RGBtoYUV[(k << 11) | (j << 5) | i] = (Y << 16) + (u << 8) + v; } } static int Diff(unsigned int dw1, unsigned int dw2) { // Alpha-difference? if((COMP(3, dw1) > 0) != (COMP(3, dw2) > 0)) return true; YUV1 = RGBtoYUV[RGBA32_RGB16(dw1)]; YUV2 = RGBtoYUV[RGBA32_RGB16(dw2)]; return ((abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY) || (abs((YUV1 & Umask) - (YUV2 & Umask)) > trU) || (abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV)); } /** * Operates on 32-bit pixels. */ void GL_SmartFilter2x(unsigned char *pIn, unsigned char *pOut, int Xres, int Yres, int BpL) { int i, j, k, pattern, flag; int prevline, nextline; uint dw[10]; uint w[10]; uint c[10]; // Bytes Per Pixel #define BPP 4 // +----+----+----+ // | | | | // | w1 | w2 | w3 | // +----+----+----+ // | | | | // | w4 | w5 | w6 | // +----+----+----+ // | | | | // | w7 | w8 | w9 | // +----+----+----+ for(j = 0; j < Yres; j++) { if(j > 0) prevline = -Xres * BPP; else prevline = 0; if(j < Yres - 1) nextline = Xres * BPP; else nextline = 0; for(i = 0; i < Xres; i++) { // The image data has 32-bit pixels. dw[2] = ULONG( *((uint*) (pIn + prevline)) ); dw[5] = ULONG( *((uint*) pIn) ); dw[8] = ULONG( *((uint*) (pIn + nextline)) ); if(i > 0) { dw[1] = ULONG( *((uint*) (pIn + prevline - BPP)) ); dw[4] = ULONG( *((uint*) (pIn - BPP)) ); dw[7] = ULONG( *((uint*) (pIn + nextline - BPP)) ); } else { dw[1] = dw[2]; dw[4] = dw[5]; dw[7] = dw[8]; } if(i < Xres - 1) { dw[3] = ULONG( *((uint*) (pIn + prevline + BPP)) ); dw[6] = ULONG( *((uint*) (pIn + BPP)) ); dw[9] = ULONG( *((uint*) (pIn + nextline + BPP)) ); } else { dw[3] = dw[2]; dw[6] = dw[5]; dw[9] = dw[8]; } // Convert 32-bit pixels to 16-bit pixels. for(k = 1; k <= 9; k++) { w[k] = RGBA32_RGB16(dw[k]); } pattern = 0; flag = 1; YUV1 = RGBtoYUV[w[5]]; for(k = 1; k <= 9; k++) { if(k == 5) continue; if(dw[k] != dw[5]) { YUV2 = RGBtoYUV[w[k]]; if((COMP(3, dw[5]) > 0) != (COMP(3, dw[k]) > 0) || (abs((YUV1 & Ymask) - (YUV2 & Ymask)) > trY) || (abs((YUV1 & Umask) - (YUV2 & Umask)) > trU) || (abs((YUV1 & Vmask) - (YUV2 & Vmask)) > trV)) pattern |= flag; } flag <<= 1; } for(k = 1; k <= 9; k++) { c[k] = dw[k]; } switch(pattern) { case 0: case 1: case 4: case 32: case 128: case 5: case 132: case 160: case 33: case 129: case 36: case 133: case 164: case 161: case 37: case 165: { PIXEL00_20 PIXEL01_20 PIXEL10_20 PIXEL11_20 break; } case 2: case 34: case 130: case 162: { PIXEL00_22 PIXEL01_21 PIXEL10_20 PIXEL11_20 break; } case 16: case 17: case 48: case 49: { PIXEL00_20 PIXEL01_22 PIXEL10_20 PIXEL11_21 break; } case 64: case 65: case 68: case 69: { PIXEL00_20 PIXEL01_20 PIXEL10_21 PIXEL11_22 break; } case 8: case 12: case 136: case 140: { PIXEL00_21 PIXEL01_20 PIXEL10_22 PIXEL11_20 break; } case 3: case 35: case 131: case 163: { PIXEL00_11 PIXEL01_21 PIXEL10_20 PIXEL11_20 break; } case 6: case 38: case 134: case 166: { PIXEL00_22 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 20: case 21: case 52: case 53: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_21 break; } case 144: case 145: case 176: case 177: { PIXEL00_20 PIXEL01_22 PIXEL10_20 PIXEL11_12 break; } case 192: case 193: case 196: case 197: { PIXEL00_20 PIXEL01_20 PIXEL10_21 PIXEL11_11 break; } case 96: case 97: case 100: case 101: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_22 break; } case 40: case 44: case 168: case 172: { PIXEL00_21 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 9: case 13: case 137: case 141: { PIXEL00_12 PIXEL01_20 PIXEL10_22 PIXEL11_20 break; } case 18: case 50: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_20} PIXEL10_20 PIXEL11_21 break; } case 80: case 81: { PIXEL00_20 PIXEL01_22 PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_20} break; } case 72: case 76: { PIXEL00_21 PIXEL01_20 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_20} PIXEL11_22 break; } case 10: case 138: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_20} PIXEL01_21 PIXEL10_22 PIXEL11_20 break; } case 66: { PIXEL00_22 PIXEL01_21 PIXEL10_21 PIXEL11_22 break; } case 24: { PIXEL00_21 PIXEL01_22 PIXEL10_22 PIXEL11_21 break; } case 7: case 39: case 135: { PIXEL00_11 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 148: case 149: case 180: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_12 break; } case 224: case 228: case 225: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_11 break; } case 41: case 169: case 45: { PIXEL00_12 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 22: case 54: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_20 PIXEL11_21 break; } case 208: case 209: { PIXEL00_20 PIXEL01_22 PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 104: case 108: { PIXEL00_21 PIXEL01_20 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_22 break; } case 11: case 139: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_21 PIXEL10_22 PIXEL11_20 break; } case 19: case 51: { if(Diff(dw[2], dw[6])) { PIXEL00_11 PIXEL01_10} else { PIXEL00_60 PIXEL01_90} PIXEL10_20 PIXEL11_21 break; } case 146: case 178: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_10 PIXEL11_12} else { PIXEL01_90 PIXEL11_61} PIXEL10_20 break; } case 84: case 85: { PIXEL00_20 if(Diff(dw[6], dw[8])) { PIXEL01_11 PIXEL11_10} else { PIXEL01_60 PIXEL11_90} PIXEL10_21 break; } case 112: case 113: { PIXEL00_20 PIXEL01_22 if(Diff(dw[6], dw[8])) { PIXEL10_12 PIXEL11_10} else { PIXEL10_61 PIXEL11_90} break; } case 200: case 204: { PIXEL00_21 PIXEL01_20 if(Diff(dw[8], dw[4])) { PIXEL10_10 PIXEL11_11} else { PIXEL10_90 PIXEL11_60} break; } case 73: case 77: { if(Diff(dw[8], dw[4])) { PIXEL00_12 PIXEL10_10} else { PIXEL00_61 PIXEL10_90} PIXEL01_20 PIXEL11_22 break; } case 42: case 170: { if(Diff(dw[4], dw[2])) { PIXEL00_10 PIXEL10_11} else { PIXEL00_90 PIXEL10_60} PIXEL01_21 PIXEL11_20 break; } case 14: case 142: { if(Diff(dw[4], dw[2])) { PIXEL00_10 PIXEL01_12} else { PIXEL00_90 PIXEL01_61} PIXEL10_22 PIXEL11_20 break; } case 67: { PIXEL00_11 PIXEL01_21 PIXEL10_21 PIXEL11_22 break; } case 70: { PIXEL00_22 PIXEL01_12 PIXEL10_21 PIXEL11_22 break; } case 28: { PIXEL00_21 PIXEL01_11 PIXEL10_22 PIXEL11_21 break; } case 152: { PIXEL00_21 PIXEL01_22 PIXEL10_22 PIXEL11_12 break; } case 194: { PIXEL00_22 PIXEL01_21 PIXEL10_21 PIXEL11_11 break; } case 98: { PIXEL00_22 PIXEL01_21 PIXEL10_12 PIXEL11_22 break; } case 56: { PIXEL00_21 PIXEL01_22 PIXEL10_11 PIXEL11_21 break; } case 25: { PIXEL00_12 PIXEL01_22 PIXEL10_22 PIXEL11_21 break; } case 26: case 31: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_22 PIXEL11_21 break; } case 82: case 214: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 88: case 248: { PIXEL00_21 PIXEL01_22 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 74: case 107: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_21 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_22 break; } case 27: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_10 PIXEL10_22 PIXEL11_21 break; } case 86: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_21 PIXEL11_10 break; } case 216: { PIXEL00_21 PIXEL01_22 PIXEL10_10 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 106: { PIXEL00_10 PIXEL01_21 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_22 break; } case 30: { PIXEL00_10 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_22 PIXEL11_21 break; } case 210: { PIXEL00_22 PIXEL01_10 PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 120: { PIXEL00_21 PIXEL01_22 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_10 break; } case 75: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_21 PIXEL10_10 PIXEL11_22 break; } case 29: { PIXEL00_12 PIXEL01_11 PIXEL10_22 PIXEL11_21 break; } case 198: { PIXEL00_22 PIXEL01_12 PIXEL10_21 PIXEL11_11 break; } case 184: { PIXEL00_21 PIXEL01_22 PIXEL10_11 PIXEL11_12 break; } case 99: { PIXEL00_11 PIXEL01_21 PIXEL10_12 PIXEL11_22 break; } case 57: { PIXEL00_12 PIXEL01_22 PIXEL10_11 PIXEL11_21 break; } case 71: { PIXEL00_11 PIXEL01_12 PIXEL10_21 PIXEL11_22 break; } case 156: { PIXEL00_21 PIXEL01_11 PIXEL10_22 PIXEL11_12 break; } case 226: { PIXEL00_22 PIXEL01_21 PIXEL10_12 PIXEL11_11 break; } case 60: { PIXEL00_21 PIXEL01_11 PIXEL10_11 PIXEL11_21 break; } case 195: { PIXEL00_11 PIXEL01_21 PIXEL10_21 PIXEL11_11 break; } case 102: { PIXEL00_22 PIXEL01_12 PIXEL10_12 PIXEL11_22 break; } case 153: { PIXEL00_12 PIXEL01_22 PIXEL10_22 PIXEL11_12 break; } case 58: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_11 PIXEL11_21 break; } case 83: { PIXEL00_11 if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 92: { PIXEL00_21 PIXEL01_11 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 202: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} PIXEL01_21 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} PIXEL11_11 break; } case 78: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} PIXEL01_12 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} PIXEL11_22 break; } case 154: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_22 PIXEL11_12 break; } case 114: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_12 if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 89: { PIXEL00_12 PIXEL01_22 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 90: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 55: case 23: { if(Diff(dw[2], dw[6])) { PIXEL00_11 PIXEL01_0} else { PIXEL00_60 PIXEL01_90} PIXEL10_20 PIXEL11_21 break; } case 182: case 150: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_0 PIXEL11_12} else { PIXEL01_90 PIXEL11_61} PIXEL10_20 break; } case 213: case 212: { PIXEL00_20 if(Diff(dw[6], dw[8])) { PIXEL01_11 PIXEL11_0} else { PIXEL01_60 PIXEL11_90} PIXEL10_21 break; } case 241: case 240: { PIXEL00_20 PIXEL01_22 if(Diff(dw[6], dw[8])) { PIXEL10_12 PIXEL11_0} else { PIXEL10_61 PIXEL11_90} break; } case 236: case 232: { PIXEL00_21 PIXEL01_20 if(Diff(dw[8], dw[4])) { PIXEL10_0 PIXEL11_11} else { PIXEL10_90 PIXEL11_60} break; } case 109: case 105: { if(Diff(dw[8], dw[4])) { PIXEL00_12 PIXEL10_0} else { PIXEL00_61 PIXEL10_90} PIXEL01_20 PIXEL11_22 break; } case 171: case 43: { if(Diff(dw[4], dw[2])) { PIXEL00_0 PIXEL10_11} else { PIXEL00_90 PIXEL10_60} PIXEL01_21 PIXEL11_20 break; } case 143: case 15: { if(Diff(dw[4], dw[2])) { PIXEL00_0 PIXEL01_12} else { PIXEL00_90 PIXEL01_61} PIXEL10_22 PIXEL11_20 break; } case 124: { PIXEL00_21 PIXEL01_11 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_10 break; } case 203: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_21 PIXEL10_10 PIXEL11_11 break; } case 62: { PIXEL00_10 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_11 PIXEL11_21 break; } case 211: { PIXEL00_11 PIXEL01_10 PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 118: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_12 PIXEL11_10 break; } case 217: { PIXEL00_12 PIXEL01_22 PIXEL10_10 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 110: { PIXEL00_10 PIXEL01_12 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_22 break; } case 155: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_10 PIXEL10_22 PIXEL11_12 break; } case 188: { PIXEL00_21 PIXEL01_11 PIXEL10_11 PIXEL11_12 break; } case 185: { PIXEL00_12 PIXEL01_22 PIXEL10_11 PIXEL11_12 break; } case 61: { PIXEL00_12 PIXEL01_11 PIXEL10_11 PIXEL11_21 break; } case 157: { PIXEL00_12 PIXEL01_11 PIXEL10_22 PIXEL11_12 break; } case 103: { PIXEL00_11 PIXEL01_12 PIXEL10_12 PIXEL11_22 break; } case 227: { PIXEL00_11 PIXEL01_21 PIXEL10_12 PIXEL11_11 break; } case 230: { PIXEL00_22 PIXEL01_12 PIXEL10_12 PIXEL11_11 break; } case 199: { PIXEL00_11 PIXEL01_12 PIXEL10_21 PIXEL11_11 break; } case 220: { PIXEL00_21 PIXEL01_11 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 158: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_22 PIXEL11_12 break; } case 234: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} PIXEL01_21 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_11 break; } case 242: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_12 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 59: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_11 PIXEL11_21 break; } case 121: { PIXEL00_12 PIXEL01_22 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 87: { PIXEL00_11 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 79: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_12 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} PIXEL11_22 break; } case 122: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 94: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 218: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 91: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 229: { PIXEL00_20 PIXEL01_20 PIXEL10_12 PIXEL11_11 break; } case 167: { PIXEL00_11 PIXEL01_12 PIXEL10_20 PIXEL11_20 break; } case 173: { PIXEL00_12 PIXEL01_20 PIXEL10_11 PIXEL11_20 break; } case 181: { PIXEL00_20 PIXEL01_11 PIXEL10_20 PIXEL11_12 break; } case 186: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_11 PIXEL11_12 break; } case 115: { PIXEL00_11 if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_12 if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 93: { PIXEL00_12 PIXEL01_11 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 206: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} PIXEL01_12 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} PIXEL11_11 break; } case 205: case 201: { PIXEL00_12 PIXEL01_20 if(Diff(dw[8], dw[4])) { PIXEL10_10} else { PIXEL10_70} PIXEL11_11 break; } case 174: case 46: { if(Diff(dw[4], dw[2])) { PIXEL00_10} else { PIXEL00_70} PIXEL01_12 PIXEL10_11 PIXEL11_20 break; } case 179: case 147: { PIXEL00_11 if(Diff(dw[2], dw[6])) { PIXEL01_10} else { PIXEL01_70} PIXEL10_20 PIXEL11_12 break; } case 117: case 116: { PIXEL00_20 PIXEL01_11 PIXEL10_12 if(Diff(dw[6], dw[8])) { PIXEL11_10} else { PIXEL11_70} break; } case 189: { PIXEL00_12 PIXEL01_11 PIXEL10_11 PIXEL11_12 break; } case 231: { PIXEL00_11 PIXEL01_12 PIXEL10_12 PIXEL11_11 break; } case 126: { PIXEL00_10 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_10 break; } case 219: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_10 PIXEL10_10 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 125: { if(Diff(dw[8], dw[4])) { PIXEL00_12 PIXEL10_0} else { PIXEL00_61 PIXEL10_90} PIXEL01_11 PIXEL11_10 break; } case 221: { PIXEL00_12 if(Diff(dw[6], dw[8])) { PIXEL01_11 PIXEL11_0} else { PIXEL01_60 PIXEL11_90} PIXEL10_10 break; } case 207: { if(Diff(dw[4], dw[2])) { PIXEL00_0 PIXEL01_12} else { PIXEL00_90 PIXEL01_61} PIXEL10_10 PIXEL11_11 break; } case 238: { PIXEL00_10 PIXEL01_12 if(Diff(dw[8], dw[4])) { PIXEL10_0 PIXEL11_11} else { PIXEL10_90 PIXEL11_60} break; } case 190: { PIXEL00_10 if(Diff(dw[2], dw[6])) { PIXEL01_0 PIXEL11_12} else { PIXEL01_90 PIXEL11_61} PIXEL10_11 break; } case 187: { if(Diff(dw[4], dw[2])) { PIXEL00_0 PIXEL10_11} else { PIXEL00_90 PIXEL10_60} PIXEL01_10 PIXEL11_12 break; } case 243: { PIXEL00_11 PIXEL01_10 if(Diff(dw[6], dw[8])) { PIXEL10_12 PIXEL11_0} else { PIXEL10_61 PIXEL11_90} break; } case 119: { if(Diff(dw[2], dw[6])) { PIXEL00_11 PIXEL01_0} else { PIXEL00_60 PIXEL01_90} PIXEL10_12 PIXEL11_10 break; } case 237: case 233: { PIXEL00_12 PIXEL01_20 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_100} PIXEL11_11 break; } case 175: case 47: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_100} PIXEL01_12 PIXEL10_11 PIXEL11_20 break; } case 183: case 151: { PIXEL00_11 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_100} PIXEL10_20 PIXEL11_12 break; } case 245: case 244: { PIXEL00_20 PIXEL01_11 PIXEL10_12 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_100} break; } case 250: { PIXEL00_10 PIXEL01_10 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 123: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_10 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_10 break; } case 95: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_10 PIXEL11_10 break; } case 222: { PIXEL00_10 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_10 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 252: { PIXEL00_21 PIXEL01_11 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_100} break; } case 249: { PIXEL00_12 PIXEL01_22 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_100} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 235: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_21 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_100} PIXEL11_11 break; } case 111: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_100} PIXEL01_12 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_22 break; } case 63: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_100} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_11 PIXEL11_21 break; } case 159: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_100} PIXEL10_22 PIXEL11_12 break; } case 215: { PIXEL00_11 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_100} PIXEL10_21 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 246: { PIXEL00_22 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} PIXEL10_12 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_100} break; } case 254: { PIXEL00_10 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_100} break; } case 253: { PIXEL00_12 PIXEL01_11 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_100} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_100} break; } case 251: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} PIXEL01_10 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_100} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 239: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_100} PIXEL01_12 if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_100} PIXEL11_11 break; } case 127: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_100} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_20} if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_20} PIXEL11_10 break; } case 191: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_100} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_100} PIXEL10_11 PIXEL11_12 break; } case 223: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_20} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_100} PIXEL10_10 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_20} break; } case 247: { PIXEL00_11 if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_100} PIXEL10_12 if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_100} break; } case 255: { if(Diff(dw[4], dw[2])) { PIXEL00_0} else { PIXEL00_100} if(Diff(dw[2], dw[6])) { PIXEL01_0} else { PIXEL01_100} if(Diff(dw[8], dw[4])) { PIXEL10_0} else { PIXEL10_100} if(Diff(dw[6], dw[8])) { PIXEL11_0} else { PIXEL11_100} break; } default: Con_Error("GL_SmartFilter2x: Invalid value, pattern = %i.", pattern); break; } pIn += BPP; pOut += 2 * BPP; } pOut += BpL; } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_timer.c0000644000175000017500000001052411357170242023115 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2007-2008 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_timer.c: Timing Subsystem * * \note Under WIN32, uses Win32 multimedia timing routines. */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #ifdef WIN32 # include #endif #ifdef UNIX # include #endif #include "de_base.h" #include "de_console.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float ticsPerSecond = TICSPERSEC; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static double timeOffset = 0; static mutex_t timer_Mutex; // To prevent Data races in the timer // CODE -------------------------------------------------------------------- void Sys_ShutdownTimer(void) { #ifdef WIN32 timeEndPeriod(1); #endif Sys_DestroyMutex(timer_Mutex); } void Sys_InitTimer(void) { Con_Message("Sys_InitTimer.\n"); timer_Mutex = Sys_CreateMutex("TIMER_MUTEX"); #ifdef WIN32 timeBeginPeriod(1); #endif } /** * @return The time in milliseconds. */ unsigned int Sys_GetRealTime(void) { static boolean first = true; static DWORD start; #ifdef WIN32 DWORD return_time, now; #elif UNIX Uint32 return_time, now; #endif Sys_Lock(timer_Mutex); #ifdef WIN32 now = timeGetTime(); #elif UNIX now = SDL_GetTicks(); #endif Sys_Unlock(timer_Mutex); Sys_Lock(timer_Mutex); if(first) { first = false; start = now; Sys_Unlock(timer_Mutex); return 0; } Sys_Unlock(timer_Mutex); Sys_Lock(timer_Mutex); // Wrapped around? (Every 50 days...) if(now < start) { return_time = 0xffffffff - start + now + 1; Sys_Unlock(timer_Mutex); return return_time; } return_time = now - start; Sys_Unlock(timer_Mutex); return return_time; } /** * @return The timer value in seconds. Affected by the * ticsPerSecond modifier. */ double Sys_GetSeconds(void) { return (double) ((Sys_GetRealTime() / 1000.0) * (ticsPerSecond / 35)) + timeOffset; } /** * @return The real timer value in seconds. */ double Sys_GetRealSeconds(void) { return (double) (Sys_GetRealTime() / 1000.0); } /** * @return The time in 35 Hz floating point tics. */ double Sys_GetTimef(void) { return Sys_GetSeconds() * 35; } /** * @return The time in 35 Hz tics. */ int Sys_GetTime(void) { return (int) Sys_GetTimef(); } /** * @return Set the number of game tics per second. */ void Sys_TicksPerSecond(float newTics) { double nowTime = Sys_GetRealTime() / 1000.0; if(newTics <= 0) newTics = TICSPERSEC; // Update the time offset so that after the change time will // continue from the same value. timeOffset += nowTime * (ticsPerSecond - newTics) / 35; ticsPerSecond = newTics; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/template.c.template0000644000175000017500000000347211357170242024530 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2008 Jaakko Keränen *\author Copyright © 2008 Daniel Swanson * (add more authors here) * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * : * * */ // HEADER FILES ------------------------------------------------------------ // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_sky.c0000644000175000017500000000757711357170242022244 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_sky.c: Sky Management */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_console.h" #include "cl_def.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- skymodel_t skyModels[NUM_SKY_MODELS]; boolean skyModelsInited = false; boolean alwaysDrawSphere = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * The sky models are set up using the data in the definition. */ void R_SetupSkyModels(ded_sky_t* def) { int i; ded_skymodel_t* modef; skymodel_t* sm; // Clear the whole sky models data. memset(skyModels, 0, sizeof(skyModels)); // Normally the sky sphere is not drawn if models are in use. alwaysDrawSphere = (def->flags & SIF_DRAW_SPHERE) != 0; // The normal sphere is used if no models will be set up. skyModelsInited = false; for(i = 0, modef = def->models, sm = skyModels; i < NUM_SKY_MODELS; ++i, modef++, sm++) { // Is the model ID set? if((sm->model = R_CheckIDModelFor(modef->id)) == NULL) continue; // There is a model here. skyModelsInited = true; sm->def = modef; sm->maxTimer = (int) (TICSPERSEC * modef->frameInterval); sm->yaw = modef->yaw; sm->frame = sm->model->sub[0].frame; } } /** * Prepare all sky model skins. */ void R_PrecacheSky(void) { int i; skymodel_t *sky; if(!skyModelsInited) return; for(i = 0, sky = skyModels; i < NUM_SKY_MODELS; ++i, sky++) { if(!sky->def) continue; R_PrecacheModelSkins(sky->model); } } /** * Animate sky models. */ void R_SkyTicker(void) { int i; skymodel_t *sky; if(!skyModelsInited || clientPaused) return; for(i = 0, sky = skyModels; i < NUM_SKY_MODELS; ++i, sky++) { if(!sky->def) continue; // Turn the model. sky->yaw += sky->def->yawSpeed / TICSPERSEC; // Is it time to advance to the next frame? if(sky->maxTimer > 0 && ++sky->timer >= sky->maxTimer) { sky->timer = 0; sky->frame++; // Execute a console command? if(sky->def->execute) Con_Execute(CMDS_DED, sky->def->execute, true, false); } } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/b_device.c0000644000175000017500000002710511357170241022641 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_device.c: Control-Device Bindings */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_misc.h" #include "b_main.h" #include "b_device.h" #include "b_context.h" // MACROS ------------------------------------------------------------------ #define EVTYPE_TO_CBDTYPE(evt) ((evt) == E_AXIS? CBD_AXIS : (evt) == E_TOGGLE? CBD_TOGGLE : CBD_ANGLE) #define CBDTYPE_TO_EVTYPE(cbt) ((cbt) == CBD_AXIS? E_AXIS : (cbt) == CBD_TOGGLE? E_TOGGLE : E_ANGLE) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float stageThreshold = 6.f/35; float stageFactor = .5f; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static dbinding_t* B_AllocDeviceBinding(void) { dbinding_t* cb = M_Calloc(sizeof(dbinding_t)); cb->bid = B_NewIdentifier(); return cb; } /** * Allocates a device state condition within a device binding. * * @return Pointer to the new condition, which should be filled with the condition parameters. */ static statecondition_t* B_AllocDeviceBindingCondition(dbinding_t* b) { b->conds = M_Realloc(b->conds, ++b->numConds * sizeof(statecondition_t)); memset(&b->conds[b->numConds - 1], 0, sizeof(statecondition_t)); return &b->conds[b->numConds - 1]; } void B_InitDeviceBindingList(dbinding_t* listRoot) { memset(listRoot, 0, sizeof(*listRoot)); listRoot->next = listRoot->prev = listRoot; } void B_DestroyDeviceBindingList(dbinding_t* listRoot) { while(listRoot->next != listRoot) { B_DestroyDeviceBinding(listRoot->next); } } boolean B_ParseDevice(dbinding_t* cb, const char* desc) { boolean successful = false; ddstring_t* str = Str_New(); ddeventtype_t type; // First, the device name. desc = Str_CopyDelim(str, desc, '-'); if(!Str_CompareIgnoreCase(str, "key")) { cb->device = IDEV_KEYBOARD; cb->type = CBD_TOGGLE; // Parse the key. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseKeyId(Str_Text(str), &cb->id)) { goto parseEnded; } } else if(!Str_CompareIgnoreCase(str, "mouse")) { cb->device = IDEV_MOUSE; desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseMouseTypeAndId(Str_Text(str), &type, &cb->id)) { goto parseEnded; } cb->type = EVTYPE_TO_CBDTYPE(type); } else if(!Str_CompareIgnoreCase(str, "joy")) { cb->device = IDEV_JOY1; // Next part defined button, axis, or hat. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseJoystickTypeAndId(cb->device, Str_Text(str), &type, &cb->id)) { goto parseEnded; } cb->type = EVTYPE_TO_CBDTYPE(type); // Hats include the angle. if(type == E_ANGLE) { desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseAnglePosition(Str_Text(str), &cb->angle)) { goto parseEnded; } } } // Finally, there may be some flags at the end. while(desc) { desc = Str_CopyDelim(str, desc, '-'); if(!Str_CompareIgnoreCase(str, "inverse")) { cb->flags |= CBDF_INVERSE; } else if(!Str_CompareIgnoreCase(str, "staged")) { cb->flags |= CBDF_TIME_STAGED; } else { Con_Message("B_ParseEvent: Unrecognized \"%s\".\n", desc); goto parseEnded; } } // Success. successful = true; parseEnded: Str_Delete(str); return successful; } boolean B_ParseDeviceDescriptor(dbinding_t* cb, const char* desc) { boolean successful = false; ddstring_t* str = Str_New(); // The first part specifies the device state. desc = Str_CopyDelim(str, desc, '+'); if(!B_ParseDevice(cb, Str_Text(str))) { // Failure in parsing the device. goto parseEnded; } // Any conditions? while(desc) { statecondition_t *cond; // A new condition. desc = Str_CopyDelim(str, desc, '+'); cond = B_AllocDeviceBindingCondition(cb); if(!B_ParseStateCondition(cond, Str_Text(str))) { // Failure parusing the condition. goto parseEnded; } } // Success. successful = true; parseEnded: Str_Delete(str); return successful; } dbinding_t* B_NewDeviceBinding(dbinding_t* listRoot, const char* deviceDesc) { dbinding_t* cb = B_AllocDeviceBinding(); // Parse the description of the event. if(!B_ParseDeviceDescriptor(cb, deviceDesc)) { // Error in parsing, failure to create binding. B_DestroyDeviceBinding(cb); return NULL; } // Link it into the list. cb->next = listRoot; cb->prev = listRoot->prev; listRoot->prev->next = cb; listRoot->prev = cb; return cb; } dbinding_t* B_FindDeviceBinding(bcontext_t* context, uint device, cbdevtype_t bindType, int id) { controlbinding_t* cb; dbinding_t* d; int i; if(!context) return NULL; for(cb = context->controlBinds.next; cb != &context->controlBinds; cb = cb->next) { for(i = 0; i < DDMAXPLAYERS; ++i) { for(d = cb->deviceBinds[i].next; d != &cb->deviceBinds[i]; d = d->next) { if(d->device == device && d->type == bindType && d->id == id) { return d; } } } } return NULL; } void B_DestroyDeviceBinding(dbinding_t* cb) { if(cb) { assert(cb->bid != 0); // Unlink first, if linked. if(cb->prev) { cb->prev->next = cb->next; cb->next->prev = cb->prev; } if(cb->conds) M_Free(cb->conds); M_Free(cb); } } void B_EvaluateDeviceBindingList(int localNum, dbinding_t* listRoot, float* pos, float* relativeOffset, bcontext_t* controlClass) { dbinding_t* cb; int i; boolean skip; inputdev_t* dev; inputdevaxis_t* axis; float devicePos; float deviceOffset; uint deviceTime; uint nowTime = Sys_GetRealTime(); *pos = 0; *relativeOffset = 0; if(!listRoot) return; for(cb = listRoot->next; cb != listRoot; cb = cb->next) { // If this binding has conditions, they may prevent using it. skip = false; for(i = 0; i < cb->numConds; ++i) { if(!B_CheckCondition(&cb->conds[i], localNum, controlClass)) { skip = true; break; } } if(skip) continue; // Get the device. dev = I_GetDevice(cb->device, true); if(!dev) continue; // Not available. devicePos = 0; deviceOffset = 0; deviceTime = 0; switch(cb->type) { case CBD_TOGGLE: if(controlClass && dev->keys[cb->id].assoc.bContext != controlClass) continue; // Shadowed by a more important active class. // Expired? if(dev->keys[cb->id].assoc.flags & IDAF_EXPIRED) break; devicePos = (dev->keys[cb->id].isDown? 1.0f : 0.0f); deviceTime = dev->keys[cb->id].time; break; case CBD_AXIS: axis = &dev->axes[cb->id]; if(controlClass && axis->assoc.bContext != controlClass) { if(!B_FindDeviceBinding(axis->assoc.bContext, cb->device, CBD_AXIS, cb->id)) { // The overriding context doesn't bind to the axis, though. if(axis->type == IDAT_POINTER) { // Reset the relative accumulation. axis->position = 0; } } continue; // Shadowed by a more important active class. } // Expired? if(axis->assoc.flags & IDAF_EXPIRED) break; if(axis->type == IDAT_POINTER) { deviceOffset = axis->position; axis->position = 0; } else { devicePos = axis->position; } deviceTime = axis->time; break; case CBD_ANGLE: if(controlClass && dev->hats[cb->id].assoc.bContext != controlClass) continue; // Shadowed by a more important active class. if(dev->hats[cb->id].assoc.flags & IDAF_EXPIRED) break; devicePos = (dev->hats[cb->id].pos == cb->angle? 1.0f : 0.0f); deviceTime = dev->hats[cb->id].time; break; default: Con_Error("B_EvaluateDeviceBindingList: Invalid value, cb->type = %i.", cb->type); break; } // Apply further modifications based on flags. if(cb->flags & CBDF_INVERSE) { devicePos = -devicePos; deviceOffset = -deviceOffset; } if(cb->flags & CBDF_TIME_STAGED) { if(nowTime - deviceTime < stageThreshold * 1000) { devicePos *= stageFactor; } } *pos += devicePos; *relativeOffset += deviceOffset; } // Clamp appropriately. *pos = MINMAX_OF(-1.0f, *pos, 1.0f); } /** * Does the opposite of the B_Parse* methods for a device binding, including the * state conditions. */ void B_DeviceBindingToString(const dbinding_t* b, ddstring_t* str) { int i; Str_Clear(str); // Name of the device and the key/axis/hat. B_AppendDeviceDescToString(b->device, CBDTYPE_TO_EVTYPE(b->type), b->id, str); if(b->type == CBD_ANGLE) { B_AppendAnglePositionToString(b->angle, str); } // Additional flags. if(b->flags & CBDF_TIME_STAGED) { Str_Append(str, "-staged"); } if(b->flags & CBDF_INVERSE) { Str_Append(str, "-inverse"); } // Append any state conditions. for(i = 0; i < b->numConds; ++i) { Str_Append(str, " + "); B_AppendConditionToString(&b->conds[i], str); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_extres.c0000644000175000017500000004164311357170242022740 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_extres.c: External Resources. * * Routines for locating external resource files. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_system.h" #include "de_console.h" #include "de_refresh.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define MAX_EXTENSIONS (10) #define DD_BASEDATAPATH "data\\" // TYPES ------------------------------------------------------------------- // Resource Class Flags (RCF): #define RCF_USE_BASEDATAPATH (0x1) typedef struct resclass_s { byte flags; // RCF_* flags. const char* defaultResourcePath; ddstring_t path; filehash_t* fileHash; } resclass_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The base directory for all resource directories. static ddstring_t* dataPath = NULL; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Recognized extensions (in order of importance). static const char* typeExtension[NUM_RESOURCE_TYPES][MAX_EXTENSIONS] = { { "png", "tga", "pcx", NULL }, // Graphic, favor quality. { "dmd", "md2", NULL }, // Model, favour DMD over MD2. { "wav", NULL }, // Sound, only WAV files. { "ogg", "mp3", "wav", "mod", "mid", NULL } // Music }; // Default resource classes for resource types. static const ddresourceclass_t defResClassForType[NUM_RESOURCE_TYPES] = { DDRC_GRAPHICS, DDRC_MODEL, DDRC_SFX, DDRC_MUSIC }; // Command line options for setting the path explicitly. static const char* explicitOption[NUM_RESOURCE_CLASSES][2] = { { "-texdir", "-texdir2" }, { "-flatdir", "-flatdir2" }, { "-patdir", "-patdir2" }, { "-lmdir", "-lmdir2" }, { "-flaredir", "-flaredir2" }, { "-musdir", "-musdir2" }, { "-sfxdir", "-sfxdir2" }, { "-gfxdir", "-gfxdir2" }, { "-modeldir", "-modeldir2" } // Additional paths, take precendence. }; static resclass_t resClasses[NUM_RESOURCE_CLASSES] = { { 0, "textures\\" }, { 0, "flats\\" }, { 0, "patches\\" }, { 0, "lightmaps\\" }, { 0, "flares\\" }, { 0, "music\\" }, { 0, "sfx\\" }, { RCF_USE_BASEDATAPATH, "graphics\\" }, { 0, "models\\" } }; static boolean inited = false; // CODE -------------------------------------------------------------------- static void updateFileHash(resclass_t* info) { if(!info->fileHash) // || rebuildHash { if(info->fileHash) FileHash_Destroy(info->fileHash); info->fileHash = FileHash_Create(Str_Text(&info->path)); assert(info->fileHash); } } static void initDataPath(const char* baseDataPath) { filename_t filePath; if(!dataPath) dataPath = Str_New(); M_TranslatePath(filePath, baseDataPath, FILENAME_T_MAXLEN); Dir_ValidDir(filePath, FILENAME_T_MAXLEN); Str_Set(dataPath, filePath); } /** * Set the data path. The game module is responsible for calling this. */ static void initClassDataPaths(void) { int i; filename_t filePath; // A string that identifies the game mode (e.g. doom2-plut). const char* gameMode = gx.GetVariable(DD_GAME_MODE); VERBOSE( Con_Message("initDataPaths: %s\n", M_PrettyPath(Str_Text(dataPath)))); // Update the paths of each class. for(i = 0; i < NUM_RESOURCE_CLASSES; ++i) { resclass_t* rc = &resClasses[i]; Str_Clear(&rc->path); if(ArgCheckWith(explicitOption[i][0], 1)) { // An explicit option specifies the path. M_TranslatePath(filePath, ArgNext(), FILENAME_T_MAXLEN); } else { // Build the path using the default elements. if(!(rc->flags & RCF_USE_BASEDATAPATH)) strncpy(filePath, Str_Text(dataPath), FILENAME_T_MAXLEN); else strncpy(filePath, DD_BASEDATAPATH, FILENAME_T_MAXLEN); strncat(filePath, rc->defaultResourcePath, FILENAME_T_MAXLEN); } Dir_ValidDir(filePath, FILENAME_T_MAXLEN); //Str_Prepend(&rc->path, ";"); Str_Prepend(&rc->path, filePath); if(!(rc->flags & RCF_USE_BASEDATAPATH) && gameMode && gameMode[0]) { filename_t other; dd_snprintf(other, FILENAME_T_MAXLEN, "%s%s", filePath, gameMode); Dir_ValidDir(other, FILENAME_T_MAXLEN); Str_Prepend(&rc->path, ";"); Str_Prepend(&rc->path, other); } // The overriding path. if(ArgCheckWith(explicitOption[i][1], 1)) { M_TranslatePath(filePath, ArgNext(), FILENAME_T_MAXLEN); Dir_ValidDir(filePath, FILENAME_T_MAXLEN); Str_Prepend(&rc->path, ";"); Str_Prepend(&rc->path, filePath); if(!(rc->flags & RCF_USE_BASEDATAPATH) && gameMode && gameMode[0]) { filename_t other; dd_snprintf(other, FILENAME_T_MAXLEN, "%s\\%s", filePath, gameMode); Dir_ValidDir(other, FILENAME_T_MAXLEN); Str_Prepend(&rc->path, ";"); Str_Prepend(&rc->path, other); } } if(verbose >= 2) { int n = 0; const char* p = Str_Text(&rc->path); ddstring_t path; Str_Init(&path); Con_Message("RC %i:\n", i); while((p = Str_CopyDelim(&path, p, ';'))) { Con_Message(" %i \"%s\"\n", n++, M_PrettyPath(Str_Text(&path))); } Str_Free(&path); } } } static boolean tryFindFile(const resclass_t* info, char* foundFileName, const char* path, size_t len) { if(info) { if(FileHash_Find(info->fileHash, foundFileName, path, len)) return true; } else { if(F_Access(path)) { if(foundFileName) strncpy(foundFileName, path, len); return true; } } return false; } /** * Check all possible extensions to see if the resource exists. * * @param path File path to search for. * * @return @c true, if it's found. */ static boolean tryResourceFile(resourcetype_t resType, ddresourceclass_t resClass, const char* path, char* foundFileName, size_t len) { boolean found = false; const resclass_t* info = NULL; char* ptr; // Do we need to rebuild a filehash? if(resClass != DDRC_NONE) { updateFileHash(&resClasses[resClass]); info = &resClasses[resClass]; } // Has an extension been specified? ptr = M_FindFileExtension((char*)path); if(ptr && *ptr != '*') // Try this first. found = tryFindFile(info, foundFileName, path, len); if(!found) { int i; const char** ext; ddstring_t path2, tmp; Str_Init(&path2); Str_Init(&tmp); // Create a copy of the path minus file extension. if(ptr) { Str_PartAppend(&path2, path, 0, ptr - path); } else { Str_Set(&path2, path); Str_AppendChar(&path2, '.'); } for(i = 0, ext = typeExtension[resType]; *ext; ext++) { Str_Copy(&tmp, &path2); Str_Appendf(&tmp, "%s", *ext); if((found = tryFindFile(info, foundFileName, Str_Text(&tmp), len))) break; } Str_Free(&path2); Str_Free(&tmp); } return found; } static boolean findResource(resourcetype_t resType, ddresourceclass_t resClass, char* fileName, const char* name, const char* optionalSuffix, size_t len) { boolean found = false; // First try with the optional suffix. if(optionalSuffix) { ddstring_t* fn = Str_New(); char* ptr, ext[10]; // Has an extension been specified? ptr = M_FindFileExtension((char*)name); if(ptr && *ptr != '*') { strncpy(ext, ptr, 10); Str_PartAppend(fn, name, 0, ptr - 1 - name); Str_Append(fn, optionalSuffix); Str_Append(fn, ext); } else { Str_Set(fn, name); Str_Append(fn, optionalSuffix); } if(tryResourceFile(resType, resClass, Str_Text(fn), fileName, len)) found = true; Str_Delete(fn); } // Try without a suffix. if(!found) { if(tryResourceFile(resType, resClass, name, fileName, len)) found = true; } return found; } static boolean tryLocateResource(resourcetype_t resType, ddresourceclass_t resClass, char* fileName, const char* origName, const char* optionalSuffix, size_t len) { ddstring_t name; boolean found; assert(inited); // Fix the directory seperators early so we don't need to many times // over, further down the line. Str_Init(&name); Str_Set(&name, origName); Dir_FixSlashes(Str_Text(&name), Str_Length(&name)); // If this is an absolute path, locate using it. if(Dir_IsAbsolute(Str_Text(&name))) { found = findResource(resType, DDRC_NONE, fileName, Str_Text(&name), optionalSuffix, len); } else { // Else, prepend the base path and try that. ddstring_t fn; const char* path; // Make this an absolute, base-relative path. // If only checking the base path and not the expected location // for the resource type (below); re-use the current string. if(resClass != DDRC_NONE) { Str_Init(&fn); Str_Copy(&fn, &name); Str_Prepend(&fn, ddBasePath); path = Str_Text(&fn); } else { Str_Prepend(&name, ddBasePath); path = Str_Text(&name); } // Try loading using the base path as the starting point. found = findResource(resType, DDRC_NONE, fileName, path, optionalSuffix, len); if(resClass != DDRC_NONE) Str_Free(&fn); } // Try expected location for this resource type and class? if(!found && resClass != DDRC_NONE) found = findResource(resType, resClass, fileName, Str_Text(&name), optionalSuffix, len); Str_Free(&name); return found; } static void initClassData(void) { int i; for(i = 0; i < NUM_RESOURCE_CLASSES; ++i) { resclass_t* info = &resClasses[i]; Str_Init(&info->path); info->fileHash = NULL; } } static void freeClassData(void) { int i; for(i = 0; i < NUM_RESOURCE_CLASSES; ++i) { resclass_t* info = &resClasses[i]; Str_Free(&info->path); if(info->fileHash) FileHash_Destroy(info->fileHash); info->fileHash = NULL; } } /** * Set the initial path names. */ void R_InitResourceLocator(void) { if(!inited) { initClassData(); inited = true; } initClassDataPaths(); } void R_ShutdownResourceLocator(void) { if(!inited) return; freeClassData(); Str_Free(dataPath); dataPath = NULL; inited = false; } /** * @return Ptr to a string containing the general data path. */ const char* R_GetDataPath(void) { return Str_Text(dataPath); } /** * Set the data path. The game module is responsible for calling this. */ void R_SetDataPath(const char* path) { if(dataPath && !stricmp(path, Str_Text(dataPath))) return; // The base data path has changed, rebuild everything! initDataPath(path); freeClassData(); initClassData(); } /** * @param origPath If a relative path, the data path is added in * front of it. */ void R_PrependDataPath(char* newPath, const char* origPath, size_t len) { if(Dir_IsAbsolute(origPath)) { // Can't prepend to absolute paths. strncpy(newPath, origPath, len); } else { dd_snprintf(newPath, len, "%s%s", Str_Text(dataPath), origPath); } } /** * Appends or prepends a new path to the list of resource search paths. */ void R_AddClassDataPath(ddresourceclass_t resClass, const char* addPath, boolean append) { resclass_t* info; if(!addPath || !addPath[0] || !stricmp(addPath, DIR_SEP_STR)) return; info = &resClasses[resClass]; // Compile the new search path. if(append) { Str_Append(&info->path, ";"); Str_Append(&info->path, addPath); } else { Str_Prepend(&info->path, ";"); Str_Prepend(&info->path, addPath); } } void R_ClearClassDataPath(ddresourceclass_t resClass) { resclass_t* info = &resClasses[resClass]; Str_Clear(&info->path); } /** * @return Ptr to a string containing the model data path. */ const char* R_GetClassDataPath(ddresourceclass_t resClass) { resclass_t* info = &resClasses[resClass]; return Str_Text(&info->path); } /** * Attempt to locate an external file for the specified resource. * * @param resType Type of resource being searched for (if known). * @param resClass Class specifier; alters search behavior including * locations to be searched. * @param fileName If a file is found, the fully qualified path will * be written back to here. * Can be @c NULL, which makes the routine just check * for the existence of the file. * @param name Name of the resource being searched for. * @param optionalSuffix An optional name suffix. If not @c NULL, append to * @p name and look for matches. If not found or not * specified then search for matches to @p name. * @param len Size of @p fileName in bytes. * * @return @c true, iff a file was found. */ boolean R_FindResource2(resourcetype_t resType, ddresourceclass_t resClass, char* fileName, const char* name, const char* optionalSuffix, size_t len) { if(resType < RT_FIRST || resType >= NUM_RESOURCE_TYPES) Con_Error("R_FindResource: Invalid resource type %i.\n", resType); if(resClass != DDRC_NONE && // No resource class means use the base path. (resClass < DDRC_FIRST || resClass >= NUM_RESOURCE_CLASSES)) Con_Error("R_FindResource: Invalid resource class %i.\n", resClass); return tryLocateResource(resType, resClass, fileName, name, optionalSuffix, len); } /** * Same as R_FindResource2 except that the resource class is chosen * automatically, using a set of logical defaults. */ boolean R_FindResource(resourcetype_t resType, char* fileName, const char* name, const char* optionalSuffix, size_t len) { if(resType < RT_FIRST || resType >= NUM_RESOURCE_TYPES) Con_Error("R_FindResource: Invalid resource type %i.\n", resType); return tryLocateResource(resType, defResClassForType[resType], fileName, name, optionalSuffix, len); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_sky.c0000644000175000017500000004374511357170242022730 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_sky.c: Sky Sphere and 3D Models * * This version supports only two sky layers. * (More would be a waste of resources?) */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_misc.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ #define MAXSKYLAYERS 2 #define SKYVTX_IDX(c, r) ( (r)*skyColumns + (c)%skyColumns ) // TYPES ------------------------------------------------------------------- typedef struct skyvertex_s { float pos[3]; } skyvertex_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(SkyDetail); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern float vx, vy, vz; extern byte topLineRGB[3]; // PUBLIC DATA DEFINITIONS ------------------------------------------------- skylayer_t skyLayers[MAXSKYLAYERS]; int firstLayer, activeLayers; skyvertex_t *skyVerts = NULL; // Vertices for the upper hemisphere. int numSkyVerts = 0; int skyDetail = 6, simpleSky; int skyColumns, skyRows = 3; int skyhemispheres; float skyDist = 1600; int r_fullsky = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // The texture offset to be applied to the texture coordinates in SkyVertex(). static float maxSideAngle = (float) PI / 3; static float horizonOffset = 0; static float skyTexOff; static int skyTexWidth, skyTexHeight; static boolean yflip; static fadeout_t *currentFO; // CODE -------------------------------------------------------------------- void Rend_SkyRegister(void) { // Cvars C_VAR_INT("rend-sky-detail", &skyDetail, CVF_PROTECTED, 3, 7); C_VAR_INT("rend-sky-rows", &skyRows, CVF_PROTECTED, 1, 8); C_VAR_FLOAT("rend-sky-distance", &skyDist, CVF_NO_MAX, 1, 0); C_VAR_INT("rend-sky-full", &r_fullsky, 0, 0, 1); C_VAR_INT("rend-sky-simple", &simpleSky, 0, 0, 2); // Ccmds C_CMD_FLAGS("skydetail", "i", SkyDetail, CMDF_NO_DEDICATED); C_CMD_FLAGS("skyrows", "i", SkyDetail, CMDF_NO_DEDICATED); } void Rend_RenderSkyModels(void) { int i, c; float inter; skymodel_t *sky; rendmodelparams_t params; float pos[3]; glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Setup basic translation. glTranslatef(vx, vy, vz); for(i = 0, sky = skyModels; i < NUM_SKY_MODELS; ++i, sky++) { if(!sky->def) continue; if(sky->def->layer > 0 && sky->def->layer <= MAXSKYLAYERS && !(skyLayers[sky->def->layer - 1].flags & SLF_ENABLED)) { // The model has been assigned to a layer, but the layer is // not visible. continue; } // Calculate the coordinates for the model. pos[0] = vx * -sky->def->coordFactor[0]; pos[1] = vy * -sky->def->coordFactor[1]; pos[2] = vz * -sky->def->coordFactor[2]; inter = (sky->maxTimer > 0 ? sky->timer / (float) sky->maxTimer : 0); memset(¶ms, 0, sizeof(params)); params.distance = 1; params.center[VX] = pos[0]; params.center[VY] = pos[2]; params.center[VZ] = params.gzt = pos[1]; params.extraYawAngle = params.yawAngleOffset = sky->def->rotate[0]; params.extraPitchAngle = params.pitchAngleOffset = sky->def->rotate[1]; params.inter = inter; params.mf = sky->model; params.alwaysInterpolate = true; R_SetModelFrame(sky->model, sky->frame); params.yaw = sky->yaw; for(c = 0; c < 4; ++c) { params.ambientColor[c] = sky->def->color[c]; } params.vLightListIdx = 0; params.shineTranslateWithViewerPos = true; Rend_RenderModel(¶ms); } // We don't want that anything interferes with what was drawn. glClear(GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } /** * Calculate the vertex and texture coordinates. */ static void SkyVertex(int r, int c) { // The direction must be clockwise. skyvertex_t *svtx = skyVerts + SKYVTX_IDX(c, r); // And the texture coordinates. if(!yflip) // Flipped Y is for the lower hemisphere. { glTexCoord2f((1024 / skyTexWidth) * c / (float) skyColumns + skyTexOff / skyTexWidth, r / (float) skyRows); } else { glTexCoord2f((1024 / skyTexWidth) * c / (float) skyColumns + skyTexOff / skyTexWidth, (skyRows - r) / (float) skyRows); } // Also the color. if(currentFO->use) { if(r == 0) glColor4f(1, 1, 1, 0); else glColor3f(1, 1, 1); } else { if(r == 0) glColor3f(0, 0, 0); else glColor3f(1, 1, 1); } // And finally the vertex itself. glVertex3f(svtx->pos[VX], svtx->pos[VY] * (yflip ? -1 : 1), svtx->pos[VZ]); } static void CapSideVertex(int r, int c) { // Look up the precalculated vertex. skyvertex_t *svtx = skyVerts + SKYVTX_IDX(c, r); glVertex3f(svtx->pos[VX], svtx->pos[VY] * (yflip ? -1 : 1), svtx->pos[VZ]); } /** * \note The current texture is used. * @param hemi Upper or Lower. Zero is not acceptable. * SKYHEMI_JUST_CAP can be used. */ void Rend_SkyRenderer(int hemi) { int r, c; if(hemi & SKYHEMI_LOWER) yflip = true; else yflip = false; // The top row (row 0) is the one that's faded out. // There must be at least 4 columns. The preferable number is 4n, where // n is 1, 2, 3... There should be at least two rows because the first // one is always faded. if(hemi & SKYHEMI_JUST_CAP) { glDisable(GL_TEXTURE_2D); // Use the appropriate color. if(currentFO->use) glColor3fv(currentFO->rgb); else glColor3f(0, 0, 0); // Draw the cap. glBegin(GL_TRIANGLE_FAN); for(c = 0; c < skyColumns; ++c) CapSideVertex(0, c); glEnd(); // If we are doing a colored fadeout... if(hemi & SKYHEMI_FADEOUT_BG) { // We must fill the background for the top row since it'll // be partially translucent. glBegin(GL_TRIANGLE_STRIP); CapSideVertex(0, 0); for(c = 0; c < skyColumns; ++c) { CapSideVertex(1, c); // One step down. CapSideVertex(0, c + 1); // And one step right. } CapSideVertex(1, c); glEnd(); } glEnable(GL_TEXTURE_2D); return; } // The total number of triangles per hemisphere can be calculated // as follows: rows * columns * 2 + 2 (for the top cap). for(r = 0; r < skyRows; ++r) { if(simpleSky) { glBegin(GL_QUADS); for(c = 0; c < skyColumns; ++c) { SkyVertex(r, c); SkyVertex(r + 1, c); SkyVertex(r + 1, c + 1); SkyVertex(r, c + 1); } glEnd(); } else { glBegin(GL_TRIANGLE_STRIP); SkyVertex(r, 0); SkyVertex(r + 1, 0); for(c = 1; c <= skyColumns; ++c) { SkyVertex(r, c); SkyVertex(r + 1, c); } glEnd(); } } } static void setupFadeout(skylayer_t* slayer) { if(slayer->mat) { int i; material_load_params_t params; material_snapshot_t ms; // Ensure we have up to date info on the material. memset(¶ms, 0, sizeof(params)); params.flags = MLF_LOAD_AS_SKY | MLF_TEX_NO_COMPRESSION; if(slayer->flags & SLF_MASKED) params.flags |= MLF_ZEROMASK; Material_Prepare(&ms, slayer->mat, true, ¶ms); slayer->fadeout.rgb[CR] = ms.topColor[CR]; slayer->fadeout.rgb[CG] = ms.topColor[CG]; slayer->fadeout.rgb[CB] = ms.topColor[CB]; // Determine if it should be used. for(slayer->fadeout.use = false, i = 0; i < 3; ++i) if(slayer->fadeout.rgb[i] > slayer->fadeout.limit) { // Colored fadeout is needed. slayer->fadeout.use = true; break; } return; } // An invalid texture, default to black. slayer->fadeout.rgb[CR] = slayer->fadeout.rgb[CG] = slayer->fadeout.rgb[CB] = 0; slayer->fadeout.use = true; } void Rend_RenderSkyHemisphere(int whichHemi) { int i; skylayer_t* slayer; // The current fadeout is the first layer's fadeout. currentFO = &skyLayers[firstLayer].fadeout; // First render the cap and the background for fadeouts, if needed. // The color for both is the current fadeout color. Rend_SkyRenderer(whichHemi | SKYHEMI_JUST_CAP | (currentFO->use ? SKYHEMI_FADEOUT_BG : 0)); for(i = firstLayer, slayer = &skyLayers[firstLayer]; i < MAXSKYLAYERS; ++i, slayer++) { if(slayer->flags & SLF_ENABLED) { byte result = 0; if(!slayer->mat) Con_Error("Rend_RenderSkyHemisphere: Sky layer " "without a material!\n"); // The texture is actually loaded when an update is done. if(renderTextures) { material_load_params_t params; material_snapshot_t ms; memset(¶ms, 0, sizeof(params)); params.flags = MLF_LOAD_AS_SKY | MLF_TEX_NO_COMPRESSION; if(slayer->flags & SLF_MASKED) params.flags |= MLF_ZEROMASK; result = Material_Prepare(&ms, slayer->mat, true, ¶ms); skyTexWidth = GLTexture_GetWidth(ms.units[MTU_PRIMARY].texInst->tex); skyTexHeight = GLTexture_GetHeight(ms.units[MTU_PRIMARY].texInst->tex); if(result) { // Texture was reloaded. setupFadeout(slayer); } GL_BindTexture(ms.units[MTU_PRIMARY].texInst->id, ms.units[MTU_PRIMARY].magMode); } else { glBindTexture(GL_TEXTURE_2D, 0); skyTexWidth = skyTexHeight = 64; } skyTexOff = slayer->offset; Rend_SkyRenderer(whichHemi); } } } void Rend_RenderSky(int hemis) { // IS there a sky to be rendered? if(!hemis || firstLayer == -1) return; // If sky models have been inited, they will be used. if(!skyModelsInited || alwaysDrawSphere) { // Always render the full sky? if(r_fullsky) hemis = SKYHEMI_UPPER | SKYHEMI_LOWER; // We don't want anything written in the depth buffer, not yet. glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); // Disable culling, all triangles face the viewer. glDisable(GL_CULL_FACE); GL_DisableArrays(true, true, DDMAXINT); // Setup a proper matrix. glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(vx, vy, vz); glScalef(skyDist, skyDist, skyDist); // Draw the possibly visible hemispheres. if(hemis & SKYHEMI_LOWER) Rend_RenderSkyHemisphere(SKYHEMI_LOWER); if(hemis & SKYHEMI_UPPER) Rend_RenderSkyHemisphere(SKYHEMI_UPPER); glMatrixMode(GL_MODELVIEW); glPopMatrix(); // Enable the disabled things. glEnable(GL_CULL_FACE); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); } // How about some 3D models? if(skyModelsInited) { Rend_RenderSkyModels(); } } /** * Calculate sky vertices. */ void Rend_InitSky(void) { int i; firstLayer = 0; Rend_SkyDetail(skyDetail, skyRows); // Initialize the layers. for(i = 0; i < MAXSKYLAYERS; ++i) { skylayer_t* slayer = &skyLayers[i]; slayer->mat = NULL; // No material. slayer->fadeout.limit = .3f; } } void Rend_ShutdownSky(void) { M_Free(skyVerts); skyVerts = NULL; numSkyVerts = 0; } void Rend_SkyDetail(int quarterDivs, int rows) { float topAngle, sideAngle, realRadius, scale = 1 /*32 */ ; int c, r; skyvertex_t *svtx; if(quarterDivs < 1) quarterDivs = 1; if(rows < 1) rows = 1; skyDetail = quarterDivs; skyColumns = 4 * skyDetail; skyRows = rows; // Calculate the sky vertices. numSkyVerts = skyColumns * (skyRows + 1); // Allocate memory for it. skyVerts = M_Realloc(skyVerts, sizeof(*skyVerts) * numSkyVerts); // Calculate the vertices. for(r = 0; r <= skyRows; ++r) for(c = 0; c < skyColumns; ++c) { svtx = skyVerts + SKYVTX_IDX(c, r); topAngle = ((c / (float) skyColumns) *2) * PI; sideAngle = horizonOffset + maxSideAngle * (skyRows - r) / (float) skyRows; realRadius = scale * cos(sideAngle); svtx->pos[VX] = realRadius * cos(topAngle); svtx->pos[VY] = scale * sin(sideAngle); // The height. svtx->pos[VZ] = realRadius * sin(topAngle); } } static void updateLayerStats(void) { int i = 0; // -1 denotes 'no active layers'. firstLayer = -1; activeLayers = 0; for(i = 0; i < MAXSKYLAYERS; ++i) { if(skyLayers[i].flags & SLF_ENABLED) { activeLayers++; if(firstLayer == -1) firstLayer = i; } } } static void internalSkyParams(skylayer_t* slayer, int param, void* data) { switch(param) { case DD_ENABLE: slayer->flags |= SLF_ENABLED; updateLayerStats(); break; case DD_DISABLE: slayer->flags &= ~SLF_ENABLED; updateLayerStats(); break; case DD_MASK: { boolean deleteTextures = false; if(*((int*)data) == DD_YES) { // Invalidate the loaded texture, if necessary. if(slayer->mat && !(slayer->flags & SLF_MASKED)) deleteTextures = true; slayer->flags |= SLF_MASKED; } else { // Invalidate the loaded texture, if necessary. if(slayer->mat && (slayer->flags & SLF_MASKED)) deleteTextures = true; slayer->flags &= ~SLF_MASKED; } if(deleteTextures) Material_DeleteTextures(slayer->mat); } break; case DD_MATERIAL: if((slayer->mat = P_ToMaterial(*(materialnum_t*) data))) { material_load_params_t params; memset(¶ms, 0, sizeof(params)); params.flags = MLF_LOAD_AS_SKY | MLF_TEX_NO_COMPRESSION; if(slayer->flags & SLF_MASKED) params.flags |= MLF_ZEROMASK; Material_Prepare(NULL, slayer->mat, true, ¶ms); } setupFadeout(slayer); break; case DD_OFFSET: slayer->offset = *((float*) data); break; case DD_COLOR_LIMIT: slayer->fadeout.limit = *((float*) data); setupFadeout(slayer); break; default: Con_Error("R_SkyParams: Bad parameter (%d).\n", param); break; } } void Rend_SkyParams(int layer, int param, void* data) { int i; if(isDedicated) return; if(layer == DD_SKY) // The whole sky? { switch(param) { case DD_COLUMNS: Rend_SkyDetail(*((int*) data), skyRows); break; case DD_ROWS: Rend_SkyDetail(skyDetail, *((int*) data)); break; case DD_HEIGHT: maxSideAngle = PI / 2 * *((float*) data); // Recalculate the vertices. Rend_SkyDetail(skyDetail, skyRows); break; case DD_HORIZON: // horizon offset angle horizonOffset = PI / 2 * *((float*) data); // Recalculate the vertices. Rend_SkyDetail(skyDetail, skyRows); break; default: // Operate on all layers. for(i = 0; i < MAXSKYLAYERS; ++i) internalSkyParams(&skyLayers[i], param, data); } } // This is for a specific layer. else if(layer >= 0 && layer < MAXSKYLAYERS) internalSkyParams(&skyLayers[layer], param, data); } D_CMD(SkyDetail) { if(!stricmp(argv[0], "skydetail")) { Rend_SkyDetail(strtol(argv[1], NULL, 0), skyRows); } else if(!stricmp(argv[0], "skyrows")) { Rend_SkyDetail(skyDetail, strtol(argv[1], NULL, 0)); } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_things.c0000644000175000017500000016751211357170242022726 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_things.c: Object Management and Refresh */ /** * Sprite rotation 0 is facing the viewer, rotation 1 is one angle * turn CLOCKWISE around the axis. This is not the same as the angle, * which increases counter clockwise (protractor). */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_refresh.h" #include "de_play.h" #include "de_render.h" #include "de_graphics.h" #include "de_misc.h" #include "def_main.h" #include "m_stack.h" // MACROS ------------------------------------------------------------------ #define MAX_FRAMES (128) #define MAX_OBJECT_RADIUS (128) // TYPES ------------------------------------------------------------------- typedef struct vlightnode_s { struct vlightnode_s* next, *nextUsed; vlight_t vlight; } vlightnode_t; typedef struct vlightlist_s { vlightnode_t* head; boolean sortByDist; } vlightlist_t; typedef struct { vec3_t pos; boolean haveList; uint listIdx; } vlightiterparams_t; typedef struct spriterecord_frame_s { lumpnum_t lump; byte frame[2]; byte rotation[2]; material_t* mat; struct spriterecord_frame_s* next; } spriterecord_frame_t; typedef struct spriterecord_s { char name[5]; int numFrames; spriterecord_frame_t* frames; struct spriterecord_s* next; } spriterecord_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float weaponOffsetScale = 0.3183f; // 1/Pi int weaponOffsetScaleY = 1000; float weaponFOVShift = 45; float modelSpinSpeed = 1; int alwaysAlign = 0; int noSpriteZWrite = false; float pspOffset[2] = {0, 0}; float pspLightLevelMultiplier = 1; // useSRVO: 1 = models only, 2 = sprites + models int useSRVO = 2, useSRVOAngle = true; int psp3d; // Variables used to look up and range check sprites patches. spritedef_t* sprites = 0; int numSprites; vissprite_t visSprites[MAXVISSPRITES], *visSpriteP; vispsprite_t visPSprites[DDMAXPSPRITES]; int maxModelDistance = 1500; int levelFullBright = false; vissprite_t visSprSortedHead; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // vlight nodes. static vlightnode_t* vLightFirst, *vLightCursor; // vlight link lists. static uint numVLightLinkLists = 0, vLightLinkListCursor = 0; static vlightlist_t* vLightLinkLists; static vissprite_t overflowVisSprite; static const float worldLight[3] = {-.400891f, -.200445f, .601336f}; // Tempory storage, used when reading sprite definitions. static int numSpriteRecords; static spriterecord_t* spriteRecords; static zblockset_t* spriteRecordBlockSet, *spriteRecordFrameBlockSet; // CODE -------------------------------------------------------------------- /** * Initialize the vlight system in preparation for rendering view(s) of the * game world. Called by R_InitLevel(). */ void VL_InitForMap(void) { vLightLinkLists = NULL; numVLightLinkLists = 0, vLightLinkListCursor = 0; } /** * Moves all used vlight nodes to the list of unused nodes, so they can be * reused. */ void VL_InitForNewFrame(void) { // Start reusing nodes from the first one in the list. vLightCursor = vLightFirst; // Clear the mobj vlight link lists. vLightLinkListCursor = 0; if(numVLightLinkLists) memset(vLightLinkLists, 0, numVLightLinkLists * sizeof(vlightlist_t)); } /** * Create a new vlight list. * * @param sortByDist Lights in this list will be automatically sorted by * their approximate distance from the point being lit. * @return Identifier for the new list. */ static uint newVLightList(boolean sortByDist) { vlightlist_t* list; // Ran out of vlight link lists? if(++vLightLinkListCursor >= numVLightLinkLists) { uint newNum = numVLightLinkLists * 2; if(!newNum) newNum = 2; vLightLinkLists = Z_Realloc(vLightLinkLists, newNum * sizeof(vlightlist_t), PU_MAP); numVLightLinkLists = newNum; } list = &vLightLinkLists[vLightLinkListCursor-1]; list->head = NULL; list->sortByDist = sortByDist; return vLightLinkListCursor - 1; } static vlightnode_t* newVLightNode(void) { vlightnode_t* node; // Have we run out of nodes? if(vLightCursor == NULL) { node = Z_Malloc(sizeof(vlightnode_t), PU_STATIC, NULL); // Link the new node to the list. node->nextUsed = vLightFirst; vLightFirst = node; } else { node = vLightCursor; vLightCursor = vLightCursor->nextUsed; } node->next = NULL; return node; } /** * @return Ptr to a new vlight node. If the list of unused * nodes is empty, a new node is created. */ static vlightnode_t* newVLight(void) { vlightnode_t* node = newVLightNode(); //vlight_t* vlight = &node->vlight; //// \todo move vlight setup here. return node; } static void linkVLightNodeToList(vlightnode_t* node, uint listIndex) { vlightlist_t* list = &vLightLinkLists[listIndex]; if(list->sortByDist && list->head) { vlightnode_t* last, *iter; vlight_t* vlight; last = iter = list->head; do { vlight = &node->vlight; // Is this closer than the one being added? if(node->vlight.approxDist > vlight->approxDist) { last = iter; iter = iter->next; } else { // Need to insert it here. node->next = last->next; last->next = node; return; } } while(iter); } node->next = list->head; list->head = node; } /** * Local function for R_InitSprites. */ static void installSpriteLump(spriteframe_t* sprTemp, int* maxFrame, material_t* mat, uint frame, uint rotation, boolean flipped) { if(frame >= 30 || rotation > 8) { return; } if((int) frame > *maxFrame) *maxFrame = frame; if(rotation == 0) { int r; // The lump should be used for all rotations. sprTemp[frame].rotate = false; for(r = 0; r < 8; ++r) { sprTemp[frame].mats[r] = mat; sprTemp[frame].flip[r] = (byte) flipped; } return; } sprTemp[frame].rotate = true; rotation--; // Make 0 based. sprTemp[frame].mats[rotation] = mat; sprTemp[frame].flip[rotation] = (byte) flipped; } /** * In DOOM, a sprite frame is a patch texture contained in a lump * existing between the S_START and S_END marker lumps (in WAD) whose * lump name matches the following pattern: * * NAME|A|R(A|R) (for example: "TROOA0" or "TROOA2A8") * * NAME: Four character name of the sprite. * A: Animation frame ordinal 'A'... (ASCII). * R: Rotation angle 0...8 * 0 : Use this frame for ALL angles. * 1...8 : Angle of rotation in 45 degree increments. * * The second set of (optional) frame and rotation characters instruct * that the same sprite frame is to be used for an additional frame * but that the sprite patch should be flipped horizontally (right to * left) during the loading phase. */ void R_PreInitSprites(void) { float startTime = Sys_GetSeconds(); int i, numSpritePatches = 0; ddstack_t* stack = Stack_New(); // Free all memory acquired for spritetex_t structures. Z_FreeTags(PU_SPRITE, PU_SPRITE); /** * Step 1: Build database of lumps which may describe sprites. */ numSpriteRecords = 0; spriteRecords = NULL; spriteRecordBlockSet = Z_BlockCreate(sizeof(spriterecord_t), 64, PU_STATIC), spriteRecordFrameBlockSet = Z_BlockCreate(sizeof(spriterecord_frame_t), 256, PU_STATIC); for(i = 0; i < numLumps; ++i) { const char* name = W_LumpName(i); spriterecord_t* rec; if(name[0] == 'S') { if(!strnicmp(name + 1, "_START", 6) || !strnicmp(name + 2, "_START", 6)) { // We've arrived at *a* sprite block. Stack_Push(stack, NULL); continue; } else if(!strnicmp(name + 1, "_END", 4) || !strnicmp(name + 2, "_END", 4)) { // The sprite block ends. Stack_Pop(stack); continue; } } if(!Stack_Height(stack)) continue; /** * This lump is potentially a sprite. */ // Check that the name is valid. if(!name[4] || !name[5] || (name[6] && !name[7])) continue; // This is not a sprite frame. // Indices 5 and 7 must be numbers (0-8). if(name[5] < '0' || name[5] > '8') continue; if(name[7] && (name[7] < '0' || name[7] > '8')) continue; if(W_LumpLength(i) < 8) continue; numSpritePatches++; // Its a valid, name. Have we already come accross it? rec = spriteRecords; while(rec) { if(!strnicmp(rec->name, name, 4)) break; rec = rec->next; } if(!rec) { // An entirely new sprite. rec = Z_BlockNewElement(spriteRecordBlockSet); strncpy(rec->name, name, 4); rec->name[4] = '\0'; rec->numFrames = 0; rec->frames = NULL; rec->next = spriteRecords; spriteRecords = rec; numSpriteRecords++; } // Add the frame(s). { spriterecord_frame_t* sprFrame = rec->frames; boolean link = false; while(sprFrame) { if(sprFrame->frame[0] == name[4] - 'A' + 1 && sprFrame->rotation[0] == name[5] - '0') break; sprFrame = sprFrame->next; } if(!sprFrame) { // A new frame. sprFrame = Z_BlockNewElement(spriteRecordFrameBlockSet); link = true; } sprFrame->lump = i; sprFrame->frame[0] = name[4] - 'A' + 1; sprFrame->rotation[0] = name[5] - '0'; if(name[6]) { sprFrame->frame[1] = name[6] - 'A' + 1; sprFrame->rotation[1] = name[7] - '0'; } else { sprFrame->frame[1] = 0; } if(link) { sprFrame->next = rec->frames; rec->frames = sprFrame; } } } while(Stack_Height(stack)) Stack_Pop(stack); Stack_Delete(stack); /** * Step 2: Create gltextures and materials for ALL sprite patches. */ numSpriteTextures = numSpritePatches; spriteTextures = NULL; if(numSpritePatches) { int idx = 0; spritetex_t* storage; spriterecord_t* rec = spriteRecords; spriteTextures = Z_Malloc(sizeof(spritetex_t*) * numSpriteTextures, PU_SPRITE, 0); storage = Z_Malloc(sizeof(spritetex_t) * numSpriteTextures, PU_SPRITE, 0); do { spriterecord_frame_t* frame = rec->frames; do { const char* name; const lumppatch_t* patch; spritetex_t* sprTex; const gltexture_t* glTex; spriteTextures[idx] = sprTex = &storage[idx]; patch = (const lumppatch_t *) W_CacheLumpNum(frame->lump, PU_CACHE); name = W_LumpName(frame->lump); sprTex->lump = frame->lump; sprTex->offX = SHORT(patch->leftOffset); sprTex->offY = SHORT(patch->topOffset); sprTex->width = SHORT(patch->width); sprTex->height = SHORT(patch->height); glTex = GL_CreateGLTexture(name, idx++, GLT_SPRITE); // Create a new material for this sprite patch. frame->mat = P_MaterialCreate(name, sprTex->width, sprTex->height, 0, glTex->id, MN_SPRITES, NULL); } while((frame = frame->next)); } while((rec = rec->next)); } VERBOSE(Con_Message("R_InitSpriteRecords: Done in %.2f seconds.\n", Sys_GetSeconds() - startTime)); } static void initSpriteDefs(spriterecord_t* const * sprRecords, int num) { numSprites = num; if(sprites) Z_Free(sprites); sprites = NULL; if(numSprites) { int n, idx = 0; spriteframe_t sprTemp[MAX_FRAMES]; int maxFrame; sprites = Z_Malloc(numSprites * sizeof(*sprites), PU_STATIC, NULL); for(n = 0; n < num; ++n) { int frame; const spriterecord_t* rec; spritedef_t* sprDef = &sprites[n]; if(!sprRecords[n]) { // A record for a sprite we were unable to locate. sprDef->numFrames = 0; sprDef->spriteFrames = NULL; continue; } rec = sprRecords[n]; memset(sprTemp, -1, sizeof(sprTemp)); maxFrame = -1; { const spriterecord_frame_t* frame = rec->frames; do { installSpriteLump(sprTemp, &maxFrame, frame->mat, frame->frame[0] - 1, frame->rotation[0], false); if(frame->frame[1]) installSpriteLump(sprTemp, &maxFrame, frame->mat, frame->frame[1] - 1, frame->rotation[1], true); } while((frame = frame->next)); } /** * Check the frames that were found for completeness. */ if(maxFrame == -1) { // Should NEVER happen. sprDef->numFrames = 0; } maxFrame++; for(frame = 0; frame < maxFrame; ++frame) { switch((int) sprTemp[frame].rotate) { case -1: // No rotations were found for that frame at all. Con_Error("R_InitSprites: No patches found for %s frame %c.", rec->name, frame + 'A'); break; case 0: // Only the first rotation is needed. break; case 1: // Must have all 8 frames. { int rotation; for(rotation = 0; rotation < 8; ++rotation) { if(!sprTemp[frame].mats[rotation]) Con_Error("R_InitSprites: Sprite %s frame %c is " "missing rotations.", rec->name, frame + 'A'); } } break; default: Con_Error("R_InitSpriteDefs: Invalid value, " "sprTemp[frame].rotate = %i.", (int) sprTemp[frame].rotate); break; } } // Allocate space for the frames present and copy sprTemp to it. strncpy(sprDef->name, rec->name, 4); sprDef->name[4] = '\0'; sprDef->numFrames = maxFrame; sprDef->spriteFrames = Z_Malloc(maxFrame * sizeof(spriteframe_t), PU_SPRITE, NULL); memcpy(sprDef->spriteFrames, sprTemp, maxFrame * sizeof(spriteframe_t)); } } } /** * Builds the sprite rotation matrixes to account for horizontally flipped * sprites. Will report an error if the lumps are inconsistant. * * Sprite lump names are 4 characters for the actor, a letter for the frame, * and a number for the rotation, A sprite that is flippable will have an * additional letter/number appended. The rotation character can be 0 to * signify no rotations. */ void R_InitSprites(void) { float startTime = Sys_GetSeconds(); int n, max; spriterecord_t* rec, **list; /** * \kludge * As the games still rely upon the sprite definition indices to match * those of the sprite name table, use the later to re-index the sprite * records database before using them to derive the sprite definitions. * New sprites added in mods that we do not have sprite name defs for * are pushed to the end of the list (this is fine as the game will not * attempt to reference them by either name or indice as they are not * present in their game-side sprite index tables. Similarly, DeHackED * does not allow for new sprite frames to be added anyway). * * \todo * This unobvious requirement should be broken somehow and perhaps even * get rid of the sprite name definitions entirely. */ max = MAX_OF(numSpriteRecords, countSprNames.num); n = max-1; list = M_Calloc(sizeof(spriterecord_t*) * max); rec = spriteRecords; do { int idx = Def_GetSpriteNum(rec->name); list[idx == -1? n-- : idx] = rec; } while((rec = rec->next)); /// \kludge end // Create sprite definitions from the located sprite patch lumps. initSpriteDefs(list, max); M_Free(list); // We are now done with the sprite records. Z_BlockDestroy(spriteRecordBlockSet); spriteRecordBlockSet = NULL; Z_BlockDestroy(spriteRecordFrameBlockSet); spriteRecordFrameBlockSet = NULL; numSpriteRecords = 0; VERBOSE(Con_Message("R_InitSprites: Done in %.2f seconds.\n", Sys_GetSeconds() - startTime)); } material_t* R_GetMaterialForSprite(int sprite, int frame) { spritedef_t* sprDef; if((unsigned) sprite >= (unsigned) numSprites) return NULL; sprDef = &sprites[sprite]; if(frame >= sprDef->numFrames) return NULL; return sprDef->spriteFrames[frame].mats[0]; } boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* info) { spritedef_t* sprDef; spriteframe_t* sprFrame; spritetex_t* sprTex; material_t* mat; material_snapshot_t ms; if((unsigned) sprite >= (unsigned) numSprites) { Con_Message("R_GetSpriteInfo: Warning, invalid sprite number %i.\n", sprite); return false; } sprDef = &sprites[sprite]; if(frame >= sprDef->numFrames) { // We have no information to return. memset(info, 0, sizeof(*info)); return false; } sprFrame = &sprDef->spriteFrames[frame]; mat = sprFrame->mats[0]; Material_Prepare(&ms, mat, false, NULL); sprTex = spriteTextures[ms.units[MTU_PRIMARY].texInst->tex->ofTypeID]; info->numFrames = sprDef->numFrames; info->material = mat; info->realLump = sprTex->lump; info->flip = sprFrame->flip[0]; info->offset = sprTex->offX; info->topOffset = sprTex->offY; info->width = ms.width; info->height = ms.height; return true; } boolean R_GetPatchInfo(lumpnum_t lump, patchinfo_t* info) { if(info) return false; memset(info, 0, sizeof(*info)); if(lump >= 0 && lump < numLumps) { lumppatch_t* patch = (lumppatch_t*) W_CacheLumpNum(lump, PU_CACHE); info->lump = info->realLump = lump; info->width = SHORT(patch->width); info->height = SHORT(patch->height); info->topOffset = SHORT(patch->topOffset); info->offset = SHORT(patch->leftOffset); return true; } VERBOSE(Con_Message("R_GetPatchInfo: Warning, invalid lumpnum %i.\n", lump)); return false; } /** * @return Radius of the mobj as it would visually appear to be. */ float R_VisualRadius(mobj_t* mo) { modeldef_t* mf, *nextmf; material_snapshot_t ms; // If models are being used, use the model's radius. if(useModels) { R_CheckModelFor(mo, &mf, &nextmf); if(mf) { // Returns the model's radius! return mf->visualRadius; } } // Use the sprite frame's width. Material_Prepare(&ms, R_GetMaterialForSprite(mo->sprite, mo->frame), true, NULL); return ms.width / 2; } /** * Called at frame start. */ void R_ClearSprites(void) { visSpriteP = visSprites; } vissprite_t* R_NewVisSprite(void) { vissprite_t* spr; if(visSpriteP == &visSprites[MAXVISSPRITES]) { spr = &overflowVisSprite; } else { visSpriteP++; spr = visSpriteP - 1; } memset(spr, 0, sizeof(*spr)); return spr; } /** * If 3D models are found for psprites, here we will create vissprites for * them. */ void R_ProjectPlayerSprites(void) { int i; float inter; modeldef_t* mf, *nextmf; ddpsprite_t* psp; boolean isFullBright = (levelFullBright != 0); boolean isModel; ddplayer_t* ddpl = &viewPlayer->shared; const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); psp3d = false; // Cameramen have no psprites. if((ddpl->flags & DDPF_CAMERA) || (ddpl->flags & DDPF_CHASECAM)) return; // Determine if we should be drawing all the psprites full bright? if(!isFullBright) { for(i = 0, psp = ddpl->pSprites; i < DDMAXPSPRITES; ++i, psp++) { if(!psp->statePtr) continue; // If one of the psprites is fullbright, both are. if(psp->statePtr->flags & STF_FULLBRIGHT) isFullBright = true; } } for(i = 0, psp = ddpl->pSprites; i < DDMAXPSPRITES; ++i, psp++) { vispsprite_t* spr = &visPSprites[i]; spr->type = VPSPR_SPRITE; spr->psp = psp; if(!psp->statePtr) continue; // First, determine whether this is a model or a sprite. isModel = false; if(useModels) { // Is there a model for this frame? mobj_t dummy; // Setup a dummy for the call to R_CheckModelFor. dummy.state = psp->statePtr; dummy.tics = psp->tics; inter = R_CheckModelFor(&dummy, &mf, &nextmf); if(mf) isModel = true; } if(isModel) { // Yes, draw a 3D model (in Rend_Draw3DPlayerSprites). // There are 3D psprites. psp3d = true; spr->type = VPSPR_MODEL; spr->data.model.subsector = ddpl->mo->subsector; spr->data.model.flags = 0; // 32 is the raised weapon height. spr->data.model.gzt = viewData->current.pos[VZ]; spr->data.model.secFloor = ddpl->mo->subsector->sector->SP_floorvisheight; spr->data.model.secCeil = ddpl->mo->subsector->sector->SP_ceilvisheight; spr->data.model.pClass = 0; spr->data.model.floorClip = 0; spr->data.model.mf = mf; spr->data.model.nextMF = nextmf; spr->data.model.inter = inter; spr->data.model.viewAligned = true; spr->center[VX] = viewData->current.pos[VX]; spr->center[VY] = viewData->current.pos[VY]; spr->center[VZ] = viewData->current.pos[VZ]; // Offsets to rotation angles. spr->data.model.yawAngleOffset = psp->pos[VX] * weaponOffsetScale - 90; spr->data.model.pitchAngleOffset = (32 - psp->pos[VY]) * weaponOffsetScale * weaponOffsetScaleY / 1000.0f; // Is the FOV shift in effect? if(weaponFOVShift > 0 && fieldOfView > 90) spr->data.model.pitchAngleOffset -= weaponFOVShift * (fieldOfView - 90) / 90; // Real rotation angles. spr->data.model.yaw = viewData->current.angle / (float) ANGLE_MAX *-360 + spr->data.model.yawAngleOffset + 90; spr->data.model.pitch = viewData->current.pitch * 85 / 110 + spr->data.model.yawAngleOffset; memset(spr->data.model.visOff, 0, sizeof(spr->data.model.visOff)); spr->data.model.alpha = psp->alpha; spr->data.model.stateFullBright = (psp->flags & DDPSPF_FULLBRIGHT)!=0; } else { // No, draw a 2D sprite (in Rend_DrawPlayerSprites). spr->type = VPSPR_SPRITE; // Adjust the center slightly so an angle can be calculated. spr->center[VX] = viewData->current.pos[VX]; spr->center[VY] = viewData->current.pos[VY]; spr->center[VZ] = viewData->current.pos[VZ]; spr->data.sprite.subsector = ddpl->mo->subsector; spr->data.sprite.alpha = psp->alpha; spr->data.sprite.isFullBright = (psp->flags & DDPSPF_FULLBRIGHT)!=0; } } } float R_MovementYaw(float momx, float momy) { // Multiply by 100 to get some artificial accuracy in bamsAtan2. return BANG2DEG(bamsAtan2(-100 * momy, 100 * momx)); } float R_MovementPitch(float momx, float momy, float momz) { return BANG2DEG(bamsAtan2 (100 * momz, 100 * P_AccurateDistance(momx, momy))); } typedef struct { vissprite_t* vis; const mobj_t* mo; boolean floorAdjust; } vismobjzparams_t; /** * Determine the correct Z coordinate for the mobj. The visible Z coordinate * may be slightly different than the actual Z coordinate due to smoothed * plane movement. */ boolean RIT_VisMobjZ(sector_t* sector, void* data) { vismobjzparams_t* params; assert(sector != NULL); assert(data != NULL); params = (vismobjzparams_t*) data; if(params->floorAdjust && params->mo->pos[VZ] == sector->SP_floorheight) { params->vis->center[VZ] = sector->SP_floorvisheight; } if(params->mo->pos[VZ] + params->mo->height == sector->SP_ceilheight) { params->vis->center[VZ] = sector->SP_ceilvisheight - params->mo->height; } return true; } static void setupSpriteParamsForVisSprite(rendspriteparams_t *params, float x, float y, float z, float distance, float visOffX, float visOffY, float visOffZ, float secFloor, float secCeil, float floorClip, float top, material_t* mat, boolean matFlipS, boolean matFlipT, blendmode_t blendMode, float ambientColorR, float ambientColorG, float ambientColorB, float alpha, uint vLightListIdx, int transMap, int transClass, subsector_t* ssec, boolean floorAdjust, boolean fitTop, boolean fitBottom, boolean viewAligned, boolean brightShadow, boolean shadow, boolean altShadow, boolean fullBright) { spritetex_t* sprTex = NULL; material_snapshot_t ms; material_load_params_t mparams; if(!params) return; // Wha? memset(&mparams, 0, sizeof(mparams)); mparams.tmap = transMap; mparams.tclass = transClass; Material_Prepare(&ms, mat, true, &mparams); sprTex = spriteTextures[ms.units[MTU_PRIMARY].texInst->tex->ofTypeID]; params->width = ms.width; params->height = ms.height; params->center[VX] = x; params->center[VY] = y; params->center[VZ] = z; params->srvo[VX] = visOffX; params->srvo[VY] = visOffY; params->srvo[VZ] = visOffZ; params->distance = distance; params->viewOffX = (float) sprTex->offX - ms.width / 2.0f; params->subsector = ssec; params->viewAligned = viewAligned; params->noZWrite = noSpriteZWrite; params->mat = mat; params->tMap = transMap; params->tClass = transClass; params->matOffset[0] = ms.units[MTU_PRIMARY].texInst->data.sprite.texCoord[0]; params->matOffset[1] = ms.units[MTU_PRIMARY].texInst->data.sprite.texCoord[1]; params->matFlip[0] = matFlipS; params->matFlip[1] = matFlipT; params->blendMode = blendMode; params->ambientColor[CR] = ambientColorR; params->ambientColor[CG] = ambientColorG; params->ambientColor[CB] = ambientColorB; params->ambientColor[CA] = alpha; params->vLightListIdx = vLightListIdx; } void setupModelParamsForVisSprite(rendmodelparams_t *params, float x, float y, float z, float distance, float visOffX, float visOffY, float visOffZ, float gzt, float yaw, float yawAngleOffset, float pitch, float pitchAngleOffset, struct modeldef_s* mf, struct modeldef_s* nextMF, float inter, float ambientColorR, float ambientColorG, float ambientColorB, float alpha, uint vLightListIdx, int id, int selector, subsector_t* ssec, int mobjDDFlags, int tmap, boolean viewAlign, boolean fullBright, boolean alwaysInterpolate) { if(!params) return; // Hmm... params->mf = mf; params->nextMF = nextMF; params->inter = inter; params->alwaysInterpolate = alwaysInterpolate; params->id = id; params->selector = selector; params->flags = mobjDDFlags; params->tmap = tmap; params->center[VX] = x; params->center[VY] = y; params->center[VZ] = z; params->srvo[VX] = visOffX; params->srvo[VY] = visOffY; params->srvo[VZ] = visOffZ; params->gzt = gzt; params->distance = distance; params->yaw = yaw; params->extraYawAngle = 0; params->yawAngleOffset = yawAngleOffset; params->pitch = pitch; params->extraPitchAngle = 0; params->pitchAngleOffset = pitchAngleOffset; params->extraScale = 0; params->viewAlign = viewAlign; params->mirror = 0; params->shineYawOffset = 0; params->shinePitchOffset = 0; params->shineTranslateWithViewerPos = false; params->shinepspriteCoordSpace = false; params->ambientColor[CR] = ambientColorR; params->ambientColor[CG] = ambientColorG; params->ambientColor[CB] = ambientColorB; params->ambientColor[CA] = alpha; params->vLightListIdx = vLightListIdx; } void getLightingParams(float x, float y, float z, subsector_t* ssec, float distance, boolean fullBright, float ambientColor[3], uint* vLightListIdx) { if(fullBright) { ambientColor[CR] = ambientColor[CG] = ambientColor[CB] = 1; *vLightListIdx = 0; } else { collectaffectinglights_params_t lparams; if(useBias) { vec3_t point; // Evaluate the position in the light grid. V3_Set(point, x, y, z); LG_Evaluate(point, ambientColor); } else { float lightLevel = ssec->sector->lightLevel; const float* secColor = R_GetSectorLightColor(ssec->sector); /* if(spr->type == VSPR_DECORATION) { // Wall decorations receive an additional light delta. lightLevel += R_WallAngleLightLevelDelta(linedef, side); } */ // Apply distance attenuation. lightLevel = R_DistAttenuateLightLevel(distance, lightLevel); // Add extra light. lightLevel += R_ExtraLightDelta(); Rend_ApplyLightAdaptation(&lightLevel); // Determine the final ambientColor in affect. ambientColor[CR] = lightLevel * secColor[CR]; ambientColor[CG] = lightLevel * secColor[CG]; ambientColor[CB] = lightLevel * secColor[CB]; } Rend_ApplyTorchLight(ambientColor, distance); lparams.starkLight = false; lparams.center[VX] = x; lparams.center[VY] = y; lparams.center[VZ] = z; lparams.subsector = ssec; lparams.ambientColor = ambientColor; *vLightListIdx = R_CollectAffectingLights(&lparams); } } /** * Generates a vissprite for a mobj if it might be visible. */ void R_ProjectSprite(mobj_t* mo) { sector_t* sect = mo->subsector->sector; float thangle = 0, alpha, floorClip, secFloor, secCeil; float pos[2], yaw, pitch; vec3_t visOff; spritedef_t* sprDef; spriteframe_t* sprFrame = NULL; int i, tmap = 0, tclass = 0; unsigned rot; boolean matFlipS, matFlipT; vissprite_t* vis; angle_t ang; boolean align, fullBright, viewAlign, floorAdjust; modeldef_t* mf = NULL, *nextmf = NULL; float interp = 0, distance, gzt; spritetex_t* sprTex; vismobjzparams_t params; visspritetype_t visType = VSPR_SPRITE; float ambientColor[3]; uint vLightListIdx = 0; material_t* mat; material_snapshot_t ms; material_load_params_t mparams; const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); if(mo->ddFlags & DDMF_DONTDRAW || mo->translucency == 0xff || mo->state == NULL || mo->state == states) { // Never make a vissprite when DDMF_DONTDRAW is set or when // the mo is fully transparent, or when the mo hasn't got // a valid state. return; } if(sect->SP_floorvisheight >= sect->SP_ceilvisheight) { // Never make a vissprite when the mobj's origin sector is of zero height. return; } // Transform the origin point. pos[VX] = mo->pos[VX] - viewData->current.pos[VX]; pos[VY] = mo->pos[VY] - viewData->current.pos[VY]; // Decide which patch to use for sprite relative to player. #ifdef RANGECHECK if((unsigned) mo->sprite >= (unsigned) numSprites) { Con_Error("R_ProjectSprite: invalid sprite number %i\n", mo->sprite); } #endif sprDef = &sprites[mo->sprite]; if(mo->frame >= sprDef->numFrames) { // The frame is not defined, we can't display this object. return; } sprFrame = &sprDef->spriteFrames[mo->frame]; // Determine distance to object. distance = Rend_PointDist2D(mo->pos); // Check for a 3D model. if(useModels) { interp = R_CheckModelFor(mo, &mf, &nextmf); if(mf && !(mf->flags & MFF_NO_DISTANCE_CHECK) && maxModelDistance && distance > maxModelDistance) { // Don't use a 3D model. mf = nextmf = NULL; interp = -1; } } if(sprFrame->rotate && !mf) { // Choose a different rotation based on player view. ang = R_PointToAngle(mo->pos[VX], mo->pos[VY]); rot = (ang - mo->angle + (unsigned) (ANG45 / 2) * 9) >> 29; mat = sprFrame->mats[rot]; matFlipS = (boolean) sprFrame->flip[rot]; } else { // Use single rotation for all views. mat = sprFrame->mats[0]; matFlipS = (boolean) sprFrame->flip[0]; } matFlipT = false; tmap = mo->tmap; tclass = mo->tclass; memset(&mparams, 0, sizeof(mparams)); mparams.tmap = tmap; mparams.tclass = tclass; Material_Prepare(&ms, mat, true, &mparams); sprTex = spriteTextures[ms.units[MTU_PRIMARY].texInst->tex->ofTypeID]; // Align to the view plane? if(mo->ddFlags & DDMF_VIEWALIGN) align = true; else align = false; if(alwaysAlign == 1) align = true; // Perform visibility checking. { float center[2], v1[2], v2[2]; float width = R_VisualRadius(mo)*2, offset = 0; if(!mf) offset = (float) sprTex->offX - (width / 2); // Project a line segment relative to the view in 2D, then check // if not entirely clipped away in the 360 degree angle clipper. center[VX] = mo->pos[VX]; center[VY] = mo->pos[VY]; M_ProjectViewRelativeLine2D(center, mf || (align || alwaysAlign == 3), width, offset, v1, v2); // Check for visibility. if(!C_CheckViewRelSeg(v1[VX], v1[VY], v2[VX], v2[VY])) { // Isn't visible. if(mf) { // If the model is close to the viewpoint we will need to // draw it. Otherwise large models are likely to disappear // too early. if(P_ApproxDistance (distance, mo->pos[VZ] + (mo->height / 2) - viewData->current.pos[VZ]) > MAX_OBJECT_RADIUS) { return; // Can't be visible. } } else { return; } } } if(!mf) { visType = mf? VSPR_MODEL : VSPR_SPRITE; } else { // Its a model. visType = VSPR_MODEL; thangle = BANG2RAD(bamsAtan2(pos[VY] * 10, pos[VX] * 10)) - PI / 2; // Viewaligning means scaling down Z with models. align = false; } // Store information in a vissprite. vis = R_NewVisSprite(); vis->type = visType; vis->center[VX] = mo->pos[VX]; vis->center[VY] = mo->pos[VY]; vis->center[VZ] = mo->pos[VZ]; vis->distance = distance; floorAdjust = (fabs(sect->SP_floorvisheight - sect->SP_floorheight) < 8); /** * The mobj's Z coordinate must match the actual visible floor/ceiling * height. When using smoothing, this requires iterating through the * sectors (planes) in the vicinity. */ validCount++; params.vis = vis; params.mo = mo; params.floorAdjust = floorAdjust; P_MobjSectorsIterator(mo, RIT_VisMobjZ, ¶ms); gzt = vis->center[VZ] + ((float) sprTex->offY); viewAlign = (align || alwaysAlign == 3)? true : false; fullBright = ((mo->state->flags & STF_FULLBRIGHT) || levelFullBright)? true : false; secFloor = mo->subsector->sector->SP_floorvisheight; secCeil = mo->subsector->sector->SP_ceilvisheight; // Foot clipping. floorClip = mo->floorClip; if(mo->ddFlags & DDMF_BOB) { // Bobbing is applied to the floorclip. floorClip += R_GetBobOffset(mo); } if(mf) { // Determine the rotation angles (in degrees). if(mf->sub[0].flags & MFF_ALIGN_YAW) { yaw = 90 - thangle / PI * 180; } else if(mf->sub[0].flags & MFF_SPIN) { yaw = modelSpinSpeed * 70 * ddMapTime + MOBJ_TO_ID(mo) % 360; } else if(mf->sub[0].flags & MFF_MOVEMENT_YAW) { yaw = R_MovementYaw(mo->mom[MX], mo->mom[MY]); } else { if(useSRVOAngle && !netGame && !playback) yaw = (mo->visAngle << 16) / (float) ANGLE_MAX * -360; else yaw = mo->angle / (float) ANGLE_MAX * -360; } // How about a unique offset? if(mf->sub[0].flags & MFF_IDANGLE) { // Multiply with an arbitrary factor. yaw += MOBJ_TO_ID(mo) % 360; } if(mf->sub[0].flags & MFF_ALIGN_PITCH) { pitch = -BANG2DEG(bamsAtan2 (((vis->center[VZ] + gzt) / 2 - viewData->current.pos[VZ]) * 10, distance * 10)); } else if(mf->sub[0].flags & MFF_MOVEMENT_PITCH) { pitch = R_MovementPitch(mo->mom[MX], mo->mom[MY], mo->mom[MZ]); } else pitch = 0; } /** * The three highest bits of the selector are used for an alpha level. * 0 = opaque (alpha -1) * 1 = 1/8 transparent * 4 = 1/2 transparent * 7 = 7/8 transparent */ i = mo->selector >> DDMOBJ_SELECTOR_SHIFT; if(i & 0xe0) { alpha = 1 - ((i & 0xe0) >> 5) / 8.0f; } else { if(mo->translucency) alpha = 1 - mo->translucency * reciprocal255; else alpha = -1; } // Determine possible short-range visual offset. V3_Set(visOff, 0, 0, 0); if((mf && useSRVO > 0) || (!mf && useSRVO > 1)) { if(mo->state && mo->tics >= 0) { V3_Set(visOff, mo->srvo[VX], mo->srvo[VY], mo->srvo[VZ]); V3_Scale(visOff, (mo->tics - frameTimePos) / (float) mo->state->tics); } if(!INRANGE_OF(mo->mom[MX], 0, NOMOMENTUM_THRESHOLD) || !INRANGE_OF(mo->mom[MY], 0, NOMOMENTUM_THRESHOLD) || !INRANGE_OF(mo->mom[MZ], 0, NOMOMENTUM_THRESHOLD)) { vec3_t tmp; // Use the object's speed to calculate a short-range offset. V3_Set(tmp, mo->mom[MX], mo->mom[MY], mo->mom[MZ]); V3_Scale(tmp, frameTimePos); V3_Sum(visOff, visOff, tmp); } } if(!mf && mat) { boolean brightShadow = (mo->ddFlags & DDMF_BRIGHTSHADOW)? true : false; boolean shadow = (mo->ddFlags & DDMF_SHADOW)? true : false; boolean altShadow = (mo->ddFlags & DDMF_ALTSHADOW)? true : false; boolean fitTop = (mo->ddFlags & DDMF_FITTOP)? true : false; boolean fitBottom = (mo->ddFlags & DDMF_NOFITBOTTOM)? false : true; float finalAlpha; blendmode_t blendMode; if(useSpriteAlpha) { if(missileBlend && brightShadow) finalAlpha = .8f; // 80 %. else if(shadow) finalAlpha = .333f; // One third. else if(altShadow) finalAlpha = .666f; // Two thirds. else finalAlpha = 1; // Sprite has a custom alpha multiplier? if(alpha >= 0) finalAlpha *= alpha; } else finalAlpha = 1; if(missileBlend && brightShadow) { // Additive blending. blendMode = BM_ADD; } else if(noSpriteTrans && finalAlpha >= .98f) { // Use the "no translucency" blending mode. blendMode = BM_ZEROALPHA; } else { blendMode = BM_NORMAL; } // We must find the correct positioning using the sector floor // and ceiling heights as an aid. if(ms.height < secCeil - secFloor) { // Sprite fits in, adjustment possible? // Check top. if(fitTop && gzt > secCeil) gzt = secCeil; // Check bottom. if(floorAdjust && fitBottom && gzt - ms.height < secFloor) gzt = secFloor + ms.height; } // Adjust by the floor clip. gzt -= floorClip; getLightingParams(vis->center[VX], vis->center[VY], gzt - ms.height / 2.0f, mo->subsector, vis->distance, fullBright, ambientColor, &vLightListIdx); setupSpriteParamsForVisSprite(&vis->data.sprite, vis->center[VX], vis->center[VY], gzt - ms.height / 2.0f, vis->distance, visOff[VX], visOff[VY], visOff[VZ], secFloor, secCeil, floorClip, gzt, mat, matFlipS, matFlipT, blendMode, ambientColor[CR], ambientColor[CG], ambientColor[CB], finalAlpha, vLightListIdx, tmap, tclass, mo->subsector, floorAdjust, fitTop, fitBottom, viewAlign, brightShadow, shadow, altShadow, fullBright); } else { getLightingParams(vis->center[VX], vis->center[VY], vis->center[VZ], mo->subsector, vis->distance, fullBright, ambientColor, &vLightListIdx); setupModelParamsForVisSprite(&vis->data.model, vis->center[VX], vis->center[VY], vis->center[VZ], vis->distance, visOff[VX], visOff[VY], visOff[VZ] - floorClip, gzt, yaw, 0, pitch, 0, mf, nextmf, interp, ambientColor[CR], ambientColor[CG], ambientColor[CB], alpha, vLightListIdx, mo->thinker.id, mo->selector, mo->subsector, mo->ddFlags, mo->tmap, viewAlign, fullBright && !(mf && (mf->sub[0].flags & MFF_DIM)), false); } // Do we need to project a flare source too? if(mo->lumIdx) { const lumobj_t* lum; const ded_light_t* def; float flareSize, xOffset; spritedef_t* sprDef; spriteframe_t* sprFrame; material_t* mat; material_snapshot_t ms; const gltexture_inst_t* texInst; // Determine the sprite frame lump of the source. sprDef = &sprites[mo->sprite]; sprFrame = &sprDef->spriteFrames[mo->frame]; if(sprFrame->rotate) { mat = sprFrame-> mats[(R_PointToAngle(mo->pos[VX], mo->pos[VY]) - mo->angle + (unsigned) (ANG45 / 2) * 9) >> 29]; } else { mat = sprFrame->mats[0]; } #if _DEBUG if(!mat) Con_Error("R_ProjectSprite: Sprite '%i' frame '%i' missing material.", (int) mo->sprite, mo->frame); #endif // Ensure we have up-to-date information about the material. Material_Prepare(&ms, mat, true, NULL); if(ms.units[MTU_PRIMARY].texInst->tex->type != GLT_SPRITE) return; // *Very* strange... texInst = ms.units[MTU_PRIMARY].texInst; lum = LO_GetLuminous(mo->lumIdx); def = (mo->state? stateLights[mo->state - states] : 0); vis = R_NewVisSprite(); vis->type = VSPR_FLARE; vis->distance = distance; // Determine the exact center of the flare. V3_Sum(vis->center, mo->pos, visOff); vis->center[VZ] += LUM_OMNI(lum)->zOff; flareSize = texInst->data.sprite.lumSize; // X offset to the flare position. xOffset = (texInst->data.sprite.flareX - (float) ms.width / 2) - (spriteTextures[texInst->tex->ofTypeID]->offX - (float) ms.width / 2); // Does the mobj have an active light definition? if(def) { if(def->size) flareSize = def->size; if(def->haloRadius) flareSize = def->haloRadius; if(def->offset[VX]) xOffset = def->offset[VX]; vis->data.flare.flags = def->flags; } vis->data.flare.size = flareSize * 60 * (50 + haloSize) / 100.0f; if(vis->data.flare.size < 8) vis->data.flare.size = 8; // Color is taken from the associated lumobj. V3_Copy(vis->data.flare.color, LUM_OMNI(lum)->color); vis->data.flare.factor = mo->haloFactors[viewPlayer - ddPlayers]; vis->data.flare.xOff = xOffset; vis->data.flare.mul = 1; if(def) { if(!(def->flare.id && def->flare.id[0] == '-')) { vis->data.flare.tex = GL_GetFlareTexture(def->flare.id, -1); } else { vis->data.flare.flags |= RFF_NO_PRIMARY; vis->data.flare.tex = 0; } } } } typedef struct { subsector_t* ssec; } addspriteparams_t; boolean RIT_AddSprite(void* ptr, void* data) { mobj_t* mo = (mobj_t*) ptr; addspriteparams_t* params = (addspriteparams_t*) data; sector_t* sec = params->ssec->sector; if(mo->addFrameCount != frameCount) { material_t* mat; R_ProjectSprite(mo); // Hack: Sprites have a tendency to extend into the ceiling in // sky sectors. Here we will raise the skyfix dynamically, to make sure // that no sprites get clipped by the sky. // Only check if((mat = R_GetMaterialForSprite(mo->sprite, mo->frame)) && R_IsSkySurface(&sec->SP_ceilsurface)) { if(!(mo->dPlayer && mo->dPlayer->flags & DDPF_CAMERA) && // Cameramen don't exist! mo->pos[VZ] <= sec->SP_ceilheight && mo->pos[VZ] >= sec->SP_floorheight) { float visibleTop; visibleTop = mo->pos[VZ] + mat->height; if(visibleTop > skyFix[PLN_CEILING].height) { // Raise skyfix ceiling. skyFix[PLN_CEILING].height = visibleTop + 16; // Add some leeway. } } } mo->addFrameCount = frameCount; } return true; // Continue iteration. } void R_AddSprites(subsector_t* ssec) { addspriteparams_t params; // Don't use validCount, because other parts of the renderer may // change it. if(ssec->addSpriteCount == frameCount) return; // Already added. params.ssec = ssec; R_IterateSubsectorContacts(ssec, OT_MOBJ, RIT_AddSprite, ¶ms); ssec->addSpriteCount = frameCount; } void R_SortVisSprites(void) { int i, count; vissprite_t* ds, *best = 0; vissprite_t unsorted; float bestdist; count = visSpriteP - visSprites; unsorted.next = unsorted.prev = &unsorted; if(!count) return; for(ds = visSprites; ds < visSpriteP; ds++) { ds->next = ds + 1; ds->prev = ds - 1; } visSprites[0].prev = &unsorted; unsorted.next = &visSprites[0]; (visSpriteP - 1)->next = &unsorted; unsorted.prev = visSpriteP - 1; // Pull the vissprites out by distance. visSprSortedHead.next = visSprSortedHead.prev = &visSprSortedHead; /** * \todo * Oprofile results from nuts.wad show over 25% of total execution time * was spent sorting vissprites (nuts.wad map01 is a perfect * pathological test case). * * Rather than try to speed up the sort, it would make more sense to * actually construct the vissprites in z order if it can be done in * linear time. */ for(i = 0; i < count; ++i) { bestdist = 0; for(ds = unsorted.next; ds != &unsorted; ds = ds->next) { if(ds->distance >= bestdist) { bestdist = ds->distance; best = ds; } } best->next->prev = best->prev; best->prev->next = best->next; best->next = &visSprSortedHead; best->prev = visSprSortedHead.prev; visSprSortedHead.prev->next = best; visSprSortedHead.prev = best; } } static void scaleFloatRGB(float* out, const float* in, float mul) { memset(out, 0, sizeof(float) * 3); R_ScaleAmbientRGB(out, in, mul); } /** * Iterator for processing light sources around a vissprite. */ boolean visSpriteLightIterator(const lumobj_t* lum, float xyDist, void* data) { float dist; float intensity; boolean addLight = false; vlightiterparams_t* params = (vlightiterparams_t*) data; if(!(lum->type == LT_OMNI || lum->type == LT_PLANE)) return true; // Continue iteration. // Is the light close enough to make the list? switch(lum->type) { case LT_OMNI: { float zDist; zDist = params->pos[VZ] - lum->pos[VZ] + LUM_OMNI(lum)->zOff; dist = P_ApproxDistance(xyDist, zDist); if(dist < (float) loMaxRadius) { // The intensity of the light. intensity = MINMAX_OF(0, (1 - dist / LUM_OMNI(lum)->radius) * 2, 1); if(intensity > .05f) addLight = true; } break; } case LT_PLANE: if(LUM_PLANE(lum)->intensity && (LUM_PLANE(lum)->color[0] > 0 || LUM_PLANE(lum)->color[1] > 0 || LUM_PLANE(lum)->color[2] > 0)) { float glowHeight = (MAX_GLOWHEIGHT * LUM_PLANE(lum)->intensity) * glowHeightFactor; // Don't make too small or too large glows. if(glowHeight > 2) { float delta[3]; if(glowHeight > glowHeightMax) glowHeight = glowHeightMax; delta[VX] = params->pos[VX] - lum->pos[VX]; delta[VY] = params->pos[VY] - lum->pos[VY]; delta[VZ] = params->pos[VZ] - lum->pos[VZ]; if(!((dist = M_DotProduct(delta, LUM_PLANE(lum)->normal)) < 0)) { // Is on the front of the glow plane. addLight = true; intensity = 1 - dist / glowHeight; } } } break; default: Con_Error("visSpriteLightIterator: Invalid value, lum->type = %i.", (int) lum->type); break; } // If the light is not close enough, skip it. if(addLight) { vlightnode_t* node = NULL; node = newVLight(); if(node) { vlight_t* vlight = &node->vlight; switch(lum->type) { case LT_OMNI: vlight->affectedByAmbient = true; vlight->approxDist = dist; vlight->lightSide = 1; vlight->darkSide = 0; vlight->offset = 0; // Calculate the normalized direction vector, pointing out of // the light origin. vlight->vector[VX] = (lum->pos[VX] - params->pos[VX]) / dist; vlight->vector[VY] = (lum->pos[VY] - params->pos[VY]) / dist; vlight->vector[VZ] = (lum->pos[VZ] + LUM_OMNI(lum)->zOff - params->pos[VZ]) / dist; vlight->color[CR] = LUM_OMNI(lum)->color[CR] * intensity; vlight->color[CG] = LUM_OMNI(lum)->color[CG] * intensity; vlight->color[CB] = LUM_OMNI(lum)->color[CB] * intensity; break; case LT_PLANE: vlight->affectedByAmbient = true; vlight->approxDist = dist; vlight->lightSide = 1; vlight->darkSide = 0; vlight->offset = .3f; /** * Calculate the normalized direction vector, pointing out of * the vissprite. * \fixme Project the nearest point on the surface to * determine the real direction vector. */ vlight->vector[VX] = LUM_PLANE(lum)->normal[VX]; vlight->vector[VY] = LUM_PLANE(lum)->normal[VY]; vlight->vector[VZ] = -LUM_PLANE(lum)->normal[VZ]; vlight->color[CR] = LUM_PLANE(lum)->color[CR] * intensity; vlight->color[CG] = LUM_PLANE(lum)->color[CG] * intensity; vlight->color[CB] = LUM_PLANE(lum)->color[CB] * intensity; break; default: Con_Error("visSpriteLightIterator: Invalid value, " "lum->type = %i.", (int) lum->type); break; } linkVLightNodeToList(node, params->listIdx); } } return true; // Continue iteration. } uint R_CollectAffectingLights(const collectaffectinglights_params_t* params) { uint vLightListIdx; uint i; vlightnode_t* node; vlight_t* vlight; if(!params) return 0; // Determine the lighting properties that affect this vissprite. vLightListIdx = 0; node = newVLight(); vlight = &node->vlight; // Should always be lit with world light. vlight->affectedByAmbient = false; vlight->approxDist = 0; for(i = 0; i < 3; ++i) { vlight->vector[i] = worldLight[i]; vlight->color[i] = params->ambientColor[i]; } if(params->starkLight) { vlight->lightSide = .35f; vlight->darkSide = .5f; vlight->offset = 0; } else { /** * World light can both light and shade. Normal objects get * more shade than light (to prevent them from becoming too * bright when compared to ambient light). */ vlight->lightSide = .2f; vlight->darkSide = .8f; vlight->offset = .3f; } vLightListIdx = newVLightList(true); // Sort by distance. linkVLightNodeToList(node, vLightListIdx); // Add extra light by interpreting lumobjs into vlights. if(loInited && params->subsector) { vlightiterparams_t vars; vars.pos[VX] = params->center[VX]; vars.pos[VY] = params->center[VY]; vars.pos[VZ] = params->center[VZ]; vars.haveList = true; vars.listIdx = vLightListIdx; LO_LumobjsRadiusIterator(params->subsector, params->center[VX], params->center[VY], (float) loMaxRadius, &vars, visSpriteLightIterator); } return vLightListIdx + 1; } /** * Calls func for all vlights in the given list. * * @param listIdx Identifier of the list to process. * @param data Ptr to pass to the callback. * @param func Callback to make for each object. * * @return @c true, iff every callback returns @c true. */ boolean VL_ListIterator(uint listIdx, void* data, boolean (*func) (const vlight_t*, void*)) { vlightnode_t* node; boolean retVal, isDone; if(listIdx == 0 || listIdx > numVLightLinkLists) return true; listIdx--; node = vLightLinkLists[listIdx].head; retVal = true; isDone = false; while(node && !isDone) { if(!func(&node->vlight, data)) { retVal = false; isDone = true; } else node = node->next; } return retVal; } /** * @return The current floatbob offset for the mobj, if the mobj * is flagged for bobbing, else @c 0. */ float R_GetBobOffset(mobj_t* mo) { if(mo->ddFlags & DDMF_BOB) { return (sin(MOBJ_TO_ID(mo) + ddMapTime / 1.8286 * 2 * PI) * 8); } return 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/ui_main.c0000644000175000017500000021446311357170242022530 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * ui_main.c: Graphical User Interface * * Has ties to the console routines. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_refresh.h" #include "de_system.h" #include "de_graphics.h" #include "de_ui.h" #include "de_misc.h" #include "rend_console.h" // \todo Move Con_InitUI somewhere more suitable. // MACROS ------------------------------------------------------------------ #define SCROLL_TIME 3 #define UICURSORWIDTH 32 #define UICURSORHEIGHT 64 enum { UITEX_MOUSE, UITEX_CORNER, UITEX_FILL, UITEX_SHADE, UITEX_HINT, UITEX_LOGO, UITEX_BACKGROUND, NUM_UITEXTURES }; // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(UIColor); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- int UI_ListItemHeight(uidata_list_t *listdata); int UI_ListButtonHeight(ui_object_t *ob); int UI_ListThumbPos(ui_object_t *ob); void UI_StrCpyLen(char *dest, char *src, int maxWidth); int UI_MouseInsideBox(int x, int y, int w, int h); void UI_MouseFocus(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int glMaxTexSize; extern int gameDrawHUD; extern boolean stopTime; extern boolean tickUI; extern boolean drawGame; // extern boolean dialogActive; // extern boolean dialogInput; // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean uiActive = false; // The user interface is active. static boolean uiShowMouse = true; static ui_page_t *uiCurrentPage = 0; // Currently active page. static int uiFontHgt; // Height of the UI font. static DGLuint uiTextures[NUM_UITEXTURES]; // Cursor texture. static int uiCX, uiCY; // Cursor position. static int uiRestCX, uiRestCY; static int uiRestStart; // Start time of current resting. static int uiRestTime = TICSPERSEC / 2; // 500 ms. static int uiRestOffsetLimit = 2; static int uiMoved; // True if the mouse has been moved. static float uiAlpha = 1.0; // Main alpha for the entire UI. static float uiTargetAlpha = 1.0; // Target alpha for the entire UI. static boolean uiDrawGame = false; // The game view should be drawn while // the UI active. static float uiCursorWidthMul = 0.75; static float uiCursorHeightMul = 0.75; // Modify these colors to change the look of the UI. static ui_color_t ui_colors[NUM_UI_COLORS] = { /* UIC_TEXT */ {.85f, .87f, 1}, /* UIC_TITLE */ {1, 1, 1}, /* UIC_SHADOW */ {0, 0, 0}, /* UIC_BG_LIGHT */ {.18f, .18f, .22f}, /* UIC_BG_MEDIUM */ {.4f, .4f, .52f}, /* UIC_BG_DARK */ {.28f, .28f, .33f}, /* UIC_BRD_HI */ {1, 1, 1}, /* UIC_BRD_MED */ {0, 0, 0}, /* UIC_BRD_LOW */ {.25f, .25f, .55f}, /* UIC_HELP */ {.4f, .4f, .52f} }; static boolean allowEscape; // Allow the user to exit a ui page using the escape key // CODE -------------------------------------------------------------------- void UI_Register(void) { // Cvars C_VAR_FLOAT("ui-cursor-width", &uiCursorWidthMul, 0, 0.5f, 1.5f); C_VAR_FLOAT("ui-cursor-height", &uiCursorHeightMul, 0, 0.5f, 1.5f); // Ccmds C_CMD_FLAGS("uicolor", "sfff", UIColor, CMDF_NO_DEDICATED); CP_Register(); } /** * Called when entering a ui page */ void UI_Init(boolean halttime, boolean tckui, boolean tckframe, boolean drwgame, boolean noescape) { if(uiActive) return; uiActive = true; B_ActivateContext(B_ContextByName(UI_BINDING_CONTEXT_NAME), true); // Restore full alpha. uiAlpha = uiTargetAlpha = 1.0; // Adjust the engine state stopTime = halttime; tickUI = tckui; tickFrame = tckframe; uiDrawGame = drawGame = drwgame; // Advise the game not to draw any HUD displays gameDrawHUD = false; I_SetUIMouseMode(true); // Change font. FR_SetFont(glFontVariable[GLFS_NORMAL]); uiFontHgt = FR_TextHeight("W"); // Should the mouse cursor be visible? uiShowMouse = !ArgExists("-nomouse"); // Allow use of the escape key to exit the ui? allowEscape = !noescape; // Init cursor to the center of the screen. uiCX = theWindow->width / 2; uiCY = theWindow->height / 2; uiMoved = false; } /** * Called upon exiting a ui page */ void UI_End(void) { ddevent_t rel; if(!uiActive) return; uiActive = false; B_ActivateContext(B_ContextByName(UI_BINDING_CONTEXT_NAME), false); // Restore full alpha. uiAlpha = uiTargetAlpha = 1.0; FR_SetFont(glFontFixed); // Update the secondary title and the game status. Con_InitUI(); // Restore the engine state tickFrame = true; stopTime = false; tickUI = false; drawGame = true; // Advise the game it can now draw HUD displays again. gameDrawHUD = true; I_SetUIMouseMode(false); // Inform everybody that the shift key was (possibly) released while // the UI was eating all the input events. if(!shiftDown) { rel.device = IDEV_KEYBOARD; rel.type = E_TOGGLE; rel.toggle.state = ETOG_UP; rel.toggle.id = DDKEY_RSHIFT; DD_PostEvent(&rel); } } /** * @return @c true, if the UI is currently active. */ boolean UI_IsActive(void) { return uiActive; } /** * @return Height of the current UI font. */ int UI_FontHeight(void) { return uiFontHgt; } /** * @param id Id number of the color to return e.g. "UIC_TEXT". */ ui_color_t *UI_Color(uint id) { if(id >= NUM_UI_COLORS) return NULL; return &ui_colors[id]; } /** * Set the alpha level of the entire UI. Alpha levels below one automatically * show the game view in addition to the UI. * * @param alpha Alpha level to set the UI too (0...1) */ void UI_SetAlpha(float alpha) { // The UI's alpha will start moving towards this target value. uiTargetAlpha = alpha; } /** * @return Current alpha level of the UI. */ float UI_Alpha(void) { return uiAlpha; } /** * @return Ptr to the current UI page if active. */ ui_page_t *UI_CurrentPage(void) { if(uiActive) return uiCurrentPage; return NULL; } /** * Called from GL_LoadSystemTextures. */ void UI_LoadTextures(void) { int i; const char* picNames[NUM_UITEXTURES] = { "Mouse", "BoxCorner", "BoxFill", "BoxShade", "Hint", "Logo", "Background", }; for(i = 0; i < NUM_UITEXTURES; ++i) if(!uiTextures[i]) { image_t image; if(GL_LoadExtTexture(&image, DDRC_GRAPHICS, picNames[i], (i == UITEX_BACKGROUND? LGM_GRAYSCALE : LGM_NORMAL))) { // Loaded successfully and converted accordingly. // Upload the image to GL. uiTextures[i] = GL_NewTextureWithParams2( ( image.pixelSize == 2 ? DGL_LUMINANCE_PLUS_A8 : image.pixelSize == 3 ? DGL_RGB : image.pixelSize == 4 ? DGL_RGBA : DGL_LUMINANCE ), image.width, image.height, image.pixels, TXCF_NO_COMPRESSION, GL_LINEAR, GL_LINEAR, 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); GL_DestroyImage(&image); } else uiTextures[i] = 0; } } void UI_ClearTextures(void) { glDeleteTextures(NUM_UITEXTURES, (const GLuint*) uiTextures); memset(uiTextures, 0, sizeof(uiTextures)); } /** * Sets focus to the object that should get focus by default. */ void UI_DefaultFocus(ui_page_t *page) { ui_object_t *deffocus = NULL; int i; for(i = 0; i < page->count; ++i) { page->objects[i].flags &= ~UIF_FOCUS; if(page->objects[i].flags & UIF_DEFAULT) deffocus = page->objects + i; } if(deffocus) { page->focus = deffocus - page->objects; deffocus->flags |= UIF_FOCUS; } else { // Find an object for focus. for(i = 0; i < page->count; ++i) { if(!(page->objects[i].flags & UIF_NO_FOCUS)) { // Set default focus. page->focus = i; page->objects[i].flags |= UIF_FOCUS; break; } } } } /** * Initialises ui page data prior to use */ void UI_InitPage(ui_page_t *page, ui_object_t *objects) { int i; ui_object_t meta; memset(&meta, 0, sizeof(meta)); memset(page, 0, sizeof(*page)); page->objects = objects; page->capture = -1; // No capture. page->focus = -1; page->responder = UIPage_Responder; page->drawer = UIPage_Drawer; page->background = true; // render background by default page->header = true; // render header by default page->ticker = UIPage_Ticker; page->count = UI_CountObjects(objects); for(i = 0; i < page->count; ++i) { if(objects[i].type == UI_TEXT || objects[i].type == UI_BOX || objects[i].type == UI_META) { objects[i].flags |= UIF_NO_FOCUS; } // Reset timer. objects[i].timer = 0; } UI_DefaultFocus(page); // Meta effects. for(i = 0, meta.type = 0; i < page->count; ++i) { if(!meta.type && objects[i].type != UI_META) continue; if(objects[i].type == UI_META) { // This will be the meta for now. memcpy(&meta, objects + i, sizeof(meta)); // Neutralize the actual object. objects[i].group = UIG_NONE; objects[i].flags |= UIF_HIDDEN; objects[i].relx = objects[i].rely = 0; objects[i].relw = objects[i].relh = 0; continue; } // Apply the meta. if(meta.group != UIG_NONE) objects[i].group = meta.group; objects[i].relx += meta.relx; objects[i].rely += meta.rely; objects[i].relw += meta.relw; objects[i].relh += meta.relh; } } /** * The width of the available page area, in pixels. */ int UI_AvailableWidth(void) { return theWindow->width - UI_BORDER * 4; } int UI_AvailableHeight(void) { return theWindow->height - UI_BORDER * 4; } /** * Convert a relative coordinate to a screen coordinate. */ int UI_ScreenX(int relx) { return UI_BORDER * 2 + ((relx / UI_WIDTH) * UI_AvailableWidth()); } /** * Convert a relative coordinate to a screen coordinate. */ int UI_ScreenY(int rely) { return UI_BORDER * 2 + ((rely / UI_HEIGHT) * UI_AvailableHeight()); } int UI_ScreenW(int relw) { return (relw / UI_WIDTH) * UI_AvailableWidth(); } int UI_ScreenH(int relh) { return (relh / UI_HEIGHT) * UI_AvailableHeight(); } /** * Change and prepare the active page. */ void UI_SetPage(ui_page_t *page) { int i; ui_object_t *ob; uiCurrentPage = page; if(!page) return; // Init objects. for(i = 0, ob = page->objects; i < page->count; ++i, ob++) { // Calculate real coordinates. ob->x = UI_ScreenX(ob->relx); ob->w = UI_ScreenW(ob->relw); ob->y = UI_ScreenY(ob->rely); ob->h = UI_ScreenH(ob->relh); // Update objects on page if(ob->type == UI_EDIT) { // Update edit box text. memset(ob->text, 0, sizeof(ob->text)); strncpy(ob->text, ((uidata_edit_t *) ob->data)->ptr, 255); } else if(ob->type == UI_BUTTON2) { // Stay-down button state. if(*(char *) ob->data) ob->flags |= UIF_ACTIVE; else ob->flags &= ~UIF_ACTIVE; } else if(ob->type == UI_BUTTON2EX) { // Stay-down button state, with extended data. if(*(char *) ((uidata_button_t *)ob->data)->data) ob->flags |= UIF_ACTIVE; else ob->flags &= ~UIF_ACTIVE; } else if(ob->type == UI_LIST) { // List box number of visible items. uidata_list_t *dat = ob->data; dat->numvis = (ob->h - 2 * UI_BORDER) / UI_ListItemHeight(dat); if(dat->selection >= 0) { if(dat->selection < dat->first) dat->first = dat->selection; if(dat->selection > dat->first + dat->numvis - 1) dat->first = dat->selection - dat->numvis + 1; } UI_InitColumns(ob); } } // The mouse has not yet been moved on this page. uiMoved = false; } /** * Directs events through the ui and current page if active */ int UI_Responder(ddevent_t *ev) { if(!uiActive) return false; if(!uiCurrentPage) return false; if(IS_MOUSE_MOTION(ev)) { uiMoved = true; if(ev->axis.id == 0) // xaxis. { uiCX += ev->axis.pos; if(uiCX < 0) uiCX = 0; if(uiCX >= theWindow->width) uiCX = theWindow->width - 1; } else if(ev->axis.id == 1) // yaxis. { uiCY += ev->axis.pos; if(uiCY < 0) uiCY = 0; if(uiCY >= theWindow->height) uiCY = theWindow->height - 1; } } // Call the page's responder. uiCurrentPage->responder(uiCurrentPage, ev); // If the UI is active, all events are eaten by it. return true; } void UI_Ticker(timespan_t time) { #define UIALPHA_FADE_STEP .07 static trigger_t fixed = { 1 / 35.0, 0 }; float diff = 0; if(!uiActive) return; if(!uiCurrentPage) return; if(!M_RunTrigger(&fixed, time)) return; // Move towards the target alpha level for the entire UI. diff = uiTargetAlpha - uiAlpha; if(fabs(diff) > UIALPHA_FADE_STEP) { uiAlpha += UIALPHA_FADE_STEP * (diff > 0? 1 : -1); } else { uiAlpha = uiTargetAlpha; } if(!uiDrawGame) { // By default, the game is not visible, but since the alpha is not // fully opaque, it must be shown anyway. drawGame = (uiAlpha < 1.0); } // Call the active page's ticker. uiCurrentPage->ticker(uiCurrentPage); #undef UIALPHA_FADE_STEP } /** * Draws the current ui page if active */ void UI_Drawer(void) { if(!uiActive || !uiCurrentPage) return; // Go into screen projection mode. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); // Call the active page's drawer. uiCurrentPage->drawer(uiCurrentPage); // Draw mouse cursor? if(uiShowMouse) { float width, height, scale; if(theWindow->width >= theWindow->height) scale = (theWindow->width / UI_WIDTH) * (theWindow->height / (float) theWindow->width); else scale = (theWindow->height / UI_HEIGHT) * (theWindow->width / (float) theWindow->height); width = UICURSORWIDTH * scale * uiCursorWidthMul; height = UICURSORHEIGHT * scale * uiCursorHeightMul; UI_DrawMouse(uiCX - 1, uiCY - 1, width, height); } // Restore the original matrices. glMatrixMode(GL_PROJECTION); glPopMatrix(); } int UI_CountObjects(ui_object_t *list) { int count; for(count = 0; list->type != UI_NONE; list++, count++); return count; } void UI_FlagGroup(ui_object_t *list, int group, int flags, int set) { for(; list->type; list++) if(list->group == group) { switch(set) { case UIFG_CLEAR: list->flags &= ~flags; break; case UIFG_SET: list->flags |= flags; break; case UIFG_XOR: list->flags ^= flags; break; default: Con_Error("UI_FlagGroup: Unknown flag bit op %i\n", set); break; } } } /** * All the specified flags must be set. */ ui_object_t *UI_FindObject(ui_object_t *list, int group, int flags) { for(; list->type; list++) if(list->group == group && (list->flags & flags) == flags) return list; return NULL; } /** * Set focus to the object under the mouse cursor. */ void UI_MouseFocus(void) { int i; ui_object_t *ob; for(i = 0, ob = uiCurrentPage->objects; i < uiCurrentPage->count; i++, ob++) if(!(ob->flags & UIF_NO_FOCUS) && UI_MouseInside(ob)) { UI_Focus(ob); break; } } /** * @param ob Must be on the current page! It can't be NULL. */ void UI_Focus(ui_object_t *ob) { int i; if(!ob) Con_Error("UI_Focus: Tried to set focus on NULL.\n"); // Can the object receive focus? if(ob->flags & UIF_NO_FOCUS) return; uiCurrentPage->focus = ob - uiCurrentPage->objects; for(i = 0; i < uiCurrentPage->count; ++i) { if(i == uiCurrentPage->focus) uiCurrentPage->objects[i].flags |= UIF_FOCUS; else uiCurrentPage->objects[i].flags &= ~UIF_FOCUS; } } /** * @param ob If @c NULL,, capture is ended. * Must be on the current page! */ void UI_Capture(ui_object_t *ob) { if(!ob) { // End capture. uiCurrentPage->capture = -1; return; } if(!ob->responder) return; // Sorry, pal... // Set the capture object. uiCurrentPage->capture = ob - uiCurrentPage->objects; // Set focus. UI_Focus(ob); } //--------------------------------------------------------------------------- // Default Callback Functions //--------------------------------------------------------------------------- int UIPage_Responder(ui_page_t *page, ddevent_t *ev) { int i, k; ui_object_t *ob; ddevent_t translated; // Translate mouse wheel? if(IS_MOUSE_DOWN(ev)) { if(ev->toggle.id == DD_MWHEEL_UP || ev->toggle.id == DD_MWHEEL_DOWN) { UI_MouseFocus(); translated.device = IDEV_KEYBOARD; translated.type = E_TOGGLE; translated.toggle.state = ETOG_DOWN; translated.toggle.id = (ev->toggle.id == DD_MWHEEL_UP ? DDKEY_UPARROW : DDKEY_DOWNARROW); ev = &translated; } } if(page->capture >= 0) { // There is an object that has captured input. ob = page->objects + page->capture; // Capture objects must have a responder! // This object gets to decide what happens. return ob->responder(ob, ev); } // Check for Esc key. if(IS_KEY_PRESS(ev)) { // We won't accept repeats with Esc. if(ev->toggle.id == DDKEY_ESCAPE && ev->toggle.state == ETOG_DOWN && allowEscape) { UI_SetPage(page->previous); // If we have no more a page, disactive UI. if(!uiCurrentPage) UI_End(); return true; // The event was used. } // // If current UI is a dialog not requiring input we'll ignore the event // if(dialogActive && !dialogInput) // return false; // Tab is used for navigation. if(ev->toggle.id == DDKEY_TAB) { // Remove the focus flag from the current focus object. page->objects[page->focus].flags &= ~UIF_FOCUS; // Move focus. k = 0; do { page->focus += shiftDown ? -1 : 1; // Check range. if(page->focus < 0) page->focus = page->count - 1; else if(page->focus >= page->count) page->focus = 0; } while(++k < page->count && (page->objects[page->focus]. flags & (UIF_DISABLED | UIF_NO_FOCUS | UIF_HIDDEN))); // Flag the new focus object. page->objects[page->focus].flags |= UIF_FOCUS; return true; // The event was used. } } // Call responders until someone uses the event. // We start with the focus object. for(i = 0; i < page->count; ++i) { // Determine the index of the object to process. k = page->focus + i; // Wrap around. if(k < 0) k += page->count; if(k >= page->count) k -= page->count; ob = page->objects + k; // Check the flags of this object. if((ob->flags & UIF_HIDDEN) || (ob->flags & UIF_DISABLED)) continue; // These flags prevent response. // When the UI is faded, a click on a nonfocusable object brings // back the UI. /*if(uiTargetAlpha < 1.0 && ev->type == EV_MOUSE_BUTTON && ev->data1 == EVS_DOWN && UI_MouseInside(ob) && (!ob->responder || (ob->flags & UIF_NO_FOCUS))) { // Restore default focus UI_DefaultFocus(page); }*/ if(!ob->responder) continue; // Must have a responder. if(ob->responder(ob, ev)) { // The event was used by this object. UI_Focus(ob); // Move focus to it. return true; } } if(uiTargetAlpha < 1.0 && IS_MOUSE_DOWN(ev)) { // When the UI the faded, an unhandled click brings back the UI. UI_DefaultFocus(page); } // We didn't use the event. return false; } /** * Call the ticker routine for each object. */ void UIPage_Ticker(ui_page_t *page) { int i; ui_object_t *ob; boolean fadedAway = false; // Call the ticker of each object, unless they're hidden or paused. for(i = 0, ob = page->objects; i < page->count; ++i, ob++) { if((ob->flags & UIF_PAUSED) || (ob->flags & UIF_HIDDEN)) continue; // Fadeaway objects cause the UI to fade away when the mouse is over // the control. if((ob->flags & UIF_FOCUS) && (ob->flags & UIF_FADE_AWAY)) { UI_SetAlpha(0); fadedAway = true; } if(ob->ticker) ob->ticker(ob); // Advance object timer. ob->timer++; } if(!fadedAway) { UI_SetAlpha(1.0); } page->timer++; // Check mouse resting. if(abs(uiCX - uiRestCX) > uiRestOffsetLimit || abs(uiCY - uiRestCY) > uiRestOffsetLimit) { // Restart resting period. uiRestCX = uiCX; uiRestCY = uiCY; uiRestStart = page->timer; } } /** * Draws the ui including all objects on the current page */ void UIPage_Drawer(ui_page_t *page) { int i; float t; ui_object_t *ob; ui_color_t focuscol; // Draw background? if(page->background) UI_DrawDDBackground(0, 0, theWindow->width, theWindow->height, uiAlpha); // Draw title? //if(page->header) // UI_DrawTitle(page); // Draw each object, unless they're hidden. for(i = 0, ob = page->objects; i < page->count; ++i, ob++) { float currentUIAlpha = uiAlpha; if((ob->flags & UIF_HIDDEN) || !ob->drawer) continue; if(ob->flags & UIF_FADE_AWAY) { if(ob->flags & UIF_FOCUS) { // The focused object must not fade away completely. uiAlpha = MAX_OF(currentUIAlpha, 0.75); } else { // Other fadeaway objects remain slightly visible. uiAlpha = MAX_OF(currentUIAlpha, 0.333); } } if(ob->flags & UIF_NEVER_FADE) { uiAlpha = 1.0; } // Draw the object itself. ob->drawer(ob); if((ob->flags & UIF_FOCUS) && (ob->type != UI_EDIT || !(ob->flags & UIF_ACTIVE))) { t = (1 + sin(page->timer / (float) TICSPERSEC * 1.5f * PI)) / 2; UI_MixColors(UI_Color(UIC_BRD_LOW), UI_Color(UIC_BRD_HI), &focuscol, t); UI_Shade(ob->x, ob->y, ob->w, ob->h, UI_BORDER, UI_Color(UIC_BRD_LOW), UI_Color(UIC_BRD_LOW), .2f + t * .3f, -1); GL_BlendMode(BM_ADD); // Draw a focus rectangle. UI_DrawRect(ob->x - 1, ob->y - 1, ob->w + 2, ob->h + 2, UI_BORDER, &focuscol, 1); GL_BlendMode(BM_NORMAL); } // Restore the correct UI alpha. uiAlpha = currentUIAlpha; } } void UIFrame_Drawer(ui_object_t *ob) { int b = UI_BORDER; UI_GradientEx(ob->x, ob->y, ob->w, ob->h, b, UI_Color(UIC_BG_MEDIUM), 0, .6f, 0); UI_DrawRect(ob->x, ob->y, ob->w, ob->h, b, UI_Color(UIC_BRD_HI) /*, UI_Color(UIC_BRD_MED), UI_Color(UIC_BRD_LOW) */ , 1); } void UIText_Drawer(ui_object_t *ob) { FR_SetFont(glFontVariable[GLFS_NORMAL]); UI_TextOutEx(ob->text, ob->x, ob->y + ob->h / 2, false, true, UI_Color(UIC_TEXT), ob->flags & UIF_DISABLED ? .2f : 1); } void UIText_BrightDrawer(ui_object_t *ob) { FR_SetFont(glFontVariable[GLFS_NORMAL]); UI_TextOutEx(ob->text, ob->x, ob->y + ob->h / 2, false, true, UI_Color(UIC_TITLE), ob->flags & UIF_DISABLED ? .2f : 1); } int UIButton_Responder(ui_object_t *ob, ddevent_t *ev) { if(ob->flags & UIF_CLICKED) { if((ev->device == IDEV_KEYBOARD || ev->device == IDEV_MOUSE) && IS_TOGGLE_UP(ev)) { UI_Capture(0); ob->flags &= ~UIF_CLICKED; if(UI_MouseInside(ob) || ev->device == IDEV_KEYBOARD) { // Activate? if(ob->action) ob->action(ob); } return true; } } else if(IS_TOGGLE_DOWN(ev) && ((ev->device == IDEV_MOUSE && UI_MouseInside(ob)) || (ev->device == IDEV_KEYBOARD && IS_ACTKEY(ev->toggle.id)))) { if(ob->type == UI_BUTTON) { // Capture input. UI_Capture(ob); ob->flags |= UIF_CLICKED; } else { // Stay-down buttons change state. ob->flags ^= UIF_ACTIVE; if(ob->data) { void *data; if(ob->type == UI_BUTTON2EX) data = ((uidata_button_t *) ob->data)->data; else data = ob->data; *(char *) data = (ob->flags & UIF_ACTIVE) != 0; } // Call the action function. if(ob->action) ob->action(ob); } ob->timer = 0; return true; } return false; } void UIButton_Drawer(ui_object_t *ob) { int dis = (ob->flags & UIF_DISABLED) != 0; int act = (ob->flags & UIF_ACTIVE) != 0; int click = (ob->flags & UIF_CLICKED) != 0; boolean down = act || click; ui_color_t back; float t = ob->timer / 15.0f; float alpha = (dis ? .2f : 1); const char *text; if(ob->type == UI_BUTTON2EX) { uidata_button_t *data = ob->data; if(down) text = data->yes; else text = data->no; } else { text = ob->text; } // Mix the background color. if(!click || t > .5f) t = .5f; if(act && t > .1f) t = .1f; UI_MixColors(UI_Color(UIC_TEXT), UI_Color(UIC_SHADOW), &back, t); UI_GradientEx(ob->x, ob->y, ob->w, ob->h, UI_BUTTON_BORDER, &back, 0, alpha, 0); UI_Shade(ob->x, ob->y, ob->w, ob->h, UI_BUTTON_BORDER * (down ? -1 : 1), UI_Color(UIC_BRD_HI), UI_Color(UIC_BRD_LOW), alpha / 3, -1); UI_DrawRectEx(ob->x, ob->y, ob->w, ob->h, UI_BUTTON_BORDER * (down ? -1 : 1), false, UI_Color(UIC_BRD_HI), NULL, alpha, -1); FR_SetFont(glFontVariable[GLFS_NORMAL]); UI_TextOutEx(text, down + ob->x + (ob->flags & UIF_LEFT_ALIGN ? UI_BUTTON_BORDER * 2 : ob->w / 2), down + ob->y + ob->h / 2, !(ob->flags & UIF_LEFT_ALIGN), true, UI_Color(UIC_TITLE), alpha); } int UIEdit_Responder(ui_object_t *ob, ddevent_t *ev) { uidata_edit_t *dat = ob->data; if(ob->flags & UIF_ACTIVE) { if(!IS_KEY_PRESS(ev)) return false; switch(ev->toggle.id) { case DDKEY_LEFTARROW: if(dat->cp > 0) dat->cp--; break; case DDKEY_RIGHTARROW: if(dat->cp < (uint) strlen(ob->text)) dat->cp++; break; case DDKEY_HOME: dat->cp = 0; break; case DDKEY_END: dat->cp = (uint) strlen(ob->text); break; case DDKEY_BACKSPACE: if(dat->cp == 0) break; dat->cp--; case DDKEY_DEL: memmove(ob->text + dat->cp, ob->text + dat->cp + 1, strlen(ob->text) - dat->cp); break; case DDKEY_RETURN: // Store changes. memset(dat->ptr, 0, dat->maxlen); strncpy(dat->ptr, ob->text, dat->maxlen); if(ob->action) ob->action(ob); case DDKEY_ESCAPE: memset(ob->text, 0, sizeof(ob->text)); strncpy(ob->text, dat->ptr, 255); ob->flags &= ~UIF_ACTIVE; UI_Capture(0); break; default: if((int) strlen(ob->text) < dat->maxlen && ev->toggle.id >= 32 && (DD_ModKey(ev->toggle.id) <= 127 || DD_ModKey(ev->toggle.id) >= DD_HIGHEST_KEYCODE)) { memmove(ob->text + dat->cp + 1, ob->text + dat->cp, strlen(ob->text) - dat->cp); ob->text[dat->cp++] = DD_ModKey(ev->toggle.id); } break; } return true; } else if(IS_TOGGLE_DOWN(ev) && ((ev->device == IDEV_MOUSE && UI_MouseInside(ob)) || (ev->device == IDEV_KEYBOARD && IS_ACTKEY(ev->toggle.id)))) { // Activate and capture. ob->flags |= UIF_ACTIVE; ob->timer = 0; UI_Capture(ob); memset(ob->text, 0, sizeof(ob->text)); strncpy(ob->text, dat->ptr, 255); dat->cp = (uint) strlen(ob->text); return true; } return false; } void UIEdit_Drawer(ui_object_t *ob) { uidata_edit_t *dat = ob->data; int act = (ob->flags & UIF_ACTIVE) != 0; int dis = (ob->flags & UIF_DISABLED) != 0; int textWidth; ui_color_t back; float t = ob->timer / 8.0f; char buf[256]; uint curx, i, maxw = ob->w - UI_BORDER * 4, firstInBuf = 0; float alpha = (dis ? .2f : .5f); // Mix the background color. if(!act || t > 1) t = 1; UI_MixColors(UI_Color(UIC_TEXT), UI_Color(UIC_SHADOW), &back, t); UI_GradientEx(ob->x, ob->y, ob->w, ob->h, UI_BORDER, &back, 0, alpha, 0); UI_Shade(ob->x, ob->y, ob->w, ob->h, UI_BORDER, UI_Color(UIC_BRD_HI), UI_Color(UIC_BRD_LOW), alpha / 3, -1); UI_DrawRectEx(ob->x, ob->y, ob->w, ob->h, UI_BORDER * (act ? -1 : 1), false, UI_Color(UIC_BRD_HI), NULL, dis ? .2f : 1, -1); // Draw text. FR_SetFont(glFontVariable[GLFS_LIGHT]); memset(buf, 0, sizeof(buf)); // Does all of it fit in the box? textWidth = FR_TextWidth(ob->text); if(textWidth > 0 && (unsigned) textWidth > maxw) { // No, it doesn't fit. if(!act) UI_StrCpyLen(buf, ob->text, maxw); else { // Can we show to the cursor? for(curx = 0, i = 0; i < dat->cp; ++i) curx += FR_CharWidth(ob->text[i]); // How much do we need to skip forward? for(; curx > maxw; ++firstInBuf) curx -= FR_CharWidth(ob->text[firstInBuf]); UI_StrCpyLen(buf, ob->text + firstInBuf, maxw); } } else { // It fits! strcpy(buf, ob->text); } UI_TextOutEx(buf, ob->x + UI_BORDER * 2, ob->y + ob->h / 2, false, true, UI_Color(UIC_TEXT), dis ? .2f : 1); if(act && ob->timer & 4) { // Draw cursor. // Determine position. for(curx = 0, i = firstInBuf; i < dat->cp; ++i) curx += FR_CharWidth(ob->text[i]); UI_Gradient(ob->x + UI_BORDER * 2 + curx - 1, ob->y + ob->h / 2 - uiFontHgt / 2, 2, uiFontHgt, UI_Color(UIC_TEXT), 0, 1, 1); } } int UIList_Responder(ui_object_t *ob, ddevent_t *ev) { uidata_list_t *dat = ob->data; int i, oldsel = dat->selection, buth, barh; int used = false; if(ob->flags & UIF_CLICKED) { // We've captured all input. if(ev->device == IDEV_MOUSE) { if(ev->type == E_AXIS) { // Calculate the new position. buth = UI_ListButtonHeight(ob); barh = ob->h - 2 * (UI_BORDER + buth); if(barh - buth) { dat->first = ((uiCY - ob->y - UI_BORDER - (buth * 3) / 2) * (dat->count - dat->numvis) + (barh - buth) / 2) / (barh - buth); } else { dat->first = 0; } // Check that it's in range. if(dat->first > dat->count - dat->numvis) dat->first = dat->count - dat->numvis; if(dat->first < 0) dat->first = 0; } else if(IS_TOGGLE_UP(ev)) { dat->button[1] = false; // Release capture. UI_Capture(0); ob->flags &= ~UIF_CLICKED; } } // We're eating everything. return true; } else if(IS_KEY_PRESS(ev)) { used = true; switch(ev->toggle.id) { case DDKEY_UPARROW: if(dat->selection > 0) dat->selection--; break; case DDKEY_DOWNARROW: if(dat->selection < dat->count - 1) dat->selection++; break; case DDKEY_HOME: dat->selection = 0; break; case DDKEY_END: dat->selection = dat->count - 1; break; default: used = false; } } else if(IS_MOUSE_DOWN(ev)) { if(!UI_MouseInside(ob)) return false; // Now we know we're going to eat this event. used = true; buth = UI_ListButtonHeight(ob); // Clicked in the item section? if(dat->count > 0 && UI_MouseInsideBox(ob->x + UI_BORDER, ob->y + UI_BORDER, ob->w - 2 * UI_BORDER - (dat->count >= dat-> numvis ? UI_BAR_WDH : 0), ob->h - 2 * UI_BORDER)) { dat->selection = dat->first + (uiCY - ob->y - UI_BORDER) / UI_ListItemHeight(dat); if(dat->selection >= dat->count) dat->selection = dat->count - 1; } else if(dat->count < dat->numvis) { // No scrollbar. return true; } // Clicked the Up button? else if(UI_MouseInsideBox (ob->x + ob->w - UI_BORDER - UI_BAR_WDH, ob->y + UI_BORDER, UI_BAR_WDH, buth)) { // The Up button is now pressed. dat->button[0] = true; ob->timer = SCROLL_TIME; // Ticker does the scrolling. return true; } // Clicked the Down button? else if(UI_MouseInsideBox (ob->x + ob->w - UI_BORDER - UI_BAR_WDH, ob->y + ob->h - UI_BORDER - buth, UI_BAR_WDH, buth)) { // The Down button is now pressed. dat->button[2] = true; ob->timer = SCROLL_TIME; // Ticker does the scrolling. return true; } // Clicked the Thumb? else if(UI_MouseInsideBox (ob->x + ob->w - UI_BORDER - UI_BAR_WDH, UI_ListThumbPos(ob), UI_BAR_WDH, buth)) { dat->button[1] = true; // Capture input and start tracking mouse movement. UI_Capture(ob); ob->flags |= UIF_CLICKED; return true; } else return false; } else if(IS_MOUSE_UP(ev)) { // Release all buttons. for(i = 0; i < 3; ++i) dat->button[i] = false; // We might have leaved the object's area, so let other objects // process this event, too. return false; } else { // We are not going to use this event. return false; } // Adjust the first visible item. if(dat->selection >= 0) { if(dat->selection < dat->first) dat->first = dat->selection; if(dat->selection > dat->first + dat->numvis - 1) dat->first = dat->selection - dat->numvis + 1; } // Call action function? if(oldsel != dat->selection && ob->action) ob->action(ob); return used; } void UIList_Ticker(ui_object_t *ob) { uidata_list_t *dat = ob->data; if(ob->timer >= SCROLL_TIME && (dat->button[0] || dat->button[2])) { // Next time in 3 ticks. ob->timer = 0; // Send a direct event. if(dat->button[0] && dat->first > 0) dat->first--; if(dat->button[2] && dat->first < dat->count - dat->numvis) dat->first++; } } void UIList_Drawer(ui_object_t *ob) { uidata_list_t *dat = ob->data; uidata_listitem_t *items = dat->items; int dis = (ob->flags & UIF_DISABLED) != 0; int i, c, x, y, ihgt, maxw = ob->w - 2 * UI_BORDER; int maxh = ob->h - 2 * UI_BORDER, buth; char buf[256], *ptr, *endptr, tmp[256]; float alpha = dis ? .2f : 1; int barw; // The background. UI_GradientEx(ob->x, ob->y, ob->w, ob->h, UI_BORDER, UI_Color(UIC_SHADOW), 0, alpha / 2, 0); // The borders. UI_DrawRectEx(ob->x, ob->y, ob->w, ob->h, -UI_BORDER, false, UI_Color(UIC_BRD_HI), NULL, alpha, -1); // The title. FR_SetFont(glFontVariable[GLFS_NORMAL]); UI_TextOutEx(ob->text, ob->x, ob->y - UI_BORDER - uiFontHgt, false, false, UI_Color(UIC_TEXT), alpha); // Is a scroll bar necessary? ihgt = UI_ListItemHeight(dat); if(dat->numvis < dat->count) { barw = UI_BAR_WDH; maxw -= barw; buth = UI_ListButtonHeight(ob); x = ob->x + ob->w - UI_BORDER - barw; y = ob->y + UI_BORDER; UI_GradientEx(x, y, barw, maxh, UI_BAR_BUTTON_BORDER, UI_Color(UIC_TEXT), 0, alpha * .2f, alpha * .2f); // Up Button. UI_DrawButton(x, y, barw, buth, UI_BAR_BUTTON_BORDER, !dat->first ? alpha * .2f : alpha, NULL, dat->button[0], dis, UIBA_UP); // Thumb Button. UI_DrawButton(x, UI_ListThumbPos(ob), barw, buth, UI_BAR_BUTTON_BORDER, alpha, NULL, dat->button[1], dis, UIBA_NONE); // Down Button. UI_DrawButton(x, y + maxh - buth, barw, buth, UI_BAR_BUTTON_BORDER, dat->first + dat->numvis >= dat->count ? alpha * .2f : alpha, NULL, dat->button[2], dis, UIBA_DOWN); } x = ob->x + UI_BORDER; y = ob->y + UI_BORDER; // Draw columns? for(c = 0; c < UI_MAX_COLUMNS; ++c) { if(!dat->column[c] || dat->column[c] > maxw - 2 * UI_BORDER) continue; UI_Gradient(x + UI_BORDER + dat->column[c] - 2, ob->y + UI_BORDER, 1, maxh, UI_Color(UIC_TEXT), 0, alpha * .5f, alpha * .5f); } FR_SetFont(glFontVariable[GLFS_LIGHT]); for(i = dat->first; i < dat->count && i < dat->first + dat->numvis; ++i, y += ihgt) { // The selection has a white background. if(i == dat->selection) { UI_GradientEx(x, y, maxw, ihgt, UI_BAR_BORDER, UI_Color(UIC_TEXT), 0, alpha * .6f, alpha * .2f); } // The text, clipped w/columns. ptr = items[i].text; for(c = 0; c < UI_MAX_COLUMNS; ++c) { endptr = strchr(ptr, '\t'); memset(tmp, 0, sizeof(tmp)); if(endptr) strncpy(tmp, ptr, endptr - ptr); else strcpy(tmp, ptr); memset(buf, 0, sizeof(buf)); UI_StrCpyLen(buf, tmp, maxw - 2 * UI_BORDER - dat->column[c]); UI_TextOutEx(buf, x + UI_BORDER + dat->column[c], y + ihgt / 2, false, true, UI_Color(UIC_TEXT), alpha); if(!endptr) break; ptr = endptr + 1; } } } int UI_SliderButtonWidth(ui_object_t *ob) { // uidata_slider_t *dat = ob->data; int width = ob->h - UI_BAR_BORDER * 2; if(width < UI_BAR_BORDER * 3) width = UI_BAR_BORDER * 3; return width; } int UI_SliderThumbPos(ui_object_t *ob) { uidata_slider_t *dat = ob->data; float range = dat->max - dat->min, useval; int butw = UI_SliderButtonWidth(ob); if(!range) range = 1; // Should never happen. if(dat->floatmode) useval = dat->value; else { if(dat->value >= 0) useval = (int) (dat->value + .5f); else useval = (int) (dat->value - .5f); } useval -= dat->min; return ob->x + UI_BAR_BORDER + butw + useval / range * (ob->w - UI_BAR_BORDER * 2 - butw * 3); } int UISlider_Responder(ui_object_t *ob, ddevent_t *ev) { uidata_slider_t *dat = ob->data; float oldvalue = dat->value; boolean used = false; int i, butw, inw; if(ob->flags & UIF_CLICKED) { // We've captured all input. if(ev->device == IDEV_MOUSE) { if(ev->type == E_AXIS) { // Calculate new value from the mouse position. butw = UI_SliderButtonWidth(ob); inw = ob->w - 2 * UI_BAR_BORDER - 3 * butw; if(inw > 0) { dat->value = dat->min + (dat->max - dat->min) * (uiCX - ob->x - UI_BAR_BORDER - (3 * butw) / 2) / (float) inw; } else { dat->value = dat->min; } if(dat->value < dat->min) dat->value = dat->min; if(dat->value > dat->max) dat->value = dat->max; if(!dat->floatmode) { if(dat->value >= 0) dat->value = (int) (dat->value + .5f); else dat->value = (int) (dat->value - .5f); } if(ob->action) ob->action(ob); } else if(IS_TOGGLE_UP(ev)) { dat->button[1] = false; // Release thumb. UI_Capture(0); ob->flags &= ~UIF_CLICKED; } } return true; } else if(IS_KEY_PRESS(ev)) { used = true; switch(ev->toggle.id) { case DDKEY_HOME: dat->value = dat->min; break; case DDKEY_END: dat->value = dat->max; break; case DDKEY_LEFTARROW: dat->value -= dat->step; if(dat->value < dat->min) dat->value = dat->min; break; case DDKEY_RIGHTARROW: dat->value += dat->step; if(dat->value > dat->max) dat->value = dat->max; break; case DDKEY_UPARROW: case DDKEY_DOWNARROW: // Ignore up/down while in the slider. break; default: used = false; } } else if(IS_MOUSE_DOWN(ev)) { if(!UI_MouseInside(ob)) return false; used = true; butw = UI_SliderButtonWidth(ob); // Where is the mouse cursor? if(UI_MouseInsideBox(ob->x, ob->y, butw + UI_BAR_BORDER, ob->h)) { // The Left button is now pressed. dat->button[0] = true; ob->timer = SCROLL_TIME; // Ticker does the scrolling. return true; } if(UI_MouseInsideBox (ob->x + ob->w - butw - UI_BAR_BORDER, ob->y, butw + UI_BAR_BORDER, ob->h)) { // The Right button is now pressed. dat->button[2] = true; ob->timer = SCROLL_TIME; // Tickes does the scrolling. return true; } if(UI_MouseInsideBox(UI_SliderThumbPos(ob), ob->y, butw, ob->h)) { // Capture input and start tracking mouse movement. dat->button[1] = true; UI_Capture(ob); ob->flags |= UIF_CLICKED; return true; } } else if(IS_MOUSE_UP(ev)) { // Release all buttons. for(i = 0; i < 3; ++i) dat->button[i] = false; // We might be outside the object's area (or none of the buttons // might even be pressed), so let others have this event, too. return false; } else { // We are not going to use this event. return false; } // Did the value change? if(oldvalue != dat->value && ob->action) ob->action(ob); return used; } void UISlider_Ticker(ui_object_t *ob) { uidata_slider_t *dat = ob->data; float oldval; if(ob->timer >= SCROLL_TIME && (dat->button[0] || dat->button[2])) { ob->timer = 0; oldval = dat->value; if(dat->button[0]) dat->value -= dat->step; if(dat->button[2]) dat->value += dat->step; if(dat->value < dat->min) dat->value = dat->min; if(dat->value > dat->max) dat->value = dat->max; if(oldval != dat->value && ob->action) ob->action(ob); } } void UISlider_Drawer(ui_object_t *ob) { uidata_slider_t *dat = ob->data; boolean dis = (ob->flags & UIF_DISABLED) != 0; int inwidth = ob->w - UI_BAR_BORDER * 2; int inheight = ob->h - UI_BAR_BORDER * 2; int butw = UI_SliderButtonWidth(ob); int butbor = UI_BAR_BUTTON_BORDER; int x, y, thumbx; float alpha = dis ? .2f : 1; char buf[80]; // The background. UI_GradientEx(ob->x, ob->y, ob->w, ob->h, UI_BAR_BORDER, UI_Color(UIC_SHADOW), 0, alpha / 2, 0); // The borders. UI_DrawRectEx(ob->x, ob->y, ob->w, ob->h, -UI_BAR_BORDER, false, UI_Color(UIC_BRD_HI), NULL, alpha, -1); x = ob->x + UI_BAR_BORDER; y = ob->y + UI_BAR_BORDER; // The left button. UI_DrawButton(x, y, butw, inheight, butbor, alpha * (dat->value == dat->min ? .2f : 1), NULL, dat->button[0], dis, UIBA_LEFT); // The right button. UI_DrawButton(x + inwidth - butw, y, butw, inheight, butbor, alpha * (dat->value == dat->max ? .2f : 1), NULL, dat->button[2], dis, UIBA_RIGHT); // The thumb. UI_DrawButton(thumbx = UI_SliderThumbPos(ob), y, butw, inheight, butbor, alpha, NULL, dat->button[1], dis, UIBA_NONE); // The value. if(dat->floatmode) { if(dat->step >= .01f) { sprintf(buf, "%.2f", dat->value); } else { sprintf(buf, "%.5f", dat->value); } } else sprintf(buf, "%i", (int) dat->value); if(dat->zerotext && dat->value == dat->min) strcpy(buf, dat->zerotext); FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(buf, x + (dat->value < (dat->min + dat->max) / 2 ? inwidth - butw - UI_BAR_BORDER - FR_TextWidth(buf) : butw + UI_BAR_BORDER), y + inheight / 2, false, true, UI_Color(UIC_TEXT), alpha); } //--------------------------------------------------------------------------- // Helper Functions //--------------------------------------------------------------------------- void UI_InitColumns(ui_object_t *ob) { uidata_list_t *dat = ob->data; uidata_listitem_t *list = dat->items; int i, c, w, sep, last, maxw; char *endptr, *ptr, temp[256]; int width[UI_MAX_COLUMNS]; int numcols = 1; memset(dat->column, 0, sizeof(dat->column)); memset(width, 0, sizeof(width)); for(i = 0; i < dat->count; ++i) { ptr = list[i].text; for(c = 0; c < UI_MAX_COLUMNS; ++c) { if(c + 1 > numcols) numcols = c + 1; endptr = strchr(ptr, '\t'); memset(temp, 0, sizeof(temp)); if(endptr) strncpy(temp, ptr, endptr - ptr); else strcpy(temp, ptr); w = FR_TextWidth(temp); if(w > width[c]) width[c] = w; if(!endptr) break; ptr = endptr + 1; } } // Calculate the total maximum width. for(w = i = 0; i < UI_MAX_COLUMNS; ++i) { w += width[i]; if(width[i]) last = width[i]; } // Calculate the offset for each column. maxw = ob->w - 4 * UI_BORDER - (dat->count > dat->numvis ? UI_BAR_WDH : 0); sep = maxw - w; if(numcols > 1) sep /= numcols - 1; if(sep < 0) sep = 0; for(c = i = 0; i < numcols; ++i) { dat->column[i] = c; c += sep + width[i]; } } int UI_ListItemHeight(uidata_list_t *listdata) { int h = listdata->itemhgt; if(h < uiFontHgt * 8 / 10) h = uiFontHgt * 8 / 10; return h; } int UI_ListButtonHeight(ui_object_t *ob) { int barh = ob->h - 2 * UI_BORDER; int buth = UI_BAR_WDH; if(buth > barh / 3) buth = barh / 3; return buth; } int UI_ListThumbPos(ui_object_t *ob) { uidata_list_t *dat = ob->data; int buth = UI_ListButtonHeight(ob); int barh = ob->h - 2 * (UI_BORDER + buth); if(dat->count <= dat->numvis) return 0; return ob->y + UI_BORDER + buth + ((barh - buth) * dat->first) / (dat->count - dat->numvis); } int UI_ListFindItem(ui_object_t *ob, int data_value) { uidata_list_t *dat = ob->data; int i; for(i = 0; i < dat->count; ++i) if(((uidata_listitem_t *) dat->items)[i].data == data_value) return i; return -1; } void UI_StrCpyLen(char *dest, char *src, int maxWidth) { int i, width; for(i = 0, width = 0; src[i]; ++i) { dest[i] = src[i]; width += FR_CharWidth(src[i]); if(width > maxWidth) { dest[i] = 0; break; } } } int UI_MouseInsideBox(int x, int y, int w, int h) { return (uiCX >= x && uiCX <= x + w && uiCY >= y && uiCY <= y + h); } /** * @return @c true, if the mouse is inside the object. */ int UI_MouseInside(ui_object_t *ob) { return UI_MouseInsideBox(ob->x, ob->y, ob->w, ob->h); } /** * @return @c true, if the mouse hasn't been moved * for a while. */ int UI_MouseResting(ui_page_t *page) { if(!uiMoved) return false; return page->timer - uiRestStart >= uiRestTime; } void UI_MixColors(ui_color_t *a, ui_color_t *b, ui_color_t *dest, float amount) { dest->red = (1 - amount) * a->red + amount * b->red; dest->green = (1 - amount) * a->green + amount * b->green; dest->blue = (1 - amount) * a->blue + amount * b->blue; } void UI_SetColorA(ui_color_t *color, float alpha) { glColor4f(color->red, color->green, color->blue, alpha); } void UI_SetColor(ui_color_t *color) { glColor3f(color->red, color->green, color->blue); } void UI_Shade(int x, int y, int w, int h, int border, ui_color_t *main, ui_color_t *secondary, float alpha, float bottomAlpha) { float s[2][2] = { {0, 1}, {1, 0} }; float t[2][2] = { {0, 1}, {1, 0} }; ui_color_t *color; uint i, flip = 0; float *u, *v; float beta = 1; alpha *= uiAlpha; bottomAlpha *= uiAlpha; if(border < 0) { //flip = 1; border = -border; } border = 0; if(bottomAlpha < 0) bottomAlpha = alpha; GL_BlendMode(BM_ADD); glBindTexture(GL_TEXTURE_2D, uiTextures[UITEX_SHADE]); glBegin(GL_QUADS); for(i = 0; i < 2; ++i) { if(!secondary) continue; color = (i == 0 ? main : secondary); u = (i == flip ? s[0] : s[1]); v = (i == flip ? t[0] : t[1]); if(i == 1) beta = 0.5f; UI_SetColorA(color, alpha * beta); glTexCoord2f(u[0], v[0]); glVertex2f(x + border, y + border); glTexCoord2f(u[1], v[0]); glVertex2f(x + w - border, y + border); UI_SetColorA(color, bottomAlpha * beta); glTexCoord2f(u[1], v[1]); glVertex2f(x + w - border, y + h - border); glTexCoord2f(u[0], v[1]); glVertex2f(x + border, y + h - border); } glEnd(); GL_BlendMode(BM_NORMAL); } void UI_Gradient(int x, int y, int w, int h, ui_color_t *top, ui_color_t *bottom, float topAlpha, float bottomAlpha) { UI_GradientEx(x, y, w, h, 0, top, bottom, topAlpha, bottomAlpha); } void UI_GradientEx(int x, int y, int w, int h, int border, ui_color_t *top, ui_color_t *bottom, float topAlpha, float bottomAlpha) { UI_DrawRectEx(x, y, w, h, border, true, top, bottom, topAlpha, bottomAlpha); } void UI_HorizGradient(int x, int y, int w, int h, ui_color_t *left, ui_color_t *right, float leftAlpha, float rightAlpha) { leftAlpha *= uiAlpha; rightAlpha *= uiAlpha; glBindTexture(GL_TEXTURE_2D, uiTextures[UITEX_HINT]); glBegin(GL_QUADS); UI_SetColorA(left, leftAlpha); glTexCoord2f(0, 1); glVertex2f(x, y + h); glTexCoord2f(0, 0); glVertex2f(x, y); UI_SetColorA(right ? right : left, rightAlpha); glTexCoord2f(1, 0); glVertex2f(x + w, y); glTexCoord2f(1, 1); glVertex2f(x + w, y + h); glEnd(); } void UI_Line(int x1, int y1, int x2, int y2, ui_color_t *start, ui_color_t *end, float startAlpha, float endAlpha) { startAlpha *= uiAlpha; endAlpha *= uiAlpha; glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); UI_SetColorA(start, startAlpha); glVertex2f(x1, y1); UI_SetColorA(end ? end : start, endAlpha); glVertex2f(x2, y2); glEnd(); glEnable(GL_TEXTURE_2D); } /** * Draw white, shadowed text. */ void UI_TextOut(const char *text, int x, int y) { UI_TextOutEx(text, x, y, false, false, UI_Color(UIC_TEXT), 1); } /** * Draw shadowed text. */ void UI_TextOutEx(const char *text, int x, int y, int horizCenter, int vertCenter, ui_color_t *color, float alpha) { alpha *= uiAlpha; if(alpha <= 0) return; // Center, if requested. if(horizCenter) x -= FR_TextWidth(text) / 2; if(vertCenter) { //y -= FR_TextHeight(text) / 2; y -= FR_SingleLineHeight(text)/2 + FR_GlyphTopToAscent(text); } // Shadow. //UI_SetColorA(UI_Color(UIC_SHADOW), .6f * alpha); //FR_TextOut((char*)text, x + UI_SHADOW_OFFSET, y + UI_SHADOW_OFFSET); // Actual text. UI_SetColorA(color, alpha); FR_CustomShadowTextOut(text, x, y, UI_SHADOW_OFFSET, UI_SHADOW_OFFSET, .6f); } int UI_TextOutWrap(const char *text, int x, int y, int w, int h) { return UI_TextOutWrapEx(text, x, y, w, h, UI_Color(UIC_TEXT), 1); } /** * Draw line-wrapped text inside a box. Returns the Y coordinate of the * last word. */ int UI_TextOutWrapEx(const char *text, int x, int y, int w, int h, ui_color_t *color, float alpha) { char word[2048], *wp = word; int len, tx = x, ty = y; byte c; int linehgt = FR_SingleLineHeight("A"); alpha *= uiAlpha; UI_SetColorA(color, alpha); for(;; text++) { c = *text; // Whitespace? if(!c || c == ' ' || c == '\n' || c == '\b' || c == '-') { if(c == '-') *wp++ = c; // Hyphens should be included in the word. // Time to print the word. *wp = 0; len = FR_TextWidth(word); if(tx + len > x + w) // Doesn't fit? { tx = x; ty += linehgt; } // Can't print any more? (always print the 1st line) if(ty + linehgt > y + h && ty != y) return ty; FR_TextOut(word, tx, ty); tx += len; wp = word; // React to delimiter. switch (c) { case 0: return ty; // All of the text has been printed. case ' ': tx += FR_TextWidth(" "); break; case '\n': tx = x; ty += linehgt; break; case '\b': // Break. tx = x; ty += 3 * linehgt / 2; break; default: break; } } else { // Append to word buffer. *wp++ = c; } } } void UI_DrawRectEx(int x, int y, int w, int h, int brd, boolean filled, ui_color_t *top, ui_color_t *bottom, float alpha, float bottomAlpha) { float s[2] = { 0, 1 }, t[2] = { 0, 1 }; alpha *= uiAlpha; bottomAlpha *= uiAlpha; if(alpha <= 0 && bottomAlpha <= 0) return; if(brd < 0) { brd = -brd; s[0] = t[0] = 1; s[1] = t[1] = 0; } if(bottomAlpha < 0) bottomAlpha = alpha; if(!bottom) bottom = top; // The fill comes first, if there's one. if(filled) { glBindTexture(GL_TEXTURE_2D, uiTextures[UITEX_FILL]); glBegin(GL_QUADS); glTexCoord2f(0.5f, 0.5f); UI_SetColorA(top, alpha); glVertex2f(x + brd, y + brd); glVertex2f(x + w - brd, y + brd); UI_SetColorA(bottom, bottomAlpha); glVertex2f(x + w - brd, y + h - brd); glVertex2f(x + brd, y + h - brd); } else { glBindTexture(GL_TEXTURE_2D, uiTextures[UITEX_CORNER]); glBegin(GL_QUADS); } if(!filled || brd > 0) { // Top Left. UI_SetColorA(top, alpha); glTexCoord2f(s[0], t[0]); glVertex2f(x, y); glTexCoord2f(0.5f, t[0]); glVertex2f(x + brd, y); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + brd, y + brd); glTexCoord2f(s[0], 0.5f); glVertex2f(x, y + brd); // Top. glTexCoord2f(0.5f, t[0]); glVertex2f(x + brd, y); glTexCoord2f(0.5f, t[0]); glVertex2f(x + w - brd, y); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + w - brd, y + brd); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + brd, y + brd); // Top Right. glTexCoord2f(0.5f, t[0]); glVertex2f(x + w - brd, y); glTexCoord2f(s[1], t[0]); glVertex2f(x + w, y); glTexCoord2f(s[1], 0.5f); glVertex2f(x + w, y + brd); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + w - brd, y + brd); // Right. glTexCoord2f(0.5f, 0.5f); glVertex2f(x + w - brd, y + brd); glTexCoord2f(s[1], 0.5f); glVertex2f(x + w, y + brd); UI_SetColorA(bottom, bottomAlpha); glTexCoord2f(s[1], 0.5f); glVertex2f(x + w, y + h - brd); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + w - brd, y + h - brd); // Bottom Right. glTexCoord2f(0.5f, 0.5f); glVertex2f(x + w - brd, y + h - brd); glTexCoord2f(s[1], 0.5f); glVertex2f(x + w, y + h - brd); glTexCoord2f(s[1], t[1]); glVertex2f(x + w, y + h); glTexCoord2f(0.5f, t[1]); glVertex2f(x + w - brd, y + h); // Bottom. glTexCoord2f(0.5f, 0.5f); glVertex2f(x + brd, y + h - brd); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + w - brd, y + h - brd); glTexCoord2f(0.5f, t[1]); glVertex2f(x + w - brd, y + h); glTexCoord2f(0.5f, t[1]); glVertex2f(x + brd, y + h); // Bottom Left. glTexCoord2f(s[0], 0.5f); glVertex2f(x, y + h - brd); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + brd, y + h - brd); glTexCoord2f(0.5f, t[1]); glVertex2f(x + brd, y + h); glTexCoord2f(s[0], t[1]); glVertex2f(x, y + h); // Left. UI_SetColorA(top, alpha); glTexCoord2f(s[0], 0.5f); glVertex2f(x, y + brd); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + brd, y + brd); UI_SetColorA(bottom, bottomAlpha); glTexCoord2f(0.5f, 0.5f); glVertex2f(x + brd, y + h - brd); glTexCoord2f(s[0], 0.5f); glVertex2f(x, y + h - brd); } glEnd(); } void UI_DrawRect(int x, int y, int w, int h, int brd, ui_color_t *color, float alpha) { UI_DrawRectEx(x, y, w, h, brd, false, color, NULL, alpha, alpha); } void UI_DrawTriangle(int x, int y, int radius, ui_color_t *hi, ui_color_t *med, ui_color_t *low, float alpha) { float xrad = radius * .866f; // cos(60) float yrad = radius / 2; // sin(60) alpha *= uiAlpha; if(alpha <= 0) return; glDisable(GL_TEXTURE_2D); glBegin(GL_TRIANGLES); y += radius / 4; // Upper left triangle. UI_SetColorA(radius > 0 ? hi : med, alpha); glVertex2f(x, y); glVertex2f(x - xrad, y + yrad); UI_SetColorA(radius > 0 ? hi : low, alpha); glVertex2f(x, y - radius); // Upper right triangle. UI_SetColorA(low, alpha); glVertex2f(x, y); glVertex2f(x, y - radius); UI_SetColorA(med, alpha); glVertex2f(x + xrad, y + yrad); // Bottom triangle. if(radius < 0) UI_SetColorA(hi, alpha); glVertex2f(x, y); glVertex2f(x + xrad, y + yrad); UI_SetColorA(radius > 0 ? low : med, alpha); glVertex2f(x - xrad, y + yrad); glEnd(); glEnable(GL_TEXTURE_2D); } /** * A horizontal triangle, pointing left or right. Positive radius * means left. */ void UI_DrawHorizTriangle(int x, int y, int radius, ui_color_t *hi, ui_color_t *med, ui_color_t *low, float alpha) { float yrad = radius * .866f; // cos(60) float xrad = radius / 2; // sin(60) alpha *= uiAlpha; if(alpha <= 0) return; glDisable(GL_TEXTURE_2D); glBegin(GL_TRIANGLES); x += radius / 4; // Upper left triangle. UI_SetColorA(radius > 0 ? hi : med, alpha); glVertex2f(x, y); if(radius < 0) UI_SetColorA(low, alpha); glVertex2f(x - radius, y); glVertex2f(x + xrad, y - yrad); // Lower left triangle. UI_SetColorA(radius > 0 ? med : hi, alpha); glVertex2f(x, y); if(radius < 0) UI_SetColorA(hi, alpha); glVertex2f(x + xrad, y + yrad); UI_SetColorA(radius > 0 ? low : med, alpha); glVertex2f(x - radius, y); // Right triangle. UI_SetColorA(radius > 0 ? med : hi, alpha); glVertex2f(x, y); UI_SetColorA(radius > 0 ? hi : med, alpha); glVertex2f(x + xrad, y - yrad); UI_SetColorA(radius > 0 ? low : hi, alpha); glVertex2f(x + xrad, y + yrad); glEnd(); glEnable(GL_TEXTURE_2D); } void UI_DefaultButtonBackground(ui_color_t *col, boolean down) { UI_MixColors(UI_Color(UIC_TEXT), UI_Color(UIC_SHADOW), col, down ? .1f : .5f); } void UI_DrawButton(int x, int y, int w, int h, int brd, float alpha, ui_color_t *background, boolean down, boolean disabled, int arrow) { int inside = MIN_OF(w - brd * 2, h - brd * 2); int boff = down ? 2 : 0; ui_color_t back; if(!background) { // Calculate the default button color. UI_DefaultButtonBackground(&back, down); background = &back; } UI_GradientEx(x, y, w, h, brd, background, 0, disabled ? .2f : 1, 0); UI_Shade(x, y, w, h, UI_BUTTON_BORDER * (down ? -1 : 1), UI_Color(UIC_BRD_HI), UI_Color(UIC_BRD_LOW), alpha / 3, -1); UI_DrawRectEx(x, y, w, h, brd * (down ? -1 : 1), false, UI_Color(UIC_BRD_HI), NULL, alpha, -1); switch(arrow) { case UIBA_UP: case UIBA_DOWN: UI_DrawTriangle(x + w / 2 + boff, y + h / 2 + boff, inside / 2.75f * (arrow == UIBA_DOWN ? -1 : 1), /*UI_Color(UIC_BRD_HI), UI_Color(UIC_BRD_MED), UI_Color(UIC_BRD_LOW), */ UI_Color(UIC_TEXT), UI_Color(UIC_TEXT), UI_Color(UIC_TEXT), alpha * (disabled ? .2f : 1)); break; case UIBA_LEFT: case UIBA_RIGHT: UI_DrawHorizTriangle(x + w / 2 + boff, y + h / 2 + boff, inside / 2.75f * (arrow == UIBA_RIGHT ? -1 : 1), /*UI_Color(UIC_BRD_HI), UI_Color(UIC_BRD_MED), UI_Color(UIC_BRD_LOW), */ UI_Color(UIC_TEXT), UI_Color(UIC_TEXT), UI_Color(UIC_TEXT), alpha * (disabled ? .2f : 1)); break; default: break; } } void UI_DrawHelpBox(int x, int y, int w, int h, float alpha, char *text) { int bor = UI_BUTTON_BORDER; UI_GradientEx(x, y, w, h, bor, UI_Color(UIC_HELP), UI_Color(UIC_HELP), alpha / 4, alpha / 2); UI_DrawRectEx(x, y, w, h, bor, false, UI_Color(UIC_BRD_HI), NULL, alpha, -1); if(text) { bor = 2 * UI_BORDER / 3; FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutWrapEx(text, x + 2 * bor, y + 2 * bor, w - 4 * bor, h - 4 * bor, UI_Color(UIC_TEXT), alpha); } } /** * Draw the mouse cursor at the given x, y co-ordinates. * * @param x X coordinate. * @param y Y coordinate. * @param w Width of the cursor. * @param h Height of the cursor. */ void UI_DrawMouse(int x, int y, int w, int h) { glColor3f(1, 1, 1); glBindTexture(GL_TEXTURE_2D, uiTextures[UITEX_MOUSE]); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(1, 0); glVertex2f(x + w, y); glTexCoord2f(1, 1); glVertex2f(x + w, y + h); glTexCoord2f(0, 1); glVertex2f(x, y + h); glEnd(); } void UI_DrawLogo(int x, int y, int w, int h) { glBindTexture(GL_TEXTURE_2D, uiTextures[UITEX_LOGO]); GL_DrawRect(x, y, w, h, 1, 1, 1, uiAlpha); } /** * Background with the "The Doomsday Engine" text superimposed. * * @param x X coordinate (left) to draw the background. * @param y Y coordinate (top) to draw the background. * @param w Width (from left) to draw the background. * @param h Height (from top) to draw the background. * @param alpha Alpha level to use when drawing the background. */ void UI_DrawDDBackground(float x, float y, float w, float h, float alpha) { float mul = (uiTextures[UITEX_BACKGROUND]? 1.5f : 1.0f); ui_color_t *dark = UI_Color(UIC_BG_DARK); ui_color_t *light = UI_Color(UIC_BG_LIGHT); // Background gradient picture. glBindTexture(GL_TEXTURE_2D, uiTextures[UITEX_BACKGROUND]); if(alpha < 1.0) { glEnable(GL_BLEND); GL_BlendMode(BM_NORMAL); } else { glDisable(GL_BLEND); } glBegin(GL_QUADS); // Top color. glColor4f(dark->red * mul, dark->green * mul, dark->blue * mul, alpha); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(1, 0); glVertex2f(x + w, y); // Bottom color. glColor4f(light->red * mul, light->green * mul, light->blue * mul, alpha); glTexCoord2f(1, 1); glVertex2f(x + w, y + h); glTexCoord2f(0, 1); glVertex2f(0, y + h); glEnd(); glEnable(GL_BLEND); } /** * CCmd: Change the UI colors. */ D_CMD(UIColor) { const char *objects[] = // Also a mapping to UIC. { "text", "title", "shadow", "bglight", "bgmed", "bgdark", "borhigh", "bormed", "borlow", "help", NULL }; int i; for(i = 0; objects[i]; ++i) if(!stricmp(argv[1], objects[i])) { ui_colors[i].red = strtod(argv[2], 0); ui_colors[i].green = strtod(argv[3], 0); ui_colors[i].blue = strtod(argv[4], 0); return true; } Con_Printf("Unknown UI object '%s'.\n", argv[1]); return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/net_msg.c0000644000175000017500000001270711357170242022540 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_msg.c: Network Messaging * * Buffer overflow checks *ARE NOT* made ifndef _DEBUG * The caller must know what it's doing. * The data is stored using little-endian ordering. * * Note that negative values are not good for the packed write/read routines, * as they always have the high bits set. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_network.h" #ifdef _DEBUG # include "de_console.h" #endif // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void Msg_Begin(int type) { netBuffer.cursor = netBuffer.msg.data; netBuffer.length = 0; netBuffer.msg.type = type; } void Msg_WriteByte(byte b) { *netBuffer.cursor++ = b; } void Msg_WriteShort(short w) { *(short *) netBuffer.cursor = SHORT(w); netBuffer.cursor += 2; } /** * Only 15 bits can be used for the number because the high bit of the * lower byte is used to determine whether the upper byte follows or not. */ void Msg_WritePackedShort(short w) { if(w < 0) { Con_Error("Msg_WritePackedShort: Cannot write %i.\n", w); } // Can the number be represented with 7 bits? if(w < 0x80) { Msg_WriteByte(w); } else { Msg_WriteByte(0x80 | (w & 0x7f)); Msg_WriteByte(w >> 7); // Highest bit is lost. } } void Msg_WriteLong(int l) { *(int *) netBuffer.cursor = LONG(l); netBuffer.cursor += 4; } void Msg_WritePackedLong(uint l) { while(l >= 0x80) { // Write the lowest 7 bits, and set the high bit to indicate that // at least one more byte will follow. Msg_WriteByte(0x80 | (l & 0x7f)); l >>= 7; } // Write the last byte, with the high bit clear. Msg_WriteByte(l); } void Msg_Write(const void *src, size_t len) { memcpy(netBuffer.cursor, src, len); netBuffer.cursor += len; } byte Msg_ReadByte(void) { #ifdef _DEBUG if(Msg_Offset() >= netBuffer.length) Con_Error("Msg_ReadByte: Packet read overflow!\n"); #endif return *netBuffer.cursor++; } short Msg_ReadShort(void) { #ifdef _DEBUG if(Msg_Offset() >= netBuffer.length) Con_Error("Msg_ReadShort: Packet read overflow!\n"); #endif netBuffer.cursor += 2; return SHORT( *(short *) (netBuffer.cursor - 2) ); } /** * Only 15 bits can be used for the number because the high bit of the * lower byte is used to determine whether the upper byte follows or not. */ short Msg_ReadPackedShort(void) { ushort pack = *netBuffer.cursor++; if(pack & 0x80) { pack &= ~0x80; pack |= (*netBuffer.cursor++) << 7; } return pack; } int Msg_ReadLong(void) { #ifdef _DEBUG if(Msg_Offset() >= netBuffer.length) Con_Error("Msg_ReadLong: Packet read overflow!\n"); #endif netBuffer.cursor += 4; return LONG( *(int *) (netBuffer.cursor - 4) ); } uint Msg_ReadPackedLong(void) { byte pack = 0; int pos = 0; uint value = 0; do { #ifdef _DEBUG if(Msg_Offset() >= netBuffer.length) Con_Error("Msg_ReadPackedLong: Packet read overflow!\n"); #endif pack = *netBuffer.cursor++; value |= ((pack & 0x7f) << pos); pos += 7; } while(pack & 0x80); return value; } void Msg_Read(void *dest, size_t len) { #ifdef _DEBUG if(Msg_Offset() >= netBuffer.length) Con_Error("Msg_Read: Packet read overflow!\n"); #endif memcpy(dest, netBuffer.cursor, len); netBuffer.cursor += len; } size_t Msg_Offset(void) { return netBuffer.cursor - netBuffer.msg.data; } void Msg_SetOffset(size_t offset) { netBuffer.cursor = netBuffer.msg.data + offset; } size_t Msg_MemoryLeft(void) { return NETBUFFER_MAXDATA - (netBuffer.cursor - netBuffer.msg.data); } boolean Msg_End(void) { if((size_t) (netBuffer.cursor - netBuffer.msg.data) >= netBuffer.length) return true; return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_direc.c0000644000175000017500000001665111357170242023072 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_direc.c: Directory Utilities * * Directory and file system related stuff. */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #if defined(WIN32) # include #endif #if defined(UNIX) # include #endif #include "de_platform.h" #if defined(WIN32) # include #endif #if defined(UNIX) # include # include # include # include #endif #include #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void Dir_GetDir(directory_t *dir) { memset(dir, 0, sizeof(*dir)); dir->drive = _getdrive(); _getcwd(dir->path, 255); if(LAST_CHAR(dir->path) != DIR_SEP_CHAR) strcat(dir->path, DIR_SEP_STR); /* VERBOSE2( printf("Dir_GetDir: %s\n", dir->path) ); */ } int Dir_ChDir(directory_t* dir) { int success; _chdrive(dir->drive); success = !_chdir(dir->path); // Successful if == 0. VERBOSE2(Con_Printf ("Dir_ChDir: %s: %s\n", success ? "Succeeded" : "Failed", M_PrettyPath(dir->path))); return success; } void Dir_MakeDir(const char* path, directory_t* dir) { filename_t temp; Dir_FileDir(path, dir); Dir_FileName(temp, path, FILENAME_T_MAXLEN); strncat(dir->path, temp, FILENAME_T_MAXLEN); // Make it a well formed path. Dir_ValidDir(dir->path, FILENAME_T_MAXLEN); } /** * Translates the given filename (>,} => basedir). */ void Dir_FileDir(const char* str, directory_t* dir) { filename_t temp, pth; if(!str) { // Nothing to do. return; } M_TranslatePath(pth, str, FILENAME_T_MAXLEN); _fullpath(temp, pth, FILENAME_T_MAXLEN); _splitpath(temp, dir->path, pth, 0, 0); strncat(dir->path, pth, FILENAME_T_MAXLEN); #ifdef WIN32 dir->drive = toupper(dir->path[0]) - 'A' + 1; #endif } void Dir_FileName(char* name, const char* str, size_t len) { char ext[100]; _splitpath(str, 0, 0, name, ext); strncat(name, ext, len); } /** * Calculate an identifier for the file based on its full path name. * The identifier is the MD5 hash of the path. */ void Dir_FileID(const char *str, byte identifier[16]) { filename_t temp; md5_ctx_t context; // First normalize the name. memset(temp, 0, FILENAME_T_MAXLEN); _fullpath(temp, str, FILENAME_T_MAXLEN); Dir_FixSlashes(temp, FILENAME_T_MAXLEN); #if defined(WIN32) || defined(MACOSX) // This is a case insensitive operation. strupr(temp); #endif md5_init(&context); md5_update(&context, (byte*) temp, (unsigned int) strlen(temp)); md5_final(&context, identifier); } /** * @return @c true, if the directories are equal. */ boolean Dir_IsEqual(directory_t *a, directory_t *b) { if(a->drive != b->drive) return false; return !stricmp(a->path, b->path); } /** * @return @c true, if the given path is absolute * (starts with \ or / or the second character is * a ':' (drive). */ int Dir_IsAbsolute(const char* str) { if(!str) return 0; if(str[0] == '\\' || str[0] == '/' || str[1] == ':') return true; #ifdef UNIX if(str[0] == '~') return true; #endif return false; } /** * Converts directory slashes to the correct type of slash. */ void Dir_FixSlashes(char* path, size_t len) { size_t i; for(i = 0; i < len && path[i]; ++i) { if(path[i] == DIR_WRONG_SEP_CHAR) path[i] = DIR_SEP_CHAR; } } #ifdef UNIX /** * If the path begins with a tilde, replace it with either the value * of the HOME environment variable or a user's home directory (from * passwd). * * @param str Path to expand. Overwritten by the result. * @param len Maximum length of str. */ void Dir_ExpandHome(char* str, size_t len) { ddstring_t *buf = NULL; if(str[0] != '~') return; buf = Str_New(); if(str[1] == '/') { // Replace it with the HOME environment variable. Str_Set(buf, getenv("HOME")); if(Str_RAt(buf, 0) != '/') Str_Append(buf, "/"); // Append the rest of the original path. Str_Append(buf, str + 2); } else { char userName[PATH_MAX], *end = NULL; struct passwd *pw; end = strchr(str + 1, '/'); strncpy(userName, str, end - str - 1); userName[end - str - 1] = 0; if((pw = getpwnam(userName)) != NULL) { Str_Set(buf, pw->pw_dir); if(Str_RAt(buf, 0) != '/') Str_Append(buf, "/"); } Str_Append(buf, str + 1); } // Replace the original. str[len - 1] = 0; strncpy(str, Str_Text(buf), len - 1); Str_Free(buf); } #endif /** * Appends a backslash, if necessary. Also converts forward slashes into * backward ones. Does not check if the directory actually exists, just * that it's a well-formed path name. */ void Dir_ValidDir(char* str, size_t len) { char* end; if(!len) return; // Nothing to do. Dir_FixSlashes(str, len); // Remove whitespace from the end. end = str + strlen(str) - 1; while(end >= str && isspace(*end)) end--; memset(end + 1, 0, len - (end - str) - 2); // Make sure it ends in a directory separator character. if(*end != DIR_SEP_CHAR) strncat(end + 1, DIR_SEP_STR, len - (end - str) - 2); #ifdef UNIX Dir_ExpandHome(str, len); #endif } /** * Converts a possibly relative path to a full path. */ void Dir_MakeAbsolute(char* path, size_t len) { filename_t buf; _fullpath(buf, path, FILENAME_T_MAXLEN); strncpy(path, buf, len); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dgl_common.c0000644000175000017500000005532111357170242023221 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dgl_common.c: */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // FUNCTION PROTOTYPES ----------------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void GL_SetGrayMipmap(int lev) { GL_state_texture.grayMipmapFactor = lev / 255.0f; } /** * Set the currently active GL texture unit by ident. * * @param texture GL texture unit ident to make active. */ void GL_ActiveTexture(const GLenum texture) { #ifdef WIN32 if(!glActiveTextureARB) return; glActiveTextureARB(texture); #else # ifdef USE_MULTITEXTURE glActiveTextureARB(texture); # endif #endif } /** * Requires a texture environment mode that can add and multiply. * Nvidia's and ATI's appropriate extensions are supported, other cards will * not be able to utilize multitextured lights. */ void envAddColoredAlpha(int activate, GLenum addFactor) { if(activate) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_state_ext.nvTexEnvComb ? GL_COMBINE4_NV : GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); // Combine: texAlpha * constRGB + 1 * prevRGB. if(GL_state_ext.nvTexEnvComb) { glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, addFactor); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_ZERO); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_ONE_MINUS_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_RGB_NV, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_RGB_NV, GL_SRC_COLOR); } else if(GL_state_ext.atiTexEnvComb) { // MODULATE_ADD_ATI: Arg0 * Arg2 + Arg1. glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE_ADD_ATI); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, addFactor); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); } else { // This doesn't look right. glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_ADD); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, addFactor); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); } } else { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } } /** * Setup the texture environment for single-pass multiplicative lighting. * The last texture unit is always used for the texture modulation. * TUs 1...n-1 are used for dynamic lights. */ void envModMultiTex(int activate) { // Setup TU 2: The modulated texture. GL_ActiveTexture(GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); // Setup TU 1: The dynamic light. GL_ActiveTexture(GL_TEXTURE0); envAddColoredAlpha(activate, GL_SRC_ALPHA); // This is a single-pass mode. The alpha should remain unmodified // during the light stage. if(activate) { // Replace: primAlpha. glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); } } /** * Configure the GL state for the specified texture modulation mode. * * @param mode Modulation mode ident. */ void GL_ModulateTexture(int mode) { switch(mode) { case 0: // No modulation: just replace with texture. GL_ActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); break; case 1: // Normal texture modulation with primary color. GL_ActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); break; case 12: // Normal texture modulation on both stages. TU 1 modulates with // primary color, TU 2 with TU 1. GL_ActiveTexture(GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); GL_ActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); break; case 2: case 3: // Texture modulation and interpolation. GL_ActiveTexture(GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); if(mode == 2) { // Used with surfaces that have a color. // TU 2: Modulate previous with primary color. glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PRIMARY_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); } else { // Mode 3: Used with surfaces with no primary color. // TU 2: Pass through. glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); } glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); // TU 1: Interpolate between texture 1 and 2, using the constant // alpha as the factor. GL_ActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_INTERPOLATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_RGB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); break; case 4: // Apply sector light, dynamic light and texture. envModMultiTex(true); break; case 5: case 10: // Sector light * texture + dynamic light. GL_ActiveTexture(GL_TEXTURE1); envAddColoredAlpha(true, mode == 5 ? GL_SRC_ALPHA : GL_SRC_COLOR); // Alpha remains unchanged. if(GL_state_ext.nvTexEnvComb) { glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_ADD); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_ZERO); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_ALPHA, GL_ZERO); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND2_ALPHA, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE3_ALPHA_NV, GL_ZERO); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND3_ALPHA_NV, GL_SRC_ALPHA); } else { glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); } GL_ActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); break; case 6: // Simple dynlight addition (add to primary color). GL_ActiveTexture(GL_TEXTURE0); envAddColoredAlpha(true, GL_SRC_ALPHA); break; case 7: // Dynlight addition without primary color. GL_ActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_CONSTANT); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); break; case 8: case 9: // Texture and Detail. GL_ActiveTexture(GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 2); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); GL_ActiveTexture(GL_TEXTURE0); if(mode == 8) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else { // Mode 9: Ignore primary color. glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); } break; case 11: // Normal modulation, alpha of 2nd stage. // Tex0: texture // Tex1: shiny texture GL_ActiveTexture(GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); GL_ActiveTexture(GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE1); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_TEXTURE0); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA, GL_SRC_ALPHA); break; default: break; } } void GL_BlendOp(int op) { #ifndef UNIX if(!glBlendEquationEXT) return; #endif glBlendEquationEXT(op); } boolean GL_Grab(int x, int y, int width, int height, dgltexformat_t format, void *buffer) { if(format != DGL_RGB) return false; // y+height-1 is the bottom edge of the rectangle. It's // flipped to change the origin. glReadPixels(x, FLIP(y + height - 1), width, height, GL_RGB, GL_UNSIGNED_BYTE, buffer); return true; } void GL_EnableTexUnit(byte id) { GL_ActiveTexture(GL_TEXTURE0 + id); glEnable(GL_TEXTURE_2D); } void GL_DisableTexUnit(byte id) { GL_ActiveTexture(GL_TEXTURE0 + id); glDisable(GL_TEXTURE_2D); // Implicit disabling of texcoord array. if(GL_state.noArrays) { GL_DisableArrays(0, 0, 1 << id); } } /** * The first selected unit is active after this call. */ void GL_SelectTexUnits(int count) { int i; // Disable extra units. for(i = numTexUnits - 1; i >= count; i--) GL_DisableTexUnit(i); // Enable the selected units. for(i = count - 1; i >= 0; i--) { if(i >= numTexUnits) continue; GL_EnableTexUnit(i); } } void GL_SetTextureCompression(boolean on) { GL_state.allowCompression = on; } void GL_SetVSync(boolean on) { #ifdef WIN32 if(GL_state_ext.wglSwapIntervalEXT) { wglSwapIntervalEXT(on? 1 : 0); GL_state.useVSync = on; } #endif } void GL_SetMultisample(boolean on) { #if WIN32 if(on) glEnable(GL_MULTISAMPLE_ARB); else glDisable(GL_MULTISAMPLE_ARB); #endif } void DGL_Scissor(int x, int y, int width, int height) { glScissor(x, FLIP(y + height - 1), width, height); } boolean DGL_GetIntegerv(int name, int *v) { int i; float color[4]; switch(name) { case DGL_MODULATE_ADD_COMBINE: *v = GL_state_ext.nvTexEnvComb || GL_state_ext.atiTexEnvComb; break; case DGL_SCISSOR_TEST: glGetIntegerv(GL_SCISSOR_TEST, (GLint*) v); break; case DGL_SCISSOR_BOX: glGetIntegerv(GL_SCISSOR_BOX, (GLint*) v); v[1] = FLIP(v[1] + v[3] - 1); break; case DGL_FOG: *v = GL_state.useFog; break; case DGL_CURRENT_COLOR_R: glGetFloatv(GL_CURRENT_COLOR, color); *v = (int) (color[0] * 255); break; case DGL_CURRENT_COLOR_G: glGetFloatv(GL_CURRENT_COLOR, color); *v = (int) (color[1] * 255); break; case DGL_CURRENT_COLOR_B: glGetFloatv(GL_CURRENT_COLOR, color); *v = (int) (color[2] * 255); break; case DGL_CURRENT_COLOR_A: glGetFloatv(GL_CURRENT_COLOR, color); *v = (int) (color[3] * 255); break; case DGL_CURRENT_COLOR_RGBA: glGetFloatv(GL_CURRENT_COLOR, color); for(i = 0; i < 4; i++) v[i] = (int) (color[i] * 255); break; default: return false; } return true; } int DGL_GetInteger(int name) { int values[10]; DGL_GetIntegerv(name, values); return values[0]; } boolean DGL_SetInteger(int name, int value) { switch(name) { case DGL_ACTIVE_TEXTURE: GL_ActiveTexture(GL_TEXTURE0 + (byte) value); break; case DGL_MODULATE_TEXTURE: GL_ModulateTexture(value); break; default: return false; } return true; } float DGL_GetFloat(int name) { switch(name) { case DGL_LINE_WIDTH: return GL_state.currentLineWidth; case DGL_POINT_SIZE: return GL_state.currentPointSize; default: return 0; } return 1; } boolean DGL_SetFloat(int name, float value) { switch(name) { case DGL_LINE_WIDTH: GL_state.currentLineWidth = value; glLineWidth(value); break; case DGL_POINT_SIZE: GL_state.currentPointSize = value; glPointSize(value); break; default: return false; } return true; } void DGL_EnableTexUnit(byte id) { GL_EnableTexUnit(id); } void DGL_DisableTexUnit(byte id) { GL_DisableTexUnit(id); } int DGL_Enable(int cap) { switch(cap) { case DGL_TEXTURING: #ifndef DRMESA glEnable(GL_TEXTURE_2D); #endif break; case DGL_FOG: glEnable(GL_FOG); GL_state.useFog = true; break; case DGL_SCISSOR_TEST: glEnable(GL_SCISSOR_TEST); break; case DGL_LINE_SMOOTH: glEnable(GL_LINE_SMOOTH); break; case DGL_POINT_SMOOTH: glEnable(GL_POINT_SMOOTH); break; default: return 0; } return 1; } void DGL_Disable(int cap) { switch(cap) { case DGL_TEXTURING: glDisable(GL_TEXTURE_2D); break; case DGL_FOG: glDisable(GL_FOG); GL_state.useFog = false; break; case DGL_SCISSOR_TEST: glDisable(GL_SCISSOR_TEST); break; case DGL_LINE_SMOOTH: glDisable(GL_LINE_SMOOTH); break; case DGL_POINT_SMOOTH: glDisable(GL_POINT_SMOOTH); break; default: break; } } void DGL_BlendOp(int op) { GL_BlendOp(op == DGL_SUBTRACT ? GL_FUNC_SUBTRACT : op == DGL_REVERSE_SUBTRACT ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD); } void DGL_BlendFunc(int param1, int param2) { glBlendFunc(param1 == DGL_ZERO ? GL_ZERO : param1 == DGL_ONE ? GL_ONE : param1 == DGL_DST_COLOR ? GL_DST_COLOR : param1 == DGL_ONE_MINUS_DST_COLOR ? GL_ONE_MINUS_DST_COLOR : param1 == DGL_SRC_ALPHA ? GL_SRC_ALPHA : param1 == DGL_ONE_MINUS_SRC_ALPHA ? GL_ONE_MINUS_SRC_ALPHA : param1 == DGL_DST_ALPHA ? GL_DST_ALPHA : param1 == DGL_ONE_MINUS_DST_ALPHA ? GL_ONE_MINUS_DST_ALPHA : param1 == DGL_SRC_ALPHA_SATURATE ? GL_SRC_ALPHA_SATURATE : GL_ZERO, param2 == DGL_ZERO ? GL_ZERO : param2 == DGL_ONE ? GL_ONE : param2 == DGL_SRC_COLOR ? GL_SRC_COLOR : param2 == DGL_ONE_MINUS_SRC_COLOR ? GL_ONE_MINUS_SRC_COLOR : param2 == DGL_SRC_ALPHA ? GL_SRC_ALPHA : param2 == DGL_ONE_MINUS_SRC_ALPHA ? GL_ONE_MINUS_SRC_ALPHA : param2 == DGL_DST_ALPHA ? GL_DST_ALPHA : param2 == DGL_ONE_MINUS_DST_ALPHA ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO); } void DGL_BlendMode(blendmode_t mode) { GL_BlendMode(mode); } void DGL_MatrixMode(int mode) { glMatrixMode(mode == DGL_PROJECTION ? GL_PROJECTION : mode == DGL_TEXTURE ? GL_TEXTURE : GL_MODELVIEW); } void DGL_PushMatrix(void) { glPushMatrix(); #if _DEBUG if(glGetError() == GL_STACK_OVERFLOW) Con_Error("DG_PushMatrix: Stack overflow.\n"); #endif } void DGL_SetMaterial(material_t* mat) { GL_SetMaterial(mat); } void DGL_SetNoMaterial(void) { GL_SetNoTexture(); } void DGL_SetPatch(lumpnum_t lump, int wrapS, int wrapT) { GL_SetPatch(lump, (wrapS == DGL_CLAMP? GL_CLAMP : wrapS == DGL_CLAMP_TO_EDGE? GL_CLAMP_TO_EDGE : GL_REPEAT), (wrapT == DGL_CLAMP? GL_CLAMP : wrapT == DGL_CLAMP_TO_EDGE? GL_CLAMP_TO_EDGE : GL_REPEAT)); } void DGL_SetTranslatedSprite(material_t* mat, int tclass, int tmap) { GL_SetTranslatedSprite(mat, tclass, tmap); } void DGL_SetPSprite(material_t* mat) { GL_SetPSprite(mat); } void DGL_SetRawImage(lumpnum_t lump, boolean part2, int wrapS, int wrapT) { GL_SetRawImage(lump, part2, (wrapS == DGL_CLAMP? GL_CLAMP : wrapS == DGL_CLAMP_TO_EDGE? GL_CLAMP_TO_EDGE : GL_REPEAT), (wrapT == DGL_CLAMP? GL_CLAMP : wrapT == DGL_CLAMP_TO_EDGE? GL_CLAMP_TO_EDGE : GL_REPEAT)); } void DGL_PopMatrix(void) { glPopMatrix(); #if _DEBUG if(glGetError() == GL_STACK_UNDERFLOW) Con_Error("DG_PopMatrix: Stack underflow.\n"); #endif } void DGL_LoadIdentity(void) { glLoadIdentity(); } void DGL_Translatef(float x, float y, float z) { glTranslatef(x, y, z); } void DGL_Rotatef(float angle, float x, float y, float z) { glRotatef(angle, x, y, z); } void DGL_Scalef(float x, float y, float z) { glScalef(x, y, z); } void DGL_Ortho(float left, float top, float right, float bottom, float znear, float zfar) { glOrtho(left, right, bottom, top, znear, zfar); } void DGL_DeleteTextures(int num, const DGLuint *names) { if(!num || !names) return; glDeleteTextures(num, (const GLuint*) names); } int DGL_Bind(DGLuint texture) { glBindTexture(GL_TEXTURE_2D, texture); #ifdef _DEBUG Sys_CheckGLError(); #endif return 0; } #if 0 // Currently unused. int DGL_Project(int num, dgl_fc3vertex_t *inVertices, dgl_fc3vertex_t *outVertices) { GLdouble modelMatrix[16], projMatrix[16]; GLint viewport[4]; GLdouble x, y, z; int i, numOut; dgl_fc3vertex_t *in = inVertices, *out = outVertices; if(num == 0) return 0; // Get the data we'll need in the operation. glGetDoublev(GL_MODELVIEW_MATRIX, modelMatrix); glGetDoublev(GL_PROJECTION_MATRIX, projMatrix); glGetIntegerv(GL_VIEWPORT, viewport); for(i = numOut = 0; i < num; ++i, in++) { if(gluProject (in->pos[VX], in->pos[VY], in->pos[VZ], modelMatrix, projMatrix, viewport, &x, &y, &z) == GL_TRUE) { // A success: add to the out vertices. out->pos[VX] = (float) x; out->pos[VY] = (float) FLIP(y); out->pos[VZ] = (float) z; // Check that it's truly visible. if(out->pos[VX] < 0 || out->pos[VY] < 0 || out->pos[VX] >= theWindow->width || out->pos[VY] >= theWindow->height) continue; memcpy(out->color, in->color, sizeof(in->color)); numOut++; out++; } } return numOut; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_clip.c0000644000175000017500000011237611357170242023046 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_clip.c: Clipper * * Clipnodes and oranges. * * The idea is to keep track of occluded angles around the camera. * Since subsectors are rendered front-to-back, the occlusion lists * start a frame empty and eventually fill up to cover the whole 360 * degrees around the camera. * * Oranges (occlusion ranges) clip a half-space on an angle range. * These are produced by horizontal edges that have empty space behind. */ // HEADER FILES ------------------------------------------------------------ #ifdef _DEBUG # include #endif #include #include "de_base.h" #include "de_console.h" #include "de_render.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define OCNF_TOPHALF 0x2 // Otherwise bottom half. // TYPES ------------------------------------------------------------------- typedef struct rovernode_s { struct rovernode_s *next, *prev; } rovernode_t; typedef struct rover_s { rovernode_t *first; rovernode_t *last; rovernode_t *rover; } rover_t; typedef struct clipnode_s { rovernode_t rover; struct clipnode_s *prev, *next; // Previous and next nodes. binangle_t start, end; // The start and end angles } clipnode_t; // (start < end). typedef struct occnode_s { rovernode_t rover; struct occnode_s *next, *prev; byte flags; // Used and tophalf. binangle_t start, end; // Start and end angles of the segment (snext); if(i > maxnumnodes) maxnumnodes = i; } static int C_CountUsedOranges(void) { int cnt; occnode_t *orange; for(cnt = 0, orange = occHead; orange; orange = orange->next, cnt++); return cnt; } #endif */ void C_RoverInit(rover_t *rover) { memset(rover, 0, sizeof(*rover)); } void C_RoverRewind(rover_t *r) { r->rover = r->first; } void *C_RoverGet(rover_t *r) { void *node; if(!r->rover) return NULL; // We'll use this. node = r->rover; r->rover = r->rover->next; return node; } void C_RoverAdd(rover_t *r, void *node) { // Link it to the start of the rover's list. if(!r->last) r->last = node; if(r->first) r->first->prev = node; ((rovernode_t*) node)->next = r->first; ((rovernode_t*) node)->prev = NULL; r->first = node; } void C_RoverRemove(rover_t *r, void *node) { #ifdef _DEBUG assert(r->last != NULL); #endif if(node == r->last) { #ifdef _DEBUG assert(r->rover == NULL); #endif // We can only remove the last if all nodes are already in use. r->rover = node; } else { // Unlink from the list entirely. ((rovernode_t*) node)->next->prev = ((rovernode_t*) node)->prev; if(((rovernode_t*) node)->prev) { ((rovernode_t*) node)->prev->next = ((rovernode_t*) node)->next; } else { r->first = r->first->next; r->first->prev = NULL; } // Put it back to the end of the list. r->last->next = node; ((rovernode_t*) node)->prev = r->last; ((rovernode_t*) node)->next = NULL; r->last = node; // If all were in use, set the rover here. Otherwise the rover // can stay where it is. if(!r->rover) r->rover = r->last; } } void C_Init(void) { C_RoverInit(&clipNodes); C_RoverInit(&occNodes); } void C_ClearRanges(void) { clipHead = NULL; // Rewind the rover. C_RoverRewind(&clipNodes); occHead = NULL; // Rewind the rover. C_RoverRewind(&occNodes); } /** * Finds the first unused clip node. */ static clipnode_t *C_NewRange(binangle_t stAng, binangle_t endAng) { clipnode_t *node; if((node = C_RoverGet(&clipNodes)) == NULL) { // Allocate a new node and add it to head the list. node = Z_Malloc(sizeof(clipnode_t), PU_STATIC, NULL); C_RoverAdd(&clipNodes, node); } // Initialize the node. node->start = stAng; node->end = endAng; node->prev = node->next = NULL; return node; } static void C_RemoveRange(clipnode_t *node) { // If this is the head, move it. if(clipHead == node) clipHead = node->next; // Unlink from the clipper. if(node->prev) node->prev->next = node->next; if(node->next) node->next->prev = node->prev; node->prev = node->next = 0; // Move this node to the free node rover. C_RoverRemove(&clipNodes, node); } static void C_AddRange(binangle_t startAngle, binangle_t endAngle) { clipnode_t *ci, *crange; // This range becomes a solid segment: cut everything away from the // corresponding occlusion range. C_CutOcclusionRange(startAngle, endAngle); // If there is no head, this will be the first range. if(!clipHead) { clipHead = C_NewRange(startAngle, endAngle); /* #if _DEBUG printf( " new head node added, %x => %x\n", clipHead->start, clipHead->end); #endif */ return; } // There are previous ranges. Check that the new range isn't contained // by any of them. for(ci = clipHead; ci; ci = ci->next) { /* #if _DEBUG printf( " %p: %4x => %4x (%d)\n",ci,ci->start,ci->end,ci->used); #endif */ if(startAngle >= ci->start && endAngle <= ci->end) { /* #if _DEBUG printf( " range already exists\n"); #endif */ return; // The new range already exists. } /* #if _DEBUG printf( "loop1\n"); if(ci == ci->next) Con_Error("%p linked to itself: %x => %x\n",ci,ci->start,ci->end); #endif */ } // Now check if any of the old ranges are contained by the new one. for(ci = clipHead; ci;) { /* #if _DEBUG printf( "loop2\n"); #endif */ if(ci->start >= startAngle && ci->end <= endAngle) { crange = ci; /* #if _DEBUG //printf( " removing contained range %x => %x\n",crange->start,crange->end); #endif */ // We must do this in order to keep the loop from breaking. ci = ci->next; C_RemoveRange(crange); //if(!ci) ci = clipHead; //if(!ci) break; continue; } ci = ci->next; } // Now it is possible that the new range overlaps one or two old ranges. // If two are overlapped, they are consecutive. First we'll try to find // a range that overlaps the beginning. for(crange = 0, ci = clipHead; ci; ci = ci->next) { // In preparation for the next stage, find a good spot for the range. if(ci->start < endAngle) crange = ci; // Add after this one. /* #if _DEBUG printf( "loop3\n"); #endif */ if(ci->start >= startAngle && ci->start <= endAngle) { // New range's end and ci's beginning overlap. ci's end is outside. // Otherwise it would have been already removed. // It suffices to adjust ci. /* #if _DEBUG printf( " overlapping beginning with %x => %x, ",ci->start,ci->end); #endif */ ci->start = startAngle; /* #if _DEBUG printf( "adjusting ci to %x => %x\n",ci->start,ci->end); #endif */ return; } // Check an overlapping end. if(ci->end >= startAngle && ci->end <= endAngle) { // Now it's possible that the ci->next's beginning overlaps the new // range's end. In that case there will be a merger. /* #if _DEBUG printf( " overlapping end with %x => %x:\n",ci->start,ci->end); #endif */ crange = ci->next; if(!crange) { ci->end = endAngle; /* #if _DEBUG printf( " no next, adjusting end (now %x => %x)\n",ci->start,ci->end); #endif */ } else { if(crange->start <= endAngle) { // A fusion will commence. Ci will eat the new range // *and* crange. ci->end = crange->end; /* #if _DEBUG printf( " merging with the next (%x => %x)\n",crange->start,crange->end); #endif */ C_RemoveRange(crange); } else { // Not overlapping. ci->end = endAngle; /* #if _DEBUG printf( " not merger w/next, ci is now %x => %x\n",ci->start,ci->end); #endif */ } } return; } } // Still here? Now we know for sure that the range is disconnected from // the others. We still need to find a good place for it. Crange will mark // the spot. if(!crange) { // We have a new head node. crange = clipHead; clipHead = C_NewRange(startAngle, endAngle); clipHead->next = crange; if(crange) crange->prev = clipHead; } else { // Add the new range after crange. ci = C_NewRange(startAngle, endAngle); ci->next = crange->next; if(ci->next) ci->next->prev = ci; ci->prev = crange; crange->next = ci; } } occnode_t *C_NewOcclusionRange(binangle_t stAng, binangle_t endAng, float *normal, boolean topHalf) { occnode_t *node; if((node = C_RoverGet(&occNodes)) == NULL) { // Allocate a new node. node = Z_Malloc(sizeof(occnode_t), PU_STATIC, NULL); C_RoverAdd(&occNodes, node); } node->flags = (topHalf ? OCNF_TOPHALF : 0); node->start = stAng; node->end = endAng; memcpy(node->normal, normal, sizeof(node->normal)); return node; } void C_RemoveOcclusionRange(occnode_t *orange) { // If this is the head, move it to the next one. if(occHead == orange) occHead = orange->next; if(orange->prev) orange->prev->next = orange->next; if(orange->next) orange->next->prev = orange->prev; C_RoverRemove(&occNodes, orange); } /** * The given range must be safe. */ void C_AddOcclusionRange(binangle_t start, binangle_t end, float *normal, boolean topHalf) { occnode_t *orange = NULL, *newor = NULL, *last = NULL; boolean done; // Is the range valid? if(start > end) return; // A new range will be added. newor = C_NewOcclusionRange(start, end, normal, topHalf); // Are there any previous occlusion nodes? if(!occHead) { // No; this is the first. occHead = newor; occHead->next = occHead->prev = NULL; return; } // \fixme An optimization: remove existing oranges that are fully // contained by the new orange. But how to do the check efficiently? // Add the new occlusion range to the appropriate position. orange = occHead; done = false; while(orange && !done) { // The list of oranges is sorted by the start angle. // Find the first range whose start is greater than the new one. if(orange->start > start) { // Add before this one. newor->next = orange; newor->prev = orange->prev; orange->prev = newor; if(newor->prev) newor->prev->next = newor; else occHead = newor; // We have a new head. done = true; } else { last = orange; orange = orange->next; } } if(done) return; // All right, add the new range to the end of the list. last->next = newor; newor->prev = last; newor->next = NULL; } #if _DEBUG void C_OrangeRanger(int mark) { occnode_t *orange; for(orange = occHead; orange; orange = orange->next) if(orange->prev && orange->prev->start > orange->start) Con_Error("C_OrangeRanger(%i): Orange order has failed.\n", mark); } void C_OcclusionLister(char *title) { occnode_t *orange; printf("*** %s:\n", title); for(orange = occHead; orange; orange = orange->next) printf(" %04x-%04x (%i)\n", orange->start, orange->end, (orange->flags & OCNF_TOPHALF) != 0); } #endif /** * Attempts to merge the two given occnodes. * * @return 0: Could not be merged. * 1: orange was merged into other. * 2: other was merged into orange. */ static int C_TryMergeOccludes(occnode_t *orange, occnode_t *other) { binangle_t crossAngle; float cross[3]; // We can't test this steep planes. if(!orange->normal[VZ]) return 0; // Where do they cross? M_CrossProduct(orange->normal, other->normal, cross); if(!cross[VX] && !cross[VY] && !cross[VZ]) { // These two planes are exactly the same! Remove one. C_RemoveOcclusionRange(orange); return 1; } // The cross angle must be outside the range. crossAngle = bamsAtan2((int) cross[VY], (int) cross[VX]); if(crossAngle >= orange->start && crossAngle <= orange->end) return 0; // Crosses inside the range, can't do a thing. // \fixme Isn't it possible to consistently determine which // direction the cross vector is pointing to? crossAngle += BANG_180; if(crossAngle >= orange->start && crossAngle <= orange->end) return 0; // Crosses inside the range, can't do a thing. // Now we must determine which plane occludes which. // Pick a point in the middle of the range. crossAngle = (orange->start + orange->end) >> (1 + BAMS_BITS - 13); cross[VX] = 100 * FIX2FLT(fineCosine[crossAngle]); cross[VY] = 100 * FIX2FLT(finesine[crossAngle]); // z = -(A*x+B*y)/C cross[VZ] = -(orange->normal[VX] * cross[VX] + orange->normal[VY] * cross[VY]) / orange->normal[VZ]; // Is orange occluded by the other one? if(M_DotProduct(cross, other->normal) < 0) { // No; then the other one is occluded by us. // Remove it instead. C_RemoveOcclusionRange(other); return 2; } else { C_RemoveOcclusionRange(orange); return 1; } } /** * Try to merge oranges with matching ranges. (Quite a number may be * produced as a result of the cuts.) */ void C_MergeOccludes(void) { occnode_t *orange, *next, *other; boolean stopScan, isDone; orange = occHead; stopScan = false; while(!stopScan) { if(orange && orange->next) { next = orange->next; // Find a good one to test with. isDone = false; other = orange->next; while(!isDone) { if(other && orange->start == other->start) { if(orange->end == other->end && (other->flags & OCNF_TOPHALF) == (orange->flags & OCNF_TOPHALF)) { // It is a candidate for merging. int result = C_TryMergeOccludes(orange, other); if(result == 2) next = next->next; isDone = true; } else { // Move on to the next candidate. other = other->next; } } else isDone = true; } orange = next; } else stopScan = true; } } /** * Everything in the given range is removed from the occlusion nodes. */ void C_CutOcclusionRange(binangle_t startAngle, binangle_t endAngle) { occnode_t *orange, *next, *after, *part; boolean isDone; #if _DEBUG C_OrangeRanger(1); #endif // Find the node after which it's OK to add oranges cut in half. // (Must preserve the ascending order of the start angles.) after = NULL; orange = occHead; isDone = false; while(!isDone) { // We want the orange with the smallest start angle, but one that // starts after the cut range has ended. if(orange && orange->start < endAngle) { after = orange; } else isDone = true; if(!isDone) orange = orange->next; } orange = occHead; isDone = false; while(!isDone) { if(orange) { // In case orange is removed, take a copy of the next one. next = orange->next; // Does the cut range include this orange? if(startAngle <= orange->end) { if(orange->start < endAngle) { #define C_O_RELATIONSHIP(start, startangle, end, endangle) (( \ (start >= startAngle && end <= endAngle)? 0: \ (start >= startAngle && start < endAngle)? 1: \ (end > startAngle && end <= endAngle)? 2: \ (start <= startAngle && end >= endAngle)? 3: -1)) // Four options: switch(C_O_RELATIONSHIP(orange->start, startAngle, orange->end, endAngle)) { case 0: // The cut range completely includes this orange. // Fully contained; this orange will be removed. C_RemoveOcclusionRange(orange); break; case 1: // The cut range contains the beginning of the orange. // Cut away the beginning of this orange. orange->start = endAngle; // Even thought the start angle is modified, we don't need to // move this orange anywhere. This is because after the cut there // will be no oranges beginning inside the cut range. break; case 2: // The cut range contains the end of the orange. // Cut away the end of this orange. orange->end = startAngle; break; case 3: // The orange contains the whole cut range. // The orange gets cut in two parts. Create a new orange that // represents the end, and add it after the 'after' node, or to // the head of the list. part = C_NewOcclusionRange(endAngle, orange->end, orange->normal, (orange->flags & OCNF_TOPHALF) != 0); part->prev = after; if(after) { part->next = after->next; after->next = part; } else { // Add to the head. part->next = occHead; occHead = part; } if(part->next) part->next->prev = part; // Modify the start part. orange->end = startAngle; break; default: // No meaningful relationship (in this context). break; } } else isDone = true; // No more possible cuts. } if(!isDone) orange = next; } else isDone = true; } #if _DEBUG C_OrangeRanger(2); #endif C_MergeOccludes(); #if _DEBUG C_OrangeRanger(6); #endif } /** * A debugging aid: checks if clipnode links are valid. */ #if _DEBUG void C_Ranger(void) { clipnode_t *ci; //printf("Ranger:\n"); for(ci = clipHead; ci; ci = ci->next) { if(ci == clipHead) { if(ci->prev != 0) Con_Error("Cliphead->prev != 0.\n"); } // Confirm that the links to prev and next are OK. if(ci->prev) { if(ci->prev->next != ci) Con_Error("Prev->next != this\n"); } else if(ci != clipHead) { Con_Error("prev == null, this isn't clipHead.\n"); } if(ci->next) { if(ci->next->prev != ci) Con_Error("Next->prev != this\n"); } } } #endif int C_SafeAddRange(binangle_t startAngle, binangle_t endAngle) { // The range may wrap around. if(startAngle > endAngle) { // The range has to added in two parts. C_AddRange(startAngle, BANG_MAX); C_AddRange(0, endAngle); } else { // Add the range as usual. C_AddRange(startAngle, endAngle); } return true; } /** * Add a segment relative to the current viewpoint. */ void C_AddViewRelSeg(float x1, float y1, float x2, float y2) { float dx1 = x1 - vx; float dy1 = y1 - vz; float dx2 = x2 - vx; float dy2 = y2 - vz; C_SafeAddRange(bamsAtan2((int) (dy2 * 100), (int) (dx2 * 100)), bamsAtan2((int) (dy1 * 100), (int) (dx1 * 100))); } /** * If necessary, cut the given range in two. */ void C_SafeAddOcclusionRange(binangle_t startAngle, binangle_t endAngle, float *normal, boolean tophalf) { // Is this range already clipped? if(!C_SafeCheckRange(startAngle, endAngle)) return; // Already clipped. if(startAngle > endAngle) { // The range has to added in two parts. C_AddOcclusionRange(startAngle, BANG_MAX, normal, tophalf); #if _DEBUG C_OrangeRanger(3); #endif C_AddOcclusionRange(0, endAngle, normal, tophalf); #if _DEBUG C_OrangeRanger(4); #endif } else { // Add the range as usual. C_AddOcclusionRange(startAngle, endAngle, normal, tophalf); #if _DEBUG C_OrangeRanger(5); #endif } } /** * The point should be view-relative! */ binangle_t C_PointToAngle(float *point) { return bamsAtan2((int) (point[VY] * 100), (int) (point[VX] * 100)); } /** * Add an occlusion segment relative to the current viewpoint. */ void C_AddViewRelOcclusion(float *v1, float *v2, float height, boolean tophalf) { float viewtov1[3], viewtov2[3]; float normal[3]; // \fixme Optimization? Check if the given line is already occluded. // Calculate the occlusion plane normal. We'll use the game's coordinate // system (left-handed, but Y and Z are swapped). viewtov1[VX] = v1[VX] - vx; viewtov1[VY] = v1[VY] - vz; viewtov2[VX] = v2[VX] - vx; viewtov2[VY] = v2[VY] - vz; viewtov1[VZ] = viewtov2[VZ] = height - vy; // The normal points to the half we want to occlude. M_CrossProduct(tophalf ? viewtov2 : viewtov1, tophalf ? viewtov1 : viewtov2, normal); #if _DEBUG { float testPos[3]; testPos[0] = 0; testPos[1] = 0; testPos[2] = (tophalf ? 1000 : -1000); if(M_DotProduct(testPos, normal) < 0) { Con_Error("C_AddViewRelOcclusion: Wrong side - [%g,%g]>[%g,%g] " "view[%g,%g]!\n", v1[VX], v1[VY], v2[VX], v2[VY], vx, vz); } } #endif C_SafeAddOcclusionRange(C_PointToAngle(viewtov2), C_PointToAngle(viewtov1), normal, tophalf); } /** * Returns true if the view relative point is occluded by an occlusion * range. */ boolean C_IsPointOccluded(float *viewrelpoint) { binangle_t angle = C_PointToAngle(viewrelpoint); occnode_t *orange; for(orange = occHead; orange; orange = orange->next) { if(angle >= orange->start && angle <= orange->end) { if(orange->start > angle) return false; // No more possibilities. // On which side of the occlusion plane is it? The positive side // is the occluded one. if(M_DotProduct(viewrelpoint, orange->normal) > 0) return true; // Occluded! } } // No orange occluded the point. return false; } /** * Returns true if the point is visible after checking both the clipnodes * and the occlusion planes. Note that this test can only be done with * points that reside in subsectors that have not yet been rendered. */ boolean C_IsPointVisible(float x, float y, float height) { float point[3]; binangle_t angle; point[0] = x - vx; point[1] = y - vz; point[2] = height - vy; angle = C_PointToAngle(point); if(!C_IsAngleVisible(angle)) return false; // The point was not clipped by the clipnodes. Perhaps it's occluded // by an orange. return !C_IsPointOccluded(point); } /** * NOTE: Unused and untested. Almost certainly doesn't work correctly. */ boolean C_IsSegOccluded(float relv1[3], float relv2[3], float reltop, float relbottom, binangle_t startAngle, binangle_t endAngle) { // The segment is always fully occluded from startAngle to occAngle. float cross[3], testNormal[3]; binangle_t occAngle, crossAngle, trueStart, trueEnd; occnode_t *orange; clipnode_t *ci; boolean side1, side2, isSafe; // See if the given actual test range is safe. (startAngle and endAngle // always are.) trueStart = C_PointToAngle(relv2); trueEnd = C_PointToAngle(relv1); isSafe = (trueStart < trueEnd); // startAngle and endAngle are the real, safe range. It's first clipped // by any available clipnodes. We already know that no clipnode fully // contains the test range. for(ci = clipHead; ci; ci = ci->next) { // Does this clipnode partially overlap the test range? if(startAngle >= ci->start && startAngle <= ci->end) { // Start of the test range gets clipped. startAngle = ci->end; } if(endAngle >= ci->start && endAngle <= ci->end) { // End of the test range gets clipped. endAngle = ci->start; } } // In the beginning we have occluded nothing, i.e. up to the start angle. occAngle = startAngle; for(orange = occHead; orange; orange = orange->next) { if(occAngle >= endAngle) return true; // Fully occluded. // This is the quickest way out of there: if we come across an // occlusion range that begins AFTER the occAngle, the portion // in between obviously won't be occluded by anybody (since oranges // are sorted by ascending start angles). if(orange->start > occAngle) return false; if(orange->end < occAngle) continue; // Useless... /* if(orange->end < startAngle) continue; // Doesn't overlap. if(orange->start > endAngle) break; // The rest are past the end. */ // This orange overlaps the test range. Let's determine the test // plane we will be using. if(orange->flags & OCNF_TOPHALF) { // Tophalf is occluded, so test with the bottom of the seg. relv1[VZ] = relv2[VZ] = relbottom; } else { // Bottomhalf is occluded, so test with the top of the seg. relv1[VZ] = relv2[VZ] = reltop; } // Side=true means 'occluded'. Note that side2's angle is smaller // than side1's. side1 = M_DotProduct(relv1, orange->normal) > 0; side2 = M_DotProduct(relv2, orange->normal) > 0; if(side1 && side2) { // Does the orange fully contain the remaining portion of the seg? if(occAngle >= orange->start && endAngle <= orange->end) return true; // Fully occluded by this orange! // Both the start and end vertex of the seg are occluded by // this orange, but the orange doesn't cover the whole seg. if(orange->end > occAngle) occAngle = orange->end; // Now we know that the seg has been occluded from the beginning // to occAngle. continue; // Find more juicy oranges. } if(!side1 && !side2) { // This orange does not fully overlap the seg. Let's hope that // some other orange will. continue; } // The test plane crosses the occlusion plane somewhere inside the // seg (because the endpoints of the test seg were at different sides // of the occlusion plane). Calculate the normal of the test plane. M_CrossProduct(relv1, relv2, testNormal); // Calculate the angle of the cross line. M_CrossProduct(testNormal, orange->normal, cross); crossAngle = C_PointToAngle(cross); if(isSafe) { if(crossAngle < trueStart || crossAngle > trueEnd) { crossAngle += BANG_180; // Flip over. if(crossAngle < trueStart || crossAngle > trueEnd) Con_Error("Cross line behaves strangely(1) " "(st=%x end=%x crs=%x).\n", trueStart, trueEnd, crossAngle); } } else { if(crossAngle < trueStart && crossAngle > trueEnd) { crossAngle += BANG_180; if(crossAngle < trueStart && crossAngle > trueEnd) Con_Error("Cross line behaves strangely(2) " "(st=%x end=%x crs=%x).\n", trueStart, trueEnd, crossAngle); } } // Remember, side2 has a smaller angle. // \fixme What about trueStart/trueEnd!!! and isSafe! it must have // an effect on this... if(side2) { // We have an occlusion up to the cross point. if(crossAngle > occAngle) occAngle = crossAngle; } else // if(side1) { // We have an occlusion starting from crossAngle. if(crossAngle <= occAngle) // The occlusion begins before or at the currently // occluded portion. if(orange->end > occAngle) occAngle = orange->end; } } // If the occlusion happened up to the end angle, we're OK. return (occAngle >= endAngle); } /** * Returns true if the segment is visible according to the current * clipnode and occlusion information. */ boolean C_CheckSeg(float *v1, float *v2, float top, float bottom) { float relv1[3], relv2[3]; float reltop = top - vy, relbottom = bottom - vy; binangle_t start, end; relv1[0] = v1[VX] - vx; relv1[1] = v1[VY] - vz; relv1[2] = 0; relv2[0] = v2[VX] - vx; relv2[1] = v2[VY] - vz; relv2[2] = 0; // Determine the range. start = C_PointToAngle(relv2); end = C_PointToAngle(relv1); if(start == end) return true; // Might as well be visible... if(!C_SafeCheckRange(start, end)) return false; // Entirely clipped. // Now the more difficult part... The range may be occluded by a number // of occlusion ranges, but we must determine whether these occlude the // segment fully, in 3D. if(start < end) { // The range doesn't wrap around. return !C_IsSegOccluded(relv1, relv2, reltop, relbottom, start, end); } // The range wraps around. return !C_IsSegOccluded(relv1, relv2, reltop, relbottom, start, BANG_MAX) || !C_IsSegOccluded(relv1, relv2, reltop, relbottom, 0, end); } /** * The specified range must be safe! */ static int C_IsRangeVisible(binangle_t startAngle, binangle_t endAngle) { clipnode_t *ci; for(ci = clipHead; ci; ci = ci->next) if(startAngle >= ci->start && endAngle <= ci->end) return false; // No node fully contained the specified range. return true; } /** * Returns 1 if the range is not entirely clipped. */ static int C_SafeCheckRange(binangle_t startAngle, binangle_t endAngle) { if(startAngle > endAngle) { // The range wraps around. return (C_IsRangeVisible(startAngle, BANG_MAX) || C_IsRangeVisible(0, endAngle)); } return C_IsRangeVisible(startAngle, endAngle); } int C_CheckViewRelSeg(float x1, float y1, float x2, float y2) { float dx1 = x1 - vx; float dy1 = y1 - vz; float dx2 = x2 - vx; float dy2 = y2 - vz; if(devNoCulling) return 1; return C_SafeCheckRange(bamsAtan2((int) (dy2 * 100), (int) (dx2 * 100)), bamsAtan2((int) (dy1 * 100), (int) (dx1 * 100))); } /** * Returns true if the specified angle is visible. */ int C_IsAngleVisible(binangle_t bang) { clipnode_t *ci; for(ci = clipHead; ci; ci = ci->next) if(bang > ci->start && bang < ci->end) return false; // No one clipped this angle. return true; } clipnode_t *C_AngleClippedBy(binangle_t bang) { clipnode_t *ci; for(ci = clipHead; ci; ci = ci->next) if(bang > ci->start && bang < ci->end) return ci; // No one clipped this angle. return 0; } /** * @return Non-zero if the subsector might be visible. */ int C_CheckSubsector(subsector_t *ssec) { uint i; seg_t **ptr; if(!ssec || ssec->segCount < 3) return 0; if(devNoCulling) return 1; // Do we need to resize the angle list buffer? if(ssec->segCount > anglistSize) { anglistSize *= 2; if(!anglistSize) anglistSize = 64; anglist = Z_Realloc(anglist, sizeof(binangle_t) * anglistSize, PU_STATIC); } ptr = ssec->segs; i = 0; while(*ptr) // Angles to all corners. { vertex_t *vtx = (*ptr)->SG_v1; // Shift for more accuracy. anglist[i++] = bamsAtan2((int) ((vtx->V_pos[VY] - vz) * 100), (int) ((vtx->V_pos[VX] - vx) * 100)); *ptr++; } // Check each of the ranges defined by the edges. for(i = 0; i < ssec->segCount - 1; ++i) { uint end = i + 1; binangle_t angLen; // The last edge won't be checked. This is because the edges // define a closed, convex polygon and the last edge's range is // always already covered by the previous edges. (Right?) // If even one of the edges is not contained by a clipnode, // the subsector is at least partially visible. angLen = anglist[end] - anglist[i]; // The viewer is on an edge, the subsector should be visible. if(angLen == BANG_180) return 1; // Choose the start and end points so that length is < 180. if(angLen < BANG_180) { if(C_SafeCheckRange(anglist[i], anglist[end])) return 1; } else { if(C_SafeCheckRange(anglist[end], anglist[i])) return 1; } } // All clipped away, the subsector cannot be seen. return 0; } /** * Returns true if clipnodes cover the whole range [0,360] degrees. */ boolean C_IsFull(void) { if(devNoCulling) return false; return clipHead && clipHead->start == 0 && clipHead->end == BANG_MAX; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_oldframe.c0000644000175000017500000000734111357170241023350 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_frame.c: Obsolete Frame Reception * * This file contains obsolete delta routines. They are preserved so that * backwards compatibility is retained with older versions of the network * protocol. * * These routines should be considered FROZEN. Do not change them. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" // MACROS ------------------------------------------------------------------ #define BIT(x) (1 << (x)) #define MAX_ACKS 40 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int gotFrame; extern int predicted_tics; extern boolean gotFirstFrame; // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int num_acks; static byte acks[MAX_ACKS]; // CODE -------------------------------------------------------------------- /** * Read and ack a PSV_FRAME delta set. * * THIS FUNCTION IS OBSOLETE (PSV_FRAME is no longer used) */ void Cl_ReadDeltaSet(void) { byte present = Msg_ReadByte(); byte set = Msg_ReadByte(); // Add the set number to the list of acks. if(num_acks < MAX_ACKS) acks[num_acks++] = set; if(present & BIT(DT_MOBJ)) while(Cl_ReadMobjDelta()); if(present & BIT(DT_PLAYER)) while(Cl_ReadPlayerDelta()); if(present & BIT(DT_LUMP)) while(Cl_ReadLumpDelta()); if(present & BIT(DT_SECTOR_R6)) while(Cl_ReadSectorDelta()); if(present & BIT(DT_SIDE_R6)) while(Cl_ReadSideDelta()); if(present & BIT(DT_POLY)) while(Cl_ReadPolyDelta()); } /** * Reads a PSV_FRAME packet from the message buffer and applies the deltas * in it. Also acks the sets in the packet immediately. * * THIS FUNCTION IS OBSOLETE (PSV_FRAME is no longer used) */ void Cl_FrameReceived(void) { int i, frametime; gotFrame = true; gotFirstFrame = true; #if _DEBUG if(!gameReady) Con_Message("Got frame but GAME NOT READY!\n"); #endif // Frame time, lowest byte of gametic. frametime = Msg_ReadByte(); num_acks = 0; while(!Msg_End()) Cl_ReadDeltaSet(); // Acknowledge all sets. Msg_Begin(PCL_ACK_SETS); for(i = 0; i < num_acks; ++i) Msg_WriteByte(acks[i]); Net_SendBuffer(0, 0); // Reset the predict counter. predicted_tics = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dgl_texture.c0000644000175000017500000006634611357170242023442 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dgl_texture.c: Textures and color palette handling. * * Get OpenGL header files from: * http://oss.sgi.com/projects/ogl-sample/ */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define RGB18(r, g, b) ((r)+((g)<<6)+((b)<<12)) // TYPES ------------------------------------------------------------------- // Color Palette Flags (CPF): #define CPF_UPDATE_18TO8 0x1 // The 18To8 table needs updating. typedef struct { ushort num; byte flags; // CPF_* flags. DGLubyte* data; // R8G8B8 color triplets, [num * 3]. ushort* pal18To8; // 262144 unique mappings. } gl_colorpalette_t; // FUNCTION PROTOTYPES ----------------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- gl_state_texture_t GL_state_texture; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static gl_colorpalette_t* colorPalettes = NULL; static DGLuint numColorPalettes = 0; // CODE -------------------------------------------------------------------- static void loadPalette(const gl_colorpalette_t* pal) { if(GL_state_texture.usePalTex) { int i; byte paldata[256 * 3]; byte* buf; if(pal->num > 256) buf = malloc(pal->num * 3); else buf = paldata; // Prepare the color table. for(i = 0; i < pal->num; ++i) { // Adjust the values for the appropriate gamma level. buf[i * 3] = gammaTable[pal->data[i * 3]]; buf[i * 3 + 1] = gammaTable[pal->data[i * 3 + 1]]; buf[i * 3 + 2] = gammaTable[pal->data[i * 3 + 2]]; } glColorTableEXT(GL_TEXTURE_2D, GL_RGB, pal->num, GL_RGB, GL_UNSIGNED_BYTE, paldata); if(pal->num > 256) free(buf); } } boolean GL_EnablePalTexExt(boolean enable) { if(!GL_state.palExtAvailable) { Con_Message("GL_EnablePalTexExt: No paletted texture support.\n"); return false; } if((enable && GL_state_texture.usePalTex) || (!enable && !GL_state_texture.usePalTex)) return true; if(!enable && GL_state_texture.usePalTex) { GL_state_texture.usePalTex = false; #ifdef WIN32 glColorTableEXT = NULL; #endif return true; } GL_state_texture.usePalTex = false; #ifdef WIN32 if((glColorTableEXT = (PFNGLCOLORTABLEEXTPROC) wglGetProcAddress("glColorTableEXT")) == NULL) { Con_Message("drOpenGL.GL_EnablePalTexExt: getProcAddress failed.\n"); return false; } #endif GL_state_texture.usePalTex = true; // Palette will be loaded separately for each texture. Con_Message("drOpenGL.GL_EnablePalTexExt: Using tex palette.\n"); return true; } /** * Prepares an 18 to 8 bit quantization table from the specified palette. * Finds the color index that most closely resembles this RGB combination. * * \note A time-consuming operation (64 * 64 * 64 * 256!). */ static void prepareColorPalette18To8(gl_colorpalette_t* pal) { if((pal->flags & CPF_UPDATE_18TO8) || !pal->pal18To8) { #define SIZEOF18TO8 (sizeof(ushort) * 262144) // \fixme Too big? int r, g, b; ushort closestIndex = 0; if(!pal->pal18To8) { pal->pal18To8 = Z_Malloc(SIZEOF18TO8, PU_STATIC, 0); } for(r = 0; r < 64; ++r) { for(g = 0; g < 64; ++g) { for(b = 0; b < 64; ++b) { ushort i; int smallestDiff = DDMAXINT; for(i = 0; i < pal->num; ++i) { int diff; const DGLubyte* rgb = &pal->data[i * 3]; diff = (rgb[CR] - (r << 2)) * (rgb[CR] - (r << 2)) + (rgb[CG] - (g << 2)) * (rgb[CG] - (g << 2)) + (rgb[CB] - (b << 2)) * (rgb[CB] - (b << 2)); if(diff < smallestDiff) { smallestDiff = diff; closestIndex = i; } } pal->pal18To8[RGB18(r, g, b)] = closestIndex; } } } pal->flags &= ~CPF_UPDATE_18TO8; /*if(ArgCheck("-dump_pal18to8")) { filename_t name; FILE* file; dd_snprintf(name, FILENAME_T_MAXLEN, "%s_18To8.lmp", pal->name); file = fopen(name, "wb"); fwrite(pal->pal18To8, SIZEOF18TO8, 1, file); fclose(file); }*/ #undef SIZEOF18TO8 } } static void readBits(byte* out, const byte** src, byte* cb, uint numBits) { int offset = 0, unread = numBits; // Read full bytes. if(unread >= 8) { do { out[offset++] = **src, (*src)++; } while((unread -= 8) >= 8); } if(unread != 0) { // Read remaining bits. byte fb = 8 - unread; if((*cb) == 0) (*cb) = 8; do { (*cb)--; out[offset] <<= 1; out[offset] |= ((**src >> (*cb)) & 0x01); } while(--unread > 0); out[offset] <<= fb; if((*cb) == 0) (*src)++; } } /** * @param compOrder Component order. Examples: * [0,1,2] == RGB * [2,1,0] == BGR * @param compSize Number of bits per component [R,G,B]. */ DGLuint GL_CreateColorPalette(const int compOrder[3], const byte compSize[3], const byte* data, ushort num) { gl_colorpalette_t* pal; byte order[3], bits[3]; // Ensure input is in range. order[0] = MINMAX_OF(0, compOrder[0], 2); order[1] = MINMAX_OF(0, compOrder[1], 2); order[2] = MINMAX_OF(0, compOrder[2], 2); bits[CR] = MIN_OF(compSize[CR], 32); bits[CG] = MIN_OF(compSize[CG], 32); bits[CB] = MIN_OF(compSize[CB], 32); // Allocate a new color palette and data buffer. colorPalettes = Z_Realloc(colorPalettes, ++numColorPalettes * sizeof(*pal), PU_STATIC); pal = &colorPalettes[numColorPalettes-1]; pal->num = num; pal->data = Z_Malloc(pal->num * sizeof(DGLubyte) * 3, PU_STATIC, 0); /** * Copy the source data and convert to R8G8B8 in the process. */ // First, see if the source data is already in the format we want. if(bits[CR] == 8 && bits[CG] == 8 && bits[CB] == 8) { // Great! Just copy it as-is. memcpy(pal->data, data, pal->num * 3); // Do we need to adjust the order? if(order[CR] != 0 || order[CG] != 1 || order[CB] != 2) { uint i; for(i = 0; i < pal->num; ++i) { byte* dst = &pal->data[i * 3]; byte tmp[3]; tmp[0] = dst[0]; tmp[1] = dst[1]; tmp[2] = dst[2]; dst[CR] = tmp[order[CR]]; dst[CG] = tmp[order[CG]]; dst[CB] = tmp[order[CB]]; } } } else { // Another format entirely. uint i; byte cb = 0; const byte* src = data; for(i = 0; i < pal->num; ++i) { byte* dst = &pal->data[i * 3]; int tmp[3]; tmp[CR] = tmp[CG] = tmp[CB] = 0; readBits((byte*) &(tmp[order[CR]]), &src, &cb, bits[order[CR]]); readBits((byte*) &(tmp[order[CG]]), &src, &cb, bits[order[CG]]); readBits((byte*) &(tmp[order[CB]]), &src, &cb, bits[order[CB]]); // Need to do any scaling? if(bits[CR] != 8) { if(bits[CR] < 8) tmp[CR] <<= 8 - bits[CR]; else tmp[CR] >>= bits[CR] - 8; } if(bits[CG] != 8) { if(bits[CG] < 8) tmp[CG] <<= 8 - bits[CG]; else tmp[CG] >>= bits[CG] - 8; } if(bits[CB] != 8) { if(bits[CB] < 8) tmp[CB] <<= 8 - bits[CB]; else tmp[CB] >>= bits[CB] - 8; } // Store the final color. dst[CR] = MINMAX_OF(0, tmp[CR], 255); dst[CG] = MINMAX_OF(0, tmp[CG], 255); dst[CB] = MINMAX_OF(0, tmp[CB], 255); } } // We defer creation of the 18 to 8 translation table as it may not // be needed depending on what this palette is used for. pal->flags = CPF_UPDATE_18TO8; pal->pal18To8 = NULL; return numColorPalettes; // 1-based index. } void GL_DeleteColorPalettes(DGLsizei n, const DGLuint* palettes) { DGLsizei i; if(!(n > 0) || !palettes) return; for(i = 0; i < n; ++i) { if(palettes[i] != 0 && palettes[i] - 1 < numColorPalettes) { uint idx = palettes[i]-1; gl_colorpalette_t* pal = &colorPalettes[idx]; Z_Free(pal->data); if(pal->pal18To8) Z_Free(pal->pal18To8); memmove(&colorPalettes[idx], &colorPalettes[idx+1], sizeof(*pal)); numColorPalettes--; } } if(numColorPalettes) { colorPalettes = Z_Realloc(colorPalettes, numColorPalettes * sizeof(gl_colorpalette_t), PU_STATIC); } else { Z_Free(colorPalettes); colorPalettes = NULL; } } void GL_GetColorPaletteRGB(DGLuint id, DGLubyte rgb[3], ushort idx) { if(id != 0 && id - 1 < numColorPalettes) { const gl_colorpalette_t* pal = &colorPalettes[id-1]; if(idx >= pal->num) VERBOSE( Con_Message("GL_GetColorPaletteRGB: Warning, color idx %u " "out of range in palette %u.\n", idx, id)) idx = MINMAX_OF(0, idx, pal->num-1) * 3; rgb[CR] = pal->data[idx]; rgb[CG] = pal->data[idx + 1]; rgb[CB] = pal->data[idx + 2]; } } boolean GL_PalettizeImage(byte* out, int outformat, DGLuint palid, boolean gammaCorrect, const byte* in, int informat, int width, int height) { if(out && in && width > 0 && height > 0 && informat <= 2 && outformat >= 3 && palid && palid - 1 < numColorPalettes) { int i, numPixels = width * height, inSize = (informat == 2 ? 1 : informat), outSize = (outformat == 2 ? 1 : outformat); const gl_colorpalette_t* pal = &colorPalettes[palid-1]; for(i = 0; i < numPixels; ++i, in += inSize, out += outSize) { ushort idx = MINMAX_OF(0, (*in), pal->num) * 3; if(gammaCorrect) { out[CR] = gammaTable[pal->data[idx]]; out[CG] = gammaTable[pal->data[idx + 1]]; out[CB] = gammaTable[pal->data[idx + 2]]; } else { out[CR] = pal->data[idx]; out[CG] = pal->data[idx + 1]; out[CB] = pal->data[idx + 2]; } // Will the alpha channel be necessary? if(outformat == 4) { if(informat == 2) out[3] = in[numPixels * inSize]; else out[3] = 0; } } return true; } return false; } boolean GL_QuantizeImageToPalette(byte* out, int outformat, DGLuint palid, const byte* in, int informat, int width, int height) { if(in && out && informat >= 3 && outformat <= 2 && width > 0 && height > 0 && palid && palid - 1 < numColorPalettes) { gl_colorpalette_t* pal = &colorPalettes[palid-1]; int i, numPixels = width * height, inSize = (informat == 2 ? 1 : informat), outSize = (outformat == 2 ? 1 : outformat); // Ensure we've prepared the 18 to 8 table. prepareColorPalette18To8(pal); for(i = 0; i < numPixels; ++i, in += inSize, out += outSize) { // Convert the color value. *out = pal->pal18To8[RGB18(in[0] >> 2, in[1] >> 2, in[2] >> 2)]; // Alpha channel? if(outformat == 2) { if(informat == 4) out[numPixels * outSize] = in[3]; else out[numPixels * outSize] = 0; } } return true; } return false; } /** * Desaturates the texture in the dest buffer by averaging the colour then * looking up the nearest match in the palette. Increases the brightness * to maximum. */ void GL_DeSaturatePalettedImage(byte* buffer, DGLuint palid, int width, int height) { int i, max; const int numpels = width * height; const gl_colorpalette_t* pal; if(!buffer || !palid || palid - 1 >= numColorPalettes) return; if(width == 0 || height == 0) return; // Nothing to do. // Ensure we've prepared the 18 to 8 table. prepareColorPalette18To8(&colorPalettes[palid-1]); pal = &colorPalettes[palid-1]; // What is the maximum color value? max = 0; for(i = 0; i < numpels; ++i) { const DGLubyte* rgb = &pal->data[ MINMAX_OF(0, buffer[i], pal->num) * 3]; int temp; temp = (2 * (int)rgb[CR] + 4 * (int)rgb[CG] + 3 * (int)rgb[CB]) / 9; if(temp > max) max = temp; } for(i = 0; i < numpels; ++i) { const DGLubyte* rgb = &pal->data[ MINMAX_OF(0, buffer[i], pal->num) * 3]; int temp; // Calculate a weighted average. temp = (2 * (int)rgb[CR] + 4 * (int)rgb[CG] + 3 * (int)rgb[CB]) / 9; if(max) temp *= 255.f / max; buffer[i] = pal->pal18To8[RGB18(temp >> 2, temp >> 2, temp >> 2)]; } } /** * Choose an internal texture format based on the number of color * components. * * @param comps Number of color components. * @return The internal texture format. */ GLenum ChooseFormat(int comps) { boolean compress = (GL_state_texture.useCompr && GL_state.allowCompression); switch(comps) { case 1: // Luminance return compress ? GL_COMPRESSED_LUMINANCE : GL_LUMINANCE; case 3: // RGB return !compress ? 3 : GL_state_ext.s3TC ? GL_COMPRESSED_RGB_S3TC_DXT1_EXT : GL_COMPRESSED_RGB; case 4: // RGBA return !compress ? 4 : GL_state_ext.s3TC ? GL_COMPRESSED_RGBA_S3TC_DXT3_EXT // >1-bit alpha : GL_COMPRESSED_RGBA; default: Con_Error("drOpenGL.ChooseFormat: Unsupported comps: %i.", comps); } // The fallback. return comps; } int GL_GetTexAnisoMul(int level) { int mul = 1; // Should anisotropic filtering be used? if(GL_state.useAnisotropic) { if(level < 0) { // Go with the maximum! mul = GL_state.maxAniso; } else { // Convert from a DGL aniso level to a multiplier. // i.e 0 > 1, 1 > 2, 2 > 4, 3 > 8, 4 > 16 switch(level) { case 0: mul = 1; break; // x1 (normal) case 1: mul = 2; break; // x2 case 2: mul = 4; break; // x4 case 3: mul = 8; break; // x8 case 4: mul = 16; break; // x16 default: // Wha? mul = 1; break; } // Clamp. if(mul > GL_state.maxAniso) mul = GL_state.maxAniso; } } return mul; } /** * Works within the given data, reducing the size of the picture to half * its original. * * @param width Width of the final texture, must be power of two. * @param height Height of the final texture, must be power of two. */ void downMip8(byte *in, byte *fadedOut, int width, int height, float fade) { byte *out = in; int x, y, outW = width / 2, outH = height / 2; float invFade; if(fade > 1) fade = 1; invFade = 1 - fade; if(width == 1 && height == 1) { // Nothing can be done. return; } if(!outW || !outH) { // Limited, 1x2|2x1 -> 1x1 reduction? int outDim = (width > 1 ? outW : outH); for(x = 0; x < outDim; x++, in += 2) { *out = (in[0] + in[1]) / 2; *fadedOut++ = (byte) (*out * invFade + 0x80 * fade); out++; } } else { // Unconstrained, 2x2 -> 1x1 reduction? for(y = 0; y < outH; y++, in += width) for(x = 0; x < outW; x++, in += 2) { *out = (in[0] + in[1] + in[width] + in[width + 1]) / 4; *fadedOut++ = (byte) (*out * invFade + 0x80 * fade); out++; } } } boolean grayMipmap(dgltexformat_t format, int width, int height, void *data) { byte *image, *in, *out, *faded; int i, numLevels, w, h, size = width * height, res; uint comps = (format == DGL_LUMINANCE? 1 : 3); float invFactor = 1 - GL_state_texture.grayMipmapFactor; // Buffer used for the faded texture. faded = M_Malloc(size / 4); image = M_Malloc(size); // Initial fading. if(format == DGL_LUMINANCE || format == DGL_RGB) { for(i = 0, in = data, out = image; i < size; ++i, in += comps) { res = (int) (*in * GL_state_texture.grayMipmapFactor + 0x80 * invFactor); // Clamp to [0, 255]. if(res < 0) res = 0; if(res > 255) res = 255; *out++ = res; } } // How many levels will there be? for(numLevels = 0, w = width, h = height; w > 1 || h > 1; w /= 2, h /= 2, numLevels++); // We do not want automatical mipmaps. if(GL_state_ext.genMip) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_FALSE); // Upload the first level right away. glTexImage2D(GL_TEXTURE_2D, 0, ChooseFormat(1), width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, image); // Generate all mipmaps levels. for(i = 0, w = width, h = height; i < numLevels; ++i) { downMip8(image, faded, w, h, (i * 1.75f) / numLevels); // Go down one level. if(w > 1) w /= 2; if(h > 1) h /= 2; glTexImage2D(GL_TEXTURE_2D, i + 1, ChooseFormat(1), w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, faded); } // Do we need to free the temp buffer? M_Free(faded); M_Free(image); if(GL_state.useAnisotropic) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(-1 /*best*/)); return true; } /** * @param format DGL texture format symbolic, one of: * DGL_RGB * DGL_RGBA * DGL_COLOR_INDEX_8 * DGL_COLOR_INDEX_8_PLUS_A8 * DGL_LUMINANCE * @param palid Id of the color palette to use with this texture. * Only has meaning if the input format is one of: * DGL_COLOR_INDEX_8 * DGL_COLOR_INDEX_8_PLUS_A8 * @param width Width of the texture, must be power of two. * @param height Height of the texture, must be power of two. * @param genMips If negative, sets a specific mipmap level, * e.g. @c -1, means mipmap level 1. * @param data Ptr to the texture data. * * @return @c true iff successful. */ boolean GL_TexImage(dgltexformat_t format, DGLuint palid, int width, int height, int genMips, void *data) { int mipLevel = 0; byte* bdata = data; // Negative genMips values mean that the specific mipmap level is // being uploaded. if(genMips < 0) { mipLevel = -genMips; genMips = 0; } // Can't operate on the null texture. if(!data) return false; // Check that the texture dimensions are valid. if(!GL_state.textureNonPow2 && (width != M_CeilPow2(width) || height != M_CeilPow2(height))) return false; if(width > GL_state.maxTexSize || height > GL_state.maxTexSize) return false; // If this is a paletted texture, we must know which palette to use. if((format == DGL_COLOR_INDEX_8 || format == DGL_COLOR_INDEX_8_PLUS_A8) && (!palid || palid - 1 >= numColorPalettes)) return false; // Special fade-to-gray luminance texture? (used for details) if(genMips == DDMAXINT) { return grayMipmap(format, width, height, data); } // Automatic mipmap generation? if(GL_state_ext.genMip && genMips) glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); // Paletted texture? if(GL_state_texture.usePalTex && format == DGL_COLOR_INDEX_8) { if(genMips && !GL_state_ext.genMip) { // Build mipmap textures. gluBuild2DMipmaps(GL_TEXTURE_2D, GL_COLOR_INDEX8_EXT, width, height, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); } else { // The texture has no mipmapping. glTexImage2D(GL_TEXTURE_2D, mipLevel, GL_COLOR_INDEX8_EXT, width, height, 0, GL_COLOR_INDEX, GL_UNSIGNED_BYTE, data); } // Load palette, too. loadPalette(&colorPalettes[palid-1]); } else { // Use true color textures. int alphachannel = ((format == DGL_RGBA) || (format == DGL_COLOR_INDEX_8_PLUS_A8) || (format == DGL_LUMINANCE_PLUS_A8)); int i, colorComps = alphachannel ? 4 : 3; int numPixels = width * height; byte *buffer; byte *pixel, *in; boolean needFree = false; int loadFormat = GL_RGBA; // Convert to either RGB or RGBA, if necessary. if(format == DGL_RGBA) { buffer = data; } // A bug in Nvidia's drivers? Very small RGBA textures don't load // properly. else if(format == DGL_RGB && width > 2 && height > 2) { buffer = data; loadFormat = GL_RGB; } else { // Needs converting. // \fixme This adds some overhead. needFree = true; buffer = M_Malloc(numPixels * 4); if(!buffer) return false; switch(format) { case DGL_RGB: for(i = 0, pixel = buffer, in = bdata; i < numPixels; i++, pixel += 4) { pixel[CR] = *in++; pixel[CG] = *in++; pixel[CB] = *in++; pixel[CA] = 255; } break; case DGL_COLOR_INDEX_8: { const gl_colorpalette_t* pal = &colorPalettes[palid]; loadFormat = GL_RGB; for(i = 0, pixel = buffer; i < numPixels; i++, pixel += 3) { const byte* src = &pal->data[MIN_OF(bdata[i], pal->num) * 3]; pixel[CR] = gammaTable[src[CR]]; pixel[CG] = gammaTable[src[CG]]; pixel[CB] = gammaTable[src[CB]]; } break; } case DGL_COLOR_INDEX_8_PLUS_A8: { const gl_colorpalette_t* pal = &colorPalettes[palid]; for(i = 0, pixel = buffer; i < numPixels; i++, pixel += 4) { const byte* src = &pal->data[MIN_OF(bdata[i], pal->num) * 3]; pixel[CR] = gammaTable[src[CR]]; pixel[CG] = gammaTable[src[CG]]; pixel[CB] = gammaTable[src[CB]]; pixel[CA] = bdata[numPixels + i]; } break; } case DGL_LUMINANCE: loadFormat = GL_RGB; for(i = 0, pixel = buffer; i < numPixels; i++, pixel += 3) pixel[CR] = pixel[CG] = pixel[CB] = bdata[i]; break; case DGL_LUMINANCE_PLUS_A8: for(i = 0, pixel = buffer; i < numPixels; i++, pixel += 4) { pixel[CR] = pixel[CG] = pixel[CB] = bdata[i]; pixel[CA] = bdata[numPixels + i]; } break; default: M_Free(buffer); Con_Error("LoadTexture: Unknown format %x.\n", format); break; } } if(genMips && !GL_state_ext.genMip) { // Build all mipmap levels. gluBuild2DMipmaps(GL_TEXTURE_2D, ChooseFormat(colorComps), width, height, loadFormat, GL_UNSIGNED_BYTE, buffer); } else { // The texture has no mipmapping, just one level. glTexImage2D(GL_TEXTURE_2D, mipLevel, ChooseFormat(colorComps), width, height, 0, loadFormat, GL_UNSIGNED_BYTE, buffer); } if(needFree) M_Free(buffer); } #ifdef _DEBUG Sys_CheckGLError(); #endif return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_objlink.c0000644000175000017500000004250211357170242023047 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_objlink.c: Objlink management. * * Object>surface contacts and object>subsector spreading. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_misc.h" #include "de_play.h" #include "de_defs.h" // MACROS ------------------------------------------------------------------ #define X_TO_OBBX(bm, cx) (((cx) - (bm)->origin[0]) >> (FRACBITS+7)) #define Y_TO_OBBY(bm, cy) (((cy) - (bm)->origin[1]) >> (FRACBITS+7)) #define OBB_XY(bm, bx, by) (&(bm)->blocks[(bx) + (by) * (bm)->width]) BEGIN_PROF_TIMERS() PROF_OBJLINK_SPREAD, PROF_OBJLINK_LINK END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- typedef struct objlink_s { struct objlink_s* nextInBlock; // Next in the same obj block, or NULL. struct objlink_s* nextUsed; struct objlink_s* next; // Next in list of ALL objlinks. objtype_t type; void* obj; } objlink_t; typedef struct objblock_s { objlink_t* head; // Used to prevent multiple processing of a block during one refresh frame. boolean doneSpread; } objblock_t; typedef struct objblockmap_s { objblock_t* blocks; fixed_t origin[2]; int width, height; // In blocks. } objblockmap_t; typedef struct contactfinder_data_s { void* obj; objtype_t objType; vec3_t objPos; float objRadius; float box[4]; } contactfinderparams_t; typedef struct objcontact_s { struct objcontact_s* next; // Next in the subsector. struct objcontact_s* nextUsed; // Next used contact. void* obj; } objcontact_t; typedef struct objcontactlist_s { objcontact_t* head[NUM_OBJ_TYPES]; } objcontactlist_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void processSeg(seg_t* seg, void* data); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static objlink_t* objLinks = NULL; static objlink_t* objLinkFirst = NULL, *objLinkCursor = NULL; static objblockmap_t* objBlockmap = NULL; // List of unused and used obj-subsector contacts. static objcontact_t* contFirst = NULL, *contCursor = NULL; // List of obj contacts for each subsector. static objcontactlist_t* subContacts = NULL; // CODE -------------------------------------------------------------------- /** * Link the given objcontact node to list. */ static __inline void linkContact(objcontact_t* con, objcontact_t** list, uint index) { con->next = list[index]; list[index] = con; } static void linkContactToSubSector(objcontact_t* node, objtype_t type, uint index) { linkContact(node, &subContacts[index].head[type], 0); } /** * Create a new objcontact for the given obj. If there are free nodes in * the list of unused nodes, the new contact is taken from there. * * @param obj Ptr to the obj the contact is required for. * * @return Ptr to the new objcontact. */ static objcontact_t* allocObjContact(void) { objcontact_t* con; if(contCursor == NULL) { con = Z_Malloc(sizeof(*con), PU_STATIC, NULL); // Link to the list of objcontact nodes. con->nextUsed = contFirst; contFirst = con; } else { con = contCursor; contCursor = contCursor->nextUsed; } con->obj = NULL; return con; } static objlink_t* allocObjLink(void) { objlink_t* oLink; if(objLinkCursor == NULL) { oLink = Z_Malloc(sizeof(*oLink), PU_STATIC, NULL); // Link to the list of objlink nodes. oLink->nextUsed = objLinkFirst; objLinkFirst = oLink; } else { oLink = objLinkCursor; objLinkCursor = objLinkCursor->nextUsed; } oLink->nextInBlock = NULL; oLink->obj = NULL; // Link it to the list of in-use objlinks. oLink->next = objLinks; objLinks = oLink; return oLink; } objblockmap_t* R_ObjBlockmapCreate(float originX, float originY, int width, int height) { objblockmap_t* obm; obm = Z_Malloc(sizeof(objblockmap_t), PU_MAPSTATIC, 0); // Origin has fixed-point coordinates. obm->origin[0] = FLT2FIX(originX); obm->origin[1] = FLT2FIX(originY); obm->width = width; obm->height = height; obm->blocks = Z_Malloc(sizeof(*obm->blocks) * obm->width * obm->height, PU_MAPSTATIC, 0); return obm; } void R_InitObjLinksForMap(void) { gamemap_t* map = P_GetCurrentMap(); float min[2], max[2]; int width, height; // Determine the dimensions of the objblockmap. P_GetMapBounds(map, &min[0], &max[0]); max[0] -= min[0]; max[1] -= min[1]; // In blocks, 128x128 world units. width = (FLT2FIX(max[0]) >> (FRACBITS + 7)) + 1; height = (FLT2FIX(max[1]) >> (FRACBITS + 7)) + 1; // Create the blockmap. objBlockmap = R_ObjBlockmapCreate(min[0], min[1], width, height); // Initialize obj -> subsector contact lists. subContacts = Z_Calloc(sizeof(*subContacts) * numSSectors, PU_MAPSTATIC, 0); } void R_ObjBlockmapClear(objblockmap_t* obm) { if(obm) { // Clear the list head ptrs and doneSpread flags. memset(obm->blocks, 0, sizeof(*obm->blocks) * obm->width * obm->height); } } /** * Called at the begining of each frame (iff the render lists are not frozen) * by R_BeginWorldFrame(). */ void R_ClearObjLinksForFrame(void) { // Clear all the roots. R_ObjBlockmapClear(objBlockmap); objLinkCursor = objLinkFirst; objLinks = NULL; } void R_ObjLinkCreate(void* obj, objtype_t type) { objlink_t* ol = allocObjLink(); ol->obj = obj; ol->type = type; } boolean RIT_LinkObjToSubSector(subsector_t* subsector, void* data) { linkobjtossecparams_t* params = (linkobjtossecparams_t*) data; objcontact_t* con = allocObjContact(); con->obj = params->obj; // Link the contact list for this subsector. linkContactToSubSector(con, params->type, GET_SUBSECTOR_IDX(subsector)); return true; // Continue iteration. } /** * Attempt to spread the obj from the given contact from the source ssec and * into the (relative) back ssec. * * @param ssec Ptr to subsector to attempt to spread over to. * @param data Ptr to contactfinder_data structure. * * @return @c true, because this function is also used as an * iterator. */ static void spreadInSsec(subsector_t* ssec, void* data) { seg_t** segPtr = ssec->segs; while(*segPtr) processSeg(*segPtr++, data); } static void processSeg(seg_t* seg, void* data) { contactfinderparams_t* params = (contactfinderparams_t*) data; subsector_t* source, *dest; float distance; vertex_t* vtx; // Seg must be between two different ssecs. if(seg->lineDef && (!seg->backSeg || seg->subsector == seg->backSeg->subsector)) return; // Which way does the spread go? if(seg->subsector->validCount == validCount && seg->backSeg->subsector->validCount != validCount) { source = seg->subsector; dest = seg->backSeg->subsector; } else { // Not eligible for spreading. return; } // Is the dest ssector inside the objlink's AABB? if(dest->bBox[1].pos[VX] <= params->box[BOXLEFT] || dest->bBox[0].pos[VX] >= params->box[BOXRIGHT] || dest->bBox[1].pos[VY] <= params->box[BOXBOTTOM] || dest->bBox[0].pos[VY] >= params->box[BOXTOP]) { // The ssector is not inside the params's bounds. return; } // Can the spread happen? if(seg->lineDef) { if(dest->sector) { if(dest->sector->planes[PLN_CEILING]->height <= dest->sector->planes[PLN_FLOOR]->height || dest->sector->planes[PLN_CEILING]->height <= source->sector->planes[PLN_FLOOR]->height || dest->sector->planes[PLN_FLOOR]->height >= source->sector->planes[PLN_CEILING]->height) { // No; destination sector is closed with no height. return; } } // Don't spread if the middle material completely fills the gap between // floor and ceiling (direction is from dest to source). if(Rend_DoesMidTextureFillGap(seg->lineDef, dest == seg->backSeg->subsector? false : true)) return; } // Calculate 2D distance to seg. { float dx, dy; dx = seg->SG_v2pos[VX] - seg->SG_v1pos[VX]; dy = seg->SG_v2pos[VY] - seg->SG_v1pos[VY]; vtx = seg->SG_v1; distance = ((vtx->V_pos[VY] - params->objPos[VY]) * dx - (vtx->V_pos[VX] - params->objPos[VX]) * dy) / seg->length; } if(seg->lineDef) { if((source == seg->subsector && distance < 0) || (source == seg->backSeg->subsector && distance > 0)) { // Can't spread in this direction. return; } } // Check distance against the obj radius. if(distance < 0) distance = -distance; if(distance >= params->objRadius) { // The obj doesn't reach that far. return; } // During next step, obj will continue spreading from there. dest->validCount = validCount; // Add this obj to the destination subsector. { linkobjtossecparams_t lparams; lparams.obj = params->obj; lparams.type = params->objType; RIT_LinkObjToSubSector(dest, &lparams); } spreadInSsec(dest, data); } /** * Create a contact for the objlink in all the subsectors the linked obj is * contacting (tests done on bounding boxes and the subsector spread test). * * @param oLink Ptr to objlink to find subsector contacts for. */ static void findContacts(objlink_t* oLink) { contactfinderparams_t params; float radius; pvec3_t pos; subsector_t** ssec; switch(oLink->type) { case OT_LUMOBJ: { lumobj_t* lum = (lumobj_t*) oLink->obj; if(lum->type != LT_OMNI) return; // Only omni lights spread. pos = lum->pos; radius = LUM_OMNI(lum)->radius; ssec = &lum->subsector; break; } case OT_MOBJ: { mobj_t* mo = (mobj_t*) oLink->obj; pos = mo->pos; radius = R_VisualRadius(mo); ssec = &mo->subsector; break; } default: Con_Error("Internal Error: Invalid value (%i) for objlink_t->type " "in findContacts.", (int) oLink->type); return; // Unreachable. } // Do the subsector spread. Begin from the obj's own ssec. (*ssec)->validCount = ++validCount; params.obj = oLink->obj; params.objType = oLink->type; V3_Copy(params.objPos, pos); // Use a slightly smaller radius than what the obj really is. params.objRadius = radius * .98f; params.box[BOXLEFT] = params.objPos[VX] - radius; params.box[BOXRIGHT] = params.objPos[VX] + radius; params.box[BOXBOTTOM] = params.objPos[VY] - radius; params.box[BOXTOP] = params.objPos[VY] + radius; // Always contact the obj's own subsector. { linkobjtossecparams_t params; params.obj = oLink->obj; params.type = oLink->type; RIT_LinkObjToSubSector(*ssec, ¶ms); } spreadInSsec(*ssec, ¶ms); } /** * Spread obj contacts in the subsector > obj blockmap to all other * subsectors within the block. * * @param subsector Ptr to the subsector to spread the obj contacts of. */ void R_ObjBlockmapSpreadObjsInSubSector(const objblockmap_t* obm, const subsector_t* ssec, float maxRadius) { int xl, xh, yl, yh, x, y; objlink_t* iter; if(!obm || !ssec) return; // Wha? xl = X_TO_OBBX(obm, FLT2FIX(ssec->bBox[0].pos[VX] - maxRadius)); xh = X_TO_OBBX(obm, FLT2FIX(ssec->bBox[1].pos[VX] + maxRadius)); yl = Y_TO_OBBY(obm, FLT2FIX(ssec->bBox[0].pos[VY] - maxRadius)); yh = Y_TO_OBBY(obm, FLT2FIX(ssec->bBox[1].pos[VY] + maxRadius)); // Are we completely outside the blockmap? if(xh < 0 || xl >= obm->width || yh < 0 || yl >= obm->height) return; // Clip to blockmap bounds. if(xl < 0) xl = 0; if(xh >= obm->width) xh = obm->width - 1; if(yl < 0) yl = 0; if(yh >= obm->height) yh = obm->height - 1; for(x = xl; x <= xh; ++x) for(y = yl; y <= yh; ++y) { objblock_t* block = OBB_XY(obm, x, y); if(!block->doneSpread) { // Spread the objs in this block. iter = block->head; while(iter) { findContacts(iter); iter = iter->nextInBlock; } block->doneSpread = true; } } } /** * Perform any processing needed before we can draw surfaces within the * specified subsector with dynamic lights. * * @param ssec Ptr to the subsector to process. */ void R_InitForSubsector(subsector_t* ssec) { float maxRadius = MAX_OF(DDMOBJ_RADIUS_MAX, loMaxRadius); BEGIN_PROF( PROF_OBJLINK_SPREAD ); // Make sure we know which objs are contacting us. R_ObjBlockmapSpreadObjsInSubSector(objBlockmap, ssec, maxRadius); END_PROF( PROF_OBJLINK_SPREAD ); } /** * Link all objlinks into the objlink blockmap. */ void R_ObjBlockmapLinkObjLink(objblockmap_t* obm, objlink_t* oLink, float x, float y) { int bx, by; objlink_t** root; if(!obm || !oLink) return; // Wha? oLink->nextInBlock = NULL; bx = X_TO_OBBX(obm, FLT2FIX(x)); by = Y_TO_OBBY(obm, FLT2FIX(y)); if(bx >= 0 && by >= 0 && bx < obm->width && by < obm->height) { root = &OBB_XY(obm, bx, by)->head; oLink->nextInBlock = *root; *root = oLink; } } /** * Called by R_BeginWorldFrame() at the beginning of render tic (iff the * render lists are not frozen) to link all objlinks into the objlink * blockmap. */ void R_LinkObjs(void) { objlink_t* oLink; BEGIN_PROF( PROF_OBJLINK_LINK ); // Link objlinks into the objlink blockmap. oLink = objLinks; while(oLink) { pvec3_t pos; switch(oLink->type) { case OT_LUMOBJ: pos = ((lumobj_t*) oLink->obj)->pos; break; case OT_MOBJ: pos = ((mobj_t*) oLink->obj)->pos; break; default: Con_Error("Internal Error: Invalid value (%i) for objlink_t->type " "in R_LinkObjs.", (int) oLink->type); return; // Unreachable. } R_ObjBlockmapLinkObjLink(objBlockmap, oLink, pos[VX], pos[VY]); oLink = oLink->next; } END_PROF( PROF_OBJLINK_LINK ); } /** * Initialize the obj > subsector contact lists ready for adding new * luminous objects. Called by R_BeginWorldFrame() at the beginning of a new * frame (if the render lists are not frozen). */ void R_InitForNewFrame(void) { #ifdef DD_PROFILE static int i; if(++i > 40) { i = 0; PRINT_PROF(PROF_OBJLINK_SPREAD); PRINT_PROF(PROF_OBJLINK_LINK); } #endif // Start reusing nodes from the first one in the list. contCursor = contFirst; if(subContacts) memset(subContacts, 0, numSSectors * sizeof(*subContacts)); } boolean R_IterateSubsectorContacts(subsector_t* ssec, objtype_t type, boolean (*func) (void*, void*), void* data) { objcontact_t* con; con = subContacts[GET_SUBSECTOR_IDX(ssec)].head[type]; while(con) { if(!func(con->obj, data)) return false; con = con->next; } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_input.c0000644000175000017500000010700111357170242022702 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_input.c: System Independent Input */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" #include "de_ui.h" #include "gl_main.h" // MACROS ------------------------------------------------------------------ #define DEFAULT_JOYSTICK_DEADZONE .05f // 5% #define MAX_AXIS_FILTER 40 #define KBDQUESIZE 32 #define MAX_DOWNKEYS 16 // Most keyboards support 6 or 7. // TYPES ------------------------------------------------------------------- typedef struct repeater_s { int key; // The DDKEY code (0 if not in use). timespan_t timer; // How's the time? int count; // How many times has been repeated? } repeater_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(AxisPrintConfig); D_CMD(AxisChangeOption); D_CMD(AxisChangeValue); D_CMD(DumpKeyMap); D_CMD(KeyMap); D_CMD(ListInputDevices); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean ignoreInput = false; int mouseFilter = 1; // Filtering on by default. // The initial and secondary repeater delays (tics). int repWait1 = 15, repWait2 = 3; int keyRepeatDelay1 = 430, keyRepeatDelay2 = 85; // milliseconds unsigned int mouseFreq = 0; boolean shiftDown = false, altDown = false; static byte shiftKeyMappings[NUMKKEYS], altKeyMappings[NUMKKEYS]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ /*static*/ inputdev_t inputDevices[NUM_INPUT_DEVICES]; static ddevent_t events[MAXEVENTS]; static int eventhead; static int eventtail; static char defaultShiftTable[96] = // Contains characters 32 to 127. { /* 32 */ ' ', 0, 0, 0, 0, 0, 0, '"', /* 40 */ 0, 0, 0, 0, '<', '_', '>', '?', ')', '!', /* 50 */ '@', '#', '$', '%', '^', '&', '*', '(', 0, ':', /* 60 */ 0, '+', 0, 0, 0, 'a', 'b', 'c', 'd', 'e', /* 70 */ 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', /* 80 */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', /* 90 */ 'z', '{', '|', '}', 0, 0, 0, 'A', 'B', 'C', /* 100 */ 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', /* 110 */ 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', /* 120 */ 'X', 'Y', 'Z', 0, 0, 0, 0, 0 }; /* *INDENT-ON* */ static repeater_t keyReps[MAX_DOWNKEYS]; //static int oldJoyBState = 0; static float oldPOV = IJOY_POV_CENTER; static char* eventStrings[MAXEVENTS]; static boolean uiMouseMode = false; // Can mouse data be modified? // CODE -------------------------------------------------------------------- void DD_RegisterInput(void) { // Cvars C_VAR_INT("input-key-delay1", &keyRepeatDelay1, CVF_NO_MAX, 50, 0); C_VAR_INT("input-key-delay2", &keyRepeatDelay2, CVF_NO_MAX, 20, 0); C_VAR_INT("input-mouse-filter", &mouseFilter, 0, 0, MAX_AXIS_FILTER - 1); C_VAR_INT("input-mouse-frequency", &mouseFreq, CVF_NO_MAX, 0, 0); // Ccmds #if 0 C_CMD("dumpkeymap", "s", DumpKeyMap); C_CMD("keymap", "s", KeyMap); #endif C_CMD("listinputdevices", "", ListInputDevices); //C_CMD_FLAGS("setaxis", "s", AxisPrintConfig, CMDF_NO_DEDICATED); //C_CMD_FLAGS("setaxis", "ss", AxisChangeOption, CMDF_NO_DEDICATED); //C_CMD_FLAGS("setaxis", "sss", AxisChangeValue, CMDF_NO_DEDICATED); } /** * Allocate an array of bytes for the input devices keys. * The allocated memory is cleared to zero. */ static void I_DeviceAllocKeys(inputdev_t *dev, uint count) { dev->numKeys = count; dev->keys = M_Calloc(count * sizeof(inputdevkey_t)); } static void I_DeviceAllocHats(inputdev_t *dev, uint count) { dev->numHats = count; dev->hats = M_Calloc(count * sizeof(inputdevhat_t)); } /** * Add a new axis to the input device. */ static inputdevaxis_t *I_DeviceNewAxis(inputdev_t *dev, const char *name, uint type) { inputdevaxis_t *axis; dev->axes = M_Realloc(dev->axes, sizeof(inputdevaxis_t) * ++dev->numAxes); axis = &dev->axes[dev->numAxes - 1]; memset(axis, 0, sizeof(*axis)); strcpy(axis->name, name); axis->type = type; // Set reasonable defaults. The user's settings will be restored // later. axis->scale = 1; axis->deadZone = 0; return axis; } /** * Initialize the input device state table. * * \note There need not be actual physical devices available in order to * use these state tables. */ void I_InitVirtualInputDevices(void) { int i; inputdev_t *dev; inputdevaxis_t *axis; memset(inputDevices, 0, sizeof(inputDevices)); // The keyboard is always assumed to be present. // DDKEYs are used as key indices. dev = &inputDevices[IDEV_KEYBOARD]; dev->flags = ID_ACTIVE; strcpy(dev->name, "key"); I_DeviceAllocKeys(dev, 256); // The mouse may not be active. dev = &inputDevices[IDEV_MOUSE]; strcpy(dev->name, "mouse"); I_DeviceAllocKeys(dev, IMB_MAXBUTTONS); // The first five mouse buttons have symbolic names. dev->keys[0].name = "left"; dev->keys[1].name = "middle"; dev->keys[2].name = "right"; dev->keys[3].name = "wheelup"; dev->keys[4].name = "wheeldown"; // The mouse wheel is translated to keys, so there is no need to // create an axis for it. axis = I_DeviceNewAxis(dev, "x", IDAT_POINTER); axis->filter = 1; // On by default. axis->scale = 1.f/1000; axis = I_DeviceNewAxis(dev, "y", IDAT_POINTER); axis->filter = 1; // On by default. axis->scale = 1.f/1000; // Register console variables for the axis settings. // CAUTION: Allocating new axes may invalidate the pointers here. C_VAR_FLOAT("input-mouse-x-scale", &dev->axes[0].scale, CVF_NO_MAX, 0, 0); C_VAR_INT("input-mouse-x-flags", &dev->axes[0].flags, 0, 0, 3); C_VAR_FLOAT("input-mouse-y-scale", &dev->axes[1].scale, CVF_NO_MAX, 0, 0); C_VAR_INT("input-mouse-y-flags", &dev->axes[1].flags, 0, 0, 3); if(I_MousePresent()) dev->flags = ID_ACTIVE; // TODO: Add support for several joysticks. dev = &inputDevices[IDEV_JOY1]; strcpy(dev->name, "joy"); I_DeviceAllocKeys(dev, IJOY_MAXBUTTONS); for(i = 0; i < IJOY_MAXAXES; ++i) { char name[32]; if(i < 4) { strcpy(name, i == 0? "x" : i == 1? "y" : i == 2? "z" : "w"); } else { sprintf(name, "axis%02i", i + 1); } axis = I_DeviceNewAxis(dev, name, IDAT_STICK); axis->scale = 1.0f / IJOY_AXISMAX; axis->deadZone = DEFAULT_JOYSTICK_DEADZONE; } // Register console variables for the axis settings. for(i = 0; i < IJOY_MAXAXES; ++i) { inputdevaxis_t* axis = &dev->axes[i]; char varName[80]; sprintf(varName, "input-joy-%s-scale", axis->name); C_VAR_FLOAT(varName, &axis->scale, CVF_NO_MAX, 0, 0); sprintf(varName, "input-joy-%s-flags", axis->name); C_VAR_INT(varName, &axis->flags, 0, 0, 3); sprintf(varName, "input-joy-%s-deadzone", axis->name); C_VAR_FLOAT(varName, &axis->deadZone, 0, 0, 1); } I_DeviceAllocHats(dev, IJOY_MAXHATS); for(i = 0; i < IJOY_MAXHATS; ++i) { dev->hats[i].pos = -1; // centered } // The joystick may not be active. if(I_JoystickPresent()) dev->flags = ID_ACTIVE; } /** * Free the memory allocated for the input devices. */ void I_ShutdownInputDevices(void) { uint i; inputdev_t* dev; for(i = 0; i < NUM_INPUT_DEVICES; ++i) { dev = &inputDevices[i]; if(dev->keys) M_Free(dev->keys); dev->keys = 0; if(dev->axes) M_Free(dev->axes); dev->axes = 0; if(dev->hats) M_Free(dev->hats); dev->hats = 0; } } void I_DeviceReset(uint ident) { inputdev_t* dev = &inputDevices[ident]; int k; for(k = 0; k < dev->numAxes; ++k) { if(dev->axes[k].type == IDAT_POINTER) { // Clear the accumulation. dev->axes[k].position = 0; } } } /** * Retrieve a pointer to the input device state by identifier. * * @param ident Intput device identifier (index). * @param ifactive Only return if the device is active. * * @return Ptr to the input device state OR @c NULL,. */ inputdev_t *I_GetDevice(uint ident, boolean ifactive) { inputdev_t* dev = &inputDevices[ident]; if(ifactive) { if(dev->flags & ID_ACTIVE) return dev; else return NULL; } return dev; } /** * Retrieve a pointer to the input device state by name. * * @param name Input device name. * @param ifactive Only return if the device is active. * * @return Ptr to the input device state OR @c NULL,. */ inputdev_t *I_GetDeviceByName(const char *name, boolean ifactive) { uint i; inputdev_t *dev = NULL; boolean found; i = 0; found = false; while(i < NUM_INPUT_DEVICES && !found) { if(!stricmp(inputDevices[i].name, name)) { dev = &inputDevices[i]; found = true; } else i++; } if(dev) { if(ifactive) { if(dev->flags & ID_ACTIVE) return dev; else return NULL; } } return dev; } /** * Retrieve a ptr to the device axis specified by id. * * @param device Ptr to input device info, to get the axis ptr from. * @param id Axis index, to search for. * * @return Ptr to the device axis OR @c NULL, if not * found. */ inputdevaxis_t *I_GetAxisByID(inputdev_t *device, uint id) { if(!device || id > device->numAxes - 1) return NULL; return &device->axes[id-1]; } /** * Retrieve the index of a device's axis by name. * * @param device Ptr to input device info, to get the axis index from. * @param name Ptr to string containing the name to be searched for. * * @return Index of the device axis named; or -1, if not found. */ int I_GetAxisByName(inputdev_t *device, const char *name) { uint i; for(i = 0; i < device->numAxes; ++i) { if(!stricmp(device->axes[i].name, name)) return i; } return -1; } int I_GetKeyByName(inputdev_t* device, const char* name) { int i; for(i = 0; i < device->numKeys; ++i) { if(device->keys[i].name && !stricmp(device->keys[i].name, name)) return i; } return -1; } /** * Check through the axes registered for the given device, see if there is * one identified by the given name. * * @return @c false, if the string is invalid. */ boolean I_ParseDeviceAxis(const char* str, uint* deviceID, uint* axis) { char name[30], *ptr; inputdev_t* device; ptr = strchr(str, '-'); if(!ptr) return false; // The name of the device. memset(name, 0, sizeof(name)); strncpy(name, str, ptr - str); device = I_GetDeviceByName(name, false); if(device == NULL) return false; if(*deviceID) *deviceID = device - inputDevices; // The axis name. if(*axis) { int a = I_GetAxisByName(device, ptr + 1); if((*axis = a) < 0) return false; *axis = a + 1; // Axis indices are base 1. } return true; } float I_TransformAxis(inputdev_t* dev, uint axis, float rawPos) { float pos = rawPos; inputdevaxis_t* a = &dev->axes[axis]; // Disabled axes are always zero. if(a->flags & IDA_DISABLED) { return 0; } // Apply scaling, deadzone and clamping. pos *= a->scale; if(a->type == IDAT_STICK) // Pointer axes are not dead-zoned or clamped. { if(fabs(pos) <= a->deadZone) { pos = 0; } else { pos -= a->deadZone * SIGN_OF(pos); // Remove the dead zone. pos *= 1.0f/(1.0f - a->deadZone); // Normalize. pos = MINMAX_OF(-1.0f, pos, 1.0f); } } if(a->flags & IDA_INVERT) { // Invert the axis position. pos = -pos; } return pos; } /** * Update an input device axis. Transformation is applied. */ static void I_UpdateAxis(inputdev_t *dev, uint axis, float pos, timespan_t ticLength) { inputdevaxis_t *a = &dev->axes[axis]; float oldRealPos = a->realPosition; float transformed = I_TransformAxis(dev, axis, pos); // The unfiltered position. a->realPosition = transformed; if(oldRealPos != a->realPosition) { // Mark down the time of the change. a->time = Sys_GetRealTime(); } if(a->filter > 0) { pos = a->realPosition; } else { // This is the new axis position. pos = a->realPosition; } if(a->type == IDAT_STICK) a->position = pos; //a->realPosition; else // Cumulative. a->position += pos; //a->realPosition; // We can clear the expiration when it returns to default state. if(!a->position || a->type == IDAT_POINTER) { a->assoc.flags &= ~IDAF_EXPIRED; } /* if(verbose > 3) { Con_Message("I_UpdateAxis: device=%s axis=%i pos=%f\n", dev->name, axis, pos); }*/ } /** * Update the input device state table. */ void I_TrackInput(ddevent_t *ev, timespan_t ticLength) { inputdev_t *dev; if((dev = I_GetDevice(ev->device, true)) == NULL) return; // Track the state of Shift and Alt. if(IS_KEY_TOGGLE(ev)) { if(ev->toggle.id == DDKEY_RSHIFT) { if(ev->toggle.state == ETOG_DOWN) shiftDown = true; else if(ev->toggle.state == ETOG_UP) shiftDown = false; } else if(ev->toggle.id == DDKEY_RALT) { if(ev->toggle.state == ETOG_DOWN) altDown = true; else if(ev->toggle.state == ETOG_UP) altDown = false; } } // Update the state table. if(ev->type == E_AXIS) { I_UpdateAxis(dev, ev->axis.id, ev->axis.pos, ticLength); } else if(ev->type == E_TOGGLE) { inputdevkey_t* key = &dev->keys[ev->toggle.id]; key->isDown = (ev->toggle.state == ETOG_DOWN || ev->toggle.state == ETOG_REPEAT); // Mark down the time when the change occurs. if(ev->toggle.state == ETOG_DOWN || ev->toggle.state == ETOG_UP) { key->time = Sys_GetRealTime(); } // We can clear the expiration when the key is released. if(!key->isDown) { key->assoc.flags &= ~IDAF_EXPIRED; } } else if(ev->type == E_ANGLE) { inputdevhat_t* hat = &dev->hats[ev->angle.id]; hat->pos = ev->angle.pos; // Mark down the time when the change occurs. hat->time = Sys_GetRealTime(); // We can clear the expiration when the hat is centered. if(hat->pos < 0) { hat->assoc.flags &= ~IDAF_EXPIRED; } } } void I_ClearDeviceContextAssociations(void) { uint i, j; inputdev_t *dev; for(i = 0; i < NUM_INPUT_DEVICES; ++i) { dev = &inputDevices[i]; // Keys. for(j = 0; j < dev->numKeys; ++j) { dev->keys[j].assoc.prevBContext = dev->keys[j].assoc.bContext; dev->keys[j].assoc.bContext = NULL; } // Axes. for(j = 0; j < dev->numAxes; ++j) { dev->axes[j].assoc.prevBContext = dev->axes[j].assoc.bContext; dev->axes[j].assoc.bContext = NULL; } // Hats. for(j = 0; j < dev->numHats; ++j) { dev->hats[j].assoc.prevBContext = dev->hats[j].assoc.bContext; dev->hats[j].assoc.bContext = NULL; } } } /** * @return The key state from the downKeys array. */ boolean I_IsDeviceKeyDown(uint ident, uint code) { inputdev_t *dev; if((dev = I_GetDevice(ident, true)) != NULL) { if(code >= dev->numKeys) return false; return dev->keys[code].isDown; } return false; } /** * @return Either key number or the scan code for the given token. */ int DD_KeyOrCode(char *token) { char *end = M_FindWhite(token); if(end - token > 1) { // Longer than one character, it must be a number. return strtol(token, 0, !strnicmp(token, "0x", 2) ? 16 : 10); } // Direct mapping. return (unsigned char) *token; } /** * Initializes the key mappings to the default values. */ void DD_InitInput(void) { int i; for(i = 0; i < 256; ++i) { shiftKeyMappings[i] = i >= 32 && i <= 127 && defaultShiftTable[i - 32] ? defaultShiftTable[i - 32] : i; altKeyMappings[i] = i; } } const char* DD_AllocEventString(const char* str) { static int eventStringRover = 0; const char* returnValue = 0; free(eventStrings[eventStringRover]); returnValue = eventStrings[eventStringRover] = strdup(str); if(++eventStringRover >= MAXEVENTS) { eventStringRover = 0; } return returnValue; } void DD_ClearEventStrings(void) { int i; for(i = 0; i < MAXEVENTS; ++i) { free(eventStrings[i]); eventStrings[i] = 0; } } /** * Clear the input event queue. */ void DD_ClearEvents(void) { eventhead = eventtail; DD_ClearEventStrings(); } /** * Called by the I/O functions when input is detected. */ void DD_PostEvent(ddevent_t *ev) { events[eventhead] = *ev; if(ev->type == E_SYMBOLIC) { // Allocate a throw-away string from our buffer. events[eventhead].symbolic.name = DD_AllocEventString(ev->symbolic.name); } eventhead++; eventhead &= MAXEVENTS - 1; } /** * Get the next event from the input event queue. Returns NULL if no * more events are available. */ static ddevent_t *DD_GetEvent(void) { ddevent_t *ev; if(eventhead == eventtail) return NULL; ev = &events[eventtail]; eventtail = (eventtail + 1) & (MAXEVENTS - 1); return ev; } void DD_ConvertEvent(const ddevent_t* ddEvent, event_t* ev) { // Copy the essentials into a cutdown version for the game. // Ensure the format stays the same for future compatibility! // // FIXME: This is probably broken! (DD_MICKEY_ACCURACY=1000 no longer used...) // memset(ev, 0, sizeof(ev)); if(ddEvent->type == E_SYMBOLIC) { ev->type = EV_SYMBOLIC; ev->data1 = ((int64_t) ddEvent->symbolic.name) & 0xffffffff; // low dword ev->data2 = ((int64_t) ddEvent->symbolic.name) >> 32; // high dword } else { switch(ddEvent->device) { case IDEV_KEYBOARD: ev->type = EV_KEY; if(ddEvent->type == E_TOGGLE) { ev->state = ( ddEvent->toggle.state == ETOG_UP? EVS_UP : ddEvent->toggle.state == ETOG_DOWN? EVS_DOWN : EVS_REPEAT ); ev->data1 = ddEvent->toggle.id; } break; case IDEV_MOUSE: if(ddEvent->type == E_AXIS) { ev->type = EV_MOUSE_AXIS; } else if(ddEvent->type == E_TOGGLE) { ev->type = EV_MOUSE_BUTTON; ev->data1 = ddEvent->toggle.id; ev->state = ( ddEvent->toggle.state == ETOG_UP? EVS_UP : ddEvent->toggle.state == ETOG_DOWN? EVS_DOWN : EVS_REPEAT ); } break; case IDEV_JOY1: case IDEV_JOY2: case IDEV_JOY3: case IDEV_JOY4: if(ddEvent->type == E_AXIS) { int* data = &ev->data1; ev->type = EV_JOY_AXIS; ev->state = 0; if(ddEvent->axis.id >= 0 && ddEvent->axis.id < 6) { data[ddEvent->axis.id] = ddEvent->axis.pos; } /// @todo The other dataN's must contain up-to-date information /// as well. Read them from the current joystick status. } else if(ddEvent->type == E_TOGGLE) { ev->type = EV_JOY_BUTTON; ev->state = ( ddEvent->toggle.state == ETOG_UP? EVS_UP : ddEvent->toggle.state == ETOG_DOWN? EVS_DOWN : EVS_REPEAT ); ev->data1 = ddEvent->toggle.id; } else if(ddEvent->type == E_ANGLE) ev->type = EV_POV; break; default: #if _DEBUG Con_Error("DD_ProcessEvents: Unknown deviceID in ddevent_t"); #endif break; } } } /** * Send all the events of the given timestamp down the responder chain. */ static void dispatchEvents(timespan_t ticLength) { ddevent_t *ddev; event_t ev; while((ddev = DD_GetEvent()) != NULL) { if(ignoreInput) continue; // Update the state of the input device tracking table. I_TrackInput(ddev, ticLength); DD_ConvertEvent(ddev, &ev); // Does the special responder use this event? if(gx.PrivilegedResponder) if(gx.PrivilegedResponder(&ev)) continue; if(UI_Responder(ddev)) continue; // The console. if(Con_Responder(ddev)) continue; // The game responder only returns true if the bindings // can't be used (like when chatting). if(gx.G_Responder(&ev)) continue; // The bindings responder. if(B_Responder(ddev)) continue; // The "fallback" responder. Gets the event if no one else is // interested. if(gx.FallbackResponder) gx.FallbackResponder(&ev); } } /** * Poll all event sources (i.e., input devices) and post events. */ static void postEvents(timespan_t ticLength) { DD_ReadKeyboard(); if(!isDedicated) { // In dedicated mode, we don't do mice or joysticks. DD_ReadMouse(ticLength); DD_ReadJoystick(); } } /** * Process all incoming input for the given timestamp. * * This gets called at least 35 times per second. Usually more frequently * than that. */ void DD_ProcessEvents(timespan_t ticLength) { // Poll all event sources (i.e., input devices) and post events. postEvents(ticLength); // Despatch all accumulated events down the responder chain. dispatchEvents(ticLength); } /** * Apply all active modifiers to the key. */ byte DD_ModKey(byte key) { if(shiftDown) key = shiftKeyMappings[key]; if(altDown) key = altKeyMappings[key]; if(key >= DDKEY_NUMPAD7 && key <= DDKEY_NUMPAD0) { byte numPadKeys[10] = { '7', '8', '9', '4', '5', '6', '1', '2', '3', '0' }; return numPadKeys[key - DDKEY_NUMPAD7]; } return key; } /** * Clears the repeaters array. */ void DD_ClearKeyRepeaters(void) { memset(keyReps, 0, sizeof(keyReps)); } /** * Checks the current keyboard state, generates input events * based on pressed/held keys and posts them. */ void DD_ReadKeyboard(void) { uint i, k; ddevent_t ev; size_t n, numkeyevs; keyevent_t keyevs[KBDQUESIZE]; // Check the repeaters. ev.device = IDEV_KEYBOARD; ev.type = E_TOGGLE; ev.toggle.state = ETOG_REPEAT; for(i = 0; i < MAX_DOWNKEYS; ++i) { repeater_t *rep = keyReps + i; if(!rep->key) continue; ev.toggle.id = rep->key; if(!rep->count && sysTime - rep->timer >= keyRepeatDelay1 / 1000.0) { // The first time. rep->count++; rep->timer += keyRepeatDelay1 / 1000.0; DD_PostEvent(&ev); } if(rep->count) { while(sysTime - rep->timer >= keyRepeatDelay2 / 1000.0) { rep->count++; rep->timer += keyRepeatDelay2 / 1000.0; DD_PostEvent(&ev); } } } // Read the new keyboard events. if(isDedicated) numkeyevs = I_GetConsoleKeyEvents(keyevs, KBDQUESIZE); else numkeyevs = I_GetKeyEvents(keyevs, KBDQUESIZE); // Convert to ddevents and post them. for(n = 0; n < numkeyevs; ++n) { keyevent_t *ke = &keyevs[n]; // Check the type of the event. if(ke->event == IKE_KEY_DOWN) // Key pressed? { ev.toggle.state = ETOG_DOWN; } else if(ke->event == IKE_KEY_UP) // Key released? { ev.toggle.state = ETOG_UP; } ev.toggle.id = ke->ddkey; // Maintain the repeater table. if(ev.toggle.state == ETOG_DOWN) { // Find an empty repeater. for(k = 0; k < MAX_DOWNKEYS; ++k) if(!keyReps[k].key) { keyReps[k].key = ev.toggle.id; keyReps[k].timer = sysTime; keyReps[k].count = 0; break; } } else if(ev.toggle.state == ETOG_UP) { // Clear any repeaters with this key. for(k = 0; k < MAX_DOWNKEYS; ++k) if(keyReps[k].key == ev.toggle.id) keyReps[k].key = 0; } // Post the event. DD_PostEvent(&ev); } } float I_FilterMouse(float pos, float* accumulation, float ticLength) { float target; int dir; float avail; int used; *accumulation += pos; dir = SIGN_OF(*accumulation); avail = fabs(*accumulation); // Determine the target velocity. target = avail * (MAX_AXIS_FILTER - mouseFilter); // Determine the amount of mickeys to send. It depends on the // current mouse velocity, and how much time has passed. used = target * ticLength; // Don't go over the available number of update frames. if(used > avail) { *accumulation = 0; used = avail; } else { if(*accumulation > 0) *accumulation -= used; else *accumulation += used; } // This is the new (filtered) axis position. return dir * used; } /** * Change between normal and UI mousing modes. */ void I_SetUIMouseMode(boolean on) { uiMouseMode = on; #ifdef UNIX if(I_MousePresent()) { // Release mouse grab when in windowed mode. boolean isFullScreen = true; Sys_GetWindowFullscreen(1, &isFullScreen); if(!isFullScreen) { SDL_WM_GrabInput(on? SDL_GRAB_OFF : SDL_GRAB_ON); } } #endif } /** * Checks the current mouse state (axis, buttons and wheel). * Generates events and mickeys and posts them. */ void DD_ReadMouse(timespan_t ticLength) { ddevent_t ev; mousestate_t mouse; float xpos, ypos; int i; if(!I_MousePresent()) return; // Should we test the mouse input frequency? if(mouseFreq > 0) { static uint lastTime = 0; uint nowTime = Sys_GetRealTime(); if(nowTime - lastTime < 1000/mouseFreq) { // Don't ask yet. memset(&mouse, 0, sizeof(mouse)); } else { lastTime = nowTime; I_GetMouseState(&mouse); } } else { // Get the mouse state. I_GetMouseState(&mouse); } ev.device = IDEV_MOUSE; ev.type = E_AXIS; ev.axis.type = EAXIS_RELATIVE; xpos = mouse.x; ypos = mouse.y; if(mouseFilter > 0) { // Filtering ensures that events are sent more evenly on each frame. static float accumulation[2] = { 0, 0 }; xpos = I_FilterMouse(xpos, &accumulation[0], ticLength); ypos = I_FilterMouse(ypos, &accumulation[1], ticLength); } // Mouse axis data may be modified if not in UI mode. /* if(uiMouseMode) { if(mouseDisableX) xpos = 0; if(mouseDisableY) ypos = 0; if(!mouseInverseY) ypos = -ypos; } */ if(uiMouseMode) { // Scale the movement depending on screen resolution. xpos *= MAX_OF(1, theWindow->width / 800.0f); ypos *= MAX_OF(1, theWindow->height / 600.0f); } else { ypos = -ypos; } // Post an event per axis. // Don't post empty events. if(xpos) { ev.axis.id = 0; ev.axis.pos = xpos; DD_PostEvent(&ev); } if(ypos) { ev.axis.id = 1; ev.axis.pos = ypos; DD_PostEvent(&ev); } // Some very verbose output about mouse buttons. if(verbose >= 3) { for(i = 0; i < IMB_MAXBUTTONS; ++i) if(mouse.buttonDowns[i] || mouse.buttonUps[i]) break; if(i < IMB_MAXBUTTONS) { for(i = 0; i < IMB_MAXBUTTONS; ++i) Con_Message("[%02i] %i/%i ", i, mouse.buttonDowns[i], mouse.buttonUps[i]); Con_Message("\n"); } } // Post mouse button up and down events. ev.type = E_TOGGLE; for(i = 0; i < IMB_MAXBUTTONS; ++i) { ev.toggle.id = i; while(mouse.buttonDowns[i] > 0 || mouse.buttonUps[i] > 0) { if(mouse.buttonDowns[i]-- > 0) { ev.toggle.state = ETOG_DOWN; DD_PostEvent(&ev); } if(mouse.buttonUps[i]-- > 0) { ev.toggle.state = ETOG_UP; DD_PostEvent(&ev); } } } } /** * Checks the current joystick state (axis, sliders, hat and buttons). * Generates events and posts them. Axis clamps and dead zone is done * here. */ void DD_ReadJoystick(void) { int i; ddevent_t ev; joystate_t state; if(!I_JoystickPresent()) return; I_GetJoystickState(&state); // Joystick buttons. ev.device = IDEV_JOY1; ev.type = E_TOGGLE; for(i = 0; i < state.numButtons; ++i) { ev.toggle.id = i; while(state.buttonDowns[i] > 0 || state.buttonUps[i] > 0) { if(state.buttonDowns[i]-- > 0) { ev.toggle.state = ETOG_DOWN; DD_PostEvent(&ev); } if(state.buttonUps[i]-- > 0) { ev.toggle.state = ETOG_UP; DD_PostEvent(&ev); } } } if(state.numHats > 0) { // Check for a POV change. // TODO: Some day, it would be nice to support multiple hats here. -jk if(state.hatAngle[0] != oldPOV) { ev.type = E_ANGLE; ev.angle.id = 0; if(state.hatAngle[0] < 0) { ev.angle.pos = -1; } else { // The new angle becomes active. ev.angle.pos = (int) (state.hatAngle[0] / 45 + .5); // Round off correctly w/.5. } DD_PostEvent(&ev); oldPOV = state.hatAngle[0]; } } // Send joystick axis events, one per axis. ev.type = E_AXIS; for(i = 0; i < state.numAxes; ++i) { ev.axis.id = i; ev.axis.pos = state.axis[i]; ev.axis.type = EAXIS_ABSOLUTE; DD_PostEvent(&ev); } } static void I_PrintAxisConfig(inputdev_t *device, inputdevaxis_t *axis) { Con_Printf("%s-%s Config:\n" " Type: %s\n" " Filter: %i\n" " Dead Zone: %g\n" " Scale: %g\n" " Flags: (%s%s)\n", device->name, axis->name, (axis->type == IDAT_STICK? "STICK" : "POINTER"), axis->filter, axis->deadZone, axis->scale, ((axis->flags & IDA_DISABLED)? "|disabled":""), ((axis->flags & IDA_INVERT)? "|inverted":"")); } D_CMD(AxisPrintConfig) { uint deviceID, axisID; inputdev_t *device; inputdevaxis_t *axis; if(!I_ParseDeviceAxis(argv[1], &deviceID, &axisID)) { Con_Printf("'%s' is not a valid device or device axis.\n", argv[1]); return false; } device = I_GetDevice(deviceID, false); axis = I_GetAxisByID(device, axisID); I_PrintAxisConfig(device, axis); return true; } D_CMD(AxisChangeOption) { uint deviceID, axisID; inputdev_t *device; inputdevaxis_t *axis; if(!I_ParseDeviceAxis(argv[1], &deviceID, &axisID)) { Con_Printf("'%s' is not a valid device or device axis.\n", argv[1]); return false; } device = I_GetDevice(deviceID, false); axis = I_GetAxisByID(device, axisID); // Options: if(!stricmp(argv[2], "disable") || !stricmp(argv[2], "off")) { axis->flags |= IDA_DISABLED; } else if(!stricmp(argv[2], "enable") || !stricmp(argv[2], "on")) { axis->flags &= ~IDA_DISABLED; } else if(!stricmp(argv[2], "invert")) // toggle { axis->flags ^= IDA_INVERT; } // Unknown option name. return true; } D_CMD(AxisChangeValue) { uint deviceID, axisID; inputdev_t *device; inputdevaxis_t *axis; if(!I_ParseDeviceAxis(argv[1], &deviceID, &axisID)) { Con_Printf("'%s' is not a valid device or device axis.\n", argv[1]); return false; } device = I_GetDevice(deviceID, false); axis = I_GetAxisByID(device, axisID); // Values: if(!stricmp(argv[2], "filter")) { axis->filter = strtod(argv[3], 0); } else if(!stricmp(argv[2], "deadzone") || !stricmp(argv[2], "dead zone")) { axis->deadZone = strtod(argv[3], 0); } else if(!stricmp(argv[2], "scale")) { axis->scale = strtod(argv[3], 0); } // Unknown value name. return true; } /** * Console command to list all of the available input devices+axes. */ D_CMD(ListInputDevices) { uint i, j; inputdev_t *dev; Con_Printf("Input Devices:\n"); for(i = 0; i < NUM_INPUT_DEVICES; ++i) { dev = &inputDevices[i]; if(!dev->name || !(dev->flags & ID_ACTIVE)) continue; Con_Printf("%s (%i keys, %i axes)\n", dev->name, dev->numKeys, dev->numAxes); for(j = 0; j < dev->numAxes; ++j) { Con_Printf(" Axis #%i: %s\n", j, dev->axes[j].name); I_PrintAxisConfig(dev, &dev->axes[j]); } } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/con_bar.c0000644000175000017500000001013611357170241022500 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_bar.c: Console Progress Bar */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_system.h" #include "de_console.h" #include "de_graphics.h" #include "de_ui.h" // MACROS ------------------------------------------------------------------ // Time for the progress to reach the new target (seconds). #define PROGRESS_DELTA_TIME 1.0 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ typedef struct tval_s { int value; timespan_t time; } tval_t; static int progressMax; static tval_t target, last; static mutex_t progressMutex; // CODE -------------------------------------------------------------------- static void lockProgress(boolean lock) { if(lock) { Sys_Lock(progressMutex); } else { Sys_Unlock(progressMutex); } } void Con_InitProgress(int maxProgress) { memset(&target, 0, sizeof(target)); memset(&last, 0, sizeof(last)); progressMax = maxProgress; if(!progressMutex) progressMutex = Sys_CreateMutex("ConBarProgressMutex"); } void Con_ShutdownProgress(void) { if(progressMutex) { Sys_DestroyMutex(progressMutex); } } /** * Updates the progress indicator. */ void Con_SetProgress(int progress) { timespan_t nowTime; lockProgress(true); nowTime = Sys_GetRealSeconds(); if(nowTime >= target.time) { // Previous movement has ended. last.time = nowTime; last.value = target.value; } target.value = progress; target.time = Sys_GetRealSeconds(); if(target.value < progressMax) { float delta = target.time - last.time; if(delta < PROGRESS_DELTA_TIME) { delta = (delta + PROGRESS_DELTA_TIME) / 2; } target.time += delta; } else { target.value = progressMax; } lockProgress(false); } /** * Calculate the progress at the current time. */ float Con_GetProgress(void) { timespan_t nowTime, span; float retValue = 1.0; lockProgress(true); nowTime = Sys_GetRealSeconds(); span = target.time - last.time; if(progressMax) { if(nowTime >= target.time) { // Done. retValue = target.value / (float) progressMax; } else if(span <= 0) { // Interpolate. retValue = target.value; } else { timespan_t inter = (target.value - last.value) * (nowTime - last.time); retValue += last.value + inter / span; retValue /= progressMax; } } lockProgress(false); return retValue; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_fakeradio.c0000644000175000017500000016412711357170242024045 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_fakeradio.c: Faked Radiosity Lighting * * Perhaps the most distinctive characteristic of radiosity lighting * is that the corners of a room are slightly dimmer than the rest of * the surfaces. (It's not the only characteristic, however.) We * will fake these shadowed areas by generating shadow polygons for * wall segments and determining, which subsector vertices will be * shadowed. * * In other words, walls use shadow polygons (over entire segs), while * planes use vertex lighting. Since planes are usually tesselated * into a great deal of subsectors (and triangles), they are better * suited for vertex lighting. In some cases we will be forced to * split a subsector into smaller pieces than strictly necessary in * order to achieve better accuracy in the shadow effect. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_misc.h" #include "de_play.h" #include "m_vector.h" // MACROS ------------------------------------------------------------------ #define MIN_OPEN (.1f) #define EDGE_OPEN_THRESHOLD (8) // world units (Z axis) #define MINDIFF (8) // min plane height difference (world units) #define INDIFF (8) // max plane height for indifference offset #define BOTTOM (0) #define TOP (1) // TYPES ------------------------------------------------------------------- typedef struct edge_s { boolean done; linedef_t* line; sector_t* sector; float length; binangle_t diff; } edge_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void scanEdges(shadowcorner_t topCorners[2], shadowcorner_t bottomCorners[2], shadowcorner_t sideCorners[2], edgespan_t spans[2], const linedef_t* line, boolean backSide); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int rendFakeRadio = true; // cvar float rendFakeRadioDarkness = 1.2f; // cvar float rendRadioLongWallMin = 400; float rendRadioLongWallMax = 1500; float rendRadioLongWallDiv = 30; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void Rend_RadioRegister(void) { C_VAR_INT("rend-fakeradio", &rendFakeRadio, 0, 0, 2); C_VAR_FLOAT("rend-fakeradio-darkness", &rendFakeRadioDarkness, 0, 0, 2); } static __inline float calcShadowDarkness(float lightLevel) { return (0.6f - lightLevel * 0.4f) * rendFakeRadioDarkness; } /** * Called to update the shadow properties used when doing FakeRadio for the * given linedef. */ void Rend_RadioUpdateLinedef(linedef_t* line, boolean backSide) { sidedef_t* s; if(!rendFakeRadio || levelFullBright || // Disabled? !line) return; // Have we yet determined the shadow properties to be used with segs // on this sidedef? s = line->sideDefs[backSide? BACK : FRONT]; if(s->fakeRadioUpdateCount != frameCount) { // Not yet. Calculate now. uint i; for(i = 0; i < 2; ++i) { s->spans[i].length = line->length; s->spans[i].shift = 0; } scanEdges(s->topCorners, s->bottomCorners, s->sideCorners, s->spans, line, backSide); s->fakeRadioUpdateCount = frameCount; // Mark as done. } } /** * Set the vertex colors in the rendpoly. */ static void setRendpolyColor(rcolor_t* rcolors, uint num, float darkness) { uint i; // Clamp it. if(darkness < 0) darkness = 0; if(darkness > 1) darkness = 1; // Shadows are black. for(i = 0; i < num; ++i) { rcolors[i].rgba[CR] = rcolors[i].rgba[CG] = rcolors[i].rgba[CB] = 0; rcolors[i].rgba[CA] = darkness; } } /** * @return @c true, if there is open space in the sector. */ static __inline boolean isSectorOpen(sector_t* sector) { return (sector && sector->SP_ceilheight > sector->SP_floorheight); } /** * Set the rendpoly's X offset and texture size. * * @param length If negative; implies that the texture is flipped * horizontally. */ static __inline float calcTexCoordX(float lineLength, float segOffset) { if(lineLength > 0) return segOffset; return lineLength + segOffset; } /** * Set the rendpoly's Y offset and texture size. * * @param size If negative; implies that the texture is flipped * vertically. */ static __inline float calcTexCoordY(float z, float bottom, float top, float texHeight) { if(texHeight > 0) return top - z; return bottom - z; } static void scanNeighbor(boolean scanTop, const linedef_t* line, uint side, edge_t* edge, boolean toLeft) { #define SEP (10) linedef_t* iter; lineowner_t* own; binangle_t diff = 0; float lengthDelta = 0, gap = 0; float iFFloor, iFCeil; float iBFloor, iBCeil; int scanSecSide = side; sector_t* startSector = line->L_sector(side); sector_t* scanSector; boolean clockwise = toLeft; boolean stopScan = false; boolean closed; float fCeil, fFloor; fFloor = line->L_sector(side)->SP_floorvisheight; fCeil = line->L_sector(side)->SP_ceilvisheight; // Retrieve the start owner node. own = R_GetVtxLineOwner(line->L_v(side^!toLeft), line); do { // Select the next line. diff = (clockwise? own->angle : own->LO_prev->angle); iter = own->link[clockwise]->lineDef; scanSecSide = (iter->L_frontsector == startSector); // Step over selfreferencing lines? while(LINE_SELFREF(iter)) { own = own->link[clockwise]; diff += (clockwise? own->angle : own->LO_prev->angle); iter = own->link[clockwise]->lineDef; scanSecSide = (iter->L_frontsector == startSector); } // Determine the relative backsector. if(iter->L_side(scanSecSide)) scanSector = iter->L_sector(scanSecSide); else scanSector = NULL; // Pick plane heights for relative offset comparison. if(!stopScan) { iFFloor = iter->L_frontsector->SP_floorvisheight; iFCeil = iter->L_frontsector->SP_ceilvisheight; if(iter->L_backside) { iBFloor = iter->L_backsector->SP_floorvisheight; iBCeil = iter->L_backsector->SP_ceilvisheight; } else iBFloor = iBCeil = 0; } lengthDelta = 0; if(!stopScan) { // This line will attribute to this seg's shadow edge. // Store identity for later use. edge->diff = diff; edge->line = iter; edge->sector = scanSector; closed = false; if(side == 0 && iter->L_backside) { if(scanTop) { if(iBFloor >= fCeil) closed = true; // Compared to "this" sector anyway } else { if(iBCeil <= fFloor) closed = true; // Compared to "this" sector anyway } } // Does this line's length contribute to the alignment of the // texture on the seg shadow edge being rendered? if(scanTop) { if(iter->L_backside && ((side == 0 && iter->L_backsector == line->L_frontsector && iFCeil >= fCeil) || (side == 1 && iter->L_backsector == line->L_backsector && iFCeil >= fCeil) || (side == 0 && closed == false && iter->L_backsector != line->L_frontsector && iBCeil >= fCeil && isSectorOpen(iter->L_backsector)))) { gap += iter->length; // Should we just mark it done instead? } else { edge->length += iter->length + gap; gap = 0; } } else { if(iter->L_backside && ((side == 0 && iter->L_backsector == line->L_frontsector && iFFloor <= fFloor) || (side == 1 && iter->L_backsector == line->L_backsector && iFFloor <= fFloor) || (side == 0 && closed == false && iter->L_backsector != line->L_frontsector && iBFloor <= fFloor && isSectorOpen(iter->L_backsector)))) { gap += iter->length; // Should we just mark it done instead? } else { lengthDelta = iter->length + gap; gap = 0; } } } // Time to stop? if(iter == line) { stopScan = true; } else { // Is this line coalignable? if(!(diff >= BANG_180 - SEP && diff <= BANG_180 + SEP)) stopScan = true; // no. else if(scanSector) { // Perhaps its a closed edge? if(!isSectorOpen(scanSector)) { stopScan = true; } else { // A height difference from the start sector? if(scanTop) { if(scanSector->SP_ceilvisheight != fCeil && scanSector->SP_floorvisheight < startSector->SP_ceilvisheight) stopScan = true; } else { if(scanSector->SP_floorvisheight != fFloor && scanSector->SP_ceilvisheight > startSector->SP_floorvisheight) stopScan = true; } } } } // Swap to the iter line's owner node (i.e: around the corner)? if(!stopScan) { // Around the corner. if(own->link[clockwise] == iter->L_vo2) own = iter->L_vo1; else if(own->link[clockwise] == iter->L_vo1) own = iter->L_vo2; // Skip into the back neighbor sector of the iter line if // heights are within accepted range. if(scanSector && line->L_side(side^1) && scanSector != line->L_sector(side^1) && ((scanTop && scanSector->SP_ceilvisheight == startSector->SP_ceilvisheight) || (!scanTop && scanSector->SP_floorvisheight == startSector->SP_floorvisheight))) { // If the map is formed correctly, we should find a back // neighbor attached to this line. However, if this is not // the case and a line which SHOULD be two sided isn't, we // need to check whether there is a valid neighbor. linedef_t *backNeighbor = R_FindLineNeighbor(startSector, iter, own, !toLeft, NULL); if(backNeighbor && backNeighbor != iter) { // Into the back neighbor sector. own = own->link[clockwise]; startSector = scanSector; } } // The last line was co-alignable so apply any length delta. edge->length += lengthDelta; } } while(!stopScan); // Now we've found the furthest coalignable neighbor, select the back // neighbor if present for "edge open-ness" comparison. if(edge->sector) // the back sector of the coalignable neighbor. { // Since we have the details of the backsector already, simply // get the next neighbor (it IS the backneighbor). edge->line = R_FindLineNeighbor(edge->sector, edge->line, edge->line->vo[(edge->line->L_backside && edge->line->L_backsector == edge->sector)^!toLeft], !toLeft, &edge->diff); } #undef SEP } static void scanNeighbors(shadowcorner_t top[2], shadowcorner_t bottom[2], const linedef_t* line, uint side, edgespan_t spans[2], boolean toLeft) { uint i; edge_t edges[2], *edge; // {bottom, top} edgespan_t* span; shadowcorner_t* corner; float fCeil, fFloor; if(LINE_SELFREF(line)) return; fFloor = line->L_sector(side)->SP_floorvisheight; fCeil = line->L_sector(side)->SP_ceilvisheight; memset(edges, 0, sizeof(edges)); scanNeighbor(false, line, side, &edges[0], toLeft); scanNeighbor(true, line, side, &edges[1], toLeft); for(i = 0; i < 2; ++i) // 0=bottom, 1=top { corner = (i == 0 ? &bottom[!toLeft] : &top[!toLeft]); edge = &edges[i]; span = &spans[i]; // Increment the apparent line length/offset. span->length += edge->length; if(toLeft) span->shift += edge->length; // Compare the relative angle difference of this edge to determine // an "open-ness" factor. if(edge->line && edge->line != line) { if(edge->diff > BANG_180) { // The corner between the walls faces outwards. corner->corner = -1; } else if(edge->diff == BANG_180) { // Perfectly coaligned? Great. corner->corner = 0; } else if(edge->diff < BANG_45 / 5) { // The difference is too small, there won't be a shadow. corner->corner = 0; } // 90 degrees is the largest effective difference. else if(edge->diff > BANG_90) { corner->corner = (float) BANG_90 / edge->diff; } else { corner->corner = (float) edge->diff / BANG_90; } } else { // Consider it coaligned. corner->corner = 0; } // Determine relative height offsets (affects shadow map selection). if(edge->sector) { corner->proximity = edge->sector; if(i == 0) // Floor. { corner->pOffset = corner->proximity->SP_floorvisheight - fFloor; corner->pHeight = corner->proximity->SP_floorvisheight; } else // Ceiling. { corner->pOffset = corner->proximity->SP_ceilvisheight - fCeil; corner->pHeight = corner->proximity->SP_ceilvisheight; } } else { corner->proximity = NULL; corner->pOffset = 0; corner->pHeight = 0; } } } /** * To determine the dimensions of a shadow, we'll need to scan edges. Edges * are composed of aligned lines. It's important to note that the scanning * is done separately for the top/bottom edges (both in the left and right * direction) and the left/right edges. * * The length of the top/bottom edges are returned in the array 'spans'. * * This may look like a complicated operation (performed for all wall polys) * but in most cases this won't take long. Aligned neighbours are relatively * rare. */ static void scanEdges(shadowcorner_t topCorners[2], shadowcorner_t bottomCorners[2], shadowcorner_t sideCorners[2], edgespan_t spans[2], const linedef_t* line, boolean backSide) { uint i, sid = (backSide? BACK : FRONT); sidedef_t* side; linedef_t* other; side = line->L_side(sid); memset(sideCorners, 0, sizeof(sideCorners)); // Find the sidecorners first: left and right neighbour. for(i = 0; i < 2; ++i) { binangle_t diff = 0; lineowner_t *vo; vo = line->L_vo(i^sid); other = R_FindSolidLineNeighbor(line->L_sector(sid), line, vo, i, &diff); if(other && other != line) { if(diff > BANG_180) { // The corner between the walls faces outwards. sideCorners[i].corner = -1; } else if(diff == BANG_180) { sideCorners[i].corner = 0; } else if(diff < BANG_45 / 5) { // The difference is too small, there won't be a shadow. sideCorners[i].corner = 0; } else if(diff > BANG_90) { // 90 degrees is the largest effective difference. sideCorners[i].corner = (float) BANG_90 / diff; } else { sideCorners[i].corner = (float) diff / BANG_90; } } else sideCorners[i].corner = 0; scanNeighbors(topCorners, bottomCorners, line, sid, spans, !i); } } /** * Long walls get slightly larger shadows. The bonus will simply be added * to the shadow size for the wall in question. */ static __inline float calcLongWallBonus(float span) { float limit; if(rendRadioLongWallDiv > 0 && span > rendRadioLongWallMin) { limit = span - rendRadioLongWallMin; if(limit > rendRadioLongWallMax) limit = rendRadioLongWallMax; return limit / rendRadioLongWallDiv; } return 0; } typedef struct { lightingtexid_t texture; boolean horizontal; float shadowMul; float texWidth; float texHeight; float texOffset[2]; float wallLength; } rendershadowseg_params_t; static void setTopShadowParams(rendershadowseg_params_t* p, float size, float top, const float* xOffset, const float* segLength, const float* fFloor, const float* fCeil, const shadowcorner_t* botCn, const shadowcorner_t* topCn, const shadowcorner_t* sideCn, const edgespan_t* spans) { p->shadowMul = 1; p->horizontal = false; p->texHeight = size; p->texOffset[VY] = calcTexCoordY(top, *fFloor, *fCeil, p->texHeight); p->wallLength = *segLength; p->texture = LST_RADIO_OO; // Corners without a neighbour backsector if(sideCn[0].corner == -1 || sideCn[1].corner == -1) { // At least one corner faces outwards p->texture = LST_RADIO_OO; p->texWidth = spans[TOP].length; p->texOffset[VX] = calcTexCoordX(spans[TOP].length, spans[TOP].shift + *xOffset); if((sideCn[0].corner == -1 && sideCn[1].corner == -1) || (topCn[0].corner == -1 && topCn[1].corner == -1)) { // Both corners face outwards p->texture = LST_RADIO_OO;//CC; } else if(sideCn[1].corner == -1) { // right corner faces outwards if(-topCn[0].pOffset < 0 && botCn[0].pHeight < *fCeil) {// Must flip horizontally! p->texWidth = -spans[TOP].length; p->texOffset[VX] = calcTexCoordX(-spans[TOP].length, spans[TOP].shift + *xOffset); p->texture = LST_RADIO_OE; } } else // left corner faces outwards { if(-topCn[1].pOffset < 0 && botCn[1].pHeight < *fCeil) { p->texture = LST_RADIO_OE; } } } else { // Corners WITH a neighbour backsector p->texWidth = spans[TOP].length; p->texOffset[VX] = calcTexCoordX(spans[TOP].length, spans[TOP].shift + *xOffset); if(topCn[0].corner == -1 && topCn[1].corner == -1) { // Both corners face outwards p->texture = LST_RADIO_OO;//CC; } else if(topCn[1].corner == -1 && topCn[0].corner > MIN_OPEN) { // Right corner faces outwards p->texture = LST_RADIO_OO; } else if(topCn[0].corner == -1 && topCn[1].corner > MIN_OPEN) { // Left corner faces outwards p->texture = LST_RADIO_OO; } // Open edges else if(topCn[0].corner <= MIN_OPEN && topCn[1].corner <= MIN_OPEN) { // Both edges are open p->texture = LST_RADIO_OO; if(topCn[0].proximity && topCn[1].proximity) { if(-topCn[0].pOffset >= 0 && -topCn[1].pOffset < 0) { p->texture = LST_RADIO_CO; // The shadow can't go over the higher edge. if(size > -topCn[0].pOffset) { if(-topCn[0].pOffset < INDIFF) p->texture = LST_RADIO_OE; else { p->texHeight = -topCn[0].pOffset; p->texOffset[VY] = calcTexCoordY(top, *fFloor, *fCeil, p->texHeight); } } } else if(-topCn[0].pOffset < 0 && -topCn[1].pOffset >= 0) { // Must flip horizontally! p->texture = LST_RADIO_CO; p->texWidth = -spans[TOP].length; p->texOffset[VX] = calcTexCoordX(-spans[TOP].length, spans[TOP].shift + *xOffset); // The shadow can't go over the higher edge. if(size > -topCn[1].pOffset) { if(-topCn[1].pOffset < INDIFF) p->texture = LST_RADIO_OE; else { p->texHeight = -topCn[1].pOffset; p->texOffset[VY] = calcTexCoordY(top, *fFloor, *fCeil, p->texHeight); } } } } else { if(-topCn[0].pOffset < -MINDIFF) { // Must flip horizontally! p->texture = LST_RADIO_OE; p->texWidth = -spans[BOTTOM].length; p->texOffset[VX] = calcTexCoordX(-spans[BOTTOM].length, spans[BOTTOM].shift + *xOffset); } else if(-topCn[1].pOffset < -MINDIFF) p->texture = LST_RADIO_OE; } } else if(topCn[0].corner <= MIN_OPEN) { if(-topCn[0].pOffset < 0) p->texture = LST_RADIO_CO; else p->texture = LST_RADIO_OO; // Must flip horizontally! p->texWidth = -spans[TOP].length; p->texOffset[VX] = calcTexCoordX(-spans[TOP].length, spans[TOP].shift + *xOffset); } else if(topCn[1].corner <= MIN_OPEN) { if(-topCn[1].pOffset < 0) p->texture = LST_RADIO_CO; else p->texture = LST_RADIO_OO; } else // C/C ??? { p->texture = LST_RADIO_OO; } } } static void setBottomShadowParams(rendershadowseg_params_t *p, float size, float top, const float* xOffset, const float* segLength, const float* fFloor, const float* fCeil, const shadowcorner_t* botCn, const shadowcorner_t* topCn, const shadowcorner_t* sideCn, const edgespan_t* spans) { p->shadowMul = 1; p->horizontal = false; p->texHeight = -size; p->texOffset[VY] = calcTexCoordY(top, *fFloor, *fCeil, p->texHeight); p->wallLength = *segLength; p->texture = LST_RADIO_OO; // Corners without a neighbour backsector if(sideCn[0].corner == -1 || sideCn[1].corner == -1) { // At least one corner faces outwards p->texture = LST_RADIO_OO; p->texWidth = spans[BOTTOM].length; p->texOffset[VX] = calcTexCoordX(spans[BOTTOM].length, spans[BOTTOM].shift + *xOffset); if((sideCn[0].corner == -1 && sideCn[1].corner == -1) || (botCn[0].corner == -1 && botCn[1].corner == -1) ) { // Both corners face outwards p->texture = LST_RADIO_OO;//CC; } else if(sideCn[1].corner == -1) // right corner faces outwards { if(botCn[0].pOffset < 0 && topCn[0].pHeight > *fFloor) { // Must flip horizontally! p->texWidth = -spans[BOTTOM].length; p->texOffset[VX] = calcTexCoordX(-spans[BOTTOM].length, spans[BOTTOM].shift + *xOffset); p->texture = LST_RADIO_OE; } } else { // left corner faces outwards if(botCn[1].pOffset < 0 && topCn[1].pHeight > *fFloor) { p->texture = LST_RADIO_OE; } } } else { // Corners WITH a neighbour backsector p->texWidth = spans[BOTTOM].length; p->texOffset[VX] = calcTexCoordX(spans[BOTTOM].length, spans[BOTTOM].shift + *xOffset); if(botCn[0].corner == -1 && botCn[1].corner == -1) { // Both corners face outwards p->texture = LST_RADIO_OO;//CC; } else if(botCn[1].corner == -1 && botCn[0].corner > MIN_OPEN) { // Right corner faces outwards p->texture = LST_RADIO_OO; } else if(botCn[0].corner == -1 && botCn[1].corner > MIN_OPEN) { // Left corner faces outwards p->texture = LST_RADIO_OO; } // Open edges else if(botCn[0].corner <= MIN_OPEN && botCn[1].corner <= MIN_OPEN) { // Both edges are open p->texture = LST_RADIO_OO; if(botCn[0].proximity && botCn[1].proximity) { if(botCn[0].pOffset >= 0 && botCn[1].pOffset < 0) { p->texture = LST_RADIO_CO; // The shadow can't go over the higher edge. if(size > botCn[0].pOffset) { if(botCn[0].pOffset < INDIFF) p->texture = LST_RADIO_OE; else { p->texHeight = -botCn[0].pOffset; p->texOffset[VY] = calcTexCoordY(top, *fFloor, *fCeil, p->texHeight); } } } else if(botCn[0].pOffset < 0 && botCn[1].pOffset >= 0) { // Must flip horizontally! p->texture = LST_RADIO_CO; p->texWidth = -spans[BOTTOM].length; p->texOffset[VX] = calcTexCoordX(-spans[BOTTOM].length, spans[BOTTOM].shift + *xOffset); if(size > botCn[1].pOffset) { if(botCn[1].pOffset < INDIFF) p->texture = LST_RADIO_OE; else { p->texHeight = -botCn[1].pOffset; p->texOffset[VY] = calcTexCoordY(top, *fFloor, *fCeil, p->texHeight); } } } } else { if(botCn[0].pOffset < -MINDIFF) { // Must flip horizontally! p->texture = LST_RADIO_OE; p->texWidth = -spans[BOTTOM].length; p->texOffset[VX] = calcTexCoordX(-spans[BOTTOM].length, spans[BOTTOM].shift + *xOffset); } else if(botCn[1].pOffset < -MINDIFF) p->texture = LST_RADIO_OE; } } else if(botCn[0].corner <= MIN_OPEN) // Right Corner is Closed { if(botCn[0].pOffset < 0) p->texture = LST_RADIO_CO; else p->texture = LST_RADIO_OO; // Must flip horizontally! p->texWidth = -spans[BOTTOM].length; p->texOffset[VX] = calcTexCoordX(-spans[BOTTOM].length, spans[BOTTOM].shift + *xOffset); } else if(botCn[1].corner <= MIN_OPEN) // Left Corner is closed { if(botCn[1].pOffset < 0) p->texture = LST_RADIO_CO; else p->texture = LST_RADIO_OO; } else // C/C ??? { p->texture = LST_RADIO_OO; } } } static void setSideShadowParams(rendershadowseg_params_t* p, float size, float bottom, float top, boolean rightSide, boolean bottomGlow, boolean topGlow, const float* xOffset, const float* segLength, const float* fFloor, const float* fCeil, const float* bFloor, const float* bCeil, const float* lineLength, const shadowcorner_t* sideCn) { p->shadowMul = sideCn[rightSide? 1 : 0].corner; p->shadowMul *= p->shadowMul * p->shadowMul; p->horizontal = true; p->texOffset[VY] = bottom - *fFloor; p->texHeight = *fCeil - *fFloor; p->wallLength = *segLength; if(rightSide) { // Right shadow. p->texOffset[VX] = -(*lineLength) + *xOffset; // Make sure the shadow isn't too big if(size > *lineLength) { if(sideCn[0].corner <= MIN_OPEN) p->texWidth = -(*lineLength); else p->texWidth = -((*lineLength) / 2); } else p->texWidth = -size; } else { // Left shadow. p->texOffset[VX] = *xOffset; // Make sure the shadow isn't too big if(size > *lineLength) { if(sideCn[1].corner <= MIN_OPEN) p->texWidth = *lineLength; else p->texWidth = (*lineLength) / 2; } else p->texWidth = size; } if(bFloor) { // There is a backside. if(*bFloor > *fFloor && *bCeil < *fCeil) { if(!bottomGlow && !topGlow) { p->texture = LST_RADIO_CC; } else if(bottomGlow) { p->texOffset[VY] = bottom - *fCeil; p->texHeight = -(*fCeil - *fFloor); p->texture = LST_RADIO_CO; } else p->texture = LST_RADIO_CO; } else if(*bFloor > *fFloor) { if(!bottomGlow && !topGlow) { p->texture = LST_RADIO_CC; } else if(bottomGlow) { p->texOffset[VY] = bottom - *fCeil; p->texHeight = -(*fCeil - *fFloor); p->texture = LST_RADIO_CO; } else p->texture = LST_RADIO_CO; } else if(*bCeil < *fCeil) { if(!bottomGlow && !topGlow) { p->texture = LST_RADIO_CC; } else if(bottomGlow) { p->texOffset[VY] = bottom - *fCeil; p->texHeight = -(*fCeil - *fFloor); p->texture = LST_RADIO_CO; } else p->texture = LST_RADIO_CO; } } else { if(bottomGlow) { p->texHeight = -(*fCeil - *fFloor); p->texOffset[VY] = calcTexCoordY(top, *fFloor, *fCeil, p->texHeight); p->texture = LST_RADIO_CO; } else if(topGlow) p->texture = LST_RADIO_CO; else p->texture = LST_RADIO_CC; } } static void quadTexCoords(rtexcoord_t* tc, const rvertex_t* rverts, float wallLength, float texWidth, float texHeight, const float texOrigin[2][3], const float texOffset[2], boolean horizontal) { if(horizontal) { // Special horizontal coordinates for wall shadows. tc[0].st[0] = tc[2].st[0] = rverts[0].pos[VX] - texOrigin[0][VX] + texOffset[VY] / texHeight; tc[0].st[1] = tc[1].st[1] = rverts[0].pos[VY] - texOrigin[0][VY] + texOffset[VX] / texWidth; tc[1].st[0] = tc[0].st[0] + (rverts[1].pos[VZ] - texOrigin[0][VZ]) / texHeight; tc[3].st[0] = tc[0].st[0] + (rverts[3].pos[VZ] - texOrigin[0][VZ]) / texHeight; tc[3].st[1] = tc[0].st[1] + wallLength / texWidth; tc[2].st[1] = tc[0].st[1] + wallLength / texWidth; return; } tc[0].st[0] = tc[1].st[0] = rverts[0].pos[VX] - texOrigin[0][VX] + texOffset[VX] / texWidth; tc[3].st[1] = tc[1].st[1] = rverts[0].pos[VY] - texOrigin[0][VY] + texOffset[VY] / texHeight; tc[3].st[0] = tc[2].st[0] = tc[0].st[0] + wallLength / texWidth; tc[2].st[1] = tc[3].st[1] + (rverts[1].pos[VZ] - rverts[0].pos[VZ]) / texHeight; tc[0].st[1] = tc[3].st[1] + (rverts[3].pos[VZ] - rverts[2].pos[VZ]) / texHeight; } static void renderShadowSeg(const rvertex_t* origVertices, const walldiv_t* divs, const rendershadowseg_params_t* p, float shadowDark) { float texOrigin[2][3]; rcolor_t* rcolors; rtexcoord_t* rtexcoords; rtexmapunit_t rTU[NUM_TEXMAP_UNITS]; uint realNumVertices = 4; if(divs) realNumVertices = 3 + divs[0].num + 3 + divs[1].num; memset(rTU, 0, sizeof(rTU)); rTU[TU_PRIMARY].tex = GL_PrepareLSTexture(p->texture); rTU[TU_PRIMARY].magMode = GL_LINEAR; rTU[TU_PRIMARY].blend = 1; // Top left. texOrigin[0][VX] = origVertices[1].pos[VX]; texOrigin[0][VY] = origVertices[1].pos[VY]; texOrigin[0][VZ] = origVertices[1].pos[VZ]; // Bottom right. texOrigin[1][VX] = origVertices[2].pos[VX]; texOrigin[1][VY] = origVertices[2].pos[VY]; texOrigin[1][VZ] = origVertices[2].pos[VZ]; // Allocate enough for the divisions too. rtexcoords = R_AllocRendTexCoords(realNumVertices); rcolors = R_AllocRendColors(realNumVertices); quadTexCoords(rtexcoords, origVertices, p->wallLength, p->texWidth, p->texHeight, texOrigin, p->texOffset, p->horizontal); setRendpolyColor(rcolors, 4, p->shadowMul * shadowDark); if(rendFakeRadio != 2) { // Write multiple polys depending on rend params. if(divs) { float bL, tL, bR, tR; rvertex_t* rvertices; rtexcoord_t origTexCoords[4]; rcolor_t origColors[4]; /** * Need to swap indices around into fans set the position * of the division vertices, interpolate texcoords and * color. */ rvertices = R_AllocRendVertices(realNumVertices); memcpy(origTexCoords, rtexcoords, sizeof(rtexcoord_t) * 4); memcpy(origColors, rcolors, sizeof(rcolor_t) * 4); bL = origVertices[0].pos[VZ]; tL = origVertices[1].pos[VZ]; bR = origVertices[2].pos[VZ]; tR = origVertices[3].pos[VZ]; R_DivVerts(rvertices, origVertices, divs); R_DivTexCoords(rtexcoords, origTexCoords, divs, bL, tL, bR, tR); R_DivVertColors(rcolors, origColors, divs, bL, tL, bR, tR); RL_AddPoly(PT_FAN, RPT_SHADOW, rvertices + 3 + divs[0].num, rtexcoords + 3 + divs[0].num, NULL, NULL, rcolors + 3 + divs[0].num, 3 + divs[1].num, 0, 0, NULL, rTU); RL_AddPoly(PT_FAN, RPT_SHADOW, rvertices, rtexcoords, NULL, NULL, rcolors, 3 + divs[0].num, 0, 0, NULL, rTU); R_FreeRendVertices(rvertices); } else { RL_AddPoly(PT_TRIANGLE_STRIP, RPT_SHADOW, origVertices, rtexcoords, NULL, NULL, rcolors, 4, 0, 0, NULL, rTU); } } R_FreeRendTexCoords(rtexcoords); R_FreeRendColors(rcolors); } /** * Create the appropriate FakeRadio shadow polygons for the wall segment. */ static void rendRadioSegSection(const rvertex_t* rvertices, const walldiv_t* divs, float shadowSize, float shadowDark, const rendsegradio_params_t* p) { const float* fFloor, *fCeil, *bFloor, *bCeil; float size; boolean bottomGlow, topGlow; bottomGlow = R_IsGlowingPlane(p->frontSec->SP_plane(PLN_FLOOR)); topGlow = R_IsGlowingPlane(p->frontSec->SP_plane(PLN_CEILING)); fFloor = &p->frontSec->SP_floorvisheight; fCeil = &p->frontSec->SP_ceilvisheight; if(p->backSec) { bFloor = &p->backSec->SP_floorvisheight; bCeil = &p->backSec->SP_ceilvisheight; } else bFloor = bCeil = NULL; /* * Top Shadow. */ if(!topGlow) { // The top shadow will reach this far down. size = shadowSize + calcLongWallBonus(p->spans[TOP].length); if(rvertices[3].pos[VZ] > *fCeil - size && rvertices[0].pos[VZ] < *fCeil) { rendershadowseg_params_t params; setTopShadowParams(¶ms, size, rvertices[1].pos[VZ], p->segOffset, p->segLength, fFloor, fCeil, p->botCn, p->topCn, p->sideCn, p->spans); renderShadowSeg(rvertices, divs, ¶ms, shadowDark); } } /* * Bottom Shadow. */ if(!bottomGlow) { size = shadowSize + calcLongWallBonus(p->spans[BOTTOM].length); if(rvertices[0].pos[VZ] < *fFloor + size && rvertices[3].pos[VZ] > *fFloor) { rendershadowseg_params_t params; setBottomShadowParams(¶ms, size, rvertices[1].pos[VZ], p->segOffset, p->segLength, fFloor, fCeil, p->botCn, p->topCn, p->sideCn, p->spans); renderShadowSeg(rvertices, divs, ¶ms, shadowDark); } } // Walls with glowing floor & ceiling get no side shadows. // Is there anything better we can do? if(bottomGlow && topGlow) return; size = shadowSize + calcLongWallBonus(*p->linedefLength); /* * Left Shadow. */ if(p->sideCn[0].corner > 0 && *p->segOffset < size) { rendershadowseg_params_t params; setSideShadowParams(¶ms, size, rvertices[0].pos[VZ], rvertices[1].pos[VZ], false, bottomGlow, topGlow, p->segOffset, p->segLength, fFloor, fCeil, bFloor, bCeil, p->linedefLength, p->sideCn); renderShadowSeg(rvertices, divs, ¶ms, shadowDark); } /* * Right Shadow. */ if(p->sideCn[1].corner > 0 && *p->segOffset + *p->segLength > *p->linedefLength - size) { rendershadowseg_params_t params; setSideShadowParams(¶ms, size, rvertices[0].pos[VZ], rvertices[1].pos[VZ], true, bottomGlow, topGlow, p->segOffset, p->segLength, fFloor, fCeil, bFloor, bCeil, p->linedefLength, p->sideCn); renderShadowSeg(rvertices, divs, ¶ms, shadowDark); } } /** * Render FakeRadio for the given seg section. */ void Rend_RadioSegSection(const rvertex_t* rvertices, const walldiv_t* divs, const rendsegradio_params_t* params) { float lightLevel, shadowSize, shadowDark; if(!rendFakeRadio || levelFullBright) // Disabled? return; if(!rvertices || !params) return; // Wha? lightLevel = *params->sectorLightLevel; Rend_ApplyLightAdaptation(&lightLevel); if(!(lightLevel > 0)) return; // No point drawing shadows in a PITCH black sector. // Determine the shadow properties. // \fixme Make cvars out of constants. shadowSize = 2 * (8 + 16 - lightLevel * 16); if(!(shadowSize > 0)) return; shadowDark = calcShadowDarkness(lightLevel) *.8f; rendRadioSegSection(rvertices, divs, shadowSize, shadowDark, params); } /** * Returns a value in the range of 0...2, which depicts how open the * specified edge is. Zero means that the edge is completely closed: it is * facing a wall or is relatively distant from the edge on the other side. * Values between zero and one describe how near the other edge is. An * openness value of one means that the other edge is at the same height as * this one. 2 means that the other edge is past our height ("clearly open"). */ static float radioEdgeOpenness(float fz, float bz, float bhz) { if(fz <= bz - EDGE_OPEN_THRESHOLD || fz >= bhz) return 0; // Fully closed. if(fz >= bhz - EDGE_OPEN_THRESHOLD) return (bhz - fz) / EDGE_OPEN_THRESHOLD; if(fz <= bz) return 1 - (bz - fz) / EDGE_OPEN_THRESHOLD; if(fz <= bz + EDGE_OPEN_THRESHOLD) return 1 + (fz - bz) / EDGE_OPEN_THRESHOLD; // Fully open! return 2; } static void setRelativeHeights(sector_t *front, sector_t *back, boolean isCeiling, float *fz, float *bz, float *bhz) { if(fz) { *fz = front->planes[isCeiling? PLN_CEILING:PLN_FLOOR]->visHeight; if(isCeiling) *fz = -(*fz); } if(bz) { *bz = back->planes[isCeiling? PLN_CEILING:PLN_FLOOR]->visHeight; if(isCeiling) *bz = -(*bz); } if(bhz) { *bhz = back->planes[isCeiling? PLN_FLOOR:PLN_CEILING]->visHeight; if(isCeiling) *bhz = -(*bhz); } } static uint radioEdgeHackType(linedef_t *line, sector_t *front, sector_t *back, int backside, boolean isCeiling, float fz, float bz) { surface_t *surface = &line->L_side(backside)-> sections[isCeiling? SEG_TOP:SEG_BOTTOM]; if(fz < bz && !surface->material && !(surface->inFlags & SUIF_MATERIAL_FIX)) return 3; // Consider it fully open. // Is the back sector closed? if(front->SP_floorvisheight >= back->SP_ceilvisheight) { if(R_IsSkySurface(&front->planes[isCeiling? PLN_FLOOR:PLN_CEILING]->surface)) { if(R_IsSkySurface(&back->planes[isCeiling? PLN_FLOOR:PLN_CEILING]->surface)) return 3; // Consider it fully open. } else return 1; // Consider it fully closed. } // Check for unmasked midtextures on twosided lines that completely // fill the gap between floor and ceiling (we don't want to give away // the location of any secret areas (false walls)). if(Rend_DoesMidTextureFillGap(line, backside)) return 1; // Consider it fully closed. return 0; } /** * Calculate the corner coordinates and add a new shadow polygon to the * rendering lists. */ static void radioAddShadowEdge(const linedef_t* line, byte side, vec2_t inner[2], vec2_t outer[2], float z, float darkness, float sideOpen[2], float normal[3]) { static const uint floorIndices[][4] = {{0, 1, 2, 3}, {1, 2, 3, 0}}; static const uint ceilIndices[][4] = {{0, 3, 2, 1}, {1, 0, 3, 2}}; uint wind; // Winding: 0 = left, 1 = right const uint* idx; rvertex_t rvertices[4]; rcolor_t rcolors[4]; rtexmapunit_t rTU[NUM_TEXMAP_UNITS]; float shadowAlpha; vertex_t* vtx0, *vtx1; if(darkness < 0) return; shadowAlpha = MIN_OF(darkness, 1.0f); vtx0 = line->L_v(side^0); vtx1 = line->L_v(side^1); // What vertex winding order? // (for best results, the cross edge should always be the shortest). wind = (V2_Distance(inner[1], vtx1->V_pos) > V2_Distance(inner[0], vtx0->V_pos)? 1 : 0); memset(rTU, 0, sizeof(rTU)); rTU[TU_PRIMARY].blend = 1; idx = (normal[VZ] > 0 ? floorIndices[wind] : ceilIndices[wind]); // Left outer corner. rvertices[idx[0]].pos[VX] = vtx0->V_pos[VX]; rvertices[idx[0]].pos[VY] = vtx0->V_pos[VY]; rvertices[idx[0]].pos[VZ] = z; rcolors[idx[0]].rgba[CR] = rcolors[idx[0]].rgba[CG] = rcolors[idx[0]].rgba[CB] = (renderWireframe? 1 : 0); rcolors[idx[0]].rgba[CA] = shadowAlpha; if(sideOpen[0] < 1) rcolors[idx[0]].rgba[CA] *= 1 - sideOpen[0]; // Right outer corner. rvertices[idx[1]].pos[VX] = vtx1->V_pos[VX]; rvertices[idx[1]].pos[VY] = vtx1->V_pos[VY]; rvertices[idx[1]].pos[VZ] = z; rcolors[idx[1]].rgba[CR] = rcolors[idx[1]].rgba[CG] = rcolors[idx[1]].rgba[CB] = (renderWireframe? 1 : 0); rcolors[idx[1]].rgba[CA] = shadowAlpha; if(sideOpen[1] < 1) rcolors[idx[1]].rgba[CA] *= 1 - sideOpen[1]; // Right inner corner. rvertices[idx[2]].pos[VX] = inner[1][VX]; rvertices[idx[2]].pos[VY] = inner[1][VY]; rvertices[idx[2]].pos[VZ] = z; rcolors[idx[2]].rgba[CR] = rcolors[idx[2]].rgba[CG] = rcolors[idx[2]].rgba[CB] = (renderWireframe? 1 : 0); rcolors[idx[2]].rgba[CA] = 0; // Left inner corner. rvertices[idx[3]].pos[VX] = inner[0][VX]; rvertices[idx[3]].pos[VY] = inner[0][VY]; rvertices[idx[3]].pos[VZ] = z; rcolors[idx[3]].rgba[CR] = rcolors[idx[3]].rgba[CG] = rcolors[idx[3]].rgba[CB] = (renderWireframe? 1 : 0); rcolors[idx[3]].rgba[CA] = 0; if(rendFakeRadio != 2) RL_AddPoly(PT_FAN, (renderWireframe? RPT_NORMAL : RPT_SHADOW), rvertices, NULL, NULL, NULL, rcolors, 4, 0, 0, NULL, rTU); } /** * Render the shadowpolygons linked to the subsector, if they haven't * already been rendered. * * Don't use the global radio state in here, the subsector can be part of * any sector, not the one chosen for wall rendering. */ static void radioSubsectorEdges(const subsector_t* subsector) { static size_t doPlaneSize = 0; static byte* doPlane = NULL; uint i, pln, hack, side; float open, sideOpen[2], vec[3]; float fz, bz, bhz, plnHeight; sector_t* front, *back; linedef_t* line; surface_t* suf; shadowlink_t* link; vec2_t inner[2], outer[2]; boolean workToDo = false; float shadowSize, shadowDark; float sectorlight = subsector->sector->lightLevel; Rend_ApplyLightAdaptation(§orlight); if(sectorlight == 0) return; // No point drawing shadows in a PITCH black sector. // Determine the shadow properties. // \fixme Make cvars out of constants. shadowSize = 2 * (8 + 16 - sectorlight * 16); shadowDark = calcShadowDarkness(sectorlight) *.8f; vec[VX] = vx - subsector->midPoint.pos[VX]; vec[VY] = vz - subsector->midPoint.pos[VY]; // Do we need to enlarge the size of the doPlane array? if(subsector->sector->planeCount > doPlaneSize) { if(!doPlaneSize) doPlaneSize = 2; else doPlaneSize *= 2; doPlane = Z_Realloc(doPlane, doPlaneSize, PU_STATIC); } memset(doPlane, 0, doPlaneSize); // See if any of this subsector's planes will get shadows. for(pln = 0; pln < subsector->sector->planeCount; ++pln) { plane_t *plane = subsector->sector->planes[pln]; if(R_IsGlowingPlane(plane)) continue; vec[VZ] = vy - plane->visHeight; // Don't bother with planes facing away from the camera. if(M_DotProduct(vec, plane->PS_normal) < 0) continue; doPlane[pln] = true; workToDo = true; } if(!workToDo) return; // We need to check all the shadow lines linked to this subsector for // the purpose of fakeradio shadowing. for(link = subsector->shadows; link != NULL; link = link->next) { // Already rendered during the current frame? We only want to // render each shadow once per frame. if(link->lineDef->shadowVisFrame[link->side] == (ushort) frameCount) continue; // Now it will be rendered. link->lineDef->shadowVisFrame[link->side] = (ushort) frameCount; line = link->lineDef; side = link->side; for(pln = 0; pln < subsector->sector->planeCount; ++pln) { plane_t* plane; if(!doPlane[pln]) continue; plane = line->L_sector(side)->SP_plane(pln); // Determine the openness of the line. If this edge is open, // there won't be a shadow at all. Open neighbours cause some // changes in the polygon corner vertices (placement, colour). suf = &subsector->sector->planes[pln]->surface; plnHeight = plane->visHeight; vec[VZ] = vy - plnHeight; // Glowing surfaces or missing textures shouldn't have shadows. if((suf->inFlags & SUIF_NO_RADIO) || !suf->material) continue; if(line->L_backside) { front = line->L_sector(side); back = line->L_sector(side ^ 1); setRelativeHeights(front, back, pln, &fz, &bz, &bhz); hack = radioEdgeHackType(line, front, back, side, pln, fz, bz); if(hack) open = hack - 1; else open = radioEdgeOpenness(fz, bz, bhz); } else open = 0; if(open >= 1) continue; // Find the neighbors of this edge and determine their 'openness'. sideOpen[0] = sideOpen[1] = 0; for(i = 0; i < 2; ++i) { lineowner_t* vo; linedef_t* neighbor; vo = line->L_vo(side^i)->link[i^1]; neighbor = vo->lineDef; if(neighbor != line && !neighbor->L_backside && neighbor->buildData.windowEffect && neighbor->L_frontsector != subsector->sector) { // A one-way window, open side. sideOpen[i] = 1; } else if(!(neighbor == line || !neighbor->L_backside)) { sector_t* othersec; byte otherSide; otherSide = (line->L_v(i^side) == neighbor->L_v1? i : i^1); othersec = neighbor->L_sector(otherSide); // Exclude 'special' neighbors which we pretend to be solid. if(LINE_SELFREF(neighbor) || ((R_IsSkySurface(&othersec->SP_planesurface(pln)) || R_IsSkySurface(&othersec->SP_planesurface(PLN_CEILING))) && othersec->SP_floorvisheight >= othersec->SP_ceilvisheight)) { sideOpen[i] = 1; } else if(Rend_DoesMidTextureFillGap(neighbor, otherSide^1)) { sideOpen[i] = 0; } else { // Its a normal neighbor. if(neighbor->L_sector(otherSide) != line->L_sector(side) && !((plane->type == PLN_FLOOR && othersec->SP_ceilvisheight <= plane->visHeight) || (plane->type == PLN_CEILING && othersec->SP_floorheight >= plane->visHeight))) { front = line->L_sector(side); back = neighbor->L_sector(otherSide); setRelativeHeights(front, back, pln, &fz, &bz, &bhz); sideOpen[i] = radioEdgeOpenness(fz, bz, bhz); } } } if(sideOpen[i] < 1) { vo = line->L_vo(i^side); if(i) vo = vo->LO_prev; V2_Sum(inner[i], line->L_vpos(i^side), vo->shadowOffsets.inner); } else { V2_Sum(inner[i], line->L_vpos(i^side), vo->shadowOffsets.extended); } } radioAddShadowEdge(line, side, inner, outer, plnHeight, shadowDark * (1 - open), sideOpen, suf->normal); } } } void Rend_RadioSubsectorEdges(subsector_t* subsector) { if(!rendFakeRadio || levelFullBright) return; radioSubsectorEdges(subsector); } #if _DEBUG static void drawPoint(float pos[3], float radius, const float color[4]) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); float viewPos[3], viewToCenter[3], finalPos[3], scale, leftOff[3], rightOff[3], radX, radY; int i; viewPos[VX] = vx; viewPos[VY] = vy; viewPos[VZ] = vz; // viewSideVec is to the left. for(i = 0; i < 3; ++i) { leftOff[i] = viewData->upVec[i] + viewData->sideVec[i]; rightOff[i] = viewData->upVec[i] - viewData->sideVec[i]; viewToCenter[i] = pos[i] - viewPos[i]; } scale = M_DotProduct(viewToCenter, viewData->frontVec) / M_DotProduct(viewData->frontVec, viewData->frontVec); finalPos[VX] = pos[VX]; finalPos[VY] = pos[VZ]; finalPos[VZ] = pos[VY]; // The final radius. radX = radius * 1; radY = radX / 1.2f; glColor4fv(color); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(finalPos[VX] + radX * leftOff[VX], finalPos[VY] + radY * leftOff[VY], finalPos[VZ] + radX * leftOff[VZ]); glTexCoord2f(1, 0); glVertex3f(finalPos[VX] + radX * rightOff[VX], finalPos[VY] + radY * rightOff[VY], finalPos[VZ] + radX * rightOff[VZ]); glTexCoord2f(1, 1); glVertex3f(finalPos[VX] - radX * leftOff[VX], finalPos[VY] - radY * leftOff[VY], finalPos[VZ] - radX * leftOff[VZ]); glTexCoord2f(0, 1); glVertex3f(finalPos[VX] - radX * rightOff[VX], finalPos[VY] - radY * rightOff[VY], finalPos[VZ] - radX * rightOff[VZ]); glEnd(); } /** * Render the shadow poly vertices, for debug. */ void Rend_DrawShadowOffsetVerts(void) { static const float red[4] = { 1.f, .2f, .2f, 1.f}; static const float yellow[4] = {.7f, .7f, .2f, 1.f}; uint i, j, k; float pos[3]; glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); GL_BindTexture(GL_PrepareLSTexture(LST_DYNAMIC), GL_LINEAR); for(i = 0; i < numLineDefs; ++i) { linedef_t* line = &lineDefs[i]; for(k = 0; k < 2; ++k) { vertex_t* vtx = line->L_v(k); lineowner_t* vo = vtx->lineOwners; for(j = 0; j < vtx->numLineOwners; ++j) { pos[VZ] = vo->lineDef->L_frontsector->SP_floorvisheight; V2_Sum(pos, vtx->V_pos, vo->shadowOffsets.extended); drawPoint(pos, 1.f, yellow); V2_Sum(pos, vtx->V_pos, vo->shadowOffsets.inner); drawPoint(pos, 1.f, red); vo = vo->LO_next; } } } glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_wad.c0000644000175000017500000012447311357170242022332 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * WAD Files and Data Lump Cache * * This version supports runtime (un)loading, replacement of flats and * sprites and IWAD checking. * * Internally, the cache has two parts: the Primary cache, which is loaded * from data files, and the Auxiliary cache, which is generated at runtime. * To outsiders, there is no difference between these two caches. The * only visible difference is that lumps in the auxiliary cache use indices * starting from AUXILIARY_BASE. Everything in the auxiliary cache takes * precedence over lumps in the primary cache. * * The W_Select() function is responsible for activating the right cache * when a lump index is provided. Functions that don't know the lump index * will have to check both the primary and the auxiliary caches (e.g., * W_CheckNumForName()). */ // HEADER FILES ------------------------------------------------------------ #include #include "de_platform.h" #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" #include "r_extres.h" #include "gl_draw.h" // for GL_SetFilter() // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { char name[9]; // End in \0. DFILE* handle; int position; size_t size; int sent; char group; // Lump grouping tag (LGT_*). } lumpinfo_t; typedef struct { char identification[4]; int numLumps; int infoTableOfs; } wadinfo_t; typedef struct { int filePos; int size; char name[8]; } filelump_t; typedef struct { char *start, *end; // Start and end markers. } grouping_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(Dir); D_CMD(Dump); D_CMD(ListFiles); D_CMD(LoadFile); D_CMD(ResetLumps); D_CMD(UnloadFile); int MarkerForGroup(char *name, boolean begin); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void W_CloseAuxiliary(void); static void W_CloseAuxiliaryFile(void); static void W_UsePrimary(void); static boolean W_UseAuxiliary(void); // may not be available // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- lumpinfo_t *lumpInfo = 0; int numLumps = 0; void** lumpCache = 0; int numCache = 0; // The file records. int numRecords = 0; filerecord_t *records = 0; char retName[9]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean loadingForStartup = true; static boolean iwadLoaded = false; static grouping_t lumpGroups[] = { {"", ""}, {"F_START", "F_END"}, // Flats {"S_START", "S_END"} // Sprites }; static lumpinfo_t* PrimaryLumpInfo; static int PrimaryNumLumps; static void** PrimaryLumpCache; static DFILE* AuxiliaryHandle; static lumpinfo_t* AuxiliaryLumpInfo; static int AuxiliaryNumLumps; static void** AuxiliaryLumpCache; boolean AuxiliaryOpened = false; // CODE -------------------------------------------------------------------- void DD_RegisterVFS(void) { C_CMD("dir", "s*", Dir); C_CMD("dump", "s", Dump); C_CMD("listfiles", "", ListFiles); C_CMD("load", "ss", LoadFile); C_CMD("ls", "s*", Dir); C_CMD("reset", "", ResetLumps); C_CMD("unload", "s*", UnloadFile); } static void convertSlashes(char* modifiableBuffer, size_t len) { size_t i; for(i = 0; i < len; ++i) if(modifiableBuffer[i] == '\\') modifiableBuffer[i] = '/'; } static lumpnum_t W_Index(lumpnum_t lump) { if(lumpCache == AuxiliaryLumpCache) { lump += AUXILIARY_BASE; } return lump; } /** * Selects which lump cache to use, given a logical lump index. This is * called in all the functions that access the lump cache. */ static lumpnum_t W_Select(lumpnum_t lump) { if(lump >= AUXILIARY_BASE) { W_UseAuxiliary(); lump -= AUXILIARY_BASE; } else { W_UsePrimary(); } return lump; } /* * File Record Handling * (all functions named W_Record*) */ /** * Allocate a new file record. */ filerecord_t* W_RecordNew(void) { filerecord_t* ptr; records = M_Realloc(records, sizeof(filerecord_t) * (++numRecords)); ptr = records + numRecords - 1; memset(ptr, 0, sizeof(*ptr)); return ptr; } int W_RecordGetIdx(const char* fileName) { int i; filename_t buf; // We have to make sure the slashes are correct. strncpy(buf, fileName, FILENAME_T_MAXLEN); convertSlashes(buf, FILENAME_T_MAXLEN); for(i = 0; i < numRecords; ++i) if(!strnicmp(records[i].fileName, buf, FILENAME_T_MAXLEN)) return i; return -1; } /** * Destroy the specified record. Returns true if successful. */ boolean W_RecordDestroy(int idx) { if(idx < 0 || idx > numRecords - 1) return false; // Huh? // First unallocate the memory of the record. // M_Free(records[idx].indices); // Collapse the record array. if(idx != numRecords - 1) memmove(records + idx, records + idx + 1, sizeof(filerecord_t) * (numRecords - idx - 1)); // Reallocate the records memory. numRecords--; // One less record. records = M_Realloc(records, sizeof(filerecord_t) * numRecords); return true; } /** * Look for the named lump, starting from the specified index. */ lumpnum_t W_ScanForName(char *lumpname, int startfrom) { char name8[9]; int v1, v2; int i; lumpinfo_t *lump_p; if(startfrom < 0 || startfrom > numLumps - 1) return -1; memset(name8, 0, sizeof(name8)); strncpy(name8, lumpname, 8); v1 = *(int *) name8; v2 = *(int *) (name8 + 4); // Start from the beginning. for(i = startfrom, lump_p = lumpInfo + startfrom; i < numLumps; i++, lump_p++) { if(v1 == *(int *) lump_p->name && v2 == *(int *) (lump_p->name + 4)) return i; } return -1; } /* * Lumpinfo inserting, filling, removal and other operations. */ /** * Writes the correct data into a lumpinfo_t entry. */ void W_FillLumpInfo(int liIndex, filelump_t* flump, filerecord_t* rec, int groupTag) { lumpinfo_t* lump = &lumpInfo[liIndex]; lump->handle = rec->handle; lump->position = LONG(flump->filePos); lump->size = LONG(flump->size); memset(lump->name, 0, sizeof(lump->name)); strncpy(lump->name, flump->name, 8); lump->group = groupTag; } /** * Moves 'count' lumpinfos, starting from 'from'. Updates the lumpcache. * Offset can only be positive. * * Lumpinfo and lumpcache are assumed to have enough memory for the * operation! */ void W_MoveLumps(int from, int count, int offset) { int i; // Check that our information is valid. if(!offset || count <= 0 || from < 0 || from > numLumps - 1) return; // First update the lumpcache. memmove(lumpCache + from + offset, lumpCache + from, sizeof(*lumpCache) * count); for(i = from + offset; i < from + count + offset; ++i) if(lumpCache[i]) Z_ChangeUser(lumpCache[i], lumpCache + i); // Update the user. // Clear the 'revealed' memory. if(offset > 0) // Revealed from the beginning. memset(lumpCache + from, 0, offset * sizeof(*lumpCache)); else // Revealed from the end. memset(lumpCache + from + count + offset, 0, -offset * sizeof(*lumpCache)); // Lumpinfo. memmove(lumpInfo + from + offset, lumpInfo + from, sizeof(lumpinfo_t) * count); } /** * Moves the rest of the lumps forward. */ void W_InsertAndFillLumpRange(int toIndex, filelump_t *lumps, int num, filerecord_t *rec, int groupTag) { int i; // Move lumps if needed. if(toIndex < numLumps) W_MoveLumps(toIndex, numLumps - toIndex, num); // Now we can just fill in the lumps. for(i = 0; i < num; ++i) W_FillLumpInfo(toIndex + i, lumps + i, rec, groupTag); // Update the number of lumps. numLumps += num; } void W_RemoveLumpsWithHandle(DFILE *handle) { int i, k, first, len; for(i = 0, first = -1; i < numLumps; ++i) { if(first < 0 && lumpInfo[i].handle == handle) { // Start a region. first = i; continue; } // Does a region end? if(first >= 0) if(lumpInfo[i].handle != handle || i == numLumps - 1 || MarkerForGroup(lumpInfo[i].name, true) || MarkerForGroup(lumpInfo[i].name, false)) { if(lumpInfo[i].handle == handle && i == numLumps - 1) i++; // Also free the last one. // The length of the region. len = i - first; // Free the memory allocated for the region. for(k = first; k < i; ++k) { // Con_Message("removing lump: %s (%d)\n", lumpInfo[k].name, lumpInfo[k].handle); if(lumpCache[k]) { // If the block has a user, it must be explicitly freed. /* if((unsigned int)Z_GetUser(lumpCache[k]) > 0x100) Z_Free(lumpCache[k]); else if(Z_GetTag(lumpCache[k]) < PU_MAP) Z_ChangeTag(lumpCache[k], PU_MAP); Z_ChangeTag(lumpCache[k], PU_CACHE); Z_ChangeUser(lumpCache[k], NULL); */ if(Z_GetTag(lumpCache[k]) < PU_MAP) Z_ChangeTag(lumpCache[k], PU_MAP); // Mark the memory pointer in use, but unowned. Z_ChangeUser(lumpCache[k], (void *) 0x2); } } // Move the data in the lump storage. W_MoveLumps(i, numLumps - i, -len); numLumps -= len; i -= len; // Make it possible to begin a new region. first = -1; } } } /** * Reallocates lumpInfo and lumpcache. */ void W_ResizeLumpStorage(int numItems) { lumpInfo = M_Realloc(lumpInfo, sizeof(lumpinfo_t) * numItems); // Updating the cache is a bit more difficult. We need to make sure // the user pointers in the memory zone remain valid. if(numCache != numItems) { int i, numToMod; void **newCache; // This is the new cache. size_t newCacheBytes = numItems * sizeof(*newCache); // The new size of the cache (bytes). newCache = M_Calloc(newCacheBytes); if(lumpCache) { // Copy the old cache. if(numCache < numItems) numToMod = numCache; else numToMod = numItems; memcpy(newCache, lumpCache, numToMod * sizeof(*lumpCache)); // Update the user information in the memory zone. for(i = 0; i < numToMod; ++i) if(newCache[i]) Z_ChangeUser(newCache[i], newCache + i); // Get rid of the old cache. M_Free(lumpCache); } lumpCache = newCache; numCache = numItems; } } /** * @return One of the grouping tags. */ int MarkerForGroup(char *name, boolean begin) { int i; for(i = 1; i < NUM_LGTAGS; ++i) if(!strnicmp(name, begin ? lumpGroups[i].start : lumpGroups[i].end, 8) || !strnicmp(name + 1, begin ? lumpGroups[i].start : lumpGroups[i].end, 7)) return i; // No matches... return LGT_NONE; } /** * Inserts the lumps in the fileinfo/record to their correct places in the * lumpInfo. Also maintains lumpInfo/records that all data is valid. * * The current placing of the lumps is that flats and sprites are added to * previously existing flat and sprite groups. All other lumps are just * appended to the end of the list. */ void W_InsertLumps(filelump_t* fileinfo, filerecord_t* rec) { int i, to, num; filelump_t* flump = fileinfo; int inside = LGT_NONE; // Not inside any group. int groupFirst = 0; // First lump in the current group. int maxNumLumps = numLumps + rec->numLumps; // This must be enough. // Allocate more memory for the lumpInfo. W_ResizeLumpStorage(maxNumLumps); for(i = 0; i < rec->numLumps; ++i, flump++) { /** * The Hexen demo on Mac uses the 0x80 on some lumps, maybe has * significance? * \todo: Ensure that this doesn't break other IWADs. The 0x80-0xff * range isn't normally used in lump names, right?? */ for(to = 0; to < 8; to++) { flump->name[to] = flump->name[to] & 0x7f; } if(inside == LGT_NONE) { // We are currently not inside any group. if((inside = MarkerForGroup(flump->name, true)) != LGT_NONE) { // We have entered a group! Go to the next lump. groupFirst = i + 1; continue; } // This lump is very ordinary. Just append it to the lumpInfo. //rec->indices[i] = numLumps; W_FillLumpInfo(numLumps++, flump, rec, inside); } else { if(MarkerForGroup(flump->name, false) == inside) // Group ends? { // This is how many lumps we'll add. num = i - groupFirst; // Find the existing group. to = W_ScanForName(lumpGroups[inside].end, 0); if(to < 0) { // There is no existing group. Include the start and // end markers in the range of lumps to add. groupFirst--; num += 2; to = numLumps; } W_InsertAndFillLumpRange(to, &fileinfo[groupFirst], num, rec, inside); // We exit this group. inside = LGT_NONE; } } } // It may be that all lumps weren't added. Make sure we don't have // excess memory allocated (=synchronize the storage size with the // real numLumps). W_ResizeLumpStorage(numLumps); // Update the record with the number of lumps that were loaded. rec->numLumps -= maxNumLumps - numLumps; } /** * Files with a .wad extension are wadlink files with multiple lumps, * other files are single lumps with the base filename for the lump name. * * @return @c true, if the operation is successful. */ boolean W_AddFile(const char* fileName, boolean allowDuplicate) { filename_t alterFileName; wadinfo_t header; DFILE* handle; unsigned int length; filelump_t singleInfo, *fileInfo, *freeFileInfo; filerecord_t* rec; const char* extension; // Filename given? if(!fileName || !fileName[0]) return true; if((handle = F_Open(fileName, "rb")) == NULL) { // Didn't find file. Try reading from the data path. R_PrependDataPath(alterFileName, fileName, FILENAME_T_MAXLEN); if((handle = F_Open(alterFileName, "rb")) == NULL) { Con_Message("W_AddFile: ERROR: %s not found!\n", fileName); return false; } // We'll use this instead. fileName = alterFileName; } // Do not read files twice. if(!allowDuplicate && !M_CheckFileID(fileName)) { F_Close(handle); // The file is not used. return false; } Con_Message("W_AddFile: %s\n", M_PrettyPath(fileName)); // Determine the file name extension. extension = strrchr(fileName, '.'); if(!extension) extension = ""; else extension++; // Move to point after the dot. // Is it a zip/pk3 package? if(!stricmp(extension, "zip") || !stricmp(extension, "pk3")) { return Zip_Open(fileName, handle); } // Get a new file record. rec = W_RecordNew(); strncpy(rec->fileName, fileName, FILENAME_T_MAXLEN); convertSlashes(rec->fileName, FILENAME_T_MAXLEN); rec->handle = handle; // If we're not loading for startup, flag the record to be a Runtime one. if(!loadingForStartup) rec->flags = FRF_RUNTIME; if(stricmp(extension, "wad")) // lmp? { int offset = 0; char* slash = NULL; // Single lump file. fileInfo = &singleInfo; freeFileInfo = NULL; singleInfo.filePos = 0; singleInfo.size = LONG(F_Length(handle)); // Is there a prefix to be omitted in the name? slash = strrchr(fileName, DIR_SEP_CHAR); // The slash mustn't be too early in the string. if(slash && slash >= fileName + 2) { // Good old negative indices. if(slash[-2] == '.' && slash[-1] >= '1' && slash[-1] <= '9') { offset = slash[-1] - '1' + 1; } } M_ExtractFileBase2(singleInfo.name, fileName, 8, offset); rec->numLumps = 1; if(!stricmp(extension, "deh")) strncpy(fileInfo->name, "DEHACKED", 8); } else { // WAD file. F_Read(&header, sizeof(header), handle); if(!strncmp(header.identification, "JWAD", 4)) { // This is treated like an IWAD, but we won't set the // iwadLoaded flag. rec->iwad = true; } else if(strncmp(header.identification, "IWAD", 4)) { if(strncmp(header.identification, "PWAD", 4)) { // Bad file id Con_Error("Wad file %s doesn't have IWAD or PWAD id\n", fileName); } } else { // Found an IWAD. iwadLoaded = true; if(!stricmp(extension, "wad")) rec->iwad = true; } header.numLumps = LONG(header.numLumps); header.infoTableOfs = LONG(header.infoTableOfs); length = header.numLumps * sizeof(filelump_t); if(!(fileInfo = M_Malloc(length))) { Con_Error("W_AddFile: fileinfo malloc failed\n"); } freeFileInfo = fileInfo; F_Seek(handle, header.infoTableOfs, SEEK_SET); F_Read(fileInfo, length, handle); rec->numLumps = header.numLumps; } // Insert the lumps to lumpInfo, into their rightful places. W_InsertLumps(fileInfo, rec); if(freeFileInfo) M_Free(freeFileInfo); PrimaryLumpInfo = lumpInfo; PrimaryLumpCache = lumpCache; PrimaryNumLumps = numLumps; // Print the 'CRC' number of the IWAD, so it can be identified. if(rec->iwad) Con_Message(" IWAD identification: %08x\n", W_CRCNumberForRecord(rec - records)); return true; } boolean W_RemoveFile(const char *fileName) { int idx = W_RecordGetIdx(fileName); filerecord_t* rec; if(idx == -1) return false; // No such file loaded. rec = records + idx; // We must remove all the data of this file from the lump storage // (lumpInfo + lumpcache). W_RemoveLumpsWithHandle(rec->handle); // Resize the lump storage to match numLumps. W_ResizeLumpStorage(numLumps); // Close the file, we don't need it any more. F_Close(rec->handle); // Destroy the file record. W_RecordDestroy(idx); PrimaryLumpInfo = lumpInfo; PrimaryLumpCache = lumpCache; PrimaryNumLumps = numLumps; // Success! return true; } /** * Remove all records flagged Runtime. */ void W_Reset(void) { int i; for(i = 0; i < numRecords; ++i) if(records[i].flags & FRF_RUNTIME) W_RemoveFile(records[i].fileName); } /** * @return @c true, iff the given filename exists and * is an IWAD. */ int W_IsIWAD(const char* fn) { FILE* file; char id[5]; const char* ext; if(!M_FileExists(fn)) return false; // Determine the file name extension. ext = strrchr(fn, '.'); if(!ext) ext = ""; else ext++; // Move to point after the dot. // Is it a gwa file? these are NOT IWADs even though they may be marked // as such in the header... if(!stricmp(ext, "gwa")) return false; if((file = fopen(fn, "rb")) == NULL) return false; fread(id, 4, 1, file); id[4] = 0; fclose(file); return !stricmp(id, "IWAD"); } /** * Determines if a file name refers to a PK3 package. * * @param fn Path of the file. * * @return @c true, if the file is a PK3 package. */ boolean W_IsPK3(const char* fn) { size_t len = strlen(fn); return (len > 4 && (!strnicmp(fn + len - 4, ".pk3", 4) || !strnicmp(fn + len - 4, ".zip", 4))); } /** * Pass a null terminated list of files to use. All files are optional, but * at least one file must be found. Lump names can appear multiple times. * The name searcher looks backwards, so a later file can override an * earlier one. */ void W_InitMultipleFiles(char** fileNames) { char** ptr; int numLoaded = 0; byte* loaded = 0; // Count number of files. for(ptr = fileNames; *ptr; ptr++, numLoaded++); loaded = M_Calloc(numLoaded); iwadLoaded = false; // Open all the files, load headers, and count lumps numLumps = 0; lumpInfo = M_Malloc(1); // Will be realloced as lumps are added // This'll force the loader NOT the flag new records Runtime. (?) loadingForStartup = true; // Before anything else, load PK3s, because they may contain virtual // WAD files. (Should load WADs that have a DD_DIREC as well...) for(ptr = fileNames; *ptr; ptr++) if(W_IsPK3(*ptr)) { loaded[ptr - fileNames] = true; W_AddFile(*ptr, false); } // IWAD(s) must be loaded before other WADs. Let's see if one has been // specified with -iwad or -file options. for(ptr = fileNames; *ptr; ptr++) { if(W_IsIWAD(*ptr)) { loaded[ptr - fileNames] = true; W_AddFile(*ptr, false); } } // Do a full autoload round before loading any other WAD files. DD_AutoLoad(); // Make sure an IWAD gets loaded; if not, display a warning. W_CheckIWAD(); // Load the rest of the WADs. for(ptr = fileNames; *ptr; ptr++) if(!loaded[ptr - fileNames]) W_AddFile(*ptr, false); // Bookkeeping no longer needed. M_Free(loaded); loaded = NULL; if(!numLumps) { Con_Error("W_InitMultipleFiles: no files found.\n"); } } void W_EndStartup(void) { // No more WADs will be loaded in startup mode. loadingForStartup = false; } /** * Reallocate the lump cache so that it has the right amount of memory. */ void W_UpdateCache(void) { /* unsigned int i, numCopy; int size; void **newCache; size = numLumps * sizeof(*lumpCache); newCache = M_Malloc(size); memset(newcache, 0, size); // The cache is a list of pointers to the memory zone. We must // update the zone user pointers. numCopy = cachesize / sizeof(*lumpCache); // Copy this many. // If the new cache is smaller, don't copy too much. if((unsigned)numLumps < numCopy) { // for(i = numLumps; i < numCopy; ++i) // if(lumpCache[i]) // { // // The blocks aren't used by anyone any more. // Z_Free(lumpCache[i]); // } // numCopy = numLumps; Con_Error("W_UpdateCache: Trying to copy more lumps than there are.\n"); } for(i = 0; i < numCopy; i++) if(lumpCache[i]) Z_ChangeUser(lumpCache[i], newCache+i); // Copy the old cache contents. memcpy(newCache, lumpCache, numCopy * sizeof(*lumpCache)); // Get rid of the old cache. M_Free(lumpCache); lumpCache = newCache; cacheSize = size; PrimaryLumpInfo = lumpInfo; PrimaryLumpCache = lumpCache; PrimaryNumLumps = numLumps; */ } /** * Initialize the primary from a single file. */ void W_InitFile(char *fileName) { char *names[2]; names[0] = fileName; names[1] = NULL; W_InitMultipleFiles(names); } lumpnum_t W_OpenAuxiliary(const char *fileName) { int i; int size; wadinfo_t header; DFILE *handle; int length; filelump_t *fileInfo; filelump_t *sourceLump; lumpinfo_t *destLump; if(AuxiliaryOpened) { W_CloseAuxiliary(); } if((handle = F_Open(fileName, "rb")) == NULL) { Con_Error("W_OpenAuxiliary: %s not found.", fileName); return -1; } AuxiliaryHandle = handle; F_Read(&header, sizeof(header), handle); if(strncmp(header.identification, "IWAD", 4)) { if(strncmp(header.identification, "PWAD", 4)) { // Bad file id Con_Error("Wad file %s doesn't have IWAD or PWAD id\n", fileName); } } header.numLumps = LONG(header.numLumps); header.infoTableOfs = LONG(header.infoTableOfs); length = header.numLumps * sizeof(filelump_t); fileInfo = M_Malloc(length); F_Seek(handle, header.infoTableOfs, SEEK_SET); F_Read(fileInfo, length, handle); numLumps = header.numLumps; // Init the auxiliary lumpInfo array lumpInfo = Z_Malloc(numLumps * sizeof(lumpinfo_t), PU_STATIC, 0); sourceLump = fileInfo; destLump = lumpInfo; for(i = 0; i < numLumps; ++i, destLump++, sourceLump++) { destLump->handle = handle; destLump->position = LONG(sourceLump->filePos); destLump->size = LONG(sourceLump->size); strncpy(destLump->name, sourceLump->name, 8); } M_Free(fileInfo); // Allocate the auxiliary lumpcache array size = numLumps * sizeof(*lumpCache); lumpCache = Z_Malloc(size, PU_STATIC, 0); memset(lumpCache, 0, size); AuxiliaryLumpInfo = lumpInfo; AuxiliaryLumpCache = lumpCache; AuxiliaryNumLumps = numLumps; AuxiliaryOpened = true; return AUXILIARY_BASE; } static void W_CloseAuxiliary(void) { lumpnum_t i; if(AuxiliaryOpened) { W_UseAuxiliary(); for(i = 0; i < numLumps; ++i) { if(lumpCache[i]) { Z_Free(lumpCache[i]); } } Z_Free(AuxiliaryLumpInfo); Z_Free(AuxiliaryLumpCache); W_CloseAuxiliaryFile(); AuxiliaryOpened = false; } W_UsePrimary(); } /** * WARNING: W_CloseAuxiliary() must be called before any further auxiliary * lump processing. */ static void W_CloseAuxiliaryFile(void) { if(AuxiliaryHandle) { F_Close(AuxiliaryHandle); AuxiliaryHandle = 0; } } static void W_UsePrimary(void) { lumpInfo = PrimaryLumpInfo; numLumps = PrimaryNumLumps; lumpCache = PrimaryLumpCache; } static boolean W_UseAuxiliary(void) { if(AuxiliaryOpened == false) { // The auxiliary cache is not available at this time. return false; } lumpInfo = AuxiliaryLumpInfo; numLumps = AuxiliaryNumLumps; lumpCache = AuxiliaryLumpCache; return true; } int W_NumLumps(void) { return numLumps; } /** * Scan backwards so patch lump files take precedence. */ static lumpnum_t W_ScanLumpInfo(int v[2]) { lumpinfo_t* lump_p = lumpInfo + numLumps; while(lump_p-- != lumpInfo) { if(*(int *) lump_p->name == v[0] && *(int *) &lump_p->name[4] == v[1]) { // W_Index handles the conversion to a logical index that is // independent of the return W_Index(lump_p - lumpInfo); } } return -1; } /** * @return @c -1, if name not found, else lump num. */ lumpnum_t W_CheckNumForName(const char* name) { char name8[9]; int v[2]; lumpnum_t idx = -1; // If the name string is empty, don't bother to search. if(!name || !name[0]) { VERBOSE2(Con_Message("W_CheckNumForName: Empty name.\n")); return -1; } memset(name8, 0, sizeof(name8)); // Make the name into two integers for easy compares strncpy(name8, name, 8); strupr(name8); // case insensitive v[0] = *(int *) name8; v[1] = *(int *) &name8[4]; // We have to check both the primary and auxiliary caches because // we've only got a name and don't know where it is located. Start with // the auxiliary lumps because they take precedence. if(W_UseAuxiliary()) { idx = W_ScanLumpInfo(v); if(idx != -1) return idx; } W_UsePrimary(); idx = W_ScanLumpInfo(v); if(idx != -1) return idx; VERBOSE2(Con_Message("W_CheckNumForName: \"%s\" not found.\n", name8)); return -1; } /** * Calls W_CheckNumForName, but bombs out if not found. */ lumpnum_t W_GetNumForName(const char *name) { lumpnum_t i; i = W_CheckNumForName(name); if(i != -1) { return i; } Con_Error("W_GetNumForName: %s not found!", name); return -1; } /** * @return The buffer size needed to load the given lump. */ size_t W_LumpLength(lumpnum_t lump) { lump = W_Select(lump); if(lump >= numLumps) { Con_Error("W_LumpLength: %i >= numLumps", lump); } return lumpInfo[lump].size; } /** * Get the name of the given lump. */ const char *W_LumpName(lumpnum_t lump) { lump = W_Select(lump); if(lump >= numLumps || lump < 0) { return NULL; // The caller must be able to handle this... //Con_Error("W_LumpName: %i >= numLumps", lump); } return lumpInfo[lump].name; } /** * Loads the lump into the given buffer, which must be >= W_LumpLength(). */ void W_ReadLump(lumpnum_t lump, void *dest) { size_t c; lumpinfo_t *l; if(lump >= numLumps) { Con_Error("W_ReadLump: %i >= numLumps", lump); } l = &lumpInfo[lump]; F_Seek(l->handle, l->position, SEEK_SET); c = F_Read(dest, l->size, l->handle); if(c < l->size) { Con_Error("W_ReadLump: only read %lu of %lu on lump %i", (unsigned long) c, (unsigned long) l->size, lump); } } void W_ReadLumpSection(lumpnum_t lump, void *dest, size_t startOffset, size_t length) { size_t c; lumpinfo_t *l; lump = W_Select(lump); if(lump >= numLumps) { Con_Error("W_ReadLumpSection: %i >= numLumps", lump); } l = &lumpInfo[lump]; F_Seek(l->handle, l->position + startOffset, SEEK_SET); c = F_Read(dest, length, l->handle); if(c < length) { Con_Error("W_ReadLumpSection: only read %lu of %lu on lump %i", (unsigned long) c, (unsigned long) length, lump); } } /** * Writes the specifed lump to file with the given name. * * @param lump */ boolean W_DumpLump(lumpnum_t lump, const char* fileName) { FILE* file; const byte* lumpPtr; const char* fname; char buf[13]; // 8 (max lump chars) + 4 (ext) + 1. lump = W_Select(lump); if(lump >= numLumps) return false; lumpPtr = W_CacheLumpNum(lump, PU_STATIC); if(fileName && fileName[0]) { fname = fileName; } else { memset(buf, 0, sizeof(buf)); dd_snprintf(buf, 13, "%s.dum", lumpInfo[lump].name); fname = buf; } if(!(file = fopen(fname, "wb"))) { Con_Printf("Couldn't open %s for writing. %s\n", fname, strerror(errno)); W_ChangeCacheTag(lump, PU_CACHE); return false; } fwrite(lumpPtr, 1, lumpInfo[lump].size, file); fclose(file); W_ChangeCacheTag(lump, PU_CACHE); Con_Printf("%s dumped to %s.\n", lumpInfo[lump].name, fname); return true; } void W_DumpLumpDir(void) { char buff[10]; int p; printf("Lumps (%d total):\n", numLumps); for(p = 0; p < numLumps; p++) { strncpy(buff, W_LumpName(p), 8); buff[8] = 0; printf("%04i - %-8s (hndl: %p, pos: %i, size: %lu)\n", p, buff, lumpInfo[p].handle, lumpInfo[p].position, (unsigned long) lumpInfo[p].size); } Con_Error("---End of lumps---\n"); } /** * If called with the special purgelevel PU_GETNAME, returns a pointer * to the name of the lump. */ const void* W_CacheLumpNum(lumpnum_t absoluteLump, int tag) { byte *ptr; lumpnum_t lump = W_Select(absoluteLump); if((unsigned) lump >= (unsigned) numLumps) { Con_Error("W_CacheLumpNum: %i >= numLumps", lump); } // Return the name instead of data? if(tag == PU_GETNAME) { strncpy(retName, lumpInfo[lump].name, 8); retName[8] = 0; return retName; } if(!lumpCache[lump]) { // Need to read the lump in ptr = Z_Malloc(W_LumpLength(absoluteLump), tag, &lumpCache[lump]); W_ReadLump(lump, lumpCache[lump]); } else { Z_ChangeTag(lumpCache[lump], tag); } return lumpCache[lump]; } const void* W_CacheLumpName(const char* name, int tag) { return W_CacheLumpNum(W_GetNumForName(name), tag); } void W_ChangeCacheTag(lumpnum_t lump, int tag) { if(lumpCache[lump]) //if(Z_GetBlock(lumpCache[lump])->id == 0x1d4a11) { Z_ChangeTag2(lumpCache[lump], tag); } } /** * Checks if an IWAD has been loaded. If not, tries to load one of the * default ones. */ void W_CheckIWAD(void) { extern char* iwadList[]; int i; if(iwadLoaded) return; // Try one of the default IWADs. for(i = 0; iwadList[i]; ++i) { if(M_FileExists(iwadList[i])) W_AddFile(iwadList[i], false); // We can leave as soon as an IWAD is found. if(iwadLoaded) return; } if(!Sys_CriticalMessage ("No IWAD has been specified! " "Important data might be missing. Are you sure you " "want to continue?")) Con_Error("W_CheckIWAD: Init aborted.\n"); } /** * @return The name of the WAD file where the given lump resides. * Always returns a valid filename (or an empty string). */ const char *W_LumpSourceFile(lumpnum_t lump) { int i; lumpinfo_t *l; lump = W_Select(lump); if(lump < 0 || lump >= numLumps) Con_Error("W_LumpSourceFile: Bad lump number: %i.", lump); l = lumpInfo + lump; for(i = 0; i < numRecords; ++i) if(records[i].handle == l->handle) return records[i].fileName; return ""; } /** * An extremely simple formula. Does not conform to any CRC standard. * (So why's it called CRC, then?) */ unsigned int W_CRCNumberForRecord(int idx) { lumpnum_t i; int k; unsigned int crc = 0; if(idx < 0 || idx >= numRecords) return 0; for(i = 0; i < numLumps; ++i) { if(lumpInfo[i].handle != records[idx].handle) continue; crc += lumpInfo[i].size; for(k = 0; k < 8; ++k) crc += lumpInfo[i].name[k]; } return crc; } /** * Calculated using the lumps of the main IWAD. */ unsigned int W_CRCNumber(void) { int i; // Find the IWAD's record. for(i = 0; i < numRecords; ++i) if(records[i].iwad) return W_CRCNumberForRecord(i); return 0; } /** * Copies the file name of the IWAD to the given buffer. */ void W_GetIWADFileName(char* buf, size_t bufSize) { int i; // Find the IWAD's record. for(i = 0; i < numRecords; ++i) if(records[i].iwad) { filename_t temp; Dir_FileName(temp, records[i].fileName, FILENAME_T_MAXLEN); strupr(temp); strncpy(buf, temp, bufSize); break; } } /** * Compiles a list of PWAD file names, separated by the specified character. */ void W_GetPWADFileNames(char* buf, size_t bufSize, char separator) { int i; for(i = 0; i < numRecords; ++i) if(!records[i].iwad) { filename_t temp; Dir_FileName(temp, records[i].fileName, FILENAME_T_MAXLEN); if(!stricmp(temp + strlen(temp) - 3, "lmp")) continue; M_LimitedStrCat(buf, temp, 64, separator, bufSize); } } /** * @return @ true, if the specified lump is in an IWAD. * Otherwise it's from a PWAD. */ boolean W_IsFromIWAD(lumpnum_t lump) { int i; lump = W_Select(lump); if(lump < 0 || lump >= numLumps) { // This lump doesn't exist. return false; } for(i = 0; i < numRecords; ++i) if(records[i].handle == lumpInfo[lump].handle) return records[i].iwad != 0; return false; } #if 0 /** * \fixme What about GL data? * * Change the map identifiers of all the maps in a PWAD. * 'episode' and 'map' are used with the first map in the PWAD, the rest * get incremented. */ boolean W_RemapPWADMaps(const char* pwadName, int episode, int map) { int i; filerecord_t* rec; filename_t baseName, buf; // Try matching the full name first. if((i = W_RecordGetIdx(pwadName)) < 0) { // Then the base name only. M_ExtractFileBase(baseName, pwadName, FILENAME_T_MAXLEN); for(i = 0; i < numRecords; ++i) { M_ExtractFileBase(buf, records[i].fileName, FILENAME_T_MAXLEN); if(!stricmp(baseName, buf)) break; } if(i == numRecords) { Con_Printf("%s has not been loaded.\n", pwadName); return false; } } rec = records + i; if(rec->iwad) { Con_Printf("%s is an IWAD!\n", rec->fileName); return false; } Con_Printf("Renumbering maps in %s.\n", rec->fileName); for(i = 0; i < numLumps; ++i) { // We'll only modify the maps if(lumpInfo[i].handle != rec->handle) continue; } return true; } #endif D_CMD(LoadFile) { int i, succeeded = false; for(i = 1; i < argc; ++i) { Con_Message("Loading %s...\n", argv[i]); if(W_AddFile(argv[i], true)) { Con_Message("OK\n"); succeeded = true; // At least one has been loaded. } else Con_Message("Failed!\n"); } // We only need to update if something was actually loaded. if(succeeded) { // Update the lumpcache. //W_UpdateCache(); // The new wad may contain lumps that alter the current ones // in use. DD_UpdateEngineState(); } return true; } D_CMD(UnloadFile) { int i, succeeded = false; for(i = 1; i < argc; ++i) { filename_t file; strncpy(file, argv[i], FILENAME_T_MAXLEN); Con_Message("Unloading %s...\n", file); if(W_RemoveFile(file)) { Con_Message("OK\n"); succeeded = true; } else Con_Message("Failed!\n"); } if(succeeded) DD_UpdateEngineState(); return true; } D_CMD(Dump) { lumpnum_t lump; if((lump = W_CheckNumForName(argv[1])) == -1) { Con_Printf("No such lump.\n"); return false; } if(!W_DumpLump(lump, NULL)) return false; return true; } /** * Print contents of directories as Doomsday sees them. */ D_CMD(Dir) { filename_t dir, pattern; int i; for(i = 1; i < argc; ++i) { M_PrependBasePath(dir, argv[i], FILENAME_T_MAXLEN); Dir_ValidDir(dir, FILENAME_T_MAXLEN); Dir_MakeAbsolute(dir, FILENAME_T_MAXLEN); Con_Printf("Directory: %s\n", dir); // Make the pattern. dd_snprintf(pattern, FILENAME_T_MAXLEN, "%s*", dir); F_ForAll(pattern, dir, Con_PrintFileName); } return true; } D_CMD(ListFiles) { int i; for(i = 0; i < numRecords; ++i) { Con_Printf("%s (%d lump%s%s)", records[i].fileName, records[i].numLumps, records[i].numLumps != 1 ? "s" : "", !(records[i].flags & FRF_RUNTIME) ? ", startup" : ""); if(records[i].iwad) Con_Printf(" [%08x]", W_CRCNumberForRecord(i)); Con_Printf("\n"); } Con_Printf("Total: %d lumps in %d files.\n", numLumps, numRecords); return true; } D_CMD(ResetLumps) { GL_SetFilter(false); W_Reset(); Con_Message("Only startup files remain.\n"); DD_UpdateEngineState(); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/con_config.c0000644000175000017500000001350211357170241023201 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_config.c: Config Files */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static char cfgFile[256]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- boolean Con_ParseCommands(const char* fileName, boolean setdefault) { DFILE* file; char buff[512]; int line = 1; // Is this supposed to be the default? if(setdefault) strcpy(cfgFile, fileName); // Open the file. if((file = F_Open(fileName, "rt")) == NULL) return false; VERBOSE(Con_Printf ("Con_ParseCommands: %s (def:%i)\n", fileName, setdefault)); // This file is filled with console commands. // Each line is a command. for(;;) { M_ReadLine(buff, 512, file); if(buff[0] && !M_IsComment(buff)) { // Execute the commands silently. if(!Con_Execute(CMDS_CONFIG, buff, setdefault, false)) Con_Message("%s(%d): error executing command\n" " \"%s\"\n", fileName, line, buff); } if(deof(file)) break; line++; } F_Close(file); return true; } static void Con_WriteHeaderComment(FILE* file) { fprintf(file, "# %s / Doomsday Engine " DOOMSDAY_VERSION_TEXT "\n", (char *) gx.GetVariable(DD_GAME_ID)); fprintf(file, "# This configuration file is generated automatically. Each line is a\n"); fprintf(file, "# console command. Lines beginning with # are comments. Use autoexec.cfg\n"); fprintf(file, "# for your own startup commands.\n\n"); } /** * Writes the state of the console (variables, bindings, aliases) into * the given file, overwriting the previous contents. */ boolean Con_WriteState(const char *fileName, const char *bindingsFileName) { unsigned int i; cvar_t *var; FILE *file; char *str; void *ccmd_help; unsigned int numCVars = Con_CVarCount(); VERBOSE(Con_Printf("Con_WriteState: %s; %s\n", fileName, bindingsFileName)); if((file = fopen(fileName, "wt")) == NULL) { Con_Message("Con_WriteState: Can't open %s for writing.\n", fileName); return false; } Con_WriteHeaderComment(file); fprintf(file, "#\n# CONSOLE VARIABLES\n#\n\n"); // We'll write all the console variables that are flagged for archiving. for(i = 0; i < numCVars; ++i) { var = Con_GetVariableIDX(i); if(var->type == CVT_NULL || var->flags & CVF_NO_ARCHIVE) continue; // First print the comment (help text). ccmd_help = DH_Find(var->name); if((str = DH_GetString(ccmd_help, HST_DESCRIPTION))) M_WriteCommented(file, str); fprintf(file, "%s ", var->name); if(var->flags & CVF_PROTECTED) fprintf(file, "force "); if(var->type == CVT_BYTE) fprintf(file, "%d", *(byte *) var->ptr); if(var->type == CVT_INT) fprintf(file, "%d", *(int *) var->ptr); if(var->type == CVT_FLOAT) fprintf(file, "%s", TrimmedFloat(*(float *) var->ptr)); if(var->type == CVT_CHARPTR) { fprintf(file, "\""); M_WriteTextEsc(file, *(char **) var->ptr); fprintf(file, "\""); } fprintf(file, "\n\n"); } fprintf(file, "\n#\n# ALIASES\n#\n\n"); Con_WriteAliasesToFile(file); fclose(file); if(bindingsFileName) { // Bindings go a separate file. if((file = fopen(bindingsFileName, "wt")) == NULL) { Con_Message("Con_WriteState: Can't open %s for writing.\n", bindingsFileName); return false; } Con_WriteHeaderComment(file); B_WriteToFile(file); fclose(file); } return true; } /** * Saves all bindings, aliases and archiveable console variables. * The output file is a collection of console commands. */ void Con_SaveDefaults(void) { Con_WriteState(cfgFile, (isDedicated? NULL : bindingsConfigFileName)); } D_CMD(WriteConsole) { Con_Message("Writing to %s...\n", argv[1]); return !Con_WriteState(argv[1], NULL); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_string.c0000644000175000017500000002307411357170242022725 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_string.c: Dynamic Strings * * Simple dynamic string management. * Uses the memory zone for memory allocation. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_base.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define MAX_LENGTH 0x4000 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Call this for uninitialized strings. Global variables are * automatically cleared, so they don't need initialization. */ void Str_Init(ddstring_t *ds) { memset(ds, 0, sizeof(*ds)); } /** * Empty an existing string. After this the string is in the same * state as just after being initialized. */ void Str_Free(ddstring_t *ds) { if(ds->size) { // The string has memory allocated, free it. Z_Free(ds->str); } memset(ds, 0, sizeof(*ds)); } /** * Allocate a new uninitialized string. Use Str_Delete() to destroy * the returned string. * * @return New ddstring_t instance. * * @see Str_Delete */ ddstring_t *Str_New(void) { return M_Calloc(sizeof(ddstring_t)); } /** * Destroy a string allocated with Str_New(). In addition to freeing * the contents of the string, it also unallocates the string instance * that was created by Str_New(). * * @param ds String to delete (that was returned by Str_New()). */ void Str_Delete(ddstring_t *ds) { Str_Free(ds); M_Free(ds); } /** * Empties a string, but does not free its memory. */ void Str_Clear(ddstring_t *ds) { Str_Set(ds, ""); } /** * Allocates so much memory that for_length characters will fit. */ void Str_Alloc(ddstring_t *ds, size_t for_length, int preserve) { boolean old_data = false; char *buf; // Include the terminating null character. for_length++; if(ds->size >= for_length) return; // We're OK. // Already some memory allocated? if(ds->size) old_data = true; else ds->size = 1; while(ds->size < for_length) ds->size *= 2; buf = Z_Calloc(ds->size, PU_STATIC, 0); if(preserve && ds->str) strncpy(buf, ds->str, ds->size - 1); // Replace the old string with the new buffer. if(old_data) Z_Free(ds->str); ds->str = buf; } void Str_Reserve(ddstring_t *ds, size_t length) { Str_Alloc(ds, length, true); } void Str_Set(ddstring_t *ds, const char *text) { size_t incoming = strlen(text); Str_Alloc(ds, incoming, false); strcpy(ds->str, text); ds->length = incoming; } void Str_Append(ddstring_t *ds, const char *append_text) { size_t incoming = strlen(append_text); // Don't allow extremely long strings. if(ds->length > MAX_LENGTH) return; Str_Alloc(ds, ds->length + incoming, true); strcpy(ds->str + ds->length, append_text); ds->length += incoming; } void Str_AppendChar(ddstring_t* ds, char ch) { char str[2] = { ch, 0 }; Str_Append(ds, str); } /** * Append formated text. */ void Str_Appendf(ddstring_t *ds, const char *format, ...) { char buf[1024]; va_list args; // Print the message into the buffer. va_start(args, format); dd_vsnprintf(buf, sizeof(buf), format, args); va_end(args); Str_Append(ds, buf); } /** * Appends a portion of a string. */ void Str_PartAppend(ddstring_t *dest, const char *src, int start, size_t count) { Str_Alloc(dest, dest->length + count + 1, true); memcpy(dest->str + dest->length, src + start, count); dest->length += count; // Terminate the appended part. dest->str[dest->length] = 0; } /** * Prepend is not even a word, is it? It should be 'prefix'? */ void Str_Prepend(ddstring_t *ds, const char *prepend_text) { size_t incoming = strlen(prepend_text); // Don't allow extremely long strings. if(ds->length > MAX_LENGTH) return; Str_Alloc(ds, ds->length + incoming, true); memmove(ds->str + incoming, ds->str, ds->length + 1); memcpy(ds->str, prepend_text, incoming); ds->length += incoming; } /** * This is safe for all strings. */ char *Str_Text(ddstring_t *ds) { return ds->str ? ds->str : ""; } /** * This is safe for all strings. */ size_t Str_Length(ddstring_t *ds) { if(ds->length) return ds->length; return strlen(Str_Text(ds)); } /** * Makes a true copy. */ void Str_Copy(ddstring_t *dest, ddstring_t *src) { Str_Free(dest); dest->size = src->size; dest->length = src->length; dest->str = Z_Malloc(src->size, PU_STATIC, 0); memcpy(dest->str, src->str, src->size); } /** * Strip whitespace from beginning. */ void Str_StripLeft(ddstring_t *ds) { size_t i, num; boolean isDone; if(!ds->length) return; // Find out how many whitespace chars are at the beginning. isDone = false; i = 0; num = 0; while(i < ds->length && !isDone) { if(isspace(ds->str[i])) { num++; i++; } else isDone = true; } if(num) { // Remove 'num' chars. memmove(ds->str, ds->str + num, ds->length - num); ds->length -= num; ds->str[ds->length] = 0; } } /** * Strip whitespace from end. */ void Str_StripRight(ddstring_t *ds) { int i; boolean isDone; if(ds->length == 0) return; i = ds->length - 1; isDone = false; while(i >= 0 && !isDone) { if(isspace(ds->str[i])) { // Remove this char. ds->str[i] = 0; ds->length--; i--; } else { isDone = true; } } } /** * Strip whitespace from beginning and end. */ void Str_Strip(ddstring_t *ds) { Str_StripLeft(ds); Str_StripRight(ds); } /** * Extract a line of text from the source. */ const char *Str_GetLine(ddstring_t *ds, const char *src) { char buf[2]; // We'll append the chars one by one. memset(buf, 0, sizeof(buf)); for(Str_Clear(ds); *src && *src != '\n'; src++) { if(*src != '\r') { buf[0] = *src; Str_Append(ds, buf); } } // Strip whitespace around the line. Str_Strip(ds); // The newline is excluded. if(*src == '\n') src++; return src; } /** * Performs a string comparison, ignoring differences in case. */ int Str_CompareIgnoreCase(ddstring_t *ds, const char *text) { return strcasecmp(Str_Text(ds), text); } /** * Copies characters from @c to @dest until a @c delim character is encountered. * Also ignores all whitespace characters. * * @param dest Destination string. * @param src Source string. * @param delim Delimiter character, where copying will stop. * * @return Pointer to the character within @c src past the delimiter, or NULL if the * source data ended. */ const char* Str_CopyDelim(ddstring_t* dest, const char* src, char delim) { Str_Clear(dest); if(!src) return NULL; for(; *src && *src != delim; ++src) { if(!isspace(*src)) Str_PartAppend(dest, src, 0, 1); } if(!*src) return NULL; // It ended. // Skip past the delimiter. return src + 1; } /** * Retrieves a character in the string. * * @param str String to get the character from. * @param index Index of the character. * * @return The character at @c index, or 0 if the index is not in range. */ char Str_At(ddstring_t* str, int index) { if(index < 0 || index >= str->length) { return 0; } return str->str[index]; } /** * Retrieves a character in the string. Indices start from the end of the string. * * @param str String to get the character from. * @param reverseIndex Index of the character, where 0 is the last character of the string. * * @return The character at @c index, or 0 if the index is not in range. */ char Str_RAt(ddstring_t* str, int reverseIndex) { if(reverseIndex < 0 || reverseIndex >= str->length) { return 0; } return str->str[str->length - 1 - reverseIndex]; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_world.c0000644000175000017500000006005511357170241022707 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_world.c: Clientside World Management */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_play.h" #include "de_refresh.h" #include "r_util.h" // MACROS ------------------------------------------------------------------ #define MAX_MOVERS 128 // Definitely enough! #define MAX_TRANSLATIONS 16384 #define MVF_CEILING 0x1 // Move ceiling. #define MVF_SET_FLOORPIC 0x2 // Set floor texture when move done. // TYPES ------------------------------------------------------------------- typedef struct { thinker_t thinker; sector_t *sector; uint sectornum; clmovertype_t type; float *current; float destination; float speed; } mover_t; typedef struct { thinker_t thinker; uint number; polyobj_t *poly; boolean move; boolean rotate; } polymover_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static mover_t *activemovers[MAX_MOVERS]; static polymover_t *activepolys[MAX_MOVERS]; short *xlat_lump; // CODE -------------------------------------------------------------------- /** * Allocates and inits the lump translation array. Clients use this * to make sure lump references are correct (in case the server and the * client are using different WAD configurations and the lump index * numbers happen to differ). * * \fixme A bit questionable? Why not allow the clients to download * data from the server in ambiguous cases? */ void Cl_InitTranslations(void) { int i; xlat_lump = Z_Malloc(sizeof(short) * MAX_TRANSLATIONS, PU_REFRESHTEX, 0); memset(xlat_lump, 0, sizeof(short) * MAX_TRANSLATIONS); for(i = 0; i < numLumps; ++i) xlat_lump[i] = i; // Identity translation. } void Cl_SetLumpTranslation(lumpnum_t lump, char *name) { if(lump < 0 || lump >= MAX_TRANSLATIONS) return; // Can't do it, sir! We just don't the power!! xlat_lump[lump] = W_CheckNumForName(name); if(xlat_lump[lump] < 0) { VERBOSE(Con_Message("Cl_SetLumpTranslation: %s not found.\n", name)); xlat_lump[lump] = 0; } } /** * This is a fail-safe operation. */ lumpnum_t Cl_TranslateLump(lumpnum_t lump) { if(lump < 0 || lump >= MAX_TRANSLATIONS) return 0; return xlat_lump[lump]; } /** * Clears the arrays that track active plane and polyobj mover thinkers. */ void Cl_InitMovers(void) { memset(activemovers, 0, sizeof(activemovers)); memset(activepolys, 0, sizeof(activepolys)); } void Cl_RemoveActiveMover(mover_t *mover) { int i; for(i = 0; i < MAX_MOVERS; ++i) if(activemovers[i] == mover) { P_ThinkerRemove(&mover->thinker); activemovers[i] = NULL; break; } } /** * Removes the given polymover from the active polys array. */ void Cl_RemoveActivePoly(polymover_t *mover) { int i; for(i = 0; i < MAX_MOVERS; ++i) if(activepolys[i] == mover) { P_ThinkerRemove(&mover->thinker); activepolys[i] = NULL; break; } } /** * Plane mover. */ void Cl_MoverThinker(mover_t *mover) { float *current = mover->current, original = *current; boolean remove = false; boolean freeMove; float fspeed; if(!Cl_GameReady()) return; // Can we think yet? // The move is cancelled if the consolePlayer becomes obstructed. freeMove = Cl_IsFreeToMove(consolePlayer); fspeed = mover->speed; // How's the gap? if(fabs(mover->destination - *current) > fabs(fspeed)) { // Do the move. *current += fspeed; } else { // We have reached the destination. *current = mover->destination; // This thinker can now be removed. remove = true; } P_SectorPlanesChanged(mover->sector); // Make sure the client didn't get stuck as a result of this move. if(freeMove != Cl_IsFreeToMove(consolePlayer)) { // Something was blocking the way! *current = original; P_SectorPlanesChanged(mover->sector); } else if(remove) // Can we remove this thinker? { Cl_RemoveActiveMover(mover); } } void Cl_AddMover(uint sectornum, clmovertype_t type, float dest, float speed) { sector_t *sector; int i; mover_t *mov; VERBOSE( Con_Printf("Cl_AddMover: Sector=%i, type=%s, dest=%f, speed=%f\n", sectornum, type==MVT_FLOOR? "floor" : "ceiling", dest, speed) ); if(speed == 0) return; if(sectornum >= numSectors) return; sector = SECTOR_PTR(sectornum); // Remove any existing movers for the same plane. for(i = 0; i < MAX_MOVERS; ++i) if(activemovers[i] && activemovers[i]->sector == sector && activemovers[i]->type == type) { Cl_RemoveActiveMover(activemovers[i]); } /*if(!speed) // Lightspeed? { // Change immediately. if(type == MVT_CEILING) sector->planes[PLN_CEILING].height = dest; else sector->planes[PLN_FLOOR].height = dest; return; } */ // Add a new mover. for(i = 0; i < MAX_MOVERS; ++i) if(activemovers[i] == NULL) { // Allocate a new mover_t thinker. mov = activemovers[i] = Z_Malloc(sizeof(mover_t), PU_MAP, 0); memset(mov, 0, sizeof(mover_t)); mov->thinker.function = Cl_MoverThinker; mov->type = type; mov->sectornum = sectornum; mov->sector = SECTOR_PTR(sectornum); mov->destination = dest; mov->speed = speed; mov->current = (type == MVT_FLOOR ? &mov->sector->planes[PLN_FLOOR]->height : &mov->sector-> planes[PLN_CEILING]->height); // Set the right sign for speed. if(mov->destination < *mov->current) mov->speed = -mov->speed; // \fixme Do these need to be public? P_ThinkerAdd(&mov->thinker, true); break; } } void Cl_PolyMoverThinker(polymover_t* mover) { polyobj_t* poly = mover->poly; float dx, dy; float dist; if(mover->move) { // How much to go? dx = poly->dest[VX] - poly->pos[VX]; dy = poly->dest[VY] - poly->pos[VY]; dist = P_ApproxDistance(dx, dy); if(dist <= poly->speed || poly->speed == 0) { // We'll arrive at the destination. mover->move = false; } else { // Adjust deltas to fit speed. dx = poly->speed * (dx / dist); dy = poly->speed * (dy / dist); } // Do the move. P_PolyobjMove(P_GetPolyobj(mover->number | 0x80000000), dx, dy); } if(mover->rotate) { // How much to go? dist = FIX2FLT(poly->destAngle - poly->angle); if((abs(FLT2FIX(dist) >> 4) <= abs(((signed) poly->angleSpeed) >> 4) /* && poly->destAngle != -1*/) || !poly->angleSpeed) { // We'll arrive at the destination. mover->rotate = false; } else { // Adjust to speed. dist = FIX2FLT(poly->angleSpeed); } P_PolyobjRotate(P_GetPolyobj(mover->number | 0x80000000), FLT2FIX(dist)); } // Can we get rid of this mover? if(!mover->move && !mover->rotate) Cl_RemoveActivePoly(mover); } polymover_t* Cl_FindActivePoly(uint number) { uint i; for(i = 0; i < MAX_MOVERS; ++i) if(activepolys[i] && activepolys[i]->number == number) return activepolys[i]; return NULL; } polymover_t* Cl_NewPolyMover(uint number) { polymover_t* mover; polyobj_t* poly = polyObjs[number]; mover = Z_Malloc(sizeof(polymover_t), PU_MAP, 0); memset(mover, 0, sizeof(*mover)); mover->thinker.function = Cl_PolyMoverThinker; mover->poly = poly; mover->number = number; // \fixme Do these need to be public? P_ThinkerAdd(&mover->thinker, true); return mover; } void Cl_SetPolyMover(uint number, int move, int rotate) { polymover_t* mover; // Try to find an existing mover. mover = Cl_FindActivePoly(number); if(!mover) mover = Cl_NewPolyMover(number); // Flag for moving. if(move) mover->move = true; if(rotate) mover->rotate = true; } /** * Removes all the active movers. */ void Cl_RemoveMovers(void) { int i; for(i = 0; i < MAX_MOVERS; ++i) { if(activemovers[i]) { P_ThinkerRemove(&activemovers[i]->thinker); activemovers[i] = NULL; } if(activepolys[i]) { P_ThinkerRemove(&activepolys[i]->thinker); activepolys[i] = NULL; } } } mover_t *Cl_GetActiveMover(uint sectornum, clmovertype_t type) { int i; for(i = 0; i < MAX_MOVERS; ++i) if(activemovers[i] && activemovers[i]->sectornum == sectornum && activemovers[i]->type == type) { return activemovers[i]; } return NULL; } /** * @return @c false, if the end marker is found (lump * index zero). */ int Cl_ReadLumpDelta(void) { lumpnum_t num = (lumpnum_t) Msg_ReadPackedShort(); char name[9]; if(!num) return false; // No more. // Read the name of the lump. memset(name, 0, sizeof(name)); Msg_Read(name, 8); VERBOSE(Con_Printf("LumpTranslate: %i => %s\n", num, name)); // Set up translation. Cl_SetLumpTranslation(num, name); return true; } /** * Reads a sector delta from the PSV_FRAME2 message buffer and applies it * to the world. */ void Cl_ReadSectorDelta2(int deltaType, boolean skip) { static sector_t dummy; // Used when skipping. static plane_t* dummyPlaneArray[2]; static plane_t dummyPlanes[2]; unsigned short num; sector_t* sec; int df; boolean wasChanged = false; // Set up the dummy. dummyPlaneArray[0] = &dummyPlanes[0]; dummyPlaneArray[1] = &dummyPlanes[1]; dummy.planes = dummyPlaneArray; // Sector index number. num = Msg_ReadShort(); // Flags. if(deltaType == DT_SECTOR_R6) { // The R6 protocol reserves two bytes for the flags. df = Msg_ReadShort(); } else { df = Msg_ReadPackedLong(); } if(!skip) { #ifdef _DEBUG if(num >= numSectors) { // This is worrisome. Con_Error("Cl_ReadSectorDelta2: Sector %i out of range.\n", num); } #endif sec = SECTOR_PTR(num); } else { // Read the data into the dummy if we're skipping. sec = &dummy; } if(df & SDF_FLOOR_MATERIAL) { material_t* mat; /** * The delta is a server-side materialnum. * \fixme What if client and server materialnums differ? */ mat = P_ToMaterial(Msg_ReadPackedShort()); Surface_SetMaterial(&sec->SP_floorsurface, mat); } if(df & SDF_CEILING_MATERIAL) { material_t* mat; /** * The delta is a server-side materialnum. * \fixme What if client and server materialnums differ? */ mat = P_ToMaterial(Msg_ReadPackedShort()); Surface_SetMaterial(&sec->SP_ceilsurface, mat); } if(df & SDF_LIGHT) sec->lightLevel = Msg_ReadByte() / 255.0f; if(df & SDF_FLOOR_HEIGHT) { sec->planes[PLN_FLOOR]->height = FIX2FLT(Msg_ReadShort() << 16); wasChanged = true; if(!skip) { VERBOSE( Con_Printf("Cl_ReadSectorDelta2: (%i) Absolute floor height=%f\n", num, sec->SP_floorheight) ); } } if(df & SDF_CEILING_HEIGHT) { fixed_t height = Msg_ReadShort() << 16; if(!skip) { sec->planes[PLN_CEILING]->height = FIX2FLT(height); wasChanged = true; VERBOSE( Con_Printf("Cl_ReadSectorDelta2: (%i) Absolute ceiling height=%f%s\n", num, sec->SP_ceilheight, skip? " --SKIPPED!--" : "") ); } } if(df & SDF_FLOOR_TARGET) { fixed_t height = Msg_ReadShort() << 16; if(!skip) { sec->planes[PLN_FLOOR]->target = FIX2FLT(height); VERBOSE( Con_Printf("Cl_ReadSectorDelta2: (%i) Floor target=%f\n", num, sec->planes[PLN_FLOOR]->target) ); } } if(df & SDF_FLOOR_SPEED) { fixed_t speed = Msg_ReadByte(); if(!skip) { sec->planes[PLN_FLOOR]->speed = FIX2FLT(speed << (df & SDF_FLOOR_SPEED_44 ? 12 : 15)); VERBOSE( Con_Printf("Cl_ReadSectorDelta2: (%i) Floor speed=%f\n", num, sec->planes[PLN_FLOOR]->speed) ); } } if(df & SDF_FLOOR_TEXMOVE) { // Old clients might include these. fixed_t moveX = Msg_ReadShort() << 8; fixed_t moveY = Msg_ReadShort() << 8; } if(df & SDF_CEILING_TARGET) { fixed_t target = Msg_ReadShort() << 16; if(!skip) { sec->planes[PLN_CEILING]->target = FIX2FLT(target); VERBOSE( Con_Printf("Cl_ReadSectorDelta2: (%i) Ceiling target=%f\n", num, sec->planes[PLN_CEILING]->target) ); } } if(df & SDF_CEILING_SPEED) { byte speed = Msg_ReadByte(); if(!skip) { sec->planes[PLN_CEILING]->speed = FIX2FLT(speed << (df & SDF_CEILING_SPEED_44 ? 12 : 15)); VERBOSE( Con_Printf("Cl_ReadSectorDelta2: (%i) Ceiling speed=%f\n", num, sec->planes[PLN_CEILING]->speed) ); } } if(df & SDF_CEILING_TEXMOVE) { // Old clients might include these. fixed_t moveX = Msg_ReadShort() << 8; fixed_t moveY = Msg_ReadShort() << 8; } if(df & SDF_COLOR_RED) sec->rgb[0] = Msg_ReadByte() / 255.f; if(df & SDF_COLOR_GREEN) sec->rgb[1] = Msg_ReadByte() / 255.f; if(df & SDF_COLOR_BLUE) sec->rgb[2] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_COLOR_RED) Surface_SetColorR(&sec->SP_floorsurface, Msg_ReadByte() / 255.f); if(df & SDF_FLOOR_COLOR_GREEN) Surface_SetColorG(&sec->SP_floorsurface, Msg_ReadByte() / 255.f); if(df & SDF_FLOOR_COLOR_BLUE) Surface_SetColorB(&sec->SP_floorsurface, Msg_ReadByte() / 255.f); if(df & SDF_CEIL_COLOR_RED) Surface_SetColorR(&sec->SP_ceilsurface, Msg_ReadByte() / 255.f); if(df & SDF_CEIL_COLOR_GREEN) Surface_SetColorG(&sec->SP_ceilsurface, Msg_ReadByte() / 255.f); if(df & SDF_CEIL_COLOR_BLUE) Surface_SetColorB(&sec->SP_ceilsurface, Msg_ReadByte() / 255.f); if(df & SDF_FLOOR_GLOW_RED) sec->planes[PLN_FLOOR]->glowRGB[0] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_GLOW_GREEN) sec->planes[PLN_FLOOR]->glowRGB[1] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_GLOW_BLUE) sec->planes[PLN_FLOOR]->glowRGB[2] = Msg_ReadByte() / 255.f; if(df & SDF_CEIL_GLOW_RED) sec->planes[PLN_CEILING]->glowRGB[0] = Msg_ReadByte() / 255.f; if(df & SDF_CEIL_GLOW_GREEN) sec->planes[PLN_CEILING]->glowRGB[1] = Msg_ReadByte() / 255.f; if(df & SDF_CEIL_GLOW_BLUE) sec->planes[PLN_CEILING]->glowRGB[2] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_GLOW) sec->planes[PLN_FLOOR]->glow = (float) Msg_ReadShort() / DDMAXSHORT; if(df & SDF_CEIL_GLOW) sec->planes[PLN_CEILING]->glow = (float) Msg_ReadShort() / DDMAXSHORT; // The whole delta has been read. If we're about to skip, let's do so. if(skip) return; // If the plane heights were changed, we need to update the mobjs in // the sector. if(wasChanged) { P_SectorPlanesChanged(sec); } // Do we need to start any moving planes? if(df & (SDF_FLOOR_TARGET | SDF_FLOOR_SPEED)) { Cl_AddMover(num, MVT_FLOOR, sec->planes[PLN_FLOOR]->target, sec->planes[PLN_FLOOR]->speed); } if(df & (SDF_CEILING_TARGET | SDF_CEILING_SPEED)) { Cl_AddMover(num, MVT_CEILING, sec->planes[PLN_CEILING]->target, sec->planes[PLN_CEILING]->speed); } } /** * Reads a side delta from the message buffer and applies it to the world. */ void Cl_ReadSideDelta2(int deltaType, boolean skip) { unsigned short num; int df, topMat = 0, midMat = 0, botMat = 0; int blendmode = 0; byte lineFlags = 0, sideFlags = 0; float toprgb[3] = {0,0,0}, midrgba[4] = {0,0,0,0}; float bottomrgb[3] = {0,0,0}; sidedef_t *sid; // First read all the data. num = Msg_ReadShort(); // Flags. if(deltaType == DT_SIDE_R6) { // The R6 protocol reserves a single byte for a side delta. df = Msg_ReadByte(); } else { df = Msg_ReadPackedLong(); } if(df & SIDF_TOP_MATERIAL) topMat = Msg_ReadPackedShort(); if(df & SIDF_MID_MATERIAL) midMat = Msg_ReadPackedShort(); if(df & SIDF_BOTTOM_MATERIAL) botMat = Msg_ReadPackedShort(); if(df & SIDF_LINE_FLAGS) lineFlags = Msg_ReadByte(); if(df & SIDF_TOP_COLOR_RED) toprgb[CR] = Msg_ReadByte() / 255.f; if(df & SIDF_TOP_COLOR_GREEN) toprgb[CG] = Msg_ReadByte() / 255.f; if(df & SIDF_TOP_COLOR_BLUE) toprgb[CB] = Msg_ReadByte() / 255.f; if(df & SIDF_MID_COLOR_RED) midrgba[CR] = Msg_ReadByte() / 255.f; if(df & SIDF_MID_COLOR_GREEN) midrgba[CG] = Msg_ReadByte() / 255.f; if(df & SIDF_MID_COLOR_BLUE) midrgba[CB] = Msg_ReadByte() / 255.f; if(df & SIDF_MID_COLOR_ALPHA) midrgba[CA] = Msg_ReadByte() / 255.f; if(df & SIDF_BOTTOM_COLOR_RED) bottomrgb[CR] = Msg_ReadByte() / 255.f; if(df & SIDF_BOTTOM_COLOR_GREEN) bottomrgb[CG] = Msg_ReadByte() / 255.f; if(df & SIDF_BOTTOM_COLOR_BLUE) bottomrgb[CB] = Msg_ReadByte() / 255.f; if(df & SIDF_MID_BLENDMODE) blendmode = Msg_ReadShort() << 16; if(df & SIDF_FLAGS) sideFlags = Msg_ReadByte(); // Must we skip this? if(skip) return; #ifdef _DEBUG if(num >= numSideDefs) { // This is worrisome. Con_Error("Cl_ReadSideDelta2: Side %i out of range.\n", num); } #endif sid = SIDE_PTR(num); if(df & SIDF_TOP_MATERIAL) { material_t* mat; /** * The delta is a server-side materialnum. * \fixme What if client and server materialnums differ? */ mat = P_ToMaterial(topMat); Surface_SetMaterial(&sid->SW_topsurface, mat); } if(df & SIDF_MID_MATERIAL) { material_t* mat; /** * The delta is a server-side materialnum. * \fixme What if client and server materialnums differ? */ mat = P_ToMaterial(midMat); Surface_SetMaterial(&sid->SW_middlesurface, mat); } if(df & SIDF_BOTTOM_MATERIAL) { material_t* mat; /** * The delta is a server-side materialnum. * \fixme What if client and server materialnums differ? */ mat = P_ToMaterial(botMat); Surface_SetMaterial(&sid->SW_bottomsurface, mat); } if(df & SIDF_TOP_COLOR_RED) Surface_SetColorR(&sid->SW_topsurface, toprgb[CR]); if(df & SIDF_TOP_COLOR_GREEN) Surface_SetColorG(&sid->SW_topsurface, toprgb[CG]); if(df & SIDF_TOP_COLOR_BLUE) Surface_SetColorB(&sid->SW_topsurface, toprgb[CB]); if(df & SIDF_MID_COLOR_RED) Surface_SetColorR(&sid->SW_middlesurface, midrgba[CR]); if(df & SIDF_MID_COLOR_GREEN) Surface_SetColorG(&sid->SW_middlesurface, midrgba[CG]); if(df & SIDF_MID_COLOR_BLUE) Surface_SetColorB(&sid->SW_middlesurface, midrgba[CB]); if(df & SIDF_MID_COLOR_ALPHA) Surface_SetColorA(&sid->SW_middlesurface, midrgba[CA]); if(df & SIDF_BOTTOM_COLOR_RED) Surface_SetColorR(&sid->SW_bottomsurface, bottomrgb[CR]); if(df & SIDF_BOTTOM_COLOR_GREEN) Surface_SetColorG(&sid->SW_bottomsurface, bottomrgb[CG]); if(df & SIDF_BOTTOM_COLOR_BLUE) Surface_SetColorB(&sid->SW_bottomsurface, bottomrgb[CB]); if(df & SIDF_MID_BLENDMODE) Surface_SetBlendMode(&sid->SW_middlesurface, blendmode); if(df & SIDF_FLAGS) { // The delta includes the entire lowest byte. sid->flags &= ~0xff; sid->flags |= sideFlags; } if(df & SIDF_LINE_FLAGS) { linedef_t *line = R_GetLineForSide(num); if(line) { // The delta includes the entire lowest byte. line->flags &= ~0xff; line->flags |= lineFlags; #if _DEBUG Con_Printf("Cl_ReadSideDelta2: Lineflag %i: %02x\n", GET_LINE_IDX(line), lineFlags); #endif } } } /** * Reads a poly delta from the message buffer and applies it to * the world. */ void Cl_ReadPolyDelta2(boolean skip) { int df; unsigned short num; polyobj_t *po; float destX = 0, destY = 0; float speed = 0; int destAngle = 0, angleSpeed = 0; num = Msg_ReadPackedShort(); // Flags. df = Msg_ReadByte(); if(df & PODF_DEST_X) destX = FIX2FLT((Msg_ReadShort() << 16) + ((char) Msg_ReadByte() << 8)); if(df & PODF_DEST_Y) destY = FIX2FLT((Msg_ReadShort() << 16) + ((char) Msg_ReadByte() << 8)); if(df & PODF_SPEED) speed = FIX2FLT(Msg_ReadShort() << 8); if(df & PODF_DEST_ANGLE) destAngle = Msg_ReadShort() << 16; if(df & PODF_ANGSPEED) angleSpeed = Msg_ReadShort() << 16; if(skip) return; #ifdef _DEBUG if(num >= numPolyObjs) { // This is worrisome. Con_Error("Cl_ReadPolyDelta2: PO %i out of range.\n", num); } #endif po = polyObjs[num]; if(df & PODF_DEST_X) po->dest[VX] = destX; if(df & PODF_DEST_Y) po->dest[VY] = destY; if(df & PODF_SPEED) po->speed = speed; if(df & PODF_DEST_ANGLE) po->destAngle = destAngle; if(df & PODF_ANGSPEED) po->angleSpeed = angleSpeed; if(df & PODF_PERPETUAL_ROTATE) po->destAngle = -1; // Update the polyobj's mover thinkers. Cl_SetPolyMover(num, df & (PODF_DEST_X | PODF_DEST_Y | PODF_SPEED), df & (PODF_DEST_ANGLE | PODF_ANGSPEED | PODF_PERPETUAL_ROTATE)); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_md5.c0000644000175000017500000002031111357170242022073 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 2006 Cryptoapi developers. *\author Copyright © 2002 James Morris *\author Copyright © 1993 Colin Plumb * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * md5.c: MD5 Hash Generator * * This code has been adapted from the Linux kernel sources (crypto/md5.c). */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "m_md5.h" // MACROS ------------------------------------------------------------------ #define MD5_DIGEST_SIZE 16 #define MD5_HMAC_BLOCK_SIZE 64 #define F1(x, y, z) (z ^ (x & (y ^ z))) #define F2(x, y, z) F1(z, x, y) #define F3(x, y, z) (x ^ y ^ z) #define F4(x, y, z) (y ^ (x | ~z)) #define MD5STEP(f, w, x, y, z, in, s) \ (w += f(x, y, z) + in, w = (w<>(32-s)) + x) // TYPES ------------------------------------------------------------------- typedef uint u32; typedef byte u8; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static void md5_transform(u32 *hash, u32 const *in) { u32 a, b, c, d; a = hash[0]; b = hash[1]; c = hash[2]; d = hash[3]; MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); hash[0] += a; hash[1] += b; hash[2] += c; hash[3] += d; } #if WIN32 #define INLINE #else #define INLINE inline #endif static INLINE void le32_to_cpu_array(u32 *buf, unsigned int words) { while (words--) { *buf = ULONG(*buf); buf++; } } static INLINE void cpu_to_le32_array(u32 *buf, unsigned int words) { while (words--) { *buf = ULONG(*buf); buf++; } } static INLINE void md5_transform_helper(struct md5_ctx *ctx) { le32_to_cpu_array(ctx->block, sizeof(ctx->block) / sizeof(u32)); md5_transform(ctx->hash, ctx->block); } void md5_init(void *ctx) { struct md5_ctx *mctx = ctx; mctx->hash[0] = 0x67452301; mctx->hash[1] = 0xefcdab89; mctx->hash[2] = 0x98badcfe; mctx->hash[3] = 0x10325476; mctx->byte_count = 0; } void md5_update(void *ctx, const u8 *data, unsigned int len) { struct md5_ctx *mctx = ctx; const u32 avail = sizeof(mctx->block) - (mctx->byte_count & 0x3f); mctx->byte_count += len; if (avail > len) { memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, len); return; } memcpy((char *)mctx->block + (sizeof(mctx->block) - avail), data, avail); md5_transform_helper(mctx); data += avail; len -= avail; while (len >= sizeof(mctx->block)) { memcpy(mctx->block, data, sizeof(mctx->block)); md5_transform_helper(mctx); data += sizeof(mctx->block); len -= sizeof(mctx->block); } memcpy(mctx->block, data, len); } void md5_final(void *ctx, u8 *out) { struct md5_ctx *mctx = ctx; const unsigned int offset = mctx->byte_count & 0x3f; char *p = (char *)mctx->block + offset; int padding = 56 - (offset + 1); *p++ = 0x80; if (padding < 0) { memset(p, 0x00, padding + 8); md5_transform_helper(mctx); p = (char *)mctx->block; padding = 56; } memset(p, 0, padding); mctx->block[14] = mctx->byte_count << 3; mctx->block[15] = mctx->byte_count >> 29; le32_to_cpu_array(mctx->block, (sizeof(mctx->block) - 8) / sizeof(u32)); md5_transform(mctx->hash, mctx->block); cpu_to_le32_array(mctx->hash, sizeof(mctx->hash) / sizeof(u32)); memcpy(out, mctx->hash, sizeof(mctx->hash)); memset(mctx, 0, sizeof(*mctx)); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_sock.c0000644000175000017500000001064611357170242022741 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_sock.c: TCP/IP Sockets */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # include #endif #ifdef UNIX # include "de_platform.h" # include # include # include # include # include # include #endif #include #include #include "de_base.h" #include "sys_sock.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /* * Called from N_Init(). */ void N_SockInit(void) { #ifdef WIN32 WSADATA wsaData; WSAStartup(MAKEWORD(1, 1), &wsaData); // \fixme Check the result... (who cares?) #endif } /* * Called from N_Shutdown(). */ void N_SockShutdown(void) { #ifdef WIN32 WSACleanup(); #endif } /** * Don't print too long messages with one call. */ void N_SockPrintf(socket_t s, const char *format, ...) { #define BUFF_SIZE 512 char buf[BUFF_SIZE]; int length; va_list args; // Print the message into the buffer. va_start(args, format); length = dd_vsnprintf(buf, BUFF_SIZE, format, args); va_end(args); if(!length) { // Overflow or encoding error. Should we still be sending it anyway? length = BUFF_SIZE; } // Send it. send(s, buf, length, 0); #undef BUFF_SIZE } struct hostent *N_SockGetHost(const char *hostName) { struct sockaddr_in addr; struct hostent *host; // Clear the socket address. memset(&addr, 0, sizeof(addr)); // Is it an IP address or name? addr.sin_addr.s_addr = inet_addr(hostName); // Get host information. if(addr.sin_addr.s_addr == INADDR_NONE) { // Try to get using DNS. if((host = gethostbyname(hostName)) == NULL) { //perror("Could not get host by name"); return NULL; } } else { // Try to get using the IP address. if((host = gethostbyaddr((const char *) &addr.sin_addr, sizeof(struct sockaddr_in), AF_INET)) == NULL) { //perror("Could not get host by address"); return NULL; } } return host; } socket_t N_SockNewStream(void) { return socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); } boolean N_SockConnect(socket_t s, struct hostent *host, unsigned short port) { struct sockaddr_in addr; // The address to connect to. memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr = *((struct in_addr *) *host->h_addr_list); // 80 is the default port. addr.sin_port = htons(port); // Let's try connecting. return connect(s, (struct sockaddr *) &addr, sizeof(struct sockaddr)) != SOCKET_ERROR; } void N_SockClose(socket_t s) { #ifdef WIN32 closesocket(s); #elif defined UNIX close(s); #endif } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/bsp_main.c0000644000175000017500000002723511357170241022675 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_main.c: GL-friendly BSP node builder. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_bsp.h" #include "de_play.h" #include "de_misc.h" #include "p_mapdata.h" #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int bspFactor = 7; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Register the ccmds and cvars of the BSP builder. Called during engine * startup */ void BSP_Register(void) { C_VAR_INT("bsp-factor", &bspFactor, CVF_NO_MAX, 0, 0); } static void findMapLimits(gamemap_t* src, int* bbox) { uint i; M_ClearBox(bbox); for(i = 0; i < src->numLineDefs; ++i) { linedef_t* l = &src->lineDefs[i]; if(!(l->buildData.mlFlags & MLF_ZEROLENGTH)) { double x1 = l->v[0]->buildData.pos[VX]; double y1 = l->v[0]->buildData.pos[VY]; double x2 = l->v[1]->buildData.pos[VX]; double y2 = l->v[1]->buildData.pos[VY]; int lX = (int) floor(MIN_OF(x1, x2)); int lY = (int) floor(MIN_OF(y1, y2)); int hX = (int) ceil(MAX_OF(x1, x2)); int hY = (int) ceil(MAX_OF(y1, y2)); M_AddToBox(bbox, lX, lY); M_AddToBox(bbox, hX, hY); } } } /** * Initially create all half-edges, one for each side of a linedef. * * @return The list of created half-edges. */ static superblock_t* createInitialHEdges(gamemap_t* map) { uint startTime = Sys_GetRealTime(); uint i; int bw, bh; hedge_t* back, *front; superblock_t* block; int mapBounds[4]; // Find maximal vertexes. findMapLimits(map, mapBounds); VERBOSE(Con_Message("Map goes from (%d,%d) to (%d,%d)\n", mapBounds[BOXLEFT], mapBounds[BOXBOTTOM], mapBounds[BOXRIGHT], mapBounds[BOXTOP])); block = BSP_SuperBlockCreate(); block->bbox[BOXLEFT] = mapBounds[BOXLEFT] - (mapBounds[BOXLEFT] & 0x7); block->bbox[BOXBOTTOM] = mapBounds[BOXBOTTOM] - (mapBounds[BOXBOTTOM] & 0x7); bw = ((mapBounds[BOXRIGHT] - block->bbox[BOXLEFT]) / 128) + 1; bh = ((mapBounds[BOXTOP] - block->bbox[BOXBOTTOM]) / 128) + 1; block->bbox[BOXRIGHT] = block->bbox[BOXLEFT] + 128 * M_CeilPow2(bw); block->bbox[BOXTOP] = block->bbox[BOXBOTTOM] + 128 * M_CeilPow2(bh); for(i = 0; i < map->numLineDefs; ++i) { linedef_t* line = &map->lineDefs[i]; if(line->buildData.mlFlags & MLF_POLYOBJ) continue; front = back = NULL; // Ignore zero-length and polyobj lines. if(!(line->buildData.mlFlags & MLF_ZEROLENGTH) /*&& !line->buildData.overlap*/) { // Check for Humungously long lines. if(ABS(line->v[0]->buildData.pos[VX] - line->v[1]->buildData.pos[VX]) >= 10000 || ABS(line->v[0]->buildData.pos[VY] - line->v[1]->buildData.pos[VY]) >= 10000) { if(3000 >= M_Length(line->v[0]->buildData.pos[VX] - line->v[1]->buildData.pos[VX], line->v[0]->buildData.pos[VY] - line->v[1]->buildData.pos[VY])) { Con_Message("Linedef #%d is VERY long, it may cause problems\n", line->buildData.index); } } if(line->sideDefs[FRONT]) { sidedef_t *side = line->sideDefs[FRONT]; // Check for a bad sidedef. if(!side->sector) Con_Message("Bad sidedef on linedef #%d (Z_CheckHeap error)\n", line->buildData.index); front = HEdge_Create(line, line, line->v[0], line->v[1], side->sector, false); BSP_AddHEdgeToSuperBlock(block, front); } else Con_Message("Linedef #%d has no front sidedef!\n", line->buildData.index); if(line->sideDefs[BACK]) { sidedef_t *side = line->sideDefs[BACK]; // Check for a bad sidedef. if(!side->sector) Con_Message("Bad sidedef on linedef #%d (Z_CheckHeap error)\n", line->buildData.index); back = HEdge_Create(line, line, line->v[1], line->v[0], side->sector, true); BSP_AddHEdgeToSuperBlock(block, back); if(front) { // Half-edges always maintain a one-to-one relationship // with their twins, so if one gets split, the other // must be split also. back->twin = front; front->twin = back; } } else { if(line->buildData.mlFlags & MLF_TWOSIDED) { Con_Message("Linedef #%d is 2s but has no back sidedef\n", line->buildData.index); line->buildData.mlFlags &= ~MLF_TWOSIDED; } // Handle the 'One-Sided Window' trick. if(line->buildData.windowEffect && front) { hedge_t *other; other = HEdge_Create(front->lineDef, line, line->v[1], line->v[0], line->buildData.windowEffect, true); BSP_AddHEdgeToSuperBlock(block, other); // Setup the twin-ing (it's very strange to have a mini // and a normal partnered together). other->twin = front; front->twin = other; } } } // \todo edge tips should be created when half-edges are created. { double x1 = line->v[0]->buildData.pos[VX]; double y1 = line->v[0]->buildData.pos[VY]; double x2 = line->v[1]->buildData.pos[VX]; double y2 = line->v[1]->buildData.pos[VY]; BSP_CreateVertexEdgeTip(line->v[0], x2 - x1, y2 - y1, back, front); BSP_CreateVertexEdgeTip(line->v[1], x1 - x2, y1 - y2, front, back); } } // How much time did we spend? VERBOSE(Con_Message ("createInitialHEdges: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); return block; } static boolean C_DECL freeBSPData(binarytree_t *tree, void *data) { void *bspData = BinaryTree_GetData(tree); if(bspData) { if(BinaryTree_IsLeaf(tree)) BSPLeaf_Destroy(bspData); else M_Free(bspData); } BinaryTree_SetData(tree, NULL); return true; // Continue iteration. } /** * Build the BSP for the given map. * * @param map The map to build the BSP for. * @param vertexes Editable vertex (ptr) array. * @param numVertexes Number of vertexes in the array. * @return @c true, if completed successfully. */ boolean BSP_Build(gamemap_t* map, vertex_t*** vertexes, uint* numVertexes) { boolean builtOK; uint startTime; superblock_t* hEdgeList; binarytree_t* rootNode; if(verbose >= 1) { Con_Message("BSP_Build: Processing map using tunable " "factor of %d...\n", bspFactor); } // It begins... startTime = Sys_GetRealTime(); BSP_InitSuperBlockAllocator(); BSP_InitIntersectionAllocator(); BSP_InitHEdgeAllocator(); BSP_InitForNodeBuild(map); // Create initial half-edges. hEdgeList = createInitialHEdges(map); // Build the BSP. { uint buildStartTime = Sys_GetRealTime(); cutlist_t *cutList; cutList = BSP_CutListCreate(); // Recursively create nodes. rootNode = NULL; builtOK = BuildNodes(hEdgeList, &rootNode, 0, cutList); // The cutlist data is no longer needed. BSP_CutListDestroy(cutList); // How much time did we spend? VERBOSE(Con_Message ("BuildNodes: Done in %.2f seconds.\n", (Sys_GetRealTime() - buildStartTime) / 1000.0f)); } BSP_SuperBlockDestroy(hEdgeList); if(builtOK) { // Success! // Wind the BSP tree and link to the map. ClockwiseBspTree(rootNode); SaveMap(map, rootNode, vertexes, numVertexes); Con_Message("BSP_Build: Built %d Nodes, %d Subsectors, %d Segs, %d Vertexes\n", map->numNodes, map->numSSectors, map->numSegs, map->numVertexes); if(rootNode && !BinaryTree_IsLeaf(rootNode)) { long rHeight, lHeight; rHeight = (long) BinaryTree_GetHeight(BinaryTree_GetChild(rootNode, RIGHT)); lHeight = (long) BinaryTree_GetHeight(BinaryTree_GetChild(rootNode, LEFT)); Con_Message(" Balance %+ld (l%ld - r%ld).\n", lHeight - rHeight, lHeight, rHeight); } } // We are finished with the BSP build data. if(rootNode) { BinaryTree_PostOrder(rootNode, freeBSPData, NULL); BinaryTree_Destroy(rootNode); } rootNode = NULL; // Free temporary storage. BSP_ShutdownHEdgeAllocator(); BSP_ShutdownIntersectionAllocator(); BSP_ShutdownSuperBlockAllocator(); // How much time did we spend? VERBOSE(Con_Message(" Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); return builtOK; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_main.c0000644000175000017500000043503511357170242023043 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_main.c: Rendering Subsystem */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_base.h" #include "de_console.h" #include "de_edit.h" #include "de_render.h" #include "de_refresh.h" #include "de_play.h" #include "de_graphics.h" #include "de_misc.h" #include "de_ui.h" #include "de_system.h" #include "net_main.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void Rend_DrawBBox(const float pos3f[3], float w, float l, float h, float a, const float color3f[3], float alpha, float br, boolean alignToBase); void Rend_DrawArrow(const float pos3f[3], float a, float s, const float color3f[3], float alpha); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void Rend_RenderBoundingBoxes(void); static DGLuint constructBBox(DGLuint name, float br); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int useDynLights, translucentIceCorpse; extern int skyhemispheres; extern int loMaxRadius; // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean usingFog = false; // Is the fog in use? float fogColor[4]; float fieldOfView = 95.0f; byte smoothTexAnim = true; int useShinySurfaces = true; float vx, vy, vz, vang, vpitch; float viewsidex, viewsidey; byte freezeRLs = false; int devRendSkyMode = false; byte devRendSkyAlways = false; int missileBlend = 1; // Ambient lighting, rAmbient is used within the renderer, ambientLight is // used to store the value of the ambient light cvar. // The value chosen for rAmbient occurs in Rend_CalcLightModRange // for convenience (since we would have to recalculate the matrix anyway). int rAmbient = 0, ambientLight = 0; int viewpw, viewph; // Viewport size, in pixels. int viewpx, viewpy; // Viewpoint top left corner, in pixels. float yfov; int gameDrawHUD = 1; // Set to zero when we advise that the HUD should not be drawn float lightRangeCompression = 0; float lightModRange[255]; byte devLightModRange = 0; float rendLightDistanceAttentuation = 1024; int devMobjBBox = 0; // 1 = Draw mobj bounding boxes (for debug) int devPolyobjBBox = 0; // 1 = Draw polyobj bounding boxes (for debug) DGLuint dlBBox = 0; // Display list: active-textured bbox model. byte devVertexIndices = 0; // @c 1= Draw world vertex indices (for debug). byte devVertexBars = 0; // @c 1= Draw world vertex position bars. byte devSurfaceNormals = 0; // @c 1= Draw world surface normal tails. byte devNoTexFix = 0; // Current sector light color. const float* sLightColor; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean firstsubsector; // No range checking for the first one. // CODE -------------------------------------------------------------------- void Rend_Register(void) { C_VAR_FLOAT("rend-camera-fov", &fieldOfView, 0, 1, 179); C_VAR_BYTE("rend-tex-anim-smooth", &smoothTexAnim, 0, 0, 1); C_VAR_INT("rend-tex-shiny", &useShinySurfaces, 0, 0, 1); C_VAR_FLOAT2("rend-light-compression", &lightRangeCompression, 0, -1, 1, Rend_CalcLightModRange); C_VAR_INT2("rend-light-ambient", &ambientLight, 0, 0, 255, Rend_CalcLightModRange); C_VAR_INT2("rend-light-sky", &rendSkyLight, 0, 0, 1, LG_MarkAllForUpdate); C_VAR_FLOAT("rend-light-wall-angle", &rendLightWallAngle, CVF_NO_MAX, 0, 0); C_VAR_BYTE("rend-light-wall-angle-smooth", &rendLightWallAngleSmooth, 0, 0, 1); C_VAR_FLOAT("rend-light-attenuation", &rendLightDistanceAttentuation, CVF_NO_MAX, 0, 0); C_VAR_INT("rend-dev-sky", &devRendSkyMode, CVF_NO_ARCHIVE, 0, 2); C_VAR_BYTE("rend-dev-sky-always", &devRendSkyAlways, CVF_NO_ARCHIVE, 0, 1); C_VAR_BYTE("rend-dev-freeze", &freezeRLs, CVF_NO_ARCHIVE, 0, 1); C_VAR_INT("rend-dev-cull-subsectors", &devNoCulling,CVF_NO_ARCHIVE,0,1); C_VAR_INT("rend-dev-mobj-bbox", &devMobjBBox, CVF_NO_ARCHIVE, 0, 1); C_VAR_INT("rend-dev-polyobj-bbox", &devPolyobjBBox, CVF_NO_ARCHIVE, 0, 1); C_VAR_BYTE("rend-dev-light-mod", &devLightModRange, CVF_NO_ARCHIVE, 0, 1); C_VAR_BYTE("rend-dev-tex-showfix", &devNoTexFix, CVF_NO_ARCHIVE, 0, 1); C_VAR_BYTE("rend-dev-blockmap-debug", &bmapShowDebug, CVF_NO_ARCHIVE, 0, 3); C_VAR_FLOAT("rend-dev-blockmap-debug-size", &bmapDebugSize, CVF_NO_ARCHIVE, .1f, 100); C_VAR_BYTE("rend-dev-vertex-show-indices", &devVertexIndices, CVF_NO_ARCHIVE, 0, 1); C_VAR_BYTE("rend-dev-vertex-show-bars", &devVertexBars, CVF_NO_ARCHIVE, 0, 1); C_VAR_BYTE("rend-dev-surface-show-normals", &devSurfaceNormals, CVF_NO_ARCHIVE, 0, 1); RL_Register(); DL_Register(); SB_Register(); LG_Register(); Rend_ModelRegister(); Rend_ParticleRegister(); Rend_RadioRegister(); Rend_ShadowRegister(); Rend_SkyRegister(); Rend_SpriteRegister(); Rend_ConsoleRegister(); } #if 0 // unused atm float Rend_SignedPointDist2D(float c[2]) { /* (YA-YC)(XB-XA)-(XA-XC)(YB-YA) s = ----------------------------- L**2 Luckily, L**2 is one. dist = s*L. Even more luckily, L is also one. */ return (vz - c[VY]) * viewsidex - (vx - c[VX]) * viewsidey; } #endif /** * Approximated! The Z axis aspect ratio is corrected. */ float Rend_PointDist3D(const float c[3]) { return M_ApproxDistance3f(vx - c[VX], vz - c[VY], 1.2f * (vy - c[VZ])); } void Rend_Init(void) { C_Init(); // Clipper. RL_Init(); // Rendering lists. Rend_InitSky(); // The sky. } /** * Used to be called before starting a new map. */ void Rend_Reset(void) { // Textures are deleted (at least skies need this???). GL_ClearRuntimeTextures(); LO_Clear(); // Free lumobj stuff. if(dlBBox) GL_DeleteLists(dlBBox, 1); dlBBox = 0; } void Rend_ModelViewMatrix(boolean useAngles) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); vx = viewData->current.pos[VX]; vy = viewData->current.pos[VZ]; vz = viewData->current.pos[VY]; vang = viewData->current.angle / (float) ANGLE_MAX *360 - 90; vpitch = viewData->current.pitch * 85.0 / 110.0; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); if(useAngles) { glRotatef(vpitch, 1, 0, 0); glRotatef(vang, 0, 1, 0); } glScalef(1, 1.2f, 1); // This is the aspect correction. glTranslatef(-vx, -vy, -vz); } static __inline float segFacingViewerDot(float v1[2], float v2[2]) { // The dot product. return (v1[VY] - v2[VY]) * (v1[VX] - vx) + (v2[VX] - v1[VX]) * (v1[VY] - vz); } #if 0 // unused atm static int Rend_FixedSegFacingDir(const seg_t *seg) { // The dot product. (1 if facing front.) return((seg->fv1.pos[VY] - seg->fv2.pos[VY]) * (seg->fv1.pos[VX] - viewX) + (seg->fv2.pos[VX] - seg->fv1.pos[VX]) * (seg->fv1.pos[VY] - viewY)) > 0; } #endif #if 0 // unused atm int Rend_SegFacingPoint(float v1[2], float v2[2], float pnt[2]) { float nx = v1[VY] - v2[VY], ny = v2[VX] - v1[VX]; float vvx = v1[VX] - pnt[VX], vvy = v1[VY] - pnt[VY]; // The dot product. if(nx * vvx + ny * vvy > 0) return 1; // Facing front. return 0; // Facing away. } #endif static int C_DECL DivSortAscend(const void *e1, const void *e2) { float f1 = *(float *) e1, f2 = *(float *) e2; if(f1 > f2) return 1; if(f2 > f1) return -1; return 0; } static int C_DECL DivSortDescend(const void *e1, const void *e2) { float f1 = *(float *) e1, f2 = *(float *) e2; if(f1 > f2) return -1; if(f2 > f1) return 1; return 0; } void Rend_VertexColorsGlow(rcolor_t* colors, size_t num) { size_t i; for(i = 0; i < num; ++i) { rcolor_t* c = &colors[i]; c->rgba[CR] = c->rgba[CG] = c->rgba[CB] = 1; } } void Rend_VertexColorsAlpha(rcolor_t* colors, size_t num, float alpha) { size_t i; for(i = 0; i < num; ++i) { colors[i].rgba[CA] = alpha; } } void Rend_ApplyTorchLight(float* color, float distance) { ddplayer_t* ddpl = &viewPlayer->shared; if(!ddpl->fixedColorMap) return; // Check for torch. if(distance < 1024) { // Colormap 1 is the brightest. I'm guessing 16 would be // the darkest. int ll = 16 - ddpl->fixedColorMap; float d = (1024 - distance) / 1024.0f * ll / 15.0f; if(torchAdditive) { color[CR] += d * torchColor[CR]; color[CG] += d * torchColor[CG]; color[CB] += d * torchColor[CB]; } else { color[CR] += d * ((color[CR] * torchColor[CR]) - color[CR]); color[CG] += d * ((color[CG] * torchColor[CG]) - color[CG]); color[CB] += d * ((color[CB] * torchColor[CB]) - color[CB]); } } } static void lightVertex(rcolor_t* color, const rvertex_t* vtx, float lightLevel, const float* ambientColor) { float lightVal, dist; dist = Rend_PointDist2D(vtx->pos); // Apply distance attenuation. lightVal = R_DistAttenuateLightLevel(dist, lightLevel); // Add extra light. lightVal += R_ExtraLightDelta(); Rend_ApplyLightAdaptation(&lightVal); // Mix with the surface color. color->rgba[CR] = lightVal * ambientColor[CR]; color->rgba[CG] = lightVal * ambientColor[CG]; color->rgba[CB] = lightVal * ambientColor[CB]; } void Rend_VertexColorsApplyTorchLight(rcolor_t* colors, const rvertex_t* vertices, size_t numVertices) { size_t i; ddplayer_t* ddpl = &viewPlayer->shared; if(!ddpl->fixedColorMap) return; // No need, its disabled. for(i = 0; i < numVertices; ++i) { const rvertex_t* vtx = &vertices[i]; rcolor_t* c = &colors[i]; Rend_ApplyTorchLight(c->rgba, Rend_PointDist2D(vtx->pos)); } } void Rend_PreparePlane(rvertex_t* rvertices, size_t numVertices, float height, const subsector_t* subsector, boolean antiClockwise) { size_t i, vid; // First vertex is always #0. rvertices[0].pos[VX] = subsector->vertices[0]->pos[VX]; rvertices[0].pos[VY] = subsector->vertices[0]->pos[VY]; rvertices[0].pos[VZ] = height; // Copy the vertices in reverse order for ceilings (flip faces). if(antiClockwise) vid = numVertices - 1; else vid = 1; for(i = 1; i < numVertices; ++i) { rvertices[i].pos[VX] = subsector->vertices[vid]->pos[VX]; rvertices[i].pos[VY] = subsector->vertices[vid]->pos[VY]; rvertices[i].pos[VZ] = height; (antiClockwise? vid-- : vid++); } } /** * \fixme No need to do this each frame. Set a flag in sidedef_t->flags to * denote this. Is sensitive to plane heights, surface properties * (e.g. alpha) and surface texture properties. */ boolean Rend_DoesMidTextureFillGap(linedef_t *line, int backside) { // Check for unmasked midtextures on twosided lines that completely // fill the gap between floor and ceiling (we don't want to give away // the location of any secret areas (false walls)). if(line->L_backside) { sector_t* front = line->L_sector(backside); sector_t* back = line->L_sector(backside^1); sidedef_t* side = line->L_side(backside); if(side->SW_middlematerial) { material_t* mat = side->SW_middlematerial; material_snapshot_t ms; // Ensure we have up to date info. Material_Prepare(&ms, mat, true, NULL); if(ms.isOpaque && !side->SW_middleblendmode && side->SW_middlergba[3] >= 1) { float openTop[2], matTop[2]; float openBottom[2], matBottom[2]; if(side->flags & SDF_MIDDLE_STRETCH) return true; openTop[0] = openTop[1] = matTop[0] = matTop[1] = MIN_OF(back->SP_ceilvisheight, front->SP_ceilvisheight); openBottom[0] = openBottom[1] = matBottom[0] = matBottom[1] = MAX_OF(back->SP_floorvisheight, front->SP_floorvisheight); // Could the mid texture fill enough of this gap for us // to consider it completely closed? if(ms.height >= (openTop[0] - openBottom[0]) && ms.height >= (openTop[1] - openBottom[1])) { // Possibly. Check the placement of the mid texture. if(Rend_MidMaterialPos (&matBottom[0], &matBottom[1], &matTop[0], &matTop[1], NULL, side->SW_middlevisoffset[VY], ms.height, 0 != (line->flags & DDLF_DONTPEGBOTTOM), !(R_IsSkySurface(&front->SP_ceilsurface) && R_IsSkySurface(&back->SP_ceilsurface)), !(R_IsSkySurface(&front->SP_floorsurface) && R_IsSkySurface(&back->SP_floorsurface)))) { if(matTop[0] >= openTop[0] && matTop[1] >= openTop[1] && matBottom[0] <= openBottom[0] && matBottom[1] <= openBottom[1]) return true; } } } } } return false; } static void Rend_MarkSegSectionsPVisible(seg_t *seg) { uint i, j; sidedef_t *side; linedef_t *line; if(!seg || !seg->lineDef) return; // huh? line = seg->lineDef; for(i = 0; i < 2; ++i) { // Missing side? if(!line->L_side(i)) continue; side = line->L_side(i); for(j = 0; j < 3; ++j) side->sections[j].inFlags |= SUIF_PVIS; // Top if(!line->L_backside) { side->sections[SEG_TOP].inFlags &= ~SUIF_PVIS; side->sections[SEG_BOTTOM].inFlags &= ~SUIF_PVIS; } else { // Check middle texture if((!side->SW_middlematerial || (side->SW_middlematerial->flags & MATF_NO_DRAW)) || side->SW_middlergba[3] <= 0) // Check alpha side->sections[SEG_MIDDLE].inFlags &= ~SUIF_PVIS; if(R_IsSkySurface(&line->L_backsector->SP_ceilsurface) && R_IsSkySurface(&line->L_frontsector->SP_ceilsurface)) side->sections[SEG_TOP].inFlags &= ~SUIF_PVIS; else { if(i != 0) { if(line->L_backsector->SP_ceilvisheight <= line->L_frontsector->SP_ceilvisheight) side->sections[SEG_TOP].inFlags &= ~SUIF_PVIS; } else { if(line->L_frontsector->SP_ceilvisheight <= line->L_backsector->SP_ceilvisheight) side->sections[SEG_TOP].inFlags &= ~SUIF_PVIS; } } // Bottom if(R_IsSkySurface(&line->L_backsector->SP_floorsurface) && R_IsSkySurface(&line->L_frontsector->SP_floorsurface)) side->sections[SEG_BOTTOM].inFlags &= ~SUIF_PVIS; else { if(i != 0) { if(line->L_backsector->SP_floorvisheight >= line->L_frontsector->SP_floorvisheight) side->sections[SEG_BOTTOM].inFlags &= ~SUIF_PVIS; } else { if(line->L_frontsector->SP_floorvisheight >= line->L_backsector->SP_floorvisheight) side->sections[SEG_BOTTOM].inFlags &= ~SUIF_PVIS; } } } } } /** * @return @true, if there is a division at the specified height. */ static int checkDiv(walldiv_t *div, float height) { uint i; for(i = 0; i < div->num; ++i) if(div->pos[i] == height) return true; return false; } static void doCalcSegDivisions(walldiv_t* div, const linedef_t* line, boolean backSide, const sector_t* frontSec, float bottomZ, float topZ, boolean doRight) { uint i, j; linedef_t *iter; sector_t *scanSec; lineowner_t *base, *own; boolean clockwise = !doRight; boolean stopScan = false; if(bottomZ >= topZ) return; // Obviously no division. // Retrieve the start owner node. base = own = R_GetVtxLineOwner(line->L_v(backSide^doRight), line); do { own = own->link[clockwise]; if(own == base) stopScan = true; else { iter = own->lineDef; if(LINE_SELFREF(iter)) continue; i = 0; do { // First front, then back. scanSec = NULL; if(!i && iter->L_frontside && iter->L_frontsector != frontSec) scanSec = iter->L_frontsector; else if(i && iter->L_backside && iter->L_backsector != frontSec) scanSec = iter->L_backsector; if(scanSec) { if(scanSec->SP_ceilvisheight - scanSec->SP_floorvisheight > 0) { for(j = 0; j < scanSec->planeCount && !stopScan; ++j) { plane_t *pln = scanSec->SP_plane(j); if(pln->visHeight > bottomZ && pln->visHeight < topZ) { if(!checkDiv(div, pln->visHeight)) { div->pos[div->num++] = pln->visHeight; // Have we reached the div limit? if(div->num == RL_MAX_DIVS) stopScan = true; } } if(!stopScan) { // Clip a range bound to this height? if(pln->type == PLN_FLOOR && pln->visHeight > bottomZ) bottomZ = pln->visHeight; else if(pln->type == PLN_CEILING && pln->visHeight < topZ) topZ = pln->visHeight; // All clipped away? if(bottomZ >= topZ) stopScan = true; } } } else { /** * A zero height sector is a special case. In this * instance, the potential division is at the height * of the back ceiling. This is because elsewhere * we automatically fix the case of a floor above a * ceiling by lowering the floor. */ float z = scanSec->SP_ceilvisheight; if(z > bottomZ && z < topZ) { if(!checkDiv(div, z)) { div->pos[div->num++] = z; // Have we reached the div limit? if(div->num == RL_MAX_DIVS) stopScan = true; } } } } } while(!stopScan && ++i < 2); // Stop the scan when a single sided line is reached. if(!iter->L_frontside || !iter->L_backside) stopScan = true; } } while(!stopScan); } static void calcSegDivisions(walldiv_t* div, const seg_t* seg, const sector_t* frontSec, float bottomZ, float topZ, boolean doRight) { sidedef_t* side; div->num = 0; side = SEG_SIDEDEF(seg); if(seg->flags & SEGF_POLYOBJ) return; // Polyobj segs are never split. // Only segs at sidedef ends can/should be split. if(!((seg == side->segs[0] && !doRight) || (seg == side->segs[side->segCount -1] && doRight))) return; doCalcSegDivisions(div, seg->lineDef, seg->side, frontSec, bottomZ, topZ, doRight); } /** * Division will only happen if it must be done. */ static void applyWallHeightDivision(walldiv_t* divs, const seg_t* seg, const sector_t* frontsec, float low, float hi) { uint i; walldiv_t* div; if(!seg->lineDef) return; // Mini-segs arn't drawn. for(i = 0; i < 2; ++i) { div = &divs[i]; calcSegDivisions(div, seg, frontsec, low, hi, i); // We need to sort the divisions for the renderer. if(div->num > 1) { // Sorting is required. This shouldn't take too long... // There seldom are more than one or two divisions. qsort(div->pos, div->num, sizeof(float), i!=0 ? DivSortDescend : DivSortAscend); } #ifdef RANGECHECK { uint k; for(k = 0; k < div->num; ++k) if(div->pos[k] > hi || div->pos[k] < low) { Con_Error("DivQuad: i=%i, pos (%f), hi (%f), low (%f), num=%i\n", i, div->pos[k], hi, low, div->num); } } #endif } } /** * Calculates the placement for a middle texture (top, bottom, offset). * texoffy may be NULL. * Returns false if the middle texture isn't visible (in the opening). */ int Rend_MidMaterialPos(float* bottomleft, float* bottomright, float* topleft, float* topright, float* texoffy, float tcyoff, float texHeight, boolean lowerUnpeg, boolean clipTop, boolean clipBottom) { int side; float openingTop, openingBottom; boolean visible[2] = {false, false}; for(side = 0; side < 2; ++side) { openingTop = *(side? topright : topleft); openingBottom = *(side? bottomright : bottomleft); if(openingTop <= openingBottom) continue; // Else the mid texture is visible on this side. visible[side] = true; if(side == 0 && texoffy) *texoffy = 0; // We don't allow vertical tiling. if(lowerUnpeg) { *(side? bottomright : bottomleft) += tcyoff; *(side? topright : topleft) = *(side? bottomright : bottomleft) + texHeight; } else { *(side? topright : topleft) += tcyoff; *(side? bottomright : bottomleft) = *(side? topright : topleft) - texHeight; } // Clip it. if(clipBottom) if(*(side? bottomright : bottomleft) < openingBottom) { *(side? bottomright : bottomleft) = openingBottom; } if(clipTop) if(*(side? topright : topleft) > openingTop) { if(side == 0 && texoffy) *texoffy += *(side? topright : topleft) - openingTop; *(side? topright : topleft) = openingTop; } } return (visible[0] || visible[1]); } static void selectSurfaceColors(const float** topColor, const float** bottomColor, sidedef_t* side, segsection_t section) { // Select the colors for this surface. switch(section) { case SEG_MIDDLE: if(side->flags & SDF_BLENDMIDTOTOP) { *topColor = side->SW_toprgba; *bottomColor = side->SW_middlergba; } else if(side->flags & SDF_BLENDMIDTOBOTTOM) { *topColor = side->SW_middlergba; *bottomColor = side->SW_bottomrgba; } else { *topColor = side->SW_middlergba; *bottomColor = NULL; } break; case SEG_TOP: if(side->flags & SDF_BLENDTOPTOMID) { *topColor = side->SW_toprgba; *bottomColor = side->SW_middlergba; } else { *topColor = side->SW_toprgba; *bottomColor = NULL; } break; case SEG_BOTTOM: // Select the correct colors for this surface. if(side->flags & SDF_BLENDBOTTOMTOMID) { *topColor = side->SW_middlergba; *bottomColor = side->SW_bottomrgba; } else { *topColor = side->SW_bottomrgba; *bottomColor = NULL; } break; default: break; } } boolean RLIT_DynGetFirst(const dynlight_t* dyn, void* data) { dynlight_t** ptr = data; *ptr = (dynlight_t*) dyn; return false; // Stop iteration. } /** * This doesn't create a rendering primitive but a vissprite! The vissprite * represents the masked poly and will be rendered during the rendering * of sprites. This is necessary because all masked polygons must be * rendered back-to-front, or there will be alpha artifacts along edges. */ void Rend_AddMaskedPoly(const rvertex_t* rvertices, const rcolor_t* rcolors, float wallLength, float texWidth, float texHeight, const float texOffset[2], blendmode_t blendMode, uint lightListIdx, boolean glow, boolean masked, const rtexmapunit_t rTU[NUM_TEXMAP_UNITS]) { vissprite_t* vis = R_NewVisSprite(); int i, c; float midpoint[3]; midpoint[VX] = (rvertices[0].pos[VX] + rvertices[3].pos[VX]) / 2; midpoint[VY] = (rvertices[0].pos[VY] + rvertices[3].pos[VY]) / 2; midpoint[VZ] = (rvertices[0].pos[VZ] + rvertices[3].pos[VZ]) / 2; vis->type = VSPR_MASKED_WALL; vis->center[VX] = midpoint[VX]; vis->center[VY] = midpoint[VY]; vis->center[VZ] = midpoint[VZ]; vis->distance = Rend_PointDist2D(midpoint); vis->data.wall.tex = rTU[TU_PRIMARY].tex; vis->data.wall.magMode = rTU[TU_PRIMARY].magMode; vis->data.wall.masked = masked; for(i = 0; i < 4; ++i) { vis->data.wall.vertices[i].pos[VX] = rvertices[i].pos[VX]; vis->data.wall.vertices[i].pos[VY] = rvertices[i].pos[VY]; vis->data.wall.vertices[i].pos[VZ] = rvertices[i].pos[VZ]; for(c = 0; c < 4; ++c) { vis->data.wall.vertices[i].color[c] = MINMAX_OF(0, rcolors[i].rgba[c], 1); } } vis->data.wall.texCoord[0][VX] = (texOffset? texOffset[VX] / texWidth : 0); vis->data.wall.texCoord[1][VX] = vis->data.wall.texCoord[0][VX] + wallLength / texWidth; vis->data.wall.texCoord[0][VY] = (texOffset? texOffset[VY] / texHeight : 0); vis->data.wall.texCoord[1][VY] = vis->data.wall.texCoord[0][VY] + (rvertices[3].pos[VZ] - rvertices[0].pos[VZ]) / texHeight; vis->data.wall.blendMode = blendMode; //// \fixme Semitransparent masked polys arn't lit atm if(!glow && lightListIdx && numTexUnits > 1 && envModAdd && !(rcolors[0].rgba[CA] < 1)) { dynlight_t* dyn = NULL; /** * The dynlights will have already been sorted so that the brightest * and largest of them is first in the list. So grab that one. */ DL_ListIterator(lightListIdx, &dyn, RLIT_DynGetFirst); vis->data.wall.modTex = dyn->texture; vis->data.wall.modTexCoord[0][0] = dyn->s[0]; vis->data.wall.modTexCoord[0][1] = dyn->s[1]; vis->data.wall.modTexCoord[1][0] = dyn->t[0]; vis->data.wall.modTexCoord[1][1] = dyn->t[1]; for(c = 0; c < 3; ++c) vis->data.wall.modColor[c] = dyn->color[c]; vis->data.wall.modColor[3] = 1; } else { vis->data.wall.modTex = 0; } } static void quadTexCoords(rtexcoord_t* tc, const rvertex_t* rverts, float wallLength, const vectorcomp_t topLeft[3]) { tc[0].st[0] = tc[1].st[0] = rverts[0].pos[VX] - topLeft[VX]; tc[3].st[1] = tc[1].st[1] = rverts[0].pos[VY] - topLeft[VY]; tc[3].st[0] = tc[2].st[0] = tc[0].st[0] + wallLength; tc[2].st[1] = tc[3].st[1] + (rverts[1].pos[VZ] - rverts[0].pos[VZ]); tc[0].st[1] = tc[3].st[1] + (rverts[3].pos[VZ] - rverts[2].pos[VZ]); } static void quadLightCoords(rtexcoord_t* tc, const float s[2], const float t[2]) { tc[1].st[0] = tc[0].st[0] = s[0]; tc[1].st[1] = tc[3].st[1] = t[0]; tc[3].st[0] = tc[2].st[0] = s[1]; tc[2].st[1] = tc[0].st[1] = t[1]; } #if 0 static void quadShinyMaskTexCoords(rtexcoord_t* tc, const rvertex_t* rverts, float wallLength, float texWidth, float texHeight, const pvec2_t texOrigin[2], const pvec2_t texOffset) { tc[0].st[0] = tc[1].st[0] = rverts[0].pos[VX] - texOrigin[0][VX] + texOffset[VX] / texWidth; tc[3].st[1] = tc[1].st[1] = rverts[0].pos[VY] - texOrigin[0][VY] + texOffset[VY] / texHeight; tc[3].st[0] = tc[2].st[0] = tc[0].st[0] + wallLength / texWidth; tc[2].st[1] = tc[3].st[1] + (rverts[1].pos[VZ] - rverts[0].pos[VZ]) / texHeight; tc[0].st[1] = tc[3].st[1] + (rverts[3].pos[VZ] - rverts[2].pos[VZ]) / texHeight; } #endif static float shinyVertical(float dy, float dx) { return ( (atan(dy/dx) / (PI/2)) + 1 ) / 2; } static void quadShinyTexCoords(rtexcoord_t* tc, const rvertex_t* topLeft, const rvertex_t* bottomRight, float wallLength) { uint i; vec2_t surface, normal, projected, s, reflected, view; float distance, angle, prevAngle = 0; // Quad surface vector. V2_Set(surface, (bottomRight->pos[VX] - topLeft->pos[VX]) / wallLength, (bottomRight->pos[VY] - topLeft->pos[VY]) / wallLength); V2_Set(normal, surface[VY], -surface[VX]); // Calculate coordinates based on viewpoint and surface normal. for(i = 0; i < 2; ++i) { // View vector. V2_Set(view, vx - (i == 0? topLeft->pos[VX] : bottomRight->pos[VX]), vz - (i == 0? topLeft->pos[VY] : bottomRight->pos[VY])); distance = V2_Normalize(view); V2_Project(projected, view, normal); V2_Subtract(s, projected, view); V2_Scale(s, 2); V2_Sum(reflected, view, s); angle = acos(reflected[VY]) / PI; if(reflected[VX] < 0) { angle = 1 - angle; } if(i == 0) { prevAngle = angle; } else { if(angle > prevAngle) angle -= 1; } // Horizontal coordinates. tc[ (i == 0 ? 1 : 2) ].st[0] = tc[ (i == 0 ? 0 : 3) ].st[0] = angle + .3f; /*acos(-dot)/PI*/ tc[ (i == 0 ? 0 : 2) ].st[1] = shinyVertical(vy - bottomRight->pos[VZ], distance); // Vertical coordinates. tc[ (i == 0 ? 1 : 3) ].st[1] = shinyVertical(vy - topLeft->pos[VZ], distance); } } static void flatShinyTexCoords(rtexcoord_t* tc, const float xyz[3]) { vec2_t view, start; float distance; float offset; // View vector. V2_Set(view, vx - xyz[VX], vz - xyz[VY]); distance = V2_Normalize(view); if(distance < 10) { // Too small distances cause an ugly 'crunch' below and above // the viewpoint. distance = 10; } // Offset from the normal view plane. V2_Set(start, vx, vz); offset = ((start[VY] - xyz[VY]) * sin(.4f)/*viewFrontVec[VX]*/ - (start[VX] - xyz[VX]) * cos(.4f)/*viewFrontVec[VZ]*/); tc->st[0] = ((shinyVertical(offset, distance) - .5f) * 2) + .5f; tc->st[1] = shinyVertical(vy - xyz[VZ], distance); } typedef struct { uint lastIdx; const rvertex_t* rvertices; uint numVertices, realNumVertices; const float* texTL, *texBR; boolean isWall; const walldiv_t* divs; } dynlightiterparams_t; boolean RLIT_DynLightWrite(const dynlight_t* dyn, void* data) { dynlightiterparams_t* params = data; // If multitexturing is in use, we skip the first light. if(!(RL_IsMTexLights() && params->lastIdx == 0)) { uint i; rvertex_t* rvertices; rtexcoord_t* rtexcoords; rcolor_t* rcolors; rtexmapunit_t rTU[NUM_TEXMAP_UNITS]; memset(rTU, 0, sizeof(rTU)); // Allocate enough for the divisions too. rvertices = R_AllocRendVertices(params->realNumVertices); rtexcoords = R_AllocRendTexCoords(params->realNumVertices); rcolors = R_AllocRendColors(params->realNumVertices); rTU[TU_PRIMARY].tex = dyn->texture; rTU[TU_PRIMARY].magMode = GL_LINEAR; rTU[TU_PRIMARY_DETAIL].tex = 0; rTU[TU_INTER].tex = 0; rTU[TU_INTER_DETAIL].tex = 0; for(i = 0; i < params->numVertices; ++i) { uint c; rcolor_t* col = &rcolors[i]; // Each vertex uses the light's color. for(c = 0; c < 3; ++c) col->rgba[c] = dyn->color[c]; col->rgba[3] = 1; } if(params->isWall) { rtexcoords[1].st[0] = rtexcoords[0].st[0] = dyn->s[0]; rtexcoords[1].st[1] = rtexcoords[3].st[1] = dyn->t[0]; rtexcoords[3].st[0] = rtexcoords[2].st[0] = dyn->s[1]; rtexcoords[2].st[1] = rtexcoords[0].st[1] = dyn->t[1]; if(params->divs) { // We need to subdivide the dynamic light quad. float bL, tL, bR, tR; rvertex_t origVerts[4]; rcolor_t origColors[4]; rtexcoord_t origTexCoords[4]; /** * Need to swap indices around into fans set the position * of the division vertices, interpolate texcoords and * color. */ memcpy(origVerts, params->rvertices, sizeof(rvertex_t) * 4); memcpy(origTexCoords, rtexcoords, sizeof(rtexcoord_t) * 4); memcpy(origColors, rcolors, sizeof(rcolor_t) * 4); bL = params->rvertices[0].pos[VZ]; tL = params->rvertices[1].pos[VZ]; bR = params->rvertices[2].pos[VZ]; tR = params->rvertices[3].pos[VZ]; R_DivVerts(rvertices, origVerts, params->divs); R_DivTexCoords(rtexcoords, origTexCoords, params->divs, bL, tL, bR, tR); R_DivVertColors(rcolors, origColors, params->divs, bL, tL, bR, tR); } else { memcpy(rvertices, params->rvertices, sizeof(rvertex_t) * params->numVertices); } } else { // It's a flat. uint i; float width, height; width = params->texBR[VX] - params->texTL[VX]; height = params->texBR[VY] - params->texTL[VY]; for(i = 0; i < params->numVertices; ++i) { rtexcoords[i].st[0] = ((params->texBR[VX] - params->rvertices[i].pos[VX]) / width * dyn->s[0]) + ((params->rvertices[i].pos[VX] - params->texTL[VX]) / width * dyn->s[1]); rtexcoords[i].st[1] = ((params->texBR[VY] - params->rvertices[i].pos[VY]) / height * dyn->t[0]) + ((params->rvertices[i].pos[VY] - params->texTL[VY]) / height * dyn->t[1]); } memcpy(rvertices, params->rvertices, sizeof(rvertex_t) * params->numVertices); } if(params->isWall && params->divs) { RL_AddPoly(PT_FAN, RPT_LIGHT, rvertices + 3 + params->divs[0].num, rtexcoords + 3 + params->divs[0].num, NULL, NULL, rcolors + 3 + params->divs[0].num, 3 + params->divs[1].num, 0, 0, NULL, rTU); RL_AddPoly(PT_FAN, RPT_LIGHT, rvertices, rtexcoords, NULL, NULL, rcolors, 3 + params->divs[0].num, 0, 0, NULL, rTU); } else { RL_AddPoly(params->isWall? PT_TRIANGLE_STRIP : PT_FAN, RPT_LIGHT, rvertices, rtexcoords, NULL, NULL, rcolors, params->numVertices, 0, 0, NULL, rTU); } R_FreeRendVertices(rvertices); R_FreeRendTexCoords(rtexcoords); R_FreeRendColors(rcolors); } params->lastIdx++; return true; // Continue iteration. } static float getSnapshots(material_snapshot_t* msA, material_snapshot_t* msB, material_t* mat) { float interPos = 0; Material_Prepare(msA, mat, true, NULL); // Smooth Texture Animation? if(msB) { // If fog is active, inter=0 is accepted as well. Otherwise // flickering may occur if the rendering passes don't match for // blended and unblended surfaces. if(numTexUnits > 1 && mat->current != mat->next && !(!usingFog && mat->inter < 0)) { // Prepare the inter texture. Material_Prepare(msB, mat->next, false, NULL); interPos = mat->inter; } } return interPos; } static void setupRTU(rtexmapunit_t rTU[NUM_TEXMAP_UNITS], rtexmapunit_t rTUs[NUM_TEXMAP_UNITS], const material_snapshot_t* msA, float inter, const material_snapshot_t* msB) { rTU[TU_PRIMARY].tex = msA->units[MTU_PRIMARY].texInst->id; rTU[TU_PRIMARY].magMode = msA->units[MTU_PRIMARY].magMode; rTU[TU_PRIMARY].scale[0] = msA->units[MTU_PRIMARY].scale[0]; rTU[TU_PRIMARY].scale[1] = msA->units[MTU_PRIMARY].scale[1]; rTU[TU_PRIMARY].offset[0] = msA->units[MTU_PRIMARY].offset[0]; rTU[TU_PRIMARY].offset[1] = msA->units[MTU_PRIMARY].offset[1]; rTU[TU_PRIMARY].blendMode = msA->units[MTU_PRIMARY].blendMode; rTU[TU_PRIMARY].blend = msA->units[MTU_PRIMARY].alpha; if(msA->units[MTU_DETAIL].texInst) { rTU[TU_PRIMARY_DETAIL].tex = msA->units[MTU_DETAIL].texInst->id; rTU[TU_PRIMARY_DETAIL].magMode = msA->units[MTU_DETAIL].magMode; rTU[TU_PRIMARY_DETAIL].scale[0] = msA->units[MTU_DETAIL].scale[0]; rTU[TU_PRIMARY_DETAIL].scale[1] = msA->units[MTU_DETAIL].scale[1]; rTU[TU_PRIMARY_DETAIL].offset[0] = msA->units[MTU_DETAIL].offset[0]; rTU[TU_PRIMARY_DETAIL].offset[1] = msA->units[MTU_DETAIL].offset[1]; rTU[TU_PRIMARY_DETAIL].blendMode = msA->units[MTU_DETAIL].blendMode; rTU[TU_PRIMARY_DETAIL].blend = msA->units[MTU_DETAIL].alpha; } if(msB && msB->units[MTU_PRIMARY].texInst) { rTU[TU_INTER].tex = msB->units[MTU_PRIMARY].texInst->id; rTU[TU_INTER].magMode = msB->units[MTU_PRIMARY].magMode; rTU[TU_INTER].scale[0] = msB->units[MTU_PRIMARY].scale[0]; rTU[TU_INTER].scale[1] = msB->units[MTU_PRIMARY].scale[1]; rTU[TU_INTER].offset[0] = msB->units[MTU_PRIMARY].offset[0]; rTU[TU_INTER].offset[1] = msB->units[MTU_PRIMARY].offset[1]; rTU[TU_INTER].blendMode = msB->units[MTU_PRIMARY].blendMode; rTU[TU_INTER].blend = msB->units[MTU_PRIMARY].alpha; // Blend between the primary and inter textures. rTU[TU_INTER].blend = inter; } if(msB && msB->units[MTU_DETAIL].texInst) { rTU[TU_INTER_DETAIL].tex = msB->units[MTU_DETAIL].texInst->id; rTU[TU_INTER_DETAIL].magMode = msB->units[MTU_DETAIL].magMode; rTU[TU_INTER_DETAIL].scale[0] = msB->units[MTU_DETAIL].scale[0]; rTU[TU_INTER_DETAIL].scale[1] = msB->units[MTU_DETAIL].scale[1]; rTU[TU_INTER_DETAIL].offset[0] = msB->units[MTU_DETAIL].offset[0]; rTU[TU_INTER_DETAIL].offset[1] = msB->units[MTU_DETAIL].offset[1]; rTU[TU_INTER_DETAIL].blendMode = msB->units[MTU_DETAIL].blendMode; rTU[TU_INTER_DETAIL].blend = msB->units[MTU_DETAIL].alpha; // Blend between the primary and inter detail textures. rTU[TU_INTER_DETAIL].blend = inter; } if(msA->units[MTU_REFLECTION].texInst) { rTUs[TU_PRIMARY].tex = msA->units[MTU_REFLECTION].texInst->id; rTUs[TU_PRIMARY].magMode = msA->units[MTU_REFLECTION].magMode; rTUs[TU_PRIMARY].scale[0] = msA->units[MTU_REFLECTION].scale[0]; rTUs[TU_PRIMARY].scale[1] = msA->units[MTU_REFLECTION].scale[1]; rTUs[TU_PRIMARY].offset[0] = msA->units[MTU_REFLECTION].offset[0]; rTUs[TU_PRIMARY].offset[1] = msA->units[MTU_REFLECTION].offset[1]; rTUs[TU_PRIMARY].blendMode = msA->units[MTU_REFLECTION].blendMode; rTUs[TU_PRIMARY].blend = msA->units[MTU_REFLECTION].alpha; if(msA->units[MTU_REFLECTION_MASK].texInst) { rTUs[TU_INTER].tex = msA->units[MTU_REFLECTION_MASK].texInst->id; rTUs[TU_INTER].magMode = msA->units[MTU_REFLECTION_MASK].magMode; rTUs[TU_INTER].scale[0] = msA->units[MTU_REFLECTION_MASK].scale[0]; rTUs[TU_INTER].scale[1] = msA->units[MTU_REFLECTION_MASK].scale[1]; rTUs[TU_INTER].offset[0] = msA->units[MTU_REFLECTION_MASK].offset[0]; rTUs[TU_INTER].offset[1] = msA->units[MTU_REFLECTION_MASK].offset[1]; rTUs[TU_INTER].blendMode = msA->units[MTU_REFLECTION_MASK].blendMode; rTUs[TU_INTER].blend = msA->units[MTU_REFLECTION_MASK].alpha; } } } /** * Apply primitive-specific manipulations. */ static void setupRTU2(rtexmapunit_t rTU[NUM_TEXMAP_UNITS], rtexmapunit_t rTUs[NUM_TEXMAP_UNITS], boolean isWall, const float texOffset[2], const float texScale[2], const material_snapshot_t* msA, const material_snapshot_t* msB) { if(texScale) { rTU[TU_PRIMARY].scale[0] *= texScale[0]; rTU[TU_PRIMARY].scale[1] *= texScale[1]; } if(texOffset) { rTU[TU_PRIMARY].offset[0] += texOffset[0] / msA->width; rTU[TU_PRIMARY].offset[1] += (isWall? texOffset[1] : -texOffset[1]) / msA->height; } if(msA->units[MTU_DETAIL].texInst && texOffset) { rTU[TU_PRIMARY_DETAIL].offset[0] += texOffset[0] * rTU[TU_PRIMARY_DETAIL].scale[0]; rTU[TU_PRIMARY_DETAIL].offset[1] += (isWall? texOffset[1] : -texOffset[1]) * rTU[TU_PRIMARY_DETAIL].scale[1]; } if(msB && msB->units[MTU_PRIMARY].texInst) { if(texScale) { rTU[TU_INTER].scale[0] *= texScale[0]; rTU[TU_INTER].scale[1] *= texScale[1]; } if(texOffset) { rTU[TU_INTER].offset[0] += texOffset[0] / msB->width; rTU[TU_INTER].offset[1] += (isWall? texOffset[1] : -texOffset[1]) / msB->height; } } if(msB && msB->units[MTU_DETAIL].texInst && texOffset) { rTU[TU_INTER_DETAIL].offset[0] += texOffset[0] * rTU[TU_INTER_DETAIL].scale[0]; rTU[TU_INTER_DETAIL].offset[1] += (isWall? texOffset[1] : -texOffset[1]) * rTU[TU_INTER_DETAIL].scale[1]; } if(msA->units[MTU_REFLECTION].texInst) { if(texScale) { rTUs[TU_INTER].scale[0] *= texScale[0]; rTUs[TU_INTER].scale[1] *= texScale[1]; } if(texOffset) { rTUs[TU_INTER].offset[0] += texOffset[0] / msA->width; rTUs[TU_INTER].offset[1] += (isWall? texOffset[1] : -texOffset[1]) / msA->height; } } } typedef struct { boolean isWall; rendpolytype_t type; blendmode_t blendMode; const float* texTL, *texBR; const float* texOffset, *texScale; const float* normal; // Surface normal. float alpha; const float* sectorLightLevel; float surfaceLightLevelDL; float surfaceLightLevelDR; const float* sectorLightColor; const float* surfaceColor; uint lightListIdx; // List of lights that affect this poly. boolean glowing; boolean reflective; boolean forceOpaque; // For bias: void* mapObject; uint elmIdx; biassurface_t* bsuf; // Wall only (todo). const float* segLength; const float* surfaceColor2; // Secondary color. } rendworldpoly_params_t; static boolean renderWorldPoly(rvertex_t* rvertices, uint numVertices, const walldiv_t* divs, const rendworldpoly_params_t* p, const material_snapshot_t* msA, float inter, const material_snapshot_t* msB) { rcolor_t* rcolors; rtexcoord_t* rtexcoords = NULL, *rtexcoords2 = NULL, *rtexcoords5 = NULL; uint realNumVertices = p->isWall && divs? 3 + divs[0].num + 3 + divs[1].num : numVertices; rcolor_t* shinyColors = NULL; rtexcoord_t* shinyTexCoords = NULL; boolean useLights = false; uint numLights = 0; DGLuint modTex = 0; float modTexTC[2][2]; float modColor[3]; boolean drawAsVisSprite = false, isGlowing = p->glowing; rtexmapunit_t rTU[NUM_TEXMAP_UNITS], rTUs[NUM_TEXMAP_UNITS]; if(!p->forceOpaque && p->type != RPT_SKY_MASK && (!msA->isOpaque || p->alpha < 1 || p->blendMode > 0)) drawAsVisSprite = true; memset(rTU, 0, sizeof(rtexmapunit_t) * NUM_TEXMAP_UNITS); memset(rTUs, 0, sizeof(rtexmapunit_t) * NUM_TEXMAP_UNITS); if(p->type != RPT_SKY_MASK) { setupRTU(rTU, rTUs, msA, inter, msB); setupRTU2(rTU, rTUs, p->isWall, p->texOffset, p->texScale, msA, msB); } memset(modTexTC, 0, sizeof(modTexTC)); memset(modColor, 0, sizeof(modColor)); rcolors = R_AllocRendColors(realNumVertices); rtexcoords = R_AllocRendTexCoords(realNumVertices); if(rTU[TU_INTER].tex) rtexcoords2 = R_AllocRendTexCoords(realNumVertices); if(p->type != RPT_SKY_MASK) { // ShinySurface? if(p->reflective && rTUs[TU_PRIMARY].tex && !drawAsVisSprite) { // We'll reuse the same verts but we need new colors. shinyColors = R_AllocRendColors(realNumVertices); // The normal texcoords are used with the mask. // New texcoords are required for shiny texture. shinyTexCoords = R_AllocRendTexCoords(realNumVertices); } /** * Dynamic lights? * In multiplicative mode, glowing surfaces are fullbright. * Rendering lights on them would be pointless. */ if(!isGlowing) { useLights = (p->lightListIdx? true : false); /** * If multitexturing is enabled and there is at least one * dynlight affecting this surface, grab the paramaters needed * to draw it. */ if(useLights && RL_IsMTexLights()) { dynlight_t* dyn = NULL; DL_ListIterator(p->lightListIdx, &dyn, RLIT_DynGetFirst); rtexcoords5 = R_AllocRendTexCoords(realNumVertices); modTex = dyn->texture; modColor[CR] = dyn->color[CR]; modColor[CG] = dyn->color[CG]; modColor[CB] = dyn->color[CB]; modTexTC[0][0] = dyn->s[0]; modTexTC[0][1] = dyn->s[1]; modTexTC[1][0] = dyn->t[0]; modTexTC[1][1] = dyn->t[1]; numLights = 1; } } } if(p->isWall) { // Primary texture coordinates. quadTexCoords(rtexcoords, rvertices, *p->segLength, p->texTL); // Blend texture coordinates. if(rTU[TU_INTER].tex && !drawAsVisSprite) quadTexCoords(rtexcoords2, rvertices, *p->segLength, p->texTL); // Shiny texture coordinates. if(p->reflective && rTUs[TU_PRIMARY].tex && !drawAsVisSprite) quadShinyTexCoords(shinyTexCoords, &rvertices[1], &rvertices[2], *p->segLength); // First light texture coordinates. if(numLights > 0 && RL_IsMTexLights()) quadLightCoords(rtexcoords5, modTexTC[0], modTexTC[1]); } else { uint i; for(i = 0; i < numVertices; ++i) { const rvertex_t* vtx = &rvertices[i]; float xyz[3]; xyz[VX] = vtx->pos[VX] - p->texTL[VX]; xyz[VY] = vtx->pos[VY] - p->texTL[VY]; xyz[VZ] = vtx->pos[VZ] - p->texTL[VZ]; // Primary texture coordinates. if(rTU[TU_PRIMARY].tex) { rtexcoord_t* tc = &rtexcoords[i]; tc->st[0] = xyz[VX]; tc->st[1] = -xyz[VY]; } // Blend primary texture coordinates. if(rTU[TU_INTER].tex) { rtexcoord_t* tc = &rtexcoords2[i]; tc->st[0] = xyz[VX]; tc->st[1] = -xyz[VY]; } // Shiny texture coordinates. if(p->reflective && rTUs[TU_PRIMARY].tex) { flatShinyTexCoords(&shinyTexCoords[i], vtx->pos); } // First light texture coordinates. if(numLights > 0 && RL_IsMTexLights()) { rtexcoord_t* tc = &rtexcoords5[i]; float width, height; width = p->texBR[VX] - p->texTL[VX]; height = p->texBR[VY] - p->texTL[VY]; tc->st[0] = ((p->texBR[VX] - vtx->pos[VX]) / width * modTexTC[0][0]) + (xyz[VX] / width * modTexTC[0][1]); tc->st[1] = ((p->texBR[VY] - vtx->pos[VY]) / height * modTexTC[1][0]) + (xyz[VY] / height * modTexTC[1][1]); } } } // Light this polygon. if(p->type != RPT_SKY_MASK) { if(isGlowing || levelFullBright) { // Uniform colour. Apply to all vertices. Rend_VertexColorsGlow(rcolors, numVertices); } else { // Non-uniform color. if(useBias && p->bsuf) { // Do BIAS lighting for this poly. SB_RendPoly(rcolors, p->bsuf, rvertices, numVertices, p->normal, *p->sectorLightLevel, p->mapObject, p->elmIdx, p->isWall); } else { uint i; // Calculate the color for each vertex, blended with plane color? if(p->surfaceColor[0] < 1 || p->surfaceColor[1] < 1 || p->surfaceColor[2] < 1) { float vColor[4]; // Blend sector light+color+surfacecolor vColor[CR] = p->surfaceColor[CR] * p->sectorLightColor[CR]; vColor[CG] = p->surfaceColor[CG] * p->sectorLightColor[CG]; vColor[CB] = p->surfaceColor[CB] * p->sectorLightColor[CB]; vColor[CA] = 1; if(p->isWall) { float llL = *p->sectorLightLevel + p->surfaceLightLevelDL; float llR = *p->sectorLightLevel + p->surfaceLightLevelDR; lightVertex(&rcolors[0], &rvertices[0], llL, vColor); lightVertex(&rcolors[1], &rvertices[1], llL, vColor); lightVertex(&rcolors[2], &rvertices[2], llR, vColor); lightVertex(&rcolors[3], &rvertices[3], llR, vColor); } else { float ll = *p->sectorLightLevel + p->surfaceLightLevelDL; for(i = 0; i < numVertices; ++i) lightVertex(&rcolors[i], &rvertices[i], ll, vColor); } } else { // Use sector light+color only. if(p->isWall) { float llL = *p->sectorLightLevel + p->surfaceLightLevelDL; float llR = *p->sectorLightLevel + p->surfaceLightLevelDR; lightVertex(&rcolors[0], &rvertices[0], llL, p->sectorLightColor); lightVertex(&rcolors[1], &rvertices[1], llL, p->sectorLightColor); lightVertex(&rcolors[2], &rvertices[2], llR, p->sectorLightColor); lightVertex(&rcolors[3], &rvertices[3], llR, p->sectorLightColor); } else { float ll = *p->sectorLightLevel + p->surfaceLightLevelDL; for(i = 0; i < numVertices; ++i) lightVertex(&rcolors[i], &rvertices[i], ll, p->sectorLightColor); } } // Bottom color (if different from top)? if(p->isWall && p->surfaceColor2) { float vColor[4]; // Blend sector light+color+surfacecolor vColor[CR] = p->surfaceColor2[CR] * p->sectorLightColor[CR]; vColor[CG] = p->surfaceColor2[CG] * p->sectorLightColor[CG]; vColor[CB] = p->surfaceColor2[CB] * p->sectorLightColor[CB]; vColor[CA] = 1; lightVertex(&rcolors[0], &rvertices[0], *p->sectorLightLevel + p->surfaceLightLevelDL, vColor); lightVertex(&rcolors[2], &rvertices[2], *p->sectorLightLevel + p->surfaceLightLevelDR, vColor); } } Rend_VertexColorsApplyTorchLight(rcolors, rvertices, numVertices); } if(p->reflective && rTUs[TU_PRIMARY].tex && !drawAsVisSprite) { uint i; // Strength of the shine. for(i = 0; i < numVertices; ++i) { shinyColors[i].rgba[CR] = MAX_OF(rcolors[i].rgba[CR], msA->shiny.minColor[CR]); shinyColors[i].rgba[CG] = MAX_OF(rcolors[i].rgba[CG], msA->shiny.minColor[CG]); shinyColors[i].rgba[CB] = MAX_OF(rcolors[i].rgba[CB], msA->shiny.minColor[CB]); shinyColors[i].rgba[CA] = rTUs[TU_PRIMARY].blend; } } // Apply uniform alpha. Rend_VertexColorsAlpha(rcolors, numVertices, p->alpha); } else { memset(rcolors, 0, sizeof(rcolor_t) * numVertices); } if(IS_MUL && useLights) { // Surfaces lit by dynamic lights may need to be rendered // differently than non-lit surfaces. uint i; float avglightlevel = 0; // Determine the average light level of this rend poly, // if too bright; do not bother with lights. for(i = 0; i < numVertices; ++i) { avglightlevel += rcolors[i].rgba[CR]; avglightlevel += rcolors[i].rgba[CG]; avglightlevel += rcolors[i].rgba[CB]; } avglightlevel /= (float) numVertices * 3; if(avglightlevel > 0.98f) { useLights = false; } } if(drawAsVisSprite) { assert(p->isWall); /** * Masked polys (walls) get a special treatment (=> vissprite). * This is needed because all masked polys must be sorted (sprites * are masked polys). Otherwise there will be artifacts. */ Rend_AddMaskedPoly(rvertices, rcolors, *p->segLength, msA->width, msA->height, p->texOffset, p->blendMode, p->lightListIdx, isGlowing, !msA->isOpaque, rTU); R_FreeRendTexCoords(rtexcoords); if(rtexcoords2) R_FreeRendTexCoords(rtexcoords2); if(rtexcoords5) R_FreeRendTexCoords(rtexcoords5); if(shinyTexCoords) R_FreeRendTexCoords(shinyTexCoords); R_FreeRendColors(rcolors); if(shinyColors) R_FreeRendColors(shinyColors); return false; // We HAD to use a vissprite, so it MUST not be opaque. } if(p->type != RPT_SKY_MASK && useLights) { /** * Generate a dynlight primitive for each of the lights affecting * the surface. Multitexturing may be used for the first light, so * it's skipped. */ dynlightiterparams_t dlparams; dlparams.rvertices = rvertices; dlparams.numVertices = numVertices; dlparams.realNumVertices = realNumVertices; dlparams.lastIdx = 0; dlparams.isWall = p->isWall; dlparams.divs = divs; dlparams.texTL = p->texTL; dlparams.texBR = p->texBR; DL_ListIterator(p->lightListIdx, &dlparams, RLIT_DynLightWrite); numLights += dlparams.lastIdx; if(RL_IsMTexLights()) numLights -= 1; } // Write multiple polys depending on rend params. if(p->isWall && divs) { float bL, tL, bR, tR; rvertex_t origVerts[4]; rcolor_t origColors[4]; rtexcoord_t origTexCoords[4]; /** * Need to swap indices around into fans set the position * of the division vertices, interpolate texcoords and * color. */ memcpy(origVerts, rvertices, sizeof(rvertex_t) * 4); memcpy(origTexCoords, rtexcoords, sizeof(rtexcoord_t) * 4); memcpy(origColors, rcolors, sizeof(rcolor_t) * 4); bL = origVerts[0].pos[VZ]; tL = origVerts[1].pos[VZ]; bR = origVerts[2].pos[VZ]; tR = origVerts[3].pos[VZ]; R_DivVerts(rvertices, origVerts, divs); R_DivTexCoords(rtexcoords, origTexCoords, divs, bL, tL, bR, tR); R_DivVertColors(rcolors, origColors, divs, bL, tL, bR, tR); if(rtexcoords2) { rtexcoord_t origTexCoords2[4]; memcpy(origTexCoords2, rtexcoords2, sizeof(rtexcoord_t) * 4); R_DivTexCoords(rtexcoords2, origTexCoords2, divs, bL, tL, bR, tR); } if(rtexcoords5) { rtexcoord_t origTexCoords5[4]; memcpy(origTexCoords5, rtexcoords5, sizeof(rtexcoord_t) * 4); R_DivTexCoords(rtexcoords5, origTexCoords5, divs, bL, tL, bR, tR); } if(shinyTexCoords) { rtexcoord_t origShinyTexCoords[4]; memcpy(origShinyTexCoords, shinyTexCoords, sizeof(rtexcoord_t) * 4); R_DivTexCoords(shinyTexCoords, origShinyTexCoords, divs, bL, tL, bR, tR); } if(shinyColors) { rcolor_t origShinyColors[4]; memcpy(origShinyColors, shinyColors, sizeof(rcolor_t) * 4); R_DivVertColors(shinyColors, origShinyColors, divs, bL, tL, bR, tR); } RL_AddPoly(PT_FAN, p->type, rvertices + 3 + divs[0].num, rtexcoords + 3 + divs[0].num, rtexcoords2? rtexcoords2 + 3 + divs[0].num : NULL, rtexcoords5? rtexcoords5 + 3 + divs[0].num : NULL, rcolors + 3 + divs[0].num, 3 + divs[1].num, numLights, modTex, modColor, rTU); RL_AddPoly(PT_FAN, p->type, rvertices, rtexcoords, rtexcoords2, rtexcoords5, rcolors, 3 + divs[0].num, numLights, modTex, modColor, rTU); if(p->reflective && rTUs[TU_PRIMARY].tex) { RL_AddPoly(PT_FAN, RPT_SHINY, rvertices + 3 + divs[0].num, shinyTexCoords? shinyTexCoords + 3 + divs[0].num : NULL, rTUs[TU_INTER].tex? rtexcoords + 3 + divs[0].num : NULL, NULL, shinyColors + 3 + divs[0].num, 3 + divs[1].num, 0, 0, NULL, rTUs); RL_AddPoly(PT_FAN, RPT_SHINY, rvertices, shinyTexCoords, rTUs[TU_INTER].tex? rtexcoords : NULL, NULL, shinyColors, 3 + divs[0].num, 0, 0, NULL, rTUs); } } else { RL_AddPoly(p->isWall? PT_TRIANGLE_STRIP : PT_FAN, p->type, rvertices, rtexcoords, rtexcoords2, rtexcoords5, rcolors, numVertices, numLights, modTex, modColor, rTU); if(p->reflective && rTUs[TU_PRIMARY].tex) RL_AddPoly(p->isWall? PT_TRIANGLE_STRIP : PT_FAN, RPT_SHINY, rvertices, shinyTexCoords, rTUs[TU_INTER].tex? rtexcoords : NULL, NULL, shinyColors, numVertices, 0, 0, NULL, rTUs); } R_FreeRendTexCoords(rtexcoords); if(rtexcoords2) R_FreeRendTexCoords(rtexcoords2); if(rtexcoords5) R_FreeRendTexCoords(rtexcoords5); if(shinyTexCoords) R_FreeRendTexCoords(shinyTexCoords); R_FreeRendColors(rcolors); if(shinyColors) R_FreeRendColors(shinyColors); return (p->forceOpaque || !(p->alpha < 1 || !msA->isOpaque || p->blendMode > 0)); } static boolean doRenderSeg(seg_t* seg, const fvertex_t* from, const fvertex_t* to, float bottom, float top, const pvec3_t normal, float alpha, const float* lightLevel, float lightLevelDL, float lightLevelDR, const float* lightColor, uint lightListIdx, const walldiv_t* divs, boolean skyMask, boolean addFakeRadio, boolean addReflection, boolean isGlowing, const float texTL[3], const float texBR[3], const float texOffset[2], const float texScale[2], blendmode_t blendMode, const float* color, const float* color2, biassurface_t* bsuf, uint elmIdx /*tmp*/, const material_snapshot_t* msA, float inter, const material_snapshot_t* msB, boolean isTwosidedMiddle) { rendworldpoly_params_t params; sidedef_t* side = (seg->lineDef? SEG_SIDEDEF(seg) : NULL); rvertex_t* rvertices; // Init the params. memset(¶ms, 0, sizeof(params)); params.type = (skyMask? RPT_SKY_MASK : RPT_NORMAL); params.isWall = true; params.segLength = &seg->length; params.forceOpaque = (alpha < 0? true : false); params.alpha = (alpha < 0? 1 : alpha); params.mapObject = seg; params.elmIdx = elmIdx; params.bsuf = bsuf; params.normal = normal; params.texTL = texTL; params.texBR = texBR; params.sectorLightLevel = lightLevel; params.surfaceLightLevelDL = lightLevelDL; params.surfaceLightLevelDR = lightLevelDR; params.sectorLightColor = lightColor; params.surfaceColor = color; params.surfaceColor2 = color2; params.blendMode = blendMode; params.texOffset = texOffset; params.texScale = texScale; params.lightListIdx = lightListIdx; if(divs) { // Allocate enough vertices for the divisions too. rvertices = R_AllocRendVertices(3 + divs[0].num + 3 + divs[1].num); } else { rvertices = R_AllocRendVertices(4); } // Vertex coords. // Bottom Left. V3_Set(rvertices[0].pos, from->pos[VX], from->pos[VY], bottom); // Top Left. V3_Set(rvertices[1].pos, from->pos[VX], from->pos[VY], top); // Bottom Right. V3_Set(rvertices[2].pos, to->pos[VX], to->pos[VY], bottom); // Top Right. V3_Set(rvertices[3].pos, to->pos[VX], to->pos[VY], top); // Is reflective? if(addReflection) { params.reflective = true; } // Make it fullbright? if(isGlowing) params.glowing = true; // Draw this seg. if(renderWorldPoly(rvertices, 4, divs, ¶ms, msA, inter, msB)) { // Drawn poly was opaque. // Render Fakeradio polys for this seg? if(params.type != RPT_SKY_MASK && addFakeRadio) { rendsegradio_params_t radioParams; radioParams.sectorLightLevel = lightLevel; radioParams.linedefLength = &seg->lineDef->length; radioParams.botCn = side->bottomCorners; radioParams.topCn = side->topCorners; radioParams.sideCn = side->sideCorners; radioParams.spans = side->spans; radioParams.segOffset = &seg->offset; radioParams.segLength = &seg->length; radioParams.frontSec = seg->SG_frontsector; radioParams.backSec = (!isTwosidedMiddle? seg->SG_backsector : NULL); /** * \kludge Revert the vertex coords as they may have been changed * due to height divisions. */ // Bottom Left. V3_Set(rvertices[0].pos, from->pos[VX], from->pos[VY], bottom); // Top Left. V3_Set(rvertices[1].pos, from->pos[VX], from->pos[VY], top); // Bottom Right. V3_Set(rvertices[2].pos, to->pos[VX], to->pos[VY], bottom); // Top Right. V3_Set(rvertices[3].pos, to->pos[VX], to->pos[VY], top); Rend_RadioSegSection(rvertices, divs, &radioParams); } R_FreeRendVertices(rvertices); return true; // Clip with this solid seg. } R_FreeRendVertices(rvertices); return false; // Do not clip with this. } static void renderPlane(subsector_t* ssec, planetype_t type, float height, const vectorcomp_t normal[3], material_t* inMat, short sufInFlags, const float sufColor[4], blendmode_t blendMode, const float texTL[3], const float texBR[3], const float texOffset[2], const float texScale[2], boolean skyMasked, boolean addDLights, boolean isGlowing, biassurface_t* bsuf, uint elmIdx /*tmp*/, int texMode /*tmp*/) { float inter = 0; rendworldpoly_params_t params; uint numVertices = ssec->numVertices; rvertex_t* rvertices; boolean blended = false; sector_t* sec = ssec->sector; material_t* mat = NULL; material_snapshot_t msA, msB; memset(&msA, 0, sizeof(msA)); memset(&msB, 0, sizeof(msB)); memset(¶ms, 0, sizeof(params)); params.isWall = false; params.mapObject = ssec; params.elmIdx = elmIdx; params.bsuf = bsuf; params.normal = normal; params.texTL = texTL; params.texBR = texBR; params.sectorLightLevel = &sec->lightLevel; params.sectorLightColor = R_GetSectorLightColor(sec); params.surfaceLightLevelDL = params.surfaceLightLevelDR = 0; params.surfaceColor = sufColor; params.texOffset = texOffset; params.texScale = texScale; if(skyMasked) { skyhemispheres |= (type == PLN_FLOOR? SKYHEMI_LOWER : SKYHEMI_UPPER); // In devRendSkyMode mode we render all polys destined for the // skymask as regular world polys (with a few obvious properties). if(devRendSkyMode) { params.type = RPT_NORMAL; params.blendMode = BM_NORMAL; params.glowing = true; params.forceOpaque = true; mat = inMat; } else { // We'll mask this. params.type = RPT_SKY_MASK; } } else { params.type = RPT_NORMAL; mat = inMat; if(isGlowing) { params.glowing = true; // Make it stand out } if(type != PLN_MID) { params.blendMode = BM_NORMAL; params.alpha = 1; params.forceOpaque = true; } else { if(blendMode == BM_NORMAL && noSpriteTrans) params.blendMode = BM_ZEROALPHA; // "no translucency" mode else params.blendMode = blendMode; params.alpha = sufColor[CA]; } } /** * If this poly is destined for the skymask, we don't need to * do any further processing. */ if(params.type != RPT_SKY_MASK) { // Smooth Texture Animation? if(smoothTexAnim && texMode != 1) blended = true; // Dynamic lights. if(addDLights && !params.glowing) { params.lightListIdx = DL_ProjectOnSurface(ssec, params.texTL, params.texBR, normal, (DLF_NO_PLANAR | (type == PLN_FLOOR? DLF_TEX_FLOOR : DLF_TEX_CEILING))); } // Render Shiny polys? if(useShinySurfaces && mat && mat->reflection) { params.reflective = true; } } rvertices = R_AllocRendVertices(numVertices); Rend_PreparePlane(rvertices, numVertices, height, ssec, !(normal[VZ] > 0)); if(params.type != RPT_SKY_MASK) { inter = getSnapshots(&msA, blended? &msB : NULL, mat); } renderWorldPoly(rvertices, numVertices, NULL, ¶ms, &msA, inter, blended? &msB : NULL); R_FreeRendVertices(rvertices); } static void Rend_RenderPlane(subsector_t* ssec, planetype_t type, float height, const vectorcomp_t normal[3], material_t* inMat, short sufInFlags, const float sufColor[4], blendmode_t blendMode, const float texOffset[2], const float texScale[2], boolean skyMasked, boolean addDLights, boolean isGlowing, biassurface_t* bsuf, uint elmIdx /*tmp*/, int texMode /*tmp*/) { vec3_t vec; // Must have a visible surface. if(!inMat || (inMat->flags & MATF_NO_DRAW)) return; V3_Set(vec, vx - ssec->midPoint.pos[VX], vz - ssec->midPoint.pos[VY], vy - height); // Don't bother with planes facing away from the camera. if(!(V3_DotProduct(vec, normal) < 0)) { float texTL[3], texBR[3]; // Set the texture origin, Y is flipped for the ceiling. V3_Set(texTL, ssec->bBox[0].pos[VX], ssec->bBox[type == PLN_FLOOR? 1 : 0].pos[VY], height); V3_Set(texBR, ssec->bBox[1].pos[VX], ssec->bBox[type == PLN_FLOOR? 0 : 1].pos[VY], height); renderPlane(ssec, type, height, normal, inMat, sufInFlags, sufColor, blendMode, texTL, texBR, texOffset, texScale, skyMasked, addDLights, isGlowing, bsuf, elmIdx, texMode); } } static boolean isVisible(surface_t* surface, sector_t* frontsec, boolean canMask, boolean* skyMask) { if(!(surface->material && (surface->material->flags & MATF_NO_DRAW))) { *skyMask = false; return true; } else if(canMask) { // Perhaps add this section to the sky mask? if(R_IsSkySurface(&frontsec->SP_ceilsurface) && R_IsSkySurface(&frontsec->SP_floorsurface)) { *skyMask = true; return true; } } return false; } static boolean rendSegSection(subsector_t* ssec, seg_t* seg, segsection_t section, surface_t* surface, const fvertex_t* from, const fvertex_t* to, float bottom, float top, const float texOffset[2], sector_t* frontsec, boolean softSurface, boolean addDLights, short sideFlags) { float alpha; boolean skyMask; boolean solidSeg = true; if(!isVisible(surface, frontsec, false, &skyMask)) return false; if(bottom >= top) return true; alpha = (section == SEG_MIDDLE? surface->rgba[3] : 1.0f); if(section == SEG_MIDDLE && softSurface) { mobj_t* mo = viewPlayer->shared.mo; const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); /** * Can the player walk through this surface? * If the player is close enough we should NOT add a * solid seg otherwise they'd get HOM when they are * directly on top of the line (eg passing through an * opaque waterfall). */ if(viewData->current.pos[VZ] > bottom && viewData->current.pos[VZ] < top) { float delta[2], pos, result[2]; linedef_t* lineDef = seg->lineDef; delta[0] = lineDef->dX; delta[1] = lineDef->dY; pos = M_ProjectPointOnLine(mo->pos, lineDef->L_v1pos, delta, 0, result); if(pos > 0 && pos < 1) { float distance; float minDistance = mo->radius * .8f; delta[VX] = mo->pos[VX] - result[VX]; delta[VY] = mo->pos[VY] - result[VY]; distance = M_ApproxDistancef(delta[VX], delta[VY]); if(distance < minDistance) { // Fade it out the closer the viewPlayer gets and clamp. alpha = (alpha / minDistance) * distance; alpha = MINMAX_OF(0, alpha, 1); } if(alpha < 1) solidSeg = false; } } } if(alpha > 0) { int texMode = 0; uint lightListIdx = 0; float texTL[3], texBR[3], texScale[2], inter = 0; walldiv_t divs[2]; boolean forceOpaque = false; material_t* mat = NULL; rendpolytype_t type = RPT_NORMAL; boolean isTwoSided = (seg->lineDef && seg->lineDef->L_frontside && seg->lineDef->L_backside)? true:false; blendmode_t blendMode = BM_NORMAL; boolean addFakeRadio = false, addReflection = false, isGlowing = false, blended = false; const float* color = NULL, *color2 = NULL; material_snapshot_t msA, msB; memset(&msA, 0, sizeof(msA)); memset(&msB, 0, sizeof(msB)); texScale[0] = ((surface->flags & DDSUF_MATERIAL_FLIPH)? -1 : 1); texScale[1] = ((surface->flags & DDSUF_MATERIAL_FLIPV)? -1 : 1); V3_Set(texTL, from->pos[VX], from->pos[VY], top); V3_Set(texBR, to->pos [VX], to->pos [VY], bottom); // Fill in the remaining params data. if(skyMask || R_IsSkySurface(surface)) { // In devRendSkyMode mode we render all polys destined for the skymask // as regular world polys (with a few obvious properties). if(devRendSkyMode) { mat = surface->material; forceOpaque = true; isGlowing = true; } else { // We'll mask this. type = RPT_SKY_MASK; } } else { int surfaceFlags, surfaceInFlags; // Determine which texture to use. if(renderTextures == 2) texMode = 2; else if(!surface->material || ((surface->inFlags & SUIF_MATERIAL_FIX) && devNoTexFix)) texMode = 1; else texMode = 0; if(texMode == 0) mat = surface->material; else if(texMode == 1) // For debug, render the "missing" texture instead of the texture // chosen for surfaces to fix the HOMs. mat = P_GetMaterial(DDT_MISSING, MN_SYSTEM); else // texMode == 2 // For lighting debug, render all solid surfaces using the gray // texture. mat = P_GetMaterial(DDT_GRAY, MN_SYSTEM); // Make any necessary adjustments to the surface flags to suit the // current texture mode. surfaceFlags = surface->flags; surfaceInFlags = surface->inFlags; if(texMode == 1) { isGlowing = true; // Make it stand out } else if(texMode == 2) { surfaceInFlags &= ~(SUIF_MATERIAL_FIX); } if(section != SEG_MIDDLE || (section == SEG_MIDDLE && !isTwoSided)) { forceOpaque = true; blendMode = BM_NORMAL; } else { if(surface->blendMode == BM_NORMAL && noSpriteTrans) blendMode = BM_ZEROALPHA; // "no translucency" mode else blendMode = surface->blendMode; } if(glowingTextures && ((surfaceFlags & DDSUF_GLOW) || (surface->material && (surface->material->flags & MATF_GLOW)))) isGlowing = true; addFakeRadio = !(surfaceInFlags & SUIF_NO_RADIO); } if(type != RPT_SKY_MASK) { // Smooth Texture Animation? if(smoothTexAnim && texMode != 1) blended = true; } if(type != RPT_SKY_MASK) { inter = getSnapshots(&msA, blended? &msB : NULL, mat); } if(addDLights && !isGlowing) lightListIdx = DL_ProjectOnSurface(ssec, texTL, texBR, SEG_SIDEDEF(seg)->SW_middlenormal, ((section == SEG_MIDDLE && isTwoSided)? DLF_SORT_LUMADSC : 0)); addFakeRadio = ((addFakeRadio && !isGlowing)? true : false); addReflection = (useShinySurfaces && mat && mat->reflection? true : false); selectSurfaceColors(&color, &color2, SEG_SIDEDEF(seg), section); // Check for neighborhood division? divs[0].num = divs[1].num = 0; if(!(section == SEG_MIDDLE && isTwoSided) && !(seg->lineDef->inFlags & LF_POLYOBJ)) { applyWallHeightDivision(divs, seg, frontsec, bottom, top); } { float deltaL, deltaR, diff; Linedef_LightLevelDelta(seg->lineDef, seg->side, &deltaL, &deltaR); // Linear interpolation of the linedef light deltas to the edges of the seg. diff = deltaR - deltaL; deltaR = deltaL + ((seg->offset + seg->length) / seg->lineDef->length) * diff; deltaL += (seg->offset / seg->lineDef->length) * diff; solidSeg = doRenderSeg(seg, from, to, bottom, top, surface->normal, (forceOpaque? -1 : alpha), &frontsec->lightLevel, deltaL, deltaR, R_GetSectorLightColor(frontsec), lightListIdx, (divs[0].num > 0 || divs[1].num > 0)? divs : NULL, skyMask, addFakeRadio, addReflection, isGlowing, texTL, texBR, texOffset, texScale, blendMode, color, color2, seg->bsuf[section], (uint) section, &msA, inter, blended? &msB : NULL, (section == SEG_MIDDLE && isTwoSided)); } } return solidSeg; } /** * Renders the given single-sided seg into the world. */ static boolean Rend_RenderSSWallSeg(subsector_t* ssec, seg_t* seg) { boolean solidSeg = true; sidedef_t* side; linedef_t* ldef; float ffloor, fceil; boolean backSide; sector_t* frontsec; int pid; side = SEG_SIDEDEF(seg); if(!side) { // A one-way window. return false; } frontsec = ssec->sector; backSide = seg->side; ldef = seg->lineDef; pid = viewPlayer - ddPlayers; if(!ldef->mapped[pid]) { ldef->mapped[pid] = true; // This line is now seen in the map. // Send a status report. if(gx.HandleMapObjectStatusReport) gx.HandleMapObjectStatusReport(DMUSC_LINE_FIRSTRENDERED, GET_LINE_IDX(ldef), DMU_LINEDEF, &pid); } ffloor = ssec->sector->SP_floorvisheight; fceil = ssec->sector->SP_ceilvisheight; // Create the wall sections. // Middle section. if(side->SW_middleinflags & SUIF_PVIS) { float texOffset[2]; surface_t* surface = &side->SW_middlesurface; texOffset[0] = surface->visOffset[0] + seg->offset; texOffset[1] = surface->visOffset[1]; if(ldef->flags & DDLF_DONTPEGBOTTOM) texOffset[1] += -(fceil - ffloor); Rend_RadioUpdateLinedef(seg->lineDef, seg->side); solidSeg = rendSegSection(ssec, seg, SEG_MIDDLE, &side->SW_middlesurface, &seg->SG_v1->v, &seg->SG_v2->v, ffloor, fceil, texOffset, /*temp >*/ frontsec, /*< temp*/ false, true, side->flags); } if(P_IsInVoid(viewPlayer)) solidSeg = false; return solidSeg; } boolean R_FindBottomTop(segsection_t section, float segOffset, const surface_t* suf, const plane_t* ffloor, const plane_t* fceil, const plane_t* bfloor, const plane_t* bceil, boolean unpegBottom, boolean unpegTop, boolean stretchMiddle, boolean isSelfRef, float* bottom, float* top, float texOffset[2]) { switch(section) { case SEG_TOP: *top = fceil->visHeight; // Can't go over front ceiling, would induce polygon flaws. if(bceil->visHeight < ffloor->visHeight) *bottom = ffloor->visHeight; else *bottom = bceil->visHeight; if(*top > *bottom) { texOffset[VX] = suf->visOffset[VX] + segOffset; texOffset[VY] = suf->visOffset[VY]; // Align with normal middle texture? if(!unpegTop) texOffset[VY] += -(fceil->visHeight - bceil->visHeight); return true; } break; case SEG_BOTTOM: { float t = bfloor->visHeight; *bottom = ffloor->visHeight; // Can't go over the back ceiling, would induce polygon flaws. if(bfloor->visHeight > bceil->visHeight) t = bceil->visHeight; // Can't go over front ceiling, would induce polygon flaws. if(t > fceil->visHeight) t = fceil->visHeight; *top = t; if(*top > *bottom) { texOffset[VX] = suf->visOffset[VX] + segOffset; texOffset[VY] = suf->visOffset[VY]; if(bfloor->visHeight > fceil->visHeight) texOffset[VY] += -(fceil->visHeight - bfloor->visHeight); // Align with normal middle texture? if(unpegBottom) texOffset[VY] += fceil->visHeight - bfloor->visHeight; return true; } break; } case SEG_MIDDLE: { float ftop, fbottom, vR_ZBottom, vR_ZTop; material_t* mat = suf->material->current; if(isSelfRef) { fbottom = MIN_OF(bfloor->visHeight, ffloor->visHeight); ftop = MAX_OF(bceil->visHeight, fceil->visHeight); } else { fbottom = MAX_OF(bfloor->visHeight, ffloor->visHeight); ftop = MIN_OF(bceil->visHeight, fceil->visHeight); } //fbottom += suf->visOffset[VY]; //ftop += suf->visOffset[VY]; *bottom = vR_ZBottom = fbottom; *top = vR_ZTop = ftop; if(stretchMiddle) { if(*top > *bottom) { texOffset[VX] = suf->visOffset[VX] + segOffset; texOffset[VY] = 0; return true; } } else { boolean clipBottom = !(R_IsSkySurface(&ffloor->surface) && R_IsSkySurface(&bfloor->surface)); boolean clipTop = !(R_IsSkySurface(&fceil->surface) && R_IsSkySurface(&bceil->surface)); if(Rend_MidMaterialPos(bottom, &vR_ZBottom, top, &vR_ZTop, NULL, suf->visOffset[VY], mat->height, unpegBottom, clipTop, clipBottom)) { texOffset[VX] = suf->visOffset[VX] + segOffset; texOffset[VY] = 0; return true; } } } break; } return false; } /** * Renders wall sections for given two-sided seg. */ static boolean Rend_RenderWallSeg(subsector_t* ssec, seg_t* seg) { int pid = viewPlayer - ddPlayers; float bottom, top, texOffset[2]; sector_t* frontSec, *backSec; sidedef_t* frontSide, *backSide; plane_t* ffloor, *fceil, *bfloor, *bceil; linedef_t* line; int solidSeg = false; frontSide = SEG_SIDEDEF(seg); backSide = SEG_SIDEDEF(seg->backSeg); frontSec = frontSide->sector; backSec = backSide->sector; line = seg->lineDef; if(!line->mapped[pid]) { line->mapped[pid] = true; // This line is now seen in the map. // Send a status report. if(gx.HandleMapObjectStatusReport) gx.HandleMapObjectStatusReport(DMUSC_LINE_FIRSTRENDERED, GET_LINE_IDX(line), DMU_LINEDEF, &pid); } if(backSec == frontSec && !frontSide->SW_topmaterial && !frontSide->SW_bottommaterial && !frontSide->SW_middlematerial) return false; // Ugh... an obvious wall seg hack. Best take no chances... ffloor = ssec->sector->SP_plane(PLN_FLOOR); fceil = ssec->sector->SP_plane(PLN_CEILING); bfloor = backSec->SP_plane(PLN_FLOOR); bceil = backSec->SP_plane(PLN_CEILING); if((frontSide->SW_middleinflags & SUIF_PVIS) || (frontSide->SW_topinflags & SUIF_PVIS) || (frontSide->SW_bottominflags & SUIF_PVIS)) Rend_RadioUpdateLinedef(seg->lineDef, seg->side); /** * Create the wall sections. * * We may need multiple wall sections. * Determine which parts of the segment are really visible. */ // Middle section. if(frontSide->SW_middleinflags & SUIF_PVIS) { surface_t* suf = &frontSide->SW_middlesurface; if(R_FindBottomTop(SEG_MIDDLE, seg->offset, suf, ffloor, fceil, bfloor, bceil, (line->flags & DDLF_DONTPEGBOTTOM)? true : false, (line->flags & DDLF_DONTPEGTOP)? true : false, (frontSide->flags & SDF_MIDDLE_STRETCH)? true : false, LINE_SELFREF(line)? true : false, &bottom, &top, texOffset)) { solidSeg = rendSegSection(ssec, seg, SEG_MIDDLE, suf, &seg->SG_v1->v, &seg->SG_v2->v, bottom, top, texOffset, frontSec, (((viewPlayer->shared.flags & (DDPF_NOCLIP|DDPF_CAMERA)) || !(line->flags & DDLF_BLOCKING))? true : false), true, frontSide->flags); if(solidSeg) { float xbottom, xtop; surface_t* suf = &frontSide->SW_middlesurface; if(LINE_SELFREF(line)) { xbottom = MIN_OF(bfloor->visHeight, ffloor->visHeight); xtop = MAX_OF(bceil->visHeight, fceil->visHeight); } else { xbottom = MAX_OF(bfloor->visHeight, ffloor->visHeight); xtop = MIN_OF(bceil->visHeight, fceil->visHeight); } xbottom += suf->visOffset[VY]; xtop += suf->visOffset[VY]; // Can we make this a solid segment? if(!(top >= xtop && bottom <= xbottom)) solidSeg = false; } } } // Upper section. if(frontSide->SW_topinflags & SUIF_PVIS) { surface_t* suf = &frontSide->SW_topsurface; if(R_FindBottomTop(SEG_TOP, seg->offset, suf, ffloor, fceil, bfloor, bceil, (line->flags & DDLF_DONTPEGBOTTOM)? true : false, (line->flags & DDLF_DONTPEGTOP)? true : false, (frontSide->flags & SDF_MIDDLE_STRETCH)? true : false, LINE_SELFREF(line)? true : false, &bottom, &top, texOffset)) { rendSegSection(ssec, seg, SEG_TOP, suf, &seg->SG_v1->v, &seg->SG_v2->v, bottom, top, texOffset, frontSec, false, true, frontSide->flags); } } // Lower section. if(frontSide->SW_bottominflags & SUIF_PVIS) { surface_t* suf = &frontSide->SW_bottomsurface; if(R_FindBottomTop(SEG_BOTTOM, seg->offset, suf, ffloor, fceil, bfloor, bceil, (line->flags & DDLF_DONTPEGBOTTOM)? true : false, (line->flags & DDLF_DONTPEGTOP)? true : false, (frontSide->flags & SDF_MIDDLE_STRETCH)? true : false, LINE_SELFREF(line)? true : false, &bottom, &top, texOffset)) { rendSegSection(ssec, seg, SEG_BOTTOM, suf, &seg->SG_v1->v, &seg->SG_v2->v, bottom, top, texOffset, frontSec, false, true, frontSide->flags); } } // Can we make this a solid segment in the clipper? if(solidSeg == -1) return false; // NEVER (we have a hole we couldn't fix). if(line->L_frontside && line->L_backside && line->L_frontsector == line->L_backsector) return false; if(!solidSeg) // We'll have to determine whether we can... { if(backSec == frontSec) { // An obvious hack, what to do though?? } else if((bceil->visHeight <= ffloor->visHeight && ((frontSide->SW_topmaterial /* && !(frontSide->flags & SDF_MIDTEXUPPER)*/) || (frontSide->SW_middlematerial))) || (bfloor->visHeight >= fceil->visHeight && (frontSide->SW_bottommaterial || frontSide->SW_middlematerial))) { // A closed gap. solidSeg = true; } else if((seg->frameFlags & SEGINF_BACKSECSKYFIX) || (!(bceil->visHeight - bfloor->visHeight > 0) && bfloor->visHeight > ffloor->visHeight && bceil->visHeight < fceil->visHeight && (frontSide->SW_topmaterial /*&& !(frontSide->flags & SDF_MIDTEXUPPER)*/) && (frontSide->SW_bottommaterial))) { // A zero height back segment solidSeg = true; } } if(solidSeg && !P_IsInVoid(viewPlayer)) return true; return false; } float Rend_SectorLight(sector_t *sec) { if(levelFullBright) return 1.0f; return sec->lightLevel; } static void Rend_MarkSegsFacingFront(subsector_t *sub) { uint i; seg_t *seg, **ptr; ptr = sub->segs; while(*ptr) { seg = *ptr; // Occlusions can only happen where two sectors contact. if(seg->lineDef && !(seg->flags & SEGF_POLYOBJ)) { seg->frameFlags &= ~SEGINF_BACKSECSKYFIX; // Which way should it be facing? if(!(segFacingViewerDot(seg->SG_v1pos, seg->SG_v2pos) < 0)) seg->frameFlags |= SEGINF_FACINGFRONT; else seg->frameFlags &= ~SEGINF_FACINGFRONT; Rend_MarkSegSectionsPVisible(seg); } *ptr++; } if(sub->polyObj) { for(i = 0; i < sub->polyObj->numSegs; ++i) { seg = sub->polyObj->segs[i]; seg->frameFlags &= ~SEGINF_BACKSECSKYFIX; // Which way should it be facing? if(!(segFacingViewerDot(seg->SG_v1pos, seg->SG_v2pos) < 0)) seg->frameFlags |= SEGINF_FACINGFRONT; else seg->frameFlags &= ~SEGINF_FACINGFRONT; Rend_MarkSegSectionsPVisible(seg); } } } static void occludeFrontFacingSegsInSubsector(const subsector_t* ssec) { seg_t** ptr; ptr = ssec->segs; while(*ptr) { seg_t* seg = *ptr; if((seg->frameFlags & SEGINF_FACINGFRONT) && seg->lineDef && !(seg->flags & SEGF_POLYOBJ)) { if(!C_CheckViewRelSeg(seg->SG_v1pos[VX], seg->SG_v1pos[VY], seg->SG_v2pos[VX], seg->SG_v2pos[VY])) seg->frameFlags &= ~SEGINF_FACINGFRONT; } *ptr++; } if(ssec->polyObj) { uint i; for(i = 0; i < ssec->polyObj->numSegs; ++i) { seg_t* seg = ssec->polyObj->segs[i]; if(seg->frameFlags & SEGINF_FACINGFRONT) { if(!C_CheckViewRelSeg(seg->SG_v1pos[VX], seg->SG_v1pos[VY], seg->SG_v2pos[VX], seg->SG_v2pos[VY])) seg->frameFlags &= ~SEGINF_FACINGFRONT; } } } } static void prepareSkyMaskPoly(rvertex_t verts[4], rtexcoord_t coords[4], rtexmapunit_t rTU[NUM_TEXMAP_UNITS], float wallLength, material_t* mat) { material_snapshot_t ms; vec3_t texOrigin[2]; // In devRendSkyMode mode we render all polys destined for the skymask as // regular world polys (with a few obvious properties). Material_Prepare(&ms, mat, true, NULL); rTU[TU_PRIMARY].tex = ms.units[MTU_PRIMARY].texInst->id; rTU[TU_PRIMARY].magMode = ms.units[MTU_PRIMARY].magMode; rTU[TU_PRIMARY].scale[0] = ms.units[MTU_PRIMARY].scale[0]; rTU[TU_PRIMARY].scale[1] = ms.units[MTU_PRIMARY].scale[1]; rTU[TU_PRIMARY].offset[0] = ms.units[MTU_PRIMARY].offset[0]; rTU[TU_PRIMARY].offset[1] = ms.units[MTU_PRIMARY].offset[1]; rTU[TU_PRIMARY].blend = ms.units[MTU_PRIMARY].alpha; rTU[TU_PRIMARY].blendMode = ms.units[MTU_PRIMARY].blendMode; // Top left. V3_Set(texOrigin[0], verts[1].pos[VX], verts[1].pos[VY], verts[1].pos[VZ]); // Bottom right. V3_Set(texOrigin[1], verts[2].pos[VX], verts[2].pos[VY], verts[2].pos[VZ]); quadTexCoords(coords, verts, wallLength, texOrigin[0]); } static void Rend_SSectSkyFixes(subsector_t *ssec) { float ffloor, fceil, bfloor, bceil, bsh; rvertex_t rvertices[4]; rcolor_t rcolors[4]; rtexcoord_t rtexcoords[4]; rtexmapunit_t rTU[NUM_TEXMAP_UNITS]; float* vBL, *vBR, *vTL, *vTR; sector_t* frontsec, *backsec; uint j, num; seg_t* seg, **list; sidedef_t* side; // Init the poly. memset(rTU, 0, sizeof(rTU)); if(devRendSkyMode) { uint i; rtexcoords[0].st[0] = 0; rtexcoords[0].st[1] = 1; rtexcoords[1].st[0] = 0; rtexcoords[1].st[1] = 0; rtexcoords[2].st[0] = 1; rtexcoords[2].st[1] = 1; rtexcoords[3].st[0] = 1; rtexcoords[3].st[1] = 0; for(i = 0; i < 4; ++i) rcolors[i].rgba[CR] = rcolors[i].rgba[CG] = rcolors[i].rgba[CB] = rcolors[i].rgba[CA] = 1; } vBL = rvertices[0].pos; vBR = rvertices[2].pos; vTL = rvertices[1].pos; vTR = rvertices[3].pos; num = ssec->segCount; list = ssec->segs; for(j = 0; j < num; ++j) { seg = list[j]; if(!seg->lineDef) // "minisegs" have no linedefs. continue; // Let's first check which way this seg is facing. if(!(seg->frameFlags & SEGINF_FACINGFRONT)) continue; side = SEG_SIDEDEF(seg); if(!side) continue; backsec = seg->SG_backsector; frontsec = seg->SG_frontsector; if(backsec == frontsec && !side->SW_topmaterial && !side->SW_bottommaterial && !side->SW_middlematerial) continue; // Ugh... an obvious wall seg hack. Best take no chances... ffloor = frontsec->SP_floorvisheight; fceil = frontsec->SP_ceilvisheight; if(backsec) { bceil = backsec->SP_ceilvisheight; bfloor = backsec->SP_floorvisheight; bsh = bceil - bfloor; } else bsh = bceil = bfloor = 0; // Get the start and end vertices, left then right. Top and bottom. vBL[VX] = vTL[VX] = seg->SG_v1pos[VX]; vBL[VY] = vTL[VY] = seg->SG_v1pos[VY]; vBR[VX] = vTR[VX] = seg->SG_v2pos[VX]; vBR[VY] = vTR[VY] = seg->SG_v2pos[VY]; // Upper/lower normal skyfixes. if(!backsec || backsec != seg->SG_frontsector) { // Floor. if(R_IsSkySurface(&frontsec->SP_floorsurface) && !(backsec && R_IsSkySurface(&backsec->SP_floorsurface)) && ffloor > skyFix[PLN_FLOOR].height) { vTL[VZ] = vTR[VZ] = ffloor; vBL[VZ] = vBR[VZ] = skyFix[PLN_FLOOR].height; if(devRendSkyMode) prepareSkyMaskPoly(rvertices, rtexcoords, rTU, seg->length, frontsec->SP_floormaterial); RL_AddPoly(PT_TRIANGLE_STRIP, (devRendSkyMode? RPT_NORMAL : RPT_SKY_MASK), rvertices, rtexcoords, NULL, NULL, rcolors, 4, 0, 0, NULL, rTU); } // Ceiling. if(R_IsSkySurface(&frontsec->SP_ceilsurface) && !(backsec && R_IsSkySurface(&backsec->SP_ceilsurface)) && fceil < skyFix[PLN_CEILING].height) { vTL[VZ] = vTR[VZ] = skyFix[PLN_CEILING].height; vBL[VZ] = vBR[VZ] = fceil; if(devRendSkyMode) prepareSkyMaskPoly(rvertices, rtexcoords, rTU, seg->length, frontsec->SP_ceilmaterial); RL_AddPoly(PT_TRIANGLE_STRIP, (devRendSkyMode? RPT_NORMAL : RPT_SKY_MASK), rvertices, rtexcoords, NULL, NULL, rcolors, 4, 0, 0, NULL, rTU); } } // Upper/lower zero height backsec skyfixes. if(backsec && bsh <= 0) { // Floor. if(R_IsSkySurface(&frontsec->SP_floorsurface) && R_IsSkySurface(&backsec->SP_floorsurface)) { if(bfloor > skyFix[PLN_FLOOR].height) { vTL[VZ] = vTR[VZ] = bfloor; vBL[VZ] = vBR[VZ] = skyFix[PLN_FLOOR].height; if(devRendSkyMode) prepareSkyMaskPoly(rvertices, rtexcoords, rTU, seg->length, frontsec->SP_floormaterial); RL_AddPoly(PT_TRIANGLE_STRIP, (devRendSkyMode? RPT_NORMAL : RPT_SKY_MASK), rvertices, rtexcoords, NULL, NULL, rcolors, 4, 0, 0, NULL, rTU); } // Ensure we add a solid view seg. seg->frameFlags |= SEGINF_BACKSECSKYFIX; } // Ceiling. if(R_IsSkySurface(&frontsec->SP_ceilsurface) && R_IsSkySurface(&backsec->SP_ceilsurface)) { if(bceil < skyFix[PLN_CEILING].height) { vTL[VZ] = vTR[VZ] = skyFix[PLN_CEILING].height; vBL[VZ] = vBR[VZ] = bceil; if(devRendSkyMode) prepareSkyMaskPoly(rvertices, rtexcoords, rTU, seg->length, frontsec->SP_ceilmaterial); RL_AddPoly(PT_TRIANGLE_STRIP, (devRendSkyMode? RPT_NORMAL : RPT_SKY_MASK), rvertices, rtexcoords, NULL, NULL, rcolors, 4, 0, 0, NULL, rTU); } // Ensure we add a solid view seg. seg->frameFlags |= SEGINF_BACKSECSKYFIX; } } } } /** * Creates new occlusion planes from the subsector's sides. * Before testing, occlude subsector's backfaces. After testing occlude * the remaining faces, i.e. the forward facing segs. This is done before * rendering segs, so solid segments cut out all unnecessary oranges. */ static void occludeSubsector(const subsector_t* sub, boolean forwardFacing) { float fronth[2], backh[2]; float* startv, *endv; sector_t* front = sub->sector, *back; seg_t* seg, **ptr; if(devNoCulling || P_IsInVoid(viewPlayer)) return; fronth[0] = front->SP_floorheight; fronth[1] = front->SP_ceilheight; ptr = sub->segs; while(*ptr) { seg = *ptr; // Occlusions can only happen where two sectors contact. if(seg->lineDef && seg->SG_backsector && !(seg->flags & SEGF_POLYOBJ) && // Polyobjects don't occlude. (forwardFacing == ((seg->frameFlags & SEGINF_FACINGFRONT)? true : false))) { back = seg->SG_backsector; backh[0] = back->SP_floorheight; backh[1] = back->SP_ceilheight; // Choose start and end vertices so that it's facing forward. if(forwardFacing) { startv = seg->SG_v1pos; endv = seg->SG_v2pos; } else { startv = seg->SG_v2pos; endv = seg->SG_v1pos; } // Do not create an occlusion for sky floors. if(!R_IsSkySurface(&back->SP_floorsurface) || !R_IsSkySurface(&front->SP_floorsurface)) { // Do the floors create an occlusion? if((backh[0] > fronth[0] && vy <= backh[0]) || (backh[0] < fronth[0] && vy >= fronth[0])) { // Occlude down. C_AddViewRelOcclusion(startv, endv, MAX_OF(fronth[0], backh[0]), false); } } // Do not create an occlusion for sky ceilings. if(!R_IsSkySurface(&back->SP_ceilsurface) || !R_IsSkySurface(&front->SP_ceilsurface)) { // Do the ceilings create an occlusion? if((backh[1] < fronth[1] && vy >= backh[1]) || (backh[1] > fronth[1] && vy <= fronth[1])) { // Occlude up. C_AddViewRelOcclusion(startv, endv, MIN_OF(fronth[1], backh[1]), true); } } } *ptr++; } } static void Rend_RenderSubsector(uint ssecidx) { uint i; subsector_t* ssec = SUBSECTOR_PTR(ssecidx); seg_t* seg, **ptr; sector_t* sect; float sceil, sfloor; if(!ssec->sector) { // An orphan subsector. return; } sect = ssec->sector; sceil = sect->SP_ceilvisheight; sfloor = sect->SP_floorvisheight; if(sceil - sfloor <= 0 || ssec->segCount < 3) { // Skip this, it has no volume. // Neighbors handle adding the solid clipper segments. return; } if(!firstsubsector) { if(!C_CheckSubsector(ssec)) return; // This isn't visible. } else { firstsubsector = false; } // Mark the sector visible for this frame. sect->frameFlags |= SIF_VISIBLE; // Retrieve the sector light color. sLightColor = R_GetSectorLightColor(sect); Rend_MarkSegsFacingFront(ssec); R_InitForSubsector(ssec); Rend_RadioSubsectorEdges(ssec); occludeSubsector(ssec, false); LO_ClipInSubsector(ssecidx); occludeSubsector(ssec, true); occludeFrontFacingSegsInSubsector(ssec); if(ssec->polyObj) { // Polyobjs don't obstruct, do clip lights with another algorithm. LO_ClipInSubsectorBySight(ssecidx); } // Mark the particle generators in the sector visible. Rend_ParticleMarkInSectorVisible(sect); /** * Sprites for this subsector have to be drawn. * @note * Must be done BEFORE the segments of this subsector are added to the * clipper. Otherwise the sprites would get clipped by them, and that * wouldn't be right. * Must be done AFTER the lumobjs have been clipped as this affects the * projection of flares. */ R_AddSprites(ssec); // Draw the various skyfixes for all front facing segs in this ssec // (includes polyobject segs). if(ssec->sector->planeCount > 0) { boolean doSkyFixes; doSkyFixes = false; i = 0; do { if(R_IsSkySurface(&ssec->sector->SP_planesurface(i))) doSkyFixes = true; else i++; } while(!doSkyFixes && i < ssec->sector->planeCount); if(doSkyFixes) Rend_SSectSkyFixes(ssec); } // Draw the walls. ptr = ssec->segs; while(*ptr) { seg = *ptr; if(!(seg->flags & SEGF_POLYOBJ) &&// Not handled here. seg->lineDef && // "minisegs" have no linedefs. (seg->frameFlags & SEGINF_FACINGFRONT)) { boolean solid; if(!seg->SG_backsector || !seg->SG_frontsector) solid = Rend_RenderSSWallSeg(ssec, seg); else solid = Rend_RenderWallSeg(ssec, seg); if(solid) { if(seg->lineDef->buildData.index -1 == 291) solid = false; if(seg->lineDef->buildData.index -1 == 302) solid = false; C_AddViewRelSeg(seg->SG_v1pos[VX], seg->SG_v1pos[VY], seg->SG_v2pos[VX], seg->SG_v2pos[VY]); } } *ptr++; } // Is there a polyobj on board? if(ssec->polyObj) { for(i = 0; i < ssec->polyObj->numSegs; ++i) { seg = ssec->polyObj->segs[i]; // Let's first check which way this seg is facing. if(seg->frameFlags & SEGINF_FACINGFRONT) { boolean solid = Rend_RenderSSWallSeg(ssec, seg); if(solid) { C_AddViewRelSeg(seg->SG_v1pos[VX], seg->SG_v1pos[VY], seg->SG_v2pos[VX], seg->SG_v2pos[VY]); } } } } // Render all planes of this sector. for(i = 0; i < sect->planeCount; ++i) { int texMode; float height, texOffset[2], texScale[2]; const plane_t* plane = sect->planes[i]; const surface_t* suf = &plane->surface; material_t* mat; boolean isGlowing = false; // Determine plane height. if(!R_IsSkySurface(suf)) { height = plane->visHeight; } else { // We don't render planes for unclosed sectors when the polys would // be added to the skymask (a DOOM.EXE renderer hack). if(sect->flags & SECF_UNCLOSED) return; if(plane->type != PLN_MID) height = skyFix[plane->type].height; else height = plane->visHeight; } if(renderTextures == 2) texMode = 2; else if(!suf->material || (devNoTexFix && (suf->inFlags & SUIF_MATERIAL_FIX))) texMode = 1; else texMode = 0; if(texMode == 0) mat = suf->material; else if(texMode == 1) // For debug, render the "missing" texture instead of the texture // chosen for surfaces to fix the HOMs. mat = P_GetMaterial(DDT_MISSING, MN_SYSTEM); else // For lighting debug, render all solid surfaces using the gray texture. mat = P_GetMaterial(DDT_GRAY, MN_SYSTEM); V2_Copy(texOffset, suf->visOffset); // Add the Y offset to orient the Y flipped texture. if(plane->type == PLN_CEILING) texOffset[VY] -= ssec->bBox[1].pos[VY] - ssec->bBox[0].pos[VY]; // Add the additional offset to align with the worldwide grid. texOffset[VX] += ssec->worldGridOffset[VX]; texOffset[VY] += ssec->worldGridOffset[VY]; texScale[VX] = ((suf->flags & DDSUF_MATERIAL_FLIPH)? -1 : 1); texScale[VY] = ((suf->flags & DDSUF_MATERIAL_FLIPV)? -1 : 1); if(glowingTextures && (texMode == 1 || ((suf->flags & DDSUF_GLOW) || (mat && (mat->flags & MATF_GLOW))))) isGlowing = true; Rend_RenderPlane(ssec, plane->type, height, suf->normal, mat, suf->inFlags, suf->rgba, suf->blendMode, texOffset, texScale, R_IsSkySurface(suf), true, isGlowing, ssec->bsuf[plane->planeID], plane->planeID, texMode); } if(devRendSkyMode == 2) { /** * In devSky mode 2, we draw additional geometry, showing the * real "physical" height of any sky masked planes that are * drawn at a different height due to the skyFix. */ if(sect->SP_floorvisheight > skyFix[PLN_FLOOR].height && R_IsSkySurface(§->SP_floorsurface)) { vec3_t normal; const plane_t* plane = sect->SP_plane(PLN_FLOOR); const surface_t* suf = &plane->surface; /** * Flip the plane normal according to the z positon of the * viewer relative to the plane height so that the plane is * always visible. */ V3_Copy(normal, plane->PS_normal); if(vy < plane->visHeight) normal[VZ] *= -1; Rend_RenderPlane(ssec, PLN_MID, plane->visHeight, normal, P_GetMaterial(DDT_GRAY, MN_SYSTEM), suf->inFlags, suf->rgba, BM_NORMAL, NULL, NULL, false, (vy > plane->visHeight? true : false), false, NULL, plane->planeID, 2); } if(sect->SP_ceilvisheight < skyFix[PLN_CEILING].height && R_IsSkySurface(§->SP_ceilsurface)) { vec3_t normal; const plane_t* plane = sect->SP_plane(PLN_CEILING); const surface_t* suf = &plane->surface; V3_Copy(normal, plane->PS_normal); if(vy > plane->visHeight) normal[VZ] *= -1; Rend_RenderPlane(ssec, PLN_MID, plane->visHeight, normal, P_GetMaterial(DDT_GRAY, MN_SYSTEM), suf->inFlags, suf->rgba, BM_NORMAL, NULL, NULL, false, (vy < plane->visHeight? true : false), false, NULL, plane->planeID, 2); } } } static void Rend_RenderNode(uint bspnum) { // If the clipper is full we're pretty much done. This means no geometry // will be visible in the distance because every direction has already been // fully covered by geometry. if(C_IsFull()) return; if(bspnum & NF_SUBSECTOR) { // We've arrived at a subsector. Render it. Rend_RenderSubsector(bspnum & ~NF_SUBSECTOR); } else { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); node_t* bsp; byte side; // Descend deeper into the nodes. bsp = NODE_PTR(bspnum); // Decide which side the view point is on. side = R_PointOnSide(viewData->current.pos[VX], viewData->current.pos[VY], &bsp->partition); Rend_RenderNode(bsp->children[side]); // Recursively divide front space. Rend_RenderNode(bsp->children[side ^ 1]); // ...and back space. } } static void drawNormal(vec3_t origin, vec3_t normal, float scalar) { float black[4] = { 0, 0, 0, 0 }; float red[4] = { 1, 0, 0, 1 }; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(origin[VX], origin[VZ], origin[VY]); glBegin(GL_LINES); { glColor4fv(black); glVertex3f(scalar * normal[VX], scalar * normal[VZ], scalar * normal[VY]); glColor4fv(red); glVertex3f(0, 0, 0); } glEnd(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } /** * Draw the surface normals, primarily for debug. */ void Rend_RenderNormals(void) { #define NORM_TAIL_LENGTH (20) uint i; if(!devSurfaceNormals) return; glDisable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); for(i = 0; i < numSegs; ++i) { seg_t* seg = &segs[i]; sidedef_t* side; surface_t* suf; vec3_t origin; float x, y, bottom, top; float scale = NORM_TAIL_LENGTH; if(!seg->lineDef || !seg->SG_frontsector || (seg->lineDef->inFlags & LF_POLYOBJ)) continue; side = SEG_SIDEDEF(seg); x = seg->SG_v1pos[VX] + (seg->SG_v2pos[VX] - seg->SG_v1pos[VX]) / 2; y = seg->SG_v1pos[VY] + (seg->SG_v2pos[VY] - seg->SG_v1pos[VY]) / 2; if(!seg->SG_backsector) { bottom = side->sector->SP_floorvisheight; top = side->sector->SP_ceilvisheight; suf = &side->SW_middlesurface; V3_Set(origin, x, y, bottom + (top - bottom) / 2); drawNormal(origin, suf->normal, scale); } else { if(side->SW_middlesurface.material) { top = seg->SG_frontsector->SP_ceilvisheight; bottom = seg->SG_frontsector->SP_floorvisheight; suf = &side->SW_middlesurface; V3_Set(origin, x, y, bottom + (top - bottom) / 2); drawNormal(origin, suf->normal, scale); } if(seg->SG_backsector->SP_ceilvisheight < seg->SG_frontsector->SP_ceilvisheight && !(R_IsSkySurface(&seg->SG_frontsector->SP_ceilsurface) && R_IsSkySurface(&seg->SG_backsector->SP_ceilsurface))) { bottom = seg->SG_backsector->SP_ceilvisheight; top = seg->SG_frontsector->SP_ceilvisheight; suf = &side->SW_topsurface; V3_Set(origin, x, y, bottom + (top - bottom) / 2); drawNormal(origin, suf->normal, scale); } if(seg->SG_backsector->SP_floorvisheight > seg->SG_frontsector->SP_floorvisheight && !(R_IsSkySurface(&seg->SG_frontsector->SP_floorsurface) && R_IsSkySurface(&seg->SG_backsector->SP_floorsurface))) { bottom = seg->SG_frontsector->SP_floorvisheight; top = seg->SG_backsector->SP_floorvisheight; suf = &side->SW_bottomsurface; V3_Set(origin, x, y, bottom + (top - bottom) / 2); drawNormal(origin, suf->normal, scale); } } } for(i = 0; i < numSSectors; ++i) { uint j; subsector_t* ssec = &ssectors[i]; for(j = 0; j < ssec->sector->planeCount; ++j) { vec3_t origin; plane_t* pln = ssec->sector->SP_plane(j); float scale = NORM_TAIL_LENGTH; V3_Set(origin, ssec->midPoint.pos[VX], ssec->midPoint.pos[VY], pln->visHeight); if(pln->type != PLN_MID && R_IsSkySurface(&pln->surface)) origin[VZ] = skyFix[pln->type].height; drawNormal(origin, pln->PS_normal, scale); } } glEnable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); #undef NORM_TAIL_LENGTH } static void getVertexPlaneMinMax(const vertex_t* vtx, float* min, float* max) { lineowner_t* vo, *base; if(!vtx || (!min && !max)) return; // Wha? vo = base = vtx->lineOwners; do { linedef_t* li = vo->lineDef; if(li->L_frontside) { if(min && li->L_frontsector->SP_floorvisheight < *min) *min = li->L_frontsector->SP_floorvisheight; if(max && li->L_frontsector->SP_ceilvisheight > *max) *max = li->L_frontsector->SP_ceilvisheight; } if(li->L_backside) { if(min && li->L_backsector->SP_floorvisheight < *min) *min = li->L_backsector->SP_floorvisheight; if(max && li->L_backsector->SP_ceilvisheight > *max) *max = li->L_backsector->SP_ceilvisheight; } vo = vo->LO_next; } while(vo != base); } static void drawVertexPoint(const vertex_t* vtx, float z, float alpha) { glBegin(GL_POINTS); glColor4f(.7f, .7f, .2f, alpha * 2); glVertex3f(vtx->V_pos[VX], z, vtx->V_pos[VY]); glEnd(); } static void drawVertexBar(const vertex_t* vtx, float bottom, float top, float alpha) { #define EXTEND_DIST 64 static const float black[4] = { 0, 0, 0, 0 }; glBegin(GL_LINES); glColor4fv(black); glVertex3f(vtx->V_pos[VX], bottom - EXTEND_DIST, vtx->V_pos[VY]); glColor4f(1, 1, 1, alpha); glVertex3f(vtx->V_pos[VX], bottom, vtx->V_pos[VY]); glVertex3f(vtx->V_pos[VX], bottom, vtx->V_pos[VY]); glVertex3f(vtx->V_pos[VX], top, vtx->V_pos[VY]); glVertex3f(vtx->V_pos[VX], top, vtx->V_pos[VY]); glColor4fv(black); glVertex3f(vtx->V_pos[VX], top + EXTEND_DIST, vtx->V_pos[VY]); glEnd(); #undef EXTEND_DIST } static void drawVertexIndex(const vertex_t* vtx, float z, float scale, float alpha) { char buf[80]; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(vtx->V_pos[VX], z, vtx->V_pos[VY]); glRotatef(-vang + 180, 0, 1, 0); glRotatef(vpitch, 1, 0, 0); glScalef(-scale, -scale, 1); sprintf(buf, "%lu", (unsigned long) (vtx - vertexes)); UI_TextOutEx(buf, 2, 2, false, false, UI_Color(UIC_TITLE), alpha); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } #define MAX_VERTEX_POINT_DIST 1280 static boolean drawVertex1(linedef_t* li, void* context) { vertex_t* vtx = li->L_v1; polyobj_t* po = context; float dist2D = M_ApproxDistancef(vx - vtx->V_pos[VX], vz - vtx->V_pos[VY]); if(dist2D < MAX_VERTEX_POINT_DIST) { float alpha = 1 - dist2D / MAX_VERTEX_POINT_DIST; if(alpha > 0) { float bottom = po->subsector->sector->SP_floorvisheight; float top = po->subsector->sector->SP_ceilvisheight; glDisable(GL_TEXTURE_2D); if(devVertexBars) drawVertexBar(vtx, bottom, top, MIN_OF(alpha, .15f)); drawVertexPoint(vtx, bottom, alpha * 2); glEnable(GL_TEXTURE_2D); } } if(devVertexIndices) { float eye[3], pos[3], dist3D; eye[VX] = vx; eye[VY] = vz; eye[VZ] = vy; pos[VX] = vtx->V_pos[VX]; pos[VY] = vtx->V_pos[VY]; pos[VZ] = po->subsector->sector->SP_floorvisheight; dist3D = M_Distance(pos, eye); if(dist3D < MAX_VERTEX_POINT_DIST) { drawVertexIndex(vtx, pos[VZ], dist3D / (theWindow->width / 2), 1 - dist3D / MAX_VERTEX_POINT_DIST); } } return true; // Continue iteration. } boolean drawPolyObjVertexes(polyobj_t* po, void* context) { return P_PolyobjLinesIterator(po, drawVertex1, po); } /** * Draw the various vertex debug aids. */ void Rend_Vertexes(void) { uint i; float oldPointSize, oldLineWidth = 1, bbox[4]; if(!devVertexBars && !devVertexIndices) return; glDisable(GL_DEPTH_TEST); if(devVertexBars) { glEnable(GL_LINE_SMOOTH); oldLineWidth = DGL_GetFloat(DGL_LINE_WIDTH); DGL_SetFloat(DGL_LINE_WIDTH, 2); glDisable(GL_TEXTURE_2D); for(i = 0; i < numVertexes; ++i) { vertex_t* vtx = &vertexes[i]; float alpha; if(!vtx->lineOwners) continue; // Not a linedef vertex. if(vtx->lineOwners[0].lineDef->inFlags & LF_POLYOBJ) continue; // A polyobj linedef vertex. alpha = 1 - M_ApproxDistancef(vx - vtx->V_pos[VX], vz - vtx->V_pos[VY]) / MAX_VERTEX_POINT_DIST; alpha = MIN_OF(alpha, .15f); if(alpha > 0) { float bottom, top; bottom = DDMAXFLOAT; top = DDMINFLOAT; getVertexPlaneMinMax(vtx, &bottom, &top); drawVertexBar(vtx, bottom, top, alpha); } } glEnable(GL_TEXTURE_2D); } // Always draw the vertex point nodes. glEnable(GL_POINT_SMOOTH); oldPointSize = DGL_GetFloat(DGL_POINT_SIZE); DGL_SetFloat(DGL_POINT_SIZE, 6); glDisable(GL_TEXTURE_2D); for(i = 0; i < numVertexes; ++i) { vertex_t* vtx = &vertexes[i]; float dist; if(!vtx->lineOwners) continue; // Not a linedef vertex. if(vtx->lineOwners[0].lineDef->inFlags & LF_POLYOBJ) continue; // A polyobj linedef vertex. dist = M_ApproxDistancef(vx - vtx->V_pos[VX], vz - vtx->V_pos[VY]); if(dist < MAX_VERTEX_POINT_DIST) { float bottom; bottom = DDMAXFLOAT; getVertexPlaneMinMax(vtx, &bottom, NULL); drawVertexPoint(vtx, bottom, (1 - dist / MAX_VERTEX_POINT_DIST) * 2); } } glEnable(GL_TEXTURE_2D); if(devVertexIndices) { float eye[3]; eye[VX] = vx; eye[VY] = vz; eye[VZ] = vy; for(i = 0; i < numVertexes; ++i) { vertex_t* vtx = &vertexes[i]; float pos[3], dist; if(!vtx->lineOwners) continue; // Not a linedef vertex. if(vtx->lineOwners[0].lineDef->inFlags & LF_POLYOBJ) continue; // A polyobj linedef vertex. pos[VX] = vtx->V_pos[VX]; pos[VY] = vtx->V_pos[VY]; pos[VZ] = DDMAXFLOAT; getVertexPlaneMinMax(vtx, &pos[VZ], NULL); dist = M_Distance(pos, eye); if(dist < MAX_VERTEX_POINT_DIST) { float alpha, scale; alpha = 1 - dist / MAX_VERTEX_POINT_DIST; scale = dist / (theWindow->width / 2); drawVertexIndex(vtx, pos[VZ], scale, alpha); } } } // Next, the vertexes of all nearby polyobjs. bbox[BOXLEFT] = vx - MAX_VERTEX_POINT_DIST; bbox[BOXRIGHT] = vx + MAX_VERTEX_POINT_DIST; bbox[BOXBOTTOM] = vy - MAX_VERTEX_POINT_DIST; bbox[BOXTOP] = vy + MAX_VERTEX_POINT_DIST; P_PolyobjsBoxIterator(bbox, drawPolyObjVertexes, NULL); // Restore previous state. if(devVertexBars) { DGL_SetFloat(DGL_LINE_WIDTH, oldLineWidth); glDisable(GL_LINE_SMOOTH); } DGL_SetFloat(DGL_POINT_SIZE, oldPointSize); glDisable(GL_POINT_SMOOTH); glEnable(GL_DEPTH_TEST); } void Rend_RenderMap(void) { binangle_t viewside; boolean doLums = (useDynLights || haloMode || spriteLight || useDecorations); // Set to true if dynlights are inited for this frame. loInited = false; GL_SetMultisample(true); // Setup the modelview matrix. Rend_ModelViewMatrix(true); if(!freezeRLs) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); // Prepare for rendering. RL_ClearLists(); // Clear the lists for new quads. C_ClearRanges(); // Clear the clipper. // Make vissprites of all the visible decorations. Rend_ProjectDecorations(); LO_BeginFrame(); // Clear particle generator visibilty info. Rend_ParticleInitForNewFrame(); // Recycle the vlight lists. Currently done here as the lists are // not shared by all viewports. VL_InitForNewFrame(); if(doLums) { /** * Clear the projected dynlight lists. This is done here as * the projections are sensitive to distance from the viewer * (e.g. some may fade out when far away). */ DL_InitForNewFrame(); } // Add the backside clipping range (if vpitch allows). if(vpitch <= 90 - yfov / 2 && vpitch >= -90 + yfov / 2) { float a = fabs(vpitch) / (90 - yfov / 2); binangle_t startAngle = (binangle_t) (BANG_45 * fieldOfView / 90) * (1 + a); binangle_t angLen = BANG_180 - startAngle; viewside = (viewData->current.angle >> (32 - BAMS_BITS)) + startAngle; C_SafeAddRange(viewside, viewside + angLen); C_SafeAddRange(viewside + angLen, viewside + 2 * angLen); } // The viewside line for the depth cue. viewsidex = -viewData->viewSin; viewsidey = viewData->viewCos; // We don't want subsector clipchecking for the first subsector. firstsubsector = true; Rend_RenderNode(numNodes - 1); Rend_RenderShadows(); } RL_RenderAllLists(); // Draw various debugging displays: Rend_RenderNormals(); // World surface normals. LO_DrawLumobjs(); // Lumobjs. Rend_RenderBoundingBoxes(); // Mobj bounding boxes. Rend_Vertexes(); // World vertex positions/indices. Rend_RenderGenerators(); // Particle generator origins. // Draw the Source Bias Editor's draw that identifies the current light. SBE_DrawCursor(); GL_SetMultisample(false); } /** * Updates the lightModRange which is used to applify sector light to help * compensate for the differences between the OpenGL lighting equation, * the software Doom lighting model and the light grid (ambient lighting). * * The offsets in the lightRangeModTables are added to the sector->lightLevel * during rendering (both positive and negative). */ void Rend_CalcLightModRange(cvar_t *unused) { int j; int mapAmbient; float f; gamemap_t *map = P_GetCurrentMap(); memset(lightModRange, 0, sizeof(float) * 255); mapAmbient = P_GetMapAmbientLightLevel(map); if(mapAmbient > ambientLight) rAmbient = mapAmbient; else rAmbient = ambientLight; for(j = 0; j < 255; ++j) { // Adjust the white point/dark point? f = 0; if(lightRangeCompression != 0) { if(lightRangeCompression >= 0) // Brighten dark areas. f = (float) (255 - j) * lightRangeCompression; else // Darken bright areas. f = (float) -j * -lightRangeCompression; } // Lower than the ambient limit? if(rAmbient != 0 && j+f <= rAmbient) f = rAmbient - j; // Clamp the result as a modifier to the light value (j). if((j+f) >= 255) f = 255 - j; else if((j+f) <= 0) f = -j; // Insert it into the matrix lightModRange[j] = f / 255.0f; } } /** * Applies the offset from the lightModRangeto the given light value. * * The lightModRange is used to implement (precalculated) ambient light * limit, light range compression and light range shift. * * \note There is no need to clamp the result. Since the offset values in * the lightModRange have already been clamped so that the resultant * lightvalue is NEVER outside the range 0-254 when the original * lightvalue is used as the index. * * @param lightvar Ptr to the value to apply the adaptation to. */ void Rend_ApplyLightAdaptation(float *lightvar) { int lightval; if(lightvar == NULL) return; // Can't apply adaptation to a NULL val ptr... lightval = ROUND(255.0f * *lightvar); if(lightval > 254) lightval = 254; else if(lightval < 0) lightval = 0; *lightvar += lightModRange[lightval]; } /** * Same as above but instead of applying light adaptation to the var directly * it returns the light adaptation value for the passed light value. * * @param lightvalue Light value to look up the adaptation value of. * @return int Adaptation value for the passed light value. */ float Rend_GetLightAdaptVal(float lightvalue) { int lightval; lightval = ROUND(255.0f * lightvalue); if(lightval > 254) lightval = 254; else if(lightval < 0) lightval = 0; return lightModRange[lightval]; } /** * Draws the lightModRange (for debug) */ void R_DrawLightRange(void) { #define bWidth 1.0f #define bHeight (bWidth * 255.0f) #define BORDER 20 int i; float c, off; ui_color_t color; if(!devLightModRange) return; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); glTranslatef(BORDER, BORDER, 0); color.red = 0.2f; color.green = 0; color.blue = 0.6f; glDisable(GL_TEXTURE_2D); // Draw an outside border. glColor4f(1, 1, 0, 1); glBegin(GL_LINES); glVertex2f(-1, -1); glVertex2f(255 + 1, -1); glVertex2f(255 + 1, -1); glVertex2f(255 + 1, bHeight + 1); glVertex2f(255 + 1, bHeight + 1); glVertex2f(-1, bHeight + 1); glVertex2f(-1, bHeight + 1); glVertex2f(-1, -1); glEnd(); glBegin(GL_QUADS); for(i = 0, c = 0; i < 255; ++i, c += (1.0f/255.0f)) { // Get the result of the source light level + offset. off = lightModRange[i]; glColor4f(c + off, c + off, c + off, 1); glVertex2f(i * bWidth, 0); glVertex2f(i * bWidth + bWidth, 0); glVertex2f(i * bWidth + bWidth, bHeight); glVertex2f(i * bWidth, bHeight); } glEnd(); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_PROJECTION); glPopMatrix(); #undef bWidth #undef bHeight #undef BORDER } static DGLuint constructBBox(DGLuint name, float br) { if(GL_NewList(name, GL_COMPILE)) { glBegin(GL_QUADS); { // Top glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f+br, 1.0f,-1.0f-br); // TR glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f-br, 1.0f,-1.0f-br); // TL glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f-br, 1.0f, 1.0f+br); // BL glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f+br, 1.0f, 1.0f+br); // BR // Bottom glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f+br,-1.0f, 1.0f+br); // TR glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f-br,-1.0f, 1.0f+br); // TL glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f-br,-1.0f,-1.0f-br); // BL glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f+br,-1.0f,-1.0f-br); // BR // Front glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f+br, 1.0f+br, 1.0f); // TR glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f-br, 1.0f+br, 1.0f); // TL glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f-br,-1.0f-br, 1.0f); // BL glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f+br,-1.0f-br, 1.0f); // BR // Back glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f+br,-1.0f-br,-1.0f); // TR glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f-br,-1.0f-br,-1.0f); // TL glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f-br, 1.0f+br,-1.0f); // BL glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f+br, 1.0f+br,-1.0f); // BR // Left glTexCoord2f(1.0f, 1.0f); glVertex3f(-1.0f, 1.0f+br, 1.0f+br); // TR glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f+br,-1.0f-br); // TL glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f,-1.0f-br,-1.0f-br); // BL glTexCoord2f(1.0f, 0.0f); glVertex3f(-1.0f,-1.0f-br, 1.0f+br); // BR // Right glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f+br,-1.0f-br); // TR glTexCoord2f(0.0f, 1.0f); glVertex3f( 1.0f, 1.0f+br, 1.0f+br); // TL glTexCoord2f(0.0f, 0.0f); glVertex3f( 1.0f,-1.0f-br, 1.0f+br); // BL glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f,-1.0f-br,-1.0f-br); // BR } glEnd(); return GL_EndList(); } return 0; } /** * Draws a textured cube using the currently bound gl texture. * Used to draw mobj bounding boxes. * * @param pos3f Coordinates of the center of the box (in "world" * coordinates [VX, VY, VZ]). * @param w Width of the box. * @param l Length of the box. * @param h Height of the box. * @param color3f Color to make the box (uniform vertex color). * @param alpha Alpha to make the box (uniform vertex color). * @param br Border amount to overlap box faces. * @param alignToBase If @c true, align the base of the box * to the Z coordinate. */ void Rend_DrawBBox(const float pos3f[3], float w, float l, float h, float a, const float color3f[3], float alpha, float br, boolean alignToBase) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); if(alignToBase) // The Z coordinate is to the bottom of the object. glTranslatef(pos3f[VX], pos3f[VZ] + h, pos3f[VY]); else glTranslatef(pos3f[VX], pos3f[VZ], pos3f[VY]); glRotatef(0, 0, 0, 1); glRotatef(0, 1, 0, 0); glRotatef(a, 0, 1, 0); glScalef(w - br - br, h - br - br, l - br - br); glColor4f(color3f[0], color3f[1], color3f[2], alpha); GL_CallList(dlBBox); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } /** * Draws a textured triangle using the currently bound gl texture. * Used to draw mobj angle direction arrow. * * @param pos3f Coordinates of the center of the base of the * triangle (in "world" coordinates [VX, VY, VZ]). * @param a Angle to point the triangle in. * @param s Scale of the triangle. * @param color3f Color to make the box (uniform vertex color). * @param alpha Alpha to make the box (uniform vertex color). */ void Rend_DrawArrow(const float pos3f[3], float a, float s, const float color3f[3], float alpha) { glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(pos3f[VX], pos3f[VZ], pos3f[VY]); glRotatef(0, 0, 0, 1); glRotatef(0, 1, 0, 0); glRotatef(a, 0, 1, 0); glScalef(s, 0, s); glBegin(GL_TRIANGLES); { glColor4f(0.0f, 0.0f, 0.0f, 0.5f); glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, 1.0f,-1.0f); // L glColor4f(color3f[0], color3f[1], color3f[2], alpha); glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, 1.0f,-1.0f); // Point glColor4f(0.0f, 0.0f, 0.0f, 0.5f); glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 1.0f); // R } glEnd(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } static boolean drawMobjBBox(thinker_t* th, void* context) { static const float red[3] = { 1, 0.2f, 0.2f}; // non-solid objects static const float green[3] = { 0.2f, 1, 0.2f}; // solid objects static const float yellow[3] = {0.7f, 0.7f, 0.2f}; // missiles mobj_t* mo = (mobj_t*) th; float size, alpha, eye[3]; // We don't want the console player. if(mo == ddPlayers[consolePlayer].shared.mo) return true; // Continue iteration. // Is it vissible? if(!(mo->subsector && mo->subsector->sector->frameFlags & SIF_VISIBLE)) return true; // Continue iteration. eye[VX] = vx; eye[VY] = vz; eye[VZ] = vy; alpha = 1 - ((M_Distance(mo->pos, eye)/(theWindow->width/2))/4); if(alpha < .25f) alpha = .25f; // Don't make them totally invisible. // Draw a bounding box in an appropriate color. size = mo->radius; Rend_DrawBBox(mo->pos, size, size, mo->height/2, 0, (mo->ddFlags & DDMF_MISSILE)? yellow : (mo->ddFlags & DDMF_SOLID)? green : red, alpha, .08f, true); Rend_DrawArrow(mo->pos, ((mo->angle + ANG45 + ANG90) / (float) ANGLE_MAX *-360), size*1.25, (mo->ddFlags & DDMF_MISSILE)? yellow : (mo->ddFlags & DDMF_SOLID)? green : red, alpha); return true; // Continue iteration. } /** * Renders bounding boxes for all mobj's (linked in sec->mobjList, except * the console player) in all sectors that are currently marked as vissible. * * Depth test is disabled to show all mobjs that are being rendered, regardless * if they are actually vissible (hidden by previously drawn map geometry). */ static void Rend_RenderBoundingBoxes(void) { static const float red[3] = { 1, 0.2f, 0.2f}; // non-solid objects static const float green[3] = { 0.2f, 1, 0.2f}; // solid objects static const float yellow[3] = {0.7f, 0.7f, 0.2f}; // missiles uint i; float eye[3]; material_t* mat; material_snapshot_t ms; if((!devMobjBBox && !devPolyobjBBox) || netGame) return; if(!dlBBox) dlBBox = constructBBox(0, .08f); eye[VX] = vx; eye[VY] = vz; eye[VZ] = vy; glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); mat = P_GetMaterial(DDT_BBOX, MN_SYSTEM); Material_Prepare(&ms, mat, true, NULL); GL_BindTexture(ms.units[MTU_PRIMARY].texInst->id, ms.units[MTU_PRIMARY].magMode); GL_BlendMode(BM_ADD); if(devMobjBBox) P_IterateThinkers(gx.MobjThinker, 0x1, drawMobjBBox, NULL); if(devPolyobjBBox) for(i = 0; i < numPolyObjs; ++i) { const polyobj_t* po = polyObjs[i]; const sector_t* sec = po->subsector->sector; float width = (po->box[1][0] - po->box[0][0])/2; float length = (po->box[1][1] - po->box[0][1])/2; float height = (sec->SP_ceilheight - sec->SP_floorheight)/2; float pos[3], alpha; pos[VX] = po->box[0][0]+width; pos[VY] = po->box[0][1]+length; pos[VZ] = sec->SP_floorheight; alpha = 1 - ((M_Distance(pos, eye)/(theWindow->width/2))/4); if(alpha < .25f) alpha = .25f; // Don't make them totally invisible. Rend_DrawBBox(pos, width, length, height, 0, yellow, alpha, .08f, true); {uint j; for(j = 0; j < po->numSegs; ++j) { seg_t* seg = po->segs[j]; linedef_t* lineDef = seg->lineDef; float width = (lineDef->bBox[BOXRIGHT] - lineDef->bBox[BOXLEFT])/2; float length = (lineDef->bBox[BOXTOP] - lineDef->bBox[BOXBOTTOM])/2; float pos[3]; /** Draw a bounding box for the lineDef. pos[VX] = lineDef->bBox[BOXLEFT]+width; pos[VY] = lineDef->bBox[BOXBOTTOM]+length; pos[VZ] = sec->SP_floorheight; Rend_DrawBBox(pos, width, length, height, 0, red, alpha, .08f, true); */ pos[VX] = (lineDef->L_v2pos[VX]+lineDef->L_v1pos[VX])/2; pos[VY] = (lineDef->L_v2pos[VY]+lineDef->L_v1pos[VY])/2; pos[VZ] = sec->SP_floorheight; width = 0; length = lineDef->length/2; Rend_DrawBBox(pos, width, length, height, BANG2DEG(BANG_90-lineDef->angle), green, alpha, 0, true); }} } GL_BlendMode(BM_NORMAL); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_particle.c0000644000175000017500000013575711357170242023241 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_particle.c: Particle Generator Management */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_play.h" #include "de_refresh.h" #include "de_audio.h" #include "de_misc.h" #include // MACROS ------------------------------------------------------------------ #define ORDER(x,y,a,b) ( (x)<(y)? ((a)=(x),(b)=(y)) : ((b)=(x),(a)=(y)) ) #define DOT2F(a,b) ( FIX2FLT(a[VX])*FIX2FLT(b[VX]) + FIX2FLT(a[VY])*FIX2FLT(b[VY]) ) #define VECMUL(a,scalar) ( a[VX]=FixedMul(a[VX],scalar), a[VY]=FixedMul(a[VY],scalar) ) #define VECADD(a,b) ( a[VX]+=b[VX], a[VY]+=b[VY] ) #define VECMULADD(a,scal,b) ( a[VX]+=FixedMul(scal, b[VX]), a[VY]+=FixedMul(scal,b[VY]) ) #define VECSUB(a,b) ( a[VX]-=b[VX], a[VY]-=b[VY] ) #define VECCPY(a,b) ( a[VX]=b[VX], a[VY]=b[VY] ) BEGIN_PROF_TIMERS() PROF_PTCGEN_LINK END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- typedef struct pglink_s { struct pglink_s* next; ptcgen_t* gen; } pglink_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void P_PtcGenThinker(ptcgen_t* gen); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void P_Uncertain(fixed_t* pos, fixed_t low, fixed_t high); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- byte useParticles = true; int maxParticles = 0; // Unlimited. float particleSpawnRate = 1; // Unmodified. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static ptcgen_t* activePtcGens[MAX_ACTIVE_PTCGENS]; static pglink_t** pgLinks = NULL; // Array of pointers to pgLinks in pgStore. static pglink_t* pgStore; static unsigned int pgCursor = 0, pgMax; static vec2_t mbox[2]; static fixed_t tmpz, tmprad, tmpx1, tmpx2, tmpy1, tmpy2; static boolean tmcross; static linedef_t* ptcHitLine; // CODE -------------------------------------------------------------------- static void freePtcGen(ptcgen_t* gen) { Z_Free(gen->ptcs); gen->ptcs = NULL; } static void unlinkPtcGen(ptcgen_t* gen) { ptcgenid_t i; for(i = 0; i < MAX_ACTIVE_PTCGENS; ++i) { if(activePtcGens[i] == gen) { activePtcGens[i] = NULL; break; } } } static void linkPtcGen(ptcgenid_t slot, ptcgen_t* gen) { assert(slot < MAX_ACTIVE_PTCGENS); activePtcGens[slot] = gen; } static boolean iterateSectorLinkedPtcGens(sector_t* sector, boolean (*callback) (ptcgen_t*, void*), void* context) { boolean result = true; if(sector) { pglink_t* it = pgLinks[GET_SECTOR_IDX(sector)]; while(it) { if((result = callback(it->gen, context)) == 0) break; it = it->next; } } return result; } static uint findSlotForNewGen(void) { ptcgenid_t i, slot = 0; int maxage = 0; boolean isEmpty = false; // Find a suitable spot in the active ptcgens list. i = 0; do { if(!activePtcGens[i]) { // An empty slot, put it here. slot = i + 1; isEmpty = true; } else if(!(activePtcGens[i]->flags & PGF_STATIC) && (!slot || activePtcGens[i]->age > maxage)) { slot = i + 1; maxage = activePtcGens[i]->age; } } while(!isEmpty && ++i < MAX_ACTIVE_PTCGENS); return slot; } static ptcgen_t* P_PtcGenCreate(void) { ptcgen_t* gen = Z_Calloc(sizeof(ptcgen_t), PU_MAP, 0); // Link the thinker to the list of (private) thinkers. gen->thinker.function = P_PtcGenThinker; P_ThinkerAdd(&gen->thinker, false); return gen; } static void P_PtcGenDestroy(ptcgen_t* gen) { P_ThinkerRemove(&gen->thinker); unlinkPtcGen(gen); freePtcGen(gen); } /** * Allocates a new active ptcgen and adds it to the list of active ptcgens. * * \fixme Linear allocation when in-game is not good... */ static ptcgen_t* P_NewPtcGen(void) { ptcgenid_t slot = findSlotForNewGen(); // Find a suitable slot in the active ptcgens list. if(slot) { ptcgen_t* gen; // If there is already a generator here, destroy it. if(activePtcGens[slot-1]) P_PtcGenDestroy(activePtcGens[slot-1]); // Allocate a new generator. gen = P_PtcGenCreate(); linkPtcGen(slot-1, gen); return gen; } return 0; // Creation failed. } /** * Called once during startup. */ void P_PtcInit(void) { memset(activePtcGens, 0, sizeof(activePtcGens)); } void P_PtcInitForMap(void) { uint startTime = Sys_GetRealTime(); pgLinks = Z_Malloc(sizeof(pglink_t *) * numSectors, PU_MAP, 0); memset(pgLinks, 0, sizeof(pglink_t *) * numSectors); // We can link 64 generators each into four sectors before // running out of pgLinks. pgMax = 4 * MAX_ACTIVE_PTCGENS; pgStore = Z_Malloc(sizeof(pglink_t) * pgMax, PU_MAP, 0); pgCursor = 0; memset(activePtcGens, 0, sizeof(activePtcGens)); // Spawn all type-triggered particle generators. // Let's hope there aren't too many... P_SpawnTypeParticleGens(); P_SpawnMapParticleGens(mapID); // How much time did we spend? VERBOSE(Con_Message ("P_PtcInitForMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } /** * Convert a particle generator id to pointer. * * @return Pointer to ptcgen iff found, ELSE @c NULL. */ const ptcgen_t* P_IndexToPtcGen(ptcgenid_t id) { if(id >= 0 && id < MAX_ACTIVE_PTCGENS) return activePtcGens[id]; return NULL; // Not found!? } /** * Convert a particle generator point to id. * * @return @c -1 iff NOT found, ELSE id of the specifed ptcgen. */ ptcgenid_t P_PtcGenToIndex(const ptcgen_t* gen) { if(gen) { ptcgenid_t i; for(i = 0; i < MAX_ACTIVE_PTCGENS; ++i) { if(activePtcGens[i] == gen) return i; } } return -1; // Not found!? } /** * Returns an unused link from the pgStore. */ static pglink_t* PG_GetLink(void) { if(pgCursor < pgMax) return &pgStore[pgCursor++]; VERBOSE(Con_Message("PG_GetLink: Out of PGen store.\n")); return NULL; } static void PG_LinkPtcGen(ptcgen_t* gen, uint secIDX) { pglink_t* link, *it; // Must check that it isn't already there... for(it = pgLinks[secIDX]; it; it = it->next) if(it->gen == gen) return; // No, no... // We need a new PG link. link = PG_GetLink(); if(!link) return; // Out of links! link->gen = gen; link->next = pgLinks[secIDX]; pgLinks[secIDX] = link; } /** * Link all active particle generators into the world. */ void P_CreatePtcGenLinks(void) { ptcgenid_t i; #ifdef DD_PROFILE static int p; if(++p > 40) { p = 0; PRINT_PROF(PROF_PTCGEN_LINK); } #endif BEGIN_PROF(PROF_PTCGEN_LINK); if(pgLinks) { // Clear the PG links. memset(pgLinks, 0, sizeof(pglink_t *) * numSectors); pgCursor = 0; } if(useParticles) { // Link all active generators to sectors. for(i = 0; i < MAX_ACTIVE_PTCGENS; ++i) { ptcgen_t* gen; if((gen = activePtcGens[i]) != NULL) { int k; // \fixme Overkill? for(k = 0; k < gen->count; ++k) if(gen->ptcs[k].stage >= 0) PG_LinkPtcGen(gen, GET_SECTOR_IDX(gen->ptcs[k].sector)); } } } END_PROF(PROF_PTCGEN_LINK); } /** * Set gen->count prior to calling this function. */ static void P_InitParticleGen(ptcgen_t* gen, const ded_ptcgen_t* def) { int i; if(gen->count <= 0) gen->count = 1; // Make sure no generator is type-triggered by default. gen->type = gen->type2 = -1; gen->def = def; gen->flags = def->flags; gen->ptcs = Z_Calloc(sizeof(particle_t) * gen->count, PU_MAP, 0); gen->stages = Z_Calloc(sizeof(ptcstage_t) * def->stageCount.num, PU_MAP, 0); for(i = 0; i < def->stageCount.num; ++i) { const ded_ptcstage_t* sdef = &def->stages[i]; ptcstage_t* s = &gen->stages[i]; s->bounce = FLT2FIX(sdef->bounce); s->resistance = FLT2FIX(1 - sdef->resistance); s->radius = FLT2FIX(sdef->radius); s->gravity = FLT2FIX(sdef->gravity); s->type = sdef->type; s->flags = sdef->flags; } // Init some data. for(i = 0; i < 3; ++i) { gen->center[i] = FLT2FIX(def->center[i]); gen->vector[i] = FLT2FIX(def->vector[i]); } // Apply a random component to the spawn vector. if(def->initVectorVariance > 0) { P_Uncertain(gen->vector, 0, FLT2FIX(def->initVectorVariance)); } // Mark unused. for(i = 0; i < gen->count; ++i) { particle_t* pt = &gen->ptcs[i]; pt->stage = -1; } } static void P_PresimParticleGen(ptcgen_t* gen, int tics) { for(; tics > 0; tics--) P_PtcGenThinker(gen); // Reset age so presim doesn't affect it. gen->age = 0; } /** * Creates a new mobj-triggered particle generator based on the given * definition. The generator is added to the list of active ptcgens. */ void P_SpawnParticleGen(const ded_ptcgen_t* def, mobj_t* source) { ptcgen_t* gen; if(isDedicated || !useParticles || !(gen = P_NewPtcGen())) return; /*#if _DEBUG Con_Message("SpawnPtcGen: %s/%i (src:%s typ:%s mo:%p)\n", def->state, def - defs.ptcgens, defs.states[source->state-states].id, defs.mobjs[source->type].id, source); #endif*/ // Initialize the particle generator. gen->count = def->particles; // Size of source sector might determine count. if(def->flags & PGF_SCALED_RATE) { gen->spawnRateMultiplier = source->subsector->sector->approxArea; } else { gen->spawnRateMultiplier = 1; } P_InitParticleGen(gen, def); gen->source = source; gen->srcid = source->thinker.id; // Is there a need to pre-simulate? P_PresimParticleGen(gen, def->preSim); } /** * Creates a new flat-triggered particle generator based on the given * definition. The generator is added to the list of active ptcgens. */ static void P_SpawnPlaneParticleGen(const ded_ptcgen_t* def, sector_t* sec, boolean isCeiling) { ptcgen_t* gen; if(isDedicated || !useParticles) return; if(!(gen = P_NewPtcGen())) return; gen->count = def->particles; // Size of source sector might determine count. if(def->flags & PGF_PARTS_PER_128) { gen->spawnRateMultiplier = sec->approxArea; } else { gen->spawnRateMultiplier = 1; } // Initialize the particle generator. P_InitParticleGen(gen, def); gen->sector = sec; gen->ceiling = isCeiling; // Is there a need to pre-simulate? P_PresimParticleGen(gen, def->preSim); } /** * The offset is spherical and random. * Low and High should be positive. */ static void P_Uncertain(fixed_t* pos, fixed_t low, fixed_t high) { int i; fixed_t off, theta, phi, vec[3]; if(!low) { // The simple, cubic algorithm. for(i = 0; i < 3; ++i) pos[i] += (high * (RNG_RandByte() - RNG_RandByte())) * reciprocal255; } else { // The more complicated, spherical algorithm. off = ((high - low) * (RNG_RandByte() - RNG_RandByte())) * reciprocal255; off += off < 0 ? -low : low; theta = RNG_RandByte() << (24 - ANGLETOFINESHIFT); phi = acos(2 * (RNG_RandByte() * reciprocal255) - 1) / PI * (ANGLE_180 >> ANGLETOFINESHIFT); vec[VX] = FixedMul(fineCosine[theta], finesine[phi]); vec[VY] = FixedMul(finesine[theta], finesine[phi]); vec[VZ] = FixedMul(fineCosine[phi], FLT2FIX(0.8333f)); for(i = 0; i < 3; ++i) pos[i] += FixedMul(vec[i], off); } } static void P_SetParticleAngles(particle_t* pt, int flags) { if(flags & PTCF_ZERO_YAW) pt->yaw = 0; if(flags & PTCF_ZERO_PITCH) pt->pitch = 0; if(flags & PTCF_RANDOM_YAW) pt->yaw = RNG_RandFloat() * 65536; if(flags & PTCF_RANDOM_PITCH) pt->pitch = RNG_RandFloat() * 65536; } static void P_ParticleSound(fixed_t pos[3], ded_embsound_t* sound) { int i; float orig[3]; // Is there any sound to play? if(!sound->id || sound->volume <= 0) return; for(i = 0; i < 3; ++i) orig[i] = FIX2FLT(pos[i]); S_LocalSoundAtVolumeFrom(sound->id, NULL, orig, sound->volume); } /** * Spawns a new particle. */ static void P_NewParticle(ptcgen_t* gen) { const ded_ptcgen_t* def = gen->def; particle_t* pt; int i; fixed_t uncertain, len; angle_t ang, ang2; subsector_t* subsec; float* box, inter = -1; modeldef_t* mf = 0, *nextmf = 0; // Check for model-only generators. if(gen->source) { inter = R_CheckModelFor(gen->source, &mf, &nextmf); if(((!mf || !useModels) && def->flags & PGF_MODEL_ONLY) || (mf && useModels && mf->flags & MFF_NO_PARTICLES)) return; } // Keep the spawn cursor in the valid range. if(++gen->spawnCP >= gen->count) gen->spawnCP -= gen->count; // Set the particle's data. pt = gen->ptcs + gen->spawnCP; pt->stage = 0; if(RNG_RandFloat() < def->altStartVariance) pt->stage = def->altStart; pt->tics = def->stages[pt->stage].tics * (1 - def->stages[pt->stage].variance * RNG_RandFloat()); // Launch vector. pt->mov[VX] = gen->vector[VX]; pt->mov[VY] = gen->vector[VY]; pt->mov[VZ] = gen->vector[VZ]; // Apply some random variance. pt->mov[VX] += FLT2FIX(def->vectorVariance * (RNG_RandFloat() - RNG_RandFloat())); pt->mov[VY] += FLT2FIX(def->vectorVariance * (RNG_RandFloat() - RNG_RandFloat())); pt->mov[VZ] += FLT2FIX(def->vectorVariance * (RNG_RandFloat() - RNG_RandFloat())); // Apply some aspect ratio scaling to the momentum vector. // This counters the 200/240 difference nearly completely. pt->mov[VX] = FixedMul(pt->mov[VX], FLT2FIX(1.1f)); pt->mov[VY] = FixedMul(pt->mov[VY], FLT2FIX(0.95f)); pt->mov[VZ] = FixedMul(pt->mov[VZ], FLT2FIX(1.1f)); // Set proper speed. uncertain = FLT2FIX( def->speed * (1 - def->speedVariance * RNG_RandFloat())); len = FLT2FIX(P_ApproxDistance( P_ApproxDistance(FIX2FLT(pt->mov[VX]), FIX2FLT(pt->mov[VY])), FIX2FLT(pt->mov[VZ]))); if(!len) len = FRACUNIT; len = FixedDiv(uncertain, len); pt->mov[VX] = FixedMul(pt->mov[VX], len); pt->mov[VY] = FixedMul(pt->mov[VY], len); pt->mov[VZ] = FixedMul(pt->mov[VZ], len); // The source is a mobj? if(gen->source) { if(gen->flags & PGF_RELATIVE_VECTOR) { // Rotate the vector using the source angle. float temp[3]; temp[VX] = FIX2FLT(pt->mov[VX]); temp[VY] = FIX2FLT(pt->mov[VY]); temp[VZ] = 0; // Player visangles have some problems, let's not use them. M_RotateVector(temp, gen->source->angle / (float) ANG180 * -180 + 90, 0); pt->mov[VX] = FLT2FIX(temp[VX]); pt->mov[VY] = FLT2FIX(temp[VY]); } if(gen->flags & PGF_RELATIVE_VELOCITY) { pt->mov[VX] += FLT2FIX(gen->source->mom[MX]); pt->mov[VY] += FLT2FIX(gen->source->mom[MY]); pt->mov[VZ] += FLT2FIX(gen->source->mom[MZ]); } // Position. pt->pos[VX] = FLT2FIX(gen->source->pos[VX]); pt->pos[VY] = FLT2FIX(gen->source->pos[VY]); pt->pos[VZ] = FLT2FIX(gen->source->pos[VZ] - gen->source->floorClip); P_Uncertain(pt->pos, FLT2FIX(def->spawnRadiusMin), FLT2FIX(def->spawnRadius)); // Offset to the real center. pt->pos[VZ] += gen->center[VZ]; // Calculate XY center with mobj angle. ang = (useSRVOAngle ? (gen->source->visAngle << 16) : gen->source-> angle) + (fixed_t) (FIX2FLT(gen->center[VY]) / 180.0f * ANG180); ang2 = (ang + ANG90) >> ANGLETOFINESHIFT; ang >>= ANGLETOFINESHIFT; pt->pos[VX] += FixedMul(fineCosine[ang], gen->center[VX]); pt->pos[VY] += FixedMul(finesine[ang], gen->center[VX]); // There might be an offset from the model of the mobj. if(mf && (mf->sub[0].flags & MFF_PARTICLE_SUB1 || def->subModel >= 0)) { int subidx; float off[3]; // Select the right submodel to use as the origin. if(def->subModel >= 0) subidx = def->subModel; else subidx = 1; // Default to submodel #1. // Interpolate the offset. if(inter > 0 && nextmf) { off[VX] = nextmf->ptcOffset[subidx][VX] - mf->ptcOffset[subidx][VX]; off[VY] = nextmf->ptcOffset[subidx][VY] - mf->ptcOffset[subidx][VY]; off[VZ] = nextmf->ptcOffset[subidx][VZ] - mf->ptcOffset[subidx][VZ]; off[VX] *= inter; off[VY] *= inter; off[VZ] *= inter; } off[VX] += mf->ptcOffset[subidx][VX]; off[VY] += mf->ptcOffset[subidx][VY]; off[VZ] += mf->ptcOffset[subidx][VZ]; // Apply it to the particle coords. pt->pos[VX] += FixedMul(fineCosine[ang], FLT2FIX(off[VX])); pt->pos[VX] += FixedMul(fineCosine[ang2], FLT2FIX(off[VZ])); pt->pos[VY] += FixedMul(finesine[ang], FLT2FIX(off[VX])); pt->pos[VY] += FixedMul(finesine[ang2], FLT2FIX(off[VZ])); pt->pos[VZ] += FLT2FIX(off[VY]); } } else if(gen->sector) // The source is a plane? { fixed_t radius = gen->stages[pt->stage].radius; // Choose a random spot inside the sector, on the spawn plane. if(gen->flags & PGF_SPACE_SPAWN) { pt->pos[VZ] = FLT2FIX(gen->sector->SP_floorheight) + radius + FixedMul(RNG_RandByte() << 8, FLT2FIX(gen->sector->SP_ceilheight - gen->sector->SP_floorheight) - 2 * radius); } else if(gen->flags & PGF_FLOOR_SPAWN || (!(gen->flags & (PGF_FLOOR_SPAWN | PGF_CEILING_SPAWN)) && !gen->ceiling)) { // Spawn on the floor. pt->pos[VZ] = FLT2FIX(gen->sector->SP_floorheight) + radius; } else { // Spawn on the ceiling. pt->pos[VZ] = FLT2FIX(gen->sector->SP_ceilheight) - radius; } /** * Choosing the XY spot is a bit more difficult. * But we must be fast and only sufficiently accurate. * * \fixme Nothing prevents spawning on the wrong side (or inside) * of one-sided walls (large diagonal subsectors!). */ box = gen->sector->bBox; for(i = 0; i < 5; ++i) // Try a couple of times (max). { float x = (box[BOXLEFT] + RNG_RandFloat() * (box[BOXRIGHT] - box[BOXLEFT])); float y = (box[BOXBOTTOM] + RNG_RandFloat() * (box[BOXTOP] - box[BOXBOTTOM])); subsec = R_PointInSubsector(x, y); if(subsec->sector == gen->sector) break; else subsec = NULL; } if(!subsec) goto spawn_failed; // Try a couple of times to get a good random spot. for(i = 0; i < 10; ++i) // Max this many tries before giving up. { float x = subsec->bBox[0].pos[VX] + RNG_RandFloat() * (subsec->bBox[1].pos[VX] - subsec->bBox[0].pos[VX]); float y = subsec->bBox[0].pos[VY] + RNG_RandFloat() * (subsec->bBox[1].pos[VY] - subsec->bBox[0].pos[VY]); pt->pos[VX] = FLT2FIX(x); pt->pos[VY] = FLT2FIX(y); if(R_PointInSubsector(x, y) == subsec) break; // This is a good place. } if(i == 10) // No good place found? { spawn_failed: pt->stage = -1; // Damn. return; } } else if(gen->flags & PGF_UNTRIGGERED) { // The center position is the spawn origin. pt->pos[VX] = gen->center[VX]; pt->pos[VY] = gen->center[VY]; pt->pos[VZ] = gen->center[VZ]; P_Uncertain(pt->pos, FLT2FIX(def->spawnRadiusMin), FLT2FIX(def->spawnRadius)); } // Initial angles for the particle. P_SetParticleAngles(pt, def->stages[pt->stage].flags); // The other place where this gets updated is after moving over // a two-sided line. if(gen->sector) pt->sector = gen->sector; else pt->sector = R_PointInSubsector(FIX2FLT(pt->pos[VX]), FIX2FLT(pt->pos[VY]))->sector; // Play a stage sound? P_ParticleSound(pt->pos, &def->stages[pt->stage].sound); } /** * Callback for the client mobj iterator, called from P_PtcGenThinker. */ boolean PIT_ClientMobjParticles(clmobj_t* cmo, void* context) { ptcgen_t* gen = (ptcgen_t*) context; // If the clmobj is not valid at the moment, don't do anything. if(cmo->flags & (CLMF_UNPREDICTABLE | CLMF_HIDDEN)) { return true; } if(cmo->mo.type != gen->type && cmo->mo.type != gen->type2) { // Type mismatch. return true; } gen->source = &cmo->mo; P_NewParticle(gen); return true; } /** * Spawn multiple new particles using all applicable sources. */ static boolean manyNewParticles(thinker_t* th, void* context) { ptcgen_t* gen = (ptcgen_t*) context; mobj_t* mo = (mobj_t *) th; // Type match? if(mo->type == gen->type || mo->type == gen->type2) { // Someone might think this is a slight hack... gen->source = mo; P_NewParticle(gen); } return true; // Continue iteration. } boolean PIT_CheckLinePtc(linedef_t* ld, void* data) { fixed_t ceil, floor; sector_t* front, *back; if(mbox[1][VX] <= ld->bBox[BOXLEFT] || mbox[0][VX] >= ld->bBox[BOXRIGHT] || mbox[1][VY] <= ld->bBox[BOXBOTTOM] || mbox[0][VY] >= ld->bBox[BOXTOP]) { return true; // Bounding box misses the line completely. } // Movement must cross the line. if(P_PointOnLinedefSide(FIX2FLT(tmpx1), FIX2FLT(tmpy1), ld) == P_PointOnLinedefSide(FIX2FLT(tmpx2), FIX2FLT(tmpy2), ld)) return true; // We are possibly hitting something here. ptcHitLine = ld; if(!ld->L_backside) return false; // Boing! // Determine the opening we have here. front = ld->L_frontsector; back = ld->L_backsector; if(front->SP_ceilheight < back->SP_ceilheight) ceil = FLT2FIX(front->SP_ceilheight); else ceil = FLT2FIX(back->SP_ceilheight); if(front->SP_floorheight > back->SP_floorheight) floor = FLT2FIX(front->SP_floorheight); else floor = FLT2FIX(back->SP_floorheight); // There is a backsector. We possibly might hit something. if(tmpz - tmprad < floor || tmpz + tmprad > ceil) return false; // Boing! // There is a possibility that the new position is in a new sector. tmcross = true; // Afterwards, update the sector pointer. // False alarm, continue checking. return true; } /** * Particle touches something solid. Returns false iff the particle dies. */ static int P_TouchParticle(particle_t* pt, ptcstage_t* stage, ded_ptcstage_t* stageDef, boolean touchWall) { // Play a hit sound. P_ParticleSound(pt->pos, &stageDef->hitSound); if(stage->flags & PTCF_DIE_TOUCH) { // Particle dies from touch. pt->stage = -1; return false; } if((stage->flags & PTCF_STAGE_TOUCH) || (touchWall && (stage->flags & PTCF_STAGE_WALL_TOUCH)) || (!touchWall && (stage->flags & PTCF_STAGE_FLAT_TOUCH))) { // Particle advances to the next stage. pt->tics = 0; } // Particle survives the touch. return true; } /** * Semi-fixed, actually. */ #if 0 // Currently unused. static void P_FixedCrossProduct(float* fa, fixed_t* b, fixed_t* result) { result[VX] = FixedMul(FRACUNIT * fa[VY], b[VZ]) - FixedMul(FRACUNIT * fa[VZ], b[VY]); result[VY] = FixedMul(FRACUNIT * fa[VZ], b[VX]) - FixedMul(FRACUNIT * fa[VX], b[VZ]); result[VZ] = FixedMul(FRACUNIT * fa[VX], b[VY]) - FixedMul(FRACUNIT * fa[VY], b[VX]); } #endif #if 0 // Currently unused. fixed_t P_FixedDotProduct(fixed_t* a, fixed_t* b) { return FixedMul(a[VX], b[VX]) + FixedMul(a[VY], b[VY]) + FixedMul(a[VZ], b[VZ]); } #endif /** * Takes care of consistent variance. * Currently only used visually, collisions use the constant radius. * The variance can be negative (results will be larger). */ float P_GetParticleRadius(const ded_ptcstage_t* def, int ptcIDX) { static const float rnd[16] = { .875f, .125f, .3125f, .75f, .5f, .375f, .5625f, .0625f, 1, .6875f, .625f, .4375f, .8125f, .1875f, .9375f, .25f }; if(!def->radiusVariance) return def->radius; return (rnd[ptcIDX & 0xf] * def->radiusVariance + (1 - def->radiusVariance)) * def->radius; } /** * A particle may be attached to the floor or ceiling of the sector. */ float P_GetParticleZ(const particle_t* pt) { if(pt->pos[VZ] == DDMAXINT) return pt->sector->SP_ceilvisheight - 2; else if(pt->pos[VZ] == DDMININT) return (pt->sector->SP_floorvisheight + 2); return FIX2FLT(pt->pos[VZ]); } static void P_SpinParticle(ptcgen_t* gen, particle_t* pt) { static const int yawSigns[4] = { 1, 1, -1, -1 }; static const int pitchSigns[4] = { 1, -1, 1, -1 }; ded_ptcstage_t* stDef = &gen->def->stages[pt->stage]; uint index = pt - &gen->ptcs[P_PtcGenToIndex(gen) / 8]; int yawSign, pitchSign; yawSign = yawSigns[index % 4]; pitchSign = pitchSigns[index % 4]; if(stDef->spin[0] != 0) { pt->yaw += 65536 * yawSign * stDef->spin[0] / (360 * TICSPERSEC); } if(stDef->spin[1] != 0) { pt->pitch += 65536 * pitchSign * stDef->spin[1] / (360 * TICSPERSEC); } pt->yaw *= 1 - stDef->spinResistance[0]; pt->pitch *= 1 - stDef->spinResistance[1]; } /** * The movement is done in two steps: * Z movement is done first. Skyflat kills the particle. * XY movement checks for hits with solid walls (no backsector). * This is supposed to be fast and simple (but not too simple). */ static void P_MoveParticle(ptcgen_t* gen, particle_t* pt) { ptcstage_t* st = &gen->stages[pt->stage]; ded_ptcstage_t* stDef = &gen->def->stages[pt->stage]; boolean zBounce = false, hitFloor = false; vec2_t point; fixed_t x, y, z, hardRadius = st->radius / 2; // Particle rotates according to spin speed. P_SpinParticle(gen, pt); // Changes to momentum. pt->mov[VZ] -= FixedMul(FLT2FIX(mapGravity), st->gravity); // Vector force. if(stDef->vectorForce[VX] != 0 || stDef->vectorForce[VY] != 0 || stDef->vectorForce[VZ] != 0) { int i; for(i = 0; i < 3; ++i) pt->mov[i] += FLT2FIX(stDef->vectorForce[i]); } // Sphere force pull and turn. // Only applicable to sourced or untriggered generators. For other // types it's difficult to define the center coordinates. if((st->flags & PTCF_SPHERE_FORCE) && (gen->source || gen->flags & PGF_UNTRIGGERED)) { int i; float delta[3], dist; if(gen->source) { delta[VX] = FIX2FLT(pt->pos[VX]) - gen->source->pos[VX]; delta[VY] = FIX2FLT(pt->pos[VY]) - gen->source->pos[VY]; delta[VZ] = P_GetParticleZ(pt) - (gen->source->pos[VZ] + FIX2FLT(gen->center[VZ])); } else { for(i = 0; i < 3; ++i) delta[i] = FIX2FLT(pt->pos[i] - gen->center[i]); } // Apply the offset (to source coords). for(i = 0; i < 3; ++i) delta[i] -= gen->def->forceOrigin[i]; // Counter the aspect ratio of old times. delta[VZ] *= 1.2f; dist = P_ApproxDistance(P_ApproxDistance(delta[VX], delta[VY]), delta[VZ]); if(dist != 0) { // Radial force pushes the particles on the surface of a sphere. if(gen->def->force) { // Normalize delta vector, multiply with (dist - forceRadius), // multiply with radial force strength. for(i = 0; i < 3; ++i) pt->mov[i] -= FLT2FIX( ((delta[i] / dist) * (dist - gen->def->forceRadius)) * gen->def->force); } // Rotate! if(gen->def->forceAxis[VX] || gen->def->forceAxis[VY] || gen->def->forceAxis[VZ]) { float cross[3]; M_CrossProduct(gen->def->forceAxis, delta, cross); for(i = 0; i < 3; ++i) pt->mov[i] += FLT2FIX(cross[i]) >> 8; } } } if(st->resistance != FRACUNIT) { int i; for(i = 0; i < 3; ++i) pt->mov[i] = FixedMul(pt->mov[i], st->resistance); } // The particle is 'soft': half of radius is ignored. // The exception is plane flat particles, which are rendered flat // against planes. They are almost entirely soft when it comes to plane // collisions. if(st->flags & PTCF_PLANE_FLAT) hardRadius = FRACUNIT; // Check the new Z position only if not stuck to a plane. z = pt->pos[VZ] + pt->mov[VZ]; if(pt->pos[VZ] != DDMININT && pt->pos[VZ] != DDMAXINT) { if(z > FLT2FIX(pt->sector->SP_ceilheight) - hardRadius) { // The Z is through the roof! if(R_IsSkySurface(&pt->sector->SP_ceilsurface)) { // Special case: particle gets lost in the sky. pt->stage = -1; return; } if(!P_TouchParticle(pt, st, stDef, false)) return; z = FLT2FIX(pt->sector->SP_ceilheight) - hardRadius; zBounce = true; hitFloor = false; } // Also check the floor. if(z < FLT2FIX(pt->sector->SP_floorheight) + hardRadius) { if(R_IsSkySurface(&pt->sector->SP_floorsurface)) { pt->stage = -1; return; } if(!P_TouchParticle(pt, st, stDef, false)) return; z = FLT2FIX(pt->sector->SP_floorheight) + hardRadius; zBounce = true; hitFloor = true; } if(zBounce) { pt->mov[VZ] = FixedMul(-pt->mov[VZ], st->bounce); if(!pt->mov[VZ]) { // The particle has stopped moving. This means its Z-movement // has ceased because of the collision with a plane. Plane-flat // particles will stick to the plane. if(st->flags & PTCF_PLANE_FLAT) { z = hitFloor ? DDMININT : DDMAXINT; } } } // Move to the new Z coordinate. pt->pos[VZ] = z; } // Now check the XY direction. // - Check if the movement crosses any solid lines. // - If it does, quit when first one contacted and apply appropriate // bounce (result depends on the angle of the contacted wall). x = pt->pos[VX] + pt->mov[VX]; y = pt->pos[VY] + pt->mov[VY]; tmcross = false; // Has crossed potential sector boundary? // XY movement can be skipped if the particle is not moving on the // XY plane. if(!pt->mov[VX] && !pt->mov[VY]) { // If the particle is contacting a line, there is a chance that the // particle should be killed (if it's moving slowly at max). if(pt->contact) { sector_t* front, *back; front = (pt->contact->L_frontside? pt->contact->L_frontsector : NULL); back = (pt->contact->L_backside? pt->contact->L_backsector : NULL); if(front && back && abs(pt->mov[VZ]) < FRACUNIT / 2) { float pz = P_GetParticleZ(pt); float fz, cz; //// \fixme $nplanes if(front->SP_floorheight > back->SP_floorheight) fz = front->SP_floorheight; else fz = back->SP_floorheight; if(front->SP_ceilheight < back->SP_ceilheight) cz = front->SP_ceilheight; else cz = back->SP_ceilheight; // If the particle is in the opening of a 2-sided line, it's // quite likely that it shouldn't be here... if(pz > fz && pz < cz) { // Kill the particle. pt->stage = -1; return; } } } // Still not moving on the XY plane... goto quit_iteration; } // We're moving in XY, so if we don't hit anything there can't be any // line contact. pt->contact = NULL; // Bounding box of the movement line. tmpz = z; tmprad = hardRadius; tmpx1 = pt->pos[VX]; tmpx2 = x; tmpy1 = pt->pos[VY]; tmpy2 = y; V2_Set(point, FIX2FLT(MIN_OF(x, pt->pos[VX]) - st->radius), FIX2FLT(MIN_OF(y, pt->pos[VY]) - st->radius)); V2_InitBox(mbox, point); V2_Set(point, FIX2FLT(MAX_OF(x, pt->pos[VX]) + st->radius), FIX2FLT(MAX_OF(y, pt->pos[VY]) + st->radius)); V2_AddToBox(mbox, point); // Iterate the lines in the contacted blocks. validCount++; if(!P_AllLinesBoxIteratorv(mbox, PIT_CheckLinePtc, 0)) { fixed_t normal[2], dotp; // Must survive the touch. if(!P_TouchParticle(pt, st, stDef, true)) return; // There was a hit! Calculate bounce vector. // - Project movement vector on the normal of hitline. // - Calculate the difference to the point on the normal. // - Add the difference to movement vector, negate movement. // - Multiply with bounce. // Calculate the normal. normal[VX] = -FLT2FIX(ptcHitLine->dX); normal[VY] = -FLT2FIX(ptcHitLine->dY); if(!normal[VX] && !normal[VY]) goto quit_iteration; // Calculate as floating point so we don't overflow. dotp = FRACUNIT * (DOT2F(pt->mov, normal) / DOT2F(normal, normal)); VECMUL(normal, dotp); VECSUB(normal, pt->mov); VECMULADD(pt->mov, 2 * FRACUNIT, normal); VECMUL(pt->mov, st->bounce); // Continue from the old position. x = pt->pos[VX]; y = pt->pos[VY]; tmcross = false; // Sector can't change if XY doesn't. // This line is the latest contacted line. pt->contact = ptcHitLine; goto quit_iteration; } quit_iteration: // The move is now OK. pt->pos[VX] = x; pt->pos[VY] = y; // Should we update the sector pointer? if(tmcross) pt->sector = R_PointInSubsector(FIX2FLT(x), FIX2FLT(y))->sector; } /** * Spawn and move particles. */ void P_PtcGenThinker(ptcgen_t* gen) { int i; particle_t* pt; float newparts; const ded_ptcgen_t* def = gen->def; // Source has been destroyed? if(!(gen->flags & PGF_UNTRIGGERED) && !P_IsUsedMobjID(gen->srcid)) { // Blasted... Spawning new particles becomes impossible. gen->source = NULL; } // Time to die? if(++gen->age > def->maxAge && def->maxAge >= 0) { P_PtcGenDestroy(gen); return; } // Spawn new particles? if((gen->age <= def->spawnAge || def->spawnAge < 0) && (gen->source || gen->sector || gen->type >= 0 || (gen->flags & PGF_UNTRIGGERED))) { newparts = def->spawnRate * gen->spawnRateMultiplier; newparts *= particleSpawnRate * (1 - def->spawnRateVariance * RNG_RandFloat()); gen->spawnCount += newparts; while(gen->spawnCount >= 1) { // Spawn a new particle. if(gen->type >= 0) // Type-triggered? { // Client's should also check the client mobjs. if(isClient) { Cl_MobjIterator(PIT_ClientMobjParticles, gen); } P_IterateThinkers(gx.MobjThinker, 0x1, // All mobjs are public manyNewParticles, gen); // The generator has no real source. gen->source = NULL; } else { P_NewParticle(gen); } gen->spawnCount--; } } // Move particles. for(i = 0, pt = gen->ptcs; i < gen->count; ++i, pt++) { if(pt->stage < 0) continue; // Not in use. if(pt->tics-- <= 0) { // Advance to next stage. if(++pt->stage == def->stageCount.num || gen->stages[pt->stage].type == PTC_NONE) { // Kill the particle. pt->stage = -1; continue; } pt->tics = def->stages[pt->stage].tics * (1 - def->stages[pt->stage]. variance * RNG_RandFloat()); // Change in particle angles? P_SetParticleAngles(pt, def->stages[pt->stage].flags); // A sound? P_ParticleSound(pt->pos, &def->stages[pt->stage].sound); } // Try to move. P_MoveParticle(gen, pt); } } /** * Returns true iff there is an active ptcgen for the given plane. */ static boolean P_HasActivePtcGen(sector_t* sector, int isCeiling) { ptcgenid_t i; for(i = 0; i < MAX_ACTIVE_PTCGENS; ++i) if(activePtcGens[i] && activePtcGens[i]->sector == sector && activePtcGens[i]->ceiling == isCeiling) return true; return false; } /** * Spawns new ptcgens for planes, if necessary. */ void P_CheckPtcPlanes(void) { uint i, p; sector_t* sector; if(isDedicated || !useParticles) return; // There is no need to do this on every tic. if(SECONDS_TO_TICKS(gameTime) % 4) return; for(i = 0; i < numSectors; ++i) { sector = SECTOR_PTR(i); for(p = 0; p < 2; ++p) { uint plane = p; material_t* mat = sector->SP_planematerial(plane); const ded_ptcgen_t* def = Material_GetPtcGen(mat); if(!def) continue; if(def->flags & PGF_CEILING_SPAWN) plane = 1; if(def->flags & PGF_FLOOR_SPAWN) plane = 0; if(!P_HasActivePtcGen(sector, plane)) { // Spawn it! P_SpawnPlaneParticleGen(def, sector, plane); } } } } /** * Spawns all type-triggered particle generators, regardless of whether * the type of mobj exists in the map or not (mobjs might be dynamically * created). */ void P_SpawnTypeParticleGens(void) { int i; ded_ptcgen_t* def; ptcgen_t* gen; if(isDedicated || !useParticles) return; for(i = 0, def = defs.ptcGens; i < defs.count.ptcGens.num; ++i, def++) { if(def->typeNum < 0) continue; if(!(gen = P_NewPtcGen())) return; // No more generators. // Initialize the particle generator. gen->count = def->particles; gen->spawnRateMultiplier = 1; P_InitParticleGen(gen, def); gen->type = def->typeNum; gen->type2 = def->type2Num; // Is there a need to pre-simulate? P_PresimParticleGen(gen, def->preSim); } } void P_SpawnMapParticleGens(const char* mapId) { int i; ded_ptcgen_t* def; ptcgen_t* gen; if(isDedicated || !useParticles) return; for(i = 0, def = defs.ptcGens; i < defs.count.ptcGens.num; ++i, def++) { if(!def->map[0] || stricmp(def->map, mapId)) continue; if(def->spawnAge > 0 && ddMapTime > def->spawnAge) continue; // No longer spawning this generator. if(!(gen = P_NewPtcGen())) return; // No more generators. // Initialize the particle generator. gen->count = def->particles; gen->spawnRateMultiplier = 1; P_InitParticleGen(gen, def); gen->flags |= PGF_UNTRIGGERED; // Is there a need to pre-simulate? P_PresimParticleGen(gen, def->preSim); } } /** * A public function (games can call this directly). */ void P_SpawnDamageParticleGen(mobj_t* mo, mobj_t* inflictor, int amount) { const ded_ptcgen_t* def; // Are particles allowed? if(isDedicated || !useParticles) return; if(!mo || !inflictor || amount <= 0) return; if((def = Def_GetDamageGenerator(mo->type))) { ptcgen_t* gen; vec3_t vector, vecDelta; // Create it. if(!(gen = P_NewPtcGen())) return; // No more generators. gen->count = def->particles; P_InitParticleGen(gen, def); gen->flags |= PGF_UNTRIGGERED; gen->spawnRateMultiplier = MAX_OF(amount, 1); // Calculate appropriate center coordinates. gen->center[VX] += FLT2FIX(mo->pos[VX]); gen->center[VY] += FLT2FIX(mo->pos[VY]); gen->center[VZ] += FLT2FIX(mo->pos[VZ] + mo->height / 2); // Calculate launch vector. V3_Set(vecDelta, inflictor->pos[VX] - mo->pos[VX], inflictor->pos[VY] - mo->pos[VY], (inflictor->pos[VZ] - inflictor->height / 2) - (mo->pos[VZ] + mo->height / 2)); V3_SetFixed(vector, gen->vector[VX], gen->vector[VY], gen->vector[VZ]); V3_Sum(vector, vector, vecDelta); V3_Normalize(vector); gen->vector[VX] = FLT2FIX(vector[VX]); gen->vector[VY] = FLT2FIX(vector[VY]); gen->vector[VZ] = FLT2FIX(vector[VZ]); // Is there a need to pre-simulate? P_PresimParticleGen(gen, def->preSim); } } /** * Called after a reset once the definitions have been re-read. */ void P_UpdateParticleGens(void) { ptcgenid_t i; for(i = 0; i < MAX_ACTIVE_PTCGENS; ++i) { int j; ded_ptcgen_t* def; boolean found; ptcgen_t* gen; if(!activePtcGens[i]) continue; gen = activePtcGens[i]; // Map generators cannot be updated (we have no means to reliably // identify them), so destroy them. // Flat generators will be spawned automatically within a few tics so we'll // just destroy those too. if((gen->flags & PGF_UNTRIGGERED) || gen->sector) { P_PtcGenDestroy(gen); continue; } // Search for a suitable definition. j = 0; def = defs.ptcGens; found = false; while(j < defs.count.ptcGens.num && !found) { // A type generator? if(def->typeNum >= 0 && (gen->type == def->typeNum || gen->type2 == def->type2Num)) { found = true; } // A damage generator? else if(gen->source && gen->source->type == def->damageNum) { found = true; } // A state generator? else if(gen->source && def->state[0] && gen->source->state - states == Def_GetStateNum(def->state)) { found = true; } else { j++; def++; } } if(found) { // Update the generator using the new definition. gen->def = def; } else { // Nothing else we can do, destroy it. P_PtcGenDestroy(gen); } } // Re-spawn map generators. P_SpawnMapParticleGens(mapID); } /** * Walk the entire list of particle generators. */ boolean P_IteratePtcGens(boolean (*callback) (ptcgen_t*, void*), void* context) { ptcgenid_t i; boolean result = true; for(i = 0; i < MAX_ACTIVE_PTCGENS; ++i) { if(!activePtcGens[i]) continue; if((result = callback(activePtcGens[i], context)) == 0) break; } return result; } /** * Walk the list of sector-linked particle generators. */ boolean P_IterateSectorLinkedPtcGens(sector_t* sector, boolean (*callback) (ptcgen_t*, void*), void* context) { return iterateSectorLinkedPtcGens(sector, callback, context); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_filehash.c0000644000175000017500000003421311357170242023177 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_filehash.c: File Name Hash Table * * Finding files *fast*. */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #include "de_base.h" #include "de_system.h" #include "de_misc.h" #include // MACROS ------------------------------------------------------------------ // Number of entries in the hash table. #define HASH_SIZE (512) // TYPES ------------------------------------------------------------------- typedef struct direcnode_s { struct direcnode_s* next; struct direcnode_s* parent; char* path; uint count; boolean processed; boolean isOnPath; } direcnode_t; typedef struct hashnode_s { struct hashnode_s* next; direcnode_t* directory; char* fileName; } hashnode_t; typedef struct hashentry_s { hashnode_t* first; hashnode_t* last; } hashentry_t; typedef struct _filehash_s { direcnode_t* direcFirst, *direcLast; hashentry_t hashTable[HASH_SIZE]; } _filehash_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void addDirectory(_filehash_t* fh, const char* path); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * @return [ a new | the ] directory node that matches the name * and has the specified parent node. */ static direcnode_t* direcNode(_filehash_t* fh, const char* name, direcnode_t* parent) { direcnode_t* node; // Just iterate through all directory nodes. for(node = fh->direcFirst; node; node = node->next) { if(!stricmp(node->path, name) && node->parent == parent) return node; } // Add a new node. if((node = M_Malloc(sizeof(*node))) == NULL) Con_Error("direcNode: failed on allocation of %lu bytes for new node.", (unsigned long) sizeof(*node)); node->next = NULL; node->parent = parent; if(fh->direcLast) fh->direcLast->next = node; fh->direcLast = node; if(!fh->direcFirst) fh->direcFirst = node; // Make a copy of the path. Freed in FileHash_Destroy(). if((node->path = M_Malloc(strlen(name) + 1)) == NULL) Con_Error("direcNode: failed on allocation of %lu bytes for path.", (unsigned long) (strlen(name) + 1)); strcpy(node->path, name); // No files yet. node->count = 0; node->isOnPath = false; node->processed = false; return node; } /** * The path is split into as many nodes as necessary. Parent links are set. * * @return The node that identifies the given path. */ static direcnode_t* buildDirecNodes(_filehash_t* fh, const char* path) { char* tokPath, *cursor; char* part; direcnode_t* node = NULL, *parent; filename_t relPath; // Let's try to make it a relative path. M_RemoveBasePath(relPath, path, FILENAME_T_MAXLEN); //strlwr(relPath); if((tokPath = cursor = M_Malloc(strlen(relPath) + 1)) == NULL) Con_Error("buildDirecNodes: failed on allocation of %lu bytes.", (unsigned long) (strlen(relPath) + 1)); strcpy(tokPath, relPath); parent = NULL; // Continue splitting as long as there are parts. while(*(part = M_StrTok(&cursor, DIR_SEP_STR))) { node = direcNode(fh, part, parent); parent = node; } M_Free(tokPath); return node; } /** * This is a hash function. It uses the base part of the file name to * generate a somewhat-random number between 0 and HASH_SIZE. * * @return The generated hash index. */ static uint hashFunction(const char* name) { unsigned short key = 0; int i, ch; // We stop when the name ends or the extension begins. for(i = 0; *name && *name != '.'; i++, name++) { ch = tolower(*name); if(i == 0) key ^= ch; else if(i == 1) key *= ch; else if(i == 2) { key -= ch; i = -1; } } return key % HASH_SIZE; } /** * Creates a file node into a directory. */ static void addFileToDirec(_filehash_t* fh, const char* filePath, direcnode_t* dir) { filename_t name; hashnode_t* node; hashentry_t* slot; // Extract the file name. Dir_FileName(name, filePath, FILENAME_T_MAXLEN); //strlwr(name); // Create a new node and link it to the hash table. if((node = M_Malloc(sizeof(hashnode_t))) == NULL) Con_Error("addFileToDirec: failed on allocation of %lu bytes for node.", (unsigned long) sizeof(hashnode_t)); node->directory = dir; if((node->fileName = M_Malloc(strlen(name) + 1)) == NULL) Con_Error("addFileToDirec: failed on allocation of %lu bytes for fileName.", (unsigned long) (strlen(name) + 1)); strcpy(node->fileName, name); node->next = NULL; // Calculate the key. slot = &fh->hashTable[hashFunction(name)]; if(slot->last) slot->last->next = node; slot->last = node; if(!slot->first) slot->first = node; // There's now one more file in the directory. dir->count++; } /** * Adds a file/directory to a directory. * * @param fn An absolute path. */ static int addFile(const char* fn, filetype_t type, void* parm) { filename_t path; char* pos; _filehash_t* fh = (_filehash_t*) parm; if(type != FT_NORMAL) return true; // Extract the path from the full file name. strncpy(path, fn, FILENAME_T_MAXLEN); if((pos = strrchr(path, DIR_SEP_CHAR))) *pos = 0; VERBOSE2(Con_Message(" File: %s\n", M_PrettyPath(fn))); // Add a node for this file. addFileToDirec(fh, fn, buildDirecNodes(fh, path)); return true; } /** * Process a directory and add its contents to the file hash. * If the path is relative, it is relative to the base path. */ static void addDirectory(_filehash_t* fh, const char* path) { direcnode_t* direc = buildDirecNodes(fh, path); filename_t searchPattern; // This directory is now on the search path. direc->isOnPath = true; if(direc->processed) { // This directory has already been processed. It means the // given path was a duplicate. We won't process it again. return; } // Compose the search pattern. M_PrependBasePath(searchPattern, path, FILENAME_T_MAXLEN); // We're interested in *everything*. strncat(searchPattern, "*", FILENAME_T_MAXLEN); F_ForAll(searchPattern, fh, addFile); // Mark this directory processed. direc->processed = true; /* // Mark all existing directories processed. // Everything they contain is already in the table. for(direc = fh->direcFirst; direc; direc = direc->next) { direc->processed = true; }*/ } /** * @param name A relative path. * * @return @c true, if the path specified in the name begins * from a directory in the search path. */ static boolean matchDirectory(hashnode_t* node, const char* name) { char* pos; filename_t dir; direcnode_t* direc = node->directory; // We'll do this in reverse order. strncpy(dir, name, FILENAME_T_MAXLEN); while((pos = strrchr(dir, DIR_SEP_CHAR)) != NULL) { // The string now ends here. *pos = 0; // Where does the directory name begin? pos = strrchr(dir, DIR_SEP_CHAR); if(!pos) pos = dir; else pos++; // Is there no more parent directories? if(!direc) return false; // Does this match the node's directory? if(stricmp(direc->path, pos)) { // Mismatch! This is not it. return false; } // So far so good. Move one directory level upwards. direc = direc->parent; } // We must have now arrived at a directory on the search path. return direc && direc->isOnPath; } /** * Composes an absolute path name for the node. */ static void composePath(hashnode_t* node, char* foundPath, size_t len) { direcnode_t* direc = node->directory; filename_t buf; strncpy(foundPath, node->fileName, len); while(direc) { dd_snprintf(buf, FILENAME_T_MAXLEN, "%s" DIR_SEP_STR "%s", direc->path, foundPath); strncpy(foundPath, buf, FILENAME_T_MAXLEN); direc = direc->parent; } // Add the base path. M_PrependBasePath(foundPath, foundPath, len); } static void clearHash(_filehash_t* fh) { if(fh->direcFirst) { uint i; direcnode_t* next; hashentry_t* entry; hashnode_t* nextNode; // Free the directory nodes. do { next = fh->direcFirst->next; M_Free(fh->direcFirst->path); M_Free(fh->direcFirst); fh->direcFirst = next; } while(fh->direcFirst); // Free the hash table. for(i = 0, entry = fh->hashTable; i < HASH_SIZE; ++i, entry++) { while(entry->first) { nextNode = entry->first->next; M_Free(entry->first->fileName); M_Free(entry->first); entry->first = nextNode; } } } fh->direcFirst = fh->direcLast = NULL; // Clear the entire table. memset(fh->hashTable, 0, sizeof(fh->hashTable)); } /** * Initialize the file hash using the given list of paths. * The paths must be separated with semicolons. */ filehash_t* FileHash_Create(const char* pathList) { char* path, *tokenPaths = M_Malloc(strlen(pathList) + 1); _filehash_t* fh; uint usedTime; if(verbose >= 2) { // Print the path list we are hashing. int n; Con_Message("FileHash_Create: Path list:\n"); strcpy(tokenPaths, pathList); path = strtok(tokenPaths, ";"); n = 0; while(path) { Con_Message(" %i - %s\n", n, M_PrettyPath(path)); // Get the next path. path = strtok(NULL, ";"); n++; } } usedTime = Sys_GetRealTime(); strcpy(tokenPaths, pathList); fh = M_Calloc(sizeof(*fh)); if((path = strtok(tokenPaths, ";"))) { do { // Convert all slashes to backslashes, so things are compatible // with the sys_file routines. Dir_FixSlashes(path, strlen(path)); addDirectory(fh, path); // Add this path to the hash. } while((path = strtok(NULL, ";"))); // Get the next path. M_Free(tokenPaths); } VERBOSE2(Con_Message(" Hash built in %.2f seconds.\n", (Sys_GetRealTime() - usedTime) / 1000.0f)); return (filehash_t*) fh; } /** * Empty the contents of the file hash. */ void FileHash_Destroy(filehash_t* fileHash) { _filehash_t* fh = (_filehash_t*) fileHash; clearHash(fh); M_Free(fh); } /** * Finds a file from the hash. * * @param foundPath The full path, returned. * @param name Relative or an absolute path. * @param len Size of @p foundPath in bytes. * * @return @c true, iff successful. */ boolean FileHash_Find(filehash_t* fileHash, char* foundPath, const char* name, size_t len) { filename_t validName, baseName; hashentry_t* slot; hashnode_t* node; _filehash_t* fh = (_filehash_t*) fileHash; // Absolute paths are not in the hash (no need to put them there). if(Dir_IsAbsolute(name)) return false; // Convert the given file name into a file name we can process. strncpy(validName, name, FILENAME_T_MAXLEN); //strlwr(validName); Dir_FixSlashes(validName, FILENAME_T_MAXLEN); // Extract the base name. Dir_FileName(baseName, validName, FILENAME_T_MAXLEN); // Which slot in the hash table? slot = &fh->hashTable[hashFunction(baseName)]; // Paths in the hash are relative to their directory node. // There is one direcnode per search path directory. // Go through the candidates. for(node = slot->first; node; node = node->next) { // The file name in the node has no path. if(stricmp(node->fileName, baseName)) continue; // If the directory compare passes, this is the match. // The directory must be on the search path for the test to pass. if(matchDirectory(node, validName)) { composePath(node, foundPath, len); return true; } } // Nothing suitable was found. return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/con_buffer.c0000644000175000017500000003624611357170241023217 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_buffer.c: Console history buffer. * * NOTE: With respect to threading, this code assumes that a cbuffer, * mutex's lock/unlock state has been manipulated by the CALLER of * private functions declared here. Therefore, public functions must * lock before and unlock after calling a private function. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_system.h" #include "de_console.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct cbnode_s { cbline_t* data; struct cbnode_s* next, *prev; } cbnode_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void insertNodeAtEnd(cbuffer_t* buf, cbnode_t* newnode); static void removeNode(cbuffer_t* buf, cbnode_t* node); static void moveNodeForReuse(cbuffer_t* buf, cbnode_t* node); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * NOTE: Also destroys the data object. */ static void destroyNode(cbnode_t* node) { cbline_t* line = node->data; if(line->text) M_Free(line->text); M_Free(line); M_Free(node); } static void insertNodeAfter(cbuffer_t* buf, cbnode_t* node, cbnode_t* newnode) { newnode->prev = node; newnode->next = node->next; if(node->next == NULL) buf->tailptr = newnode; else node->next->prev = newnode; node->next = newnode; } static void insertNodeBefore(cbuffer_t* buf, cbnode_t* node, cbnode_t* newnode) { newnode->prev = node->prev; newnode->next = node; if(node->prev == NULL) buf->headptr = newnode; else node->prev->next = newnode; node->prev = newnode; } static void insertNodeAtStart(cbuffer_t* buf, cbnode_t* newnode) { if(buf->headptr == NULL) { buf->headptr = newnode; buf->tailptr = newnode; newnode->prev = NULL; newnode->next = NULL; } else insertNodeBefore(buf, buf->headptr, newnode); } static void insertNodeAtEnd(cbuffer_t* buf, cbnode_t* newnode) { if(buf->tailptr == NULL) insertNodeAtStart(buf, newnode); else insertNodeAfter(buf, buf->tailptr, newnode); } static void moveNodeForReuse(cbuffer_t* buf, cbnode_t* node) { cbline_t* line; if(buf->unused != NULL) node->next = buf->unused; else node->next = NULL; node->prev = NULL; buf->unused = node; line = node->data; line->flags = 0; if(line->text) memset(line->text, 0, line->len); } static void removeNode(cbuffer_t* buf, cbnode_t* node) { if(node->prev == NULL) buf->headptr = node->next; else node->prev->next = node->next; if(node->next == NULL) buf->tailptr = node->prev; else node->next->prev = node->prev; moveNodeForReuse(buf, node); } /** * Creates a new console history buffer. * * @param maxNumLines Maximum number of lines the buffer can hold, * @c 0, means unlimited. * @param maxLineLength Maximum length of each line in the buffer. * @param flags Console buffer flags (CBF_*). * * @return Ptr to the newly created console buffer. */ cbuffer_t* Con_NewBuffer(uint maxNumLines, uint maxLineLength, int flags) { char name[32+1]; cbuffer_t* buf; if(maxLineLength < 1) Con_Error("Con_NewBuffer: Odd buffer params"); buf = M_Malloc(sizeof(*buf)); dd_snprintf(name, 33, "CBufferMutex%p", buf); buf->mutex = Sys_CreateMutex(name); buf->flags = flags; buf->headptr = buf->tailptr = NULL; buf->numLines = 0; buf->maxLineLen = maxLineLength; buf->writebuf = M_Calloc(buf->maxLineLen + 1); buf->wbc = 0; buf->wbFlags = 0; buf->maxLines = maxNumLines; if(buf->maxLines != 0) // not unlimited. { // Might as well allocate the index now. buf->index = M_Malloc(sizeof(cbline_t*) * buf->maxLines); buf->indexSize = buf->maxLines; } else { buf->index = NULL; buf->indexSize = 0; } buf->indexGood = true; // its empty so... buf->unused = NULL; return buf; } static void clearBuffer(cbuffer_t* buf, boolean destroy) { cbnode_t* n, *np; // Free the buffer contents. n = buf->headptr; while(n != NULL) { np = n->next; if(destroy) destroyNode(n); else moveNodeForReuse(buf, n); n = np; } buf->headptr = buf->tailptr = NULL; buf->numLines = 0; memset(buf->writebuf, 0, buf->maxLineLen); buf->wbc = 0; } /** * Clear the contents of a console history buffer. * * @param buf Ptr to the buffer to be cleared. */ void Con_BufferClear(cbuffer_t* buf) { if(!buf) return; Sys_Lock(buf->mutex); clearBuffer(buf, false); Sys_Unlock(buf->mutex); } /** * Destroy an existing console history buffer. * * @param buf Ptr to the buffer to be destroyed. */ void Con_DestroyBuffer(cbuffer_t* buf) { if(buf) { cbnode_t* n, *np; Sys_Lock(buf->mutex); clearBuffer(buf, true); M_Free(buf->writebuf); if(buf->index) M_Free(buf->index); // Free any unused nodes. n = buf->unused; while(n) { np = n->next; destroyNode(n); n = np; } Sys_Unlock(buf->mutex); Sys_DestroyMutex(buf->mutex); buf->mutex = 0; M_Free(buf); } } /** * Change the maximum line length for the given console history buffer. * Existing lines are unaffected, the change only impacts new lines. * * @param buf Ptr to the buffer to be changed. * @param length Length to set the max line length to. */ void Con_BufferSetMaxLineLength(cbuffer_t* buf, uint length) { if(!buf) return; Sys_Lock(buf->mutex); buf->maxLineLen = length; // The write buffer will be trimmed if resizing smaller. buf->writebuf = M_Realloc(buf->writebuf, buf->maxLineLen + 1); if(buf->wbc > buf->maxLineLen) buf->wbc = buf->maxLineLen; Sys_Unlock(buf->mutex); } /** * @param buf Ptr to the buffer to be queried. * * @return Number of lines currently in the buffer. */ uint Con_BufferNumLines(cbuffer_t* buf) { uint num; if(!buf) return 0; Sys_Lock(buf->mutex); num = buf->numLines; // index + 1 Sys_Unlock(buf->mutex); return num; } static cbline_t const* bufferGetLine(cbuffer_t* buf, uint idx) { const cbline_t* ptr = NULL; if(!(buf->numLines == 0 || idx >= buf->numLines)) { if(!buf->indexGood) { // Rebuild the index. uint i; cbnode_t* node; // Do we need to enlarge the index? if(buf->indexSize < buf->numLines) { buf->index = M_Realloc(buf->index, sizeof(cbline_t*) * buf->numLines); buf->indexSize = buf->numLines; } i = 0; node = buf->headptr; while(node != NULL) { buf->index[i++] = node->data; node = node->next; } buf->indexGood = true; } ptr = (const cbline_t*) buf->index[idx]; } return ptr; } static uint bufferGetLines(cbuffer_t* buf, uint reqCount, int firstIdx, cbline_t const** list) { if((long) firstIdx <= (long) buf->numLines) { uint i, n, idx, count = reqCount; if(firstIdx < 0) { long other = -((long) firstIdx); if(other > (long) buf->numLines) firstIdx = 0; else firstIdx = buf->numLines - other; } idx = firstIdx; if(reqCount == 0 || idx + count > buf->numLines) count = buf->numLines - idx; // Collect the ptrs. for(i = 0, n = idx; i < count; ++i) list[i] = bufferGetLine(buf, n++); // Terminate. list[i] = NULL; return count; // index + 1 } if(*list) list[0] = NULL; return 0; } /** * Retrive an array of un-mutable ptrs to console buffer lines from the * given cbuffer. * * NOTE: The array must be free'd with M_Free(). * * @param buf Ptr to the buffer to retrieve the lines from. * @param reqCount Number of lines requested from the buffer, zero means * use the current number of lines as the limit. * @param firstIdx Line index of the first line to be retrieved. If * negative, the index is from the end of list. * @param list Ptr to an array of console buffer ptrs which we'll * write to and terminate with @c NULL, * * @return The number of elements written back to the buffer. */ uint Con_BufferGetLines(cbuffer_t* buf, uint reqCount, int firstIdx, cbline_t const** list) { if(buf) { uint result; Sys_Lock(buf->mutex); result = bufferGetLines(buf, reqCount, firstIdx, list); Sys_Unlock(buf->mutex); return result; } if(*list) list[0] = NULL; return 0; } /** * Retrieve an un-mutable ptr to the line with the given index from the * history buffer. * * @param buf Ptr to the buffer to use. * @param idx Index of the line to retrieve. * * @return Ptr to the cbline_t with the requested index or * @c NULL, if the index was invalid. */ const cbline_t* Con_BufferGetLine(cbuffer_t* buf, uint idx) { if(buf) { const cbline_t* ptr; Sys_Lock(buf->mutex); ptr = bufferGetLine(buf, idx); Sys_Unlock(buf->mutex); return ptr; } return NULL; } /** * Create a new buffer line and link it into the history buffer. * * @param buf Ptr to the buffer to use. * * @return Ptr to the cbline_t with the requested index or * @c NULL, if the index was invalid. */ static cbline_t* bufferNewLine(cbuffer_t* buf) { cbnode_t* node; cbline_t* line; if(!buf) return NULL; // This is unacceptable! // Do we have any unused nodes we can reuse? if(buf->unused != NULL) { node = buf->unused; buf->unused = node->next; line = node->data; } else { // Allocate another line. line = M_Malloc(sizeof(cbline_t)); node = M_Malloc(sizeof(cbnode_t)); node->data = line; line->text = NULL; line->len = 0; } assert(node->data); buf->numLines++; line->flags = 0; // Link it in. insertNodeAtEnd(buf, node); // Check if there are too many lines. if(buf->maxLines != 0 && buf->numLines > buf->maxLines) { // Drop the earliest. removeNode(buf, buf->headptr); buf->numLines--; } buf->indexGood = false; // it will be updated when needed. return line; } static void bufferFlush(cbuffer_t* buf) { uint len; cbline_t* line; // Is there anything to flush? if(buf->wbc < 1) return; line = bufferNewLine(buf); // // Flush the write buffer. // len = buf->wbc; if(line->text != NULL) { // We are re-using an existing line so we may not need to // reallocate at all. if(line->len <= len) { line->len = len + 1; line->text = M_Realloc(line->text, line->len); } } else { line->len = len + 1; line->text = M_Malloc(line->len); } memcpy(line->text, buf->writebuf, len); line->text[len] = 0; line->flags = buf->wbFlags; // Clear the write buffer. memset(buf->writebuf, 0, buf->maxLineLen); buf->wbc = 0; buf->wbFlags = 0; } /** * Flushes the contents of the write buffer to the history buffer. * * @param buf Ptr to the history buffer to flush. */ void Con_BufferFlush(cbuffer_t* buf) { if(!buf) return; Sys_Lock(buf->mutex); bufferFlush(buf); Sys_Unlock(buf->mutex); } /** * Write the given text string (plus optional flags) to the buffer. * * @param buf Ptr to the buffer to write to. * @param flags CBLF_* flags in use for this write. * @param txt Ptr to the text string to be written. */ void Con_BufferWrite(cbuffer_t* buf, int flags, const char* txt) { if(!buf) return; Sys_Lock(buf->mutex); // Check for special write actions first. if(flags & CBLF_RULER) { bufferFlush(buf); bufferNewLine(buf)->flags |= CBLF_RULER; flags &= ~CBLF_RULER; } if(!(!txt || !strcmp(txt, ""))) { size_t i, len = strlen(txt); // Copy the text into the write buffer and flush to the history // buffer when as necessary/required. for(i = 0; i < len; ++i) { buf->wbFlags = flags; if(txt[i] == '\n' || buf->wbc >= buf->maxLineLen) // A new line? { bufferFlush(buf); // Newlines won't get in the buffer at all. if(txt[i] == '\n') continue; } // Copy the next character to the write buffer. buf->writebuf[buf->wbc++] = txt[i]; } if(buf->flags & CBF_ALWAYSFLUSH) { // Don't leave data in the write buffer. bufferFlush(buf); } } Sys_Unlock(buf->mutex); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_defer.c0000644000175000017500000003305211357170242022647 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_defer.c: Deferred GL Tasks */ // HEADER FILES ------------------------------------------------------------ #ifdef UNIX # include "de_platform.h" #endif #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define NUM_RESERVED_NAMES 512 // TYPES ------------------------------------------------------------------- typedef struct deferred_s { texturecontent_t content; struct deferred_s* next; } deferred_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- deferred_t* GL_GetNextDeferred(void); void GL_DestroyDeferred(deferred_t* d); // PRIVATE DATA DEFINITIONS ------------------------------------------------ static mutex_t deferredMutex; static DGLuint reservedNames[NUM_RESERVED_NAMES]; static volatile int reservedCount = 0; static volatile deferred_t* deferredContentFirst = NULL; static volatile deferred_t* deferredContentLast = NULL; static boolean deferredInited = false; // CODE -------------------------------------------------------------------- void GL_InitDeferred(void) { if(deferredInited) return; // Been here already... deferredInited = true; deferredMutex = Sys_CreateMutex("DGLDeferredMutex"); GL_ReserveNames(); } void GL_ShutdownDeferred(void) { deferred_t* d; if(!deferredInited) return; GL_ReleaseReservedNames(); while((d = GL_GetNextDeferred()) != NULL) { GL_DestroyDeferred(d); } Sys_DestroyMutex(deferredMutex); deferredMutex = 0; reservedCount = 0; } int GL_GetDeferredCount(void) { int count = 0; deferred_t* i = 0; if(!deferredInited) return 0; Sys_Lock(deferredMutex); for(i = (deferred_t*) deferredContentFirst; i; i = i->next, ++count); Sys_Unlock(deferredMutex); return count; } deferred_t* GL_GetNextDeferred(void) { deferred_t* d = NULL; if(!deferredInited) return NULL; Sys_Lock(deferredMutex); if((d = (deferred_t*) deferredContentFirst) != NULL) { deferredContentFirst = d->next; } if(!deferredContentFirst) deferredContentLast = NULL; Sys_Unlock(deferredMutex); return d; } void GL_DestroyDeferred(deferred_t* d) { M_Free(d->content.buffer); M_Free(d); } void GL_ReserveNames(void) { if(!deferredInited) return; // Just ignore. Sys_Lock(deferredMutex); if(reservedCount < NUM_RESERVED_NAMES) { glGenTextures(NUM_RESERVED_NAMES - reservedCount, (GLuint*) &reservedNames[reservedCount]); reservedCount = NUM_RESERVED_NAMES; } Sys_Unlock(deferredMutex); } void GL_ReleaseReservedNames(void) { if(!deferredInited) return; // Just ignore. Sys_Lock(deferredMutex); glDeleteTextures(reservedCount, (const GLuint*) reservedNames); memset(reservedNames, 0, sizeof(reservedNames)); reservedCount = 0; Sys_Unlock(deferredMutex); } DGLuint GL_GetReservedName(void) { DGLuint name; if(!deferredInited) Con_Error("GL_GetReserved: Deferred GL task system not initialized."); Sys_Lock(deferredMutex); if(!reservedCount) { Sys_Unlock(deferredMutex); while(reservedCount == 0) { // Wait for someone to refill the names buffer. Con_Message("GL_GetReservedName: Sleeping until new names available.\n"); Sys_Sleep(5); } Sys_Lock(deferredMutex); } name = reservedNames[0]; memmove(reservedNames, reservedNames + 1, (NUM_RESERVED_NAMES - 1) * sizeof(DGLuint)); reservedCount--; Sys_Unlock(deferredMutex); return name; } /** * Initializes a texture content struct with default params. */ void GL_InitTextureContent(texturecontent_t* content) { memset(content, 0, sizeof(*content)); content->palette = 0; // Use the default. content->minFilter = GL_LINEAR; content->magFilter = GL_LINEAR; content->anisoFilter = -1; // Best. content->wrap[0] = GL_CLAMP; content->wrap[1] = GL_CLAMP; content->grayMipmap = -1; } void GL_UploadTextureContent(texturecontent_t* content) { boolean result = false; if(content->flags & TXCF_EASY_UPLOAD) { GL_UploadTexture2(content); } else { byte* allocatedTempBuffer = NULL; DGLuint palid; if(content->grayMipmap >= 0) { GL_SetGrayMipmap(content->grayMipmap); } // The texture name must already be created. glBindTexture(GL_TEXTURE_2D, content->name); // Upload the texture. // No mipmapping or resizing is needed, upload directly. if(content->flags & TXCF_NO_COMPRESSION) { GL_SetTextureCompression(false); } if((content->flags & TXCF_CONVERT_8BIT_TO_ALPHA) && (content->format == DGL_LUMINANCE || content->format == DGL_COLOR_INDEX_8 || content->format == DGL_DEPTH_COMPONENT)) { int total = content->width * content->height; allocatedTempBuffer = M_Malloc(total * 2); // Move the average color to the alpha channel, make the // actual color white. memcpy(allocatedTempBuffer + total, content->buffer, total); memset(allocatedTempBuffer, 255, total); content->format = DGL_LUMINANCE_PLUS_A8; } // Do we need to locate a color palette? if(content->format == DGL_COLOR_INDEX_8 || content->format == DGL_COLOR_INDEX_8_PLUS_A8) { palid = R_GetColorPalette(content->palette); } else palid = 0; if(!GL_TexImage(content->format, palid, content->width, content->height, (content->grayMipmap >= 0? DDMAXINT : (content->flags & TXCF_MIPMAP) != 0), allocatedTempBuffer? allocatedTempBuffer : content->buffer)) Con_Error("GL_UploadTextureContent: TexImage failed " "(%u:%ix%i fmt%i).", content->name, content->width, content->height, (int) content->format); if(content->flags & TXCF_NO_COMPRESSION) { GL_SetTextureCompression(true); } if(allocatedTempBuffer) { M_Free(allocatedTempBuffer); } } glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, content->minFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, content->magFilter); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, content->wrap[0]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, content->wrap[1]); if(GL_state.useAnisotropic) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(content->anisoFilter)); #ifdef _DEBUG Sys_CheckGLError(); #endif } /** * @return @c true, iff this operation was deferred. */ DGLuint GL_NewTexture(texturecontent_t* content, boolean* result) { boolean deferred = true; // Calculate the size of the buffer automatically? if(content->bufferSize == 0) { int bytesPerPixel = 0; switch(content->format) { case DGL_LUMINANCE: if(content->flags & TXCF_CONVERT_8BIT_TO_ALPHA) bytesPerPixel = 2; // We'll need a larger buffer. else bytesPerPixel = 1; break; case DGL_COLOR_INDEX_8: case DGL_DEPTH_COMPONENT: bytesPerPixel = 1; break; case DGL_COLOR_INDEX_8_PLUS_A8: case DGL_LUMINANCE_PLUS_A8: bytesPerPixel = 2; break; case DGL_RGB: bytesPerPixel = 3; break; case DGL_RGBA: bytesPerPixel = 4; break; default: Con_Error("GL_NewTexture: Unknown format %i, " "don't know pixel size.\n", content->format); } content->bufferSize = content->width * content->height * bytesPerPixel; } if(content->flags & TXCF_GRAY_MIPMAP) { content->grayMipmap = ((content->flags & TXCF_GRAY_MIPMAP_LEVEL_MASK) >> TXCF_GRAY_MIPMAP_LEVEL_SHIFT); } content->name = GL_GetReservedName(); if((content->flags & TXCF_NEVER_DEFER) || !Con_IsBusy()) { // Let's do this right away. No need to take a copy. GL_UploadTextureContent(content); #ifdef _DEBUG Con_Message("GL_NewTexture: Uploading (%i:%ix%i) while not busy! " "Should be precached in busy mode?\n", content->name, content->width, content->height); #endif deferred = false; // We haven't deferred. } else { // Defer this operation. Need to make a copy. deferred_t* d = M_Calloc(sizeof(deferred_t)); memcpy(&d->content, content, sizeof(*content)); d->content.buffer = M_Malloc(content->bufferSize); memcpy(d->content.buffer, content->buffer, content->bufferSize); Sys_Lock(deferredMutex); if(deferredContentLast) deferredContentLast->next = d; if(!deferredContentFirst) deferredContentFirst = d; deferredContentLast = d; Sys_Unlock(deferredMutex); } if(result) *result = deferred; return content->name; } DGLuint GL_NewTextureWithParams(dgltexformat_t format, int width, int height, void* pixels, int flags) { texturecontent_t c; GL_InitTextureContent(&c); c.format = format; c.width = width; c.height = height; c.buffer = pixels; c.flags = flags; return GL_NewTexture(&c, NULL); } DGLuint GL_NewTextureWithParams2(dgltexformat_t format, int width, int height, void* pixels, int flags, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT) { texturecontent_t c; GL_InitTextureContent(&c); c.format = format; c.width = width; c.height = height; c.buffer = pixels; c.flags = flags; c.magFilter = magFilter; c.minFilter = minFilter; c.anisoFilter = anisoFilter; c.wrap[0] = wrapS; c.wrap[1] = wrapT; return GL_NewTexture(&c, NULL); } /** * Same as above except this version is part of the public API and thus some * of the paramaters use the DGL counterparts. */ DGLuint GL_NewTextureWithParams3(dgltexformat_t format, int width, int height, void* pixels, int flags, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT) { return GL_NewTextureWithParams2(format, width, height, pixels, flags, (minFilter == DGL_LINEAR? GL_LINEAR : minFilter == DGL_NEAREST? GL_NEAREST : minFilter == DGL_NEAREST_MIPMAP_NEAREST? GL_NEAREST_MIPMAP_NEAREST : minFilter == DGL_LINEAR_MIPMAP_NEAREST? GL_LINEAR_MIPMAP_NEAREST : minFilter == DGL_NEAREST_MIPMAP_LINEAR? GL_NEAREST_MIPMAP_LINEAR : GL_LINEAR_MIPMAP_LINEAR), (magFilter == DGL_LINEAR? GL_LINEAR : GL_NEAREST), anisoFilter, (wrapS == DGL_CLAMP? GL_CLAMP : wrapS == DGL_CLAMP_TO_EDGE? GL_CLAMP_TO_EDGE : GL_REPEAT), (wrapT == DGL_CLAMP? GL_CLAMP : wrapT == DGL_CLAMP_TO_EDGE? GL_CLAMP_TO_EDGE : GL_REPEAT)); } /** * @param timeOutMilliSeconds Zero for no timeout. */ void GL_UploadDeferredContent(uint timeOutMilliSeconds) { deferred_t* d; uint startTime; if(!deferredInited) Con_Error("GL_UploadDeferredContent: Deferred GL task system " "not initialized."); startTime = Sys_GetRealTime(); // We'll reserve names multiple times, because the worker thread may be // needing new texture names while we are uploading. GL_ReserveNames(); while((!timeOutMilliSeconds || Sys_GetRealTime() - startTime < timeOutMilliSeconds) && (d = GL_GetNextDeferred()) != NULL) { GL_UploadTextureContent(&d->content); GL_DestroyDeferred(d); GL_ReserveNames(); } GL_ReserveNames(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_binarytree.c0000644000175000017500000002416211357170242023562 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_binarytree.c: A fairly standard binary tree implementation. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "m_binarytree.h" // MACROS ------------------------------------------------------------------ #define RIGHT 0 #define LEFT 1 #define IS_LEAF(node) (!((node)->children[RIGHT] || (node)->children[LEFT])) // TYPES ------------------------------------------------------------------- typedef struct treenode_s { void *data; struct treenode_s *children[2]; // {RIGHT, LEFT} } treenode_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static __inline treenode_t *allocNode(void) { return malloc(sizeof(treenode_t)); } static __inline void freeNode(treenode_t *node) { free(node); } static treenode_t *createTree(const void *userData, treenode_t *right, treenode_t *left) { treenode_t *n; n = allocNode(); n->data = (void*) userData; n->children[RIGHT] = right; n->children[LEFT] = left; return n; } static void destroyTree(treenode_t *tree) { treenode_t *n; if(!tree) return; n = (treenode_t*) tree; destroyTree(n->children[RIGHT]); destroyTree(n->children[LEFT]); freeNode(n); } static size_t getHeight(const treenode_t *n) { if(n && !IS_LEAF(n)) { size_t left, right; right = getHeight(n->children[RIGHT]); left = getHeight(n->children[LEFT]); return MAX_OF(left, right) + 1; } return 0; } static boolean preOrder(treenode_t *n, boolean (C_DECL *func) (binarytree_t *tree, void *data), void *data) { if(!n) return true; // Visit this node. if(!func((binarytree_t*) n, data)) return false; if(!IS_LEAF(n)) { if(!preOrder(n->children[RIGHT], func, data)) return false; if(!preOrder(n->children[LEFT], func, data)) return false; } return true; } static boolean inOrder(treenode_t *n, boolean (C_DECL *func) (binarytree_t *tree, void *data), void *data) { if(!n) return true; if(!IS_LEAF(n)) { if(!inOrder(n->children[RIGHT], func, data)) return false; } // Visit this node. if(!func((binarytree_t*) n, data)) return false; if(!IS_LEAF(n)) { if(!inOrder(n->children[LEFT], func, data)) return false; } return true; } static boolean postOrder(treenode_t *n, boolean (C_DECL *func) (binarytree_t *tree, void *data), void *data) { if(!n) return true; if(!IS_LEAF(n)) { if(!postOrder(n->children[RIGHT], func, data)) return false; if(!postOrder(n->children[LEFT], func, data)) return false; } // Visit this node. if(!func((binarytree_t*) n, data)) return false; return true; } /** * Create a new binary (sub)tree. * * @param data User-data to be associated with the new (sub)tree. * * @return Ptr to the newly created (sub)tree. */ binarytree_t *BinaryTree_Create(const void *data) { return (binarytree_t*) createTree(data, NULL, NULL); } /** * Create a new binary (sub)tree. * * @param data User-data to be associated with the new (sub)tree. * @param initialRight Ptr to the (sub)tree to link as the right child. * @param initialLeft Ptr to the (sub)tree to link as the left child. * * @return Ptr to the newly created (sub)tree. */ binarytree_t *BinaryTree_Create2(const void *data, binarytree_t *initialRight, binarytree_t *initialLeft) { return (binarytree_t*) createTree(data, (treenode_t*) initialRight, (treenode_t*) initialLeft); } /** * Destroy the given binary tree. * * @param tree Ptr to the tree to be destroyed. */ void BinaryTree_Destroy(binarytree_t *tree) { if(!tree) return; destroyTree((treenode_t*) tree); } /** * Calculate the height of the given tree. * * @param rootNode Node to begin at. * * @return Height of the tree. */ size_t BinaryTree_GetHeight(binarytree_t *tree) { if(!tree) return 0; return getHeight((treenode_t*) tree); } /** * Is this node a leaf? * * @param node Ptr to the node to test. * @return @c true iff this node is a leaf. */ boolean BinaryTree_IsLeaf(binarytree_t *tree) { if(!tree) return false; return IS_LEAF((treenode_t*) tree); } /** * Given the specified node, return one of it's children. * * @param node Ptr to the parent. * @param left @c true= retrieve the left child. * @c false= retrieve the right child. * @return Ptr to the requested child if present ELSE @c NULL. */ binarytree_t *BinaryTree_GetChild(binarytree_t *tree, boolean left) { treenode_t *n; if(!tree) return NULL; n = (treenode_t*) tree; return (binarytree_t*) n->children[left? LEFT : RIGHT]; } /** * Set a child of the specified tree. * * @param tree Ptr to the (parent) tree to have its child set. * @param left @c true= set the left child. * @c false= set the right child. * @param subTree Ptr to the (child) tree to be linked or @c NULL. */ void BinaryTree_SetChild(binarytree_t *tree, boolean left, binarytree_t *subTree) { treenode_t *parent, *child; if(!tree) return; parent = (treenode_t*) tree; child = (treenode_t*) subTree; parent->children[left? LEFT : RIGHT] = child; } /** * Retrieve the user data associated with the specified (sub)tree. * * @param Ptr to the node. * * @return Ptr to the user data if present ELSE @c NULL. */ void *BinaryTree_GetData(binarytree_t *tree) { treenode_t *n; if(!tree) return NULL; n = (treenode_t*) tree; return n->data; } /** * Set the user data assoicated with the specified (sub)tree. * * @param tree Ptr to the tree. * @param data Ptr to the user data. */ void BinaryTree_SetData(binarytree_t *tree, const void *data) { treenode_t *n; if(!tree) return; n = (treenode_t*) tree; n->data = (void*) data; } /** * Traverse a binary tree in Preorder. * * Make a callback for all nodes of the tree (including the root). * Traversal continues until all nodes have been visited or a callback * returns @c false; at which point traversal is aborted. * * @param tree Ptr to the (sub)tree to be traversed. * @param callback Function to call for each object of the tree. * @param data Used to pass additional data to func. * * @return @c true, iff all callbacks return @c true; */ boolean BinaryTree_PreOrder(binarytree_t *tree, boolean (C_DECL *callback) (binarytree_t *tree, void *data), void *data) { if(!tree) return true; return preOrder((treenode_t*) tree, callback, data); } /** * Traverse a binary tree in Inorder. * * Make a callback for all nodes of the tree (including the root). * Traversal continues until all nodes have been visited or a callback * returns @c false; at which point traversal is aborted. * * @param tree Ptr to the (sub)tree to be traversed. * @param callback Function to call for each object of the tree. * @param data Used to pass additional data to func. * * @return @c true, iff all callbacks return @c true; */ boolean BinaryTree_InOrder(binarytree_t *tree, boolean (C_DECL *callback) (binarytree_t *tree, void *data), void *data) { if(!tree) return true; return inOrder((treenode_t*) tree, callback, data); } /** * Traverse a binary tree in Postorder. * * Make a callback for all nodes of the tree (including the root). * Traversal continues until all nodes have been visited or a callback * returns @c false; at which point traversal is aborted. * * @param tree Ptr to the (sub)tree to be traversed. * @param callback Function to call for each object of the tree. * @param data Used to pass additional data to func. * * @return @c true, iff all callbacks return @c true; */ boolean BinaryTree_PostOrder(binarytree_t *tree, boolean (C_DECL *callback) (binarytree_t *tree, void *data), void *data) { if(!tree) return true; return postOrder((treenode_t*) tree, callback, data); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_surface.c0000644000175000017500000002757211357170242023061 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_surface.c: World surfaces. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Change the material to be used on the specified surface. * * @param suf Ptr to the surface to chage the material of. * @param mat Ptr to the material to change to. * @return @c true, if changed successfully. */ boolean Surface_SetMaterial(surface_t* suf, material_t* mat) { if(!suf || !mat) return false; if(suf->material == mat) return true; // No longer a missing texture fix? if(mat && (suf->oldFlags & SUIF_MATERIAL_FIX)) suf->inFlags &= ~SUIF_MATERIAL_FIX; suf->material = mat; suf->inFlags |= SUIF_UPDATE_DECORATIONS; suf->oldFlags = suf->inFlags; return true; } /** * Update the surface, material X offset. * * @param suf The surface to be updated. * @param x Material offset, X delta. * * @return @c true, if the change was made successfully. */ boolean Surface_SetMaterialOffsetX(surface_t* suf, float x) { if(!suf) return false; if(suf->offset[VX] == x) return true; suf->offset[VX] = x; suf->inFlags |= SUIF_UPDATE_DECORATIONS; if(!ddMapSetup) R_SurfaceListAdd(movingSurfaceList, suf); return true; } /** * Update the surface, material Y offset. * * @param suf The surface to be updated. * @param y Material offset, Y delta. * * @return @c true, if the change was made successfully. */ boolean Surface_SetMaterialOffsetY(surface_t* suf, float y) { if(!suf) return false; if(suf->offset[VY] == y) return true; suf->offset[VY] = y; suf->inFlags |= SUIF_UPDATE_DECORATIONS; if(!ddMapSetup) R_SurfaceListAdd(movingSurfaceList, suf); return true; } /** * Update the surface, material X+Y offset. * * @param suf The surface to be updated. * @param x Material offset, X delta. * @param y Material offset, Y delta. * * @return @c true, if the change was made successfully. */ boolean Surface_SetMaterialOffsetXY(surface_t* suf, float x, float y) { if(!suf) return false; if(suf->offset[VX] == x && suf->offset[VY] == y) return true; suf->offset[VX] = x; suf->offset[VY] = y; suf->inFlags |= SUIF_UPDATE_DECORATIONS; if(!ddMapSetup) R_SurfaceListAdd(movingSurfaceList, suf); return true; } /** * Update the surface, red color component. */ boolean Surface_SetColorR(surface_t* suf, float r) { if(!suf) return false; r = MINMAX_OF(0, r, 1); if(suf->rgba[CR] == r) return true; // \todo when surface colours are intergrated with the // bias lighting model we will need to recalculate the // vertex colours when they are changed. suf->rgba[CR] = r; return true; } /** * Update the surface, green color component. */ boolean Surface_SetColorG(surface_t* suf, float g) { if(!suf) return false; g = MINMAX_OF(0, g, 1); if(suf->rgba[CG] == g) return true; // \todo when surface colours are intergrated with the // bias lighting model we will need to recalculate the // vertex colours when they are changed. suf->rgba[CG] = g; return true; } /** * Update the surface, blue color component. */ boolean Surface_SetColorB(surface_t* suf, float b) { if(!suf) return false; b = MINMAX_OF(0, b, 1); if(suf->rgba[CB] == b) return true; // \todo when surface colours are intergrated with the // bias lighting model we will need to recalculate the // vertex colours when they are changed. suf->rgba[CB] = b; return true; } /** * Update the surface, alpha. */ boolean Surface_SetColorA(surface_t* suf, float a) { if(!suf) return false; a = MINMAX_OF(0, a, 1); if(suf->rgba[CA] == a) return true; // \todo when surface colours are intergrated with the // bias lighting model we will need to recalculate the // vertex colours when they are changed. suf->rgba[CA] = a; return true; } /** * Update the surface, color. */ boolean Surface_SetColorRGBA(surface_t* suf, float r, float g, float b, float a) { if(!suf) return false; r = MINMAX_OF(0, r, 1); g = MINMAX_OF(0, g, 1); b = MINMAX_OF(0, b, 1); a = MINMAX_OF(0, a, 1); if(suf->rgba[CR] == r && suf->rgba[CG] == g && suf->rgba[CB] == b && suf->rgba[CA] == a) return true; // \todo when surface colours are intergrated with the // bias lighting model we will need to recalculate the // vertex colours when they are changed. suf->rgba[CR] = r; suf->rgba[CG] = g; suf->rgba[CB] = b; suf->rgba[CA] = a; return true; } /** * Update the surface, blendmode. */ boolean Surface_SetBlendMode(surface_t* suf, blendmode_t blendMode) { if(!suf) return false; if(suf->blendMode == blendMode) return true; suf->blendMode = blendMode; return true; } /** * Mark the surface as requiring a full update. Called during engine-reset. */ void Surface_Update(surface_t* suf) { if(!suf) return; suf->inFlags |= SUIF_UPDATE_DECORATIONS; } /** * Update the surface, property is selected by DMU_* name. */ boolean Surface_SetProperty(surface_t* suf, const setargs_t* args) { switch(args->prop) { case DMU_BLENDMODE: { blendmode_t blendMode; DMU_SetValue(DMT_SURFACE_BLENDMODE, &blendMode, args, 0); Surface_SetBlendMode(suf, blendMode); } break; case DMU_FLAGS: DMU_SetValue(DMT_SURFACE_FLAGS, &suf->flags, args, 0); break; case DMU_COLOR: { float rgb[3]; DMU_SetValue(DMT_SURFACE_RGBA, &rgb[CR], args, 0); DMU_SetValue(DMT_SURFACE_RGBA, &rgb[CG], args, 1); DMU_SetValue(DMT_SURFACE_RGBA, &rgb[CB], args, 2); Surface_SetColorR(suf, rgb[CR]); Surface_SetColorG(suf, rgb[CG]); Surface_SetColorB(suf, rgb[CB]); } break; case DMU_COLOR_RED: { float r; DMU_SetValue(DMT_SURFACE_RGBA, &r, args, 0); Surface_SetColorR(suf, r); } break; case DMU_COLOR_GREEN: { float g; DMU_SetValue(DMT_SURFACE_RGBA, &g, args, 0); Surface_SetColorG(suf, g); } break; case DMU_COLOR_BLUE: { float b; DMU_SetValue(DMT_SURFACE_RGBA, &b, args, 0); Surface_SetColorB(suf, b); } break; case DMU_ALPHA: { float a; DMU_SetValue(DMT_SURFACE_RGBA, &a, args, 0); Surface_SetColorA(suf, a); } break; case DMU_MATERIAL: { material_t* mat; DMU_SetValue(DMT_SURFACE_MATERIAL, &mat, args, 0); Surface_SetMaterial(suf, mat); } break; case DMU_OFFSET_X: { float offX; DMU_SetValue(DMT_SURFACE_OFFSET, &offX, args, 0); Surface_SetMaterialOffsetX(suf, offX); } break; case DMU_OFFSET_Y: { float offY; DMU_SetValue(DMT_SURFACE_OFFSET, &offY, args, 0); Surface_SetMaterialOffsetY(suf, offY); } break; case DMU_OFFSET_XY: { float offset[2]; DMU_SetValue(DMT_SURFACE_OFFSET, &offset[VX], args, 0); DMU_SetValue(DMT_SURFACE_OFFSET, &offset[VY], args, 1); Surface_SetMaterialOffsetXY(suf, offset[VX], offset[VY]); } break; default: Con_Error("Surface_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } /** * Get the value of a surface property, selected by DMU_* name. */ boolean Surface_GetProperty(const surface_t *suf, setargs_t *args) { switch(args->prop) { case DMU_MATERIAL: { material_t* mat = suf->material; if(suf->inFlags & SUIF_MATERIAL_FIX) mat = NULL; DMU_GetValue(DMT_SURFACE_MATERIAL, &mat, args, 0); break; } case DMU_OFFSET_X: DMU_GetValue(DMT_SURFACE_OFFSET, &suf->offset[VX], args, 0); break; case DMU_OFFSET_Y: DMU_GetValue(DMT_SURFACE_OFFSET, &suf->offset[VY], args, 0); break; case DMU_OFFSET_XY: DMU_GetValue(DMT_SURFACE_OFFSET, &suf->offset[VX], args, 0); DMU_GetValue(DMT_SURFACE_OFFSET, &suf->offset[VY], args, 1); break; case DMU_NORMAL_X: DMU_GetValue(DMT_SURFACE_NORMAL, &suf->normal[VX], args, 0); break; case DMU_NORMAL_Y: DMU_GetValue(DMT_SURFACE_NORMAL, &suf->normal[VY], args, 0); break; case DMU_NORMAL_Z: DMU_GetValue(DMT_SURFACE_NORMAL, &suf->normal[VZ], args, 0); break; case DMU_NORMAL_XYZ: DMU_GetValue(DMT_SURFACE_NORMAL, &suf->normal[VX], args, 0); DMU_GetValue(DMT_SURFACE_NORMAL, &suf->normal[VY], args, 1); DMU_GetValue(DMT_SURFACE_NORMAL, &suf->normal[VZ], args, 2); break; case DMU_COLOR: DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CR], args, 0); DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CG], args, 1); DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CB], args, 2); DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CA], args, 2); break; case DMU_COLOR_RED: DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CR], args, 0); break; case DMU_COLOR_GREEN: DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CG], args, 0); break; case DMU_COLOR_BLUE: DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CB], args, 0); break; case DMU_ALPHA: DMU_GetValue(DMT_SURFACE_RGBA, &suf->rgba[CA], args, 0); break; case DMU_BLENDMODE: DMU_GetValue(DMT_SURFACE_BLENDMODE, &suf->blendMode, args, 0); break; case DMU_FLAGS: DMU_GetValue(DMT_SURFACE_FLAGS, &suf->flags, args, 0); break; default: Con_Error("Surface_GetProperty: No property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/b_util.c0000644000175000017500000004216111357170241022356 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_util.c: Bindings-related Utility Functions */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_misc.h" #include "b_main.h" #include "b_util.h" #include "b_context.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- boolean B_ParseToggleState(const char* toggleName, ebstate_t* state) { if(!strlen(toggleName) || !strcasecmp(toggleName, "down")) { *state = EBTOG_DOWN; // this is the default, if omitted return true; } if(!strcasecmp(toggleName, "undefined")) { *state = EBTOG_UNDEFINED; return true; } if(!strcasecmp(toggleName, "repeat")) { *state = EBTOG_REPEAT; return true; } if(!strcasecmp(toggleName, "press")) { *state = EBTOG_PRESS; return true; } if(!strcasecmp(toggleName, "up")) { *state = EBTOG_UP; return true; } Con_Message("B_ParseToggleState: \"%s\" is not a toggle state.\n", toggleName); return false; // Not recognized. } boolean B_ParseAxisPosition(const char* desc, ebstate_t* state, float* pos) { if(!strncasecmp(desc, "within", 6) && strlen(desc) > 6) { *state = EBAXIS_WITHIN; *pos = strtod(desc + 6, NULL); } else if(!strncasecmp(desc, "beyond", 6) && strlen(desc) > 6) { *state = EBAXIS_BEYOND; *pos = strtod(desc + 6, NULL); } else if(!strncasecmp(desc, "pos", 3) && strlen(desc) > 3) { *state = EBAXIS_BEYOND_POSITIVE; *pos = strtod(desc + 3, NULL); } else if(!strncasecmp(desc, "neg", 3) && strlen(desc) > 3) { *state = EBAXIS_BEYOND_NEGATIVE; *pos = -strtod(desc + 3, NULL); } else { Con_Message("B_ParseAxisPosition: Axis position \"%s\" is invalid.\n", desc); return false; } return true; } boolean B_ParseModifierId(const char* desc, int* id) { *id = strtoul(desc, NULL, 10) - 1 + CTL_MODIFIER_1; if(*id < CTL_MODIFIER_1 || *id > CTL_MODIFIER_4) { // Out of range. return false; } return true; } boolean B_ParseKeyId(const char* desc, int* id) { // The possibilies: symbolic key name, or "codeNNN". if(!strncasecmp(desc, "code", 4) && strlen(desc) == 7) { if(desc[4] == 'x' || desc[4] == 'X') { // Hexadecimal. *id = strtoul(desc + 5, NULL, 16); } else { // Decimal. *id = strtoul(desc + 4, NULL, 10); if(*id <= 0 || *id > 255) { Con_Message("B_ParseKeyId: Key code %i out of range.\n", *id); return false; } } } else { // Symbolic key name. *id = B_KeyForShortName(desc); if(!*id) { Con_Message("B_ParseKeyId: Unknown key \"%s\".\n", desc); return false; } } return true; } boolean B_ParseMouseTypeAndId(const char* desc, ddeventtype_t* type, int* id) { // Maybe it's one of the buttons? *id = I_GetKeyByName(I_GetDevice(IDEV_MOUSE, false), desc); if(*id >= 0) { // Got it. *type = E_TOGGLE; return true; } if(!strncasecmp(desc, "button", 6) && strlen(desc) > 6) // generic button { *type = E_TOGGLE; *id = strtoul(desc + 6, NULL, 10) - 1; if(*id < 0 || *id >= I_GetDevice(IDEV_MOUSE, false)->numKeys) { Con_Message("B_ParseMouseTypeAndId: Button %i does not exist.\n", *id); return false; } } else { // Try to find the axis. *type = E_AXIS; *id = I_GetAxisByName(I_GetDevice(IDEV_MOUSE, false), desc); if(*id < 0) { Con_Message("B_ParseMouseTypeAndId: Axis \"%s\" is not defined.\n", desc); return false; } } return true; } boolean B_ParseJoystickTypeAndId(uint device, const char* desc, ddeventtype_t* type, int* id) { if(!strncasecmp(desc, "button", 6) && strlen(desc) > 6) { *type = E_TOGGLE; *id = strtoul(desc + 6, NULL, 10) - 1; if(*id < 0 || *id >= I_GetDevice(device, false)->numKeys) { Con_Message("B_ParseJoystickTypeAndId: Button %i does not exist in joystick.\n", *id); return false; } } else if(!strncasecmp(desc, "hat", 3) && strlen(desc) > 3) { *type = E_ANGLE; *id = strtoul(desc + 3, NULL, 10) - 1; if(*id < 0 || *id >= I_GetDevice(device, false)->numHats) { Con_Message("B_ParseJoystickTypeAndId: Hat %i does not exist in joystick.\n", *id); return false; } } else if(!strcasecmp(desc, "hat")) { *type = E_ANGLE; *id = 0; } else { // Try to find the axis. *type = E_AXIS; *id = I_GetAxisByName(I_GetDevice(device, false), desc); if(*id < 0) { Con_Message("B_ParseJoystickTypeAndId: Axis \"%s\" is not defined in joystick.\n", desc); return false; } } return true; } boolean B_ParseAnglePosition(const char* desc, float* pos) { if(!strcasecmp(desc, "center")) { *pos = -1; } else if(!strncasecmp(desc, "angle", 5) && strlen(desc) > 5) { *pos = strtod(desc + 5, NULL); } else { Con_Message("B_ParseAnglePosition: Angle position \"%s\" invalid.\n", desc); return false; } return true; } /** * Parse a state condition. */ boolean B_ParseStateCondition(statecondition_t* cond, const char* desc) { boolean successful = false; ddstring_t* str = Str_New(); ddeventtype_t type; // First, we expect to encounter a device name. desc = Str_CopyDelim(str, desc, '-'); if(!Str_CompareIgnoreCase(str, "modifier")) { cond->device = 0; // not used cond->type = SCT_MODIFIER_STATE; // Parse the modifier number. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseModifierId(Str_Text(str), &cond->id)) { goto parseEnded; } // The final part of a modifier is the state. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseToggleState(Str_Text(str), &cond->state)) { goto parseEnded; } } else if(!Str_CompareIgnoreCase(str, "key")) { cond->device = IDEV_KEYBOARD; cond->type = SCT_TOGGLE_STATE; // Parse the key. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseKeyId(Str_Text(str), &cond->id)) { goto parseEnded; } // The final part of a key event is the state of the key toggle. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseToggleState(Str_Text(str), &cond->state)) { goto parseEnded; } } else if(!Str_CompareIgnoreCase(str, "mouse")) { cond->device = IDEV_MOUSE; // What is being targeted? desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseMouseTypeAndId(Str_Text(str), &type, &cond->id)) { goto parseEnded; } desc = Str_CopyDelim(str, desc, '-'); if(type == E_TOGGLE) { cond->type = SCT_TOGGLE_STATE; if(!B_ParseToggleState(Str_Text(str), &cond->state)) { goto parseEnded; } } else if(type == E_AXIS) { cond->type = SCT_AXIS_BEYOND; if(!B_ParseAxisPosition(Str_Text(str), &cond->state, &cond->pos)) { goto parseEnded; } } } else if(!Str_CompareIgnoreCase(str, "joy")) { cond->device = IDEV_JOY1; // What is being targeted? desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseJoystickTypeAndId(cond->device, Str_Text(str), &type, &cond->id)) { goto parseEnded; } desc = Str_CopyDelim(str, desc, '-'); if(type == E_TOGGLE) { cond->type = SCT_TOGGLE_STATE; if(!B_ParseToggleState(Str_Text(str), &cond->state)) { goto parseEnded; } } else if(type == E_AXIS) { cond->type = SCT_AXIS_BEYOND; if(!B_ParseAxisPosition(Str_Text(str), &cond->state, &cond->pos)) { goto parseEnded; } } else // Angle. { cond->type = SCT_ANGLE_AT; if(!B_ParseAnglePosition(Str_Text(str), &cond->pos)) { goto parseEnded; } } } else { Con_Message("B_ParseEvent: Device \"%s\" unknown.\n", Str_Text(str)); goto parseEnded; } // Check for valid toggle states. if(cond->type == SCT_TOGGLE_STATE && cond->state != EBTOG_UP && cond->state != EBTOG_DOWN) { Con_Message("B_ParseStateCondition: \"%s\": Toggle condition can only be 'up' or 'down'.\n", desc); goto parseEnded; } // Finally, there may be the negation at the end. desc = Str_CopyDelim(str, desc, '-'); if(!Str_CompareIgnoreCase(str, "not")) { cond->negate = true; } // Anything left that wasn't used? if(desc) { Con_Message("B_ParseStateCondition: Unrecognized \"%s\".\n", desc); goto parseEnded; } // No errors detected. successful = true; parseEnded: Str_Delete(str); return successful; } boolean B_CheckAxisPos(ebstate_t test, float testPos, float pos) { switch(test) { case EBAXIS_WITHIN: if((pos > 0 && pos > testPos) || (pos < 0 && pos < -testPos)) return false; break; case EBAXIS_BEYOND: if(!((pos > 0 && pos >= testPos) || (pos < 0 && pos <= -testPos))) return false; break; case EBAXIS_BEYOND_POSITIVE: if(pos < testPos) return false; break; case EBAXIS_BEYOND_NEGATIVE: if(pos > -testPos) return false; break; default: return false; } return true; } boolean B_CheckCondition(statecondition_t* cond, int localNum, bcontext_t* context) { boolean fulfilled = !cond->negate; inputdev_t* dev = I_GetDevice(cond->device, false); switch(cond->type) { case SCT_MODIFIER_STATE: if(context) { // Evaluate the current state of the modifier (in this context). float pos = 0, relative = 0; dbinding_t* binds = &B_GetControlBinding(context, cond->id)->deviceBinds[localNum]; B_EvaluateDeviceBindingList(localNum, binds, &pos, &relative, context); if((cond->state == EBTOG_DOWN && fabs(pos) > .5) || (cond->state == EBTOG_UP && fabs(pos) < .5)) return fulfilled; } break; case SCT_TOGGLE_STATE: { int isDown = (dev->keys[cond->id].isDown != 0); if((isDown && cond->state == EBTOG_DOWN) || (!isDown && cond->state == EBTOG_UP)) return fulfilled; break; } case SCT_AXIS_BEYOND: if(B_CheckAxisPos(cond->state, cond->pos, dev->axes[cond->id].position)) return fulfilled; break; case SCT_ANGLE_AT: if(dev->hats[cond->id].pos == cond->pos) return fulfilled; break; } return !fulfilled; } void B_AppendDeviceDescToString(uint device, ddeventtype_t type, int id, ddstring_t* str) { inputdev_t* dev = I_GetDevice(device, false); const char* name; if(type != E_SYMBOLIC) { // Name of the device. Str_Append(str, dev->name); Str_Append(str, "-"); } switch(type) { case E_TOGGLE: if(dev->keys[id].name) { Str_Append(str, dev->keys[id].name); } else if(device == IDEV_KEYBOARD) { name = B_ShortNameForKey(id); if(name) Str_Append(str, name); else Str_Appendf(str, "code%03i", id); } else Str_Appendf(str, "button%i",id + 1); break; case E_AXIS: Str_Append(str, dev->axes[id].name); break; case E_ANGLE: Str_Appendf(str, "hat%i", id + 1); break; case E_SYMBOLIC: Str_Append(str, "sym"); break; default: Con_Error("B_AppendDeviceDescToString: Invalid value, type = %i.", (int) type); break; } } void B_AppendToggleStateToString(ebstate_t state, ddstring_t* str) { if(state == EBTOG_UNDEFINED) Str_Append(str, "-undefined"); if(state == EBTOG_DOWN) Str_Append(str, "-down"); if(state == EBTOG_REPEAT) Str_Append(str, "-repeat"); if(state == EBTOG_PRESS) Str_Append(str, "-press"); if(state == EBTOG_UP) Str_Append(str, "-up"); } void B_AppendAxisPositionToString(ebstate_t state, float pos, ddstring_t* str) { if(state == EBAXIS_WITHIN) Str_Appendf(str, "-within%g", pos); else if(state == EBAXIS_BEYOND) Str_Appendf(str, "-beyond%g", pos); else if(state == EBAXIS_BEYOND_POSITIVE) Str_Appendf(str, "-pos%g", pos); else Str_Appendf(str, "-neg%g", -pos); } void B_AppendAnglePositionToString(float pos, ddstring_t* str) { if(pos < 0) Str_Append(str, "-center"); else Str_Appendf(str, "-angle%g", pos); } /** * @param str The condition in textual format is appended here. */ void B_AppendConditionToString(const statecondition_t* cond, ddstring_t* str) { if(cond->type == SCT_MODIFIER_STATE) { Str_Appendf(str, "modifier-%i", cond->id - CTL_MODIFIER_1 + 1); } else { B_AppendDeviceDescToString(cond->device, cond->type == SCT_TOGGLE_STATE? E_TOGGLE : cond->type == SCT_AXIS_BEYOND? E_AXIS : E_ANGLE, cond->id, str); } if(cond->type == SCT_TOGGLE_STATE || cond->type == SCT_MODIFIER_STATE) { B_AppendToggleStateToString(cond->state, str); } else if(cond->type == SCT_AXIS_BEYOND) { B_AppendAxisPositionToString(cond->state, cond->pos, str); } else if(cond->type == SCT_ANGLE_AT) { B_AppendAnglePositionToString(cond->pos, str); } // Flags. if(cond->negate) { Str_Append(str, "-not"); } } /** * @param str The event in textual format is appended here. */ void B_AppendEventToString(const ddevent_t* ev, ddstring_t* str) { B_AppendDeviceDescToString(ev->device, ev->type, ev->type == E_TOGGLE? ev->toggle.id : ev->type == E_AXIS? ev->axis.id : ev->type == E_ANGLE? ev->angle.id : ev->type == E_SYMBOLIC? ev->symbolic.id : 0, str); switch(ev->type) { case E_TOGGLE: B_AppendToggleStateToString(ev->toggle.state == ETOG_DOWN? EBTOG_DOWN : ev->toggle.state == ETOG_UP? EBTOG_UP : EBTOG_REPEAT, str); break; case E_AXIS: B_AppendAxisPositionToString(ev->axis.pos >= 0? EBAXIS_BEYOND_POSITIVE : EBAXIS_BEYOND_NEGATIVE, ev->axis.pos, str); break; case E_ANGLE: B_AppendAnglePositionToString(ev->angle.pos, str); break; case E_SYMBOLIC: Str_Appendf(str, "-%s", ev->symbolic.name); break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/edit_bias.c0000644000175000017500000007244011357170242023027 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * edit_bias.c: Bias light source editor. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_edit.h" #include "de_system.h" #include "de_render.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_misc.h" #include "de_ui.h" #include "de_console.h" #include "de_play.h" #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(BLEditor); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void SBE_MenuSave(ui_object_t *ob); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int gameDrawHUD; extern int numSources; extern byte freezeRLs; // PUBLIC DATA DEFINITIONS ------------------------------------------------- const char *saveFile = NULL; static ui_page_t page_bias; static ui_object_t ob_bias[] = { // bias editor page {UI_BUTTON, 0, UIF_DEFAULT, 400, 450, 180, 70, "Save", UIButton_Drawer, UIButton_Responder, 0, SBE_MenuSave}, {UI_NONE} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ /** * Editing variables: * * edit-bias-blink: keep blinking the nearest light (unless a light is grabbed) * edit-bias-grab-distance: how far the light is when grabbed * edit-bias-{red,green,blue,intensity}: RGBI of the light */ static int editBlink = false; static float editDistance = 300; static float editColor[3]; static float editIntensity; /** * Editor status. */ static int editActive = false; // Edit mode active? static int editGrabbed = -1; static int editHidden = false; static int editShowAll = false; static int editShowIndices = true; static int editHueCircle = false; static float hueDistance = 100; static vec3_t hueOrigin, hueSide, hueUp; // CODE -------------------------------------------------------------------- /** * Register console variables for Shadow Bias. */ void SBE_Register(void) { // Editing variables. C_VAR_FLOAT("edit-bias-grab-distance", &editDistance, 0, 10, 1000); C_VAR_FLOAT("edit-bias-red", &editColor[0], CVF_NO_ARCHIVE, 0, 1); C_VAR_FLOAT("edit-bias-green", &editColor[1], CVF_NO_ARCHIVE, 0, 1); C_VAR_FLOAT("edit-bias-blue", &editColor[2], CVF_NO_ARCHIVE, 0, 1); C_VAR_FLOAT("edit-bias-intensity", &editIntensity, CVF_NO_ARCHIVE, 1, 50000); C_VAR_INT("edit-bias-blink", &editBlink, 0, 0, 1); C_VAR_INT("edit-bias-hide", &editHidden, 0, 0, 1); C_VAR_INT("edit-bias-show-sources", &editShowAll, 0, 0, 1); C_VAR_INT("edit-bias-show-indices", &editShowIndices, 0, 0, 1); // Commands for light editing. C_CMD_FLAGS("bledit", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blquit", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blclear", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blsave", NULL, BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blnew", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("bldel", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("bllock", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blunlock", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blgrab", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("bldup", "", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blc", "fff", BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("bli", NULL, BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blhue", NULL, BLEditor, CMDF_NO_DEDICATED); C_CMD_FLAGS("blmenu", "", BLEditor, CMDF_NO_DEDICATED); } /** * Editor Functionality: */ static void SBE_GetHand(float pos[3]) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); pos[0] = vx + viewData->frontVec[VX] * editDistance; pos[1] = vz + viewData->frontVec[VZ] * editDistance; pos[2] = vy + viewData->frontVec[VY] * editDistance; } static source_t *SBE_GrabSource(int index) { source_t *s; int i; editGrabbed = index; s = SB_GetSource(index); // Update the property cvars. editIntensity = s->primaryIntensity; for(i = 0; i < 3; ++i) editColor[i] = s->color[i]; return s; } static source_t *SBE_GetGrabbed(void) { if(editGrabbed >= 0 && editGrabbed < numSources) { return SB_GetSource(editGrabbed); } return NULL; } static source_t *SBE_GetNearest(void) { float hand[3]; source_t *nearest = NULL, *s; float minDist = 0, len; int i; SBE_GetHand(hand); s = SB_GetSource(0); for(i = 0; i < numSources; ++i, s++) { len = M_Distance(hand, s->pos); if(i == 0 || len < minDist) { minDist = len; nearest = s; } } return nearest; } static void SBE_GetHueColor(float *color, float *angle, float *sat) { int i; float dot; float saturation, hue, scale; float minAngle = 0.1f, range = 0.19f; vec3_t h, proj; const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); dot = M_DotProduct(viewData->frontVec, hueOrigin); saturation = (acos(dot) - minAngle) / range; if(saturation < 0) saturation = 0; if(saturation > 1) saturation = 1; if(sat) *sat = saturation; if(saturation == 0 || dot > .999f) { if(angle) *angle = 0; if(sat) *sat = 0; R_HSVToRGB(color, 0, 0, 1); return; } // Calculate hue angle by projecting the current viewfront to the // hue circle plane. Project onto the normal and subtract. scale = M_DotProduct(viewData->frontVec, hueOrigin) / M_DotProduct(hueOrigin, hueOrigin); M_Scale(h, hueOrigin, scale); for(i = 0; i < 3; ++i) proj[i] = viewData->frontVec[i] - h[i]; // Now we have the projected view vector on the circle's plane. // Normalize the projected vector. M_Normalize(proj); hue = acos(M_DotProduct(proj, hueUp)); if(M_DotProduct(proj, hueSide) > 0) hue = 2*PI - hue; hue /= (float) (2*PI); hue += 0.25; if(angle) *angle = hue; //Con_Printf("sat=%f, hue=%f\n", saturation, hue); R_HSVToRGB(color, hue, saturation, 1); } void SBE_EndFrame(void) { source_t *src; // Update the grabbed light. if(editActive && (src = SBE_GetGrabbed()) != NULL) { source_t old; memcpy(&old, src, sizeof(old)); if(editHueCircle) { // Get the new color from the circle. SBE_GetHueColor(editColor, NULL, NULL); } SB_SetColor(src->color, editColor); src->primaryIntensity = src->intensity = editIntensity; if(!(src->flags & BLF_LOCKED)) { // Update source properties. SBE_GetHand(src->pos); } if(memcmp(&old, src, sizeof(old))) { // The light must be re-evaluated. src->flags |= BLF_CHANGED; } } } static void SBE_Begin(void) { // Advise the game not to draw any HUD displays gameDrawHUD = false; editActive = true; editGrabbed = -1; Con_Printf("Bias light editor: ON\n"); } static void SBE_End(void) { // Advise the game it can safely draw any HUD displays again gameDrawHUD = true; editActive = false; Con_Printf("Bias light editor: OFF\n"); } static boolean SBE_New(void) { source_t *s; if(numSources == MAX_BIAS_LIGHTS) return false; s = SBE_GrabSource(numSources); s->flags &= ~BLF_LOCKED; s->flags |= BLF_COLOR_OVERRIDE; editIntensity = 200; editColor[0] = editColor[1] = editColor[2] = 1; numSources++; return true; } static void SBE_Clear(void) { SB_Clear(); editGrabbed = -1; SBE_New(); } static void SBE_Delete(int which) { if(editGrabbed == which) editGrabbed = -1; else if(editGrabbed > which) editGrabbed--; SB_Delete(which); } static void SBE_Lock(int which) { SB_GetSource(which)->flags |= BLF_LOCKED; } static void SBE_Unlock(int which) { SB_GetSource(which)->flags &= ~BLF_LOCKED; } static void SBE_Grab(int which) { if(editGrabbed != which) SBE_GrabSource(which); else editGrabbed = -1; } static void SBE_Dupe(int which) { source_t *orig = SB_GetSource(which); source_t *s; int i; if(SBE_New()) { s = SBE_GetGrabbed(); s->flags &= ~BLF_LOCKED; s->sectorLevel[0] = orig->sectorLevel[0]; s->sectorLevel[1] = orig->sectorLevel[1]; editIntensity = orig->primaryIntensity; for(i = 0; i < 3; ++i) editColor[i] = orig->color[i]; } } static boolean SBE_Save(const char *name) { int i; source_t *s; FILE *file; filename_t fileName; gamemap_t *map = P_GetCurrentMap(); const char *uid = P_GetUniqueMapID(map); if(!name) { sprintf(fileName, "%s.ded", P_GetMapID(map)); } else { strcpy(fileName, name); if(!strchr(fileName, '.')) { // Append the file name extension. strcat(fileName, ".ded"); } } Con_Printf("Saving to %s...\n", fileName); if((file = fopen(fileName, "wt")) == NULL) return false; fprintf(file, "# %i Bias Lights for %s\n\n", numSources, uid); // Since there can be quite a lot of these, make sure we'll skip // the ones that are definitely not suitable. fprintf(file, "SkipIf Not %s\n", (char *) gx.GetVariable(DD_GAME_MODE)); s = SB_GetSource(0); for(i = 0; i < numSources; ++i, ++s) { fprintf(file, "\nLight {\n"); fprintf(file, " Map = \"%s\"\n", uid); fprintf(file, " Origin { %g %g %g }\n", s->pos[0], s->pos[1], s->pos[2]); fprintf(file, " Color { %g %g %g }\n", s->color[0], s->color[1], s->color[2]); fprintf(file, " Intensity = %g\n", s->primaryIntensity); fprintf(file, " Sector levels { %g %g }\n", s->sectorLevel[0], s->sectorLevel[1]); fprintf(file, "}\n"); } fclose(file); return true; } void SBE_MenuSave(ui_object_t *ob) { SBE_Save(saveFile); } void SBE_SetHueCircle(boolean activate) { int i; if((signed) activate == editHueCircle) return; // No change in state. if(activate && SBE_GetGrabbed() == NULL) return; editHueCircle = activate; if(activate) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); // Determine the orientation of the hue circle. for(i = 0; i < 3; ++i) { hueOrigin[i] = viewData->frontVec[i]; hueSide[i] = viewData->sideVec[i]; hueUp[i] = viewData->upVec[i]; } } } /** * Returns true if the console player is currently using the HueCircle. */ boolean SBE_UsingHueCircle(void) { return (editActive && editHueCircle); } /* * Editor commands. */ D_CMD(BLEditor) { char *cmd = argv[0] + 2; int which; if(!stricmp(cmd, "edit")) { if(!editActive) { SBE_Begin(); return true; } return false; } if(!editActive) { Con_Printf("The bias light editor is not active.\n"); return false; } if(!stricmp(cmd, "quit")) { SBE_End(); return true; } if(!stricmp(cmd, "save")) { return SBE_Save(argc >= 2 ? argv[1] : NULL); } if(!stricmp(cmd, "clear")) { SBE_Clear(); return true; } if(!stricmp(cmd, "hue")) { int activate = (argc >= 2 ? stricmp(argv[1], "off") : !editHueCircle); SBE_SetHueCircle(activate); return true; } if(!stricmp(cmd, "new")) { return SBE_New(); } if(!stricmp(cmd, "menu")) { //extern int consolePlayer; //P_ControlReset(-1); // clear the actions array Con_Open(false); // close the console if open // show the bias menu interface UI_InitPage(&page_bias, ob_bias); sprintf(page_bias.title, "Doomsday BIAS Light Editor"); page_bias.background = false; // we don't want a background UI_Init(false, true, true, true, false); UI_SetPage(&page_bias); return true; } // Has the light index been given as an argument? if(editGrabbed >= 0) which = editGrabbed; else which = SB_ToIndex(SBE_GetNearest()); if(!stricmp(cmd, "c") && numSources > 0) { source_t *src = SB_GetSource(which); float r = 1, g = 1, b = 1; if(argc >= 4) { r = strtod(argv[1], NULL); g = strtod(argv[2], NULL); b = strtod(argv[3], NULL); } editColor[0] = r; editColor[1] = g; editColor[2] = b; SB_SetColor(src->color, editColor); src->flags |= BLF_CHANGED; return true; } if(!stricmp(cmd, "i") && numSources > 0) { source_t *src = SB_GetSource(which); if(argc >= 3) { src->sectorLevel[0] = strtod(argv[1], NULL) / 255.0f; if(src->sectorLevel[0] < 0) src->sectorLevel[0] = 0; else if(src->sectorLevel[0] > 1) src->sectorLevel[0] = 1; src->sectorLevel[1] = strtod(argv[2], NULL) / 255.0f; if(src->sectorLevel[1] < 0) src->sectorLevel[1] = 0; else if(src->sectorLevel[1] > 1) src->sectorLevel[1] = 1; } else if(argc >= 2) { editIntensity = strtod(argv[1], NULL); } src->primaryIntensity = src->intensity = editIntensity; src->flags |= BLF_CHANGED; return true; } if(argc > 1) { which = atoi(argv[1]); } if(which < 0 || which >= numSources) { Con_Printf("Invalid light index %i.\n", which); return false; } if(!stricmp(cmd, "del")) { SBE_Delete(which); return true; } if(!stricmp(cmd, "dup")) { SBE_Dupe(which); return true; } if(!stricmp(cmd, "lock")) { SBE_Lock(which); return true; } if(!stricmp(cmd, "unlock")) { SBE_Unlock(which); return true; } if(!stricmp(cmd, "grab")) { SBE_Grab(which); return true; } return false; } static void SBE_DrawBox(int x, int y, int w, int h, ui_color_t *c) { UI_GradientEx(x, y, w, h, 6, c ? c : UI_Color(UIC_BG_MEDIUM), c ? c : UI_Color(UIC_BG_LIGHT), .2f, .4f); UI_DrawRectEx(x, y, w, h, 6, false, c ? c : UI_Color(UIC_BRD_HI), NULL, .4f, -1); } static void SBE_InfoBox(source_t *s, int rightX, char *title, float alpha) { float eye[3]; int w = 16 + FR_TextWidth("R:0.000 G:0.000 B:0.000"); int th = FR_TextHeight("a"), h = th * 6 + 16; int x, y; char buf[80]; ui_color_t color; x = theWindow->width - 10 - w - rightX; y = theWindow->height - 10 - h; eye[0] = vx; eye[1] = vz; eye[2] = vy; color.red = s->color[0]; color.green = s->color[1]; color.blue = s->color[2]; SBE_DrawBox(x, y, w, h, &color); x += 8; y += 8 + th/2; // - index # // - locked status // - coordinates // - distance from eye // - intensity // - color UI_TextOutEx(title, x, y, false, true, UI_Color(UIC_TITLE), alpha); y += th; sprintf(buf, "# %03i %s", SB_ToIndex(s), s->flags & BLF_LOCKED ? "(lock)" : ""); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), alpha); y += th; sprintf(buf, "(%+06.0f,%+06.0f,%+06.0f)", s->pos[0], s->pos[1], s->pos[2]); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), alpha); y += th; sprintf(buf, "Distance:%-.0f", M_Distance(eye, s->pos)); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), alpha); y += th; sprintf(buf, "Intens:%-5.0f L:%3i/%3i", s->primaryIntensity, (int) (255.0f * s->sectorLevel[0]), (int) (255.0f * s->sectorLevel[1])); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), alpha); y += th; sprintf(buf, "R:%.3f G:%.3f B:%.3f", s->color[0], s->color[1], s->color[2]); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), alpha); y += th; } /* * Editor HUD */ static void SBE_DrawLevelGauge(int x, int y, int height) { static sector_t *lastSector = NULL; static float minLevel = 0, maxLevel = 0; sector_t *sector; int off = FR_TextWidth("000"); int secY, maxY = 0, minY = 0, p; char buf[80]; source_t *src; if(SBE_GetGrabbed()) src = SBE_GetGrabbed(); else src = SBE_GetNearest(); sector = R_PointInSubsector(src->pos[VX], src->pos[VY])->sector; if(lastSector != sector) { minLevel = maxLevel = sector->lightLevel; lastSector = sector; } if(sector->lightLevel < minLevel) minLevel = sector->lightLevel; if(sector->lightLevel > maxLevel) maxLevel = sector->lightLevel; glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); glColor4f(1, 1, 1, .5f); glVertex2f(x + off, y); glVertex2f(x + off, y + height); // Normal lightlevel. secY = y + height * (1.0f - sector->lightLevel); glVertex2f(x + off - 4, secY); glVertex2f(x + off, secY); if(maxLevel != minLevel) { // Max lightlevel. maxY = y + height * (1.0f - maxLevel); glVertex2f(x + off + 4, maxY); glVertex2f(x + off, maxY); // Min lightlevel. minY = y + height * (1.0f - minLevel); glVertex2f(x + off + 4, minY); glVertex2f(x + off, minY); } // Current min/max bias sector level. if(src->sectorLevel[0] > 0 || src->sectorLevel[1] > 0) { glColor3f(1, 0, 0); p = y + height * (1.0f - src->sectorLevel[0]); glVertex2f(x + off + 2, p); glVertex2f(x + off - 2, p); glColor3f(0, 1, 0); p = y + height * (1.0f - src->sectorLevel[1]); glVertex2f(x + off + 2, p); glVertex2f(x + off - 2, p); } glEnd(); glEnable(GL_TEXTURE_2D); // The number values. sprintf(buf, "%03i", (short) (255.0f * sector->lightLevel)); UI_TextOutEx(buf, x, secY, true, true, UI_Color(UIC_TITLE), .7f); if(maxLevel != minLevel) { sprintf(buf, "%03i", (short) (255.0f * maxLevel)); UI_TextOutEx(buf, x + 2*off, maxY, true, true, UI_Color(UIC_TEXT), .7f); sprintf(buf, "%03i", (short) (255.0f * minLevel)); UI_TextOutEx(buf, x + 2*off, minY, true, true, UI_Color(UIC_TEXT), .7f); } } void SBE_DrawHUD(void) { int w, h, y; char buf[80]; float alpha = .8f; gamemap_t *map = P_GetCurrentMap(); source_t *s; if(!editActive || editHidden) return; // Go into screen projection mode. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); // Overall stats: numSources / MAX (left) sprintf(buf, "%i / %i (%i free)", numSources, MAX_BIAS_LIGHTS, MAX_BIAS_LIGHTS - numSources); w = FR_TextWidth(buf) + 16; h = FR_TextHeight(buf) + 16; y = theWindow->height - 10 - h; SBE_DrawBox(10, y, w, h, 0); UI_TextOutEx(buf, 18, y + h / 2, false, true, UI_Color(UIC_TITLE), alpha); // The map ID. UI_TextOutEx(P_GetUniqueMapID(map), 18, y - h/2, false, true, UI_Color(UIC_TITLE), alpha); // Stats for nearest & grabbed: if(numSources) { s = SBE_GetNearest(); SBE_InfoBox(s, 0, SBE_GetGrabbed() ? "Nearest" : "Highlighted", alpha); } if((s = SBE_GetGrabbed()) != NULL) { SBE_InfoBox(s, FR_TextWidth("0") * 26, "Grabbed", alpha); } if(SBE_GetGrabbed() || SBE_GetNearest()) { SBE_DrawLevelGauge(20, theWindow->height/2 - 255/2, 255); } glMatrixMode(GL_PROJECTION); glPopMatrix(); } void SBE_DrawStar(float pos[3], float size, float color[4]) { float black[4] = { 0, 0, 0, 0 }; glBegin(GL_LINES); glColor4fv(black); glVertex3f(pos[VX] - size, pos[VZ], pos[VY]); glColor4fv(color); glVertex3f(pos[VX], pos[VZ], pos[VY]); glVertex3f(pos[VX], pos[VZ], pos[VY]); glColor4fv(black); glVertex3f(pos[VX] + size, pos[VZ], pos[VY]); glVertex3f(pos[VX], pos[VZ] - size, pos[VY]); glColor4fv(color); glVertex3f(pos[VX], pos[VZ], pos[VY]); glVertex3f(pos[VX], pos[VZ], pos[VY]); glColor4fv(black); glVertex3f(pos[VX], pos[VZ] + size, pos[VY]); glVertex3f(pos[VX], pos[VZ], pos[VY] - size); glColor4fv(color); glVertex3f(pos[VX], pos[VZ], pos[VY]); glVertex3f(pos[VX], pos[VZ], pos[VY]); glColor4fv(black); glVertex3f(pos[VX], pos[VZ], pos[VY] + size); glEnd(); } static void SBE_DrawIndex(source_t *src) { char buf[80]; float eye[3], scale; if(!editShowIndices) return; eye[0] = vx; eye[1] = vz; eye[2] = vy; scale = M_Distance(src->pos, eye) / (theWindow->width / 2); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(src->pos[VX], src->pos[VZ], src->pos[VY]); glRotatef(-vang + 180, 0, 1, 0); glRotatef(vpitch, 1, 0, 0); glScalef(-scale, -scale, 1); // Show the index number of the source. sprintf(buf, "%i", SB_ToIndex(src)); UI_TextOutEx(buf, 2, 2, false, false, UI_Color(UIC_TITLE), 1 - M_Distance(src->pos, eye)/2000); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); } static void SBE_DrawSource(source_t *src) { float col[4], d; float eye[3]; eye[0] = vx; eye[1] = vz; eye[2] = vy; col[0] = src->color[0]; col[1] = src->color[1]; col[2] = src->color[2]; d = (M_Distance(eye, src->pos) - 100) / 1000; if(d < 1) d = 1; col[3] = 1.0f / d; SBE_DrawStar(src->pos, 25 + src->intensity/20, col); SBE_DrawIndex(src); } static void SBE_HueOffset(double angle, float *offset) { offset[0] = cos(angle) * hueSide[VX] + sin(angle) * hueUp[VX]; offset[1] = sin(angle) * hueUp[VY]; offset[2] = cos(angle) * hueSide[VZ] + sin(angle) * hueUp[VZ]; } static void SBE_DrawHue(void) { vec3_t eye; vec3_t center, off, off2; float steps = 32, inner = 10, outer = 30, s; double angle; float color[4], sel[4], hue, saturation; int i; eye[0] = vx; eye[1] = vy; eye[2] = vz; glDisable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glDisable(GL_CULL_FACE); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(vx, vy, vz); glScalef(1, 1.0f/1.2f, 1); glTranslatef(-vx, -vy, -vz); // The origin of the circle. for(i = 0; i < 3; ++i) center[i] = eye[i] + hueOrigin[i] * hueDistance; // Draw the circle. glBegin(GL_QUAD_STRIP); for(i = 0; i <= steps; ++i) { angle = 2*PI * i/steps; // Calculate the hue color for this angle. R_HSVToRGB(color, i/steps, 1, 1); color[3] = .5f; SBE_HueOffset(angle, off); glColor4fv(color); glVertex3f(center[0] + outer * off[0], center[1] + outer * off[1], center[2] + outer * off[2]); // Saturation decreases in the center. color[0] = 1; color[1] = 1; color[2] = 1; color[3] = .15f; glColor4fv(color); glVertex3f(center[0] + inner * off[0], center[1] + inner * off[1], center[2] + inner * off[2]); } glEnd(); glBegin(GL_LINES); // Draw the current hue. SBE_GetHueColor(sel, &hue, &saturation); SBE_HueOffset(2*PI * hue, off); sel[3] = 1; if(saturation > 0) { glColor4fv(sel); glVertex3f(center[0] + outer * off[0], center[1] + outer * off[1], center[2] + outer * off[2]); glVertex3f(center[0] + inner * off[0], center[1] + inner * off[1], center[2] + inner * off[2]); } // Draw the edges. for(i = 0; i < steps; ++i) { SBE_HueOffset(2*PI * i/steps, off); SBE_HueOffset(2*PI * (i + 1)/steps, off2); // Calculate the hue color for this angle. R_HSVToRGB(color, i/steps, 1, 1); color[3] = 1; glColor4fv(color); glVertex3f(center[0] + outer * off[0], center[1] + outer * off[1], center[2] + outer * off[2]); glVertex3f(center[0] + outer * off2[0], center[1] + outer * off2[1], center[2] + outer * off2[2]); if(saturation > 0) { // Saturation decreases in the center. sel[3] = 1 - fabs(M_CycleIntoRange(hue - i/steps + .5f, 1) - .5f) * 2.5f; } else { sel[3] = 1; } glColor4fv(sel); s = inner + (outer - inner) * saturation; glVertex3f(center[0] + s * off[0], center[1] + s * off[1], center[2] + s * off[2]); glVertex3f(center[0] + s * off2[0], center[1] + s * off2[1], center[2] + s * off2[2]); } glEnd(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glEnable(GL_CULL_FACE); } void SBE_DrawCursor(void) { #define SET_COL(x, r, g, b, a) {x[0]=(r); x[1]=(g); x[2]=(b); x[3]=(a);} double t = Sys_GetRealTime()/100.0f; source_t *s; float hand[3]; float size = 10000, distance; float col[4], eye[3]; if(!editActive || !numSources || editHidden || freezeRLs) return; eye[0] = vx; eye[1] = vz; eye[2] = vy; if(editHueCircle && SBE_GetGrabbed()) SBE_DrawHue(); // The grabbed cursor blinks yellow. if(!editBlink || currentTimeSB & 0x80) SET_COL(col, 1.0f, 1.0f, .8f, .5f) else SET_COL(col, .7f, .7f, .5f, .4f) s = SBE_GetGrabbed(); if(!s) { // The nearest cursor phases blue. SET_COL(col, sin(t)*.2f, .2f + sin(t)*.15f, .9f + sin(t)*.3f, .8f - sin(t)*.2f) s = SBE_GetNearest(); } glDisable(GL_TEXTURE_2D); SBE_GetHand(hand); if((distance = M_Distance(s->pos, hand)) > 2 * editDistance) { // Show where it is. glDisable(GL_DEPTH_TEST); } SBE_DrawStar(s->pos, size, col); SBE_DrawIndex(s); // Show if the source is locked. if(s->flags & BLF_LOCKED) { float lock = 2 + M_Distance(eye, s->pos)/100; glColor4f(1, 1, 1, 1); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(s->pos[VX], s->pos[VZ], s->pos[VY]); glRotatef(t/2, 0, 0, 1); glRotatef(t, 1, 0, 0); glRotatef(t * 15, 0, 1, 0); glBegin(GL_LINES); glVertex3f(-lock, 0, -lock); glVertex3f(+lock, 0, -lock); glVertex3f(+lock, 0, -lock); glVertex3f(+lock, 0, +lock); glVertex3f(+lock, 0, +lock); glVertex3f(-lock, 0, +lock); glVertex3f(-lock, 0, +lock); glVertex3f(-lock, 0, -lock); glEnd(); glPopMatrix(); } if(SBE_GetNearest() != SBE_GetGrabbed() && SBE_GetGrabbed()) { glDisable(GL_DEPTH_TEST); SBE_DrawSource(SBE_GetNearest()); } // Show all sources? if(editShowAll) { int i; source_t *src; glDisable(GL_DEPTH_TEST); src = SB_GetSource(0); for(i = 0; i < numSources; ++i, src++) { if(s == src) continue; SBE_DrawSource(src); } } glEnable(GL_TEXTURE_2D); glEnable(GL_DEPTH_TEST); #undef SET_COL } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_bmap.c0000644000175000017500000013365111357170242022344 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_bmap.c: Blockmaps */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_system.h" #include "de_console.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_play.h" #include "de_misc.h" #include "de_ui.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct ssecmapblock_s { subsector_t** ssecs; } ssecmapblock_t; typedef struct bmapblock_s { linedef_t** lineDefs; linkmobj_t* mobjLinks; linkpolyobj_t* polyLinks; } bmapblock_t; typedef struct bmap_s { vec2_t bBox[2]; vec2_t blockSize; uint dimensions[2]; // In blocks. gridmap_t* gridmap; } bmap_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- byte bmapShowDebug = 0; // 1 = mobjs, 2 = linedefs, 3 = ssecs. float bmapDebugSize = 1.5f; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void P_BoxToBlockmapBlocks(blockmap_t* blockmap, uint blockBox[4], const arvec2_t box) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; vec2_t m[2]; m[0][VX] = MAX_OF(bmap->bBox[0][VX], box[0][VX]); m[1][VX] = MIN_OF(bmap->bBox[1][VX], box[1][VX]); m[0][VY] = MAX_OF(bmap->bBox[0][VY], box[0][VY]); m[1][VY] = MIN_OF(bmap->bBox[1][VY], box[1][VY]); blockBox[BOXLEFT] = MINMAX_OF(0, (m[0][VX] - bmap->bBox[0][VX]) / bmap->blockSize[VX], bmap->dimensions[0]); blockBox[BOXRIGHT] = MINMAX_OF(0, (m[1][VX] - bmap->bBox[0][VX]) / bmap->blockSize[VX], bmap->dimensions[0]); blockBox[BOXBOTTOM] = MINMAX_OF(0, (m[0][VY] - bmap->bBox[0][VY]) / bmap->blockSize[VY], bmap->dimensions[1]); blockBox[BOXTOP] = MINMAX_OF(0, (m[1][VY] - bmap->bBox[0][VY]) / bmap->blockSize[VY], bmap->dimensions[1]); } } /** * Given a world coordinate, output the blockmap block[x, y] it resides in. */ boolean P_ToBlockmapBlockIdx(blockmap_t* blockmap, uint dest[2], const pvec2_t pos) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; if(!(pos[VX] < bmap->bBox[0][VX] || pos[VX] >= bmap->bBox[1][VX] || pos[VY] < bmap->bBox[0][VY] || pos[VY] >= bmap->bBox[1][VY])) { dest[VX] = (pos[VX] - bmap->bBox[0][VX]) / bmap->blockSize[VX]; dest[VY] = (pos[VY] - bmap->bBox[0][VY]) / bmap->blockSize[VY]; return true; } return false; // Outside blockmap. } return false; // hmm... } static __inline int xToSSecBlockX(bmap_t* bmap, float x) { if(x >= bmap->bBox[0][VX] && x < bmap->bBox[1][VX]) return (x - bmap->bBox[0][VX]) / bmap->blockSize[VX]; return -1; } static __inline int yToSSecBlockY(bmap_t* bmap, float y) { if(y >= bmap->bBox[0][VY] && y < bmap->bBox[1][VY]) return (y - bmap->bBox[0][VY]) / bmap->blockSize[VY]; return -1; } static bmap_t* allocBmap(void) { return Z_Calloc(sizeof(bmap_t), PU_MAPSTATIC, 0); } blockmap_t* P_BlockmapCreate(const pvec2_t min, const pvec2_t max, uint width, uint height) { bmap_t* bmap = allocBmap(); V2_Copy(bmap->bBox[0], min); V2_Copy(bmap->bBox[1], max); bmap->dimensions[VX] = width; bmap->dimensions[VY] = height; V2_Set(bmap->blockSize, (bmap->bBox[1][VX] - bmap->bBox[0][VX]) / bmap->dimensions[VX], (bmap->bBox[1][VY] - bmap->bBox[0][VY]) / bmap->dimensions[VY]); bmap->gridmap = M_GridmapCreate(bmap->dimensions[VX], bmap->dimensions[VY], sizeof(bmapblock_t), PU_MAPSTATIC); VERBOSE(Con_Message ("P_BlockMapCreate: w=%i h=%i\n", bmap->dimensions[VX], bmap->dimensions[VY])); return (blockmap_t *) bmap; } void P_SSecBlockmapSetBlock(blockmap_t* blockmap, uint x, uint y, subsector_t** ssecs) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; ssecmapblock_t* block = M_GridmapGetBlock(bmap->gridmap, x, y, true); if(block) { block->ssecs = ssecs; } } } void P_BuildSubsectorBlockMap(gamemap_t* map) { #define BLKMARGIN 8 #define BLOCK_WIDTH 128 #define BLOCK_HEIGHT 128 typedef struct ssecnode_s { void* data; struct ssecnode_s* next; } ssecnode_t; typedef struct subsecmap_s { uint count; ssecnode_t* nodes; } ssecmap_t; uint startTime = Sys_GetRealTime(); int xl, xh, yl, yh, x, y; int subMapWidth, subMapHeight; uint i; ssecnode_t* iter, *next; ssecmap_t* bmap, *block; vec2_t bounds[2], blockSize, dims; blockmap_t* ssecBlockMap; subsector_t** ssecLinks; size_t totalLinks; // Setup the blockmap area to enclose the whole map, plus a margin // (margin is needed for a map that fits entirely inside one blockmap // cell). V2_Set(bounds[0], map->bBox[BOXLEFT] - BLKMARGIN, map->bBox[BOXBOTTOM] - BLKMARGIN); V2_Set(bounds[1], map->bBox[BOXRIGHT] + BLKMARGIN, map->bBox[BOXTOP] + BLKMARGIN); // Select a good size for the blocks. V2_Set(blockSize, MAPBLOCKUNITS, MAPBLOCKUNITS); V2_Subtract(dims, bounds[1], bounds[0]); // Calculate the dimensions of the blockmap. if(dims[VX] <= blockSize[VX]) subMapWidth = 1; else subMapWidth = ceil(dims[VX] / blockSize[VX]); if(dims[VY] <= blockSize[VY]) subMapHeight = 1; else subMapHeight = ceil(dims[VY] / blockSize[VY]); // Adjust the max bound so we have whole blocks. V2_Set(bounds[1], bounds[0][VX] + subMapWidth * blockSize[VX], bounds[0][VY] + subMapHeight * blockSize[VY]); ssecBlockMap = (blockmap_t*) P_BlockmapCreate(bounds[0], bounds[1], subMapWidth, subMapHeight); // We'll construct the temporary links using nodes. bmap = M_Calloc(sizeof(ssecmap_t) * subMapWidth * subMapHeight); // Process all the subsectors in the map. totalLinks = 0; for(i = 0; i < map->numSSectors; ++i) { subsector_t* ssec = &map->ssectors[i]; if(!ssec->sector) continue; // Blockcoords to link to. xl = xToSSecBlockX((bmap_t*)ssecBlockMap, ssec->bBox[0].pos[VX]); xh = xToSSecBlockX((bmap_t*)ssecBlockMap, ssec->bBox[1].pos[VX]); yl = yToSSecBlockY((bmap_t*)ssecBlockMap, ssec->bBox[0].pos[VY]); yh = yToSSecBlockY((bmap_t*)ssecBlockMap, ssec->bBox[1].pos[VY]); for(x = xl; x <= xh; ++x) for(y = yl; y <= yh; ++y) { if(x < 0 || y < 0 || x >= subMapWidth || y >= subMapHeight) { Con_Printf("sub%i: outside block x=%i, y=%i\n", i, x, y); continue; } // Create a new node. iter = M_Malloc(sizeof(ssecnode_t)); iter->data = ssec; // Link to the temporary map. block = &bmap[x + y * subMapWidth]; iter->next = block->nodes; block->nodes = iter; totalLinks++; if(!block->count) totalLinks++; // +1 for terminating NULL. block->count++; } } ssecLinks = Z_Malloc(totalLinks * sizeof(subsector_t*), PU_MAP, NULL); // Create the actual links by 'hardening' the lists into arrays. for(y = 0; y < subMapHeight; ++y) for(x = 0; x < subMapWidth; ++x) { block = &bmap[y * subMapWidth + x]; if(block->count > 0) { subsector_t** ssecs, **ptr; // A NULL-terminated array of pointers to subsectors. ssecs = ssecLinks; // Copy pointers to the array, delete the nodes. ptr = ssecs; for(iter = block->nodes; iter; iter = next) { *ptr++ = (subsector_t *) iter->data; // Kill the node. next = iter->next; M_Free(iter); } // Terminate. *ptr = NULL; // Link it into the ssecblockmap. P_SSecBlockmapSetBlock(ssecBlockMap, x, y, ssecs); ssecLinks += block->count + 1; } } map->ssecBlockMap = ssecBlockMap; // Free the temporary link map. M_Free(bmap); // How much time did we spend? VERBOSE(Con_Message ("P_BuildSubsectorBlockMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); #undef BLOCK_WIDTH #undef BLOCK_HEIGHT } void P_BlockmapSetBlock(blockmap_t* blockmap, uint x, uint y, linedef_t** lines, linkmobj_t* moLink, linkpolyobj_t* poLink) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; bmapblock_t* block = M_GridmapGetBlock(bmap->gridmap, x, y, true); if(block) { block->lineDefs = lines; block->mobjLinks = moLink; block->polyLinks = poLink; } } } boolean unlinkPolyobjInBlock(void* ptr, void* context) { bmapblock_t* block = (bmapblock_t*) ptr; polyobj_t* po = (polyobj_t*) context; P_PolyobjUnlinkFromRing(po, &block->polyLinks); return true; } boolean linkPolyobjInBlock(void* ptr, void* context) { bmapblock_t* block = (bmapblock_t*) ptr; polyobj_t* po = (polyobj_t *) context; P_PolyobjLinkToRing(po, &block->polyLinks); return true; } void P_BlockmapLinkPolyobj(blockmap_t* blockmap, polyobj_t* po) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; uint blockBox[4], x, y; P_PolyobjUpdateBBox(po); P_BoxToBlockmapBlocks(blockmap, blockBox, po->box); for(y = blockBox[BOXBOTTOM]; y <= blockBox[BOXTOP]; ++y) for(x = blockBox[BOXLEFT]; x <= blockBox[BOXRIGHT]; ++x) { bmapblock_t* block = (bmapblock_t*) M_GridmapGetBlock(bmap->gridmap, x, y, true); linkPolyobjInBlock((void*)block, po); } } } void P_BlockmapUnlinkPolyobj(blockmap_t* blockmap, polyobj_t* po) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; uint blockBox[4]; P_PolyobjUpdateBBox(po); P_BoxToBlockmapBlocks(BlockMap, blockBox, po->box); M_GridmapBoxIteratorv(bmap->gridmap, blockBox, unlinkPolyobjInBlock, (void*) po); } } void P_BlockmapLinkMobj(blockmap_t* blockmap, mobj_t* mo) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; uint blockXY[2]; bmapblock_t* block; P_ToBlockmapBlockIdx(BlockMap, blockXY, mo->pos); block = (bmapblock_t*) M_GridmapGetBlock(bmap->gridmap, blockXY[0], blockXY[1], true); if(block) P_MobjLinkToRing(mo, &block->mobjLinks); } } boolean P_BlockmapUnlinkMobj(blockmap_t* blockmap, mobj_t* mo) { boolean unlinked = false; if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; uint blockXY[2]; bmapblock_t* block; P_ToBlockmapBlockIdx(BlockMap, blockXY, mo->pos); block = (bmapblock_t*) M_GridmapGetBlock(bmap->gridmap, blockXY[0], blockXY[1], false); if(block) unlinked = P_MobjUnlinkFromRing(mo, &block->mobjLinks); } return unlinked; } void P_GetBlockmapBounds(blockmap_t* blockmap, pvec2_t min, pvec2_t max) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; if(min) V2_Copy(min, bmap->bBox[0]); if(max) V2_Copy(max, bmap->bBox[1]); } } void P_GetBlockmapDimensions(blockmap_t* blockmap, uint v[2]) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; v[VX] = bmap->dimensions[VX]; v[VY] = bmap->dimensions[VY]; } } typedef struct bmapiterparams_s { int localValidCount; boolean (*func) (linedef_t*, void *); void* param; } bmapiterparams_t; static boolean bmapBlockLinesIterator(void* ptr, void* context) { bmapblock_t* block = (bmapblock_t*) ptr; if(block->lineDefs) { linedef_t** iter; bmapiterparams_t* args = (bmapiterparams_t*) context; iter = block->lineDefs; while(*iter) { linedef_t* line = *iter; if(line->validCount != args->localValidCount) { line->validCount = args->localValidCount; if(!args->func(line, args->param)) return false; } *iter++; } } return true; } boolean P_BlockmapLinesIterator(blockmap_t* blockmap, const uint block[2], boolean (*func) (linedef_t*, void*), void* data) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; bmapblock_t* bmapBlock = M_GridmapGetBlock(bmap->gridmap, block[VX], block[VY], false); if(bmapBlock) { bmapiterparams_t args; args.localValidCount = validCount; args.func = func; args.param = data; return bmapBlockLinesIterator(bmapBlock, &args); } } return true; } boolean P_BlockBoxLinesIterator(blockmap_t* blockmap, const uint blockBox[4], boolean (*func) (linedef_t*, void*), void* data) { bmap_t* bmap = (bmap_t*) blockmap; bmapiterparams_t args; args.localValidCount = validCount; args.func = func; args.param = data; return M_GridmapBoxIteratorv(bmap->gridmap, blockBox, bmapBlockLinesIterator, (void*) &args); } typedef struct bmappoiterparams_s { int localValidCount; boolean (*func) (polyobj_t*, void *); void* param; } bmappoiterparams_t; static boolean bmapBlockPolyobjsIterator(void* ptr, void* context) { bmapblock_t* block = (bmapblock_t*) ptr; bmappoiterparams_t* args = (bmappoiterparams_t*) context; linkpolyobj_t* link; link = block->polyLinks; while(link) { linkpolyobj_t* next = link->next; if(link->polyobj) if(link->polyobj->validCount != args->localValidCount) { link->polyobj->validCount = args->localValidCount; if(!args->func(link->polyobj, args->param)) return false; } link = next; } return true; } boolean P_BlockmapPolyobjsIterator(blockmap_t* blockmap, const uint block[2], boolean (*func) (polyobj_t*, void*), void* data) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; bmapblock_t* bmapBlock = M_GridmapGetBlock(bmap->gridmap, block[VX], block[VY], false); if(bmapBlock) { bmappoiterparams_t args; args.localValidCount = validCount; args.func = func; args.param = data; return bmapBlockPolyobjsIterator(bmapBlock, (void*) &args); } } return true; } boolean P_BlockBoxPolyobjsIterator(blockmap_t* blockmap, const uint blockBox[4], boolean (*func) (polyobj_t*, void*), void* data) { bmap_t* bmap = (bmap_t*) blockmap; bmappoiterparams_t args; args.localValidCount = validCount; args.func = func; args.param = data; return M_GridmapBoxIteratorv(bmap->gridmap, blockBox, bmapBlockPolyobjsIterator, (void*) &args); } typedef struct bmapmoiterparams_s { int localValidCount; boolean (*func) (mobj_t*, void *); void* param; } bmapmoiterparams_t; static boolean bmapBlockMobjsIterator(void* ptr, void* context) { bmapblock_t* block = (bmapblock_t*) ptr; bmapmoiterparams_t* args = (bmapmoiterparams_t*) context; linkmobj_t* link; link = block->mobjLinks; while(link) { linkmobj_t* next = link->next; if(link->mobj) if(link->mobj->validCount != args->localValidCount) { link->mobj->validCount = args->localValidCount; if(!args->func(link->mobj, args->param)) return false; } link = next; } return true; } boolean P_BlockmapMobjsIterator(blockmap_t* blockmap, const uint block[2], boolean (*func) (mobj_t*, void*), void* data) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; bmapblock_t* bmapBlock = M_GridmapGetBlock(bmap->gridmap, block[VX], block[VY], false); if(bmapBlock) { bmapmoiterparams_t args; args.localValidCount = validCount; args.func = func; args.param = data; return bmapBlockMobjsIterator(bmapBlock, (void*) &args); } } return true; } boolean P_BlockBoxMobjsIterator(blockmap_t *blockmap, const uint blockBox[4], boolean (*func) (mobj_t*, void*), void* data) { bmap_t* bmap = (bmap_t*) blockmap; bmapmoiterparams_t args; args.localValidCount = validCount; args.func = func; args.param = data; return M_GridmapBoxIteratorv(bmap->gridmap, blockBox, bmapBlockMobjsIterator, (void*) &args); } typedef struct sseciterparams_s { arvec2_t box; sector_t* sector; int localValidCount; boolean (*func) (subsector_t*, void*); void* param; } sseciterparams_t; static boolean ssecBlockIterator(void* ptr, void* context) { ssecmapblock_t* block = (ssecmapblock_t*) ptr; if(block->ssecs) { subsector_t** iter; sseciterparams_t* args = (sseciterparams_t*) context; iter = block->ssecs; while(*iter) { subsector_t* ssec = *iter; if(ssec->validCount != args->localValidCount) { boolean ok = true; ssec->validCount = args->localValidCount; // Check the sector restriction. if(args->sector && ssec->sector != args->sector) ok = false; // Check the bounds. if(args->box && (ssec->bBox[1].pos[VX] < args->box[0][VX] || ssec->bBox[0].pos[VX] > args->box[1][VX] || ssec->bBox[0].pos[VY] > args->box[1][VY] || ssec->bBox[1].pos[VY] < args->box[0][VY])) ok = false; if(ok) { if(!args->func(ssec, args->param)) return false; } } *iter++; } } return true; } boolean P_BlockmapSubsectorsIterator(blockmap_t* blockmap, const uint block[2], sector_t* sector, const arvec2_t box, int localValidCount, boolean (*func) (subsector_t*, void*), void* data) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; ssecmapblock_t* ssecBlock = M_GridmapGetBlock(bmap->gridmap, block[VX], block[VY], false); if(ssecBlock && ssecBlock->ssecs) { sseciterparams_t args; args.box = box; args.localValidCount = localValidCount; args.sector = sector; args.func = func; args.param = data; return ssecBlockIterator(ssecBlock, &args); } } return true; } boolean P_BlockBoxSubsectorsIterator(blockmap_t* blockmap, const uint blockBox[4], sector_t* sector, const arvec2_t box, int localValidCount, boolean (*func) (subsector_t*, void*), void* data) { bmap_t* bmap = (bmap_t *) blockmap; sseciterparams_t args; args.box = box; args.localValidCount = localValidCount; args.sector = sector; args.func = func; args.param = data; return M_GridmapBoxIteratorv(bmap->gridmap, blockBox, ssecBlockIterator, (void*) &args); } typedef struct poiterparams_s { boolean (*func) (linedef_t*, void*); void* param; } poiterparams_t; boolean PTR_PolyobjLines(polyobj_t* po, void* data) { poiterparams_t* args = (poiterparams_t*) data; return P_PolyobjLinesIterator(po, args->func, args->param); } boolean P_BlockmapPolyobjLinesIterator(blockmap_t* blockmap, const uint block[2], boolean (*func) (linedef_t*, void*), void* data) { if(blockmap) { bmap_t* bmap = (bmap_t*) blockmap; bmapblock_t* bmapBlock = M_GridmapGetBlock(bmap->gridmap, block[VX], block[VY], false); if(bmapBlock && bmapBlock->polyLinks) { bmappoiterparams_t args; poiterparams_t poargs; poargs.func = func; poargs.param = data; args.localValidCount = validCount; args.func = PTR_PolyobjLines; args.param = &poargs; return bmapBlockPolyobjsIterator(bmapBlock, &args); } } return true; } boolean P_BlockBoxPolyobjLinesIterator(blockmap_t* blockmap, const uint blockBox[4], boolean (*func) (linedef_t*, void*), void* data) { bmap_t* bmap = (bmap_t*) blockmap; bmappoiterparams_t args; poiterparams_t poargs; poargs.func = func; poargs.param = data; args.localValidCount = validCount; args.func = PTR_PolyobjLines; args.param = &poargs; return M_GridmapBoxIteratorv(bmap->gridmap, blockBox, bmapBlockPolyobjsIterator, (void*) &args); } boolean P_BlockPathTraverse(blockmap_t* bmap, const uint originBlock[2], const uint destBlock[2], const float origin[2], const float dest[2], int flags, boolean (*func) (intercept_t*)) { uint count, block[2]; float delta[2], partial; fixed_t intercept[2], step[2]; int stepDir[2]; if(destBlock[VX] > originBlock[VX]) { stepDir[VX] = 1; partial = FIX2FLT(FRACUNIT - ((FLT2FIX(origin[VX]) >> MAPBTOFRAC) & (FRACUNIT - 1))); delta[VY] = (dest[VY] - origin[VY]) / fabs(dest[VX] - origin[VX]); } else if(destBlock[VX] < originBlock[VX]) { stepDir[VX] = -1; partial = FIX2FLT((FLT2FIX(origin[VX]) >> MAPBTOFRAC) & (FRACUNIT - 1)); delta[VY] = (dest[VY] - origin[VY]) / fabs(dest[VX] - origin[VX]); } else { stepDir[VX] = 0; partial = 1; delta[VY] = 256; } intercept[VY] = (FLT2FIX(origin[VY]) >> MAPBTOFRAC) + FLT2FIX(partial * delta[VY]); if(destBlock[VY] > originBlock[VY]) { stepDir[VY] = 1; partial = FIX2FLT(FRACUNIT - ((FLT2FIX(origin[VY]) >> MAPBTOFRAC) & (FRACUNIT - 1))); delta[VX] = (dest[VX] - origin[VX]) / fabs(dest[VY] - origin[VY]); } else if(destBlock[VY] < originBlock[VY]) { stepDir[VY] = -1; partial = FIX2FLT((FLT2FIX(origin[VY]) >> MAPBTOFRAC) & (FRACUNIT - 1)); delta[VX] = (dest[VX] - origin[VX]) / fabs(dest[VY] - origin[VY]); } else { stepDir[VY] = 0; partial = 1; delta[VX] = 256; } intercept[VX] = (FLT2FIX(origin[VX]) >> MAPBTOFRAC) + FLT2FIX(partial * delta[VX]); // // Step through map blocks. // // Count is present to prevent a round off error from skipping the // break and ending up in an infinite loop.. block[VX] = originBlock[VX]; block[VY] = originBlock[VY]; step[VX] = FLT2FIX(delta[VX]); step[VY] = FLT2FIX(delta[VY]); for(count = 0; count < 64; ++count) { if(flags & PT_ADDLINES) { if(numPolyObjs > 0) { if(!P_BlockmapPolyobjLinesIterator(BlockMap, block, PIT_AddLineIntercepts, 0)) return false; // Early out. } if(!P_BlockmapLinesIterator(BlockMap, block, PIT_AddLineIntercepts, 0)) return false; // Early out } if(flags & PT_ADDMOBJS) { if(!P_BlockmapMobjsIterator(BlockMap, block, PIT_AddMobjIntercepts, 0)) return false; // Early out. } if(block[VX] == destBlock[VX] && block[VY] == destBlock[VY]) break; if((unsigned) (intercept[VY] >> FRACBITS) == block[VY]) { intercept[VY] += step[VY]; block[VX] += stepDir[VX]; } else if((unsigned) (intercept[VX] >> FRACBITS) == block[VX]) { intercept[VX] += step[VX]; block[VY] += stepDir[VY]; } } return true; } static boolean rendBlockMobj(mobj_t* mo, void* data) { vec2_t start, end; arvec2_t bbox = data; V2_Set(start, mo->pos[VX] - bbox[0][VX] - mo->radius, mo->pos[VY] - bbox[0][VY] - mo->radius); V2_Set(end, mo->pos[VX] - bbox[0][VX] + mo->radius, mo->pos[VY] - bbox[0][VY] + mo->radius); glVertex2f(start[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(start[VX], end[VY]); return true; // Continue iteration. } static boolean rendBlockLinedef(linedef_t* line, void* data) { vec2_t start, end; arvec2_t bbox = data; V2_Set(start, line->L_v1pos[VX] - bbox[0][VX], line->L_v1pos[VY] - bbox[0][VY]); V2_Set(end, line->L_v2pos[VX] - bbox[0][VX], line->L_v2pos[VY] - bbox[0][VY]); glVertex2fv(start); glVertex2fv(end); return true; // Continue iteration. } static boolean rendBlockSubsector(subsector_t* ssec, void* data) { vec2_t start, end; arvec2_t bbox = data; seg_t** segs = ssec->segs; while(*segs) { seg_t* seg = *segs; V2_Set(start, seg->SG_v1pos[VX] - bbox[0][VX], seg->SG_v1pos[VY] - bbox[0][VY]); V2_Set(end, seg->SG_v2pos[VX] - bbox[0][VX], seg->SG_v2pos[VY] - bbox[0][VY]); glBegin(GL_LINES); glVertex2fv(start); glVertex2fv(end); glEnd(); { float length, dx, dy; float normal[2], unit[2]; float scale = MAX_OF(bmapDebugSize, 1); float width = (theWindow->width / 16) / scale; dx = end[VX] - start[VX]; dy = end[VY] - start[VY]; length = sqrt(dx * dx + dy * dy); if(length > 0) { unit[VX] = dx / length; unit[VY] = dy / length; normal[VX] = -unit[VY]; normal[VY] = unit[VX]; glBindTexture(GL_TEXTURE_2D, GL_PrepareLSTexture(LST_DYNAMIC)); glEnable(GL_TEXTURE_2D); GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE); glBegin(GL_QUADS); glTexCoord2f(0.75f, 0.5f); glVertex2fv(start); glTexCoord2f(0.75f, 0.5f); glVertex2fv(end); glTexCoord2f(0.75f, 1); glVertex2f(end[VX] - normal[VX] * width, end[VY] - normal[VY] * width); glTexCoord2f(0.75f, 1); glVertex2f(start[VX] - normal[VX] * width, start[VY] - normal[VY] * width); glEnd(); glDisable(GL_TEXTURE_2D); GL_BlendMode(BM_NORMAL); } } // Draw the bounding box. V2_Set(start, ssec->bBox[0].pos[VX] - bbox[0][VX], ssec->bBox[0].pos[VY] - bbox[0][VY]); V2_Set(end, ssec->bBox[1].pos[VX] - bbox[0][VX], ssec->bBox[1].pos[VY] - bbox[0][VY]); glBegin(GL_LINES); glVertex2f(start[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(start[VX], end[VY]); glVertex2f(start[VX], end[VY]); glVertex2f(start[VX], start[VY]); glEnd(); *segs++; } return true; // Continue iteration. } void rendBlockLinedefs(void* blockPtr, void* param, float r, float g, float b, float a) { bmapblock_t* block = blockPtr; // Lines? if(block->lineDefs) { bmapiterparams_t args; args.localValidCount = validCount; args.func = rendBlockLinedef; args.param = param; glColor4f(r, g, b, a); glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); bmapBlockLinesIterator(block, &args); glEnd(); glEnable(GL_TEXTURE_2D); } // Polyobj lines? if(block->polyLinks) { bmappoiterparams_t args; poiterparams_t poargs; poargs.func = rendBlockLinedef; poargs.param = param; args.localValidCount = validCount; args.func = PTR_PolyobjLines; args.param = &poargs; glColor4f(r, g, b, a); glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); bmapBlockPolyobjsIterator(block, &args); glEnd(); glEnable(GL_TEXTURE_2D); } } void rendBlockMobjs(void* blockPtr, void* data, float r, float g, float b, float a) { bmapblock_t* block = blockPtr; // Mobjs? if(block->mobjLinks) { bmapmoiterparams_t args; args.localValidCount = validCount; args.func = rendBlockMobj; args.param = data; glColor4f(r, g, b, a); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); bmapBlockMobjsIterator(block, (void*) &args); glEnd(); glEnable(GL_TEXTURE_2D); } } void rendBlockSubsectors(void* blockPtr, void* param, float r, float g, float b, float a) { ssecmapblock_t* block = blockPtr; if(block->ssecs) { sseciterparams_t args; args.box = NULL; args.localValidCount = validCount; args.sector = NULL; args.func = rendBlockSubsector; args.param = param; glColor4f(r, g, b, a); ssecBlockIterator(block, &args); } } static void drawInfoBox(int x, int y, long blockIdx, uint blockX, uint blockY, int lineCount, int moCount, int poCount) { int w, h; char buf[160]; sprintf(buf, "Block: %li [%u, %u] Lines: #%i Mobjs: #%i Polyobjs: #%i", blockIdx, blockX, blockY, lineCount, moCount, poCount); w = FR_TextWidth(buf) + 16; h = FR_TextHeight(buf) + 16; x -= w / 2; UI_GradientEx(x, y, w, h, 6, UI_Color(UIC_BG_MEDIUM), UI_Color(UIC_BG_LIGHT), .5f, .5f); UI_DrawRectEx(x, y, w, h, 6, false, UI_Color(UIC_BRD_HI), NULL, .5f, -1); UI_SetColor(UI_Color(UIC_TEXT)); UI_TextOutEx(buf, x + 8, y + h / 2, false, true, UI_Color(UIC_TITLE), 1); } static void drawInfoBox2(float minX, float minY, float maxX, float maxY, float blockWidth, float blockHeight, uint width, uint height) { int w = 16 + FR_TextWidth("(+000.0,+000.0)(+000.0,+000.0)"); int th = FR_TextHeight("a"), h = th * 4 + 16; int x, y; char buf[80]; x = theWindow->width - 10 - w; y = theWindow->height - 10 - h; UI_GradientEx(x, y, w, h, 6, UI_Color(UIC_BG_MEDIUM), UI_Color(UIC_BG_LIGHT), .5f, .5f); UI_DrawRectEx(x, y, w, h, 6, false, UI_Color(UIC_BRD_HI), NULL, .5f, -1); x += 8; y += 8 + th/2; UI_TextOutEx("Blockmap", x, y, false, true, UI_Color(UIC_TITLE), 1); y += th; sprintf(buf, "Dimensions:[%u,%u] #%li", width, height, width * (long) height); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), 1); y += th; sprintf(buf, "Blksize:[%.2f,%.2f]", blockWidth, blockHeight); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), 1); y += th; sprintf(buf, "(%+06.0f,%+06.0f)(%+06.0f,%+06.0f)", minX, minY, maxX, maxY); UI_TextOutEx(buf, x, y, false, true, UI_Color(UIC_TEXT), 1); y += th; } static void drawBlockInfoBox(uint vBlock[2]) { int lineCount = -1, moCount = -1, poCount = -1; long blockIdx = -1; bmap_t* bmap = (bmap_t*) BlockMap; bmapblock_t* block; block = M_GridmapGetBlock(bmap->gridmap, vBlock[VX], vBlock[VY], false); if(block) { blockIdx = vBlock[VY] * bmap->dimensions[VY] + vBlock[VX]; // Count the number of lines linked to this block. lineCount = 0; if(block->lineDefs) { linedef_t** iter = block->lineDefs; while(*iter) { lineCount++; *iter++; } } // Count the number of mobjs linked to this block. moCount = 0; if(block->mobjLinks) { linkmobj_t* link = block->mobjLinks; while(link) { if(link->mobj) moCount++; link = link->next; } } // Count the number of polyobjs linked to this block. poCount = 0; if(block->polyLinks) { linkpolyobj_t* link = block->polyLinks; while(link) { if(link->polyobj) poCount++; link = link->next; } } } drawInfoBox(theWindow->width / 2, 30, blockIdx, vBlock[VX], vBlock[VY], lineCount, moCount, poCount); } /** * Draw the blockmap in 2D HUD mode. */ static void blockmapDebug(blockmap_t* blockmap, mobj_t* followMobj, void (*func) (void* blockPtr, void* param, float r, float g, float b, float a)) { bmap_t* bmap = (bmap_t*) blockmap; void* block; uint x, y, vBlock[2], vBlockBox[4]; float scale, radius; vec2_t start, end, box[2]; scale = bmapDebugSize / MAX_OF(theWindow->height / 100, 1); if(followMobj) { // Determine the mobj's block. if(!P_ToBlockmapBlockIdx(blockmap, vBlock, followMobj->pos)) followMobj = NULL; // The target is outside the blockmap. } if(followMobj) { // Determine the mobj's collision blockbox. radius = followMobj->radius + DDMOBJ_RADIUS_MAX * 2; V2_Set(start, followMobj->pos[VX] - radius, followMobj->pos[VY] - radius); V2_Set(end, followMobj->pos[VX] + radius, followMobj->pos[VY] + radius); V2_InitBox(box, start); V2_AddToBox(box, end); P_BoxToBlockmapBlocks(blockmap, vBlockBox, box); } // Go into screen projection mode. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); glTranslatef((theWindow->width / 2), (theWindow->height / 2), 0); glScalef(scale, -scale, 1); if(followMobj) { // Offset relatively to center on the location of the mobj. V2_Set(start, (vBlock[VX] * bmap->blockSize[VX]), (vBlock[VY] * bmap->blockSize[VY])); glTranslatef(-start[VX], -start[VY], 0); } else { // Offset to center the blockmap on the screen. glTranslatef(-(bmap->blockSize[VX] * bmap->dimensions[VX] / 2), -(bmap->blockSize[VY] * bmap->dimensions[VY] / 2), 0); } glDisable(GL_TEXTURE_2D); // Draw a background. V2_Set(start, 0, 0); V2_Set(end, bmap->blockSize[VX] * bmap->dimensions[VX], bmap->blockSize[VY] * bmap->dimensions[VY]); glColor4f(.25f, .25f, .25f, .66f); glBegin(GL_QUADS); glVertex2f(start[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(start[VX], end[VY]); glEnd(); /** * Draw the blocks. */ for(y = 0; y < bmap->dimensions[VY]; ++y) for(x = 0; x < bmap->dimensions[VX]; ++x) { boolean draw = false; bmapblock_t* block = M_GridmapGetBlock(bmap->gridmap, x, y, false); if(followMobj) { if(x == vBlock[VX] && y == vBlock[VY]) { // The block the viewPlayer is in. glColor4f(.66f, .66f, 1, .66f); draw = true; } else if(x >= vBlockBox[BOXLEFT] && x <= vBlockBox[BOXRIGHT] && y >= vBlockBox[BOXBOTTOM] && y <= vBlockBox[BOXTOP]) { // In the viewPlayer's extended collision range. glColor4f(.33f, .33f, .66f, .33f); draw = true; } } if(!draw && !block) { // NULL block. glColor4f(0, 0, 0, .95f); draw = true; } if(draw) { V2_Set(start, x * bmap->blockSize[VX], y * bmap->blockSize[VY]); V2_Set(end, bmap->blockSize[VX], bmap->blockSize[VY]); V2_Sum(end, end, start); glBegin(GL_QUADS); glVertex2f(start[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(start[VX], end[VY]); glEnd(); } } /** * Draw the grid lines */ glColor4f(.5f, .5f, .5f, .125f); // Vertical lines: glBegin(GL_LINES); for(x = 1; x < bmap->dimensions[VX]; ++x) { glVertex2f(x * bmap->blockSize[VX], 0); glVertex2f(x * bmap->blockSize[VX], bmap->blockSize[VY] * bmap->dimensions[VY]); } glEnd(); // Horizontal lines glBegin(GL_LINES); for(y = 1; y < bmap->dimensions[VY]; ++y) { glVertex2f(0, y * bmap->blockSize[VY]); glVertex2f(bmap->blockSize[VX] * bmap->dimensions[VX], y * bmap->blockSize[VY]); } glEnd(); glEnable(GL_TEXTURE_2D); /** * Draw the blockmap-linked data. */ validCount++; if(followMobj) { // First, the blocks outside the viewPlayer's range. for(y = 0; y < bmap->dimensions[VY]; ++y) for(x = 0; x < bmap->dimensions[VX]; ++x) { if(x >= vBlockBox[BOXLEFT] && x <= vBlockBox[BOXRIGHT] && y >= vBlockBox[BOXBOTTOM] && y <= vBlockBox[BOXTOP]) continue; block = M_GridmapGetBlock(bmap->gridmap, x, y, false); if(block) { func(block, bmap->bBox, .33f, 0, 0, .75f); } } validCount++; // Next, the blocks within the viewPlayer's extended collision range. for(y = vBlockBox[BOXBOTTOM]; y <= vBlockBox[BOXTOP]; ++y) for(x = vBlockBox[BOXLEFT]; x <= vBlockBox[BOXRIGHT]; ++x) { if(x == vBlock[VX] && y == vBlock[VY]) continue; block = M_GridmapGetBlock(bmap->gridmap, x, y, false); if(block) { func(block, bmap->bBox, 1, .5f, 0, 1); } } validCount++; // Lastly, the block the viewPlayer is in. block = M_GridmapGetBlock(bmap->gridmap, vBlock[VX], vBlock[VY], false); if(block) { func(block, bmap->bBox, 1, 1, 0, 1); } /** * Draw the followMobj. */ radius = followMobj->radius; V2_Set(start, followMobj->pos[VX] - bmap->bBox[0][VX] - radius, followMobj->pos[VY] - bmap->bBox[0][VY] - radius); V2_Set(end, followMobj->pos[VX] - bmap->bBox[0][VX] + radius, followMobj->pos[VY] - bmap->bBox[0][VY] + radius); glColor4f(0, 1, 0, 1); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); glVertex2f(start[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(start[VX], end[VY]); glEnd(); glEnable(GL_TEXTURE_2D); } else { // Just draw the lot. for(y = 0; y < bmap->dimensions[VY]; ++y) for(x = 0; x < bmap->dimensions[VX]; ++x) { block = M_GridmapGetBlock(bmap->gridmap, x, y, false); if(block) { func(block, bmap->bBox, .33f, 0, 0, .75f); } } } /** * Draw the blockmap bounds. */ V2_Set(start, -1, -1); V2_Set(end, 1 + bmap->blockSize[VX] * bmap->dimensions[VX], 1 + bmap->blockSize[VY] * bmap->dimensions[VY]); glColor4f(1, .5f, .5f, 1); glDisable(GL_TEXTURE_2D); glBegin(GL_LINES); glVertex2f(start[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], start[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(end[VX], end[VY]); glVertex2f(start[VX], end[VY]); glVertex2f(start[VX], end[VY]); glVertex2f(start[VX], start[VY]); glEnd(); glPopMatrix(); glEnable(GL_TEXTURE_2D); } void P_BlockmapDebug(void) { blockmap_t* blockmap; bmap_t* bmap; mobj_t* followMobj = NULL; void (*func) (void*, void*, float r, float g, float b, float a); if(!bmapShowDebug || bmapShowDebug > 3) return; switch(bmapShowDebug) { default: // Mobjs. if(!BlockMap) return; blockmap = BlockMap; func = rendBlockMobjs; break; case 2: // Linedefs. if(!BlockMap) return; blockmap = BlockMap; func = rendBlockLinedefs; break; case 3: // Subsectors. if(!SSecBlockMap) return; blockmap = SSecBlockMap; func = rendBlockSubsectors; break; } // If possible, we'll tailor what we draw relative to the viewPlayer. if(viewPlayer && viewPlayer->shared.mo) followMobj = viewPlayer->shared.mo; blockmapDebug(blockmap, followMobj, func); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); if(followMobj && bmapShowDebug != 3) { uint vBlock[2]; // Determine the block mobj is in. if(P_ToBlockmapBlockIdx(blockmap, vBlock, followMobj->pos)) { // Draw info about the block mobj is in. drawBlockInfoBox(vBlock); } } // Draw info about the blockmap. bmap = (bmap_t*) blockmap; drawInfoBox2(bmap->bBox[0][VX], bmap->bBox[0][VY], bmap->bBox[1][VX], bmap->bBox[1][VY], bmap->blockSize[VX], bmap->blockSize[VY], bmap->dimensions[VX], bmap->dimensions[VY]); glMatrixMode(GL_PROJECTION); glPopMatrix(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_oldworld.c0000644000175000017500000002672111357170241023410 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_oldworld.c: Obsolete Clientside World Management * * This file contains obsolete delta routines. They are preserved so that * backwards compatibility is retained with older versions of the network * protocol. * * These routines should be considered FROZEN. Do not change them. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_play.h" #include "de_refresh.h" #include "r_util.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Reads a sector delta from the message buffer and applies it to the world. * * \note THIS FUNCTION IS NOW OBSOLETE (only used with PSV_FRAME packets). * * @return @c false, iff the end marker is found. */ int Cl_ReadSectorDelta(void) { short num = Msg_ReadPackedShort(); sector_t* sec; int df; // Sector number first (0 terminates). if(!num) return false; sec = SECTOR_PTR(--num); // Flags. df = Msg_ReadPackedShort(); if(df & SDF_FLOOR_MATERIAL) { lumpnum_t lumpNum; // A bit convoluted; the delta is a server-side (flat) lump number. if((lumpNum = Cl_TranslateLump(Msg_ReadPackedShort())) != 0) { material_t* mat = P_ToMaterial( P_MaterialNumForName(W_LumpName(lumpNum), MN_FLATS)); #if _DEBUG if(!mat) Con_Message("Cl_ReadSectorDelta: No material for flat %i.", (int) lumpNum); #endif Surface_SetMaterial(&sec->SP_floorsurface, mat); } } if(df & SDF_CEILING_MATERIAL) { lumpnum_t lumpNum; // A bit convoluted; the delta is a server-side (flat) lump number. if((lumpNum = Cl_TranslateLump(Msg_ReadPackedShort())) != 0) { material_t* mat = P_ToMaterial( P_MaterialNumForName(W_LumpName(lumpNum), MN_FLATS)); #if _DEBUG if(!mat) Con_Message("Cl_ReadSectorDelta: No material for flat %i.", (int) lumpNum); #endif Surface_SetMaterial(&sec->SP_ceilsurface, mat); } } if(df & SDF_LIGHT) sec->lightLevel = Msg_ReadByte() / 255.0f; if(df & SDF_FLOOR_TARGET) sec->planes[PLN_FLOOR]->target = FIX2FLT(Msg_ReadShort() << 16); if(df & SDF_FLOOR_SPEED) { sec->planes[PLN_FLOOR]->speed = FIX2FLT((fixed_t) (Msg_ReadByte() << (df & SDF_FLOOR_SPEED_44 ? 12 : 15))); } if(df & SDF_FLOOR_TEXMOVE) { // Old clients might include these. fixed_t movex = Msg_ReadShort() << 8; fixed_t movey = Msg_ReadShort() << 8; } if(df & SDF_CEILING_TARGET) sec->planes[PLN_CEILING]->target = FIX2FLT(Msg_ReadShort() << 16); if(df & SDF_CEILING_SPEED) { sec->planes[PLN_CEILING]->speed = FIX2FLT((fixed_t) (Msg_ReadByte() << (df & SDF_CEILING_SPEED_44 ? 12 : 15))); } if(df & SDF_CEILING_TEXMOVE) { // Old clients might include these. fixed_t movex = Msg_ReadShort() << 8; fixed_t movey = Msg_ReadShort() << 8; } if(df & SDF_COLOR_RED) sec->rgb[0] = Msg_ReadByte() / 255.f; if(df & SDF_COLOR_GREEN) sec->rgb[1] = Msg_ReadByte() / 255.f; if(df & SDF_COLOR_BLUE) sec->rgb[2] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_COLOR_RED) Surface_SetColorR(&sec->SP_floorsurface, Msg_ReadByte() / 255.f); if(df & SDF_FLOOR_COLOR_GREEN) Surface_SetColorG(&sec->SP_floorsurface, Msg_ReadByte() / 255.f); if(df & SDF_FLOOR_COLOR_BLUE) Surface_SetColorB(&sec->SP_floorsurface, Msg_ReadByte() / 255.f); if(df & SDF_CEIL_COLOR_RED) Surface_SetColorR(&sec->SP_ceilsurface, Msg_ReadByte() / 255.f); if(df & SDF_CEIL_COLOR_GREEN) Surface_SetColorG(&sec->SP_ceilsurface, Msg_ReadByte() / 255.f); if(df & SDF_CEIL_COLOR_BLUE) Surface_SetColorB(&sec->SP_ceilsurface, Msg_ReadByte() / 255.f); if(df & SDF_FLOOR_GLOW_RED) sec->SP_floorglowrgb[0] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_GLOW_GREEN) sec->SP_floorglowrgb[1] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_GLOW_BLUE) sec->SP_floorglowrgb[2] = Msg_ReadByte() / 255.f; if(df & SDF_CEIL_GLOW_RED) sec->SP_ceilglowrgb[0] = Msg_ReadByte() / 255.f; if(df & SDF_CEIL_GLOW_GREEN) sec->SP_ceilglowrgb[1] = Msg_ReadByte() / 255.f; if(df & SDF_CEIL_GLOW_BLUE) sec->SP_ceilglowrgb[2] = Msg_ReadByte() / 255.f; if(df & SDF_FLOOR_GLOW) sec->SP_floorglow = (float) (Msg_ReadShort() / DDMAXSHORT); if(df & SDF_CEIL_GLOW) sec->SP_ceilglow = (float) (Msg_ReadShort() / DDMAXSHORT); // Do we need to start any moving planes? if(df & (SDF_FLOOR_TARGET | SDF_FLOOR_SPEED)) { Cl_AddMover(num, MVT_FLOOR, sec->planes[PLN_FLOOR]->target, sec->planes[PLN_FLOOR]->speed); } if(df & (SDF_CEILING_TARGET | SDF_CEILING_SPEED)) { Cl_AddMover(num, MVT_CEILING, sec->planes[PLN_CEILING]->target, sec->planes[PLN_CEILING]->speed); } // Continue reading. return true; } /** * Reads a side delta from the message buffer and applies it to * the world. * * \note THIS FUNCTION IS NOW OBSOLETE (only used with PSV_FRAME packets). * * @return @c false, iff the end marker is found. */ int Cl_ReadSideDelta(void) { short num = Msg_ReadPackedShort(); // \fixme we support > 32768 sidedefs! sidedef_t* sid; int df; // Side number first (0 terminates). if(!num) return false; sid = SIDE_PTR(--num); // Flags. df = Msg_ReadByte(); if(df & SIDF_TOP_MATERIAL) { material_t* mat; /** * The delta is a server-side texture num. * \fixme What if client and server texture nums differ? */ mat = P_GetMaterial(Msg_ReadPackedShort(), MN_TEXTURES); Surface_SetMaterial(&sid->SW_topsurface, mat); } if(df & SIDF_MID_MATERIAL) { material_t* mat; /** * The delta is a server-side texture num. * \fixme What if client and server texture nums differ? */ mat = P_GetMaterial(Msg_ReadPackedShort(), MN_TEXTURES); Surface_SetMaterial(&sid->SW_middlesurface, mat); } if(df & SIDF_BOTTOM_MATERIAL) { material_t* mat; /** * The delta is a server-side texture num. * \fixme What if client and server texture nums differ? */ mat = P_GetMaterial(Msg_ReadPackedShort(), MN_TEXTURES); Surface_SetMaterial(&sid->SW_bottomsurface, mat); } if(df & SIDF_LINE_FLAGS) { byte updatedFlags = Msg_ReadByte(); linedef_t* line = R_GetLineForSide(num); if(line) { // The delta includes the lowest byte. line->flags &= ~0xff; line->flags |= updatedFlags; #if _DEBUG Con_Printf("lineflag %i: %02x\n", GET_LINE_IDX(line), updatedFlags); #endif } } if(df & SIDF_TOP_COLOR_RED) Surface_SetColorR(&sid->SW_topsurface, Msg_ReadByte() / 255.f); if(df & SIDF_TOP_COLOR_GREEN) Surface_SetColorG(&sid->SW_topsurface, Msg_ReadByte() / 255.f); if(df & SIDF_TOP_COLOR_BLUE) Surface_SetColorB(&sid->SW_topsurface, Msg_ReadByte() / 255.f); if(df & SIDF_MID_COLOR_RED) Surface_SetColorR(&sid->SW_middlesurface, Msg_ReadByte() / 255.f); if(df & SIDF_MID_COLOR_GREEN) Surface_SetColorG(&sid->SW_middlesurface, Msg_ReadByte() / 255.f); if(df & SIDF_MID_COLOR_BLUE) Surface_SetColorB(&sid->SW_middlesurface, Msg_ReadByte() / 255.f); if(df & SIDF_MID_COLOR_ALPHA) Surface_SetColorA(&sid->SW_middlesurface, Msg_ReadByte() / 255.f); if(df & SIDF_BOTTOM_COLOR_RED) Surface_SetColorR(&sid->SW_bottomsurface, Msg_ReadByte() / 255.f); if(df & SIDF_BOTTOM_COLOR_GREEN) Surface_SetColorG(&sid->SW_bottomsurface, Msg_ReadByte() / 255.f); if(df & SIDF_BOTTOM_COLOR_BLUE) Surface_SetColorB(&sid->SW_bottomsurface, Msg_ReadByte() / 255.f); if(df & SIDF_MID_BLENDMODE) Surface_SetBlendMode(&sid->SW_middlesurface, (blendmode_t) Msg_ReadShort()); if(df & SIDF_FLAGS) { byte updatedFlags = Msg_ReadByte(); // The delta includes the lowest byte. sid->flags &= ~0xff; sid->flags |= updatedFlags; } // Continue reading. return true; } /** * Reads a poly delta from the message buffer and applies it to the world. * * \note THIS FUNCTION IS NOW OBSOLETE (only used with PSV_FRAME packets). * * @return @c false, iff the end marker is found. */ int Cl_ReadPolyDelta(void) { int df; short num = Msg_ReadPackedShort(); polyobj_t* po; // Check the number. A zero terminates. if(!num) return false; po = polyObjs[--num]; // Flags. df = Msg_ReadPackedShort(); if(df & PODF_DEST_X) po->dest[VX] = FIX2FLT((Msg_ReadShort() << 16) + ((char) Msg_ReadByte() << 8)); if(df & PODF_DEST_Y) po->dest[VY] = FIX2FLT((Msg_ReadShort() << 16) + ((char) Msg_ReadByte() << 8)); if(df & PODF_SPEED) po->speed = FIX2FLT(Msg_ReadShort() << 8); if(df & PODF_DEST_ANGLE) po->destAngle = Msg_ReadShort() << 16; if(df & PODF_ANGSPEED) po->angleSpeed = Msg_ReadShort() << 16; /*CON_Printf("num=%i:\n", num); CON_Printf(" destang=%x angsp=%x\n", po->destAngle, po->angleSpeed); */ if(df & PODF_PERPETUAL_ROTATE) po->destAngle = -1; // Update the polyobj's mover thinkers. Cl_SetPolyMover(num, df & (PODF_DEST_X | PODF_DEST_Y | PODF_SPEED), df & (PODF_DEST_ANGLE | PODF_ANGSPEED | PODF_PERPETUAL_ROTATE)); // Continue reading. return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/bsp_node.c0000644000175000017500000005245511357170241022700 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_node.c: BSP node builder. Recursive node creation and sorting. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ * * \notes * Split a list of half-edges into two using the method described at the * bottom of the file, this was taken from OBJECTS.C in the DEU5beta source. * * This is done by scanning all of the half-edges and finding the one that * does the least splitting and has the least difference in numbers of * half-edges on either side. * * If the ones on the left side make a SSector, then create another SSector * else put the half-edges into the left list. * If the ones on the right side make a SSector, then create another SSector * else put the half-edges into the right list. * * Rewritten by Andrew Apted (-AJA-), 1999-2000. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_bsp.h" #include "de_play.h" #include "de_misc.h" #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Used when sorting subsector hEdges by angle around midpoint. static size_t hEdgeSortBufSize; static hedge_t **hEdgeSortBuf; // CODE -------------------------------------------------------------------- static __inline int pointOnHEdgeSide(double x, double y, const hedge_t *part) { return P_PointOnLinedefSide2(x, y, part->pDX, part->pDY, part->pPerp, part->pLength, DIST_EPSILON); } /** * Add the given half-edge to the specified list. */ void BSP_AddHEdgeToSuperBlock(superblock_t *block, hedge_t *hEdge) { #define SUPER_IS_LEAF(s) \ ((s)->bbox[BOXRIGHT] - (s)->bbox[BOXLEFT] <= 256 && \ (s)->bbox[BOXTOP] - (s)->bbox[BOXBOTTOM] <= 256) for(;;) { int p1, p2; int child; int midPoint[2]; superblock_t *sub; midPoint[VX] = (block->bbox[BOXLEFT] + block->bbox[BOXRIGHT]) / 2; midPoint[VY] = (block->bbox[BOXBOTTOM] + block->bbox[BOXTOP]) / 2; // Update half-edge counts. if(hEdge->lineDef) block->realNum++; else block->miniNum++; if(SUPER_IS_LEAF(block)) { // Block is a leaf -- no subdivision possible. BSP_LinkHEdgeToSuperBlock(block, hEdge); return; } if(block->bbox[BOXRIGHT] - block->bbox[BOXLEFT] >= block->bbox[BOXTOP] - block->bbox[BOXBOTTOM]) { // Block is wider than it is high, or square. p1 = hEdge->v[0]->buildData.pos[VX] >= midPoint[VX]; p2 = hEdge->v[1]->buildData.pos[VX] >= midPoint[VX]; } else { // Block is higher than it is wide. p1 = hEdge->v[0]->buildData.pos[VY] >= midPoint[VY]; p2 = hEdge->v[1]->buildData.pos[VY] >= midPoint[VY]; } if(p1 && p2) child = 1; else if(!p1 && !p2) child = 0; else { // Line crosses midpoint -- link it in and return. BSP_LinkHEdgeToSuperBlock(block, hEdge); return; } // The seg lies in one half of this block. Create the block if it // doesn't already exist, and loop back to add the seg. if(!block->subs[child]) { block->subs[child] = sub = BSP_SuperBlockCreate(); sub->parent = block; if(block->bbox[BOXRIGHT] - block->bbox[BOXLEFT] >= block->bbox[BOXTOP] - block->bbox[BOXBOTTOM]) { sub->bbox[BOXLEFT] = (child? midPoint[VX] : block->bbox[BOXLEFT]); sub->bbox[BOXBOTTOM] = block->bbox[BOXBOTTOM]; sub->bbox[BOXRIGHT] = (child? block->bbox[BOXRIGHT] : midPoint[VX]); sub->bbox[BOXTOP] = block->bbox[BOXTOP]; } else { sub->bbox[BOXLEFT] = block->bbox[BOXLEFT]; sub->bbox[BOXBOTTOM] = (child? midPoint[VY] : block->bbox[BOXBOTTOM]); sub->bbox[BOXRIGHT] = block->bbox[BOXRIGHT]; sub->bbox[BOXTOP] = (child? block->bbox[BOXTOP] : midPoint[VY]); } } block = block->subs[child]; } #undef SUPER_IS_LEAF } static boolean getAveragedCoords(hedge_t *headPtr, double *x, double *y) { size_t total = 0; double avg[2]; hedge_t *cur; if(!x || !y) return false; avg[VX] = avg[VY] = 0; for(cur = headPtr; cur; cur = cur->next) { avg[VX] += cur->v[0]->buildData.pos[VX]; avg[VY] += cur->v[0]->buildData.pos[VY]; avg[VX] += cur->v[1]->buildData.pos[VX]; avg[VY] += cur->v[1]->buildData.pos[VY]; total += 2; } if(total > 0) { *x = avg[VX] / total; *y = avg[VY] / total; return true; } return false; } /** * Sort half-edges by angle (from the middle point to the start vertex). * The desired order (clockwise) means descending angles. * * \note Algorithm: * Uses the now famous "double bubble" sorter :). */ static void sortHEdgesByAngleAroundPoint(hedge_t **hEdges, size_t total, double x, double y) { size_t i; i = 0; while(i + 1 < total) { hedge_t *a = hEdges[i]; hedge_t *b = hEdges[i+1]; angle_g angle1, angle2; angle1 = M_SlopeToAngle(a->v[0]->buildData.pos[VX] - x, a->v[0]->buildData.pos[VY] - y); angle2 = M_SlopeToAngle(b->v[0]->buildData.pos[VX] - x, b->v[0]->buildData.pos[VY] - y); if(angle1 + ANG_EPSILON < angle2) { // Swap them. hEdges[i] = b; hEdges[i + 1] = a; // Bubble down. if(i > 0) i--; } else { // Bubble up. i++; } } } /** * Sort the given list of half-edges into clockwise order based on their * position/orientation compared to the specified point. * * @param headPtr Ptr to the address of the headPtr to the list * of hedges to be sorted. * @param num Number of half edges in the list. * @param x X coordinate of the point to order around. * @param y Y coordinate of the point to order around. */ static void clockwiseOrder(hedge_t **headPtr, size_t num, double x, double y) { size_t i; hedge_t *hEdge; // Insert ptrs to the hEdges into the sort buffer. for(hEdge = *headPtr, i = 0; hEdge; hEdge = hEdge->next, ++i) hEdgeSortBuf[i] = hEdge; hEdgeSortBuf[i] = NULL; // Terminate. if(i != num) Con_Error("clockwiseOrder: Miscounted?"); sortHEdgesByAngleAroundPoint(hEdgeSortBuf, num, x, y); // Re-link the half-edge list in the order of the sorted array. *headPtr = NULL; for(i = 0; i < num; ++i) { size_t idx = (num - 1) - i; size_t j = idx % num; hEdgeSortBuf[j]->next = *headPtr; *headPtr = hEdgeSortBuf[j]; } /*#if _DEBUG Con_Message("Sorted half-edges around (%1.1f,%1.1f)\n", x, y); for(hEdge = sub->hEdges; hEdge; hEdge = hEdge->next) { angle_g angle = M_SlopeToAngle(hEdge->v[0]->V_pos[VX] - x, hEdge->v[0]->V_pos[VY] - y); Con_Message(" half-edge %p: Angle %1.6f (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", hEdge, angle, hEdge->v[0]->V_pos[VX], hEdge->v[0]->V_pos[VY], hEdge->v[1]->V_pos[VX], hEdge->v[1]->V_pos[VY]); } #endif*/ } static void sanityCheckClosed(const bspleafdata_t *leaf) { int total = 0, gaps = 0; hedge_t *cur, *next; for(cur = leaf->hEdges; cur; cur = cur->next) { next = (cur->next? cur->next : leaf->hEdges); if(cur->v[1]->buildData.pos[VX] != next->v[0]->buildData.pos[VX] || cur->v[1]->buildData.pos[VY] != next->v[0]->buildData.pos[VY]) gaps++; total++; } if(gaps > 0) { VERBOSE( Con_Message("HEdge list for leaf #%p is not closed (%d gaps, %d half-edges)\n", leaf, gaps, total) ); /*#if _DEBUG for(cur = leaf->hEdges; cur; cur = cur->next) { Con_Message(" half-edge %p (%1.1f,%1.1f) --> (%1.1f,%1.1f)\n", cur, cur->v[0]->pos[VX], cur->v[0]->pos[VY], cur->v[1]->pos[VX], cur->v[1]->pos[VY]); } #endif*/ } } static void sanityCheckSameSector(const bspleafdata_t *leaf) { hedge_t *cur, *compare; // Find a suitable half-edge for comparison. for(compare = leaf->hEdges; compare; compare = compare->next) { if(!compare->sector) continue; break; } if(!compare) return; for(cur = compare->next; cur; cur = cur->next) { if(!cur->sector) continue; if(cur->sector == compare->sector) continue; // Prevent excessive number of warnings. if(compare->sector->buildData.warnedFacing == cur->sector->buildData.index) continue; compare->sector->buildData.warnedFacing = cur->sector->buildData.index; if(verbose >= 1) { if(cur->lineDef) Con_Message("Sector #%d has sidedef facing #%d (line #%d).\n", compare->sector->buildData.index, cur->sector->buildData.index, cur->lineDef->buildData.index); else Con_Message("Sector #%d has sidedef facing #%d.\n", compare->sector->buildData.index, cur->sector->buildData.index); } } } static boolean sanityCheckHasRealHEdge(const bspleafdata_t *leaf) { hedge_t *cur; for(cur = leaf->hEdges; cur; cur = cur->next) { if(cur->lineDef) return true; } return false; } static void renumberLeafHEdges(bspleafdata_t *leaf, uint *curIndex) { uint n; hedge_t *cur; n = 0; for(cur = leaf->hEdges; cur; cur = cur->next) { cur->index = *curIndex; (*curIndex)++; n++; } } static void prepareHEdgeSortBuffer(size_t numHEdges) { // Do we need to enlarge our sort buffer? if(numHEdges + 1 > hEdgeSortBufSize) { hEdgeSortBufSize = numHEdges + 1; hEdgeSortBuf = M_Realloc(hEdgeSortBuf, hEdgeSortBufSize * sizeof(hedge_t *)); } } static boolean C_DECL clockwiseLeaf(binarytree_t *tree, void *data) { if(BinaryTree_IsLeaf(tree)) { // obj is a leaf. size_t total; hedge_t *hEdge; bspleafdata_t *leaf = (bspleafdata_t*) BinaryTree_GetData(tree); double midPoint[2]; getAveragedCoords(leaf->hEdges, &midPoint[VX], &midPoint[VY]); // Count half-edges. total = 0; for(hEdge = leaf->hEdges; hEdge; hEdge = hEdge->next) total++; // Ensure the sort buffer is large enough. prepareHEdgeSortBuffer(total); clockwiseOrder(&leaf->hEdges, total, midPoint[VX], midPoint[VY]); renumberLeafHEdges(leaf, data); // Do some sanity checks. sanityCheckClosed(leaf); sanityCheckSameSector(leaf); if(!sanityCheckHasRealHEdge(leaf)) { Con_Error("BSP Leaf #%p has no linedef-linked half-edge!", leaf); } } return true; // Continue traversal. } /** * Traverse the BSP tree and put all the half-edges in each subsector into * clockwise order, and renumber their indices. * * \important This cannot be done during BuildNodes() since splitting a * half-edge with a twin may insert another half-edge into that twin's list, * usually in the wrong place order-wise. */ void ClockwiseBspTree(binarytree_t *rootNode) { uint curIndex; hEdgeSortBufSize = 0; hEdgeSortBuf = NULL; curIndex = 0; BinaryTree_PostOrder(rootNode, clockwiseLeaf, &curIndex); // Free temporary storage. if(hEdgeSortBuf) { M_Free(hEdgeSortBuf); hEdgeSortBuf = NULL; } } static void createBSPLeafWorker(bspleafdata_t *leaf, superblock_t *block) { uint num; while(block->hEdges) { hedge_t *cur = block->hEdges; // Un-link first half-edge from the block. block->hEdges = cur->next; // Link it into head of the subsector's list. cur->next = leaf->hEdges; cur->block = NULL; leaf->hEdges = cur; } // Recursively handle sub-blocks. for(num = 0; num < 2; ++num) { superblock_t *a = block->subs[num]; if(a) { createBSPLeafWorker(leaf, a); if(a->realNum + a->miniNum > 0) Con_Error("createSubSectorWorker: child %d not empty!", num); BSP_SuperBlockDestroy(a); block->subs[num] = NULL; } } block->realNum = block->miniNum = 0; } static __inline bspleafdata_t *allocBSPLeaf(void) { return M_Malloc(sizeof(bspleafdata_t)); } static __inline void freeBSPLeaf(bspleafdata_t *leaf) { M_Free(leaf); } bspleafdata_t *BSPLeaf_Create(void) { bspleafdata_t *leaf = allocBSPLeaf(); leaf->hEdges = NULL; return leaf; } void BSPLeaf_Destroy(bspleafdata_t *leaf) { hedge_t *cur, *np; if(!leaf) return; cur = leaf->hEdges; while(cur) { np = cur->next; HEdge_Destroy(cur); cur = np; } freeBSPLeaf(leaf); } /** * Create a new leaf from a list of half-edges. */ static bspleafdata_t *createBSPLeaf(superblock_t *hEdgeList) { bspleafdata_t *leaf = BSPLeaf_Create(); // Link the half-edges into the new leaf. createBSPLeafWorker(leaf, hEdgeList); return leaf; } /** * Takes the half-edge list and determines if it is convex, possibly * converting it into a subsector. Otherwise, the list is divided into two * halves and recursion will continue on the new sub list. * * @param hEdgeList Ptr to the list of half edges at the current node. * @param parent Ptr to write back the address of any newly created * subtree. * @param depth Current tree depth. * @param cutList Ptr to the cutlist to use for storing new segment * intersections (cuts). * @return @c true, if successfull. */ boolean BuildNodes(superblock_t* hEdgeList, binarytree_t** parent, size_t depth, cutlist_t* cutList) { binarytree_t* subTree; bspnodedata_t* node; superblock_t* hEdgeSet[2]; bspleafdata_t* leaf; boolean builtOK = false; bspartition_t partition; *parent = NULL; /*#if _DEBUG Con_Message("Build: Begun @ %lu\n", (unsigned long) depth); BSP_PrintSuperblockHEdges(hEdgeList); #endif*/ // Pick the next partition to use. if(!BSP_PickPartition(hEdgeList, depth, &partition)) { // No partition required, already convex. /*#if _DEBUG Con_Message("BuildNodes: Convex.\n"); #endif*/ leaf = createBSPLeaf(hEdgeList); *parent = BinaryTree_Create(leaf); return true; } /*#if _DEBUG Con_Message("BuildNodes: Partition %p (%1.0f,%1.0f) -> (%1.0f,%1.0f).\n", best, best->v[0]->V_pos[VX], best->v[0]->V_pos[VY], best->v[1]->V_pos[VX], best->v[1]->V_pos[VY]); #endif*/ // Create left and right super blocks. hEdgeSet[RIGHT] = (superblock_t *) BSP_SuperBlockCreate(); hEdgeSet[LEFT] = (superblock_t *) BSP_SuperBlockCreate(); // Copy the bounding box of the edge list to the superblocks. M_CopyBox(hEdgeSet[LEFT]->bbox, hEdgeList->bbox); M_CopyBox(hEdgeSet[RIGHT]->bbox, hEdgeList->bbox); // Divide the half-edges into two lists: left & right. BSP_PartitionHEdges(hEdgeList, &partition, hEdgeSet[RIGHT], hEdgeSet[LEFT], cutList); BSP_CutListEmpty(cutList); node = M_Calloc(sizeof(bspnodedata_t)); *parent = BinaryTree_Create(node); BSP_FindNodeBounds(node, hEdgeSet[RIGHT], hEdgeSet[LEFT]); node->partition.x = partition.x; node->partition.y = partition.y; node->partition.dX = partition.dX; node->partition.dY = partition.dY; builtOK = BuildNodes(hEdgeSet[RIGHT], &subTree, depth + 1, cutList); BinaryTree_SetChild(*parent, RIGHT, subTree); BSP_SuperBlockDestroy(hEdgeSet[RIGHT]); if(builtOK) { builtOK = BuildNodes(hEdgeSet[LEFT], &subTree, depth + 1, cutList); BinaryTree_SetChild(*parent, LEFT, subTree); } BSP_SuperBlockDestroy(hEdgeSet[LEFT]); return builtOK; } //--------------------------------------------------------------------------- // // This message has been taken, complete, from OBJECTS.C in DEU5beta // source. It outlines the method used here to pick the nodelines. // // IF YOU ARE WRITING A DOOM EDITOR, PLEASE READ THIS: // // I spent a lot of time writing the Nodes builder. There are some bugs in // it, but most of the code is OK. If you steal any ideas from this program, // put a prominent message in your own editor to make it CLEAR that some // original ideas were taken from DEU. Thanks. // // While everyone was talking about LineDefs, I had the idea of taking only // the Segs into account, and creating the Segs directly from the SideDefs. // Also, dividing the list of Segs in two after each call to CreateNodes makes // the algorithm faster. I use several other tricks, such as looking at the // two ends of a Seg to see on which side of the nodeline it lies or if it // should be split in two. I took me a lot of time and efforts to do this. // // I give this algorithm to whoever wants to use it, but with this condition: // if your program uses some of the ideas from DEU or the whole algorithm, you // MUST tell it to the user. And if you post a message with all or parts of // this algorithm in it, please post this notice also. I don't want to speak // legalese; I hope that you understand me... I kindly give the sources of my // program to you: please be kind with me... // // If you need more information about this, here is my E-mail address: // Raphael.Quinet@eed.ericsson.se (Raphael Quinet). // // Short description of the algorithm: // 1 - Create one Seg for each SideDef: pick each LineDef in turn. If it // has a "first" SideDef, then create a normal Seg. If it has a // "second" SideDef, then create a flipped Seg. // 2 - Call CreateNodes with the current list of Segs. The list of Segs is // the only argument to CreateNodes. // 3 - Save the Nodes, Segs and SSectors to disk. Start with the leaves of // the Nodes tree and continue up to the root (last Node). // // CreateNodes does the following: // 1 - Pick a nodeline amongst the Segs (minimize the number of splits and // keep the tree as balanced as possible). // 2 - Move all Segs on the right of the nodeline in a list (segs1) and do // the same for all Segs on the left of the nodeline (in segs2). // 3 - If the first list (segs1) contains references to more than one // Sector or if the angle between two adjacent Segs is greater than // 180 degrees, then call CreateNodes with this (smaller) list. // Else, create a SubSector with all these Segs. // 4 - Do the same for the second list (segs2). // 5 - Return the new node (its two children are already OK). // // Each time CreateSSector is called, the Segs are put in a global list. // When there is no more Seg in CreateNodes' list, then they are all in the // global list and ready to be saved to disk. // deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_players.c0000644000175000017500000001173611357170242023103 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_players.c: Players */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_play.h" #include "de_refresh.h" #include "de_network.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- player_t* viewPlayer; player_t ddPlayers[DDMAXPLAYERS]; int consolePlayer; int displayPlayer; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Determine which console is used by the given local player. Local players * are numbered starting from zero. */ int P_LocalToConsole(int localPlayer) { int i, count; for(i = 0, count = 0; i < DDMAXPLAYERS; ++i) { int console = (i + consolePlayer) % DDMAXPLAYERS; player_t* plr = &ddPlayers[console]; ddplayer_t* ddpl = &plr->shared; if(ddpl->flags & DDPF_LOCAL) { if(count++ == localPlayer) return console; } } // No match! return -1; } /** * Determine the local player number used by a particular console. Local * players are numbered starting from zero. */ int P_ConsoleToLocal(int playerNum) { int i, count = 0; player_t* plr = &ddPlayers[playerNum]; int console = consolePlayer; if(playerNum == consolePlayer) { return 0; } if(!(plr->shared.flags & DDPF_LOCAL)) return -1; // Not local at all. for(i = 0; i < DDMAXPLAYERS; ++i) { int console = (i + consolePlayer) % DDMAXPLAYERS; player_t* plr = &ddPlayers[console]; if(console == playerNum) { return count; } if(plr->shared.flags & DDPF_LOCAL) count++; } return -1; } /** * Given a ptr to ddplayer_t, return it's logical index. */ int P_GetDDPlayerIdx(ddplayer_t* ddpl) { if(ddpl) { uint i; for(i = 0; i < DDMAXPLAYERS; ++i) if(&ddPlayers[i].shared == ddpl) return i; } return -1; } /** * Do we THINK the given (camera) player is currently in the void. * The method used to test this is to compare the position of the mobj * each time it is linked into a subsector. * * \note Cannot be 100% accurate so best not to use it for anything critical... * * @param player The player to test. * * @return @c true, If the player is thought to be in the void. */ boolean P_IsInVoid(player_t* player) { ddplayer_t* ddpl; if(!player) return false; ddpl = &player->shared; // Cameras are allowed to move completely freely (so check z height // above/below ceiling/floor). if(ddpl->flags & DDPF_CAMERA) { if(ddpl->inVoid) return true; if(ddpl->mo && ddpl->mo->subsector) { sector_t* sec = ddpl->mo->subsector->sector; if(R_IsSkySurface(&sec->SP_ceilsurface)) { if(ddpl->mo->pos[VZ] > skyFix[PLN_CEILING].height - 4) return true; } else if(ddpl->mo->pos[VZ] > sec->SP_ceilvisheight - 4) return true; if(R_IsSkySurface(&sec->SP_floorsurface)) { if(ddpl->mo->pos[VZ] < skyFix[PLN_FLOOR].height + 4) return true; } else if(ddpl->mo->pos[VZ] < sec->SP_floorvisheight + 4) return true; } } return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_frame.c0000644000175000017500000002733211357170241022653 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_frame.c: Frame Reception */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" // MACROS ------------------------------------------------------------------ #define SET_HISTORY_SIZE 50 #define RESEND_HISTORY_SIZE 50 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int gotFrame; // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Set to true when the PSV_FIRST_FRAME2 packet is received. // Until then, all PSV_FRAME2 packets are ignored (they must be // from the wrong map). boolean gotFirstFrame; int predicted_tics; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Ordinal of the latest set received by the client. Used for detecting deltas // that arrive out of order. The ordinal is the logical equivalent of the set // identifier (which is 0...255). static uint latestSetOrdinal; static byte latestSet; // The ordinal base is added to the set number to convert it from a set // identifier to an ordinal. Every time the set numbers wrap around from 255 // to zero, the ordinal is incremented by 256. static uint setOrdinalBase; // The set history keeps track of received sets and is used to detect // duplicate frames. static short setHistory[SET_HISTORY_SIZE]; static int historyIdx; // The resend ID history keeps track of received resend deltas. Used // to detect duplicate resends. static byte resendHistory[RESEND_HISTORY_SIZE]; static int resendHistoryIdx; // CODE -------------------------------------------------------------------- /** * Clear the history of received set numbers. */ void Cl_InitFrame(void) { gotFrame = false; // Nothing yet... // -1 denotes an invalid entry. memset(setHistory, -1, sizeof(setHistory)); historyIdx = 0; // Clear the resend ID history. memset(resendHistory, 0, sizeof(resendHistory)); resendHistoryIdx = 0; // Reset ordinal counters. latestSet = 0; latestSetOrdinal = 0; setOrdinalBase = 256; } /** * Called when the map changes. */ void Cl_ResetFrame(void) { gotFrame = false; // All frames received before the PSV_FIRST_FRAME2 are ignored. // They must be from the wrong map. gotFirstFrame = false; } /** * Add a set number to the history. */ void Cl_HistoryAdd(byte set) { setHistory[historyIdx++] = set; if(historyIdx >= SET_HISTORY_SIZE) historyIdx -= SET_HISTORY_SIZE; } /** * @return @c true, if the set is found in the recent set * history. */ boolean Cl_HistoryCheck(byte set) { uint i; for(i = 0; i < SET_HISTORY_SIZE; ++i) { if(setHistory[i] == set) return true; } return false; } /** * Add a resend ID number to the resend history. */ void Cl_ResendHistoryAdd(byte id) { resendHistory[resendHistoryIdx++] = id; if(resendHistoryIdx >= RESEND_HISTORY_SIZE) resendHistoryIdx -= RESEND_HISTORY_SIZE; } /** * @return @c true, if the resend ID is found in the history. */ boolean Cl_ResendHistoryCheck(byte id) { uint i; for(i = 0; i < RESEND_HISTORY_SIZE; ++i) { if(resendHistory[i] == id) return true; } return false; } /** * Converts a set identifier, which ranges from 0...255, into a logical * ordinal. Checks for set identifier wraparounds and updates the set * ordinal base accordingly. */ uint Cl_ConvertSetToOrdinal(byte set) { uint ordinal = 0; if(latestSet > 185 && set < 70) { // We must conclude that wraparound has occured. setOrdinalBase += 256; #if _NETDEBUG VERBOSE2( Con_Printf("Cl_ConvertSetToOrdinal: Wraparound, now base is %i.\n", setOrdinalBase) ); #endif } ordinal = set + setOrdinalBase; if(latestSet < 35 && set > 220) { // This is most likely a set that came in before wraparound. ordinal -= 256; } else { latestSet = set; } return ordinal; } /** * Read a PSV_FRAME2/PSV_FIRST_FRAME2 packet. */ void Cl_Frame2Received(int packetType) { byte set = Msg_ReadByte(), oldSet, resend, deltaType; byte resendAcks[300]; int i, numResendAcks = 0; boolean skip = false; #ifdef _NETDEBUG int deltaCount = 0; int startOffset; int deltaLength; #endif // All frames that arrive before the first frame are ignored. // They are most likely from the wrong map. if(packetType == PSV_FIRST_FRAME2) { gotFirstFrame = true; #ifdef _DEBUG VERBOSE( Con_Printf("*** GOT THE FIRST FRAME (%i) ***\n", set) ); #endif } else if(!gotFirstFrame) { // Just ignore. If this was a legitimate frame, the server will // send it again when it notices no ack is coming. #ifdef _DEBUG VERBOSE( Con_Printf("==> Ignored set %i\n", set) ); #endif return; } #ifdef _DEBUG VERBOSE2( Con_Printf("Cl_Frame2Received: Processing delta set %i.\n", set) ); #endif if(packetType != PSV_FIRST_FRAME2) { // If this is not the first frame, it will be ignored if it arrives // out of order. uint ordinal = Cl_ConvertSetToOrdinal(set); if(ordinal < latestSetOrdinal) { VERBOSE2( Con_Printf("==> Ignored set %i because it arrived out of order.\n", set) ); return; } latestSetOrdinal = ordinal; VERBOSE2( Con_Printf("Latest set ordinal is %i.\n", latestSetOrdinal) ); } // Check for duplicates (might happen if ack doesn't get through // or ack arrives too late). if(!Cl_HistoryCheck(set)) { // It isn't yet in the history, so add it there. Cl_HistoryAdd(set); VERBOSE2( Con_Printf("Starting to process deltas in set %i.\n", set) ); #ifdef _NETDEBUG deltaCount = Msg_ReadLong(); VERBOSE2( Con_Message("Set contains %i deltas.\n", deltaCount) ); #endif // Read and process the message. while(!Msg_End()) { #ifdef _NETDEBUG /*Con_Message("Starting to read delta %i of %i...\n", ++readCount, deltaCount);*/ // Check length field. startOffset = Msg_Offset(); deltaLength = Msg_ReadLong(); //Con_Message("Incoming delta length %i bytes.\n", deltaLength); #endif deltaType = Msg_ReadByte(); #ifdef _NETDEBUG //Con_Message(" Delta type is %i.\n", deltaType & ~DT_RESENT); #endif skip = false; VERBOSE2( Con_Printf("Received delta %i.\n",deltaType & ~DT_RESENT) ); // Is this a resent delta? if(deltaType & DT_RESENT) { VERBOSE2( Con_Printf(" This is a resent delta.\n") ); deltaType &= ~DT_RESENT; // Read the set number this was originally in. oldSet = Msg_ReadByte(); // Read the resend ID. resend = Msg_ReadByte(); // Did we already receive this delta? { boolean historyChecked = Cl_HistoryCheck(oldSet); boolean resendChecked = Cl_ResendHistoryCheck(resend); if(historyChecked || resendChecked) { // Yes, we've already got this. Must skip. skip = true; VERBOSE2( Con_Printf(" Skipping delta %i (oldset=%i, rsid=%i), because history=%i resend=%i\n", deltaType, oldSet, resend, historyChecked, resendChecked) ); } } // We must acknowledge that we've received this. resendAcks[numResendAcks++] = resend; Cl_ResendHistoryAdd(resend); } else { VERBOSE2( Con_Printf(" Not resent.\n") ); } switch(deltaType) { case DT_CREATE_MOBJ: // The mobj will be created/shown. Cl_ReadMobjDelta2(skip); break; case DT_MOBJ: // The mobj will be hidden if it's not yet Created. Cl_ReadMobjDelta2(skip); break; case DT_NULL_MOBJ: // The mobj will be removed. Cl_ReadNullMobjDelta2(skip); break; case DT_PLAYER: Cl_ReadPlayerDelta2(skip); break; case DT_SECTOR_R6: // Old format. case DT_SECTOR: Cl_ReadSectorDelta2(deltaType, skip); break; case DT_SIDE_R6: // Old format. case DT_SIDE: Cl_ReadSideDelta2(deltaType, skip); break; case DT_POLY: Cl_ReadPolyDelta2(skip); break; case DT_SOUND: case DT_MOBJ_SOUND: case DT_SECTOR_SOUND: case DT_POLY_SOUND: Cl_ReadSoundDelta2(deltaType, skip); break; default: Con_Error("Cl_Frame2Received: Unknown delta type %i.\n", deltaType); } #ifdef _NETDEBUG // Check that we didn't misread. if(Msg_Offset() - startOffset != deltaLength) { Con_Error("Cl_Frame2Received: Misinterpreted delta! Real length was " "%i bytes, but we read %i bytes.\n", deltaLength, Msg_Offset() - startOffset); } #endif } // We have now received a frame. gotFrame = true; // Reset the predict counter. predicted_tics = 0; } if(numResendAcks == 0) { // Acknowledge the set. Msg_Begin(PCL_ACK_SETS); Msg_WriteByte(set); #ifdef _DEBUG VERBOSE2( Con_Printf("Cl_Frame2Received: Ack set %i. " "Nothing was resent.\n", set) ); #endif } else { // Acknowledge the set and the resent deltas. Msg_Begin(PCL_ACKS); Msg_WriteByte(set); #ifdef _DEBUG VERBOSE2( Con_Printf("Cl_Frame2Received: Ack set %i. " "Contained %i resent deltas: \n", set, numResendAcks) ); #endif for(i = 0; i < numResendAcks; ++i) { Msg_WriteByte(resendAcks[i]); #ifdef _DEBUG VERBOSE2( Con_Printf("%i ", resendAcks[i]) ); #endif } #ifdef _DEBUG VERBOSE2( Con_Printf("\n") ); #endif } Net_SendBuffer(0, 0); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_bams.c0000644000175000017500000000706111357170242022337 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * m_bams.c: Binary Angle Mathematics * * Trigonometric functions. */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #include #include "m_bams.h" // MACROS ------------------------------------------------------------------ #define BAMS_TABLE_ACCURACY_SHIFT 13 #define BAMS_TABLE_ACCURACY (1 << BAMS_TABLE_ACCURACY_SHIFT) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static binangle_t atantable[BAMS_TABLE_ACCURACY]; // CODE -------------------------------------------------------------------- /** * Fills the BAM LUTs. */ void bamsInit(void) { uint i; float fbta = (float) BAMS_TABLE_ACCURACY; for(i = 0; i < BAMS_TABLE_ACCURACY; ++i) { atantable[i] = RAD2BANG(atan(i / fbta)); } } binangle_t bamsAtan2(int y, int x) { binangle_t bang; INTEGER64 absy = y, absx = x; // << TABLE_ACCURACY needs space. if(!x && !y) return BANG_0; // Indeterminate. // Make sure the absolute values are absolute. if(absy < 0) absy = -absy; if(absx < 0) absx = -absx; // We'll first determine what the angle is in the first quadrant. // That's what the tables are for. if(!absy) bang = BANG_0; else if(absy == absx) bang = BANG_45; else if(!absx) bang = BANG_90; else { // The special cases didn't help. Use the tables. // absx and absy can't be zero here. if(absy > absx) bang = BANG_90 - atantable[(absx << BAMS_TABLE_ACCURACY_SHIFT) / absy]; else bang = atantable[(absy << BAMS_TABLE_ACCURACY_SHIFT) / absx]; } // Now we know the angle in the first quadrant. Let's look at the signs // and choose the right quadrant. if(x < 0) // Flip horizontally? { bang = BANG_180 - bang; } if(y < 0) // Flip vertically? { // At the moment bang must be smaller than 180. bang = BANG_180 + BANG_180 - bang; } // This is the final angle. return bang; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_subsector.c0000644000175000017500000000576611357170242023443 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_subsector.c: World subsectors. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Update the subsector, property is selected by DMU_* name. */ boolean Subsector_SetProperty(subsector_t *sub, const setargs_t *args) { Con_Error("Subsector_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); return true; // Continue iteration. } /** * Get the value of a subsector property, selected by DMU_* name. */ boolean Subsector_GetProperty(const subsector_t *sub, setargs_t *args) { switch(args->prop) { case DMU_SECTOR: DMU_GetValue(DMT_SUBSECTOR_SECTOR, &sub->sector, args, 0); break; case DMU_LIGHT_LEVEL: DMU_GetValue(DMT_SECTOR_LIGHTLEVEL, &sub->sector->lightLevel, args, 0); break; case DMT_MOBJS: DMU_GetValue(DMT_SECTOR_MOBJLIST, &sub->sector->mobjList, args, 0); break; case DMU_SEG_COUNT: { // FIXME: //DMU_GetValue(DMT_SUBSECTOR_SEGCOUNT, &sub->segCount, args, 0); int val = (int) sub->segCount; DMU_GetValue(DDVT_INT, &val, args, 0); break; } default: Con_Error("Subsector_GetProperty: No property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_intercept.c0000644000175000017500000001043311357170242023412 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_intercept.c: Line/Object Interception */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ #define MININTERCEPTS 128 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Must be static so these are not confused with intercepts in game libs. static intercept_t* intercepts = 0; static intercept_t* intercept_p = 0; static int maxIntercepts = 0; // CODE -------------------------------------------------------------------- /** * Calculate intercept distances. */ void P_CalcInterceptDistances(const divline_t* strace) { intercept_t* scan; for(scan = intercepts; scan < intercept_p; scan++) { divline_t dl; P_MakeDivline(scan->d.lineDef, &dl); scan->frac = P_InterceptVector(strace, &dl); } } /** * Empties the intercepts array and makes sure it has been allocated. */ void P_ClearIntercepts(void) { if(!intercepts) { maxIntercepts = MININTERCEPTS; intercepts = Z_Malloc(sizeof(*intercepts) * maxIntercepts, PU_STATIC, 0); } intercept_p = intercepts; } /** * You must clear intercepts before the first time this is called. * The intercepts array grows if necessary. * * @return Ptr to the new intercept. */ intercept_t* P_AddIntercept(float frac, intercepttype_t type, void* ptr) { int count = intercept_p - intercepts; if(count == maxIntercepts) { // Allocate more memory. maxIntercepts *= 2; intercepts = Z_Realloc(intercepts, sizeof(*intercepts) * maxIntercepts, PU_STATIC); intercept_p = intercepts + count; } if(type == ICPT_LINE && P_ToIndex(ptr) >= numLineDefs) { count = count; } // Fill in the data that has been provided. intercept_p->frac = frac; intercept_p->type = type; intercept_p->d.mo = ptr; return intercept_p++; } /** * @return @c true, if the traverser function returns @c true, * for all lines. */ boolean P_TraverseIntercepts(traverser_t func, float maxFrac) { int count = intercept_p - intercepts; while(count--) { float dist = DDMAXFLOAT; intercept_t* scan, *in; in = NULL; for(scan = intercepts; scan < intercept_p; scan++) if(scan->frac < dist) { dist = scan->frac; in = scan; } if(maxFrac > 0 && dist > maxFrac) return true; // Checked everything in range. if(in) { if(!func(in)) return false; // Don't bother going farther. in->frac = DDMAXFLOAT; } } return true; // Everything was traversed. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/s_logic.c0000644000175000017500000001653311357170242022524 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_logic.c: The Logical Sound Manager * * The Logical Sound Manager. Tracks all currently playing sounds * in the world, regardless of whether Sfx is available or if the * sounds are actually audible to anyone. * * Uses PU_MAP, so this has to be inited for every map. * (Done via S_MapChange()). */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_audio.h" #include "sys_timer.h" // MACROS ------------------------------------------------------------------ // The logical sounds hash table uses sound IDs as keys. #define LOGIC_HASH_SIZE 64 #define PURGE_INTERVAL 2000 // 2 seconds // TYPES ------------------------------------------------------------------- typedef struct logicsound_s { struct logicsound_s *next, *prev; int id; mobj_t *origin; uint endTime; byte isRepeating; } logicsound_t; typedef struct logichash_s { logicsound_t *first, *last; } logichash_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static logichash_t logicHash[LOGIC_HASH_SIZE]; // CODE -------------------------------------------------------------------- /* * Initialize the Logical Sound Manager for a new map. */ void Sfx_InitLogical(void) { // Memory in the hash table is PU_MAP, so this is acceptable. memset(logicHash, 0, sizeof(logicHash)); } /* * Return a pointer the logical sounds hash. */ logichash_t *Sfx_LogicHash(int id) { return &logicHash[(uint) id % LOGIC_HASH_SIZE]; } /* * Create and link a new logical sound hash table node. */ logicsound_t *Sfx_CreateLogical(int id) { logichash_t *hash = Sfx_LogicHash(id); logicsound_t *node = Z_Calloc(sizeof(logicsound_t), PU_MAP, 0); if(hash->last) { hash->last->next = node; node->prev = hash->last; } hash->last = node; if(!hash->first) hash->first = node; node->id = id; return node; } /* * Unlink and destroy a logical sound hash table node. */ void Sfx_DestroyLogical(logicsound_t * node) { logichash_t *hash = Sfx_LogicHash(node->id); if(hash->first == node) hash->first = node->next; if(hash->last == node) hash->last = node->prev; if(node->next) node->next->prev = node->prev; if(node->prev) node->prev->next = node->next; #ifdef _DEBUG memset(node, 0xDD, sizeof(*node)); #endif Z_Free(node); } /* * The sound is entered into the list of playing sounds. Called when a * 'world class' sound is started, regardless of whether it's actually * started on the local system. */ void Sfx_StartLogical(int id, mobj_t *origin, boolean isRepeating) { logicsound_t *node; uint length = (isRepeating ? 1 : Sfx_GetSoundLength(id)); if(!length) { // This is not a valid sound. return; } id &= ~DDSF_FLAG_MASK; node = Sfx_CreateLogical(id); node->origin = origin; node->isRepeating = isRepeating; node->endTime = Sys_GetRealTime() + length; } /* * The sound is removed from the list of playing sounds. Called whenever * a sound is stopped, regardless of whether it was actually playing on * the local system. Returns the number of sounds stopped. * * id=0, origin=0: stop everything */ int Sfx_StopLogical(int id, mobj_t *origin) { logicsound_t *it, *next; int stopCount = 0; int i; if(id) { for(it = Sfx_LogicHash(id)->first; it; it = next) { next = it->next; if(it->id == id && it->origin == origin) { Sfx_DestroyLogical(it); stopCount++; } } } else { // Browse through the entire hash. for(i = 0; i < LOGIC_HASH_SIZE; i++) { for(it = logicHash[i].first; it; it = next) { next = it->next; if(!origin || it->origin == origin) { Sfx_DestroyLogical(it); stopCount++; } } } } return stopCount; } /* * Remove stopped logical sounds from the hash. */ void Sfx_PurgeLogical(void) { static uint lastTime = 0; uint i, nowTime = Sys_GetRealTime(); logicsound_t *it, *next; if(nowTime - lastTime < PURGE_INTERVAL) { // It's too early. return; } lastTime = nowTime; // Check all sounds in the hash. for(i = 0; i < LOGIC_HASH_SIZE; i++) { for(it = logicHash[i].first; it; it = next) { next = it->next; /*#ifdef _DEBUG Con_Printf("LS:%i orig=%i(%p) %s\n", it->id, it->origin? it->origin->thinker.id : 0, it->origin, it->isRepeating? "[repeat]" : ""); #endif */ if(!it->isRepeating && it->endTime < nowTime) { // This has stopped. Sfx_DestroyLogical(it); } } } } /* * Returns true if the sound is currently playing somewhere in the world. * It doesn't matter if it's audible or not. * * id=0: true if any sounds are playing using the specified origin */ boolean Sfx_IsPlaying(int id, mobj_t *origin) { uint nowTime = Sys_GetRealTime(); logicsound_t *it; int i; if(id) { for(it = Sfx_LogicHash(id)->first; it; it = it->next) { if(it->id == id && it->origin == origin && (it->endTime > nowTime || it->isRepeating)) { // This one is still playing. return true; } } } else if(origin) { // Check if the origin is playing any sound. for(i = 0; i < LOGIC_HASH_SIZE; i++) { for(it = logicHash[i].first; it; it = it->next) { if(it->origin == origin && (it->endTime > nowTime || it->isRepeating)) { // This one is playing. return true; } } } } // The sound was not found. return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_draw.c0000644000175000017500000002661111357170242022522 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_draw.c: Basic (Generic) Drawing Routines */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_base.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_render.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean drawFilter = false; static float filterColor[4] = { 0, 0, 0, 0 }; static boolean usePatchOffset = true; // A bit of a hack... // CODE -------------------------------------------------------------------- void GL_UsePatchOffset(boolean enable) { usePatchOffset = enable; } void GL_DrawRawScreen_CS(lumpnum_t lump, float offx, float offy, float scalex, float scaley) { boolean isTwoPart; float pixelBorder = 0; float tcb = 0; rawtex_t* raw; if(lump < 0 || lump >= numLumps) return; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); // Setup offset and scale. // Scale the offsets to match the resolution. glTranslatef(offx * theWindow->width / 320.0f, offy * theWindow->height / 200.0f, 0); glScalef(scalex, scaley, 1); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); GL_SetRawImage(lump, false, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); raw = R_GetRawTex(lump); isTwoPart = (raw->tex2 != 0); if(isTwoPart) { tcb = raw->height / 256.0f; } else { // Bottom texture coordinate. tcb = 1; } pixelBorder = raw->width * theWindow->width / 320; // The first part is rendered in any case. glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(pixelBorder, 0); glTexCoord2f(1, tcb); glVertex2f(pixelBorder, theWindow->height); glTexCoord2f(0, tcb); glVertex2f(0, theWindow->height); glEnd(); if(isTwoPart) { // And the other part. GL_SetRawImage(lump, true, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(pixelBorder, 0); glTexCoord2f(1, 0); glVertex2f(theWindow->width, 0); glTexCoord2f(1, tcb); glVertex2f(theWindow->width, theWindow->height); glTexCoord2f(0, tcb); glVertex2f(pixelBorder, theWindow->height); glEnd(); } // Restore the old projection matrix. glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } /** * Raw screens are 320 x 200. */ void GL_DrawRawScreen(lumpnum_t lump, float offx, float offy) { glColor3f(1, 1, 1); GL_DrawRawScreen_CS(lump, offx, offy, 1, 1); } /** * Drawing with the Current State. */ void GL_DrawPatch_CS(int posX, int posY, lumpnum_t lump) { float x = posX; float y = posY; float w, h; patchtex_t* p = R_GetPatchTex(lump); if(!p) return; // Set the texture. GL_BindTexture(GL_PreparePatch(p), glmode[texMagMode]); w = (float) p->width; h = (float) p->height; if(usePatchOffset) { x += (float) p->offX; y += (float) p->offY; } if(p->extraOffset[VX]) { // This offset is used only for the extra borders in the // "upscaled and sharpened" patches, so we can tweak the values // to our liking a bit more. x += p->extraOffset[VX] * .75f; y += p->extraOffset[VY] * .75f; w -= fabs(p->extraOffset[VX]) / 2; h -= fabs(p->extraOffset[VY]) / 2; } glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(1, 0); glVertex2f(x + w, y); glTexCoord2f(1, 1); glVertex2f(x + w, y + h); glTexCoord2f(0, 1); glVertex2f(x, y + h); glEnd(); // Is there a second part? if(GL_PreparePatchOtherPart(p)) { x += (float) p->width2; GL_BindTexture(GL_PreparePatchOtherPart(p), glmode[texMagMode]); w = (float) p->width2; glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(1, 0); glVertex2f(x + w, y); glTexCoord2f(1, 1); glVertex2f(x + w, y + h); glTexCoord2f(0, 1); glVertex2f(x, y + h); glEnd(); } } void GL_DrawPatchLitAlpha(int x, int y, float light, float alpha, lumpnum_t lump) { glColor4f(light, light, light, alpha); GL_DrawPatch_CS(x, y, lump); } void GL_DrawPatch(int x, int y, lumpnum_t lump) { if(lump < 0) return; GL_DrawPatchLitAlpha(x, y, 1, 1, lump); } void GL_DrawFuzzPatch(int x, int y, lumpnum_t lump) { if(lump < 0) return; GL_DrawPatchLitAlpha(x, y, 1, .333f, lump); } void GL_DrawAltFuzzPatch(int x, int y, lumpnum_t lump) { if(lump < 0) return; GL_DrawPatchLitAlpha(x, y, 1, .666f, lump); } void GL_DrawShadowedPatch(int x, int y, lumpnum_t lump) { if(lump < 0) return; GL_DrawPatchLitAlpha(x + 2, y + 2, 0, .4f, lump); GL_DrawPatchLitAlpha(x, y, 1, 1, lump); } void GL_DrawRect(float x, float y, float w, float h, float r, float g, float b, float a) { glColor4f(r, g, b, a); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(1, 0); glVertex2f(x + w, y); glTexCoord2f(1, 1); glVertex2f(x + w, y + h); glTexCoord2f(0, 1); glVertex2f(x, y + h); glEnd(); } void GL_DrawRectTiled(float x, float y, float w, float h, int tw, int th) { // Make sure the current texture will be tiled. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(x, y); glTexCoord2f(w / (float) tw, 0); glVertex2f(x + w, y); glTexCoord2f(w / (float) tw, h / (float) th); glVertex2f(x + w, y + h); glTexCoord2f(0, h / (float) th); glVertex2f(x, y + h); glEnd(); } /** * The cut rectangle must be inside the other one. */ void GL_DrawCutRectTiled(float x, float y, float w, float h, int tw, int th, int txoff, int tyoff, float cx, float cy, float cw, float ch) { float ftw = tw, fth = th; float txo = (1.0f / (float)tw) * (float)txoff; float tyo = (1.0f / (float)th) * (float)tyoff; // We'll draw at max four rectangles. float toph = cy - y, bottomh = y + h - (cy + ch), sideh = h - toph - bottomh, lefth = cx - x, righth = x + w - (cx + cw); glBegin(GL_QUADS); if(toph > 0) { // The top rectangle. glTexCoord2f(txo, tyo); glVertex2f(x, y); glTexCoord2f(txo + (w / ftw), tyo); glVertex2f(x + w, y ); glTexCoord2f(txo + (w / ftw), tyo + (toph / fth)); glVertex2f(x + w, y + toph); glTexCoord2f(txo, tyo + (toph / fth)); glVertex2f(x, y + toph); } if(lefth > 0 && sideh > 0) { float yoff = toph / fth; // The left rectangle. glTexCoord2f(txo, yoff + tyo); glVertex2f(x, y + toph); glTexCoord2f(txo + (lefth / ftw), yoff + tyo); glVertex2f(x + lefth, y + toph); glTexCoord2f(txo + (lefth / ftw), yoff + tyo + sideh / fth); glVertex2f(x + lefth, y + toph + sideh); glTexCoord2f(txo, yoff + tyo + sideh / fth); glVertex2f(x, y + toph + sideh); } if(righth > 0 && sideh > 0) { float ox = x + lefth + cw; float xoff = (lefth + cw) / ftw; float yoff = toph / fth; // The left rectangle. glTexCoord2f(xoff + txo, yoff + tyo); glVertex2f(ox, y + toph); glTexCoord2f(xoff + txo + righth / ftw, yoff + tyo); glVertex2f(ox + righth, y + toph); glTexCoord2f(xoff + txo + righth / ftw, yoff + tyo + sideh / fth); glVertex2f(ox + righth, y + toph + sideh); glTexCoord2f(xoff + txo, yoff + tyo + sideh / fth); glVertex2f(ox, y + toph + sideh); } if(bottomh > 0) { float oy = y + toph + sideh; float yoff = (toph + sideh) / fth; glTexCoord2f(txo, yoff + tyo); glVertex2f(x, oy); glTexCoord2f(txo + w / ftw, yoff + tyo); glVertex2f(x + w, oy); glTexCoord2f(txo + w / ftw, yoff + tyo + bottomh / fth); glVertex2f(x + w, oy + bottomh); glTexCoord2f(txo, yoff + tyo + bottomh / fth); glVertex2f(x, oy + bottomh); } glEnd(); } /** * Totally inefficient for a large number of lines. */ void GL_DrawLine(float x1, float y1, float x2, float y2, float r, float g, float b, float a) { glColor4f(r, g, b, a); glBegin(GL_LINES); glVertex2f(x1, y1); glVertex2f(x2, y2); glEnd(); } void GL_SetFilter(boolean enabled) { drawFilter = enabled; } void GL_SetFilterColor(float r, float g, float b, float a) { filterColor[CR] = MINMAX_OF(0, r, 1); filterColor[CG] = MINMAX_OF(0, g, 1); filterColor[CB] = MINMAX_OF(0, b, 1); filterColor[CA] = MINMAX_OF(0, a, 1); } /** * @return Non-zero if the filter was drawn. */ int GL_DrawFilter(void) { if(!drawFilter) return 0; // No filter needed. // No texture, please. glDisable(GL_TEXTURE_2D); glColor4fv(filterColor); glBegin(GL_QUADS); glVertex2f(viewwindowx, viewwindowy); glVertex2f(viewwindowx + viewwidth, viewwindowy); glVertex2f(viewwindowx + viewwidth, viewwindowy + viewheight); glVertex2f(viewwindowx, viewwindowy + viewheight); glEnd(); glEnable(GL_TEXTURE_2D); return 1; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_cmd.c0000644000175000017500000000726211357170242022166 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_cmd.c: Tic Commands * * Tic commands are generated out of controller state. There is one command * per input tic (35 Hz). The commands are used to control all players. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_network.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Combine the source ticcmd with the destination ticcmd. This is * done when there are multiple ticcmds to execute on a single game * tick. */ void P_MergeCommand(ticcmd_t *dest, ticcmd_t *src) { dest->forwardMove = src->forwardMove; dest->sideMove = src->sideMove; dest->upMove = src->upMove; dest->angle = src->angle; dest->pitch = src->pitch; dest->actions |= src->actions; } /** * Build one command for the specified player. This routine is used * to generate commands for local players. The commands are added to * the command buffer. * * This function is called from the input thread. */ void P_BuildCommand(ticcmd_t *cmd, int playerNumber) { memset(cmd, 0, sizeof(*cmd)); #if 0 ddplayer_t *player = &ddPlayers[playerNumber].shared; //client_t *client = clients + playerNumber; // Examine the state of controllers to see which controls are // active. // The player's class affects the movement speed. cmd->forwardMove = (char) (0x10 * P_ControlGetAxis(playerNumber, "walk")); cmd->sideMove = (char) (0x10 * P_ControlGetAxis(playerNumber, "sidestep")); // The view angles are updated elsewhere as the axis positions // change. if(player->mo) { // These will be sent to the server (or P_MovePlayer). cmd->angle = player->mo->angle >> 16; /* $unifiedangles */ } else cmd->angle = 0; /* $unifiedangles */ cmd->pitch = player->lookDir / 110 * DDMAXSHORT; cmd->actions = P_ControlGetToggles(playerNumber); //Con_Printf("%i: a=%04x p=%04x\n", playerNumber, cmd->angle, cmd->pitch); if(isClient) { // Clients mirror their local commands. memcpy(&players->cmd, cmd, sizeof(*cmd)); } #endif } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/bsp_superblock.c0000644000175000017500000006457211357170241024127 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_superblock.c: GL-friendly BSP node builder. Half-edge blockmap. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ /** * \notes * To be able to divide the nodes down, evalPartition must decide which is * the best half-edge to use as a nodeline. It does this by selecting the * line with least splits and has least difference of hald-edges on either * side of it. * * Credit to Raphael Quinet and DEU, this algorithm is a copy of the * nodeline picker used in DEU5beta. I am using this method because the * method I (AJA) originally used was not so good. * * Rewritten by Lee Killough to significantly improve performance, while not * affecting results one bit in >99% of cases (some tiny differences due to * roundoff error may occur, but they are insignificant). * * Rewritten again by Andrew Apted (-AJA-), 1999-2000. * Rewritten yet again by Daniel Swanson, 2007-2008. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_bsp.h" #include "de_play.h" #include "de_misc.h" #include #include #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct evalinfo_s { int cost; int splits; int iffy; int nearMiss; int realLeft; int realRight; int miniLeft; int miniRight; } evalinfo_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static __inline void calcIntersection(hedge_t* cur, const bspartition_t* part, double perpC, double perpD, double* x, double* y); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static superblock_t* quickAllocSupers; // CODE -------------------------------------------------------------------- /** * Init the superblock allocator. */ void BSP_InitSuperBlockAllocator(void) { quickAllocSupers = NULL; } /** * Free all the superblocks on the quick-alloc list. */ void BSP_ShutdownSuperBlockAllocator(void) { while(quickAllocSupers) { superblock_t* block = quickAllocSupers; quickAllocSupers = block->subs[0]; M_Free(block); } } /** * Acquire memory for a new superblock. */ static superblock_t* allocSuperBlock(void) { superblock_t* superblock; if(quickAllocSupers == NULL) return M_Calloc(sizeof(superblock_t)); superblock = quickAllocSupers; quickAllocSupers = superblock->subs[0]; // Clear out any old rubbish. memset(superblock, 0, sizeof(*superblock)); return superblock; } /** * Free all memory allocated for the specified superblock. */ static void freeSuperBlock(superblock_t* superblock) { uint num; if(superblock->hEdges) { // This can happen, but only under abnormal circumstances. #if _DEBUG Con_Error("FreeSuper: Superblock contains half-edges!"); #endif superblock->hEdges = NULL; } // Recursively handle sub-blocks. for(num = 0; num < 2; ++num) { if(superblock->subs[num]) freeSuperBlock(superblock->subs[num]); } // Add block to quick-alloc list. Note that subs[0] is used for // linking the blocks together. superblock->subs[0] = quickAllocSupers; quickAllocSupers = superblock; } superblock_t* BSP_SuperBlockCreate(void) { return allocSuperBlock(); } void BSP_SuperBlockDestroy(superblock_t* superblock) { freeSuperBlock(superblock); } /** * Link the given half-edge into the given superblock. */ void BSP_LinkHEdgeToSuperBlock(superblock_t* superblock, hedge_t* hEdge) { hEdge->next = superblock->hEdges; hEdge->block = superblock; superblock->hEdges = hEdge; } /** * Increase the counts within the superblock, to account for the given * half-edge being split. */ void BSP_IncSuperBlockHEdgeCounts(superblock_t* superblock, boolean lineLinked) { do { if(lineLinked) superblock->realNum++; else superblock->miniNum++; superblock = superblock->parent; } while(superblock != NULL); } static void makeIntersection(cutlist_t* cutList, vertex_t* vert, const bspartition_t* part, boolean selfRef) { intersection_t* cut = BSP_CutListFindIntersection(cutList, vert); if(!cut) { cut = BSP_IntersectionCreate(vert, part, selfRef); BSP_CutListInsertIntersection(cutList, cut); } } /** * Partition the given edge and perform any further necessary action (moving * it into either the left list, right list, or splitting it). * * Take the given half-edge 'cur', compare it with the partition line, and * determine it's fate: moving it into either the left or right lists * (perhaps both, when splitting it in two). Handles the twin as well. * Updates the intersection list if the half-edge lies on or crosses the * partition line. * * \note * I have rewritten this routine based on evalPartition() (which I've also * reworked, heavily). I think it is important that both these routines * follow the exact same logic when determining which half-edges should go * left, right or be split. - AJA */ void BSP_DivideOneHEdge(hedge_t* cur, const bspartition_t* part, superblock_t* rightList, superblock_t* leftList, cutlist_t* cutList) { hedge_t* newHEdge; double x, y; double a, b; boolean selfRef = (cur->lineDef? (cur->lineDef->buildData.mlFlags & MLF_SELFREF) : false); // Get state of lines' relation to each other. a = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->length, cur->pSX, cur->pSY); b = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->length, cur->pEX, cur->pEY); if(cur->sourceLine == part->sourceLine) a = b = 0; // Check for being on the same line. if(fabs(a) <= DIST_EPSILON && fabs(b) <= DIST_EPSILON) { makeIntersection(cutList, cur->v[0], part, selfRef); makeIntersection(cutList, cur->v[1], part, selfRef); // This seg runs along the same line as the partition. Check // whether it goes in the same direction or the opposite. if(cur->pDX * part->pDX + cur->pDY * part->pDY < 0) { BSP_AddHEdgeToSuperBlock(leftList, cur); } else { BSP_AddHEdgeToSuperBlock(rightList, cur); } return; } // Check for right side. if(a > -DIST_EPSILON && b > -DIST_EPSILON) { if(a < DIST_EPSILON) makeIntersection(cutList, cur->v[0], part, selfRef); else if(b < DIST_EPSILON) makeIntersection(cutList, cur->v[1], part, selfRef); BSP_AddHEdgeToSuperBlock(rightList, cur); return; } // Check for left side. if(a < DIST_EPSILON && b < DIST_EPSILON) { if(a > -DIST_EPSILON) makeIntersection(cutList, cur->v[0], part, selfRef); else if(b > -DIST_EPSILON) makeIntersection(cutList, cur->v[1], part, selfRef); BSP_AddHEdgeToSuperBlock(leftList, cur); return; } // When we reach here, we have a and b non-zero and opposite sign, // hence this edge will be split by the partition line. calcIntersection(cur, part, a, b, &x, &y); newHEdge = HEdge_Split(cur, x, y); makeIntersection(cutList, cur->v[1], part, selfRef); if(a < 0) { BSP_AddHEdgeToSuperBlock(leftList, cur); BSP_AddHEdgeToSuperBlock(rightList, newHEdge); } else { BSP_AddHEdgeToSuperBlock(rightList, cur); BSP_AddHEdgeToSuperBlock(leftList, newHEdge); } } static void partitionHEdges(superblock_t* hEdgeList, const bspartition_t* part, superblock_t* rights, superblock_t* lefts, cutlist_t* cutList) { uint num; while(hEdgeList->hEdges) { hedge_t* cur = hEdgeList->hEdges; hEdgeList->hEdges = cur->next; cur->block = NULL; BSP_DivideOneHEdge(cur, part, rights, lefts, cutList); } // Recursively handle sub-blocks. for(num = 0; num < 2; ++num) { superblock_t* a = hEdgeList->subs[num]; if(a) { partitionHEdges(a, part, rights, lefts, cutList); if(a->realNum + a->miniNum > 0) Con_Error("BSP_SeparateHEdges: child %d not empty!", num); BSP_SuperBlockDestroy(a); hEdgeList->subs[num] = NULL; } } hEdgeList->realNum = hEdgeList->miniNum = 0; } /** * Remove all the half-edges from the list, partitioning them into the left * or right lists based on the given partition line. Adds any intersections * onto the intersection list as it goes. */ void BSP_PartitionHEdges(superblock_t* hEdgeList, const bspartition_t* part, superblock_t* rights, superblock_t* lefts, cutlist_t* cutList) { partitionHEdges(hEdgeList, part, rights, lefts, cutList); // Sanity checks... if(rights->realNum + rights->miniNum == 0) Con_Error("BuildNodes: Separated halfedge-list has no right side."); if(lefts->realNum + lefts->miniNum == 0) Con_Error("BuildNodes: Separated halfedge-list has no left side."); BSP_AddMiniHEdges(part, rights, lefts, cutList); } /** * @return @c true, if a "bad half-edge" was found early. */ static int evalPartitionWorker(const superblock_t* hEdgeList, hedge_t* part, int bestCost, evalinfo_t* info) { #define ADD_LEFT() \ do { \ if (check->lineDef) info->realLeft += 1; \ else info->miniLeft += 1; \ } while (0) #define ADD_RIGHT() \ do { \ if (check->lineDef) info->realRight += 1; \ else info->miniRight += 1; \ } while (0) int num; int factor = bspFactor; hedge_t* check; double qnty; double a, b, fa, fb; /** * This is the heart of my superblock idea, it tests the _whole_ block * against the partition line to quickly handle all the half-edges * within it at once. Only when the partition line intercepts the box do * we need to go deeper into it - AJA. */ num = P_BoxOnLineSide3(hEdgeList->bbox, part->pSX, part->pSY, part->pDX, part->pDY, part->pPerp, part->pLength, DIST_EPSILON); if(num < 0) { // Left. info->realLeft += hEdgeList->realNum; info->miniLeft += hEdgeList->miniNum; return false; } else if(num > 0) { // Right. info->realRight += hEdgeList->realNum; info->miniRight += hEdgeList->miniNum; return false; } // Check partition against all half-edges. for(check = hEdgeList->hEdges; check; check = check->next) { // This is the heart of my pruning idea - it catches // "bad half-edges" early on - LK. if(info->cost > bestCost) return true; // Get state of lines' relation to each other. if(check->sourceLine == part->sourceLine) { a = b = fa = fb = 0; } else { a = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->pLength, check->pSX, check->pSY); b = M_PerpDist(part->pDX, part->pDY, part->pPerp, part->pLength, check->pEX, check->pEY); fa = fabs(a); fb = fabs(b); } // Check for being on the same line. if(fa <= DIST_EPSILON && fb <= DIST_EPSILON) { // This half-edge runs along the same line as the partition. // Check whether it goes in the same direction or the opposite. if(check->pDX * part->pDX + check->pDY * part->pDY < 0) { ADD_LEFT(); } else { ADD_RIGHT(); } continue; } // Check for right side. if(a > -DIST_EPSILON && b > -DIST_EPSILON) { ADD_RIGHT(); // Check for a near miss. if((a >= IFFY_LEN && b >= IFFY_LEN) || (a <= DIST_EPSILON && b >= IFFY_LEN) || (b <= DIST_EPSILON && a >= IFFY_LEN)) { continue; } info->nearMiss++; /** * Near misses are bad, since they have the potential to cause * really short minihedges to be created in future processing. * Thus the closer the near miss, the higher the cost - AJA. */ if(a <= DIST_EPSILON || b <= DIST_EPSILON) qnty = IFFY_LEN / MAX_OF(a, b); else qnty = IFFY_LEN / MIN_OF(a, b); info->cost += (int) (100 * factor * (qnty * qnty - 1.0)); continue; } // Check for left side. if(a < DIST_EPSILON && b < DIST_EPSILON) { ADD_LEFT(); // Check for a near miss. if((a <= -IFFY_LEN && b <= -IFFY_LEN) || (a >= -DIST_EPSILON && b <= -IFFY_LEN) || (b >= -DIST_EPSILON && a <= -IFFY_LEN)) { continue; } info->nearMiss++; // The closer the miss, the higher the cost (see note above). if(a >= -DIST_EPSILON || b >= -DIST_EPSILON) qnty = IFFY_LEN / -MIN_OF(a, b); else qnty = IFFY_LEN / -MAX_OF(a, b); info->cost += (int) (70 * factor * (qnty * qnty - 1.0)); continue; } /** * When we reach here, we have a and b non-zero and opposite sign, * hence this half-edge will be split by the partition line. */ info->splits++; info->cost += 100 * factor; /** * Check if the split point is very close to one end, which is quite * an undesirable situation (producing really short edges). This is * perhaps _one_ source of those darn slime trails. Hence the name * "IFFY segs", and a rather hefty surcharge - AJA. */ if(fa < IFFY_LEN || fb < IFFY_LEN) { info->iffy++; // The closer to the end, the higher the cost. qnty = IFFY_LEN / MIN_OF(fa, fb); info->cost += (int) (140 * factor * (qnty * qnty - 1.0)); } } // Handle sub-blocks recursively. for(num = 0; num < 2; ++num) { if(!hEdgeList->subs[num]) continue; if(evalPartitionWorker(hEdgeList->subs[num], part, bestCost, info)) return true; } // No "bad half-edge" was found. Good. return false; #undef ADD_LEFT #undef ADD_RIGHT } /** * Evaluate a partition and determine the cost, taking into account the * number of splits and the difference between left and right. * * @return The computed cost, or a negative value if the edge * should be skipped altogether. */ static int evalPartition(const superblock_t* hEdgeList, hedge_t* part, int bestCost) { evalinfo_t info; // Initialize info structure. info.cost = 0; info.splits = 0; info.iffy = 0; info.nearMiss = 0; info.realLeft = 0; info.realRight = 0; info.miniLeft = 0; info.miniRight = 0; if(evalPartitionWorker(hEdgeList, part, bestCost, &info)) return -1; // Make sure there is at least one real seg on each side. if(!info.realLeft || !info.realRight) { /*#if _DEBUG Con_Message("Eval : No real half-edges on %s%sside\n", (info.realLeft? "" : "left "), (info.realRight? "" : "right ")); #endif*/ return -1; } // Increase cost by the difference between left and right. info.cost += 100 * ABS(info.realLeft - info.realRight); // Allow minihedge counts to affect the outcome, but only to a lesser // degree than real half-edges - AJA. info.cost += 50 * ABS(info.miniLeft - info.miniRight); // Another little twist, here we show a slight preference for partition // lines that lie either purely horizontally or purely vertically - AJA. if(part->pDX != 0 && part->pDY != 0) info.cost += 25; /*#if _DEBUG Con_Message("Eval %p: splits=%d iffy=%d near=%d left=%d+%d right=%d+%d " "cost=%d.%02d\n", part, info.splits, info.iffy, info.nearMiss, info.realLeft, info.miniLeft, info.realRight, info.miniRight, info.cost / 100, info.cost % 100); #endif*/ return info.cost; } /** * @return @c false, if cancelled. */ static boolean pickHEdgeWorker(const superblock_t* partList, const superblock_t* hEdgeList, hedge_t** best, int* bestCost) { int num, cost; hedge_t* part; // Test each half-edge as a potential partition. for(part = partList->hEdges; part; part = part->next) { /*#if _DEBUG Con_Message("BSP_PickHEdge: %sSEG %p sector=%d (%1.1f,%1.1f) -> " "(%1.1f,%1.1f)\n", (part->lineDef? "" : "MINI"), part, (part->sector? part->sector->index : -1), part->v[0]->V_pos[VX], part->v[0]->V_pos[VY], part->v[1]->V_pos[VX], part->v[1]->V_pos[VY]); #endif*/ // Ignore minihedges as partition candidates. if(!part->lineDef) continue; // Only test half-edges from the same linedef once per round of // partition picking (they are collinear). if(part->lineDef->validCount == validCount) continue; part->lineDef->validCount = validCount; cost = evalPartition(hEdgeList, part, *bestCost); // half-edge unsuitable or too costly? if(cost < 0 || cost >= *bestCost) continue; // We have a new better choice. (*bestCost) = cost; // Remember which half-edge. (*best) = part; } // Recursively handle sub-blocks. for(num = 0; num < 2; ++num) { if(partList->subs[num]) pickHEdgeWorker(partList->subs[num], hEdgeList, best, bestCost); } return true; } /** * Find the best half-edge in the list to use as a partition. * * @param hEdgeList List of half-edges to choose from. * @param depth Current node depth. * @param partition Ptr to partition to be updated with the results. * * @return @c true, iff a suitable partition was found. */ boolean BSP_PickPartition(const superblock_t* hEdgeList, size_t depth, bspartition_t* partition) { int bestCost = INT_MAX; hedge_t* best = NULL; /*#if _DEBUG Con_Message("BSP_PickPartition: Begun (depth %lu)\n", (unsigned long) depth); #endif*/ validCount++; if(false == pickHEdgeWorker(hEdgeList, hEdgeList, &best, &bestCost)) { // \hack BuildNodes will detect the cancellation. return false; } // Finished, return the best partition. if(best) { /*if _DEBUG Con_Message("BSP_PickPartition: Best has score %d.%02d (%1.1f,%1.1f) -> " "(%1.1f,%1.1f)\n", bestCost / 100, bestCost % 100, best->v[0]->V_pos[VX], best->v[0]->V_pos[VY], best->v[1]->V_pos[VX], best->v[1]->V_pos[VY]); #endif*/ assert(best->lineDef); partition->x = best->lineDef->v[best->side]->buildData.pos[VX]; partition->y = best->lineDef->v[best->side]->buildData.pos[VY]; partition->dX = best->lineDef->v[best->side^1]->buildData.pos[VX] - partition->x; partition->dY = best->lineDef->v[best->side^1]->buildData.pos[VY] - partition->y; partition->lineDef = best->lineDef; partition->sourceLine = best->sourceLine; partition->pDX = best->pDX; partition->pDY = best->pDY; partition->pSX = best->pSX; partition->pSY = best->pSY; partition->pPara = best->pPara; partition->pPerp = best->pPerp; partition->length = best->pLength; return true; } /*#if _DEBUG Con_Message("BSP_PickPartition: No best found!\n"); #endif*/ return false; } static void findLimitWorker(superblock_t* block, float* bbox) { uint num; hedge_t* cur; for(cur = block->hEdges; cur; cur = cur->next) { double x1 = cur->v[0]->buildData.pos[VX]; double y1 = cur->v[0]->buildData.pos[VY]; double x2 = cur->v[1]->buildData.pos[VX]; double y2 = cur->v[1]->buildData.pos[VY]; float lx = (float) MIN_OF(x1, x2); float ly = (float) MIN_OF(y1, y2); float hx = (float) MAX_OF(x1, x2); float hy = (float) MAX_OF(y1, y2); if(lx < bbox[BOXLEFT]) bbox[BOXLEFT] = lx; else if(lx > bbox[BOXRIGHT]) bbox[BOXRIGHT] = lx; if(ly < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = ly; else if(ly > bbox[BOXTOP]) bbox[BOXTOP] = ly; if(hx < bbox[BOXLEFT]) bbox[BOXLEFT] = hx; else if(hx > bbox[BOXRIGHT]) bbox[BOXRIGHT] = hx; if(hy < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = hy; else if(hy > bbox[BOXTOP]) bbox[BOXTOP] = hy; } // Recursively handle sub-blocks. for(num = 0; num < 2; ++num) { if(block->subs[num]) findLimitWorker(block->subs[num], bbox); } } static void findLimits(superblock_t* hEdgeList, float* bbox) { bbox[BOXTOP] = bbox[BOXRIGHT] = DDMINFLOAT; bbox[BOXBOTTOM] = bbox[BOXLEFT] = DDMAXFLOAT; findLimitWorker(hEdgeList, bbox); } /** * Find the extremes of a box containing all half-edges. */ void BSP_FindNodeBounds(bspnodedata_t* node, superblock_t* hEdgesRightList, superblock_t* hEdgesLeftList) { findLimits(hEdgesLeftList, &node->bBox[LEFT][0]); findLimits(hEdgesRightList, &node->bBox[RIGHT][0]); } /** * Calculate the intersection location between the current half-edge and the * partition. Takes advantage of some common situations like horizontal and * vertical lines to choose a 'nicer' intersection point. */ static __inline void calcIntersection(hedge_t* cur, const bspartition_t* part, double perpC, double perpD, double* x, double* y) { double ds; // Horizontal partition against vertical half-edge. if(part->pDY == 0 && cur->pDX == 0) { *x = cur->pSX; *y = part->pSY; return; } // Vertical partition against horizontal half-edge. if(part->pDX == 0 && cur->pDY == 0) { *x = part->pSX; *y = cur->pSY; return; } // 0 = start, 1 = end. ds = perpC / (perpC - perpD); if(cur->pDX == 0) *x = cur->pSX; else *x = cur->pSX + (cur->pDX * ds); if(cur->pDY == 0) *y = cur->pSY; else *y = cur->pSY + (cur->pDY * ds); } /** * For debugging. */ #if _DEBUG void BSP_PrintSuperblockHEdges(superblock_t* superblock) { hedge_t* hEdge; int num; for(hEdge = superblock->hEdges; hEdge; hEdge = hEdge->next) { Con_Message("Build: %s %p sector=%d (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", (hEdge->lineDef? "NORM" : "MINI"), hEdge, hEdge->sector->buildData.index, hEdge->v[0]->buildData.pos[VX], hEdge->v[0]->buildData.pos[VY], hEdge->v[1]->buildData.pos[VX], hEdge->v[1]->buildData.pos[VY]); } for(num = 0; num < 2; ++num) { if(superblock->subs[num]) BSP_PrintSuperblockHEdges(superblock->subs[num]); } } static void testSuperWorker(superblock_t* block, int* real, int* mini) { int num; hedge_t* cur; for(cur = block->hEdges; cur; cur = cur->next) { if(cur->lineDef) (*real) += 1; else (*mini) += 1; } for(num = 0; num < 2; ++num) { if(block->subs[num]) testSuperWorker(block->subs[num], real, mini); } } /** * For debugging. */ void testSuper(superblock_t* block) { int realNum = 0; int miniNum = 0; testSuperWorker(block, &realNum, &miniNum); if(realNum != block->realNum || miniNum != block->miniNum) Con_Error("testSuper: Failed, block=%p %d/%d != %d/%d", block, block->realNum, block->miniNum, realNum, miniNum); } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sv_sound.c0000644000175000017500000001076411357170242022745 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_sound.c: Server-side Sound Management */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_refresh.h" #include "de_play.h" #include "de_audio.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Tell clients to play a sound with full volume. */ void Sv_Sound(int sound_id, mobj_t *origin, int toPlr) { Sv_SoundAtVolume(sound_id, origin, 1, toPlr); } /** * Finds the sector/polyobj to whom the origin mobj belong. */ static void Sv_IdentifySoundOrigin(mobj_t **origin, sector_t **sector, polyobj_t **poly) { *sector = NULL; *poly = NULL; if(*origin && !(*origin)->thinker.id) { // No mobj ID => it's not a real mobj. if(P_IsPolyobjOrigin(*origin)) *poly = (polyobj_t*) *origin; else { // It wasn't a polyobj. // Try the sectors instead. *sector = R_GetSectorForOrigin(*origin); } #ifdef _DEBUG if(*poly == NULL && *sector == NULL) { Con_Error("Sv_IdentifySoundOrigin: Bad mobj.\n"); } #endif *origin = NULL; } } /** * Tell clients to play a sound. */ void Sv_SoundAtVolume(int soundIDAndFlags, mobj_t *origin, float volume, int toPlr) { int soundID = (soundIDAndFlags & ~DDSF_FLAG_MASK); sector_t *sector; polyobj_t *poly; int targetPlayers = 0; if(isClient || !soundID) return; Sv_IdentifySoundOrigin(&origin, §or, &poly); if(toPlr & SVSF_TO_ALL) { targetPlayers = -1; } else { targetPlayers = (1 << (toPlr & 0xf)); } if(toPlr & SVSF_EXCLUDE_ORIGIN) { // Remove the bit of the player who owns the origin mobj (if any). if(origin && origin->dPlayer) { targetPlayers &= ~(1 << P_GetDDPlayerIdx(origin->dPlayer)); } } #ifdef _DEBUG VERBOSE( Con_Message("Sv_SoundAtVolume: Id=%i, vol=%g, targets=%x\n", soundID, volume, targetPlayers) ); #endif Sv_NewSoundDelta(soundID, origin, sector, poly, volume, (soundIDAndFlags & DDSF_REPEAT) != 0, targetPlayers); } /** * This is called when the server needs to tell clients to stop * a sound. */ void Sv_StopSound(int sound_id, mobj_t *origin) { sector_t *sector; polyobj_t *poly; if(isClient) return; Sv_IdentifySoundOrigin(&origin, §or, &poly); /*#ifdef _DEBUG Con_Printf("Sv_StopSound: id=%i origin=%i(%p) sec=%i poly=%i\n", sound_id, origin? origin->thinker.id : 0, origin, sector, poly); #endif */ // Send the stop sound delta to everybody. // Volume zero means silence. Sv_NewSoundDelta(sound_id, origin, sector, poly, 0, false, -1); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_sector.c0000644000175000017500000001051611357170242022716 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_sector.c: World sectors. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Update the sector, property is selected by DMU_* name. */ boolean Sector_SetProperty(sector_t *sec, const setargs_t *args) { switch(args->prop) { case DMU_COLOR: DMU_SetValue(DMT_SECTOR_RGB, &sec->rgb[0], args, 0); DMU_SetValue(DMT_SECTOR_RGB, &sec->rgb[1], args, 1); DMU_SetValue(DMT_SECTOR_RGB, &sec->rgb[2], args, 2); break; case DMU_COLOR_RED: DMU_SetValue(DMT_SECTOR_RGB, &sec->rgb[0], args, 0); break; case DMU_COLOR_GREEN: DMU_SetValue(DMT_SECTOR_RGB, &sec->rgb[1], args, 0); break; case DMU_COLOR_BLUE: DMU_SetValue(DMT_SECTOR_RGB, &sec->rgb[2], args, 0); break; case DMU_LIGHT_LEVEL: DMU_SetValue(DMT_SECTOR_LIGHTLEVEL, &sec->lightLevel, args, 0); break; case DMU_VALID_COUNT: DMU_SetValue(DMT_SECTOR_VALIDCOUNT, &sec->validCount, args, 0); break; default: Con_Error("Sector_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } /** * Get the value of a sector property, selected by DMU_* name. */ boolean Sector_GetProperty(const sector_t *sec, setargs_t *args) { switch(args->prop) { case DMU_LIGHT_LEVEL: DMU_GetValue(DMT_SECTOR_LIGHTLEVEL, &sec->lightLevel, args, 0); break; case DMU_COLOR: DMU_GetValue(DMT_SECTOR_RGB, &sec->rgb[0], args, 0); DMU_GetValue(DMT_SECTOR_RGB, &sec->rgb[1], args, 1); DMU_GetValue(DMT_SECTOR_RGB, &sec->rgb[2], args, 2); break; case DMU_COLOR_RED: DMU_GetValue(DMT_SECTOR_RGB, &sec->rgb[0], args, 0); break; case DMU_COLOR_GREEN: DMU_GetValue(DMT_SECTOR_RGB, &sec->rgb[1], args, 0); break; case DMU_COLOR_BLUE: DMU_GetValue(DMT_SECTOR_RGB, &sec->rgb[2], args, 0); break; case DMU_SOUND_ORIGIN: { const ddmobj_base_t* dmo = &sec->soundOrg; DMU_GetValue(DMT_SECTOR_SOUNDORG, &dmo, args, 0); break; } case DMU_LINEDEF_COUNT: { int val = (int) sec->lineDefCount; DMU_GetValue(DDVT_INT, &val, args, 0); break; } case DMT_MOBJS: DMU_GetValue(DMT_SECTOR_MOBJLIST, &sec->mobjList, args, 0); break; case DMU_VALID_COUNT: DMU_GetValue(DMT_SECTOR_VALIDCOUNT, &sec->validCount, args, 0); break; default: Con_Error("Sector_GetProperty: No property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_mobj.c0000644000175000017500000007310711357170241022511 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_mobj.c: Client Map Objects */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_defs.h" #include "de_system.h" #include "de_console.h" #include "de_network.h" #include "de_play.h" #include "de_audio.h" // MACROS ------------------------------------------------------------------ // The client mobjs are stored into a hash to speed up the searching. #define HASH_SIZE 256 // Convert 8.8/10.6 fixed point to 16.16. #define UNFIXED8_8(x) (((x) << 16) / 256) #define UNFIXED10_6(x) (((x) << 16) / 64) // Milliseconds it takes for Unpredictable and Hidden mobjs to be // removed from the hash. Under normal circumstances, the special // status should be removed fairly quickly (a matter of out-of-sequence // frames or sounds playing before a mobj is sent). #define CLMOBJ_TIMEOUT 10000 // 10 seconds // Missiles don't hit mobjs only after a short delay. This'll // allow the missile to move free of the shooter. (Quite a hack!) #define MISSILE_FREE_MOVE_TIME 1000 // TYPES ------------------------------------------------------------------- typedef struct cmhash_s { clmobj_t *first, *last; } cmhash_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int /*latest_frame_size, */ gotFrame; extern int predicted_tics; // PUBLIC DATA DEFINITIONS ------------------------------------------------- cmhash_t cmHash[HASH_SIZE]; //int predict_tics = 70; // Time skew tells whether client time is running before or after frame time. //int net_timeskew = 0; //int net_skewdampen = 5; // In frames. //boolean net_showskew = false; //boolean pred_forward = true; // Predicting forward in time. // PRIVATE DATA DEFINITIONS ------------------------------------------------ //static byte previous_time = 0; // CODE -------------------------------------------------------------------- /** * @return Pointer to the hash chain with the specified id. */ cmhash_t *Cl_MobjHash(thid_t id) { return &cmHash[(uint) id % HASH_SIZE]; } /** * Links the clmobj into the client mobj hash table. */ void Cl_LinkMobj(clmobj_t *cmo, thid_t id) { cmhash_t *hash = Cl_MobjHash(id); // Set the ID. cmo->mo.thinker.id = id; cmo->next = NULL; if(hash->last) { hash->last->next = cmo; cmo->prev = hash->last; } hash->last = cmo; if(!hash->first) { hash->first = cmo; } } /** * Unlinks the clmobj from the client mobj hash table. */ void Cl_UnlinkMobj(clmobj_t *cmo) { cmhash_t *hash = Cl_MobjHash(cmo->mo.thinker.id); /* #ifdef _DEBUG if(cmo->flags & CLMF_HIDDEN) { Con_Printf("Cl_UnlinkMobj: Hidden mobj %i unlinked.\n", cmo->mo.thinker.id); } #endif */ if(hash->first == cmo) hash->first = cmo->next; if(hash->last == cmo) hash->last = cmo->prev; if(cmo->next) cmo->next->prev = cmo->prev; if(cmo->prev) cmo->prev->next = cmo->next; } /** * Searches through the client mobj hash table and returns the clmobj * with the specified ID, if that exists. */ clmobj_t *Cl_FindMobj(thid_t id) { cmhash_t *hash = Cl_MobjHash(id); clmobj_t *cmo; // Scan the existing client mobjs. for(cmo = hash->first; cmo; cmo = cmo->next) { if(cmo->mo.thinker.id == id) return cmo; } // Not found! return NULL; } /** * Iterate the client mobj hash, exec the callback on each. Abort if callback * returns @c false. * * @return If the callback returns @c false. */ boolean Cl_MobjIterator(boolean (*callback) (clmobj_t *, void *), void *parm) { clmobj_t *cmo; int i; for(i = 0; i < HASH_SIZE; ++i) { for(cmo = cmHash[i].first; cmo; cmo = cmo->next) { if(!callback(cmo, parm)) return false; } } return true; } /** * Unlinks the mobj from sectorlinks and if the object is solid, * the blockmap. */ void Cl_UnsetMobjPosition(clmobj_t *cmo) { P_MobjUnlink(&cmo->mo); } /** * Links the mobj into sectorlinks and if the object is solid, the * blockmap. Linking to sectorlinks makes the mobj visible and linking * to the blockmap makes it possible to interact with it (collide). * If the client mobj is Hidden, it will not be linked anywhere. */ void Cl_SetMobjPosition(clmobj_t *cmo) { mobj_t *mo = &cmo->mo; if((cmo->flags & (CLMF_HIDDEN | CLMF_UNPREDICTABLE)) || mo->dPlayer) { // We do not yet have all the details about Hidden mobjs. // The server hasn't sent us a Create Mobj delta for them. // Client mobjs that belong to players remain unlinked. return; } P_MobjLink(mo, (mo->ddFlags & DDMF_DONTDRAW ? 0 : DDLINK_SECTOR) | (mo->ddFlags & DDMF_SOLID ? DDLINK_BLOCKMAP : 0)); } /** * Change the state of a mobj. */ void Cl_SetMobjState(mobj_t *mo, int stnum) { if(stnum < 0) return; do { P_MobjSetState(mo, stnum); stnum = states[stnum].nextState; } while(!mo->tics && stnum > 0); // Update mobj's type (this is not perfectly reliable...) // from the stateOwners table. if(stateOwners[stnum]) mo->type = stateOwners[stnum] - mobjInfo; else mo->type = 0; } /** * Updates floorz and ceilingz of the mobj. */ void Cl_CheckMobj(clmobj_t *cmo, boolean justCreated) { mobj_t *mo = &cmo->mo; boolean onFloor = false, inCeiling = false; if(mo->pos[VZ] == DDMINFLOAT) { // Make the mobj stick to the floor. cmo->flags |= CLMF_STICK_FLOOR; // Give it a real Z coordinate. onFloor = true; mo->pos[VZ] = mo->floorZ; } if(mo->pos[VZ] == DDMAXFLOAT) { // Make the mobj stick to the ceiling. cmo->flags |= CLMF_STICK_CEILING; // Give it a real Z coordinate. inCeiling = true; mo->pos[VZ] = mo->ceilingZ - mo->height; } // Find out floor and ceiling z. P_CheckPosXYZ(mo, mo->pos[VX], mo->pos[VY], mo->pos[VZ]); mo->floorZ = tmpFloorZ; mo->ceilingZ = tmpCeilingZ; if(onFloor) { mo->pos[VZ] = mo->floorZ; } if(inCeiling) { mo->pos[VZ] = mo->ceilingZ - mo->height; } #if 0 // P_CheckPosition sets blockingMobj. # ifdef _DEBUG /*if(blockingMobj) Con_Printf("Collision %i\n", mo->thinker.id); */ if(justCreated && mo->ddFlags & DDMF_MISSILE) { Con_Printf("Misl creat %i, (%g %g %g) mom (%g %g %g)\n", mo->thinker.id, mo->pos[VX], mo->pos[VY], mo->pos[VZ], mo->mom[MX], mo->mom[MY], mo->mom[MZ]); } # endif if(justCreated && mo->ddFlags & DDMF_MISSILE && blockingMobj != NULL) { // This happens when a missile is created inside an object // (the shooter, typically). We allow the missile to noclip // through mobjs until it's free. cmo->flags |= CLMF_OVERLAPPING; # ifdef _DEBUG Con_Printf("Overlap %i\n", mo->thinker.id); # endif } #endif } /** * Make the real player mobj identical with the client mobj. * The client mobj is always unlinked. Only the *real* mobj is visible. * (The real mobj was created by the Game.) */ void Cl_UpdateRealPlayerMobj(mobj_t *mo, mobj_t *clmo, int flags) { #if _DEBUG if(!mo || !clmo) { VERBOSE( Con_Message("Cl_UpdateRealPlayerMobj: mo=%p clmo=%p\n", mo, clmo) ); return; } #endif if(flags & (MDF_POS_X | MDF_POS_Y)) { // We have to unlink the real mobj before we move it. P_MobjUnlink(mo); mo->pos[VX] = clmo->pos[VX]; mo->pos[VY] = clmo->pos[VY]; P_MobjLink(mo, DDLINK_SECTOR | DDLINK_BLOCKMAP); } mo->pos[VZ] = clmo->pos[VZ]; if(flags & MDF_MOM_X) mo->mom[MX] = clmo->mom[MX]; if(flags & MDF_MOM_Y) mo->mom[MY] = clmo->mom[MY]; if(flags & MDF_MOM_Z) mo->mom[MZ] = clmo->mom[MZ]; if(flags & MDF_ANGLE) { mo->angle = clmo->angle; #ifdef _DEBUG VERBOSE( Con_Message("Cl_UpdateRealPlayerMobj: mo=%p angle=%x\n", mo, mo->angle) ); #endif } mo->sprite = clmo->sprite; mo->frame = clmo->frame; //mo->nextframe = clmo->nextframe; mo->tics = clmo->tics; mo->state = clmo->state; //mo->nexttime = clmo->nexttime; mo->ddFlags = clmo->ddFlags; mo->radius = clmo->radius; mo->height = clmo->height; mo->floorClip = clmo->floorClip; mo->floorZ = clmo->floorZ; mo->ceilingZ = clmo->ceilingZ; mo->selector &= ~DDMOBJ_SELECTOR_MASK; mo->selector |= clmo->selector & DDMOBJ_SELECTOR_MASK; mo->visAngle = clmo->angle >> 16; //if(flags & MDF_FLAGS) CON_Printf("Cl_RMD: ddf=%x\n", mo->ddFlags); } /** * Reads a single mobj delta from the message buffer and applies * it to the client mobj in question. * For client mobjs that belong to players, updates the real player mobj. * Returns false only if the list of deltas ends. * * THIS FUNCTION IS NOW OBSOLETE (only used with old PSV_FRAME packets) */ int Cl_ReadMobjDelta(void) { thid_t id = Msg_ReadShort(); // Read the ID. clmobj_t *cmo; boolean linked = true; int df = 0; mobj_t *d; boolean justCreated = false; // Stop if end marker found. if(!id) return false; // Get a mobj for this. cmo = Cl_FindMobj(id); if(!cmo) { justCreated = true; // This is a new ID, allocate a new mobj. cmo = Z_Malloc(sizeof(*cmo), PU_MAP, 0); memset(cmo, 0, sizeof(*cmo)); cmo->mo.ddFlags |= DDMF_REMOTE; Cl_LinkMobj(cmo, id); P_SetMobjID(id, true); // Mark this ID as used. linked = false; } // This client mobj is alive. cmo->time = Sys_GetRealTime(); // Flags. df = Msg_ReadShort(); if(!df) { #ifdef _DEBUG if(justCreated) //Con_Error("justCreated!\n"); Con_Printf("CL_RMD: deleted justCreated id=%i\n", id); #endif // A Null Delta. We should delete this mobj. if(cmo->mo.dPlayer) { clPlayerStates[P_GetDDPlayerIdx(cmo->mo.dPlayer)].cmo = NULL; } Cl_DestroyMobj(cmo); return true; // Continue. } #ifdef _DEBUG if(justCreated && (!(df & MDF_POS_X) || !(df & MDF_POS_Y))) { Con_Error("Cl_ReadMobjDelta: Mobj is being created without X,Y.\n"); } #endif d = &cmo->mo; // Need to unlink? (Flags because DDMF_SOLID determines block-linking.) if(df & (MDF_POS_X | MDF_POS_Y | MDF_POS_Z | MDF_FLAGS) && linked && !d->dPlayer) { linked = false; Cl_UnsetMobjPosition(cmo); } // Coordinates with three bytes. if(df & MDF_POS_X) d->pos[VX] = FIX2FLT((Msg_ReadShort() << FRACBITS) | (Msg_ReadByte() << 8)); if(df & MDF_POS_Y) d->pos[VY] = FIX2FLT((Msg_ReadShort() << FRACBITS) | (Msg_ReadByte() << 8)); if(df & MDF_POS_Z) d->pos[VZ] = FIX2FLT((Msg_ReadShort() << FRACBITS) | (Msg_ReadByte() << 8)); #ifdef _DEBUG if(d->pos[VX] == 0 && d->pos[VY] == 0) { Con_Printf("CL_RMD: x,y zeroed t%i(%s)\n", d->type, defs.mobjs[d->type].id); } #endif // Momentum using 8.8 fixed point. if(df & MDF_MOM_X) d->mom[MX] = FIX2FLT(Msg_ReadShort() << 16) / 256; //>> 8; if(df & MDF_MOM_Y) d->mom[MY] = FIX2FLT(Msg_ReadShort() << 16) / 256; //>> 8; if(df & MDF_MOM_Z) d->mom[MZ] = FIX2FLT(Msg_ReadShort() << 16) / 256; //>> 8; // Angles with 16-bit accuracy. if(df & MDF_ANGLE) d->angle = Msg_ReadShort() << 16; // MDF_SELSPEC is never used without MDF_SELECTOR. if(df & MDF_SELECTOR) d->selector = Msg_ReadPackedShort(); if(df & MDF_SELSPEC) d->selector |= Msg_ReadByte() << 24; if(df & MDF_STATE) Cl_SetMobjState(d, (unsigned short) Msg_ReadPackedShort()); // Pack flags into a word (3 bytes?). // \fixme Do the packing! if(df & MDF_FLAGS) { // Only the flags in the pack mask are affected. d->ddFlags &= ~DDMF_PACK_MASK; d->ddFlags |= DDMF_REMOTE | (Msg_ReadLong() & DDMF_PACK_MASK); } // Radius, height and floorclip are all bytes. if(df & MDF_RADIUS) d->radius = (float) Msg_ReadByte(); if(df & MDF_HEIGHT) d->height = (float) Msg_ReadByte(); if(df & MDF_FLOORCLIP) { if(df & MDF_LONG_FLOORCLIP) d->floorClip = FIX2FLT(Msg_ReadPackedShort() << 14); else d->floorClip = FIX2FLT(Msg_ReadByte() << 14); } // Link again. if(!linked && !d->dPlayer) Cl_SetMobjPosition(cmo); if(df & (MDF_POS_X | MDF_POS_Y | MDF_POS_Z)) { // This'll update floorz and ceilingz. Cl_CheckMobj(cmo, justCreated); } // Update players. if(d->dPlayer) { // Players have real mobjs. The client mobj is hidden (unlinked). Cl_UpdateRealPlayerMobj(d->dPlayer->mo, d, df); } // Continue reading. return true; } /** * Initialize clientside data. */ void Cl_InitClientMobjs(void) { //previousTime = gameTime; // List of client mobjs. memset(cmHash, 0, sizeof(cmHash)); Cl_InitPlayers(); } /** * Called when the client is shut down. Unlinks everything from the * sectors and the blockmap and clears the clmobj list. */ void Cl_DestroyClientMobjs(void) { int i; clmobj_t* cmo; for(i = 0; i < HASH_SIZE; ++i) { for(cmo = cmHash[i].first; cmo; cmo = cmo->next) { // Players' clmobjs are not linked anywhere. if(!cmo->mo.dPlayer) Cl_UnsetMobjPosition(cmo); } } Cl_Reset(); } /** * Reset the client status. Called when the map changes. */ void Cl_Reset(void) { Cl_ResetFrame(); // The PU_MAP memory was freed, so just clear the hash. memset(cmHash, 0, sizeof(cmHash)); // Clear player data, too, since we just lost all clmobjs. Cl_InitPlayers(); } /** * The client mobj is moved linearly, with collision checking. */ void Cl_MobjMove(clmobj_t* cmo) { mobj_t* mo = &cmo->mo; boolean collided = false; float gravity = FIX2FLT(mapGravity); // First do XY movement. if(mo->mom[MX] != 0 || mo->mom[MY] != 0) { // Missiles don't hit mobjs only after a short delay. This'll // allow the missile to move free of the shooter. (Quite a hack!) if(mo->ddFlags & DDMF_MISSILE && Sys_GetRealTime() - cmo->time < MISSILE_FREE_MOVE_TIME) { // The mobj should be allowed to move freely though mobjs. // Use the quick and dirty global variable. dontHitMobjs = true; } // Move while doing collision checking. if(!P_StepMove(mo, mo->mom[MX], mo->mom[MY], 0)) { // There was a collision! collided = true; } // Allow mobj hit checks once again. dontHitMobjs = false; } if(mo->mom[MZ] != 0) { mo->pos[VZ] += mo->mom[MZ]; if(mo->pos[VZ] < mo->floorZ) { mo->pos[VZ] = mo->floorZ; mo->mom[MZ] = 0; collided = true; } if(mo->pos[VZ] + mo->height > mo->ceilingZ) { mo->pos[VZ] = mo->ceilingZ - mo->height; mo->mom[MZ] = 0; collided = true; } } if(mo->pos[VZ] > mo->floorZ) { // Gravity will affect the prediction. //// \fixme What about sector-specific gravity? if(mo->ddFlags & DDMF_LOWGRAVITY) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= gravity / 8; } else if(!(mo->ddFlags & DDMF_NOGRAVITY)) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; } } if(collided) { // Missiles are immediately removed. // (An explosion should follow shortly.) if(mo->ddFlags & DDMF_MISSILE) { // We don't know how to proceed from this, but merely // stopping the mobj is not enough. Let's hide it until // next delta arrives. cmo->flags |= CLMF_UNPREDICTABLE; Cl_UnsetMobjPosition(cmo); } // [Kaboom!] } // Stick to a plane? if(cmo->flags & CLMF_STICK_FLOOR) { mo->pos[VZ] = mo->floorZ; } if(cmo->flags & CLMF_STICK_CEILING) { mo->pos[VZ] = mo->ceilingZ - mo->height; } } /** * Decrement tics counter and changes the state of the mobj if necessary. */ void Cl_MobjAnimate(mobj_t *mo) { if(!mo->state || mo->tics < 0) return; // In stasis. mo->tics--; if(mo->tics <= 0) { // Go to next state, if possible. if(mo->state->nextState >= 0) { Cl_SetMobjState(mo, mo->state->nextState); // Players have both client mobjs and regular mobjs. This // routine modifies the *client* mobj, so for players we need // to update the real, visible mobj as well. if(mo->dPlayer) Cl_UpdateRealPlayerMobj(mo->dPlayer->mo, mo, 0); } else { // Freeze it; the server will probably to remove it soon. mo->tics = -1; } } } /** * All client mobjs are moved and animated using the data we have. */ void Cl_PredictMovement(void) { clmobj_t *cmo, *next = NULL; int i; int moCount = 0; uint nowTime = Sys_GetRealTime(); predicted_tics++; // Move all client mobjs. for(i = 0; i < HASH_SIZE; ++i) { for(cmo = cmHash[i].first; cmo; cmo = next) { next = cmo->next; moCount++; if(cmo->mo.dPlayer != &ddPlayers[consolePlayer].shared && (cmo->flags & (CLMF_UNPREDICTABLE | CLMF_HIDDEN)) /*|| (cmo->mo.ddFlags & DDMF_MISSILE)*/) { // Has this mobj timed out? if(nowTime - cmo->time > CLMOBJ_TIMEOUT) { // Too long. The server will probably never send anything // for this mobj, so get rid of it. (Both unpredictable // and hidden mobjs are not visible or bl/seclinked.) Cl_DestroyMobj(cmo); } // We can't predict what Hidden and Unpredictable mobjs do. // Must wait for the next delta to arrive. This mobj won't be // visible until then. continue; } // The local player gets a bit more complex prediction. if(cmo->mo.dPlayer) { Cl_MovePlayer(P_GetDDPlayerIdx(cmo->mo.dPlayer)); } else { // Linear movement prediction with collisions, then. Cl_MobjMove(cmo); } // Tic away. Cl_MobjAnimate(&cmo->mo); // Remove mobjs who have reached the NULL state, from whose // bourn no traveller returns. if(cmo->mo.state == states) { #ifdef _DEBUG if(!cmo->mo.thinker.id) Con_Error("No clmobj id!!!!\n"); #endif Cl_DestroyMobj(cmo); continue; } // Update the visual angle of the mobj (no SRVO action). cmo->mo.visAngle = cmo->mo.angle >> 16; } } #ifdef _DEBUG if(verbose >= 2) { static int timer = 0; if(++timer > 5 * 35) { timer = 0; Con_Printf("moCount=%i\n", moCount); } } #endif } /** * Create a new client mobj. */ clmobj_t *Cl_CreateMobj(thid_t id) { clmobj_t *cmo = Z_Calloc(sizeof(*cmo), PU_MAP, 0); cmo->mo.ddFlags |= DDMF_REMOTE; cmo->time = Sys_GetRealTime(); Cl_LinkMobj(cmo, id); P_SetMobjID(id, true); // Mark this ID as used. return cmo; } /** * Destroys the client mobj. */ void Cl_DestroyMobj(clmobj_t *cmo) { // Stop any sounds originating from this mobj. S_StopSound(0, &cmo->mo); // The ID is free once again. P_SetMobjID(cmo->mo.thinker.id, false); Cl_UnsetMobjPosition(cmo); Cl_UnlinkMobj(cmo); Z_Free(cmo); } /** * Call for Hidden client mobjs to make then visible. * If a sound is waiting, it's now played. * * @return @c true, if the mobj was revealed. */ boolean Cl_RevealMobj(clmobj_t *cmo) { // Check that we know enough about the clmobj. if(cmo->mo.dPlayer != &ddPlayers[consolePlayer].shared && (!(cmo->flags & CLMF_KNOWN_X) || !(cmo->flags & CLMF_KNOWN_Y) || !(cmo->flags & CLMF_KNOWN_Z) || !(cmo->flags & CLMF_KNOWN_STATE))) { // Don't reveal just yet. We lack a vital piece of information. return false; } /* #ifdef _DEBUG Con_Printf("Cl_RMD2: Mo %i Hidden status lifted.\n", cmo->mo.thinker.id); #endif */ cmo->flags &= ~CLMF_HIDDEN; // Start a sound that has been queued for playing at the time // of unhiding. Sounds are queued if a sound delta arrives for an // object ID we don't know (yet). if(cmo->flags & CLMF_SOUND) { cmo->flags &= ~CLMF_SOUND; S_StartSoundAtVolume(cmo->sound, &cmo->mo, cmo->volume); } #ifdef _DEBUG VERBOSE2( Con_Printf("Cl_RevealMobj: Revealing id %i, state %p (%i)\n", cmo->mo.thinker.id, cmo->mo.state, cmo->mo.state - states) ); #endif return true; } /** * Reads a single mobj PSV_FRAME2 delta from the message buffer and * applies it to the client mobj in question. * * For client mobjs that belong to players, updates the real player mobj. */ void Cl_ReadMobjDelta2(boolean skip) { boolean needsLinking = false, justCreated = false; clmobj_t *cmo = NULL; mobj_t *d; static mobj_t dummy; int df = 0; byte moreFlags = 0, fastMom = false; short mom; thid_t id = Msg_ReadShort(); // Read the ID. // Flags. df = Msg_ReadShort(); // More flags? if(df & MDF_MORE_FLAGS) { moreFlags = Msg_ReadByte(); // Fast momentum uses 10.6 fixed point instead of the normal 8.8. if(moreFlags & MDFE_FAST_MOM) fastMom = true; } if(!skip) { // Get a mobj for this. cmo = Cl_FindMobj(id); if(!cmo) { // This is a new ID, allocate a new mobj. cmo = Cl_CreateMobj(id); cmo->mo.ddFlags |= DDMF_NOGRAVITY; // safer this way justCreated = true; needsLinking = true; // Always create new mobjs as hidden. They will be revealed when // we know enough about them. cmo->flags |= CLMF_HIDDEN; } if(!(cmo->flags & CLMF_NULLED)) { // Now that we've received a delta, the mobj's Predictable again. cmo->flags &= ~CLMF_UNPREDICTABLE; // This clmobj is evidently alive. cmo->time = Sys_GetRealTime(); } d = &cmo->mo; /*if(d->dPlayer && d->dPlayer == &ddPlayers[consolePlayer]) { // Mark the local player known. cmo->flags |= CLMF_KNOWN; }*/ // Need to unlink? (Flags because DDMF_SOLID determines block-linking.) if(df & (MDF_POS_X | MDF_POS_Y | MDF_POS_Z | MDF_FLAGS) && !justCreated && !d->dPlayer) { needsLinking = true; Cl_UnsetMobjPosition(cmo); } } else { // We're skipping. d = &dummy; } // Coordinates with three bytes. if(df & MDF_POS_X) { d->pos[VX] = FIX2FLT((Msg_ReadShort() << FRACBITS) | (Msg_ReadByte() << 8)); if(cmo) cmo->flags |= CLMF_KNOWN_X; } if(df & MDF_POS_Y) { d->pos[VY] = FIX2FLT((Msg_ReadShort() << FRACBITS) | (Msg_ReadByte() << 8)); if(cmo) cmo->flags |= CLMF_KNOWN_Y; } if(df & MDF_POS_Z) { d->pos[VZ] = FIX2FLT((Msg_ReadShort() << FRACBITS) | (Msg_ReadByte() << 8)); if(cmo) { cmo->flags |= CLMF_KNOWN_Z; // The mobj won't stick if an explicit coordinate is supplied. cmo->flags &= ~(CLMF_STICK_FLOOR | CLMF_STICK_CEILING); } } // When these flags are set, the normal Z coord is not included. if(moreFlags & MDFE_Z_FLOOR) { d->pos[VZ] = DDMINFLOAT; if(cmo) cmo->flags |= CLMF_KNOWN_Z; } if(moreFlags & MDFE_Z_CEILING) { d->pos[VZ] = DDMAXFLOAT; if(cmo) cmo->flags |= CLMF_KNOWN_Z; } // Momentum using 8.8 fixed point. if(df & MDF_MOM_X) { mom = Msg_ReadShort(); d->mom[MX] = FIX2FLT(fastMom? UNFIXED10_6(mom) : UNFIXED8_8(mom)); } if(df & MDF_MOM_Y) { mom = Msg_ReadShort(); d->mom[MY] = FIX2FLT(fastMom ? UNFIXED10_6(mom) : UNFIXED8_8(mom)); } if(df & MDF_MOM_Z) { mom = Msg_ReadShort(); d->mom[MZ] = FIX2FLT(fastMom ? UNFIXED10_6(mom) : UNFIXED8_8(mom)); } // Angles with 16-bit accuracy. if(df & MDF_ANGLE) d->angle = Msg_ReadShort() << 16; // MDF_SELSPEC is never used without MDF_SELECTOR. if(df & MDF_SELECTOR) d->selector = Msg_ReadPackedShort(); if(df & MDF_SELSPEC) d->selector |= Msg_ReadByte() << 24; if(df & MDF_STATE) { ushort stateIdx = Msg_ReadPackedShort(); if(!skip) { Cl_SetMobjState(d, stateIdx); cmo->flags |= CLMF_KNOWN_STATE; } } // Pack flags into a word (3 bytes?). // \fixme Do the packing! if(df & MDF_FLAGS) { // Only the flags in the pack mask are affected. d->ddFlags &= ~DDMF_PACK_MASK; d->ddFlags |= DDMF_REMOTE | (Msg_ReadLong() & DDMF_PACK_MASK); } // Radius, height and floorclip are all bytes. if(df & MDF_RADIUS) d->radius = (float) Msg_ReadByte(); if(df & MDF_HEIGHT) d->height = (float) Msg_ReadByte(); if(df & MDF_FLOORCLIP) { if(df & MDF_LONG_FLOORCLIP) d->floorClip = FIX2FLT(Msg_ReadPackedShort() << 14); else d->floorClip = FIX2FLT(Msg_ReadByte() << 14); } if(moreFlags & MDFE_TRANSLUCENCY) d->translucency = Msg_ReadByte(); if(moreFlags & MDFE_FADETARGET) d->visTarget = ((short)Msg_ReadByte()) -1; // The delta has now been read. We can now skip if necessary. if(skip) return; // Is it time to remove the Hidden status? if(cmo->flags & CLMF_HIDDEN) { // Now it can be displayed (potentially). if(Cl_RevealMobj(cmo)) { // Now it can be linked to the world. needsLinking = true; } } if(df & (MDF_POS_X | MDF_POS_Y | MDF_POS_Z) || moreFlags & (MDFE_Z_FLOOR | MDFE_Z_CEILING)) { // This'll update floorz and ceilingz. Cl_CheckMobj(cmo, justCreated); } // If the clmobj is Hidden (or Nulled), it will not be linked back to // the world until it's officially Created. (Otherwise, partially updated // mobjs may be visible for a while.) if(!(cmo->flags & (CLMF_HIDDEN | CLMF_NULLED))) { // Link again. if(needsLinking && !d->dPlayer) { Cl_SetMobjPosition(cmo); } // Update players. if(d->dPlayer) { // Players have real mobjs. The client mobj is hidden (unlinked). Cl_UpdateRealPlayerMobj(d->dPlayer->mo, d, df); } } } /** * Null mobjs deltas have their own type in a PSV_FRAME2 packet. * Here we remove the mobj in question. */ void Cl_ReadNullMobjDelta2(boolean skip) { clmobj_t *cmo; thid_t id; // The delta only contains an ID. id = Msg_ReadShort(); if(skip) return; #ifdef _DEBUG Con_Printf("Cl_ReadNullMobjDelta2: Null %i\n", id); #endif if((cmo = Cl_FindMobj(id)) == NULL) { // Wasted bandwidth... #ifdef _DEBUG Con_Printf("Cl_ReadNullMobjDelta2: Request to remove id %i that has " "not been received.\n", id); #endif return; } // Get rid of this mobj. if(!cmo->mo.dPlayer) { Cl_UnsetMobjPosition(cmo); } else { // The clmobjs of players aren't linked. clPlayerStates[P_GetDDPlayerIdx(cmo->mo.dPlayer)].cmo = NULL; } // This'll allow playing sounds from the mobj for a little while. // The mobj will soon time out and be permanently removed. cmo->time = Sys_GetRealTime(); cmo->flags |= CLMF_UNPREDICTABLE | CLMF_NULLED; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/con_data.c0000644000175000017500000007231311357170241022652 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_data.c: Console Subsystem * * Console databases for knownwords, cvars, ccmds and aliases. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include "de_base.h" #include "de_console.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(HelpWhat); D_CMD(ListAliases); D_CMD(ListCmds); D_CMD(ListVars); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static int C_DECL wordListSorter(const void* e1, const void* e2); static int C_DECL knownWordListSorter(const void* e1, const void* e2); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static cvar_t* cvars = NULL; static ddccmd_t* ccmds = NULL; static calias_t* caliases = NULL; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static uint numCVars = 0, maxCVars = 0; static uint numCCmds = 0, maxCCmds = 0; static uint numCAliases = 0; // The list of known words (for completion). static knownword_t* knownWords = NULL; static uint numKnownWords = 0; // CODE -------------------------------------------------------------------- void Con_DataRegister(void) { C_CMD("help", "s", HelpWhat); C_CMD("listaliases", NULL, ListAliases); C_CMD("listcmds", NULL, ListCmds); C_CMD("listvars", NULL, ListVars); } void Con_SetString(const char* name, char* text, byte overRide) { cvar_t* cvar = Con_GetVariable(name); boolean changed = false; if(!cvar) return; if(cvar->flags & CVF_READ_ONLY && !overRide) { Con_Printf("%s (cvar) is read-only. It can't be changed " "(not even with force)\n", name); return; } if(cvar->type == CVT_CHARPTR) { if(CV_CHARPTR(cvar) && !stricmp(text, CV_CHARPTR(cvar))) changed = true; // Free the old string, if one exists. if(cvar->flags & CVF_CAN_FREE && CV_CHARPTR(cvar)) M_Free(CV_CHARPTR(cvar)); // Allocate a new string. cvar->flags |= CVF_CAN_FREE; CV_CHARPTR(cvar) = M_Malloc(strlen(text) + 1); strcpy(CV_CHARPTR(cvar), text); // Make the change notification callback if(cvar->notifyChanged != NULL && changed) cvar->notifyChanged(cvar); } else Con_Error("Con_SetString: cvar is not of type char*.\n"); } /** * \note: Also works with bytes. */ void Con_SetInteger(const char* name, int value, byte overRide) { cvar_t* var = Con_GetVariable(name); boolean changed = false; if(!var) return; if(var->flags & CVF_READ_ONLY && !overRide) { Con_Printf("%s (cvar) is read-only. It can't be changed " "(not even with force)\n", name); return; } if(var->type == CVT_INT) { if(CV_INT(var) != value) changed = true; CV_INT(var) = value; } if(var->type == CVT_BYTE) { if(CV_BYTE(var) != (byte) value) changed = true; CV_BYTE(var) = (byte) value; } if(var->type == CVT_FLOAT) { if(CV_FLOAT(var) != (float) value) changed = true; CV_FLOAT(var) = (float) value; } // Make the change notification callback if(var->notifyChanged != NULL && changed) var->notifyChanged(var); } void Con_SetFloat(const char* name, float value, byte overRide) { cvar_t* var = Con_GetVariable(name); boolean changed = false; if(!var) return; if(var->flags & CVF_READ_ONLY && !overRide) { Con_Printf("%s (cvar) is read-only. It can't be changed " "(not even with force)\n", name); return; } if(var->type == CVT_INT) { if(CV_INT(var) != (int) value) changed = true; CV_INT(var) = (int) value; } if(var->type == CVT_BYTE) { if(CV_BYTE(var) != (byte) value) changed = true; CV_BYTE(var) = (byte) value; } if(var->type == CVT_FLOAT) { if(CV_FLOAT(var) != value) changed = true; CV_FLOAT(var) = value; } // Make the change notification callback if(var->notifyChanged != NULL && changed) var->notifyChanged(var); } int Con_GetInteger(const char* name) { cvar_t* var = Con_GetVariable(name); if(!var) return 0; if(var->type == CVT_BYTE) return CV_BYTE(var); if(var->type == CVT_FLOAT) return CV_FLOAT(var); if(var->type == CVT_CHARPTR) return strtol(CV_CHARPTR(var), 0, 0); return CV_INT(var); } float Con_GetFloat(const char* name) { cvar_t* var = Con_GetVariable(name); if(!var) return 0; if(var->type == CVT_INT) return CV_INT(var); if(var->type == CVT_BYTE) return CV_BYTE(var); if(var->type == CVT_CHARPTR) return strtod(CV_CHARPTR(var), 0); return CV_FLOAT(var); } byte Con_GetByte(const char* name) { cvar_t* var = Con_GetVariable(name); if(!var) return 0; if(var->type == CVT_INT) return CV_INT(var); if(var->type == CVT_FLOAT) return CV_FLOAT(var); if(var->type == CVT_CHARPTR) return strtol(CV_CHARPTR(var), 0, 0); return CV_BYTE(var); } char* Con_GetString(const char* name) { cvar_t* var = Con_GetVariable(name); if(!var || var->type != CVT_CHARPTR) return ""; return CV_CHARPTR(var); } void Con_AddVariableList(cvar_t* varlist) { if(!varlist) return; for(; varlist->name; varlist++) Con_AddVariable(varlist); } void Con_AddVariable(cvar_t* var) { char* nameCopy = NULL; if(!var) return; if(Con_GetVariable(var->name)) Con_Error("Con_AddVariable: A CVAR by the name \"%s\" " "is already registered", var->name); if(++numCVars > maxCVars) { // Allocate more memory. maxCVars *= 2; if(maxCVars < numCVars) maxCVars = numCVars; cvars = M_Realloc(cvars, sizeof(cvar_t) * maxCVars); } memcpy(cvars + numCVars - 1, var, sizeof(cvar_t)); // Make a static copy of the variable name in the zone. // This allows the source data to change (in case of dynamic registrations). nameCopy = Z_Malloc(strlen(var->name) + 1, PU_STATIC, NULL); strcpy(nameCopy, var->name); cvars[numCVars - 1].name = nameCopy; // Sort them. qsort(cvars, numCVars, sizeof(cvar_t), wordListSorter); } cvar_t* Con_GetVariable(const char* name) { int result; uint bottomIdx, topIdx, pivot; cvar_t* var; boolean isDone; if(numCVars == 0) return NULL; if(!name || !name[0]) return NULL; bottomIdx = 0; topIdx = numCVars-1; var = NULL; isDone = false; while(bottomIdx <= topIdx && !isDone) { pivot = bottomIdx + (topIdx - bottomIdx)/2; result = stricmp(cvars[pivot].name, name); if(result == 0) { // Found. var = &cvars[pivot]; isDone = true; } else { if(result > 0) { if(pivot == 0) { // Not present. isDone = true; } else topIdx = pivot - 1; } else bottomIdx = pivot + 1; } } return var; } cvar_t* Con_GetVariableIDX(uint idx) { if(idx < numCVars) return &cvars[idx]; return NULL; } uint Con_CVarCount(void) { return numCVars; } void Con_PrintCVar(cvar_t* var, char* prefix) { char equals = '='; if(!var) return; if(var->flags & CVF_PROTECTED || var->flags & CVF_READ_ONLY) equals = ':'; if(prefix) Con_Printf("%s", prefix); switch(var->type) { case CVT_NULL: Con_Printf("%s", var->name); break; case CVT_BYTE: Con_Printf("%s %c %d", var->name, equals, CV_BYTE(var)); break; case CVT_INT: Con_Printf("%s %c %d", var->name, equals, CV_INT(var)); break; case CVT_FLOAT: Con_Printf("%s %c %g", var->name, equals, CV_FLOAT(var)); break; case CVT_CHARPTR: Con_Printf("%s %c %s", var->name, equals, CV_CHARPTR(var)); break; default: Con_Printf("%s (bad type!)", var->name); break; } Con_Printf("\n"); } void Con_AddCommandList(ccmd_t* cmdlist) { if(!cmdlist) return; for(; cmdlist->name; cmdlist++) Con_AddCommand(cmdlist); } void Con_AddCommand(ccmd_t* cmd) { uint i; cvartype_t params[MAX_ARGS]; int minArgs, maxArgs; ddccmd_t* newCmd; if(!cmd) return; if(!cmd->name) Con_Error("Con_AddCommand: CCmd missing a name."); /*#if _DEBUG Con_Message("Con_AddCommand: \"%s\" \"%s\" (%i).\n", cmd->name, cmd->params, cmd->flags); #endif*/ // Decode the usage string if present. if(cmd->params != NULL) { char c; size_t l, len; cvartype_t type = CVT_NULL; boolean unlimitedArgs; len = strlen(cmd->params); minArgs = 0; unlimitedArgs = false; for(l = 0; l < len; ++l) { c = cmd->params[l]; switch(c) { // Supported parameter type symbols: case 'b': type = CVT_BYTE; break; case 'i': type = CVT_INT; break; case 'f': type = CVT_FLOAT; break; case 's': type = CVT_CHARPTR; break; // Special symbols: case '*': // Variable arg list. if(l != len-1) Con_Error("Con_AddCommand: CCmd '%s': '*' character " "not last in parameter string: \"%s\".", cmd->name, cmd->params); unlimitedArgs = true; type = CVT_NULL; // not a real parameter. break; // Erroneous symbol: default: Con_Error("Con_AddCommand: CCmd '%s': Invalid character " "'%c' in parameter string: \"%s\".", cmd->name, c, cmd->params); } if(type != CVT_NULL) { if(minArgs >= MAX_ARGS) Con_Error("Con_AddCommand: CCmd '%s': Too many parameters. " "Limit is %i.", cmd->name, MAX_ARGS); // Copy the parameter type into the buffer. params[minArgs++] = type; } } // Set the min/max parameter counts for this ccmd. if(unlimitedArgs) { maxArgs = -1; if(minArgs == 0) minArgs = -1; } else maxArgs = minArgs; /*#if _DEBUG { int i; Con_Message("Con_AddCommand: CCmd \"%s\": minArgs %i, maxArgs %i: \"", cmd->name, minArgs, maxArgs); for(i = 0; i < minArgs; ++i) { switch(params[i]) { case CVT_BYTE: c = 'b'; break; case CVT_INT: c = 'i'; break; case CVT_FLOAT: c = 'f'; break; case CVT_CHARPTR: c = 's'; break; } Con_Printf("%c", c); } Con_Printf("\".\n"); } #endif*/ } else // it's usage is NOT validated by Doomsday. { minArgs = maxArgs = -1; /*#if _DEBUG if(cmd->params == NULL) Con_Message("Con_AddCommand: CCmd \"%s\" will not have it's usage " "validated.\n", cmd->name); #endif*/ } // Now check that the ccmd to be registered is unique. // We allow multiple ccmds with the same name if we can determine by // their paramater lists that they are unique (overloading). for(i = 0; i < numCCmds; ++i) { ddccmd_t* other = &ccmds[i]; if(!stricmp(other->name, cmd->name)) { boolean unique = true; // The ccmd being registered is NOT a deng validated ccmd // and there is already an existing ccmd by this name? if(minArgs == -1 && maxArgs == -1) unique = false; // An existing ccmd with no validation? else if(other->minArgs == -1 && other->maxArgs == -1) unique = false; // An existing ccmd with a lower minimum and no maximum? else if(other->minArgs < minArgs && other->maxArgs == -1) unique = false; // An existing ccmd with a larger min and this ccmd has no max? else if(other->minArgs > minArgs && maxArgs == -1) unique = false; // An existing ccmd with the same minimum number of args? else if(other->minArgs == minArgs) { // \todo Implement support for paramater type checking. unique = false; } if(!unique) Con_Error("Con_AddCommand: A CCmd by the name '%s' " "is already registered. Their parameter lists " "would be ambiguant.", cmd->name); // Sanity check. if(other->func == cmd->func) Con_Error("Con_AddCommand: A CCmd by the name '%s' is " "already registered and the callback funcs are " "the same, is this really what you wanted?", cmd->name); } } // Have we ran out of available ddcmd_t's? if(++numCCmds > maxCCmds) { // Allocate some more. maxCCmds *= 2; if(maxCCmds < numCCmds) maxCCmds = numCCmds; ccmds = M_Realloc(ccmds, sizeof(ddccmd_t) * maxCCmds); } newCmd = &ccmds[numCCmds - 1]; // Copy the properties. newCmd->name = cmd->name; newCmd->func = cmd->func; newCmd->flags = cmd->flags; newCmd->minArgs = minArgs; newCmd->maxArgs = maxArgs; memcpy(newCmd->params, ¶ms, sizeof(newCmd->params)); // Sort them. qsort(ccmds, numCCmds, sizeof(ddccmd_t), wordListSorter); } ddccmd_t* Con_GetCommand(cmdargs_t* args) { uint i; ddccmd_t* ccmd = NULL; ddccmd_t* matchingNameCmd = NULL; if(!args) return NULL; // \todo Use a faster than O(n) linear search. Note, ccmd->name is not // a unique key (ccmds can share names if params differ). for(i = 0; i < numCCmds; ++i) { ccmd = &ccmds[i]; if(!stricmp(args->argv[0], ccmd->name)) { boolean invalidArgs = false; // Remember the first one with a matching name. if(!matchingNameCmd) matchingNameCmd = ccmd; // Are we validating the arguments? if(!(ccmd->minArgs == -1 && ccmd->maxArgs == -1)) { int j; // Do we have the right number of arguments? if(args->argc-1 < ccmd->minArgs) invalidArgs = true; else if(ccmd->maxArgs != -1 && args->argc-1 > ccmd->maxArgs) invalidArgs = true; else { // We can only validate the minimum number of arguments, // currently. We cannot yet validate non-required args. for(j = 0; j < ccmd->minArgs && !invalidArgs; ++j) { if(ccmd->params[j] == CVT_BYTE) invalidArgs = !M_IsStringValidByte(args->argv[j+1]); else if(ccmd->params[j] == CVT_INT) invalidArgs = !M_IsStringValidInt(args->argv[j+1]); else if(ccmd->params[j] == CVT_FLOAT) invalidArgs = !M_IsStringValidFloat(args->argv[j+1]); // Strings are considered always valid. } } } if(!invalidArgs) return ccmd; // This is the one! } } if(matchingNameCmd) { // We did find a command, perhaps the user needs some help. Con_PrintCCmdUsage(matchingNameCmd, false); } // No command found, or none with matching arguments. return NULL; } /** * @return @c true, if the given string is a * valid command or alias name. */ boolean Con_IsValidCommand(const char* name) { uint i = 0; boolean found = false; if(!name || !name[0]) return false; // Try the console commands first. while(!found && i < numCCmds) { if(!stricmp(ccmds[i].name, name)) found = true; else i++; } if(found) { return true; } else // Try the aliases (aliai?) then. { return (Con_GetAlias(name) != NULL); } } /** * Outputs the usage information for the given ccmd to the console if the * ccmd's usage is validated by Doomsday. * * @param ccmd Ptr to the ccmd to print the usage info for. * @param showExtra If @c true, print any additional info we * have about the ccmd. */ void Con_PrintCCmdUsage(ddccmd_t* ccmd, boolean showExtra) { int i; char* str; void* ccmd_help; if(!ccmd || (ccmd->minArgs == -1 && ccmd->maxArgs == -1)) return; ccmd_help = DH_Find(ccmd->name); // Print the expected form for this ccmd. Con_Printf("Usage: %s", ccmd->name); for(i = 0; i < ccmd->minArgs; ++i) { switch(ccmd->params[i]) { case CVT_BYTE: Con_Printf(" (byte)"); break; case CVT_INT: Con_Printf(" (int)"); break; case CVT_FLOAT: Con_Printf(" (float)"); break; case CVT_CHARPTR: Con_Printf(" (string)"); break; default: break; } } if(ccmd->maxArgs == -1) Con_Printf(" ..."); Con_Printf("\n"); if(showExtra) { // Check for extra info about this ccmd's usage. if((str = DH_GetString(ccmd_help, HST_INFO))) Con_Printf("%s\n", str); } } /** * Returns NULL if the specified alias can't be found. */ calias_t* Con_GetAlias(const char* name) { int result; uint bottomIdx, topIdx, pivot; calias_t* cal; boolean isDone; if(numCAliases == 0) return NULL; if(!name || !name[0]) return NULL; bottomIdx = 0; topIdx = numCAliases-1; cal = NULL; isDone = false; while(bottomIdx <= topIdx && !isDone) { pivot = bottomIdx + (topIdx - bottomIdx)/2; result = stricmp(caliases[pivot].name, name); if(result == 0) { // Found. cal = &caliases[pivot]; isDone = true; } else { if(result > 0) { if(pivot == 0) { // Not present. isDone = true; } else topIdx = pivot - 1; } else bottomIdx = pivot + 1; } } return cal; } calias_t* Con_AddAlias(const char* aName, const char* command) { calias_t* cal; if(!aName || !aName[0] || !command || !command[0]) return NULL; caliases = M_Realloc(caliases, sizeof(calias_t) * (++numCAliases)); cal = caliases + numCAliases - 1; // Allocate memory for them. cal->name = M_Malloc(strlen(aName) + 1); cal->command = M_Malloc(strlen(command) + 1); strcpy(cal->name, aName); strcpy(cal->command, command); // Sort them. qsort(caliases, numCAliases, sizeof(calias_t), wordListSorter); return cal; } void Con_DeleteAlias(calias_t* cal) { uint idx; if(!cal) return; idx = cal - caliases; M_Free(cal->name); M_Free(cal->command); if(idx < numCAliases - 1) memmove(caliases + idx, caliases + idx + 1, sizeof(calias_t) * (numCAliases - idx - 1)); caliases = M_Realloc(caliases, sizeof(calias_t) * --numCAliases); } /** * Called by the config file writer. */ void Con_WriteAliasesToFile(FILE* file) { uint i; calias_t* cal; if(!file) return; for(i = 0, cal = caliases; i < numCAliases; ++i, cal++) { fprintf(file, "alias \""); M_WriteTextEsc(file, cal->name); fprintf(file, "\" \""); M_WriteTextEsc(file, cal->command); fprintf(file, "\"\n"); } } static int C_DECL wordListSorter(const void* e1, const void* e2) { return stricmp(*(char**)e1, *(char**)e2); } static int C_DECL knownWordListSorter(const void* e1, const void* e2) { return stricmp(((knownword_t*) e1)->word, ((knownword_t*) e2)->word); } /** * \note: Variables with CVF_HIDE are not considered known words. */ void Con_UpdateKnownWords(void) { uint i, c, knownVars; size_t len; // Count the number of visible console variables. for(i = knownVars = 0; i < numCVars; ++i) if(!(cvars[i].flags & CVF_HIDE)) knownVars++; // Fill the known words table. numKnownWords = numCCmds + knownVars + numCAliases /*+ numBindClasses*/; len = sizeof(knownword_t) * numKnownWords; knownWords = M_Realloc(knownWords, len); memset(knownWords, 0, len); // Commands, variables, aliases, and bind class names are known words. for(i = 0, c = 0; i < numCCmds; ++i, ++c) { strncpy(knownWords[c].word, ccmds[i].name, 63); knownWords[c].type = WT_CCMD; } for(i = 0; i < knownVars; ++i) { if(!(cvars[i].flags & CVF_HIDE)) { strncpy(knownWords[c].word, cvars[i].name, 63); knownWords[c].type = WT_CVAR; c++; } } for(i = 0; i < numCAliases; ++i, ++c) { strncpy(knownWords[c].word, caliases[i].name, 63); knownWords[c].type = WT_ALIAS; } // TODO: Add bind context names to the known words. /* for(i = 0; i < numBindContexts; ++i, ++c) { strncpy(knownWords[c].word, bindContexts[i].name, 63); knownWords[c].type = WT_BINDCONTEXT; } */ // Sort it so we get nice alphabetical word completions. qsort(knownWords, numKnownWords, sizeof(knownword_t), knownWordListSorter); } /** * Collect an array of knownWords which match the given word (at least * partially). * * \note: The array must be freed with M_Free. * * @param word The word to be matched. * @param count The count of the number of matching words will be * written back to this location if NOT @c NULL. * * @return A NULL-terminated array of pointers to all the known * words which match (at least partially) @param word */ knownword_t** Con_CollectKnownWordsMatchingWord(const char* word, uint* count) { uint i, num = 0, num2 = 0; size_t wordLength; knownword_t** matches; if(!word || !word[0]) return NULL; wordLength = strlen(word); // Count the number of matching words. for(i = 0; i < numKnownWords; ++i) { if(!strnicmp(knownWords[i].word, word, wordLength)) num++; } // Tell the caller how many we found. if(count) *count = num; if(num == 0) // No matches. return NULL; // Allocate the array, plus one for the terminator. matches = M_Malloc(sizeof(knownword_t *) * (num + 1)); // Collect the pointers. i = 0; num2 = 0; do { if(!strnicmp(knownWords[i].word, word, wordLength)) matches[num2++] = &knownWords[i]; i++; } while(num2 < num); // Terminate. matches[num] = NULL; return matches; } void Con_DestroyDatabases(void) { uint i, k; char* ptr; // Free the data of the data cvars. for(i = 0; i < numCVars; ++i) if(cvars[i].flags & CVF_CAN_FREE && cvars[i].type == CVT_CHARPTR) { ptr = *(char **) cvars[i].ptr; // Multiple vars could be using the same pointer, // make sure it gets freed only once. for(k = i; k < numCVars; ++k) if(cvars[k].type == CVT_CHARPTR && ptr == *(char **) cvars[k].ptr) { cvars[k].flags &= ~CVF_CAN_FREE; } M_Free(ptr); } if(cvars) M_Free(cvars); cvars = NULL; numCVars = 0; if(ccmds) M_Free(ccmds); ccmds = NULL; numCCmds = 0; if(knownWords) M_Free(knownWords); knownWords = NULL; numKnownWords = 0; if(caliases) { // Free the alias data. for(i = 0; i < numCAliases; ++i) { M_Free(caliases[i].command); M_Free(caliases[i].name); } M_Free(caliases); } caliases = NULL; numCAliases = 0; } D_CMD(HelpWhat) { char* str; void* help; ddccmd_t* ccmd; cvar_t* cvar; uint i, found = 0; if(!stricmp(argv[1], "(what)")) { Con_Printf("You've got to be kidding!\n"); return true; } // Try the console commands first. for(i = 0; i < numCCmds; ++i) { ccmd = &ccmds[i]; if(!stricmp(argv[1], ccmd->name)) { if(found == 0) // only print a description once. { help = DH_Find(ccmd->name); if((str = DH_GetString(help, HST_DESCRIPTION))) Con_Printf("%s\n", str); } Con_PrintCCmdUsage(ccmd, (found == 0)); found++; // found one, but there may be more... } } if(found == 0) // Perhaps its a cvar then? { cvar = Con_GetVariable(argv[1]); if(cvar != NULL) { help = DH_Find(cvar->name); if((str = DH_GetString(help, HST_DESCRIPTION))) { Con_Printf("%s\n", str); found = true; } } } if(found == 0) // Still not found? Con_Printf("There's no help about '%s'.\n", argv[1]); return true; } D_CMD(ListCmds) { uint i; char* str; void* ccmd_help; size_t length = 0; if(argc > 1) length = strlen(argv[1]); Con_Printf("Console commands:\n"); for(i = 0; i < numCCmds; ++i) { // Is there a filter? if(!(argc > 1 && strnicmp(ccmds[i].name, argv[1], length))) { ccmd_help = DH_Find(ccmds[i].name); if((str = DH_GetString(ccmd_help, HST_DESCRIPTION))) Con_FPrintf( CBLF_LIGHT | CBLF_YELLOW, " %s (%s)\n", ccmds[i].name, str); else Con_FPrintf( CBLF_LIGHT | CBLF_YELLOW, " %s\n", ccmds[i].name); } } return true; } D_CMD(ListVars) { uint i; size_t length = 0; if(argc > 1) length = strlen(argv[1]); Con_Printf("Console variables:\n"); for(i = 0; i < numCVars; ++i) { if(!(cvars[i].flags & CVF_HIDE)) { // Is there a filter? if(!(argc > 1 && strnicmp(cvars[i].name, argv[1], length))) Con_PrintCVar(cvars + i, " "); } } return true; } D_CMD(ListAliases) { uint i; size_t length = 0; if(argc > 1) length = strlen(argv[1]); Con_Printf("Aliases:\n"); for(i = 0; i < numCAliases; ++i) { // Is there a filter? if(!(argc > 1 && strnicmp(caliases[i].name, argv[1], length))) Con_FPrintf(CBLF_LIGHT|CBLF_YELLOW, " %s == %s\n", caliases[i].name, caliases[i].command); } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_sdl_window.c0000644000175000017500000006657511357170242024167 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2008 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_sdl_window.c: Cross-platform, SDL-based window management. * * This code wraps SDL window management routines in order to provide * common behavior. The availabilty of features and behavioral traits can * be queried for. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_refresh.h" #include "de_misc.h" #include "de_ui.h" // MACROS ------------------------------------------------------------------ #define LINELEN (80) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static boolean setDDWindow(ddwindow_t *win, int newWidth, int newHeight, int newBPP, uint wFlags, uint uFlags); static void setConWindowCmdLine(uint idx, const char *text, unsigned int cursorPos, int flags); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Currently active window where all drawing operations are directed at. const ddwindow_t* theWindow; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean winManagerInited = false; static ddwindow_t mainWindow; static boolean mainWindowInited = false; static int screenWidth, screenHeight, screenBPP; // CODE -------------------------------------------------------------------- static __inline ddwindow_t *getWindow(uint idx) { if(!winManagerInited) return NULL; // Window manager is not initialized. if(idx != 0) return NULL; return &mainWindow; } #if defined(UNIX) static void setAttrib(int flags) { if(flags & (CBLF_YELLOW | CBLF_LIGHT)) wattrset(mainWindow.console.winText, A_BOLD); else wattrset(mainWindow.console.winText, A_NORMAL); } /** * Writes the text in winText at (cx,cy). */ static void writeText(const char *line, int len) { wmove(mainWindow.console.winText, mainWindow.console.cy, mainWindow.console.cx); waddnstr(mainWindow.console.winText, line, len); wclrtoeol(mainWindow.console.winText); } static int getScreenSize(int axis) { int x, y; getmaxyx(mainWindow.console.winText, y, x); return axis == VX ? x : y; } void Sys_ConPrint(uint idx, const char *text, int clflags) { ddwindow_t *win; char line[LINELEN]; int count = strlen(text), lineStart, bPos; const char *ptr = text; char ch; int maxPos[2]; if(!winManagerInited) return; if(idx != 1) { // We only support one terminal window (this isn't for us). return; } win = &mainWindow; // Determine the size of the text window. getmaxyx(win->console.winText, maxPos[VY], maxPos[VX]); if(win->console.needNewLine) { // Need to make some room. win->console.cx = 0; win->console.cy++; if(win->console.cy >= maxPos[VY]) { win->console.cy--; scroll(win->console.winText); } win->console.needNewLine = false; } bPos = lineStart = win->console.cx; setAttrib(clflags); for(; count > 0; count--, ptr++) { ch = *ptr; // Ignore carriage returns. if(ch == '\r') continue; if(ch != '\n' && bPos < maxPos[VX]) { line[bPos] = ch; bPos++; } // Time for newline? if(ch == '\n' || bPos >= maxPos[VX]) { writeText(line + lineStart, bPos - lineStart); win->console.cx += bPos - lineStart; bPos = 0; lineStart = 0; if(count > 1) // Not the last character? { win->console.needNewLine = false; win->console.cx = 0; win->console.cy++; if(win->console.cy == maxPos[VY]) { scroll(win->console.winText); win->console.cy--; } } else win->console.needNewLine = true; } } // Something in the buffer? if(bPos - lineStart) { writeText(line + lineStart, bPos - lineStart); win->console.cx += bPos - lineStart; } wrefresh(win->console.winText); // Move the cursor back onto the command line. setConWindowCmdLine(1, NULL, 0, 0); } /** * Set the command line display of the specified console window. * * @param idx Console window identifier. * @param text Text string to copy. * @param cursorPos Position to set the cursor on the command line. * @param flags CLF_* flags control the appearance of the * command line. */ void Sys_SetConWindowCmdLine(uint idx, const char *text, uint cursorPos, int flags) { ddwindow_t *win; if(!winManagerInited) return; win = getWindow(idx - 1); if(!win || win->type != WT_CONSOLE) return; setConWindowCmdLine(idx, text, cursorPos, flags); } static void setConWindowCmdLine(uint idx, const char *text, unsigned int cursorPos, int flags) { ddwindow_t *win; unsigned int i; char line[LINELEN], *ch; int maxX; int length; if(idx != 1) { // We only support one console window; (this isn't for us). return; } win = &mainWindow; maxX = getScreenSize(VX); if(!text) { int y, x; // Just move the cursor into the command line window. getyx(win->console.winCommand, y, x); wmove(win->console.winCommand, y, x); } else { memset(line, 0, sizeof(line)); line[0] = '>'; for(i = 0, ch = line + 1; i < LINELEN - 1; ++i, ch++) { if(i < strlen(text)) *ch = text[i]; else *ch = 0; } wmove(win->console.winCommand, 0, 0); // Can't print longer than the window. length = strlen(text); waddnstr(win->console.winCommand, line, MIN_OF(maxX, length + 1)); wclrtoeol(win->console.winCommand); } wrefresh(win->console.winCommand); } #endif boolean Sys_ChangeVideoMode(int width, int height, int bpp) { int flags = SDL_OPENGL; const SDL_VideoInfo *info = NULL; int windowflags; windowflags = (theWindow->flags); if(windowflags & DDWF_FULLSCREEN) flags |= SDL_FULLSCREEN; if(!SDL_SetVideoMode(width, height, bpp, flags)) { // This could happen for a variety of reasons, including // DISPLAY not being set, the specified resolution not being // available, etc. Con_Message("SDL Error: %s\n", SDL_GetError()); return false; } Con_Message("createContext: OpenGL.\n"); info = SDL_GetVideoInfo(); screenWidth = info->current_w; screenHeight = info->current_h; screenBPP = info->vfmt->BitsPerPixel; return true; } /** * Initialize the window manager. * Tasks include; checking the system environment for feature enumeration. * * @return @c true, if initialization was successful. */ boolean Sys_InitWindowManager(void) { if(winManagerInited) return true; // Already been here. Con_Message("Sys_InitWindowManager: Using SDL window management.\n"); // Initialize the SDL video subsystem, unless we're going to run in // dedicated mode. if(!ArgExists("-dedicated")) { /** * @attention Solaris has no Joystick support according to * https://sourceforge.net/tracker/?func=detail&atid=542099&aid=1732554&group_id=74815 */ #ifdef SOLARIS if(SDL_InitSubSystem(SDL_INIT_VIDEO)) #else if(SDL_InitSubSystem(SDL_INIT_VIDEO | (!ArgExists("-nojoy")?SDL_INIT_JOYSTICK : 0))) #endif { Con_Message("SDL Init Failed: %s\n", SDL_GetError()); return false; } } memset(&mainWindow, 0, sizeof(mainWindow)); winManagerInited = true; theWindow = &mainWindow; return true; } /** * Shutdown the window manager. * * @return @c true, if shutdown was successful. */ boolean Sys_ShutdownWindowManager(void) { if(!winManagerInited) return false; // Window manager is not initialized. if(mainWindow.type == WT_CONSOLE) Sys_DestroyWindow(1); // Now off-line, no more window management will be possible. winManagerInited = false; //if(isDedicated) // Sys_ConShutdown(); return true; } static boolean initOpenGL(void) { // Attempt to set the video mode. if(!Sys_ChangeVideoMode(theWindow->width, theWindow->height, theWindow->normal.bpp)) return false; // Setup the GL state like we want it. Sys_InitGLState(); return true; } /** * Attempt to acquire a device context for OGL rendering and then init. * * @param width Width of the OGL window. * @param height Height of the OGL window. * @param bpp 0= the current display color depth is used. * @param windowed @c true = windowed mode ELSE fullscreen. * @param data Ptr to system-specific data, e.g a window handle * or similar. * * @return @c true if successful. */ static boolean createContext(int width, int height, int bpp, boolean windowed, void *data) { Con_Message("createContext: OpenGL.\n"); // Set GL attributes. We want at least 5 bits per color and a 16 // bit depth buffer. Plus double buffering, of course. SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); if(!initOpenGL()) { Con_Error("createContext: OpenGL init failed.\n"); } return true; } /** * Complete the given wminfo_t, detailing what features are supported by * this window manager implementation. * * @param info Ptr to the wminfo_t structure to complete. * * @return @c true, if successful. */ boolean Sys_GetWindowManagerInfo(wminfo_t *info) { if(!winManagerInited) return false; // Window manager is not initialized. if(!info) return false; // Wha? // Complete the structure detailing what features are available. info->canMoveWindow = false; info->maxWindows = 1; info->maxConsoles = 1; return true; } static ddwindow_t *createDDWindow(application_t *app, int w, int h, int bpp, int flags, ddwindowtype_t type, const char *title) { // SDL only supports one window. if(mainWindowInited) return NULL; if(type == WT_CONSOLE) { #if defined(UNIX) int maxPos[2]; // Initialize curses. if(!initscr()) Sys_CriticalMessage("createDDWindow: Failed creating terminal."); cbreak(); noecho(); nonl(); // The current size of the screen. getmaxyx(stdscr, maxPos[VY], maxPos[VX]); // Create the three windows we will be using. mainWindow.console.winTitle = newwin(1, maxPos[VX], 0, 0); mainWindow.console.winText = newwin(maxPos[VY] - 2, maxPos[VX], 1, 0); mainWindow.console.winCommand = newwin(1, maxPos[VX], maxPos[VY] - 1, 0); // Set attributes. wattrset(mainWindow.console.winTitle, A_REVERSE); wattrset(mainWindow.console.winText, A_NORMAL); wattrset(mainWindow.console.winCommand, A_BOLD); scrollok(mainWindow.console.winText, TRUE); wclear(mainWindow.console.winText); wrefresh(mainWindow.console.winText); keypad(mainWindow.console.winCommand, TRUE); nodelay(mainWindow.console.winCommand, TRUE); setConWindowCmdLine(1, "", 1, 0); // The background will also be in reverse. wbkgdset(mainWindow.console.winTitle, ' ' | A_REVERSE); // First clear the whole line. wmove(mainWindow.console.winTitle, 0, 0); wclrtoeol(mainWindow.console.winTitle); // Center the title. wmove(mainWindow.console.winTitle, 0, getmaxx(mainWindow.console.winTitle) / 2 - strlen(title) / 2); waddstr(mainWindow.console.winTitle, title); wrefresh(mainWindow.console.winTitle); // We'll need the input event handler. Sys_ConInputInit(); #endif } else { if(!(bpp == 32 || bpp == 16)) { Con_Message("createWindow: Unsupported BPP %i.", bpp); return 0; } #if defined(WIN32) // We need to grab a handle from SDL so we can link other subsystems // (e.g. DX-based input). { struct SDL_SysWMinfo wmInfo; if(!SDL_GetWMInfo(&wmInfo)) return NULL; mainWindow.hWnd = wmInfo.window; } #endif } setDDWindow(&mainWindow, w, h, bpp, flags, DDSW_NOVISIBLE | DDSW_NOCENTER | DDSW_NOFULLSCREEN); mainWindowInited = true; return &mainWindow; } /** * Create a new (OpenGL-ready) system window. * * @param app Ptr to the application structure holding our globals. * @param parentIDX Ignored: SDL does not support parent/child windows. * @param x Ignored: SDL does not support changing X position. * @param y Ignored: SDL does not support changing Y position.. * @param w Width (client area). * @param h Height (client area). * @param bpp BPP (bits-per-pixel) * @param flags DDWF_* flags, control appearance/behavior. * @param type Type of window to be created. * @param title Window title string, ELSE @c NULL,. * @param data Platform specific data. * * @return If @c 0, window creation was unsuccessful, * ELSE 1-based index identifier of the new window. */ uint Sys_CreateWindow(application_t *app, uint parentIDX, int x, int y, int w, int h, int bpp, int flags, ddwindowtype_t type, const char *title, void *data) { ddwindow_t *win; if(isDedicated) return 1; // No use. if(!winManagerInited) return 0; // Window manager not initialized yet. win = createDDWindow(app, w, h, bpp, flags, type, title); if(win) return 1; // Success. return 0; } /** * Destroy the specified window. * * Side-effects: If the window is fullscreen and the current video mode is * not that set as the desktop default: an attempt will be made to change * back to the desktop default video mode. * * @param idx Index of the window to destroy (1-based). * * @return @c true, if successful. */ boolean Sys_DestroyWindow(uint idx) { ddwindow_t *window = getWindow(idx - 1); if(!window) return false; if(window->type == WT_CONSOLE) { // Delete windows and shut down curses. delwin(window->console.winTitle); delwin(window->console.winText); delwin(window->console.winCommand); endwin(); window->console.winTitle = window->console.winText = window->console.winCommand = NULL; Sys_ConInputShutdown(); } return true; } /** * Change the currently active window. * * @param idx Index of the window to make active (1-based). * * @return @c true, if successful. */ boolean Sys_SetActiveWindow(uint idx) { // We only support one window, so yes its active. return true; } static boolean setDDWindow(ddwindow_t *window, int newWidth, int newHeight, int newBPP, uint wFlags, uint uFlags) { int width, height, bpp, flags; boolean newGLContext = false; boolean changeWindowDimensions = false; boolean inControlPanel = false; if(novideo) return true; if(uFlags & DDSW_NOCHANGES) return true; // Nothing to do. // Grab the current values. width = window->width; height = window->height; bpp = window->normal.bpp; flags = window->flags; // Force update on init? if(!window->inited && window->type == WT_NORMAL) { newGLContext = true; } if(window->type == WT_NORMAL) inControlPanel = UI_IsActive(); // Change to fullscreen? if(!(uFlags & DDSW_NOFULLSCREEN) && (flags & DDWF_FULLSCREEN) != (wFlags & DDWF_FULLSCREEN)) { flags ^= DDWF_FULLSCREEN; if(window->type == WT_NORMAL) { newGLContext = true; //changeVideoMode = true; } } // Change window size? if(!(uFlags & DDSW_NOSIZE) && (width != newWidth || height != newHeight)) { width = newWidth; height = newHeight; changeWindowDimensions = true; if(window->type == WT_NORMAL) newGLContext = true; } // Change BPP (bits per pixel)? if(window->type == WT_NORMAL) { if(!(uFlags & DDSW_NOBPP) && bpp != newBPP) { if(!(newBPP == 32 || newBPP == 16)) Con_Error("Sys_SetWindow: Unsupported BPP %i.", newBPP); bpp = newBPP; newGLContext = true; //changeVideoMode = true; } } if(changeWindowDimensions && window->type == WT_NORMAL) { // Can't change the resolution while the UI is active. // (controls need to be repositioned). if(inControlPanel) UI_End(); } /* if(changeVideoMode) { if(flags & DDWF_FULLSCREEN) { if(!Sys_ChangeVideoMode(width, height, bpp)) { Sys_CriticalMessage("Sys_SetWindow: Resolution change failed."); return false; } } else { // Go back to normal display settings. ChangeDisplaySettings(0, 0); } } */ // Update the current values. window->width = width; window->height = height; window->normal.bpp = bpp; window->flags = flags; if(!window->inited) window->inited = true; // Do NOT modify ddwindow_t properties after this point. // Do we need a new GL context due to changes to the window? if(newGLContext) { // Maybe requires a renderer restart. extern boolean usingFog; boolean glIsInited = GL_IsInited(); #if defined(WIN32) void *data = window->hWnd; #else void *data = NULL; #endif boolean hadFog; if(glIsInited) { // Shut everything down, but remember our settings. hadFog = usingFog; GL_TotalReset(); gx.UpdateState(DD_RENDER_RESTART_PRE); UI_ClearTextures(); } if(createContext(window->width, window->height, window->normal.bpp, (window->flags & DDWF_FULLSCREEN)? false : true, data)) { // We can get on with initializing the OGL state. Sys_InitGLState(); } if(glIsInited) { // Re-initialize. GL_TotalRestore(); GL_InitRefresh(); if(hadFog) GL_UseFog(true); gx.UpdateState(DD_RENDER_RESTART_POST); UI_LoadTextures(); } } /*else { Sys_ChangeVideoMode(window->width, window->height, window->normal.bpp); }*/ // If the window dimensions have changed, update any sub-systems // which need to respond. if(changeWindowDimensions && window->type == WT_NORMAL) { // Update viewport coordinates. R_SetViewGrid(0, 0); if(inControlPanel) // Reactivate the panel? Con_Execute(CMDS_DDAY, "panel", true, false); } return true; } /** * Attempt to set the appearance/behavioral properties of the given window. * * @param idx Index identifier (1-based) to the window. * @param newX New x position of the left side of the window. * @param newY New y position of the top of the window. * @param newWidth New width to set the window to. * @param newHeight New height to set the window to. * @param newBPP New BPP (bits-per-pixel) to change to. * @param wFlags DDWF_* flags to change other appearance/behavior. * @param uFlags DDSW_* flags govern how the other paramaters should be * interpreted. * * DDSW_NOSIZE: * If set, params 'newWidth' and 'newHeight' are ignored * and no change will be made to the window dimensions. * * DDSW_NOMOVE: * If set, params 'newX' and 'newY' are ignored and no * change will be made to the window position. * * DDSW_NOBPP: * If set, param 'newBPP' is ignored and the no change * will be made to the window color depth. * * DDSW_NOFULLSCREEN: * If set, the value of the DDWF_FULLSCREEN bit in param * 'wFlags' is ignored and no change will be made to the * fullscreen state of the window. * * DDSW_NOVISIBLE: * If set, the value of the DDWF_VISIBLE bit in param * 'wFlags' is ignored and no change will be made to the * window's visibility. * * DDSW_NOCENTER: * If set, the value of the DDWF_CENTER bit in param * 'wFlags' is ignored and no change will be made to the * auto-center state of the window. * * @return @c true, if successful. */ boolean Sys_SetWindow(uint idx, int newX, int newY, int newWidth, int newHeight, int newBPP, uint wFlags, uint uFlags) { ddwindow_t *window = getWindow(idx - 1); if(window) return setDDWindow(window, newWidth, newHeight, newBPP, wFlags, uFlags); return false; } /** * Make the content of the framebuffer visible. */ void Sys_UpdateWindow(uint idx) { if(GL_state.forceFinishBeforeSwap) { glFinish(); } // Swap buffers. SDL_GL_SwapBuffers(); // Includes a call to glFlush() } /** * Attempt to set the title of the given window. * * @param idx Index identifier (1-based) to the window. * @param title New title for the window. * * @return @c true, if successful. */ boolean Sys_SetWindowTitle(uint idx, const char *title) { ddwindow_t *window = getWindow(idx - 1); if(window) { if(window->type == WT_NORMAL) { SDL_WM_SetCaption(title, NULL); } else // Its a terminal window. { #if defined(UNIX) // The background will also be in reverse. wbkgdset(window->console.winTitle, ' ' | A_REVERSE); // First clear the whole line. wmove(window->console.winTitle, 0, 0); wclrtoeol(window->console.winTitle); // Center the title. wmove(window->console.winTitle, 0, getmaxx(window->console.winTitle) / 2 - strlen(title) / 2); waddstr(window->console.winTitle, title); wrefresh(window->console.winTitle); #endif } return true; } return false; } /** * Attempt to get the dimensions (and position) of the given window (client * area) in screen-space. * * @param idx Index identifier (1-based) to the window. * @param x Address to write the x position back to, * unsupported by SDL so always 0. * @param y Address to write the y position back to, * unsupported by SDL so always 0. * @param width Address to write the width back to (if any). * @param height Address to write the height back to (if any). * * @return @c true, if successful. */ boolean Sys_GetWindowDimensions(uint idx, int *x, int *y, int *width, int *height) { ddwindow_t *window = getWindow(idx - 1); if(!window || (!x && !y && !width && !height)) return false; // Moving does not work in dedicated mode. if(isDedicated) return false; if(x) *x = 0; if(y) *y = 0; if(width) *width = window->width; if(height) *height = window->height; return true; } /** * Attempt to get the BPP (bits-per-pixel) of the given window. * * @param idx Index identifier (1-based) to the window. * @param bpp Address to write the BPP back to (if any). * * @return @c true, if successful. */ boolean Sys_GetWindowBPP(uint idx, int *bpp) { ddwindow_t *window = getWindow(idx - 1); if(!window || !bpp) return false; // Not in dedicated mode. if(isDedicated) return false; *bpp = window->normal.bpp; return true; } /** * Attempt to get the fullscreen-state of the given window. * * @param idx Index identifier (1-based) to the window. * @param fullscreen Address to write the fullscreen state back to (if any). * * @return @c true, if successful. */ boolean Sys_GetWindowFullscreen(uint idx, boolean *fullscreen) { ddwindow_t *window = getWindow(idx - 1); if(!window || !fullscreen) return false; *fullscreen = ((window->flags & DDWF_FULLSCREEN)? true : false); return true; } /** * Attempt to get a HWND handle to the given window. * * \todo: Factor platform specific design patterns out of Doomsday. We should * not be passing around HWND handles... * * @param idx Index identifier (1-based) to the window. * * @return HWND handle if successful, ELSE @c NULL,. */ #if defined(WIN32) HWND Sys_GetWindowHandle(uint idx) { ddwindow_t *window = getWindow(idx - 1); if(!window) return NULL; return window->hWnd; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/cl_player.c0000644000175000017500000006125511357170241023057 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_player.c: Clientside Player Management */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_refresh.h" #include "de_play.h" #include "def_main.h" // MACROS ------------------------------------------------------------------ #define TOP_PSPY (32) #define BOTTOM_PSPY (128) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float pspMoveSpeed = 6; float cplrThrustMul = 1; clplayerstate_t clPlayerStates[DDMAXPLAYERS]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int fixSpeed = 15; static float fixPos[3]; static int fixTics; static float pspY; // Console player demo momentum (used to smooth out abrupt momentum changes). static float cpMom[3][LOCALCAM_WRITE_TICS]; // CODE -------------------------------------------------------------------- /** * Clears the player state table. */ void Cl_InitPlayers(void) { int i; fixTics = 0; pspY = 0; memset(&clPlayerStates, 0, sizeof(clPlayerStates)); memset(fixPos, 0, sizeof(fixPos)); memset(cpMom, 0, sizeof(cpMom)); // Clear psprites. The server will send them. for(i = 0; i < DDMAXPLAYERS; ++i) { client_t *cl = &clients[i]; memset(cl->lastCmd, 0, sizeof(*cl->lastCmd)); } } /** * Updates the state of the local player by looking at lastCmd. */ void Cl_LocalCommand(void) { client_t *cl = &clients[consolePlayer]; player_t *plr = &ddPlayers[consolePlayer]; ddplayer_t *ddpl = &plr->shared; clplayerstate_t *s = &clPlayerStates[consolePlayer]; float off, vel; if(ddMapTime < 0.333) { // In the very beginning of a map, moving is not allowed. memset(cl->lastCmd, 0, TICCMD_SIZE); if(s->cmo) { s->cmo->mo.mom[MX] = 0; s->cmo->mo.mom[MY] = 0; } } //s->forwardMove = cl->lastCmd->forwardMove * 2048; P_GetControlState(consolePlayer, CTL_WALK, &vel, &off); s->forwardMove = (off + vel) * 2048; s->sideMove = cl->lastCmd->sideMove * 2048; s->angle = ddpl->mo->angle; //ddpl->clAngle; /* $unifiedangles */ #if _DEBUG if(s->forwardMove || s->sideMove) { Con_Message("Cl_LocalCommand: fwd=%i sd=%i\n", s->forwardMove, s->sideMove); } VERBOSE2(Con_Message("Cl_LocalCommand: angle=%x\n", s->angle)); #endif s->turnDelta = 0; } /** * Reads a single player delta from the message buffer and applies it to the * player in question. Returns false only if the list of deltas ends. * * \deprecated THIS FUNCTION IS NOW OBSOLETE (only used with PSV_FRAME * packets). */ int Cl_ReadPlayerDelta(void) { int df, psdf, i, idx; int num = Msg_ReadByte(); short junk; player_t *plr; clplayerstate_t *s; ddplayer_t *ddpl; ddpsprite_t *psp; if(num == 0xff) return false; // End of list. // The first byte consists of a player number and some flags. df = (num & 0xf0) << 8; df |= Msg_ReadByte(); // Second byte is just flags. num &= 0xf; // Clear the upper bits of the number. plr = &ddPlayers[num]; ddpl = &plr->shared; s = &clPlayerStates[num]; if(df & PDF_MOBJ) { clmobj_t *old = s->cmo; int newid = Msg_ReadShort(); /** * Make sure the 'new' mobj is different than the old one; there * will be linking problems otherwise. * \fixme What causes the duplicate sending of mobj ids? */ if(newid != s->mobjId) { s->mobjId = newid; // Find the new mobj. s->cmo = Cl_FindMobj(s->mobjId); #ifdef _DEBUG Con_Message("Pl%i: mobj=%i old=%ul\n", num, s->mobjId, (uint) old); Con_Message(" x=%f y=%f z=%f\n", s->cmo->mo.pos[VX], s->cmo->mo.pos[VY], s->cmo->mo.pos[VZ]); #endif s->cmo->mo.dPlayer = ddpl; #ifdef _DEBUG Con_Message("Cl_RPlD: pl=%i => moid=%i\n", num, s->mobjId); #endif // Unlink this cmo (not interactive or visible). Cl_UnsetMobjPosition(s->cmo); // Make the old clmobj a non-player one. if(old) { old->mo.dPlayer = NULL; Cl_SetMobjPosition(old); Cl_UpdateRealPlayerMobj(ddpl->mo, &s->cmo->mo, ~0); } else { //Cl_UpdatePlayerPos(ddpl); // Replace the hidden client mobj with the real player mobj. Cl_UpdateRealPlayerMobj(ddpl->mo, &s->cmo->mo, ~0); } // Update the real player mobj. //Cl_UpdateRealPlayerMobj(ddpl->mo, &s->cmo->mo, ~0); } } if(df & PDF_FORWARDMOVE) s->forwardMove = (char) Msg_ReadByte() * 2048; if(df & PDF_SIDEMOVE) s->sideMove = (char) Msg_ReadByte() * 2048; if(df & PDF_ANGLE) //s->angle = Msg_ReadByte() << 24; junk = Msg_ReadByte(); /* $unifiedangles */ if(df & PDF_TURNDELTA) { s->turnDelta = ((char) Msg_ReadByte() << 24) / 16; } if(df & PDF_FRICTION) s->friction = Msg_ReadByte() << 8; if(df & PDF_EXTRALIGHT) { i = Msg_ReadByte(); ddpl->fixedColorMap = i & 7; ddpl->extraLight = i & 0xf8; } if(df & PDF_FILTER) { int filter = Msg_ReadLong(); if(filter) ddpl->flags |= DDPF_VIEW_FILTER; else ddpl->flags &= ~DDPF_VIEW_FILTER; ddpl->filterColor[CR] = filter & 0xff; ddpl->filterColor[CG] = (filter >> 8) & 0xff; ddpl->filterColor[CB] = (filter >> 16) & 0xff; ddpl->filterColor[CA] = (filter >> 24) & 0xff; } if(df & PDF_CLYAW) // Only sent when Fixangles is used. //pl->clAngle = Msg_ReadShort() << 16; /* $unifiedangles */ junk = Msg_ReadShort(); if(df & PDF_CLPITCH) // Only sent when Fixangles is used. //pl->clLookDir = Msg_ReadShort() * 110.0 / DDMAXSHORT; /* $unifiedangles */ junk = Msg_ReadShort(); if(df & PDF_PSPRITES) { for(i = 0; i < 2; ++i) { // First the flags. psdf = Msg_ReadByte(); psp = ddpl->pSprites + i; if(psdf & PSDF_STATEPTR) { idx = Msg_ReadPackedShort(); if(!idx) psp->statePtr = 0; else if(idx < countStates.num) { psp->statePtr = states + (idx - 1); psp->tics = psp->statePtr->tics; } } //if(psdf & PSDF_SPRITE) psp->sprite = Msg_ReadPackedShort() - 1; //if(psdf & PSDF_FRAME) psp->frame = Msg_ReadByte(); //if(psdf & PSDF_NEXT/*FRAME*/) psp->nextframe = (char) Msg_ReadByte(); //if(psdf & PSDF_NEXT/*TIME*/) psp->nexttime = (char) Msg_ReadByte(); //if(psdf & PSDF_TICS) psp->tics = (char) Msg_ReadByte(); if(psdf & PSDF_LIGHT) /* psp->light = */ Msg_ReadByte() /* / 255.0f */; if(psdf & PSDF_ALPHA) psp->alpha = Msg_ReadByte() / 255.0f; if(psdf & PSDF_STATE) psp->state = Msg_ReadByte(); if(psdf & PSDF_OFFSET) { psp->offset[VX] = (char) Msg_ReadByte() * 2; psp->offset[VY] = (char) Msg_ReadByte() * 2; } } } // Continue reading. return true; } /** * Thrust (with a multiplier). */ void Cl_ThrustMul(mobj_t *mo, angle_t angle, float move, float thmul) { // Make a fine angle. angle >>= ANGLETOFINESHIFT; move *= thmul; mo->mom[MX] += move * FIX2FLT(fineCosine[angle]); mo->mom[MY] += move * FIX2FLT(finesine[angle]); } void Cl_Thrust(mobj_t *mo, angle_t angle, float move) { Cl_ThrustMul(mo, angle, move, 1); } /** * Predict the movement of the given player. * * This kind of player movement can't be used with demos. The local player * movement is recorded into the demo file as absolute coordinates. */ void Cl_MovePlayer(int plrNum) { player_t *plr; ddplayer_t *ddpl; clplayerstate_t *st; mobj_t *mo; if(plrNum < 0 || plrNum >= DDMAXPLAYERS) return; // If we are playing a demo, we shouldn't be here... if(playback && plrNum == consolePlayer) return; plr = &ddPlayers[plrNum]; st = &clPlayerStates[plrNum]; ddpl = &plr->shared; mo = plr->shared.mo; // Move. P_MobjMovement2(mo, st); P_MobjZMovement(mo); #ifdef _DEBUG VERBOSE2(Con_Message("Cl_MovePlayer: Pl%i: mo x=%g y=%g\n", plrNum, mo->pos[VX], mo->pos[VY])); #endif /** * Predict change in movement (thrust). * The console player is always affected by the thrust multiplier * (Other players are never handled because clients only receive mobj * information about non-local player movement). */ if(plrNum == consolePlayer) { float airThrust = 1.0f / 32; boolean airborne = (mo->pos[VZ] > mo->floorZ && !(mo->ddFlags & DDMF_FLY)); if(!(ddpl->flags & DDPF_DEAD) && !mo->reactionTime) // Dead players do not move willfully. { float mul = (airborne? airThrust : cplrThrustMul); if(st->forwardMove) Cl_ThrustMul(mo, st->angle, FIX2FLT(st->forwardMove), mul); if(st->sideMove) Cl_ThrustMul(mo, st->angle - ANG90, FIX2FLT(st->sideMove), mul); } // Turn delta on move prediction angle. st->angle += st->turnDelta; //mo->angle += st->turnDelta; } // Mirror changes in the (hidden) client mobj. Cl_UpdatePlayerPos(plrNum); } /** * Move the (hidden, unlinked) client player mobj to the same coordinates * where the real mobj of the player is. */ void Cl_UpdatePlayerPos(int plrNum) { player_t *plr; mobj_t *clmo, *mo; clplayerstate_t *s; if(plrNum < 0 || plrNum >= DDMAXPLAYERS) return; plr = &ddPlayers[plrNum]; s = &clPlayerStates[plrNum]; if(!s->cmo || !plr->shared.mo) return; // Must have a mobj! clmo = &s->cmo->mo; mo = plr->shared.mo; clmo->angle = mo->angle; // The player's client mobj is not linked to any lists, so position // can be updated without any hassles. memcpy(clmo->pos, mo->pos, sizeof(mo->pos)); P_MobjLink(clmo, 0); // Update subsector pointer. clmo->floorZ = mo->floorZ; clmo->ceilingZ = mo->ceilingZ; clmo->mom[MX] = mo->mom[MX]; clmo->mom[MY] = mo->mom[MY]; clmo->mom[MZ] = mo->mom[MZ]; } void Cl_CoordsReceived(void) { if(playback) return; #ifdef _DEBUG Con_Printf("Cl_CoordsReceived\n"); #endif fixPos[VX] = (float) Msg_ReadShort(); fixPos[VY] = (float) Msg_ReadShort(); fixTics = fixSpeed; fixPos[VX] /= fixSpeed; fixPos[VY] /= fixSpeed; } void Cl_HandlePlayerFix(void) { player_t *plr = &ddPlayers[consolePlayer]; clmobj_t *clmo = clPlayerStates[consolePlayer].cmo; ddplayer_t *ddpl = &plr->shared; mobj_t *mo = ddpl->mo; int fixes = Msg_ReadLong(); angle_t angle; float lookdir; if(fixes & 1) // fix angles? { ddpl->fixCounter.angles = ddpl->fixAcked.angles = Msg_ReadLong(); angle = Msg_ReadLong(); lookdir = FIX2FLT(Msg_ReadLong()); #ifdef _DEBUG Con_Message("Cl_HandlePlayerFix: Fix angles %i. Angle=%f, lookdir=%f\n", ddpl->fixAcked.angles, FIX2FLT(angle), lookdir); #endif if(mo) { #ifdef _DEBUG Con_Message(" Applying to mobj %p...\n", mo); #endif mo->angle = angle; ddpl->lookDir = lookdir; } if(clmo) { #ifdef _DEBUG Con_Message(" Applying to clmobj %i...\n", clmo->mo.thinker.id); #endif clmo->mo.angle = angle; } } if(fixes & 2) // fix pos? { float pos[3]; ddpl->fixCounter.pos = ddpl->fixAcked.pos = Msg_ReadLong(); pos[VX] = FIX2FLT(Msg_ReadLong()); pos[VY] = FIX2FLT(Msg_ReadLong()); pos[VZ] = FIX2FLT(Msg_ReadLong()); #ifdef _DEBUG Con_Message("Cl_HandlePlayerFix: Fix pos %i. Pos=%f, %f, %f\n", ddpl->fixAcked.pos, pos[VX], pos[VY], pos[VZ]); #endif if(mo) { #ifdef _DEBUG Con_Message(" Applying to mobj %p...\n", mo); #endif Sv_PlaceMobj(mo, pos[VX], pos[VY], pos[VZ], false); mo->reactionTime = 18; } if(clmo) { #ifdef _DEBUG Con_Message(" Applying to clmobj %i...\n", clmo->mo.thinker.id); #endif Cl_UpdatePlayerPos(plr - ddPlayers); } } if(fixes & 4) // fix momentum? { float pos[3]; ddpl->fixCounter.mom = ddpl->fixAcked.mom = Msg_ReadLong(); pos[0] = FIX2FLT(Msg_ReadLong()); pos[1] = FIX2FLT(Msg_ReadLong()); pos[2] = FIX2FLT(Msg_ReadLong()); #ifdef _DEBUG Con_Message("Cl_HandlePlayerFix: Fix momentum %i. Mom=%f, %f, %f\n", ddpl->fixAcked.mom, pos[0], pos[1], pos[2]); #endif if(mo) { #ifdef _DEBUG Con_Message(" Applying to mobj %p...\n", mo); #endif mo->mom[MX] = pos[0]; mo->mom[MY] = pos[1]; mo->mom[MZ] = pos[2]; } if(clmo) { #ifdef _DEBUG Con_Message(" Applying to clmobj %i...\n", clmo->mo.thinker.id); #endif clmo->mo.mom[MX] = pos[0]; clmo->mo.mom[MY] = pos[1]; clmo->mo.mom[MZ] = pos[2]; } } // Send an acknowledgement. Msg_Begin(PCL_ACK_PLAYER_FIX); Msg_WriteLong(ddpl->fixAcked.angles); Msg_WriteLong(ddpl->fixAcked.pos); Msg_WriteLong(ddpl->fixAcked.mom); Net_SendBuffer(0, SPF_ORDERED | SPF_CONFIRM); } /** * Used in DEMOS. (Not in regular netgames.) * Applies the given dx and dy to the local player's coordinates. * * @param z Absolute viewpoint height. * @param onground If @c true the mobj's Z will be set to floorz, and * the player's viewheight is set so that the viewpoint * height is param 'z'. * If @c false the mobj's Z will be param 'z' and * viewheight is zero. */ void Cl_MoveLocalPlayer(float dx, float dy, float z, boolean onground) { player_t *plr = &ddPlayers[consolePlayer]; ddplayer_t *ddpl = &plr->shared; mobj_t *mo = ddpl->mo; int i; float mom[3]; if(!mo) return; // Place the new momentum in the appropriate place. cpMom[MX][SECONDS_TO_TICKS(gameTime) % LOCALCAM_WRITE_TICS] = dx; cpMom[MY][SECONDS_TO_TICKS(gameTime) % LOCALCAM_WRITE_TICS] = dy; // Calculate an average. mom[MX] = mom[MY] = 0; for(i = 0; i < LOCALCAM_WRITE_TICS; ++i) { mom[MX] += cpMom[MX][i]; mom[MY] += cpMom[MY][i]; } mom[MX] /= LOCALCAM_WRITE_TICS; mom[MY] /= LOCALCAM_WRITE_TICS; mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; if(dx != 0 || dy != 0) { P_MobjUnlink(mo); mo->pos[VX] += dx; mo->pos[VY] += dy; P_MobjLink(mo, DDLINK_SECTOR | DDLINK_BLOCKMAP); } mo->subsector = R_PointInSubsector(mo->pos[VX], mo->pos[VY]); mo->floorZ = mo->subsector->sector->SP_floorheight; mo->ceilingZ = mo->subsector->sector->SP_ceilheight; if(onground) { mo->pos[VZ] = z - 1; } else { mo->pos[VZ] = z; } Cl_UpdatePlayerPos(consolePlayer); } /** * Animates the player sprites based on their states (up, down, etc.) */ #if 0 // Currently unused. void Cl_MovePsprites(void) { ddplayer_t *pl = &players[consolePlayer].shared; ddpsprite_t *psp = pl->pSprites; int i; for(i = 0; i < 2; ++i) if(psp[i].tics > 0) psp[i].tics--; switch(psp->state) { case DDPSP_UP: pspY -= pspMoveSpeed; if(pspY <= TOP_PSPY) { pspY = TOP_PSPY; psp->state = DDPSP_BOBBING; } psp->y = pspY; break; case DDPSP_DOWN: pspY += pspMoveSpeed; if(pspY > BOTTOM_PSPY) pspY = BOTTOM_PSPY; psp->y = pspY; break; case DDPSP_FIRE: pspY = TOP_PSPY; //psp->x = 0; psp->y = pspY; break; case DDPSP_BOBBING: pspY = TOP_PSPY; // Get bobbing from the Game DLL. psp->x = *((float*) gx.GetVariable(DD_PSPRITE_BOB_X)); psp->y = *((float*) gx.GetVariable(DD_PSPRITE_BOB_Y)); break; } if(psp->state != DDPSP_BOBBING) { if(psp->offX) psp->x = psp->offX; if(psp->offY) psp->y = psp->offY; } // The other psprite gets the same coords. psp[1].x = psp->x; psp[1].y = psp->y; } #endif /** * Reads a single PSV_FRAME2 player delta from the message buffer and * applies it to the player in question. */ void Cl_ReadPlayerDelta2(boolean skip) { static player_t dummyPlayer; static clplayerstate_t dummyClState; int df = 0, psdf, i, idx; clplayerstate_t *s; ddplayer_t *ddpl; ddpsprite_t *psp; int num, newId; short junk; // The first byte consists of a player number and some flags. num = Msg_ReadByte(); df = (num & 0xf0) << 8; df |= Msg_ReadByte(); // Second byte is just flags. num &= 0xf; // Clear the upper bits of the number. if(!skip) { s = &clPlayerStates[num]; ddpl = &ddPlayers[num].shared; } else { // We're skipping, read the data into dummies. s = &dummyClState; ddpl = &dummyPlayer.shared; } if(df & PDF_MOBJ) { clmobj_t *old = s->cmo; newId = Msg_ReadShort(); // Make sure the 'new' mobj is different than the old one; // there will be linking problems otherwise. if(!skip && newId != s->mobjId) { boolean justCreated = false; s->mobjId = newId; // Find the new mobj. s->cmo = Cl_FindMobj(s->mobjId); if(!s->cmo) { // This mobj hasn't yet been sent to us. // We should be receiving the rest of the info very shortly. s->cmo = Cl_CreateMobj(s->mobjId); if(num == consolePlayer) { // Mark everything known about our local player. s->cmo->flags |= CLMF_KNOWN; } justCreated = true; } else { // The client mobj is already known to us. // Unlink it (not interactive or visible). Cl_UnsetMobjPosition(s->cmo); } s->cmo->mo.dPlayer = ddpl; // Make the old clmobj a non-player one (if any). if(old) { old->mo.dPlayer = NULL; Cl_SetMobjPosition(old); } // If it was just created, the coordinates are not yet correct. // The update will be made when the mobj data is received. if(!justCreated && num != consolePlayer) { // Replace the hidden client mobj with the real player mobj. Cl_UpdateRealPlayerMobj(ddpl->mo, &s->cmo->mo, 0xffffffff); } else if(ddpl->mo) { // Update the new client mobj's information from the real // mobj, which is already known. #if _DEBUG Con_Message("Cl_RdPlrD2: Pl%i: Copying pos&angle from real mobj to clmobj.\n", num); Con_Message(" x=%g y=%g z=%g\n", ddpl->mo->pos[VX], ddpl->mo->pos[VY], ddpl->mo->pos[VZ]); #endif s->cmo->mo.pos[VX] = ddpl->mo->pos[VX]; s->cmo->mo.pos[VY] = ddpl->mo->pos[VY]; s->cmo->mo.pos[VZ] = ddpl->mo->pos[VZ]; s->cmo->mo.angle = ddpl->mo->angle; if(!skip) Cl_UpdatePlayerPos(num); } #if _DEBUG Con_Message("Cl_RdPlrD2: Pl%i: mobj=%i old=%ul\n", num, s->mobjId, (unsigned int) old); Con_Message(" x=%g y=%g z=%g fz=%g cz=%g\n", s->cmo->mo.pos[VX], s->cmo->mo.pos[VY], s->cmo->mo.pos[VZ], s->cmo->mo.floorZ, s->cmo->mo.ceilingZ); Con_Message("Cl_RdPlrD2: pl=%i => moid=%i\n", (skip? -1 : num), s->mobjId); #endif } } if(df & PDF_FORWARDMOVE) s->forwardMove = (char) Msg_ReadByte() * 2048; if(df & PDF_SIDEMOVE) s->sideMove = (char) Msg_ReadByte() * 2048; if(df & PDF_ANGLE) //s->angle = Msg_ReadByte() << 24; junk = Msg_ReadByte(); if(df & PDF_TURNDELTA) { s->turnDelta = ((char) Msg_ReadByte() << 24) / 16; } if(df & PDF_FRICTION) s->friction = Msg_ReadByte() << 8; if(df & PDF_EXTRALIGHT) { i = Msg_ReadByte(); ddpl->fixedColorMap = i & 7; ddpl->extraLight = i & 0xf8; } if(df & PDF_FILTER) { int filter = Msg_ReadLong(); if(filter) ddpl->flags |= DDPF_VIEW_FILTER; else ddpl->flags &= ~DDPF_VIEW_FILTER; ddpl->filterColor[CR] = filter & 0xff; ddpl->filterColor[CG] = (filter >> 8) & 0xff; ddpl->filterColor[CB] = (filter >> 16) & 0xff; ddpl->filterColor[CA] = (filter >> 24) & 0xff; } if(df & PDF_CLYAW) // Only sent when Fixangles is used. //ddpl->clAngle = Msg_ReadShort() << 16; /* $unifiedangles */ junk = Msg_ReadShort(); if(df & PDF_CLPITCH) // Only sent when Fixangles is used. //ddpl->clLookDir = Msg_ReadShort() * 110.0 / DDMAXSHORT; /* $unifiedangles */ junk = Msg_ReadShort(); if(df & PDF_PSPRITES) { for(i = 0; i < 2; ++i) { // First the flags. psdf = Msg_ReadByte(); psp = ddpl->pSprites + i; if(psdf & PSDF_STATEPTR) { idx = Msg_ReadPackedShort(); if(!idx) psp->statePtr = 0; else if(idx < countStates.num) { psp->statePtr = states + (idx - 1); psp->tics = psp->statePtr->tics; } } /*if(psdf & PSDF_LIGHT) psp->light = Msg_ReadByte() / 255.0f;*/ if(psdf & PSDF_ALPHA) psp->alpha = Msg_ReadByte() / 255.0f; if(psdf & PSDF_STATE) psp->state = Msg_ReadByte(); if(psdf & PSDF_OFFSET) { psp->offset[VX] = (char) Msg_ReadByte() * 2; psp->offset[VY] = (char) Msg_ReadByte() * 2; } } } } /** * Used by the client plane mover. * * @return @c true, if the player is free to move according to * floorz and ceilingz. */ boolean Cl_IsFreeToMove(int plrNum) { mobj_t* mo = ddPlayers[plrNum].shared.mo; if(!mo) return false; return (mo->pos[VZ] >= mo->floorZ && mo->pos[VZ] + mo->height <= mo->ceilingZ); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_model.c0000644000175000017500000007142211357170242023213 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_model.c: 3D Model Renderer v2.0 * * Note: Light vectors and triangle normals are considered to be * in a totally independent, right-handed coordinate system. * * There is some more confusion with Y and Z axes as the game uses * Z as the vertical axis and the rendering code and model definitions * use the Y axis. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_console.h" #include "de_render.h" #include "de_play.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_misc.h" #include "net_main.h" // for gametic // MACROS ------------------------------------------------------------------ #define MAX_VERTS 4096 // Maximum number of vertices per model. #define DOTPROD(a, b) (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) #define QATAN2(y,x) qatan2(y,x) #define QASIN(x) asin(x) // \fixme Precalculate arcsin. // TYPES ------------------------------------------------------------------- typedef enum rendcmd_e { RC_COMMAND_COORDS, RC_OTHER_COORDS, RC_BOTH_COORDS } rendcmd_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int modelLight = 4; int frameInter = true; int mirrorHudModels = false; int modelShinyMultitex = true; float modelShinyFactor = 1.0f; int modelTriCount; float rend_model_lod = 256; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Fixed-size vertex arrays for the model. static dgl_vertex_t modelVertices[MAX_VERTS]; static dgl_vertex_t modelNormals[MAX_VERTS]; static dgl_color_t modelColors[MAX_VERTS]; static dgl_texcoord_t modelTexCoords[MAX_VERTS]; // Global variables for ease of use. (Egads!) static float modelCenter[3]; static int activeLod; static char *vertexUsage; // CODE -------------------------------------------------------------------- void Rend_ModelRegister(void) { C_VAR_BYTE("rend-model", &useModels, 0, 0, 1); C_VAR_INT("rend-model-lights", &modelLight, 0, 0, 10); C_VAR_INT("rend-model-inter", &frameInter, 0, 0, 1); C_VAR_FLOAT("rend-model-aspect", &rModelAspectMod, CVF_NO_MAX | CVF_NO_MIN, 0, 0); C_VAR_INT("rend-model-distance", &maxModelDistance, CVF_NO_MAX, 0, 0); C_VAR_BYTE("rend-model-precache", &precacheSkins, 0, 0, 1); C_VAR_FLOAT("rend-model-lod", &rend_model_lod, CVF_NO_MAX, 0, 0); C_VAR_INT("rend-model-mirror-hud", &mirrorHudModels, 0, 0, 1); C_VAR_FLOAT("rend-model-spin-speed", &modelSpinSpeed, CVF_NO_MAX | CVF_NO_MIN, 0, 0); C_VAR_INT("rend-model-shiny-multitex", &modelShinyMultitex, 0, 0, 1); C_VAR_FLOAT("rend-model-shiny-strength", &modelShinyFactor, 0, 0, 10); } static __inline float qatan2(float y, float x) { float ang = BANG2RAD(bamsAtan2(y * 512, x * 512)); if(ang > PI) ang -= 2 * (float) PI; return ang; // This is slightly faster, I believe... //return atan2(y, x); } /** * Linear interpolation between two values. */ __inline float Mod_Lerp(float start, float end, float pos) { return end * pos + start * (1 - pos); } /** * Return a pointer to the visible model frame. */ model_frame_t *Mod_GetVisibleFrame(modeldef_t *mf, int subnumber, int mobjid) { model_t *mdl = modellist[mf->sub[subnumber].model]; int index = mf->sub[subnumber].frame; if(mf->flags & MFF_IDFRAME) { index += mobjid % mf->sub[subnumber].frameRange; } if(index >= mdl->info.numFrames) { Con_Error("Mod_GetVisibleFrame: Frame index out of bounds.\n" " (Model: %s)\n", mdl->fileName); } return mdl->frames + index; } /** * Render a set of GL commands using the given data. */ void Mod_RenderCommands(rendcmd_t mode, void *glCommands, /*uint numVertices,*/ dgl_vertex_t *vertices, dgl_color_t *colors, dgl_texcoord_t *texCoords) { byte *pos; glcommand_vertex_t *v; int count; void *coords[2]; // Disable all vertex arrays. GL_DisableArrays(true, true, DDMAXINT); // Load the vertex array. switch(mode) { case RC_OTHER_COORDS: coords[0] = texCoords; GL_Arrays(vertices, colors, 1, coords, 0); break; case RC_BOTH_COORDS: coords[0] = NULL; coords[1] = texCoords; GL_Arrays(vertices, colors, 2, coords, 0); break; default: GL_Arrays(vertices, colors, 0, NULL, 0 /* numVertices */ ); break; } for(pos = glCommands; *pos;) { count = LONG( *(int *) pos ); pos += 4; // The type of primitive depends on the sign. glBegin(count > 0 ? GL_TRIANGLE_STRIP : GL_TRIANGLE_FAN); if(count < 0) count = -count; // Increment the total model triangle counter. modelTriCount += count - 2; while(count--) { v = (glcommand_vertex_t *) pos; pos += sizeof(glcommand_vertex_t); if(mode != RC_OTHER_COORDS) { glTexCoord2f(FLOAT(v->s), FLOAT(v->t)); } GL_ArrayElement(LONG(v->index)); } // The primitive is complete. glEnd(); } } /** * Interpolate linearly between two sets of vertices. */ void Mod_LerpVertices(float pos, int count, model_vertex_t *start, model_vertex_t *end, dgl_vertex_t *out) { int i; float inv; if(start == end || pos == 0) { for(i = 0; i < count; ++i, start++, out++) { out->xyz[0] = start->xyz[0]; out->xyz[1] = start->xyz[1]; out->xyz[2] = start->xyz[2]; } return; } inv = 1 - pos; if(vertexUsage) { for(i = 0; i < count; ++i, start++, end++, out++) if(vertexUsage[i] & (1 << activeLod)) { out->xyz[0] = inv * start->xyz[0] + pos * end->xyz[0]; out->xyz[1] = inv * start->xyz[1] + pos * end->xyz[1]; out->xyz[2] = inv * start->xyz[2] + pos * end->xyz[2]; } } else { for(i = 0; i < count; ++i, start++, end++, out++) { out->xyz[0] = inv * start->xyz[0] + pos * end->xyz[0]; out->xyz[1] = inv * start->xyz[1] + pos * end->xyz[1]; out->xyz[2] = inv * start->xyz[2] + pos * end->xyz[2]; } } } /** * Negate all Z coordinates. */ void Mod_MirrorVertices(int count, dgl_vertex_t *v, int axis) { for(; count-- > 0; v++) v->xyz[axis] = -v->xyz[axis]; } typedef struct { float color[3], extra[3], rotateYaw, rotatePitch; dgl_vertex_t* normal; uint processedLights, maxLights; boolean invert; } lightmodelvertexparams_t; static boolean lightModelVertex(const vlight_t* vlight, void* context) { float dot; float* dest, lightVector[3]; lightmodelvertexparams_t* params = (lightmodelvertexparams_t*) context; // Take a copy of the light vector as we intend to change it. lightVector[0] = vlight->vector[0]; lightVector[1] = vlight->vector[1]; lightVector[2] = vlight->vector[2]; // We must transform the light vector to model space. M_RotateVector(lightVector, params->rotateYaw, params->rotatePitch); // Quick hack: Flip light normal if model inverted. if(params->invert) { lightVector[VX] = -lightVector[VX]; lightVector[VY] = -lightVector[VY]; } dot = DOTPROD(lightVector, params->normal->xyz); dot += vlight->offset; // Shift a bit towards the light. if(!vlight->affectedByAmbient) { // Won't be affected by ambient. dest = params->extra; } else { dest = params->color; } // Ability to both light and shade. if(dot > 0) { dot *= vlight->lightSide; } else { dot *= vlight->darkSide; } dot = MINMAX_OF(-1, dot, 1); dest[CR] += dot * vlight->color[CR]; dest[CG] += dot * vlight->color[CG]; dest[CB] += dot * vlight->color[CB]; params->processedLights++; if(params->maxLights && !(params->processedLights < params->maxLights)) return false; // Stop iteration. return true; // Continue iteration. } /** * Calculate vertex lighting. */ void Mod_VertexColors(int count, dgl_color_t* out, dgl_vertex_t* normal, uint vLightListIdx, uint maxLights, float ambient[4], boolean invert, float rotateYaw, float rotatePitch) { int i, k; lightmodelvertexparams_t params; for(i = 0; i < count; ++i, out++, normal++) { if(vertexUsage && !(vertexUsage[i] & (1 << activeLod))) continue; // Begin with total darkness. params.color[CR] = params.color[CG] = params.color[CB] = 0; params.extra[CR] = params.extra[CG] = params.extra[CB] = 0; params.processedLights = 0; params.maxLights = maxLights; params.normal = normal; params.invert = invert; params.rotateYaw = rotateYaw; params.rotatePitch = rotatePitch; // Add light from each source. VL_ListIterator(vLightListIdx, ¶ms, lightModelVertex); // Check for ambient and convert to ubyte. for(k = 0; k < 3; ++k) { if(params.color[k] < ambient[k]) params.color[k] = ambient[k]; params.color[k] += params.extra[k]; params.color[k] = MINMAX_OF(0, params.color[k], 1); // This is the final color. out->rgba[k] = (byte) (255 * params.color[k]); } out->rgba[CA] = (byte) (255 * ambient[CA]); } } /** * Set all the colors in the array to bright white. */ void Mod_FullBrightVertexColors(int count, dgl_color_t *colors, float alpha) { for(; count-- > 0; colors++) { memset(colors->rgba, 255, 3); colors->rgba[3] = (byte) (255 * alpha); } } /** * Set all the colors into the array to the same values. */ void Mod_FixedVertexColors(int count, dgl_color_t *colors, float *color) { byte rgba[4]; rgba[0] = color[0] * 255; rgba[1] = color[1] * 255; rgba[2] = color[2] * 255; rgba[3] = color[3] * 255; for(; count-- > 0; colors++) memcpy(colors->rgba, rgba, 4); } /** * Calculate cylindrically mapped, shiny texture coordinates. */ void Mod_ShinyCoords(int count, dgl_texcoord_t *coords, dgl_vertex_t *normals, float normYaw, float normPitch, float shinyAng, float shinyPnt, float reactSpeed) { int i; float u, v; float rotatedNormal[3]; for(i = 0; i < count; ++i, coords++, normals++) { if(vertexUsage && !(vertexUsage[i] & (1 << activeLod))) continue; rotatedNormal[VX] = normals->xyz[VX]; rotatedNormal[VY] = normals->xyz[VY]; rotatedNormal[VZ] = normals->xyz[VZ]; // Rotate the normal vector so that it approximates the // model's orientation compared to the viewer. M_RotateVector(rotatedNormal, (shinyPnt + normYaw) * 360 * reactSpeed, (shinyAng + normPitch - .5f) * 180 * reactSpeed); u = rotatedNormal[VX] + 1; v = rotatedNormal[VZ]; coords->st[0] = u; coords->st[1] = v; } } /** * Render a submodel from the vissprite. */ static void Mod_RenderSubModel(uint number, const rendmodelparams_t* params) { modeldef_t *mf = params->mf, *mfNext = params->nextMF; submodeldef_t *smf = &mf->sub[number]; model_t *mdl = modellist[smf->model]; model_frame_t *frame = Mod_GetVisibleFrame(mf, number, params->id); model_frame_t *nextFrame = NULL; //int mainFlags = mf->flags; int subFlags = smf->flags; int numVerts; int useSkin; int i, c; float endPos, offset; float alpha, customAlpha; float delta[3], color[4]; float ambient[4]; float shininess, *shinyColor; float normYaw, normPitch, shinyAng, shinyPnt; float inter = params->inter; blendmode_t blending = mf->def->sub[number].blendMode; DGLuint skinTexture = 0, shinyTexture = 0; int zSign = (params->mirror? -1 : 1); if(mf->scale[VX] == 0 && mf->scale[VY] == 0 && mf->scale[VZ] == 0) { // Why bother? It's infinitely small... return; } // Submodel can define a custom Transparency level. customAlpha = 1 - smf->alpha / 255.0f; if(missileBlend && ((params->flags & DDMF_BRIGHTSHADOW) || (subFlags & MFF_BRIGHTSHADOW))) { alpha = .80f; blending = BM_ADD; } else if(subFlags & MFF_BRIGHTSHADOW2) { alpha = customAlpha; blending = BM_ADD; } else if(subFlags & MFF_DARKSHADOW) { alpha = customAlpha; blending = BM_DARK; } else if((params->flags & DDMF_SHADOW) || (subFlags & MFF_SHADOW2)) alpha = .2f; else if((params->flags & DDMF_ALTSHADOW) || (subFlags & MFF_SHADOW1)) alpha = .62f; else alpha = customAlpha; // More custom alpha? if(params->ambientColor[CA] >= 0) alpha *= params->ambientColor[CA]; if(alpha <= 0) return; // Fully transparent. if(alpha > 1) alpha = 1; // Extra blending modes. if(subFlags & MFF_SUBTRACT) blending = BM_SUBTRACT; if(subFlags & MFF_REVERSE_SUBTRACT) blending = BM_REVERSE_SUBTRACT; useSkin = smf->skin; // Selskin overrides the skin range. if(subFlags & MFF_SELSKIN) { i = (params->selector >> DDMOBJ_SELECTOR_SHIFT) & mf->def->sub[number].selSkinBits[0]; // Selskin mask c = mf->def->sub[number].selSkinBits[1]; // Selskin shift if(c > 0) i >>= c; else i <<= -c; if(i > 7) i = 7; // Maximum number of skins for selskin. if(i < 0) i = 0; // Improbable (impossible?), but doesn't hurt. useSkin = mf->def->sub[number].selSkins[i]; } // Is there a skin range for this frame? // (During model setup skintics and skinrange are set to >0.) if(smf->skinRange > 1) { // What rule to use for determining the skin? useSkin += (subFlags & MFF_IDSKIN ? params->id : SECONDS_TO_TICKS(ddMapTime) / mf->skinTics) % smf->skinRange; } // Scale interpos. Intermark becomes zero and endmark becomes one. // (Full sub-interpolation!) But only do it for the standard // interrange. If a custom one is defined, don't touch interpos. if((mf->interRange[0] == 0 && mf->interRange[1] == 1) || (subFlags & MFF_WORLD_TIME_ANIM)) { endPos = (mf->interNext ? mf->interNext->interMark : 1); inter = (params->inter - mf->interMark) / (endPos - mf->interMark); } // Do we have a sky/particle model here? if(params->alwaysInterpolate) { // Always interpolate, if there's animation. // Used with sky and particle models. nextFrame = mdl->frames + (smf->frame + 1) % mdl->info.numFrames; mfNext = mf; } else { // Check for possible interpolation. if(frameInter && mfNext && !(subFlags & MFF_DONT_INTERPOLATE)) { if(mfNext->sub[number].model == smf->model) { nextFrame = Mod_GetVisibleFrame(mfNext, number, params->id); } } } // Need translation? if(subFlags & MFF_SKINTRANS) useSkin = params->tmap; // Clamp interpolation. if(inter < 0) inter = 0; if(inter > 1) inter = 1; if(!nextFrame) { // If not interpolating, use the same frame as interpolation target. // The lerp routines will recognize this special case. nextFrame = frame; mfNext = mf; } // Setup transformation. glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Model space => World space glTranslatef(params->center[VX] + params->srvo[VX] + Mod_Lerp(mf->offset[VX], mfNext->offset[VX], inter), params->center[VZ] + params->srvo[VZ] + Mod_Lerp(mf->offset[VY], mfNext->offset[VY], inter), params->center[VY] + params->srvo[VY] + zSign * Mod_Lerp(mf->offset[VZ], mfNext->offset[VZ], inter)); if(params->extraYawAngle || params->extraPitchAngle) { // Sky models have an extra rotation. glScalef(1, 200 / 240.0f, 1); glRotatef(params->extraYawAngle, 1, 0, 0); glRotatef(params->extraPitchAngle, 0, 0, 1); glScalef(1, 240 / 200.0f, 1); } // Model rotation. glRotatef(params->viewAlign ? params->yawAngleOffset : params->yaw, 0, 1, 0); glRotatef(params->viewAlign ? params->pitchAngleOffset : params->pitch, 0, 0, 1); // Scaling and model space offset. glScalef(Mod_Lerp(mf->scale[VX], mfNext->scale[VX], inter), Mod_Lerp(mf->scale[VY], mfNext->scale[VY], inter), Mod_Lerp(mf->scale[VZ], mfNext->scale[VZ], inter)); if(params->extraScale) { // Particle models have an extra scale. glScalef(params->extraScale, params->extraScale, params->extraScale); } glTranslatef(smf->offset[VX], smf->offset[VY], smf->offset[VZ]); // Now we can draw. numVerts = mdl->info.numVertices; // Determine the suitable LOD. if(mdl->info.numLODs > 1 && rend_model_lod != 0) { float lodFactor; lodFactor = rend_model_lod * theWindow->width / 640.0f / (fieldOfView / 90.0f); if(lodFactor) lodFactor = 1 / lodFactor; // Determine the LOD we will be using. activeLod = (int) (lodFactor * params->distance); if(activeLod < 0) activeLod = 0; if(activeLod >= mdl->info.numLODs) activeLod = mdl->info.numLODs - 1; vertexUsage = mdl->vertexUsage; } else { activeLod = 0; vertexUsage = NULL; } // Interpolate vertices and normals. Mod_LerpVertices(inter, numVerts, frame->vertices, nextFrame->vertices, modelVertices); Mod_LerpVertices(inter, numVerts, frame->normals, nextFrame->normals, modelNormals); if(zSign < 0) { Mod_MirrorVertices(numVerts, modelVertices, VZ); Mod_MirrorVertices(numVerts, modelNormals, VY); } // Coordinates to the center of the model (game coords). modelCenter[VX] = params->center[VX] + params->srvo[VX] + mf->offset[VX]; modelCenter[VY] = params->center[VY] + params->srvo[VY] + mf->offset[VZ]; modelCenter[VZ] = ((params->center[VZ] + params->gzt) * 2) + params->srvo[VZ] + mf->offset[VY]; // Calculate lighting. if((subFlags & MFF_FULLBRIGHT) && !(subFlags & MFF_DIM)) { // Submodel-specific lighting override. ambient[CR] = ambient[CG] = ambient[CB] = ambient[CA] = 1; Mod_FullBrightVertexColors(numVerts, modelColors, alpha); } else if(!params->vLightListIdx) { // Lit uniformly. ambient[CR] = params->ambientColor[CR]; ambient[CG] = params->ambientColor[CG]; ambient[CB] = params->ambientColor[CB]; ambient[CA] = alpha; Mod_FixedVertexColors(numVerts, modelColors, ambient); } else { // Lit normally. ambient[CR] = params->ambientColor[CR]; ambient[CG] = params->ambientColor[CG]; ambient[CB] = params->ambientColor[CB]; ambient[CA] = alpha; Mod_VertexColors(numVerts, modelColors, modelNormals, params->vLightListIdx, modelLight + 1, ambient, mf->scale[VY] < 0? true: false, -params->yaw, -params->pitch); } // Calculate shiny coordinates. shininess = mf->def->sub[number].shiny * modelShinyFactor; if(shininess < 0) shininess = 0; if(shininess > 1) shininess = 1; if(shininess > 0) { const skinname_t* sn; shinyColor = mf->def->sub[number].shinyColor; // With psprites, add the view angle/pitch. offset = params->shineYawOffset; // Calculate normalized (0,1) model yaw and pitch. normYaw = M_CycleIntoRange(((params->viewAlign ? params->yawAngleOffset : params->yaw) + offset) / 360, 1); offset = params->shinePitchOffset; normPitch = M_CycleIntoRange(((params->viewAlign ? params->pitchAngleOffset : params->pitch) + offset) / 360, 1); if(params->shinepspriteCoordSpace) { // This is a hack to accommodate the psprite coordinate space. shinyAng = 0; shinyPnt = 0.5; } else { delta[VX] = modelCenter[VX] - vx; delta[VY] = modelCenter[VY] - vz; delta[VZ] = modelCenter[VZ] - vy; if(params->shineTranslateWithViewerPos) { delta[VX] += vx; delta[VY] += vz; delta[VZ] += vy; } shinyAng = QATAN2(delta[VZ], M_ApproxDistancef(delta[VX], delta[VY])) / PI + 0.5f; // shinyAng is [0,1] shinyPnt = QATAN2(delta[VY], delta[VX]) / (2 * PI); } Mod_ShinyCoords(numVerts, modelTexCoords, modelNormals, normYaw, normPitch, shinyAng, shinyPnt, mf->def->sub[number].shinyReact); // Shiny color. if(subFlags & MFF_SHINY_LIT) { for(c = 0; c < 3; ++c) color[c] = ambient[c] * shinyColor[c]; } else { for(c = 0; c < 3; ++c) color[c] = shinyColor[c]; } color[3] = shininess; // Ensure we've prepared the shiny skin. shinyTexture = 0; if((sn = R_GetSkinNameByIndex(mf->sub[number].shinySkin))) { const gltexture_inst_t* texInst; if((texInst = GL_PrepareGLTexture(sn->id, NULL, NULL))) shinyTexture = texInst->id; } } if(renderTextures == 2) { // For lighting debug, render all surfaces using the gray texture. material_t* mat = P_GetMaterial(DDT_GRAY, MN_SYSTEM); if(mat) { material_snapshot_t ms; Material_Prepare(&ms, mat, true, NULL); skinTexture = ms.units[MTU_PRIMARY].texInst->id; } else { skinTexture = 0; } } else { const skinname_t* sn; if(useSkin < 0 || useSkin >= mdl->info.numSkins) useSkin = 0; skinTexture = 0; if((sn = R_GetSkinNameByIndex(mdl->skins[useSkin].id))) { const gltexture_inst_t* texInst; material_load_params_t params; memset(¶ms, 0, sizeof(params)); params.flags = (!mdl->allowTexComp? MLF_TEX_NO_COMPRESSION : 0); if((texInst = GL_PrepareGLTexture(sn->id, ¶ms, NULL))) skinTexture = texInst->id; } } // If we mirror the model, triangles have a different orientation. if(zSign < 0) { glFrontFace(GL_CCW); } // Twosided models won't use backface culling. if(subFlags & MFF_TWO_SIDED) glDisable(GL_CULL_FACE); // Render using multiple passes? if(!modelShinyMultitex || shininess <= 0 || alpha < 1 || blending != BM_NORMAL || !(subFlags & MFF_SHINY_SPECULAR) || numTexUnits < 2 || !envModAdd) { // The first pass can be skipped if it won't be visible. if(shininess < 1 || subFlags & MFF_SHINY_SPECULAR) { GL_SelectTexUnits(1); GL_BlendMode(blending); GL_BindTexture(renderTextures? skinTexture : 0, glmode[texMagMode]); Mod_RenderCommands(RC_COMMAND_COORDS, mdl->lods[activeLod].glCommands, /*numVerts,*/ modelVertices, modelColors, NULL); } if(shininess > 0) { glDepthFunc(GL_LEQUAL); // Set blending mode, two choices: reflected and specular. if(subFlags & MFF_SHINY_SPECULAR) GL_BlendMode(BM_ADD); else GL_BlendMode(BM_NORMAL); // Shiny color. Mod_FixedVertexColors(numVerts, modelColors, color); if(numTexUnits > 1 && modelShinyMultitex) { // We'll use multitexturing to clear out empty spots in // the primary texture. GL_SelectTexUnits(2); GL_ModulateTexture(11); GL_ActiveTexture(GL_TEXTURE1); GL_BindTexture(renderTextures ? shinyTexture : 0, glmode[texMagMode]); GL_ActiveTexture(GL_TEXTURE0); GL_BindTexture(renderTextures ? skinTexture : 0, glmode[texMagMode]); Mod_RenderCommands(RC_BOTH_COORDS, mdl->lods[activeLod].glCommands, /*numVerts,*/ modelVertices, modelColors, modelTexCoords); GL_SelectTexUnits(1); GL_ModulateTexture(1); } else { // Empty spots will get shine, too. GL_SelectTexUnits(1); GL_BindTexture(renderTextures ? shinyTexture : 0, glmode[texMagMode]); Mod_RenderCommands(RC_OTHER_COORDS, mdl->lods[activeLod].glCommands, /*numVerts,*/ modelVertices, modelColors, modelTexCoords); } } } else { // A special case: specular shininess on an opaque object. // Multitextured shininess with the normal blending. GL_BlendMode(blending); GL_SelectTexUnits(2); // Tex1*Color + Tex2RGB*ConstRGB GL_ModulateTexture(10); GL_ActiveTexture(GL_TEXTURE1); GL_BindTexture(renderTextures ? shinyTexture : 0, glmode[texMagMode]); // Multiply by shininess. for(c = 0; c < 3; ++c) color[c] *= color[3]; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); GL_ActiveTexture(GL_TEXTURE0); GL_BindTexture(renderTextures ? skinTexture : 0, glmode[texMagMode]); Mod_RenderCommands(RC_BOTH_COORDS, mdl->lods[activeLod].glCommands, /*numVerts,*/ modelVertices, modelColors, modelTexCoords); GL_SelectTexUnits(1); GL_ModulateTexture(1); } // We're done! glMatrixMode(GL_MODELVIEW); glPopMatrix(); // Normally culling is always enabled. if(subFlags & MFF_TWO_SIDED) glEnable(GL_CULL_FACE); if(zSign < 0) { glFrontFace(GL_CW); } glDepthFunc(GL_LESS); GL_BlendMode(BM_NORMAL); } /** * Render all the submodels of a model. */ void Rend_RenderModel(const rendmodelparams_t *params) { int i; if(!params || !params->mf) return; // Render all the submodels of this model. for(i = 0; i < MAX_FRAME_MODELS; ++i) { if(params->mf->sub[i].model) { boolean disableZ = (params->mf->flags & MFF_DISABLE_Z_WRITE || params->mf->sub[i].flags & MFF_DISABLE_Z_WRITE); if(disableZ) glDepthMask(GL_FALSE); // Render the submodel. Mod_RenderSubModel(i, params); if(disableZ) glDepthMask(GL_TRUE); } } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dam_blockmap.c0000644000175000017500000003610311357170241023510 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dam_blockmap.c: BlockMap generation. * * Generate valid blockmap data from the already loaded map data. * Adapted from algorithm used in prBoom 2.2.6 -DJS * * Algorithm is order of nlines*(ncols+nrows) not nlines*ncols*nrows */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_misc.h" #include "de_play.h" #include "p_mapdata.h" #include #include #include // MACROS ------------------------------------------------------------------ #define BLKSHIFT 7 // places to shift rel position for cell num #define BLKMASK ((1<line = line; l->next = lists[blockno]; lists[blockno] = l; count[blockno]++; done[blockno] = 1; } /** * Construct a blockmap from the map data. * * This finds the intersection of each linedef with the column and row * lines at the left and bottom of each blockmap cell. It then adds the * line to all block lists touching the intersection. */ blockmap_t* DAM_BuildBlockMap(vertex_t*** vertexes, uint* numVertexes, linedef_t** lineDefs, uint* numLineDefs) { uint startTime = Sys_GetRealTime(); uint i; int j; uint bMapWidth, bMapHeight; // Blockmap dimensions. vec2_t blockSize; // Size of the blocks. uint* blockcount = NULL; // Array of counters of line lists. uint* blockdone = NULL; // Array keeping track of blocks/line. uint numBlocks; // Number of cells = nrows*ncols. linelist_t** blocklists = NULL; // Array of pointers to lists of lines. vec2_t bounds[2], point, dims; vertex_t* vtx; blockmap_t* blockmap; // Scan for map limits, which the blockmap must enclose. for(i = 0; i < *numVertexes; ++i) { vtx = (*vertexes)[i]; V2_Set(point, vtx->V_pos[VX], vtx->V_pos[VY]); if(!i) V2_InitBox(bounds, point); else V2_AddToBox(bounds, point); } // Setup the blockmap area to enclose the whole map, plus a margin // (margin is needed for a map that fits entirely inside one blockmap // cell). V2_Set(bounds[0], bounds[0][VX] - BLKMARGIN, bounds[0][VY] - BLKMARGIN); V2_Set(bounds[1], bounds[1][VX] + BLKMARGIN, bounds[1][VY] + BLKMARGIN); // Select a good size for the blocks. V2_Set(blockSize, MAPBLOCKUNITS, MAPBLOCKUNITS); V2_Subtract(dims, bounds[1], bounds[0]); // Calculate the dimensions of the blockmap. if(dims[VX] <= blockSize[VX]) bMapWidth = 1; else bMapWidth = ceil(dims[VX] / blockSize[VX]); if(dims[VY] <= blockSize[VY]) bMapHeight = 1; else bMapHeight = ceil(dims[VY] / blockSize[VY]); numBlocks = bMapWidth * bMapHeight; // Adjust the max bound so we have whole blocks. V2_Set(bounds[1], bounds[0][VX] + bMapWidth * blockSize[VX], bounds[0][VY] + bMapHeight * blockSize[VY]); // Create the array of pointers on NBlocks to blocklists, create an array // of linelist counts on NBlocks, then finally, make an array in which we // can mark blocks done per line. blocklists = M_Calloc(numBlocks * sizeof(linelist_t*)); blockcount = M_Calloc(numBlocks * sizeof(uint)); blockdone = M_Malloc(numBlocks * sizeof(uint)); // For each linedef in the wad, determine all blockmap blocks it touches // and add the linedef number to the blocklists for those blocks. { int xorg = (int) bounds[0][VX]; int yorg = (int) bounds[0][VY]; int v1[2], v2[2]; int dx, dy; int vert, horiz; boolean slopePos, slopeNeg; int bx, by; int minx, maxx, miny, maxy; for(i = 0; i < *numLineDefs; ++i) { linedef_t* line = &(*lineDefs)[i]; if(line->inFlags & LF_POLYOBJ) continue; // Polyobj lines don't get into the blockmap. v1[VX] = (int) line->L_v1pos[VX]; v1[VY] = (int) line->L_v1pos[VY]; v2[VX] = (int) line->L_v2pos[VX]; v2[VY] = (int) line->L_v2pos[VY]; dx = v2[VX] - v1[VX]; dy = v2[VY] - v1[VY]; vert = !dx; horiz = !dy; slopePos = (dx ^ dy) > 0; slopeNeg = (dx ^ dy) < 0; // Extremal lines[i] coords. minx = (v1[VX] > v2[VX]? v2[VX] : v1[VX]); maxx = (v1[VX] > v2[VX]? v1[VX] : v2[VX]); miny = (v1[VY] > v2[VY]? v2[VY] : v1[VY]); maxy = (v1[VY] > v2[VY]? v1[VY] : v2[VY]); // No blocks done for this linedef yet. memset(blockdone, 0, numBlocks * sizeof(uint)); // The line always belongs to the blocks containing its endpoints bx = (v1[VX] - xorg) >> BLKSHIFT; by = (v1[VY] - yorg) >> BLKSHIFT; addBlockLine(blocklists, blockcount, blockdone, by * bMapWidth + bx, line); bx = (v2[VX] - xorg) >> BLKSHIFT; by = (v2[VY] - yorg) >> BLKSHIFT; addBlockLine(blocklists, blockcount, blockdone, by * bMapWidth + bx, line); // For each column, see where the line along its left edge, which // it contains, intersects the Linedef i. Add i to each corresponding // blocklist. // We don't want to interesect vertical lines with columns. if(!vert) { for(j = 0; j < (signed) bMapWidth; ++j) { // intersection of Linedef with x=xorg+(j<> BLKSHIFT; // block row number int yp = (y - yorg) & BLKMASK; // y position within block // Already outside the blockmap? if(yb < 0 || yb > (signed) (bMapHeight) + 1) continue; // Does the line touch this column at all? if(x < minx || x > maxx) continue; // The cell that contains the intersection point is always added addBlockLine(blocklists, blockcount, blockdone, bMapWidth * yb + j, line); // If the intersection is at a corner it depends on the slope // (and whether the line extends past the intersection) which // blocks are hit. // Where does the intersection occur? if(yp == 0) { // Intersection occured at a corner if(slopeNeg) // \ - blocks x,y-, x-,y { if(yb > 0 && miny < y) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * (yb - 1) + j, line); if(j > 0 && minx < x) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * yb + j - 1, line); } else if(slopePos) // / - block x-,y- { if(yb > 0 && j > 0 && minx < x) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * (yb - 1) + j - 1, line); } else if(horiz) // - - block x-,y { if(j > 0 && minx < x) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * yb + j - 1, line); } } else if(j > 0 && minx < x) { // Else not at corner: x-,y addBlockLine(blocklists, blockcount, blockdone, bMapWidth * yb + j - 1, line); } } } // For each row, see where the line along its bottom edge, which // it contains, intersects the Linedef i. Add i to all the corresponding // blocklists. if(!horiz) { for(j = 0; j < (signed) bMapHeight; ++j) { // intersection of Linedef with y=yorg+(j<> BLKSHIFT; // block column number int xp = (x - xorg) & BLKMASK; // x position within block // Outside the blockmap? if(xb < 0 || xb > (signed) (bMapWidth) + 1) continue; // Touches this row? if(y < miny || y > maxy) continue; // The cell that contains the intersection point is always added addBlockLine(blocklists, blockcount, blockdone, bMapWidth * j + xb, line); // If the intersection is at a corner it depends on the slope // (and whether the line extends past the intersection) which // blocks are hit // Where does the intersection occur? if(xp == 0) { // Intersection occured at a corner if(slopeNeg) // \ - blocks x,y-, x-,y { if(j > 0 && miny < y) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * (j - 1) + xb, line); if(xb > 0 && minx < x) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * j + xb - 1, line); } else if(vert) // | - block x,y- { if(j > 0 && miny < y) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * (j - 1) + xb, line); } else if(slopePos) // / - block x-,y- { if(xb > 0 && j > 0 && miny < y) addBlockLine(blocklists, blockcount, blockdone, bMapWidth * (j - 1) + xb -1, line); } } else if(j > 0 && miny < y) { // Else not on a corner: x, y- addBlockLine(blocklists, blockcount, blockdone, bMapWidth * (j - 1) + xb, line); } } } } } // Create the blockmap. blockmap = P_BlockmapCreate(bounds[0], bounds[1], bMapWidth, bMapHeight); // Create the actual links by 'hardening' the lists into arrays. { uint x, y; for(y = 0; y < bMapHeight; ++y) for(x = 0; x < bMapWidth; ++x) { uint count = blockcount[y * bMapWidth + x]; linelist_t* bl = blocklists[y * bMapWidth + x]; if(count > 0) { linedef_t** lines, **ptr; // A NULL-terminated array of pointers to lines. lines = Z_Malloc((count + 1) * sizeof(linedef_t *), PU_MAPSTATIC, NULL); // Copy pointers to the array, delete the nodes. ptr = lines; while(bl) { linelist_t *tmp = bl->next; *ptr++ = (linedef_t *) bl->line; M_Free(bl); bl = tmp; } // Terminate. *ptr = NULL; // Link it into the BlockMap. P_BlockmapSetBlock(blockmap, x, y, lines, NULL, NULL); } } } // free all temporary storage M_Free(blocklists); M_Free(blockcount); M_Free(blockdone); // How much time did we spend? VERBOSE(Con_Message ("DAM_BuildBlockMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); return blockmap; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_font.c0000644000175000017500000005453111357170242022535 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_font.c: Font Renderer * * The font must be small enough to fit in one texture * (not a problem with *real* video cards! ;-)). */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #ifndef WIN32 # define SYSTEM_FONT 1 # define SYSTEM_FIXED_FONT 2 #endif // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void* readFormat0(DFILE* file, jfrfont_t* font); static void* readFormat2(DFILE* file, jfrfont_t* font); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int initFROk = 0; static int numFonts = 0; static jfrfont_t* fonts = NULL; // The list of fonts. static int currentFontIndex; // Index of the current font. static filename_t fontpath = ""; // CODE -------------------------------------------------------------------- static int getFontByName(const char* name) { int i; size_t len = strlen(name); for(i = 0; i < numFonts; ++i) { const jfrfont_t* font = &fonts[i]; if(!strnicmp(font->name, name, len)) return i; } return -1; } static int getFontById(int id) { int i; for(i = 0; i < numFonts; ++i) { const jfrfont_t* font = &fonts[i]; if(font->id == id) return i; } return -1; } /** * Destroys the font with the index. */ static void destroyFontIdx(int idx) { jfrfont_t* font = &fonts[idx]; glDeleteTextures(1, (const GLuint*) &font->tex); memmove(&fonts[idx], &fonts[idx + 1], sizeof(jfrfont_t) * (numFonts - idx - 1)); numFonts--; fonts = M_Realloc(fonts, sizeof(jfrfont_t) * numFonts); if(currentFontIndex == idx) currentFontIndex = -1; } static int getNewId(void) { int i, max = 0; for(i = 0; i < numFonts; ++i) { jfrfont_t* font = &fonts[i]; if(font->id > max) max = font->id; } return max + 1; } /** * @return @c 0, iff there are no errors. */ int FR_Init(void) { if(initFROk) return -1; // No reinitializations... numFonts = 0; fonts = 0; // No fonts! currentFontIndex = -1; initFROk = 1; // Check the font path. if(ArgCheckWith("-fontdir", 1)) { M_TranslatePath(fontpath, ArgNext(), FILENAME_T_MAXLEN); Dir_ValidDir(fontpath, FILENAME_T_MAXLEN); M_CheckPath(fontpath); } else { strncpy(fontpath, ddBasePath, FILENAME_T_MAXLEN); strncat(fontpath, "data\\fonts\\", FILENAME_T_MAXLEN); } return 0; } void FR_Shutdown(void) { // Destroy all fonts. while(numFonts) destroyFontIdx(0); fonts = 0; currentFontIndex = -1; initFROk = 0; } int FR_GetFontIdx(int id) { int idx; if((idx = getFontById(id)) == -1) Con_Printf("FR_GetFontIdx: Unknown ID %i.\n", id); return idx; } void FR_DestroyFont(int id) { int idx; if((idx = getFontById(id)) != -1) { destroyFontIdx(idx); if(currentFontIndex == idx) currentFontIndex = -1; } } jfrfont_t* FR_GetFont(int id) { int idx = getFontById(id); if(idx == -1) return 0; return fonts + idx; } #ifdef WIN32 static void outByte(FILE* f, byte b) { fwrite(&b, sizeof(b), 1, f); } static void outShort(FILE* f, short s) { fwrite(&s, sizeof(s), 1, f); } static int dumpFont(const char* filename, const jfrchar_t chars[256], const uint32_t* image, int w, int h) { FILE* file = fopen(filename, "wb"); int i, c, bit, numPels; byte mask; if(!file) return false; // Write header. outByte(file, 0); // Version. outShort(file, w); outShort(file, h); outShort(file, MAX_CHARS); // Number of characters. // Characters. for(i = 0; i < MAX_CHARS; ++i) { outShort(file, chars[i].x); outShort(file, chars[i].y); outByte(file, chars[i].w); outByte(file, chars[i].h); } // Write a zero to indicate the data is in bitmap format (0,1). outByte(file, 0); numPels = w * h; for(c = i = 0; i < (numPels + 7) / 8; ++i) { for(mask = 0, bit = 7; bit >= 0; bit--, ++c) mask |= (c < numPels ? image[c] != 0 : false) << bit; outByte(file, mask); } fclose(file); return true; } #endif static int createFont(void) { jfrfont_t* font; currentFontIndex = numFonts; fonts = M_Realloc(fonts, sizeof(jfrfont_t) * ++numFonts); font = &fonts[currentFontIndex]; memset(font, 0, sizeof(jfrfont_t)); font->id = getNewId(); return currentFontIndex; } static byte inByte(DFILE* f) { byte b; F_Read(&b, sizeof(b), f); return b; } static unsigned short inShort(DFILE* f) { unsigned short s; F_Read(&s, sizeof(s), f); return USHORT(s); } /** * Prepares a font from a file. If the given file is not found, prepares * the corresponding GDI font. */ int FR_PrepareFont(const char* name) { #ifdef WIN32 struct { char* name; int gdires; char winfontname[32]; // Limit including terminator. int pointsize; } fontmapper[] = { {"Fixed", SYSTEM_FIXED_FONT}, {"Fixed12", 0, "Fixedsys", 12}, {"System", SYSTEM_FONT}, {"System12", 0, "System", 12}, {"Large", 0, "MS Sans Serif", 18}, {"Small7", 0, "Small Fonts", 7}, {"Small8", 0, "Small Fonts", 8}, {"Small10", 0, "Small Fonts", 10}, {NULL, 0} }; #endif filename_t buf; DFILE* file; int idx, version; jfrfont_t* font; void* image; // Is this a font we've already prepared? if((idx = getFontByName(name)) != -1) { /*font = &fonts[idx]; if(font->tex)*/ return true; } strcpy(buf, fontpath); strcat(buf, name); strcat(buf, ".dfn"); if(ArgCheck("-gdifonts") || (file = F_Open(buf, "rb")) == NULL) { boolean retVal = false; #ifdef WIN32 HWND hWnd = Sys_GetWindowHandle(windowIDX); HDC hDC = NULL; int i; if(hWnd) hDC = GetDC(hWnd); // No luck... for(i = 0; fontmapper[i].name; ++i) { if(!stricmp(fontmapper[i].name, name)) { if(verbose) { Con_Printf("FR_PrepareFont: GDI font for \"%s\".\n", fontmapper[i].name); } if(hWnd && hDC && fontmapper[i].winfontname) { HFONT uifont = CreateFont(-MulDiv(fontmapper[i].pointsize, GetDeviceCaps(hDC, LOGPIXELSY), 72), 0, 0, 0, 0, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, VARIABLE_PITCH | FF_SWISS, (LPCTSTR) fontmapper[i].winfontname); FR_PrepareGDIFont(uifont); DeleteObject(uifont); } else { FR_PrepareGDIFont(GetStockObject(fontmapper[i].gdires)); } strcpy(fonts[currentFontIndex].name, name); retVal = true; break; } } if(hWnd && hDC) ReleaseDC(hWnd, hDC); #endif // The font was not found. return retVal; } VERBOSE2(Con_Printf("FR_PrepareFont: %s\n", M_PrettyPath(buf))); version = inByte(file); VERBOSE2(Con_Printf("FR_PrepareFont: Version %i.\n", version)); // Load the font from the file. createFont(); font = &fonts[currentFontIndex]; strncpy(font->name, name, 255); font->name[255] = '\0'; VERBOSE(Con_Printf("FR_PrepareFont: New font %i: %s.\n", currentFontIndex, font->name)); // Font glyph map. image = 0; switch(version) { case 0: // Original format. image = readFormat0(file, font); break; case 2: // Enhanced format. image = readFormat2(file, font); break; default: Con_Error("FR_PrepareFont: Format is unsupported.\n"); break; } if(image) { VERBOSE2(Con_Printf("FR_PrepareFont: Creating GL texture.\n")); // Load in the texture. font->tex = GL_NewTextureWithParams2(DGL_RGBA, font->texWidth, font->texHeight, image, 0, GL_LINEAR, GL_NEAREST, -1 /*best anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); M_Free(image); image = 0; F_Close(file); } VERBOSE2(Con_Printf("FR_PrepareFont: Loaded %s.\n", name)); return true; } static void* readFormat0(DFILE* file, jfrfont_t* font) { int i, c, numChars = 0, format, numPels; uint32_t* image; font->hasEmbeddedShadow = false; font->marginWidth = font->marginHeight = 0; // Load in the data. font->texWidth = inShort(file); font->texHeight = inShort(file); numChars = inShort(file); VERBOSE2(Con_Printf("readFormat0: Dimensions %i x %i, with %i chars.\n", font->texWidth, font->texHeight, numChars)); for(i = 0; i < numChars; ++i) { jfrchar_t* ch = &font->chars[i < MAX_CHARS ? i : MAX_CHARS - 1]; ch->x = inShort(file); ch->y = inShort(file); ch->w = inByte(file); ch->h = inByte(file); } // The bitmap. format = inByte(file); if(format > 0) { Con_Error("readFormat0: Font %s uses unknown bitmap format %i.\n", font->name, format); } numPels = font->texWidth * font->texHeight; image = M_Calloc(numPels * sizeof(int)); for(c = i = 0; i < (numPels + 7) / 8; ++i) { int bit, mask = inByte(file); for(bit = 7; bit >= 0; bit--, ++c) { if(c >= numPels) break; if(mask & (1 << bit)) image[c] = ~0; } } return image; } static void* readFormat2(DFILE* file, jfrfont_t* font) { int i, numPels, dataHeight, glyphCount = 0; byte bitmapFormat = 0; uint32_t* image, *ptr; bitmapFormat = inByte(file); if(bitmapFormat != 1 && bitmapFormat != 0) // Luminance + Alpha. { Con_Error("FR_ReadFormat1: Bitmap format %i not implemented.\n", bitmapFormat); } font->hasEmbeddedShadow = true; // Load in the data. font->texWidth = inShort(file); dataHeight = inShort(file); font->texHeight = M_CeilPow2(dataHeight); glyphCount = inShort(file); font->marginWidth = font->marginHeight = inShort(file); font->lineHeight = inShort(file); font->glyphHeight = inShort(file); font->ascent = inShort(file); font->descent = inShort(file); for(i = 0; i < glyphCount; ++i) { ushort code = inShort(file); ushort x = inShort(file); ushort y = inShort(file); ushort w = inShort(file); ushort h = inShort(file); if(code < MAX_CHARS) { font->chars[code].x = x; font->chars[code].y = y; font->chars[code].w = w; font->chars[code].h = h; } } // Read the bitmap. numPels = font->texWidth * font->texHeight; image = ptr = M_Calloc(numPels * 4); if(bitmapFormat == 0) { for(i = 0; i < numPels; ++i) { byte red = inByte(file); byte green = inByte(file); byte blue = inByte(file); byte alpha = inByte(file); *ptr++ = ULONG(red | (green << 8) | (blue << 16) | (alpha << 24)); } } else if(bitmapFormat == 1) { for(i = 0; i < numPels; ++i) { byte luminance = inByte(file); byte alpha = inByte(file); *ptr++ = ULONG(luminance | (luminance << 8) | (luminance << 16) | (alpha << 24)); } } return image; } /** * Prepare a GDI font. Select it as the current font. */ #ifdef WIN32 int FR_PrepareGDIFont(HFONT hfont) { RECT rect; jfrfont_t* font; int i, x, y, maxh, bmpWidth = 256, bmpHeight = 0, imgWidth, imgHeight; HDC hdc; HBITMAP hbmp; uint32_t* image; // Create a new font. createFont(); font = &fonts[currentFontIndex]; // Now we'll create the actual data. hdc = CreateCompatibleDC(NULL); SetMapMode(hdc, MM_TEXT); SelectObject(hdc, hfont); // Let's first find out the sizes of all the characters. // Then we can decide how large a texture we need. for(i = 0, x = 0, y = 0, maxh = 0; i < 256; ++i) { jfrchar_t* fc = font->chars + i; SIZE size; byte ch[2]; ch[0] = i; ch[1] = 0; GetTextExtentPoint32(hdc, (LPCTSTR) ch, 1, &size); fc->w = size.cx; fc->h = size.cy; maxh = max(maxh, fc->h); x += fc->w + 1; if(x >= bmpWidth) { x = 0; y += maxh + 1; maxh = 0; } } bmpHeight = y + maxh; hbmp = CreateCompatibleBitmap(hdc, bmpWidth, bmpHeight); SelectObject(hdc, hbmp); SetBkMode(hdc, OPAQUE); SetBkColor(hdc, 0); SetTextColor(hdc, 0xffffff); rect.left = 0; rect.top = 0; rect.right = bmpWidth; rect.bottom = bmpHeight; FillRect(hdc, &rect, GetStockObject(BLACK_BRUSH)); // Print all the characters. for(i = 0, x = 0, y = 0, maxh = 0; i < 256; ++i) { jfrchar_t* fc = font->chars + i; char ch[2]; ch[0] = i; ch[1] = '\0'; if(x + fc->w + 1 >= bmpWidth) { x = 0; y += maxh + 1; maxh = 0; } if(i) TextOut(hdc, x + 1, y + 1, ch, 1); fc->x = x + 1; fc->y = y + 1; maxh = max(maxh, fc->h); x += fc->w + 1; } // Now we can make a version that DGL can read. imgWidth = M_CeilPow2(bmpWidth); imgHeight = M_CeilPow2(bmpHeight); /* #if _DEBUG Con_Printf( "font: %d x %d\n", imgWidth, imgHeight); #endif */ image = M_Malloc(4 * imgWidth * imgHeight); memset(image, 0, 4 * imgWidth * imgHeight); for(y = 0; y < bmpHeight; ++y) for(x = 0; x < bmpWidth; ++x) if(GetPixel(hdc, x, y)) { image[x + y * imgWidth] = 0xffffffff; /*if(x+1 < imgWidth && y+1 < imgHeight) image[x+1 + (y+1)*imgWidth] = 0xff000000; */ } font->texWidth = imgWidth; font->texHeight = imgHeight; // If necessary, write the font data to a file. if(ArgCheck("-dumpfont")) { char buf[20]; sprintf(buf, "font%i.dfn", font->id); dumpFont(buf, font->chars, image, font->texWidth, font->texHeight); } // Create the DGL texture. font->tex = GL_NewTextureWithParams2(DGL_RGBA, imgWidth, imgHeight, image, 0, GL_NEAREST, GL_NEAREST, -1 /*best anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE); // We no longer need these. M_Free(image); DeleteObject(hbmp); DeleteDC(hdc); return 0; } #endif // WIN32 /** * Change the current font. */ void FR_SetFont(int id) { int idx = -1; idx = FR_GetFontIdx(id); if(idx == -1) return; // No such font. currentFontIndex = idx; } int FR_CharWidth(int ch) { jfrfont_t* cf; if(currentFontIndex == -1) return 0; cf = &fonts[currentFontIndex]; return cf->chars[ch].w - cf->marginWidth * 2; } int FR_TextWidth(const char* text) { size_t i, len; int width = 0; jfrfont_t* cf; if(currentFontIndex == -1 || !text) return 0; // Just add them together. len = strlen(text); cf = &fonts[currentFontIndex]; for(i = 0; i < len; ++i) width += cf->chars[(byte) text[i]].w - 2 * cf->marginWidth; return width; } int FR_TextHeight(const char* text) { size_t i, len; int height = 0; jfrfont_t* cf; if(currentFontIndex == -1 || !text) return 0; // Find the greatest height. len = strlen(text); cf = &fonts[currentFontIndex]; for(i = 0; i < len; ++i) height = MAX_OF(height, cf->chars[(byte) text[i]].h - 2 * cf->marginHeight); return height; } int FR_SingleLineHeight(const char* text) { jfrfont_t* cf; if(currentFontIndex == -1 || !text) return 0; cf = &fonts[currentFontIndex]; if(cf->ascent) { return cf->ascent; } return cf->chars[(byte)text[0]].h - 2 * cf->marginHeight; } int FR_GlyphTopToAscent(const char* text) { jfrfont_t* cf; if(currentFontIndex == -1 || !text) return 0; cf = &fonts[currentFontIndex]; if(!cf->lineHeight) return 0; return cf->lineHeight - cf->ascent; } int FR_GetCurrent(void) { if(currentFontIndex == -1) return 0; return fonts[currentFontIndex].id; } /** * (x,y) is the upper left corner. Returns the length. */ int FR_CustomShadowTextOut(const char* text, int x, int y, int shadowX, int shadowY, float shadowAlpha) { int width = 0, step; size_t i, len; jfrfont_t* cf; float origColor[4]; boolean drawShadow = (shadowX || shadowY); if(!text) return 0; len = strlen(text); // Check the font. if(currentFontIndex == -1) return 0; // No selected font. cf = &fonts[currentFontIndex]; if(cf->hasEmbeddedShadow) drawShadow = false; if(drawShadow) { // The color of the text itself. glGetFloatv(GL_CURRENT_COLOR, origColor); glColor4f(0, 0, 0, origColor[3] * shadowAlpha); } // Set the texture. glBindTexture(GL_TEXTURE_2D, cf->tex); glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glScalef(1.f / cf->texWidth, 1.f / cf->texHeight, 1.f); // Print it. glBegin(GL_QUADS); if(drawShadow) { int startX = x + shadowX, startY = y + shadowY; for(i = 0; i < len; ++i) { // First draw the shadow. const jfrchar_t* ch = &cf->chars[(byte) text[i]]; // Upper left. glTexCoord2f(ch->x, ch->y); glVertex2f(x, y); // Upper right. glTexCoord2f(ch->x + ch->w, ch->y); glVertex2f(x + ch->w, y); // Lower right. glTexCoord2f(ch->x + ch->w, ch->y + ch->h); glVertex2f(x + ch->w, y + ch->h); // Lower left. glTexCoord2f(ch->x, ch->y + ch->h); glVertex2f(x, y + ch->h); // Move on. x += ch->w; } x = startX; y = startY; } if(drawShadow) glColor4fv(origColor); x -= cf->marginWidth; y -= cf->marginHeight; for(i = 0; i < len; ++i) { const jfrchar_t* ch = &cf->chars[(byte) text[i]]; // Upper left. glTexCoord2f(ch->x, ch->y); glVertex2f(x, y); // Upper right. glTexCoord2f(ch->x + ch->w, ch->y); glVertex2f(x + ch->w, y); // Lower right. glTexCoord2f(ch->x + ch->w, ch->y + ch->h); glVertex2f(x + ch->w, y + ch->h); // Lower left. glTexCoord2f(ch->x, ch->y + ch->h); glVertex2f(x, y + ch->h); // Move on. step = ch->w - 2*cf->marginWidth; width += step; x += step; } glEnd(); glMatrixMode(GL_TEXTURE); glPopMatrix(); return width; } int FR_TextOut(const char* text, int x, int y) { return FR_CustomShadowTextOut(text, x, y, 0, 0, 0); } int FR_ShadowTextOut(const char* text, int x, int y) { return FR_CustomShadowTextOut(text, x, y, 2, 2, .5f); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_audiod_dummy.c0000644000175000017500000001730311357170242024457 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_dummy.c: Dummy Audio Driver. * * Used in dedicated server mode, when it's necessary to simulate * sound playing but not actually play anything. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" #include "sys_audiod.h" #include "sys_audiod_sfx.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- int DS_DummyInit(void); void DS_DummyShutdown(void); void DS_DummyEvent(int type); int DS_Dummy_SFX_Init(void); sfxbuffer_t* DS_Dummy_SFX_CreateBuffer(int flags, int bits, int rate); void DS_Dummy_SFX_DestroyBuffer(sfxbuffer_t* buf); void DS_Dummy_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample); void DS_Dummy_SFX_Reset(sfxbuffer_t* buf); void DS_Dummy_SFX_Play(sfxbuffer_t* buf); void DS_Dummy_SFX_Stop(sfxbuffer_t* buf); void DS_Dummy_SFX_Refresh(sfxbuffer_t* buf); void DS_Dummy_SFX_Set(sfxbuffer_t* buf, int prop, float value); void DS_Dummy_SFX_Setv(sfxbuffer_t* buf, int prop, float* values); void DS_Dummy_SFX_Listener(int prop, float value); void DS_Dummy_SFX_Listenerv(int prop, float* values); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- audiodriver_t audiod_dummy = { DS_DummyInit, DS_DummyShutdown, DS_DummyEvent }; audiointerface_sfx_t audiod_dummy_sfx = { DS_Dummy_SFX_Init, DS_Dummy_SFX_CreateBuffer, DS_Dummy_SFX_DestroyBuffer, DS_Dummy_SFX_Load, DS_Dummy_SFX_Reset, DS_Dummy_SFX_Play, DS_Dummy_SFX_Stop, DS_Dummy_SFX_Refresh, DS_Dummy_SFX_Set, DS_Dummy_SFX_Setv, DS_Dummy_SFX_Listener, DS_Dummy_SFX_Listenerv }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean inited; // CODE -------------------------------------------------------------------- /** * Init DirectSound, start playing the primary buffer. Returns true * if successful. */ int DS_DummyInit(void) { if(inited) return true; // Already initialized. inited = true; return true; } /** * Shut everything down. */ void DS_DummyShutdown(void) { inited = false; } /** * The Event function is called to tell the driver about certain critical * events like the beginning and end of an update cycle. */ void DS_DummyEvent(int type) { // Do nothing... } int DS_Dummy_SFX_Init(void) { return inited; } sfxbuffer_t* DS_Dummy_SFX_CreateBuffer(int flags, int bits, int rate) { sfxbuffer_t* buf; // Clear the buffer. buf = Z_Calloc(sizeof(*buf), PU_STATIC, 0); buf->bytes = bits / 8; buf->rate = rate; buf->flags = flags; buf->freq = rate; // Modified by calls to Set(SFXBP_FREQUENCY). return buf; } void DS_Dummy_SFX_DestroyBuffer(sfxbuffer_t* buf) { if(!buf) return; // Free the memory allocated for the buffer. Z_Free(buf); } /** * Prepare the buffer for playing a sample by filling the buffer with as * much sample data as fits. The pointer to sample is saved, so the caller * mustn't free it while the sample is loaded. */ void DS_Dummy_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample) { if(!buf || !sample) return; // Now the buffer is ready for playing. buf->sample = sample; buf->written = sample->size; buf->flags &= ~SFXBF_RELOAD; } /** * Stops the buffer and makes it forget about its sample. */ void DS_Dummy_SFX_Reset(sfxbuffer_t* buf) { if(!buf) return; DS_Dummy_SFX_Stop(buf); buf->sample = NULL; buf->flags &= ~SFXBF_RELOAD; } /** * @return The length of the buffer in milliseconds. */ unsigned int DS_DummyBufferLength(sfxbuffer_t* buf) { if(!buf) return 0; return 1000 * buf->sample->numSamples / buf->freq; } void DS_Dummy_SFX_Play(sfxbuffer_t* buf) { // Playing is quite impossible without a sample. if(!buf || !buf->sample) return; // Do we need to reload? if(buf->flags & SFXBF_RELOAD) DS_Dummy_SFX_Load(buf, buf->sample); // The sound starts playing now? if(!(buf->flags & SFXBF_PLAYING)) { // Calculate the end time (milliseconds). buf->endTime = Sys_GetRealTime() + DS_DummyBufferLength(buf); } // The buffer is now playing. buf->flags |= SFXBF_PLAYING; } void DS_Dummy_SFX_Stop(sfxbuffer_t* buf) { if(!buf) return; // Clear the flag that tells the Sfx module about playing buffers. buf->flags &= ~SFXBF_PLAYING; // If the sound is started again, it needs to be reloaded. buf->flags |= SFXBF_RELOAD; } /** * Buffer streamer. Called by the Sfx refresh thread. */ void DS_Dummy_SFX_Refresh(sfxbuffer_t* buf) { // Can only be done if there is a sample and the buffer is playing. if(!buf || !buf->sample || !(buf->flags & SFXBF_PLAYING)) return; // Have we passed the predicted end of sample? if(!(buf->flags & SFXBF_REPEAT) && Sys_GetRealTime() >= buf->endTime) { // Time for the sound to stop. DS_Dummy_SFX_Stop(buf); } } /** * @param prop SFXBP_VOLUME (if negative, interpreted as attenuation) * SFXBP_FREQUENCY * SFXBP_PAN (-1..1) * SFXBP_MIN_DISTANCE * SFXBP_MAX_DISTANCE * SFXBP_RELATIVE_MODE */ void DS_Dummy_SFX_Set(sfxbuffer_t* buf, int prop, float value) { if(!buf) return; switch(prop) { case SFXBP_FREQUENCY: buf->freq = buf->rate * value; break; default: break; } } /** * Coordinates specified in world coordinate system, converted to DSound's: * +X to the right, +Y up and +Z away (Y and Z swapped, i.e.). * * @param property SFXBP_POSITION * SFXBP_VELOCITY */ void DS_Dummy_SFX_Setv(sfxbuffer_t* buf, int prop, float* values) { // Nothing to do. } /** * @param property SFXLP_UNITS_PER_METER * SFXLP_DOPPLER * SFXLP_UPDATE */ void DS_Dummy_SFX_Listener(int prop, float value) { // Nothing to do. } /** * Values use SRD_* for indices. */ void DS_DummyListenerEnvironment(float* rev) { // Nothing to do. } /** * Call SFXLP_UPDATE at the end of every channel update. */ void DS_Dummy_SFX_Listenerv(int prop, float* values) { // Nothing to do. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/s_environ.c0000644000175000017500000003147611357170242023112 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_environ.c: Environmental Sound Effects * * Calculation of the aural properties of sectors. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_play.h" #include "de_refresh.h" #include "de_audio.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { const char name[9]; // Material type name. int volumeMul; int decayMul; int dampingMul; } materialenvinfo_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static materialenvinfo_t matInfo[NUM_MATERIAL_ENV_CLASSES] = { {"Metal", 255, 255, 25}, {"Rock", 200, 160, 100}, {"Wood", 80, 50, 200}, {"Cloth", 5, 5, 255} }; static ownernode_t *unusedNodeList = NULL; // CODE -------------------------------------------------------------------- /** * Given a texture/flat name, look up the associated material type. * * @param name Name of the texture/flat to look up. * @param mnamespace Material namespace (MG_* e.g. MN_FLATS). * * @return If found; material type associated to the texture, * else @c MEC_UNKNOWN. */ material_env_class_t S_MaterialClassForName(const char* name, material_namespace_t mnamespace) { int i; ded_tenviron_t* env; for(i = 0, env = defs.textureEnv; i < defs.count.textureEnv.num; ++i, env++) { int j; for(j = 0; j < env->count.num; ++j) { ded_materialid_t* mid = &env->materials[j]; if(mid->mnamespace == mnamespace && !stricmp(mid->name, name)) { // A match! material_env_class_t k; // See if we recognise the material name. for(k = 0; k < NUM_MATERIAL_ENV_CLASSES; ++k) if(!stricmp(env->id, matInfo[k].name)) return k; return MEC_UNKNOWN; } } } return MEC_UNKNOWN; } static ownernode_t* newOwnerNode(void) { ownernode_t* node; if(unusedNodeList) { // An existing node is available for re-use. node = unusedNodeList; unusedNodeList = unusedNodeList->next; node->next = NULL; node->data = NULL; } else { // Need to allocate another. node = M_Malloc(sizeof(ownernode_t)); } return node; } static void setSubSecSectorOwner(ownerlist_t* ownerList, subsector_t* ssec) { ownernode_t* node; if(!ssec) return; // Add a new owner. // NOTE: No need to check for duplicates. ownerList->count++; node = newOwnerNode(); node->data = ssec; node->next = ownerList->head; ownerList->head = node; } static void findSSecsAffectingSector(gamemap_t* map, uint secIDX) { uint i; subsector_t* sub; ownernode_t* node, *p; float bbox[4]; ownerlist_t subSecOwnerList; sector_t* sec = &map->sectors[secIDX]; memset(&subSecOwnerList, 0, sizeof(subSecOwnerList)); memcpy(bbox, sec->bBox, sizeof(bbox)); bbox[BOXLEFT] -= 128; bbox[BOXRIGHT] += 128; bbox[BOXTOP] += 128; bbox[BOXBOTTOM] -= 128; /* #if _DEBUG Con_Message("sector %i: (%f,%f) - (%f,%f)\n", c, bbox[BOXLEFT], bbox[BOXTOP], bbox[BOXRIGHT], bbox[BOXBOTTOM]); #endif */ for(i = 0; i < map->numSSectors; ++i) { sub = &map->ssectors[i]; // Is this subsector close enough? if(sub->sector == sec || // subsector is IN this sector (sub->midPoint.pos[VX] > bbox[BOXLEFT] && sub->midPoint.pos[VX] < bbox[BOXRIGHT] && sub->midPoint.pos[VY] < bbox[BOXTOP] && sub->midPoint.pos[VY] > bbox[BOXBOTTOM])) { // It will contribute to the reverb settings of this sector. setSubSecSectorOwner(&subSecOwnerList, sub); } } // Now harden the list. sec->numReverbSSecAttributors = subSecOwnerList.count; if(sec->numReverbSSecAttributors) { subsector_t **ptr; sec->reverbSSecs = Z_Malloc((sec->numReverbSSecAttributors + 1) * sizeof(subsector_t*), PU_MAPSTATIC, 0); for(i = 0, ptr = sec->reverbSSecs, node = subSecOwnerList.head; i < sec->numReverbSSecAttributors; ++i, ptr++) { p = node->next; *ptr = (subsector_t*) node->data; if(i < numSectors - 1) { // Move this node to the unused list for re-use. node->next = unusedNodeList; unusedNodeList = node; } else { // No further use for the nodes. M_Free(node); } node = p; } *ptr = NULL; // terminate. } } /** * Called during map init to determine which subsectors affect the reverb * properties of all sectors. Given that subsectors do not change shape (in * two dimensions at least), they do not move and are not created/destroyed * once the map has been loaded; this step can be pre-processed. */ void S_DetermineSubSecsAffectingSectorReverb(gamemap_t* map) { uint startTime = Sys_GetRealTime(); uint i; ownernode_t* node, *p; for(i = 0; i < map->numSectors; ++i) { findSSecsAffectingSector(map, i); } // Free any nodes left in the unused list. node = unusedNodeList; while(node) { p = node->next; M_Free(node); node = p; } unusedNodeList = NULL; // How much time did we spend? VERBOSE(Con_Message ("S_DetermineSubSecsAffectingSectorReverb: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } static boolean calcSSecReverb(subsector_t* ssec) { uint i, v; seg_t** ptr; float total = 0; material_env_class_t mclass; float materials[NUM_MATERIAL_ENV_CLASSES]; if(!ssec->sector) { ssec->reverb[SRD_SPACE] = ssec->reverb[SRD_VOLUME] = ssec->reverb[SRD_DECAY] = ssec->reverb[SRD_DAMPING] = 0; return false; } memset(&materials, 0, sizeof(materials)); // Space is the rough volume of the subsector (bounding box). ssec->reverb[SRD_SPACE] = (int) (ssec->sector->SP_ceilheight - ssec->sector->SP_floorheight) * (ssec->bBox[1].pos[VX] - ssec->bBox[0].pos[VX]) * (ssec->bBox[1].pos[VY] - ssec->bBox[0].pos[VY]); // The other reverb properties can be found out by taking a look at the // materials of all surfaces in the subsector. ptr = ssec->segs; while(*ptr) { seg_t* seg = *ptr; if(seg->lineDef && SEG_SIDEDEF(seg) && SEG_SIDEDEF(seg)->SW_middlematerial) { material_t* mat = SEG_SIDEDEF(seg)->SW_middlematerial; // The material determines its type. mclass = Material_GetEnvClass(mat); total += seg->length; if(!(mclass >= 0 && mclass < NUM_MATERIAL_ENV_CLASSES)) mclass = MEC_WOOD; // Assume it's wood if unknown. materials[mclass] += seg->length; } *ptr++; } if(!total) { // Huh? ssec->reverb[SRD_VOLUME] = ssec->reverb[SRD_DECAY] = ssec->reverb[SRD_DAMPING] = 0; return false; } // Average the results. for(i = 0; i < NUM_MATERIAL_ENV_CLASSES; ++i) materials[i] /= total; // Volume. for(i = 0, v = 0; i < NUM_MATERIAL_ENV_CLASSES; ++i) v += materials[i] * matInfo[i].volumeMul; if(v > 255) v = 255; ssec->reverb[SRD_VOLUME] = v; // Decay time. for(i = 0, v = 0; i < NUM_MATERIAL_ENV_CLASSES; ++i) v += materials[i] * matInfo[i].decayMul; if(v > 255) v = 255; ssec->reverb[SRD_DECAY] = v; // High frequency damping. for(i = 0, v = 0; i < NUM_MATERIAL_ENV_CLASSES; ++i) v += materials[i] * matInfo[i].dampingMul; if(v > 255) v = 255; ssec->reverb[SRD_DAMPING] = v; /* #if _DEBUG Con_Message("ssec %04i: vol:%3i sp:%3i dec:%3i dam:%3i\n", GET_SUBSECTOR_IDX(ssec), ssec->reverb[SRD_VOLUME], ssec->reverb[SRD_SPACE], ssec->reverb[SRD_DECAY], ssec->reverb[SRD_DAMPING]); #endif */ return true; } /** * Re-calculate the reverb properties of the given sector. Should be called * whenever any of the properties governing reverb properties have changed * (i.e. seg/plane texture or plane height changes). * * PRE: Subsector attributors must have been determined first. * * @param sec Ptr to the sector to calculate reverb properties of. */ void S_CalcSectorReverb(sector_t* sec) { uint i; subsector_t* sub; float spaceScatter; uint sectorSpace; if(!sec) return; // Wha? sectorSpace = (int) (sec->SP_ceilheight - sec->SP_floorheight) * (sec->bBox[BOXRIGHT] - sec->bBox[BOXLEFT]) * (sec->bBox[BOXTOP] - sec->bBox[BOXBOTTOM]); /* #if _DEBUG Con_Message("sector %i: secsp:%i\n", c, sectorSpace); #endif */ for(i = 0; i < sec->numReverbSSecAttributors; ++i) { sub = sec->reverbSSecs[i]; if(calcSSecReverb(sub)) { sec->reverb[SRD_SPACE] += sub->reverb[SRD_SPACE]; sec->reverb[SRD_VOLUME] += sub->reverb[SRD_VOLUME] / 255.0f * sub->reverb[SRD_SPACE]; sec->reverb[SRD_DECAY] += sub->reverb[SRD_DECAY] / 255.0f * sub->reverb[SRD_SPACE]; sec->reverb[SRD_DAMPING] += sub->reverb[SRD_DAMPING] / 255.0f * sub->reverb[SRD_SPACE]; } } if(sec->reverb[SRD_SPACE]) { spaceScatter = sectorSpace / sec->reverb[SRD_SPACE]; // These three are weighted by the space. sec->reverb[SRD_VOLUME] /= sec->reverb[SRD_SPACE]; sec->reverb[SRD_DECAY] /= sec->reverb[SRD_SPACE]; sec->reverb[SRD_DAMPING] /= sec->reverb[SRD_SPACE]; } else { spaceScatter = 0; sec->reverb[SRD_VOLUME] = .2f; sec->reverb[SRD_DECAY] = .4f; sec->reverb[SRD_DAMPING] = 1; } // If the space is scattered, the reverb effect lessens. sec->reverb[SRD_SPACE] /= (spaceScatter > .8 ? 10 : spaceScatter > .6 ? 4 : 1); // Normalize the reverb space [0...1]. // 0= very small // .99= very large // 1.0= only for open areas (special case). sec->reverb[SRD_SPACE] /= 120e6; if(sec->reverb[SRD_SPACE] > .99) sec->reverb[SRD_SPACE] = .99f; if(R_IsSkySurface(&sec->SP_ceilsurface) || R_IsSkySurface(&sec->SP_floorsurface)) { // An "open" sector. // It can still be small, in which case; reverb is diminished a bit. if(sec->reverb[SRD_SPACE] > .5) sec->reverb[SRD_VOLUME] = 1; // Full volume. else sec->reverb[SRD_VOLUME] = .5f; // Small, but still open. sec->reverb[SRD_SPACE] = 1; } else { // A "closed" sector. // Large spaces have automatically a bit more audible reverb. sec->reverb[SRD_VOLUME] += sec->reverb[SRD_SPACE] / 4; } if(sec->reverb[SRD_VOLUME] > 1) sec->reverb[SRD_VOLUME] = 1; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/bsp_intersection.c0000644000175000017500000004040511357170241024451 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_intersection.c: Intersections and cutlists (lists of intersections). */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_bsp.h" #include "de_misc.h" #include #include #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct cnode_s { void* data; struct cnode_s* next; struct cnode_s* prev; } cnode_t; // The intersection list is kept sorted by along_dist, in ascending order. typedef struct clist_s { cnode_t* headPtr; } clist_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static clist_t* UnusedIntersectionList; static cnode_t* unusedCNodes; static boolean initedOK = false; // CODE -------------------------------------------------------------------- static cnode_t* allocCNode(void) { return M_Malloc(sizeof(cnode_t)); } static void freeCNode(cnode_t* node) { M_Free(node); } static cnode_t* quickAllocCNode(void) { cnode_t* node; if(initedOK && unusedCNodes) { node = unusedCNodes; unusedCNodes = unusedCNodes->next; } else { // Need to allocate another. node = allocCNode(); } node->data = NULL; node->next = node->prev = NULL; return node; } static clist_t* allocCList(void) { return M_Malloc(sizeof(clist_t)); } static void freeCList(clist_t* list) { M_Free(list); } static intersection_t* allocIntersection(void) { return M_Calloc(sizeof(intersection_t)); } static void freeIntersection(intersection_t* cut) { M_Free(cut); } static intersection_t* quickAllocIntersection(void) { intersection_t* cut; if(initedOK && UnusedIntersectionList->headPtr) { cnode_t* node = UnusedIntersectionList->headPtr; // Unlink from the unused list. UnusedIntersectionList->headPtr = node->next; // Grab the intersection. cut = node->data; // Move the list node to the unused node list. node->next = unusedCNodes; unusedCNodes = node; } else { cut = allocIntersection(); } memset(cut, 0, sizeof(*cut)); return cut; } static void emptyCList(clist_t* list) { cnode_t* node; node = list->headPtr; while(node) { cnode_t* p = node->next; BSP_IntersectionDestroy(node->data); // Move the list node to the unused node list. node->next = unusedCNodes; unusedCNodes = node; node = p; } list->headPtr = NULL; } void BSP_InitIntersectionAllocator(void) { if(!initedOK) { UnusedIntersectionList = M_Calloc(sizeof(clist_t)); unusedCNodes = NULL; initedOK = true; } } void BSP_ShutdownIntersectionAllocator(void) { if(UnusedIntersectionList) { cnode_t* node; node = UnusedIntersectionList->headPtr; while(node) { cnode_t* p = node->next; freeIntersection(node->data); freeCNode(node); node = p; } M_Free(UnusedIntersectionList); UnusedIntersectionList = NULL; } if(unusedCNodes) { cnode_t* node; node = unusedCNodes; while(node) { cnode_t* np = node->next; freeCNode(node); node = np; } unusedCNodes = NULL; } initedOK = false; } /** * Create a new intersection. */ intersection_t* BSP_IntersectionCreate(vertex_t* vert, const struct bspartition_s* part, boolean selfRef) { intersection_t* cut = quickAllocIntersection(); cut->vertex = vert; cut->alongDist = M_ParallelDist(part->pDX, part->pDY, part->pPara, part->length, vert->buildData.pos[VX], vert->buildData.pos[VY]); cut->selfRef = selfRef; cut->before = BSP_VertexCheckOpen(vert, -part->pDX, -part->pDY); cut->after = BSP_VertexCheckOpen(vert, part->pDX, part->pDY); return cut; } /** * Destroy the specified intersection. * * @param cut Ptr to the intersection to be destroyed. */ void BSP_IntersectionDestroy(intersection_t* cut) { if(initedOK) { // If the allocator is initialized, move the intersection to the // unused list for reuse. cnode_t* node = quickAllocCNode(); node->data = cut; node->next = UnusedIntersectionList->headPtr; node->prev = NULL; UnusedIntersectionList->headPtr = node; } else { // Just free it. freeIntersection(cut); } } #if _DEBUG void BSP_IntersectionPrint(intersection_t* cut) { Con_Message(" Vertex %8X (%1.1f,%1.1f) Along %1.2f [%d/%d] %s\n", cut->vertex->buildData.index, cut->vertex->buildData.pos[VX], cut->vertex->buildData.pos[VY], cut->alongDist, (cut->before? cut->before->buildData.index : -1), (cut->after? cut->after->buildData.index : -1), (cut->selfRef? "SELFREF" : "")); } #endif /** * Create a new cutlist. */ cutlist_t* BSP_CutListCreate(void) { clist_t* list = allocCList(); list->headPtr = NULL; return (cutlist_t*) list; } /** * Destroy a cutlist. */ void BSP_CutListDestroy(cutlist_t* cutList) { if(cutList) { clist_t* list = (clist_t*) cutList; emptyCList(list); freeCList(list); } } /** * Empty all intersections from the specified cutlist. */ void BSP_CutListEmpty(cutlist_t* cutList) { if(cutList) { clist_t* list = (clist_t*) cutList; emptyCList(list); } } /** * Search the given list for an intersection, if found; return it. * * @param list The list to be searched. * @param vert Ptr to the intersection vertex to look for. * * @return Ptr to the found intersection, else @c NULL; */ intersection_t* BSP_CutListFindIntersection(cutlist_t* cutList, vertex_t* v) { clist_t* list = (clist_t*) cutList; cnode_t* node; node = list->headPtr; while(node) { intersection_t *cut = node->data; if(cut->vertex == v) return cut; node = node->next; } return NULL; } /** * Insert the given intersection into the specified cutlist. * * @return @c true, if successful. */ boolean BSP_CutListInsertIntersection(cutlist_t* cutList, intersection_t* cut) { if(cutList && cut) { clist_t* list = (clist_t*) cutList; cnode_t* newNode = quickAllocCNode(); cnode_t* after; /** * Enqueue the new intersection into the list. */ after = list->headPtr; while(after && after->next) after = after->next; while(after && cut->alongDist < ((intersection_t *)after->data)->alongDist) after = after->prev; newNode->data = cut; // Link it in. newNode->next = (after? after->next : list->headPtr); newNode->prev = after; if(after) { if(after->next) after->next->prev = newNode; after->next = newNode; } else { if(list->headPtr) list->headPtr->prev = newNode; list->headPtr = newNode; } return true; } return false; } static void buildEdgeBetweenIntersections(const bspartition_t* part, intersection_t* start, intersection_t* end, hedge_t** right, hedge_t** left) { // Create the half-edge pair. // Leave 'linedef' field as NULL as these are not linedef-linked. // Leave 'side' as zero too. (*right) = HEdge_Create(NULL, part->lineDef, start->vertex, end->vertex, start->after, false); (*left) = HEdge_Create(NULL, part->lineDef, end->vertex, start->vertex, start->after, false); // Twin the half-edges together. (*right)->twin = *left; (*left)->twin = *right; /*#if _DEBUG Con_Message("buildEdgeBetweenIntersections: Capped intersection:\n"); Con_Message(" %p RIGHT sector %d (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", (*right), ((*right)->sector? (*right)->sector->index : -1), (*right)->v[0]->V_pos[VX], (*right)->v[0]->V_pos[VY], (*right)->v[1]->V_pos[VX], (*right)->v[1]->V_pos[VY]); Con_Message(" %p LEFT sector %d (%1.1f,%1.1f) -> (%1.1f,%1.1f)\n", (*left), ((*left)->sector? (*left)->sector->index : -1), (*left)->v[0]->V_pos[VX], (*left)->v[0]->V_pos[VY], (*left)->v[1]->V_pos[VX], (*left)->v[1]->V_pos[VY]); #endif*/ } /** * Analyze the intersection list, and add any needed minihedges to the given * half-edge lists (one minihedge on each side). * * \note All the intersections in the cutList will be freed back into the * quick-alloc list for re-use! * * \todo Does this belong in here? */ void BSP_AddMiniHEdges(const bspartition_t* part, superblock_t* rightList, superblock_t* leftList, cutlist_t* cutList) { clist_t* list; cnode_t* node, *np; if(!cutList) return; list = (clist_t*) cutList; /* #if _DEBUG BSP_CutListPrint(cutList); Con_Message("BSP_AddMiniHEdges: Partition (%1.1f,%1.1f) += (%1.1f,%1.1f)\n", part->pSX, part->pSY, part->pDX, part->pDY); */ /** * Step 1: Fix problems in the intersection list... */ node = list->headPtr; np = node->next; while(node && np) { intersection_t* cur = node->data; intersection_t* next = np->data; double len = next->alongDist - cur->alongDist; if(len < -0.1) { Con_Error("BSP_AddMiniHEdges: Bad order in intersect list - " "%1.3f > %1.3f\n", cur->alongDist, next->alongDist); } else if(len > 0.2) { node = np; np = node->next; continue; } else if(len > DIST_EPSILON) { /* #if _DEBUG Con_Message(" Skipping very short half-edge (len=%1.3f) near " "(%1.1f,%1.1f)\n", len, cur->vertex->V_pos[VX], cur->vertex->V_pos[VY]); #endif */ } // Merge the two intersections into one. /* #if _DEBUG Con_Message(" Merging intersections:\n"); BSP_IntersectionPrint(cur); BSP_IntersectionPrint(next); #endif */ if(cur->selfRef && !next->selfRef) { if(cur->before && next->before) cur->before = next->before; if(cur->after && next->after) cur->after = next->after; cur->selfRef = false; } if(!cur->before && next->before) cur->before = next->before; if(!cur->after && next->after) cur->after = next->after; /* #if _DEBUG Con_Message(" Result:\n"); BSP_IntersectionPrint(cur); #endif */ // Free the unused cut. node->next = np->next; BSP_IntersectionDestroy(next); np = node->next; } // Step 2: Find connections in the intersection list... node = list->headPtr; while(node && node->next) { intersection_t* cur = node->data; intersection_t* next = (node->next? node->next->data : NULL); if(!(!cur->after && !next->before)) { // Check for some nasty open/closed or close/open cases. if(cur->after && !next->before) { if(!cur->selfRef) { double pos[2]; pos[VX] = cur->vertex->buildData.pos[VX] + next->vertex->buildData.pos[VX]; pos[VY] = cur->vertex->buildData.pos[VY] + next->vertex->buildData.pos[VY]; pos[VX] /= 2; pos[VY] /= 2; MPE_RegisterUnclosedSectorNear(cur->after, pos[VX], pos[VY]); } } else if(!cur->after && next->before) { if(!next->selfRef) { double pos[2]; pos[VX] = cur->vertex->buildData.pos[VX] + next->vertex->buildData.pos[VX]; pos[VY] = cur->vertex->buildData.pos[VY] + next->vertex->buildData.pos[VY]; pos[VX] /= 2; pos[VY] /= 2; MPE_RegisterUnclosedSectorNear(next->before, pos[VX], pos[VY]); } } else { // This is definitetly open space. // Do a sanity check on the sectors (just for good measure). if(cur->after != next->before) { if(!cur->selfRef && !next->selfRef) { VERBOSE( Con_Message("Sector mismatch: #%d (%1.1f,%1.1f) != #%d " "(%1.1f,%1.1f)\n", cur->after->buildData.index, cur->vertex->buildData.pos[VX], cur->vertex->buildData.pos[VY], next->before->buildData.index, next->vertex->buildData.pos[VX], next->vertex->buildData.pos[VY])); } // Choose the non-self-referencing sector when we can. if(cur->selfRef && !next->selfRef) { cur->after = next->before; } } { hedge_t* right, *left; buildEdgeBetweenIntersections(part, cur, next, &right, &left); // Add the new half-edges to the appropriate lists. BSP_AddHEdgeToSuperBlock(rightList, right); BSP_AddHEdgeToSuperBlock(leftList, left); } } } node = node->next; } } #if _DEBUG void BSP_CutListPrint(cutlist_t* cutList) { if(cutList) { clist_t* list = (clist_t*) cutList; cnode_t* node; Con_Message("CutList %p:\n", list); node = list->headPtr; while(node) { intersection_t *cut = node->data; BSP_IntersectionPrint(cut); node = node->next; } } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/ui_panel.c0000644000175000017500000016765611357170242022716 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * ui_panel.c: Control Panel * * Doomsday Control Panel (opened with the "panel" command). * During netgames the game is NOT PAUSED while the UI is active. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_graphics.h" #include "de_ui.h" #include "rend_main.h" // MACROS ------------------------------------------------------------------ #define NUM_CP_BUTTONS 11 #define NUMITEMS(x) (sizeof(x)/sizeof(uidata_listitem_t)) #define RES(x, y) (x | (y<<16)) #define CPID_FRAME (UIF_ID0 | UIF_ID1) #define CPID_RES_X UIF_ID0 #define CPID_RES_Y UIF_ID1 #define CPID_SET_RES UIF_ID2 #define CPID_RES_LIST UIF_ID3 #define CPG_VIDEO 2 #define HELP_OFFSET (UI_ScreenW(UI_WIDTH)*290/UI_WIDTH) // TYPES ------------------------------------------------------------------- typedef struct cvarbutton_s { char active; const char *cvarname; const char *yes; const char *no; int mask; } cvarbutton_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(OpenPanel); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void CP_ClosePanel(ui_object_t *ob); void CP_ChooseGroup(ui_object_t *ob); void CP_DrawLogo(ui_object_t *ob); void CP_DrawBorder(ui_object_t *ob); void CP_CvarButton(ui_object_t *ob); void CP_CvarList(ui_object_t *ob); void CP_CvarEdit(ui_object_t *ob); void CP_CvarSlider(ui_object_t *ob); int CP_KeyGrabResponder(ui_object_t *ob, ddevent_t *ev); void CP_KeyGrabDrawer(ui_object_t *ob); void CP_QuickFOV(ui_object_t *ob); void CP_VideoModeInfo(ui_object_t *ob); void CP_ResolutionList(ui_object_t *ob); void CP_SetDefaultVidMode(ui_object_t *ob); void CP_SetVidMode(ui_object_t *ob); void CP_VidModeChanged(ui_object_t *ob); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- char panel_buttons[NUM_CP_BUTTONS] = { true }; // The first is active. char panel_sv_password[100], panel_res_x[40], panel_res_y[40]; int panel_fullscreen, panel_bpp; int panel_help_active = false; int panel_help_offset = 0; // Zero means the help is completely hidden. byte panel_show_help = true; // cvar byte panel_show_tips = true; // cvar ui_object_t *panel_help_source; void *panel_help; cvarbutton_t cvarbuttons[] = { {0, "con-var-silent"}, {0, "con-dump"}, {0, "con-fps"}, {0, "con-text-shadow"}, {0, "ui-panel-help"}, {0, "ui-panel-tips"}, {0, "input-mouse-filter"}, {0, "input-joy"}, {0, "net-nosleep"}, {0, "net-dev"}, {0, "net-queue-show"}, {0, "sound-16bit"}, {0, "sound-3d"}, {0, "sound-info"}, {0, "rend-particle"}, {0, "rend-camera-smooth"}, {0, "rend-mobj-smooth-turn"}, {0, "rend-sprite-precache"}, {0, "rend-sprite-noz"}, {0, "rend-sprite-blend"}, {0, "rend-model"}, {0, "rend-model-inter"}, {0, "rend-model-precache"}, {0, "rend-model-mirror-hud"}, {0, "rend-model-shiny-multitex", "Shiny", "Shiny"}, {0, "rend-tex"}, {0, "rend-tex-filter-sprite", "Sprite", "Sprite"}, {0, "rend-tex-filter-mag", "World", "World"}, {0, "rend-tex-filter-raw", "Raw", "Raw"}, {0, "rend-tex-filter-smart"}, {0, "rend-tex-detail"}, {0, "rend-tex-detail-multitex", "Detail", "Detail"}, {0, "rend-tex-anim-smooth"}, {0, "rend-light"}, {0, "rend-light-decor"}, {0, "rend-light-multitex", "Lights", "Lights"}, {0, "rend-halo-realistic"}, {0, "rend-glow"}, {0, "rend-glow-wall"}, {0, "rend-info-tris"}, {0, "rend-sky-full"}, {0, "rend-shadow"}, {0, "rend-fakeradio"}, {0, "input-mouse-x-flags", "Invert", "Invert", IDA_INVERT }, {0, "input-mouse-x-flags", "Disable", "Disable", IDA_DISABLED }, {0, "input-mouse-y-flags", "Invert", "Invert", IDA_INVERT }, {0, "input-mouse-y-flags", "Disable", "Disable", IDA_DISABLED }, {0, 0} }; uidata_button_t btn_bpp = {&panel_bpp, "32", "16"}; uidata_button_t btn_fullscreen = {&panel_fullscreen, "Yes", "No"}; uidata_listitem_t lstit_con_completion[] = { {"List with values", 0}, {"Cycle through", 1} }; uidata_list_t lst_con_completion = { lstit_con_completion, NUMITEMS(lstit_con_completion), "con-completion" }; uidata_listitem_t lstit_music_source[] = { {"MUS lumps", 0}, {"External files", 1}, {"CD", 2} }; uidata_list_t lst_music_source = { lstit_music_source, NUMITEMS(lstit_music_source), "music-source" }; uidata_listitem_t lstit_sound_rate[] = { {"11025 Hz (1x)", 11025}, {"22050 Hz (2x)", 22050}, {"44100 Hz (4x)", 44100} }; uidata_list_t lst_sound_rate = { lstit_sound_rate, NUMITEMS(lstit_sound_rate), "sound-rate" }; uidata_listitem_t lstit_smooth_move[] = { {"Disabled", 0}, {"Models only", 1}, {"Models and sprites", 2} }; uidata_list_t lst_smooth_move = { lstit_smooth_move, NUMITEMS(lstit_smooth_move), "rend-mobj-smooth-move" }; uidata_listitem_t lstit_sprite_align[] = { {"Camera", 0}, {"View plane", 1}, {"Camera (limited)", 2}, {"View plane (limited)", 3} }; uidata_list_t lst_sprite_align = { lstit_sprite_align, NUMITEMS(lstit_sprite_align), "rend-sprite-align" }; uidata_listitem_t lstit_mipmap[] = { {"No filter, no mip", 0}, {"Linear filter, no mip", 1}, {"No filter, near mip", 2}, {"Linear filter, near mip", 3}, {"No filter, linear mip", 4}, {"Linear filter, linear mip", 5} }; uidata_list_t lst_mipmap = { lstit_mipmap, NUMITEMS(lstit_mipmap), "rend-tex-mipmap" }; uidata_listitem_t lstit_blend[] = { {"Multiply", 0}, {"Add", 1}, {"Process wo/rendering", 2} }; uidata_list_t lst_blend = { lstit_blend, NUMITEMS(lstit_blend), "rend-light-blend" }; uidata_listitem_t lstit_resolution[] = { // 5:4 {"1280 x 1024 (5:4 SXGA)", RES(1280, 1024)}, {"2560 x 2048 (5:4 QSXGA)", RES(2560, 2048)}, // 4:3 {"320 x 240 (4:3 QVGA)", RES(320, 240)}, {"640 x 480 (4:3 VGA)", RES(640, 480)}, {"768 x 576 (4:3 PAL)", RES(768, 576)}, {"800 x 600 (4:3 SVGA)", RES(800, 600)}, {"1024 x 768 (4:3 XGA)", RES(1024, 768)}, {"1152 x 864 (4:3)", RES(1152, 864)}, {"1280 x 960 (4:3)", RES(1280, 960)}, {"1400 x 1050 (4:3 SXGA+)", RES(1400, 1050)}, {"1600 x 1200 (4:3 UXGA)", RES(1600, 1200)}, {"2048 x 1536 (4:3 QXGA)", RES(2048, 1536)}, // 3:2 {"720 x 480 (3:2 NTSC)", RES(720, 480)}, {"1152 x 768 (3:2)", RES(1152, 768)}, {"1280 x 854 (3:2)", RES(1280, 854)}, {"1440 x 960 (3:2)", RES(1440, 960)}, // 16:10 {"320 x 200 (16:10 CGA)", RES(320, 200)}, {"800 x 500 (16:10)", RES(800, 500)}, {"1024 x 640 (16:10)", RES(1024, 640)}, {"1280 x 800 (16:10)", RES(1280, 800)}, {"1440 x 900 (16:10 WXGA)", RES(1440, 900)}, {"1600 x 1000 (16:10)", RES(1600, 1000)}, {"1680 x 1050 (16:10 WSXGA+)", RES(1680, 1050)}, {"1920 x 1200 (16:10 WUXGA)", RES(1920, 1200)}, {"2560 x 1600 (16:10 WQXGA)", RES(2560, 1600)}, // 16:9 {"854 x 480 (16:9 WVGA)", RES(854, 480)}, {"1280 x 720 (16:9 WXGA/HD720)", RES(1280, 720)}, {"1920 x 1080 (16:9 HD1080)", RES(1920, 1080)} }; uidata_list_t lst_resolution = { lstit_resolution, NUMITEMS(lstit_resolution) }; uidata_slider_t sld_con_alpha = { 0, 100, 0, 1, false, "con-alpha" }; uidata_slider_t sld_con_light = { 0, 100, 0, 1, false, "con-light" }; uidata_slider_t sld_keywait1 = { 50, 1000, 0, 1, false, "input-key-delay1" }; uidata_slider_t sld_keywait2 = { 20, 1000, 0, 1, false, "input-key-delay2" }; uidata_slider_t sld_mouse_x_scale = { 0, .01f, 0, .00005f, true, "input-mouse-x-scale" }; uidata_slider_t sld_mouse_y_scale = { 0, .01f, 0, .00005f, true, "input-mouse-y-scale" }; uidata_slider_t sld_client_pos_interval = { 0, 70, 0, 1, false, "client-pos-interval" }; uidata_slider_t sld_server_frame_interval = { 0, 35, 0, 1, false, "server-frame-interval" }; uidata_slider_t sld_sound_volume = { 0, 255, 0, 1, false, "sound-volume" }; uidata_slider_t sld_music_volume = { 0, 255, 0, 1, false, "music-volume" }; uidata_slider_t sld_reverb_volume = { 0, 1, 0, .01f, true, "sound-reverb-volume" }; uidata_slider_t sld_particle_max = { 0, 10000, 0, 10, false, "rend-particle-max", "Unlimited" }; uidata_slider_t sld_particle_rate = { .1f, 10, 0, .01f, true, "rend-particle-rate" }; uidata_slider_t sld_particle_diffuse = { 0, 20, 0, .01f, true, "rend-particle-diffuse" }; uidata_slider_t sld_particle_visnear = { 0, 1000, 0, 1, false, "rend-particle-visible-near", "Disabled" }; uidata_slider_t sld_model_far = { 0, 3000, 0, 1, false, "rend-model-distance", "Unlimited" }; uidata_slider_t sld_model_lights = { 0, 10, 0, 1, false, "rend-model-lights" }; uidata_slider_t sld_model_lod = { 0, 1000, 0, 1, true, "rend-model-lod", "No LOD" }; uidata_slider_t sld_detail_scale = { .1f, 32, 0, .01f, true, "rend-tex-detail-scale" }; uidata_slider_t sld_detail_strength = { 0, 2, 0, .01f, true, "rend-tex-detail-strength" }; uidata_slider_t sld_detail_far = { 1, 1000, 0, 1, true, "rend-tex-detail-far" }; uidata_slider_t sld_tex_quality = { 0, 8, 0, 1, false, "rend-tex-quality" }; uidata_slider_t sld_tex_aniso = { -1, 4, 0, 1, false, "rend-tex-filter-anisotropic", "Best Available"}; uidata_slider_t sld_light_bright = { 0, 1, 0, .01f, true, "rend-light-bright" }; uidata_slider_t sld_light_scale = { .1f, 10, 0, .01f, true, "rend-light-radius-scale" }; uidata_slider_t sld_light_radmax = { 64, 512, 0, 1, false, "rend-light-radius-max" }; uidata_slider_t sld_light_max = { 0, 2000, 0, 1, false, "rend-light-num", "Unlimited" }; uidata_slider_t sld_light_fog_bright = { 0, 1, 0, .01f, true, "rend-glow-fog-bright" }; uidata_slider_t sld_light_ambient = { 0, 255, 0, 1, false, "rend-light-ambient" }; uidata_slider_t sld_light_compression = { -1, 1, 0, 0.1f, true, "rend-light-compression" }; uidata_slider_t sld_glow_height = { 0, 1024, 0, 1, false, "rend-glow-height" }; uidata_slider_t sld_glow_scale = { .1f, 10, 0, 0.1f, true, "rend-glow-scale" }; uidata_slider_t sld_fov = { 1, 179, 0, .01f, true, "rend-camera-fov" }; uidata_slider_t sld_sky_distance = { 1, 10000, 0, 10, true, "rend-sky-distance" }; uidata_slider_t sld_shadow_dark = { 0, 1, 0, .01f, true, "rend-shadow-darkness" }; uidata_slider_t sld_shadow_far = { 0, 3000, 0, 1, false, "rend-shadow-far" }; uidata_slider_t sld_shadow_radmax = { 0, 128, 0, 1, false, "rend-shadow-radius-max" }; uidata_slider_t sld_fakeradio_dark = { 0, 2, 0, .01f, true, "rend-fakeradio-darkness" }; uidata_slider_t sld_vid_gamma = { .1f, 3, 0, .01f, true, "vid-gamma" }; uidata_slider_t sld_vid_contrast = { .1f, 3, 0, .01f, true, "vid-contrast" }; uidata_slider_t sld_vid_bright = { -.5f, .5f, 0, .01f, true, "vid-bright" }; uidata_slider_t sld_halo = { 0, 5, 0, 1, false, "rend-halo", "None" }; uidata_slider_t sld_halo_bright = { 0, 100, 0, 1, false, "rend-halo-bright" }; uidata_slider_t sld_halo_occlusion = { 1, 256, 0, 1, false, "rend-halo-occlusion" }; uidata_slider_t sld_halo_size = { 0, 100, 0, 1, false, "rend-halo-size" }; uidata_slider_t sld_halo_seclimit = { 0, 10, 0, .01f, true, "rend-halo-secondary-limit" }; uidata_slider_t sld_halo_dimfar = { 0, 200, 0, .01f, true, "rend-halo-dim-far" }; uidata_slider_t sld_halo_dimnear = { 0, 200, 0, .01f, true, "rend-halo-dim-near" }; uidata_slider_t sld_halo_zmagdiv = { 1, 200, 0, .01f, true, "rend-halo-zmag-div" }; uidata_slider_t sld_halo_radmin = { 1, 80, 0, .01f, true, "rend-halo-radius-min" }; uidata_slider_t sld_sprite_lights = { 0, 10, 0, 1, false, "rend-sprite-lights" }; uidata_edit_t ed_server_password = { panel_sv_password, 100, "server-password" }; uidata_edit_t ed_res_x = { panel_res_x, 40 }; uidata_edit_t ed_res_y = { panel_res_y, 40 }; ui_page_t page_panel; /* *INDENT-OFF* */ ui_object_t ob_panel[] = { { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 10, 210, 240, 60, "Video", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[0] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 10, 275, 240, 60, "Audio", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[1] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 10, 340, 240, 60, "Input", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[2] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 10, 405, 240, 60, "Graphics", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[3] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 40, 467, 210, 60, "Lights", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[4] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 40, 529, 210, 60, "Halos", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[5] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 40, 591, 210, 60, "Textures", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[6] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 40, 653, 210, 60, "Objects", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[7] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 40, 715, 210, 60, "Particles", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[8] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 10, 780, 240, 60, "Network", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[9] }, { UI_BUTTON2, 1, UIF_LEFT_ALIGN, 10, 845, 240, 60, "Console", UIButton_Drawer, UIButton_Responder, 0, CP_ChooseGroup, &panel_buttons[10] }, { UI_BUTTON, 0, UIF_NEVER_FADE, 10, 940, 240, 60, "Close Panel (Esc)", UIButton_Drawer, UIButton_Responder, 0, CP_ClosePanel }, { UI_BOX, 0, 0, 8, -20, 250, 250, "", CP_DrawLogo }, { UI_BOX, 0, CPID_FRAME, 280, 55, 720, 945, "", CP_DrawBorder }, { UI_META, 2 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Video Options", UIText_BrightDrawer }, { UI_TEXT, 0, UIF_FADE_AWAY, 300, 70, 0, 55, "Gamma correction", UIText_Drawer }, { UI_SLIDER, 0, UIF_FADE_AWAY, 680, 70, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_vid_gamma }, { UI_TEXT, 0, UIF_FADE_AWAY, 300, 130, 0, 55, "Display contrast", UIText_Drawer }, { UI_SLIDER, 0, UIF_FADE_AWAY, 680, 130, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_vid_contrast }, { UI_TEXT, 0, UIF_FADE_AWAY, 300, 190, 0, 55, "Display brightness", UIText_Drawer }, { UI_SLIDER, 0, UIF_FADE_AWAY, 680, 190, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_vid_bright }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Current video mode", UIText_Drawer }, { UI_BOX, 0, 0, 680, 250, 0, 60, "current", CP_VideoModeInfo }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Resolution", UIText_Drawer }, { UI_LIST, 0, CPID_RES_LIST, 680, 310, 300, 175, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_ResolutionList, &lst_resolution }, { UI_TEXT, 0, 0, 300, 490, 0, 55, "Custom resolution", UIText_Drawer }, { UI_EDIT, 0, CPID_RES_X, 680, 490, 130, 55, "", UIEdit_Drawer, UIEdit_Responder, 0, CP_VidModeChanged, &ed_res_x }, { UI_TEXT, 0, 0, 826, 490, 0, 55, "x", UIText_Drawer }, { UI_EDIT, 0, CPID_RES_Y, 850, 490, 130, 55, "", UIEdit_Drawer, UIEdit_Responder, 0, CP_VidModeChanged, &ed_res_y }, { UI_TEXT, 0, 0, 300, 550, 0, 55, "Fullscreen", UIText_Drawer }, { UI_BUTTON2EX, 0, 0, 680, 550, 130, 55, "", UIButton_Drawer, UIButton_Responder, 0, CP_VidModeChanged, &btn_fullscreen }, { UI_TEXT, 0, 0, 300, 610, 0, 55, "Color depth", UIText_Drawer }, { UI_BUTTON2EX, 0, 0, 680, 610, 130, 55, "", UIButton_Drawer, UIButton_Responder, 0, CP_VidModeChanged, &btn_bpp }, { UI_TEXT, 0, 0, 300, 670, 0, 55, "Default video mode", UIText_Drawer }, { UI_BOX, 0, 0, 680, 670, 0, 55, "default", CP_VideoModeInfo }, { UI_BUTTON, 0, 0, 680, 730, 170, 60, "Set Default", UIButton_Drawer, UIButton_Responder, 0, CP_SetDefaultVidMode }, { UI_TEXT, 0, 0, 300, 910, 0, 55, "Change to", UIText_Drawer }, { UI_BUTTON, 0, CPID_SET_RES, 680, 910, 300, 60, "", UIButton_Drawer, UIButton_Responder, 0, CP_SetVidMode }, { UI_META, 3 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Audio Options", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Sound volume", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 70, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_sound_volume }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Music volume", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 130, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_music_volume }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Preferred music source", UIText_Drawer }, { UI_LIST, 0, 0, 680, 190, 300, 150, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_CvarList, &lst_music_source }, { UI_TEXT, 0, 0, 300, 345, 0, 55, "16-bit sound effects", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 345, 70, 55, "sound-16bit", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 405, 0, 55, "Sound effects sample rate", UIText_Drawer }, { UI_LIST, 0, 0, 680, 405, 300, 150, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_CvarList, &lst_sound_rate }, { UI_TEXT, 0, 0, 300, 560, 0, 55, "3D sounds", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 560, 70, 55, "sound-3d", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 620, 0, 55, "General reverb strength", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 620, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_reverb_volume }, { UI_TEXT, 0, 0, 300, 680, 0, 55, "Show status of channels", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 680, 70, 55, "sound-info", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 4 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Input Options", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Mouse X sensitivity", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 70, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_mouse_x_scale }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Mouse X mode", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 130, 80, 55, "input-mouse-x-flags", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton, 0, IDA_INVERT }, { UI_BUTTON2, 0, 0, 765, 130, 80, 55, "input-mouse-x-flags", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton, 0, IDA_DISABLED }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Mouse Y sensitivity", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 190, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_mouse_y_scale }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Mouse Y mode", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 250, 80, 55, "input-mouse-y-flags", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton, 0, IDA_INVERT }, { UI_BUTTON2, 0, 0, 765, 250, 80, 55, "input-mouse-y-flags", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton, 0, IDA_DISABLED }, { UI_META, 4, 0, 0, 60 }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Enable joystick", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 250, 70, 55, "input-joy", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 430, 0, 55, "Key repeat delay (ms)", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 430, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_keywait1 }, { UI_TEXT, 0, 0, 300, 490, 0, 55, "Key repeat rate (ms)", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 490, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_keywait2 }, { UI_META, 5 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Graphics Options", UIText_BrightDrawer }, { UI_META, 5, 0, 0, -60 }, { UI_TEXT, 0, UIF_FADE_AWAY, 300, 130, 0, 55, "Field Of View angle", UIText_Drawer }, { UI_SLIDER, 0, UIF_FADE_AWAY, 680, 130, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_fov }, { UI_BUTTON, 0, 0, 680, 190, 70, 60, "90", UIButton_Drawer, UIButton_Responder, 0, CP_QuickFOV }, { UI_BUTTON, 0, 0, 755, 190, 70, 60, "95", UIButton_Drawer, UIButton_Responder, 0, CP_QuickFOV }, { UI_BUTTON, 0, 0, 830, 190, 70, 60, "100", UIButton_Drawer, UIButton_Responder, 0, CP_QuickFOV }, { UI_BUTTON, 0, 0, 905, 190, 70, 60, "110", UIButton_Drawer, UIButton_Responder, 0, CP_QuickFOV }, { UI_TEXT, 0, 0, 300, 255, 0, 55, "Mirror player weapon models", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 255, 70, 55, "rend-model-mirror-hud", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 5, 0, 0, 60 }, { UI_TEXT, 0, 0, 300, 255, 0, 55, "Sky sphere radius", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 255, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_sky_distance }, { UI_TEXT, 0, 0, 300, 315, 0, 55, "Always render full sky", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 315, 70, 55, "rend-sky-full", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 375, 0, 55, "Objects cast shadows", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 375, 70, 55, "rend-shadow", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 435, 0, 55, "Shadow darkness factor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 435, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_shadow_dark }, { UI_TEXT, 0, 0, 300, 495, 0, 55, "Shadow visible distance", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 495, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_shadow_far }, { UI_TEXT, 0, 0, 300, 555, 0, 55, "Maximum shadow radius", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 555, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_shadow_radmax }, { UI_TEXT, 0, 0, 300, 615, 0, 55, "Simulate radiosity", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 615, 70, 55, "rend-fakeradio", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 675, 0, 55, "Radiosity shadow darkness", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 675, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_fakeradio_dark }, { UI_META, 6 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Graphics Options: Lights", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Enable dynamic lights", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 70, 70, 55, "rend-light", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Blending mode", UIText_Drawer }, { UI_LIST, 0, 0, 680, 130, 300, 115, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_CvarList, &lst_blend }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Dynamic light brightness", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 250, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_light_bright }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Dynamic light radius factor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 310, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_light_scale }, { UI_TEXT, 0, 0, 300, 370, 0, 55, "Maximum dynamic light radius", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 370, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_light_radmax }, { UI_TEXT, 0, 0, 300, 430, 0, 55, "Maximum number of dynamic lights", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 430, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_light_max }, { UI_META, 6, 0, 0, -120 }, { UI_TEXT, 0, UIF_FADE_AWAY, 300, 610, 0, 55, "Ambient light level", UIText_Drawer }, { UI_SLIDER, 0, UIF_FADE_AWAY, 680, 610, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_light_ambient }, { UI_TEXT, 0, UIF_FADE_AWAY, 300, 670, 0, 55, "Light range compression", UIText_Drawer }, { UI_SLIDER, 0, UIF_FADE_AWAY, 680, 670, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_light_compression }, { UI_TEXT, 0, 0, 300, 730, 0, 55, "Enable glowing textures", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 730, 70, 55, "rend-glow", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 790, 0, 55, "Floor/ceiling glow on walls", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 790, 70, 55, "rend-glow-wall", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 850, 0, 55, "Maximum floor/ceiling glow height", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 850, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_glow_height }, { UI_TEXT, 0, 0, 300, 910, 0, 55, "Floor/ceiling glow height factor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 910, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_glow_scale }, { UI_TEXT, 0, 0, 300, 970, 0, 55, "Glow brightness in fog", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 970, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_light_fog_bright }, { UI_TEXT, 0, 0, 300, 1030, 0, 55, "Enable decorations", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 1030, 70, 55, "rend-light-decor", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 7 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Graphics Options: Halos", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Number of flares per halo", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 70, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Use realistic halos", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 130, 70, 55, "rend-halo-realistic", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 7, 0, 0, 60 }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Halo brightness", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 130, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_bright }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Halo size factor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 190, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_size }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Occlusion fade speed", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 250, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_occlusion }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Minimum halo radius", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 310, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_radmin }, { UI_TEXT, 0, 0, 300, 370, 0, 55, "Flare visibility limitation", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 370, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_seclimit }, { UI_TEXT, 0, 0, 300, 430, 0, 55, "Halo fading start", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 430, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_dimnear }, { UI_TEXT, 0, 0, 300, 490, 0, 55, "Halo fading end", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 490, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_dimfar }, { UI_TEXT, 0, 0, 300, 550, 0, 55, "Z magnification divisor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 550, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_halo_zmagdiv }, { UI_META, 8 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Graphics Options: Textures", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Enable textures", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 70, 70, 55, "rend-tex", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Multitexturing", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 130, 95, 55, "rend-tex-detail-multitex", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_BUTTON2, 0, 0, 780, 130, 95, 55, "rend-light-multitex", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_BUTTON2, 0, 0, 880, 130, 95, 55, "rend-model-shiny-multitex", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Smooth texture animation", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 190, 70, 55, "rend-tex-anim-smooth", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 8, 0, 0, 120 }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Mipmapping filter", UIText_Drawer }, { UI_LIST, 0, 0, 680, 130, 300, 175, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_CvarList, &lst_mipmap }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Texture quality", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 310, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_tex_quality }, { UI_TEXT, 0, 0, 300, 370, 0, 55, "Smart texture filtering", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 370, 70, 55, "rend-tex-filter-smart", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 8, 0, 0, 180 }, { UI_TEXT, 0, 0, 300, 370, 0, 55, "Bilinear filtering", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 370, 95, 55, "rend-tex-filter-sprite", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_BUTTON2, 0, 0, 780, 370, 95, 55, "rend-tex-filter-mag", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_BUTTON2, 0, 0, 880, 370, 95, 55, "rend-tex-filter-raw", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 430, 0, 55, "Anisotropic filtering", UIText_Drawer }, { UI_SLIDER, 0, UIF_FADE_AWAY, 680, 430, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_tex_aniso }, { UI_TEXT, 0, 0, 300, 490, 0, 55, "Enable detail textures", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 490, 70, 55, "rend-tex-detail", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 550, 0, 55, "Detail texture scaling factor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 550, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_detail_scale }, { UI_TEXT, 0, 0, 300, 610, 0, 55, "Detail texture contrast", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 610, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_detail_strength }, { UI_META, 9 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Graphics Options: Objects", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Enable 3D models", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 70, 70, 55, "rend-model", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Interpolate between frames", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 130, 70, 55, "rend-model-inter", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "3D model visibility limit", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 190, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_model_far }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Precache 3D models", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 250, 70, 55, "rend-model-precache", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Max dynamic lights on 3D models", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 310, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_model_lights }, { UI_TEXT, 0, 0, 300, 370, 0, 55, "LOD level zero distance", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 370, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_model_lod }, { UI_TEXT, 0, 0, 300, 430, 0, 55, "Precache sprites (slow)", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 430, 70, 55, "rend-sprite-precache", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 490, 0, 55, "Disable Z-writes for sprites", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 490, 70, 55, "rend-sprite-noz", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 550, 0, 55, "Additive blending for sprites", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 550, 70, 55, "rend-sprite-blend", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 610, 0, 55, "Max dynamic lights on sprites", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 610, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_sprite_lights }, { UI_TEXT, 0, 0, 300, 670, 0, 55, "Align sprites to...", UIText_Drawer }, { UI_LIST, 0, 0, 680, 670, 300, 115, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_CvarList, &lst_sprite_align }, { UI_TEXT, 0, 0, 300, 790, 0, 55, "Smooth actor rotation", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 790, 70, 55, "rend-mobj-smooth-turn", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 850, 0, 55, "Smooth actor movement", UIText_Drawer }, { UI_LIST, 0, 0, 680, 850, 300, 115, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_CvarList, &lst_smooth_move }, { UI_META, 10 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Graphics Options: Particles", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Enable particle effects", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 70, 70, 55, "rend-particle", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Maximum number of particles", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 130, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_particle_max }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Spawn rate factor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 190, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_particle_rate }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Near diffusion factor", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 250, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_particle_diffuse }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Near clip distance", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 310, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_particle_visnear }, { UI_META, 11 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Network Options", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Continuous screen refresh", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 70, 70, 55, "net-nosleep", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Show development info", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 130, 70, 55, "net-dev", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Server login password", UIText_Drawer }, { UI_EDIT, 0, 0, 680, 190, 300, 55, "", UIEdit_Drawer, UIEdit_Responder, 0, CP_CvarEdit, &ed_server_password }, { UI_TEXT, 0, 0, 300, 250, 0, 55, "Cl-to-sv pos transmit tics", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 250, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_client_pos_interval }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Frame interval tics", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 310, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_server_frame_interval }, { UI_META, 12 }, { UI_TEXT, 0, 0, 280, 0, 0, 50, "Console Options", UIText_BrightDrawer }, { UI_TEXT, 0, 0, 300, 70, 0, 55, "Display FPS counter", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 70, 70, 55, "con-fps", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 12, 0, 0, 60 }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Display Control Panel help window", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 130, 70, 55, "ui-panel-help", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Display help indicators", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 190, 70, 55, "ui-panel-tips", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_META, 12, 0, 0, 180 }, { UI_TEXT, 0, 0, 300, 130, 0, 55, "Silent console variables", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 130, 70, 55, "con-var-silent", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 190, 0, 55, "Dump messages to Doomsday.out", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 190, 70, 55, "con-dump", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 310, 0, 55, "Command completion with Tab", UIText_Drawer }, { UI_LIST, 0, 0, 680, 310, 300, 120, "", UIList_Drawer, UIList_Responder, UIList_Ticker, CP_CvarList, &lst_con_completion }, { UI_TEXT, 0, 0, 300, 435, 0, 55, "Background opacity", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 435, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_con_alpha }, { UI_TEXT, 0, 0, 300, 495, 0, 55, "Background light", UIText_Drawer }, { UI_SLIDER, 0, 0, 680, 495, 300, 55, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_con_light }, { UI_TEXT, 0, 0, 300, 555, 0, 55, "Console text has shadows", UIText_Drawer }, { UI_BUTTON2, 0, 0, 680, 555, 70, 55, "con-text-shadow", UIButton_Drawer, UIButton_Responder, 0, CP_CvarButton }, { UI_TEXT, 0, 0, 300, 615, 0, 55, "Activation key", UIText_Drawer }, { UI_FOCUSBOX, 0, 0, 680, 615, 70, 55, "con-key-activate", CP_KeyGrabDrawer, CP_KeyGrabResponder }, { UI_TEXT, 0, 0, 680, 670, 0, 40, "Click the box, press a key.", UIText_Drawer }, { UI_NONE } }; /* *INDENT-ON* */ // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void CP_Register(void) { // Cvars C_VAR_BYTE("ui-panel-help", &panel_show_help, 0, 0, 1); C_VAR_BYTE("ui-panel-tips", &panel_show_tips, 0, 0, 1); // Ccmds C_CMD_FLAGS("panel", NULL, OpenPanel, CMDF_NO_DEDICATED); } void CP_ClosePanel(ui_object_t *ob) { UI_End(); } void CP_ChooseGroup(ui_object_t *ob) { int i; memset(panel_buttons, 0, sizeof(panel_buttons)); UI_FlagGroup(ob_panel, 1, UIF_ACTIVE, UIFG_CLEAR); *(char *) ob->data = true; ob->flags |= UIF_ACTIVE; // Hide/show the option controls. for(i = 0; i < NUM_CP_BUTTONS; ++i) UI_FlagGroup(ob_panel, 2 + i, UIF_HIDDEN, !panel_buttons[i]); } void CP_DrawLogo(ui_object_t *ob) { UI_DrawLogo(ob->x, ob->y, ob->w, ob->h); } void CP_DrawBorder(ui_object_t *ob) { int b = UI_BORDER; ui_object_t *it; void *help_ptr; boolean shown; UIFrame_Drawer(ob); // Draw help window visual cues. if(panel_show_tips) { GL_BlendMode(BM_ADD); for(it = ob_panel; it->type; it++) { if(it->flags & UIF_HIDDEN || it->group < 2 || it->type != UI_TEXT) continue; // Try to find help for this. if((help_ptr = DH_Find(it->text))) { shown = (panel_help == help_ptr && panel_help_active); UI_HorizGradient(ob->x + b, it->y + it->h / 2 - UI_FontHeight() / 2, 2 * UI_FontHeight(), UI_FontHeight(), UI_Color(UIC_BRD_HI), 0, shown ? .8f : .2f, 0); } } GL_BlendMode(BM_NORMAL); } } void CP_CvarButton(ui_object_t *ob) { cvarbutton_t *cb = ob->data; cvar_t *var = Con_GetVariable(cb->cvarname); int value; strcpy(ob->text, cb->active? cb->yes : cb->no); if(!var) return; if(cb->mask) { value = Con_GetInteger(cb->cvarname); if(cb->active) { value |= cb->mask; } else { value &= ~cb->mask; } } else { value = cb->active; } Con_SetInteger(cb->cvarname, value, true); } void CP_CvarList(ui_object_t *ob) { uidata_list_t *list = ob->data; cvar_t *var = Con_GetVariable(list->data); int value = ((uidata_listitem_t *) list->items)[list->selection].data; if(list->selection < 0) return; // Hmm? if(!var) return; Con_SetInteger(var->name, value, true); } void CP_CvarEdit(ui_object_t *ob) { uidata_edit_t *ed = ob->data; Con_SetString(ed->data, ed->ptr, true); } void CP_CvarSlider(ui_object_t *ob) { uidata_slider_t *slid = ob->data; cvar_t *var = Con_GetVariable(slid->data); float value = slid->value; if(!var) return; if(!slid->floatmode) { value += (slid->value < 0? -.5f : .5f); } if(var->type == CVT_FLOAT) { if(slid->step >= .01f) { Con_SetFloat(var->name, (int) (100 * value) / 100.0f, true); } else { Con_SetFloat(var->name, value, true); } } else if(var->type == CVT_INT) Con_SetInteger(var->name, (int) value, true); else if(var->type == CVT_BYTE) Con_SetInteger(var->name, (byte) value, true); } int CP_KeyGrabResponder(ui_object_t *ob, ddevent_t *ev) { if(IS_TOGGLE_DOWN(ev) && ((ev->device == IDEV_MOUSE && UI_MouseInside(ob)) || (ev->device == IDEV_KEYBOARD && IS_ACTKEY(ev->toggle.id)))) { // We want the focus. return true; } // Only does something when has the focus. if(!(ob->flags & UIF_FOCUS)) return false; if(IS_KEY_DOWN(ev)) { Con_SetInteger(ob->text, ev->toggle.id, true); // All keydown events are eaten. // Note that the UI responder eats all Tabs! return true; } return false; } void CP_KeyGrabDrawer(ui_object_t *ob) { boolean sel = (ob->flags & UIF_FOCUS) != 0; float alpha = (ob->flags & UIF_DISABLED ? .2f : 1); char buf[80]; byte key = Con_GetByte(ob->text); const char *name; UI_GradientEx(ob->x, ob->y, ob->w, ob->h, UI_BORDER, UI_Color(UIC_SHADOW), 0, 1, 0); UI_Shade(ob->x, ob->y, ob->w, ob->h, UI_BORDER, UI_Color(UIC_BRD_HI), UI_Color(UIC_BRD_LOW), alpha / 3, -1); UI_DrawRectEx(ob->x, ob->y, ob->w, ob->h, UI_BORDER * (sel ? -1 : 1), false, UI_Color(UIC_BRD_HI), NULL, alpha, -1); if((name = B_ShortNameForKey((int) key)) != NULL) sprintf(buf, "%s", name); else if(key > 32 && key < 128) sprintf(buf, "%c", (char) key); else sprintf(buf, "%i", key); FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(buf, ob->x + ob->w / 2, ob->y + ob->h / 2, true, true, UI_Color(UIC_TEXT), alpha); } void CP_QuickFOV(ui_object_t *ob) { Con_SetFloat("rend-camera-fov", sld_fov.value = atoi(ob->text), true); } void CP_VideoModeInfo(ui_object_t *ob) { char buf[80]; if(!strcmp(ob->text, "default")) { sprintf(buf, "%i x %i x %i (%s)", defResX, defResY, defBPP, defFullscreen? "fullscreen":"windowed"); } else { boolean fullscreen; if(!Sys_GetWindowFullscreen(windowIDX, &fullscreen)) return; sprintf(buf, "%i x %i x %i (%s)", theWindow->width, theWindow->height, theWindow->normal.bpp, (fullscreen? "fullscreen" : "windowed")); } FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(buf, ob->x, ob->y + ob->h / 2, false, true, UI_Color(UIC_TEXT), 1); } void CP_UpdateSetVidModeButton(int w, int h, int bpp, boolean fullscreen) { boolean cFullscreen; ui_object_t *ob; if(!Sys_GetWindowFullscreen(windowIDX, &cFullscreen)) return; ob = UI_FindObject(ob_panel, CPG_VIDEO, CPID_SET_RES); bpp = (bpp? 32 : 16); sprintf(ob->text, "%i x %i x %i (%s)", w, h, bpp, fullscreen? "fullscreen" : "windowed"); if(w == theWindow->width && h == theWindow->height && bpp == theWindow->normal.bpp && fullscreen == cFullscreen) ob->flags |= UIF_DISABLED; else ob->flags &= ~UIF_DISABLED; } void CP_ResolutionList(ui_object_t *ob) { uidata_list_t *list = ob->data; int seldata = ((uidata_listitem_t *) list->items)[list->selection].data; sprintf(panel_res_x, "%i", seldata & 0xffff); sprintf(panel_res_y, "%i", seldata >> 16); strcpy(UI_FindObject(ob_panel, ob->group, CPID_RES_X)->text, panel_res_x); strcpy(UI_FindObject(ob_panel, ob->group, CPID_RES_Y)->text, panel_res_y); CP_VidModeChanged(ob); } void CP_SetDefaultVidMode(ui_object_t *ob) { int x = atoi(panel_res_x), y = atoi(panel_res_y); if(!x || !y) return; defResX = x; defResY = y; defBPP = (panel_bpp? 32 : 16); defFullscreen = panel_fullscreen; } void CP_SetVidMode(ui_object_t *ob) { int x = atoi(panel_res_x), y = atoi(panel_res_y); int bpp = (panel_bpp? 32 : 16); if(!x || !y) return; if(x < 320 || y < 240) return; ob->flags |= UIF_DISABLED; Sys_SetWindow(windowIDX, 0, 0, x, y, bpp, (panel_fullscreen? DDWF_FULLSCREEN : 0), DDSW_NOVISIBLE|DDSW_NOCENTER); } void CP_VidModeChanged(ui_object_t *ob) { CP_UpdateSetVidModeButton(atoi(panel_res_x), atoi(panel_res_y), panel_bpp, panel_fullscreen); } /** * Returns the object, if any, the mouse is currently hovering on. The * check is based on the coordinates of the Text object. */ ui_object_t *CP_FindHover(void) { ui_object_t *ob; for(ob = ob_panel; ob->type; ob++) { if(ob->flags & UIF_HIDDEN || ob->type != UI_TEXT || ob->group < 2 || ob->relx < 280) continue; // Extend the detection area to the right edge of the screen. if(UI_MouseInsideBox(ob->x, ob->y, UI_ScreenW(1000), ob->h)) return ob; } return NULL; } /** * Track the mouse and move the documentation window as needed. */ void CP_Ticker(ui_page_t *page) { int off; ui_object_t *ob; void *help; // Normal ticker actions first. UIPage_Ticker(page); // Check if the mouse is inside the options box. ob = UI_FindObject(page->objects, 0, CPID_FRAME); if(!UI_MouseInside(ob) || !panel_show_help) { panel_help_active = false; } else { // The mouse is inside the options box, so we may need to display // the options box or change its text. Detect which object the // mouse is on. if((ob = CP_FindHover())) { // Change the text. if((help = DH_Find(ob->text))) { panel_help = help; panel_help_source = ob; } if(UI_MouseResting(page)) { // The mouse has been paused on a text, activate help. panel_help_active = true; } if(!help) panel_help_active = false; } } // Should we move the help box? off = 0; if(panel_help_active && UI_Alpha() >= 1.0) { if(panel_help_offset < HELP_OFFSET) off = (HELP_OFFSET - panel_help_offset) / 2; if(off < 4) off = 4; } else // Help should be hidden. { if(panel_help_offset > 0) off = -panel_help_offset / 2; if(off > -4) off = -4; } panel_help_offset += off; if(panel_help_offset > HELP_OFFSET) panel_help_offset = HELP_OFFSET; if(panel_help_offset < 0) panel_help_offset = 0; } int CP_LabelText(char *label, char *text, int x, int y, int w, int h, float alpha) { int ind; FR_SetFont(glFontVariable[GLFS_NORMAL]); UI_SetColorA(UI_Color(UIC_TEXT), .5f * alpha * UI_Alpha()); FR_TextOut(label, x, y); ind = FR_TextWidth(label); return UI_TextOutWrapEx(text, x + ind, y, w - ind, h, UI_Color(UIC_TEXT), alpha); } void CP_Drawer(ui_page_t *page) { float alpha = panel_help_offset / (float) HELP_OFFSET; int x, y, w, h, bor; char *str; // First call the regular drawer. UIPage_Drawer(page); // Project home. FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(DOOMSDAY_PROJECTURL, UI_ScreenW(1000) - UI_BORDER - FR_TextWidth(DOOMSDAY_PROJECTURL), UI_ScreenY(25), false, true, UI_Color(UIC_TEXT), 0.4f); // Is the help box visible? if(panel_help_offset <= 0 || !panel_help_source) return; // Help box placement. bor = 2 * UI_BORDER / 3; x = -bor; y = UI_ScreenY(0); w = HELP_OFFSET; h = UI_ScreenH(920); UI_GradientEx(x, y, w, h, bor, UI_Color(UIC_HELP), UI_Color(UIC_HELP), alpha, alpha); UI_DrawRectEx(x, y, w, h, bor, false, UI_Color(UIC_BRD_HI), NULL, alpha, -1); x += 2 * bor; y += 2 * bor; w -= 4 * bor; h -= 4 * bor; // The title (with shadow). FR_SetFont(glFontVariable[GLFS_BOLD]); /*UI_TextOutWrapEx(panel_help_source->text, x + UI_SHADOW_OFFSET, y + UI_SHADOW_OFFSET, w, h, UI_Color(UIC_SHADOW), alpha);*/ y = UI_TextOutWrapEx(panel_help_source->text, x, y, w, h, UI_Color(UIC_TITLE), alpha) + UI_FontHeight() + 3; UI_Line(x, y, x + w, y, UI_Color(UIC_TEXT), 0, alpha * .5f, 0); y += 2; // Cvar? if((str = DH_GetString(panel_help, HST_CONSOLE_VARIABLE))) y = CP_LabelText("CVar: ", str, x, y, w, h, alpha) + UI_FontHeight(); // Default? if((str = DH_GetString(panel_help, HST_DEFAULT_VALUE))) y = CP_LabelText("Default: ", str, x, y, w, h, alpha) + UI_FontHeight(); // Information. if((str = DH_GetString(panel_help, HST_DESCRIPTION))) { y += UI_FontHeight() / 2; FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutWrapEx(str, x, y, w, h, UI_Color(UIC_TEXT), alpha); } } /** * Initializes all slider objects. */ void CP_InitCvarSliders(ui_object_t *ob) { for(; ob->type; ob++) { if(ob->action == CP_CvarSlider) { uidata_slider_t *slid = ob->data; if(slid->floatmode) slid->value = Con_GetFloat(slid->data); else slid->value = Con_GetInteger(slid-> data); } } } /** * Initialize and open the Control Panel. */ D_CMD(OpenPanel) { int i; ui_object_t *ob, *foc; uidata_list_t *list; cvarbutton_t *cvb; Con_Execute(CMDS_DDAY, "conclose", true, false); // The help window is hidden. panel_help_active = false; panel_help_offset = 0; panel_help_source = NULL; UI_InitPage(&page_panel, ob_panel); strcpy(page_panel.title, "Doomsday " DOOMSDAY_VERSION_TEXT " Control Panel"); page_panel.ticker = CP_Ticker; page_panel.drawer = CP_Drawer; if(argc != 2) { // Choose the group that was last visible. foc = NULL; for(i = 0; i < NUM_CP_BUTTONS; ++i) if(panel_buttons[i]) CP_ChooseGroup(foc = ob_panel + i); } else { // With an argument, choose the appropriate group. foc = NULL; for(i = 0; i < NUM_CP_BUTTONS; ++i) { if(!stricmp(ob_panel[i].text, argv[1])) { CP_ChooseGroup(foc = ob_panel + i); break; } } if(!foc) CP_ChooseGroup(foc = ob_panel); } // Set default Yes/No strings. for(cvb = cvarbuttons; cvb->cvarname; cvb++) { if(!cvb->yes) cvb->yes = "Yes"; if(!cvb->no) cvb->no = "No"; } // Set cvarbutton data pointers. // This is only done the first time "panel" is issued. for(i = 0, ob = ob_panel; ob_panel[i].type; ++i, ob++) { if(ob->action == CP_CvarButton) { if(ob->data) { // This button has already been initialized. cvb = ob->data; cvb->active = (Con_GetByte(cvb->cvarname) & (ob->data2? ob->data2 : ~0)) != 0; strcpy(ob->text, cvb->active ? cvb->yes : cvb->no); continue; } // Find the cvarbutton representing this one. for(cvb = cvarbuttons; cvb->cvarname; cvb++) { if(!strcmp(ob->text, cvb->cvarname) && ob->data2 == cvb->mask) { cvb->active = (Con_GetByte(cvb->cvarname) & (ob->data2? ob->data2 : ~0)) != 0; ob->data = cvb; strcpy(ob->text, cvb->active ? cvb->yes : cvb->no); break; } } } else if(ob->action == CP_CvarList) { list = ob->data; // Choose the correct list item based on the value of the cvar. list->selection = UI_ListFindItem(ob, Con_GetInteger(list->data)); } else if(ob->action == CP_CvarEdit) { uidata_edit_t *ed = ob->data; strncpy(ed->ptr, Con_GetString(ed->data), ed->maxlen); } } CP_InitCvarSliders(ob_panel); // Update width the current resolution. { boolean cFullscreen = true; Sys_GetWindowFullscreen(windowIDX, &cFullscreen); ob = UI_FindObject(ob_panel, CPG_VIDEO, CPID_RES_LIST); list = ob->data; list->selection = UI_ListFindItem(ob, RES(theWindow->width, theWindow->height)); if(list->selection == -1) { // Then use a reasonable default. list->selection = UI_ListFindItem(ob, RES(640, 480)); } panel_fullscreen = cFullscreen; panel_bpp = (theWindow->normal.bpp == 32? 1 : 0); CP_ResolutionList(ob); } UI_Init(true, true, false, false, false); UI_SetPage(&page_panel); UI_Focus(foc); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_particle.c0000644000175000017500000006555311357170242023726 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_particle.c: Particle Effects */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_render.h" #include "de_play.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_misc.h" #include "de_ui.h" // MACROS ------------------------------------------------------------------ // Point + custom textures. #define NUM_TEX_NAMES (MAX_PTC_TEXTURES) // TYPES ------------------------------------------------------------------- typedef struct { ptcgenid_t ptcGenID; // Generator id. int ptID; // Particle id. float distance; } porder_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern float vang, vpitch; // PUBLIC DATA DEFINITIONS ------------------------------------------------- DGLuint pointTex, ptctexname[MAX_PTC_TEXTURES]; int particleNearLimit = 0; float particleDiffuse = 4; byte devDrawGenerators = false; // Display active generators? // PRIVATE DATA DEFINITIONS ------------------------------------------------ static size_t numParts; static boolean hasPoints, hasLines, hasModels, hasNoBlend, hasBlend; static boolean hasPointTexs[NUM_TEX_NAMES]; static byte visiblePtcGens[MAX_ACTIVE_PTCGENS]; static size_t orderSize = 0; static porder_t* order = NULL; // CODE -------------------------------------------------------------------- void Rend_ParticleRegister(void) { // Cvars C_VAR_BYTE("rend-particle", &useParticles, 0, 0, 1); C_VAR_INT("rend-particle-max", &maxParticles, CVF_NO_MAX, 0, 0); C_VAR_FLOAT("rend-particle-rate", &particleSpawnRate, 0, 0, 5); C_VAR_FLOAT("rend-particle-diffuse", &particleDiffuse, CVF_NO_MAX, 0, 0); C_VAR_INT("rend-particle-visible-near", &particleNearLimit, CVF_NO_MAX, 0, 0); C_VAR_BYTE("rend-dev-generator-show-indices", &devDrawGenerators, CVF_NO_ARCHIVE, 0, 1); } static boolean markPtcGenVisible(ptcgen_t* gen, void* context) { visiblePtcGens[P_PtcGenToIndex(gen)] = true; return true; // Continue iteration. } static boolean isPtcGenVisible(const ptcgen_t* gen) { return visiblePtcGens[P_PtcGenToIndex(gen)]; } static float pointDist(fixed_t c[3]) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); float dist = ((viewData->current.pos[VY] - FIX2FLT(c[VY])) * -viewData->viewSin) - ((viewData->current.pos[VX] - FIX2FLT(c[VX])) * viewData->viewCos); if(dist < 0) return -dist; // Always return positive. return dist; } byte GL_LoadParticleTexture(image_t* image, const char* name) { filename_t fileName; if(R_FindResource2(RT_GRAPHIC, DDRC_TEXTURE, fileName, name, "-ck", FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName)) { return 2; } return 0; } /** * The particle texture is a modification of the dynlight texture. */ void Rend_ParticleInitTextures(void) { int i; boolean reported; if(pointTex) return; // Already been here. // Load the zeroth texture (the default: a blurred point). pointTex = GL_PrepareExtTexture(DDRC_GRAPHICS, "Zeroth", LGM_WHITE_ALPHA, true, GL_LINEAR, GL_LINEAR, 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); if(pointTex == 0) { Con_Error("Rend_ParticleInitTextures: \"Zeroth\" not found.\n"); } // Load any custom particle textures. They are loaded from the // highres texture directory and are named "ParticleNN.(tga|png|pcx)". // The first is "Particle00". (based on Leesz' textured particles mod) // Clear the texture names array. memset(ptctexname, 0, sizeof(ptctexname)); reported = false; for(i = 0; i < MAX_PTC_TEXTURES; ++i) { image_t image; char name[80]; // Try to load the texture. sprintf(name, "Particle%02i", i); if(GL_LoadParticleTexture(&image, name)) { VERBOSE( Con_Message("Rend_ParticleInitTextures: Texture " "%02i: %i * %i * %i\n", i, image.width, image.height, image.pixelSize)); // If 8-bit with no alpha, generate alpha automatically. if(image.originalBits == 8) { GL_ConvertToAlpha(&image, true); } // Create a new texture and upload the image. ptctexname[i] = GL_NewTextureWithParams( image.pixelSize == 4 ? DGL_RGBA : image.pixelSize == 2 ? DGL_LUMINANCE_PLUS_A8 : DGL_RGB, image.width, image.height, image.pixels, TXCF_NO_COMPRESSION); // Free the buffer. GL_DestroyImage(&image); } else { // Just show the first 'not found'. if(verbose && !reported) { Con_Message("Rend_ParticleInitTextures: %s not found.\n", name); reported = true; } } } } void Rend_ParticleShutdownTextures(void) { glDeleteTextures(1, (const GLuint*) &pointTex); pointTex = 0; glDeleteTextures(NUM_TEX_NAMES, (const GLuint*) ptctexname); memset(ptctexname, 0, sizeof(ptctexname)); } /** * Prepare for rendering a new view of the world. */ void Rend_ParticleInitForNewFrame(void) { if(!useParticles) return; // Clear all visibility flags. memset(visiblePtcGens, 0, MAX_ACTIVE_PTCGENS); } /** * The given sector is visible. All PGs in it should be rendered. * Scans PG links. */ void Rend_ParticleMarkInSectorVisible(sector_t* sector) { if(!useParticles) return; P_IterateSectorLinkedPtcGens(sector, markPtcGenVisible, NULL); } /** * Sorts in descending order. */ static int C_DECL comparePOrder(const void* pt1, const void* pt2) { if(((porder_t *) pt1)->distance > ((porder_t *) pt2)->distance) return -1; else if(((porder_t *) pt1)->distance < ((porder_t *) pt2)->distance) return 1; // Highly unlikely (but possible)... return 0; } /** * Allocate more memory for the particle ordering buffer, if necessary. */ static void checkOrderBuffer(size_t max) { size_t currentSize = orderSize; if(!orderSize) { orderSize = MAX_OF(max, 256); } else { while(max > orderSize) orderSize *= 2; } if(orderSize > currentSize) order = Z_Realloc(order, sizeof(porder_t) * orderSize, PU_STATIC); } static boolean countParticles(ptcgen_t* gen, void* context) { if(isPtcGenVisible(gen)) { int p; size_t* numParts = (size_t*) context; for(p = 0; p < gen->count; ++p) if(gen->ptcs[p].stage >= 0) (*numParts)++; } return true; // Continue iteration. } static boolean populateSortBuffer(ptcgen_t* gen, void* context) { int p; const ded_ptcgen_t* def; particle_t* pt; size_t* m = (size_t*) context; if(!isPtcGenVisible(gen)) return true; // Continue iteration. def = gen->def; for(p = 0, pt = gen->ptcs; p < gen->count; ++p, pt++) { int stagetype; float dist; porder_t* slot; if(pt->stage < 0) continue; // Is the particle's sector visible? if(!(pt->sector->frameFlags & SIF_VISIBLE)) continue; // No; this particle can't be seen. // Don't allow zero distance. dist = MAX_OF(pointDist(pt->pos), 1); if(def->maxDist != 0 && dist > def->maxDist) continue; // Too far. if(dist < (float) particleNearLimit) continue; // Too near. // This particle is visible. Add it to the sort buffer. slot = &order[(*m)++]; slot->ptcGenID = P_PtcGenToIndex(gen); slot->ptID = p; slot->distance = dist; // Determine what type of particle this is, as this will affect how // we go order our render passes and manipulate the render state. stagetype = gen->stages[pt->stage].type; if(stagetype == PTC_POINT) { hasPoints = true; } else if(stagetype == PTC_LINE) { hasLines = true; } else if(stagetype >= PTC_TEXTURE && stagetype < PTC_TEXTURE + MAX_PTC_TEXTURES) { hasPointTexs[stagetype - PTC_TEXTURE] = true; } else if(stagetype >= PTC_MODEL && stagetype < PTC_MODEL + MAX_PTC_MODELS) { hasModels = true; } if(gen->flags & PGF_ADD_BLEND) hasBlend = true; else hasNoBlend = true; } return true; // Continue iteration. } /** * @return @c true if there are particles to render. */ static int listVisibleParticles(void) { size_t numVisibleParticles; hasPoints = hasModels = hasLines = hasBlend = hasNoBlend = false; memset(hasPointTexs, 0, sizeof(hasPointTexs)); // First count how many particles are in the visible generators. numParts = 0; P_IteratePtcGens(countParticles, &numParts); if(!numParts) return false; // No visible generators. // Allocate the particle depth sort buffer. checkOrderBuffer(numParts); // Populate the particle sort buffer and determine what type(s) of // particle (model/point/line/etc...) we'll need to draw. numVisibleParticles = 0; P_IteratePtcGens(populateSortBuffer, &numVisibleParticles); if(!numVisibleParticles) return false; // No visible particles (all too far?). // This is the real number of possibly visible particles. numParts = numVisibleParticles; // Sort the order list back->front. A quicksort is fast enough. qsort(order, numParts, sizeof(porder_t), comparePOrder); return true; } static void setupModelParamsForParticle(rendmodelparams_t* params, const particle_t* pt, const ptcstage_t* st, const ded_ptcstage_t* dst, float* center, float dist, float size, float mark, float alpha) { int frame; subsector_t* ssec; // Render the particle as a model. params->center[VX] = center[VX]; params->center[VY] = center[VZ]; params->center[VZ] = params->gzt = center[VY]; params->distance = dist; ssec = R_PointInSubsector(center[VX], center[VZ]); params->extraScale = size; // Extra scaling factor. params->mf = &modefs[dst->model]; params->alwaysInterpolate = true; if(dst->endFrame < 0) { frame = dst->frame; params->inter = 0; } else { frame = dst->frame + (dst->endFrame - dst->frame) * mark; params->inter = M_CycleIntoRange(mark * (dst->endFrame - dst->frame), 1); } R_SetModelFrame(params->mf, frame); // Set the correct orientation for the particle. if(params->mf->sub[0].flags & MFF_MOVEMENT_YAW) { params->yaw = R_MovementYaw(FIX2FLT(pt->mov[0]), FIX2FLT(pt->mov[1])); } else { params->yaw = pt->yaw / 32768.0f * 180; } if(params->mf->sub[0].flags & MFF_MOVEMENT_PITCH) { params->pitch = R_MovementPitch(pt->mov[0], pt->mov[1], pt->mov[2]); } else { params->pitch = pt->pitch / 32768.0f * 180; } params->ambientColor[CA] = alpha; if((st->flags & PTCF_BRIGHT) || levelFullBright) { params->ambientColor[CR] = params->ambientColor[CG] = params->ambientColor[CB] = 1; params->vLightListIdx = 0; } else { collectaffectinglights_params_t lparams; if(useBias) { LG_Evaluate(params->center, params->ambientColor); } else { float lightLevel = pt->sector->lightLevel; const float* secColor = R_GetSectorLightColor(pt->sector); // Apply distance attenuation. lightLevel = R_DistAttenuateLightLevel(params->distance, lightLevel); // Add extra light. lightLevel += R_ExtraLightDelta(); Rend_ApplyLightAdaptation(&lightLevel); // Determine the final ambientColor in affect. params->ambientColor[CR] = lightLevel * secColor[CR]; params->ambientColor[CG] = lightLevel * secColor[CG]; params->ambientColor[CB] = lightLevel * secColor[CB]; } Rend_ApplyTorchLight(params->ambientColor, params->distance); lparams.starkLight = false; lparams.center[VX] = params->center[VX]; lparams.center[VY] = params->center[VY]; lparams.center[VZ] = params->center[VZ]; lparams.subsector = ssec; lparams.ambientColor = params->ambientColor; params->vLightListIdx = R_CollectAffectingLights(&lparams); } } static void renderParticles(int rtype, boolean withBlend) { size_t i; int c; DGLuint tex = 0; float leftoff[3], rightoff[3]; ushort primType = GL_QUADS; blendmode_t mode = BM_NORMAL, newMode; { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); // viewSideVec points to the left. for(c = 0; c < 3; ++c) { leftoff[c] = viewData->upVec[c] + viewData->sideVec[c]; rightoff[c] = viewData->upVec[c] - viewData->sideVec[c]; } } // Should we use a texture? if(rtype == PTC_POINT || (rtype >= PTC_TEXTURE && rtype < PTC_TEXTURE + MAX_PTC_TEXTURES)) { if(renderTextures) { if(rtype == PTC_POINT || !ptctexname[rtype - PTC_TEXTURE]) tex = pointTex; else tex = ptctexname[rtype - PTC_TEXTURE]; } } if(rtype == PTC_MODEL) { glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); } else if(tex != 0) { glDepthMask(GL_FALSE); glDisable(GL_CULL_FACE); glBindTexture(GL_TEXTURE_2D, tex); glDepthFunc(GL_LEQUAL); glBegin(primType = GL_QUADS); } else { glDisable(GL_TEXTURE_2D); // Lines don't use textures. glBegin(primType = GL_LINES); } // How many particles can we render? if(maxParticles) i = numParts - (unsigned) maxParticles; else i = 0; for(; i < numParts; ++i) { const porder_t* slot = &order[i]; const ptcgen_t* gen; const particle_t* pt; const ptcstage_t* st; const ded_ptcstage_t* dst, *nextDst; float size, color[4], center[3], mark, invMark; float dist, maxdist, projected[2]; boolean flatOnPlane, flatOnWall, nearPlane, nearWall; gen = P_IndexToPtcGen(slot->ptcGenID); pt = &gen->ptcs[slot->ptID]; st = &gen->stages[pt->stage]; dst = &gen->def->stages[pt->stage]; // Only render one type of particles. if((rtype == PTC_MODEL && dst->model < 0) || (rtype != PTC_MODEL && st->type != rtype)) { continue; } if(!(gen->flags & PGF_ADD_BLEND) == withBlend) continue; if(rtype != PTC_MODEL && !withBlend) { // We may need to change the blending mode. newMode = (gen->flags & PGF_SUB_BLEND ? BM_SUBTRACT : gen-> flags & PGF_REVSUB_BLEND ? BM_REVERSE_SUBTRACT : gen-> flags & PGF_MUL_BLEND ? BM_MUL : gen-> flags & PGF_INVMUL_BLEND ? BM_INVERSE_MUL : BM_NORMAL); if(newMode != mode) { glEnd(); GL_BlendMode(mode = newMode); glBegin(primType); } } // Is there a next stage for this particle? if(pt->stage >= gen->def->stageCount.num - 1 || !gen->stages[pt->stage + 1].type) { // There is no "next stage". Use the current one. nextDst = gen->def->stages + pt->stage; } else nextDst = gen->def->stages + (pt->stage + 1); // Where is intermark? invMark = pt->tics / (float) dst->tics; mark = 1 - invMark; // Calculate size and color. size = P_GetParticleRadius(dst, slot->ptID) * invMark + P_GetParticleRadius(nextDst, slot->ptID) * mark; if(!size) continue; // Infinitely small. for(c = 0; c < 4; ++c) { color[c] = dst->color[c] * invMark + nextDst->color[c] * mark; if(!(st->flags & PTCF_BRIGHT) && c < 3 && !levelFullBright) { // This is a simplified version of sectorlight (no distance // attenuation or range compression). if(pt->sector) color[c] *= pt->sector->lightLevel; } } maxdist = gen->def->maxDist; dist = order[i].distance; // Far diffuse? if(maxdist) { if(dist > maxdist * .75f) color[3] *= 1 - (dist - maxdist * .75f) / (maxdist * .25f); } // Near diffuse? if(particleDiffuse > 0) { if(dist < particleDiffuse * size) color[3] -= 1 - dist / (particleDiffuse * size); } // Fully transparent? if(color[3] <= 0) continue; glColor4fv(color); nearPlane = (pt->sector && (FLT2FIX(pt->sector->SP_floorheight) + 2 * FRACUNIT >= pt->pos[VZ] || FLT2FIX(pt->sector->SP_ceilheight) - 2 * FRACUNIT <= pt->pos[VZ])); flatOnPlane = (st->flags & PTCF_PLANE_FLAT && nearPlane); nearWall = (pt->contact && !pt->mov[VX] && !pt->mov[VY]); flatOnWall = (st->flags & PTCF_WALL_FLAT && nearWall); center[VX] = FIX2FLT(pt->pos[VX]); center[VZ] = FIX2FLT(pt->pos[VY]); center[VY] = P_GetParticleZ(pt); if(!flatOnPlane && !flatOnWall) { center[VX] += frameTimePos * FIX2FLT(pt->mov[VX]); center[VZ] += frameTimePos * FIX2FLT(pt->mov[VY]); if(!nearPlane) center[VY] += frameTimePos * FIX2FLT(pt->mov[VZ]); } // Model particles are rendered using the normal model rendering // routine. if(rtype == PTC_MODEL && dst->model >= 0) { rendmodelparams_t params; memset(¶ms, 0, sizeof(rendmodelparams_t)); setupModelParamsForParticle(¶ms, pt, st, dst, center, dist, size, mark, color[CA]); Rend_RenderModel(¶ms); continue; } // The vertices, please. if(tex != 0) { // Should the particle be flat against a plane? if(flatOnPlane) { glTexCoord2f(0, 0); glVertex3f(center[VX] - size, center[VY], center[VZ] - size); glTexCoord2f(1, 0); glVertex3f(center[VX] + size, center[VY], center[VZ] - size); glTexCoord2f(1, 1); glVertex3f(center[VX] + size, center[VY], center[VZ] + size); glTexCoord2f(0, 1); glVertex3f(center[VX] - size, center[VY], center[VZ] + size); } // Flat against a wall, then? else if(flatOnWall) { float line[2], pos[2]; vertex_t* vtx; line[0] = pt->contact->dX; line[1] = pt->contact->dY; vtx = pt->contact->L_v1; // There will be a slight approximation on the XY plane since // the particles aren't that accurate when it comes to wall // collisions. // Calculate a new center point (project onto the wall). // Also move 1 unit away from the wall to avoid the worst // Z-fighting. pos[VX] = FIX2FLT(pt->pos[VX]); pos[VY] = FIX2FLT(pt->pos[VY]); M_ProjectPointOnLine(pos, &vtx->V_pos[VX], line, 1, projected); P_LineUnitVector(pt->contact, line); glTexCoord2f(0, 0); glVertex3f(projected[VX] - size * line[VX], center[VY] - size, projected[VY] - size * line[VY]); glTexCoord2f(1, 0); glVertex3f(projected[VX] - size * line[VX], center[VY] + size, projected[VY] - size * line[VY]); glTexCoord2f(1, 1); glVertex3f(projected[VX] + size * line[VX], center[VY] + size, projected[VY] + size * line[VY]); glTexCoord2f(0, 1); glVertex3f(projected[VX] + size * line[VX], center[VY] - size, projected[VY] + size * line[VY]); } else { glTexCoord2f(0, 0); glVertex3f(center[VX] + size * leftoff[VX], center[VY] + size * leftoff[VY] / 1.2f, center[VZ] + size * leftoff[VZ]); glTexCoord2f(1, 0); glVertex3f(center[VX] + size * rightoff[VX], center[VY] + size * rightoff[VY] / 1.2f, center[VZ] + size * rightoff[VZ]); glTexCoord2f(1, 1); glVertex3f(center[VX] - size * leftoff[VX], center[VY] - size * leftoff[VY] / 1.2f, center[VZ] - size * leftoff[VZ]); glTexCoord2f(0, 1); glVertex3f(center[VX] - size * rightoff[VX], center[VY] - size * rightoff[VY] / 1.2f, center[VZ] - size * rightoff[VZ]); } } else // It's a line. { glVertex3f(center[VX], center[VY], center[VZ]); glVertex3f(center[VX] - FIX2FLT(pt->mov[VX]), center[VY] - FIX2FLT(pt->mov[VZ]), center[VZ] - FIX2FLT(pt->mov[VY])); } } if(rtype != PTC_MODEL) { glEnd(); if(tex != 0) { glEnable(GL_CULL_FACE); glDepthMask(GL_TRUE); glDepthFunc(GL_LESS); } else { glEnable(GL_TEXTURE_2D); } } if(!withBlend) { // We may have rendered subtractive stuff. GL_BlendMode(BM_NORMAL); } } static void renderPass(boolean useBlending) { int i; // Set blending mode. if(useBlending) GL_BlendMode(BM_ADD); if(hasModels) renderParticles(PTC_MODEL, useBlending); if(hasLines) renderParticles(PTC_LINE, useBlending); if(hasPoints) renderParticles(PTC_POINT, useBlending); for(i = 0; i < NUM_TEX_NAMES; ++i) if(hasPointTexs[i]) { renderParticles(PTC_TEXTURE + i, useBlending); } // Restore blending mode. if(useBlending) GL_BlendMode(BM_NORMAL); } /** * Render all the visible particle generators. * We must render all particles ordered back->front, or otherwise * particles from one generator will obscure particles from another. * This would be especially bad with smoke trails. */ void Rend_RenderParticles(void) { if(!useParticles) return; if(!listVisibleParticles()) return; // No visible particles at all? // Render all the visible particles. if(hasNoBlend) { renderPass(false); } if(hasBlend) { // A second pass with additive blending. // This makes the additive particles 'glow' through all other // particles. renderPass(true); } } static boolean drawGeneratorOrigin(ptcgen_t* gen, void* context) { #define MAX_GENERATOR_DIST 2048 float* eye = (float*) context; // Determine approximate center. if((gen->source || (gen->flags & PGF_UNTRIGGERED))) { float pos[3], dist, alpha; if(gen->source) { pos[VX] = gen->source->pos[VX]; pos[VY] = gen->source->pos[VY]; pos[VZ] = gen->source->pos[VZ] - gen->source->floorClip + FIX2FLT(gen->center[VZ]); } else { pos[VX] = FIX2FLT(gen->center[VX]); pos[VY] = FIX2FLT(gen->center[VY]); pos[VZ] = FIX2FLT(gen->center[VZ]); } dist = M_Distance(pos, eye); alpha = 1 - MIN_OF(dist, MAX_GENERATOR_DIST) / MAX_GENERATOR_DIST; if(alpha > 0) { char buf[80]; float scale = dist / (theWindow->width / 2); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(pos[VX], pos[VZ], pos[VY]); glRotatef(-vang + 180, 0, 1, 0); glRotatef(vpitch, 1, 0, 0); glScalef(-scale, -scale, 1); sprintf(buf, "%i", P_PtcGenToIndex(gen)); UI_TextOutEx(buf, 2, 2, false, false, UI_Color(UIC_TITLE), alpha); glMatrixMode(GL_MODELVIEW); glPopMatrix(); } } return true; // Continue iteration. #undef MAX_GENERATOR_DIST } /** * Debugging aid; Draw all active generators. */ void Rend_RenderGenerators(void) { float eye[3]; if(!devDrawGenerators) return; glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); eye[VX] = vx; eye[VY] = vz; eye[VZ] = vy; P_IteratePtcGens(drawGeneratorOrigin, eye); // Restore previous state. glEnable(GL_DEPTH_TEST); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/net_main.c0000644000175000017500000012462511357170242022701 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_main.c: Client/server networking. * * Player number zero is always the server. * In single-player games there is only the server present. */ // HEADER FILES ------------------------------------------------------------ #include // for atoi() #include "de_base.h" #include "de_console.h" #include "de_edit.h" #include "de_system.h" #include "de_network.h" #include "de_play.h" #include "de_graphics.h" #include "de_misc.h" #include "de_ui.h" #include "rend_bias.h" #include "rend_console.h" #include "r_lgrid.h" // MACROS ------------------------------------------------------------------ #define OBSOLETE CVF_NO_ARCHIVE|CVF_HIDE // Old ccmds. // The threshold is the average ack time * mul. #define ACK_THRESHOLD_MUL 1.5f // Never wait a too short time for acks. #define ACK_MINIMUM_THRESHOLD 50 // TYPES ------------------------------------------------------------------- typedef struct connectparam_s { char address[256]; int port; serverinfo_t info; } connectparam_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- D_CMD(HuffmanStats); // in net_buf.c D_CMD(Login); // in cl_main.c D_CMD(Logout); // in sv_main.c D_CMD(Ping); // in net_ping.c void R_DrawLightRange(void); int Sv_GetRegisteredMobj(pool_t *, thid_t, mobjdelta_t *); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(Connect); D_CMD(Chat); D_CMD(Kick); D_CMD(MakeCamera); D_CMD(Net); D_CMD(SetConsole); D_CMD(SetName); D_CMD(SetTicks); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- char *serverName = "Doomsday"; char *serverInfo = "Multiplayer Host"; char *playerName = "Player"; int serverData[3]; // Some parameters passed to master server. client_t clients[DDMAXPLAYERS]; // All network data for the players. int netGame; // true if a netGame is in progress int isServer; // true if this computer is an open server. int isClient; // true if this computer is a client // Gotframe is true if a frame packet has been received. int gotFrame = false; boolean firstNetUpdate = true; byte monitorMsgQueue = false; byte netShowLatencies = false; byte netDev = false; byte netDontSleep = false; byte netTicSync = true; float netConnectTime; int netCoordTime = 17; float netConnectTimeout = 10; // Local packets are stored into this buffer. boolean reboundPacket; netbuffer_t reboundStore; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int coordTimer = 0; // CODE -------------------------------------------------------------------- void Net_Register(void) { // Cvars C_VAR_BYTE("net-queue-show", &monitorMsgQueue, 0, 0, 1); C_VAR_BYTE("net-dev", &netDev, 0, 0, 1); C_VAR_BYTE("net-nosleep", &netDontSleep, 0, 0, 1); C_VAR_CHARPTR("net-master-address", &masterAddress, 0, 0, 0); C_VAR_INT("net-master-port", &masterPort, 0, 0, 65535); C_VAR_CHARPTR("net-master-path", &masterPath, 0, 0, 0); C_VAR_CHARPTR("net-name", &playerName, 0, 0, 0); // Cvars (client) C_VAR_INT("client-pos-interval", &netCoordTime, CVF_NO_MAX, 0, 0); C_VAR_FLOAT("client-connect-timeout", &netConnectTimeout, CVF_NO_MAX, 0, 0); // Cvars (server) C_VAR_CHARPTR("server-name", &serverName, 0, 0, 0); C_VAR_CHARPTR("server-info", &serverInfo, 0, 0, 0); C_VAR_INT("server-public", &masterAware, 0, 0, 1); C_VAR_CHARPTR("server-password", &netPassword, 0, 0, 0); C_VAR_BYTE("server-latencies", &netShowLatencies, 0, 0, 1); C_VAR_INT("server-frame-interval", &frameInterval, CVF_NO_MAX, 0, 0); C_VAR_INT("server-player-limit", &svMaxPlayers, 0, 0, DDMAXPLAYERS); // Ccmds C_CMD("chat", NULL, Chat); C_CMD("chatnum", NULL, Chat); C_CMD("chatto", NULL, Chat); C_CMD("conlocp", "i", MakeCamera); C_CMD_FLAGS("connect", NULL, Connect, CMDF_NO_DEDICATED); C_CMD("huffman", "", HuffmanStats); C_CMD("kick", "i", Kick); C_CMD("login", NULL, Login); C_CMD("logout", "", Logout); C_CMD("net", NULL, Net); C_CMD("ping", NULL, Ping); C_CMD("say", NULL, Chat); C_CMD("saynum", NULL, Chat); C_CMD("sayto", NULL, Chat); C_CMD("setname", "s", SetName); C_CMD("setcon", "i", SetConsole); C_CMD("settics", "i", SetTicks); N_Register(); } void Net_Init(void) { Net_AllocArrays(); memset(&netBuffer, 0, sizeof(netBuffer)); netBuffer.headerLength = netBuffer.msg.data - (byte *) &netBuffer.msg; // The game is always started in single-player mode. netGame = false; } void Net_Shutdown(void) { netGame = false; N_Shutdown(); Net_DestroyArrays(); } /** * Part of the Doomsday public API. * * @return The name of the specified player. */ const char* Net_GetPlayerName(int player) { return clients[player].name; } /** * Part of the Doomsday public API. * * @return Client identifier for the specified player. */ ident_t Net_GetPlayerID(int player) { if(!clients[player].connected) return 0; return clients[player].id; } /** * Sends the contents of the netBuffer. */ void Net_SendBuffer(int toPlayer, int spFlags) { // Don't send anything during demo playback. if(playback) return; // Update the length of the message. netBuffer.length = netBuffer.cursor - netBuffer.msg.data; netBuffer.player = toPlayer; // A rebound packet? if(spFlags & SPF_REBOUND) { reboundStore = netBuffer; reboundPacket = true; return; } Demo_WritePacket(toPlayer); // Can we send the packet? if(spFlags & SPF_DONT_SEND) return; // Send the packet to the network. N_SendPacket(spFlags); } /** * @return @C false, if there are no packets waiting. */ boolean Net_GetPacket(void) { if(reboundPacket) // Local packets rebound. { netBuffer = reboundStore; netBuffer.player = consolePlayer; netBuffer.cursor = netBuffer.msg.data; reboundPacket = false; return true; } if(playback) { // We're playing a demo. This overrides all other packets. return Demo_ReadPacket(); } if(!netGame) { // Packets cannot be received. return false; } if(!N_GetPacket()) return false; // Are we recording a demo? if(isClient && clients[consolePlayer].recording) Demo_WritePacket(consolePlayer); // Reset the cursor for Msg_* routines. netBuffer.cursor = netBuffer.msg.data; return true; } /** * This is the public interface of the message sender. */ void Net_SendPacket(int to_player, int type, void *data, size_t length) { int flags = 0; // What kind of delivery to use? if(to_player & DDSP_CONFIRM) flags |= SPF_CONFIRM; if(to_player & DDSP_ORDERED) flags |= SPF_ORDERED; Msg_Begin(type); if(data) Msg_Write(data, length); if(isClient) { // As a client we can only send messages to the server. Net_SendBuffer(0, flags); } else { // The server can send packets to any player. // Only allow sending to the sixteen possible players. Net_SendBuffer(to_player & DDSP_ALL_PLAYERS ? NSP_BROADCAST : (to_player & 0xf), flags); } } /** * Prints the message in the console. */ void Net_ShowChatMessage(void) { // The current packet in the netBuffer is a chat message, let's unwrap // and show it. Con_FPrintf(CBLF_GREEN, "%s: %s\n", clients[netBuffer.msg.data[0]].name, netBuffer.msg.data + 3); } /** * After a long period with no updates (map setup), calling this will reset * the tictimer so that no time seems to have passed. */ void Net_ResetTimer(void) { firstNetUpdate = true; } /** * @return @c true, if the specified player is a real, local * player. */ boolean Net_IsLocalPlayer(int plrNum) { player_t *plr = &ddPlayers[plrNum]; return plr->shared.inGame && (plr->shared.flags & DDPF_LOCAL); } /** * Send the local player(s) ticcmds to the server. */ void Net_SendCommands(void) { uint i; byte *msg; ticcmd_t *cmd; if(isDedicated) return; // Send the commands of all local players. for(i = 0; i < DDMAXPLAYERS; ++i) { if(!Net_IsLocalPlayer(i)) continue; /** * Clients send their ticcmds to the server at regular intervals, * but significantly less often than new ticcmds are built. * Therefore they need to send a combination of all the cmds built * during the wait period. */ cmd = clients[i].aggregateCmd; /** * The game will pack the commands into a buffer. The returned * pointer points to a buffer that contains its size and the * packed commands. */ msg = gx.NetWriteCommands(1, cmd); Msg_Begin(PCL_COMMANDS); Msg_Write(msg + 2, *(ushort *) msg); /** * Send the packet to the server, i.e. player zero. * Player commands are sent over TCP so their integrity and order * are guaranteed. */ Net_SendBuffer(0, (isClient ? 0 : SPF_REBOUND) | SPF_ORDERED); // Clients will begin composing a new aggregate now that this one // has been sent. memset(cmd, 0, TICCMD_SIZE); } } static void Net_DoUpdate(void) { static int lastTime = 0; int nowTime, newTics; /** * This timing is only used by the client when it determines if it is * time to send ticcmds or coordinates to the server. */ // Check time. nowTime = Sys_GetTime(); // Clock reset? if(firstNetUpdate) { firstNetUpdate = false; lastTime = nowTime; } newTics = nowTime - lastTime; if(newTics <= 0) return; // Nothing new to update. lastTime = nowTime; #if 0 // Build new ticcmds for console player. for(i = 0; i < newtics; ++i) { DD_ProcessEvents(); /*Con_Printf("mktic:%i gt:%i newtics:%i >> %i\n", maketic, gametic, newtics, maketic-gametic); */ if(playback) { numlocal = 0; if(availableTics < LOCALTICS) availableTics++; } else if(!isDedicated && !ui_active) { // Place the new ticcmd in the local ticcmds buffer. ticcmd_t *cmd = Net_LocalCmd(); if(cmd) { gx.BuildTicCmd(cmd); // Set the time stamp. Only the lowest byte is stored. //cmd->time = gametic + availableTics; // Availabletics counts the tics that have cmds. availableTics++; if(isClient) { // When not playing a demo, this is the last command. // It is used in local movement prediction. memcpy(clients[consolePlayer].lastCmd, cmd, sizeof(*cmd)); } } } } #endif // This is as far as dedicated servers go. if(isDedicated) return; /** * Clients will periodically send their coordinates to the server so * any prediction errors can be fixed. Client movement is almost * entirely local. */ coordTimer -= newTics; if(isClient && allowFrames && coordTimer < 0 && ddPlayers[consolePlayer].shared.mo) { mobj_t *mo = ddPlayers[consolePlayer].shared.mo; coordTimer = netCoordTime; // 35/2 Msg_Begin(PKT_COORDS); Msg_WriteShort((short) mo->pos[VX]); Msg_WriteShort((short) mo->pos[VY]); if(mo->pos[VZ] == mo->floorZ) { // This'll keep us on the floor even in fast moving sectors. Msg_WriteShort(DDMININT >> 16); } else { Msg_WriteShort((short) mo->pos[VZ]); } Net_SendBuffer(0, 0); } } /** * Handle incoming packets, clients send ticcmds and coordinates to * the server. */ void Net_Update(void) { Net_DoUpdate(); // Listen for packets. Call the correct packet handler. N_Listen(); if(isClient) Cl_GetPackets(); else // Single-player or server. Sv_GetPackets(); } /** * Build a ticcmd for the local player. */ void Net_BuildLocalCommands(timespan_t time) { uint i; ticcmd_t *cmd; if(isDedicated) return; // Generate ticcmds for local players. for(i = 0; i < DDMAXPLAYERS; ++i) { if(!Net_IsLocalPlayer(i)) continue; cmd = clients[i].lastCmd; // The command will stay 'empty' if no controls are active. memset(cmd, 0, sizeof(*cmd)); // No actions can be undertaken during demo playback or when // in UI mode. if(!(playback || UI_IsActive())) { P_BuildCommand(cmd, i); } // Be sure to merge each built command into the aggregate that // will be sent periodically to the server. P_MergeCommand(clients[i].aggregateCmd, cmd); } } /** * Called from Net_Init to initialize the ticcmd arrays. */ void Net_AllocArrays(void) { int i; #if 0 // Local ticcmds are stored into this array before they're copied // to netplayer[0]'s ticcmds buffer. localticcmds = M_Calloc(LOCALTICS * TICCMD_SIZE); numlocal = 0; // Nothing in the buffer. #endif for(i = 0; i < DDMAXPLAYERS; ++i) { memset(clients + i, 0, sizeof(clients[i])); // The server stores ticcmds sent by the clients to these // buffers. clients[i].ticCmds = M_Calloc(BACKUPTICS * TICCMD_SIZE); // The last cmd that was executed is stored here. clients[i].lastCmd = M_Calloc(TICCMD_SIZE); clients[i].aggregateCmd = M_Calloc(TICCMD_SIZE); clients[i].runTime = -1; } } void Net_DestroyArrays(void) { int i; #if 0 M_Free(localticcmds); localticcmds = NULL; #endif for(i = 0; i < DDMAXPLAYERS; ++i) { M_Free(clients[i].ticCmds); M_Free(clients[i].lastCmd); M_Free(clients[i].aggregateCmd); clients[i].ticCmds = NULL; clients[i].lastCmd = NULL; clients[i].aggregateCmd = NULL; } } /** * This is the network one-time initialization (into single-player mode). */ void Net_InitGame(void) { Cl_InitID(); // In single-player mode there is only player number zero. consolePlayer = displayPlayer = 0; // We're in server mode if we aren't a client. isServer = true; // Netgame is true when we're aware of the network (i.e. other players). netGame = false; ddPlayers[0].shared.inGame = true; ddPlayers[0].shared.flags |= DDPF_LOCAL; clients[0].id = clientID; clients[0].ready = true; clients[0].connected = true; clients[0].viewConsole = 0; clients[0].lastTransmit = -1; // Are we timing a demo here? if(ArgCheck("-timedemo")) netTicSync = false; } void Net_StopGame(void) { int i; if(isServer) { // We are an open server. // This means we should inform all the connected clients that the // server is about to close. Msg_Begin(PSV_SERVER_CLOSE); Net_SendBuffer(NSP_BROADCAST, SPF_CONFIRM); N_FlushOutgoing(); } else { // We are a connected client. // Must stop recording, we're disconnecting. Demo_StopRecording(consolePlayer); Cl_CleanUp(); isClient = false; } // Netgame has ended. netGame = false; isServer = true; allowSending = false; // No more remote users. netRemoteUser = 0; netLoggedIn = false; // All remote players are forgotten. for(i = 0; i < DDMAXPLAYERS; ++i) { player_t *plr = &ddPlayers[i]; client_t *cl = &clients[i]; plr->shared.inGame = false; cl->ready = cl->connected = false; cl->nodeID = 0; plr->shared.flags &= ~(DDPF_CAMERA | DDPF_CHASECAM | DDPF_LOCAL); } // We're about to become player zero, so update it's view angles to // match our current ones. if(ddPlayers[0].shared.mo) { /* $unifiedangles */ ddPlayers[0].shared.mo->angle = ddPlayers[consolePlayer].shared.mo->angle; ddPlayers[0].shared.lookDir = ddPlayers[consolePlayer].shared.lookDir; } consolePlayer = displayPlayer = 0; ddPlayers[0].shared.inGame = true; clients[0].ready = true; clients[0].connected = true; clients[0].viewConsole = 0; ddPlayers[0].shared.flags |= DDPF_LOCAL; } /** * @return Delta based on 'now' (- future, + past). */ int Net_TimeDelta(byte now, byte then) { int delta; if(now >= then) { // Simple case. delta = now - then; } else { // There's a wraparound. delta = 256 - then + now; } // The time can be in the future. We'll allow one second. if(delta > 220) delta -= 256; return delta; } /** * This is a bit complicated and quite possibly unnecessarily so. The * idea is, however, that because the ticcmds sent by clients arrive in * bursts, we'll preserve the motion by 'executing' the commands in the * same order in which they were generated. If the client's connection * lags a lot, the difference between the serverside and clientside * positions will be *large*, especially when the client is running. * If too many commands are buffered, the client's coord announcements * will be processed before the actual movement commands, resulting in * serverside warping (which is perceived by all other clients). */ int Net_GetTicCmd(void *pCmd, int player) { client_t *client = &clients[player]; ticcmd_t *cmd = pCmd; /* int doMerge = false; int future; */ if(client->numTics <= 0) { // No more commands for this player. return false; } // Return the next ticcmd from the buffer. // There will be one less tic in the buffer after this. client->numTics--; memcpy(cmd, &client->ticCmds[TICCMD_IDX(client->firstTic++)], TICCMD_SIZE); // This is the new last command. memcpy(client->lastCmd, cmd, TICCMD_SIZE); // Make sure the firsttic index is in range. client->firstTic %= BACKUPTICS; return true; #if 0 /* #if _DEBUG Con_Printf("GetTicCmd: Cl=%i, GT=%i (%i)...\n", player, gametic, (byte)gametic); // Check the lag stress. if(cl->lagStress > net_stressmargin) { // Command lag should be increased, we're running out of cmds. cl->lagStress -= net_stressmargin; memcpy(cmd, cl->lastcmd, TICCMD_SIZE); // Repeat lastcmd. Con_Printf(" Increasing lag\n"); return true; } else if(cl->lagStress < -net_stressmargin) { // Command lag should be decreased. cl->lagStress += net_stressmargin; cl->runTime++; Con_Printf(" Decreasing lag\n"); } #endif */ for(;;) { if(Net_TimeDelta(gametic, cl->runTime) <= 0) { /* #if _DEBUG Con_Printf(" Running in the future! Rt=%i\n", cl->runTime); #endif */ future = true; //cl->lagStress++; } else { future = false; } // Are there any commands left for this player? if(!cl->numtics) { cl->lagStress++; // Reuse the last command. memcpy(cmd, cl->lastcmd, TICCMD_SIZE); // Runtime advances. if(!future) cl->runTime++; /* #if _DEBUG Con_Printf(" Out of Cmds! Rt set to %i\n", cl->runTime); #endif */ return false; } // There's at least one command in the buffer. // There will be one less tic in the buffer after this. cl->numtics--; memcpy(cmd, &cl->ticcmds[TICCMD_IDX(cl->firsttic++)], TICCMD_SIZE); // Make sure the firsttic iterator is in range. if(cl->firsttic >= BACKUPTICS) cl->firsttic = 0; // Do we need to do any merging? if(doMerge && gx.DiscardTicCmd) gx.DiscardTicCmd(cl->lastcmd, cmd); // This is the new last command. memcpy(cl->lastcmd, cmd, TICCMD_SIZE); // Check that the command is valid (not if its tick has already passed). if(Net_TimeDelta(cl->runTime, cmd->time) >= 0) { /* #if _DEBUG Con_Printf(" Obsolete Cmd! Rt=%i Ct=%i\n", cl->runTime, cmd->time); #endif */ // Cmd is too old. Go to next command and merge this one with it. doMerge = true; continue; } cl->runTime = cmd->time; // Note command lag. cl->lag = Sv_Latency(cmd->time); // The local player doesn't need lag stress, because we know it's // always running exactly synced with the server, i.e. itself. if(player && cl->numtics > 1) cl->lagStress--; /* #if _DEBUG Con_Printf(" CmdLag=%i\n", cl->lag); #endif */ break; } return true; #endif } /** * Does drawing for the engine's HUD, not just the net. */ void Net_Drawer(void) { char buf[160], tmp[40]; int i, c; boolean showBlinkR = false; for(i = 0; i < DDMAXPLAYERS; ++i) { if(ddPlayers[i].shared.inGame && clients[i].recording) showBlinkR = true; } // Draw the Shadow Bias Editor HUD (if it is active). SBE_DrawHUD(); // Draw lightgrid debug display. LG_Debug(); // Draw the blockmap debug display. P_BlockmapDebug(); // Draw the light range debug display. R_DrawLightRange(); if(!netDev && !showBlinkR && !consoleShowFPS) return; // Go into screen projection mode. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); if(showBlinkR && SECONDS_TO_TICKS(gameTime) & 8) { strcpy(buf, "["); for(i = c = 0; i < DDMAXPLAYERS; ++i) { if(!(!ddPlayers[i].shared.inGame || !clients[i].recording)) { // This is a "real" player (or camera). if(c++) strcat(buf, ","); sprintf(tmp, "%i:%s", i, clients[i].recordPaused ? "-P-" : "REC"); strcat(buf, tmp); } } strcat(buf, "]"); i = theWindow->width - FR_TextWidth(buf); //glColor3f(0, 0, 0); //FR_TextOut(buf, i - 8, 12); glColor3f(1, 1, 1); FR_ShadowTextOut(buf, i - 10, 10); } if(netDev) { /* glColor3f(1, 1, 1); sprintf(buf, "G%i", gametic); FR_TextOut(buf, 10, 10); for(i = 0, cl = clients; ilag, cl->lagStress, cl->numtics, cl->runTime, ddPlayers[i].flags); FR_TextOut(buf, 10, 10+10*(i+1)); } */ } Rend_ConsoleFPS(theWindow->width - 10, 30); // Restore original matrix. glMatrixMode(GL_PROJECTION); glPopMatrix(); } /** * Maintain the ack threshold average. */ void Net_SetAckTime(int clientNumber, uint period) { client_t *client = &clients[clientNumber]; // Add the new time into the array. client->ackTimes[client->ackIdx++] = period; client->ackIdx %= NUM_ACK_TIMES; #ifdef _DEBUG VERBOSE( Con_Printf("Net_SetAckTime: Client %i, new ack sample of %05u ms.\n", clientNumber, period) ); #endif } /** * @return The average ack time of the client. */ uint Net_GetAckTime(int clientNumber) { client_t *client = &clients[clientNumber]; uint average = 0; int i, count = 0; uint smallest = 0, largest = 0; // Find the smallest and largest so that they can be ignored. smallest = largest = client->ackTimes[0]; for(i = 0; i < NUM_ACK_TIMES; ++i) { if(client->ackTimes[i] < smallest) smallest = client->ackTimes[i]; if(client->ackTimes[i] > largest) largest = client->ackTimes[i]; } // Calculate the average. for(i = 0; i < NUM_ACK_TIMES; ++i) { if(client->ackTimes[i] != largest && client->ackTimes[i] != smallest) { average += client->ackTimes[i]; count++; } } if(count > 0) { return average / count; } else { return client->ackTimes[0]; } } /** * Sets all the ack times. Used to initial the ack times for new clients. */ void Net_SetInitialAckTime(int clientNumber, uint period) { int i; for(i = 0; i < NUM_ACK_TIMES; ++i) { clients[clientNumber].ackTimes[i] = period; } } /** * The ack threshold is the maximum period of time to wait before * deciding an ack is not coming. The minimum threshold is 50 ms. */ uint Net_GetAckThreshold(int clientNumber) { uint threshold = Net_GetAckTime(clientNumber) * ACK_THRESHOLD_MUL; if(threshold < ACK_MINIMUM_THRESHOLD) { threshold = ACK_MINIMUM_THRESHOLD; } return threshold; } void Net_Ticker(void /*timespan_t time*/) { int i; client_t *cl; // Network event ticker. N_NETicker(); if(netDev) { static int printTimer = 0; if(printTimer++ > TICSPERSEC) { printTimer = 0; for(i = 0; i < DDMAXPLAYERS; ++i) { if(Sv_IsFrameTarget(i)) { Con_Message("%i(rdy%i): avg=%05ims thres=%05ims " "bwr=%05i (adj:%i) maxfs=%05lub unakd=%05i\n", i, clients[i].ready, Net_GetAckTime(i), Net_GetAckThreshold(i), clients[i].bandwidthRating, clients[i].bwrAdjustTime, (unsigned long) Sv_GetMaxFrameSize(i), Sv_CountUnackedDeltas(i)); } /*if(ddPlayers[i].inGame) Con_Message("%i: cmds=%i\n", i, clients[i].numTics);*/ } } } // The following stuff is only for netgames. if(!netGame) return; // Check the pingers. for(i = 0, cl = clients; i < DDMAXPLAYERS; ++i, cl++) { // Clients can only ping the server. if(!(isClient && i) && i != consolePlayer) { if(cl->ping.sent) { // The pinger is active. if(Sys_GetRealTime() - cl->ping.sent > PING_TIMEOUT) // Timed out? { cl->ping.times[cl->ping.current] = -1; Net_SendPing(i, 0); } } } } } /** * Prints server/host information into the console. The header line is * printed if 'info' is NULL. */ void Net_PrintServerInfo(int index, serverinfo_t *info) { if(!info) { Con_Printf(" %-20s P/M L Ver: Game: Location:\n", "Name:"); } else { Con_Printf("%-2i: %-20s %i/%-2i %c %-5i %-16s %s:%i\n", index, info->name, info->numPlayers, info->maxPlayers, info->canJoin ? ' ' : '*', info->version, info->game, info->address, info->port); Con_Printf(" %s (%s:%x) p:%ims %-40s\n", info->map, info->iwad, info->wadNumber, info->ping, info->description); Con_Printf(" %s %s\n", info->gameMode, info->gameConfig); // Optional: PWADs in use. if(info->pwads[0]) Con_Printf(" PWADs: %s\n", info->pwads); // Optional: names of players. if(info->clientNames[0]) Con_Printf(" Players: %s\n", info->clientNames); // Optional: data values. if(info->data[0] || info->data[1] || info->data[2]) { Con_Printf(" Data: (%08x, %08x, %08x)\n", info->data[0], info->data[1], info->data[2]); } } } /** * All arguments are sent out as a chat message. */ D_CMD(Chat) { char buffer[100]; int i, mode = !stricmp(argv[0], "chat") || !stricmp(argv[0], "say") ? 0 : !stricmp(argv[0], "chatNum") || !stricmp(argv[0], "sayNum") ? 1 : 2; unsigned short mask = 0; if(argc == 1) { Con_Printf("Usage: %s %s(text)\n", argv[0], !mode ? "" : mode == 1 ? "(plr#) " : "(name) "); Con_Printf("Chat messages are max. 80 characters long.\n"); Con_Printf("Use quotes to get around arg processing.\n"); return true; } // Chatting is only possible when connected. if(!netGame) return false; // Too few arguments? if(mode && argc < 3) return false; // Assemble the chat message. strcpy(buffer, argv[!mode ? 1 : 2]); for(i = (!mode ? 2 : 3); i < argc; ++i) { strcat(buffer, " "); strncat(buffer, argv[i], 80 - (strlen(buffer) + strlen(argv[i]) + 1)); } buffer[80] = 0; // Send the message. switch(mode) { case 0: // chat mask = ~0; break; case 1: // chatNum mask = 1 << atoi(argv[1]); break; case 2: // chatTo { boolean found = false; for(i = 0; i < DDMAXPLAYERS && !found; ++i) { if(!stricmp(clients[i].name, argv[1])) { mask = 1 << i; found = true; } } break; } default: Con_Error("CCMD_Chat: Invalid value, mode = %i.", mode); break; } Msg_Begin(PKT_CHAT); Msg_WriteByte(consolePlayer); Msg_WriteShort(mask); Msg_Write(buffer, strlen(buffer) + 1); if(!isClient) { if(mask == (unsigned short) ~0) { Net_SendBuffer(NSP_BROADCAST, SPF_ORDERED); } else { for(i = 1; i < DDMAXPLAYERS; ++i) if(ddPlayers[i].shared.inGame && (mask & (1 << i))) Net_SendBuffer(i, SPF_ORDERED); } } else { Net_SendBuffer(0, SPF_ORDERED); } // Show the message locally. Net_ShowChatMessage(); // Inform the game, too. gx.NetPlayerEvent(consolePlayer, DDPE_CHAT_MESSAGE, buffer); return true; } D_CMD(Kick) { int num; if(!netGame) { Con_Printf("This is not a netGame.\n"); return false; } if(!isServer) { Con_Printf("This command is for the server only.\n"); return false; } num = atoi(argv[1]); if(num < 1 || num >= DDMAXPLAYERS) { Con_Printf("Invalid client number.\n"); return false; } if(netRemoteUser == num) { Con_Printf("Can't kick the client who's logged in.\n"); return false; } Sv_Kick(num); return true; } D_CMD(SetName) { playerinfo_packet_t info; Con_SetString("net-name", argv[1], false); if(!netGame) return true; // In netgames, a notification is sent to other players. memset(&info, 0, sizeof(info)); info.console = consolePlayer; strncpy(info.name, argv[1], PLAYERNAMELEN - 1); // Serverplayers can update their name right away. if(!isClient) strcpy(clients[consolePlayer].name, info.name); Net_SendPacket(DDSP_CONFIRM | (isClient ? consolePlayer : DDSP_ALL_PLAYERS), PKT_PLAYER_INFO, &info, sizeof(info)); return true; } D_CMD(SetTicks) { // extern double lastSharpFrameTime; firstNetUpdate = true; Sys_TicksPerSecond(strtod(argv[1], 0)); // lastSharpFrameTime = Sys_GetTimef(); return true; } D_CMD(MakeCamera) { /* int cp; mobj_t *mo; ddplayer_t *conp = players + consolePlayer; if(argc < 2) return true; cp = atoi(argv[1]); clients[cp].connected = true; clients[cp].ready = true; clients[cp].updateCount = UPDATECOUNT; ddPlayers[cp].flags |= DDPF_CAMERA; ddPlayers[cp].inGame = true; // !!! Sv_InitPoolForClient(cp); mo = Z_Malloc(sizeof(mobj_t), PU_MAP, 0); memset(mo, 0, sizeof(*mo)); mo->pos[VX] = conp->mo->pos[VX]; mo->pos[VY] = conp->mo->pos[VY]; mo->pos[VZ] = conp->mo->pos[VZ]; mo->subsector = conp->mo->subsector; ddPlayers[cp].mo = mo; displayPlayer = cp; */ // Create a new local player. int cp; cp = atoi(argv[1]); if(cp < 0 || cp >= DDMAXPLAYERS) return false; if(clients[cp].connected) { Con_Printf("Client %i already connected.\n", cp); return false; } clients[cp].connected = true; clients[cp].ready = true; clients[cp].updateCount = UPDATECOUNT; ddPlayers[cp].shared.flags |= DDPF_LOCAL; Sv_InitPoolForClient(cp); // Update the viewports. R_SetViewGrid(0, 0); return true; } D_CMD(SetConsole) { int cp; cp = atoi(argv[1]); if(ddPlayers[cp].shared.inGame) { consolePlayer = displayPlayer = cp; } // Update the viewports. R_SetViewGrid(0, 0); return true; } int Net_ConnectWorker(void *ptr) { connectparam_t *param = ptr; double startTime = 0; boolean isDone = false; int returnValue = false; // Make sure TCP/IP is active. if(N_InitService(false)) { Con_Message("Connecting to %s...\n", param->address); // Start searching at the specified location. N_LookForHosts(param->address, param->port); startTime = Sys_GetSeconds(); isDone = false; while(!isDone) { if(N_GetHostInfo(0, ¶m->info)) { // Found something! Net_PrintServerInfo(0, NULL); Net_PrintServerInfo(0, ¶m->info); Con_Execute(CMDS_CONSOLE, "net connect 0", false, false); returnValue = true; isDone = true; } else { // Nothing yet, should we wait a while longer? if(Sys_GetSeconds() - startTime >= netConnectTimeout) isDone = true; else Sys_Sleep(250); // Wait a while. } } if(!returnValue) Con_Printf("No response from %s.\n", param->address); } else { Con_Message("TCP/IP not available.\n"); } Con_BusyWorkerEnd(); return returnValue; } /** * Intelligently connect to a server. Just provide an IP address and the * rest is automatic. */ D_CMD(Connect) { connectparam_t param; char *ptr; if(argc < 2 || argc > 3) { Con_Printf("Usage: %s (ip-address) [port]\n", argv[0]); Con_Printf("A TCP/IP connection is created to the given server.\n"); Con_Printf("If a port is not specified port zero will be used.\n"); return true; } if(netGame) { Con_Printf("Already connected.\n"); return false; } strcpy(param.address, argv[1]); // If there is a port specified in the address, use it. if((ptr = strrchr(param.address, ':'))) { param.port = strtol(ptr + 1, 0, 0); *ptr = 0; } if(argc == 3) { param.port = strtol(argv[2], 0, 0); } return Con_Busy(BUSYF_ACTIVITY | (verbose? BUSYF_CONSOLE_OUTPUT : 0), NULL, Net_ConnectWorker, ¶m); } /** * The 'net' console command. */ D_CMD(Net) { int i; boolean success = true; if(argc == 1) // No args? { Con_Printf("Usage: %s (cmd/args)\n", argv[0]); Con_Printf("Commands:\n"); Con_Printf(" init\n"); Con_Printf(" shutdown\n"); Con_Printf(" setup client\n"); Con_Printf(" setup server\n"); Con_Printf(" info\n"); Con_Printf(" announce\n"); Con_Printf(" request\n"); Con_Printf(" search (address) [port] (local or targeted query)\n"); Con_Printf(" servers (asks the master server)\n"); Con_Printf(" connect (idx)\n"); Con_Printf(" mconnect (m-idx)\n"); Con_Printf(" disconnect\n"); Con_Printf(" server go/start\n"); Con_Printf(" server close/stop\n"); return true; } if(argc == 2 || argc == 3) { if(!stricmp(argv[1], "init")) { // Init the service (assume client mode). if((success = N_InitService(false))) Con_Message("Network initialization OK.\n"); else Con_Message("Network initialization failed!\n"); // Let everybody know of this. return CmdReturnValue = success; } } if(argc == 2) // One argument? { if(!stricmp(argv[1], "shutdown")) { if(N_IsAvailable()) { Con_Printf("Shutting down %s.\n", N_GetProtocolName()); N_ShutdownService(); } else { success = false; } } else if(!stricmp(argv[1], "announce")) { N_MasterAnnounceServer(true); } else if(!stricmp(argv[1], "request")) { N_MasterRequestList(); } else if(!stricmp(argv[1], "servers")) { N_MAPost(MAC_REQUEST); N_MAPost(MAC_WAIT); N_MAPost(MAC_LIST); } else if(!stricmp(argv[1], "info")) { if(isServer) { Con_Printf("Clients:\n"); for(i = 0; i < DDMAXPLAYERS; ++i) { client_t *cl = &clients[i]; player_t *plr = &ddPlayers[i]; if(cl->connected) Con_Printf("%2i: %10s node %2x, entered at %07i (ingame:%i, handshake:%i)\n", i, cl->name, cl->nodeID, cl->enterTime, plr->shared.inGame, cl->handshake); } } Con_Printf("Network game: %s\n", netGame ? "yes" : "no"); Con_Printf("Server: %s\n", isServer ? "yes" : "no"); Con_Printf("Client: %s\n", isClient ? "yes" : "no"); Con_Printf("Console number: %i\n", consolePlayer); Con_Printf("Local player #: %i\n", P_ConsoleToLocal(consolePlayer)); N_PrintInfo(); } else if(!stricmp(argv[1], "disconnect")) { if(!netGame) { Con_Printf("This client is not connected to a server.\n"); return false; } if(!isClient) { Con_Printf("This is not a client.\n"); return false; } if((success = N_Disconnect()) != false) { Con_Message("Disconnected.\n"); } } else { Con_Printf("Bad arguments.\n"); return false; // Bad args. } } if(argc == 3) // Two arguments? { if(!stricmp(argv[1], "server")) { if(!stricmp(argv[2], "go") || !stricmp(argv[2], "start")) { if(netGame) { Con_Printf("Already in a netGame.\n"); return false; } CmdReturnValue = success = N_ServerOpen(); if(success) { Con_Message("Server \"%s\" started.\n", serverName); } } else if(!stricmp(argv[2], "close") || !stricmp(argv[2], "stop")) { if(!isServer) { Con_Printf("This is not a server!\n"); return false; } // Close the server and kick everybody out. if((success = N_ServerClose()) != false) { Con_Message("Server \"%s\" closed.\n", serverName); } } else { Con_Printf("Bad arguments.\n"); return false; } } else if(!stricmp(argv[1], "search")) { success = N_LookForHosts(argv[2], 0); } else if(!stricmp(argv[1], "connect")) { int idx; if(netGame) { Con_Printf("Already connected.\n"); return false; } idx = strtol(argv[2], NULL, 10); CmdReturnValue = success = N_Connect(idx); if(success) { Con_Message("Connected.\n"); } } else if(!stricmp(argv[1], "mconnect")) { serverinfo_t info; if(N_MasterGet(strtol(argv[2], 0, 0), &info)) { // Connect using TCP/IP. return Con_Executef(CMDS_CONSOLE, false, "connect %s %i", info.address, info.port); } else return false; } else if(!stricmp(argv[1], "setup")) { // Start network setup. DD_NetSetup(!stricmp(argv[2], "server")); CmdReturnValue = true; } } if(argc == 4) { if(!stricmp(argv[1], "search")) { success = N_LookForHosts(argv[2], strtol(argv[3], 0, 0)); } } return success; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/net_ping.c0000644000175000017500000001225411357170242022704 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_ping.c: Pinging Clients and the Server * * Warning: This is not a very accurate ping. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void Net_ShowPingSummary(int player) { client_t *cl = clients + player; pinger_t *ping = &cl->ping; float avgTime = 0, loss; int i, goodCount = 0; if(player < 0 && ping->total > 0) return; for(i = 0; i < ping->total; ++i) { if(ping->times[i] < 0) continue; goodCount++; avgTime += ping->times[i]; } avgTime /= goodCount; loss = 1 - goodCount / (float) ping->total; Con_Printf("Plr %i (%s): average ping %.0f ms, loss %.0f%%.\n", player, cl->name, avgTime * 1000, loss * 100); } void Net_SendPing(int player, int count) { client_t *cl = clients + player; // Valid destination? if((player == consolePlayer) || (isClient && player)) return; if(count) { // We can't start a new ping run until the old one is done. if(cl->ping.sent) return; // Start a new ping session. if(count > MAX_PINGS) count = MAX_PINGS; cl->ping.current = 0; cl->ping.total = count; } else { // Continue or finish the current pinger. if(++cl->ping.current >= cl->ping.total) { // We're done. cl->ping.sent = 0; // Print a summary (average ping, loss %). Net_ShowPingSummary(netBuffer.player); return; } } // Send a new ping. Msg_Begin(PKT_PING); cl->ping.sent = Sys_GetRealTime(); Msg_WriteLong(cl->ping.sent); // Update the length of the message. netBuffer.length = netBuffer.cursor - netBuffer.msg.data; netBuffer.player = player; N_SendPacket(10000); } // Called when a ping packet comes in. void Net_PingResponse(void) { client_t *cl = &clients[netBuffer.player]; int time = Msg_ReadLong(); // Is this a response to our ping? if(time == cl->ping.sent) { // Record the time and send the next ping. cl->ping.times[cl->ping.current] = (Sys_GetRealTime() - time) / 1000.0f; // Show a notification. /*Con_Printf( "Ping to plr %i: %.0f ms.\n", netbuffer.player, cl->ping.times[cl->ping.current] * 1000); */ // Send the next ping. Net_SendPing(netBuffer.player, 0); } else { // Not ours, just respond. Net_SendBuffer(netBuffer.player, 10000); } } D_CMD(Ping) { int dest, count = 4; if(!netGame) { Con_Printf("Ping is only for netgames.\n"); return true; } if(isServer && argc == 1) { Con_Printf("Usage: %s (plrnum) (count)\n", argv[0]); Con_Printf("(count) is optional. 4 pings are sent by default.\n"); return true; } if(isServer) { dest = atoi(argv[1]); if(argc >= 3) count = atoi(argv[2]); } else { dest = 0; if(argc >= 2) count = atoi(argv[1]); } // Check that the given parameters are valid. if(count <= 0 || count > MAX_PINGS || dest < 0 || dest >= DDMAXPLAYERS || dest == consolePlayer || (dest && !ddPlayers[dest].shared.inGame)) return false; Net_SendPing(dest, count); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_console.c0000644000175000017500000004517011357170242023556 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_console.c: Console rendering. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_ui.h" #include "math.h" #ifdef TextOut // Windows has its own TextOut. # undef TextOut #endif // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(BackgroundTurn); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float CcolYellow[3] = { 1, .85f, .3f }; float ConsoleOpenY; // Where the console bottom is when open. int consoleTurn; // The rotation variable. int consoleLight = 14, consoleAlpha = 75; byte consoleShowFPS = false; byte consoleShadowText = true; float consoleMoveSpeed = .2f; // Speed of console opening/closing // PRIVATE DATA DEFINITIONS ------------------------------------------------ static float ConsoleY; // Where the console bottom is currently? static float ConsoleDestY; // Where the console bottom should be? static float ConsoleBlink; // Cursor blink timer (35 Hz tics). static boolean openingOrClosing = true; static float fontFx, fontSy; // Font x factor and y size. static float funnyAng; static char *consoleTitle = "Doomsday " DOOMSDAY_VERSION_TEXT; static char secondaryTitleText[256]; static char statusText[256]; // CODE -------------------------------------------------------------------- void Rend_ConsoleRegister(void) { C_CMD_FLAGS("bgturn", "i", BackgroundTurn, CMDF_NO_DEDICATED); C_VAR_INT("con-alpha", &consoleAlpha, 0, 0, 100); C_VAR_INT("con-light", &consoleLight, 0, 0, 100); C_VAR_BYTE("con-fps", &consoleShowFPS, 0, 0, 1); C_VAR_BYTE("con-text-shadow", &consoleShadowText, 0, 0, 1); C_VAR_FLOAT("con-move-speed", &consoleMoveSpeed, 0, 0, 1); } void Rend_ConsoleInit(void) { ConsoleY = 0; ConsoleOpenY = 90; ConsoleDestY = 0; // Font size in VGA coordinates. (Everything is in VGA coords.) fontFx = 1; fontSy = 9; funnyAng = 0; } void Rend_ConsoleCursorResetBlink(void) { ConsoleBlink = 0; } static float GetConsoleTitleBarHeight(void) { int oldFont = FR_GetCurrent(); int border = theWindow->width / 120; int height; FR_SetFont(glFontVariable[GLFS_BOLD]); height = FR_TextHeight("W") + border; FR_SetFont(oldFont); return height; } static void consoleSetColor(int fl, float alpha) { float r = 0, g = 0, b = 0; int count = 0; // Calculate the average of the given colors. if(fl & CBLF_BLACK) { count++; } if(fl & CBLF_BLUE) { b += 1; count++; } if(fl & CBLF_GREEN) { g += 1; count++; } if(fl & CBLF_CYAN) { g += 1; b += 1; count++; } if(fl & CBLF_RED) { r += 1; count++; } if(fl & CBLF_MAGENTA) { r += 1; b += 1; count++; } if(fl & CBLF_YELLOW) { r += CcolYellow[0]; g += CcolYellow[1]; b += CcolYellow[2]; count++; } if(fl & CBLF_WHITE) { r += 1; g += 1; b += 1; count++; } // Calculate the average. if(count) { r /= count; g /= count; b /= count; } if(fl & CBLF_LIGHT) { r += (1 - r) / 2; g += (1 - g) / 2; b += (1 - b) / 2; } glColor4f(r, g, b, alpha); } static void drawRuler2(int y, int lineHeight, float alpha, int scrWidth) { int xoff = 5; int rh = 6; UI_GradientEx(xoff, y + (lineHeight - rh) / 2 + 1, scrWidth - 2 * xoff, rh, rh / 2, UI_Color(UIC_SHADOW), UI_Color(UIC_BG_DARK), alpha / 3, alpha); UI_DrawRectEx(xoff, y + (lineHeight - rh) / 2 + 1, scrWidth - 2 * xoff, rh, rh / 2, false, UI_Color(UIC_TEXT), NULL, /*UI_Color(UIC_BG_DARK), UI_Color(UIC_BG_LIGHT), */ alpha, -1); } void Con_DrawRuler(int y, int lineHeight, float alpha) { if(isDedicated) return; drawRuler2(y, lineHeight, alpha, theWindow->width); } /** * Initializes the Doomsday console user interface. This is called when * engine startup is complete. * * \todo Doesn't belong here. */ void Con_InitUI(void) { // Update the secondary title and the game status. strncpy(secondaryTitleText, (char *) gx.GetVariable(DD_GAME_ID), sizeof(secondaryTitleText) - 1); strncpy(statusText, (char *) gx.GetVariable(DD_GAME_MODE), sizeof(statusText) - 1); } /** * Draw a 'side' text in the console. This is intended for extra * information about the current game mode. */ #if 0 // currently unused static void drawSideText(const char *text, int line, float alpha) { char buf[300]; float gtosMulY = glScreenHeight / 200.0f; float fontScaledY = Cfont.height * Cfont.sizeY; float y = ConsoleY * gtosMulY - fontScaledY * (1 + line); int ssw; if(y > -fontScaledY) { // The side text is a bit transparent. alpha *= .75f; // scaled screen width ssw = (int) (glScreenWidth / Cfont.sizeX); // Print the version. strncpy(buf, text, sizeof(buf)); if(Cfont.Filter) Cfont.Filter(buf); /* if(consoleShadowText) { // Draw a shadow. glColor4f(0, 0, 0, alpha); Cfont.TextOut(buf, ssw - Cfont.Width(buf) - 2, y / Cfont.sizeY + 1); } */ glColor4f(CcolYellow[0], CcolYellow[1], CcolYellow[2], alpha); Cfont.TextOut(buf, ssw - Cfont.Width(buf) - 3, y / Cfont.sizeY); } } #endif static __inline int consoleMinHeight(void) { return 1.25f * fontSy + GetConsoleTitleBarHeight() / theWindow->height * 200; } void Rend_ConsoleToggleFullscreen(void) { float y; int minHeight; if(isDedicated) return; minHeight = consoleMinHeight(); if(ConsoleDestY == minHeight) y = 100; else if(ConsoleDestY == 100) y = 200; else y = minHeight; ConsoleDestY = ConsoleOpenY = y; } void Rend_ConsoleOpen(int yes) { if(isDedicated) return; openingOrClosing = true; if(yes) { ConsoleDestY = ConsoleOpenY; Rend_ConsoleCursorResetBlink(); } else { ConsoleDestY = 0; } } void Rend_ConsoleMove(int numLines) { if(isDedicated) return; if(numLines == 0) return; if(numLines < 0) { int minHeight = consoleMinHeight(); ConsoleOpenY -= fontSy * -numLines; if(ConsoleOpenY < minHeight) ConsoleOpenY = minHeight; } else { ConsoleOpenY += fontSy * numLines; if(ConsoleOpenY > 200) ConsoleOpenY = 200; } ConsoleDestY = ConsoleOpenY; } void Rend_ConsoleTicker(timespan_t time) { float step; if(isDedicated) return; step = time * 35; if(ConsoleY == 0) openingOrClosing = true; // Move the console to the destination Y. if(ConsoleDestY > ConsoleY) { float diff = (ConsoleDestY - ConsoleY) * consoleMoveSpeed; if(diff < 1) diff = 1; ConsoleY += diff * step; if(ConsoleY > ConsoleDestY) ConsoleY = ConsoleDestY; } else if(ConsoleDestY < ConsoleY) { float diff = (ConsoleY - ConsoleDestY) * consoleMoveSpeed; if(diff < 1) diff = 1; ConsoleY -= diff * step; if(ConsoleY < ConsoleDestY) ConsoleY = ConsoleDestY; } if(ConsoleY == ConsoleOpenY) openingOrClosing = false; funnyAng += step * consoleTurn / 10000; if(!Con_IsActive()) return; // We have nothing further to do here. ConsoleBlink += step; // Cursor blink timer (0 = visible). } void Rend_ConsoleFPS(int x, int y) { int w, h; char buf[160]; if(isDedicated) return; if(!consoleShowFPS) return; // If the ui is active draw the counter a bit further down if(UI_IsActive()) y += 20; sprintf(buf, "%.1f FPS", DD_GetFrameRate()); w = FR_TextWidth(buf) + 16; h = FR_TextHeight(buf) + 16; x -= w; UI_GradientEx(x, y, w, h, 6, UI_Color(UIC_BG_MEDIUM), UI_Color(UIC_BG_LIGHT), .5f, .5f); UI_DrawRectEx(x, y, w, h, 6, false, UI_Color(UIC_BRD_HI), NULL, .5f, -1); UI_SetColor(UI_Color(UIC_TEXT)); UI_TextOutEx(buf, x + 8, y + h / 2, false, true, UI_Color(UIC_TITLE), 1); } static void DrawConsoleTitleBar(float closeFade) { int width = 0; int height; int oldFont = FR_GetCurrent(); int border = theWindow->width / 120; glMatrixMode(GL_PROJECTION); glPushMatrix(); //FR_SetFont(glFontVariable[GLFS_BOLD]); height = GetConsoleTitleBarHeight(); //FR_TextHeight("W") + border; FR_SetFont(glFontVariable[GLFS_BOLD]); UI_Gradient(0, 0, theWindow->width, height, UI_Color(UIC_BG_MEDIUM), UI_Color(UIC_BG_LIGHT), .8f * closeFade, closeFade); UI_Gradient(0, height, theWindow->width, border, UI_Color(UIC_SHADOW), UI_Color(UIC_BG_DARK), closeFade, 0); UI_TextOutEx(consoleTitle, border, height / 2, false, true, UI_Color(UIC_TITLE), closeFade); if(secondaryTitleText[0]) { width = FR_TextWidth(consoleTitle) + FR_TextWidth(" "); FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(secondaryTitleText, border + width, height / 2, false, true, UI_Color(UIC_TEXT), .75f * closeFade); } if(statusText[0]) { width = FR_TextWidth(statusText); FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(statusText, theWindow->width - UI_BORDER - width, height / 2, false, true, UI_Color(UIC_TEXT), .75f * closeFade); } glMatrixMode(GL_PROJECTION); glPopMatrix(); FR_SetFont(oldFont); } static void drawConsoleBackground(int x, int y, int w, int h, float gtosMulY, float closeFade) { int bgX = 64, bgY = 64; // The console is composed of two parts: the main area background // and the border. glColor4f(consoleLight / 100.0f, consoleLight / 100.0f, consoleLight / 100.0f, closeFade * consoleAlpha / 100); // The background. if(gx.ConsoleBackground) gx.ConsoleBackground(&bgX, &bgY); // Let's make it a bit more interesting. glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glTranslatef(2 * sin(funnyAng / 4), 2 * cos(funnyAng / 4), 0); glRotatef(funnyAng * 3, 0, 0, 1); GL_DrawRectTiled(x, y, w, h, bgX, bgY); glMatrixMode(GL_TEXTURE); glPopMatrix(); } /** * NOTE: Slightly messy... */ static void drawConsole(void) { extern uint bLineOff; int k; // Line and buffer cursor. float x, y; float closeFade = 1; float gtosMulY; char buff[CMDLINE_SIZE + 1], temp[CMDLINE_SIZE + 1], *cmdLine; float fontScaledY; int textOffsetY = 0; uint cmdCursor; cbuffer_t *buffer; static const cbline_t **lines = NULL; static int bufferSize = 0; gtosMulY = theWindow->height / 200.0f; cmdLine = Con_GetCommandLine(); cmdCursor = Con_CursorPosition(); buffer = Con_GetConsoleBuffer(); // Do we have a font? if(Cfont.drawText == NULL) { Cfont.flags = DDFONT_WHITE; Cfont.height = FR_SingleLineHeight("Con"); Cfont.sizeX = 1; Cfont.sizeY = 1; Cfont.drawText = FR_ShadowTextOut; Cfont.getWidth = FR_TextWidth; Cfont.filterText = NULL; } FR_SetFont(glFontFixed); fontScaledY = Cfont.height * Cfont.sizeY; fontSy = fontScaledY / gtosMulY; textOffsetY = fontScaledY / 4; // Go into screen projection mode. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); if(openingOrClosing) { closeFade = ConsoleY / (float) ConsoleOpenY; } drawConsoleBackground(0, (int) (ConsoleY * gtosMulY + 4), theWindow->width, -theWindow->height - 4, gtosMulY, closeFade); glDisable(GL_TEXTURE_2D); // The border. GL_DrawRect(0, (int) (ConsoleY * gtosMulY + 4), theWindow->width, 2, 0, 0, 0, closeFade); // Subtle shadow. glBegin(GL_QUADS); glColor4f(.1f, .1f, .1f, closeFade * consoleAlpha / 150); glVertex2f(0, (int) (ConsoleY * gtosMulY + 5)); glVertex2f(theWindow->width, (int) (ConsoleY * gtosMulY + 5)); glColor4f(0, 0, 0, 0); glVertex2f(theWindow->width, (int) (ConsoleY * gtosMulY + 13)); glVertex2f(0, (int) (ConsoleY * gtosMulY + 13)); glEnd(); glEnable(GL_TEXTURE_2D); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glScalef(Cfont.sizeX, Cfont.sizeY, 1); // The game & version number. //drawSideText(gx.Get(DD_GAME_ID), 2, closeFade); //drawSideText(gx.Get(DD_GAME_MODE), 1, closeFade); glColor4f(1, 1, 1, closeFade); // The console history log is drawn from top to bottom. y = ConsoleY * gtosMulY - fontScaledY * 2 - textOffsetY; if(ceil(y / fontScaledY) > 0) { int firstIdx = 0; uint i, count, reqLines = ceil(y / fontScaledY); y -= (reqLines - 1) * fontScaledY; // Need to enlarge the buffer? if(reqLines > (uint) bufferSize) { lines = Z_Realloc((void*) lines, sizeof(cbline_t *) * (reqLines + 1), PU_STATIC); bufferSize = reqLines; } firstIdx -= reqLines; if(bLineOff > reqLines) firstIdx -= (bLineOff - reqLines); if(bLineOff < reqLines) firstIdx -= bLineOff; count = Con_BufferGetLines(buffer, reqLines, firstIdx, lines); for(i = 0; i < count; ++i) { const cbline_t* line = lines[i]; if(!line) continue; if(line->flags & CBLF_RULER) { // Draw a ruler here, and nothing else. drawRuler2(y / Cfont.sizeY, Cfont.height, closeFade, theWindow->width / Cfont.sizeX); } else { if(!line->text) continue; memset(buff, 0, sizeof(buff)); strncpy(buff, line->text, 255); if(line->flags & CBLF_CENTER) x = (theWindow->width / Cfont.sizeX - Cfont.getWidth(buff)) / 2; else x = 2; if(Cfont.filterText) Cfont.filterText(buff); /*else if(consoleShadowText) { // Draw a shadow. glColor3f(0, 0, 0); Cfont.drawText(buff, x + 2, y / Cfont.sizeY + 2); }*/ // Set the color. if(Cfont.flags & DDFONT_WHITE) // Can it be colored? consoleSetColor(line->flags, closeFade); Cfont.drawText(buff, x, y / Cfont.sizeY); } // Move down. y += fontScaledY; } } // The command line. strcpy(buff, ">"); strncat(buff, cmdLine, 255); if(Cfont.filterText) Cfont.filterText(buff); /*if(consoleShadowText) { // Draw a shadow. glColor3f(0, 0, 0); Cfont.TextOut(buff, 4, 2 + (ConsoleY * gtosMulY - fontScaledY) / Cfont.sizeY); }*/ if(Cfont.flags & DDFONT_WHITE) glColor4f(CcolYellow[0], CcolYellow[1], CcolYellow[2], closeFade); else glColor4f(1, 1, 1, closeFade); Cfont.drawText(buff, 2, (ConsoleY * gtosMulY - fontScaledY - textOffsetY) / Cfont.sizeY); // Width of the current char. temp[0] = cmdLine[cmdCursor]; temp[1] = 0; k = Cfont.getWidth(temp); if(!k) k = Cfont.getWidth(" "); // Draw the cursor in the appropriate place. if(!Con_IsLocked()) { int i; float curHeight = fontScaledY / 4; // What is the width? memset(temp, 0, sizeof(temp)); strncpy(temp, buff, MIN_OF(250, cmdCursor) + 1); i = Cfont.getWidth(temp); glDisable(GL_TEXTURE_2D); GL_DrawRect(2 + i, (ConsoleY * gtosMulY - textOffsetY + curHeight) / Cfont.sizeY, k, -(Con_InputMode()? fontScaledY + curHeight: curHeight) / Cfont.sizeY, CcolYellow[0], CcolYellow[1], CcolYellow[2], closeFade * (((int) ConsoleBlink) & 0x10 ? .2f : .5f)); glEnable(GL_TEXTURE_2D); } // Restore the original matrices. glMatrixMode(GL_MODELVIEW); glPopMatrix(); // Draw the console title bar. DrawConsoleTitleBar(closeFade); glMatrixMode(GL_PROJECTION); glPopMatrix(); } void Rend_Console(void) { if(isDedicated) return; if(ConsoleY <= 0) return; // We have nothing to do here. drawConsole(); } D_CMD(BackgroundTurn) { consoleTurn = atoi(argv[1]); if(!consoleTurn) funnyAng = 0; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_main.c0000644000175000017500000006750711357170242022522 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_main.c: Graphics Subsystem */ // HEADER FILES ------------------------------------------------------------ #ifdef UNIX #ifdef HAVE_CONFIG_H # include "config.h" #endif #endif #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_render.h" #include "de_misc.h" #include "de_ui.h" #include "de_defs.h" #include "r_draw.h" #if defined(WIN32) && defined(WIN32_GAMMA) # include # include #endif // SDL's gamma settings seem more robust. #if 0 #if defined(UNIX) && defined(HAVE_X11_EXTENSIONS_XF86VMODE_H) # define XFREE_GAMMA # include # include #endif #endif #if !defined(WIN32_GAMMA) && !defined(XFREE_GAMMA) # define SDL_GAMMA # include #endif #ifdef TextOut // Windows has its own TextOut. # undef TextOut #endif // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef unsigned short gramp_t[3 * 256]; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(Fog); D_CMD(SetBPP); D_CMD(SetRes); D_CMD(ToggleFullscreen); void GL_SetGamma(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int maxnumnodes; extern boolean fillOutlines; // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The default resolution (config file). int defResX = 640, defResY = 480, defBPP = 32; int defFullscreen = true; int numTexUnits; boolean envModAdd; // TexEnv: modulate and add is available. int test3dfx = 0; int r_framecounter; // Used only for statistics. int r_detail = true; // Render detail textures (if available). float vid_gamma = 1.0f, vid_bright = 0, vid_contrast = 1.0f; int glFontFixed, glFontVariable[NUM_GLFS]; float glNearClip, glFarClip; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean initGLOk = false; static boolean varFontInited = false; static gramp_t original_gamma_ramp; static boolean gamma_support = false; static float oldgamma, oldcontrast, oldbright; static int fogModeDefault = 0; static viewport_t currentView; // CODE -------------------------------------------------------------------- void GL_Register(void) { // Cvars C_VAR_INT("rend-dev-wireframe", &renderWireframe, 0, 0, 1); C_VAR_INT("rend-fog-default", &fogModeDefault, 0, 0, 2); // * Render-HUD C_VAR_FLOAT("rend-hud-offset-scale", &weaponOffsetScale, CVF_NO_MAX, 0, 0); C_VAR_FLOAT("rend-hud-fov-shift", &weaponFOVShift, CVF_NO_MAX, 0, 1); // * Render-Mobj C_VAR_INT("rend-mobj-smooth-move", &useSRVO, 0, 0, 2); C_VAR_INT("rend-mobj-smooth-turn", &useSRVOAngle, 0, 0, 1); // * video C_VAR_INT("vid-res-x", &defResX, CVF_NO_MAX, 320, 0); C_VAR_INT("vid-res-y", &defResY, CVF_NO_MAX, 240, 0); C_VAR_INT("vid-bpp", &defBPP, 0, 16, 32); C_VAR_INT("vid-fullscreen", &defFullscreen, 0, 0, 1); C_VAR_FLOAT("vid-gamma", &vid_gamma, 0, 0.1f, 6); C_VAR_FLOAT("vid-contrast", &vid_contrast, 0, 0, 10); C_VAR_FLOAT("vid-bright", &vid_bright, 0, -2, 2); // Ccmds C_CMD_FLAGS("fog", NULL, Fog, CMDF_NO_DEDICATED); C_CMD_FLAGS("setbpp", "i", SetBPP, CMDF_NO_DEDICATED); C_CMD_FLAGS("setres", "ii", SetRes, CMDF_NO_DEDICATED); C_CMD_FLAGS("setvidramp", "", UpdateGammaRamp, CMDF_NO_DEDICATED); C_CMD("togglefullscreen", "", ToggleFullscreen); GL_TexRegister(); } boolean GL_IsInited(void) { return initGLOk; } /** * Swaps buffers / blits the back buffer to the front. */ void GL_DoUpdate(void) { // Check for color adjustment changes. if(oldgamma != vid_gamma || oldcontrast != vid_contrast || oldbright != vid_bright) GL_SetGamma(); // Blit screen to video. if(renderWireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); Sys_UpdateWindow(windowIDX); if(renderWireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Increment frame counter. r_framecounter++; } /** * On Win32, use the gamma ramp functions in the Win32 API. On Linux, use * the XFree86-VidMode extension. */ void GL_GetGammaRamp(unsigned short *ramp) { if(ArgCheck("-noramp")) { gamma_support = false; return; } #ifdef SDL_GAMMA gamma_support = true; if(SDL_GetGammaRamp(ramp, ramp + 256, ramp + 512) < 0) { gamma_support = false; } #endif #if defined(WIN32) && defined(WIN32_GAMMA) { HWND hWnd = Sys_GetWindowHandle(windowIDX); HDC hDC; if(!hWnd) { suspendMsgPump = true; MessageBox(HWND_DESKTOP, "GL_GetGammaRamp: Main window not available.", NULL, MB_ICONERROR | MB_OK); suspendMsgPump = false; } else { hDC = GetDC(hWnd); if(!hDC) { Con_Message("GL_GetGammaRamp: Failed getting device context."); gamma_support = false; } else { gamma_support = false; if(GetDeviceGammaRamp(hDC, (void*) ramp)) { gamma_support = true; } ReleaseDC(hWnd, hDC); } } } #endif #ifdef XFREE_GAMMA { Display *dpy = XOpenDisplay(NULL); int screen = DefaultScreen(dpy); int event = 0, error = 0; int rampSize = 0; Con_Message("GL_GetGammaRamp:\n"); if(!dpy || !XF86VidModeQueryExtension(dpy, &event, &error)) { Con_Message(" XFree86-VidModeExtension not available.\n"); gamma_support = false; return; } VERBOSE(Con_Message(" XFree86-VidModeExtension: event# %i " "error# %i\n", event, error)); XF86VidModeGetGammaRampSize(dpy, screen, &rampSize); Con_Message(" Gamma ramp size: %i\n", rampSize); if(rampSize != 256) { Con_Message(" This implementation only understands ramp size " "256.\n Please complain to the developer.\n"); gamma_support = false; XCloseDisplay(dpy); return; } // Get the current ramps. XF86VidModeGetGammaRamp(dpy, screen, rampSize, ramp, ramp + 256, ramp + 512); XCloseDisplay(dpy); gamma_support = true; } #endif } void GL_SetGammaRamp(unsigned short *ramp) { if(!gamma_support) return; #ifdef SDL_GAMMA SDL_SetGammaRamp(ramp, ramp + 256, ramp + 512); #endif #if defined(WIN32) && defined(WIN32_GAMMA) { HWND hWnd = Sys_GetWindowHandle(windowIDX); if(!hWnd) { suspendMsgPump = true; MessageBox(HWND_DESKTOP, "GL_SetGammaRamp: Main window not available.", NULL, MB_ICONERROR | MB_OK); suspendMsgPump = false; } else { HDC hDC = GetDC(hWnd); if(!hDC) { Con_Message("GL_SetGammaRamp: Failed getting device context."); gamma_support = false; } else { SetDeviceGammaRamp(hDC, (void*) ramp); ReleaseDC(hWnd, hDC); } } } #endif #ifdef XFREE_GAMMA { Display *dpy = XOpenDisplay(NULL); int screen = DefaultScreen(dpy); if(!dpy) return; // We assume that the gamme ramp size actually is 256. XF86VidModeSetGammaRamp(dpy, screen, 256, ramp, ramp + 256, ramp + 512); XCloseDisplay(dpy); } #endif } /** * Calculate a gamma ramp and write the result to the location pointed to. * * PRE: 'ramp' must point to a ushort[256] area of memory. * * @param ramp Ptr to the ramp table to write to. * @param gamma Non-linear factor (curvature; >1.0 multiplies). * @param contrast Steepness. * @param bright Brightness, uniform offset. */ void GL_MakeGammaRamp(unsigned short *ramp, float gamma, float contrast, float bright) { int i; double ideal[256]; // After processing clamped to unsigned short. double norm; // Don't allow stupid values. if(contrast < 0.1f) contrast = 0.1f; if(bright > 0.8f) bright = 0.8f; if(bright < -0.8f) bright = -0.8f; // Init the ramp as a line with the steepness defined by contrast. for(i = 0; i < 256; ++i) ideal[i] = i * contrast - (contrast - 1) * 127; // Apply the gamma curve. if(gamma != 1) { if(gamma <= 0.1f) gamma = 0.1f; norm = pow(255, 1 / gamma - 1); // Normalizing factor. for(i = 0; i < 256; ++i) ideal[i] = pow(ideal[i], 1 / gamma) / norm; } // The last step is to add the brightness offset. for(i = 0; i < 256; ++i) ideal[i] += bright * 128; // Clamp it and write the ramp table. for(i = 0; i < 256; ++i) { ideal[i] *= 0x100; // Byte => word if(ideal[i] < 0) ideal[i] = 0; if(ideal[i] > 0xffff) ideal[i] = 0xffff; ramp[i] = ramp[i + 256] = ramp[i + 512] = (unsigned short) ideal[i]; } } /** * Updates the gamma ramp based on vid_gamma, vid_contrast and vid_bright. */ void GL_SetGamma(void) { gramp_t myramp; oldgamma = vid_gamma; oldcontrast = vid_contrast; oldbright = vid_bright; GL_MakeGammaRamp(myramp, vid_gamma, vid_contrast, vid_bright); GL_SetGammaRamp(myramp); } const char* GL_ChooseFixedFont(void) { if(theWindow->width < 300) return "console11"; if(theWindow->width > 768) return "console18"; return "console14"; } const char* GL_ChooseVariableFont(glfontstyle_t style, int resX, int resY) { const int SMALL_LIMIT = 500; const int MED_LIMIT = 800; switch(style) { default: return (resY < SMALL_LIMIT ? "normal12" : resY < MED_LIMIT ? "normal18" : "normal24"); case GLFS_LIGHT: return (resY < SMALL_LIMIT ? "normallight12" : resY < MED_LIMIT ? "normallight18" : "normallight24"); case GLFS_BOLD: return (resY < SMALL_LIMIT ? "normalbold12" : resY < MED_LIMIT ? "normalbold18" : "normalbold24"); } } void GL_InitFont(void) { FR_Init(); FR_PrepareFont(GL_ChooseFixedFont()); glFontFixed = FR_GetCurrent(); Con_SetMaxLineLength(); FR_PrepareFont(GL_ChooseVariableFont(GLFS_NORMAL, theWindow->width, theWindow->height)); glFontVariable[GLFS_NORMAL] = FR_GetCurrent(); FR_PrepareFont(GL_ChooseVariableFont(GLFS_BOLD, theWindow->width, theWindow->height)); glFontVariable[GLFS_BOLD] = FR_GetCurrent(); FR_PrepareFont(GL_ChooseVariableFont(GLFS_LIGHT, theWindow->width, theWindow->height)); glFontVariable[GLFS_LIGHT] = FR_GetCurrent(); FR_SetFont(glFontFixed); Cfont.flags = DDFONT_WHITE; Cfont.height = FR_SingleLineHeight("Con"); Cfont.sizeX = 1; Cfont.sizeY = 1; Cfont.drawText = FR_ShadowTextOut; Cfont.getWidth = FR_TextWidth; Cfont.filterText = NULL; } void GL_ShutdownFont(void) { FR_Shutdown(); glFontFixed = glFontVariable[GLFS_NORMAL] = glFontVariable[GLFS_BOLD] = glFontVariable[GLFS_LIGHT] = 0; } #if 0 void GL_InitVarFont(void) { int oldFont; //int i; if(novideo) //|| varFontInited) return; /* VERBOSE2(Con_Message("GL_InitVarFont.\n")); oldFont = FR_GetCurrent(); VERBOSE2(Con_Message("GL_InitVarFont: Old font = %i.\n", oldFont)); for(i = 0; i < NUM_GLFS; ++i) { // The bold font and light fonts are always loaded. if(i == GLFS_BOLD || i == GLFS_LIGHT) continue; FR_PrepareFont(GL_ChooseVariableFont(i, theWindow->width, theWindow->height)); glFontVariable[i] = FR_GetCurrent(); VERBOSE2(Con_Message("GL_InitVarFont: Variable font = %i.\n", glFontVariable[i])); } FR_SetFont(oldFont); VERBOSE2(Con_Message("GL_InitVarFont: Restored old font %i.\n", oldFont)); */ //varFontInited = true; } void GL_ShutdownVarFont(void) { // int i; if(novideo) // || !varFontInited) return; //FR_SetFont(glFontFixed); /* for(i = 0; i < NUM_GLFS; ++i) { // Keep the bold and light fonts loaded. if(i == GLFS_BOLD || i == GLFS_LIGHT) continue; FR_DestroyFont(glFontVariable[i]); glFontVariable[i] = glFontFixed; } */ //varFontInited = false; } #endif /** * One-time initialization of DGL and the renderer. This is done very early * on during engine startup, and is supposed to be fast. All subsystems * cannot yet be initialized, such as fonts or texture management, so any * rendering occuring before GL_Init() must be done with manually prepared * textures. */ boolean GL_EarlyInit(void) { if(initGLOk) return true; // Already initialized. if(novideo) return true; Con_Message("GL_Init: Initializing Doomsday Graphics Library.\n"); // Get the original gamma ramp and check if ramps are supported. GL_GetGammaRamp(original_gamma_ramp); GL_InitDeferred(); // Check the maximum texture size. if(GL_state.maxTexSize == 256) { int bpp; Con_Message(" Using restricted texture w/h ratio (1:8).\n"); ratioLimit = 8; Sys_GetWindowBPP(windowIDX, &bpp); if(bpp == 32) { Con_Message(" Warning: Are you sure your video card accelerates" " a 32 bit mode?\n"); } } // Set a custom maximum size? if(ArgCheckWith("-maxtex", 1)) { int customSize = M_CeilPow2(strtol(ArgNext(), 0, 0)); if(GL_state.maxTexSize < customSize) customSize = GL_state.maxTexSize; GL_state.maxTexSize = customSize; Con_Message(" Using maximum texture size of %i x %i.\n", GL_state.maxTexSize, GL_state.maxTexSize); } if(ArgCheck("-outlines")) { fillOutlines = false; Con_Message(" Textures have outlines.\n"); } // Does the graphics library support multitexturing? numTexUnits = GL_state.maxTexUnits; envModAdd = (DGL_GetInteger(DGL_MODULATE_ADD_COMBINE)? true : false); if(numTexUnits > 1) { Con_Printf(" Multitexturing enabled (%s).\n", envModAdd ? "full" : "partial"); } else { // Can't use multitexturing... Con_Printf(" Multitexturing not available.\n"); } // Initialize the renderer into a 2D state. GL_Init2DState(); // Allow font rendering. FR_Init(); // Render a few black frames before we continue. This will help to // stableize things before we begin drawing for real and to avoid any // unwanted video artefacts. { int i = 0; while(i++ < 3) { glClear(GL_COLOR_BUFFER_BIT); GL_DoUpdate(); } } initGLOk = true; return true; } /** * Finishes GL initialization. This can be called once the virtual file * system has been fully loaded up, and the console variables have been * read from the config file. */ void GL_Init(void) { if(!initGLOk) { Con_Error("GL_Init: GL_EarlyInit has not been done yet.\n"); } // Initialize font renderer. GL_InitFont(); // Initialize palette management. GL_InitPalettedTexture(); // Set the gamma in accordance with vid-gamma, vid-bright and // vid-contrast. GL_SetGamma(); // Initialize one viewport. R_SetViewGrid(1, 1); } /** * Initializes the graphics library for refresh. Also called at update. */ void GL_InitRefresh(void) { GL_InitTextureManager(); } /** * Called once at final shutdown. */ void GL_ShutdownRefresh(void) { GL_ShutdownTextureManager(); R_DestroySkins(); R_DestroyDetailTextures(); R_DestroyLightMaps(); R_DestroyFlareTextures(); R_DestroyShinyTextures(); R_DestroyMaskTextures(); } /** * Kills the graphics library for good. */ void GL_Shutdown(void) { if(!initGLOk) return; // Not yet initialized fully. GL_ShutdownDeferred(); GL_ShutdownFont(); Rend_ShutdownSky(); Rend_Reset(); GL_ShutdownRefresh(); // Shutdown OpenGL. Sys_ShutdownGL(); // Restore original gamma. if(!ArgExists("-leaveramp")) { GL_SetGammaRamp(original_gamma_ramp); } initGLOk = false; } /** * Initializes the renderer to 2D state. */ void GL_Init2DState(void) { // The variables. glNearClip = 5; glFarClip = 16500; // Here we configure the OpenGL state and set the projection matrix. glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); // The projection matrix. glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, 320, 200, 0, -1, 1); // Default state for the white fog is off. usingFog = false; glDisable(GL_FOG); glFogi(GL_FOG_MODE, (fogModeDefault == 0 ? GL_LINEAR : fogModeDefault == 1 ? GL_EXP : GL_EXP2)); glFogf(GL_FOG_START, DEFAULT_FOG_START); glFogf(GL_FOG_END, DEFAULT_FOG_END); glFogf(GL_FOG_DENSITY, DEFAULT_FOG_DENSITY); fogColor[0] = DEFAULT_FOG_COLOR_RED; fogColor[1] = DEFAULT_FOG_COLOR_GREEN; fogColor[2] = DEFAULT_FOG_COLOR_BLUE; fogColor[3] = 1; glFogfv(GL_FOG_COLOR, fogColor); } void GL_SwitchTo3DState(boolean push_state, viewport_t* port) { if(push_state) { // Push the 2D matrices on the stack. glMatrixMode(GL_PROJECTION); glPushMatrix(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); #if 0 viewpx = viewwindowx * theWindow->width / 320, viewpy = viewwindowy * theWindow->height / 200; // Set the viewport. if(viewheight != SCREENHEIGHT) { viewpw = viewwidth * theWindow->width / 320; viewph = viewheight * theWindow->height / 200 + 1; glViewport(viewpx, FLIP(viewpy + viewph - 1), viewpw, viewph); } else { viewpw = theWindow->width; viewph = theWindow->height; } #endif memcpy(¤tView, port, sizeof(currentView)); viewpx = port->x + viewwindowx / 320.0f * port->width; viewpy = port->y + viewwindowy / 200.0f * port->height; viewpw = port->width * viewwidth / 320.0f; viewph = port->height * viewheight / 200.0f; glViewport(viewpx, FLIP(viewpy + viewph - 1), viewpw, viewph); // The 3D projection matrix. GL_ProjectionMatrix(); } void GL_Restore2DState(int step) { switch(step) { case 1: // After Restore Step 1 normal player sprites are rendered. glMatrixMode(GL_PROJECTION); glLoadIdentity(); // FIXME: Aspect ratio when not 4:3. glOrtho(0, 320, (320 * viewheight) / viewwidth, 0, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Depth testing must be disabled so that psprite 1 will be drawn // on top of psprite 0 (Doom plasma rifle fire). glDisable(GL_DEPTH_TEST); break; case 2: // After Restore Step 2 nothing special happens. glViewport(currentView.x, FLIP(currentView.y + currentView.height - 1), currentView.width, currentView.height); break; case 3: // After Restore Step 3 we're back in 2D rendering mode. glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); break; default: Con_Error("GL_Restore2DState: Invalid value, step = %i.", step); break; } } void GL_ProjectionMatrix(void) { // We're assuming pixels are squares. float aspect = viewpw / (float) viewph; glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(yfov = fieldOfView / aspect, aspect, glNearClip, glFarClip); // We'd like to have a left-handed coordinate system. glScalef(1, 1, -1); } void GL_UseFog(int yes) { usingFog = yes; } /** * GL is reset back to the state it was right after initialization. * Use GL_TotalRestore to bring back online. */ void GL_TotalReset(void) { if(isDedicated) return; //GL_ShutdownVarFont(); // Update the secondary title and the game status. Con_InitUI(); // Delete all textures. GL_ResetTextureManager(); GL_ShutdownFont(); GL_ReleaseReservedNames(); #if _DEBUG Z_CheckHeap(); #endif } /** * Called after a GL_TotalReset to bring GL back online. */ void GL_TotalRestore(void) { if(isDedicated) return; // Getting back up and running. GL_ReserveNames(); GL_InitFont(); //GL_InitVarFont(); GL_Init2DState(); GL_InitPalettedTexture(); { gamemap_t* map = P_GetCurrentMap(); ded_mapinfo_t* mapInfo = Def_GetMapInfo(P_GetMapID(map)); // Restore map's fog settings. if(!mapInfo || !(mapInfo->flags & MIF_FOG)) R_SetupFogDefaults(); else R_SetupFog(mapInfo->fogStart, mapInfo->fogEnd, mapInfo->fogDensity, mapInfo->fogColor); } #if _DEBUG Z_CheckHeap(); #endif } /** * Copies the current contents of the frame buffer and returns a pointer * to data containing 24-bit RGB triplets. The caller must free the * returned buffer using M_Free()! */ unsigned char* GL_GrabScreen(void) { unsigned char* buffer = 0; buffer = M_Malloc(theWindow->width * theWindow->height * 3); GL_Grab(0, 0, theWindow->width, theWindow->height, DGL_RGB, buffer); return buffer; } /** * Set the GL blending mode. */ void GL_BlendMode(blendmode_t mode) { switch(mode) { case BM_ZEROALPHA: GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_ONE, GL_ZERO); break; case BM_ADD: GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; case BM_DARK: GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); break; case BM_SUBTRACT: GL_BlendOp(GL_FUNC_SUBTRACT); glBlendFunc(GL_ONE, GL_SRC_ALPHA); break; case BM_ALPHA_SUBTRACT: GL_BlendOp(GL_FUNC_SUBTRACT); glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; case BM_REVERSE_SUBTRACT: GL_BlendOp(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_SRC_ALPHA, GL_ONE); break; case BM_MUL: GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_ZERO, GL_SRC_COLOR); break; case BM_INVERSE: GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR); break; case BM_INVERSE_MUL: GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR); break; default: GL_BlendOp(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); break; } } void GL_LowRes(void) { // Set everything as low as they go. filterSprites = 0; linearRaw = 0; texMagMode = 0; // And do a texreset so everything is updated. GL_SetTextureParams(GL_NEAREST, true, true); GL_TexReset(); } /** * Change graphics mode resolution. */ D_CMD(SetRes) { int width = atoi(argv[1]), height = atoi(argv[2]); return Sys_SetWindow(windowIDX, 0, 0, width, height, 0, 0, DDSW_NOVISIBLE|DDSW_NOCENTER|DDSW_NOFULLSCREEN| DDSW_NOBPP); } D_CMD(ToggleFullscreen) { boolean fullscreen; if(!Sys_GetWindowFullscreen(windowIDX, &fullscreen)) Con_Message("CCmd 'ToggleFullscreen': Failed acquiring window " "fullscreen"); else Sys_SetWindow(windowIDX, 0, 0, 0, 0, 0, (!fullscreen? DDWF_FULLSCREEN : 0), DDSW_NOCENTER|DDSW_NOSIZE|DDSW_NOBPP|DDSW_NOVISIBLE); return true; } D_CMD(UpdateGammaRamp) { GL_SetGamma(); Con_Printf("Gamma ramp set.\n"); return true; } D_CMD(SetBPP) { int bpp = atoi(argv[1]); if(bpp != 16 && bpp != 32) { bpp = 32; Con_Printf("%d not valid for bits per pixel, setting to 32.\n", bpp); } return Sys_SetWindow(windowIDX, 0, 0, 0, 0, bpp, 0, DDSW_NOCENTER|DDSW_NOSIZE|DDSW_NOFULLSCREEN| DDSW_NOVISIBLE); } D_CMD(Fog) { int i; if(argc == 1) { Con_Printf("Usage: %s (cmd) (args)\n", argv[0]); Con_Printf("Commands: on, off, mode, color, start, end, density.\n"); Con_Printf("Modes: linear, exp, exp2.\n"); //Con_Printf( "Hints: fastest, nicest, dontcare.\n"); Con_Printf("Color is given as RGB (0-255).\n"); Con_Printf ("Start and end are for linear fog, density for exponential.\n"); return true; } if(!stricmp(argv[1], "on")) { GL_UseFog(true); Con_Printf("Fog is now active.\n"); } else if(!stricmp(argv[1], "off")) { GL_UseFog(false); Con_Printf("Fog is now disabled.\n"); } else if(!stricmp(argv[1], "mode") && argc == 3) { if(!stricmp(argv[2], "linear")) { glFogi(GL_FOG_MODE, GL_LINEAR); Con_Printf("Fog mode set to linear.\n"); } else if(!stricmp(argv[2], "exp")) { glFogi(GL_FOG_MODE, GL_EXP); Con_Printf("Fog mode set to exp.\n"); } else if(!stricmp(argv[2], "exp2")) { glFogi(GL_FOG_MODE, GL_EXP2); Con_Printf("Fog mode set to exp2.\n"); } else return false; } else if(!stricmp(argv[1], "color") && argc == 5) { for(i = 0; i < 3; i++) fogColor[i] = strtol(argv[2 + i], NULL, 0) / 255.0f; fogColor[3] = 1; glFogfv(GL_FOG_COLOR, fogColor); Con_Printf("Fog color set.\n"); } else if(!stricmp(argv[1], "start") && argc == 3) { glFogf(GL_FOG_START, (GLfloat) strtod(argv[2], NULL)); Con_Printf("Fog start distance set.\n"); } else if(!stricmp(argv[1], "end") && argc == 3) { glFogf(GL_FOG_END, (GLfloat) strtod(argv[2], NULL)); Con_Printf("Fog end distance set.\n"); } else if(!stricmp(argv[1], "density") && argc == 3) { glFogf(GL_FOG_DENSITY, (GLfloat) strtod(argv[2], NULL)); Con_Printf("Fog density set.\n"); } else return false; // Exit with a success. return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_data.c0000644000175000017500000021376511357170242022345 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_data.c: Data Structures and Constants for Refresh */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_misc.h" #include "de_audio.h" // For texture, environmental audio properties. #include "m_stack.h" // MACROS ------------------------------------------------------------------ #define PATCHTEX_HASH_SIZE 128 #define PATCHTEX_HASH(x) (patchtexhash + (((unsigned) x) & (PATCHTEX_HASH_SIZE - 1))) #define RAWTEX_HASH_SIZE 128 #define RAWTEX_HASH(x) (rawtexhash + (((unsigned) x) & (RAWTEX_HASH_SIZE - 1))) #define COLORPALETTENAME_MAXLEN (32) // TYPES ------------------------------------------------------------------- typedef struct patchtexhash_s { patchtex_t* first; } patchtexhash_t; typedef struct rawtexhash_s { rawtex_t* first; } rawtexhash_t; typedef enum { RPT_VERT, RPT_COLOR, RPT_TEXCOORD } rpolydatatype_t; typedef struct { boolean inUse; rpolydatatype_t type; uint num; void* data; } rendpolydata_t; /** * DGL color palette name bindings. * These are mainly intended as a public API convenience. * Internally, we are only interested in the associated DGL name(s). */ typedef struct { char name[COLORPALETTENAME_MAXLEN+1]; DGLuint id; } colorpalettebind_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- int gameDataFormat; // Use a game-specifc data format where applicable. extern boolean mapSetup; // We are currently setting up a map. // PUBLIC DATA DEFINITIONS ------------------------------------------------- byte precacheSkins = true; byte precacheSprites = true; int numFlats = 0; flat_t** flats = NULL; int numSpriteTextures = 0; spritetex_t** spriteTextures = NULL; int numDetailTextures = 0; detailtex_t** detailTextures = NULL; int numLightMaps = 0; lightmap_t** lightMaps = NULL; int numFlareTextures = 0; flaretex_t** flareTextures = NULL; int numShinyTextures = 0; shinytex_t** shinyTextures = NULL; int numMaskTextures = 0; masktex_t** maskTextures = NULL; // Glowing textures are always rendered fullbright. int glowingTextures = true; byte rendInfoRPolys = 0; // Skinnames will only *grow*. It will never be destroyed, not even // at resets. The skin textures themselves will be deleted, though. // This is because we want to have permanent ID numbers for skins, // and the ID numbers are the same as indices to the skinNames array. // Created in r_model.c, when registering the skins. uint numSkinNames = 0; skinname_t* skinNames = NULL; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int numDoomTextureDefs; static doomtexturedef_t** doomTextureDefs; static patchtexhash_t patchtexhash[PATCHTEX_HASH_SIZE]; static rawtexhash_t rawtexhash[RAWTEX_HASH_SIZE]; static unsigned int numrendpolys = 0; static unsigned int maxrendpolys = 0; static rendpolydata_t** rendPolys; static colorpalettebind_t* colorPalettes = NULL; static uint numColorPalettes = 0; static colorpaletteid_t defaultColorPalette = 0; // CODE -------------------------------------------------------------------- static colorpaletteid_t colorPaletteNumForName(const char* name) { uint i; // Linear search (sufficiently fast enough given the probably small set // and infrequency of searches). for(i = 0; i < numColorPalettes; ++i) { colorpalettebind_t* pal = &colorPalettes[i]; if(!strnicmp(pal->name, name, COLORPALETTENAME_MAXLEN)) return i + 1; // Already registered. 1-based index. } return 0; // Not found. } /** * Given a colorpalette id return the associated DGL color palette num. * If the specified id cannot be found, the default color palette will be * returned instead. * * @param id Id of the color palette to be prepared. * * @return The DGL palette number iff found else @c NULL. */ DGLuint R_GetColorPalette(colorpaletteid_t id) { if(!id || id - 1 >= numColorPalettes) { if(numColorPalettes) return colorPalettes[defaultColorPalette-1].id; return 0; } return colorPalettes[id-1].id; } /** * Change the default color palette. * * @param id Id of the color palette to make default. * * @return @c true iff successful, else @c NULL. */ boolean R_SetDefaultColorPalette(colorpaletteid_t id) { if(id && id - 1 < numColorPalettes) { defaultColorPalette = id; return true; } VERBOSE(Con_Message("R_SetDefaultColorPalette: Invalid id %u.\n", id)) return false; } /** * Add a new (named) color palette. * \note Part of the Doomsday public API. * * \design The idea with the two-teered implementation is to allow maximum * flexibility. Within the engine we can create new palettes and manipulate * them directly via the DGL interface. The underlying implementation is * wrapped in a similar way to the materials so that publically, there is a * set of (eternal) names and unique identifiers that survive engine and * GL resets. * * @param fmt Format string describes the format of @p data. * Expected form: "C#C#C" * C = color component, one of R, G, B. * # = bits per component. * @param name Unique name by which the palette will be known. * @param data Buffer containing the src color data. * @param num Number of sets of components). * * @return Color palette id. */ colorpaletteid_t R_CreateColorPalette(const char* fmt, const char* name, const byte* data, ushort num) { #define MAX_BPC (16) // Max bits per component. static const char* compNames[] = { "red", "green", "blue" }; colorpaletteid_t id; colorpalettebind_t* pal; const char* c, *end; int i, pos, compOrder[3]; byte compSize[3]; if(!name || !name[0]) Con_Error("R_CreateColorPalette: Color palettes require a name.\n"); if(strlen(name) > COLORPALETTENAME_MAXLEN) Con_Error("R_CreateColorPalette: Failed creating \"%s\", " "color palette name can be at most %i characters long.\n", name, COLORPALETTENAME_MAXLEN); if(!fmt || !fmt[0]) Con_Error("R_CreateColorPalette: Failed creating \"%s\", " "missing format string.\n", name); if(!data || !num) Con_Error("R_CreateColorPalette: Failed creating \"%s\", " "cannot create a zero-sized palette.\n", name); // All arguments supplied. Parse the format string. memset(compOrder, -1, sizeof(compOrder)); pos = 0; end = fmt + (strlen(fmt) - 1); c = fmt; do { int comp = -1; if(*c == 'R' || *c == 'r') comp = CR; else if(*c == 'G' || *c == 'g') comp = CG; else if(*c == 'B' || *c == 'b') comp = CB; if(comp != -1) { // Have encountered this component yet? if(compOrder[comp] == -1) { // No. const char* start; size_t numDigits; compOrder[comp] = pos++; // Read the number of bits. start = ++c; while((*c >= '0' && *c <= '9') && ++c < end); numDigits = c - start; if(numDigits != 0 && numDigits <= 2) { char buf[3]; memset(buf, 0, sizeof(buf)); memcpy(buf, start, numDigits); compSize[comp] = atoi(buf); if(pos == 3) break; // We're done. // Unread the last character. c--; continue; } } } Con_Error("R_CreateColorPalette: Failed creating \"%s\", " "invalid character '%c' in format string at " "position %u.\n", name, *c, (unsigned int) (c - fmt)); } while(++c <= end); if(pos != 3) Con_Error("R_CreateColorPalette: Failed creating \"%s\", " "incomplete format specification.\n", name); // Check validity of bits per component. for(i = 0; i < 3; ++i) if(compSize[i] == 0 || compSize[i] > MAX_BPC) { Con_Error("R_CreateColorPalette: Failed creating \"%s\", " "unsupported bit size %i for %s component.\n", name, compSize[i], compNames[compOrder[i]]); } if((id = colorPaletteNumForName(name))) { // We are replacing an existing palette. pal = &colorPalettes[id-1]; // Destroy the existing DGL color palette. GL_DeleteColorPalettes(1, &pal->id); pal->id = 0; } else { // We are creating a new palette. if(!numColorPalettes) { colorPalettes = Z_Malloc( ++numColorPalettes * sizeof(colorpalettebind_t), PU_STATIC, 0); defaultColorPalette = numColorPalettes; } else colorPalettes = Z_Realloc(&colorPalettes, ++numColorPalettes * sizeof(colorpalettebind_t), PU_STATIC); pal = &colorPalettes[numColorPalettes-1]; memset(pal, 0, sizeof(*pal)); strncpy(pal->name, name, COLORPALETTENAME_MAXLEN); id = numColorPalettes; // 1-based index. } // Generate the actual DGL color palette. pal->id = GL_CreateColorPalette(compOrder, compSize, data, num); return id; // 1-based index. #undef MAX_BPC } /** * Given a color palette name, look up the associated identifier. * \note Part of the Doomsday public API. * * @param name Unique name of the palette to locate. * @return Iff found, identifier of the palette associated * with this name, ELSE @c 0. */ colorpaletteid_t R_GetColorPaletteNumForName(const char* name) { if(name && name[0] && strlen(name) <= COLORPALETTENAME_MAXLEN) return colorPaletteNumForName(name); return 0; } /** * Given a color palette id, look up the specified unique name. * \note Part of the Doomsday public API. * * @param id Id of the color palette to locate. * @return Iff found, pointer to the unique name associated * with the specified id, ELSE @c NULL. */ const char* R_GetColorPaletteNameForNum(colorpaletteid_t id) { if(id && id - 1 < numColorPalettes) return colorPalettes[id-1].name; return NULL; } /** * Given a color palette index, calculate the equivilent RGB color. * \note Part of the Doomsday public API. * * @param id Id of the color palette to use. * @param rgb Final color will be written back here. * @param idx Color Palette, color index. * @param correctGamma @c TRUE if the current gamma ramp should be applied. */ void R_GetColorPaletteRGBf(colorpaletteid_t id, float rgb[3], int idx, boolean correctGamma) { if(rgb) { if(idx >= 0) { DGLuint pal = R_GetColorPalette(id); DGLubyte rgbUBV[3]; GL_GetColorPaletteRGB(pal, rgbUBV, idx); if(correctGamma) { rgbUBV[CR] = gammaTable[rgbUBV[CR]]; rgbUBV[CG] = gammaTable[rgbUBV[CG]]; rgbUBV[CB] = gammaTable[rgbUBV[CB]]; } rgb[CR] = rgbUBV[CR] * reciprocal255; rgb[CG] = rgbUBV[CG] * reciprocal255; rgb[CB] = rgbUBV[CB] * reciprocal255; return; } rgb[CR] = rgb[CG] = rgb[CB] = 0; } } void R_InfoRendVerticesPool(void) { uint i; if(!rendInfoRPolys) return; Con_Printf("RP Count: %-4i\n", numrendpolys); for(i = 0; i < numrendpolys; ++i) { rendpolydata_t* rp = rendPolys[i]; Con_Printf("RP: %-4u %c (vtxs=%u t=%c)\n", i, (rp->inUse? 'Y':'N'), rp->num, (rp->type == RPT_VERT? 'v' : rp->type == RPT_COLOR?'c' : 't')); } } /** * Called at the start of each map. */ void R_InitRendVerticesPool(void) { rvertex_t* rvertices; rcolor_t* rcolors; rtexcoord_t* rtexcoords; numrendpolys = maxrendpolys = 0; rendPolys = NULL; rvertices = R_AllocRendVertices(24); rcolors = R_AllocRendColors(24); rtexcoords = R_AllocRendTexCoords(24); // Mark unused. R_FreeRendVertices(rvertices); R_FreeRendColors(rcolors); R_FreeRendTexCoords(rtexcoords); } /** * Retrieves a batch of rvertex_t. * Possibly allocates new if necessary. * * @param num The number of verts required. * * @return Ptr to array of rvertex_t */ rvertex_t* R_AllocRendVertices(uint num) { unsigned int idx; boolean found = false; for(idx = 0; idx < maxrendpolys; ++idx) { if(rendPolys[idx]->inUse || rendPolys[idx]->type != RPT_VERT) continue; if(rendPolys[idx]->num >= num) { // Use this one. rendPolys[idx]->inUse = true; return (rvertex_t*) rendPolys[idx]->data; } else if(rendPolys[idx]->num == 0) { // There is an unused one but we haven't allocated verts yet. numrendpolys++; found = true; break; } } if(!found) { // We may need to allocate more. if(++numrendpolys > maxrendpolys) { uint i, newCount; rendpolydata_t* newPolyData, *ptr; maxrendpolys = (maxrendpolys > 0? maxrendpolys * 2 : 8); rendPolys = Z_Realloc(rendPolys, sizeof(rendpolydata_t*) * maxrendpolys, PU_MAP); newCount = maxrendpolys - numrendpolys + 1; newPolyData = Z_Malloc(sizeof(rendpolydata_t) * newCount, PU_MAP, 0); ptr = newPolyData; for(i = numrendpolys-1; i < maxrendpolys; ++i, ptr++) { ptr->inUse = false; ptr->num = 0; ptr->data = NULL; ptr->type = RPT_VERT; rendPolys[i] = ptr; } } idx = numrendpolys - 1; } rendPolys[idx]->inUse = true; rendPolys[idx]->type = RPT_VERT; rendPolys[idx]->num = num; rendPolys[idx]->data = Z_Malloc(sizeof(rvertex_t) * num, PU_MAP, 0); return (rvertex_t*) rendPolys[idx]->data; } /** * Retrieves a batch of rcolor_t. * Possibly allocates new if necessary. * * @param num The number of verts required. * * @return Ptr to array of rcolor_t */ rcolor_t* R_AllocRendColors(uint num) { unsigned int idx; boolean found = false; for(idx = 0; idx < maxrendpolys; ++idx) { if(rendPolys[idx]->inUse || rendPolys[idx]->type != RPT_COLOR) continue; if(rendPolys[idx]->num >= num) { // Use this one. rendPolys[idx]->inUse = true; return (rcolor_t*) rendPolys[idx]->data; } else if(rendPolys[idx]->num == 0) { // There is an unused one but we haven't allocated verts yet. numrendpolys++; found = true; break; } } if(!found) { // We may need to allocate more. if(++numrendpolys > maxrendpolys) { uint i, newCount; rendpolydata_t* newPolyData, *ptr; maxrendpolys = (maxrendpolys > 0? maxrendpolys * 2 : 8); rendPolys = Z_Realloc(rendPolys, sizeof(rendpolydata_t*) * maxrendpolys, PU_MAP); newCount = maxrendpolys - numrendpolys + 1; newPolyData = Z_Malloc(sizeof(rendpolydata_t) * newCount, PU_MAP, 0); ptr = newPolyData; for(i = numrendpolys-1; i < maxrendpolys; ++i, ptr++) { ptr->inUse = false; ptr->num = 0; ptr->data = NULL; ptr->type = RPT_COLOR; rendPolys[i] = ptr; } } idx = numrendpolys - 1; } rendPolys[idx]->inUse = true; rendPolys[idx]->type = RPT_COLOR; rendPolys[idx]->num = num; rendPolys[idx]->data = Z_Malloc(sizeof(rcolor_t) * num, PU_MAP, 0); return (rcolor_t*) rendPolys[idx]->data; } /** * Retrieves a batch of rtexcoord_t. * Possibly allocates new if necessary. * * @param num The number required. * * @return Ptr to array of rtexcoord_t */ rtexcoord_t* R_AllocRendTexCoords(uint num) { unsigned int idx; boolean found = false; for(idx = 0; idx < maxrendpolys; ++idx) { if(rendPolys[idx]->inUse || rendPolys[idx]->type != RPT_TEXCOORD) continue; if(rendPolys[idx]->num >= num) { // Use this one. rendPolys[idx]->inUse = true; return (rtexcoord_t*) rendPolys[idx]->data; } else if(rendPolys[idx]->num == 0) { // There is an unused one but we haven't allocated verts yet. numrendpolys++; found = true; break; } } if(!found) { // We may need to allocate more. if(++numrendpolys > maxrendpolys) { uint i, newCount; rendpolydata_t* newPolyData, *ptr; maxrendpolys = (maxrendpolys > 0? maxrendpolys * 2 : 8); rendPolys = Z_Realloc(rendPolys, sizeof(rendpolydata_t*) * maxrendpolys, PU_MAP); newCount = maxrendpolys - numrendpolys + 1; newPolyData = Z_Malloc(sizeof(rendpolydata_t) * newCount, PU_MAP, 0); ptr = newPolyData; for(i = numrendpolys-1; i < maxrendpolys; ++i, ptr++) { ptr->inUse = false; ptr->num = 0; ptr->data = NULL; ptr->type = RPT_TEXCOORD; rendPolys[i] = ptr; } } idx = numrendpolys - 1; } rendPolys[idx]->inUse = true; rendPolys[idx]->type = RPT_TEXCOORD; rendPolys[idx]->num = num; rendPolys[idx]->data = Z_Malloc(sizeof(rtexcoord_t) * num, PU_MAP, 0); return (rtexcoord_t*) rendPolys[idx]->data; } /** * Doesn't actually free anything. Instead, mark them as unused ready for * the next time a batch of rendvertex_t is needed. * * @param vertices Ptr to array of rvertex_t to mark unused. */ void R_FreeRendVertices(rvertex_t* rvertices) { uint i; if(!rvertices) return; for(i = 0; i < numrendpolys; ++i) { if(rendPolys[i]->data == rvertices) { rendPolys[i]->inUse = false; return; } } #if _DEBUG Con_Message("R_FreeRendPoly: Dangling poly ptr!\n"); #endif } /** * Doesn't actually free anything. Instead, mark them as unused ready for * the next time a batch of rendvertex_t is needed. * * @param vertices Ptr to array of rcolor_t to mark unused. */ void R_FreeRendColors(rcolor_t* rcolors) { uint i; if(!rcolors) return; for(i = 0; i < numrendpolys; ++i) { if(rendPolys[i]->data == rcolors) { rendPolys[i]->inUse = false; return; } } #if _DEBUG Con_Message("R_FreeRendPoly: Dangling poly ptr!\n"); #endif } /** * Doesn't actually free anything. Instead, mark them as unused ready for * the next time a batch of rendvertex_t is needed. * * @param rtexcoords Ptr to array of rtexcoord_t to mark unused. */ void R_FreeRendTexCoords(rtexcoord_t* rtexcoords) { uint i; if(!rtexcoords) return; for(i = 0; i < numrendpolys; ++i) { if(rendPolys[i]->data == rtexcoords) { rendPolys[i]->inUse = false; return; } } #if _DEBUG Con_Message("R_FreeRendPoly: Dangling poly ptr!\n"); #endif } void R_DivVerts(rvertex_t* dst, const rvertex_t* src, const walldiv_t* divs) { #define COPYVERT(d, s) (d)->pos[VX] = (s)->pos[VX]; \ (d)->pos[VY] = (s)->pos[VY]; \ (d)->pos[VZ] = (s)->pos[VZ]; uint i; uint numL = 3 + divs[0].num; uint numR = 3 + divs[1].num; // Right fan: COPYVERT(&dst[numL + 0], &src[0]) COPYVERT(&dst[numL + 1], &src[3]); COPYVERT(&dst[numL + numR - 1], &src[2]); for(i = 0; i < divs[1].num; ++i) { dst[numL + 2 + i].pos[VX] = src[2].pos[VX]; dst[numL + 2 + i].pos[VY] = src[2].pos[VY]; dst[numL + 2 + i].pos[VZ] = divs[1].pos[i]; } // Left fan: COPYVERT(&dst[0], &src[3]); COPYVERT(&dst[1], &src[0]); COPYVERT(&dst[numL - 1], &src[1]); for(i = 0; i < divs[0].num; ++i) { dst[2 + i].pos[VX] = src[0].pos[VX]; dst[2 + i].pos[VY] = src[0].pos[VY]; dst[2 + i].pos[VZ] = divs[0].pos[i]; } #undef COPYVERT } void R_DivTexCoords(rtexcoord_t* dst, const rtexcoord_t* src, const walldiv_t* divs, float bL, float tL, float bR, float tR) { #define COPYTEXCOORD(d, s) (d)->st[0] = (s)->st[0]; \ (d)->st[1] = (s)->st[1]; uint i; uint numL = 3 + divs[0].num; uint numR = 3 + divs[1].num; float height; // Right fan: COPYTEXCOORD(&dst[numL + 0], &src[0]); COPYTEXCOORD(&dst[numL + 1], &src[3]); COPYTEXCOORD(&dst[numL + numR-1], &src[2]); height = tR - bR; for(i = 0; i < divs[1].num; ++i) { float inter = (divs[1].pos[i] - bR) / height; dst[numL + 2 + i].st[0] = src[2].st[0]; dst[numL + 2 + i].st[1] = src[2].st[1] + (src[3].st[1] - src[2].st[1]) * inter; } // Left fan: COPYTEXCOORD(&dst[0], &src[3]); COPYTEXCOORD(&dst[1], &src[0]); COPYTEXCOORD(&dst[numL - 1], &src[1]); height = tL - bL; for(i = 0; i < divs[0].num; ++i) { float inter = (divs[0].pos[i] - bL) / height; dst[2 + i].st[0] = src[0].st[0]; dst[2 + i].st[1] = src[0].st[1] + (src[1].st[1] - src[0].st[1]) * inter; } #undef COPYTEXCOORD } void R_DivVertColors(rcolor_t* dst, const rcolor_t* src, const walldiv_t* divs, float bL, float tL, float bR, float tR) { #define COPYVCOLOR(d, s) (d)->rgba[CR] = (s)->rgba[CR]; \ (d)->rgba[CG] = (s)->rgba[CG]; \ (d)->rgba[CB] = (s)->rgba[CB]; \ (d)->rgba[CA] = (s)->rgba[CA]; uint i; uint numL = 3 + divs[0].num; uint numR = 3 + divs[1].num; float height; // Right fan: COPYVCOLOR(&dst[numL + 0], &src[0]); COPYVCOLOR(&dst[numL + 1], &src[3]); COPYVCOLOR(&dst[numL + numR-1], &src[2]); height = tR - bR; for(i = 0; i < divs[1].num; ++i) { uint c; float inter = (divs[1].pos[i] - bR) / height; for(c = 0; c < 4; ++c) { dst[numL + 2 + i].rgba[c] = src[2].rgba[c] + (src[3].rgba[c] - src[2].rgba[c]) * inter; } } // Left fan: COPYVCOLOR(&dst[0], &src[3]); COPYVCOLOR(&dst[1], &src[0]); COPYVCOLOR(&dst[numL - 1], &src[1]); height = tL - bL; for(i = 0; i < divs[0].num; ++i) { uint c; float inter = (divs[0].pos[i] - bL) / height; for(c = 0; c < 4; ++c) { dst[2 + i].rgba[c] = src[0].rgba[c] + (src[1].rgba[c] - src[0].rgba[c]) * inter; } } #undef COPYVCOLOR } void R_ShutdownData(void) { P_ShutdownMaterialManager(); } /** * Returns a NULL-terminated array of pointers to all the patchetexs. * The array must be freed with Z_Free. */ patchtex_t** R_CollectPatchTexs(int* count) { int i, num; patchtex_t* p, **list; // First count the number of patchtexs. for(num = 0, i = 0; i < PATCHTEX_HASH_SIZE; ++i) for(p = patchtexhash[i].first; p; p = p->next) num++; // Tell this to the caller. if(count) *count = num; // Allocate the array, plus one for the terminator. list = Z_Malloc(sizeof(p) * (num + 1), PU_STATIC, NULL); // Collect the pointers. for(num = 0, i = 0; i < PATCHTEX_HASH_SIZE; ++i) for(p = patchtexhash[i].first; p; p = p->next) list[num++] = p; // Terminate. list[num] = NULL; return list; } /** * Returns a patchtex_t* for the given lump, if one already exists. */ patchtex_t* R_FindPatchTex(lumpnum_t lump) { patchtex_t* i; patchtexhash_t* hash = PATCHTEX_HASH(lump); for(i = hash->first; i; i = i->next) if(i->lump == lump) { return i; } return NULL; } /** * Get a patchtex_t data structure for a patch specified with a WAD lump * number. Allocates a new patchtex_t if it hasn't been loaded yet. */ patchtex_t* R_GetPatchTex(lumpnum_t lump) { patchtex_t* p = 0; patchtexhash_t* hash = 0; if(lump >= numLumps) { Con_Error("R_GetPatchTex: lump = %i out of bounds (%i).\n", lump, numLumps); } p = R_FindPatchTex(lump); if(!lump) return NULL; // Check if this lump has already been loaded as a patch. if(p) return p; // Hmm, this is an entirely new patch. p = Z_Calloc(sizeof(*p), PU_PATCH, NULL); hash = PATCHTEX_HASH(lump); // Link to the hash. p->next = hash->first; hash->first = p; // Init the new one. p->lump = lump; return p; } /** * Returns a NULL-terminated array of pointers to all the rawtexs. * The array must be freed with Z_Free. */ rawtex_t** R_CollectRawTexs(int* count) { int i, num; rawtex_t* r, **list; // First count the number of patchtexs. for(num = 0, i = 0; i < RAWTEX_HASH_SIZE; ++i) for(r = rawtexhash[i].first; r; r = r->next) num++; // Tell this to the caller. if(count) *count = num; // Allocate the array, plus one for the terminator. list = Z_Malloc(sizeof(r) * (num + 1), PU_STATIC, NULL); // Collect the pointers. for(num = 0, i = 0; i < RAWTEX_HASH_SIZE; ++i) for(r = rawtexhash[i].first; r; r = r->next) list[num++] = r; // Terminate. list[num] = NULL; return list; } /** * Returns a rawtex_t* for the given lump, if one already exists. */ rawtex_t *R_FindRawTex(lumpnum_t lump) { rawtex_t* i; rawtexhash_t* hash = RAWTEX_HASH(lump); for(i = hash->first; i; i = i->next) if(i->lump == lump) { return i; } return NULL; } /** * Get a rawtex_t data structure for a raw texture specified with a WAD lump * number. Allocates a new rawtex_t if it hasn't been loaded yet. */ rawtex_t* R_GetRawTex(lumpnum_t lump) { rawtex_t* r = 0; rawtexhash_t* hash = 0; if(lump >= numLumps) { Con_Error("R_GetRawTex: lump = %i out of bounds (%i).\n", lump, numLumps); } r = R_FindRawTex(lump); if(!lump) return NULL; // Check if this lump has already been loaded as a rawtex. if(r) return r; // Hmm, this is an entirely new rawtex. r = Z_Calloc(sizeof(*r), PU_PATCH, NULL); // \todo Need a new cache tag? hash = RAWTEX_HASH(lump); // Link to the hash. r->next = hash->first; hash->first = r; // Init the new one. r->lump = lump; return r; } static lumpnum_t* loadPatchList(lumpnum_t lump, size_t* num) { char name[9], *names; lumpnum_t* patchLumpList; size_t i, numPatches, lumpSize = W_LumpLength(lump); names = M_Malloc(lumpSize); W_ReadLump(lump, names); numPatches = LONG(*((int *) names)); if(numPatches > (lumpSize - 4) / 8) { // Lump is truncated. Con_Message("loadPatchList: Warning, lump '%s' truncated (%lu bytes, " "expected %lu).\n", W_LumpName(lump), (unsigned long) lumpSize, (unsigned long) (numPatches * 8 + 4)); numPatches = (lumpSize - 4) / 8; } patchLumpList = M_Malloc(numPatches * sizeof(*patchLumpList)); for(i = 0; i < numPatches; ++i) { memset(name, 0, sizeof(name)); strncpy(name, names + 4 + i * 8, 8); patchLumpList[i] = W_CheckNumForName(name); if(patchLumpList[i] == -1) { Con_Message("loadPatchList: Warning, missing patch '%s'.\n", name); } } M_Free(names); if(num) *num = numPatches; return patchLumpList; } /** * Read DOOM and Strife format texture definitions from the specified lump. */ static doomtexturedef_t** readDoomTextureDefLump(lumpnum_t lump, lumpnum_t* patchlookup, size_t numPatches, boolean firstNull, int* numDefs) { #pragma pack(1) typedef struct { int16_t originX; int16_t originY; int16_t patch; int16_t stepDir; int16_t colorMap; } mappatch_t; typedef struct { byte name[8]; int16_t unused; byte scale[2]; // [x, y] Used by ZDoom, div 8. int16_t width; int16_t height; //void **columnDirectory; // OBSOLETE int32_t columnDirectoryPadding; int16_t patchCount; mappatch_t patches[1]; } maptexture_t; // strifeformat texture definition variants typedef struct { int16_t originX; int16_t originY; int16_t patch; } strifemappatch_t; typedef struct { byte name[8]; int16_t unused; byte scale[2]; // [x, y] Used by ZDoom, div 8. int16_t width; int16_t height; int16_t patchCount; strifemappatch_t patches[1]; } strifemaptexture_t; #pragma pack() int i; int* maptex1; size_t lumpSize, offset, n, numValidPatchRefs; int* directory; void* storage; byte* validTexDefs; short* texDefNumPatches; int numTexDefs, numValidTexDefs; doomtexturedef_t** texDefs = NULL; lumpSize = W_LumpLength(lump); maptex1 = M_Malloc(lumpSize); W_ReadLump(lump, maptex1); numTexDefs = LONG(*maptex1); VERBOSE(Con_Message("R_ReadTextureDefs: Processing lump '%s'...\n", W_LumpName(lump))); validTexDefs = M_Calloc(numTexDefs * sizeof(byte)); texDefNumPatches = M_Calloc(numTexDefs * sizeof(*texDefNumPatches)); /** * Pass #1 * Count total number of texture and patch defs we'll need and check * for missing patches and any other irregularities. */ numValidTexDefs = 0; numValidPatchRefs = 0; directory = maptex1 + 1; for(i = 0; i < numTexDefs; ++i, directory++) { offset = LONG(*directory); if(offset > lumpSize) { Con_Message("R_ReadTextureDefs: Bad offset %lu for definition " "%i in lump '%s'.\n", (unsigned long) offset, i, W_LumpName(lump)); continue; } if(gameDataFormat == 0) { // DOOM format. maptexture_t* mtexture = (maptexture_t *) ((byte *) maptex1 + offset); short j, n, patchCount = SHORT(mtexture->patchCount); n = 0; if(patchCount > 0) { mappatch_t* mpatch = &mtexture->patches[0]; for(j = 0; j < patchCount; ++j, mpatch++) { short patchNum = SHORT(mpatch->patch); if(patchNum < 0 || (unsigned) patchNum >= numPatches) { Con_Message("R_ReadTextureDefs: Invalid patch %i in " "texture '%s'.\n", (int) patchNum, mtexture->name); continue; } if(patchlookup[patchNum] == -1) { Con_Message("R_ReadTextureDefs: Missing patch %i in " "texture '%s'.\n", (int) j, mtexture->name); continue; } n++; } } else { Con_Message("R_ReadTextureDefs: Invalid patchcount %i in " "texture '%s'.\n", (int) patchCount, mtexture->name); } texDefNumPatches[i] = n; numValidPatchRefs += n; } else if(gameDataFormat == 3) { // Strife format. strifemaptexture_t* smtexture = (strifemaptexture_t *) ((byte *) maptex1 + offset); short j, n, patchCount = SHORT(smtexture->patchCount); n = 0; if(patchCount > 0) { strifemappatch_t* smpatch = &smtexture->patches[0]; for(j = 0; j < patchCount; ++j, smpatch++) { short patchNum = SHORT(smpatch->patch); if(patchNum < 0 || (unsigned) patchNum >= numPatches) { Con_Message("R_ReadTextureDefs: Invalid patch %i in " "texture '%s'.\n", (int) patchNum, smtexture->name); continue; } if(patchlookup[patchNum] == -1) { Con_Message("R_ReadTextureDefs: Missing patch %i in " "texture '%s'.\n", (int) j, smtexture->name); continue; } n++; } } else { Con_Message("R_ReadTextureDefs: Invalid patchcount %i in " "texture '%s'.\n", (int) patchCount, smtexture->name); } texDefNumPatches[i] = n; numValidPatchRefs += n; } if(texDefNumPatches[i] > 0) { // This is a valid texture definition. validTexDefs[i] = true; numValidTexDefs++; } } if(numValidTexDefs > 0 && numValidPatchRefs > 0) { /** * Pass #2 * There is at least one valid texture def in this lump so convert * to the internal format. */ // Build the texturedef index. texDefs = Z_Malloc(numValidTexDefs * sizeof(*texDefs), PU_REFRESHTEX, 0); storage = Z_Calloc(sizeof(doomtexturedef_t) * numValidTexDefs + sizeof(texpatch_t) * numValidPatchRefs, PU_REFRESHTEX, 0); directory = maptex1 + 1; n = 0; for(i = 0; i < numTexDefs; ++i, directory++) { short j; doomtexturedef_t* texDef; if(!validTexDefs[i]) continue; offset = LONG(*directory); // Read and create the texture def. if(gameDataFormat == 0) { // DOOM format. texpatch_t* patch; mappatch_t* mpatch; maptexture_t* mtexture = (maptexture_t *) ((byte *) maptex1 + offset); texDef = storage; texDef->patchCount = texDefNumPatches[i]; strncpy(texDef->name, mtexture->name, 8); strupr(texDef->name); texDef->width = SHORT(mtexture->width); texDef->height = SHORT(mtexture->height); storage = (byte *) storage + sizeof(doomtexturedef_t) + sizeof(texpatch_t) * texDef->patchCount; mpatch = &mtexture->patches[0]; patch = &texDef->patches[0]; for(j = 0; j < SHORT(mtexture->patchCount); ++j, mpatch++) { short patchNum = SHORT(mpatch->patch); if(patchNum < 0 || (unsigned) patchNum >= numPatches || patchlookup[patchNum] == -1) continue; patch->offX = SHORT(mpatch->originX); patch->offY = SHORT(mpatch->originY); patch->lump = patchlookup[patchNum]; patch++; } } else if(gameDataFormat == 3) { // Strife format. texpatch_t* patch; strifemappatch_t* smpatch; strifemaptexture_t* smtexture = (strifemaptexture_t *) ((byte *) maptex1 + offset); texDef = storage; texDef->patchCount = texDefNumPatches[i]; strncpy(texDef->name, smtexture->name, 8); strupr(texDef->name); texDef->width = SHORT(smtexture->width); texDef->height = SHORT(smtexture->height); storage = (byte *) storage + sizeof(doomtexturedef_t) + sizeof(texpatch_t) * texDef->patchCount; smpatch = &smtexture->patches[0]; patch = &texDef->patches[0]; for(j = 0; j < SHORT(smtexture->patchCount); ++j, smpatch++) { short patchNum = SHORT(smpatch->patch); if(patchNum < 0 || (unsigned) patchNum >= numPatches || patchlookup[patchNum] == -1) continue; patch->offX = SHORT(smpatch->originX); patch->offY = SHORT(smpatch->originY); patch->lump = patchlookup[patchNum]; patch++; } } /** * DOOM.EXE had a bug in the way textures were managed resulting in * the first texture being used dually as a "NULL" texture. */ if(firstNull && i == 0) texDef->flags |= TXDF_NODRAW; /** * Is this a non-IWAD texture? * At this stage we assume it is an IWAD texture definition * unless one of the patches is not. */ texDef->flags |= TXDF_IWAD; j = 0; while(j < texDef->patchCount && (texDef->flags & TXDF_IWAD)) { if(!W_IsFromIWAD(texDef->patches[j].lump)) texDef->flags &= ~TXDF_IWAD; else j++; } // Add it to the list. texDefs[n++] = texDef; } } VERBOSE(Con_Message(" Loaded %i of %i definitions.\n", numValidTexDefs, numTexDefs)); // Free all temporary storage. M_Free(validTexDefs); M_Free(texDefNumPatches); M_Free(maptex1); if(numDefs) *numDefs = numValidTexDefs; return texDefs; } static void loadDoomTextureDefs(void) { lumpnum_t i, pnamesLump, *patchLumpList; size_t numPatches; int count = 0, countCustom = 0, *eCount; doomtexturedef_t** list = NULL, **listCustom = NULL, ***eList; boolean firstNull; if((pnamesLump = W_CheckNumForName("PNAMES")) == -1) return; // Load the patch names from the PNAMES lump. patchLumpList = loadPatchList(pnamesLump, &numPatches); if(!patchLumpList) Con_Error("loadDoomTextureDefs: Error loading PNAMES."); /** * Many PWADs include new TEXTURE1/2 lumps including the IWAD doomtexture * definitions, with new definitions appended. In order to correctly * determine whether a defined texture originates from an IWAD we must * compare all definitions against those in the IWAD and if matching, * they should be considered as IWAD resources, even though the doomtexture * definition does not come from an IWAD lump. */ firstNull = true; for(i = 0; i < numLumps; ++i) { char name[9]; memset(name, 0, sizeof(name)); strncpy(name, W_LumpName(i), 8); strupr(name); // Case insensitive. if(!strncmp(name, "TEXTURE1", 8) || !strncmp(name, "TEXTURE2", 8)) { boolean isFromIWAD = W_IsFromIWAD(i); int newNumTexDefs; doomtexturedef_t** newTexDefs; // Read in the new texture defs. newTexDefs = readDoomTextureDefLump(i, patchLumpList, numPatches, firstNull, &newNumTexDefs); eList = (isFromIWAD? &list : &listCustom); eCount = (isFromIWAD? &count : &countCustom); if(*eList) { int i; size_t n; doomtexturedef_t** newList; // Merge with the existing doomtexturedefs. newList = Z_Malloc(sizeof(*newList) * ((*eCount) + newNumTexDefs), PU_REFRESHTEX, 0); n = 0; for(i = 0; i < *eCount; ++i) newList[n++] = (*eList)[i]; for(i = 0; i < newNumTexDefs; ++i) newList[n++] = newTexDefs[i]; Z_Free(*eList); Z_Free(newTexDefs); *eList = newList; *eCount += newNumTexDefs; } else { *eList = newTexDefs; *eCount = newNumTexDefs; } // No more NULL textures. firstNull = false; } } if(listCustom) { // There are custom doomtexturedefs, cross compare with the IWAD // originals to see if they have been changed. size_t n; doomtexturedef_t** newList; i = 0; while(i < count) { int j; doomtexturedef_t* orig = list[i]; boolean hasReplacement = false; for(j = 0; j < countCustom; ++j) { doomtexturedef_t* custom = listCustom[j]; if(!strncmp(orig->name, custom->name, 8)) { // This is a newer version of an IWAD doomtexturedef. if(!(custom->flags & TXDF_IWAD)) hasReplacement = true; // Uses a non-IWAD patch. else if(custom->height == orig->height && custom->width == orig->width && custom->patchCount == orig->patchCount) { // Check the patches. short k = 0; while(k < orig->patchCount && (custom->flags & TXDF_IWAD)) { texpatch_t* origP = orig->patches + k; texpatch_t* customP = custom->patches + k; if(origP->lump != customP->lump && origP->offX != customP->offX && origP->offY != customP->offY) { custom->flags &= ~TXDF_IWAD; } else k++; } hasReplacement = true; } break; } } if(hasReplacement) { // Let the PWAD "copy" override the IWAD original. int n; for(n = i + 1; n < count; ++n) list[n-1] = list[n]; count--; } else i++; } // List contains only non-replaced doomtexturedefs, merge them. newList = Z_Malloc(sizeof(*newList) * (count + countCustom), PU_REFRESHTEX, 0); n = 0; for(i = 0; i < count; ++i) newList[n++] = list[i]; for(i = 0; i < countCustom; ++i) newList[n++] = listCustom[i]; Z_Free(list); Z_Free(listCustom); doomTextureDefs = newList; numDoomTextureDefs = count + countCustom; } else { doomTextureDefs = list; numDoomTextureDefs = count; } // We're finished with the patch lump list now. M_Free(patchLumpList); } /** * Reads in the texture defs and creates materials for them. */ void R_InitTextures(void) { int i; float startTime = Sys_GetSeconds(); numDoomTextureDefs = 0; doomTextureDefs = NULL; // Load texture definitions from TEXTURE1/2 lumps. loadDoomTextureDefs(); if(numDoomTextureDefs > 0) { // Create materials for the defined textures. for(i = 0; i < numDoomTextureDefs; ++i) { doomtexturedef_t* texDef = doomTextureDefs[i]; material_t* mat; const gltexture_t* tex; tex = GL_CreateGLTexture(texDef->name, i, GLT_DOOMTEXTURE); // Create a material for this texture. mat = P_MaterialCreate(texDef->name, texDef->width, texDef->height, ((texDef->flags & TXDF_NODRAW)? MATF_NO_DRAW : 0), tex->id, MN_TEXTURES, NULL); } } else { Con_Message("R_InitTextures: Warning, no textures found.\n"); } VERBOSE(Con_Message("R_InitTextures: Done in %.2f seconds.\n", Sys_GetSeconds() - startTime)); } doomtexturedef_t* R_GetDoomTextureDef(int num) { if(num < 0 || num >= numDoomTextureDefs) { #if _DEBUG Con_Error("R_GetDoomTextureDef: Invalid def num %i.", num); #endif return NULL; } return doomTextureDefs[num]; } /** * Returns the new flat index. */ static int R_NewFlat(lumpnum_t lump) { int i; flat_t** newlist, *ptr; for(i = 0; i < numFlats; ++i) { ptr = flats[i]; // Is this lump already entered? if(ptr->lump == lump) return i; // Is this a known identifer? Newer idents overide old. if(!strnicmp(W_LumpName(ptr->lump), W_LumpName(lump), 8)) { ptr->lump = lump; return i; } } newlist = Z_Malloc(sizeof(flat_t*) * ++numFlats, PU_REFRESHTEX, 0); if(numFlats > 1) { for(i = 0; i < numFlats -1; ++i) newlist[i] = flats[i]; Z_Free(flats); } flats = newlist; ptr = flats[numFlats - 1] = Z_Calloc(sizeof(flat_t), PU_REFRESHTEX, 0); ptr->lump = lump; ptr->width = 64; /// \fixme not all flats are 64 texels in width! ptr->height = 64; /// \fixme not all flats are 64 texels in height! return numFlats - 1; } void R_InitFlats(void) { int i; float starttime = Sys_GetSeconds(); ddstack_t* stack = Stack_New(); numFlats = 0; for(i = 0; i < numLumps; ++i) { const char* name = W_LumpName(i); if(name[0] == 'F') { if(!strnicmp(name + 1, "_START", 6) || !strnicmp(name + 2, "_START", 6)) { // We've arrived at *a* flat block. Stack_Push(stack, NULL); continue; } else if(!strnicmp(name + 1, "_END", 4) || !strnicmp(name + 2, "_END", 4)) { // The flat block ends. Stack_Pop(stack); continue; } } if(!Stack_Height(stack)) continue; R_NewFlat(i); } while(Stack_Height(stack)) Stack_Pop(stack); Stack_Delete(stack); for(i = 0; i < numFlats; ++i) { const flat_t* flat = flats[i]; const gltexture_t* tex; tex = GL_CreateGLTexture(W_LumpName(flat->lump), i, GLT_FLAT); // Create a material for this flat. // \note that width = 64, height = 64 regardless of the flat dimensions. P_MaterialCreate(W_LumpName(flat->lump), 64, 64, 0, tex->id, MN_FLATS, NULL); } VERBOSE(Con_Message("R_InitFlats: Done in %.2f seconds.\n", Sys_GetSeconds() - starttime)); } uint R_CreateSkinTex(const char* skin, boolean isShinySkin) { int id; skinname_t* st; char realPath[256]; char name[9]; const gltexture_t* glTex; if(!skin[0]) return 0; // Convert the given skin file to a full pathname. // \fixme Why is this done here and not during init?? _fullpath(realPath, skin, 255); // Have we already created one for this? if((id = R_GetSkinNumForName(realPath))) return id; if(M_NumDigits(numSkinNames + 1) > 8) { #if _DEBUG Con_Message("R_GetSkinTex: Too many model skins!\n"); #endif return 0; } /** * A new skin name. */ // Create a gltexture for it. dd_snprintf(name, 9, "%-*i", 8, numSkinNames + 1); glTex = GL_CreateGLTexture(name, numSkinNames, (isShinySkin? GLT_MODELSHINYSKIN : GLT_MODELSKIN)); skinNames = M_Realloc(skinNames, sizeof(skinname_t) * ++numSkinNames); st = skinNames + (numSkinNames - 1); strncpy(st->path, realPath, FILENAME_T_MAXLEN); st->id = glTex->id; if(verbose) { Con_Message("SkinTex: %s => %li\n", M_PrettyPath(skin), (long) (1 + (st - skinNames))); } return 1 + (st - skinNames); // 1-based index. } static boolean expandSkinName(char* expanded, const char* skin, const char* modelfn, size_t len) { directory_t mydir; ddstring_t fn; boolean found; // The "first choice" directory. memset(&mydir, 0, sizeof(mydir)); Dir_FileDir(modelfn, &mydir); Str_Init(&fn); Str_Set(&fn, mydir.path); Str_Append(&fn, skin); // Try the "first choice" directory first. found = R_FindResource2(RT_GRAPHIC, DDRC_NONE, expanded, Str_Text(&fn), NULL, len); if(!found) // Try the model path(s). found = R_FindResource2(RT_GRAPHIC, DDRC_MODEL, expanded, skin, NULL, len); Str_Free(&fn); return found; } /** * Registers a new skin name. */ uint R_RegisterSkin(char* fullpath, const char* skin, const char* modelfn, boolean isShinySkin, size_t len) { // Has a skin name been provided? if(skin && skin[0]) { filename_t buf; if(expandSkinName(fullpath ? fullpath : buf, skin, modelfn, len)) return R_CreateSkinTex(fullpath ? fullpath : buf, isShinySkin); } return 0; } const skinname_t* R_GetSkinNameByIndex(uint id) { if(!id || id > numSkinNames) return NULL; return &skinNames[id-1]; } uint R_GetSkinNumForName(const char* path) { uint i; for(i = 0; i < numSkinNames; ++i) if(!stricmp(skinNames[i].path, path)) return i + 1; // 1-based index. return 0; } /** * This is called at final shutdown. */ void R_DestroySkins(void) { M_Free(skinNames); skinNames = 0; numSkinNames = 0; } void R_UpdateTexturesAndFlats(void) { Z_FreeTags(PU_REFRESHTEX, PU_REFRESHTEX); } void R_InitPatches(void) { memset(patchtexhash, 0, sizeof(patchtexhash)); } void R_UpdatePatches(void) { Z_FreeTags(PU_PATCH, PU_PATCH); memset(patchtexhash, 0, sizeof(patchtexhash)); R_InitPatches(); } void R_InitRawTexs(void) { memset(rawtexhash, 0, sizeof(rawtexhash)); } void R_UpdateRawTexs(void) { Z_FreeTags(PU_PATCH, PU_PATCH); memset(rawtexhash, 0, sizeof(rawtexhash)); R_InitRawTexs(); } /** * Locates all the lumps that will be used by all views. * Must be called after W_Init. */ void R_InitData(void) { R_InitPatches(); R_InitRawTexs(); Cl_InitTranslations(); } void R_UpdateData(void) { R_UpdatePatches(); R_UpdateRawTexs(); Cl_InitTranslations(); } void R_InitTranslationTables(void) { // Allocate translation tables translationTables = Z_Calloc(256 * 3 * 7, PU_REFRESHTRANS, 0); } void R_UpdateTranslationTables(void) { Z_FreeTags(PU_REFRESHTRANS, PU_REFRESHTRANS); R_InitTranslationTables(); } /** * @return @c true, if the given light decoration definition * is valid. */ boolean R_IsValidLightDecoration(const ded_decorlight_t *lightDef) { return (lightDef && (lightDef->color[0] != 0 || lightDef->color[1] != 0 || lightDef->color[2] != 0)); } /** * @return @c true, if the given decoration works under the * specified circumstances. */ boolean R_IsAllowedDecoration(ded_decor_t* def, material_t* mat, boolean hasExternal) { if(hasExternal) { return (def->flags & DCRF_EXTERNAL) != 0; } if(!(mat->flags & MATF_CUSTOM)) return !(def->flags & DCRF_NO_IWAD); return (def->flags & DCRF_PWAD) != 0; } /** * @return @c true, if the given reflection works under the * specified circumstances. */ boolean R_IsAllowedReflection(ded_reflection_t* def, material_t* mat, boolean hasExternal) { if(hasExternal) { return (def->flags & REFF_EXTERNAL) != 0; } if(!(mat->flags & MATF_CUSTOM)) return !(def->flags & REFF_NO_IWAD); return (def->flags & REFF_PWAD) != 0; } /** * @return @c true, if the given decoration works under the * specified circumstances. */ boolean R_IsAllowedDetailTex(ded_detailtexture_t* def, material_t* mat, boolean hasExternal) { if(hasExternal) { return (def->flags & DTLF_EXTERNAL) != 0; } if(!(mat->flags & MATF_CUSTOM)) return !(def->flags & DTLF_NO_IWAD); return (def->flags & DTLF_PWAD) != 0; } /** * Prepares the specified patch. */ void R_PrecachePatch(lumpnum_t num) { GL_PreparePatch(R_GetPatchTex(num)); } static boolean isInList(void** list, size_t len, void* elm) { size_t n; if(!list || !elm || len == 0) return false; for(n = 0; n < len; ++n) if(list[n] == elm) return true; return false; } boolean findSpriteOwner(thinker_t* th, void* context) { int i; mobj_t* mo = (mobj_t*) th; spritedef_t* sprDef = (spritedef_t*) context; if(mo->type >= 0 && mo->type < defs.count.mobjs.num) { //// \optimize Traverses the entire state list! for(i = 0; i < defs.count.states.num; ++i) { if(stateOwners[i] != &mobjInfo[mo->type]) continue; if(&sprites[states[i].sprite] == sprDef) return false; // Found an owner! } } return true; // Keep looking... } /** * Prepare all the relevant resources for the specified mobjtype. * * \note Part of the Doomsday public API. */ void R_PrecacheMobjNum(int num) { int i; if(!((useModels && precacheSkins) || precacheSprites)) return; if(num < 0 || num >= defs.count.mobjs.num) return; //// \optimize Traverses the entire state list! for(i = 0; i < defs.count.states.num; ++i) { state_t* state; if(stateOwners[i] != &mobjInfo[num]) continue; state = &states[i]; R_PrecacheSkinsForState(i); if(precacheSprites) { int j; spritedef_t* sprDef = &sprites[state->sprite]; for(j = 0; j < sprDef->numFrames; ++j) { int k; spriteframe_t* sprFrame = &sprDef->spriteFrames[j]; for(k = 0; k < 8; ++k) Material_Precache(sprFrame->mats[k]); } } } } /** * Prepare all relevant skins, textures, flats and sprites. * Doesn't unload anything, though (so that if there's enough * texture memory it will be used more efficiently). That much trust * is placed in the GL/D3D drivers. The prepared textures are also bound * here once so they should be ready for use ASAP. */ void R_PrecacheMap(void) { uint i, j; size_t n; sector_t* sec; sidedef_t* side; float startTime; material_t* mat, **matPresent; materialnum_t numMaterials; // Don't precache when playing demo. if(isDedicated || playback) return; // Precaching from 100 to 200. Con_SetProgress(100); startTime = Sys_GetSeconds(); // Precache all materials used on world surfaces. numMaterials = numMaterialBinds; matPresent = M_Calloc(sizeof(material_t*) * numMaterials); n = 0; for(i = 0; i < numSideDefs; ++i) { side = SIDE_PTR(i); mat = side->SW_topmaterial; if(mat && !isInList((void**) matPresent, n, mat)) matPresent[n++] = mat; mat = side->SW_middlematerial; if(mat && !isInList((void**) matPresent, n, mat)) matPresent[n++] = mat; mat = side->SW_bottommaterial; if(mat && !isInList((void**) matPresent, n, mat)) matPresent[n++] = mat; } for(i = 0; i < numSectors; ++i) { sec = SECTOR_PTR(i); for(j = 0; j < sec->planeCount; ++j) { mat = sec->SP_planematerial(j); if(mat && !isInList((void**) matPresent, n, mat)) matPresent[n++] = mat; } } // Precache sprites? if(precacheSprites) { int i; for(i = 0; i < numSprites; ++i) { spritedef_t* sprDef = &sprites[i]; if(!P_IterateThinkers(gx.MobjThinker, 0x1, // All mobjs are public findSpriteOwner, sprDef)) { // This sprite is used by some state of at least one mobj. int j; // Precache all the frames. for(j = 0; j < sprDef->numFrames; ++j) { int k; spriteframe_t* sprFrame = &sprDef->spriteFrames[j]; for(k = 0; k < 8; ++k) { material_t* mat = sprFrame->mats[k]; if(mat && !isInList((void**) matPresent, n, mat)) matPresent[n++] = mat; } } } } } // \fixme Precache sky materials! i = 0; while(i < numMaterials && matPresent[i]) Material_Precache(matPresent[i++]); // We are done with list of used materials. M_Free(matPresent); matPresent = NULL; // Precache model skins? if(useModels && precacheSkins) { // All mobjs are public. P_IterateThinkers(gx.MobjThinker, 0x1, R_PrecacheSkinsForMobj, NULL); } // Sky models usually have big skins. R_PrecacheSky(); VERBOSE(Con_Message("Precaching took %.2f seconds.\n", Sys_GetSeconds() - startTime)) } /** * Initialize an entire animation using the data in the definition. */ void R_InitAnimGroup(ded_group_t* def) { int i, groupNumber = -1; materialnum_t num; for(i = 0; i < def->count.num; ++i) { ded_group_member_t *gm = &def->members[i]; num = P_MaterialCheckNumForName(gm->material.name, gm->material.mnamespace); if(!num) continue; // Only create a group when the first texture is found. if(groupNumber == -1) { // Create a new animation group. groupNumber = R_CreateAnimGroup(def->flags); } R_AddToAnimGroup(groupNumber, num, gm->tics, gm->randomTics); } } detailtex_t* R_CreateDetailTexture(const ded_detailtexture_t* def) { char name[9]; const gltexture_t* glTex; detailtex_t* dTex; lumpnum_t lump = W_CheckNumForName(def->detailLump.path); const char* external = (def->isExternal? def->detailLump.path : NULL); // Have we already created one for this? if((dTex = R_GetDetailTexture(lump, external))) return NULL; if(M_NumDigits(numDetailTextures + 1) > 8) { #if _DEBUG Con_Message("R_CreateDetailTexture: Too many detail textures!\n"); #endif return NULL; } /** * A new detail texture. */ // Create a gltexture for it. dd_snprintf(name, 9, "%-*i", 8, numDetailTextures + 1); glTex = GL_CreateGLTexture(name, numDetailTextures, GLT_DETAIL); dTex = M_Malloc(sizeof(*dTex)); dTex->id = glTex->id; dTex->lump = lump; dTex->external = external; // Add it to the list. detailTextures = M_Realloc(detailTextures, sizeof(detailtex_t*) * ++numDetailTextures); detailTextures[numDetailTextures-1] = dTex; return dTex; } detailtex_t* R_GetDetailTexture(lumpnum_t lump, const char* external) { int i; for(i = 0; i < numDetailTextures; ++i) { detailtex_t* dTex = detailTextures[i]; if(dTex->lump == lump && ((dTex->external == NULL && external == NULL) || (dTex->external && external && !stricmp(dTex->external, external)))) return dTex; } return NULL; } /** * This is called at final shutdown. */ void R_DestroyDetailTextures(void) { int i; for(i = 0; i < numDetailTextures; ++i) { M_Free(detailTextures[i]); } if(detailTextures) M_Free(detailTextures); detailTextures = NULL; numDetailTextures = 0; } lightmap_t* R_CreateLightMap(const ded_lightmap_t* def) { char name[9]; const gltexture_t* glTex; lightmap_t* lmap; if(!def->id[0] || def->id[0] == '-') return NULL; // Not a lightmap // Have we already created one for this? if((lmap = R_GetLightMap(def->id))) return NULL; if(M_NumDigits(numLightMaps + 1) > 8) { #if _DEBUG Con_Message("R_CreateLightMap: Too many lightmaps!\n"); #endif return NULL; } /** * A new lightmap. */ // Create a gltexture for it. dd_snprintf(name, 9, "%-*i", 8, numLightMaps + 1); glTex = GL_CreateGLTexture(name, numLightMaps, GLT_LIGHTMAP); lmap = M_Malloc(sizeof(*lmap)); lmap->id = glTex->id; lmap->external = def->id; // Add it to the list. lightMaps = M_Realloc(lightMaps, sizeof(lightmap_t*) * ++numLightMaps); lightMaps[numLightMaps-1] = lmap; return lmap; } lightmap_t* R_GetLightMap(const char* external) { int i; if(external && external[0] && external[0] != '-') { for(i = 0; i < numLightMaps; ++i) { lightmap_t* lmap = lightMaps[i]; if(!stricmp(lmap->external, external)) return lmap; } } return NULL; } /** * This is called at final shutdown. */ void R_DestroyLightMaps(void) { int i; for(i = 0; i < numLightMaps; ++i) { M_Free(lightMaps[i]); } if(lightMaps) M_Free(lightMaps); lightMaps = NULL; numLightMaps = 0; } flaretex_t* R_CreateFlareTexture(const ded_flaremap_t* def) { flaretex_t* fTex; char name[9]; const gltexture_t* glTex; if(!def->id || !def->id[0] || def->id[0] == '-') return NULL; // Not a flare texture. // Perhaps a "built-in" flare texture id? // Try to convert the id to a system flare tex constant idx if(def->id[0] >= '0' && def->id[0] <= '4' && !def->id[1]) return NULL; // Don't create a flaretex for this // Have we already created one for this? if((fTex = R_GetFlareTexture(def->id))) return NULL; if(M_NumDigits(numFlareTextures + 1) > 8) { #if _DEBUG Con_Message("R_CreateFlareTexture: Too many flare textures!\n"); #endif return NULL; } /** * A new flare texture. */ // Create a gltexture for it. dd_snprintf(name, 9, "%-*i", 8, numFlareTextures + 1); glTex = GL_CreateGLTexture(name, numFlareTextures, GLT_FLARE); fTex = M_Malloc(sizeof(*fTex)); fTex->external = def->id; fTex->id = glTex->id; // Add it to the list. flareTextures = M_Realloc(flareTextures, sizeof(flaretex_t*) * ++numFlareTextures); flareTextures[numFlareTextures-1] = fTex; return fTex; } flaretex_t* R_GetFlareTexture(const char* external) { int i; if(!external || !external[0] || external[0] == '-') return NULL; for(i = 0; i < numFlareTextures; ++i) { flaretex_t* fTex = flareTextures[i]; if(!stricmp(fTex->external, external)) return fTex; } return NULL; } /** * This is called at final shutdown. */ void R_DestroyFlareTextures(void) { int i; for(i = 0; i < numFlareTextures; ++i) { M_Free(flareTextures[i]); } if(flareTextures) M_Free(flareTextures); flareTextures = NULL; numFlareTextures = 0; } shinytex_t* R_CreateShinyTexture(const ded_reflection_t* def) { char name[9]; const gltexture_t* glTex; shinytex_t* sTex; // Have we already created one for this? if((sTex = R_GetShinyTexture(def->shinyMap.path))) return NULL; if(M_NumDigits(numShinyTextures + 1) > 8) { #if _DEBUG Con_Message("R_CreateShinyTexture: Too many shiny textures!\n"); #endif return NULL; } /** * A new shiny texture. */ // Create a gltexture for it. dd_snprintf(name, 9, "%-*i", 8, numShinyTextures + 1); glTex = GL_CreateGLTexture(name, numShinyTextures, GLT_SHINY); sTex = M_Malloc(sizeof(*sTex)); sTex->id = glTex->id; sTex->external = def->shinyMap.path; // Add it to the list. shinyTextures = M_Realloc(shinyTextures, sizeof(shinytex_t*) * ++numShinyTextures); shinyTextures[numShinyTextures-1] = sTex; return sTex; } shinytex_t* R_GetShinyTexture(const char* external) { int i; if(external && external[0]) for(i = 0; i < numShinyTextures; ++i) { shinytex_t* sTex = shinyTextures[i]; if(!stricmp(sTex->external, external)) return sTex; } return NULL; } /** * This is called at final shutdown. */ void R_DestroyShinyTextures(void) { int i; for(i = 0; i < numShinyTextures; ++i) { M_Free(shinyTextures[i]); } if(shinyTextures) M_Free(shinyTextures); shinyTextures = NULL; numShinyTextures = 0; } masktex_t* R_CreateMaskTexture(const ded_reflection_t* def) { char name[9]; const gltexture_t* glTex; masktex_t* mTex; // Have we already created one for this? if((mTex = R_GetMaskTexture(def->maskMap.path))) return NULL; if(M_NumDigits(numMaskTextures + 1) > 8) { #if _DEBUG Con_Message("R_CreateMaskTexture: Too many mask textures!\n"); #endif return NULL; } /** * A new shiny texture. */ // Create a gltexture for it. dd_snprintf(name, 9, "%-*i", 8, numMaskTextures + 1); glTex = GL_CreateGLTexture(name, numMaskTextures, GLT_MASK); mTex = M_Malloc(sizeof(*mTex)); mTex->id = glTex->id; mTex->external = def->maskMap.path; mTex->width = def->maskWidth; mTex->height = def->maskHeight; // Add it to the list. maskTextures = M_Realloc(maskTextures, sizeof(masktex_t*) * ++numMaskTextures); maskTextures[numMaskTextures-1] = mTex; return mTex; } masktex_t* R_GetMaskTexture(const char* external) { int i; if(external && external[0]) for(i = 0; i < numMaskTextures; ++i) { masktex_t* mTex = maskTextures[i]; if(!stricmp(mTex->external, external)) return mTex; } return NULL; } /** * This is called at final shutdown. */ void R_DestroyMaskTextures(void) { int i; for(i = 0; i < numMaskTextures; ++i) { M_Free(maskTextures[i]); } if(maskTextures) M_Free(maskTextures); maskTextures = NULL; numMaskTextures = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/s_wav.c0000644000175000017500000001733711357170242022227 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_wav.c: WAV Files * * A 'bare necessities' WAV loader. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "m_misc.h" // MACROS ------------------------------------------------------------------ #define WAVE_FORMAT_PCM 1 // TYPES ------------------------------------------------------------------- #pragma pack(1) typedef struct riff_hdr_s { char id[4]; // Identifier string = "RIFF" uint32_t len; // Remaining length after this header } riff_hdr_t; typedef struct chunk_hdr_s { // CHUNK 8-byte header char id[4]; // Identifier, e.g. "fmt " or "data" uint32_t len; // Remaining chunk length after header } chunk_hdr_t; // data bytes follow chunk header typedef struct wav_format_s { uint16_t wFormatTag; // Format category uint16_t wChannels; // Number of channels uint32_t dwSamplesPerSec; // Sampling rate uint32_t dwAvgBytesPerSec; // For buffer estimation uint16_t wBlockAlign; // Data block size uint16_t wBitsPerSample; // Sample size } wav_format_t; #pragma pack() // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static void WRead(void** ptr, void** dest, int length) { *dest = *ptr; *(char**) ptr += length; } /** * @return Non-zero if the "RIFF" and "WAVE" strings are found. */ int WAV_CheckFormat(const char* data) { return !strncmp(data, "RIFF", 4) && !strncmp(data + 8, "WAVE", 4); } /** * The returned buffer contains the wave data. If NULL is returned, the * loading obviously failed. The caller must free the sample data using * Z_Free when it's no longer needed. The WAV file must have only one * channel! All parameters must be passed, no NULLs are allowed. */ void* WAV_MemoryLoad(const byte* data, size_t datalength, int* bits, int* rate, int* samples) { const byte* end = data + datalength; byte* sampledata = NULL; chunk_hdr_t* riff_chunk; wav_format_t* wave_format = NULL; if(!WAV_CheckFormat(data)) { Con_Message("WAV_MemoryLoad: Not a WAV file.\n"); return NULL; } // Read the RIFF header. data += sizeof(riff_hdr_t); // Correct endianness. //riff_header->len = ULONG(riff_header->len); data += 4; // Start readin' the chunks, baby! while(data < end) { // Read next chunk header. WRead((void **) &data, (void **) &riff_chunk, sizeof(*riff_chunk)); // Correct endianness. riff_chunk->len = ULONG(riff_chunk->len); // What have we got here? if(!strncmp(riff_chunk->id, "fmt ", 4)) { // Read format chunk. WRead((void **) &data, (void **) &wave_format, sizeof(*wave_format)); // Correct endianness. wave_format->wFormatTag = USHORT(wave_format->wFormatTag); wave_format->wChannels = USHORT(wave_format->wChannels); wave_format->dwSamplesPerSec = ULONG(wave_format->dwSamplesPerSec); wave_format->dwAvgBytesPerSec = ULONG(wave_format->dwAvgBytesPerSec); wave_format->wBlockAlign = USHORT(wave_format->wBlockAlign); wave_format->wBitsPerSample = USHORT(wave_format->wBitsPerSample); // Check that it's a format we know how to read. if(wave_format->wFormatTag != WAVE_FORMAT_PCM) { Con_Message("WAV_MemoryLoad: Unsupported format.\n"); return NULL; } if(wave_format->wChannels != 1) { Con_Message ("WAV_MemoryLoad: Too many channels (only mono supported).\n"); return NULL; } // Read the extra format information. //WRead(&data, &wave_format2, sizeof(*wave_format2)); /*if(wave_format->wBitsPerSample == 0) { // We'll have to guess... *bits = 8*wave_format->dwAvgBytesPerSec/ wave_format->dwSamplesPerSec; } else { */ if(wave_format->wBitsPerSample != 8 && wave_format->wBitsPerSample != 16) { Con_Message("WAV_MemoryLoad: Not a 8/16 bit WAVE.\n"); return NULL; } // Now we know some information about the sample. *bits = wave_format->wBitsPerSample; *rate = wave_format->dwSamplesPerSec; } else if(!strncmp(riff_chunk->id, "data", 4)) { if(!wave_format) { Con_Message("WAV_MemoryLoad: Malformed WAVE data.\n"); return NULL; } // Read data chunk. *samples = riff_chunk->len / wave_format->wBlockAlign; // Allocate the sample buffer. sampledata = Z_Malloc(riff_chunk->len, PU_STATIC, 0); memcpy(sampledata, data, riff_chunk->len); #ifdef __BIG_ENDIAN__ // Correct endianness. /*if(wave_format->wBitsPerSample == 16) { ushort* sample = sampledata; for(; sample < ((short*)sampledata) + *samples; ++sample) *sample = USHORT(*sample); }*/ #endif // We're satisfied with this! Let's get out of here. break; } else { // Unknown chunk, just skip it. data += riff_chunk->len; } } return sampledata; } void* WAV_Load(const char* filename, int* bits, int* rate, int* samples) { DFILE* file; byte* data; size_t size; void* sampledata; // Try to open the file. if((file = F_Open(filename, "b")) == NULL) return NULL; // Read in the whole thing. F_Seek(file, 0, SEEK_END); size = F_Tell(file); F_Rewind(file); data = M_Malloc(size); F_Read(data, size, file); F_Close(file); // Parse the RIFF data. sampledata = WAV_MemoryLoad((const byte*) data, size, bits, rate, samples); if(!sampledata) { Con_Message("WAV_Load: Failed to load %s.\n", filename); } M_Free(data); return sampledata; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_list.c0000644000175000017500000016342011357170242023066 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_list.c: Doomsday Rendering Lists v3.2 * * 3.2 -- Shiny walls and floors * 3.1 -- Support for multiple shadow textures * 3.0 -- Multitexturing */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_render.h" #include "de_play.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_misc.h" #include "def_main.h" #include "m_profiler.h" // MACROS ------------------------------------------------------------------ BEGIN_PROF_TIMERS() PROF_RL_ADD_POLY, PROF_RL_GET_LIST, PROF_RL_RENDER_ALL, PROF_RL_RENDER_NORMAL, PROF_RL_RENDER_LIGHT, PROF_RL_RENDER_MASKED, PROF_RL_RENDER_SHINY, PROF_RL_RENDER_SHADOW, PROF_RL_RENDER_SKYMASK END_PROF_TIMERS() #define RL_HASH_SIZE 128 // Number of extra bytes to keep allocated in the end of each rendering list. #define LIST_DATA_PADDING 16 // \fixme Rlist allocation could be dynamic. #define MAX_RLISTS 1024 #define MTEX_DETAILS_ENABLED (r_detail && useMultiTexDetails && \ defs.count.details.num > 0) #define IS_MTEX_DETAILS (MTEX_DETAILS_ENABLED && numTexUnits > 1) #define IS_MTEX_LIGHTS (!IS_MTEX_DETAILS && !usingFog && useMultiTexLights \ && numTexUnits > 1 && envModAdd) // Drawing condition flags. #define DCF_NO_BLEND 0x00000001 #define DCF_BLEND 0x00000002 #define DCF_SET_LIGHT_ENV0 0x00000004 #define DCF_SET_LIGHT_ENV1 0x00000008 #define DCF_SET_LIGHT_ENV (DCF_SET_LIGHT_ENV0 | DCF_SET_LIGHT_ENV1) #define DCF_JUST_ONE_LIGHT 0x00000010 #define DCF_MANY_LIGHTS 0x00000020 #define DCF_SET_BLEND_MODE 0x00000040 // Primitive-specific blending. #define DCF_SET_MATRIX_DTEXTURE0 0x00000080 #define DCF_SET_MATRIX_DTEXTURE1 0x00000100 #define DCF_SET_MATRIX_DTEXTURE (DCF_SET_MATRIX_DTEXTURE0 | DCF_SET_MATRIX_DTEXTURE1) #define DCF_SET_MATRIX_TEXTURE0 0x00000200 #define DCF_SET_MATRIX_TEXTURE1 0x00000400 #define DCF_SET_MATRIX_TEXTURE (DCF_SET_MATRIX_TEXTURE0 | DCF_SET_MATRIX_TEXTURE1) #define DCF_NO_COLOR 0x00000800 #define DCF_SKIP 0x80000000 // TYPES ------------------------------------------------------------------- // List Modes. typedef enum listmode_e { LM_SKYMASK, LM_ALL, LM_LIGHT_MOD_TEXTURE, LM_FIRST_LIGHT, LM_TEXTURE_PLUS_LIGHT, LM_UNBLENDED_TEXTURE_AND_DETAIL, LM_BLENDED, LM_BLENDED_FIRST_LIGHT, LM_NO_LIGHTS, LM_WITHOUT_TEXTURE, LM_LIGHTS, LM_MOD_TEXTURE, LM_MOD_TEXTURE_MANY_LIGHTS, LM_UNBLENDED_MOD_TEXTURE_AND_DETAIL, LM_BLENDED_MOD_TEXTURE, LM_ALL_DETAILS, LM_BLENDED_DETAILS, LM_SHADOW, LM_SHINY, LM_MASKED_SHINY, LM_ALL_SHINY } listmode_t; // Texture coordinate array indices. enum { TCA_MAIN, // Main texture. TCA_BLEND, // Blendtarget texture. TCA_LIGHT, // Dynlight texture coordinates. NUM_TEXCOORD_ARRAYS }; /** * Primitive flags: */ #define PF_ONE_LIGHT 0x01 #define PF_MANY_LIGHTS 0x02 #define PF_IS_LIT (PF_ONE_LIGHT | PF_MANY_LIGHTS) /** * Each primhdr begins a block of polygon data that ends up as one or * more triangles on the screen. Note that there are pointers to the * rendering list itself here; they will need to be properly restored * whenever the list is resized. */ typedef struct primhdr_s { // RL_AddPoly expects that size is the first thing in the header. // Must be an offset since the list is sometimes reallocated. uint size; // Size of this primitive (zero = n/a). ushort type; // OpenGL primitive type e.g., GL_TRIANGLE_STRIP. blendmode_t blendMode; // BM_* Primitive-specific blending mode. // Elements in the vertex array for this primitive. // The indices are always contiguous: indices[0] is the base, and // indices[1...n] > indices[0]. // All indices in the range indices[0]...indices[n] are used by this // primitive (some are shared). ushort numIndices; uint* indices; byte flags; // PF_* primitive flags. float ptexOffset[2], ptexScale[2]; // Detail texture matrix manipulations. float texOffset[2], texScale[2]; // Some primitives are modulated with an additional texture and color // using multitexturing (if available), depending on the list state. // Example: first light affecting the primitive. DGLuint modTex; float modColor[4]; } primhdr_t; // Helper macro for accessing rendlist texmap units. #define TU(x, n) (&((x)->texmapunits[(n)])) // \note: Slighty different representation than that passed to RL_AddPoly. typedef struct rendlist_texmapunit_s { DGLuint tex; int magMode; float blend; // Blend amount. blendmode_t blendMode; // Currently used only with shiny pass. } rendlist_texmapunit_t; /** * The rendering list. When the list is resized, pointers in the primitives * need to be restored so that they point to the new list. */ typedef struct rendlist_s { struct rendlist_s* next; rendlist_texmapunit_t texmapunits[NUM_TEXMAP_UNITS]; size_t size; // Number of bytes allocated for the data. byte* data; // Data for a number of polygons (The List). byte* cursor; // A pointer to data, for reading/writing. primhdr_t* last; // Pointer to the last primitive (or NULL). } rendlist_t; typedef struct listhash_s { rendlist_t* first, *last; } listhash_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int skyhemispheres; extern int devRendSkyMode; extern byte devRendSkyAlways; extern int useDynLights, dlBlend, simpleSky; extern boolean usingFog; extern byte freezeRLs; // PUBLIC DATA DEFINITIONS ------------------------------------------------- int renderTextures = true; int renderWireframe = false; int useMultiTexLights = true; int useMultiTexDetails = true; // Rendering parameters for detail textures. float detailFactor = .5f; float detailScale = 4; float torchColor[3] = {1, 1, 1}; int torchAdditive = true; // PRIVATE DATA DEFINITIONS ------------------------------------------------ /** * The vertex arrays. */ static dgl_vertex_t* vertices; static dgl_texcoord_t* texCoords[NUM_TEXCOORD_ARRAYS]; static dgl_color_t* colors; static uint numVertices, maxVertices; /** * The rendering lists. */ // Surfaces without lights. static listhash_t plainHash[RL_HASH_SIZE]; // Surfaces with lights. static listhash_t litHash[RL_HASH_SIZE]; // Additional light primitives. static listhash_t dynHash[RL_HASH_SIZE]; // Shiny surfaces. static listhash_t shinyHash[RL_HASH_SIZE]; static listhash_t shadowHash[RL_HASH_SIZE]; static rendlist_t skyMaskList; static boolean rendSky; static float blackColor[4] = { 0, 0, 0, 0 }; // CODE -------------------------------------------------------------------- void RL_Register(void) { // \todo Move cvars here. } static void rlBind(DGLuint tex, int magMode) { if(!renderTextures) tex = 0; glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magMode); if(GL_state.useAnisotropic) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(texAniso)); #ifdef _DEBUG { GLenum error; if((error = glGetError()) != GL_NO_ERROR) Con_Error("OpenGL error: %i\n", error); } #endif } static void rlBind2(const rendlist_texmapunit_t* tmu) { if(!tmu->tex) return; rlBind(tmu->tex, tmu->magMode); } static void rlBindTo(int unit, const rendlist_texmapunit_t* tmu) { if(!tmu->tex) return; GL_ActiveTexture(GL_TEXTURE0 + (byte) unit); rlBind(tmu->tex, tmu->magMode); } static void clearHash(listhash_t* hash) { memset(hash, 0, sizeof(listhash_t) * RL_HASH_SIZE); } /** * Called only once, from R_Init -> Rend_Init. */ void RL_Init(void) { clearHash(plainHash); clearHash(litHash); clearHash(dynHash); clearHash(shadowHash); clearHash(shinyHash); memset(&skyMaskList, 0, sizeof(skyMaskList)); } boolean RL_IsMTexLights(void) { return IS_MTEX_LIGHTS; } boolean RL_IsMTexDetails(void) { return IS_MTEX_DETAILS; } /** * The first selected unit is active after this call. */ static void selectTexUnits(int count) { int i; // Disable extra units. for(i = numTexUnits - 1; i >= count; i--) { GL_ActiveTexture(GL_TEXTURE0 + (byte) i); glDisable(GL_TEXTURE_2D); } // Enable the selected units. for(i = count - 1; i >= 0; i--) { if(i >= numTexUnits) continue; GL_ActiveTexture(GL_TEXTURE0 + (byte) i); glEnable(GL_TEXTURE_2D); } } static void clearVertices(void) { numVertices = 0; } static void destroyVertices(void) { uint i; numVertices = maxVertices = 0; if(vertices) M_Free(vertices); vertices = NULL; if(colors) M_Free(colors); colors = NULL; for(i = 0; i < NUM_TEXCOORD_ARRAYS; ++i) { if(texCoords[i]) M_Free(texCoords[i]); texCoords[i] = NULL; } } /** * Allocate vertices from the global vertex array. */ static uint allocateVertices(uint count) { uint i, base = numVertices; // Do we need to allocate more memory? numVertices += count; while(numVertices > maxVertices) { if(maxVertices == 0) { maxVertices = 16; } else { maxVertices *= 2; } vertices = M_Realloc(vertices, sizeof(dgl_vertex_t) * maxVertices); colors = M_Realloc(colors, sizeof(dgl_color_t) * maxVertices); for(i = 0; i < NUM_TEXCOORD_ARRAYS; ++i) { texCoords[i] = M_Realloc(texCoords[i], sizeof(dgl_texcoord_t) * maxVertices); } } return base; } static void destroyList(rendlist_t* rl) { // All the list data will be destroyed. if(rl->data) Z_Free(rl->data); rl->data = NULL; #if _DEBUG Z_CheckHeap(); #endif rl->cursor = NULL; TU(rl, TU_INTER_DETAIL)->tex = 0; rl->last = NULL; rl->size = 0; } static void deleteHash(listhash_t* hash) { uint i; rendlist_t* list, *next; for(i = 0; i < RL_HASH_SIZE; ++i) { for(list = hash[i].first; list; list = next) { next = list->next; destroyList(list); Z_Free(list); } } clearHash(hash); } /** * All lists will be destroyed. */ void RL_DeleteLists(void) { // Delete all lists. deleteHash(plainHash); deleteHash(litHash); deleteHash(dynHash); deleteHash(shadowHash); deleteHash(shinyHash); destroyList(&skyMaskList); destroyVertices(); #ifdef _DEBUG Z_CheckHeap(); #endif PRINT_PROF( PROF_RL_ADD_POLY ); PRINT_PROF( PROF_RL_GET_LIST ); PRINT_PROF( PROF_RL_RENDER_ALL ); PRINT_PROF( PROF_RL_RENDER_NORMAL ); PRINT_PROF( PROF_RL_RENDER_LIGHT ); PRINT_PROF( PROF_RL_RENDER_MASKED ); PRINT_PROF( PROF_RL_RENDER_SHADOW ); PRINT_PROF( PROF_RL_RENDER_SHINY ); PRINT_PROF( PROF_RL_RENDER_SKYMASK ); } /** * Set the R/W cursor to the beginning. */ static void rewindList(rendlist_t* rl) { rl->cursor = rl->data; rl->last = NULL; // The interpolation target must be explicitly set (in RL_AddPoly). TU(rl, TU_INTER)->tex = 0; TU(rl, TU_INTER)->blend = 0; TU(rl, TU_INTER_DETAIL)->tex = 0; TU(rl, TU_INTER_DETAIL)->blend = 0; } static void rewindHash(listhash_t* hash) { uint i; rendlist_t* list; for(i = 0; i < RL_HASH_SIZE; ++i) { for(list = hash[i].first; list; list = list->next) rewindList(list); } } /** * Called before rendering a frame. */ void RL_ClearLists(void) { rewindHash(plainHash); rewindHash(litHash); rewindHash(dynHash); rewindHash(shadowHash); rewindHash(shinyHash); rewindList(&skyMaskList); // Clear the vertex array. clearVertices(); // \fixme Does this belong here? skyhemispheres = 0; } static rendlist_t* createList(listhash_t* hash) { rendlist_t* list = Z_Calloc(sizeof(rendlist_t), PU_STATIC, 0); if(hash->last) hash->last->next = list; hash->last = list; if(!hash->first) hash->first = list; return list; } static __inline void copyTU(rendlist_texmapunit_t* lTU, const rtexmapunit_t* rTU) { lTU->tex = rTU->tex; lTU->magMode = rTU->magMode; lTU->blendMode = rTU->blendMode; lTU->blend = MINMAX_OF(0, rTU->blend, 1); } static __inline boolean compareTU(const rendlist_texmapunit_t* lTU, const rtexmapunit_t* rTU) { if(lTU->tex == rTU->tex && lTU->magMode == rTU->magMode && lTU->blend == rTU->blend) return true; return false; } static rendlist_t* getListFor(rendpolytype_t polyType, const rtexmapunit_t rTU[NUM_TEXMAP_UNITS], boolean useLights) { listhash_t* hash, *table; rendlist_t* dest, *convertable = NULL; // Check for specialized rendering lists first. if(polyType == RPT_SKY_MASK) { return &skyMaskList; } // Choose the correct hash table. switch(polyType) { case RPT_SHINY: table = shinyHash; break; case RPT_SHADOW: table = shadowHash; break; case RPT_LIGHT: table = dynHash; break; default: table = (useLights ? litHash : plainHash); break; } // Find/create a list in the hash. hash = &table[rTU[TU_PRIMARY].tex % RL_HASH_SIZE]; for(dest = hash->first; dest; dest = dest->next) { if((polyType == RPT_SHINY && compareTU(TU(dest, TU_PRIMARY), &rTU[TU_PRIMARY])) || (polyType != RPT_SHINY && compareTU(TU(dest, TU_PRIMARY), &rTU[TU_PRIMARY]) && compareTU(TU(dest, TU_PRIMARY_DETAIL), &rTU[TU_PRIMARY_DETAIL]))) { if(!TU(dest, TU_INTER)->tex && !rTU[TU_INTER].tex) { // This will do great. return dest; } // Is this eligible for conversion to a blended list? if(!dest->last && !convertable && rTU[TU_INTER].tex) { // If necessary, this empty list will be selected. convertable = dest; } // Possibly an exact match? if((polyType == RPT_SHINY && compareTU(TU(dest, TU_INTER), &rTU[TU_INTER])) || (polyType != RPT_SHINY && compareTU(TU(dest, TU_INTER), &rTU[TU_INTER]) && compareTU(TU(dest, TU_INTER_DETAIL), &rTU[TU_INTER_DETAIL]))) { return dest; } } } // Did we find a convertable list? if(convertable) { // This list is currently empty. if(polyType == RPT_SHINY) { copyTU(TU(convertable, TU_INTER), &rTU[TU_INTER]); } else { copyTU(TU(convertable, TU_INTER), &rTU[TU_INTER]); copyTU(TU(convertable, TU_INTER_DETAIL), &rTU[TU_INTER_DETAIL]); } return convertable; } // Create a new list. dest = createList(hash); // Init the info. if(polyType == RPT_SHINY) { copyTU(TU(dest, TU_PRIMARY), &rTU[TU_PRIMARY]); if(rTU[TU_INTER].tex) copyTU(TU(dest, TU_INTER), &rTU[TU_INTER]); } else { copyTU(TU(dest, TU_PRIMARY), &rTU[TU_PRIMARY]); copyTU(TU(dest, TU_PRIMARY_DETAIL), &rTU[TU_PRIMARY_DETAIL]); if(rTU[TU_INTER].tex) { copyTU(TU(dest, TU_INTER), &rTU[TU_INTER]); copyTU(TU(dest, TU_INTER_DETAIL), &rTU[TU_INTER_DETAIL]); } } return dest; } /** * @return Pointer to the start of the allocated data. */ static void* allocateData(rendlist_t* list, int bytes) { size_t required; int startOffset = list->cursor - list->data; primhdr_t* hdr; if(bytes <= 0) return NULL; // We require the extra bytes because we want that the end of the // list data is always safe for writing-in-advance. This is needed // when the 'end of data' marker is written in RL_AddPoly. required = startOffset + bytes + LIST_DATA_PADDING; // First check that the data buffer of the list is large enough. if(required > list->size) { // Offsets must be preserved. byte* oldData = list->data; int cursorOffset = -1; int lastOffset = -1; if(list->cursor) cursorOffset = list->cursor - oldData; if(list->last) lastOffset = (byte *) list->last - oldData; // Allocate more memory for the data buffer. if(list->size == 0) list->size = 1024; while(list->size < required) list->size *= 2; list->data = Z_Realloc(list->data, list->size, PU_STATIC); // Restore main pointers. list->cursor = (cursorOffset >= 0 ? list->data + cursorOffset : list->data); list->last = (lastOffset >= 0 ? (primhdr_t *) (list->data + lastOffset) : NULL); // Restore in-list pointers. if(oldData) { hdr = (primhdr_t *) list->data; while(hdr <= list->last) { if(hdr->indices != NULL) { hdr->indices = (uint *) (list->data + ((byte *) hdr->indices - oldData)); } // Check here in the end; primitive composition may be // in progress. if(hdr->size == 0) break; hdr = (primhdr_t*) ((byte*) hdr + hdr->size); } } } // Advance the cursor. list->cursor += bytes; return list->data + startOffset; } static void allocateIndices(rendlist_t* list, uint numIndices) { void* indices; list->last->numIndices = numIndices; indices = allocateData(list, sizeof(uint) * numIndices); // list->last may change during allocateData. list->last->indices = indices; } static void endWrite(rendlist_t* list) { // The primitive has been written, update the size in the header. list->last->size = list->cursor - (byte *) list->last; // Write the end marker (which will be overwritten by the next // primitive). The idea is that this zero is interpreted as the // size of the following primhdr. *(int *) list->cursor = 0; } static void writePrimitive(const rendlist_t* list, uint base, const rvertex_t* rvertices, const rtexcoord_t* coords, const rtexcoord_t* coords1, const rtexcoord_t* coords2, const rcolor_t* rcolors, uint numVertices, rendpolytype_t type) { uint i; for(i = 0; i < numVertices; ++i) { // Vertex. { const rvertex_t* rvtx = &rvertices[i]; dgl_vertex_t* vtx = &vertices[base + i]; vtx->xyz[0] = rvtx->pos[VX]; vtx->xyz[1] = rvtx->pos[VZ]; vtx->xyz[2] = rvtx->pos[VY]; } if(type == RPT_SKY_MASK) continue; // Sky masked polys need nothing more. // Primary texture coordinates. if(TU(list, TU_PRIMARY)->tex) { const rtexcoord_t* rtc = &coords[i]; dgl_texcoord_t* tc = &texCoords[TCA_MAIN][base + i]; tc->st[0] = rtc->st[0]; tc->st[1] = rtc->st[1]; } // Secondary texture coordinates. if(TU(list, TU_INTER)->tex) { const rtexcoord_t* rtc = &coords1[i]; dgl_texcoord_t* tc = &texCoords[TCA_BLEND][base + i]; tc->st[0] = rtc->st[0]; tc->st[1] = rtc->st[1]; } // First light texture coordinates. if((list->last->flags & PF_IS_LIT) && IS_MTEX_LIGHTS) { const rtexcoord_t* rtc = &coords2[i]; dgl_texcoord_t* tc = &texCoords[TCA_LIGHT][base + i]; tc->st[0] = rtc->st[0]; tc->st[1] = rtc->st[1]; } // Color. { const rcolor_t* rcolor = &rcolors[i]; dgl_color_t* color = &colors[base + i]; color->rgba[CR] = (DGLubyte) (255 * MINMAX_OF(0, rcolor->rgba[CR], 1)); color->rgba[CG] = (DGLubyte) (255 * MINMAX_OF(0, rcolor->rgba[CG], 1)); color->rgba[CB] = (DGLubyte) (255 * MINMAX_OF(0, rcolor->rgba[CB], 1)); color->rgba[CA] = (DGLubyte) (255 * MINMAX_OF(0, rcolor->rgba[CA], 1)); } } } /** * Adds one or more polys the render lists depending on configuration. */ static void addPoly(primtype_t type, rendpolytype_t polyType, const rvertex_t* rvertices, const rtexcoord_t* rtexcoords, const rtexcoord_t* rtexcoords1, const rtexcoord_t* rtexcoords2, const rcolor_t* rcolors, uint numVertices, blendmode_t blendMode, uint numLights, DGLuint modTex, float modColor[3], const rtexmapunit_t rTU[NUM_TEXMAP_UNITS]) { uint i, base, primSize, numIndices; rendlist_t* li; primhdr_t* hdr; boolean useLights = (polyType != RPT_LIGHT && numLights > 0); BEGIN_PROF( PROF_RL_ADD_POLY ); BEGIN_PROF( PROF_RL_GET_LIST ); // Find/create a rendering list for the polygon's texture. li = getListFor(polyType, rTU, useLights); END_PROF( PROF_RL_GET_LIST ); primSize = numVertices; numIndices = numVertices; base = allocateVertices(primSize); hdr = allocateData(li, sizeof(primhdr_t)); assert(hdr); li->last = hdr; // This becomes the new last primitive. // Primitive-specific blending mode. hdr->blendMode = blendMode; hdr->size = 0; hdr->indices = NULL; hdr->numIndices = 0; hdr->flags = 0; if(numLights > 1) hdr->flags |= PF_MANY_LIGHTS; else if(numLights == 1) hdr->flags |= PF_ONE_LIGHT; hdr->modTex = modTex; hdr->modColor[CR] = modColor? modColor[CR] : 0; hdr->modColor[CG] = modColor? modColor[CG] : 0; hdr->modColor[CB] = modColor? modColor[CB] : 0; hdr->modColor[CA] = 0; if(polyType == RPT_SHINY && rTU[TU_INTER].tex) { hdr->ptexScale[0] = rTU[TU_INTER].scale[0]; hdr->ptexScale[1] = rTU[TU_INTER].scale[1]; hdr->ptexOffset[0] = rTU[TU_INTER].offset[0]; hdr->ptexOffset[1] = rTU[TU_INTER].offset[1]; } else if(rTU[TU_PRIMARY].tex) { hdr->ptexScale[0] = rTU[TU_PRIMARY].scale[0]; hdr->ptexScale[1] = rTU[TU_PRIMARY].scale[1]; hdr->ptexOffset[0] = rTU[TU_PRIMARY].offset[0]; hdr->ptexOffset[1] = rTU[TU_PRIMARY].offset[1]; } if(rTU[TU_PRIMARY_DETAIL].tex) { hdr->texScale[0] = rTU[TU_PRIMARY_DETAIL].scale[0]; hdr->texScale[1] = rTU[TU_PRIMARY_DETAIL].scale[1]; hdr->texOffset[0] = rTU[TU_PRIMARY_DETAIL].offset[0]; hdr->texOffset[1] = rTU[TU_PRIMARY_DETAIL].offset[1]; } else { hdr->texScale[0] = hdr->texScale[1] = 1.f; hdr->texOffset[0] = hdr->texOffset[1] = 1.f; } // Setup the indices. allocateIndices(li, numIndices); for(i = 0; i < numIndices; ++i) li->last->indices[i] = base + i; li->last->type = (type == PT_TRIANGLE_STRIP? GL_TRIANGLE_STRIP : GL_TRIANGLE_FAN); writePrimitive(li, base, rvertices, rtexcoords, rtexcoords1, rtexcoords2, rcolors, numVertices, polyType); endWrite(li); END_PROF( PROF_RL_ADD_POLY ); } void RL_AddPoly(primtype_t type, rendpolytype_t polyType, const rvertex_t* rvertices, const rtexcoord_t* rtexcoords, const rtexcoord_t* rtexcoords1, const rtexcoord_t* rtexcoords2, const rcolor_t* rcolors, uint numVertices, uint numLights, DGLuint modTex, float modColor[3], const rtexmapunit_t rTU[NUM_TEXMAP_UNITS]) { if(numVertices < 3) return; // huh? if(type < PT_FIRST || type >= NUM_PRIM_TYPES) Con_Error("RL_AddPoly: Unknown primtype %i.", type); addPoly(type, polyType, rvertices, rtexcoords, rtexcoords1, rtexcoords2, rcolors, numVertices, rTU[TU_PRIMARY].blendMode, numLights, modTex, modColor, rTU); } /** * Draws the privitives that match the conditions. If no condition bits * are given, all primitives are considered eligible. */ static void drawPrimitives(int conditions, uint coords[MAX_TEX_UNITS], const rendlist_t* list) { primhdr_t* hdr; boolean skip, bypass = false; // Should we just skip all this? if(conditions & DCF_SKIP) return; if(TU(list, TU_INTER)->tex) { // Is blending allowed? if(conditions & DCF_NO_BLEND) return; // Should all blended primitives be included? if(conditions & DCF_BLEND) { // The other conditions will be bypassed. bypass = true; } } // Check conditions dependant on primitive-specific values once before // entering the loop. If none of the conditions are true for this list // then we can bypass the skip tests completely during iteration. if(!bypass) { if(!(conditions & DCF_JUST_ONE_LIGHT) && !(conditions & DCF_MANY_LIGHTS)) bypass = true; } // Compile our list of indices. hdr = (primhdr_t *) list->data; skip = false; while(hdr->size != 0) { // Check for skip conditions. if(!bypass) { skip = false; if((conditions & DCF_JUST_ONE_LIGHT) && (hdr->flags & PF_MANY_LIGHTS)) skip = true; else if((conditions & DCF_MANY_LIGHTS) && (hdr->flags & PF_ONE_LIGHT)) skip = true; } if(!skip) { // Render the primitive. int i; if(conditions & DCF_SET_LIGHT_ENV) { // Use the correct texture and color for the light. GL_ActiveTexture((conditions & DCF_SET_LIGHT_ENV0)? GL_TEXTURE0 : GL_TEXTURE1); rlBind(hdr->modTex, GL_LINEAR); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, hdr->modColor); // Make sure the light is not repeated. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } if(conditions & DCF_SET_MATRIX_DTEXTURE) { // Primitive-specific texture translation & scale. if(conditions & DCF_SET_MATRIX_DTEXTURE0) { GL_ActiveTexture(GL_TEXTURE0); glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glTranslatef(hdr->texOffset[0], hdr->texOffset[1], 1); glScalef(hdr->texScale[0], hdr->texScale[1], 1); } if(conditions & DCF_SET_MATRIX_DTEXTURE1) { // Primitive-specific texture translation & scale. GL_ActiveTexture(GL_TEXTURE1); glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glTranslatef(hdr->texOffset[0], hdr->texOffset[1], 1); glScalef(hdr->texScale[0], hdr->texScale[1], 1); } } if(conditions & DCF_SET_MATRIX_TEXTURE) { // Primitive-specific texture translation & scale. if(conditions & DCF_SET_MATRIX_TEXTURE0) { GL_ActiveTexture(GL_TEXTURE0); glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glTranslatef(hdr->ptexOffset[0], hdr->ptexOffset[1], 1); glScalef(hdr->ptexScale[0], hdr->ptexScale[1], 1); } if(conditions & DCF_SET_MATRIX_TEXTURE1) { GL_ActiveTexture(GL_TEXTURE1); glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glTranslatef(hdr->ptexOffset[0], hdr->ptexOffset[1], 1); glScalef(hdr->ptexScale[0], hdr->ptexScale[1], 1); } } if(conditions & DCF_SET_BLEND_MODE) { // Primitive-specific blending. Not used in all lists. GL_BlendMode(hdr->blendMode); } glBegin(hdr->type); for(i = 0; i < hdr->numIndices; ++i) { int j; uint index = hdr->indices[i]; for(j = 0; j < GL_state.maxTexUnits && j < MAX_TEX_UNITS; ++j) { if(coords[j]) { glMultiTexCoord2fvARB(GL_TEXTURE0 + j, texCoords[coords[j] - 1][index].st); } } if(!(conditions & DCF_NO_COLOR)) glColor4ubv(colors[index].rgba); glVertex3fv(vertices[index].xyz); } glEnd(); // Restore the texture matrix if changed. if(conditions & DCF_SET_MATRIX_TEXTURE) { if(conditions & DCF_SET_MATRIX_TEXTURE0) { GL_ActiveTexture(GL_TEXTURE0); glMatrixMode(GL_TEXTURE); glPopMatrix(); } if(conditions & DCF_SET_MATRIX_TEXTURE1) { GL_ActiveTexture(GL_TEXTURE1); glMatrixMode(GL_TEXTURE); glPopMatrix(); } } if(conditions & DCF_SET_MATRIX_DTEXTURE) { if(conditions & DCF_SET_MATRIX_DTEXTURE0) { GL_ActiveTexture(GL_TEXTURE0); glMatrixMode(GL_TEXTURE); glPopMatrix(); } if(conditions & DCF_SET_MATRIX_DTEXTURE1) { GL_ActiveTexture(GL_TEXTURE1); glMatrixMode(GL_TEXTURE); glPopMatrix(); } } #ifdef _DEBUG Sys_CheckGLError(); #endif } hdr = (primhdr_t *) ((byte *) hdr + hdr->size); } } /** * Set per-list GL state. * * @return The conditions to select primitives. */ static int setupListState(listmode_t mode, rendlist_t* list) { switch(mode) { case LM_SKYMASK: // Render all primitives on the list without discrimination. return DCF_NO_COLOR; case LM_ALL: // All surfaces. // Should we do blending? if(TU(list, TU_INTER)->tex) { float color[4]; // Blend between two textures, modulate with primary color. #ifdef _DEBUG if(numTexUnits < 2) Con_Error("setupListState: Not enough texture units.\n"); #endif selectTexUnits(2); rlBindTo(0, TU(list, TU_PRIMARY)); rlBindTo(1, TU(list, TU_INTER)); GL_ModulateTexture(2); color[0] = color[1] = color[2] = 0; color[3] = TU(list, TU_INTER)->blend; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); } else { // Normal modulation. selectTexUnits(1); rlBind2(TU(list, TU_PRIMARY)); GL_ModulateTexture(1); } return DCF_SET_MATRIX_TEXTURE0 | (TU(list, TU_INTER)->tex? DCF_SET_MATRIX_TEXTURE1 : 0); case LM_LIGHT_MOD_TEXTURE: // Modulate sector light, dynamic light and regular texture. rlBindTo(1, TU(list, TU_PRIMARY)); return DCF_SET_MATRIX_TEXTURE1 | DCF_SET_LIGHT_ENV0 | DCF_JUST_ONE_LIGHT | DCF_NO_BLEND; case LM_TEXTURE_PLUS_LIGHT: rlBindTo(0, TU(list, TU_PRIMARY)); return DCF_SET_MATRIX_TEXTURE0 | DCF_SET_LIGHT_ENV1 | DCF_NO_BLEND; case LM_FIRST_LIGHT: // Draw all primitives with more than one light // and all primitives which will have a blended texture. return DCF_SET_LIGHT_ENV0 | DCF_MANY_LIGHTS | DCF_BLEND; case LM_BLENDED: { float color[4]; // Only render the blended surfaces. if(!TU(list, TU_INTER)->tex) return DCF_SKIP; #ifdef _DEBUG if(numTexUnits < 2) Con_Error("setupListState: Not enough texture units.\n"); #endif selectTexUnits(2); rlBindTo(0, TU(list, TU_PRIMARY)); rlBindTo(1, TU(list, TU_INTER)); GL_ModulateTexture(2); color[0] = color[1] = color[2] = 0; color[3] = TU(list, TU_INTER)->blend; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); return DCF_SET_MATRIX_TEXTURE0 | DCF_SET_MATRIX_TEXTURE1; } case LM_BLENDED_FIRST_LIGHT: // Only blended surfaces. if(!TU(list, TU_INTER)->tex) return DCF_SKIP; return DCF_SET_MATRIX_TEXTURE1 | DCF_SET_LIGHT_ENV0; case LM_WITHOUT_TEXTURE: // Only render the primitives affected by dynlights. return 0; case LM_LIGHTS: // The light lists only contain dynlight primitives. rlBind2(TU(list, TU_PRIMARY)); // Make sure the texture is not repeated. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); return 0; case LM_BLENDED_MOD_TEXTURE: // Blending required. if(!TU(list, TU_INTER)->tex) break; case LM_MOD_TEXTURE: case LM_MOD_TEXTURE_MANY_LIGHTS: // Texture for surfaces with (many) dynamic lights. // Should we do blending? if(TU(list, TU_INTER)->tex) { float color[4]; // Mode 3 actually just disables the second texture stage, // which would modulate with primary color. #ifdef _DEBUG if(numTexUnits < 2) Con_Error("setupListState: Not enough texture units.\n"); #endif selectTexUnits(2); rlBindTo(0, TU(list, TU_PRIMARY)); rlBindTo(1, TU(list, TU_INTER)); GL_ModulateTexture(3); color[0] = color[1] = color[2] = 0; color[3] = TU(list, TU_INTER)->blend; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); // Render all primitives. return DCF_SET_MATRIX_TEXTURE0 | DCF_SET_MATRIX_TEXTURE1; } // No modulation at all. selectTexUnits(1); rlBind2(TU(list, TU_PRIMARY)); GL_ModulateTexture(0); return DCF_SET_MATRIX_TEXTURE0 | (mode == LM_MOD_TEXTURE_MANY_LIGHTS ? DCF_MANY_LIGHTS : 0); case LM_UNBLENDED_MOD_TEXTURE_AND_DETAIL: // Blending is not done now. if(TU(list, TU_INTER)->tex) break; if(TU(list, TU_PRIMARY_DETAIL)->tex) { selectTexUnits(2); GL_ModulateTexture(9); // Tex+Detail, no color. rlBindTo(0, TU(list, TU_PRIMARY)); rlBindTo(1, TU(list, TU_PRIMARY_DETAIL)); return DCF_SET_MATRIX_TEXTURE0 | DCF_SET_MATRIX_DTEXTURE1; } else { selectTexUnits(1); GL_ModulateTexture(0); rlBind2(TU(list, TU_PRIMARY)); return DCF_SET_MATRIX_TEXTURE0; } break; case LM_ALL_DETAILS: if(TU(list, TU_PRIMARY_DETAIL)->tex) { rlBind2(TU(list, TU_PRIMARY_DETAIL)); // Render all surfaces on the list. return DCF_SET_MATRIX_DTEXTURE0; } break; case LM_UNBLENDED_TEXTURE_AND_DETAIL: // Only unblended. Details are optional. if(TU(list, TU_INTER)->tex) break; if(TU(list, TU_PRIMARY_DETAIL)->tex) { selectTexUnits(2); GL_ModulateTexture(8); rlBindTo(0, TU(list, TU_PRIMARY)); rlBindTo(1, TU(list, TU_PRIMARY_DETAIL)); return DCF_SET_MATRIX_TEXTURE0 | DCF_SET_MATRIX_DTEXTURE1; } else { // Normal modulation. selectTexUnits(1); GL_ModulateTexture(1); rlBind2(TU(list, TU_PRIMARY)); return DCF_SET_MATRIX_TEXTURE0; } break; case LM_BLENDED_DETAILS: { float color[4]; // We'll only render blended primitives. if(!TU(list, TU_INTER)->tex) break; if(!TU(list, TU_PRIMARY_DETAIL)->tex || !TU(list, TU_INTER_DETAIL)->tex) break; rlBindTo(0, TU(list, TU_PRIMARY_DETAIL)); rlBindTo(1, TU(list, TU_INTER_DETAIL)); color[0] = color[1] = color[2] = 0; color[3] = TU(list, TU_INTER_DETAIL)->blend; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); return DCF_SET_MATRIX_DTEXTURE0 | DCF_SET_MATRIX_DTEXTURE1; } case LM_SHADOW: // Render all primitives. if(TU(list, TU_PRIMARY)->tex) rlBind2(TU(list, TU_PRIMARY)); else rlBind(0, GL_LINEAR); if(!TU(list, TU_PRIMARY)->tex) { // Apply a modelview shift. glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Scale towards the viewpoint to avoid Z-fighting. glTranslatef(vx, vy, vz); glScalef(.99f, .99f, .99f); glTranslatef(-vx, -vy, -vz); } return 0; case LM_MASKED_SHINY: if(TU(list, TU_INTER)->tex) { selectTexUnits(2); // The intertex holds the info for the mask texture. rlBindTo(1, TU(list, TU_INTER)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); {float color[4]; color[0] = color[1] = color[2] = 0; color[3] = 1.0f; glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); } } case LM_ALL_SHINY: case LM_SHINY: rlBindTo(0, TU(list, TU_PRIMARY)); if(!TU(list, TU_INTER)->tex) selectTexUnits(1); // Make sure the texture is not clamped. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); // Render all primitives. if(mode == LM_ALL_SHINY) return DCF_SET_BLEND_MODE; if(mode == LM_MASKED_SHINY) return DCF_SET_BLEND_MODE | DCF_SET_MATRIX_TEXTURE1; return DCF_SET_BLEND_MODE | DCF_NO_BLEND; default: break; } // Unknown mode, let's not draw anything. return DCF_SKIP; } static void finishListState(listmode_t mode, rendlist_t* list) { switch(mode) { default: break; case LM_SHADOW: if(!TU(list, TU_PRIMARY)->tex) { // Restore original modelview matrix. glMatrixMode(GL_MODELVIEW); glPopMatrix(); } break; case LM_SHINY: case LM_ALL_SHINY: case LM_MASKED_SHINY: GL_BlendMode(BM_NORMAL); break; } } static void finishPassState(listmode_t mode) { switch(mode) { default: break; case LM_ALL: case LM_SHADOW: case LM_BLENDED: case LM_LIGHT_MOD_TEXTURE: case LM_TEXTURE_PLUS_LIGHT: case LM_LIGHTS: case LM_UNBLENDED_TEXTURE_AND_DETAIL: case LM_ALL_DETAILS: case LM_BLENDED_DETAILS: case LM_SHINY: case LM_MASKED_SHINY: case LM_ALL_SHINY: if(usingFog) glDisable(GL_FOG); break; } } /** * Setup GL state for an entire rendering pass (compassing multiple lists). */ static void setupPassState(listmode_t mode, uint coords[MAX_TEX_UNITS]) { memset(coords, 0, sizeof(*coords) * MAX_TEX_UNITS); switch(mode) { case LM_SKYMASK: selectTexUnits(0); glDisable(GL_ALPHA_TEST); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // We don't want to write to the color buffer. glEnable(GL_BLEND); glBlendFunc(GL_ZERO, GL_ONE); break; case LM_BLENDED: selectTexUnits(2); case LM_ALL: // The first texture unit is used for the main texture. coords[0] = TCA_MAIN + 1; coords[1] = TCA_BLEND + 1; glDisable(GL_ALPHA_TEST); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // Fog is allowed during this pass. if(usingFog) glEnable(GL_FOG); // All of the surfaces are opaque. glDisable(GL_BLEND); break; case LM_LIGHT_MOD_TEXTURE: case LM_TEXTURE_PLUS_LIGHT: // Modulate sector light, dynamic light and regular texture. selectTexUnits(2); if(mode == LM_LIGHT_MOD_TEXTURE) { coords[0] = TCA_LIGHT + 1; coords[1] = TCA_MAIN + 1; GL_ModulateTexture(4); // Light * texture. } else { coords[0] = TCA_MAIN + 1; coords[1] = TCA_LIGHT + 1; GL_ModulateTexture(5); // Texture + light. } glDisable(GL_ALPHA_TEST); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // Fog is allowed during this pass. if(usingFog) glEnable(GL_FOG); // All of the surfaces are opaque. glDisable(GL_BLEND); break; case LM_FIRST_LIGHT: // One light, no texture. selectTexUnits(1); coords[0] = TCA_LIGHT + 1; GL_ModulateTexture(6); glDisable(GL_ALPHA_TEST); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // All of the surfaces are opaque. glDisable(GL_BLEND); break; case LM_BLENDED_FIRST_LIGHT: // One additive light, no texture. selectTexUnits(1); coords[0] = TCA_LIGHT + 1; GL_ModulateTexture(7); // Add light, no color. glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 1 / 255.0f); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // All of the surfaces are opaque. glEnable(GL_BLEND); glBlendFunc(GL_ONE, GL_ONE); break; case LM_WITHOUT_TEXTURE: selectTexUnits(0); GL_ModulateTexture(1); glDisable(GL_ALPHA_TEST); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // All of the surfaces are opaque. glDisable(GL_BLEND); break; case LM_LIGHTS: selectTexUnits(1); coords[0] = TCA_MAIN + 1; GL_ModulateTexture(1); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 1 / 255.0f); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); if(usingFog) { glEnable(GL_FOG); glFogfv(GL_FOG_COLOR, blackColor); } glEnable(GL_BLEND); GL_BlendMode(BM_ADD); break; case LM_MOD_TEXTURE: case LM_MOD_TEXTURE_MANY_LIGHTS: case LM_BLENDED_MOD_TEXTURE: // The first texture unit is used for the main texture. coords[0] = TCA_MAIN + 1; coords[1] = TCA_BLEND + 1; glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // All of the surfaces are opaque. glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_ZERO); break; case LM_UNBLENDED_TEXTURE_AND_DETAIL: coords[0] = TCA_MAIN + 1; coords[1] = TCA_MAIN + 1; glDisable(GL_ALPHA_TEST); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); // All of the surfaces are opaque. glDisable(GL_BLEND); // Fog is allowed. if(usingFog) glEnable(GL_FOG); break; case LM_UNBLENDED_MOD_TEXTURE_AND_DETAIL: coords[0] = TCA_MAIN + 1; coords[1] = TCA_MAIN + 1; glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // All of the surfaces are opaque. glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_ZERO); break; case LM_ALL_DETAILS: selectTexUnits(1); coords[0] = TCA_MAIN + 1; GL_ModulateTexture(0); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // All of the surfaces are opaque. glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // Use fog to fade the details, if fog is enabled. if(usingFog) { float midGray[4]; glEnable(GL_FOG); midGray[0] = midGray[1] = midGray[2] = .5f; midGray[3] = fogColor[3]; // The alpha is probably meaningless? glFogfv(GL_FOG_COLOR, midGray); } break; case LM_BLENDED_DETAILS: selectTexUnits(2); coords[0] = TCA_MAIN + 1; coords[1] = TCA_BLEND + 1; GL_ModulateTexture(3); glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // All of the surfaces are opaque. glEnable(GL_BLEND); glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // Use fog to fade the details, if fog is enabled. if(usingFog) { float midGray[4]; glEnable(GL_FOG); midGray[0] = midGray[1] = midGray[2] = .5f; midGray[3] = fogColor[3]; // The alpha is probably meaningless? glFogfv(GL_FOG_COLOR, midGray); } break; case LM_SHADOW: // A bit like 'negative lights'. selectTexUnits(1); coords[0] = TCA_MAIN + 1; GL_ModulateTexture(1); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 1 / 255.0f); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); // Set normal fog, if it's enabled. if(usingFog) { glEnable(GL_FOG); glFogfv(GL_FOG_COLOR, fogColor); } glEnable(GL_BLEND); GL_BlendMode(BM_NORMAL); break; case LM_SHINY: selectTexUnits(1); coords[0] = TCA_MAIN + 1; GL_ModulateTexture(1); // 8 for multitexture glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); if(usingFog) { // Fog makes the shininess diminish in the distance. glEnable(GL_FOG); glFogfv(GL_FOG_COLOR, blackColor); } glEnable(GL_BLEND); GL_BlendMode(BM_ADD); // Purely additive. break; case LM_MASKED_SHINY: selectTexUnits(2); coords[0] = TCA_MAIN + 1; coords[1] = TCA_BLEND + 1; // the mask GL_ModulateTexture(8); // same as with details glDisable(GL_ALPHA_TEST); glDepthMask(GL_FALSE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LEQUAL); if(usingFog) { // Fog makes the shininess diminish in the distance. glEnable(GL_FOG); glFogfv(GL_FOG_COLOR, blackColor); } glEnable(GL_BLEND); GL_BlendMode(BM_ADD); // Purely additive. break; default: break; } } /** * Renders the given lists. They must not be empty. */ static void renderLists(listmode_t mode, rendlist_t** lists, uint num) { uint i; rendlist_t* list; uint coords[MAX_TEX_UNITS]; // If the first list is empty, we do nothing. Normally we expect // all lists to contain something. if(num == 0 || lists[0]->last == NULL) return; // Setup GL state that's common to all the lists in this mode. setupPassState(mode, coords); // Draw each given list. for(i = 0; i < num; ++i) { list = lists[i]; // Setup GL state for this list, and draw the necessary subset of // primitives on the list. drawPrimitives(setupListState(mode, list), coords, list); // Some modes require cleanup. finishListState(mode, list); } finishPassState(mode); } /** * Extracts a selection of lists from the hash. */ static uint collectLists(listhash_t* table, rendlist_t** lists) { uint i, count; rendlist_t* it; // Collect a list of rendering lists. count = 0; for(i = 0; i < RL_HASH_SIZE; ++i) { for(it = table[i].first; it; it = it->next) { // Only non-empty lists are collected. if(it->last != NULL) { if(count == MAX_RLISTS) { #ifdef _DEBUG Con_Error("collectLists: Ran out of MAX_RLISTS.\n"); #endif return count; } lists[count++] = it; } } } return count; } /** * We have several different paths to accommodate both multitextured * details and dynamic lights. Details take precedence (they always cover * entire primitives, and usually *all* of the surfaces in a scene). */ void RL_RenderAllLists(void) { uint count; // Pointers to all the rendering lists. rendlist_t* lists[MAX_RLISTS]; BEGIN_PROF( PROF_RL_RENDER_ALL ); if(!freezeRLs) // Only update when lists are not frozen. { if(devRendSkyAlways) { rendSky = true; skyhemispheres |= SKYHEMI_UPPER | SKYHEMI_LOWER; } else rendSky = !P_IsInVoid(viewPlayer); } // When in the void we don't render a sky. // \fixme We could use a stencil when rendering the sky, using the // already collected skymask polys as a mask. if(rendSky && !devRendSkyMode) // The sky might be visible. Render the needed hemispheres. Rend_RenderSky(skyhemispheres); // Mask the sky in the Z-buffer. lists[0] = &skyMaskList; // \fixme As we arn't rendering the sky when in the void we have // have no need to render the skymask. BEGIN_PROF( PROF_RL_RENDER_SKYMASK ); if(rendSky) renderLists(LM_SKYMASK, lists, 1); END_PROF( PROF_RL_RENDER_SKYMASK ); // Render the real surfaces of the visible world. /** * Unlit Primitives (all normal lists). */ BEGIN_PROF( PROF_RL_RENDER_NORMAL ); count = collectLists(plainHash, lists); if(IS_MTEX_DETAILS) { // Draw details for unblended surfaces in this pass. renderLists(LM_UNBLENDED_TEXTURE_AND_DETAIL, lists, count); // Blended surfaces. renderLists(LM_BLENDED, lists, count); } else { // Blending is done during this pass. renderLists(LM_ALL, lists, count); } END_PROF( PROF_RL_RENDER_NORMAL ); /** * Lit Primitives */ BEGIN_PROF( PROF_RL_RENDER_LIGHT ); count = collectLists(litHash, lists); // If multitexturing is available, we'll use it to our advantage // when rendering lights. if(IS_MTEX_LIGHTS && dlBlend != 2) { if(IS_MUL) { // All (unblended) surfaces with exactly one light can be // rendered in a single pass. renderLists(LM_LIGHT_MOD_TEXTURE, lists, count); // Render surfaces with many lights without a texture, just // with the first light. renderLists(LM_FIRST_LIGHT, lists, count); } else // Additive ('foggy') lights. { renderLists(LM_TEXTURE_PLUS_LIGHT, lists, count); // Render surfaces with blending. renderLists(LM_BLENDED, lists, count); // Render the first light for surfaces with blending. // (Not optimal but shouldn't matter; texture is changed for // each primitive.) renderLists(LM_BLENDED_FIRST_LIGHT, lists, count); } } else // Multitexturing is not available for lights. { if(IS_MUL) { // Render all lit surfaces without a texture. renderLists(LM_WITHOUT_TEXTURE, lists, count); } else { if(IS_MTEX_DETAILS) // Draw detail textures using multitexturing. { // Unblended surfaces with a detail. renderLists(LM_UNBLENDED_TEXTURE_AND_DETAIL, lists, count); // Blended surfaces without details. renderLists(LM_BLENDED, lists, count); // Details for blended surfaces. renderLists(LM_BLENDED_DETAILS, lists, count); } else { renderLists(LM_ALL, lists, count); } } } /** * Dynamic Lights * * Draw all dynamic lights (always additive). */ count = collectLists(dynHash, lists); if(dlBlend != 2) renderLists(LM_LIGHTS, lists, count); END_PROF( PROF_RL_RENDER_LIGHT ); /** * Texture Modulation Pass */ if(IS_MUL) { // Finish the lit surfaces that didn't yet get a texture. count = collectLists(litHash, lists); if(IS_MTEX_DETAILS) { renderLists(LM_UNBLENDED_MOD_TEXTURE_AND_DETAIL, lists, count); renderLists(LM_BLENDED_MOD_TEXTURE, lists, count); renderLists(LM_BLENDED_DETAILS, lists, count); } else { if(IS_MTEX_LIGHTS && dlBlend != 2) { renderLists(LM_MOD_TEXTURE_MANY_LIGHTS, lists, count); } else { renderLists(LM_MOD_TEXTURE, lists, count); } } } /** * Detail Modulation Pass * * If multitexturing is not available for details, we need to apply * them as an extra pass over all the detailed surfaces. */ if(r_detail) { // Render detail textures for all surfaces that need them. count = collectLists(plainHash, lists); if(IS_MTEX_DETAILS) { // Blended detail textures. renderLists(LM_BLENDED_DETAILS, lists, count); } else { renderLists(LM_ALL_DETAILS, lists, count); count = collectLists(litHash, lists); renderLists(LM_ALL_DETAILS, lists, count); } } /** * Shiny Surfaces Pass * * Draw the shiny environment surfaces. * * If we have two texture units, the shiny masks will be * enabled. Otherwise the masks are ignored. The shine is * basically specular environmental additive light, multiplied * by the mask so that black texels in the mask produce areas * without shine. * * Walls with holes (so called 'masked textures') cannot be * shiny. */ BEGIN_PROF( PROF_RL_RENDER_SHINY ); count = collectLists(shinyHash, lists); if(numTexUnits > 1) { // Render masked shiny surfaces in a separate pass. renderLists(LM_SHINY, lists, count); renderLists(LM_MASKED_SHINY, lists, count); } else { renderLists(LM_ALL_SHINY, lists, count); } END_PROF( PROF_RL_RENDER_SHINY ); /** * Shadow Pass: Objects and FakeRadio */ { int oldr = renderTextures; renderTextures = true; BEGIN_PROF( PROF_RL_RENDER_SHADOW ); count = collectLists(shadowHash, lists); renderLists(LM_SHADOW, lists, count); END_PROF( PROF_RL_RENDER_SHADOW ); renderTextures = oldr; } // Return to the normal GL state. selectTexUnits(1); GL_ModulateTexture(1); glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0); glEnable(GL_BLEND); GL_BlendMode(BM_NORMAL); if(usingFog) { glEnable(GL_FOG); glFogfv(GL_FOG_COLOR, fogColor); } // Draw masked walls, sprites and models. BEGIN_PROF( PROF_RL_RENDER_MASKED ); Rend_DrawMasked(); // Draw particles. Rend_RenderParticles(); if(usingFog) glDisable(GL_FOG); END_PROF( PROF_RL_RENDER_MASKED ); END_PROF( PROF_RL_RENDER_ALL ); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_linedef.c0000644000175000017500000002123711357170242023027 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_linedef.c: World linedefs. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" #include "m_bams.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static void calcNormal(const linedef_t* l, byte side, pvec2_t normal) { V2_Set(normal, (l->L_vpos(side^1)[VY] - l->L_vpos(side)[VY]) / l->length, (l->L_vpos(side)[VX] - l->L_vpos(side^1)[VX]) / l->length); } static float lightLevelDelta(const pvec2_t normal) { return (1.0f / 255) * (normal[VX] * 18) * rendLightWallAngle; } static linedef_t* findBlendNeighbor(const linedef_t* l, byte side, byte right, binangle_t* diff) { if(!l->L_backside || l->L_backsector->SP_ceilvisheight <= l->L_frontsector->SP_floorvisheight || l->L_backsector->SP_floorvisheight >= l->L_frontsector->SP_ceilvisheight) { return R_FindSolidLineNeighbor(l->L_sector(side), l, l->L_vo(right^side), right, diff); } return R_FindLineNeighbor(l->L_sector(side), l, l->L_vo(right^side), right, diff); } /** * The DOOM lighting model applies a sector light level delta when drawing * segs based on their 2D world angle. * * @param l Linedef to calculate the delta for. * @param side Side of the linedef we are interested in. * @param deltaL Light delta for the left edge is written back here. * @param deltaR Light delta for the right edge is written back here. */ void Linedef_LightLevelDelta(const linedef_t* l, byte side, float* deltaL, float* deltaR) { vec2_t normal; float delta; // Disabled? if(!(rendLightWallAngle > 0)) { *deltaL = *deltaR = 0; return; } calcNormal(l, side, normal); delta = lightLevelDelta(normal); // If smoothing is disabled use this delta for left and right edges. // Must forcibly disable smoothing for polyobj linedefs as they have // no owner rings. if(!rendLightWallAngleSmooth || (l->inFlags & LF_POLYOBJ)) { *deltaL = *deltaR = delta; return; } // Find the left neighbour linedef for which we will calculate the // lightlevel delta and then blend with this to produce the value for // the left edge. Blend iff the angle between the two linedefs is less // than 45 degrees. { binangle_t diff = 0; linedef_t* other = findBlendNeighbor(l, side, 0, &diff); if(other && INRANGE_OF(diff, BANG_180, BANG_45)) { vec2_t otherNormal; calcNormal(other, other->L_v2 != l->L_v(side), otherNormal); // Average normals. V2_Sum(otherNormal, otherNormal, normal); otherNormal[VX] /= 2; otherNormal[VY] /= 2; *deltaL = lightLevelDelta(otherNormal); } else *deltaL = delta; } // Do the same for the right edge but with the right neighbour linedef. { binangle_t diff = 0; linedef_t* other = findBlendNeighbor(l, side, 1, &diff); if(other && INRANGE_OF(diff, BANG_180, BANG_45)) { vec2_t otherNormal; calcNormal(other, other->L_v1 != l->L_v(side^1), otherNormal); // Average normals. V2_Sum(otherNormal, otherNormal, normal); otherNormal[VX] /= 2; otherNormal[VY] /= 2; *deltaR = lightLevelDelta(otherNormal); } else *deltaR = delta; } } /** * Update the linedef, property is selected by DMU_* name. */ boolean Linedef_SetProperty(linedef_t *lin, const setargs_t *args) { switch(args->prop) { case DMU_FRONT_SECTOR: DMU_SetValue(DMT_LINEDEF_SEC, &lin->L_frontsector, args, 0); break; case DMU_BACK_SECTOR: DMU_SetValue(DMT_LINEDEF_SEC, &lin->L_backsector, args, 0); break; case DMU_SIDEDEF0: DMU_SetValue(DMT_LINEDEF_SIDEDEFS, &lin->L_frontside, args, 0); break; case DMU_SIDEDEF1: DMU_SetValue(DMT_LINEDEF_SIDEDEFS, &lin->L_backside, args, 0); break; case DMU_VALID_COUNT: DMU_SetValue(DMT_LINEDEF_VALIDCOUNT, &lin->validCount, args, 0); break; case DMU_FLAGS: { sidedef_t *s; DMU_SetValue(DMT_LINEDEF_FLAGS, &lin->flags, args, 0); s = lin->L_frontside; Surface_Update(&s->SW_topsurface); Surface_Update(&s->SW_bottomsurface); Surface_Update(&s->SW_middlesurface); if(lin->L_backside) { s = lin->L_backside; Surface_Update(&s->SW_topsurface); Surface_Update(&s->SW_bottomsurface); Surface_Update(&s->SW_middlesurface); } break; } default: Con_Error("Linedef_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } /** * Get the value of a linedef property, selected by DMU_* name. */ boolean Linedef_GetProperty(const linedef_t *lin, setargs_t *args) { switch(args->prop) { case DMU_VERTEX0: DMU_GetValue(DMT_LINEDEF_V, &lin->L_v1, args, 0); break; case DMU_VERTEX1: DMU_GetValue(DMT_LINEDEF_V, &lin->L_v2, args, 0); break; case DMU_DX: DMU_GetValue(DMT_LINEDEF_DX, &lin->dX, args, 0); break; case DMU_DY: DMU_GetValue(DMT_LINEDEF_DY, &lin->dY, args, 0); break; case DMU_DXY: DMU_GetValue(DMT_LINEDEF_DX, &lin->dX, args, 0); DMU_GetValue(DMT_LINEDEF_DY, &lin->dY, args, 1); break; case DMU_LENGTH: DMU_GetValue(DDVT_FLOAT, &lin->length, args, 0); break; case DMU_ANGLE: DMU_GetValue(DDVT_ANGLE, &lin->angle, args, 0); break; case DMU_SLOPE_TYPE: DMU_GetValue(DMT_LINEDEF_SLOPETYPE, &lin->slopeType, args, 0); break; case DMU_FRONT_SECTOR: { sector_t *sec = (lin->L_frontside? lin->L_frontsector : NULL); DMU_GetValue(DMT_LINEDEF_SEC, &sec, args, 0); break; } case DMU_BACK_SECTOR: { sector_t *sec = (lin->L_backside? lin->L_backsector : NULL); DMU_GetValue(DMT_LINEDEF_SEC, &sec, args, 0); break; } case DMU_FLAGS: DMU_GetValue(DMT_LINEDEF_FLAGS, &lin->flags, args, 0); break; case DMU_SIDEDEF0: DMU_GetValue(DDVT_PTR, &lin->L_frontside, args, 0); break; case DMU_SIDEDEF1: DMU_GetValue(DDVT_PTR, &lin->L_backside, args, 0); break; case DMU_BOUNDING_BOX: if(args->valueType == DDVT_PTR) { const float* bbox = lin->bBox; DMU_GetValue(DDVT_PTR, &bbox, args, 0); } else { DMU_GetValue(DMT_LINEDEF_BBOX, &lin->bBox[0], args, 0); DMU_GetValue(DMT_LINEDEF_BBOX, &lin->bBox[1], args, 1); DMU_GetValue(DMT_LINEDEF_BBOX, &lin->bBox[2], args, 2); DMU_GetValue(DMT_LINEDEF_BBOX, &lin->bBox[3], args, 3); } break; case DMU_VALID_COUNT: DMU_GetValue(DMT_LINEDEF_VALIDCOUNT, &lin->validCount, args, 0); break; default: Con_Error("Linedef_GetProperty: No property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_decomp64.c0000644000175000017500000001505111357170242023034 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_decomp64.c: Decompression algorithm. * * Used with various lumps of DOOM64 data. */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static short mapA[629], mapB[629]; static short tableA[1258], tableB[1258]; static const byte* srcPos; // CODE -------------------------------------------------------------------- static void cycleTable(int a, int b) { short n; for(;;) { if(a == mapA[tableA[b]]) n = mapB[tableA[b]]; else n = mapA[tableA[b]]; tableB[tableA[a]] = tableB[n] + tableB[a]; if(tableA[a] == 1) break; a = b = tableA[a]; } } static short rotateMap(int a, int b, int c) { if(a == mapA[tableA[a]]) { mapB[tableA[a]] = c; } else { mapA[tableA[a]] = c; } if(c == mapA[a]) { mapA[a] = b; return mapB[a]; } else { mapB[a] = b; return mapA[a]; } } /** * DOOM64 data decompression algorithm. * * \todo Needs further analysis and documentation. * Get rid of the fixed-size working buffer used with byte sequences. * Clean up * * @param dst Output buffer. Must be large enough! * @param src Src buffer (the compressed data). */ void M_Decompress64(byte* dst, const byte* src) { #define BUFF_SIZE (21903) // ith = ((2 / 3) * (4 ^ n - 1)) * 8 static const int strides[] = {0, 16, 80, 336, 1360, 5456}; int i, val, lastOut, curByte; byte buff[BUFF_SIZE], curBit; byte* dstPos; // Initialize LUTs, todo: precalculate where possible. for(i = 0; i < 1258; ++i) { tableB[i] = 1; } for(i = 0; i < 1258; ++i) { tableA[i] = ((i + 2) / 2) - 1; } mapB[0] = 0; for(i = 0; i < 628; ++i) { mapB[1 + i] = (i * 2) + 3; } for(i = 0; i < 629; ++i) { mapA[i] = i * 2; } srcPos = src; dstPos = dst; curByte = 0; curBit = 0; // Begin decompression. lastOut = 0; do { int index = 1; while(index < 629) { if(curBit == 0) curByte = *srcPos++; if(curByte & 0x80) index = mapB[index]; else index = mapA[index]; curBit = (curBit == 0? 7 : curBit - 1); curByte <<= 1; } tableB[index]++; if(tableA[index] != 1) { cycleTable(index, index); if(tableB[1] == 2000) { int i; for(i = 0; i < 1258; ++i) { tableB[i] >>= 1; } } } { int c; c = index; while(tableA[c] != 1) { int b, a; a = tableA[c]; if(a == mapA[tableA[a]]) b = mapB[tableA[a]]; else b = mapA[tableA[a]]; if(tableB[b] < tableB[c]) { int result; result = rotateMap(a, b, c); tableA[b] = a; tableA[c] = tableA[a]; cycleTable(b, result); c = tableA[b]; } else { c = tableA[c]; } } } val = index - 629; if(val != 256) { if(val < 256) { byte out = (val & 0xff); *dstPos++ = out; buff[lastOut++] = out; } else { int i, div, to, from, num, result; div = (val - 257) / 62; result = 0; { int shift = 1; for(i = 0; i < div * 2 + 4; ++i) { if(curBit == 0) curByte = *srcPos++; if((curByte) & 0x80) result |= shift; curBit = (curBit == 0? 7 : curBit - 1); curByte <<= 1; shift <<= 1; } } num = val - 254 - (div * 62); from = lastOut - result - strides[div] - num; if(from < 0) from += BUFF_SIZE; to = lastOut; for(i = 0; i < num; ++i) { byte out = buff[from]; *dstPos++ = out; buff[to] = out; if(++from == BUFF_SIZE) from = 0; if(++to == BUFF_SIZE) to = 0; } lastOut += num; } if(lastOut >= BUFF_SIZE) lastOut -= BUFF_SIZE; } } while(val != 256); #undef BUFF_SIZE } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_opengl.c0000644000175000017500000005046711357170242023273 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_opengl.c: OpenGL interface, low-level. * * Get OpenGL header files from: * http://oss.sgi.com/projects/ogl-sample/ */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #include "de_base.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #ifdef WIN32 # define GETPROC(x) x = (void*)wglGetProcAddress(#x) #elif defined(UNIX) # define GETPROC(x) x = SDL_GL_GetProcAddress(#x) #endif // TYPES ------------------------------------------------------------------- // FUNCTION PROTOTYPES ----------------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- gl_state_t GL_state; gl_state_ext_t GL_state_ext; #ifdef WIN32 PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; PFNGLCLIENTACTIVETEXTUREPROC glClientActiveTextureARB; PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB; PFNGLMULTITEXCOORD2FVARBPROC glMultiTexCoord2fvARB; PFNGLBLENDEQUATIONEXTPROC glBlendEquationEXT; PFNGLLOCKARRAYSEXTPROC glLockArraysEXT; PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT; PFNGLCOLORTABLEEXTPROC glColorTableEXT; #endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean initedGL = false; static boolean firstTimeInit = true; #if WIN32 static PROC wglGetExtString; #endif // CODE -------------------------------------------------------------------- static void checkExtensions(void) { Sys_InitGLExtensions(); #ifdef WIN32 Sys_InitWGLExtensions(); #endif // Get the maximum texture size. glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint*) &GL_state.maxTexSize); glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint*) &GL_state.maxTexUnits); #ifndef USE_MULTITEXTURE GL_state.maxTexUnits = 1; #endif // But sir, we are simple people; two units is enough. if(GL_state.maxTexUnits > 2) GL_state.maxTexUnits = 2; if(GL_state_ext.aniso) glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, (GLint*) &GL_state.maxAniso); else GL_state.maxAniso = 1; // Decide whether vertex arrays should be done manually or with real // OpenGL calls. GL_InitArrays(); GL_state.useAnisotropic = ((GL_state_ext.aniso && !ArgExists("-noanifilter"))? true : false); GL_state.allowCompression = true; } static void printGLUInfo(void) { GLint iVal; GLfloat fVals[2]; // Print some OpenGL information (console must be initialized by now). Con_Message("OpenGL information:\n"); Con_Message(" Vendor: %s\n", glGetString(GL_VENDOR)); Con_Message(" Renderer: %s\n", glGetString(GL_RENDERER)); Con_Message(" Version: %s\n", glGetString(GL_VERSION)); Con_Message(" GLU Version: %s\n", gluGetString(GLU_VERSION)); glGetIntegerv(GL_MAX_TEXTURE_UNITS, &iVal); Con_Message(" Available Texture units: %i\n", iVal); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &iVal); Con_Message(" Maximum Texture Size: %i\n", iVal); if(GL_state_ext.aniso) { glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &iVal); Con_Message(" Maximum Anisotropy: %i\n", iVal); } else { Con_Message(" Variable Texture Anisotropy Unavailable.\n"); } if(GL_state_ext.s3TC) { glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &iVal); Con_Message(" Num Texture Formats: %i\n", iVal); } glGetFloatv(GL_LINE_WIDTH_GRANULARITY, fVals); Con_Message(" Line Width Granularity: %3.1f\n", fVals[0]); glGetFloatv(GL_LINE_WIDTH_RANGE, fVals); Con_Message(" Line Width Range: %3.1f...%3.1f\n", fVals[0], fVals[1]); Sys_PrintGLExtensions(); } static void printDGLConfiguration(void) { static const char *yesNo[] = {"Disabled", "Enabled"}; Con_Message("DGL Configuration:\n"); Con_Message(" NPOT Textures: %s\n", yesNo[GL_state.textureNonPow2? 1:0]); Con_Message(" Texture Compression: %s\n", yesNo[GL_state_texture.useCompr? 1:0]); Con_Message(" Variable Texture Anisotropy: %s\n", yesNo[GL_state.useAnisotropic? 1:0]); Con_Message(" Utilized Texture Units: %i\n", GL_state.maxTexUnits); #ifdef WIN32 Con_Message(" Multisampling: %s", yesNo[GL_state_ext.wglMultisampleARB? 1:0]); if(GL_state_ext.wglMultisampleARB) Con_Message(" (%i)\n", GL_state.multisampleFormat); #endif } #ifdef WIN32 static void testMultisampling(HDC hDC) { int pixelFormat; int valid; uint numFormats; float fAttributes[] = {0,0}; int iAttributes[] = { WGL_DRAW_TO_WINDOW_ARB,GL_TRUE, WGL_SUPPORT_OPENGL_ARB,GL_TRUE, WGL_ACCELERATION_ARB,WGL_FULL_ACCELERATION_ARB, WGL_COLOR_BITS_ARB,24, WGL_ALPHA_BITS_ARB,8, WGL_DEPTH_BITS_ARB,16, WGL_STENCIL_BITS_ARB,0, WGL_DOUBLE_BUFFER_ARB,GL_TRUE, WGL_SAMPLE_BUFFERS_ARB,GL_TRUE, WGL_SAMPLES_ARB,4, 0,0 }; // First, see if we can get a pixel format using four samples. valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats); if(valid && numFormats >= 1) { // This will do nicely. GL_state_ext.wglMultisampleARB = 1; GL_state.multisampleFormat = pixelFormat; } else { // Failed. Try a pixel format using two samples. iAttributes[19] = 2; valid = wglChoosePixelFormatARB(hDC, iAttributes, fAttributes, 1, &pixelFormat, &numFormats); if(valid && numFormats >= 1) { GL_state_ext.wglMultisampleARB = 1; GL_state.multisampleFormat = pixelFormat; } } } static void createDummyWindow(application_t* app) { HWND hWnd = NULL; HGLRC hGLRC = NULL; boolean ok = true; // Create the window. hWnd = CreateWindowEx(WS_EX_APPWINDOW, MAINWCLASS, "dummy", (WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS), CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, app->hInstance, NULL); if(hWnd) { // Initialize. PIXELFORMATDESCRIPTOR pfd; int pixForm = 0; HDC hDC = NULL; // Setup the pixel format descriptor. ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.iPixelType = PFD_TYPE_RGBA; pfd.iLayerType = PFD_MAIN_PLANE; #ifndef DRMESA pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.cColorBits = 32; pfd.cDepthBits = 16; #else /* Double Buffer, no alpha */ pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_FORMAT | PFD_DOUBLEBUFFER | PFD_SWAP_COPY; pfd.cColorBits = 24; pfd.cRedBits = 8; pfd.cGreenBits = 8; pfd.cGreenShift = 8; pfd.cBlueBits = 8; pfd.cBlueShift = 16; pfd.cDepthBits = 16; pfd.cStencilBits = 8; #endif if(ok) { // Acquire a device context handle. hDC = GetDC(hWnd); if(!hDC) { Sys_CriticalMessage("DD_CreateWindow: Failed acquiring device context handle."); hDC = NULL; ok = false; } } if(ok) { // Request a matching (or similar) pixel format. pixForm = ChoosePixelFormat(hDC, &pfd); if(!pixForm) { Sys_CriticalMessage("DD_CreateWindow: Choosing of pixel format failed."); pixForm = -1; ok = false; } } if(ok) { // Make sure that the driver is hardware-accelerated. DescribePixelFormat(hDC, pixForm, sizeof(pfd), &pfd); if((pfd.dwFlags & PFD_GENERIC_FORMAT) && !ArgCheck("-allowsoftware")) { Sys_CriticalMessage("DD_CreateWindow: GL driver not accelerated!\n" "Use the -allowsoftware option to bypass this."); ok = false; } } if(ok) { // Set the pixel format for the device context. Can only be done once // (unless we release the context and acquire another). if(!SetPixelFormat(hDC, pixForm, &pfd)) { Sys_CriticalMessage("DD_CreateWindow: Warning, setting of pixel " "format failed."); } } // Create the OpenGL rendering context. if(ok) { if(!(hGLRC = wglCreateContext(hDC))) { Sys_CriticalMessage("createContext: Creation of rendering context " "failed."); ok = false; } // Make the context current. else if(!wglMakeCurrent(hDC, hGLRC)) { Sys_CriticalMessage("createContext: Couldn't make the rendering " "context current."); ok = false; } } if(ok) { PROC getExtString = wglGetProcAddress("wglGetExtensionsStringARB"); const GLubyte* extensions = ((const GLubyte*(__stdcall*)(HDC))getExtString)(hDC); if(Sys_QueryGLExtension("WGL_ARB_multisample", extensions)) { GETPROC(wglChoosePixelFormatARB); if(wglChoosePixelFormatARB) testMultisampling(hDC); } } // We've now finished with the device context. if(hDC) ReleaseDC(hWnd, hDC); } // Delete the window's rendering context if one has been acquired. if(hGLRC) { wglMakeCurrent(NULL, NULL); wglDeleteContext(hGLRC); } // Destroy the window and release the handle. if(hWnd) DestroyWindow(hWnd); } #endif boolean Sys_PreInitGL(void) { if(isDedicated) return true; if(initedGL) return true; // Already inited. memset(&GL_state, 0, sizeof(GL_state)); memset(&GL_state_ext, 0, sizeof(GL_state_ext)); memset(&GL_state_texture, 0, sizeof(GL_state_texture)); #ifdef WIN32 // We want to be able to use multisampling if available so lets create a // dummy window and see what pixel formats we have. createDummyWindow(&app); #endif GL_state_texture.dumpTextures = (ArgCheck("-dumptextures")? true : false); if(GL_state_texture.dumpTextures) Con_Message(" Dumping textures (mipmap level zero).\n"); GL_state.forceFinishBeforeSwap = (ArgExists("-glfinish")? true : false); if(GL_state.forceFinishBeforeSwap) Con_Message(" glFinish() forced before swapping buffers.\n"); initedGL = true; return true; } /** * Initializes OpenGL. */ boolean Sys_InitGL(void) { if(isDedicated) return true; if(!initedGL) return false; if(firstTimeInit) { checkExtensions(); printGLUInfo(); printDGLConfiguration(); firstTimeInit = false; } return true; } void Sys_ShutdownGL(void) { if(!initedGL) return; initedGL = false; } void Sys_InitGLState(void) { GLfloat fogcol[4] = { .54f, .54f, .54f, 1 }; GL_state.nearClip = 5; GL_state.farClip = 8000; polyCounter = 0; GL_state_texture.usePalTex = false; GL_state_texture.dumpTextures = false; GL_state_texture.useCompr = false; // Here we configure the OpenGL state and set projection matrix. glFrontFace(GL_CW); glDisable(GL_CULL_FACE); glCullFace(GL_BACK); glDisable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); #ifndef DRMESA glEnable(GL_TEXTURE_2D); #else glDisable(GL_TEXTURE_2D); #endif // The projection matrix. glMatrixMode(GL_PROJECTION); glLoadIdentity(); // Initialize the modelview matrix. glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Also clear the texture matrix. glMatrixMode(GL_TEXTURE); glLoadIdentity(); #if DRMESA glDisable(GL_DITHER); glDisable(GL_LIGHTING); glDisable(GL_LINE_SMOOTH); glDisable(GL_POINT_SMOOTH); glDisable(GL_POLYGON_SMOOTH); glShadeModel(GL_FLAT); #else // Setup for antialiased lines/points. glEnable(GL_LINE_SMOOTH); glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); GL_state.currentLineWidth = 1.5f; glLineWidth(GL_state.currentLineWidth); glEnable(GL_POINT_SMOOTH); glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); GL_state.currentPointSize = 1.5f; glPointSize(GL_state.currentPointSize); glShadeModel(GL_SMOOTH); #endif // Alpha blending is a go! glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GREATER, 0); // Default state for the white fog is off. GL_state.useFog = 0; glDisable(GL_FOG); glFogi(GL_FOG_MODE, GL_LINEAR); glFogi(GL_FOG_END, 2100); // This should be tweaked a bit. glFogfv(GL_FOG_COLOR, fogcol); #ifdef WIN32 // Default state for vsync is on. GL_state.useVSync = true; if(wglSwapIntervalEXT != NULL) { wglSwapIntervalEXT(1); } #else GL_state.useVSync = false; #endif #if DRMESA glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); #else glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); #endif // Prefer good quality in texture compression. glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); // Clear the buffers. glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } /** * @return Non-zero iff the extension string is found. This * function is based on the method used by David Blythe * and Tom McReynolds in the book "Advanced Graphics * Programming Using OpenGL" ISBN: 1-55860-659-9. */ boolean Sys_QueryGLExtension(const char* name, const GLubyte* extensions) { const GLubyte *start; GLubyte *c, *terminator; // Extension names should not have spaces. c = (GLubyte *) strchr(name, ' '); if(c || *name == '\0') return false; if(!extensions) return false; // It takes a bit of care to be fool-proof about parsing the // OpenGL extensions string. Don't be fooled by sub-strings, etc. start = extensions; for(;;) { c = (GLubyte *) strstr((const char *) start, name); if(!c) break; terminator = c + strlen(name); if(c == start || *(c - 1) == ' ') if(*terminator == ' ' || *terminator == '\0') { return true; } start = terminator; } return false; } static int query(const char *ext, int *var) { int result = 0; if(ext) { #if WIN32 // Preference the wgl-specific extensions. if(wglGetExtString) { const GLubyte* extensions = ((const GLubyte*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC()); result = (Sys_QueryGLExtension(ext, extensions)? 1 : 0); } #endif if(!result) result = (Sys_QueryGLExtension(ext, glGetString(GL_EXTENSIONS))? 1 : 0); if(var) *var = result; } return result; } #ifdef WIN32 void Sys_InitWGLExtensions(void) { wglGetExtString = wglGetProcAddress("wglGetExtensionsStringARB"); if(query("WGL_EXT_swap_control", &GL_state_ext.wglSwapIntervalEXT)) { GETPROC(wglSwapIntervalEXT); } if(query("WGL_ARB_multisample", NULL)) { GETPROC(wglChoosePixelFormatARB); if(wglChoosePixelFormatARB) { GL_state_ext.wglMultisampleARB = 1; } } } #endif /** * Pre: A rendering context must be aquired and made current before this is * called. */ void Sys_InitGLExtensions(void) { GLint iVal; if(query("GL_EXT_compiled_vertex_array", &GL_state_ext.lockArray)) { #ifdef WIN32 GETPROC(glLockArraysEXT); GETPROC(glUnlockArraysEXT); #endif } query("GL_EXT_paletted_texture", &GL_state.palExtAvailable); query("GL_EXT_texture_filter_anisotropic", &GL_state_ext.aniso); if(ArgExists("-texnonpow2")) query("GL_ARB_texture_non_power_of_two", &GL_state.textureNonPow2); // EXT_blend_subtract if(query("GL_EXT_blend_subtract", &GL_state_ext.blendSub)) { #ifdef WIN32 GETPROC(glBlendEquationEXT); #endif } // ARB_texture_env_combine if(!query("GL_ARB_texture_env_combine", &GL_state_ext.texEnvComb)) { // Try the older EXT_texture_env_combine (identical to ARB). query("GL_EXT_texture_env_combine", &GL_state_ext.texEnvComb); } // NV_texture_env_combine4 query("GL_NV_texture_env_combine4", &GL_state_ext.nvTexEnvComb); // ATI_texture_env_combine3 query("GL_ATI_texture_env_combine3", &GL_state_ext.atiTexEnvComb); // Texture compression. query("GL_EXT_texture_compression_s3tc", &GL_state_ext.s3TC); // On by default if we have it. glGetError(); glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &iVal); if(iVal && glGetError() == GL_NO_ERROR) GL_state_texture.useCompr = true; if(ArgExists("-notexcomp")) GL_state_texture.useCompr = false; #ifdef USE_MULTITEXTURE // ARB_multitexture if(query("GL_ARB_multitexture", &GL_state_ext.multiTex)) { # ifdef WIN32 // Get the function pointers. GETPROC(glClientActiveTextureARB); GETPROC(glActiveTextureARB); GETPROC(glMultiTexCoord2fARB); GETPROC(glMultiTexCoord2fvARB); # endif } #endif // Automatic mipmap generation. if(!ArgExists("-nosgm") && query("GL_SGIS_generate_mipmap", &GL_state_ext.genMip)) { // Use nice quality, please. glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); } } /** * Show the list of GL extensions. */ static void printExtensions(const GLubyte* extensions) { char *token, *extbuf; extbuf = M_Malloc(strlen((const char*) extensions) + 1); strcpy(extbuf, (const char *) extensions); token = strtok(extbuf, " "); while(token) { Con_Message(" "); // Indent. if(verbose) { // Show full names. Con_Message("%s\n", token); } else { // Two on one line, clamp to 30 characters. Con_Message("%-30.30s", token); token = strtok(NULL, " "); if(token) Con_Message(" %-30.30s", token); Con_Message("\n"); } token = strtok(NULL, " "); } M_Free(extbuf); } void Sys_PrintGLExtensions(void) { Con_Message(" Extensions:\n"); printExtensions(glGetString(GL_EXTENSIONS)); #if WIN32 // List the WGL extensions too. if(wglGetExtString) { Con_Message(" Extensions (WGL):\n"); printExtensions( ((const GLubyte*(__stdcall*)(HDC))wglGetExtString)(wglGetCurrentDC())); } #endif } void Sys_CheckGLError(void) { #ifdef _DEBUG GLenum error; if((error = glGetError()) != GL_NO_ERROR) Con_Error("OpenGL error: %i\n", error); #endif } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/bsp_map.c0000644000175000017500000003612311357170241022522 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_map.c: */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_bsp.h" #include "de_misc.h" #include "de_play.h" #include "de_edit.h" #include "de_refresh.h" #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static void hardenSideSegList(gamemap_t* map, sidedef_t* side, seg_t* seg, hedge_t* hEdge) { uint count; hedge_t* first, *other; if(!side) return; // Have we already processed this side? if(side->segs) return; // Find the first seg. first = hEdge; while(first->prevOnSide) first = first->prevOnSide; // Count the segs for this side. count = 0; other = first; while(other) { other = other->nextOnSide; count++; } // Allocate the final side seg table. side->segCount = count; side->segs = Z_Malloc(sizeof(seg_t*) * (side->segCount + 1), PU_MAPSTATIC, 0); count = 0; other = first; while(other) { side->segs[count++] = &map->segs[other->index]; other = other->nextOnSide; } side->segs[count] = NULL; // Terminate. } static int C_DECL hEdgeCompare(const void* p1, const void* p2) { const hedge_t* a = ((const hedge_t**) p1)[0]; const hedge_t* b = ((const hedge_t**) p2)[0]; if(a->index == b->index) return 0; if(a->index < b->index) return -1; return 1; } typedef struct { size_t curIdx; hedge_t*** indexPtr; boolean write; } hedgecollectorparams_t; static boolean hEdgeCollector(binarytree_t* tree, void* data) { if(BinaryTree_IsLeaf(tree)) { hedgecollectorparams_t* params = (hedgecollectorparams_t*) data; bspleafdata_t* leaf = (bspleafdata_t*) BinaryTree_GetData(tree); hedge_t* hEdge; for(hEdge = leaf->hEdges; hEdge; hEdge = hEdge->next) { if(params->indexPtr) { // Write mode. (*params->indexPtr)[params->curIdx++] = hEdge; } else { // Count mode. if(hEdge->index == -1) Con_Error("HEdge %p never reached a subsector!", hEdge); params->curIdx++; } } } return true; // Continue traversal. } static void buildSegsFromHEdges(gamemap_t* dest, binarytree_t* rootNode) { uint i; hedge_t** index; hedgecollectorparams_t params; // // First we need to build a sorted index of the used hedges. // // Pass 1: Count the number of used hedges. params.curIdx = 0; params.indexPtr = NULL; BinaryTree_InOrder(rootNode, hEdgeCollector, ¶ms); if(!(params.curIdx > 0)) Con_Error("buildSegsFromHEdges: No halfedges?"); // Allocate the sort buffer. index = M_Malloc(sizeof(hedge_t*) * params.curIdx); // Pass 2: Collect ptrs the hedges and insert into the index. params.curIdx = 0; params.indexPtr = &index; BinaryTree_InOrder(rootNode, hEdgeCollector, ¶ms); // Sort the half-edges into ascending index order. qsort(index, params.curIdx, sizeof(hedge_t*), hEdgeCompare); dest->numSegs = (uint) params.curIdx; dest->segs = Z_Calloc(dest->numSegs * sizeof(seg_t), PU_MAPSTATIC, 0); for(i = 0; i < dest->numSegs; ++i) { seg_t* seg = &dest->segs[i]; hedge_t* hEdge = index[i]; seg->header.type = DMU_SEG; seg->SG_v1 = &dest->vertexes[hEdge->v[0]->buildData.index - 1]; seg->SG_v2 = &dest->vertexes[hEdge->v[1]->buildData.index - 1]; seg->side = hEdge->side; if(hEdge->lineDef) seg->lineDef = &dest->lineDefs[hEdge->lineDef->buildData.index - 1]; if(hEdge->twin) seg->backSeg = &dest->segs[hEdge->twin->index]; seg->flags = 0; if(seg->lineDef) { linedef_t* ldef = seg->lineDef; vertex_t* vtx = seg->lineDef->L_v(seg->side); if(ldef->L_side(seg->side)) seg->SG_frontsector = ldef->L_side(seg->side)->sector; if(ldef->L_frontside && ldef->L_backside) { seg->SG_backsector = ldef->L_side(seg->side ^ 1)->sector; } else { seg->SG_backsector = 0; } seg->offset = P_AccurateDistance(seg->SG_v1pos[VX] - vtx->V_pos[VX], seg->SG_v1pos[VY] - vtx->V_pos[VY]); } else { seg->lineDef = NULL; seg->SG_frontsector = NULL; seg->SG_backsector = NULL; } if(seg->lineDef) hardenSideSegList(dest, SEG_SIDEDEF(seg), seg, hEdge); seg->angle = bamsAtan2((int) (seg->SG_v2pos[VY] - seg->SG_v1pos[VY]), (int) (seg->SG_v2pos[VX] - seg->SG_v1pos[VX])) << FRACBITS; // Calculate the length of the segment. We need this for // the texture coordinates. -jk seg->length = P_AccurateDistance(seg->SG_v2pos[VX] - seg->SG_v1pos[VX], seg->SG_v2pos[VY] - seg->SG_v1pos[VY]); if(seg->length == 0) seg->length = 0.01f; // Hmm... // Calculate the surface normals // Front first if(seg->lineDef && SEG_SIDEDEF(seg)) { sidedef_t* side = SEG_SIDEDEF(seg); surface_t* surface = &side->SW_topsurface; surface->normal[VY] = (seg->SG_v1pos[VX] - seg->SG_v2pos[VX]) / seg->length; surface->normal[VX] = (seg->SG_v2pos[VY] - seg->SG_v1pos[VY]) / seg->length; surface->normal[VZ] = 0; // All surfaces of a sidedef have the same normal. memcpy(side->SW_middlenormal, surface->normal, sizeof(surface->normal)); memcpy(side->SW_bottomnormal, surface->normal, sizeof(surface->normal)); } } // Free temporary storage M_Free(index); } static void hardenSSecSegList(gamemap_t* dest, subsector_t* ssec, hedge_t* list, size_t segCount) { size_t i; hedge_t* cur; seg_t** segs; segs = Z_Malloc(sizeof(seg_t*) * (segCount + 1), PU_MAPSTATIC, 0); for(cur = list, i = 0; cur; cur = cur->next, ++i) segs[i] = &dest->segs[cur->index]; segs[segCount] = NULL; // Terminate. if(i != segCount) Con_Error("hardenSSecSegList: Miscounted?"); ssec->segs = segs; } static void hardenLeaf(gamemap_t* map, subsector_t* dest, const bspleafdata_t* src) { seg_t** segp; boolean found; size_t hEdgeCount; hedge_t* hEdge; hEdge = src->hEdges; hEdgeCount = 0; do { hEdgeCount++; } while((hEdge = hEdge->next) != NULL); dest->header.type = DMU_SUBSECTOR; dest->segCount = (uint) hEdgeCount; dest->shadows = NULL; dest->vertices = NULL; hardenSSecSegList(map, dest, src->hEdges, hEdgeCount); // Determine which sector this subsector belongs to. segp = dest->segs; found = false; while(*segp) { seg_t* seg = *segp; if(!found && seg->lineDef && SEG_SIDEDEF(seg)) { sidedef_t* side = SEG_SIDEDEF(seg); dest->sector = side->sector; found = true; } seg->subsector = dest; *segp++; } if(!dest->sector) { Con_Message("hardenLeaf: Warning orphan subsector %p.\n", dest); } } typedef struct { gamemap_t* dest; uint ssecCurIndex; uint nodeCurIndex; } hardenbspparams_t; static boolean C_DECL hardenNode(binarytree_t* tree, void* data) { binarytree_t* right, *left; bspnodedata_t* nodeData; hardenbspparams_t* params; node_t* node; if(BinaryTree_IsLeaf(tree)) return true; // Continue iteration. nodeData = BinaryTree_GetData(tree); params = (hardenbspparams_t*) data; node = ¶ms->dest->nodes[nodeData->index = params->nodeCurIndex++]; node->header.type = DMU_NODE; node->partition.x = nodeData->partition.x; node->partition.y = nodeData->partition.y; node->partition.dX = nodeData->partition.dX; node->partition.dY = nodeData->partition.dY; node->bBox[RIGHT][BOXTOP] = nodeData->bBox[RIGHT][BOXTOP]; node->bBox[RIGHT][BOXBOTTOM] = nodeData->bBox[RIGHT][BOXBOTTOM]; node->bBox[RIGHT][BOXLEFT] = nodeData->bBox[RIGHT][BOXLEFT]; node->bBox[RIGHT][BOXRIGHT] = nodeData->bBox[RIGHT][BOXRIGHT]; node->bBox[LEFT][BOXTOP] = nodeData->bBox[LEFT][BOXTOP]; node->bBox[LEFT][BOXBOTTOM] = nodeData->bBox[LEFT][BOXBOTTOM]; node->bBox[LEFT][BOXLEFT] = nodeData->bBox[LEFT][BOXLEFT]; node->bBox[LEFT][BOXRIGHT] = nodeData->bBox[LEFT][BOXRIGHT]; right = BinaryTree_GetChild(tree, RIGHT); if(right) { if(BinaryTree_IsLeaf(right)) { bspleafdata_t* leaf = (bspleafdata_t*) BinaryTree_GetData(right); uint idx = params->ssecCurIndex++; node->children[RIGHT] = idx | NF_SUBSECTOR; hardenLeaf(params->dest, ¶ms->dest->ssectors[idx], leaf); } else { bspnodedata_t* data = (bspnodedata_t*) BinaryTree_GetData(right); node->children[RIGHT] = data->index; } } left = BinaryTree_GetChild(tree, LEFT); if(left) { if(BinaryTree_IsLeaf(left)) { bspleafdata_t* leaf = (bspleafdata_t*) BinaryTree_GetData(left); uint idx = params->ssecCurIndex++; node->children[LEFT] = idx | NF_SUBSECTOR; hardenLeaf(params->dest, ¶ms->dest->ssectors[idx], leaf); } else { bspnodedata_t* data = (bspnodedata_t*) BinaryTree_GetData(left); node->children[LEFT] = data->index; } } return true; // Continue iteration. } static boolean C_DECL countNode(binarytree_t* tree, void* data) { if(!BinaryTree_IsLeaf(tree)) (*((uint*) data))++; return true; // Continue iteration. } static boolean C_DECL countSSec(binarytree_t* tree, void* data) { if(BinaryTree_IsLeaf(tree)) (*((uint*) data))++; return true; // Continue iteration. } static void hardenBSP(gamemap_t* dest, binarytree_t* rootNode) { dest->numNodes = 0; BinaryTree_PostOrder(rootNode, countNode, &dest->numNodes); dest->nodes = Z_Calloc(dest->numNodes * sizeof(node_t), PU_MAPSTATIC, 0); dest->numSSectors = 0; BinaryTree_PostOrder(rootNode, countSSec, &dest->numSSectors); dest->ssectors = Z_Calloc(dest->numSSectors * sizeof(subsector_t), PU_MAPSTATIC, 0); if(rootNode) { hardenbspparams_t params; params.dest = dest; params.ssecCurIndex = 0; params.nodeCurIndex = 0; BinaryTree_PostOrder(rootNode, hardenNode, ¶ms); } } void BSP_InitForNodeBuild(gamemap_t* map) { uint i; for(i = 0; i < map->numLineDefs; ++i) { linedef_t* l = &map->lineDefs[i]; vertex_t* start = l->v[0]; vertex_t* end = l->v[1]; start->buildData.refCount++; end->buildData.refCount++; l->buildData.mlFlags = 0; // Check for zero-length line. if((fabs(start->buildData.pos[VX] - end->buildData.pos[VX]) < DIST_EPSILON) && (fabs(start->buildData.pos[VY] - end->buildData.pos[VY]) < DIST_EPSILON)) l->buildData.mlFlags |= MLF_ZEROLENGTH; if(l->inFlags & LF_POLYOBJ) l->buildData.mlFlags |= MLF_POLYOBJ; if(l->sideDefs[BACK] && l->sideDefs[FRONT]) { l->buildData.mlFlags |= MLF_TWOSIDED; if(l->sideDefs[BACK]->sector == l->sideDefs[FRONT]->sector) l->buildData.mlFlags |= MLF_SELFREF; } } } static void hardenVertexes(gamemap_t* dest, vertex_t*** vertexes, uint* numVertexes) { uint i; dest->numVertexes = *numVertexes; dest->vertexes = Z_Calloc(dest->numVertexes * sizeof(vertex_t), PU_MAPSTATIC, 0); for(i = 0; i < dest->numVertexes; ++i) { vertex_t* destV = &dest->vertexes[i]; vertex_t* srcV = (*vertexes)[i]; destV->header.type = DMU_VERTEX; destV->numLineOwners = srcV->numLineOwners; destV->lineOwners = srcV->lineOwners; //// \fixme Add some rounding. destV->V_pos[VX] = (float) srcV->buildData.pos[VX]; destV->V_pos[VY] = (float) srcV->buildData.pos[VY]; } } static void updateVertexLinks(gamemap_t* dest) { uint i; for(i = 0; i < dest->numLineDefs; ++i) { linedef_t* line = &dest->lineDefs[i]; line->L_v1 = &dest->vertexes[line->L_v1->buildData.index - 1]; line->L_v2 = &dest->vertexes[line->L_v2->buildData.index - 1]; } } void SaveMap(gamemap_t* dest, void* rootNode, vertex_t*** vertexes, uint* numVertexes) { uint startTime = Sys_GetRealTime(); binarytree_t* rn = (binarytree_t*) rootNode; hardenVertexes(dest, vertexes, numVertexes); updateVertexLinks(dest); buildSegsFromHEdges(dest, rn); hardenBSP(dest, rn); // How much time did we spend? VERBOSE(Con_Message ("SaveMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sv_pool.c0000644000175000017500000024755511357170242022600 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_pool.c: Delta Pools * * Delta Pools use PU_MAP, which means all the memory allocated for them * is deallocated when the map changes. Sv_InitPools() is called in * R_SetupMap() to clear out all the old data. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_refresh.h" #include "de_play.h" #include "s_main.h" #include "sys_timer.h" // MACROS ------------------------------------------------------------------ #define DEFAULT_DELTA_BASE_SCORE 10000 #define REG_MOBJ_HASH_SIZE 1024 #define REG_MOBJ_HASH_FUNCTION_MASK 0x3ff // Maximum difference in plane height where the absolute height doesn't // need to be sent. #define PLANE_SKIP_LIMIT (40) // TYPES ------------------------------------------------------------------- typedef struct reg_mobj_s { // Links to next and prev mobj in the register hash. struct reg_mobj_s* next, *prev; // The tic when the mobj state was last sent. int lastTimeStateSent; dt_mobj_t mo; // The state of the mobj. } reg_mobj_t; typedef struct mobjhash_s { reg_mobj_t* first, *last; } mobjhash_t; /** * One cregister_t holds the state of the entire world. */ typedef struct cregister_s { // The time the register was last updated. int gametic; // True if this register contains a read-only copy of the initial state // of the world. boolean isInitial; // The mobjs are stored in a hash for efficiency (ID is the key). mobjhash_t mobjs[REG_MOBJ_HASH_SIZE]; dt_player_t ddPlayers[DDMAXPLAYERS]; dt_sector_t* sectors; dt_side_t* sideDefs; dt_poly_t* polyObjs; } cregister_t; /** * Each entity (mobj, sector, side, etc.) has an origin the world. */ typedef struct origin_s { float pos[2]; } origin_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void Sv_RegisterWorld(cregister_t* reg, boolean isInitial); void Sv_NewDelta(void* deltaPtr, deltatype_t type, uint id); boolean Sv_IsVoidDelta(const void* delta); void Sv_PoolQueueClear(pool_t* pool); void Sv_GenerateNewDeltas(cregister_t* reg, int clientNumber, boolean doUpdate); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The register contains the previous state of the world. cregister_t worldRegister; // The initial register is used when generating deltas for a new client. cregister_t initialRegister; // Each client has its own pool for deltas. pool_t pools[DDMAXPLAYERS]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static float deltaBaseScores[NUM_DELTA_TYPES]; // Keep this zeroed out. Used if the register doesn't have data for // the mobj being compared. static dt_mobj_t dummyZeroMobj; // Origins of stuff. Calculated at the beginning of a map. static origin_t* sectorOrigins, *sideOrigins; // Pointer to the owner line for each side. static linedef_t** sideOwners; // CODE -------------------------------------------------------------------- /** * Called once for each map, from R_SetupMap(). Initialize the world * register and drain all pools. */ void Sv_InitPools(void) { uint i; sector_t* sec; uint startTime; // Clients don't register anything. if(isClient) return; startTime = Sys_GetRealTime(); // Set base priority scores for all the delta types. for(i = 0; i < NUM_DELTA_TYPES; ++i) { deltaBaseScores[i] = DEFAULT_DELTA_BASE_SCORE; } // Priorities for all deltas that will be sent out by the server. // No priorities need to be declared for obsolete delta types. deltaBaseScores[DT_MOBJ] = 1000; deltaBaseScores[DT_PLAYER] = 1000; deltaBaseScores[DT_SECTOR] = 2000; deltaBaseScores[DT_SIDE] = 800; deltaBaseScores[DT_POLY] = 2000; deltaBaseScores[DT_LUMP] = 0; deltaBaseScores[DT_SOUND] = 2000; deltaBaseScores[DT_MOBJ_SOUND] = 3000; deltaBaseScores[DT_SECTOR_SOUND] = 5000; deltaBaseScores[DT_POLY_SOUND] = 5000; // Since the map has changed, PU_MAP memory has been freed. // Reset all pools (set numbers are kept, though). for(i = 0; i < DDMAXPLAYERS; ++i) { pools[i].owner = i; pools[i].resendDealer = 1; memset(pools[i].hash, 0, sizeof(pools[i].hash)); memset(pools[i].misHash, 0, sizeof(pools[i].misHash)); pools[i].queueSize = 0; pools[i].allocatedSize = 0; pools[i].queue = NULL; // This will be set to false when a frame is sent. pools[i].isFirst = true; } // Find the owners of all sides. sideOwners = Z_Malloc(sizeof(linedef_t *) * numSideDefs, PU_MAP, 0); for(i = 0; i < numSideDefs; ++i) { sideOwners[i] = R_GetLineForSide(i); } // Origins of sectors. sectorOrigins = Z_Malloc(sizeof(origin_t) * numSectors, PU_MAP, 0); for(i = 0; i < numSectors; ++i) { sec = SECTOR_PTR(i); sectorOrigins[i].pos[VX] = (sec->bBox[BOXRIGHT] + sec->bBox[BOXLEFT]) / 2; sectorOrigins[i].pos[VY] = (sec->bBox[BOXBOTTOM] + sec->bBox[BOXTOP]) / 2; } // Origins of sides. sideOrigins = Z_Malloc(sizeof(origin_t) * numSideDefs, PU_MAP, 0); for(i = 0; i < numSideDefs; ++i) { vertex_t* vtx; // The side must be owned by a line. if(sideOwners[i] == NULL) continue; vtx = sideOwners[i]->L_v1; sideOrigins[i].pos[VX] = vtx->V_pos[VX] + sideOwners[i]->dX / 2; sideOrigins[i].pos[VY] = vtx->V_pos[VY] + sideOwners[i]->dY / 2; } // Store the current state of the world into both the registers. Sv_RegisterWorld(&worldRegister, false); Sv_RegisterWorld(&initialRegister, true); #ifdef _DEBUG // How much time did we spend? Con_Message("Sv_InitPools: World registered, done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f); #endif } /** * Called during server shutdown (when shutting down the engine). */ void Sv_ShutdownPools(void) { } /** * Called when a client joins the game. */ void Sv_InitPoolForClient(uint clientNumber) { // Free everything that might exist in the pool. Sv_DrainPool(clientNumber); // Generate deltas by comparing against the initial state of the world. // The initial register remains unmodified. Sv_GenerateNewDeltas(&initialRegister, clientNumber, false); // No frames have yet been sent for this client. // The first frame is processed a bit more thoroughly than the others // (e.g. *all* sides are compared, not just a portion). pools[clientNumber].isFirst = true; } /** * @return Pointer to the console's delta pool. */ pool_t* Sv_GetPool(uint consoleNumber) { return &pools[consoleNumber]; } /** * The hash function for the register mobj hash. */ uint Sv_RegisterHashFunction(thid_t id) { return (uint) id & REG_MOBJ_HASH_FUNCTION_MASK; } /** * @return Pointer to the register-mobj, if it already exists. */ reg_mobj_t* Sv_RegisterFindMobj(cregister_t* reg, thid_t id) { mobjhash_t* hash = ®->mobjs[Sv_RegisterHashFunction(id)]; reg_mobj_t* iter; // See if there already is a register-mobj for this id. for(iter = hash->first; iter; iter = iter->next) { // Is this the one? if(iter->mo.thinker.id == id) { return iter; } } return NULL; } /** * Adds a new reg_mobj_t to the register's mobj hash. */ reg_mobj_t* Sv_RegisterAddMobj(cregister_t* reg, thid_t id) { mobjhash_t* hash = ®->mobjs[Sv_RegisterHashFunction(id)]; reg_mobj_t* newRegMo; // Try to find an existing register-mobj. if((newRegMo = Sv_RegisterFindMobj(reg, id)) != NULL) { return newRegMo; } // Allocate the new register-mobj. newRegMo = Z_Calloc(sizeof(reg_mobj_t), PU_MAP, 0); // Link it to the end of the hash list. if(hash->last) { hash->last->next = newRegMo; newRegMo->prev = hash->last; } hash->last = newRegMo; if(!hash->first) { hash->first = newRegMo; } return newRegMo; } /** * Removes a reg_mobj_t from the register's mobj hash. */ void Sv_RegisterRemoveMobj(cregister_t* reg, reg_mobj_t* regMo) { mobjhash_t* hash = ®->mobjs[Sv_RegisterHashFunction(regMo->mo.thinker.id)]; // Update the first and last links. if(hash->last == regMo) { hash->last = regMo->prev; } if(hash->first == regMo) { hash->first = regMo->next; } // Link out of the list. if(regMo->next) { regMo->next->prev = regMo->prev; } if(regMo->prev) { regMo->prev->next = regMo->next; } // Destroy the register-mobj. Z_Free(regMo); } /** * @return If the mobj is on the floor; @c MININT. * If the mobj is touching the ceiling; @c MAXINT. * Otherwise returns the Z coordinate. */ float Sv_GetMaxedMobjZ(const mobj_t* mo) { if(mo->pos[VZ] == mo->floorZ) { return DDMINFLOAT; } if(mo->pos[VZ] + mo->height == mo->ceilingZ) { return DDMAXFLOAT; } return mo->pos[VZ]; } /** * Store the state of the mobj into the register-mobj. * Called at register init and after each delta generation cycle. */ void Sv_RegisterMobj(dt_mobj_t* reg, const mobj_t* mo) { // (dt_mobj_t <=> mobj_t) // Just copy the data we need. reg->thinker.id = mo->thinker.id; reg->dPlayer = mo->dPlayer; reg->subsector = mo->subsector; reg->pos[VX] = mo->pos[VX]; reg->pos[VY] = mo->pos[VY]; reg->pos[VZ] = Sv_GetMaxedMobjZ(mo); reg->floorZ = mo->floorZ; reg->ceilingZ = mo->ceilingZ; reg->mom[MX] = mo->mom[MX]; reg->mom[MY] = mo->mom[MY]; reg->mom[MZ] = mo->mom[MZ]; reg->angle = mo->angle; reg->selector = mo->selector; reg->state = mo->state; reg->radius = mo->radius; reg->height = mo->height; reg->ddFlags = mo->ddFlags; reg->floorClip = mo->floorClip; reg->translucency = mo->translucency; reg->visTarget = mo->visTarget; } /** * Reset the data of the registered mobj to reasonable defaults. * In effect, forces a resend of the zeroed entries as deltas. */ void Sv_RegisterResetMobj(dt_mobj_t* reg) { reg->pos[VX] = 0; reg->pos[VY] = 0; reg->pos[VZ] = 0; reg->angle = 0; reg->selector = 0; reg->state = 0; reg->radius = 0; reg->height = 0; reg->ddFlags = 0; reg->floorClip = 0; reg->translucency = 0; reg->visTarget = 0; } /** * Store the state of the player into the register-player. * Called at register init and after each delta generation cycle. */ void Sv_RegisterPlayer(dt_player_t* reg, uint number) { #define FMAKERGBA(r,g,b,a) ( (byte)(0xff*r) + ((byte)(0xff*g)<<8) + ((byte)(0xff*b)<<16) + ((byte)(0xff*a)<<24) ) player_t* plr = &ddPlayers[number]; ddplayer_t* ddpl = &plr->shared; client_t* c = &clients[number]; reg->mobj = (ddpl->mo ? ddpl->mo->thinker.id : 0); reg->forwardMove = c->lastCmd->forwardMove; reg->sideMove = c->lastCmd->sideMove; reg->angle = (ddpl->mo ? ddpl->mo->angle : 0); reg->turnDelta = (ddpl->mo ? ddpl->mo->angle - ddpl->lastAngle : 0); reg->friction = ddpl->mo && (gx.MobjFriction ? gx.MobjFriction(ddpl->mo) : DEFAULT_FRICTION); reg->extraLight = ddpl->extraLight; reg->fixedColorMap = ddpl->fixedColorMap; if(ddpl->flags & DDPF_VIEW_FILTER) { reg->filter = FMAKERGBA(ddpl->filterColor[CR], ddpl->filterColor[CG], ddpl->filterColor[CB], ddpl->filterColor[CA]); } else { reg->filter = 0; } reg->clYaw = (ddpl->mo ? ddpl->mo->angle : 0); reg->clPitch = ddpl->lookDir; memcpy(reg->psp, ddpl->pSprites, sizeof(ddpsprite_t) * 2); #undef FMAKERGBA } /** * Store the state of the sector into the register-sector. * Called at register init and after each delta generation. * * @param reg The sector register to be initialized. * @param number The world sector number to be registered. */ void Sv_RegisterSector(dt_sector_t* reg, uint number) { uint i; sector_t* sec = SECTOR_PTR(number); reg->lightLevel = sec->lightLevel; memcpy(reg->rgb, sec->rgb, sizeof(reg->rgb)); // \fixme $nplanes for(i = 0; i < 2; ++i) // number of planes in sector. { // Plane properties reg->planes[i].height = sec->planes[i]->height; reg->planes[i].target = sec->planes[i]->target; reg->planes[i].speed = sec->planes[i]->speed; reg->planes[i].glow = sec->planes[i]->glow; memcpy(reg->planes[i].glowRGB, sec->planes[i]->glowRGB, sizeof(reg->planes[i].glowRGB)); // Surface properties. memcpy(reg->planes[i].surface.rgba, sec->planes[i]->surface.rgba, sizeof(reg->planes[i].surface.rgba)); // Surface material. reg->planes[i].surface.material = sec->SP_planematerial(i); } } /** * Store the state of the side into the register-side. * Called at register init and after each delta generation. */ void Sv_RegisterSide(dt_side_t* reg, uint number) { sidedef_t* side = SIDE_PTR(number); linedef_t* line = sideOwners[number]; reg->top.material = side->SW_topmaterial; reg->middle.material = side->SW_middlematerial; reg->bottom.material = side->SW_bottommaterial; reg->lineFlags = (line ? line->flags & 0xff : 0); memcpy(reg->top.rgba, side->SW_toprgba, sizeof(reg->top.rgba)); memcpy(reg->middle.rgba, side->SW_middlergba, sizeof(reg->middle.rgba)); memcpy(reg->bottom.rgba, side->SW_bottomrgba, sizeof(reg->bottom.rgba)); reg->middle.blendMode = side->SW_middleblendmode; // only middle supports blendmode. reg->flags = side->flags & 0xff; } /** * Store the state of the polyobj into the register-poly. * Called at register init and after each delta generation. */ void Sv_RegisterPoly(dt_poly_t* reg, uint number) { polyobj_t* poly = polyObjs[number]; reg->dest.pos[VX] = poly->dest[VX]; reg->dest.pos[VY] = poly->dest[VY]; reg->speed = poly->speed; reg->destAngle = poly->destAngle; reg->angleSpeed = poly->angleSpeed; } /** * @return @c true, if the result is not void. */ boolean Sv_RegisterCompareMobj(cregister_t* reg, const mobj_t* s, mobjdelta_t* d) { int df; reg_mobj_t* regMo = NULL; const dt_mobj_t* r = &dummyZeroMobj; if((regMo = Sv_RegisterFindMobj(reg, s->thinker.id)) != NULL) { // Use the registered data. r = ®Mo->mo; df = 0; } else { // This didn't exist in the register, so it's a new mobj. df = MDFC_CREATE; } if(r->pos[VX] != s->pos[VX]) df |= MDF_POS_X; if(r->pos[VY] != s->pos[VY]) df |= MDF_POS_Y; if(r->pos[VZ] != Sv_GetMaxedMobjZ(s)) df |= MDF_POS_Z; if(r->mom[MX] != s->mom[MX]) df |= MDF_MOM_X; if(r->mom[MY] != s->mom[MY]) df |= MDF_MOM_Y; if(r->mom[MZ] != s->mom[MZ]) df |= MDF_MOM_Z; if(r->angle != s->angle) df |= MDF_ANGLE; if(r->selector != s->selector) df |= MDF_SELECTOR; if(r->translucency != s->translucency) df |= MDFC_TRANSLUCENCY; if(r->visTarget != s->visTarget) df |= MDFC_FADETARGET; // Mobj state sent periodically, if it keeps changing. if((!(s->ddFlags & DDMF_MISSILE) && regMo && Sys_GetTime() - regMo->lastTimeStateSent > (60 + s->thinker.id%35) && r->state != s->state) || !Def_SameStateSequence(r->state, s->state)) { df |= MDF_STATE; #ifdef _DEBUG VERBOSE2( if(regMo && Sys_GetTime() - regMo->lastTimeStateSent > (60 + s->thinker.id%35)) Con_Message("Sv_RegisterCompareMobj: (%i) Sending state due to time.\n", s->thinker.id) ); #endif if(regMo) regMo->lastTimeStateSent = Sys_GetTime(); } if(r->radius != s->radius) df |= MDF_RADIUS; if(r->height != s->height) df |= MDF_HEIGHT; if((r->ddFlags & DDMF_PACK_MASK) != (s->ddFlags & DDMF_PACK_MASK)) { df |= MDF_FLAGS; } if(r->floorClip != s->floorClip) df |= MDF_FLOORCLIP; if(df) { // Init the delta with current data. Sv_NewDelta(d, DT_MOBJ, s->thinker.id); Sv_RegisterMobj(&d->mo, s); } d->delta.flags = df; return !Sv_IsVoidDelta(d); } /** * @return @c true, if the result is not void. */ boolean Sv_RegisterComparePlayer(cregister_t* reg, uint number, playerdelta_t* d) { const dt_player_t* r = ®->ddPlayers[number]; dt_player_t* s = &d->player; int df = 0; // Init the delta with current data. Sv_NewDelta(d, DT_PLAYER, number); Sv_RegisterPlayer(&d->player, number); // Determine which data is different. if(r->mobj != s->mobj) df |= PDF_MOBJ; if(r->forwardMove != s->forwardMove) df |= PDF_FORWARDMOVE; if(r->sideMove != s->sideMove) df |= PDF_SIDEMOVE; /*if(r->angle != s->angle) df |= PDF_ANGLE;*/ if(r->turnDelta != s->turnDelta) df |= PDF_TURNDELTA; if(r->friction != s->friction) df |= PDF_FRICTION; if(r->extraLight != s->extraLight || r->fixedColorMap != s->fixedColorMap) { df |= PDF_EXTRALIGHT; } if(r->filter != s->filter) df |= PDF_FILTER; /* if(r->clYaw != s->clYaw) df |= PDF_CLYAW; if(r->clPitch != s->clPitch) df |= PDF_CLPITCH;*/ /* // The player sprites are a bit more complicated to check. for(i = 0; i < 2; ++i) { int off = 16 + i * 8; const ddpsprite_t *rps = r->psp + i; const ddpsprite_t *sps = s->psp + i; if(rps->statePtr != sps->statePtr) df |= PSDF_STATEPTR << off; if(rps->light != sps->light) df |= PSDF_LIGHT << off; if(rps->alpha != sps->alpha) df |= PSDF_ALPHA << off; if(rps->state != sps->state) df |= PSDF_STATE << off; if((rps->offX != sps->offX || rps->offY != sps->offY) && !i) { df |= PSDF_OFFSET << off; } } // Check for any psprite flags. if(df & 0xffff0000) df |= PDF_PSPRITES; */ d->delta.flags = df; return !Sv_IsVoidDelta(d); } /** * @return @c true, if the result is not void. */ boolean Sv_RegisterCompareSector(cregister_t* reg, uint number, sectordelta_t* d, byte doUpdate) { dt_sector_t* r = ®->sectors[number]; const sector_t* s = SECTOR_PTR(number); int df = 0; // Determine which data is different. if(s->SP_floormaterial != r->planes[PLN_FLOOR].surface.material) df |= SDF_FLOOR_MATERIAL; if(s->SP_ceilmaterial != r->planes[PLN_CEILING].surface.material) df |= SDF_CEILING_MATERIAL; if(r->lightLevel != s->lightLevel) df |= SDF_LIGHT; if(r->rgb[0] != s->rgb[0]) df |= SDF_COLOR_RED; if(r->rgb[1] != s->rgb[1]) df |= SDF_COLOR_GREEN; if(r->rgb[2] != s->rgb[2]) df |= SDF_COLOR_BLUE; if(r->planes[PLN_FLOOR].surface.rgba[0] != s->SP_floorrgb[0]) df |= SDF_FLOOR_COLOR_RED; if(r->planes[PLN_FLOOR].surface.rgba[1] != s->SP_floorrgb[1]) df |= SDF_FLOOR_COLOR_GREEN; if(r->planes[PLN_FLOOR].surface.rgba[2] != s->SP_floorrgb[2]) df |= SDF_FLOOR_COLOR_BLUE; if(r->planes[PLN_CEILING].surface.rgba[0] != s->SP_ceilrgb[0]) df |= SDF_CEIL_COLOR_RED; if(r->planes[PLN_CEILING].surface.rgba[1] != s->SP_ceilrgb[1]) df |= SDF_CEIL_COLOR_GREEN; if(r->planes[PLN_CEILING].surface.rgba[2] != s->SP_ceilrgb[2]) df |= SDF_CEIL_COLOR_BLUE; if(r->planes[PLN_FLOOR].glowRGB[0] != s->SP_floorglowrgb[0]) df |= SDF_FLOOR_GLOW_RED; if(r->planes[PLN_FLOOR].glowRGB[1] != s->SP_floorglowrgb[1]) df |= SDF_FLOOR_GLOW_GREEN; if(r->planes[PLN_FLOOR].glowRGB[2] != s->SP_floorglowrgb[2]) df |= SDF_FLOOR_GLOW_BLUE; if(r->planes[PLN_CEILING].glowRGB[0] != s->SP_ceilglowrgb[0]) df |= SDF_CEIL_GLOW_RED; if(r->planes[PLN_CEILING].glowRGB[1] != s->SP_ceilglowrgb[1]) df |= SDF_CEIL_GLOW_GREEN; if(r->planes[PLN_CEILING].glowRGB[2] != s->SP_ceilglowrgb[2]) df |= SDF_CEIL_GLOW_BLUE; if(r->planes[PLN_FLOOR].glow != s->planes[PLN_FLOOR]->glow) df |= SDF_FLOOR_GLOW; if(r->planes[PLN_CEILING].glow != s->planes[PLN_CEILING]->glow) df |= SDF_CEIL_GLOW; // The cases where an immediate change to a plane's height is needed: // 1) Plane is not moving, but the heights are different. This means // the plane's height was changed unpredictably. // 2) Plane is moving, but there is a large difference in the heights. // The clientside height should be fixed. // Should we make an immediate change in floor height? if(!r->planes[PLN_FLOOR].speed && !s->planes[PLN_FLOOR]->speed) { if(r->planes[PLN_FLOOR].height != s->planes[PLN_FLOOR]->height) df |= SDF_FLOOR_HEIGHT; } else { if(fabs(r->planes[PLN_FLOOR].height - s->planes[PLN_FLOOR]->height) > PLANE_SKIP_LIMIT) df |= SDF_FLOOR_HEIGHT; } // How about the ceiling? if(!r->planes[PLN_CEILING].speed && !s->planes[PLN_CEILING]->speed) { if(r->planes[PLN_CEILING].height != s->planes[PLN_CEILING]->height) df |= SDF_CEILING_HEIGHT; } else { if(fabs(r->planes[PLN_CEILING].height - s->planes[PLN_CEILING]->height) > PLANE_SKIP_LIMIT) df |= SDF_CEILING_HEIGHT; } // Check planes, too. if(r->planes[PLN_FLOOR].target != s->planes[PLN_FLOOR]->target) { // Target and speed are always sent together. df |= SDF_FLOOR_TARGET | SDF_FLOOR_SPEED; } if(r->planes[PLN_FLOOR].speed != s->planes[PLN_FLOOR]->speed) { // Target and speed are always sent together. df |= SDF_FLOOR_SPEED | SDF_FLOOR_TARGET; } if(r->planes[PLN_CEILING].target != s->planes[PLN_CEILING]->target) { // Target and speed are always sent together. df |= SDF_CEILING_TARGET | SDF_CEILING_SPEED; } if(r->planes[PLN_CEILING].speed != s->planes[PLN_CEILING]->speed) { // Target and speed are always sent together. df |= SDF_CEILING_SPEED | SDF_CEILING_TARGET; } // Only do a delta when something changes. if(df) { // Init the delta with current data. Sv_NewDelta(d, DT_SECTOR, number); Sv_RegisterSector(&d->sector, number); if(doUpdate) { Sv_RegisterSector(r, number); } } if(doUpdate) { // The plane heights should be tracked regardless of the // change flags. r->planes[PLN_FLOOR].height = s->planes[PLN_FLOOR]->height; r->planes[PLN_CEILING].height = s->planes[PLN_CEILING]->height; } d->delta.flags = df; return !Sv_IsVoidDelta(d); } /** * @eturn @c true, if the result is not void. */ boolean Sv_RegisterCompareSide(cregister_t* reg, uint number, sidedelta_t* d, byte doUpdate) { const sidedef_t* s = SIDE_PTR(number); const linedef_t* line = sideOwners[number]; dt_side_t* r = ®->sideDefs[number]; int df = 0; byte lineFlags = (line ? line->flags & 0xff : 0); byte sideFlags = s->flags & 0xff; if(r->top.material != s->SW_topmaterial && !(s->SW_topinflags & SUIF_MATERIAL_FIX)) { df |= SIDF_TOP_MATERIAL; if(doUpdate) r->top.material = s->SW_topmaterial; } if(r->middle.material != s->SW_middlematerial && !(s->SW_middleinflags & SUIF_MATERIAL_FIX)) { df |= SIDF_MID_MATERIAL; if(doUpdate) r->middle.material = s->SW_middlematerial; } if(r->bottom.material != s->SW_bottommaterial && !(s->SW_bottominflags & SUIF_MATERIAL_FIX)) { df |= SIDF_BOTTOM_MATERIAL; if(doUpdate) r->bottom.material = s->SW_bottommaterial; } if(r->lineFlags != lineFlags) { df |= SIDF_LINE_FLAGS; if(doUpdate) r->lineFlags = lineFlags; } if(r->top.rgba[0] != s->SW_toprgba[0]) { df |= SIDF_TOP_COLOR_RED; if(doUpdate) r->top.rgba[0] = s->SW_toprgba[0]; } if(r->top.rgba[1] != s->SW_toprgba[1]) { df |= SIDF_TOP_COLOR_GREEN; if(doUpdate) r->top.rgba[1] = s->SW_toprgba[1]; } if(r->top.rgba[2] != s->SW_toprgba[2]) { df |= SIDF_TOP_COLOR_BLUE; if(doUpdate) r->top.rgba[3] = s->SW_toprgba[3]; } if(r->middle.rgba[0] != s->SW_middlergba[0]) { df |= SIDF_MID_COLOR_RED; if(doUpdate) r->middle.rgba[0] = s->SW_middlergba[0]; } if(r->middle.rgba[1] != s->SW_middlergba[1]) { df |= SIDF_MID_COLOR_GREEN; if(doUpdate) r->middle.rgba[1] = s->SW_middlergba[1]; } if(r->middle.rgba[2] != s->SW_middlergba[2]) { df |= SIDF_MID_COLOR_BLUE; if(doUpdate) r->middle.rgba[3] = s->SW_middlergba[3]; } if(r->middle.rgba[3] != s->SW_middlergba[3]) { df |= SIDF_MID_COLOR_ALPHA; if(doUpdate) r->middle.rgba[3] = s->SW_middlergba[3]; } if(r->bottom.rgba[0] != s->SW_bottomrgba[0]) { df |= SIDF_BOTTOM_COLOR_RED; if(doUpdate) r->bottom.rgba[0] = s->SW_bottomrgba[0]; } if(r->bottom.rgba[1] != s->SW_bottomrgba[1]) { df |= SIDF_BOTTOM_COLOR_GREEN; if(doUpdate) r->bottom.rgba[1] = s->SW_bottomrgba[1]; } if(r->bottom.rgba[2] != s->SW_bottomrgba[2]) { df |= SIDF_BOTTOM_COLOR_BLUE; if(doUpdate) r->bottom.rgba[3] = s->SW_bottomrgba[3]; } if(r->middle.blendMode != s->SW_middleblendmode) { df |= SIDF_MID_BLENDMODE; if(doUpdate) r->middle.blendMode = s->SW_middleblendmode; } if(r->flags != sideFlags) { df |= SIDF_FLAGS; if(doUpdate) r->flags = sideFlags; } // Was there any change? if(df) { // This happens quite rarely. // Init the delta with current data. Sv_NewDelta(d, DT_SIDE, number); Sv_RegisterSide(&d->side, number); } d->delta.flags = df; return !Sv_IsVoidDelta(d); } /** * @return @c true, if the result is not void. */ boolean Sv_RegisterComparePoly(cregister_t* reg, uint number, polydelta_t *d) { const dt_poly_t* r = ®->polyObjs[number]; dt_poly_t* s = &d->po; int df = 0; // Init the delta with current data. Sv_NewDelta(d, DT_POLY, number); Sv_RegisterPoly(&d->po, number); // What is different? if(r->dest.pos[VX] != s->dest.pos[VX]) df |= PODF_DEST_X; if(r->dest.pos[VY] != s->dest.pos[VY]) df |= PODF_DEST_Y; if(r->speed != s->speed) df |= PODF_SPEED; if(r->destAngle != s->destAngle) df |= PODF_DEST_ANGLE; if(r->angleSpeed != s->angleSpeed) df |= PODF_ANGSPEED; d->delta.flags = df; return !Sv_IsVoidDelta(d); } /** * @return @c true, if the mobj can be excluded from delta * processing. */ boolean Sv_IsMobjIgnored(mobj_t* mo) { return (mo->ddFlags & DDMF_LOCAL) != 0; } /** * @return @c true, if the player can be excluded from delta * processing. */ boolean Sv_IsPlayerIgnored(int plrNum) { return !ddPlayers[plrNum].shared.inGame; } /** * Initialize the register with the current state of the world. * The arrays are allocated and the data is copied, nothing else is done. * * An initial register doesn't contain any mobjs. When new clients enter, * they know nothing about any mobjs. If the mobjs were included in the * initial register, clients wouldn't receive much info from mobjs that * haven't moved since the beginning. */ void Sv_RegisterWorld(cregister_t* reg, boolean isInitial) { uint i; memset(reg, 0, sizeof(*reg)); reg->gametic = SECONDS_TO_TICKS(gameTime); // Is this the initial state? reg->isInitial = isInitial; // Init sectors. reg->sectors = Z_Calloc(sizeof(dt_sector_t) * numSectors, PU_MAP, 0); for(i = 0; i < numSectors; ++i) { Sv_RegisterSector(®->sectors[i], i); } // Init sides. reg->sideDefs = Z_Calloc(sizeof(dt_side_t) * numSideDefs, PU_MAP, 0); for(i = 0; i < numSideDefs; ++i) { Sv_RegisterSide(®->sideDefs[i], i); } // Init polyobjs. reg->polyObjs = (numPolyObjs ? Z_Calloc(sizeof(dt_poly_t) * numPolyObjs, PU_MAP, 0) : NULL); for(i = 0; i < numPolyObjs; ++i) { Sv_RegisterPoly(®->polyObjs[i], i); } } /** * Update the pool owner's info. */ void Sv_UpdateOwnerInfo(pool_t* pool) { player_t* plr = &ddPlayers[pool->owner]; ownerinfo_t* info = &pool->ownerInfo; memset(info, 0, sizeof(*info)); // Pointer to the owner's pool. info->pool = pool; if(plr->shared.mo) { mobj_t* mo = plr->shared.mo; info->pos[VX] = mo->pos[VX]; info->pos[VY] = mo->pos[VY]; info->pos[VZ] = mo->pos[VZ]; info->angle = mo->angle; info->speed = P_ApproxDistance(mo->mom[MX], mo->mom[MY]); } // The acknowledgement threshold is a multiple of the average // ack time of the client. If an unacked delta is not acked within // the threshold, it'll be re-included in the ratings. info->ackThreshold = Net_GetAckThreshold(pool->owner); } /** * @return A timestamp that is used to track how old deltas are. */ uint Sv_GetTimeStamp(void) { return Sys_GetRealTime(); } /** * Initialize a new delta. */ void Sv_NewDelta(void* deltaPtr, deltatype_t type, uint id) { delta_t* delta = deltaPtr; // NOTE: This only clears the common delta_t part, not the extra data. memset(delta, 0, sizeof(*delta)); delta->id = id; delta->type = type; delta->state = DELTA_NEW; delta->timeStamp = Sv_GetTimeStamp(); } /** * @return @c true, if the delta contains no information. */ boolean Sv_IsVoidDelta(const void* delta) { return ((const delta_t *) delta)->flags == 0; } /** * @return @c true, if the delta is a Sound delta. */ boolean Sv_IsSoundDelta(const void* delta) { const delta_t* d = delta; return (d->type == DT_SOUND || d->type == DT_MOBJ_SOUND || d->type == DT_SECTOR_SOUND || d->type == DT_POLY_SOUND); } /** * @return @c true, if the delta is a Start Sound delta. */ boolean Sv_IsStartSoundDelta(const void* delta) { const sounddelta_t* d = delta; return Sv_IsSoundDelta(delta) && ((d->delta.flags & SNDDF_VOLUME) && d->volume > 0); } /** * @return @c true, if the delta is Stop Sound delta. */ boolean Sv_IsStopSoundDelta(const void* delta) { const sounddelta_t* d = delta; return Sv_IsSoundDelta(delta) && ((d->delta.flags & SNDDF_VOLUME) && d->volume <= 0); } /** * @return @c true, if the delta is a Null Mobj delta. */ boolean Sv_IsNullMobjDelta(const void *delta) { return ((const delta_t *) delta)->type == DT_MOBJ && (((const delta_t *) delta)->flags & MDFC_NULL); } /** * @return @c true, if the delta is a Create Mobj delta. */ boolean Sv_IsCreateMobjDelta(const void* delta) { return ((const delta_t *) delta)->type == DT_MOBJ && (((const delta_t *) delta)->flags & MDFC_CREATE); } /** * @return @c true, if the deltas refer to the same object. */ boolean Sv_IsSameDelta(const void* delta1, const void* delta2) { const delta_t* a = delta1, *b = delta2; return (a->type == b->type) && (a->id == b->id); } /** * Makes a copy of the delta. */ void* Sv_CopyDelta(void* deltaPtr) { void* newDelta; delta_t* delta = deltaPtr; size_t size = (delta->type == DT_MOBJ ? sizeof(mobjdelta_t) : delta->type == DT_PLAYER ? sizeof(playerdelta_t) : delta->type == DT_SECTOR ? sizeof(sectordelta_t) : delta->type == DT_SIDE ? sizeof(sidedelta_t) : delta->type == DT_POLY ? sizeof(polydelta_t) : delta->type == DT_SOUND ? sizeof(sounddelta_t) : delta->type == DT_MOBJ_SOUND ? sizeof(sounddelta_t) : delta->type == DT_SECTOR_SOUND ? sizeof(sounddelta_t) : delta->type == DT_POLY_SOUND ? sizeof(sounddelta_t) /* : delta->type == DT_LUMP? sizeof(lumpdelta_t) */ : 0); if(size == 0) { Con_Error("Sv_CopyDelta: Unknown delta type %i.\n", delta->type); } newDelta = Z_Malloc(size, PU_MAP, 0); memcpy(newDelta, deltaPtr, size); return newDelta; } /** * Subtracts the contents of the second delta from the first delta. * Subtracting means that if a given flag is defined for both 1 and 2, * the flag for 1 is cleared (2 overrides 1). The result is that the * deltas can be applied in any order and the result is still correct. * * 1 and 2 must refer to the same entity! */ void Sv_SubtractDelta(void* deltaPtr1, const void* deltaPtr2) { delta_t* delta = deltaPtr1; const delta_t* sub = deltaPtr2; #ifdef _DEBUG if(!Sv_IsSameDelta(delta, sub)) { Con_Error("Sv_SubtractDelta: Not the same!\n"); } #endif if(Sv_IsNullMobjDelta(sub)) { // Null deltas kill everything. delta->flags = 0; } else { // Clear the common flags. delta->flags &= ~(delta->flags & sub->flags); } } /** * Applies the data in the source delta to the destination delta. * Both must be in the NEW state. Handles all types of deltas. */ void Sv_ApplyDeltaData(void* destDelta, const void* srcDelta) { const delta_t* src = srcDelta; delta_t* dest = destDelta; int sf = src->flags; if(src->type == DT_MOBJ) { const dt_mobj_t* s = &((const mobjdelta_t *) src)->mo; dt_mobj_t* d = &((mobjdelta_t *) dest)->mo; // *Always* set the player pointer. d->dPlayer = s->dPlayer; if(sf & (MDF_POS_X | MDF_POS_Y)) d->subsector = s->subsector; if(sf & MDF_POS_X) d->pos[VX] = s->pos[VX]; if(sf & MDF_POS_Y) d->pos[VY] = s->pos[VY]; if(sf & MDF_POS_Z) d->pos[VZ] = s->pos[VZ]; if(sf & MDF_MOM_X) d->mom[MX] = s->mom[MX]; if(sf & MDF_MOM_Y) d->mom[MY] = s->mom[MY]; if(sf & MDF_MOM_Z) d->mom[MZ] = s->mom[MZ]; if(sf & MDF_ANGLE) d->angle = s->angle; if(sf & MDF_SELECTOR) d->selector = s->selector; if(sf & MDF_STATE) { d->state = s->state; d->tics = (s->state ? s->state->tics : 0); } if(sf & MDF_RADIUS) d->radius = s->radius; if(sf & MDF_HEIGHT) d->height = s->height; if(sf & MDF_FLAGS) d->ddFlags = s->ddFlags; if(sf & MDF_FLOORCLIP) d->floorClip = s->floorClip; if(sf & MDFC_TRANSLUCENCY) d->translucency = s->translucency; if(sf & MDFC_FADETARGET) d->visTarget = s->visTarget; } else if(src->type == DT_PLAYER) { const dt_player_t* s = &((const playerdelta_t *) src)->player; dt_player_t* d = &((playerdelta_t *) dest)->player; if(sf & PDF_MOBJ) d->mobj = s->mobj; if(sf & PDF_FORWARDMOVE) d->forwardMove = s->forwardMove; if(sf & PDF_SIDEMOVE) d->sideMove = s->sideMove; /*if(sf & PDF_ANGLE) d->angle = s->angle;*/ if(sf & PDF_TURNDELTA) d->turnDelta = s->turnDelta; if(sf & PDF_FRICTION) d->friction = s->friction; if(sf & PDF_EXTRALIGHT) { d->extraLight = s->extraLight; d->fixedColorMap = s->fixedColorMap; } if(sf & PDF_FILTER) d->filter = s->filter; /* if(sf & PDF_CLYAW) d->clYaw = s->clYaw; if(sf & PDF_CLPITCH) d->clPitch = s->clPitch; */ /* $unifiedangles */ if(sf & PDF_PSPRITES) { uint i; for(i = 0; i < 2; ++i) { int off = 16 + i * 8; if(sf & (PSDF_STATEPTR << off)) { d->psp[i].statePtr = s->psp[i].statePtr; d->psp[i].tics = (s->psp[i].statePtr ? s->psp[i].statePtr->tics : 0); } /*if(sf & (PSDF_LIGHT << off)) d->psp[i].light = s->psp[i].light;*/ if(sf & (PSDF_ALPHA << off)) d->psp[i].alpha = s->psp[i].alpha; if(sf & (PSDF_STATE << off)) d->psp[i].state = s->psp[i].state; if(sf & (PSDF_OFFSET << off)) { d->psp[i].offset[VX] = s->psp[i].offset[VX]; d->psp[i].offset[VY] = s->psp[i].offset[VY]; } } } } else if(src->type == DT_SECTOR) { const dt_sector_t* s = &((const sectordelta_t *) src)->sector; dt_sector_t* d = &((sectordelta_t *) dest)->sector; if(sf & SDF_FLOOR_MATERIAL) d->planes[PLN_FLOOR].surface.material = s->planes[PLN_FLOOR].surface.material; if(sf & SDF_CEILING_MATERIAL) d->planes[PLN_CEILING].surface.material = s->planes[PLN_CEILING].surface.material; if(sf & SDF_LIGHT) d->lightLevel = s->lightLevel; if(sf & SDF_FLOOR_TARGET) d->planes[PLN_FLOOR].target = s->planes[PLN_FLOOR].target; if(sf & SDF_FLOOR_SPEED) d->planes[PLN_FLOOR].speed = s->planes[PLN_FLOOR].speed; if(sf & SDF_CEILING_TARGET) d->planes[PLN_CEILING].target = s->planes[PLN_CEILING].target; if(sf & SDF_CEILING_SPEED) d->planes[PLN_CEILING].speed = s->planes[PLN_CEILING].speed; if(sf & SDF_FLOOR_HEIGHT) d->planes[PLN_FLOOR].height = s->planes[PLN_FLOOR].height; if(sf & SDF_CEILING_HEIGHT) d->planes[PLN_CEILING].height = s->planes[PLN_CEILING].height; if(sf & SDF_COLOR_RED) d->rgb[0] = s->rgb[0]; if(sf & SDF_COLOR_GREEN) d->rgb[1] = s->rgb[1]; if(sf & SDF_COLOR_BLUE) d->rgb[2] = s->rgb[2]; if(sf & SDF_FLOOR_COLOR_RED) d->planes[PLN_FLOOR].surface.rgba[0] = s->planes[PLN_FLOOR].surface.rgba[0]; if(sf & SDF_FLOOR_COLOR_GREEN) d->planes[PLN_FLOOR].surface.rgba[1] = s->planes[PLN_FLOOR].surface.rgba[1]; if(sf & SDF_FLOOR_COLOR_BLUE) d->planes[PLN_FLOOR].surface.rgba[2] = s->planes[PLN_FLOOR].surface.rgba[2]; if(sf & SDF_CEIL_COLOR_RED) d->planes[PLN_CEILING].surface.rgba[0] = s->planes[PLN_CEILING].surface.rgba[0]; if(sf & SDF_CEIL_COLOR_GREEN) d->planes[PLN_CEILING].surface.rgba[1] = s->planes[PLN_CEILING].surface.rgba[1]; if(sf & SDF_CEIL_COLOR_BLUE) d->planes[PLN_CEILING].surface.rgba[2] = s->planes[PLN_CEILING].surface.rgba[2]; if(sf & SDF_FLOOR_GLOW_RED) d->planes[PLN_FLOOR].glowRGB[0] = s->planes[PLN_FLOOR].glowRGB[0]; if(sf & SDF_FLOOR_GLOW_GREEN) d->planes[PLN_FLOOR].glowRGB[1] = s->planes[PLN_FLOOR].glowRGB[1]; if(sf & SDF_FLOOR_GLOW_BLUE) d->planes[PLN_FLOOR].glowRGB[2] = s->planes[PLN_FLOOR].glowRGB[2]; if(sf & SDF_CEIL_GLOW_RED) d->planes[PLN_CEILING].glowRGB[0] = s->planes[PLN_CEILING].glowRGB[0]; if(sf & SDF_CEIL_GLOW_GREEN) d->planes[PLN_CEILING].glowRGB[1] = s->planes[PLN_CEILING].glowRGB[1]; if(sf & SDF_CEIL_GLOW_BLUE) d->planes[PLN_CEILING].glowRGB[2] = s->planes[PLN_CEILING].glowRGB[2]; if(sf & SDF_FLOOR_GLOW) d->planes[PLN_FLOOR].glow = s->planes[PLN_FLOOR].glow; if(sf & SDF_CEIL_GLOW) d->planes[PLN_CEILING].glow = s->planes[PLN_CEILING].glow; } else if(src->type == DT_SIDE) { const dt_side_t* s = &((const sidedelta_t *) src)->side; dt_side_t* d = &((sidedelta_t *) dest)->side; if(sf & SIDF_TOP_MATERIAL) d->top.material = s->top.material; if(sf & SIDF_MID_MATERIAL) d->middle.material = s->middle.material; if(sf & SIDF_BOTTOM_MATERIAL) d->bottom.material = s->bottom.material; if(sf & SIDF_LINE_FLAGS) d->lineFlags = s->lineFlags; if(sf & SIDF_TOP_COLOR_RED) d->top.rgba[0] = s->top.rgba[0]; if(sf & SIDF_TOP_COLOR_GREEN) d->top.rgba[1] = s->top.rgba[1]; if(sf & SIDF_TOP_COLOR_BLUE) d->top.rgba[2] = s->top.rgba[2]; if(sf & SIDF_MID_COLOR_RED) d->middle.rgba[0] = s->middle.rgba[0]; if(sf & SIDF_MID_COLOR_GREEN) d->middle.rgba[1] = s->middle.rgba[1]; if(sf & SIDF_MID_COLOR_BLUE) d->middle.rgba[2] = s->middle.rgba[2]; if(sf & SIDF_MID_COLOR_ALPHA) d->middle.rgba[3] = s->middle.rgba[3]; if(sf & SIDF_BOTTOM_COLOR_RED) d->bottom.rgba[0] = s->bottom.rgba[0]; if(sf & SIDF_BOTTOM_COLOR_GREEN) d->bottom.rgba[1] = s->bottom.rgba[1]; if(sf & SIDF_BOTTOM_COLOR_BLUE) d->bottom.rgba[2] = s->bottom.rgba[2]; if(sf & SIDF_MID_BLENDMODE) d->middle.blendMode = s->middle.blendMode; if(sf & SIDF_FLAGS) d->flags = s->flags; } else if(src->type == DT_POLY) { const dt_poly_t* s = &((const polydelta_t *) src)->po; dt_poly_t* d = &((polydelta_t *) dest)->po; if(sf & PODF_DEST_X) d->dest.pos[VX] = s->dest.pos[VX]; if(sf & PODF_DEST_Y) d->dest.pos[VY] = s->dest.pos[VY]; if(sf & PODF_SPEED) d->speed = s->speed; if(sf & PODF_DEST_ANGLE) d->destAngle = s->destAngle; if(sf & PODF_ANGSPEED) d->angleSpeed = s->angleSpeed; } else if(Sv_IsSoundDelta(src)) { const sounddelta_t* s = srcDelta; sounddelta_t* d = destDelta; if(sf & SNDDF_VOLUME) d->volume = s->volume; d->sound = s->sound; } else { Con_Error("Sv_ApplyDeltaData: Unknown delta type %i.\n", src->type); } } /** * Merges the second delta with the first one. * The source and destination must refer to the same entity. * * @return @c false, if the result of the merge is a void delta. */ boolean Sv_MergeDelta(void* destDelta, const void* srcDelta) { const delta_t* src = srcDelta; delta_t* dest = destDelta; #ifdef _DEBUG if(!Sv_IsSameDelta(src, dest)) { Con_Error("Sv_MergeDelta: Not the same!\n"); } if(dest->state != DELTA_NEW) { Con_Error("Sv_MergeDelta: Dest is not NEW.\n"); } #endif if(Sv_IsNullMobjDelta(dest)) { // Nothing can be merged with a null mobj delta. return true; } if(Sv_IsNullMobjDelta(src)) { // Null mobj deltas kill the destination. dest->flags = MDFC_NULL; return true; } if(Sv_IsCreateMobjDelta(dest) && Sv_IsNullMobjDelta(src)) { // Applying a Null mobj delta on a Create mobj delta causes // the two deltas to negate each other. Returning false // signifies that both should be removed from the pool. dest->flags = 0; return false; } if(Sv_IsStartSoundDelta(src) || Sv_IsStopSoundDelta(src)) { // Sound deltas completely override what they're being // merged with. (Only one sound per source.) Stop Sound deltas must // kill NEW sound deltas, because what is the benefit of sending // both in the same frame: first start a sound and then immediately // stop it? We don't want that. sounddelta_t* destSound = destDelta; const sounddelta_t* srcSound = srcDelta; // Destination becomes equal to source. dest->flags = src->flags; destSound->sound = srcSound->sound; destSound->mobj = srcSound->mobj; destSound->volume = srcSound->volume; return true; } // The destination will contain all of source's data in addition // to the existing data. dest->flags |= src->flags; // The time stamp must NOT be always updated: the delta already // contains data which should've been sent some time ago. If we // update the time stamp now, the overdue data might not be sent. /* dest->timeStamp = src->timeStamp; */ Sv_ApplyDeltaData(dest, src); return true; } /** * @return The age of the delta, in milliseconds. */ uint Sv_DeltaAge(const delta_t* delta) { return Sv_GetTimeStamp() - delta->timeStamp; } /** * Approximate the distance to the given sector. Set 'mayBeGone' to true * if the mobj may have been destroyed and should not be processed. */ float Sv_MobjDistance(const mobj_t* mo, const ownerinfo_t* info, boolean isReal) { float z; if(isReal && !P_IsUsedMobjID(mo->thinker.id)) { // This mobj does not exist any more! return DDMAXFLOAT; } z = mo->pos[VZ]; // Registered mobjs may have a maxed out Z coordinate. if(!isReal) { if(z == DDMINFLOAT) z = mo->floorZ; if(z == DDMAXFLOAT) z = mo->ceilingZ - mo->height; } return P_ApproxDistance3(info->pos[VX] - mo->pos[VX], info->pos[VY] - mo->pos[VY], info->pos[VZ] - z + mo->height / 2); } /** * Approximate the distance to the given sector. */ float Sv_SectorDistance(int index, const ownerinfo_t* info) { sector_t* sector = SECTOR_PTR(index); return P_ApproxDistance3(info->pos[VX] - sectorOrigins[index].pos[VX], info->pos[VY] - sectorOrigins[index].pos[VY], info->pos[VZ] - ((sector->planes[PLN_CEILING]->height + sector->planes[PLN_FLOOR]->height) / 2)); } /** * @return The distance to the origin of the delta's entity. */ float Sv_DeltaDistance(const void* deltaPtr, const ownerinfo_t* info) { const delta_t* delta = deltaPtr; if(delta->type == DT_MOBJ) { #ifdef _DEBUG if(delta->flags & MDFC_NULL) { delta = delta; } #endif // Use the delta's registered mobj position. For old unacked data, // it may be somewhat inaccurate. return Sv_MobjDistance(&((mobjdelta_t *) deltaPtr)->mo, info, false); } if(delta->type == DT_PLAYER) { // Use the player's actual position. const mobj_t* mo = ddPlayers[delta->id].shared.mo; if(mo) { return Sv_MobjDistance(mo, info, true); } } if(delta->type == DT_SECTOR) { return Sv_SectorDistance(delta->id, info); } if(delta->type == DT_SIDE) { return P_ApproxDistance(info->pos[VX] - sideOrigins[delta->id].pos[VX], info->pos[VY] - sideOrigins[delta->id].pos[VY]); } if(delta->type == DT_POLY) { polyobj_t* po = polyObjs[delta->id]; return P_ApproxDistance(info->pos[VX] - po->pos[VX], info->pos[VY] - po->pos[VY]); } if(delta->type == DT_MOBJ_SOUND) { const sounddelta_t* sound = deltaPtr; return Sv_MobjDistance(sound->mobj, info, true); } if(delta->type == DT_SECTOR_SOUND) { return Sv_SectorDistance(delta->id, info); } if(delta->type == DT_POLY_SOUND) { polyobj_t* po = polyObjs[delta->id]; return P_ApproxDistance(info->pos[VX] - po->pos[VX], info->pos[VY] - po->pos[VY]); } // Unknown distance. return 1; } /** * The hash function for the pool delta hash. */ deltalink_t* Sv_PoolHash(pool_t* pool, int id) { return &pool->hash[(uint) id & POOL_HASH_FUNCTION_MASK]; } /** * The delta is removed from the pool's delta hash. */ void Sv_RemoveDelta(pool_t* pool, void* deltaPtr) { delta_t* delta = deltaPtr; deltalink_t* hash = Sv_PoolHash(pool, delta->id); // Update first and last links. if(hash->last == delta) { hash->last = delta->prev; } if(hash->first == delta) { hash->first = delta->next; } // Link the delta out of the list. if(delta->next) { delta->next->prev = delta->prev; } if(delta->prev) { delta->prev->next = delta->next; } // Destroy it. Z_Free(delta); } /** * Draining the pool means emptying it of all contents. (Doh?) */ void Sv_DrainPool(uint clientNumber) { pool_t* pool = &pools[clientNumber]; delta_t* delta; misrecord_t* mis; void* next = NULL; int i; // Update the number of the owner. pool->owner = clientNumber; // Reset the counters. pool->setDealer = 0; pool->resendDealer = 0; Sv_PoolQueueClear(pool); // Free all deltas stored in the hash. for(i = 0; i < POOL_HASH_SIZE; ++i) { for(delta = pool->hash[i].first; delta; delta = next) { next = delta->next; Z_Free(delta); } } // Free all missile records in the pool. for(i = 0; i < POOL_MISSILE_HASH_SIZE; ++i) { for(mis = pool->misHash[i].first; mis; mis = next) { next = mis->next; Z_Free(mis); } } // Clear all the chains. memset(pool->hash, 0, sizeof(pool->hash)); memset(pool->misHash, 0, sizeof(pool->misHash)); } /** * @return The maximum distance for the sound. If the origin * is any farther, the delta will not be sent to the * client in question. */ float Sv_GetMaxSoundDistance(const sounddelta_t* delta) { float volume = 1; // Volume shortens the maximum distance (why send it if it's not // audible?). if(delta->delta.flags & SNDDF_VOLUME) { volume = delta->volume; } if(volume <= 0) { // Silence is heard all over the world. return DDMAXFLOAT; } return volume * soundMaxDist; } /** * @return The flags that remain after exclusion. */ int Sv_ExcludeDelta(pool_t* pool, const void* deltaPtr) { const delta_t* delta = deltaPtr; player_t* plr = &ddPlayers[pool->owner]; mobj_t* poolViewer = plr->shared.mo; int flags = delta->flags; // Can we exclude information from the delta? (for this player only) if(delta->type == DT_MOBJ) { const mobjdelta_t* mobjDelta = deltaPtr; if(poolViewer && poolViewer->thinker.id == delta->id) { // This is the mobj the owner of the pool uses as a camera. flags &= ~MDF_CAMERA_EXCLUDE; // This information is sent in the PSV_PLAYER_FIX packet, // but only under specific circumstances. Most of the time // the client is responsible for updating its own pos/mom/angle. flags &= ~MDF_POS; flags &= ~MDF_MOM; flags &= ~MDF_ANGLE; } // What about missiles? We might be allowed to exclude some // information. if(mobjDelta->mo.ddFlags & DDMF_MISSILE) { if(!Sv_IsCreateMobjDelta(delta)) { // This'll might exclude the coordinates. // The missile is put on record when the client acknowledges // the Create Mobj delta. flags &= ~Sv_MRCheck(pool, mobjDelta); } else if(Sv_IsNullMobjDelta(delta)) { // The missile is being removed entirely. // Remove the entry from the missile record. Sv_MRRemove(pool, delta->id); } } } else if(delta->type == DT_PLAYER) { if(pool->owner == delta->id) { // All information does not need to be sent. flags &= ~PDF_CAMERA_EXCLUDE; /* $unifiedangles */ /* if(!(player->flags & DDPF_FIXANGLES)) { // Fixangles means that the server overrides the clientside // view angles. Normally they are always clientside, so // exclude them here. flags &= ~(PDF_CLYAW | PDF_CLPITCH); } */ } else { // This is a remote player, the owner of the pool doesn't need // to know everything about it (like psprites). flags &= ~PDF_NONCAMERA_EXCLUDE; } } else if(Sv_IsSoundDelta(delta)) { // Sounds that originate from too far away are not added to a pool. // Stop Sound deltas have an infinite max distance, though. if(Sv_DeltaDistance(delta, &pool->ownerInfo) > Sv_GetMaxSoundDistance(deltaPtr)) { // Don't add it. return 0; } } // These are the flags that remain. return flags; } /** * When adding a delta to the pool, it subtracts from the unacked deltas * there and is merged with matching new deltas. If a delta becomes void * after subtraction, it's removed from the pool. All the processing is * done based on the ID number of the delta (and type), so to make things * more efficient, a hash table is used (key is ID). * * Deltas are unique only in the NEW state. There may be multiple UNACKED * deltas for the same entity. * * The contents of the delta must not be modified. */ void Sv_AddDelta(pool_t* pool, void* deltaPtr) { delta_t* iter, *next = NULL, *existingNew = NULL; delta_t* delta = deltaPtr; deltalink_t* hash = Sv_PoolHash(pool, delta->id); int flags, originalFlags; // Sometimes we can exclude a part of the data, if the client has no // use for it. flags = Sv_ExcludeDelta(pool, delta); if(!flags) { // No data remains... No need to add this delta. return; } // Temporarily use the excluded flags. originalFlags = delta->flags; delta->flags = flags; // While subtracting from old deltas, we'll look for a pointer to // an existing NEW delta. for(iter = hash->first; iter; iter = next) { // Iter is removed if it becomes void. next = iter->next; // Sameness is determined with type and ID. if(Sv_IsSameDelta(iter, delta)) { if(iter->state == DELTA_NEW) { // We'll merge with this instead of adding a new delta. existingNew = iter; } else if(iter->state == DELTA_UNACKED) { // The new information in the delta overrides the info in // this unacked delta. Let's subtract. This way, if the // unacked delta needs to be resent, it won't contain // obsolete data. Sv_SubtractDelta(iter, delta); // Was everything removed? if(Sv_IsVoidDelta(iter)) { Sv_RemoveDelta(pool, iter); continue; } } } } if(existingNew) { // Merge the new delta with the older NEW delta. if(!Sv_MergeDelta(existingNew, delta)) { // The deltas negated each other (Null -> Create). // The existing delta must be removed. Sv_RemoveDelta(pool, existingNew); } } else { // Add it to the end of the hash chain. We must take a copy // of the delta so it can be stored in the hash. iter = Sv_CopyDelta(delta); if(hash->last) { hash->last->next = iter; iter->prev = hash->last; } hash->last = iter; if(!hash->first) { hash->first = iter; } } // This delta may yet be added to other pools. They should use the // original flags, not the ones we might've used (hackish: copying the // whole delta is not really an option, though). delta->flags = originalFlags; } /** * Add the delta to all the pools in the NULL-terminated array. */ void Sv_AddDeltaToPools(void* deltaPtr, pool_t** targets) { for(; *targets; targets++) { Sv_AddDelta(*targets, deltaPtr); } } /** * All NEW deltas for the mobj are removed from the pool as obsolete. */ void Sv_PoolMobjRemoved(pool_t* pool, thid_t id) { deltalink_t* hash = Sv_PoolHash(pool, id); delta_t* delta, *next = NULL; for(delta = hash->first; delta; delta = next) { next = delta->next; if(delta->state == DELTA_NEW && delta->type == DT_MOBJ && delta->id == id) { // This must be removed! Sv_RemoveDelta(pool, delta); } } // Also check the missile record. Sv_MRRemove(pool, id); } /** * This is called when a mobj is removed in a predictable fashion. * (Mobj state is NULL when it's destroyed. Assumption: The NULL state * is set only when animation reaches its end.) Because the register-mobj * is removed, no Null Mobj delta is generated for the mobj. */ void Sv_MobjRemoved(thid_t id) { uint i; reg_mobj_t* mo = Sv_RegisterFindMobj(&worldRegister, id); if(mo) { Sv_RegisterRemoveMobj(&worldRegister, mo); // We must remove all NEW deltas for this mobj from the pools. // One possibility: there are mobj deltas waiting in the pool, // but the mobj is removed here. Because it'll be no longer in // the register, no Null Mobj delta is generated, and thus the // client will eventually receive those mobj deltas unnecessarily. for(i = 0; i < DDMAXPLAYERS; ++i) { if(clients[i].connected) { Sv_PoolMobjRemoved(&pools[i], id); } } } } /** * When a player leaves the game, his data is removed from the register. * Otherwise he'll not get all the data if he reconnects before the map * is changed. */ void Sv_PlayerRemoved(uint playerNumber) { dt_player_t* p = &worldRegister.ddPlayers[playerNumber]; memset(p, 0, sizeof(*p)); } /** * @return @c true, if the pool is in the targets array. */ boolean Sv_IsPoolTargeted(pool_t* pool, pool_t** targets) { for(; *targets; targets++) { if(pool == *targets) return true; } return false; } /** * Fills the array with pointers to the pools of the connected clients, * if specificClient is < 0. * * @return The number of pools in the list. */ int Sv_GetTargetPools(pool_t** targets, int clientsMask) { int i, numTargets = 0; for(i = 0; i < DDMAXPLAYERS; ++i) { if(clientsMask & (1 << i) && clients[i].connected) { targets[numTargets++] = &pools[i]; } } /* if(specificClient & SVSF_ specificClient >= 0) { targets[0] = &pools[specificClient]; targets[1] = NULL; return 1; } for(i = 0; i < DDMAXPLAYERS; ++i) { // Deltas must be generated for all connected players, even // if they aren't yet ready to receive them. if(clients[i].connected) { if(specificClient == SV_TARGET_ALL_POOLS || i != -specificClient) targets[numTargets++] = &pools[i]; } } */ // A NULL pointer marks the end of target pools. targets[numTargets] = NULL; return numTargets; } /** * Null deltas are generated for mobjs that have been destroyed. * The register's mobj hash is scanned to see which mobjs no longer exist. * * When updating, the destroyed mobjs are removed from the register. */ void Sv_NewNullDeltas(cregister_t* reg, boolean doUpdate, pool_t** targets) { int i; mobjhash_t* hash; reg_mobj_t* obj, *next = 0; mobjdelta_t null; for(i = 0, hash = reg->mobjs; i < REG_MOBJ_HASH_SIZE; ++i, hash++) { for(obj = hash->first; obj; obj = next) { // This reg_mobj_t might be removed. next = obj->next; if(!P_IsUsedMobjID(obj->mo.thinker.id)) { // This object no longer exists! Sv_NewDelta(&null, DT_MOBJ, obj->mo.thinker.id); null.delta.flags = MDFC_NULL; // We need all the data for positioning. memcpy(&null.mo, &obj->mo, sizeof(dt_mobj_t)); Sv_AddDeltaToPools(&null, targets); /*#ifdef _DEBUG Con_Printf("New null: %i, %s\n", obj->mo.thinker.id, defs.states[obj->mo.state - states].id); #endif */ if(doUpdate) { // Keep the register up to date. Sv_RegisterRemoveMobj(reg, obj); } } } } } typedef struct { cregister_t* reg; boolean doUpdate; pool_t** targets; } newmobjdeltaparams_t; static boolean newMobjDelta(thinker_t* th, void* context) { newmobjdeltaparams_t* params = (newmobjdeltaparams_t*) context; mobj_t* mo = (mobj_t *) th; // Some objects should not be processed. if(!Sv_IsMobjIgnored(mo)) { mobjdelta_t delta; // Compare to produce a delta. if(Sv_RegisterCompareMobj(params->reg, mo, &delta)) { Sv_AddDeltaToPools(&delta, params->targets); if(params->doUpdate) { reg_mobj_t* obj; // This'll add a new register-mobj if it doesn't // already exist. obj = Sv_RegisterAddMobj(params->reg, mo->thinker.id); Sv_RegisterMobj(&obj->mo, mo); } } } return true; // Continue iteration. } /** * Mobj deltas are generated for all mobjs that have changed. */ void Sv_NewMobjDeltas(cregister_t* reg, boolean doUpdate, pool_t** targets) { newmobjdeltaparams_t params; params.reg = reg; params.doUpdate = doUpdate; params.targets = targets; // Mobjs are always public. P_IterateThinkers(gx.MobjThinker, 0x1, newMobjDelta, ¶ms); } /** * Player deltas are generated for changed player data. */ void Sv_NewPlayerDeltas(cregister_t* reg, boolean doUpdate, pool_t** targets) { uint i; playerdelta_t player; for(i = 0; i < DDMAXPLAYERS; ++i) { if(Sv_IsPlayerIgnored(i)) continue; // Compare to produce a delta. if(Sv_RegisterComparePlayer(reg, i, &player)) { // Did the mobj change? If so, the old mobj must be zeroed // in the register. Otherwise, the clients may not receive // all the data they need (because of viewpoint exclusion // flags). if(doUpdate && (player.delta.flags & PDF_MOBJ)) { reg_mobj_t* registered = Sv_RegisterFindMobj(reg, reg->ddPlayers[i].mobj); if(registered) { Sv_RegisterResetMobj(®istered->mo); } } Sv_AddDeltaToPools(&player, targets); } if(doUpdate) { Sv_RegisterPlayer(®->ddPlayers[i], i); } // What about forced deltas? if(Sv_IsPoolTargeted(&pools[i], targets)) { #if 0 if(ddPlayers[i].flags & DDPF_FIXANGLES) { Sv_NewDelta(&player, DT_PLAYER, i); Sv_RegisterPlayer(&player.player, i); //player.delta.flags = PDF_CLYAW | PDF_CLPITCH; /* $unifiedangles */ // Once added to the pool, the information will not get lost. Sv_AddDelta(&pools[i], &player); // Doing this once is enough. ddPlayers[i].flags &= ~DDPF_FIXANGLES; } // Generate a FIXPOS/FIXMOM mobj delta, too? if(ddPlayers[i].mo && (ddPlayers[i].flags & (DDPF_FIXPOS | DDPF_FIXMOM))) { const mobj_t *mo = ddPlayers[i].mo; mobjdelta_t mobj; Sv_NewDelta(&mobj, DT_MOBJ, mo->thinker.id); Sv_RegisterMobj(&mobj.mo, mo); if(ddPlayers[i].flags & DDPF_FIXPOS) { mobj.delta.flags |= MDF_POS; } if(ddPlayers[i].flags & DDPF_FIXMOM) { mobj.delta.flags |= MDF_MOM; } Sv_AddDelta(&pools[i], &mobj); // Doing this once is enough. ddPlayers[i].flags &= ~(DDPF_FIXPOS | DDPF_FIXMOM); } #endif } } } /** * Sector deltas are generated for changed sectors. */ void Sv_NewSectorDeltas(cregister_t* reg, boolean doUpdate, pool_t** targets) { uint i; sectordelta_t delta; for(i = 0; i < numSectors; ++i) { if(Sv_RegisterCompareSector(reg, i, &delta, doUpdate)) { Sv_AddDeltaToPools(&delta, targets); } } } /** * Side deltas are generated for changed sides (and line flags). * Changes in sides (textures) are so rare that all sides need not be * checked on every tic. */ void Sv_NewSideDeltas(cregister_t* reg, boolean doUpdate, pool_t** targets) { static uint numShifts = 2, shift = 0; sidedelta_t delta; uint i, start, end; // When comparing against an initial register, always compare all // sides (since the comparing is only done once, not continuously). if(reg->isInitial) { start = 0; end = numSideDefs; } else { // Because there are so many sides in a typical map, the number // of compared sides soon accumulates to millions. To reduce the // load, we'll check only a portion of all sides for a frame. start = shift * numSideDefs / numShifts; end = ++shift * numSideDefs / numShifts; shift %= numShifts; } for(i = start; i < end; ++i) { // The side must be owned by a line. if(sideOwners[i] == NULL) continue; if(Sv_RegisterCompareSide(reg, i, &delta, doUpdate)) { Sv_AddDeltaToPools(&delta, targets); } } } /** * Poly deltas are generated for changed polyobjs. */ void Sv_NewPolyDeltas(cregister_t* reg, boolean doUpdate, pool_t** targets) { uint i; polydelta_t delta; for(i = 0; i < numPolyObjs; ++i) { if(Sv_RegisterComparePoly(reg, i, &delta)) { #ifdef _DEBUG Con_Printf("Sv_NewPolyDeltas: Change in %i\n", i); #endif Sv_AddDeltaToPools(&delta, targets); } if(doUpdate) { Sv_RegisterPoly(®->polyObjs[i], i); } } } /** * Adds a new sound delta to the appropriate pools. * Because the starting of a sound is in itself a 'delta-like' event, * there is no need for comparing or to have a register. * Set 'volume' to zero to create a sound-stopping delta. * * \assume: No two sounds with the same ID play at the same time from the * same origin. */ void Sv_NewSoundDelta(int soundId, mobj_t* emitter, sector_t* sourceSector, polyobj_t* sourcePoly, float volume, boolean isRepeating, int clientsMask) { pool_t* targets[DDMAXPLAYERS + 1]; sounddelta_t soundDelta; int type = DT_SOUND, df = 0; uint id = soundId; // Determine the target pools. Sv_GetTargetPools(targets, clientsMask); if(sourceSector != NULL) { type = DT_SECTOR_SOUND; id = GET_SECTOR_IDX(sourceSector); // Clients need to know which emitter to use. if(emitter) { if(emitter == (mobj_t*) &sourceSector->planes[PLN_FLOOR]->soundOrg) df |= SNDDF_FLOOR; else if(emitter == (mobj_t*) &sourceSector->planes[PLN_CEILING]->soundOrg) df |= SNDDF_CEILING; // else client assumes sector->soundOrg } } else if(sourcePoly != NULL) { type = DT_POLY_SOUND; id = sourcePoly->idx; } else if(emitter) { type = DT_MOBJ_SOUND; id = emitter->thinker.id; soundDelta.mobj = emitter; } // Init to the right type. Sv_NewDelta(&soundDelta, type, id); // Always set volume. df |= SNDDF_VOLUME; soundDelta.volume = volume; if(isRepeating) df |= SNDDF_REPEAT; // This is used by mobj/sector sounds. soundDelta.sound = soundId; soundDelta.delta.flags = df; Sv_AddDeltaToPools(&soundDelta, targets); } /** * @return @c true, if the client should receive frames. */ boolean Sv_IsFrameTarget(uint plrNum) { player_t* plr = &ddPlayers[plrNum]; ddplayer_t* ddpl = &plr->shared; // Local players receive frames only when they're recording a demo. // Clients must tell us they are ready before we can begin sending. return (ddpl->inGame && !(ddpl->flags & DDPF_LOCAL) && clients[plrNum].ready) || ((ddpl->flags & DDPF_LOCAL) && clients[plrNum].recording); } /** * Compare the current state of the world with the register and add the * deltas to all the pools, or if a specific client number is given, only * to its pool (done when a new client enters the game). No deltas will be * generated for predictable changes (state changes, linear movement...). * * Updating the register means that the current state of the world is stored * in the register after the deltas have been generated. * * @param clientNumber < 0 = All ingame clients should get the deltas. */ void Sv_GenerateNewDeltas(cregister_t* reg, int clientNumber, boolean doUpdate) { pool_t* targets[DDMAXPLAYERS + 1], **pool; // Determine the target pools. Sv_GetTargetPools(targets, (clientNumber < 0 ? 0xff : (1 << clientNumber))); // Update the info of the pool owners. for(pool = targets; *pool; pool++) { Sv_UpdateOwnerInfo(*pool); } // Generate null deltas (removed mobjs). Sv_NewNullDeltas(reg, doUpdate, targets); // Generate mobj deltas. Sv_NewMobjDeltas(reg, doUpdate, targets); // Generate player deltas. Sv_NewPlayerDeltas(reg, doUpdate, targets); // Generate sector deltas. Sv_NewSectorDeltas(reg, doUpdate, targets); // Generate side deltas. Sv_NewSideDeltas(reg, doUpdate, targets); // Generate poly deltas. Sv_NewPolyDeltas(reg, doUpdate, targets); if(doUpdate) { // The register has now been updated to the current time. reg->gametic = SECONDS_TO_TICKS(gameTime); } } /** * This is called once for each frame, in Sv_TransmitFrame(). */ void Sv_GenerateFrameDeltas(void) { // Generate new deltas for all clients and update the world register. Sv_GenerateNewDeltas(&worldRegister, -1, true); } /** * Clears the priority queue of the pool. */ void Sv_PoolQueueClear(pool_t* pool) { pool->queueSize = 0; } /** * Exchanges two elements in the queue. */ void Sv_PoolQueueExchange(pool_t* pool, int index1, int index2) { delta_t *temp = pool->queue[index1]; pool->queue[index1] = pool->queue[index2]; pool->queue[index2] = temp; } /** * Adds the delta to the priority queue. More memory is allocated for the * queue if necessary. */ void Sv_PoolQueueAdd(pool_t* pool, delta_t* delta) { int i, parent; // Do we need more memory? if(pool->allocatedSize == pool->queueSize) { delta_t** newQueue; // Double the memory. pool->allocatedSize *= 2; if(!pool->allocatedSize) { // At least eight. pool->allocatedSize = 8; } // Allocate the new queue. newQueue = Z_Malloc(pool->allocatedSize * sizeof(delta_t *), PU_MAP, 0); // Copy the old data. if(pool->queue) { memcpy(newQueue, pool->queue, sizeof(delta_t *) * pool->queueSize); // Get rid of the old queue. Z_Free(pool->queue); } pool->queue = newQueue; } // Add the new delta to the end of the queue array. i = pool->queueSize; pool->queue[i] = delta; ++pool->queueSize; // Rise in the heap until the correct place is found. while(i > 0) { parent = HEAP_PARENT(i); // Is it good now? if(pool->queue[parent]->score >= delta->score) break; // Exchange with the parent. Sv_PoolQueueExchange(pool, parent, i); i = parent; } } /** * Extracts the delta with the highest priority from the queue. * * @return @c NULL, if there are no more deltas. */ delta_t* Sv_PoolQueueExtract(pool_t* pool) { delta_t* max; int i, left, right, big; boolean isDone; if(!pool->queueSize) { // There is nothing in the queue. return NULL; } // This is what we'll return. max = pool->queue[0]; // Remove the first element from the queue. pool->queue[0] = pool->queue[--pool->queueSize]; // Heapify the heap. This is O(log n). i = 0; isDone = false; while(!isDone) { left = HEAP_LEFT(i); right = HEAP_RIGHT(i); big = i; // Which child is more important? if(left < pool->queueSize && pool->queue[left]->score > pool->queue[i]->score) { big = left; } if(right < pool->queueSize && pool->queue[right]->score > pool->queue[big]->score) { big = right; } // Can we stop now? if(big != i) { // Exchange and continue. Sv_PoolQueueExchange(pool, i, big); i = big; } else { // Heapifying is complete. isDone = true; } } return max; } /** * Postponed deltas can't be sent yet. */ boolean Sv_IsPostponedDelta(void* deltaPtr, ownerinfo_t* info) { delta_t* delta = deltaPtr; uint age = Sv_DeltaAge(delta); if(delta->state == DELTA_UNACKED) { // Is it old enough? If not, it's still possible that the ack // has not reached us yet. return age < info->ackThreshold; } else if(delta->state == DELTA_NEW) { // Normally NEW deltas are never postponed. They are sent as soon // as possible. if(Sv_IsStopSoundDelta(delta)) { // Stop Sound deltas require a bit of care. To make sure they // arrive to the client in the correct order, we won't send // a Stop Sound until we can be sure all the Start Sound deltas // have arrived. (i.e. the pool must contain no Unacked Start // Sound deltas for the same source.) delta_t* iter; for(iter = Sv_PoolHash(info->pool, delta->id)->first; iter; iter = iter->next) { if(iter->state == DELTA_UNACKED && Sv_IsSameDelta(iter, delta) && Sv_IsStartSoundDelta(iter)) { // Must postpone this Stop Sound delta until this one // has been sent. #ifdef _DEBUG Con_Printf("POSTPONE: Stop %i\n", delta->id); #endif return true; } } } } // This delta is not postponed. return false; } /** * Calculate a priority score for the delta. A higher score indicates * greater importance. * * @return @c true iff the delta should be included in the * queue. */ boolean Sv_RateDelta(void* deltaPtr, ownerinfo_t* info) { float score, distance, size; delta_t* delta = deltaPtr; int df = delta->flags; uint age = Sv_DeltaAge(delta); // The importance doubles normally in 1 second. float ageScoreDouble = 1.0f; if(Sv_IsPostponedDelta(delta, info)) { // This delta will not be considered at this time. return false; } // Calculate the distance to the delta's origin. // If no distance can be determined, it's 1.0. distance = Sv_DeltaDistance(delta, info); if(distance < 1) distance = 1; distance = distance * distance; // Power of two. // What is the base score? score = deltaBaseScores[delta->type] / distance; // It's very important to send sound deltas in time. if(Sv_IsSoundDelta(delta)) { // Score doubles very quickly. ageScoreDouble = 1; } // Deltas become more important with age (milliseconds). score *= 1 + age / (ageScoreDouble * 1000.0f); // \fixme Consider viewpoint speed and angle. // Priority bonuses based on the contents of the delta. if(delta->type == DT_MOBJ) { const mobj_t* mo = &((mobjdelta_t *) delta)->mo; // Seeing new mobjs is interesting. if(df & MDFC_CREATE) score *= 1.5f; // Position changes are important. if(df & (MDF_POS_X | MDF_POS_Y)) score *= 1.2f; // Small objects are not that important. size = MAX_OF(mo->radius, mo->height); if(size < 16) { // Not too small, though. if(size < 2) size = 2; score *= size / 16; } else if(size > 50) { // Large objects are important. score *= size / 50; } } else if(delta->type == DT_PLAYER) { // Knowing the player's mobj is quite important. if(df & PDF_MOBJ) score *= 2; } else if(delta->type == DT_SECTOR) { // Lightlevel changes are very noticeable. if(df & SDF_LIGHT) score *= 1.2f; // Plane movements are very important (can be seen from far away). if(df & (SDF_FLOOR_HEIGHT | SDF_CEILING_HEIGHT | SDF_FLOOR_SPEED | SDF_CEILING_SPEED | SDF_FLOOR_TARGET | SDF_CEILING_TARGET)) { score *= 3; } } else if(delta->type == DT_POLY) { // Changes in speed are noticeable. if(df & PODF_SPEED) score *= 1.2f; } // This is the final score. Only positive scores are accepted in // the frame (deltas with nonpositive scores as ignored). return (delta->score = score? true : false); } /** * Calculate a priority score for each delta and build the priority queue. * The most important deltas will be included in a frame packet. * A pool is rated after new deltas have been generated. */ void Sv_RatePool(pool_t* pool) { #ifdef _DEBUG player_t* plr = &ddPlayers[pool->owner]; //client_t* client = &clients[pool->owner]; #endif delta_t* delta; int i; #ifdef _DEBUG if(!plr->shared.mo) { Con_Error("Sv_RatePool: Player %i has no mobj.\n", pool->owner); } #endif // Clear the queue. Sv_PoolQueueClear(pool); // We will rate all the deltas in the pool. After each delta // has been rated, it's added to the priority queue. for(i = 0; i < POOL_HASH_SIZE; ++i) { for(delta = pool->hash[i].first; delta; delta = delta->next) { if(Sv_RateDelta(delta, &pool->ownerInfo)) { Sv_PoolQueueAdd(pool, delta); } } } } /** * Do special things that need to be done when the delta has been acked. */ void Sv_AckDelta(pool_t* pool, delta_t* delta) { if(Sv_IsCreateMobjDelta(delta)) { mobjdelta_t* mobjDelta = (mobjdelta_t *) delta; // Created missiles are put on record. if(mobjDelta->mo.ddFlags & DDMF_MISSILE) { // Once again, we're assuming the delta is always completely // filled with valid information. (There are no 'partial' deltas.) Sv_MRAdd(pool, mobjDelta); } } } /** * Acknowledged deltas are removed from the pool, never to be seen again. * Clients ack deltas to tell the server they've received them. * * @param resent If nonzero, ignore 'set' and ack by resend ID. */ void Sv_AckDeltaSet(uint clientNumber, int set, byte resent) { int i; pool_t* pool = &pools[clientNumber]; delta_t* delta, *next = NULL; boolean ackTimeRegistered = false; // Iterate through the entire hash table. for(i = 0; i < POOL_HASH_SIZE; ++i) { for(delta = pool->hash[i].first; delta; delta = next) { next = delta->next; if(delta->state == DELTA_UNACKED && ((!resent && delta->set == set) || (resent && delta->resend == resent))) { // Register the ack time only for the first acked delta. if(!ackTimeRegistered) { Net_SetAckTime(clientNumber, Sv_DeltaAge(delta)); ackTimeRegistered = true; } // There may be something that we need to do now that the // delta has been acknowledged. Sv_AckDelta(pool, delta); // This delta is now finished! Sv_RemoveDelta(pool, delta); } } } } /** * Debugging metric. */ uint Sv_CountUnackedDeltas(uint clientNumber) { uint i, count; pool_t* pool = Sv_GetPool(clientNumber); delta_t* delta; // Iterate through the entire hash table. count = 0; for(i = 0; i < POOL_HASH_SIZE; ++i) { for(delta = pool->hash[i].first; delta; delta = delta->next) { if(delta->state == DELTA_UNACKED) ++count; } } return count; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_plugin.c0000644000175000017500000001103211357170242023037 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_plugin.c: Plugin Subsystem */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_defs.h" // MACROS ------------------------------------------------------------------ #define HOOKMASK(x) ((x) & 0xffffff) // TYPES ------------------------------------------------------------------- typedef struct { int exclude; hookfunc_t list[MAX_HOOKS]; } hookreg_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ hookreg_t hooks[NUM_HOOK_TYPES]; // CODE -------------------------------------------------------------------- /** * This routine is called by plugin DLLs who want to register hooks. * * @return @c true, iff the hook was successfully registered. */ int Plug_AddHook(int hookType, hookfunc_t hook) { int i, type = HOOKMASK(hookType); // The type must be good. if(type < 0 || type >= NUM_HOOK_TYPES) return false; // Exclusive hooks. if(hookType & HOOKF_EXCLUSIVE) { hooks[type].exclude = true; memset(hooks[type].list, 0, sizeof(hooks[type].list)); } else if(hooks[type].exclude) { // An exclusive hook has closed down this list. return false; } for(i = 0; i < MAX_HOOKS && hooks[type].list[i]; i++); if(i == MAX_HOOKS) return false; // No more hooks allowed! // Add the hook. hooks[type].list[i] = hook; return true; } /** * Removes the given hook. * * @return @c true iff it was found. */ int Plug_RemoveHook(int hookType, hookfunc_t hook) { int i, type = HOOKMASK(hookType); // The type must be good. if(type < 0 || type >= NUM_HOOK_TYPES) return false; for(i = 0; i < MAX_HOOKS; i++) if(hooks[type].list[i] == hook) { hooks[type].list[i] = NULL; if(hookType & HOOKF_EXCLUSIVE) { // Exclusive hook removed; allow normal hooks. hooks[type].exclude = false; } return true; } return false; } /** * Executes all the hooks of the given type. Bit zero of the return value * is set if a hook was executed successfully (returned true). Bit one is * set if all the hooks that were executed returned true. */ int Plug_DoHook(int hookType, int parm, void *data) { int i, ret = 0; boolean allGood = true; // Try all the hooks. for(i = 0; i < MAX_HOOKS; i++) if(hooks[hookType].list[i]) { if(hooks[hookType].list[i] (hookType, parm, data)) { // One hook executed; return nonzero from this routine. ret = 1; } else allGood = false; } if(ret && allGood) ret |= 2; return ret; } /** * Check if a plugin is available of the specified type. * * @param hookType Type of hook to check we have a plugin for. * @return @c true, if a plugin is available for this hook type. */ int Plug_CheckForHook(int hookType) { int i; // Try all the hooks. for(i = 0; i < MAX_HOOKS; i++) if(hooks[hookType].list[i]) return true; return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dam_main.c0000644000175000017500000003614111357170242022647 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dam_main.c: Doomsday Archived Map (DAM), map management. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_dam.h" #include "de_misc.h" #include "de_refresh.h" #include "de_defs.h" #include "de_edit.h" #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void freeArchivedMap(archivedmap_t *dam); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Should we be caching successfully loaded maps? byte mapCache = true; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static const char *mapCacheDir = "mapcache\\"; static archivedmap_t **archivedMaps; static uint numArchivedMaps; // CODE -------------------------------------------------------------------- /** * Called during init to register the cvars and ccmds for DAM. */ void DAM_Register(void) { C_VAR_BYTE("map-cache", &mapCache, 0, 0, 1); } /** * Initializes DAM. */ void DAM_Init(void) { archivedMaps = NULL; numArchivedMaps = 0; P_InitGameMapObjDefs(); } /** * Shutdown DAM. */ void DAM_Shutdown(void) { archivedmap_t *dam; // Free all the archived map records. dam = *archivedMaps; while(dam) { freeArchivedMap(dam); } Z_Free(archivedMaps); archivedMaps = NULL; numArchivedMaps = 0; P_ShutdownGameMapObjDefs(); } static int mapLumpTypeForName(const char* name) { struct maplumpinfo_s { int type; const char *name; } mapLumpInfos[] = { {ML_THINGS, "THINGS"}, {ML_LINEDEFS, "LINEDEFS"}, {ML_SIDEDEFS, "SIDEDEFS"}, {ML_VERTEXES, "VERTEXES"}, {ML_SEGS, "SEGS"}, {ML_SSECTORS, "SSECTORS"}, {ML_NODES, "NODES"}, {ML_SECTORS, "SECTORS"}, {ML_REJECT, "REJECT"}, {ML_BLOCKMAP, "BLOCKMAP"}, {ML_BEHAVIOR, "BEHAVIOR"}, {ML_SCRIPTS, "SCRIPTS"}, {ML_LIGHTS, "LIGHTS"}, {ML_MACROS, "MACROS"}, {ML_LEAFS, "LEAFS"}, {ML_INVALID, NULL} }; int i; if(!name) return ML_INVALID; for(i = 0; mapLumpInfos[i].type > ML_INVALID; ++i) { if(!strcmp(name, mapLumpInfos[i].name)) return mapLumpInfos[i].type; } return ML_INVALID; } /** * Allocate a new list node. */ static listnode_t* allocListNode(void) { listnode_t *node = Z_Calloc(sizeof(listnode_t), PU_STATIC, 0); return node; } /** * Free all memory acquired for the given list node. */ static void freeListNode(listnode_t *node) { if(node) Z_Free(node); } /** * Allocate memory for a new map lump info record. */ static maplumpinfo_t* allocMapLumpInfo(void) { maplumpinfo_t *info = Z_Calloc(sizeof(maplumpinfo_t), PU_STATIC, 0); return info; } /** * Free all memory acquired for the given map lump info record. */ static void freeMapLumpInfo(maplumpinfo_t *info) { if(info) Z_Free(info); } /** * Free a list of maplumpinfo records. */ static void freeMapLumpInfoList(listnode_t* headPtr) { listnode_t* node, *np; node = headPtr; while(node) { np = node->next; if(node->data) freeMapLumpInfo(node->data); freeListNode(node); node = np; } } /** * Create a new map lump info record. */ static maplumpinfo_t* createMapLumpInfo(int lumpNum, int lumpClass) { maplumpinfo_t* info = allocMapLumpInfo(); info->lumpNum = lumpNum; info->lumpClass = lumpClass; info->length = W_LumpLength(lumpNum); info->format = NULL; info->startOffset = 0; return info; } /** * Link a maplumpinfo record to an archivedmap record. */ static void addLumpInfoToList(listnode_t** headPtr, maplumpinfo_t* info) { listnode_t* node = allocListNode(); node->data = info; node->next = *headPtr; *headPtr = node; } /** * Allocate memory for a new archived map record. */ static archivedmap_t* allocArchivedMap(void) { archivedmap_t *dam = Z_Calloc(sizeof(archivedmap_t), PU_STATIC, 0); return dam; } /** * Free all memory acquired for an archived map record. */ static void freeArchivedMap(archivedmap_t *dam) { if(!dam) return; Z_Free(dam->lumpList); Z_Free(dam); } /** * Create a new archivedmap record. */ static archivedmap_t* createArchivedMap(const char *mapID, listnode_t *headPtr, filename_t cachedMapDataFile) { uint i; listnode_t *ln; archivedmap_t *dam = allocArchivedMap(); VERBOSE( Con_Message("createArchivedMap: Add record for map \"%s\".\n", mapID)); strncpy(dam->identifier, mapID, 8); dam->identifier[8] = '\0'; // Terminate. dam->lastLoadAttemptFailed = false; memcpy(dam->cachedMapDataFile, cachedMapDataFile, sizeof(dam->cachedMapDataFile)); if(DAM_MapIsValid(dam->cachedMapDataFile, W_GetNumForName(dam->identifier))) dam->cachedMapFound = true; // Count the lumps for this map dam->numLumps = 0; ln = headPtr; while(ln) { dam->numLumps++; ln = ln->next; } // Allocate an array of the lump indices. dam->lumpList = Z_Malloc(sizeof(int) * dam->numLumps, PU_STATIC, 0); ln = headPtr; i = 0; while(ln) { maplumpinfo_t *info = (maplumpinfo_t*) ln->data; dam->lumpList[i++] = info->lumpNum; ln = ln->next; } return dam; } /** * Search the list of maps for one matching the specified identifier. * * @param mapID Identifier of the map to be searched for. * @return Ptr to the found map, else @c NULL. */ static archivedmap_t* findArchivedMap(const char *mapID) { if(numArchivedMaps) { archivedmap_t **p = archivedMaps; while(*p) { archivedmap_t *dam = *p; if(!strnicmp(dam->identifier, mapID, 8)) return dam; *p++; } } return NULL; } /** * Add an archived map to the list of maps. */ static void addArchivedMap(archivedmap_t* dam) { archivedMaps = Z_Realloc(archivedMaps, sizeof(archivedmap_t*) * (++numArchivedMaps + 1), PU_STATIC); archivedMaps[numArchivedMaps - 1] = dam; archivedMaps[numArchivedMaps] = NULL; // Terminate. } /** * Find the lumps associated with this map dataset and link them to the * archivedmap record. * * \note Some obscure PWADs have these lumps in a non-standard order, * so we need to go resort to finding them automatically. * * @param headPtr The list to link the created maplump records to. * @param startLump The lump number to begin our search with. * * @return The number of collected lumps. */ static uint collectMapLumps(listnode_t** headPtr, int startLump) { int i; uint numCollectedLumps = 0; VERBOSE(Con_Message("collectMapLumps: Locating lumps...\n")); if(startLump > 0 && startLump < numLumps) { // Keep checking lumps to see if its a map data lump. for(i = startLump; i < numLumps; ++i) { int lumpType; const char* lumpName; // Lookup the lump name in our list of known map lump names. lumpName = W_LumpName(i); lumpType = mapLumpTypeForName(lumpName); if(lumpType != ML_INVALID) { // Its a known map lump. maplumpinfo_t *info = createMapLumpInfo(i, lumpType); addLumpInfoToList(headPtr, info); numCollectedLumps++; continue; } // Stop looking, we *should* have found them all. break; } } return numCollectedLumps; } /** * Compose the path where to put the cached map data. */ void DAM_GetCachedMapDir(char* dir, int mainLump, size_t len) { const char* sourceFile = W_LumpSourceFile(mainLump); filename_t base; ushort identifier = 0; int i; M_ExtractFileBase(base, sourceFile, FILENAME_T_MAXLEN); for(i = 0; sourceFile[i]; ++i) identifier ^= sourceFile[i] << ((i * 3) % 11); // The cached map directory is relative to the runtime directory. dd_snprintf(dir, len, "%s%s\\%s-%04X\\", mapCacheDir, (char*) gx.GetVariable(DD_GAME_MODE), base, identifier); M_TranslatePath(dir, dir, len); } static boolean loadMap(gamemap_t **map, archivedmap_t *dam) { *map = Z_Calloc(sizeof(gamemap_t), PU_MAPSTATIC, 0); if(DAM_MapRead(*map, dam->cachedMapDataFile)) return true; return false; } static boolean convertMap(gamemap_t **map, archivedmap_t *dam) { boolean converted = false; Con_Message("convertMap: Attempting conversion of \"%s\".\n", dam->identifier); // Nope. See if there is a converter available. if(Plug_CheckForHook(HOOK_MAP_CONVERT)) { // Pass the lump list around the map converters, hopefully // one of them will recognise the format and convert it. if(Plug_DoHook(HOOK_MAP_CONVERT, dam->numLumps, (void*) dam->lumpList)) { converted = true; *map = MPE_GetLastBuiltMap(); } } Con_Message("convertMap: %s.\n", (converted? "Successful" : "Failed")); return converted; } /** * Attempt to load the map associated with the specified identifier. */ boolean DAM_AttemptMapLoad(const char* mapID) { archivedmap_t* dam; boolean loadedOK = false; VERBOSE2( Con_Message("DAM_AttemptMapLoad: Loading \"%s\"...\n", mapID)); dam = findArchivedMap(mapID); if(!dam) { // We've not yet attempted to load this map. int startLump = W_CheckNumForName(mapID); listnode_t* headPtr = NULL; filename_t cachedMapDir; filename_t cachedMapDataFile; if(startLump == -1) return false; // Add the marker lump to the list of lumps for this map. addLumpInfoToList(&headPtr, createMapLumpInfo(startLump, ML_LABEL)); // Find the rest of the map data lumps associated with this map. collectMapLumps(&headPtr, startLump + 1); DAM_GetCachedMapDir(cachedMapDir, startLump, FILENAME_T_MAXLEN); // Make sure the directory exists. M_CheckPath(cachedMapDir); // First test if we already have valid cached map data. sprintf(cachedMapDataFile, "%s%s", cachedMapDir, W_LumpName(startLump)); M_TranslatePath(cachedMapDataFile, cachedMapDataFile, FILENAME_T_MAXLEN); strncat(cachedMapDataFile, ".dcm", FILENAME_T_MAXLEN); // Create an archivedmap record and link it to our list // of available maps. dam = createArchivedMap(mapID, headPtr, cachedMapDataFile); addArchivedMap(dam); freeMapLumpInfoList(headPtr); } // Load it in. if(!dam->lastLoadAttemptFailed) { gamemap_t *map = NULL; ded_mapinfo_t *mapInfo; if(mapCache && dam->cachedMapFound) { // Attempt to load the cached map data. if(loadMap(&map, dam)) loadedOK = true; } else { // Try a JIT conversion with the help of a plugin. if(convertMap(&map, dam)) loadedOK = true; } if(loadedOK) { ded_sky_t* skyDef = NULL; // Do any initialization/error checking work we need to do. // Must be called before we go any further. P_InitUnusedMobjList(); // Must be called before any mobjs are spawned. R_InitLinks(map); R_BuildSectorLinks(map); // Init blockmap for searching subsectors. P_BuildSubsectorBlockMap(map); // Init the watched object lists. memset(&map->watchedPlaneList, 0, sizeof(map->watchedPlaneList)); memset(&map->movingSurfaceList, 0, sizeof(map->movingSurfaceList)); memset(&map->decoratedSurfaceList, 0, sizeof(map->decoratedSurfaceList)); strncpy(map->mapID, dam->identifier, 8); strncpy(map->uniqueID, P_GenerateUniqueMapID(dam->identifier), sizeof(map->uniqueID)); // See what mapinfo says about this map. mapInfo = Def_GetMapInfo(map->mapID); if(!mapInfo) mapInfo = Def_GetMapInfo("*"); if(mapInfo) { skyDef = Def_GetSky(mapInfo->skyID); if(!skyDef) skyDef = &mapInfo->sky; } R_SetupSky(skyDef); // Setup accordingly. if(mapInfo) { map->globalGravity = mapInfo->gravity; map->ambientLightLevel = mapInfo->ambient * 255; } else { // No map info found, so set some basic stuff. map->globalGravity = 1.0f; map->ambientLightLevel = 0; } // \todo should be called from P_LoadMap() but R_InitMap requires the // currentMap to be set first. P_SetCurrentMap(map); R_InitSectorShadows(); { uint startTime = Sys_GetRealTime(); R_InitSkyFix(); // How much time did we spend? VERBOSE(Con_Message (" InitialSkyFix: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } } } if(!loadedOK) dam->lastLoadAttemptFailed = true; return loadedOK; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_vertex.c0000644000175000017500000000540711357170242022737 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_vertex.c: World vertexes. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Update the vertex, property is selected by DMU_* name. */ boolean Vertex_SetProperty(vertex_t *vtx, const setargs_t *args) { // Vertices are not writable through DMU. Con_Error("Vertex_SetProperty: Is not writable.\n"); return true; // Continue iteration. } /** * Get the value of a vertex property, selected by DMU_* name. */ boolean Vertex_GetProperty(const vertex_t *vtx, setargs_t *args) { switch(args->prop) { case DMU_X: DMU_GetValue(DMT_VERTEX_POS, &vtx->V_pos[VX], args, 0); break; case DMU_Y: DMU_GetValue(DMT_VERTEX_POS, &vtx->V_pos[VY], args, 0); break; case DMU_XY: DMU_GetValue(DMT_VERTEX_POS, &vtx->V_pos[VX], args, 0); DMU_GetValue(DMT_VERTEX_POS, &vtx->V_pos[VY], args, 1); break; default: Con_Error("Vertex_GetProperty: Has no property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/net_demo.c0000644000175000017500000004526311357170242022701 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA * * \bug - Demo playback is broken -> http://sourceforge.net/tracker/index.php?func=detail&aid=1693198&group_id=74815&atid=542099 */ /** * net_demo.c: Demos * * Handling of demo recording and playback. * Opening of, writing to, reading from and closing of demo files. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_render.h" #include "de_misc.h" #include "de_play.h" #include "r_main.h" #include "gl_main.h" // For r_framecounter. // MACROS ------------------------------------------------------------------ #define DEMOTIC SECONDS_TO_TICKS(demoTime) // Local Camera flags. #define LCAMF_ONGROUND 0x1 #define LCAMF_FOV 0x2 // FOV has changed (short). #define LCAMF_CAMERA 0x4 // Camera mode. // TYPES ------------------------------------------------------------------- #pragma pack(1) typedef struct { //ushort angle; //short lookdir; ushort length; } demopacket_header_t; #pragma pack() typedef struct { boolean first; int begintime; boolean canwrite; // False until Handshake packet. int cameratimer; int pausetime; float fov; } demotimer_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(DemoLump); D_CMD(PauseDemo); D_CMD(PlayDemo); D_CMD(RecordDemo); D_CMD(StopDemo); void Demo_WriteLocalCamera(int plnum); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern float netConnectTime; // PUBLIC DATA DEFINITIONS ------------------------------------------------- char demoPath[128] = "demo\\"; //int demotic = 0; LZFILE *playdemo = 0; int playback = false; int viewangleDelta = 0; float lookdirDelta = 0; float posDelta[3]; float demoFrameZ, demoZ; boolean demoOnGround; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static demotimer_t writeInfo[DDMAXPLAYERS]; static demotimer_t readInfo; static float startFOV; static int demoStartTic; // CODE -------------------------------------------------------------------- void Demo_Register(void) { // Ccmds C_CMD("demolump", "ss", DemoLump); C_CMD("pausedemo", NULL, PauseDemo); C_CMD("playdemo", "s", PlayDemo); C_CMD("recorddemo", NULL, RecordDemo); C_CMD("stopdemo", NULL, StopDemo); } void Demo_Init(void) { // Make sure the demo path is there. M_CheckPath(demoPath); } /** * Open a demo file and begin recording. * Returns false if the recording can't be begun. */ boolean Demo_BeginRecording(const char* fileName, int plrNum) { filename_t buf; client_t* cl = &clients[plrNum]; player_t* plr = &ddPlayers[plrNum]; // Is a demo already being recorded for this client? if(cl->recording || playback || (isDedicated && !plrNum) || !plr->shared.inGame) return false; // Compose the real file name. strncpy(buf, demoPath, FILENAME_T_MAXLEN); strncat(buf, fileName, FILENAME_T_MAXLEN); M_TranslatePath(buf, buf, FILENAME_T_MAXLEN); // Open the demo file. cl->demo = lzOpen(buf, "wp"); if(!cl->demo) return false; // Couldn't open it! cl->recording = true; cl->recordPaused = false; writeInfo[plrNum].first = true; writeInfo[plrNum].canwrite = false; writeInfo[plrNum].cameratimer = 0; writeInfo[plrNum].fov = -1; // Must be written in the first packet. if(isServer) { // Playing demos alters gametic. This'll make sure we're going to // get updates. clients[0].lastTransmit = -1; // Servers need to send a handshake packet. // It only needs to recorded in the demo file, though. allowSending = false; Sv_Handshake(plrNum, false); // Enable sending to network. allowSending = true; } else { // Clients need a Handshake packet. // Request a new one from the server. Cl_SendHello(); } // The operation is a success. return true; } void Demo_PauseRecording(int playerNum) { client_t *cl = clients + playerNum; // A demo is not being recorded? if(!cl->recording || cl->recordPaused) return; // All packets will be written for the same tic. writeInfo[playerNum].pausetime = SECONDS_TO_TICKS(demoTime); cl->recordPaused = true; } /** * Resumes a paused recording. */ void Demo_ResumeRecording(int playerNum) { client_t *cl = clients + playerNum; // Not recording or not paused? if(!cl->recording || !cl->recordPaused) return; Demo_WriteLocalCamera(playerNum); cl->recordPaused = false; // When the demo is read there can't be a jump in the timings, so we // have to make it appear the pause never happened; begintime is // moved forwards. writeInfo[playerNum].begintime += DEMOTIC - writeInfo[playerNum].pausetime; } /** * Stop recording a demo. */ void Demo_StopRecording(int playerNum) { client_t *cl = clients + playerNum; // A demo is not being recorded? if(!cl->recording) return; // Close demo file. lzClose(cl->demo); cl->demo = 0; cl->recording = false; } void Demo_WritePacket(int playerNum) { LZFILE *file; demopacket_header_t hdr; demotimer_t *inf = writeInfo + playerNum; byte ptime; if(playerNum == NSP_BROADCAST) { Demo_BroadcastPacket(); return; } // Is this client recording? if(!clients[playerNum].recording) return; if(!inf->canwrite) { if(netBuffer.msg.type != PSV_HANDSHAKE) return; // The handshake has arrived. Now we can begin writing. inf->canwrite = true; } if(clients[playerNum].recordPaused) { // Some types of packet are not written in record-paused mode. if(netBuffer.msg.type == PSV_SOUND || netBuffer.msg.type == DDPT_MESSAGE) return; } // This counts as an update. (We know the client is alive.) clients[playerNum].updateCount = UPDATECOUNT; file = clients[playerNum].demo; #if _DEBUG if(!file) Con_Error("Demo_WritePacket: No demo file!\n"); #endif if(!inf->first) { ptime = (clients[playerNum].recordPaused ? inf->pausetime : DEMOTIC) - inf->begintime; } else { ptime = 0; inf->first = false; inf->begintime = DEMOTIC; } lzWrite(&ptime, 1, file); // The header. #if _DEBUG if(netBuffer.length >= sizeof(hdr.length)) Con_Error("Demo_WritePacket: Write buffer too large!\n"); #endif hdr.length = (ushort) 1 + netBuffer.length; lzWrite(&hdr, sizeof(hdr), file); // Write the packet itself. lzPutC(netBuffer.msg.type, file); lzWrite(netBuffer.msg.data, (long) netBuffer.length, file); } void Demo_BroadcastPacket(void) { int i; // Write packet to all recording demo files. for(i = 0; i < DDMAXPLAYERS; ++i) Demo_WritePacket(i); } boolean Demo_BeginPlayback(const char* fileName) { filename_t buf; int i; if(playback) return false; // Already in playback. if(netGame || isClient) return false; // Can't do it. // Check that we aren't recording anything. for(i = 0; i < DDMAXPLAYERS; ++i) if(clients[i].recording) return false; // Open the demo file. dd_snprintf(buf, FILENAME_T_MAXLEN, "%s%s", Dir_IsAbsolute(fileName) ? "" : demoPath, fileName); M_TranslatePath(buf, buf, FILENAME_T_MAXLEN); playdemo = lzOpen(buf, "rp"); if(!playdemo) return false; // Failed to open the file. // OK, let's begin the demo. playback = true; isServer = false; isClient = true; readInfo.first = true; viewangleDelta = 0; lookdirDelta = 0; demoFrameZ = 1; demoZ = 0; startFOV = fieldOfView; demoStartTic = DEMOTIC; memset(posDelta, 0, sizeof(posDelta)); // Start counting frames from here. if(ArgCheck("-timedemo")) r_framecounter = 0; return true; } void Demo_StopPlayback(void) { float diff; if(!playback) return; Con_Message("Demo was %.2f seconds (%i tics) long.\n", (DEMOTIC - demoStartTic) / (float) TICSPERSEC, DEMOTIC - demoStartTic); playback = false; lzClose(playdemo); playdemo = 0; fieldOfView = startFOV; Net_StopGame(); if(ArgCheck("-timedemo")) { diff = Sys_GetSeconds() - netConnectTime; if(!diff) diff = 1; // Print summary and exit. Con_Message("Timedemo results: "); Con_Message("%i game tics in %.1f seconds\n", r_framecounter, diff); Con_Message("%f FPS\n", r_framecounter / diff); Sys_Quit(); } // "Play demo once" mode? if(ArgCheck("-playdemo")) Sys_Quit(); } boolean Demo_ReadPacket(void) { static byte ptime; int nowtime = DEMOTIC; demopacket_header_t hdr; if(!playback) return false; if(lzEOF(playdemo)) { Demo_StopPlayback(); // Tell the Game the demo has ended. if(gx.NetWorldEvent) gx.NetWorldEvent(DDWE_DEMO_END, 0, 0); return false; } if(readInfo.first) { readInfo.first = false; readInfo.begintime = nowtime; ptime = lzGetC(playdemo); } // Check if the packet can be read. if(Net_TimeDelta(nowtime - readInfo.begintime, ptime) < 0) return false; // Can't read yet. // Read the packet. lzRead(&hdr, sizeof(hdr), playdemo); // Get the packet. netBuffer.length = hdr.length - 1; netBuffer.player = 0; // From the server. netBuffer.msg.id = 0; netBuffer.msg.type = lzGetC(playdemo); lzRead(netBuffer.msg.data, (long) netBuffer.length, playdemo); netBuffer.cursor = netBuffer.msg.data; /*#if _DEBUG Con_Printf("RDP: pt=%i ang=%i ld=%i len=%i type=%i\n", ptime, hdr.angle, hdr.lookdir, hdr.length, netBuffer.msg.type); #endif*/ // Read the next packet time. ptime = lzGetC(playdemo); return true; } /** * Writes a view angle and coords packet. Doesn't send the packet outside. */ void Demo_WriteLocalCamera(int plrNum) { player_t* plr = &ddPlayers[plrNum]; ddplayer_t* ddpl = &plr->shared; mobj_t* mo = ddpl->mo; fixed_t x, y, z; byte flags; boolean incfov = (writeInfo[plrNum].fov != fieldOfView); const viewdata_t* viewData = R_ViewData(plrNum); if(!mo) return; Msg_Begin(clients[plrNum].recordPaused ? PKT_DEMOCAM_RESUME : PKT_DEMOCAM); // Flags. flags = (mo->pos[VZ] <= mo->floorZ ? LCAMF_ONGROUND : 0) // On ground? | (incfov ? LCAMF_FOV : 0); if(ddpl->flags & DDPF_CAMERA) { flags &= ~LCAMF_ONGROUND; flags |= LCAMF_CAMERA; } Msg_WriteByte(flags); // Coordinates. x = FLT2FIX(mo->pos[VX]); y = FLT2FIX(mo->pos[VY]); Msg_WriteShort(x >> 16); Msg_WriteByte(x >> 8); Msg_WriteShort(y >> 16); Msg_WriteByte(y >> 8); z = FLT2FIX(mo->pos[VZ] + viewData->current.pos[VZ]); Msg_WriteShort(z >> 16); Msg_WriteByte(z >> 8); Msg_WriteShort(mo->angle /*ddpl->clAngle*/ >> 16); /* $unifiedangles */ Msg_WriteShort(ddpl->lookDir / 110 * DDMAXSHORT /* $unifiedangles */); // Field of view is optional. if(incfov) { Msg_WriteShort(fieldOfView / 180 * DDMAXSHORT); writeInfo[plrNum].fov = fieldOfView; } Net_SendBuffer(plrNum, SPF_DONT_SEND); } /** * Read a view angle and coords packet. NOTE: The Z coordinate of the * camera is the real eye Z coordinate, not the player mobj's Z coord. */ void Demo_ReadLocalCamera(void) { ddplayer_t *pl = &ddPlayers[consolePlayer].shared; mobj_t *mo = pl->mo; int flags; float z; int intertics = LOCALCAM_WRITE_TICS; int dang; float dlook; if(!mo) return; if(netBuffer.msg.type == PKT_DEMOCAM_RESUME) { intertics = 1; } // Framez keeps track of the current camera Z. demoFrameZ += demoZ; flags = Msg_ReadByte(); demoOnGround = (flags & LCAMF_ONGROUND) != 0; if(flags & LCAMF_CAMERA) pl->flags |= DDPF_CAMERA; else pl->flags &= ~DDPF_CAMERA; // X and Y coordinates are easy. Calculate deltas to the new coords. posDelta[VX] = (FIX2FLT((Msg_ReadShort() << 16) + (Msg_ReadByte() << 8)) - mo->pos[VX]) / intertics; posDelta[VY] = (FIX2FLT((Msg_ReadShort() << 16) + (Msg_ReadByte() << 8)) - mo->pos[VY]) / intertics; // The Z coordinate is a bit trickier. We are tracking the *camera's* // Z coordinate (z+viewheight), not the player mobj's Z. z = FIX2FLT((Msg_ReadShort() << 16) + (Msg_ReadByte() << 8)); posDelta[VZ] = (z - demoFrameZ) / LOCALCAM_WRITE_TICS; // View angles. dang = Msg_ReadShort() << 16; dlook = Msg_ReadShort() * 110.0f / DDMAXSHORT; // FOV included? if(flags & LCAMF_FOV) fieldOfView = Msg_ReadShort() * 180.0f / DDMAXSHORT; if(intertics == 1 || demoFrameZ == 1) { // Immediate change. /*pl->clAngle = dang; pl->clLookDir = dlook;*/ pl->mo->angle = dang; pl->lookDir = dlook; /* $unifiedangles */ viewangleDelta = 0; lookdirDelta = 0; } else { viewangleDelta = (dang - pl->mo->angle) / intertics; lookdirDelta = (dlook - pl->lookDir) / intertics; /* $unifiedangles */ } // The first one gets no delta. if(demoFrameZ == 1) { // This must be the first democam packet. // Initialize framez to the height we just read. demoFrameZ = z; posDelta[VZ] = 0; } // demo_z is the offset to demo_framez for the current tic. // It is incremented by pos_delta[VZ] every tic. demoZ = 0; if(intertics == 1) { // Instantaneous move. R_ResetViewer(); demoFrameZ = z; Cl_MoveLocalPlayer(posDelta[VX], posDelta[VY], z, demoOnGround); posDelta[VX] = posDelta[VY] = posDelta[VZ] = 0; } } /** * Called once per tic. */ void Demo_Ticker(timespan_t time) { static trigger_t fixed = { 1 / 35.0, 0 }; if(!M_RunTrigger(&fixed, time)) return; // Only playback is handled. if(playback) { player_t *plr = &ddPlayers[consolePlayer]; ddplayer_t *ddpl = &plr->shared; ddpl->mo->angle += viewangleDelta; ddpl->lookDir += lookdirDelta; /* $unifiedangles */ // Move player (i.e. camera). Cl_MoveLocalPlayer(posDelta[VX], posDelta[VY], demoFrameZ + demoZ, demoOnGround); // Interpolate camera Z offset (to framez). demoZ += posDelta[VZ]; } else { int i; for(i = 0; i < DDMAXPLAYERS; ++i) { player_t *plr = &ddPlayers[i]; ddplayer_t *ddpl = &plr->shared; client_t *cl = &clients[i]; if(ddpl->inGame && cl->recording && !cl->recordPaused && ++writeInfo[i].cameratimer >= LOCALCAM_WRITE_TICS) { // It's time to write local view angles and coords. writeInfo[i].cameratimer = 0; Demo_WriteLocalCamera(i); } } } } D_CMD(PlayDemo) { Con_Printf("Playing demo \"%s\"...\n", argv[1]); return Demo_BeginPlayback(argv[1]); } D_CMD(RecordDemo) { int plnum = consolePlayer; if(argc == 3 && isClient) { Con_Printf("Clients can only record the consolePlayer.\n"); return true; } if(isClient && argc != 2) { Con_Printf("Usage: %s (fileName)\n", argv[0]); return true; } if(isServer && (argc < 2 || argc > 3)) { Con_Printf("Usage: %s (fileName) (plnum)\n", argv[0]); Con_Printf("(plnum) is the player which will be recorded.\n"); return true; } if(argc == 3) plnum = atoi(argv[2]); Con_Printf("Recording demo of player %i to \"%s\".\n", plnum, argv[1]); return Demo_BeginRecording(argv[1], plnum); } D_CMD(PauseDemo) { int plnum = consolePlayer; if(argc >= 2) plnum = atoi(argv[1]); if(!clients[plnum].recording) { Con_Printf("Not recording for player %i.\n", plnum); return false; } if(clients[plnum].recordPaused) { Demo_ResumeRecording(plnum); Con_Printf("Demo recording of player %i resumed.\n", plnum); } else { Demo_PauseRecording(plnum); Con_Printf("Demo recording of player %i paused.\n", plnum); } return true; } D_CMD(StopDemo) { int plnum = consolePlayer; if(argc > 2) { Con_Printf("Usage: stopdemo (plrnum)\n"); return true; } if(argc == 2) plnum = atoi(argv[1]); if(!playback && !clients[plnum].recording) return true; Con_Printf("Demo %s of player %i stopped.\n", clients[plnum].recording ? "recording" : "playback", plnum); if(playback) { Demo_StopPlayback(); // Tell the Game DLL that the playback was aborted. gx.NetWorldEvent(DDWE_DEMO_END, true, 0); } else Demo_StopRecording(plnum); return true; } /** * Make a demo lump. */ D_CMD(DemoLump) { char buf[64]; memset(buf, 0, sizeof(buf)); strncpy(buf, argv[1], 64); return M_WriteFile(argv[2], buf, 64); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/s_main.c0000644000175000017500000004263711357170242022357 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_main.c: Sound Subsystem * * Interface to the Sfx and Mus modules. * High-level (and exported) sound control. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_system.h" #include "de_graphics.h" #include "de_audio.h" #include "de_misc.h" #include "de_defs.h" #include "r_extres.h" #include "sys_audio.h" // MACROS ------------------------------------------------------------------ BEGIN_PROF_TIMERS() PROF_SOUND_STARTFRAME END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(PlaySound); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- audiodriver_t* audioDriver = NULL; int showSoundInfo = false; int soundMinDist = 256; // No distance attenuation this close. int soundMaxDist = 2025; // Setting these variables is enough to adjust the volumes. // S_StartFrame() will call the actual routines to change the volume // when there are changes. int sfxVolume = 255, musVolume = 255; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean noRndPitch; // CODE -------------------------------------------------------------------- void S_Register(void) { // Cvars C_VAR_INT("sound-volume", &sfxVolume, 0, 0, 255); C_VAR_INT("sound-info", &showSoundInfo, 0, 0, 1); C_VAR_INT("sound-rate", &sfxSampleRate, 0, 11025, 44100); C_VAR_INT("sound-16bit", &sfx16Bit, 0, 0, 1); C_VAR_INT("sound-3d", &sfx3D, 0, 0, 1); C_VAR_FLOAT("sound-reverb-volume", &sfxReverbStrength, 0, 0, 10); // Ccmds C_CMD_FLAGS("playsound", NULL, PlaySound, CMDF_NO_DEDICATED); Mus_Register(); } /** * Initializes the audio driver interfaces. * * @return @c true, if successful. */ boolean S_InitDriver(audiodriver_e drvid) { Con_Printf(" Driver: "); switch(drvid) { case AUDIOD_DUMMY: Con_Printf("Dummy\n"); audioDriver = &audiod_dummy; break; case AUDIOD_SDL_MIXER: Con_Printf("SDLMixer\n"); audioDriver = &audiod_sdlmixer; break; case AUDIOD_OPENAL: Con_Printf("OpenAL\n"); if(!(audioDriver = Sys_LoadAudioDriver("openal"))) return false; break; #ifdef WIN32 case AUDIOD_DSOUND: Con_Printf("DirectSound\n"); if(!(audioDriver = Sys_LoadAudioDriver("directsound"))) return false; break; case AUDIOD_WINMM: Con_Printf("WinMM\n"); if(!(audioDriver = Sys_LoadAudioDriver("winmm"))) return false; break; #endif default: Con_Error("S_InitDriver: Unknown driver id %i.\n", drvid); } // Initialize the audioDriver. return audioDriver->Init(); } /** * Main sound system initialization. Inits both the Sfx and Mus modules. * * @return @c true, if there were no errors. */ boolean S_Init(void) { boolean ok, sfxOK, musOK; if(ArgExists("-nosound")) return true; // First let's set up the drivers. First we much choose which one we // want to use. if(isDedicated || ArgExists("-dummy")) { ok = S_InitDriver(AUDIOD_DUMMY); } else if(ArgExists("-oal")) { ok = S_InitDriver(AUDIOD_OPENAL); } #ifdef WIN32 else if(ArgExists("-dsound")) { // DirectSound with 3D sound support, EAX effects. ok = S_InitDriver(AUDIOD_DSOUND); } else if(ArgExists("-winmm")) { // Windows Multimedia. ok = S_InitDriver(AUDIOD_WINMM); } #endif else { // The default audio driver, sdl_mixer. ok = S_InitDriver(AUDIOD_SDL_MIXER); } // Did we succeed? if(!ok) { Con_Message("S_Init: Driver init failed. Sound is disabled.\n"); return false; } // Disable random pitch changes? noRndPitch = ArgExists("-noRndPitch"); sfxOK = Sfx_Init(); musOK = Mus_Init(); Con_Message("S_Init: %s.\n", sfxOK && musOK ? "OK" : "Errors during initialization."); return (sfxOK && musOK); } /** * Shutdown the whole sound system (Sfx + Mus). */ void S_Shutdown(void) { Sfx_Shutdown(); Mus_Shutdown(); // Finally, close the audio driver. Sys_ShutdownAudioDriver(); audioDriver = NULL; } /** * Must be called before the map is changed. */ void S_MapChange(void) { // Stop everything in the LSM. Sfx_InitLogical(); Sfx_MapChange(); } /** * Stop all channels and music, delete the entire sample cache. */ void S_Reset(void) { Sfx_Reset(); S_StopMusic(); } void S_StartFrame(void) { static int oldMusVolume = -1; #ifdef DD_PROFILE static int i; if(++i > 40) { i = 0; PRINT_PROF( PROF_SOUND_STARTFRAME ); } #endif BEGIN_PROF( PROF_SOUND_STARTFRAME ); if(musVolume != oldMusVolume) { oldMusVolume = musVolume; Mus_SetVolume(musVolume / 255.0f); } // Update all channels (freq, 2D:pan,volume, 3D:position,velocity). Sfx_StartFrame(); Mus_StartFrame(); // Remove stopped sounds from the LSM. Sfx_PurgeLogical(); END_PROF( PROF_SOUND_STARTFRAME ); } void S_EndFrame(void) { Sfx_EndFrame(); } /** * Usually the display player. */ mobj_t* S_GetListenerMobj(void) { return ddPlayers[displayPlayer].shared.mo; } /** * \note freq and volume may be NULL(they will be modified by sound links). * * @param freq May be @c NULL. * @param volume May be @c NULL. */ sfxinfo_t* S_GetSoundInfo(int soundID, float* freq, float* volume) { float dummy = 0; sfxinfo_t* info; int i; if(soundID <= 0) return NULL; if(!freq) freq = &dummy; if(!volume) volume = &dummy; /** * Traverse all links when getting the definition. * (But only up to 10, which is certainly enough and prevents endless * recursion.) Update the sound id at the same time. * The links were checked in Def_Read() so there can't be any bogus ones. */ for(info = &sounds[soundID], i = 0; info->link && i < 10; info = info->link, *freq = (info->linkPitch > 0 ? info->linkPitch / 128.0f : *freq), *volume += (info->linkVolume != -1 ? info->linkVolume / 127.0f : 0), soundID = info - sounds, i++); return info; } /** * @return @c true, if the specified ID is a repeating sound. */ boolean S_IsRepeating(int idFlags) { sfxinfo_t* info; if(idFlags & DDSF_REPEAT) return true; if(!(info = S_GetSoundInfo(idFlags & ~DDSF_FLAG_MASK, NULL, NULL))) return false; else return (info->flags & SF_REPEAT) != 0; } /** * Play a sound on the local system. A public interface. * * \note: Flags can be included in the sound ID number (DDSF_*). * Origin and fixedpos can be both NULL, in which case the sound is played * in 2D and centered. * * @param origin May be @c NULL. * @param fixedPos May be @c NULL. * * @return Non-zero if a sound was started. */ int S_LocalSoundAtVolumeFrom(int soundIdAndFlags, mobj_t* origin, float* fixedPos, float volume) { int soundId = (soundIdAndFlags & ~DDSF_FLAG_MASK); sfxsample_t* sample; sfxinfo_t* info; float freq = 1; int result; boolean isRepeating = false; // A dedicated server never starts any local sounds (only logical // sounds in the LSM). if(isDedicated) return false; if(soundId <= 0 || soundId >= defs.count.sounds.num || sfxVolume <= 0 || volume <= 0) return false; // This won't play... #if _DEBUG if(volume > 1) { Con_Message("S_LocalSoundAtVolumeFrom: Warning! " "Too high volume (%f).\n", volume); } #endif // This is the sound we're going to play. if((info = S_GetSoundInfo(soundId, &freq, &volume)) == NULL) { return false; // Hmm? This ID is not defined. } isRepeating = S_IsRepeating(soundIdAndFlags); // Check the distance (if applicable). if(!(info->flags & SF_NO_ATTENUATION) && !(soundIdAndFlags & DDSF_NO_ATTENUATION)) { // If origin is too far, don't even think about playing the sound. if(P_MobjPointDistancef(S_GetListenerMobj(), origin, fixedPos) > soundMaxDist) return false; } // Load the sample. if((sample = Sfx_Cache(soundId)) == NULL) { if(sfxAvail) { VERBOSE(Con_Message ("S_LocalSoundAtVolumeFrom: Sound %i " "caching failed.\n", soundId)); } return false; } // Random frequency alteration? (Multipliers chosen to match original // sound code.) if(!noRndPitch) { if(info->flags & SF_RANDOM_SHIFT) freq += (RNG_RandFloat() - RNG_RandFloat()) * (7.0f / 255); if(info->flags & SF_RANDOM_SHIFT2) freq += (RNG_RandFloat() - RNG_RandFloat()) * (15.0f / 255); } // If the sound has an exclusion group, either all or the same emitter's // iterations of this sound will stop. if(info->group) { Sfx_StopSoundGroup(info->group, (info->flags & SF_GLOBAL_EXCLUDE)? NULL : origin); } // Let's play it. result = Sfx_StartSound(sample, volume, freq, origin, fixedPos, ((info->flags & SF_NO_ATTENUATION) || (soundIdAndFlags & DDSF_NO_ATTENUATION) ? SF_NO_ATTENUATION : 0) | (isRepeating ? SF_REPEAT : 0) | ((info->flags & SF_DONT_STOP) ? SF_DONT_STOP : 0)); return result; } /** * Plays a sound on the local system at the given volume. * This is a public sound interface. * * @return Non-zero if a sound was started. */ int S_LocalSoundAtVolume(int soundID, mobj_t* origin, float volume) { return S_LocalSoundAtVolumeFrom(soundID, origin, NULL, volume); } /** * Plays a sound on the local system from the given origin. * This is a public sound interface. * * @return Non-zero if a sound was started. */ int S_LocalSound(int soundID, mobj_t* origin) { // Play local sound at max volume. return S_LocalSoundAtVolumeFrom(soundID, origin, NULL, 1); } /** * Plays a sound on the local system at a give distance from listener. * This is a public sound interface. * * @return Non-zero if a sound was started. */ int S_LocalSoundFrom(int soundID, float* fixedPos) { return S_LocalSoundAtVolumeFrom(soundID, NULL, fixedPos, 1); } /** * Play a world sound. All players in the game will hear it. * * @return Non-zero if a sound was started. */ int S_StartSound(int soundID, mobj_t* origin) { // The sound is audible to everybody. Sv_Sound(soundID, origin, SVSF_TO_ALL); Sfx_StartLogical(soundID, origin, S_IsRepeating(soundID)); return S_LocalSound(soundID, origin); } /** * Play a world sound. The sound is sent to all players except the one who * owns the origin mobj. The server assumes that the owner of the origin plays * the sound locally, which is done here, in the end of S_StartSoundEx(). * * @param soundId Id of the sound. * @param origin Origin mobj for the sound. * * @return Non-zero if a sound was successfully started. */ int S_StartSoundEx(int soundID, mobj_t* origin) { Sv_Sound(soundID, origin, SVSF_TO_ALL | SVSF_EXCLUDE_ORIGIN); Sfx_StartLogical(soundID, origin, S_IsRepeating(soundID)); return S_LocalSound(soundID, origin); } /** * Play a world sound. All players in the game will hear it. * * @return Non-zero if a sound was started. */ int S_StartSoundAtVolume(int soundID, mobj_t* origin, float volume) { Sv_SoundAtVolume(soundID, origin, volume, SVSF_TO_ALL); Sfx_StartLogical(soundID, origin, S_IsRepeating(soundID)); // The sound is audible to everybody. return S_LocalSoundAtVolume(soundID, origin, volume); } /** * Play a player sound. Only the specified player will hear it. * * @return Non-zero if a sound was started (always). */ int S_ConsoleSound(int soundID, mobj_t* origin, int targetConsole) { Sv_Sound(soundID, origin, targetConsole); // If it's for us, we can hear it. if(targetConsole == consolePlayer) { S_LocalSound(soundID, origin); } return true; } /** * @param soundID @c 0 = stops all sounds of the origin. * @param origin @c NULL = stops all sounds with the ID. * Otherwise both ID and origin must match. */ void S_StopSound(int soundID, mobj_t* emitter) { // Sfx provides a routine for this. Sfx_StopSound(soundID, emitter); // Notify the LSM. if(Sfx_StopLogical(soundID, emitter)) { // In netgames, the server is responsible for telling clients // when to stop sounds. The LSM will tell us if a sound was // stopped somewhere in the world. Sv_StopSound(soundID, emitter); } } /** * Is an instance of the sound being played using the given emitter? * If sound_id is zero, returns true if the source is emitting any sounds. * An exported function. * * @return Non-zero if a sound is playing. */ int S_IsPlaying(int soundID, mobj_t* emitter) { // The Logical Sound Manager (under Sfx) provides a routine for this. return Sfx_IsPlaying(soundID, emitter); } /** * Start a song based on its number. * * @return @c NULL, if the ID exists. */ int S_StartMusicNum(int id, boolean looped) { ded_music_t* def; if(id < 0 || id >= defs.count.music.num) return false; def = &defs.music[id]; // Don't play music if the volume is at zero. if(isDedicated) return true; if(verbose) Con_Message("S_StartMusic: %s.\n", def->id); return Mus_Start(def, looped); } /** * @return @c NULL, if the song is found. */ int S_StartMusic(const char* musicID, boolean looped) { int idx = Def_GetMusicNum(musicID); if(idx < 0) { Con_Message("S_StartMusic: song %s not defined.\n", musicID); return false; } return S_StartMusicNum(idx, looped); } /** * Stops playing a song. */ void S_StopMusic(void) { Mus_Stop(); } /** * Change paused state of the current music. */ void S_PauseMusic(boolean paused) { Mus_Pause(paused); } /** * Draws debug information on-screen. */ void S_Drawer(void) { if(!showSoundInfo) return; // Go into screen projection mode. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); Sfx_DebugInfo(); // Back to the original. glMatrixMode(GL_PROJECTION); glPopMatrix(); } /** * Console command for playing a (local) sound effect. */ D_CMD(PlaySound) { int id = 0; float volume = 1; float fixedPos[3]; int p; boolean useFixedPos = false; if(argc < 2) { Con_Printf("Usage: %s (id) (volume) at (x) (y) (z)\n", argv[0]); Con_Printf("(volume) must be in 0..1, but may be omitted.\n"); Con_Printf("'at (x) (y) (z)' may also be omitted.\n"); Con_Printf("The sound is always played locally.\n"); return true; } // The sound ID is always first. id = Def_GetSoundNum(argv[1]); // The second argument may be a volume. if(argc >= 3 && stricmp(argv[2], "at")) { volume = strtod(argv[2], NULL); p = 3; } else { p = 2; } if(argc >= p + 4 && !stricmp(argv[p], "at")) { useFixedPos = true; fixedPos[VX] = strtod(argv[p + 1], NULL); fixedPos[VY] = strtod(argv[p + 2], NULL); fixedPos[VZ] = strtod(argv[p + 3], NULL); } // Check that the volume is valid. if(volume <= 0) return true; if(volume > 1) volume = 1; if(useFixedPos) S_LocalSoundAtVolumeFrom(id, NULL, fixedPos, volume); else S_LocalSoundAtVolume(id, NULL, volume); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_pinit.c0000644000175000017500000001614111357170242022672 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_pinit.c: Portable Engine Initialization * * Platform independent routines for initializing the engine. */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_play.h" #include "de_refresh.h" #include "de_network.h" #include "de_misc.h" #include "def_main.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- /* * The game imports and exports. */ game_import_t __gi; game_export_t __gx; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- int DD_CheckArg(char* tag, const char** value) { int i = ArgCheck(tag); const char* next = ArgNext(); if(!i) return 0; if(value && next) *value = next; return 1; } void DD_ErrorBox(boolean error, char* format, ...) { char buff[200]; va_list args; va_start(args, format); dd_vsnprintf(buff, sizeof(buff), format, args); va_end(args); #ifdef WIN32 suspendMsgPump = true; MessageBox(NULL, (LPCTSTR) buff, (LPCTSTR) ("Doomsday " DOOMSDAY_VERSION_TEXT), (UINT) (MB_OK | (error ? MB_ICONERROR : MB_ICONWARNING))); suspendMsgPump = false; #endif #ifdef UNIX fputs(buff, stderr); #endif } /** * Compose the title for the main window. */ void DD_ComposeMainWindowTitle(char* title) { if(__gx.GetVariable) { char* gameName = (char*) __gx.GetVariable(DD_GAME_ID); sprintf(title, "Doomsday " DOOMSDAY_VERSION_TEXT "%s : %s", (isDedicated? " (Dedicated)" : ""), gameName); } else { sprintf(title, "Doomsday " DOOMSDAY_VERSION_TEXT "%s", (isDedicated? " (Dedicated)" : "")); } } void SetGameImports(game_import_t* imp) { memset(imp, 0, sizeof(*imp)); imp->apiSize = sizeof(*imp); imp->version = DOOMSDAY_VERSION; // Data. imp->mobjInfo = &mobjInfo; imp->states = &states; imp->sprNames = &sprNames; imp->text = &texts; imp->validCount = &validCount; } void DD_InitAPI(void) { GETGAMEAPI GetGameAPI = app.GetGameAPI; game_export_t* gameExPtr; // Put the imported stuff into the imports. SetGameImports(&__gi); memset(&__gx, 0, sizeof(__gx)); gameExPtr = GetGameAPI(&__gi); memcpy(&__gx, gameExPtr, MIN_OF(sizeof(__gx), gameExPtr->apiSize)); } void DD_InitCommandLine(const char* cmdLine) { ArgInit(cmdLine); // Register some abbreviations for command line options. ArgAbbreviate("-game", "-g"); ArgAbbreviate("-gl", "-r"); // As in (R)enderer... ArgAbbreviate("-defs", "-d"); ArgAbbreviate("-width", "-w"); ArgAbbreviate("-height", "-h"); ArgAbbreviate("-winsize", "-wh"); ArgAbbreviate("-bpp", "-b"); ArgAbbreviate("-window", "-wnd"); ArgAbbreviate("-nocenter", "-noc"); ArgAbbreviate("-paltex", "-ptx"); ArgAbbreviate("-file", "-f"); ArgAbbreviate("-maxZone", "-mem"); ArgAbbreviate("-config", "-cfg"); ArgAbbreviate("-parse", "-p"); ArgAbbreviate("-cparse", "-cp"); ArgAbbreviate("-command", "-cmd"); ArgAbbreviate("-fontdir", "-fd"); ArgAbbreviate("-modeldir", "-md"); ArgAbbreviate("-basedir", "-bd"); ArgAbbreviate("-stdbasedir", "-sbd"); ArgAbbreviate("-userdir", "-ud"); ArgAbbreviate("-texdir", "-td"); ArgAbbreviate("-texdir2", "-td2"); ArgAbbreviate("-anifilter", "-ani"); ArgAbbreviate("-verbose", "-v"); } /** * Sets the level of verbosity that was requested using the -verbose * option(s). */ void DD_Verbosity(void) { verbose = ArgExists("-verbose"); } /** * Called early on during the startup process so that we can get the console * online ready for printing ASAP. */ boolean DD_EarlyInit(void) { const char* outFileName = "doomsday.out"; // We'll redirect stdout to a log file. DD_CheckArg("-out", &outFileName); outFile = fopen(outFileName, "w"); if(!outFile) { DD_ErrorBox(false, "Couldn't open message output file."); } else { setbuf(outFile, NULL); // Don't buffer much. // Determine the requested degree of verbosity. DD_Verbosity(); // Get the console online ASAP. if(!Con_Init()) { DD_ErrorBox(true, "Error initializing console."); } else { Con_Message("Executable: " DOOMSDAY_VERSIONTEXT ".\n"); // Print the used command line. if(verbose) { int p; Con_Message("Command line (%i strings):\n", Argc()); for(p = 0; p < Argc(); ++p) Con_Message(" %i: %s\n", p, Argv(p)); } } } // Bring the window manager online. Sys_InitWindowManager(); return true; } /** * This is called from DD_Shutdown(). */ void DD_ShutdownAll(void) { int i; Con_Shutdown(); DD_ShutdownHelp(); Zip_Shutdown(); #ifdef WIN32 // Enables Alt-Tab, Alt-Esc, Ctrl-Alt-Del. SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, FALSE, 0, 0); #endif // Stop all demo recording. for(i = 0; i < DDMAXPLAYERS; ++i) Demo_StopRecording(i); P_ControlShutdown(); Sv_Shutdown(); R_Shutdown(); Def_Destroy(); F_ShutdownDirec(); ArgShutdown(); Z_Shutdown(); Sys_ShutdownWindowManager(); // Close the message output file. if(outFile) { fclose(outFile); outFile = NULL; } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/s_sfx.c0000644000175000017500000010537111357170242022226 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_sfx.c: Sound Effects */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_play.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_audio.h" #include "de_misc.h" #include "sys_audio.h" // MACROS ------------------------------------------------------------------ #define SFX_MAX_CHANNELS (64) #define SFX_LOWEST_PRIORITY (-1000) #define UPDATE_TIME (2.0/TICSPERSEC) // Seconds. // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void Sfx_3DMode(boolean activate); void Sfx_SampleFormat(int newBits, int newRate); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // SFX playback functions loaded from a sound driver plugin. extern audiodriver_t audiodExternal; extern audiointerface_sfx_t audiodExternalISFX; // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean sfxAvail = false; int sfxMaxChannels = 16; int sfxDedicated2D = 4; float sfxReverbStrength = 1; int sfxBits = 8; int sfxRate = 11025; // Console variables: int sfx3D = false; int sfx16Bit = false; int sfxSampleRate = 11025; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // The interfaces. static audiointerface_sfx_generic_t* iSFX = NULL; static int numChannels = 0; static sfxchannel_t* channels; static mobj_t* listener; static sector_t* listenerSector = NULL; static thread_t refreshHandle; static volatile boolean allowRefresh, refreshing; static byte refMonitor = 0; // CODE -------------------------------------------------------------------- /** * This is a high-priority thread that periodically checks if the channels * need to be updated with more data. The thread terminates when it notices * that the channels have been destroyed. The Sfx audioDriver maintains a 250ms * buffer for each channel, which means the refresh must be done often * enough to keep them filled. * * \fixme Use a real mutex, will you? */ int C_DECL Sfx_ChannelRefreshThread(void* parm) { int i; sfxchannel_t* ch; // We'll continue looping until the Sfx module is shut down. while(sfxAvail && channels) { // The bit is swapped on each refresh (debug info). refMonitor ^= 1; if(allowRefresh) { // Do the refresh. refreshing = true; for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || !(ch->buffer->flags & SFXBF_PLAYING)) continue; iSFX->Refresh(ch->buffer); } refreshing = false; // Let's take a nap. Sys_Sleep(200); } else { // Refreshing is not allowed, so take a shorter nap while // waiting for allowRefresh. Sys_Sleep(150); } } // Time to end this thread. return 0; } /** * Enabling refresh is simple: the refresh thread is resumed. When * disabling refresh, first make sure a new refresh doesn't begin (using * allowRefresh). We still have to see if a refresh is being made and wait * for it to stop. Then we can suspend the refresh thread. */ void Sfx_AllowRefresh(boolean allow) { if(!sfxAvail) return; if(allowRefresh == allow) return; // No change. allowRefresh = allow; // If we're denying refresh, let's make sure that if it's currently // running, we don't continue until it has stopped. if(!allow) { while(refreshing) Sys_Sleep(0); } // Sys_SuspendThread(refreshHandle, !allow); } /** * Stop all sounds of the group. If an emitter is specified, only it's * sounds are checked. */ void Sfx_StopSoundGroup(int group, mobj_t* emitter) { int i; sfxchannel_t* ch; if(!sfxAvail) return; for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || !(ch->buffer->flags & SFXBF_PLAYING) || ch->buffer->sample->group != group || (emitter && ch->emitter != emitter)) continue; // This channel must stop. iSFX->Stop(ch->buffer); } } /** * Stops all channels that are playing the specified sound. * * @param id @c 0 = all sounds are stopped. * @param emitter If not @c NULL, then the channel's emitter mobj * must match it. * * @return The number of samples stopped. */ int Sfx_StopSound(int id, mobj_t* emitter) { int i, stopCount = 0; sfxchannel_t* ch; if(!sfxAvail) return false; for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || !(ch->buffer->flags & SFXBF_PLAYING) || (id && ch->buffer->sample->id != id) || (emitter && ch->emitter != emitter)) continue; // Can it be stopped? if(ch->buffer->flags & SFXBF_DONT_STOP) { // The emitter might get destroyed... ch->emitter = NULL; ch->flags |= SFXCF_NO_UPDATE | SFXCF_NO_ORIGIN; continue; } // This channel must be stopped! iSFX->Stop(ch->buffer); ++stopCount; } return stopCount; } #if 0 // Currently unused. int Sfx_IsPlaying(int id, mobj_t* emitter) { int i; sfxchannel_t* ch; if(!sfxAvail) return false; for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || !(ch->buffer->flags & SFXBF_PLAYING) || ch->emitter != emitter || id && ch->buffer->sample->id != id) continue; // Once playing, repeating sounds don't stop. if(ch->buffer->flags & SFXBF_REPEAT) return true; // Check time. The flag is updated after a slight delay // (only at refresh). if(Sys_GetTime() - ch->starttime < ch->buffer->sample->numsamples / (float) ch->buffer->freq * TICSPERSEC) return true; } return false; } #endif /** * The specified sample will soon no longer exist. All channel buffers * loaded with the sample will be reset. */ void Sfx_UnloadSoundID(int id) { int i; sfxchannel_t* ch; if(!sfxAvail) return; BEGIN_COP; for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || !ch->buffer->sample || ch->buffer->sample->id != id) continue; // Stop and unload. iSFX->Reset(ch->buffer); } END_COP; } /** * @return The number of channels the sound is playing on. */ int Sfx_CountPlaying(int id) { int i = 0, count = 0; sfxchannel_t* ch = channels; if(!sfxAvail) return 0; for(; i < numChannels; i++, ch++) { if(!ch->buffer || !ch->buffer->sample || ch->buffer->sample->id != id || !(ch->buffer->flags & SFXBF_PLAYING)) continue; count++; } return count; } /** * The priority of a sound is affected by distance, volume and age. */ float Sfx_Priority(mobj_t* emitter, float* fixPos, float volume, int startTic) { // In five seconds all priority of a sound is gone. float timeoff = 1000 * (Sys_GetTime() - startTic) / (5.0f * TICSPERSEC); float orig[3]; if(!listener || (!emitter && !fixPos)) { // The sound does not have an origin. return 1000 * volume - timeoff; } // The sound has an origin, base the points on distance. if(emitter) { memcpy(orig, emitter->pos, sizeof(orig)); } else { // No emitter mobj, use the fixed source position. memcpy(orig, fixPos, sizeof(orig)); } return 1000 * volume - P_MobjPointDistancef(listener, 0, orig) / 2 - timeoff; } /** * Calculate priority points for a sound playing on a channel. * They are used to determine which sounds can be cancelled by new sounds. * Zero is the lowest priority. */ float Sfx_ChannelPriority(sfxchannel_t* ch) { if(!ch->buffer || !(ch->buffer->flags & SFXBF_PLAYING)) return SFX_LOWEST_PRIORITY; if(ch->flags & SFXCF_NO_ORIGIN) return Sfx_Priority(0, 0, ch->volume, ch->startTime); // ch->pos is set to emitter->xyz during updates. return Sfx_Priority(0, ch->pos, ch->volume, ch->startTime); } /** * @return The actual 3D coordinates of the listener. */ void Sfx_GetListenerXYZ(float* pos) { if(!listener) return; // \fixme Make it exactly eye-level! (viewheight). pos[VX] = listener->pos[VX]; pos[VY] = listener->pos[VY]; pos[VZ] = listener->pos[VZ] + listener->height - 5; } /** * Updates the channel buffer's properties based on 2D/3D position * calculations. Listener might be NULL. Sounds emitted from the listener * object are considered to be inside the listener's head. */ void Sfx_ChannelUpdate(sfxchannel_t* ch) { sfxbuffer_t* buf = ch->buffer; float normdist, dist, pan, angle, vec[3]; if(!buf || (ch->flags & SFXCF_NO_UPDATE)) return; // Copy the emitter's position (if any), to the pos coord array. if(ch->emitter) { ch->pos[VX] = ch->emitter->pos[VX]; ch->pos[VY] = ch->emitter->pos[VY]; ch->pos[VZ] = ch->emitter->pos[VZ]; // If this is a mobj, center the Z pos. if(P_IsMobjThinker(ch->emitter->thinker.function)) { // Sounds originate from the center. ch->pos[VZ] += ch->emitter->height / 2; } } // Frequency is common to both 2D and 3D sounds. iSFX->Set(buf, SFXBP_FREQUENCY, ch->frequency); if(buf->flags & SFXBF_3D) { // Volume is affected only by maxvol. iSFX->Set(buf, SFXBP_VOLUME, ch->volume * sfxVolume / 255.0f); if(ch->emitter && ch->emitter == listener) { // Emitted by the listener object. Go to relative position mode // and set the position to (0,0,0). vec[VX] = vec[VY] = vec[VZ] = 0; iSFX->Set(buf, SFXBP_RELATIVE_MODE, true); iSFX->Setv(buf, SFXBP_POSITION, vec); } else { // Use the channel's real position. iSFX->Set(buf, SFXBP_RELATIVE_MODE, false); iSFX->Setv(buf, SFXBP_POSITION, ch->pos); } // If the sound is emitted by the listener, speed is zero. if(ch->emitter && ch->emitter != listener && P_IsMobjThinker(ch->emitter->thinker.function)) { vec[VX] = ch->emitter->mom[MX] * TICSPERSEC; vec[VY] = ch->emitter->mom[MY] * TICSPERSEC; vec[VZ] = ch->emitter->mom[MZ] * TICSPERSEC; iSFX->Setv(buf, SFXBP_VELOCITY, vec); } else { // Not moving. vec[VX] = vec[VY] = vec[VZ] = 0; iSFX->Setv(buf, SFXBP_VELOCITY, vec); } } else { // This is a 2D buffer. if((ch->flags & SFXCF_NO_ORIGIN) || (ch->emitter && ch->emitter == listener)) { dist = 1; pan = 0; } else { // Calculate roll-off attenuation. [.125/(.125+x), x=0..1] dist = P_MobjPointDistancef(listener, 0, ch->pos); if(dist < soundMinDist || (ch->flags & SFXCF_NO_ATTENUATION)) { // No distance attenuation. dist = 1; } else if(dist > soundMaxDist) { // Can't be heard. dist = 0; } else { normdist = (dist - soundMinDist) / (soundMaxDist - soundMinDist); // Apply the linear factor so that at max distance there // really is silence. dist = .125f / (.125f + normdist) * (1 - normdist); } // And pan, too. Calculate angle from listener to emitter. if(listener) { angle = (R_PointToAngle2(listener->pos[VX], listener->pos[VY], ch->pos[VX], ch->pos[VY]) - listener->angle) / (float) ANGLE_MAX *360; // We want a signed angle. if(angle > 180) angle -= 360; // Front half. if(angle <= 90 && angle >= -90) { pan = -angle / 90; } else { // Back half. pan = (angle + (angle > 0 ? -180 : 180)) / 90; // Dampen sounds coming from behind. dist *= (1 + (pan > 0 ? pan : -pan)) / 2; } } else { // No listener mobj? Can't pan, then. pan = 0; } } iSFX->Set(buf, SFXBP_VOLUME, ch->volume * dist * sfxVolume / 255.0f); iSFX->Set(buf, SFXBP_PAN, pan); } } void Sfx_ListenerUpdate(void) { int i; float vec[4]; // No volume means no sound. if(!sfxAvail || !sfx3D || !sfxVolume) return; // Update the listener mobj. listener = S_GetListenerMobj(); if(listener) { // Position. At eye-level. Sfx_GetListenerXYZ(vec); iSFX->Listenerv(SFXLP_POSITION, vec); // Orientation. (0,0) will produce front=(1,0,0) and up=(0,0,1). vec[VX] = listener->angle / (float) ANGLE_MAX *360; vec[VY] = listener->dPlayer ? LOOKDIR2DEG(listener->dPlayer->lookDir) : 0; iSFX->Listenerv(SFXLP_ORIENTATION, vec); // Velocity. The unit is world distance units per second. vec[VX] = listener->mom[MX] * TICSPERSEC; vec[VY] = listener->mom[MY] * TICSPERSEC; vec[VZ] = listener->mom[MZ] * TICSPERSEC; iSFX->Listenerv(SFXLP_VELOCITY, vec); // Reverb effects. Has the current sector changed? if(listenerSector != listener->subsector->sector) { listenerSector = listener->subsector->sector; for(i = 0; i < NUM_REVERB_DATA; ++i) { vec[i] = listenerSector->reverb[i]; if(i == SRD_VOLUME) vec[i] *= sfxReverbStrength; } iSFX->Listenerv(SFXLP_REVERB, vec); } } // Update all listener properties. iSFX->Listener(SFXLP_UPDATE, 0); } void Sfx_ListenerNoReverb(void) { float rev[4] = { 0, 0, 0, 0 }; if(!sfxAvail) return; listenerSector = NULL; iSFX->Listenerv(SFXLP_REVERB, rev); iSFX->Listener(SFXLP_UPDATE, 0); } /** * Stops the sound playing on the channel. * \note Just stopping a buffer doesn't affect refresh. */ void Sfx_ChannelStop(sfxchannel_t* ch) { if(!ch->buffer) return; iSFX->Stop(ch->buffer); } void Sfx_GetChannelPriorities(float* prios) { int i; for(i = 0; i < numChannels; ++i) prios[i] = Sfx_ChannelPriority(channels + i); } sfxchannel_t* Sfx_ChannelFindVacant(boolean use3D, int bytes, int rate, int sampleID) { int i; sfxchannel_t* ch; for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || (ch->buffer->flags & SFXBF_PLAYING) || use3D != ((ch->buffer->flags & SFXBF_3D) != 0) || ch->buffer->bytes != bytes || ch->buffer->rate != rate) continue; // What about the sample? if(sampleID > 0) { if(!ch->buffer->sample || ch->buffer->sample->id != sampleID) continue; } else if(sampleID == 0) { // We're trying to find a channel with no sample already loaded. if(ch->buffer->sample) continue; } // This is perfect, take this! return ch; } return NULL; } /** * Used by the high-level sound interface to play sounds on this system. * * @param sample Ptr must be persistent! No copying is done here. * @param volume Volume at which the sample should be played. * @param freq Relative and modifies the sample's rate. * @param emitter @c NULL = 'fixedPos' is checked for a position. * If both 'emitter' and 'fixedPos' are @c NULL, then * the sound is played as centered 2D. * @return @c true, if a sound is started. */ int Sfx_StartSound(sfxsample_t* sample, float volume, float freq, mobj_t* emitter, float* fixedPos, int flags) { sfxchannel_t* ch, *selCh, *prioCh; sfxinfo_t* info; int i, count, nowTime; float myPrio, lowPrio = 0, channelPrios[SFX_MAX_CHANNELS]; boolean haveChannelPrios = false; boolean play3D = sfx3D && (emitter || fixedPos); if(!sfxAvail || sample->id < 1 || sample->id >= defs.count.sounds.num || volume <= 0) return false; // Calculate the new sound's priority. nowTime = Sys_GetTime(); myPrio = Sfx_Priority(emitter, fixedPos, volume, nowTime); // Ensure there aren't already too many channels playing this sample. info = sounds + sample->id; if(info->channels > 0) { // The decision to stop channels is based on priorities. Sfx_GetChannelPriorities(channelPrios); haveChannelPrios = true; count = Sfx_CountPlaying(sample->id); while(count >= info->channels) { /** * Stop the lowest priority sound of the playing instances, * again noting sounds that are more important than us. */ for(selCh = NULL, i = 0, ch = channels; i < numChannels; ++i, ch++) { if(ch->buffer && (ch->buffer->flags & SFXBF_PLAYING) && ch->buffer->sample->id == sample->id && myPrio >= channelPrios[i] && (!selCh || channelPrios[i] <= lowPrio)) { selCh = ch; lowPrio = channelPrios[i]; } } if(!selCh) { /** * The new sound can't be played because we were unable to * stop enough channels to accommodate the limitation. */ return false; } // Stop this one. count--; Sfx_ChannelStop(selCh); } } // Hit count tells how many times the cached sound has been used. Sfx_CacheHit(sample->id); /** * Pick a channel for the sound. We will do our best to play the sound, * cancelling existing ones if need be. The best choice would be a * free channel already loaded with the sample, in the correct format * and mode. */ BEGIN_COP; // First look through the stopped channels. At this stage we're very // picky: only the perfect choice will be good enough. selCh = Sfx_ChannelFindVacant(play3D, sample->bytesPer, sample->rate, sample->id); // The second step is to look for a vacant channel with any sample, // but preferably one with no sample already loaded. if(!selCh) { selCh = Sfx_ChannelFindVacant(play3D, sample->bytesPer, sample->rate, 0); } // Then try any non-playing channel in the correct format. if(!selCh) { selCh = Sfx_ChannelFindVacant(play3D, sample->bytesPer, sample->rate, -1); } if(!selCh) { // A perfect channel could not be found. /** * We must use a channel with the wrong format or decide which one * of the playing ones gets stopped. */ if(!haveChannelPrios) Sfx_GetChannelPriorities(channelPrios); // All channels with a priority less than or equal to ours can be // stopped. for(prioCh = NULL, i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || play3D != ((ch->buffer->flags & SFXBF_3D) != 0)) continue; // No buffer or in the wrong mode. if(!(ch->buffer->flags & SFXBF_PLAYING)) { // This channel is not playing, just take it! selCh = ch; break; } // Are we more important than this sound? // We want to choose the lowest priority sound. if(myPrio >= channelPrios[i] && (!prioCh || channelPrios[i] <= lowPrio)) { prioCh = ch; lowPrio = channelPrios[i]; } } // If a good low-priority channel was found, use it. if(prioCh) { selCh = prioCh; Sfx_ChannelStop(selCh); } } if(!selCh) { // A suitable channel was not found. END_COP; return false; } // Does our channel need to be reformatted? if(selCh->buffer->rate != sample->rate || selCh->buffer->bytes != sample->bytesPer) { iSFX->Destroy(selCh->buffer); // Create a new buffer with the correct format. selCh->buffer = iSFX->Create(play3D ? SFXBF_3D : 0, sample->bytesPer * 8, sample->rate); } // Clear flags. selCh->buffer->flags &= ~(SFXBF_REPEAT | SFXBF_DONT_STOP); // Set buffer flags. if(flags & SF_REPEAT) selCh->buffer->flags |= SFXBF_REPEAT; if(flags & SF_DONT_STOP) selCh->buffer->flags |= SFXBF_DONT_STOP; // Init the channel information. selCh->flags &= ~(SFXCF_NO_ORIGIN | SFXCF_NO_ATTENUATION | SFXCF_NO_UPDATE); selCh->volume = volume; selCh->frequency = freq; if(!emitter && !fixedPos) { selCh->flags |= SFXCF_NO_ORIGIN; selCh->emitter = NULL; } else { selCh->emitter = emitter; if(fixedPos) memcpy(selCh->pos, fixedPos, sizeof(selCh->pos)); } if(flags & SF_NO_ATTENUATION) { // The sound can be heard from any distance. selCh->flags |= SFXCF_NO_ATTENUATION; } /** * Load in the sample. Must load prior to setting properties, because * the audioDriver might actually create the real buffer only upon loading. */ iSFX->Load(selCh->buffer, sample); // Update channel properties. Sfx_ChannelUpdate(selCh); // 3D sounds need a few extra properties set up. if(play3D) { // Init the buffer's min/max distances. // This is only done once, when the sound is started (i.e. here). iSFX->Set(selCh->buffer, SFXBP_MIN_DISTANCE, (selCh->flags & SFXCF_NO_ATTENUATION)? 10000 : soundMinDist); iSFX->Set(selCh->buffer, SFXBP_MAX_DISTANCE, (selCh->flags & SFXCF_NO_ATTENUATION)? 20000 : soundMaxDist); } // This'll commit all the deferred properties. iSFX->Listener(SFXLP_UPDATE, 0); // Start playing. iSFX->Play(selCh->buffer); END_COP; // Take note of the start time. selCh->startTime = nowTime; // Sound successfully started. return true; } /** * Update channel and listener properties. */ void Sfx_Update(void) { int i; sfxchannel_t* ch; // If the display player doesn't have a mobj, no positioning is done. listener = S_GetListenerMobj(); // Update channels. for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(!ch->buffer || !(ch->buffer->flags & SFXBF_PLAYING)) continue; // Not playing sounds on this... Sfx_ChannelUpdate(ch); } // Update listener. Sfx_ListenerUpdate(); } /** * Periodical routines: channel updates, cache purge, cvar checks. */ void Sfx_StartFrame(void) { static int old3DMode = false; static int old16Bit = false; static int oldRate = 11025; static double lastUpdate = 0; double nowTime = Sys_GetSeconds(); if(!sfxAvail) return; // Tell the audioDriver that the sound frame begins. audioDriver->Event(SFXEV_BEGIN); // Have there been changes to the cvar settings? if(old3DMode != sfx3D) { Sfx_3DMode(sfx3D != 0); old3DMode = sfx3D; } // Check that the rate is valid. if(sfxSampleRate != 11025 && sfxSampleRate != 22050 && sfxSampleRate != 44100) { Con_Message("sound-rate corrected to 11025.\n"); sfxSampleRate = 11025; } // Do we need to change the sample format? if(old16Bit != sfx16Bit || oldRate != sfxSampleRate) { Sfx_SampleFormat(sfx16Bit ? 16 : 8, sfxSampleRate); old16Bit = sfx16Bit; oldRate = sfxSampleRate; } // Should we purge the cache (to conserve memory)? Sfx_PurgeCache(); // Is it time to do a channel update? if(nowTime - lastUpdate >= UPDATE_TIME) { lastUpdate = nowTime; Sfx_Update(); } } void Sfx_EndFrame(void) { if(!sfxAvail) return; // The sound frame ends. audioDriver->Event(SFXEV_END); } /** * Creates the buffers for the channels. * * @param num2D Number of 2D the rest will be 3D. */ void Sfx_CreateChannels(int num2D, int bits, int rate) { int i; sfxchannel_t* ch; float parm[2]; // Change the primary buffer's format to match the channel format. parm[0] = bits; parm[1] = rate; iSFX->Listenerv(SFXLP_PRIMARY_FORMAT, parm); // Try to create a buffer for each channel. for(i = 0, ch = channels; i < numChannels; ++i, ch++) { ch->buffer = iSFX->Create(num2D-- > 0 ? 0 : SFXBF_3D, bits, rate); if(!ch->buffer) { Con_Message("Sfx_CreateChannels: Failed to create " "buffer for #%i.\n", i); continue; } } } /** * Stop all channels and destroy their buffers. */ void Sfx_DestroyChannels(void) { int i; BEGIN_COP; for(i = 0; i < numChannels; ++i) { Sfx_ChannelStop(channels + i); if(channels[i].buffer) iSFX->Destroy(channels[i].buffer); channels[i].buffer = NULL; } END_COP; } void Sfx_InitChannels(void) { numChannels = sfxMaxChannels; // The -sfxchan option can be used to change the number of channels. if(ArgCheckWith("-sfxchan", 1)) { numChannels = strtol(ArgNext(), 0, 0); if(numChannels < 1) numChannels = 1; if(numChannels > SFX_MAX_CHANNELS) numChannels = SFX_MAX_CHANNELS; Con_Message("Sfx_InitChannels: %i channels.\n", numChannels); } // Allocate and init the channels. channels = Z_Calloc(sizeof(*channels) * numChannels, PU_STATIC, 0); // Create channels according to the current mode. Sfx_CreateChannels(sfx3D ? sfxDedicated2D : numChannels, sfxBits, sfxRate); } /** * Frees all memory allocated for the channels. */ void Sfx_ShutdownChannels(void) { Sfx_DestroyChannels(); if(channels) Z_Free(channels); channels = NULL; numChannels = 0; } /** * Start the channel refresh thread. It will stop on its own when it * notices that the rest of the sound system is going down. */ void Sfx_StartRefresh(void) { refreshing = false; allowRefresh = true; refreshHandle = Sys_StartThread(Sfx_ChannelRefreshThread, NULL); if(!refreshHandle) Con_Error("Sfx_StartRefresh: Failed to start refresh.\n"); } /** * Initialize the Sfx module. This includes setting up the available Sfx * drivers and the channels, and initializing the sound cache. Returns * true if the module is operational after the init. */ boolean Sfx_Init(void) { if(sfxAvail) return true; // Already initialized. // Check if sound has been disabled with a command line option. if(ArgExists("-nosfx")) { Con_Message("Sfx_Init: Disabled.\n"); return true; } Con_Message("Sfx_Init: Initializing...\n"); // Use the external SFX playback facilities, if available. if(audioDriver == &audiod_dummy) { iSFX = (audiointerface_sfx_generic_t*) &audiod_dummy_sfx; } else if(audioDriver == &audiod_sdlmixer) { iSFX = (audiointerface_sfx_generic_t*) &audiod_sdlmixer_sfx; } else { iSFX = (audiodExternalISFX.gen.Init ? (audiointerface_sfx_generic_t*) &audiodExternalISFX : 0); } if(!iSFX) { // No interface for SFX playback. return false; } // This is based on the scientific calculations that if the DOOM marine // is 56 units tall, 60 is about two meters. //// \fixme Derive from the viewheight. iSFX->Listener(SFXLP_UNITS_PER_METER, 30); iSFX->Listener(SFXLP_DOPPLER, 1); // The audioDriver is working, let's create the channels. Sfx_InitChannels(); // Init the sample cache. Sfx_InitCache(); // The Sfx module is now available. sfxAvail = true; Sfx_ListenerNoReverb(); // Finally, start the refresh thread. Sfx_StartRefresh(); return true; } /** * Shut down the whole Sfx module: drivers, channel buffers and the cache. */ void Sfx_Shutdown(void) { if(!sfxAvail) return; // Not initialized. // These will stop further refreshing. sfxAvail = false; allowRefresh = false; // Destroy the sample cache. Sfx_ShutdownCache(); // Destroy channels. Sfx_ShutdownChannels(); } /** * Stop all channels, clear the cache. */ void Sfx_Reset(void) { int i; if(!sfxAvail) return; listenerSector = NULL; // Stop all channels. for(i = 0; i < numChannels; ++i) Sfx_ChannelStop(&channels[i]); // Free all samples. Sfx_ShutdownCache(); } /** * Destroys all channels and creates them again. */ void Sfx_RecreateChannels(void) { Sfx_DestroyChannels(); Sfx_CreateChannels(sfx3D ? sfxDedicated2D : numChannels, sfxBits, sfxRate); } /** * Swaps between 2D and 3D sound modes. Called automatically by * Sfx_StartFrame when cvar changes. */ void Sfx_3DMode(boolean activate) { if(sfx3D == activate) return; // No change; do nothing. sfx3D = activate; // To make the change effective, re-create all channels. Sfx_RecreateChannels(); // If going to 2D, make sure the reverb is off. Sfx_ListenerNoReverb(); } /** * Reconfigures the sample bits and rate. Called automatically by * Sfx_StartFrame when changes occur. */ void Sfx_SampleFormat(int newBits, int newRate) { if(sfxBits == newBits && sfxRate == newRate) return; // No change; do nothing. // Set the new buffer format. sfxBits = newBits; sfxRate = newRate; Sfx_RecreateChannels(); // The cache just became useless, clear it. Sfx_ShutdownCache(); } /** * Must be done before the map is changed (from P_SetupMap, via * S_MapChange). */ void Sfx_MapChange(void) { int i; sfxchannel_t* ch; for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(ch->emitter) { // Mobjs are about to be destroyed. ch->emitter = NULL; // Stop all channels with an origin. Sfx_ChannelStop(ch); } } // Sectors, too, for that matter. listenerSector = NULL; } void Sfx_DebugInfo(void) { int i, lh = FR_TextHeight("W") - 3; sfxchannel_t* ch; char buf[200]; uint cachesize, ccnt; glColor3f(1, 1, 0); if(!sfxAvail) { FR_ShadowTextOut("Sfx disabled", 0, 0); return; } if(refMonitor) FR_ShadowTextOut("!", 0, 0); // Sample cache information. Sfx_GetCacheInfo(&cachesize, &ccnt); sprintf(buf, "Cached:%i (%i)", cachesize, ccnt); glColor3f(1, 1, 1); FR_ShadowTextOut(buf, 10, 0); // Print a line of info about each channel. for(i = 0, ch = channels; i < numChannels; ++i, ch++) { if(ch->buffer && (ch->buffer->flags & SFXBF_PLAYING)) glColor3f(1, 1, 1); else glColor3f(1, 1, 0); sprintf(buf, "%02i: %c%c%c v=%3.1f f=%3.3f st=%i et=%u", i, !(ch->flags & SFXCF_NO_ORIGIN) ? 'O' : '.', !(ch->flags & SFXCF_NO_ATTENUATION) ? 'A' : '.', ch->emitter ? 'E' : '.', ch->volume, ch->frequency, ch->startTime, ch->buffer ? ch->buffer->endTime : 0); FR_ShadowTextOut(buf, 5, lh * (1 + i * 2)); if(!ch->buffer) continue; sprintf(buf, " %c%c%c%c id=%03i/%-8s ln=%05i b=%i rt=%2i bs=%05i " "(C%05i/W%05i)", (ch->buffer->flags & SFXBF_3D) ? '3' : '.', (ch->buffer->flags & SFXBF_PLAYING) ? 'P' : '.', (ch->buffer->flags & SFXBF_REPEAT) ? 'R' : '.', (ch->buffer->flags & SFXBF_RELOAD) ? 'L' : '.', ch->buffer->sample ? ch->buffer->sample->id : 0, ch->buffer->sample ? defs.sounds[ch->buffer->sample->id]. id : "", ch->buffer->sample ? ch->buffer->sample->size : 0, ch->buffer->bytes, ch->buffer->rate / 1000, ch->buffer->length, ch->buffer->cursor, ch->buffer->written); FR_ShadowTextOut(buf, 5, lh * (2 + i * 2)); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_main.c0000644000175000017500000006550211357170242022352 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_main.c: Refresh Subsystem * * The refresh daemon has the highest-level rendering code. * The view window is handled by refresh. The more specialized * rendering code in rend_*.c does things inside the view window. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_render.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_audio.h" #include "de_misc.h" #include "de_ui.h" // MACROS ------------------------------------------------------------------ BEGIN_PROF_TIMERS() PROF_MOBJ_INIT_ADD END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(ViewGrid); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern byte rendInfoRPolys; extern byte freezeRLs; extern boolean firstFrameAfterLoad; // PUBLIC DATA DEFINITIONS ------------------------------------------------- int validCount = 1; // Increment every time a check is made. int frameCount; // Just for profiling purposes. int rendInfoTris = 0; int useVSync = 0; float viewX = 0, viewY = 0, viewZ = 0, viewPitch = 0; int viewAngle = 0; boolean setSizeNeeded; // Precalculated math tables. fixed_t* fineCosine = &finesine[FINEANGLES / 4]; int extraLight; // Bumped light from gun blasts. float extraLightDelta; float frameTimePos; // 0...1: fractional part for sharp game tics. int loadInStartupMode = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int rendCameraSmooth = true; // Smoothed by default. static boolean resetNextViewer = true; static viewdata_t viewData[DDMAXPLAYERS]; static byte showFrameTimePos = false; static byte showViewAngleDeltas = false; static byte showViewPosDeltas = false; static int gridCols, gridRows; static viewport_t viewports[DDMAXPLAYERS], *currentPort; // CODE -------------------------------------------------------------------- /** * Register console variables. */ void R_Register(void) { C_VAR_INT("con-show-during-setup", &loadInStartupMode, 0, 0, 1); C_VAR_INT("rend-camera-smooth", &rendCameraSmooth, CVF_HIDE, 0, 1); C_VAR_BYTE("rend-info-deltas-angles", &showViewAngleDeltas, 0, 0, 1); C_VAR_BYTE("rend-info-deltas-pos", &showViewPosDeltas, 0, 0, 1); C_VAR_BYTE("rend-info-frametime", &showFrameTimePos, 0, 0, 1); C_VAR_BYTE("rend-info-rendpolys", &rendInfoRPolys, CVF_NO_ARCHIVE, 0, 1); C_VAR_INT("rend-info-tris", &rendInfoTris, 0, 0, 1); // C_VAR_INT("rend-vsync", &useVSync, 0, 0, 1); C_CMD("viewgrid", "ii", ViewGrid); P_MaterialManagerRegister(); } /** * Will the specified surface be added to the sky mask? * * @param suf Ptr to the surface to test. * @return boolean @c true, iff the surface will be masked. */ boolean R_IsSkySurface(const surface_t* suf) { if(suf && suf->material && (suf->material->flags & MATF_SKYMASK)) return true; return false; } /** * Don't really change anything here, because i might be in the middle of * a refresh. The change will take effect next refresh. */ void R_SetViewWindow(int x, int y, int w, int h) { viewwindowx = x; viewwindowy = y; viewwidth = w; viewheight = h; } /** * Retrieve the dimensions of the specified viewport by console player num. */ int R_GetViewPort(int player, int* x, int* y, int* w, int* h) { int p = P_ConsoleToLocal(player); if(p != -1) { if(x) *x = viewports[p].x; if(y) *y = viewports[p].y; if(w) *w = viewports[p].width; if(h) *h = viewports[p].height; return p; } return -1; } /** * Calculate the placement and dimensions of a specific viewport. * Assumes that the grid has already been configured. */ void R_ViewPortPlacement(viewport_t* port, int x, int y) { float w = theWindow->width / (float) gridCols; float h = theWindow->height / (float) gridRows; port->x = x * w; port->y = y * h; port->width = (x + 1) * w - port->x; port->height = (y + 1) * h - port->y; } /** * Set up a view grid and calculate the viewports. Set 'numCols' and * 'numRows' to zero to just update the viewport coordinates. */ void R_SetViewGrid(int numCols, int numRows) { int x, y, p; if(numCols > 0 && numRows > 0) { if(numCols > 16) numCols = 16; if(numRows > 16) numRows = 16; gridCols = numCols; gridRows = numRows; } // Reset all viewports to zero. memset(viewports, 0, sizeof(viewports)); for(p = 0, y = 0; y < gridRows; ++y) { for(x = 0; x < gridCols; ++x, ++p) { R_ViewPortPlacement(&viewports[p], x, y); // The console number is -1 if the viewport belongs to no // one. viewports[p].console = displayPlayer; //clients[P_LocalToConsole(p)].viewConsole; } } } /** * One-time initialization of the refresh daemon. Called by DD_Main. * GL has not yet been inited. */ void R_Init(void) { R_InitData(); // viewwidth / viewheight / detailLevel are set by the defaults R_SetViewWindow(0, 0, 320, 200); R_InitSprites(); // Fully initialize sprites. R_InitTranslationTables(); Rend_Init(); frameCount = 0; R_InitViewBorder(); P_PtcInit(); // Defs have been read; we can now init models. R_InitModels(); Def_PostInit(); } /** * Re-initialize almost everything. */ void R_Update(void) { uint i; R_UpdateTexturesAndFlats(); R_InitTextures(); R_InitFlats(); R_PreInitSprites(); // Re-read definitions. Def_Read(); R_UpdateData(); R_InitSprites(); // Fully reinitialize sprites. R_UpdateTranslationTables(); R_InitModels(); // Defs might've changed. // Now that we've read the defs, we can load system textures. GL_LoadSystemTextures(); Def_PostInit(); P_UpdateParticleGens(); // Defs might've changed. for(i = 0; i < DDMAXPLAYERS; ++i) { player_t* plr = &ddPlayers[i]; ddplayer_t* ddpl = &plr->shared; // States have changed, the states are unknown. ddpl->pSprites[0].statePtr = ddpl->pSprites[1].statePtr = NULL; } // Update all world surfaces. for(i = 0; i < numSectors; ++i) { uint j; sector_t* sec = §ors[i]; for(j = 0; j < sec->planeCount; ++j) Surface_Update(&sec->SP_planesurface(j)); } for(i = 0; i < numSideDefs; ++i) { sidedef_t* side = &sideDefs[i]; Surface_Update(&side->SW_topsurface); Surface_Update(&side->SW_middlesurface); Surface_Update(&side->SW_bottomsurface); } for(i = 0; i < numPolyObjs; ++i) { polyobj_t* po = polyObjs[i]; seg_t** segPtr = po->segs; while(*segPtr) { sidedef_t* side = SEG_SIDEDEF(*segPtr); Surface_Update(&side->SW_middlesurface); *segPtr++; } } // The rendering lists have persistent data that has changed during // the re-initialization. RL_DeleteLists(); // Update the secondary title and the game status. Con_InitUI(); #if _DEBUG Z_CheckHeap(); #endif } /** * Shutdown the refresh daemon. */ void R_Shutdown(void) { R_ShutdownModels(); R_ShutdownData(); R_ShutdownResourceLocator(); // Most allocated memory goes down with the zone. } void R_ResetViewer(void) { resetNextViewer = 1; } void R_InterpolateViewer(viewer_t* start, viewer_t* end, float pos, viewer_t* out) { float inv = 1 - pos; out->pos[VX] = inv * start->pos[VX] + pos * end->pos[VX]; out->pos[VY] = inv * start->pos[VY] + pos * end->pos[VY]; out->pos[VZ] = inv * start->pos[VZ] + pos * end->pos[VZ]; out->angle = start->angle + pos * ((int) end->angle - (int) start->angle); out->pitch = inv * start->pitch + pos * end->pitch; } void R_CopyViewer(viewer_t* dst, const viewer_t* src) { dst->pos[VX] = src->pos[VX]; dst->pos[VY] = src->pos[VY]; dst->pos[VZ] = src->pos[VZ]; dst->angle = src->angle; dst->pitch = src->pitch; } const viewdata_t* R_ViewData(int localPlayerNum) { assert(localPlayerNum >= 0 && localPlayerNum < DDMAXPLAYERS); return &viewData[localPlayerNum]; } /** * The components whose difference is too large for interpolation will be * snapped to the sharp values. */ void R_CheckViewerLimits(viewer_t* src, viewer_t* dst) { #define MAXMOVE 32 if(fabs(dst->pos[VX] - src->pos[VX]) > MAXMOVE || fabs(dst->pos[VY] - src->pos[VY]) > MAXMOVE) { src->pos[VX] = dst->pos[VX]; src->pos[VY] = dst->pos[VY]; src->pos[VZ] = dst->pos[VZ]; } if(abs((int) dst->angle - (int) src->angle) >= ANGLE_45) src->angle = dst->angle; #undef MAXMOVE } /** * Retrieve the current sharp camera position. */ void R_GetSharpView(viewer_t* view, player_t* player) { ddplayer_t* ddpl; if(!player || !player->shared.mo) { return; } ddpl = &player->shared; view->pos[VX] = viewX; view->pos[VY] = viewY; view->pos[VZ] = viewZ; /* $unifiedangles */ view->angle = viewAngle; view->pitch = viewPitch; if((ddpl->flags & DDPF_CHASECAM) && !(ddpl->flags & DDPF_CAMERA)) { /* STUB * This needs to be fleshed out with a proper third person * camera control setup. Currently we simply project the viewer's * position a set distance behind the ddpl. */ angle_t pitch = LOOKDIR2DEG(view->pitch) / 360 * ANGLE_MAX; angle_t angle = view->angle; float distance = 90; angle = view->angle >> ANGLETOFINESHIFT; pitch >>= ANGLETOFINESHIFT; view->pos[VX] -= distance * FIX2FLT(fineCosine[angle]); view->pos[VY] -= distance * FIX2FLT(finesine[angle]); view->pos[VZ] -= distance * FIX2FLT(finesine[pitch]); } // Check that the viewZ doesn't go too high or low. // Cameras are not restricted. if(!(ddpl->flags & DDPF_CAMERA)) { if(view->pos[VZ] > ddpl->mo->ceilingZ - 4) { view->pos[VZ] = ddpl->mo->ceilingZ - 4; } if(view->pos[VZ] < ddpl->mo->floorZ + 4) { view->pos[VZ] = ddpl->mo->floorZ + 4; } } } /** * Update the sharp world data by rotating the stored values of plane * heights and sharp camera positions. */ void R_NewSharpWorld(void) { extern boolean firstFrameAfterLoad; int i; if(firstFrameAfterLoad) { /** * We haven't yet drawn the world. Everything *is* sharp so simply * reset the viewer data. * \fixme A bit of a kludge? */ memset(viewData, 0, sizeof(viewData)); return; } if(resetNextViewer) resetNextViewer = 2; for(i = 0; i < DDMAXPLAYERS; ++i) { viewer_t sharpView; viewdata_t* vd = &viewData[i]; player_t* plr = &ddPlayers[i]; if(/*(plr->shared.flags & DDPF_LOCAL) &&*/ (!plr->shared.inGame || !plr->shared.mo)) { continue; } R_GetSharpView(&sharpView, plr); // Update the camera angles that will be used when the camera is // not smoothed. vd->frozenAngle = sharpView.angle; vd->frozenPitch = sharpView.pitch; // The game tic has changed, which means we have an updated sharp // camera position. However, the position is at the beginning of // the tic and we are most likely not at a sharp tic boundary, in // time. We will move the viewer positions one step back in the // buffer. The effect of this is that [0] is the previous sharp // position and [1] is the current one. memcpy(&vd->lastSharp[0], &vd->lastSharp[1], sizeof(viewer_t)); memcpy(&vd->lastSharp[1], &sharpView, sizeof(sharpView)); R_CheckViewerLimits(vd->lastSharp, &sharpView); } R_UpdateWatchedPlanes(watchedPlaneList); R_UpdateMovingSurfaces(); } void R_CreateMobjLinks(void) { uint i; sector_t* seciter; #ifdef DD_PROFILE static int p; if(++p > 40) { p = 0; PRINT_PROF( PROF_MOBJ_INIT_ADD ); } #endif BEGIN_PROF( PROF_MOBJ_INIT_ADD ); for(i = 0, seciter = sectors; i < numSectors; seciter++, ++i) { mobj_t* iter; for(iter = seciter->mobjList; iter; iter = iter->sNext) { R_ObjLinkCreate(iter, OT_MOBJ); // For spreading purposes. } } END_PROF( PROF_MOBJ_INIT_ADD ); } /** * Prepare for rendering view(s) of the world. */ void R_BeginWorldFrame(void) { R_ClearSectorFlags(); R_InterpolateWatchedPlanes(watchedPlaneList, resetNextViewer); R_InterpolateMovingSurfaces(resetNextViewer); if(!freezeRLs) { LG_Update(); SB_BeginFrame(); LO_ClearForFrame(); R_ClearObjLinksForFrame(); // Zeroes the links. // Clear the objlinks. R_InitForNewFrame(); // Generate surface decorations for the frame. Rend_InitDecorationsForFrame(); // Spawn omnilights for decorations. Rend_AddLuminousDecorations(); // Spawn omnilights for mobjs. LO_AddLuminousMobjs(); // Create objlinks for mobjs. R_CreateMobjLinks(); // Link all active particle generators into the world. P_CreatePtcGenLinks(); // Link objs to all contacted surfaces. R_LinkObjs(); } } /** * Wrap up after drawing view(s) of the world. */ void R_EndWorldFrame(void) { if(!freezeRLs) { // Wrap up with Source, Bias lights. SB_EndFrame(); } } /** * Prepare rendering the view of the given player. */ void R_SetupFrame(player_t* player) { #define VIEWPOS_MAX_SMOOTHDISTANCE 172 #define MINEXTRALIGHTFRAMES 2 int tableAngle; float yawRad, pitchRad; viewer_t sharpView, smoothView; viewdata_t* vd; // Reset the GL triangle counter. polyCounter = 0; viewPlayer = player; vd = &viewData[viewPlayer - ddPlayers]; R_GetSharpView(&sharpView, viewPlayer); if(resetNextViewer || V3_Distance(vd->current.pos, sharpView.pos) > VIEWPOS_MAX_SMOOTHDISTANCE) { // Keep reseting until a new sharp world has arrived. if(resetNextViewer > 1) resetNextViewer = 0; // Just view from the sharp position. R_CopyViewer(&vd->current, &sharpView); memcpy(&vd->lastSharp[0], &sharpView, sizeof(sharpView)); memcpy(&vd->lastSharp[1], &sharpView, sizeof(sharpView)); } // While the game is paused there is no need to calculate any // time offsets or interpolated camera positions. else //if(!clientPaused) { // Calculate the smoothed camera position, which is somewhere // between the previous and current sharp positions. This // introduces a slight delay (max. 1/35 sec) to the movement // of the smoothed camera. R_InterpolateViewer(vd->lastSharp, vd->lastSharp + 1, frameTimePos, &smoothView); // Use the latest view angles known to us, if the interpolation flags // are not set. The interpolation flags are used when the view angles // are updated during the sharp tics and need to be smoothed out here. // For example, view locking (dead or camera setlock). if(!(player->shared.flags & DDPF_INTERYAW)) smoothView.angle = sharpView.angle; if(!(player->shared.flags & DDPF_INTERPITCH)) smoothView.pitch = sharpView.pitch; R_CopyViewer(&vd->current, &smoothView); // Monitor smoothness of yaw/pitch changes. if(showViewAngleDeltas) { typedef struct oldangle_s { double time; float yaw, pitch; } oldangle_t; static oldangle_t oldangle[DDMAXPLAYERS]; oldangle_t* old = &oldangle[viewPlayer - ddPlayers]; float yaw = (double)smoothView.angle / ANGLE_MAX * 360; Con_Message("(%i) F=%.3f dt=%-10.3f dx=%-10.3f dy=%-10.3f " "Rdx=%-10.3f Rdy=%-10.3f\n", SECONDS_TO_TICKS(gameTime), frameTimePos, sysTime - old->time, yaw - old->yaw, smoothView.pitch - old->pitch, (yaw - old->yaw) / (sysTime - old->time), (smoothView.pitch - old->pitch) / (sysTime - old->time)); old->yaw = yaw; old->pitch = smoothView.pitch; old->time = sysTime; } // The Rdx and Rdy should stay constant when moving. if(showViewPosDeltas) { typedef struct oldpos_s { double time; float x, y, z; } oldpos_t; static oldpos_t oldpos[DDMAXPLAYERS]; oldpos_t* old = &oldpos[viewPlayer - ddPlayers]; Con_Message("(%i) F=%.3f dt=%-10.3f dx=%-10.3f dy=%-10.3f dz=%-10.3f\n", //"Rdx=%-10.3f Rdy=%-10.3f\n", SECONDS_TO_TICKS(gameTime), frameTimePos, sysTime - old->time, smoothView.pos[0] - old->x, smoothView.pos[1] - old->y, smoothView.pos[2] - old->z /*, smoothView.pos[0] - old->x / (sysTime - old->time), smoothView.pos[1] - old->y / (sysTime - old->time)*/); old->x = smoothView.pos[VX]; old->y = smoothView.pos[VY]; old->z = smoothView.pos[VZ]; old->time = sysTime; } } // Update viewer. tableAngle = viewData->current.angle >> ANGLETOFINESHIFT; viewData->viewSin = FIX2FLT(finesine[tableAngle]); viewData->viewCos = FIX2FLT(fineCosine[tableAngle]); // Calculate the front, up and side unit vectors. // The vectors are in the DGL coordinate system, which is a left-handed // one (same as in the game, but Y and Z have been swapped). Anyone // who uses these must note that it might be necessary to fix the aspect // ratio of the Y axis by dividing the Y coordinate by 1.2. yawRad = ((viewData->current.angle / (float) ANGLE_MAX) *2) * PI; pitchRad = viewData->current.pitch * 85 / 110.f / 180 * PI; // The front vector. viewData->frontVec[VX] = cos(yawRad) * cos(pitchRad); viewData->frontVec[VZ] = sin(yawRad) * cos(pitchRad); viewData->frontVec[VY] = sin(pitchRad); // The up vector. viewData->upVec[VX] = -cos(yawRad) * sin(pitchRad); viewData->upVec[VZ] = -sin(yawRad) * sin(pitchRad); viewData->upVec[VY] = cos(pitchRad); // The side vector is the cross product of the front and up vectors. M_CrossProduct(viewData->frontVec, viewData->upVec, viewData->sideVec); if(showFrameTimePos) { Con_Printf("frametime = %f\n", frameTimePos); } // Handle extralight (used to light up the world momentarily (used for // e.g. gun flashes). We want to avoid flickering, so when ever it is // enabled; make it last for a few frames. if(player->targetExtraLight != player->shared.extraLight) { player->targetExtraLight = player->shared.extraLight; player->extraLightCounter = MINEXTRALIGHTFRAMES; } if(player->extraLightCounter > 0) { player->extraLightCounter--; if(player->extraLightCounter == 0) player->extraLight = player->targetExtraLight; } extraLight = player->extraLight; extraLightDelta = extraLight / 16.0f; // Why? validCount++; #undef MINEXTRALIGHTFRAMES #undef VIEWPOS_MAX_SMOOTHDISTANCE } /** * Draw the border around the view window. */ void R_RenderPlayerViewBorder(void) { R_DrawViewBorder(); } /** * Set the GL viewport. */ void R_UseViewPort(viewport_t* port) { if(!port) { glViewport(0, FLIP(0 + theWindow->height - 1), theWindow->width, theWindow->height); } else { currentPort = port; glViewport(port->x, FLIP(port->y + port->height - 1), port->width, port->height); } } /** * Render a blank view for the specified player. */ void R_RenderBlankView(void) { UI_DrawDDBackground(0, 0, 320, 200, 1); } /** * Draw the view of the player inside the view window. */ void R_RenderPlayerView(int num) { extern boolean firstFrameAfterLoad; extern int psp3d, modelTriCount; int oldFlags = 0; player_t* player; if(num < 0 || num >= DDMAXPLAYERS) return; // Huh? player = &ddPlayers[num]; if(!player->shared.inGame || !player->shared.mo) return; if(firstFrameAfterLoad) { // Don't let the clock run yet. There may be some texture // loading still left to do that we have been unable to // predetermine. firstFrameAfterLoad = false; DD_ResetTimer(); } // Setup for rendering the frame. R_SetupFrame(player); if(!freezeRLs) R_ClearSprites(); R_ProjectPlayerSprites(); // Only if 3D models exists for them. // Hide the viewPlayer's mobj? if(!(player->shared.flags & DDPF_CHASECAM)) { oldFlags = player->shared.mo->ddFlags; player->shared.mo->ddFlags |= DDMF_DONTDRAW; } // Go to wireframe mode? if(renderWireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // GL is in 3D transformation state only during the frame. GL_SwitchTo3DState(true, currentPort); Rend_RenderMap(); // Orthogonal projection to the view window. GL_Restore2DState(1); // Don't render in wireframe mode with 2D psprites. if(renderWireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); Rend_Draw2DPlayerSprites(); // If the 2D versions are needed. if(renderWireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); // Fullscreen viewport. GL_Restore2DState(2); // Do we need to render any 3D psprites? if(psp3d) { GL_SwitchTo3DState(false, currentPort); Rend_Draw3DPlayerSprites(); GL_Restore2DState(2); // Restore viewport. } // Original matrices and state: back to normal 2D. GL_Restore2DState(3); // Back from wireframe mode? if(renderWireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // Now we can show the viewPlayer's mobj again. if(!(player->shared.flags & DDPF_CHASECAM)) player->shared.mo->ddFlags = oldFlags; // Should we be counting triangles? if(rendInfoTris) { // This count includes all triangles drawn since R_SetupFrame. Con_Printf("Tris: %-4i (Mdl=%-4i)\n", polyCounter, modelTriCount); modelTriCount = 0; polyCounter = 0; } if(rendInfoLums) { Con_Printf("LumObjs: %-4i\n", LO_GetNumLuminous()); } R_InfoRendVerticesPool(); // The colored filter. GL_DrawFilter(); } /** * Should be called when returning from a game-side drawing method to ensure * that our assumptions of the GL state are valid. This is necessary because * DGL affords the user the posibility of modifiying the GL state. * * Todo: A cleaner approach would be a DGL state stack which could simply pop. */ static void restoreDefaultGLState(void) { // Here we use the DGL methods as this ensures it's state is kept in sync. DGL_Disable(DGL_FOG); DGL_Disable(DGL_SCISSOR_TEST); DGL_Enable(DGL_TEXTURING); DGL_Enable(DGL_LINE_SMOOTH); DGL_Enable(DGL_POINT_SMOOTH); } /** * Render all view ports in the viewport grid. */ void R_RenderViewPorts(void) { int oldDisplay = displayPlayer; int x, y, p; GLbitfield bits = GL_DEPTH_BUFFER_BIT; if(/*firstFrameAfterLoad ||*/ freezeRLs) { bits |= GL_COLOR_BUFFER_BIT; } else { int i; for(i = 0; i < DDMAXPLAYERS; ++i) { player_t* plr = &ddPlayers[i]; if(!plr->shared.inGame || !(plr->shared.flags & DDPF_LOCAL)) continue; if(P_IsInVoid(plr)) { bits |= GL_COLOR_BUFFER_BIT; break; } } } // This is all the clearing we'll do. glClear(bits); // Draw a view for all players with a visible viewport. for(p = 0, y = 0; y < gridRows; ++y) for(x = 0; x < gridCols; x++, ++p) { displayPlayer = viewports[p].console; R_UseViewPort(viewports + p); if(displayPlayer < 0) { R_RenderBlankView(); continue; } // Draw in-window game graphics (layer 0). gx.G_Drawer(0); restoreDefaultGLState(); // Draw the view border. R_RenderPlayerViewBorder(); // Draw in-window game graphics (layer 1). gx.G_Drawer(1); restoreDefaultGLState(); // Increment the internal frame count. This does not // affect the FPS counter. frameCount++; } // Restore things back to normal. displayPlayer = oldDisplay; R_UseViewPort(NULL); } D_CMD(ViewGrid) { if(argc != 3) { Con_Printf("Usage: %s (cols) (rows)\n", argv[0]); return true; } // Recalculate viewports. R_SetViewGrid(strtol(argv[1], NULL, 0), strtol(argv[2], NULL, 0)); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_materialmanager.c0000644000175000017500000007671011357170242024560 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_materialmanager.c: Materials manager. */ // HEADER FILES ------------------------------------------------------------ #include // For tolower() #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_misc.h" #include "de_audio.h" // For texture, environmental audio properties. // MACROS ------------------------------------------------------------------ #define MATERIALS_BLOCK_ALLOC (32) // Num materials to allocate per block. #define MATERIAL_NAME_HASH_SIZE (512) // TYPES ------------------------------------------------------------------- typedef struct materialbind_s { char name[9]; material_t* mat; uint hashNext; // 1-based index } materialbind_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(ListMaterials); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void animateAnimGroups(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern boolean ddMapSetup; // PUBLIC DATA DEFINITIONS ------------------------------------------------- materialnum_t numMaterialBinds = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean initedOk = false; /** * The following data structures and variables are intrinsically linked and * are inter-dependant. The scheme used is somewhat complicated due to the * required traits of the materials themselves and in of the system itself: * * 1) Pointers to material_t are eternal, they are always valid and continue * to reference the same logical material data even after engine reset. * 2) Public material identifiers (materialnum_t) are similarly eternal. * Note that they are used to index the material name bindings array. * 3) Dynamic creation/update of materials. * 4) Material name bindings are semi-independant from the materials. There * may be multiple name bindings for a given material (aliases). * The only requirement is that the name is unique among materials in * a given material mnamespace. * 5) Super-fast look up by public material identifier. * 6) Fast look up by material name (a hashing scheme is used). */ static zblockset_t* materialsBlockSet; static material_t* materialsHead; // Head of the linked list of materials. static materialbind_t* materialBinds; static materialnum_t maxMaterialBinds; static uint hashTable[NUM_MATERIAL_NAMESPACES][MATERIAL_NAME_HASH_SIZE]; // CODE -------------------------------------------------------------------- void P_MaterialManagerRegister(void) { C_CMD("listmaterials", NULL, ListMaterials); } /** * Is the specified id a valid (known) material namespace. * * \note The special case MN_ANY is considered invalid here as it does not * relate to one specific mnamespace. * * @return @c true, iff the id is valid. */ static boolean isKnownMNamespace(material_namespace_t mnamespace) { if(mnamespace >= MN_FIRST && mnamespace < NUM_MATERIAL_NAMESPACES) return true; return false; } /** * This is a hash function. Given a material name it generates a * somewhat-random number between 0 and MATERIAL_NAME_HASH_SIZE. * * @return The generated hash index. */ static uint hashForName(const char* name) { ushort key = 0; int i; // Stop when the name ends. for(i = 0; *name; ++i, name++) { if(i == 0) key ^= (int) (*name); else if(i == 1) key *= (int) (*name); else if(i == 2) { key -= (int) (*name); i = -1; } } return key % MATERIAL_NAME_HASH_SIZE; } /** * Given a name and namespace, search the materials db for a match. * \assume Caller knows what it's doing; params arn't validity checked. * * @param name Name of the material to search for. Must have been * transformed to all lower case. * @param mnamespace Specific MG_* material namespace NOT @c MN_ANY. * @return Unique number of the found material, else zero. */ static materialnum_t getMaterialNumForName(const char* name, uint hash, material_namespace_t mnamespace) { // Go through the candidates. if(hashTable[mnamespace][hash]) { materialbind_t* mb = &materialBinds[ hashTable[mnamespace][hash] - 1]; for(;;) { material_t* mat; mat = mb->mat; if(!strncmp(mb->name, name, 8)) return ((mb) - materialBinds) + 1; if(!mb->hashNext) break; mb = &materialBinds[mb->hashNext - 1]; } } return 0; // Not found. } /** * Given an index and namespace, search the materials db for a match. * \assume Caller knows what it's doing; params arn't validity checked. * * @param id gltextureid to search for. * @param mnamespace Specific MG_* material namespace NOT @c MN_ANY. * @return Unique number of the found material, else zero. */ static materialnum_t getMaterialNumForIndex(uint idx, material_namespace_t mnamespace) { materialnum_t i; // Go through the candidates. for(i = 0; i < numMaterialBinds; ++i) { materialbind_t* mb = &materialBinds[i]; material_t* mat = mb->mat; if(mat->mnamespace == mnamespace && GL_GetGLTexture(mat->layers[0].tex)->ofTypeID == idx) return ((mb) - materialBinds) + 1; } return 0; // Not found. } static void newMaterialNameBinding(material_t* mat, const char* name, material_namespace_t mnamespace, uint hash) { materialbind_t* mb; if(++numMaterialBinds > maxMaterialBinds) { // Allocate more memory. maxMaterialBinds += MATERIALS_BLOCK_ALLOC; materialBinds = Z_Realloc(materialBinds, sizeof(*materialBinds) * maxMaterialBinds, PU_STATIC); } // Add the new material to the end. mb = &materialBinds[numMaterialBinds - 1]; strncpy(mb->name, name, 8); mb->name[8] = '\0'; mb->mat = mat; // We also hash the name for faster searching. mb->hashNext = hashTable[mnamespace][hash]; hashTable[mnamespace][hash] = (mb - materialBinds) + 1; } /** * One time initialization of the materials list. Called during init. */ void P_InitMaterialManager(void) { if(initedOk) return; // Already been here. materialsBlockSet = Z_BlockCreate(sizeof(material_t), MATERIALS_BLOCK_ALLOC, PU_STATIC); materialsHead = NULL; materialBinds = NULL; numMaterialBinds = maxMaterialBinds = 0; // Clear the name bind hash tables. memset(hashTable, 0, sizeof(hashTable)); initedOk = true; } /** * Release all memory acquired for the materials list. * Called during shutdown. */ void P_ShutdownMaterialManager(void) { if(!initedOk) return; Z_BlockDestroy(materialsBlockSet); materialsBlockSet = NULL; materialsHead = NULL; // Destroy the bindings. if(materialBinds) { Z_Free(materialBinds); materialBinds = NULL; } numMaterialBinds = maxMaterialBinds = 0; initedOk = false; } /** * Deletes all GL texture instances, linked to materials. * * @param mnamespace @c MN_ANY = delete everything, ELSE * Only delete those currently in use by materials * in the specified namespace. */ void P_DeleteMaterialTextures(material_namespace_t mnamespace) { if(mnamespace == MN_ANY) { // Delete the lot. GL_DeleteAllTexturesForGLTextures(GLT_ANY); return; } if(!isKnownMNamespace(mnamespace)) Con_Error("P_DeleteMaterialTextures: Internal error, " "invalid materialgroup '%i'.", (int) mnamespace); if(materialBinds) { uint i; for(i = 0; i < MATERIAL_NAME_HASH_SIZE; ++i) if(hashTable[mnamespace][i]) { materialbind_t* mb = &materialBinds[ hashTable[mnamespace][i] - 1]; for(;;) { material_t* mat = mb->mat; uint j; for(j = 0; j < mat->numLayers; ++j) GL_ReleaseGLTexture(mat->layers[j].tex); if(!mb->hashNext) break; mb = &materialBinds[mb->hashNext - 1]; } } } } static material_t* createMaterial(short width, short height, byte flags, material_namespace_t mnamespace, ded_material_t* def, gltextureid_t tex) { uint i; material_t* mat = Z_BlockNewElement(materialsBlockSet); memset(mat, 0, sizeof(*mat)); mat->header.type = DMU_MATERIAL; mat->mnamespace = mnamespace; mat->width = width; mat->height = height; mat->flags = flags; mat->envClass = MEC_UNKNOWN; mat->current = mat->next = mat; mat->def = def; mat->decoration = NULL; mat->ptcGen = NULL; mat->detail = NULL; mat->layers[0].tex = tex; mat->numLayers = 1; // Is this a custom material? mat->flags &= ~MATF_CUSTOM; for(i = 0; i < mat->numLayers; ++i) { if(!GLTexture_IsFromIWAD(GL_GetGLTexture(mat->layers[i].tex))) { mat->flags |= MATF_CUSTOM; break; } } // Link the new material into the global list of materials. mat->globalNext = materialsHead; materialsHead = mat; return mat; } static material_t* getMaterialByNum(materialnum_t num) { if(num < numMaterialBinds) return materialBinds[num].mat; return NULL; } /** * Given a unique material number return the associated material. * * @param num Unique material number. * * @return The associated material, ELSE @c NULL. */ material_t* P_ToMaterial(materialnum_t num) { if(!initedOk) return NULL; if(num != 0) return getMaterialByNum(num - 1); // 1-based index. return NULL; } /** * Retrieve the unique material number for the given material. * * @param mat The material to retrieve the unique number of. * * @return The associated unique number. */ materialnum_t P_ToMaterialNum(const material_t* mat) { if(mat) { materialnum_t i; for(i = 0; i < numMaterialBinds; ++i) if(materialBinds[i].mat == mat) return i + 1; // 1-based index. } return 0; } /** * Create a new material. If there exists one by the same name and in the * same namespace, it is returned else a new material is created. * * \note: May fail if the name is invalid. * * @param name Name of the new material. * @param width Width of the material (not of the texture). * @param height Height of the material (not of the texture). * @param flags MATF_* material flags * @param tex Texture to use with this material. * @param mnamespace MG_* material namespace. * MN_ANY is only valid when updating an existing material. * * @return The created material, ELSE @c NULL. */ material_t* P_MaterialCreate(const char* rawName, short width, short height, byte flags, gltextureid_t tex, material_namespace_t mnamespace, ded_material_t* def) { int n; uint hash; char name[9]; materialnum_t oldMat; material_t* mat; if(!initedOk) return NULL; // In original DOOM, texture name references beginning with the // hypen '-' character are always treated as meaning "no reference" // or "invalid texture" and surfaces using them were not drawn. if(!rawName || !rawName[0] || rawName[0] == '-') { #if _DEBUG Con_Message("P_MaterialCreate: Warning, attempted to create material with " "NULL name\n."); #endif return NULL; } // Prepare 'name'. for(n = 0; *rawName && n < 8; ++n, rawName++) name[n] = tolower(*rawName); name[n] = '\0'; hash = hashForName(name); // Check if we've already created a material for this. if(mnamespace == MN_ANY) { // Caller doesn't care which namespace. This is only valid if we // can find a material by this name using a priority search order. oldMat = getMaterialNumForName(name, hash, MN_SPRITES); if(!oldMat) oldMat = getMaterialNumForName(name, hash, MN_TEXTURES); if(!oldMat) oldMat = getMaterialNumForName(name, hash, MN_FLATS); } else { if(!isKnownMNamespace(mnamespace)) { #if _DEBUG Con_Message("P_MaterialCreate: Warning, attempted to create material in " "unknown namespace '%i'.\n", (int) mnamespace); #endif return NULL; } oldMat = getMaterialNumForName(name, hash, mnamespace); } if(oldMat) { // We are updating an existing material. materialbind_t* mb = &materialBinds[oldMat - 1]; uint i; mat = mb->mat; // Update the (possibly new) meta data. mat->flags = flags; if(tex) mat->layers[0].tex = tex; if(width > 0) mat->width = width; if(height > 0) mat->height = height; mat->inAnimGroup = false; mat->current = mat->next = mat; mat->def = def; mat->inter = 0; mat->decoration = NULL; mat->ptcGen = NULL; mat->detail = NULL; mat->envClass = MEC_UNKNOWN; mat->mnamespace = mnamespace; // Is this a custom material? mat->flags &= ~MATF_CUSTOM; for(i = 0; i < mat->numLayers; ++i) { if(!GLTexture_IsFromIWAD(GL_GetGLTexture(mat->layers[i].tex))) { mat->flags |= MATF_CUSTOM; break; } } return mat; // Yep, return it. } if(mnamespace == MN_ANY) { #if _DEBUG Con_Message("P_MaterialCreate: Warning, attempted to create material " "without specifying a namespace.\n"); #endif return NULL; } /** * A new material. */ // Only create complete materials. // \todo Doing this here isn't ideal. if(tex == 0 || !(width > 0) || !(height > 0)) return NULL; mat = createMaterial(width, height, flags, mnamespace, def, tex); // Now create a name binding for it. newMaterialNameBinding(mat, name, mnamespace, hash); return mat; } /** * Given a Texture/Flat/Sprite etc idx and a MG_* namespace, search * for a matching material. * * @param ofTypeID Texture/Flat/Sprite etc idx. * @param mnamespace Specific MG_* namespace (not MN_ANY). * * @return The associated material, ELSE @c NULL. */ material_t* P_GetMaterial(int ofTypeID, material_namespace_t mnamespace) { if(!initedOk) return NULL; if(!isKnownMNamespace(mnamespace)) // MN_ANY is considered invalid. { #if _DEBUG Con_Message("P_GetMaterial: Internal error, invalid namespace '%i'\n", (int) mnamespace); #endif return NULL; } if(materialsHead) { material_t* mat; mat = materialsHead; do { if(mnamespace == mat->mnamespace && GL_GetGLTexture(mat->layers[0].tex)->ofTypeID == ofTypeID) { if(mat->flags & MATF_NO_DRAW) return NULL; return mat; } } while((mat = mat->globalNext)); } return NULL; } materialnum_t P_MaterialCheckNumForIndex(uint idx, material_namespace_t mnamespace) { if(!initedOk) return 0; // Caller wants a material in a specific namespace. if(!isKnownMNamespace(mnamespace)) { #if _DEBUG Con_Message("P_GetMaterial: Internal error, invalid namespace '%i'\n", (int) mnamespace); #endif return 0; } return getMaterialNumForIndex(idx, mnamespace); } /** * Given a texture/flat/sprite/etc index num, search the materials db for * a name-bound material. * \note Part of the Doomsday public API. * \note2 Sames as P_MaterialCheckNumForIndex except will log an error * message if the material being searched for is not found. * * @param idx Index of the texture/flat/sprite/etc. * @param mnamespace MG_* namespace. * * @return Unique identifier of the found material, else zero. */ materialnum_t P_MaterialNumForIndex(uint idx, material_namespace_t mnamespace) { materialnum_t result = P_MaterialCheckNumForIndex(idx, mnamespace); // Not found? Don't announce during map setup or if not yet inited. if(verbose && result == 0 && (!ddMapSetup || !initedOk)) Con_Message("P_MaterialNumForIndex: %u in namespace %i not found!\n", idx, mnamespace); return result; } /** * Given a name and namespace, search the materials db for a match. * \note Part of the Doomsday public API. * * @param name Name of the material to search for. * @param mnamespace Specific MG_* namespace ELSE, * @c MN_ANY = no namespace requirement in which case * the material is searched for among all namespaces * using a logic which prioritizes the namespaces as * follows: * 1st: MN_SPRITES * 2nd: MN_TEXTURES * 3rd: MN_FLATS * * @return Unique number of the found material, else zero. */ materialnum_t P_MaterialCheckNumForName(const char* rawName, material_namespace_t mnamespace) { int n; uint hash; char name[9]; if(!initedOk) return 0; // In original DOOM, texture name references beginning with the // hypen '-' character are always treated as meaning "no reference" // or "invalid texture" and surfaces using them were not drawn. if(!rawName || !rawName[0] || rawName[0] == '-') return 0; if(mnamespace != MN_ANY && !isKnownMNamespace(mnamespace)) { #if _DEBUG Con_Message("P_GetMaterial: Internal error, invalid namespace '%i'\n", (int) mnamespace); #endif return 0; } // Prepare 'name'. for(n = 0; *rawName && n < 8; ++n, rawName++) name[n] = tolower(*rawName); name[n] = '\0'; hash = hashForName(name); if(mnamespace == MN_ANY) { // Caller doesn't care which namespace. materialnum_t matNum; // Check for the material in these namespaces, in priority order. if((matNum = getMaterialNumForName(name, hash, MN_SPRITES))) return matNum; if((matNum = getMaterialNumForName(name, hash, MN_TEXTURES))) return matNum; if((matNum = getMaterialNumForName(name, hash, MN_FLATS))) return matNum; return 0; // Not found. } // Caller wants a material in a specific namespace. return getMaterialNumForName(name, hash, mnamespace); } /** * Given a name and namespace, search the materials db for a match. * \note Part of the Doomsday public API. * \note2 Same as P_MaterialCheckNumForName except will log an error * message if the material being searched for is not found. * * @param name Name of the material to search for. * @param mnamespace MG_* namespace. * * @return Unique identifier of the found material, else zero. */ materialnum_t P_MaterialNumForName(const char* name, material_namespace_t mnamespace) { materialnum_t result; if(!initedOk) return 0; // In original DOOM, texture name references beginning with the // hypen '-' character are always treated as meaning "no reference" // or "invalid texture" and surfaces using them were not drawn. if(!name || !name[0] || name[0] == '-') return 0; result = P_MaterialCheckNumForName(name, mnamespace); // Not found? if(verbose && result == 0 && !ddMapSetup) // Don't announce during map setup. Con_Message("P_MaterialNumForName: \"%.8s\" in namespace %i not found!\n", name, mnamespace); return result; } /** * Given a unique material identifier, lookup the associated name. * \note Part of the Doomsday public API. * * @param mat The material to lookup the name for. * * @return The associated name. */ const char* P_GetMaterialName(material_t* mat) { materialnum_t num; if(!initedOk) return NULL; if(mat && (num = P_ToMaterialNum(mat))) return materialBinds[num-1].name; return "NOMAT"; // Should never happen. } /** * Precache the specified material. * \note Part of the Doomsday public API. * * @param mat The material to be precached. */ void P_MaterialPrecache(material_t* mat) { if(!initedOk) return; Material_Precache(mat); } /** * Called every tic by P_Ticker. */ void P_MaterialManagerTicker(timespan_t time) { // material_t* mat; static trigger_t fixed = { 1.0 / 35, 0 }; // The animation will only progress when the game is not paused. if(clientPaused) return; #if 0 mat = materialsHead; while(mat) { Material_Ticker(mat, time); mat = mat->globalNext; } #endif if(!M_RunTrigger(&fixed, time)) return; animateAnimGroups(); } static void printMaterialInfo(materialnum_t num, boolean printNamespace) { const materialbind_t* mb = &materialBinds[num]; int numDigits = M_NumDigits(numMaterialBinds); uint i; Con_Printf(" %*u - \"%s\"", numDigits, (unsigned int) num, mb->name); if(printNamespace) Con_Printf(" (%i)", mb->mat->mnamespace); Con_Printf(" [%i, %i]", mb->mat->width, mb->mat->height); for(i = 0; i < mb->mat->numLayers; ++i) { Con_Printf(" %i:%s", i, GL_GetGLTexture(mb->mat->layers[i].tex)->name); } Con_Printf("\n"); } static void printMaterials(material_namespace_t mnamespace, const char* like) { materialnum_t i; if(!(mnamespace < NUM_MATERIAL_NAMESPACES)) return; if(mnamespace == MN_ANY) { Con_Printf("Known Materials (IDX - Name (Namespace) [width, height]):\n"); for(i = 0; i < numMaterialBinds; ++i) { materialbind_t* mb = &materialBinds[i]; if(like && like[0] && strnicmp(mb->name, like, strlen(like))) continue; printMaterialInfo(i, true); } } else { Con_Printf("Known Materials in Namespace %i (IDX - Name " "[width, height]):\n", mnamespace); if(materialBinds) { uint i; for(i = 0; i < MATERIAL_NAME_HASH_SIZE; ++i) if(hashTable[mnamespace][i]) { materialnum_t num = hashTable[mnamespace][i] - 1; materialbind_t* mb = &materialBinds[num]; for(;;) { if(like && like[0] && strnicmp(mb->name, like, strlen(like))) continue; printMaterialInfo(num, false); if(!mb->hashNext) break; mb = &materialBinds[mb->hashNext - 1]; } } } } } D_CMD(ListMaterials) { material_namespace_t mnamespace = MN_ANY; if(argc > 1) { mnamespace = atoi(argv[1]); if(mnamespace < MN_FIRST) { mnamespace = MN_ANY; } else if(!(mnamespace < NUM_MATERIAL_NAMESPACES)) { Con_Printf("Invalid namespace \"%s\".\n", argv[1]); return false; } } printMaterials(mnamespace, argc > 2? argv[2] : NULL); return true; } // Code bellow needs re-implementing -------------------------------------- typedef struct animframe_s { material_t* mat; ushort tics; ushort random; } animframe_t; typedef struct animgroup_s { int id; int flags; int index; int maxTimer; int timer; int count; animframe_t* frames; } animgroup_t; static int numgroups; static animgroup_t* groups; static animgroup_t* getAnimGroup(int number) { if(--number < 0 || number >= numgroups) return NULL; return &groups[number]; } static boolean isInAnimGroup(animgroup_t* group, const material_t* mat) { int i; if(!mat || !group) return false; // Is it in there? for(i = 0; i < group->count; ++i) { animframe_t* frame = &group->frames[i]; if(frame->mat == mat) return true; } return false; } boolean R_IsInAnimGroup(int groupNum, material_t* mat) { return isInAnimGroup(getAnimGroup(groupNum), mat); } int R_NumAnimGroups(void) { return numgroups; } /** * Create a new animation group. Returns the group number. * \note Part of the Doomsday public API. */ int R_CreateAnimGroup(int flags) { animgroup_t* group; // Allocating one by one is inefficient, but it doesn't really matter. groups = Z_Realloc(groups, sizeof(animgroup_t) * (numgroups + 1), PU_STATIC); // Init the new group. group = &groups[numgroups]; memset(group, 0, sizeof(*group)); // The group number is (index + 1). group->id = ++numgroups; group->flags = flags; return group->id; } /** * Called during engine reset to clear the existing animation groups. */ void R_DestroyAnimGroups(void) { int i; if(numgroups > 0) { for(i = 0; i < numgroups; ++i) { animgroup_t* group = &groups[i]; Z_Free(group->frames); } Z_Free(groups); groups = NULL; numgroups = 0; } } /** * \note Part of the Doomsday public API. */ void R_AddToAnimGroup(int groupNum, materialnum_t num, int tics, int randomTics) { animgroup_t* group; animframe_t* frame; material_t* mat; group = getAnimGroup(groupNum); if(!group) Con_Error("R_AddToAnimGroup: Unknown anim group '%i'\n.", groupNum); if(!num || !(mat = getMaterialByNum(num - 1))) { Con_Message("R_AddToAnimGroup: Invalid material num '%i'\n.", num); return; } // Mark the material as being in an animgroup. mat->inAnimGroup = true; // Allocate a new animframe. group->frames = Z_Realloc(group->frames, sizeof(animframe_t) * ++group->count, PU_STATIC); frame = &group->frames[group->count - 1]; frame->mat = mat; frame->tics = tics; frame->random = randomTics; } boolean R_IsPrecacheGroup(int groupNum) { animgroup_t* group; if((group = getAnimGroup(groupNum))) { return (group->flags & AGF_PRECACHE)? true : false; } return false; } static void animateAnimGroups(void) { int i, timer, k; animgroup_t* group; for(i = 0, group = groups; i < numgroups; ++i, group++) { // The Precache groups are not intended for animation. if((group->flags & AGF_PRECACHE) || !group->count) continue; if(--group->timer <= 0) { // Advance to next frame. group->index = (group->index + 1) % group->count; timer = (int) group->frames[group->index].tics; if(group->frames[group->index].random) { timer += (int) RNG_RandByte() % (group->frames[group->index].random + 1); } group->timer = group->maxTimer = timer; // Update translations. for(k = 0; k < group->count; ++k) { material_t* real, *current, *next; real = group->frames[k].mat; current = group->frames[(group->index + k) % group->count].mat; next = group->frames[(group->index + k + 1) % group->count].mat; Material_SetTranslation(real, current, next, 0); // Just animate the first in the sequence? if(group->flags & AGF_FIRST_ONLY) break; } } else { // Update the interpolation point of animated group members. for(k = 0; k < group->count; ++k) { material_t* mat = group->frames[k].mat; if(group->flags & AGF_SMOOTH) { mat->inter = 1 - group->timer / (float) group->maxTimer; } else { mat->inter = 0; } // Just animate the first in the sequence? if(group->flags & AGF_FIRST_ONLY) break; } } } } /** * All animation groups are reseted back to their original state. * Called when setting up a map. */ void R_ResetAnimGroups(void) { int i; animgroup_t* group; for(i = 0, group = groups; i < numgroups; ++i, group++) { // The Precache groups are not intended for animation. if((group->flags & AGF_PRECACHE) || !group->count) continue; group->timer = 0; group->maxTimer = 1; // The anim group should start from the first step using the // correct timings. group->index = group->count - 1; } // This'll get every group started on the first step. animateAnimGroups(); } void R_MaterialsPrecacheGroup(material_t* mat) { int i; for(i = 0; i < numgroups; ++i) { if(isInAnimGroup(&groups[i], mat)) { int k; // Precache this group. for(k = 0; k < groups[i].count; ++k) { animframe_t* frame = &groups[i].frames[k]; Material_Prepare(NULL, frame->mat, true, NULL); } } } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_huffman.c0000644000175000017500000004003111357170242023033 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_huffman.c: Huffman Codes * * Huffman encoding/decoding using predetermined, fixed frequencies. * NOT THREAD-SAFE (static buffers used for storing data) */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ //#define PRINT_CODES // TYPES ------------------------------------------------------------------- typedef struct huffnode_s { struct huffnode_s *left, *right; double freq; byte value; // Only valid for leaves. } huffnode_t; typedef struct huffqueue_s { huffnode_t *nodes[256]; int count; } huffqueue_t; typedef struct huffcode_s { uint code; uint length; } huffcode_t; typedef struct huffbuffer_s { byte *data; uint size; } huffbuffer_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ /* * Total number of bytes: 4857074 * Frequencies calculated in jHexen, co-op (1p) hub 2, map4, map5 * (12 min, frame interval 0). * * Optimal compression: 69.6% */ static double freqs[256] = { 0.261347881463, 0.016916769232, 0.099777149782, 0.007231102512, 0.078927148320, 0.003303840954, 0.003997674320, 0.051381346053, 0.004863421887, 0.002004704890, 0.023628011432, 0.001021396833, 0.010792094170, 0.001282047587, 0.001111368696, 0.000778452212, 0.005905613133, 0.000729039747, 0.002841010864, 0.011992199419, 0.005981378912, 0.000727804435, 0.005555402285, 0.000820864578, 0.003674846214, 0.001290077112, 0.001652229305, 0.002900099937, 0.001201340560, 0.000922983673, 0.001000602420, 0.000942748659, 0.008744976914, 0.000595008435, 0.001374078303, 0.001144927996, 0.003616374797, 0.001251164796, 0.001358019252, 0.001723053839, 0.000872747667, 0.001004926011, 0.000651009229, 0.001242517615, 0.001207723004, 0.001599728561, 0.001360901646, 0.001332695364, 0.004142205781, 0.001597669708, 0.001850702707, 0.001053309050, 0.000786069967, 0.001016867357, 0.002317650503, 0.000990308157, 0.001347519103, 0.001928115569, 0.001500491860, 0.002002234267, 0.001933674472, 0.001370784139, 0.001208134774, 0.001714612542, 0.005039453795, 0.002550918516, 0.002118353560, 0.003177839168, 0.001923380208, 0.001494932958, 0.001643582124, 0.001712553690, 0.001529521683, 0.001255900157, 0.001523345125, 0.001288635915, 0.001455402985, 0.000617861700, 0.000676333117, 0.000837541285, 0.003083749599, 0.000586361254, 0.000994425862, 0.001056191444, 0.000882836045, 0.002295209009, 0.001077397627, 0.001015014389, 0.001331665937, 0.001822084654, 0.003632227963, 0.001015837930, 0.000865335797, 0.000736863387, 0.000598302599, 0.000684774414, 0.003247016619, 0.001498638892, 0.000759098997, 0.000711745384, 0.000926895493, 0.000828482333, 0.000836100088, 0.000679215511, 0.001347724988, 0.000768775604, 0.000724510271, 0.001178487295, 0.000712363040, 0.000693009824, 0.000760951964, 0.000659656410, 0.006524298374, 0.000662950575, 0.000968690203, 0.001575022328, 0.001306547934, 0.001461785429, 0.001409078799, 0.000990514042, 0.001219870235, 0.002090147278, 0.001233664548, 0.000780511065, 0.000655950476, 0.000589037762, 0.005355281801, 0.002871275999, 0.012205908331, 0.001121457075, 0.001259194322, 0.001241282303, 0.000553213725, 0.000456447647, 0.000562272677, 0.000433594382, 0.000508124850, 0.000560625595, 0.000521095623, 0.000535095821, 0.000518007344, 0.000676539003, 0.000595626091, 0.000676744888, 0.011022685675, 0.001302841999, 0.001583257739, 0.001272782749, 0.001249105943, 0.001152751636, 0.000997308256, 0.000526448640, 0.000746128225, 0.000989484616, 0.001275047487, 0.001116309943, 0.001525403978, 0.001194134576, 0.001201134675, 0.000638244342, 0.009756079483, 0.000558566742, 0.000810364429, 0.000763010817, 0.001378607779, 0.001397137454, 0.001303253770, 0.001260841404, 0.001317253968, 0.001550110210, 0.001201752331, 0.001166340064, 0.001016867357, 0.001269282700, 0.001046514836, 0.000477653830, 0.009010363029, 0.000524595672, 0.000525419213, 0.000557743201, 0.000509154277, 0.000721216107, 0.000516977917, 0.000750040045, 0.000867188764, 0.000793893608, 0.000699186383, 0.001072662265, 0.000882630160, 0.000708039449, 0.000686627381, 0.000714010122, 0.009556370770, 0.000669333018, 0.000901983375, 0.001089338972, 0.001178899066, 0.001021808603, 0.001060309149, 0.001137927897, 0.001738083463, 0.001676935538, 0.001687847457, 0.001666435389, 0.001912468289, 0.001787084158, 0.001850702707, 0.003220869190, 0.010349029066, 0.002433769796, 0.002500064854, 0.001287194718, 0.001127839518, 0.001192487493, 0.001099839121, 0.001036632343, 0.001130310141, 0.001100868548, 0.001021808603, 0.000994631747, 0.001126810092, 0.001035602916, 0.001080485906, 0.001121868845, 0.009375809386, 0.001078632938, 0.001236546942, 0.001240870532, 0.001318901050, 0.001059897379, 0.001052691394, 0.001085221267, 0.001181369689, 0.000856276845, 0.001283900554, 0.001125163010, 0.001325901150, 0.001437902737, 0.001482373956, 0.001487726973, 0.005829023811, 0.001277929881, 0.001573787017, 0.001741377628, 0.001309636213, 0.001333930675, 0.000908983474, 0.001500080089, 0.001828055327, 0.001625670105, 0.001895379811, 0.002661273022, 0.003641698685, 0.003401018803, 0.005049130402, 0.010072525146 }; // The root of the Huffman tree. static huffnode_t *huffRoot; // The lookup table for encoding. static huffcode_t huffCodes[256]; // The buffer used for the result of encoding/decoding. static huffbuffer_t huffEnc, huffDec; // CODE -------------------------------------------------------------------- /** * Exchange two nodes in the queue. */ static void Huff_QueueExchange(huffqueue_t *queue, int index1, int index2) { huffnode_t *temp = queue->nodes[index1]; queue->nodes[index1] = queue->nodes[index2]; queue->nodes[index2] = temp; } /** * Insert a node into a priority queue. */ static void Huff_QueueInsert(huffqueue_t *queue, huffnode_t *node) { int i, parent; // Add the new node to the end of the queue. i = queue->count; queue->nodes[i] = node; ++queue->count; // Rise in the heap until the correct place is found. while(i > 0) { parent = HEAP_PARENT(i); // Is it good now? if(queue->nodes[parent]->freq <= node->freq) break; // Exchange with the parent. Huff_QueueExchange(queue, parent, i); i = parent; } } /** * Extract the smallest node from the queue. */ static huffnode_t *Huff_QueueExtract(huffqueue_t *queue) { huffnode_t *min; int i, left, right, small; if(!queue->count) { Con_Error("Huff_QueueExtract: Out of nodes.\n"); } // This is what we'll return. min = queue->nodes[0]; // Remove the first element from the queue. queue->nodes[0] = queue->nodes[--queue->count]; // Heapify the heap. This is O(log n). i = 0; for(;;) { left = HEAP_LEFT(i); right = HEAP_RIGHT(i); small = i; // Which child has smaller freq? if(left < queue->count && queue->nodes[left]->freq < queue->nodes[i]->freq) { small = left; } if(right < queue->count && queue->nodes[right]->freq < queue->nodes[small]->freq) { small = right; } // Can we stop now? if(i == small) { // Heapifying is complete. break; } // Exchange and continue. Huff_QueueExchange(queue, i, small); i = small; } return min; } /** * Recursively builds the Huffman code lookup for the node's subtree. */ static void Huff_BuildLookup(huffnode_t *node, uint code, uint length) { if(!node->left && !node->right) { // This is a leaf. huffCodes[node->value].code = code; huffCodes[node->value].length = length; return; } if(length == 32) { Con_Error("Huff_BuildLookup: Out of bits, length = %i\n", length); } // Descend into the left and right subtrees. if(node->left) { // This child's bit is zero. Huff_BuildLookup(node->left, code, length + 1); } if(node->right) { // This child's bit is one. Huff_BuildLookup(node->right, code | (1 << length), length + 1); } } /** * Checks if the encoding/decoding buffer can hold the given number of * bytes. If not, reallocates the buffer. */ static void Huff_CheckBuffer(huffbuffer_t *buffer, size_t neededSize) { byte *tempbuffer; while(neededSize > buffer->size) { buffer->size *= 2; if(!buffer->size) buffer->size = 0x2000; if((tempbuffer = M_Realloc(buffer->data, buffer->size)) == NULL) Con_Error("Huff_CheckBuffer: realloc failed."); buffer->data = tempbuffer; } } /** * Build the Huffman tree and initialize the code lookup. * (CLR 2nd Ed, p. 388) */ void Huff_Init(void) { huffqueue_t queue; huffnode_t *node; int i; // Initialize the priority queue that holds the remaining nodes. queue.count = 0; for(i = 0; i < 256; ++i) { // These are the leaves of the tree. node = M_Calloc(sizeof(huffnode_t)); node->freq = freqs[i]; node->value = i; Huff_QueueInsert(&queue, node); } // Build the tree. for(i = 0; i < 255; ++i) { node = M_Calloc(sizeof(huffnode_t)); node->left = Huff_QueueExtract(&queue); node->right = Huff_QueueExtract(&queue); node->freq = node->left->freq + node->right->freq; Huff_QueueInsert(&queue, node); } // The root is the last node left in the queue. huffRoot = Huff_QueueExtract(&queue); // Fill in the code lookup table. Huff_BuildLookup(huffRoot, 0, 0); // Allocate memory for the encoding/decoding buffer. Huff_CheckBuffer(&huffEnc, 0x10000); Huff_CheckBuffer(&huffDec, 0x10000); if(ArgExists("-huffcodes")) { double realBits = 0; double huffBits = 0; Con_Printf("Huffman codes:\n"); for(i = 0; i < 256; ++i) { uint k; realBits += freqs[i] * 8; huffBits += freqs[i] * huffCodes[i].length; Con_Printf("%03i: (%07i) ", i, (int) (6e6 * freqs[i])); for(k = 0; k < huffCodes[i].length; ++k) { Con_Printf("%c", huffCodes[i].code & (1 << k) ? '1' : '0'); } Con_Printf("\n"); } Con_Printf("realbits=%f, huffbits=%f (%f%%)\n", realBits, huffBits, huffBits / realBits * 100); } } /** * Recursively frees the node and its subtree. */ static void Huff_DestroyNode(huffnode_t *node) { if(node) { Huff_DestroyNode(node->left); Huff_DestroyNode(node->right); M_Free(node); } } /** * Free the buffer. */ static void Huff_DestroyBuffer(huffbuffer_t *buffer) { M_Free(buffer->data); memset(buffer, 0, sizeof(*buffer)); } /** * Free all resources allocated here. */ void Huff_Shutdown(void) { Huff_DestroyNode(huffRoot); huffRoot = NULL; // Free the encoding/decoding buffer. Huff_DestroyBuffer(&huffEnc); Huff_DestroyBuffer(&huffDec); } /** * Encode the data using Huffman codes. Returns a pointer to the encoded * block of bits. The number of bytes in the encoded data is returned * in 'encodedSize'. */ void *Huff_Encode(byte *data, size_t size, size_t *encodedSize) { size_t i; uint code; int remaining, fits; byte *out, bit; // The encoded message is never twice the original size // (longest codes are currently 11 bits). Huff_CheckBuffer(&huffEnc, 2 * size); // First three bits of the encoded data contain the number of bits (-1) // in the last byte of the encoded data. It's written when we have // finished the encoding. bit = 3; // Clear the first byte of the result. out = huffEnc.data; *out = 0; for(i = 0; i < size; ++i) { remaining = huffCodes[data[i]].length; code = huffCodes[data[i]].code; while(remaining > 0) { fits = 8 - bit; if(fits > remaining) fits = remaining; // Write the bits that fit the current byte. *out |= code << bit; code >>= fits; remaining -= fits; // Advance the bit position. bit += fits; if(bit == 8) { bit = 0; *++out = 0; } } } // If the last byte is empty, back up. if(bit == 0) { out--; bit = 8; } if(encodedSize) *encodedSize = out - huffEnc.data + 1; // The number of valid bits - 1 in the last byte. huffEnc.data[0] |= bit - 1; /*#if _DEBUG { // Test decode. byte *backup = M_Malloc(huffDec.size); size_t decsize; memcpy(backup, huffDec.data, huffDec.size); Huff_Decode(huffEnc.data, *encodedSize, &decsize); if(decsize != size || memcmp(huffDec.data, data, size)) { Con_Error("Huff_Encode: Data corruption!\n"); } memcpy(huffDec.data, backup, huffDec.size); M_Free(backup); } #endif*/ return huffEnc.data; } /** * Decode using the Huffman tree. Returns a pointer to the decoded data. */ byte *Huff_Decode(void *data, size_t size, size_t *decodedSize) { huffnode_t *node; size_t outBytes = 0; byte *in = data, bit = 3, lastByteBits; byte *lastIn = in + size - 1; // The first three bits contain the number of valid bits in // the last byte. lastByteBits = (*in & 7) + 1; // Start from the root node. node = huffRoot; while(in < lastIn || bit < lastByteBits) { // Go left or right? if(*in & (1 << bit)) { node = node->right; } else { node = node->left; } // Did we arrive at a leaf? if(!node->left && !node->right) { // This node represents a value. huffDec.data[outBytes++] = node->value; // Should we allocate more memory? if(outBytes == huffDec.size) { Huff_CheckBuffer(&huffDec, 2 * huffDec.size); } // Back to the root. node = huffRoot; } // Advance bit position. if(++bit == 8) { bit = 0; ++in; // Out of buffer? if(in > lastIn) break; } } if(decodedSize) *decodedSize = outBytes; return huffDec.data; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_args.c0000644000175000017500000002405011357170242022346 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_args.c: Command Line Arguments */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include "de_base.h" #include "de_console.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define MAX_ARG_NAMES (256) // TYPES ------------------------------------------------------------------- enum // Parser modes. { PM_NORMAL, PM_NORMAL_REC, PM_COUNT }; typedef struct { char longName[32]; char shortName[8]; } argname_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int numArgs; static char** args; static int argPos; static int numNames; static argname_t* names[MAX_ARG_NAMES]; static int lastMatch; // CODE -------------------------------------------------------------------- /** * Parses the given command line. */ int ArgParse(int mode, const char* cmdline) { #define MAX_WORDLENGTH (512) char word[MAX_WORDLENGTH], *ptr, *response; unsigned char* cmd; int i, count = 0, ccount; FILE* file; boolean quote = false, isResponse, isDone, copyC; // Init normal mode? if(mode == PM_NORMAL) argPos = 0; cmd = (unsigned char*) cmdline; isDone = false; while(*cmd && !isDone) { /** * Must allow: -cmd "echo ""this is a command""" * But also: @"\Program Files\test.rsp\" * And also: @\"Program Files"\test.rsp * Hello" My"Friend means "Hello MyFriend" */ // Skip initial whitespace. cmd = (unsigned char*) M_SkipWhite((char *) cmd); // Check for response files. if(*cmd == '@') { isResponse = true; cmd = (unsigned char*) M_SkipWhite((char *)(cmd + 1)); } else { isResponse = false; } ccount = 0; ptr = word; while(*cmd && (quote || !isspace(*cmd))) { copyC = true; if(!quote) { // We're not inside quotes. if(*cmd == '\"') // Quote begins. { quote = true; copyC = false; } } else { // We're inside quotes. if(*cmd == '\"') // Quote ends. { if(cmd[1] == '\"') // Doubles? { // Normal processing, but output only one quote. cmd++; ccount++; } else { quote = false; copyC = false; } } } if(copyC) { if(ccount > MAX_WORDLENGTH -1) Con_Error("ArgParse: too many characters in word!"); *ptr++ = *cmd; } cmd++; ccount++; } // Append NULL to the word. *ptr++ = '\0'; // Word has been extracted, examine it. if(isResponse) // Response file? { // Try to open it. if((file = fopen(word, "rt")) != NULL) { // How long is it? if(fseek(file, 0, SEEK_END)) Con_Error("ArgParse: fseek failed on SEEK_END!"); i = ftell(file); rewind(file); if((response = M_Calloc(i + 1)) == NULL) Con_Error("ArgParse: failed on alloc of %d bytes.", i + 1); fread(response, 1, i, file); fclose(file); count += ArgParse(mode == PM_COUNT ? PM_COUNT : PM_NORMAL_REC, response); M_Free(response); } } else if(!strcmp(word, "--")) // End of arguments. { isDone = true; } else if(word[0]) // Make sure there *is* a word. { // Increase argument count. count++; if(mode != PM_COUNT) { // Allocate memory for the argument and copy it to the list. args[argPos] = M_Malloc(strlen(word) + 1); strcpy(args[argPos++], word); } } } return count; } /** * Initializes the command line arguments list. */ void ArgInit(const char* cmdline) { // Clear the names register. numNames = 0; memset(names, 0, sizeof(names)); // First count the number of arguments. numArgs = ArgParse(PM_COUNT, cmdline); // Allocate memory for the list. args = M_Calloc(numArgs * sizeof(char *)); // Then create the actual list of arguments. ArgParse(PM_NORMAL, cmdline); } /** * Frees the memory allocated for the command line. */ void ArgShutdown(void) { int i; for(i = 0; i < numArgs; ++i) M_Free(args[i]); M_Free(args); args = NULL; numArgs = 0; for(i = 0; i < numNames; ++i) M_Free(names[i]); memset(names, 0, sizeof(names)); numNames = 0; } /** * Registers a short name for a long arg name. * The short name can then be used on the command line and CheckParm * will know to match occurances of the short name with the long name. */ void ArgAbbreviate(const char* longName, const char* shortName) { argname_t* name; if(numNames == MAX_ARG_NAMES) return; if((name = M_Calloc(sizeof(*name))) == NULL) Con_Error("ArgAbbreviate: failed on allocation of %lu bytes.", (unsigned long) sizeof(*name)); names[numNames++] = name; strncpy(name->longName, longName, sizeof(name->longName) - 1); strncpy(name->shortName, shortName, sizeof(name->shortName) - 1); } /** * @return The number of arguments on the command line. */ int Argc(void) { return numArgs; } /** * @return Pointer to the i'th argument. */ const char* Argv(int i) { if(i < 0 || i >= numArgs) Con_Error("Argv: There is no arg %i.\n", i); return args[i]; } /** * @return Pointer to the i'th argument's pointer. */ const char** ArgvPtr(int i) { if(i < 0 || i >= numArgs) Con_Error("ArgvPtr: There is no arg %i.\n", i); return &args[i]; } const char* ArgNext(void) { if(!lastMatch || lastMatch >= Argc() - 1) return NULL; return args[++lastMatch]; } /** * @return @c true, iff the two parameters are equivalent * according to the abbreviations. */ int ArgRecognize(const char* first, const char* second) { int k; boolean match; // A simple match? if(!stricmp(first, second)) return true; match = false; k = 0; while(k < numNames && !match) { if(!stricmp(first, names[k]->longName)) { // names[k] now matches the first string. if(!stricmp(names[k]->shortName, second)) match = true; } k++; } return match; } /** * Checks for the given parameter in the program's command line arguments. * * @return The argument number (1 to argc-1) else * @c 0 if not present. */ int ArgCheck(const char* check) { int i; boolean isDone; lastMatch = 0; i = 1; isDone = false; while(i < numArgs && !isDone) { // Check the short names for this arg, too. if(ArgRecognize(check, args[i])) { lastMatch = i; isDone = true; } else i++; } return lastMatch; } /** * Checks for the given parameter in the program's command line arguments * and it is followed by N other arguments. * * @return The argument number (1 to argc-1) else * @c 0 if not present. */ int ArgCheckWith(const char* check, int num) { int i = ArgCheck(check); if(!i || i + num >= numArgs) return 0; return i; } /** * @return @c true, if the given argument begins with a hyphen. */ int ArgIsOption(int i) { if(i < 0 || i >= numArgs) return false; return args[i][0] == '-'; } /** * Determines if an argument exists on the command line. * * @return Number of times the argument is found. */ int ArgExists(const char* check) { int i, count; for(i = 1, count = 0; i < Argc(); ++i) if(ArgRecognize(check, Argv(i))) count++; return count; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sv_main.c0000644000175000017500000010770111357170242022537 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_main.c: Network Server */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_play.h" #include "de_misc.h" #include "r_world.h" // MACROS ------------------------------------------------------------------ // This is absolute maximum bandwidth rating. Frame size is practically // unlimited with this score. #define MAX_BANDWIDTH_RATING 100 // When the difference between clientside and serverside positions is this // much, server will update its position to match the clientside position, // which is assumed to be correct. #define WARP_LIMIT 300 // Maximum length of a token in the textual representation of // serverinfo. #define TOKEN_LEN 128 #define VALID_LABEL_LEN 16 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void Sv_ClientCoords(int playerNum); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int netRemoteUser = 0; // The client who is currently logged in. char *netPassword = ""; // Remote login password. // This is the limit when accepting new clients. int svMaxPlayers = DDMAXPLAYERS; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Fills the provided struct with information about the local server. */ void Sv_GetInfo(serverinfo_t *info) { int i; gamemap_t *currentMap = P_GetCurrentMap(); memset(info, 0, sizeof(*info)); // Let's figure out what we want to tell about ourselves. info->version = DOOMSDAY_VERSION; strncpy(info->game, gx.GetVariable(DD_GAME_ID), sizeof(info->game) - 1); strncpy(info->gameMode, gx.GetVariable(DD_GAME_MODE), sizeof(info->gameMode) - 1); strncpy(info->gameConfig, gx.GetVariable(DD_GAME_CONFIG), sizeof(info->gameConfig) - 1); strncpy(info->name, serverName, sizeof(info->name) - 1); strncpy(info->description, serverInfo, sizeof(info->description) - 1); info->numPlayers = Sv_GetNumPlayers(); // The server player is there, it's just hidden. info->maxPlayers = DDMAXPLAYERS - (isDedicated ? 1 : 0); // Don't go over the limit. if(info->maxPlayers > svMaxPlayers) info->maxPlayers = svMaxPlayers; info->canJoin = (isServer != 0 && Sv_GetNumPlayers() < svMaxPlayers); // Identifier of the current map. strncpy(info->map, P_GetMapID(currentMap), sizeof(info->map) - 1); // These are largely unused at the moment... Mainly intended for // the game's custom values. memcpy(info->data, serverData, sizeof(info->data)); // Also include the port we're using. info->port = nptIPPort; // Let's compile a list of client names. for(i = 0; i < DDMAXPLAYERS; ++i) if(clients[i].connected) { M_LimitedStrCat(info->clientNames, clients[i].name, 15, ';', sizeof(info->clientNames)); } // Some WAD names. W_GetIWADFileName(info->iwad, sizeof(info->iwad) - 1); W_GetPWADFileNames(info->pwads, sizeof(info->pwads), ';'); // This should be a CRC number that describes all the loaded data. info->wadNumber = W_CRCNumber(); } /** * @return The length of the string. */ size_t Sv_InfoToString(serverinfo_t *info, ddstring_t *msg) { unsigned int i; Str_Appendf(msg, "port:%i\n", info->port); Str_Appendf(msg, "name:%s\n", info->name); Str_Appendf(msg, "info:%s\n", info->description); Str_Appendf(msg, "ver:%i\n", info->version); Str_Appendf(msg, "game:%s\n", info->game); Str_Appendf(msg, "mode:%s\n", info->gameMode); Str_Appendf(msg, "setup:%s\n", info->gameConfig); Str_Appendf(msg, "iwad:%s\n", info->iwad); Str_Appendf(msg, "wcrc:%i\n", info->wadNumber); Str_Appendf(msg, "pwads:%s\n", info->pwads); Str_Appendf(msg, "map:%s\n", info->map); Str_Appendf(msg, "nump:%i\n", info->numPlayers); Str_Appendf(msg, "maxp:%i\n", info->maxPlayers); Str_Appendf(msg, "open:%i\n", info->canJoin); Str_Appendf(msg, "plrn:%s\n", info->clientNames); for(i = 0; i < sizeof(info->data) / sizeof(info->data[0]); ++i) { Str_Appendf(msg, "data%i:%x\n", i, info->data[i]); } return Str_Length(msg); } /** * Extracts the label and value from a string. 'max' is the maximum * allowed length of a token, including terminating \0. */ static boolean Sv_Tokenize(const char *line, char *label, char *value, int max) { const char *src = line; const char *colon = strchr(src, ':'); // The colon must exist near the beginning. if(!colon || colon - src >= VALID_LABEL_LEN) return false; // Copy the label. memset(label, 0, max); strncpy(label, src, MIN_OF(colon - src, max - 1)); // Copy the value. memset(value, 0, max); strncpy(value, colon + 1, MIN_OF(strlen(line) - (colon - src + 1), (unsigned) max - 1)); // Everything is OK. return true; } /** * Converts textual data to a serverinfo struct. Returns true if the * label/value pair is recognized. */ boolean Sv_StringToInfo(const char *valuePair, serverinfo_t *info) { char label[TOKEN_LEN], value[TOKEN_LEN]; // Extract the label and value. The maximum length of a value is // TOKEN_LEN. Labels are returned in lower case. if(!Sv_Tokenize(valuePair, label, value, sizeof(value))) { // Badly formed lines are ignored. return false; } if(!strcmp(label, "at")) { strncpy(info->address, value, sizeof(info->address) - 1); } else if(!strcmp(label, "port")) { info->port = strtol(value, 0, 0); } else if(!strcmp(label, "ver")) { info->version = strtol(value, 0, 0); } else if(!strcmp(label, "map")) { strncpy(info->map, value, sizeof(info->map) - 1); } else if(!strcmp(label, "game")) { strncpy(info->game, value, sizeof(info->game) - 1); } else if(!strcmp(label, "name")) { strncpy(info->name, value, sizeof(info->name) - 1); } else if(!strcmp(label, "info")) { strncpy(info->description, value, sizeof(info->description) - 1); } else if(!strcmp(label, "nump")) { info->numPlayers = strtol(value, 0, 0); } else if(!strcmp(label, "maxp")) { info->maxPlayers = strtol(value, 0, 0); } else if(!strcmp(label, "open")) { info->canJoin = strtol(value, 0, 0); } else if(!strcmp(label, "mode")) { strncpy(info->gameMode, value, sizeof(info->gameMode) - 1); } else if(!strcmp(label, "setup")) { strncpy(info->gameConfig, value, sizeof(info->gameConfig) - 1); } else if(!strcmp(label, "iwad")) { strncpy(info->iwad, value, sizeof(info->iwad) - 1); } else if(!strcmp(label, "wcrc")) { info->wadNumber = strtol(value, 0, 0); } else if(!strcmp(label, "pwads")) { strncpy(info->pwads, value, sizeof(info->pwads) - 1); } else if(!strcmp(label, "plrn")) { strncpy(info->clientNames, value, sizeof(info->clientNames) - 1); } else if(!strcmp(label, "data0")) { info->data[0] = strtol(value, 0, 16); } else if(!strcmp(label, "data1")) { info->data[1] = strtol(value, 0, 16); } else if(!strcmp(label, "data2")) { info->data[2] = strtol(value, 0, 16); } else { // Unknown labels are ignored. return false; } return true; } /** * @return gametic - cmdtime. */ int Sv_Latency(byte cmdtime) { return Net_TimeDelta(SECONDS_TO_TICKS(gameTime), cmdtime); } /** * For local players. */ /* $unifiedangles */ /* void Sv_FixLocalAngles(boolean clearFixAnglesFlag) { ddplayer_t *pl; int i; for(i = 0; i < DDMAXPLAYERS; ++i) { pl = players + i; if(!pl->inGame || !(pl->flags & DDPF_LOCAL)) continue; // This is not for clients. if(isDedicated && i == 0) continue; if(pl->flags & DDPF_FIXANGLES) { if(clearFixAnglesFlag) { pl->flags &= ~DDPF_FIXANGLES; } else { pl->clAngle = pl->mo->angle; pl->clLookDir = pl->lookDir; } } } } */ void Sv_HandlePacket(void) { ident_t id; int i, mask, from = netBuffer.player; player_t *plr = &ddPlayers[from]; ddplayer_t *ddpl = &plr->shared; client_t *sender = &clients[from]; playerinfo_packet_t info; int msgfrom; char *msg; char buf[17]; #ifdef _DEBUG Con_Message("Sv_HandlePacket: type=%i\n", netBuffer.msg.type); Con_Message("Sv_HandlePacket: length=%i\n", netBuffer.length); #endif switch(netBuffer.msg.type) { case PCL_HELLO: case PCL_HELLO2: // Get the ID of the client. id = Msg_ReadLong(); Con_Printf("Sv_HandlePacket: Hello from client %i (%08X).\n", from, id); // Check for duplicate IDs. if(!ddpl->inGame && !sender->handshake) { for(i = 0; i < DDMAXPLAYERS; ++i) { if(clients[i].connected && clients[i].id == id) { // Send a message to everybody. Con_FPrintf(CBLF_TRANSMIT | SV_CONSOLE_FLAGS, "New client connection refused: Duplicate ID " "(%08x). From=%i, i=%i\n", id, from, i); N_TerminateClient(from); break; } } if(i < DDMAXPLAYERS) break; // Can't continue, refused! } // This is OK. sender->id = id; if(netBuffer.msg.type == PCL_HELLO2) { // Check the game mode (max 16 chars). Msg_Read(buf, 16); if(strnicmp(buf, gx.GetVariable(DD_GAME_MODE), 16)) { Con_Printf(" Bad Game ID: %-.16s\n", buf); N_TerminateClient(from); break; } } // The client requests a handshake. if(!ddpl->inGame && !sender->handshake) { // This'll be true until the client says it's ready. sender->handshake = true; // The player is now in the game. ddPlayers[from].shared.inGame = true; // Tell the game about this. gx.NetPlayerEvent(from, DDPE_ARRIVAL, 0); // Send the handshake packets. Sv_Handshake(from, true); // Note the time when the player entered. sender->enterTime = SECONDS_TO_TICKS(gameTime); sender->runTime = SECONDS_TO_TICKS(gameTime) - 1; //sender->lagStress = 0; } else if(ddpl->inGame) { // The player is already in the game but requests a new // handshake. Perhaps it's starting to record a demo. Sv_Handshake(from, false); } break; case PKT_OK: // The client says it's ready to receive frames. sender->ready = true; #ifdef _DEBUG Con_Printf("Sv_HandlePacket: OK (\"ready!\") from client %i " "(%08X).\n", from, sender->id); #endif if(sender->handshake) { // The handshake is complete. The client has acknowledged it // and sends its regards. sender->handshake = false; // Send a clock sync message. Msg_Begin(PSV_SYNC); Msg_WriteLong(SECONDS_TO_TICKS(gameTime) + (sender->shakePing * 35) / 2000); // Send reliably, although if it has to be resent, the tics // will already be way off... Net_SendBuffer(from, SPF_CONFIRM); // Send welcome string. Sv_SendText(from, SV_CONSOLE_FLAGS, SV_WELCOME_STRING "\n"); } break; case PKT_CHAT: // The first byte contains the sender. msgfrom = Msg_ReadByte(); // Is the message for us? mask = Msg_ReadShort(); // Copy the message into a buffer. // integer overflow in PKT_CHAT attacks us with an incomplete PKT_CHAT packet // with a size less then 3. As we will replace the entire netcode, lets bandaid this // by breaking out. Yagisan if(netBuffer.length <=3) break; // end of bandaid msg = M_Malloc(netBuffer.length - 3); strcpy(msg, (char *) netBuffer.cursor); // Message for us? Show it locally. if(mask & 1) { Net_ShowChatMessage(); gx.NetPlayerEvent(msgfrom, DDPE_CHAT_MESSAGE, msg); } // Servers relay chat messages to all the recipients. Msg_Begin(PKT_CHAT); Msg_WriteByte(msgfrom); Msg_WriteShort(mask); Msg_Write(msg, strlen(msg) + 1); for(i = 1; i < DDMAXPLAYERS; ++i) if(ddPlayers[i].shared.inGame && (mask & (1 << i)) && i != from) { Net_SendBuffer(i, SPF_ORDERED); } M_Free(msg); break; case PKT_PLAYER_INFO: Msg_Read(&info, sizeof(info)); Con_FPrintf(CBLF_TRANSMIT | SV_CONSOLE_FLAGS, "%s renamed to %s.\n", sender->name, info.name); strcpy(sender->name, info.name); Net_SendPacket(DDSP_CONFIRM | DDSP_ALL_PLAYERS, PKT_PLAYER_INFO, &info, sizeof(info)); break; default: Con_Error("Sv_HandlePacket: Invalid value, netBuffer.msg.type = %i.", (int) netBuffer.msg.type); break; } } /** * Handles a login packet. If the password is OK and no other client * is current logged in, a response is sent. */ void Sv_Login(void) { if(netRemoteUser) { Sv_SendText(netBuffer.player, SV_CONSOLE_FLAGS, "Sv_Login: A client is already logged in.\n"); return; } // Check the password. if(strcmp((char *) netBuffer.cursor, netPassword)) { Sv_SendText(netBuffer.player, SV_CONSOLE_FLAGS, "Sv_Login: Invalid password.\n"); return; } // OK! netRemoteUser = netBuffer.player; Con_Printf("Sv_Login: %s (client %i) logged in.\n", clients[netRemoteUser].name, netRemoteUser); // Send a confirmation packet to the client. Msg_Begin(PKT_LOGIN); Msg_WriteByte(true); // Yes, you're logged in. Net_SendBuffer(netRemoteUser, SPF_ORDERED); } /** * Executes the command in the message buffer. * Usually sent by Con_Send. */ void Sv_ExecuteCommand(void) { int flags; byte cmdSource; unsigned short len; boolean silent; if(!netRemoteUser) { Con_Printf ("Sv_ExecuteCommand: Cmd received but no one's logged in!\n"); return; } // The command packet is very simple. len = Msg_ReadShort(); silent = (len & 0x8000) != 0; len &= 0x7fff; switch(netBuffer.msg.type) { case PKT_COMMAND: cmdSource = CMDS_UNKNOWN; // unknown command source. break; case PKT_COMMAND2: // New format includes flags and command source. // Flags are currently unused but added for future expansion. flags = Msg_ReadShort(); cmdSource = Msg_ReadByte(); break; default: Con_Error("Sv_ExecuteCommand: Not a command packet!\n"); return; // shutup compiler } // Verify using string length. if(strlen((char *) netBuffer.cursor) != (unsigned) len - 1) { Con_Printf("Sv_ExecuteCommand: Damaged packet?\n"); return; } Con_Execute(cmdSource, (char *) netBuffer.cursor, silent, true); } /** * Server's packet handler. */ void Sv_GetPackets(void) { int netconsole; int start, num, i; client_t *sender; byte *unpacked; while(Net_GetPacket()) { switch(netBuffer.msg.type) { case PCL_COMMANDS: // Determine who sent this packet. netconsole = netBuffer.player; if(netconsole < 0 || netconsole >= DDMAXPLAYERS) continue; sender = &clients[netconsole]; // If the client isn't ready, don't accept any cmds. if(!clients[netconsole].ready) continue; // Now we know this client is alive, update the frame send count. // Clients will only be refreshed if their updateCount is greater // than zero. sender->updateCount = UPDATECOUNT; // Unpack the commands in the packet. Since the game defines the // ticcmd_t structure, it is the only one who can do this. unpacked = gx.NetReadCommands(netBuffer.length, (void*) netBuffer.msg.data); // The first two bytes contain the number of commands. num = *(ushort *) unpacked; unpacked += 2; // Add the tics into the client's ticcmd buffer, if there is room. // If the buffer overflows, the rest of the cmds will be forgotten. if(sender->numTics + num > BACKUPTICS) { num = BACKUPTICS - sender->numTics; } start = sender->firstTic + sender->numTics; // Increase the counter. sender->numTics += num; // Copy as many as fits (circular buffer). for(i = start; num > 0; num--, ++i) { if(i >= BACKUPTICS) i -= BACKUPTICS; memcpy(sender->ticCmds + TICCMD_IDX(i), unpacked, TICCMD_SIZE); unpacked += TICCMD_SIZE; } break; case PCL_ACK_SETS: // The client is acknowledging that it has received a number of // delta sets. while(!Msg_End()) { Sv_AckDeltaSet(netBuffer.player, Msg_ReadByte(), 0); } break; case PCL_ACKS: // The client is acknowledging both entire sets and resent deltas. // The first byte contains the acked set. Sv_AckDeltaSet(netBuffer.player, Msg_ReadByte(), 0); // The rest of the packet contains resend IDs. while(!Msg_End()) { Sv_AckDeltaSet(netBuffer.player, 0, Msg_ReadByte()); } break; case PKT_COORDS: Sv_ClientCoords(netBuffer.player); break; case PCL_ACK_SHAKE: // The client has acknowledged our handshake. // Note the time (this isn't perfectly accurate, though). netconsole = netBuffer.player; if(netconsole < 0 || netconsole >= DDMAXPLAYERS) continue; sender = &clients[netconsole]; sender->shakePing = Sys_GetRealTime() - sender->shakePing; Con_Printf("Cl%i handshake ping: %i ms\n", netconsole, sender->shakePing); // Update the initial ack time accordingly. Since the ping // fluctuates, assume the a poor case. Net_SetInitialAckTime(netconsole, 2 * sender->shakePing); break; case PCL_ACK_PLAYER_FIX: { player_t *plr = &ddPlayers[netBuffer.player]; ddplayer_t *ddpl = &plr->shared; fixcounters_t *acked = &ddpl->fixAcked; acked->angles = Msg_ReadLong(); acked->pos = Msg_ReadLong(); acked->mom = Msg_ReadLong(); #ifdef _DEBUG Con_Message("PCL_ACK_PLAYER_FIX: (%i) Angles %i (%i), pos %i (%i), mom %i (%i).\n", netBuffer.player, acked->angles, ddpl->fixCounter.angles, acked->pos, ddpl->fixCounter.pos, acked->mom, ddpl->fixCounter.mom); #endif break; } case PKT_PING: Net_PingResponse(); break; case PCL_HELLO: case PCL_HELLO2: case PKT_OK: case PKT_CHAT: case PKT_PLAYER_INFO: Sv_HandlePacket(); break; case PKT_LOGIN: Sv_Login(); break; case PKT_COMMAND: case PKT_COMMAND2: Sv_ExecuteCommand(); break; default: if(netBuffer.msg.type >= PKT_GAME_MARKER) { // A client has sent a game specific packet. gx.HandlePacket(netBuffer.player, netBuffer.msg.type, netBuffer.msg.data, netBuffer.length); } } } } /** * Assign a new console to the player. Returns true if successful. * Called by N_Update(). */ boolean Sv_PlayerArrives(unsigned int nodeID, char *name) { int i; Con_Message("Sv_PlayerArrives: '%s' has arrived.\n", name); // We need to find the new player a client entry. for(i = 1; i < DDMAXPLAYERS; ++i) { client_t *cl = &clients[i]; if(!cl->connected) { player_t *plr = &ddPlayers[i]; ddplayer_t *ddpl = &plr->shared; // This'll do. cl->connected = true; cl->ready = false; cl->nodeID = nodeID; cl->viewConsole = i; cl->lastTransmit = -1; strncpy(cl->name, name, PLAYERNAMELEN); ddpl->fixAcked.angles = ddpl->fixAcked.pos = ddpl->fixAcked.mom = -1; Sv_InitPoolForClient(i); VERBOSE(Con_Printf ("Sv_PlayerArrives: '%s' assigned to " "console %i (node: %x)\n", cl->name, i, nodeID)); // In order to get in the game, the client must first // shake hands. It'll request this by sending a Hello packet. // We'll be waiting... cl->handshake = false; cl->updateCount = UPDATECOUNT; return true; } } return false; } /** * Remove the specified player from the game. Called by N_Update(). */ void Sv_PlayerLeaves(unsigned int nodeID) { int i, plrNum = -1; boolean wasInGame; player_t *plr; client_t *cl; // First let's find out who this node actually is. for(i = 0; i < DDMAXPLAYERS; ++i) if(clients[i].nodeID == nodeID) { plrNum = i; break; } if(plrNum == -1) return; // Bogus? // Log off automatically. if(netRemoteUser == plrNum) netRemoteUser = 0; cl = &clients[plrNum]; plr = &ddPlayers[plrNum]; // Print a little something in the console. Con_Message("Sv_PlayerLeaves: '%s' (console %i) has left.\n", cl->name, plrNum); wasInGame = plr->shared.inGame; plr->shared.inGame = false; cl->connected = false; cl->ready = false; cl->updateCount = 0; cl->handshake = false; cl->nodeID = 0; cl->bandwidthRating = BWR_DEFAULT; // Set a modest ack time by default. Net_SetInitialAckTime(plrNum, ACK_DEFAULT); // Remove the player's data from the register. Sv_PlayerRemoved(plrNum); if(wasInGame) { // Inform the DLL about this. gx.NetPlayerEvent(plrNum, DDPE_EXIT, NULL); // Inform other clients about this. Msg_Begin(PSV_PLAYER_EXIT); Msg_WriteByte(plrNum); Net_SendBuffer(NSP_BROADCAST, SPF_CONFIRM); } // This client no longer has an ID number. cl->id = 0; } /** * The player will be sent the introductory handshake packets. */ void Sv_Handshake(int plrNum, boolean newPlayer) { int i; handshake_packet_t shake; playerinfo_packet_t info; Con_Printf("Sv_Handshake: Shaking hands with player %i.\n", plrNum); shake.version = SV_VERSION; // byte shake.yourConsole = plrNum; // byte shake.playerMask = 0; shake.gameTime = LONG(gameTime * 100); for(i = 0; i < DDMAXPLAYERS; ++i) if(clients[i].connected) shake.playerMask |= 1 << i; shake.playerMask = USHORT(shake.playerMask); Net_SendPacket(plrNum | DDSP_ORDERED, PSV_HANDSHAKE, &shake, sizeof(shake)); #if _DEBUG Con_Message("Sv_Handshake: plmask=%x\n", USHORT(shake.playerMask)); #endif if(newPlayer) { // Note the time when the handshake was sent. clients[plrNum].shakePing = Sys_GetRealTime(); } // The game DLL wants to shake hands as well? gx.NetWorldEvent(DDWE_HANDSHAKE, plrNum, (void *) &newPlayer); // Propagate client information. for(i = 0; i < DDMAXPLAYERS; ++i) { if(clients[i].connected) { info.console = i; strcpy(info.name, clients[i].name); Net_SendPacket(plrNum | DDSP_ORDERED, PKT_PLAYER_INFO, &info, sizeof(info)); } // Send the new player's info to other players. if(newPlayer && i != 0 && i != plrNum && clients[i].connected) { info.console = plrNum; strcpy(info.name, clients[plrNum].name); Net_SendPacket(i | DDSP_CONFIRM, PKT_PLAYER_INFO, &info, sizeof(info)); } } if(!newPlayer) { // This is not a new player (just a re-handshake) but we'll // nevertheless re-init the client's state register. For new // players this is done in Sv_PlayerArrives. Sv_InitPoolForClient(plrNum); } ddPlayers[plrNum].shared.flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; } void Sv_StartNetGame(void) { int i; // Reset all the counters and other data. for(i = 0; i < DDMAXPLAYERS; ++i) { client_t *client = &clients[i]; player_t *plr = &ddPlayers[i]; ddplayer_t *ddpl = &plr->shared; ddpl->inGame = false; ddpl->flags &= ~DDPF_CAMERA; client->connected = false; client->ready = false; client->nodeID = 0; client->numTics = 0; client->firstTic = 0; client->enterTime = 0; client->runTime = -1; client->lastTransmit = -1; client->updateCount = UPDATECOUNT; client->fov = 90; client->viewConsole = i; memset(client->name, 0, sizeof(client->name)); client->bandwidthRating = BWR_DEFAULT; client->bwrAdjustTime = 0; memset(client->ackTimes, 0, sizeof(client->ackTimes)); } gameTime = 0; firstNetUpdate = true; netRemoteUser = 0; // The server is always player number zero. consolePlayer = displayPlayer = 0; netGame = true; isServer = true; allowSending = true; if(!isDedicated) { player_t *plr = &ddPlayers[consolePlayer]; ddplayer_t *ddpl = &plr->shared; client_t *cl = &clients[consolePlayer]; ddpl->inGame = true; cl->connected = true; cl->ready = true; strcpy(cl->name, playerName); } } void Sv_SendText(int to, int con_flags, char *text) { Msg_Begin(PSV_CONSOLE_TEXT); Msg_WriteLong(con_flags & ~CBLF_TRANSMIT); Msg_Write(text, strlen(text) + 1); Net_SendBuffer(to, SPF_ORDERED); } /** * Asks a client to disconnect. Clients will immediately disconnect * after receiving the PSV_SERVER_CLOSE message. */ void Sv_Kick(int who) { if(!clients[who].connected) return; Sv_SendText(who, SV_CONSOLE_FLAGS, "You were kicked out!\n"); Msg_Begin(PSV_SERVER_CLOSE); Net_SendBuffer(who, SPF_ORDERED); //ddPlayers[who].shared.inGame = false; } void Sv_SendPlayerFixes(int plrNum) { int fixes = 0; player_t *plr = &ddPlayers[plrNum]; ddplayer_t *ddpl = &plr->shared; if(!(ddpl->flags & (DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM))) { // Nothing to fix. return; } // Start writing a player fix message. Msg_Begin(PSV_PLAYER_FIX); // Indicate what is included in the message. if(ddpl->flags & DDPF_FIXANGLES) fixes |= 1; if(ddpl->flags & DDPF_FIXPOS) fixes |= 2; if(ddpl->flags & DDPF_FIXMOM) fixes |= 4; Msg_WriteLong(fixes); // Increment counters. if(ddpl->flags & DDPF_FIXANGLES) { Msg_WriteLong(++ddpl->fixCounter.angles); Msg_WriteLong(ddpl->mo->angle); Msg_WriteLong(FLT2FIX(ddpl->lookDir)); #ifdef _DEBUG Con_Message("Sv_SendPlayerFixes: Sent angles (%i): angle=%f lookdir=%f\n", ddpl->fixCounter.angles, FIX2FLT(ddpl->mo->angle), ddpl->lookDir); #endif } if(ddpl->flags & DDPF_FIXPOS) { Msg_WriteLong(++ddpl->fixCounter.pos); Msg_WriteLong(FLT2FIX(ddpl->mo->pos[VX])); Msg_WriteLong(FLT2FIX(ddpl->mo->pos[VY])); Msg_WriteLong(FLT2FIX(ddpl->mo->pos[VZ])); #ifdef _DEBUG Con_Message("Sv_SendPlayerFixes: Sent position (%i): %f, %f, %f\n", ddpl->fixCounter.pos, ddpl->mo->pos[VX], ddpl->mo->pos[VY], ddpl->mo->pos[VZ]); #endif } if(ddpl->flags & DDPF_FIXMOM) { Msg_WriteLong(++ddpl->fixCounter.mom); Msg_WriteLong(FLT2FIX(ddpl->mo->mom[MX])); Msg_WriteLong(FLT2FIX(ddpl->mo->mom[MY])); Msg_WriteLong(FLT2FIX(ddpl->mo->mom[MZ])); #ifdef _DEBUG Con_Message("Sv_SendPlayerFixes: Sent momentum (%i): %f, %f, %f\n", ddpl->fixCounter.mom, ddpl->mo->mom[MX], ddpl->mo->mom[MY], ddpl->mo->mom[MZ]); #endif } // Send the fix message. Net_SendBuffer(plrNum, SPF_ORDERED | SPF_CONFIRM); ddpl->flags &= ~(DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM); } void Sv_Ticker(void) { int i; // Note last angles for all players. for(i = 0; i < DDMAXPLAYERS; ++i) { player_t *plr = &ddPlayers[i]; if(!plr->shared.inGame || !plr->shared.mo) continue; plr->shared.lastAngle = plr->shared.mo->angle; if(clients[i].bwrAdjustTime > 0) { // BWR adjust time tics away. clients[i].bwrAdjustTime--; } // Increment counter, send new data. Sv_SendPlayerFixes(i); } } /** * @return The number of players in the game. */ int Sv_GetNumPlayers(void) { int i, count; // Clients can't count. if(isClient) return 1; for(i = count = 0; i < DDMAXPLAYERS; ++i) { player_t *plr = &ddPlayers[i]; if(plr->shared.inGame && plr->shared.mo) count++; } return count; } /** * @return The number of connected clients. */ int Sv_GetNumConnected(void) { int i, count = 0; // Clients can't count. if(isClient) return 1; for(i = isDedicated ? 1 : 0; i < DDMAXPLAYERS; ++i) if(clients[i].connected) count++; return count; } /** * The bandwidth rating is updated according to the status of the * player's send queue. Returns true if a new packet may be sent. */ boolean Sv_CheckBandwidth(int playerNumber) { client_t *client = &clients[playerNumber]; uint qSize = N_GetSendQueueSize(playerNumber); uint limit = 400; // If there are too many messages in the queue, the player's bandwidth // is overrated. if(qSize > limit) { // Drop quickly to allow the send queue to clear out sooner. client->bandwidthRating -= 10; } // If the send queue is practically empty, we can use more bandwidth. // (Providing we have BWR adjust time.) if(qSize < limit / 20 && client->bwrAdjustTime > 0) { client->bandwidthRating++; // Increase BWR only once during the adjust time. client->bwrAdjustTime = 0; } // Do not go past the boundaries, though. if(client->bandwidthRating < 0) { client->bandwidthRating = 0; } if(client->bandwidthRating > MAX_BANDWIDTH_RATING) { client->bandwidthRating = MAX_BANDWIDTH_RATING; } // New messages will not be sent if there's too much already. return qSize <= 10 * limit; } void Sv_PlaceMobj(mobj_t* mo, float x, float y, float z, boolean onFloor) { P_CheckPosXYZ(mo, x, y, z); P_MobjUnlink(mo); mo->pos[VX] = x; mo->pos[VY] = y; mo->pos[VZ] = z; P_MobjLink(mo, DDLINK_SECTOR | DDLINK_BLOCKMAP); mo->floorZ = tmpFloorZ; mo->ceilingZ = tmpCeilingZ; if(onFloor) { mo->pos[VZ] = mo->floorZ; } } /** * Reads a PKT_COORDS packet from the message buffer. We trust the * client's position and change ours to match it. The client better not * be cheating. */ void Sv_ClientCoords(int plrNum) { player_t *plr = &ddPlayers[plrNum]; ddplayer_t *ddpl = &plr->shared; mobj_t *mo = ddpl->mo; int clz; float clientPos[3]; boolean onFloor = false; // If mobj or player is invalid, the message is discarded. if(!mo || !ddpl->inGame || (ddpl->flags & DDPF_DEAD)) return; clientPos[VX] = (float) Msg_ReadShort(); clientPos[VY] = (float) Msg_ReadShort(); clz = Msg_ReadShort(); clientPos[VZ] = (float) clz; if((unsigned) (clz << 16) == (DDMININT & 0xffff0000)) { clientPos[VZ] = mo->floorZ; onFloor = true; } // If we aren't about to forcibly change the client's position, update // with new pos if it's valid. But it must be a valid pos. if(ddpl->fixCounter.pos == ddpl->fixAcked.pos && P_CheckPosXYZ(mo, clientPos[VX], clientPos[VY], clientPos[VZ])) { // Large differences in the coordinates suggest that player position // has been misestimated on serverside. // Prevent illegal stepups. if(tmpFloorZ - mo->pos[VZ] <= 24 || // But also allow warping the position. (fabs(clientPos[VX] - mo->pos[VX]) > WARP_LIMIT || fabs(clientPos[VY] - mo->pos[VY]) > WARP_LIMIT || fabs(clientPos[VZ] - mo->pos[VZ]) > WARP_LIMIT)) { Sv_PlaceMobj(mo, clientPos[VX], clientPos[VY], clientPos[VZ], onFloor); } } } /** * Console command for terminating a remote console connection. */ D_CMD(Logout) { // Only servers can execute this command. if(!netRemoteUser || !isServer) return false; // Notice that the server WILL execute this command when a client // is logged in and types "logout". Sv_SendText(netRemoteUser, SV_CONSOLE_FLAGS, "Goodbye...\n"); // Send a logout packet. Msg_Begin(PKT_LOGIN); Msg_WriteByte(false); // You're outta here. Net_SendBuffer(netRemoteUser, SPF_ORDERED); netRemoteUser = 0; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_seg.c0000644000175000017500000000734511357170242022203 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_seg.c: World segs. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Update the seg, property is selected by DMU_* name. */ boolean Seg_SetProperty(seg_t *seg, const setargs_t *args) { switch(args->prop) { case DMU_FLAGS: DMU_SetValue(DMT_SEG_FLAGS, &seg->flags, args, 0); break; default: Con_Error("Seg_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } /** * Get the value of a seg property, selected by DMU_* name. */ boolean Seg_GetProperty(const seg_t *seg, setargs_t *args) { switch(args->prop) { case DMU_VERTEX0: DMU_GetValue(DMT_SEG_V, &seg->SG_v1, args, 0); break; case DMU_VERTEX1: DMU_GetValue(DMT_SEG_V, &seg->SG_v2, args, 0); break; case DMU_LENGTH: DMU_GetValue(DMT_SEG_LENGTH, &seg->length, args, 0); break; case DMU_OFFSET: DMU_GetValue(DMT_SEG_OFFSET, &seg->offset, args, 0); break; case DMU_SIDEDEF: DMU_GetValue(DMT_SEG_SIDEDEF, &SEG_SIDEDEF(seg), args, 0); break; case DMU_LINEDEF: DMU_GetValue(DMT_SEG_LINEDEF, &seg->lineDef, args, 0); break; case DMU_FRONT_SECTOR: { sector_t *sec = NULL; if(seg->SG_frontsector && seg->lineDef) sec = seg->SG_frontsector; DMU_GetValue(DMT_SEG_SEC, &sec, args, 0); break; } case DMU_BACK_SECTOR: { sector_t *sec = NULL; if(seg->SG_backsector && seg->lineDef) sec = seg->SG_backsector; DMU_GetValue(DMT_SEG_SEC, &seg->SG_backsector, args, 0); break; } case DMU_FLAGS: DMU_GetValue(DMT_SEG_FLAGS, &seg->flags, args, 0); break; case DMU_ANGLE: DMU_GetValue(DMT_SEG_ANGLE, &seg->angle, args, 0); break; default: Con_Error("Seg_GetProperty: No property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/con_busy.c0000644000175000017500000006636511357170241022735 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_busy.c: Console Busy Mode * * Draws the screen while the main engine thread is working a long * operation. The busy mode can be configured to be displaying a progress * bar, the console output, or a more generic "please wait" message. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_ui.h" #include "de_misc.h" #include "de_network.h" // MACROS ------------------------------------------------------------------ #define SCREENSHOT_TEXTURE_SIZE 512 #define DOOMWIPESINE_NUMSAMPLES 320 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void Con_BusyLoop(void); static void Con_BusyDrawer(void); static void Con_BusyLoadTextures(void); static void Con_BusyDeleteTextures(void); static void seedDoomWipeSine(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int rTransition = (int) TS_CROSSFADE; int rTransitionTics = 28; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean busyInited; static int busyMode; static char* busyTaskName; static thread_t busyThread; static timespan_t busyTime; static volatile boolean busyDone; static volatile boolean busyDoneCopy; static volatile const char* busyError = NULL; static int busyFont = 0; static int busyFontHgt; // Height of the font. static mutex_t busy_Mutex; // To prevent Data races in the busy thread. static DGLuint texLoading[2]; static DGLuint texScreenshot; // Captured screenshot of the latest frame. static boolean transitionInProgress = false; static uint transitionStartTime = 0; static float transitionPosition; static float doomWipeSine[DOOMWIPESINE_NUMSAMPLES]; // CODE -------------------------------------------------------------------- /** * Busy mode. * * @param flags Busy mode flags (see BUSYF_PROGRESS_BAR and others). * @param taskName Optional task name (drawn with the progress bar). * @param worker Worker thread that does processing while in busy mode. * @param workerData Data context for the worker thread. * * @return Return value of the worker. */ int Con_Busy(int flags, const char* taskName, busyworkerfunc_t worker, void* workerData) { int result = 0; if(!busyInited) { busy_Mutex = Sys_CreateMutex("BUSY_MUTEX"); } if(busyInited) { Con_Error("Con_Busy: Already busy.\n"); } busyMode = flags; Sys_Lock(busy_Mutex); busyDone = false; if(taskName && taskName[0]) { // Take a copy of the task name. size_t len = strlen(taskName); busyTaskName = M_Calloc(len + 1); dd_snprintf(busyTaskName, len+1, "%s", taskName); } Sys_Unlock(busy_Mutex); // Load any textures needed in this mode. Con_BusyLoadTextures(); // Activate the UI binding context so that any and all accumulated input // events are discarded when done. DD_ClearKeyRepeaters(); B_ActivateContext(B_ContextByName(UI_BINDING_CONTEXT_NAME), true); busyInited = true; // Start the busy worker thread, which will proces things in the // background while we keep the user occupied with nice animations. busyThread = Sys_StartThread(worker, workerData); // Wait for the busy thread to stop. Con_BusyLoop(); // Are we doing a transition effect? if(!isDedicated && !netGame && !(busyMode & BUSYF_STARTUP) && rTransitionTics > 0 && (busyMode & BUSYF_TRANSITION)) { if(rTransition == TS_DOOM || rTransition == TS_DOOMSMOOTH) seedDoomWipeSine(); transitionStartTime = Sys_GetTime(); transitionPosition = 0; transitionInProgress = true; } else { // Clear any input events that might have accumulated whilst busy. DD_ClearEvents(); B_ActivateContext(B_ContextByName(UI_BINDING_CONTEXT_NAME), false); } // Free resources. Con_BusyDeleteTextures(); if(busyTaskName) M_Free(busyTaskName); busyTaskName = NULL; if(busyError) { Con_AbnormalShutdown((const char*) busyError); } // Make sure the worker finishes before we continue. result = Sys_WaitThread(busyThread); busyThread = NULL; busyInited = false; // Make sure that any remaining deferred content gets uploaded. if(!(isDedicated || (busyMode & BUSYF_NO_UPLOADS))) { GL_UploadDeferredContent(0); } return result; } /** * Called by the busy worker to shutdown the engine immediately. * * @param message Message, expected to exist until the engine closes. */ void Con_BusyWorkerError(const char* message) { busyError = message; Con_BusyWorkerEnd(); } /** * Called by the busy worker thread when it has finished processing, * to end busy mode. */ void Con_BusyWorkerEnd(void) { if(!busyInited) return; Sys_Lock(busy_Mutex); busyDone = true; Sys_Unlock(busy_Mutex); } boolean Con_IsBusy(void) { return busyInited; } static void Con_BusyLoadTextures(void) { image_t image; if(isDedicated) return; if(!(busyMode & BUSYF_STARTUP)) { // Not in startup, so take a copy of the current frame contents. Con_AcquireScreenshotTexture(); } // Need to load the progress indicator? if(busyMode & (BUSYF_ACTIVITY | BUSYF_PROGRESS_BAR)) { // These must be real files in the base dir because virtual files haven't // been loaded yet when engine startup is done. if(GL_LoadImage(&image, "}data/graphics/loading1.png")) { texLoading[0] = GL_NewTextureWithParams(DGL_RGBA, image.width, image.height, image.pixels, TXCF_NEVER_DEFER); GL_DestroyImage(&image); } if(GL_LoadImage(&image, "}data/graphics/loading2.png")) { texLoading[1] = GL_NewTextureWithParams(DGL_RGBA, image.width, image.height, image.pixels, TXCF_NEVER_DEFER); GL_DestroyImage(&image); } } if((busyMode & BUSYF_CONSOLE_OUTPUT) || busyTaskName) { const char* fontName; if(!(theWindow->width > 640)) fontName = "normal12"; else fontName = "normal18"; if(FR_PrepareFont(fontName)) { busyFont = FR_GetCurrent(); busyFontHgt = FR_TextHeight("A"); } } } static void Con_BusyDeleteTextures(void) { if(isDedicated) return; // Destroy the font. /* if(busyFont) { FR_DestroyFont(busyFont); }*/ glDeleteTextures(2, (const GLuint*) texLoading); texLoading[0] = texLoading[1] = 0; busyFont = 0; // Don't release this yet if doing a transition. if(!transitionInProgress) Con_ReleaseScreenshotTexture(); } /** * Take a screenshot and store it as a texture. */ void Con_AcquireScreenshotTexture(void) { int oldMaxTexSize = GL_state.maxTexSize; byte* frame; #ifdef _DEBUG timespan_t startTime; #endif if(texScreenshot) { Con_ReleaseScreenshotTexture(); } #ifdef _DEBUG startTime = Sys_GetRealSeconds(); #endif frame = M_Malloc(theWindow->width * theWindow->height * 3); GL_Grab(0, 0, theWindow->width, theWindow->height, DGL_RGB, frame); GL_state.maxTexSize = SCREENSHOT_TEXTURE_SIZE; // A bit of a hack, but don't use too large a texture. texScreenshot = GL_UploadTexture(frame, theWindow->width, theWindow->height, false, false, true, false, true, GL_LINEAR, GL_LINEAR, 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, TXCF_NEVER_DEFER|TXCF_NO_COMPRESSION); GL_state.maxTexSize = oldMaxTexSize; M_Free(frame); #ifdef _DEBUG printf("Con_AcquireScreenshotTexture: Took %.2f seconds.\n", Sys_GetRealSeconds() - startTime); #endif } void Con_ReleaseScreenshotTexture(void) { glDeleteTextures(1, (const GLuint*) &texScreenshot); texScreenshot = 0; } /** * The busy thread main function. Runs until busyDone set to true. */ static void Con_BusyLoop(void) { boolean canDraw = !isDedicated; boolean canUpload = !(isDedicated || (busyMode & BUSYF_NO_UPLOADS)); timespan_t startTime = Sys_GetRealSeconds(); if(canDraw) { glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1); } Sys_Lock(busy_Mutex); busyDoneCopy = busyDone; Sys_Unlock(busy_Mutex); while(!busyDoneCopy || (canUpload && GL_GetDeferredCount() > 0)) { Sys_Lock(busy_Mutex); busyDoneCopy = busyDone; Sys_Unlock(busy_Mutex); Sys_Sleep(20); if(canUpload) { // Make sure that any deferred content gets uploaded. GL_UploadDeferredContent(15); } // Update the time. busyTime = Sys_GetRealSeconds() - startTime; // Time for an update? if(canDraw) Con_BusyDrawer(); } if(verbose) { Con_Message("Con_Busy: Was busy for %.2lf seconds.\n", busyTime); } if(canDraw) { glMatrixMode(GL_PROJECTION); glPopMatrix(); } } /** * Draws the captured screenshot as a background, or just clears the screen if no * screenshot is available. */ static void Con_DrawScreenshotBackground(float x, float y, float width, float height) { if(texScreenshot) { glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texScreenshot); glColor3ub(255, 255, 255); glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex2f(x, y); glTexCoord2f(1, 1); glVertex2f(x + width, y); glTexCoord2f(1, 0); glVertex2f(x + width, y + height); glTexCoord2f(0, 0); glVertex2f(x, y + height); glEnd(); } else { glClear(GL_COLOR_BUFFER_BIT); } } /** * @param 0...1, to indicate how far things have progressed. */ static void Con_BusyDrawIndicator(float x, float y, float radius, float pos) { float col[4] = {1.f, 1.f, 1.f, .2f}; int i = 0; int edgeCount = 0; int backW, backH; backW = backH = (radius * 2); pos = MINMAX_OF(0, pos, 1); edgeCount = MAX_OF(1, pos * 30); // Draw a background. glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); GL_BlendMode(BM_NORMAL); glBegin(GL_TRIANGLE_FAN); glColor4ub(0, 0, 0, 140); glVertex2f(x, y); glColor4ub(0, 0, 0, 0); glVertex2f(x, y - backH); glVertex2f(x + backW*.8f, y - backH*.8f); glVertex2f(x + backW, y); glVertex2f(x + backW*.8f, y + backH*.8f); glVertex2f(x, y + backH); glVertex2f(x - backW*.8f, y + backH*.8f); glVertex2f(x - backW, y); glVertex2f(x - backW*.8f, y - backH*.8f); glVertex2f(x, y - backH); glEnd(); // Draw the frame. glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texLoading[0]); GL_DrawRect(x - radius, y - radius, radius*2, radius*2, col[0], col[1], col[2], col[3]); // Rotate around center. glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glTranslatef(.5f, .5f, 0.f); glRotatef(-busyTime * 20, 0.f, 0.f, 1.f); glTranslatef(-.5f, -.5f, 0.f); // Draw a fan. glColor4f(col[0], col[1], col[2], .66f); glBindTexture(GL_TEXTURE_2D, texLoading[1]); glBegin(GL_TRIANGLE_FAN); // Center. glTexCoord2f(.5f, .5f); glVertex2f(x, y); // Vertices along the edge. for(i = 0; i <= edgeCount; ++i) { float angle = 2 * PI * pos * (i / (float)edgeCount) + PI/2; glTexCoord2f(.5f + cos(angle)*.5f, .5f + sin(angle)*.5f); glVertex2f(x + cos(angle)*radius*1.105f, y + sin(angle)*radius*1.105f); } glEnd(); glMatrixMode(GL_TEXTURE); glPopMatrix(); // Draw the task name. if(busyTaskName) { glColor4f(1.f, 1.f, 1.f, .66f); FR_TextOut(busyTaskName, x+radius, y - busyFontHgt/2); } } #define LINE_COUNT 4 /** * @return Number of new lines since the old ones. */ static int GetBufLines(cbuffer_t* buffer, cbline_t const **oldLines) { cbline_t const* bufLines[LINE_COUNT + 1]; int count; int newCount = 0; int i, k; count = Con_BufferGetLines(buffer, LINE_COUNT, -LINE_COUNT, bufLines); for(i = 0; i < count; ++i) { for(k = 0; k < 2 * LINE_COUNT - newCount; ++k) { if(oldLines[k] == bufLines[i]) { goto lineIsNotNew; } } newCount++; for(k = 0; k < (2 * LINE_COUNT - 1); ++k) oldLines[k] = oldLines[k+1]; //memmove(oldLines, oldLines + 1, sizeof(cbline_t*) * (2 * LINE_COUNT - 1)); oldLines[2 * LINE_COUNT - 1] = bufLines[i]; lineIsNotNew:; } return newCount; } /** * Draws a number of console output to the bottom of the screen. * \fixme: Wow. I had some weird time hacking the smooth scrolling. Cleanup would be * good some day. -jk */ void Con_BusyDrawConsoleOutput(void) { cbuffer_t* buffer; static cbline_t const* visibleBusyLines[2 * LINE_COUNT]; static float scroll = 0; static float scrollStartTime = 0; static float scrollEndTime = 0; static double lastNewTime = 0; static double timeSinceLastNew = 0; double nowTime = 0; float y, topY; uint i, newCount; buffer = Con_GetConsoleBuffer(); newCount = GetBufLines(buffer, visibleBusyLines); nowTime = Sys_GetRealSeconds(); if(newCount > 0) { timeSinceLastNew = nowTime - lastNewTime; lastNewTime = nowTime; if(nowTime < scrollEndTime) { // Abort last scroll. scroll = 0; scrollStartTime = nowTime; scrollEndTime = nowTime; } else { double interval = MIN_OF(timeSinceLastNew/2, 1.3); // Begin new scroll. scroll = newCount; scrollStartTime = nowTime; scrollEndTime = nowTime + interval; } } glDisable(GL_TEXTURE_2D); glEnable(GL_BLEND); GL_BlendMode(BM_NORMAL); // Dark gradient as background. glBegin(GL_QUADS); glColor4ub(0, 0, 0, 0); y = theWindow->height - (LINE_COUNT + 3) * busyFontHgt; glVertex2f(0, y); glVertex2f(theWindow->width, y); glColor4ub(0, 0, 0, 128); glVertex2f(theWindow->width, theWindow->height); glVertex2f(0, theWindow->height); glEnd(); glEnable(GL_TEXTURE_2D); // The text lines. topY = y = theWindow->height - busyFontHgt * (2 * LINE_COUNT + .5f); if(newCount > 0 || (nowTime >= scrollStartTime && nowTime < scrollEndTime && scrollEndTime > scrollStartTime)) { if(scrollEndTime - scrollStartTime > 0) y += scroll * (scrollEndTime - nowTime) / (scrollEndTime - scrollStartTime) * busyFontHgt; } for(i = 0; i < 2 * LINE_COUNT; ++i, y += busyFontHgt) { float color = 1;//lineAlpha[i]; const cbline_t* line = visibleBusyLines[i]; if(!line) continue; color = ((y - topY) / busyFontHgt) - (LINE_COUNT - 1); if(color < LINE_COUNT) color = MINMAX_OF(0, color/2, 1); else color = 1 - (color - LINE_COUNT); if(!(line->flags & CBLF_RULER)) // ignore rulers. { if(!line->text) continue; glColor4f(1.f, 1.f, 1.f, color); FR_TextOut(line->text, (theWindow->width - FR_TextWidth(line->text))/2, y); } } #undef LINE_COUNT } /** * Busy drawer function. The entire frame is drawn here. */ static void Con_BusyDrawer(void) { float pos = 0; Con_DrawScreenshotBackground(0, 0, theWindow->width, theWindow->height); // Indefinite activity? if((busyMode & BUSYF_ACTIVITY) || (busyMode & BUSYF_PROGRESS_BAR)) { if(busyMode & BUSYF_ACTIVITY) pos = 1; else // The progress is animated elsewhere. pos = Con_GetProgress(); Con_BusyDrawIndicator(theWindow->width/2, theWindow->height/2, theWindow->height/12, pos); } // Output from the console? if(busyMode & BUSYF_CONSOLE_OUTPUT) { Con_BusyDrawConsoleOutput(); } Sys_UpdateWindow(windowIDX); } boolean Con_TransitionInProgress(void) { return transitionInProgress; } void Con_TransitionTicker(timespan_t ticLength) { if(isDedicated) return; if(!Con_TransitionInProgress()) return; transitionPosition = (float)(Sys_GetTime() - transitionStartTime) / rTransitionTics; if(transitionPosition >= 1) { // Clear any input events that might have accumulated during the transition. DD_ClearEvents(); B_ActivateContext(B_ContextByName(UI_BINDING_CONTEXT_NAME), false); Con_ReleaseScreenshotTexture(); transitionInProgress = false; } } static void seedDoomWipeSine(void) { int i; doomWipeSine[0] = (128 - RNG_RandByte()) / 128.f; for(i = 1; i < DOOMWIPESINE_NUMSAMPLES; ++i) { float r = (128 - RNG_RandByte()) / 512.f; doomWipeSine[i] = MINMAX_OF(-1, doomWipeSine[i-1] + r, 1); } } static float sampleDoomWipeSine(float point) { float sample = doomWipeSine[(uint)ROUND((DOOMWIPESINE_NUMSAMPLES-1) * MINMAX_OF(0, point, 1))]; float offset = SCREENHEIGHT * transitionPosition * transitionPosition; return offset + (SCREENHEIGHT/2) * (transitionPosition + sample) * transitionPosition * transitionPosition; } void Con_DrawTransition(void) { if(isDedicated) return; if(!Con_TransitionInProgress()) return; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, SCREENWIDTH, SCREENHEIGHT, 0, -1, 1); glBindTexture(GL_TEXTURE_2D, texScreenshot); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); switch(rTransition) { case TS_DOOMSMOOTH: { float colWidth = .5f / SCREENSHOT_TEXTURE_SIZE; int i; glColor3f(1, 1, 1); glBegin(GL_QUAD_STRIP); glTexCoord2f(0, 1); glVertex2f(0, MAX_OF(0, sampleDoomWipeSine(0))); glTexCoord2f(0, 0); glVertex2f(0, MAX_OF(0, sampleDoomWipeSine(0))+SCREENHEIGHT); for(i = 1; i <= SCREENWIDTH; ++i) { float s = (float) i / SCREENWIDTH - colWidth; float x = i - .5f; float y = MAX_OF(0, sampleDoomWipeSine((float) i / SCREENWIDTH)); glTexCoord2f(s, 1); glVertex2f(x, y); glTexCoord2f(s, 0); glVertex2f(x, y+SCREENHEIGHT); } glTexCoord2f(1, 1); glVertex2f(SCREENWIDTH, MAX_OF(0, sampleDoomWipeSine(1))); glTexCoord2f(1, 0); glVertex2f(SCREENWIDTH, MAX_OF(0, sampleDoomWipeSine(1))+SCREENHEIGHT); glEnd(); break; } case TS_DOOM: { // As above but drawn with whole pixel columns. float colWidth = 1.0f / SCREENSHOT_TEXTURE_SIZE; int i; glColor3f(1, 1, 1); glBegin(GL_QUADS); for(i = 0; i <= SCREENWIDTH; ++i) { float s = (float) i / SCREENWIDTH; float x = i; float y = MAX_OF(0, sampleDoomWipeSine((float) i / SCREENWIDTH)); glTexCoord2f(s, 1); glVertex2f(x, y); glTexCoord2f(s+colWidth, 1); glVertex2f(x+1, y); glTexCoord2f(s+colWidth, 0); glVertex2f(x+1, y+SCREENHEIGHT); glTexCoord2f(s, 0); glVertex2f(x, y+SCREENHEIGHT); } glEnd(); break; } case TS_CROSSFADE: glColor4f(1, 1, 1, 1 - transitionPosition); glBegin(GL_QUADS); glTexCoord2f(0, 1); glVertex2f(0, 0); glTexCoord2f(0, 0); glVertex2f(0, SCREENHEIGHT); glTexCoord2f(1, 0); glVertex2f(SCREENWIDTH, SCREENHEIGHT); glTexCoord2f(1, 1); glVertex2f(SCREENWIDTH, 0); glEnd(); break; } glMatrixMode(GL_PROJECTION); glPopMatrix(); } #if 0 /* * The startup screen mode is used during engine startup. In startup * mode, the whole screen is used for console output. */ void Con_StartupInit(void) { static boolean firstTime = true; if(novideo) return; GL_InitVarFont(); fontHgt = FR_SingleLineHeight("Doomsday!"); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, glScreenWidth, glScreenHeight, 0, -1, 1); if(firstTime) { titleText = "Doomsday " DOOMSDAY_VERSION_TEXT " Startup"; firstTime = false; } else { titleText = "Doomsday " DOOMSDAY_VERSION_TEXT; } // Load graphics. startupLogo = GL_PrepareExtTexture(DDRC_GRAPHICS, "Background", LGM_GRAYSCALE, false, GL_LINEAR, GL_LINEAR, 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); } void Con_StartupDone(void) { if(isDedicated) return; titleText = "Doomsday " DOOMSDAY_VERSION_TEXT; glDeleteTextures(1, (const GLuint*) &startupLogo); startupLogo = 0; glMatrixMode(GL_PROJECTION); glPopMatrix(); GL_ShutdownVarFont(); // Update the secondary title and the game status. strncpy(secondaryTitleText, (char *) gx.GetVariable(DD_GAME_ID), sizeof(secondaryTitleText) - 1); strncpy(statusText, (char *) gx.GetVariable(DD_GAME_MODE), sizeof(statusText) - 1); } /** * Background with the "The Doomsday Engine" text superimposed. * * @param alpha Alpha level to use when drawing the background. */ void Con_DrawStartupBackground(float alpha) { float mul = (startupLogo ? 1.5f : 1.0f); ui_color_t* dark = UI_COL(UIC_BG_DARK), *light = UI_COL(UIC_BG_LIGHT); // Background gradient picture. glBindTexture(GL_TEXTURE_2D, startupLogo); if(alpha < 1.0) { glEnable(GL_BLEND); GL_BlendMode(BM_NORMAL); } else { glDisable(GL_BLEND); } glBegin(GL_QUADS); // Top color. glColor4f(dark->red * mul, dark->green * mul, dark->blue * mul, alpha); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(glScreenWidth, 0); // Bottom color. glColor4f(light->red * mul, light->green * mul, light->blue * mul, alpha); glTexCoord2f(1, 1); glVertex2f(glScreenWidth, glScreenHeight); glTexCoord2f(0, 1); glVertex2f(0, glScreenHeight); glEnd(); glEnable(GL_BLEND); } /* * Draws the title bar of the console. * * @return Title bar height. */ int Con_DrawTitle(float alpha) { int width = 0; int height = UI_FontHeight(); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); FR_SetFont(glFontVariable[GLFS_BOLD]); height = FR_TextHeight("W") + UI_ScreenW(UI_BORDER); UI_DrawTitleEx(titleText, height, alpha); if(secondaryTitleText[0]) { width = FR_TextWidth(titleText) + FR_TextWidth(" "); FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(secondaryTitleText, UI_ScreenW(UI_BORDER) + width, height / 2, false, true, UI_COL(UIC_TEXT), .75f * alpha); } if(statusText[0]) { width = FR_TextWidth(statusText); FR_SetFont(glFontVariable[GLFS_LIGHT]); UI_TextOutEx(statusText, glScreenWidth - UI_ScreenW(UI_BORDER) - width, height / 2, false, true, UI_COL(UIC_TEXT), .75f * alpha); } glMatrixMode(GL_MODELVIEW); glPopMatrix(); FR_SetFont(glFontFixed); return height; } /* * Draw the background and the current console output. */ void Con_DrawStartupScreen(int show) { int vislines, y, x; int topy; uint i, count; cbuffer_t *buffer; static cbline_t **lines = NULL; static int bufferSize = 0; cbline_t *line; // Print the messages in the console. if(ui_active) return; //glMatrixMode(GL_PROJECTION); //glLoadIdentity(); //glOrtho(0, glScreenWidth, glScreenHeight, 0, -1, 1); Con_DrawStartupBackground(1.0); // Draw the title. topy = Con_DrawTitle(1.0); topy += UI_ScreenW(UI_BORDER); vislines = (glScreenHeight - topy + fontHgt / 2) / fontHgt; y = topy; buffer = Con_GetConsoleBuffer(); if(vislines > 0) { // Need to enlarge the buffer? if(vislines > bufferSize) { lines = Z_Realloc(lines, sizeof(cbline_t *) * (vislines + 1), PU_STATIC); bufferSize = vislines; } count = Con_BufferGetLines(buffer, vislines, -vislines, lines); if(count > 0) { for(i = 0; i < count - 1; ++i) { line = lines[i]; if(!line) break; if(line->flags & CBLF_RULER) { Con_DrawRuler(y, fontHgt, 1); } else { if(!line->text) continue; x = (line->flags & CBLF_CENTER ? (glScreenWidth - FR_TextWidth(line->text)) / 2 : 3); //glColor3f(0, 0, 0); //FR_TextOut(line->text, x + 1, y + 1); glColor3f(1, 1, 1); FR_CustomShadowTextOut(line->text, x, y, 1, 1, 1); } y += fontHgt; } } } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_sidedef.c0000644000175000017500000000556611357170242023033 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_sidedef.c: World sidedefs. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Update the sidedef, property is selected by DMU_* name. */ boolean Sidedef_SetProperty(sidedef_t *sid, const setargs_t *args) { switch(args->prop) { case DMU_FLAGS: DMU_SetValue(DMT_SIDEDEF_FLAGS, &sid->flags, args, 0); break; default: Con_Error("Sidedef_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } /** * Get the value of a sidedef property, selected by DMU_* name. */ boolean Sidedef_GetProperty(const sidedef_t *sid, setargs_t *args) { switch(args->prop) { case DMU_SECTOR: DMU_GetValue(DMT_SIDEDEF_SECTOR, &sid->sector, args, 0); break; case DMU_LINEDEF: DMU_GetValue(DMT_SIDEDEF_LINE, &sid->line, args, 0); break; case DMU_FLAGS: DMU_GetValue(DMT_SIDEDEF_FLAGS, &sid->flags, args, 0); break; default: Con_Error("Sidedef_GetProperty: Has no property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_mobj.c0000644000175000017500000006441411357170242022354 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.c: Map Objects * * Contains various routines for moving mobjs, collision and Z checking. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_play.h" #include "de_refresh.h" #include "de_misc.h" #include "de_audio.h" #include "def_main.h" // MACROS ------------------------------------------------------------------ // Max. distance to move in one call to P_MobjMoveXY. #define MAXMOVE 30 // Shortest possible movement step. #define MINMOVE (1.0f/128) #define MIN_STEP(d) ((d) <= MINMOVE && (d) >= -MINMOVE) #define STOPSPEED (0.1f/1.6f) // TYPES ------------------------------------------------------------------- typedef struct { mobj_t *mo; vec2_t box[2]; int flags; float pos[3]; float height, floorZ, ceilingZ, dropOffZ; } checkpos_data_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // If set to true, P_CheckPosition will skip the mobj hit test. boolean dontHitMobjs = false; float tmpFloorZ; float tmpCeilingZ; // When a mobj is contacted in PIT_CheckMobj, this pointer is set. // It's reset to NULL in the beginning of P_CheckPosition. mobj_t *blockingMobj; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Slide variables. static float bestSlideFrac; static float secondSlideFrac; static linedef_t *bestSlideLine; static linedef_t *secondSlideLine; static mobj_t *slideMo; static boolean noFit; static float tmpDropOffZ; static float tmpMom[3]; static mobj_t *unusedMobjs = NULL; // CODE -------------------------------------------------------------------- /** * Called during map loading. */ void P_InitUnusedMobjList(void) { // Any zone memory allocated for the mobjs will have already been purged. unusedMobjs = NULL; } /** * All mobjs must be allocated through this routine. Part of the public API. */ mobj_t* P_MobjCreate(think_t function, float x, float y, float z, angle_t angle, float radius, float height, int ddflags) { mobj_t* mo; if(!function) Con_Error("P_MobjCreate: Think function invalid, cannot create mobj."); // Do we have any unused mobjs we can reuse? if(unusedMobjs) { mo = unusedMobjs; unusedMobjs = unusedMobjs->sNext; memset(mo, 0, MOBJ_SIZE); } else { // No, we need to allocate another. mo = Z_Calloc(MOBJ_SIZE, PU_MAP, NULL); } mo->pos[VX] = x; mo->pos[VY] = y; mo->pos[VZ] = z; mo->angle = angle; mo->visAngle = mo->angle >> 16; // "angle-servo"; smooth actor turning. mo->radius = radius; mo->height = height; mo->ddFlags = ddflags; mo->thinker.function = function; if(mo->thinker.function) P_ThinkerAdd(&mo->thinker, true); // Make it public. return mo; } /** * All mobjs must be destroyed through this routine. Part of the public API. * * \note Does not actually destroy the mobj. Instead, mobj is marked as * awaiting removal (which occurs when its turn for thinking comes around). */ void P_MobjDestroy(mobj_t* mo) { // Unlink from sector and block lists. P_MobjUnlink(mo); S_StopSound(0, mo); P_ThinkerRemove((thinker_t *) mo); } /** * Called when a mobj is actually removed (when it's thinking turn comes around). * The mobj is moved to the unused list to be reused later. */ void P_MobjRecycle(mobj_t* mo) { // The sector next link is used as the unused mobj list links. mo->sNext = unusedMobjs; unusedMobjs = mo; } /** * 'statenum' must be a valid state (not null!). */ void P_MobjSetState(mobj_t* mobj, int statenum) { state_t* st = states + statenum; boolean spawning = (mobj->state == 0); ded_ptcgen_t* pg; #if _DEBUG if(statenum < 0 || statenum >= defs.count.states.num) Con_Error("P_MobjSetState: statenum %i out of bounds.\n", statenum); #endif mobj->state = st; mobj->tics = st->tics; mobj->sprite = st->sprite; mobj->frame = st->frame; // Check for a ptcgen trigger. for(pg = statePtcGens[statenum]; pg; pg = pg->stateNext) { if(!(pg->flags & PGF_SPAWN_ONLY) || spawning) { // We are allowed to spawn the generator. P_SpawnParticleGen(pg, mobj); } } if(defs.states[statenum].execute) Con_Execute(CMDS_DED, defs.states[statenum].execute, true, false); } /** * Adjusts tmpFloorZ and tmpCeilingZ as lines are contacted. */ boolean PIT_LineCollide(linedef_t* ld, void* parm) { checkpos_data_t* tm = parm; if(tm->box[1][VX] <= ld->bBox[BOXLEFT] || tm->box[0][VX] >= ld->bBox[BOXRIGHT] || tm->box[1][VY] <= ld->bBox[BOXBOTTOM] || tm->box[0][VY] >= ld->bBox[BOXTOP]) // Bounding boxes do not overlap. return true; if(P_BoxOnLineSide2(tm->box[0][VX], tm->box[1][VX], tm->box[0][VY], tm->box[1][VY], ld) != -1) return true; // A line has been hit. tm->mo->wallHit = true; if(!ld->L_backside) return false; // One sided line, can't go through. if(!(tm->mo->ddFlags & DDMF_MISSILE)) { if(ld->flags & DDLF_BLOCKING) return false; // explicitly blocking everything } // set openrange, opentop, openbottom. P_LineOpening(ld); // adjust floor / ceiling heights. if(opentop < tm->ceilingZ) tm->ceilingZ = opentop; if(openbottom > tm->floorZ) tm->floorZ = openbottom; if(lowfloor < tm->dropOffZ) tm->dropOffZ = lowfloor; tm->mo->wallHit = false; return true; } boolean PIT_MobjCollide(mobj_t* mo, void* parm) { checkpos_data_t* tm = parm; float blockdist; boolean overlap = false; // Don't clip against self. if(mo == tm->mo) return true; if(!(mo->ddFlags & DDMF_SOLID)) return true; blockdist = mo->radius + tm->mo->radius; // Only players can move under or over other mobjs. if(tm->pos[VZ] != DDMAXFLOAT && (tm->mo->dPlayer || mo->ddFlags & DDMF_NOGRAVITY)) { if(mo->pos[VZ] > tm->pos[VZ] + tm->height) { // We're under it. return true; } else if(mo->pos[VZ] + mo->height < tm->pos[VZ]) { // We're over it. return true; } overlap = true; } if(fabs(mo->pos[VX] - tm->pos[VX]) >= blockdist || fabs(mo->pos[VY] - tm->pos[VY]) >= blockdist) { // Didn't hit it. return true; } if(overlap) { // How are we positioned? if(tm->pos[VZ] >= mo->pos[VZ] + mo->height - 24) { // Above, allowing stepup. tm->mo->onMobj = mo; tm->floorZ = mo->pos[VZ] + mo->height; return true; } // This was causing problems in Doom E1M1, where a client was able // to walk through the barrel obstacle and get the shotgun. -jk /* // To prevent getting stuck, don't block if moving away from // the object. if(tm->mo->dPlayer && P_ApproxDistance(tm->mo->pos[VX] - mo->pos[VX], tm->mo->pos[VY] - mo->pos[VY]) < P_ApproxDistance(tm->pos[VX] - mo->pos[VX], tm->pos[VY] - mo->pos[VY]) && tm->mo->momz > -12) { // The current distance is smaller than the new one would be. // No blocking needs to occur. // The Z movement test is done to prevent a 'falling through' // case when a mo is moving at a high speed. return true; }*/ // We're hitting this mobj. blockingMobj = mo; } return false; } /** * @return @c true, if the mobj can be positioned at the * specified coordinates. */ boolean P_CheckPosXYZ(mobj_t *mo, float x, float y, float z) { subsector_t *newsubsec; checkpos_data_t data; vec2_t point; boolean result = true; blockingMobj = NULL; mo->onMobj = NULL; mo->wallHit = false; // Prepare the data struct. data.mo = mo; data.flags = mo->ddFlags; data.pos[VX] = x; data.pos[VY] = y; data.pos[VZ] = z; data.height = mo->height; // The bounding box is extended by DDMOBJ_RADIUS_MAX because mobj_ts are // grouped into mapblocks based on their origin point, and can overlap // into adjacent blocks by up to DDMOBJ_RADIUS_MAX units. V2_Set(point, x - mo->radius - DDMOBJ_RADIUS_MAX, y - mo->radius - DDMOBJ_RADIUS_MAX); V2_InitBox(data.box, point); V2_Set(point, x + mo->radius + DDMOBJ_RADIUS_MAX, y + mo->radius + DDMOBJ_RADIUS_MAX); V2_AddToBox(data.box, point); newsubsec = R_PointInSubsector(x, y); // The base floor / ceiling is from the subsector that contains the // point. Any contacted lines the step closer together will adjust them. data.floorZ = data.dropOffZ = newsubsec->sector->SP_floorheight; data.ceilingZ = newsubsec->sector->SP_ceilheight; validCount++; // Check mobjs first, possibly picking stuff up. if(!dontHitMobjs) { if(!P_MobjsBoxIteratorv(data.box, PIT_MobjCollide, &data)) { result = false; } } // Hit something yet? if(result) { // Nope. // Try polyobj->lineDefs and lines. if(!P_AllLinesBoxIteratorv(data.box, PIT_LineCollide, &data)) { result = false; } } tmpCeilingZ = data.ceilingZ; tmpFloorZ = data.floorZ; tmpDropOffZ = data.dropOffZ; return result; } /** * @return @c true, if the mobj can be positioned at the * specified coordinates, assuming traditional 2D DOOM * mobj placement rules. */ boolean P_CheckPosXY(mobj_t *mo, float x, float y) { return P_CheckPosXYZ(mo, x, y, DDMAXFLOAT); } /** * Attempt to move to a mobj to a new position. * * @return @c true, if the move was successful. Both lines and * and other mobjs are checked for collisions. */ boolean P_TryMoveXYZ(mobj_t *mo, float x, float y, float z) { int links = 0; boolean goodPos; blockingMobj = NULL; // Is this a real move? if(mo->pos[VX] == x && mo->pos[VY] == y && mo->pos[VZ] == z) { // No move. Of course it's successful. return true; } goodPos = P_CheckPosXYZ(mo, x, y, z); // Is movement clipping in effect? if(!mo->dPlayer || !(mo->dPlayer->flags & DDPF_NOCLIP)) { if(!goodPos) { if(!mo->onMobj || mo->wallHit) return false; // Solid wall or mo. } // Does it fit between contacted ceiling and floor? if(tmpCeilingZ - tmpFloorZ < mo->height) return false; if(tmpCeilingZ - z < mo->height) return false; // mobj must lower itself to fit. if(mo->dPlayer) { // Players are allowed a stepup. if(tmpFloorZ - z > 24) return false; // Too big a step up. } else { // Normals mobjs are not... if(tmpFloorZ > z) return false; // Below the floor. } } // The move is OK. First unlink. links = P_MobjUnlink(mo); mo->floorZ = tmpFloorZ; mo->ceilingZ = tmpCeilingZ; mo->pos[VX] = x; mo->pos[VY] = y; mo->pos[VZ] = z; // Put back to the same links. P_MobjLink(mo, links); return true; } /** * Try to do the given move. Returns true if nothing was hit. */ boolean P_StepMove(mobj_t *mo, float dx, float dy, float dz) { float delta[3]; float step[3]; boolean notHit = true; delta[VX] = dx; delta[VY] = dy; delta[VZ] = dz; while(delta[VX] || delta[VY] || delta[VZ]) { step[VX] = delta[VX]; step[VY] = delta[VY]; step[VZ] = delta[VZ]; // Is the step too long? while(step[VX] > MAXMOVE || step[VX] < -MAXMOVE || step[VY] > MAXMOVE || step[VY] < -MAXMOVE || step[VZ] > MAXMOVE || step[VZ] < -MAXMOVE) { // Only half that, then. step[VX] /= 2; step[VY] /= 2; step[VZ] /= 2; } // If there is no step, we're already there! if(!(step[VX] == 0 && step[VY] == 0 && step[VZ] == 0)) return notHit; // Can we do this step? while(!P_TryMoveXYZ(mo, mo->pos[VX] + step[VX], mo->pos[VY] + step[VY], mo->pos[VZ] + step[VZ])) { // We hit something! notHit = false; // This means even the current step is unreachable. // Let's make it our intended destination. delta[VX] = step[VX]; delta[VY] = step[VY]; delta[VZ] = step[VZ]; // Try a smaller step. step[VX] /= 2; step[VY] /= 2; step[VZ] /= 2; // If we run out of step, we must give up. if(MIN_STEP(step[VX]) && MIN_STEP(step[VY]) && MIN_STEP(step[VZ])) { return false; } } // Subtract from the 'to go' distance. delta[VX] -= step[VX]; delta[VY] -= step[VY]; delta[VZ] -= step[VZ]; } return notHit; } /** * Takes a valid mobj and adjusts the mobj->floorZ, mobj->ceilingZ, and * possibly mobj->z. This is called for all nearby mobjs whenever a sector * changes height. If the mobj doesn't fit, the z will be set to the lowest * value and false will be returned. */ static boolean heightClip(mobj_t *mo) { boolean onfloor; // During demo playback the player gets preferential treatment. if(mo->dPlayer == &ddPlayers[consolePlayer].shared && playback) return true; onfloor = (mo->pos[VZ] <= mo->floorZ); P_CheckPosXYZ(mo, mo->pos[VX], mo->pos[VY], mo->pos[VZ]); mo->floorZ = tmpFloorZ; mo->ceilingZ = tmpCeilingZ; if(onfloor) { mo->pos[VZ] = mo->floorZ; } else { // Don't adjust a floating mobj unless forced to. if(mo->pos[VZ] + mo->height > mo->ceilingZ) mo->pos[VZ] = mo->ceilingZ - mo->height; } // On clientside, players are represented by two mobjs: the real mobj, // created by the Game, is the one that is visible and modified in this // function. We'll need to sync the hidden client mobj (that receives // all the changes from the server) to match the changes. if(isClient && mo->dPlayer) { Cl_UpdatePlayerPos(P_GetDDPlayerIdx(mo->dPlayer)); } if(mo->ceilingZ - mo->floorZ < mo->height) return false; return true; } /** * Allows the player to slide along any angled walls. Adjusts the player's * momentum vector so that the next move slides along the linedef. */ static void wallMomSlide(linedef_t *ld) { int side; uint an; float movelen, newlen; angle_t moveangle, lineangle, deltaangle; // First check the simple cases. if(ld->slopeType == ST_HORIZONTAL) { tmpMom[VY] = 0; return; } if(ld->slopeType == ST_VERTICAL) { tmpMom[VX] = 0; return; } side = P_PointOnLinedefSide(slideMo->pos[VX], slideMo->pos[VY], ld); lineangle = R_PointToAngle2(0, 0, ld->dX, ld->dY); if(side == 1) lineangle += ANG180; moveangle = R_PointToAngle2(0, 0, tmpMom[VX], tmpMom[VY]); deltaangle = moveangle - lineangle; if(deltaangle > ANG180) deltaangle += ANG180; an = deltaangle >> ANGLETOFINESHIFT; movelen = P_ApproxDistance(tmpMom[MX], tmpMom[MY]); newlen = movelen * FIX2FLT(fineCosine[an]); an = lineangle >> ANGLETOFINESHIFT; tmpMom[VX] = newlen * FIX2FLT(fineCosine[an]); tmpMom[VY] = newlen * FIX2FLT(finesine[an]); } static boolean slideTraverse(intercept_t *in) { linedef_t *li; if(in->type != ICPT_LINE) Con_Error("PTR_SlideTraverse: not a line?"); li = in->d.lineDef; if(!li->L_frontside || !li->L_backside) { if(P_PointOnLinedefSide(slideMo->pos[VX], slideMo->pos[VY], li)) { // The back side. return true; // Continue iteration. } goto isblocking; } // Set openrange, opentop, openbottom. P_LineOpening(li); if(openrange < slideMo->height) goto isblocking; // Doesn't fit. if(opentop - slideMo->pos[VZ] < slideMo->height) goto isblocking; // Mobj is too high. if(openbottom - slideMo->pos[VZ] > 24) goto isblocking; // Too big a step up. // This line doesn't block movement. return true; // Continue iteration. // The line does block movement, see if it is closer than best so far. isblocking: if(in->frac < bestSlideFrac) { secondSlideFrac = bestSlideFrac; secondSlideLine = bestSlideLine; bestSlideFrac = in->frac; bestSlideLine = li; } return false; // Stop iteration. } /** * The momx / momy move is bad, so try to slide along a wall. * Find the first line hit, move flush to it, and slide along it * * This is a kludgy mess. (No kidding?) */ static void mobjSlideMove(mobj_t *mo) { float leadPos[2]; float trailPos[2]; float delta[2]; int hitcount; slideMo = mo; hitcount = 0; retry: if(++hitcount == 3) goto stairstep; // Don't loop forever. // Trace along the three leading corners. if(mo->mom[MX] > 0) { leadPos[VX] = mo->pos[VX] + mo->radius; trailPos[VX] = mo->pos[VX] - mo->radius; } else { leadPos[VX] = mo->pos[VX] - mo->radius; trailPos[VX] = mo->pos[VX] + mo->radius; } if(mo->mom[MY] > 0) { leadPos[VY] = mo->pos[VY] + mo->radius; trailPos[VY] = mo->pos[VY] - mo->radius; } else { leadPos[VY] = mo->pos[VY] - mo->radius; trailPos[VY] = mo->pos[VY] + mo->radius; } bestSlideFrac = FIX2FLT(FRACUNIT + 1); P_PathTraverse(leadPos[VX], leadPos[VY], leadPos[VX] + mo->mom[MX], leadPos[VY] + mo->mom[MY], PT_ADDLINES, slideTraverse); P_PathTraverse(trailPos[VX], leadPos[VY], trailPos[VX] + mo->mom[MX], leadPos[VY] + mo->mom[MY], PT_ADDLINES, slideTraverse); P_PathTraverse(leadPos[VX], trailPos[VY], leadPos[VX] + mo->mom[MX], trailPos[VY] + mo->mom[MY], PT_ADDLINES, slideTraverse); // Move up to the wall. if(bestSlideFrac == FIX2FLT(FRACUNIT + 1)) { // The move most have hit the middle, so stairstep. stairstep: if(!P_TryMoveXYZ(mo, mo->pos[VX], mo->pos[VY] + mo->mom[MY], mo->pos[VZ])) P_TryMoveXYZ(mo, mo->pos[VX] + mo->mom[MX], mo->pos[VY], mo->pos[VZ]); return; } // Fudge a bit to make sure it doesn't hit. bestSlideFrac -= FIX2FLT(0x800); if(bestSlideFrac > 0) { delta[VX] = mo->mom[MX] * bestSlideFrac; delta[VY] = mo->mom[MY] * bestSlideFrac; if(!P_TryMoveXYZ(mo, mo->pos[VX] + delta[VX], mo->pos[VY] + delta[VY], mo->pos[VZ])) goto stairstep; } // Now continue along the wall, first calculate remainder. bestSlideFrac = 1 - (bestSlideFrac + FIX2FLT(0x800)); if(bestSlideFrac > 1) bestSlideFrac = 1; if(bestSlideFrac <= 0) return; tmpMom[MX] = mo->mom[MX] * bestSlideFrac; tmpMom[MY] = mo->mom[MY] * bestSlideFrac; wallMomSlide(bestSlideLine); // Clip the move. mo->mom[MX] = tmpMom[MX]; mo->mom[MY] = tmpMom[MY]; if(!P_TryMoveXYZ(mo, mo->pos[VX] + tmpMom[MX], mo->pos[VY] + tmpMom[MY], mo->pos[VZ])) { goto retry; } } /** * After modifying a sectors floor or ceiling height, call this routine * to adjust the positions of all mobjs that touch the sector. * * If anything doesn't fit anymore, true will be returned. */ boolean PIT_SectorPlanesChanged(mobj_t *mo, void *data) { // Always keep checking. if(heightClip(mo)) return true; noFit = true; return true; } /** * Called whenever a sector's planes are moved. This will update the mobjs * inside the sector and do crushing. */ boolean P_SectorPlanesChanged(sector_t *sector) { noFit = false; // We'll use validCount to make sure mobjs are only checked once. validCount++; P_SectorTouchingMobjsIterator(sector, PIT_SectorPlanesChanged, 0); return noFit; } void P_MobjMovement(mobj_t *mo) { P_MobjMovement2(mo, NULL); } /** * Playmove can be NULL. It's only used with player mobjs. */ void P_MobjMovement2(mobj_t *mo, void *pstate) { clplayerstate_t *playstate = pstate; float tryPos[3]; float delta[3]; ddplayer_t *player; if(mo->mom[MX] == 0 && mo->mom[MY] == 0) return; // This isn't moving anywhere. player = mo->dPlayer; // Make sure we're not trying to move too much. if(mo->mom[MX] > MAXMOVE) mo->mom[MX] = MAXMOVE; else if(mo->mom[MX] < -MAXMOVE) mo->mom[MX] = -MAXMOVE; if(mo->mom[MY] > MAXMOVE) mo->mom[MY] = MAXMOVE; else if(mo->mom[MY] < -MAXMOVE) mo->mom[MY] = -MAXMOVE; // Do the move in progressive steps. delta[MX] = mo->mom[MX]; delta[MY] = mo->mom[MY]; do { if(delta[MX] > MAXMOVE / 2 || delta[MY] > MAXMOVE / 2 || delta[MX] < -MAXMOVE / 2 || delta[MY] < -MAXMOVE / 2) { tryPos[VX] = mo->pos[VX] + delta[MX] / 2; tryPos[VY] = mo->pos[VY] + delta[MY] / 2; delta[MX] /= 2; delta[MY] /= 2; } else { tryPos[VX] = mo->pos[VX] + delta[MX]; tryPos[VY] = mo->pos[VY] + delta[MY]; delta[MX] = delta[MY] = 0; } if(!P_TryMoveXYZ(mo, tryPos[VX], tryPos[VY], mo->pos[VZ])) { // Blocked move. if(player) { if(blockingMobj) { // Slide along the side of the mobj. if(P_TryMoveXYZ(mo, mo->pos[VX], tryPos[VY], mo->pos[VZ])) { mo->mom[MX] = 0; } else if(P_TryMoveXYZ(mo, tryPos[VX], mo->pos[VY], mo->pos[VZ])) { mo->mom[MY] = 0; } else { // All movement stops here. mo->mom[MX] = mo->mom[MY] = 0; } } else { // Try to slide along it. mobjSlideMove(mo); } } else { // Stop moving. mo->mom[MX] = mo->mom[MY] = 0; } } } while(delta[MX] != 0 || delta[MY] != 0); // Apply friction. if(mo->ddFlags & DDMF_MISSILE) return; // No friction for missiles, ever. if(mo->pos[VZ] > mo->floorZ && !mo->onMobj && !(mo->ddFlags & DDMF_FLY)) return; // No friction when airborne. if(mo->mom[MX] > -STOPSPEED && mo->mom[MX] < STOPSPEED && mo->mom[MY] > -STOPSPEED && mo->mom[MY] < STOPSPEED && (!playstate || (!playstate->forwardMove && !playstate->sideMove))) { mo->mom[MX] = mo->mom[MY] = 0; } else { float friction; if(playstate) friction = FIX2FLT(playstate->friction); else friction = DEFAULT_FRICTION; mo->mom[MX] *= friction; mo->mom[MY] *= friction; } } void P_MobjZMovement(mobj_t *mo) { float gravity = FIX2FLT(mapGravity); // Adjust height. mo->pos[VZ] += mo->mom[MZ]; // Clip movement. Another mobj? if(mo->onMobj && mo->pos[VZ] <= mo->onMobj->pos[VZ] + mo->onMobj->height) { if(mo->mom[MZ] < 0) { mo->mom[MZ] = 0; } if(mo->mom[MZ] == 0) mo->pos[VZ] = mo->onMobj->pos[VZ] + mo->onMobj->height; } // The floor. if(mo->pos[VZ] <= mo->floorZ) { // Hit the floor. if(mo->mom[MZ] < 0) { mo->mom[MZ] = 0; } mo->pos[VZ] = mo->floorZ; } else if(mo->ddFlags & DDMF_LOWGRAVITY) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= gravity / 8; } else if(!(mo->ddFlags & DDMF_NOGRAVITY)) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; } if(mo->pos[VZ] + mo->height > mo->ceilingZ) { // hit the ceiling if(mo->mom[MZ] > 0) mo->mom[MZ] = 0; mo->pos[VZ] = mo->ceilingZ - mo->height; } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/net_buf.c0000644000175000017500000002734511357170242022532 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_buf.c: Network Message Handling and Buffering */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_system.h" #include "de_network.h" #include "de_console.h" #include "de_misc.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ #define MSG_MUTEX_NAME "MsgQueueMutex" // Flags for the sent message store (for to-be-confirmed messages): //#define SMSF_ORDERED 0x1 // Block other ordered messages until confirmed //#define SMSF_QUEUED 0x2 // Ordered message waiting to be sent //#define SMSF_CONFIRMED 0x4 // Delivery has been confirmed! (OK to remove) // Length of the received message ID history. //#define STORE_HISTORY_SIZE 100 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean allowSending; netbuffer_t netBuffer; // The Sent Message Store: list of sent or queued messages waiting to be // confirmed. //static store_t stores[DDMAXPLAYERS]; // The message queue: list of incoming messages waiting for processing. static netmessage_t *msgHead, *msgTail; static int msgCount; // A mutex is used to protect the addition and removal of messages from // the message queue. static mutex_t msgMutex; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Number of bytes of outgoing data transmitted. static size_t numOutBytes; // Number of bytes sent over the network (compressed). static size_t numSentBytes; // CODE -------------------------------------------------------------------- /** * Initialize the low-level network subsystem. This is called always * during startup (via Sys_Init()). */ void N_Init(void) { // Create a mutex for the message queue. msgMutex = Sys_CreateMutex(MSG_MUTEX_NAME); allowSending = false; N_SockInit(); N_MasterInit(); N_SystemInit(); // Platform dependent stuff. } /** * Shut down the low-level network interface. Called during engine * shutdown (not before). */ void N_Shutdown(void) { N_SystemShutdown(); N_MasterShutdown(); N_SockShutdown(); allowSending = false; // Close the handle of the message queue mutex. Sys_DestroyMutex(msgMutex); msgMutex = 0; if(ArgExists("-huffavg")) { Con_Execute(CMDS_DDAY, "huffman", false, false); } } /** * Acquire or release ownership of the message queue mutex. * * @return @c true, if successful. */ boolean N_LockQueue(boolean doAcquire) { if(doAcquire) Sys_Lock(msgMutex); else Sys_Unlock(msgMutex); return true; } /** * Adds the given netmessage_s to the queue of received messages. * Before calling this, allocate the message using malloc(). We use a * mutex to synchronize access to the message queue. This is called * in the network receiver thread. */ void N_PostMessage(netmessage_t *msg) { N_LockQueue(true); // This will be the latest message. msg->next = NULL; if(msgTail) { // There are previous messages. msgTail->next = msg; } // The tail pointer points to the last message. msgTail = msg; // If there is no head, this'll be the first message. if(msgHead == NULL) msgHead = msg; // One new message available. msgCount++; N_LockQueue(false); } /** * Extracts the next message from the queue of received messages. * The caller must release the message when it's no longer needed, * using N_ReleaseMessage(). * * We use a mutex to synchronize access to the message queue. This is * called in the Doomsday thread. * * @return @c NULL, if no message is found; */ netmessage_t *N_GetMessage(void) { // This is the message we'll return. netmessage_t *msg = NULL; N_LockQueue(true); if(msgHead != NULL) { msg = msgHead; // If there are no more messages, the tail pointer must be // cleared, too. if(!msgHead->next) msgTail = NULL; // Advance the head pointer. msgHead = msgHead->next; if(msg) { // One less message available. msgCount--; } } N_LockQueue(false); // Identify the sender. if(msg) { msg->player = N_IdentifyPlayer(msg->sender); } return msg; } /** * Frees the message. */ void N_ReleaseMessage(netmessage_t *msg) { if(msg->handle) { N_ReturnBuffer(msg->handle); } M_Free(msg); } /** * Empties the message buffers. */ void N_ClearMessages(void) { netmessage_t *msg; while((msg = N_GetMessage()) != NULL) N_ReleaseMessage(msg); // The queue is now empty. msgHead = msgTail = NULL; msgCount = 0; } /** * Send the data in the netbuffer. The message is sent using an * unreliable, nonsequential (i.e. fast) method. * * Handles broadcasts using recursion. * Clients can only send stuff to the server. */ void N_SendPacket(int flags) { uint i, dest = 0; void *data; size_t size; // Is the network available? if(!allowSending || !N_IsAvailable()) return; // Figure out the destination DPNID. if(netServerMode) { player_t *plr = &ddPlayers[netBuffer.player]; ddplayer_t *ddpl = &plr->shared; if(netBuffer.player >= 0 && netBuffer.player < DDMAXPLAYERS) { if((ddpl->flags & DDPF_LOCAL) || !clients[netBuffer.player].connected) { // Do not send anything to local or disconnected players. return; } dest = clients[netBuffer.player].nodeID; } else { // Broadcast to all non-local players, using recursive calls. for(i = 0; i < DDMAXPLAYERS; ++i) { netBuffer.player = i; N_SendPacket(flags); } // Reset back to -1 to notify of the broadcast. netBuffer.player = NSP_BROADCAST; return; } } // Message IDs are currently not used. netBuffer.msg.id = 0; // This is what will be sent. numOutBytes += netBuffer.headerLength + netBuffer.length; // Compress using Huffman codes. data = Huff_Encode((byte *) &netBuffer.msg, netBuffer.headerLength + netBuffer.length, &size); // This many bytes are actually sent. numSentBytes += size; if(flags & (SPF_CONFIRM | SPF_ORDERED)) { // Ordered and confirmed messages are send over a TCP connection. N_SendDataBufferReliably(data, size, dest); #if _DEBUG VERBOSE2( Con_Message("N_SendPacket: Sending %ul bytes reliably to %i.\n", size, dest)); #endif } else { // Other messages are sent via UDP, so that there is as little latency // as possible. N_SendDataBuffer(data, size, dest); } } /** * @return The player number that corresponds the DPNID. */ uint N_IdentifyPlayer(nodeid_t id) { uint i; boolean found; if(netServerMode) { // What is the corresponding player number? Only the server keeps // a list of all the IDs. i = 0; found = false; while(i < DDMAXPLAYERS && !found) if(clients[i].nodeID == id) found = true; else i++; if(found) return i; else return -1; // Bogus? } // Clients receive messages only from the server. return 0; } /** * Confirmations are handled here. * * \note Skips all messages from unknown nodeids! * * @return The next message waiting in the incoming message * queue. */ netmessage_t *N_GetNextMessage(void) { netmessage_t *msg; while((msg = N_GetMessage()) != NULL) { //// \fixme When can player IDs be unknown? /* if(msg->player < 0) { // From an unknown ID? N_ReleaseMessage(msg); } else */ { // Decode the Huffman codes. The returned buffer is static, so // it doesn't need to be freed (not thread-safe, though). msg->data = Huff_Decode(msg->data, msg->size, &msg->size); // The original packet buffer can be freed. N_ReturnBuffer(msg->handle); msg->handle = NULL; return msg; } } return NULL; // There are no more messages. } /** * An attempt is made to extract a message from the message queue. * * @return @c true, if a message successfull. */ boolean N_GetPacket(void) { netmessage_t *msg; // If there are net events pending, let's not return any packets // yet. The net events may need to be processed before the // packets. if(!N_IsAvailable() || N_NEPending()) return false; netBuffer.player = -1; netBuffer.length = 0; /*{extern byte monitorMsgQueue; if(monitorMsgQueue) Con_Message("N_GetPacket: %i messages queued.\n", msgCount); }*/ if((msg = N_GetNextMessage()) == NULL) { // No messages at this time. return false; } // There was a packet! /* #if _DEBUG Con_Message("N_GetPacket: from=%x, len=%i\n", msg->sender, msg->size); #endif */ netBuffer.player = msg->player; netBuffer.length = msg->size - netBuffer.headerLength; memcpy(&netBuffer.msg, msg->data, MIN_OF(sizeof(netBuffer.msg), msg->size)); // The message can now be freed. N_ReleaseMessage(msg); // We have no idea who sent this (on serverside). if(netBuffer.player == -1) return false; return true; } /** * Print low-level information about the network buffer. */ void N_PrintBufferInfo(void) { N_PrintHuffmanStats(); } /** * Print status information about the workings of Huffman compression * in the network buffer. */ void N_PrintHuffmanStats(void) { if(numOutBytes == 0) { Con_Printf("Huffman efficiency: Nothing has been sent yet.\n"); } else { Con_Printf("Huffman efficiency: %.3f%% (data: %ul bytes, sent: %ul " "bytes)\n", 100 - (100.0f * numSentBytes) / numOutBytes, numOutBytes, numSentBytes); } } /** * Console command for printing the Huffman efficiency. */ D_CMD(HuffmanStats) { N_PrintHuffmanStats(); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_plane.c0000644000175000017500000000672111357170242022521 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_plane.c: World planes. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Update the plane, property is selected by DMU_* name. */ boolean Plane_SetProperty(plane_t *pln, const setargs_t *args) { switch(args->prop) { case DMU_HEIGHT: DMU_SetValue(DMT_PLANE_HEIGHT, &pln->height, args, 0); if(!ddMapSetup) { R_AddWatchedPlane(watchedPlaneList, pln); R_MarkDependantSurfacesForDecorationUpdate(pln); } break; case DMU_TARGET_HEIGHT: DMU_SetValue(DMT_PLANE_TARGET, &pln->target, args, 0); break; case DMU_SPEED: DMU_SetValue(DMT_PLANE_SPEED, &pln->speed, args, 0); break; default: Con_Error("Plane_SetProperty: Property %s is not writable.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } /** * Get the value of a plane property, selected by DMU_* name. */ boolean Plane_GetProperty(const plane_t *pln, setargs_t *args) { switch(args->prop) { case DMU_SECTOR: DMU_GetValue(DMT_PLANE_SECTOR, &pln->sector, args, 0); break; case DMU_HEIGHT: DMU_GetValue(DMT_PLANE_HEIGHT, &pln->height, args, 0); break; case DMU_SOUND_ORIGIN: { const ddmobj_base_t* dmo = &pln->soundOrg; DMU_GetValue(DMT_PLANE_SOUNDORG, &dmo, args, 0); break; } case DMU_TARGET_HEIGHT: DMU_GetValue(DMT_PLANE_TARGET, &pln->target, args, 0); break; case DMU_SPEED: DMU_GetValue(DMT_PLANE_SPEED, &pln->speed, args, 0); break; default: Con_Error("Plane_GetProperty: No property %s.\n", DMU_Str(args->prop)); } return true; // Continue iteration. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_help.c0000644000175000017500000002254611357170242022505 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_help.c: Help Text Strings. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define MAX_STRINGS 16 // TYPES ------------------------------------------------------------------- typedef struct helpstring_s { int type; char* text; } helpstring_t; typedef struct helpnode_s { struct helpnode_s *prev, *next; char* id; helpstring_t str[MAX_STRINGS]; } helpnode_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(LoadHelp); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean helpInited = false; static helpnode_t helpRoot; // CODE -------------------------------------------------------------------- void DH_Register(void) { C_CMD("loadhelp", "", LoadHelp); } /** * Create and link a new help node. * * @return Ptr to the newly created helpnode. */ static helpnode_t* DH_NewNode(void) { helpnode_t* n = M_Calloc(sizeof(*n)); n->next = &helpRoot; n->prev = helpRoot.prev; helpRoot.prev = n->prev->next = n; return n; } /** * Unlink the helpnode from the dlist and destroy it. * * @param node Ptr to the node to be destroyed. */ static void DH_DeleteNode(helpnode_t* node) { int i; if(!node) return; node->prev->next = node->next; node->next->prev = node->prev; // Free all memory associated with the node. if(node->id) M_Free(node->id); for(i = 0; i < MAX_STRINGS; ++i) M_Free(node->str[i].text); M_Free(node); } /** * Parses the given file looking for help strings. * * @param fileName Path to the file to be read. * * @return Non-zero if the file was read successfully. */ static int DH_ReadStrings(char* fileName) { DFILE* file = F_Open(fileName, "rt"); char line[2048], *ptr, *eol, *end; helpnode_t* node = NULL; int count = 0, length; if(!file) { Con_Message("DH_ReadStrings: %s not found.\n", fileName); return false; // The file was not found. } while(!deof(file)) { M_ReadLine(line, sizeof(line), file); if(M_IsComment(line)) continue; // Where does the line begin? ptr = M_SkipWhite(line); if(!*ptr) continue; // An empty line. eol = ptr + strlen(ptr); // End of line. // A new node? if(*ptr == '[') { node = DH_NewNode(); count = 0; if(!(end = strchr(ptr, ']'))) end = eol; node->id = M_Calloc(end - ptr); strncpy(node->id, ptr + 1, end - ptr - 1); } else if(node && (end = strchr(ptr, '='))) // It must be a key? { helpstring_t* hst = node->str + count; if(count == MAX_STRINGS) continue; // No more room. count++; // The type of the string. if(!strnicmp(ptr, "des", 3)) hst->type = HST_DESCRIPTION; else if(!strnicmp(ptr, "cv", 2)) hst->type = HST_CONSOLE_VARIABLE; else if(!strnicmp(ptr, "def", 3)) hst->type = HST_DEFAULT_VALUE; else if(!strnicmp(ptr , "inf", 3)) hst->type = HST_INFO; ptr = M_SkipWhite(end + 1); // The value may be split over multiple lines. // 64 kb should be quite enough. length = 0, hst->text = M_Malloc(0x10000); while(*ptr) { // Backslash escapes. if(*ptr == '\\') { // Is this the last visible char? if(!*M_SkipWhite(ptr + 1)) { // Read the next line. M_ReadLine(line, sizeof(line), file); ptr = M_SkipWhite(line); } else // \ is not the last char on the line. { ptr++; if(*ptr == '\\') hst->text[length++] = '\\'; if(*ptr == 'n') hst->text[length++] = '\n'; if(*ptr == 'b') hst->text[length++] = '\b'; ptr++; } } else { // Append to the text. hst->text[length++] = *ptr++; } } // Resize the memory to fit the text. hst->text[length] = 0; hst->text = M_Realloc(hst->text, length + 1); } } // The file was read successfully. F_Close(file); return true; } /** * Finds a node matching the ID. Use DH_GetString to read strings from it. * * @param id Help node ID to be searched for. * * @return Ptr to helpnode if matched ELSE @c NULL,. */ void* DH_Find(const char* id) { helpnode_t* n; size_t length; if(!helpInited) return NULL; length = strlen(id); for(n = helpRoot.next; n != &helpRoot; n = n->next) { /** * Don't compare unless the string is long enough. * This also stops us returning a false positive when a substring * matches the search string e.g: * [rend-light] != [rend-light-ambient] */ if(strlen(n->id) < length) continue; if(!strnicmp(id, n->id, length)) return n; } return NULL; } /** * Return a string from within the helpnode. Strings are stored internally * and indexed by their type (e.g. HST_DESCRIPTION). * * @param foundNode The helpnode to return the string from. * @param type The string type (index) to look for within the node. * * @return Ptr to the found string ELSE @c NULL,. Note, * may also return @c NULL, if passed an * invalid helpnode ptr OR the help string database has * not beeen initialized yet. */ char* DH_GetString(void* foundNode, int type) { helpnode_t* n = foundNode; int i; if(!n || !helpInited || type < 0 || type > NUM_HELPSTRING_TYPES) return NULL; for(i = 0; i < MAX_STRINGS; ++i) if(n->str[i].text && n->str[i].type == type) return n->str[i].text; return NULL; } /** * Initializes the help string database. After which, attempts to read * help strings from both the engine and game-specific help string files. */ void DD_InitHelp(void) { filename_t helpFileName; float starttime; if(helpInited) return; // Already inited. starttime = Sys_GetSeconds(); // Init the links. helpRoot.next = helpRoot.prev = &helpRoot; // Control Panel help. M_TranslatePath(helpFileName, "}data\\cphelp.txt", FILENAME_T_MAXLEN); DH_ReadStrings(helpFileName); // Ccmd help (game-specific). sprintf(helpFileName, "}data\\%s\\conhelp.txt", (char *) gx.GetVariable(DD_GAME_NAME)); M_TranslatePath(helpFileName, helpFileName, FILENAME_T_MAXLEN); DH_ReadStrings(helpFileName); // Help is now available. helpInited = true; VERBOSE(Con_Message("DD_InitHelp: Done in %.2f seconds.\n", Sys_GetSeconds() - starttime)); } /** * Shuts down the help string database. Frees all storage and destroys * database itself. */ void DD_ShutdownHelp(void) { if(!helpInited) return; helpInited = false; // Delete all the nodes. while(helpRoot.next != &helpRoot) DH_DeleteNode(helpRoot.next); } D_CMD(LoadHelp) { DD_ShutdownHelp(); DD_InitHelp(); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/def_main.c0000644000175000017500000013751011357170242022646 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * def_main.c: Definitions Subsystem */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_system.h" #include "de_platform.h" #include "de_refresh.h" #include "de_console.h" #include "de_audio.h" #include "de_misc.h" #include #include // XGClass.h is actually a part of the engine. #include "../../../plugins/common/include/xgclass.h" // MACROS ------------------------------------------------------------------ #define LOOPi(n) for(i = 0; i < (n); ++i) #define LOOPk(n) for(k = 0; k < (n); ++k) // Legacy frame flags. #define FF_FULLBRIGHT 0x8000 // flag in mobj->frame #define FF_FRAMEMASK 0x7fff // TYPES ------------------------------------------------------------------- typedef struct { char* name; // Name of the routine. void (C_DECL * func) (); // Pointer to the function. } actionlink_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void Def_ReadProcessDED(const char* filename); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern filename_t defsFileName; extern filename_t topDefsFileName; // PUBLIC DATA DEFINITIONS ------------------------------------------------- ded_t defs; // The main definitions database. sprname_t* sprNames; // Sprite name list. state_t* states; // State list. ded_light_t** stateLights; ded_ptcgen_t** statePtcGens; mobjinfo_t* mobjInfo; // Map object info database. sfxinfo_t* sounds; // Sound effect list. ddtext_t* texts; // Text list. mobjinfo_t** stateOwners; // A pointer for each state. ded_count_t countSprNames; ded_count_t countStates; ded_count_t countMobjInfo; ded_count_t countSounds; ded_count_t countTexts; ded_count_t countStateOwners; boolean firstDED; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean defsInited = false; static const char* dedFiles[MAX_READ]; static mobjinfo_t* gettingFor; xgclass_t nullXgClassLinks; // Used when none defined. xgclass_t* xgClassLinks; // CODE -------------------------------------------------------------------- /** * Retrieves the XG Class list from the Game. * XGFunc links are provided by the Game, who owns the actual * XG classes and their functions. */ static int GetXGClasses(void) { xgClassLinks = (xgclass_t *) gx.GetVariable(DD_XGFUNC_LINK); if(!xgClassLinks) { memset(&nullXgClassLinks, 0, sizeof(nullXgClassLinks)); xgClassLinks = &nullXgClassLinks; } return 1; } /** * Initializes the definition databases. */ void Def_Init(void) { int i, c, p; sprNames = NULL; // Sprite name list. mobjInfo = NULL; states = NULL; statePtcGens = NULL; stateLights = NULL; sounds = NULL; texts = NULL; stateOwners = NULL; DED_ZCount(&countSprNames); DED_ZCount(&countMobjInfo); DED_ZCount(&countStates); DED_ZCount(&countSounds); DED_ZCount(&countTexts); DED_ZCount(&countStateOwners); // Retrieve the XG Class links from the game .dll GetXGClasses(); DED_Init(&defs); for(i = 0; i < MAX_READ; ++i) dedFiles[i] = NULL; // The engine defs. c = 0; dedFiles[c++] = defsFileName; // Add the default ded. It will be overwritten by -defs. dedFiles[c++] = topDefsFileName; // See which .ded files are specified on the command line. for(p = 0; p < Argc(); ++p) { const char* arg = Argv(p); if(!ArgRecognize("-def", arg) && !ArgRecognize("-defs", arg)) continue; while(c < MAX_READ && ++p != Argc() && !ArgIsOption(p)) { // Add it to the list. dedFiles[c++] = Argv(p); Con_Message("Def_Init: Added '%s' to dedFiles.\n", Argv(p)); } p--;/* For ArgIsOption(p) necessary, for p==Argc() harmless */ } } /** * Destroy databases. */ void Def_Destroy(void) { // To make sure... DED_Destroy(&defs); DED_Init(&defs); // Destroy the databases. DED_DelArray((void **) &sprNames, &countSprNames); DED_DelArray((void **) &states, &countStates); DED_DelArray((void **) &mobjInfo, &countMobjInfo); DED_DelArray((void **) &sounds, &countSounds); DED_DelArray((void **) &texts, &countTexts); DED_DelArray((void **) &stateOwners, &countStateOwners); // Destroy the state array, parallel LUTs. if(statePtcGens) M_Free(statePtcGens); statePtcGens = NULL; if(stateLights) M_Free(stateLights); stateLights = NULL; defsInited = false; } /** * Guesses the location of the Defs Auto directory based on main DED * file. */ void Def_GetAutoPath(char* path, size_t len) { char* lastSlash; strncpy(path, topDefsFileName, len); lastSlash = strrchr(path, DIR_SEP_CHAR); if(!lastSlash) { strncpy(path, "", len); // Failure! return; } strncpy(lastSlash + 1, "auto" DIR_SEP_STR, len - ((lastSlash + 1) - path)); } /** * @return Number of the given sprite else, * @c -1, if it doesn't exist. */ int Def_GetSpriteNum(const char* name) { int i; if(!name || !name[0]) return -1; for(i = 0; i < countSprNames.num; ++i) if(!stricmp(sprNames[i].name, name)) return i; return -1; } int Def_GetMobjNum(const char* id) { int i; if(!id || !id[0]) return -1; for(i = 0; i < defs.count.mobjs.num; ++i) if(!stricmp(defs.mobjs[i].id, id)) return i; return -1; } int Def_GetMobjNumForName(const char* name) { int i; if(!name || !name[0]) return -1; for(i = defs.count.mobjs.num -1; i >= 0; --i) if(!stricmp(defs.mobjs[i].name, name)) return i; return -1; } int Def_GetStateNum(const char* id) { int i; if(!id || !id[0]) return -1; for(i = 0; i < defs.count.states.num; ++i) if(!strcmp(defs.states[i].id, id)) return i; return -1; } int Def_GetModelNum(const char *id) { int i; if(!id[0]) return -1; for(i = 0; i < defs.count.models.num; ++i) if(!strcmp(defs.models[i].id, id)) return i; return -1; } int Def_GetSoundNum(const char* id) { int i; if(!id || !id[0]) return -1; for(i = 0; i < defs.count.sounds.num; ++i) { if(!strcmp(defs.sounds[i].id, id)) return i; } return -1; } /** * Looks up a sound using the Name key. If the name is not found, returns * the NULL sound index (zero). */ int Def_GetSoundNumForName(const char* name) { int i; if(!name || !name[0]) return -1; for(i = 0; i < defs.count.sounds.num; ++i) if(!stricmp(defs.sounds[i].name, name)) return i; return 0; } int Def_GetMusicNum(const char* id) { int i; if(!id || !id[0]) return -1; for(i = 0; i < defs.count.music.num; ++i) if(!strcmp(defs.music[i].id, id)) return i; return -1; } /*// A simple action function that will be executed. void A_ExecuteCommand(mobj_t *mobj) { } */ acfnptr_t Def_GetActionPtr(const char* name) { // Action links are provided by the Game, who owns the actual // action functions. actionlink_t* link = (actionlink_t *) gx.GetVariable(DD_ACTION_LINK); if(!name || !name[0]) return 0; if(!link) { Con_Error("GetActionPtr: Game DLL doesn't have an action " "function link table.\n"); } for(; link->name; link++) if(!strcmp(name, link->name)) return link->func; // The engine provides a couple of simple action functions. /*if(!strcmp(name, "A_ExecuteCommand")) return A_ExecuteCommand; if(!strcmp(name, "A_ExecuteCommandPSpr")) return A_ExecuteCommandPSpr; */ return 0; } ded_mapinfo_t* Def_GetMapInfo(const char* mapID) { int i; if(!mapID || !mapID[0]) return 0; for(i = defs.count.mapInfo.num - 1; i >= 0; i--) if(!stricmp(defs.mapInfo[i].id, mapID)) return defs.mapInfo + i; return 0; } ded_sky_t* Def_GetSky(const char* id) { int i; if(!id || !id[0]) return NULL; for(i = defs.count.skies.num - 1; i >= 0; i--) if(!stricmp(defs.skies[i].id, id)) return defs.skies + i; return NULL; } ded_material_t* Def_GetMaterial(const char* name, material_namespace_t mnamespace) { int i; if(!name || !name[0]) return NULL; for(i = defs.count.materials.num - 1; i >= 0; i--) { ded_material_t* def = &defs.materials[i]; if(mnamespace != MN_ANY && def->id.mnamespace != mnamespace) continue; if(!stricmp(def->id.name, name)) return def; } return 0; } ded_decor_t* Def_GetDecoration(material_t* mat, boolean hasExt) { int i; ded_decor_t* def; for(i = defs.count.decorations.num - 1, def = defs.decorations + i; i >= 0; i--, def--) { material_t* defMat = P_ToMaterial(P_MaterialNumForName(def->material.name, def->material.mnamespace)); if(mat == defMat) { // Is this suitable? if(R_IsAllowedDecoration(def, mat, hasExt)) return def; } } return 0; } ded_reflection_t* Def_GetReflection(material_t* mat, boolean hasExt) { int i; ded_reflection_t* def; for(i = defs.count.reflections.num - 1, def = defs.reflections + i; i >= 0; i--, def--) { material_t* defMat = P_ToMaterial(P_MaterialNumForName(def->material.name, def->material.mnamespace)); if(mat == defMat) { // Is this suitable? if(R_IsAllowedReflection(def, mat, hasExt)) return def; } } return NULL; } ded_detailtexture_t* Def_GetDetailTex(material_t* mat, boolean hasExt) { int i; ded_detailtexture_t* def; // Search through the assignments. for(i = defs.count.details.num - 1, def = defs.details + i; i >= 0; i--, def--) { material_t* defMat = P_ToMaterial(P_MaterialNumForName(def->material1.name, def->material1.mnamespace)); if(mat == defMat) { // Is this sutiable? if(R_IsAllowedDetailTex(def, mat, hasExt)) return def; } defMat = P_ToMaterial(P_MaterialNumForName(def->material2.name, def->material2.mnamespace)); if(mat == defMat) { // Is this sutiable? if(R_IsAllowedDetailTex(def, mat, hasExt)) return def; } } return NULL; } ded_ptcgen_t* Def_GetGenerator(material_t* mat, boolean hasExt) { ded_ptcgen_t* def; int i; // The generator will be determined now. for(i = 0, def = defs.ptcGens; i < defs.count.ptcGens.num; ++i, def++) { material_t* defMat; if(!(defMat = P_ToMaterial( P_MaterialNumForName(def->material.name, def->material.mnamespace)))) continue; if(def->flags & PGF_GROUP) { // Generator triggered by all materials in the (animation) group. /** * A search is necessary only if we know both the used material and * the specified material in this definition are in *a* group. */ if(defMat->inAnimGroup && mat->inAnimGroup) { int g, numGroups = R_NumAnimGroups(); for(g = 0; g < numGroups; ++g) { if(R_IsInAnimGroup(g, defMat) && R_IsInAnimGroup(g, mat)) { if(R_IsPrecacheGroup(g)) continue; // Precache groups don't apply. // Both are in this group! This def will do. return def; } } } } if(mat == defMat) return def; } return NULL; // Not found. } ded_ptcgen_t* Def_GetDamageGenerator(int mobjType) { int i; ded_ptcgen_t* def; // Search for a suitable definition. for(i = 0, def = defs.ptcGens; i < defs.count.ptcGens.num; ++i, def++) { // It must be for this type of mobj. if(def->damageNum == mobjType) return def; } return NULL; } ded_xgclass_t* Def_GetXGClass(const char* name) { ded_xgclass_t* def; int i; if(!name || !name[0]) return 0; for(i = defs.count.xgClasses.num - 1, def = defs.xgClasses + i; i >= 0; i--, def--) { if(!(stricmp(name, def->id))) return def; } return 0; } int Def_GetFlagValue(const char* flag) { int i; for(i = defs.count.flags.num - 1; i >= 0; i--) if(!stricmp(defs.flags[i].id, flag)) return defs.flags[i].value; Con_Message("Def_GetFlagValue: Undefined flag '%s'.\n", flag); return 0; } /** * Attempts to retrieve a flag by its prefix and value. * Returns a ptr to the text string of the first flag it * finds that matches the criteria, else NULL. */ const char* Def_GetFlagTextByPrefixVal(const char* prefix, int val) { int i; for(i = defs.count.flags.num - 1; i >= 0; i--) if(strnicmp(defs.flags[i].id, prefix, sizeof(prefix)) == 0 && defs.flags[i].value == val) return defs.flags[i].text; return NULL; } int Def_EvalFlags(char* ptr) { int value = 0, len; char buf[64]; while(*ptr) { ptr = M_SkipWhite(ptr); len = M_FindWhite(ptr) - ptr; strncpy(buf, ptr, len); buf[len] = 0; value |= Def_GetFlagValue(buf); ptr += len; } return value; } int Def_GetTextNumForName(const char* name) { int i; if(!name[0]) return -1; for(i = defs.count.text.num -1; i >= 0; --i) if(!(strcmp(defs.text[i].id, name))) return i; return -1; } /** * Escape sequences are un-escaped (\n, \r, \t, \s, \_). */ void Def_InitTextDef(ddtext_t* txt, char* str) { char* out, *in; if(!str) str = ""; // Handle null pointers with "". txt->text = M_Calloc(strlen(str) + 1); for(out = txt->text, in = str; *in; out++, in++) { if(*in == '\\') { in++; if(*in == 'n') *out = '\n'; // Newline. else if(*in == 'r') *out = '\r'; // Carriage return. else if(*in == 't') *out = '\t'; // Tab. else if(*in == '_' || *in == 's') *out = ' '; // Space. else *out = *in; continue; } *out = *in; } // Adjust buffer to fix exactly. txt->text = M_Realloc(txt->text, strlen(txt->text) + 1); } /** * Callback for DD_ReadProcessDED. */ int Def_ReadDEDFile(const char* fn, filetype_t type, void* parm) { // Skip directories. if(type == FT_DIRECTORY) return true; if(M_CheckFileID(fn)) { if(!DED_Read(&defs, fn)) { // Damn. Con_Error("Def_ReadDEDFile: %s\n", dedReadError); } else if(verbose) { Con_Message("DED done: %s\n", M_PrettyPath(fn)); } } // Continue processing files. return true; } void Def_ReadProcessDED(const char* fileName) { filename_t fn, fullFn; directory_t dir; memset(&dir, 0, sizeof(dir)); Dir_FileName(fn, fileName, FILENAME_T_MAXLEN); // We want an absolute path. if(!Dir_IsAbsolute(fileName)) { Dir_FileDir(fileName, &dir); sprintf(fullFn, "%s%s", dir.path, fn); } else { strncpy(fullFn, fileName, FILENAME_T_MAXLEN); } if(strchr(fn, '*') || strchr(fn, '?')) { // Wildcard search. F_ForAll(fullFn, 0, Def_ReadDEDFile); } else { Def_ReadDEDFile(fullFn, FT_NORMAL, 0); } } /** * Prints a count with a 2-space indentation. */ void Def_CountMsg(int count, const char* label) { if(!verbose && !count) return; // Don't print zeros if not verbose. Con_Message("%5i %s\n", count, label); } /** * Reads all DD_DEFNS lumps found in the lumpInfo. */ void Def_ReadLumpDefs(void) { int i, c; for(i = 0, c = 0; i < numLumps; ++i) if(!strnicmp(W_LumpName(i), "DD_DEFNS", 8)) { c++; if(!DED_ReadLump(&defs, i)) { Con_Error("DD_ReadLumpDefs: Parse error when reading " "DD_DEFNS from\n %s.\n", W_LumpSourceFile(i)); } } if(c || verbose) { Con_Message("ReadLumpDefs: %i definition lump%s read.\n", c, c != 1 ? "s" : ""); } } /** * Uses gettingFor. Initializes the state-owners information. */ int Def_StateForMobj(const char* state) { int num = Def_GetStateNum(state); int st, count = 16; if(num < 0) num = 0; // State zero is the NULL state. if(num > 0) { stateOwners[num] = gettingFor; // Scan forward at most 'count' states, or until we hit a state with // an owner, or the NULL state. for(st = states[num].nextState; st > 0 && count-- && !stateOwners[st]; st = states[st].nextState) { stateOwners[st] = gettingFor; } } return num; } int Def_GetIntValue(char* val, int* returned_val) { char *data; // First look for a DED Value if(Def_Get(DD_DEF_VALUE, val, &data)) { *returned_val = strtol(data, 0, 0); return true; } // Convert the literal string *returned_val = strtol(val, 0, 0); return false; } static void readDefs(void) { int i; float starttime = Sys_GetSeconds(); for(i = 0; dedFiles[i]; ++i) { Con_Message("Reading definition file: %s\n", M_PrettyPath(dedFiles[i])); Def_ReadProcessDED(dedFiles[i]); } // Read definitions from WAD files. Def_ReadLumpDefs(); VERBOSE(Con_Message("Def_ReadDefs: Done in %.2f seconds.\n", Sys_GetSeconds() - starttime)); } /** * Reads the specified definition files, and creates the sprite name, * state, mobjinfo, sound, music, text and mapinfo databases accordingly. */ void Def_Read(void) { int i, k; if(defsInited) { // We've already initialized the definitions once. // Get rid of everything. R_ClearClassDataPath(DDRC_MODEL); Def_Destroy(); } firstDED = true; // Clear all existing definitions. DED_Destroy(&defs); DED_Init(&defs); // Reset file IDs so previously seen files can be processed again. M_ResetFileIDs(); // Read all definitions, files and lumps. readDefs(); // Any definition hooks? Plug_DoHook(HOOK_DEFS, 0, &defs); // Check that enough defs were found. if(!defs.count.states.num || !defs.count.mobjs.num) Con_Error("DD_ReadDefs: No state or mobj definitions found!\n"); Con_Message("Definitions:\n"); // Sprite names. DED_NewEntries((void **) &sprNames, &countSprNames, sizeof(*sprNames), defs.count.sprites.num); for(i = 0; i < countSprNames.num; ++i) strcpy(sprNames[i].name, defs.sprites[i].id); Def_CountMsg(countSprNames.num, "sprite names"); // States. DED_NewEntries((void **) &states, &countStates, sizeof(*states), defs.count.states.num); // Zero the parallel LUTs to the states array. These will be re-inited // anyway so there is no need to worry about updating any old values. statePtcGens = M_Realloc(statePtcGens, sizeof(*statePtcGens) * countStates.num); memset(statePtcGens, 0, sizeof(*statePtcGens) * countStates.num); stateLights = M_Realloc(stateLights, sizeof(*stateLights) * countStates.num); memset(stateLights, 0, sizeof(*stateLights) * countStates.num); for(i = 0; i < countStates.num; ++i) { ded_state_t* dstNew, *dst = &defs.states[i]; // Make sure duplicate IDs overwrite the earliest. int stateNum = Def_GetStateNum(dst->id); state_t* st; if(stateNum == -1) continue; dstNew = defs.states + stateNum; st = states + stateNum; st->sprite = Def_GetSpriteNum(dst->sprite.id); st->flags = dst->flags; st->frame = dst->frame; // Check for the old or'd in fullbright flag. if(st->frame & FF_FULLBRIGHT) { st->frame &= FF_FRAMEMASK; st->flags |= STF_FULLBRIGHT; } st->tics = dst->tics; st->action = Def_GetActionPtr(dst->action); st->nextState = Def_GetStateNum(dst->nextState); for(k = 0; k < NUM_STATE_MISC; ++k) st->misc[k] = dst->misc[k]; // Replace the older execute string. if(dst != dstNew) { if(dstNew->execute) M_Free(dstNew->execute); dstNew->execute = dst->execute; dst->execute = NULL; } } Def_CountMsg(countStates.num, "states"); DED_NewEntries((void **) &stateOwners, &countStateOwners, sizeof(mobjinfo_t *), defs.count.states.num); // Mobj info. DED_NewEntries((void **) &mobjInfo, &countMobjInfo, sizeof(*mobjInfo), defs.count.mobjs.num); for(i = 0; i < countMobjInfo.num; ++i) { ded_mobj_t* dmo = &defs.mobjs[i]; // Make sure duplicate defs overwrite the earliest. mobjinfo_t* mo = &mobjInfo[Def_GetMobjNum(dmo->id)]; gettingFor = mo; mo->doomEdNum = dmo->doomEdNum; mo->spawnHealth = dmo->spawnHealth; mo->reactionTime = dmo->reactionTime; mo->painChance = dmo->painChance; mo->speed = dmo->speed; mo->radius = dmo->radius; mo->height = dmo->height; mo->mass = dmo->mass; mo->damage = dmo->damage; mo->flags = dmo->flags[0]; mo->flags2 = dmo->flags[1]; mo->flags3 = dmo->flags[2]; for(k = 0; k < NUM_STATE_NAMES; ++k) { mo->states[k] = Def_StateForMobj(dmo->states[k]); } mo->seeSound = Def_GetSoundNum(dmo->seeSound); mo->attackSound = Def_GetSoundNum(dmo->attackSound); mo->painSound = Def_GetSoundNum(dmo->painSound); mo->deathSound = Def_GetSoundNum(dmo->deathSound); mo->activeSound = Def_GetSoundNum(dmo->activeSound); for(k = 0; k < NUM_MOBJ_MISC; ++k) mo->misc[k] = dmo->misc[k]; } Def_CountMsg(countMobjInfo.num, "things"); Def_CountMsg(defs.count.models.num, "models"); // Materials. for(i = 0; i < defs.count.materials.num; ++i) { ded_material_t* def = &defs.materials[i]; const gltexture_t* tex = NULL; // No change. float width = -1, height = -1; // No change. material_namespace_t mnamespace = MN_ANY; // No change. // Sanitize so that when updating we only change what is requested. if(def->width > 0) width = MAX_OF(1, def->width); if(def->height > 0) height = MAX_OF(1, def->height); if(def->id.mnamespace != MN_ANY) mnamespace = def->id.mnamespace; if(def->layers[0].stageCount.num > 0) { const ded_material_layer_t* l = &def->layers[0]; if(l->stages[0].type != -1) // Not unused. { if(!(tex = GL_GetGLTextureByName(l->stages[0].name, l->stages[0].type))) VERBOSE( Con_Message("Def_Read: Warning, unknown %s " "'%s' in material '%s' (layer %i " "stage %i).\n", GLTEXTURE_TYPE_STRING(l->stages[0].type), l->stages[0].name, def->id.name, 0, 0) ); } } P_MaterialCreate(def->id.name, width, height, def->flags, tex? tex->id : 0, mnamespace, def); } // Dynamic lights. Update the sprite numbers. for(i = 0; i < defs.count.lights.num; ++i) { k = Def_GetStateNum(defs.lights[i].state); if(k < 0) { // It's probably a bias light definition, then? if(!defs.lights[i].uniqueMapID[0]) { Con_Message("Def_Read: Lights: Undefined state '%s'.\n", defs.lights[i].state); } continue; } stateLights[k] = &defs.lights[i]; } Def_CountMsg(defs.count.lights.num, "lights"); // Sound effects. DED_NewEntries((void **) &sounds, &countSounds, sizeof(*sounds), defs.count.sounds.num); for(i = 0; i < countSounds.num; ++i) { ded_sound_t* snd = defs.sounds + i; // Make sure duplicate defs overwrite the earliest. sfxinfo_t* si = sounds + Def_GetSoundNum(snd->id); strcpy(si->id, snd->id); strcpy(si->lumpName, snd->lumpName); si->lumpNum = W_CheckNumForName(snd->lumpName); strcpy(si->name, snd->name); k = Def_GetSoundNum(snd->link); si->link = (k >= 0 ? sounds + k : NULL); si->linkPitch = snd->linkPitch; si->linkVolume = snd->linkVolume; si->priority = snd->priority; si->channels = snd->channels; si->flags = snd->flags; si->group = snd->group; strcpy(si->external, snd->ext.path); } Def_CountMsg(countSounds.num, "sound effects"); // Music. for(i = 0; i < defs.count.music.num; ++i) { ded_music_t* mus = defs.music + i; // Make sure duplicate defs overwrite the earliest. ded_music_t* earliest = defs.music + Def_GetMusicNum(mus->id); if(earliest == mus) continue; strcpy(earliest->lumpName, mus->lumpName); strcpy(earliest->path.path, mus->path.path); earliest->cdTrack = mus->cdTrack; } Def_CountMsg(defs.count.music.num, "songs"); // Text. DED_NewEntries((void **) &texts, &countTexts, sizeof(*texts), defs.count.text.num); for(i = 0; i < countTexts.num; ++i) Def_InitTextDef(texts + i, defs.text[i].text); // Handle duplicate strings. for(i = 0; i < countTexts.num; ++i) { if(!texts[i].text) continue; for(k = i + 1; k < countTexts.num; ++k) if(!strcmp(defs.text[i].id, defs.text[k].id) && texts[k].text) { // Update the earlier string. texts[i].text = M_Realloc(texts[i].text, strlen(texts[k].text) + 1); strcpy(texts[i].text, texts[k].text); // Free the later string, it isn't used (>NUMTEXT). M_Free(texts[k].text); texts[k].text = 0; } } Def_CountMsg(countTexts.num, "text strings"); // Particle generators. for(i = 0; i < defs.count.ptcGens.num; ++i) { ded_ptcgen_t* pg = &defs.ptcGens[i]; int st = Def_GetStateNum(pg->state); pg->typeNum = Def_GetMobjNum(pg->type); pg->type2Num = Def_GetMobjNum(pg->type2); pg->damageNum = Def_GetMobjNum(pg->damage); // Figure out embedded sound ID numbers. for(k = 0; k < pg->stageCount.num; ++k) { if(pg->stages[k].sound.name[0]) { pg->stages[k].sound.id = Def_GetSoundNum(pg->stages[k].sound.name); } if(pg->stages[k].hitSound.name[0]) { pg->stages[k].hitSound.id = Def_GetSoundNum(pg->stages[k].hitSound.name); } } if(st <= 0) continue; // Not state triggered, then... // Link the definition to the state. if(pg->flags & PGF_STATE_CHAIN) { // Add to the chain. pg->stateNext = statePtcGens[st]; statePtcGens[st] = pg; } else { // Make sure the previously built list is unlinked. while(statePtcGens[st]) { ded_ptcgen_t* temp = statePtcGens[st]->stateNext; statePtcGens[st]->stateNext = NULL; statePtcGens[st] = temp; } statePtcGens[st] = pg; pg->stateNext = NULL; } } Def_CountMsg(defs.count.ptcGens.num, "particle generators"); // Detail textures. Initialize later... Def_CountMsg(defs.count.details.num, "detail textures"); // Texture animation groups. Def_CountMsg(defs.count.groups.num, "animation groups"); // Surface decorations. Def_CountMsg(defs.count.decorations.num, "surface decorations"); // Surface reflections. Def_CountMsg(defs.count.reflections.num, "surface reflections"); // Materials. Def_CountMsg(defs.count.materials.num, "surface materials"); // Map infos. for(i = 0; i < defs.count.mapInfo.num; ++i) { ded_mapinfo_t* mi = &defs.mapInfo[i]; /** * Historically, the map info flags field was used for sky flags, * here we copy those flags to the embedded sky definition for * backward-compatibility. */ if(mi->flags & MIF_DRAW_SPHERE) mi->sky.flags |= SIF_DRAW_SPHERE; } Def_CountMsg(defs.count.mapInfo.num, "map infos"); // Other data: Def_CountMsg(defs.count.skies.num, "skies"); Def_CountMsg(defs.count.finales.num, "finales"); Def_CountMsg(defs.count.lineTypes.num, "line types"); Def_CountMsg(defs.count.sectorTypes.num, "sector types"); // Init the base model search path (prepend). Dir_ValidDir(defs.modelPath, FILENAME_T_MAXLEN); R_AddClassDataPath(DDRC_MODEL, defs.modelPath, false); // Model search path specified on the command line? if(ArgCheckWith("-modeldir", 1)) { filename_t path; strncpy(path, ArgNext(), FILENAME_T_MAXLEN); Dir_ValidDir(path, FILENAME_T_MAXLEN); // Prepend to the search list; takes precedence. R_AddClassDataPath(DDRC_MODEL, path, false); } if(ArgCheckWith("-modeldir2", 1)) { filename_t path; strncpy(path, ArgNext(), FILENAME_T_MAXLEN); Dir_ValidDir(path, FILENAME_T_MAXLEN); // Prepend to the search list; takes precedence. R_AddClassDataPath(DDRC_MODEL, ArgNext(), false); } defsInited = true; } /** * Initialize definitions that must be initialized when engine init is * complete (called from R_Init). */ void Def_PostInit(void) { int i, k; ded_ptcgen_t* gen; char name[40]; modeldef_t* modef; ded_ptcstage_t* st; // Particle generators: model setup. for(i = 0, gen = defs.ptcGens; i < defs.count.ptcGens.num; ++i, gen++) { for(k = 0, st = gen->stages; k < gen->stageCount.num; ++k, st++) { if(st->type < PTC_MODEL || st->type >= PTC_MODEL + MAX_PTC_MODELS) continue; sprintf(name, "Particle%02i", st->type - PTC_MODEL); if(!(modef = R_CheckIDModelFor(name)) || modef->sub[0].model <= 0) { st->model = -1; continue; } st->model = modef - modefs; st->frame = R_ModelFrameNumForName(modef->sub[0].model, st->frameName); if(st->endFrameName[0]) { st->endFrame = R_ModelFrameNumForName(modef->sub[0].model, st->endFrameName); } else { st->endFrame = -1; } } } // Detail textures. GL_DeleteAllTexturesForGLTextures(GLT_DETAIL); R_DestroyDetailTextures(); for(i = 0; i < defs.count.details.num; ++i) { R_CreateDetailTexture(&defs.details[i]); } // Lightmaps and flare textures. GL_DeleteAllTexturesForGLTextures(GLT_LIGHTMAP); GL_DeleteAllTexturesForGLTextures(GLT_FLARE); R_DestroyLightMaps(); R_DestroyFlareTextures(); for(i = 0; i < defs.count.lights.num; ++i) { ded_light_t* lig = &defs.lights[i]; R_CreateLightMap(&lig->up); R_CreateLightMap(&lig->down); R_CreateLightMap(&lig->sides); R_CreateFlareTexture(&lig->flare); } for(i = 0; i < defs.count.decorations.num; ++i) { ded_decor_t* decor = &defs.decorations[i]; for(k = 0; k < DED_DECOR_NUM_LIGHTS; ++k) { ded_decorlight_t* lig = &decor->lights[k]; if(!R_IsValidLightDecoration(lig)) break; R_CreateLightMap(&lig->up); R_CreateLightMap(&lig->down); R_CreateLightMap(&lig->sides); R_CreateFlareTexture(&lig->flare); } } // Surface reflections. GL_DeleteAllTexturesForGLTextures(GLT_SHINY); GL_DeleteAllTexturesForGLTextures(GLT_MASK); R_DestroyShinyTextures(); R_DestroyMaskTextures(); for(i = 0; i < defs.count.reflections.num; ++i) { ded_reflection_t* ref = &defs.reflections[i]; if(ref->shinyMap.path[0]) R_CreateShinyTexture(ref); if(ref->maskMap.path[0]) R_CreateMaskTexture(ref); } // Animation groups. R_DestroyAnimGroups(); for(i = 0; i < defs.count.groups.num; ++i) { R_InitAnimGroup(&defs.groups[i]); } } /** * Can we reach 'snew' if we start searching from 'sold'? * Take a maximum of 16 steps. */ boolean Def_SameStateSequence(state_t* snew, state_t* sold) { int it, target = snew - states, start = sold - states; int count = 0; if(!snew || !sold) return false; if(snew == sold) return true; // Trivial. for(it = sold->nextState; it >= 0 && it != start && count < 16; it = states[it].nextState, ++count) { if(it == target) return true; if(it == states[it].nextState) break; } return false; } static int Friendly(int num) { if(num < 0) num = 0; return num; } /** * Converts a DED line type to the internal format. * Bit of a nuisance really... */ void Def_CopyLineType(linetype_t* l, ded_linetype_t* def) { int i, k, a, temp; l->id = def->id; l->flags = def->flags[0]; l->flags2 = def->flags[1]; l->flags3 = def->flags[2]; l->lineClass = def->lineClass; l->actType = def->actType; l->actCount = def->actCount; l->actTime = def->actTime; l->actTag = def->actTag; for(i = 0; i < 10; ++i) { if(i == 9) l->aparm[i] = Def_GetMobjNum(def->aparm9); else l->aparm[i] = def->aparm[i]; } l->tickerStart = def->tickerStart; l->tickerEnd = def->tickerEnd; l->tickerInterval = def->tickerInterval; l->actSound = Friendly(Def_GetSoundNum(def->actSound)); l->deactSound = Friendly(Def_GetSoundNum(def->deactSound)); l->evChain = def->evChain; l->actChain = def->actChain; l->deactChain = def->deactChain; l->actLineType = def->actLineType; l->deactLineType = def->deactLineType; l->wallSection = def->wallSection; l->actMaterial = P_MaterialCheckNumForName(def->actMaterial.name, def->actMaterial.mnamespace); l->deactMaterial = P_MaterialCheckNumForName(def->deactMaterial.name, def->deactMaterial.mnamespace); l->actMsg = def->actMsg; l->deactMsg = def->deactMsg; l->materialMoveAngle = def->materialMoveAngle; l->materialMoveSpeed = def->materialMoveSpeed; memcpy(l->iparm, def->iparm, sizeof(int) * 20); memcpy(l->fparm, def->fparm, sizeof(int) * 20); LOOPi(5) l->sparm[i] = def->sparm[i]; // Some of the parameters might be strings depending on the line class. // Find the right mapping table. for(k = 0; k < 20; ++k) { temp = 0; a = xgClassLinks[l->lineClass].iparm[k].map; if(a < 0) continue; if(a & MAP_SND) { l->iparm[k] = Friendly(Def_GetSoundNum(def->iparmStr[k])); } else if(a & MAP_MATERIAL) { if(def->iparmStr[k][0]) { if(!stricmp(def->iparmStr[k], "-1")) l->iparm[k] = -1; else l->iparm[k] = P_MaterialCheckNumForName(def->iparmStr[k], MN_ANY); } } else if(a & MAP_MUS) { temp = Friendly(Def_GetMusicNum(def->iparmStr[k])); if(temp == 0) { temp = Def_EvalFlags(def->iparmStr[k]); if(temp) l->iparm[k] = temp; } else l->iparm[k] = Friendly(Def_GetMusicNum(def->iparmStr[k])); } else { temp = Def_EvalFlags(def->iparmStr[k]); if(temp) l->iparm[k] = temp; } } } /** * Converts a DED sector type to the internal format. */ void Def_CopySectorType(sectortype_t* s, ded_sectortype_t* def) { int i, k; s->id = def->id; s->flags = def->flags; s->actTag = def->actTag; LOOPi(5) { s->chain[i] = def->chain[i]; s->chainFlags[i] = def->chainFlags[i]; s->start[i] = def->start[i]; s->end[i] = def->end[i]; LOOPk(2) s->interval[i][k] = def->interval[i][k]; s->count[i] = def->count[i]; } s->ambientSound = Friendly(Def_GetSoundNum(def->ambientSound)); LOOPi(2) { s->soundInterval[i] = def->soundInterval[i]; s->materialMoveAngle[i] = def->materialMoveAngle[i]; s->materialMoveSpeed[i] = def->materialMoveSpeed[i]; } s->windAngle = def->windAngle; s->windSpeed = def->windSpeed; s->verticalWind = def->verticalWind; s->gravity = def->gravity; s->friction = def->friction; s->lightFunc = def->lightFunc; LOOPi(2) s->lightInterval[i] = def->lightInterval[i]; LOOPi(3) { s->colFunc[i] = def->colFunc[i]; LOOPk(2) s->colInterval[i][k] = def->colInterval[i][k]; } s->floorFunc = def->floorFunc; s->floorMul = def->floorMul; s->floorOff = def->floorOff; LOOPi(2) s->floorInterval[i] = def->floorInterval[i]; s->ceilFunc = def->ceilFunc; s->ceilMul = def->ceilMul; s->ceilOff = def->ceilOff; LOOPi(2) s->ceilInterval[i] = def->ceilInterval[i]; } /** * @return @c true, if the definition was found. */ int Def_Get(int type, const char* id, void* out) { int i; ded_mapinfo_t* map; ddmapinfo_t* mout; finalescript_t* fin; switch(type) { case DD_DEF_MOBJ: return Def_GetMobjNum(id); case DD_DEF_MOBJ_BY_NAME: return Def_GetMobjNumForName(id); case DD_DEF_STATE: return Def_GetStateNum(id); case DD_DEF_SPRITE: return Def_GetSpriteNum(id); case DD_DEF_SOUND: return Def_GetSoundNum(id); case DD_DEF_SOUND_BY_NAME: return Def_GetSoundNumForName(id); case DD_DEF_SOUND_LUMPNAME: i = *((long*) id); if(i < 0 || i >= countSounds.num) return false; strcpy(out, sounds[i].lumpName); break; case DD_DEF_MUSIC: return Def_GetMusicNum(id); case DD_DEF_MAP_INFO: map = Def_GetMapInfo(id); if(!map) return false; mout = (ddmapinfo_t *) out; mout->name = map->name; mout->author = map->author; mout->music = Def_GetMusicNum(map->music); mout->flags = map->flags; mout->ambient = map->ambient; mout->gravity = map->gravity; mout->parTime = map->parTime; break; case DD_DEF_TEXT: if(id && id[0]) { int i; // Read backwards to allow patching. for(i = defs.count.text.num - 1; i >= 0; i--) if(!stricmp(defs.text[i].id, id)) { // \fixme: should be returning an immutable ptr. if(out) *(char **) out = defs.text[i].text; return i; } } return -1; case DD_DEF_VALUE: // Read backwards to allow patching. for(i = defs.count.values.num - 1; i >= 0; i--) if(!stricmp(defs.values[i].id, id)) { if(out) *(char **) out = defs.values[i].text; return true; } return false; case DD_DEF_FINALE: // Find InFine script by ID. for(i = defs.count.finales.num - 1; i >= 0; i--) if(!stricmp(defs.finales[i].id, id)) { // This has a matching ID. Return a pointer to the script. *(void **) out = defs.finales[i].script; return true; } return false; case DD_DEF_FINALE_BEFORE: fin = (finalescript_t *) out; for(i = defs.count.finales.num - 1; i >= 0; i--) if(!stricmp(defs.finales[i].before, id)) { fin->before = defs.finales[i].before; fin->after = defs.finales[i].after; fin->script = defs.finales[i].script; return true; } return false; case DD_DEF_FINALE_AFTER: fin = (finalescript_t *) out; for(i = defs.count.finales.num - 1; i >= 0; i--) if(!stricmp(defs.finales[i].after, id)) { fin->before = defs.finales[i].before; fin->after = defs.finales[i].after; fin->script = defs.finales[i].script; return true; } return false; case DD_DEF_LINE_TYPE: { int typeId = strtol(id, (char **)NULL, 10); for(i = defs.count.lineTypes.num - 1; i >= 0; i--) if(defs.lineTypes[i].id == typeId) { if(out) Def_CopyLineType(out, &defs.lineTypes[i]); return true; } } return false; case DD_DEF_SECTOR_TYPE: { int typeId = strtol(id, (char **)NULL, 10); for(i = defs.count.sectorTypes.num - 1; i >= 0; i--) if(defs.sectorTypes[i].id == typeId) { if(out) Def_CopySectorType(out, &defs.sectorTypes[i]); return true; } } return false; default: return false; } return true; } /** * This is supposed to be the main interface for outside parties to * modify definitions (unless they want to do it manually with dedfile.h). */ int Def_Set(int type, int index, int value, const void* ptr) { int i; ded_music_t* musdef = 0; switch(type) { case DD_DEF_TEXT: if(index < 0 || index >= defs.count.text.num) Con_Error("Def_Set: Text index %i is invalid.\n", index); defs.text[index].text = M_Realloc(defs.text[index].text, strlen((char*)ptr) + 1); strcpy(defs.text[index].text, ptr); break; case DD_DEF_STATE: { ded_state_t* stateDef; if(index < 0 || index >= defs.count.states.num) Con_Error("Def_Set: State index %i is invalid.\n", index); stateDef = &defs.states[index]; switch(value) { case DD_SPRITE: { int sprite = *(int*) ptr; if(sprite < 0 || sprite >= defs.count.sprites.num) { Con_Message("Def_Set: Warning, invalid sprite index %i.\n", sprite); break; } strcpy((char*) stateDef->sprite.id, defs.sprites[value].id); break; } case DD_FRAME: { int frame = *(int*) ptr; if(frame & FF_FULLBRIGHT) stateDef->flags |= STF_FULLBRIGHT; else stateDef->flags &= ~STF_FULLBRIGHT; stateDef->frame = frame & ~FF_FULLBRIGHT; break; } default: break; } break; } case DD_DEF_SOUND: if(index < 0 || index >= countSounds.num) Con_Error("Def_Set: Sound index %i is invalid.\n", index); switch(value) { case DD_LUMP: S_StopSound(index, 0); strcpy(sounds[index].lumpName, ptr); sounds[index].lumpNum = W_CheckNumForName(sounds[index].lumpName); break; default: break; } break; case DD_DEF_MUSIC: if(index == DD_NEW) { // We should create a new music definition. i = DED_AddMusic(&defs, ""); // No ID is known at this stage. musdef = defs.music + i; } else if(index >= 0 && index < defs.count.music.num) { musdef = defs.music + index; } else Con_Error("Def_Set: Music index %i is invalid.\n", index); // Which key to set? switch(value) { case DD_ID: if(ptr) strcpy(musdef->id, ptr); break; case DD_LUMP: if(ptr) strcpy(musdef->lumpName, ptr); break; case DD_CD_TRACK: musdef->cdTrack = *(int *) ptr; break; default: break; } // If the def was just created, return its index. if(index == DD_NEW) return musdef - defs.music; break; default: return false; } return true; } /** * Prints a list of all the registered mobjs to the console. * \fixme Does this belong here? */ D_CMD(ListMobjs) { int i; Con_Printf("Registered Mobjs (ID | Name):\n"); for(i = 0; i < defs.count.mobjs.num; ++i) { if(defs.mobjs[i].name[0]) Con_Printf(" %s | %s\n", defs.mobjs[i].id, defs.mobjs[i].name); else Con_Printf(" %s | (Unnamed)\n", defs.mobjs[i].id); } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_model.c0000644000175000017500000011361311357170242022523 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_model.c: 3D Model Resources * * MD2/DMD2 loading and setup. * My variable naming convention is a bit incoherent. */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #include #include #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_play.h" #include "de_misc.h" #include "def_main.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { float pos[3]; } vector_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float rModelAspectMod = 1 / 1.2f; //.833334f; // The dummy is used for model zero. model_t dummy = { true, "Dummy-Dummy" }; model_t* modellist[MAX_MODELS] = { &dummy }; byte useModels = true; modeldef_t* modefs = NULL; int numModelDefs; float avertexnormals[NUMVERTEXNORMALS][3] = { #include "tab_anorms.h" }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int maxModelDefs; static modeldef_t** stateModefs; // CODE -------------------------------------------------------------------- /** * Packed: pppppppy yyyyyyyy. Yaw is on the XY plane. */ static void UnpackVector(unsigned short packed, float vec[3]) { float yaw = (packed & 511) / 512.0f * 2 * PI; float pitch = ((packed >> 9) / 127.0f - 0.5f) * PI; float cosp = (float) cos(pitch); vec[VX] = (float) cos(yaw) * cosp; vec[VY] = (float) sin(yaw) * cosp; vec[VZ] = (float) sin(pitch); } /** * Returns an index if the specified model has already been loaded. */ static int R_FindModelFor(const char* filename) { int i; for(i = 0; i < MAX_MODELS; ++i) if(modellist[i] && !stricmp(modellist[i]->fileName, filename)) return i; return -1; } /** * Allocates a new model. Returns the index. */ static int R_NewModelFor(void /*const char *filename*/) { int i; // Take the first empty spot. for(i = 0; i < MAX_MODELS; ++i) if(!modellist[i]) { modellist[i] = M_Calloc(sizeof(model_t)); return i; } // Dang, we're out of models. return -1; } /** * Calculate vertex normals. Only with -renorm. */ #if 0 // unused atm. static void R_VertexNormals(model_t *mdl) { int tris = mdl->lodInfo[0].numTriangles; int verts = mdl->info.numVertices; int i, k, j, n, cnt; vector_t *normals, norm; model_vertex_t *list; dmd_triangle_t *tri; // Renormalizing? if(!ArgCheck("-renorm")) return; normals = Z_Malloc(sizeof(vector_t) * tris, PU_STATIC, 0); // Calculate the normal for each vertex. for(i = 0; i < mdl->info.numFrames; ++i) { list = mdl->frames[i].vertices; for(k = 0; k < tris; ++k) { tri = mdl->lods[0].triangles + k; // First calculate surface normals, combine them to vertex ones. M_PointCrossProduct(list[tri->vertexIndices[0]].vertex, list[tri->vertexIndices[2]].vertex, list[tri->vertexIndices[1]].vertex, normals[k].pos); M_Normalize(normals[k].pos); } for(k = 0; k < verts; ++k) { memset(&norm, 0, sizeof(norm)); for(j = 0, cnt = 0; j < tris; ++j) { tri = mdl->lods[0].triangles + j; for(n = 0; n < 3; ++n) if(tri->vertexIndices[n] == k) { cnt++; for(n = 0; n < 3; ++n) norm.pos[n] += normals[j].pos[n]; break; } } if(!cnt) continue; // Impossible... // Calculate the average. for(n = 0; n < 3; ++n) norm.pos[n] /= cnt; // Normalize it. M_Normalize(norm.pos); memcpy(list[k].normal, norm.pos, sizeof(norm.pos)); } } Z_Free(normals); } #endif static void *AllocAndLoad(DFILE *file, int offset, int len) { void *ptr = M_Malloc(len); F_Seek(file, offset, SEEK_SET); F_Read(ptr, len, file); return ptr; } static void R_MissingModel(const char* fn) { //if(verbose) Con_Printf("Warning: Failed to locate model \"%s\".\n", fn); } static void R_LoadModelMD2(DFILE *file, model_t *mdl) { md2_header_t oldhd; dmd_header_t *hd = &mdl->header; dmd_info_t *inf = &mdl->info; model_frame_t *frame; byte *frames; int i, k, c; const int axis[3] = { 0, 2, 1 }; // Read the header. F_Read(&oldhd, sizeof(oldhd), file); // Convert it to DMD. hd->magic = MD2_MAGIC; hd->version = 8; hd->flags = 0; mdl->vertexUsage = NULL; inf->skinWidth = LONG(oldhd.skinWidth); inf->skinHeight = LONG(oldhd.skinHeight); inf->frameSize = LONG(oldhd.frameSize); inf->numLODs = 1; inf->numSkins = LONG(oldhd.numSkins); inf->numTexCoords = LONG(oldhd.numTexCoords); inf->numVertices = LONG(oldhd.numVertices); inf->numFrames = LONG(oldhd.numFrames); inf->offsetSkins = LONG(oldhd.offsetSkins); inf->offsetTexCoords = LONG(oldhd.offsetTexCoords); inf->offsetFrames = LONG(oldhd.offsetFrames); inf->offsetLODs = LONG(oldhd.offsetEnd); // Doesn't exist. mdl->lodInfo[0].numTriangles = LONG(oldhd.numTriangles); mdl->lodInfo[0].numGlCommands = LONG(oldhd.numGlCommands); mdl->lodInfo[0].offsetTriangles = LONG(oldhd.offsetTriangles); mdl->lodInfo[0].offsetGlCommands = LONG(oldhd.offsetGlCommands); inf->offsetEnd = LONG(oldhd.offsetEnd); // The frames need to be unpacked. frames = AllocAndLoad(file, inf->offsetFrames, inf->frameSize * inf->numFrames); mdl->frames = M_Malloc(sizeof(model_frame_t) * inf->numFrames); for(i = 0, frame = mdl->frames; i < inf->numFrames; ++i, frame++) { md2_packedFrame_t *pfr = (md2_packedFrame_t *) (frames + inf->frameSize * i); md2_triangleVertex_t *pVtx; memcpy(frame->name, pfr->name, sizeof(pfr->name)); frame->vertices = M_Malloc(sizeof(model_vertex_t) * inf->numVertices); frame->normals = M_Malloc(sizeof(model_vertex_t) * inf->numVertices); // Translate each vertex. for(k = 0, pVtx = pfr->vertices; k < inf->numVertices; ++k, pVtx++) { memcpy(frame->normals[k].xyz, avertexnormals[pVtx->lightNormalIndex], sizeof(float) * 3); for(c = 0; c < 3; ++c) { frame->vertices[k].xyz[axis[c]] = pVtx->vertex[c] * FLOAT(pfr->scale[c]) + FLOAT(pfr->translate[c]); } // Aspect undoing. frame->vertices[k].xyz[VY] *= rModelAspectMod; for(c = 0; c < 3; ++c) { if(!k || frame->vertices[k].xyz[c] < frame->min[c]) frame->min[c] = frame->vertices[k].xyz[c]; if(!k || frame->vertices[k].xyz[c] > frame->max[c]) frame->max[c] = frame->vertices[k].xyz[c]; } } } M_Free(frames); mdl->lods[0].glCommands = AllocAndLoad(file, mdl->lodInfo[0].offsetGlCommands, sizeof(int) * mdl->lodInfo[0].numGlCommands); // Load skins. mdl->skins = M_Calloc(sizeof(dmd_skin_t) * inf->numSkins); F_Seek(file, inf->offsetSkins, SEEK_SET); for(i = 0; i < inf->numSkins; ++i) F_Read(mdl->skins[i].name, 64, file); } static void R_LoadModelDMD(DFILE *file, model_t *mo) { dmd_chunk_t chunk; char *temp; dmd_info_t *inf = &mo->info; model_frame_t *frame; int i, k, c; dmd_triangle_t *triangles[MAX_LODS]; const int axis[3] = { 0, 2, 1 }; // Read the chunks. F_Read(&chunk, sizeof(chunk), file); while(LONG(chunk.type) != DMC_END) { switch (LONG(chunk.type)) { case DMC_INFO: // Standard DMD information chunk. F_Read(inf, LONG(chunk.length), file); inf->skinWidth = LONG(inf->skinWidth); inf->skinHeight = LONG(inf->skinHeight); inf->frameSize = LONG(inf->frameSize); inf->numSkins = LONG(inf->numSkins); inf->numVertices = LONG(inf->numVertices); inf->numTexCoords = LONG(inf->numTexCoords); inf->numFrames = LONG(inf->numFrames); inf->numLODs = LONG(inf->numLODs); inf->offsetSkins = LONG(inf->offsetSkins); inf->offsetTexCoords = LONG(inf->offsetTexCoords); inf->offsetFrames = LONG(inf->offsetFrames); inf->offsetLODs = LONG(inf->offsetLODs); inf->offsetEnd = LONG(inf->offsetEnd); break; default: // Just skip all unknown chunks. temp = M_Malloc(LONG(chunk.length)); F_Read(temp, LONG(chunk.length), file); free(temp); } // Read the next chunk header. F_Read(&chunk, sizeof(chunk), file); } // Allocate and load in the data. mo->skins = M_Calloc(sizeof(dmd_skin_t) * inf->numSkins); F_Seek(file, inf->offsetSkins, SEEK_SET); for(i = 0; i < inf->numSkins; ++i) F_Read(mo->skins[i].name, 64, file); temp = AllocAndLoad(file, inf->offsetFrames, inf->frameSize * inf->numFrames); mo->frames = M_Malloc(sizeof(model_frame_t) * inf->numFrames); for(i = 0, frame = mo->frames; i < inf->numFrames; ++i, frame++) { dmd_packedFrame_t *pfr = (dmd_packedFrame_t *) (temp + inf->frameSize * i); dmd_packedVertex_t *pVtx; memcpy(frame->name, pfr->name, sizeof(pfr->name)); frame->vertices = M_Malloc(sizeof(model_vertex_t) * inf->numVertices); frame->normals = M_Malloc(sizeof(model_vertex_t) * inf->numVertices); // Translate each vertex. for(k = 0, pVtx = pfr->vertices; k < inf->numVertices; ++k, pVtx++) { UnpackVector(USHORT(pVtx->normal), frame->normals[k].xyz); for(c = 0; c < 3; ++c) { frame->vertices[k].xyz[axis[c]] = pVtx->vertex[c] * FLOAT(pfr->scale[c]) + FLOAT(pfr->translate[c]); } // Aspect undo. frame->vertices[k].xyz[1] *= rModelAspectMod; for(c = 0; c < 3; ++c) { if(!k || frame->vertices[k].xyz[c] < frame->min[c]) frame->min[c] = frame->vertices[k].xyz[c]; if(!k || frame->vertices[k].xyz[c] > frame->max[c]) frame->max[c] = frame->vertices[k].xyz[c]; } } } M_Free(temp); F_Seek(file, inf->offsetLODs, SEEK_SET); F_Read(mo->lodInfo, sizeof(dmd_levelOfDetail_t) * inf->numLODs, file); for(i = 0; i < inf->numLODs; ++i) { mo->lodInfo[i].numTriangles = LONG(mo->lodInfo[i].numTriangles); mo->lodInfo[i].numGlCommands = LONG(mo->lodInfo[i].numGlCommands); mo->lodInfo[i].offsetTriangles = LONG(mo->lodInfo[i].offsetTriangles); mo->lodInfo[i].offsetGlCommands = LONG(mo->lodInfo[i].offsetGlCommands); triangles[i] = AllocAndLoad(file, mo->lodInfo[i].offsetTriangles, sizeof(dmd_triangle_t) * mo->lodInfo[i].numTriangles); mo->lods[i].glCommands = AllocAndLoad(file, mo->lodInfo[i].offsetGlCommands, sizeof(int) * mo->lodInfo[i].numGlCommands); } // Determine vertex usage at each LOD level. // This code assumes there will never be more than 8 LOD levels. mo->vertexUsage = M_Calloc(inf->numVertices); for(i = 0; i < inf->numLODs; ++i) for(k = 0; k < mo->lodInfo[i].numTriangles; ++k) for(c = 0; c < 3; ++c) mo->vertexUsage[SHORT(triangles[i][k].vertexIndices[c])] |= 1 << i; // We don't need the triangles any more. for(i = 0; i < inf->numLODs; ++i) M_Free(triangles[i]); } static void R_RegisterModelSkin(model_t* mdl, int index) { mdl->skins[index].id = R_RegisterSkin(NULL, mdl->skins[index].name, mdl->fileName, false, FILENAME_T_MAXLEN); if(!mdl->skins[index].id) { // Not found! VERBOSE(Con_Printf(" %s (#%i) not found.\n", mdl->skins[index].name, index)); } } /** * Finds the existing model or loads in a new one. */ static int R_LoadModel(char* origfn) { int i, index; model_t* mdl; DFILE* file = NULL; filename_t filename; if(!origfn || !origfn[0]) return 0; // No model specified. if(!R_FindResource2(RT_MODEL, DDRC_MODEL, filename, origfn, NULL, FILENAME_T_MAXLEN)) { R_MissingModel(origfn); return 0; } // Has this been already loaded? if((index = R_FindModelFor(filename)) < 0) { // Not loaded yet, try to open the file. if((file = F_Open(filename, "rb")) == NULL) { R_MissingModel(filename); return 0; } // Allocate a new model_t. if((index = R_NewModelFor(/*filename*/)) < 0) { F_Close(file); return 0; } } mdl = modellist[index]; if(mdl->loaded) { if(file) F_Close(file); return index; // Already loaded. } // Now we can load in the data. F_Read(&mdl->header, sizeof(mdl->header), file); if(LONG(mdl->header.magic) == MD2_MAGIC) { // Load as MD2. F_Rewind(file); R_LoadModelMD2(file, mdl); } else if(LONG(mdl->header.magic) == DMD_MAGIC) { // Load as DMD. R_LoadModelDMD(file, mdl); } else { // Bad magic! // Cancel the loading. M_Free(mdl); modellist[index] = 0; F_Close(file); return 0; } // We're done. mdl->loaded = true; mdl->allowTexComp = true; F_Close(file); strncpy(mdl->fileName, filename, FILENAME_T_MAXLEN); // Determine the actual (full) paths. for(i = 0; i < mdl->info.numSkins; ++i) { R_RegisterModelSkin(mdl, i); } return index; } int R_ModelFrameNumForName(int modelnum, char *fname) { int i; model_t *mdl; if(!modelnum) return 0; mdl = modellist[modelnum]; for(i = 0; i < mdl->info.numFrames; ++i) { if(!stricmp(mdl->frames[i].name, fname)) return i; } return 0; } /** * Returns the appropriate modeldef for the given state. */ static modeldef_t *GetStateModel(state_t *st, int select) { modeldef_t *modef, *iter; int mosel; if(!st || !stateModefs[st - states]) return 0; modef = stateModefs[st - states]; mosel = select & DDMOBJ_SELECTOR_MASK; if(select) { boolean found; // Choose the correct selector, or selector zero if the given // one not available. found = false; for(iter = modef; iter && !found; iter = iter->selectNext) if(iter->select == mosel) { modef = iter; found = true; } } return modef; } modeldef_t *R_CheckIDModelFor(const char *id) { int i; if(!id[0]) return NULL; for(i = 0; i < numModelDefs; ++i) if(!strcmp(modefs[i].id, id)) return modefs + i; return NULL; } /** * Is there a model for this mobj? The decision is made based on the * state and tics of the mobj. Returns the modeldefs that are in effect * at the moment (interlinks checked appropriately). */ float R_CheckModelFor(mobj_t *mo, modeldef_t **modef, modeldef_t **nextmodef) { float interp = -1; state_t *st = mo->state; modeldef_t *mdit; boolean worldTime = false; // By default there are no models. *nextmodef = NULL; *modef = GetStateModel(st, mo->selector); if(!*modef) return -1; // No model available. // World time animation? if((*modef)->flags & MFF_WORLD_TIME_ANIM) { float duration = (*modef)->interRange[0]; float offset = (*modef)->interRange[1]; // Validate/modify the values. if(duration == 0) duration = 1; if(offset == -1) { offset = M_CycleIntoRange(MOBJ_TO_ID(mo), duration); } interp = M_CycleIntoRange(ddMapTime / duration + offset, 1); worldTime = true; } else { // Calculate the currently applicable intermark. interp = 1.0f - (mo->tics - frameTimePos) / (float) st->tics; } /* #if _DEBUG if(mo->dPlayer) Con_Printf("itp:%f mot:%i stt:%i\n", interp, mo->tics, st->tics); #endif */ // First find the modef for the interpoint. Intermark is 'stronger' // than interrange. // Scan interlinks. while((*modef)->interNext && (*modef)->interNext->interMark <= interp) *modef = (*modef)->interNext; if(!worldTime) { // Scale to the modeldef's interpolation range. interp = (*modef)->interRange[0] + interp * ((*modef)->interRange[1] - (*modef)->interRange[0]); } // What would be the next model? Check interlinks first. if((*modef)->interNext) { *nextmodef = (*modef)->interNext; } else if(worldTime) { *nextmodef = GetStateModel(st, mo->selector); } else if(st->nextState > 0) // Check next state. { int max; boolean foundNext; state_t *it; // Find the appropriate state based on interrange. it = states + st->nextState; foundNext = false; if((*modef)->interRange[1] < 1) { boolean stopScan; // Current modef doesn't interpolate to the end, find the // proper destination modef (it isn't just the next one). // Scan the states that follow (and interlinks of each). stopScan = false; max = 20; // Let's not be here forever... while(!stopScan) { if(!((!stateModefs[it - states] || GetStateModel(it, mo->selector)->interRange[0] > 0) && it->nextState > 0)) { stopScan = true; } else { // Scan interlinks, then go to the next state. if((mdit = GetStateModel(it, mo->selector)) && mdit->interNext) { boolean isDone = false; while(!isDone) { mdit = mdit->interNext; if(mdit) { if(mdit->interRange[0] <= 0) // A new beginning? { *nextmodef = mdit; foundNext = true; } } if(!mdit || foundNext) { isDone = true; } } } if(foundNext) { stopScan = true; } else { it = states + it->nextState; } } if(max-- <= 0) stopScan = true; } // \fixme What about max == -1? What should 'it' be then? } if(!foundNext) *nextmodef = GetStateModel(it, mo->selector); } // Is this group disabled? if(useModels >= 2 && (*modef)->group & useModels) { *modef = *nextmodef = NULL; return -1; } return interp; } static model_frame_t* R_GetModelFrame(int model, int frame) { return modellist[model]->frames + frame; } static void R_GetModelBounds(int model, int frame, float min[3], float max[3]) { model_frame_t* mframe = R_GetModelFrame(model, frame); if(!mframe) Con_Error("R_GetModelBounds: bad model/frame.\n"); memcpy(min, mframe->min, sizeof(float)*3); memcpy(max, mframe->max, sizeof(float)*3); } /** * Height range, really ("horizontal range" comes to mind...). */ static float R_GetModelHRange(int model, int frame, float *top, float *bottom) { float min[3], max[3]; R_GetModelBounds(model, frame, min, max); *top = max[VY]; *bottom = min[VY]; return max[VY] - min[VY]; } /** * Scales the given model so that it'll be 'destHeight' units tall. * The measurements are based on submodel zero. The scaling is done * uniformly! */ static void R_ScaleModel(modeldef_t *mf, float destHeight, float offset) { submodeldef_t *smf = &mf->sub[0]; int i; float top, bottom, height; float scale; if(!smf->model) return; // No model to scale! // Find the top and bottom heights. height = R_GetModelHRange(smf->model, smf->frame, &top, &bottom); if(!height) height = 1; scale = destHeight / height; for(i = 0; i < 3; ++i) mf->scale[i] = scale; mf->offset[VY] = -bottom * scale + offset; } static void R_ScaleModelToSprite(modeldef_t* mf, int sprite, int frame) { int off; spritedef_t* spr = &sprites[sprite]; material_snapshot_t ms; if(!spr->numFrames || spr->spriteFrames == NULL) return; Material_Prepare(&ms, spr->spriteFrames[frame].mats[0], true, NULL); off = spriteTextures[ms.units[MTU_PRIMARY].texInst->tex->ofTypeID]->offY - ms.height; if(off < 0) off = 0; R_ScaleModel(mf, ms.height, off); } float R_GetModelVisualRadius(modeldef_t* mf) { int i; float maxRadius = 0; if(!mf->sub[0].model) return 0; // Use the first frame bounds. for(i = 0; i < MAX_FRAME_MODELS; ++i) { float min[3], max[3], radius; if(!mf->sub[i].model) break; R_GetModelBounds(mf->sub[i].model, mf->sub[i].frame, min, max); // Half the distance from bottom left to top right. radius = (mf->scale[VX] * (max[VX] - min[VX]) + mf->scale[VZ] * (max[VZ] - min[VZ])) / 3.5f; if(radius > maxRadius) maxRadius = radius; } return maxRadius; } /** * Allocate room for a new skin file name. This allows using more than * the maximum number of skins. */ static short R_NewModelSkin(model_t *mdl, const char *fileName) { int added = mdl->info.numSkins, i; mdl->skins = M_Realloc(mdl->skins, sizeof(dmd_skin_t) * ++mdl->info.numSkins); memset(mdl->skins + added, 0, sizeof(dmd_skin_t)); strncpy(mdl->skins[added].name, fileName, 64); R_RegisterModelSkin(mdl, added); // Did we get a dupe? for(i = 0; i < mdl->info.numSkins - 1; ++i) { if(mdl->skins[i].id == mdl->skins[added].id) { // This is the same skin file. // We did a lot of unnecessary work... mdl->info.numSkins--; mdl->skins = M_Realloc(mdl->skins, sizeof(dmd_skin_t) * mdl->info.numSkins); return i; } } return added; } /** * Create a new modeldef or find an existing one. This is for ID'd models. */ static modeldef_t *R_GetIDModelDef(const char *id) { modeldef_t *md; // ID defined? if(!id[0]) return NULL; // First try to find an existing modef. if((md = R_CheckIDModelFor(id)) != NULL) return md; // Get a new entry. md = modefs + numModelDefs++; memset(md, 0, sizeof(*md)); strncpy(md->id, id, MODELDEF_ID_MAXLEN); return md; } /** * Create a new modeldef or find an existing one. There can be only one * model definition associated with a state/intermark pair. */ static modeldef_t *R_GetModelDef(int state, float interMark, int select) { int i; modeldef_t *md; if(state < 0 || state >= countStates.num) return NULL; // Not a valid state. // First try to find an existing modef. for(i = 0; i < numModelDefs; ++i) if(modefs[i].state == &states[state] && modefs[i].interMark == interMark && modefs[i].select == select) { // Models are loaded in reverse order; this one already has // a model. return NULL; } // This is impossible, but checking won't hurt... if(numModelDefs >= maxModelDefs) return NULL; md = modefs + numModelDefs++; memset(md, 0, sizeof(*md)); // Set initial data. md->state = &states[state]; md->interMark = interMark; md->select = select; return md; } /** * Creates a modeldef based on the given DED info. * A pretty straightforward operation. No interlinks are set yet. * Autoscaling is done and the scale factors set appropriately. * After this has been called for all available Model DEDs, each * State that has a model will have a pointer to the one with the * smallest intermark (start of a chain). */ static void setupModel(ded_model_t *def) { modeldef_t *modef; int modelScopeFlags = def->flags | defs.modelFlags; ded_submodel_t *subdef; submodeldef_t *sub; int i, k, statenum = Def_GetStateNum(def->state); float min[3], max[3]; // Is this an ID'd model? if((modef = R_GetIDModelDef(def->id)) == NULL) { // No, normal State-model. if(statenum < 0) { Con_Message("R_SetupModel: Undefined state '%s'.\n", def->state); return; } modef = R_GetModelDef(statenum + def->off, def->interMark, def->selector); if(!modef) return; // Can't get a modef, quit! } // Init modef info (state & intermark already set). modef->def = def; modef->group = def->group; modef->flags = modelScopeFlags; for(i = 0; i < 3; ++i) { modef->offset[i] = def->offset[i]; modef->scale[i] = def->scale[i]; } modef->offset[VY] += defs.modelOffset; // Common Y axis offset. modef->scale[VY] *= defs.modelScale; // Common Y axis scaling. modef->resize = def->resize; modef->skinTics = def->skinTics; for(i = 0; i < 2; ++i) { modef->interRange[i] = def->interRange[i]; } if(modef->skinTics < 1) modef->skinTics = 1; // Submodels. for(i = 0, subdef = def->sub, sub = modef->sub; i < MAX_FRAME_MODELS; ++i, subdef++, sub++) { sub->model = R_LoadModel(subdef->filename.path); if(!sub->model) continue; sub->frame = R_ModelFrameNumForName(sub->model, subdef->frame); sub->frameRange = subdef->frameRange; // Frame range must always be greater than zero. if(sub->frameRange < 1) sub->frameRange = 1; // Submodel-specific flags cancel out model-scope flags! sub->flags = modelScopeFlags ^ subdef->flags; if(subdef->skinFilename.path[0]) { // A specific file name has been given for the skin. sub->skin = R_NewModelSkin(modellist[sub->model], subdef->skinFilename.path); } else { sub->skin = subdef->skin; } sub->skinRange = subdef->skinRange; // Skin range must always be greater than zero. if(sub->skinRange < 1) sub->skinRange = 1; // Offset within the model. for(k = 0; k < 3; ++k) sub->offset[k] = subdef->offset[k]; sub->alpha = (byte) (subdef->alpha * 255); sub->shinySkin = R_RegisterSkin(subdef->filename.path, subdef->shinySkin, NULL, true, DED_PATH_LEN); // Should we allow texture compression with this model? if(sub->flags & MFF_NO_TEXCOMP) { // All skins of this model will no longer use compression. modellist[sub->model]->allowTexComp = false; } } // Do scaling, if necessary. if(modef->resize) { R_ScaleModel(modef, modef->resize, modef->offset[VY]); } else if(modef->state && modef->sub[0].flags & MFF_AUTOSCALE) { int sprNum = Def_GetSpriteNum(def->sprite.id); int sprFrame = def->spriteFrame; if(sprNum < 0) { // No sprite ID given. sprNum = modef->state->sprite; sprFrame = modef->state->frame; } R_ScaleModelToSprite(modef, sprNum, sprFrame); } if(modef->state) { int stateNum = modef->state - states; // Associate this modeldef with its state. if(!stateModefs[stateNum]) { // No modef; use this. stateModefs[stateNum] = modef; } else { // Must check intermark; smallest wins! modeldef_t *other = stateModefs[stateNum]; if((modef->interMark <= other->interMark && // Should never be == modef->select == other->select) || modef->select < other->select) // Smallest selector? stateModefs[stateNum] = modef; } } // Calculate the particle offset for each submodel. for(i = 0, sub = modef->sub; i < MAX_FRAME_MODELS; ++i, sub++) { if(sub->model) { R_GetModelBounds(sub->model, sub->frame, min, max); // Apply the various scalings and offsets. for(k = 0; k < 3; ++k) { modef->ptcOffset[i][k] = ((max[k] + min[k]) / 2 + sub->offset[k]) * modef->scale[k] + modef->offset[k]; } } else { memset(modef->ptcOffset[i], 0, sizeof(modef->ptcOffset[i])); } } // Calculate visual radius for shadows. if(def->shadowRadius) { modef->visualRadius = def->shadowRadius; } else { modef->visualRadius = R_GetModelVisualRadius(modef); } } /** * States must be initialized before this. */ void R_InitModels(void) { int i, k, minsel; float minmark; modeldef_t* me, *other, *closest; uint usedTime; // Dedicated servers do nothing with models. if(isDedicated || ArgCheck("-nomd2")) return; Con_Message("R_InitModels: Initializing MD2 models.\n"); usedTime = Sys_GetRealTime(); if(modefs) M_Free(modefs); // There can't be more modeldefs than there are DED Models. // There can be fewer, though. maxModelDefs = defs.count.models.num; modefs = M_Malloc(sizeof(modeldef_t) * maxModelDefs); numModelDefs = 0; // Clear the modef pointers of all States. stateModefs = M_Realloc(stateModefs, countStates.num * sizeof(*stateModefs)); memset(stateModefs, 0, countStates.num * sizeof(*stateModefs)); // Read in the model files and their data. // Use the latest definition available for each sprite ID. for(i = defs.count.models.num - 1; i >= 0; --i) { //Con_Progress(1, PBARF_DONTSHOW); setupModel(defs.models + i); } // Create interlinks. Note that the order in which the defs were loaded // is important. We want to allow "patch" definitions, right? // For each modeldef we will find the "next" def. for(i = numModelDefs - 1, me = modefs + i; i >= 0; --i, --me) { minmark = 2; // max = 1, so this is "out of bounds". closest = NULL; for(k = numModelDefs - 1, other = modefs + k; k >= 0; --k, --other) { // Same state and a bigger order are the requirements. if(other->state == me->state && other->def > me->def && // Defined after me. other->interMark > me->interMark && other->interMark < minmark) { minmark = other->interMark; closest = other; } } me->interNext = closest; } // Create selectlinks. for(i = numModelDefs - 1, me = modefs + i; i >= 0; --i, --me) { minsel = DDMAXINT; closest = NULL; // Start scanning from the next definition. for(k = numModelDefs - 1, other = modefs + k; k >= 0; --k, --other) { // Same state and a bigger order are the requirements. if(other->state == me->state && other->def > me->def && // Defined after me. other->select > me->select && other->select < minsel && other->interMark >= me->interMark) { minsel = other->select; closest = other; } } me->selectNext = closest; /*#if _DEBUG if(closest) Con_Message("%s -> %s\n", defs.states[me->state - states].id, defs.states[closest->state - states].id); #endif*/ } Con_Message("R_InitModels: Done in %.2f seconds.\n", (Sys_GetRealTime() - usedTime) / 1000.0f); } /** * Frees all memory allocated for models. * \fixme Why only centralized memory deallocation? Bad design... */ void R_ShutdownModels(void) { int i, k; model_t *m; if(modefs) M_Free(modefs); modefs = NULL; if(stateModefs) M_Free(stateModefs); stateModefs = NULL; for(i = 1; i < MAX_MODELS; ++i) { if(!(m = modellist[i])) continue; M_Free(m->skins); //M_Free(modellist[i]->texCoords); for(k = 0; k < m->info.numFrames; ++k) { M_Free(m->frames[k].vertices); M_Free(m->frames[k].normals); } M_Free(m->frames); for(k = 0; k < m->info.numLODs; ++k) { //M_Free(modellist[i]->lods[k].triangles); M_Free(m->lods[k].glCommands); } M_Free(m->vertexUsage); M_Free(m); modellist[i] = NULL; } } void R_SetModelFrame(modeldef_t* modef, int frame) { int k; model_t* mdl; for(k = 0; k < DED_MAX_SUB_MODELS; ++k) { if(!modef->sub[k].model) continue; mdl = modellist[modef->sub[k].model]; // Modify the modeldef itself: set the current frame. modef->sub[k].frame = frame % mdl->info.numFrames; } } void R_PrecacheModelSkins(modeldef_t* modef) { int k, sub; model_t* mdl; if(!(useModels && precacheSkins)) return; // Precache this. for(sub = 0; sub < MAX_FRAME_MODELS; ++sub) { const skinname_t* sn; if(!modef->sub[sub].model) continue; mdl = modellist[modef->sub[sub].model]; // Load all skins. for(k = 0; k < mdl->info.numSkins; ++k) { if((sn = R_GetSkinNameByIndex(mdl->skins[k].id))) { material_load_params_t params; memset(¶ms, 0, sizeof(params)); params.flags = (!mdl->allowTexComp? MLF_TEX_NO_COMPRESSION : 0); GL_PrepareGLTexture(sn->id, ¶ms, NULL); } } // Load the shiny skin. if((sn = R_GetSkinNameByIndex(modef->sub[sub].shinySkin))) { GL_PrepareGLTexture(sn->id, NULL, NULL); } } } void R_PrecacheSkinsForState(int stateIndex) { if(stateIndex <= 0 || stateIndex >= defs.count.states.num || !stateModefs[stateIndex]) return; R_PrecacheModelSkins(stateModefs[stateIndex]); } /** * The skins are also bound here once so they should be ready for use the * next time they're needed. */ boolean R_PrecacheSkinsForMobj(thinker_t* th, void* context) { int i; mobj_t* mo = (mobj_t*) th; modeldef_t* modef; // Check through all the model definitions. for(i = 0, modef = modefs; i < numModelDefs; ++i, modef++) { if(!modef->state) continue; if(mo->type < 0 || mo->type >= defs.count.mobjs.num) continue; // Hmm? if(stateOwners[modef->state - states] != &mobjInfo[mo->type]) continue; R_PrecacheModelSkins(modef); } return true; // Used as iterator. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_texmanager.c0000644000175000017500000031770011357170242023722 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_texman.c: Texture management routines. * * Much of this stuff actually belongs in Refresh. * This file needs to be split into smaller portions. */ // HEADER FILES ------------------------------------------------------------ #include #include #ifdef UNIX # include "de_platform.h" #endif #include "de_base.h" #include "de_console.h" #include "de_graphics.h" #include "de_render.h" #include "de_refresh.h" #include "de_system.h" #include "de_misc.h" #include "de_play.h" #include "def_main.h" #include "ui_main.h" #include "p_particle.h" // MACROS ------------------------------------------------------------------ #define GLTEXTURE_NAME_HASH_SIZE (512) // TYPES ------------------------------------------------------------------- typedef struct gltexture_inst_node_s { int flags; // Texture instance (MLF_*) flags. gltexture_inst_t inst; struct gltexture_inst_node_s* next; // Next in list of instances. } gltexture_inst_node_t; typedef struct gltexture_typedata_s { byte (*loadData) (image_t*, const gltexture_inst_t*, void*); uint hashTable[GLTEXTURE_NAME_HASH_SIZE]; } gltexture_typedata_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(LowRes); D_CMD(ResetTextures); D_CMD(MipMap); D_CMD(SmoothRaw); #ifdef _DEBUG D_CMD(TranslateFont); #endif void GL_DoResetDetailTextures(cvar_t* unused); /// gltexture_t abstract interface: gltexture_inst_t* GLTexture_Prepare(gltexture_t* tex, void* context, byte* result); void GLTexture_ReleaseTextures(gltexture_t* tex); void GLTexture_SetMinMode(gltexture_t* tex, int minMode); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void GL_SetTexCoords(float* tc, int wid, int hgt); static void calcGammaTable(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int ratioLimit; extern boolean palettedTextureExtAvailable; extern boolean s3tcAvailable; // PUBLIC DATA DEFINITIONS ------------------------------------------------- int ratioLimit = 0; // Zero if none. boolean fillOutlines = true; byte loadExtAlways = false; // Always check for extres (cvar) byte paletted = false; // Use GL_EXT_paletted_texture (cvar) boolean load8bit = false; // Load textures as 8 bit? (w/paltex) int monochrome = 0; // desaturate a patch (average colours) int upscaleAndSharpenPatches = 0; int useSmartFilter = 0; // Smart filter mode (cvar: 1=hq2x) int mipmapping = 5, linearRaw = 1, texQuality = TEXQ_BEST; int filterSprites = true; int texMagMode = 1; // Linear. int texAniso = -1; // Use best. float texGamma = 0; byte gammaTable[256]; int glmode[6] = // Indexed by 'mipmapping'. { GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_NEAREST, GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_LINEAR }; // Names of the dynamic light textures. ddtexture_t lightingTextures[NUM_LIGHTING_TEXTURES]; // Names of the flare textures (halos). ddtexture_t sysFlareTextures[NUM_SYSFLARE_TEXTURES]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean texInited = false; // Init done. static boolean allowMaskedTexEnlarge = false; static boolean noHighResTex = false; static boolean noHighResPatches = false; static boolean highResWithPWAD = false; // gltextures. static uint numGLTextures; static gltexture_t** glTextures; static gltexture_typedata_t glTextureTypeData[NUM_GLTEXTURE_TYPES] = { { GL_LoadDDTexture }, // GLT_SYSTEM { GL_LoadFlat }, // GLT_FLAT { GL_LoadDoomTexture }, // GLT_DOOMTEXTURE { GL_LoadSprite }, // GLT_SPRITE { GL_LoadDetailTexture }, // GLT_DETAIL { GL_LoadShinyTexture }, // GLT_SHINY { GL_LoadMaskTexture }, // GLT_MASK { GL_LoadModelSkin }, // GLT_MODELSKIN { GL_LoadModelShinySkin }, // GLT_MODELSHINYSKIN { GL_LoadLightMap }, // GLT_LIGHTMAP { GL_LoadFlareTexture } }; // CODE -------------------------------------------------------------------- void GL_TexRegister(void) { // Cvars C_VAR_INT("rend-tex", &renderTextures, CVF_NO_ARCHIVE, 0, 2); C_VAR_FLOAT2("rend-tex-gamma", &texGamma, 0, 0, 1, GL_DoUpdateTexGamma); C_VAR_INT2("rend-tex-mipmap", &mipmapping, CVF_PROTECTED, 0, 5, GL_DoTexReset); C_VAR_BYTE2("rend-tex-paletted", &paletted, CVF_PROTECTED, 0, 1, GL_DoTexReset); C_VAR_BYTE2("rend-tex-external-always", &loadExtAlways, 0, 0, 1, GL_DoTexReset); C_VAR_INT2("rend-tex-quality", &texQuality, 0, 0, 8, GL_DoTexReset); C_VAR_INT("rend-tex-filter-mag", &texMagMode, 0, 0, 1); C_VAR_INT("rend-tex-filter-sprite", &filterSprites, 0, 0, 1); C_VAR_INT("rend-tex-filter-raw", &linearRaw, 0, 0, 1); C_VAR_INT2("rend-tex-filter-smart", &useSmartFilter, 0, 0, 1, GL_DoTexReset); C_VAR_INT("rend-tex-filter-anisotropic", &texAniso, 0, -1, 4); C_VAR_INT("rend-tex-detail", &r_detail, 0, 0, 1); C_VAR_FLOAT("rend-tex-detail-scale", &detailScale, CVF_NO_MIN | CVF_NO_MAX, 0, 0); C_VAR_FLOAT2("rend-tex-detail-strength", &detailFactor, 0, 0, 10, GL_DoResetDetailTextures); C_VAR_INT("rend-tex-detail-multitex", &useMultiTexDetails, 0, 0, 1); // Ccmds C_CMD_FLAGS("lowres", "", LowRes, CMDF_NO_DEDICATED); C_CMD_FLAGS("mipmap", "i", MipMap, CMDF_NO_DEDICATED); C_CMD_FLAGS("smoothscr", "i", SmoothRaw, CMDF_NO_DEDICATED); C_CMD_FLAGS("texreset", "", ResetTextures, CMDF_NO_DEDICATED); #if _DEBUG C_CMD_FLAGS("translatefont", "ss", TranslateFont, CMDF_NO_DEDICATED); #endif } /** * Called before real texture management is up and running, during engine * early init. */ void GL_EarlyInitTextureManager(void) { int i; // Initialize the smart texture filtering routines. GL_InitSmartFilter(); calcGammaTable(); numGLTextures = 0; glTextures = NULL; for(i = 0; i < NUM_GLTEXTURE_TYPES; ++i) memset(glTextureTypeData[i].hashTable, 0, sizeof(glTextureTypeData[i].hashTable)); } /** * This should be cleaned up once and for all. */ void GL_InitTextureManager(void) { if(novideo) return; if(texInited) return; // Don't init again. // The -bigmtex option allows the engine to enlarge masked textures // that have taller patches than they are themselves. allowMaskedTexEnlarge = ArgExists("-bigmtex"); // Disable the use of 'high resolution' textures? noHighResTex = ArgExists("-nohightex"); noHighResPatches = ArgExists("-nohighpat"); // Should we allow using external resources with PWAD textures? highResWithPWAD = ArgExists("-pwadtex"); // System textures loaded in GL_LoadSystemTextures. memset(sysFlareTextures, 0, sizeof(sysFlareTextures)); memset(lightingTextures, 0, sizeof(lightingTextures)); // Initialization done. texInited = true; } /** * Call this if a full cleanup of the textures is required (engine update). */ void GL_ResetTextureManager(void) { if(!texInited) return; GL_ClearTextureMemory(); texInited = false; } /** * Called once during engine shutdown. */ void GL_ShutdownTextureManager(void) { if(!texInited) return; // Already been here? if(glTextures) { uint i; for(i = 0; i < numGLTextures; ++i) { gltexture_t* mTex = glTextures[i]; gltexture_inst_node_t* node, *next; node = (gltexture_inst_node_t*) mTex->instances; while(node) { next = node->next; Z_Free(node); node = next; } Z_Free(mTex); } Z_Free(glTextures); glTextures = NULL; numGLTextures = 0; } texInited = false; } static void calcGammaTable(void) { int i; double invGamma; // Clamp to a sane range. invGamma = 1.0f - MINMAX_OF(0, texGamma, 1); for(i = 0; i < 256; ++i) gammaTable[i] = (byte)(255.0f * pow(i / 255.0f, invGamma)); } /** * Initializes the paletted texture extension. * Returns true if successful. */ int GL_InitPalettedTexture(void) { if(novideo) return true; // Should the extension be used? if(!paletted && !ArgCheck("-paltex")) return true; // Check if the operation was a success. if(!GL_EnablePalTexExt(true)) { Con_Message("\nPaletted textures init failed!\n"); return false; } // Textures must be uploaded as 8-bit, now. load8bit = true; return true; } /** * Prepares all the system textures (dlight, ptcgens). */ void GL_LoadSystemTextures(void) { struct ddtexdef_s { char name[9]; int id; byte flags; // MATF_* flags } static const ddtexdefs[NUM_DD_TEXTURES] = { {"DDT_UNKN", DDT_UNKNOWN}, {"DDT_MISS", DDT_MISSING}, {"DDT_BBOX", DDT_BBOX}, {"DDT_GRAY", DDT_GRAY} }; int i; if(!texInited) return; i = 0; for(i = 0; i < NUM_DD_TEXTURES; ++i) { material_t* mat; const gltexture_t* tex; tex = GL_CreateGLTexture(ddtexdefs[i].name, ddtexdefs[i].id, GLT_SYSTEM); mat = P_MaterialCreate(ddtexdefs[i].name, 64, 64, 0, tex->id, MN_SYSTEM, NULL); } UI_LoadTextures(); // Preload lighting system textures. GL_PrepareLSTexture(LST_DYNAMIC); GL_PrepareLSTexture(LST_GRADIENT); GL_PrepareSysFlareTexture(FXT_ROUND); GL_PrepareSysFlareTexture(FXT_FLARE); if(!haloRealistic) { GL_PrepareSysFlareTexture(FXT_BRFLARE); GL_PrepareSysFlareTexture(FXT_BIGFLARE); } Rend_ParticleInitTextures(); // Load particle textures. } /** * System textures are loaded at startup and remain in memory all the time. * After clearing they must be manually reloaded. */ void GL_ClearSystemTextures(void) { int i; if(!texInited) return; for(i = 0; i < NUM_LIGHTING_TEXTURES; ++i) glDeleteTextures(1, (const GLuint*) &lightingTextures[i].tex); memset(lightingTextures, 0, sizeof(lightingTextures)); for(i = 0; i < NUM_SYSFLARE_TEXTURES; ++i) glDeleteTextures(1, (const GLuint*) &sysFlareTextures[i].tex); memset(sysFlareTextures, 0, sizeof(sysFlareTextures)); P_DeleteMaterialTextures(MN_SYSTEM); UI_ClearTextures(); // Delete the particle textures. Rend_ParticleShutdownTextures(); } /** * Runtime textures are not loaded until precached or actually needed. * They may be cleared, in which case they will be reloaded when needed. */ void GL_ClearRuntimeTextures(void) { if(!texInited) return; // The rendering lists contain persistent references to texture names. // Which, obviously, can't persist any longer... RL_DeleteLists(); // gltexture-wrapped GL textures; textures, flats, sprites, system... GL_DeleteAllTexturesForGLTextures(GLT_ANY); { patchtex_t** patches, **ptr; patches = R_CollectPatchTexs(NULL); for(ptr = patches; *ptr; ptr++) { patchtex_t* p = (*ptr); if(p->tex) { glDeleteTextures(1, (const GLuint*) &p->tex); p->tex = 0; } if(p->tex2) { glDeleteTextures(1, (const GLuint*) &p->tex2); p->tex2 = 0; } } Z_Free(patches); } GL_DeleteRawImages(); } void GL_ClearTextureMemory(void) { if(!texInited) return; // Delete runtime textures (textures, flats, ...) GL_ClearRuntimeTextures(); // Delete system textures. GL_ClearSystemTextures(); } /** * Binds the OGL texture. */ void GL_BindTexture(DGLuint texname, int magMode) { if(Con_IsBusy()) return; glBindTexture(GL_TEXTURE_2D, texname); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magMode); if(GL_state.useAnisotropic) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(texAniso)); } /*DGLuint GL_UploadTexture(byte *data, int width, int height, boolean alphaChannel, boolean generateMipmaps, boolean RGBData, boolean noStretch)*/ DGLuint GL_UploadTexture(byte *data, int width, int height, boolean flagAlphaChannel, boolean flagGenerateMipmaps, boolean flagRgbData, boolean flagNoStretch, boolean flagNoSmartFilter, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT, int otherFlags)/*boolean alphaChannel, boolean generateMipmaps, boolean RGBData, boolean noStretch)*/ { texturecontent_t content; GL_InitTextureContent(&content); content.buffer = data; content.format = (flagRgbData? (flagAlphaChannel? DGL_RGBA : DGL_RGB) : (flagAlphaChannel? DGL_COLOR_INDEX_8_PLUS_A8 : DGL_COLOR_INDEX_8)); content.width = width; content.height = height; content.flags = TXCF_EASY_UPLOAD | otherFlags; if(flagAlphaChannel) content.flags |= TXCF_UPLOAD_ARG_ALPHACHANNEL; if(flagGenerateMipmaps) content.flags |= TXCF_MIPMAP; if(flagRgbData) content.flags |= TXCF_UPLOAD_ARG_RGBDATA; if(flagNoStretch) content.flags |= TXCF_UPLOAD_ARG_NOSTRETCH; if(flagNoSmartFilter) content.flags |= TXCF_UPLOAD_ARG_NOSMARTFILTER; content.minFilter = minFilter; content.magFilter = magFilter; content.anisoFilter = anisoFilter; content.wrap[0] = wrapS; content.wrap[1] = wrapT; return GL_NewTexture(&content, NULL); } /** * Can be rather time-consuming due to scaling operations and mipmap * generation. The texture parameters will NOT be set here. * * @param data Contains indices to the color palette. * @param alphaChannel If true, 'data' also contains the alpha values * (after the indices). * @return The name of the texture (same as 'texName'). */ DGLuint GL_UploadTexture2(texturecontent_t* content) { byte* data = content->buffer; int width = content->width; int height = content->height; boolean alphaChannel = ((content->flags & TXCF_UPLOAD_ARG_ALPHACHANNEL) != 0); boolean generateMipmaps = ((content->flags & TXCF_MIPMAP) != 0); boolean RGBData = ((content->flags & TXCF_UPLOAD_ARG_RGBDATA) != 0); boolean noStretch = ((content->flags & TXCF_UPLOAD_ARG_NOSTRETCH) != 0); boolean noSmartFilter = ((content->flags & TXCF_UPLOAD_ARG_NOSMARTFILTER) != 0); boolean applyTexGamma = ((content->flags & TXCF_APPLY_GAMMACORRECTION) != 0); int i, levelWidth, levelHeight; // width and height at the current level int comps; byte *buffer, *rgbaOriginal, *idxBuffer; boolean freeOriginal; boolean freeBuffer; // Number of color components in the destination image. comps = (alphaChannel ? 4 : 3); // Calculate the real dimensions for the texture, as required by // the graphics hardware. noStretch = GL_OptimalSize(width, height, &levelWidth, &levelHeight, noStretch, generateMipmaps); // Get the RGB(A) version of the original texture. if(RGBData) { // The source image can be used as-is. freeOriginal = false; rgbaOriginal = data; } else { // Convert a paletted source image to truecolor so it can be scaled. freeOriginal = true; rgbaOriginal = M_Malloc(width * height * comps); GL_ConvertBuffer(width, height, alphaChannel ? 2 : 1, comps, data, rgbaOriginal, 0, !load8bit); } if(applyTexGamma) { for(i = 0; i < width * height * comps; i += comps) { rgbaOriginal[i] = gammaTable[data[i]]; rgbaOriginal[i+1] = gammaTable[data[i+1]]; rgbaOriginal[i+2] = gammaTable[data[i+2]]; } } // If smart filtering is enabled, all textures are magnified 2x. if(useSmartFilter && !noSmartFilter /* && comps == 3 */ ) { byte* filtered = M_Malloc(4 * width * height * 4); if(comps == 3) { // Must convert to RGBA. byte* temp = M_Malloc(4 * width * height); GL_ConvertBuffer(width, height, 3, 4, rgbaOriginal, temp, 0, !load8bit); if(freeOriginal) M_Free(rgbaOriginal); rgbaOriginal = temp; freeOriginal = true; comps = 4; alphaChannel = true; } GL_SmartFilter2x(rgbaOriginal, filtered, width, height, width * 8); width *= 2; height *= 2; noStretch = GL_OptimalSize(width, height, &levelWidth, &levelHeight, noStretch, generateMipmaps); /*memcpy(filtered, rgbaOriginal, comps * width * height); */ // The filtered copy is now the 'original' image data. if(freeOriginal) M_Free(rgbaOriginal); rgbaOriginal = filtered; freeOriginal = true; } // Prepare the RGB(A) buffer for the texture: we want a buffer with // power-of-two dimensions. It will be the mipmap level zero. // The buffer will be modified in the mipmap generation (if done here). if(width == levelWidth && height == levelHeight) { // No resizing necessary. buffer = rgbaOriginal; freeBuffer = freeOriginal; freeOriginal = false; } else { freeBuffer = true; buffer = M_Malloc(levelWidth * levelHeight * comps); if(noStretch) { // Copy the image into a buffer with power-of-two dimensions. memset(buffer, 0, levelWidth * levelHeight * comps); for(i = 0; i < height; ++i) // Copy line by line. memcpy(buffer + levelWidth * comps * i, rgbaOriginal + width * comps * i, comps * width); } else { // Stretch to fit into power-of-two. if(width != levelWidth || height != levelHeight) { GL_ScaleBuffer32(rgbaOriginal, width, height, buffer, levelWidth, levelHeight, comps); } } } // The RGB(A) copy of the source image is no longer needed. if(freeOriginal) M_Free(rgbaOriginal); rgbaOriginal = NULL; // Bind the texture so we can upload content. glBindTexture(GL_TEXTURE_2D, content->name); if(load8bit) { // We are unable to generate mipmaps for paletted textures. int canGenMips = 0; DGLuint pal = R_GetColorPalette(content->palette); // Prepare the palette indices buffer, to be handed over to DGL. idxBuffer = M_Malloc(levelWidth * levelHeight * (alphaChannel ? 2 : 1)); // Since this is a paletted texture, we may need to manually // generate the mipmaps. for(i = 0; levelWidth || levelHeight; ++i) { if(!levelWidth) levelWidth = 1; if(!levelHeight) levelHeight = 1; // Convert to palette indices. GL_ConvertBuffer(levelWidth, levelHeight, comps, alphaChannel ? 2 : 1, buffer, idxBuffer, content->palette, false); // Upload it. if(!GL_TexImage(alphaChannel ? DGL_COLOR_INDEX_8_PLUS_A8 : DGL_COLOR_INDEX_8, pal, levelWidth, levelHeight, generateMipmaps && canGenMips ? true : generateMipmaps ? -i : false, idxBuffer)) { Con_Error ("GL_UploadTexture: TexImage failed (%i x %i) as " "8-bit, alpha:%i\n", levelWidth, levelHeight, alphaChannel); } // If no mipmaps need to generated, quit now. if(!generateMipmaps || canGenMips) break; if(levelWidth > 1 || levelHeight > 1) GL_DownMipmap32(buffer, levelWidth, levelHeight, comps); // Move on. levelWidth >>= 1; levelHeight >>= 1; } M_Free(idxBuffer); } else { // DGL knows how to generate mipmaps for RGB(A) textures. if(!GL_TexImage(alphaChannel ? DGL_RGBA : DGL_RGB, 0, levelWidth, levelHeight, generateMipmaps ? true : false, buffer)) { Con_Error ("GL_UploadTexture: TexImage failed (%i x %i), alpha:%i\n", levelWidth, levelHeight, alphaChannel); } } if(freeBuffer) M_Free(buffer); return content->name; } /** * @return The outcome: * 0 = not loaded. * 1 = loaded data from a lump resource. * 2 = loaded data from an external resource. */ byte GL_LoadDDTexture(image_t* image, const gltexture_inst_t* inst, void* context) { static const char* ddTexNames[NUM_DD_TEXTURES] = { "unknown", "missing", "bbox", "gray" }; int num; byte result = 0; filename_t fileName; if(!image) return result; // Wha? num = inst->tex->ofTypeID; if(num < 0 || num > NUM_DD_TEXTURES) Con_Error("GL_LoadDDTexture: Internal error, " "invalid ddtex id %i.", num); if(!(R_FindResource2(RT_GRAPHIC, DDRC_GRAPHICS, fileName, ddTexNames[num], NULL, FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName))) { Con_Error("GL_LoadDDTexture: \"%s\" not found!\n", ddTexNames[num]); } result = 2; // Always external. return result; } /** * @return The outcome: * 0 = none loaded. * 1 = a lump resource. * 2 = an external resource. */ byte GL_LoadDetailTexture(image_t* image, const gltexture_inst_t* inst, void* context) { detailtex_t* dTex; if(!image) return 0; // Wha? dTex = detailTextures[inst->tex->ofTypeID]; if(dTex->external != NULL) { filename_t fileName; if(!(R_FindResource2(RT_GRAPHIC, DDRC_TEXTURE, fileName, dTex->external, NULL, FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName))) { VERBOSE(Con_Message("GL_LoadDetailTexture: " "Failed to load: %s\n", dTex->external)); return 0; } return 2; } else { const byte* data = W_CacheLumpNum(dTex->lump, PU_STATIC); // First try loading it as a PCX image. if(PCX_MemoryGetSize(data, &image->width, &image->height)) { // Nice... image->pixels = M_Malloc(image->width * image->height * 3); PCX_MemoryLoad(data, W_LumpLength(dTex->lump), image->width, image->height, image->pixels); } else // It must be a raw image. { size_t lumpLength = W_LumpLength(dTex->lump); /** * @fixme we should not error out here if the lump is not * of the required format! Perform this check much earlier, * when the definitions are read and mark which are valid. */ // How big is it? if(lumpLength != 256 * 256) { if(lumpLength != 128 * 128) { if(lumpLength != 64 * 64) { W_ChangeCacheTag(dTex->lump, PU_CACHE); Con_Error ("GL_LoadDetailTexture: Must be 256x256, " "128x128 or 64x64.\n"); } image->width = image->height = 64; } else { image->width = image->height = 128; } } else image->width = image->height = 256; image->pixels = M_Malloc(image->width * image->height); memcpy(image->pixels, W_CacheLumpNum(dTex->lump, PU_CACHE), image->width * image->height); image->pixelSize = 1; } W_ChangeCacheTag(dTex->lump, PU_CACHE); return 1; } } /** * @return The outcome: * 0 = none loaded. * 1 = a lump resource. * 2 = an external resource. */ byte GL_LoadLightMap(image_t* image, const gltexture_inst_t* inst, void* context) { lightmap_t* lmap; filename_t fileName; if(!image) return 0; // Wha? lmap = lightMaps[inst->tex->ofTypeID]; // Search an external resource. if(!(R_FindResource2(RT_GRAPHIC, DDRC_LIGHTMAP, fileName, lmap->external, "-ck", FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName))) { VERBOSE( Con_Message("GL_LoadLightMap: Failed to load: %s\n", lmap->external)); return 0; } return 2; } /** * @return The outcome: * 0 = none loaded. * 1 = a lump resource. * 2 = an external resource. */ byte GL_LoadFlareTexture(image_t* image, const gltexture_inst_t* inst, void* context) { flaretex_t* fTex; filename_t fileName; if(!image) return 0; // Wha? fTex = flareTextures[inst->tex->ofTypeID]; // Search an external resource. if(!(R_FindResource2(RT_GRAPHIC, DDRC_FLAREMAP, fileName, fTex->external, "-ck", FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName))) { VERBOSE( Con_Message("GL_LoadFlareTexture: Failed to load: %s\n", fTex->external)); return 0; } return 2; } /** * @return The outcome: * 0 = none loaded. * 1 = a lump resource. * 2 = an external resource. */ byte GL_LoadShinyTexture(image_t* image, const gltexture_inst_t* inst, void* context) { filename_t fileName; shinytex_t* sTex; if(!image) return 0; // Wha? sTex = shinyTextures[inst->tex->ofTypeID]; if(!(R_FindResource2(RT_GRAPHIC, DDRC_LIGHTMAP, fileName, sTex->external, NULL, FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName))) { VERBOSE(Con_Printf("GL_LoadShinyTexture: %s not found!\n", sTex->external)); return 0; } return 2; // Always external. } /** * @return The outcome: * 0 = none loaded. * 1 = a lump resource. * 2 = an external resource. */ byte GL_LoadMaskTexture(image_t* image, const gltexture_inst_t* inst, void* context) { filename_t fileName; masktex_t* mTex; if(!image) return 0; // Wha? mTex = maskTextures[inst->tex->ofTypeID]; if(!(R_FindResource2(RT_GRAPHIC, DDRC_LIGHTMAP, fileName, mTex->external, NULL, FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName))) { VERBOSE(Con_Printf("GL_LoadMaskTexture: %s not found!\n", mTex->external)); return 0; } return 2; // Always external. } /** * @return The outcome: * 0 = none loaded. * 1 = a lump resource. * 2 = an external resource. */ byte GL_LoadModelSkin(image_t* image, const gltexture_inst_t* inst, void* context) { const skinname_t* sn; filename_t fileName; if(!image) return 0; // Wha? sn = &skinNames[inst->tex->ofTypeID]; if(R_FindResource2(RT_GRAPHIC, DDRC_MODEL, fileName, sn->path, NULL, FILENAME_T_MAXLEN)) if(GL_LoadImage(image, fileName)) { return 2; // Always external. } VERBOSE(Con_Printf("GL_LoadModelSkin: %s not found!\n", sn->path)); return 0; } /** * @return The outcome: * 0 = none loaded. * 1 = a lump resource. * 2 = an external resource. */ byte GL_LoadModelShinySkin(image_t* img, const gltexture_inst_t* inst, void* context) { const skinname_t* sn; filename_t resource, fileName; char* ptr; if(!img) return 0; // Wha? sn = &skinNames[inst->tex->ofTypeID]; /** * First sees if there is a color-keyed version. If there is load it. * Otherwise the 'regular' version is loaded. */ strncpy(resource, sn->path, FILENAME_T_MAXLEN); // Append the "-ck" and try to load. if((ptr = strrchr(resource, '.'))) { memmove(ptr + 3, ptr, strlen(ptr) + 1); ptr[0] = '-'; ptr[1] = 'c'; ptr[2] = 'k'; if(R_FindResource2(RT_GRAPHIC, DDRC_MODEL, fileName, resource, NULL, FILENAME_T_MAXLEN)) if(GL_LoadImage(img, fileName)) return 2; } if(R_FindResource2(RT_GRAPHIC, DDRC_MODEL, fileName, sn->path, NULL, FILENAME_T_MAXLEN)) if(GL_LoadImage(img, fileName)) return 2; VERBOSE(Con_Printf("GL_LoadModelShinySkin: %s not found!\n", sn->path)); return 0; } /** * Prepare a texture used in the lighting system. 'which' must be one * of the LST_* constants. */ DGLuint GL_PrepareLSTexture(lightingtexid_t which) { struct lstex_s { const char* name; int wrapS, wrapT; } lstexes[NUM_LIGHTING_TEXTURES] = { { "dLight", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }, { "wallglow", GL_REPEAT, GL_CLAMP_TO_EDGE }, { "radioCO", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }, { "radioCC", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }, { "radioOO", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE }, { "radioOE", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE } }; if(which < 0 || which >= NUM_LIGHTING_TEXTURES) return 0; if(!lightingTextures[which].tex) { lightingTextures[which].tex = GL_PrepareExtTexture(DDRC_GRAPHICS, lstexes[which].name, LGM_WHITE_ALPHA, false, GL_LINEAR, GL_LINEAR, -1 /*best anisotropy*/, lstexes[which].wrapS, lstexes[which].wrapT, TXCF_NO_COMPRESSION); } return lightingTextures[which].tex; } DGLuint GL_PrepareSysFlareTexture(flaretexid_t flare) { if(flare >= NUM_SYSFLARE_TEXTURES) return 0; if(!sysFlareTextures[flare].tex) { // We don't want to compress the flares (banding would be noticeable). sysFlareTextures[flare].tex = GL_PrepareExtTexture(DDRC_GRAPHICS, flare == 0 ? "dlight" : flare == 1 ? "flare" : flare == 2 ? "brflare" : "bigflare", LGM_WHITE_ALPHA, false, GL_NEAREST, GL_LINEAR, 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, TXCF_NO_COMPRESSION); if(sysFlareTextures[flare].tex == 0) { Con_Error("GL_PrepareSysFlareTexture: flare texture %i not found!\n", flare); } } return sysFlareTextures[flare].tex; } /** * @return The outcome: * 0 = not prepared * 1 = found and prepared a lump resource. * 2 = found and prepared an external resource. */ byte GL_LoadExtTexture(image_t* image, ddresourceclass_t resClass, const char* name, gfxmode_t mode) { filename_t fileName; if(R_FindResource2(RT_GRAPHIC, resClass, fileName, name, NULL, FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName)) { // Too big for us? if(image->width > GL_state.maxTexSize || image->height > GL_state.maxTexSize) { int newWidth = MIN_OF(image->width, GL_state.maxTexSize); int newHeight = MIN_OF(image->height, GL_state.maxTexSize); byte *tmp = M_Malloc(newWidth * newHeight * image->pixelSize); GL_ScaleBuffer32(image->pixels, image->width, image->height, tmp, newWidth, newHeight, image->pixelSize); M_Free(image->pixels); image->pixels = tmp; image->width = newWidth; image->height = newHeight; } // Force it to grayscale? if(mode == LGM_GRAYSCALE_ALPHA || mode == LGM_WHITE_ALPHA) { GL_ConvertToAlpha(image, mode == LGM_WHITE_ALPHA); } else if(mode == LGM_GRAYSCALE) { GL_ConvertToLuminance(image); } return 2; // Always external. } return 0; } /** * @return The outcome: * 0 = not prepared * 1 = found and prepared a lump resource. * 2 = found and prepared an external resource. */ byte GL_LoadFlat(image_t* img, const gltexture_inst_t* inst, void* context) { const flat_t* flat; size_t lumpLength; if(!img) return 0; // Wha? flat = flats[inst->tex->ofTypeID]; // Try to load a high resolution version of this flat? if(!noHighResTex && (loadExtAlways || highResWithPWAD || GLTexture_IsFromIWAD(inst->tex))) { filename_t file; boolean found; const char* lumpName = W_LumpName(flat->lump); // First try the Flats category. if(!(found = R_FindResource2(RT_GRAPHIC, DDRC_FLAT, file, lumpName, NULL, FILENAME_T_MAXLEN))) { // Try the old-fashioned "Flat-NAME" in the Textures category. filename_t resource; dd_snprintf(resource, FILENAME_T_MAXLEN, "flat-%s", lumpName); found = R_FindResource2(RT_GRAPHIC, DDRC_TEXTURE, file, resource, NULL, FILENAME_T_MAXLEN); } if(found && GL_LoadImage(img, file)) return 2; } if((lumpLength = W_LumpLength(flat->lump)) < 4096) return 0; // Too small. // Read in the flat. img->pixels = M_Malloc(lumpLength); W_ReadLump(flat->lump, img->pixels); img->width = flat->width; img->height = flat->height; img->isMasked = false; img->pixelSize = 1; return 1; } /** * Loads PCX, TGA and PNG images. The returned buffer must be freed * with M_Free. Color keying is done if "-ck." is found in the filename. * The allocated memory buffer always has enough space for 4-component * colors. */ static byte* loadImage(image_t* img, const char* imagefn) { DFILE* file; char* p; int format; // We know how to load PCX, TGA and PNG. p = M_FindFileExtension(img->fileName); if(p) { if(!strcmp(p, "pcx")) { if(!PCX_GetSize(img->fileName, &img->width, &img->height)) return NULL; img->pixels = M_Malloc(4 * img->width * img->height); PCX_Load(img->fileName, img->width, img->height, img->pixels); img->pixelSize = 3; // PCXs can't be masked. img->originalBits = 8; } else if(!strcmp(p, "tga")) { if(!TGA_GetSize(img->fileName, &img->width, &img->height)) return NULL; if(!(file = F_Open(img->fileName, "rb"))) return NULL; // Allocate a big enough buffer and read in the image. img->pixels = M_Malloc(4 * img->width * img->height); format = TGA_Load32_rgba8888(file, img->width, img->height, img->pixels); if(format == TGA_TARGA24) { img->pixelSize = 3; img->originalBits = 24; } else { img->pixelSize = 4; img->originalBits = 32; } F_Close(file); } else if(!strcmp(p, "png")) { img->pixels = PNG_Load(img->fileName, &img->width, &img->height, &img->pixelSize); img->originalBits = 8 * img->pixelSize; if(img->pixels == NULL) return NULL; } } VERBOSE(Con_Message("LoadImage: %s (%ix%i)\n", M_PrettyPath(img->fileName), img->width, img->height)); // How about some color-keying? if(GL_IsColorKeyed(img->fileName)) { byte *out; out = GL_ApplyColorKeying(img->pixels, img->pixelSize, img->width, img->height); if(out) { // Had to allocate a larger buffer, free the old and attach the new. M_Free(img->pixels); img->pixels = out; } // Color keying is done; now we have 4 bytes per pixel. img->pixelSize = 4; img->originalBits = 32; // Effectively... } // Any alpha pixels? img->isMasked = ImageHasAlpha(img); return img->pixels; } byte* GL_LoadImage(image_t* img, const char* imagefn) { if(img) { // Clear any old values. memset(img, 0, sizeof(*img)); if(imagefn && imagefn[0]) { strncpy(img->fileName, imagefn, FILENAME_T_MAXLEN); return loadImage(img, imagefn); } } return NULL; } /** * Frees all memory associated with the image. */ void GL_DestroyImage(image_t* img) { if(img) { if(img->pixels) M_Free(img->pixels); img->pixels = NULL; } } /** * Set mode to 2 to include an alpha channel. Set to 3 to make the * actual pixel colors all white. */ DGLuint GL_PrepareExtTexture(ddresourceclass_t resClass, const char* name, gfxmode_t mode, int useMipmap, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT, int otherFlags) { image_t image; DGLuint texture = 0; if(GL_LoadExtTexture(&image, resClass, name, mode)) { // Loaded successfully and converted accordingly. // Upload the image to GL. texture = GL_NewTextureWithParams2( ( image.pixelSize == 2 ? DGL_LUMINANCE_PLUS_A8 : image.pixelSize == 3 ? DGL_RGB : image.pixelSize == 4 ? DGL_RGBA : DGL_LUMINANCE ), image.width, image.height, image.pixels, ( otherFlags | (useMipmap? TXCF_MIPMAP : 0) | (useMipmap == DDMAXINT? TXCF_GRAY_MIPMAP : 0) | (image.width < 128 && image.height < 128? TXCF_NO_COMPRESSION : 0) ), (useMipmap ? glmode[mipmapping] : GL_LINEAR), magFilter, texAniso, wrapS, wrapT); GL_DestroyImage(&image); } return texture; } /** * Part of the Doomsday public API. */ DGLuint GL_LoadGraphics(ddresourceclass_t resClass, const char *name, gfxmode_t mode, int useMipmap, boolean clamped, int otherFlags) { return GL_PrepareExtTexture(resClass, name, mode, useMipmap, GL_LINEAR, GL_LINEAR, 0 /*no anisotropy*/, clamped? GL_CLAMP_TO_EDGE : GL_REPEAT, clamped? GL_CLAMP_TO_EDGE : GL_REPEAT, otherFlags); } /** * Renders the given texture into the buffer. */ static boolean bufferTexture(const doomtexturedef_t* texDef, byte* buffer, int width, int height, int* hasBigPatch) { int i, len; boolean alphaChannel = false; lumppatch_t* patch; len = width * height; // Clear the buffer. memset(buffer, 0, 2 * len); // By default zero is put in the big patch height. if(hasBigPatch) *hasBigPatch = 0; // Draw all the patches. Check for alpha pixels after last patch has // been drawn. for(i = 0; i < texDef->patchCount; ++i) { const texpatch_t* patchDef = &texDef->patches[i]; patch = (lumppatch_t*) W_CacheLumpNum(patchDef->lump, PU_CACHE); // Check for big patches? if(SHORT(patch->height) > texDef->height && hasBigPatch && *hasBigPatch < SHORT(patch->height)) { *hasBigPatch = SHORT(patch->height); } // Draw the patch in the buffer. alphaChannel = DrawRealPatch(buffer, /*palette,*/ width, height, patch, patchDef->offX, patchDef->offY, false, i == texDef->patchCount - 1); } return alphaChannel; } /** * Draws the given sky texture in a buffer. The returned buffer must be * freed by the caller. Idx must be a valid texture number. */ static void bufferSkyTexture(const doomtexturedef_t* texDef, byte** outbuffer, int width, int height, boolean zeroMask) { int i, numpels; byte* imgdata; if(texDef->patchCount > 1) { numpels = width * height; imgdata = M_Calloc(2 * numpels); for(i = 0; i < texDef->patchCount; ++i) { const texpatch_t* patchDef = &texDef->patches[i]; DrawRealPatch(imgdata, /*palette,*/ width, height, W_CacheLumpNum(patchDef->lump, PU_CACHE), patchDef->offX, patchDef->offY, zeroMask, false); } } else { lumppatch_t *patch = (lumppatch_t*) W_CacheLumpNum(texDef->patches[0].lump, PU_CACHE); int bufHeight = SHORT(patch->height) > height ? SHORT(patch->height) : height; if(bufHeight > height) { // Heretic sky textures are reported to be 128 tall, even if the // data is 200. We'll adjust the real height of the texture up to // 200 pixels (remember Caldera?). height = bufHeight; if(height > 200) height = 200; } // Allocate a large enough buffer. numpels = width * bufHeight; imgdata = M_Calloc(2 * numpels); DrawRealPatch(imgdata, /*palette,*/ width, bufHeight, patch, 0, 0, zeroMask, false); } *outbuffer = imgdata; } /** * @return The outcome: * 0 = not loaded. * 1 = loaded data from a lump resource. * 2 = loaded data from an external resource. */ byte GL_LoadDoomTexture(image_t* image, const gltexture_inst_t* inst, void* context) { int i, flags = 0; doomtexturedef_t* texDef; boolean loadAsSky = false, zeroMask = false; material_load_params_t* params = (material_load_params_t*) context; if(!image) return 0; // Wha? if(params) { loadAsSky = (params->flags & MLF_LOAD_AS_SKY)? true : false; zeroMask = (params->flags & MLF_ZEROMASK)? true : false; } texDef = R_GetDoomTextureDef(inst->tex->ofTypeID); // Try to load a high resolution version of this texture? if(!noHighResTex && (loadExtAlways || highResWithPWAD || GLTexture_IsFromIWAD(inst->tex))) { filename_t fileName; if(R_FindResource2(RT_GRAPHIC, DDRC_TEXTURE, fileName, texDef->name, "-ck", FILENAME_T_MAXLEN)) if(GL_LoadImage(image, fileName)) return 2; // High resolution texture loaded. } // None found. Load the lowres version. image->width = texDef->width; image->height = texDef->height; image->pixelSize = 1; if(loadAsSky) { bufferSkyTexture(texDef, &image->pixels, image->width, image->height, zeroMask); image->isMasked = zeroMask; } else { /** * \todo if we are resizing masked textures re match patches then * we are needlessly duplicating work. */ image->pixels = M_Malloc(2 * image->width * image->height); image->isMasked = bufferTexture(texDef, image->pixels, image->width, image->height, &i); // The -bigmtex option allows the engine to resize masked // textures whose patches are too big to fit the texture. if(allowMaskedTexEnlarge && image->isMasked && i) { // Adjust the defined height to fit the largest patch. texDef->height = image->height = i; // Get a new buffer. M_Free(image->pixels); image->pixels = M_Malloc(2 * image->width * image->height); image->isMasked = bufferTexture(texDef, image->pixels, image->width, image->height, 0); } } return 1; } /** * @return The outcome: * 0 = not prepared * 1 = found and prepared a lump resource. * 2 = found and prepared an external resource. */ byte GL_LoadDoomPatch(image_t* image, const patchtex_t* p) { if(!image) return 0; // Wha? // Try to load a high resolution version of the patch? if(!noHighResTex && (loadExtAlways || highResWithPWAD || W_IsFromIWAD(p->lump))) { filename_t fileName; if(R_FindResource2(RT_GRAPHIC, DDRC_PATCH, fileName, W_LumpName(p->lump), "-ck", FILENAME_T_MAXLEN)) if(GL_LoadImage(image, fileName)) return 2; // High resolution patch loaded. } // Use data from the normal lump. if(p->lump >= 0 && p->lump < numLumps) { boolean scaleSharp = (upscaleAndSharpenPatches || (p->flags & PF_UPSCALE_AND_SHARPEN)); int patchWidth, patchHeight; const lumppatch_t* patch; patch = W_CacheLumpNum(p->lump, PU_CACHE); patchWidth = SHORT(patch->width); patchHeight = SHORT(patch->height); if(patchWidth * patchHeight) { if(scaleSharp) { patchWidth += 2; patchHeight += 2; } image->width = patchWidth; image->height = patchHeight; image->pixelSize = 1; // Allocate memory for the patch. image->pixels = M_Calloc(2 * image->width * image->height); image->isMasked = DrawRealPatch(image->pixels, image->width, image->height, patch, scaleSharp? 1 : 0, scaleSharp? 1 : 0, false, true); return 1; } } return 0; } /** * @return The outcome: * 0 = not loaded. * 1 = loaded data from a lump resource. * 2 = loaded data from an external resource. */ byte GL_LoadSprite(image_t* image, const gltexture_inst_t* inst, void* context) { const spritetex_t* sprTex; int tmap = 0, tclass = 0; boolean pSprite = false; material_load_params_t* params = (material_load_params_t*) context; if(!image) return 0; // Wha? sprTex = spriteTextures[inst->tex->ofTypeID]; if(params) { tmap = params->tmap; tclass = params->tclass; pSprite = params->pSprite; } // Attempt to load a high resolution version of this sprite? if(!noHighResPatches) { filename_t resource, fileName; boolean found; const char* lumpName = W_LumpName(sprTex->lump); // Compose a resource name. if(pSprite) { dd_snprintf(resource, FILENAME_T_MAXLEN, "%s-hud", lumpName); } else { if(tclass || tmap) { // Translated. dd_snprintf(resource, FILENAME_T_MAXLEN, "%s-table%i%i", lumpName, tclass, tmap); } else { // Not translated; use the normal resource. strncpy(resource, lumpName, FILENAME_T_MAXLEN); } } found = R_FindResource2(RT_GRAPHIC, DDRC_PATCH, fileName, resource, "-ck", FILENAME_T_MAXLEN); if(!found && pSprite) found = R_FindResource2(RT_GRAPHIC, DDRC_PATCH, fileName, lumpName, "-ck", FILENAME_T_MAXLEN); if(found && GL_LoadImage(image, fileName) != NULL) return 2; // Loaded high resolution sprite. } { boolean freePatch = false; const lumppatch_t* patch; void* tmp = NULL; image->width = sprTex->width; image->height = sprTex->height; image->pixelSize = 1; image->pixels = M_Calloc(2 * image->width * image->height); if(tclass || tmap) { int offset = -256 + tclass * ((8-1) * 256) + tmap * 256; // We need to translate the patch. tmp = M_Malloc(W_LumpLength(sprTex->lump)); W_ReadLump(sprTex->lump, tmp); GL_TranslatePatch((lumppatch_t*) tmp, &translationTables[MAX_OF(0, offset)]); patch = (lumppatch_t*) tmp; freePatch = true; } else { patch = W_CacheLumpNum(sprTex->lump, PU_STATIC); } DrawRealPatch(image->pixels, image->width, image->height, patch, 0, 0, false, false); if(freePatch) M_Free(tmp); else W_ChangeCacheTag(sprTex->lump, PU_CACHE); return 1; } } void GL_SetPSprite(material_t* mat) { material_load_params_t params; material_snapshot_t ms; memset(¶ms, 0, sizeof(params)); params.pSprite = true; Material_Prepare(&ms, mat, true, ¶ms); GL_BindTexture(ms.units[MTU_PRIMARY].texInst->id, ms.units[MTU_PRIMARY].magMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } void GL_SetTranslatedSprite(material_t* mat, int tclass, int tmap) { material_snapshot_t ms; material_load_params_t params; memset(¶ms, 0, sizeof(params)); params.tmap = tmap; params.tclass = tclass; Material_Prepare(&ms, mat, true, ¶ms); GL_BindTexture(ms.units[MTU_PRIMARY].texInst->id, ms.units[MTU_PRIMARY].magMode); } /** * @return The outcome: * 0 = not prepared * 1 = found and prepared a lump resource. * 2 = found and prepared an external resource. */ byte GL_LoadRawTex(image_t* image, const rawtex_t* r) { byte result = 0; filename_t fileName; if(!image) return result; // Wha? // First try to find an external resource. if(R_FindResource2(RT_GRAPHIC, DDRC_PATCH, fileName, W_LumpName(r->lump), NULL, FILENAME_T_MAXLEN) && GL_LoadImage(image, fileName) != NULL) { // High resolution rawtex loaded. result = 2; } else { // Must load the old-fashioned data lump. const byte* lumpdata; size_t bufSize, lumpLength = W_LumpLength(r->lump); // Load the raw image data. lumpdata = W_CacheLumpNum(r->lump, PU_STATIC); image->width = 320; image->height = 200; // Try to load it as a PCX image first. bufSize = 3 * image->width * image->height; image->pixels = M_Malloc(bufSize); if(PCX_MemoryLoad(lumpdata, lumpLength, image->width, image->height, image->pixels)) { image->pixelSize = 3; } else { // PCX load failed. It must be an old-fashioned raw image. memcpy(image->pixels, lumpdata, MIN_OF(bufSize, lumpLength)); image->height = (int) (lumpLength / image->width); image->pixelSize = 1; } W_ChangeCacheTag(r->lump, PU_CACHE); result = 1; } return result; } /** * Raw images are always 320x200. * * 2003-05-30 (skyjake): External resources can be larger than 320x200, * but they're never split into two parts. */ DGLuint GL_PrepareRawTex2(rawtex_t* raw) { if(!raw) return 0; // Wha? if(raw->lump < 0 || raw->lump >= numLumps) { GL_BindTexture(0, 0); return 0; } if(!raw->tex) { image_t image; byte result; // Clear any old values. memset(&image, 0, sizeof(image)); if((result = GL_LoadRawTex(&image, raw)) == 2) { // Loaded an external raw texture. // We have the image in the buffer. We'll upload it as one // big texture. raw->tex = GL_UploadTexture(image.pixels, image.width, image.height, image.pixelSize == 4, false, true, false, false, GL_NEAREST, (linearRaw ? GL_LINEAR : GL_NEAREST), 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, (image.pixelSize == 4? TXCF_APPLY_GAMMACORRECTION : 0)); raw->width = 320; raw->width2 = 0; raw->tex2 = 0; raw->height = raw->height2 = 200; GL_DestroyImage(&image); } else { int assumedWidth = 320; boolean rgbdata = (image.pixelSize > 1? true:false); // It's most efficient to create two textures (256+64 = 320). if(!(image.height < 200)) { int k, comps = image.pixelSize; byte* dat1, *dat2; // Two pieces: dat1 = M_Calloc(comps * 256 * 256); dat2 = M_Calloc(comps * 64 * 256); // Image data loaded, divide it into two parts. for(k = 0; k < image.height; ++k) { int i; for(i = 0; i < 256; ++i) { int c, idx = k * assumedWidth + i; // Part one. for(c = 0; c < comps; ++c) { dat1[(k * 256 + i) * comps + c] = image.pixels[idx * comps + c]; // We can setup part two at the same time. dat2[(k * 64 + i) * comps + c] = image.pixels[(idx + 256) * comps + c]; } } } // Upload part one. raw->tex = GL_UploadTexture(dat1, 256, assumedWidth < 320 ? image.height : 256, false, false, rgbdata, false, false, GL_NEAREST, (linearRaw? GL_LINEAR:GL_NEAREST), 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, (rgbdata? TXCF_APPLY_GAMMACORRECTION : 0)); // And the other part. raw->tex2 = GL_UploadTexture(dat2, 64, 256, false, false, rgbdata, false, false, GL_NEAREST, (linearRaw? GL_LINEAR:GL_NEAREST), 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, (rgbdata? TXCF_APPLY_GAMMACORRECTION : 0)); raw->width = 256; raw->width2 = 64; raw->height = raw->height2 = image.height; M_Free(dat1); M_Free(dat2); } else // We can use the normal one-part method. { assumedWidth = 256; // Generate a texture. raw->tex = GL_UploadTexture(image.pixels, 256, image.height, false, false, rgbdata, false, false, GL_NEAREST, (linearRaw? GL_LINEAR:GL_NEAREST), 0 /*no anisotropy*/, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, (rgbdata? TXCF_APPLY_GAMMACORRECTION : 0)); raw->width = 256; raw->height = image.height; raw->tex2 = 0; raw->width2 = raw->height2 = 0; } GL_DestroyImage(&image); } } return raw->tex; } /** * Returns the OpenGL name of the texture. */ DGLuint GL_PrepareRawTex(rawtex_t* rawTex) { if(rawTex) { if(!rawTex->tex) { // The rawtex isn't yet bound with OpenGL. rawTex->tex = GL_PrepareRawTex2(rawTex); } return rawTex->tex; } return 0; } /** * Returns the OpenGL name of the texture. */ DGLuint GL_PrepareRawTexOtherPart(rawtex_t* rawTex) { if(rawTex) { if(!rawTex->tex) { // The rawtex isn't yet bound with OpenGL. rawTex->tex = GL_PrepareRawTex2(rawTex); } return rawTex->tex2; } return 0; } void GL_SetRawImage(lumpnum_t lump, boolean part2, int wrapS, int wrapT) { rawtex_t* rawTex; if((rawTex = R_GetRawTex(lump))) { DGLuint tex; if(!part2) tex = GL_PrepareRawTex(rawTex); else tex = GL_PrepareRawTexOtherPart(rawTex); GL_BindTexture(tex, (linearRaw ? GL_LINEAR : GL_NEAREST)); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); } } DGLuint GL_GetLightMapTexture(const char* name) { lightmap_t* lmap; if(name && name[0]) { if(name[0] == '-') return 0; if((lmap = R_GetLightMap(name))) { const gltexture_inst_t* texInst; if((texInst = GL_PrepareGLTexture(lmap->id, NULL, NULL))) return texInst->id; } } // Return the default texture name. return GL_PrepareLSTexture(LST_DYNAMIC); } #if 0 /** * Flare textures are normally monochrome images but we'll allow full color. */ void GL_LoadFlareTexture(ded_flaremap_t* map, int oldidx) { boolean loaded = false; if(map->tex) return; // Already loaded. // Default texture (automatic). map->tex = 0; if(!strcmp(map->id, "-")) { // We don't know where to find the texture. map->tex = 0; map->disabled = true; map->custom = false; loaded = true; } else if(map->id[0]) // Not an empty string. { // A custom flare texture map->custom = true; map->disabled = false; if prepareFails setChosenTexture to default; } if(!loaded) { // External resource not found. // Perhaps a "built-in" flare texture id? char* end; int id = 0, pass; boolean ok; // First pass: // Try to convert str "map->tex" to a flare tex constant idx // Second pass: // Use oldidx (if available) as a flare tex constant idx for(pass = 0; pass < 2 && !loaded; ++pass) { ok = false; if(pass == 0 && map->id[0]) { id = strtol(map->id, &end, 0); if(!(*end && !isspace(*end))) ok = true; } else if(pass == 1 && oldIdx != -1) { id = oldIdx; ok = true; } if(ok) { // Yes it is! // Maybe Automatic OR dynlight? if(id == 0 || id == 1) { map->tex = (id? GL_PrepareLSTexture(LST_DYNAMIC) : 0); map->custom = false; map->disabled = false; loaded = true; } else { id -= 2; if(id >= 0 && id < NUM_FLARE_TEXTURES) { map->tex = GL_PrepareFlareTexture(id); map->custom = false; map->disabled = false; loaded = true; } } } } } } #endif /** * Attempt to locate and prepare a flare texture. * Somewhat more complicated than it needs to be due to the fact there * are two different selection methods. * * @param name Name of a flare texture or "0" to "4". * @param oldIdx Old method of flare texture selection, by id. */ DGLuint GL_GetFlareTexture(const char* name, int oldIdx) { if(name && name[0]) { flaretex_t* fTex; if(name[0] == '-' || (name[0] == '0' && !name[1])) return 0; // Use the automatic selection logic. if(name[0] >= '1' && name[0] <= '4' && !name[1]) return GL_PrepareSysFlareTexture(name[0] - '1'); if((fTex = R_GetFlareTexture(name))) { const gltexture_inst_t* texInst; if((texInst = GL_PrepareGLTexture(fTex->id, NULL, NULL))) return texInst->id; } } else if(oldIdx > 0 && oldIdx < NUM_SYSFLARE_TEXTURES) { return GL_PrepareSysFlareTexture(oldIdx-1); } return 0; // Use the automatic selection logic. } /** * @param pixels RGBA data. Input read here, and output written here. * @param width Width of the buffer. * @param height Height of the buffer. */ static void BlackOutlines(byte* pixels, int width, int height) { short* dark = M_Calloc(width * height * 2); int x, y; int a, b; byte* pix; for(y = 1; y < height - 1; ++y) { for(x = 1; x < width - 1; ++x) { pix = pixels + (x + y * width) * 4; if(pix[3] > 128) // Not transparent. { // Apply darkness to surrounding transparent pixels. for(a = -1; a <= 1; ++a) { for(b = -1; b <= 1; ++b) { byte* other = pix + (a + b * width) * 4; if(other[3] < 128) // Transparent. { dark[(x + a) + (y + b) * width] += 40; } } } } } } // Apply the darkness. for(a = 0, pix = pixels; a < width * height; ++a, pix += 4) { uint c = pix[3] + dark[a]; pix[3] = MIN_OF(255, c); } // Release temporary storage. M_Free(dark); } #if 0 // Currently unused. static void EnhanceContrast(byte *pixels, int width, int height) { int i, c; byte* pix; for(i = 0, pix = pixels; i < width * height; ++i, pix += 4) { for(c = 0; c < 3; ++c) { float f = pix[c]; if(f < 90) // Darken dark parts. f = (f - 90) * 3 + 90; else if(f > 200) // Lighten light parts. f = (f - 200) * 2 + 200; pix[c] = MINMAX_OF(0, f, 255); } } } #endif static void SharpenPixels(byte* pixels, int width, int height) { int x, y, c; byte* result = M_Calloc(4 * width * height); const float strength = .05f; float A, B, C; A = strength; B = .70710678 * strength; // 1/sqrt(2) C = 1 + 4*A + 4*B; for(y = 1; y < height - 1; ++y) { for(x = 1; x < width -1; ++x) { byte* pix = pixels + (x + y*width) * 4; byte* out = result + (x + y*width) * 4; for(c = 0; c < 3; ++c) { int r = (C*pix[c] - A*pix[c - width] - A*pix[c + 4] - A*pix[c - 4] - A*pix[c + width] - B*pix[c + 4 - width] - B*pix[c + 4 + width] - B*pix[c - 4 - width] - B*pix[c - 4 + width]); out[c] = MINMAX_OF(0, r, 255); } out[3] = pix[3]; } } memcpy(pixels, result, 4 * width * height); M_Free(result); } /** * \note: No mipmaps are generated for regular patches. */ DGLuint GL_PreparePatch2(patchtex_t* p) { if(!p->tex) { image_t image; byte result; if(p->lump < 0 || p->lump >= numLumps) { GL_BindTexture(0, 0); return 0; } { lumppatch_t* patch; patch = (lumppatch_t*) W_CacheLumpNum(p->lump, PU_CACHE); p->offX = -SHORT(patch->leftOffset); p->offY = -SHORT(patch->topOffset); p->extraOffset[VX] = p->extraOffset[VY] = 0; p->width = SHORT(patch->width); p->height = SHORT(patch->height); } if((result = GL_LoadDoomPatch(&image, p)) == 2) { // High resolution patch loaded. // This is our texture! No mipmaps are generated. p->tex = GL_UploadTexture(image.pixels, image.width, image.height, image.pixelSize == 4, false, true, false, false, GL_NEAREST, glmode[texMagMode], texAniso, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); // The original image is no longer needed. GL_DestroyImage(&image); } else if(result == 1) { // Using data from the normal lump. boolean scaleSharp = (upscaleAndSharpenPatches || (p->flags & PF_UPSCALE_AND_SHARPEN)); int addBorder = (scaleSharp? 1 : 0); int numpels = image.width * image.height; if(fillOutlines && !scaleSharp) ColorOutlines(image.pixels, image.width, image.height); if(monochrome || (p->flags & PF_MONOCHROME)) { DGLuint pal = R_GetColorPalette(0); GL_DeSaturatePalettedImage(image.pixels, pal, image.width, image.height); p->flags |= PF_MONOCHROME; } if(scaleSharp) { byte* rgbaPixels = M_Malloc(numpels * 4 * 2); byte* upscaledPixels = M_Malloc(numpels * 4 * 4); GL_ConvertBuffer(image.width, image.height, 2, 4, image.pixels, rgbaPixels, 0, false); GL_SmartFilter2x(rgbaPixels, upscaledPixels, image.width, image.height, image.width * 8); image.width *= 2; image.height *= 2; //EnhanceContrast(upscaledPixels, image.width,image.height); SharpenPixels(upscaledPixels, image.width, image.height); BlackOutlines(upscaledPixels, image.width, image.height); // Back to indexed+alpha. GL_ConvertBuffer(image.width, image.height, 4, 2, upscaledPixels, rgbaPixels, 0, false); // Replace the old buffer. M_Free(upscaledPixels); M_Free(image.pixels); image.pixels = rgbaPixels; // We'll sharpen it in the future as well. p->flags |= PF_UPSCALE_AND_SHARPEN; } /** * See if we have to split the patch into two parts. * This is done to conserve the quality of wide textures (like * the DOOM status bar) on video cards that have a pitifully * small maximum texture size. */ if(p->width > GL_state.maxTexSize) { // The width of the first part is max texture size. int part2Width; byte* tmpBuf; part2Width = image.width - GL_state.maxTexSize; tmpBuf = M_Malloc(2 * image.height * MAX_OF(GL_state.maxTexSize, part2Width)); // Use a temporary buffer for doing the splitting. // First, part one. pixBlt(image.pixels, image.width, image.height, tmpBuf, GL_state.maxTexSize, image.height, image.isMasked, 0, 0, 0, 0, GL_state.maxTexSize, image.height); p->tex = GL_UploadTexture(tmpBuf, GL_state.maxTexSize, image.height, image.isMasked, false, false, false, false, GL_NEAREST, GL_LINEAR, texAniso, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); // Then part two. pixBlt(image.pixels, image.width, image.height, tmpBuf, part2Width, image.height, image.isMasked, GL_state.maxTexSize, 0, 0, 0, part2Width, image.height); p->tex2 = GL_UploadTexture(tmpBuf, part2Width, image.height, image.isMasked, false, false, false, false, GL_NEAREST, glmode[texMagMode], texAniso, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); p->width2 = p->width - GL_state.maxTexSize; p->width = GL_state.maxTexSize; p->height2 = p->height; M_Free(tmpBuf); } else // We can use the normal one-part method. { // Generate a texture. p->tex = GL_UploadTexture(image.pixels, image.width, image.height, image.isMasked, false, false, false, false, GL_NEAREST, glmode[texMagMode], texAniso, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 0); p->width += addBorder*2; p->height += addBorder*2; p->extraOffset[VX] = -addBorder; p->extraOffset[VY] = -addBorder; p->tex2 = 0; p->width2 = p->height2 = 0; } // The original image is no longer needed. GL_DestroyImage(&image); } } return p->tex; } /** * Returns the OpenGL name of the texture. */ DGLuint GL_PreparePatch(patchtex_t* patchTex) { if(patchTex) { if(!patchTex->tex) { // The patch isn't yet bound with OpenGL. patchTex->tex = GL_PreparePatch2(patchTex); } return patchTex->tex; } return 0; } DGLuint GL_PreparePatchOtherPart(patchtex_t* patchTex) { if(patchTex) { if(!patchTex->tex) { // The patch isn't yet bound with OpenGL. patchTex->tex = GL_PreparePatch2(patchTex); } return patchTex->tex2; } return 0; } void GL_SetPatch(lumpnum_t lump, int wrapS, int wrapT) { GL_BindTexture(GL_PreparePatch(R_GetPatchTex(lump)), glmode[texMagMode]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapS); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapT); } /** * You should use glDisable(GL_TEXTURE_2D) instead of this. */ void GL_SetNoTexture(void) { glBindTexture(GL_TEXTURE_2D, 0); } static void setTextureMinMode(DGLuint tex, int minMode) { glBindTexture(GL_TEXTURE_2D, tex); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minMode); } void GL_SetRawTextureParams(int minMode) { rawtex_t** rawTexs, **ptr; rawTexs = R_CollectRawTexs(NULL); for(ptr = rawTexs; *ptr; ptr++) { rawtex_t* r = (*ptr); if(r->tex) // Is the texture loaded? setTextureMinMode(r->tex, minMode); if(r->tex2) // Is the texture loaded? setTextureMinMode(r->tex2, minMode); } Z_Free(rawTexs); } /** * Updates the textures, flats and sprites (gameTex) or the user * interface textures (patches and raw screens). */ void GL_SetTextureParams(int minMode, int gameTex, int uiTex) { if(gameTex) { GL_SetAllGLTexturesMinMode(minMode); } if(uiTex) { // Patch textures. { patchtex_t **patches, **ptr; patches = R_CollectPatchTexs(NULL); for(ptr = patches; *ptr; ptr++) { patchtex_t* p = (*ptr); if(p->tex) // Is the texture loaded? setTextureMinMode(p->tex, minMode); if(p->tex2) // Is the texture loaded? setTextureMinMode(p->tex2, minMode); } Z_Free(patches); } GL_SetRawTextureParams(minMode); } } void GL_UpdateTexParams(int mipmode) { mipmapping = mipmode; GL_SetTextureParams(glmode[mipmode], true, false); } /** * Called when changing the value of any cvar affecting texture quality which * can be actioned by simply changing texture paramaters i.e. does not require * flushing GL textures). * * @param unused Unused, must be signature compatible. */ void GL_DoUpdateTexParams(cvar_t *unused) { GL_SetTextureParams(glmode[mipmapping], true, true); } static int doTexReset(void* parm) { boolean usingBusyMode = *((boolean*) parm); if(usingBusyMode) Con_SetProgress(100); /// \todo re-upload ALL textures currently in use. GL_LoadSystemTextures(); if(usingBusyMode) { Con_SetProgress(200); Con_BusyWorkerEnd(); } return 0; } void GL_TexReset(void) { boolean useBusyMode = !Con_IsBusy(); GL_ClearTextureMemory(); Con_Printf("All DGL textures deleted.\n"); if(useBusyMode) { Con_InitProgress(200); Con_Busy(BUSYF_ACTIVITY | BUSYF_PROGRESS_BAR | (verbose? BUSYF_CONSOLE_OUTPUT : 0), "Reseting textures...", doTexReset, &useBusyMode); } else { doTexReset(&useBusyMode); } } /** * Called when changing the value of the texture gamma cvar. */ void GL_DoUpdateTexGamma(cvar_t *unused) { if(texInited) { calcGammaTable(); GL_InitPalettedTexture(); GL_TexReset(); } Con_Printf("Gamma correction set to %f.\n", texGamma); } /** * Called when changing the value of any cvar affecting texture quality which * in turn calls GL_TexReset. Added to remove the need for reseting manually. * * @param unused Unused. Must be signature compatible. */ void GL_DoTexReset(cvar_t* unused) { GL_TexReset(); } void GL_DoResetDetailTextures(cvar_t* unused) { GL_DeleteAllTexturesForGLTextures(GLT_DETAIL); } /** * To save texture memory, delete all raw image textures. Raw images are * used as interlude backgrounds, title screens, etc. Called from * DD_SetupLevel. */ void GL_DeleteRawImages(void) { rawtex_t** rawTexs, **ptr; rawTexs = R_CollectRawTexs(NULL); for(ptr = rawTexs; *ptr; ptr++) { rawtex_t* r = (*ptr); if(r->tex) { glDeleteTextures(1, (const GLuint*) &r->tex); r->tex = 0; } if(r->tex2) { glDeleteTextures(1, (const GLuint*) &r->tex2); r->tex2 = 0; } } Z_Free(rawTexs); } /** * Calculates texture coordinates based on the given dimensions. The * coordinates are calculated as width/CeilPow2(width), or 1 if the * CeilPow2 would go over glMaxTexSize. */ static void GL_SetTexCoords(float *tc, int wid, int hgt) { int pw = M_CeilPow2(wid), ph = M_CeilPow2(hgt); if(pw > GL_state.maxTexSize || ph > GL_state.maxTexSize) tc[VX] = tc[VY] = 1; else { tc[VX] = wid / (float) pw; tc[VY] = hgt / (float) ph; } } /** * Returns true if the given path name refers to an image, which should * be color keyed. Color keying is done for both (0,255,255) and * (255,0,255). */ boolean GL_IsColorKeyed(const char* path) { filename_t buf; strncpy(buf, path, FILENAME_T_MAXLEN); strlwr(buf); return strstr(buf, "-ck.") != NULL; } void GL_SetMaterial(material_t* mat) { material_snapshot_t ms; if(!mat) return; Material_Prepare(&ms, mat, true, NULL); GL_BindTexture(ms.units[MTU_PRIMARY].texInst->id, ms.units[MTU_PRIMARY].magMode); } /** * This is a hash function. Given a gltexture name it generates a * somewhat-random number between 0 and GLTEXTURE_NAME_HASH_SIZE. * * @return The generated hash index. */ static uint hashForGLTextureName(const char* name) { ushort key = 0; int i; // Stop when the name ends. for(i = 0; *name; ++i, name++) { if(i == 0) key ^= (int) (*name); else if(i == 1) key *= (int) (*name); else if(i == 2) { key -= (int) (*name); i = -1; } } return key % GLTEXTURE_NAME_HASH_SIZE; } /** * Given a name and gltexture type, search the gltextures db for a match. * \assume Caller knows what it's doing; params arn't validity checked. * * @param name Name of the gltexture to search for. Must have been * transformed to all lower case. * @param type Specific GLT_* gltexture type. * @return Ptr to the found gltexture_t else, @c NULL. */ static gltexture_t* getGLTextureByName(const char* name, uint hash, gltexture_type_t type) { // Go through the candidates. if(glTextureTypeData[type].hashTable[hash]) { gltexture_t* tex = glTextures[glTextureTypeData[type].hashTable[hash] - 1]; for(;;) { if(tex->type == type && !strncmp(tex->name, name, 8)) return tex; if(!tex->hashNext) break; tex = glTextures[tex->hashNext - 1]; } } return 0; // Not found. } static __inline gltexture_t* getGLTexture(gltextureid_t id) { if(id != 0 && id <= numGLTextures) return glTextures[id - 1]; return NULL; } /** * Updates the minification mode of ALL gltextures. * * @param minMode The DGL minification mode to set. */ void GL_SetAllGLTexturesMinMode(int minMode) { uint i; for(i = 0; i < numGLTextures; ++i) { GLTexture_SetMinMode(glTextures[i], minMode); } } const gltexture_t* GL_CreateGLTexture(const char* rawName, int ofTypeID, gltexture_type_t type) { uint i; gltexture_t* tex; if(!rawName || !rawName[0]) return NULL; #if _DEBUG if(type < GLT_SYSTEM || !(type < NUM_GLTEXTURE_TYPES)) Con_Error("GL_CreateGLTexture: Invalid type %i.", type); #endif // Check if we've already created a gltexture for this. for(i = 0; i < numGLTextures; ++i) { tex = glTextures[i]; if(tex->type == type && tex->ofTypeID == ofTypeID) { GLTexture_ReleaseTextures(tex); return tex; // Yep, return it. } } /** * A new gltexture. */ tex = Z_Malloc(sizeof(*tex), PU_STATIC, 0); tex->type = type; tex->ofTypeID = ofTypeID; tex->instances = NULL; tex->id = numGLTextures + 1; // 1-based index. // Prepare 'name'. for(i = 0; *rawName && i < 8; ++i, rawName++) tex->name[i] = tolower(*rawName); tex->name[i] = '\0'; // We also hash the name for faster searching. { uint hash = hashForGLTextureName(tex->name); tex->hashNext = glTextureTypeData[type].hashTable[hash]; glTextureTypeData[type].hashTable[hash] = numGLTextures + 1; // 1-based index. } /** * Link the new gltexture into the global list of gltextures. */ // Resize the existing list. glTextures = Z_Realloc(glTextures, sizeof(gltexture_t*) * ++numGLTextures, PU_STATIC); // Add the new gltexture; glTextures[numGLTextures - 1] = tex; return tex; } const gltexture_inst_t* GL_PrepareGLTexture(gltextureid_t id, void* context, byte* result) { return GLTexture_Prepare(getGLTexture(id), context, result); } void GL_ReleaseGLTexture(gltextureid_t id) { GLTexture_ReleaseTextures(getGLTexture(id)); } /** * Deletes all OpenGL texture instances for ALL gltextures. */ void GL_DeleteAllTexturesForGLTextures(gltexture_type_t type) { uint i; if(type != GLT_ANY && (type < 0 || type > NUM_GLTEXTURE_TYPES)) Con_Error("GL_DeleteAllTexturesForGLTextures: Internal error, " "invalid type %i.", (int) type); for(i = 0; i < numGLTextures; ++i) { gltexture_t* tex = glTextures[i]; if(type != GLT_ANY && tex->type != type) continue; GLTexture_ReleaseTextures(tex); } } const gltexture_t* GL_GetGLTexture(gltextureid_t id) { return getGLTexture(id); } const gltexture_t* GL_GetGLTextureByName(const char* rawName, gltexture_type_t type) { int n; uint hash; char name[9]; if(!rawName || !rawName[0]) return NULL; // Prepare 'name'. for(n = 0; *rawName && n < 8; ++n, rawName++) name[n] = tolower(*rawName); name[n] = '\0'; hash = hashForGLTextureName(name); return getGLTextureByName(name, hash, type); } static gltexture_inst_t* pickGLTextureInst(gltexture_t* tex, void* context) { gltexture_inst_node_t* node; material_load_params_t* params = (material_load_params_t*) context; int flags = 0; if(params) flags = params->flags; node = (gltexture_inst_node_t*) tex->instances; while(node) { if(node->flags == flags) return &node->inst; node = node->next; } return NULL; } static gltexture_inst_t* pickDetailTextureInst(gltexture_t* tex, void* context) { gltexture_inst_node_t* node; float contrast = *((float*) context); // Round off the contrast to nearest 0.1. contrast = (int) ((contrast + .05f) * 10) / 10.f; node = (gltexture_inst_node_t*) tex->instances; while(node) { if(node->inst.data.detail.contrast == contrast) return &node->inst; node = node->next; } return NULL; } static gltexture_inst_t* pickSpriteTextureInst(gltexture_t* tex, void* context) { gltexture_inst_node_t* node; material_load_params_t* params = (material_load_params_t*) context; int tmap = 0, tclass = 0; boolean pSprite = false; if(params) { tmap = params->tmap; tclass = params->tclass; pSprite = params->pSprite; } node = (gltexture_inst_node_t*) tex->instances; while(node) { if(node->inst.data.sprite.pSprite == pSprite && node->inst.data.sprite.tmap == tmap && node->inst.data.sprite.tclass == tclass) return &node->inst; node = node->next; } return NULL; } gltexture_inst_t* GLTexture_Prepare(gltexture_t* tex, void* context, byte* result) { byte tmpResult; gltexture_inst_t* texInst = NULL; if(tex->type < GLT_SYSTEM || tex->type >= NUM_GLTEXTURE_TYPES) { Con_Error("GLTexture_Prepare: Internal error, invalid type %i.", (int) tex->type); } switch(tex->type) { case GLT_DETAIL: texInst = pickDetailTextureInst(tex, context); break; case GLT_SPRITE: texInst = pickSpriteTextureInst(tex, context); break; default: texInst = pickGLTextureInst(tex, context); break; } if(texInst && texInst->id) { // Already prepared. tmpResult = 0; } else { boolean didDefer = false; image_t image; gltexture_typedata_t* glTexType = &glTextureTypeData[tex->type]; gltexture_inst_t localInst; if(!texInst) { // No existing suitable instance. // Use a temporary local instance until we are sure preparation // completes successfully. memset(&localInst, 0, sizeof(localInst)); localInst.tex = tex; texInst = &localInst; } memset(&image, 0, sizeof(image)); // Load in the raw source image. if(!(tmpResult = glTexType->loadData(&image, texInst, context))) { // Source image not loaded. return NULL; } // Too big for us? if(image.width > GL_state.maxTexSize || image.height > GL_state.maxTexSize) { if(image.pixelSize == 3 || image.pixelSize == 4) { int newWidth = MIN_OF(image.width, GL_state.maxTexSize); int newHeight = MIN_OF(image.height, GL_state.maxTexSize); byte *temp = M_Malloc(newWidth * newHeight * image.pixelSize); GL_ScaleBuffer32(image.pixels, image.width, image.height, temp, newWidth, newHeight, image.pixelSize); M_Free(image.pixels); image.pixels = temp; image.width = newWidth; image.height = newHeight; } else { Con_Message("GLTexture_Prepare: Warning, non RGB(A) " "texture larger than max size (%ix%i bpp%i).\n", image.width, image.height, image.pixelSize); } } if(tex->type == GLT_SPRITE || tex->type == GLT_DOOMTEXTURE) { if(image.pixelSize == 1 && fillOutlines /*&& image.isMasked*/) ColorOutlines(image.pixels, image.width, image.height); } // Lightmaps and flare textures should be monochrome images. if((tex->type == GLT_LIGHTMAP || (tex->type == GLT_FLARE && image.pixelSize != 4)) && !image.isMasked) { // An alpha channel is required. If one is not in the // image data, we'll generate it. GL_ConvertToAlpha(&image, true); } switch(tex->type) { case GLT_FLAT: if(tmpResult) { texturecontent_t content; GL_InitTextureContent(&content); content.buffer = image.pixels; content.format = (tmpResult == 2? (image.pixelSize == 4? DGL_RGBA : DGL_RGB) : (image.pixelSize == 4? DGL_COLOR_INDEX_8_PLUS_A8 : DGL_COLOR_INDEX_8)); content.width = image.width; content.height = image.height; content.flags = TXCF_EASY_UPLOAD | TXCF_MIPMAP; if(image.pixelSize > 1) content.flags |= TXCF_APPLY_GAMMACORRECTION; if(image.pixelSize == 4) content.flags |= TXCF_UPLOAD_ARG_ALPHACHANNEL; if(tmpResult == 2) content.flags |= TXCF_UPLOAD_ARG_RGBDATA; content.minFilter = glmode[mipmapping]; content.magFilter = glmode[texMagMode]; content.anisoFilter = texAniso; content.wrap[0] = GL_REPEAT; content.wrap[1] = GL_REPEAT; texInst->id = GL_NewTexture(&content, &didDefer); if(image.isMasked) texInst->flags |= GLTF_MASKED; } break; case GLT_DOOMTEXTURE: if(tmpResult) { texturecontent_t content; int flags = 0; boolean noCompression = false; boolean alphaChannel; if(image.pixelSize > 1) flags |= TXCF_APPLY_GAMMACORRECTION; // Disable compression? if(context) { material_load_params_t* params = (material_load_params_t*) context; if(params->flags & MLF_TEX_NO_COMPRESSION) flags |= TXCF_NO_COMPRESSION; } alphaChannel = ((tmpResult == 2 && image.pixelSize == 4) || (tmpResult == 1 && image.isMasked))? true : false; GL_InitTextureContent(&content); content.buffer = image.pixels; content.format = (tmpResult == 2? (alphaChannel? DGL_RGBA : DGL_RGB) : (alphaChannel? DGL_COLOR_INDEX_8_PLUS_A8 : DGL_COLOR_INDEX_8)); content.width = image.width; content.height = image.height; content.flags = TXCF_EASY_UPLOAD | TXCF_MIPMAP | flags; if(alphaChannel) content.flags |= TXCF_UPLOAD_ARG_ALPHACHANNEL; if(tmpResult == 2) content.flags |= TXCF_UPLOAD_ARG_RGBDATA; content.minFilter = glmode[mipmapping]; content.magFilter = glmode[texMagMode]; content.anisoFilter = texAniso; content.wrap[0] = GL_REPEAT; content.wrap[1] = GL_REPEAT; texInst->id = GL_NewTexture(&content, &didDefer); if(image.isMasked) texInst->flags |= GLTF_MASKED; } break; case GLT_SPRITE: case GLT_DETAIL: case GLT_SYSTEM: case GLT_SHINY: case GLT_MASK: case GLT_MODELSKIN: case GLT_MODELSHINYSKIN: case GLT_LIGHTMAP: case GLT_FLARE: if(tmpResult) { texturecontent_t c; GL_InitTextureContent(&c); if(tex->type == GLT_SPRITE) { c.format = ( image.pixelSize > 1? ( image.pixelSize != 3? DGL_RGBA : DGL_RGB) : ( image.pixelSize != 3? DGL_COLOR_INDEX_8_PLUS_A8 : DGL_COLOR_INDEX_8 ) ); } else if(tex->type == GLT_MODELSKIN || tex->type == GLT_MODELSHINYSKIN) { c.format = (image.pixelSize == 4? DGL_RGBA : DGL_RGB); } else { c.format = ( image.pixelSize == 2 ? DGL_LUMINANCE_PLUS_A8 : image.pixelSize == 3 ? DGL_RGB : image.pixelSize == 4 ? DGL_RGBA : DGL_LUMINANCE ); } c.width = image.width; c.height = image.height; c.buffer = image.pixels; c.flags = 0; // Disable compression? if((image.width < 128 && image.height < 128) || tex->type == GLT_FLARE || tex->type == GLT_SHINY) c.flags |= TXCF_NO_COMPRESSION; if(context && (tex->type == GLT_LIGHTMAP || tex->type == GLT_MODELSKIN || tex->type == GLT_MODELSHINYSKIN)) { material_load_params_t* params = (material_load_params_t*) context; if(params->flags & MLF_TEX_NO_COMPRESSION) c.flags |= TXCF_NO_COMPRESSION; } if(tex->type == GLT_SPRITE || tex->type == GLT_MODELSKIN || tex->type == GLT_MODELSHINYSKIN || tex->type == GLT_LIGHTMAP || tex->type == GLT_FLARE) { c.flags |= TXCF_EASY_UPLOAD; if(tex->type == GLT_SPRITE) c.flags |= TXCF_UPLOAD_ARG_NOSTRETCH; if(image.pixelSize != 3) c.flags |= TXCF_UPLOAD_ARG_ALPHACHANNEL; if(tex->type != GLT_LIGHTMAP && tex->type != GLT_FLARE) if(image.pixelSize > 1) c.flags |= TXCF_UPLOAD_ARG_RGBDATA; } if(tex->type == GLT_MODELSKIN) c.flags |= TXCF_APPLY_GAMMACORRECTION; if(tex->type == GLT_DETAIL) { float contrast = *((float*) context); /** * Detail textures are faded to gray depending on the contrast * factor. The texture is also progressively faded towards gray * when each mipmap level is loaded. */ // Round off the contrast to nearest 0.1. contrast = (int) ((contrast + .05f) * 10) / 10.f; c.grayMipmap = MINMAX_OF(0, contrast * 255, 255); c.flags |= TXCF_GRAY_MIPMAP | (c.grayMipmap << TXCF_GRAY_MIPMAP_LEVEL_SHIFT); c.minFilter = GL_LINEAR_MIPMAP_LINEAR; texInst->data.detail.contrast = contrast; } else if(tex->type == GLT_SPRITE || tex->type == GLT_MASK || tex->type == GLT_MODELSKIN || tex->type == GLT_MODELSHINYSKIN || tex->type == GLT_SYSTEM) { c.flags |= TXCF_MIPMAP; c.minFilter = glmode[mipmapping]; } else { c.minFilter = GL_LINEAR; } c.magFilter = (tex->type == GLT_MASK? glmode[texMagMode] : tex->type == GLT_SPRITE? (filterSprites ? GL_LINEAR : GL_NEAREST) : GL_LINEAR); if(tex->type == GLT_FLARE) c.anisoFilter = 0 /*no anisotropy*/; else c.anisoFilter = texAniso; if(tex->type == GLT_SPRITE || tex->type == GLT_LIGHTMAP || tex->type == GLT_FLARE) c.wrap[0] = c.wrap[1] = GL_CLAMP_TO_EDGE; else c.wrap[0] = c.wrap[1] = GL_REPEAT; texInst->id = GL_NewTexture(&c, &didDefer); } break; default: break; } if(!didDefer) { #ifdef _DEBUG Con_Message("GLTexture_Prepare: Uploaded \"%s\" (%i) while not busy! " "Should be precached in busy mode?\n", texInst->tex->name, texInst->id); #endif } if(tex->type == GLT_SPRITE) { material_load_params_t* params = (material_load_params_t*) context; int tmap = 0, tclass = 0; boolean pSprite = false; if(params) { tmap = params->tmap; tclass = params->tclass; pSprite = params->pSprite; } texInst->data.sprite.tmap = tmap; texInst->data.sprite.tclass = tclass; texInst->data.sprite.pSprite = pSprite; if(image.isMasked) texInst->flags |= GLTF_MASKED; if(!pSprite) { // Calculate light source properties. GL_CalcLuminance(image.pixels, image.width, image.height, image.pixelSize, 0, &texInst->data.sprite.flareX, &texInst->data.sprite.flareY, &texInst->data.sprite.autoLightColor, &texInst->data.sprite.lumSize); } // Determine coordinates for the texture. GL_SetTexCoords(texInst->data.sprite.texCoord, image.width, image.height); } if(tex->type == GLT_FLAT || tex->type == GLT_DOOMTEXTURE) { // Average color for glow planes and top line color. if(image.pixelSize > 1) { averageColorRGB(texInst->data.texture.color, image.pixels, image.width, image.height); lineAverageColorRGB(texInst->data.texture.topColor, image.pixels, image.width, image.height, 0); } else { averageColorIdx(texInst->data.texture.color, image.pixels, image.width, image.height, 0, false); lineAverageColorIdx(texInst->data.texture.topColor, image.pixels, image.width, image.height, 0, 0, false); } } GL_DestroyImage(&image); if(tmpResult && texInst == &localInst) { // We have a new instance. int flags = 0; gltexture_inst_node_t* node; if(tex->type != GLT_DETAIL) { material_load_params_t* params = (material_load_params_t*) context; if(params) flags = params->flags; } // Add it to the list of intances for this gltexture. node = Z_Malloc(sizeof(*node), PU_STATIC, 0); memcpy(&node->inst, &localInst, sizeof(gltexture_inst_t)); node->flags = flags; node->next = (gltexture_inst_node_t*) tex->instances; tex->instances = (void*) node; texInst = &node->inst; } } if(result) *result = tmpResult; return texInst; } boolean GLTexture_IsFromIWAD(const gltexture_t* tex) { switch(tex->type) { case GLT_FLAT: return W_IsFromIWAD(flats[tex->ofTypeID]->lump); case GLT_DOOMTEXTURE: return (R_GetDoomTextureDef(tex->ofTypeID)->flags & TXDF_IWAD)? true : false; case GLT_SPRITE: return W_IsFromIWAD(spriteTextures[tex->ofTypeID]->lump); case GLT_DETAIL: case GLT_SHINY: case GLT_MASK: case GLT_SYSTEM: case GLT_MODELSKIN: case GLT_MODELSHINYSKIN: case GLT_LIGHTMAP: case GLT_FLARE: return false; // Its definitely not. default: Con_Error("updateGLTexture: Internal Error, invalid type %i.", (int) tex->type); } return false; // Unreachable. } float GLTexture_GetWidth(const gltexture_t* tex) { if(!tex) return 0; switch(tex->type) { case GLT_FLAT: return flats[tex->ofTypeID]->width; case GLT_DOOMTEXTURE: return R_GetDoomTextureDef(tex->ofTypeID)->width; case GLT_SPRITE: return spriteTextures[tex->ofTypeID]->width; case GLT_DETAIL: return 128; case GLT_SHINY: return 128; // Could be used for something useful. case GLT_MASK: return maskTextures[tex->ofTypeID]->width; case GLT_SYSTEM: /// \fixme Do not assume! case GLT_MODELSKIN: case GLT_MODELSHINYSKIN: case GLT_LIGHTMAP: case GLT_FLARE: return 64; default: Con_Error("GLTexture_GetWidth: Internal error, " "invalid material type %i.", (int) tex->type); } return 0; // Unreachable. } float GLTexture_GetHeight(const gltexture_t* tex) { if(!tex) return 0; switch(tex->type) { case GLT_FLAT: return flats[tex->ofTypeID]->height; case GLT_DOOMTEXTURE: return R_GetDoomTextureDef(tex->ofTypeID)->height; case GLT_SPRITE: return spriteTextures[tex->ofTypeID]->height; case GLT_DETAIL: return 128; case GLT_SHINY: return 128; // Could be used for something useful. case GLT_MASK: return maskTextures[tex->ofTypeID]->height; case GLT_SYSTEM: /// \fixme Do not assume! case GLT_MODELSKIN: case GLT_MODELSHINYSKIN: case GLT_LIGHTMAP: case GLT_FLARE: return 64; default: Con_Error("GLTexture_GetHeight: Internal error, " "invalid material type %i.", (int) tex->type); } return 0; // Unreachable. } /** * Deletes all GL texture instances for the specified gltexture. */ void GLTexture_ReleaseTextures(gltexture_t* tex) { if(tex) { gltexture_inst_node_t* node; // Delete all instances. node = (gltexture_inst_node_t*) tex->instances; while(node) { gltexture_inst_t* inst = &node->inst; if(inst->id) // Is the texture loaded? { glDeleteTextures(1, (const GLuint*) &inst->id); inst->id = 0; } node = node->next; } } } /** * Sets the minification mode of the specified gltexture. * * @param tex The gltexture to be updated. * @param minMode The GL minification mode to set. */ void GLTexture_SetMinMode(gltexture_t* tex, int minMode) { if(tex) { gltexture_inst_node_t* node; node = (gltexture_inst_node_t*) tex->instances; while(node) { gltexture_inst_t* inst = &node->inst; if(inst->id) // Is the texture loaded? { glBindTexture(GL_TEXTURE_2D, inst->id); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minMode); } node = node->next; } } } D_CMD(LowRes) { GL_LowRes(); return true; } #ifdef _DEBUG D_CMD(TranslateFont) { char name[32]; int i, lump; size_t size; lumppatch_t *patch; byte redToWhite[256]; if(argc < 3) return false; // Prepare the red-to-white table. for(i = 0; i < 256; ++i) { if(i == 176) redToWhite[i] = 168; // Full red -> white. else if(i == 45) redToWhite[i] = 106; else if(i == 46) redToWhite[i] = 107; else if(i == 47) redToWhite[i] = 108; else if(i >= 177 && i <= 191) { redToWhite[i] = 80 + (i - 177) * 2; } else redToWhite[i] = i; // No translation for this. } // Translate everything. for(i = 0; i < 256; ++i) { sprintf(name, "%s%.3d", argv[1], i); if((lump = W_CheckNumForName(name)) != -1) { Con_Message("%s...\n", name); size = W_LumpLength(lump); patch = M_Malloc(size); memcpy(patch, W_CacheLumpNum(lump, PU_CACHE), size); GL_TranslatePatch(patch, redToWhite); sprintf(name, "%s%.3d.lmp", argv[2], i); M_WriteFile(name, patch, size); M_Free(patch); } } return true; } #endif D_CMD(ResetTextures) { if(argc == 2 && !stricmp(argv[1], "raw")) { // Reset just raw images. GL_DeleteRawImages(); } else { // Reset everything. GL_TexReset(); } return true; } D_CMD(MipMap) { GL_UpdateTexParams(strtol(argv[1], NULL, 0)); return true; } D_CMD(SmoothRaw) { linearRaw = strtol(argv[1], NULL, 0) ? GL_LINEAR : GL_NEAREST; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_zip.c0000644000175000017500000005530711357170242022360 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_zip.h: Zip/Pk3 Files * * Loading .pk3/.zip files. * Finding files inside packages. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_defs.h" #include "de_platform.h" #include "de_console.h" #include "de_misc.h" #include "sys_direc.h" #include "r_extres.h" #include // MACROS ------------------------------------------------------------------ #define SIG_LOCAL_FILE_HEADER 0x04034b50 #define SIG_CENTRAL_FILE_HEADER 0x02014b50 #define SIG_END_OF_CENTRAL_DIR 0x06054b50 // Maximum tolerated size of the comment. #define MAXIMUM_COMMENT_SIZE 2048 // This is the length of the central directory end record (without the // comment, but with the signature). #define CENTRAL_END_SIZE 22 // File header flags. #define ZFH_ENCRYPTED 0x1 #define ZFH_COMPRESSION_OPTS 0x6 #define ZFH_DESCRIPTOR 0x8 #define ZFH_COMPRESS_PATCHED 0x20 // Not supported. // Compression methods. enum { ZFC_NO_COMPRESSION = 0, // Supported format. ZFC_SHRUNK, ZFC_REDUCED_1, ZFC_REDUCED_2, ZFC_REDUCED_3, ZFC_REDUCED_4, ZFC_IMPLODED, ZFC_DEFLATED = 8, // The only supported compression (via zlib). ZFC_DEFLATED_64, ZFC_PKWARE_DCL_IMPLODED }; // TYPES ------------------------------------------------------------------- typedef struct package_s { struct package_s *next; char *name; DFILE *file; uint order; } package_t; typedef struct zipentry_s { char *name; // Absolute path. package_t *package; uint offset; // Offset from the beginning of the package. size_t size; size_t deflatedSize; /* Size of the original deflated entry. If the entry is not compressed, this is set to zero. */ uint lastModified; // Unix timestamp. } zipentry_t; #pragma pack(1) typedef struct localfileheader_s { uint signature; ushort requiredVersion; ushort flags; ushort compression; ushort lastModTime; ushort lastModDate; uint crc32; uint compressedSize; uint size; ushort fileNameSize; ushort extraFieldSize; } localfileheader_t; typedef struct descriptor_s { uint crc32; uint compressedSize; uint size; } descriptor_t; typedef struct centralfileheader_s { uint signature; ushort version; ushort requiredVersion; ushort flags; ushort compression; ushort lastModTime; ushort lastModDate; uint crc32; uint compressedSize; uint size; ushort fileNameSize; ushort extraFieldSize; ushort commentSize; ushort diskStart; ushort internalAttrib; uint externalAttrib; uint relOffset; /* * file name (variable size) * extra field (variable size) * file comment (variable size) */ } centralfileheader_t; typedef struct centralend_s { ushort disk; ushort centralStartDisk; ushort diskEntryCount; ushort totalEntryCount; uint size; uint offset; ushort commentSize; } centralend_t; #pragma pack() // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void removeDuplicateFiles(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static package_t *zipRoot; static zipentry_t *zipFiles; static uint zipNumFiles, zipAllocatedFiles; // CODE -------------------------------------------------------------------- /** * Initializes the zip file database. */ void Zip_Init(void) { VERBOSE(Con_Message("Zip_Init: Initializing package system...\n")); zipRoot = NULL; zipFiles = 0; zipNumFiles = 0; zipAllocatedFiles = 0; } /** * Shuts down the zip file database and frees all resources. */ void Zip_Shutdown(void) { uint i; package_t *pack, *next; // Close package files and free the nodes. for(pack = zipRoot; pack; pack = next) { next = pack->next; if(pack->file) F_Close(pack->file); if(pack->name) M_Free(pack->name); M_Free(pack); } // Free the file directory. for(i = 0; i < zipNumFiles; ++i) M_Free(zipFiles[i].name); M_Free(zipFiles); zipRoot = NULL; zipFiles = NULL; zipNumFiles = 0; zipAllocatedFiles = 0; } /** * Allocate a zipentry array element and return a pointer to it. * Duplicate entries are removed later. */ static zipentry_t* newZipEntry(const char* name) { uint oldCount = zipNumFiles; boolean changed = false; zipNumFiles++; while(zipNumFiles > zipAllocatedFiles) { // Double the size of the array. zipAllocatedFiles *= 2; if(!zipAllocatedFiles) zipAllocatedFiles = 1; // Realloc the zipentry array. zipFiles = M_Realloc(zipFiles, sizeof(zipentry_t) * zipAllocatedFiles); changed = true; } // Clear the new memory. if(changed) { memset(&zipFiles[oldCount], 0, sizeof(zipentry_t) * (zipAllocatedFiles - oldCount)); } // Take a copy of the name. This is freed in Zip_Shutdown(). zipFiles[oldCount].name = M_Malloc(sizeof(char) * (strlen(name) + 1)); strcpy(zipFiles[oldCount].name, name); // Return a pointer to the first new zipentry. return &zipFiles[oldCount]; } /** * Sorts all the zip entries alphabetically. All the paths are absolute. */ int C_DECL Zip_EntrySorter(const void *a, const void *b) { // Compare the names. return stricmp(((const zipentry_t *) a)->name, ((const zipentry_t *) b)->name); } /** * Sorts all the zip entries alphabetically. */ static void sortZipEntries(void) { // Sort all the zipentries by name. (Note: When lots of files loaded, // most of list is already sorted. Quicksort becomes slow...) qsort(zipFiles, zipNumFiles, sizeof(zipentry_t), Zip_EntrySorter); } /** * Adds a new package to the list of packages. */ static package_t* newPackage(void) { // When duplicates are removed, newer packages are favored. static uint packageCounter = 0; package_t* newPack = M_Calloc(sizeof(package_t)); newPack->next = zipRoot; newPack->order = packageCounter++; return zipRoot = newPack; } /** * Finds the central directory end record in the end of the file. * Note: This gets awfully slow if the comment is long. * * @return @c true, if successful. */ static boolean locateCentralDirectory(DFILE *file) { int pos = CENTRAL_END_SIZE; // Offset from the end. uint signature; // Start from the earliest location where the signature might be. while(pos < MAXIMUM_COMMENT_SIZE) { F_Seek(file, -pos, SEEK_END); // Is this is signature? F_Read(&signature, 4, file); if(ULONG(signature) == SIG_END_OF_CENTRAL_DIR) { // This is it! return true; } // Move backwards. pos++; } // Scan was not successful. return false; } /** * Copies num characters (up to destSize) and adds a terminating NULL. */ static void copyStr(char* dest, const char* src, size_t num, size_t destSize) { // Only copy as much as we can. if(num >= destSize) num = destSize - 1; memcpy(dest, src, num); dest[num] = 0; } /** * The path inside the pack is mapped to another virtual location. * * Data files (pk3, zip, lmp, wad, deh) in the root are mapped to Data/Game/Auto. * Definition files (ded) in the root are mapped to Defs/Game/Auto. * Paths that begin with a '@' are mapped to Defs/Game/Auto. * Paths that begin with a '#' are mapped to Data/Game/Auto. * * DJS 05/05/05 * The folder in the root is mapped to another location * * Location is one of the following keynames. * Folder 'Models' is mapped to Data/Game/Models * Floder 'Flares' is mapped to Data/Game/Flares * Folder 'LightMaps' is mapped to Data/Game/LightMaps * Folder 'Music' is mapped to Data/Game/Music * Folder 'Textures' is mapped to Data/Game/Textures * Folder 'Flats' is mapped to Data/Game/Flats * Folder 'DetailTextures' is mapped to Data/Game/DetailTextures * Folder 'Patches' is mapped to Data/Game/Patches * Folder 'Sfx' is mapped to Data/Game/Sfx */ static void mapPath(char* path, size_t len) { filename_t mapped; if(strchr(path, DIR_SEP_CHAR) != NULL) { // There is at least one level of directory structure inside // the archive. // Check the beginning of the path. if(!strnicmp("Models" DIR_SEP_STR, path, 7) || !strnicmp("Flares" DIR_SEP_STR, path, 7) || !strnicmp("LightMaps" DIR_SEP_STR, path, 10) || !strnicmp("Music" DIR_SEP_STR, path, 6) || !strnicmp("Textures" DIR_SEP_STR, path, 9) || !strnicmp("Flats" DIR_SEP_STR, path, 6) || !strnicmp("DetailTextures" DIR_SEP_STR, path, 15) || !strnicmp("Patches" DIR_SEP_STR, path, 8) || !strnicmp("Sfx" DIR_SEP_STR, path, 4)) { // Contents mapped to keyname folder. dd_snprintf(mapped, FILENAME_T_MAXLEN, "%s%s", R_GetDataPath(), path); strncpy(path, mapped, len); return; } } if(path[0] == '@') // Manually mapped to Defs. { Def_GetAutoPath(mapped, FILENAME_T_MAXLEN); strcat(mapped, path + 1); strcpy(path, mapped); } else if(path[0] == '#') // Manually mapped to Data. { sprintf(mapped, "%sauto" DIR_SEP_STR "%s", R_GetDataPath(), path + 1); strcpy(path, mapped); } else if(strchr(path, DIR_SEP_CHAR) == NULL) { // The name contains no directory separators. // Check the extension. char *ext = strrchr(path, '.'); if(ext != NULL) { ++ext; if(!stricmp(ext, "pk3") || !stricmp(ext, "zip") || !stricmp(ext, "lmp") || !stricmp(ext, "wad") || !stricmp(ext, "deh")) { // Data files are mapped to the Data directory. sprintf(mapped, "%sauto" DIR_SEP_STR, R_GetDataPath()); } else if(!stricmp(ext, "ded")) { // Definitions are mapped to the Defs directory. Def_GetAutoPath(mapped, FILENAME_T_MAXLEN); } else { strncpy(mapped, "", FILENAME_T_MAXLEN); } strncat(mapped, path, FILENAME_T_MAXLEN); strncpy(path, mapped, len); } } } /** * Opens the file zip, reads the directory and stores the info for later * access. * * @param prevOpened If not @c NULL,, all data will be read * from there. */ boolean Zip_Open(const char* fileName, DFILE* prevOpened) { centralend_t summary; zipentry_t* entry; package_t* pack; void* directory; char* pos; filename_t buf; uint index; DFILE* file; if(prevOpened == NULL) { // Try to open the file. if((file = F_Open(fileName, "rb")) == NULL) { Con_Message("Zip_Open: %s not found.\n", fileName); return false; } } else { // Use the previously opened file. file = prevOpened; } VERBOSE(Con_Message("Zip_Open: %s\n", M_PrettyPath(fileName))); // Scan the end of the file for the central directory end record. if(!locateCentralDirectory(file)) { Con_Error("Zip_Open: %s: Central directory not found.\n", M_PrettyPath(fileName)); } // Read the central directory end record. F_Read(&summary, sizeof(summary), file); // Does the summary say something we don't like? if(USHORT(summary.diskEntryCount) != USHORT(summary.totalEntryCount)) { Con_Error("Zip_Open: %s: Multipart Zip files are not supported.\n", M_PrettyPath(fileName)); } // Read the entire central directory into memory. directory = M_Malloc(ULONG(summary.size)); F_Seek(file, ULONG(summary.offset), SEEK_SET); F_Read(directory, ULONG(summary.size), file); pack = newPackage(); pack->name = M_Malloc(sizeof(char) * (strlen(fileName) + 1)); strcpy(pack->name, fileName); pack->file = file; // Read all the entries. pos = directory; for(index = 0; index < USHORT(summary.totalEntryCount); ++index, pos += sizeof(centralfileheader_t)) { localfileheader_t localHeader; centralfileheader_t* header = (void *) pos; char* nameStart = pos + sizeof(centralfileheader_t); // Advance the cursor past the variable sized fields. pos += USHORT(header->fileNameSize) + USHORT(header->extraFieldSize) + USHORT(header->commentSize); copyStr(buf, nameStart, USHORT(header->fileNameSize), FILENAME_T_MAXLEN); // Directories are skipped. if(buf[USHORT(header->fileNameSize) - 1] == '/' && ULONG(header->size) == 0) continue; // Do we support the format of this file? if(USHORT(header->compression) != ZFC_NO_COMPRESSION && USHORT(header->compression) != ZFC_DEFLATED) { Con_Error("Zip_Open: %s: '%s' uses an unsupported compression " "algorithm.\n", M_PrettyPath(fileName), buf); } if(USHORT(header->flags) & ZFH_ENCRYPTED) { Con_Error("Zip_Open: %s: '%s' is encrypted.\n Encryption is " "not supported.\n", M_PrettyPath(fileName), buf); } // Convert all slashes to the host OS's directory separator, // for compatibility with the sys_filein routines. Dir_FixSlashes(buf, FILENAME_T_MAXLEN); // In some cases the path inside the pack is mapped to another // virtual location. mapPath(buf, FILENAME_T_MAXLEN); // Make it absolute. M_PrependBasePath(buf, buf, FILENAME_T_MAXLEN); // We can add this file to the zipentry list. entry = newZipEntry(buf); entry->package = pack; entry->size = ULONG(header->size); if(USHORT(header->compression) == ZFC_DEFLATED) { // Compressed using the deflate algorithm. entry->deflatedSize = ULONG(header->compressedSize); } else { // No compression. entry->deflatedSize = 0; } // The modification date is inherited from the real file (note // recursion). entry->lastModified = file->lastModified; // Read the local file header, which contains the correct // extra field size (Info-ZIP!). F_Seek(file, ULONG(header->relOffset), SEEK_SET); F_Read(&localHeader, sizeof(localHeader), file); entry->offset = ULONG(header->relOffset) + sizeof(localfileheader_t) + USHORT(header->fileNameSize) + USHORT(localHeader.extraFieldSize); } // The central directory is no longer needed. M_Free(directory); sortZipEntries(); removeDuplicateFiles(); // File successfully opened! return true; } /** * If two or more packages have the same file, the file from the last * loaded package is the one to use. Others will be removed from the * directory. The entries must be sorted before this can be done. */ static void removeDuplicateFiles(void) { uint i; boolean modified = false; zipentry_t* entry, *loser; if(!(zipNumFiles > 1)) return; // Obviously no duplicates. // One scan through the directory is enough. for(i = 0, entry = zipFiles; i < zipNumFiles - 1; ++i, entry++) { // Is this entry the same as the next one? if(!stricmp(entry[0].name, entry[1].name)) { // One of these should be removed. // The newer one survives. if(entry[0].package->order > entry[1].package->order) loser = entry + 1; else loser = entry; // Overwrite the loser with the last entry in the entire // entry directory. M_Free(loser->name); memcpy(loser, &zipFiles[zipNumFiles - 1], sizeof(zipentry_t)); memset(&zipFiles[zipNumFiles - 1], 0, sizeof(zipentry_t)); // One less entry. zipNumFiles--; modified = true; } } if(modified) { // Sort the entries again. sortZipEntries(); } } /** * Iterates through the zipentry list. If the finder func returns * @c true,; iteration stops and the the 1-based index of the * zipentry is returned. * * @param parm Ptr passed to the finder func. * * @return Non-zero if something is found. */ zipindex_t Zip_Iterate(int (*iterator) (const char *, void *), void *parm) { uint i; for(i = 0; i < zipNumFiles; ++i) { if(iterator(zipFiles[i].name, parm)) return i + 1; } // Nothing was accepted. return 0; } /** * Find a specific path in the zipentry list. Relative paths are converted * to absolute ones. A binary search is used (the entries have been sorted). * Good performance: O(log n). * * @return Non-zero if something is found. */ zipindex_t Zip_Find(const char *fileName) { zipindex_t begin, end, mid; int relation; filename_t fullPath; if(!zipNumFiles) return 0; // None registered yet. // Convert to an absolute path. strncpy(fullPath, fileName, FILENAME_T_MAXLEN); Dir_MakeAbsolute(fullPath, FILENAME_T_MAXLEN); // Init the search. begin = 0; end = zipNumFiles - 1; while(begin <= end) { mid = (begin + end) / 2; // How does this compare? relation = strnicmp(fullPath, zipFiles[mid].name, FILENAME_T_MAXLEN); if(!relation) { // Got it! We return a 1-based index. return mid + 1; } if(relation < 0) { // What we are searching must be in the first half. if(mid > 0) end = mid - 1; else return 0; // Not found. } else { // Then it must be in the second half. begin = mid + 1; } } // It wasn't found. return 0; } /** * Uses zlib to inflate a compressed entry. * * @return @c true, if successful. */ static boolean inflateEntry(void *in, size_t inSize, void *out, size_t outSize) { z_stream stream; int result; memset(&stream, 0, sizeof(stream)); stream.next_in = in; stream.avail_in = (uInt) inSize; stream.zalloc = Z_NULL; stream.zfree = Z_NULL; stream.next_out = out; stream.avail_out = (uInt) outSize; if(inflateInit2(&stream, -MAX_WBITS) != Z_OK) return false; // Do the inflation in one call. result = inflate(&stream, Z_FINISH); if(stream.total_out != outSize) { Con_Message("inflateEntry: Failure due to %s.\n", result == Z_DATA_ERROR ? "corrupt data" : "zlib error"); return false; } // We're done. inflateEnd(&stream); return true; } /** * @return Size of a zipentry specified by index. */ size_t Zip_GetSize(zipindex_t index) { if(index == 0 || index - 1 >= zipNumFiles) return 0; // Doesn't exist. return zipFiles[index - 1].size; } /** * Reads a zipentry into the buffer. The caller must make sure that * the buffer is large enough. Zip_GetSize() returns the size. * * @return Number of bytes read. */ size_t Zip_Read(zipindex_t index, void *buffer) { package_t *pack; zipentry_t *entry; void *compressedData; boolean result; if(index == 0 || index - 1 >= zipNumFiles) return 0; // Doesn't exist. index--; entry = &zipFiles[index]; pack = entry->package; VERBOSE2(Con_Message ("Zip_Read: %s: '%s' (%lu bytes%s)\n", M_PrettyPath(pack->name), M_PrettyPath(entry->name), (unsigned long) entry->size, (entry->deflatedSize? ", deflated" : ""))); F_Seek(pack->file, entry->offset, SEEK_SET); if(entry->deflatedSize != 0) { // Read the compressed data into a buffer. compressedData = M_Malloc(entry->deflatedSize); F_Read(compressedData, entry->deflatedSize, pack->file); // Run zlib's inflate to decompress. result = inflateEntry(compressedData, entry->deflatedSize, buffer, entry->size); M_Free(compressedData); if(!result) return 0; // Inflate failed. } else { // Read the uncompressed data directly to the buffer provided // by the caller. F_Read(buffer, entry->size, pack->file); } return entry->size; } /** * @return "Last modified" timestamp of the zip entry. */ uint Zip_GetLastModified(zipindex_t index) { if(index == 0 || index - 1 >= zipNumFiles) return 0; // Doesn't exist. return zipFiles[index - 1].lastModified; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_data.c0000644000175000017500000007405311357170242022336 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_data.c: Playsim Data Structures, Macros and Constants */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_play.h" #include "de_render.h" #include "de_refresh.h" #include "de_system.h" #include "de_misc.h" #include "rend_bias.h" #include "m_bams.h" #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // Bad texture record. typedef struct { char *name; boolean planeTex; uint count; } badtex_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern boolean mapSetup; // PUBLIC DATA DEFINITIONS ------------------------------------------------- /** * These map data arrays are internal to the engine. */ char mapID[9]; // Name by which the game referred to the current map. uint numVertexes = 0; vertex_t* vertexes = NULL; uint numSegs = 0; seg_t* segs = NULL; uint numSectors = 0; sector_t* sectors = NULL; uint numSSectors = 0; subsector_t* ssectors = NULL; uint numNodes = 0; node_t* nodes = NULL; uint numLineDefs = 0; linedef_t* lineDefs = NULL; uint numSideDefs = 0; sidedef_t* sideDefs = NULL; watchedplanelist_t* watchedPlaneList = NULL; surfacelist_t* movingSurfaceList = NULL; surfacelist_t* decoratedSurfaceList = NULL; blockmap_t* BlockMap = NULL; blockmap_t* SSecBlockMap = NULL; nodepile_t* mobjNodes = NULL, *lineNodes = NULL; // All kinds of wacky links. float mapGravity; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static gamemap_t* currentMap = NULL; // Bad texture list static uint numBadTexNames = 0; static uint maxBadTexNames = 0; static badtex_t *badTexNames = NULL; // Game-specific, map object type definitions. static uint numGameMapObjDefs; static gamemapobjdef_t* gameMapObjDefs; // CODE -------------------------------------------------------------------- void P_InitData(void) { P_InitMapUpdate(); } void P_PolyobjChanged(polyobj_t* po) { uint i; seg_t** segPtr = po->segs; for(i = 0; i < po->numSegs; ++i, segPtr++) { int j; seg_t* seg = *segPtr; // Shadow bias must be told. for(j = 0; j < 3; ++j) { SB_SurfaceMoved(seg->bsuf[j]); } } } /** * Generate a 'unique' identifier for the map. This identifier * contains information about the map tag (E3M3), the WAD that * contains the map (DOOM.IWAD), and the game mode (doom-ultimate). * * The entire ID string will be in lowercase letters. */ const char* P_GenerateUniqueMapID(const char* mapID) { static char uid[255]; filename_t base; int lump = W_GetNumForName(mapID); M_ExtractFileBase(base, W_LumpSourceFile(lump), FILENAME_T_MAXLEN); dd_snprintf(uid, 255, "%s|%s|%s|%s", mapID, base, (W_IsFromIWAD(lump) ? "iwad" : "pwad"), (char *) gx.GetVariable(DD_GAME_MODE)); strlwr(uid); return uid; } /** * @return Ptr to the current map. */ gamemap_t *P_GetCurrentMap(void) { return currentMap; } void P_SetCurrentMap(gamemap_t* map) { strncpy(mapID, map->mapID, sizeof(mapID)); numVertexes = map->numVertexes; vertexes = map->vertexes; numSegs = map->numSegs; segs = map->segs; numSectors = map->numSectors; sectors = map->sectors; numSSectors = map->numSSectors; ssectors = map->ssectors; numNodes = map->numNodes; nodes = map->nodes; numLineDefs = map->numLineDefs; lineDefs = map->lineDefs; numSideDefs = map->numSideDefs; sideDefs = map->sideDefs; watchedPlaneList = &map->watchedPlaneList; movingSurfaceList = &map->movingSurfaceList; decoratedSurfaceList = &map->decoratedSurfaceList; numPolyObjs = map->numPolyObjs; polyObjs = map->polyObjs; mobjNodes = &map->mobjNodes; lineNodes = &map->lineNodes; linelinks = map->lineLinks; BlockMap = map->blockMap; SSecBlockMap = map->ssecBlockMap; mapGravity = map->globalGravity; currentMap = map; } /** * This ID is the name of the lump tag that marks the beginning of map * data, e.g. "MAP03" or "E2M8". */ const char* P_GetMapID(gamemap_t* map) { if(!map) return NULL; return map->mapID; } /** * @return The 'unique' identifier of the map. */ const char* P_GetUniqueMapID(gamemap_t* map) { if(!map) return NULL; return map->uniqueID; } void P_GetMapBounds(gamemap_t* map, float* min, float* max) { min[VX] = map->bBox[BOXLEFT]; min[VY] = map->bBox[BOXBOTTOM]; max[VX] = map->bBox[BOXRIGHT]; max[VY] = map->bBox[BOXTOP]; } /** * Get the ambient light level of the specified map. */ int P_GetMapAmbientLightLevel(gamemap_t* map) { if(!map) return 0; return map->ambientLightLevel; } /** * Begin the process of loading a new map. * Can be accessed by the games via the public API. * * @param levelId Identifier of the map to be loaded (eg "E1M1"). * * @return @c true, if the map was loaded successfully. */ boolean P_LoadMap(const char *mapID) { uint i; if(!mapID || !mapID[0]) return false; // Yeah, ok... :P Con_Message("P_LoadMap: \"%s\"\n", mapID); // It would be very cool if map loading happened in another // thread. That way we could be keeping ourselves busy while // the intermission is played... // We could even try to divide a HUB up into zones, so that // when a player enters a zone we could begin loading the map(s) // reachable through exits in that zone (providing they have // enough free memory of course) so that transitions are // (potentially) seamless :-) if(isServer) { // Whenever the map changes, remote players must tell us when // they're ready to begin receiving frames. for(i = 0; i < DDMAXPLAYERS; ++i) { player_t *plr = &ddPlayers[i]; if(!(plr->shared.flags & DDPF_LOCAL) && clients[i].connected) { #ifdef _DEBUG Con_Printf("Cl%i NOT READY ANY MORE!\n", i); #endif clients[i].ready = false; } } } if(DAM_AttemptMapLoad(mapID)) { uint i; gamemap_t* map = P_GetCurrentMap(); // Init the thinker lists (public and private). P_InitThinkerLists(0x1 | 0x2); // Tell shadow bias to initialize the bias light sources. SB_InitForMap(P_GetUniqueMapID(map)); Cl_Reset(); RL_DeleteLists(); Rend_CalcLightModRange(NULL); // Invalidate old cmds and init player values. for(i = 0; i < DDMAXPLAYERS; ++i) { player_t *plr = &ddPlayers[i]; if(isServer && plr->shared.inGame) clients[i].runTime = SECONDS_TO_TICKS(gameTime); plr->extraLight = plr->targetExtraLight = 0; plr->extraLightCounter = 0; } // Make sure that the next frame doesn't use a filtered viewer. R_ResetViewer(); // Texture animations should begin from their first step. R_ResetAnimGroups(); R_InitObjLinksForMap(); LO_InitForMap(); // Lumobj management. DL_InitForMap(); // Projected dynlights (from lumobjs) management. VL_InitForMap(); // Converted vlights (from lumobjs) management. // Init Particle Generator links. P_PtcInitForMap(); // Initialize the lighting grid. LG_Init(); if(!isDedicated) R_InitRendVerticesPool(); return true; } return false; } void P_RegisterUnknownTexture(const char *name, boolean planeTex) { uint i; char namet[9]; boolean known = false; namet[8] = 0; memcpy(namet, name, 8); // Do we already know about it? if(numBadTexNames > 0) { for(i = 0; i < numBadTexNames && !known; ++i) { if(!strcmp(badTexNames[i].name, namet) && badTexNames[i].planeTex == planeTex) { // Yep we already know about it. known = true; badTexNames[i].count++; } } } if(!known) { // A new unknown texture. Add it to the list if(++numBadTexNames > maxBadTexNames) { // Allocate more memory maxBadTexNames *= 2; if(maxBadTexNames < numBadTexNames) maxBadTexNames = numBadTexNames; badTexNames = M_Realloc(badTexNames, sizeof(badtex_t) * maxBadTexNames); } badTexNames[numBadTexNames -1].name = M_Malloc(strlen(namet) +1); strcpy(badTexNames[numBadTexNames -1].name, namet); badTexNames[numBadTexNames -1].planeTex = planeTex; badTexNames[numBadTexNames -1].count = 1; } } void P_PrintMissingTextureList(void) { // Announce any bad texture names we came across when loading the map. // Non-critical as a "MISSING" texture will be drawn in place of them. if(numBadTexNames) { uint i; Con_Message(" [110] Warning: Found %u bad texture name(s):\n", numBadTexNames); for(i = 0; i < numBadTexNames; ++i) Con_Message(" %4u x \"%s\"\n", badTexNames[i].count, badTexNames[i].name); } } /** * Frees memory we allocated for bad texture name collection. */ void P_FreeBadTexList(void) { uint i; if(badTexNames != NULL) { for(i = 0; i < numBadTexNames; ++i) { M_Free(badTexNames[i].name); badTexNames[i].name = NULL; } M_Free(badTexNames); badTexNames = NULL; numBadTexNames = maxBadTexNames = 0; } } /** * Look up a mapobj definition. * * @param identifer If objName is @c NULL, compare using this unique identifier. * @param objName If not @c NULL, compare using this unique name. */ gamemapobjdef_t *P_GetGameMapObjDef(int identifier, const char *objName, boolean canCreate) { uint i; size_t len; gamemapobjdef_t *def; if(objName) len = strlen(objName); // Is this a known game object? for(i = 0; i < numGameMapObjDefs; ++i) { def = &gameMapObjDefs[i]; if(objName && objName[0]) { if(!strnicmp(objName, def->name, len)) { // Found it! return def; } } else { if(identifier == def->identifier) { // Found it! return def; } } } if(!canCreate) return NULL; // Not a known game map object. if(identifier == 0) return NULL; // Not a valid indentifier. if(!objName || !objName[0]) return NULL; // Must have a name. // Ensure the name is unique. for(i = 0; i < numGameMapObjDefs; ++i) { def = &gameMapObjDefs[i]; if(!strnicmp(objName, def->name, len)) { // Oh dear, a duplicate. return NULL; } } gameMapObjDefs = M_Realloc(gameMapObjDefs, ++numGameMapObjDefs * sizeof(*gameMapObjDefs)); def = &gameMapObjDefs[numGameMapObjDefs - 1]; def->identifier = identifier; def->name = M_Malloc(len+1); strncpy(def->name, objName, len); def->name[len] = '\0'; def->numProps = 0; def->props = NULL; return def; } /** * Called by the game to register the map object types it wishes us to make * public via the MPE interface. */ boolean P_RegisterMapObj(int identifier, const char *name) { if(P_GetGameMapObjDef(identifier, name, true)) return true; // Success. return false; } /** * Called by the game to add a new property to a previously registered * map object type definition. */ boolean P_RegisterMapObjProperty(int identifier, int propIdentifier, const char *propName, valuetype_t type) { uint i; size_t len; mapobjprop_t *prop; gamemapobjdef_t *def = P_GetGameMapObjDef(identifier, NULL, false); if(!def) // Not a valid identifier. { Con_Error("P_RegisterMapObjProperty: Unknown mapobj identifier %i.", identifier); } if(propIdentifier == 0) // Not a valid identifier. Con_Error("P_RegisterMapObjProperty: 0 not valid for propIdentifier."); if(!propName || !propName[0]) // Must have a name. Con_Error("P_RegisterMapObjProperty: Cannot register without name."); // Screen out value types we don't currently support for gmos. switch(type) { case DDVT_BYTE: case DDVT_SHORT: case DDVT_INT: case DDVT_FIXED: case DDVT_ANGLE: case DDVT_FLOAT: break; default: Con_Error("P_RegisterMapObjProperty: Unknown/not supported value type %i.", type); } // Next, make sure propIdentifer and propName are unique. len = strlen(propName); for(i = 0; i < def->numProps; ++i) { prop = &def->props[i]; if(prop->identifier == propIdentifier) Con_Error("P_RegisterMapObjProperty: propIdentifier %i not unique for %s.", propIdentifier, def->name); if(!strnicmp(propName, prop->name, len)) Con_Error("P_RegisterMapObjProperty: propName \"%s\" not unique for %s.", propName, def->name); } // Looks good! Add it to the list of properties. def->props = M_Realloc(def->props, ++def->numProps * sizeof(*def->props)); prop = &def->props[def->numProps - 1]; prop->identifier = propIdentifier; prop->name = M_Malloc(len + 1); strncpy(prop->name, propName, len); prop->name[len] = '\0'; prop->type = type; return true; // Success! } /** * Called during init to initialize the map obj defs. */ void P_InitGameMapObjDefs(void) { gameMapObjDefs = NULL; numGameMapObjDefs = 0; } /** * Called at shutdown to free all memory allocated for the map obj defs. */ void P_ShutdownGameMapObjDefs(void) { uint i, j; if(gameMapObjDefs) { for(i = 0; i < numGameMapObjDefs; ++i) { gamemapobjdef_t *def = &gameMapObjDefs[i]; for(j = 0; j < def->numProps; ++j) { mapobjprop_t *prop = &def->props[i]; M_Free(prop->name); } M_Free(def->name); M_Free(def->props); } M_Free(gameMapObjDefs); } gameMapObjDefs = NULL; numGameMapObjDefs = 0; } static valuetable_t *getDBTable(valuedb_t *db, valuetype_t type, boolean canCreate) { uint i; valuetable_t *tbl; if(!db) return NULL; for(i = 0; i < db->numTables; ++i) { tbl = db->tables[i]; if(tbl->type == type) { // Found it! return tbl; } } if(!canCreate) return NULL; // We need to add a new value table to the db. db->tables = M_Realloc(db->tables, ++db->numTables * sizeof(*db->tables)); tbl = db->tables[db->numTables - 1] = M_Malloc(sizeof(valuetable_t)); tbl->data = NULL; tbl->type = type; tbl->numElms = 0; return tbl; } static uint insertIntoDB(valuedb_t *db, valuetype_t type, void *data) { valuetable_t *tbl = getDBTable(db, type, true); // Insert the new value. switch(type) { case DDVT_BYTE: tbl->data = M_Realloc(tbl->data, ++tbl->numElms); ((byte*) tbl->data)[tbl->numElms - 1] = *((byte*) data); break; case DDVT_SHORT: tbl->data = M_Realloc(tbl->data, ++tbl->numElms * sizeof(short)); ((short*) tbl->data)[tbl->numElms - 1] = *((short*) data); break; case DDVT_INT: tbl->data = M_Realloc(tbl->data, ++tbl->numElms * sizeof(int)); ((int*) tbl->data)[tbl->numElms - 1] = *((int*) data); break; case DDVT_FIXED: tbl->data = M_Realloc(tbl->data, ++tbl->numElms * sizeof(fixed_t)); ((fixed_t*) tbl->data)[tbl->numElms - 1] = *((fixed_t*) data); break; case DDVT_ANGLE: tbl->data = M_Realloc(tbl->data, ++tbl->numElms * sizeof(angle_t)); ((angle_t*) tbl->data)[tbl->numElms - 1] = *((angle_t*) data); break; case DDVT_FLOAT: tbl->data = M_Realloc(tbl->data, ++tbl->numElms * sizeof(float)); ((float*) tbl->data)[tbl->numElms - 1] = *((float*) data); break; default: Con_Error("insetIntoDB: Unknown value type %d.", type); } return tbl->numElms - 1; } static void* getPtrToDBElm(valuedb_t *db, valuetype_t type, uint elmIdx) { valuetable_t *tbl = getDBTable(db, type, false); if(!tbl) Con_Error("getPtrToDBElm: Table for type %i not found.", (int) type); // Sanity check: ensure the elmIdx is in bounds. if(elmIdx < 0 || elmIdx >= tbl->numElms) Con_Error("P_GetGMOByte: valueIdx out of bounds."); switch(tbl->type) { case DDVT_BYTE: return &(((byte*) tbl->data)[elmIdx]); case DDVT_SHORT: return &(((short*)tbl->data)[elmIdx]); case DDVT_INT: return &(((int*) tbl->data)[elmIdx]); case DDVT_FIXED: return &(((fixed_t*) tbl->data)[elmIdx]); case DDVT_ANGLE: return &(((angle_t*) tbl->data)[elmIdx]); case DDVT_FLOAT: return &(((float*) tbl->data)[elmIdx]); default: Con_Error("P_GetGMOByte: Invalid table type %i.", tbl->type); } // Should never reach here. return NULL; } /** * Destroy the given game map obj database. */ void P_DestroyGameMapObjDB(gameobjdata_t *moData) { uint i, j; if(moData->objLists) { for(i = 0; i < numGameMapObjDefs; ++i) { gamemapobjlist_t* objList = &moData->objLists[i]; for(j = 0; j < objList->num; ++j) { gamemapobj_t *gmo = objList->objs[j]; if(gmo->props) M_Free(gmo->props); M_Free(gmo); } } M_Free(moData->objLists); } moData->objLists = NULL; if(moData->db.tables) { for(i = 0; i < moData->db.numTables; ++i) { valuetable_t *tbl = moData->db.tables[i]; if(tbl->data) M_Free(tbl->data); M_Free(tbl); } M_Free(moData->db.tables); } moData->db.tables = NULL; moData->db.numTables = 0; } static uint countGameMapObjs(gameobjdata_t *moData, int identifier) { if(moData) { uint i; for(i = 0; i < numGameMapObjDefs; ++i) { gamemapobjlist_t* objList = &moData->objLists[i]; if(objList->def->identifier == identifier) return objList->num; } } return 0; } uint P_CountGameMapObjs(int identifier) { gamemap_t* map = P_GetCurrentMap(); return countGameMapObjs(&map->gameObjData, identifier); } static gamemapobjlist_t* getMapObjList(gameobjdata_t* moData, gamemapobjdef_t* def) { uint i; for(i = 0; i < numGameMapObjDefs; ++i) if(moData->objLists[i].def == def) return &moData->objLists[i]; return NULL; } gamemapobj_t* P_GetGameMapObj(gameobjdata_t *moData, gamemapobjdef_t *def, uint elmIdx, boolean canCreate) { uint i; gamemapobj_t* gmo; gamemapobjlist_t* objList; if(!moData->objLists) { // We haven't yet created the lists. moData->objLists = M_Malloc(sizeof(*objList) * numGameMapObjDefs); for(i = 0; i < numGameMapObjDefs; ++i) { objList = &moData->objLists[i]; objList->def = &gameMapObjDefs[i]; objList->objs = NULL; objList->num = 0; } } objList = getMapObjList(moData, def); assert(objList); // Have we already created this gmo? for(i = 0; i < objList->num; ++i) { gmo = objList->objs[i]; if(gmo->elmIdx == elmIdx) return gmo; // Yep, return it. } if(!canCreate) return NULL; // It is a new gamemapobj. objList->objs = M_Realloc(objList->objs, ++objList->num * sizeof(gamemapobj_t*)); gmo = objList->objs[objList->num - 1] = M_Malloc(sizeof(*gmo)); gmo->elmIdx = elmIdx; gmo->numProps = 0; gmo->props = NULL; return gmo; } void P_AddGameMapObjValue(gameobjdata_t *moData, gamemapobjdef_t *gmoDef, uint propIdx, uint elmIdx, valuetype_t type, void *data) { uint i; customproperty_t *prop; gamemapobj_t *gmo = P_GetGameMapObj(moData, gmoDef, elmIdx, true); if(!gmo) Con_Error("addGameMapObj: Failed creation."); // Check whether this is a new value or whether we are updating an // existing one. for(i = 0; i < gmo->numProps; ++i) { if(gmo->props[i].idx == propIdx) { // We are updating. //if(gmo->props[i].type == type) // updateInDB(map->values, type, gmo->props[i].valueIdx, data); //else Con_Error("addGameMapObj: Value type change not currently supported."); return; } } // Its a new value. gmo->props = M_Realloc(gmo->props, ++gmo->numProps * sizeof(*gmo->props)); prop = &gmo->props[gmo->numProps - 1]; prop->idx = propIdx; prop->type = type; prop->valueIdx = insertIntoDB(&moData->db, type, data); } static void* getGMOPropValue(gameobjdata_t *data, int identifier, uint elmIdx, int propIdentifier, valuetype_t *type) { uint i; gamemapobjdef_t *def; gamemapobj_t *gmo; if((def = P_GetGameMapObjDef(identifier, NULL, false)) == NULL) Con_Error("P_GetGMOByte: Invalid identifier %i.", identifier); if((gmo = P_GetGameMapObj(data, def, elmIdx, false)) == NULL) Con_Error("P_GetGMOByte: There is no element %i of type %s.", elmIdx, def->name); // Find the requested property. for(i = 0; i < gmo->numProps; ++i) { customproperty_t *prop = &gmo->props[i]; if(def->props[prop->idx].identifier == propIdentifier) { void *ptr; if(NULL == (ptr = getPtrToDBElm(&data->db, prop->type, prop->valueIdx))) Con_Error("P_GetGMOByte: Failed db look up."); if(type) *type = prop->type; return ptr; } } return NULL; } /** * Handle some basic type conversions. */ static void setValue(void *dst, valuetype_t dstType, void *src, valuetype_t srcType) { if(dstType == DDVT_FIXED) { fixed_t *d = dst; switch(srcType) { case DDVT_BYTE: *d = (*((byte*) src) << FRACBITS); break; case DDVT_INT: *d = (*((int*) src) << FRACBITS); break; case DDVT_FIXED: *d = *((fixed_t*) src); break; case DDVT_FLOAT: *d = FLT2FIX(*((float*) src)); break; default: Con_Error("SetValue: DDVT_FIXED incompatible with value type %s.\n", value_Str(srcType)); } } else if(dstType == DDVT_FLOAT) { float *d = dst; switch(srcType) { case DDVT_BYTE: *d = *((byte*) src); break; case DDVT_INT: *d = *((int*) src); break; case DDVT_SHORT: *d = *((short*) src); break; case DDVT_FIXED: *d = FIX2FLT(*((fixed_t*) src)); break; case DDVT_FLOAT: *d = *((float*) src); break; default: Con_Error("SetValue: DDVT_FLOAT incompatible with value type %s.\n", value_Str(srcType)); } } else if(dstType == DDVT_BYTE) { byte *d = dst; switch(srcType) { case DDVT_BYTE: *d = *((byte*) src); break; case DDVT_INT: *d = *((int*) src); break; case DDVT_FLOAT: *d = (byte) *((float*) src); break; default: Con_Error("SetValue: DDVT_BYTE incompatible with value type %s.\n", value_Str(srcType)); } } else if(dstType == DDVT_INT) { int *d = dst; switch(srcType) { case DDVT_BYTE: *d = *((byte*) src); break; case DDVT_INT: *d = *((int*) src); break; case DDVT_SHORT: *d = *((short*) src); break; case DDVT_FLOAT: *d = *((float*) src); break; case DDVT_FIXED: *d = (*((fixed_t*) src) >> FRACBITS); break; default: Con_Error("SetValue: DDVT_INT incompatible with value type %s.\n", value_Str(srcType)); } } else if(dstType == DDVT_SHORT) { short *d = dst; switch(srcType) { case DDVT_BYTE: *d = *((byte*) src); break; case DDVT_INT: *d = *((int*) src); break; case DDVT_SHORT: *d = *((short*) src); break; case DDVT_FLOAT: *d = *((float*) src); break; case DDVT_FIXED: *d = (*((fixed_t*) src) >> FRACBITS); break; default: Con_Error("SetValue: DDVT_SHORT incompatible with value type %s.\n", value_Str(srcType)); } } else if(dstType == DDVT_ANGLE) { angle_t *d = dst; switch(srcType) { case DDVT_ANGLE: *d = *((angle_t*) src); break; default: Con_Error("SetValue: DDVT_ANGLE incompatible with value type %s.\n", value_Str(srcType)); } } else { Con_Error("SetValue: unknown value type %d.\n", dstType); } } byte P_GetGMOByte(int identifier, uint elmIdx, int propIdentifier) { valuetype_t type; gamemap_t* map = P_GetCurrentMap(); void* ptr; byte returnVal = 0; if((ptr = getGMOPropValue(&map->gameObjData, identifier, elmIdx, propIdentifier, &type))) setValue(&returnVal, DDVT_BYTE, ptr, type); return returnVal; } short P_GetGMOShort(int identifier, uint elmIdx, int propIdentifier) { valuetype_t type; gamemap_t* map = P_GetCurrentMap(); void* ptr; short returnVal = 0; if((ptr = getGMOPropValue(&map->gameObjData, identifier, elmIdx, propIdentifier, &type))) setValue(&returnVal, DDVT_SHORT, ptr, type); return returnVal; } int P_GetGMOInt(int identifier, uint elmIdx, int propIdentifier) { valuetype_t type; gamemap_t* map = P_GetCurrentMap(); void* ptr; int returnVal = 0; if((ptr = getGMOPropValue(&map->gameObjData, identifier, elmIdx, propIdentifier, &type))) setValue(&returnVal, DDVT_INT, ptr, type); return returnVal; } fixed_t P_GetGMOFixed(int identifier, uint elmIdx, int propIdentifier) { valuetype_t type; gamemap_t* map = P_GetCurrentMap(); void* ptr; fixed_t returnVal = 0; if((ptr = getGMOPropValue(&map->gameObjData, identifier, elmIdx, propIdentifier, &type))) setValue(&returnVal, DDVT_FIXED, ptr, type); return returnVal; } angle_t P_GetGMOAngle(int identifier, uint elmIdx, int propIdentifier) { valuetype_t type; gamemap_t* map = P_GetCurrentMap(); void* ptr; angle_t returnVal = 0; if((ptr = getGMOPropValue(&map->gameObjData, identifier, elmIdx, propIdentifier, &type))) setValue(&returnVal, DDVT_ANGLE, ptr, type); return returnVal; } float P_GetGMOFloat(int identifier, uint elmIdx, int propIdentifier) { valuetype_t type; gamemap_t* map = P_GetCurrentMap(); void* ptr; float returnVal = 0; if((ptr = getGMOPropValue(&map->gameObjData, identifier, elmIdx, propIdentifier, &type))) setValue(&returnVal, DDVT_FLOAT, ptr, type); return returnVal; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sv_frame.c0000644000175000017500000006605311357170242022711 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_frame.c: Frame Generation and Transmission */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_network.h" #include "de_system.h" #include "de_refresh.h" #include "de_misc.h" #include "de_play.h" #include "def_main.h" // MACROS ------------------------------------------------------------------ // Hitting the maximum packet size allows checks for raising BWR. #define BWR_ADJUST_TICS (TICSPERSEC / 2) // The minimum frame size is used when bandwidth rating is zero (poorest // possible connection). #define MINIMUM_FRAME_SIZE 400 // bytes // The frame size is calculated by multiplying the bandwidth rating // (max 100) with this factor (+min). #define FRAME_SIZE_FACTOR 13 #define FIXED8_8(x) (((x)*256) >> 16) #define FIXED10_6(x) (((x)*64) >> 16) #define CLAMPED_CHAR(x) ((x)>127? 127 : (x)<-128? -128 : (x)) // If movement is faster than this, we'll adjust the place of the point. #define MOM_FAST_LIMIT (127) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void Sv_SendFrame(int playerNumber); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int allowFrames = false; int frameInterval = 1; // Skip every second frame by default (17.5fps) // PRIVATE DATA DEFINITIONS ------------------------------------------------ #ifdef _DEBUG static int byteCounts[256]; static int totalFrameCount; #endif static int lastTransmitTic = 0; // CODE -------------------------------------------------------------------- /** * Send all the relevant information to each client. */ void Sv_TransmitFrame(void) { int i, cTime, numInGame, pCount; // Obviously clients don't transmit anything. if(!allowFrames || isClient) { return; } if(!netGame) { // When not running a netGame, only generate deltas when somebody // is recording a demo. for(i = 0; i < DDMAXPLAYERS; ++i) if(Sv_IsFrameTarget(i)) break; if(i == DDMAXPLAYERS) { // Nobody is a frame target. return; } } if(SECONDS_TO_TICKS(gameTime) == lastTransmitTic) { // We were just here! return; } lastTransmitTic = SECONDS_TO_TICKS(gameTime); // Generate new deltas for the frame. Sv_GenerateFrameDeltas(); // How many players currently in the game? numInGame = Sv_GetNumPlayers(); for(i = 0, pCount = 0; i < DDMAXPLAYERS; ++i) { if(!Sv_IsFrameTarget(i)) { // This player is not a valid target for frames. continue; } // When the interval is greater than zero, this causes the frames // to be sent at different times for each player. pCount++; cTime = SECONDS_TO_TICKS(gameTime); if(frameInterval > 0 && numInGame > 1) { cTime += (pCount * frameInterval) / numInGame; } if(cTime <= clients[i].lastTransmit + frameInterval) { // Still too early to send. continue; } clients[i].lastTransmit = cTime; /*#if _DEBUG ST_Message("gt:%i (%i) -> cl%i\n", gametic, ctime, i); #endif */ if(clients[i].ready && clients[i].updateCount > 0) { // A frame will be sent to this client. If the client // doesn't send ticcmds, the updatecount will eventually // decrease back to zero. clients[i].updateCount--; Sv_SendFrame(i); } } } /** * Shutdown routine for the server. */ void Sv_Shutdown(void) { #ifdef _DEBUG if(totalFrameCount > 0) { uint i; // Byte probabilities. for(i = 0; i < 256; ++i) { Con_Printf("Byte %02x: %f\n", i, byteCounts[i] / (float) totalFrameCount); } } #endif Sv_ShutdownPools(); } /** * The delta is written to the message buffer. */ void Sv_WriteMobjDelta(const void* deltaPtr) { const mobjdelta_t* delta = deltaPtr; const dt_mobj_t* d = &delta->mo; int df = delta->delta.flags; byte moreFlags = 0; // Do we have fast momentum? if(fabs(d->mom[MX]) >= MOM_FAST_LIMIT || fabs(d->mom[MY]) >= MOM_FAST_LIMIT || fabs(d->mom[MZ]) >= MOM_FAST_LIMIT) { df |= MDF_MORE_FLAGS; moreFlags |= MDFE_FAST_MOM; } // Any translucency? if(df & MDFC_TRANSLUCENCY) { df |= MDF_MORE_FLAGS; moreFlags |= MDFE_TRANSLUCENCY; } // A fade target? if(df & MDFC_FADETARGET) { df |= MDF_MORE_FLAGS; moreFlags |= MDFE_FADETARGET; } // Do we need the longer floorclip entry? if(d->floorClip > 64) df |= MDF_LONG_FLOORCLIP; // Flags. What elements are included in the delta? if(d->selector & ~DDMOBJ_SELECTOR_MASK) df |= MDF_SELSPEC; // Floor/ceiling z? if(df & MDF_POS_Z) { if(d->pos[VZ] == DDMINFLOAT || d->pos[VZ] == DDMAXFLOAT) { df &= ~MDF_POS_Z; df |= MDF_MORE_FLAGS; moreFlags |= (d->pos[VZ] == DDMINFLOAT ? MDFE_Z_FLOOR : MDFE_Z_CEILING); } } #ifdef _DEBUG if(df & MDFC_NULL) { Con_Error("Sv_WriteMobjDelta: We don't write Null deltas.\n"); } if((df & 0xffff) == 0) { Con_Printf("Sv_WriteMobjDelta: This delta id%i [%x] is empty.\n", delta->delta.id, df); } #endif // First the mobj ID number and flags. Msg_WriteShort(delta->delta.id); Msg_WriteShort(df & 0xffff); // More flags? if(df & MDF_MORE_FLAGS) { Msg_WriteByte(moreFlags); } // Coordinates with three bytes. if(df & MDF_POS_X) { fixed_t vx = FLT2FIX(d->pos[VX]); Msg_WriteShort(vx >> FRACBITS); Msg_WriteByte(vx >> 8); } if(df & MDF_POS_Y) { fixed_t vy = FLT2FIX(d->pos[VY]); Msg_WriteShort(vy >> FRACBITS); Msg_WriteByte(vy >> 8); } if(df & MDF_POS_Z) { fixed_t vz = FLT2FIX(d->pos[VZ]); Msg_WriteShort(vz >> FRACBITS); Msg_WriteByte(vz >> 8); } // Momentum using 8.8 fixed point. if(df & MDF_MOM_X) { fixed_t mx = FLT2FIX(d->mom[MX]); Msg_WriteShort(moreFlags & MDFE_FAST_MOM ? FIXED10_6(mx) : FIXED8_8(mx)); } if(df & MDF_MOM_Y) { fixed_t my = FLT2FIX(d->mom[MY]); Msg_WriteShort(moreFlags & MDFE_FAST_MOM ? FIXED10_6(my) : FIXED8_8(my)); } if(df & MDF_MOM_Z) { fixed_t mz = FLT2FIX(d->mom[MZ]); Msg_WriteShort(moreFlags & MDFE_FAST_MOM ? FIXED10_6(mz) : FIXED8_8(mz)); } // Angles with 16-bit accuracy. if(df & MDF_ANGLE) Msg_WriteShort(d->angle >> 16); if(df & MDF_SELECTOR) Msg_WritePackedShort(d->selector); if(df & MDF_SELSPEC) Msg_WriteByte(d->selector >> 24); if(df & MDF_STATE) Msg_WritePackedShort(d->state - states); // Pack flags into a word (3 bytes?). // \fixme Do the packing! if(df & MDF_FLAGS) Msg_WriteLong(d->ddFlags & DDMF_PACK_MASK); // Radius, height and floorclip are all bytes. if(df & MDF_RADIUS) Msg_WriteByte((byte) d->radius); if(df & MDF_HEIGHT) Msg_WriteByte((byte) d->height); if(df & MDF_FLOORCLIP) { if(df & MDF_LONG_FLOORCLIP) Msg_WritePackedShort(FLT2FIX(d->floorClip) >> 14); else Msg_WriteByte(FLT2FIX(d->floorClip) >> 14); } if(df & MDFC_TRANSLUCENCY) Msg_WriteByte(d->translucency); if(df & MDFC_FADETARGET) Msg_WriteByte((byte)(d->visTarget +1)); } /** * The delta is written to the message buffer. */ void Sv_WritePlayerDelta(const void* deltaPtr) { const playerdelta_t* delta = deltaPtr; const dt_player_t* d = &delta->player; const ddpsprite_t* psp; int df = delta->delta.flags; int psdf, i, k; // First the player number. Upper three bits contain flags. Msg_WriteByte(delta->delta.id | (df >> 8)); // Flags. What elements are included in the delta? Msg_WriteByte(df & 0xff); if(df & PDF_MOBJ) Msg_WriteShort(d->mobj); if(df & PDF_FORWARDMOVE) Msg_WriteByte(d->forwardMove); if(df & PDF_SIDEMOVE) Msg_WriteByte(d->sideMove); /*if(df & PDF_ANGLE) Msg_WriteByte(d->angle >> 24);*/ if(df & PDF_TURNDELTA) Msg_WriteByte((d->turnDelta * 16) >> 24); if(df & PDF_FRICTION) Msg_WriteByte(FLT2FIX(d->friction) >> 8); if(df & PDF_EXTRALIGHT) { // Three bits is enough for fixedcolormap. i = d->fixedColorMap; if(i < 0) i = 0; if(i > 7) i = 7; // Write the five upper bytes of extraLight. Msg_WriteByte(i | (d->extraLight & 0xf8)); } if(df & PDF_FILTER) Msg_WriteLong(d->filter); /* if(df & PDF_CLYAW) Msg_WriteShort(d->clYaw >> 16); if(df & PDF_CLPITCH) Msg_WriteShort(d->clPitch / 110 * DDMAXSHORT);*/ /* $unifiedangles */ if(df & PDF_PSPRITES) // Only set if there's something to write. { for(i = 0; i < 2; ++i) { psdf = df >> (16 + i * 8); psp = d->psp + i; // First the flags. Msg_WriteByte(psdf); if(psdf & PSDF_STATEPTR) { if(psp->statePtr) Msg_WritePackedShort(psp->statePtr - states + 1); else Msg_WritePackedShort(0); } /*if(psdf & PSDF_LIGHT) { k = psp->light * 255; if(k < 0) k = 0; if(k > 255) k = 255; Msg_WriteByte(k); }*/ if(psdf & PSDF_ALPHA) { k = psp->alpha * 255; if(k < 0) k = 0; if(k > 255) k = 255; Msg_WriteByte(k); } if(psdf & PSDF_STATE) { Msg_WriteByte(psp->state); } if(psdf & PSDF_OFFSET) { Msg_WriteByte(CLAMPED_CHAR(psp->offset[VX] / 2)); Msg_WriteByte(CLAMPED_CHAR(psp->offset[VY] / 2)); } } } } /** * The delta is written to the message buffer. */ void Sv_WriteSectorDelta(const void* deltaPtr) { const sectordelta_t* delta = deltaPtr; const dt_sector_t* d = &delta->sector; int df = delta->delta.flags, spd; byte floorspd = 0, ceilspd = 0; // Is there need to use 4.4 fixed-point speeds? // (7.1 is too inaccurate for very slow movement) if(df & SDF_FLOOR_SPEED) { spd = FLT2FIX(fabs(d->planes[PLN_FLOOR].speed)); floorspd = spd >> 15; if(!floorspd) { df |= SDF_FLOOR_SPEED_44; floorspd = spd >> 12; } } if(df & SDF_CEILING_SPEED) { spd = FLT2FIX(fabs(d->planes[PLN_CEILING].speed)); ceilspd = spd >> 15; if(!ceilspd) { df |= SDF_CEILING_SPEED_44; ceilspd = spd >> 12; } } // Sector number first. Msg_WriteShort(delta->delta.id); // Flags. Msg_WritePackedLong(df); if(df & SDF_FLOOR_MATERIAL) Msg_WritePackedShort(P_ToMaterialNum(d->planes[PLN_FLOOR].surface.material)); if(df & SDF_CEILING_MATERIAL) Msg_WritePackedShort(P_ToMaterialNum(d->planes[PLN_CEILING].surface.material)); if(df & SDF_LIGHT) { // Must fit into a byte. int lightlevel = (int) (255.0f * d->lightLevel); lightlevel = (lightlevel < 0 ? 0 : lightlevel > 255 ? 255 : lightlevel); Msg_WriteByte((byte) lightlevel); } if(df & SDF_FLOOR_HEIGHT) { Msg_WriteShort(FLT2FIX(d->planes[PLN_FLOOR].height) >> 16); } if(df & SDF_CEILING_HEIGHT) { #ifdef _DEBUG VERBOSE( Con_Printf("Sv_WriteSectorDelta: (%i) Absolute ceiling height=%f\n", delta->delta.id, d->planes[PLN_CEILING].height) ); #endif Msg_WriteShort(FLT2FIX(d->planes[PLN_CEILING].height) >> 16); } if(df & SDF_FLOOR_TARGET) Msg_WriteShort(FLT2FIX(d->planes[PLN_FLOOR].target) >> 16); if(df & SDF_FLOOR_SPEED) // 7.1/4.4 fixed-point Msg_WriteByte(floorspd); if(df & SDF_CEILING_TARGET) Msg_WriteShort(FLT2FIX(d->planes[PLN_CEILING].target) >> 16); if(df & SDF_CEILING_SPEED) // 7.1/4.4 fixed-point Msg_WriteByte(ceilspd); if(df & SDF_COLOR_RED) Msg_WriteByte((byte) (255 * d->rgb[0])); if(df & SDF_COLOR_GREEN) Msg_WriteByte((byte) (255 * d->rgb[1])); if(df & SDF_COLOR_BLUE) Msg_WriteByte((byte) (255 * d->rgb[2])); if(df & SDF_FLOOR_COLOR_RED) Msg_WriteByte((byte) (255 * d->planes[PLN_FLOOR].surface.rgba[0])); if(df & SDF_FLOOR_COLOR_GREEN) Msg_WriteByte((byte) (255 * d->planes[PLN_FLOOR].surface.rgba[1])); if(df & SDF_FLOOR_COLOR_BLUE) Msg_WriteByte((byte) (255 * d->planes[PLN_FLOOR].surface.rgba[2])); if(df & SDF_CEIL_COLOR_RED) Msg_WriteByte((byte) (255 * d->planes[PLN_CEILING].surface.rgba[0])); if(df & SDF_CEIL_COLOR_GREEN) Msg_WriteByte((byte) (255 * d->planes[PLN_CEILING].surface.rgba[1])); if(df & SDF_CEIL_COLOR_BLUE) Msg_WriteByte((byte) (255 * d->planes[PLN_CEILING].surface.rgba[2])); if(df & SDF_FLOOR_GLOW_RED) Msg_WriteByte((byte) (255 * d->planes[PLN_FLOOR].glowRGB[0])); if(df & SDF_FLOOR_GLOW_GREEN) Msg_WriteByte((byte) (255 * d->planes[PLN_FLOOR].glowRGB[1])); if(df & SDF_FLOOR_GLOW_BLUE) Msg_WriteByte((byte) (255 * d->planes[PLN_FLOOR].glowRGB[2])); if(df & SDF_CEIL_GLOW_RED) Msg_WriteByte((byte) (255 * d->planes[PLN_CEILING].glowRGB[0])); if(df & SDF_CEIL_GLOW_GREEN) Msg_WriteByte((byte) (255 * d->planes[PLN_CEILING].glowRGB[1])); if(df & SDF_CEIL_GLOW_BLUE) Msg_WriteByte((byte) (255 * d->planes[PLN_CEILING].glowRGB[2])); if(df & SDF_FLOOR_GLOW) Msg_WriteShort(d->planes[PLN_FLOOR].glow < 0 ? 0 : d->planes[PLN_FLOOR].glow > 1 ? DDMAXSHORT : (short)(d->planes[PLN_FLOOR].glow * DDMAXSHORT)); if(df & SDF_CEIL_GLOW) Msg_WriteShort(d->planes[PLN_CEILING].glow < 0 ? 0 : d->planes[PLN_CEILING].glow > 1 ? DDMAXSHORT : (short)(d->planes[PLN_CEILING].glow * DDMAXSHORT)); } /** * The delta is written to the message buffer. */ void Sv_WriteSideDelta(const void* deltaPtr) { const sidedelta_t* delta = deltaPtr; const dt_side_t* d = &delta->side; int df = delta->delta.flags; // Side number first. Msg_WriteShort(delta->delta.id); // Flags. Msg_WritePackedLong(df); if(df & SIDF_TOP_MATERIAL) Msg_WritePackedShort(P_ToMaterialNum(d->top.material)); if(df & SIDF_MID_MATERIAL) Msg_WritePackedShort(P_ToMaterialNum(d->middle.material)); if(df & SIDF_BOTTOM_MATERIAL) Msg_WritePackedShort(P_ToMaterialNum(d->bottom.material)); if(df & SIDF_LINE_FLAGS) Msg_WriteByte(d->lineFlags); if(df & SIDF_TOP_COLOR_RED) Msg_WriteByte((byte) (255 * d->top.rgba[0])); if(df & SIDF_TOP_COLOR_GREEN) Msg_WriteByte((byte) (255 * d->top.rgba[1])); if(df & SIDF_TOP_COLOR_BLUE) Msg_WriteByte((byte) (255 * d->top.rgba[2])); if(df & SIDF_MID_COLOR_RED) Msg_WriteByte((byte) (255 * d->middle.rgba[0])); if(df & SIDF_MID_COLOR_GREEN) Msg_WriteByte((byte) (255 * d->middle.rgba[1])); if(df & SIDF_MID_COLOR_BLUE) Msg_WriteByte((byte) (255 * d->middle.rgba[2])); if(df & SIDF_MID_COLOR_ALPHA) Msg_WriteByte((byte) (255 * d->middle.rgba[3])); if(df & SIDF_BOTTOM_COLOR_RED) Msg_WriteByte((byte) (255 * d->bottom.rgba[0])); if(df & SIDF_BOTTOM_COLOR_GREEN) Msg_WriteByte((byte) (255 * d->bottom.rgba[1])); if(df & SIDF_BOTTOM_COLOR_BLUE) Msg_WriteByte((byte) (255 * d->bottom.rgba[2])); if(df & SIDF_MID_BLENDMODE) Msg_WriteShort(d->middle.blendMode >> 16); if(df & SIDF_FLAGS) Msg_WriteByte(d->flags); } /** * The delta is written to the message buffer. */ void Sv_WritePolyDelta(const void* deltaPtr) { const polydelta_t* delta = deltaPtr; const dt_poly_t* d = &delta->po; int df = delta->delta.flags; if(d->destAngle == (unsigned) -1) { // Send Perpetual Rotate instead of Dest Angle flag. df |= PODF_PERPETUAL_ROTATE; df &= ~PODF_DEST_ANGLE; } // Poly number first. Msg_WritePackedShort(delta->delta.id); // Flags. Msg_WriteByte(df & 0xff); if(df & PODF_DEST_X) { Msg_WriteShort(FLT2FIX(d->dest.pos[VX]) >> 16); Msg_WriteByte(FLT2FIX(d->dest.pos[VX]) >> 8); } if(df & PODF_DEST_Y) { Msg_WriteShort(FLT2FIX(d->dest.pos[VY]) >> 16); Msg_WriteByte(FLT2FIX(d->dest.pos[VY]) >> 8); } if(df & PODF_SPEED) Msg_WriteShort(FLT2FIX(d->speed) >> 8); if(df & PODF_DEST_ANGLE) Msg_WriteShort(d->destAngle >> 16); if(df & PODF_ANGSPEED) Msg_WriteShort(d->angleSpeed >> 16); } /** * The delta is written to the message buffer. */ void Sv_WriteSoundDelta(const void* deltaPtr) { const sounddelta_t* delta = deltaPtr; int df = delta->delta.flags; // This is either the sound ID, emitter ID or sector index. Msg_WriteShort(delta->delta.id); // First the flags byte. Msg_WriteByte(df & 0xff); switch(delta->delta.type) { case DT_MOBJ_SOUND: case DT_SECTOR_SOUND: case DT_POLY_SOUND: // The sound ID. Msg_WriteShort(delta->sound); break; default: break; } // The common parts. if(df & SNDDF_VOLUME) { if(delta->volume > 1) { // Very loud indeed. Msg_WriteByte(255); } else if(delta->volume <= 0) { // Silence. Msg_WriteByte(0); } else { Msg_WriteByte(delta->volume * 127 + 0.5f); } } } /** * Write the type and possibly the set number (for Unacked deltas). */ void Sv_WriteDeltaHeader(byte type, const delta_t* delta) { #ifdef _DEBUG if(type >= NUM_DELTA_TYPES) { Con_Error("Sv_WriteDeltaHeader: Invalid delta type %i.\n", type); } #endif if(delta->state == DELTA_UNACKED) { // Flag this as Resent. type |= DT_RESENT; } Msg_WriteByte(type); // Include the set number? if(type & DT_RESENT) { // The client will use this to avoid dupes. If the client has already // received the set this delta belongs to, it means the delta has // already been received. This is needed in the situation where the // ack is lost or delayed. Msg_WriteByte(delta->set); // Also send the unique ID of this delta. If the client has already // received a delta with this ID, the delta is discarded. This is // needed in the situation where the set is lost. Msg_WriteByte(delta->resend); } } /** * The delta is written to the message buffer. */ void Sv_WriteDelta(const delta_t* delta) { byte type = delta->type; #ifdef _NETDEBUG int lengthOffset; int endOffset; #endif #ifdef _NETDEBUG // Extra length field in debug builds. lengthOffset = Msg_Offset(); Msg_WriteLong(0); #endif // Null mobj deltas are special. if(type == DT_MOBJ) { if(delta->flags & MDFC_NULL) { // This'll be the entire delta. No more data is needed. Sv_WriteDeltaHeader(DT_NULL_MOBJ, delta); Msg_WriteShort(delta->id); #ifdef _NETDEBUG goto writeDeltaLength; #else return; #endif } } // First the type of the delta. Sv_WriteDeltaHeader(type, delta); switch(delta->type) { case DT_MOBJ: Sv_WriteMobjDelta(delta); break; case DT_PLAYER: Sv_WritePlayerDelta(delta); break; case DT_SECTOR: Sv_WriteSectorDelta(delta); break; case DT_SIDE: Sv_WriteSideDelta(delta); break; case DT_POLY: Sv_WritePolyDelta(delta); break; case DT_SOUND: case DT_MOBJ_SOUND: case DT_SECTOR_SOUND: case DT_POLY_SOUND: Sv_WriteSoundDelta(delta); break; /*case DT_LUMP: Sv_WriteLumpDelta(delta); break; */ default: Con_Error("Sv_WriteDelta: Unknown delta type %i.\n", delta->type); } #ifdef _NETDEBUG writeDeltaLength: // Update the length of the delta. endOffset = Msg_Offset(); Msg_SetOffset(lengthOffset); Msg_WriteLong(endOffset - lengthOffset); Msg_SetOffset(endOffset); #endif } /** * @return An estimate for the maximum frame size appropriate * for the client. The bandwidth rating is updated * whenever a frame is sent. */ size_t Sv_GetMaxFrameSize(int playerNumber) { size_t size = MINIMUM_FRAME_SIZE + FRAME_SIZE_FACTOR * clients[playerNumber].bandwidthRating; // What about the communications medium? if(size > maxDatagramSize) size = maxDatagramSize; return size; } /** * @return A unique resend ID. Never returns zero. */ byte Sv_GetNewResendID(pool_t* pool) { byte id = pool->resendDealer; // Advance to next ID, skipping zero. while(!++pool->resendDealer); return id; } /** * Send a sv_frame packet to the specified player. The amount of data sent * depends on the player's bandwidth rating. */ void Sv_SendFrame(int plrNum) { pool_t* pool = Sv_GetPool(plrNum); byte oldResend; delta_t* delta; int deltaCount = 0; size_t lastStart, maxFrameSize, deltaCountOffset = 0; #if _NETDEBUG int endOffset = 0; #endif // Does the send queue allow us to send this packet? // Bandwidth rating is updated during the check. if(!Sv_CheckBandwidth(plrNum)) { // We cannot send anything at this time. This will only happen if // the send queue has too many packets waiting to be sent. return; } // The priority queue of the client needs to be rebuilt before // a new frame can be sent. Sv_RatePool(pool); // This will be a new set. pool->setDealer++; // Determine the maximum size of the frame packet. maxFrameSize = Sv_GetMaxFrameSize(plrNum); // Allow more info for the first frame. if(pool->isFirst) maxFrameSize = maxDatagramSize; // If this is the first frame after a map change, use the special // first frame packet type. Msg_Begin(pool->isFirst ? PSV_FIRST_FRAME2 : PSV_FRAME2); // The first byte contains the set number, which identifies this // frame. The client will keep track of the numbers to detect // duplicates. Msg_WriteByte(pool->setDealer); // The number of deltas in the packet will be here. deltaCountOffset = Msg_Offset(); #ifdef _NETDEBUG Msg_WriteLong(0); #endif /* #ifdef _DEBUG Con_Printf("set%i\n", pool->setDealer); #endif */ // Keep writing until the maximum size is reached. while((delta = Sv_PoolQueueExtract(pool)) != NULL && (lastStart = Msg_Offset()) < maxFrameSize) { oldResend = pool->resendDealer; // Is this going to be a resent? if(delta->state == DELTA_UNACKED && !delta->resend) { // Assign a new unique ID for this delta. // This ID won't be changed after this. delta->resend = Sv_GetNewResendID(pool); } Sv_WriteDelta(delta); // Did we go over the limit? if(Msg_Offset() > maxFrameSize) { // Time to see if BWR needs to be adjusted. if(clients[plrNum].bwrAdjustTime <= 0) { clients[plrNum].bwrAdjustTime = BWR_ADJUST_TICS; } // Cancel the last delta. Msg_SetOffset(lastStart); // Restore the resend dealer. if(oldResend) pool->resendDealer = oldResend; break; } // Successfully written, increment counter. deltaCount++; /* #ifdef _DEBUG if(delta->state == DELTA_UNACKED) { Con_Printf("Resend: %i, type%i[%x], set%i, rsid%i\n", delta->id, delta->type, delta->flags, delta->set, delta->resend); } #endif */ // Update the sent delta's state. if(delta->state == DELTA_NEW) { // New deltas are assigned to this set. Unacked deltas will // remain in the set they were initially sent in. delta->set = pool->setDealer; delta->timeStamp = Sv_GetTimeStamp(); delta->state = DELTA_UNACKED; } } // Update the number of deltas included in the packet. #ifdef _NETDEBUG endOffset = Msg_Offset(); Msg_SetOffset(deltaCountOffset); Msg_WriteLong(deltaCount); Msg_SetOffset(endOffset); #endif // The PSV_FIRST_FRAME2 packet is sent Ordered, which means it'll // always arrive in the correct order when compared to the other // game setup packets. Net_SendBuffer(plrNum, pool->isFirst ? SPF_ORDERED : 0); // If the target is local, ack immediately. This effectively removes // all the sent deltas from the pool. if(ddPlayers[plrNum].shared.flags & DDPF_LOCAL) { Sv_AckDeltaSet(plrNum, pool->setDealer, 0); } // Now a frame has been sent. pool->isFirst = false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/bsp_edge.c0000644000175000017500000002522411357170241022651 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_edge.c: GL-friendly BSP node builder, half-edges. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_bsp.h" #include "de_misc.h" #include #include #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static zblockset_t *hEdgeBlockSet; static boolean hEdgeAllocatorInited = false; // CODE -------------------------------------------------------------------- static __inline hedge_t *allocHEdge(void) { if(hEdgeAllocatorInited) { // Use the block allocator. hedge_t *hEdge = Z_BlockNewElement(hEdgeBlockSet); memset(hEdge, 0, sizeof(hedge_t)); return hEdge; } return M_Calloc(sizeof(hedge_t)); } static __inline void freeHEdge(hedge_t *hEdge) { if(hEdgeAllocatorInited) { // Ignore, it'll be free'd along with the block allocator. return; } M_Free(hEdge); } static __inline edgetip_t *allocEdgeTip(void) { return M_Calloc(sizeof(edgetip_t)); } static __inline void freeEdgeTip(edgetip_t *tip) { M_Free(tip); } /** * Init the half-edge block allocator. */ void BSP_InitHEdgeAllocator(void) { if(hEdgeAllocatorInited) return; // Already been here. hEdgeBlockSet = Z_BlockCreate(sizeof(hedge_t), 512, PU_STATIC); hEdgeAllocatorInited = true; } /** * Shutdown the half-edge block allocator. All elements will be free'd! */ void BSP_ShutdownHEdgeAllocator(void) { if(hEdgeAllocatorInited) { Z_BlockDestroy(hEdgeBlockSet); hEdgeBlockSet = NULL; hEdgeAllocatorInited = false; } } /** * Update the precomputed members of the hedge. */ static void updateHEdge(hedge_t *hedge) { hedge->pSX = hedge->v[0]->buildData.pos[VX]; hedge->pSY = hedge->v[0]->buildData.pos[VY]; hedge->pEX = hedge->v[1]->buildData.pos[VX]; hedge->pEY = hedge->v[1]->buildData.pos[VY]; hedge->pDX = hedge->pEX - hedge->pSX; hedge->pDY = hedge->pEY - hedge->pSY; hedge->pLength = M_Length(hedge->pDX, hedge->pDY); hedge->pAngle = M_SlopeToAngle(hedge->pDX, hedge->pDY); if(hedge->pLength <= 0) Con_Error("Hedge %p has zero p_length.", hedge); hedge->pPerp = hedge->pSY * hedge->pDX - hedge->pSX * hedge->pDY; hedge->pPara = -hedge->pSX * hedge->pDX - hedge->pSY * hedge->pDY; } /** * Create a new half-edge. */ hedge_t *HEdge_Create(linedef_t *line, linedef_t *sourceLine, vertex_t *start, vertex_t *end, sector_t *sec, boolean back) { hedge_t *hEdge = allocHEdge(); hEdge->v[0] = start; hEdge->v[1] = end; hEdge->lineDef = line; hEdge->side = (back? 1 : 0); hEdge->sector = sec; hEdge->twin = NULL; hEdge->nextOnSide = hEdge->prevOnSide = NULL; hEdge->sourceLine = sourceLine; hEdge->index = -1; updateHEdge(hEdge); return hEdge; } /** * Destroys the given half-edge. * * @param hEdge Ptr to the half-edge to be destroyed. */ void HEdge_Destroy(hedge_t *hEdge) { if(hEdge) { freeHEdge(hEdge); } } /** * Splits the given half-edge at the point (x,y). The new half-edge is * returned. The old half-edge is shortened (the original start vertex is * unchanged), the new half-edge becomes the cut-off tail (keeping the * original end vertex). * * \note * If the half-edge has a twin, it is also split and is inserted into the * same list as the original (and after it), thus all half-edges (except the * one we are currently splitting) must exist on a singly-linked list * somewhere. * * \note * We must update the count values of any superblock that contains the * half-edge (and/or backseg), so that future processing is not messed up by * incorrect counts. */ hedge_t *HEdge_Split(hedge_t *oldHEdge, double x, double y) { hedge_t *newHEdge; vertex_t *newVert; /*#if _DEBUG if(oldHEdge->lineDef) Con_Message("Splitting Linedef %d (%p) at (%1.1f,%1.1f)\n", oldHEdge->lineDef->index, oldHEdge, x, y); else Con_Message("Splitting MiniHEdge %p at (%1.1f,%1.1f)\n", oldHEdge, x, y); #endif*/ // Update superblock, if needed. if(oldHEdge->block) BSP_IncSuperBlockHEdgeCounts(oldHEdge->block, (oldHEdge->lineDef != NULL)); /** * Create a new vertex (with correct wall_tip info) for the split that * happens along the given half-edge at the given location. */ newVert = createVertex(); newVert->buildData.pos[VX] = x; newVert->buildData.pos[VY] = y; newVert->buildData.refCount = (oldHEdge->twin? 4 : 2); // Compute wall_tip info. BSP_CreateVertexEdgeTip(newVert, -oldHEdge->pDX, -oldHEdge->pDY, oldHEdge, oldHEdge->twin); BSP_CreateVertexEdgeTip(newVert, oldHEdge->pDX, oldHEdge->pDY, oldHEdge->twin, oldHEdge); newHEdge = allocHEdge(); // Copy the old half-edge info. memcpy(newHEdge, oldHEdge, sizeof(hedge_t)); newHEdge->next = NULL; newHEdge->prevOnSide = oldHEdge; oldHEdge->nextOnSide = newHEdge; oldHEdge->v[1] = newVert; updateHEdge(oldHEdge); newHEdge->v[0] = newVert; updateHEdge(newHEdge); /*#if _DEBUG Con_Message("Splitting Vertex is %04X at (%1.1f,%1.1f)\n", newVert->index, newVert->V_pos[VX], newVert->V_pos[VY]); #endif*/ // Handle the twin. if(oldHEdge->twin) { /*#if _DEBUG Con_Message("Splitting hEdge->twin %p\n", oldHEdge->twin); #endif*/ // Update superblock, if needed. if(oldHEdge->twin->block) BSP_IncSuperBlockHEdgeCounts(oldHEdge->twin->block, (oldHEdge->twin != NULL)); newHEdge->twin = allocHEdge(); // Copy seg info. memcpy(newHEdge->twin, oldHEdge->twin, sizeof(hedge_t)); // It is important to keep the twin relationship valid. newHEdge->twin->twin = newHEdge; newHEdge->twin->nextOnSide = oldHEdge->twin; oldHEdge->twin->prevOnSide = newHEdge->twin; oldHEdge->twin->v[0] = newVert; updateHEdge(oldHEdge->twin); newHEdge->twin->v[1] = newVert; updateHEdge(newHEdge->twin); // Link it into list. oldHEdge->twin->next = newHEdge->twin; } return newHEdge; } void BSP_CreateVertexEdgeTip(vertex_t *vert, double dx, double dy, hedge_t *back, hedge_t *front) { edgetip_t *tip = allocEdgeTip(); edgetip_t *after; tip->angle = M_SlopeToAngle(dx, dy); tip->ET_edge[BACK] = back; tip->ET_edge[FRONT] = front; // Find the correct place (order is increasing angle). for(after = vert->buildData.tipSet; after && after->ET_next; after = after->ET_next); while(after && tip->angle + ANG_EPSILON < after->angle) after = after->ET_prev; // Link it in. if(after) tip->ET_next = after->ET_next; else tip->ET_next = vert->buildData.tipSet; tip->ET_prev = after; if(after) { if(after->ET_next) after->ET_next->ET_prev = tip; after->ET_next = tip; } else { if(vert->buildData.tipSet) vert->buildData.tipSet->ET_prev = tip; vert->buildData.tipSet = tip; } } void BSP_DestroyVertexEdgeTip(edgetip_t *tip) { if(tip) { freeEdgeTip(tip); } } /** * Check whether a line with the given delta coordinates and beginning * at this vertex is open. Returns a sector reference if it's open, * or NULL if closed (void space or directly along a linedef). */ sector_t *BSP_VertexCheckOpen(vertex_t *vert, double dX, double dY) { edgetip_t *tip; angle_g angle = M_SlopeToAngle(dX, dY); // First check whether there's a wall_tip that lies in the exact // direction of the given direction (which is relative to the // vertex). for(tip = vert->buildData.tipSet; tip; tip = tip->ET_next) { angle_g diff = fabs(tip->angle - angle); if(diff < ANG_EPSILON || diff > (360.0 - ANG_EPSILON)) { // Yes, found one. return NULL; } } // OK, now just find the first wall_tip whose angle is greater than // the angle we're interested in. Therefore we'll be on the FRONT // side of that tip edge. for(tip = vert->buildData.tipSet; tip; tip = tip->ET_next) { if(angle + ANG_EPSILON < tip->angle) { // Found it. return (tip->ET_edge[FRONT]? tip->ET_edge[FRONT]->sector : NULL); } if(!tip->ET_next) { // No more tips, thus we must be on the BACK side of the tip // with the largest angle. return (tip->ET_edge[BACK]? tip->ET_edge[BACK]->sector : NULL); } } Con_Error("Vertex %d has no tips !", vert->buildData.index); return NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_shadow.c0000644000175000017500000001677211357170242023407 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_shadow.c: Map Object Shadows */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_render.h" #include "de_play.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int useShadows = true; static int shadowMaxRad = 80; static int shadowMaxDist = 1000; static float shadowFactor = 0.5f; // CODE -------------------------------------------------------------------- void Rend_ShadowRegister(void) { // Cvars C_VAR_INT("rend-shadow", &useShadows, 0, 0, 1); C_VAR_FLOAT("rend-shadow-darkness", &shadowFactor, 0, 0, 1); C_VAR_INT("rend-shadow-far", &shadowMaxDist, CVF_NO_MAX, 0, 0); C_VAR_INT("rend-shadow-radius-max", &shadowMaxRad, CVF_NO_MAX, 0, 0); } /** * This is called for each sector a shadow-caster is touching. * The highest floor height will be searched and if larger than the * value of 'data' it will be written back. * * @param sector The sector to search the floor height of. * @param data Ptr to plane_t for comparison. * * @return @c true, if iteration should continue. */ static boolean Rend_ShadowIterator(sector_t *sector, void *data) { plane_t **highest = (plane_t**) data; plane_t *compare = sector->SP_plane(PLN_FLOOR); if(compare->visHeight > (*highest)->visHeight) *highest = compare; return true; // Continue iteration. } static void processMobjShadow(mobj_t* mo) { #define SHADOWZOFFSET (0.2f) float moz; float height, moh, halfmoh, alpha, pos[2]; sector_t* sec = mo->subsector->sector; float radius; uint i; rvertex_t rvertices[4]; rcolor_t rcolors[4]; rtexcoord_t rtexcoords[4]; rtexmapunit_t rTU[NUM_TEXMAP_UNITS]; plane_t* plane; float distance; // Is this too far? pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; if((distance = Rend_PointDist2D(pos)) > shadowMaxDist) return; // Apply a Short Range Visual Offset? if(useSRVO && mo->state && mo->tics >= 0) { float mul = mo->tics / (float) mo->state->tics; pos[VX] += mo->srvo[VX] * mul; pos[VY] += mo->srvo[VY] * mul; } // Check the height. moz = mo->pos[VZ] - mo->floorClip; if(mo->ddFlags & DDMF_BOB) moz -= R_GetBobOffset(mo); height = moz - mo->floorZ; moh = mo->height; if(!moh) moh = 1; if(height > moh) return; // Too far. if(moz + mo->height < mo->floorZ) return; // Calculate the strength of the shadow. // Simplified version, no light diminishing or range compression. alpha = shadowFactor * sec->lightLevel * (1 - mo->translucency * reciprocal255); halfmoh = moh / 2; if(height > halfmoh) alpha *= 1 - (height - halfmoh) / (moh - halfmoh); if(usingFog) alpha /= 2; if(distance > 3 * shadowMaxDist / 4) { // Fade when nearing the maximum distance. alpha *= (shadowMaxDist - distance) / (shadowMaxDist / 4); } if(alpha <= 0) return; // Can't be seen. if(alpha > 1) alpha = 1; // Calculate the radius of the shadow. radius = R_VisualRadius(mo); if(!(radius > 0)) return; if(radius > (float) shadowMaxRad) radius = (float) shadowMaxRad; // Figure out the visible floor height. plane = mo->subsector->sector->SP_plane(PLN_FLOOR); P_MobjSectorsIterator(mo, Rend_ShadowIterator, &plane); if(plane->visHeight >= moz + mo->height) return; // Can't have a shadow above the object! // View height might prevent us from seeing the shadow. if(vy < plane->visHeight) return; // Don't render mobj shadows on sky floors or glowing surfaces. if(R_IsGlowingPlane(plane)) return; // Prepare the poly. memset(rTU, 0, sizeof(rTU)); rTU[TU_PRIMARY].tex = GL_PrepareLSTexture(LST_DYNAMIC); rTU[TU_PRIMARY].magMode = GL_LINEAR; rTU[TU_PRIMARY].blend = 1; rvertices[0].pos[VX] = pos[VX] - radius; rvertices[0].pos[VY] = pos[VY] + radius; rvertices[0].pos[VZ] = plane->visHeight + SHADOWZOFFSET; rtexcoords[0].st[0] = 0; rtexcoords[0].st[1] = 1; rvertices[1].pos[VX] = pos[VX] + radius; rvertices[1].pos[VY] = pos[VY] + radius; rvertices[1].pos[VZ] = plane->visHeight + SHADOWZOFFSET; rtexcoords[1].st[0] = 1; rtexcoords[1].st[1] = 1; rvertices[2].pos[VX] = pos[VX] + radius; rvertices[2].pos[VY] = pos[VY] - radius; rvertices[2].pos[VZ] = plane->visHeight + SHADOWZOFFSET; rtexcoords[2].st[0] = 1; rtexcoords[2].st[1] = 0; rvertices[3].pos[VX] = pos[VX] - radius; rvertices[3].pos[VY] = pos[VY] - radius; rvertices[3].pos[VZ] = plane->visHeight + SHADOWZOFFSET; rtexcoords[3].st[0] = 0; rtexcoords[3].st[1] = 0; // Shadows are black. for(i = 0; i < 4; ++i) { rcolors[i].rgba[CR] = rcolors[i].rgba[CG] = rcolors[i].rgba[CB] = 0; rcolors[i].rgba[CA] = alpha; } RL_AddPoly(PT_FAN, RPT_SHADOW, rvertices, rtexcoords, NULL, NULL, rcolors, 4, 0, 0, NULL, rTU); #undef SHADOWZOFFSET } void Rend_RenderShadows(void) { sector_t *sec; mobj_t *mo; uint i; if(!useShadows || levelFullBright) return; // Check all mobjs in all visible sectors. for(i = 0; i < numSectors; ++i) { sec = SECTOR_PTR(i); if(!(sec->frameFlags & SIF_VISIBLE)) continue; for(mo = sec->mobjList; mo; mo = mo->sNext) { if(!mo->state) continue; // Should this mobj have a shadow? if((mo->state->flags & STF_FULLBRIGHT) || (mo->ddFlags & DDMF_DONTDRAW) || (mo->ddFlags & DDMF_ALWAYSLIT)) continue; processMobjShadow(mo); } } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_main.c0000644000175000017500000007705311357170242022504 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_main.c: Engine Core */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # define _WIN32_DCOM # include #endif #include "de_platform.h" #ifdef WIN32 # include #endif #ifdef UNIX # include # include #endif #include #include #include #include #include #include "de_base.h" #include "de_system.h" #include "de_console.h" #include "de_network.h" #include "de_play.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_audio.h" #include "de_misc.h" #include "de_dam.h" #include "dd_pinit.h" // MACROS ------------------------------------------------------------------ #define MAXWADFILES (4096) // TYPES ------------------------------------------------------------------- typedef struct ddvalue_s { int* readPtr; int* writePtr; } ddvalue_t; typedef struct autoload_s { boolean loadFiles; // Should files be loaded right away. int count; // Number of files loaded successfully. } autoload_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void G_CheckDemoStatus(void); void F_Drawer(void); void S_InitScript(void); void Net_Drawer(void); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static int DD_StartupWorker(void* parm); static int DD_StartupWorker2(void* parm); static void HandleArgs(int state); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- #ifdef WIN32 extern HINSTANCE hInstDGL; #endif extern int renderTextures; extern char skyFlatName[9]; extern int gotFrame; extern int monochrome; extern int gameDataFormat; extern int gameDrawHUD; extern int symbolicEchoMode; // PUBLIC DATA DEFINITIONS ------------------------------------------------- directory_t ddRuntimeDir, ddBinDir; int verbose = 0; // For debug messages (-verbose). boolean cmdfrag; // true if a CMD_FRAG packet should be sent out int isDedicated = false; int maxZone = 0x2000000; // Default zone heap. (32meg) boolean autoStart; FILE* outFile; // Output file for console messages. char* iwadList[64]; char* defaultWads = ""; // List of wad names, whitespace seperating(in .cfg). filename_t configFileName; filename_t bindingsConfigFileName; filename_t defsFileName, topDefsFileName; filename_t ddBasePath = ""; // Doomsday root directory is at...? // PRIVATE DATA DEFINITIONS ------------------------------------------------ static char *wadFiles[MAXWADFILES]; // CODE -------------------------------------------------------------------- /** * Convert propertyType enum constant into a string for error/debug messages. */ const char* value_Str(int val) { static char valStr[40]; struct val_s { int val; const char* str; } valuetypes[] = { { DDVT_BOOL, "DDVT_BOOL" }, { DDVT_BYTE, "DDVT_BYTE" }, { DDVT_SHORT, "DDVT_SHORT" }, { DDVT_INT, "DDVT_INT" }, { DDVT_UINT, "DDVT_UINT" }, { DDVT_FIXED, "DDVT_FIXED" }, { DDVT_ANGLE, "DDVT_ANGLE" }, { DDVT_FLOAT, "DDVT_FLOAT" }, { DDVT_LONG, "DDVT_LONG" }, { DDVT_ULONG, "DDVT_ULONG" }, { DDVT_PTR, "DDVT_PTR" }, { DDVT_BLENDMODE, "DDVT_BLENDMODE" }, { 0, NULL } }; uint i; for(i = 0; valuetypes[i].str; ++i) if(valuetypes[i].val == val) return valuetypes[i].str; sprintf(valStr, "(unnamed %i)", val); return valStr; } /** * Adds the given IWAD to the list of default IWADs. */ void DD_AddIWAD(const char* path) { int i = 0; filename_t buf; while(iwadList[i]) i++; M_TranslatePath(buf, path, FILENAME_T_MAXLEN); iwadList[i] = M_Calloc(strlen(buf) + 1); // This mem is not freed? strcpy(iwadList[i], buf); } #define ATWSEPS ",; \t" static void AddToWadList(char* list) { size_t len = strlen(list); char *buffer = M_Malloc(len + 1), *token; strcpy(buffer, list); token = strtok(buffer, ATWSEPS); while(token) { DD_AddStartupWAD(token /*, false */ ); token = strtok(NULL, ATWSEPS); } M_Free(buffer); } /** * (f_forall_func_t) */ static int autoDataAdder(const char *fileName, filetype_t type, void* ptr) { autoload_t* data = ptr; // Skip directories. if(type == FT_DIRECTORY) return true; if(data->loadFiles) { if(W_AddFile(fileName, false)) ++data->count; } else { DD_AddStartupWAD(fileName); } // Continue searching. return true; } /** * Files with the extensions wad, lmp, pk3, zip and deh in the automatical data * directory are added to the wadFiles list. * * @return Number of new files that were loaded. */ int DD_AddAutoData(boolean loadFiles) { autoload_t data; const char* extensions[] = { "wad", "lmp", "pk3", "zip", "deh", #ifdef UNIX "WAD", "LMP", "PK3", "ZIP", "DEH", // upper case alternatives #endif NULL }; filename_t pattern; uint i; data.loadFiles = loadFiles; data.count = 0; for(i = 0; extensions[i]; ++i) { dd_snprintf(pattern, FILENAME_T_MAXLEN, "%sauto\\*.%s", R_GetDataPath(), extensions[i]); Dir_FixSlashes(pattern, FILENAME_T_MAXLEN); F_ForAll(pattern, &data, autoDataAdder); } return data.count; } void DD_SetConfigFile(const char* file) { strncpy(configFileName, file, FILENAME_T_MAXLEN); configFileName[FILENAME_T_LASTINDEX] = '\0'; Dir_FixSlashes(configFileName, FILENAME_T_MAXLEN); strncpy(bindingsConfigFileName, configFileName, FILENAME_T_MAXLEN); bindingsConfigFileName[FILENAME_T_LASTINDEX] = '\0'; strncpy(bindingsConfigFileName + strlen(bindingsConfigFileName) - 4, "-bindings.cfg", FILENAME_T_MAXLEN - strlen(bindingsConfigFileName) - 4); bindingsConfigFileName[FILENAME_T_LASTINDEX] = '\0'; } /** * Set the primary DED file, which is included immediately after * Doomsday.ded. */ void DD_SetDefsFile(const char* file) { dd_snprintf(topDefsFileName, FILENAME_T_MAXLEN, "%sdefs\\%s", ddBasePath, file); Dir_FixSlashes(topDefsFileName, FILENAME_T_MAXLEN); } /** * Define Auto mappings for the runtime directory. */ void DD_DefineBuiltinVDM(void) { filename_t dest; // Data files. dd_snprintf(dest, FILENAME_T_MAXLEN, "%sauto", R_GetDataPath()); F_AddMapping("auto", dest); // Definition files. Def_GetAutoPath(dest, FILENAME_T_MAXLEN); F_AddMapping("auto", dest); } /** * Looks for new files to autoload. Runs until there are no more files to * autoload. */ void DD_AutoLoad(void) { int p; /** * Load files from the Auto directory. (If already loaded, won't * be loaded again.) This is done again because virtual files may * now exist in the Auto directory. Repeated until no new files * found. */ while((p = DD_AddAutoData(true)) > 0) { VERBOSE(Con_Message("Autoload round completed with %i new files.\n", p)); } } /** * Engine and game initialization. When complete, starts the game loop. */ int DD_Main(void) { int winWidth, winHeight, winBPP, winX, winY; uint winFlags = DDWF_VISIBLE | DDWF_CENTER; boolean noCenter = false; int exitCode; // By default, use the resolution defined in (default).cfg. winX = 0; winY = 0; winWidth = defResX; winHeight = defResY; winBPP = defBPP; winFlags |= (defFullscreen? DDWF_FULLSCREEN : 0); // Check for command line options modifying the defaults. if(ArgCheckWith("-width", 1)) winWidth = atoi(ArgNext()); if(ArgCheckWith("-height", 1)) winHeight = atoi(ArgNext()); if(ArgCheckWith("-winsize", 2)) { winWidth = atoi(ArgNext()); winHeight = atoi(ArgNext()); } if(ArgCheckWith("-bpp", 1)) winBPP = atoi(ArgNext()); // Ensure a valid value. if(winBPP != 16 && winBPP != 32) winBPP = 32; if(ArgCheck("-nocenter")) noCenter = true; if(ArgCheckWith("-xpos", 1)) { winX = atoi(ArgNext()); noCenter = true; } if(ArgCheckWith("-ypos", 1)) { winY = atoi(ArgNext()); noCenter = true; } if(noCenter) winFlags &= ~DDWF_CENTER; if(ArgExists("-nofullscreen") || ArgExists("-window")) winFlags &= ~DDWF_FULLSCREEN; if(!Sys_SetWindow(windowIDX, winX, winY, winWidth, winHeight, winBPP, winFlags, 0)) return -1; if(!isDedicated) { if(!GL_EarlyInit()) { Sys_CriticalMessage("GL_EarlyInit() failed."); return -1; } } /** * \note This must be called from the main thread due to issues with * the devices we use via the WINAPI, MCI (cdaudio, mixer etc). */ Con_Message("Sys_Init: Setting up machine state.\n"); Sys_Init(); // Enter busy mode until startup complete. Con_InitProgress(200); Con_Busy(BUSYF_NO_UPLOADS | BUSYF_STARTUP | BUSYF_PROGRESS_BAR | (verbose? BUSYF_CONSOLE_OUTPUT : 0), "Starting up...", DD_StartupWorker, NULL); // Engine initialization is complete. Now finish up with the GL. if(!isDedicated) { GL_Init(); GL_InitRefresh(); // \todo we could be loading these in busy mode. GL_LoadSystemTextures(); } // Do deferred uploads. Con_Busy(BUSYF_PROGRESS_BAR | BUSYF_STARTUP | BUSYF_ACTIVITY | (verbose? BUSYF_CONSOLE_OUTPUT : 0), NULL, DD_StartupWorker2, NULL); // Client connection command. if(ArgCheckWith("-connect", 1)) Con_Executef(CMDS_CMDLINE, false, "connect %s", ArgNext()); // Server start command. // (shortcut for -command "net init tcpip; net server start"). if(ArgExists("-server")) { if(!N_InitService(true)) Con_Message("Can't start server: network init failed.\n"); else Con_Executef(CMDS_CMDLINE, false, "net server start"); } // Final preparations for using the console UI. Con_InitUI(); // Start the game loop. exitCode = DD_GameLoop(); // Time to shutdown. if(netGame) { // Quit netGame if one is in progress. Con_Execute(CMDS_DDAY, isServer ? "net server close" : "net disconnect", true, false); } Demo_StopPlayback(); Con_SaveDefaults(); Sys_Shutdown(); B_Shutdown(); return exitCode; } static int DD_StartupWorker(void *parm) { int p = 0; float starttime; #ifdef WIN32 // Initialize COM for this thread (needed for DirectInput). CoInitialize(NULL); #endif F_InitMapping(); // Initialize the key mappings. DD_InitInput(); Con_SetProgress(10); // Any startup hooks? Plug_DoHook(HOOK_STARTUP, 0, 0); Con_SetProgress(20); DD_AddStartupWAD("}data\\doomsday.pk3"); R_SetDataPath("}data\\"); // The name of the .cfg will invariably be overwritten by the Game. strncpy(configFileName, "doomsday.cfg", FILENAME_T_MAXLEN); dd_snprintf(defsFileName, FILENAME_T_MAXLEN, "%sdefs\\doomsday.ded", ddBasePath); // Was the change to userdir OK? if(!app.userDirOk) Con_Message("--(!)-- User directory not found " "(check -userdir).\n"); bamsInit(); // Binary angle calculations. // Initialize the zip file database. Zip_Init(); Def_Init(); autoStart = false; HandleArgs(0); // Everything but WADs. novideo = ArgCheck("-novideo") || isDedicated; DAM_Init(); if(gx.PreInit) gx.PreInit(); Con_SetProgress(40); // We now accept no more custom properties. //DAM_LockCustomPropertys(); // Automatically create an Auto mapping in the runtime directory. DD_DefineBuiltinVDM(); // Initialize subsystems Net_Init(); // Network before anything else. // Now we can hide the mouse cursor for good. Sys_HideMouse(); // Load defaults before initing other systems Con_Message("Parsing configuration files.\n"); // Check for a custom config file. if(ArgCheckWith("-config", 1)) { // This will override the default config file. strcpy(configFileName, ArgNext()); Con_Message("Custom config file: %s\n", configFileName); } // This'll be the default config file. Con_ParseCommands(configFileName, true); // Parse additional files (that should be parsed BEFORE init). if(ArgCheckWith("-cparse", 1)) { for(;;) { const char* arg = ArgNext(); if(!arg || arg[0] == '-') break; Con_Message("Parsing: %s\n", arg); Con_ParseCommands(arg, false); } } Con_SetProgress(50); if(defaultWads && defaultWads[0]) AddToWadList(defaultWads); // These must take precedence. HandleArgs(1); // Only the WADs. Con_Message("W_Init: Init WADfiles.\n"); starttime = Sys_GetSeconds(); // Add real files from the Auto directory to the wadFiles list. DD_AddAutoData(false); Con_SetProgress(60); W_InitMultipleFiles(wadFiles); F_InitDirec(); VERBOSE(Con_Message("W_Init: Done in %.2f seconds.\n", Sys_GetSeconds() - starttime)); Con_SetProgress(70); // Load help resources. Now virtual files are available as well. if(!isDedicated) DD_InitHelp(); // Final autoload round. DD_AutoLoad(); Con_SetProgress(80); // No more WADs will be loaded in startup mode after this point. W_EndStartup(); // Execute the startup script (Startup.cfg). Con_ParseCommands("startup.cfg", false); // Now the game can identify the game mode. gx.UpdateState(DD_GAME_MODE); Con_SetProgress(90); // We can now initialize the resource locator (game mode identified). R_InitResourceLocator(); Con_SetProgress(100); GL_EarlyInitTextureManager(); // Get the material manager up and running. P_InitMaterialManager(); R_InitTextures(); R_InitFlats(); R_PreInitSprites(); Con_SetProgress(130); // Now that we've generated the auto-materials we can initialize // definitions. Def_Read(); #ifdef WIN32 if(ArgCheck("-nowsk")) // No Windows system keys? { // Disable Alt-Tab, Alt-Esc, Ctrl-Alt-Del. // A bit of a hack, I'm afraid... SystemParametersInfo(SPI_SETSCREENSAVERRUNNING, TRUE, 0, 0); Con_Message("Windows system keys disabled.\n"); } #endif if(ArgCheckWith("-dumplump", 1)) { const char* lumpName = ArgNext(); lumpnum_t lump; if((lump = W_CheckNumForName(lumpName)) != -1) W_DumpLump(lump, NULL); } if(ArgCheck("-dumpwaddir")) W_DumpLumpDir(); Con_SetProgress(140); Con_Message("B_Init: Init bindings.\n"); B_Init(); Con_ParseCommands(bindingsConfigFileName, false); Con_SetProgress(150); Con_Message("R_Init: Init the refresh daemon.\n"); R_Init(); Con_SetProgress(165); Con_Message("Net_InitGame: Initializing game data.\n"); Net_InitGame(); Demo_Init(); if(gx.PostInit) gx.PostInit(); Con_SetProgress(175); // Defs have been read; we can now init the map format info. P_InitData(); Con_SetProgress(190); // Try to load the autoexec file. This is done here to make sure // everything is initialized: the user can do here anything that // s/he'd be able to do in the game. Con_ParseCommands("autoexec.cfg", false); // Parse additional files. if(ArgCheckWith("-parse", 1)) { for(;;) { const char* arg = ArgNext(); if(!arg || arg[0] == '-') break; Con_Message("Parsing: %s\n", arg); Con_ParseCommands(arg, false); } } // A console command on the command line? for(p = 1; p < Argc() - 1; p++) { if(stricmp(Argv(p), "-command") && stricmp(Argv(p), "-cmd")) continue; for(++p; p < Argc(); p++) { const char* arg = Argv(p); if(arg[0] == '-') { p--; break; } Con_Execute(CMDS_CMDLINE, arg, false, false); } } // In dedicated mode the console must be opened, so all input events // will be handled by it. if(isDedicated) Con_Open(true); Con_SetProgress(199); Plug_DoHook(HOOK_INIT, 0, 0); // Any initialization hooks? Con_UpdateKnownWords(); // For word completion (with Tab). Con_SetProgress(200); #ifdef WIN32 // This thread has finished using COM. CoUninitialize(); #endif Con_BusyWorkerEnd(); return 0; } /** * This only exists so we have something to call while the deferred uploads of the * startup are processed. */ static int DD_StartupWorker2(void *parm) { Con_SetProgress(200); Con_BusyWorkerEnd(); return 0; } static void HandleArgs(int state) { int order, p; if(state == 0) { renderTextures = !ArgExists("-notex"); } // Process all -iwad and -file options. -iwad options are processed // first so that the loading order remains correct. if(state) { for(order = 0; order < 2; order++) { for(p = 0; p < Argc(); p++) { if((order == 1 && !ArgRecognize("-file", Argv(p))) || (order == 0 && !ArgRecognize("-iwad", Argv(p)))) continue; while(++p != Argc() && !ArgIsOption(p)) DD_AddStartupWAD(Argv(p)); p--;/* For ArgIsOption(p) necessary, for p==Argc() harmless */ } } } } void DD_CheckTimeDemo(void) { static boolean checked = false; if(!checked) { checked = true; if(ArgCheckWith("-timedemo", 1) || // Timedemo mode. ArgCheckWith("-playdemo", 1)) // Play-once mode. { char buf[200]; sprintf(buf, "playdemo %s", ArgNext()); Con_Execute(CMDS_CMDLINE, buf, false, false); } } } /** * This is a 'public' WAD file addition routine. The caller can put a * greater-than character (>) in front of the name to prepend the base * path to the file name (providing it's a relative path). */ void DD_AddStartupWAD(const char* file) { int i; char* new; filename_t temp; i = 0; while(wadFiles[i]) i++; M_TranslatePath(temp, file, FILENAME_T_MAXLEN); new = M_Calloc(strlen(temp) + 1); // This is never freed? strcat(new, temp); wadFiles[i] = new; } static int DD_UpdateWorker(void* parm) { GL_InitRefresh(); R_Update(); Con_BusyWorkerEnd(); return 0; } void DD_UpdateEngineState(void) { boolean hadFog; // Update refresh. Con_Message("Updating state...\n"); // Update the dir/WAD translations. F_InitDirec(); gx.UpdateState(DD_PRE); // Stop playing sounds and music. Demo_StopPlayback(); S_Reset(); //GL_InitVarFont(); /*glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, theWindow->width, theWindow->height, 0, -1, 1);*/ hadFog = usingFog; GL_TotalReset(); GL_TotalRestore(); // Bring GL back online. // Make sure the fog is enabled, if necessary. if(hadFog) GL_UseFog(true); // Now that GL is back online, we can continue the update in busy mode. Con_InitProgress(200); Con_Busy(BUSYF_ACTIVITY | BUSYF_PROGRESS_BAR | (verbose? BUSYF_CONSOLE_OUTPUT : 0), "Updating engine state...", DD_UpdateWorker, NULL); //GL_ShutdownVarFont(); /*glMatrixMode(GL_PROJECTION); glPopMatrix();*/ gx.UpdateState(DD_POST); // Reset the anim groups (if in-game) R_ResetAnimGroups(); } /* *INDENT-OFF* */ ddvalue_t ddValues[DD_LAST_VALUE - DD_FIRST_VALUE - 1] = { {&netGame, 0}, {&isServer, 0}, // An *open* server? {&isClient, 0}, {&allowFrames, &allowFrames}, {&viewwindowx, &viewwindowx}, {&viewwindowy, &viewwindowy}, {&viewwidth, &viewwidth}, {&viewheight, &viewheight}, {&consolePlayer, &consolePlayer}, {&displayPlayer, &displayPlayer}, {&mipmapping, 0}, {&linearRaw, 0}, {&defResX, &defResX}, {&defResY, &defResY}, {&skyDetail, 0}, {&sfxVolume, &sfxVolume}, {&musVolume, &musVolume}, {0, 0}, //{&mouseInverseY, &mouseInverseY}, {&levelFullBright, &levelFullBright}, {&CmdReturnValue, 0}, {&gameReady, &gameReady}, {&isDedicated, 0}, {&novideo, 0}, {&defs.count.mobjs.num, 0}, {&gotFrame, 0}, {&playback, 0}, {&defs.count.sounds.num, 0}, {&defs.count.music.num, 0}, {&numLumps, 0}, {&clientPaused, &clientPaused}, {&weaponOffsetScaleY, &weaponOffsetScaleY}, {&monochrome, &monochrome}, {&gameDataFormat, &gameDataFormat}, {&gameDrawHUD, 0}, {&upscaleAndSharpenPatches, &upscaleAndSharpenPatches}, {&symbolicEchoMode, &symbolicEchoMode}, {&GL_state.maxTexUnits, 0} }; /* *INDENT-ON* */ /** * Get a 32-bit signed integer value. */ int DD_GetInteger(int ddvalue) { if(ddvalue >= DD_LAST_VALUE || ddvalue <= DD_FIRST_VALUE) { // How about some specials? switch(ddvalue) { case DD_DYNLIGHT_TEXTURE: return (int) GL_PrepareLSTexture(LST_DYNAMIC); case DD_MAP_MUSIC: { gamemap_t *map = P_GetCurrentMap(); ded_mapinfo_t *mapInfo = Def_GetMapInfo(P_GetMapID(map)); if(mapInfo) return Def_GetMusicNum(mapInfo->music); return -1; } case DD_WINDOW_WIDTH: return theWindow->width; case DD_WINDOW_HEIGHT: return theWindow->height; default: break; } return 0; } if(ddValues[ddvalue].readPtr == NULL) return 0; return *ddValues[ddvalue].readPtr; } /** * Set a 32-bit signed integer value. */ void DD_SetInteger(int ddvalue, int parm) { if(ddvalue <= DD_FIRST_VALUE || ddvalue >= DD_LAST_VALUE) { // How about some special values? return; } if(ddValues[ddvalue].writePtr) *ddValues[ddvalue].writePtr = parm; } /** * Get a pointer to the value of a variable. Not all variables support * this. Added for 64-bit support. */ void* DD_GetVariable(int ddvalue) { if(ddvalue >= DD_LAST_VALUE || ddvalue <= DD_FIRST_VALUE) { // How about some specials? switch(ddvalue) { case DD_GAME_EXPORTS: return &gx; case DD_VIEW_X: return &viewX; case DD_VIEW_Y: return &viewY; case DD_VIEW_Z: return &viewZ; case DD_VIEW_ANGLE: return &viewAngle; case DD_VIEW_PITCH: return &viewPitch; case DD_SECTOR_COUNT: return &numSectors; case DD_LINE_COUNT: return &numLineDefs; case DD_SIDE_COUNT: return &numSideDefs; case DD_VERTEX_COUNT: return &numVertexes; case DD_POLYOBJ_COUNT: return &numPolyObjs; case DD_SEG_COUNT: return &numSegs; case DD_SUBSECTOR_COUNT: return &numSSectors; case DD_NODE_COUNT: return &numNodes; case DD_MATERIAL_COUNT: return &numMaterialBinds; case DD_TRACE_ADDRESS: return &traceLOS; case DD_TRANSLATIONTABLES_ADDRESS: return translationTables; case DD_MAP_NAME: { gamemap_t *map = P_GetCurrentMap(); ded_mapinfo_t *mapInfo = Def_GetMapInfo(P_GetMapID(map)); if(mapInfo && mapInfo->name[0]) { int id; if((id = Def_Get(DD_DEF_TEXT, mapInfo->name, NULL)) != -1) { return defs.text[id].text; } return mapInfo->name; } break; } case DD_MAP_AUTHOR: { gamemap_t *map = P_GetCurrentMap(); ded_mapinfo_t *mapInfo = Def_GetMapInfo(P_GetMapID(map)); if(mapInfo && mapInfo->author[0]) return mapInfo->author; break; } case DD_MAP_MIN_X: { gamemap_t *map = P_GetCurrentMap(); if(map) return &map->bBox[BOXLEFT]; else return NULL; } case DD_MAP_MIN_Y: { gamemap_t *map = P_GetCurrentMap(); if(map) return &map->bBox[BOXBOTTOM]; else return NULL; } case DD_MAP_MAX_X: { gamemap_t *map = P_GetCurrentMap(); if(map) return &map->bBox[BOXRIGHT]; else return NULL; } case DD_MAP_MAX_Y: { gamemap_t *map = P_GetCurrentMap(); if(map) return &map->bBox[BOXTOP]; else return NULL; } case DD_PSPRITE_OFFSET_X: return &pspOffset[VX]; case DD_PSPRITE_OFFSET_Y: return &pspOffset[VY]; case DD_PSPRITE_LIGHTLEVEL_MULTIPLIER: return &pspLightLevelMultiplier; case DD_SHARED_FIXED_TRIGGER: return &sharedFixedTrigger; case DD_CPLAYER_THRUST_MUL: return &cplrThrustMul; case DD_GRAVITY: return &mapGravity; case DD_TORCH_RED: return &torchColor[CR]; case DD_TORCH_GREEN: return &torchColor[CG]; case DD_TORCH_BLUE: return &torchColor[CB]; case DD_TORCH_ADDITIVE: return &torchAdditive; #ifdef WIN32 case DD_WINDOW_HANDLE: return Sys_GetWindowHandle(windowIDX); #endif // We have to separately calculate the 35 Hz ticks. case DD_GAMETIC: { static timespan_t fracTic; fracTic = gameTime * TICSPERSEC; return &fracTic; } case DD_OPENRANGE: return &openrange; case DD_OPENTOP: return &opentop; case DD_OPENBOTTOM: return &openbottom; case DD_LOWFLOOR: return &lowfloor; default: break; } return 0; } // Other values not supported. return ddValues[ddvalue].writePtr; } /** * Set the value of a variable. The pointer can point to any data, its * interpretation depends on the variable. Added for 64-bit support. */ void DD_SetVariable(int ddvalue, void *parm) { if(ddvalue <= DD_FIRST_VALUE || ddvalue >= DD_LAST_VALUE) { switch(ddvalue) { case DD_VIEW_X: viewX = *(float*) parm; return; case DD_VIEW_Y: viewY = *(float*) parm; return; case DD_VIEW_Z: viewZ = *(float*) parm; return; case DD_VIEW_ANGLE: viewAngle = *(angle_t*) parm; return; case DD_VIEW_PITCH: viewPitch = *(float*) parm; return; case DD_CPLAYER_THRUST_MUL: cplrThrustMul = *(float*) parm; return; case DD_GRAVITY: mapGravity = *(float*) parm; return; case DD_PSPRITE_OFFSET_X: pspOffset[VX] = *(float*) parm; return; case DD_PSPRITE_OFFSET_Y: pspOffset[VY] = *(float*) parm; return; case DD_PSPRITE_LIGHTLEVEL_MULTIPLIER: pspLightLevelMultiplier = *(float*) parm; return; case DD_TORCH_RED: torchColor[CR] = MINMAX_OF(0, *((float*) parm), 1); return; case DD_TORCH_GREEN: torchColor[CG] = MINMAX_OF(0, *((float*) parm), 1); return; case DD_TORCH_BLUE: torchColor[CB] = MINMAX_OF(0, *((float*) parm), 1); return; case DD_TORCH_ADDITIVE: torchAdditive = (*(int*) parm)? true : false; break; default: break; } } } /** * Gets the data of a player. */ ddplayer_t *DD_GetPlayer(int number) { return (ddplayer_t *) &ddPlayers[number].shared; } #ifdef UNIX /** * Some routines are not available on the *nix platform. */ char *strupr(char *string) { char *ch = string; for(; *ch; ch++) *ch = toupper(*ch); return string; } char *strlwr(char *string) { char *ch = string; for(; *ch; ch++) *ch = tolower(*ch); return string; } #endif /** * Prints a formatted string into a fixed-size buffer. At most @c size * characters will be * written to the output buffer @c str. The output will always contain a * terminating null character. * * @param str Output buffer. * @param size Size of the output buffer. * @param format Format of the output. * @param ap Variable-size argument list. * * @return Number of characters written to the output buffer * if lower than or equal to @c size, else @c -1. */ int dd_vsnprintf(char* str, size_t size, const char* format, va_list ap) { int result = vsnprintf(str, size, format, ap); #ifdef WIN32 // Always terminate. str[size - 1] = 0; return result; #else return result >= size? -1 : size; #endif } /** * Prints a formatted string into a fixed-size buffer. At most @c size * characters will be written to the output buffer @c str. The output will * always contain a terminating null character. * * @param str Output buffer. * @param size Size of the output buffer. * @param format Format of the output. * * @return Number of characters written to the output buffer * if lower than or equal to @c size, else @c -1. */ int dd_snprintf(char* str, size_t size, const char* format, ...) { int result = 0; va_list args; va_start(args, format); result = dd_vsnprintf(str, size, format, args); va_end(args); return result; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/con_main.c0000644000175000017500000016777311357170241022704 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_main.c: Console Subsystem * * Should be completely redesigned. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #include "de_platform.h" #ifdef WIN32 # include #endif #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_graphics.h" #include "de_refresh.h" #include "de_render.h" #include "de_edit.h" #include "de_play.h" #include "de_audio.h" #include "de_ui.h" #include "de_misc.h" #include "de_bsp.h" #ifdef TextOut // Windows has its own TextOut. # undef TextOut #endif // MACROS ------------------------------------------------------------------ #define SC_EMPTY_QUOTE -1 // Length of the print buffer. Used in conPrintf and in Console_Message. // If console messages are longer than this, an error will occur. // Needed because we can't sizeof a malloc'd block. #define PRBUFF_SIZE 655365 // Operators for the "if" command. enum { IF_EQUAL, IF_NOT_EQUAL, IF_GREATER, IF_LESS, IF_GEQUAL, IF_LEQUAL }; #define CMDTYPESTR(src) (src == CMDS_DDAY? "a direct call" \ : src == CMDS_GAME? "a dll call" \ : src == CMDS_CONSOLE? "the console" \ : src == CMDS_BIND? "a binding" \ : src == CMDS_CONFIG? "a cfg file" \ : src == CMDS_PROFILE? "a player profile" \ : src == CMDS_CMDLINE? "the command line" \ : src == CMDS_DED? "an action command" : "???") // TYPES ------------------------------------------------------------------- typedef struct execbuff_s { boolean used; // Is this in use? timespan_t when; // System time when to execute the command. byte source; // Where the command came from // (console input, a cfg file etc..) boolean isNetCmd; // Command was sent over the net to us. char subCmd[1024]; // A single command w/args. } execbuff_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(AddSub); D_CMD(IncDec); D_CMD(Alias); D_CMD(Clear); D_CMD(Echo); D_CMD(Font); D_CMD(Help); D_CMD(If); D_CMD(OpenClose); D_CMD(Parse); D_CMD(Quit); D_CMD(Repeat); D_CMD(Toggle); D_CMD(Version); D_CMD(Wait); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void Con_Register(void); static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd); static void Con_SplitIntoSubCommands(const char *command, timespan_t markerOffset, byte src, boolean isNetCmd); static void Con_ClearExecBuffer(void); static void Con_DestroyMatchedWordList(void); static void updateDedicatedConsoleCmdLine(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int CmdReturnValue = 0; ddfont_t Cfont; // The console font. byte ConsoleSilent = false; int conCompMode = 0; // Completion mode. byte conSilentCVars = 1; byte consoleDump = true; int consoleActiveKey = '`'; // Tilde. byte consoleSnapBackOnPrint = false; char trimmedFloatBuffer[32]; // Returned by TrimmedFloat(). char *prbuff = NULL; // Print buffer, used by conPrintf. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static cbuffer_t *histBuf = NULL; // The console history buffer (log). uint bLineOff; // How many lines from the last in the histBuf? static cbuffer_t *oldCmds = NULL; // The old commands buffer. uint ocPos; // How many cmds from the last in the oldCmds buffer. static boolean ConsoleInited; // Has Con_Init() been called? static boolean ConsoleActive; // Is the console active? static timespan_t ConsoleTime; // How many seconds has the console been open? static char cmdLine[CMDLINE_SIZE]; // The command line. static uint cmdCursor; // Position of the cursor on the command line. static boolean cmdInsMode; // Are we in insert input mode. static boolean conInputLock; // While locked, most user input is disabled. static execbuff_t *exBuff; static int exBuffSize; static execbuff_t *curExec; static uint complPos; // Where is the completion cursor? static knownword_t **matchedWords; static unsigned int matchedWordCount; static unsigned int lastCompletion; // The last completed known word match. static boolean matchedWordListGood; static boolean finishCompletion; // An autocomplete has taken place that must // be completed ASAP. // CODE -------------------------------------------------------------------- static void Con_Register(void) { C_CMD("add", NULL, AddSub); C_CMD("after", "is", Wait); C_CMD("alias", NULL, Alias); C_CMD("clear", "", Clear); C_CMD_FLAGS("conclose", "", OpenClose, CMDF_NO_DEDICATED); C_CMD_FLAGS("conopen", "", OpenClose, CMDF_NO_DEDICATED); C_CMD_FLAGS("contoggle", "", OpenClose, CMDF_NO_DEDICATED); C_CMD("dec", NULL, IncDec); C_CMD("echo", "s*", Echo); C_CMD("print", "s*", Echo); C_CMD("exec", "s*", Parse); C_CMD("font", NULL, Font); C_CMD("help", "", Help); C_CMD("if", NULL, If); C_CMD("inc", NULL, IncDec); C_CMD("listmobjtypes", "", ListMobjs); C_CMD("quit!", "", Quit); C_CMD("repeat", "ifs", Repeat); C_CMD("sub", NULL, AddSub); C_CMD("toggle", "s", Toggle); C_CMD("version", "", Version); C_CMD("write", "s", WriteConsole); // Console C_VAR_INT("con-completion", &conCompMode, 0, 0, 1); C_VAR_BYTE("con-dump", &consoleDump, 0, 0, 1); C_VAR_INT("con-key-activate", &consoleActiveKey, 0, 0, 255); C_VAR_BYTE("con-var-silent", &conSilentCVars, 0, 0, 1); C_VAR_BYTE("con-snapback", &consoleSnapBackOnPrint, 0, 0, 1); // File C_VAR_CHARPTR("file-startup", &defaultWads, 0, 0, 0); C_VAR_INT("con-transition", &rTransition, 0, FIRST_TRANSITIONSTYLE, LAST_TRANSITIONSTYLE); C_VAR_INT("con-transition-tics", &rTransitionTics, 0, 0, 60); Con_DataRegister(); } boolean Con_IsActive(void) { return ConsoleActive; } boolean Con_IsLocked(void) { return conInputLock; } boolean Con_InputMode(void) { return cmdInsMode; } char *Con_GetCommandLine(void) { return cmdLine; } cbuffer_t *Con_GetConsoleBuffer(void) { return histBuf; } uint Con_CursorPosition(void) { return cmdCursor; } void PrepareCmdArgs(cmdargs_t *cargs, const char *lpCmdLine) { #define IS_ESC_CHAR(x) ((x) == '"' || (x) == '\\' || (x) == '{' || (x) == '}') size_t i, len = strlen(lpCmdLine); // Prepare the data. memset(cargs, 0, sizeof(cmdargs_t)); strcpy(cargs->cmdLine, lpCmdLine); // Prepare. for(i = 0; i < len; ++i) { // Whitespaces are separators. if(ISSPACE(cargs->cmdLine[i])) cargs->cmdLine[i] = 0; if(cargs->cmdLine[i] == '\\' && IS_ESC_CHAR(cargs->cmdLine[i + 1])) { // Escape sequence. memmove(cargs->cmdLine + i, cargs->cmdLine + i + 1, sizeof(cargs->cmdLine) - i - 1); len--; continue; } if(cargs->cmdLine[i] == '"') { // Find the end. size_t start = i; cargs->cmdLine[i] = 0; for(++i; i < len && cargs->cmdLine[i] != '"'; ++i) { if(cargs->cmdLine[i] == '\\' && IS_ESC_CHAR(cargs->cmdLine[i + 1])) // Escape sequence? { memmove(cargs->cmdLine + i, cargs->cmdLine + i + 1, sizeof(cargs->cmdLine) - i - 1); len--; continue; } } // Quote not terminated? if(i == len) break; // An empty set of quotes? if(i == start + 1) cargs->cmdLine[i] = SC_EMPTY_QUOTE; else cargs->cmdLine[i] = 0; } if(cargs->cmdLine[i] == '{') { // Find matching end, braces are another notation for quotes. int level = 0; size_t start = i; cargs->cmdLine[i] = 0; for(++i; i < len; ++i) { if(cargs->cmdLine[i] == '\\' && IS_ESC_CHAR(cargs->cmdLine[i + 1])) // Escape sequence? { memmove(cargs->cmdLine + i, cargs->cmdLine + i + 1, sizeof(cargs->cmdLine) - i - 1); len--; i++; continue; } if(cargs->cmdLine[i] == '}') { if(!level) break; level--; } if(cargs->cmdLine[i] == '{') level++; } // Quote not terminated? if(i == len) break; // An empty set of braces? if(i == start + 1) cargs->cmdLine[i] = SC_EMPTY_QUOTE; else cargs->cmdLine[i] = 0; } } // Scan through the cmdLine and get the beginning of each token. cargs->argc = 0; for(i = 0; i < len; ++i) { if(!cargs->cmdLine[i]) continue; // Is this an empty quote? if(cargs->cmdLine[i] == SC_EMPTY_QUOTE) cargs->cmdLine[i] = 0; // Just an empty string. cargs->argv[cargs->argc++] = cargs->cmdLine + i; i += strlen(cargs->cmdLine + i); } #undef IS_ESC_CHAR } boolean Con_Init(void) { histBuf = Con_NewBuffer(512, 70, 0); bLineOff = 0; oldCmds = Con_NewBuffer(0, CMDLINE_SIZE, CBF_ALWAYSFLUSH); ocPos = 0; // No commands yet. //B_Init(); ConsoleActive = false; ConsoleInited = true; ConsoleTime = 0; Rend_ConsoleInit(); complPos = 0; matchedWordListGood = false; cmdCursor = 0; exBuff = NULL; exBuffSize = 0; // Register the engine commands and variables. DD_RegisterLoop(); DD_RegisterInput(); DD_RegisterVFS(); B_Register(); // for control bindings Con_Register(); DH_Register(); R_Register(); S_Register(); SBE_Register(); // for bias editor Rend_Register(); GL_Register(); Net_Register(); I_Register(); H_Register(); DAM_Register(); BSP_Register(); UI_Register(); Demo_Register(); P_ControlRegister(); Con_Message("Con_Init: Initializing the console.\n"); return true; } void Con_Shutdown(void) { // Announce VERBOSE(Con_Printf("Con_Shutdown: Shuting down the console...\n")); Con_DestroyBuffer(histBuf); // The console history buffer. Con_DestroyBuffer(oldCmds); // The old commands buffer. if(prbuff) M_Free(prbuff); // Free the print buffer. Con_DestroyMatchedWordList(); Con_DestroyDatabases(); Con_ClearExecBuffer(); } /** * Changes the console font. * Part of the Doomsday public API. */ void Con_SetFont(ddfont_t* cfont) { if(!cfont) return; memcpy(&Cfont, cfont, sizeof(Cfont)); } /** * Send a console command to the server. * This shouldn't be called unless we're logged in with the right password. */ static void Con_Send(const char *command, byte src, int silent) { ushort len = (ushort) (strlen(command) + 1); Msg_Begin(PKT_COMMAND2); // Mark high bit for silent commands. Msg_WriteShort(len | (silent ? 0x8000 : 0)); Msg_WriteShort(0); // flags. Unused at present. Msg_WriteByte(src); Msg_Write(command, len); // Send it reliably. Net_SendBuffer(0, SPF_ORDERED); } static void Con_QueueCmd(const char *singleCmd, timespan_t atSecond, byte source, boolean isNetCmd) { execbuff_t *ptr = NULL; int i; // Look for an empty spot. for(i = 0; i < exBuffSize; ++i) if(!exBuff[i].used) { ptr = exBuff + i; break; } if(ptr == NULL) { // No empty places, allocate a new one. exBuff = M_Realloc(exBuff, sizeof(execbuff_t) * ++exBuffSize); ptr = exBuff + exBuffSize - 1; } ptr->used = true; strcpy(ptr->subCmd, singleCmd); ptr->when = atSecond; ptr->source = source; ptr->isNetCmd = isNetCmd; } static void Con_ClearExecBuffer(void) { M_Free(exBuff); exBuff = NULL; exBuffSize = 0; } /** * The execbuffer is used to schedule commands for later. * * @return @c false, if an executed command fails. */ static boolean Con_CheckExecBuffer(void) { #define BUFFSIZE 256 boolean allDone; boolean ret = true; int i, count = 0; char storage[BUFFSIZE]; storage[255] = 0; do // We'll keep checking until all is done. { allDone = true; // Execute the commands marked for this or a previous tic. for(i = 0; i < exBuffSize; ++i) { execbuff_t *ptr = exBuff + i; if(!ptr->used || ptr->when > sysTime) continue; // We'll now execute this command. curExec = ptr; ptr->used = false; strncpy(storage, ptr->subCmd, BUFFSIZE-1); if(!executeSubCmd(storage, ptr->source, ptr->isNetCmd)) ret = false; allDone = false; } if(count++ > 100) { Con_Message("Console execution buffer overflow! " "Everything canceled.\n"); Con_ClearExecBuffer(); break; } } while(!allDone); return ret; #undef BUFFSIZE } void Con_Ticker(timespan_t time) { if(!conInputLock && finishCompletion) { knownword_t *word = matchedWords[lastCompletion]; // Add a trailing space if the word is NOT a cmd or alias. if(matchedWordListGood && !(word->type == WT_ALIAS || word->type == WT_CCMD) && cmdCursor < CMDLINE_SIZE) { strcat(cmdLine, " "); cmdCursor++; } matchedWordListGood = false; finishCompletion = false; } Con_CheckExecBuffer(); if(tickFrame) Con_TransitionTicker(time); Rend_ConsoleTicker(time); if(!ConsoleActive) return; // We have nothing further to do here. ConsoleTime += time; // Increase the ticker. } void Con_SetMaxLineLength(void) { int cw = FR_TextWidth("A"); int length; float winWidth = theWindow->width? theWindow->width : 640; if(!cw) { length = 70; } else { length = winWidth / cw - 2; if(length > 250) length = 250; } Con_BufferSetMaxLineLength(histBuf, length); } /** * expCommand gets reallocated in the expansion process. * This could be bit more clever. */ static void expandWithArguments(char **expCommand, cmdargs_t *args) { int p; char *text = *expCommand; size_t i, off, size = strlen(text) + 1; for(i = 0; text[i]; ++i) { if(text[i] == '%' && (text[i + 1] >= '1' && text[i + 1] <= '9')) { char *substr; int aidx = text[i + 1] - '1' + 1; // Expand! (or delete) if(aidx > args->argc - 1) substr = ""; else substr = args->argv[aidx]; // First get rid of the %n. memmove(text + i, text + i + 2, size - i - 2); // Reallocate. off = strlen(substr); text = *expCommand = M_Realloc(*expCommand, size += off - 2); if(off) { // Make room for the insert. memmove(text + i + off, text + i, size - i - off); memcpy(text + i, substr, off); } i += off - 1; } else if(text[i] == '%' && text[i + 1] == '0') { // First get rid of the %0. memmove(text + i, text + i + 2, size - i - 2); text = *expCommand = M_Realloc(*expCommand, size -= 2); for(p = args->argc - 1; p > 0; p--) { off = strlen(args->argv[p]) + 1; text = *expCommand = M_Realloc(*expCommand, size += off); memmove(text + i + off, text + i, size - i - off); text[i] = ' '; memcpy(text + i + 1, args->argv[p], off - 1); } } } } /** * The command is executed forthwith!! */ static int executeSubCmd(const char *subCmd, byte src, boolean isNetCmd) { cmdargs_t args; ddccmd_t *ccmd; cvar_t *cvar; calias_t *cal; PrepareCmdArgs(&args, subCmd); if(!args.argc) return true; /* if(args.argc == 1) // Possibly a control command? { if(P_ControlExecute(args.argv[0])) { // It was a control command. No further processing is // necessary. return true; } } */ // If logged in, send command to server at this point. if(!isServer && netLoggedIn) { // We have logged in on the server. Send the command there. Con_Send(subCmd, src, ConsoleSilent); return true; } // Try to find a matching console command. ccmd = Con_GetCommand(&args); if(ccmd != NULL) { // Found a match. Are we allowed to execute? boolean canExecute = true; // A dedicated server, trying to execute a ccmd not available to us? if(isDedicated && (ccmd->flags & CMDF_NO_DEDICATED)) { Con_Printf("executeSubCmd: '%s' impossible in dedicated mode.\n", ccmd->name); return true; } // Net commands sent to servers have extra protection. if(isServer && isNetCmd) { // Is the command permitted for use by clients? if(ccmd->flags & CMDF_CLIENT) { Con_Printf("executeSubCmd: Blocked command. A client" " attempted to use '%s'.\n" "This command is not permitted for use by clients\n", ccmd->name); // \todo Tell the client! return true; } // Are ANY commands from this (remote) src permitted for use // by our clients? // NOTE: // This is an interim measure to protect against abuse of the // most vulnerable invocation methods. // Once all console commands are updated with the correct usage // flags we can then remove these restrictions or make them // optional for servers. // // The next step will then be allowing select console commands // to be executed by non-logged in clients. switch(src) { case CMDS_UNKNOWN: case CMDS_CONFIG: case CMDS_PROFILE: case CMDS_CMDLINE: case CMDS_DED: Con_Printf("executeSubCmd: Blocked command. A client" " attempted to use '%s' via %s.\n" "This invocation method is not permitted " "by clients\n", ccmd->name, CMDTYPESTR(src)); // \todo Tell the client! return true; default: break; } } // Is the src permitted for this command? switch(src) { case CMDS_UNKNOWN: canExecute = false; break; case CMDS_DDAY: if(ccmd->flags & CMDF_DDAY) canExecute = false; break; case CMDS_GAME: if(ccmd->flags & CMDF_GAME) canExecute = false; break; case CMDS_CONSOLE: if(ccmd->flags & CMDF_CONSOLE) canExecute = false; break; case CMDS_BIND: if(ccmd->flags & CMDF_BIND) canExecute = false; break; case CMDS_CONFIG: if(ccmd->flags & CMDF_CONFIG) canExecute = false; break; case CMDS_PROFILE: if(ccmd->flags & CMDF_PROFILE) canExecute = false; break; case CMDS_CMDLINE: if(ccmd->flags & CMDF_CMDLINE) canExecute = false; break; case CMDS_DED: if(ccmd->flags & CMDF_DED) canExecute = false; break; default: return true; } if(!canExecute) { Con_Printf("Error: '%s' cannot be executed via %s.\n", ccmd->name, CMDTYPESTR(src)); return true; } if(canExecute) { // Execute the command! int cret = ccmd->func(src, args.argc, args.argv); if(cret == false) Con_Printf("Error: '%s' failed.\n", ccmd->name); // We're quite done. return cret; } else { return true; } } // Then try the cvars? cvar = Con_GetVariable(args.argv[0]); if(cvar != NULL) { boolean out_of_range = false, setting = false; if(args.argc == 2 || (args.argc == 3 && !stricmp(args.argv[1], "force"))) { char *argptr = args.argv[args.argc - 1]; boolean forced = args.argc == 3; setting = true; if(cvar->flags & CVF_READ_ONLY) { Con_Printf("%s is read-only. It can't be changed (not even " "with force)\n", cvar->name); } else if(cvar->flags & CVF_PROTECTED && !forced) { Con_Printf ("%s is protected. You shouldn't change its value.\n", cvar->name); Con_Printf ("Use the command: '%s force %s' to modify it anyway.\n", cvar->name, argptr); } else if(cvar->type == CVT_BYTE) { byte val = (byte) strtol(argptr, NULL, 0); if(!forced && ((!(cvar->flags & CVF_NO_MIN) && val < cvar->min) || (!(cvar->flags & CVF_NO_MAX) && val > cvar->max))) out_of_range = true; else Con_SetInteger(cvar->name, val, false); } else if(cvar->type == CVT_INT) { int val = strtol(argptr, NULL, 0); if(!forced && ((!(cvar->flags & CVF_NO_MIN) && val < cvar->min) || (!(cvar->flags & CVF_NO_MAX) && val > cvar->max))) out_of_range = true; else Con_SetInteger(cvar->name, val, false); } else if(cvar->type == CVT_FLOAT) { float val = strtod(argptr, NULL); if(!forced && ((!(cvar->flags & CVF_NO_MIN) && val < cvar->min) || (!(cvar->flags & CVF_NO_MAX) && val > cvar->max))) out_of_range = true; else Con_SetFloat(cvar->name, val, false); } else if(cvar->type == CVT_CHARPTR) { Con_SetString(cvar->name, argptr, false); } } if(out_of_range) { if(!(cvar->flags & (CVF_NO_MIN | CVF_NO_MAX))) { char temp[20]; strcpy(temp, TrimmedFloat(cvar->min)); Con_Printf("Error: %s <= %s <= %s\n", temp, cvar->name, TrimmedFloat(cvar->max)); } else if(cvar->flags & CVF_NO_MAX) { Con_Printf("Error: %s >= %s\n", cvar->name, TrimmedFloat(cvar->min)); } else { Con_Printf("Error: %s <= %s\n", cvar->name, TrimmedFloat(cvar->max)); } } else if(!setting || !conSilentCVars) // Show the value. { Con_PrintCVar(cvar, ""); } return true; } // How about an alias then? cal = Con_GetAlias(args.argv[0]); if(cal != NULL) { char *expCommand; // Expand the command with arguments. expCommand = M_Malloc(strlen(cal->command) + 1); strcpy(expCommand, cal->command); expandWithArguments(&expCommand, &args); // Do it, man! Con_SplitIntoSubCommands(expCommand, 0, src, isNetCmd); M_Free(expCommand); return true; } // What *is* that? Con_Printf("%s: unknown identifier, or command arguments invalid.\n", args.argv[0]); return false; } /** * Splits the command into subcommands and queues them into the * execution buffer. */ static void Con_SplitIntoSubCommands(const char *command, timespan_t markerOffset, byte src, boolean isNetCmd) { #define BUFFSIZE 2048 char subCmd[BUFFSIZE]; int inQuotes = false, escape = false; size_t gPos = 0, scPos = 0, len; // Is there a command to execute? if(!command || command[0] == 0) return; // Jump over initial semicolons. len = strlen(command); while(gPos < len && command[gPos] == ';' && command[gPos] != 0) gPos++; subCmd[0] = subCmd[BUFFSIZE-1] = 0; // The command may actually contain many commands, separated // with semicolons. This isn't a very clear algorithm... for(; command[gPos];) { escape = false; if(inQuotes && command[gPos] == '\\') // Escape sequence? { subCmd[scPos++] = command[gPos++]; escape = true; } if(command[gPos] == '"' && !escape) inQuotes = !inQuotes; // Collect characters. subCmd[scPos++] = command[gPos++]; if(subCmd[0] == ' ') scPos = 0; // No spaces in the beginning. if((command[gPos] == ';' && !inQuotes) || command[gPos] == 0) { while(gPos < len && command[gPos] == ';' && command[gPos] != 0) gPos++; // The subcommand ends. subCmd[scPos] = 0; } else { continue; } // Queue it. Con_QueueCmd(subCmd, sysTime + markerOffset, src, isNetCmd); scPos = 0; } #undef BUFFSIZE } static void Con_DestroyMatchedWordList(void) { // Free the matched words array. if(matchedWordCount) M_Free(matchedWords); } /** * Ambiguous string check. 'amb' is cut at the first character that * differs when compared to 'str' (case ignored). */ static void stramb(char *amb, const char *str) { while(*str && tolower((unsigned) *amb) == tolower((unsigned) *str)) { amb++; str++; } *amb = 0; } /** * Look at the last word and try to complete it. If there are several * possibilities, print them. * * @return Number of possible completions. */ static int completeWord(int mode) { int cp = (int) strlen(cmdLine) - 1; char word[100], *wordBegin; char unambiguous[256]; char *completion = 0; // Pointer to the completed word. cvar_t *cvar; boolean justUpdated; if(mode == 1) cp = complPos - 1; memset(unambiguous, 0, sizeof(unambiguous)); if(cp < 0) return 0; // Skip over any whitespace behind the cursor. while(cp > 0 && cmdLine[cp] == ' ') cp--; // Rewind the word pointer until space or a semicolon is found. while(cp > 0 && cmdLine[cp - 1] != ' ' && cmdLine[cp - 1] != ';' && cmdLine[cp - 1] != '"') cp--; // Now cp is at the beginning of the word that needs completing. strcpy(word, wordBegin = cmdLine + cp); if(mode == 1) word[complPos - cp] = 0; // Only check a partial word. // Can we use the previous valid matched word list? // If yes we will use it, else perform a new search. justUpdated = false; if(!matchedWordListGood) { Con_DestroyMatchedWordList(); matchedWords = Con_CollectKnownWordsMatchingWord(word, &matchedWordCount); matchedWordListGood = true; lastCompletion = 0; justUpdated = true; } if(!matchedWordCount) return 0; // At this point we have at least one completion for the word. // What happens next depends on the completion mode. if(mode == 1) { // Completion Mode 1: Cycle through the possible completions. uint idx; // fix me: signed/unsigned mismatch // use another var to note when lastCompletion is not valid. if(justUpdated || lastCompletion + 1 >= matchedWordCount) idx = 0; else idx = lastCompletion + 1; completion = matchedWords[idx]->word; lastCompletion = idx; } else { // Completion Mode 2: Print the possible completions knownword_t **foundWord; boolean updated = false; boolean printCompletions = (matchedWordCount > 1? true : false); if(printCompletions) Con_Printf("Completions:\n"); // Look through the known words. for(foundWord = matchedWords; *foundWord; foundWord++) { if(printCompletions) { switch((*foundWord)->type) { case WT_CVAR: if((cvar = Con_GetVariable((*foundWord)->word)) != NULL) Con_PrintCVar(cvar, " "); break; case WT_CCMD: case WT_ALIAS: Con_FPrintf(CBLF_LIGHT | CBLF_YELLOW, " %s\n", (*foundWord)->word); break; default: Con_Printf(" %s\n", (*foundWord)->word); break; } } // This matches! if(!unambiguous[0]) strcpy(unambiguous, (*foundWord)->word); else stramb(unambiguous, (*foundWord)->word); if(!updated) { // Update completion. completion = (*foundWord)->word; lastCompletion = foundWord - matchedWords; updated = true; } } } // Was a single completion found? if(matchedWordCount == 1 || (mode == 1 && matchedWordCount > 1)) { if(wordBegin - cmdLine + strlen(completion) < CMDLINE_SIZE) { strcpy(wordBegin, completion); cmdCursor = (uint) strlen(cmdLine); } } else if(matchedWordCount > 1) { // More than one completion; only complete the unambiguous part. if(wordBegin - cmdLine + strlen(unambiguous) < CMDLINE_SIZE) { strcpy(wordBegin, unambiguous); cmdCursor = (uint) strlen(cmdLine); } } return matchedWordCount; } /** * Wrapper for Con_Execute * Allows plugin dlls to execute a console command */ int DD_Execute(int silent, const char *command) { return Con_Execute(CMDS_GAME, command, silent, false); } /** * Returns false if a command fails. * * @param src The source of the command (e.g. DDay internal, DED etc). * @param command The command to be executed. * @param silent Non-zero indicates not to log execution of the command. * @param netCmd If @c true, command was sent over the net. * * @return Non-zero if command was executed successfully. */ int Con_Execute(byte src, const char *command, int silent, boolean netCmd) { int ret; if(silent) ConsoleSilent = true; Con_SplitIntoSubCommands(command, 0, src, netCmd); ret = Con_CheckExecBuffer(); if(silent) ConsoleSilent = false; return ret; } /** * Exported version of Con_Executef */ int DD_Executef(int silent, const char *command, ...) { va_list argptr; char buffer[4096]; va_start(argptr, command); vsprintf(buffer, command, argptr); va_end(argptr); return Con_Execute(CMDS_GAME, buffer, silent, false); } int Con_Executef(byte src, int silent, const char *command, ...) { va_list argptr; char buffer[4096]; va_start(argptr, command); dd_vsnprintf(buffer, sizeof(buffer), command, argptr); va_end(argptr); return Con_Execute(src, buffer, silent, false); } static void processCmd(byte src) { DD_ClearKeyRepeaters(); // Add the command line to the oldCmds buffer. if(strlen(cmdLine) > 0) { Con_BufferWrite(oldCmds, 0, cmdLine); ocPos = Con_BufferNumLines(oldCmds); } Con_Execute(src, cmdLine, false, false); } static void updateCmdLine(void) { if(ocPos >= Con_BufferNumLines(oldCmds)) memset(cmdLine, 0, sizeof(cmdLine)); else strncpy(cmdLine, Con_BufferGetLine(oldCmds, ocPos)->text, sizeof(cmdLine)); cmdCursor = complPos = (uint) strlen(cmdLine); matchedWordListGood = false; } static void updateDedicatedConsoleCmdLine(void) { int flags = 0; if(!isDedicated) return; if(cmdInsMode) flags |= CLF_CURSOR_LARGE; Sys_SetConWindowCmdLine(windowIDX, cmdLine, cmdCursor+1, flags); } void Con_Open(int yes) { // The console cannot be closed in dedicated mode. if(isDedicated) yes = true; // Clear all action keys, keyup events won't go to bindings processing // when the console is open. //P_ControlReset(-1); Rend_ConsoleOpen(yes); if(yes) { ConsoleActive = true; ConsoleTime = 0; B_ActivateContext(B_ContextByName(CONSOLE_BINDING_CONTEXT_NAME), true); } else { memset(cmdLine, 0, sizeof(cmdLine)); cmdCursor = 0; ConsoleActive = false; B_ActivateContext(B_ContextByName(CONSOLE_BINDING_CONTEXT_NAME), false); } } /** * @return @c true, if the event is eaten. */ boolean Con_Responder(ddevent_t* ev) { // The console is only interested in keyboard toggle events. if(!IS_KEY_TOGGLE(ev)) return false; // Special console key: Shift-Escape opens the Control Panel. if(!conInputLock && shiftDown && IS_TOGGLE_DOWN_ID(ev, DDKEY_ESCAPE)) { Con_Execute(CMDS_DDAY, "panel", true, false); return true; } if(!ConsoleActive) { // In this case we are only interested in the activation key. if(IS_TOGGLE_DOWN_ID(ev, consoleActiveKey)) { Con_Open(true); return true; } return false; } // All keyups are eaten by the console. if(IS_TOGGLE_UP(ev)) { if(!shiftDown && conInputLock) conInputLock = false; // release the lock return true; } // We only want keydown events. if(!IS_KEY_PRESS(ev)) return false; // In this case the console is active and operational. // Check the shutdown key. if(!conInputLock) { if(ev->toggle.id == consoleActiveKey) { if(shiftDown) // Shift-Tilde to fullscreen and halfscreen. Rend_ConsoleToggleFullscreen(); else Con_Open(false); return true; } else { switch(ev->toggle.id) { case DDKEY_ESCAPE: // Hitting Escape in the console closes it. Con_Open(false); return false; // Let the menu know about this. case DDKEY_PGUP: if(shiftDown) { Rend_ConsoleMove(-3); return true; } break; case DDKEY_PGDN: if(shiftDown) { Rend_ConsoleMove(3); return true; } break; default: break; } } } switch(ev->toggle.id) { case DDKEY_UPARROW: if(conInputLock) break; if(ocPos > 0) ocPos--; // Update the command line. updateCmdLine(); updateDedicatedConsoleCmdLine(); return true; case DDKEY_DOWNARROW: { uint num; if(conInputLock) break; num = Con_BufferNumLines(oldCmds); if(ocPos < num) ocPos++; updateCmdLine(); updateDedicatedConsoleCmdLine(); return true; } case DDKEY_PGUP: { uint num; if(conInputLock) break; num = Con_BufferNumLines(histBuf); if(num > 0) { bLineOff = MIN_OF(bLineOff + 3, num - 1); } return true; } case DDKEY_PGDN: if(conInputLock) break; bLineOff = MAX_OF((int)bLineOff - 3, 0); return true; case DDKEY_END: if(conInputLock) break; bLineOff = 0; return true; case DDKEY_HOME: if(conInputLock) break; bLineOff = Con_BufferNumLines(histBuf); if(bLineOff != 0) bLineOff--; return true; case DDKEY_RETURN: if(conInputLock) break; // Return to the bottom. bLineOff = 0; // Print the command line with yellow text. Con_FPrintf(CBLF_YELLOW, ">%s\n", cmdLine); // Process the command line. processCmd(CMDS_CONSOLE); // Clear it. memset(cmdLine, 0, sizeof(cmdLine)); cmdCursor = 0; complPos = 0; matchedWordListGood = false; Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); return true; case DDKEY_INS: if(conInputLock) break; cmdInsMode = !cmdInsMode; // Toggle text insert mode. updateDedicatedConsoleCmdLine(); return true; case DDKEY_DEL: if(conInputLock) break; if(cmdLine[cmdCursor] != 0) { memmove(cmdLine + cmdCursor, cmdLine + cmdCursor + 1, sizeof(cmdLine) - cmdCursor + 1); complPos = cmdCursor; matchedWordListGood = false; Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); } return true; case DDKEY_BACKSPACE: if(conInputLock) break; if(cmdCursor > 0) { memmove(cmdLine + cmdCursor - 1, cmdLine + cmdCursor, sizeof(cmdLine) - cmdCursor); cmdCursor--; complPos = cmdCursor; matchedWordListGood = false; Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); } return true; case DDKEY_TAB: { int completions; int mode; if(shiftDown) // one time toggle of completion mode. { mode = (conCompMode == 0)? 1 : 0; conInputLock = true; // prevent most user input. } else mode = conCompMode; // Attempt to complete the word and return the number of possibilites. completions = completeWord(mode); if((completions == 1 || (mode == 1 && completions >= 1)) && matchedWordListGood) { // Finish the completion ASAP. finishCompletion = true; } Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); } return true; case DDKEY_LEFTARROW: if(conInputLock) break; if(cmdCursor > 0) { if(shiftDown) cmdCursor = 0; else cmdCursor--; } complPos = cmdCursor; Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); break; case DDKEY_RIGHTARROW: if(conInputLock) break; if(cmdCursor < CMDLINE_SIZE) { if(cmdLine[cmdCursor] == 0) { uint num; const cbline_t *line; num = Con_BufferNumLines(oldCmds); if(num > 0 && ocPos > 0) { line = Con_BufferGetLine(oldCmds, ocPos - 1); if(line && cmdCursor < line->len) { cmdLine[cmdCursor] = line->text[cmdCursor]; cmdCursor++; matchedWordListGood = false; updateDedicatedConsoleCmdLine(); } } } else { if(shiftDown) cmdCursor = (uint) strlen(cmdLine); else cmdCursor++; } } complPos = cmdCursor; Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); break; case DDKEY_F5: if(conInputLock) break; Con_Execute(CMDS_DDAY, "clear", true, false); break; default: // Check for a character. { byte ch; if(conInputLock) break; ch = ev->toggle.id; ch = DD_ModKey(ch); if(ch < 32 || (ch > 127 && ch < DD_HIGHEST_KEYCODE)) return true; if(ch == 'c' && altDown) // if alt + c clear the current cmdline { memset(cmdLine, 0, sizeof(cmdLine)); cmdCursor = 0; complPos = 0; matchedWordListGood = false; Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); return true; } // If not in insert mode, push the rest of the command-line forward. if(!cmdInsMode) { size_t len = strlen(cmdLine); if(cmdCursor < len) { if(len < CMDLINE_SIZE - 1) { memmove(cmdLine + cmdCursor + 1, cmdLine + cmdCursor, sizeof(cmdLine) - cmdCursor - 1); // The last char is always zero, though. cmdLine[sizeof(cmdLine) - 1] = 0; } else { return true; // Can't place character. } } } cmdLine[cmdCursor] = ch; if(cmdCursor < CMDLINE_SIZE) cmdCursor++; complPos = cmdCursor; //strlen(cmdLine); matchedWordListGood = false; Rend_ConsoleCursorResetBlink(); updateDedicatedConsoleCmdLine(); return true; } } // The console is very hungry for keys... return true; } /** * A ruler line will be added into the console. */ void Con_AddRuler(void) { int i; Con_BufferWrite(histBuf, CBLF_RULER, NULL); if(consoleDump) { // A 70 characters long line. for(i = 0; i < 7; ++i) { fprintf(outFile, "----------"); if(isDedicated) Sys_ConPrint(windowIDX, "----------", 0); } fprintf(outFile, "\n"); if(isDedicated) Sys_ConPrint(windowIDX, "\n", 0); } } void conPrintf(int flags, const char *format, va_list args) { if(flags & CBLF_RULER) { Con_AddRuler(); flags &= ~CBLF_RULER; } if(prbuff == NULL) prbuff = M_Malloc(PRBUFF_SIZE); else memset(prbuff, 0, PRBUFF_SIZE); // Format the message to prbuff. dd_vsnprintf(prbuff, PRBUFF_SIZE, format, args); if(consoleDump) fprintf(outFile, "%s", prbuff); // Servers might have to send the text to a number of clients. if(isServer) { if(flags & CBLF_TRANSMIT) Sv_SendText(NSP_BROADCAST, flags, prbuff); else if(netRemoteUser) // Is somebody logged in? Sv_SendText(netRemoteUser, flags | SV_CONSOLE_FLAGS, prbuff); } if(isDedicated) { Sys_ConPrint(windowIDX, prbuff, flags); } else { Con_BufferWrite(histBuf, flags, prbuff); if(consoleSnapBackOnPrint) { // Now that something new has been printed, it will be shown. bLineOff = 0; } } } /** * Print into the buffer. */ void Con_Printf(const char *format, ...) { va_list args; if(!ConsoleInited || ConsoleSilent) return; va_start(args, format); conPrintf(CBLF_WHITE, format, args); va_end(args); } void Con_FPrintf(int flags, const char *format, ...) // Flagged printf { va_list args; if(!ConsoleInited || ConsoleSilent) return; va_start(args, format); conPrintf(flags, format, args); va_end(args); } /** * Prints a file name to the console. * This is a f_forall_func_t. */ int Con_PrintFileName(const char *fn, filetype_t type, void *dir) { // Exclude the path. Con_Printf(" %s\n", fn + strlen(dir)); // Continue the listing. return true; } /** * Print a 'global' message (to stdout and the console). */ void Con_Message(const char *message, ...) { va_list argptr; char *buffer; if(message[0]) { buffer = M_Malloc(PRBUFF_SIZE); va_start(argptr, message); dd_vsnprintf(buffer, PRBUFF_SIZE, message, argptr); va_end(argptr); #ifdef UNIX if(!isDedicated) { // These messages are supposed to be visible in the real console. fprintf(stderr, "%s", buffer); } #endif // These messages are always dumped. If consoleDump is set, // Con_Printf() will dump the message for us. if(!consoleDump) printf("%s", buffer); // Also print in the console. Con_Printf("%s", buffer); M_Free(buffer); } } /** * Print an error message and quit. */ void Con_Error(const char *error, ...) { static boolean errorInProgress = false; int i, numBufLines; char buff[2048], err[256]; va_list argptr; // Already in an error? if(!ConsoleInited || errorInProgress) { fprintf(outFile, "Con_Error: Stack overflow imminent, aborting...\n"); va_start(argptr, error); dd_vsnprintf(buff, sizeof(buff), error, argptr); va_end(argptr); Sys_MessageBox(buff, true); // Exit immediately, lest we go into an infinite loop. exit(1); } // We've experienced a fatal error; program will be shut down. errorInProgress = true; // Get back to the directory we started from. Dir_ChDir(&ddRuntimeDir); va_start(argptr, error); dd_vsnprintf(err, sizeof(err), error, argptr); va_end(argptr); fprintf(outFile, "%s\n", err); strcpy(buff, ""); if(histBuf != NULL) { // Flush anything still in the write buffer. Con_BufferFlush(histBuf); numBufLines = Con_BufferNumLines(histBuf); for(i = 5; i > 1; i--) { const cbline_t *cbl = Con_BufferGetLine(histBuf, numBufLines - i); if(!cbl || !cbl->text) continue; strcat(buff, cbl->text); strcat(buff, "\n"); } } strcat(buff, "\n"); strcat(buff, err); if(Con_IsBusy()) { // In busy mode, the other thread will handle this. Con_BusyWorkerError(buff); for(;;) { // We'll stop here. // \todo Kill this thread? Sys_Sleep(10000); } } else { Con_AbnormalShutdown(buff); } } void Con_AbnormalShutdown(const char* message) { Sys_Shutdown(); B_Shutdown(); #ifdef WIN32 ChangeDisplaySettings(0, 0); // Restore original mode, just in case. #endif // Be a bit more graphic. Sys_ShowCursor(true); Sys_ShowCursor(true); if(message) // Only show if a message given. { Sys_MessageBox(message, true); } DD_Shutdown(); // Open Doomsday.out in a text editor. fflush(outFile); // Make sure all the buffered stuff goes into the file. Sys_OpenTextEditor("doomsday.out"); // Get outta here. exit(1); } char* TrimmedFloat(float val) { char* ptr = trimmedFloatBuffer; sprintf(ptr, "%f", val); // Get rid of the extra zeros. for(ptr += strlen(ptr) - 1; ptr >= trimmedFloatBuffer; ptr--) { if(*ptr == '0') *ptr = 0; else if(*ptr == '.') { *ptr = 0; break; } else break; } return trimmedFloatBuffer; } /** * Create an alias. */ static void Con_Alias(char *aName, char *command) { calias_t *cal = Con_GetAlias(aName); boolean remove = false; // Will we remove this alias? if(command == NULL) remove = true; else if(command[0] == 0) remove = true; if(cal && remove) // This alias will be removed. { Con_DeleteAlias(cal); return; // We're done. } // Does the alias already exist? if(cal) { cal->command = M_Realloc(cal->command, strlen(command) + 1); strcpy(cal->command, command); return; } // We need to create a new alias. Con_AddAlias(aName, command); Con_UpdateKnownWords(); } D_CMD(Help) { Con_FPrintf(CBLF_RULER | CBLF_YELLOW | CBLF_CENTER, "-=- Doomsday " DOOMSDAY_VERSION_TEXT " Console -=-\n"); Con_Printf("Keys:\n"); Con_Printf("Tilde Open/close the console.\n"); Con_Printf("Shift-Tilde Switch between half and full screen mode.\n"); Con_Printf("F5 Clear the buffer.\n"); Con_Printf("Alt-C Clear the command line.\n"); Con_Printf("Insert Switch between replace and insert modes.\n"); Con_Printf("Shift-Left Move cursor to the start of the command line.\n"); Con_Printf("Shift-Right Move cursor to the end of the command line.\n"); Con_Printf("Shift-PgUp/Dn Move console window up/down.\n"); Con_Printf("Home Jump to the beginning of the buffer.\n"); Con_Printf("End Jump to the end of the buffer.\n"); Con_Printf("PageUp/Down Scroll up/down a couple of lines.\n"); Con_Printf("\n"); Con_Printf("Type \"listcmds\" to see a list of available commands.\n"); Con_Printf("Type \"help (what)\" to see information about (what).\n"); Con_FPrintf(CBLF_RULER, "\n"); return true; } D_CMD(Clear) { Con_BufferClear(histBuf); bLineOff = 0; return true; } D_CMD(Version) { Con_Printf("Doomsday Engine %s (" __TIME__ ")\n", DOOMSDAY_VERSIONTEXT); Con_Printf("Game DLL: %s\n", (char *) gx.GetVariable(DD_VERSION_LONG)); Con_Printf("%s\n", DOOMSDAY_PROJECTURL); return true; } D_CMD(Quit) { // No questions asked. Sys_Quit(); return true; } D_CMD(Alias) { if(argc != 3 && argc != 2) { Con_Printf("Usage: %s (alias) (cmd)\n", argv[0]); Con_Printf("Example: alias bigfont \"font size 3\".\n"); Con_Printf ("Use %%1-%%9 to pass the alias arguments to the command.\n"); return true; } Con_Alias(argv[1], argc == 3 ? argv[2] : NULL); if(argc != 3) Con_Printf("Alias '%s' deleted.\n", argv[1]); return true; } D_CMD(Parse) { int i; for(i = 1; i < argc; ++i) { Con_Printf("Parsing %s.\n", argv[i]); Con_ParseCommands(argv[i], false); } return true; } D_CMD(Wait) { timespan_t offset; offset = strtod(argv[1], NULL) / 35; // Offset in seconds. if(offset < 0) offset = 0; Con_SplitIntoSubCommands(argv[2], offset, CMDS_CONSOLE, false); return true; } D_CMD(Repeat) { int count; timespan_t interval, offset; count = atoi(argv[1]); interval = strtod(argv[2], NULL) / 35; // In seconds. offset = 0; while(count-- > 0) { offset += interval; Con_SplitIntoSubCommands(argv[3], offset, CMDS_CONSOLE, false); } return true; } D_CMD(Echo) { int i; for(i = 1; i < argc; ++i) { Con_Printf("%s\n", argv[i]); #if _DEBUG printf("%s\n", argv[i]); #endif } return true; } static boolean cvarAddSub(const char* name, float delta, boolean force) { float val; cvar_t* cvar = Con_GetVariable(name); if(!cvar) return false; if(cvar->flags & CVF_READ_ONLY) { Con_Printf("%s (cvar) is read-only. " "It can't be changed (not even with force)\n", name); return false; } val = Con_GetFloat(name) + delta; if(!force) { if(!(cvar->flags & CVF_NO_MAX) && val > cvar->max) val = cvar->max; if(!(cvar->flags & CVF_NO_MIN) && val < cvar->min) val = cvar->min; } Con_SetFloat(name, val, false); return true; } /** * Rather messy, wouldn't you say? */ D_CMD(AddSub) { boolean force = false; float delta = 0; if(argc <= 2) { Con_Printf("Usage: %s (cvar) (val) (force)\n", argv[0]); Con_Printf("Use force to make cvars go off limits.\n"); return true; } if(argc >= 4) { force = !stricmp(argv[3], "force"); } delta = strtod(argv[2], NULL); if(!stricmp(argv[0], "sub")) delta = -delta; return cvarAddSub(argv[1], delta, force); } /** * Rather messy, wouldn't you say? */ D_CMD(IncDec) { boolean force = false; float val; cvar_t* cvar; if(argc == 1) { Con_Printf("Usage: %s (cvar) (force)\n", argv[0]); Con_Printf("Use force to make cvars go off limits.\n"); return true; } if(argc >= 3) { force = !stricmp(argv[2], "force"); } cvar = Con_GetVariable(argv[1]); if(!cvar) return false; if(cvar->flags & CVF_READ_ONLY) { Con_Printf("%s (cvar) is read-only. It can't be changed (not even with force)\n", argv[1]); return false; } val = Con_GetFloat(argv[1]); val += !stricmp(argv[0], "inc")? 1 : -1; if(!force) { if(!(cvar->flags & CVF_NO_MAX) && val > cvar->max) val = cvar->max; if(!(cvar->flags & CVF_NO_MIN) && val < cvar->min) val = cvar->min; } Con_SetFloat(argv[1], val, false); return true; } /** * Toggle the value of a variable between zero and nonzero. */ D_CMD(Toggle) { Con_SetInteger(argv[1], Con_GetInteger(argv[1]) ? 0 : 1, false); return true; } /** * Execute a command if the condition passes. */ D_CMD(If) { struct { const char *opstr; uint op; } operators[] = { {"not", IF_NOT_EQUAL}, {"=", IF_EQUAL}, {">", IF_GREATER}, {"<", IF_LESS}, {">=", IF_GEQUAL}, {"<=", IF_LEQUAL}, {NULL, 0} }; uint i, oper; cvar_t *var; boolean isTrue = false; if(argc != 5 && argc != 6) { Con_Printf("Usage: %s (cvar) (operator) (value) (cmd) (else-cmd)\n", argv[0]); Con_Printf("Operator must be one of: not, =, >, <, >=, <=.\n"); Con_Printf("The (else-cmd) can be omitted.\n"); return true; } var = Con_GetVariable(argv[1]); if(!var) return false; // Which operator? for(i = 0; operators[i].opstr; ++i) if(!stricmp(operators[i].opstr, argv[2])) { oper = operators[i].op; break; } if(!operators[i].opstr) return false; // Bad operator. // Value comparison depends on the type of the variable. if(var->type == CVT_BYTE || var->type == CVT_INT) { int value = (var->type == CVT_INT ? CV_INT(var) : CV_BYTE(var)); int test = strtol(argv[3], 0, 0); isTrue = (oper == IF_EQUAL ? value == test : oper == IF_NOT_EQUAL ? value != test : oper == IF_GREATER ? value > test : oper == IF_LESS ? value < test : oper == IF_GEQUAL ? value >= test : value <= test); } else if(var->type == CVT_FLOAT) { float value = CV_FLOAT(var); float test = strtod(argv[3], 0); isTrue = (oper == IF_EQUAL ? value == test : oper == IF_NOT_EQUAL ? value != test : oper == IF_GREATER ? value > test : oper == IF_LESS ? value < test : oper == IF_GEQUAL ? value >= test : value <= test); } else if(var->type == CVT_CHARPTR) { int comp = stricmp(CV_CHARPTR(var), argv[3]); isTrue = (oper == IF_EQUAL ? comp == 0 : oper == IF_NOT_EQUAL ? comp != 0 : oper == IF_GREATER ? comp > 0 : oper == IF_LESS ? comp < 0 : oper == IF_GEQUAL ? comp >= 0 : comp <= 0); } // Should the command be executed? if(isTrue) { Con_Execute(src, argv[4], ConsoleSilent, false); } else if(argc == 6) { Con_Execute(src, argv[5], ConsoleSilent, false); } CmdReturnValue = isTrue; return true; } /** * Console command to open/close the console prompt. */ D_CMD(OpenClose) { if(!stricmp(argv[0], "conopen")) { Con_Open(true); } else if(!stricmp(argv[0], "conclose")) { Con_Open(false); } else { Con_Open(!ConsoleActive); } return true; } D_CMD(Font) { if(argc == 1 || argc > 3) { Con_Printf("Usage: %s (cmd) (args)\n", argv[0]); Con_Printf("Commands: default, name, size, xsize, ysize.\n"); Con_Printf ("Names: Fixed, Fixed12, System, System12, Large, Small7, Small8, Small10.\n"); Con_Printf("Size 1.0 is normal.\n"); return true; } if(!stricmp(argv[1], "default")) { FR_SetFont(glFontFixed); FR_DestroyFont(FR_GetCurrent()); FR_PrepareFont(GL_ChooseFixedFont()); glFontFixed = FR_GetCurrent(); Cfont.flags = DDFONT_WHITE; Cfont.height = FR_SingleLineHeight("Con"); Cfont.sizeX = 1; Cfont.sizeY = 1; Cfont.drawText = FR_ShadowTextOut; Cfont.getWidth = FR_TextWidth; Cfont.filterText = NULL; } else if(!stricmp(argv[1], "name") && argc == 3) { FR_SetFont(glFontFixed); FR_DestroyFont(FR_GetCurrent()); if(!FR_PrepareFont(argv[2])) FR_PrepareFont(GL_ChooseFixedFont()); glFontFixed = FR_GetCurrent(); Cfont.height = FR_SingleLineHeight("Con"); } else if(argc == 3) { if(!stricmp(argv[1], "xsize") || !stricmp(argv[1], "size")) Cfont.sizeX = strtod(argv[2], NULL); if(!stricmp(argv[1], "ysize") || !stricmp(argv[1], "size")) Cfont.sizeY = strtod(argv[2], NULL); // Make sure the sizes are valid. if(Cfont.sizeX <= 0) Cfont.sizeX = 1; if(Cfont.sizeY <= 0) Cfont.sizeY = 1; } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/edit_map.c0000644000175000017500000017475011357170242022675 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * edit_map.c: */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_play.h" #include "de_bsp.h" #include "de_refresh.h" #include "de_misc.h" #include "de_edit.h" #include "de_dam.h" #include "s_environ.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct usecrecord_s { sector_t *sec; double nearPos[2]; } usecrecord_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void MPE_PrintMapErrors(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean editMapInited = false; static editmap_t editMap, *map = &editMap; static gamemap_t *lastBuiltMap = NULL; static uint numUnclosedSectors; static usecrecord_t *unclosedSectors; static vertex_t *rootVtx; // Used when sorting vertex line owners. // CODE -------------------------------------------------------------------- vertex_t* createVertex(void) { vertex_t* vtx; vtx = M_Calloc(sizeof(*vtx)); vtx->header.type = DMU_VERTEX; map->vertexes = M_Realloc(map->vertexes, sizeof(vtx) * (++map->numVertexes + 1)); map->vertexes[map->numVertexes-1] = vtx; map->vertexes[map->numVertexes] = NULL; vtx->buildData.index = map->numVertexes; // 1-based index, 0 = NIL. return vtx; } static linedef_t* createLine(void) { linedef_t* line; line = M_Calloc(sizeof(*line)); line->header.type = DMU_LINEDEF; map->lineDefs = M_Realloc(map->lineDefs, sizeof(line) * (++map->numLineDefs + 1)); map->lineDefs[map->numLineDefs-1] = line; map->lineDefs[map->numLineDefs] = NULL; line->buildData.index = map->numLineDefs; // 1-based index, 0 = NIL. return line; } static sidedef_t* createSide(void) { sidedef_t* side; side = M_Calloc(sizeof(*side)); side->header.type = DMU_SIDEDEF; map->sideDefs = M_Realloc(map->sideDefs, sizeof(side) * (++map->numSideDefs + 1)); map->sideDefs[map->numSideDefs-1] = side; map->sideDefs[map->numSideDefs] = NULL; side->buildData.index = map->numSideDefs; // 1-based index, 0 = NIL. side->SW_bottomsurface.owner = (void*) side; return side; } static sector_t* createSector(void) { sector_t* sec; sec = M_Calloc(sizeof(*sec)); sec->header.type = DMU_SECTOR; map->sectors = M_Realloc(map->sectors, sizeof(sec) * (++map->numSectors + 1)); map->sectors[map->numSectors-1] = sec; map->sectors[map->numSectors] = NULL; sec->buildData.index = map->numSectors; // 1-based index, 0 = NIL. return sec; } static polyobj_t* createPolyobj(void) { polyobj_t* po; po = M_Calloc(sizeof(*po)); map->polyObjs = M_Realloc(map->polyObjs, sizeof(po) * (++map->numPolyObjs + 1)); map->polyObjs[map->numPolyObjs-1] = po; map->polyObjs[map->numPolyObjs] = NULL; po->buildData.index = map->numPolyObjs; // 1-based index, 0 = NIL. return po; } static void destroyEditablePolyObjs(editmap_t* map) { if(map->polyObjs) { uint i; for(i = 0; i < map->numPolyObjs; ++i) { polyobj_t *po = map->polyObjs[i]; M_Free(po->buildData.lineDefs); M_Free(po); } M_Free(map->polyObjs); } map->polyObjs = NULL; map->numPolyObjs = 0; } static void destroyEditableLineDefs(editmap_t *map) { if(map->lineDefs) { uint i; for(i = 0; i < map->numLineDefs; ++i) { linedef_t *line = map->lineDefs[i]; M_Free(line); } M_Free(map->lineDefs); } map->lineDefs = NULL; map->numLineDefs = 0; } static void destroyEditableSideDefs(editmap_t *map) { if(map->sideDefs) { uint i; for(i = 0; i < map->numSideDefs; ++i) { sidedef_t *side = map->sideDefs[i]; M_Free(side); } M_Free(map->sideDefs); } map->sideDefs = NULL; map->numSideDefs = 0; } static void destroyEditableSectors(editmap_t *map) { if(map->sectors) { uint i; for(i = 0; i < map->numSectors; ++i) { uint j; sector_t *s = map->sectors[i]; if(s->planes) { for(j = 0; j < s->planeCount; ++j) { M_Free(s->planes[j]); } M_Free(s->planes); } M_Free(s); } M_Free(map->sectors); } map->sectors = NULL; map->numSectors = 0; } static void destroyEditableVertexes(editmap_t *map) { if(map->vertexes) { uint i; for(i = 0; i < map->numVertexes; ++i) { vertex_t *vtx = map->vertexes[i]; edgetip_t *tip, *n; tip = vtx->buildData.tipSet; while(tip) { n = tip->ET_next; BSP_DestroyVertexEdgeTip(tip); tip = n; } M_Free(vtx); } M_Free(map->vertexes); } map->vertexes = NULL; map->numVertexes = 0; } static void destroyMap(void) { destroyEditableVertexes(map); // These should already be gone: destroyEditableLineDefs(map); destroyEditableSideDefs(map); destroyEditableSectors(map); destroyEditablePolyObjs(map); } static int C_DECL vertexCompare(const void *p1, const void *p2) { const vertex_t *a = *((const void **) p1); const vertex_t *b = *((const void **) p2); if(a == b) return 0; if((int) a->buildData.pos[VX] != (int) b->buildData.pos[VX]) return (int) a->buildData.pos[VX] - (int) b->buildData.pos[VX]; return (int) a->buildData.pos[VY] - (int) b->buildData.pos[VY]; } void MPE_DetectDuplicateVertices(editmap_t *map) { size_t i; vertex_t **hits; hits = M_Malloc(map->numVertexes * sizeof(vertex_t*)); // Sort array of ptrs. for(i = 0; i < map->numVertexes; ++i) hits[i] = map->vertexes[i]; qsort(hits, map->numVertexes, sizeof(vertex_t*), vertexCompare); // Now mark them off. for(i = 0; i < map->numVertexes - 1; ++i) { // A duplicate? if(vertexCompare(hits + i, hits + i + 1) == 0) { // Yes. vertex_t *a = hits[i]; vertex_t *b = hits[i + 1]; b->buildData.equiv = (a->buildData.equiv ? a->buildData.equiv : a); } } M_Free(hits); } static void findEquivalentVertexes(editmap_t *src) { uint i, newNum; // Scan all linedefs. for(i = 0, newNum = 0; i < src->numLineDefs; ++i) { linedef_t *l = src->lineDefs[i]; // Handle duplicated vertices. while(l->v[0]->buildData.equiv) { l->v[0]->buildData.refCount--; l->v[0] = l->v[0]->buildData.equiv; l->v[0]->buildData.refCount++; } while(l->v[1]->buildData.equiv) { l->v[1]->buildData.refCount--; l->v[1] = l->v[1]->buildData.equiv; l->v[1]->buildData.refCount++; } l->buildData.index = newNum + 1; src->lineDefs[newNum++] = src->lineDefs[i]; } } static void pruneLinedefs(editmap_t* map) { uint i, newNum, unused = 0; for(i = 0, newNum = 0; i < map->numLineDefs; ++i) { linedef_t* l = map->lineDefs[i]; if(!l->L_frontside && !l->L_backside) { unused++; M_Free(l); continue; } l->buildData.index = newNum + 1; map->lineDefs[newNum++] = l; } if(newNum < map->numLineDefs) { if(unused > 0) Con_Message(" Pruned %d unused linedefs\n", unused); map->numLineDefs = newNum; } } static void pruneVertices(editmap_t* map) { uint i, newNum, unused = 0; // Scan all vertices. for(i = 0, newNum = 0; i < map->numVertexes; ++i) { vertex_t *v = map->vertexes[i]; if(v->buildData.refCount < 0) Con_Error("Vertex %d ref_count is %d", i, v->buildData.refCount); if(v->buildData.refCount == 0) { if(v->buildData.equiv == NULL) unused++; M_Free(v); continue; } v->buildData.index = newNum + 1; map->vertexes[newNum++] = v; } if(newNum < map->numVertexes) { int dupNum = map->numVertexes - newNum - unused; if(unused > 0) Con_Message(" Pruned %d unused vertices.\n", unused); if(dupNum > 0) Con_Message(" Pruned %d duplicate vertices\n", dupNum); map->numVertexes = newNum; } } static void pruneUnusedSidedefs(editmap_t* map) { uint i, newNum, unused = 0; for(i = 0, newNum = 0; i < map->numSideDefs; ++i) { sidedef_t* s = map->sideDefs[i]; if(s->buildData.refCount == 0) { unused++; M_Free(s); continue; } s->buildData.index = newNum + 1; map->sideDefs[newNum++] = s; } if(newNum < map->numSideDefs) { int dupNum = map->numSideDefs - newNum - unused; if(unused > 0) Con_Message(" Pruned %d unused sidedefs\n", unused); if(dupNum > 0) Con_Message(" Pruned %d duplicate sidedefs\n", dupNum); map->numSideDefs = newNum; } } static void pruneUnusedSectors(editmap_t* map) { uint i, newNum; for(i = 0; i < map->numSideDefs; ++i) { sidedef_t* s = map->sideDefs[i]; if(s->sector) s->sector->buildData.refCount++; } // Scan all sectors. for(i = 0, newNum = 0; i < map->numSectors; ++i) { sector_t* s = map->sectors[i]; if(s->buildData.refCount == 0) { M_Free(s); continue; } s->buildData.index = newNum + 1; map->sectors[newNum++] = s; } if(newNum < map->numSectors) { Con_Message(" Pruned %d unused sectors\n", map->numSectors - newNum); map->numSectors = newNum; } } /** * \note Order here is critical! */ void MPE_PruneRedundantMapData(editmap_t *map, int flags) { #if 0 /** * \fixme Pruning cannot be done as game map data object properties * are currently indexed by their original indices as determined by the * position in the map data. The same problem occurs within ACS scripts * and XG line/sector references. */ if(!editMapInited) return; findEquivalentVertexes(map); if(flags & PRUNE_LINEDEFS) pruneLinedefs(map); if(flags & PRUNE_VERTEXES) pruneVertices(map); if(flags & PRUNE_SIDEDEFS) pruneUnusedSidedefs(map); if(flags & PRUNE_SECTORS) pruneUnusedSectors(map); #endif } /** * Register the specified sector in the list of unclosed sectors. * * @param sec Ptr to the sector to be registered. * @param x Approximate X coordinate to the sector's origin. * @param y Approximate Y coordinate to the sector's origin. * * @return @c true, if sector was registered. */ boolean MPE_RegisterUnclosedSectorNear(sector_t *sec, double x, double y) { uint i; usecrecord_t *usec; if(!sec) return false; // Wha? // Has this sector already been registered as unclosed? for(i = 0; i < numUnclosedSectors; ++i) { if(unclosedSectors[i].sec == sec) return true; } // A new one. unclosedSectors = M_Realloc(unclosedSectors, ++numUnclosedSectors * sizeof(usecrecord_t)); usec = &unclosedSectors[numUnclosedSectors-1]; usec->sec = sec; usec->nearPos[VX] = x; usec->nearPos[VY] = y; // Flag the sector as unclosed. sec->flags |= SECF_UNCLOSED; return true; } /** * Print the list of unclosed sectors. */ void MPE_PrintUnclosedSectorList(void) { uint i; if(!editMapInited) return; for(i = 0; i < numUnclosedSectors; ++i) { usecrecord_t *usec = &unclosedSectors[i]; Con_Message("Sector #%d is unclosed near (%1.1f,%1.1f)\n", usec->sec->buildData.index - 1, usec->nearPos[VX], usec->nearPos[VY]); } } /** * Free the list of unclosed sectors. */ void MPE_FreeUnclosedSectorList(void) { if(unclosedSectors) M_Free(unclosedSectors); unclosedSectors = NULL; numUnclosedSectors = 0; } /** * Called to begin the map building process. */ boolean MPE_Begin(const char *name) { if(editMapInited) return true; // Already been here. MPE_FreeUnclosedSectorList(); // Init the gameObj lists, and value db. map->gameObjData.db.numTables = 0; map->gameObjData.db.tables = NULL; map->gameObjData.objLists = NULL; destroyMap(); if(name && name[0]) { strncpy(map->name, name, 8); } editMapInited = true; return true; } static void hardenSectorSSecList(gamemap_t *map, uint secIDX) { uint i, n, count; sector_t *sec = &map->sectors[secIDX]; count = 0; for(i = 0; i < map->numSSectors; ++i) { subsector_t *ssec = &map->ssectors[i]; if(ssec->sector == sec) count++; } sec->ssectors = Z_Malloc((count + 1) * sizeof(subsector_t*), PU_MAPSTATIC, NULL); n = 0; for(i = 0; i < map->numSSectors; ++i) { subsector_t *ssec = &map->ssectors[i]; if(ssec->sector == sec) { ssec->inSectorID = n; sec->ssectors[n++] = ssec; } } sec->ssectors[n] = NULL; // Terminate. sec->ssectorCount = count; } /** * Build subsector tables for all sectors. */ static void buildSectorSSecLists(gamemap_t *map) { uint i; Con_Message(" Build subsector tables...\n"); for(i = 0; i < map->numSectors; ++i) { hardenSectorSSecList(map, i); } } static void buildSectorLineLists(gamemap_t* map) { typedef struct linelink_s { linedef_t* line; struct linelink_s* next; } linelink_t; uint i, j; linedef_t* li; sector_t* sec; zblockset_t* lineLinksBlockSet; linelink_t** sectorLineLinks; uint totallinks; Con_Message(" Build line tables...\n"); // build line tables for each sector. lineLinksBlockSet = Z_BlockCreate(sizeof(linelink_t), 512, PU_STATIC); sectorLineLinks = M_Calloc(sizeof(linelink_t*) * map->numSectors); totallinks = 0; for(i = 0, li = map->lineDefs; i < map->numLineDefs; ++i, li++) { uint secIDX; linelink_t* link; if(li->L_frontside) { link = Z_BlockNewElement(lineLinksBlockSet); secIDX = li->L_frontsector - map->sectors; link->line = li; link->next = sectorLineLinks[secIDX]; sectorLineLinks[secIDX] = link; li->L_frontsector->lineDefCount++; totallinks++; } if(li->L_backside && li->L_backsector != li->L_frontsector) { link = Z_BlockNewElement(lineLinksBlockSet); secIDX = li->L_backsector - map->sectors; link->line = li; link->next = sectorLineLinks[secIDX]; sectorLineLinks[secIDX] = link; li->L_backsector->lineDefCount++; totallinks++; } } // Harden the sector line links into arrays. { linedef_t** linebuffer; linedef_t** linebptr; linebuffer = Z_Malloc((totallinks + map->numSectors) * sizeof(linedef_t*), PU_MAPSTATIC, 0); linebptr = linebuffer; for(i = 0, sec = map->sectors; i < map->numSectors; ++i, sec++) { if(sectorLineLinks[i]) { linelink_t* link = sectorLineLinks[i]; uint numLineDefs; /** * The behaviour of some algorithms used in original DOOM are * dependant upon the order of these lists (e.g., EV_DoFloor * and EV_BuildStairs). Lets be helpful and use the same order. * * Sort: LineDef index ascending (zero based). */ numLineDefs = 0; while(link) { numLineDefs++; link = link->next; } sec->lineDefs = linebptr; j = numLineDefs - 1; link = sectorLineLinks[i]; while(link) { sec->lineDefs[j--] = link->line; link = link->next; } sec->lineDefs[numLineDefs] = NULL; // terminate. sec->lineDefCount = numLineDefs; linebptr += numLineDefs + 1; } else { sec->lineDefs = NULL; sec->lineDefCount = 0; } } } // Free temporary storage. Z_BlockDestroy(lineLinksBlockSet); M_Free(sectorLineLinks); } /** * \pre Lines in sector must be setup before this is called! */ static void updateSectorBounds(sector_t* sec) { uint i; float* bbox; vertex_t* vtx; if(!sec) return; bbox = sec->bBox; if(!(sec->lineDefCount > 0)) { memset(sec->bBox, 0, sizeof(sec->bBox)); return; } vtx = sec->lineDefs[0]->L_v1; bbox[BOXLEFT] = bbox[BOXRIGHT] = vtx->V_pos[VX]; bbox[BOXTOP] = bbox[BOXBOTTOM] = vtx->V_pos[VY]; for(i = 1; i < sec->lineDefCount; ++i) { vtx = sec->lineDefs[i]->L_v1; if(vtx->V_pos[VX] < bbox[BOXLEFT]) bbox[BOXLEFT] = vtx->V_pos[VX]; if(vtx->V_pos[VX] > bbox[BOXRIGHT]) bbox[BOXRIGHT] = vtx->V_pos[VX]; if(vtx->V_pos[VY] < bbox[BOXBOTTOM]) bbox[BOXBOTTOM] = vtx->V_pos[VY]; if(vtx->V_pos[VY] > bbox[BOXTOP]) bbox[BOXTOP] = vtx->V_pos[VY]; } // This is very rough estimate of sector area. sec->approxArea = ((bbox[BOXRIGHT] - bbox[BOXLEFT]) / 128) * ((bbox[BOXTOP] - bbox[BOXBOTTOM]) / 128); } /** * \pre Sector bounds must be setup before this is called! */ void P_GetSectorBounds(sector_t *sec, float *min, float *max) { min[VX] = sec->bBox[BOXLEFT]; min[VY] = sec->bBox[BOXBOTTOM]; max[VX] = sec->bBox[BOXRIGHT]; max[VY] = sec->bBox[BOXTOP]; } static void finishSectors(gamemap_t *map) { uint i; vec2_t bmapOrigin; uint bmapSize[2]; P_GetBlockmapBounds(map->blockMap, bmapOrigin, NULL); P_GetBlockmapDimensions(map->blockMap, bmapSize); for(i = 0; i < map->numSectors; ++i) { uint k; float min[2], max[2]; sector_t *sec = &map->sectors[i]; updateSectorBounds(sec); P_GetSectorBounds(sec, min, max); // Set the degenmobj_t to the middle of the bounding box. sec->soundOrg.pos[VX] = (min[VX] + max[VX]) / 2; sec->soundOrg.pos[VY] = (min[VY] + max[VY]) / 2; // Set the z height of the sector sound origin. sec->soundOrg.pos[VZ] = (sec->SP_ceilheight - sec->SP_floorheight) / 2; // Set the position of the sound origin for all plane sound origins. // Set target heights for all planes. for(k = 0; k < sec->planeCount; ++k) { sec->planes[k]->soundOrg.pos[VX] = sec->soundOrg.pos[VX]; sec->planes[k]->soundOrg.pos[VY] = sec->soundOrg.pos[VY]; sec->planes[k]->soundOrg.pos[VZ] = sec->planes[k]->height; sec->planes[k]->target = sec->planes[k]->height; } } } /** * Completes the linedef loading by resolving the front/back * sector ptrs which we couldn't do earlier as the sidedefs * hadn't been loaded at the time. */ static void finishLineDefs(gamemap_t* map) { uint i; linedef_t *ld; vertex_t *v[2]; seg_t *startSeg, *endSeg; VERBOSE2(Con_Message("Finalizing Linedefs...\n")); for(i = 0; i < map->numLineDefs; ++i) { ld = &map->lineDefs[i]; if(!ld->sideDefs[0]->segCount) continue; startSeg = ld->sideDefs[0]->segs[0]; endSeg = ld->sideDefs[0]->segs[ld->sideDefs[0]->segCount - 1]; ld->v[0] = v[0] = startSeg->SG_v1; ld->v[1] = v[1] = endSeg->SG_v2; ld->dX = v[1]->V_pos[VX] - v[0]->V_pos[VX]; ld->dY = v[1]->V_pos[VY] - v[0]->V_pos[VY]; // Calculate the accurate length of each line. ld->length = P_AccurateDistance(ld->dX, ld->dY); ld->angle = bamsAtan2((int) (ld->v[1]->V_pos[VY] - ld->v[0]->V_pos[VY]), (int) (ld->v[1]->V_pos[VX] - ld->v[0]->V_pos[VX])); if(!ld->dX) ld->slopeType = ST_VERTICAL; else if(!ld->dY) ld->slopeType = ST_HORIZONTAL; else { if(ld->dY / ld->dX > 0) ld->slopeType = ST_POSITIVE; else ld->slopeType = ST_NEGATIVE; } if(v[0]->V_pos[VX] < v[1]->V_pos[VX]) { ld->bBox[BOXLEFT] = v[0]->V_pos[VX]; ld->bBox[BOXRIGHT] = v[1]->V_pos[VX]; } else { ld->bBox[BOXLEFT] = v[1]->V_pos[VX]; ld->bBox[BOXRIGHT] = v[0]->V_pos[VX]; } if(v[0]->V_pos[VY] < v[1]->V_pos[VY]) { ld->bBox[BOXBOTTOM] = v[0]->V_pos[VY]; ld->bBox[BOXTOP] = v[1]->V_pos[VY]; } else { ld->bBox[BOXBOTTOM] = v[1]->V_pos[VY]; ld->bBox[BOXTOP] = v[0]->V_pos[VY]; } } } static void updateMapBounds(gamemap_t *map) { uint i; memset(map->bBox, 0, sizeof(map->bBox)); for(i = 0; i < map->numSectors; ++i) { sector_t *sec = &map->sectors[i]; if(i == 0) { // The first sector is used as is. memcpy(map->bBox, sec->bBox, sizeof(map->bBox)); } else { // Expand the bounding box. M_JoinBoxes(map->bBox, sec->bBox); } } } static void updateSSecMidPoint(subsector_t *sub) { seg_t **ptr; fvertex_t *vtx; // Find the center point. First calculate the bounding box. ptr = sub->segs; vtx = &((*ptr)->SG_v1->v); sub->bBox[0].pos[VX] = sub->bBox[1].pos[VX] = sub->midPoint.pos[VX] = vtx->pos[VX]; sub->bBox[0].pos[VY] = sub->bBox[1].pos[VY] = sub->midPoint.pos[VY] = vtx->pos[VY]; *ptr++; while(*ptr) { vtx = &((*ptr)->SG_v1->v); if(vtx->pos[VX] < sub->bBox[0].pos[VX]) sub->bBox[0].pos[VX] = vtx->pos[VX]; if(vtx->pos[VY] < sub->bBox[0].pos[VY]) sub->bBox[0].pos[VY] = vtx->pos[VY]; if(vtx->pos[VX] > sub->bBox[1].pos[VX]) sub->bBox[1].pos[VX] = vtx->pos[VX]; if(vtx->pos[VY] > sub->bBox[1].pos[VY]) sub->bBox[1].pos[VY] = vtx->pos[VY]; sub->midPoint.pos[VX] += vtx->pos[VX]; sub->midPoint.pos[VY] += vtx->pos[VY]; *ptr++; } sub->midPoint.pos[VX] /= sub->segCount; // num vertices. sub->midPoint.pos[VY] /= sub->segCount; // Calculate the worldwide grid offset. sub->worldGridOffset[VX] = fmod(sub->bBox[0].pos[VX], 64); sub->worldGridOffset[VY] = fmod(sub->bBox[1].pos[VY], 64); } static void prepareSubSectors(gamemap_t *map) { uint i; for(i = 0; i < map->numSSectors; ++i) { subsector_t *ssec = &map->ssectors[i]; updateSSecMidPoint(ssec); } } /** * Compares the angles of two lines that share a common vertex. * * pre: rootVtx must point to the vertex common between a and b * which are (lineowner_t*) ptrs. */ static int C_DECL lineAngleSorter(const void *a, const void *b) { uint i; fixed_t dx, dy; binangle_t angles[2]; lineowner_t *own[2]; linedef_t *line; own[0] = (lineowner_t *)a; own[1] = (lineowner_t *)b; for(i = 0; i < 2; ++i) { if(own[i]->LO_prev) // We have a cached result. { angles[i] = own[i]->angle; } else { vertex_t *otherVtx; line = own[i]->lineDef; otherVtx = line->L_v(line->L_v1 == rootVtx? 1:0); dx = otherVtx->V_pos[VX] - rootVtx->V_pos[VX]; dy = otherVtx->V_pos[VY] - rootVtx->V_pos[VY]; own[i]->angle = angles[i] = bamsAtan2(-100 *dx, 100 * dy); // Mark as having a cached angle. own[i]->LO_prev = (lineowner_t*) 1; } } return (angles[1] - angles[0]); } /** * Merge left and right line owner lists into a new list. * * @return Ptr to the newly merged list. */ static lineowner_t *mergeLineOwners(lineowner_t *left, lineowner_t *right, int (C_DECL *compare) (const void *a, const void *b)) { lineowner_t tmp, *np; np = &tmp; tmp.LO_next = np; while(left != NULL && right != NULL) { if(compare(left, right) <= 0) { np->LO_next = left; np = left; left = left->LO_next; } else { np->LO_next = right; np = right; right = right->LO_next; } } // At least one of these lists is now empty. if(left) np->LO_next = left; if(right) np->LO_next = right; // Is the list empty? if(tmp.LO_next == &tmp) return NULL; return tmp.LO_next; } static lineowner_t *splitLineOwners(lineowner_t *list) { lineowner_t *lista, *listb, *listc; if(!list) return NULL; lista = listb = listc = list; do { listc = listb; listb = listb->LO_next; lista = lista->LO_next; if(lista != NULL) lista = lista->LO_next; } while(lista); listc->LO_next = NULL; return listb; } /** * This routine uses a recursive mergesort algorithm; O(NlogN) */ static lineowner_t *sortLineOwners(lineowner_t *list, int (C_DECL *compare) (const void *a, const void *b)) { lineowner_t *p; if(list && list->LO_next) { p = splitLineOwners(list); // Sort both halves and merge them back. list = mergeLineOwners(sortLineOwners(list, compare), sortLineOwners(p, compare), compare); } return list; } static void setVertexLineOwner(vertex_t *vtx, linedef_t *lineptr, lineowner_t **storage) { lineowner_t *p, *newOwner; if(!lineptr) return; // Has this line already been registered with this vertex? if(vtx->numLineOwners != 0) { p = vtx->lineOwners; while(p) { if(p->lineDef == lineptr) return; // Yes, we can exit. p = p->LO_next; } } //Add a new owner. vtx->numLineOwners++; newOwner = (*storage)++; newOwner->lineDef = lineptr; newOwner->LO_prev = NULL; // Link it in. // NOTE: We don't bother linking everything at this stage since we'll // be sorting the lists anyway. After which we'll finish the job by // setting the prev and circular links. // So, for now this is only linked singlely, forward. newOwner->LO_next = vtx->lineOwners; vtx->lineOwners = newOwner; // Link the line to its respective owner node. if(vtx == lineptr->L_v1) lineptr->L_vo1 = newOwner; else lineptr->L_vo2 = newOwner; } /** * Generates the line owner rings for each vertex. Each ring includes all * the lines which the vertex belongs to sorted by angle, (the rings are * arranged in clockwise order, east = 0). */ static void buildVertexOwnerRings(editmap_t* map) { uint i; lineowner_t* lineOwners, *allocator; // We know how many vertex line owners we need (numLineDefs * 2). lineOwners = Z_Malloc(sizeof(lineowner_t) * map->numLineDefs * 2, PU_MAPSTATIC, 0); allocator = lineOwners; for(i = 0; i < map->numLineDefs; ++i) { uint p; linedef_t* line = map->lineDefs[i]; for(p = 0; p < 2; ++p) { vertex_t* vtx = line->L_v(p); setVertexLineOwner(vtx, line, &allocator); } } } static void hardenVertexOwnerRings(gamemap_t* dest, editmap_t* src) { uint i; // Sort line owners and then finish the rings. for(i = 0; i < src->numVertexes; ++i) { vertex_t* v = src->vertexes[i]; // Line owners: if(v->numLineOwners != 0) { lineowner_t* p, *last; binangle_t firstAngle; // Redirect the linedef links to the hardened map. p = v->lineOwners; while(p) { p->lineDef = &dest->lineDefs[p->lineDef->buildData.index - 1]; p = p->LO_next; } // Sort them; ordered clockwise by angle. rootVtx = v; v->lineOwners = sortLineOwners(v->lineOwners, lineAngleSorter); // Finish the linking job and convert to relative angles. // They are only singly linked atm, we need them to be doubly // and circularly linked. firstAngle = v->lineOwners->angle; last = v->lineOwners; p = last->LO_next; while(p) { p->LO_prev = last; // Convert to a relative angle between last and this. last->angle = last->angle - p->angle; last = p; p = p->LO_next; } last->LO_next = v->lineOwners; v->lineOwners->LO_prev = last; // Set the angle of the last owner. last->angle = last->angle - firstAngle; /* #if _DEBUG { // For checking the line owner link rings are formed correctly. lineowner_t *base; uint idx; if(verbose >= 2) Con_Message("Vertex #%i: line owners #%i\n", i, v->numLineOwners); p = base = v->lineOwners; idx = 0; do { if(verbose >= 2) Con_Message(" %i: p= #%05i this= #%05i n= #%05i, dANG= %-3.f\n", idx, p->LO_prev->line - map->lineDefs, p->line - map->lineDefs, p->LO_next->line - map->lineDefs, BANG2DEG(p->angle)); if(p->LO_prev->LO_next != p || p->LO_next->LO_prev != p) Con_Error("Invalid line owner link ring!"); p = p->LO_next; idx++; } while(p != base); } #endif */ } } } static void hardenLinedefs(gamemap_t *dest, editmap_t *src) { uint i; dest->numLineDefs = src->numLineDefs; dest->lineDefs = Z_Calloc(dest->numLineDefs * sizeof(linedef_t), PU_MAPSTATIC, 0); for(i = 0; i < dest->numLineDefs; ++i) { linedef_t *destL = &dest->lineDefs[i]; linedef_t *srcL = src->lineDefs[i]; memcpy(destL, srcL, sizeof(*destL)); //// \todo We shouldn't still have lines with missing fronts but... destL->L_frontside = (srcL->L_frontside? &dest->sideDefs[srcL->L_frontside->buildData.index - 1] : NULL); destL->L_backside = (srcL->L_backside? &dest->sideDefs[srcL->L_backside->buildData.index - 1] : NULL); if(destL->L_frontside) destL->L_frontside->line = destL; if(destL->L_backside) destL->L_backside->line = destL; } } static void hardenSidedefs(gamemap_t* dest, editmap_t* src) { uint i; dest->numSideDefs = src->numSideDefs; dest->sideDefs = Z_Malloc(dest->numSideDefs * sizeof(sidedef_t), PU_MAPSTATIC, 0); for(i = 0; i < dest->numSideDefs; ++i) { sidedef_t *destS = &dest->sideDefs[i]; sidedef_t *srcS = src->sideDefs[i]; memcpy(destS, srcS, sizeof(*destS)); destS->sector = &dest->sectors[srcS->sector->buildData.index - 1]; destS->SW_bottomsurface.owner = destS; destS->SW_middlesurface.owner = destS; destS->SW_topsurface.owner = destS; destS->SW_bottomsurface.visOffset[0] = destS->SW_bottomsurface.offset[0]; destS->SW_bottomsurface.visOffset[1] = destS->SW_bottomsurface.offset[1]; destS->SW_middlesurface.visOffset[0] = destS->SW_middlesurface.offset[0]; destS->SW_middlesurface.visOffset[1] = destS->SW_middlesurface.offset[1]; destS->SW_topsurface.visOffset[0] = destS->SW_topsurface.offset[0]; destS->SW_topsurface.visOffset[1] = destS->SW_topsurface.offset[1]; } } static void hardenSectors(gamemap_t* dest, editmap_t* src) { uint i; dest->numSectors = src->numSectors; dest->sectors = Z_Malloc(dest->numSectors * sizeof(sector_t), PU_MAPSTATIC, 0); for(i = 0; i < dest->numSectors; ++i) { sector_t *destS = &dest->sectors[i]; sector_t *srcS = src->sectors[i]; memcpy(destS, srcS, sizeof(*destS)); destS->planeCount = 0; destS->planes = NULL; } } static void hardenPlanes(gamemap_t* dest, editmap_t* src) { uint i, j; for(i = 0; i < dest->numSectors; ++i) { sector_t *destS = &dest->sectors[i]; sector_t *srcS = src->sectors[i]; for(j = 0; j < srcS->planeCount; ++j) { plane_t* destP = R_NewPlaneForSector(destS); plane_t* srcP = srcS->planes[j]; destP->glow = srcP->glow; destP->glowRGB[CR] = srcP->glowRGB[CR]; destP->glowRGB[CG] = srcP->glowRGB[CG]; destP->glowRGB[CB] = srcP->glowRGB[CB]; destP->height = destP->oldHeight[0] = destP->oldHeight[1] = destP->visHeight = srcP->height; destP->visHeightDelta = 0; memcpy(&destP->surface, &srcP->surface, sizeof(destP->surface)); destP->type = srcP->type; destP->sector = destS; } } } static void hardenPolyobjs(gamemap_t* dest, editmap_t* src) { uint i; if(src->numPolyObjs == 0) { dest->numPolyObjs = 0; dest->polyObjs = NULL; return; } dest->numPolyObjs = src->numPolyObjs; dest->polyObjs = Z_Malloc((dest->numPolyObjs+1) * sizeof(polyobj_t*), PU_MAP, 0); for(i = 0; i < dest->numPolyObjs; ++i) { uint j; polyobj_t* destP, *srcP = src->polyObjs[i]; seg_t* segs; destP = Z_Calloc(POLYOBJ_SIZE, PU_MAP, 0); destP->idx = i; destP->crush = srcP->crush; destP->tag = srcP->tag; destP->seqType = srcP->seqType; destP->pos[VX] = srcP->pos[VX]; destP->pos[VY] = srcP->pos[VY]; destP->numSegs = srcP->buildData.lineCount; destP->originalPts = Z_Malloc(destP->numSegs * sizeof(fvertex_t), PU_MAP, 0); destP->prevPts = Z_Malloc(destP->numSegs * sizeof(fvertex_t), PU_MAP, 0); // Create a seg for each line of this polyobj. segs = Z_Calloc(sizeof(seg_t) * destP->numSegs, PU_MAP, 0); destP->segs = Z_Malloc(sizeof(seg_t*) * (destP->numSegs+1), PU_MAP, 0); for(j = 0; j < destP->numSegs; ++j) { linedef_t* line = &dest->lineDefs[srcP->buildData.lineDefs[j]->buildData.index - 1]; seg_t* seg = &segs[j]; float dx, dy; // This line is part of a polyobj. line->inFlags |= LF_POLYOBJ; seg->header.type = DMU_SEG; seg->lineDef = line; dx = line->L_v2pos[VX] - line->L_v1pos[VX]; dy = line->L_v2pos[VY] - line->L_v1pos[VY]; seg->length = P_AccurateDistance(dx, dy); seg->backSeg = NULL; seg->subsector = NULL; seg->SG_frontsector = line->L_frontsector; seg->SG_backsector = NULL; seg->flags |= SEGF_POLYOBJ; destP->segs[j] = seg; } destP->segs[j] = NULL; // Terminate. // Add this polyobj to the global list. dest->polyObjs[i] = destP; } dest->polyObjs[i] = NULL; // Terminate. } /** * \note Algorithm: * Cast a line horizontally or vertically and see what we hit (OUCH, we * have to iterate over all linedefs!). */ static void testForWindowEffect(editmap_t* map, linedef_t* l) { // Smallest distance between two points before being considered equal. #define DIST_EPSILON (1.0 / 128.0) uint i; double mX, mY, dX, dY; boolean castHoriz; double backDist = DDMAXFLOAT; sector_t* backOpen = NULL; double frontDist = DDMAXFLOAT; sector_t* frontOpen = NULL; linedef_t* frontLine = NULL, *backLine = NULL; mX = (l->v[0]->buildData.pos[VX] + l->v[1]->buildData.pos[VX]) / 2.0; mY = (l->v[0]->buildData.pos[VY] + l->v[1]->buildData.pos[VY]) / 2.0; dX = l->v[1]->buildData.pos[VX] - l->v[0]->buildData.pos[VX]; dY = l->v[1]->buildData.pos[VY] - l->v[0]->buildData.pos[VY]; castHoriz = (fabs(dX) < fabs(dY)? true : false); for(i = 0; i < map->numLineDefs; ++i) { linedef_t* n = map->lineDefs[i]; double dist; boolean isFront; sidedef_t* hitSide; double dX2, dY2; if(n == l || LINE_SELFREF(n) /*|| n->buildData.overlap || (n->buildData.mlFlags & MLF_ZEROLENGTH)*/) continue; if(n->buildData.mlFlags & MLF_POLYOBJ) continue; dX2 = n->v[1]->buildData.pos[VX] - n->v[0]->buildData.pos[VX]; dY2 = n->v[1]->buildData.pos[VY] - n->v[0]->buildData.pos[VY]; if(castHoriz) { // Horizontal. if(fabs(dY2) < DIST_EPSILON) continue; if((MAX_OF(n->v[0]->buildData.pos[VY], n->v[1]->buildData.pos[VY]) < mY - DIST_EPSILON) || (MIN_OF(n->v[0]->buildData.pos[VY], n->v[1]->buildData.pos[VY]) > mY + DIST_EPSILON)) continue; dist = (n->v[0]->buildData.pos[VX] + (mY - n->v[0]->buildData.pos[VY]) * dX2 / dY2) - mX; isFront = (((dY > 0) != (dist > 0)) ? true : false); dist = fabs(dist); if(dist < DIST_EPSILON) continue; // Too close (overlapping lines ?) hitSide = n->sideDefs[(dY > 0) ^ (dY2 > 0) ^ !isFront]; } else { // Vertical. if(fabs(dX2) < DIST_EPSILON) continue; if((MAX_OF(n->v[0]->buildData.pos[VX], n->v[1]->buildData.pos[VX]) < mX - DIST_EPSILON) || (MIN_OF(n->v[0]->buildData.pos[VX], n->v[1]->buildData.pos[VX]) > mX + DIST_EPSILON)) continue; dist = (n->v[0]->buildData.pos[VY] + (mX - n->v[0]->buildData.pos[VX]) * dY2 / dX2) - mY; isFront = (((dX > 0) == (dist > 0)) ? true : false); dist = fabs(dist); hitSide = n->sideDefs[(dX > 0) ^ (dX2 > 0) ^ !isFront]; } if(dist < DIST_EPSILON) // Too close (overlapping lines ?) continue; if(isFront) { if(dist < frontDist) { frontDist = dist; if(hitSide) frontOpen = hitSide->sector; else frontOpen = NULL; frontLine = n; } } else { if(dist < backDist) { backDist = dist; if(hitSide) backOpen = hitSide->sector; else backOpen = NULL; backLine = n; } } } /*#if _DEBUG Con_Message("back line: %d back dist: %1.1f back_open: %s\n", (backLine? backLine->buildData.index : -1), backDist, (backOpen? "OPEN" : "CLOSED")); Con_Message("front line: %d front dist: %1.1f front_open: %s\n", (frontLine? frontLine->buildData.index : -1), frontDist, (frontOpen? "OPEN" : "CLOSED")); #endif*/ if(backOpen && frontOpen && l->sideDefs[FRONT]->sector == backOpen) { VERBOSE( Con_Message("Linedef #%d seems to be a One-Sided Window " "(back faces sector #%d).\n", l->buildData.index - 1, backOpen->buildData.index - 1) ); l->buildData.windowEffect = frontOpen; } #undef DIST_EPSILON } static void countVertexLineOwners(vertex_t* vtx, uint* oneSided, uint* twoSided) { lineowner_t* p; p = vtx->lineOwners; while(p) { if(!p->lineDef->L_frontside || !p->lineDef->L_backside) (*oneSided)++; else (*twoSided)++; p = p->LO_next; } } /** * \note Algorithm: * Scan the linedef list looking for possible candidates, checking for an * odd number of one-sided linedefs connected to a single vertex. * This idea courtesy of Graham Jackson. */ void MPE_DetectWindowEffects(editmap_t* map) { uint i, oneSiders, twoSiders; for(i = 0; i < map->numLineDefs; ++i) { linedef_t* l = map->lineDefs[i]; if((l->L_frontside && l->L_backside) || !l->L_frontside /*|| (l->buildData.mlFlags & MLF_ZEROLENGTH) || l->buildData.overlap*/) continue; if(l->buildData.mlFlags & MLF_POLYOBJ) continue; oneSiders = twoSiders = 0; countVertexLineOwners(l->v[0], &oneSiders, &twoSiders); if((oneSiders % 2) == 1 && (oneSiders + twoSiders) > 1) { /*#if _DEBUG Con_Message("FUNNY LINE %d : start vertex %d has odd number of one-siders\n", i, l->buildData.v[0]->index); #endif*/ testForWindowEffect(map, l); continue; } oneSiders = twoSiders = 0; countVertexLineOwners(l->v[1], &oneSiders, &twoSiders); if((oneSiders % 2) == 1 && (oneSiders + twoSiders) > 1) { /*#if _DEBUG Con_Message("FUNNY LINE %d : end vertex %d has odd number of one-siders\n", i, l->buildData.v[1]->index)); #endif*/ testForWindowEffect(map, l); } } } #if 0 /* Currently unused. */ /** * @return The "lowest" vertex (normally the left-most, but if * the line is vertical, then the bottom-most). * @c => 0 for start, 1 for end. */ static __inline int lineVertexLowest(const linedef_t* l) { return (((int) l->v[0]->buildData.pos[VX] < (int) l->v[1]->buildData.pos[VX] || ((int) l->v[0]->buildData.pos[VX] == (int) l->v[1]->buildData.pos[VX] && (int) l->v[0]->buildData.pos[VY] < (int) l->v[1]->buildData.pos[VY]))? 0 : 1); } static int C_DECL lineStartCompare(const void* p1, const void* p2) { const linedef_t* a = (const linedef_t*) p1; const linedef_t* b = (const linedef_t*) p2; vertex_t* c, *d; // Determine left-most vertex of each line. c = (lineVertexLowest(a)? a->v[1] : a->v[0]); d = (lineVertexLowest(b)? b->v[1] : b->v[0]); if((int) c->buildData.pos[VX] != (int) d->buildData.pos[VX]) return (int) c->buildData.pos[VX] - (int) d->buildData.pos[VX]; return (int) c->buildData.pos[VY] - (int) d->buildData.pos[VY]; } static int C_DECL lineEndCompare(const void* p1, const void* p2) { const linedef_t* a = (const linedef_t*) p1; const linedef_t* b = (const linedef_t*) p2; vertex_t* c, *d; // Determine right-most vertex of each line. c = (lineVertexLowest(a)? a->v[0] : a->v[1]); d = (lineVertexLowest(b)? b->v[0] : b->v[1]); if((int) c->buildData.pos[VX] != (int) d->buildData.pos[VX]) return (int) c->buildData.pos[VX] - (int) d->buildData.pos[VX]; return (int) c->buildData.pos[VY] - (int) d->buildData.pos[VY]; } size_t numOverlaps; boolean testOverlaps(linedef_t* b, void* data) { linedef_t* a = (linedef_t*) data; if(a != b) { if(lineStartCompare(a, b) == 0) if(lineEndCompare(a, b) == 0) { // Found an overlap! b->buildData.overlap = (a->buildData.overlap ? a->buildData.overlap : a); numOverlaps++; } } return true; // Continue iteration. } typedef struct { blockmap_t* blockMap; uint block[2]; } findoverlaps_params_t; boolean findOverlapsForLinedef(linedef_t* l, void* data) { findoverlaps_params_t* params = (findoverlaps_params_t*) data; P_BlockmapLinesIterator(params->blockMap, params->block, testOverlaps, l); return true; // Continue iteration. } /** * \note Does not detect partially overlapping lines! */ void MPE_DetectOverlappingLines(gamemap_t* map) { uint x, y, bmapDimensions[2]; findoverlaps_params_t params; params.blockMap = map->blockMap; numOverlaps = 0; P_GetBlockmapDimensions(map->blockMap, bmapDimensions); for(y = 0; y < bmapDimensions[VY]; ++y) for(x = 0; x < bmapDimensions[VX]; ++x) { params.block[VX] = x; params.block[VY] = y; P_BlockmapLinesIterator(map->blockMap, params.block, findOverlapsForLinedef, ¶ms); } if(numOverlaps > 0) VERBOSE(Con_Message("Detected %lu overlapped linedefs\n", (unsigned long) numOverlaps)); } #endif /** * Called to complete the map building process. */ boolean MPE_End(void) { uint i; gamemap_t* gamemap; boolean builtOK; if(!editMapInited) return false; gamemap = Z_Calloc(sizeof(*gamemap), PU_MAPSTATIC, 0); // Pass on the game map obj database. The game will want to query it // once we have finished constructing the map. memcpy(&gamemap->gameObjData, &map->gameObjData, sizeof(gamemap->gameObjData)); /** * Perform cleanup on the loaded map data, removing duplicate vertexes, * pruning unused sectors etc, etc... */ MPE_DetectDuplicateVertices(map); MPE_PruneRedundantMapData(map, PRUNE_ALL); buildVertexOwnerRings(map); MPE_DetectWindowEffects(map); /** * Harden most of the map data so that we can construct some of the more * intricate data structures early on (and thus make use of them during * the BSP generation). * * \todo I'm sure this can be reworked further so that we destroy as we * go and reduce the current working memory surcharge. */ hardenSectors(gamemap, map); hardenSidedefs(gamemap, map); hardenLinedefs(gamemap, map); hardenPolyobjs(gamemap, map); hardenVertexOwnerRings(gamemap, map); // Don't destroy the sectors (planes are linked to them). destroyEditableSideDefs(map); destroyEditableLineDefs(map); destroyEditablePolyObjs(map); /** * Build a blockmap for this map. */ gamemap->blockMap = DAM_BuildBlockMap(&map->vertexes, &map->numVertexes, &gamemap->lineDefs, &gamemap->numLineDefs); /** * Build a BSP for this map. */ builtOK = BSP_Build(gamemap, &map->vertexes, &map->numVertexes); // Finish the polyobjs (after the vertexes are hardened). for(i = 0; i < gamemap->numPolyObjs; ++i) { polyobj_t* po = gamemap->polyObjs[i]; seg_t** segPtr; size_t n; segPtr = po->segs; n = 0; while(*segPtr) { seg_t* seg = *segPtr; seg->SG_v1 = seg->lineDef->L_v1; seg->SG_v2 = seg->lineDef->L_v2; // The original Pts are based off the anchor Pt, and are unique // to each seg, not each linedef. po->originalPts[n].pos[VX] = seg->SG_v1pos[VX] - po->pos[VX]; po->originalPts[n].pos[VY] = seg->SG_v1pos[VY] - po->pos[VY]; *segPtr++; n++; } } // Polygonize. R_PolygonizeMap(gamemap); buildSectorSSecLists(gamemap); // Announce any issues detected with the map. MPE_PrintMapErrors(); // Map must be polygonized and sector->ssectors must be built before // this is called! hardenPlanes(gamemap, map); // Destroy the rest of editable map, we are finished with it. // \note Only the vertexes should be left anyway. destroyMap(); if(!builtOK) { // Argh, failed. // Need to clean up. P_DestroyGameMapObjDB(&gamemap->gameObjData); Z_Free(gamemap); return false; } buildSectorLineLists(gamemap); finishLineDefs(gamemap); finishSectors(gamemap); updateMapBounds(gamemap); S_DetermineSubSecsAffectingSectorReverb(gamemap); prepareSubSectors(gamemap); P_FreeBadTexList(); MPE_FreeUnclosedSectorList(); editMapInited = false; // Call the game's setup routines. if(gx.SetupForMapData) { gx.SetupForMapData(DMU_VERTEX, gamemap->numVertexes); gx.SetupForMapData(DMU_LINEDEF, gamemap->numLineDefs); gx.SetupForMapData(DMU_SIDEDEF, gamemap->numSideDefs); gx.SetupForMapData(DMU_SECTOR, gamemap->numSectors); } /** * Are we caching this map? */ if(gamemap->mapID && gamemap->mapID[0]) { // Yes, write the cached map data file. filename_t cachedMapDir; filename_t cachedMapDataFile; int markerLumpNum; markerLumpNum = W_GetNumForName(gamemap->mapID); DAM_GetCachedMapDir(cachedMapDir, markerLumpNum, FILENAME_T_MAXLEN); // Ensure the destination path exists. M_CheckPath(cachedMapDir); sprintf(cachedMapDataFile, "%s%s", cachedMapDir, W_LumpName(markerLumpNum)); M_TranslatePath(cachedMapDataFile, cachedMapDataFile, FILENAME_T_MAXLEN); strncat(cachedMapDataFile, ".dcm", FILENAME_T_MAXLEN); DAM_MapWrite(gamemap, cachedMapDataFile); } lastBuiltMap = gamemap; // Success! return true; } gamemap_t* MPE_GetLastBuiltMap(void) { return lastBuiltMap; } /** * If we encountered any problems during setup - announce them to the user. */ void MPE_PrintMapErrors(void) { // Announce unclosed sectors. MPE_PrintUnclosedSectorList(); // Announce any bad texture names we came across when loading the map. P_PrintMissingTextureList(); } /** * Create a new vertex in currently loaded editable map. * * @param x X coordinate of the new vertex. * @param y Y coordinate of the new vertex. * * @return Index number of the newly created vertex else 0 if * the vertex could not be created for some reason. */ uint MPE_VertexCreate(float x, float y) { vertex_t* v; if(!editMapInited) return 0; v = createVertex(); v->V_pos[VX] = x; v->V_pos[VY] = y; v->buildData.pos[VX] = (double) v->V_pos[VX]; v->buildData.pos[VY] = (double) v->V_pos[VY]; return v->buildData.index; } /** * Create many new vertexs in the currently loaded editable map. * * @param num Number of vertexes to be created. * @param values Ptr to an array containing the coordinates for the * vertexs to create [v0 X, vo Y, v1 X, v1 Y...] * @param indices If not @c NULL, the indices of the newly created * vertexes will be written back here. */ boolean MPE_VertexCreatev(size_t num, float* values, uint* indices) { uint n; if(!editMapInited || !num || !values) return false; // Create many vertexes. for(n = 0; n < num; ++n) { vertex_t* v; v = createVertex(); v->V_pos[VX] = values[n * 2]; v->V_pos[VY] = values[n * 2 + 1]; v->buildData.pos[VX] = (double) v->V_pos[VX]; v->buildData.pos[VY] = (double) v->V_pos[VY]; if(indices) indices[n] = v->buildData.index; } return true; } uint MPE_SidedefCreate(uint sector, short flags, materialnum_t topMaterial, float topOffsetX, float topOffsetY, float topRed, float topGreen, float topBlue, materialnum_t middleMaterial, float middleOffsetX, float middleOffsetY, float middleRed, float middleGreen, float middleBlue, float middleAlpha, materialnum_t bottomMaterial, float bottomOffsetX, float bottomOffsetY, float bottomRed, float bottomGreen, float bottomBlue) { sidedef_t* s; if(!editMapInited) return 0; if(sector > map->numSectors) return 0; s = createSide(); s->flags = flags; s->sector = (sector == 0? NULL: map->sectors[sector-1]); Surface_SetMaterial(&s->SW_topsurface, P_ToMaterial(topMaterial)); Surface_SetMaterialOffsetXY(&s->SW_topsurface, topOffsetX, topOffsetY); Surface_SetColorRGBA(&s->SW_topsurface, topRed, topGreen, topBlue, 1); Surface_SetMaterial(&s->SW_middlesurface, P_ToMaterial(middleMaterial)); Surface_SetMaterialOffsetXY(&s->SW_middlesurface, middleOffsetX, middleOffsetY); Surface_SetColorRGBA(&s->SW_middlesurface, middleRed, middleGreen, middleBlue, middleAlpha); Surface_SetMaterial(&s->SW_bottomsurface, P_ToMaterial(bottomMaterial)); Surface_SetMaterialOffsetXY(&s->SW_bottomsurface, bottomOffsetX, bottomOffsetY); Surface_SetColorRGBA(&s->SW_bottomsurface, bottomRed, bottomGreen, bottomBlue, 1); return s->buildData.index; } /** * Create a new linedef in the editable map. * * @param v1 Idx of the start vertex. * @param v2 Idx of the end vertex. * @param frontSide Idx of the front sidedef. * @param backSide Idx of the back sidedef. * @param flags Currently unused. * * @return Idx of the newly created linedef else @c 0 if there * was an error. */ uint MPE_LinedefCreate(uint v1, uint v2, uint frontSide, uint backSide, int flags) { linedef_t* l; sidedef_t* front = NULL, *back = NULL; vertex_t* vtx1, *vtx2; float length, dx, dy; if(!editMapInited) return 0; if(frontSide > map->numSideDefs) return 0; if(backSide > map->numSideDefs) return 0; if(v1 == 0 || v1 > map->numVertexes) return 0; if(v2 == 0 || v2 > map->numVertexes) return 0; if(v1 == v2) return 0; // First, ensure that the side indices are unique. if(frontSide && map->sideDefs[frontSide - 1]->buildData.refCount) return 0; // Already in use. if(backSide && map->sideDefs[backSide - 1]->buildData.refCount) return 0; // Already in use. // Next, check the length is not zero. vtx1 = map->vertexes[v1 - 1]; vtx2 = map->vertexes[v2 - 1]; dx = vtx2->V_pos[VX] - vtx1->V_pos[VX]; dy = vtx2->V_pos[VY] - vtx1->V_pos[VY]; length = P_AccurateDistance(dx, dy); if(!(length > 0)) return 0; if(frontSide > 0) front = map->sideDefs[frontSide - 1]; if(backSide > 0) back = map->sideDefs[backSide - 1]; l = createLine(); l->L_v1 = vtx1; l->L_v2 = vtx2; l->L_v1->buildData.refCount++; l->L_v2->buildData.refCount++; l->dX = dx; l->dY = dy; l->length = length; l->angle = bamsAtan2((int) (l->L_v2pos[VY] - l->L_v1pos[VY]), (int) (l->L_v2pos[VX] - l->L_v1pos[VX])); if(l->dX == 0) l->slopeType = ST_VERTICAL; else if(l->dY == 0) l->slopeType = ST_HORIZONTAL; else { if(l->dY / l->dX > 0) l->slopeType = ST_POSITIVE; else l->slopeType = ST_NEGATIVE; } if(l->L_v1pos[VX] < l->L_v2pos[VX]) { l->bBox[BOXLEFT] = l->L_v1pos[VX]; l->bBox[BOXRIGHT] = l->L_v2pos[VX]; } else { l->bBox[BOXLEFT] = l->L_v2pos[VX]; l->bBox[BOXRIGHT] = l->L_v1pos[VX]; } if(l->L_v1pos[VY] < l->L_v2pos[VY]) { l->bBox[BOXBOTTOM] = l->L_v1pos[VY]; l->bBox[BOXTOP] = l->L_v2pos[VY]; } else { l->bBox[BOXBOTTOM] = l->L_v2pos[VY]; l->bBox[BOXTOP] = l->L_v1pos[VY]; } l->L_frontside = front; l->L_backside = back; // Remember the number of unique references. if(l->L_frontside) { l->L_frontside->line = l; l->L_frontside->buildData.refCount++; } if(l->L_backside) { l->L_backside->line = l; l->L_backside->buildData.refCount++; } l->inFlags = 0; // Determine the default linedef flags. l->flags = 0; if(!front || !back) l->flags |= DDLF_BLOCKING; return l->buildData.index; } uint MPE_PlaneCreate(uint sector, float height, materialnum_t material, float matOffsetX, float matOffsetY, float r, float g, float b, float a, float normalX, float normalY, float normalZ) { uint i; sector_t* s; plane_t** newList, *pln; if(!editMapInited) return 0; if(sector == 0 || sector > map->numSectors) return 0; s = map->sectors[sector - 1]; pln = M_Calloc(sizeof(plane_t)); pln->height = height; Surface_SetMaterial(&pln->surface, P_ToMaterial(material)); Surface_SetColorRGBA(&pln->surface, r, g, b, a); Surface_SetMaterialOffsetXY(&pln->surface, matOffsetX, matOffsetY); pln->PS_normal[VX] = normalX; pln->PS_normal[VY] = normalY; pln->PS_normal[VZ] = normalZ; if(pln->PS_normal[VZ] < 0) pln->type = PLN_CEILING; else pln->type = PLN_FLOOR; M_Normalize(pln->PS_normal); pln->sector = s; newList = M_Malloc(sizeof(plane_t*) * (++s->planeCount + 1)); for(i = 0; i < s->planeCount - 1; ++i) { newList[i] = s->planes[i]; } newList[i++] = pln; newList[i] = NULL; // Terminate. if(s->planes) M_Free(s->planes); s->planes = newList; return s->planeCount; // 1-based index. } uint MPE_SectorCreate(float lightlevel, float red, float green, float blue) { sector_t *s; if(!editMapInited) return 0; s = createSector(); s->rgb[CR] = MINMAX_OF(0, red, 1); s->rgb[CG] = MINMAX_OF(0, green, 1); s->rgb[CB] = MINMAX_OF(0, blue, 1); s->lightLevel = MINMAX_OF(0, lightlevel, 1); s->planeCount = 0; s->planes = NULL; return s->buildData.index; } uint MPE_PolyobjCreate(uint *lines, uint lineCount, int tag, int sequenceType, float anchorX, float anchorY) { uint i; polyobj_t *po; if(!editMapInited || !lineCount || !lines) return 0; // First check that all the line indices are valid and that they arn't // already part of another polyobj. for(i = 0; i < lineCount; ++i) { linedef_t *line; if(lines[i] == 0 || lines[i] > map->numLineDefs) return 0; line = map->lineDefs[lines[i] - 1]; if(line->inFlags & LF_POLYOBJ) return 0; } po = createPolyobj(); po->buildData.lineDefs = M_Calloc(sizeof(linedef_t*) * (lineCount+1)); for(i = 0; i < lineCount; ++i) { linedef_t *line = map->lineDefs[lines[i] - 1]; // This line is part of a polyobj. line->inFlags |= LF_POLYOBJ; po->buildData.lineDefs[i] = line; } po->buildData.lineDefs[i] = NULL; po->buildData.lineCount = lineCount; po->tag = tag; po->seqType = sequenceType; po->pos[VX] = anchorX; po->pos[VY] = anchorY; return po->buildData.index; } boolean MPE_GameObjProperty(const char *objName, uint idx, const char *propName, valuetype_t type, void *data) { uint i; size_t len; gamemapobjdef_t *def; if(!objName || !propName || !data) return false; // Hmm... // Is this a known object? if((def = P_GetGameMapObjDef(0, objName, false)) == NULL) return false; // Nope. // Is this a known property? len = strlen(propName); for(i = 0; i < def->numProps; ++i) { if(!strnicmp(propName, def->props[i].name, len)) { // Found a match! // Create a record of this so that the game can query it later. P_AddGameMapObjValue(&map->gameObjData, def, i, idx, type, data); return true; // We're done. } } // An unknown property. VERBOSE(Con_Message("MPE_GameObjProperty: %s has no property \"%s\".\n", def->name, propName)); return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/ui_mpi.c0000644000175000017500000005065211357170242022367 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * ui_mpi.c: Multiplayer Setup Interface */ // HEADER FILES ------------------------------------------------------------ #include #include #include "de_base.h" #include "de_system.h" #include "de_network.h" #include "de_console.h" #include "de_ui.h" // MACROS ------------------------------------------------------------------ #define MAX_FOUND 32 #define NUMITEMS(x) (sizeof(x)/sizeof(uidata_listitem_t)) #define UIF_SERVER_LIST UIF_ID0 #define UIG_CONNECT 6 // TYPES ------------------------------------------------------------------- typedef enum searchmode_e { SEARCH_MASTER, SEARCH_CUSTOM } searchmode_t; typedef struct serverstrings_s { char desc[90]; char version[20]; char ping[20]; char game[80]; char names[256]; char pwads[256]; char warning[128]; } serverstrings_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void MPIGotoPage(ui_object_t *ob); void MPIGoBack(ui_object_t *ob); void MPIChooseMode(ui_object_t *ob); void MPIToggleMasterItems(ui_object_t *ob); void MPIStartServer(ui_object_t *ob); void MPIShowProtocolSettings(ui_object_t *ob); void MPISetupProtocol(ui_object_t *ob); void MPISearch(ui_object_t *ob); void MPIRetrieve(ui_object_t *ob); void MPIUpdateServerList(void); void MPIUpdateFound(ui_object_t *ob); void MPIConnect(ui_object_t *ob); void MPIHelpDrawer(ui_object_t *ob); void MPIUpdateServerInfo(ui_object_t *ob); void MPIServerInfoDrawer(ui_object_t *ob); void MPIUpdatePublicButton(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- char str_server[101]; char str_desc[201]; char str_masterip[128]; char str_ipaddr[128]; char str_ipport[128]; char str_myudp[51]; serverstrings_t str_sinfo; uidata_slider_t sld_player_limit = { 0, 16, 0, 1, false, "server-player-limit" }; uidata_listitem_t lstit_found[MAX_FOUND]; static boolean mode_buttons[2] = { true, false }; static uidata_edit_t ed_server = { str_server, 100 }; static uidata_edit_t ed_desc = { str_desc, 200 }; static uidata_edit_t ed_masterip = { str_masterip, 127 }; static uidata_list_t lst_found = { lstit_found, 0 }; static uidata_edit_t ed_ipsearch = { str_ipaddr, 127 }; static uidata_edit_t ed_portsearch = { str_ipport, 127 }; static uidata_edit_t ed_myudp = { str_myudp, 50 }; static ui_page_t page_server, page_client; static ui_object_t ob_server[] = { // Server setup {UI_TEXT, 0, 0, 50, 200, 0, 70, "Server name", UIText_Drawer}, {UI_EDIT, 0, 0, 320, 200, 500, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_server}, {UI_TEXT, 0, 0, 50, 300, 0, 70, "Description", UIText_Drawer}, {UI_EDIT, 0, 0, 320, 300, 580, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_desc}, {UI_TEXT, 0, 0, 50, 400, 0, 70, "Max. players", UIText_Drawer}, {UI_SLIDER, 0, 0, 320, 405, 350, 60, "", UISlider_Drawer, UISlider_Responder, UISlider_Ticker, CP_CvarSlider, &sld_player_limit}, {UI_TEXT, 0, 0, 50, 600, 0, 70, "Register on master?", UIText_Drawer}, {UI_BUTTON2, 2, 0, 320, 600, 100, 70, "Yes", UIButton_Drawer, UIButton_Responder, 0, MPIToggleMasterItems, &masterAware}, {UI_TEXT, 1, 0, 50, 700, 0, 70, "Master TCP/IP address", UIText_Drawer}, {UI_EDIT, 1, 0, 320, 700, 350, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_masterip}, /* The port settings and "Start" button */ {UI_BOX, 0, 0, 0, 910, 1000, 90, "", UIFrame_Drawer}, {UI_TEXT, 0, 0, 20, 920, 0, 70, "Incoming TCP port", UIText_Drawer}, {UI_EDIT, 0, 0, 230, 920, 110, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_portsearch}, {UI_TEXT, 0, 0, 420, 920, 0, 70, "In/out UDP port", UIText_Drawer}, {UI_EDIT, 0, 0, 600, 920, 110, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_myudp}, {UI_BUTTON, 0, UIF_DEFAULT, 800, 920, 180, 70, "Start", UIButton_Drawer, UIButton_Responder, 0, MPIStartServer}, {UI_NONE} }; static ui_object_t ob_client[] = { {UI_TEXT, 0, 0, 0, 0, 0, 70, "Get servers from:", UIText_Drawer}, {UI_BUTTON2, 1, UIF_ACTIVE, 200, 0, 180, 70, "Master Server", UIButton_Drawer, UIButton_Responder, 0, MPIChooseMode, &mode_buttons[0]}, {UI_BUTTON2, 2, 0, 390, 0, 180, 70, "Custom Search", UIButton_Drawer, UIButton_Responder, 0, MPIChooseMode, &mode_buttons[1]}, {UI_BOX, 0, 0, 0, 80, 1000, 90, "", UIFrame_Drawer}, /* Search Parameters: Master Server */ {UI_TEXT, 3, 0, 20, 90, 0, 70, "Master server's address", UIText_Drawer}, {UI_EDIT, 3, 0, 290, 90, 500, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_masterip}, /* Search Parameters: Custom Search */ {UI_TEXT, 4, 0, 20, 90, 0, 70, "Query address (IP or hostname)", UIText_Drawer}, {UI_EDIT, 4, 0, 360, 90, 290, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_ipsearch}, {UI_TEXT, 4, 0, 680, 90, 0, 70, "Server's TCP port", UIText_Drawer}, {UI_EDIT, 4, 0, 870, 90, 110, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_portsearch}, {UI_BUTTON, 0, UIF_DEFAULT, 0, 180, 180, 70, "Update", UIButton_Drawer, UIButton_Responder, 0, MPISearch}, /* The List of Servers */ {UI_LIST, 0, UIF_SERVER_LIST, 190, 180, 810, 300, "", UIList_Drawer, UIList_Responder, MPIUpdateFound, MPIUpdateServerInfo, &lst_found}, {UI_TEXT, 0, 0, 20, 490, 0, 70, "Description", UIText_Drawer}, {UI_TEXT, 0, 0, 190, 490, 570, 70, "", MPIServerInfoDrawer, 0, 0, 0, str_sinfo.desc}, {UI_TEXT, 0, 0, 20, 570, 0, 70, "Game", UIText_Drawer}, {UI_TEXT, 0, 0, 190, 570, 250, 70, "", MPIServerInfoDrawer, 0, 0, 0, str_sinfo.game}, {UI_TEXT, 0, 0, 460, 570, 0, 70, "Version", UIText_Drawer}, {UI_TEXT, 0, 0, 560, 570, 200, 70, "", MPIServerInfoDrawer, 0, 0, 0, str_sinfo.version}, {UI_TEXT, 0, 0, 20, 650, 0, 70, "Setup", UIText_Drawer}, {UI_TEXT, 0, 0, 190, 650, 570, 120, "", MPIServerInfoDrawer, 0, 0, 0, str_sinfo.pwads}, {UI_TEXT, 0, 0, 20, 780, 0, 70, "Players", UIText_Drawer}, {UI_TEXT, 0, 0, 190, 780, 570, 120, "", MPIServerInfoDrawer, 0, 0, 0, str_sinfo.names}, {UI_TEXT, 5, UIF_DISABLED, 770, 490, 0, 70, "Warnings", UIText_Drawer}, {UI_TEXT, 5, UIF_DISABLED, 770, 560, 230, 340, "", MPIServerInfoDrawer, 0, 0, 0, str_sinfo.warning}, //{UI_TEXT, 0, 0, 20, 870, 0, 70, "Ping", UIText_Drawer}, //{UI_TEXT, 0, 0, 190, 870, 200, 70, "", MPIServerInfoDrawer, 0, 0, 0, // str_sinfo.ping}, {UI_BOX, 0, 0, 0, 910, 1000, 90, "", UIFrame_Drawer}, {UI_TEXT, 0, 0, 20, 920, 0, 70, "My UDP port", UIText_Drawer}, {UI_EDIT, 0, 0, 170, 920, 110, 70, "", UIEdit_Drawer, UIEdit_Responder, 0, 0, &ed_myudp}, {UI_TEXT, 0, 0, 290, 920, 0, 70, "(must be open for incoming and outgoing traffic)", UIText_Drawer}, {UI_BUTTON, UIG_CONNECT, 0, 800, 920, 180, 70, "Connect", UIButton_Drawer, UIButton_Responder, 0, MPIConnect}, {UI_NONE} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static searchmode_t searchMode = SEARCH_MASTER; static boolean lookedForHosts = false; static boolean retrieving = false; static unsigned int myCrc = 0; static char warningString[256]; // CODE -------------------------------------------------------------------- /* * Change the search mode. */ void MPIChooseMode(ui_object_t *ob) { int i; memset(mode_buttons, 0, sizeof(mode_buttons)); UI_FlagGroup(ob_client, 1, UIF_ACTIVE, UIFG_CLEAR); UI_FlagGroup(ob_client, 2, UIF_ACTIVE, UIFG_CLEAR); *(boolean *) ob->data = true; ob->flags |= UIF_ACTIVE; // Hide/show the option controls. for(i = 1; i <= 2; i++) UI_FlagGroup(ob_client, i + 2, UIF_HIDDEN, !mode_buttons[i - 1]); // Update the search mode. searchMode = (mode_buttons[0] ? SEARCH_MASTER : SEARCH_CUSTOM); // Update the list of found hosts. MPIUpdateServerList(); } /* * Clear all the strings that display information about currently * selected server. */ void MPIClearServerInfo(void) { memset(&str_sinfo, 0, sizeof(str_sinfo)); } /* * Copies string from src to dest, replacing 'match' chars with 'rep'. */ void MPITranslateString(char *dest, const char *src, char match, const char *rep) { char *dp = dest; const char *sp = src; for(; *sp; sp++) if(*sp == match) { strcpy(dp, rep); dp += strlen(rep); } else { *dp++ = *sp; } *dp = 0; } /* * Update the strings that display information about currently selected * server. This is called when the server selection changes in the list. */ void MPIUpdateServerInfo(ui_object_t *ob) { serverinfo_t info; char str[256]; int success; // If nothing is currently selected, clear the info fields. if(lst_found.selection < 0) { MPIClearServerInfo(); return; } if(retrieving) return; success = (searchMode == SEARCH_MASTER ? N_MasterGet(lstit_found[lst_found.selection].data2, &info) : N_GetHostInfo(lstit_found[lst_found.selection].data2, &info)); if(!success) { MPIClearServerInfo(); return; } strcpy(str_sinfo.desc, info.description); sprintf(str_sinfo.version, "%i", info.version); // if(info.ping) // sprintf(str_sinfo.ping, "%i ms", info.ping); // else // strcpy(str_sinfo.ping, "?"); strcpy(str_sinfo.game, info.game); MPITranslateString(str_sinfo.names, info.clientNames, ';', ", "); MPITranslateString(str, info.pwads, ';', ", "); strcpy(str_sinfo.pwads, info.gameMode); if(info.gameConfig[0]) { strcat(str_sinfo.pwads, " "); strcat(str_sinfo.pwads, info.gameConfig); } if(info.pwads[0]) { strcat(str_sinfo.pwads, " ("); strcat(str_sinfo.pwads, str); strcat(str_sinfo.pwads, ")"); } W_GetIWADFileName(str, sizeof(str)); sprintf(warningString, "This server is using %s (%x), " "but you have %s (%x). " "Errors may occur during game play.", info.iwad, info.wadNumber, str, myCrc); // Show IWAD warning? if(! (lst_found.count >= 1 && lst_found.selection >= 0 && lstit_found[lst_found.selection].data != -1 && lstit_found[lst_found.selection].data != (int) myCrc)) { UI_FlagGroup(ob_client, 5, UIF_DISABLED, true); strcpy(str_sinfo.warning, ""); } else { UI_FlagGroup(ob_client, 5, UIF_DISABLED, false); strcpy(str_sinfo.warning, warningString); } } /* * Draw a framed text box. */ void MPIServerInfoDrawer(ui_object_t *ob) { UI_DrawHelpBox(ob->x, ob->y, ob->w, ob->h, ob->flags & UIF_DISABLED ? .2f : 1, ob->data); } void MPIToggleMasterItems(ui_object_t *ob) { UI_FlagGroup(page_server.objects, 1, UIF_DISABLED, UIFG_XOR); MPIUpdatePublicButton(); } void MPIGotoPage(ui_object_t *ob) { UI_SetPage((ui_page_t *) ob->data); } void MPIGoBack(ui_object_t *ob) { if(!UI_CurrentPage()->previous) UI_End(); else UI_SetPage(UI_CurrentPage()->previous); } void MPIStartServer(ui_object_t *ob) { N_ShutdownService(); Con_SetInteger("net-port-control", strtol(str_ipport, 0, 0), true); Con_SetInteger("net-port-data", strtol(str_myudp, 0, 0), true); N_InitService(true); // Update the variables. Con_SetString("server-name", str_server, true); Con_SetString("server-info", str_desc, true); Con_SetString("net-master-address", str_masterip, true); // Start the server. Con_Execute(CMDS_DDAY,"net server start", false, false); UI_End(); } void MPISearch(ui_object_t *ob) { if(retrieving) return; // Network services are naturally needed for searching. if(!N_IsAvailable()) N_InitService(false); if(searchMode == SEARCH_CUSTOM) { // This is a synchronous operation. N_LookForHosts(str_ipaddr, strtol(str_ipport, 0, 0)); lookedForHosts = true; MPIUpdateServerList(); } else { // Get servers from the master. MPIRetrieve(ob); } } /* * Formats the given serverinfo_t into a list-viewable tabbed string. */ void MPIFormatServerInfo(char *dest, serverinfo_t *info) { sprintf(dest, "%s\t%i / %i players\t%s\t%s", info->name, info->numPlayers, info->maxPlayers, info->map, info->iwad); } /* * Fill the server list with the list of currently known servers. */ void MPIUpdateServerList(void) { int num, i, k; serverinfo_t info; ui_object_t *listObject = UI_FindObject(ob_client, 0, UIF_SERVER_LIST); if(searchMode == SEARCH_CUSTOM) { num = N_GetHostCount(); if(!num) { lst_found.selection = -1; if(lookedForHosts) { lst_found.count = 1; lstit_found[0].data = -1; sprintf(lstit_found[0].text, "(No response from %s)", str_ipaddr); } else { lst_found.count = 0; } UI_FlagGroup(ob_client, UIG_CONNECT, UIF_DISABLED, true); } else { if(num > MAX_FOUND) num = MAX_FOUND; for(i = 0; i < num; i++) { memset(&info, 0, sizeof(info)); N_GetHostInfo(i, &info); MPIFormatServerInfo(lstit_found[i].text, &info); lstit_found[i].data = info.wadNumber; lstit_found[i].data2 = i; } lst_found.count = num; lst_found.selection = 0; UI_FlagGroup(ob_client, UIG_CONNECT, UIF_DISABLED, false); } } else if(searchMode == SEARCH_MASTER) { num = N_MasterGet(0, 0); for(i = 0, k = 0; i < num && k < MAX_FOUND; i++) { N_MasterGet(i, &info); // Is this suitable? if(info.version != DOOMSDAY_VERSION || stricmp(info.gameMode, gx.GetVariable(DD_GAME_MODE)) || !info.canJoin) { Con_Message("Server %s filtered out:\n", info.name); Con_Message(" remote = %i, local = %i\n", info.version, DOOMSDAY_VERSION); Con_Message(" remote = %s, local = %s\n", info.gameMode, (char *) gx.GetVariable(DD_GAME_MODE)); Con_Message(" can join = %i\n", info.canJoin); continue; } MPIFormatServerInfo(lstit_found[k].text, &info); lstit_found[k].data = info.wadNumber; // Connection will be formed using this index. lstit_found[k].data2 = i; k++; } lst_found.count = k; UI_FlagGroup(ob_client, UIG_CONNECT, UIF_DISABLED, !k); } // Make sure the current selection isn't past the end of the list. if(lst_found.selection >= lst_found.count) lst_found.selection = -1; UI_InitColumns(listObject); MPIUpdateServerInfo(NULL); } /* * "Located Servers" list ticker. */ void MPIUpdateFound(ui_object_t *ob) { // Call list ticker. UIList_Ticker(ob); if(retrieving && N_MADone()) { // The list has been retrieved. retrieving = false; if(searchMode == SEARCH_MASTER) { MPIUpdateServerList(); } } } void MPIRetrieve(ui_object_t *ob) { ui_object_t *list = UI_FindObject(ob_client, 0, UIF_SERVER_LIST); if(retrieving) return; // Already retrieving! retrieving = true; // Disable Connect button. UI_FlagGroup(ob_client, UIG_CONNECT, UIF_DISABLED, true); MPIClearServerInfo(); lst_found.selection = -1; lst_found.count = 1; strcpy(lstit_found[0].text, "(Retrieving servers from master...)"); lstit_found[0].data = -1; UI_InitColumns(list); // Update master settings. Con_SetString("net-master-address", str_masterip, true); // Get the list. N_MAPost(MAC_REQUEST); N_MAPost(MAC_WAIT); } void MPIConnect(ui_object_t *ob) { char buf[80]; N_ShutdownService(); // Update my UDP port. Con_SetInteger("net-port-data", strtol(str_myudp, 0, 0), true); N_InitService(false); sprintf(buf, "net %sconnect %i", searchMode == SEARCH_MASTER ? "m" : "", lstit_found[lst_found.selection].data2); if(Con_Execute(CMDS_DDAY,buf, false, false)) { // Success. UI_End(); } } /* * Draw the per-page information about the currently displayed protocol. * The text is retrieved from the Help strings. */ #if 0 void MPIHelpDrawer(ui_object_t *ob) { int yPos[4] = { 250, 80, 530, 900 }; int selection = lst_protocol.selection; static int lastSelection = -1; static void *help = NULL; char *text; // Has the page changed? if(lastSelection != selection) { // Retrieve new help text. lastSelection = selection; help = DH_Find(lstit_protocols[selection].text); } if((text = DH_GetString(help, HST_DESCRIPTION)) != NULL) { UI_TextOutWrap(text, ob->x, UI_ScreenY(yPos[selection]), ob->w, UI_ScreenH(980 - yPos[selection])); } } #endif void MPIUpdatePublicButton(void) { strcpy(UI_FindObject(ob_server, 2, 0)->text, masterAware ? "Yes" : "No"); } /* * The GUI interface for setting up a server/client. */ void DD_NetSetup(int serverMode) { lookedForHosts = false; if(serverMode) { // Prepare Server Setup. UI_InitPage(&page_server, ob_server); sprintf(page_server.title, "Doomsday %s Server Setup", DOOMSDAY_VERSION_TEXT); strcpy(str_server, serverName); strcpy(str_desc, serverInfo); // Disable the Master Address and Port edit boxes. UI_FlagGroup(ob_server, 1, UIF_DISABLED, !masterAware); MPIUpdatePublicButton(); } else { // Prepare Client Setup. UI_InitPage(&page_client, ob_client); sprintf(page_client.title, "Doomsday %s Client Setup", DOOMSDAY_VERSION_TEXT); strcpy(str_ipaddr, nptIPAddress); UI_FlagGroup(ob_client, 1, UIF_ACTIVE, searchMode == SEARCH_MASTER); UI_FlagGroup(ob_client, 2, UIF_ACTIVE, searchMode != SEARCH_MASTER); UI_FlagGroup(ob_client, 3, UIF_HIDDEN, searchMode != SEARCH_MASTER); UI_FlagGroup(ob_client, 4, UIF_HIDDEN, searchMode == SEARCH_MASTER); lst_found.selection = -1; lst_found.count = 0; myCrc = W_CRCNumber(); UI_FlagGroup(ob_client, 5, UIF_DISABLED, true); // warnings UI_FlagGroup(ob_client, UIG_CONNECT, UIF_DISABLED, true); MPIUpdateServerList(); } sprintf(str_ipport, "%i", (nptIPPort ? nptIPPort : DEFAULT_TCP_PORT)); sprintf(str_myudp, "%i", (nptUDPPort ? nptUDPPort : DEFAULT_UDP_PORT)); strcpy(str_masterip, masterAddress); // Prepare Protocol Setup. //UI_InitPage(&page_protocol, ob_protocol); //strcpy(page_protocol.title, "Network Setup"); //page_protocol.previous = server_mode ? &page_server : &page_client; //sprintf(str_ipport, "%.10i", nptIPPort); //lst_protocol.selection = nptActive; UI_Init(true, true, false, false, false); UI_SetPage(serverMode ? &page_server : &page_client); CP_InitCvarSliders(ob_server); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_zone.c0000644000175000017500000006247411357170242022534 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 1999-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * Memory Zone * * There is never any space between memblocks, and there will never be * two contiguous free memblocks. * * The rover can be left pointing at a non-empty block. * * It is of no value to free a cachable block, because it will get * overwritten automatically if needed. * * The zone is composed of multiple memory volumes. * * When fast malloc mode is enabled, memory volumes aren't checked for purgable * blocks. If the rover block isn't suitable, a new empty volume is created * without further checking. This is suitable for cases where lots of blocks * are being allocated in a rapid sequence, with no frees in between (e.g., * map setup). * * Block sequences. The PU_MAPSTATIC purge tag has a special purpose. * It works like PU_MAP so that it is purged on a per map basis, but * blocks allocated as PU_MAPSTATIC should not be freed at any time when the * map is being used. Internally, the map-static blocks are linked into * sequences so that Z_Malloc knows to skip all of them efficiently. This is * possible because no block inside the sequence could be purged by Z_Malloc * anyway. */ // HEADER FILES ------------------------------------------------------------ #include #include // Define NDEBUG in release builds. #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // Size of one memory zone volume. #define MEMORY_VOLUME_SIZE 0x2000000 // 32 Mb #define ZONEID 0x1d4a11 #define MINFRAGMENT (sizeof(memblock_t)+32) // TYPES ------------------------------------------------------------------- /** * The memory is composed of multiple volumes. New volumes are * allocated when necessary. */ typedef struct memvolume_s { memzone_t *zone; size_t size; struct memvolume_s *next; } memvolume_t; // Used for block allocation of memory from the zone. typedef struct zblock_s { unsigned int max; // maximum number of elements unsigned int count; // number of used elements size_t elementSize; // size of a single element void* elements; // block of memory where elements are } zblock_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static memvolume_t *volumeRoot; /** * If false, Z_Malloc will free purgable blocks and aggressively look for * free memory blocks inside each memory volume before creating new volumes. * This leads to slower mallocing performance, but reduces memory fragmentation * as free and purgable blocks are utilized within the volumes. Fast mode is * enabled during map setup because a large number of mallocs will occur * during setup. */ static boolean fastMalloc = false; // CODE -------------------------------------------------------------------- /** * Conversion from string to long, with the "k" and "m" suffixes. */ long superatol(char *s) { char *endptr; long val = strtol(s, &endptr, 0); if(*endptr == 'k' || *endptr == 'K') val *= 1024; else if(*endptr == 'm' || *endptr == 'M') val *= 1048576; return val; } /** * Enables or disables fast malloc mode. Enable for added performance during * map setup. Disable fast mode during other times to save memory and reduce * fragmentation. * * @param isEnabled true or false. */ void Z_EnableFastMalloc(boolean isEnabled) { fastMalloc = isEnabled; } /** * Create a new memory volume. The new volume is added to the list of * memory volumes. */ memvolume_t *Z_Create(size_t volumeSize) { memblock_t *block; memvolume_t *vol = M_Calloc(sizeof(memvolume_t)); vol->next = volumeRoot; volumeRoot = vol; vol->size = volumeSize; // Allocate memory for the zone volume. vol->zone = M_Malloc(vol->size); // Clear the start of the zone. memset(vol->zone, 0, sizeof(memzone_t) + sizeof(memblock_t)); vol->zone->size = vol->size; // Set the entire zone to one free block. vol->zone->blockList.next = vol->zone->blockList.prev = block = (memblock_t *) ((byte *) vol->zone + sizeof(memzone_t)); vol->zone->blockList.user = (void *) vol->zone; vol->zone->blockList.volume = vol; vol->zone->blockList.tag = PU_STATIC; vol->zone->rover = block; block->prev = block->next = &vol->zone->blockList; block->user = NULL; // free block block->seqFirst = block->seqLast = NULL; block->size = vol->zone->size - sizeof(memzone_t); Con_Message("Z_Create: New %.1f MB memory volume.\n", vol->size / 1024.0 / 1024.0); return vol; } /** * Initialize the memory zone. */ int Z_Init(void) { // Create the first volume. Z_Create(MEMORY_VOLUME_SIZE); return true; } /** * Shut down the memory zone by destroying all the volumes. */ void Z_Shutdown(void) { int numVolumes = 0; size_t totalMemory = 0; // Destroy all the memory volumes. while(volumeRoot) { memvolume_t *vol = volumeRoot; volumeRoot = vol->next; // Calculate stats. numVolumes++; totalMemory += vol->size; #ifdef FAKE_MEMORY_ZONE Z_FreeTags(0, DDMAXINT); #endif M_Free(vol->zone); M_Free(vol); } printf("Z_Shutdown: Used %i volumes, total %lu bytes.\n", numVolumes, (long unsigned int) totalMemory); } #ifdef FAKE_MEMORY_ZONE memblock_t *Z_GetBlock(void *ptr) { memvolume_t *volume; memblock_t *block; for(volume = volumeRoot; volume; volume = volume->next) { for(block = volume->zone->blockList.next; block != &volume->zone->blockList; block = block->next) { if(block->area == ptr) { return block; } } } Con_Error("Z_GetBlock: There is no memory block for %p.\n", ptr); return NULL; } #endif /** * Free memory that was allocated with Z_Malloc. */ void Z_Free(void *ptr) { memblock_t *block, *other; memvolume_t *volume; if(!ptr) { VERBOSE(Con_Message("Z_Free: Warning: Attempt to free NULL ignored.\n") ); return; } block = Z_GetBlock(ptr); if(block->id != ZONEID) { Con_Error("Z_Free: Attempt to free pointer without ZONEID."); } // The block was allocated from this volume. volume = block->volume; if(block->user > (void **) 0x100) // Smaller values are not pointers. *block->user = 0; // Clear the user's mark. block->user = NULL; // Mark as free. block->tag = 0; block->volume = NULL; block->id = 0; #ifdef FAKE_MEMORY_ZONE M_Free(block->area); block->area = NULL; #endif /** * Erase the entire sequence, if there is one. * It would also be possible to carefully break the sequence in two * parts, but since PU_LEVELSTATICs aren't supposed to be freed one by * one, this this sufficient. */ if(block->seqFirst) { memblock_t* first = block->seqFirst; memblock_t* iter = first; while(iter->seqFirst == first) { iter->seqFirst = iter->seqLast = NULL; iter = iter->next; } } other = block->prev; if(!other->user) { // Merge with previous free block. other->size += block->size; other->next = block->next; other->next->prev = other; if(block == volume->zone->rover) volume->zone->rover = other; block = other; } other = block->next; if(!other->user) { // Merge the next free block onto the end. block->size += other->size; block->next = other->next; block->next->prev = block; if(other == volume->zone->rover) volume->zone->rover = block; } } /** * You can pass a NULL user if the tag is < PU_PURGELEVEL. */ void *Z_Malloc(size_t size, int tag, void *user) { size_t extra; memblock_t *start, *rover, *new, *base; memvolume_t *volume; boolean gotoNextVolume; if(tag < PU_STATIC || tag > PU_CACHE) { Con_Error("Z_Malloc: Invalid purgelevel %i.", tag); } if(!size) { // You can't allocate "nothing." return NULL; } // Account for size of block header. size += sizeof(memblock_t); // Iterate through memory volumes until we can find one with // enough free memory. (Note: we *will* find one that's large // enough.) for(volume = volumeRoot; ; volume = volume->next) { if(volume == NULL) { // We've run out of volumes. Let's allocate a new one // with enough memory. size_t newVolumeSize = MEMORY_VOLUME_SIZE; if(newVolumeSize < size + 0x1000) newVolumeSize = size + 0x1000; // with some spare memory volume = Z_Create(newVolumeSize); } if(!volume->zone) { Con_Error("Z_Malloc: Volume without zone."); } // Scan through the block list looking for the first free block of // sufficient size, throwing out any purgable blocks along the // way. // If there is a free block behind the rover, back up over them. base = volume->zone->rover; assert(base->prev); if(!base->prev->user) base = base->prev; gotoNextVolume = false; if(fastMalloc) { // In fast malloc mode, if the rover block isn't large enough, // just give up and move to the next volume right away. if(base->user || base->size < size) { gotoNextVolume = true; } } if(!gotoNextVolume) { boolean isDone; rover = base; start = base->prev; // If the start is in a sequence, move it to the beginning of the // entire sequence. Sequences are handled as a single unpurgable entity, // so we can stop checking at its start. if(start->seqFirst) { start = start->seqFirst; } isDone = false; do { if(rover != start) { if(rover->user) { if(rover->tag < PU_PURGELEVEL) { if(rover->seqFirst) { // This block is part of a sequence of blocks, none of // which can be purged. Skip the entire sequence. base = rover = rover->seqFirst->seqLast->next; } else { // Hit a block that can't be purged, so move base // past it. base = rover = rover->next; } } else { // Free the rover block (adding the size to base). base = base->prev; // the rover can be the base block #ifdef FAKE_MEMORY_ZONE Z_Free(rover->area); #else Z_Free((byte *) rover + sizeof(memblock_t)); #endif base = base->next; rover = base->next; } } else { rover = rover->next; } } else { // Scanned all the way around the list. // Move over to the next volume. gotoNextVolume = true; } // Have we finished? if(gotoNextVolume) isDone = true; else isDone = !(base->user || base->size < size); } while(!isDone); // At this point we've found/created a big enough block or we are // skipping this volume entirely. if(!gotoNextVolume) { // Found a block big enough. extra = base->size - size; if(extra > MINFRAGMENT) { // There will be a free fragment after the allocated // block. new = (memblock_t *) ((byte *) base + size); new->size = extra; new->user = NULL; // free block new->tag = 0; new->volume = NULL; new->prev = base; new->next = base->next; new->next->prev = new; new->seqFirst = new->seqLast = NULL; base->next = new; base->size = size; } #ifdef FAKE_MEMORY_ZONE base->area = M_Malloc(size - sizeof(memblock_t)); #endif if(user) { base->user = user; // mark as an in use block #ifdef FAKE_MEMORY_ZONE *(void **) user = base->area; #else *(void **) user = (void *) ((byte *) base + sizeof(memblock_t)); #endif } else { if(tag >= PU_PURGELEVEL) Con_Error("Z_Malloc: an owner is required for " "purgable blocks.\n"); base->user = (void *) 2; // mark as in use, but unowned } base->tag = tag; if(tag == PU_MAPSTATIC) { // Level-statics are linked into unpurgable sequences so they can // be skipped en masse. base->seqFirst = base; base->seqLast = base; if(base->prev->seqFirst) { base->seqFirst = base->prev->seqFirst; base->seqFirst->seqLast = base; } } else { // Not part of a sequence. base->seqLast = base->seqFirst = NULL; } // next allocation will start looking here volume->zone->rover = base->next; base->volume = volume; base->id = ZONEID; #ifdef FAKE_MEMORY_ZONE return base->area; #else return (void *) ((byte *) base + sizeof(memblock_t)); #endif } } // Move to the next volume. } } /** * Only resizes blocks with no user. If a block with a user is * reallocated, the user will lose its current block and be set to * NULL. Does not change the tag of existing blocks. */ void *Z_Realloc(void *ptr, size_t n, int mallocTag) { int tag = ptr ? Z_GetTag(ptr) : mallocTag; void *p = Z_Malloc(n, tag, 0); // User always 0 if(ptr) { size_t bsize; // Has old data; copy it. memblock_t *block = Z_GetBlock(ptr); bsize = block->size - sizeof(memblock_t); memcpy(p, ptr, MIN_OF(n, bsize)); Z_Free(ptr); } return p; } /** * Free memory blocks in all volumes with a tag in the specified range. */ void Z_FreeTags(int lowTag, int highTag) { memvolume_t *volume; memblock_t *block, *next; for(volume = volumeRoot; volume; volume = volume->next) { for(block = volume->zone->blockList.next; block != &volume->zone->blockList; block = next) { next = block->next; // Get link before freeing. if(block->user) { if(block->tag >= lowTag && block->tag <= highTag) #ifdef FAKE_MEMORY_ZONE Z_Free(block->area); #else Z_Free((byte *) block + sizeof(memblock_t)); #endif } } } } /** * Check all zone volumes for consistency. */ void Z_CheckHeap(void) { memvolume_t *volume; memblock_t *block; boolean isDone; #ifdef _DEBUG VERBOSE2( Con_Message("Z_CheckHeap\n") ); #endif for(volume = volumeRoot; volume; volume = volume->next) { block = volume->zone->blockList.next; isDone = false; while(!isDone) { if(block->next != &volume->zone->blockList) { if(block->size == 0) Con_Error("Z_CheckHeap: zero-size block\n"); if((byte *) block + block->size != (byte *) block->next) Con_Error("Z_CheckHeap: block size does not touch the " "next block\n"); if(block->next->prev != block) Con_Error("Z_CheckHeap: next block doesn't have proper " "back link\n"); if(!block->user && !block->next->user) Con_Error("Z_CheckHeap: two consecutive free blocks\n"); if(block->user == (void **) -1) Con_Error("Z_CheckHeap: bad user pointer %p\n", block->user); /* if(block->seqFirst == block) { // This is the first. printf("sequence begins at (%p): start=%p, end=%p\n", block, block->seqFirst, block->seqLast); } */ if(block->seqFirst) { //printf(" seq member (%p): start=%p\n", block, block->seqFirst); if(block->seqFirst->seqLast == block) { //printf(" -=- last member of seq %p -=-\n", block->seqFirst); } else { if(block->next->seqFirst != block->seqFirst) { Con_Error("Z_CheckHeap: disconnected sequence\n"); } } } block = block->next; } else isDone = true; // all blocks have been hit } } } /** * Change the tag of a memory block. */ void Z_ChangeTag2(void *ptr, int tag) { memblock_t *block = Z_GetBlock(ptr); if(block->id != ZONEID) Con_Error("Z_ChangeTag: Modifying a block without ZONEID."); if(tag >= PU_PURGELEVEL && (unsigned long) block->user < 0x100) Con_Error("Z_ChangeTag: An owner is required for purgable blocks."); block->tag = tag; } /** * Change the user of a memory block. */ void Z_ChangeUser(void *ptr, void *newUser) { memblock_t *block = Z_GetBlock(ptr); if(block->id != ZONEID) Con_Error("Z_ChangeUser: Block without ZONEID."); block->user = newUser; } /** * Get the user of a memory block. */ void *Z_GetUser(void *ptr) { memblock_t *block = Z_GetBlock(ptr); if(block->id != ZONEID) Con_Error("Z_GetUser: Block without ZONEID."); return block->user; } /** * Get the tag of a memory block. */ int Z_GetTag(void *ptr) { memblock_t *block = Z_GetBlock(ptr); if(block->id != ZONEID) Con_Error("Z_GetTag: Block without ZONEID."); return block->tag; } /** * Memory allocation utility: malloc and clear. */ void *Z_Calloc(size_t size, int tag, void *user) { void *ptr = Z_Malloc(size, tag, user); memset(ptr, 0, size); return ptr; } /** * Realloc and set possible new memory to zero. */ void *Z_Recalloc(void *ptr, size_t n, int callocTag) { memblock_t *block; void *p; size_t bsize; if(ptr) // Has old data. { p = Z_Malloc(n, Z_GetTag(ptr), NULL); block = Z_GetBlock(ptr); bsize = block->size - sizeof(memblock_t); if(bsize <= n) { memcpy(p, ptr, bsize); memset((char *) p + bsize, 0, n - bsize); } else { // New block is smaller. memcpy(p, ptr, n); } Z_Free(ptr); } else { // Totally new allocation. p = Z_Calloc(n, callocTag, NULL); } return p; } /** * Calculate the amount of unused memory in all volumes combined. */ size_t Z_FreeMemory(void) { memvolume_t *volume; memblock_t *block; size_t free = 0; Z_CheckHeap(); for(volume = volumeRoot; volume; volume = volume->next) { for(block = volume->zone->blockList.next; block != &volume->zone->blockList; block = block->next) { if(!block->user) { free += block->size; } } } return free; } /** * Allocate a new block of memory to be used for linear object allocations. * A "zblock" (its from the zone). * * @param zblockset_t* Block set into which the new block is added. */ static void Z_AddBlockToSet(zblockset_t *set) { zblock_t *block = 0; // Get a new block by resizing the blocks array. This is done relatively // seldom, since there is a large number of elements per each block. set->count++; set->blocks = Z_Recalloc(set->blocks, sizeof(zblock_t) * set->count, set->tag); // Initialize the block's data. block = &set->blocks[set->count - 1]; block->max = set->elementsPerBlock; block->elementSize = set->elementSize; block->elements = Z_Malloc(block->elementSize * block->max, set->tag, NULL); block->count = 0; } /** * Return a ptr to the next unused element in the blockset. * * @param blockset The blockset to return the next element from. * * @return Ptr to the next unused element in the blockset. */ void *Z_BlockNewElement(zblockset_t* set) { zblock_t* block = &set->blocks[set->count - 1]; // When this is called, there is always an available element in the topmost // block. We will return it. void* element = ((byte*)block->elements) + (block->elementSize * block->count); // Reserve the element. block->count++; // If we run out of space in the topmost block, add a new one. if(block->count == block->max) { // Just being cautious: adding a new block invalidates existing // pointers to the blocks. block = 0; Z_AddBlockToSet(set); } return element; } /** * Creates a new block memory allocator. These are used instead of many * calls to Z_Malloc when the number of required elements is unknown and * when linear allocation would be too slow. * * Memory is allocated as needed in blocks of "batchSize" elements. When * a new element is required we simply reserve a ptr in the previously * allocated block of elements or create a new block just in time. * * The internal state of a blockset is managed automatically. * * @param sizeOfElement Required size of each element. * @param batchSize Number of elements in each zblock of the set. * * @return Ptr to the newly created blockset. */ zblockset_t *Z_BlockCreate(size_t sizeOfElement, unsigned int batchSize, int tag) { zblockset_t *set; // Allocate the blockset. set = Z_Calloc(sizeof(*set), tag, NULL); set->elementsPerBlock = batchSize; set->elementSize = sizeOfElement; set->tag = tag; // Allocate the first block right away. Z_AddBlockToSet(set); return set; } /** * Free an entire blockset. * All memory allocated is released for all elements in all blocks and any * used for the blockset itself. * * @param set The blockset to be freed. */ void Z_BlockDestroy(zblockset_t *set) { uint i; if(!set) return; // Free the elements from each block. for(i = 0; i < set->count; ++i) Z_Free(set->blocks[i].elements); Z_Free(set->blocks); Z_Free(set); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_lumobjs.c0000644000175000017500000006512211357170242023077 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_lumobjs.c: Lumobj (luminous object) management. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_refresh.h" #include "de_render.h" #include "de_graphics.h" #include "de_misc.h" #include "de_play.h" #include "de_defs.h" // MACROS ------------------------------------------------------------------ BEGIN_PROF_TIMERS() PROF_LUMOBJ_INIT_ADD, PROF_LUMOBJ_FRAME_SORT END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- typedef struct lumlistnode_s { struct lumlistnode_s* next; struct lumlistnode_s* nextUsed; void* data; } lumlistnode_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static boolean iterateSubsectorLumObjs(subsector_t* ssec, boolean (*func) (void*, void*), void* data); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int useBias; // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean loInited = false; uint loMaxLumobjs = 0; int loMaxRadius = 256; // Dynamic lights maximum radius. float loRadiusFactor = 3; int useMobjAutoLights = true; // Enable automaticaly calculated lights // attached to mobjs. byte rendInfoLums = false; byte devDrawLums = false; // Display active lumobjs? // PRIVATE DATA DEFINITIONS ------------------------------------------------ static zblockset_t* luminousBlockSet = NULL; static uint numLuminous = 0, maxLuminous = 0; static lumobj_t** luminousList = NULL; static float* luminousDist = NULL; static byte* luminousClipped = NULL; static uint* luminousOrder = NULL; // List of unused and used list nodes, for linking lumobjs with subsectors. static lumlistnode_t* listNodeFirst = NULL, *listNodeCursor = NULL; // List of lumobjs for each subsector; static lumlistnode_t** subLumObjList = NULL; // CODE -------------------------------------------------------------------- /** * Registers the cvars and ccmds for lumobj management. */ void LO_Register(void) { C_VAR_INT("rend-light-num", &loMaxLumobjs, CVF_NO_MAX, 0, 0); C_VAR_FLOAT("rend-light-radius-scale", &loRadiusFactor, 0, 0.1f, 10); C_VAR_INT("rend-light-radius-max", &loMaxRadius, 0, 64, 512); C_VAR_BYTE("rend-info-lums", &rendInfoLums, 0, 0, 1); C_VAR_BYTE("rend-dev-lums", &devDrawLums, CVF_NO_ARCHIVE, 0, 1); } static lumlistnode_t* allocListNode(void) { lumlistnode_t* ln; if(listNodeCursor == NULL) { ln = Z_Malloc(sizeof(*ln), PU_STATIC, 0); // Link to the list of list nodes. ln->nextUsed = listNodeFirst; listNodeFirst = ln; } else { ln = listNodeCursor; listNodeCursor = listNodeCursor->nextUsed; } ln->next = NULL; ln->data = NULL; return ln; } static void linkLumObjToSSec(lumobj_t* lum) { lumlistnode_t* ln = allocListNode(); lumlistnode_t** root; root = &subLumObjList[GET_SUBSECTOR_IDX(lum->subsector)]; ln->next = *root; ln->data = lum; *root = ln; } static uint lumToIndex(const lumobj_t* lum) { uint i; for(i = 0; i < numLuminous; ++i) if(luminousList[i] == lum) return i; Con_Error("lumToIndex: Invalid lumobj.\n"); return 0; } void LO_InitForMap(void) { // First initialize the subsector links (root pointers). subLumObjList = Z_Calloc(sizeof(*subLumObjList) * numSSectors, PU_MAPSTATIC, 0); maxLuminous = 0; luminousBlockSet = NULL; // Will have already been free'd. } /** * Called once during engine shutdown by Rend_Reset(). Releases any system * resources acquired by the objlink + obj contact management subsystem. */ void LO_Clear(void) { Z_BlockDestroy(luminousBlockSet); if(luminousList) M_Free(luminousList); luminousList = NULL; if(luminousDist) M_Free(luminousDist); luminousDist = NULL; if(luminousClipped) M_Free(luminousClipped); luminousClipped = NULL; if(luminousOrder) M_Free(luminousOrder); luminousOrder = NULL; maxLuminous = numLuminous = 0; } /** * Called at the begining of each frame (iff the render lists are not frozen) * by R_BeginWorldFrame(). */ void LO_ClearForFrame(void) { #ifdef DD_PROFILE static int i; if(++i > 40) { i = 0; PRINT_PROF(PROF_LUMOBJ_INIT_ADD); PRINT_PROF(PROF_LUMOBJ_FRAME_SORT); } #endif // Start reusing nodes from the first one in the list. listNodeCursor = listNodeFirst; if(subLumObjList) memset(subLumObjList, 0, sizeof(lumlistnode_t*) * numSSectors); numLuminous = 0; } /** * @return The number of active lumobjs for this frame. */ uint LO_GetNumLuminous(void) { return numLuminous; } static lumobj_t* allocLumobj(void) { #define LUMOBJ_BATCH_SIZE (32) lumobj_t* lum; // Only allocate memory when it's needed. // \fixme No upper limit? if(++numLuminous > maxLuminous) { uint i, newMax = maxLuminous + LUMOBJ_BATCH_SIZE; if(!luminousBlockSet) { luminousBlockSet = Z_BlockCreate(sizeof(lumobj_t), LUMOBJ_BATCH_SIZE, PU_MAP); } luminousList = M_Realloc(luminousList, sizeof(lumobj_t*) * newMax); // Add the new lums to the end of the list. for(i = maxLuminous; i < newMax; ++i) luminousList[i] = Z_BlockNewElement(luminousBlockSet); maxLuminous = newMax; // Resize the associated buffers used for per-frame stuff. luminousDist = M_Realloc(luminousDist, sizeof(*luminousDist) * maxLuminous); luminousClipped = M_Realloc(luminousClipped, sizeof(*luminousClipped) * maxLuminous); luminousOrder = M_Realloc(luminousOrder, sizeof(*luminousOrder) * maxLuminous); } lum = luminousList[numLuminous - 1]; memset(lum, 0, sizeof(*lum)); return lum; #undef LUMOBJ_BATCH_SIZE } /** * Allocate a new lumobj. * * @return Index (name) by which the lumobj should be referred. */ uint LO_NewLuminous(lumtype_t type, subsector_t* ssec) { lumobj_t* lum = allocLumobj(); lum->type = type; lum->subsector = ssec; linkLumObjToSSec(lum); R_ObjLinkCreate(lum, OT_LUMOBJ); // For spreading purposes. return numLuminous; // == index + 1 } /** * Retrieve a ptr to the lumobj with the given index. A public interface to * the lumobj list. * * @return Ptr to the lumobj with the given 1-based index. */ lumobj_t* LO_GetLuminous(uint idx) { if(!(idx == 0 || idx > numLuminous)) return luminousList[idx - 1]; return NULL; } /** * @return Index of the specified lumobj. */ uint LO_ToIndex(const lumobj_t* lum) { return lumToIndex(lum)+1; } /** * Is the specified lumobj clipped for the current display player? */ boolean LO_IsClipped(uint idx, int i) { if(!(idx == 0 || idx > numLuminous)) return (luminousClipped[idx - 1]? true : false); return false; } /** * Is the specified lumobj hidden for the current display player? */ boolean LO_IsHidden(uint idx, int i) { if(!(idx == 0 || idx > numLuminous)) return (luminousClipped[idx - 1] == 2? true : false); return false; } /** * @return Approximated distance between the lumobj and the * viewer. */ float LO_DistanceToViewer(uint idx, int i) { if(!(idx == 0 || idx > numLuminous)) return luminousDist[idx - 1]; return 0; } /** * Registers the given mobj as a luminous, light-emitting object. * NOTE: This is called each frame for each luminous object! * * @param mo Ptr to the mobj to register. */ void LO_AddLuminous(mobj_t* mo) { mo->lumIdx = 0; if(((mo->state && (mo->state->flags & STF_FULLBRIGHT)) && !(mo->ddFlags & DDMF_DONTDRAW)) || (mo->ddFlags & DDMF_ALWAYSLIT)) { uint i; float mul, center; int radius; float rgb[3], yOffset, size; lumobj_t* l; ded_light_t* def = (mo->state? def = stateLights[mo->state - states] : 0); spritedef_t* sprDef; spriteframe_t* sprFrame; material_t* mat; rgbcol_t autoLightColor; material_snapshot_t ms; const gltexture_inst_t* texInst; // Are the automatically calculated light values for fullbright // sprite frames in use? if(mo->state && (!useMobjAutoLights || (mo->state->flags & STF_NOAUTOLIGHT)) && !stateLights[mo->state - states]) return; // Determine the sprite frame lump of the source. sprDef = &sprites[mo->sprite]; sprFrame = &sprDef->spriteFrames[mo->frame]; // Always use rotation zero. mat = sprFrame->mats[0]; #if _DEBUG if(!mat) Con_Error("LO_AddLuminous: Sprite '%i' frame '%i' missing material.", (int) mo->sprite, mo->frame); #endif // Ensure we have up-to-date information about the material. Material_Prepare(&ms, mat, true, NULL); if(ms.units[MTU_PRIMARY].texInst->tex->type != GLT_SPRITE) return; // *Very* strange... texInst = ms.units[MTU_PRIMARY].texInst; size = texInst->data.sprite.lumSize; yOffset = texInst->data.sprite.flareY; // Does the mobj have an active light definition? if(def) { if(def->size) size = def->size; if(def->offset[VY]) yOffset = def->offset[VY]; } autoLightColor[CR] = texInst->data.sprite.autoLightColor[CR]; autoLightColor[CG] = texInst->data.sprite.autoLightColor[CG]; autoLightColor[CB] = texInst->data.sprite.autoLightColor[CB]; center = spriteTextures[texInst->tex->ofTypeID]->offY - mo->floorClip - R_GetBobOffset(mo) - yOffset; // Will the sprite be allowed to go inside the floor? mul = mo->pos[VZ] + spriteTextures[texInst->tex->ofTypeID]->offY - (float) ms.height - mo->subsector->sector->SP_floorheight; if(!(mo->ddFlags & DDMF_NOFITBOTTOM) && mul < 0) { // Must adjust. center -= mul; } radius = size * 40 * loRadiusFactor; // Don't make a too small light. if(radius < 32) radius = 32; // Does the mobj use a light scale? if(mo->ddFlags & DDMF_LIGHTSCALE) { // Also reduce the size of the light according to // the scale flags. *Won't affect the flare.* mul = 1.0f - ((mo->ddFlags & DDMF_LIGHTSCALE) >> DDMF_LIGHTSCALESHIFT) / 4.0f; radius *= mul; } // If any of the color components are != 0, use the def's color. if(def && (def->color[0] || def->color[1] || def->color[2])) { for(i = 0; i < 3; ++i) rgb[i] = def->color[i]; } else { // Use the auto-calculated color. for(i = 0; i < 3; ++i) rgb[i] = autoLightColor[i]; } // This'll allow a halo to be rendered. If the light is hidden from // view by world geometry, the light pointer will be set to NULL. mo->lumIdx = LO_NewLuminous(LT_OMNI, mo->subsector); l = LO_GetLuminous(mo->lumIdx); l->pos[VX] = mo->pos[VX]; l->pos[VY] = mo->pos[VY]; l->pos[VZ] = mo->pos[VZ]; l->maxDistance = 0; l->decorSource = NULL; // Don't make too large a light. if(radius > loMaxRadius) radius = loMaxRadius; LUM_OMNI(l)->radius = radius; for(i = 0; i < 3; ++i) LUM_OMNI(l)->color[i] = rgb[i]; LUM_OMNI(l)->zOff = center; if(def) { LUM_OMNI(l)->tex = GL_GetLightMapTexture(def->sides.id); LUM_OMNI(l)->ceilTex = GL_GetLightMapTexture(def->up.id); LUM_OMNI(l)->floorTex = GL_GetLightMapTexture(def->down.id); } else { // Use the same default light texture for all directions. LUM_OMNI(l)->tex = LUM_OMNI(l)->ceilTex = LUM_OMNI(l)->floorTex = GL_PrepareLSTexture(LST_DYNAMIC); } } } /** * Used to sort lumobjs by distance from viewpoint. */ static int C_DECL lumobjSorter(const void* e1, const void* e2) { float a = luminousDist[*(const uint *) e1]; float b = luminousDist[*(const uint *) e2]; if(a > b) return 1; else if(a < b) return -1; else return 0; } /** * Called by Rend_RenderMap() if the render lists are not frozen. */ void LO_BeginFrame(void) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); uint i; if(!(numLuminous > 0)) return; BEGIN_PROF( PROF_LUMOBJ_FRAME_SORT ); // Update lumobj distances ready for linking and sorting. for(i = 0; i < numLuminous; ++i) { lumobj_t* lum = luminousList[i]; float pos[3]; V3_Subtract(pos, lum->pos, viewData->current.pos); // Approximate the distance in 3D. luminousDist[i] = P_ApproxDistance3(pos[VX], pos[VY], pos[VZ]); } if(loMaxLumobjs > 0 && numLuminous > loMaxLumobjs) { // Sort lumobjs by distance from the viewer. Then clip all lumobjs // so that only the closest are visible (max loMaxLumobjs). uint n; // Init the lumobj indices, sort array. for(i = 0; i < numLuminous; ++i) luminousOrder[i] = i; qsort(luminousOrder, numLuminous, sizeof(uint), lumobjSorter); // Mark all as hidden. memset(luminousClipped, 2, numLuminous * sizeof(*luminousClipped)); n = 0; for(i = 0; i < numLuminous; ++i) { if(n++ > loMaxLumobjs) break; // Unhide this lumobj. luminousClipped[luminousOrder[i]] = 1; } } else { // Mark all as clipped. memset(luminousClipped, 1, numLuminous * sizeof(*luminousClipped)); } // objLinks already contains links if there are any light decorations // currently in use. loInited = true; END_PROF( PROF_LUMOBJ_FRAME_SORT ); } /** * Generate one dynlight node for each plane glow. * The light is attached to the appropriate dynlight node list. * * @param ssec Ptr to the subsector to process. */ static void createGlowLightPerPlaneForSubSector(subsector_t* ssec) { uint g; plane_t* glowPlanes[2], *pln; glowPlanes[PLN_FLOOR] = ssec->sector->planes[PLN_FLOOR]; glowPlanes[PLN_CEILING] = ssec->sector->planes[PLN_CEILING]; //// \fixme $nplanes for(g = 0; g < 2; ++g) { uint lumIdx; lumobj_t* l; pln = glowPlanes[g]; if(pln->glow <= 0) continue; lumIdx = LO_NewLuminous(LT_PLANE, ssec); l = LO_GetLuminous(lumIdx); l->pos[VX] = ssec->midPoint.pos[VX]; l->pos[VY] = ssec->midPoint.pos[VY]; l->pos[VZ] = pln->visHeight; l->maxDistance = 0; l->decorSource = NULL; LUM_PLANE(l)->normal[VX] = pln->PS_normal[VX]; LUM_PLANE(l)->normal[VY] = pln->PS_normal[VY]; LUM_PLANE(l)->normal[VZ] = pln->PS_normal[VZ]; LUM_PLANE(l)->color[CR] = pln->glowRGB[CR]; LUM_PLANE(l)->color[CG] = pln->glowRGB[CG]; LUM_PLANE(l)->color[CB] = pln->glowRGB[CB]; LUM_PLANE(l)->intensity = pln->glow; LUM_PLANE(l)->tex = GL_PrepareLSTexture(LST_GRADIENT); // Planar lights don't spread, so just link the lum to its own ssec. { linkobjtossecparams_t params; params.obj = l; params.type = OT_LUMOBJ; RIT_LinkObjToSubSector(l->subsector, ¶ms); } } } /** * Create lumobjs for all sector-linked mobjs who want them. */ void LO_AddLuminousMobjs(void) { uint i; sector_t* seciter; if(!useDynLights && !useWallGlow) return; BEGIN_PROF( PROF_LUMOBJ_INIT_ADD ); for(i = 0, seciter = sectors; i < numSectors; seciter++, ++i) { if(useDynLights) { mobj_t* iter; for(iter = seciter->mobjList; iter; iter = iter->sNext) { LO_AddLuminous(iter); } } // If the segs of this subsector are affected by glowing planes we need // to create dynlights and link them. if(useWallGlow && seciter->ssectors) { subsector_t** ssec = seciter->ssectors; while(*ssec) { createGlowLightPerPlaneForSubSector(*ssec); *ssec++; } } } END_PROF( PROF_LUMOBJ_INIT_ADD ); } typedef struct lumobjiterparams_s { float origin[2]; float radius; void* data; boolean (*func) (const lumobj_t*, float, void* data); } lumobjiterparams_t; boolean LOIT_RadiusLumobjs(void* ptr, void* data) { const lumobj_t* lum = (const lumobj_t*) ptr; lumobjiterparams_t* params = data; float dist = P_ApproxDistance(lum->pos[VX] - params->origin[VX], lum->pos[VY] - params->origin[VY]); if(dist <= params->radius && !params->func(lum, dist, params->data)) return false; // Stop iteration. return true; // Continue iteration. } /** * Calls func for all luminous objects within the specified origin range. * * @param subsector The subsector in which the origin resides. * @param x X coordinate of the origin (must be within subsector). * @param y Y coordinate of the origin (must be within subsector). * @param radius Radius of the range around the origin point. * @param data Ptr to pass to the callback. * @param func Callback to make for each object. * * @return @c true, iff every callback returns @c true, else @c false. */ boolean LO_LumobjsRadiusIterator(subsector_t* ssec, float x, float y, float radius, void* data, boolean (*func) (const lumobj_t*, float, void*)) { lumobjiterparams_t params; if(!ssec) return true; params.origin[VX] = x; params.origin[VY] = y; params.radius = radius; params.func = func; params.data = data; return R_IterateSubsectorContacts(ssec, OT_LUMOBJ, LOIT_RadiusLumobjs, (void*) ¶ms); } boolean LOIT_ClipLumObj(void* data, void* context) { lumobj_t* lum = (lumobj_t*) data; uint lumIdx = lumToIndex(lum); vec3_t pos; if(lum->type != LT_OMNI) return true; // Only interested in omnilights. if(luminousClipped[lumIdx] > 1) return true; // Already hidden by some other means. luminousClipped[lumIdx] = 0; // \fixme Determine the exact centerpoint of the light in // LO_AddLuminous! V3_Set(pos, lum->pos[VX], lum->pos[VY], lum->pos[VZ] + LUM_OMNI(lum)->zOff); /** * Select clipping strategy: * * If culling world surfaces with the angle clipper and the viewer is * not in the void; use the angle clipper here too. Otherwise, use the * BSP-based LOS algorithm. */ if(!(devNoCulling || P_IsInVoid(&ddPlayers[displayPlayer]))) { if(!C_IsPointVisible(pos[VX], pos[VY], pos[VZ])) luminousClipped[lumIdx] = 1; // Won't have a halo. } else { vec3_t vpos; V3_Set(vpos, vx, vz, vy); luminousClipped[lumIdx] = 1; if(P_CheckLineSight(vpos, pos, -1, 1, LS_PASSLEFT | LS_PASSOVER | LS_PASSUNDER)) { luminousClipped[lumIdx] = 0; // Will have a halo. } } return true; // Continue iteration. } /** * Clip lumobj, omni lights in the given subsector. * * @param ssecidx Subsector index in which lights will be clipped. */ void LO_ClipInSubsector(uint ssecidx) { iterateSubsectorLumObjs(&ssectors[ssecidx], LOIT_ClipLumObj, NULL); } boolean LOIT_ClipLumObjBySight(void* data, void* context) { lumobj_t* lum = (lumobj_t*) data; uint lumIdx = lumToIndex(lum); subsector_t* ssec = (subsector_t*) context; if(lum->type != LT_OMNI) return true; // Only interested in omnilights. if(!luminousClipped[lumIdx]) { uint i; vec2_t eye; V2_Set(eye, vx, vz); // We need to figure out if any of the polyobj's segments lies // between the viewpoint and the lumobj. for(i = 0; i < ssec->polyObj->numSegs; ++i) { seg_t* seg = ssec->polyObj->segs[i]; // Ignore segs facing the wrong way. if(seg->frameFlags & SEGINF_FACINGFRONT) { vec2_t source; V2_Set(source, lum->pos[VX], lum->pos[VY]); if(V2_Intercept2(source, eye, seg->SG_v1pos, seg->SG_v2pos, NULL, NULL, NULL)) { luminousClipped[lumIdx] = 1; break; } } } } return true; // Continue iteration. } /** * In the situation where a subsector contains both lumobjs and a polyobj, * the lumobjs must be clipped more carefully. Here we check if the line of * sight intersects any of the polyobj segs that face the camera. * * @param ssecidx Subsector index in which lumobjs will be clipped. */ void LO_ClipInSubsectorBySight(uint ssecidx) { iterateSubsectorLumObjs(&ssectors[ssecidx], LOIT_ClipLumObjBySight, &ssectors[ssecidx]); } static boolean iterateSubsectorLumObjs(subsector_t* ssec, boolean (*func) (void*, void*), void* data) { lumlistnode_t* ln; ln = subLumObjList[GET_SUBSECTOR_IDX(ssec)]; while(ln) { if(!func(ln->data, data)) return false; ln = ln->next; } return true; } void LO_UnlinkMobjLumobj(mobj_t* mo) { mo->lumIdx = 0; } boolean LOIT_UnlinkMobjLumobj(thinker_t* th, void* context) { LO_UnlinkMobjLumobj((mobj_t*) th); return true; // Continue iteration. } void LO_UnlinkMobjLumobjs(cvar_t* var) { if(!useDynLights) { // Mobjs are always public. P_IterateThinkers(gx.MobjThinker, 0x1, LOIT_UnlinkMobjLumobj, NULL); } } void LO_DrawLumobjs(void) { static const float black[4] = { 0, 0, 0, 0 }; static const float white[4] = { 1, 1, 1, 1 }; float color[4]; uint i; if(!devDrawLums) return; glDisable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); for(i = 0; i < numLuminous; ++i) { lumobj_t* lum = luminousList[i]; vec3_t lumCenter; if(!(lum->type == LT_OMNI || lum->type == LT_PLANE)) continue; if(lum->type == LT_OMNI && loMaxLumobjs > 0 && luminousClipped[i] == 2) continue; V3_Copy(lumCenter, lum->pos); if(lum->type == LT_OMNI) lumCenter[VZ] += LUM_OMNI(lum)->zOff; glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(lumCenter[VX], lumCenter[VZ], lumCenter[VY]); switch(lum->type) { case LT_OMNI: { float scale = LUM_OMNI(lum)->radius; color[CR] = LUM_OMNI(lum)->color[CR]; color[CG] = LUM_OMNI(lum)->color[CG]; color[CB] = LUM_OMNI(lum)->color[CB]; color[CA] = 1; glBegin(GL_LINES); { glColor4fv(black); glVertex3f(-scale, 0, 0); glColor4fv(color); glVertex3f(0, 0, 0); glVertex3f(0, 0, 0); glColor4fv(black); glVertex3f(scale, 0, 0); glVertex3f(0, -scale, 0); glColor4fv(color); glVertex3f(0, 0, 0); glVertex3f(0, 0, 0); glColor4fv(black); glVertex3f(0, scale, 0); glVertex3f(0, 0, -scale); glColor4fv(color); glVertex3f(0, 0, 0); glVertex3f(0, 0, 0); glColor4fv(black); glVertex3f(0, 0, scale); } glEnd(); break; } case LT_PLANE: { float scale = LUM_PLANE(lum)->intensity * 10; color[CR] = LUM_PLANE(lum)->color[CR]; color[CG] = LUM_PLANE(lum)->color[CG]; color[CB] = LUM_PLANE(lum)->color[CB]; color[CA] = 1; glBegin(GL_LINES); { glColor4fv(black); glVertex3f(scale * LUM_PLANE(lum)->normal[VX], scale * LUM_PLANE(lum)->normal[VZ], scale * LUM_PLANE(lum)->normal[VY]); glColor4fv(color); glVertex3f(0, 0, 0); } glEnd(); break; } default: break; } glMatrixMode(GL_MODELVIEW); glPopMatrix(); } glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/tab_tables.c0000644000175000017500000036174211357170242023212 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006 Jamie Jones *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * tab_tables.c: Precalculated Trigonometric Functions * Tables sourced from tables.c in the Doom GPL release. */ int finetangent[4096] = { -170910304,-56965752,-34178904,-24413316,-18988036,-15535599,-13145455,-11392683, -10052327,-8994149,-8137527,-7429880,-6835455,-6329090,-5892567,-5512368, -5178251,-4882318,-4618375,-4381502,-4167737,-3973855,-3797206,-3635590, -3487165,-3350381,-3223918,-3106651,-2997613,-2895966,-2800983,-2712030, -2628549,-2550052,-2476104,-2406322,-2340362,-2277919,-2218719,-2162516, -2109087,-2058233,-2009771,-1963536,-1919378,-1877161,-1836758,-1798063, -1760956,-1725348,-1691149,-1658278,-1626658,-1596220,-1566898,-1538632, -1511367,-1485049,-1459630,-1435065,-1411312,-1388330,-1366084,-1344537, -1323658,-1303416,-1283783,-1264730,-1246234,-1228269,-1210813,-1193846, -1177345,-1161294,-1145673,-1130465,-1115654,-1101225,-1087164,-1073455, -1060087,-1047046,-1034322,-1021901,-1009774,-997931,-986361,-975054, -964003,-953199,-942633,-932298,-922186,-912289,-902602,-893117, -883829,-874730,-865817,-857081,-848520,-840127,-831898,-823827, -815910,-808143,-800521,-793041,-785699,-778490,-771411,-764460, -757631,-750922,-744331,-737853,-731486,-725227,-719074,-713023, -707072,-701219,-695462,-689797,-684223,-678737,-673338,-668024, -662792,-657640,-652568,-647572,-642651,-637803,-633028,-628323, -623686,-619117,-614613,-610174,-605798,-601483,-597229,-593033, -588896,-584815,-580789,-576818,-572901,-569035,-565221,-561456, -557741,-554074,-550455,-546881,-543354,-539870,-536431,-533034, -529680,-526366,-523094,-519861,-516667,-513512,-510394,-507313, -504269,-501261,-498287,-495348,-492443,-489571,-486732,-483925, -481150,-478406,-475692,-473009,-470355,-467730,-465133,-462565, -460024,-457511,-455024,-452564,-450129,-447720,-445337,-442978, -440643,-438332,-436045,-433781,-431540,-429321,-427125,-424951, -422798,-420666,-418555,-416465,-414395,-412344,-410314,-408303, -406311,-404338,-402384,-400448,-398530,-396630,-394747,-392882, -391034,-389202,-387387,-385589,-383807,-382040,-380290,-378555, -376835,-375130,-373440,-371765,-370105,-368459,-366826,-365208, -363604,-362013,-360436,-358872,-357321,-355783,-354257,-352744, -351244,-349756,-348280,-346816,-345364,-343924,-342495,-341078, -339671,-338276,-336892,-335519,-334157,-332805,-331464,-330133, -328812,-327502,-326201,-324910,-323629,-322358,-321097,-319844, -318601,-317368,-316143,-314928,-313721,-312524,-311335,-310154, -308983,-307819,-306664,-305517,-304379,-303248,-302126,-301011, -299904,-298805,-297714,-296630,-295554,-294485,-293423,-292369, -291322,-290282,-289249,-288223,-287204,-286192,-285186,-284188, -283195,-282210,-281231,-280258,-279292,-278332,-277378,-276430, -275489,-274553,-273624,-272700,-271782,-270871,-269965,-269064, -268169,-267280,-266397,-265519,-264646,-263779,-262917,-262060, -261209,-260363,-259522,-258686,-257855,-257029,-256208,-255392, -254581,-253774,-252973,-252176,-251384,-250596,-249813,-249035, -248261,-247492,-246727,-245966,-245210,-244458,-243711,-242967, -242228,-241493,-240763,-240036,-239314,-238595,-237881,-237170, -236463,-235761,-235062,-234367,-233676,-232988,-232304,-231624, -230948,-230275,-229606,-228941,-228279,-227621,-226966,-226314, -225666,-225022,-224381,-223743,-223108,-222477,-221849,-221225, -220603,-219985,-219370,-218758,-218149,-217544,-216941,-216341, -215745,-215151,-214561,-213973,-213389,-212807,-212228,-211652, -211079,-210509,-209941,-209376,-208815,-208255,-207699,-207145, -206594,-206045,-205500,-204956,-204416,-203878,-203342,-202809, -202279,-201751,-201226,-200703,-200182,-199664,-199149,-198636, -198125,-197616,-197110,-196606,-196105,-195606,-195109,-194614, -194122,-193631,-193143,-192658,-192174,-191693,-191213,-190736, -190261,-189789,-189318,-188849,-188382,-187918,-187455,-186995, -186536,-186080,-185625,-185173,-184722,-184274,-183827,-183382, -182939,-182498,-182059,-181622,-181186,-180753,-180321,-179891, -179463,-179037,-178612,-178190,-177769,-177349,-176932,-176516, -176102,-175690,-175279,-174870,-174463,-174057,-173653,-173251, -172850,-172451,-172053,-171657,-171263,-170870,-170479,-170089, -169701,-169315,-168930,-168546,-168164,-167784,-167405,-167027, -166651,-166277,-165904,-165532,-165162,-164793,-164426,-164060, -163695,-163332,-162970,-162610,-162251,-161893,-161537,-161182, -160828,-160476,-160125,-159775,-159427,-159079,-158734,-158389, -158046,-157704,-157363,-157024,-156686,-156349,-156013,-155678, -155345,-155013,-154682,-154352,-154024,-153697,-153370,-153045, -152722,-152399,-152077,-151757,-151438,-151120,-150803,-150487, -150172,-149859,-149546,-149235,-148924,-148615,-148307,-148000, -147693,-147388,-147084,-146782,-146480,-146179,-145879,-145580, -145282,-144986,-144690,-144395,-144101,-143808,-143517,-143226, -142936,-142647,-142359,-142072,-141786,-141501,-141217,-140934, -140651,-140370,-140090,-139810,-139532,-139254,-138977,-138701, -138426,-138152,-137879,-137607,-137335,-137065,-136795,-136526, -136258,-135991,-135725,-135459,-135195,-134931,-134668,-134406, -134145,-133884,-133625,-133366,-133108,-132851,-132594,-132339, -132084,-131830,-131576,-131324,-131072,-130821,-130571,-130322, -130073,-129825,-129578,-129332,-129086,-128841,-128597,-128353, -128111,-127869,-127627,-127387,-127147,-126908,-126669,-126432, -126195,-125959,-125723,-125488,-125254,-125020,-124787,-124555, -124324,-124093,-123863,-123633,-123404,-123176,-122949,-122722, -122496,-122270,-122045,-121821,-121597,-121374,-121152,-120930, -120709,-120489,-120269,-120050,-119831,-119613,-119396,-119179, -118963,-118747,-118532,-118318,-118104,-117891,-117678,-117466, -117254,-117044,-116833,-116623,-116414,-116206,-115998,-115790, -115583,-115377,-115171,-114966,-114761,-114557,-114354,-114151, -113948,-113746,-113545,-113344,-113143,-112944,-112744,-112546, -112347,-112150,-111952,-111756,-111560,-111364,-111169,-110974, -110780,-110586,-110393,-110200,-110008,-109817,-109626,-109435, -109245,-109055,-108866,-108677,-108489,-108301,-108114,-107927, -107741,-107555,-107369,-107184,-107000,-106816,-106632,-106449, -106266,-106084,-105902,-105721,-105540,-105360,-105180,-105000, -104821,-104643,-104465,-104287,-104109,-103933,-103756,-103580, -103404,-103229,-103054,-102880,-102706,-102533,-102360,-102187, -102015,-101843,-101671,-101500,-101330,-101159,-100990,-100820, -100651,-100482,-100314,-100146,-99979,-99812,-99645,-99479, -99313,-99148,-98982,-98818,-98653,-98489,-98326,-98163, -98000,-97837,-97675,-97513,-97352,-97191,-97030,-96870, -96710,-96551,-96391,-96233,-96074,-95916,-95758,-95601, -95444,-95287,-95131,-94975,-94819,-94664,-94509,-94354, -94200,-94046,-93892,-93739,-93586,-93434,-93281,-93129, -92978,-92826,-92675,-92525,-92375,-92225,-92075,-91926, -91777,-91628,-91480,-91332,-91184,-91036,-90889,-90742, -90596,-90450,-90304,-90158,-90013,-89868,-89724,-89579, -89435,-89292,-89148,-89005,-88862,-88720,-88577,-88435, -88294,-88152,-88011,-87871,-87730,-87590,-87450,-87310, -87171,-87032,-86893,-86755,-86616,-86479,-86341,-86204, -86066,-85930,-85793,-85657,-85521,-85385,-85250,-85114, -84980,-84845,-84710,-84576,-84443,-84309,-84176,-84043, -83910,-83777,-83645,-83513,-83381,-83250,-83118,-82987, -82857,-82726,-82596,-82466,-82336,-82207,-82078,-81949, -81820,-81691,-81563,-81435,-81307,-81180,-81053,-80925, -80799,-80672,-80546,-80420,-80294,-80168,-80043,-79918, -79793,-79668,-79544,-79420,-79296,-79172,-79048,-78925, -78802,-78679,-78557,-78434,-78312,-78190,-78068,-77947, -77826,-77705,-77584,-77463,-77343,-77223,-77103,-76983, -76864,-76744,-76625,-76506,-76388,-76269,-76151,-76033, -75915,-75797,-75680,-75563,-75446,-75329,-75213,-75096, -74980,-74864,-74748,-74633,-74517,-74402,-74287,-74172, -74058,-73944,-73829,-73715,-73602,-73488,-73375,-73262, -73149,-73036,-72923,-72811,-72699,-72587,-72475,-72363, -72252,-72140,-72029,-71918,-71808,-71697,-71587,-71477, -71367,-71257,-71147,-71038,-70929,-70820,-70711,-70602, -70494,-70385,-70277,-70169,-70061,-69954,-69846,-69739, -69632,-69525,-69418,-69312,-69205,-69099,-68993,-68887, -68781,-68676,-68570,-68465,-68360,-68255,-68151,-68046, -67942,-67837,-67733,-67629,-67526,-67422,-67319,-67216, -67113,-67010,-66907,-66804,-66702,-66600,-66498,-66396, -66294,-66192,-66091,-65989,-65888,-65787,-65686,-65586, -65485,-65385,-65285,-65185,-65085,-64985,-64885,-64786, -64687,-64587,-64488,-64389,-64291,-64192,-64094,-63996, -63897,-63799,-63702,-63604,-63506,-63409,-63312,-63215, -63118,-63021,-62924,-62828,-62731,-62635,-62539,-62443, -62347,-62251,-62156,-62060,-61965,-61870,-61775,-61680, -61585,-61491,-61396,-61302,-61208,-61114,-61020,-60926, -60833,-60739,-60646,-60552,-60459,-60366,-60273,-60181, -60088,-59996,-59903,-59811,-59719,-59627,-59535,-59444, -59352,-59261,-59169,-59078,-58987,-58896,-58805,-58715, -58624,-58534,-58443,-58353,-58263,-58173,-58083,-57994, -57904,-57815,-57725,-57636,-57547,-57458,-57369,-57281, -57192,-57104,-57015,-56927,-56839,-56751,-56663,-56575, -56487,-56400,-56312,-56225,-56138,-56051,-55964,-55877, -55790,-55704,-55617,-55531,-55444,-55358,-55272,-55186, -55100,-55015,-54929,-54843,-54758,-54673,-54587,-54502, -54417,-54333,-54248,-54163,-54079,-53994,-53910,-53826, -53741,-53657,-53574,-53490,-53406,-53322,-53239,-53156, -53072,-52989,-52906,-52823,-52740,-52657,-52575,-52492, -52410,-52327,-52245,-52163,-52081,-51999,-51917,-51835, -51754,-51672,-51591,-51509,-51428,-51347,-51266,-51185, -51104,-51023,-50942,-50862,-50781,-50701,-50621,-50540, -50460,-50380,-50300,-50221,-50141,-50061,-49982,-49902, -49823,-49744,-49664,-49585,-49506,-49427,-49349,-49270, -49191,-49113,-49034,-48956,-48878,-48799,-48721,-48643, -48565,-48488,-48410,-48332,-48255,-48177,-48100,-48022, -47945,-47868,-47791,-47714,-47637,-47560,-47484,-47407, -47331,-47254,-47178,-47102,-47025,-46949,-46873,-46797, -46721,-46646,-46570,-46494,-46419,-46343,-46268,-46193, -46118,-46042,-45967,-45892,-45818,-45743,-45668,-45593, -45519,-45444,-45370,-45296,-45221,-45147,-45073,-44999, -44925,-44851,-44778,-44704,-44630,-44557,-44483,-44410, -44337,-44263,-44190,-44117,-44044,-43971,-43898,-43826, -43753,-43680,-43608,-43535,-43463,-43390,-43318,-43246, -43174,-43102,-43030,-42958,-42886,-42814,-42743,-42671, -42600,-42528,-42457,-42385,-42314,-42243,-42172,-42101, -42030,-41959,-41888,-41817,-41747,-41676,-41605,-41535, -41465,-41394,-41324,-41254,-41184,-41113,-41043,-40973, -40904,-40834,-40764,-40694,-40625,-40555,-40486,-40416, -40347,-40278,-40208,-40139,-40070,-40001,-39932,-39863, -39794,-39726,-39657,-39588,-39520,-39451,-39383,-39314, -39246,-39178,-39110,-39042,-38973,-38905,-38837,-38770, -38702,-38634,-38566,-38499,-38431,-38364,-38296,-38229, -38161,-38094,-38027,-37960,-37893,-37826,-37759,-37692, -37625,-37558,-37491,-37425,-37358,-37291,-37225,-37158, -37092,-37026,-36959,-36893,-36827,-36761,-36695,-36629, -36563,-36497,-36431,-36365,-36300,-36234,-36168,-36103, -36037,-35972,-35907,-35841,-35776,-35711,-35646,-35580, -35515,-35450,-35385,-35321,-35256,-35191,-35126,-35062, -34997,-34932,-34868,-34803,-34739,-34675,-34610,-34546, -34482,-34418,-34354,-34289,-34225,-34162,-34098,-34034, -33970,-33906,-33843,-33779,-33715,-33652,-33588,-33525, -33461,-33398,-33335,-33272,-33208,-33145,-33082,-33019, -32956,-32893,-32830,-32767,-32705,-32642,-32579,-32516, -32454,-32391,-32329,-32266,-32204,-32141,-32079,-32017, -31955,-31892,-31830,-31768,-31706,-31644,-31582,-31520, -31458,-31396,-31335,-31273,-31211,-31150,-31088,-31026, -30965,-30904,-30842,-30781,-30719,-30658,-30597,-30536, -30474,-30413,-30352,-30291,-30230,-30169,-30108,-30048, -29987,-29926,-29865,-29805,-29744,-29683,-29623,-29562, -29502,-29441,-29381,-29321,-29260,-29200,-29140,-29080, -29020,-28959,-28899,-28839,-28779,-28719,-28660,-28600, -28540,-28480,-28420,-28361,-28301,-28241,-28182,-28122, -28063,-28003,-27944,-27884,-27825,-27766,-27707,-27647, -27588,-27529,-27470,-27411,-27352,-27293,-27234,-27175, -27116,-27057,-26998,-26940,-26881,-26822,-26763,-26705, -26646,-26588,-26529,-26471,-26412,-26354,-26295,-26237, -26179,-26120,-26062,-26004,-25946,-25888,-25830,-25772, -25714,-25656,-25598,-25540,-25482,-25424,-25366,-25308, -25251,-25193,-25135,-25078,-25020,-24962,-24905,-24847, -24790,-24732,-24675,-24618,-24560,-24503,-24446,-24389, -24331,-24274,-24217,-24160,-24103,-24046,-23989,-23932, -23875,-23818,-23761,-23704,-23647,-23591,-23534,-23477, -23420,-23364,-23307,-23250,-23194,-23137,-23081,-23024, -22968,-22911,-22855,-22799,-22742,-22686,-22630,-22573, -22517,-22461,-22405,-22349,-22293,-22237,-22181,-22125, -22069,-22013,-21957,-21901,-21845,-21789,-21733,-21678, -21622,-21566,-21510,-21455,-21399,-21343,-21288,-21232, -21177,-21121,-21066,-21010,-20955,-20900,-20844,-20789, -20734,-20678,-20623,-20568,-20513,-20457,-20402,-20347, -20292,-20237,-20182,-20127,-20072,-20017,-19962,-19907, -19852,-19797,-19742,-19688,-19633,-19578,-19523,-19469, -19414,-19359,-19305,-19250,-19195,-19141,-19086,-19032, -18977,-18923,-18868,-18814,-18760,-18705,-18651,-18597, -18542,-18488,-18434,-18380,-18325,-18271,-18217,-18163, -18109,-18055,-18001,-17946,-17892,-17838,-17784,-17731, -17677,-17623,-17569,-17515,-17461,-17407,-17353,-17300, -17246,-17192,-17138,-17085,-17031,-16977,-16924,-16870, -16817,-16763,-16710,-16656,-16603,-16549,-16496,-16442, -16389,-16335,-16282,-16229,-16175,-16122,-16069,-16015, -15962,-15909,-15856,-15802,-15749,-15696,-15643,-15590, -15537,-15484,-15431,-15378,-15325,-15272,-15219,-15166, -15113,-15060,-15007,-14954,-14901,-14848,-14795,-14743, -14690,-14637,-14584,-14531,-14479,-14426,-14373,-14321, -14268,-14215,-14163,-14110,-14057,-14005,-13952,-13900, -13847,-13795,-13742,-13690,-13637,-13585,-13533,-13480, -13428,-13375,-13323,-13271,-13218,-13166,-13114,-13062, -13009,-12957,-12905,-12853,-12800,-12748,-12696,-12644, -12592,-12540,-12488,-12436,-12383,-12331,-12279,-12227, -12175,-12123,-12071,-12019,-11967,-11916,-11864,-11812, -11760,-11708,-11656,-11604,-11552,-11501,-11449,-11397, -11345,-11293,-11242,-11190,-11138,-11086,-11035,-10983, -10931,-10880,-10828,-10777,-10725,-10673,-10622,-10570, -10519,-10467,-10415,-10364,-10312,-10261,-10209,-10158, -10106,-10055,-10004,-9952,-9901,-9849,-9798,-9747, -9695,-9644,-9592,-9541,-9490,-9438,-9387,-9336, -9285,-9233,-9182,-9131,-9080,-9028,-8977,-8926, -8875,-8824,-8772,-8721,-8670,-8619,-8568,-8517, -8466,-8414,-8363,-8312,-8261,-8210,-8159,-8108, -8057,-8006,-7955,-7904,-7853,-7802,-7751,-7700, -7649,-7598,-7547,-7496,-7445,-7395,-7344,-7293, -7242,-7191,-7140,-7089,-7038,-6988,-6937,-6886, -6835,-6784,-6733,-6683,-6632,-6581,-6530,-6480, -6429,-6378,-6327,-6277,-6226,-6175,-6124,-6074, -6023,-5972,-5922,-5871,-5820,-5770,-5719,-5668, -5618,-5567,-5517,-5466,-5415,-5365,-5314,-5264, -5213,-5162,-5112,-5061,-5011,-4960,-4910,-4859, -4808,-4758,-4707,-4657,-4606,-4556,-4505,-4455, -4404,-4354,-4303,-4253,-4202,-4152,-4101,-4051, -4001,-3950,-3900,-3849,-3799,-3748,-3698,-3648, -3597,-3547,-3496,-3446,-3395,-3345,-3295,-3244, -3194,-3144,-3093,-3043,-2992,-2942,-2892,-2841, -2791,-2741,-2690,-2640,-2590,-2539,-2489,-2439, -2388,-2338,-2288,-2237,-2187,-2137,-2086,-2036, -1986,-1935,-1885,-1835,-1784,-1734,-1684,-1633, -1583,-1533,-1483,-1432,-1382,-1332,-1281,-1231, -1181,-1131,-1080,-1030,-980,-929,-879,-829, -779,-728,-678,-628,-578,-527,-477,-427, -376,-326,-276,-226,-175,-125,-75,-25, 25,75,125,175,226,276,326,376, 427,477,527,578,628,678,728,779, 829,879,929,980,1030,1080,1131,1181, 1231,1281,1332,1382,1432,1483,1533,1583, 1633,1684,1734,1784,1835,1885,1935,1986, 2036,2086,2137,2187,2237,2288,2338,2388, 2439,2489,2539,2590,2640,2690,2741,2791, 2841,2892,2942,2992,3043,3093,3144,3194, 3244,3295,3345,3395,3446,3496,3547,3597, 3648,3698,3748,3799,3849,3900,3950,4001, 4051,4101,4152,4202,4253,4303,4354,4404, 4455,4505,4556,4606,4657,4707,4758,4808, 4859,4910,4960,5011,5061,5112,5162,5213, 5264,5314,5365,5415,5466,5517,5567,5618, 5668,5719,5770,5820,5871,5922,5972,6023, 6074,6124,6175,6226,6277,6327,6378,6429, 6480,6530,6581,6632,6683,6733,6784,6835, 6886,6937,6988,7038,7089,7140,7191,7242, 7293,7344,7395,7445,7496,7547,7598,7649, 7700,7751,7802,7853,7904,7955,8006,8057, 8108,8159,8210,8261,8312,8363,8414,8466, 8517,8568,8619,8670,8721,8772,8824,8875, 8926,8977,9028,9080,9131,9182,9233,9285, 9336,9387,9438,9490,9541,9592,9644,9695, 9747,9798,9849,9901,9952,10004,10055,10106, 10158,10209,10261,10312,10364,10415,10467,10519, 10570,10622,10673,10725,10777,10828,10880,10931, 10983,11035,11086,11138,11190,11242,11293,11345, 11397,11449,11501,11552,11604,11656,11708,11760, 11812,11864,11916,11967,12019,12071,12123,12175, 12227,12279,12331,12383,12436,12488,12540,12592, 12644,12696,12748,12800,12853,12905,12957,13009, 13062,13114,13166,13218,13271,13323,13375,13428, 13480,13533,13585,13637,13690,13742,13795,13847, 13900,13952,14005,14057,14110,14163,14215,14268, 14321,14373,14426,14479,14531,14584,14637,14690, 14743,14795,14848,14901,14954,15007,15060,15113, 15166,15219,15272,15325,15378,15431,15484,15537, 15590,15643,15696,15749,15802,15856,15909,15962, 16015,16069,16122,16175,16229,16282,16335,16389, 16442,16496,16549,16603,16656,16710,16763,16817, 16870,16924,16977,17031,17085,17138,17192,17246, 17300,17353,17407,17461,17515,17569,17623,17677, 17731,17784,17838,17892,17946,18001,18055,18109, 18163,18217,18271,18325,18380,18434,18488,18542, 18597,18651,18705,18760,18814,18868,18923,18977, 19032,19086,19141,19195,19250,19305,19359,19414, 19469,19523,19578,19633,19688,19742,19797,19852, 19907,19962,20017,20072,20127,20182,20237,20292, 20347,20402,20457,20513,20568,20623,20678,20734, 20789,20844,20900,20955,21010,21066,21121,21177, 21232,21288,21343,21399,21455,21510,21566,21622, 21678,21733,21789,21845,21901,21957,22013,22069, 22125,22181,22237,22293,22349,22405,22461,22517, 22573,22630,22686,22742,22799,22855,22911,22968, 23024,23081,23137,23194,23250,23307,23364,23420, 23477,23534,23591,23647,23704,23761,23818,23875, 23932,23989,24046,24103,24160,24217,24274,24331, 24389,24446,24503,24560,24618,24675,24732,24790, 24847,24905,24962,25020,25078,25135,25193,25251, 25308,25366,25424,25482,25540,25598,25656,25714, 25772,25830,25888,25946,26004,26062,26120,26179, 26237,26295,26354,26412,26471,26529,26588,26646, 26705,26763,26822,26881,26940,26998,27057,27116, 27175,27234,27293,27352,27411,27470,27529,27588, 27647,27707,27766,27825,27884,27944,28003,28063, 28122,28182,28241,28301,28361,28420,28480,28540, 28600,28660,28719,28779,28839,28899,28959,29020, 29080,29140,29200,29260,29321,29381,29441,29502, 29562,29623,29683,29744,29805,29865,29926,29987, 30048,30108,30169,30230,30291,30352,30413,30474, 30536,30597,30658,30719,30781,30842,30904,30965, 31026,31088,31150,31211,31273,31335,31396,31458, 31520,31582,31644,31706,31768,31830,31892,31955, 32017,32079,32141,32204,32266,32329,32391,32454, 32516,32579,32642,32705,32767,32830,32893,32956, 33019,33082,33145,33208,33272,33335,33398,33461, 33525,33588,33652,33715,33779,33843,33906,33970, 34034,34098,34162,34225,34289,34354,34418,34482, 34546,34610,34675,34739,34803,34868,34932,34997, 35062,35126,35191,35256,35321,35385,35450,35515, 35580,35646,35711,35776,35841,35907,35972,36037, 36103,36168,36234,36300,36365,36431,36497,36563, 36629,36695,36761,36827,36893,36959,37026,37092, 37158,37225,37291,37358,37425,37491,37558,37625, 37692,37759,37826,37893,37960,38027,38094,38161, 38229,38296,38364,38431,38499,38566,38634,38702, 38770,38837,38905,38973,39042,39110,39178,39246, 39314,39383,39451,39520,39588,39657,39726,39794, 39863,39932,40001,40070,40139,40208,40278,40347, 40416,40486,40555,40625,40694,40764,40834,40904, 40973,41043,41113,41184,41254,41324,41394,41465, 41535,41605,41676,41747,41817,41888,41959,42030, 42101,42172,42243,42314,42385,42457,42528,42600, 42671,42743,42814,42886,42958,43030,43102,43174, 43246,43318,43390,43463,43535,43608,43680,43753, 43826,43898,43971,44044,44117,44190,44263,44337, 44410,44483,44557,44630,44704,44778,44851,44925, 44999,45073,45147,45221,45296,45370,45444,45519, 45593,45668,45743,45818,45892,45967,46042,46118, 46193,46268,46343,46419,46494,46570,46646,46721, 46797,46873,46949,47025,47102,47178,47254,47331, 47407,47484,47560,47637,47714,47791,47868,47945, 48022,48100,48177,48255,48332,48410,48488,48565, 48643,48721,48799,48878,48956,49034,49113,49191, 49270,49349,49427,49506,49585,49664,49744,49823, 49902,49982,50061,50141,50221,50300,50380,50460, 50540,50621,50701,50781,50862,50942,51023,51104, 51185,51266,51347,51428,51509,51591,51672,51754, 51835,51917,51999,52081,52163,52245,52327,52410, 52492,52575,52657,52740,52823,52906,52989,53072, 53156,53239,53322,53406,53490,53574,53657,53741, 53826,53910,53994,54079,54163,54248,54333,54417, 54502,54587,54673,54758,54843,54929,55015,55100, 55186,55272,55358,55444,55531,55617,55704,55790, 55877,55964,56051,56138,56225,56312,56400,56487, 56575,56663,56751,56839,56927,57015,57104,57192, 57281,57369,57458,57547,57636,57725,57815,57904, 57994,58083,58173,58263,58353,58443,58534,58624, 58715,58805,58896,58987,59078,59169,59261,59352, 59444,59535,59627,59719,59811,59903,59996,60088, 60181,60273,60366,60459,60552,60646,60739,60833, 60926,61020,61114,61208,61302,61396,61491,61585, 61680,61775,61870,61965,62060,62156,62251,62347, 62443,62539,62635,62731,62828,62924,63021,63118, 63215,63312,63409,63506,63604,63702,63799,63897, 63996,64094,64192,64291,64389,64488,64587,64687, 64786,64885,64985,65085,65185,65285,65385,65485, 65586,65686,65787,65888,65989,66091,66192,66294, 66396,66498,66600,66702,66804,66907,67010,67113, 67216,67319,67422,67526,67629,67733,67837,67942, 68046,68151,68255,68360,68465,68570,68676,68781, 68887,68993,69099,69205,69312,69418,69525,69632, 69739,69846,69954,70061,70169,70277,70385,70494, 70602,70711,70820,70929,71038,71147,71257,71367, 71477,71587,71697,71808,71918,72029,72140,72252, 72363,72475,72587,72699,72811,72923,73036,73149, 73262,73375,73488,73602,73715,73829,73944,74058, 74172,74287,74402,74517,74633,74748,74864,74980, 75096,75213,75329,75446,75563,75680,75797,75915, 76033,76151,76269,76388,76506,76625,76744,76864, 76983,77103,77223,77343,77463,77584,77705,77826, 77947,78068,78190,78312,78434,78557,78679,78802, 78925,79048,79172,79296,79420,79544,79668,79793, 79918,80043,80168,80294,80420,80546,80672,80799, 80925,81053,81180,81307,81435,81563,81691,81820, 81949,82078,82207,82336,82466,82596,82726,82857, 82987,83118,83250,83381,83513,83645,83777,83910, 84043,84176,84309,84443,84576,84710,84845,84980, 85114,85250,85385,85521,85657,85793,85930,86066, 86204,86341,86479,86616,86755,86893,87032,87171, 87310,87450,87590,87730,87871,88011,88152,88294, 88435,88577,88720,88862,89005,89148,89292,89435, 89579,89724,89868,90013,90158,90304,90450,90596, 90742,90889,91036,91184,91332,91480,91628,91777, 91926,92075,92225,92375,92525,92675,92826,92978, 93129,93281,93434,93586,93739,93892,94046,94200, 94354,94509,94664,94819,94975,95131,95287,95444, 95601,95758,95916,96074,96233,96391,96551,96710, 96870,97030,97191,97352,97513,97675,97837,98000, 98163,98326,98489,98653,98818,98982,99148,99313, 99479,99645,99812,99979,100146,100314,100482,100651, 100820,100990,101159,101330,101500,101671,101843,102015, 102187,102360,102533,102706,102880,103054,103229,103404, 103580,103756,103933,104109,104287,104465,104643,104821, 105000,105180,105360,105540,105721,105902,106084,106266, 106449,106632,106816,107000,107184,107369,107555,107741, 107927,108114,108301,108489,108677,108866,109055,109245, 109435,109626,109817,110008,110200,110393,110586,110780, 110974,111169,111364,111560,111756,111952,112150,112347, 112546,112744,112944,113143,113344,113545,113746,113948, 114151,114354,114557,114761,114966,115171,115377,115583, 115790,115998,116206,116414,116623,116833,117044,117254, 117466,117678,117891,118104,118318,118532,118747,118963, 119179,119396,119613,119831,120050,120269,120489,120709, 120930,121152,121374,121597,121821,122045,122270,122496, 122722,122949,123176,123404,123633,123863,124093,124324, 124555,124787,125020,125254,125488,125723,125959,126195, 126432,126669,126908,127147,127387,127627,127869,128111, 128353,128597,128841,129086,129332,129578,129825,130073, 130322,130571,130821,131072,131324,131576,131830,132084, 132339,132594,132851,133108,133366,133625,133884,134145, 134406,134668,134931,135195,135459,135725,135991,136258, 136526,136795,137065,137335,137607,137879,138152,138426, 138701,138977,139254,139532,139810,140090,140370,140651, 140934,141217,141501,141786,142072,142359,142647,142936, 143226,143517,143808,144101,144395,144690,144986,145282, 145580,145879,146179,146480,146782,147084,147388,147693, 148000,148307,148615,148924,149235,149546,149859,150172, 150487,150803,151120,151438,151757,152077,152399,152722, 153045,153370,153697,154024,154352,154682,155013,155345, 155678,156013,156349,156686,157024,157363,157704,158046, 158389,158734,159079,159427,159775,160125,160476,160828, 161182,161537,161893,162251,162610,162970,163332,163695, 164060,164426,164793,165162,165532,165904,166277,166651, 167027,167405,167784,168164,168546,168930,169315,169701, 170089,170479,170870,171263,171657,172053,172451,172850, 173251,173653,174057,174463,174870,175279,175690,176102, 176516,176932,177349,177769,178190,178612,179037,179463, 179891,180321,180753,181186,181622,182059,182498,182939, 183382,183827,184274,184722,185173,185625,186080,186536, 186995,187455,187918,188382,188849,189318,189789,190261, 190736,191213,191693,192174,192658,193143,193631,194122, 194614,195109,195606,196105,196606,197110,197616,198125, 198636,199149,199664,200182,200703,201226,201751,202279, 202809,203342,203878,204416,204956,205500,206045,206594, 207145,207699,208255,208815,209376,209941,210509,211079, 211652,212228,212807,213389,213973,214561,215151,215745, 216341,216941,217544,218149,218758,219370,219985,220603, 221225,221849,222477,223108,223743,224381,225022,225666, 226314,226966,227621,228279,228941,229606,230275,230948, 231624,232304,232988,233676,234367,235062,235761,236463, 237170,237881,238595,239314,240036,240763,241493,242228, 242967,243711,244458,245210,245966,246727,247492,248261, 249035,249813,250596,251384,252176,252973,253774,254581, 255392,256208,257029,257855,258686,259522,260363,261209, 262060,262917,263779,264646,265519,266397,267280,268169, 269064,269965,270871,271782,272700,273624,274553,275489, 276430,277378,278332,279292,280258,281231,282210,283195, 284188,285186,286192,287204,288223,289249,290282,291322, 292369,293423,294485,295554,296630,297714,298805,299904, 301011,302126,303248,304379,305517,306664,307819,308983, 310154,311335,312524,313721,314928,316143,317368,318601, 319844,321097,322358,323629,324910,326201,327502,328812, 330133,331464,332805,334157,335519,336892,338276,339671, 341078,342495,343924,345364,346816,348280,349756,351244, 352744,354257,355783,357321,358872,360436,362013,363604, 365208,366826,368459,370105,371765,373440,375130,376835, 378555,380290,382040,383807,385589,387387,389202,391034, 392882,394747,396630,398530,400448,402384,404338,406311, 408303,410314,412344,414395,416465,418555,420666,422798, 424951,427125,429321,431540,433781,436045,438332,440643, 442978,445337,447720,450129,452564,455024,457511,460024, 462565,465133,467730,470355,473009,475692,478406,481150, 483925,486732,489571,492443,495348,498287,501261,504269, 507313,510394,513512,516667,519861,523094,526366,529680, 533034,536431,539870,543354,546881,550455,554074,557741, 561456,565221,569035,572901,576818,580789,584815,588896, 593033,597229,601483,605798,610174,614613,619117,623686, 628323,633028,637803,642651,647572,652568,657640,662792, 668024,673338,678737,684223,689797,695462,701219,707072, 713023,719074,725227,731486,737853,744331,750922,757631, 764460,771411,778490,785699,793041,800521,808143,815910, 823827,831898,840127,848520,857081,865817,874730,883829, 893117,902602,912289,922186,932298,942633,953199,964003, 975054,986361,997931,1009774,1021901,1034322,1047046,1060087, 1073455,1087164,1101225,1115654,1130465,1145673,1161294,1177345, 1193846,1210813,1228269,1246234,1264730,1283783,1303416,1323658, 1344537,1366084,1388330,1411312,1435065,1459630,1485049,1511367, 1538632,1566898,1596220,1626658,1658278,1691149,1725348,1760956, 1798063,1836758,1877161,1919378,1963536,2009771,2058233,2109087, 2162516,2218719,2277919,2340362,2406322,2476104,2550052,2628549, 2712030,2800983,2895966,2997613,3106651,3223918,3350381,3487165, 3635590,3797206,3973855,4167737,4381502,4618375,4882318,5178251, 5512368,5892567,6329090,6835455,7429880,8137527,8994149,10052327, 11392683,13145455,15535599,18988036,24413316,34178904,56965752,170910304 }; int finesine[10240] = { 25,75,125,175,226,276,326,376, 427,477,527,578,628,678,728,779, 829,879,929,980,1030,1080,1130,1181, 1231,1281,1331,1382,1432,1482,1532,1583, 1633,1683,1733,1784,1834,1884,1934,1985, 2035,2085,2135,2186,2236,2286,2336,2387, 2437,2487,2537,2587,2638,2688,2738,2788, 2839,2889,2939,2989,3039,3090,3140,3190, 3240,3291,3341,3391,3441,3491,3541,3592, 3642,3692,3742,3792,3843,3893,3943,3993, 4043,4093,4144,4194,4244,4294,4344,4394, 4445,4495,4545,4595,4645,4695,4745,4796, 4846,4896,4946,4996,5046,5096,5146,5197, 5247,5297,5347,5397,5447,5497,5547,5597, 5647,5697,5748,5798,5848,5898,5948,5998, 6048,6098,6148,6198,6248,6298,6348,6398, 6448,6498,6548,6598,6648,6698,6748,6798, 6848,6898,6948,6998,7048,7098,7148,7198, 7248,7298,7348,7398,7448,7498,7548,7598, 7648,7697,7747,7797,7847,7897,7947,7997, 8047,8097,8147,8196,8246,8296,8346,8396, 8446,8496,8545,8595,8645,8695,8745,8794, 8844,8894,8944,8994,9043,9093,9143,9193, 9243,9292,9342,9392,9442,9491,9541,9591, 9640,9690,9740,9790,9839,9889,9939,9988, 10038,10088,10137,10187,10237,10286,10336,10386, 10435,10485,10534,10584,10634,10683,10733,10782, 10832,10882,10931,10981,11030,11080,11129,11179, 11228,11278,11327,11377,11426,11476,11525,11575, 11624,11674,11723,11773,11822,11872,11921,11970, 12020,12069,12119,12168,12218,12267,12316,12366, 12415,12464,12514,12563,12612,12662,12711,12760, 12810,12859,12908,12957,13007,13056,13105,13154, 13204,13253,13302,13351,13401,13450,13499,13548, 13597,13647,13696,13745,13794,13843,13892,13941, 13990,14040,14089,14138,14187,14236,14285,14334, 14383,14432,14481,14530,14579,14628,14677,14726, 14775,14824,14873,14922,14971,15020,15069,15118, 15167,15215,15264,15313,15362,15411,15460,15509, 15557,15606,15655,15704,15753,15802,15850,15899, 15948,15997,16045,16094,16143,16191,16240,16289, 16338,16386,16435,16484,16532,16581,16629,16678, 16727,16775,16824,16872,16921,16970,17018,17067, 17115,17164,17212,17261,17309,17358,17406,17455, 17503,17551,17600,17648,17697,17745,17793,17842, 17890,17939,17987,18035,18084,18132,18180,18228, 18277,18325,18373,18421,18470,18518,18566,18614, 18663,18711,18759,18807,18855,18903,18951,19000, 19048,19096,19144,19192,19240,19288,19336,19384, 19432,19480,19528,19576,19624,19672,19720,19768, 19816,19864,19912,19959,20007,20055,20103,20151, 20199,20246,20294,20342,20390,20438,20485,20533, 20581,20629,20676,20724,20772,20819,20867,20915, 20962,21010,21057,21105,21153,21200,21248,21295, 21343,21390,21438,21485,21533,21580,21628,21675, 21723,21770,21817,21865,21912,21960,22007,22054, 22102,22149,22196,22243,22291,22338,22385,22433, 22480,22527,22574,22621,22668,22716,22763,22810, 22857,22904,22951,22998,23045,23092,23139,23186, 23233,23280,23327,23374,23421,23468,23515,23562, 23609,23656,23703,23750,23796,23843,23890,23937, 23984,24030,24077,24124,24171,24217,24264,24311, 24357,24404,24451,24497,24544,24591,24637,24684, 24730,24777,24823,24870,24916,24963,25009,25056, 25102,25149,25195,25241,25288,25334,25381,25427, 25473,25520,25566,25612,25658,25705,25751,25797, 25843,25889,25936,25982,26028,26074,26120,26166, 26212,26258,26304,26350,26396,26442,26488,26534, 26580,26626,26672,26718,26764,26810,26856,26902, 26947,26993,27039,27085,27131,27176,27222,27268, 27313,27359,27405,27450,27496,27542,27587,27633, 27678,27724,27770,27815,27861,27906,27952,27997, 28042,28088,28133,28179,28224,28269,28315,28360, 28405,28451,28496,28541,28586,28632,28677,28722, 28767,28812,28858,28903,28948,28993,29038,29083, 29128,29173,29218,29263,29308,29353,29398,29443, 29488,29533,29577,29622,29667,29712,29757,29801, 29846,29891,29936,29980,30025,30070,30114,30159, 30204,30248,30293,30337,30382,30426,30471,30515, 30560,30604,30649,30693,30738,30782,30826,30871, 30915,30959,31004,31048,31092,31136,31181,31225, 31269,31313,31357,31402,31446,31490,31534,31578, 31622,31666,31710,31754,31798,31842,31886,31930, 31974,32017,32061,32105,32149,32193,32236,32280, 32324,32368,32411,32455,32499,32542,32586,32630, 32673,32717,32760,32804,32847,32891,32934,32978, 33021,33065,33108,33151,33195,33238,33281,33325, 33368,33411,33454,33498,33541,33584,33627,33670, 33713,33756,33799,33843,33886,33929,33972,34015, 34057,34100,34143,34186,34229,34272,34315,34358, 34400,34443,34486,34529,34571,34614,34657,34699, 34742,34785,34827,34870,34912,34955,34997,35040, 35082,35125,35167,35210,35252,35294,35337,35379, 35421,35464,35506,35548,35590,35633,35675,35717, 35759,35801,35843,35885,35927,35969,36011,36053, 36095,36137,36179,36221,36263,36305,36347,36388, 36430,36472,36514,36555,36597,36639,36681,36722, 36764,36805,36847,36889,36930,36972,37013,37055, 37096,37137,37179,37220,37262,37303,37344,37386, 37427,37468,37509,37551,37592,37633,37674,37715, 37756,37797,37838,37879,37920,37961,38002,38043, 38084,38125,38166,38207,38248,38288,38329,38370, 38411,38451,38492,38533,38573,38614,38655,38695, 38736,38776,38817,38857,38898,38938,38979,39019, 39059,39100,39140,39180,39221,39261,39301,39341, 39382,39422,39462,39502,39542,39582,39622,39662, 39702,39742,39782,39822,39862,39902,39942,39982, 40021,40061,40101,40141,40180,40220,40260,40300, 40339,40379,40418,40458,40497,40537,40576,40616, 40655,40695,40734,40773,40813,40852,40891,40931, 40970,41009,41048,41087,41127,41166,41205,41244, 41283,41322,41361,41400,41439,41478,41517,41556, 41595,41633,41672,41711,41750,41788,41827,41866, 41904,41943,41982,42020,42059,42097,42136,42174, 42213,42251,42290,42328,42366,42405,42443,42481, 42520,42558,42596,42634,42672,42711,42749,42787, 42825,42863,42901,42939,42977,43015,43053,43091, 43128,43166,43204,43242,43280,43317,43355,43393, 43430,43468,43506,43543,43581,43618,43656,43693, 43731,43768,43806,43843,43880,43918,43955,43992, 44029,44067,44104,44141,44178,44215,44252,44289, 44326,44363,44400,44437,44474,44511,44548,44585, 44622,44659,44695,44732,44769,44806,44842,44879, 44915,44952,44989,45025,45062,45098,45135,45171, 45207,45244,45280,45316,45353,45389,45425,45462, 45498,45534,45570,45606,45642,45678,45714,45750, 45786,45822,45858,45894,45930,45966,46002,46037, 46073,46109,46145,46180,46216,46252,46287,46323, 46358,46394,46429,46465,46500,46536,46571,46606, 46642,46677,46712,46747,46783,46818,46853,46888, 46923,46958,46993,47028,47063,47098,47133,47168, 47203,47238,47273,47308,47342,47377,47412,47446, 47481,47516,47550,47585,47619,47654,47688,47723, 47757,47792,47826,47860,47895,47929,47963,47998, 48032,48066,48100,48134,48168,48202,48237,48271, 48305,48338,48372,48406,48440,48474,48508,48542, 48575,48609,48643,48676,48710,48744,48777,48811, 48844,48878,48911,48945,48978,49012,49045,49078, 49112,49145,49178,49211,49244,49278,49311,49344, 49377,49410,49443,49476,49509,49542,49575,49608, 49640,49673,49706,49739,49771,49804,49837,49869, 49902,49935,49967,50000,50032,50065,50097,50129, 50162,50194,50226,50259,50291,50323,50355,50387, 50420,50452,50484,50516,50548,50580,50612,50644, 50675,50707,50739,50771,50803,50834,50866,50898, 50929,50961,50993,51024,51056,51087,51119,51150, 51182,51213,51244,51276,51307,51338,51369,51401, 51432,51463,51494,51525,51556,51587,51618,51649, 51680,51711,51742,51773,51803,51834,51865,51896, 51926,51957,51988,52018,52049,52079,52110,52140, 52171,52201,52231,52262,52292,52322,52353,52383, 52413,52443,52473,52503,52534,52564,52594,52624, 52653,52683,52713,52743,52773,52803,52832,52862, 52892,52922,52951,52981,53010,53040,53069,53099, 53128,53158,53187,53216,53246,53275,53304,53334, 53363,53392,53421,53450,53479,53508,53537,53566, 53595,53624,53653,53682,53711,53739,53768,53797, 53826,53854,53883,53911,53940,53969,53997,54026, 54054,54082,54111,54139,54167,54196,54224,54252, 54280,54308,54337,54365,54393,54421,54449,54477, 54505,54533,54560,54588,54616,54644,54672,54699, 54727,54755,54782,54810,54837,54865,54892,54920, 54947,54974,55002,55029,55056,55084,55111,55138, 55165,55192,55219,55246,55274,55300,55327,55354, 55381,55408,55435,55462,55489,55515,55542,55569, 55595,55622,55648,55675,55701,55728,55754,55781, 55807,55833,55860,55886,55912,55938,55965,55991, 56017,56043,56069,56095,56121,56147,56173,56199, 56225,56250,56276,56302,56328,56353,56379,56404, 56430,56456,56481,56507,56532,56557,56583,56608, 56633,56659,56684,56709,56734,56760,56785,56810, 56835,56860,56885,56910,56935,56959,56984,57009, 57034,57059,57083,57108,57133,57157,57182,57206, 57231,57255,57280,57304,57329,57353,57377,57402, 57426,57450,57474,57498,57522,57546,57570,57594, 57618,57642,57666,57690,57714,57738,57762,57785, 57809,57833,57856,57880,57903,57927,57950,57974, 57997,58021,58044,58067,58091,58114,58137,58160, 58183,58207,58230,58253,58276,58299,58322,58345, 58367,58390,58413,58436,58459,58481,58504,58527, 58549,58572,58594,58617,58639,58662,58684,58706, 58729,58751,58773,58795,58818,58840,58862,58884, 58906,58928,58950,58972,58994,59016,59038,59059, 59081,59103,59125,59146,59168,59190,59211,59233, 59254,59276,59297,59318,59340,59361,59382,59404, 59425,59446,59467,59488,59509,59530,59551,59572, 59593,59614,59635,59656,59677,59697,59718,59739, 59759,59780,59801,59821,59842,59862,59883,59903, 59923,59944,59964,59984,60004,60025,60045,60065, 60085,60105,60125,60145,60165,60185,60205,60225, 60244,60264,60284,60304,60323,60343,60363,60382, 60402,60421,60441,60460,60479,60499,60518,60537, 60556,60576,60595,60614,60633,60652,60671,60690, 60709,60728,60747,60766,60785,60803,60822,60841, 60859,60878,60897,60915,60934,60952,60971,60989, 61007,61026,61044,61062,61081,61099,61117,61135, 61153,61171,61189,61207,61225,61243,61261,61279, 61297,61314,61332,61350,61367,61385,61403,61420, 61438,61455,61473,61490,61507,61525,61542,61559, 61577,61594,61611,61628,61645,61662,61679,61696, 61713,61730,61747,61764,61780,61797,61814,61831, 61847,61864,61880,61897,61913,61930,61946,61963, 61979,61995,62012,62028,62044,62060,62076,62092, 62108,62125,62141,62156,62172,62188,62204,62220, 62236,62251,62267,62283,62298,62314,62329,62345, 62360,62376,62391,62407,62422,62437,62453,62468, 62483,62498,62513,62528,62543,62558,62573,62588, 62603,62618,62633,62648,62662,62677,62692,62706, 62721,62735,62750,62764,62779,62793,62808,62822, 62836,62850,62865,62879,62893,62907,62921,62935, 62949,62963,62977,62991,63005,63019,63032,63046, 63060,63074,63087,63101,63114,63128,63141,63155, 63168,63182,63195,63208,63221,63235,63248,63261, 63274,63287,63300,63313,63326,63339,63352,63365, 63378,63390,63403,63416,63429,63441,63454,63466, 63479,63491,63504,63516,63528,63541,63553,63565, 63578,63590,63602,63614,63626,63638,63650,63662, 63674,63686,63698,63709,63721,63733,63745,63756, 63768,63779,63791,63803,63814,63825,63837,63848, 63859,63871,63882,63893,63904,63915,63927,63938, 63949,63960,63971,63981,63992,64003,64014,64025, 64035,64046,64057,64067,64078,64088,64099,64109, 64120,64130,64140,64151,64161,64171,64181,64192, 64202,64212,64222,64232,64242,64252,64261,64271, 64281,64291,64301,64310,64320,64330,64339,64349, 64358,64368,64377,64387,64396,64405,64414,64424, 64433,64442,64451,64460,64469,64478,64487,64496, 64505,64514,64523,64532,64540,64549,64558,64566, 64575,64584,64592,64601,64609,64617,64626,64634, 64642,64651,64659,64667,64675,64683,64691,64699, 64707,64715,64723,64731,64739,64747,64754,64762, 64770,64777,64785,64793,64800,64808,64815,64822, 64830,64837,64844,64852,64859,64866,64873,64880, 64887,64895,64902,64908,64915,64922,64929,64936, 64943,64949,64956,64963,64969,64976,64982,64989, 64995,65002,65008,65015,65021,65027,65033,65040, 65046,65052,65058,65064,65070,65076,65082,65088, 65094,65099,65105,65111,65117,65122,65128,65133, 65139,65144,65150,65155,65161,65166,65171,65177, 65182,65187,65192,65197,65202,65207,65212,65217, 65222,65227,65232,65237,65242,65246,65251,65256, 65260,65265,65270,65274,65279,65283,65287,65292, 65296,65300,65305,65309,65313,65317,65321,65325, 65329,65333,65337,65341,65345,65349,65352,65356, 65360,65363,65367,65371,65374,65378,65381,65385, 65388,65391,65395,65398,65401,65404,65408,65411, 65414,65417,65420,65423,65426,65429,65431,65434, 65437,65440,65442,65445,65448,65450,65453,65455, 65458,65460,65463,65465,65467,65470,65472,65474, 65476,65478,65480,65482,65484,65486,65488,65490, 65492,65494,65496,65497,65499,65501,65502,65504, 65505,65507,65508,65510,65511,65513,65514,65515, 65516,65518,65519,65520,65521,65522,65523,65524, 65525,65526,65527,65527,65528,65529,65530,65530, 65531,65531,65532,65532,65533,65533,65534,65534, 65534,65535,65535,65535,65535,65535,65535,65535, 65535,65535,65535,65535,65535,65535,65535,65534, 65534,65534,65533,65533,65532,65532,65531,65531, 65530,65530,65529,65528,65527,65527,65526,65525, 65524,65523,65522,65521,65520,65519,65518,65516, 65515,65514,65513,65511,65510,65508,65507,65505, 65504,65502,65501,65499,65497,65496,65494,65492, 65490,65488,65486,65484,65482,65480,65478,65476, 65474,65472,65470,65467,65465,65463,65460,65458, 65455,65453,65450,65448,65445,65442,65440,65437, 65434,65431,65429,65426,65423,65420,65417,65414, 65411,65408,65404,65401,65398,65395,65391,65388, 65385,65381,65378,65374,65371,65367,65363,65360, 65356,65352,65349,65345,65341,65337,65333,65329, 65325,65321,65317,65313,65309,65305,65300,65296, 65292,65287,65283,65279,65274,65270,65265,65260, 65256,65251,65246,65242,65237,65232,65227,65222, 65217,65212,65207,65202,65197,65192,65187,65182, 65177,65171,65166,65161,65155,65150,65144,65139, 65133,65128,65122,65117,65111,65105,65099,65094, 65088,65082,65076,65070,65064,65058,65052,65046, 65040,65033,65027,65021,65015,65008,65002,64995, 64989,64982,64976,64969,64963,64956,64949,64943, 64936,64929,64922,64915,64908,64902,64895,64887, 64880,64873,64866,64859,64852,64844,64837,64830, 64822,64815,64808,64800,64793,64785,64777,64770, 64762,64754,64747,64739,64731,64723,64715,64707, 64699,64691,64683,64675,64667,64659,64651,64642, 64634,64626,64617,64609,64600,64592,64584,64575, 64566,64558,64549,64540,64532,64523,64514,64505, 64496,64487,64478,64469,64460,64451,64442,64433, 64424,64414,64405,64396,64387,64377,64368,64358, 64349,64339,64330,64320,64310,64301,64291,64281, 64271,64261,64252,64242,64232,64222,64212,64202, 64192,64181,64171,64161,64151,64140,64130,64120, 64109,64099,64088,64078,64067,64057,64046,64035, 64025,64014,64003,63992,63981,63971,63960,63949, 63938,63927,63915,63904,63893,63882,63871,63859, 63848,63837,63825,63814,63803,63791,63779,63768, 63756,63745,63733,63721,63709,63698,63686,63674, 63662,63650,63638,63626,63614,63602,63590,63578, 63565,63553,63541,63528,63516,63504,63491,63479, 63466,63454,63441,63429,63416,63403,63390,63378, 63365,63352,63339,63326,63313,63300,63287,63274, 63261,63248,63235,63221,63208,63195,63182,63168, 63155,63141,63128,63114,63101,63087,63074,63060, 63046,63032,63019,63005,62991,62977,62963,62949, 62935,62921,62907,62893,62879,62865,62850,62836, 62822,62808,62793,62779,62764,62750,62735,62721, 62706,62692,62677,62662,62648,62633,62618,62603, 62588,62573,62558,62543,62528,62513,62498,62483, 62468,62453,62437,62422,62407,62391,62376,62360, 62345,62329,62314,62298,62283,62267,62251,62236, 62220,62204,62188,62172,62156,62141,62125,62108, 62092,62076,62060,62044,62028,62012,61995,61979, 61963,61946,61930,61913,61897,61880,61864,61847, 61831,61814,61797,61780,61764,61747,61730,61713, 61696,61679,61662,61645,61628,61611,61594,61577, 61559,61542,61525,61507,61490,61473,61455,61438, 61420,61403,61385,61367,61350,61332,61314,61297, 61279,61261,61243,61225,61207,61189,61171,61153, 61135,61117,61099,61081,61062,61044,61026,61007, 60989,60971,60952,60934,60915,60897,60878,60859, 60841,60822,60803,60785,60766,60747,60728,60709, 60690,60671,60652,60633,60614,60595,60576,60556, 60537,60518,60499,60479,60460,60441,60421,60402, 60382,60363,60343,60323,60304,60284,60264,60244, 60225,60205,60185,60165,60145,60125,60105,60085, 60065,60045,60025,60004,59984,59964,59944,59923, 59903,59883,59862,59842,59821,59801,59780,59759, 59739,59718,59697,59677,59656,59635,59614,59593, 59572,59551,59530,59509,59488,59467,59446,59425, 59404,59382,59361,59340,59318,59297,59276,59254, 59233,59211,59190,59168,59146,59125,59103,59081, 59059,59038,59016,58994,58972,58950,58928,58906, 58884,58862,58840,58818,58795,58773,58751,58729, 58706,58684,58662,58639,58617,58594,58572,58549, 58527,58504,58481,58459,58436,58413,58390,58367, 58345,58322,58299,58276,58253,58230,58207,58183, 58160,58137,58114,58091,58067,58044,58021,57997, 57974,57950,57927,57903,57880,57856,57833,57809, 57785,57762,57738,57714,57690,57666,57642,57618, 57594,57570,57546,57522,57498,57474,57450,57426, 57402,57377,57353,57329,57304,57280,57255,57231, 57206,57182,57157,57133,57108,57083,57059,57034, 57009,56984,56959,56935,56910,56885,56860,56835, 56810,56785,56760,56734,56709,56684,56659,56633, 56608,56583,56557,56532,56507,56481,56456,56430, 56404,56379,56353,56328,56302,56276,56250,56225, 56199,56173,56147,56121,56095,56069,56043,56017, 55991,55965,55938,55912,55886,55860,55833,55807, 55781,55754,55728,55701,55675,55648,55622,55595, 55569,55542,55515,55489,55462,55435,55408,55381, 55354,55327,55300,55274,55246,55219,55192,55165, 55138,55111,55084,55056,55029,55002,54974,54947, 54920,54892,54865,54837,54810,54782,54755,54727, 54699,54672,54644,54616,54588,54560,54533,54505, 54477,54449,54421,54393,54365,54337,54308,54280, 54252,54224,54196,54167,54139,54111,54082,54054, 54026,53997,53969,53940,53911,53883,53854,53826, 53797,53768,53739,53711,53682,53653,53624,53595, 53566,53537,53508,53479,53450,53421,53392,53363, 53334,53304,53275,53246,53216,53187,53158,53128, 53099,53069,53040,53010,52981,52951,52922,52892, 52862,52832,52803,52773,52743,52713,52683,52653, 52624,52594,52564,52534,52503,52473,52443,52413, 52383,52353,52322,52292,52262,52231,52201,52171, 52140,52110,52079,52049,52018,51988,51957,51926, 51896,51865,51834,51803,51773,51742,51711,51680, 51649,51618,51587,51556,51525,51494,51463,51432, 51401,51369,51338,51307,51276,51244,51213,51182, 51150,51119,51087,51056,51024,50993,50961,50929, 50898,50866,50834,50803,50771,50739,50707,50675, 50644,50612,50580,50548,50516,50484,50452,50420, 50387,50355,50323,50291,50259,50226,50194,50162, 50129,50097,50065,50032,50000,49967,49935,49902, 49869,49837,49804,49771,49739,49706,49673,49640, 49608,49575,49542,49509,49476,49443,49410,49377, 49344,49311,49278,49244,49211,49178,49145,49112, 49078,49045,49012,48978,48945,48911,48878,48844, 48811,48777,48744,48710,48676,48643,48609,48575, 48542,48508,48474,48440,48406,48372,48338,48304, 48271,48237,48202,48168,48134,48100,48066,48032, 47998,47963,47929,47895,47860,47826,47792,47757, 47723,47688,47654,47619,47585,47550,47516,47481, 47446,47412,47377,47342,47308,47273,47238,47203, 47168,47133,47098,47063,47028,46993,46958,46923, 46888,46853,46818,46783,46747,46712,46677,46642, 46606,46571,46536,46500,46465,46429,46394,46358, 46323,46287,46252,46216,46180,46145,46109,46073, 46037,46002,45966,45930,45894,45858,45822,45786, 45750,45714,45678,45642,45606,45570,45534,45498, 45462,45425,45389,45353,45316,45280,45244,45207, 45171,45135,45098,45062,45025,44989,44952,44915, 44879,44842,44806,44769,44732,44695,44659,44622, 44585,44548,44511,44474,44437,44400,44363,44326, 44289,44252,44215,44178,44141,44104,44067,44029, 43992,43955,43918,43880,43843,43806,43768,43731, 43693,43656,43618,43581,43543,43506,43468,43430, 43393,43355,43317,43280,43242,43204,43166,43128, 43091,43053,43015,42977,42939,42901,42863,42825, 42787,42749,42711,42672,42634,42596,42558,42520, 42481,42443,42405,42366,42328,42290,42251,42213, 42174,42136,42097,42059,42020,41982,41943,41904, 41866,41827,41788,41750,41711,41672,41633,41595, 41556,41517,41478,41439,41400,41361,41322,41283, 41244,41205,41166,41127,41088,41048,41009,40970, 40931,40891,40852,40813,40773,40734,40695,40655, 40616,40576,40537,40497,40458,40418,40379,40339, 40300,40260,40220,40180,40141,40101,40061,40021, 39982,39942,39902,39862,39822,39782,39742,39702, 39662,39622,39582,39542,39502,39462,39422,39382, 39341,39301,39261,39221,39180,39140,39100,39059, 39019,38979,38938,38898,38857,38817,38776,38736, 38695,38655,38614,38573,38533,38492,38451,38411, 38370,38329,38288,38248,38207,38166,38125,38084, 38043,38002,37961,37920,37879,37838,37797,37756, 37715,37674,37633,37592,37551,37509,37468,37427, 37386,37344,37303,37262,37220,37179,37137,37096, 37055,37013,36972,36930,36889,36847,36805,36764, 36722,36681,36639,36597,36556,36514,36472,36430, 36388,36347,36305,36263,36221,36179,36137,36095, 36053,36011,35969,35927,35885,35843,35801,35759, 35717,35675,35633,35590,35548,35506,35464,35421, 35379,35337,35294,35252,35210,35167,35125,35082, 35040,34997,34955,34912,34870,34827,34785,34742, 34699,34657,34614,34571,34529,34486,34443,34400, 34358,34315,34272,34229,34186,34143,34100,34057, 34015,33972,33929,33886,33843,33799,33756,33713, 33670,33627,33584,33541,33498,33454,33411,33368, 33325,33281,33238,33195,33151,33108,33065,33021, 32978,32934,32891,32847,32804,32760,32717,32673, 32630,32586,32542,32499,32455,32411,32368,32324, 32280,32236,32193,32149,32105,32061,32017,31974, 31930,31886,31842,31798,31754,31710,31666,31622, 31578,31534,31490,31446,31402,31357,31313,31269, 31225,31181,31136,31092,31048,31004,30959,30915, 30871,30826,30782,30738,30693,30649,30604,30560, 30515,30471,30426,30382,30337,30293,30248,30204, 30159,30114,30070,30025,29980,29936,29891,29846, 29801,29757,29712,29667,29622,29577,29533,29488, 29443,29398,29353,29308,29263,29218,29173,29128, 29083,29038,28993,28948,28903,28858,28812,28767, 28722,28677,28632,28586,28541,28496,28451,28405, 28360,28315,28269,28224,28179,28133,28088,28042, 27997,27952,27906,27861,27815,27770,27724,27678, 27633,27587,27542,27496,27450,27405,27359,27313, 27268,27222,27176,27131,27085,27039,26993,26947, 26902,26856,26810,26764,26718,26672,26626,26580, 26534,26488,26442,26396,26350,26304,26258,26212, 26166,26120,26074,26028,25982,25936,25889,25843, 25797,25751,25705,25658,25612,25566,25520,25473, 25427,25381,25334,25288,25241,25195,25149,25102, 25056,25009,24963,24916,24870,24823,24777,24730, 24684,24637,24591,24544,24497,24451,24404,24357, 24311,24264,24217,24171,24124,24077,24030,23984, 23937,23890,23843,23796,23750,23703,23656,23609, 23562,23515,23468,23421,23374,23327,23280,23233, 23186,23139,23092,23045,22998,22951,22904,22857, 22810,22763,22716,22668,22621,22574,22527,22480, 22433,22385,22338,22291,22243,22196,22149,22102, 22054,22007,21960,21912,21865,21817,21770,21723, 21675,21628,21580,21533,21485,21438,21390,21343, 21295,21248,21200,21153,21105,21057,21010,20962, 20915,20867,20819,20772,20724,20676,20629,20581, 20533,20485,20438,20390,20342,20294,20246,20199, 20151,20103,20055,20007,19959,19912,19864,19816, 19768,19720,19672,19624,19576,19528,19480,19432, 19384,19336,19288,19240,19192,19144,19096,19048, 19000,18951,18903,18855,18807,18759,18711,18663, 18614,18566,18518,18470,18421,18373,18325,18277, 18228,18180,18132,18084,18035,17987,17939,17890, 17842,17793,17745,17697,17648,17600,17551,17503, 17455,17406,17358,17309,17261,17212,17164,17115, 17067,17018,16970,16921,16872,16824,16775,16727, 16678,16629,16581,16532,16484,16435,16386,16338, 16289,16240,16191,16143,16094,16045,15997,15948, 15899,15850,15802,15753,15704,15655,15606,15557, 15509,15460,15411,15362,15313,15264,15215,15167, 15118,15069,15020,14971,14922,14873,14824,14775, 14726,14677,14628,14579,14530,14481,14432,14383, 14334,14285,14236,14187,14138,14089,14040,13990, 13941,13892,13843,13794,13745,13696,13646,13597, 13548,13499,13450,13401,13351,13302,13253,13204, 13154,13105,13056,13007,12957,12908,12859,12810, 12760,12711,12662,12612,12563,12514,12464,12415, 12366,12316,12267,12218,12168,12119,12069,12020, 11970,11921,11872,11822,11773,11723,11674,11624, 11575,11525,11476,11426,11377,11327,11278,11228, 11179,11129,11080,11030,10981,10931,10882,10832, 10782,10733,10683,10634,10584,10534,10485,10435, 10386,10336,10286,10237,10187,10137,10088,10038, 9988,9939,9889,9839,9790,9740,9690,9640, 9591,9541,9491,9442,9392,9342,9292,9243, 9193,9143,9093,9043,8994,8944,8894,8844, 8794,8745,8695,8645,8595,8545,8496,8446, 8396,8346,8296,8246,8196,8147,8097,8047, 7997,7947,7897,7847,7797,7747,7697,7648, 7598,7548,7498,7448,7398,7348,7298,7248, 7198,7148,7098,7048,6998,6948,6898,6848, 6798,6748,6698,6648,6598,6548,6498,6448, 6398,6348,6298,6248,6198,6148,6098,6048, 5998,5948,5898,5848,5798,5748,5697,5647, 5597,5547,5497,5447,5397,5347,5297,5247, 5197,5146,5096,5046,4996,4946,4896,4846, 4796,4745,4695,4645,4595,4545,4495,4445, 4394,4344,4294,4244,4194,4144,4093,4043, 3993,3943,3893,3843,3792,3742,3692,3642, 3592,3541,3491,3441,3391,3341,3291,3240, 3190,3140,3090,3039,2989,2939,2889,2839, 2788,2738,2688,2638,2587,2537,2487,2437, 2387,2336,2286,2236,2186,2135,2085,2035, 1985,1934,1884,1834,1784,1733,1683,1633, 1583,1532,1482,1432,1382,1331,1281,1231, 1181,1130,1080,1030,980,929,879,829, 779,728,678,628,578,527,477,427, 376,326,276,226,175,125,75,25, -25,-75,-125,-175,-226,-276,-326,-376, -427,-477,-527,-578,-628,-678,-728,-779, -829,-879,-929,-980,-1030,-1080,-1130,-1181, -1231,-1281,-1331,-1382,-1432,-1482,-1532,-1583, -1633,-1683,-1733,-1784,-1834,-1884,-1934,-1985, -2035,-2085,-2135,-2186,-2236,-2286,-2336,-2387, -2437,-2487,-2537,-2588,-2638,-2688,-2738,-2788, -2839,-2889,-2939,-2989,-3039,-3090,-3140,-3190, -3240,-3291,-3341,-3391,-3441,-3491,-3541,-3592, -3642,-3692,-3742,-3792,-3843,-3893,-3943,-3993, -4043,-4093,-4144,-4194,-4244,-4294,-4344,-4394, -4445,-4495,-4545,-4595,-4645,-4695,-4745,-4796, -4846,-4896,-4946,-4996,-5046,-5096,-5146,-5197, -5247,-5297,-5347,-5397,-5447,-5497,-5547,-5597, -5647,-5697,-5748,-5798,-5848,-5898,-5948,-5998, -6048,-6098,-6148,-6198,-6248,-6298,-6348,-6398, -6448,-6498,-6548,-6598,-6648,-6698,-6748,-6798, -6848,-6898,-6948,-6998,-7048,-7098,-7148,-7198, -7248,-7298,-7348,-7398,-7448,-7498,-7548,-7598, -7648,-7697,-7747,-7797,-7847,-7897,-7947,-7997, -8047,-8097,-8147,-8196,-8246,-8296,-8346,-8396, -8446,-8496,-8545,-8595,-8645,-8695,-8745,-8794, -8844,-8894,-8944,-8994,-9043,-9093,-9143,-9193, -9243,-9292,-9342,-9392,-9442,-9491,-9541,-9591, -9640,-9690,-9740,-9790,-9839,-9889,-9939,-9988, -10038,-10088,-10137,-10187,-10237,-10286,-10336,-10386, -10435,-10485,-10534,-10584,-10634,-10683,-10733,-10782, -10832,-10882,-10931,-10981,-11030,-11080,-11129,-11179, -11228,-11278,-11327,-11377,-11426,-11476,-11525,-11575, -11624,-11674,-11723,-11773,-11822,-11872,-11921,-11970, -12020,-12069,-12119,-12168,-12218,-12267,-12316,-12366, -12415,-12464,-12514,-12563,-12612,-12662,-12711,-12760, -12810,-12859,-12908,-12957,-13007,-13056,-13105,-13154, -13204,-13253,-13302,-13351,-13401,-13450,-13499,-13548, -13597,-13647,-13696,-13745,-13794,-13843,-13892,-13941, -13990,-14040,-14089,-14138,-14187,-14236,-14285,-14334, -14383,-14432,-14481,-14530,-14579,-14628,-14677,-14726, -14775,-14824,-14873,-14922,-14971,-15020,-15069,-15118, -15167,-15215,-15264,-15313,-15362,-15411,-15460,-15509, -15557,-15606,-15655,-15704,-15753,-15802,-15850,-15899, -15948,-15997,-16045,-16094,-16143,-16191,-16240,-16289, -16338,-16386,-16435,-16484,-16532,-16581,-16629,-16678, -16727,-16775,-16824,-16872,-16921,-16970,-17018,-17067, -17115,-17164,-17212,-17261,-17309,-17358,-17406,-17455, -17503,-17551,-17600,-17648,-17697,-17745,-17793,-17842, -17890,-17939,-17987,-18035,-18084,-18132,-18180,-18228, -18277,-18325,-18373,-18421,-18470,-18518,-18566,-18614, -18663,-18711,-18759,-18807,-18855,-18903,-18951,-19000, -19048,-19096,-19144,-19192,-19240,-19288,-19336,-19384, -19432,-19480,-19528,-19576,-19624,-19672,-19720,-19768, -19816,-19864,-19912,-19959,-20007,-20055,-20103,-20151, -20199,-20246,-20294,-20342,-20390,-20438,-20485,-20533, -20581,-20629,-20676,-20724,-20772,-20819,-20867,-20915, -20962,-21010,-21057,-21105,-21153,-21200,-21248,-21295, -21343,-21390,-21438,-21485,-21533,-21580,-21628,-21675, -21723,-21770,-21817,-21865,-21912,-21960,-22007,-22054, -22102,-22149,-22196,-22243,-22291,-22338,-22385,-22433, -22480,-22527,-22574,-22621,-22668,-22716,-22763,-22810, -22857,-22904,-22951,-22998,-23045,-23092,-23139,-23186, -23233,-23280,-23327,-23374,-23421,-23468,-23515,-23562, -23609,-23656,-23703,-23750,-23796,-23843,-23890,-23937, -23984,-24030,-24077,-24124,-24171,-24217,-24264,-24311, -24357,-24404,-24451,-24497,-24544,-24591,-24637,-24684, -24730,-24777,-24823,-24870,-24916,-24963,-25009,-25056, -25102,-25149,-25195,-25241,-25288,-25334,-25381,-25427, -25473,-25520,-25566,-25612,-25658,-25705,-25751,-25797, -25843,-25889,-25936,-25982,-26028,-26074,-26120,-26166, -26212,-26258,-26304,-26350,-26396,-26442,-26488,-26534, -26580,-26626,-26672,-26718,-26764,-26810,-26856,-26902, -26947,-26993,-27039,-27085,-27131,-27176,-27222,-27268, -27313,-27359,-27405,-27450,-27496,-27542,-27587,-27633, -27678,-27724,-27770,-27815,-27861,-27906,-27952,-27997, -28042,-28088,-28133,-28179,-28224,-28269,-28315,-28360, -28405,-28451,-28496,-28541,-28586,-28632,-28677,-28722, -28767,-28812,-28858,-28903,-28948,-28993,-29038,-29083, -29128,-29173,-29218,-29263,-29308,-29353,-29398,-29443, -29488,-29533,-29577,-29622,-29667,-29712,-29757,-29801, -29846,-29891,-29936,-29980,-30025,-30070,-30114,-30159, -30204,-30248,-30293,-30337,-30382,-30426,-30471,-30515, -30560,-30604,-30649,-30693,-30738,-30782,-30826,-30871, -30915,-30959,-31004,-31048,-31092,-31136,-31181,-31225, -31269,-31313,-31357,-31402,-31446,-31490,-31534,-31578, -31622,-31666,-31710,-31754,-31798,-31842,-31886,-31930, -31974,-32017,-32061,-32105,-32149,-32193,-32236,-32280, -32324,-32368,-32411,-32455,-32499,-32542,-32586,-32630, -32673,-32717,-32760,-32804,-32847,-32891,-32934,-32978, -33021,-33065,-33108,-33151,-33195,-33238,-33281,-33325, -33368,-33411,-33454,-33498,-33541,-33584,-33627,-33670, -33713,-33756,-33799,-33843,-33886,-33929,-33972,-34015, -34057,-34100,-34143,-34186,-34229,-34272,-34315,-34358, -34400,-34443,-34486,-34529,-34571,-34614,-34657,-34699, -34742,-34785,-34827,-34870,-34912,-34955,-34997,-35040, -35082,-35125,-35167,-35210,-35252,-35294,-35337,-35379, -35421,-35464,-35506,-35548,-35590,-35633,-35675,-35717, -35759,-35801,-35843,-35885,-35927,-35969,-36011,-36053, -36095,-36137,-36179,-36221,-36263,-36305,-36347,-36388, -36430,-36472,-36514,-36555,-36597,-36639,-36681,-36722, -36764,-36805,-36847,-36889,-36930,-36972,-37013,-37055, -37096,-37137,-37179,-37220,-37262,-37303,-37344,-37386, -37427,-37468,-37509,-37551,-37592,-37633,-37674,-37715, -37756,-37797,-37838,-37879,-37920,-37961,-38002,-38043, -38084,-38125,-38166,-38207,-38248,-38288,-38329,-38370, -38411,-38451,-38492,-38533,-38573,-38614,-38655,-38695, -38736,-38776,-38817,-38857,-38898,-38938,-38979,-39019, -39059,-39100,-39140,-39180,-39221,-39261,-39301,-39341, -39382,-39422,-39462,-39502,-39542,-39582,-39622,-39662, -39702,-39742,-39782,-39822,-39862,-39902,-39942,-39982, -40021,-40061,-40101,-40141,-40180,-40220,-40260,-40299, -40339,-40379,-40418,-40458,-40497,-40537,-40576,-40616, -40655,-40695,-40734,-40773,-40813,-40852,-40891,-40931, -40970,-41009,-41048,-41087,-41127,-41166,-41205,-41244, -41283,-41322,-41361,-41400,-41439,-41478,-41517,-41556, -41595,-41633,-41672,-41711,-41750,-41788,-41827,-41866, -41904,-41943,-41982,-42020,-42059,-42097,-42136,-42174, -42213,-42251,-42290,-42328,-42366,-42405,-42443,-42481, -42520,-42558,-42596,-42634,-42672,-42711,-42749,-42787, -42825,-42863,-42901,-42939,-42977,-43015,-43053,-43091, -43128,-43166,-43204,-43242,-43280,-43317,-43355,-43393, -43430,-43468,-43506,-43543,-43581,-43618,-43656,-43693, -43731,-43768,-43806,-43843,-43880,-43918,-43955,-43992, -44029,-44067,-44104,-44141,-44178,-44215,-44252,-44289, -44326,-44363,-44400,-44437,-44474,-44511,-44548,-44585, -44622,-44659,-44695,-44732,-44769,-44806,-44842,-44879, -44915,-44952,-44989,-45025,-45062,-45098,-45135,-45171, -45207,-45244,-45280,-45316,-45353,-45389,-45425,-45462, -45498,-45534,-45570,-45606,-45642,-45678,-45714,-45750, -45786,-45822,-45858,-45894,-45930,-45966,-46002,-46037, -46073,-46109,-46145,-46180,-46216,-46252,-46287,-46323, -46358,-46394,-46429,-46465,-46500,-46536,-46571,-46606, -46642,-46677,-46712,-46747,-46783,-46818,-46853,-46888, -46923,-46958,-46993,-47028,-47063,-47098,-47133,-47168, -47203,-47238,-47273,-47308,-47342,-47377,-47412,-47446, -47481,-47516,-47550,-47585,-47619,-47654,-47688,-47723, -47757,-47792,-47826,-47860,-47895,-47929,-47963,-47998, -48032,-48066,-48100,-48134,-48168,-48202,-48236,-48271, -48304,-48338,-48372,-48406,-48440,-48474,-48508,-48542, -48575,-48609,-48643,-48676,-48710,-48744,-48777,-48811, -48844,-48878,-48911,-48945,-48978,-49012,-49045,-49078, -49112,-49145,-49178,-49211,-49244,-49278,-49311,-49344, -49377,-49410,-49443,-49476,-49509,-49542,-49575,-49608, -49640,-49673,-49706,-49739,-49771,-49804,-49837,-49869, -49902,-49935,-49967,-50000,-50032,-50065,-50097,-50129, -50162,-50194,-50226,-50259,-50291,-50323,-50355,-50387, -50420,-50452,-50484,-50516,-50548,-50580,-50612,-50644, -50675,-50707,-50739,-50771,-50803,-50834,-50866,-50898, -50929,-50961,-50993,-51024,-51056,-51087,-51119,-51150, -51182,-51213,-51244,-51276,-51307,-51338,-51369,-51401, -51432,-51463,-51494,-51525,-51556,-51587,-51618,-51649, -51680,-51711,-51742,-51773,-51803,-51834,-51865,-51896, -51926,-51957,-51988,-52018,-52049,-52079,-52110,-52140, -52171,-52201,-52231,-52262,-52292,-52322,-52353,-52383, -52413,-52443,-52473,-52503,-52534,-52564,-52594,-52624, -52653,-52683,-52713,-52743,-52773,-52803,-52832,-52862, -52892,-52922,-52951,-52981,-53010,-53040,-53069,-53099, -53128,-53158,-53187,-53216,-53246,-53275,-53304,-53334, -53363,-53392,-53421,-53450,-53479,-53508,-53537,-53566, -53595,-53624,-53653,-53682,-53711,-53739,-53768,-53797, -53826,-53854,-53883,-53911,-53940,-53969,-53997,-54026, -54054,-54082,-54111,-54139,-54167,-54196,-54224,-54252, -54280,-54308,-54337,-54365,-54393,-54421,-54449,-54477, -54505,-54533,-54560,-54588,-54616,-54644,-54672,-54699, -54727,-54755,-54782,-54810,-54837,-54865,-54892,-54920, -54947,-54974,-55002,-55029,-55056,-55084,-55111,-55138, -55165,-55192,-55219,-55246,-55274,-55300,-55327,-55354, -55381,-55408,-55435,-55462,-55489,-55515,-55542,-55569, -55595,-55622,-55648,-55675,-55701,-55728,-55754,-55781, -55807,-55833,-55860,-55886,-55912,-55938,-55965,-55991, -56017,-56043,-56069,-56095,-56121,-56147,-56173,-56199, -56225,-56250,-56276,-56302,-56328,-56353,-56379,-56404, -56430,-56456,-56481,-56507,-56532,-56557,-56583,-56608, -56633,-56659,-56684,-56709,-56734,-56760,-56785,-56810, -56835,-56860,-56885,-56910,-56935,-56959,-56984,-57009, -57034,-57059,-57083,-57108,-57133,-57157,-57182,-57206, -57231,-57255,-57280,-57304,-57329,-57353,-57377,-57402, -57426,-57450,-57474,-57498,-57522,-57546,-57570,-57594, -57618,-57642,-57666,-57690,-57714,-57738,-57762,-57785, -57809,-57833,-57856,-57880,-57903,-57927,-57950,-57974, -57997,-58021,-58044,-58067,-58091,-58114,-58137,-58160, -58183,-58207,-58230,-58253,-58276,-58299,-58322,-58345, -58367,-58390,-58413,-58436,-58459,-58481,-58504,-58527, -58549,-58572,-58594,-58617,-58639,-58662,-58684,-58706, -58729,-58751,-58773,-58795,-58818,-58840,-58862,-58884, -58906,-58928,-58950,-58972,-58994,-59016,-59038,-59059, -59081,-59103,-59125,-59146,-59168,-59190,-59211,-59233, -59254,-59276,-59297,-59318,-59340,-59361,-59382,-59404, -59425,-59446,-59467,-59488,-59509,-59530,-59551,-59572, -59593,-59614,-59635,-59656,-59677,-59697,-59718,-59739, -59759,-59780,-59801,-59821,-59842,-59862,-59883,-59903, -59923,-59944,-59964,-59984,-60004,-60025,-60045,-60065, -60085,-60105,-60125,-60145,-60165,-60185,-60205,-60225, -60244,-60264,-60284,-60304,-60323,-60343,-60363,-60382, -60402,-60421,-60441,-60460,-60479,-60499,-60518,-60537, -60556,-60576,-60595,-60614,-60633,-60652,-60671,-60690, -60709,-60728,-60747,-60766,-60785,-60803,-60822,-60841, -60859,-60878,-60897,-60915,-60934,-60952,-60971,-60989, -61007,-61026,-61044,-61062,-61081,-61099,-61117,-61135, -61153,-61171,-61189,-61207,-61225,-61243,-61261,-61279, -61297,-61314,-61332,-61350,-61367,-61385,-61403,-61420, -61438,-61455,-61473,-61490,-61507,-61525,-61542,-61559, -61577,-61594,-61611,-61628,-61645,-61662,-61679,-61696, -61713,-61730,-61747,-61764,-61780,-61797,-61814,-61831, -61847,-61864,-61880,-61897,-61913,-61930,-61946,-61963, -61979,-61995,-62012,-62028,-62044,-62060,-62076,-62092, -62108,-62125,-62141,-62156,-62172,-62188,-62204,-62220, -62236,-62251,-62267,-62283,-62298,-62314,-62329,-62345, -62360,-62376,-62391,-62407,-62422,-62437,-62453,-62468, -62483,-62498,-62513,-62528,-62543,-62558,-62573,-62588, -62603,-62618,-62633,-62648,-62662,-62677,-62692,-62706, -62721,-62735,-62750,-62764,-62779,-62793,-62808,-62822, -62836,-62850,-62865,-62879,-62893,-62907,-62921,-62935, -62949,-62963,-62977,-62991,-63005,-63019,-63032,-63046, -63060,-63074,-63087,-63101,-63114,-63128,-63141,-63155, -63168,-63182,-63195,-63208,-63221,-63235,-63248,-63261, -63274,-63287,-63300,-63313,-63326,-63339,-63352,-63365, -63378,-63390,-63403,-63416,-63429,-63441,-63454,-63466, -63479,-63491,-63504,-63516,-63528,-63541,-63553,-63565, -63578,-63590,-63602,-63614,-63626,-63638,-63650,-63662, -63674,-63686,-63698,-63709,-63721,-63733,-63745,-63756, -63768,-63779,-63791,-63803,-63814,-63825,-63837,-63848, -63859,-63871,-63882,-63893,-63904,-63915,-63927,-63938, -63949,-63960,-63971,-63981,-63992,-64003,-64014,-64025, -64035,-64046,-64057,-64067,-64078,-64088,-64099,-64109, -64120,-64130,-64140,-64151,-64161,-64171,-64181,-64192, -64202,-64212,-64222,-64232,-64242,-64252,-64261,-64271, -64281,-64291,-64301,-64310,-64320,-64330,-64339,-64349, -64358,-64368,-64377,-64387,-64396,-64405,-64414,-64424, -64433,-64442,-64451,-64460,-64469,-64478,-64487,-64496, -64505,-64514,-64523,-64532,-64540,-64549,-64558,-64566, -64575,-64584,-64592,-64601,-64609,-64617,-64626,-64634, -64642,-64651,-64659,-64667,-64675,-64683,-64691,-64699, -64707,-64715,-64723,-64731,-64739,-64747,-64754,-64762, -64770,-64777,-64785,-64793,-64800,-64808,-64815,-64822, -64830,-64837,-64844,-64852,-64859,-64866,-64873,-64880, -64887,-64895,-64902,-64908,-64915,-64922,-64929,-64936, -64943,-64949,-64956,-64963,-64969,-64976,-64982,-64989, -64995,-65002,-65008,-65015,-65021,-65027,-65033,-65040, -65046,-65052,-65058,-65064,-65070,-65076,-65082,-65088, -65094,-65099,-65105,-65111,-65117,-65122,-65128,-65133, -65139,-65144,-65150,-65155,-65161,-65166,-65171,-65177, -65182,-65187,-65192,-65197,-65202,-65207,-65212,-65217, -65222,-65227,-65232,-65237,-65242,-65246,-65251,-65256, -65260,-65265,-65270,-65274,-65279,-65283,-65287,-65292, -65296,-65300,-65305,-65309,-65313,-65317,-65321,-65325, -65329,-65333,-65337,-65341,-65345,-65349,-65352,-65356, -65360,-65363,-65367,-65371,-65374,-65378,-65381,-65385, -65388,-65391,-65395,-65398,-65401,-65404,-65408,-65411, -65414,-65417,-65420,-65423,-65426,-65429,-65431,-65434, -65437,-65440,-65442,-65445,-65448,-65450,-65453,-65455, -65458,-65460,-65463,-65465,-65467,-65470,-65472,-65474, -65476,-65478,-65480,-65482,-65484,-65486,-65488,-65490, -65492,-65494,-65496,-65497,-65499,-65501,-65502,-65504, -65505,-65507,-65508,-65510,-65511,-65513,-65514,-65515, -65516,-65518,-65519,-65520,-65521,-65522,-65523,-65524, -65525,-65526,-65527,-65527,-65528,-65529,-65530,-65530, -65531,-65531,-65532,-65532,-65533,-65533,-65534,-65534, -65534,-65535,-65535,-65535,-65535,-65535,-65535,-65535, -65535,-65535,-65535,-65535,-65535,-65535,-65535,-65534, -65534,-65534,-65533,-65533,-65532,-65532,-65531,-65531, -65530,-65530,-65529,-65528,-65527,-65527,-65526,-65525, -65524,-65523,-65522,-65521,-65520,-65519,-65518,-65516, -65515,-65514,-65513,-65511,-65510,-65508,-65507,-65505, -65504,-65502,-65501,-65499,-65497,-65496,-65494,-65492, -65490,-65488,-65486,-65484,-65482,-65480,-65478,-65476, -65474,-65472,-65470,-65467,-65465,-65463,-65460,-65458, -65455,-65453,-65450,-65448,-65445,-65442,-65440,-65437, -65434,-65431,-65429,-65426,-65423,-65420,-65417,-65414, -65411,-65408,-65404,-65401,-65398,-65395,-65391,-65388, -65385,-65381,-65378,-65374,-65371,-65367,-65363,-65360, -65356,-65352,-65349,-65345,-65341,-65337,-65333,-65329, -65325,-65321,-65317,-65313,-65309,-65305,-65300,-65296, -65292,-65287,-65283,-65279,-65274,-65270,-65265,-65260, -65256,-65251,-65246,-65242,-65237,-65232,-65227,-65222, -65217,-65212,-65207,-65202,-65197,-65192,-65187,-65182, -65177,-65171,-65166,-65161,-65155,-65150,-65144,-65139, -65133,-65128,-65122,-65117,-65111,-65105,-65099,-65094, -65088,-65082,-65076,-65070,-65064,-65058,-65052,-65046, -65040,-65033,-65027,-65021,-65015,-65008,-65002,-64995, -64989,-64982,-64976,-64969,-64963,-64956,-64949,-64943, -64936,-64929,-64922,-64915,-64908,-64902,-64895,-64887, -64880,-64873,-64866,-64859,-64852,-64844,-64837,-64830, -64822,-64815,-64808,-64800,-64793,-64785,-64777,-64770, -64762,-64754,-64747,-64739,-64731,-64723,-64715,-64707, -64699,-64691,-64683,-64675,-64667,-64659,-64651,-64642, -64634,-64626,-64617,-64609,-64601,-64592,-64584,-64575, -64566,-64558,-64549,-64540,-64532,-64523,-64514,-64505, -64496,-64487,-64478,-64469,-64460,-64451,-64442,-64433, -64424,-64414,-64405,-64396,-64387,-64377,-64368,-64358, -64349,-64339,-64330,-64320,-64310,-64301,-64291,-64281, -64271,-64261,-64252,-64242,-64232,-64222,-64212,-64202, -64192,-64181,-64171,-64161,-64151,-64140,-64130,-64120, -64109,-64099,-64088,-64078,-64067,-64057,-64046,-64035, -64025,-64014,-64003,-63992,-63981,-63971,-63960,-63949, -63938,-63927,-63915,-63904,-63893,-63882,-63871,-63859, -63848,-63837,-63825,-63814,-63803,-63791,-63779,-63768, -63756,-63745,-63733,-63721,-63709,-63698,-63686,-63674, -63662,-63650,-63638,-63626,-63614,-63602,-63590,-63578, -63565,-63553,-63541,-63528,-63516,-63504,-63491,-63479, -63466,-63454,-63441,-63429,-63416,-63403,-63390,-63378, -63365,-63352,-63339,-63326,-63313,-63300,-63287,-63274, -63261,-63248,-63235,-63221,-63208,-63195,-63182,-63168, -63155,-63141,-63128,-63114,-63101,-63087,-63074,-63060, -63046,-63032,-63019,-63005,-62991,-62977,-62963,-62949, -62935,-62921,-62907,-62893,-62879,-62865,-62850,-62836, -62822,-62808,-62793,-62779,-62764,-62750,-62735,-62721, -62706,-62692,-62677,-62662,-62648,-62633,-62618,-62603, -62588,-62573,-62558,-62543,-62528,-62513,-62498,-62483, -62468,-62453,-62437,-62422,-62407,-62391,-62376,-62360, -62345,-62329,-62314,-62298,-62283,-62267,-62251,-62236, -62220,-62204,-62188,-62172,-62156,-62141,-62125,-62108, -62092,-62076,-62060,-62044,-62028,-62012,-61995,-61979, -61963,-61946,-61930,-61913,-61897,-61880,-61864,-61847, -61831,-61814,-61797,-61780,-61764,-61747,-61730,-61713, -61696,-61679,-61662,-61645,-61628,-61611,-61594,-61577, -61559,-61542,-61525,-61507,-61490,-61473,-61455,-61438, -61420,-61403,-61385,-61367,-61350,-61332,-61314,-61297, -61279,-61261,-61243,-61225,-61207,-61189,-61171,-61153, -61135,-61117,-61099,-61081,-61062,-61044,-61026,-61007, -60989,-60971,-60952,-60934,-60915,-60897,-60878,-60859, -60841,-60822,-60803,-60785,-60766,-60747,-60728,-60709, -60690,-60671,-60652,-60633,-60614,-60595,-60576,-60556, -60537,-60518,-60499,-60479,-60460,-60441,-60421,-60402, -60382,-60363,-60343,-60323,-60304,-60284,-60264,-60244, -60225,-60205,-60185,-60165,-60145,-60125,-60105,-60085, -60065,-60045,-60025,-60004,-59984,-59964,-59944,-59923, -59903,-59883,-59862,-59842,-59821,-59801,-59780,-59759, -59739,-59718,-59697,-59677,-59656,-59635,-59614,-59593, -59572,-59551,-59530,-59509,-59488,-59467,-59446,-59425, -59404,-59382,-59361,-59340,-59318,-59297,-59276,-59254, -59233,-59211,-59189,-59168,-59146,-59125,-59103,-59081, -59059,-59038,-59016,-58994,-58972,-58950,-58928,-58906, -58884,-58862,-58840,-58818,-58795,-58773,-58751,-58729, -58706,-58684,-58662,-58639,-58617,-58594,-58572,-58549, -58527,-58504,-58481,-58459,-58436,-58413,-58390,-58367, -58345,-58322,-58299,-58276,-58253,-58230,-58207,-58183, -58160,-58137,-58114,-58091,-58067,-58044,-58021,-57997, -57974,-57950,-57927,-57903,-57880,-57856,-57833,-57809, -57785,-57762,-57738,-57714,-57690,-57666,-57642,-57618, -57594,-57570,-57546,-57522,-57498,-57474,-57450,-57426, -57402,-57377,-57353,-57329,-57304,-57280,-57255,-57231, -57206,-57182,-57157,-57133,-57108,-57083,-57059,-57034, -57009,-56984,-56959,-56935,-56910,-56885,-56860,-56835, -56810,-56785,-56760,-56734,-56709,-56684,-56659,-56633, -56608,-56583,-56557,-56532,-56507,-56481,-56456,-56430, -56404,-56379,-56353,-56328,-56302,-56276,-56250,-56225, -56199,-56173,-56147,-56121,-56095,-56069,-56043,-56017, -55991,-55965,-55938,-55912,-55886,-55860,-55833,-55807, -55781,-55754,-55728,-55701,-55675,-55648,-55622,-55595, -55569,-55542,-55515,-55489,-55462,-55435,-55408,-55381, -55354,-55327,-55300,-55274,-55246,-55219,-55192,-55165, -55138,-55111,-55084,-55056,-55029,-55002,-54974,-54947, -54920,-54892,-54865,-54837,-54810,-54782,-54755,-54727, -54699,-54672,-54644,-54616,-54588,-54560,-54533,-54505, -54477,-54449,-54421,-54393,-54365,-54337,-54308,-54280, -54252,-54224,-54196,-54167,-54139,-54111,-54082,-54054, -54026,-53997,-53969,-53940,-53911,-53883,-53854,-53826, -53797,-53768,-53739,-53711,-53682,-53653,-53624,-53595, -53566,-53537,-53508,-53479,-53450,-53421,-53392,-53363, -53334,-53304,-53275,-53246,-53216,-53187,-53158,-53128, -53099,-53069,-53040,-53010,-52981,-52951,-52922,-52892, -52862,-52832,-52803,-52773,-52743,-52713,-52683,-52653, -52624,-52594,-52564,-52534,-52503,-52473,-52443,-52413, -52383,-52353,-52322,-52292,-52262,-52231,-52201,-52171, -52140,-52110,-52079,-52049,-52018,-51988,-51957,-51926, -51896,-51865,-51834,-51803,-51773,-51742,-51711,-51680, -51649,-51618,-51587,-51556,-51525,-51494,-51463,-51432, -51401,-51369,-51338,-51307,-51276,-51244,-51213,-51182, -51150,-51119,-51087,-51056,-51024,-50993,-50961,-50929, -50898,-50866,-50834,-50803,-50771,-50739,-50707,-50675, -50644,-50612,-50580,-50548,-50516,-50484,-50452,-50420, -50387,-50355,-50323,-50291,-50259,-50226,-50194,-50162, -50129,-50097,-50065,-50032,-50000,-49967,-49935,-49902, -49869,-49837,-49804,-49771,-49739,-49706,-49673,-49640, -49608,-49575,-49542,-49509,-49476,-49443,-49410,-49377, -49344,-49311,-49278,-49244,-49211,-49178,-49145,-49112, -49078,-49045,-49012,-48978,-48945,-48911,-48878,-48844, -48811,-48777,-48744,-48710,-48676,-48643,-48609,-48575, -48542,-48508,-48474,-48440,-48406,-48372,-48338,-48305, -48271,-48237,-48202,-48168,-48134,-48100,-48066,-48032, -47998,-47963,-47929,-47895,-47860,-47826,-47792,-47757, -47723,-47688,-47654,-47619,-47585,-47550,-47516,-47481, -47446,-47412,-47377,-47342,-47307,-47273,-47238,-47203, -47168,-47133,-47098,-47063,-47028,-46993,-46958,-46923, -46888,-46853,-46818,-46783,-46747,-46712,-46677,-46642, -46606,-46571,-46536,-46500,-46465,-46429,-46394,-46358, -46323,-46287,-46251,-46216,-46180,-46145,-46109,-46073, -46037,-46002,-45966,-45930,-45894,-45858,-45822,-45786, -45750,-45714,-45678,-45642,-45606,-45570,-45534,-45498, -45462,-45425,-45389,-45353,-45316,-45280,-45244,-45207, -45171,-45135,-45098,-45062,-45025,-44989,-44952,-44915, -44879,-44842,-44806,-44769,-44732,-44695,-44659,-44622, -44585,-44548,-44511,-44474,-44437,-44400,-44363,-44326, -44289,-44252,-44215,-44178,-44141,-44104,-44067,-44029, -43992,-43955,-43918,-43880,-43843,-43806,-43768,-43731, -43693,-43656,-43618,-43581,-43543,-43506,-43468,-43430, -43393,-43355,-43317,-43280,-43242,-43204,-43166,-43128, -43091,-43053,-43015,-42977,-42939,-42901,-42863,-42825, -42787,-42749,-42711,-42672,-42634,-42596,-42558,-42520, -42481,-42443,-42405,-42366,-42328,-42290,-42251,-42213, -42174,-42136,-42097,-42059,-42020,-41982,-41943,-41904, -41866,-41827,-41788,-41750,-41711,-41672,-41633,-41595, -41556,-41517,-41478,-41439,-41400,-41361,-41322,-41283, -41244,-41205,-41166,-41127,-41087,-41048,-41009,-40970, -40931,-40891,-40852,-40813,-40773,-40734,-40695,-40655, -40616,-40576,-40537,-40497,-40458,-40418,-40379,-40339, -40299,-40260,-40220,-40180,-40141,-40101,-40061,-40021, -39982,-39942,-39902,-39862,-39822,-39782,-39742,-39702, -39662,-39622,-39582,-39542,-39502,-39462,-39422,-39382, -39341,-39301,-39261,-39221,-39180,-39140,-39100,-39059, -39019,-38979,-38938,-38898,-38857,-38817,-38776,-38736, -38695,-38655,-38614,-38573,-38533,-38492,-38451,-38411, -38370,-38329,-38288,-38248,-38207,-38166,-38125,-38084, -38043,-38002,-37961,-37920,-37879,-37838,-37797,-37756, -37715,-37674,-37633,-37592,-37550,-37509,-37468,-37427, -37386,-37344,-37303,-37262,-37220,-37179,-37137,-37096, -37055,-37013,-36972,-36930,-36889,-36847,-36805,-36764, -36722,-36681,-36639,-36597,-36556,-36514,-36472,-36430, -36388,-36347,-36305,-36263,-36221,-36179,-36137,-36095, -36053,-36011,-35969,-35927,-35885,-35843,-35801,-35759, -35717,-35675,-35633,-35590,-35548,-35506,-35464,-35421, -35379,-35337,-35294,-35252,-35210,-35167,-35125,-35082, -35040,-34997,-34955,-34912,-34870,-34827,-34785,-34742, -34699,-34657,-34614,-34571,-34529,-34486,-34443,-34400, -34358,-34315,-34272,-34229,-34186,-34143,-34100,-34057, -34015,-33972,-33929,-33886,-33843,-33799,-33756,-33713, -33670,-33627,-33584,-33541,-33498,-33454,-33411,-33368, -33325,-33281,-33238,-33195,-33151,-33108,-33065,-33021, -32978,-32934,-32891,-32847,-32804,-32760,-32717,-32673, -32630,-32586,-32542,-32499,-32455,-32411,-32368,-32324, -32280,-32236,-32193,-32149,-32105,-32061,-32017,-31974, -31930,-31886,-31842,-31798,-31754,-31710,-31666,-31622, -31578,-31534,-31490,-31446,-31402,-31357,-31313,-31269, -31225,-31181,-31136,-31092,-31048,-31004,-30959,-30915, -30871,-30826,-30782,-30738,-30693,-30649,-30604,-30560, -30515,-30471,-30426,-30382,-30337,-30293,-30248,-30204, -30159,-30114,-30070,-30025,-29980,-29936,-29891,-29846, -29801,-29757,-29712,-29667,-29622,-29577,-29533,-29488, -29443,-29398,-29353,-29308,-29263,-29218,-29173,-29128, -29083,-29038,-28993,-28948,-28903,-28858,-28812,-28767, -28722,-28677,-28632,-28586,-28541,-28496,-28451,-28405, -28360,-28315,-28269,-28224,-28179,-28133,-28088,-28042, -27997,-27952,-27906,-27861,-27815,-27770,-27724,-27678, -27633,-27587,-27542,-27496,-27450,-27405,-27359,-27313, -27268,-27222,-27176,-27131,-27085,-27039,-26993,-26947, -26902,-26856,-26810,-26764,-26718,-26672,-26626,-26580, -26534,-26488,-26442,-26396,-26350,-26304,-26258,-26212, -26166,-26120,-26074,-26028,-25982,-25936,-25889,-25843, -25797,-25751,-25705,-25658,-25612,-25566,-25520,-25473, -25427,-25381,-25334,-25288,-25241,-25195,-25149,-25102, -25056,-25009,-24963,-24916,-24870,-24823,-24777,-24730, -24684,-24637,-24591,-24544,-24497,-24451,-24404,-24357, -24311,-24264,-24217,-24171,-24124,-24077,-24030,-23984, -23937,-23890,-23843,-23796,-23750,-23703,-23656,-23609, -23562,-23515,-23468,-23421,-23374,-23327,-23280,-23233, -23186,-23139,-23092,-23045,-22998,-22951,-22904,-22857, -22810,-22763,-22716,-22668,-22621,-22574,-22527,-22480, -22432,-22385,-22338,-22291,-22243,-22196,-22149,-22102, -22054,-22007,-21960,-21912,-21865,-21817,-21770,-21723, -21675,-21628,-21580,-21533,-21485,-21438,-21390,-21343, -21295,-21248,-21200,-21153,-21105,-21057,-21010,-20962, -20915,-20867,-20819,-20772,-20724,-20676,-20629,-20581, -20533,-20485,-20438,-20390,-20342,-20294,-20246,-20199, -20151,-20103,-20055,-20007,-19959,-19912,-19864,-19816, -19768,-19720,-19672,-19624,-19576,-19528,-19480,-19432, -19384,-19336,-19288,-19240,-19192,-19144,-19096,-19048, -19000,-18951,-18903,-18855,-18807,-18759,-18711,-18663, -18614,-18566,-18518,-18470,-18421,-18373,-18325,-18277, -18228,-18180,-18132,-18084,-18035,-17987,-17939,-17890, -17842,-17793,-17745,-17697,-17648,-17600,-17551,-17503, -17455,-17406,-17358,-17309,-17261,-17212,-17164,-17115, -17067,-17018,-16970,-16921,-16872,-16824,-16775,-16727, -16678,-16629,-16581,-16532,-16484,-16435,-16386,-16338, -16289,-16240,-16191,-16143,-16094,-16045,-15997,-15948, -15899,-15850,-15802,-15753,-15704,-15655,-15606,-15557, -15509,-15460,-15411,-15362,-15313,-15264,-15215,-15167, -15118,-15069,-15020,-14971,-14922,-14873,-14824,-14775, -14726,-14677,-14628,-14579,-14530,-14481,-14432,-14383, -14334,-14285,-14236,-14187,-14138,-14089,-14040,-13990, -13941,-13892,-13843,-13794,-13745,-13696,-13647,-13597, -13548,-13499,-13450,-13401,-13351,-13302,-13253,-13204, -13154,-13105,-13056,-13007,-12957,-12908,-12859,-12810, -12760,-12711,-12662,-12612,-12563,-12514,-12464,-12415, -12366,-12316,-12267,-12217,-12168,-12119,-12069,-12020, -11970,-11921,-11872,-11822,-11773,-11723,-11674,-11624, -11575,-11525,-11476,-11426,-11377,-11327,-11278,-11228, -11179,-11129,-11080,-11030,-10981,-10931,-10882,-10832, -10782,-10733,-10683,-10634,-10584,-10534,-10485,-10435, -10386,-10336,-10286,-10237,-10187,-10137,-10088,-10038, -9988,-9939,-9889,-9839,-9790,-9740,-9690,-9640, -9591,-9541,-9491,-9442,-9392,-9342,-9292,-9243, -9193,-9143,-9093,-9043,-8994,-8944,-8894,-8844, -8794,-8745,-8695,-8645,-8595,-8545,-8496,-8446, -8396,-8346,-8296,-8246,-8196,-8147,-8097,-8047, -7997,-7947,-7897,-7847,-7797,-7747,-7697,-7648, -7598,-7548,-7498,-7448,-7398,-7348,-7298,-7248, -7198,-7148,-7098,-7048,-6998,-6948,-6898,-6848, -6798,-6748,-6698,-6648,-6598,-6548,-6498,-6448, -6398,-6348,-6298,-6248,-6198,-6148,-6098,-6048, -5998,-5948,-5898,-5848,-5798,-5747,-5697,-5647, -5597,-5547,-5497,-5447,-5397,-5347,-5297,-5247, -5197,-5146,-5096,-5046,-4996,-4946,-4896,-4846, -4796,-4745,-4695,-4645,-4595,-4545,-4495,-4445, -4394,-4344,-4294,-4244,-4194,-4144,-4093,-4043, -3993,-3943,-3893,-3843,-3792,-3742,-3692,-3642, -3592,-3541,-3491,-3441,-3391,-3341,-3291,-3240, -3190,-3140,-3090,-3039,-2989,-2939,-2889,-2839, -2788,-2738,-2688,-2638,-2588,-2537,-2487,-2437, -2387,-2336,-2286,-2236,-2186,-2135,-2085,-2035, -1985,-1934,-1884,-1834,-1784,-1733,-1683,-1633, -1583,-1532,-1482,-1432,-1382,-1331,-1281,-1231, -1181,-1130,-1080,-1030,-980,-929,-879,-829, -779,-728,-678,-628,-578,-527,-477,-427, -376,-326,-276,-226,-175,-125,-75,-25, 25,75,125,175,226,276,326,376, 427,477,527,578,628,678,728,779, 829,879,929,980,1030,1080,1130,1181, 1231,1281,1331,1382,1432,1482,1532,1583, 1633,1683,1733,1784,1834,1884,1934,1985, 2035,2085,2135,2186,2236,2286,2336,2387, 2437,2487,2537,2587,2638,2688,2738,2788, 2839,2889,2939,2989,3039,3090,3140,3190, 3240,3291,3341,3391,3441,3491,3542,3592, 3642,3692,3742,3792,3843,3893,3943,3993, 4043,4093,4144,4194,4244,4294,4344,4394, 4445,4495,4545,4595,4645,4695,4745,4796, 4846,4896,4946,4996,5046,5096,5146,5197, 5247,5297,5347,5397,5447,5497,5547,5597, 5647,5697,5747,5798,5848,5898,5948,5998, 6048,6098,6148,6198,6248,6298,6348,6398, 6448,6498,6548,6598,6648,6698,6748,6798, 6848,6898,6948,6998,7048,7098,7148,7198, 7248,7298,7348,7398,7448,7498,7548,7598, 7648,7697,7747,7797,7847,7897,7947,7997, 8047,8097,8147,8196,8246,8296,8346,8396, 8446,8496,8545,8595,8645,8695,8745,8794, 8844,8894,8944,8994,9043,9093,9143,9193, 9243,9292,9342,9392,9442,9491,9541,9591, 9640,9690,9740,9790,9839,9889,9939,9988, 10038,10088,10137,10187,10237,10286,10336,10386, 10435,10485,10534,10584,10634,10683,10733,10782, 10832,10882,10931,10981,11030,11080,11129,11179, 11228,11278,11327,11377,11426,11476,11525,11575, 11624,11674,11723,11773,11822,11872,11921,11970, 12020,12069,12119,12168,12218,12267,12316,12366, 12415,12464,12514,12563,12612,12662,12711,12760, 12810,12859,12908,12957,13007,13056,13105,13154, 13204,13253,13302,13351,13401,13450,13499,13548, 13597,13647,13696,13745,13794,13843,13892,13941, 13990,14040,14089,14138,14187,14236,14285,14334, 14383,14432,14481,14530,14579,14628,14677,14726, 14775,14824,14873,14922,14971,15020,15069,15118, 15167,15215,15264,15313,15362,15411,15460,15509, 15557,15606,15655,15704,15753,15802,15850,15899, 15948,15997,16045,16094,16143,16191,16240,16289, 16338,16386,16435,16484,16532,16581,16629,16678, 16727,16775,16824,16872,16921,16970,17018,17067, 17115,17164,17212,17261,17309,17358,17406,17455, 17503,17551,17600,17648,17697,17745,17793,17842, 17890,17939,17987,18035,18084,18132,18180,18228, 18277,18325,18373,18421,18470,18518,18566,18614, 18663,18711,18759,18807,18855,18903,18951,19000, 19048,19096,19144,19192,19240,19288,19336,19384, 19432,19480,19528,19576,19624,19672,19720,19768, 19816,19864,19912,19959,20007,20055,20103,20151, 20199,20246,20294,20342,20390,20438,20485,20533, 20581,20629,20676,20724,20772,20819,20867,20915, 20962,21010,21057,21105,21153,21200,21248,21295, 21343,21390,21438,21485,21533,21580,21628,21675, 21723,21770,21817,21865,21912,21960,22007,22054, 22102,22149,22196,22243,22291,22338,22385,22432, 22480,22527,22574,22621,22668,22716,22763,22810, 22857,22904,22951,22998,23045,23092,23139,23186, 23233,23280,23327,23374,23421,23468,23515,23562, 23609,23656,23703,23750,23796,23843,23890,23937, 23984,24030,24077,24124,24171,24217,24264,24311, 24357,24404,24451,24497,24544,24591,24637,24684, 24730,24777,24823,24870,24916,24963,25009,25056, 25102,25149,25195,25241,25288,25334,25381,25427, 25473,25520,25566,25612,25658,25705,25751,25797, 25843,25889,25936,25982,26028,26074,26120,26166, 26212,26258,26304,26350,26396,26442,26488,26534, 26580,26626,26672,26718,26764,26810,26856,26902, 26947,26993,27039,27085,27131,27176,27222,27268, 27313,27359,27405,27450,27496,27542,27587,27633, 27678,27724,27770,27815,27861,27906,27952,27997, 28042,28088,28133,28179,28224,28269,28315,28360, 28405,28451,28496,28541,28586,28632,28677,28722, 28767,28812,28858,28903,28948,28993,29038,29083, 29128,29173,29218,29263,29308,29353,29398,29443, 29488,29533,29577,29622,29667,29712,29757,29801, 29846,29891,29936,29980,30025,30070,30114,30159, 30204,30248,30293,30337,30382,30427,30471,30516, 30560,30604,30649,30693,30738,30782,30826,30871, 30915,30959,31004,31048,31092,31136,31181,31225, 31269,31313,31357,31402,31446,31490,31534,31578, 31622,31666,31710,31754,31798,31842,31886,31930, 31974,32017,32061,32105,32149,32193,32236,32280, 32324,32368,32411,32455,32499,32542,32586,32630, 32673,32717,32760,32804,32847,32891,32934,32978, 33021,33065,33108,33151,33195,33238,33281,33325, 33368,33411,33454,33498,33541,33584,33627,33670, 33713,33756,33799,33843,33886,33929,33972,34015, 34057,34100,34143,34186,34229,34272,34315,34358, 34400,34443,34486,34529,34571,34614,34657,34699, 34742,34785,34827,34870,34912,34955,34997,35040, 35082,35125,35167,35210,35252,35294,35337,35379, 35421,35464,35506,35548,35590,35633,35675,35717, 35759,35801,35843,35885,35927,35969,36011,36053, 36095,36137,36179,36221,36263,36305,36347,36388, 36430,36472,36514,36556,36597,36639,36681,36722, 36764,36805,36847,36889,36930,36972,37013,37055, 37096,37137,37179,37220,37262,37303,37344,37386, 37427,37468,37509,37551,37592,37633,37674,37715, 37756,37797,37838,37879,37920,37961,38002,38043, 38084,38125,38166,38207,38248,38288,38329,38370, 38411,38451,38492,38533,38573,38614,38655,38695, 38736,38776,38817,38857,38898,38938,38979,39019, 39059,39100,39140,39180,39221,39261,39301,39341, 39382,39422,39462,39502,39542,39582,39622,39662, 39702,39742,39782,39822,39862,39902,39942,39982, 40021,40061,40101,40141,40180,40220,40260,40299, 40339,40379,40418,40458,40497,40537,40576,40616, 40655,40695,40734,40773,40813,40852,40891,40931, 40970,41009,41048,41087,41127,41166,41205,41244, 41283,41322,41361,41400,41439,41478,41517,41556, 41595,41633,41672,41711,41750,41788,41827,41866, 41904,41943,41982,42020,42059,42097,42136,42174, 42213,42251,42290,42328,42366,42405,42443,42481, 42520,42558,42596,42634,42672,42711,42749,42787, 42825,42863,42901,42939,42977,43015,43053,43091, 43128,43166,43204,43242,43280,43317,43355,43393, 43430,43468,43506,43543,43581,43618,43656,43693, 43731,43768,43806,43843,43880,43918,43955,43992, 44029,44067,44104,44141,44178,44215,44252,44289, 44326,44363,44400,44437,44474,44511,44548,44585, 44622,44659,44695,44732,44769,44806,44842,44879, 44915,44952,44989,45025,45062,45098,45135,45171, 45207,45244,45280,45316,45353,45389,45425,45462, 45498,45534,45570,45606,45642,45678,45714,45750, 45786,45822,45858,45894,45930,45966,46002,46037, 46073,46109,46145,46180,46216,46252,46287,46323, 46358,46394,46429,46465,46500,46536,46571,46606, 46642,46677,46712,46747,46783,46818,46853,46888, 46923,46958,46993,47028,47063,47098,47133,47168, 47203,47238,47273,47308,47342,47377,47412,47446, 47481,47516,47550,47585,47619,47654,47688,47723, 47757,47792,47826,47861,47895,47929,47963,47998, 48032,48066,48100,48134,48168,48202,48237,48271, 48305,48338,48372,48406,48440,48474,48508,48542, 48575,48609,48643,48676,48710,48744,48777,48811, 48844,48878,48911,48945,48978,49012,49045,49078, 49112,49145,49178,49211,49244,49278,49311,49344, 49377,49410,49443,49476,49509,49542,49575,49608, 49640,49673,49706,49739,49771,49804,49837,49869, 49902,49935,49967,50000,50032,50064,50097,50129, 50162,50194,50226,50259,50291,50323,50355,50387, 50420,50452,50484,50516,50548,50580,50612,50644, 50675,50707,50739,50771,50803,50834,50866,50898, 50929,50961,50993,51024,51056,51087,51119,51150, 51182,51213,51244,51276,51307,51338,51369,51401, 51432,51463,51494,51525,51556,51587,51618,51649, 51680,51711,51742,51773,51803,51834,51865,51896, 51926,51957,51988,52018,52049,52079,52110,52140, 52171,52201,52231,52262,52292,52322,52353,52383, 52413,52443,52473,52503,52534,52564,52594,52624, 52653,52683,52713,52743,52773,52803,52832,52862, 52892,52922,52951,52981,53010,53040,53069,53099, 53128,53158,53187,53216,53246,53275,53304,53334, 53363,53392,53421,53450,53479,53508,53537,53566, 53595,53624,53653,53682,53711,53739,53768,53797, 53826,53854,53883,53912,53940,53969,53997,54026, 54054,54082,54111,54139,54167,54196,54224,54252, 54280,54309,54337,54365,54393,54421,54449,54477, 54505,54533,54560,54588,54616,54644,54672,54699, 54727,54755,54782,54810,54837,54865,54892,54920, 54947,54974,55002,55029,55056,55084,55111,55138, 55165,55192,55219,55246,55274,55300,55327,55354, 55381,55408,55435,55462,55489,55515,55542,55569, 55595,55622,55648,55675,55701,55728,55754,55781, 55807,55833,55860,55886,55912,55938,55965,55991, 56017,56043,56069,56095,56121,56147,56173,56199, 56225,56250,56276,56302,56328,56353,56379,56404, 56430,56456,56481,56507,56532,56557,56583,56608, 56633,56659,56684,56709,56734,56760,56785,56810, 56835,56860,56885,56910,56935,56959,56984,57009, 57034,57059,57083,57108,57133,57157,57182,57206, 57231,57255,57280,57304,57329,57353,57377,57402, 57426,57450,57474,57498,57522,57546,57570,57594, 57618,57642,57666,57690,57714,57738,57762,57785, 57809,57833,57856,57880,57903,57927,57950,57974, 57997,58021,58044,58067,58091,58114,58137,58160, 58183,58207,58230,58253,58276,58299,58322,58345, 58367,58390,58413,58436,58459,58481,58504,58527, 58549,58572,58594,58617,58639,58662,58684,58706, 58729,58751,58773,58795,58818,58840,58862,58884, 58906,58928,58950,58972,58994,59016,59038,59059, 59081,59103,59125,59146,59168,59190,59211,59233, 59254,59276,59297,59318,59340,59361,59382,59404, 59425,59446,59467,59488,59509,59530,59551,59572, 59593,59614,59635,59656,59677,59697,59718,59739, 59759,59780,59801,59821,59842,59862,59883,59903, 59923,59944,59964,59984,60004,60025,60045,60065, 60085,60105,60125,60145,60165,60185,60205,60225, 60244,60264,60284,60304,60323,60343,60363,60382, 60402,60421,60441,60460,60479,60499,60518,60537, 60556,60576,60595,60614,60633,60652,60671,60690, 60709,60728,60747,60766,60785,60803,60822,60841, 60859,60878,60897,60915,60934,60952,60971,60989, 61007,61026,61044,61062,61081,61099,61117,61135, 61153,61171,61189,61207,61225,61243,61261,61279, 61297,61314,61332,61350,61367,61385,61403,61420, 61438,61455,61473,61490,61507,61525,61542,61559, 61577,61594,61611,61628,61645,61662,61679,61696, 61713,61730,61747,61764,61780,61797,61814,61831, 61847,61864,61880,61897,61913,61930,61946,61963, 61979,61995,62012,62028,62044,62060,62076,62092, 62108,62125,62141,62156,62172,62188,62204,62220, 62236,62251,62267,62283,62298,62314,62329,62345, 62360,62376,62391,62407,62422,62437,62453,62468, 62483,62498,62513,62528,62543,62558,62573,62588, 62603,62618,62633,62648,62662,62677,62692,62706, 62721,62735,62750,62764,62779,62793,62808,62822, 62836,62850,62865,62879,62893,62907,62921,62935, 62949,62963,62977,62991,63005,63019,63032,63046, 63060,63074,63087,63101,63114,63128,63141,63155, 63168,63182,63195,63208,63221,63235,63248,63261, 63274,63287,63300,63313,63326,63339,63352,63365, 63378,63390,63403,63416,63429,63441,63454,63466, 63479,63491,63504,63516,63528,63541,63553,63565, 63578,63590,63602,63614,63626,63638,63650,63662, 63674,63686,63698,63709,63721,63733,63745,63756, 63768,63779,63791,63803,63814,63825,63837,63848, 63859,63871,63882,63893,63904,63915,63927,63938, 63949,63960,63971,63981,63992,64003,64014,64025, 64035,64046,64057,64067,64078,64088,64099,64109, 64120,64130,64140,64151,64161,64171,64181,64192, 64202,64212,64222,64232,64242,64252,64261,64271, 64281,64291,64301,64310,64320,64330,64339,64349, 64358,64368,64377,64387,64396,64405,64414,64424, 64433,64442,64451,64460,64469,64478,64487,64496, 64505,64514,64523,64532,64540,64549,64558,64566, 64575,64584,64592,64600,64609,64617,64626,64634, 64642,64651,64659,64667,64675,64683,64691,64699, 64707,64715,64723,64731,64739,64747,64754,64762, 64770,64777,64785,64793,64800,64808,64815,64822, 64830,64837,64844,64852,64859,64866,64873,64880, 64887,64895,64902,64908,64915,64922,64929,64936, 64943,64949,64956,64963,64969,64976,64982,64989, 64995,65002,65008,65015,65021,65027,65033,65040, 65046,65052,65058,65064,65070,65076,65082,65088, 65094,65099,65105,65111,65117,65122,65128,65133, 65139,65144,65150,65155,65161,65166,65171,65177, 65182,65187,65192,65197,65202,65207,65212,65217, 65222,65227,65232,65237,65242,65246,65251,65256, 65260,65265,65270,65274,65279,65283,65287,65292, 65296,65300,65305,65309,65313,65317,65321,65325, 65329,65333,65337,65341,65345,65349,65352,65356, 65360,65363,65367,65371,65374,65378,65381,65385, 65388,65391,65395,65398,65401,65404,65408,65411, 65414,65417,65420,65423,65426,65429,65431,65434, 65437,65440,65442,65445,65448,65450,65453,65455, 65458,65460,65463,65465,65467,65470,65472,65474, 65476,65478,65480,65482,65484,65486,65488,65490, 65492,65494,65496,65497,65499,65501,65502,65504, 65505,65507,65508,65510,65511,65513,65514,65515, 65516,65518,65519,65520,65521,65522,65523,65524, 65525,65526,65527,65527,65528,65529,65530,65530, 65531,65531,65532,65532,65533,65533,65534,65534, 65534,65535,65535,65535,65535,65535,65535,65535 }; int tantoangle[2049] = { 0,333772,667544,1001315,1335086,1668857,2002626,2336395, 2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492, 5340245,5673995,6007743,6341488,6675230,7008968,7342704,7676435, 8010164,8343888,8677609,9011325,9345037,9678744,10012447,10346145, 10679838,11013526,11347209,11680887,12014558,12348225,12681885,13015539, 13349187,13682829,14016464,14350092,14683714,15017328,15350936,15684536, 16018129,16351714,16685291,17018860,17352422,17685974,18019518,18353054, 18686582,19020100,19353610,19687110,20020600,20354080,20687552,21021014, 21354466,21687906,22021338,22354758,22688168,23021568,23354956,23688332, 24021698,24355052,24688396,25021726,25355046,25688352,26021648,26354930, 26688200,27021456,27354702,27687932,28021150,28354356,28687548,29020724, 29353888,29687038,30020174,30353296,30686404,31019496,31352574,31685636, 32018684,32351718,32684734,33017736,33350722,33683692,34016648,34349584, 34682508,35015412,35348300,35681172,36014028,36346868,36679688,37012492, 37345276,37678044,38010792,38343524,38676240,39008936,39341612,39674272, 40006912,40339532,40672132,41004716,41337276,41669820,42002344,42334848, 42667332,42999796,43332236,43664660,43997060,44329444,44661800,44994140, 45326456,45658752,45991028,46323280,46655512,46987720,47319908,47652072, 47984212,48316332,48648428,48980500,49312548,49644576,49976580,50308556, 50640512,50972444,51304352,51636236,51968096,52299928,52631740,52963524, 53295284,53627020,53958728,54290412,54622068,54953704,55285308,55616888, 55948444,56279972,56611472,56942948,57274396,57605816,57937212,58268576, 58599916,58931228,59262512,59593768,59924992,60256192,60587364,60918508, 61249620,61580704,61911760,62242788,62573788,62904756,63235692,63566604, 63897480,64228332,64559148,64889940,65220696,65551424,65882120,66212788, 66543420,66874024,67204600,67535136,67865648,68196120,68526568,68856984, 69187360,69517712,69848024,70178304,70508560,70838776,71168960,71499112, 71829224,72159312,72489360,72819376,73149360,73479304,73809216,74139096, 74468936,74798744,75128520,75458264,75787968,76117632,76447264,76776864, 77106424,77435952,77765440,78094888,78424304,78753688,79083032,79412336, 79741608,80070840,80400032,80729192,81058312,81387392,81716432,82045440, 82374408,82703336,83032224,83361080,83689896,84018664,84347400,84676096, 85004760,85333376,85661952,85990488,86318984,86647448,86975864,87304240, 87632576,87960872,88289128,88617344,88945520,89273648,89601736,89929792, 90257792,90585760,90913688,91241568,91569408,91897200,92224960,92552672, 92880336,93207968,93535552,93863088,94190584,94518040,94845448,95172816, 95500136,95827416,96154648,96481832,96808976,97136080,97463136,97790144, 98117112,98444032,98770904,99097736,99424520,99751256,100077944,100404592, 100731192,101057744,101384248,101710712,102037128,102363488,102689808,103016080, 103342312,103668488,103994616,104320696,104646736,104972720,105298656,105624552, 105950392,106276184,106601928,106927624,107253272,107578872,107904416,108229920, 108555368,108880768,109206120,109531416,109856664,110181872,110507016,110832120, 111157168,111482168,111807112,112132008,112456856,112781648,113106392,113431080, 113755720,114080312,114404848,114729328,115053760,115378136,115702464,116026744, 116350960,116675128,116999248,117323312,117647320,117971272,118295176,118619024, 118942816,119266560,119590248,119913880,120237456,120560984,120884456,121207864, 121531224,121854528,122177784,122500976,122824112,123147200,123470224,123793200, 124116120,124438976,124761784,125084528,125407224,125729856,126052432,126374960, 126697424,127019832,127342184,127664472,127986712,128308888,128631008,128953072, 129275080,129597024,129918912,130240744,130562520,130884232,131205888,131527480, 131849016,132170496,132491912,132813272,133134576,133455816,133776992,134098120, 134419184,134740176,135061120,135382000,135702816,136023584,136344272,136664912, 136985488,137306016,137626464,137946864,138267184,138587456,138907664,139227808, 139547904,139867920,140187888,140507776,140827616,141147392,141467104,141786752, 142106336,142425856,142745312,143064720,143384048,143703312,144022512,144341664, 144660736,144979744,145298704,145617584,145936400,146255168,146573856,146892480, 147211040,147529536,147847968,148166336,148484640,148802880,149121056,149439152, 149757200,150075168,150393072,150710912,151028688,151346400,151664048,151981616, 152299136,152616576,152933952,153251264,153568496,153885680,154202784,154519824, 154836784,155153696,155470528,155787296,156104000,156420624,156737200,157053696, 157370112,157686480,158002768,158318976,158635136,158951216,159267232,159583168, 159899040,160214848,160530592,160846256,161161840,161477376,161792832,162108208, 162423520,162738768,163053952,163369040,163684080,163999040,164313936,164628752, 164943504,165258176,165572784,165887312,166201776,166516160,166830480,167144736, 167458912,167773008,168087040,168400992,168714880,169028688,169342432,169656096, 169969696,170283216,170596672,170910032,171223344,171536576,171849728,172162800, 172475808,172788736,173101600,173414384,173727104,174039728,174352288,174664784, 174977200,175289536,175601792,175913984,176226096,176538144,176850096,177161984, 177473792,177785536,178097200,178408784,178720288,179031728,179343088,179654368, 179965568,180276704,180587744,180898720,181209616,181520448,181831184,182141856, 182452448,182762960,183073408,183383760,183694048,184004240,184314368,184624416, 184934400,185244288,185554096,185863840,186173504,186483072,186792576,187102000, 187411344,187720608,188029808,188338912,188647936,188956896,189265760,189574560, 189883264,190191904,190500448,190808928,191117312,191425632,191733872,192042016, 192350096,192658096,192966000,193273840,193581584,193889264,194196848,194504352, 194811792,195119136,195426400,195733584,196040688,196347712,196654656,196961520, 197268304,197574992,197881616,198188144,198494592,198800960,199107248,199413456, 199719584,200025616,200331584,200637456,200943248,201248960,201554576,201860128, 202165584,202470960,202776256,203081456,203386592,203691632,203996592,204301472, 204606256,204910976,205215600,205520144,205824592,206128960,206433248,206737456, 207041584,207345616,207649568,207953424,208257216,208560912,208864512,209168048, 209471488,209774832,210078112,210381296,210684384,210987408,211290336,211593184, 211895936,212198608,212501184,212803680,213106096,213408432,213710672,214012816, 214314880,214616864,214918768,215220576,215522288,215823920,216125472,216426928, 216728304,217029584,217330784,217631904,217932928,218233856,218534704,218835472, 219136144,219436720,219737216,220037632,220337952,220638192,220938336,221238384, 221538352,221838240,222138032,222437728,222737344,223036880,223336304,223635664, 223934912,224234096,224533168,224832160,225131072,225429872,225728608,226027232, 226325776,226624240,226922608,227220880,227519056,227817152,228115168,228413088, 228710912,229008640,229306288,229603840,229901312,230198688,230495968,230793152, 231090256,231387280,231684192,231981024,232277760,232574416,232870960,233167440, 233463808,233760096,234056288,234352384,234648384,234944304,235240128,235535872, 235831504,236127056,236422512,236717888,237013152,237308336,237603424,237898416, 238193328,238488144,238782864,239077488,239372016,239666464,239960816,240255072, 240549232,240843312,241137280,241431168,241724960,242018656,242312256,242605776, 242899200,243192512,243485744,243778896,244071936,244364880,244657744,244950496, 245243168,245535744,245828224,246120608,246412912,246705104,246997216,247289216, 247581136,247872960,248164688,248456320,248747856,249039296,249330640,249621904, 249913056,250204128,250495088,250785968,251076736,251367424,251658016,251948512, 252238912,252529200,252819408,253109520,253399536,253689456,253979280,254269008, 254558640,254848176,255137632,255426976,255716224,256005376,256294432,256583392, 256872256,257161024,257449696,257738272,258026752,258315136,258603424,258891600, 259179696,259467696,259755600,260043392,260331104,260618704,260906224,261193632, 261480960,261768176,262055296,262342320,262629248,262916080,263202816,263489456, 263776000,264062432,264348784,264635024,264921168,265207216,265493168,265779024, 266064784,266350448,266636000,266921472,267206832,267492096,267777264,268062336, 268347312,268632192,268916960,269201632,269486208,269770688,270055072,270339360, 270623552,270907616,271191616,271475488,271759296,272042976,272326560,272610048, 272893440,273176736,273459936,273743040,274026048,274308928,274591744,274874432, 275157024,275439520,275721920,276004224,276286432,276568512,276850528,277132416, 277414240,277695936,277977536,278259040,278540448,278821728,279102944,279384032, 279665056,279945952,280226752,280507456,280788064,281068544,281348960,281629248, 281909472,282189568,282469568,282749440,283029248,283308960,283588544,283868032, 284147424,284426720,284705920,284985024,285264000,285542912,285821696,286100384, 286378976,286657440,286935840,287214112,287492320,287770400,288048384,288326240, 288604032,288881696,289159264,289436768,289714112,289991392,290268576,290545632, 290822592,291099456,291376224,291652896,291929440,292205888,292482272,292758528, 293034656,293310720,293586656,293862496,294138240,294413888,294689440,294964864, 295240192,295515424,295790560,296065600,296340512,296615360,296890080,297164704, 297439200,297713632,297987936,298262144,298536256,298810240,299084160,299357952, 299631648,299905248,300178720,300452128,300725408,300998592,301271680,301544640, 301817536,302090304,302362976,302635520,302908000,303180352,303452608,303724768, 303996800,304268768,304540608,304812320,305083968,305355520,305626944,305898272, 306169472,306440608,306711616,306982528,307253344,307524064,307794656,308065152, 308335552,308605856,308876032,309146112,309416096,309685984,309955744,310225408, 310494976,310764448,311033824,311303072,311572224,311841280,312110208,312379040, 312647776,312916416,313184960,313453376,313721696,313989920,314258016,314526016, 314793920,315061728,315329408,315597024,315864512,316131872,316399168,316666336, 316933408,317200384,317467232,317733984,318000640,318267200,318533632,318799968, 319066208,319332352,319598368,319864288,320130112,320395808,320661408,320926912, 321192320,321457632,321722816,321987904,322252864,322517760,322782528,323047200, 323311744,323576192,323840544,324104800,324368928,324632992,324896928,325160736, 325424448,325688096,325951584,326215008,326478304,326741504,327004608,327267584, 327530464,327793248,328055904,328318496,328580960,328843296,329105568,329367712, 329629760,329891680,330153536,330415264,330676864,330938400,331199808,331461120, 331722304,331983392,332244384,332505280,332766048,333026752,333287296,333547776, 333808128,334068384,334328544,334588576,334848512,335108352,335368064,335627712, 335887200,336146624,336405920,336665120,336924224,337183200,337442112,337700864, 337959552,338218112,338476576,338734944,338993184,339251328,339509376,339767296, 340025120,340282848,340540480,340797984,341055392,341312704,341569888,341826976, 342083968,342340832,342597600,342854272,343110848,343367296,343623648,343879904, 344136032,344392064,344648000,344903808,345159520,345415136,345670656,345926048, 346181344,346436512,346691616,346946592,347201440,347456224,347710880,347965440, 348219872,348474208,348728448,348982592,349236608,349490528,349744320,349998048, 350251648,350505152,350758528,351011808,351264992,351518048,351771040,352023872, 352276640,352529280,352781824,353034272,353286592,353538816,353790944,354042944, 354294880,354546656,354798368,355049952,355301440,355552800,355804096,356055264, 356306304,356557280,356808128,357058848,357309504,357560032,357810464,358060768, 358311008,358561088,358811104,359060992,359310784,359560480,359810048,360059520, 360308896,360558144,360807296,361056352,361305312,361554144,361802880,362051488, 362300032,362548448,362796736,363044960,363293056,363541024,363788928,364036704, 364284384,364531936,364779392,365026752,365274016,365521152,365768192,366015136, 366261952,366508672,366755296,367001792,367248192,367494496,367740704,367986784, 368232768,368478656,368724416,368970080,369215648,369461088,369706432,369951680, 370196800,370441824,370686752,370931584,371176288,371420896,371665408,371909792, 372154080,372398272,372642336,372886304,373130176,373373952,373617600,373861152, 374104608,374347936,374591168,374834304,375077312,375320224,375563040,375805760, 376048352,376290848,376533248,376775520,377017696,377259776,377501728,377743584, 377985344,378227008,378468544,378709984,378951328,379192544,379433664,379674688, 379915584,380156416,380397088,380637696,380878176,381118560,381358848,381599040, 381839104,382079072,382318912,382558656,382798304,383037856,383277280,383516640, 383755840,383994976,384233984,384472896,384711712,384950400,385188992,385427488, 385665888,385904160,386142336,386380384,386618368,386856224,387093984,387331616, 387569152,387806592,388043936,388281152,388518272,388755296,388992224,389229024, 389465728,389702336,389938816,390175200,390411488,390647680,390883744,391119712, 391355584,391591328,391826976,392062528,392297984,392533312,392768544,393003680, 393238720,393473632,393708448,393943168,394177760,394412256,394646656,394880960, 395115136,395349216,395583200,395817088,396050848,396284512,396518080,396751520, 396984864,397218112,397451264,397684288,397917248,398150080,398382784,398615424, 398847936,399080320,399312640,399544832,399776928,400008928,400240832,400472608, 400704288,400935872,401167328,401398720,401629984,401861120,402092192,402323136, 402553984,402784736,403015360,403245888,403476320,403706656,403936896,404167008, 404397024,404626944,404856736,405086432,405316032,405545536,405774912,406004224, 406233408,406462464,406691456,406920320,407149088,407377760,407606336,407834784, 408063136,408291392,408519520,408747584,408975520,409203360,409431072,409658720, 409886240,410113664,410340992,410568192,410795296,411022304,411249216,411476032, 411702720,411929312,412155808,412382176,412608480,412834656,413060736,413286720, 413512576,413738336,413964000,414189568,414415040,414640384,414865632,415090784, 415315840,415540800,415765632,415990368,416215008,416439552,416663968,416888288, 417112512,417336640,417560672,417784576,418008384,418232096,418455712,418679200, 418902624,419125920,419349120,419572192,419795200,420018080,420240864,420463552, 420686144,420908608,421130976,421353280,421575424,421797504,422019488,422241344, 422463104,422684768,422906336,423127776,423349120,423570400,423791520,424012576, 424233536,424454368,424675104,424895744,425116288,425336736,425557056,425777280, 425997408,426217440,426437376,426657184,426876928,427096544,427316064,427535488, 427754784,427974016,428193120,428412128,428631040,428849856,429068544,429287168, 429505664,429724064,429942368,430160576,430378656,430596672,430814560,431032352, 431250048,431467616,431685120,431902496,432119808,432336992,432554080,432771040, 432987936,433204736,433421408,433637984,433854464,434070848,434287104,434503296, 434719360,434935360,435151232,435367008,435582656,435798240,436013696,436229088, 436444352,436659520,436874592,437089568,437304416,437519200,437733856,437948416, 438162880,438377248,438591520,438805696,439019744,439233728,439447584,439661344, 439875008,440088576,440302048,440515392,440728672,440941824,441154880,441367872, 441580736,441793472,442006144,442218720,442431168,442643552,442855808,443067968, 443280032,443492000,443703872,443915648,444127296,444338880,444550336,444761696, 444972992,445184160,445395232,445606176,445817056,446027840,446238496,446449088, 446659552,446869920,447080192,447290400,447500448,447710432,447920320,448130112, 448339776,448549376,448758848,448968224,449177536,449386720,449595808,449804800, 450013664,450222464,450431168,450639776,450848256,451056640,451264960,451473152, 451681248,451889248,452097152,452304960,452512672,452720288,452927808,453135232, 453342528,453549760,453756864,453963904,454170816,454377632,454584384,454791008, 454997536,455203968,455410304,455616544,455822688,456028704,456234656,456440512, 456646240,456851904,457057472,457262912,457468256,457673536,457878688,458083744, 458288736,458493600,458698368,458903040,459107616,459312096,459516480,459720768, 459924960,460129056,460333056,460536960,460740736,460944448,461148064,461351584, 461554976,461758304,461961536,462164640,462367680,462570592,462773440,462976160, 463178816,463381344,463583776,463786144,463988384,464190560,464392608,464594560, 464796448,464998208,465199872,465401472,465602944,465804320,466005600,466206816, 466407904,466608896,466809824,467010624,467211328,467411936,467612480,467812896, 468013216,468213440,468413600,468613632,468813568,469013440,469213184,469412832, 469612416,469811872,470011232,470210528,470409696,470608800,470807776,471006688, 471205472,471404192,471602784,471801312,471999712,472198048,472396288,472594400, 472792448,472990400,473188256,473385984,473583648,473781216,473978688,474176064, 474373344,474570528,474767616,474964608,475161504,475358336,475555040,475751648, 475948192,476144608,476340928,476537184,476733312,476929376,477125344,477321184, 477516960,477712640,477908224,478103712,478299104,478494400,478689600,478884704, 479079744,479274656,479469504,479664224,479858880,480053408,480247872,480442240, 480636512,480830656,481024736,481218752,481412640,481606432,481800128,481993760, 482187264,482380704,482574016,482767264,482960416,483153472,483346432,483539296, 483732064,483924768,484117344,484309856,484502240,484694560,484886784,485078912, 485270944,485462880,485654720,485846464,486038144,486229696,486421184,486612576, 486803840,486995040,487186176,487377184,487568096,487758912,487949664,488140320, 488330880,488521312,488711712,488901984,489092160,489282240,489472256,489662176, 489851968,490041696,490231328,490420896,490610336,490799712,490988960,491178144, 491367232,491556224,491745120,491933920,492122656,492311264,492499808,492688256, 492876608,493064864,493253056,493441120,493629120,493817024,494004832,494192544, 494380160,494567712,494755136,494942496,495129760,495316928,495504000,495691008, 495877888,496064704,496251424,496438048,496624608,496811040,496997408,497183680, 497369856,497555936,497741920,497927840,498113632,498299360,498484992,498670560, 498856000,499041376,499226656,499411840,499596928,499781920,499966848,500151680, 500336416,500521056,500705600,500890080,501074464,501258752,501442944,501627040, 501811072,501995008,502178848,502362592,502546240,502729824,502913312,503096704, 503280000,503463232,503646368,503829408,504012352,504195200,504377984,504560672, 504743264,504925760,505108192,505290496,505472736,505654912,505836960,506018944, 506200832,506382624,506564320,506745952,506927488,507108928,507290272,507471552, 507652736,507833824,508014816,508195744,508376576,508557312,508737952,508918528, 509099008,509279392,509459680,509639904,509820032,510000064,510180000,510359872, 510539648,510719328,510898944,511078432,511257856,511437216,511616448,511795616, 511974688,512153664,512332576,512511392,512690112,512868768,513047296,513225792, 513404160,513582432,513760640,513938784,514116800,514294752,514472608,514650368, 514828064,515005664,515183168,515360608,515537952,515715200,515892352,516069440, 516246432,516423328,516600160,516776896,516953536,517130112,517306592,517482976, 517659264,517835488,518011616,518187680,518363648,518539520,518715296,518891008, 519066624,519242144,519417600,519592960,519768256,519943424,520118528,520293568, 520468480,520643328,520818112,520992800,521167392,521341888,521516320,521690656, 521864896,522039072,522213152,522387168,522561056,522734912,522908640,523082304, 523255872,523429376,523602784,523776096,523949312,524122464,524295552,524468512, 524641440,524814240,524986976,525159616,525332192,525504640,525677056,525849344, 526021568,526193728,526365792,526537760,526709632,526881440,527053152,527224800, 527396352,527567840,527739200,527910528,528081728,528252864,528423936,528594880, 528765760,528936576,529107296,529277920,529448480,529618944,529789344,529959648, 530129856,530300000,530470048,530640000,530809888,530979712,531149440,531319072, 531488608,531658080,531827488,531996800,532166016,532335168,532504224,532673184, 532842080,533010912,533179616,533348288,533516832,533685312,533853728,534022048, 534190272,534358432,534526496,534694496,534862400,535030240,535197984,535365632, 535533216,535700704,535868128,536035456,536202720,536369888,536536992,536704000, 536870912 }; deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_sprite.c0000644000175000017500000010352411357170242023420 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_sprite.c: Rendering Map Objects as 2D Sprites */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_refresh.h" #include "de_render.h" #include "de_play.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define DOTPROD(a, b) (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void setupPSpriteParams(rendpspriteparams_t *params, vispsprite_t *spr); static void setupModelParamsForVisPSprite(rendmodelparams_t* params, vispsprite_t* spr); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int spriteLight = 4; float maxSpriteAngle = 60; // If true - use the "no translucency" blending mode for sprites/masked walls byte noSpriteTrans = false; int useSpriteAlpha = 1; byte devNoSprites = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void Rend_SpriteRegister(void) { // Cvars C_VAR_INT("rend-sprite-align", &alwaysAlign, 0, 0, 3); C_VAR_FLOAT("rend-sprite-align-angle", &maxSpriteAngle, 0, 0, 90); C_VAR_INT("rend-sprite-alpha", &useSpriteAlpha, 0, 0, 1); C_VAR_INT("rend-sprite-blend", &missileBlend, 0, 0, 1); C_VAR_INT("rend-sprite-lights", &spriteLight, 0, 0, 10); C_VAR_BYTE("rend-sprite-mode", &noSpriteTrans, 0, 0, 1); C_VAR_INT("rend-sprite-noz", &noSpriteZWrite, 0, 0, 1); C_VAR_BYTE("rend-sprite-precache", &precacheSprites, 0, 0, 1); C_VAR_BYTE("rend-dev-nosprite", &devNoSprites, CVF_NO_ARCHIVE, 0, 1); } static __inline void renderQuad(dgl_vertex_t *v, dgl_color_t *c, dgl_texcoord_t *tc) { glBegin(GL_QUADS); glColor4ubv(c[0].rgba); glTexCoord2fv(tc[0].st); glVertex3fv(v[0].xyz); glColor4ubv(c[1].rgba); glTexCoord2fv(tc[1].st); glVertex3fv(v[1].xyz); glColor4ubv(c[2].rgba); glTexCoord2fv(tc[2].st); glVertex3fv(v[2].xyz); glColor4ubv(c[3].rgba); glTexCoord2fv(tc[3].st); glVertex3fv(v[3].xyz); glEnd(); } void Rend_Draw3DPlayerSprites(void) { int i; // Setup the modelview matrix. Rend_ModelViewMatrix(false); if(usingFog) glEnable(GL_FOG); // Clear Z buffer. This will prevent the psprites from being clipped // by nearby polygons. glClear(GL_DEPTH_BUFFER_BIT); for(i = 0; i < DDMAXPSPRITES; ++i) { vispsprite_t* spr = &visPSprites[i]; if(spr->type != VPSPR_MODEL) continue; // Not used. { rendmodelparams_t params; setupModelParamsForVisPSprite(¶ms, spr); Rend_RenderModel(¶ms); } } if(usingFog) glDisable(GL_FOG); } /** * Set all the colors in the array to that specified. */ void Spr_UniformVertexColors(int count, dgl_color_t *colors, const float *rgba) { for(; count-- > 0; colors++) { colors->rgba[CR] = (byte) (255 * rgba[CR]); colors->rgba[CG] = (byte) (255 * rgba[CG]); colors->rgba[CB] = (byte) (255 * rgba[CB]); colors->rgba[CA] = (byte) (255 * rgba[CA]); } } typedef struct { float color[3], extra[3]; dgl_vertex_t* normal; uint processedLights, maxLights; } lightspriteparams_t; static boolean lightSprite(const vlight_t* vlight, void* context) { float* dest; float dot; lightspriteparams_t* params = (lightspriteparams_t*) context; dot = DOTPROD(vlight->vector, params->normal->xyz); dot += vlight->offset; // Shift a bit towards the light. if(!vlight->affectedByAmbient) { // Won't be affected by ambient. dest = params->extra; } else { dest = params->color; } // Ability to both light and shade. if(dot > 0) { dot *= vlight->lightSide; } else { dot *= vlight->darkSide; } dot = MINMAX_OF(-1, dot, 1); dest[CR] += dot * vlight->color[CR]; dest[CG] += dot * vlight->color[CG]; dest[CB] += dot * vlight->color[CB]; params->processedLights++; if(params->maxLights && !(params->processedLights < params->maxLights)) return false; // Stop iteration. return true; // Continue iteration. } /** * Calculate vertex lighting. */ void Spr_VertexColors(int count, dgl_color_t *out, dgl_vertex_t *normal, uint vLightListIdx, uint maxLights, const float* ambient) { int i, k; lightspriteparams_t params; for(i = 0; i < count; ++i, out++, normal++) { // Begin with total darkness. params.color[CR] = params.color[CG] = params.color[CB] = 0; params.extra[CR] = params.extra[CG] = params.extra[CB] = 0; params.normal = normal; params.processedLights = 0; params.maxLights = maxLights; VL_ListIterator(vLightListIdx, ¶ms, lightSprite); // Check for ambient and convert to ubyte. for(k = 0; k < 3; ++k) { if(params.color[k] < ambient[k]) params.color[k] = ambient[k]; params.color[k] += params.extra[k]; params.color[k] = MINMAX_OF(0, params.color[k], 1); // This is the final color. out->rgba[k] = (byte) (255 * params.color[k]); } out->rgba[CA] = (byte) (255 * ambient[CA]); } } static void setupPSpriteParams(rendpspriteparams_t* params, vispsprite_t* spr) { float offScaleY = weaponOffsetScaleY / 1000.0f; spritetex_t* sprTex; spritedef_t* sprDef; ddpsprite_t* psp = spr->psp; int sprite = psp->statePtr->sprite; int frame = psp->statePtr->frame; boolean flip; spriteframe_t* sprFrame; material_load_params_t mparams; material_snapshot_t ms; #ifdef RANGECHECK if((unsigned) sprite >= (unsigned) numSprites) Con_Error("R_GetSpriteInfo: invalid sprite number %i.\n", sprite); #endif sprDef = &sprites[sprite]; #ifdef RANGECHECK if(frame >= sprDef->numFrames) Con_Error("setupPSpriteParams: Invalid frame number %i for sprite %i", frame, sprite); #endif sprFrame = &sprDef->spriteFrames[frame]; flip = sprFrame->flip[0]; memset(&mparams, 0, sizeof(mparams)); mparams.pSprite = true; Material_Prepare(&ms, sprFrame->mats[0], true, &mparams); sprTex = spriteTextures[ms.units[MTU_PRIMARY].texInst->tex->ofTypeID]; params->pos[VX] = psp->pos[VX] - sprTex->offX + pspOffset[VX]; params->pos[VX] = psp->pos[VX] - sprTex->offX + pspOffset[VX]; params->pos[VY] = offScaleY * (psp->pos[VY] - sprTex->offY) + pspOffset[VY]; params->width = ms.width; params->height = ms.height; // Calculate texture coordinates. params->texOffset[0] = ms.units[MTU_PRIMARY].texInst->data.sprite.texCoord[VX]; params->texOffset[1] = ms.units[MTU_PRIMARY].texInst->data.sprite.texCoord[VY]; params->texFlip[0] = flip; params->texFlip[1] = false; params->mat = sprFrame->mats[0]; params->ambientColor[CA] = spr->data.sprite.alpha; if(spr->data.sprite.isFullBright) { params->ambientColor[CR] = params->ambientColor[CG] = params->ambientColor[CB] = 1; params->vLightListIdx = 0; } else { collectaffectinglights_params_t lparams; if(useBias) { // Evaluate the position in the light grid. LG_Evaluate(spr->center, params->ambientColor); } else { float lightLevel; const float* secColor = R_GetSectorLightColor(spr->data.sprite.subsector->sector); // No need for distance attentuation. lightLevel = spr->data.sprite.subsector->sector->lightLevel; // Add extra light plus bonus. lightLevel += R_ExtraLightDelta(); lightLevel *= pspLightLevelMultiplier; Rend_ApplyLightAdaptation(&lightLevel); // Determine the final ambientColor in affect. params->ambientColor[CR] = lightLevel * secColor[CR]; params->ambientColor[CG] = lightLevel * secColor[CG]; params->ambientColor[CB] = lightLevel * secColor[CB]; } Rend_ApplyTorchLight(params->ambientColor, 0); lparams.starkLight = false; lparams.center[VX] = spr->center[VX]; lparams.center[VY] = spr->center[VY]; lparams.center[VZ] = spr->center[VZ]; lparams.subsector = spr->data.sprite.subsector; lparams.ambientColor = params->ambientColor; params->vLightListIdx = R_CollectAffectingLights(&lparams); } } void Rend_DrawPSprite(const rendpspriteparams_t *params) { int i; float v1[2], v2[2], v3[2], v4[2]; dgl_color_t quadColors[4]; dgl_vertex_t quadNormals[4]; if(renderTextures == 1) { GL_SetPSprite(params->mat); } else if(renderTextures == 2) { // For lighting debug, render all solid surfaces using the gray texture. material_t* mat = P_GetMaterial(DDT_GRAY, MN_SYSTEM); material_snapshot_t ms; Material_Prepare(&ms, mat, true, NULL); GL_BindTexture(ms.units[MTU_PRIMARY].texInst->id, ms.units[MTU_PRIMARY].magMode); } else { glBindTexture(GL_TEXTURE_2D, 0); } // 0---1 // | | Vertex layout. // 3---2 v1[VX] = params->pos[VX]; v1[VY] = params->pos[VY]; v2[VX] = params->pos[VX] + params->width; v2[VY] = params->pos[VY]; v3[VX] = params->pos[VX] + params->width; v3[VY] = params->pos[VY] + params->height; v4[VX] = params->pos[VX]; v4[VY] = params->pos[VY] + params->height; // All psprite vertices are co-plannar, so just copy the view front vector. // \fixme: Can we do something better here? { const float* frontVec = R_ViewData(viewPlayer - ddPlayers)->frontVec; for(i = 0; i < 4; ++i) { quadNormals[i].xyz[VX] = frontVec[VX]; quadNormals[i].xyz[VY] = frontVec[VZ]; quadNormals[i].xyz[VZ] = frontVec[VY]; } } if(!params->vLightListIdx) { // Lit uniformly. Spr_UniformVertexColors(4, quadColors, params->ambientColor); } else { // Lit normally. Spr_VertexColors(4, quadColors, quadNormals, params->vLightListIdx, spriteLight + 1, params->ambientColor); } { dgl_texcoord_t tcs[4], *tc = tcs; dgl_color_t *c = quadColors; tc[0].st[0] = params->texOffset[0] * (params->texFlip[0]? 1:0); tc[0].st[1] = params->texOffset[1] * (params->texFlip[1]? 1:0); tc[1].st[0] = params->texOffset[0] * (!params->texFlip[0]? 1:0); tc[1].st[1] = params->texOffset[1] * (params->texFlip[1]? 1:0); tc[2].st[0] = params->texOffset[0] * (!params->texFlip[0]? 1:0); tc[2].st[1] = params->texOffset[1] * (!params->texFlip[1]? 1:0); tc[3].st[0] = params->texOffset[0] * (params->texFlip[0]? 1:0); tc[3].st[1] = params->texOffset[1] * (!params->texFlip[1]? 1:0); glBegin(GL_QUADS); glColor4ubv(c[0].rgba); glTexCoord2fv(tc[0].st); glVertex2fv(v1); glColor4ubv(c[1].rgba); glTexCoord2fv(tc[1].st); glVertex2fv(v2); glColor4ubv(c[2].rgba); glTexCoord2fv(tc[2].st); glVertex2fv(v3); glColor4ubv(c[3].rgba); glTexCoord2fv(tc[3].st); glVertex2fv(v4); glEnd(); } } /** * Draws 2D HUD sprites. * * \note If they were already drawn 3D, this won't do anything. */ void Rend_Draw2DPlayerSprites(void) { int i; ddplayer_t *ddpl = &viewPlayer->shared; ddpsprite_t *psp; // Cameramen have no HUD sprites. if((ddpl->flags & DDPF_CAMERA) || (ddpl->flags & DDPF_CHASECAM)) return; if(usingFog) glEnable(GL_FOG); // Check for fullbright. for(i = 0, psp = ddpl->pSprites; i < DDMAXPSPRITES; ++i, psp++) { vispsprite_t *spr = &visPSprites[i]; // Should this psprite be drawn? if(spr->type != VPSPR_SPRITE) continue; // No... // Draw as separate sprites. if(spr->psp && spr->psp->statePtr) { rendpspriteparams_t params; setupPSpriteParams(¶ms, spr); Rend_DrawPSprite(¶ms); } } if(usingFog) glDisable(GL_FOG); } /** * A sort of a sprite, I guess... Masked walls must be rendered sorted * with sprites, so no artifacts appear when sprites are seen behind * masked walls. */ void Rend_RenderMaskedWall(rendmaskedwallparams_t *params) { boolean withDyn = false; int normal = 0, dyn = 1; GLenum normalTarget, dynTarget; // Do we have a dynamic light to blend with? // This only happens when multitexturing is enabled. if(params->modTex) { if(IS_MUL) { normal = 1; dyn = 0; } else { normal = 0; dyn = 1; } GL_SelectTexUnits(2); GL_ModulateTexture(IS_MUL ? 4 : 5); // The dynamic light. GL_ActiveTexture(IS_MUL ? GL_TEXTURE0 : GL_TEXTURE1); GL_BindTexture(renderTextures ? params->modTex : 0, GL_LINEAR); glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, params->modColor); // The actual texture. GL_ActiveTexture(IS_MUL ? GL_TEXTURE1 : GL_TEXTURE0); GL_BindTexture(renderTextures ? params->tex : 0, params->magMode); withDyn = true; } else { GL_SelectTexUnits(1); GL_ModulateTexture(1); GL_BindTexture(renderTextures? params->tex : 0, params->magMode); normal = 0; } // Masked walls are sometimes used for special effects like arcs, // cobwebs and bottoms of sails. In order for them to look right, // we need to disable texture wrapping on the horizontal axis (S). // Most masked walls need wrapping, though. What we need to do is // look at the texture coordinates and see if they require texture // wrapping. if(params->masked) { if(withDyn) { GL_ActiveTexture(IS_MUL ? GL_TEXTURE1 : GL_TEXTURE0); } if(params->texCoord[0][VX] < 0 || params->texCoord[0][VX] > 1 || params->texCoord[1][VX] < 0 || params->texCoord[1][VX] > 1) { // The texcoords are out of the normal [0,1] range. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); } else { // Visible portion is within the actual [0,1] range. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); } // Clamp on the vertical axis if the coords are in the normal [0, 1] range. if(!(params->texCoord[0][VY] < 0 || params->texCoord[0][VY] > 1 || params->texCoord[1][VY] < 0 || params->texCoord[1][VY] > 1)) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } GL_BlendMode(params->blendMode); normalTarget = normal? GL_TEXTURE1 : GL_TEXTURE0; dynTarget = dyn? GL_TEXTURE1 : GL_TEXTURE0; // Draw one quad. This is obviously not a very efficient way to render // lots of masked walls, but since 3D models and sprites must be // rendered interleaved with masked walls, there's not much that can be // done about this. if(withDyn) { glBegin(GL_QUADS); glColor4fv(params->vertices[0].color); glMultiTexCoord2fARB(normalTarget, params->texCoord[0][0], params->texCoord[1][1]); glMultiTexCoord2fARB(dynTarget, params->modTexCoord[0][0], params->modTexCoord[1][1]); glVertex3f(params->vertices[0].pos[VX], params->vertices[0].pos[VZ], params->vertices[0].pos[VY]); glColor4fv(params->vertices[1].color); glMultiTexCoord2fARB(normalTarget, params->texCoord[0][0], params->texCoord[0][1]); glMultiTexCoord2fARB(dynTarget, params->modTexCoord[0][0], params->modTexCoord[1][0]); glVertex3f(params->vertices[1].pos[VX], params->vertices[1].pos[VZ], params->vertices[1].pos[VY]); glColor4fv(params->vertices[3].color); glMultiTexCoord2fARB(normalTarget, params->texCoord[1][0], params->texCoord[0][1]); glMultiTexCoord2fARB(dynTarget, params->modTexCoord[0][1], params->modTexCoord[1][0]); glVertex3f(params->vertices[3].pos[VX], params->vertices[3].pos[VZ], params->vertices[3].pos[VY]); glColor4fv(params->vertices[2].color); glMultiTexCoord2fARB(normalTarget, params->texCoord[1][0], params->texCoord[1][1]); glMultiTexCoord2fARB(dynTarget, params->modTexCoord[0][1], params->modTexCoord[1][1]); glVertex3f(params->vertices[2].pos[VX], params->vertices[2].pos[VZ], params->vertices[2].pos[VY]); glEnd(); // Restore normal GL state. GL_SelectTexUnits(1); GL_ModulateTexture(1); GL_DisableArrays(true, true, 0x1); } else { glBegin(GL_QUADS); glColor4fv(params->vertices[0].color); glTexCoord2f(params->texCoord[0][0], params->texCoord[1][1]); glVertex3f(params->vertices[0].pos[VX], params->vertices[0].pos[VZ], params->vertices[0].pos[VY]); glColor4fv(params->vertices[1].color); glTexCoord2f(params->texCoord[0][0], params->texCoord[0][1]); glVertex3f(params->vertices[1].pos[VX], params->vertices[1].pos[VZ], params->vertices[1].pos[VY]); glColor4fv(params->vertices[3].color); glTexCoord2f(params->texCoord[1][0], params->texCoord[0][1]); glVertex3f(params->vertices[3].pos[VX], params->vertices[3].pos[VZ], params->vertices[3].pos[VY]); glColor4fv(params->vertices[2].color); glTexCoord2f(params->texCoord[1][0], params->texCoord[1][1]); glVertex3f(params->vertices[2].pos[VX], params->vertices[2].pos[VZ], params->vertices[2].pos[VY]); glEnd(); } GL_BlendMode(BM_NORMAL); } static void setupModelParamsForVisPSprite(rendmodelparams_t* params, vispsprite_t* spr) { params->mf = spr->data.model.mf; params->nextMF = spr->data.model.nextMF; params->inter = spr->data.model.inter; params->alwaysInterpolate = false; params->id = spr->data.model.id; params->selector = spr->data.model.selector; params->flags = spr->data.model.flags; params->center[VX] = spr->center[VX]; params->center[VY] = spr->center[VY]; params->center[VZ] = spr->center[VZ]; params->srvo[VX] = spr->data.model.visOff[VX]; params->srvo[VY] = spr->data.model.visOff[VY]; params->srvo[VZ] = spr->data.model.visOff[VZ] - spr->data.model.floorClip; params->gzt = spr->data.model.gzt; params->distance = -10; params->yaw = spr->data.model.yaw; params->extraYawAngle = 0; params->yawAngleOffset = spr->data.model.yawAngleOffset; params->pitch = spr->data.model.pitch; params->extraPitchAngle = 0; params->pitchAngleOffset = spr->data.model.pitchAngleOffset; params->extraScale = 0; params->viewAlign = spr->data.model.viewAligned; params->mirror = (mirrorHudModels? true : false); params->shineYawOffset = -vang; params->shinePitchOffset = vpitch + 90; params->shineTranslateWithViewerPos = false; params->shinepspriteCoordSpace = true; params->ambientColor[CA] = spr->data.model.alpha; if((levelFullBright || spr->data.model.stateFullBright) && !(spr->data.model.mf->sub[0].flags & MFF_DIM)) { params->ambientColor[CR] = params->ambientColor[CG] = params->ambientColor[CB] = 1; params->vLightListIdx = 0; } else { collectaffectinglights_params_t lparams; if(useBias) { LG_Evaluate(params->center, params->ambientColor); } else { float lightLevel; const float* secColor = R_GetSectorLightColor(spr->data.model.subsector->sector); // Diminished light (with compression). lightLevel = spr->data.model.subsector->sector->lightLevel; // No need for distance attentuation. // Add extra light. lightLevel += R_ExtraLightDelta(); // The last step is to compress the resultant light value by // the global lighting function. Rend_ApplyLightAdaptation(&lightLevel); // Determine the final ambientColor in effect. params->ambientColor[CR] = lightLevel * secColor[CR]; params->ambientColor[CG] = lightLevel * secColor[CG]; params->ambientColor[CB] = lightLevel * secColor[CB]; } Rend_ApplyTorchLight(params->ambientColor, params->distance); lparams.starkLight = true; lparams.center[VX] = spr->center[VX]; lparams.center[VY] = spr->center[VY]; lparams.center[VZ] = spr->center[VZ]; lparams.subsector = spr->data.model.subsector; lparams.ambientColor = params->ambientColor; params->vLightListIdx = R_CollectAffectingLights(&lparams); } } static boolean generateHaloForVisSprite(const vissprite_t* spr, boolean primary) { float occlussionFactor; if(primary && (spr->data.flare.flags & RFF_NO_PRIMARY)) return false; if(spr->data.flare.isDecoration) { /** * \kludge surface decorations do not yet persist over frames, * thus we do not smoothly occlude their flares. Instead, we will * have to put up with them instantly appearing/disappearing. */ occlussionFactor = (LO_IsClipped(spr->data.flare.lumIdx, viewPlayer - ddPlayers)? 0 : 1); } else occlussionFactor = (spr->data.flare.factor & 0x7f) / 127.0f; return H_RenderHalo(spr->center[VX], spr->center[VY], spr->center[VZ], spr->data.flare.size, spr->data.flare.tex, spr->data.flare.color, spr->distance, occlussionFactor, spr->data.flare.mul, spr->data.flare.xOff, primary, (spr->data.flare.flags & RFF_NO_TURN)); } /** * Render sprites, 3D models, masked wall segments and halos, ordered * back to front. Halos are rendered with Z-buffer tests and writes * disabled, so they don't go into walls or interfere with real objects. * It means that halos can be partly occluded by objects that are closer * to the viewpoint, but that's the price to pay for not having access to * the actual Z-buffer per-pixel depth information. The other option would * be for halos to shine through masked walls, sprites and models, which * looks even worse. (Plus, they are *halos*, not real lens flares...) */ void Rend_DrawMasked(void) { boolean flareDrawn = false; vissprite_t* spr; if(devNoSprites) return; R_SortVisSprites(); if(visSpriteP > visSprites) { // Draw all vissprites back to front. // Sprites look better with Z buffer writes turned off. for(spr = visSprSortedHead.next; spr != &visSprSortedHead; spr = spr->next) { switch(spr->type) { default: break; case VSPR_MASKED_WALL: // A masked wall is a specialized sprite. Rend_RenderMaskedWall(&spr->data.wall); break; case VSPR_SPRITE: // Render an old fashioned sprite, ah the nostalgia... Rend_RenderSprite(&spr->data.sprite); break; case VSPR_MODEL: Rend_RenderModel(&spr->data.model); break; case VSPR_FLARE: if(generateHaloForVisSprite(spr, true) && !flareDrawn) flareDrawn = true; break; } } // Draw secondary halos. if(flareDrawn && haloMode > 1) { // Now we can setup the state only once. H_SetupState(true); for(spr = visSprSortedHead.next; spr != &visSprSortedHead; spr = spr->next) { if(spr->type == VSPR_FLARE) { generateHaloForVisSprite(spr, false); } } // And we're done... H_SetupState(false); } } } #if _DEBUG boolean drawVLightVector(const vlight_t* light, void* context) { float scale = 100; glBegin(GL_LINES); { glColor4f(light->color[CR], light->color[CG], light->color[CB], 1); glVertex3f(scale * light->vector[VX], scale * light->vector[VZ], scale * light->vector[VY]); glColor4f(0, 0, 0, 1); glVertex3f(0, 0, 0); } glEnd(); return true; // Continue iteration. } #endif void Rend_RenderSprite(const rendspriteparams_t* params) { int i; dgl_color_t quadColors[4]; dgl_vertex_t quadNormals[4]; boolean restoreMatrix = false; boolean restoreZ = false; float spriteCenter[3]; float surfaceNormal[3]; float v1[3], v2[3], v3[3], v4[3]; material_t* mat = NULL; material_snapshot_t ms; if(renderTextures == 1) mat = params->mat; else if(renderTextures == 2) // For lighting debug, render all solid surfaces using the gray texture. mat = P_GetMaterial(DDT_GRAY, MN_SYSTEM); if(mat) { // Might we need a colour translation? if(renderTextures == 1) { // Possibly. material_load_params_t mparams; memset(&mparams, 0, sizeof(mparams)); mparams.tmap = params->tMap; mparams.tclass = params->tClass; mparams.pSprite = false; Material_Prepare(&ms, mat, true, &mparams); } else { Material_Prepare(&ms, mat, true, NULL); } GL_BindTexture(ms.units[MTU_PRIMARY].texInst->id, ms.units[MTU_PRIMARY].magMode); } else { GL_SetNoTexture(); } // Coordinates to the center of the sprite (game coords). spriteCenter[VX] = params->center[VX] + params->srvo[VX]; spriteCenter[VY] = params->center[VY] + params->srvo[VY]; spriteCenter[VZ] = params->center[VZ] + params->srvo[VZ]; M_ProjectViewRelativeLine2D(spriteCenter, params->viewAligned, params->width, params->viewOffX, v1, v4); v2[VX] = v1[VX]; v2[VY] = v1[VY]; v3[VX] = v4[VX]; v3[VY] = v4[VY]; v1[VZ] = v4[VZ] = spriteCenter[VZ] - params->height / 2; v2[VZ] = v3[VZ] = spriteCenter[VZ] + params->height / 2; // Calculate the surface normal. M_PointCrossProduct(v2, v1, v3, surfaceNormal); M_Normalize(surfaceNormal); /*#if _DEBUG // Draw the surface normal. glDisable(GL_TEXTURE2D); glBegin(GL_LINES); glColor4f(1, 0, 0, 1); glVertex3f(spriteCenter[VX], spriteCenter[VZ], spriteCenter[VY]); glColor4f(1, 0, 0, 0); glVertex3f(spriteCenter[VX] + surfaceNormal[VX] * 10, spriteCenter[VZ] + surfaceNormal[VZ] * 10, spriteCenter[VY] + surfaceNormal[VY] * 10); glEnd(); glEnable(GL_TEXTURE2D); #endif*/ // All sprite vertices are co-plannar, so just copy the surface normal. // \fixme: Can we do something better here? for(i = 0; i < 4; ++i) memcpy(quadNormals[i].xyz, surfaceNormal, sizeof(surfaceNormal)); if(!params->vLightListIdx) { // Lit uniformly. Spr_UniformVertexColors(4, quadColors, params->ambientColor); } else { // Lit normally. Spr_VertexColors(4, quadColors, quadNormals, params->vLightListIdx, spriteLight + 1, params->ambientColor); } /*#if _DEBUG if(params->vLightListIdx) { // Draw the vlight vectors, for debug. glDisable(GL_TEXTURE2D); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glTranslatef(params->center[VX], params->center[VZ], params->center[VY]); VL_ListIterator(params->vLightListIdx, NULL, drawVLightVector); glMatrixMode(GL_MODELVIEW); glPopMatrix(); glEnable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glEnable(GL_TEXTURE2D); } #endif*/ // Do we need to do some aligning? if(params->viewAligned || alwaysAlign >= 2) { // We must set up a modelview transformation matrix. restoreMatrix = true; glMatrixMode(GL_MODELVIEW); glPushMatrix(); // Rotate around the center of the sprite. glTranslatef(spriteCenter[VX], spriteCenter[VZ], spriteCenter[VY]); if(!params->viewAligned) { float s_dx = v1[VX] - v2[VX]; float s_dy = v1[VY] - v2[VY]; if(alwaysAlign == 2) { // Restricted camera alignment. float dx = spriteCenter[VX] - vx; float dy = spriteCenter[VY] - vz; float spriteAngle = BANG2DEG(bamsAtan2(spriteCenter[VZ] - vy, sqrt(dx * dx + dy * dy))); if(spriteAngle > 180) spriteAngle -= 360; if(fabs(spriteAngle) > maxSpriteAngle) { float turnAngle = (spriteAngle > 0 ? spriteAngle - maxSpriteAngle : spriteAngle + maxSpriteAngle); // Rotate along the sprite edge. glRotatef(turnAngle, s_dx, 0, s_dy); } } else { // Restricted view plane alignment. // This'll do, for now... Really it should notice both the // sprite angle and vpitch. glRotatef(vpitch * .5f, s_dx, 0, s_dy); } } else { // Normal rotation perpendicular to the view plane. glRotatef(vpitch, viewsidex, 0, viewsidey); } glTranslatef(-spriteCenter[VX], -spriteCenter[VZ], -spriteCenter[VY]); } // Need to change blending modes? if(params->blendMode != BM_NORMAL) GL_BlendMode(params->blendMode); // Transparent sprites shouldn't be written to the Z buffer. if(params->noZWrite || params->ambientColor[CA] < .98f || !(params->blendMode == BM_NORMAL || params->blendMode == BM_ZEROALPHA)) { restoreZ = true; glDepthMask(GL_FALSE); } { dgl_vertex_t vs[4], *v = vs; dgl_texcoord_t tcs[4], *tc = tcs; // 1---2 // | | Vertex layout. // 0---3 v[0].xyz[0] = v1[VX]; v[0].xyz[1] = v1[VZ]; v[0].xyz[2] = v1[VY]; v[1].xyz[0] = v2[VX]; v[1].xyz[1] = v2[VZ]; v[1].xyz[2] = v2[VY]; v[2].xyz[0] = v3[VX]; v[2].xyz[1] = v3[VZ]; v[2].xyz[2] = v3[VY]; v[3].xyz[0] = v4[VX]; v[3].xyz[1] = v4[VZ]; v[3].xyz[2] = v4[VY]; tc[0].st[0] = params->matOffset[0] * (params->matFlip[0]? 1:0); tc[0].st[1] = params->matOffset[1] * (!params->matFlip[1]? 1:0); tc[1].st[0] = params->matOffset[0] * (params->matFlip[0]? 1:0); tc[1].st[1] = params->matOffset[1] * (params->matFlip[1]? 1:0); tc[2].st[0] = params->matOffset[0] * (!params->matFlip[0]? 1:0); tc[2].st[1] = params->matOffset[1] * (params->matFlip[1]? 1:0); tc[3].st[0] = params->matOffset[0] * (!params->matFlip[0]? 1:0); tc[3].st[1] = params->matOffset[1] * (!params->matFlip[1]? 1:0); renderQuad(v, quadColors, tc); } // Need to restore the original modelview matrix? if(restoreMatrix) glPopMatrix(); // Change back to normal blending? if(params->blendMode != BM_NORMAL) GL_BlendMode(BM_NORMAL); // Enable Z-writing again? if(restoreZ) glDepthMask(GL_TRUE); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_decor.c0000644000175000017500000006646311357170242023220 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_decor.c: Decorations * * Surface decorations. */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_play.h" #include "de_refresh.h" #include "de_graphics.h" #include "de_render.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // Quite a bit of decorations, there! #define MAX_DECOR_LIGHTS (16384) #define MAX_DECOR_MODELS (8192) BEGIN_PROF_TIMERS() PROF_DECOR_UPDATE, PROF_DECOR_PROJECT, PROF_DECOR_ADD_LUMINOUS END_PROF_TIMERS() // TYPES ------------------------------------------------------------------- typedef struct decorsource_s { float pos[3]; float maxDistance; const surface_t* surface; subsector_t* subsector; decortype_t type; unsigned int lumIdx; // index+1 of linked lumobj, or 0. float fadeMul; union decorsource_data_s { struct decorsource_data_light_s { const ded_decorlight_t* def; } light; struct decorsource_data_model_s { const ded_decormodel_t* def; struct modeldef_s* mf; float pitch, yaw; } model; } data; struct decorsource_s* next; } decorsource_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- byte useDecorations = true; float decorMaxDist = 2048; // No decorations are visible beyond this. float decorFactor = 1; float decorFadeAngle = .1f; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static uint numDecorLights = 0, numDecorModels = 0; static decorsource_t* sourceFirst = NULL, *sourceLast = NULL; static decorsource_t* sourceCursor = NULL; // CODE -------------------------------------------------------------------- void Rend_DecorRegister(void) { C_VAR_BYTE("rend-light-decor", &useDecorations, 0, 0, 1); C_VAR_FLOAT("rend-light-decor-angle", &decorFadeAngle, 0, 0, 1); C_VAR_FLOAT("rend-light-decor-bright", &decorFactor, 0, 0, 10); } /** * Clears the list of decoration dummies. */ static void clearDecorations(void) { numDecorLights = numDecorModels = 0; sourceCursor = sourceFirst; } extern void setupModelParamsForVisSprite(rendmodelparams_t *params, float x, float y, float z, float distance, float visOffX, float visOffY, float visOffZ, float gzt, float yaw, float yawAngleOffset, float pitch, float pitchAngleOffset, struct modeldef_s* mf, struct modeldef_s* nextMF, float inter, float ambientColorR, float ambientColorG, float ambientColorB, float alpha, vlight_t* lightList, uint numLights, int id, int selector, subsector_t* ssec, int mobjDDFlags, int tmap, boolean viewAlign, boolean fullBright, boolean alwaysInterpolate); extern void getLightingParams(float x, float y, float z, subsector_t* ssec, float distance, boolean fullBright, uint maxLights, float ambientColor[3], vlight_t** lights, uint* numLights); static void projectDecoration(decorsource_t* src) { float v1[2], min, max; vissprite_t* vis; float distance, brightness; // Does it pass the sector light limitation? if(src->type == DT_LIGHT) { min = src->data.light.def->lightLevels[0]; max = src->data.light.def->lightLevels[1]; } else // Its a decor model. { min = src->data.model.def->lightLevels[0]; max = src->data.model.def->lightLevels[0]; } if(!((brightness = R_CheckSectorLight(src->subsector->sector->lightLevel, min, max)) > 0)) return; if(src->fadeMul <= 0) return; // Is the point in range? distance = Rend_PointDist3D(src->pos); if(distance > src->maxDistance) return; // Calculate edges of the shape. v1[VX] = src->pos[VX]; v1[VY] = src->pos[VY]; /** * Model decorations become model-type vissprites. * Light decorations become flare-type vissprites. */ vis = R_NewVisSprite(); vis->type = ((src->type == DT_MODEL)? VSPR_MODEL : VSPR_FLARE); vis->center[VX] = src->pos[VX]; vis->center[VY] = src->pos[VY]; vis->center[VZ] = src->pos[VZ]; vis->distance = distance; switch(src->type) { case DT_MODEL: { float ambientColor[3]; vlight_t* lightList = NULL; uint numLights = 0; getLightingParams(src->pos[VX], src->pos[VY], src->pos[VZ], src->subsector, distance, levelFullBright, modelLight, ambientColor, &lightList, &numLights); setupModelParamsForVisSprite(&vis->data.model, src->pos[VX], src->pos[VY], src->pos[VZ], distance, 0, 0, 0, src->pos[VZ], src->data.model.yaw, 0, src->data.model.pitch, 0, src->data.model.mf, NULL, 0, ambientColor[CR], ambientColor[CG], ambientColor[CB], src->fadeMul, lightList, numLights, 0, 0, src->subsector, 0, 0, false, levelFullBright, true); break; } case DT_LIGHT: { const ded_decorlight_t* def = src->data.light.def; const lumobj_t* lum = LO_GetLuminous(src->lumIdx); vis->data.flare.isDecoration = true; vis->data.flare.lumIdx = src->lumIdx; // Color is taken from the associated lumobj. V3_Copy(vis->data.flare.color, LUM_OMNI(lum)->color); if(def->haloRadius > 0) { vis->data.flare.size = MAX_OF(1, def->haloRadius * 60 * (50 + haloSize) / 100.0f); } else { vis->data.flare.size = 0; } if(!(def->flare.id && def->flare.id[0] == '-')) { vis->data.flare.tex = GL_GetFlareTexture(def->flare.id, def->flareTexture); } else { // Primary halo disabled. vis->data.flare.flags |= RFF_NO_PRIMARY; vis->data.flare.tex = 0; } // Halo brightness drops as the angle gets too big. vis->data.flare.mul = 1; if(src->data.light.def->elevation < 2 && decorFadeAngle > 0) // Close the surface? { float vector[3], dot; vector[VX] = src->pos[VX] - vx; vector[VY] = src->pos[VY] - vz; vector[VZ] = src->pos[VZ] - vy; M_Normalize(vector); dot = -(src->surface->normal[VX] * vector[VX] + src->surface->normal[VY] * vector[VY] + src->surface->normal[VZ] * vector[VZ]); if(dot < decorFadeAngle / 2) vis->data.flare.mul = 0; else if(dot < 3 * decorFadeAngle) vis->data.flare.mul = (dot - decorFadeAngle / 2) / (2.5f * decorFadeAngle); } break; } } } /** * Project all the non-clipped decorations. They become regular vissprites. */ void Rend_ProjectDecorations(void) { if(sourceFirst != sourceCursor) { decorsource_t* src = sourceFirst; do { projectDecoration(src); } while((src = src->next) != sourceCursor); } } static void addLuminousDecoration(decorsource_t* src) { uint i; float min, max; uint lumIdx; lumobj_t* l; float brightness; const ded_decorlight_t* def = src->data.light.def; src->lumIdx = 0; src->fadeMul = 1; if(src->type != DT_LIGHT) return; // Does it pass the sector light limitation? min = def->lightLevels[0]; max = def->lightLevels[1]; if(!((brightness = R_CheckSectorLight( src->subsector->sector->lightLevel, min, max)) > 0)) return; // Apply the brightness factor (was calculated using sector lightlevel). src->fadeMul *= brightness * decorFactor; if(src->fadeMul <= 0) return; /** * \todo From here on is pretty much the same as LO_AddLuminous, * reconcile the two. */ lumIdx = LO_NewLuminous(LT_OMNI, src->subsector); l = LO_GetLuminous(lumIdx); l->pos[VX] = src->pos[VX]; l->pos[VY] = src->pos[VY]; l->pos[VZ] = src->pos[VZ]; l->maxDistance = src->maxDistance; l->decorSource = src; LUM_OMNI(l)->zOff = 0; LUM_OMNI(l)->tex = GL_GetLightMapTexture(def->sides.id); LUM_OMNI(l)->ceilTex = GL_GetLightMapTexture(def->up.id); LUM_OMNI(l)->floorTex = GL_GetLightMapTexture(def->down.id); // These are the same rules as in DL_MobjRadius(). LUM_OMNI(l)->radius = def->radius * 40 * loRadiusFactor; // Don't make a too small or too large light. if(LUM_OMNI(l)->radius > loMaxRadius) LUM_OMNI(l)->radius = loMaxRadius; for(i = 0; i < 3; ++i) LUM_OMNI(l)->color[i] = def->color[i] * src->fadeMul; src->lumIdx = lumIdx; } /** * Create lumobjs for all decorations who want them. */ void Rend_AddLuminousDecorations(void) { BEGIN_PROF( PROF_DECOR_ADD_LUMINOUS ); if(sourceFirst != sourceCursor) { decorsource_t* src = sourceFirst; do { addLuminousDecoration(src); } while((src = src->next) != sourceCursor); } END_PROF( PROF_DECOR_ADD_LUMINOUS ); } /** * Create a new decoration source. */ static decorsource_t* addDecoration(void) { decorsource_t* src; // If the cursor is NULL, new sources must be allocated. if(!sourceCursor) { // Allocate a new entry. src = Z_Calloc(sizeof(decorsource_t), PU_STATIC, NULL); if(sourceLast) sourceLast->next = src; sourceLast = src; if(!sourceFirst) sourceFirst = src; } else { // There are old sources to use. src = sourceCursor; // Advance the cursor. sourceCursor = sourceCursor->next; } return src; } /** * A decorsource is created from the specified surface decoration. */ static void createDecorSource(const surface_t* suf, const surfacedecor_t* dec, const float maxDistance) { decorsource_t* src; if(dec->type == DT_LIGHT) { if(numDecorLights > MAX_DECOR_LIGHTS) return; // Out of sources! numDecorLights++; } else // It's a model decoration. { if(numDecorModels > MAX_DECOR_MODELS) return; // Out of sources! numDecorModels++; } // Fill in the data for a new surface decoration. src = addDecoration(); src->pos[VX] = dec->pos[VX]; src->pos[VY] = dec->pos[VY]; src->pos[VZ] = dec->pos[VZ]; src->maxDistance = maxDistance; src->subsector = dec->subsector; src->surface = suf; src->type = dec->type; switch(src->type) { case DT_LIGHT: src->data.light.def = DEC_LIGHT(dec)->def; break; case DT_MODEL: src->data.model.def = DEC_MODEL(dec)->def; src->data.model.mf = DEC_MODEL(dec)->mf; src->data.model.pitch = DEC_MODEL(dec)->pitch; src->data.model.yaw = DEC_MODEL(dec)->yaw; break; } } boolean R_IsValidModelDecoration(const ded_decormodel_t* modelDef) { return ((modelDef && modelDef->id && modelDef->id[0])? true : false); } /** * @return As this can also be used with iterators, will always * return @c true. */ boolean R_ProjectSurfaceDecorations(surface_t* suf, void* context) { uint i; float maxDist = *((float*) context); for(i = 0; i < suf->numDecorations; ++i) { const surfacedecor_t* d = &suf->decorations[i]; switch(d->type) { case DT_LIGHT: if(!R_IsValidLightDecoration(DEC_LIGHT(d)->def)) return true; break; case DT_MODEL: if(!R_IsValidModelDecoration(DEC_MODEL(d)->def)) return true; break; } createDecorSource(suf, d, maxDist); } return true; } /** * Determine proper skip values. */ static void getDecorationSkipPattern(const int patternSkip[2], int* skip) { uint i; for(i = 0; i < 2; ++i) { // Skip must be at least one. skip[i] = patternSkip[i] + 1; if(skip[i] < 1) skip[i] = 1; } } static uint generateDecorLights(const ded_decorlight_t* def, surface_t* suf, const pvec3_t v1, const pvec3_t v2, float width, float height, const pvec3_t delta, int axis, float offsetS, float offsetT, sector_t* sec) { uint num; float s, t; // Horizontal and vertical offset. vec3_t posBase, pos; float patternW, patternH; int skip[2]; material_t* mat = suf->material; if(!R_IsValidLightDecoration(def)) return 0; // Skip must be at least one. getDecorationSkipPattern(def->patternSkip, skip); patternW = mat->width * skip[0]; patternH = mat->height * skip[1]; V3_Set(posBase, def->elevation * suf->normal[VX], def->elevation * suf->normal[VY], def->elevation * suf->normal[VZ]); V3_Sum(posBase, posBase, v1); // Let's see where the top left light is. s = M_CycleIntoRange(def->pos[0] - suf->visOffset[0] - mat->width * def->patternOffset[0] + offsetS, patternW); num = 0; for(; s < width; s += patternW) { t = M_CycleIntoRange(def->pos[1] - suf->visOffset[1] - mat->height * def->patternOffset[1] + offsetT, patternH); for(; t < height; t += patternH) { surfacedecor_t* d; float offS = s / width, offT = t / height; V3_Set(pos, delta[VX] * offS, delta[VY] * (axis == VZ? offT : offS), delta[VZ] * (axis == VZ? offS : offT)); V3_Sum(pos, posBase, pos); if(sec) { // The point must be inside the correct sector. if(!R_IsPointInSector(pos[VX], pos[VY], sec)) continue; } if(NULL != (d = R_CreateSurfaceDecoration(DT_LIGHT, suf))) { V3_Copy(d->pos, pos); d->subsector = R_PointInSubsector(d->pos[VX], d->pos[VY]); DEC_LIGHT(d)->def = def; R_SurfaceListAdd(decoratedSurfaceList, suf); num++; } } } return num; } static uint generateDecorModels(const ded_decormodel_t* def, surface_t* suf, const pvec3_t v1, const pvec3_t v2, float width, float height, const pvec3_t delta, int axis, float offsetS, float offsetT, sector_t* sec) { uint num; modeldef_t* mf; float pitch, yaw; float patternW, patternH; float s, t; // Horizontal and vertical offset. vec3_t posBase, pos; int skip[2]; material_t* mat = suf->material; if(!R_IsValidModelDecoration(def)) return 0; if((mf = R_CheckIDModelFor(def->id)) == NULL) return 0; yaw = R_MovementYaw(suf->normal[VX], suf->normal[VY]); if(axis == VZ) yaw += 90; pitch = R_MovementPitch(suf->normal[VX], suf->normal[VY], suf->normal[VZ]); // Skip must be at least one. getDecorationSkipPattern(def->patternSkip, skip); patternW = mat->width * skip[0]; patternH = mat->height * skip[1]; V3_Set(posBase, def->elevation * suf->normal[VX], def->elevation * suf->normal[VY], def->elevation * suf->normal[VZ]); V3_Sum(posBase, posBase, v1); // Let's see where the top left light is. s = M_CycleIntoRange(def->pos[0] - suf->visOffset[0] - mat->width * def->patternOffset[0] + offsetS, patternW); num = 0; for(; s < width; s += patternW) { t = M_CycleIntoRange(def->pos[1] - suf->visOffset[1] - mat->height * def->patternOffset[1] + offsetT, patternH); for(; t < height; t += patternH) { surfacedecor_t *d; float offS = s / width, offT = t / height; V3_Set(pos, delta[VX] * offS, delta[VY] * (axis == VZ? offT : offS), delta[VZ] * (axis == VZ? offS : offT)); V3_Sum(pos, posBase, pos); if(sec) { // The point must be inside the correct sector. if(!R_IsPointInSector(pos[VX], pos[VY], sec)) continue; } if(NULL != (d = R_CreateSurfaceDecoration(DT_MODEL, suf))) { V3_Copy(d->pos, pos); d->subsector = R_PointInSubsector(d->pos[VX], d->pos[VY]); DEC_MODEL(d)->def = def; DEC_MODEL(d)->mf = mf; DEC_MODEL(d)->pitch = pitch; DEC_MODEL(d)->yaw = yaw; R_SurfaceListAdd(decoratedSurfaceList, suf); num++; } } } return num; } /** * Generate decorations for the specified surface. */ static void updateSurfaceDecorations(surface_t* suf, float offsetS, float offsetT, vec3_t v1, vec3_t v2, sector_t* sec, boolean visible) { vec3_t delta; R_ClearSurfaceDecorations(suf); R_SurfaceListRemove(decoratedSurfaceList, suf); V3_Subtract(delta, v2, v1); if(visible && (delta[VX] * delta[VY] != 0 || delta[VX] * delta[VZ] != 0 || delta[VY] * delta[VZ] != 0)) { uint i; float matW, matH, width, height; int axis = V3_MajorAxis(suf->normal); const ded_decor_t* def = Material_GetDecoration(suf->material); if(def) { matW = suf->material->width; matH = suf->material->height; if(axis == VX || axis == VY) { width = sqrt(delta[VX] * delta[VX] + delta[VY] * delta[VY]); height = delta[VZ]; } else { width = sqrt(delta[VX] * delta[VX]); height = delta[VY]; } if(width < 0) width = -width; if(height < 0) height = -height; // Generate a number of models. for(i = 0; i < DED_DECOR_NUM_MODELS; ++i) { generateDecorModels(&def->models[i], suf, v1, v2, width, height, delta, axis, offsetS, offsetT, sec); } // Generate a number of lights. for(i = 0; i < DED_DECOR_NUM_LIGHTS; ++i) { generateDecorLights(&def->lights[i], suf, v1, v2, width, height, delta, axis, offsetS, offsetT, sec); } } } suf->inFlags &= ~SUIF_UPDATE_DECORATIONS; } /** * Generate decorations for a plane. */ static void updatePlaneDecorations(plane_t* pln) { sector_t* sec = pln->sector; surface_t* suf = &pln->surface; vec3_t v1, v2; float offsetS, offsetT; if(pln->type == PLN_FLOOR) { V3_Set(v1, sec->bBox[BOXLEFT], sec->bBox[BOXTOP], pln->visHeight); V3_Set(v2, sec->bBox[BOXRIGHT], sec->bBox[BOXBOTTOM], pln->visHeight); } else { V3_Set(v1, sec->bBox[BOXLEFT], sec->bBox[BOXBOTTOM], pln->visHeight); V3_Set(v2, sec->bBox[BOXRIGHT], sec->bBox[BOXTOP], pln->visHeight); } offsetS = -fmod(sec->bBox[BOXLEFT], 64); offsetT = -fmod(sec->bBox[BOXBOTTOM], 64); updateSurfaceDecorations(suf, offsetS, offsetT, v1, v2, sec, suf->material? true : false); } static void updateSideSectionDecorations(sidedef_t* side, segsection_t section) { linedef_t* line; surface_t* suf; vec3_t v1, v2; int sid; float offsetS = 0, offsetT = 0; boolean visible = false; const plane_t* frontCeil, *frontFloor, *backCeil, *backFloor; float bottom, top; if(!side->segs || !side->segs[0]) return; line = side->segs[0]->lineDef; sid = (line->L_backside && line->L_backside == side)? 1 : 0; frontCeil = line->L_sector(sid)->SP_plane(PLN_CEILING); frontFloor = line->L_sector(sid)->SP_plane(PLN_FLOOR); if(line->L_backside) { backCeil = line->L_sector(sid^1)->SP_plane(PLN_CEILING); backFloor = line->L_sector(sid^1)->SP_plane(PLN_FLOOR); } switch(section) { case SEG_MIDDLE: suf = &side->SW_middlesurface; if(suf->material) if(!line->L_backside) { top = frontCeil->visHeight; bottom = frontFloor->visHeight; if(line->flags & DDLF_DONTPEGBOTTOM) offsetT += frontCeil->visHeight - frontFloor->visHeight; visible = true; } else { float texOffset[2]; if(R_FindBottomTop(SEG_MIDDLE, 0, suf, frontFloor, frontCeil, backFloor, backCeil, (line->flags & DDLF_DONTPEGBOTTOM)? true : false, (line->flags & DDLF_DONTPEGTOP)? true : false, (side->flags & SDF_MIDDLE_STRETCH)? true : false, LINE_SELFREF(line)? true : false, &bottom, &top, texOffset)) { offsetS = texOffset[VX]; offsetT = texOffset[VY]; visible = true; } } break; case SEG_TOP: suf = &side->SW_topsurface; if(suf->material) if(line->L_backside && backCeil->visHeight < frontCeil->visHeight && (!R_IsSkySurface(&backCeil->surface) || !R_IsSkySurface(&frontCeil->surface))) { top = frontCeil->visHeight; bottom = backCeil->visHeight; if(!(line->flags & DDLF_DONTPEGTOP)) offsetT += frontCeil->visHeight - backCeil->visHeight; visible = true; } break; case SEG_BOTTOM: suf = &side->SW_bottomsurface; if(suf->material) if(line->L_backside && backFloor->visHeight > frontFloor->visHeight && (!R_IsSkySurface(&backFloor->surface) || !R_IsSkySurface(&frontFloor->surface))) { top = backFloor->visHeight; bottom = frontFloor->visHeight; if(line->flags & DDLF_DONTPEGBOTTOM) offsetT -= frontCeil->visHeight - backFloor->visHeight; visible = true; } break; } if(visible) { V3_Set(v1, line->L_vpos(sid )[VX], line->L_vpos(sid )[VY], top); V3_Set(v2, line->L_vpos(sid^1)[VX], line->L_vpos(sid^1)[VY], bottom); } updateSurfaceDecorations(suf, offsetS, offsetT, v1, v2, NULL, visible); } void Rend_UpdateSurfaceDecorations(void) { BEGIN_PROF( PROF_DECOR_UPDATE ); // This only needs to be done if decorations have been enabled. if(useDecorations) { uint i; // Process all sidedefs. for(i = 0; i < numSideDefs; ++i) { sidedef_t* side = &sideDefs[i]; surface_t* suf; suf = &side->SW_middlesurface; if(suf->inFlags & SUIF_UPDATE_DECORATIONS) updateSideSectionDecorations(side, SEG_MIDDLE); suf = &side->SW_topsurface; if(suf->inFlags & SUIF_UPDATE_DECORATIONS) updateSideSectionDecorations(side, SEG_TOP); suf = &side->SW_bottomsurface; if(suf->inFlags & SUIF_UPDATE_DECORATIONS) updateSideSectionDecorations(side, SEG_BOTTOM); } // Process all planes. for(i = 0; i < numSectors; ++i) { uint j; sector_t* sec = §ors[i]; for(j = 0; j < sec->planeCount; ++j) { plane_t* pln = sec->SP_plane(j); if(pln->surface.inFlags & SUIF_UPDATE_DECORATIONS) updatePlaneDecorations(pln); } } } END_PROF( PROF_DECOR_UPDATE ); } /** * Decorations are generated for each frame. */ void Rend_InitDecorationsForFrame(void) { #ifdef DD_PROFILE static int i; if(++i > 40) { i = 0; PRINT_PROF( PROF_DECOR_UPDATE ); PRINT_PROF( PROF_DECOR_PROJECT ); PRINT_PROF( PROF_DECOR_ADD_LUMINOUS ); } #endif clearDecorations(); // This only needs to be done if decorations have been enabled. if(useDecorations) { Rend_UpdateSurfaceDecorations(); // temporary. BEGIN_PROF( PROF_DECOR_PROJECT ); R_SurfaceListIterate(decoratedSurfaceList, R_ProjectSurfaceDecorations, &decorMaxDist); END_PROF( PROF_DECOR_PROJECT ); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_draw.c0000644000175000017500000001222211357170242022352 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_draw.c: Drawing Routines */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_graphics.h" #include "de_refresh.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- enum { // A logical ordering (twice around). BG_BACKGROUND, BG_TOP, BG_RIGHT, BG_BOTTOM, BG_LEFT, BG_TOPLEFT, BG_TOPRIGHT, BG_BOTTOMRIGHT, BG_BOTTOMLEFT }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The view window. int viewwidth, viewheight, viewwindowx, viewwindowy; // View border width. int bwidth; byte* translationTables; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static char borderGfx[9][9]; // CODE -------------------------------------------------------------------- void R_SetBorderGfx(char *gfx[9]) { uint i; for(i = 0; i < 9; ++i) if(gfx[i]) strcpy(borderGfx[i], gfx[i]); else strcpy(borderGfx[i], "-"); R_InitViewBorder(); } void R_InitViewBorder(void) { lumppatch_t* patch = NULL; // Detemine the view border width. if(W_CheckNumForName(borderGfx[BG_TOP]) == -1) return; patch = (lumppatch_t*) W_CacheLumpName(borderGfx[BG_TOP], PU_CACHE); bwidth = SHORT(patch->height); } /** * Draws the border around the view for different size windows. */ void R_DrawViewBorder(void) { patchtex_t* p; material_t* mat; if(viewwidth == 320 && viewheight == 200) return; glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, 320, 200, 0, -1, 1); // View background. glColor4f(1, 1, 1, 1); mat = P_ToMaterial(P_MaterialNumForName(borderGfx[BG_BACKGROUND], MN_FLATS)); if(mat) { GL_SetMaterial(mat); GL_DrawCutRectTiled(0, 0, 320, 200, mat->width, mat->height, 0, 0, viewwindowx - bwidth, viewwindowy - bwidth, viewwidth + 2 * bwidth, viewheight + 2 * bwidth); } // The border top. p = R_GetPatchTex(W_GetNumForName(borderGfx[BG_TOP])); GL_BindTexture(GL_PreparePatch(R_GetPatchTex(p->lump)), glmode[texMagMode]); GL_DrawRectTiled(viewwindowx, viewwindowy - bwidth, viewwidth, p->height, 16, p->height); // Border bottom. p = R_GetPatchTex(W_GetNumForName(borderGfx[BG_BOTTOM])); GL_BindTexture(GL_PreparePatch(R_GetPatchTex(p->lump)), glmode[texMagMode]); GL_DrawRectTiled(viewwindowx, viewwindowy + viewheight , viewwidth, p->height, 16, p->height); // Left view border. p = R_GetPatchTex(W_GetNumForName(borderGfx[BG_LEFT])); GL_BindTexture(GL_PreparePatch(R_GetPatchTex(p->lump)), glmode[texMagMode]); GL_DrawRectTiled(viewwindowx - bwidth, viewwindowy, p->width, viewheight, p->width, 16); // Right view border. p = R_GetPatchTex(W_GetNumForName(borderGfx[BG_RIGHT])); GL_BindTexture(GL_PreparePatch(R_GetPatchTex(p->lump)), glmode[texMagMode]); GL_DrawRectTiled(viewwindowx + viewwidth , viewwindowy, p->width, viewheight, p->width, 16); GL_UsePatchOffset(false); GL_DrawPatch(viewwindowx - bwidth, viewwindowy - bwidth, W_GetNumForName(borderGfx[BG_TOPLEFT])); GL_DrawPatch(viewwindowx + viewwidth, viewwindowy - bwidth, W_GetNumForName(borderGfx[BG_TOPRIGHT])); GL_DrawPatch(viewwindowx + viewwidth, viewwindowy + viewheight, W_GetNumForName(borderGfx[BG_BOTTOMRIGHT])); GL_DrawPatch(viewwindowx - bwidth, viewwindowy + viewheight, W_GetNumForName(borderGfx[BG_BOTTOMLEFT])); GL_UsePatchOffset(true); glMatrixMode(GL_PROJECTION); glPopMatrix(); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/net_event.c0000644000175000017500000001661511357170242023075 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_event.c: Network Events * * Network events include clients joining and leaving. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_system.h" #include "de_console.h" #include "de_network.h" // MACROS ------------------------------------------------------------------ #define MASTER_QUEUE_LEN 16 #define NETEVENT_QUEUE_LEN 32 #define MASTER_HEARTBEAT 120 // seconds // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // The master action queue. static masteraction_t masterQueue[MASTER_QUEUE_LEN]; static int mqHead, mqTail; // The net event queue (player arrive/leave). static netevent_t netEventQueue[NETEVENT_QUEUE_LEN]; static int neqHead, neqTail; // CODE -------------------------------------------------------------------- /** * Add a master action command to the queue. The master action stuff really * doesn't belong in this file... */ void N_MAPost(masteraction_t act) { masterQueue[mqHead++] = act; mqHead %= MASTER_QUEUE_LEN; } /** * Get a master action command from the queue. */ boolean N_MAGet(masteraction_t *act) { // Empty queue? if(mqHead == mqTail) return false; *act = masterQueue[mqTail]; return true; } /** * Remove a master action command from the queue. */ void N_MARemove(void) { if(mqHead != mqTail) { mqTail = (mqTail + 1) % MASTER_QUEUE_LEN; } } /** * Clear the master action command queue. */ void N_MAClear(void) { mqHead = mqTail = 0; } /** * @return @c true, if the master action command queue is empty. */ boolean N_MADone(void) { return (mqHead == mqTail); } /** * Add a net event to the queue, to wait for processing. */ void N_NEPost(netevent_t * nev) { netEventQueue[neqHead] = *nev; neqHead = (neqHead + 1) % NETEVENT_QUEUE_LEN; } /** * Are there any net events awaiting processing? * * \note N_GetPacket() will not return a packet until all net events have * processed. * * @return @c true if there are net events waiting to be * processed. */ boolean N_NEPending(void) { return neqHead != neqTail; } /** * Get a net event from the queue. * * @return @c true, if an event was returned. */ boolean N_NEGet(netevent_t *nev) { // Empty queue? if(!N_NEPending()) return false; *nev = netEventQueue[neqTail]; neqTail = (neqTail + 1) % NETEVENT_QUEUE_LEN; return true; } /** * Handles low-level net tick stuff: communication with the master server. */ void N_NETicker(void) { masteraction_t act; int i, num; if(netGame) { // Update master every 2 minutes. if(masterAware && N_UsingInternet() && !(SECONDS_TO_TICKS(sysTime) % (MASTER_HEARTBEAT * TICRATE))) { N_MasterAnnounceServer(true); } } // Is there a master action to worry about? if(N_MAGet(&act)) { switch(act) { case MAC_REQUEST: // Send the request for servers. N_MasterRequestList(); N_MARemove(); break; case MAC_WAIT: // Handle incoming messages. if(N_MasterGet(0, 0) >= 0) { // The list has arrived! N_MARemove(); } break; case MAC_LIST: //Con_Printf(" %-20s P/M L Ver: Game: Location:\n", "Name:"); Net_PrintServerInfo(0, NULL); num = i = N_MasterGet(0, 0); while(--i >= 0) { serverinfo_t info; N_MasterGet(i, &info); /*Con_Printf("%-2i: %-20s %i/%-2i %c %-5i %-16s %s:%i\n", * i, info.name, * info.players, info.maxPlayers, * info.canJoin? ' ':'*', info.version, info.game, * info.address, info.port); * Con_Printf(" %s (%x) %s\n", info.map, info.data[0], * info.description); */ Net_PrintServerInfo(i, &info); } Con_Printf("%i server%s found.\n", num, num != 1 ? "s were" : " was"); N_MARemove(); break; default: Con_Error("N_NETicker: Invalid value, act = %i.", (int) act); break; } } } /** * The event list is checked for arrivals and exits, and the 'clients' * and 'players' arrays are updated accordingly. */ void N_Update(void) { netevent_t nevent; char name[256]; // Are there any events to process? while(N_NEGet(&nevent)) { switch(nevent.type) { case NE_CLIENT_ENTRY: // Find out the name of the new player. memset(name, 0, sizeof(name)); N_GetNodeName(nevent.id, name); // Assign a console to the new player. Sv_PlayerArrives(nevent.id, name); break; case NE_CLIENT_EXIT: Sv_PlayerLeaves(nevent.id); break; case NE_END_CONNECTION: // A client receives this event when the connection is // terminated. if(netGame) { // We're still in a netGame, which means we didn't disconnect // voluntarily. Con_Message("N_Update: Connection was terminated.\n"); N_Disconnect(); } break; default: Con_Error("N_Update: Invalid value, nevent.type = %i.", (int) nevent.type); break; } } } /** * The client is removed from the game without delay. This is used when the * server needs to terminate a client's connection abnormally. */ void N_TerminateClient(int console) { if(!N_IsAvailable() || !clients[console].connected || !netServerMode) return; Con_Message("N_TerminateClient: '%s' from console %i.\n", clients[console].name, console); N_TerminateNode(clients[console].nodeID); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/s_cache.c0000644000175000017500000004757611357170242022505 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_cache.c: Sound Sample Cache * * The data is stored using M_Malloc(). * * To play a sound: * 1) Figure out the ID of the sound. * 2) Call Sfx_Cache() to get a sfxsample_t. * 3) Pass the sfxsample_t to Sfx_StartSound(). */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_system.h" #include "de_console.h" #include "de_refresh.h" #include "de_audio.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ // The cached samples are stored in a hash. When a sample is purged, its // data will stay in the hash (sample lengths needed by the Logical Sound // Manager). #define CACHE_HASH_SIZE (64) #define PURGE_TIME (10 * TICSPERSEC) // Convert an unsigned byte to signed short (for resampling). #define U8_S16(b) (((byte)(b) - 0x80) << 8) // TYPES ------------------------------------------------------------------- typedef struct sfxcache_s { struct sfxcache_s* next, *prev; int hits; int lastUsed; // Tic the sample was last hit. sfxsample_t sample; } sfxcache_t; typedef struct cachehash_s { sfxcache_t* first, *last; } cachehash_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void Sfx_Uncache(sfxcache_t* node); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // 1 Mb = about 12 sec of 44KHz 16bit sound in the cache. int sfxMaxCacheKB = 4096; // Even one minute of silence is quite a long time during gameplay. int sfxMaxCacheTics = TICSPERSEC * 60 * 4; // 4 minutes. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static cachehash_t scHash[CACHE_HASH_SIZE]; // CODE -------------------------------------------------------------------- void Sfx_InitCache(void) { // The cache is empty in the beginning. memset(scHash, 0, sizeof(scHash)); } void Sfx_ShutdownCache(void) { int i; // Uncache all the samples in the cache. for(i = 0; i < CACHE_HASH_SIZE; ++i) { while(scHash[i].first) Sfx_Uncache(scHash[i].first); } } cachehash_t* Sfx_CacheHash(int id) { return &scHash[(unsigned int) id % CACHE_HASH_SIZE]; } /** * If the sound is cached, return a pointer to it. */ sfxcache_t* Sfx_GetCached(int id) { sfxcache_t* it; for(it = Sfx_CacheHash(id)->first; it; it = it->next) { if(it->sample.id == id) return it; } return NULL; } /** * Simple linear resampling with possible conversion to 16 bits. * The destination sample must be initialized and it must have a large * enough buffer. We won't reduce rate or bits here. * * \note This is not a clean way to resample a sound. If you read about * DSP a bit, you'll find out that interpolation adds a lot of extra * frequencies in the sample. It should be low-pass filtered after the * interpolation. */ static void resample(void* dst, int dstBytesPer, int dstRate, const void* src, int srcBytesPer, int srcRate, int srcNumSamples, unsigned int srcSize) { int i; assert(src); assert(dst); // Let's first check for the easy cases. if(dstRate == srcRate) { if(srcBytesPer == dstBytesPer) { // A simple copy will suffice. memcpy(dst, src, srcSize); } else if(srcBytesPer == 1 && dstBytesPer == 2) { // Just changing the bytes won't do much good... const unsigned char* sp = src; short* dp = dst; for(i = 0; i < srcNumSamples; ++i) *dp++ = (*sp++ - 0x80) << 8; } return; } // 2x resampling. if(dstRate == 2 * srcRate) { if(dstBytesPer == 1) { // The source has a byte per sample as well. const unsigned char* sp = src; unsigned char* dp = dst; for(i = 0; i < srcNumSamples - 1; ++i, sp++) { *dp++ = *sp; *dp++ = (*sp + sp[1]) >> 1; } // Fill in the last two as well. dp[0] = dp[1] = *sp; } else if(srcBytesPer == 1) { // Destination is signed 16bit. Source is 8bit. const unsigned char* sp = src; short* dp = dst; short first; for(i = 0; i < srcNumSamples - 1; ++i, sp++) { *dp++ = first = U8_S16(*sp); *dp++ = (first + U8_S16(sp[1])) >> 1; } // Fill in the last two as well. dp[0] = dp[1] = U8_S16(*sp); } else if(srcBytesPer == 2) { // Destination is signed 16bit. Source is 16bit. const short* sp = src; short* dp = dst; for(i = 0; i < srcNumSamples - 1; ++i, sp++) { *dp++ = *sp; *dp++ = (*sp + sp[1]) >> 1; } dp[0] = dp[1] = *sp; } return; } // 4x resampling (11Khz => 44KHz only). if(dstRate == 4 * srcRate) { if(dstBytesPer == 1) { // The source has a byte per sample as well. const unsigned char* sp = src; unsigned char* dp = dst; unsigned char mid; for(i = 0; i < srcNumSamples - 1; ++i, sp++) { mid = (*sp + sp[1]) >> 1; *dp++ = *sp; *dp++ = (*sp + mid) >> 1; *dp++ = mid; *dp++ = (mid + sp[1]) >> 1; } // Fill in the last four as well. dp[0] = dp[1] = dp[2] = dp[3] = *sp; } else if(srcBytesPer == 1) { // Destination is signed 16bit. Source is 8bit. const unsigned char* sp = src; short* dp = dst; short first, mid, last; for(i = 0; i < srcNumSamples - 1; ++i, sp++) { first = U8_S16(*sp); last = U8_S16(sp[1]); mid = (first + last) >> 1; *dp++ = first; *dp++ = (first + mid) >> 1; *dp++ = mid; *dp++ = (mid + last) >> 1; } // Fill in the last four as well. dp[0] = dp[1] = dp[2] = dp[3] = U8_S16(*sp); } else if(srcBytesPer == 2) { // Destination is signed 16bit. Source is 16bit. const short* sp = src; short* dp = dst; short mid; for(i = 0; i < srcNumSamples - 1; ++i, sp++) { mid = (*sp + sp[1]) >> 1; *dp++ = *sp; *dp++ = (*sp + mid) >> 1; *dp++ = mid; *dp++ = (mid + sp[1]) >> 1; } // Fill in the last four as well. dp[0] = dp[1] = dp[2] = dp[3] = *sp; } } } /** * Caches a copy of the given sample. If it's already in the cache and has * the same format, nothing is done. * * @param id Id number of the sound sample. * @param data Actual sample data. * @param size Size in bytes. * @param numSamples Number of samples. * @param bytesPer Bytes per sample (1 or 2). * @param rate Samples per second. * @param group Exclusion group (0, if none). * * @returns Ptr to the cached sample. Always valid. */ sfxcache_t* Sfx_CacheInsert(int id, const void* data, unsigned int size, int numSamples, int bytesPer, int rate, int group) { sfxcache_t* node; sfxsample_t cached; cachehash_t* hash; int rsfactor; void* buf; /** * First convert the sample to the minimum resolution and bits, set * by sfxRate and sfxBits. */ // The resampling factor. rsfactor = sfxRate / rate; if(!rsfactor) rsfactor = 1; /** * If the sample is already in the right format, just make a copy of it. * If necessary, resample the sound upwards, but not downwards. * (You can play higher resolution sounds than the current setting, but * not lower resolution ones.) */ cached.size = numSamples * bytesPer * rsfactor; if(sfxBits == 16 && bytesPer == 1) { cached.bytesPer = 2; cached.size *= 2; // Will be resampled to 16bit. } else { cached.bytesPer = bytesPer; } cached.rate = rsfactor * rate; cached.numSamples = numSamples * rsfactor; cached.id = id; cached.group = group; // Check if this kind of a sample already exists. node = Sfx_GetCached(id); if(node) { // The sound is already in the cache. Is it in the right format? if(cached.bytesPer * 8 == sfxBits && cached.rate == sfxRate) return node; // This will do. // Stop all sounds using this sample (we are going to destroy the // existing sample data). Sfx_UnloadSoundID(node->sample.id); // It's in the wrong format! We'll reuse this node. M_Free(node->sample.data); } else { // Get a new node and link it in. node = M_Calloc(sizeof(sfxcache_t)); hash = Sfx_CacheHash(id); if(hash->last) { hash->last->next = node; node->prev = hash->last; } hash->last = node; if(!hash->first) hash->first = node; } buf = M_Malloc(cached.size); // Do the resampling, if necessary. resample(buf, cached.bytesPer, cached.rate, data, bytesPer, rate, numSamples, size); cached.data = buf; // Hits keep count of how many times the cached sound has been played. // The purger will remove samples with the lowest hitcount first. node->hits = 0; memcpy(&node->sample, &cached, sizeof(cached)); return node; } void Sfx_Uncache(sfxcache_t* node) { cachehash_t* hash; if(!node) return; BEGIN_COP; // Reset all channels loaded with this sample. Sfx_UnloadSoundID(node->sample.id); hash = Sfx_CacheHash(node->sample.id); // Unlink the node. if(hash->last == node) hash->last = node->prev; if(hash->first == node) hash->first = node->next; if(node->next) node->next->prev = node->prev; if(node->prev) node->prev->next = node->next; END_COP; // Free all memory allocated for the node. M_Free(node->sample.data); M_Free(node); } /** * Removes the sound with the matching ID from the sound cache. */ void Sfx_UncacheID(int id) { sfxcache_t* node = Sfx_GetCached(id); if(!node) return; // No such sound is cached. Sfx_Uncache(node); } /** * Called periodically by S_Ticker(). If the cache is too large, stopped * samples with the lowest hitcount will be uncached. */ void Sfx_PurgeCache(void) { static int lastPurge = 0; int totalSize = 0, maxSize = sfxMaxCacheKB * 1024; sfxcache_t* it, *next, *lowest; int i, lowHits = 0, nowTime = Sys_GetTime(); if(!sfxAvail) return; // Is it time for a purge? if(nowTime - lastPurge < PURGE_TIME) return; // Don't purge yet. lastPurge = nowTime; // Count the total size of the cache. // Also get rid of all sounds that have timed out. for(i = 0; i < CACHE_HASH_SIZE; i++) { for(it = scHash[i].first; it; it = next) { next = it->next; if(nowTime - it->lastUsed > sfxMaxCacheTics) { // This sound hasn't been used in a looong time. Sfx_Uncache(it); continue; } totalSize += it->sample.size + sizeof(*it); } } while(totalSize > maxSize) { /** * The cache is too large! Find the stopped sample with the lowest * hitcount and get rid of it. Repeat until cache size is within * limits or there are no more stopped sounds. */ lowest = NULL; for(i = 0; i < CACHE_HASH_SIZE; i++) { for(it = scHash[i].first; it; it = it->next) { // If the sample is playing we won't remove it now. if(Sfx_CountPlaying(it->sample.id)) continue; // This sample could be removed, let's check the hits. if(!lowest || it->hits < lowHits) { lowest = it; lowHits = it->hits; } } } if(!lowest) break; // No more samples to remove. // Stop and uncache this cached sample. totalSize -= lowest->sample.size + sizeof(*lowest); Sfx_Uncache(lowest); } } /** * @return Number of bytes and samples cached. */ void Sfx_GetCacheInfo(uint* cacheBytes, uint* sampleCount) { sfxcache_t* it; uint size = 0, count = 0; int i; for(i = 0; i < CACHE_HASH_SIZE; ++i) { for(it = scHash[i].first; it; it = it->next, count++) size += it->sample.size; } if(cacheBytes) *cacheBytes = size; if(sampleCount) *sampleCount = count; } void Sfx_CacheHit(int id) { sfxcache_t* node = Sfx_GetCached(id); if(node) { node->hits++; node->lastUsed = Sys_GetTime(); } } static sfxsample_t* cacheSample(int id, sfxinfo_t* info) { void* data = NULL; int numSamples = 0, bytesPer = 0, rate = 0; VERBOSE2( Con_Message("Sfx_Cache: Caching sound %i (%s).\n", id, info->id)); /** * Figure out where to get the sample data for this sound. It might be * from a data file such as a WAD or external sound resources. * The definition and the configuration settings will help us in making * the decision. */ // Has an external sound file been defined? if(info->external[0]) { // Yes. filename_t buf; // Try loading (note the file name is relative to the base path). M_PrependBasePath(buf, info->external, FILENAME_T_MAXLEN); if((data = WAV_Load(buf, &bytesPer, &rate, &numSamples))) { // Loading was successful! bytesPer /= 8; // Was returned as bits. } } // If external didn't succeed, let's try the default resource dir. if(!data) { filename_t buf; /** * If the sound has an invalid lumpname, search external anyway. * If the original sound is from a PWAD, we won't look for an * external resource (probably a custom sound). * \fixme should be a cvar. */ if((info->lumpNum < 0 || W_IsFromIWAD(info->lumpNum)) && R_FindResource(RT_SOUND, buf, info->lumpName, NULL, FILENAME_T_MAXLEN) && (data = WAV_Load(buf, &bytesPer, &rate, &numSamples))) { // Loading was successful! bytesPer /= 8; // Was returned as bits. } } // No sample loaded yet? if(!data) { char hdr[12]; // Try loading from the lump. if(info->lumpNum < 0) { if(verbose) { Con_Message("Sfx_Cache: Sound %s has a missing lump: '%s'.\n", info->id, info->lumpName); Con_Message(" Verifying... The lump number is %i.\n", W_CheckNumForName(info->lumpName)); } return NULL; } if(W_LumpLength(info->lumpNum) <= 8) return NULL; W_ReadLumpSection(info->lumpNum, hdr, 0, 12); // Is this perhaps a WAV sound? if(WAV_CheckFormat(hdr)) { const void* sp = W_CacheLumpNum(info->lumpNum, PU_STATIC); // Load as WAV, then. if(!(data = WAV_MemoryLoad((const byte*) sp, W_LumpLength(info->lumpNum), &bytesPer, &rate, &numSamples))) { // Abort... Con_Message("Sfx_Cache: WAV data in lump %s is bad.\n", info->lumpName); W_ChangeCacheTag(info->lumpNum, PU_CACHE); return NULL; } W_ChangeCacheTag(info->lumpNum, PU_CACHE); bytesPer /= 8; } } if(data) // Loaded! { sfxcache_t* node; // Insert a copy of this into the cache. node = Sfx_CacheInsert(id, data, bytesPer * numSamples, numSamples, bytesPer, rate, info->group); Z_Free(data); return &node->sample; } else // Must be an old-fashioned DOOM sample. { /** * We can use the sample data as-is, so make use of the lump cache * by loading from it directly. */ sfxcache_t* node; const void* data, *sp = W_CacheLumpNum(info->lumpNum, PU_STATIC); data = ((const char*) sp) + 8; // Eight byte header. bytesPer = 1; // 8-bit. rate = SHORT(*(short*) (((const char*) sp) + 2)); numSamples = LONG(*(int*) (((const char*) sp) + 4)); // Insert a copy of this into the cache. node = Sfx_CacheInsert(id, data, bytesPer * numSamples, numSamples, bytesPer, rate, info->group); // We don't need the temporary sample any more, clean up. W_ChangeCacheTag(info->lumpNum, PU_CACHE); return &node->sample; } } /** * @return Ptr to the cached copy of the sample (give this ptr * to Sfx_StartSound), ELSE @c NULL if the soundID is * invalid. */ sfxsample_t* Sfx_Cache(int id) { sfxcache_t* node; sfxinfo_t* info; if(!id || !sfxAvail) return NULL; // Are we so lucky that the sound is already cached? if((node = Sfx_GetCached(id)) != NULL) { return &node->sample; } // Get the sound decription. info = S_GetSoundInfo(id, NULL, NULL); if(!info) { Con_Message("Sfx_Cache: Warning, missing sound info for ID %i.\n", id); return NULL; } return cacheSample(id, info); } /** * @return The length of the sound (in milliseconds). */ uint Sfx_GetSoundLength(int id) { sfxsample_t* sample = Sfx_Cache(id & ~DDSF_FLAG_MASK); if(!sample) { // No idea. return 0; } return (1000 * sample->numSamples) / sample->rate; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_audiod_sdlmixer.c0000644000175000017500000003354711357170242025163 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_sdlmixer.h: SDL_mixer, for SFX, Ext and Mus interfaces. */ // HEADER FILES ------------------------------------------------------------ #include #include #ifdef MACOSX # include # include #else # include # include #endif #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" #include "sys_audiod.h" #include "sys_audiod_sfx.h" #include "sys_audiod_mus.h" // MACROS ------------------------------------------------------------------ #define DEFAULT_MIDI_COMMAND "" //"timidity" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- int DS_SDLMixerInit(void); void DS_SDLMixerShutdown(void); void DS_SDLMixerEvent(int type); int DS_SDLMixer_SFX_Init(void); sfxbuffer_t* DS_SDLMixer_SFX_CreateBuffer(int flags, int bits, int rate); void DS_SDLMixer_SFX_DestroyBuffer(sfxbuffer_t* buf); void DS_SDLMixer_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample); void DS_SDLMixer_SFX_Reset(sfxbuffer_t* buf); void DS_SDLMixer_SFX_Play(sfxbuffer_t* buf); void DS_SDLMixer_SFX_Stop(sfxbuffer_t* buf); void DS_SDLMixer_SFX_Refresh(sfxbuffer_t* buf); void DS_SDLMixer_SFX_Set(sfxbuffer_t* buf, int prop, float value); void DS_SDLMixer_SFX_Setv(sfxbuffer_t* buf, int prop, float* values); void DS_SDLMixer_SFX_Listener(int prop, float value); void DS_SDLMixer_SFX_Listenerv(int prop, float* values); // The music interface. int DS_SDLMixer_Music_Init(void); void DS_SDLMixer_Music_Update(void); void DS_SDLMixer_Music_Set(int prop, float value); int DS_SDLMixer_Music_Get(int prop, void* value); void DS_SDLMixer_Music_Pause(int pause); void DS_SDLMixer_Music_Stop(void); int DS_SDLMixer_Music_PlayFile(const char* fileName, int looped); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean sdlInitOk = false; audiodriver_t audiod_sdlmixer = { DS_SDLMixerInit, DS_SDLMixerShutdown, DS_SDLMixerEvent }; audiointerface_sfx_t audiod_sdlmixer_sfx = { DS_SDLMixer_SFX_Init, DS_SDLMixer_SFX_CreateBuffer, DS_SDLMixer_SFX_DestroyBuffer, DS_SDLMixer_SFX_Load, DS_SDLMixer_SFX_Reset, DS_SDLMixer_SFX_Play, DS_SDLMixer_SFX_Stop, DS_SDLMixer_SFX_Refresh, DS_SDLMixer_SFX_Set, DS_SDLMixer_SFX_Setv, DS_SDLMixer_SFX_Listener, DS_SDLMixer_SFX_Listenerv }; audiointerface_music_t audiod_sdlmixer_music = { DS_SDLMixer_Music_Init, DS_SDLMixer_Music_Update, DS_SDLMixer_Music_Set, DS_SDLMixer_Music_Get, DS_SDLMixer_Music_Pause, DS_SDLMixer_Music_Stop, NULL, NULL, DS_SDLMixer_Music_PlayFile, }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int numChannels; static boolean* usedChannels; static Mix_Music* lastMusic; static boolean playingMusic = false; // CODE -------------------------------------------------------------------- /** * This is the hook we ask SDL_mixer to call when music playback finishes. */ #if _DEBUG static void musicPlaybackFinished(void) { Con_Printf("DS_SDLMixer: Music playback finished.\n"); } #endif static int getFreeChannel(void) { int i; for(i = 0; i < numChannels; ++i) { if(!usedChannels[i]) return i; } return -1; } /** * @return Length of the buffer in milliseconds. */ static unsigned int getBufLength(sfxbuffer_t* buf) { if(!buf) return 0; return 1000 * buf->sample->numSamples / buf->freq; } int DS_SDLMixerInit(void) { int freq, channels; uint16_t format; SDL_version compVer; const SDL_version* linkVer; if(sdlInitOk) return true; if(SDL_InitSubSystem(SDL_INIT_AUDIO)) { Con_Message("DS_SDLMixerInit: Error initializing SDL AUDIO\n %s\n", SDL_GetError()); return false; } SDL_MIXER_VERSION(&compVer); linkVer = Mix_Linked_Version(); if(SDL_VERSIONNUM(linkVer->major, linkVer->minor, linkVer->patch) > SDL_VERSIONNUM(compVer.major, compVer.minor, compVer.patch)) { Con_Message("DS_SDLMixerInit: Warning, linked version of SDLMixer (%u.%u.%u) is " "newer than expected (%u.%u.%u)\n", linkVer->major, linkVer->minor, linkVer->patch, compVer.major, compVer.minor, compVer.patch); } if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024)) { Con_Message("DS_SDLMixerInit: Failed opening mixer %s.\n", Mix_GetError()); return false; } Mix_QuerySpec(&freq, &format, &channels); // Announce capabilites: Con_Printf("SDLMixer Configuration:\n"); Con_Printf(" Output: %s\n", channels > 1? "stereo" : "mono"); Con_Printf(" Format: %#x (%#x)\n", format, (uint16_t) AUDIO_S16LSB); Con_Printf(" Frequency: %iHz (%iHz)\n", freq, (int) MIX_DEFAULT_FREQUENCY); Con_Printf(" Initial Channels: %i\n", MIX_CHANNELS); // Prepare to play simultaneous sounds. /*numChannels =*/ Mix_AllocateChannels(MIX_CHANNELS); usedChannels = NULL; // Everything is OK. sdlInitOk = true; return true; } void DS_SDLMixerShutdown(void) { if(!sdlInitOk) return; if(usedChannels) free(usedChannels); if(lastMusic) { Mix_HaltMusic(); Mix_FreeMusic(lastMusic); } lastMusic = NULL; Mix_CloseAudio(); SDL_QuitSubSystem(SDL_INIT_AUDIO); sdlInitOk = false; } void DS_SDLMixerEvent(int type) { // Not supported. } int DS_SDLMixer_SFX_Init(void) { // No extra init needed. return sdlInitOk; } sfxbuffer_t* DS_SDLMixer_SFX_CreateBuffer(int flags, int bits, int rate) { sfxbuffer_t* buf; // Create the buffer. buf = Z_Calloc(sizeof(*buf), PU_STATIC, 0); buf->bytes = bits / 8; buf->rate = rate; buf->flags = flags; buf->freq = rate; // Modified by calls to Set(SFXBP_FREQUENCY). // The cursor is used to keep track of the channel on which the sample // is playing. if(-1 == (buf->cursor = getFreeChannel())) { buf->cursor = numChannels++; usedChannels = realloc(usedChannels, sizeof(usedChannels[0]) * numChannels); // Make sure we have enough channels allocated. Mix_AllocateChannels(numChannels); Mix_UnregisterAllEffects(buf->cursor); } usedChannels[buf->cursor] = true; return buf; } void DS_SDLMixer_SFX_DestroyBuffer(sfxbuffer_t* buf) { Mix_HaltChannel(buf->cursor); usedChannels[buf->cursor] = false; if(buf) Z_Free(buf); } void DS_SDLMixer_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample) { static char localBuf[0x40000]; char* conv = NULL; size_t size; if(!buf || !sample) return; // Wha? // Does the buffer already have a sample loaded? if(buf->sample) { // Is the same one? if(buf->sample->id == sample->id) return; // Free the existing data. buf->sample = NULL; Mix_FreeChunk(buf->ptr); } size = 8 + 4 + 8 + 16 + 8 + sample->size; if(size <= sizeof(localBuf)) { conv = localBuf; } else { conv = malloc(size); } // Transfer the sample to SDL_mixer by converting it to WAVE format. strcpy(conv, "RIFF"); *(Uint32 *) (conv + 4) = ULONG(4 + 8 + 16 + 8 + sample->size); strcpy(conv + 8, "WAVE"); // Format chunk. strcpy(conv + 12, "fmt "); *(Uint32 *) (conv + 16) = ULONG(16); /** * WORD wFormatTag; // Format category * WORD wChannels; // Number of channels * uint dwSamplesPerSec; // Sampling rate * uint dwAvgBytesPerSec; // For buffer estimation * WORD wBlockAlign; // Data block size * WORD wBitsPerSample; // Sample size */ *(Uint16 *) (conv + 20) = USHORT(1); *(Uint16 *) (conv + 22) = USHORT(1); *(Uint32 *) (conv + 24) = ULONG(sample->rate); *(Uint32 *) (conv + 28) = ULONG(sample->rate * sample->bytesPer); *(Uint16 *) (conv + 32) = USHORT(sample->bytesPer); *(Uint16 *) (conv + 34) = USHORT(sample->bytesPer * 8); // Data chunk. strcpy(conv + 36, "data"); *(Uint32 *) (conv + 40) = ULONG(sample->size); memcpy(conv + 44, sample->data, sample->size); buf->ptr = Mix_LoadWAV_RW(SDL_RWFromMem(conv, 44 + sample->size), 1); if(!buf->ptr) { Con_Message("DS_SDLMixer_SFX_Load: Warning, failed loading sample (%s).\n", Mix_GetError()); } if(conv != localBuf) { free(conv); } buf->sample = sample; } /** * Stops the buffer and makes it forget about its sample. */ void DS_SDLMixer_SFX_Reset(sfxbuffer_t* buf) { if(!buf) return; DS_SDLMixer_SFX_Stop(buf); buf->sample = NULL; // Unallocate the resources of the source. Mix_FreeChunk(buf->ptr); buf->ptr = NULL; } void DS_SDLMixer_SFX_Play(sfxbuffer_t* buf) { // Playing is quite impossible without a sample. if(!buf || !buf->sample) return; // Update the volume at which the sample will be played. Mix_Volume(buf->cursor, buf->written); Mix_PlayChannel(buf->cursor, buf->ptr, (buf->flags & SFXBF_REPEAT ? -1 : 0)); // Calculate the end time (milliseconds). buf->endTime = Sys_GetRealTime() + getBufLength(buf); // The buffer is now playing. buf->flags |= SFXBF_PLAYING; } void DS_SDLMixer_SFX_Stop(sfxbuffer_t* buf) { if(!buf || !buf->sample) return; Mix_HaltChannel(buf->cursor); //usedChannels[buf->cursor] = false; buf->flags &= ~SFXBF_PLAYING; } void DS_SDLMixer_SFX_Refresh(sfxbuffer_t* buf) { unsigned int nowTime; // Can only be done if there is a sample and the buffer is playing. if(!buf || !buf->sample || !(buf->flags & SFXBF_PLAYING)) return; nowTime = Sys_GetRealTime(); /** * Have we passed the predicted end of sample? * \note This test fails if the game has been running for about 50 days, * since the millisecond counter overflows. It only affects sounds that * are playing while the overflow happens, though. */ if(!(buf->flags & SFXBF_REPEAT) && nowTime >= buf->endTime) { // Time for the sound to stop. buf->flags &= ~SFXBF_PLAYING; } } void DS_SDLMixer_SFX_Set(sfxbuffer_t* buf, int prop, float value) { int right; if(!buf) return; switch(prop) { case SFXBP_VOLUME: // 'written' is used for storing the volume of the channel. buf->written = (unsigned int) (value * MIX_MAX_VOLUME); Mix_Volume(buf->cursor, buf->written); break; case SFXBP_PAN: // -1 ... +1 right = (int) ((value + 1) * 127); Mix_SetPanning(buf->cursor, 254 - right, right); break; default: break; } } void DS_SDLMixer_SFX_Setv(sfxbuffer_t* buf, int prop, float* values) { // Not supported. } void DS_SDLMixer_SFX_Listener(int prop, float value) { // Not supported. } void SetEnvironment(float* rev) { // Not supported. } void DS_SDLMixer_SFX_Listenerv(int prop, float* values) { // Not supported. } int DS_SDLMixer_Music_Init(void) { #if _DEBUG Mix_HookMusicFinished(musicPlaybackFinished); #endif return sdlInitOk; } void DS_SDLMixer_Music_Update(void) { // Nothing to update. } void DS_SDLMixer_Music_Set(int prop, float value) { if(!sdlInitOk) return; switch(prop) { case MUSIP_VOLUME: Mix_VolumeMusic((int) (MIX_MAX_VOLUME * value)); break; default: break; } } int DS_SDLMixer_Music_Get(int prop, void* value) { if(!sdlInitOk) return false; switch(prop) { case MUSIP_ID: strcpy(value, "SDLMixer/Music"); break; case MUSIP_PLAYING: return Mix_PlayingMusic(); default: return false; } return true; } void DS_SDLMixer_Music_Pause(int pause) { if(!sdlInitOk) return; if(pause) Mix_PauseMusic(); else Mix_ResumeMusic(); } void DS_SDLMixer_Music_Stop(void) { if(!sdlInitOk) return; Mix_HaltMusic(); } int DS_SDLMixer_Music_PlayFile(const char* filename, int looped) { if(!sdlInitOk) return false; // Free any previously loaded music. if(lastMusic) { Mix_HaltMusic(); Mix_FreeMusic(lastMusic); } if(!(lastMusic = Mix_LoadMUS(filename))) { Con_Message("DS_SDLMixer_Music_PlayFile: Error %s.\n", Mix_GetError()); return false; } return !Mix_PlayMusic(lastMusic, looped ? -1 : 1); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_nodepile.c0000644000175000017500000001336011357170242023213 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_nodepile.c: Specialized Node Allocation * * The 'piles' are allocated as PU_MAP. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define NP_MAX_NODES 65535 // Indices are shorts. // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Initialize (alloc) the nodepile with n nodes. * * @param pile Ptr to the pile to be initialized. * @param initial Number of nodes to allocate. */ void NP_Init(nodepile_t *pile, int initial) { size_t size; // Allocate room for at least two nodes. // Node zero is never used. if(initial < 2) initial = 2; size = sizeof(*pile->nodes) * initial; pile->nodes = Z_Calloc(size, PU_MAP, 0); pile->count = initial; // Index #1 is the first. pile->pos = 1; } /** * Adds a new node to a node pile. * Pos always has the index of the next node to check when allocating * a new node. Pos shouldn't be accessed outside this routine because its * value may prove to be outside the valid range. * * @param pile Ptr to nodepile to add the node to. * @param ptr Data to attach to the new node. */ nodeindex_t NP_New(nodepile_t *pile, void *ptr) { linknode_t *node; linknode_t *end = pile->nodes + pile->count; int i, newcount; linknode_t *newlist; boolean found; pile->pos %= pile->count; node = pile->nodes + pile->pos++; // Scan for an unused node, starting from current pos. i = 0; found = false; while(i < pile->count - 1 && !found) { if(node == end) node = pile->nodes + 1; // Wrap back to #1. if(!node->ptr) { // This is the one! found = true; } else { i++; node++; pile->pos++; } } if(!found) { // Damned, we ran out of nodes. Let's allocate more. if(pile->count == NP_MAX_NODES) { // This happens *theoretically* only in freakishly complex // maps with lots and lots of mobjs. Con_Error("NP_New: Out of linknodes! Contact the developer.\n"); } // Double the number of nodes, but add at most 1024. if(pile->count >= 1024) newcount = pile->count + 1024; else newcount = pile->count * 2; if(newcount > NP_MAX_NODES) newcount = NP_MAX_NODES; newlist = Z_Malloc(sizeof(*newlist) * newcount, PU_MAP, 0); memcpy(newlist, pile->nodes, sizeof(*pile->nodes) * pile->count); memset(newlist + pile->count, 0, (newcount - pile->count) * sizeof(*newlist)); // Get rid of the old list and start using the new one. Z_Free(pile->nodes); pile->nodes = newlist; pile->pos = pile->count + 1; node = pile->nodes + pile->count; pile->count = newcount; } node->ptr = ptr; // Make it point to itself by default (a root, basically). node->next = node->prev = node - pile->nodes; return node->next; // Well, node's index, really. } /** * Links the node to the beginning of the ring. * * @param pile Nodepile ring to work with. * @param node Node to be linked. * @param root The root node to link the node to. */ void NP_Link(nodepile_t *pile, nodeindex_t node, nodeindex_t root) { linknode_t *nd = pile->nodes; nd[node].prev = root; nd[node].next = nd[root].next; nd[root].next = nd[nd[node].next].prev = node; } /** * Unlink a node from the ring (make it a root node) * * @param pile Nodepile ring to work with. * @param node Node to be unlinked. */ void NP_Unlink(nodepile_t *pile, nodeindex_t node) { linknode_t *nd = pile->nodes; // Try deciphering that! :-) (d->n->p = d->p, d->p->n = d->n) nd[nd[nd[node].next].prev = nd[node].prev].next = nd[node].next; // Make it link to itself (a root, basically). nd[node].next = nd[node].prev = node; } #if 0 // This is now a macro. /** * Caller must unlink first. */ void NP_Dismiss(nodepile_t *pile, nodeindex_t node) { pile->nodes[node].ptr = 0; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/m_stack.c0000644000175000017500000000603111357170242022516 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_stack.c: A standard, basic stack. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "m_stack.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { size_t height; // Height of the stack. void** data; } stackdata_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- ddstack_t* Stack_New(void) { stackdata_t* stack = malloc(sizeof(stackdata_t)); stack->height = 0; stack->data = NULL; return (ddstack_t*) stack; } void Stack_Delete(ddstack_t* s) { stackdata_t* stack; if(!s) return; stack = (stackdata_t*) s; if(stack->height) { #if _DEBUG Con_Message("Stack::Delete: Stack not empty!\n"); #endif } if(stack->data) free(stack->data); free(stack); } size_t Stack_Height(ddstack_t* s) { if(!s) return 0; return ((stackdata_t*) s)->height; } void Stack_Push(ddstack_t* s, void* data) { stackdata_t* stack; if(!s) return; stack = (stackdata_t*) s; stack->data = realloc(stack->data, sizeof(void*) * ++stack->height); stack->data[stack->height-1] = data; } void* Stack_Pop(ddstack_t* s) { stackdata_t* stack; void* retVal; if(!s) return NULL; stack = (stackdata_t*) s; if(!(stack->height > 0)) { #if _DEBUG Con_Message("Stack::Pop: Underflow.\n"); #endif return NULL; } retVal = stack->data[--stack->height]; stack->data[stack->height] = NULL; return retVal; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/dd_loop.c0000644000175000017500000003053211357170242022520 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_loop.c: Main Loop */ // HEADER FILES ------------------------------------------------------------ #include "de_platform.h" #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_network.h" #include "de_render.h" #include "de_refresh.h" #include "de_play.h" #include "de_graphics.h" #include "de_audio.h" #include "de_ui.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ /** * There needs to be at least this many tics per second. A smaller value * is likely to cause unpredictable changes in playsim. */ #define MIN_TIC_RATE 35 /** * The length of one tic can be at most this. */ #define MAX_FRAME_TIME (1.0/MIN_TIC_RATE) /** * Maximum number of milliseconds spent uploading textures at the beginning * of a frame. Note that non-uploaded textures will appear as pure white * until their content gets uploaded (you should precache them). */ #define FRAME_DEFERRED_UPLOAD_TIMEOUT 20 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void Net_ResetTimer(void); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void DD_RunTics(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean appShutdown = false; // Set to true when we should exit (normally). #ifdef WIN32 boolean suspendMsgPump = false; // Set to true to disable checking windows msgs. #endif int maxFrameRate = 200; // Zero means 'unlimited'. // Refresh frame count (independant of the viewport-specific frameCount). int rFrameCount = 0; timespan_t sysTime, gameTime, demoTime, ddMapTime; timespan_t frameStartTime; boolean stopTime = false; // If true the time counters won't be incremented boolean tickUI = false; // If true the UI will be tick'd boolean tickFrame = true; // If false frame tickers won't be tick'd (unless netGame) boolean drawGame = true; // If false the game viewport won't be rendered trigger_t sharedFixedTrigger = { 1 / 35.0, 0 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static double lastFrameTime; static float fps; static int lastFrameCount; static boolean firstTic = true; // CODE -------------------------------------------------------------------- /** * Register console variables for main loop. */ void DD_RegisterLoop(void) { C_VAR_INT("refresh-rate-maximum", &maxFrameRate, 0, 35, 1000); C_VAR_INT("rend-dev-framecount", &rFrameCount, CVF_NO_ARCHIVE | CVF_PROTECTED, 0, 0); } /** * This is the refresh thread (the main thread). */ int DD_GameLoop(void) { int exitCode = 0; #ifdef WIN32 MSG msg; #endif // Limit the frame rate to 35 when running in dedicated mode. if(isDedicated) { maxFrameRate = 35; } while(!appShutdown) { #ifdef WIN32 /** * Start by checking Windows messages. * \note Must be in the same thread as that which registered the * window it is handling messages for - DJS. */ while(!suspendMsgPump && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) > 0) { if(msg.message == WM_QUIT) { appShutdown = true; suspendMsgPump = true; exitCode = msg.wParam; } else { TranslateMessage(&msg); DispatchMessage(&msg); } } if(appShutdown) continue; #endif // Frame syncronous I/O operations. DD_StartFrame(); // Run at least one tic. If no tics are available (maxfps interval // not reached yet), the function blocks. DD_RunTics(); // Update clients. Sv_TransmitFrame(); // Finish the refresh frame. DD_EndFrame(); // Send out new accumulation. Drawing will take the longest. //Net_Update(); DD_DrawAndBlit(); //Net_Update(); // After the first frame, start timedemo. DD_CheckTimeDemo(); } return exitCode; } /** * Drawing anything outside this routine is frowned upon. * Seriously frowned! */ void DD_DrawAndBlit(void) { if(novideo) return; if(Con_IsBusy()) { Con_Error("DD_DrawAndBlit: Console is busy, can't draw!\n"); } if(renderWireframe) { // When rendering is wireframe mode, we must clear the screen // before rendering a frame. glClear(GL_COLOR_BUFFER_BIT); } if(drawGame) { // Interpolate the world ready for drawing view(s) of it. R_BeginWorldFrame(); // Set up the basic 320x200 legacy projection for the game. glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0, 320, 200, 0, -1, 1); R_RenderViewPorts(); // Draw any over/outside view window game graphics (e.g. fullscreen // menus and other displays). if(gx.G_Drawer2 && !(UI_IsActive() && UI_Alpha() >= 1.0)) { gx.G_Drawer2(); } // Restore the projection mode that was previously in effect. glMatrixMode(GL_PROJECTION); glPopMatrix(); } if(Con_TransitionInProgress()) Con_DrawTransition(); if(drawGame) { // Debug information. Net_Drawer(); S_Drawer(); // Finish up any tasks that must be completed after view(s) have // been drawn. R_EndWorldFrame(); } if(UI_IsActive()) { // Draw user interface. UI_Drawer(); } // Draw console. Rend_Console(); // End any open DGL sequence. DGL_End(); // Flush buffered stuff to screen (blits everything). GL_DoUpdate(); } void DD_StartFrame(void) { if(!isDedicated) GL_UploadDeferredContent(FRAME_DEFERRED_UPLOAD_TIMEOUT); frameStartTime = Sys_GetTimef(); S_StartFrame(); if(gx.BeginFrame) { gx.BeginFrame(); } } void DD_EndFrame(void) { static uint lastFpsTime = 0; uint nowTime = Sys_GetRealTime(); // Increment the (local) frame counter. rFrameCount++; // Count the frames every other second. if(nowTime - 2000 >= lastFpsTime) { fps = (rFrameCount - lastFrameCount) / ((nowTime - lastFpsTime)/1000.0f); lastFpsTime = nowTime; lastFrameCount = rFrameCount; } if(gx.EndFrame) gx.EndFrame(); S_EndFrame(); } float DD_GetFrameRate(void) { return fps; } /** * This is the main ticker of the engine. We'll call all the other tickers * from here. */ void DD_Ticker(timespan_t time) { static float realFrameTimePos = 0; if(!Con_TransitionInProgress()) { // Demo ticker. Does stuff like smoothing of view angles. Net_BuildLocalCommands(time); Demo_Ticker(time); P_Ticker(time); if(tickFrame || netGame) { // Advance frametime /** * It will be reduced when new sharp world positions are calculated, * so that frametime always stays within the range 0..1. */ realFrameTimePos += time * TICSPERSEC; // Game logic. gx.Ticker(time); if(M_RunTrigger(&sharedFixedTrigger, time)) { // A new 35 Hz tick begins. // Clear the player fixangles flags which have been in effect // for any fractional ticks since they were set. //Sv_FixLocalAngles(true /* just clear flags; don't apply */); /** * Server ticks. * * These are placed here because they still rely on fixed ticks * and thus it's best to keep them in sync with the fixed game * ticks. */ if(isClient) Cl_Ticker( /* time */ ); else Sv_Ticker( /* time */ ); // This is needed by camera smoothing. It needs to know // when the world tic has occured so the next sharp // position can be processed. // Frametime will be set back by one tick. realFrameTimePos -= 1; // We can't sent FixAngles messages to ourselves, so it's // done here. //Sv_FixLocalAngles(false /* apply only; don't clear flag */); R_NewSharpWorld(); } // While paused, don't modify frametime so things keep still. if(!clientPaused) frameTimePos = realFrameTimePos; // We can't sent FixAngles messages to ourselves, so it's // done here. //Sv_FixLocalAngles(false /* apply only; don't clear flag */); } } // Console is always ticking. Con_Ticker(time); if(tickUI) { // User interface ticks. UI_Ticker(time); } // Plugins tick always. Plug_DoHook(HOOK_TICKER, 0, &time); } /** * Advance time counters. */ void DD_AdvanceTime(timespan_t time) { sysTime += time; if(!stopTime || netGame) { // The difference between gametic and demotic is that demotic // is not altered at any point. Gametic changes at handshakes. gameTime += time; demoTime += time; // Leveltic is reset to zero at every map change. // The map time only advances when the game is not paused. if(!clientPaused) { ddMapTime += time; } } } /** * Reset the game time so that on the next frame, the effect will be * that no time has passed. */ void DD_ResetTimer(void) { firstTic = true; Net_ResetTimer(); } /** * Run at least one tic. */ void DD_RunTics(void) { double frameTime, ticLength; double nowTime = Sys_GetSeconds(); // Do a network update first. N_Update(); Net_Update(); // Check the clock. if(firstTic) { // On the first tic, no time actually passes. firstTic = false; lastFrameTime = nowTime; return; } // We'll sleep until we go past the maxfps interval (the shortest // allowed interval between tics). if(maxFrameRate > 0) { while((nowTime = Sys_GetSeconds()) - lastFrameTime < 1.0 / maxFrameRate) { // Wait for a short while. Sys_Sleep(3); N_Update(); Net_Update(); } } // How much time do we have for this frame? frameTime = nowTime - lastFrameTime; lastFrameTime = nowTime; // Tic length is determined by the minfps rate. while(frameTime > 0) { ticLength = MIN_OF(MAX_FRAME_TIME, frameTime); frameTime -= ticLength; // Process input events. DD_ProcessEvents(ticLength); // Call all the tickers. DD_Ticker(ticLength); // The netcode gets to tick, too. Net_Ticker(/*ticLength*/); // Various global variables are used for counting time. DD_AdvanceTime(ticLength); } // Clients send commands periodically, not on every frame. if(!isClient) { Net_SendCommands(); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/sys_filein.c0000644000175000017500000006101511357170242023244 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_filein.c: File (Input) Stream Abstraction Layer * * File input. Can read from real files or WAD lumps. Note that * reading from WAD lumps means that a copy is taken of the lump when * the corresponding 'file' is opened. With big files this uses * considerable memory and time. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_platform.h" #include "de_base.h" #include "de_console.h" #include "de_system.h" #include "de_misc.h" #include "sys_findfile.h" // MACROS ------------------------------------------------------------------ #define MAX_LUMPDIRS 1024 // TYPES ------------------------------------------------------------------- typedef struct { DFILE *file; } filehandle_t; typedef struct { char lump[9]; char *path; // Full path name. } lumpdirec_t; typedef struct { char *source; // Full path name. char *target; // Full path name. } vdmapping_t; typedef struct { f_forall_func_t func; void *parm; const char *searchPath; const char *pattern; } zipforall_t; typedef struct foundentry_s { filename_t name; int attrib; } foundentry_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void F_ResetMapping(void); void F_ResetDirec(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static lumpdirec_t direc[MAX_LUMPDIRS + 1]; static filehandle_t* files; static unsigned int filesCount; static vdmapping_t* vdMappings; static unsigned int vdMappingsCount; static unsigned int vdMappingsMax; // CODE -------------------------------------------------------------------- /** * This is a case-insensitive test. * I do hope this algorithm works like it should... * * @return @c true, if the string matches the pattern. */ int F_MatchName(const char *string, const char *pattern) { const char *in = string, *st = pattern; while(*in) { if(*st == '*') { st++; continue; } if(*st != '?' && (tolower((unsigned char) *st) != tolower((unsigned char) *in))) { // A mismatch. Hmm. Go back to a previous *. while(st >= pattern && *st != '*') st--; if(st < pattern) return false; // No match! // The asterisk lets us continue. } // This character of the pattern is OK. st++; in++; } // Match is good if the end of the pattern was reached. while(*st == '*') st++; // Skip remaining asterisks. return *st == 0; } /** * Skips all whitespace except newlines. */ char *F_SkipSpace(char *ptr) { while(*ptr && *ptr != '\n' && isspace(*ptr)) ptr++; return ptr; } char *F_FindNewline(char *ptr) { while(*ptr && *ptr != '\n') ptr++; return ptr; } int F_GetDirecIdx(char *exact_path) { int i; boolean found; for(i = 0, found = false; direc[i].path && !found; ++i) if(!stricmp(direc[i].path, exact_path)) found = true; if(found) return i; else return -1; } /** * The path names are converted to full paths before adding to the table. */ void F_AddDirec(const char* lumpname, char* symbolic_path, size_t len) { int i; filename_t path; char* full; lumpdirec_t* ld; if(!lumpname[0] || !symbolic_path[0]) return; for(i = 0; direc[i].path && i < MAX_LUMPDIRS; ++i); if(i == MAX_LUMPDIRS) { // \fixme Why no dynamic allocation? Con_Error("F_AddDirec: Not enough direcs (%s).\n", symbolic_path); } ld = direc + i; // Convert the symbolic path into a real path. Dir_FixSlashes(symbolic_path, len); if(symbolic_path[0] == DIR_SEP_CHAR) dd_snprintf(path, FILENAME_T_MAXLEN, "%s%s", ddBasePath, symbolic_path + 1); else dd_snprintf(path, FILENAME_T_MAXLEN, "%s%s", ddRuntimeDir.path, symbolic_path); // Since the basepath might be relative, let's explicitly make // the path absolute. _fullpath will allocate memory, which will // be freed in F_ShutdownDirec() (also via F_InitDirec()). full = _fullpath(0, path, 0); // If this path already exists, we'll just update the lump name. i = F_GetDirecIdx(full); if(i >= 0) { // Already exists! M_Free(full); ld = direc + i; full = ld->path; } ld->path = full; strcpy(ld->lump, lumpname); strupr(ld->lump); if(verbose) { Con_Message("F_AddDirec: %s -> %s\n", ld->lump, ld->path); } } /** * The path names are converted to full paths before adding to the table. * Files in the source directory are mapped to the target directory. */ void F_AddMapping(const char* source, const char* destination) { filename_t src; filename_t dst; vdmapping_t* vd; // Convert to absolute path names. M_TranslatePath(src, source, FILENAME_T_MAXLEN); Dir_ValidDir(src, FILENAME_T_MAXLEN); Dir_MakeAbsolute(src, FILENAME_T_MAXLEN); M_TranslatePath(dst, destination, FILENAME_T_MAXLEN); Dir_ValidDir(dst, FILENAME_T_MAXLEN); Dir_MakeAbsolute(dst, FILENAME_T_MAXLEN); // Allocate more memory if necessary. if(++vdMappingsCount > vdMappingsMax) { vdMappingsMax *= 2; if(vdMappingsMax < vdMappingsCount) vdMappingsMax = 2*vdMappingsCount; vdMappings = M_Realloc(vdMappings, sizeof(vdmapping_t) * vdMappingsMax); } // Fill in the info into the array. vd = &vdMappings[vdMappingsCount - 1]; vd->source = strdup(src); vd->target = strdup(dst); VERBOSE(Con_Message("F_AddMapping: %s mapped to %s.\n", vd->source, vd->target)); } /** * LUMPNAM0 \Path\In\The\Base.ext * LUMPNAM1 Path\In\The\RuntimeDir.ext * : */ void F_ParseDirecData(char* buffer) { char* ptr = buffer, *end; char name[9]; filename_t path; size_t len; for(; *ptr;) { ptr = F_SkipSpace(ptr); if(!*ptr) break; if(*ptr == '\n') { ptr++; // Advance to the next line. continue; } // We're at the lump name. end = M_FindWhite(ptr); if(!*end) break; len = end - ptr; if(len > 8) len = 8; memset(name, 0, sizeof(name)); strncpy(name, ptr, len); ptr = F_SkipSpace(end); if(!*ptr || *ptr == '\n') continue; // Missing filename? // We're at the path name. end = F_FindNewline(ptr); // Get rid of extra whitespace. while(end > ptr && isspace(*end)) end--; end = M_FindWhite(end); len = end - ptr; if(len > FILENAME_T_MAXLEN) len = FILENAME_T_MAXLEN; memset(path, 0, sizeof(path)); strncpy(path, ptr, len); F_AddDirec(name, path, len); ptr = end; } } void F_InitMapping(void) { int i, argC = Argc(); F_ResetMapping(); // Create virtual directory mappings by processing all -vdmap // options. for(i = 0; i < argC; ++i) { if(strnicmp("-vdmap", Argv(i), 6)) continue; // This is not the option we're looking for. if(i < argC - 1 && !ArgIsOption(i + 1) && !ArgIsOption(i + 2)) { F_AddMapping(Argv(i + 1), Argv(i + 2)); i += 2; } } } /** * Initialize the WAD/dir translations. Called after WADs have been read. */ void F_InitDirec(void) { static boolean alreadyInited = false; int i; size_t len; char* buf; if(alreadyInited) { // Free old paths, if any. F_ResetDirec(); memset(direc, 0, sizeof(direc)); } // Add the contents of all DD_DIREC lumps. for(i = 0; i < numLumps; ++i) { if(!strnicmp(W_LumpName(i), "DD_DIREC", 8)) { // Make a copy of it so we can make it end in a null. len = W_LumpLength(i); buf = M_Malloc(len + 1); memcpy(buf, W_CacheLumpNum(i, PU_CACHE), len); buf[len] = 0; F_ParseDirecData(buf); M_Free(buf); } } alreadyInited = true; } void F_ResetMapping(void) { uint i; if(vdMappings) { // Free the allocated memory. for(i = 0; i < vdMappingsCount; ++i) { M_Free(vdMappings[i].source); M_Free(vdMappings[i].target); } M_Free(vdMappings); } vdMappings = NULL; vdMappingsCount = vdMappingsMax = 0; } void F_ResetDirec(void) { size_t i; for(i = 0; direc[i].path; ++i) if(direc[i].path) M_Free(direc[i].path); // Allocated by _fullpath. } void F_CloseAll(void) { uint i; if(files) { for(i = 0; i < filesCount; ++i) if(files[i].file != NULL) { F_Close(files[i].file); } M_Free(files); } files = NULL; filesCount = 0; } void F_ShutdownDirec(void) { F_ResetMapping(); F_ResetDirec(); F_CloseAll(); } /** * Returns true if the file can be opened for reading. */ int F_Access(const char *path) { // Open for reading, but don't buffer anything. DFILE *file = F_Open(path, "rx"); if(!file) return false; F_Close(file); return true; } DFILE *F_GetFreeFile(void) { uint i, oldCount; boolean found; filehandle_t *fhdl; for(i = 0, found = false, fhdl = files; i < filesCount && !found; fhdl++, ++i) { if(fhdl->file == NULL) found = true; } if(found) { fhdl->file = M_Calloc(sizeof(DFILE)); return fhdl->file; } oldCount = filesCount; // Allocate more memory. filesCount *= 2; if(filesCount < 16) filesCount = 16; files = M_Realloc(files, sizeof(filehandle_t) * filesCount); // Clear the new handles. for(i = oldCount; i < filesCount; ++i) { memset(&files[i], 0, sizeof(filehandle_t)); } files[oldCount].file = M_Calloc(sizeof(DFILE)); return files[oldCount].file; } /** * Frees the memory allocated to the handle. */ void F_Release(DFILE *file) { uint i; if(!file) return; if(files) { // Clear references to the handle. for(i = 0; i < filesCount; ++i) if(files[i].file == file) files[i].file = NULL; } // File was allocated in F_GetFreeFile. M_Free(file); } DFILE *F_OpenLump(const char *name, boolean dontBuffer) { int num = W_CheckNumForName((char *) name); DFILE *file; if(num < 0) return NULL; file = F_GetFreeFile(); if(!file) return NULL; // Init and load in the lump data. file->flags.open = true; file->flags.file = false; file->lastModified = time(NULL); // So I'm lazy... if(!dontBuffer) { file->size = W_LumpLength(num); file->pos = file->data = M_Malloc(file->size); memcpy(file->data, W_CacheLumpNum(num, PU_CACHE), file->size); } return file; } /** * This only works on real files. */ static unsigned int F_GetLastModified(const char *path) { #ifdef UNIX struct stat s; stat(path, &s); return s.st_mtime; #endif #ifdef WIN32 struct _stat s; _stat(path, &s); return s.st_mtime; #endif } /** * @return @c true, if the mapping matched the path. */ boolean F_MapPath(char* mapped, const char* path, vdmapping_t* vd, size_t len) { size_t targetLen = strlen(vd->target); if(!strnicmp(path, vd->target, targetLen)) { // Replace the beginning with the source path. strncpy(mapped, vd->source, len); strncat(mapped, path + targetLen, len); return true; } return false; } DFILE* F_OpenFile(const char* path, const char* mymode) { DFILE* file = F_GetFreeFile(); char mode[8]; uint i; filename_t mapped; if(!file) return NULL; strcpy(mode, "r"); // Open for reading. if(strchr(mymode, 't')) strcat(mode, "t"); if(strchr(mymode, 'b')) strcat(mode, "b"); // Try opening as a real file. file->data = fopen(path, mode); if(!file->data) { // Any applicable virtual directory mappings? for(i = 0; i < vdMappingsCount; ++i) { if(F_MapPath(mapped, path, &vdMappings[i], FILENAME_T_MAXLEN)) { // The mapping was successful. if((file->data = fopen(mapped, mode)) != NULL) { // Success! VERBOSE(Con_Message("F_OpenFile: %s opened as %s.\n", mapped, path)); break; } } } if(!file->data) { // Still can't find it. F_Release(file); return NULL; // Can't find the file. } } file->flags.open = true; file->flags.file = true; file->lastModified = F_GetLastModified(path); return file; } /** * Zip data is buffered like lump data. */ DFILE* F_OpenZip(zipindex_t zipIndex, boolean dontBuffer) { DFILE* file = F_GetFreeFile(); if(!file) return NULL; // Init and load in the lump data. file->flags.open = true; file->flags.file = false; file->lastModified = Zip_GetLastModified(zipIndex); if(!dontBuffer) { file->size = Zip_GetSize(zipIndex); file->pos = file->data = M_Malloc(file->size); Zip_Read(zipIndex, file->data); } return file; } /** * Opens the given file (will be translated) or lump for reading. * "t" = text mode (with real files, lumps are always binary) * "b" = binary * "f" = must be a real file * "w" = file must be in a WAD * "x" = just test for access (don't buffer anything) */ DFILE* F_Open(const char* path, const char* mode) { int i; filename_t trans, full; boolean dontBuffer; if(!mode) mode = ""; dontBuffer = (strchr(mode, 'x') != NULL); // Make it a full path. M_TranslatePath(trans, path, FILENAME_T_MAXLEN); _fullpath(full, trans, 255); // Lumpdirecs take precedence. if(!strchr(mode, 'f')) // Doesn't need to be a real file? { // First check the Zip directory. zipindex_t foundZip = Zip_Find(full); if(foundZip) return F_OpenZip(foundZip, dontBuffer); for(i = 0; direc[i].path; ++i) if(!strnicmp(full, direc[i].path, FILENAME_T_MAXLEN)) return F_OpenLump(direc[i].lump, dontBuffer); } if(strchr(mode, 'w')) return NULL; // Must be in a WAD... // Try to open as a real file, then. return F_OpenFile(full, mode); } void F_Close(DFILE *file) { if(!file) return; // Wha? if(!file->flags.open) return; if(file->flags.file) { fclose(file->data); } else { // Free the stored data. if(file->data) M_Free(file->data); } memset(file, 0, sizeof(*file)); F_Release(file); } /** * @return The number of bytes read (up to 'count'). */ size_t F_Read(void *dest, size_t count, DFILE *file) { size_t bytesleft; if(!file->flags.open) return 0; if(file->flags.file) { // Normal file. count = fread(dest, 1, count, file->data); if(feof((FILE *) file->data)) file->flags.eof = true; return count; } // Is there enough room in the file? bytesleft = file->size - (file->pos - (char *) file->data); if(count > bytesleft) { count = bytesleft; file->flags.eof = true; } if(count) { memcpy(dest, file->pos, count); file->pos += count; } return count; } unsigned char F_GetC(DFILE *file) { unsigned char ch = 0; if(!file->flags.open) return 0; F_Read(&ch, 1, file); return ch; } size_t F_Tell(DFILE *file) { if(!file->flags.open) return 0; if(file->flags.file) return (size_t) ftell(file->data); return file->pos - (char *) file->data; } /** * @return The current position in the file, before the move, * as an offset from the beginning of the file. */ size_t F_Seek(DFILE *file, size_t offset, int whence) { size_t oldpos = F_Tell(file); if(!file->flags.open) return 0; file->flags.eof = false; if(file->flags.file) { fseek(file->data, (long) offset, whence); } else { if(whence == SEEK_SET) file->pos = (char *) file->data + offset; else if(whence == SEEK_END) file->pos = (char *) file->data + (file->size + offset); else if(whence == SEEK_CUR) file->pos += offset; } return oldpos; } void F_Rewind(DFILE *file) { F_Seek(file, 0, SEEK_SET); } /** * \note Stream position is not affected. * * @return The length of the file, in bytes. */ size_t F_Length(DFILE *file) { size_t length, currentPosition; if(!file) return 0; currentPosition = F_Seek(file, 0, SEEK_END); length = F_Tell(file); F_Seek(file, currentPosition, SEEK_SET); return length; } /** * @return The time when the file was last modified, as seconds * since the Epoch else zero if the file is not found. */ unsigned int F_LastModified(const char* fileName) { // Try to open the file, but don't buffer any contents. DFILE* file = F_Open(fileName, "rx"); unsigned int modified = 0; if(!file) return 0; modified = file->lastModified; F_Close(file); return modified; } /** * @return The number of times the char appears in the path. */ size_t F_CountPathChars(const char* path, char ch) { size_t count; for(count = 0; *path; path++) if(*path == ch) count++; return count; } /** * @return @c true, to indicate to stop searching, when forall_func * returns @c false. */ int F_ZipFinderForAll(const char* zipFileName, void* parm) { zipforall_t* info = parm; if(F_MatchName(zipFileName, info->pattern)) { if(!info->func(zipFileName, FT_NORMAL, info->parm)) { return true; // Stop searching. } } // Continue searching. return false; } static int C_DECL F_EntrySorter(const void* a, const void* b) { return stricmp(((const foundentry_t*)a)->name, ((const foundentry_t*)b)->name); } /** * Descends into 'physical' subdirectories. */ int F_ForAllDescend(const char* pattern, const char* path, void* parm, f_forall_func_t func) { int i, count, max; finddata_t fd; foundentry_t* found; filename_t fn, spec, localPattern; dd_snprintf(localPattern, FILENAME_T_MAXLEN, "%s%s", path, pattern); // Collect a list of paths. The list contains files in all the // paths mapped to the current path. count = 0; max = 16; found = M_Malloc(max * sizeof(*found)); for(i = -1; i < (int)vdMappingsCount; ++i) { dd_snprintf(spec, FILENAME_T_MAXLEN, "%s*", path); if(i >= 0) { filename_t mapped; // Possible virtual mapping. if(!F_MapPath(mapped, spec, &vdMappings[i], FILENAME_T_MAXLEN)) { // The mapping didn't match this one. continue; } strncpy(spec, mapped, FILENAME_T_MAXLEN); // Also map the local pattern. //F_MapPath(localPattern, &vdMappings[i], mapped); //strncpy(localPattern, mapped, FILENAME_T_MAXLEN); } if(!myfindfirst(spec, &fd)) { // The first file found! do { // Ignore the relative directory names. if(strcmp(fd.name, ".") && strcmp(fd.name, "..")) { if(count >= max) { max *= 2; found = M_Realloc(found, sizeof(*found) * max); } memset(&found[count], 0, sizeof(*found)); strncpy(found[count].name, fd.name, FILENAME_T_MAXLEN); found[count].attrib = fd.attrib; count++; } } while(!myfindnext(&fd)); } myfindend(&fd); } // Sort all the found entries. qsort(found, count, sizeof(foundentry_t), F_EntrySorter); for(i = 0; i < count; ++i) { // Compile the full pathname of the found file. strncpy(fn, path, FILENAME_T_MAXLEN); strncat(fn, found[i].name, FILENAME_T_MAXLEN); // Descend recursively into subdirectories. if(found[i].attrib & A_SUBDIR) { strncat(fn, DIR_SEP_STR, FILENAME_T_MAXLEN); if(!F_ForAllDescend(pattern, fn, parm, func)) { M_Free(found); return false; } } else { // Does this match the pattern? if(F_MatchName(fn, localPattern)) { // If the callback returns false, stop immediately. if(!func(fn, FT_NORMAL, parm)) { M_Free(found); return false; } } } } // Free the memory allocate for the list of found entries. M_Free(found); return true; } /** * Parm is passed on to the callback, which is called for each file * matching the filespec. Absolute path names are given to the callback. * Zip directory, DD_DIREC and the real files are scanned. */ int F_ForAll(const char* filespec, void* parm, f_forall_func_t func) { int i; filename_t fn; directory_t specdir; zipforall_t zipFindInfo; memset(&specdir, 0, sizeof(specdir)); Dir_FileDir(filespec, &specdir); // First check the Zip directory. _fullpath(fn, filespec, FILENAME_T_MAXLEN); zipFindInfo.func = func; zipFindInfo.parm = parm; zipFindInfo.pattern = fn; zipFindInfo.searchPath = specdir.path; if(Zip_Iterate(F_ZipFinderForAll, &zipFindInfo)) { // Find didn't finish. return false; } // Check through the dir/WAD direcs. for(i = 0; direc[i].path; ++i) if(F_MatchName(direc[i].path, fn)) if(!func(direc[i].path, FT_NORMAL, parm)) //if(!F_ForAllCaller(specdir.path, direc[i].path, func, parm)) return false; Dir_FileName(fn, filespec, FILENAME_T_MAXLEN); if(!F_ForAllDescend(fn, specdir.path, parm, func)) return false; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/def_data.c0000644000175000017500000004317011357170242022631 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * def_data.c: Doomsday Engine Definition Files * * \fixme Needs to be redesigned. */ #include #include #include #include "de_misc.h" #include "def_data.h" #include "gl_main.h" #include "p_materialmanager.h" // Helper Routines ------------------------------------------------------- /** * @return Pointer to the new block of memory. */ void *DED_NewEntries(void **ptr, ded_count_t *cnt, size_t elemSize, int count) { void *np; cnt->num += count; if(cnt->num > cnt->max) { cnt->max *= 2; // Double the size of the array. if(cnt->num > cnt->max) cnt->max = cnt->num; *ptr = M_Realloc(*ptr, elemSize * cnt->max); } np = (char *) *ptr + (cnt->num - count) * elemSize; memset(np, 0, elemSize * count); // Clear the new entries. return np; } /** * @return Pointer to the new block of memory. */ void *DED_NewEntry(void **ptr, ded_count_t *cnt, size_t elemSize) { return DED_NewEntries(ptr, cnt, elemSize, 1); } void DED_DelEntry(int index, void **ptr, ded_count_t *cnt, size_t elemSize) { if(index < 0 || index >= cnt->num) return; // Can't do that! memmove((char *) *ptr + elemSize * index, (char *) *ptr + elemSize * (index + 1), elemSize * (cnt->num - index - 1)); if(--cnt->num < cnt->max / 2) { cnt->max /= 2; *ptr = M_Realloc(*ptr, elemSize * cnt->max); } } void DED_DelArray(void **ptr, ded_count_t *cnt) { if(*ptr) M_Free(*ptr); *ptr = 0; cnt->num = cnt->max = 0; } void DED_ZCount(ded_count_t *c) { c->num = c->max = 0; } // DED Code -------------------------------------------------------------- void DED_Init(ded_t *ded) { memset(ded, 0, sizeof(*ded)); ded->version = DED_VERSION; } void DED_Destroy(ded_t* ded) { int i; if(ded->flags) M_Free(ded->flags); if(ded->mobjs) M_Free(ded->mobjs); if(ded->states) M_Free(ded->states); if(ded->sprites) M_Free(ded->sprites); if(ded->lights) M_Free(ded->lights); if(ded->models) M_Free(ded->models); if(ded->sounds) M_Free(ded->sounds); if(ded->music) M_Free(ded->music); if(ded->mapInfo) M_Free(ded->mapInfo); if(ded->skies) M_Free(ded->skies); if(ded->materials) { for(i = 0; i < ded->count.materials.num; ++i) { uint j; for(j = 0; j < DED_MAX_MATERIAL_LAYERS; ++j) M_Free(ded->materials[i].layers[j].stages); } M_Free(ded->materials); } if(ded->text) { for(i = 0; i < ded->count.text.num; ++i) { M_Free(ded->text[i].text); } M_Free(ded->text); } if(ded->textureEnv) { for(i = 0; i < ded->count.textureEnv.num; ++i) { M_Free(ded->textureEnv[i].materials); } M_Free(ded->textureEnv); } if(ded->values) { for(i = 0; i < ded->count.values.num; ++i) { M_Free(ded->values[i].id); M_Free(ded->values[i].text); } M_Free(ded->values); } if(ded->decorations) M_Free(ded->decorations); if(ded->groups) { for(i = 0; i < ded->count.groups.num; ++i) { M_Free(ded->groups[i].members); } M_Free(ded->groups); } if(ded->sectorTypes) M_Free(ded->sectorTypes); if(ded->lineTypes) M_Free(ded->lineTypes); if(ded->ptcGens) { for(i = 0; i < ded->count.ptcGens.num; ++i) { M_Free(ded->ptcGens[i].stages); } M_Free(ded->ptcGens); } if(ded->finales) M_Free(ded->finales); if(ded->xgClasses) { for(i = 0; i < ded->count.xgClasses.num; ++i) { M_Free(ded->xgClasses[i].properties); } M_Free(ded->xgClasses); } } int DED_AddMobj(ded_t *ded, char *idstr) { ded_mobj_t *mo = DED_NewEntry((void **) &ded->mobjs, &ded->count.mobjs, sizeof(ded_mobj_t)); strcpy(mo->id, idstr); return mo - ded->mobjs; } void DED_RemoveMobj(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->mobjs, &ded->count.mobjs, sizeof(ded_mobj_t)); } int DED_AddXGClass(ded_t *ded) { ded_xgclass_t *xgc = DED_NewEntry((void **) &ded->xgClasses, &ded->count.xgClasses, sizeof(ded_xgclass_t)); return xgc - ded->xgClasses; } int DED_AddXGClassProperty(ded_xgclass_t *xgc) { ded_xgclass_property_t *xgcp = DED_NewEntry((void **) &xgc->properties, &xgc->propertiesCount, sizeof(ded_xgclass_property_t)); return xgcp - xgc->properties; } void DED_RemoveXGClass(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->xgClasses, &ded->count.xgClasses, sizeof(ded_xgclass_t)); } int DED_AddFlag(ded_t *ded, char *name, char *text, int value) { ded_flag_t *fl = DED_NewEntry((void **) &ded->flags, &ded->count.flags, sizeof(ded_flag_t)); strcpy(fl->id, name); strcpy(fl->text, text); fl->value = value; return fl - ded->flags; } void DED_RemoveFlag(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->flags, &ded->count.flags, sizeof(ded_flag_t)); } int DED_AddModel(ded_t *ded, char *spr) { int i; ded_model_t *md = DED_NewEntry((void **) &ded->models, &ded->count.models, sizeof(ded_model_t)); strcpy(md->sprite.id, spr); md->interRange[1] = 1; md->scale[0] = md->scale[1] = md->scale[2] = 1; // Init submodels. for(i = 0; i < DED_MAX_SUB_MODELS; ++i) { md->sub[i].shinyColor[CR] = md->sub[i].shinyColor[CG] = md->sub[i].shinyColor[CB] = 1; md->sub[i].shinyReact = 1.0f; } return md - ded->models; } void DED_RemoveModel(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->models, &ded->count.models, sizeof(ded_model_t)); } int DED_AddSky(ded_t* ded, char* id) { int i; ded_sky_t* sky = DED_NewEntry((void **) &ded->skies, &ded->count.skies, sizeof(ded_sky_t)); strcpy(sky->id, id); sky->height = .666667f; for(i = 0; i < NUM_SKY_MODELS; ++i) { sky->models[i].frameInterval = 1; sky->models[i].color[0] = 1; sky->models[i].color[1] = 1; sky->models[i].color[2] = 1; sky->models[i].color[3] = 1; } return sky - ded->skies; } void DED_RemoveSky(ded_t* ded, int index) { DED_DelEntry(index, (void **) &ded->skies, &ded->count.skies, sizeof(ded_sky_t)); } int DED_AddState(ded_t *ded, char *id) { ded_state_t *st = DED_NewEntry((void **) &ded->states, &ded->count.states, sizeof(ded_state_t)); strcpy(st->id, id); return st - ded->states; } void DED_RemoveState(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->states, &ded->count.states, sizeof(ded_state_t)); } int DED_AddSprite(ded_t *ded, const char *name) { ded_sprid_t *sp = DED_NewEntry((void **) &ded->sprites, &ded->count.sprites, sizeof(ded_sprid_t)); strcpy(sp->id, name); return sp - ded->sprites; } void DED_RemoveSprite(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->sprites, &ded->count.sprites, sizeof(ded_sprid_t)); } int DED_AddLight(ded_t *ded, const char *stateid) { ded_light_t *light = DED_NewEntry((void **) &ded->lights, &ded->count.lights, sizeof(ded_light_t)); strcpy(light->state, stateid); return light - ded->lights; } void DED_RemoveLight(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->lights, &ded->count.lights, sizeof(ded_light_t)); } int DED_AddMaterial(ded_t* ded, const char* name) { ded_material_t* mat = DED_NewEntry((void **) &ded->materials, &ded->count.materials, sizeof(ded_material_t)); strcpy(mat->id.name, name); mat->id.mnamespace = MN_ANY; return mat - ded->materials; } int DED_AddMaterialLayerStage(ded_material_layer_t* ml) { ded_material_layer_stage_t* stage = DED_NewEntry((void **) &ml->stages, &ml->stageCount, sizeof(*stage)); stage->type = -1; // Unused. return stage - ml->stages; } void DED_RemoveMaterial(ded_t* ded, int index) { DED_DelEntry(index, (void **) &ded->materials, &ded->count.materials, sizeof(ded_material_t)); } int DED_AddSound(ded_t *ded, char *id) { ded_sound_t *snd = DED_NewEntry((void **) &ded->sounds, &ded->count.sounds, sizeof(ded_sound_t)); strcpy(snd->id, id); return snd - ded->sounds; } void DED_RemoveSound(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->sounds, &ded->count.sounds, sizeof(ded_sound_t)); } int DED_AddMusic(ded_t *ded, char *id) { ded_music_t *mus = DED_NewEntry((void **) &ded->music, &ded->count.music, sizeof(ded_music_t)); strcpy(mus->id, id); return mus - ded->music; } void DED_RemoveMusic(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->music, &ded->count.music, sizeof(ded_music_t)); } int DED_AddMapInfo(ded_t *ded, char *str) { ded_mapinfo_t *inf = DED_NewEntry((void **) &ded->mapInfo, &ded->count.mapInfo, sizeof(ded_mapinfo_t)); int i; strcpy(inf->id, str); inf->gravity = 1; inf->parTime = -1; // unknown inf->fogColor[0] = DEFAULT_FOG_COLOR_RED; inf->fogColor[1] = DEFAULT_FOG_COLOR_GREEN; inf->fogColor[2] = DEFAULT_FOG_COLOR_BLUE; inf->fogDensity = DEFAULT_FOG_DENSITY; inf->fogStart = DEFAULT_FOG_START; inf->fogEnd = DEFAULT_FOG_END; inf->sky.height = .666667f; for(i = 0; i < NUM_SKY_MODELS; ++i) { inf->sky.models[i].frameInterval = 1; inf->sky.models[i].color[0] = 1; inf->sky.models[i].color[1] = 1; inf->sky.models[i].color[2] = 1; inf->sky.models[i].color[3] = 1; } return inf - ded->mapInfo; } void DED_RemoveMapInfo(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->mapInfo, &ded->count.mapInfo, sizeof(ded_mapinfo_t)); } int DED_AddText(ded_t *ded, char *id) { ded_text_t *txt = DED_NewEntry((void **) &ded->text, &ded->count.text, sizeof(ded_text_t)); strcpy(txt->id, id); return txt - ded->text; } void DED_RemoveText(ded_t *ded, int index) { M_Free(ded->text[index].text); DED_DelEntry(index, (void **) &ded->text, &ded->count.text, sizeof(ded_text_t)); } int DED_AddTextureEnv(ded_t *ded, char *id) { ded_tenviron_t *env = DED_NewEntry((void **) &ded->textureEnv, &ded->count.textureEnv, sizeof(ded_tenviron_t)); strcpy(env->id, id); return env - ded->textureEnv; } void DED_RemoveTextureEnv(ded_t *ded, int index) { M_Free(ded->textureEnv[index].materials); DED_DelEntry(index, (void **) &ded->textureEnv, &ded->count.textureEnv, sizeof(ded_tenviron_t)); } int DED_AddValue(ded_t *ded, const char *id) { ded_value_t *val = DED_NewEntry((void **) &ded->values, &ded->count.values, sizeof(ded_value_t)); if(id) { val->id = M_Malloc(strlen(id) + 1); strcpy(val->id, id); } return val - ded->values; } void DED_RemoveValue(ded_t *ded, int index) { M_Free(ded->values[index].id); M_Free(ded->values[index].text); DED_DelEntry(index, (void **) &ded->values, &ded->count.values, sizeof(ded_value_t)); } int DED_AddDetail(ded_t *ded, const char *lumpname) { ded_detailtexture_t *dtl = DED_NewEntry((void **) &ded->details, &ded->count.details, sizeof(ded_detailtexture_t)); strcpy(dtl->detailLump.path, lumpname); dtl->scale = 1; dtl->strength = 1; return dtl - ded->details; } void DED_RemoveDetail(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->details, &ded->count.details, sizeof(ded_detailtexture_t)); } int DED_AddPtcGen(ded_t *ded, const char *state) { ded_ptcgen_t *gen = DED_NewEntry((void **) &ded->ptcGens, &ded->count.ptcGens, sizeof(ded_ptcgen_t)); strcpy(gen->state, state); // Default choice (use either submodel zero or one). gen->subModel = -1; return gen - ded->ptcGens; } int DED_AddPtcGenStage(ded_ptcgen_t *gen) { ded_ptcstage_t *stage = DED_NewEntry((void **) &gen->stages, &gen->stageCount, sizeof(ded_ptcstage_t)); stage->model = -1; stage->sound.volume = 1; stage->hitSound.volume = 1; return stage - gen->stages; } void DED_RemovePtcGen(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->ptcGens, &ded->count.ptcGens, sizeof(ded_ptcgen_t)); } int DED_AddFinale(ded_t *ded) { ded_finale_t *fin = DED_NewEntry((void **) &ded->finales, &ded->count.finales, sizeof(ded_finale_t)); return fin - ded->finales; } void DED_RemoveFinale(ded_t *ded, int index) { M_Free(ded->finales[index].script); DED_DelEntry(index, (void **) &ded->finales, &ded->count.finales, sizeof(ded_finale_t)); } int DED_AddDecoration(ded_t *ded) { ded_decor_t *decor = DED_NewEntry((void **) &ded->decorations, &ded->count.decorations, sizeof(ded_decor_t)); int i; // Init some default values. for(i = 0; i < DED_DECOR_NUM_LIGHTS; ++i) { // The color (0,0,0) means the light is not active. decor->lights[i].elevation = 1; decor->lights[i].radius = 1; } return decor - ded->decorations; } void DED_RemoveDecoration(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->decorations, &ded->count.decorations, sizeof(ded_decor_t)); } int DED_AddReflection(ded_t *ded) { ded_reflection_t *ref = DED_NewEntry((void **) &ded->reflections, &ded->count.reflections, sizeof(ded_reflection_t)); // Init to defaults. ref->shininess = 1.0f; ref->maskWidth = 1.0f; ref->maskHeight = 1.0f; ref->blendMode = BM_ADD; return ref - ded->reflections; } void DED_RemoveReflection(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->reflections, &ded->count.reflections, sizeof(ded_reflection_t)); } int DED_AddGroup(ded_t *ded) { ded_group_t *group = DED_NewEntry((void **) &ded->groups, &ded->count.groups, sizeof(ded_group_t)); return group - ded->groups; } void DED_RemoveGroup(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->groups, &ded->count.groups, sizeof(ded_group_t)); } int DED_AddGroupMember(ded_group_t *grp) { ded_group_member_t *memb = DED_NewEntry((void **) &grp->members, &grp->count, sizeof(ded_group_member_t)); return memb - grp->members; } int DED_AddSectorType(ded_t *ded, int id) { ded_sectortype_t *sec = DED_NewEntry((void **) &ded->sectorTypes, &ded->count.sectorTypes, sizeof(ded_sectortype_t)); sec->id = id; return sec - ded->sectorTypes; } void DED_RemoveSectorType(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->sectorTypes, &ded->count.sectorTypes, sizeof(ded_sectortype_t)); } int DED_AddLineType(ded_t *ded, int id) { ded_linetype_t *li = DED_NewEntry((void **) &ded->lineTypes, &ded->count.lineTypes, sizeof(ded_linetype_t)); li->id = id; //li->actCount = -1; return li - ded->lineTypes; } void DED_RemoveLineType(ded_t *ded, int index) { DED_DelEntry(index, (void **) &ded->lineTypes, &ded->count.lineTypes, sizeof(ded_linetype_t)); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/b_command.c0000644000175000017500000003522411357170241023021 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_command.c: Event-Command Bindings */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_misc.h" #include "de_play.h" #include "b_main.h" #include "b_command.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void B_InitCommandBindingList(evbinding_t* listRoot) { memset(listRoot, 0, sizeof(*listRoot)); listRoot->next = listRoot; listRoot->prev = listRoot; } void B_DestroyCommandBindingList(evbinding_t* listRoot) { while(listRoot->next != listRoot) { B_DestroyCommandBinding(listRoot->next); } } /** * Allocates a new command binding and gives it a unique identifier. */ static evbinding_t* B_AllocCommandBinding(void) { evbinding_t* eb = M_Calloc(sizeof(evbinding_t)); eb->bid = B_NewIdentifier(); return eb; } /** * Allocates a device state condition within an event binding. * * @return Pointer to the new condition, which should be filled with the condition parameters. */ static statecondition_t* B_AllocCommandBindingCondition(evbinding_t* eb) { eb->conds = M_Realloc(eb->conds, ++eb->numConds * sizeof(statecondition_t)); memset(&eb->conds[eb->numConds - 1], 0, sizeof(statecondition_t)); return &eb->conds[eb->numConds - 1]; } /** * Parse the main part of the event descriptor, with no conditions included. */ boolean B_ParseEvent(evbinding_t* eb, const char* desc) { boolean successful = false; ddstring_t* str = Str_New(); // First, we expect to encounter a device name. desc = Str_CopyDelim(str, desc, '-'); if(!Str_CompareIgnoreCase(str, "key")) { eb->device = IDEV_KEYBOARD; // Keyboards only have toggles (as far as we know). eb->type = E_TOGGLE; // Parse the key. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseKeyId(Str_Text(str), &eb->id)) { goto parseEnded; } // The final part of a key event is the state of the key toggle. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseToggleState(Str_Text(str), &eb->state)) { goto parseEnded; } } else if(!Str_CompareIgnoreCase(str, "mouse")) { eb->device = IDEV_MOUSE; // Next comes a button or axis name. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseMouseTypeAndId(Str_Text(str), &eb->type, &eb->id)) { goto parseEnded; } // The last part determines the toggle state or the axis position. desc = Str_CopyDelim(str, desc, '-'); if(eb->type == E_TOGGLE) { if(!B_ParseToggleState(Str_Text(str), &eb->state)) { goto parseEnded; } } else // Axis position. { if(!B_ParseAxisPosition(Str_Text(str), &eb->state, &eb->pos)) { goto parseEnded; } } } else if(!Str_CompareIgnoreCase(str, "joy")) { eb->device = IDEV_JOY1; // Next part defined button, axis, or hat. desc = Str_CopyDelim(str, desc, '-'); if(!B_ParseJoystickTypeAndId(eb->device, Str_Text(str), &eb->type, &eb->id)) { goto parseEnded; } // What is the state of the toggle, axis, or hat? desc = Str_CopyDelim(str, desc, '-'); if(eb->type == E_TOGGLE) { if(!B_ParseToggleState(Str_Text(str), &eb->state)) { goto parseEnded; } } else if(eb->type == E_AXIS) { if(!B_ParseAxisPosition(Str_Text(str), &eb->state, &eb->pos)) { goto parseEnded; } } else // Angle. { if(!B_ParseAnglePosition(Str_Text(str), &eb->pos)) { goto parseEnded; } } } else if(!Str_CompareIgnoreCase(str, "sym")) { // It must be a symbolic event. eb->type = E_SYMBOLIC; eb->device = 0; eb->symbolicName = strdup(desc); desc = NULL; } else { Con_Message("B_ParseEvent: Device \"%s\" unknown.\n", Str_Text(str)); goto parseEnded; } // Anything left that wasn't used? if(desc) { Con_Message("B_ParseEvent: Unrecognized \"%s\".\n", desc); goto parseEnded; } // No errors detected. successful = true; parseEnded: Str_Delete(str); return successful; } /** * Parses a textual descriptor of the conditions for triggering an event-command binding. * eventparams{+cond}* * * @param eb The results of the parsing are stored here. * @param desc Descriptor containing event information and possible additional conditions. * * @return @c true, if successful; otherwise @c false. */ boolean B_ParseEventDescriptor(evbinding_t* eb, const char* desc) { boolean successful = false; ddstring_t* str = Str_New(); // The main part, i.e., the first part. desc = Str_CopyDelim(str, desc, '+'); if(!B_ParseEvent(eb, Str_Text(str))) { // Failure parsing the event. goto parseEnded; } // Any conditions? while(desc) { statecondition_t *cond; // A new condition. desc = Str_CopyDelim(str, desc, '+'); cond = B_AllocCommandBindingCondition(eb); if(!B_ParseStateCondition(cond, Str_Text(str))) { // Failure parusing the condition. goto parseEnded; } } // Success. successful = true; parseEnded: Str_Delete(str); return successful; } /** * Creates a new event-command binding. * * @param bindsList List of bindings where the binding will be added. * @param desc Descriptor of the event. * @param command Command that will be executed by the binding. * * @return New binding, or @c NULL if there was an error. */ evbinding_t* B_NewCommandBinding(evbinding_t* bindsList, const char* desc, const char* command) { evbinding_t* eb = B_AllocCommandBinding(); // Parse the description of the event. if(!B_ParseEventDescriptor(eb, desc)) { // Error in parsing, failure to create binding. B_DestroyCommandBinding(eb); return NULL; } // The command string. eb->command = strdup(command); // Link it into the list. eb->next = bindsList; eb->prev = bindsList->prev; bindsList->prev->next = eb; bindsList->prev = eb; return eb; } /** * Destroys a command binding. * * @param eb Command binding to destroy. */ void B_DestroyCommandBinding(evbinding_t* eb) { if(!eb) return; assert(eb->bid != 0); // Unlink first, if linked. if(eb->prev) { eb->prev->next = eb->next; eb->next->prev = eb->prev; } if(eb->command) M_Free(eb->command); if(eb->conds) M_Free(eb->conds); free(eb->symbolicName); M_Free(eb); } /** * Substitute placeholders in a command string. Placeholders consist of two characters, * the first being a %. Use %% to output a plain % character. * * - %i: id member of the event * - %p: (symbolic events only) local player number * * @param command Original command string with the placeholders. * @param event Event data. * @param eb Binding data. * @param out String with placeholders replaced. */ void B_SubstituteInCommand(const char* command, ddevent_t* event, evbinding_t* eb, ddstring_t* out) { const char* ptr = command; for(; *ptr; ptr++) { if(*ptr == '%') { // Escape. ptr++; // Must have another character in the placeholder. if(!*ptr) break; if(*ptr == 'i') { int id = 0; switch(event->type) { case E_TOGGLE: id = event->toggle.id; break; case E_AXIS: id = event->axis.id; break; case E_ANGLE: id = event->angle.id; break; case E_SYMBOLIC: id = event->symbolic.id; break; } Str_Appendf(out, "%i", id); } else if(*ptr == 'p') { int id = 0; if(event->type == E_SYMBOLIC) { id = P_ConsoleToLocal(event->symbolic.id); } Str_Appendf(out, "%i", id); } else if(*ptr == '%') { Str_AppendChar(out, *ptr); } continue; } Str_AppendChar(out, *ptr); } } /** * Checks if the event matches the binding's conditions, and if so, executes the * bound command. * * @param eventClass The event has been bound in this binding class. If the * bound state is associated with a higher-priority active * class, the binding cannot be executed. * * @return @c true, if the bound command was executed. @c false otherwise, as the * event didn't match all the conditions. */ boolean B_TryCommandBinding(evbinding_t* eb, ddevent_t* event, struct bcontext_s* eventClass) { int i; inputdev_t* dev; ddstring_t command; if(eb->device != event->device || eb->type != event->type) return false; if(event->type != E_SYMBOLIC) { dev = I_GetDevice(eb->device, true); if(!dev) { // The device is not active, there is no way this could get executed. return false; } } switch(event->type) { case E_TOGGLE: if(eb->id != event->toggle.id) return false; if(eventClass && dev->keys[eb->id].assoc.bContext != eventClass) return false; // Shadowed by a more important active class. // Is the state as required? switch(eb->state) { case EBTOG_UNDEFINED: // Passes no matter what. break; case EBTOG_DOWN: if(event->toggle.state != ETOG_DOWN) return false; break; case EBTOG_UP: if(event->toggle.state != ETOG_UP) return false; break; case EBTOG_REPEAT: if(event->toggle.state != ETOG_REPEAT) return false; break; case EBTOG_PRESS: if(event->toggle.state == ETOG_UP) return false; break; default: return false; } break; case E_AXIS: if(eb->id != event->axis.id) return false; if(eventClass && dev->axes[eb->id].assoc.bContext != eventClass) return false; // Shadowed by a more important active class. // Is the position as required? if(!B_CheckAxisPos(eb->state, eb->pos, I_TransformAxis(I_GetDevice(event->device, false), event->axis.id, event->axis.pos))) return false; break; case E_ANGLE: if(eb->id != event->angle.id) return false; if(eventClass && dev->hats[eb->id].assoc.bContext != eventClass) return false; // Shadowed by a more important active class. // Is the position as required? if(event->angle.pos != eb->pos) return false; break; case E_SYMBOLIC: if(strcmp(event->symbolic.name, eb->symbolicName)) return false; break; default: return false; } // Any conditions on the current state of the input devices? for(i = 0; i < eb->numConds; ++i) { if(!B_CheckCondition(&eb->conds[i], 0, NULL)) return false; } // Substitute parameters in the command. Str_Init(&command); Str_Reserve(&command, strlen(eb->command)); B_SubstituteInCommand(eb->command, event, eb, &command); // Do the command. Con_Executef(CMDS_BIND, false, Str_Text(&command)); Str_Free(&command); return true; } /** * Does the opposite of the B_Parse* methods for event descriptor, including the * state conditions. */ void B_EventBindingToString(const evbinding_t* eb, ddstring_t* str) { int i; Str_Clear(str); B_AppendDeviceDescToString(eb->device, eb->type, eb->id, str); if(eb->type == E_TOGGLE) { B_AppendToggleStateToString(eb->state, str); } else if(eb->type == E_AXIS) { B_AppendAxisPositionToString(eb->state, eb->pos, str); } else if(eb->type == E_ANGLE) { B_AppendAnglePositionToString(eb->pos, str); } else if(eb->type == E_SYMBOLIC) { Str_Appendf(str, "-%s", eb->symbolicName); } // Append any state conditions. for(i = 0; i < eb->numConds; ++i) { Str_Append(str, " + "); B_AppendConditionToString(&eb->conds[i], str); } } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_shadow.c0000644000175000017500000002223511357170242022707 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_shadow.c: Runtime Map Shadowing (FakeRadio) */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_console.h" #include "de_refresh.h" #include "de_misc.h" #include "de_play.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static zblockset_t *shadowLinksBlockSet; // CODE -------------------------------------------------------------------- /** * Line1 and line2 are the (dx,dy)s for two lines, connected at the * origin (0,0). Dist1 and dist2 are the distances from these lines. * The returned point (in 'point') is dist1 away from line1 and dist2 * from line2, while also being the nearest point to the origin (in * case the lines are parallel). */ void R_CornerNormalPoint(const pvec2_t line1, float dist1, const pvec2_t line2, float dist2, pvec2_t point, pvec2_t lp) { float len1, len2; vec2_t norm1, norm2; // Length of both lines. len1 = V2_Length(line1); len2 = V2_Length(line2); // Calculate normals for both lines. V2_Set(norm1, -line1[VY] / len1 * dist1, line1[VX] / len1 * dist1); V2_Set(norm2, line2[VY] / len2 * dist2, -line2[VX] / len2 * dist2); // Do we need to calculate the extended points, too? Check that // the extension does not bleed too badly outside the legal shadow // area. if(lp) { V2_Set(lp, line2[VX] / len2 * dist2, line2[VY] / len2 * dist2); } // Are the lines parallel? If so, they won't connect at any // point, and it will be impossible to determine a corner point. if(V2_IsParallel(line1, line2)) { // Just use a normal as the point. if(point) V2_Copy(point, norm1); return; } // Find the intersection of normal-shifted lines. That'll be our // corner point. if(point) V2_Intersection(norm1, line1, norm2, line2, point); } /** * @return The width (world units) of the shadow edge. * It is scaled depending on the length of the edge. */ float R_ShadowEdgeWidth(const pvec2_t edge) { float length = V2_Length(edge); float normalWidth = 20; //16; float maxWidth = 60; float w; // A long edge? if(length > 600) { w = length - 600; if(w > 1000) w = 1000; return normalWidth + w / 1000 * maxWidth; } return normalWidth; } /** * Updates all the shadow offsets for the given vertex. * * \pre Lineowner rings MUST be set up. * * @param vtx Ptr to the vertex being updated. */ void R_UpdateVertexShadowOffsets(vertex_t *vtx) { vec2_t left, right; if(vtx->numLineOwners > 0) { lineowner_t *own, *base; own = base = vtx->lineOwners; do { linedef_t *lineB = own->lineDef; linedef_t *lineA = own->LO_next->lineDef; if(lineB->L_v1 == vtx) { right[VX] = lineB->dX; right[VY] = lineB->dY; } else { right[VX] = -lineB->dX; right[VY] = -lineB->dY; } if(lineA->L_v1 == vtx) { left[VX] = -lineA->dX; left[VY] = -lineA->dY; } else { left[VX] = lineA->dX; left[VY] = lineA->dY; } // The left side is always flipped. V2_Scale(left, -1); R_CornerNormalPoint(left, R_ShadowEdgeWidth(left), right, R_ShadowEdgeWidth(right), own->shadowOffsets.inner, own->shadowOffsets.extended); own = own->LO_next; } while(own != base); } } /** * Link a seg to an arbitary subsector for the purposes of shadowing. */ static void linkShadowLineDefToSSec(linedef_t *line, byte side, subsector_t *subsector) { shadowlink_t *link; #ifdef _DEBUG // Check the links for dupes! { shadowlink_t *i; for(i = subsector->shadows; i; i = i->next) if(i->lineDef == line && i->side == side) Con_Error("R_LinkShadow: Already here!!\n"); } #endif // We'll need to allocate a new link. link = Z_BlockNewElement(shadowLinksBlockSet); // The links are stored into a linked list. link->next = subsector->shadows; subsector->shadows = link; link->lineDef = line; link->side = side; } typedef struct shadowlinkerparms_s { linedef_t *lineDef; byte side; } shadowlinkerparms_t; /** * If the shadow polygon (parm) contacts the subsector, link the poly * to the subsector's shadow list. */ boolean RIT_ShadowSubsectorLinker(subsector_t *subsector, void *parm) { shadowlinkerparms_t *data = (shadowlinkerparms_t*) parm; linkShadowLineDefToSSec(data->lineDef, data->side, subsector); return true; } /** * Does the given linedef qualify as an edge shadow caster? */ boolean R_IsShadowingLinedef(linedef_t *line) { if(line) { if(!LINE_SELFREF(line) && !(line->inFlags & LF_POLYOBJ) && !(line->vo[0]->LO_next->lineDef == line || line->vo[1]->LO_next->lineDef == line)) { return true; } } return false; } /** * Calculate sector edge shadow points, create the shadow polygons and link * them to the subsectors. */ void R_InitSectorShadows(void) { uint startTime = Sys_GetRealTime(); uint i, j; vec2_t bounds[2], point; vertex_t *vtx0, *vtx1; lineowner_t *vo0, *vo1; shadowlinkerparms_t data; for(i = 0; i < numVertexes; ++i) { R_UpdateVertexShadowOffsets(VERTEX_PTR(i)); } /** * The algorithm: * * 1. Use the subsector blockmap to look for all the blocks that are * within the linedef's shadow bounding box. * * 2. Check the subsectors whose sector is the same as the linedef. * * 3. If any of the shadow points are in the subsector, or any of the * shadow edges cross one of the subsector's edges (not parallel), * link the linedef to the subsector. */ shadowLinksBlockSet = Z_BlockCreate(sizeof(shadowlink_t), 1024, PU_MAP); for(i = 0; i < numLineDefs; ++i) { linedef_t *line = LINE_PTR(i); if(R_IsShadowingLinedef(line)) for(j = 0; j < 2; ++j) { if(!line->L_side(j)) continue; vtx0 = line->L_v(j); vtx1 = line->L_v(j^1); vo0 = line->L_vo(j)->LO_next; vo1 = line->L_vo(j^1)->LO_prev; // Use the extended points, they are wider than inoffsets. V2_Set(point, vtx0->V_pos[VX], vtx0->V_pos[VY]); V2_InitBox(bounds, point); V2_Sum(point, point, vo0->shadowOffsets.extended); V2_AddToBox(bounds, point); V2_Set(point, vtx1->V_pos[VX], vtx1->V_pos[VY]); V2_AddToBox(bounds, point); V2_Sum(point, point, vo1->shadowOffsets.extended); V2_AddToBox(bounds, point); data.lineDef = line; data.side = j; P_SubsectorsBoxIteratorv(bounds, line->L_sector(j), RIT_ShadowSubsectorLinker, &data); } } // How much time did we spend? VERBOSE(Con_Message ("R_InitSectorShadows: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/p_think.c0000644000175000017500000002464611357170242022545 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_think.c: Thinkers. */ // HEADER FILES ------------------------------------------------------------ #include "de_base.h" #include "de_defs.h" #include "de_console.h" #include "de_network.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { boolean isPublic; /* @c true = all thinkers in this list are visible publically */ thinker_t thinkerCap; } thinkerlist_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int idtable[2048]; // 65536 bits telling which IDs are in use. unsigned short iddealer = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static size_t numThinkerLists; static thinkerlist_t** thinkerLists; static boolean inited = false; // CODE -------------------------------------------------------------------- static thid_t newMobjID(void) { // Increment the ID dealer until a free ID is found. // \fixme What if all IDs are in use? 65535 thinkers!? while(P_IsUsedMobjID(++iddealer)); // Mark this ID as used. P_SetMobjID(iddealer, true); return iddealer; } void P_ClearMobjIDs(void) { memset(idtable, 0, sizeof(idtable)); idtable[0] |= 1; // ID zero is always "used" (it's not a valid ID). } boolean P_IsUsedMobjID(thid_t id) { return idtable[id >> 5] & (1 << (id & 31) /*(id % 32) */ ); } void P_SetMobjID(thid_t id, boolean state) { int c = id >> 5, bit = 1 << (id & 31); //(id % 32); if(state) idtable[c] |= bit; else idtable[c] &= ~bit; } static void linkThinkerToList(thinker_t* th, thinkerlist_t* list) { // Link the thinker to the thinker list. list->thinkerCap.prev->next = th; th->next = &list->thinkerCap; th->prev = list->thinkerCap.prev; list->thinkerCap.prev = th; } static void unlinkThinkerFromList(thinker_t* th) { th->next->prev = th->prev; th->prev->next = th->next; } static void initThinkerList(thinkerlist_t* list) { list->thinkerCap.prev = list->thinkerCap.next = &list->thinkerCap; } static thinkerlist_t* listForThinkFunc(think_t func, boolean isPublic, boolean canCreate) { size_t i; for(i = 0; i < numThinkerLists; ++i) { thinkerlist_t* list = thinkerLists[i]; if(list->thinkerCap.function == func && list->isPublic == isPublic) return list; } if(!canCreate) return NULL; // A new thinker type. { thinkerlist_t* list; thinkerLists = Z_Realloc(thinkerLists, sizeof(thinkerlist_t*) * ++numThinkerLists, PU_STATIC); thinkerLists[numThinkerLists-1] = list = Z_Calloc(sizeof(thinkerlist_t), PU_STATIC, 0); initThinkerList(list); list->isPublic = isPublic; list->thinkerCap.function = func; // Set the list sentinel to instasis (safety measure). list->thinkerCap.inStasis = true; return list; } } static boolean runThinker(thinker_t* th, void* context) { // Thinker cannot think when in stasis. if(!th->inStasis) { if(th->function == (think_t) -1) { // Time to remove it. unlinkThinkerFromList(th); if(th->id) { // Its a mobj. P_MobjRecycle((mobj_t*) th); } else { Z_Free(th); } } else if(th->function) { th->function(th); } } return true; // Continue iteration. } static boolean iterateThinkers(thinkerlist_t* list, boolean (*callback) (thinker_t*, void*), void* context) { boolean result = true; if(list) { thinker_t* th, *next; th = list->thinkerCap.next; while(th != &list->thinkerCap && th) { #ifdef FAKE_MEMORY_ZONE assert(th->next != NULL); assert(th->prev != NULL); #endif next = th->next; if((result = callback(th, context)) == 0) break; th = next; } } return result; } /** * @param th Thinker to be added. * @param makePublic If @c true, this thinker will be visible publically * via the Doomsday public API thinker interface(s). */ void P_ThinkerAdd(thinker_t* th, boolean makePublic) { if(!th) return; if(!th->function) { Con_Error("P_ThinkerAdd: Invalid thinker function."); } // Will it need an ID? if(P_IsMobjThinker(th->function)) { // It is a mobj, give it an ID. th->id = newMobjID(); } else { // Zero is not a valid ID. th->id = 0; } // Link the thinker to the thinker list. linkThinkerToList(th, listForThinkFunc(th->function, makePublic, true)); } /** * Deallocation is lazy -- it will not actually be freed until its * thinking turn comes up. */ void P_ThinkerRemove(thinker_t* th) { // Has got an ID? if(th->id) { // Then it must be a mobj. mobj_t* mo = (mobj_t *) th; // Flag the ID as free. P_SetMobjID(th->id, false); // If the state of the mobj is the NULL state, this is a // predictable mobj removal (result of animation reaching its // end) and shouldn't be included in netGame deltas. if(!isClient) { if(!mo->state || mo->state == states) { Sv_MobjRemoved(th->id); } } } th->function = (think_t) - 1; } boolean P_IsMobjThinker(think_t func) { if(func && func == gx.MobjThinker) return true; return false; } /** * Init the thinker lists. * * @params flags 0x1 = Init public thinkers. * 0x2 = Init private (engine-internal) thinkers. */ void P_InitThinkerLists(byte flags) { if(!inited) { numThinkerLists = 0; thinkerLists = NULL; } else { size_t i; for(i = 0; i < numThinkerLists; ++i) { thinkerlist_t* list = thinkerLists[i]; if(list->isPublic && !(flags & 0x1)) continue; if(!list->isPublic && !(flags & 0x2)) continue; initThinkerList(list); } } P_ClearMobjIDs(); inited = true; } boolean P_ThinkerListInited(void) { return inited; } /** * Iterate the list of thinkers making a callback for each. * * @param func If not @c NULL, only make a callback for thinkers * whose function matches this. * @param flags Thinker filter flags. * @param callback The callback to make. Iteration will continue * until a callback returns a zero value. * @param context Is passed to the callback function. */ boolean P_IterateThinkers(think_t func, byte flags, boolean (*callback) (thinker_t*, void*), void* context) { if(!inited) return true; if(func) { // We might have both public and shared lists for this func. boolean result = true; if(flags & 0x1) result = iterateThinkers(listForThinkFunc(func, true, false), callback, context); if(result && (flags & 0x2)) result = iterateThinkers(listForThinkFunc(func, false, false), callback, context); return result; } { boolean result = true; size_t i; for(i = 0; i < numThinkerLists; ++i) { thinkerlist_t* list = thinkerLists[i]; if(list->isPublic && !(flags & 0x1)) continue; if(!list->isPublic && !(flags & 0x2)) continue; if((result = iterateThinkers(list, callback, context)) == 0) break; } return result; } } /** * Part of the Doomsday public API. */ void DD_InitThinkers(void) { P_InitThinkerLists(0x1); // Init the public thinker lists. } /** * Part of the Doomsday public API. */ void DD_RunThinkers(void) { P_IterateThinkers(NULL, 0x1 | 0x2, runThinker, NULL); } /** * Adds a new thinker to the thinker lists. * Part of the Doomsday public API. */ void DD_ThinkerAdd(thinker_t* th) { P_ThinkerAdd(th, true); // This is a public thinker. } /** * Removes a thinker from the thinker lists. * Part of the Doomsday public API. */ void DD_ThinkerRemove(thinker_t* th) { P_ThinkerRemove(th); } /** * Change the 'in stasis' state of a thinker (stop it from thinking). * * @param th The thinker to change. * @param on @c true, put into stasis. */ void DD_ThinkerSetStasis(thinker_t* th, boolean on) { if(th) { th->inStasis = on; } } /** * Part of the Doomsday public API. */ boolean DD_IterateThinkers(think_t func, boolean (*callback) (thinker_t*, void*), void* context) { return P_IterateThinkers(func, 0x1, callback, context); } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/r_util.c0000644000175000017500000003212111357170242022372 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_util.c: Refresh Utility Routines */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_refresh.h" #include "de_play.h" #include "p_dmu.h" // MACROS ------------------------------------------------------------------ #define SLOPERANGE 2048 #define SLOPEBITS 11 #define DBITS (FRACBITS-SLOPEBITS) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int tantoangle[SLOPERANGE + 1]; // get from tables.c // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Which side of the partition does the point lie? * * @param x X coordinate to test. * @param y Y coordinate to test. * @return int @c 0 = front, else @c 1 = back. */ int R_PointOnSide(const float x, const float y, const partition_t *par) { float dx, dy; float left, right; if(!par->dX) { if(x <= par->x) return (par->dY > 0? 1:0); else return (par->dY < 0? 1:0); } if(!par->dY) { if(y <= par->y) return (par->dX < 0? 1:0); else return (par->dX > 0? 1:0); } dx = (x - par->x); dy = (y - par->y); // Try to quickly decide by looking at the signs. if(par->dX < 0) { if(par->dY < 0) { if(dx < 0) { if(dy >= 0) return 0; } else if(dy < 0) return 1; } else { if(dx < 0) { if(dy < 0) return 1; } else if(dy >= 0) return 0; } } else { if(par->dY < 0) { if(dx < 0) { if(dy < 0) return 0; } else if(dy >= 0) return 1; } else { if(dx < 0) { if(dy >= 0) return 1; } else if(dy < 0) return 0; } } left = par->dY * dx; right = dy * par->dX; if(right < left) return 0; // front side else return 1; // back side } int R_SlopeDiv(unsigned num, unsigned den) { unsigned int ans; if(den < 512) return SLOPERANGE; ans = (num << 3) / (den >> 8); return ans <= SLOPERANGE ? ans : SLOPERANGE; } static angle_t pointToAngle(float x, float y) { fixed_t pos[2]; if(x == 0 && y == 0) return 0; pos[VX] = FLT2FIX(x); pos[VY] = FLT2FIX(y); if(pos[VX] >= 0) { // x >=0 if(pos[VY] >= 0) { // y>= 0 if(pos[VX] > pos[VY]) return tantoangle[R_SlopeDiv(pos[VY], pos[VX])]; // octant 0 return ANG90 - 1 - tantoangle[R_SlopeDiv(pos[VX], pos[VY])]; // octant 1 } // y<0 pos[VY] = -pos[VY]; if(pos[VX] > pos[VY]) return -tantoangle[R_SlopeDiv(pos[VY], pos[VX])]; // octant 8 return ANG270 + tantoangle[R_SlopeDiv(pos[VX], pos[VY])]; // octant 7 } // x<0 pos[VX] = -pos[VX]; if(pos[VY] >= 0) { // y>= 0 if(pos[VX] > pos[VY]) return ANG180 - 1 - tantoangle[R_SlopeDiv(pos[VY], pos[VX])]; // octant 3 return ANG90 + tantoangle[R_SlopeDiv(pos[VX], pos[VY])]; // octant 2 } // y<0 pos[VY] = -pos[VY]; if(pos[VX] > pos[VY]) return ANG180 + tantoangle[R_SlopeDiv(pos[VY], pos[VX])]; // octant 4 return ANG270 - 1 - tantoangle[R_SlopeDiv(pos[VX], pos[VY])]; // octant 5 } /** * To get a global angle from cartesian coordinates, the coordinates are * flipped until they are in the first octant of the coordinate system, then * the y (<=x) is scaled and divided by x to get a tangent (slope) value * which is looked up in the tantoangle[] table. The +1 size is to handle * the case when x==y without additional checking. * * @param x X coordinate to test. * @param y Y coordinate to test. * * @return angle_t Angle between the test point and viewX,y. */ angle_t R_PointToAngle(float x, float y) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); x -= viewData->current.pos[VX]; y -= viewData->current.pos[VY]; return pointToAngle(x, y); } angle_t R_PointToAngle2(float x1, float y1, float x2, float y2) { x2 -= x1; y2 -= y1; return pointToAngle(x2, y2); } float R_PointToDist(const float x, const float y) { const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); float dx, dy, temp, dist; uint angle; dx = fabs(x - viewData->current.pos[VX]); dy = fabs(y - viewData->current.pos[VY]); if(dy > dx) { temp = dx; dx = dy; dy = temp; } angle = (tantoangle[FLT2FIX(dy / dx) >> DBITS] + ANG90) >> ANGLETOFINESHIFT; dist = dx / FIX2FLT(finesine[angle]); // Use as cosine return dist; } subsector_t *R_PointInSubsector(const float x, const float y) { node_t *node = 0; uint nodenum = 0; if(!numNodes) // single subsector is a special case return (subsector_t *) ssectors; nodenum = numNodes - 1; while(!(nodenum & NF_SUBSECTOR)) { node = NODE_PTR(nodenum); ASSERT_DMU_TYPE(node, DMU_NODE); nodenum = node->children[R_PointOnSide(x, y, &node->partition)]; } return SUBSECTOR_PTR(nodenum & ~NF_SUBSECTOR); } linedef_t *R_GetLineForSide(const uint sideNumber) { uint i; sidedef_t *side = SIDE_PTR(sideNumber); sector_t *sector = side->sector; // All sides may not have a sector. if(!sector) return NULL; for(i = 0; i < sector->lineDefCount; ++i) if(sector->lineDefs[i]->L_frontside == side || sector->lineDefs[i]->L_backside == side) { return sector->lineDefs[i]; } return NULL; } /** * Is the point inside the sector, according to the edge lines of the * subsector. Uses the well-known algorithm described here: * http://www.alienryderflex.com/polygon/ * * @param X coordinate to test. * @param Y coordinate to test. * @param Sector to test. * * @return @c true, if the point is inside the sector. */ boolean R_IsPointInSector(const float x, const float y, const sector_t *sector) { uint i; boolean isOdd = false; for(i = 0; i < sector->lineDefCount; ++i) { linedef_t *line = sector->lineDefs[i]; vertex_t *vtx[2]; // Skip lines that aren't sector boundaries. if(line->L_frontside && line->L_backside && line->L_frontsector == sector && line->L_backsector == sector) continue; vtx[0] = line->L_v1; vtx[1] = line->L_v2; // It shouldn't matter whether the line faces inward or outward. if((vtx[0]->V_pos[VY] < y && vtx[1]->V_pos[VY] >= y) || (vtx[1]->V_pos[VY] < y && vtx[0]->V_pos[VY] >= y)) { if(vtx[0]->V_pos[VX] + (((y - vtx[0]->V_pos[VY]) / (vtx[1]->V_pos[VY] - vtx[0]->V_pos[VY])) * (vtx[1]->V_pos[VX] - vtx[0]->V_pos[VX])) < x) { // Toggle oddness. isOdd = !isOdd; } } } // The point is inside if the number of crossed nodes is odd. return isOdd; } /** * Is the point inside the subsector, according to the edge lines of the * subsector. Uses the well-known algorithm described here: * http://www.alienryderflex.com/polygon/ * * @param x X coordinate to test. * @param y Y coordinate to test. * @param ssec Subsector to test. * * @return @c true, if the point is inside the subsector. */ boolean R_IsPointInSubsector(const float x, const float y, const subsector_t* ssec) { uint i; fvertex_t* vi, *vj; for(i = 0; i < ssec->segCount; ++i) { vi = &ssec->segs[i]->SG_v1->v; vj = &ssec->segs[(i + 1) % ssec->segCount]->SG_v1->v; if(((vi->pos[VY] - y) * (vj->pos[VX] - vi->pos[VX]) - (vi->pos[VX] - x) * (vj->pos[VY] - vi->pos[VY])) < 0) { // Outside the subsector's edges. return false; } /* if((vi->pos[VY] < y && vj->pos[VY] >= y) || (vj->pos[VY] < y && vi->pos[VY] >= y)) { if(vi->pos[VX] + (((y - vi->pos[VY])/(vj->pos[VY] - vi->pos[VY])) * (vj->pos[VX] - vi->pos[VX])) < x) { // Toggle oddness. isOdd = !isOdd; } } */ } return true; } /** * Is the point inside the sector, according to the edge lines of the * subsector. * * More accurate than R_IsPointInSector. * * @param X coordinate to test. * @param Y coordinate to test. * @param Sector to test. * * @return @c true, if the point is inside the sector. */ boolean R_IsPointInSector2(const float x, const float y, const sector_t* sector) { subsector_t* ssec = R_PointInSubsector(x, y); if(ssec->sector != sector) { // Wrong sector. return false; } return R_IsPointInSubsector(x, y, ssec); } void R_ScaleAmbientRGB(float *out, const float *in, float mul) { int i; float val; if(mul < 0) mul = 0; else if(mul > 1) mul = 1; for(i = 0; i < 3; ++i) { val = in[i] * mul; if(out[i] < val) out[i] = val; } } /** * Conversion from HSV to RGB. Everything is [0,1]. */ void R_HSVToRGB(float* rgb, float h, float s, float v) { int i; float f, p, q, t; if(!rgb) return; if(s == 0) { // achromatic (grey) rgb[0] = rgb[1] = rgb[2] = v; return; } if(h >= 1) h -= 1; h *= 6; // sector 0 to 5 i = floor(h); f = h - i; // factorial part of h p = v * (1 - s); q = v * (1 - s * f); t = v * (1 - s * (1 - f)); switch(i) { case 0: rgb[0] = v; rgb[1] = t; rgb[2] = p; break; case 1: rgb[0] = q; rgb[1] = v; rgb[2] = p; break; case 2: rgb[0] = p; rgb[1] = v; rgb[2] = t; break; case 3: rgb[0] = p; rgb[1] = q; rgb[2] = v; break; case 4: rgb[0] = t; rgb[1] = p; rgb[2] = v; break; default: rgb[0] = v; rgb[1] = p; rgb[2] = q; break; } } /** * Returns a ptr to the sector which owns the given ddmobj_base_t. * * @param ddMobjBase ddmobj_base_t to search for. * * @return Ptr to the Sector where the ddmobj_base_t resides, * else @c NULL. */ sector_t* R_GetSectorForOrigin(const void* ddMobjBase) { uint i, k; sector_t* sec; // Check all sectors; find where the sound is coming from. for(i = 0; i < numSectors; ++i) { sec = SECTOR_PTR(i); if(ddMobjBase == &sec->soundOrg) return sec; else { // Check the planes of this sector for(k = 0; k < sec->planeCount; ++k) if(ddMobjBase == &sec->planes[k]->soundOrg) { return sec; } } } return NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/gl_tga.c0000644000175000017500000003704211357170242022340 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_tga.c: TGA file format (TARGA) reader/writer. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "de_base.h" #include "de_system.h" #include "de_graphics.h" // MACROS ------------------------------------------------------------------ #undef SHORT #ifdef __BIG_ENDIAN__ #define SHORT(x) shortSwap(x) # else // Little-endian. #define SHORT(x) (x) #endif // TYPES ------------------------------------------------------------------- typedef unsigned char uchar; // 1 byte typedef struct { uchar idLength; // Identification field size in bytes. uchar colorMapType; // Type of the color map. uchar imageType; // Image type code. } tga_header_t; // Color map specification. typedef struct { int16_t index; // Index of first color map entry. int16_t length; // Number of color map entries. uchar entrySize; // Number of bits in a color map entry (16/24/32). } tga_colormapspec_t; // Image specification flags: #define ISF_SCREEN_ORIGIN_UPPER 0x1 // Upper left-hand corner screen origin. // Data interleaving: #define ISF_INTERLEAVE_TWOWAY 0x2 // Two-way (even/odd) interleaving. #define ISF_INTERLEAVE_FOURWAY 0x4 // Four-way interleaving. // Image specification. typedef struct { uchar flags; int16_t xOrigin; // X coordinate of lower left corner. int16_t yOrigin; // Y coordinate of lower left corner. int16_t width; // Width of the image in pixels. int16_t height; // Height of the image in pixels. uchar pixelDepth; // Number of bits in a pixel (16/24/32). uchar attributeBits; } tga_imagespec_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- #ifdef __BIG_ENDIAN__ static int16_t shortSwap(int16_t n) { return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); } #endif static void writeByte(FILE* f, uchar b) { fwrite(&b, 1, 1, f); } static void writeShort(FILE* f, int16_t s) { int16_t v = SHORT(s); fwrite(&v, sizeof(v), 1, f); } static uchar readByte(DFILE* f) { uchar v; F_Read(&v, 1, f); return v; } static int16_t readShort(DFILE* f) { int16_t v; F_Read(&v, sizeof(v), f); return SHORT(v); } /** * @param idLength Identification field size in bytes (max 255). * @c 0 indicates no identification field. * @param colorMapType Type of the color map, @c 0 or @c 1: * @c 0 = color map data is not present. * @c 1 = color map data IS present. * @param imageType Image data type code, one of: * @c 0 = no image data is present. * @c 1 = uncompressed, color mapped image. * @c 2 = uncompressed, true-color image. * @c 3 = uncompressed, grayscale image. * @c 9 = run-length encoded, color mapped image. * @c 10 = run-length encoded, true-color image. * @c 11 = run-length encoded, grayscale image. * @param file Handle to the file to be written to. */ static void writeHeader(uchar idLength, uchar colorMapType, uchar imageType, FILE* file) { writeByte(file, idLength); writeByte(file, colorMapType? 1 : 0); writeByte(file, imageType); } static void readHeader(tga_header_t* dst, DFILE* file) { dst->idLength = readByte(file); dst->colorMapType = readByte(file); dst->imageType = readByte(file); } /** * @param index Index of first color map entry. * @param length Total number of color map entries. * @param entrySize Number of bits in a color map entry; 15/16/24/32. * @param file Handle to the file to be written to. */ static void writeColorMapSpec(int16_t index, int16_t length, uchar entrySize, FILE* file) { writeShort(file, index); writeShort(file, length); writeByte(file, entrySize); } static void readColorMapSpec(tga_colormapspec_t* dst, DFILE* file) { dst->index = readShort(file); dst->length = readShort(file); dst->entrySize = readByte(file); } /** * @param xOrigin X coordinate of lower left corner. * @param yOrigin Y coordinate of lower left corner. * @param width Width of the image in pixels. * @param height Height of the image in pixels. * @param pixDepth Number of bits per pixel, one of; 16/24/32. * @param file Handle to the file to be written to. */ static void writeImageSpec(int16_t xOrigin, int16_t yOrigin, int16_t width, int16_t height, uchar pixDepth, FILE* file) { writeShort(file, xOrigin); writeShort(file, yOrigin); writeShort(file, width); writeShort(file, height); writeByte(file, pixDepth); /** * attributeBits:4; // Attribute bits associated with each pixel. * reserved:1; // A reserved bit; must be 0. * screenOrigin:1; // Location of screen origin; must be 0. * dataInterleave:2; // TGA_INTERLEAVE_* */ writeByte(file, 0); } static void readImageSpec(tga_imagespec_t* dst, DFILE* file) { uchar bits; dst->xOrigin = readShort(file); dst->yOrigin = readShort(file); dst->width = readShort(file); dst->height = readShort(file); dst->pixelDepth = readByte(file); bits = readByte(file); /** * attributeBits:4; // Attribute bits associated with each pixel. * reserved:1; // A reserved bit; must be 0. * screenOrigin:1; // Location of screen origin; must be 0. * dataInterleave:2; // TGA_INTERLEAVE_* */ dst->flags = 0 | ((bits & 6)? ISF_SCREEN_ORIGIN_UPPER : 0) | ((bits & 7)? ISF_INTERLEAVE_TWOWAY : (bits & 8)? ISF_INTERLEAVE_FOURWAY : 0); dst->attributeBits = (bits & 0xf); } /** * Saves the buffer (which is formatted rgb565) to a Targa 24 image file. * * @param filename Path to the file to be written to (need not exist). * @param w Width of the image in pixels. * @param h Height of the image in pixels. * @param buf Ptr to the image data to be written. * * @return Non-zero iff successful. */ int TGA_Save24_rgb565(const char* filename, int w, int h, const uint16_t* buf) { int i, k; FILE* file; uchar* outBuf; size_t outBufStart; if(!buf || !(w > 0 && h > 0)) return 0; if((file = fopen(filename, "wb")) == NULL) return 0; // No identification field, no color map, Targa type 2 (unmapped RGB). writeHeader(0, 0, 2, file); writeColorMapSpec(0, 0, 0, file); writeImageSpec(0, 0, w, h, 24, file); /** * Convert the buffer: * From RRRRRGGGGGGBBBBB > ARRRRRGGGGGBBBBB * * \note Alpha will always be @c 0. */ outBuf = malloc(w * h * 3); outBufStart = w * h - 1; // From the end. for(k = 0; k < h; ++k) for(i = 0; i < w; ++i) { int16_t r, g, b; const int16_t src = buf[k * w + i]; uchar* dst = &outBuf[outBufStart - (((k + 1) * w - 1 - i)) * 3]; r = (src >> 11) & 0x1f; // The last 5 bits. g = (src >> 5) & 0x3f; // The middle 6 bits (one bit'll be lost). b = src & 0x1f; // The first 5 bits. dst[2] = b << 3; dst[0] = g << 2; dst[1] = r << 3; } // Write the converted buffer (bytes may go the wrong way around...!). fwrite(outBuf, w * h * 3, 1, file); free(outBuf); fclose(file); return 1; // Success. } /** * Save the rgb888 buffer as Targa 24. * * @param filename Path to the file to be written to (need not exist). * @param w Width of the image in pixels. * @param h Height of the image in pixels. * @param buf Ptr to the image data to be written. * * @return Non-zero iff successful. */ int TGA_Save24_rgb888(const char* filename, int w, int h, const byte* buf) { int i; FILE* file; uchar* outBuf; if(!buf || !(w > 0 && h > 0)) return 0; if((file = fopen(filename, "wb")) == NULL) return 0; // Huh? // No identification field, no color map, Targa type 2 (unmapped RGB). writeHeader(0, 0, 2, file); writeColorMapSpec(0, 0, 0, file); writeImageSpec(0, 0, w, h, 24, file); // The save format is BRG. outBuf = malloc(w * h * 3); for(i = 0; i < w * h; ++i) { const uchar* src = &buf[i * 3]; uchar* dst = &outBuf[i * 3]; dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0]; } fwrite(outBuf, w * h * 3, 1, file); free(outBuf); fclose(file); return 1; // Success. } /** * Save the rgb8888 buffer as Targa 24. * * @param filename Path to the file to be written to (need not exist). * @param w Width of the image in pixels. * @param h Height of the image in pixels. * @param buf Ptr to the image data to be written. * * @return Non-zero iff successful. */ int TGA_Save24_rgba8888(const char* filename, int w, int h, const byte* buf) { int i; FILE* file; uchar* outBuf; if(!buf || !(w > 0 && h > 0)) return 0; if((file = fopen(filename, "wb")) == NULL) return 0; // Huh? // No identification field, no color map, Targa type 2 (unmapped RGB). writeHeader(0, 0, 2, file); writeColorMapSpec(0, 0, 0, file); writeImageSpec(0, 0, w, h, 24, file); // The save format is BGR. outBuf = malloc(w * h * 3); for(i = 0; i < w * h; ++i) { const byte* src = &buf[i * 4]; uchar* dst = &outBuf[i * 3]; dst[0] = src[2]; dst[1] = src[1]; dst[2] = src[0]; } fwrite(outBuf, w * h * 3, 1, file); free(outBuf); fclose(file); return 1; // Success. } /** * Save the rgb888 buffer as Targa 16. * * @param filename Path to the file to be written to (need not exist). * @param w Width of the image in pixels. * @param h Height of the image in pixels. * @param buf Ptr to the image data to be written. * * @return Non-zero iff successful. */ int TGA_Save16_rgb888(const char* filename, int w, int h, const byte* buf) { int i; FILE* file; int16_t* outBuf; if(!buf || !(w > 0 && h > 0)) return 0; if((file = fopen(filename, "wb")) == NULL) return 0; // Huh? // No identification field, no color map, Targa type 2 (unmapped RGB). writeHeader(0, 0, 2, file); writeColorMapSpec(0, 0, 0, file); writeImageSpec(0, 0, w, h, 16, file); // The destination format is _RRRRRGG GGGBBBBB. outBuf = malloc(w * h * 2); for(i = 0; i < w * h; ++i) { const uchar* src = &buf[i * 3]; int16_t* dst = &outBuf[i]; *dst = (src[2] >> 3) + ((src[1] & 0xf8) << 2) + ((src[0] & 0xf8) << 7); } fwrite(outBuf, w * h * 2, 1, file); free(outBuf); fclose(file); return 1; // Success. } /** * Loads a 24-bit or a 32-bit TGA image (24-bit color + 8-bit alpha). * * \warning: This is not a generic TGA loader. Only type 2, 24/32 pixel * size, attrbits 0/8 and lower left origin supported. * * @param buf Caller allocated memory for 'buffer', MUST be at * least 4 * w * h! * * @return Non-zero iff the image is loaded successfully. */ int TGA_Load32_rgba8888(DFILE* file, int w, int h, byte* buf) { int x, y, pixbytes, format; tga_header_t header; tga_colormapspec_t colorMapSpec; tga_imagespec_t imageSpec; uchar* srcBuf; const uchar* src; // Read and check the header. readHeader(&header, file); readColorMapSpec(&colorMapSpec, file); readImageSpec(&imageSpec, file); if(header.imageType != 2 || (imageSpec.pixelDepth != 32 && imageSpec.pixelDepth != 24) || (imageSpec.attributeBits != 8 && imageSpec.attributeBits != 0) || (imageSpec.flags & ISF_SCREEN_ORIGIN_UPPER)) { // May or may not get displayed... Con_Message("TGA_Load32_rgba8888: I don't know this format!\n"); Con_Message(" (type=%i pxsize=%i abits=%i)\n", header.imageType, imageSpec.pixelDepth, imageSpec.attributeBits); return TGA_FALSE; } VERBOSE( Con_Message("(TGA: type=%i pxsize=%i abits=%i)\n", header.imageType, imageSpec.pixelDepth, imageSpec.attributeBits)); // Determine format. if(imageSpec.pixelDepth == 24) { format = TGA_TARGA24; pixbytes = 3; } else { format = TGA_TARGA32; pixbytes = 4; } // Read the pixel data. srcBuf = malloc(w * h * pixbytes); F_Read(srcBuf, w * h * pixbytes, file); // "Unpack" the pixels (origin in the lower left corner). // TGA pixels are in BGRA format. src = srcBuf; for(y = h - 1; y >= 0; y--) for(x = 0; x < w; x++) { byte* dst = &buf[(y * w + x) * pixbytes]; dst[2] = *src++; dst[1] = *src++; dst[0] = *src++; if(pixbytes == 4) dst[3] = *src++; } free(srcBuf); // Success! return format; } /** * @return @c true, iff a file was found and then read. */ int TGA_GetSize(const char* filename, int* w, int *h) { tga_header_t header; tga_colormapspec_t colorMapSpec; tga_imagespec_t imageSpec; DFILE* file = F_Open(filename, "rb"); if(!file || !w || !h) return 0; readHeader(&header, file); readColorMapSpec(&colorMapSpec, file); readImageSpec(&imageSpec, file); F_Close(file); if(w) *w = imageSpec.width; if(h) *h = imageSpec.height; return 1; // Success. } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/src/rend_halo.c0000644000175000017500000003407311357170242023037 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_halo.c: Halos and Flares */ // HEADER FILES ------------------------------------------------------------ #include #include "de_base.h" #include "de_console.h" #include "de_render.h" #include "de_refresh.h" #include "de_play.h" #include "de_graphics.h" #include "de_misc.h" // MACROS ------------------------------------------------------------------ #define NUM_FLARES 5 // TYPES ------------------------------------------------------------------- typedef struct flare_s { float offset; float size; float alpha; int texture; // 0=round, 1=flare, 2=brflare, 3=bigflare } flare_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- D_CMD(FlareConfig); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int haloMode = 5, haloBright = 35, haloSize = 50; int haloRealistic = true; int haloOccludeSpeed = 48; float haloZMagDiv = 100, haloMinRadius = 20; float haloDimStart = 10, haloDimEnd = 100; float haloFadeMax = 0, haloFadeMin = 0, minHaloSize = 1; flare_t flares[NUM_FLARES] = { {0, 1, 1, 0}, // Primary flare. {1, .41f, .5f, 0}, // Main secondary flare. {1.5f, .29f, .333f, 1}, {-.6f, .24f, .333f, 0}, {.4f, .29f, .25f, 0} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void H_Register(void) { cvar_t cvars[] = { {"rend-halo", 0, CVT_INT, &haloMode, 0, 5}, {"rend-halo-realistic", 0, CVT_INT, &haloRealistic, 0, 1}, {"rend-halo-bright", 0, CVT_INT, &haloBright, 0, 100}, {"rend-halo-occlusion", CVF_NO_MAX, CVT_INT, &haloOccludeSpeed, 0, 0}, {"rend-halo-size", 0, CVT_INT, &haloSize, 0, 100}, {"rend-halo-secondary-limit", CVF_NO_MAX, CVT_FLOAT, &minHaloSize, 0, 0}, {"rend-halo-fade-far", CVF_NO_MAX, CVT_FLOAT, &haloFadeMax, 0, 0}, {"rend-halo-fade-near", CVF_NO_MAX, CVT_FLOAT, &haloFadeMin, 0, 0}, {"rend-halo-zmag-div", CVF_NO_MAX, CVT_FLOAT, &haloZMagDiv, 1, 1}, {"rend-halo-radius-min", CVF_NO_MAX, CVT_FLOAT, &haloMinRadius, 0, 0}, {"rend-halo-dim-near", CVF_NO_MAX, CVT_FLOAT, &haloDimStart, 0, 0}, {"rend-halo-dim-far", CVF_NO_MAX, CVT_FLOAT, &haloDimEnd, 0, 0}, {NULL} }; Con_AddVariableList(cvars); C_CMD_FLAGS("flareconfig", NULL, FlareConfig, CMDF_NO_DEDICATED); } void H_SetupState(boolean dosetup) { if(dosetup) { glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); GL_BlendMode(BM_ADD); } else { glDepthMask(GL_TRUE); glEnable(GL_DEPTH_TEST); GL_BlendMode(BM_NORMAL); } } /** * The caller must check that @c sourcevis, really has a ->light! * * @param x X coordinate of the center of the halo. * @param y Y coordinate of the center of the halo. * @param z Z coordinate of the center of the halo. * @param primary @c true = we'll draw the primary halo, otherwise the * secondary ones (which won't be clipped or occluded * by anything; they're drawn after everything else, * during a separate pass). * @c false = the caller must setup the rendering state. * * @return @c true, if a halo was rendered. */ boolean H_RenderHalo(float x, float y, float z, float size, DGLuint tex, const float color[3], float distanceToViewer, float occlusionFactor, float brightnessFactor, float viewXOffset, boolean primary, boolean viewRelativeRotate) { int i, k; float viewPos[3]; float viewToCenter[3], mirror[3], normalViewToCenter[3]; float leftOff[3], rightOff[3], center[3], radius; float haloPos[3]; float rgba[4], radX, radY, scale, turnAngle = 0; float fadeFactor = 1, secBold, secDimFactor; float colorAverage, f, distanceDim; flare_t* fl; const viewdata_t* viewData = R_ViewData(viewPlayer - ddPlayers); // In realistic mode we don't render secondary halos. if(!primary && haloRealistic) return false; if(distanceToViewer <= 0 || occlusionFactor == 0 || (haloFadeMax && distanceToViewer > haloFadeMax)) return false; occlusionFactor = (1 + occlusionFactor) / 2; if(haloFadeMax && haloFadeMax != haloFadeMin && distanceToViewer < haloFadeMax && distanceToViewer >= haloFadeMin) { fadeFactor = (distanceToViewer - haloFadeMin) / (haloFadeMax - haloFadeMin); } // viewSideVec is to the left. for(i = 0; i < 3; ++i) { leftOff[i] = viewData->upVec[i] + viewData->sideVec[i]; rightOff[i] = viewData->upVec[i] - viewData->sideVec[i]; } rgba[CR] = color[CR]; rgba[CG] = color[CG]; rgba[CB] = color[CB]; rgba[CA] = 1; // Real alpha is set later. // Setup the proper DGL state. if(primary) H_SetupState(true); center[VX] = x; center[VZ] = y; center[VY] = z; // Apply the flare's X offset. (Positive is to the right.) for(i = 0; i < 3; i++) center[i] -= viewXOffset * viewData->sideVec[i]; // Calculate the mirrored position. // Project viewtocenter vector onto viewSideVec. viewPos[VX] = vx; viewPos[VY] = vy; viewPos[VZ] = vz; for(i = 0; i < 3; i++) normalViewToCenter[i] = viewToCenter[i] = center[i] - viewPos[i]; // Calculate the dimming factor for secondary flares. M_Normalize(normalViewToCenter); secDimFactor = M_DotProduct(normalViewToCenter, viewData->frontVec); scale = M_DotProduct(viewToCenter, viewData->frontVec) / M_DotProduct(viewData->frontVec, viewData->frontVec); for(i = 0; i < 3; i++) haloPos[i] = mirror[i] = (viewData->frontVec[i] * scale - viewToCenter[i]) * 2; // Now adding 'mirror' to a position will mirror it. // Calculate texture turn angle. if(M_Normalize(haloPos)) { // Now halopos is a normalized version of the mirror vector. // Both vectors are on the view plane. if(viewRelativeRotate) { turnAngle = M_DotProduct(haloPos, viewData->upVec); if(turnAngle > 1) turnAngle = 1; else if(turnAngle < -1) turnAngle = -1; if(turnAngle >= 1) turnAngle = 0; else if(turnAngle <= -1) turnAngle = (float) PI; else turnAngle = acos(turnAngle); // On which side of the up vector (left or right)? if(M_DotProduct(haloPos, viewData->sideVec) < 0) turnAngle = -turnAngle; } else { turnAngle = 0; } } // Radius is affected by the precalculated 'flaresize' and the // distance to the source. // Prepare the texture rotation matrix. glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); // Rotate around the center of the texture. glTranslatef(0.5f, 0.5f, 0); glRotatef(turnAngle / PI * 180, 0, 0, 1); glTranslatef(-0.5f, -0.5f, 0); // The overall brightness of the flare. colorAverage = (rgba[CR] + rgba[CG] + rgba[CB] + 1) / 4; // Small flares have stronger dimming. f = distanceToViewer / size; if(haloDimStart && haloDimStart < haloDimEnd && f > haloDimStart) distanceDim = 1 - (f - haloDimStart) / (haloDimEnd - haloDimStart); else distanceDim = 1; for(i = 0, fl = flares; i < haloMode && i < NUM_FLARES; i++, fl++) { if(primary && i) break; if(!primary && !i) continue; f = 1; if(i) { // Secondary flare dimming? f = minHaloSize * size / distanceToViewer; if(f > 1) f = 1; } f *= distanceDim * brightnessFactor; // The rgba & alpha of the flare. rgba[CA] = f * (fl->alpha * occlusionFactor * fadeFactor + colorAverage * colorAverage / 5); radius = size * (1 - colorAverage / 3) + distanceToViewer / haloZMagDiv; if(radius < haloMinRadius) radius = haloMinRadius; radius *= occlusionFactor; secBold = colorAverage - 8 * (1 - secDimFactor); rgba[CA] *= .8f * haloBright / 100.0f; if(i) { rgba[CA] *= secBold; // Secondary flare boldness. } if(rgba[CA] <= 0) break; // Not visible. // In the realistic mode, halos are slightly dimmer. if(haloRealistic) { rgba[CA] *= .6f; } if(haloRealistic) { // The 'realistic' halos just use the blurry round // texture unless custom. if(!tex) tex = GL_PrepareSysFlareTexture(FXT_ROUND); } else { if(!(primary && tex)) { if(size > 45 || (colorAverage > .90 && size > 20)) { // The "Very Bright" condition. radius *= .65f; if(!i) tex = GL_PrepareSysFlareTexture(FXT_BIGFLARE); else tex = GL_PrepareSysFlareTexture(fl->texture); } else { if(!i) tex = GL_PrepareSysFlareTexture(FXT_ROUND); else tex = GL_PrepareSysFlareTexture(fl->texture); } } } // In the realistic mode, halos are slightly smaller. if(haloRealistic) { radius *= 0.8f; } // The final radius. radX = radius * fl->size; radY = radX / 1.2f; // Determine the final position of the halo. haloPos[VX] = center[VX]; haloPos[VY] = center[VY]; haloPos[VZ] = center[VZ]; if(i) { // Secondary halos. // Mirror it according to the flare table. for(k = 0; k < 3; ++k) haloPos[k] += mirror[k] * fl->offset; } if(renderTextures) GL_BindTexture(tex, GL_LINEAR); else glBindTexture(GL_TEXTURE_2D, 0); // Don't wrap the texture. Evidently some drivers can't just // take a hint... (or then something's changing the wrapping // mode inadvertently) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glColor4fv(rgba); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex3f(haloPos[VX] + radX * leftOff[VX], haloPos[VY] + radY * leftOff[VY], haloPos[VZ] + radX * leftOff[VZ]); glTexCoord2f(1, 0); glVertex3f(haloPos[VX] + radX * rightOff[VX], haloPos[VY] + radY * rightOff[VY], haloPos[VZ] + radX * rightOff[VZ]); glTexCoord2f(1, 1); glVertex3f(haloPos[VX] - radX * leftOff[VX], haloPos[VY] - radY * leftOff[VY], haloPos[VZ] - radX * leftOff[VZ]); glTexCoord2f(0, 1); glVertex3f(haloPos[VX] - radX * rightOff[VX], haloPos[VY] - radY * rightOff[VY], haloPos[VZ] - radX * rightOff[VZ]); glEnd(); } glMatrixMode(GL_TEXTURE); glPopMatrix(); // Undo the changes to the DGL state. if(primary) H_SetupState(false); return true; } /** * flareconfig list * flareconfig (num) pos/size/alpha/tex (val) */ D_CMD(FlareConfig) { int i; float val; if(argc == 2) { if(!stricmp(argv[1], "list")) { for(i = 0; i < NUM_FLARES; ++i) { Con_Message("%i: pos:%f s:%.2f a:%.2f tex:%i\n", i, flares[i].offset, flares[i].size, flares[i].alpha, flares[i].texture); } } } else if(argc == 4) { i = atoi(argv[1]); val = strtod(argv[3], NULL); if(i < 0 || i >= NUM_FLARES) return false; if(!stricmp(argv[2], "pos")) { flares[i].offset = val; } else if(!stricmp(argv[2], "size")) { flares[i].size = val; } else if(!stricmp(argv[2], "alpha")) { flares[i].alpha = val; } else if(!stricmp(argv[2], "tex")) { flares[i].texture = (int) val; } } else { Con_Printf("Usage:\n"); Con_Printf(" %s list\n", argv[0]); Con_Printf(" %s (num) pos/size/alpha/tex (val)\n", argv[0]); } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/0000755000175000017500000000000011523516205021563 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_object.h0000644000175000017500000000526011357170241023525 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_object.h: Map Objects */ #ifndef __DOOMSDAY_MOBJ_H__ #define __DOOMSDAY_MOBJ_H__ #include "p_mapdata.h" #if defined(__JDOOM__) || defined(__JHERETIC__) || defined(__JHEXEN__) # error "Attempted to include internal Doomsday p_object.h from a game" #endif // This macro can be used to calculate a mobj-specific 'random' number. #define MOBJ_TO_ID(mo) ( (long)(mo)->thinker.id * 48 + ((unsigned long)(mo)/1000) ) // We'll use the base mobj template directly as our mobj. typedef struct mobj_s { DD_BASE_MOBJ_ELEMENTS()} mobj_t; #define MOBJ_SIZE gx.mobjSize #define DEFAULT_FRICTION FIX2FLT(0xe800) #define NOMOMENTUM_THRESHOLD (0.000001f) extern float tmpFloorZ, tmpCeilingZ; extern mobj_t *blockingMobj; extern boolean dontHitMobjs; #include "cl_def.h" // for clplayerstate_s void P_InitUnusedMobjList(void); mobj_t *P_MobjCreate(think_t function, float x, float y, float z, angle_t angle, float radius, float height, int ddflags); void P_MobjDestroy(mobj_t *mo); void P_MobjRecycle(mobj_t *mo); void P_MobjSetState(mobj_t *mo, int statenum); void P_MobjMovement(mobj_t *mo); void P_MobjMovement2(mobj_t *mo, void *pstate); void P_MobjZMovement(mobj_t *mo); boolean P_TryMoveXYZ(mobj_t *mo, float x, float y, float z); boolean P_StepMove(mobj_t *mo, float dx, float dy, float dz); boolean P_CheckPosXY(mobj_t *mo, float x, float y); boolean P_CheckPosXYZ(mobj_t *mo, float x, float y, float z); boolean P_SectorPlanesChanged(sector_t *sector); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/con_config.h0000644000175000017500000000251111357170241024040 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * con_config.h: Config Files */ #ifndef __DOOMSDAY_CONSOLE_CONFIG_H__ #define __DOOMSDAY_CONSOLE_CONFIG_H__ #include "con_decl.h" boolean Con_ParseCommands(const char* fileName, boolean setdefault); void Con_SaveDefaults(void); boolean Con_WriteState(const char* fileName, const char* bindingsFileName); D_CMD(WriteConsole); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/con_busy.h0000644000175000017500000000370611357170241023564 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_busy.h: Console Busy Mode */ #ifndef __DOOMSDAY_CONSOLE_BUSY_H__ #define __DOOMSDAY_CONSOLE_BUSY_H__ typedef int (C_DECL *busyworkerfunc_t) (void* parm); typedef enum { FIRST_TRANSITIONSTYLE, TS_CROSSFADE = FIRST_TRANSITIONSTYLE, // Basic opacity crossfade. TS_DOOMSMOOTH, // Emulates the DOOM "blood on wall" screen wipe (smoothed). TS_DOOM, // Emulates the DOOM "blood on wall" screen wipe. LAST_TRANSITIONSTYLE = TS_DOOM } transitionstyle_t; extern int rTransition; extern int rTransitionTics; int Con_Busy(int flags, const char* taskName, busyworkerfunc_t worker, void *workerData); boolean Con_IsBusy(void); void Con_BusyWorkerEnd(void); void Con_BusyWorkerError(const char* message); void Con_AcquireScreenshotTexture(void); void Con_ReleaseScreenshotTexture(void); boolean Con_TransitionInProgress(void); void Con_TransitionTicker(timespan_t ticLength); void Con_DrawTransition(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_util.h0000644000175000017500000000412711357170241023237 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_util.h: Refresh Utility Routines */ #ifndef __DOOMSDAY_REFRESH_UTIL_H__ #define __DOOMSDAY_REFRESH_UTIL_H__ int R_PointOnSide(const float x, const float y, const partition_t* par); angle_t R_PointToAngle(float x, float y); angle_t R_PointToAngle2(float x1, float y1, float x2, float y2); float R_PointToDist(const float x, const float y); linedef_t* R_GetLineForSide(const uint sideIDX); subsector_t* R_PointInSubsector(const float x, const float y); boolean R_IsPointInSector(const float x, const float y, const sector_t* sector); boolean R_IsPointInSector2(const float x, const float y, const sector_t* sector); boolean R_IsPointInSubsector(const float x, const float y, const subsector_t* ssec); void R_ScaleAmbientRGB(float* out, const float* in, float mul); void R_HSVToRGB(float* rgb, float h, float s, float v); sector_t* R_GetSectorForOrigin(const void* ddMobjBase); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_master.h0000644000175000017500000000254211357170241024131 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * sys_master.h: Communication with the Master Server * * The master server maintains a list of running public servers. */ #ifndef __DOOMSDAY_SYSTEM_MASTER_H__ #define __DOOMSDAY_SYSTEM_MASTER_H__ #include "dd_share.h" void N_MasterInit(void); void N_MasterShutdown(void); void N_MasterAnnounceServer(boolean isOpen); void N_MasterRequestList(void); int N_MasterGet(int index, serverinfo_t *info); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/bsp_intersection.h0000644000175000017500000000574511357170241025322 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_intersection.h: Segment intersections. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ #ifndef __BSP_INTERSECTION_H__ #define __BSP_INTERSECTION_H__ #include "bsp_edge.h" typedef void* cutlist_t; struct bspartition_s; /** * An "intersection" remembers the vertex that touches a BSP divider * line (especially a new vertex that is created at a twin-edge split). */ typedef struct intersection_s { // Vertex in question. vertex_t* vertex; // How far along the partition line the vertex is. Zero is at the // partition half-edge's start point, positive values move in the same // direction as the partition's direction, and negative values move // in the opposite direction. double alongDist; // True if this intersection was on a self-referencing linedef. boolean selfRef; // Sector on each side of the vertex (along the partition), // or NULL when that direction isn't OPEN. sector_t* before; sector_t* after; } intersection_t; void BSP_InitIntersectionAllocator(void); void BSP_ShutdownIntersectionAllocator(void); intersection_t* BSP_IntersectionCreate(vertex_t* vert, const struct bspartition_s* part, boolean selfRef); void BSP_IntersectionDestroy(intersection_t* cut); #if _DEBUG void BSP_IntersectionPrint(intersection_t* cut); #endif // Cutlist functions: cutlist_t* BSP_CutListCreate(void); void BSP_CutListDestroy(cutlist_t* cutList); void BSP_CutListEmpty(cutlist_t* cutList); void BSP_CutListPrint(cutlist_t* cutList); boolean BSP_CutListInsertIntersection(cutlist_t* cutList, intersection_t* cut); intersection_t* BSP_CutListFindIntersection(cutlist_t* cutList, vertex_t* v); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_bsp.h0000644000175000017500000000216711357170241023177 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_bsp.h: BSP generation. */ #ifndef __DOOMSDAY_BSP__ #define __DOOMSDAY_BSP__ #include "bsp_main.h" #include "bsp_map.h" #include "bsp_node.h" #include "bsp_edge.h" #include "bsp_superblock.h" #include "bsp_intersection.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_zip.h0000644000175000017500000000317111357170241023210 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * dd_zip.h: Zip/Pk3 Files */ #ifndef __DOOMSDAY_ZIP_PACKAGE_H__ #define __DOOMSDAY_ZIP_PACKAGE_H__ #include "sys_file.h" // Zip entry indices are invalidated when a new Zip file is read. typedef uint zipindex_t; void Zip_Init(void); void Zip_Shutdown(void); boolean Zip_Open(const char *fileName, DFILE *prevOpened); zipindex_t Zip_Find(const char *fileName); zipindex_t Zip_Iterate(int (*iterator) (const char*, void*), void *parm); size_t Zip_GetSize(zipindex_t index); size_t Zip_Read(zipindex_t index, void *buffer); uint Zip_GetLastModified(zipindex_t index); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sv_missile.h0000644000175000017500000000256511357170241024122 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_missile.h: Delta Pool Missile Record */ #ifndef __DOOMSDAY_SERVER_POOL_MISSILE_H__ #define __DOOMSDAY_SERVER_POOL_MISSILE_H__ #include "sv_def.h" #include "sv_pool.h" misrecord_t *Sv_MRFind(pool_t *pool, thid_t id); void Sv_MRAdd(pool_t *pool, const mobjdelta_t *delta); int Sv_MRCheck(pool_t *pool, const mobjdelta_t *mobj); void Sv_MRRemove(pool_t *pool, thid_t id); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_model.h0000644000175000017500000001146111357170241023361 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_model.h: 3D Model Resources */ #ifndef __DOOMSDAY_REFRESH_MODEL_H__ #define __DOOMSDAY_REFRESH_MODEL_H__ #include "gl_model.h" #define MAX_FRAME_MODELS DED_MAX_SUB_MODELS // Model frame flags. #define MFF_FULLBRIGHT 0x00000001 #define MFF_SHADOW1 0x00000002 #define MFF_SHADOW2 0x00000004 #define MFF_BRIGHTSHADOW 0x00000008 #define MFF_MOVEMENT_PITCH 0x00000010 // Pitch aligned to movement. #define MFF_SPIN 0x00000020 // Spin around (for bonus items). #define MFF_SKINTRANS 0x00000040 // Color translation -> skins. #define MFF_AUTOSCALE 0x00000080 // Scale to match sprite height. #define MFF_MOVEMENT_YAW 0x00000100 #define MFF_DONT_INTERPOLATE 0x00000200 // Don't interpolate from the frame. #define MFF_BRIGHTSHADOW2 0x00000400 #define MFF_ALIGN_YAW 0x00000800 #define MFF_ALIGN_PITCH 0x00001000 #define MFF_DARKSHADOW 0x00002000 #define MFF_IDSKIN 0x00004000 // Mobj id -> skin in skin range #define MFF_DISABLE_Z_WRITE 0x00008000 #define MFF_NO_DISTANCE_CHECK 0x00010000 #define MFF_SELSKIN 0x00020000 #define MFF_PARTICLE_SUB1 0x00040000 // Sub1 center is particle origin. #define MFF_NO_PARTICLES 0x00080000 // No particles for this object. #define MFF_SHINY_SPECULAR 0x00100000 // Shiny skin rendered as additive. #define MFF_SHINY_LIT 0x00200000 // Shiny skin is not fullbright. #define MFF_IDFRAME 0x00400000 // Mobj id -> frame in frame range #define MFF_IDANGLE 0x00800000 // Mobj id -> static angle offset #define MFF_DIM 0x01000000 // Never fullbright. #define MFF_SUBTRACT 0x02000000 // Subtract blending. #define MFF_REVERSE_SUBTRACT 0x04000000 // Reverse subtract blending. #define MFF_TWO_SIDED 0x08000000 // Disable culling. #define MFF_NO_TEXCOMP 0x10000000 // Never compress skins. #define MFF_WORLD_TIME_ANIM 0x20000000 typedef struct { short model; short frame; char frameRange; int flags; short skin; char skinRange; float offset[3]; byte alpha; uint shinySkin; // Skinname ID (index) } submodeldef_t; #define MODELDEF_ID_MAXLEN 32 typedef struct modeldef_s { char id[MODELDEF_ID_MAXLEN + 1]; state_t* state; // Pointer to the states list (in dd_defns.c). int flags; unsigned int group; int select; short skinTics; float interMark; // [0,1) When is this frame in effect? float interRange[2]; float offset[3]; float resize, scale[3]; float ptcOffset[MAX_FRAME_MODELS][3]; float visualRadius; ded_model_t* def; // Points to next inter-frame, or NULL. struct modeldef_s* interNext; // Points to next selector, or NULL (only for "base" modeldefs). struct modeldef_s* selectNext; // Submodels. submodeldef_t sub[MAX_FRAME_MODELS]; } modeldef_t; extern modeldef_t *modefs; extern int numModelDefs; extern byte useModels; extern float rModelAspectMod; void R_InitModels(void); void R_ShutdownModels(void); float R_CheckModelFor(struct mobj_s* mo, modeldef_t** mdef, modeldef_t** nextmdef); modeldef_t* R_CheckIDModelFor(const char* id); int R_ModelFrameNumForName(int modelnum, char* fname); void R_SetModelFrame(modeldef_t* modef, int frame); void R_SetSpriteReplacement(int sprite, char* modelname); void R_PrecacheSkinsForState(int stateIndex); boolean R_PrecacheSkinsForMobj(thinker_t* th, void* context); void R_PrecacheModelSkins(modeldef_t* modef); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_mapdata.h0000644000175000017500000002132111357170241023662 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mapdata.h: Playsim Data Structures, Macros and Constants * * These are internal to Doomsday. The games have no direct access to * this data. */ #ifndef __DOOMSDAY_PLAY_DATA_H__ #define __DOOMSDAY_PLAY_DATA_H__ #if defined(__JDOOM__) || defined(__JHERETIC__) || defined(__JHEXEN__) # error "Attempted to include internal Doomsday p_mapdata.h from a game" #endif #include "dd_share.h" #include "dam_main.h" #include "rend_bias.h" #include "m_nodepile.h" #include "m_vector.h" #define GET_VERTEX_IDX(vtx) ((vtx) - vertexes) #define GET_LINE_IDX(li) ((li) - lineDefs) #define GET_SIDE_IDX(si) ((si) - sideDefs) #define GET_SECTOR_IDX(sec) ((sec) - sectors) #define GET_SUBSECTOR_IDX(sub) ((sub) - ssectors) #define GET_SEG_IDX(seg) ((seg) - segs) #define GET_NODE_IDX(nd) ((nd) - nodes) // Return the index of plane within a sector's planes array. #define GET_PLANE_IDX(pln) ((pln) - (pln)->sector->planes[0]) #define VERTEX_PTR(i) (&vertexes[i]) #define SEG_PTR(i) (&segs[i]) #define SECTOR_PTR(i) (§ors[i]) #define SUBSECTOR_PTR(i) (&ssectors[i]) #define NODE_PTR(i) (&nodes[i]) #define LINE_PTR(i) (&lineDefs[i]) #define SIDE_PTR(i) (&sideDefs[i]) // Node flags. #define NF_SUBSECTOR 0x80000000 // Runtime map data objects, such as vertices, sectors, and subsectors all // have this header as their first member. This makes it possible to treat // an unknown map data pointer as a runtime_mapdata_header_t* and determine // its type. Note that this information is internal to the engine. typedef struct runtime_mapdata_header_s { int type; // One of the DMU type constants. } runtime_mapdata_header_t; typedef unsigned int gltextureid_t; /// \todo Does not belong here. typedef struct fvertex_s { float pos[2]; } fvertex_t; typedef struct shadowcorner_s { float corner; struct sector_s* proximity; float pOffset; float pHeight; } shadowcorner_t; typedef struct edgespan_s { float length; float shift; } edgespan_t; typedef struct linkmobj_s { struct mobj_s* mobj; struct linkmobj_s* prev; struct linkmobj_s* next; } linkmobj_t; typedef struct linkpolyobj_s { struct polyobj_s* polyobj; struct linkpolyobj_s* prev; struct linkpolyobj_s* next; } linkpolyobj_t; typedef struct watchedplanelist_s { uint num, maxNum; struct plane_s** list; } watchedplanelist_t; typedef struct surfacelistnode_s { void* data; struct surfacelistnode_s* next; } surfacelistnode_t; typedef struct surfacelist_s { uint num; surfacelistnode_t* head; } surfacelist_t; /** * Stores the data pertaining to vertex lighting for a worldmap, surface. */ typedef struct biassurface_s { uint updated; uint size; vertexillum_t* illum; // [size] biastracker_t tracker; biasaffection_t affected[MAX_BIAS_AFFECTED]; struct biassurface_s* next; } biassurface_t; typedef void* blockmap_t; #include "p_polyob.h" #include "p_maptypes.h" // Game-specific, map object type definitions. typedef struct { int identifier; char* name; valuetype_t type; } mapobjprop_t; typedef struct { int identifier; char* name; uint numProps; mapobjprop_t* props; } gamemapobjdef_t; // Map objects. typedef struct { uint idx; valuetype_t type; uint valueIdx; } customproperty_t; typedef struct { uint elmIdx; uint numProps; customproperty_t* props; } gamemapobj_t; typedef struct { uint num; gamemapobjdef_t* def; gamemapobj_t** objs; } gamemapobjlist_t; // Map value databases. typedef struct { valuetype_t type; uint numElms; void* data; } valuetable_t; typedef struct { uint numTables; valuetable_t** tables; } valuedb_t; typedef struct { gamemapobjlist_t* objLists; valuedb_t db; } gameobjdata_t; /** * The map data arrays are accessible globally inside the engine. */ extern char mapID[9]; extern uint numVertexes; extern vertex_t* vertexes; extern uint numSegs; extern seg_t* segs; extern uint numSectors; extern sector_t* sectors; extern uint numSSectors; extern subsector_t* ssectors; extern uint numNodes; extern node_t* nodes; extern uint numLineDefs; extern linedef_t* lineDefs; extern uint numSideDefs; extern sidedef_t* sideDefs; extern watchedplanelist_t* watchedPlaneList; extern surfacelist_t* movingSurfaceList; extern surfacelist_t* decoratedSurfaceList; extern float mapGravity; typedef struct gamemap_s { char mapID[9]; char uniqueID[256]; float bBox[4]; uint numVertexes; vertex_t* vertexes; uint numSegs; seg_t* segs; uint numSectors; sector_t* sectors; uint numSSectors; subsector_t* ssectors; uint numNodes; node_t* nodes; uint numLineDefs; linedef_t* lineDefs; uint numSideDefs; sidedef_t* sideDefs; uint numPolyObjs; polyobj_t** polyObjs; gameobjdata_t gameObjData; linkpolyobj_t** polyBlockMap; watchedplanelist_t watchedPlaneList; surfacelist_t movingSurfaceList; surfacelist_t decoratedSurfaceList; blockmap_t* blockMap; blockmap_t* ssecBlockMap; nodepile_t mobjNodes, lineNodes; // All kinds of wacky links. nodeindex_t* lineLinks; // Indices to roots. float globalGravity; // Gravity for the current map. int ambientLightLevel; // Ambient lightlevel for the current map. } gamemap_t; void P_InitData(void); gamemap_t* P_GetCurrentMap(void); void P_SetCurrentMap(gamemap_t* map); const char* P_GetMapID(gamemap_t* map); const char* P_GetUniqueMapID(gamemap_t* map); void P_GetMapBounds(gamemap_t* map, float* min, float* max); int P_GetMapAmbientLightLevel(gamemap_t* map); const char* P_GenerateUniqueMapID(const char* mapID); void P_PolyobjChanged(polyobj_t* po); void P_RegisterUnknownTexture(const char* name, boolean planeTex); void P_PrintMissingTextureList(void); void P_FreeBadTexList(void); void P_InitGameMapObjDefs(void); void P_ShutdownGameMapObjDefs(void); boolean P_RegisterMapObj(int identifier, const char* name); boolean P_RegisterMapObjProperty(int identifier, int propIdentifier, const char* propName, valuetype_t type); gamemapobjdef_t* P_GetGameMapObjDef(int identifier, const char *objName, boolean canCreate); void P_DestroyGameMapObjDB(gameobjdata_t* moData); void P_AddGameMapObjValue(gameobjdata_t* moData, gamemapobjdef_t* gmoDef, uint propIdx, uint elmIdx, valuetype_t type, void* data); gamemapobj_t* P_GetGameMapObj(gameobjdata_t* moData, gamemapobjdef_t* def, uint elmIdx, boolean canCreate); uint P_CountGameMapObjs(int identifier); byte P_GetGMOByte(int identifier, uint elmIdx, int propIdentifier); short P_GetGMOShort(int identifier, uint elmIdx, int propIdentifier); int P_GetGMOInt(int identifier, uint elmIdx, int propIdentifier); fixed_t P_GetGMOFixed(int identifier, uint elmIdx, int propIdentifier); angle_t P_GetGMOAngle(int identifier, uint elmIdx, int propIdentifier); float P_GetGMOFloat(int identifier, uint elmIdx, int propIdentifier); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/net_main.h0000644000175000017500000002315711357170241023537 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_main.h: Network Subsystem */ #ifndef __DOOMSDAY_NETWORK_H__ #define __DOOMSDAY_NETWORK_H__ #include #include "lzss.h" #include "dd_share.h" #include "sys_network.h" #include "net_msg.h" #include "p_mapdata.h" #include "con_decl.h" #define BIT(x) (1 << (x)) #define NSP_BROADCAST -1 // For Net_SendBuffer. // Flags for console text from the server. // Change with server version? #define SV_CONSOLE_FLAGS (CBLF_WHITE|CBLF_LIGHT|CBLF_GREEN) #define PING_TIMEOUT 1000 // Ping timeout (ms). #define MAX_PINGS 10 // The default bandwidth rating for new clients. #define BWR_DEFAULT 40 // A modest acktime used by default for new clients (1 sec ping). #define ACK_DEFAULT 1000 #define MONITORTICS 7 #define LOCALTICS 10 // Built ticcmds are stored here. #define BACKUPTICS 70 // Two seconds worth of tics. // The number of mobjs that can be stored in the input/visible buffer. // The server won't send more mobjs than this. #define MAX_CLMOBJS 80 // Packet types. // PKT = sent by anybody // PSV = sent by server // PCL = sent by client enum { // Messages and responses. PCL_HELLO = 0, PKT_OK = 1, PKT_CANCEL = 2, // unused? PKT_PLAYER_INFO = 3, PKT_CHAT = 4, PKT_TICCMD = 5, // unused? PKT_PING = 6, PSV_HANDSHAKE = 7, PSV_SERVER_CLOSE = 8, PSV_FRAME = 9, // obsolete PSV_PLAYER_EXIT = 10, PSV_CONSOLE_TEXT = 11, PCL_ACK_SHAKE = 12, PSV_SYNC = 13, PSV_FILTER = 14, // unused? PKT_COMMAND = 15, // obsolete PKT_LOGIN = 16, PCL_ACK_SETS = 17, PKT_COORDS = 18, PKT_DEMOCAM = 19, PKT_DEMOCAM_RESUME = 20, PCL_HELLO2 = 21, // Includes game ID PSV_FRAME2 = 22, // Frame packet v2 PSV_FIRST_FRAME2 = 23, // First PSV_FRAME2 after map change PSV_SOUND2 = 24, // unused? PSV_STOP_SOUND = 25, PCL_ACKS = 26, PSV_PLAYER_FIX = 27, // Fix angles/pos/mom. PCL_ACK_PLAYER_FIX = 28, // Acknowledge player fix. /* 28 */ PKT_COMMAND2 = 29, PCL_COMMANDS = DDPT_COMMANDS, // 32; ticcmds (handled by game) // Game specific events. PKT_GAME_MARKER = DDPT_FIRST_GAME_EVENT // 64 }; // Use the number defined in dd_share.h for sound packets. // This is for backwards compatibility. #define PSV_SOUND 71 /* DDPT_SOUND */ #define RESENDCOUNT 10 #define HANDSHAKECOUNT 17 #define UPDATECOUNT 20 // These dd-flags are packed (i.e. included in mobj deltas). #define DDMF_PACK_MASK 0x3cfff1ff // A client's acknowledgement threshold depends on the average of his // acknowledgement times. #define NUM_ACK_TIMES 8 // The consolePlayer's camera position is written to the demo file // every 3rd tic. #define LOCALCAM_WRITE_TICS 3 //--------------------------------------------------------------------------- // Types //--------------------------------------------------------------------------- typedef struct { // High tics when ping was sent (0 if pinger not used). int sent; // A record of the pings (negative time: no response). float times[MAX_PINGS]; // Total number of pings and the current one. int total; int current; } pinger_t; // Network information for a player. Corresponds the players array. typedef struct { // ID number. Each client has a unique ID number. ident_t id; // Ticcmd buffer. The server uses this when clients send it ticcmds. byte *ticCmds; // Number of tics in the buffer. int numTics; // Index of the first tic in the buffer. int firstTic; // Last command executed, reused if a new one isn't found. ticcmd_t *lastCmd; // Clients merge several ticcmds into this one, which is them sent // periodically to the server. ticcmd_t *aggregateCmd; int lastTransmit; // If >0, the server will send the next world frame to the client. // This is set when input is received from the client. int updateCount; // Gametic when the client entered the game. int enterTime; // Client-reported time of the last processed ticcmd. // Older or as old tics than this are discarded. int runTime; // Bandwidth rating for connection. Determines how much information // can be sent to the client. Determined dynamically. int bandwidthRating; // During the adjust period, raising the BWR is allowed (hitting max // frame size). int bwrAdjustTime; // A record of the past few acknowledgement times. uint ackTimes[NUM_ACK_TIMES]; int ackIdx; // Clients use this to determine how long ago they received the // last update of this client. int age; // Is this client connected? (Might not be in the game yet.) Only // used by the server. int connected; // Clients are pinged by the server when they join the game. // This is the ping in milliseconds for this client. For the server. unsigned int shakePing; // If true, the server will send the player a handshake. The client must // acknowledge it before this flag is turned off. int handshake; // Server uses this to determine whether it's OK to send game packets // to the client. int ready; // The name of the player. char name[PLAYERNAMELEN]; // Field of view. Used in determining visible mobjs (default: 90). float fov; // The DirectPlay player that represents this client. unsigned int nodeID; // DP player ID. // Ping tracker for this client. pinger_t ping; // Demo recording file (being recorded if not NULL). LZFILE *demo; boolean recording; boolean recordPaused; // View console. Which player this client is viewing? int viewConsole; } client_t; // Packets. typedef struct { byte version; unsigned short playerMask; // 16 players. byte yourConsole; // Which one's you? int gameTime; } handshake_packet_t; typedef struct { byte console; char name[PLAYERNAMELEN]; } playerinfo_packet_t; //--------------------------------------------------------------------------- // Variables //--------------------------------------------------------------------------- extern boolean firstNetUpdate; extern int resendStart; // set when server needs our tics extern int resendCount; extern int oldEnterTics; extern int numClMobjs; extern boolean masterAware; extern int netGame; extern int realTics, availableTics; extern int isServer, isClient; extern boolean allowNetTraffic; // Should net traffic be allowed? extern byte netDontSleep, netTicSync; extern client_t clients[DDMAXPLAYERS]; //--------------------------------------------------------------------------- // Functions //--------------------------------------------------------------------------- void Net_Register(void); void Net_Init(void); void Net_Shutdown(void); void Net_AllocArrays(void); void Net_DestroyArrays(void); void Net_SendPacket(int to_player, int type, void *data, size_t length); boolean Net_GetPacket(void); void Net_SendBuffer(int to_player, int sp_flags); void Net_InitGame(void); void Net_StartGame(void); void Net_StopGame(void); void Net_BuildLocalCommands(timespan_t time); void Net_SendCommands(void); void Net_SendPing(int player, int count); void Net_PingResponse(void); void Net_ShowPingSummary(int player); void Net_ShowChatMessage(void); int Net_TimeDelta(byte now, byte then); int Net_GetTicCmd(void *cmd, int player); void Net_Update(void); void Net_Ticker(void/*timespan_t time*/); void Net_Drawer(void); boolean Net_IsLocalPlayer(int pNum); void Net_SetInitialAckTime(int clientNumber, uint period); void Net_SetAckTime(int clientNumber, uint period); uint Net_GetAckTime(int clientNumber); uint Net_GetAckThreshold(int clientNumber); const char* Net_GetPlayerName(int player); ident_t Net_GetPlayerID(int player); void Net_PrintServerInfo(int index, serverinfo_t *info); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/ui_panel.h0000644000175000017500000000226711357170241023540 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * ui_panel.h: Control Panel */ #ifndef __DOOMSDAY_CONTROL_PANEL_H__ #define __DOOMSDAY_CONTROL_PANEL_H__ #include "con_decl.h" void CP_Register(void); // Helpful handlers. void CP_CvarSlider(ui_object_t *ob); void CP_InitCvarSliders(ui_object_t *ob); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_model.h0000644000175000017500000000514011357170241024045 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_model.h: 3D Models */ #ifndef __DOOMSDAY_RENDER_MODEL_H__ #define __DOOMSDAY_RENDER_MODEL_H__ typedef struct rendmodelparams_s { // Animation, frame interpolation. struct modeldef_s *mf, *nextMF; float inter; boolean alwaysInterpolate; int id; // For a unique skin offset. int selector; // Position/Orientation/Scale float center[3], gzt; // The real center point and global top z for silhouette clipping. float srvo[3]; // Short-range visual offset. float distance; // Distance from viewer. float yaw, extraYawAngle, yawAngleOffset; // \todo we don't need three sets of angles, update users of this struct instead. float pitch, extraPitchAngle, pitchAngleOffset; float extraScale; boolean viewAlign; boolean mirror; // If true the model will be mirrored about its Z axis (in model space). // Appearance int flags; // Mobj flags. int tmap; // Lighting/color: float ambientColor[4]; uint vLightListIdx; // Shinemaping: float shineYawOffset; float shinePitchOffset; boolean shineTranslateWithViewerPos; boolean shinepspriteCoordSpace; // Use the psprite coordinate space hack. } rendmodelparams_t; extern int modelLight; extern int frameInter; extern int mirrorHudModels; extern int modelShinyMultitex; extern float rendModelLOD; void Rend_ModelRegister(void); void Rend_RenderModel(const rendmodelparams_t *params); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_md5.h0000644000175000017500000000260611357170241022742 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * m_md5.h: MD5 Hash Generator */ #ifndef __DOOMSDAY_MISC_MD5_H__ #define __DOOMSDAY_MISC_MD5_H__ #include "dd_types.h" #define MD5_BLOCK_WORDS 16 #define MD5_HASH_WORDS 4 typedef struct md5_ctx { uint hash[MD5_HASH_WORDS]; uint block[MD5_BLOCK_WORDS]; uint byte_count; uint pad32; } md5_ctx_t; void md5_init(void *ctx); void md5_update(void *ctx, const byte *data, unsigned int len); void md5_final(void *ctx, byte *out); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_draw.h0000644000175000017500000000251011357170241023211 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_draw.h: Drawing Routines */ #ifndef __DOOMSDAY_REFRESH_DRAW_H__ #define __DOOMSDAY_REFRESH_DRAW_H__ extern byte *translationTables; void R_InitTranslationTables(void); void R_UpdateTranslationTables(void); void R_InitViewBorder(void); void R_SetBorderGfx(char *gfx[9]); void R_DrawViewBorder(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/cl_sound.h0000644000175000017500000000225511357170241023547 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_sound.h: Clientside Sounds */ #ifndef __DOOMSDAY_CLIENT_SOUND_H__ #define __DOOMSDAY_CLIENT_SOUND_H__ void Cl_ReadSoundDelta2(deltatype_t type, boolean skip); void Cl_Sound(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/ui_mpi.h0000644000175000017500000000207711357170241023225 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * ui_mpi.h: Multiplayer Setup Interface */ #ifndef __DOOMSDAY_MPLAYINTERFACE_H__ #define __DOOMSDAY_MPLAYINTERFACE_H__ void DD_NetSetup(int server_mode); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/cl_frame.h0000644000175000017500000000235311357170241023510 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_frame.h: Frame Reception */ #ifndef __DOOMSDAY_CLIENT_FRAME_H__ #define __DOOMSDAY_CLIENT_FRAME_H__ void Cl_InitFrame(void); void Cl_ResetFrame(void); void Cl_FrameReceived(void); void Cl_Frame2Received(int packetType); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dam_file.h0000644000175000017500000000241111357170241023473 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dam_file.h: Doomsday Archived Map (DAM), reader/writer. */ #ifndef __DOOMSDAY_ARCHIVED_MAP_FILE_H__ #define __DOOMSDAY_ARCHIVED_MAP_FILE_H__ #include "de_play.h" boolean DAM_MapIsValid(filename_t cachedMapDataFile, int markerLumpNum); boolean DAM_MapWrite(gamemap_t *map, filename_t path); boolean DAM_MapRead(gamemap_t *map, filename_t path); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_shadow.h0000644000175000017500000000227311357170241024236 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * rend_shadow.h: Map Object Shadows */ #ifndef __DOOMSDAY_RENDER_SHADOW_H__ #define __DOOMSDAY_RENDER_SHADOW_H__ //extern int useShadows, shadowMaxRad, shadowMaxDist; //extern float shadowFactor; void Rend_ShadowRegister(void); void Rend_RenderShadows(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_tex.h0000644000175000017500000000710711357170241023224 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_tex.h: Texture Manipulation Algorithms. */ #ifndef __DOOMSDAY_TEXTURES_H__ #define __DOOMSDAY_TEXTURES_H__ #include "gl_texmanager.h" boolean GL_OptimalSize(int width, int height, int *optWidth, int *optHeight, boolean noStretch, boolean isMipMapped); void GL_ConvertBuffer(int width, int height, int informat, int outformat, byte *in, byte *out, colorpaletteid_t pal, boolean gamma); void GL_ScaleBuffer32(byte *in, int inWidth, int inHeight, byte *out, int outWidth, int outHeight, int comps); void GL_DownMipmap32(byte* in, int width, int height, int comps); void GL_ConvertToAlpha(image_t *image, boolean makeWhite); void GL_ConvertToLuminance(image_t *image); void GL_CalcLuminance(byte* buffer, int width, int height, int pixelsize, colorpaletteid_t palid, float* brightX, float* brightY, rgbcol_t* color, float* lumSize); byte* GL_ApplyColorKeying(byte* buf, unsigned int pixelSize, unsigned int width, unsigned int height); int GL_ValidTexHeight2(int width, int height); void pixBlt(byte* src, int srcWidth, int srcHeight, byte* dest, int destWidth, int destHeight, int alpha, int srcRegX, int srcRegY, int destRegX, int destRegY, int regWidth, int regHeight); void averageColorIdx(rgbcol_t col, byte* data, int w, int h, colorpaletteid_t palid, boolean hasAlpha); void averageColorRGB(rgbcol_t col, byte* data, int w, int h); int lineAverageColorIdx(rgbcol_t col, byte* data, int w, int h, int line, colorpaletteid_t palid, boolean hasAlpha); int lineAverageColorRGB(rgbcol_t col, byte* data, int w, int h, int line); void ColorOutlines(byte* buffer, int width, int height); int DrawRealPatch(byte* buffer, int texwidth, int texheight, const lumppatch_t* patch, int origx, int origy, boolean maskZero, boolean checkForAlpha); boolean ImageHasAlpha(image_t *image); void GL_TranslatePatch(lumppatch_t* patch, byte* transTable); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/b_device.h0000644000175000017500000000424311357170241023500 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_device.h: Control-Device Bindings */ #ifndef __DOOMSDAY_BIND_DEVICE_H__ #define __DOOMSDAY_BIND_DEVICE_H__ #include "b_util.h" typedef enum cbdevtype_e { CBD_TOGGLE, CBD_AXIS, CBD_ANGLE } cbdevtype_t; // Flags for control-device bindings. #define CBDF_INVERSE 0x1 #define CBDF_TIME_STAGED 0x2 typedef struct dbinding_s { struct dbinding_s* next; struct dbinding_s* prev; int bid; uint device; cbdevtype_t type; int id; float angle; uint flags; // Additional conditions. int numConds; statecondition_t* conds; } dbinding_t; void B_InitDeviceBindingList(dbinding_t* listRoot); void B_DestroyDeviceBindingList(dbinding_t* listRoot); dbinding_t* B_NewDeviceBinding(dbinding_t* listRoot, const char* deviceDesc); void B_DestroyDeviceBinding(dbinding_t* cb); void B_DeviceBindingToString(const dbinding_t* b, ddstring_t* str); void B_EvaluateDeviceBindingList(int localNum, dbinding_t* listRoot, float* pos, float* relativeOffset, struct bcontext_s* controlClass); #endif // __DOOMSDAY_BIND_DEVICE_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_zone.h0000644000175000017500000000733211357170241023364 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 1999-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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: http://www.opensource.org/ */ /** * dd_zone.h: Memory Zone */ #ifndef __DOOMSDAY_ZONE_H__ #define __DOOMSDAY_ZONE_H__ /** * Define this to force all memory blocks to be allocated from * the real heap. Useful when debugging memory-related problems. */ //#define FAKE_MEMORY_ZONE 1 #define PU_REFRESHTEX 11 // Textures/Flats/refresh. #define PU_REFRESHCM 12 // Colormap. #define PU_REFRESHTRANS 13 #define PU_REFRESHSPR 14 #define PU_PATCH 15 #define PU_MODEL 16 #define PU_SPRITE 20 int Z_Init(void); void Z_Shutdown(void); void Z_EnableFastMalloc(boolean isEnabled); //void Z_PrintStatus(void); void* Z_Malloc(size_t size, int tag, void* ptr); void Z_Free(void* ptr); void Z_FreeTags(int lowTag, int highTag); void Z_CheckHeap(void); void Z_ChangeTag2(void* ptr, int tag); void Z_ChangeUser(void* ptr, void* newUser); void* Z_GetUser(void* ptr); int Z_GetTag(void* ptr); void* Z_Realloc(void* ptr, size_t n, int mallocTag); void* Z_Calloc(size_t size, int tag, void* user); void* Z_Recalloc(void* ptr, size_t n, int callocTag); size_t Z_FreeMemory(void); typedef struct memblock_s { size_t size; // Including header and possibly tiny fragments. void** user; // NULL if a free block. int tag; // Purge level. int id; // Should be ZONEID. struct memvolume_s* volume; // Volume this block belongs to. struct memblock_s* next, *prev; struct memblock_s* seqLast, *seqFirst; #ifdef FAKE_MEMORY_ZONE void* area; // The real memory area. #endif } memblock_t; typedef struct { size_t size; // Total bytes malloced, including header. memblock_t blockList; // Start / end cap for linked list. memblock_t* rover; } memzone_t; typedef struct zblockset_s { unsigned int elementsPerBlock; size_t elementSize; int tag; // All blocks in a blockset have the same tag. unsigned int count; struct zblock_s* blocks; } zblockset_t; zblockset_t* Z_BlockCreate(size_t sizeOfElement, uint batchSize, int tag); void Z_BlockDestroy(zblockset_t* set); void* Z_BlockNewElement(zblockset_t* set); #ifdef FAKE_MEMORY_ZONE // Fake memory zone allocates memory from the real heap. #define Z_ChangeTag(p,t) Z_ChangeTag2(p,t) memblock_t* Z_GetBlock(void* ptr); #else // Real memory zone allocates memory from a custom heap. #define Z_GetBlock(ptr) ((memblock_t*) ((byte*)(ptr) - sizeof(memblock_t))) #define Z_ChangeTag(p,t) \ { \ if (( (memblock_t *)( (byte *)(p) - sizeof(memblock_t)))->id!=0x1d4a11) \ Con_Error("Z_CT at "__FILE__":%i",__LINE__); \ Z_ChangeTag2(p,t); \ }; #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/con_bar.h0000644000175000017500000000232211357170241023337 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_bar.h: Console Progress Bar */ #ifndef __DOOMSDAY_CONSOLE_BAR_H__ #define __DOOMSDAY_CONSOLE_BAR_H__ void Con_InitProgress(int maxProgress); void Con_SetProgress(int progress); float Con_GetProgress(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_linkedlist.h0000644000175000017500000000710211357170241024413 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * m_linkedlist.h: Linked lists. */ #ifndef __LINKEDLIST_H__ #define __LINKEDLIST_H__ #ifdef __cplusplus extern "C" { #endif // The C_DECL macro, used with compare functions. #ifndef C_DECL # if defined(WIN32) # define C_DECL __cdecl # elif defined(UNIX) # define C_DECL # endif #endif typedef int listindex_t; // Helper macro for defining list compare functions. #define COMPAREFUNC(name) int C_DECL name(const void *a, const void *b) typedef int (C_DECL *comparefunc) (const void *a, const void *b); // Premade compare functions: COMPAREFUNC( compareInt ); COMPAREFUNC( compareUInt ); COMPAREFUNC( compareFloat ); COMPAREFUNC( compareDouble ); COMPAREFUNC( compareString ); COMPAREFUNC( compareAddress ); // // Linked lists. // typedef void* linklist_t; #define PTR_NOT_LIST -1 // Linked list errors: enum { LL_NO_ERROR, LL_ERROR_UNKNOWN, LL_ERROR_OUT_OF_MEMORY, LL_ERROR_UNDERFLOW, LL_ERROR_OVERFLOW, LL_ERROR_LAST }; // List_Create flags: #define LCF_CIRCULAR 0x1 // The list forms a ring of items, as // opposed to the default linear list. // List_Iterate flags #define LIF_REVERSE 0x1 // Iteration will be tail > head. // Create/Destroy: linklist_t *List_Create(void); linklist_t *List_Create2(int createFlags, comparefunc func); void List_Destroy(linklist_t *list); // Inserts: int List_InsertFront(linklist_t *list, const void *data); int List_InsertBack(linklist_t *list, const void *data); // Retrieves: void* List_GetFront(const linklist_t *list); void* List_GetBack(const linklist_t *list); void* List_GetAt(const linklist_t *list, listindex_t position); // Extracts: void* List_ExtractFront(linklist_t *list); void* List_ExtractBack(linklist_t *list); void* List_ExtractAt(linklist_t *list, listindex_t position); // Other: void List_SetCompareFunc(linklist_t *list, comparefunc func); void List_Clear(linklist_t *list); listindex_t List_Find(const linklist_t *list, const void *data); int List_Exchange(linklist_t *list, listindex_t positionA, listindex_t positionB); // Sorts: void List_Sort(linklist_t *list); // State retrieval: listindex_t List_Count(const linklist_t *list); int List_GetError(const linklist_t *list); // Iteration: int List_Iterate(const linklist_t *list, int iterateFlags, void *data, int (*callback) (void *element, void *data)); // Debugging: #ifndef NDEBUG void List_Test(void); #endif #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_draw.h0000644000175000017500000000476511357170241023370 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_draw.h: Basic Drawing Routines */ #ifndef __DOOMSDAY_GRAPHICS_DRAW_H__ #define __DOOMSDAY_GRAPHICS_DRAW_H__ void GL_UsePatchOffset(boolean enable); // 2D drawing routines: void GL_DrawPatch_CS(int x, int y, lumpnum_t lump); void GL_DrawPatch(int x, int y, lumpnum_t lump); void GL_DrawPatchLitAlpha(int x, int y, float light, float alpha, lumpnum_t lump); void GL_DrawFuzzPatch(int x, int y, lumpnum_t lump); void GL_DrawAltFuzzPatch(int x, int y, lumpnum_t lump); void GL_DrawShadowedPatch(int x, int y, lumpnum_t lump); void GL_DrawRawScreen(lumpnum_t lump, float offx, float offy); void GL_DrawRawScreen_CS(lumpnum_t lump, float offx, float offy, float scalex, float scaley); void GL_DrawLine(float x1, float y1, float x2, float y2, float r, float g, float b, float a); void GL_DrawRect(float x, float y, float w, float h, float r, float g, float b, float a); void GL_DrawRectTiled(float x, float y, float w, float h, int tw, int th); void GL_DrawCutRectTiled(float x, float y, float w, float h, int tw, int th, int txoff, int tyoff, float cx, float cy, float cw, float ch); // Filters: void GL_SetFilter(boolean enable); void GL_SetFilterColor(float r, float g, float b, float a); int GL_DrawFilter(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_main.h0000644000175000017500000000433311357170241023333 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_main.h: Engine Core */ #ifndef __DOOMSDAY_MAIN_H__ #define __DOOMSDAY_MAIN_H__ #include "dd_types.h" // Verbose messages. #define VERBOSE(code) { if(verbose >= 1) { code; } } #define VERBOSE2(code) { if(verbose >= 2) { code; } } extern int verbose; extern int maxZone; extern FILE* outFile; // Output file for console messages. extern int isDedicated; extern char ddBasePath[]; extern char* defaultWads; // A list of wad names, whitespace in between (in .cfg). extern directory_t ddRuntimeDir, ddBinDir; extern filename_t bindingsConfigFileName; #ifndef WIN32 extern GETGAMEAPI GetGameAPI; #endif int DD_Main(void); void DD_UpdateEngineState(void); void DD_GameUpdate(int flags); void DD_AddStartupWAD(const char* file); void DD_AddIWAD(const char* path); void DD_AutoLoad(void); void DD_SetConfigFile(const char* file); void DD_SetDefsFile(const char* file); int DD_GetInteger(int ddvalue); void DD_SetInteger(int ddvalue, int parm); void DD_SetVariable(int ddvalue, void* ptr); void* DD_GetVariable(int ddvalue); ddplayer_t* DD_GetPlayer(int number); void DD_CheckTimeDemo(void); const char* value_Str(int val); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/mapdata.hs0000644000175000017500000004400511357170241023532 0ustar keeskees# $Id$ # Runtime map data defitions. Processed by the makedmt.py script. public #define DMT_VERTEX_POS DDVT_FLOAT end internal #define LO_prev link[0] #define LO_next link[1] typedef struct shadowvert_s { float inner[2]; float extended[2]; } shadowvert_t; typedef struct lineowner_s { struct linedef_s *lineDef; struct lineowner_s *link[2]; // {prev, next} (i.e. {anticlk, clk}). binangle_t angle; // between this and next clockwise. shadowvert_t shadowOffsets; } lineowner_t; #define V_pos v.pos typedef struct mvertex_s { // Vertex index. Always valid after loading and pruning of unused // vertices has occurred. int index; // Reference count. When building normal node info, unused vertices // will be pruned. int refCount; // Usually NULL, unless this vertex occupies the same location as a // previous vertex. Only used during the pruning phase. struct vertex_s *equiv; struct edgetip_s *tipSet; // Set of wall_tips. // Final data. double pos[2]; } mvertex_t; end struct vertex - uint numLineOwners // Number of line owners. - lineowner_t* lineOwners // Lineowner base ptr [numlineowners] size. A doubly, circularly linked list. The base is the line with the lowest angle and the next-most with the largest angle. - fvertex_t v - mvertex_t buildData end internal // Helper macros for accessing seg data elements. #define FRONT 0 #define BACK 1 #define SG_v(n) v[(n)] #define SG_vpos(n) SG_v(n)->V_pos #define SG_v1 SG_v(0) #define SG_v1pos SG_v(0)->V_pos #define SG_v2 SG_v(1) #define SG_v2pos SG_v(1)->V_pos #define SG_sector(n) sec[(n)] #define SG_frontsector SG_sector(FRONT) #define SG_backsector SG_sector(BACK) #define SEG_SIDEDEF(s) ((s)->lineDef->sideDefs[(s)->side]) // Seg flags #define SEGF_POLYOBJ 0x1 // Seg is part of a poly object. // Seg frame flags #define SEGINF_FACINGFRONT 0x0001 #define SEGINF_BACKSECSKYFIX 0x0002 end public #define DMT_SEG_SIDEDEF DDVT_PTR end struct seg PTR vertex_s*[2] v // [Start, End] of the segment. PTR linedef_s* lineDef PTR sector_s*[2] sec PTR subsector_s* subsector PTR seg_s* backSeg ANGLE angle_t angle BYTE byte side // 0=front, 1=back BYTE byte flags FLOAT float length // Accurate length of the segment (v1 -> v2). FLOAT float offset - biassurface_t*[3] bsuf // 0=middle, 1=top, 2=bottom - short frameFlags end internal #define SUBF_MIDPOINT 0x80 // Midpoint is tri-fan centre. end struct subsector UINT uint segCount PTR seg_s** segs // [segcount] size. PTR polyobj_s* polyObj // NULL, if there is no polyobj. PTR sector_s* sector - int addSpriteCount // frame number of last R_AddSprites - uint inSectorID - int flags - int validCount - uint[NUM_REVERB_DATA] reverb - fvertex_t bBox[2] // Min and max points. - float[2] worldGridOffset // Offset to align the top left of the bBox to the world grid. - fvertex_t midPoint // Center of vertices. - ushort numVertices - fvertex_s** vertices // [numvertices] size - shadowlink_s* shadows - biassurface_s** bsuf // [sector->planeCount] size. end internal typedef struct materiallayer_s { int stage; // -1 => layer not in use. short tics; gltextureid_t tex; } material_layer_t; typedef enum { MEC_UNKNOWN = -1, MEC_METAL = 0, MEC_ROCK, MEC_WOOD, MEC_CLOTH, NUM_MATERIAL_ENV_CLASSES } material_env_class_t; end struct material INT material_namespace_t mnamespace - ded_material_s* def // Can be NULL (was generated automatically). SHORT short flags // MATF_* flags SHORT short width // Defined width & height of the material (not texture!). SHORT short height - material_layer_t layers[DDMAX_MATERIAL_LAYERS] - uint numLayers - material_env_class_t envClass // Used for environmental sound properties. - ded_detailtexture_s* detail - ded_decor_s* decoration - ded_ptcgen_s* ptcGen - ded_reflection_s* reflection - boolean inAnimGroup // True if belongs to some animgroup. - material_s* current - material_s* next - float inter - material_s* globalNext // Linear list linking all materials. end internal // Internal surface flags: #define SUIF_PVIS 0x0001 #define SUIF_MATERIAL_FIX 0x0002 // Current texture is a fix replacement // (not sent to clients, returned via DMU etc). #define SUIF_BLEND 0x0004 // Surface possibly has a blended texture. #define SUIF_NO_RADIO 0x0008 // No fakeradio for this surface. #define SUIF_UPDATE_FLAG_MASK 0xff00 #define SUIF_UPDATE_DECORATIONS 0x8000 // Decoration types. typedef enum { DT_LIGHT, DT_MODEL, NUM_DECORTYPES } decortype_t; // Helper macros for accessing decor data. #define DEC_LIGHT(x) (&((x)->data.light)) #define DEC_MODEL(x) (&((x)->data.model)) typedef struct surfacedecor_s { float pos[3]; // World coordinates of the decoration. decortype_t type; subsector_t* subsector; union surfacedecor_data_u { struct surfacedecor_light_s { const struct ded_decorlight_s* def; } light; struct surfacedecor_model_s { const struct ded_decormodel_s* def; struct modeldef_s* mf; float pitch, yaw; } model; } data; } surfacedecor_t; end struct surface - void* owner // Either @c DMU_SIDEDEF, or @c DMU_PLANE INT int flags // SUF_ flags - int oldFlags PTR material_t* material BLENDMODE blendmode_t blendMode FLOAT float[3] normal // Surface normal - float[3] oldNormal FLOAT float[2] offset // [X, Y] Planar offset to surface material origin. - float[2][2] oldOffset - float[2] visOffset - float[2] visOffsetDelta FLOAT float[4] rgba // Surface color tint - short inFlags // SUIF_* flags - uint numDecorations - surfacedecor_t *decorations end internal typedef enum { PLN_FLOOR, PLN_CEILING, PLN_MID, NUM_PLANE_TYPES } planetype_t; end internal #define PS_normal surface.normal #define PS_material surface.material #define PS_offset surface.offset #define PS_visoffset surface.visOffset #define PS_rgba surface.rgba #define PS_flags surface.flags #define PS_inflags surface.inFlags end struct plane PTR ddmobj_base_t soundOrg // Sound origin for plane PTR sector_s* sector // Owner of the plane (temp) - surface_t surface FLOAT float height // Current height - float[2] oldHeight FLOAT float glow // Glow amount FLOAT float[3] glowRGB // Glow color FLOAT float target // Target height FLOAT float speed // Move speed - float visHeight // Visible plane height (smoothed) - float visHeightDelta - planetype_t type // PLN_* type. - int planeID end internal // Helper macros for accessing sector floor/ceiling plane data elements. #define SP_plane(n) planes[(n)] #define SP_planesurface(n) SP_plane(n)->surface #define SP_planeheight(n) SP_plane(n)->height #define SP_planenormal(n) SP_plane(n)->surface.normal #define SP_planematerial(n) SP_plane(n)->surface.material #define SP_planeoffset(n) SP_plane(n)->surface.offset #define SP_planergb(n) SP_plane(n)->surface.rgba #define SP_planeglow(n) SP_plane(n)->glow #define SP_planeglowrgb(n) SP_plane(n)->glowRGB #define SP_planetarget(n) SP_plane(n)->target #define SP_planespeed(n) SP_plane(n)->speed #define SP_planesoundorg(n) SP_plane(n)->soundOrg #define SP_planevisheight(n) SP_plane(n)->visHeight #define SP_ceilsurface SP_planesurface(PLN_CEILING) #define SP_ceilheight SP_planeheight(PLN_CEILING) #define SP_ceilnormal SP_planenormal(PLN_CEILING) #define SP_ceilmaterial SP_planematerial(PLN_CEILING) #define SP_ceiloffset SP_planeoffset(PLN_CEILING) #define SP_ceilrgb SP_planergb(PLN_CEILING) #define SP_ceilglow SP_planeglow(PLN_CEILING) #define SP_ceilglowrgb SP_planeglowrgb(PLN_CEILING) #define SP_ceiltarget SP_planetarget(PLN_CEILING) #define SP_ceilspeed SP_planespeed(PLN_CEILING) #define SP_ceilsoundorg SP_planesoundorg(PLN_CEILING) #define SP_ceilvisheight SP_planevisheight(PLN_CEILING) #define SP_floorsurface SP_planesurface(PLN_FLOOR) #define SP_floorheight SP_planeheight(PLN_FLOOR) #define SP_floornormal SP_planenormal(PLN_FLOOR) #define SP_floormaterial SP_planematerial(PLN_FLOOR) #define SP_flooroffset SP_planeoffset(PLN_FLOOR) #define SP_floorrgb SP_planergb(PLN_FLOOR) #define SP_floorglow SP_planeglow(PLN_FLOOR) #define SP_floorglowrgb SP_planeglowrgb(PLN_FLOOR) #define SP_floortarget SP_planetarget(PLN_FLOOR) #define SP_floorspeed SP_planespeed(PLN_FLOOR) #define SP_floorsoundorg SP_planesoundorg(PLN_FLOOR) #define SP_floorvisheight SP_planevisheight(PLN_FLOOR) #define S_skyfix(n) skyFix[(n)] #define S_floorskyfix S_skyfix(PLN_FLOOR) #define S_ceilskyfix S_skyfix(PLN_CEILING) end internal // Sector frame flags #define SIF_VISIBLE 0x1 // Sector is visible on this frame. #define SIF_FRAME_CLEAR 0x1 // Flags to clear before each frame. #define SIF_LIGHT_CHANGED 0x2 // Sector flags. #define SECF_UNCLOSED 0x1 // An unclosed sector (some sort of fancy hack). typedef struct msector_s { // Sector index. Always valid after loading & pruning. int index; // Suppress superfluous mini warnings. int warnedFacing; int refCount; } msector_t; end struct sector - int frameFlags INT int validCount // if == validCount, already checked. - int flags - float[4] bBox // Bounding box for the sector. - float approxArea // Rough approximation of sector area. FLOAT float lightLevel - float oldLightLevel FLOAT float[3] rgb - float[3] oldRGB PTR mobj_s* mobjList // List of mobjs in the sector. UINT uint lineDefCount PTR linedef_s** lineDefs // [lineDefCount+1] size. UINT uint ssectorCount PTR subsector_s** ssectors // [ssectorCount+1] size. - uint numReverbSSecAttributors - subsector_s** reverbSSecs // [numReverbSSecAttributors] size. PTR ddmobj_base_t soundOrg UINT uint planeCount - plane_s** planes // [planeCount+1] size. - sector_s* lightSource // Main sky light source. - uint blockCount // Number of gridblocks in the sector. - uint changedBlockCount // Number of blocks to mark changed. - ushort* blocks // Light grid block indices. FLOAT float[NUM_REVERB_DATA] reverb - msector_t buildData end internal // Parts of a wall segment. typedef enum segsection_e { SEG_MIDDLE, SEG_TOP, SEG_BOTTOM } segsection_t; // Helper macros for accessing sidedef top/middle/bottom section data elements. #define SW_surface(n) sections[(n)] #define SW_surfaceflags(n) SW_surface(n).flags #define SW_surfaceinflags(n) SW_surface(n).inFlags #define SW_surfacematerial(n) SW_surface(n).material #define SW_surfacenormal(n) SW_surface(n).normal #define SW_surfaceoffset(n) SW_surface(n).offset #define SW_surfacevisoffset(n) SW_surface(n).visOffset #define SW_surfacergba(n) SW_surface(n).rgba #define SW_surfaceblendmode(n) SW_surface(n).blendMode #define SW_middlesurface SW_surface(SEG_MIDDLE) #define SW_middleflags SW_surfaceflags(SEG_MIDDLE)0 #define SW_middleinflags SW_surfaceinflags(SEG_MIDDLE) #define SW_middlematerial SW_surfacematerial(SEG_MIDDLE) #define SW_middlenormal SW_surfacenormal(SEG_MIDDLE) #define SW_middletexmove SW_surfacetexmove(SEG_MIDDLE) #define SW_middleoffset SW_surfaceoffset(SEG_MIDDLE) #define SW_middlevisoffset SW_surfacevisoffset(SEG_MIDDLE) #define SW_middlergba SW_surfacergba(SEG_MIDDLE) #define SW_middleblendmode SW_surfaceblendmode(SEG_MIDDLE) #define SW_topsurface SW_surface(SEG_TOP) #define SW_topflags SW_surfaceflags(SEG_TOP) #define SW_topinflags SW_surfaceinflags(SEG_TOP) #define SW_topmaterial SW_surfacematerial(SEG_TOP) #define SW_topnormal SW_surfacenormal(SEG_TOP) #define SW_toptexmove SW_surfacetexmove(SEG_TOP) #define SW_topoffset SW_surfaceoffset(SEG_TOP) #define SW_topvisoffset SW_surfacevisoffset(SEG_TOP) #define SW_toprgba SW_surfacergba(SEG_TOP) #define SW_bottomsurface SW_surface(SEG_BOTTOM) #define SW_bottomflags SW_surfaceflags(SEG_BOTTOM) #define SW_bottominflags SW_surfaceinflags(SEG_BOTTOM) #define SW_bottommaterial SW_surfacematerial(SEG_BOTTOM) #define SW_bottomnormal SW_surfacenormal(SEG_BOTTOM) #define SW_bottomtexmove SW_surfacetexmove(SEG_BOTTOM) #define SW_bottomoffset SW_surfaceoffset(SEG_BOTTOM) #define SW_bottomvisoffset SW_surfacevisoffset(SEG_BOTTOM) #define SW_bottomrgba SW_surfacergba(SEG_BOTTOM) end internal #define FRONT 0 #define BACK 1 typedef struct msidedef_s { // Sidedef index. Always valid after loading & pruning. int index; int refCount; } msidedef_t; end struct sidedef - surface_t[3] sections UINT uint segCount PTR seg_s** segs // [segcount] size, segs arranged left>right PTR linedef_s* line PTR sector_s* sector SHORT short flags - msidedef_t buildData # The following is used with FakeRadio. - int fakeRadioUpdateCount // frame number of last update - shadowcorner_t[2] topCorners - shadowcorner_t[2] bottomCorners - shadowcorner_t[2] sideCorners - edgespan_t[2] spans // [left, right] end internal // Helper macros for accessing linedef data elements. #define L_v(n) v[(n)] #define L_vpos(n) v[(n)]->V_pos #define L_v1 L_v(0) #define L_v1pos L_v(0)->V_pos #define L_v2 L_v(1) #define L_v2pos L_v(1)->V_pos #define L_vo(n) vo[(n)] #define L_vo1 L_vo(0) #define L_vo2 L_vo(1) #define L_side(n) sideDefs[(n)] #define L_frontside L_side(FRONT) #define L_backside L_side(BACK) #define L_sector(n) sideDefs[(n)]->sector #define L_frontsector L_sector(FRONT) #define L_backsector L_sector(BACK) // Is this line self-referencing (front sec == back sec)? #define LINE_SELFREF(l) ((l)->L_frontside && (l)->L_backside && \ (l)->L_frontsector == (l)->L_backsector) // Internal flags: #define LF_POLYOBJ 0x1 // Line is part of a polyobject. end internal #define MLF_TWOSIDED 0x1 // Line is marked two-sided. #define MLF_ZEROLENGTH 0x2 // Zero length (line should be totally ignored). #define MLF_SELFREF 0x4 // Sector is the same on both sides. #define MLF_POLYOBJ 0x8 // Line is part of a polyobj. typedef struct mlinedef_s { // Linedef index. Always valid after loading & pruning of zero // length lines has occurred. int index; int mlFlags; // MLF_* flags. // One-sided linedef used for a special effect (windows). // The value refers to the opposite sector on the back side. struct sector_s *windowEffect; // Normally NULL, except when this linedef directly overlaps an earlier // one (a rarely-used trick to create higher mid-masked textures). // No segs should be created for these overlapping linedefs. struct linedef_s *overlap; } mlinedef_t; end public #define DMT_LINEDEF_SEC DDVT_PTR end struct linedef PTR vertex_s*[2] v - lineowner_s*[2] vo // Links to vertex line owner nodes [left, right] PTR sidedef_s*[2] sideDefs INT int flags // Public DDLF_* flags. - byte inFlags // Internal LF_* flags INT slopetype_t slopeType INT int validCount - binangle_t angle // Calculated from front side's normal FLOAT float dX FLOAT float dY - float length // Accurate length FLOAT float[4] bBox - boolean[DDMAXPLAYERS] mapped // Whether the line has been mapped by each player yet. - mlinedef_t buildData - ushort[2] shadowVisFrame // Framecount of last time shadows were drawn for this line, for each side [right, left]. end internal #define RIGHT 0 #define LEFT 1 /** * An infinite line of the form point + direction vectors. */ typedef struct partition_s { float x, y; float dX, dY; } partition_t; end struct node - partition_t partition FLOAT float[2][4] bBox // Bounding box for each child. UINT uint[2] children // If NF_SUBSECTOR it's a subsector. end deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_play.h0000644000175000017500000000315711357170241023360 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_play.h: Game World Events (Playsim) */ #ifndef __DOOMSDAY_PLAYSIM__ #define __DOOMSDAY_PLAYSIM__ #include "p_mapdata.h" #include "p_vertex.h" #include "p_material.h" #include "p_surface.h" #include "p_sidedef.h" #include "p_linedef.h" #include "p_plane.h" #include "p_seg.h" #include "p_subsector.h" #include "p_sector.h" #include "p_polyobj.h" #include "p_dmu.h" #include "p_think.h" #include "p_object.h" #include "p_intercept.h" #include "p_maputil.h" #include "p_bmap.h" #include "p_particle.h" #include "p_polyob.h" #include "p_sight.h" #include "p_ticker.h" #include "p_players.h" #include "p_control.h" #include "p_cmd.h" #include "p_objlink.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/b_util.h0000644000175000017500000000647011357170241023222 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_util.h: Bindings */ #ifndef __DOOMSDAY_BIND_UTIL_H__ #define __DOOMSDAY_BIND_UTIL_H__ #include "de_base.h" #include "m_string.h" // Event Binding Toggle State typedef enum ebstate_e { EBTOG_UNDEFINED = 0, EBTOG_DOWN, EBTOG_REPEAT, EBTOG_PRESS, EBTOG_UP, EBAXIS_WITHIN, EBAXIS_BEYOND, EBAXIS_BEYOND_POSITIVE, EBAXIS_BEYOND_NEGATIVE } ebstate_t; typedef enum stateconditiontype_e { SCT_TOGGLE_STATE, ///< Toggle is in a specific state. SCT_MODIFIER_STATE, ///< Modifier is in a specific state. SCT_AXIS_BEYOND, ///< Axis is past a specific position. SCT_ANGLE_AT ///< Angle is pointing to a specific direction. } stateconditiontype_t; // Device state condition. typedef struct statecondition_s { uint device; // Which device? stateconditiontype_t type; boolean negate; // Test the inverse (e.g., not in a specific state). int id; // Toggle/axis/angle identifier in the device. ebstate_t state; float pos; // Axis position/angle condition. } statecondition_t; boolean B_ParseToggleState(const char* toggleName, ebstate_t* state); boolean B_ParseAxisPosition(const char* desc, ebstate_t* state, float* pos); boolean B_ParseKeyId(const char* desc, int* id); boolean B_ParseMouseTypeAndId(const char* desc, ddeventtype_t* type, int* id); boolean B_ParseJoystickTypeAndId(uint device, const char* desc, ddeventtype_t* type, int* id); boolean B_ParseAnglePosition(const char* desc, float* pos); boolean B_ParseStateCondition(statecondition_t* cond, const char* desc); boolean B_CheckAxisPos(ebstate_t test, float testPos, float pos); boolean B_CheckCondition(statecondition_t* cond, int localNum, struct bcontext_s* context); void B_AppendDeviceDescToString(uint device, ddeventtype_t type, int id, ddstring_t* str); void B_AppendToggleStateToString(ebstate_t state, ddstring_t* str); void B_AppendAxisPositionToString(ebstate_t state, float pos, ddstring_t* str); void B_AppendAnglePositionToString(float pos, ddstring_t* str); void B_AppendConditionToString(const statecondition_t* cond, ddstring_t* str); void B_AppendEventToString(const ddevent_t* ev, ddstring_t* str); #endif // __DOOMSDAY_BIND_UTIL_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_binarytree.h0000644000175000017500000000475311357170241024426 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_binarytree.h: A fairly standard binary tree implementation. */ #ifndef __BINARYTREE_H__ #define __BINARYTREE_H__ #ifdef __cplusplus extern "C" { #endif typedef void* binarytree_t; // Creation/destruction methods: binarytree_t *BinaryTree_Create(const void *data); binarytree_t *BinaryTree_Create2(const void *data, binarytree_t *initialRight, binarytree_t *initialLeft); void BinaryTree_Destroy(binarytree_t *node); // State management methods: binarytree_t *BinaryTree_GetChild(binarytree_t *tree, boolean left); void *BinaryTree_GetData(binarytree_t *tree); void BinaryTree_SetChild(binarytree_t *tree, boolean left, binarytree_t *subtree); void BinaryTree_SetData(binarytree_t *tree, const void *data); // Utility methods: boolean BinaryTree_IsLeaf(binarytree_t *tree); size_t BinaryTree_GetHeight(binarytree_t *tree); // Standard traversals: boolean BinaryTree_PreOrder(binarytree_t *tree, boolean (C_DECL *callback) (binarytree_t *tree, void *data), void *data); boolean BinaryTree_InOrder(binarytree_t *tree, boolean (C_DECL *callback) (binarytree_t *tree, void *data), void *data); boolean BinaryTree_PostOrder(binarytree_t *tree, boolean (C_DECL *callback) (binarytree_t *tree, void *data), void *data); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_cmd.h0000644000175000017500000000241411357170241023020 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_cmd.h: Tic Commands */ #ifndef __DOOMSDAY_PLAY_TIC_CMD_H__ #define __DOOMSDAY_PLAY_TIC_CMD_H__ // Ticcmd #define TICCMD_SIZE gx.ticcmdSize #define TICCMD_IDX(i) ((i)*TICCMD_SIZE) void P_BuildCommand(ticcmd_t *cmd, int playerNumber); void P_MergeCommand(ticcmd_t *dest, ticcmd_t *src); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/con_bind.h0000644000175000017500000000406111357170241023511 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * con_bind.h: Control Binding */ #ifndef __DOOMSDAY_CONSOLE_BIND_H__ #define __DOOMSDAY_CONSOLE_BIND_H__ #include #include "de_base.h" typedef enum { BND_UNUSED = -1, BND_COMMAND = 0, BND_AXIS, NUM_BIND_TYPES } bindtype_t; typedef struct { char *command[NUM_EVENT_STATES]; // { down, up, repeat } } bindcommand_t; typedef struct { int localPlayer; int playercontrol; boolean invert; } bindaxis_t; typedef struct { bindtype_t type; union { bindcommand_t command; bindaxis_t axiscontrol; } data; } bindcontrol_t; typedef struct { int controlID; // control index. bindcontrol_t *binds; // [maxBindClasses] size } binding_t; void B_Register(void); void B_Init(void); void DD_AddBindClass(struct bindclass_s *); boolean B_SetBindClass(uint classID, uint type); void B_RegisterBindClasses(void); char *B_ShortNameForKey(int ddkey); boolean B_Responder(ddevent_t *ev); void B_WriteToFile(FILE *file); void B_Shutdown(void); int DD_GetKeyCode(const char *key); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/net_msg.h0000644000175000017500000000337711357170241023403 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_msg.h: Network Messaging */ #ifndef __DOOMSDAY_NETMESSAGE_H__ #define __DOOMSDAY_NETMESSAGE_H__ void Msg_Begin(int type); void Msg_WriteByte(byte b); void Msg_WriteShort(short w); void Msg_WritePackedShort(short w); void Msg_WriteLong(int l); void Msg_WritePackedLong(unsigned int l); void Msg_Write(const void *src, size_t len); byte Msg_ReadByte(void); short Msg_ReadShort(void); short Msg_ReadPackedShort(void); int Msg_ReadLong(void); unsigned int Msg_ReadPackedLong(void); void Msg_Read(void *dest, size_t len); size_t Msg_Offset(void); void Msg_SetOffset(size_t offset); size_t Msg_MemoryLeft(void); boolean Msg_End(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/edit_map.h0000644000175000017500000001004311357170241023515 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * edit_map.h: Runtime map building. */ #ifndef __DOOMSDAY_MAP_EDITOR_H__ #define __DOOMSDAY_MAP_EDITOR_H__ #include "p_mapdata.h" #include "m_binarytree.h" #include "p_materialmanager.h" // Editable map. typedef struct editmap_s { char name[9]; uint numVertexes; vertex_t** vertexes; uint numLineDefs; linedef_t** lineDefs; uint numSideDefs; sidedef_t** sideDefs; uint numSectors; sector_t** sectors; uint numPolyObjs; polyobj_t** polyObjs; // The following is for game-specific map object data. gameobjdata_t gameObjData; } editmap_t; boolean MPE_Begin(const char *name); boolean MPE_End(void); uint MPE_VertexCreate(float x, float y); boolean MPE_VertexCreatev(size_t num, float *values, uint *indices); uint MPE_SidedefCreate(uint sector, short flags, materialnum_t topMaterial, float topOffsetX, float topOffsetY, float topRed, float topGreen, float topBlue, materialnum_t middleMaterial, float middleOffsetX, float middleOffsetY, float middleRed, float middleGreen, float middleBlue, float middleAlpha, materialnum_t bottomMaterial, float bottomOffsetX, float bottomOffsetY, float bottomRed, float bottomGreen, float bottomBlue); uint MPE_LinedefCreate(uint v1, uint v2, uint frontSide, uint backSide, int flags); uint MPE_SectorCreate(float lightlevel, float red, float green, float blue); uint MPE_PlaneCreate(uint sector, float height, materialnum_t material, float matOffsetX, float matOffsetY, float r, float g, float b, float a, float normalX, float normalY, float normalZ); uint MPE_PolyobjCreate(uint *lines, uint linecount, int tag, int sequenceType, float startX, float startY); boolean MPE_GameObjProperty(const char *objName, uint idx, const char *propName, valuetype_t type, void *data); // Non-public (temporary) // Flags for MPE_PruneRedundantMapData(). #define PRUNE_LINEDEFS 0x1 #define PRUNE_VERTEXES 0x2 #define PRUNE_SIDEDEFS 0x4 #define PRUNE_SECTORS 0x8 #define PRUNE_ALL (PRUNE_LINEDEFS|PRUNE_VERTEXES|PRUNE_SIDEDEFS|PRUNE_SECTORS) void MPE_PruneRedundantMapData(editmap_t *map, int flags); boolean MPE_RegisterUnclosedSectorNear(sector_t *sec, double x, double y); void MPE_PrintUnclosedSectorList(void); void MPE_FreeUnclosedSectorList(void); gamemap_t *MPE_GetLastBuiltMap(void); vertex_t *createVertex(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/b_command.h0000644000175000017500000000432011357170241023653 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_command.h: Event-Command Bindings */ #ifndef __DOOMSDAY_BIND_COMMAND_H__ #define __DOOMSDAY_BIND_COMMAND_H__ #include "b_util.h" typedef struct evbinding_s { struct evbinding_s* prev; // Previous in list of bindings. struct evbinding_s* next; // Next in list of bindings. int bid; // Binding identifier. char* command; // Command to execute. uint device; // Which device? ddeventtype_t type; // Type of event. int id; // Identifier. ebstate_t state; float pos; char* symbolicName; // Name of a symbolic event. // Additional conditions. int numConds; statecondition_t* conds; } evbinding_t; void B_InitCommandBindingList(evbinding_t* listRoot); void B_DestroyCommandBindingList(evbinding_t* listRoot); evbinding_t* B_NewCommandBinding(evbinding_t* listRoot, const char* desc, const char* command); void B_DestroyCommandBinding(evbinding_t* eb); void B_EventBindingToString(const evbinding_t* eb, ddstring_t* str); boolean B_TryCommandBinding(evbinding_t* eb, ddevent_t* event, struct bcontext_s* eventClass); #endif // __DOOMSDAY_BIND_COMMAND_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_dam.h0000644000175000017500000000221411357170241023145 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_dam.h: Doomsday Archived Map (DAM) subsystem */ #ifndef __DOOMSDAY_DAM__ #define __DOOMSDAY_DAM__ #include "dam_main.h" #include "dam_blockmap.h" #include "dam_file.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_console.h0000644000175000017500000000235711357170241024056 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_console.h: Console Subsystem */ #ifndef __DOOMSDAY_CONSOLE__ #define __DOOMSDAY_CONSOLE__ #include "con_decl.h" #include "con_buffer.h" #include "con_main.h" #include "con_config.h" #include "con_busy.h" #include "con_bar.h" #include "b_main.h" #include "b_context.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_string.h0000644000175000017500000000542011357170241023560 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * m_string.h: Dynamic Strings */ #ifndef __DOOMSDAY_DYN_STRING_H__ #define __DOOMSDAY_DYN_STRING_H__ // You can init with string constants, for example: // ddstring_t mystr = { "Hello world." }; typedef struct ddstring_s { char *str; size_t length; // String length (no terminating nulls). size_t size; // Allocated memory (not necessarily string size). } ddstring_t; // Format checking for Str_Appendf in GCC2 #if defined(__GNUC__) && __GNUC__ >= 2 # define PRINTF_F(f,v) __attribute__ ((format (printf, f, v))) #else # define PRINTF_F(f,v) #endif void Str_Init(ddstring_t *ds); void Str_Free(ddstring_t *ds); ddstring_t *Str_New(void); void Str_Delete(ddstring_t *ds); void Str_Clear(ddstring_t *ds); void Str_Reserve(ddstring_t *ds, size_t length); void Str_Set(ddstring_t *ds, const char *text); void Str_Append(ddstring_t *ds, const char *append_text); void Str_AppendChar(ddstring_t* ds, char ch); void Str_Appendf(ddstring_t * ds, const char *format, ...) PRINTF_F(2,3); void Str_PartAppend(ddstring_t *dest, const char *src, int start, size_t count); void Str_Prepend(ddstring_t *ds, const char *prepend_text); size_t Str_Length(ddstring_t *ds); char *Str_Text(ddstring_t *ds); void Str_Copy(ddstring_t *dest, ddstring_t *src); void Str_StripLeft(ddstring_t *ds); void Str_StripRight(ddstring_t *ds); void Str_Strip(ddstring_t *ds); const char *Str_GetLine(ddstring_t *ds, const char *src); const char *Str_CopyDelim(ddstring_t* dest, const char* src, char delim); int Str_CompareIgnoreCase(ddstring_t *ds, const char *text); char Str_At(ddstring_t* str, int index); char Str_RAt(ddstring_t* str, int reverseIndex); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_main.h0000644000175000017500000001264511357170241023353 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_main.h: Graphics Subsystem */ #ifndef __DOOMSDAY_GRAPHICS_H__ #define __DOOMSDAY_GRAPHICS_H__ #include "con_decl.h" #include "r_main.h" // This should be tweaked a bit. #define DEFAULT_FOG_START 0 #define DEFAULT_FOG_END 2100 #define DEFAULT_FOG_DENSITY 0.0001f #define DEFAULT_FOG_COLOR_RED 138.0f/255 #define DEFAULT_FOG_COLOR_GREEN 138.0f/255 #define DEFAULT_FOG_COLOR_BLUE 138.0f/255 typedef enum glfontstyle_e { GLFS_NORMAL, GLFS_BOLD, GLFS_LIGHT, NUM_GLFS } glfontstyle_t; extern int numTexUnits; extern boolean envModAdd; extern int defResX, defResY, defBPP, defFullscreen; extern int viewph, viewpw, viewpx, viewpy; extern int r_framecounter; extern char hiTexPath[], hiTexPath2[]; extern int UpdateState; extern float vid_gamma, vid_bright, vid_contrast; extern int glFontFixed, glFontVariable[NUM_GLFS]; extern int r_detail; boolean GL_IsInited(void); void GL_Register(void); boolean GL_EarlyInit(void); void GL_Init(void); void GL_Shutdown(void); void GL_TotalReset(void); void GL_TotalRestore(void); void GL_Init2DState(void); void GL_SwitchTo3DState(boolean push_state, viewport_t* port); void GL_Restore2DState(int step); void GL_ProjectionMatrix(void); void GL_RuntimeMode(void); void GL_DoUpdate(void); void GL_BlendMode(blendmode_t mode); void GL_InitRefresh(void); void GL_ShutdownRefresh(void); void GL_UseFog(int yes); //void GL_InitVarFont(void); //void GL_ShutdownVarFont(void); const char* GL_ChooseFixedFont(void); const char* GL_ChooseVariableFont(glfontstyle_t style, int resX, int resY); void GL_LowRes(void); void GL_ActiveTexture(const GLenum texture); void GL_ModulateTexture(int mode); void GL_SelectTexUnits(int count); void GL_SetTextureCompression(boolean on); void GL_SetVSync(boolean on); void GL_SetMultisample(boolean on); void GL_EnableTexUnit(byte id); void GL_DisableTexUnit(byte id); void GL_BlendOp(int op); void GL_SetGrayMipmap(int lev); boolean GL_EnablePalTexExt(boolean enable); boolean GL_NewList(DGLuint list, int mode); DGLuint GL_EndList(void); void GL_CallList(DGLuint list); void GL_DeleteLists(DGLuint list, int range); void GL_InitArrays(void); void GL_EnableArrays(int vertices, int colors, int coords); void GL_DisableArrays(int vertices, int colors, int coords); void GL_Arrays(void* vertices, void* colors, int numCoords, void** coords, int lock); void GL_UnlockArrays(void); void GL_ArrayElement(int index); void GL_DrawElements(dglprimtype_t type, int count, const uint* indices); boolean GL_Grab(int x, int y, int width, int height, dgltexformat_t format, void* buffer); boolean GL_TexImage(dgltexformat_t format, DGLuint palid, int width, int height, int genMips, void* data); int GL_GetTexAnisoMul(int level); DGLuint GL_CreateColorPalette(const int compOrder[3], const byte compSize[3], const byte* data, ushort num); void GL_DeleteColorPalettes(DGLsizei n, const DGLuint* palettes); void GL_GetColorPaletteRGB(DGLuint id, DGLubyte rgb[3], ushort idx); boolean GL_PalettizeImage(byte* out, int outformat, DGLuint palid, boolean gammaCorrect, const byte* in, int informat, int width, int height); boolean GL_QuantizeImageToPalette(byte* out, int outformat, DGLuint palid, const byte* in, int informat, int width, int height); void GL_DeSaturatePalettedImage(byte* buffer, DGLuint palid, int width, int height); // Returns a pointer to a copy of the screen. The pointer must be // deallocated by the caller. unsigned char* GL_GrabScreen(void); // Console commands. D_CMD(UpdateGammaRamp); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_audiod_dummy.h0000644000175000017500000000241211357170241025312 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_dummy.h: Dummy Music Driver. * * Used in dedicated server mode. */ #ifndef __DOOMSDAY_SYSTEM_AUDIO_DUMMY_H__ #define __DOOMSDAY_SYSTEM_AUDIO_DUMMY_H__ #include "sys_audiod.h" #include "sys_audiod_sfx.h" extern audiodriver_t audiod_dummy; extern audiointerface_sfx_t audiod_dummy_sfx; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_args.h0000644000175000017500000000316211357170241023207 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * m_args.h: Command Line Arguments */ #ifndef __COMMAND_LINE_ARGS_H__ #define __COMMAND_LINE_ARGS_H__ void ArgInit(const char* cmdline); void ArgShutdown(void); void ArgAbbreviate(const char* longname, const char* shortname); int Argc(void); const char* Argv(int i); const char** ArgvPtr(int i); const char* ArgNext(void); int ArgCheck(const char* check); int ArgCheckWith(const char* check, int num); int ArgExists(const char* check); int ArgIsOption(int i); int ArgRecognize(const char* first, const char* second); #endif //__COMMAND_LINE_ARGS_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_sidedef.h0000644000175000017500000000241211357170241023656 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sidedef.h: World sidedefs. */ #ifndef __DOOMSDAY_WORLD_SIDEDEF_H__ #define __DOOMSDAY_WORLD_SIDEDEF_H__ #include "r_data.h" #include "p_dmu.h" boolean Sidedef_GetProperty(const sidedef_t* sid, setargs_t* args); boolean Sidedef_SetProperty(sidedef_t* sid, const setargs_t* args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_model.h0000644000175000017500000001360211357170241023521 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * gl_model.h: 3D Model Constants and Data Structures * * Supported model formats: MD2 and DMD2. */ #ifndef __DOOMSDAY_MODEL_H__ #define __DOOMSDAY_MODEL_H__ #include "dd_types.h" #include "r_data.h" #define MD2_MAGIC 0x32504449 #define NUMVERTEXNORMALS 162 #define MAX_MODELS 768 // "DMDM" = Doomsday/Detailed MoDel Magic #define DMD_MAGIC 0x4D444D44 #define MAX_LODS 4 typedef struct { int magic; int version; int skinWidth; int skinHeight; int frameSize; int numSkins; int numVertices; int numTexCoords; int numTriangles; int numGlCommands; int numFrames; int offsetSkins; int offsetTexCoords; int offsetTriangles; int offsetFrames; int offsetGlCommands; int offsetEnd; } md2_header_t; typedef struct { byte vertex[3]; byte lightNormalIndex; } md2_triangleVertex_t; typedef struct { float scale[3]; float translate[3]; char name[16]; md2_triangleVertex_t vertices[1]; } md2_packedFrame_t; typedef struct { float vertex[3]; byte lightNormalIndex; } md2_modelVertex_t; // Translated frame (vertices in model space). typedef struct { char name[16]; md2_modelVertex_t *vertices; } md2_frame_t; typedef struct { char name[256]; int id; } md2_skin_t; typedef struct { short vertexIndices[3]; short textureIndices[3]; } md2_triangle_t; typedef struct { short s, t; } md2_textureCoordinate_t; typedef struct { float s, t; int vertexIndex; } md2_glCommandVertex_t; //=========================================================================== // DMD (Detailed/Doomsday Models) //=========================================================================== typedef struct { int magic; int version; int flags; } dmd_header_t; // Chunk types. enum { DMC_END, // Must be the last chunk. DMC_INFO // Required; will be expected to exist. }; typedef struct { int type; int length; // Next chunk follows... } dmd_chunk_t; typedef struct // DMC_INFO { int skinWidth; int skinHeight; int frameSize; int numSkins; int numVertices; int numTexCoords; int numFrames; int numLODs; int offsetSkins; int offsetTexCoords; int offsetFrames; int offsetLODs; int offsetEnd; } dmd_info_t; typedef struct { int numTriangles; int numGlCommands; int offsetTriangles; int offsetGlCommands; } dmd_levelOfDetail_t; #pragma pack(1) typedef struct { byte vertex[3]; unsigned short normal; // Yaw and pitch. } dmd_packedVertex_t; typedef struct { float scale[3]; float translate[3]; char name[16]; dmd_packedVertex_t vertices[1]; } dmd_packedFrame_t; #pragma pack() /*typedef struct { float vertex[3]; float normal[3]; } dmd_vertex_t; // Translated frame (vertices in model space). typedef struct { char name[16]; dmd_vertex_t *vertices; } dmd_frame_t; */ typedef struct { filename_t name; uint id; } dmd_skin_t; typedef struct { short vertexIndices[3]; short textureIndices[3]; } dmd_triangle_t; /*typedef struct { short s, t; } dmd_textureCoordinate_t;*/ typedef struct { float s, t; int vertexIndex; } dmd_glCommandVertex_t; typedef struct { //dmd_triangle_t *triangles; int *glCommands; } dmd_lod_t; typedef struct model_vertex_s { float xyz[3]; } model_vertex_t; typedef struct model_frame_s { char name[16]; model_vertex_t *vertices; model_vertex_t *normals; float min[3], max[3]; } model_frame_t; typedef struct model_s { boolean loaded; filename_t fileName; // Name of the md2 file. dmd_header_t header; dmd_info_t info; dmd_skin_t *skins; //dmd_textureCoordinate_t *texCoords; model_frame_t *frames; dmd_levelOfDetail_t lodInfo[MAX_LODS]; dmd_lod_t lods[MAX_LODS]; char *vertexUsage; // Bitfield for each vertex. boolean allowTexComp; // Allow texture compression with this. } model_t; extern model_t *modellist[MAX_MODELS]; extern float avertexnormals[NUMVERTEXNORMALS][3]; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_input.h0000644000175000017500000000541411357170241023776 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_input.h: Game Controllers */ #ifndef __DOOMSDAY_INPUT_H__ #define __DOOMSDAY_INPUT_H__ // Key event types. #define IKE_NONE 0 #define IKE_KEY_DOWN 0x1 #define IKE_KEY_UP 0x2 // Mouse buttons. (1=left, 2=middle, 3=right, 4=wheel up, 5=wheel down) #define IMB_MAXBUTTONS 16 // Joystick. #define IJOY_AXISMIN -10000 #define IJOY_AXISMAX 10000 #define IJOY_MAXAXES 32 #define IJOY_MAXBUTTONS 32 #define IJOY_MAXHATS 4 #define IJOY_POV_CENTER -1 typedef struct keyevent_s { char event; // Type of the event. byte ddkey; // The scancode (extended, corresponds DD_KEYs). } keyevent_t; typedef struct mousestate_s { int x, y; // Relative X and Y mickeys since last call. int buttonDowns[IMB_MAXBUTTONS]; // Button down count. int buttonUps[IMB_MAXBUTTONS]; // Button up count. } mousestate_t; typedef struct joystate_s { int numAxes; // Number of axes present. int numButtons; // Number of buttons present. int numHats; // Number of hats present. int axis[IJOY_MAXAXES]; int buttonDowns[IJOY_MAXBUTTONS]; // Button down count. int buttonUps[IJOY_MAXBUTTONS]; // Button up count. float hatAngle[IJOY_MAXHATS]; // 0 - 359 degrees. } joystate_t; extern byte usejoystick; void I_Register(void); boolean I_Init(void); void I_Shutdown(void); boolean I_MousePresent(void); boolean I_JoystickPresent(void); size_t I_GetKeyEvents(keyevent_t *evbuf, size_t bufsize); void I_GetMouseState(mousestate_t *state); void I_GetJoystickState(joystate_t * state); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_font.h0000644000175000017500000000616111357170241023371 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_font.h: Font Renderer */ #ifndef __GL_FONT_RENDERER_H__ #define __GL_FONT_RENDERER_H__ #ifdef WIN32 # ifndef WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN # define NOSOUND # define NOCOMM # define NOHELP # define NOCOLOR # define NOCLIPBOARD # define NOCTLMGR # define NOKERNEL # endif # include #endif #define MAX_CHARS 256 // Normal 256 ANSI characters. // Data for a character. typedef struct { int x, y; // The upper left corner of the character. int w, h; // The width and height. } jfrchar_t; // Data for a font. typedef struct { int id; char name[256]; DGLuint tex; // The name of the texture for this font. int texWidth, texHeight; boolean hasEmbeddedShadow; int marginWidth; int marginHeight; int lineHeight; int glyphHeight; int ascent; int descent; jfrchar_t chars[MAX_CHARS]; } jfrfont_t; int FR_Init(void); void FR_Shutdown(void); jfrfont_t* FR_GetFont(int id); #ifdef WIN32 // Prepare a GDI font. Select it as the current font. Only available // on Windows. int FR_PrepareGDIFont(HFONT hfont); #endif int FR_PrepareFont(const char* name); // Change the current font. void FR_SetFont(int id); int FR_GetCurrent(void); void FR_DestroyFont(int id); int FR_CharWidth(int ch); int FR_TextWidth(const char* text); int FR_TextHeight(const char* text); int FR_SingleLineHeight(const char* text); int FR_GlyphTopToAscent(const char* text); // (x,y) is the upper left corner. Returns the length. int FR_TextOut(const char* text, int x, int y); int FR_ShadowTextOut(const char* text, int x, int y); int FR_CustomShadowTextOut(const char* text, int x, int y, int shadowX, int shadowY, float shadowAlpha); #endif // __OGL_FONT_RENDERER_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_audiod_loader.h0000644000175000017500000000234511357170241025432 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_loader.h: Audio Driver, Loader. */ #ifndef __DOOMSDAY_SYSTEM_AUDIO_LOADER_H__ #define __DOOMSDAY_SYSTEM_AUDIO_LOADER_H__ #include "sys_audiod.h" audiodriver_t* Sys_LoadAudioDriver(const char* name); void Sys_ShutdownAudioDriver(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/con_buffer.h0000644000175000017500000000535111357170241024051 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * con_buffer.h: Console history buffer. */ #ifndef __DOOMSDAY_CONSOLE_BUFFER_H__ #define __DOOMSDAY_CONSOLE_BUFFER_H__ // A console buffer line. typedef struct cbline_s { uint len; // This is the length of the line (no term). char* text; // This is the text. int flags; } cbline_t; #define CBF_ALWAYSFLUSH 0x00000001 // don't leave data in the write buffer. // A console buffer. typedef struct { mutex_t mutex; int flags; // CBF_* flags. uint numLines; // How many lines are there in the buffer? uint maxLines; // Maximum number of lines for the buffer. uint maxLineLen; // Maximum length of a line. void* headptr; void* tailptr; void* unused; cbline_t** index; // Used when indexing the buffer for read. uint indexSize; boolean indexGood; // If the index needs updating. char* writebuf; // write buffer. uint wbc; // write buffer cursor. int wbFlags; // write buffer line flags. } cbuffer_t; cbuffer_t* Con_NewBuffer(uint maxNumLines, uint maxLineLength, int flags); void Con_DestroyBuffer(cbuffer_t* buf); void Con_BufferWrite(cbuffer_t* buf, int flags, const char* txt); void Con_BufferFlush(cbuffer_t* buf); void Con_BufferClear(cbuffer_t* buf); void Con_BufferSetMaxLineLength(cbuffer_t* buf, uint length); const cbline_t* Con_BufferGetLine(cbuffer_t* buf, uint idx); uint Con_BufferGetLines(cbuffer_t* buf, uint reqCount, int firstIdx, cbline_t const** list); uint Con_BufferNumLines(cbuffer_t* buf); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_audio.h0000644000175000017500000000230311357170241023504 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_audio.h: Audio Subsystem */ #ifndef __DOOMSDAY_AUDIO__ #define __DOOMSDAY_AUDIO__ #include "s_main.h" #include "s_environ.h" #include "s_sfx.h" #include "s_mus.h" #include "s_wav.h" #include "s_cache.h" #include "s_logic.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_linedef.h0000644000175000017500000000256611357170241023673 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_lindef.h: World linedefs. */ #ifndef __DOOMSDAY_WORLD_LINEDEF_H__ #define __DOOMSDAY_WORLD_LINEDEF_H__ #include "r_data.h" #include "p_dmu.h" void Linedef_LightLevelDelta(const linedef_t* lineDef, byte side, float* deltaL, float* deltaR); boolean Linedef_GetProperty(const linedef_t *lin, setargs_t *args); boolean Linedef_SetProperty(linedef_t *lin, const setargs_t *args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/def_share.h0000644000175000017500000001241011357170241023653 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * def_share.h: Shared Definition Data Structures and Constants */ #ifndef __DOOMSDAY_GAME_DATA_H__ #define __DOOMSDAY_GAME_DATA_H__ #include "dd_types.h" #define NUM_MOBJ_FLAGS 3 #define NUM_MOBJ_MISC 4 #define NUM_STATE_MISC 3 typedef struct { char name[5]; } sprname_t; typedef void (C_DECL * acfnptr_t) (); typedef struct state_s { int sprite; int flags; int frame; int tics; acfnptr_t action; int nextState; int misc[NUM_STATE_MISC]; } state_t; typedef enum { SN_SPAWN, SN_SEE, SN_PAIN, SN_MELEE, SN_MISSILE, SN_CRASH, SN_DEATH, SN_XDEATH, SN_RAISE, NUM_STATE_NAMES } statename_t; typedef struct { int doomEdNum; int spawnHealth; float speed; float radius; float height; int mass; int damage; int flags; int flags2; int flags3; int reactionTime; int painChance; int states[NUM_STATE_NAMES]; int painSound; int deathSound; int activeSound; int attackSound; int seeSound; int misc[NUM_MOBJ_MISC]; } mobjinfo_t; typedef struct { char lumpName[9]; int lumpNum; char* extFile; void* data; } musicinfo_t; typedef struct { char* text; // Pointer to the text (don't modify). } ddtext_t; // Map Info flags. #define MIF_FOG 0x1 // Fog is used in the map. #define MIF_DRAW_SPHERE 0x2 // Always draw the sky sphere. #define MIF_NO_INTERMISSION 0x4 // Skip any intermission between maps. typedef struct { char* name; char* author; int music; int flags; // MIF_* flags. float ambient; float gravity; float parTime; } ddmapinfo_t; typedef struct { char* after; char* before; int game; char* script; } ddfinale_t; typedef ddfinale_t finalescript_t; #define DDLT_MAX_APARAMS 10 #define DDLT_MAX_PARAMS 20 #define DDLT_MAX_SPARAMS 5 typedef struct { int id; int flags; int flags2; int flags3; int lineClass; int actType; int actCount; float actTime; int actTag; int aparm[DDLT_MAX_APARAMS]; float tickerStart, tickerEnd; int tickerInterval; int actSound, deactSound; int evChain, actChain, deactChain; int wallSection; materialnum_t actMaterial, deactMaterial; int actLineType, deactLineType; char* actMsg, *deactMsg; float materialMoveAngle; float materialMoveSpeed; int iparm[DDLT_MAX_PARAMS]; float fparm[DDLT_MAX_PARAMS]; char* sparm[DDLT_MAX_SPARAMS]; } linetype_t; #define DDLT_MAX_CHAINS 5 typedef struct { int id; int flags; int actTag; int chain[DDLT_MAX_CHAINS]; int chainFlags[DDLT_MAX_CHAINS]; float start[DDLT_MAX_CHAINS]; float end[DDLT_MAX_CHAINS]; float interval[DDLT_MAX_CHAINS][2]; int count[DDLT_MAX_CHAINS]; int ambientSound; float soundInterval[2]; // min,max float materialMoveAngle[2]; // floor, ceil float materialMoveSpeed[2]; // floor, ceil float windAngle; float windSpeed; float verticalWind; float gravity; float friction; char* lightFunc; int lightInterval[2]; char* colFunc[3]; // RGB int colInterval[3][2]; char* floorFunc; float floorMul, floorOff; int floorInterval[2]; char* ceilFunc; float ceilMul, ceilOff; int ceilInterval[2]; } sectortype_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_particle.h0000644000175000017500000000304011357170241024545 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_particle.h: Particle Effects */ #ifndef __DOOMSDAY_RENDER_PARTICLES_H__ #define __DOOMSDAY_RENDER_PARTICLES_H__ extern byte useParticles; extern int maxParticles; extern float particleSpawnRate; void Rend_ParticleRegister(void); void Rend_ParticleInitTextures(void); void Rend_ParticleShutdownTextures(void); void Rend_ParticleInitForNewFrame(void); void Rend_ParticleMarkInSectorVisible(sector_t* sector); void Rend_RenderParticles(void); // Debugging aid: void Rend_RenderGenerators(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/con_main.h0000644000175000017500000001226711357170241023530 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * con_main.h: Console Subsystem */ #ifndef __DOOMSDAY_CONSOLE_MAIN_H__ #define __DOOMSDAY_CONSOLE_MAIN_H__ #include #include "dd_share.h" #include "de_system.h" #include "dd_input.h" #include "con_buffer.h" #define CMDLINE_SIZE 256 #define MAX_ARGS 256 #define OBSOLETE CVF_NO_ARCHIVE|CVF_HIDE // Macros for accessing the console command values through the void ptr. #define CV_INT(var) (*(int*) var->ptr) #define CV_BYTE(var) (*(byte*) var->ptr) #define CV_FLOAT(var) (*(float*) var->ptr) #define CV_CHARPTR(var) (*(char**) var->ptr) typedef struct { char cmdLine[2048]; int argc; char *argv[MAX_ARGS]; } cmdargs_t; // Doomsday's internal representation of registered ccmds. typedef struct { const char *name; cvartype_t params[MAX_ARGS]; int (*func) (byte src, int argc, char **argv); int flags; int minArgs, maxArgs; } ddccmd_t; typedef enum { WT_CCMD, WT_CVAR, WT_CVARREADONLY, WT_ALIAS, WT_BINDCONTEXT } knownwordtype_t; typedef struct knownword_S { char word[64]; // 64 chars MAX for words. knownwordtype_t type; } knownword_t; typedef struct calias_s { char *name; char *command; } calias_t; // Console commands can set this when they need to return a custom value // e.g. for the game dll. extern int CmdReturnValue; extern ddfont_t Cfont; extern byte consoleDump; void Con_DataRegister(void); void Con_DestroyDatabases(void); ddccmd_t *Con_GetCommand(cmdargs_t *args); void Con_AddCommand(ccmd_t *cmd); void Con_AddVariable(cvar_t *var); void Con_AddCommandList(ccmd_t *cmdlist); void Con_AddVariableList(cvar_t *varlist); calias_t *Con_AddAlias(const char *aName, const char *command); void Con_DeleteAlias(calias_t *cal); void Con_PrintCVar(cvar_t *var, char *prefix); boolean Con_IsValidCommand(const char *name); void Con_PrintCCmdUsage(ddccmd_t *ccmd, boolean showExtra); calias_t *Con_GetAlias(const char *name); cvar_t *Con_GetVariable(const char *name); cvar_t *Con_GetVariableIDX(unsigned int idx); unsigned int Con_CVarCount(void); int Con_GetInteger(const char *name); float Con_GetFloat(const char *name); byte Con_GetByte(const char *name); char *Con_GetString(const char *name); void Con_SetInteger(const char *name, int value, byte override); void Con_SetFloat(const char *name, float value, byte override); void Con_SetString(const char *name, char *text, byte override); boolean Con_Init(void); void Con_Shutdown(void); void Con_AbnormalShutdown(const char* message); void Con_WriteAliasesToFile(FILE * file); void Con_SetMaxLineLength(void); void Con_Open(int yes); boolean Con_IsActive(void); boolean Con_IsLocked(void); boolean Con_InputMode(void); uint Con_CursorPosition(void); char *Con_GetCommandLine(void); cbuffer_t *Con_GetConsoleBuffer(void); boolean Con_IsSpecialChar(int ch); void Con_UpdateKnownWords(void); knownword_t **Con_CollectKnownWordsMatchingWord(const char *word, unsigned int *count); void Con_Ticker(timespan_t time); boolean Con_Responder(ddevent_t *event); void Con_Printf(const char *format, ...) PRINTF_F(1,2); void Con_FPrintf(int flags, const char *format, ...) PRINTF_F(2,3); // Flagged printf. int Con_PrintFileName(const char *fn, filetype_t type, void *dir); void Con_SetFont(ddfont_t *cfont); float Con_FontScaleY(void); cbline_t *Con_GetBufferLine(cbuffer_t *buffer, int num); int Con_Execute(byte src, const char *command, int silent, boolean netCmd); int Con_Executef(byte src, int silent, const char *command, ...); void Con_Message(const char *message, ...) PRINTF_F(1,2); void Con_Error(const char *error, ...) PRINTF_F(1,2); char *TrimmedFloat(float val); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_sky.h0000644000175000017500000000301511357170241023063 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * r_sky.h: Sky Management */ #ifndef __DOOMSDAY_REFRESH_SKY_H__ #define __DOOMSDAY_REFRESH_SKY_H__ #include "r_model.h" typedef struct skymodel_s { ded_skymodel_t *def; modeldef_t *model; int frame; int timer; int maxTimer; float yaw; } skymodel_t; extern skymodel_t skyModels[NUM_SKY_MODELS]; extern boolean skyModelsInited; extern boolean alwaysDrawSphere; void R_SetupSkyModels(ded_sky_t* sky); void R_PrecacheSky(void); void R_SkyTicker(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_input.h0000644000175000017500000001745611357170241023560 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_input.h: Input Subsystem */ #ifndef __DOOMSDAY_BASEINPUT_H__ #define __DOOMSDAY_BASEINPUT_H__ #include "con_decl.h" #define NUMKKEYS 256 // Input devices. enum { IDEV_KEYBOARD = 0, IDEV_MOUSE, IDEV_JOY1, IDEV_JOY2, IDEV_JOY3, IDEV_JOY4, NUM_INPUT_DEVICES // Theoretical maximum. }; typedef enum ddeventtype_e { E_TOGGLE, // Two-state device E_AXIS, // Axis position E_ANGLE, // Hat angle E_SYMBOLIC // Symbolic event } ddeventtype_t; typedef enum ddeevent_togglestate_e { ETOG_DOWN, ETOG_UP, ETOG_REPEAT } ddevent_togglestate_t; typedef enum ddevent_axistype_e { EAXIS_ABSOLUTE, // Absolute position on the axis EAXIS_RELATIVE // Offset relative to the previous position } ddevent_axistype_t; // These are used internally, a cutdown version containing // only need-to-know metadata is sent down the games' responder chain. typedef struct ddevent_s { uint device; // e.g. IDEV_KEYBOARD ddeventtype_t type; // E_TOGGLE, E_AXIS, E_ANGLE, or E_SYMBOLIC union { struct { int id; // Button/key index number ddevent_togglestate_t state;// State of the toggle } toggle; struct { int id; // Axis index number float pos; // Position of the axis ddevent_axistype_t type; // Type of the axis (absolute or relative) } axis; struct { int id; // Angle index number float pos; // Angle, or negative if centered } angle; struct { int id; // Console that originated the event. const char* name; // Symbolic name of the event. } symbolic; }; } ddevent_t; // Convenience macros. #define IS_TOGGLE_DOWN(evp) (evp->type == E_TOGGLE && evp->toggle.state == ETOG_DOWN) #define IS_TOGGLE_DOWN_ID(evp, togid) (evp->type == E_TOGGLE && evp->toggle.state == ETOG_DOWN && evp->toggle.id == togid) #define IS_TOGGLE_UP(evp) (evp->type == E_TOGGLE && evp->toggle.state == ETOG_UP) #define IS_TOGGLE_REPEAT(evp) (evp->type == E_TOGGLE && evp->toggle.state == ETOG_REPEAT) #define IS_KEY_TOGGLE(evp) (evp->device == IDEV_KEYBOARD && evp->type == E_TOGGLE) #define IS_KEY_DOWN(evp) (evp->device == IDEV_KEYBOARD && evp->type == E_TOGGLE && evp->toggle.state == ETOG_DOWN) #define IS_KEY_PRESS(evp) (evp->device == IDEV_KEYBOARD && evp->type == E_TOGGLE && evp->toggle.state != ETOG_UP) #define IS_MOUSE_DOWN(evp) (evp->device == IDEV_MOUSE && IS_TOGGLE_DOWN(evp)) #define IS_MOUSE_UP(evp) (evp->device == IDEV_MOUSE && IS_TOGGLE_UP(evp)) #define IS_MOUSE_MOTION(evp) (evp->device == IDEV_MOUSE && evp->type == E_AXIS) // Binding association. How the device axis/key/etc. relates to binding contexts. typedef struct inputdevassoc_s { struct bcontext_s* bContext; struct bcontext_s* prevBContext; int flags; } inputdevassoc_t; // Association flags. #define IDAF_EXPIRED 0x1 // The state has expired. The device is considered to remain // in default state until the flag gets cleared (which happens when // the real device state returns to its default). // Input device axis types. enum { IDAT_STICK = 0, // Joysticks, gamepads IDAT_POINTER = 1 // Mouse }; // Input device axis flags. #define IDA_DISABLED 0x1 // Axis is always zero. #define IDA_INVERT 0x2 // Real input data should be inverted. typedef struct inputdevaxis_s { char name[20]; // Symbolic name of the axis. int type; // Type of the axis (pointer or stick). int flags; float position; // Current translated position of the axis (-1..1) including any filtering. float realPosition; // The actual position of the axis (-1..1). float scale; // Scaling factor for real input values. float deadZone; // Dead zone, in (0..1) range. int filter; // Filter grade. float accumulation; // Position accumulator for the filter. uint time; // Timestamp for the latest update that changed the position. inputdevassoc_t assoc; // Binding association. } inputdevaxis_t; typedef struct inputdevkey_s { char isDown; // True/False for each key. uint time; inputdevassoc_t assoc; // Binding association. const char* name; // Symbolic name. } inputdevkey_t; typedef struct inputdevhat_s { int pos; // Position of each hat, -1 if centered. uint time; // Timestamp for each hat for the latest change. inputdevassoc_t assoc; // Binding association. } inputdevhat_t; // Input device flags. #define ID_ACTIVE 0x1 // The input device is active. typedef struct inputdev_s { char name[20]; // Symbolic name of the device. int flags; uint numAxes; // Number of axes in this input device. inputdevaxis_t *axes; uint numKeys; // Number of keys for this input device. inputdevkey_t *keys; uint numHats; // NUmber of hats. inputdevhat_t *hats; } inputdev_t; extern boolean ignoreInput; extern int repWait1, repWait2; extern int keyRepeatDelay1, keyRepeatDelay2; // milliseconds extern boolean shiftDown, altDown; void DD_RegisterInput(void); void DD_InitInput(void); void DD_ShutdownInput(void); void DD_StartInput(void); void DD_StopInput(void); void DD_ReadKeyboard(void); void DD_ReadMouse(timespan_t ticLength); void DD_ReadJoystick(void); void DD_PostEvent(ddevent_t *ev); void DD_ProcessEvents(timespan_t ticLength); void DD_ClearEvents(void); void DD_ClearKeyRepeaters(void); byte DD_ModKey(byte key); void DD_ConvertEvent(const ddevent_t* ddEvent, event_t* ev); void I_InitVirtualInputDevices(void); void I_ShutdownInputDevices(void); void I_ClearDeviceContextAssociations(void); void I_DeviceReset(uint ident); inputdev_t *I_GetDevice(uint ident, boolean ifactive); inputdev_t *I_GetDeviceByName(const char *name, boolean ifactive); boolean I_ParseDeviceAxis(const char *str, uint *deviceID, uint *axis); inputdevaxis_t *I_GetAxisByID(inputdev_t *device, uint id); int I_GetAxisByName(inputdev_t *device, const char *name); int I_GetKeyByName(inputdev_t* device, const char* name); float I_TransformAxis(inputdev_t* dev, uint axis, float rawPos); boolean I_IsDeviceKeyDown(uint ident, uint code); void I_SetUIMouseMode(boolean on); void I_TrackInput(ddevent_t *ev, timespan_t ticLength); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/bsp_edge.h0000644000175000017500000001061711357170241023512 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_edge.h: Choose the best half-edge to use for a node line. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ #ifndef __BSP_EDGE_H__ #define __BSP_EDGE_H__ #define IFFY_LEN 4.0 // Smallest distance between two points before being considered equal. #define DIST_EPSILON (1.0 / 128.0) // Smallest degrees between two angles before being considered equal. #define ANG_EPSILON (1.0 / 1024.0) #define ET_prev link[0] #define ET_next link[1] #define ET_edge hEdges // An edge tip is where an edge meets a vertex. typedef struct edgetip_s { // Link in list. List is kept in ANTI-clockwise order. struct edgetip_s* link[2]; // {prev, next}; // Angle that line makes at vertex (degrees). angle_g angle; // Half-edge on each side of the edge. Left is the side of increasing // angles, right is the side of decreasing angles. Either can be NULL // for one sided edges. struct hedge_s* hEdges[2]; } edgetip_t; typedef struct hedge_s { vertex_t* v[2]; // [Start, End] of the half-edge.. // Half-edge on the other side, or NULL if one-sided. This relationship // is always one-to-one -- if one of the half-edges is split, the twin // must also be split. struct hedge_s* twin; struct hedge_s* next; struct hedge_s* nextOnSide; struct hedge_s* prevOnSide; // Index of the half-edge. Only valid once the half-edge has been added // to a polygon. A negative value means it is invalid -- there // shouldn't be any of these once the BSP tree has been built. int index; // The superblock that contains this half-edge, or NULL if the half-edge // is no longer in any superblock (e.g. now in a subsector). struct superblock_s* block; // Precomputed data for faster calculations. double pSX, pSY; double pEX, pEY; double pDX, pDY; double pLength; double pAngle; double pPara; double pPerp; // Linedef that this half-edge goes along, or NULL if miniseg. linedef_t* lineDef; // Linedef that this half-edge initially comes from. // For "real" half-edges, this is just the same as the 'linedef' field // above. For "miniedges", this is the linedef of the partition line. linedef_t* sourceLine; sector_t* sector; // Adjacent sector, or NULL if invalid sidedef or minihedge. byte side; // 0 for right, 1 for left. } hedge_t; void BSP_InitHEdgeAllocator(void); void BSP_ShutdownHEdgeAllocator(void); hedge_t* HEdge_Create(linedef_t* line, linedef_t* sourceLine, vertex_t* start, vertex_t* end, sector_t* sec, boolean back); void HEdge_Destroy(hedge_t* hEdge); hedge_t* HEdge_Split(hedge_t* oldHEdge, double x, double y); // Edge tip functions: void BSP_CreateVertexEdgeTip(vertex_t* vert, double dx, double dy, hedge_t* back, hedge_t* front); void BSP_DestroyVertexEdgeTip(struct edgetip_s* tip); sector_t* BSP_VertexCheckOpen(vertex_t* vert, double dx, double dy); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_system.h0000644000175000017500000000450311357170241024161 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Jamie Jones *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_system.h: OS Specific Services Subsystem */ #ifndef __DOOMSDAY_SYSTEM_H__ #define __DOOMSDAY_SYSTEM_H__ #include "dd_types.h" typedef void* thread_t; typedef intptr_t mutex_t; typedef intptr_t sem_t; typedef int (C_DECL *systhreadfunc_t) (void* parm); extern int novideo; void Sys_Init(void); void Sys_Shutdown(void); void Sys_Quit(void); int Sys_CriticalMessage(char* msg); void Sys_Sleep(int millisecs); void Sys_ShowCursor(boolean show); void Sys_HideMouse(void); void Sys_MessageBox(const char* msg, boolean iserror); void Sys_OpenTextEditor(const char* filename); thread_t Sys_StartThread(systhreadfunc_t startpos, void* parm); void Sys_SuspendThread(thread_t handle, boolean dopause); int Sys_WaitThread(thread_t handle); uint Sys_ThreadID(void); mutex_t Sys_CreateMutex(const char* name); void Sys_DestroyMutex(mutex_t mutexHandle); void Sys_Lock(mutex_t mutexHandle); void Sys_Unlock(mutex_t mutexHandle); sem_t Sem_Create(uint32_t initialValue); // returns handle void Sem_Destroy(sem_t semaphore); void Sem_P(sem_t semaphore); void Sem_V(sem_t semaphore); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_texmanager.h0000644000175000017500000002200411357170241024550 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_texmanager.h: Texture Management */ #ifndef __DOOMSDAY_TEXTURE_MANAGER_H__ #define __DOOMSDAY_TEXTURE_MANAGER_H__ #include "r_data.h" #include "r_model.h" #include "r_extres.h" #include "con_decl.h" #include "gl_model.h" #include "gl_defer.h" #define TEXQ_BEST 8 /** * gltexture * * Presents an abstract interface to all supported texture types so that * they may be managed transparently. */ typedef enum { GLT_ANY = -1, GLT_SYSTEM, // system texture e.g., the "missing" texture. GLT_FLAT, GLT_DOOMTEXTURE, GLT_SPRITE, GLT_DETAIL, GLT_SHINY, GLT_MASK, GLT_MODELSKIN, GLT_MODELSHINYSKIN, GLT_LIGHTMAP, GLT_FLARE, NUM_GLTEXTURE_TYPES } gltexture_type_t; #define GLTEXTURE_TYPE_STRING(t) ((t) == GLT_FLAT? "flat" : \ (t) == GLT_DOOMTEXTURE? "doomtexture" : \ (t) == GLT_SPRITE? "sprite" : \ (t) == GLT_DETAIL? "detailtex" : \ (t) == GLT_SHINY? "shinytex" : \ (t) == GLT_MASK? "masktex" : \ (t) == GLT_MODELSKIN? "modelskin" : \ (t) == GLT_MODELSHINYSKIN? "modelshinyskin" : \ (t) == GLT_LIGHTMAP? "lightmap" : \ (t) == GLT_FLARE? "flaretex" : "systemtex") typedef struct gltexture_s { gltextureid_t id; char name[9]; gltexture_type_t type; int ofTypeID; void* instances; uint hashNext; // 1-based index } gltexture_t; // gltexture flags: #define GLTF_MASKED 0x1 typedef struct gltexture_inst_s { DGLuint id; // Name of the associated DGL texture. byte flags; // GLTF_* flags. const gltexture_t* tex; union { struct { float color[3]; // Average color (for lighting). float topColor[3]; // Averaged top line color, used for sky fadeouts. } texture; // also used with GLT_FLAT. struct { boolean pSprite; // @c true, iff this is for use as a psprite. float flareX, flareY, lumSize; rgbcol_t autoLightColor; float texCoord[2]; // Prepared texture coordinates. int tmap, tclass; // Color translation. } sprite; struct { float contrast; } detail; } data; // type-specific data. } gltexture_inst_t; /** * This structure is used with GL_LoadImage. When it is no longer needed * it must be discarded with GL_DestroyImage. */ typedef struct image_s { filename_t fileName; int width; int height; int pixelSize; boolean isMasked; int originalBits; // Bits per pixel in the image file. byte* pixels; } image_t; extern int ratioLimit; extern int mipmapping, linearRaw, texQuality, filterSprites; extern int texMagMode, texAniso; extern int useSmartFilter; extern byte loadExtAlways; extern int texMagMode; extern int upscaleAndSharpenPatches; extern int glmode[6]; void GL_TexRegister(void); void GL_EarlyInitTextureManager(void); void GL_InitTextureManager(void); void GL_ResetTextureManager(void); void GL_ShutdownTextureManager(void); void GL_TexReset(void); void GL_LoadSystemTextures(void); void GL_ClearTextureMemory(void); void GL_ClearRuntimeTextures(void); void GL_ClearSystemTextures(void); void GL_DeleteRawImages(void); int GL_InitPalettedTexture(void); void GL_DoTexReset(cvar_t* unused); void GL_DoUpdateTexGamma(cvar_t* unused); void GL_DoUpdateTexParams(cvar_t* unused); void GL_UpdateTexParams(int mipmode); void GL_BindTexture(DGLuint texname, int magMode); void GL_SetNoTexture(void); void GL_SetTextureParams(int minMode, int gameTex, int uiTex); boolean GL_IsColorKeyed(const char* path); byte* GL_LoadImage(image_t* img, const char* imagefn); void GL_DestroyImage(image_t* img); DGLuint GL_UploadTexture(byte* data, int width, int height, boolean flagAlphaChannel, boolean flagGenerateMipmaps, boolean flagRgbData, boolean flagNoStretch, boolean flagNoSmartFilter, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT, int otherFlags); DGLuint GL_UploadTexture2(texturecontent_t *content); byte GL_LoadFlat(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadDoomTexture(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadSprite(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadDDTexture(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadShinyTexture(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadMaskTexture(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadDetailTexture(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadModelSkin(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadModelShinySkin(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadLightMap(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadFlareTexture(image_t* image, const gltexture_inst_t* inst, void* context); byte GL_LoadDoomPatch(image_t* image, const patchtex_t* p); byte GL_LoadRawTex(image_t* image, const rawtex_t* r); byte GL_LoadExtTexture(image_t* image, ddresourceclass_t resClass, const char* name, gfxmode_t mode); DGLuint GL_PrepareExtTexture(ddresourceclass_t resClass, const char* name, gfxmode_t mode, int useMipmap, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT, int otherFlags); DGLuint GL_PrepareLSTexture(lightingtexid_t which); DGLuint GL_PrepareSysFlareTexture(flaretexid_t flare); DGLuint GL_PreparePatch(patchtex_t* patch); DGLuint GL_PreparePatchOtherPart(patchtex_t* patch); DGLuint GL_PrepareRawTex(rawtex_t* rawTex); DGLuint GL_PrepareRawTexOtherPart(rawtex_t* rawTex); DGLuint GL_GetLightMapTexture(const char* name); DGLuint GL_GetFlareTexture(const char* name, int oldIdx); void GL_SetMaterial(material_t* mat); void GL_SetPSprite(material_t* mat); void GL_SetTranslatedSprite(material_t* mat, int tclass, int tmap); void GL_SetPatch(lumpnum_t lump, int wrapS, int wrapT); // No mipmaps are generated. void GL_SetRawImage(lumpnum_t lump, boolean part2, int wrapS, int wrapT); // Management of and access to gltextures (via the texmanager): const gltexture_t* GL_CreateGLTexture(const char* name, int ofTypeID, gltexture_type_t type); void GL_ReleaseGLTexture(gltextureid_t id); const gltexture_inst_t* GL_PrepareGLTexture(gltextureid_t id, void* context, byte* result); const gltexture_t* GL_GetGLTexture(gltextureid_t id); const gltexture_t* GL_GetGLTextureByName(const char* name, gltexture_type_t type); void GL_SetAllGLTexturesMinMode(int minMode); void GL_DeleteAllTexturesForGLTextures(gltexture_type_t); /// \todo should not be visible outside the texmanager? float GLTexture_GetWidth(const gltexture_t* tex); float GLTexture_GetHeight(const gltexture_t* tex); boolean GLTexture_IsFromIWAD(const gltexture_t* tex); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_graphics.h0000644000175000017500000000245411357170241024212 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_graphics.h: Graphics Subsystem */ #ifndef __DOOMSDAY_GRAPHICS__ #define __DOOMSDAY_GRAPHICS__ #include "gl_main.h" #include "gl_draw.h" #include "gl_texmanager.h" #include "gl_tex.h" #include "gl_hq2x.h" #include "gl_font.h" #include "gl_model.h" #include "gl_pcx.h" #include "gl_png.h" #include "gl_tga.h" #include "gl_defer.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/net_demo.h0000644000175000017500000000333611357170241023534 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_demo.h: Demos */ #ifndef __DOOMSDAY_DEMO_H__ #define __DOOMSDAY_DEMO_H__ #include "con_decl.h" extern int playback; void Demo_Register(void); void Demo_Init(void); void Demo_Ticker(timespan_t time); boolean Demo_BeginRecording(const char* filename, int playernum); void Demo_StopRecording(int playernum); void Demo_PauseRecording(int playernum); void Demo_ResumeRecording(int playernum); void Demo_WritePacket(int playernum); void Demo_BroadcastPacket(void); void Demo_ReadLocalCamera(void); // PKT_DEMOCAM boolean Demo_BeginPlayback(const char* filename); boolean Demo_ReadPacket(void); void Demo_StopPlayback(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sv_frame.h0000644000175000017500000000232211357170241023536 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_frame.h: Frame Generation and Transmission */ #ifndef __DOOMSDAY_SERVER_FRAME_H__ #define __DOOMSDAY_SERVER_FRAME_H__ extern int bwrAdjustTime; void Sv_TransmitFrame(void); size_t Sv_GetMaxFrameSize(int playerNumber); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_sight.h0000644000175000017500000000234111357170241023372 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_play.h: Line of Sight Testing */ #ifndef __DOOMSDAY_PLAY_SIGHT_H__ #define __DOOMSDAY_PLAY_SIGHT_H__ boolean P_CheckLineSight(const float from[3], const float to[3], float bottomSlope, float topSlope, int flags); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/s_logic.h0000644000175000017500000000243411357170241023357 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * s_logic.h: The Logical Sound Manager */ #ifndef __DOOMSDAY_SOUND_LOGICAL_H__ #define __DOOMSDAY_SOUND_LOGICAL_H__ void Sfx_InitLogical(void); void Sfx_PurgeLogical(void); void Sfx_StartLogical(int id, mobj_t *origin, boolean isRepeating); int Sfx_StopLogical(int id, mobj_t *origin); boolean Sfx_IsPlaying(int id, mobj_t *origin); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sv_sound.h0000644000175000017500000000374311357170241023604 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * sv_sound.h: Serverside Sound Management */ #ifndef __DOOMSDAY_SERVER_SOUND_H__ #define __DOOMSDAY_SERVER_SOUND_H__ // Sound packet (PSV_SOUND) flags. #define SNDF_ORIGIN 0x01 // Sound has an origin. #define SNDF_SECTOR 0x02 // Originates from a degenmobj. #define SNDF_PLAYER 0x04 // Originates from a player. #define SNDF_VOLUME 0x08 // Volume included. #define SNDF_ID 0x10 // Mobj ID of the origin. #define SNDF_REPEATING 0x20 // Repeat sound indefinitely. #define SNDF_SHORT_SOUND_ID 0x40 // Sound ID is a short. // Stop Sound packet (PSV_STOP_SOUND) flags. #define STOPSNDF_SOUND_ID 0x01 #define STOPSNDF_ID 0x02 #define STOPSNDF_SECTOR 0x04 // Sv_Sound toPlr flags. #define SVSF_TO_ALL 0x01000000 #define SVSF_EXCLUDE_ORIGIN 0x02000000 // Sound is not sent to origin player. #define SVSF_MASK 0x7fffffff void Sv_Sound(int sound_id, mobj_t *origin, int toPlr); void Sv_SoundAtVolume(int sound_id_and_flags, mobj_t *origin, float volume, int toPlr); void Sv_StopSound(int sound_id, mobj_t *origin); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_dyn.h0000644000175000017500000000506611357170241023546 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_dyn.h: Dynamic Lights. */ #ifndef __DOOMSDAY_DYNLIGHTS_H__ #define __DOOMSDAY_DYNLIGHTS_H__ #include "p_object.h" #include "rend_list.h" #define DYN_ASPECT (1.1f) // 1.2f is just too round for Doom. #define MAX_GLOWHEIGHT (1024.0f) // Absolute max glow height. // Flags for DL_ProjectOnSurface #define DLF_SORT_LUMADSC 0x1 // Sort dynlights by luma, brightest to dullest. #define DLF_NO_PLANAR 0x2 // Surface is not lit by planar lights. #define DLF_TEX_FLOOR 0x4 // Prefer the "floor" slot when picking textures. #define DLF_TEX_CEILING 0x8 // Prefer the "ceiling" slot when picking textures. /** * The data of a projected dynamic light is stored in this structure. * A list of these is associated with each surface lit by texture mapped lights * in a frame. */ typedef struct dynlight_s { float s[2], t[2]; float color[3]; DGLuint texture; } dynlight_t; extern int useDynLights, dlBlend; extern float dlFactor, dlFogBright; extern int useWallGlow, glowHeightMax; extern float glowHeightFactor; // Initialization void DL_Register(void); // Setup. void DL_InitForMap(void); void DL_InitForNewFrame(void); // Action. uint DL_ProjectOnSurface(subsector_t* ssec, const vectorcomp_t topLeft[3], const vectorcomp_t bottomRight[3], const vectorcomp_t normal[3], byte flags); // Helpers. boolean DL_ListIterator(uint listIdx, void* data, boolean (*func) (const dynlight_t*, void*)); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_ticker.h0000644000175000017500000000215711357170241023542 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * p_ticker.h: Timed Playsim Events */ #ifndef __DOOMSDAY_PLAY_TICKER_H__ #define __DOOMSDAY_PLAY_TICKER_H__ void P_Ticker(timespan_t time); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_audiod_sdlmixer.h0000644000175000017500000000270111357170241026007 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006-2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audiod_sdlmixer.h: Default Audio Driver. * * Uses SDL_mixer, for SFX, Ext and Mus interfaces. */ #ifndef __DOOMSDAY_SYSTEM_AUDIO_SDLMIXER_H__ #define __DOOMSDAY_SYSTEM_AUDIO_SDLMIXER_H__ #include "sys_audiod.h" #include "sys_audiod_sfx.h" #include "sys_audiod_mus.h" extern audiodriver_t audiod_sdlmixer; extern audiointerface_sfx_t audiod_sdlmixer_sfx; extern audiointerface_music_t audiod_sdlmixer_music; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_profiler.h0000644000175000017500000000437111357170241024100 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * m_profiler.h: Utility Macros for Profiling */ #ifndef __DOOMSDAY_MISC_PROFILER_H__ #define __DOOMSDAY_MISC_PROFILER_H__ #include "dd_types.h" #include "sys_timer.h" /* * This header defines some handy macros for profiling. * Define DD_PROFILE to active. */ typedef struct profiler_s { uint totalTime; uint startTime; uint startCount; } profiler_t; #define BEGIN_PROF_TIMERS() enum { #ifdef DD_PROFILE // Profiling is enabled. # define END_PROF_TIMERS() ,NUM_PROFS }; static profiler_t profiler_[NUM_PROFS]; # define BEGIN_PROF(x) (profiler_[x].startCount++, profiler_[x].startTime = Sys_GetRealTime()) # define END_PROF(x) (profiler_[x].totalTime += Sys_GetRealTime() - profiler_[x].startTime) # define PRINT_PROF(x) Con_Message("[%f ms] " #x ": %i ms (%i starts)\n", \ profiler_[x].startCount? profiler_[x].totalTime / \ (float) profiler_[x].startCount : 0, \ profiler_[x].totalTime, profiler_[x].startCount) #else // Profiling is disabled. # define END_PROF_TIMERS() ,NUM_PROFS }; # define BEGIN_PROF(x) # define END_PROF(x) # define PRINT_PROF(x) #endif // DD_PROFILE #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_file.h0000644000175000017500000000461111357170241023554 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_file.h: File Stream Abstraction Layer * * Data can be read from memory, virtual files or actual files. */ #ifndef __FILE_IO_H__ #define __FILE_IO_H__ #include #define deof(file) ((file)->flags.eof != 0) typedef struct { struct DFILE_flags_s { unsigned char open:1; unsigned char file:1; unsigned char eof:1; } flags; size_t size; void *data; char *pos; unsigned int lastModified; } DFILE; typedef enum filetype_e { FT_NORMAL, FT_DIRECTORY } filetype_t; typedef int (*f_forall_func_t) (const char *fn, filetype_t type, void *parm); void F_InitMapping(void); void F_AddMapping(const char* source, const char* destination); void F_InitDirec(void); void F_ShutdownDirec(void); int F_Access(const char *path); DFILE *F_Open(const char *path, const char *mode); void F_Close(DFILE *file); size_t F_Length(DFILE *file); size_t F_Read(void *dest, size_t count, DFILE *file); unsigned char F_GetC(DFILE *file); size_t F_Tell(DFILE *file); size_t F_Seek(DFILE *file, size_t offset, int whence); void F_Rewind(DFILE *file); int F_ForAll(const char *filespec, void *parm, f_forall_func_t func); unsigned int F_LastModified(const char *fileName); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/def_main.h0000644000175000017500000000734711357170241023512 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * def_main.h: Definitions Subsystem. */ #ifndef __DOOMSDAY_DEFINITIONS_MAIN_H__ #define __DOOMSDAY_DEFINITIONS_MAIN_H__ #include "def_data.h" typedef struct sfxinfo_s { void* data; // Pointer to sound data. int lumpNum; char lumpName[9]; // Actual lump name of the sound (full name). char id[32]; // Identifier name (from the def). char name[32]; // Long name. struct sfxinfo_s* link; // Link to another sound. int linkPitch; int linkVolume; int priority; int channels; // Max. channels for the sound to occupy. int usefulness; // Used to determine when to cache out. int flags; int group; char external[256]; // Path to external file. } sfxinfo_t; extern ded_t defs; // The main definitions database. extern sprname_t* sprNames; // Sprite name list. extern state_t* states; // State list. extern ded_light_t** stateLights; extern ded_ptcgen_t** statePtcGens; extern mobjinfo_t* mobjInfo; // Map object info database. extern sfxinfo_t* sounds; // Sound effect list. extern ddtext_t* texts; // Text list. extern mobjinfo_t** stateOwners; extern ded_count_t countSprNames; extern ded_count_t countStates; void Def_Init(void); void Def_PostInit(void); // Destroy databases. void Def_Destroy(void); void Def_GetAutoPath(char* path, size_t len); // Reads the specified definition file, and creates the sprite name, // state, mobjinfo, sound, music and text databases accordingly. void Def_Read(void); void Def_ReadProcessDED(const char* fileName); int Def_GetMobjNum(const char* id); int Def_GetMobjNumForName(const char* name); int Def_GetStateNum(const char* id); int Def_GetSpriteNum(const char* name); int Def_GetModelNum(const char* id); int Def_GetMusicNum(const char* id); int Def_GetSoundNum(const char* id); int Def_EvalFlags(char* ptr); ded_mapinfo_t* Def_GetMapInfo(const char* mapID); ded_sky_t* Def_GetSky(const char* id); ded_material_t* Def_GetMaterial(const char* name, material_namespace_t group); ded_light_t* Def_GetLightDef(int spr, int frame); ded_decor_t* Def_GetDecoration(material_t* mat, boolean hasExt); ded_reflection_t* Def_GetReflection(material_t* mat, boolean hasExt); ded_detailtexture_t* Def_GetDetailTex(material_t* mat, boolean hasExt); ded_ptcgen_t* Def_GetGenerator(material_t* mat, boolean hasExt); ded_ptcgen_t* Def_GetDamageGenerator(int mobjType); int Def_Get(int type, const char* id, void* out); boolean Def_SameStateSequence(state_t* snew, state_t* sold); D_CMD(ListMobjs); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_fakeradio.h0000644000175000017500000000343511357170241024677 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_fakeradio.h: Faked Radiosity Lighting */ #ifndef __DOOMSDAY_RENDER_FAKERADIO_H__ #define __DOOMSDAY_RENDER_FAKERADIO_H__ typedef struct { const float* sectorLightLevel; const shadowcorner_t* botCn, *topCn, *sideCn; const edgespan_t* spans; const float* segOffset; const float* segLength; const float* linedefLength; const sector_t* frontSec, *backSec; } rendsegradio_params_t; void Rend_RadioRegister(void); void Rend_RadioUpdateLinedef(linedef_t* line, boolean backSide); void Rend_RadioSegSection(const rvertex_t* rvertices, const walldiv_t* divs, const rendsegradio_params_t* params); void Rend_RadioSubsectorEdges(subsector_t* subsector); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_gridmap.h0000644000175000017500000000375511357170241023706 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_gridmap.h: Generalized blockmap */ #ifndef __DOOMSDAY_MISC_GRIDMAP_H__ #define __DOOMSDAY_MISC_GRIDMAP_H__ typedef void* gridmap_t; gridmap_t *M_GridmapCreate(uint width, uint height, size_t sizeOfBlock, int memzoneTag); void M_GridmapDestroy(gridmap_t *gridmap); void *M_GridmapGetBlock(gridmap_t *gridmap, uint x, uint y, boolean alloc); // Iteration boolean M_GridmapIterator(gridmap_t *gridmap, boolean (*callback) (void* p, void *ctx), void *param); boolean M_GridmapBoxIterator(gridmap_t *gridmap, uint xl, uint xh, uint yl, uint yh, boolean (*callback) (void* p, void *ctx), void *param); boolean M_GridmapBoxIteratorv(gridmap_t *gridmap, const uint box[4], boolean (*callback) (void* p, void *ctx), void *param); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dam_main.h0000644000175000017500000000531011357170241023501 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dam_main.h: Doomsday Archived Map (DAM) reader */ #ifndef __DOOMSDAY_ARCHIVED_MAP_MAIN_H__ #define __DOOMSDAY_ARCHIVED_MAP_MAIN_H__ enum { ML_INVALID = -1, ML_LABEL, // A separator, name, ExMx or MAPxx ML_THINGS, // Monsters, items.. ML_LINEDEFS, // LineDefs, from editing ML_SIDEDEFS, // SideDefs, from editing ML_VERTEXES, // Vertices, edited and BSP splits generated ML_SEGS, // LineSegs, from LineDefs split by BSP ML_SSECTORS, // SubSectors, list of LineSegs ML_NODES, // BSP nodes ML_SECTORS, // Sectors, from editing ML_REJECT, // LUT, sector-sector visibility ML_BLOCKMAP, // LUT, motion clipping, walls/grid element ML_BEHAVIOR, // ACS Scripts (compiled). ML_SCRIPTS, // ACS Scripts (source). ML_LIGHTS, // Surface color tints. ML_MACROS, // DOOM64 format, macro scripts. ML_LEAFS, // DOOM64 format, segs (close subsectors). NUM_MAPLUMPS }; typedef struct maplumpformat_s { int hversion; char *formatName; int lumpClass; } maplumpformat_t; typedef struct maplumpinfo_s { int lumpNum; maplumpformat_t *format; int lumpClass; int startOffset; uint elements; size_t length; } maplumpinfo_t; typedef struct listnode_s { void *data; struct listnode_s *next; } listnode_t; typedef struct archivedmap_s { char identifier[9]; int numLumps; int *lumpList; filename_t cachedMapDataFile; boolean cachedMapFound; boolean lastLoadAttemptFailed; } archivedmap_t; extern byte mapCache; void DAM_Register(void); void DAM_Init(void); void DAM_Shutdown(void); void DAM_GetCachedMapDir(char* dir, int mainLump, size_t len); boolean DAM_AttemptMapLoad(const char* mapID); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_mus2midi.h0000644000175000017500000000223011357170241023777 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_mus2midi.h: MUS to MIDI conversion */ #ifndef __DOOMSDAY_MUS2MIDI_H__ #define __DOOMSDAY_MUS2MIDI_H__ boolean M_Mus2Midi(void* data, size_t length, const char* outFile); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_network.h0000644000175000017500000000647711357170241024342 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_network.h: Low-Level Network Services */ #ifndef __DOOMSDAY_SYSTEM_NETWORK_H__ #define __DOOMSDAY_SYSTEM_NETWORK_H__ #include "dd_share.h" #include "net_buf.h" #ifdef __cplusplus extern "C" { #endif #include "con_decl.h" #define DEFAULT_TCP_PORT 13209 #define DEFAULT_UDP_PORT 13209 // If a master action fails, the action queue is emptied. typedef enum { MAC_REQUEST, // Retrieve the list of servers from the master. MAC_WAIT, // Wait for the server list to arrive. MAC_LIST // Print the server list in the console. } masteraction_t; extern size_t maxDatagramSize; extern boolean allowSending; extern int maxQueuePackets; extern boolean netServerMode; extern char *nptIPAddress; extern int nptIPPort; extern int nptUDPPort; extern char *serverName, *serverInfo, *playerName; extern int serverData[]; extern char *masterAddress; extern int masterPort; extern char *masterPath; void N_Register(void); void N_SystemInit(void); void N_SystemShutdown(void); boolean N_InitService(boolean inServerMode); void N_ShutdownService(void); boolean N_IsAvailable(void); boolean N_UsingInternet(void); void N_PrintInfo(void); boolean N_LookForHosts(const char *address, int port); void N_Listen(void); boolean N_Connect(int index); boolean N_Disconnect(void); boolean N_ServerOpen(void); boolean N_ServerClose(void); void N_SendDataBuffer(void *data, size_t size, nodeid_t destination); void N_SendDataBufferReliably(void *data, size_t size, nodeid_t destination); void N_ReturnBuffer(void *handle); uint N_GetSendQueueCount(int player); uint N_GetSendQueueSize(int player); void N_TerminateNode(nodeid_t id); void N_FlushOutgoing(void); boolean N_GetNodeName(nodeid_t id, char *name); const char *N_GetProtocolName(void); int N_GetHostCount(void); boolean N_GetHostInfo(int index, struct serverinfo_s *info); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_edit.h0000644000175000017500000000214511357170241023334 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_edit.h: Editor subsystems */ #ifndef __DOOMSDAY_EDITOR__ #define __DOOMSDAY_EDITOR__ #include "edit_bias.h" #include "edit_map.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_loop.h0000644000175000017500000000303611357170241023357 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_loop.h: Main Loop */ #ifndef __DOOMSDAY_BASELOOP_H__ #define __DOOMSDAY_BASELOOP_H__ extern boolean appShutdown; #ifdef WIN32 extern boolean suspendMsgPump; #endif extern int rFrameCount; extern timespan_t sysTime, gameTime, demoTime, ddMapTime; extern trigger_t sharedFixedTrigger; extern boolean tickFrame; void DD_RegisterLoop(void); int DD_GameLoop(void); void DD_DrawAndBlit(void); void DD_StartFrame(void); void DD_EndFrame(void); float DD_GetFrameRate(void); void DD_ResetTimer(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/s_main.h0000644000175000017500000000604311357170241023206 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_main.h: Sound Subsystem */ #ifndef __DOOMSDAY_SOUND_MAIN_H__ #define __DOOMSDAY_SOUND_MAIN_H__ #include "con_decl.h" #include "p_object.h" #include "def_main.h" #include "sys_audiod.h" #define SF_RANDOM_SHIFT 0x1 // Random frequency shift. #define SF_RANDOM_SHIFT2 0x2 // 2x bigger random frequency shift. #define SF_GLOBAL_EXCLUDE 0x4 // Exclude all emitters. #define SF_NO_ATTENUATION 0x8 // Very, very loud... #define SF_REPEAT 0x10 // Repeats until stopped. #define SF_DONT_STOP 0x20 // Sound can't be stopped while playing. extern int showSoundInfo; extern int soundMinDist, soundMaxDist; extern int sfxVolume, musVolume; extern audiodriver_t* audioDriver; void S_Register(void); boolean S_Init(void); void S_Shutdown(void); void S_MapChange(void); void S_Reset(void); void S_StartFrame(void); void S_EndFrame(void); sfxinfo_t* S_GetSoundInfo(int sound_id, float* freq, float* volume); mobj_t* S_GetListenerMobj(void); int S_LocalSoundAtVolumeFrom(int sound_id, mobj_t* origin, float* fixedpos, float volume); int S_LocalSoundAtVolume(int sound_id, mobj_t* origin, float volume); int S_LocalSound(int sound_id, mobj_t* origin); int S_LocalSoundFrom(int sound_id, float* fixedpos); int S_StartSound(int soundId, mobj_t* origin); int S_StartSoundEx(int soundId, mobj_t* origin); int S_StartSoundAtVolume(int sound_id, mobj_t* origin, float volume); int S_ConsoleSound(int sound_id, mobj_t* origin, int target_console); void S_StopSound(int sound_id, mobj_t* origin); int S_IsPlaying(int sound_id, mobj_t* emitter); int S_StartMusic(const char* musicid, boolean looped); void S_StopMusic(void); void S_PauseMusic(boolean paused); void S_Drawer(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_sky.h0000644000175000017500000000410611357170241023554 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_sky.h: Sky Sphere and 3D Models */ #ifndef __DOOMSDAY_SKY_H__ #define __DOOMSDAY_SKY_H__ // Sky hemispheres. #define SKYHEMI_UPPER 0x1 #define SKYHEMI_LOWER 0x2 #define SKYHEMI_JUST_CAP 0x4 // Just draw the top or bottom cap. #define SKYHEMI_FADEOUT_BG 0x8 // Draw the fadeout bg when drawing the cap. typedef struct { float rgb[3]; // The RGB values. short set, use; // Is this set? Should be used? float limit; // .3 by default. } fadeout_t; // Sky layer flags. #define SLF_ENABLED 0x1 // Layer enabled. #define SLF_MASKED 0x2 // Mask the layer texture. typedef struct { int flags; material_t* mat; float offset; fadeout_t fadeout; } skylayer_t; extern int skyDetail; // Initialization: void Rend_SkyRegister(void); // Functions: void Rend_InitSky(void); void Rend_ShutdownSky(void); void Rend_SkyDetail(int quarterDivs, int rows); void Rend_SkyParams(int layer, int param, void* data); void Rend_RenderSky(int hemis); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_direc.h0000644000175000017500000000331211357170241023720 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_direc.h: Directory Utilities */ #ifndef __DOOMSDAY_DIREC_H__ #define __DOOMSDAY_DIREC_H__ #include "dd_types.h" void Dir_GetDir(directory_t* dir); int Dir_ChDir(directory_t* dir); void Dir_FileDir(const char* str, directory_t* dir); void Dir_FileName(char* name, const char* str, size_t len); void Dir_MakeDir(const char* path, directory_t* dir); void Dir_FileID(const char* str, byte identifier[16]); void Dir_FixSlashes(char* path, size_t len); void Dir_ValidDir(char* str, size_t len); boolean Dir_IsEqual(directory_t* a, directory_t* b); int Dir_IsAbsolute(const char* str); void Dir_MakeAbsolute(char* path, size_t len); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_lgrid.h0000644000175000017500000000264611357170241023367 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_lgrid.h: Ambient world lighting (smoothed sector lighting). */ #ifndef __DOOMSDAY_REFRESH_LIGHT_GRID_H__ #define __DOOMSDAY_REFRESH_LIGHT_GRID_H__ void LG_Register(void); void LG_Init(void); void LG_Update(void); void LG_MarkAllForUpdate(cvar_t *unused); void LG_SectorChanged(sector_t *sector); void LG_Evaluate(const float *point, float *destColor); void LG_Debug(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/cl_mobj.h0000644000175000017500000000554711357170241023355 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_mobj.h: Client Map Objects */ #ifndef __DOOMSDAY_CLIENT_MOBJ_H__ #define __DOOMSDAY_CLIENT_MOBJ_H__ // Flags for clmobjs. #define CLMF_HIDDEN 0x01 // Not officially created yet #define CLMF_UNPREDICTABLE 0x02 // Temporarily hidden (until next delta) #define CLMF_SOUND 0x04 // Sound is queued for playing on unhide. #define CLMF_NULLED 0x08 // Once nulled, it can't be updated. #define CLMF_STICK_FLOOR 0x10 // Mobj will stick to the floor. #define CLMF_STICK_CEILING 0x20 // Mobj will stick to the ceiling. // Clmobj knowledge flags. This keeps track of the information that has been // received. #define CLMF_KNOWN_X 0x10000 #define CLMF_KNOWN_Y 0x20000 #define CLMF_KNOWN_Z 0x40000 #define CLMF_KNOWN_STATE 0x80000 #define CLMF_KNOWN 0xf0000 // combination of all the KNOWN-flags typedef struct clmobj_s { struct clmobj_s *next, *prev; int flags; uint time; // Time of last update. int sound; // Queued sound ID. float volume; // Volume for queued sound. mobj_t mo; } clmobj_t; void Cl_InitClientMobjs(void); void Cl_Reset(void); void Cl_DestroyClientMobjs(void); clmobj_t *Cl_CreateMobj(thid_t id); void Cl_DestroyMobj(clmobj_t *cmo); boolean Cl_MobjIterator(boolean (*callback) (clmobj_t *, void *), void *parm); void Cl_PredictMovement(void); void Cl_UnsetMobjPosition(clmobj_t *cmo); void Cl_SetMobjPosition(clmobj_t *cmo); int Cl_ReadMobjDelta(void); void Cl_ReadMobjDelta2(boolean skip); void Cl_ReadNullMobjDelta2(boolean skip); clmobj_t *Cl_FindMobj(thid_t id); void Cl_CheckMobj(clmobj_t *cmo, boolean justCreated); void Cl_UpdateRealPlayerMobj(mobj_t *mo, mobj_t *clmo, int flags); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_players.h0000644000175000017500000000314511357170241023736 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_players.h: Players */ #ifndef __DOOMSDAY_PLAYERS_H__ #define __DOOMSDAY_PLAYERS_H__ typedef struct player_s { byte extraLightCounter; // Num tics to go till extraLight is disabled. int extraLight, targetExtraLight; ddplayer_t shared; // The public player data. } player_t; extern player_t *viewPlayer; extern player_t ddPlayers[DDMAXPLAYERS]; extern int consolePlayer; extern int displayPlayer; int P_LocalToConsole(int localPlayer); int P_ConsoleToLocal(int playerNum); int P_GetDDPlayerIdx(ddplayer_t *ddpl); boolean P_IsInVoid(player_t *p); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_bias.h0000644000175000017500000000761411357170241023673 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_bias.h: Light/Shadow Bias */ #ifndef __DOOMSDAY_RENDER_SHADOW_BIAS_H__ #define __DOOMSDAY_RENDER_SHADOW_BIAS_H__ #include "m_vector.h" #define MAX_BIAS_LIGHTS (8 * 32) // Hard limit due to change tracking. #define MAX_BIAS_TRACKED (MAX_BIAS_LIGHTS / 8) #define MAX_BIAS_AFFECTED (6) typedef struct vilight_s { short source; float color[3]; // Light from an affecting source. } vilight_t; // Vertex illumination flags. #define VIF_LERP 0x1 // Interpolation is in progress. #define VIF_STILL_UNSEEN 0x2 // The color of the vertex is still unknown. typedef struct vertexillum_s { float color[3]; // Current color of the vertex. float dest[3]; // Destination color of the vertex. uint updatetime; // When the value was calculated. short flags; vilight_t casted[MAX_BIAS_AFFECTED]; } vertexillum_t; typedef struct biasaffection_s { short source; // Index of light source. } biasaffection_t; // Bias light source macros. #define BLF_COLOR_OVERRIDE 0x00000001 #define BLF_LOCKED 0x40000000 #define BLF_CHANGED 0x80000000 typedef struct source_s { int flags; float pos[3]; float color[3]; float intensity; float primaryIntensity; float sectorLevel[2]; uint lastUpdateTime; } source_t; typedef struct biastracker_s { uint changes[MAX_BIAS_TRACKED]; } biastracker_t; struct rendpoly_s; struct rvertex_s; struct rcolor_s; extern int useBias; // Bias lighting enabled. extern uint currentTimeSB; void SB_Register(void); void SB_InitForMap(const char* uniqueId); void SB_InitVertexIllum(vertexillum_t* villum); struct biassurface_s* SB_CreateSurface(void); void SB_DestroySurface(struct biassurface_s* bsuf); void SB_SurfaceMoved(struct biassurface_s* bsuf); void SB_BeginFrame(void); void SB_RendPoly(struct rcolor_s* rcolors, struct biassurface_s* bsuf, const struct rvertex_s* rvertices, size_t numVertices, const vectorcomp_t* normal, float sectorLightLevel, void* mapObject, uint elmIdx, boolean isSeg); void SB_EndFrame(void); int SB_NewSourceAt(float x, float y, float z, float size, float minLight, float maxLight, float* rgb); void SB_UpdateSource(int which, float x, float y, float z, float size, float minLight, float maxLight, float* rgb); void SB_Delete(int which); void SB_Clear(void); source_t* SB_GetSource(int which); int SB_ToIndex(source_t* source); void SB_SetColor(float* dest, float* src); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_objlink.h0000644000175000017500000000345511357170241023713 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_objlink.h: Objlink management. */ #ifndef __DOOMSDAY_OBJLINK_H__ #define __DOOMSDAY_OBJLINK_H__ typedef enum { OT_MOBJ, OT_LUMOBJ, NUM_OBJ_TYPES } objtype_t; void R_InitObjLinksForMap(void); void R_ClearObjLinksForFrame(void); void R_ObjLinkCreate(void* obj, objtype_t type); void R_LinkObjs(void); void R_InitForSubsector(subsector_t* ssec); void R_InitForNewFrame(void); typedef struct { void* obj; objtype_t type; } linkobjtossecparams_t; boolean RIT_LinkObjToSubSector(subsector_t* subsector, void* params); boolean R_IterateSubsectorContacts(subsector_t* ssec, objtype_t type, boolean (*func) (void*, void*), void* data); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_sector.h0000644000175000017500000000240211357170241023551 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sector.h: World sectors. */ #ifndef __DOOMSDAY_WORLD_SECTOR_H__ #define __DOOMSDAY_WORLD_SECTOR_H__ #include "r_data.h" #include "p_dmu.h" boolean Sector_GetProperty(const sector_t *sec, setargs_t *args); boolean Sector_SetProperty(sector_t *sec, const setargs_t *args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_sock.h0000644000175000017500000000325711357170241023601 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * sys_sock.h: TCP/IP Sockets */ #ifndef __DOOMSDAY_SYSTEM_SOCKET_H__ #define __DOOMSDAY_SYSTEM_SOCKET_H__ #include "dd_types.h" // DJS - this was unsigned, however socket() will return a signed // value depending on the outcome. Which we check against a signed // value in several places in the code. typedef int socket_t; void N_SockInit(void); void N_SockShutdown(void); void N_SockPrintf(socket_t s, const char *format, ...) PRINTF_F(2,3); struct hostent *N_SockGetHost(const char *hostName); socket_t N_SockNewStream(void); boolean N_SockConnect(socket_t s, struct hostent *host, unsigned short port); void N_SockClose(socket_t s); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_surface.h0000644000175000017500000000376511357170241023717 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_surface.h: World surfaces. */ #ifndef __DOOMSDAY_REFRESH_SURFACE_H__ #define __DOOMSDAY_REFRESH_SURFACE_H__ #include "r_data.h" #include "p_dmu.h" boolean Surface_GetProperty(const surface_t* suf, setargs_t* args); boolean Surface_SetProperty(surface_t* suf, const setargs_t* args); void Surface_Update(surface_t* suf); boolean Surface_SetMaterial(surface_t* suf, material_t* mat); boolean Surface_SetMaterialOffsetX(surface_t* suf, float x); boolean Surface_SetMaterialOffsetY(surface_t* suf, float y); boolean Surface_SetMaterialOffsetXY(surface_t* suf, float x, float y); boolean Surface_SetColorR(surface_t* suf, float r); boolean Surface_SetColorG(surface_t* suf, float g); boolean Surface_SetColorB(surface_t* suf, float b); boolean Surface_SetColorA(surface_t* suf, float a); boolean Surface_SetColorRGBA(surface_t* suf, float r, float g, float b, float a); boolean Surface_SetBlendMode(surface_t* suf, blendmode_t blendMode); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sv_pool.h0000644000175000017500000003313111357170241023417 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_pool.h: Delta Pools */ #ifndef __DOOMSDAY_SERVER_POOL_H__ #define __DOOMSDAY_SERVER_POOL_H__ #include "dd_share.h" #include "p_object.h" #include "r_data.h" #include "p_materialmanager.h" // Prefer adding new flags inside the deltas instead of adding new delta types. typedef enum { DT_MOBJ = 0, DT_PLAYER = 1, DT_SECTOR_R6 = 2, // 2 bytes for flags. DT_SIDE_R6 = 3, // 1 byte for flags. DT_POLY = 4, DT_LUMP = 5, DT_SOUND = 6, // No emitter DT_MOBJ_SOUND = 7, DT_SECTOR_SOUND = 8, DT_POLY_SOUND = 9, DT_SECTOR = 10, // Flags in a packed long. // Special types: (only in the PSV_FRAME2 packet when written to message) DT_NULL_MOBJ = 11, // Mobj was removed (just type and ID). DT_CREATE_MOBJ = 12, // Regular DT_MOBJ, but the mobj was just created. DT_SIDE = 13, // Flags in a packed long. NUM_DELTA_TYPES } deltatype_t; // OR'd with the type number when resending Unacked deltas. #define DT_RESENT 0x80 // Mobj delta flags. These are used to determine what a delta contains. // (Which parts of a delta mobj_t are used.) #define MDF_POS_X 0x0001 #define MDF_POS_Y 0x0002 #define MDF_POS_Z 0x0004 #define MDF_POS 0x0007 #define MDF_MOM_X 0x0008 #define MDF_MOM_Y 0x0010 #define MDF_MOM_Z 0x0020 #define MDF_MOM 0x0038 #define MDF_ANGLE 0x0040 #define MDF_LONG_FLOORCLIP 0x0080 #define MDF_MORE_FLAGS 0x0100 // A byte of extra flags follows. #define MDF_SELSPEC 0x0200 // Only during transfer. #define MDF_SELECTOR 0x0400 #define MDF_STATE 0x0800 #define MDF_RADIUS 0x1000 #define MDF_HEIGHT 0x2000 #define MDF_FLAGS 0x4000 #define MDF_FLOORCLIP 0x8000 // Mobj Delta Control flags (not included directly in the frame). #define MDFC_NULL 0x10000 // The delta is not defined. #define MDFC_CREATE 0x20000 // Mobj didn't exist before. #define MDFC_TRANSLUCENCY 0x40000 // Mobj has translucency. #define MDFC_FADETARGET 0x80000 // Mobj is fading to/from visible/invisible // Extra flags for the Extra Flags byte. #define MDFE_FAST_MOM 0x01 // Momentum has 10.6 bits (+/- 512) #define MDFE_TRANSLUCENCY 0x02 #define MDFE_Z_FLOOR 0x04 // Mobj z is on the floor. #define MDFE_Z_CEILING 0x08 // Mobj z+hgt is in the ceiling. #define MDFE_FADETARGET 0x10 // The flags that are not included when a mobj is the viewpoint. #define MDF_CAMERA_EXCLUDE 0x0e00 // The flags that are not included for hidden mobjs. #define MDF_DONTDRAW_EXCLUDE 0x0ec0 #define PDF_MOBJ 0x0001 #define PDF_FORWARDMOVE 0x0002 #define PDF_SIDEMOVE 0x0004 #define PDF_ANGLE 0x0008 #define PDF_TURNDELTA 0x0010 #define PDF_FRICTION 0x0020 #define PDF_EXTRALIGHT 0x0040 // Plus fixedcolormap (same byte). #define PDF_FILTER 0x0080 #define PDF_CLYAW 0x1000 // Sent in the player num byte. #define PDF_CLPITCH 0x2000 // Sent in the player num byte. #define PDF_PSPRITES 0x4000 // Sent in the player num byte. // Written separately, stored in playerdelta flags 2 highest bytes. #define PSDF_STATEPTR 0x01 #define PSDF_OFFSET 0x08 #define PSDF_LIGHT 0x20 #define PSDF_ALPHA 0x40 #define PSDF_STATE 0x80 // The flags that are not included when a player is the viewpoint. #define PDF_CAMERA_EXCLUDE 0x001e // The flags that are not included when a player is not the viewpoint. #define PDF_NONCAMERA_EXCLUDE 0x70de #define SDF_FLOOR_MATERIAL 0x00000001 #define SDF_CEILING_MATERIAL 0x00000002 #define SDF_LIGHT 0x00000004 #define SDF_FLOOR_TARGET 0x00000008 #define SDF_FLOOR_SPEED 0x00000010 #define SDF_CEILING_TARGET 0x00000020 #define SDF_CEILING_SPEED 0x00000040 #define SDF_FLOOR_TEXMOVE 0x00000080 #define SDF_CEILING_TEXMOVE 0x00000100 #define SDF_COLOR_RED 0x00000200 #define SDF_COLOR_GREEN 0x00000400 #define SDF_COLOR_BLUE 0x00000800 #define SDF_FLOOR_SPEED_44 0x00001000 // Used for sent deltas. #define SDF_CEILING_SPEED_44 0x00002000 // Used for sent deltas. #define SDF_FLOOR_HEIGHT 0x00004000 #define SDF_CEILING_HEIGHT 0x00008000 #define SDF_FLOOR_COLOR_RED 0x00010000 #define SDF_FLOOR_COLOR_GREEN 0x00020000 #define SDF_FLOOR_COLOR_BLUE 0x00040000 #define SDF_CEIL_COLOR_RED 0x00080000 #define SDF_CEIL_COLOR_GREEN 0x00100000 #define SDF_CEIL_COLOR_BLUE 0x00200000 #define SDF_FLOOR_GLOW_RED 0x00400000 #define SDF_FLOOR_GLOW_GREEN 0x00800000 #define SDF_FLOOR_GLOW_BLUE 0x01000000 #define SDF_CEIL_GLOW_RED 0x02000000 #define SDF_CEIL_GLOW_GREEN 0x04000000 #define SDF_CEIL_GLOW_BLUE 0x08000000 #define SDF_FLOOR_GLOW 0x10000000 #define SDF_CEIL_GLOW 0x20000000 #define SIDF_TOP_MATERIAL 0x0001 #define SIDF_MID_MATERIAL 0x0002 #define SIDF_BOTTOM_MATERIAL 0x0004 #define SIDF_LINE_FLAGS 0x0008 #define SIDF_TOP_COLOR_RED 0x0010 #define SIDF_TOP_COLOR_GREEN 0x0020 #define SIDF_TOP_COLOR_BLUE 0x0040 #define SIDF_MID_COLOR_RED 0x0080 #define SIDF_MID_COLOR_GREEN 0x0100 #define SIDF_MID_COLOR_BLUE 0x0200 #define SIDF_MID_COLOR_ALPHA 0x0400 #define SIDF_BOTTOM_COLOR_RED 0x0800 #define SIDF_BOTTOM_COLOR_GREEN 0x1000 #define SIDF_BOTTOM_COLOR_BLUE 0x2000 #define SIDF_MID_BLENDMODE 0x4000 #define SIDF_FLAGS 0x8000 #define PODF_DEST_X 0x01 #define PODF_DEST_Y 0x02 #define PODF_SPEED 0x04 #define PODF_DEST_ANGLE 0x08 #define PODF_ANGSPEED 0x10 #define PODF_PERPETUAL_ROTATE 0x20 // Special flag. #define LDF_INFO 0x01 #define SNDDF_VOLUME 0x01 // 0=stop, 1=full, >1=no att. #define SNDDF_REPEAT 0x02 // Start repeating sound. #define SNDDF_FLOOR 0x04 // Play sound from floor. #define SNDDF_CEILING 0x08 // Play sound from ceiling. typedef enum deltastate_e { DELTA_NEW, DELTA_UNACKED } deltastate_t; /** * All delta structures begin the same way (with a delta_t). * That way they can all be linked into the same hash table. */ typedef struct delta_s { // Links to the next and previous delta in the hash. struct delta_s* next, *prev; // The ID number and type determine the entity this delta applies to. deltatype_t type; uint id; // The priority score tells how badly the delta needs to be sent to // the client. float score; // Deltas can be either New or Unacked. New deltas haven't yet been sent. deltastate_t state; // ID of the delta set. Assigned when the delta is sent to a client. // All deltas in the same frame update have the same set ID. // Clients acknowledge complete sets (and then the whole set is removed). byte set; // Resend ID of this delta. Assigned when the delta is first resent. // Zero means there is no resend ID. byte resend; // System time when the delta was sent. uint timeStamp; int flags; } delta_t; typedef mobj_t dt_mobj_t; typedef struct { delta_t delta; // The header. dt_mobj_t mo; // The data of the delta. } mobjdelta_t; typedef struct { thid_t mobj; char forwardMove; char sideMove; int angle; int turnDelta; float friction; int extraLight; int fixedColorMap; int filter; int clYaw; float clPitch; ddpsprite_t psp[2]; // Player sprites. } dt_player_t; typedef struct { delta_t delta; // The header. dt_player_t player; } playerdelta_t; typedef struct { material_t* material; float rgba[4]; // Surface color tint int blendMode; } dt_surface_t; typedef struct { dt_surface_t surface; float height; float target; // Target height. float speed; // Move speed. float glow; // Glow amount. float glowRGB[3]; // Glow color. } dt_plane_t; typedef struct { float lightLevel; float rgb[3]; uint planeCount; dt_plane_t planes[2]; } dt_sector_t; typedef struct { delta_t delta; dt_sector_t sector; } sectordelta_t; typedef struct { delta_t delta; } lumpdelta_t; typedef struct { dt_surface_t top; dt_surface_t middle; dt_surface_t bottom; byte lineFlags; // note: only a byte! byte flags; // Sidedef flags. } dt_side_t; typedef struct { delta_t delta; dt_side_t side; } sidedelta_t; typedef struct { fvertex_t dest; float speed; angle_t destAngle; angle_t angleSpeed; } dt_poly_t; typedef struct { delta_t delta; dt_poly_t po; } polydelta_t; typedef struct { delta_t delta; // id = Emitter identifier (mobjid/sectoridx) int sound; // Sound ID mobj_t* mobj; float volume; } sounddelta_t; /** * One hash table holds all the deltas in a pool. * (delta ID number) & (mask) is the key. */ #define POOL_HASH_SIZE 1024 #define POOL_HASH_FUNCTION_MASK 0x3ff /** * The missile record contains an entry for each missile mobj that * the client has acknowledged. Since missiles move predictably, * we do not need to sent the coordinates in every delta. The record * is checked every time a missile delta is added to a pool. */ #define POOL_MISSILE_HASH_SIZE 256 typedef struct misrecord_s { struct misrecord_s* next, *prev; thid_t id; //fixed_t momx, momy, momz; } misrecord_t; typedef struct mislink_s { misrecord_t* first, *last; } mislink_t; typedef struct deltalink_s { // Links to the first and last delta in the hash key. struct delta_s* first, *last; } deltalink_t; /** * When calculating priority scores, this struct is used to store * information about the owner of the pool. */ typedef struct ownerinfo_s { struct pool_s* pool; float pos[3]; // Distance is the most important factor angle_t angle; // Angle can change rapidly => not very important float speed; uint ackThreshold; // Expected ack time in milliseconds } ownerinfo_t; /** * Each client has a delta pool. */ typedef struct pool_s { // True if the first frame has not yet been sent. boolean isFirst; // The number of the console this pool belongs to. (i.e. player number) uint owner; ownerinfo_t ownerInfo; // The set ID numbers are generated using this value. It's // incremented after each transmitted set. byte setDealer; // The resend ID numbers are generated using this value. It's incremented // for each resent delta. Zero is not used. byte resendDealer; // The delta hash table holds all kinds of deltas. deltalink_t hash[POOL_HASH_SIZE]; // The missile record is used to detect when the mobj coordinates need // not be sent. mislink_t misHash[POOL_MISSILE_HASH_SIZE]; // The priority queue (a heap). Built when the pool contents are rated. // Contains pointers to deltas in the hash. Becomes invalid when deltas // are removed from the hash! int queueSize; int allocatedSize; delta_t** queue; } pool_t; void Sv_InitPools(void); void Sv_ShutdownPools(void); void Sv_DrainPool(uint clientNumber); void Sv_InitPoolForClient(uint clientNumber); void Sv_MobjRemoved(thid_t id); void Sv_PlayerRemoved(uint clientNumber); void Sv_GenerateFrameDeltas(void); boolean Sv_IsFrameTarget(uint clientNumber); uint Sv_GetTimeStamp(void); pool_t* Sv_GetPool(uint clientNumber); void Sv_RatePool(pool_t* pool); delta_t* Sv_PoolQueueExtract(pool_t* pool); void Sv_AckDeltaSet(uint clientNumber, int set, byte resent); uint Sv_CountUnackedDeltas(uint clientNumber); void Sv_NewSoundDelta(int soundId, mobj_t* emitter, sector_t* sourceSector, polyobj_t* sourcePoly, float volume, boolean isRepeating, int clientsMask); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_bams.h0000644000175000017500000000705511357170241023202 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_bams.h: Binary Angle Mathematics */ #ifndef __MY_BAMS_MATH_H__ #define __MY_BAMS_MATH_H__ #include "dd_types.h" #if BAMS_BITS == 32 // Some predefined angles. #define BANG_0 0 // To the east. #define BANG_45 0x20000000 // To the northeast. #define BANG_90 0x40000000 // To the north. #define BANG_135 0x60000000 // To the northwest. #define BANG_180 0x80000000 // To the west. #define BANG_225 0xa0000000 // To the southwest. #define BANG_270 0xc0000000 // To the south. #define BANG_315 0xe0000000 // To the southeast. #define BANG_360 0x100000000 // Actually the same as angle 0. #define BANG_MAX 0xffffffff // The largest possible angle. #elif BAMS_BITS == 16 // Some predefined angles. #define BANG_0 0 // To the east. #define BANG_45 0x2000 // To the northeast. #define BANG_90 0x4000 // To the north. #define BANG_135 0x6000 // To the northwest. #define BANG_180 0x8000 // To the west. #define BANG_225 0xa000 // To the southwest. #define BANG_270 0xc000 // To the south. #define BANG_315 0xe000 // To the southeast. #define BANG_360 0x10000 // Actually the same than angle 0. #define BANG_MAX 0xffff // The largest possible angle. #else // Byte-sized. // Some predefined angles. #define BANG_0 0 // To the east. #define BANG_45 0x20 // To the northeast. #define BANG_90 0x40 // To the north. #define BANG_135 0x60 // To the northwest. #define BANG_180 0x80 // To the west. #define BANG_225 0xa0 // To the southwest. #define BANG_270 0xc0 // To the south. #define BANG_315 0xe0 // To the southeast. #define BANG_360 0x100 // Actually the same than angle 0. #define BANG_MAX 0xff // The largest possible angle. #endif #define BAMS_PI 3.14159265359 #define RAD2BANG(x) ((binangle_t)((x)/BAMS_PI*BANG_180)) #define BANG2RAD(x) ((float)((x)/(float)BANG_180*BAMS_PI)) #define BANG2DEG(x) ((float)((x)/(float)BANG_180*180)) // Compass directions, for convenience. #define BANG_EAST BANG_0 #define BANG_NORTHEAST BANG_45 #define BANG_NORTH BANG_90 #define BANG_NORTHWEST BANG_135 #define BANG_WEST BANG_180 #define BANG_SOUTHWEST BANG_225 #define BANG_SOUTH BANG_270 #define BANG_SOUTHEAST BANG_315 void bamsInit(void); // Fill in the tables. binangle_t bamsAtan2(int y, int x); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/s_wav.h0000644000175000017500000000254711357170241023064 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_wav.h: WAV Files */ #ifndef __DOOMSDAY_SOUND_WAVE_FILE_H__ #define __DOOMSDAY_SOUND_WAVE_FILE_H__ int WAV_CheckFormat(const char* data); void* WAV_Load(const char* filename, int* bits, int* rate, int* samples); void* WAV_MemoryLoad(const byte* data, size_t datalength, int* bits, int* rate, int* samples); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_plane.h0000644000175000017500000000237211357170241023357 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_plane.h: World planes. */ #ifndef __DOOMSDAY_WORLD_PLANE_H__ #define __DOOMSDAY_WORLD_PLANE_H__ #include "r_data.h" #include "p_dmu.h" boolean Plane_GetProperty(const plane_t *pln, setargs_t *args); boolean Plane_SetProperty(plane_t *pln, const setargs_t *args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_render.h0000644000175000017500000000262211357170241023666 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_render.h: Rendering Subsystem */ #ifndef __DOOMSDAY_RENDERER__ #define __DOOMSDAY_RENDERER__ #include "rend_main.h" #include "rend_clip.h" #include "rend_halo.h" #include "rend_dyn.h" #include "rend_list.h" #include "rend_particle.h" #include "rend_sky.h" #include "rend_sprite.h" #include "rend_model.h" #include "rend_shadow.h" #include "rend_fakeradio.h" #include "rend_bias.h" #include "rend_decor.h" #include "rend_console.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_maptypes.h0000644000175000017500000004627211357170241024131 0ustar keeskees/* Generated by .\..\..\engine\scripts\makedmt.py */ #ifndef __DOOMSDAY_PLAY_MAP_DATA_TYPES_H__ #define __DOOMSDAY_PLAY_MAP_DATA_TYPES_H__ #include "p_mapdata.h" #define LO_prev link[0] #define LO_next link[1] typedef struct shadowvert_s { float inner[2]; float extended[2]; } shadowvert_t; typedef struct lineowner_s { struct linedef_s *lineDef; struct lineowner_s *link[2]; // {prev, next} (i.e. {anticlk, clk}). binangle_t angle; // between this and next clockwise. shadowvert_t shadowOffsets; } lineowner_t; #define V_pos v.pos typedef struct mvertex_s { // Vertex index. Always valid after loading and pruning of unused // vertices has occurred. int index; // Reference count. When building normal node info, unused vertices // will be pruned. int refCount; // Usually NULL, unless this vertex occupies the same location as a // previous vertex. Only used during the pruning phase. struct vertex_s *equiv; struct edgetip_s *tipSet; // Set of wall_tips. // Final data. double pos[2]; } mvertex_t; typedef struct vertex_s { runtime_mapdata_header_t header; unsigned int numLineOwners; // Number of line owners. lineowner_t* lineOwners; // Lineowner base ptr [numlineowners] size. A doubly, circularly linked list. The base is the line with the lowest angle and the next-most with the largest angle. fvertex_t v; mvertex_t buildData; } vertex_t; // Helper macros for accessing seg data elements. #define FRONT 0 #define BACK 1 #define SG_v(n) v[(n)] #define SG_vpos(n) SG_v(n)->V_pos #define SG_v1 SG_v(0) #define SG_v1pos SG_v(0)->V_pos #define SG_v2 SG_v(1) #define SG_v2pos SG_v(1)->V_pos #define SG_sector(n) sec[(n)] #define SG_frontsector SG_sector(FRONT) #define SG_backsector SG_sector(BACK) #define SEG_SIDEDEF(s) ((s)->lineDef->sideDefs[(s)->side]) // Seg flags #define SEGF_POLYOBJ 0x1 // Seg is part of a poly object. // Seg frame flags #define SEGINF_FACINGFRONT 0x0001 #define SEGINF_BACKSECSKYFIX 0x0002 typedef struct seg_s { runtime_mapdata_header_t header; struct vertex_s* v[2]; // [Start, End] of the segment. struct linedef_s* lineDef; struct sector_s* sec[2]; struct subsector_s* subsector; struct seg_s* backSeg; angle_t angle; byte side; // 0=front, 1=back byte flags; float length; // Accurate length of the segment (v1 -> v2). float offset; biassurface_t* bsuf[3]; // 0=middle, 1=top, 2=bottom short frameFlags; } seg_t; #define SUBF_MIDPOINT 0x80 // Midpoint is tri-fan centre. typedef struct subsector_s { runtime_mapdata_header_t header; unsigned int segCount; struct seg_s** segs; // [segcount] size. struct polyobj_s* polyObj; // NULL, if there is no polyobj. struct sector_s* sector; int addSpriteCount; // frame number of last R_AddSprites unsigned int inSectorID; int flags; int validCount; unsigned int reverb[NUM_REVERB_DATA]; fvertex_t bBox[2]; // Min and max points. float worldGridOffset[2]; // Offset to align the top left of the bBox to the world grid. fvertex_t midPoint; // Center of vertices. unsigned short numVertices; struct fvertex_s** vertices; // [numvertices] size struct shadowlink_s* shadows; struct biassurface_s** bsuf; // [sector->planeCount] size. } subsector_t; typedef struct materiallayer_s { int stage; // -1 => layer not in use. short tics; gltextureid_t tex; } material_layer_t; typedef enum { MEC_UNKNOWN = -1, MEC_METAL = 0, MEC_ROCK, MEC_WOOD, MEC_CLOTH, NUM_MATERIAL_ENV_CLASSES } material_env_class_t; typedef struct material_s { runtime_mapdata_header_t header; material_namespace_t mnamespace; struct ded_material_s* def; // Can be NULL (was generated automatically). short flags; // MATF_* flags short width; // Defined width & height of the material (not texture!). short height; material_layer_t layers[DDMAX_MATERIAL_LAYERS]; unsigned int numLayers; material_env_class_t envClass; // Used for environmental sound properties. struct ded_detailtexture_s* detail; struct ded_decor_s* decoration; struct ded_ptcgen_s* ptcGen; struct ded_reflection_s* reflection; boolean inAnimGroup; // True if belongs to some animgroup. struct material_s* current; struct material_s* next; float inter; struct material_s* globalNext; // Linear list linking all materials. } material_t; // Internal surface flags: #define SUIF_PVIS 0x0001 #define SUIF_MATERIAL_FIX 0x0002 // Current texture is a fix replacement // (not sent to clients, returned via DMU etc). #define SUIF_BLEND 0x0004 // Surface possibly has a blended texture. #define SUIF_NO_RADIO 0x0008 // No fakeradio for this surface. #define SUIF_UPDATE_FLAG_MASK 0xff00 #define SUIF_UPDATE_DECORATIONS 0x8000 // Decoration types. typedef enum { DT_LIGHT, DT_MODEL, NUM_DECORTYPES } decortype_t; // Helper macros for accessing decor data. #define DEC_LIGHT(x) (&((x)->data.light)) #define DEC_MODEL(x) (&((x)->data.model)) typedef struct surfacedecor_s { float pos[3]; // World coordinates of the decoration. decortype_t type; subsector_t* subsector; union surfacedecor_data_u { struct surfacedecor_light_s { const struct ded_decorlight_s* def; } light; struct surfacedecor_model_s { const struct ded_decormodel_s* def; struct modeldef_s* mf; float pitch, yaw; } model; } data; } surfacedecor_t; typedef struct surface_s { runtime_mapdata_header_t header; void* owner; // Either @c DMU_SIDEDEF, or @c DMU_PLANE int flags; // SUF_ flags int oldFlags; material_t* material; blendmode_t blendMode; float normal[3]; // Surface normal float oldNormal[3]; float offset[2]; // [X, Y] Planar offset to surface material origin. float oldOffset[2][2]; float visOffset[2]; float visOffsetDelta[2]; float rgba[4]; // Surface color tint short inFlags; // SUIF_* flags unsigned int numDecorations; surfacedecor_t *decorations; } surface_t; typedef enum { PLN_FLOOR, PLN_CEILING, PLN_MID, NUM_PLANE_TYPES } planetype_t; #define PS_normal surface.normal #define PS_material surface.material #define PS_offset surface.offset #define PS_visoffset surface.visOffset #define PS_rgba surface.rgba #define PS_flags surface.flags #define PS_inflags surface.inFlags typedef struct plane_s { runtime_mapdata_header_t header; ddmobj_base_t soundOrg; // Sound origin for plane struct sector_s* sector; // Owner of the plane (temp) surface_t surface; float height; // Current height float oldHeight[2]; float glow; // Glow amount float glowRGB[3]; // Glow color float target; // Target height float speed; // Move speed float visHeight; // Visible plane height (smoothed) float visHeightDelta; planetype_t type; // PLN_* type. int planeID; } plane_t; // Helper macros for accessing sector floor/ceiling plane data elements. #define SP_plane(n) planes[(n)] #define SP_planesurface(n) SP_plane(n)->surface #define SP_planeheight(n) SP_plane(n)->height #define SP_planenormal(n) SP_plane(n)->surface.normal #define SP_planematerial(n) SP_plane(n)->surface.material #define SP_planeoffset(n) SP_plane(n)->surface.offset #define SP_planergb(n) SP_plane(n)->surface.rgba #define SP_planeglow(n) SP_plane(n)->glow #define SP_planeglowrgb(n) SP_plane(n)->glowRGB #define SP_planetarget(n) SP_plane(n)->target #define SP_planespeed(n) SP_plane(n)->speed #define SP_planesoundorg(n) SP_plane(n)->soundOrg #define SP_planevisheight(n) SP_plane(n)->visHeight #define SP_ceilsurface SP_planesurface(PLN_CEILING) #define SP_ceilheight SP_planeheight(PLN_CEILING) #define SP_ceilnormal SP_planenormal(PLN_CEILING) #define SP_ceilmaterial SP_planematerial(PLN_CEILING) #define SP_ceiloffset SP_planeoffset(PLN_CEILING) #define SP_ceilrgb SP_planergb(PLN_CEILING) #define SP_ceilglow SP_planeglow(PLN_CEILING) #define SP_ceilglowrgb SP_planeglowrgb(PLN_CEILING) #define SP_ceiltarget SP_planetarget(PLN_CEILING) #define SP_ceilspeed SP_planespeed(PLN_CEILING) #define SP_ceilsoundorg SP_planesoundorg(PLN_CEILING) #define SP_ceilvisheight SP_planevisheight(PLN_CEILING) #define SP_floorsurface SP_planesurface(PLN_FLOOR) #define SP_floorheight SP_planeheight(PLN_FLOOR) #define SP_floornormal SP_planenormal(PLN_FLOOR) #define SP_floormaterial SP_planematerial(PLN_FLOOR) #define SP_flooroffset SP_planeoffset(PLN_FLOOR) #define SP_floorrgb SP_planergb(PLN_FLOOR) #define SP_floorglow SP_planeglow(PLN_FLOOR) #define SP_floorglowrgb SP_planeglowrgb(PLN_FLOOR) #define SP_floortarget SP_planetarget(PLN_FLOOR) #define SP_floorspeed SP_planespeed(PLN_FLOOR) #define SP_floorsoundorg SP_planesoundorg(PLN_FLOOR) #define SP_floorvisheight SP_planevisheight(PLN_FLOOR) #define S_skyfix(n) skyFix[(n)] #define S_floorskyfix S_skyfix(PLN_FLOOR) #define S_ceilskyfix S_skyfix(PLN_CEILING) // Sector frame flags #define SIF_VISIBLE 0x1 // Sector is visible on this frame. #define SIF_FRAME_CLEAR 0x1 // Flags to clear before each frame. #define SIF_LIGHT_CHANGED 0x2 // Sector flags. #define SECF_UNCLOSED 0x1 // An unclosed sector (some sort of fancy hack). typedef struct msector_s { // Sector index. Always valid after loading & pruning. int index; // Suppress superfluous mini warnings. int warnedFacing; int refCount; } msector_t; typedef struct sector_s { runtime_mapdata_header_t header; int frameFlags; int validCount; // if == validCount, already checked. int flags; float bBox[4]; // Bounding box for the sector. float approxArea; // Rough approximation of sector area. float lightLevel; float oldLightLevel; float rgb[3]; float oldRGB[3]; struct mobj_s* mobjList; // List of mobjs in the sector. unsigned int lineDefCount; struct linedef_s** lineDefs; // [lineDefCount+1] size. unsigned int ssectorCount; struct subsector_s** ssectors; // [ssectorCount+1] size. unsigned int numReverbSSecAttributors; struct subsector_s** reverbSSecs; // [numReverbSSecAttributors] size. ddmobj_base_t soundOrg; unsigned int planeCount; struct plane_s** planes; // [planeCount+1] size. struct sector_s* lightSource; // Main sky light source. unsigned int blockCount; // Number of gridblocks in the sector. unsigned int changedBlockCount; // Number of blocks to mark changed. unsigned short* blocks; // Light grid block indices. float reverb[NUM_REVERB_DATA]; msector_t buildData; } sector_t; // Parts of a wall segment. typedef enum segsection_e { SEG_MIDDLE, SEG_TOP, SEG_BOTTOM } segsection_t; // Helper macros for accessing sidedef top/middle/bottom section data elements. #define SW_surface(n) sections[(n)] #define SW_surfaceflags(n) SW_surface(n).flags #define SW_surfaceinflags(n) SW_surface(n).inFlags #define SW_surfacematerial(n) SW_surface(n).material #define SW_surfacenormal(n) SW_surface(n).normal #define SW_surfaceoffset(n) SW_surface(n).offset #define SW_surfacevisoffset(n) SW_surface(n).visOffset #define SW_surfacergba(n) SW_surface(n).rgba #define SW_surfaceblendmode(n) SW_surface(n).blendMode #define SW_middlesurface SW_surface(SEG_MIDDLE) #define SW_middleflags SW_surfaceflags(SEG_MIDDLE)0 #define SW_middleinflags SW_surfaceinflags(SEG_MIDDLE) #define SW_middlematerial SW_surfacematerial(SEG_MIDDLE) #define SW_middlenormal SW_surfacenormal(SEG_MIDDLE) #define SW_middletexmove SW_surfacetexmove(SEG_MIDDLE) #define SW_middleoffset SW_surfaceoffset(SEG_MIDDLE) #define SW_middlevisoffset SW_surfacevisoffset(SEG_MIDDLE) #define SW_middlergba SW_surfacergba(SEG_MIDDLE) #define SW_middleblendmode SW_surfaceblendmode(SEG_MIDDLE) #define SW_topsurface SW_surface(SEG_TOP) #define SW_topflags SW_surfaceflags(SEG_TOP) #define SW_topinflags SW_surfaceinflags(SEG_TOP) #define SW_topmaterial SW_surfacematerial(SEG_TOP) #define SW_topnormal SW_surfacenormal(SEG_TOP) #define SW_toptexmove SW_surfacetexmove(SEG_TOP) #define SW_topoffset SW_surfaceoffset(SEG_TOP) #define SW_topvisoffset SW_surfacevisoffset(SEG_TOP) #define SW_toprgba SW_surfacergba(SEG_TOP) #define SW_bottomsurface SW_surface(SEG_BOTTOM) #define SW_bottomflags SW_surfaceflags(SEG_BOTTOM) #define SW_bottominflags SW_surfaceinflags(SEG_BOTTOM) #define SW_bottommaterial SW_surfacematerial(SEG_BOTTOM) #define SW_bottomnormal SW_surfacenormal(SEG_BOTTOM) #define SW_bottomtexmove SW_surfacetexmove(SEG_BOTTOM) #define SW_bottomoffset SW_surfaceoffset(SEG_BOTTOM) #define SW_bottomvisoffset SW_surfacevisoffset(SEG_BOTTOM) #define SW_bottomrgba SW_surfacergba(SEG_BOTTOM) #define FRONT 0 #define BACK 1 typedef struct msidedef_s { // Sidedef index. Always valid after loading & pruning. int index; int refCount; } msidedef_t; typedef struct sidedef_s { runtime_mapdata_header_t header; surface_t sections[3]; unsigned int segCount; struct seg_s** segs; // [segcount] size, segs arranged left>right struct linedef_s* line; struct sector_s* sector; short flags; msidedef_t buildData; int fakeRadioUpdateCount; // frame number of last update shadowcorner_t topCorners[2]; shadowcorner_t bottomCorners[2]; shadowcorner_t sideCorners[2]; edgespan_t spans[2]; // [left, right] } sidedef_t; // Helper macros for accessing linedef data elements. #define L_v(n) v[(n)] #define L_vpos(n) v[(n)]->V_pos #define L_v1 L_v(0) #define L_v1pos L_v(0)->V_pos #define L_v2 L_v(1) #define L_v2pos L_v(1)->V_pos #define L_vo(n) vo[(n)] #define L_vo1 L_vo(0) #define L_vo2 L_vo(1) #define L_side(n) sideDefs[(n)] #define L_frontside L_side(FRONT) #define L_backside L_side(BACK) #define L_sector(n) sideDefs[(n)]->sector #define L_frontsector L_sector(FRONT) #define L_backsector L_sector(BACK) // Is this line self-referencing (front sec == back sec)? #define LINE_SELFREF(l) ((l)->L_frontside && (l)->L_backside && \ (l)->L_frontsector == (l)->L_backsector) // Internal flags: #define LF_POLYOBJ 0x1 // Line is part of a polyobject. #define MLF_TWOSIDED 0x1 // Line is marked two-sided. #define MLF_ZEROLENGTH 0x2 // Zero length (line should be totally ignored). #define MLF_SELFREF 0x4 // Sector is the same on both sides. #define MLF_POLYOBJ 0x8 // Line is part of a polyobj. typedef struct mlinedef_s { // Linedef index. Always valid after loading & pruning of zero // length lines has occurred. int index; int mlFlags; // MLF_* flags. // One-sided linedef used for a special effect (windows). // The value refers to the opposite sector on the back side. struct sector_s *windowEffect; // Normally NULL, except when this linedef directly overlaps an earlier // one (a rarely-used trick to create higher mid-masked textures). // No segs should be created for these overlapping linedefs. struct linedef_s *overlap; } mlinedef_t; typedef struct linedef_s { runtime_mapdata_header_t header; struct vertex_s* v[2]; struct lineowner_s* vo[2]; // Links to vertex line owner nodes [left, right] struct sidedef_s* sideDefs[2]; int flags; // Public DDLF_* flags. byte inFlags; // Internal LF_* flags slopetype_t slopeType; int validCount; binangle_t angle; // Calculated from front side's normal float dX; float dY; float length; // Accurate length float bBox[4]; boolean mapped[DDMAXPLAYERS]; // Whether the line has been mapped by each player yet. mlinedef_t buildData; unsigned short shadowVisFrame[2]; // Framecount of last time shadows were drawn for this line, for each side [right, left]. } linedef_t; #define RIGHT 0 #define LEFT 1 /** * An infinite line of the form point + direction vectors. */ typedef struct partition_s { float x, y; float dX, dY; } partition_t; typedef struct node_s { runtime_mapdata_header_t header; partition_t partition; float bBox[2][4]; // Bounding box for each child. unsigned int children[2]; // If NF_SUBSECTOR it's a subsector. } node_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_sprite.h0000644000175000017500000000366011357170241024260 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_sprite.h: Rendering Map Objects as 2D Sprites */ #ifndef __DOOMSDAY_RENDER_SPRITE_H__ #define __DOOMSDAY_RENDER_SPRITE_H__ typedef struct rendpspriteparams_s { // Position/Orientation/Scale float pos[2]; // {X, Y} Screen-space position. float width, height; // Appearance // Texture: material_t* mat; float texOffset[2]; boolean texFlip[2]; // {X, Y} Flip along the specified axis. // Lighting/color: float ambientColor[4]; uint vLightListIdx; } rendpspriteparams_t; extern int spriteLight, useSpriteAlpha; extern byte noSpriteTrans; extern byte devNoSprites; void Rend_SpriteRegister(void); void Rend_DrawMasked(void); void Rend_Draw2DPlayerSprites(void); void Rend_Draw3DPlayerSprites(void); void Rend_SpriteTexCoord(int pnum, int x, int y); void Rend_RenderSprite(const rendspriteparams_t* params); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_dmu.h0000644000175000017500000000455111357170241023046 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_dmu.h: Map Update API * * Engine-internal header for DMU. */ #ifndef __DOOMSDAY_MAP_UPDATE_H__ #define __DOOMSDAY_MAP_UPDATE_H__ typedef struct setargs_s { int type; uint prop; int modifiers; // Property modifiers (e.g., line of sector) valuetype_t valueType; boolean *booleanValues; byte *byteValues; int *intValues; fixed_t *fixedValues; float *floatValues; angle_t *angleValues; void **ptrValues; } setargs_t; void P_InitMapUpdate(void); void *P_AllocDummy(int type, void* extraData); void P_FreeDummy(void* dummy); int P_DummyType(void* dummy); boolean P_IsDummy(void* dummy); void *P_DummyExtraData(void* dummy); uint P_ToIndex(const void* ptr); const char *DMU_Str(uint prop); void DMU_SetValue(valuetype_t valueType, void* dst, const setargs_t* args, uint index); void DMU_GetValue(valuetype_t valueType, const void* src, setargs_t* args, uint index); #ifndef NDEBUG # define ASSERT_DMU_TYPE(ptr, dmuType) \ if(!ptr || ((runtime_mapdata_header_t*)ptr)->type != dmuType) \ Con_Error("ASSERT_DMU_TYPE failure on line %i in "__FILE__". " #ptr " is not %s.\n", __LINE__, DMU_Str(dmuType)); #else # define ASSERT_DMU_TYPE(ptr, dmuType) #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sv_def.h0000644000175000017500000000520311357170241023203 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sv_def.h: Server Definitions */ #ifndef __DOOMSDAY_SERVER_H__ #define __DOOMSDAY_SERVER_H__ #include "dd_def.h" #include "m_string.h" #define SV_VERSION 7 #define SV_WELCOME_STRING "Doomsday "DOOMSDAY_VERSION_TEXT" Server (R7)" // Anything closer than this is always taken into consideration when // deltas are being generated. #define CLOSE_MOBJ_DIST 512 // Anything farther than this will never be taken into consideration. #define FAR_MOBJ_DIST 1500 extern int svMaxPlayers; extern int allowFrames; // Allow sending of frames. extern int frameInterval; // In tics. extern int netRemoteUser; // The client who is currently logged in. extern char* netPassword; // Remote login password. void Sv_Shutdown(void); void Sv_StartNetGame(void); boolean Sv_PlayerArrives(unsigned int nodeID, char* name); void Sv_PlayerLeaves(unsigned int nodeID); void Sv_Handshake(int playernum, boolean newplayer); void Sv_GetPackets(void); void Sv_SendText(int to, int conFlags, char* text); //void Sv_FixLocalAngles(boolean clearFixAnglesFlag); void Sv_Ticker(void); int Sv_Latency(byte cmdTime); void Sv_Kick(int who); void Sv_GetInfo(serverinfo_t* info); size_t Sv_InfoToString(serverinfo_t* info, ddstring_t* msg); boolean Sv_StringToInfo(const char* valuePair, serverinfo_t* info); int Sv_GetNumPlayers(void); int Sv_GetNumConnected(void); void Sv_PlaceMobj(struct mobj_s* mo, float x, float y, float z, boolean onFloor); boolean Sv_CheckBandwidth(int playerNumber); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/cl_def.h0000644000175000017500000000305611357170241023155 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_def.h: Client Definitions */ #ifndef __DOOMSDAY_CLIENT_H__ #define __DOOMSDAY_CLIENT_H__ #include "p_object.h" #define SHORTP(x) (*(short*) (x)) #define USHORTP(x) (*(unsigned short*) (x)) extern ident_t clientID; extern int serverTime; extern boolean handshakeReceived; extern int gameReady; extern boolean netLoggedIn; extern int clientPaused; void Cl_InitID(void); void Cl_CleanUp(void); void Cl_GetPackets(void); void Cl_Ticker(void); int Cl_GameReady(void); void Cl_SendHello(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_def.h0000644000175000017500000000564511357170241023154 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_def.h: Internal Doomsday Macros and Constants */ #ifndef __DOOMSDAY_DEFS_H__ #define __DOOMSDAY_DEFS_H__ #include #include #include #include "dd_types.h" #include "dd_api.h" #ifdef WIN32 // Disable annoying MSVC warnings. // 4761: integral size mismatch in argument // 4244: conversion from 'type1' to 'type2', possible loss of data #pragma warning (disable:4761 4244) #endif // if rangecheck is undefined, most parameter validation debugging code // will not be compiled #ifndef NORANGECHECKING # define RANGECHECK #endif #ifndef DOOMSDAY_VER_ID # ifdef _DEBUG # define DOOMSDAY_VER_ID "+D DGL" # else # define DOOMSDAY_VER_ID "DGL" # endif #endif #ifdef RANGECHECK # define DOOMSDAY_VERSIONTEXT "Version "DOOMSDAY_VERSION_TEXT" +R "__DATE__" ("DOOMSDAY_VER_ID")" #else # define DOOMSDAY_VERSIONTEXT "Version "DOOMSDAY_VERSION_TEXT" "__DATE__" ("DOOMSDAY_VER_ID")" #endif #define SAFEDIV(x,y) (!(y) || !((x)/(y))? 1 : (x)/(y)) #define ORDER(x,y,a,b) ( (x)<(y)? ((a)=(x),(b)=(y)) : ((b)=(x),(a)=(y)) ) #define LAST_CHAR(str) (str[strlen(str) - 1]) #define ASSERT_NOT_64BIT() {if( sizeof(void*)!=sizeof(int) ) Con_Error("Pointer size assumption in "__FILE__" at line %i.\n", __LINE__);} #define MAXEVENTS 256 #define SBARHEIGHT 39 // status bar height at bottom of screen #define PI 3.14159265359 #define PI_D 3.14159265358979323846 #define SECONDS_TO_TICKS(sec) ((int)(sec*35)) // Heap relations. #define HEAP_PARENT(i) (((i) + 1)/2 - 1) #define HEAP_LEFT(i) (2*(i) + 1) #define HEAP_RIGHT(i) (2*(i) + 2) enum { VX, VY, VZ }; // Vertex indices. enum { CR, CG, CB, CA }; // Color indices. // dd_pinit.c extern game_export_t __gx; extern game_import_t __gi; #define gx __gx #define gi __gi extern byte gammaTable[256]; extern float texGamma; // tab_tables.c extern fixed_t finesine[5 * FINEANGLES / 4]; extern fixed_t *fineCosine; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_help.h0000644000175000017500000000261311357170241023336 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * dd_help.h: Help Text Strings */ #ifndef __DOOMSDAY_HELP_H__ #define __DOOMSDAY_HELP_H__ // Help string types. enum { HST_DESCRIPTION, HST_CONSOLE_VARIABLE, HST_DEFAULT_VALUE, HST_INFO, NUM_HELPSTRING_TYPES }; void DH_Register(void); void DD_InitHelp(void); void DD_ShutdownHelp(void); void *DH_Find(const char *id); char *DH_GetString(void *found, int type); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/ui_main.h0000644000175000017500000002627611357170241023373 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * ui_main.h: Graphical User Interface */ #ifndef __DOOMSDAY_UI_H__ #define __DOOMSDAY_UI_H__ #include "con_decl.h" enum // Colors. { UIC_TEXT, UIC_TITLE, UIC_SHADOW, UIC_BG_LIGHT, UIC_BG_MEDIUM, UIC_BG_DARK, UIC_BRD_HI, UIC_BRD_MED, UIC_BRD_LOW, UIC_HELP, NUM_UI_COLORS }; #define IS_ACTKEY(x) (x == ' ' || x == DDKEY_RETURN) typedef enum { UI_NONE, UI_TEXT, UI_BOX, UI_FOCUSBOX, // Can receive focus. UI_BUTTON, UI_BUTTON2, // Staydown/2-state button. UI_BUTTON2EX, // Staydown/2-state with additional data. UI_EDIT, UI_LIST, UI_SLIDER, UI_META // Special: affects all objects up to the next meta. } ui_obtype_e; // Standard dimensions. #define UI_WIDTH (1000.0f) #define UI_HEIGHT (1000.0f) #define UI_BORDER (UI_WIDTH/120) // All borders are this wide. #define UI_SHADOW_OFFSET (MIN_OF(3, UI_WIDTH/320)) #define UI_BUTTON_BORDER (UI_BORDER) #define UI_BAR_WDH (UI_BORDER * 3) #define UI_BAR_BORDER (UI_BORDER / 2) #define UI_BAR_BUTTON_BORDER (3 * UI_BAR_BORDER / 2) #define UI_MAX_COLUMNS 10 // Maximum columns for list box. // Object flags. #define UIF_HIDDEN 0x1 #define UIF_DISABLED 0x2 // Can't be interacted with. #define UIF_PAUSED 0x4 // Ticker not called. #define UIF_CLICKED 0x8 #define UIF_ACTIVE 0x10 // Object active. #define UIF_FOCUS 0x20 // Has focus. #define UIF_NO_FOCUS 0x40 // Can't receive focus. #define UIF_DEFAULT 0x80 // Has focus by default. #define UIF_LEFT_ALIGN 0x100 #define UIF_FADE_AWAY 0x200 // Fade UI away while the control is active. #define UIF_NEVER_FADE 0x400 #define UIF_ID0 0x10000000 #define UIF_ID1 0x20000000 #define UIF_ID2 0x40000000 #define UIF_ID3 0x80000000 // Special group: no group. #define UIG_NONE -1 // Flag group modes (for UI_FlagGroup). enum { UIFG_CLEAR, UIFG_SET, UIFG_XOR }; // Button arrows. enum { UIBA_NONE, UIBA_UP, UIBA_DOWN, UIBA_LEFT, UIBA_RIGHT }; // Types. typedef struct { float red, green, blue; } ui_color_t; typedef struct ui_object_s { ui_obtype_e type; // Type of the object. int group; int flags; int relx, rely, relw, relh; // Relative placement. char text[256]; // Used in various ways. void (*drawer) (struct ui_object_s *); int (*responder) (struct ui_object_s *, ddevent_t *); void (*ticker) (struct ui_object_s *); void (*action) (struct ui_object_s *); void *data; // Pointer to extra data. int data2; // Extra numerical data. int timer; int x, y, w, h; // Position and dimensions, auto-inited. } ui_object_t; // UI Pages consist of one or more controls. typedef struct ui_page_s { ui_object_t *objects; // List of objects, UI_NONE terminates. char title[128]; // Title for the screen. boolean background; // Draw the background? boolean header; // Draw the header bar? int focus; // Index of the focus object. int capture; // Index of the capture object. void (*drawer) (struct ui_page_s *); int (*responder) (struct ui_page_s *, ddevent_t *); void (*ticker) (struct ui_page_s *); struct ui_page_s *previous; // Pointer to the previous page, if any. int timer; int count; // Object count, no need to initialize. } ui_page_t; typedef struct { void *data; const char *yes; const char *no; } uidata_button_t; typedef struct { char *ptr; // Text to modify. int maxlen; // Maximum allowed length. void *data; uint cp; // Cursor position. } uidata_edit_t; typedef struct { char text[256]; int data; int data2; } uidata_listitem_t; typedef struct { void *items; int count; // Number of items. void *data; int selection; // Selected item (-1 if none). int first; // First visible item. int itemhgt; // Height of each item (0 = fonthgt). int numvis; // Number of visible items (updated at SetPage). byte button[3]; // Button states (0=normal, 1=down). int column[UI_MAX_COLUMNS]; // Column offsets (real coords). } uidata_list_t; typedef struct { float min, max; float value; float step; // Button step. boolean floatmode; // Otherwise only integers are allowed. void *data; char *zerotext; byte button[3]; // Button states (0=normal, 1=down). } uidata_slider_t; void UI_Register(void); // Functions. void UI_Init(boolean halttime, boolean tckui, boolean tckframe, boolean drwgame, boolean noescape); void UI_End(void); boolean UI_IsActive(void); ui_page_t *UI_CurrentPage(void); void UI_SetAlpha(float alpha); float UI_Alpha(void); ui_color_t *UI_Color(uint id); int UI_FontHeight(void); void UI_LoadTextures(void); void UI_ClearTextures(void); void UI_InitPage(ui_page_t *page, ui_object_t *objects); void UI_SetPage(ui_page_t *page); int UI_Responder(ddevent_t *ev); void UI_Ticker(timespan_t time); void UI_Drawer(void); int UI_CountObjects(ui_object_t *list); void UI_FlagGroup(ui_object_t *list, int group, int flags, int set); ui_object_t *UI_FindObject(ui_object_t *list, int group, int flags); void UI_Focus(ui_object_t *ob); void UI_Capture(ui_object_t *ob); // Default callbacks. int UIPage_Responder(ui_page_t *page, ddevent_t *ev); void UIPage_Ticker(ui_page_t *page); void UIPage_Drawer(ui_page_t *page); void UIFrame_Drawer(ui_object_t *ob); void UIText_Drawer(ui_object_t *ob); void UIText_BrightDrawer(ui_object_t *ob); int UIButton_Responder(ui_object_t *ob, ddevent_t *ev); void UIButton_Drawer(ui_object_t *ob); int UIEdit_Responder(ui_object_t *ob, ddevent_t *ev); void UIEdit_Drawer(ui_object_t *ob); int UIList_Responder(ui_object_t *ob, ddevent_t *ev); void UIList_Ticker(ui_object_t *ob); void UIList_Drawer(ui_object_t *ob); int UISlider_Responder(ui_object_t *ob, ddevent_t *ev); void UISlider_Ticker(ui_object_t *ob); void UISlider_Drawer(ui_object_t *ob); // Helpers. int UI_ScreenX(int relx); int UI_ScreenY(int rely); int UI_ScreenW(int relw); int UI_ScreenH(int relh); void UI_InitColumns(ui_object_t *ob); int UI_MouseInsideBox(int x, int y, int w, int h); int UI_MouseInside(ui_object_t *ob); int UI_MouseResting(ui_page_t *page); int UI_ListFindItem(ui_object_t *ob, int data_value); void UI_DrawLogo(int x, int y, int w, int h); void UI_DrawDDBackground(float x, float y, float w, float h, float alpha); void UI_DrawMouse(int x, int y, int w, int h); void UI_DrawTitle(ui_page_t *page); void UI_DrawTitleEx(char *text, int height, float alpha); void UI_MixColors(ui_color_t *a, ui_color_t *b, ui_color_t *dest, float amount); void UI_SetColorA(ui_color_t *color, float alpha); void UI_SetColor(ui_color_t *color); void UI_Line(int x1, int y1, int x2, int y2, ui_color_t *start, ui_color_t *end, float startAlpha, float endAlpha); void UI_Shade(int x, int y, int w, int h, int border, ui_color_t *main, ui_color_t *secondary, float alpha, float bottom_alpha); void UI_Gradient(int x, int y, int w, int h, ui_color_t *top, ui_color_t *bottom, float topAlpha, float bottomAlpha); void UI_GradientEx(int x, int y, int w, int h, int border, ui_color_t *top, ui_color_t *bottom, float topAlpha, float bottomAlpha); void UI_HorizGradient(int x, int y, int w, int h, ui_color_t *left, ui_color_t *right, float leftAlpha, float rightAlpha); void UI_DrawRect(int x, int y, int w, int h, int brd, ui_color_t *color, float alpha); void UI_DrawRectEx(int x, int y, int w, int h, int brd, boolean filled, ui_color_t *top, ui_color_t *bottom, float alpha, float bottomAlpha); void UI_DrawTriangle(int x, int y, int radius, ui_color_t *hi, ui_color_t *med, ui_color_t *low, float alpha); void UI_DrawButton(int x, int y, int w, int h, int brd, float alpha, ui_color_t *background, boolean down, boolean disabled, int arrow); void UI_TextOut(const char *text, int x, int y); void UI_TextOutEx(const char *text, int x, int y, int horiz_center, int vert_center, ui_color_t *color, float alpha); int UI_TextOutWrap(const char *text, int x, int y, int w, int h); int UI_TextOutWrapEx(const char *text, int x, int y, int w, int h, ui_color_t *color, float alpha); void UI_DrawHelpBox(int x, int y, int w, int h, float alpha, char *text); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_network.h0000644000175000017500000000262411357170241024102 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_network.h: Network Subsystem */ #ifndef __DOOMSDAY_NETWORK__ #define __DOOMSDAY_NETWORK__ #include "net_main.h" #include "net_event.h" #include "net_msg.h" #include "net_buf.h" #include "net_demo.h" #include "sv_def.h" #include "sv_pool.h" #include "sv_frame.h" #include "sv_sound.h" #include "sv_missile.h" #include "cl_def.h" #include "cl_player.h" #include "cl_mobj.h" #include "cl_frame.h" #include "cl_sound.h" #include "cl_world.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/edit_bias.h0000644000175000017500000000243411357170241023663 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * edit_bias.h: BIAS lighting editor. */ #ifndef __DOOMSDAY_BIAS_EDITOR__ #define __DOOMSDAY_BIAS_EDITOR__ #include "edit_bias.h" void SBE_Register(void); void SBE_EndFrame(void); void SBE_DrawCursor(void); void SBE_DrawHUD(void); boolean SBE_UsingHueCircle(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_polyobj.h0000644000175000017500000000240711357170241023735 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_polyobj.h: World polyobj. */ #ifndef __DOOMSDAY_WORLD_POLYOBJ_H__ #define __DOOMSDAY_WORLD_POLYOBJ_H__ #include "r_data.h" #include "p_dmu.h" boolean Polyobj_GetProperty(const polyobj_t *po, setargs_t *args); boolean Polyobj_SetProperty(polyobj_t *po, const setargs_t *args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/cl_world.h0000644000175000017500000000351511357170241023546 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_world.h: Clientside World Management */ #ifndef __DOOMSDAY_CLIENT_WORLD_H__ #define __DOOMSDAY_CLIENT_WORLD_H__ typedef enum { MVT_FLOOR, MVT_CEILING } clmovertype_t; void Cl_InitTranslations(void); void Cl_InitMovers(void); void Cl_RemoveMovers(void); lumpnum_t Cl_TranslateLump(lumpnum_t lump); void Cl_SetPolyMover(uint number, int move, int rotate); void Cl_AddMover(uint sectornum, clmovertype_t type, float dest, float speed); int Cl_ReadSectorDelta(void); int Cl_ReadLumpDelta(void); int Cl_ReadSideDelta(void); int Cl_ReadPolyDelta(void); void Cl_ReadSectorDelta2(int deltaType, boolean skip); void Cl_ReadSideDelta2(int deltaType, boolean skip); void Cl_ReadPolyDelta2(boolean skip); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/template.h.template0000644000175000017500000000215111357170241025361 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2008 Jaakko Keränen *\author Copyright © 2008 Daniel Swanson * (add more authors here) * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * : * * */ #ifndef __DOOMSDAY_ _H__ #define __DOOMSDAY_ _H__ #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/net_event.h0000644000175000017500000000300411357170241023721 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * net_event.h: Network Events */ #ifndef __DOOMSDAY_NETWORK_EVENT_H__ #define __DOOMSDAY_NETWORK_EVENT_H__ // Net events. typedef enum neteventtype_e { NE_CLIENT_ENTRY, NE_CLIENT_EXIT, NE_END_CONNECTION } neteventtype_t; typedef struct netevent_s { neteventtype_t type; nodeid_t id; } netevent_t; void N_MAPost(masteraction_t act); boolean N_MADone(void); void N_MAClear(void); void N_NEPost(netevent_t * nev); boolean N_NEPending(void); void N_NETicker(void); void N_TerminateClient(int console); void N_Update(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/s_environ.h0000644000175000017500000000256611357170241023750 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_environ.h: Environmental Sound Effects */ #ifndef __DOOMSDAY_SOUND_ENVIRON_H__ #define __DOOMSDAY_SOUND_ENVIRON_H__ #include "p_mapdata.h" void S_CalcSectorReverb(sector_t* sec); void S_DetermineSubSecsAffectingSectorReverb(gamemap_t* map); material_env_class_t S_MaterialClassForName(const char* name, material_namespace_t mnamespace); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/s_cache.h0000644000175000017500000000241511357170241023324 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * s_cache.h: Sound Sample Cache */ #ifndef __DOOMSDAY_SOUND_CACHE_H__ #define __DOOMSDAY_SOUND_CACHE_H__ void Sfx_InitCache(void); void Sfx_ShutdownCache(void); sfxsample_t *Sfx_Cache(int id); void Sfx_CacheHit(int id); uint Sfx_GetSoundLength(int id); void Sfx_GetCacheInfo(uint *cacheBytes, uint *sampleCount); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_lumobjs.h0000644000175000017500000000674611357170241023746 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_lumobjs.h: Lumobj (luminous object) management. */ #ifndef __DOOMSDAY_REFRESH_LUMINOUS_H__ #define __DOOMSDAY_REFRESH_LUMINOUS_H__ // Lumobject types. typedef enum { LT_OMNI, // Omni (spherical) light. LT_PLANE, // Planar light. } lumtype_t; // Helper macros for accessing lum data. #define LUM_OMNI(x) (&((x)->data.omni)) #define LUM_PLANE(x) (&((x)->data.plane)) typedef struct lumobj_s { lumtype_t type; float pos[3]; // Center of the obj. subsector_t* subsector; float maxDistance; void* decorSource; // decorsource_t ptr, else @c NULL. union lumobj_data_u { struct lumobj_omni_s { float color[3]; float radius; // Radius for this omnilight source. float zOff; // Offset to center from pos[VZ]. DGLuint tex; // Lightmap texture. DGLuint floorTex, ceilTex; // Lightmaps for floor/ceil. } omni; struct lumobj_plane_s { float color[3]; float intensity; DGLuint tex; float normal[3]; } plane; } data; } lumobj_t; extern boolean loInited; extern uint loMaxLumobjs; extern int loMaxRadius; extern float loRadiusFactor; extern byte rendInfoLums; extern int useMobjAutoLights; // Initialization. void LO_Register(void); // Setup. void LO_InitForMap(void); void LO_Clear(void); // 'Physically' destroy the tables. // Action. void LO_ClearForFrame(void); void LO_InitForNewFrame(void); void LO_AddLuminousMobjs(void); void LO_BeginFrame(void); void LO_UnlinkMobjLumobjs(cvar_t* var); uint LO_NewLuminous(lumtype_t type, subsector_t* ssec); lumobj_t* LO_GetLuminous(uint idx); uint LO_ToIndex(const lumobj_t* lum); boolean LO_IsClipped(uint idx, int i); boolean LO_IsHidden(uint idx, int i); float LO_DistanceToViewer(uint idx, int i); uint LO_GetNumLuminous(void); // Helpers. boolean LO_LumobjsRadiusIterator(subsector_t* subsector, float x, float y, float radius, void* data, boolean (*func) (const lumobj_t*, float, void *data)); void LO_ClipInSubsector(uint ssecidx); void LO_ClipInSubsectorBySight(uint ssecidx); void LO_DrawLumobjs(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_shadow.h0000644000175000017500000000230011357170241023536 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_shadow.h: Runtime Map Shadowing (FakeRadio) */ #ifndef __DOOMSDAY_REFRESH_SHADOW_H__ #define __DOOMSDAY_REFRESH_SHADOW_H__ void R_InitSectorShadows(void); boolean R_IsShadowingLinedef(linedef_t *line); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_material.h0000644000175000017500000000635311357170241024061 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_material.h: Materials for world surfaces. */ #ifndef __DOOMSDAY_MATERIAL_H__ #define __DOOMSDAY_MATERIAL_H__ #include "p_dmu.h" // Material load flags: #define MLF_LOAD_AS_SKY 0x1 #define MLF_ZEROMASK 0x2 // Zero the alpha of loaded textures. #define MLF_TEX_NO_COMPRESSION 0x4 // Do not compress the loaded textures. typedef struct { int flags; // MLF_* material load flags int tmap, tclass; boolean pSprite; } material_load_params_t; // Material texture unit idents: enum { MTU_PRIMARY, MTU_DETAIL, MTU_REFLECTION, MTU_REFLECTION_MASK, NUM_MATERIAL_TEXTURE_UNITS }; typedef struct material_textureunit_s { const struct gltexture_inst_s* texInst; int magMode; blendmode_t blendMode; // Currently used only with reflection. float alpha; float scale[2], offset[2]; // For use with the texture matrix. } material_textureunit_t; typedef struct material_snapshot_s { short width, height; // In world units. boolean isOpaque; float color[3]; // Average color (for lighting). float topColor[3]; // Averaged top line color, used for sky fadeouts. material_textureunit_t units[NUM_MATERIAL_TEXTURE_UNITS]; /** * \todo: the following should be removed once incorporated into the layers (above). */ struct shinydata_s { float minColor[3]; } shiny; } material_snapshot_t; boolean Material_GetProperty(const material_t* mat, setargs_t* args); boolean Material_SetProperty(material_t* mat, const setargs_t* args); const ded_decor_t* Material_GetDecoration(material_t* mat); const ded_ptcgen_t* Material_GetPtcGen(material_t* mat); material_env_class_t Material_GetEnvClass(material_t* mat); void Material_SetTranslation(material_t* mat, material_t* current, material_t* next, float inter); byte Material_Prepare(material_snapshot_t* snapshot, material_t* mat, boolean smoothed, material_load_params_t* params); //void Material_Ticker(material_t* mat, timespan_t time); void Material_DeleteTextures(material_t* mat); void Material_Precache(material_t* mat); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_decor.h0000644000175000017500000000265611357170241024052 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_decor.h: Decorations */ #ifndef __DOOMSDAY_RENDER_DECOR_H__ #define __DOOMSDAY_RENDER_DECOR_H__ extern byte useDecorations; extern float decorMaxDist; // No decorations are visible beyond this. extern float decorFactor; extern float decorFadeAngle; void Rend_DecorRegister(void); void Rend_InitDecorationsForFrame(void); void Rend_AddLuminousDecorations(void); void Rend_ProjectDecorations(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_platform.h0000644000175000017500000000535311357170241024237 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_platform.h: Platform Independence * * Define either WIN32 or UNIX when compiling. * * Use this header file in source files which can be compiled on any * platform but still use some platform specific code. */ #ifndef __DOOMSDAY_PLATFORM__ #define __DOOMSDAY_PLATFORM__ #include "dd_types.h" /* * The Win32 Platform */ #if defined(WIN32) #define WIN32_LEAN_AND_MEAN #include #include #define INTEGER64 __int64 #define DIR_SEP_CHAR '\\' #define DIR_SEP_STR "\\" #define DIR_WRONG_SEP_CHAR '/' #define stricmp _stricmp #define strnicmp _strnicmp #define open _open #define close _close #define read _read #define write _write #define access _access #define mkdir _mkdir #define strlwr _strlwr #define strupr _strupr #define strdup _strdup #define spawnlp _spawnlp #endif // WIN32 /* * The Unix Platform */ #if defined(UNIX) #include #include typedef long long int INTEGER64; typedef unsigned int DWORD; /* * Networking. */ #define INVALID_SOCKET (-1) #define SOCKET_ERROR (-1) /* * File system routines. */ #define _getdrive() (0) #define _chdrive(x) #define _getcwd getcwd #define _chdir chdir #define DIR_SEP_CHAR '/' #define DIR_SEP_STR "/" #define DIR_WRONG_SEP_CHAR '\\' #include "../../unix/include/sys_path.h" /* * Replacements for the Win32 findfirst/next routines. */ #include "../../unix/include/sys_findfile.h" #define _A_SUBDIR A_SUBDIR #define _findfirst myfindfirst #define _findnext myfindnext #define _findend myfindend #endif // UNIX // Initialization code. #ifdef WIN32 # include "dd_winit.h" #else # ifdef UNIX # include "dd_uinit.h" # endif #endif #endif // __DOOMSDAY_PLATFORM__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_main.h0000644000175000017500000000534411357170241023210 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_main.h: Refresh Subsystem */ #ifndef __DOOMSDAY_REFRESH_MAIN_H__ #define __DOOMSDAY_REFRESH_MAIN_H__ typedef struct viewport_s { int console; int x, y, width, height; } viewport_t; typedef struct viewer_s { float pos[3]; angle_t angle; float pitch; } viewer_t; typedef struct viewdata_s { viewer_t current; // Current view paramaters. viewer_t lastSharp[2]; // For smoothing. float frontVec[3], upVec[3], sideVec[3]; float viewCos, viewSin; // These are used when camera smoothing is disabled. angle_t frozenAngle; float frozenPitch; } viewdata_t; extern float viewX, viewY, viewZ, viewPitch; extern int viewAngle; extern float frameTimePos; // 0...1: fractional part for sharp game tics extern int loadInStartupMode; extern int validCount; extern int viewwidth, viewheight, viewwindowx, viewwindowy; extern int frameCount; extern int extraLight; extern float extraLightDelta; extern int rendInfoTris; extern fixed_t fineTangent[FINEANGLES / 2]; void R_Register(void); void R_Init(void); void R_Update(void); void R_Shutdown(void); void R_BeginWorldFrame(void); void R_EndWorldFrame(void); void R_RenderPlayerView(int num); void R_RenderPlayerViewBorder(void); void R_RenderViewPorts(void); const viewdata_t* R_ViewData(int localPlayerNum); void R_ResetViewer(void); void R_SetViewWindow(int x, int y, int w, int h); void R_NewSharpWorld(void); void R_SetViewGrid(int numCols, int numRows); void R_SetViewWindow(int x, int y, int w, int h); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_vector.h0000644000175000017500000001074511357170241023562 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_vector.h: Vector Math */ #ifndef __DOOMSDAY_MISC_VECTOR_H__ #define __DOOMSDAY_MISC_VECTOR_H__ typedef float vectorcomp_t; typedef vectorcomp_t vec2_t[2]; typedef const float const_pvec2_t[2]; typedef vectorcomp_t vec3_t[3]; typedef const float const_pvec3_t[3]; typedef vectorcomp_t *pvec2_t; typedef vectorcomp_t *pvec3_t; typedef vec2_t *arvec2_t; typedef vec3_t *arvec3_t; // 2-dimensions: void V2_Set(pvec2_t vec, vectorcomp_t x, vectorcomp_t y); void V2_SetFixed(pvec2_t vec, fixed_t x, fixed_t y); float V2_Length(const pvec2_t vector); float V2_Distance(const pvec2_t a, const pvec2_t b); float V2_Normalize(pvec2_t vec); void V2_Copy(pvec2_t dest, const_pvec2_t src); void V2_Scale(pvec2_t vector, float scalar); void V2_Rotate(pvec2_t vec, float radians); void V2_Sum(pvec2_t dest, const pvec2_t src1, const pvec2_t src2); void V2_Subtract(pvec2_t dest, const pvec2_t src1, const pvec2_t src2); float V2_DotProduct(const pvec2_t a, const pvec2_t b); float V2_ScalarProject(const pvec2_t a, const pvec2_t b); void V2_Project(pvec2_t dest, const pvec2_t a, const pvec2_t b); boolean V2_IsParallel(const pvec2_t a, const pvec2_t b); boolean V2_IsZero(const pvec2_t vec); float V2_Intersection(const pvec2_t p1, const pvec2_t delta1, const pvec2_t p2, const pvec2_t delta2, pvec2_t point); float V2_Intercept(const pvec2_t a, const pvec2_t b, const pvec2_t c, const pvec2_t d, pvec2_t point); boolean V2_Intercept2(const pvec2_t a, const pvec2_t b, const pvec2_t c, const pvec2_t d, pvec2_t point, float *abFrac, float *cdFrac); void V2_Lerp(pvec2_t dest, const pvec2_t a, const pvec2_t b, float c); void V2_InitBox(arvec2_t box, const pvec2_t point); void V2_AddToBox(arvec2_t box, const pvec2_t point); // 3-dimensions: void V3_Set(pvec3_t vec, vectorcomp_t x, vectorcomp_t y, vectorcomp_t z); void V3_SetFixed(pvec3_t vec, fixed_t x, fixed_t y, fixed_t z); float V3_Length(const pvec3_t vec); float V3_Distance(const pvec3_t a, const pvec3_t b); float V3_Normalize(pvec3_t vec); void V3_Copy(pvec3_t dest, const_pvec3_t src); void V3_Scale(pvec3_t vec, float scalar); void V3_Sum(pvec3_t dest, const_pvec3_t src1, const_pvec3_t src2); void V3_Subtract(pvec3_t dest, const_pvec3_t src1, const_pvec3_t src2); float V3_DotProduct(const_pvec3_t a, const_pvec3_t b); void V3_CrossProduct(pvec3_t dest, const pvec3_t src1, const pvec3_t src2); void V3_PointCrossProduct(pvec3_t dest, const pvec3_t v1, const pvec3_t v2, const pvec3_t v3); float V3_ClosestPointOnPlane(pvec3_t dest, const pvec3_t planeNormal, const pvec3_t planePoint, const pvec3_t arbPoint); int V3_MajorAxis(const pvec3_t vec); boolean V3_IsZero(const pvec3_t vec); void V3_Lerp(pvec3_t dest, const pvec3_t a, const pvec3_t b, float c); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_extres.h0000644000175000017500000000410411357170241023567 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_extres.h: External Resources */ #ifndef __DOOMSDAY_REFRESH_EXT_RES_H__ #define __DOOMSDAY_REFRESH_EXT_RES_H__ void R_InitResourceLocator(void); void R_ShutdownResourceLocator(void); void R_SetDataPath(const char* path); const char* R_GetDataPath(void); void R_PrependDataPath(char* newPath, const char* origPath, size_t len); void R_AddClassDataPath(ddresourceclass_t resClass, const char* addPath, boolean append); void R_ClearClassDataPath(ddresourceclass_t resClass); const char* R_GetClassDataPath(ddresourceclass_t resClass); boolean R_FindResource(resourcetype_t resType, char* fileName, const char* name, const char* optionalSuffix, size_t len); boolean R_FindResource2(resourcetype_t resType, ddresourceclass_t resClass, char* fileName, const char* name, const char*optionalSuffix, size_t len); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_pcx.h0000644000175000017500000000266011357170241023215 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_pcx.h: PCX Images */ #ifndef __DOOMSDAY_GRAPHICS_PCX_H__ #define __DOOMSDAY_GRAPHICS_PCX_H__ boolean PCX_GetSize(const char* fn, int* w, int* h); boolean PCX_Load(const char* fn, int bufW, int bufH, byte* outBuffer); boolean PCX_MemoryGetSize(const void* imageData, int* w, int* h); boolean PCX_MemoryLoad(const byte* imgdata, size_t len, int bufW, int bufH, byte* outBuffer); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/con_decl.h0000644000175000017500000000533111357170241023505 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * con_decl.h: Console Utility Macros */ #ifndef __DOOMSDAY_CONSOLE_DECL_H__ #define __DOOMSDAY_CONSOLE_DECL_H__ #include "con_main.h" /* * Macros for creating new console commands. */ #define C_CMD(name, params, fn) \ { ccmd_t _c = { name, params, CCmd##fn, 0 }; Con_AddCommand(&_c); } #define C_CMD_FLAGS(name, params, fn, flags) \ { ccmd_t _c = { name, params, CCmd##fn, flags }; Con_AddCommand(&_c); } // A handy helper for declaring console commands. #define D_CMD(x) int CCmd##x(byte src, int argc, char **argv) /* * Macros for creating new console variables. */ #define C_VAR(name, ptr, type, flags, min, max, notifyChanged) \ { cvar_t _v = { name, flags, type, ptr, min, max, notifyChanged }; \ Con_AddVariable(&_v); } #define C_VAR_BYTE(name, ptr, flags, min, max) \ C_VAR(name, ptr, CVT_BYTE, flags, min, max, NULL) #define C_VAR_INT(name, ptr, flags, min, max) \ C_VAR(name, ptr, CVT_INT, flags, min, max, NULL) #define C_VAR_FLOAT(name, ptr, flags, min, max) \ C_VAR(name, ptr, CVT_FLOAT, flags, min, max, NULL) #define C_VAR_CHARPTR(name, ptr, flags, min, max) \ C_VAR(name, ptr, CVT_CHARPTR, flags, min, max, NULL) // Same as above but allow for a change notification callback func #define C_VAR_BYTE2(name, ptr, flags, min, max, notifyChanged) \ C_VAR(name, ptr, CVT_BYTE, flags, min, max, notifyChanged) #define C_VAR_INT2(name, ptr, flags, min, max, notifyChanged) \ C_VAR(name, ptr, CVT_INT, flags, min, max, notifyChanged) #define C_VAR_FLOAT2(name, ptr, flags, min, max, notifyChanged) \ C_VAR(name, ptr, CVT_FLOAT, flags, min, max, notifyChanged) #define C_VAR_CHARPTR2(name, ptr, flags, min, max, notifyChanged) \ C_VAR(name, ptr, CVT_CHARPTR, flags, min, max, notifyChanged) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_png.h0000644000175000017500000000211211357170241023177 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * gl_png.h: PNG Images */ #ifndef __DOOMSDAY_PNG_H__ #define __DOOMSDAY_PNG_H__ unsigned char *PNG_Load(const char *fileName, int *width, int *height, int *pixelSize); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/def_data.h0000644000175000017500000005630111357170241023471 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * def_data.h: Doomsday Engine Definition Files * * \fixme Needs to be redesigned. */ #ifndef __DOOMSDAY_DED_FILES_H__ #define __DOOMSDAY_DED_FILES_H__ #ifdef __cplusplus extern "C" { #endif #include "def_share.h" #include "p_mapdata.h" // Version 6 does not require semicolons. #define DED_VERSION 6 #define DED_SPRITEID_LEN 4 #define DED_STRINGID_LEN 31 #define DED_PATH_LEN FILENAME_T_MAXLEN #define DED_FUNC_LEN 255 #define DED_MAX_SUB_MODELS 8 #define DED_MAX_MATERIAL_LAYERS 1 //// \temp typedef char ded_stringid_t[DED_STRINGID_LEN + 1]; typedef ded_stringid_t ded_string_t; typedef ded_stringid_t ded_mobjid_t; typedef ded_stringid_t ded_stateid_t; typedef ded_stringid_t ded_soundid_t; typedef ded_stringid_t ded_musicid_t; typedef ded_stringid_t ded_funcid_t; typedef char ded_func_t[DED_FUNC_LEN + 1]; typedef int ded_flags_t; typedef char* ded_anystring_t; typedef struct ded_count_s { int num, max; } ded_count_t; typedef struct { char path[DED_PATH_LEN + 1]; } ded_path_t; typedef struct { char id[DED_SPRITEID_LEN + 1]; } ded_sprid_t; typedef struct { char str[DED_STRINGID_LEN + 1]; } ded_str_t; typedef struct { ded_string_t name; material_namespace_t mnamespace; } ded_materialid_t; typedef struct { ded_flags_t id; // ID of this property ded_flags_t flags; ded_string_t name; ded_string_t flagPrefix; int map; } ded_xgclass_property_t; typedef struct { ded_stringid_t id; ded_string_t name; ded_count_t propertiesCount; ded_xgclass_property_t* properties; // The rest of the properties are retrieved at runtime // by querying the game for the callbacks for the // classes by "name"; int (C_DECL *doFunc)(); void (*initFunc)(linedef_t* line); int traverse; int travRef; int travData; int evTypeFlags; } ded_xgclass_t; typedef struct { ded_stringid_t id; ded_string_t text; int value; } ded_flag_t; typedef struct { ded_mobjid_t id; int doomEdNum; ded_string_t name; ded_stateid_t states[NUM_STATE_NAMES]; ded_soundid_t seeSound; ded_soundid_t attackSound; ded_soundid_t painSound; ded_soundid_t deathSound; ded_soundid_t activeSound; int reactionTime; int painChance; int spawnHealth; float speed; float radius; float height; int mass; int damage; ded_flags_t flags[NUM_MOBJ_FLAGS]; int misc[NUM_MOBJ_MISC]; } ded_mobj_t; typedef struct { ded_stateid_t id; // ID of this state. ded_sprid_t sprite; ded_flags_t flags; int frame; int tics; ded_funcid_t action; ded_stateid_t nextState; int misc[NUM_STATE_MISC]; ded_anystring_t execute; // Console command. } ded_state_t; typedef struct ded_lightmap_s { ded_stringid_t id; } ded_lightmap_t; typedef struct ded_flaremap_s { ded_stringid_t id; } ded_flaremap_t; typedef struct { ded_stateid_t state; char uniqueMapID[64]; float offset[3]; /* Origin offset in world coords Zero means automatic */ float size; // Zero: automatic float color[3]; // Red Green Blue (0,1) float lightLevel[2]; // Min/max lightlevel for bias ded_flags_t flags; ded_lightmap_t up, down, sides; ded_flaremap_t flare; float haloRadius; // Halo radius (zero = no halo). } ded_light_t; typedef struct { ded_path_t filename; ded_path_t skinFilename; // Optional; override model's skin. ded_string_t frame; int frameRange; ded_flags_t flags; // ASCII string of the flags. int skin; int skinRange; float offset[3]; // Offset XYZ within model. float alpha; float parm; // Custom parameter. unsigned char selSkinBits[2]; // Mask and offset. unsigned char selSkins[8]; ded_string_t shinySkin; float shiny; float shinyColor[3]; float shinyReact; blendmode_t blendMode; // bm_* } ded_submodel_t; typedef struct { ded_stringid_t id; // Optional identifier for the definition. ded_stateid_t state; int off; ded_sprid_t sprite; // Only used by autoscale. int spriteFrame; // Only used by autoscale. ded_flags_t group; int selector; ded_flags_t flags; float interMark; float interRange[2]; // 0-1 by default. int skinTics; // Tics per skin in range. float scale[3]; // Scale XYZ float resize; float offset[3]; // Offset XYZ float shadowRadius; // Radius for shadow (0=auto). ded_submodel_t sub[DED_MAX_SUB_MODELS]; } ded_model_t; typedef struct { ded_soundid_t id; // ID of this sound, refered to by others. ded_string_t lumpName; /* Actual lump name of the sound ("DS" not included). */ ded_string_t name; // A tag name for the sound. ded_soundid_t link; // Link to another sound. int linkPitch; int linkVolume; int priority; // Priority classification. int channels; // Max number of channels to occupy. int group; // Exclusion group. ded_flags_t flags; // Flags (like chg_pitch). ded_path_t ext; // External sound file (WAV). } ded_sound_t; typedef struct { ded_musicid_t id; // ID of this piece of music. ded_string_t lumpName; // Lump name. ded_path_t path; // External file (not a normal MUS file). int cdTrack; // 0 = no track. } ded_music_t; typedef struct { ded_flags_t flags; ded_materialid_t material; float offset; float colorLimit; } ded_skylayer_t; typedef struct ded_skymodel_s { ded_stringid_t id; int layer; // Defaults to -1. float frameInterval; // Seconds per frame. float yaw; float yawSpeed; // Angles per second. float coordFactor[3]; float rotate[2]; ded_anystring_t execute; // Executed on every frame change. float color[4]; // RGBA } ded_skymodel_t; #define NUM_SKY_LAYERS 2 #define NUM_SKY_MODELS 32 typedef struct ded_sky_s { ded_stringid_t id; ded_flags_t flags; // Flags. float height; float horizonOffset; float color[3]; // Color of sky-lit sectors. ded_skylayer_t layers[NUM_SKY_LAYERS]; ded_skymodel_t models[NUM_SKY_MODELS]; } ded_sky_t; typedef struct ded_mapinfo_s { ded_stringid_t id; // ID of the map (e.g. E2M3 or MAP21). ded_string_t name; // Name of the map. ded_string_t author; // Author of the map. ded_flags_t flags; // Flags. ded_musicid_t music; // Music to play. float parTime; // Par time, in seconds. float fogColor[3]; // Fog color (RGB). float fogStart; float fogEnd; float fogDensity; float ambient; // Ambient light level. float gravity; // 1 = normal. ded_stringid_t skyID; // ID of the sky definition to use with this map. If not set, use the sky data in the mapinfo. ded_sky_t sky; ded_anystring_t execute; // Executed during map setup (savegames, too). } ded_mapinfo_t; typedef struct { ded_stringid_t id; char* text; } ded_text_t; typedef struct { ded_stringid_t id; ded_count_t count; ded_materialid_t* materials; } ded_tenviron_t; typedef struct { char* id; char* text; } ded_value_t; typedef struct { ded_stringid_t id; ded_stringid_t before; ded_stringid_t after; char* script; } ded_finale_t; typedef struct { int id; char comment[64]; ded_flags_t flags[3]; ded_flags_t lineClass; ded_flags_t actType; int actCount; float actTime; int actTag; int aparm[9]; //ded_stringid_t aparm_str[3]; // aparms 4, 6, 9 ded_stringid_t aparm9; float tickerStart; float tickerEnd; int tickerInterval; ded_soundid_t actSound; ded_soundid_t deactSound; int evChain; int actChain; int deactChain; int actLineType; int deactLineType; ded_flags_t wallSection; ded_materialid_t actMaterial; ded_materialid_t deactMaterial; char actMsg[128]; char deactMsg[128]; float materialMoveAngle; float materialMoveSpeed; int iparm[20]; char iparmStr[20][64]; float fparm[20]; char sparm[5][128]; } ded_linetype_t; typedef struct { int id; char comment[64]; ded_flags_t flags; int actTag; int chain[5]; ded_flags_t chainFlags[5]; float start[5]; float end[5]; float interval[5][2]; int count[5]; ded_soundid_t ambientSound; float soundInterval[2]; // min,max float materialMoveAngle[2]; // floor, ceil float materialMoveSpeed[2]; // floor, ceil float windAngle; float windSpeed; float verticalWind; float gravity; float friction; ded_func_t lightFunc; int lightInterval[2]; ded_func_t colFunc[3]; // RGB int colInterval[3][2]; ded_func_t floorFunc; float floorMul, floorOff; int floorInterval[2]; ded_func_t ceilFunc; float ceilMul, ceilOff; int ceilInterval[2]; } ded_sectortype_t; typedef struct ded_detailtexture_s { ded_materialid_t material1; ded_materialid_t material2; ded_flags_t flags; ded_path_t detailLump; // The lump with the detail texture. boolean isExternal; // True, if detailLump is external. float scale; float strength; float maxDist; } ded_detailtexture_t; // Embedded sound information. typedef struct ded_embsound_s { ded_string_t name; int id; // Figured out at runtime. float volume; } ded_embsound_t; typedef struct { ded_flags_t type; int tics; float variance; // Stage variance (time). float color[4]; // RGBA float radius; float radiusVariance; ded_flags_t flags; float bounce; float resistance; // Air resistance. float gravity; float vectorForce[3]; float spin[2]; // Yaw and pitch. float spinResistance[2]; // Yaw and pitch. int model; ded_string_t frameName; // For model particles. ded_string_t endFrameName; short frame, endFrame; ded_embsound_t sound, hitSound; } ded_ptcstage_t; typedef struct ded_ptcgen_s { struct ded_ptcgen_s* stateNext; // List of generators for a state. ded_stateid_t state; // Triggered by this state (if mobj-gen). ded_materialid_t material; ded_mobjid_t type; // Triggered by this type of mobjs. ded_mobjid_t type2; // Also triggered by this type. int typeNum; int type2Num; ded_mobjid_t damage; // Triggered by mobj damage of this type. int damageNum; ded_string_t map; // Triggered by this map (or empty string). ded_flags_t flags; float speed; // Particle spawn velocity. float speedVariance; // Spawn speed variance (0-1). float vector[3]; // Particle launch vector. float vectorVariance; // Launch vector variance (0-1). 1=totally random. float initVectorVariance; // Initial launch vector variance (0-1). float center[3]; // Offset to the mobj (relat. to source). int subModel; // Model source: origin submodel #. float spawnRadius; float spawnRadiusMin; // Spawn uncertainty box. float maxDist; // Max visibility for particles. int spawnAge; // How long until spawning stops? int maxAge; // How long until generator dies? int particles; // Maximum number of particles. float spawnRate; // Particles spawned per tic. float spawnRateVariance; int preSim; // Tics to pre-simulate when spawned. int altStart; float altStartVariance; // Probability for alt start. float force; // Radial strength of the sphere force. float forceRadius; // Radius of the sphere force. float forceAxis[3]; /* Rotation axis of the sphere force (+ speed). */ float forceOrigin[3]; // Offset for the force sphere. ded_ptcstage_t* stages; ded_count_t stageCount; } ded_ptcgen_t; typedef struct ded_decorlight_s { float pos[2]; // Coordinates on the surface. float elevation; // Distance from the surface. float color[3]; // Light color. float radius; // Dynamic light radius (-1 = no light). float haloRadius; // Halo radius (zero = no halo). int patternOffset[2]; int patternSkip[2]; float lightLevels[2]; // Fade by sector lightlevel. int flareTexture; ded_lightmap_t up, down, sides; ded_flaremap_t flare; // Overrides flare_texture } ded_decorlight_t; // There is a fixed number of light decorations in each decoration. #define DED_DECOR_NUM_LIGHTS 16 typedef struct ded_decormodel_s { float pos[2]; // Coordinates on the surface. float elevation; // Distance from the surface. int patternOffset[2]; int patternSkip[2]; float lightLevels[2]; // Fade by sector lightlevel. ded_stringid_t id; float frameInterval; // Seconds per frame. } ded_decormodel_t; // There is a fixed number of model decorations in each decoration. #define DED_DECOR_NUM_MODELS 8 typedef struct ded_decor_s { ded_materialid_t material; ded_flags_t flags; ded_decorlight_t lights[DED_DECOR_NUM_LIGHTS]; ded_decormodel_t models[DED_DECOR_NUM_MODELS]; } ded_decor_t; typedef struct ded_reflection_s { ded_materialid_t material; ded_flags_t flags; blendmode_t blendMode; // Blend mode flags (bm_*). float shininess; float minColor[3]; ded_path_t shinyMap; ded_path_t maskMap; float maskWidth; float maskHeight; } ded_reflection_t; typedef struct ded_group_member_s { ded_materialid_t material; float tics; float randomTics; } ded_group_member_t; typedef struct ded_group_s { ded_flags_t flags; ded_count_t count; ded_group_member_t* members; } ded_group_t; typedef struct ded_material_layer_stage_s { ded_string_t name; // Material tex name. int type; // Material tex type, @see gltexture_type_t. int tics; float variance; // Stage variance (time). } ded_material_layer_stage_t; typedef struct ded_material_layer_s { ded_material_layer_stage_t* stages; ded_count_t stageCount; } ded_material_layer_t; typedef struct ded_material_s { ded_materialid_t id; ded_flags_t flags; float width, height; // In world units. ded_material_layer_t layers[DED_MAX_MATERIAL_LAYERS]; } ded_material_t; // The ded_t structure encapsulates all the data one definition file // can contain. This is only an internal representation of the data. // An ASCII version is written and read by DED_Write() and DED_Read() // routines. // It is VERY important not to sort the data arrays in any way: the // index numbers are important. The Game DLL must be recompiled with the // new constants if the order of the array items changes. typedef struct ded_s { int version; // DED version number. filename_t modelPath; // Directories for searching MD2s. ded_flags_t modelFlags; // Default values for models. float modelScale; float modelOffset; struct ded_counts_s { ded_count_t flags; ded_count_t mobjs; ded_count_t states; ded_count_t sprites; ded_count_t lights; ded_count_t materials; ded_count_t models; ded_count_t skies; ded_count_t sounds; ded_count_t music; ded_count_t mapInfo; ded_count_t text; ded_count_t textureEnv; ded_count_t values; ded_count_t details; ded_count_t ptcGens; ded_count_t finales; ded_count_t decorations; ded_count_t reflections; ded_count_t groups; ded_count_t lineTypes; ded_count_t sectorTypes; ded_count_t xgClasses; } count; // Flag values (for all types of data). ded_flag_t* flags; // Map object information. ded_mobj_t* mobjs; // States. ded_state_t* states; // Sprites. ded_sprid_t* sprites; // Lights. ded_light_t* lights; // Materials. ded_material_t* materials; // Models. ded_model_t* models; // Skies. ded_sky_t* skies; // Sounds. ded_sound_t* sounds; // Music. ded_music_t* music; // Map information. ded_mapinfo_t* mapInfo; // Text. ded_text_t* text; // Aural environments for textures. ded_tenviron_t* textureEnv; // Free-from string values. ded_value_t* values; // Detail texture assignments. ded_detailtexture_t* details; // Particle generators. ded_ptcgen_t* ptcGens; // Finales. ded_finale_t* finales; // Decorations. ded_decor_t* decorations; // Reflections. ded_reflection_t* reflections; // Animation/Precache groups for textures. ded_group_t* groups; // XG line types. ded_linetype_t* lineTypes; // XG sector types. ded_sectortype_t* sectorTypes; // XG Classes ded_xgclass_t* xgClasses; } ded_t; // Routines for managing DED files. void DED_Init(ded_t* ded); void DED_Destroy(ded_t* ded); int DED_Read(ded_t* ded, const char* sPathName); int DED_ReadLump(ded_t* ded, lumpnum_t lump); int DED_AddFlag(ded_t* ded, char* name, char* text, int value); int DED_AddMobj(ded_t* ded, char* idStr); int DED_AddState(ded_t* ded, char* id); int DED_AddSprite(ded_t* ded, const char* name); int DED_AddLight(ded_t* ded, const char* stateID); int DED_AddMaterial(ded_t* ded, const char* name); int DED_AddMaterialLayerStage(ded_material_layer_t* ml); int DED_AddModel(ded_t* ded, char* spr); int DED_AddSky(ded_t* ded, char* id); int DED_AddSound(ded_t* ded, char* id); int DED_AddMusic(ded_t* ded, char* id); int DED_AddMapInfo(ded_t* ded, char* str); int DED_AddText(ded_t* ded, char* id); int DED_AddTextureEnv(ded_t* ded, char* id); int DED_AddValue(ded_t *ded, const char* id); int DED_AddDetail(ded_t* ded, const char* lumpname); int DED_AddPtcGen(ded_t* ded, const char* state); int DED_AddPtcGenStage(ded_ptcgen_t* gen); int DED_AddFinale(ded_t* ded); int DED_AddDecoration(ded_t* ded); int DED_AddReflection(ded_t* ded); int DED_AddGroup(ded_t* ded); int DED_AddGroupMember(ded_group_t* grp); int DED_AddSectorType(ded_t* ded, int id); int DED_AddLineType(ded_t* ded, int id); int DED_AddXGClass(ded_t* ded); int DED_AddXGClassProperty(ded_xgclass_t* xgc); void DED_RemoveFlag(ded_t* ded, int index); void DED_RemoveMobj(ded_t* ded, int index); void DED_RemoveState(ded_t* ded, int index); void DED_RemoveSprite(ded_t* ded, int index); void DED_RemoveLight(ded_t* ded, int index); void DED_RemoveMaterial(ded_t* ded, int index); void DED_RemoveModel(ded_t* ded, int index); void DED_RemoveSky(ded_t* ded, int index); void DED_RemoveSound(ded_t* ded, int index); void DED_RemoveMusic(ded_t* ded, int index); void DED_RemoveMapInfo(ded_t* ded, int index); void DED_RemoveText(ded_t* ded, int index); void DED_RemoveTextureEnv(ded_t* ded, int index); void DED_RemoveValue(ded_t* ded, int index); void DED_RemoveDetail(ded_t* ded, int index); void DED_RemovePtcGen(ded_t* ded, int index); void DED_RemoveFinale(ded_t* ded, int index); void DED_RemoveDecoration(ded_t* ded, int index); void DED_RemoveReflection(ded_t* ded, int index); void DED_RemoveGroup(ded_t* ded, int index); void DED_RemoveSectorType(ded_t* ded, int index); void DED_RemoveLineType(ded_t* ded, int index); void DED_RemoveXGClass(ded_t* ded, int index); void* DED_NewEntries(void** ptr, ded_count_t* cnt, size_t elemSize, int count); void* DED_NewEntry(void** ptr, ded_count_t* cnt, size_t elemSize); void DED_DelEntry(int index, void** ptr, ded_count_t* cnt, size_t elemSize); void DED_DelArray(void** ptr, ded_count_t* cnt); void DED_ZCount(ded_count_t* c); extern char dedReadError[]; #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_think.h0000644000175000017500000000441711357170241023377 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_think.h: Thinkers */ #ifndef __DOOMSDAY_THINKER_H__ #define __DOOMSDAY_THINKER_H__ // think_t is a function pointer to a routine to handle an actor typedef void (*think_t) (); typedef struct thinker_s { struct thinker_s *prev, *next; think_t function; boolean inStasis; thid_t id; // Only used for mobjs (zero is not an ID). } thinker_t; boolean P_ThinkerListInited(void); void P_InitThinkerLists(byte flags); boolean P_IterateThinkers(think_t type, byte flags, boolean (*callback) (thinker_t* th, void*), void* context); void P_ThinkerAdd(thinker_t* th, boolean makePublic); void P_ThinkerRemove(thinker_t* th); void P_SetMobjID(thid_t id, boolean state); boolean P_IsUsedMobjID(thid_t id); boolean P_IsMobjThinker(think_t thinker); // Public interface: void DD_InitThinkers(void); void DD_RunThinkers(void); void DD_ThinkerAdd(thinker_t* th); void DD_ThinkerRemove(thinker_t* th); void DD_ThinkerSetStasis(thinker_t* th, boolean on); boolean DD_IterateThinkers(think_t func, boolean (*callback) (thinker_t*, void*), void* context); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_materialmanager.h0000644000175000017500000000542711357170241025415 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_materialmanager.h: Materials manager. */ #ifndef __DOOMSDAY_MATERIAL_MANAGER_H__ #define __DOOMSDAY_MATERIAL_MANAGER_H__ #include "gl_texmanager.h" extern materialnum_t numMaterialBinds; void P_MaterialManagerRegister(void); void P_MaterialManagerTicker(timespan_t time); void P_InitMaterialManager(void); void P_ShutdownMaterialManager(void); void P_DeleteMaterialTextures(material_namespace_t mnamespace); material_t* P_MaterialCreate(const char* name, short width, short height, byte flags, gltextureid_t tex, material_namespace_t mnamespace, ded_material_t* def); material_t* P_ToMaterial(materialnum_t num); materialnum_t P_ToMaterialNum(const material_t* mat); // Lookup: const char* P_GetMaterialName(material_t* mat); materialnum_t P_MaterialCheckNumForName(const char* name, material_namespace_t mnamespace); materialnum_t P_MaterialNumForName(const char* name, material_namespace_t mnamespace); material_t* P_GetMaterial(int ofTypeID, material_namespace_t mnamespace); materialnum_t P_MaterialCheckNumForIndex(uint idx, material_namespace_t mnamespace); materialnum_t P_MaterialNumForIndex(uint idx, material_namespace_t mnamespace); void P_MaterialPrecache(material_t* mat); // Anim groups: int R_NumAnimGroups(void); int R_CreateAnimGroup(int flags); void R_AddToAnimGroup(int animGroupNum, materialnum_t num, int tics, int randomTics); boolean R_IsInAnimGroup(int animGroupNum, material_t* mat); boolean R_IsPrecacheGroup(int groupNum); void R_DestroyAnimGroups(void); void R_ResetAnimGroups(void); void R_MaterialsPrecacheGroup(material_t* mat); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_list.h0000644000175000017500000000535011357170241023723 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_list.h: Rendering Lists */ #ifndef __DOOMSDAY_REND_LIST_H__ #define __DOOMSDAY_REND_LIST_H__ #include "r_data.h" // Multiplicative blending for dynamic lights? #define IS_MUL (dlBlend != 1 && !usingFog) // Types of rendering primitives. typedef enum primtype_e { PT_FIRST = 0, PT_TRIANGLE_STRIP = PT_FIRST, // Used for most stuff. PT_FAN, NUM_PRIM_TYPES } primtype_t; // Special rendpoly types. typedef enum { RPT_NORMAL = 0, RPT_SKY_MASK, // A sky mask polygon. RPT_LIGHT, // A dynamic light. RPT_SHADOW, // An object shadow or fakeradio edge shadow. RPT_SHINY // A shiny polygon. } rendpolytype_t; typedef struct rtexmapuint_s { DGLuint tex; int magMode; float blend; float scale[2], offset[2]; // For use with the texture matrix. blendmode_t blendMode; } rtexmapunit_t; extern int renderTextures; extern int renderWireframe; extern int useMultiTexLights; extern int useMultiTexDetails; extern float detailFactor, detailScale; extern int torchAdditive; extern float torchColor[]; void RL_Register(void); void RL_Init(void); boolean RL_IsMTexLights(void); boolean RL_IsMTexDetails(void); void RL_ClearLists(void); void RL_DeleteLists(void); void RL_AddPoly(primtype_t type, rendpolytype_t polyType, const rvertex_t* rvertices, const rtexcoord_t* rtexcoords, const rtexcoord_t* rtexcoords1, const rtexcoord_t* rtexcoords2, const rcolor_t* rcolors, uint numVertices, uint numLights, DGLuint modTex, float modColor[3], const rtexmapunit_t rTU[NUM_TEXMAP_UNITS]); void RL_RenderAllLists(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/s_mus.h0000644000175000017500000000320611357170241023064 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_mus.h: Music Subsystem */ #ifndef __DOOMSDAY_SOUND_MUSIC_H__ #define __DOOMSDAY_SOUND_MUSIC_H__ #include "con_decl.h" #include "sys_audiod_mus.h" // Music preference. If multiple resources are available, this setting // is used to determine which one to use (mus < ext < cd). enum { MUSP_MUS, MUSP_EXT, MUSP_CD }; extern int musPreference; void Mus_Register(void); boolean Mus_Init(void); void Mus_Shutdown(void); void Mus_SetVolume(float vol); void Mus_Pause(boolean doPause); void Mus_StartFrame(void); int Mus_Start(ded_music_t* def, boolean looped); void Mus_Stop(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_nodepile.h0000644000175000017500000000313411357170241024051 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * m_nodepile.h: Specialized Node Allocation */ #ifndef __DOOMSDAY_NODEPILE_H__ #define __DOOMSDAY_NODEPILE_H__ #define NP_ROOT_NODE ((void*) -1) struct linknode_s; // Defined in dd_share.h. typedef struct nodepile_s { int count; int pos; struct linknode_s *nodes; } nodepile_t; void NP_Init(nodepile_t *pile, int initial); nodeindex_t NP_New(nodepile_t *pile, void *ptr); void NP_Link(nodepile_t *pile, nodeindex_t node, nodeindex_t root); void NP_Unlink(nodepile_t *pile, nodeindex_t node); #define NP_Dismiss(pile, node) (pile->nodes[node].ptr = 0) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_hq2x.h0000644000175000017500000000223711357170241023305 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * gl_hq2x.h: High-Quality 2x Graphics Resizing */ #ifndef __DOOMSDAY_HQ2X_H__ #define __DOOMSDAY_HQ2X_H__ void GL_InitSmartFilter(void); void GL_SmartFilter2x(unsigned char *pIn, unsigned char *pOut, int Xres, int Yres, int BpL); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_console.h0000644000175000017500000000314011357170241024405 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2006 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * rend_console.h: Console Rendering. */ #ifndef __DOOMSDAY_CONSOLE_RENDER_H__ #define __DOOMSDAY_CONSOLE_RENDER_H__ extern int consoleAlpha, consoleLight; extern byte consoleShowFPS, consoleShadowText; void Rend_ConsoleRegister(void); void Rend_ConsoleInit(void); void Rend_ConsoleTicker(timespan_t time); void Rend_Console(void); void Rend_ConsoleFPS(int x, int y); void Rend_ConsoleOpen(int yes); void Rend_ConsoleMove(int numLines); void Con_DrawRuler(int y, int lineHeight, float alpha); void Con_InitUI(void); void Rend_ConsoleToggleFullscreen(void); void Rend_ConsoleCursorResetBlink(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_bmap.h0000644000175000017500000001273311357170241023201 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_bmap.h: Blockmaps */ #ifndef __DOOMSDAY_PLAYSIM_BLOCKMAP_H__ #define __DOOMSDAY_PLAYSIM_BLOCKMAP_H__ //// \todo This stuff is obsolete and needs to be removed! #define MAPBLOCKUNITS 128 #define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) #define MAPBLOCKSHIFT (FRACBITS+7) #define MAPBMASK (MAPBLOCKSIZE-1) #define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) byte bmapShowDebug; float bmapDebugSize; // Alloc/dealloc: blockmap_t* P_BlockmapCreate(const pvec2_t min, const pvec2_t max, uint width, uint height); // Management: void P_BlockmapSetBlock(blockmap_t* bmap, uint x, uint y, linedef_t** lines, linkmobj_t* moLink, linkpolyobj_t* poLink); void P_SSecBlockmapSetBlock(blockmap_t* bmap, uint x, uint y, subsector_t** ssecs); void P_BuildSubsectorBlockMap(gamemap_t* map); void P_BlockmapLinkMobj(blockmap_t* bmap, mobj_t* mo); boolean P_BlockmapUnlinkMobj(blockmap_t* bmap, mobj_t* mo); void P_BlockmapLinkPolyobj(blockmap_t* bmap, polyobj_t* po); void P_BlockmapUnlinkPolyobj(blockmap_t* bmap, polyobj_t* po); // Utility: void P_GetBlockmapBounds(blockmap_t* bmap, pvec2_t min, pvec2_t max); void P_GetBlockmapDimensions(blockmap_t* bmap, uint v[2]); boolean P_ToBlockmapBlockIdx(blockmap_t* bmap, uint destBlock[2], const pvec2_t sourcePos); void P_BoxToBlockmapBlocks(blockmap_t* bmap, uint blockBox[4], const arvec2_t box); // Block Iterators: boolean P_BlockmapMobjsIterator(blockmap_t* bmap, const uint block[2], boolean (*func) (struct mobj_s*, void*), void* data); boolean P_BlockmapLinesIterator(blockmap_t* bmap, const uint block[2], boolean (*func) (linedef_t*, void*), void* data); boolean P_BlockmapSubsectorsIterator(blockmap_t* bmap, const uint block[2], sector_t* sector, const arvec2_t box, int localValidCount, boolean (*func) (subsector_t*, void*), void* data); boolean P_BlockmapPolyobjsIterator(blockmap_t* bmap, const uint block[2], boolean (*func) (polyobj_t*, void*), void* data); boolean P_BlockmapPolyobjLinesIterator(blockmap_t* bmap, const uint block[2], boolean (*func) (linedef_t*, void*), void* data); // Block Box Iterators: boolean P_BlockBoxMobjsIterator(blockmap_t* bmap, const uint blockBox[4], boolean (*func) (struct mobj_s*, void*), void* data); boolean P_BlockBoxLinesIterator(blockmap_t* bmap, const uint blockBox[4], boolean (*func) (linedef_t*, void*), void* data); boolean P_BlockBoxSubsectorsIterator(blockmap_t* bmap, const uint blockBox[4], sector_t* sector, const arvec2_t box, int localValidCount, boolean (*func) (subsector_t*, void*), void* data); boolean P_BlockBoxPolyobjsIterator(blockmap_t* bmap, const uint blockBox[4], boolean (*func) (polyobj_t*, void*), void* data); boolean P_BlockBoxPolyobjLinesIterator(blockmap_t* bmap, const uint blockBox[4], boolean (*func) (linedef_t*, void*), void* data); // Specialized Traversals: boolean P_BlockPathTraverse(blockmap_t* bmap, const uint start[2], const uint end[2], const float origin[2], const float dest[2], int flags, boolean (*func) (intercept_t*)); // Misc: void P_BlockmapDebug(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/cl_player.h0000644000175000017500000000373511357170241023717 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cl_player.h: Clientside Player Management */ #ifndef __DOOMSDAY_CLIENT_PLAYER_H__ #define __DOOMSDAY_CLIENT_PLAYER_H__ #include "cl_mobj.h" typedef struct clplayerstate_s { clmobj_t *cmo; thid_t mobjId; int forwardMove; int sideMove; int angle; angle_t turnDelta; int friction; } clplayerstate_t; extern float pspMoveSpeed; extern float cplrThrustMul; extern clplayerstate_t clPlayerStates[DDMAXPLAYERS]; void Cl_InitPlayers(void); void Cl_LocalCommand(void); void Cl_MovePlayer(int plrnum); void Cl_MoveLocalPlayer(float dx, float dy, float dz, boolean onground); void Cl_UpdatePlayerPos(int plrnum); //void Cl_MovePsprites(void); void Cl_CoordsReceived(void); void Cl_HandlePlayerFix(void); int Cl_ReadPlayerDelta(void); void Cl_ReadPlayerDelta2(boolean skip); boolean Cl_IsFreeToMove(int plrnum); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_version.h0000644000175000017500000000470211357170241024074 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_version.h: Version Information */ #ifndef __DOOMSDAY_VERSION_H__ #define __DOOMSDAY_VERSION_H__ /** * Version number rules: (major).(minor).(revision)-(release) * * Major version will be 1 for now (few things short of a complete * rewrite will increase the major version). * * Minor version increases with important feature releases. * NOTE: No extra zeros. Numbering goes from 1 to 9 and continues from * 10 like 'normal' numbers. * * Revision number increases with each small (maintenance) release. */ #define DOOMSDAY_RELEASE_NAME "beta6.9" /** * Version constants. The Game module can use DOOMSDAY_VERSION to * verify that the engine is new enough. Don't change * DOOMSDAY_VERSION unless you wish to break compatibility. */ #define DOOMSDAY_VERSION 10900 // Don't touch; see above. #if defined(DOOMSDAY_RELEASE_NAME) # define DOOMSDAY_VERSION_TEXT "1.9.0-" DOOMSDAY_RELEASE_NAME #else # define DOOMSDAY_VERSION_TEXT "1.9.0" #endif #define DOOMSDAY_VERSION_NUMBER 1,9,0,0 // For WIN32 version info. #define DOOMSDAY_PROJECTURL "http://sourceforge.net/projects/deng/" /** * If DOOMSDAY_RELEASE_FULL is NOT defined, the Win32 version info * will be marked accordingly, indicating that this is a special build, * for example, an alpha/beta/release candidate/etc and the SpecialBuild * string will be populated with the content of DOOMSDAY_RELEASE_NAME. */ //#define DOOMSDAY_RELEASE_FULL 1 #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_timer.h0000644000175000017500000000252711357170241023761 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * sys_timer.h: Timing Subsystem */ #ifndef __DOOMSDAY_SYSTEM_TIMER_H__ #define __DOOMSDAY_SYSTEM_TIMER_H__ #include "dd_types.h" void Sys_InitTimer(void); void Sys_ShutdownTimer(void); int Sys_GetTime(void); double Sys_GetTimef(void); double Sys_GetSeconds(void); uint Sys_GetRealTime(void); double Sys_GetRealSeconds(void); void Sys_TicksPerSecond(float num); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/bsp_map.h0000644000175000017500000000271011357170241023356 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * GL-friendly BSP node builder. * bsp_level.h: Level structure read/write functions. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ #ifndef __BSP_LEVEL_H__ #define __BSP_LEVEL_H__ #include "p_mapdata.h" struct superblock_s; void BSP_InitForNodeBuild(gamemap_t* map); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_particle.h0000644000175000017500000001427611357170241024071 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_particle.h: Particle Generator Management */ #ifndef __DOOMSDAY_PARTICLES_H__ #define __DOOMSDAY_PARTICLES_H__ #include "def_data.h" #define MAX_ACTIVE_PTCGENS 256 #define MAX_PTC_TEXTURES 32 // Maximum # of textures in particle system #define MAX_PTC_MODELS 100 // Generator flags #define PGF_STATIC 0x1 // Can't be replaced by anything. #define PGF_RELATIVE_VELOCITY 0x2 // Particles inherit source's velocity. #define PGF_SPAWN_ONLY 0x4 // Generator is spawned only when source is being spawned. #define PGF_RELATIVE_VECTOR 0x8 // Rotate spawn vector w/mobj angle. #define PGF_ADD_BLEND 0x10 // Render using additive blending. #define PGF_FLOOR_SPAWN 0x20 // Flat-trig: spawn on floor. #define PGF_CEILING_SPAWN 0x40 // Flat-trig: spawn on ceiling. #define PGF_SPACE_SPAWN 0x80 // Flat-trig: spawn in air. #define PGF_PARTS_PER_128 0x100 // Definition specifies a density. #define PGF_MODEL_ONLY 0x200 // Only spawn if source is a 3D model. #define PGF_SCALED_RATE 0x400 // Spawn rate affected by a factor. #define PGF_GROUP 0x800 // Triggered by all in anim group. #define PGF_SUB_BLEND 0x1000 // Subtractive blending. #define PGF_REVSUB_BLEND 0x2000 // Reverse subtractive blending. #define PGF_MUL_BLEND 0x4000 // Multiplicative blending. #define PGF_INVMUL_BLEND 0x8000 // Inverse multiplicative blending. #define PGF_STATE_CHAIN 0x10000 // Chain after existing state gen(s). // Runtime generator flags: #define PGF_UNTRIGGERED 0x8000000 // Particle types typedef enum { PTC_NONE, PTC_POINT, PTC_LINE, // New types can be added here. PTC_TEXTURE = 100, // ...followed by MAX_PTC_TEXTURES types. PTC_MODEL = 1000 } ptc_type_e; // Particle flags #define PTCF_STAGE_TOUCH 0x1 // Touching ends current stage. #define PTCF_DIE_TOUCH 0x2 // Dies from first touch. #define PTCF_BRIGHT 0x4 // Fullbright. #define PTCF_SHADING 0x8 // Pseudo-3D. #define PTCF_PLANE_FLAT 0x10 // Touches a plane => render as flat. #define PTCF_STAGE_WALL_TOUCH 0x20 // Touch a wall => end stage. #define PTCF_STAGE_FLAT_TOUCH 0x40 // Touch a flat => end stage. #define PTCF_WALL_FLAT 0x80 // Touches a wall => render as flat. #define PTCF_SPHERE_FORCE 0x100 #define PTCF_ZERO_YAW 0x200 // Set particle yaw to zero. #define PTCF_ZERO_PITCH 0x400 // Set particle pitch to zero. #define PTCF_RANDOM_YAW 0x800 #define PTCF_RANDOM_PITCH 0x1000 typedef struct { int stage; // -1 => particle doesn't exist short tics; fixed_t pos[3]; // Coordinates. fixed_t mov[3]; // Momentum. sector_t* sector; // Updated when needed. linedef_t* contact; // Updated when lines hit/avoided. ushort yaw, pitch; // Rotation angles (0-65536 => 0-360). } particle_t; typedef struct { short type; short flags; fixed_t resistance; fixed_t bounce; fixed_t radius; fixed_t gravity; } ptcstage_t; // Particle Generator typedef struct ptcgen_s { thinker_t thinker; // Func = P_PtcGenThinker sector_t* sector; // Flat-triggered. int ceiling; // Flat-triggered. //float area; // Rough estimate of sector area. const ded_ptcgen_t* def; // The definition of this generator. mobj_t* source; // If mobj-triggered. int srcid; // Source mobj ID. int type; // Type-triggered; mobj type number (-1=none). int type2; // Type-triggered; alternate type. fixed_t center[3]; // Used by untriggered/damage gens. fixed_t vector[3]; // Converted from the definition. int flags; // PGF_* flags. float spawnCount; float spawnRateMultiplier; int spawnCP; // Spawn cursor. int age; int count; // Number of particles. particle_t* ptcs; // List of particles. ptcstage_t* stages; } ptcgen_t; typedef short ptcgenid_t; void P_PtcInit(void); void P_PtcInitForMap(void); void P_CreatePtcGenLinks(void); const ptcgen_t* P_IndexToPtcGen(ptcgenid_t ptcGenID); ptcgenid_t P_PtcGenToIndex(const ptcgen_t* gen); boolean P_IteratePtcGens(boolean (*callback) (ptcgen_t*, void*), void* context); boolean P_IterateSectorLinkedPtcGens(sector_t* sector, boolean (*callback) (ptcgen_t*, void*), void* context); void P_SpawnParticleGen(const ded_ptcgen_t* def, mobj_t* source); void P_SpawnTypeParticleGens(void); void P_SpawnMapParticleGens(const char* mapID); void P_SpawnDamageParticleGen(mobj_t* mo, mobj_t* inflictor, int amount); void P_CheckPtcPlanes(void); void P_UpdateParticleGens(void); float P_GetParticleRadius(const ded_ptcstage_t* stageDef, int ptcIndex); float P_GetParticleZ(const particle_t* pt); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_console.h0000644000175000017500000000236611357170241024304 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_console.h: Win32 Console */ #ifndef __DOOMSDAY_WINCONSOLE_H__ #define __DOOMSDAY_WINCONSOLE_H__ #include "sys_input.h" void Sys_ConInputInit(void); void Sys_ConInputShutdown(void); size_t I_GetConsoleKeyEvents(keyevent_t *evbuf, size_t bufsize); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_base.h0000644000175000017500000000255111357170241023322 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_base.h: Engine Core */ #ifndef __DOOMSDAY_BASE__ #define __DOOMSDAY_BASE__ #include "de_platform.h" #include "dd_def.h" #include "dd_share.h" #include "dd_api.h" #include "dd_plugin.h" #include "dd_wad.h" #include "dd_zone.h" #include "dd_main.h" #include "dd_input.h" #include "dd_loop.h" #include "dd_help.h" #include "dd_zip.h" // System headers needed everywhere. #include #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/b_context.h0000644000175000017500000000731711357170241023732 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_context.h: Bindings Contexts. */ #ifndef __DOOMSDAY_BIND_CONTEXT_H__ #define __DOOMSDAY_BIND_CONTEXT_H__ #include "de_base.h" #include "b_command.h" #include "b_device.h" typedef struct controlbinding_s { struct controlbinding_s* next; struct controlbinding_s* prev; int bid; // Unique identifier. int control; // Identifier of the player control. dbinding_t deviceBinds[DDMAXPLAYERS]; // Separate bindings for each local player. } controlbinding_t; // Binding Context Flags: #define BCF_ACTIVE 0x01 // Context is only used when it is active. #define BCF_PROTECTED 0x02 // Context cannot be #define BCF_ACQUIRE_KEYBOARD 0x04 // Context has acquired all keyboard states, unless // higher-priority contexts override it. #define BCF_ACQUIRE_ALL 0x08 // Context will acquire all unacquired states. typedef struct bcontext_s { char* name; // Name of the binding context. byte flags; evbinding_t commandBinds; // List of command bindings. controlbinding_t controlBinds; int (*fallbackResponder)(event_t* event); // event_t } bcontext_t; void B_UpdateDeviceStateAssociations(void); bcontext_t* B_NewContext(const char* name); void B_DestroyAllContexts(void); void B_ActivateContext(bcontext_t* bc, boolean doActivate); void B_AcquireKeyboard(bcontext_t* bc, boolean doAcquire); void B_AcquireAll(bcontext_t* bc, boolean doAcquire); void B_SetContextFallback(const char* name, int (*responderFunc)(event_t*)); bcontext_t* B_ContextByPos(int pos); bcontext_t* B_ContextByName(const char* name); int B_ContextCount(void); int B_GetContextPos(bcontext_t* bc); void B_ReorderContext(bcontext_t* bc, int pos); void B_ClearContext(bcontext_t* bc); void B_DestroyContext(bcontext_t* bc); controlbinding_t* B_FindControlBinding(bcontext_t* bc, int control); controlbinding_t* B_GetControlBinding(bcontext_t* bc, int control); void B_DestroyControlBinding(controlbinding_t* conBin); void B_InitControlBindingList(controlbinding_t* listRoot); void B_DestroyControlBindingList(controlbinding_t* listRoot); boolean B_DeleteBinding(bcontext_t* bc, int bid); boolean B_TryEvent(ddevent_t* event); boolean B_FindMatchingBinding(bcontext_t* bc, evbinding_t* match1, dbinding_t* match2, evbinding_t** evResult, dbinding_t** dResult); void B_PrintContexts(void); void B_PrintAllBindings(void); void B_WriteContextToFile(const bcontext_t* bc, FILE* file); #endif // __DOOMSDAY_BIND_CONTEXT_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_world.h0000644000175000017500000001251411357170241023410 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_world.h: World Setup and Refresh */ #ifndef __DOOMSDAY_REFRESH_WORLD_H__ #define __DOOMSDAY_REFRESH_WORLD_H__ #include "r_data.h" // Used for vertex sector owners, side line owners and reverb subsectors. typedef struct ownernode_s { void* data; struct ownernode_s* next; } ownernode_t; typedef struct { ownernode_t* head; uint count; } ownerlist_t; typedef struct skyfix_s { float height; } skyfix_t; extern int rendSkyLight; // cvar extern float rendLightWallAngle; extern byte rendLightWallAngleSmooth; extern boolean ddMapSetup; extern skyfix_t skyFix[2]; // [floor, ceiling] // Sky flags. #define SIF_DRAW_SPHERE 0x1 // Always draw the sky sphere. void R_SetupMap(int mode, int flags); void R_InitLinks(gamemap_t* map); void R_PolygonizeMap(gamemap_t* map); void R_BuildSectorLinks(gamemap_t* map); void R_SetupFog(float start, float end, float density, float* rgb); void R_SetupFogDefaults(void); void R_SetupSky(ded_sky_t* sky); const float* R_GetSectorLightColor(const sector_t* sector); float R_DistAttenuateLightLevel(float distToViewer, float lightLevel); float R_ExtraLightDelta(void); float R_CheckSectorLight(float lightlevel, float min, float max); boolean R_IsSkySurface(const surface_t* suf); boolean R_SectorContainsSkySurfaces(const sector_t* sec); void R_UpdatePlanes(void); void R_ClearSectorFlags(void); void R_InitSkyFix(void); void R_UpdateSkyFixForSec(const sector_t* sec); void R_OrderVertices(const linedef_t* line, const sector_t* sector, vertex_t* verts[2]); boolean R_FindBottomTop(segsection_t section, float segOffset, const surface_t* suf, const plane_t* ffloor, const plane_t* fceil, const plane_t* bfloor, const plane_t* bceil, boolean unpegBottom, boolean unpegTop, boolean stretchMiddle, boolean isSelfRef, float* bottom, float* top, float texOffset[2]); plane_t* R_NewPlaneForSector(sector_t* sec); void R_DestroyPlaneOfSector(uint id, sector_t* sec); surfacedecor_t* R_CreateSurfaceDecoration(decortype_t type, surface_t* suf); void R_ClearSurfaceDecorations(surface_t* suf); void R_UpdateWatchedPlanes(watchedplanelist_t* wpl); void R_InterpolateWatchedPlanes(watchedplanelist_t* wpl, boolean resetNextViewer); void R_AddWatchedPlane(watchedplanelist_t* wpl, plane_t* pln); boolean R_RemoveWatchedPlane(watchedplanelist_t* wpl, const plane_t* pln); void R_UpdateMovingSurfaces(void); void R_InterpolateMovingSurfaces(boolean resetNextViewer); void R_SurfaceListAdd(surfacelist_t* sl, surface_t* suf); boolean R_SurfaceListRemove(surfacelist_t* sl, const surface_t* suf); boolean R_SurfaceListIterate(surfacelist_t* sl, boolean (*callback) (surface_t* suf, void*), void* context); void R_MarkDependantSurfacesForDecorationUpdate(plane_t* pln); boolean R_IsGlowingPlane(const plane_t* pln); lineowner_t* R_GetVtxLineOwner(const vertex_t* vtx, const linedef_t* line); linedef_t* R_FindLineNeighbor(const sector_t* sector, const linedef_t* line, const lineowner_t* own, boolean antiClockwise, binangle_t* diff); linedef_t* R_FindSolidLineNeighbor(const sector_t* sector, const linedef_t* line, const lineowner_t* own, boolean antiClockwise, binangle_t* diff); linedef_t* R_FindLineBackNeighbor(const sector_t* sector, const linedef_t* line, const lineowner_t* own, boolean antiClockwise, binangle_t* diff); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_defer.h0000644000175000017500000000705111357170241023507 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_defer.h: Deferred GL Tasks */ #ifndef __DOOMSDAY_GRAPHICS_DEREF_H__ #define __DOOMSDAY_GRAPHICS_DEREF_H__ /** * Defines the content of a GL texture. Used when creating textures either * immediately or in deferred mode (when busy). */ typedef struct texturecontent_s { DGLuint name; void* buffer; size_t bufferSize; dgltexformat_t format; colorpaletteid_t palette; int width; int height; int minFilter; int magFilter; int anisoFilter; int wrap[2]; int grayMipmap; int flags; } texturecontent_t; // Flags for texture content. #define TXCF_NO_COMPRESSION 0x1 #define TXCF_MIPMAP 0x2 #define TXCF_GRAY_MIPMAP 0x4 #define TXCF_CONVERT_8BIT_TO_ALPHA 0x8 #define TXCF_APPLY_GAMMACORRECTION 0x10 #define TXCF_EASY_UPLOAD 0x20 #define TXCF_UPLOAD_ARG_ALPHACHANNEL 0x40 #define TXCF_UPLOAD_ARG_RGBDATA 0x80 #define TXCF_UPLOAD_ARG_NOSTRETCH 0x100 #define TXCF_UPLOAD_ARG_NOSMARTFILTER 0x200 #define TXCF_NEVER_DEFER 0x400 #define TXCF_GRAY_MIPMAP_LEVEL_SHIFT 24 #define TXCF_GRAY_MIPMAP_LEVEL_MASK 0xff000000 void GL_InitDeferred(void); void GL_ShutdownDeferred(void); void GL_UploadDeferredContent(uint timeOutMilliSeconds); int GL_GetDeferredCount(void); void GL_InitTextureContent(texturecontent_t* content); DGLuint GL_NewTexture(texturecontent_t* content, boolean* result); DGLuint GL_NewTextureWithParams(dgltexformat_t format, int width, int height, void* pixels, int flags); DGLuint GL_NewTextureWithParams2(dgltexformat_t format, int width, int height, void* pixels, int flags, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT); DGLuint GL_NewTextureWithParams3(dgltexformat_t format, int width, int height, void* pixels, int flags, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT); /// \todo should these be public? void GL_ReserveNames(void); void GL_ReleaseReservedNames(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_refresh.h0000644000175000017500000000260311357170241024044 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_refresh.h: Refresh Subsystem (Resource Management) */ #ifndef __DOOMSDAY_REFRESH__ #define __DOOMSDAY_REFRESH__ #include "p_materialmanager.h" #include "r_data.h" #include "r_main.h" #include "r_things.h" #include "r_model.h" #include "r_draw.h" #include "r_world.h" #include "r_shadow.h" #include "r_sky.h" #include "r_util.h" #include "r_extres.h" #include "r_shadow.h" #include "r_lgrid.h" #include "r_lumobjs.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/s_sfx.h0000644000175000017500000000602111357170241023056 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_sfx.h: Sound Effects */ #ifndef __DOOMSDAY_SOUND_SFX_H__ #define __DOOMSDAY_SOUND_SFX_H__ #include "sys_audiod.h" #include "sys_audiod_sfx.h" #include "de_play.h" // Begin and end macros for Critical Operations. They are operations // that can't be done while a refresh is being made. No refreshing // will be done between BEGIN_COP and END_COP. #define BEGIN_COP Sfx_AllowRefresh(false) #define END_COP Sfx_AllowRefresh(true) // Channel flags. #define SFXCF_NO_ORIGIN (0x1) // Sound is coming from a mystical emitter. #define SFXCF_NO_ATTENUATION (0x2) // Sound is very, very loud. #define SFXCF_NO_UPDATE (0x4) // Channel update is skipped. typedef struct sfxchannel_s { int flags; sfxbuffer_t* buffer; mobj_t* emitter; // Mobj that is emitting the sound. float pos[3]; // Emit from here (synced with emitter). float volume; // Sound volume: 1.0 is max. float frequency; // Frequency adjustment: 1.0 is normal. int startTime; // When was the channel last started? } sfxchannel_t; extern boolean sfxAvail; extern float sfxReverbStrength; extern int sfxMaxCacheKB, sfxMaxCacheTics; extern int sfxBits, sfxRate; extern int sfx3D, sfx16Bit, sfxSampleRate; boolean Sfx_Init(void); void Sfx_Shutdown(void); void Sfx_Reset(void); void Sfx_AllowRefresh(boolean allow); void Sfx_MapChange(void); void Sfx_StartFrame(void); void Sfx_EndFrame(void); void Sfx_PurgeCache(void); void Sfx_RefreshChannels(void); int Sfx_StartSound(sfxsample_t* sample, float volume, float freq, mobj_t* emitter, float* fixedpos, int flags); int Sfx_StopSound(int id, mobj_t* emitter); void Sfx_StopSoundGroup(int group, mobj_t* emitter); int Sfx_CountPlaying(int id); void Sfx_UnloadSoundID(int id); void Sfx_DebugInfo(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_huffman.h0000644000175000017500000000243511357170241023701 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_huffman.h: Huffman Codes */ #ifndef __DOOMSDAY_MISC_HUFFMAN_H__ #define __DOOMSDAY_MISC_HUFFMAN_H__ void Huff_Init(void); void Huff_Shutdown(void); void *Huff_Encode(byte *data, size_t size, size_t *encodedSize); byte *Huff_Decode(void *data, size_t size, size_t *decodedSize); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_misc.h0000644000175000017500000000261411357170241023343 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_misc.h: Miscellaneous Services */ #ifndef __DOOMSDAY_MISC__ #define __DOOMSDAY_MISC__ #include "m_misc.h" #include "m_args.h" #include "m_bams.h" #include "m_vector.h" #include "m_string.h" #include "m_nodepile.h" #include "m_filehash.h" #include "m_huffman.h" #include "m_vector.h" #include "m_profiler.h" #include "m_md5.h" #include "m_linkedlist.h" #include "m_binarytree.h" #include "m_gridmap.h" #include "m_decomp64.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_control.h0000644000175000017500000000351511357170241023740 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_control.h: Player Controls */ #ifndef __DOOMSDAY_PLAYER_CONTROL_H__ #define __DOOMSDAY_PLAYER_CONTROL_H__ // Public: void P_NewPlayerControl(int id, controltype_t type, const char *name, const char* bindContext); void P_GetControlState(int playerNum, int control, float* pos, float* relativeOffset); int P_GetImpulseControlState(int playerNum, int control); // Internal: typedef struct playercontrol_s { int id; controltype_t type; char* name; char* bindContextName; } playercontrol_t; void P_ControlRegister(void); void P_ControlShutdown(void); void P_ControlTicker(timespan_t time); playercontrol_t* P_PlayerControlById(int id); playercontrol_t* P_PlayerControlByName(const char* name); void P_Impulse(int playerNum, int control); void P_ImpulseByName(int playerNum, const char* control); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_defs.h0000644000175000017500000000221011357170241023321 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_defs.h: Definitions Subsystem */ #ifndef __DOOMSDAY_DEFINITIONS_H__ #define __DOOMSDAY_DEFINITIONS_H__ #include "def_main.h" #include "def_data.h" #include "def_share.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/tab_anorms.h0000644000175000017500000001300611357170241024062 0ustar keeskees/**\file *\section License * License: GPL * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © id Software, Inc. * * From Quake. */ #ifdef WIN32 #pragma warning(disable:4305) #endif {-0.525731, 0.000000, 0.850651}, {-0.442863, 0.238856, 0.864188}, {-0.295242, 0.000000, 0.955423}, {-0.309017, 0.500000, 0.809017}, {-0.162460, 0.262866, 0.951056}, {0.000000, 0.000000, 1.000000}, {0.000000, 0.850651, 0.525731}, {-0.147621, 0.716567, 0.681718}, {0.147621, 0.716567, 0.681718}, {0.000000, 0.525731, 0.850651}, {0.309017, 0.500000, 0.809017}, {0.525731, 0.000000, 0.850651}, {0.295242, 0.000000, 0.955423}, {0.442863, 0.238856, 0.864188}, {0.162460, 0.262866, 0.951056}, {-0.681718, 0.147621, 0.716567}, {-0.809017, 0.309017, 0.500000}, {-0.587785, 0.425325, 0.688191}, {-0.850651, 0.525731, 0.000000}, {-0.864188, 0.442863, 0.238856}, {-0.716567, 0.681718, 0.147621}, {-0.688191, 0.587785, 0.425325}, {-0.500000, 0.809017, 0.309017}, {-0.238856, 0.864188, 0.442863}, {-0.425325, 0.688191, 0.587785}, {-0.716567, 0.681718, -0.147621}, {-0.500000, 0.809017, -0.309017}, {-0.525731, 0.850651, 0.000000}, {0.000000, 0.850651, -0.525731}, {-0.238856, 0.864188, -0.442863}, {0.000000, 0.955423, -0.295242}, {-0.262866, 0.951056, -0.162460}, {0.000000, 1.000000, 0.000000}, {0.000000, 0.955423, 0.295242}, {-0.262866, 0.951056, 0.162460}, {0.238856, 0.864188, 0.442863}, {0.262866, 0.951056, 0.162460}, {0.500000, 0.809017, 0.309017}, {0.238856, 0.864188, -0.442863}, {0.262866, 0.951056, -0.162460}, {0.500000, 0.809017, -0.309017}, {0.850651, 0.525731, 0.000000}, {0.716567, 0.681718, 0.147621}, {0.716567, 0.681718, -0.147621}, {0.525731, 0.850651, 0.000000}, {0.425325, 0.688191, 0.587785}, {0.864188, 0.442863, 0.238856}, {0.688191, 0.587785, 0.425325}, {0.809017, 0.309017, 0.500000}, {0.681718, 0.147621, 0.716567}, {0.587785, 0.425325, 0.688191}, {0.955423, 0.295242, 0.000000}, {1.000000, 0.000000, 0.000000}, {0.951056, 0.162460, 0.262866}, {0.850651, -0.525731, 0.000000}, {0.955423, -0.295242, 0.000000}, {0.864188, -0.442863, 0.238856}, {0.951056, -0.162460, 0.262866}, {0.809017, -0.309017, 0.500000}, {0.681718, -0.147621, 0.716567}, {0.850651, 0.000000, 0.525731}, {0.864188, 0.442863, -0.238856}, {0.809017, 0.309017, -0.500000}, {0.951056, 0.162460, -0.262866}, {0.525731, 0.000000, -0.850651}, {0.681718, 0.147621, -0.716567}, {0.681718, -0.147621, -0.716567}, {0.850651, 0.000000, -0.525731}, {0.809017, -0.309017, -0.500000}, {0.864188, -0.442863, -0.238856}, {0.951056, -0.162460, -0.262866}, {0.147621, 0.716567, -0.681718}, {0.309017, 0.500000, -0.809017}, {0.425325, 0.688191, -0.587785}, {0.442863, 0.238856, -0.864188}, {0.587785, 0.425325, -0.688191}, {0.688191, 0.587785, -0.425325}, {-0.147621, 0.716567, -0.681718}, {-0.309017, 0.500000, -0.809017}, {0.000000, 0.525731, -0.850651}, {-0.525731, 0.000000, -0.850651}, {-0.442863, 0.238856, -0.864188}, {-0.295242, 0.000000, -0.955423}, {-0.162460, 0.262866, -0.951056}, {0.000000, 0.000000, -1.000000}, {0.295242, 0.000000, -0.955423}, {0.162460, 0.262866, -0.951056}, {-0.442863, -0.238856, -0.864188}, {-0.309017, -0.500000, -0.809017}, {-0.162460, -0.262866, -0.951056}, {0.000000, -0.850651, -0.525731}, {-0.147621, -0.716567, -0.681718}, {0.147621, -0.716567, -0.681718}, {0.000000, -0.525731, -0.850651}, {0.309017, -0.500000, -0.809017}, {0.442863, -0.238856, -0.864188}, {0.162460, -0.262866, -0.951056}, {0.238856, -0.864188, -0.442863}, {0.500000, -0.809017, -0.309017}, {0.425325, -0.688191, -0.587785}, {0.716567, -0.681718, -0.147621}, {0.688191, -0.587785, -0.425325}, {0.587785, -0.425325, -0.688191}, {0.000000, -0.955423, -0.295242}, {0.000000, -1.000000, 0.000000}, {0.262866, -0.951056, -0.162460}, {0.000000, -0.850651, 0.525731}, {0.000000, -0.955423, 0.295242}, {0.238856, -0.864188, 0.442863}, {0.262866, -0.951056, 0.162460}, {0.500000, -0.809017, 0.309017}, {0.716567, -0.681718, 0.147621}, {0.525731, -0.850651, 0.000000}, {-0.238856, -0.864188, -0.442863}, {-0.500000, -0.809017, -0.309017}, {-0.262866, -0.951056, -0.162460}, {-0.850651, -0.525731, 0.000000}, {-0.716567, -0.681718, -0.147621}, {-0.716567, -0.681718, 0.147621}, {-0.525731, -0.850651, 0.000000}, {-0.500000, -0.809017, 0.309017}, {-0.238856, -0.864188, 0.442863}, {-0.262866, -0.951056, 0.162460}, {-0.864188, -0.442863, 0.238856}, {-0.809017, -0.309017, 0.500000}, {-0.688191, -0.587785, 0.425325}, {-0.681718, -0.147621, 0.716567}, {-0.442863, -0.238856, 0.864188}, {-0.587785, -0.425325, 0.688191}, {-0.309017, -0.500000, 0.809017}, {-0.147621, -0.716567, 0.681718}, {-0.425325, -0.688191, 0.587785}, {-0.162460, -0.262866, 0.951056}, {0.442863, -0.238856, 0.864188}, {0.162460, -0.262866, 0.951056}, {0.309017, -0.500000, 0.809017}, {0.147621, -0.716567, 0.681718}, {0.000000, -0.525731, 0.850651}, {0.425325, -0.688191, 0.587785}, {0.587785, -0.425325, 0.688191}, {0.688191, -0.587785, 0.425325}, {-0.955423, 0.295242, 0.000000}, {-0.951056, 0.162460, 0.262866}, {-1.000000, 0.000000, 0.000000}, {-0.850651, 0.000000, 0.525731}, {-0.955423, -0.295242, 0.000000}, {-0.951056, -0.162460, 0.262866}, {-0.864188, 0.442863, -0.238856}, {-0.951056, 0.162460, -0.262866}, {-0.809017, 0.309017, -0.500000}, {-0.864188, -0.442863, -0.238856}, {-0.951056, -0.162460, -0.262866}, {-0.809017, -0.309017, -0.500000}, {-0.681718, 0.147621, -0.716567}, {-0.681718, -0.147621, -0.716567}, {-0.850651, 0.000000, -0.525731}, {-0.688191, 0.587785, -0.425325}, {-0.587785, 0.425325, -0.688191}, {-0.425325, 0.688191, -0.587785}, {-0.425325, -0.688191, -0.587785}, {-0.587785, -0.425325, -0.688191}, {-0.688191, -0.587785, -0.425325}, deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_clip.h0000644000175000017500000000403411357170241023675 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_clip.h: Clipper */ #ifndef __DOOMSDAY_RENDER_CLIP_H__ #define __DOOMSDAY_RENDER_CLIP_H__ #include "m_bams.h" extern int devNoCulling; void C_Init(void); boolean C_IsFull(void); void C_ClearRanges(void); void C_Ranger(void); // Debugging aid. int C_SafeAddRange(binangle_t startAngle, binangle_t endAngle); boolean C_IsPointVisible(float x, float y, float height); // Add a segment relative to the current viewpoint. void C_AddViewRelSeg(float x1, float y1, float x2, float y2); // Add an occlusion segment relative to the current viewpoint. void C_AddViewRelOcclusion(float *v1, float *v2, float height, boolean tophalf); // Check a segment relative to the current viewpoint. int C_CheckViewRelSeg(float x1, float y1, float x2, float y2); // Returns 1 if the specified angle is visible. int C_IsAngleVisible(binangle_t bang); // Returns 1 if the subsector might be visible. int C_CheckSubsector(subsector_t *ssec); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_ui.h0000644000175000017500000000222011357170241023016 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_ui.h: User Interface Subsystem */ #ifndef __DOOMSDAY_USER_INTERFACE_H__ #define __DOOMSDAY_USER_INTERFACE_H__ #include "ui_main.h" #include "ui_mpi.h" #include "ui_panel.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_audio.h0000644000175000017500000000264011357170241023736 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_audio.h: OS Specific Audio Drivers * * Not included in de_system.h because this is only needed by the * Sfx/Mus modules. */ #ifndef __DOOMSDAY_SYSTEM_AUDIO_H__ #define __DOOMSDAY_SYSTEM_AUDIO_H__ #include "sys_audiod.h" #include "sys_audiod_sfx.h" #include "sys_audiod_mus.h" #include "sys_audiod_loader.h" #include "sys_audiod_dummy.h" #include "sys_audiod_sdlmixer.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_window.h0000644000175000017500000001174211357170241024147 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_window.h: Window management. */ #ifndef __DOOMSDAY_SYS_WINDOW_H__ #define __DOOMSDAY_SYS_WINDOW_H__ #include "de_base.h" #if defined(UNIX) # include #endif #if defined(WIN32) # include #endif // Structure used to describe what features are available in a window // manager implementation. typedef struct wminfo_s { uint maxWindows; /* Max number of simultaneous windows of all supported types 0 = Unlimited. */ uint maxConsoles; boolean canMoveWindow; // Windows can be moved. } wminfo_t; typedef enum { WT_NORMAL, WT_CONSOLE } ddwindowtype_t; // Console commandline flags: #define CLF_CURSOR_LARGE 0x1 // Use the large command line cursor. typedef struct { ddwindowtype_t type; boolean inited; int x, y; // SDL cannot move windows; these are ignored. int width, height; int flags; #if defined(WIN32) HWND hWnd; // Needed for input (among other things). #endif union { struct { #if defined(WIN32) HGLRC glContext; #endif int bpp; } normal; struct { #if defined(WIN32) HANDLE hcScreen; CONSOLE_SCREEN_BUFFER_INFO cbInfo; WORD attrib; #elif defined(UNIX) WINDOW *winTitle, *winText, *winCommand; #endif int cx, cy; int needNewLine; struct { int flags; } cmdline; } console; }; } ddwindow_t; // Doomsday window flags. #define DDWF_VISIBLE 0x01 #define DDWF_FULLSCREEN 0x02 #define DDWF_CENTER 0x04 // Flags for Sys_SetWindow() #define DDSW_NOSIZE 0x01 #define DDSW_NOMOVE 0x02 #define DDSW_NOBPP 0x04 #define DDSW_NOVISIBLE 0x08 #define DDSW_NOFULLSCREEN 0x10 #define DDSW_NOCENTER 0x20 #define DDSW_NOCHANGES (DDSW_NOSIZE & DDSW_NOMOVE & DDSW_NOBPP & \ DDSW_NOFULLSCREEN & DDSW_NOVISIBLE & \ DDSW_NOCENTER) /** * Currently active window. There is always one active window, so no need * to worry about NULLs. The easiest way to get information about the * window where drawing is being is done. */ extern const ddwindow_t* theWindow; boolean Sys_InitWindowManager(void); boolean Sys_ShutdownWindowManager(void); boolean Sys_GetWindowManagerInfo(wminfo_t *info); boolean Sys_ChangeVideoMode(int width, int height, int bpp); boolean Sys_GetDesktopBPP(int *bpp); /** * Window management. */ uint Sys_CreateWindow(application_t *app, uint parentIDX, int x, int y, int w, int h, int bpp, int flags, ddwindowtype_t type, const char *title, void *data); boolean Sys_DestroyWindow(uint idx); void Sys_UpdateWindow(uint idx); boolean Sys_GetWindowDimensions(uint idx, int *x, int *y, int *w, int *h); boolean Sys_GetWindowBPP(uint idx, int *bpp); boolean Sys_GetWindowFullscreen(uint idx, boolean *fullscreen); boolean Sys_GetWindowVisibility(uint idx, boolean *show); boolean Sys_SetActiveWindow(uint idx); boolean Sys_SetWindow(uint idx, int x, int y, int w, int h, int bpp, uint wflags, uint uflags); boolean Sys_SetWindowTitle(uint idx, const char *title); // Console window routines. void Sys_ConPrint(uint idx, const char *text, int flags); void Sys_SetConWindowCmdLine(uint idx, const char *text, unsigned int cursorPos, int clflags); /** *\todo This is a compromise to prevent having to refactor half the * engine. In general, system specific patterns should not be carried * into the engine. */ #if defined(WIN32) HWND Sys_GetWindowHandle(uint idx); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_opengl.h0000644000175000017500000001072311357170241024122 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_opengl.h: OpenGL interface, low-level. */ #ifndef __DOOMSDAY_SYSTEM_OPENGL_H__ #define __DOOMSDAY_SYSTEM_OPENGL_H__ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include # include # include # include # include #endif #ifdef UNIX # define GL_GLEXT_PROTOTYPES # ifdef MACOSX # include # include # else # include # include # endif # define wglGetProcAddress SDL_GL_GetProcAddress #endif #include #define USE_MULTITEXTURE 1 #define MAX_TEX_UNITS 2 // More won't be used. // A helpful macro that changes the origin of the screen // coordinate system. #define FLIP(y) (theWindow->height - (y+1)) typedef enum arraytype_e { AR_VERTEX, AR_COLOR, AR_TEXCOORD0, AR_TEXCOORD1, AR_TEXCOORD2, AR_TEXCOORD3, AR_TEXCOORD4, AR_TEXCOORD5, AR_TEXCOORD6, AR_TEXCOORD7 } arraytype_t; typedef struct gl_state_s { int maxTexSize; int palExtAvailable; boolean allowCompression; boolean noArrays; boolean forceFinishBeforeSwap; int useAnisotropic; boolean useVSync; int maxAniso; int maxTexUnits; boolean useFog; float nearClip, farClip; float currentLineWidth, currentPointSize; int textureNonPow2; #if WIN32 int multisampleFormat; #endif } gl_state_t; typedef struct rgba_s { unsigned char color[4]; } rgba_t; typedef struct gl_state_texture_s { boolean usePalTex, dumpTextures, useCompr; float grayMipmapFactor; } gl_state_texture_t; typedef struct gl_state_ext_s { int multiTex; int texEnvComb; int nvTexEnvComb; int atiTexEnvComb; int aniso; int genMip; int blendSub; int s3TC; int lockArray; #if WIN32 int wglSwapIntervalEXT; int wglMultisampleARB; #endif } gl_state_ext_t; extern int polyCounter; extern gl_state_t GL_state; extern gl_state_texture_t GL_state_texture; extern gl_state_ext_t GL_state_ext; #ifdef WIN32 extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; extern PFNGLCLIENTACTIVETEXTUREARBPROC glClientActiveTextureARB; extern PFNGLACTIVETEXTUREARBPROC glActiveTextureARB; extern PFNGLMULTITEXCOORD2FARBPROC glMultiTexCoord2fARB; extern PFNGLMULTITEXCOORD2FVARBPROC glMultiTexCoord2fvARB; extern PFNGLBLENDEQUATIONEXTPROC glBlendEquationEXT; extern PFNGLLOCKARRAYSEXTPROC glLockArraysEXT; extern PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT; extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; extern PFNGLCOLORTABLEEXTPROC glColorTableEXT; #endif #ifndef GL_ATI_texture_env_combine3 #define GL_MODULATE_ADD_ATI 0x8744 #define GL_MODULATE_SIGNED_ADD_ATI 0x8745 #define GL_MODULATE_SUBTRACT_ATI 0x8746 #endif #ifndef GL_ATI_texture_env_combine3 #define GL_ATI_texture_env_combine3 1 #endif boolean Sys_PreInitGL(void); boolean Sys_InitGL(void); void Sys_ShutdownGL(void); void Sys_InitGLState(void); void Sys_InitGLExtensions(void); #ifdef WIN32 void Sys_InitWGLExtensions(void); #endif void Sys_PrintGLExtensions(void); boolean Sys_QueryGLExtension(const char* name, const GLubyte* extensions); void Sys_CheckGLError(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_things.h0000644000175000017500000002006511357170241023555 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_things.h: Object Management and Refresh */ #ifndef __DOOMSDAY_REFRESH_THINGS_H__ #define __DOOMSDAY_REFRESH_THINGS_H__ #include "p_mapdata.h" #include "r_data.h" #include "p_materialmanager.h" #include "rend_model.h" // Sprites are patches with a special naming convention so they can be // recognized by R_InitSprites. The sprite and frame specified by a // mobj is range checked at run time. // A sprite is a patch_t that is assumed to represent a three dimensional // object and may have multiple rotations pre drawn. Horizontal flipping // is used to save space. Some sprites will only have one picture used // for all views. typedef struct { boolean rotate; // If false use 0 for any position material_t* mats[8]; // Material to use for view angles 0-7 byte flip[8]; // Flip (1 = flip) to use for view angles 0-7 } spriteframe_t; typedef struct { char name[5]; int numFrames; spriteframe_t* spriteFrames; } spritedef_t; #define MAXVISSPRITES 8192 // These constants are used as the type of vissprite_s. typedef enum { VSPR_SPRITE, VSPR_MASKED_WALL, VSPR_MODEL, VSPR_FLARE } visspritetype_t; typedef struct rendmaskedwallparams_s { DGLuint tex; int magMode; boolean masked; blendmode_t blendMode; // Blendmode to be used when drawing // (two sided mid textures only) struct wall_vertex_s { float pos[3]; // x y and z coordinates. float color[4]; } vertices[4]; float texCoord[2][2]; // u and v coordinates. DGLuint modTex; // Texture to modulate with. float modTexCoord[2][2]; // u and v coordinates. float modColor[4]; } rendmaskedwallparams_t; typedef struct rendspriteparams_s { // Position/Orientation/Scale float center[3]; // The real center point. float width, height; float viewOffX; // View-aligned offset to center point. float srvo[3]; // Short-range visual offset. float distance; // Distance from viewer. boolean viewAligned; // Appearance boolean noZWrite; blendmode_t blendMode; // Material: material_t* mat; int tMap, tClass; float matOffset[2]; boolean matFlip[2]; // [S, T] Flip along the specified axis. // Lighting/color: float ambientColor[4]; uint vLightListIdx; // Misc struct subsector_s* subsector; } rendspriteparams_t; /** @name rendFlareFlags */ //@{ /// Do not draw a primary flare (aka halo). #define RFF_NO_PRIMARY 0x1 /// Flares do not turn in response to viewangle/viewdir #define RFF_NO_TURN 0x2 //@} typedef struct rendflareparams_s { byte flags; // @see rendFlareFlags. int size; float color[3]; byte factor; float xOff; DGLuint tex; // Flaremap if flareCustom ELSE (flaretexName id. // Zero = automatical) float mul; // Flare brightness factor. boolean isDecoration; uint lumIdx; } rendflareparams_t; #define MAX_VISSPRITE_LIGHTS (10) // A vissprite_t is a mobj or masked wall that will be drawn during // a refresh. typedef struct vissprite_s { struct vissprite_s* prev, *next; visspritetype_t type; // VSPR_* type of vissprite. float distance; // Vissprites are sorted by distance. float center[3]; // An anonymous union for the data. union vissprite_data_u { rendspriteparams_t sprite; rendmaskedwallparams_t wall; rendmodelparams_t model; rendflareparams_t flare; } data; } vissprite_t; typedef enum { VPSPR_SPRITE, VPSPR_MODEL } vispspritetype_t; typedef struct vispsprite_s { vispspritetype_t type; ddpsprite_t* psp; float center[3]; union vispsprite_data_u { struct vispsprite_sprite_s { subsector_t* subsector; float alpha; boolean isFullBright; } sprite; struct vispsprite_model_s { subsector_t* subsector; float gzt; // global top for silhouette clipping int flags; // for color translation and shadow draw uint id; int selector; int pClass; // player class (used in translation) float floorClip; boolean stateFullBright; boolean viewAligned; // Align to view plane. float secFloor, secCeil; float alpha; float visOff[3]; // Last-minute offset to coords. boolean floorAdjust; // Allow moving sprite to match visible floor. struct modeldef_s* mf, *nextMF; float yaw, pitch; float pitchAngleOffset; float yawAngleOffset; float inter; // Frame interpolation, 0..1 } model; } data; } vispsprite_t; typedef struct collectaffectinglights_params_s { float center[3]; float* ambientColor; subsector_t* subsector; boolean starkLight; // World light has a more pronounced effect. } collectaffectinglights_params_t; extern spritedef_t* sprites; extern int numSprites; extern float pspOffset[2], pspLightLevelMultiplier; extern int alwaysAlign; extern float weaponOffsetScale, weaponFOVShift; extern int weaponOffsetScaleY; extern float modelSpinSpeed; extern int maxModelDistance, noSpriteZWrite; extern int useSRVO, useSRVOAngle; extern vissprite_t visSprites[MAXVISSPRITES], *visSpriteP; extern vissprite_t visSprSortedHead; extern vispsprite_t visPSprites[DDMAXPSPRITES]; material_t* R_GetMaterialForSprite(int sprite, int frame); boolean R_GetSpriteInfo(int sprite, int frame, spriteinfo_t* sprinfo); boolean R_GetPatchInfo(lumpnum_t lump, patchinfo_t* info); float R_VisualRadius(struct mobj_s* mo); float R_GetBobOffset(struct mobj_s* mo); float R_MovementYaw(float momx, float momy); float R_MovementPitch(float momx, float momy, float momz); void R_ProjectSprite(struct mobj_s* mobj); void R_ProjectPlayerSprites(void); void R_SortVisSprites(void); vissprite_t* R_NewVisSprite(void); void R_AddSprites(subsector_t* ssec); void R_AddPSprites(void); void R_DrawSprites(void); void R_PreInitSprites(void); void R_InitSprites(void); void R_ClearSprites(void); void R_ClipVisSprite(vissprite_t* vis, int xl, int xh); uint R_CollectAffectingLights(const collectaffectinglights_params_t* params); void VL_InitForMap(void); void VL_InitForNewFrame(void); boolean VL_ListIterator(uint listIdx, void* data, boolean (*func) (const vlight_t*, void*)); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_seg.h0000644000175000017500000000235211357170241023034 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_seg.h: World segs. */ #ifndef __DOOMSDAY_WORLD_SEG_H__ #define __DOOMSDAY_WORLD_SEG_H__ #include "r_data.h" #include "p_dmu.h" boolean Seg_GetProperty(const seg_t *seg, setargs_t *args); boolean Seg_SetProperty(seg_t *seg, const setargs_t *args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/bsp_superblock.h0000644000175000017500000000716711357170241024765 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_superblock.h: Blockmap for half-edges * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ #ifndef __BSP_SUPERBLOCK_H__ #define __BSP_SUPERBLOCK_H__ #include "bsp_intersection.h" typedef struct superblock_s { // Parent of this block, or NULL for a top-level block. struct superblock_s* parent; // Coordinates on map for this block, from lower-left corner to // upper-right corner. Pseudo-inclusive, i.e (x,y) is inside block // if and only if BOXLEFT <= x < BOXRIGHT and BOXBOTTOM <= y < BOXTOP. int bbox[4]; // Sub-blocks. NULL when empty. [0] has the lower coordinates, and // [1] has the higher coordinates. Division of a square always // occurs horizontally (e.g. 512x512 -> 256x512 -> 256x256). struct superblock_s* subs[2]; // Number of real half-edges and minihedges contained by this block // (including all sub-blocks below it). int realNum; int miniNum; // List of half-edges completely contained by this block. struct hedge_s* hEdges; } superblock_t; void BSP_InitSuperBlockAllocator(void); void BSP_ShutdownSuperBlockAllocator(void); superblock_t* BSP_SuperBlockCreate(void); void BSP_SuperBlockDestroy(superblock_t* block); #if _DEBUG void BSP_SuperBlockPrintHEdges(superblock_t* superblock); #endif superblock_t* CreateHEdges(void); void BSP_LinkHEdgeToSuperBlock(superblock_t* superblock, hedge_t* hEdge); void BSP_IncSuperBlockHEdgeCounts(superblock_t* block, boolean lineLinked); boolean BSP_PickPartition(const superblock_t* hEdgeList, size_t depth, bspartition_t* partition); void BSP_FindNodeBounds(bspnodedata_t* node, superblock_t* hEdgeListRight, superblock_t* hEdgeListLeft); void BSP_DivideOneHEdge(hedge_t* hEdge, const bspartition_t* part, superblock_t* rightList, superblock_t* leftList, cutlist_t* cutList); void BSP_PartitionHEdges(superblock_t* hEdgeList, const bspartition_t* part, superblock_t* rightList, superblock_t* leftList, cutlist_t* cutList); void BSP_AddMiniHEdges(const bspartition_t* part, superblock_t* rightList, superblock_t* leftList, cutlist_t* cutList); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_intercept.h0000644000175000017500000000253011357170241024251 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_intercept.h: Line/Object Interception */ #ifndef __DOOMSDAY_PLAY_INTERCEPT_H__ #define __DOOMSDAY_PLAY_INTERCEPT_H__ void P_ClearIntercepts(void); intercept_t* P_AddIntercept(float frac, intercepttype_t type, void* ptr); void P_CalcInterceptDistances(const divline_t* strace); boolean P_TraverseIntercepts(traverser_t func, float maxfrac); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/gl_tga.h0000644000175000017500000000415611357170241023200 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * gl_tga.h: TGA Images */ #ifndef __TARGA_FILE_FORMAT_LIB__ #define __TARGA_FILE_FORMAT_LIB__ #include "sys_file.h" #ifdef __cplusplus extern "C" { #endif enum { TGA_FALSE, TGA_TRUE, TGA_TARGA24, // rgb888 TGA_TARGA32 // rgba8888 }; // Save the rgb565 buffer as Targa 16. int TGA_Save24_rgb565(const char* filename, int w, int h, const ushort* buffer); // Save the rgb888 buffer as Targa 24. int TGA_Save24_rgb888(const char* filename, int w, int h, const byte* buf); int TGA_Save24_rgba8888(const char* filename, int w, int h, const byte* buf); // Save the rgb888 buffer as Targa 16. int TGA_Save16_rgb888(const char* filename, int w, int h, const byte* buf); // Load an rgba8888 image (32 bits per pixel). int TGA_Load32_rgba8888(DFILE* file, int w, int h, byte* buf); // Get the dimensions of a Targa image. int TGA_GetSize(const char* filename, int* w, int* h); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/de_system.h0000644000175000017500000000273011357170241023733 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * de_system.h: Operating System Dependent Subsystems */ #ifndef __DOOMSDAY_SYSTEM__ #define __DOOMSDAY_SYSTEM__ #include "sys_system.h" #include "sys_console.h" #include "sys_direc.h" #include "sys_file.h" #include "sys_input.h" #include "sys_network.h" #include "sys_sock.h" #include "sys_master.h" #include "sys_timer.h" #include "sys_opengl.h" // Use SDL for window management under *nix #ifdef UNIX # define USING_SDL_WINDOW # include "../../unix/include/sys_path.h" #endif #include "sys_window.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_pinit.h0000644000175000017500000000321611357170241023531 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_pinit.h: Portable Engine Initialization */ #ifndef __DOOMSDAY_PORTABLE_INIT_H__ #define __DOOMSDAY_PORTABLE_INIT_H__ #include "dd_share.h" #include "dd_api.h" // Maximum allowed number of plugins. #define MAX_PLUGS 32 void DD_ShutdownAll(void); int DD_CheckArg(char* tag, const char** value); void DD_ErrorBox(boolean error, char* format, ...) PRINTF_F(2,3); void DD_ComposeMainWindowTitle(char* title); boolean DD_EarlyInit(void); void DD_InitAPI(void); void DD_InitCommandLine(const char* cmdLine); extern game_import_t gi; extern game_export_t gx; #endif // __DOOMSDAY_PORTABLE_INIT_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/r_data.h0000644000175000017500000002771111357170241023177 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_data.h: Data Structures For Refresh */ #ifndef __DOOMSDAY_REFRESH_DATA_H__ #define __DOOMSDAY_REFRESH_DATA_H__ #include "gl_main.h" #include "dd_def.h" #include "p_think.h" #include "m_nodepile.h" #include "def_data.h" #include "r_extres.h" // Flags for material decorations. #define DCRF_NO_IWAD 0x1 // Don't use if from IWAD. #define DCRF_PWAD 0x2 // Can use if from PWAD. #define DCRF_EXTERNAL 0x4 // Can use if from external resource. // Flags for material reflections. #define REFF_NO_IWAD 0x1 // Don't use if from IWAD. #define REFF_PWAD 0x2 // Can use if from PWAD. #define REFF_EXTERNAL 0x4 // Can use if from external resource. // Flags for material detailtexs. #define DTLF_NO_IWAD 0x1 // Don't use if from IWAD. #define DTLF_PWAD 0x2 // Can use if from PWAD. #define DTLF_EXTERNAL 0x4 // Can use if from external resource. typedef struct detailtex_s { gltextureid_t id; lumpnum_t lump; const char* external; } detailtex_t; typedef struct lightmap_s { gltextureid_t id; const char* external; } lightmap_t; typedef struct flaretex_s { gltextureid_t id; const char* external; } flaretex_t; typedef struct shinytex_s { gltextureid_t id; const char* external; } shinytex_t; typedef struct masktex_s { gltextureid_t id; const char* external; short width, height; } masktex_t; typedef enum { TU_PRIMARY = 0, TU_PRIMARY_DETAIL, TU_INTER, TU_INTER_DETAIL, NUM_TEXMAP_UNITS } gltexunit_t; typedef struct glcommand_vertex_s { float s, t; int index; } glcommand_vertex_t; #define RL_MAX_DIVS 64 typedef struct walldiv_s { unsigned int num; float pos[RL_MAX_DIVS]; } walldiv_t; typedef struct rvertex_s { float pos[3]; } rvertex_t; typedef struct rcolor_s { float rgba[4]; } rcolor_t; typedef struct rtexcoord_s { float st[2]; } rtexcoord_t; typedef struct shadowlink_s { struct shadowlink_s* next; linedef_t* lineDef; byte side; } shadowlink_t; typedef float colorcomp_t; typedef colorcomp_t rgbcol_t[3]; typedef colorcomp_t rgbacol_t[4]; typedef struct { lumpnum_t lump; short offX; // block origin (allways UL), which has allready short offY; // accounted for the patch's internal origin } texpatch_t; #define TXDF_NODRAW 0x0001 // Not to be drawn. #define TXDF_IWAD 0x0002 // Defines an IWAD texture. Note the definition may NOT be from the IWAD. // Describes a rectangular texture, which is composed of one // or more texpatch_t structures that arrange graphic patches. typedef struct { char name[9]; short width, height; short flags; short patchCount; texpatch_t patches[1]; // [patchcount] drawn back to front into the cached texture. } doomtexturedef_t; typedef struct flat_s { lumpnum_t lump; short width, height; } flat_t; typedef struct { lumpnum_t lump; // Real lump number. short width, height, offX, offY; } spritetex_t; // Model skin. typedef struct { filename_t path; gltextureid_t id; } skinname_t; // Patch flags. #define PF_MONOCHROME 0x1 #define PF_UPSCALE_AND_SHARPEN 0x2 // A patchtex is a lumppatch that has been prepared for render. typedef struct patchtex_s { lumpnum_t lump; short offX, offY; short extraOffset[2]; // Only used with upscaled and sharpened patches. int flags; // Possible modifier filters to apply (monochrome, scale+sharp) // Part 1 DGLuint tex; // Name of the associated DGL texture. short width, height; // Part 2 (only used with textures larger than the max texture size). DGLuint tex2; short width2, height2; struct patchtex_s* next; } patchtex_t; // A rawtex is a lump raw graphic that has been prepared for render. typedef struct rawtex_s { lumpnum_t lump; // Part 1 DGLuint tex; // Name of the associated DGL texture. short width, height; byte masked; // Part 2 (only used with textures larger than the max texture size). DGLuint tex2; short width2, height2; byte masked2; struct rawtex_s* next; } rawtex_t; typedef struct { float approxDist; // Only an approximation. float vector[3]; // Light direction vector. float color[3]; // How intense the light is (0..1, RGB). float offset; float lightSide, darkSide; // Factors for world light. boolean affectedByAmbient; } vlight_t; /** * Textures used in the lighting system. */ typedef enum lightingtexid_e { LST_DYNAMIC, // Round dynamic light LST_GRADIENT, // Top-down gradient LST_RADIO_CO, // FakeRadio closed/open corner shadow LST_RADIO_CC, // FakeRadio closed/closed corner shadow LST_RADIO_OO, // FakeRadio open/open shadow LST_RADIO_OE, // FakeRadio open/edge shadow NUM_LIGHTING_TEXTURES } lightingtexid_t; typedef enum flaretexid_e { FXT_ROUND, FXT_FLARE, // (flare) FXT_BRFLARE, // (brFlare) FXT_BIGFLARE, // (bigFlare) NUM_SYSFLARE_TEXTURES } flaretexid_t; /** * Textures used in world rendering. * eg a surface with a missing tex/flat is drawn using the "missing" graphic */ typedef enum ddtextureid_e { DDT_UNKNOWN, // Drawn if a texture/flat is unknown DDT_MISSING, // Drawn in place of HOMs in dev mode. DDT_BBOX, // Drawn when rendering bounding boxes DDT_GRAY, // For lighting debug. NUM_DD_TEXTURES } ddtextureid_t; typedef struct { DGLuint tex; } ddtexture_t; extern nodeindex_t* linelinks; extern blockmap_t* BlockMap; extern blockmap_t* SSecBlockMap; extern nodepile_t* mobjNodes, *lineNodes; extern int viewwidth, viewheight; extern int levelFullBright; extern int glowingTextures; extern byte precacheSprites, precacheSkins; extern int numFlats; extern flat_t** flats; extern spritetex_t** spriteTextures; extern int numSpriteTextures; extern detailtex_t** detailTextures; extern int numDetailTextures; extern lightmap_t** lightMaps; extern int numLightMaps; extern flaretex_t** flareTextures; extern int numFlareTextures; extern shinytex_t** shinyTextures; extern int numShinyTextures; extern masktex_t** maskTextures; extern int numMaskTextures; extern uint numSkinNames; extern skinname_t* skinNames; void R_InitRendVerticesPool(void); rvertex_t* R_AllocRendVertices(uint num); rcolor_t* R_AllocRendColors(uint num); rtexcoord_t* R_AllocRendTexCoords(uint num); void R_FreeRendVertices(rvertex_t* rvertices); void R_FreeRendColors(rcolor_t* rcolors); void R_FreeRendTexCoords(rtexcoord_t* rtexcoords); void R_InfoRendVerticesPool(void); void R_DivVerts(rvertex_t* dst, const rvertex_t* src, const walldiv_t* divs); void R_DivVertColors(rcolor_t* dst, const rcolor_t* src, const walldiv_t* divs, float bL, float tL, float bR, float tR); void R_DivTexCoords(rtexcoord_t* dst, const rtexcoord_t* src, const walldiv_t* divs, float bL, float tL, float bR, float tR); void R_UpdateTexturesAndFlats(void); void R_InitTextures(void); void R_InitFlats(void); void R_InitData(void); void R_UpdateData(void); void R_ShutdownData(void); colorpaletteid_t R_CreateColorPalette(const char* fmt, const char* name, const byte* data, ushort num); const char* R_GetColorPaletteNameForNum(colorpaletteid_t id); colorpaletteid_t R_GetColorPaletteNumForName(const char* name); DGLuint R_GetColorPalette(colorpaletteid_t id); void R_GetColorPaletteRGBf(colorpaletteid_t id, float rgb[3], int idx, boolean correctGamma); boolean R_SetDefaultColorPalette(colorpaletteid_t id); //boolean R_UpdateSubSector(struct subsector_t* ssec, boolean forceUpdate); boolean R_UpdateSector(struct sector_s* sec, boolean forceUpdate); boolean R_UpdateLinedef(struct linedef_s* line, boolean forceUpdate); boolean R_UpdateSidedef(struct sidedef_s* side, boolean forceUpdate); boolean R_UpdatePlane(struct plane_s* pln, boolean forceUpdate); boolean R_UpdateSurface(struct surface_s* suf, boolean forceUpdate); void R_PrecacheMap(void); void R_PrecacheMobjNum(int mobjtypeNum); void R_PrecachePatch(lumpnum_t lump); doomtexturedef_t* R_GetDoomTextureDef(int num); uint R_GetSkinNumForName(const char* path); const skinname_t* R_GetSkinNameByIndex(uint id); uint R_RegisterSkin(char* fullpath, const char* skin, const char* modelfn, boolean isShinySkin, size_t len); void R_DestroySkins(void); // Called at shutdown. void R_InitAnimGroup(ded_group_t* def); detailtex_t* R_CreateDetailTexture(const ded_detailtexture_t* def); detailtex_t* R_GetDetailTexture(lumpnum_t lump, const char* external); void R_DestroyDetailTextures(void); // Called at shutdown. lightmap_t* R_CreateLightMap(const ded_lightmap_t* def); lightmap_t* R_GetLightMap(const char* external); void R_DestroyLightMaps(void); // Called at shutdown. flaretex_t* R_CreateFlareTexture(const ded_flaremap_t* def); flaretex_t* R_GetFlareTexture(const char* external); void R_DestroyFlareTextures(void); // Called at shutdown. shinytex_t* R_CreateShinyTexture(const ded_reflection_t* def); shinytex_t* R_GetShinyTexture(const char* external); void R_DestroyShinyTextures(void); // Called at shutdown. masktex_t* R_CreateMaskTexture(const ded_reflection_t* def); masktex_t* R_GetMaskTexture(const char* external); void R_DestroyMaskTextures(void); // Called at shutdown. patchtex_t* R_FindPatchTex(lumpnum_t lump); // May return NULL. patchtex_t* R_GetPatchTex(lumpnum_t lump); // Creates new entries. patchtex_t** R_CollectPatchTexs(int* count); rawtex_t* R_FindRawTex(lumpnum_t lump); // May return NULL. rawtex_t* R_GetRawTex(lumpnum_t lump); // Creates new entries. rawtex_t** R_CollectRawTexs(int* count); boolean R_IsAllowedDecoration(ded_decor_t* def, material_t* mat, boolean hasExternal); boolean R_IsAllowedReflection(ded_reflection_t* def, material_t* mat, boolean hasExternal); boolean R_IsAllowedDetailTex(ded_detailtexture_t* def, material_t* mat, boolean hasExternal); boolean R_IsValidLightDecoration(const ded_decorlight_t* lightDef); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/bsp_node.h0000644000175000017500000000526411357170241023535 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_node.h: BSP node builder. Recursive node creation. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ #ifndef __BSP_NODE_H__ #define __BSP_NODE_H__ #include "bsp_edge.h" #include "bsp_intersection.h" #include "m_binarytree.h" #include "p_mapdata.h" typedef struct bspartition_s { double x, y; double dX, dY; double length; linedef_t* lineDef; // Not NULL if partition originated from a linedef. linedef_t* sourceLine; double pSX, pSY; double pDX, pDY; double pPara, pPerp; } bspartition_t; typedef struct bspnodedata_s { partition_t partition; float bBox[2][4]; // Bounding box for each child. // Node index. Only valid once the NODES or GL_NODES lump has been // created. int index; } bspnodedata_t; boolean BuildNodes(struct superblock_s *hEdgeList, binarytree_t **parent, size_t depth, cutlist_t *cutList); void BSP_AddHEdgeToSuperBlock(struct superblock_s *block, hedge_t *hEdge); void ClockwiseBspTree(binarytree_t *rootNode); void SaveMap(gamemap_t *dest, void *rootNode, vertex_t ***vertexes, uint *numVertexes); typedef struct bspleafdata_s { struct hedge_s* hEdges; // Head ptr to a list of half-edges at this leaf. } bspleafdata_t; bspleafdata_t *BSPLeaf_Create(void); void BSPLeaf_Destroy(bspleafdata_t *leaf); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dd_wad.h0000644000175000017500000000617211357170241023165 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dd_wad.h: WAD Files and Data Lump Cache */ #ifndef __DOOMSDAY_WAD_H__ #define __DOOMSDAY_WAD_H__ #include "sys_file.h" #include "con_decl.h" #define RECORD_FILENAMELEN FILENAME_T_MAXLEN // File record flags. #define FRF_RUNTIME 0x1 // Loaded at runtime (for reset). #define AUXILIARY_BASE 100000000 // Lump Grouping Tags typedef enum { LGT_NONE = 0, LGT_FLATS, LGT_SPRITES, NUM_LGTAGS } lumpgrouptag_t; typedef struct { filename_t fileName; // Full filename (every '\' -> '/'). int numLumps; // Number of lumps. int flags; DFILE* handle; // File handle. char iwad; } filerecord_t; extern char* defaultWads; // A list of wad names, whitespace in between (in .cfg). extern int numLumps; void DD_RegisterVFS(void); void W_InitMultipleFiles(char** fileNames); void W_EndStartup(void); lumpnum_t W_CheckNumForName(const char* name); lumpnum_t W_GetNumForName(const char* name); size_t W_LumpLength(lumpnum_t lump); const char* W_LumpName(lumpnum_t lump); void W_ReadLump(lumpnum_t lump, void* dest); void W_ReadLumpSection(lumpnum_t lump, void* dest, size_t startOffset, size_t length); const void* W_CacheLumpNum(lumpnum_t lump, int tag); const void* W_CacheLumpName(const char* name, int tag); boolean W_AddFile(const char* fileName, boolean allowDuplicate); boolean W_RemoveFile(const char* fileName); void W_Reset(void); lumpnum_t W_OpenAuxiliary(const char* fileName); void W_ChangeCacheTag(lumpnum_t lump, int tag); void W_CheckIWAD(void); boolean W_IsFromIWAD(lumpnum_t lump); const char* W_LumpSourceFile(lumpnum_t lump); unsigned int W_CRCNumberForRecord(int idx); unsigned int W_CRCNumber(void); void W_GetIWADFileName(char* buf, size_t bufSize); void W_GetPWADFileNames(char* buf, size_t bufSize, char separator); boolean W_DumpLump(lumpnum_t, const char* fileName); void W_DumpLumpDir(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_polyob.h0000644000175000017500000000425111357170241023562 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_polyob.h: Polygon Objects */ #ifndef __DOOMSDAY_POLYOB_H__ #define __DOOMSDAY_POLYOB_H__ // We'll use the base polyobj template directly as our mobj. typedef struct polyobj_s { DD_BASE_POLYOBJ_ELEMENTS()} polyobj_t; #define POLYOBJ_SIZE gx.polyobjSize extern polyobj_t** polyObjs; // List of all poly-objects on the map. extern uint numPolyObjs; // Polyobj system. void P_MapInitPolyobjs(void); void P_SetPolyobjCallback(void (*func) (struct mobj_s*, void*, void*)); polyobj_t* P_GetPolyobj(uint num); boolean P_IsPolyobjOrigin(void* ddMobjBase); // Polyobject interface. boolean P_PolyobjMove(struct polyobj_s* po, float x, float y); boolean P_PolyobjRotate(struct polyobj_s* po, angle_t angle); void P_PolyobjLink(struct polyobj_s* po); void P_PolyobjUnLink(struct polyobj_s* po); void P_PolyobjUpdateBBox(polyobj_t* po); void P_PolyobjLinkToRing(polyobj_t* po, linkpolyobj_t** link); void P_PolyobjUnlinkFromRing(polyobj_t* po, linkpolyobj_t** link); boolean P_PolyobjLinesIterator(polyobj_t* po, boolean (*func) (struct linedef_s*, void*), void* data); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_halo.h0000644000175000017500000000332511357170241023673 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_halo.h: Halos and Flares */ #ifndef __DOOMSDAY_RENDER_HALO_H__ #define __DOOMSDAY_RENDER_HALO_H__ #include "con_decl.h" extern int haloOccludeSpeed; extern int haloMode, haloRealistic, haloBright, haloSize; extern float haloFadeMax, haloFadeMin, minHaloSize; void H_Register(void); void H_SetupState(boolean dosetup); boolean H_RenderHalo(float x, float y, float z, float size, DGLuint tex, const float color[3], float distanceToViewer, float occlusionFactor, float brightnessFactor, float viewXOffset, boolean primary, boolean viewRelativeRotate); // Console commands. D_CMD(FlareConfig); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_maputil.h0000644000175000017500000001551211357170241023733 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputil.h: Map Utility Routines */ #ifndef __DOOMSDAY_MAP_UTILITIES_H__ #define __DOOMSDAY_MAP_UTILITIES_H__ #include "m_vector.h" #include "p_object.h" #define MAXINTERCEPTS 128 #define IS_SECTOR_LINKED(mo) ((mo)->sPrev != NULL) #define IS_BLOCK_LINKED(mo) ((mo)->bNext != NULL) extern float opentop, openbottom, openrange, lowfloor; extern divline_t traceLOS; float P_AccurateDistanceFixed(fixed_t dx, fixed_t dy); float P_AccurateDistance(float dx, float dy); float P_ApproxDistance(float dx, float dy); float P_ApproxDistance3(float dx, float dy, float dz); void P_LineUnitVector(linedef_t *line, float *unitvec); float P_MobjPointDistancef(mobj_t *start, mobj_t *end, float *fixpoint); int P_PointOnLinedefSide(float x, float y, const linedef_t* line); int P_PointOnLinedefSide2(double pointX, double pointY, double lineDX, double lineDY, double linePerp, double lineLength, double epsilon); int P_BoxOnLineSide(const float* tmbox, const linedef_t* ld); int P_BoxOnLineSide2(float xl, float xh, float yl, float yh, const linedef_t *ld); int P_BoxOnLineSide3(const int bbox[4], double lineSX, double lineSY, double lineDX, double lineDY, double linePerp, double lineLength, double epsilon); void P_MakeDivline(const linedef_t* li, divline_t* dl); int P_PointOnDivlineSide(float x, float y, const divline_t* line); float P_InterceptVector(const divline_t* v2, const divline_t* v1); int P_PointOnDivLineSidef(fvertex_t *pnt, fdivline_t *dline); float P_FloatInterceptVertex(fvertex_t *start, fvertex_t *end, fdivline_t *fdiv, fvertex_t *inter); void P_LineOpening(linedef_t* linedef); void P_MobjLink(mobj_t* mo, byte flags); int P_MobjUnlink(mobj_t* mo); boolean P_MobjUnlinkFromRing(mobj_t* mo, linkmobj_t** list); void P_MobjLinkToRing(mobj_t* mo, linkmobj_t** link); boolean PIT_AddLineIntercepts(linedef_t *ld, void *data); boolean PIT_AddMobjIntercepts(mobj_t *mo, void *data); boolean P_MobjLinesIterator(mobj_t *mo, boolean (*func) (linedef_t *, void *), void *); boolean P_MobjSectorsIterator(mobj_t *mo, boolean (*func) (sector_t *, void *), void *data); boolean P_LineMobjsIterator(linedef_t *line, boolean (*func) (mobj_t *, void *), void *data); boolean P_SectorTouchingMobjsIterator(sector_t *sector, boolean (*func) (mobj_t *, void *), void *data); // Mobjs in bounding box iterators. boolean P_MobjsBoxIterator(const float box[4], boolean (*func) (mobj_t *, void *), void *data); boolean P_MobjsBoxIteratorv(const arvec2_t box, boolean (*func) (mobj_t *, void *), void *data); // Lines in bounding box iterators. boolean P_LinesBoxIterator(const float box[4], boolean (*func) (linedef_t *, void *), void *data); boolean P_LinesBoxIteratorv(const arvec2_t box, boolean (*func) (linedef_t *, void *), void *data); // Polyobj in bounding box iterators. boolean P_PolyobjsBoxIterator(const float box[4], boolean (*func) (polyobj_t *, void *), void *data); boolean P_PolyobjsBoxIteratorv(const arvec2_t box, boolean (*func) (polyobj_t *, void *), void *data); // (Polyobj in bounding box)->lineDefs iterators. boolean P_PolyobjLinesBoxIterator(const float box[4], boolean (*func) (linedef_t *, void *), void *data); boolean P_PolyobjLinesBoxIteratorv(const arvec2_t box, boolean (*func) (linedef_t *, void *), void *data); // Lines and (Polyobj in bounding box)->lineDefs iterators. // Polyobj lines are iterated first. boolean P_AllLinesBoxIterator(const float box[4], boolean (*func) (linedef_t *, void *), void *data); boolean P_AllLinesBoxIteratorv(const arvec2_t box, boolean (*func) (linedef_t *, void *), void *data); // Subsectors in bounding box iterators. boolean P_SubsectorsBoxIterator(const float box[4], sector_t *sector, boolean (*func) (subsector_t *, void *), void *parm); boolean P_SubsectorsBoxIteratorv(const arvec2_t box, sector_t *sector, boolean (*func) (subsector_t *, void *), void *data); boolean P_PathTraverse(float x1, float y1, float x2, float y2, int flags, boolean (*trav) (intercept_t *)); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/b_main.h0000644000175000017500000000364311357170241023170 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * b_main.h: Bindings */ #ifndef __DOOMSDAY_BIND_MAIN_H__ #define __DOOMSDAY_BIND_MAIN_H__ #define DEFAULT_BINDING_CONTEXT_NAME "game" #define CONSOLE_BINDING_CONTEXT_NAME "console" #define UI_BINDING_CONTEXT_NAME "deui" void B_Register(void); void B_Init(void); void B_Shutdown(void); boolean B_Delete(int bid); boolean B_Responder(ddevent_t* ev); void B_WriteToFile(FILE* file); struct evbinding_s* B_BindCommand(const char* eventDesc, const char* command); struct dbinding_s* B_BindControl(const char* controlDesc, const char* device); struct dbinding_s* B_GetControlDeviceBindings(int localNum, int control, struct bcontext_s** bContext); // Utils //// \todo: move to b_util.h int B_NewIdentifier(void); const char* B_ShortNameForKey(int ddkey); int B_KeyForShortName(const char* key); int DD_GetKeyCode(const char* key); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/dam_blockmap.h0000644000175000017500000000301311357170241024343 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dam_blockmap.h: BlockMap generation. * * Generate valid blockmap data from the already loaded map data. * Adapted from algorithm used in prBoom 2.2.6 -DJS * * Algorithm is order of nlines*(ncols+nrows) not nlines*ncols*nrows */ #ifndef __DOOMSDAY_ARCHIVED_MAP_BLOCKMAP_H__ #define __DOOMSDAY_ARCHIVED_MAP_BLOCKMAP_H__ #include "p_mapdata.h" blockmap_t* DAM_BuildBlockMap(vertex_t*** vertexes, uint* numVertexes, linedef_t** lineDefs, uint* numLineDefs); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_subsector.h0000644000175000017500000000243211357170241024266 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_subsector.h: World subsectors. */ #ifndef __DOOMSDAY_WORLD_SUBSECTOR_H__ #define __DOOMSDAY_WORLD_SUBSECTOR_H__ #include "r_data.h" #include "p_dmu.h" boolean Subsector_GetProperty(const subsector_t* sub, setargs_t* args); boolean Subsector_SetProperty(subsector_t* sub, const setargs_t* args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_filehash.h0000644000175000017500000000253411357170241024040 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_filehash.h: File name/directory search hashes. */ #ifndef __DOOMSDAY_MISC_FILE_HASH_H__ #define __DOOMSDAY_MISC_FILE_HASH_H__ typedef void* filehash_t; filehash_t* FileHash_Create(const char* pathList); void FileHash_Destroy(filehash_t* fh); boolean FileHash_Find(filehash_t* fh, char* foundPath, const char* name, size_t len); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_stack.h0000644000175000017500000000243611357170241023363 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_stack.h: A basic stack. */ #ifndef __STACK_H__ #define __STACK_H__ #ifdef __cplusplus extern "C" { #endif typedef void* ddstack_t; ddstack_t* Stack_New(void); void Stack_Delete(ddstack_t* stack); size_t Stack_Height(ddstack_t* stack); void Stack_Push(ddstack_t* stack, void* data); void* Stack_Pop(ddstack_t* stack); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/rend_main.h0000644000175000017500000000473111357170241023676 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_main.h: Rendering Subsystem */ #ifndef __DOOMSDAY_REND_MAIN_H__ #define __DOOMSDAY_REND_MAIN_H__ #include #include "rend_list.h" #include "r_things.h" extern float vx, vy, vz, vang, vpitch, fieldOfView, yfov; extern byte smoothTexAnim; extern float viewsidex, viewsidey; extern int missileBlend; extern boolean usingFog; extern float fogColor[4]; extern int rAmbient; extern float rendLightDistanceAttentuation; extern float lightModRange[255]; void Rend_Register(void); void Rend_Init(void); void Rend_Reset(void); void Rend_RenderMap(void); void Rend_ModelViewMatrix(boolean use_angles); #define Rend_PointDist2D(c) (fabs((vz-c[VY])*viewsidex - (vx-c[VX])*viewsidey)) float Rend_PointDist3D(const float c[3]); float Rend_SectorLight(sector_t* sec); void Rend_ApplyTorchLight(float* color, float distance); int Rend_MidMaterialPos(float* bottomleft, float* bottomright, float* topleft, float* topright, float* texoffy, float tcyoff, float texHeight, boolean lower_unpeg, boolean clipTop, boolean clipBottom); boolean Rend_DoesMidTextureFillGap(linedef_t* line, int backside); void Rend_ApplyLightAdaptation(float* lightvalue); float Rend_GetLightAdaptVal(float lightvalue); void Rend_CalcLightModRange(struct cvar_s* unused); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/sys_findfile.h0000644000175000017500000000323011357170241024411 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sys_findfile.h: Win32-Style File Finding */ #ifndef __DOOMSDAY_FILE_FIND_H__ #define __DOOMSDAY_FILE_FIND_H__ // File attributes. #define A_SUBDIR 0x1 #define A_RDONLY 0x2 #define A_HIDDEN 0x4 #define A_ARCH 0x8 typedef struct finddata_s { void *finddata; time_t date; time_t time; size_t size; char *name; long attrib; } finddata_t; /** * \note The functions return zero if successful. */ int myfindfirst(const char *filename, finddata_t *dta); int myfindnext(finddata_t *dta); void myfindend(finddata_t *dta); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/bsp_main.h0000644000175000017500000000304011357170241023522 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2000-2007 Andrew Apted *\author Copyright © 1998-2000 Colin Reed *\author Copyright © 1998-2000 Lee Killough * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * bsp_main.h: GL-friendly BSP node builder. * * Based on glBSP 2.24 (in turn, based on BSP 2.3), which is hosted on * SourceForge: http://sourceforge.net/projects/glbsp/ */ #ifndef __BSP_MAIN_H__ #define __BSP_MAIN_H__ #include "de_edit.h" typedef double angle_g; // Degrees, 0 is E, 90 is N extern int bspFactor; void BSP_Register(void); boolean BSP_Build(gamemap_t *map, vertex_t ***vertexes, uint *numVertexes); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/p_vertex.h0000644000175000017500000000240311357170241023570 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_vertex.h: World vertexes. */ #ifndef __DOOMSDAY_WORLD_VERTEX_H__ #define __DOOMSDAY_WORLD_VERTEX_H__ #include "r_data.h" #include "p_dmu.h" boolean Vertex_GetProperty(const vertex_t *vtx, setargs_t *args); boolean Vertex_SetProperty(vertex_t *vtx, const setargs_t *args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/net_buf.h0000644000175000017500000000570511357170241023366 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * net_buf.h: Network Message Handling and Buffering */ #ifndef __DOOMSDAY_NETWORK_BUFFER_H__ #define __DOOMSDAY_NETWORK_BUFFER_H__ #include "con_decl.h" // Send Packet flags: #define SPF_REBOUND 0x00020000 // Write only to local loopback #define SPF_DONT_SEND 0x00040000 // Don't really send out anything #define SPF_CONFIRM 0x40000000 // Make sure it's received #define SPF_ORDERED 0x80000000 // Send in order & confirm #define NETBUFFER_MAXDATA 32768 // Each network node is identified by a number. typedef unsigned int nodeid_t; // Incoming messages are stored in netmessage_s structs. typedef struct netmessage_s { struct netmessage_s *next; nodeid_t sender; uint player; // Set in N_GetMessage(). size_t size; byte *data; void *handle; } netmessage_t; typedef unsigned short msgid_t; #pragma pack(1) typedef struct { msgid_t id; // Unused. byte type; // Type of the message. byte data[NETBUFFER_MAXDATA]; } netdata_t; #pragma pack() typedef struct netbuffer_s { int player; // Recipient or sender. size_t length; // Number of bytes in the data buffer. size_t headerLength; // 1 byte at the moment. byte *cursor; // Points into the data buffer. netdata_t msg; // The data buffer for sending and // receiving packets. } netbuffer_t; /** * Globally accessible data. */ extern netbuffer_t netBuffer; extern boolean allowSending; /** * Functions. */ void N_Init(void); void N_Shutdown(void); void N_ClearMessages(void); void N_SendPacket(int flags); boolean N_GetPacket(void); uint N_IdentifyPlayer(nodeid_t id); void N_PrintBufferInfo(void); void N_PrintHuffmanStats(void); void N_PostMessage(netmessage_t *msg); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_misc.h0000644000175000017500000001430111357170241023203 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_misc.h: Miscellanous Routines */ #ifndef __DOOMSDAY_MISCELLAN_H__ #define __DOOMSDAY_MISCELLAN_H__ #include "dd_types.h" #include "sys_file.h" #define MAX_READ 8192 #define ISSPACE(c) ((c) == 0 || (c) == ' ' || (c) == '\t' || (c) == '\n' ||\ (c) == '\r') // Memory. void* M_Malloc(size_t size); void* M_Calloc(size_t size); void* M_Realloc(void* ptr, size_t size); void M_Free(void* ptr); // File system routines. void M_ResetFileIDs(void); boolean M_CheckFileID(const char* path); size_t M_ReadFile(char const* name, byte** buffer); size_t M_ReadFileCLib(char const* name, byte** buffer); boolean M_WriteFile(char const* name, void* source, size_t length); void M_ExtractFileBase(char* dest, const char* path, size_t len); void M_ExtractFileBase2(char* dest, const char* path, size_t len, int ignore); char* M_FindFileExtension(char* path); void M_ReplaceFileExt(char* path, const char* newext, size_t len); boolean M_CheckPath(const char* path); int M_FileExists(const char* file); void M_TranslatePath(char* translated, const char* path, size_t len); void M_PrependBasePath(char* newpath, const char* path, size_t len); void M_RemoveBasePath(char* newPath, const char* absPath, size_t len); const char* M_PrettyPath(const char* path); void M_ReadLine(char* buffer, size_t len, DFILE* file); // Bounding boxes. void M_ClearBox(fixed_t* box); void M_CopyBox(fixed_t dest[4], const fixed_t src[4]); void M_AddToBox(fixed_t* box, fixed_t x, fixed_t y); float M_BoundingBoxDiff(const float in[4], const float out[4]); void M_JoinBoxes(float box[4], const float other[4]); // Text utilities. char* M_SkipWhite(char* str); char* M_FindWhite(char* str); char* M_SkipLine(char* str); void M_WriteCommented(FILE* file, const char* text); void M_WriteTextEsc(FILE* file, const char* text); boolean M_IsComment(const char* text); boolean M_IsStringValidInt(const char* str); boolean M_IsStringValidByte(const char* str); boolean M_IsStringValidFloat(const char* str); char* M_LimitedStrCat(char* buf, const char* str, size_t maxWidth, char separator, size_t bufLength); char* M_StrCatQuoted(char* dest, const char* src, size_t len); char* M_StrTok(char** cursor, char* delimiters); // Random numbers. byte RNG_RandByte(void); float RNG_RandFloat(void); void RNG_Reset(void); // Math routines. float M_ApproxDistancef(float dx, float dy); float M_ApproxDistance3(const float delta[3]); float M_ApproxDistance3f(float dx, float dy, float dz); float M_PointLineDistance(const float* a, const float* b, const float* c); float M_PointUnitLineDistance(const float* a, const float* b, const float* c); float M_Normalize(float* a); float M_Distance(const float* a, const float* b); void M_Scale(float* dest, const float* a, float scale); float M_DotProduct(const float* a, const float* b); void M_CrossProduct(const float* a, const float* b, float* out); void M_PointCrossProduct(const float* v1, const float* v2, const float* v3, float* out); float M_TriangleArea(const float* v1, const float* v2, const float* v3); void M_RotateVector(float vec[3], float degYaw, float degPitch); float M_ProjectPointOnLine(const float* point, const float* linepoint, const float* delta, float gap, float* result); void M_ProjectViewRelativeLine2D(const float center[2], boolean alignToViewPlane, float width, float offset, float start[2], float end[2]); double M_ParallelDist(double lineDX, double lineDY, double linePara, double lineLength, double x, double y); double M_PerpDist(double lineDX, double lineDY, double linePerp, double lineLength, double x, double y); int M_CeilPow2(int num); int M_FloorPow2(int num); int M_RoundPow2(int num); int M_WeightPow2(int num, float weight); float M_CycleIntoRange(float value, float length); double M_SlopeToAngle(double dx, double dy); double M_Length(double x, double y); int M_NumDigits(int num); uint M_CRC32(byte* data, uint length); // Time utilities. boolean M_RunTrigger(trigger_t* trigger, timespan_t advanceTime); boolean M_CheckTrigger(const trigger_t* trigger, timespan_t advanceTime); // Other utilities. int M_ScreenShot(const char* filename, int bits); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/portable/include/m_decomp64.h0000644000175000017500000000215311357170241023673 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_decomp64.h: Decompression algorithm, used with various lumps of * DOOM64 data. */ #ifndef __M_DECOMPRESS64_H__ #define __M_DECOMPRESS64_H__ void M_Decompress64(byte* dst, const byte* src); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/engine/defs/0000755000175000017500000000000011523516205017251 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/defs/flags.ded0000644000175000017500000002124411357170241021027 0ustar keeskees# Doomsday: Flags # Texture Groups Flag { ID = "tgf_smooth"; Value = 0x1; } Flag { ID = "tgf_first_only"; Value = 0x2; } Flag { ID = "tgf_precache"; Value = 0x4000; } # State flags Flag { ID = "statef_fullbright"; Value = 0x01; } Flag { ID = "statef_noautolight"; Value = 0x02; } # Sounds Flag { ID = "sf_shift"; Value = 0x1; } Flag { ID = "sf_shift2"; Value = 0x2; } Flag { ID = "sf_exclude"; Value = 0x4; } Flag { ID = "sf_nodist"; Value = 0x8; } Flag { ID = "sf_repeat"; Value = 0x10; } Flag { ID = "sf_dontstop"; Value = 0x20; } # Decorations Flag { # Decoration will not be used with IWAD resources. ID = "dcf_noiwad"; Value = 0x1; } Flag { # Allow using decoration with PWAD resources. ID = "dcf_pwad"; Value = 0x2; } Flag { # Allow using decoration with external resources. ID = "dcf_ext"; Value = 0x4; } # Reflections Flag { # Reflection will not be used with IWAD resources. ID = "rff_noiwad"; Value = 0x1; } Flag { # Allow using reflection with PWAD resources. ID = "rff_pwad"; Value = 0x2; } Flag { # Allow using reflection with external resources. ID = "rff_ext"; Value = 0x4; } # Details Flag { # DetailTex will not be used with IWAD resources. ID = "dtf_noiwad"; Value = 0x1; } Flag { # Allow using detailtex with PWAD resources. ID = "dtf_pwad"; Value = 0x2; } Flag { # Allow using detailtex with external resources. ID = "dtf_ext"; Value = 0x4; } # Materials Flag { ID = "matf_custom"; Value = 0x1; } Flag { ID = "matf_dontdraw"; Value = 0x2; } # Material should never be drawn. Flag { ID = "matf_glow"; Value = 0x4; } # Glowing material. Flag { ID = "matf_skymask"; Value = 0x8; } # Sky-mask surfaces using this material. # Material groups Flag { ID = "mn_textures"; Value = 0; } Flag { ID = "mn_flats"; Value = 1; } Flag { ID = "mn_sprites"; Value = 2; } Flag { ID = "mn_system"; Value = 3; } # Lights Flag { ID = "lgf_nohalo"; Value = 0x1; } Flag { ID = "lgf_dontturnhalo"; Value = 0x2; } # Map Info Flag { ID = "mif_fog"; Value = 0x1; } Flag { # Draw the sky sphere even when models are in use. ID = "mif_sphere"; Value = 0x2; } Flag { ID = "mif_nointermission"; Value = 0x4; } # Sky Info Flag { # Draw the sky sphere even when models are in use. ID = "sif_sphere"; Value = 0x1; } # Sky Layers Flag { ID = "slf_enable"; Value = 0x1; } Flag { ID = "slf_mask"; Value = 0x2; } # Blending Modes Flag { ID = "bm_normal"; Value = 0; } Flag { ID = "bm_add"; Value = 1; } Flag { ID = "bm_dark"; Value = 2; } Flag { ID = "bm_sub"; Value = 3; } # src_alpha multiplied with dest_color Flag { ID = "bm_sub2"; Value = 7; } # src_alpha multiplied with src_color Flag { ID = "bm_revsub"; Value = 4; } Flag { ID = "bm_mul"; Value = 5; } Flag { ID = "bm_invmul"; Value = 6; } Flag { ID = "bm_inv"; Value = 7; } Flag { ID = "sdf_fade_top_mid"; Value = 0x1; } Flag { ID = "sdf_fade_mid_top"; Value = 0x2; } Flag { ID = "sdf_fade_mid_bottom"; Value = 0x4; } Flag { ID = "sdf_fade_bottom_mid"; Value = 0x8; } Flag { ID = "sdf_middle_stretch"; Value = 0x10; } # Models Flag { ID = "df_fullbright"; Value = 0x1; } Flag { ID = "df_shadow1"; Value = 0x2; } Flag { ID = "df_shadow2"; Value = 0x4; } Flag { ID = "df_brightshadow"; Value = 0x8; } Flag { ID = "df_movpitch"; Value = 0x10; } Flag { ID = "df_spin"; Value = 0x20; } Flag { ID = "df_skintrans"; Value = 0x40; } Flag { ID = "df_autoscale"; Value = 0x80; } Flag { ID = "df_movyaw"; Value = 0x100; } Flag { ID = "df_nointerpol"; Value = 0x200; } Flag { ID = "df_brightshadow2"; Value = 0x400; } Flag { ID = "df_alignyaw"; Value = 0x800; } Flag { ID = "df_alignpitch"; Value = 0x1000; } Flag { ID = "df_darkshadow"; Value = 0x2000; } Flag { ID = "df_idskin"; Value = 0x4000; } Flag { ID = "df_noz"; Value = 0x8000; } Flag { ID = "df_nomaxz"; Value = 0x10000; } Flag { ID = "df_selskin"; Value = 0x20000; } Flag { ID = "df_ptoffsub1"; Value = 0x40000; } Flag { ID = "df_noptc"; Value = 0x80000; } Flag { ID = "df_specular"; Value = 0x100000; } Flag { ID = "df_litshiny"; Value = 0x200000; } Flag { ID = "df_idframe"; Value = 0x400000; } Flag { ID = "df_idangle"; Value = 0x800000; } Flag { ID = "df_dim"; Value = 0x1000000; } Flag { ID = "df_subtract"; Value = 0x2000000; } Flag { ID = "df_revsubtract"; Value = 0x4000000; } Flag { ID = "df_twosided"; Value = 0x8000000; } Flag { ID = "df_notexcomp"; Value = 0x10000000; } Flag { ID = "df_worldtime"; Value = 0x20000000; } # Model grouping Flag { ID = "mg_hud"; Value = 0x2; } Flag { ID = "mg_player"; Value = 0x4; } Flag { ID = "mg_monster"; Value = 0x8; } Flag { ID = "mg_weapon"; Value = 0x10; } Flag { ID = "mg_ammo"; Value = 0x20; } Flag { ID = "mg_bonus"; Value = 0x40; } Flag { ID = "mg_light"; Value = 0x80; } Flag { ID = "mg_decor"; Value = 0x100; } Flag { ID = "mg_misc"; Value = 0x200; } # Generators Flag { ID = "gnf_static"; Value = 1; } Flag { ID = "gnf_srcvel"; Value = 2; } Flag { ID = "gnf_spawn"; Value = 4; } Flag { ID = "gnf_srcdir"; Value = 8; } Flag { ID = "gnf_blend"; Value = 0x10; } Flag { ID = "gnf_floor"; Value = 0x20; } Flag { ID = "gnf_ceiling"; Value = 0x40; } Flag { ID = "gnf_space"; Value = 0x80; } Flag { ID = "gnf_density"; Value = 0x100; } Flag { ID = "gnf_modelonly"; Value = 0x200; } Flag { ID = "gnf_scalerate"; Value = 0x400; } Flag { ID = "gnf_group"; Value = 0x800; } Flag { ID = "gnf_blendadd"; Value = 0x10; } Flag { ID = "gnf_blendsub"; Value = 0x1000; } Flag { ID = "gnf_blendrsub"; Value = 0x2000; } Flag { ID = "gnf_blendmul"; Value = 0x4000; } Flag { ID = "gnf_blendimul"; Value = 0x8000; } Flag { ID = "gnf_extra"; Value = 0x10000; } # Particle types Flag { ID = "pt_point"; Value = 1; } Flag { ID = "pt_line"; Value = 2; } Flag { ID = "pt_tex00"; Value = 100; } Flag { ID = "pt_tex01"; Value = 101; } Flag { ID = "pt_tex02"; Value = 102; } Flag { ID = "pt_tex03"; Value = 103; } Flag { ID = "pt_tex04"; Value = 104; } Flag { ID = "pt_tex05"; Value = 105; } Flag { ID = "pt_tex06"; Value = 106; } Flag { ID = "pt_tex07"; Value = 107; } Flag { ID = "pt_tex08"; Value = 108; } Flag { ID = "pt_tex09"; Value = 109; } Flag { ID = "pt_tex10"; Value = 110; } Flag { ID = "pt_tex11"; Value = 111; } Flag { ID = "pt_tex12"; Value = 112; } Flag { ID = "pt_tex13"; Value = 113; } Flag { ID = "pt_tex14"; Value = 114; } Flag { ID = "pt_tex15"; Value = 115; } Flag { ID = "pt_tex16"; Value = 116; } Flag { ID = "pt_tex17"; Value = 117; } Flag { ID = "pt_tex18"; Value = 118; } Flag { ID = "pt_tex19"; Value = 119; } Flag { ID = "pt_tex20"; Value = 120; } Flag { ID = "pt_tex21"; Value = 121; } Flag { ID = "pt_tex22"; Value = 122; } Flag { ID = "pt_tex23"; Value = 123; } Flag { ID = "pt_tex24"; Value = 124; } Flag { ID = "pt_tex25"; Value = 125; } Flag { ID = "pt_tex26"; Value = 126; } Flag { ID = "pt_tex27"; Value = 127; } Flag { ID = "pt_tex28"; Value = 128; } Flag { ID = "pt_tex29"; Value = 129; } Flag { ID = "pt_tex30"; Value = 130; } Flag { ID = "pt_tex31"; Value = 131; } Flag { ID = "pt_model00"; Value = 1000; } Flag { ID = "pt_model01"; Value = 1001; } Flag { ID = "pt_model02"; Value = 1002; } Flag { ID = "pt_model03"; Value = 1003; } Flag { ID = "pt_model04"; Value = 1004; } Flag { ID = "pt_model05"; Value = 1005; } Flag { ID = "pt_model06"; Value = 1006; } Flag { ID = "pt_model07"; Value = 1007; } Flag { ID = "pt_model08"; Value = 1008; } Flag { ID = "pt_model09"; Value = 1009; } Flag { ID = "pt_model10"; Value = 1010; } Flag { ID = "pt_model11"; Value = 1011; } Flag { ID = "pt_model12"; Value = 1012; } Flag { ID = "pt_model13"; Value = 1013; } Flag { ID = "pt_model14"; Value = 1014; } Flag { ID = "pt_model15"; Value = 1015; } Flag { ID = "pt_model16"; Value = 1016; } Flag { ID = "pt_model17"; Value = 1017; } Flag { ID = "pt_model18"; Value = 1018; } Flag { ID = "pt_model19"; Value = 1019; } Flag { ID = "pt_model20"; Value = 1020; } Flag { ID = "pt_model21"; Value = 1021; } Flag { ID = "pt_model22"; Value = 1022; } Flag { ID = "pt_model23"; Value = 1023; } Flag { ID = "pt_model24"; Value = 1024; } Flag { ID = "pt_model25"; Value = 1025; } Flag { ID = "pt_model26"; Value = 1026; } Flag { ID = "pt_model27"; Value = 1027; } Flag { ID = "pt_model28"; Value = 1028; } Flag { ID = "pt_model29"; Value = 1029; } Flag { ID = "pt_model30"; Value = 1030; } Flag { ID = "pt_model31"; Value = 1031; } # Particle flags (for Generator Stages) Flag { ID = "ptf_stagetouch"; Value = 0x1; } Flag { ID = "ptf_stagevtouch"; Value = 0x20; } Flag { ID = "ptf_stagehtouch"; Value = 0x40; } Flag { ID = "ptf_dietouch"; Value = 0x2; } Flag { ID = "ptf_bright"; Value = 0x4; } Flag { ID = "ptf_shading"; Value = 0x8; } Flag { ID = "ptf_hflat"; Value = 0x10; } Flag { ID = "ptf_vflat"; Value = 0x80; } Flag { ID = "ptf_flat"; Value = 0x90; } Flag { ID = "ptf_force"; Value = 0x100; } Flag { ID = "ptf_zeroyaw"; Value = 0x200; } Flag { ID = "ptf_zeropitch"; Value = 0x400; } Flag { ID = "ptf_rndyaw"; Value = 0x800; } Flag { ID = "ptf_rndpitch"; Value = 0x1000; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/defs/xg.ded0000644000175000017500000003004411357170241020347 0ustar keeskees# Doomsday: XG Lines and Sectors # XG Line Classes Flag { ID = "ltc_none"; } Flag { ID = "ltc_chain_sequence"; Value = 0x1; } Flag { ID = "ltc_plane_move"; Value = 0x2; } Flag { ID = "ltc_build_stairs"; Value = 0x3; } Flag { ID = "ltc_damage"; Value = 0x4; } Flag { ID = "ltc_power"; Value = 0x5; } Flag { ID = "ltc_line_type"; Value = 0x6; } Flag { ID = "ltc_sector_type"; Value = 0x7; } Flag { ID = "ltc_sector_light"; Value = 0x8; } Flag { ID = "ltc_activate"; Value = 0x9; } Flag { ID = "ltc_key"; Value = 0xA; } Flag { ID = "ltc_music"; Value = 0xB; } Flag { ID = "ltc_line_count"; Value = 0xC; } Flag { ID = "ltc_end_level"; Value = 0xD; } Flag { ID = "ltc_leave_map"; Value = 0xD; } # Alias for end_level Flag { ID = "ltc_disable_if_active"; Value = 0xE; } Flag { ID = "ltc_enable_if_active"; Value = 0xF; } Flag { ID = "ltc_explode"; Value = 0x10; } Flag { ID = "ltc_plane_texture"; Value = 0x11; } Flag { ID = "ltc_plane_material"; Value = 0x11; } # Alias for plane_texture Flag { ID = "ltc_wall_texture"; Value = 0x12; } Flag { ID = "ltc_wall_material"; Value = 0x12; } # Alias for wall_texture Flag { ID = "ltc_command"; Value = 0x13; } Flag { ID = "ltc_sound"; Value = 0x14; } Flag { ID = "ltc_mimic_sector"; Value = 0x15; } Flag { ID = "ltc_teleport"; Value = 0x16; } Flag { ID = "ltc_line_teleport"; Value = 0x17; } Flag { ID = "ltf_active"; Value = 0x1; } Flag { ID = "ltf_player_use_a"; Value = 0x2; } Flag { ID = "ltf_other_use_a"; Value = 0x4; } Flag { ID = "ltf_player_shoot_a"; Value = 0x8; } Flag { ID = "ltf_other_shoot_a"; Value = 0x10; } Flag { ID = "ltf_any_cross_a"; Value = 0x20; } Flag { ID = "ltf_monster_cross_a"; Value = 0x40; } Flag { ID = "ltf_player_cross_a"; Value = 0x80; } Flag { ID = "ltf_missile_cross_a"; Value = 0x100; } Flag { ID = "ltf_player_hit_a"; Value = 0x200; } Flag { ID = "ltf_other_hit_a"; Value = 0x400; } Flag { ID = "ltf_monster_hit_a"; Value = 0x800; } Flag { ID = "ltf_missile_hit_a"; Value = 0x1000; } Flag { ID = "ltf_any_hit_a"; Value = 0x2000; } Flag { ID = "ltf_player_use_d"; Value = 0x4000; } Flag { ID = "ltf_other_use_d"; Value = 0x8000; } Flag { ID = "ltf_player_shoot_d"; Value = 0x10000; } Flag { ID = "ltf_other_shoot_d"; Value = 0x20000; } Flag { ID = "ltf_any_cross_d"; Value = 0x40000; } Flag { ID = "ltf_monster_cross_d"; Value = 0x80000; } Flag { ID = "ltf_player_cross_d"; Value = 0x100000; } Flag { ID = "ltf_missile_cross_d"; Value = 0x200000; } Flag { ID = "ltf_player_hit_d"; Value = 0x400000; } Flag { ID = "ltf_other_hit_d"; Value = 0x800000; } Flag { ID = "ltf_monster_hit_d"; Value = 0x1000000; } Flag { ID = "ltf_missile_hit_d"; Value = 0x2000000; } Flag { ID = "ltf_any_hit_d"; Value = 0x4000000; } Flag { ID = "ltf_player_use"; Value = 0x4002; } Flag { ID = "ltf_other_use"; Value = 0x8004; } Flag { ID = "ltf_player_shoot"; Value = 0x10008; } Flag { ID = "ltf_other_shoot"; Value = 0x20010; } Flag { ID = "ltf_any_cross"; Value = 0x40020; } Flag { ID = "ltf_monster_cross"; Value = 0x80040; } Flag { ID = "ltf_player_cross"; Value = 0x100080; } Flag { ID = "ltf_missile_cross"; Value = 0x200100; } Flag { ID = "ltf_player_hit"; Value = 0x400200; } Flag { ID = "ltf_other_hit"; Value = 0x800400; } Flag { ID = "ltf_monster_hit"; Value = 0x1000800; } Flag { ID = "ltf_missile_hit"; Value = 0x2001000; } Flag { ID = "ltf_any_hit"; Value = 0x4002000; } Flag { ID = "ltf_ticker_a"; Value = 0x8000000; } Flag { ID = "ltf_ticker_d"; Value = 0x10000000; } Flag { ID = "ltf_ticker"; Value = 0x18000000; } Flag { ID = "ltf_mobj_gone"; Value = 0x20000000; } Flag { ID = "ltf_no_other_use_secret"; Value = 0x40000000; } Flag { ID = "ltf_activator_type"; Value = 0x80000000; } Flag { ID = "ltf2_when_act"; Value = 0x1; } Flag { ID = "ltf2_when_deact"; Value = 0x2; } Flag { ID = "ltf2_when_last"; Value = 0x10; } Flag { ID = "ltf2_while_act"; Value = 0x4; } Flag { ID = "ltf2_while_inact"; Value = 0x8; } Flag { ID = "ltf2_key1"; Value = 0x20; } Flag { ID = "ltf2_key2"; Value = 0x40; } Flag { ID = "ltf2_key3"; Value = 0x80; } Flag { ID = "ltf2_key4"; Value = 0x100; } Flag { ID = "ltf2_key5"; Value = 0x200; } Flag { ID = "ltf2_key6"; Value = 0x400; } Flag { ID = "ltf2_line_act"; Value = 0x800; } Flag { ID = "ltf2_line_inact"; Value = 0x1000; } Flag { ID = "ltf2_color"; Value = 0x2000; } Flag { ID = "ltf2_health_above"; Value = 0x4000; } Flag { ID = "ltf2_health_below"; Value = 0x8000; } Flag { ID = "ltf2_power_above"; Value = 0x10000; } Flag { ID = "ltf2_power_below"; Value = 0x20000; } Flag { ID = "ltf2_singleplayer"; Value = 0x40000; } Flag { ID = "ltf2_cooperative"; Value = 0x80000; } Flag { ID = "ltf2_deathmatch"; Value = 0x100000; } Flag { ID = "ltf2_any_mode"; Value = 0x1C0000; } Flag { ID = "ltf2_easy"; Value = 0x200000; } Flag { ID = "ltf2_med"; Value = 0x400000; } Flag { ID = "ltf2_hard"; Value = 0x800000; } Flag { ID = "ltf2_any_skill"; Value = 0xE00000; } Flag { ID = "ltf2_any"; Value = 0xFC0000; } Flag { ID = "ltf2_multiple"; Value = 0x1000000; } Flag { ID = "ltf2_2sided"; Value = 0x2000000; } Flag { ID = "ltf2_global_a_msg"; Value = 0x4000000; } Flag { ID = "ltf2_global_d_msg"; Value = 0x8000000; } Flag { ID = "ltf2_global_msg"; Value = 0xC000000; } Flag { ID = "ltf2_group_act"; Value = 0x10000000; } Flag { ID = "ltf2_group_deact"; Value = 0x20000000; } Flag { ID = "ltf2_override_any"; Value = 0x40000000; } Flag { ID = "lat_timed_off"; } Flag { ID = "lat_timed_on"; Value = 0x1; } Flag { ID = "lat_flip"; Value = 0x2; } Flag { ID = "lat_flip_timed_off"; Value = 0x3; } Flag { ID = "lat_flip_timed_on"; Value = 0x4; } Flag { ID = "lref_none"; } Flag { ID = "lref_self"; Value = 0x1; } Flag { ID = "lref_tagged"; Value = 0x2; } Flag { ID = "lref_line_tagged"; Value = 0x3; } Flag { ID = "lref_act_tagged"; Value = 0x4; } Flag { ID = "lref_index"; Value = 0x5; } Flag { ID = "lref_all"; Value = 0x6; } Flag { ID = "lpref_none"; } Flag { ID = "lpref_my_floor"; Value = 0x1; } Flag { ID = "lpref_tagged_floors"; Value = 0x2; } Flag { ID = "lpref_line_tagged_floors"; Value = 0x3; } Flag { ID = "lpref_act_tagged_floors"; Value = 0x4; } Flag { ID = "lpref_index_floor"; Value = 0x5; } Flag { ID = "lpref_all_floors"; Value = 0x6; } Flag { ID = "lpref_my_ceiling"; Value = 0x7; } Flag { ID = "lpref_tagged_ceilings"; Value = 0x8; } Flag { ID = "lpref_line_tagged_ceilings"; Value = 0x9; } Flag { ID = "lpref_act_tagged_ceilings"; Value = 0xA; } Flag { ID = "lpref_index_ceiling"; Value = 0xB; } Flag { ID = "lpref_all_ceilings"; Value = 0xC; } Flag { ID = "lpref_special"; Value = 0xD; } Flag { ID = "lpref_back_floor"; Value = 0xE; } Flag { ID = "lpref_back_ceiling"; Value = 0xF; } Flag { ID = "lpref_thing_exist_floors"; Value = 0x10; } Flag { ID = "lpref_thing_exist_ceilings"; Value = 0x11; } Flag { ID = "lpref_thing_noexist_floors"; Value = 0x12; } Flag { ID = "lpref_thing_noexist_ceilings"; Value = 0x13; } Flag { ID = "lsref_none"; } Flag { ID = "lsref_my"; Value = 0x1; } Flag { ID = "lsref_tagged"; Value = 0x2; } Flag { ID = "lsref_line_tagged"; Value = 0x3; } Flag { ID = "lsref_act_tagged"; Value = 0x4; } Flag { ID = "lsref_index"; Value = 0x5; } Flag { ID = "lsref_all"; Value = 0x6; } Flag { ID = "lsref_back"; Value = 0x7; } Flag { ID = "lsref_thing_exist"; Value = 0x8; } Flag { ID = "lsref_thing_noexist"; Value = 0x9; } Flag { ID = "spref_none"; } Flag { ID = "spref_my_floor"; Value = 0x1; } Flag { ID = "spref_my_ceiling"; Value = 0x2; } Flag { ID = "spref_original_floor"; Value = 0x3; } Flag { ID = "spref_original_ceiling"; Value = 0x4; } Flag { ID = "spref_current_floor"; Value = 0x5; } Flag { ID = "spref_current_ceiling"; Value = 0x6; } Flag { ID = "spref_highest_floor"; Value = 0x7; } Flag { ID = "spref_highest_ceiling"; Value = 0x8; } Flag { ID = "spref_lowest_floor"; Value = 0x9; } Flag { ID = "spref_lowest_ceiling"; Value = 0xA; } Flag { ID = "spref_next_highest_floor"; Value = 0xB; } Flag { ID = "spref_next_highest_ceiling"; Value = 0xC; } Flag { ID = "spref_next_lowest_floor"; Value = 0xD; } Flag { ID = "spref_next_lowest_ceiling"; Value = 0xE; } Flag { ID = "spref_min_bottom_texture"; Value = 0xF; } Flag { ID = "spref_min_bottom_material"; Value = 0xF; } # Alias for min_bottom_texture Flag { ID = "spref_min_mid_texture"; Value = 0x10; } Flag { ID = "spref_min_mid_material"; Value = 0x10; } # Alias for min_mid_texture Flag { ID = "spref_min_top_texture"; Value = 0x11; } Flag { ID = "spref_min_top_material"; Value = 0x11; } # Alias for min_top_texture Flag { ID = "spref_max_bottom_texture"; Value = 0x12; } Flag { ID = "spref_max_bottom_material"; Value = 0x12; } # Alias for max_bottom_texture Flag { ID = "spref_max_mid_texture"; Value = 0x13; } Flag { ID = "spref_max_mid_material"; Value = 0x13; } # Alias for max_mid_texture Flag { ID = "spref_max_top_texture"; Value = 0x14; } Flag { ID = "spref_max_top_material"; Value = 0x14; } # Alias for max_top_texture Flag { ID = "spref_sector_tagged_floor"; Value = 0x15; } Flag { ID = "spref_line_tagged_floor"; Value = 0x16; } Flag { ID = "spref_tagged_floor"; Value = 0x17; } Flag { ID = "spref_act_tagged_floor"; Value = 0x18; } Flag { ID = "spref_index_floor"; Value = 0x19; } Flag { ID = "spref_sector_tagged_ceiling"; Value = 0x20; } Flag { ID = "spref_line_tagged_ceiling"; Value = 0x21; } Flag { ID = "spref_tagged_ceiling"; Value = 0x22; } Flag { ID = "spref_act_tagged_ceiling"; Value = 0x23; } Flag { ID = "spref_index_ceiling"; Value = 0x24; } Flag { ID = "spref_back_floor"; Value = 0x25; } Flag { ID = "spref_back_ceiling"; Value = 0x26; } Flag { ID = "spref_special"; Value = 0x27; } Flag { ID = "spref_line_act_tagged_floor"; Value = 0x28; } Flag { ID = "spref_line_act_tagged_ceiling"; Value = 0x29; } Flag { ID = "lightref_none"; } Flag { ID = "lightref_my"; Value = 0x1; } Flag { ID = "lightref_original"; Value = 0x2; } Flag { ID = "lightref_current"; Value = 0x3; } Flag { ID = "lightref_highest"; Value = 0x4; } Flag { ID = "lightref_lowest"; Value = 0x5; } Flag { ID = "lightref_next_highest"; Value = 0x6; } Flag { ID = "lightref_next_lowest"; Value = 0x7; } Flag { ID = "lightref_back"; Value = 0x8; } Flag { ID = "ldref_none"; } Flag { ID = "ldref_id"; Value = 0x1; } Flag { ID = "ldref_special"; Value = 0x2; } Flag { ID = "ldref_tag"; Value = 0x3; } Flag { ID = "ldref_acttag"; Value = 0x4; } Flag { ID = "ldref_count"; Value = 0x5; } Flag { ID = "ldref_angle"; Value = 0x6; } Flag { ID = "ldref_length"; Value = 0x7; } Flag { ID = "ldref_top_offsetx"; Value = 0x8; } Flag { ID = "ldref_top_offsety"; Value = 0x9; } Flag { ID = "ldref_middle_offsetx"; Value = 0x10; } Flag { ID = "ldref_middle_offsety"; Value = 0x11; } Flag { ID = "ldref_bottom_offsetx"; Value = 0x12; } Flag { ID = "ldref_bottom_offsety"; Value = 0x13; } Flag { ID = "chsf_done_d"; Value = 0x1; } Flag { ID = "chsf_loop"; Value = 0x2; } Flag { ID = "pmf_crush"; Value = 0x1; } Flag { ID = "pmf_abort_a"; Value = 0x2; } Flag { ID = "pmf_abort_d"; Value = 0x4; } Flag { ID = "pmf_done_a"; Value = 0x8; } Flag { ID = "pmf_done_d"; Value = 0x10; } Flag { ID = "pmf_follow"; Value = 0x20; } Flag { ID = "pmf_setorig"; Value = 0x40; } Flag { ID = "pmf_1snd"; Value = 0x100; } Flag { ID = "lws_none"; } Flag { ID = "lws_mid"; Value = 0x1; } Flag { ID = "lws_upper"; Value = 0x2; } Flag { ID = "lws_lower"; Value = 0x3; } # XG Sectors Flag { ID = "stf_gravity"; Value = 0x1; } Flag { ID = "stf_friction"; Value = 0x2; } Flag { ID = "stf_crush"; Value = 0x4; } Flag { ID = "stf_tagtexmove"; Value = 0x80; } Flag { ID = "stf_windplayer"; Value = 0x8; } Flag { ID = "stf_windother"; Value = 0x10; } Flag { ID = "stf_windmonster"; Value = 0x20; } Flag { ID = "stf_windmissile"; Value = 0x40; } Flag { ID = "stf_windany"; Value = 0x18; } Flag { ID = "stf_tagwind"; Value = 0x100; } Flag { ID = "stf_floorwind"; Value = 0x200; } Flag { ID = "stf_ceilingwind"; Value = 0x400; } Flag { ID = "scef_player_a"; Value = 0x1; } Flag { ID = "scef_other_a"; Value = 0x2; } Flag { ID = "scef_monster_a"; Value = 0x4; } Flag { ID = "scef_missile_a"; Value = 0x8; } Flag { ID = "scef_any_a"; Value = 0x10; } Flag { ID = "scef_ticker_a"; Value = 0x20; } Flag { ID = "scef_player_d"; Value = 0x40; } Flag { ID = "scef_other_d"; Value = 0x80; } Flag { ID = "scef_monster_d"; Value = 0x100; } Flag { ID = "scef_missile_d"; Value = 0x200; } Flag { ID = "scef_any_d"; Value = 0x400; } Flag { ID = "scef_ticker_d"; Value = 0x800; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/defs/doomsday.ded0000644000175000017500000000014111357170241021543 0ustar keeskees# Doomsday Engine 1.9 # Definitions shared by all games. Include "flags.ded"; Include "xg.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/0000755000175000017500000000000011523516205017070 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/res/0000755000175000017500000000000011523516205017661 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/res/deng.icns0000644000175000017500000014507711357170241021473 0ustar keeskeesicns?ics#H????is32 ,kimiaaU]WU,}.ʸ.iӹsvwxy}D^ύrPERRWdT.Jҡt37¢ȗühG8<^a?srvoɋS5A17RT`hjdN:BMhkkyrdeni3 "#)3396363 ,jjnkaaX`ZV,}3ͺ4nռ||Lgѕ{\Xhe]m\-Vէʴu3HǬˤʫsM>Nv|_ї`=_WZpyj(Qfg{E 99?IOY]``UX\[ULPOF}ŭnQϴv^abb`c(ĂhC;JA?L8(М^oƓO,"VX4kjngxs:-%'?IV^`[yoB (46KZ^gcZX_W &),-)-(s8mkQP^]27KPPPPPOOOKICN#????????????????????????????il32  !y\'#ż/!Ƚk>Ŷy|}}w/HǶvjebeinjknpplhf.Dӓwg[QC=CHQXYXXYYTG'B{gadF8@F9OJEIKYWWD=*AtybRajUB2@fqmbaS޽FL;DWf/`ڡpcOUA6>E:􌗊ymhфYa`I/<6C1AõswpiflU?GA*#'++:;@JPZ][cd^^wpnP=?<22786>HNY^adfghheŒvjL'?B<788BYaWZaeimnifebajs|p< 4IG==MVizn^epx{{nfbelowe3GJLW\f{kr{qlpuxzy_)3*-7DLDDLPMMKFEHHIF1! x^*(Ǿ3&q! FȺ ~~8PQɹ~roovxumptxxtpp5Oԙqf_RSYak_Z^`cgaK! NrlmRJPZReRPaH6# N}l`}T>.Np|ylj^LM9 UhqFm۩[[D FORQ󗣚ŒՑlCohO >LCYPZƜʭutY :KLLEIOPaZbnxݘ~~a :M[VTX]\enoӮd2U\eY]]`o}z~ŻSE^lecilz##Dbunru}ȿ50BFDDKU]\^gorwy{~xtmO  d~JɽvyĸM{hfhllghljegg\&zk]OMTVTSVTPMI$ҍmZNG75;?DB@?<<>9* k~r\XX7-4>1HC914D@?( XbXFxZa; EZbZX}@ܷ+,7O%Zٞi\57'!'0􈒅reWyBEA05%7lphbvIJ7!!-04?FPTQZ[VSjQQ>%)'&**)2>DNUX[]_[}[W?*-0+,,/>NLPW\`cc`]\VU]_gk_3"152169Ga^T\cgiia\XY^cgkqS#4<;>@I[g^dmppokebddhliP""'0878>DDA?>INPQOMMLNNE@<'+;++=kz{`^|3UCFAC@1+=bspֻN~_Qbh|GGF7+?YibeI@USO@iy=JdJLK= +BZ_RHB6RNecRRQB DI&X4)N9ANU]PkdۃV\XXF +39>?q&Pޡ[Tlgl[Rbca`K %/9;5.t̵-&_iaYm_글igU +7>=E2!-:,-55244<@HNSY]_`beedegh\bdlucO+ CG8<5/145766=HFLRY]_abcdeghgidwwzncL)2;;@;347:867>FNPU\_aeghijjhghgd`r}szfhE@=BD98;K^hdXW\`dgijmmkige hggqzte+)-FEGA;;=EMWhs{lZ_cgkqw|}tjgdbcgllpy}P' 4IJHB@BY^Vcq|fafq~}||xojdbfjmpru{f% -CNKKNS_Zcr~wgpxtmkoqtwy{~xT%,3;B69=GQZd`OV^djhede_\XY\[\_^ZL+       # 3PRXORSUeXeVQPMPUQNPHC?RXZHAHIE' #~Ŀj5'-Ŀ<) #½|1)3YŽU +<¹~~h. ,"Dȿ~zzy}|{sxy}yz}vxl7U+!Fŵyrhhniotrunjjoqpwyrpkqa(+ FŻÙvmgaSVWYagpjZ[a_eegpchXA+ I炈|sd[WYVHKMQVV[mcQTWVWW[^QA3+ Ivu~hcokRDML\]SUnjYk_HL]ba`WB73%+ JtjiEeek??;,+ Ll|y־Zlc|JHD3+ Nctpn\M^]fg~LVjQPK:+ Skp^]XGk~l\YUB+#V]XTgG@[NXbowߎfhb^I+ AIMLxCbૹw{nhupjfP+?LJGAмLDq˄餒誐xvrmX+=PIDKAIULLUXVRSZkssr伻vyt]+8KFLVKONSWWUi^^jryŠ|zb"+ 9LIY]OSVT^^\etiluєd+3SN[gSW[]^\[`ivsxZ +$RTUq][[\]]dq|}y?+:\Wim_`cdelx|ļj3)C`^olfeosnx."(#<=;4#*ctvi^M?;?<,++0426A=67830/01-#*Spw~z}ehQO^Y:&//BC05UN3<8*2DFDB9# +LeigWRv%K:<}$#+AWVҷDwyUG[bo+)$+6LIU>6KIF7cs&6R./+ +6A9>9.KC^q}P872&+!*.(R+ H08GNVFdQw>A=9,+aHݞSIfRcK;IHD@2+oɲ!XbZOgKRKIF7* "0 ))%()1FNKDLSUVY[YYZUݢFMJ< "!$ "$&%%115=CHNSUWY[[\\^`QSTKRO@ *#"()#%'**))1=;FPahWX]bikigb_[YY\_cefikpU%0:>;:=A@HR^ha]cimoppoohfbadbcfilnhG! ',-)*,3;DKLHKOTXWWVVTSQQTRQQRNB$h8mk FpnCid OM #(;!";?8-,*4?<)#+))(*))(,><10)20!+?6 8?8%;?/  'A3 >:,/)! 75!$592) "1:7$ '$%#1(83$&$$':1 3:4&6:*   :/(*# 937\~5yT # ^/ȀɁ Ǥp:/8% 3C½»Ŀû~@99/jIòa$(0"U ÿh024$A 'x26:!Z  i064V'&`R46(n4(1:26[(<,¿ `2:%82?-64A:1 `9?'k T49$>?-/¿~)}}y~{|zk4;(r+A>A¾{{zy|y~|~{|wrzxz{xzx~}~xs{~}v560/A> 3C;qځ]¿}|zwqmjmopoqpmqsxzyrjrpoutrlplgqvvrowvrtzyvrsuqnqrtmjnpkmmrS=1 t 2C;t|yvttrnhdcgnpmgiddkmnmikokmupnjokeloonnqtqhpuvsoqoiloqgdhjcinqM0+ v 2C-- < 2Cg.~{zxurojigd`[Y[^J>KI?ABBCBBFIJJKLNRTUXY X[\ZUZ[[_b]YRTafe\KVa_SDDGC1/2 3D>eSwzvvtqmkh_c`YSQSWWC9DI;;<=>?>?CDFFGJIJPSSTUVUUTVXWTTVZZWTPPT\`_Y]YNEDCA@5/0 3D>b0nzxqnoog^[XWZRIFIMPN=2>F:699;<<;>ABBCFDCJNOOQRQSVRJOUQQSTMSTNX]VC@ECA@?70/ 3D?a0f|~|uuoeeg^UPNPUNGEEDIF5,8C<26778;8:>==?A?AEHKLLNPNMMLIMNJLQOJSODIPD;IB=@=;72/ 2D?^zS`vxwpmn`Z\XQKGFKHEA>=A>3.6@<-0334986;979::>@ADGGHKKLKJHGIIKFHLBHLBGF?;BC><;:9642 2E@\~zzyxwzjZsxwpcgcRJC:50/.3:;=>:99::.#"&'*7;54+(()*2=??FJJKMMLIGC>;=:870984771;C?@?<;:966 2E@Yz{~yjſUv1TotvscYOAV}h;*48;:?A8_uomnpp=2(Fy_36?EJLMJ>4?SgryvttvuvvuzU=BCB?=;;97 2E@Xyz}sxmٮ Phlnl]Ao 3+6:CC(?5 J6DILMKE8b3CB?=<:: 2FAXxy|uyygMaccYP@+< 1FBWtty{|{~|eL[YRIË93?F%4IMG; 5GGFEDBAA? 1FBUqoswwvxqfHYQ:ؖ*HHGGFDBCC 1FBRhilpprt`ugzDVFU-)*US6G*⠖ʄl>H;ӂI67b,1AIJIHHGFDEE 2GCPbchikqq[؃LY[N:@P95+=<34F-B.Ã:CPGCRP8m8KMKJIGH 2HDPb`efmsfdaZhd^Er:I8҂!)&#V7A.=DON5x9Ed8TYXLD/YASWU?Y=Ok8UYXJI?MQOONMMLKJJ 3JGM\ahifZDBTWSP>s~.6FF=0QKVZWFUF]^O?NJ5>PTRQPPONMLL! 3LIP`cbZVYI8NPMK:p|+2DN?2UMY[WLYMhTnQXBTVUSRPOON# 4LKT_ZRONTI~1EHHF6n{&.8ﹼ¼MC4VMZZUO\QnccJPWXXVUSQPQ% 5NMQQEGPORJe@7ABA.gz$/%т)#&')*-10//6DI5VO\YXQ]Spp]hՉZKYZ XWVVUSRS& 7OKFA>FJQQKJ%.2-!x!/*59;>??9/:QFL7XP[Z]S]Tptp_QՅNL[^^]\[[YYWWVU& :J97BC>EMLJ8YI]w+ F6&+/204L׫=O:XPZ\^S]TputkOڀ ᄅsPGV]_` _]\\[ZXWV' .;26>>9?FJI7\x($}{53>4-)s,)*#5BT>ZU`a`T_Spup]ރ œgM\fh fedba``+ (964=<;>4-257&| w.-,.)*̂KNVC`Waa`XeUotoUS]hj ihgedbc. +=21AD?<62:@4)"4}Ь^CS.10153(6jǯZ=?NVYM_]c_a_nn_P_ъUellkihged/ )=23>C?87>J@-+)&""% )(!)(-32379983/37<<;?HPU[ZXXNFEDEGM\bec[KHLJHO\ijZqXlmlkjihi0<-D8:@?85?KN6+-)(**))')+-021001246502469=?@EEGGHJMOQTVX[][[]^_aacddeffeb`aggbfij^hulksRloljgfl15,GEFA<=ENQH3/,*+,--,,.11343436248=:479;?BDHKLNPRUVXZ[\]``abdedejjgfjhQ ^LaffdWAɁSlqrsrme_^e1*HNPD@MOOPB51,+,.-.0334554490/8=B<8;<@DFIMNQSSWYZ[]^`_bcddedeiegeOˁ KYmqqoc@Tosuvul_[^`. )JOSSNNC>@992,#./../013565445226:AE?;>AEGJNOSUUXZ[[^ada_abcddedfghfifedMYRVVTZ\sxyztc^\^_+ (LOSRJA49;9;1.0221376569:;?HIA@CFHKMPSVXY[\]^__`abbccdeddeghgejiffXl[my|~{ob`_]]' $KOPA761;<2//0&113642377665669>4001122358:8898787769<>AHPOHHKOPQTX[\]]^aa_`bcdefghiihg efjkgegdQ]Б_k{zz~yjdbdb_XAJ;45<>@A82 33456:@?<;98658:=?CHQQLLOQSVZ\^__acgfghijiihg(fhiiheghg[KNcx}h[ct}{vogdcfccL  1A897:7$8997798779;;:=GRY_egf`XV[TTWXZ\]^_aceghijk2jjihijjkjhgfeefefedegkkhhikmsvxz|}~tjggfO   DD78@BCCBHD98 79978:;;DHOX`eilpuvxvjYVYZ[]_abcffghj klnruwyzvrmjig&edcbddbbegiklkjkosvyz|~{nfM >ECEDEIJE>;,<;:>EJKMPW^dimquxz{xeXZ[]_`bcegiijjknrux| }wqmkhhgfddcbefghjmnmkmquxyz}yh%  !DGF[DCKJC=<>=;=@@?FRVSPQV^dhmruxz|~taZ\^`acdfhijlosw{}}|~}zupmlhgfddca``cfggiklopmloqvyz|~D g $DGFCFFDGIH@@?<=@A?DQ[aZSRV]bfkquw{|~}n\^``befghkpv{~|}}z|zzxrnnkhfeedb`aeghikmlmqpnopsxy{|~U   *HCCHIJJG_F?>ACACKVbh`WUV[bfjpux|~yf_`begfhmv}|{{|z{yywrnonkhedcbbcfhikmmnoptsrqrvy{|}Y 4  +@HJJKJDGLH?AEDCFKT`gbZWVZ`ejotxzp`adffgmw~~|z|{y{|yywsonqmigedehijknmnrqrvvsstwy{}}~}U  +  >LJKIEKOH@CHGGFHNY`a]XVY^dinswz~wbbfkt{}5~|}~{~}{~~ysotrkjhffghhikmpooqsrtwxvtvxyz|}uD 0 2BHFHPRICGGRRJHJRX\]XVY^cgmrvz~~jbggipw{}6||~|}|vqwtnmjhjiknomnqsrruuttwyxwxz{}z], j  (9IVRJGJIZ`QJILPUXUTX^bekpuz}ocghjpuxzz{}~}|vrvupolkknrsrqnptvstwvttvx{|}xb9 K  #9CACHGZgXJHHILOOPW]beimrv{uehhkoquz|~~|wwxurqonpsuvtrswywyyxvtspaM.  7  !)# %(*.0136:<>?:122458;>@CEFGEDC ADEDA@CA?>>=>?@AA@@>@CAB=8-                         %%(&#+&  %""&    %"$   +! 55-0%$1."#$$%%&"%"$($$#%""#$4/%)#%("0+ 1>7/#9=' # !0'!*)'$5-4a7uN$"!  $!^DȀŧv?&7;%U "#;/û$Ľǿ½J@=4 $! p܀.¿ÿ¹üǶe).3 33 &#%Zm579&&%%/${9<@#3D "'#&n7=83o$$&%gX==+"S6+#9B9>Y)D/#ÿf:D(3-s7J.E/)v.OKB~~~{w}z{~{{x}BH%"^ 3SHi¾}y|{wz}ry{|zz{~rutpz~zs}y{yz|}{xvywyvsSNM"34TIsڃ]~yvsvxxvyzsx{{tywt}{wqtrlu}}vt}x|yz|wty|tpuxqtt{aK9' $ 4TJvՀa~||zvqmlpx{vsxppz~}tqvru}vrnsphouvttx|ynx~wzxpuy~oiptiqz~[:/-"",4TJtπa¾~zvtrolicbjpsnhgikmpqtutrowuomjoldkikpqrrqllpz{xslsuvnhjljuunH403!w*4TJpǺ|wrnjgdd\Ybabcb^]bghhimqtuspigghb^ghfhgghgmlgjpy{tknnbdggnqn_W>2**x35ULlƷ~{yuqmifefYQ\WUZ[[XW^cbdehlsxshdb]ZY]ffc`]cdgikhbhswsneUYinogWKO;(# )35VMj¾0}zwtrpnkjgimYKWVSVVWXUT\_aacdiqtsk^VW"[cea[`a`hlda\_mutiXbon_OIKJ2"" (35VMh/|~|yuroiigc__bfhTFQVNPQSUUQSZ]__`eddqukYU!W]a^[[\cd_]YW\ionhmh\OKHD>,#" ( 36WOe 0t|yyxrjfb`a[TRV\a`NBLTLMPPQSROVZZ[]c_[lrufTSW]]UW]YY]^W\`[hofQLMIB97-&# (36XPdm{qqulc_[[\XVSRU[YG>HQMIO4RVORZVVY^Z^ejqraRQQPPOQVVWWRU\[U`\PX^QGOJA954-)&('6XPc2h{yymgid^YSRTSSPLMTQF@FONDHOLOUTOXTRTWV\`bhpn]PONMMQVUPSYPTYOQSHDKK=7521/,)('6XP_}qUc|zorn_ULE>:98>FHIKQMJIIHA:6>>BSXMOD??@BLZ\^jqn\RQQOMHC@EECC>DA=@?8BIA:86520/+('6XQ\}oYyU^y~}ncXK]nD6AHNKOPGj|wy|}UN=;97531/('6YR]~sگ [txxwgJu >;IKTU;OI ]SgntxkQ>g2A@><;8752('7ZS^~nXmoncXL;MVY;e؆ Y_nrshP2DDB@><985('7ZS]~}kVif]QŋDCQY<QlsjX5GGDB@><:7('7[T]{y~~znSf_Fښ8MX=]itZ˵v@KJHFDB@=;('8\UYqrvyy{lxkOcS]757(\]H[D䧞΄}amVׂO?>g/6FMNMKIGECA=('8\UVkkpqs}fكQ_e^GL]D>9KKB(E^HYJIAƃZddON]ZAq=QRQOMKIGEC@('8]VWlimpyrke_tysTxGVCӂ.652!\K^J[kwtPWatDbgeXKBTVTQONLIGFB('8_YUhgq{x[yPkwwmS}CMM֜T^Knh`lYizFfkhXRHVZXVSQOMKIF!('9`ZUjpy{uhONlphcP|AHR\]Ljtil_vpZP`ZBG[]\ZXUSQOLJ#(':b]]qvtjcdSIgha^Ly=FQb^Novttelw]bL`a_][XVTRPM%(':dbismca[_TDY]][Iw:DG fdRox{zkxU^edb`^\YWUSQ'(';fegdWU^\^VmPLXXWBp;G7Ԃ3(58:=?BGHRdkRq{|o}}ىeZijhfda_][XVT)('=fbXQNSW]\US5CGA18L4,?KQV\TIQifmVr||qiօ[^mnmkigdb`^[YW+('C]LIPROU[YVBdVi5H=VE:DLQLL^ڶ^uZt}|tl܀ðaZkrsronligeca_\[+('8H@GMNJNRWUCa;E@-諈]tZu~{uc>QYcnuxxvusqoljhfda_].('$EHHCFHKJOUG1эZu^w|w}ځlie_^blvxwvtqonkifdb`/('#HJJDGIKFELE?<:SHG>Hƌd{`xyǤs^oxxvtrpnkigec1('*LJHNLILGCGEGD4 7UOIJEAѐeqi{amxywusqnligf2('.OHFQQKIIGFEMJ>1HԳn0X8f;RTMMQOAJyͷoY^p{sqpӊbt{zxusqnljh3(' #NJINQLEJGACLOIC?65;=:8?KI?>@HQGNVPOUWVTQKMQU$WY_kt|xnnlns}}yi|}zxvsqomk5(V3 FKNNOIDFDBFMPHGJKIHGJNRSQQTXUSYd^RPRRV\^^gghiikpruy|䢌łb}}zxvtqon7(U3 BFMQOHECCGPSMGHLMNNMPRUUPPWXUORbmcSUVV]bbjlnqsvz}~ vt{Źd~}zxvsqo8( 3 DEFNMFEN`WKIJO>PQRXXTSYXWPLZjqbVYY_dgkpqvvw}Ձ i\āf|zxvsr9(' EFFHHFIHYgVKJLPQPQSQORY^[Z[ZWSXdpucY[`ehkqsx{zĂxy}}xwq}zxut6 (' FIHKajVMMNQR>QNOV`^[\[\Z[biwwc^bfhknrv|s|zyt3 (%DKJNhkWOOPQRTUVUQPU`_]6^]_cgpyfcgknptw~׃~||s-("%@MLNL'KPlnZPPRRTVW[[XVX`a_`_^^`bdgr{khmqrtx$úע~~~n '!& 4OM/Qmq_SQRTUVXZ^_]\aa_`^ZWY\^`dm}{nkoqsz9¿^&("* $PQPOYQfufWTUTVZZY[]]`a\XWYZY^`befgl{qpux}ĺK2# *JRQkP\wr^VXVY]\ZY[^_[WY[]\\`cfiknlosvz|û{/)-# 8USRVp|hY6[^]ZZ_\YY]ba\[ahlqwz{ys{wuy{~)üd(&"")QUTZfu^Z[[\[Y^^Z[_b_^]bjptx||vyz}½ ?+$%& 8XU\x|f\I[]^^[^ab_\_bflquy|{w||~žh')"$)MZXPYk|te`_ac__cgeabeefhmrvz~z}~5+%"$"+ &WZYP]r~obafc^chhacjljhhlrvz~}U.'&"$-# 0[\[Pbyyhigabihcckqtpkkmsvz}n%+%%$,!6]^]Xguurdbilecgnvztomnrwz~u+)(&%-1[`^)jvbfnicehmuyvqonqvz}p0&"#o#-," &Sca``_lvdlohgghlrvwtpprwz~^+(%n'&+%<[dcaluhqlnnihjnrttqprvz}ÿ@%+'##!-&2,>Wdixqwluxpkkmorsrqux|~!¾ R-+'(""F(-(.*+?Xemsgszqihhiklmmquy|€ oE',&)%#"#%'-,*%+&+0+'&''*.02469;>ADFHFAFDFHJNPSUWZ\^``bdfhihijlmlmopqrqqpokihgfec]VF3 (++)('&""!%-)(,-0&   +-((-&$'"-#-'+()+-,++.++,,*)($% "&'()')(''* +''()+%$"!3'# %#"$%!$!!$#!$""33P            &                 0          ?g r^2   C- ȼg( > &¿ s+T _M >  Y  > _ ? |(O 9  R¿%2 [ u S u C  ` !~~yy}|{|}}y{||}{~zxy~zz{{y{{|}z{{| z{}|~o E]}xwwsswvuuwvqsvz}|{wsqpsx|}zvwvsvtuyuvvuvtrtxvty3 a  xqpqmlponoomkkmouyuromlljijjotvuqnnqmkolnon omjjpomsO A ~{ujhjddgfefe+jnqoljhgfhfcddfglopkikicdbfhfegigbbffej\8ށ+¿}xtpe`a\]`]_a`,glkieceecaec_`bbaadiigfc]\\_a_^`c`\\_^^aZJفG|zyvsmiaYYXY[WY\Z\dgfc`^]__`\`_Z]`_][^^`ehd[ZXYZ[^ZXWXWX.VԀGÿ~zwtrpnkea[TSSRUVSVZ__`[W[ZWZZYWZ[UX[\XW[ZX[ab^WTRUVZRPRTOQRZ3;Y½}zwsokihea[VUQNO2RNPZYXYTRUUVWUSQVWPRUUTTUVUQUY\YTTSMPRULGLNHMRS, TV}yuqlgc_\ZVSLKOMJJIIJKMNOQRQPOSQONMQQLNMMOLLMRWUQNILMNHCDFGLJH# KR|vrmgc^YUPMNE@KFBCCBBEGHHIKNOPNMIKIHLKIIH JIGHKOQMFFEB ACCD=9 =N~yvrmjfc^YVSPNMA9C=9<= >ACCDEGIMOLGEFCEJHCCBCCDDFCADHMKG@:2<<689:;::>?AABCEIKKIC?BGDB??@?BD@>==DIOD8>D?70*+-HQp}wsnkgc_[WPNLJGHKNM:,5:23345667;<=>>@AAGID=;<;;=AA?;::==:9867=C@:?<5,)'%#D0g|}zspkfcc^UOKFD?:8;DIG4'/70./12332689::=<;BDF@9878;?>768556634657:;.,*&% ?xw||$_tusllg][`\NGC?=;<86:A>-"*3/),-./2014 5868;>BC;5543588420022/41,.2-&-'" :norwz~s4XmmlfcbVPQNE?975573.085)"&/.%'**+//-10//11458;?>71210 /120,,.,,-) #!&) 7hhlpsvz}}tooljjnbRilkdZ[WH>5.)%# %++*-51+*5"!-1-+" !")2570$V $$"  3]_cadhkmhUEWXWMG;!-47[Ն =6@BB;3 ~'&%#" 1XX^`aaeeSBQOG?.%07+?C=3 )('%#! /TSW[\\^YW>NG1ג-6@_'?BA5; -576430/-+)( #$;BIIHC1z3KNJG6o{'-@@4(LBMPN>P7HOD-:6$ *8:975420.-+ $ &@AA=;<-{.EFCA1lx"(=H5)OCNQLBT:RBeDM ,<<:986420.-$#->976+p*;>>=-jw%1︻F9,PDQQLFV?YQW9:??=<:875310 &',3.0432+V;.887&cv$Ђ $!"%)(-;@-QFRPOIXA[]O^҉L7BBA?>=;:7643 )'$'&),-.*5%)#s$!+.0454/'2H<;98!"#%&Nsyw3F2SHSUUJXD]``OS,2:CIKKJJIHFEDB@?=;;  &!p$̍4G4TJUWVJXD]`]M҂VME<89AIK JHGFDBA?>=o.9J6ULWLZC\`\N܃ٿX8DKLKJIGFECA??  " y s""!# "}߇EEM;[NXP`E\_\EACLMLKIIGEDBA "#! -yϩX;$J!%$&)(.fƬT67ELODXSZVZO\[NCXЊ @INMMKIHGECC!#6!&&(+./.*&*/553326?GKQPOPF==<NONLKIHGED" !  !"$#$#%)(%&)+.246:;<=>@CEGJLOQTQRSTVWXYZ[\\][YXY__ZY[\P^l`_h :OQONMKJIGG# !"!!"  !"#%$$%%'#$)0-(+-/378ACFHHLNOPRSVVWVXYZZ[\[[\\[[\]]_``\]YEȁ BI[^^\R2 @BFHLNOPRSTUVVWWXYYZ[[\]\^__^__]a`\ZMf JQWYZWSRPONM""#-/&##$*%%&))(&)*))()(+/29A@99=@BDGILOPQRTVWVVWXYZZ[\]]_ ]]ab]\YEz]U\Y\\WTSQPOL%$%01(%&''(+.-,+**)-/25=DD>>ADFGJNPRSSUWYZZ[]\]]^^``_ ^\^ab_\[WFVΈQ[gd^][VUTSRQI&%&%&13+&'(),21.-,++*)(+.137=FFABDFHLOQTUUW XY\]]\\]^^_`a,_``__^]_`a_[Z[ZPBF\rs\LQailke]YWWVTSS@&'&.5.('('()*,*()-0358:=FJDEHJMOQSUVWY\^__`abbccb`__^%]__[YZ[[YUPKJIGIKOT\bfijmmkbZXYVUTU2 $(' +74+(*))++*++*)**+/37:=??ALLGILNPRSTVVWY[]^_`abccbaab`_^ ]]__]ZYZ\]\]^_abdeghijjklnkbZZXVWR*)*4:1*+*,,*+,,**,..--07;AFJMKFIPIJMNPRSUVWY[\]^_`aab aa``aaba_^\]\][XXZ]^^`acdffhi jklmnj`ZYXXC (*0<6,+,*++,,+,-../.27>AFKRY^YOOLKMOQSSVWXZ]\]^`aa``ab_` ^\\[ZZ]\YXY\]^_`cdefgi jkklnnh^YYW(-,.9;1.-.[-./01/125:?CHKQZekaTNMOQRTUWYZ\]^_`abaabdfhiifca_`_^^]][ZZ\\YXYZ\^`_``bdfgghijjkkllmle]\F  '.-=3;81//00//021023445:@CHLQXcnoaRNPQSUWXZ\]_``aabcegikoqpkfc``_^\ZYXXYZ[]`abcegghikjkklkklidZ"-.K6<60010/02312797669@CFLQU^jpl\QQRUWWY[]^_``bcfhiijljmnkgfba`_\[[YXXVVWXYZ[\_bdfghijjkjki9 /0/A1;;3431134238=@<88:@DGKQUZdlndXRUVWX[]^_`begjlkjijjfjlghgdaa`^\[ZXWYZ[\]_acdccdfghiijklklJ 1-49983246546:@E?;:;?DHKOUY_jnh_VWWXZ\]_`dhklmmji"gjkeggebab`]\[ZYXYYZ[\]^_`ceedeeghijkllmO032/6?;3477556:@C@=;;?CGKNTX\cihc[XXY[]^`dgjkmlkjiiji ghhfcacb_]\[ \[[\]^_``begfgijkklkK,543@7C<47:86679=AA?<?@==@DHKOSW[^beebZY]]^adfhhiijklmoroknmknmjgdcfcb`^__adda_`abbcddfhi jjljR'R!/68A=:=:?A<99:;=>==ADHKNRWZ^acee^Z]^_acfgghilopnnpnlnmkmljhfegeda`acfgfecbbccdefhjkklhV3  ".48=9?E>98#9:;;?DHJNQUY\acfhb\^`aacehjknqsspnoononljjkjhgffghjjkkigffg hhgfcVE(  "$&(*-/1/+-./0124689:;;:9:;:9:;:9989:;:98 9853'       t8mk@&6@FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF?5$,a϶[' HА? ;3wg"*% $   yh ?8  ME   44  h^  ")  37 BD KN  PS" QU# RV$ SV% TW& TW& TW& TW& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TX& TW& TW& TW& PS& JM& =D& 1;' (5&  $vs3$  $LQ1! "2?.+fg:*)@ZNS.objects?IBCDEFGHIJKLMNOPQRSTUVWX_NSWindowStyleMask_NSWindowBackingYNSMinSize]NSWindowTitle]NSWindowClass\NSWindowRect\NSScreenRectYNSMaxSize\NSWindowViewYNSWTFlags[NSViewClassF EG pxH _{{82, 551}, {628, 413}}_Doomsday Engine Startup\]^YNS.stringXNSWindow 78`aab5_NSMutableStringXNSString\d^TView ghij.lmZNSSubviews_NSNextResponderWNSFrameCD=oqpghstiuvwxyzUU}~}[NSSuperview]NSNextKeyView[NSHScrollerXNSvFlagsXNSsFlags[NSVScroller]NSContentView A>:B=q}:>ghstivppYNSBGColorYNSDocViewYNScvFlagsXNSCursor65 9=qhsIv}}.[NSFrameSizeXNSMinize\NSSharedDataZNSDelegateYNSTVFlags_NSTextContainer32 4Y{571, 14}WNSWidthZNSTextView_NSLayoutManagerYNSTCFlags"D.]NSTextStorageYNSLMFlags_NSTextContainersb.ǀ\^P 785_NSMutableAttributedString_NSAttributedString=q78գ5^NSMutableArrayWNSArray785785.._NSSelectedAttributesWNSFlags_NSDefaultParagraphStyle_NSInsertionColor_NSLinkAttributes_NSMarkedAttributes_NSBackgroundColor" a!,1WNSWhite\NSColorSpaceB1 785WNSColorB0 =WNS.keys%)#$+[NSColorName]NSCatalogName('& VSystem_selectedTextBackgroundColor K0.66666669 !*& _selectedTextColor785\NSDictionary=/0-.+[NSUnderline UNSRGBF0 0 1 78#$$5_NSTextViewSharedData\{586, 1e+07}X{114, 0}78()*+,5[%NSTextViewVNSTextVNSView[NSResponder_{{1, 1}, {571, 371}}/012YNSHotSpot\NSCursorType78W{4, -5}785578788+,5ZNSClipViewhs:;iv<pp?pABCDZNSCurValueXNSTargetXNSAction"?;=<_{{572, 1}, {15, 371}}\_doScroller:78HIIJ+,5ZNSScrollerYNSControlhs:;ivwL<pp?pPBCRSYNSPercent?="?rC@_{{-100, -100}, {87, 18}}_{{20, 20}, {588, 373}}78WXX+,5\NSScrollView_{{1, 9}, {628, 413}}78[++,5_{{0, 0}, {1680, 1028}}Z{213, 129}_{3.40282e+38, 3.40282e+38}78`aa5_NSWindowTemplate78cdde5\NSMutableSetUNSSet=gqhijKPRmnopqr?]NSDestinationWNSLabelXNSSourceLNO23vM_StartupWindowControllerXdelegate78z{{|5_NSNibOutletConnector^NSNibConnectormnorpQOL[startupTextmno?rpSOLVwindow=pp?UL U78֢5=0pU0? U=pp0?LU=YZ[\]U]NSScrollView2\File's OwnerVWindow=U=U=Uh0pi?pj KLPRU=ʀbc/defghiU    =q=U=U78ޢ5^NSIBObjectData#,1:LQVdfEK$7>LZh$7@KNPR !#%').02Lfoy   :FT`ir~!$&/246cox3AK^`bdfsuwy <S[u   ! $ & 3 ; @ B D I K M O d p ~    $ & ( - / 1 3 ? L R Y [ d i    " ' 0 9 D e p y      ! & ( C \ e n {   ! ' 0 7 9 ; = ? P ^ f o q s u w "+68:<>@BKPYdfhjlnpy  #68:<>@BDFHJLNPRTVXabdmnpyz|deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/res/Startup.nib/info.nib0000644000175000017500000000070511357170241023522 0ustar keeskees IBDocumentLocation 718 122 356 240 0 0 1680 1028 IBFramework Version 439.0 IBOpenObjects 5 IBSystem Version 8B15 deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/res/Startup.nib/classes.nib0000644000175000017500000000056411357170241024227 0ustar keeskees{ IBClasses = ( {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, { ACTIONS = {closeNow = id; }; CLASS = StartupWindowController; LANGUAGE = ObjC; OUTLETS = {startupText = NSTextView; window = NSWindow; }; SUPERCLASS = NSObject; } ); IBVersion = 1; }deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/src/0000755000175000017500000000000011357170241017660 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/src/qt.c0000644000175000017500000001712511357170241020456 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * qt.c: QuickTime implementation for Ext and Mus interfaces * * This is only used in the Mac OS X version of the plugin. */ // HEADER FILES ------------------------------------------------------------ #include typedef uint64_t io_user_reference_t; #include "doomsday.h" #include "sys_audiod.h" #include "sys_audiod_mus.h" #include #include // MACROS ------------------------------------------------------------------ #define BUFFERED_MUSIC_FILE "_dd-qt-buffered-music-file" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- static int DM_Ext_PlayFile(const char *filename, int looped); static void DM_Ext_Stop(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean qtInited = false; static boolean inLoopedMode = false; static unsigned songSize = 0; static char *song; static Movie movie = NULL; static short movieVolume = kFullVolume; // CODE -------------------------------------------------------------------- static void DS_Error(void) { Con_Message("DS_Error: Error playing music with QuickTime.\n"); } static void ExtMus_Init(void) { if(qtInited) return; Con_Message(" Initializing QuickTime.\n"); // Initialize QuickTime. EnterMovies(); qtInited = true; } static void ExtMus_Shutdown(void) { DM_Ext_Stop(); if(song) free(song); if(movie) DisposeMovie(movie); // Shut down QuickTime. ExitMovies(); song = NULL; movie = NULL; qtInited = false; } static int DM_Ext_Init(void) { ExtMus_Init(); return qtInited; } static void DM_Ext_Update(void) { if(!qtInited || movie == NULL) return; MoviesTask(movie, 0); if(IsMovieDone(movie) && inLoopedMode) { GoToBeginningOfMovie(movie); StartMovie(movie); } } static void DM_Ext_Set(int property, float value) { if(!qtInited) return; switch (property) { case MUSIP_VOLUME: if(value > 1) value = 1; if(value < 0) value = 0; movieVolume = (short) (0x100 * value); if(movie) { // Update the volume of the running movie. SetMovieVolume(movie, movieVolume); } break; } } static int DM_Ext_Get(int property, void *value) { if(!qtInited) return false; switch (property) { case MUSIP_ID: strcpy(value, "QuickTime/Ext"); break; default: return false; } return true; } static void *DM_Ext_SongBuffer(int length) { if(!qtInited) return NULL; if(song) free(song); songSize = length; return song = malloc(length); } static int DM_Ext_PlayBuffer(int looped) { if(!qtInited) return false; if(song) { // Dump the song into a temporary file where QuickTime can // load it. FILE *tmp = fopen(BUFFERED_MUSIC_FILE, "wb"); if(tmp) { fwrite(song, songSize, 1, tmp); fclose(tmp); } free(song); song = 0; songSize = 0; } return DM_Ext_PlayFile(BUFFERED_MUSIC_FILE, looped); } static void DM_Ext_Pause(int pause) { if(!qtInited || movie == NULL) return; if(pause) StopMovie(movie); else StartMovie(movie); } static void DM_Ext_Stop(void) { if(!qtInited || movie == NULL) return; StopMovie(movie); } static int playFile(const char *filename, int looped) { OSErr error = noErr; CFStringRef pathStr; CFStringRef escapedStr; CFURLRef url; FSRef fsRef; FSSpec fsSpec; short refNum; if(!qtInited) return false; // Free any previously loaded music. if(movie) { DisposeMovie(movie); movie = NULL; } // Now we'll open the file using Carbon and QuickTime. pathStr = CFStringCreateWithCString(NULL, filename, CFStringGetSystemEncoding()); escapedStr = CFURLCreateStringByAddingPercentEscapes( NULL, pathStr, NULL, CFSTR(""), kCFStringEncodingUTF8); url = CFURLCreateWithString(NULL, escapedStr, NULL); CFRelease(pathStr); CFRelease(escapedStr); // We've got the URL, get the FSSpec. if(!CFURLGetFSRef(url, &fsRef)) { // File does not exist?? if(url) CFRelease(url); DS_Error(); return false; } CFRelease(url); url = NULL; if(FSGetCatalogInfo(&fsRef, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL) != noErr) { DS_Error(); return false; } // Open the 'movie' from the specified file. if(OpenMovieFile(&fsSpec, &refNum, fsRdPerm) != noErr) { DS_Error(); return false; } error = NewMovieFromFile(&movie, refNum, NULL, NULL, newMovieActive & newMovieDontAskUnresolvedDataRefs, NULL); CloseMovieFile(refNum); if(error != noErr) { DS_Error(); return false; } GoToBeginningOfMovie(movie); StartMovie(movie); SetMovieVolume(movie, movieVolume); inLoopedMode = (looped != 0); return true; } static int DM_Ext_PlayFile(const char *filename, int looped) { return playFile(filename, looped); } static int DM_Mus_Init(void) { ExtMus_Init(); return qtInited; } static void DM_Mus_Update(void) { // Nothing to update. } static void DM_Mus_Set(int property, float value) { // No MUS-specific properties exist. } static int DM_Mus_Get(int property, void *value) { if(!qtInited) return false; switch (property) { case MUSIP_ID: strcpy(value, "QuickTime/Mus"); break; default: return false; } return true; } static void DM_Mus_Pause(int pause) { // Not needed. } static void DM_Mus_Stop(void) { // Not needed. } static void *DM_Mus_SongBuffer(int length) { return DM_Ext_SongBuffer(length); } static int DM_Mus_Play(int looped) { char fileName[256]; sprintf(fileName, "%s.mid", BUFFERED_MUSIC_FILE); convertMusToMidi((byte*) song, songSize, fileName); return playFile(fileName, looped); } // The audio driver struct. audiointerface_music_t audiodQuickTimeMusic = { DM_Ext_Init, DM_Ext_Update, DM_Ext_Set, DM_Ext_Get, DM_Ext_Pause, DM_Ext_Stop, NULL, NULL, DM_Ext_PlayFile, }; deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/src/SDLMain.m0000755000175000017500000002266111357170241021277 0ustar keeskees/**\file *\section License * License: LGPL * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © Max Horn *\author Copyright © Darrell Walisser */ /* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #include typedef uint64_t io_user_reference_t; #import "SDL.h" #import "../include/SDLMain.h" #import /* for MAXPATHLEN */ #import #import #import "../include/StartupWindowController.h" #import "../include/DoomsdayRunner.h" /* Use this flag to determine whether we use SDLMain.nib or not */ #define SDL_USE_NIB_FILE 0 int gArgc; char **gArgv; static BOOL gFinderLaunch; /* The window controller takes care of the Doomsday startup message window. */ /*static NSWindowController *gWindowController;*/ /* Set when the startup window is created. */ /*StartupWindowController* gStartupWindowController;*/ #if SDL_USE_NIB_FILE /* A helper category for NSString */ @interface NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString; @end #else /* An internal Apple class used to setup Apple menus */ @interface NSAppleMenuController:NSObject {} - (void)controlMenu:(NSMenu *)aMenu; @end #endif @interface SDLApplication : NSApplication @end @implementation SDLApplication /* Invoked from the Quit menu item */ - (void)terminate:(id)sender { /* Post a SDL_QUIT event */ SDL_Event event; event.type = SDL_QUIT; SDL_PushEvent(&event); } @end /* The main class of the application, the application's delegate */ @implementation SDLMain /* Set the working directory to the .app's parent directory */ - (void) setupWorkingDirectory:(BOOL)shouldChdir { char parentdir[MAXPATHLEN]; char *c; strncpy ( parentdir, gArgv[0], sizeof(parentdir) ); c = (char*) parentdir; while (*c != '\0') /* go to end */ c++; while (*c != '/') /* back up to parent */ c--; *c++ = '\0'; /* cut off last part (binary name) */ if (shouldChdir) { assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */ assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */ } } #if SDL_USE_NIB_FILE /* Fix menu to contain the real app name instead of "SDL App" */ - (void)fixMenu:(NSMenu *)aMenu withAppName:(NSString *)appName { NSRange aRange; NSEnumerator *enumerator; NSMenuItem *menuItem; aRange = [[aMenu title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [aMenu setTitle: [[aMenu title] stringByReplacingRange:aRange with:appName]]; enumerator = [[aMenu itemArray] objectEnumerator]; while ((menuItem = [enumerator nextObject])) { aRange = [[menuItem title] rangeOfString:@"SDL App"]; if (aRange.length != 0) [menuItem setTitle: [[menuItem title] stringByReplacingRange:aRange with:appName]]; if ([menuItem hasSubmenu]) [self fixMenu:[menuItem submenu] withAppName:appName]; } [ aMenu sizeToFit ]; } #else void setupAppleMenu(void) { /* warning: this code is very odd */ NSAppleMenuController *appleMenuController; NSMenu *appleMenu; NSMenuItem *appleMenuItem; appleMenuController = [[NSAppleMenuController alloc] init]; appleMenu = [[NSMenu alloc] initWithTitle:@""]; appleMenuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""]; [appleMenuItem setSubmenu:appleMenu]; /* yes, we do need to add it and then remove it -- if you don't add it, it doesn't get displayed if you don't remove it, you have an extra, titleless item in the menubar when you remove it, it appears to stick around very, very odd */ [[NSApp mainMenu] addItem:appleMenuItem]; [appleMenuController controlMenu:appleMenu]; [[NSApp mainMenu] removeItem:appleMenuItem]; [appleMenu release]; [appleMenuItem release]; } /* Create a window menu */ void setupWindowMenu(void) { NSMenu *windowMenu; NSMenuItem *windowMenuItem; NSMenuItem *menuItem; windowMenu = [[NSMenu alloc] initWithTitle:@"Window"]; /* "Minimize" item */ menuItem = [[NSMenuItem alloc] initWithTitle:@"Minimize" action:@selector(performMiniaturize:) keyEquivalent:@"m"]; [windowMenu addItem:menuItem]; [menuItem release]; /* Put menu into the menubar */ windowMenuItem = [[NSMenuItem alloc] initWithTitle:@"Window" action:nil keyEquivalent:@""]; [windowMenuItem setSubmenu:windowMenu]; [[NSApp mainMenu] addItem:windowMenuItem]; /* Tell the application object that this is now the window menu */ [NSApp setWindowsMenu:windowMenu]; /* Finally give up our references to the objects */ [windowMenu release]; [windowMenuItem release]; } void openStartupWindow(void) { /* gWindowController = [[NSWindowController alloc] initWithWindowNibName:@"Startup"]; NSWindow* window = [gWindowController window]; [window orderFrontRegardless]; */ } /* * Print a message in the startup window. This function is called from the * engine when a startup window message is printed. */ void PrintInStartupWindow(const char *message) { /* if(gStartupWindowController) { [gStartupWindowController print:message]; } */ } /* * Called when startup is done. */ void CloseStartupWindow(void) { // I don't know if these actually have any effect; the window controller // doesn't seem to realize it has a window in the NIB... // This isn't done in the right thread, though. /* [gWindowController close]; [gWindowController release]; gWindowController = 0; */ } /* Replacement for NSApplicationMain */ void CustomApplicationMain (argc, argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; SDLMain *sdlMain; /* Ensure the application object is initialised */ [SDLApplication sharedApplication]; /* Set up the menubar */ [NSApp setMainMenu:[[NSMenu alloc] init]]; setupAppleMenu(); setupWindowMenu(); /* Create SDLMain and make it the app delegate */ sdlMain = [[SDLMain alloc] init]; [NSApp setDelegate:sdlMain]; /* Create a window for Doomsday startup messages. */ openStartupWindow(); /* Start the main event loop */ [NSApp run]; /*[gWindowController release]; */ [sdlMain release]; [pool release]; } #endif /* Called when the internal event loop has just started running */ - (void) applicationDidFinishLaunching: (NSNotification *) note { //int status; /* Set the working directory to the .app's parent directory */ [self setupWorkingDirectory:gFinderLaunch]; #if SDL_USE_NIB_FILE /* Set the main menu to contain the real app name instead of "SDL App" */ [self fixMenu:[NSApp mainMenu] withAppName:[[NSProcessInfo processInfo] processName]]; #endif /* Start a new thread for the engine. */ #if 0 [NSThread detachNewThreadSelector:@selector(threadEntryPoint:) toTarget:[DoomsdayRunner class] withObject:nil]; #else // Won't return. [DoomsdayRunner threadEntryPoint:nil]; #endif /* // Hand off to main application code status = SDL_main (gArgc, gArgv); // We're done, thank you for playing exit(status); */ } @end @implementation NSString (ReplaceSubString) - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString { unsigned int bufferSize; unsigned int selfLen = [self length]; unsigned int aStringLen = [aString length]; unichar *buffer; NSRange localRange; NSString *result; bufferSize = selfLen + aStringLen - aRange.length; buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar)); /* Get first part into buffer */ localRange.location = 0; localRange.length = aRange.location; [self getCharacters:buffer range:localRange]; /* Get middle part into buffer */ localRange.location = 0; localRange.length = aStringLen; [aString getCharacters:(buffer+aRange.location) range:localRange]; /* Get last part into buffer */ localRange.location = aRange.location + aRange.length; localRange.length = selfLen - localRange.location; [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange]; /* Build output string */ result = [NSString stringWithCharacters:buffer length:bufferSize]; NSDeallocateMemoryPages(buffer, bufferSize); return result; } @end #ifdef main # undef main #endif /* Main entry point to executable - should *not* be SDL_main! */ int main (int argc, char *argv[]) { /* Copy the arguments into a global variable */ int i; /* This is passed if we are launched by double-clicking */ if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { gArgc = 1; gFinderLaunch = YES; } else { gArgc = argc; gFinderLaunch = NO; } gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1)); assert (gArgv != NULL); for (i = 0; i < gArgc; i++) gArgv[i] = argv[i]; gArgv[i] = NULL; #if SDL_USE_NIB_FILE [SDLApplication poseAsClass:[NSApplication class]]; NSApplicationMain (argc, argv); #else CustomApplicationMain (argc, argv); #endif return 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/src/StartupWindowController.m0000644000175000017500000000475511357170241024747 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #include typedef uint64_t io_user_reference_t; #import "../include/StartupWindowController.h" @implementation StartupWindowController - (void)awakeFromNib { /* [window setAutodisplay:YES]; // This startup window is used by the engine. extern StartupWindowController* gStartupWindowController; gStartupWindowController = self; // Print something. NSTextStorage* storage = [startupText textStorage]; NSAttributedString* str = [[NSAttributedString alloc] initWithString:@"Doomsday Engine launching...\n"]; [storage appendAttributedString:str]; */ } - (void)print:(const char *)message { NSTextStorage* storage = [startupText textStorage]; NSString* messageString = [[NSString alloc] initWithCString:message /*encoding:NSASCIIStringEncoding*/]; NSAttributedString* str = [[[NSAttributedString alloc] initWithString:messageString] autorelease]; // Where is the scroller? float pos = [[[startupText enclosingScrollView] verticalScroller] floatValue]; [storage appendAttributedString:str]; if(pos > .9) { // Stay at the bottom. [startupText scrollRangeToVisible: NSMakeRange([[startupText string] length], 0)]; } // A bit crude but does the job. (The event loop is blocked by SDL...) // TODO: Make a separate thread and invoke display from there. // Only actually does display when something has been printed. // This'll make startup faster. The thread can be stopped when startup // is over. [startupText display]; } @end deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/src/DoomsdayRunner.m0000644000175000017500000000256011357170241023012 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #include typedef uint64_t io_user_reference_t; #import "SDL.h" #import "../include/DoomsdayRunner.h" @implementation DoomsdayRunner + (void) threadEntryPoint:(id)anObject { extern int gArgc; extern char **gArgv; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // Hand off to main application code. int status = SDL_main(gArgc, gArgv); /* We're done, thank you for playing */ exit(status); [pool release]; } @end deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/include/0000755000175000017500000000000011523516205020513 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/include/DoomsdayRunner.h0000644000175000017500000000177411357170241023647 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #import @interface DoomsdayRunner : NSObject { } + (void) threadEntryPoint:(id)anObject; @end deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/include/SDLMain.h0000755000175000017500000000103711357170241022120 0ustar keeskees/**\file *\section License * License: LGPL * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © Max Horn *\author Copyright © Darrell Walisser */ /* SDLMain.m - main entry point for our Cocoa-ized SDL app Initial Version: Darrell Walisser Non-NIB-Code & other changes: Max Horn Feel free to customize this file to suit your needs */ #import @interface SDLMain : NSObject @end deng-1.9.0-beta6.9+dfsg1/doomsday/engine/mac/include/StartupWindowController.h0000644000175000017500000000217411357170241025567 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* StartupWindowController */ #import @interface StartupWindowController : NSObject { IBOutlet NSTextView *startupText; IBOutlet NSWindow *window; } - (void)awakeFromNib; - (void)print:(const char *)message; @end deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/0000755000175000017500000000000011523516205020017 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/apply-style.sh0000755000175000017500000000016211357170242022642 0ustar keeskees#!/bin/sh find Src -iname '*.c' | xargs ./deng-style.sh find Include -iname '*.h' | xargs ./deng-header-style.sh deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/deng-style.sh0000755000175000017500000000150411357170242022433 0ustar keeskees#!/bin/sh . indent-typenames.sh indent --k-and-r-style \ -ts 4 \ --blank-lines-after-declarations \ --blank-lines-after-procedures \ --blank-lines-before-block-comments \ --no-blank-lines-after-commas \ --break-after-boolean-operator \ --braces-on-struct-decl-line \ --braces-after-if-line \ --brace-indent0 \ --comment-indentation33 \ --declaration-comment-column33 \ --format-first-column-comments \ --comment-line-length79 \ --declaration-indentation8 \ --struct-brace-indentation0 \ -ppi 2 \ --indent-level4 \ --no-tabs \ --line-length79 \ --continue-at-parentheses \ --cuddle-do-while \ --dont-cuddle-else \ --space-after-cast \ --no-space-after-parentheses \ --no-space-after-if \ --no-space-after-while \ --no-space-after-for \ --ignore-newlines \ --swallow-optional-blank-lines \ $TYPENAMES \ $* deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/licensecheck.sh0000644000175000017500000005540011357170242023001 0ustar keeskees#!/bin/bash ################################################################################ # Copyright and License Summary # License: GPL # Online License Link: http://www.gnu.org/licenses/gpl.html # # Copyright © 2006-2007 Jamie Jones # # 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 St, Fifth Floor, # Boston, MA 02110-1301 USA ################################################################################ # # This script is used to do a license audit on sources in The Doomsday Engine. # It produces several files depending on the license of code it finds. # Currently it identifiles GPL, GPL + jHeretic/jHexen exception and Raven. # ################################################################################ FILES_PROCESSED=0 GPL_SOURCE_FILES=0 GPL_ONLY_SOURCE_FILES=0 GPL_PLUS_EXCEPTION_SOURCE_FILES=0 RAVEN_SOURCE_FILES=0 UNKNOWN_SOURCE_FILES=0 AUTOGENERATED_SOURCE_FILES=0 TOP_LEVEL_DIR=$PWD findfiles() { find -name *.c > $TOP_LEVEL_DIR/filelist.txt find -name *.cpp >> $TOP_LEVEL_DIR/filelist.txt find -name *.h >> $TOP_LEVEL_DIR/filelist.txt find -name *.m >> $TOP_LEVEL_DIR/filelist.txt FILE_LIST=`cat $TOP_LEVEL_DIR/filelist.txt` } findprojectfiles() { find -name *.c | grep engine > $TOP_LEVEL_DIR/filelist.txt find -name *.c | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.cpp | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.cpp | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.h | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.h | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.m | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.m | grep plugins >> $TOP_LEVEL_DIR/filelist.txt FILE_LIST=`cat $TOP_LEVEL_DIR/filelist.txt` } scanfiles() { let FILES_PROCESSED=0 let GPL_SOURCE_FILES=0 let GPL_ONLY_SOURCE_FILES=0 let GPL_PLUS_EXCEPTION_SOURCE_FILES=0 let RAVEN_SOURCE_FILES=0 let UNKNOWN_SOURCE_FILES=0 let AUTOGENERATED_SOURCE_FILES=0 echo "" > $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html for CURRENT_FILE in $FILE_LIST ; do # echo $CURRENT_FILE grep -q " * License: GPL + jHeretic/jHexen Exception" $CURRENT_FILE if [[ "$?" = 0 ]] then let GPL_SOURCE_FILES=GPL_SOURCE_FILES+1 let GPL_PLUS_EXCEPTION_SOURCE_FILES=GPL_PLUS_EXCEPTION_SOURCE_FILES+1 echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html else grep -q " * License: GPL" $CURRENT_FILE if [[ "$?" = 0 ]] then let GPL_SOURCE_FILES=GPL_SOURCE_FILES+1 let GPL_ONLY_SOURCE_FILES=GPL_ONLY_SOURCE_FILES+1 echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html else grep -q " * License: Raven" $CURRENT_FILE if [[ "$?" = 0 ]] then let RAVEN_SOURCE_FILES=RAVEN_SOURCE_FILES+1 echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html else grep -q "Generated by" $CURRENT_FILE if [[ "$?" = 0 ]] then let AUTOGENERATED_SOURCE_FILES=AUTOGENERATED_SOURCE_FILES+1 let GPL_SOURCE_FILES=GPL_SOURCE_FILES+1 echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html else let UNKNOWN_SOURCE_FILES=UNKNOWN_SOURCE_FILES+1 echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html fi fi fi fi echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html rm cp1.txt rm cp2.txt let FILES_PROCESSED=FILES_PROCESSED+1 done echo "
" >> $TOP_LEVEL_DIR/code.html echo "Individual file license details" >> $TOP_LEVEL_DIR/code.html echo "
" >> $TOP_LEVEL_DIR/code.html echo "Filename" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "License" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "File Encoding" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "Author(s)" >> $TOP_LEVEL_DIR/code.html echo "
" >> $TOP_LEVEL_DIR/code.html echo $CURRENT_FILE >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "GPL + jHeretic/jHexen Exception" >> $TOP_LEVEL_DIR/code.html echo "
" >> $TOP_LEVEL_DIR/code.html echo $CURRENT_FILE >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "GPL" >> $TOP_LEVEL_DIR/code.html echo "
" >> $TOP_LEVEL_DIR/code.html echo $CURRENT_FILE >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "Raven" >> $TOP_LEVEL_DIR/code.html echo "
" >> $TOP_LEVEL_DIR/code.html echo $CURRENT_FILE >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "Generated by makedmt.py" >> $TOP_LEVEL_DIR/code.html echo "
" >> $TOP_LEVEL_DIR/code.html echo $CURRENT_FILE >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo "Unknown or Unaudited" >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html echo `file -b $CURRENT_FILE` >> $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/code.html grep "Copyright" $CURRENT_FILE | sed 's/*\\section Copyright and License Summary//g' > cp1.txt cat cp1.txt | sed 's/*\\author //g' > cp2.txt cat cp2.txt | sed 's/* //g' > cp1.txt cat cp1.txt | sed 's/\/\///g' > cp2.txt cat cp2.txt | sed 's/Copyright/
Copyright/g' >> $TOP_LEVEL_DIR/code.html echo "
" >> $TOP_LEVEL_DIR/code.html } consoleout() { echo "Current Directory is: "$PWD echo "Total Files Processed in this Module: "$FILES_PROCESSED echo "This modules license structure is:" echo "" echo "Total GPL Only Code is "$GPL_ONLY_SOURCE_PERCENT"% (" $GPL_ONLY_SOURCE_FILES" files )" echo "Total GPL + jHeretic/jHexen Exception Code is "$GPL_PLUS_EXCEPTION_SOURCE_PERCENT"% (" $GPL_PLUS_EXCEPTION_SOURCE_FILES" files )" echo "Total Autogenerated Code is "$AUTOGENERATED_SOURCE_PERCENT"% (" $AUTOGENERATED_SOURCE_FILES" files )" echo "------------------------------------------------------------------------" echo "Combined GPL Compatible Total is "$GPL_SOURCE_PERCENT"% (" $GPL_SOURCE_FILES" files )" echo "Total Raven Licensed Code is "$RAVEN_SOURCE_PERCENT"% (" $RAVEN_SOURCE_FILES" files )" echo "Total Unknown Licensed or Unaudited Code is "$UNKNOWN_SOURCE_PERCENT"% ( "$UNKNOWN_SOURCE_FILES" files )" echo "------------------------------------------------------------------------" echo " "$AUDIT_TOTAL_SANITY_CHECK } calcpercent() { GPL_ONLY_SOURCE_PERCENT=`echo "scale=3; 100/$FILES_PROCESSED*$GPL_ONLY_SOURCE_FILES"|bc -l` GPL_PLUS_EXCEPTION_SOURCE_PERCENT=`echo "scale=3; 100/$FILES_PROCESSED*$GPL_PLUS_EXCEPTION_SOURCE_FILES"|bc -l` GPL_SOURCE_PERCENT=`echo "scale=3; 100/$FILES_PROCESSED*$GPL_SOURCE_FILES"|bc -l` AUTOGENERATED_SOURCE_PERCENT=`echo "scale=3; 100/$FILES_PROCESSED*$AUTOGENERATED_SOURCE_FILES"|bc -l` RAVEN_SOURCE_PERCENT=`echo "scale=3; 100/$FILES_PROCESSED*$RAVEN_SOURCE_FILES"|bc -l` UNKNOWN_SOURCE_PERCENT=`echo "scale=3; 100/$FILES_PROCESSED*$UNKNOWN_SOURCE_FILES"|bc -l` AUDIT_TOTAL_SANITY_CHECK=`echo "scale=3; $GPL_SOURCE_PERCENT+$RAVEN_SOURCE_PERCENT+$AUTOGENERATED_SOURCE_PERCENT+$UNKNOWN_SOURCE_PERCENT"|bc -l` } htmlsummary() { echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Current Directory is: "$PWD >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Total Files Processed in this Module: " >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $FILES_PROCESSED >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "This modules license structure is:" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "License" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "Percentage of files" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "Number of files" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Total GPL Only Code is" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $GPL_ONLY_SOURCE_PERCENT"%" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $GPL_ONLY_SOURCE_FILES >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Total GPL + jHeretic/jHexen Exception Code is" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $GPL_PLUS_EXCEPTION_SOURCE_PERCENT"%" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $GPL_PLUS_EXCEPTION_SOURCE_FILES >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Total Autogenerated Code is" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $AUTOGENERATED_SOURCE_PERCENT"%" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $AUTOGENERATED_SOURCE_FILES >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Combined GPL Compatible Total is" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $GPL_SOURCE_PERCENT"%" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $GPL_SOURCE_FILES >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Total Raven Licensed Code is" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $RAVEN_SOURCE_PERCENT"%" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $RAVEN_SOURCE_FILES >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "Total Unknown Licensed or Unaudited Code is" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $UNKNOWN_SOURCE_PERCENT"%" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo $UNKNOWN_SOURCE_FILES >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html } htmllist() { cat $TOP_LEVEL_DIR/code.html >> $TOP_LEVEL_DIR/index.html } auditall() { echo "


" >> $TOP_LEVEL_DIR/index.html echo "

Entire Project Audit Summary

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR findprojectfiles scanfiles calcpercent consoleout htmlsummary echo "
" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo "

The Doomsday Engine

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/engine findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

All Plugins Summary

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

jDoom plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/jdoom findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

jHeretic plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/jheretic findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

jHexen plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/jhexen findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

WolfTC plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/wolftc findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

Doom64TC plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/doom64tc findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

dehread plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/dehread findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

mapload plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/mapload findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

OpenGL plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/opengl findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

Direct3D plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/d3d findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

debugrenderer plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/debugrenderer findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

OpenAL plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/openal findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

sdlmixer plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/sdlmixer findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

DirectSound Plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/ds6 findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

a3d plugin

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/a3d findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist echo "
" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

Plugin Common files

" >> $TOP_LEVEL_DIR/index.html cd $TOP_LEVEL_DIR/plugins/common findfiles scanfiles calcpercent consoleout htmlsummary echo "Return to Table of Contents" >> $TOP_LEVEL_DIR/index.html htmllist } toc() { echo "
" >> $TOP_LEVEL_DIR/index.html echo "

Contents

" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html } echo "------------------------------------------------------------------------" echo "The script will recursively audit all source files starting in the" echo "current working directory. If it does not find it's magic strings it" echo "will classify the code as 'Autogenerated or Unknown Licensed Code'." echo "If you ARE NOT in the source directory you wish to audit" echo "You WILL get incorrect results." echo "------------------------------------------------------------------------" if [[ -e $TOP_LEVEL_DIR/index.html ]] then rm $TOP_LEVEL_DIR/index.html fi if [[ -e $TOP_LEVEL_DIR/code.html ]] then rm $TOP_LEVEL_DIR/code.html fi echo "" > $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo "The Doomsday Engine, Project Audit Summary" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html echo " " >> $TOP_LEVEL_DIR/index.html echo "

The Doomsday Engine, Project Audit Summary

" >> $TOP_LEVEL_DIR/index.html echo "

Last Updated `date`

" >> $TOP_LEVEL_DIR/index.html ## Check if in deng's top level directory. If so, audit all of deng, ## if not, then just the directory we are in if [[ -e $TOP_LEVEL_DIR/doxygen ]] then toc auditall else findfiles scanfiles calcpercent consoleout htmlsummary htmllist fi rm $TOP_LEVEL_DIR/filelist.txt rm $TOP_LEVEL_DIR/code.html echo "" >> $TOP_LEVEL_DIR/index.html echo "" >> $TOP_LEVEL_DIR/index.html deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/deng-header-style.sh0000755000175000017500000000144311357170242023663 0ustar keeskees#!/bin/sh . indent-typenames.sh indent --k-and-r-style \ -ts 4 \ --blank-lines-after-declarations \ --blank-lines-after-procedures \ --blank-lines-before-block-comments \ --no-blank-lines-after-commas \ --braces-on-struct-decl-line \ --braces-after-if-line \ --brace-indent0 \ --comment-indentation36 \ --declaration-comment-column36 \ --format-first-column-comments \ --comment-line-length79 \ --declaration-indentation16 \ --struct-brace-indentation0 \ -ppi 0 \ --indent-level4 \ --no-tabs \ --line-length79 \ --continue-at-parentheses \ --cuddle-do-while \ --dont-cuddle-else \ --space-after-cast \ --no-space-after-parentheses \ --no-space-after-if \ --no-space-after-while \ --no-space-after-for \ --ignore-newlines \ --swallow-optional-blank-lines \ $TYPENAMES \ $* deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/mass_replace.sh0000755000175000017500000000424511357170242023023 0ustar keeskees#!/bin/bash ################################################################################ # Copyright and License Summary # License: GPL # Online License Link: http://www.gnu.org/licenses/gpl.html # # Copyright © 2006-2008 Jamie Jones # # 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 St, Fifth Floor, # Boston, MA 02110-1301 USA ################################################################################ # # This script is used to do a mass replace # ################################################################################ FILES_PROCESSED=0 TOP_LEVEL_DIR=$PWD findprojectfiles() { find -name *.c | grep engine > $TOP_LEVEL_DIR/filelist.txt find -name *.c | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.cpp | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.cpp | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.h | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.h | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.m | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.m | grep plugins >> $TOP_LEVEL_DIR/filelist.txt FILE_LIST=`cat $TOP_LEVEL_DIR/filelist.txt` } scanfiles() { let FILES_PROCESSED=0 for CURRENT_FILE in $FILE_LIST ; do cat $CURRENT_FILE | sed s_"Copyright and License Summary"_"License"_g > $TOP_LEVEL_DIR/tmp.txt rm $CURRENT_FILE mv $TOP_LEVEL_DIR/tmp.txt $CURRENT_FILE let FILES_PROCESSED=FILES_PROCESSED+1 done } if [[ -e $TOP_LEVEL_DIR/doxygen ]] then findprojectfiles scanfiles fi rm $TOP_LEVEL_DIR/filelist.txt rm $TOP_LEVEL_DIR/tmp.txt deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/makedmt.py0000755000175000017500000001122211357170242022016 0ustar keeskees#!/usr/bin/python # Python script for generating Doomsday map data structs and definitions. import sys, string def error(line, cause): """Reports a parsing error.""" err = sys.stderr err.write("At input line \"%s\":\nProcessing aborted: %s\n" % (line.rstrip(), cause)) sys.exit(1) def add_comment(line, comment): """Appends a comment to a line of text. Appropriate number of padding whitespace is added to align comments.""" if comment == '': return line if len(line) < 39: line += ' ' * (39 - len(line)) else: line += ' ' return line + comment def println(f, line, comment=''): """Print a line of text. Comment will be added optionally.""" f.write(add_comment(line, comment) + "\n") # Type symbol to real C types mapping table. type_replacements = { 'uint': 'unsigned int', 'ushort': 'unsigned short' } current = None verbatim = None internal_header_filename = 'p_maptypes.h' public_header_filename = 'dd_maptypes.h' internal_file = file(internal_header_filename, 'w') public_file = file(public_header_filename, 'w') banner = "/* Generated by " + string.join(sys.argv, ' ') + " */\n\n" internal_file.write(banner) public_file.write(banner) # Begin writing to the internal header. internal_file.write("#ifndef __DOOMSDAY_PLAY_MAP_DATA_TYPES_H__\n") internal_file.write("#define __DOOMSDAY_PLAY_MAP_DATA_TYPES_H__\n\n") internal_file.write("#include \"p_mapdata.h\"\n\n") # Begin writing to the public header. public_file.write("#ifndef __DOOMSDAY_PLAY_PUBLIC_MAP_DATA_TYPES_H__\n") public_file.write("#define __DOOMSDAY_PLAY_PUBLIC_MAP_DATA_TYPES_H__\n\n") for input_line in sys.stdin.readlines(): line = input_line.strip() if verbatim: if line == 'end': println(verbatim, "") verbatim = None else: println(verbatim, input_line.rstrip()) continue # Skip empty lines and comments. if len(line) == 0 or line[0] == '#': continue # If there is a comment on the line, get rid of it. comment_stripped = line line_comment = '' if '//' in comment_stripped: index = comment_stripped.index('//') line_comment = comment_stripped[index:] comment_stripped = comment_stripped[:index] tokens = comment_stripped.split() count = len(tokens) if current is None: if count == 1: if tokens[0] == 'internal': verbatim = internal_file elif tokens[0] == 'public': verbatim = public_file elif count == 2 or count == 3: if tokens[0] == 'struct': current = tokens[1] if count == 3: publicName = tokens[2] else: publicName = tokens[1] println(internal_file, "typedef struct %s_s {" % current, line_comment) println(internal_file, " runtime_mapdata_header_t header;", '') else: error(input_line, 'syntax error') else: if count == 3: # Use "-" to omit the DDVT type declaration (internal usage only). if tokens[0] != '-': println(public_file, "#define DMT_%s_%s DDVT_%s" % (publicName.upper(), tokens[2].upper(), tokens[0].upper()), line_comment) # Determine the C type. c_type = tokens[1] indexed = '' if '[' in c_type: pos = c_type.index('[') indexed = c_type[pos:] c_type = c_type[:pos] # Translate the type into a real C type. if '_s' in c_type: c_type = 'struct ' + c_type for symbol, real in type_replacements.items(): c_type = c_type.replace(symbol, real) # Add some visual padding to align the members. padding = 24 - len(c_type) - 4 if padding < 1: padding = 1 println(internal_file, " %s%s%s%s;" % (c_type, ' '*padding, tokens[2], indexed), line_comment) elif count == 1: if tokens[0] == 'end': println(internal_file, "} %s_t;\n" % current, line_comment) println(public_file, "", line_comment) current = None else: error(input_line, 'syntax error') else: error(input_line, "unknown definition in struct %s" % current) # End the header files. internal_file.write("#endif\n") public_file.write("#endif\n") deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/definefinder.sh0000755000175000017500000000424511357170242023007 0ustar keeskees#!/bin/bash ################################################################################ # Copyright and License Summary # License: GPL # Online License Link: http://www.gnu.org/licenses/gpl.html # # Copyright © 2006-2008 Jamie Jones # # 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 St, Fifth Floor, # Boston, MA 02110-1301 USA ################################################################################ # # This script is used to do a find all "Defines" in The Doomsday Engine sources. # ################################################################################ FILES_PROCESSED=0 TOP_LEVEL_DIR=$PWD findprojectfiles() { find -name *.c | grep engine > $TOP_LEVEL_DIR/filelist.txt find -name *.c | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.cpp | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.cpp | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.h | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.h | grep plugins >> $TOP_LEVEL_DIR/filelist.txt find -name *.m | grep engine >> $TOP_LEVEL_DIR/filelist.txt find -name *.m | grep plugins >> $TOP_LEVEL_DIR/filelist.txt FILE_LIST=`cat $TOP_LEVEL_DIR/filelist.txt` } scanfiles() { let FILES_PROCESSED=0 for CURRENT_FILE in $FILE_LIST ; do # echo $CURRENT_FILE grep '#if' $CURRENT_FILE grep '#define' $CURRENT_FILE grep '#elif' $CURRENT_FILE grep '#else' $CURRENT_FILE let FILES_PROCESSED=FILES_PROCESSED+1 done } if [[ -e $TOP_LEVEL_DIR/doxygen ]] then findprojectfiles scanfiles fi rm $TOP_LEVEL_DIR/filelist.txt deng-1.9.0-beta6.9+dfsg1/doomsday/engine/scripts/indent-typenames.sh0000644000175000017500000000105411357170242023641 0ustar keeskees#!/bin/sh TYPENAMES="-T DFILE -T fixed_t -T boolean -T binangle_t -T angle_t -T byte -T uint -T ushort -T event_t -T ccmd_t -T cvar_t -T ddfont_t -T action_t -T mobj_s -T mobj_t -T sector_t -T subsector_t -T line_t -T vertex_t -T seg_t -T thinker_t -T ddplayer_t -T spriteinfo_t -T rendpoly_t -T shadowpoly_t -T planeinfo_t -T dynlight_t -T sectorinfo_t -T sendqueue_t -T IPaddress -T UDPsocket -T TCPsocket -T ui_object_t -T serverinfo_t -T texture_t -T patch_t -T player_t -T mousestate_t -T keyevent_t -T clmobj_t -T fipic_t -T ticcmd_t -T rendlist_t" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/0000755000175000017500000000000011357170242016546 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/0000755000175000017500000000000011523516204021744 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/res/0000755000175000017500000000000011523516204022535 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/res/wadmapconverter.rc0000644000175000017500000001013311357170242026265 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * wadmapconverter.rc: dpWadMapConveter.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""dpwadmapconverter.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION PLUGIN_VERSION_NUMBER\r\n" "PRODUCTVERSION PLUGIN_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine map converter plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dpWadMapConverter.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION PLUGIN_VERSION_NUMBER PRODUCTVERSION PLUGIN_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine map converter plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "dpWadMapConverter.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/res/dpwadmapconverter.dll.manifest0000644000175000017500000000062311357170242030570 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/res/resource.h0000644000175000017500000000062311357170242024541 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by wadmapconverter.rc // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/doc/0000755000175000017500000000000011523516204022511 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/doc/LICENSE0000644000175000017500000003545111357170242023531 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/src/0000755000175000017500000000000011357170242022536 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/src/wadmapconverter.c0000644000175000017500000000757111357170242026115 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * wadmapconverter.c: Doomsday Plugin for converting DOOM-like format maps. * * The purpose of a wadmapconverter plugin is to transform a map into * Doomsday's native map format by use of the public map editing interface. */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #include "doomsday.h" #include "dd_api.h" #include "wadmapconverter.h" #include #include #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static int ConvertMapHook(int hookType, int parm, void *data); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- map_t theMap, *map = &theMap; boolean verbose; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ void DP_Initialize(void) { Plug_AddHook(HOOK_MAP_CONVERT, ConvertMapHook); } #ifdef WIN32 /** * Windows calls this when the DLL is loaded. */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch(fdwReason) { case DLL_PROCESS_ATTACH: // Register our hooks. DP_Initialize(); break; default: break; } return TRUE; } #endif /** * This function is called when Doomsday is asked to load a map that is not * presently available in its native map format. * * Our job is to read in the map data structures then use the Doomsday map * editing interface to recreate the map in native format. */ int ConvertMapHook(int hookType, int param, void *data) { int *lumpList = (int*) data; verbose = ArgExists("-verbose"); Con_Message("WadMapConverter::Convert: Attempting map conversion...\n"); memset(map, 0, sizeof(*map)); if(!IsSupportedFormat(lumpList, param)) { Con_Message("WadMapConverter::Convert: Unknown map format, aborting.\n"); return false; // Cannot convert. } // A supported format. Con_Message("WadMapConverter::Convert: %s map format.\n", (map->format == MF_DOOM64? "DOOM64" : map->format == MF_HEXEN? "Hexen" : "DOOM")); // Load it in. if(!LoadMap(lumpList, param)) { Con_Message("WadMapConverter::Convert: Internal error, load failed.\n"); return false; // Something went horribly wrong... } AnalyzeMap(); return TransferMap(); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/src/load.c0000644000175000017500000016317511357170242023636 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * load.c: Load and analyzation of the map data structures. */ // HEADER FILES ------------------------------------------------------------ #include "doomsday.h" #include "dd_api.h" #include "wadmapconverter.h" #include #include #include // MACROS ------------------------------------------------------------------ // Size of the map data structures in bytes in the arrived WAD format. #define SIZEOF_64VERTEX (4 * 2) #define SIZEOF_VERTEX (2 * 2) #define SIZEOF_64THING (2 * 7) #define SIZEOF_XTHING (2 * 7 + 1 * 6) #define SIZEOF_THING (2 * 5) #define SIZEOF_XLINEDEF (2 * 5 + 1 * 6) #define SIZEOF_64LINEDEF (2 * 6 + 1 * 4) #define SIZEOF_LINEDEF (2 * 7) #define SIZEOF_64SIDEDEF (2 * 6) #define SIZEOF_SIDEDEF (2 * 3 + 8 * 3) #define SIZEOF_64SECTOR (2 * 12) #define SIZEOF_SECTOR (2 * 5 + 8 * 2) #define SIZEOF_LIGHT (1 * 6) #define PO_LINE_START (1) // polyobj line start special #define PO_LINE_EXPLICIT (5) #define PO_ANCHOR_DOOMEDNUM (3000) #define PO_SPAWN_DOOMEDNUM (3001) #define PO_SPAWNCRUSH_DOOMEDNUM (3002) #define SEQTYPE_NUMSEQ (10) // TYPES ------------------------------------------------------------------- typedef enum lumptype_e { ML_INVALID = -1, FIRST_LUMP_TYPE, ML_LABEL = FIRST_LUMP_TYPE, // A separator, name, ExMx or MAPxx ML_THINGS, // Monsters, items.. ML_LINEDEFS, // LineDefs, from editing ML_SIDEDEFS, // SideDefs, from editing ML_VERTEXES, // Vertices, edited and BSP splits generated ML_SEGS, // LineSegs, from LineDefs split by BSP ML_SSECTORS, // SubSectors, list of LineSegs ML_NODES, // BSP nodes ML_SECTORS, // Sectors, from editing ML_REJECT, // LUT, sector-sector visibility ML_BLOCKMAP, // LUT, motion clipping, walls/grid element ML_BEHAVIOR, // ACS Scripts (compiled). ML_SCRIPTS, // ACS Scripts (source). ML_LIGHTS, // Surface color tints. ML_MACROS, // DOOM64 format, macro scripts. ML_LEAFS, // DOOM64 format, segs (close subsectors). ML_GLVERT, // GL vertexes ML_GLSEGS, // GL segs ML_GLSSECT, // GL subsectors ML_GLNODES, // GL nodes ML_GLPVS, // GL PVS dataset NUM_LUMP_TYPES } lumptype_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static uint PolyLineCount; static int16_t PolyStart[2]; static uint validCount = 0; // Used for Polyobj LineDef collection. // CODE -------------------------------------------------------------------- static int C_DECL compareMaterialNames(const void* a, const void* b) { return stricmp((*(materialref_t**)a)->name, (*(materialref_t**)b)->name); } static const materialref_t* getMaterial(const char* regName, materialref_t* const ** list, size_t size) { int result; size_t bottomIdx, topIdx, pivot; const materialref_t* m; boolean isDone; char name[9]; if(size == 0) return NULL; if(map->format == MF_DOOM64) { int idx = *((int*) regName); sprintf(name, "UNK%05i", idx); name[8] = '\0'; } else { strncpy(name, regName, 8); name[8] = '\0'; } bottomIdx = 0; topIdx = size-1; m = NULL; isDone = false; while(bottomIdx <= topIdx && !isDone) { pivot = bottomIdx + (topIdx - bottomIdx)/2; result = stricmp((*list)[pivot]->name, name); if(result == 0) { // Found. m = (*list)[pivot]; isDone = true; } else { if(result > 0) { if(pivot == 0) { // Not present. isDone = true; } else topIdx = pivot - 1; } else bottomIdx = pivot + 1; } } return m; } const materialref_t* GetMaterial(const char* name, boolean isFlat) { return getMaterial(name, isFlat? &map->flats : &map->textures, isFlat? map->numFlats : map->numTextures); } static void addMaterialToList(materialref_t* m, materialref_t*** list, size_t* size) { size_t i, n; // Enlarge the list. (*list) = realloc((*list), sizeof(m) * ++(*size)); // Find insertion point. n = 0; for(i = 0; i < (*size) - 1; ++i) if(compareMaterialNames(&(*list)[i], &m) > 0) { n = i; break; } // Shift the rest over. if((*size) > 1) memmove(&(*list)[n+1], &(*list)[n], sizeof(m) * ((*size)-1-n)); // Insert the new element. (*list)[n] = m; } const materialref_t* RegisterMaterial(const char* name, boolean isFlat) { const materialref_t* m; // Check if this material has already been registered. if((m = GetMaterial(name, isFlat)) != NULL) { return m; // Already registered. } else { materialref_t* m; /** * A new material. */ m = malloc(sizeof(*m)); if(map->format == MF_DOOM64) { int idx = *((int*) name); sprintf(m->name, "UNK%05i", idx); m->name[8] = '\0'; // First try the prefered namespace, then any. if(!(m->num = P_MaterialCheckNumForIndex(idx, (isFlat? MN_FLATS : MN_TEXTURES)))) m->num = P_MaterialCheckNumForIndex(idx, MN_ANY); } else { memcpy(m->name, name, 8); m->name[8] = '\0'; // First try the prefered namespace, then any. if(!(m->num = P_MaterialCheckNumForName(m->name, (isFlat? MN_FLATS : MN_TEXTURES)))) m->num = P_MaterialCheckNumForName(m->name, MN_ANY); } // Add it to the list of known materials. addMaterialToList(m, isFlat? &map->flats : &map->textures, isFlat? &map->numFlats : &map->numTextures); return m; } } /** * Attempts to load the BLOCKMAP data resource. * * If the map is too large (would overflow the size limit of * the BLOCKMAP lump in a WAD therefore it will have been truncated), * it's zero length or we are forcing a rebuild - we'll have to * generate the blockmap data ourselves. */ #if 0 // Needs updating. static boolean loadBlockmap(tempmap_t *map, maplumpinfo_t *maplump) { #define MAPBLOCKUNITS 128 boolean generateBMap = (createBMap == 2)? true : false; Con_Message("WadMapConverter::loadBlockmap: Processing...\n"); // Do we have a lump to process? if(maplump->lumpNum == -1 || maplump->length == 0) generateBMap = true; // We'll HAVE to generate it. // Are we generating new blockmap data? if(generateBMap) { // Only announce if the user has choosen to always generate // new data (we will have already announced it if the lump // was missing). if(maplump->lumpNum != -1) VERBOSE( Con_Message("loadBlockMap: Generating NEW blockmap...\n")); } else { // No, the existing data is valid - so load it in. uint startTime; blockmap_t *blockmap; uint x, y, width, height; float v[2]; vec2_t bounds[2]; long *lineListOffsets, i, n, numBlocks, blockIdx; short *blockmapLump; VERBOSE( Con_Message("loadBlockMap: Converting existing blockmap...\n")); startTime = Sys_GetRealTime(); blockmapLump = (short *) W_CacheLumpNum(maplump->lumpNum, PU_STATIC); v[VX] = (float) SHORT(blockmapLump[0]); v[VY] = (float) SHORT(blockmapLump[1]); width = ((SHORT(blockmapLump[2])) & 0xffff); height = ((SHORT(blockmapLump[3])) & 0xffff); numBlocks = (long) width * (long) height; /** * Expand WAD blockmap into a larger one, by treating all * offsets except -1 as unsigned and zero-extending them. * This potentially doubles the size of blockmaps allowed * because DOOM originally considered the offsets as always * signed. */ lineListOffsets = M_Malloc(sizeof(long) * numBlocks); n = 4; for(i = 0; i < numBlocks; ++i) { short t = SHORT(blockmapLump[n++]); lineListOffsets[i] = (t == -1? -1 : (long) t & 0xffff); } /** * Finally, convert the blockmap into our internal representation. * We'll ensure the blockmap is formed correctly as we go. * * \todo We could gracefully handle malformed blockmaps by * by cleaning up and then generating our own. */ V2_Set(bounds[0], v[VX], v[VY]); v[VX] += (float) (width * MAPBLOCKUNITS); v[VY] += (float) (height * MAPBLOCKUNITS); V2_Set(bounds[1], v[VX], v[VY]); blockmap = P_BlockmapCreate(bounds[0], bounds[1], width, height); blockIdx = 0; for(y = 0; y < height; ++y) for(x = 0; x < width; ++x) { long offset = lineListOffsets[blockIdx]; long idx; uint count; #if _DEBUG if(SHORT(blockmapLump[offset]) != 0) { Con_Error("loadBlockMap: Offset (%li) for block %u [%u, %u] " "does not index the beginning of a line list!\n", offset, blockIdx, x, y); } #endif // Count the number of lines in this block. count = 0; while((idx = SHORT(blockmapLump[offset + 1 + count])) != -1) count++; if(count > 0) { linedef_t **lines, **ptr; // A NULL-terminated array of pointers to lines. lines = Z_Malloc((count + 1) * sizeof(linedef_t *), PU_MAPSTATIC, NULL); // Copy pointers to the array, delete the nodes. ptr = lines; count = 0; while((idx = SHORT(blockmapLump[offset + 1 + count])) != -1) { #if _DEBUG if(idx < 0 || idx >= (long) map->numLines) { Con_Error("loadBlockMap: Invalid linedef id %li\n!", idx); } #endif *ptr++ = &map->lines[idx]; count++; } // Terminate. *ptr = NULL; // Link it into the BlockMap. P_BlockmapSetBlock(blockmap, x, y, lines, NULL); } blockIdx++; } // Don't need this anymore. M_Free(lineListOffsets); map->blockMap = blockmap; // How much time did we spend? VERBOSE(Con_Message ("loadBlockMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); } return true; #undef MAPBLOCKUNITS } #endif #if 0 /** * The REJECT resource is a LUT that provides the results of trivial * line-of-sight tests between sectors. This is done with a matrix of sector * pairs i.e. if a monster in sector 4 can see the player in sector 2; the * inverse should be true. * * Note however, some PWADS have carefully constructed REJECT data to create * special effects. For example it is possible to make a player completely * invissible in certain sectors. * * The format of the table is a simple matrix of boolean values, a (true) * value indicates that it is impossible for mobjs in sector A to see mobjs * in sector B (and vice-versa). A (false) value indicates that a * line-of-sight MIGHT be possible and a more accurate (thus more expensive) * calculation will have to be made. * * The table itself is constructed as follows: * * X = sector num player is in * Y = sector num monster is in * * X * * 0 1 2 3 4 -> * 0 1 - 1 - - * Y 1 - - 1 - - * 2 1 1 - - 1 * 3 - - - 1 - * \|/ * * These results are read left-to-right, top-to-bottom and are packed into * bytes (each byte represents eight results). As are all lumps in WAD the * data is in little-endian order. * * Thus the size of a valid REJECT lump can be calculated as: * * ceiling(numSectors^2) * * For now we only do very basic reject processing, limited to determining * all isolated sector groups (islands that are surrounded by void space). * * \note Algorithm: * Initially all sectors are in individual groups. Next, we scan the linedef * list. For each 2-sectored line, merge the two sector groups into one. */ static void buildReject(gamemap_t *map) { /** * \todo We can do something much better now that we are building the BSP. */ int i; int group; int *secGroups; int view, target; size_t rejectSize; byte *matrix; secGroups = M_Malloc(sizeof(int) * numSectors); for(i = 0; i < numSectors; ++i) { sector_t *sec = LookupSector(i); secGroups[i] = group++; sec->rejNext = sec->rejPrev = sec; } for(i = 0; i < numLinedefs; ++i) { linedef_t *line = LookupLinedef(i); sector_t *sec1, *sec2, *p; if(!line->sideDefs[FRONT] || !line->sideDefs[BACK]) continue; sec1 = line->sideDefs[FRONT]->sector; sec2 = line->sideDefs[BACK]->sector; if(!sec1 || !sec2 || sec1 == sec2) continue; // Already in the same group? if(secGroups[sec1->index] == secGroups[sec2->index]) continue; // Swap sectors so that the smallest group is added to the biggest // group. This is based on the assumption that sector numbers in // wads will generally increase over the set of linedefs, and so // (by swapping) we'll tend to add small groups into larger // groups, thereby minimising the updates to 'rej_group' fields // that is required when merging. if(secGroups[sec1->index] > secGroups[sec2->index]) { p = sec1; sec1 = sec2; sec2 = p; } // Update the group numbers in the second group secGroups[sec2->index] = secGroups[sec1->index]; for(p = sec2->rejNext; p != sec2; p = p->rejNext) secGroups[p->index] = secGroups[sec1->index]; // Merge 'em baby... sec1->rejNext->rejPrev = sec2; sec2->rejNext->rejPrev = sec1; p = sec1->rejNext; sec1->rejNext = sec2->rejNext; sec2->rejNext = p; } rejectSize = (numSectors * numSectors + 7) / 8; matrix = Z_Calloc(rejectSize, PU_MAPSTATIC, 0); for(view = 0; view < numSectors; ++view) for(target = 0; target < view; ++target) { int p1, p2; if(secGroups[view] == secGroups[target]) continue; // For symmetry, do two bits at a time. p1 = view * numSectors + target; p2 = target * numSectors + view; matrix[p1 >> 3] |= (1 << (p1 & 7)); matrix[p2 >> 3] |= (1 << (p2 & 7)); } M_Free(secGroups); } #endif int DataTypeForLumpName(const char* name) { struct lumptype_s { lumptype_t type; const char* name; } knownLumps[] = { {ML_LABEL, "*"}, {ML_THINGS, "THINGS"}, {ML_LINEDEFS, "LINEDEFS"}, {ML_SIDEDEFS, "SIDEDEFS"}, {ML_VERTEXES, "VERTEXES"}, {ML_SEGS, "SEGS"}, {ML_SSECTORS, "SSECTORS"}, {ML_NODES, "NODES"}, {ML_SECTORS, "SECTORS"}, {ML_REJECT, "REJECT"}, {ML_BLOCKMAP, "BLOCKMAP"}, {ML_BEHAVIOR, "BEHAVIOR"}, {ML_SCRIPTS, "SCRIPTS"}, {ML_LIGHTS, "LIGHTS"}, {ML_MACROS, "MACROS"}, {ML_LEAFS, "LEAFS"}, {ML_GLVERT, "GL_VERT"}, {ML_GLSEGS, "GL_SEGS"}, {ML_GLSSECT, "GL_SSECT"}, {ML_GLNODES, "GL_NODES"}, {ML_GLPVS, "GL_PVS"}, {ML_INVALID, NULL}, }; lumptype_t i; if(name && name[0]) { for(i = FIRST_LUMP_TYPE; knownLumps[i].type != ML_INVALID; ++i) { if(!strncmp(knownLumps[i].name, name, 8)) return knownLumps[i].type; } } return ML_INVALID; } /** * Create a temporary polyobj (read from the original map data). */ static boolean createPolyobj(mline_t **lineList, uint num, uint *poIdx, int tag, int sequenceType, int16_t anchorX, int16_t anchorY) { uint i; mpolyobj_t *po, **newList; if(!lineList || num == 0) return false; // Allocate the new polyobj. po = calloc(1, sizeof(*po)); /** * Link the new polyobj into the global list. */ newList = malloc(((++map->numPolyobjs) + 1) * sizeof(mpolyobj_t*)); // Copy the existing list. for(i = 0; i < map->numPolyobjs - 1; ++i) { newList[i] = map->polyobjs[i]; } newList[i++] = po; // Add the new polyobj. newList[i] = NULL; // Terminate. if(map->numPolyobjs-1 > 0) free(map->polyobjs); map->polyobjs = newList; po->idx = map->numPolyobjs-1; po->tag = tag; po->seqType = sequenceType; po->anchor[VX] = anchorX; po->anchor[VY] = anchorY; po->lineCount = num; po->lineIndices = malloc(sizeof(uint) * num); for(i = 0; i < num; ++i) { mline_t* line = lineList[i]; line->aFlags |= LAF_POLYOBJ; po->lineIndices[i] = line - map->lines; } if(poIdx) *poIdx = po->idx; return true; // Success! } /** * @param lineList @c NULL, will cause IterFindPolyLines to count * the number of lines in the polyobj. */ static void iterFindPolyLines(int16_t x, int16_t y, mline_t** lineList) { uint i; for(i = 0; i < map->numLines; ++i) { mline_t* line = &map->lines[i]; int16_t v1[2], v2[2]; if(line->aFlags & LAF_POLYOBJ) continue; if(line->validCount == validCount) continue; v1[VX] = (int16_t) map->vertexes[(line->v[0] - 1) * 2]; v1[VY] = (int16_t) map->vertexes[(line->v[0] - 1) * 2 + 1]; v2[VX] = (int16_t) map->vertexes[(line->v[1] - 1) * 2]; v2[VY] = (int16_t) map->vertexes[(line->v[1] - 1) * 2 + 1]; if(v1[VX] == x && v1[VY] == y) { line->validCount = validCount; if(!lineList) PolyLineCount++; else *lineList++ = line; iterFindPolyLines(v2[VX], v2[VY], lineList); } } } /** * @todo This terribly inefficent (naive) algorithm may need replacing * (it is far outside an exceptable polynominal range!). */ static mline_t** collectPolyobjLineDefs(mline_t* lineDef, uint* num) { mline_t** lineList; int16_t v1[2], v2[2]; lineDef->xType = 0; lineDef->xArgs[0] = 0; v1[VX] = (int16_t) map->vertexes[(lineDef->v[0]-1) * 2]; v1[VY] = (int16_t) map->vertexes[(lineDef->v[0]-1) * 2 + 1]; v2[VX] = (int16_t) map->vertexes[(lineDef->v[1]-1) * 2]; v2[VY] = (int16_t) map->vertexes[(lineDef->v[1]-1) * 2 + 1]; PolyStart[VX] = v1[VX]; PolyStart[VY] = v1[VY]; PolyLineCount = 1; validCount++; lineDef->validCount = validCount; iterFindPolyLines(v2[VX], v2[VY], NULL); lineList = malloc((PolyLineCount+1) * sizeof(mline_t*)); lineList[0] = lineDef; // Insert the first line. validCount++; lineDef->validCount = validCount; iterFindPolyLines(v2[VX], v2[VY], lineList + 1); lineList[PolyLineCount] = 0; // Terminate. *num = PolyLineCount; return lineList; } /** * Find all linedefs marked as belonging to a polyobject with the given tag * and attempt to create a polyobject from them. * * @param tag Line tag of linedefs to search for. * * @return @c true = successfully created polyobj. */ static boolean findAndCreatePolyobj(int16_t tag, int16_t anchorX, int16_t anchorY) { #define MAXPOLYLINES 32 uint i; for(i = 0; i < map->numLines; ++i) { mline_t* line = &map->lines[i]; if(line->aFlags & LAF_POLYOBJ) continue; if(!(line->xType == PO_LINE_START && line->xArgs[0] == tag)) continue; {mline_t** lineList; uint num; if((lineList = collectPolyobjLineDefs(line, &num))) { uint poIdx; byte seqType; boolean result; seqType = line->xArgs[2]; if(seqType >= SEQTYPE_NUMSEQ) seqType = 0; result = createPolyobj(lineList, num, &poIdx, tag, seqType, anchorX, anchorY); free(lineList); if(result) return true; }} } /** * Didn't find a polyobj through PO_LINE_START. * We'll try another approach... */ { mline_t *polyLineList[MAXPOLYLINES]; uint lineCount = 0; uint j, psIndex, psIndexOld; psIndex = 0; for(j = 1; j < MAXPOLYLINES; ++j) { psIndexOld = psIndex; for(i = 0; i < map->numLines; ++i) { mline_t *line = &map->lines[i]; if(line->aFlags & LAF_POLYOBJ) continue; if(line->xType == PO_LINE_EXPLICIT && line->xArgs[0] == tag) { if(!line->xArgs[1]) { Con_Error ("WadMapConverter::findAndCreatePolyobj: Explicit line missing order number " "(probably %d) in poly %d.\n", j + 1, tag); } if(line->xArgs[1] == j) { // Add this line to the list. polyLineList[psIndex] = line; lineCount++; psIndex++; if(psIndex > MAXPOLYLINES) { Con_Error ("WadMapConverter::findAndCreatePolyobj: psIndex > MAXPOLYLINES\n"); } // Clear out any special. line->xType = 0; line->xArgs[0] = 0; line->aFlags |= LAF_POLYOBJ; } } } if(psIndex == psIndexOld) { // Check if an explicit line order has been skipped // A line has been skipped if there are any more explicit // lines with the current tag value for(i = 0; i < map->numLines; ++i) { mline_t *line = &map->lines[i]; if(line->xType == PO_LINE_EXPLICIT && line->xArgs[0] == tag) { Con_Error ("WadMapConverter::findAndCreatePolyobj: Missing explicit line %d for poly %d\n", j, tag); } } } } if(lineCount) { uint poIdx; int seqType = polyLineList[0]->xArgs[3]; if(createPolyobj(polyLineList, lineCount, &poIdx, tag, seqType, anchorX, anchorY)) { mline_t *line = polyLineList[0]; // Next, change the polyobjs first line to point to a mirror // if it exists. line->xArgs[1] = line->xArgs[2]; return true; } } } return false; #undef MAXPOLYLINES } static void findPolyobjs(void) { uint i; VERBOSE(Con_Message("WadMapConverter::findPolyobjs: Processing...\n")); for(i = 0; i < map->numThings; ++i) { mthing_t *thing = &map->things[i]; if(thing->doomEdNum == PO_ANCHOR_DOOMEDNUM) { // A polyobj anchor. int tag = thing->angle; findAndCreatePolyobj(tag, thing->pos[VX], thing->pos[VY]); } } } void AnalyzeMap(void) { if(map->format == MF_HEXEN) findPolyobjs(); } boolean IsSupportedFormat(const int *lumpList, int numLumps) { int i; boolean supported = false; // Lets first check for format specific lumps, as their prescense // determines the format of the map data. Assume DOOM format by default. map->format = MF_DOOM; for(i = 0; i < numLumps; ++i) { const char* lumpName = W_LumpName(lumpList[i]); if(!lumpName || !lumpName[0]) continue; if(!strncmp(lumpName, "BEHAVIOR", 8)) { map->format = MF_HEXEN; break; } if(!strncmp(lumpName, "MACROS", 6) || !strncmp(lumpName, "LIGHTS", 6) || !strncmp(lumpName, "LEAFS", 5)) { map->format = MF_DOOM64; break; } } for(i = 0; i < numLumps; ++i) { uint* ptr; size_t elmSize = 0; // Num of bytes. const char* lumpName = W_LumpName(lumpList[i]); // Determine the number of map data objects of each data type. ptr = NULL; switch(DataTypeForLumpName(lumpName)) { case ML_VERTEXES: ptr = &map->numVertexes; elmSize = (map->format == MF_DOOM64? SIZEOF_64VERTEX : SIZEOF_VERTEX); break; case ML_THINGS: ptr = &map->numThings; elmSize = (map->format == MF_DOOM64? SIZEOF_64THING : map->format == MF_HEXEN? SIZEOF_XTHING : SIZEOF_THING); break; case ML_LINEDEFS: ptr = &map->numLines; elmSize = (map->format == MF_DOOM64? SIZEOF_64LINEDEF : map->format == MF_HEXEN? SIZEOF_XLINEDEF : SIZEOF_LINEDEF); break; case ML_SIDEDEFS: ptr = &map->numSides; elmSize = (map->format == MF_DOOM64? SIZEOF_64SIDEDEF : SIZEOF_SIDEDEF); break; case ML_SECTORS: ptr = &map->numSectors; elmSize = (map->format == MF_DOOM64? SIZEOF_64SECTOR : SIZEOF_SECTOR); break; case ML_LIGHTS: ptr = &map->numLights; elmSize = SIZEOF_LIGHT; break; default: break; } if(ptr) { size_t lumpLength = W_LumpLength(lumpList[i]); if(0 != lumpLength % elmSize) return false; // What is this?? *ptr += lumpLength / elmSize; } } if(map->numVertexes > 0 && map->numLines > 0 && map->numSides > 0 && map->numSectors > 0 && map->numThings > 0) { supported = true; } return supported; } static void freeMapData(void) { if(map->vertexes) free(map->vertexes); map->vertexes = NULL; if(map->lines) free(map->lines); map->lines = NULL; if(map->sides) free(map->sides); map->sides = NULL; if(map->sectors) free(map->sectors); map->sectors = NULL; if(map->things) free(map->things); map->things = NULL; if(map->polyobjs) { uint i; for(i = 0; i < map->numPolyobjs; ++i) { mpolyobj_t* po = map->polyobjs[i]; free(po->lineIndices); free(po); } free(map->polyobjs); } map->polyobjs = NULL; if(map->lights) free(map->lights); map->lights = NULL; /*if(map->macros) free(map->macros); map->macros = NULL;*/ if(map->textures) { size_t i; for(i = 0; i < map->numTextures; ++i) { materialref_t* m = map->textures[i]; free(m); } free(map->textures); } map->textures = NULL; if(map->flats) { size_t i; for(i = 0; i < map->numFlats; ++i) { materialref_t* m = map->flats[i]; free(m); } free(map->flats); } map->flats = NULL; } static boolean loadVertexes(const byte* buf, size_t len) { uint num, n; size_t elmSize; const byte* ptr; VERBOSE(Con_Message("WadMapConverter::loadVertexes: Processing...\n")); elmSize = (map->format == MF_DOOM64? SIZEOF_64VERTEX : SIZEOF_VERTEX); num = len / elmSize; switch(map->format) { default: case MF_DOOM: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { map->vertexes[n * 2] = (float) SHORT(*((const int16_t*) (ptr))); map->vertexes[n * 2 + 1] = (float) SHORT(*((const int16_t*) (ptr+2))); } break; case MF_DOOM64: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { map->vertexes[n * 2] = FIX2FLT(LONG(*((const int32_t*) (ptr)))); map->vertexes[n * 2 + 1] = FIX2FLT(LONG(*((const int32_t*) (ptr+4)))); } break; } return true; } static boolean loadLinedefs(const byte* buf, size_t len) { uint num, n; size_t elmSize; const byte* ptr; VERBOSE(Con_Message("WadMapConverter::loadLinedefs: Processing...\n")); elmSize = (map->format == MF_DOOM64? SIZEOF_64LINEDEF : map->format == MF_HEXEN? SIZEOF_XLINEDEF : SIZEOF_LINEDEF); num = len / elmSize; switch(map->format) { default: case MF_DOOM: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { int idx; mline_t* l = &map->lines[n]; idx = USHORT(*((const uint16_t*) (ptr))); if(idx == 0xFFFF) l->v[0] = 0; else l->v[0] = idx + 1; idx = USHORT(*((const uint16_t*) (ptr+2))); if(idx == 0xFFFF) l->v[1] = 0; else l->v[1] = idx + 1; l->flags = SHORT(*((const int16_t*) (ptr+4))); l->dType = SHORT(*((const int16_t*) (ptr+6))); l->dTag = SHORT(*((const int16_t*) (ptr+8))); idx = USHORT(*((const uint16_t*) (ptr+10))); if(idx == 0xFFFF) l->sides[RIGHT] = 0; else l->sides[RIGHT] = idx + 1; idx = USHORT(*((const uint16_t*) (ptr+12))); if(idx == 0xFFFF) l->sides[LEFT] = 0; else l->sides[LEFT] = idx + 1; l->aFlags = 0; l->validCount = 0; } break; case MF_DOOM64: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { int idx; mline_t* l = &map->lines[n]; idx = USHORT(*((const uint16_t*) (ptr))); if(idx == 0xFFFF) l->v[0] = 0; else l->v[0] = idx + 1; idx = USHORT(*((const uint16_t*) (ptr+2))); if(idx == 0xFFFF) l->v[1] = 0; else l->v[1] = idx + 1; l->flags = USHORT(*((const uint16_t*) (ptr+4))); l->d64drawFlags = *((const byte*) (ptr + 6)); l->d64texFlags = *((const byte*) (ptr + 7)); l->d64type = *((const byte*) (ptr + 8)); l->d64useType = *((const byte*) (ptr + 9)); l->d64tag = SHORT(*((const int16_t*) (ptr+10))); idx = USHORT(*((const uint16_t*) (ptr+12))); if(idx == 0xFFFF) l->sides[RIGHT] = 0; else l->sides[RIGHT] = idx + 1; idx = USHORT(*((const uint16_t*) (ptr+14))); if(idx == 0xFFFF) l->sides[LEFT] = 0; else l->sides[LEFT] = idx + 1; l->aFlags = 0; l->validCount = 0; } break; case MF_HEXEN: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { int idx; mline_t* l = &map->lines[n]; idx = USHORT(*((const uint16_t*) (ptr))); if(idx == 0xFFFF) l->v[0] = 0; else l->v[0] = idx + 1; idx = USHORT(*((const uint16_t*) (ptr+2))); if(idx == 0xFFFF) l->v[1] = 0; else l->v[1] = idx + 1; l->flags = SHORT(*((const int16_t*) (ptr+4))); l->xType = *((const byte*) (ptr+6)); l->xArgs[0] = *((const byte*) (ptr+7)); l->xArgs[1] = *((const byte*) (ptr+8)); l->xArgs[2] = *((const byte*) (ptr+9)); l->xArgs[3] = *((const byte*) (ptr+10)); l->xArgs[4] = *((const byte*) (ptr+11)); idx = USHORT(*((const uint16_t*) (ptr+12))); if(idx == 0xFFFF) l->sides[RIGHT] = 0; else l->sides[RIGHT] = idx + 1; idx = USHORT(*((const uint16_t*) (ptr+14))); if(idx == 0xFFFF) l->sides[LEFT] = 0; else l->sides[LEFT] = idx + 1; l->aFlags = 0; l->validCount = 0; } break; } return true; } static boolean loadSidedefs(const byte* buf, size_t len) { uint num, n; size_t elmSize; const byte* ptr; VERBOSE(Con_Message("WadMapConverter::loadSidedefs: Processing...\n")); elmSize = (map->format == MF_DOOM64? SIZEOF_64SIDEDEF : SIZEOF_SIDEDEF); num = len / elmSize; switch(map->format) { default: case MF_DOOM: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { int idx; char name[9]; mside_t* s = &map->sides[n]; s->offset[VX] = SHORT(*((const int16_t*) (ptr))); s->offset[VY] = SHORT(*((const int16_t*) (ptr+2))); memcpy(name, ptr+4, 8); name[8] = '\0'; s->topMaterial = RegisterMaterial(name, false); memcpy(name, ptr+12, 8); name[8] = '\0'; s->bottomMaterial = RegisterMaterial(name, false); memcpy(name, ptr+20, 8); name[8] = '\0'; s->middleMaterial = RegisterMaterial(name, false); idx = USHORT(*((const uint16_t*) (ptr+28))); if(idx == 0xFFFF) s->sector = 0; else s->sector = idx + 1; } break; case MF_DOOM64: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { int idx; mside_t* s = &map->sides[n]; s->offset[VX] = SHORT(*((const int16_t*) (ptr))); s->offset[VY] = SHORT(*((const int16_t*) (ptr+2))); idx = USHORT(*((const uint16_t*) (ptr+4))); s->topMaterial = RegisterMaterial((const char*) &idx, false); idx = USHORT(*((const uint16_t*) (ptr+6))); s->bottomMaterial = RegisterMaterial((const char*) &idx, false); idx = USHORT(*((const uint16_t*) (ptr+8))); s->middleMaterial = RegisterMaterial((const char*) &idx, false); idx = USHORT(*((const uint16_t*) (ptr+10))); if(idx == 0xFFFF) s->sector = 0; else s->sector = idx + 1; } break; } return true; } static boolean loadSectors(const byte* buf, size_t len) { uint num, n; size_t elmSize; const byte* ptr; VERBOSE(Con_Message("WadMapConverter::loadSectors: Processing...\n")); elmSize = (map->format == MF_DOOM64? SIZEOF_64SECTOR : SIZEOF_SECTOR); num = len / elmSize; switch(map->format) { default: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { char name[9]; msector_t* s = &map->sectors[n]; s->floorHeight = SHORT(*((const int16_t*) ptr)); s->ceilHeight = SHORT(*((const int16_t*) (ptr+2))); memcpy(name, ptr+4, 8); name[8] = '\0'; s->floorMaterial = RegisterMaterial(name, true); memcpy(name, ptr+12, 8); name[8] = '\0'; s->ceilMaterial = RegisterMaterial(name, true); s->lightLevel = SHORT(*((const int16_t*) (ptr+20))); s->type = SHORT(*((const int16_t*) (ptr+22))); s->tag = SHORT(*((const int16_t*) (ptr+24))); } break; case MF_DOOM64: for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { int idx; msector_t* s = &map->sectors[n]; s->floorHeight = SHORT(*((const int16_t*) ptr)); s->ceilHeight = SHORT(*((const int16_t*) (ptr+2))); idx = USHORT(*((const uint16_t*) (ptr+4))); s->floorMaterial = RegisterMaterial((const char*) &idx, false); idx = USHORT(*((const uint16_t*) (ptr+6))); s->ceilMaterial = RegisterMaterial((const char*) &idx, false); s->d64ceilingColor = USHORT(*((const uint16_t*) (ptr+8))); s->d64floorColor = USHORT(*((const uint16_t*) (ptr+10))); s->d64unknownColor = USHORT(*((const uint16_t*) (ptr+12))); s->d64wallTopColor = USHORT(*((const uint16_t*) (ptr+14))); s->d64wallBottomColor = USHORT(*((const uint16_t*) (ptr+16))); s->type = SHORT(*((const int16_t*) (ptr+18))); s->tag = SHORT(*((const int16_t*) (ptr+20))); s->d64flags = USHORT(*((const uint16_t*) (ptr+22))); s->lightLevel = 160; } break; } return true; } static boolean loadThings(const byte* buf, size_t len) { // New flags: \todo get these from a game api header. #define MTF_Z_FLOOR 0x20000000 // Spawn relative to floor height. #define MTF_Z_CEIL 0x40000000 // Spawn relative to ceiling height (minus thing height). #define MTF_Z_RANDOM 0x80000000 // Random point between floor and ceiling. #define ANG45 0x20000000 uint num, n; size_t elmSize; const byte* ptr; VERBOSE(Con_Message("WadMapConverter::loadThings: Processing...\n")); elmSize = (map->format == MF_DOOM64? SIZEOF_64THING : map->format == MF_HEXEN? SIZEOF_XTHING : SIZEOF_THING); num = len / elmSize; switch(map->format) { default: case MF_DOOM: /** * DOOM Thing flags: */ #define MTF_EASY 0x00000001 // Can be spawned in Easy skill modes. #define MTF_MEDIUM 0x00000002 // Can be spawned in Medium skill modes. #define MTF_HARD 0x00000004 // Can be spawned in Hard skill modes. #define MTF_DEAF 0x00000008 // Mobj will be deaf spawned deaf. #define MTF_NOTSINGLE 0x00000010 // (BOOM) Can not be spawned in single player gamemodes. #define MTF_NOTDM 0x00000020 // (BOOM) Can not be spawned in the Deathmatch gameMode. #define MTF_NOTCOOP 0x00000040 // (BOOM) Can not be spawned in the Co-op gameMode. #define MTF_FRIENDLY 0x00000080 // (BOOM) friendly monster. #define MASK_UNKNOWN_THING_FLAGS (0xffffffff \ ^ (MTF_EASY|MTF_MEDIUM|MTF_HARD|MTF_DEAF|MTF_NOTSINGLE|MTF_NOTDM|MTF_NOTCOOP|MTF_FRIENDLY)) for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { mthing_t* t = &map->things[n]; t->pos[VX] = SHORT(*((const int16_t*) (ptr))); t->pos[VY] = SHORT(*((const int16_t*) (ptr+2))); t->pos[VZ] = 0; t->angle = ANG45 * (SHORT(*((const int16_t*) (ptr+4))) / 45); t->doomEdNum = SHORT(*((const int16_t*) (ptr+6))); t->flags = SHORT(*((const int16_t*) (ptr+8))); t->flags &= ~MASK_UNKNOWN_THING_FLAGS; // DOOM format things spawn on the floor by default unless their // type-specific flags override. t->flags |= MTF_Z_FLOOR; } #undef MTF_EASY #undef MTF_MEDIUM #undef MTF_HARD #undef MTF_AMBUSH #undef MTF_NOTSINGLE #undef MTF_NOTDM #undef MTF_NOTCOOP #undef MTF_FRIENDLY #undef MASK_UNKNOWN_THING_FLAGS break; case MF_DOOM64: /** * DOOM64 Thing flags: */ #define MTF_EASY 0x00000001 // Appears in easy skill modes. #define MTF_MEDIUM 0x00000002 // Appears in medium skill modes. #define MTF_HARD 0x00000004 // Appears in hard skill modes. #define MTF_DEAF 0x00000008 // Thing is deaf. #define MTF_NOTSINGLE 0x00000010 // Appears in multiplayer game modes only. #define MTF_DONTSPAWNATSTART 0x00000020 // Do not spawn this thing at map start. #define MTF_SCRIPT_TOUCH 0x00000040 // Mobjs spawned from this spot will envoke a script when touched. #define MTF_SCRIPT_DEATH 0x00000080 // Mobjs spawned from this spot will envoke a script on death. #define MTF_SECRET 0x00000100 // A secret (bonus) item. #define MTF_NOTARGET 0x00000200 // Mobjs spawned from this spot will not target their attacker when hurt. #define MTF_NOTDM 0x00000400 // Can not be spawned in the Deathmatch gameMode. #define MTF_NOTCOOP 0x00000800 // Can not be spawned in the Co-op gameMode. #define MASK_UNKNOWN_THING_FLAGS (0xffffffff \ ^ (MTF_EASY|MTF_MEDIUM|MTF_HARD|MTF_DEAF|MTF_NOTSINGLE|MTF_DONTSPAWNATSTART|MTF_SCRIPT_TOUCH|MTF_SCRIPT_DEATH|MTF_SECRET|MTF_NOTARGET|MTF_NOTDM|MTF_NOTCOOP)) for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { mthing_t* t = &map->things[n]; t->pos[VX] = SHORT(*((const int16_t*) (ptr))); t->pos[VY] = SHORT(*((const int16_t*) (ptr+2))); t->pos[VZ] = SHORT(*((const int16_t*) (ptr+4))); t->angle = ANG45 * (SHORT(*((const int16_t*) (ptr+6))) / 45); t->doomEdNum = SHORT(*((const int16_t*) (ptr+8))); t->flags = SHORT(*((const int16_t*) (ptr+10))); t->flags &= ~MASK_UNKNOWN_THING_FLAGS; // DOOM64 format things spawn relative to the floor by default // unless their type-specific flags override. t->flags |= MTF_Z_FLOOR; t->d64TID = SHORT(*((const int16_t*) (ptr+12))); } #undef MTF_EASY #undef MTF_MEDIUM #undef MTF_HARD #undef MTF_DEAF #undef MTF_NOTSINGLE #undef MTF_DONTSPAWNATSTART #undef MTF_SCRIPT_TOUCH #undef MTF_SCRIPT_DEATH #undef MTF_SECRET #undef MTF_NOTARGET #undef MTF_NOTDM #undef MTF_NOTCOOP #undef MASK_UNKNOWN_THING_FLAGS break; case MF_HEXEN: /** * Hexen Thing flags: */ #define MTF_EASY 0x00000001 #define MTF_NORMAL 0x00000002 #define MTF_HARD 0x00000004 #define MTF_AMBUSH 0x00000008 #define MTF_DORMANT 0x00000010 #define MTF_FIGHTER 0x00000020 #define MTF_CLERIC 0x00000040 #define MTF_MAGE 0x00000080 #define MTF_GSINGLE 0x00000100 #define MTF_GCOOP 0x00000200 #define MTF_GDEATHMATCH 0x00000400 // The following are not currently used. #define MTF_SHADOW 0x00000800 // (ZDOOM) Thing is 25% translucent. #define MTF_INVISIBLE 0x00001000 // (ZDOOM) Makes the thing invisible. #define MTF_FRIENDLY 0x00002000 // (ZDOOM) Friendly monster. #define MTF_STILL 0x00004000 // (ZDOOM) Thing stands still (only useful for specific Strife monsters or friendlies). #define MASK_UNKNOWN_THING_FLAGS (0xffffffff \ ^ (MTF_EASY|MTF_NORMAL|MTF_HARD|MTF_AMBUSH|MTF_DORMANT|MTF_FIGHTER|MTF_CLERIC|MTF_MAGE|MTF_GSINGLE|MTF_GCOOP|MTF_GDEATHMATCH|MTF_SHADOW|MTF_INVISIBLE|MTF_FRIENDLY|MTF_STILL)) for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { mthing_t* t = &map->things[n]; t->xTID = SHORT(*((const int16_t*) (ptr))); t->pos[VX] = SHORT(*((const int16_t*) (ptr+2))); t->pos[VY] = SHORT(*((const int16_t*) (ptr+4))); t->pos[VZ] = SHORT(*((const int16_t*) (ptr+6))); t->angle = SHORT(*((const int16_t*) (ptr+8))); t->doomEdNum = SHORT(*((const int16_t*) (ptr+10))); /** * For some reason, the Hexen format stores polyobject tags in * the angle field in THINGS. Thus, we cannot translate the * angle until we know whether it is a polyobject type or not. */ if(t->doomEdNum != PO_ANCHOR_DOOMEDNUM && t->doomEdNum != PO_SPAWN_DOOMEDNUM && t->doomEdNum != PO_SPAWNCRUSH_DOOMEDNUM) t->angle = ANG45 * (t->angle / 45); t->flags = SHORT(*((const int16_t*) (ptr+12))); t->flags &= ~MASK_UNKNOWN_THING_FLAGS; /** * Translate flags: */ // Game type logic is inverted. t->flags ^= (MTF_GSINGLE|MTF_GCOOP|MTF_GDEATHMATCH); // HEXEN format things spawn relative to the floor by default // unless their type-specific flags override. t->flags |= MTF_Z_FLOOR; t->xSpecial = *(ptr+14); t->xArgs[0] = *(ptr+15); t->xArgs[1] = *(ptr+16); t->xArgs[2] = *(ptr+17); t->xArgs[3] = *(ptr+18); t->xArgs[4] = *(ptr+19); } #undef MTF_EASY #undef MTF_NORMAL #undef MTF_HARD #undef MTF_AMBUSH #undef MTF_DORMANT #undef MTF_FIGHTER #undef MTF_CLERIC #undef MTF_MAGE #undef MTF_GSINGLE #undef MTF_GCOOP #undef MTF_GDEATHMATCH // The following are not currently used. #undef MTF_SHADOW #undef MTF_INVISIBLE #undef MTF_FRIENDLY #undef MTF_STILL #undef MASK_UNKNOWN_THING_FLAGS break; } return true; #undef MTF_Z_FLOOR #undef MTF_Z_CEIL #undef MTF_Z_RANDOM } static boolean loadLights(const byte* buf, size_t len) { uint num, n; size_t elmSize; const byte* ptr; VERBOSE(Con_Message("WadMapConverter::loadLights: Processing...\n")); elmSize = SIZEOF_LIGHT; num = len / elmSize; for(n = 0, ptr = buf; n < num; ++n, ptr += elmSize) { surfacetint_t* t = &map->lights[n]; t->rgb[0] = (float) *(ptr) / 255; t->rgb[1] = (float) *(ptr+1) / 255; t->rgb[2] = (float) *(ptr+2) / 255; t->xx[0] = *(ptr+3); t->xx[1] = *(ptr+4); t->xx[2] = *(ptr+5); } return true; } static void bufferLump(int lumpNum, byte** buf, size_t* len, size_t* oldLen) { *len = W_LumpLength(lumpNum); // Need to enlarge our buffer? if(*len > *oldLen) { *buf = realloc(*buf, *len); *oldLen = *len; } // Buffer the entire lump. W_ReadLump(lumpNum, *buf); } boolean LoadMap(const int* lumpList, int numLumps) { int i; byte* buf = NULL; size_t oldLen = 0; // Allocate the data structure arrays. map->vertexes = malloc(map->numVertexes * 2 * sizeof(float)); map->lines = malloc(map->numLines * sizeof(mline_t)); map->sides = malloc(map->numSides * sizeof(mside_t)); map->sectors = malloc(map->numSectors * sizeof(msector_t)); map->things = malloc(map->numThings * sizeof(mthing_t)); if(map->numLights) map->lights = malloc(map->numLights * sizeof(surfacetint_t)); for(i = 0; i < numLumps; ++i) { size_t len; lumptype_t lumpType; lumpType = DataTypeForLumpName(W_LumpName(lumpList[i])); // Process it, transforming it into our local representation. switch(lumpType) { case ML_VERTEXES: bufferLump(lumpList[i], &buf, &len, &oldLen); loadVertexes(buf, len); break; case ML_LINEDEFS: bufferLump(lumpList[i], &buf, &len, &oldLen); loadLinedefs(buf, len); break; case ML_SIDEDEFS: bufferLump(lumpList[i], &buf, &len, &oldLen); loadSidedefs(buf, len); break; case ML_SECTORS: bufferLump(lumpList[i], &buf, &len, &oldLen); loadSectors(buf, len); break; case ML_THINGS: if(map->numThings) { bufferLump(lumpList[i], &buf, &len, &oldLen); loadThings(buf, len); } break; case ML_LIGHTS: if(map->numLights) { bufferLump(lumpList[i], &buf, &len, &oldLen); loadLights(buf, len); } break; case ML_MACROS: //// \todo Write me! break; default: break; } } if(buf) free(buf); return true; // Read and converted successfully. } boolean TransferMap(void) { uint startTime = Sys_GetRealTime(); uint i; boolean result; VERBOSE(Con_Message("WadMapConverter::TransferMap...\n")); MPE_Begin(map->name); // Create all the data structures. VERBOSE(Con_Message("WadMapConverter::Transfering vertexes...\n")); MPE_VertexCreatev(map->numVertexes, map->vertexes, NULL); VERBOSE(Con_Message("WadMapConverter::Transfering sectors...\n")); for(i = 0; i < map->numSectors; ++i) { msector_t* sec = &map->sectors[i]; uint sectorIDX; sectorIDX = MPE_SectorCreate((float) sec->lightLevel / 255.0f, 1, 1, 1); MPE_PlaneCreate(sectorIDX, sec->floorHeight, sec->floorMaterial->num, 0, 0, 1, 1, 1, 1, 0, 0, 1); MPE_PlaneCreate(sectorIDX, sec->ceilHeight, sec->ceilMaterial->num, 0, 0, 1, 1, 1, 1, 0, 0, -1); MPE_GameObjProperty("XSector", i, "Tag", DDVT_SHORT, &sec->tag); MPE_GameObjProperty("XSector", i, "Type", DDVT_SHORT, &sec->type); if(map->format == MF_DOOM64) { MPE_GameObjProperty("XSector", i, "Flags", DDVT_SHORT, &sec->d64flags); MPE_GameObjProperty("XSector", i, "CeilingColor", DDVT_SHORT, &sec->d64ceilingColor); MPE_GameObjProperty("XSector", i, "FloorColor", DDVT_SHORT, &sec->d64floorColor); MPE_GameObjProperty("XSector", i, "UnknownColor", DDVT_SHORT, &sec->d64unknownColor); MPE_GameObjProperty("XSector", i, "WallTopColor", DDVT_SHORT, &sec->d64wallTopColor); MPE_GameObjProperty("XSector", i, "WallBottomColor", DDVT_SHORT, &sec->d64wallBottomColor); } } VERBOSE(Con_Message("WadMapConverter::Transfering linedefs...\n")); for(i = 0; i < map->numLines; ++i) { mline_t* l = &map->lines[i]; mside_t* front, *back; uint frontIdx = 0, backIdx = 0; front = (l->sides[RIGHT] != 0? &map->sides[l->sides[RIGHT]-1] : NULL); if(front) { frontIdx = MPE_SidedefCreate(front->sector, (map->format == MF_DOOM64? SDF_MIDDLE_STRETCH : 0), front->topMaterial->num, front->offset[VX], front->offset[VY], 1, 1, 1, front->middleMaterial->num, front->offset[VX], front->offset[VY], 1, 1, 1, 1, front->bottomMaterial->num, front->offset[VX], front->offset[VY], 1, 1, 1); } back = (l->sides[LEFT] != 0? &map->sides[l->sides[LEFT]-1] : NULL); if(back) { backIdx = MPE_SidedefCreate(back->sector, (map->format == MF_DOOM64? SDF_MIDDLE_STRETCH : 0), back->topMaterial->num, back->offset[VX], back->offset[VY], 1, 1, 1, back->middleMaterial->num, back->offset[VX], back->offset[VY], 1, 1, 1, 1, back->bottomMaterial->num, back->offset[VX], back->offset[VY], 1, 1, 1); } MPE_LinedefCreate(l->v[0], l->v[1], frontIdx, backIdx, 0); MPE_GameObjProperty("XLinedef", i, "Flags", DDVT_SHORT, &l->flags); switch(map->format) { default: case MF_DOOM: MPE_GameObjProperty("XLinedef", i, "Type", DDVT_SHORT, &l->dType); MPE_GameObjProperty("XLinedef", i, "Tag", DDVT_SHORT, &l->dTag); break; case MF_DOOM64: MPE_GameObjProperty("XLinedef", i, "DrawFlags", DDVT_BYTE, &l->d64drawFlags); MPE_GameObjProperty("XLinedef", i, "TexFlags", DDVT_BYTE, &l->d64texFlags); MPE_GameObjProperty("XLinedef", i, "Type", DDVT_BYTE, &l->d64type); MPE_GameObjProperty("XLinedef", i, "UseType", DDVT_BYTE, &l->d64useType); MPE_GameObjProperty("XLinedef", i, "Tag", DDVT_SHORT, &l->d64tag); break; case MF_HEXEN: MPE_GameObjProperty("XLinedef", i, "Type", DDVT_BYTE, &l->xType); MPE_GameObjProperty("XLinedef", i, "Arg0", DDVT_BYTE, &l->xArgs[0]); MPE_GameObjProperty("XLinedef", i, "Arg1", DDVT_BYTE, &l->xArgs[1]); MPE_GameObjProperty("XLinedef", i, "Arg2", DDVT_BYTE, &l->xArgs[2]); MPE_GameObjProperty("XLinedef", i, "Arg3", DDVT_BYTE, &l->xArgs[3]); MPE_GameObjProperty("XLinedef", i, "Arg4", DDVT_BYTE, &l->xArgs[4]); break; } } VERBOSE(Con_Message("WadMapConverter::Transfering lights...\n")); for(i = 0; i < map->numLights; ++i) { surfacetint_t* l = &map->lights[i]; MPE_GameObjProperty("Light", i, "ColorR", DDVT_FLOAT, &l->rgb[0]); MPE_GameObjProperty("Light", i, "ColorG", DDVT_FLOAT, &l->rgb[1]); MPE_GameObjProperty("Light", i, "ColorB", DDVT_FLOAT, &l->rgb[2]); MPE_GameObjProperty("Light", i, "XX0", DDVT_BYTE, &l->xx[0]); MPE_GameObjProperty("Light", i, "XX1", DDVT_BYTE, &l->xx[1]); MPE_GameObjProperty("Light", i, "XX2", DDVT_BYTE, &l->xx[2]); } VERBOSE(Con_Message("WadMapConverter::Transfering polyobjs...\n")); for(i = 0; i < map->numPolyobjs; ++i) { mpolyobj_t* po = map->polyobjs[i]; uint j, *lineList; lineList = malloc(sizeof(uint) * po->lineCount); for(j = 0; j < po->lineCount; ++j) lineList[j] = po->lineIndices[j] + 1; MPE_PolyobjCreate(lineList, po->lineCount, po->tag, po->seqType, (float) po->anchor[VX], (float) po->anchor[VY]); free(lineList); } VERBOSE(Con_Message("WadMapConverter::Transfering things...\n")); for(i = 0; i < map->numThings; ++i) { mthing_t* th = &map->things[i]; MPE_GameObjProperty("Thing", i, "X", DDVT_SHORT, &th->pos[VX]); MPE_GameObjProperty("Thing", i, "Y", DDVT_SHORT, &th->pos[VY]); MPE_GameObjProperty("Thing", i, "Z", DDVT_SHORT, &th->pos[VZ]); MPE_GameObjProperty("Thing", i, "Angle", DDVT_ANGLE, &th->angle); MPE_GameObjProperty("Thing", i, "DoomEdNum", DDVT_SHORT, &th->doomEdNum); MPE_GameObjProperty("Thing", i, "Flags", DDVT_INT, &th->flags); if(map->format == MF_DOOM64) { MPE_GameObjProperty("Thing", i, "ID", DDVT_SHORT, &th->d64TID); } else if(map->format == MF_HEXEN) { MPE_GameObjProperty("Thing", i, "Special", DDVT_BYTE, &th->xSpecial); MPE_GameObjProperty("Thing", i, "ID", DDVT_SHORT, &th->xTID); MPE_GameObjProperty("Thing", i, "Arg0", DDVT_BYTE, &th->xArgs[0]); MPE_GameObjProperty("Thing", i, "Arg1", DDVT_BYTE, &th->xArgs[1]); MPE_GameObjProperty("Thing", i, "Arg2", DDVT_BYTE, &th->xArgs[2]); MPE_GameObjProperty("Thing", i, "Arg3", DDVT_BYTE, &th->xArgs[3]); MPE_GameObjProperty("Thing", i, "Arg4", DDVT_BYTE, &th->xArgs[4]); } } // We've now finished with the original map data. freeMapData(); // Let Doomsday know that we've finished with this map. result = MPE_End(); VERBOSE( Con_Message("WadMapConverter::TransferMap: Done in %.2f seconds.\n", (Sys_GetRealTime() - startTime) / 1000.0f)); return result; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/include/0000755000175000017500000000000011523516204023367 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/include/wadmapconverter.h0000644000175000017500000001134211357170242026745 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * wadmapconverter.h: Doomsday plugin for converting DOOM-like format maps. * * The purpose of a mapconverter plugin is to transform a map into * Doomsday's native map format by use of the public map editing interface. */ #ifndef __MAPCONVERTER_H__ #define __MAPCONVERTER_H__ #include "dd_types.h" // Vertex indices. enum { VX, VY, VZ }; // Line sides. #define RIGHT 0 #define LEFT 1 #define VERBOSE(code) { if(verbose) { code; } } typedef struct materialref_s { char name[9]; materialnum_t num; // Doomsday's unique identifier for this. } materialref_t; typedef struct mside_s { int16_t offset[2]; const materialref_t* topMaterial; const materialref_t* bottomMaterial; const materialref_t* middleMaterial; uint sector; } mside_t; // Line flags #define LAF_POLYOBJ 0x1 // Line is from a polyobject. typedef struct mline_s { uint v[2]; uint sides[2]; int16_t flags; // MF_* flags, read from the LINEDEFS, map data lump. // Analysis data: int16_t aFlags; // DOOM format members: int16_t dType; int16_t dTag; // Hexen format members: byte xType; byte xArgs[5]; // DOOM64 format members: byte d64drawFlags; byte d64texFlags; byte d64type; byte d64useType; int16_t d64tag; uint validCount; // Used for Polyobj LineDef collection. } mline_t; typedef struct msector_s { int16_t floorHeight; int16_t ceilHeight; int16_t lightLevel; int16_t type; int16_t tag; const materialref_t* floorMaterial; const materialref_t* ceilMaterial; // DOOM64 format members: int16_t d64flags; uint16_t d64floorColor; uint16_t d64ceilingColor; uint16_t d64unknownColor; uint16_t d64wallTopColor; uint16_t d64wallBottomColor; } msector_t; typedef struct mthing_s { int16_t pos[3]; angle_t angle; int16_t doomEdNum; int32_t flags; // Hexen format members: int16_t xTID; byte xSpecial; byte xArgs[5]; // DOOM64 format members: int16_t d64TID; } mthing_t; // Hexen only (at present): typedef struct mpolyobj_s { uint idx; // Idx of polyobject uint lineCount; uint* lineIndices; int tag; // Reference tag assigned in HereticEd int seqType; int16_t anchor[2]; } mpolyobj_t; // DOOM64 only (at present): typedef struct mlight_s { float rgb[3]; byte xx[3]; } surfacetint_t; typedef enum { MF_DOOM = 0, MF_HEXEN, MF_DOOM64 } mapformatid_t; typedef struct map_s { char name[9]; uint numVertexes; uint numSectors; uint numLines; uint numSides; uint numPolyobjs; uint numThings; uint numLights; float* vertexes; // Array of vertex coords [v0 X, vo Y, v1 X, v1 Y...] msector_t* sectors; mline_t* lines; mside_t* sides; mthing_t* things; mpolyobj_t** polyobjs; surfacetint_t* lights; size_t numFlats; materialref_t** flats; size_t numTextures; materialref_t** textures; mapformatid_t format; byte* rejectMatrix; void* blockMap; } map_t; extern map_t* map; extern boolean verbose; boolean IsSupportedFormat(const int* lumpList, int numLumps); boolean LoadMap(const int* lumpList, int numLumps); void AnalyzeMap(void); boolean TransferMap(); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/include/version.h0000644000175000017500000000342311357170242025232 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __WADMAPCONVERTER_VERSION_H__ #define __WADMAPCONVERTER_VERSION_H__ #ifndef WADMAPCONVERTER_VER_ID # ifdef _DEBUG # define WADMAPCONVERTER_VER_ID "+D Doomsday" # else # define WADMAPCONVERTER_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define PLUGIN_NAME "dpwadmapconverter" // Presented to the user in dialogs, messages etc. #define PLUGIN_NICENAME "WAD Map Converter" #define PLUGIN_DETAILS "Doomsday plugin for loading WAD format maps." #define PLUGIN_VERSION_TEXT "1.0.5" #define PLUGIN_VERSION_TEXTLONG "Version" PLUGIN_VERSION_TEXT " " __DATE__ " (" WADMAPCONVERTER_VER_ID ")" #define PLUGIN_VERSION_NUMBER 1,0,5,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/wadmapconverter/CMakeLists.txt0000644000175000017500000000455711357170242024522 0ustar keeskees## deng build scripts. ## Copyright © 2006 - 2007 Jamie Jones ## Copyright © 2007 Daniel Swanson ## ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ ######################## WAD Map Converter Plugin ############################## INCLUDE_DIRECTORIES ( include ) FILE(GLOB WADMAPCONVERTER_SOURCES src/*.c) ADD_LIBRARY (dpwadmapconverter SHARED ${WADMAPCONVERTER_SOURCES}) #IF (APPLE) # SET_TARGET_PROPERTIES (dpwadmapconverter PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -bundle -bundle_loader doomsday") #ENDIF (APPLE) ################################################################################ ######################## Install Targets ###################################### INSTALL(TARGETS dpwadmapconverter RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) IF (APPLE) # Bundling. SET (BUNDLE_BASE dpWADMapConverter) SET (BUNDLE ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.bundle) ADD_CUSTOM_COMMAND( TARGET dpwadmapconverter POST_BUILD COMMAND rm -rf ${BUNDLE} COMMAND mkdir -p ${BUNDLE}/Contents/MacOS COMMAND cp libdpwadmapconverter.dylib ${BUNDLE}/Contents/MacOS/${BUNDLE_BASE} COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/${BUNDLE_BASE}-Info.plist ${BUNDLE}/Contents/Info.plist #COMMAND mkdir -p ${BUNDLE}/Contents/Resources/English.lproj #COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/InfoPlist.strings ${BUNDLE}/Contents/Resources/English.lproj/ COMMAND echo 'APPL????' > ${BUNDLE}/Contents/PkgInfo ) ENDIF (APPLE) deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/0000755000175000017500000000000011523516204020021 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/api/0000755000175000017500000000000011523516204020572 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/api/dsopenal.def0000644000175000017500000000043311357170242023062 0ustar keeskeesLIBRARY DSOPENAL ; All exports should be prefixed DS_. EXPORTS DS_Init DS_Shutdown DS_Event DS_SFX_Init DS_SFX_CreateBuffer DS_SFX_DestroyBuffer DS_SFX_Load DS_SFX_Reset DS_SFX_Play DS_SFX_Stop DS_SFX_Refresh DS_SFX_Set DS_SFX_Setv DS_SFX_Listener DS_SFX_Listenerv DS_SFX_Getv deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/res/0000755000175000017500000000000011523516204020612 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/res/resource.h0000644000175000017500000000061211357170242022614 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by openal.rc // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/res/dsopenal.dll.manifest0000644000175000017500000000062311357170242024725 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/res/openal.rc0000644000175000017500000001003711357170242022422 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * openal.rc: dsOpenAL.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""dsopenal.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION PLUGIN_VERSION_NUMBER\r\n" "PRODUCTVERSION PLUGIN_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dsOpenAL.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION PLUGIN_VERSION_NUMBER PRODUCTVERSION PLUGIN_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "dsOpenAL.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/doc/0000755000175000017500000000000011523516204020566 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/doc/LICENSE0000644000175000017500000003545111357170242021606 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/src/0000755000175000017500000000000011357170242020613 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/src/driver_openal.c0000644000175000017500000003172111357170242023614 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA * * \bug Not 64bit clean: In function 'DS_SFX_CreateBuffer': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'DS_SFX_DestroyBuffer': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'Sys_LoadAudioDriver': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'DS_SFX_Play': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'DS_SFX_Stop': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'DS_SFX_Refresh': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'DS_SFX_Set': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'DS_SFX_Setv': cast to pointer from integer of different size */ /** * driver_openal.c: OpenAL Doomsday Sfx Driver. * * Link with openal32.lib (and doomsday.lib). */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #ifdef MSVC # pragma warning (disable: 4244) #endif #ifndef FINK #include #include #else #include #include #endif #include #include #include "doomsday.h" #include "sys_audiod.h" #include "sys_audiod_sfx.h" // MACROS ------------------------------------------------------------------ #define PI 3.141592654 #define SRC(buf) ((ALuint)buf->ptr3D) #define BUF(buf) ((ALuint)buf->ptr) // TYPES ------------------------------------------------------------------- enum { VX, VY, VZ }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- #ifdef WIN32 ALenum(*EAXGet) (const struct _GUID* propertySetID, ALuint prop, ALuint source, ALvoid* value, ALuint size); ALenum(*EAXSet) (const struct _GUID* propertySetID, ALuint prop, ALuint source, ALvoid *value, ALuint size); #endif // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- int DS_Init(void); void DS_Shutdown(void); void DS_Event(int type); int DS_SFX_Init(void); sfxbuffer_t* DS_SFX_CreateBuffer(int flags, int bits, int rate); void DS_SFX_DestroyBuffer(sfxbuffer_t* buf); void DS_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample); void DS_SFX_Reset(sfxbuffer_t* buf); void DS_SFX_Play(sfxbuffer_t* buf); void DS_SFX_Stop(sfxbuffer_t* buf); void DS_SFX_Refresh(sfxbuffer_t* buf); void DS_SFX_Set(sfxbuffer_t* buf, int prop, float value); void DS_SFX_Setv(sfxbuffer_t* buf, int prop, float* values); void DS_SFX_Listener(int prop, float value); void DS_SFX_Listenerv(int prop, float* values); int DS_SFX_Getv(int prop, void* values); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- #ifdef WIN32 // EAX 2.0 GUIDs struct _GUID DSPROPSETID_EAX20_ListenerProperties = { 0x306a6a8, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22} }; struct _GUID DSPROPSETID_EAX20_BufferProperties = { 0x306a6a7, 0xb224, 0x11d2, {0x99, 0xe5, 0x0, 0x0, 0xe8, 0xd8, 0xc7, 0x22} }; #endif boolean initOk = false, hasEAX = false; int verbose; float unitsPerMeter = 1; float headYaw, headPitch; // In radians. ALCdevice* device = 0; ALCcontext* context = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static int error(const char* what, const char* msg) { ALenum code = alGetError(); if(code == AL_NO_ERROR) return false; Con_Message("DS_%s(OpenAL): %s [%s]\n", what, msg, alGetString(code)); return true; } int DS_Init(void) { if(initOk) return true; // Are we in verbose mode? if((verbose = ArgExists("-verbose"))) Con_Message("DS_Init(OpenAL): Starting OpenAL...\n"); // Open device. if(!(device = alcOpenDevice((ALubyte *) "DirectSound3D"))) { Con_Message("Failed to initialize OpenAL (DS3D).\n"); return false; } // Create a context. alcMakeContextCurrent(context = alcCreateContext(device, NULL)); // Clear error message. alGetError(); #ifdef WIN32 // Check for EAX 2.0. if((hasEAX = alIsExtensionPresent((ALubyte *) "EAX2.0"))) { if(!(EAXGet = alGetProcAddress("EAXGet"))) hasEAX = false; if(!(EAXSet = alGetProcAddress("EAXSet"))) hasEAX = false; } if(hasEAX && verbose) Con_Message("DS_Init(OpenAL): EAX 2.0 available.\n"); #else hasEAX = false; #endif alListenerf(AL_GAIN, 1); alDistanceModel(AL_INVERSE_DISTANCE_CLAMPED); headYaw = headPitch = 0; unitsPerMeter = 36; // Everything is OK. initOk = true; return true; } void DS_Shutdown(void) { if(!initOk) return; alcMakeContextCurrent(NULL); alcDestroyContext(context); alcCloseDevice(device); context = NULL; device = NULL; initOk = false; } void DS_Event(int type) { // Not supported. } int DS_SFX_Init(void) { return true; } sfxbuffer_t* DS_SFX_CreateBuffer(int flags, int bits, int rate) { sfxbuffer_t* buf; ALuint bufName, srcName; // Create a new buffer and a new source. alGenBuffers(1, &bufName); if(error("CreateBuffer", "GenBuffers")) return NULL; alGenSources(1, &srcName); if(error("CreateBuffer", "GenSources")) { alDeleteBuffers(1, &bufName); return NULL; } // Attach the buffer to the source. alSourcei(srcName, AL_BUFFER, bufName); error("CreateBuffer", "Source BUFFER"); if(!(flags & SFXBF_3D)) { // 2D sounds are around the listener. alSourcei(srcName, AL_SOURCE_RELATIVE, AL_TRUE); alSourcef(srcName, AL_ROLLOFF_FACTOR, 0); } // Create the buffer object. buf = Z_Calloc(sizeof(*buf), PU_STATIC, 0); buf->ptr = (void *) bufName; buf->ptr3D = (void *) srcName; buf->bytes = bits / 8; buf->rate = rate; buf->flags = flags; buf->freq = rate; // Modified by calls to Set(SFXBP_FREQUENCY). return buf; } void DS_SFX_DestroyBuffer(sfxbuffer_t* buf) { ALuint srcName, bufName; if(!buf) return; srcName = SRC(buf); bufName = BUF(buf); alDeleteSources(1, &srcName); alDeleteBuffers(1, &bufName); Z_Free(buf); } void DS_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample) { if(!buf || !sample) return; // Does the buffer already have a sample loaded? if(buf->sample) { // Is the same one? if(buf->sample->id == sample->id) return; // No need to reload. } alBufferData(BUF(buf), sample->bytesPer == 1 ? AL_FORMAT_MONO8 : AL_FORMAT_MONO16, sample->data, sample->size, sample->rate); error("Load", "BufferData"); buf->sample = sample; } /** * Stops the buffer and makes it forget about its sample. */ void DS_SFX_Reset(sfxbuffer_t* buf) { if(!buf) return; DS_SFX_Stop(buf); buf->sample = NULL; } void DS_SFX_Play(sfxbuffer_t* buf) { ALuint source; // Playing is quite impossible without a sample. if(!buf || !buf->sample) return; source = SRC(buf); /*#if _DEBUG alGetSourcei(source, AL_BUFFER, &bn); Con_Message("Buffer = %x\n", bn); if(bn != BUF(buf)) Con_Message("Not the same!\n"); #endif*/ alSourcei(source, AL_BUFFER, BUF(buf)); alSourcei(source, AL_LOOPING, (buf->flags & SFXBF_REPEAT) != 0); alSourcePlay(source); error("Play", "SourcePlay"); error("Play", "Get state"); // The buffer is now playing. buf->flags |= SFXBF_PLAYING; } void DS_SFX_Stop(sfxbuffer_t* buf) { if(!buf || !buf->sample) return; alSourceRewind(SRC(buf)); buf->flags &= ~SFXBF_PLAYING; } void DS_SFX_Refresh(sfxbuffer_t* buf) { ALint state; if(!buf || !buf->sample) return; alGetSourcei(SRC(buf), AL_SOURCE_STATE, &state); if(state == AL_STOPPED) { buf->flags &= ~SFXBF_PLAYING; } } /** * @param yaw Yaw in radians. * @param pitch Pitch in radians. * @param front Ptr to front vector, can be @c NULL. * @param up Ptr to up vector, can be @c NULL. */ static void vectors(float yaw, float pitch, float* front, float* up) { if(!front && !up) return; // Nothing to do. if(front) { front[VX] = (float) (cos(yaw) * cos(pitch)); front[VZ] = (float) (sin(yaw) * cos(pitch)); front[VY] = (float) sin(pitch); } if(up) { up[VX] = (float) (-cos(yaw) * sin(pitch)); up[VZ] = (float) (-sin(yaw) * sin(pitch)); up[VY] = (float) cos(pitch); } } /** * Pan is linear, from -1 to 1. 0 is in the middle. */ static void setPan(ALuint source, float pan) { float pos[3]; vectors((float) (headYaw - pan * PI / 2), headPitch, pos, 0); alSourcefv(source, AL_POSITION, pos); } void DS_SFX_Set(sfxbuffer_t* buf, int prop, float value) { unsigned int dw; ALuint source; if(!buf) return; source = SRC(buf); switch(prop) { case SFXBP_VOLUME: alSourcef(source, AL_GAIN, value); break; case SFXBP_FREQUENCY: dw = (int) (buf->rate * value); if(dw != buf->freq) // Don't set redundantly. { buf->freq = dw; alSourcef(source, AL_PITCH, value); } break; case SFXBP_PAN: setPan(source, value); break; case SFXBP_MIN_DISTANCE: alSourcef(source, AL_REFERENCE_DISTANCE, value / unitsPerMeter); break; case SFXBP_MAX_DISTANCE: alSourcef(source, AL_MAX_DISTANCE, value / unitsPerMeter); break; case SFXBP_RELATIVE_MODE: alSourcei(source, AL_SOURCE_RELATIVE, value ? AL_TRUE : AL_FALSE); break; default: break; } } void DS_SFX_Setv(sfxbuffer_t* buf, int prop, float* values) { ALuint source; if(!buf || !values) return; source = SRC(buf); switch(prop) { case SFXBP_POSITION: alSource3f(source, AL_POSITION, values[VX] / unitsPerMeter, values[VZ] / unitsPerMeter, values[VY] / unitsPerMeter); break; case SFXBP_VELOCITY: alSource3f(source, AL_VELOCITY, values[VX] / unitsPerMeter, values[VZ] / unitsPerMeter, values[VY] / unitsPerMeter); break; default: break; } } void DS_SFX_Listener(int prop, float value) { switch(prop) { case SFXLP_UNITS_PER_METER: unitsPerMeter = value; break; case SFXLP_DOPPLER: alDopplerFactor(value); break; default: break; } } void DS_SFX_Listenerv(int prop, float* values) { float ori[6]; if(!values) return; switch(prop) { case SFXLP_PRIMARY_FORMAT: // No need to concern ourselves with this kind of things... break; case SFXLP_POSITION: alListener3f(AL_POSITION, values[VX] / unitsPerMeter, values[VZ] / unitsPerMeter, values[VY] / unitsPerMeter); break; case SFXLP_VELOCITY: alListener3f(AL_VELOCITY, values[VX] / unitsPerMeter, values[VZ] / unitsPerMeter, values[VY] / unitsPerMeter); break; case SFXLP_ORIENTATION: vectors(headYaw = (float) (values[VX] / 180 * PI), headPitch = (float) (values[VY] / 180 * PI), ori, ori + 3); alListenerfv(AL_ORIENTATION, ori); break; case SFXLP_REVERB: // Not supported. break; default: DS_SFX_Listener(prop, 0); break; } } int DS_SFX_Getv(int prop, void* values) { // Stub. return 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/include/0000755000175000017500000000000011523516204021444 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/include/version.h0000644000175000017500000000334311357170242023310 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __DSOPENAL_VERSION_H__ #define __DSOPENAL_VERSION_H__ #ifndef DSOPENAL_VER_ID # ifdef _DEBUG # define DSOPENAL_VER_ID "+D Doomsday" # else # define DSOPENAL_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define PLUGIN_NAME "dsopenal" // Presented to the user in dialogs, messages etc. #define PLUGIN_NICENAME "OpenAL Audio Driver" #define PLUGIN_DETAILS "Doomsday plugin for audio playback via OpenAL" #define PLUGIN_VERSION_TEXT "1.2.4" #define PLUGIN_VERSION_TEXTLONG "Version" PLUGIN_VERSION_TEXT " " __DATE__ " (" DSOPENAL_VER_ID ")" #define PLUGIN_VERSION_NUMBER 1,2,4,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/openal/CMakeLists.txt0000644000175000017500000000307711357170242022573 0ustar keeskees## deng build scripts. ## Copyright © 2006 - 2007 Jamie Jones ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ ######################## OpenAL Output Plugin ################################# FILE(GLOB OPENAL_SOURCES src/*.c) ADD_LIBRARY (dsopenal SHARED ${OPENAL_SOURCES}) TARGET_LINK_LIBRARIES (dsopenal ${OPENAL_LIBRARY} ) IF (APPLE) SET_TARGET_PROPERTIES (dsopenal PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -bundle -bundle_loader doomsday") ENDIF (APPLE) ################################################################################ ######################## Install Targets ###################################### INSTALL(TARGETS dsopenal RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/0000755000175000017500000000000011523516204020025 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/api/0000755000175000017500000000000011523516204020576 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/api/jdoom64.def0000644000175000017500000000005511357170242022543 0ustar keeskeesLIBRARY JDOOM64 EXPORTS GetGameAPI @1deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/res/0000755000175000017500000000000011523516204020616 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/res/jdoom64.rc0000644000175000017500000001027511357170242022436 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jdoom64.rc: jDoom64.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""jdoom64.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION GAME_VERSION_NUMBER\r\n" "PRODUCTVERSION GAME_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", GAME_NICENAME "" (Doomsday Engine game plugin)\0""\r\n" " VALUE ""FileVersion"", GAME_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", GAME_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""jDoom64.dll\0""\r\n" " VALUE ""ProductName"", GAME_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", GAME_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif /** * Icons: * Icon with lowest ID value placed first to ensure application icon * remains consistent on all systems. */ IDI_GAME_ICON ICON DISCARDABLE "jdoom64.ico" #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION GAME_VERSION_NUMBER PRODUCTVERSION GAME_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", GAME_NICENAME " (Doomsday Engine game plugin)\0" VALUE "FileVersion", GAME_VERSION_TEXT "\0" VALUE "InternalName", GAME_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "jDoom64.dll\0" VALUE "ProductName", GAME_NICENAME "\0" VALUE "ProductVersion", GAME_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/res/resource.h0000644000175000017500000000066711357170242022632 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by jdoom64.rc // #define IDI_GAME_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/res/jdoom64.dll.manifest0000644000175000017500000000062311357170242024406 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/res/jdoom64.ico0000644000175000017500000001163611357170242022606 0ustar keeskees&((&P`  X@@0 X@X@X@X@ 8(8(@0H8@0 X@pXpXpXX@ X@X@X@X@ pXpXpXX@pXpXX@ hpXpXX@@0X@X@pX( 8(X@X@8(pXX@X@@0H8H8X@X@8(@0X@( X@@0( X@X@H8H8H8H8X@@0  @0X@H8H8@0H8@0( @0 8(8(@0@0H8@0 ( H88(pX@0@0pX8((  ( 8(8(@0@0H8( X@@0@08(pXpX@0H88(H8H8@0@08(8(( 8(@0@0H8X@X@@08(8(@0@0X@X@H8@0@08(( @0@0H8X@pXxX@X@xpXX@H8@0@0( (  @0H8H8xxH8H8xx@0H8@0 ( @0X@xx8(H8@08(xxX@ (   8(@0pXx@08(8(@0xpX@0  8(H8(  ( ( ( H88(   ( 8(@0 H8pX pX@0@08(( 8( 8(@0( ( @08(8((  8( 8(@0 8(8(8(   ( ( ( 8(( (    (   ( (      8( 8( 8(8(    8(   8( 8(  8(  ( (   ( (   <xx <<<<<<<|||||<<Ü?deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/doc/0000755000175000017500000000000011523516204020572 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/doc/LICENSE0000644000175000017500000003545111357170242021612 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/data/0000755000175000017500000000000011523516204020736 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/data/conhelp.txt0000644000175000017500000004565011357170242023144 0ustar keeskees# # CONSOLE COMMANDS - JDOOM64 SPECFIC # [conbg] desc = Console background setup. inf = Params: conbg (materialname) [setcolor] desc = Set player color. inf = Params: setcolor (playernum)\nFor example, 'setcolor 4'. [setmap] desc = Set map. inf = Params: setmap (episode) (map)\nFor example, 'setmap 1 7'. [setclass] desc = Set player class. [startcycle] desc = Begin map rotation. [endcycle] desc = End map rotation. [menu] desc = Open/Close the menu. [menuup] desc = Move the menu cursor up. [menudown] desc = Move the menu cursor down. [menuleft] desc = Move the menu cursor left. [menuright] desc = Move the menu cursor right. [menuselect] desc = Select/Accept the current menu item. [menuback] desc = Return to the previous menu page. [helpscreen] desc = Show the Help screens. [savegame] desc = Open the save game menu. [loadgame] desc = Open the load game menu. [listmaps] desc = List all loaded maps. [soundmenu] desc = Open the sound settings menu. [quicksave] desc = Quicksave the game. [endgame] desc = End the game. [togglemsgs] desc = Messages on/off. [quickload] desc = Load the quicksaved game. [quit] desc = Quit the game and return to the OS. [togglegamma] desc = Cycle gamma correction levels. [messageyes] desc = Respond - YES to the message promt. [messageno] desc = Respond - NO to the message promt. [messagecancel] desc = Respond - CANCEL to the message promt. [spy] desc = Spy mode: cycle player views in co-op. [screenshot] desc = Takes a screenshot. Saved to DOOM64nn.TGA. [viewsize] desc = View size adjustment. inf = Params: viewsize (size)\nFor example, 'viewsize 10'.\nSize can be: +, -, (num). [pause] desc = Pause the game. [god] desc = God mode. [notarget] desc = Enemies will not target the player (cheat). [noclip] desc = No movement clipping (walk through walls). [warp] desc = Warp to another map. [reveal] desc = Map cheat. inf = Params: reveal (0-4)\nModes:\n 0=nothing\n 1=show unseen\n 2=full map\n 3=map+things\n 4=show subsectors [give] desc = Gives you weapons, ammo, power-ups, etc. [kill] desc = Kill all the monsters on the map [leavemap] desc = Leave the current map. [suicide] desc = Kill yourself. What did you think? [doom64font] desc = Use the Doom64 font in the console. [startinf] desc = Start an InFine script. inf = Params: startinf (script-id)\nFor example, 'startinf coolscript'. [stopinf] desc = Stop the currently playing interlude/finale. [stopfinale] desc = Stop the currently playing interlude/finale. [spawnmobj] desc = Spawn a new mobj. [coord] desc = Print the coordinates of the consoleplayer. [makelocp] desc = Make local player. inf = Params: makelocp (playernum)\nFor example, 'makelocp 1'. [makecam] desc = Toggle camera mode. inf = Params: makecam (playernum)\nFor example, 'makecam 1'. [setlock] desc = Set camera viewlock. [lockmode] desc = Set camera viewlock mode. inf = Params: lockmode (0-1). [movefloor] desc = Move a sector's floor plane. [moveceil] desc = Move a sector's ceiling plane. [movesec] desc = Move a sector's both planes. [chatcomplete] desc = Send the chat message and exit chat mode. [chatdelete] desc = Delete a character from the chat buffer. [chatcancel] desc = Exit chat mode without sending the message. [chatsendmacro] desc = Send a chat macro. [beginchat] desc = Begin chat mode. [message] desc = Show a local game message. inf = Params: message (msg)\nFor example, 'message "this is a message"'. # # CONSOLE VARIABLES - JDOOM64 SPECIFIC # [server-game-mapcycle] desc = Map rotation sequence. [server-game-mapcycle-noexit] desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). [menu-scale] desc = Scaling for menus. [menu-flash-r] desc = Menu selection flash color, red component. [menu-flash-g] desc = Menu selection flash color, green component. [menu-flash-b] desc = Menu selection flash color, blue component. [menu-flash-speed] desc = Menu selection flash speed. [menu-turningskull] desc = 1=Menu skull turns at slider items. [menu-effect] desc = 0=Disable menu effects. 1=type-in. [menu-color-r] desc = Menu color red component. [menu-color-g] desc = Menu color green component. [menu-color-b] desc = Menu color blue component. [menu-colorb-r] desc = Menu color B red component. [menu-colorb-g] desc = Menu color B green component. [menu-colorb-b] desc = Menu color B blue component. [menu-glitter] desc = Strength of type-in glitter. [menu-fog] desc = Menu fog mode: 0=off, 1=shimmer, 2=black smoke, 3=blue vertical, 4=grey smoke, 5=dimmed. [menu-hotkeys] desc = 1=Enable hotkey navigation in the menu. [menu-shadow] desc = Menu text shadow darkness. [menu-patch-replacement] desc = Patch Replacement strings. 1=Enable external, 2=Enable built-in. [menu-slam] desc = 1=Slam the menu when opening. [menu-quick-ask] desc = 1=Ask me to confirm when quick saving/loading. [xg-dev] desc = 1=Print XG debug messages. [view-cross-type] desc = The current crosshair. [view-cross-size] desc = Crosshair size: 1=Normal. [view-cross-vitality] desc = Color the crosshair according to how near you are to death. [view-cross-r] desc = Crosshair color red component. [view-cross-g] desc = Crosshair color green component. [view-cross-b] desc = Crosshair color blue component. [view-cross-a] desc = Crosshair color alpha component. [view-filter-strength] desc = Strength of view filter. [msg-show] desc = 1=Show messages. [msg-echo] desc = 1=Echo all messages to the console. [msg-count] desc = Number of HUD messages displayed at the same time. [msg-uptime] desc = Number of seconds to keep HUD messages on screen. [msg-scale] desc = Scaling factor for HUD messages. [msg-align] desc = Alignment of HUD messages. 0 = left, 1 = center, 2 = right. [msg-color-r] desc = Color of HUD messages red component. [msg-color-g] desc = Color of HUD messages green component. [msg-color-b] desc = Color of HUD messages blue component. [msg-blink] desc = HUD messages blink for this number of tics when printed. [game-state] desc = Current game state. [game-state-map] desc = 1=Currently playing a map. [game-paused] desc = 1=Game paused. [game-skill] desc = Current skill level. [map-id] desc = Current map id. [map-name] desc = Current map name. [map-episode] desc = Current episode. [map-mission] desc = Current mission. [game-music] desc = Currently playing music (id). [map-music] desc = Music (id) for current map. [game-stats-kills] desc = Current number of kills. [game-stats-items] desc = Current number of items. [game-stats-secrets] desc = Current number of discovered secrets. [player-health] desc = Current health ammount. [player-armor] desc = Current armor ammount. [player-ammo-bullets] desc = Current number of bullets. [player-ammo-shells] desc = Current number of shells. [player-ammo-cells] desc = Current number of cells. [player-ammo-missiles] desc = Current number of missiles. [player-weapon-current] desc = Current weapon (id) [player-weapon-fist] desc = 1= Player has fist. [player-weapon-pistol] desc = 1= Player has pistol. [player-weapon-shotgun] desc = 1= Player has shotgun. [player-weapon-chaingun] desc = 1= Player has chaingun. [player-weapon-mlauncher] desc = 1= Player has missile launcher. [player-weapon-plasmarifle] desc = 1= Player has plasma rifle. [player-weapon-bfg] desc = 1= Player has BFG. [player-weapon-chainsaw] desc = 1= Player has chainsaw. [player-weapon-sshotgun] desc = 1= Player has super shotgun. [player-weapon-recoil] desc = 1= Weapon recoil active (shake/push-back). [player-key-blue] desc = 1= Player has blue keycard. [player-key-yellow] desc = 1= Player has yellow keycard. [player-key-red] desc = 1= Player has red keycard. [player-key-blueskull] desc = 1= Player has blue skullkey. [player-key-yellowskull] desc = 1= Player has yellow skullkey. [player-key-redskull] desc = 1= Player has red skullkey. [chat-beep] desc = 1= Play a beep sound when a new chat message arrives. [chat-macro0] desc = Chat macro 1. [chat-macro1] desc = Chat macro 2. [chat-macro2] desc = Chat macro 3. [chat-macro3] desc = Chat macro 4. [chat-macro4] desc = Chat macro 5. [chat-macro5] desc = Chat macro 6. [chat-macro6] desc = Chat macro 7. [chat-macro7] desc = Chat macro 8. [chat-macro8] desc = Chat macro 9. [chat-macro9] desc = Chat macro 10. [map-alpha-lines] desc = Alpha level of automap lines. [map-babykeys] desc = 1=Show keys in automap (easy skill mode only). [map-background-r] desc = Automap background color, red component. [map-background-g] desc = Automap background color, green component. [map-background-b] desc = Automap background color, blue component. [map-cheat-counter] desc = 6-bit bitfield. Show kills, items and secret counters in automap. [map-cheat-counter-scale] desc = Size factor for the counters in the automap. [map-customcolors] desc = Custom automap coloring 0=Never, 1=Auto (enabled if unchanged), 2=Always. [map-door-colors] desc = 1=Show door colors in automap. [map-door-glow] desc = Door glow thickness in the automap (with map-door-colors). [map-huddisplay] desc = 0=No HUD when in the automap 1=Current HUD display shown when in the automap 2=Always show Status Bar when in the automap [map-mobj-r] desc = Automap mobjs, red component. [map-mobj-g] desc = Automap mobjs, green component. [map-mobj-b] desc = Automap mobjs, blue component. [map-opacity] desc = Opacity of the automap. [map-open-timer] desc = Time taken to open/close the automap, in seconds. [map-pan-speed] desc = Pan speed multiplier in the automap. [map-pan-resetonopen] desc = 1= Reset automap pan location when opening the automap. [map-rotate] desc = 1=Automap turns with player, up=forward. [map-wall-r] desc = Automap walls, red component. [map-wall-g] desc = Automap walls, green component. [map-wall-b] desc = Automap walls, blue component. [map-wall-ceilingchange-r] desc = Automap ceiling height difference lines, red component. [map-wall-ceilingchange-g] desc = Automap ceiling height difference lines, green component. [map-wall-ceilingchange-b] desc = Automap ceiling height difference lines, blue component. [map-wall-floorchange-r] desc = Automap floor height difference lines, red component. [map-wall-floorchange-g] desc = Automap floor height difference lines, green component. [map-wall-floorchange-b] desc = Automap floor height difference lines, blue component. [map-wall-unseen-r] desc = Automap unseen areas, red component. [map-wall-unseen-g] desc = Automap unseen areas, green component. [map-wall-unseen-b] desc = Automap unseen areas, blue component. [map-zoom-speed] desc = Zoom in/out speed multiplier in the automap. [input-mouse-x-sensi] desc = Mouse X axis sensitivity. [input-mouse-y-sensi] desc = Mouse Y axis sensitivity. [input-joy-x] desc = X axis control: 0=None, 1=Move, 2=Turn, 3=Strafe, 4=Look. [input-joy-y] desc = Y axis control. [input-joy-z] desc = Z axis control. [input-joy-rx] desc = X rotational axis control. [input-joy-ry] desc = Y rotational axis control. [input-joy-rz] desc = Z rotational axis control. [input-joy-slider1] desc = First slider control. [input-joy-slider2] desc = Second slider control. [ctl-aim-noauto] desc = 1=Autoaiming disabled. [ctl-turn-speed] desc = The speed of turning left/right. [ctl-run] desc = 1=Always run. [ctl-use-dclick] desc = 1=Doubleclick forward/strafe equals use key. [ctl-look-speed] desc = The speed of looking up/down. [ctl-look-spring] desc = 1=Lookspring active. [ctl-look-mouse] desc = 1=Mouse look active. [ctl-look-mouse-inverse] desc = 1=Inverse mouse look Y axis. [ctl-look-pov] desc = 1=Look around using the POV hat. [ctl-look-joy] desc = 1=Joystick look active. [ctl-look-joy-inverse] desc = 1=Inverse joystick look Y axis. [ctl-look-joy-delta] desc = 1=Joystick values => look angle delta. [hud-scale] desc = Scaling for HUD info. [hud-status-size] desc = Status bar size (1-20). [hud-color-r] desc = HUD info color red component. [hud-color-g] desc = HUD info color green component. [hud-color-b] desc = HUD info color alpha component. [hud-color-a] desc = HUD info alpha value. [hud-icon-alpha] desc = HUD icon alpha value. [hud-status-alpha] desc = Status bar Alpha level. [hud-status-icon-a] desc = Status bar icons & counters Alpha level. [hud-face] desc = 1=Show Doom guy's face in HUD. [hud-health] desc = 1=Show health in HUD. [hud-armor] desc = 1=Show armor in HUD. [hud-ammo] desc = 1=Show ammo in HUD. [hud-keys] desc = 1=Show keys in HUD. [hud-power] desc = 1=Show power in HUD. [hud-frags] desc = 1=Show deathmatch frags in HUD. [hud-frags-all] desc = Debug: HUD shows all frags of all players. [hud-timer] desc = Number of seconds before the hud auto-hides. [hud-unhide-damage] desc = 1=Unhide the HUD when player receives damaged. [hud-unhide-pickup-health] desc = 1=Unhide the HUD when player collects a health item. [hud-unhide-pickup-armor] desc = 1=Unhide the HUD when player collects an armor item. [hud-unhide-pickup-powerup] desc = 1=Unhide the HUD when player collects a powerup or item of equipment. [hud-unhide-pickup-weapon] desc = 1=Unhide the HUD when player collects a weapon. [hud-unhide-pickup-ammo] desc = 1=Unhide the HUD when player collects an ammo item. [hud-unhide-pickup-key] desc = 1=Unhide the HUD when player collects a key. [menu-quitsound] desc = 1=Play a sound when quitting the game. [con-zoom] desc = Zoom factor for the console background. [view-size] desc = View window size (3-13). [hud-title] desc = 1=Show map title and author in the beginning. [hud-title-author-noiwad] desc = 1=Do not show map author if it is a map from an IWAD. [view-bob-height] desc = Scale for viewheight bobbing. [view-bob-weapon] desc = Scale for player weapon bobbing. [view-bob-weapon-switch-lower] desc = HUD weapon lowered during weapon switching. [server-game-announce-secret] desc = 1=Announce the discovery of secret areas. [server-game-skill] desc = Skill level in multiplayer games. [server-game-map] desc = Map to use in multiplayer games. [server-game-deathmatch] desc = Start multiplayers games as deathmatch. [server-game-mod-damage] desc = Enemy (mob) damage modifier, multiplayer (1..100). [server-game-mod-health] desc = Enemy (mob) health modifier, multiplayer (1..20). [server-game-mod-gravity] desc = World gravity modifier, multiplayer (-1..100). -1 = Map default. [server-game-nobfg] desc = 1=Disable BFG9000 in all netgames. [server-game-coop-nothing] desc = 1=Disable all multiplayer objects in co-op games. [server-game-coop-respawn-items] desc = 1=Respawn items in co-op games. [server-game-coop-noweapons] desc = 1=Disable multiplayer weapons during co-op games. [server-game-jump] desc = 1=Allow jumping in multiplayer games. [server-game-bfg-freeaim] desc = Allow free-aim with BFG in deathmatch. [server-game-nomonsters] desc = 1=No monsters. [server-game-respawn] desc = 1= -respawn was used. [server-game-respawn-monsters-nightmare] desc = 1=Monster respawning in Nightmare difficulty enabled. [server-game-radiusattack-nomaxz] desc = 1=ALL radius attacks are infinitely tall. [server-game-monster-meleeattack-nomaxz] desc = 1=Monster melee attacks are infinitely tall. [server-game-coop-nodamage] desc = 1=Disable player-player damage in co-op games. [server-game-noteamdamage] desc = 1=Disable team damage (player color = team). [server-game-deathmatch-killmsg] desc = 1=Announce frags in deathmatch. [player-color] desc = Player color: 0=green, 1=gray, 2=brown, 3=red. [player-eyeheight] desc = Player eye height. The original is 41. [player-move-speed] desc = Player movement speed modifier. [player-jump] desc = 1=Allow jumping. [player-jump-power] desc = Jump power (for all clients if this is the server). [player-air-movement] desc = Player movement speed while airborne. [player-autoswitch] desc = Change weapon automatically when picking one up. 1=If better 2=Always [player-autoswitch-notfiring] desc = 1=Disable automatic weapon switch if firing when picking one up. [player-autoswitch-ammo] desc = Change weapon automatically when picking up ammo. 1=If better 2=Always [player-autoswitch-berserk] desc = Change to fist automatically when picking up berserk pack [player-weapon-order0] desc = Weapon change order, slot 0. [player-weapon-order1] desc = Weapon change order, slot 1. [player-weapon-order2] desc = Weapon change order, slot 2. [player-weapon-order3] desc = Weapon change order, slot 3. [player-weapon-order4] desc = Weapon change order, slot 4. [player-weapon-order5] desc = Weapon change order, slot 5. [player-weapon-order6] desc = Weapon change order, slot 6. [player-weapon-order7] desc = Weapon change order, slot 7. [player-weapon-order8] desc = Weapon change order, slot 8. [player-weapon-nextmode] desc = 1=Use custom weapon order with Next/Previous weapon. [player-camera-noclip] desc = 1=Camera players have no movement clipping. [player-death-lookup] desc = 1=Look up when killed [game-maxskulls] desc = 1=Pain Elementals can't spawn Lost Souls if more than twenty exist (original behaviour). [game-skullsinwalls] desc = 1=Pain Elementals can spawn Lost Souls inside walls (disables DOOM bug fix). [game-anybossdeath666] desc = 1=The death of ANY boss monster triggers a 666 special (on applicable maps). [game-monsters-stuckindoors] desc = 1=Monsters can get stuck in doortracks (disables DOOM bug fix). [game-objects-hangoverledges] desc = 1=Only some objects can hang over tall ledges (enables DOOM bug fix). [game-objects-clipping] desc = 1=Use EXACTLY DOOM's clipping code (disables DOOM bug fix). [game-zombiescanexit] desc = 1=Zombie players can exit maps (disables DOOM bug fix). [game-player-wallrun-northonly] desc = 1=Players can only wallrun North (disables DOOM bug fix). [game-objects-falloff] desc = 1=Objects fall under their own weight (enables DOOM bug fix). [game-zclip] desc = 1=Allow mobjs to move under/over each other (enables DOOM bug fix). [game-corpse-sliding] desc = 1=Corpses slide down stairs and ledges (enables enhanced BOOM behaviour). [game-fastmonsters] desc = 1=Fast monsters in non-demo single player. [game-corpse-time] desc = Corpse vanish time in seconds, 0=disabled. [rend-dev-freeze-map] desc = 1=Stop updating the automap rendering lists. deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/data/lumps/0000755000175000017500000000000011357170242022101 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/data/lumps/sndcurve.lmp0000644000175000017500000000310011357170242024436 0ustar keeskees|{zyxxwwvuuuttssrrrqqqpppooonnnnmmmllllkkkkjjjjjiiiihhhhhgggggfffffeeeeedddddccccccbbbbbbaaaaaa``````_______^^^^^^]]]]]]]\\\\\\\[[[[[[[ZZZZZZZZYYYYYYYXXXXXXXXWWWWWWWWVVVVVVVVUUUUUUUUUTTTTTTTTTSSSSSSSSRRRRRRRRRQQQQQQQQQQPPPPPPPPPOOOOOOOOOONNNNNNNNNNMMMMMMMMMMLLLLLLLLLLKKKKKKKKKKJJJJJJJJJJJIIIIIIIIIIIHHHHHHHHHHHGGGGGGGGGGGFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@@?????????????>>>>>>>>>>>>>=============<<<<<<<<<<<<<;;;;;;;;;;;;;;::::::::::::::9999999999999988888888888888777777777777776666666666666665555555555555554444444444444433333333333333332222222222222221111111111111111000000000000000////////////////.................----------------,,,,,,,,,,,,,,,,+++++++++++++++++*****************)))))))))))))))))(((((((((((((((((('''''''''''''''''&&&&&&&&&&&&&&&&&&%%%%%%%%%%%%%%%%%%$$$$$$$$$$$$$$$$$$##################"""""""""""""""""""!!!!!!!!!!!!!!!!!!!  deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/data/lumps/m_therm2.lmp0000644000175000017500000000027011357170242024327 0ustar keeskees (:L^p beeelbeeej beeelbeeej beeembeeej beeejbeeej beeelbeeej beeejaeeej beeelaeeej beeelbeeejdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/data/lumps/mapmask.lmp0000644000175000017500000020000011357170242024234 0ustar keeskees             !  !!! ! !"! ! !!!!!"""#!!"""!! ""!!! !!!"" !!!!! !! "" !"! !  ! ! !!!"! !! """ ! !""!!!"!" !!!!!!!"  "#""!!! ! !! !! !!! ! ! !! !  "!! "!"" !! ! !"!!" """ !  "$&'&&%&'&'&'&&&'&&%&&&'''&((('''''&&'&&&%&(('&%&''&'(&%&'''&%%%&&&&'(%&'&&&%&%&&%%&&&('&''&(((&&'&&&&&(&&'((&&&&'''&'''(&&&%%&'(&&'&'&&&&&&&&&&'&&&'&&&''&&'&''('&&'&%&(''&('&&&&''&&&&'''&&''((&'$"    #%()+,,-,,,+,+,++++++++,*++,+,,-+,,,+++,,,+*,,-,+*+,,,,-+*+-..-+*,++*++,*+,+++,-*,+**+++--,-,+-,,-+,,,+,*,**,-,+++-++,--,+,*,+**++,++,++,,++++++,+,++,,-,+,,+,,-,,,++,-+++-,,+,,++,,+,++,++,,++-+,-,+)(&$#    "%'),./1121110101010//0001//010000/0110//1110/1120/.0/0111//012211000.////./000021/10.000011120000010/1101000/11100020/1110///0/////10010011/000/0110001111101001100///01000200/010011//00101101010001/.,*('$#!    #&&(*-/245777677666755655667755567766567665556765675654655688555666676564445545766676576466667767666665657767766577556676555655556555556775667756665666656566666766754455567665566566566745676667666655665420-+*&&&"  "%&(++-/3579:<<;;<<<;;<::;:;==<=;;;;<<<=<<<;;;;:;<<;;<:;:9;;:;==<<:;;:;<<:;::9<;9:<;;;<<<==;<===<<;;;==<<:;<<<<<<<<<<<:;<<<<;::;;;<;<<:<;;;<<:;;=<:;;<;;;;;:<:;;;;;=<;<::9::;<<;<;:;<<;;;<;<9;<<;<;<;;;;;;<;;:7530/,++($! "&)+-00259;<=?AA@@AAA@@A@???ABBABAAA@AAABAAAA@@@?AAA@@A@@A?BA@@ABBA?@@?@AAA@AA@A@@A@@@@ABBBBAABBBAA@@@BBAAA@AAAAAAAAAACAAAAAAAA@@@@A@AAAAAAAAA?@BBAA@@A@@@BB@A?@@@@@BA@A@@@?AAAA@BA@@AA@AAA@A?@AAAA@A@@BABAA@@?<:866300-)(#   %*.03568;<>ACEFFFGGGGGFFGEEEGHGFGGGFFFEFGFGFGFFFFGGFFFGFGGFHGFFFHHFEFFEGFGGGGGGFFGGFEEFFHHGGDFGHGFFEFFGGFFGFFFEFFFGFGGIHGFFFGGGGEEFFFFFHGGFGFFFGHGGGFFGFFGHHFGFEGGGFGFFFFFFFGFFGFGGEFEEFGFFFFEEFFGGFGFGHGHGFFFEC@=<<86420.)$ $*/3589;>@ACFHJJKLMLKLMKKLJKJLMKKKKJJLKIKLJLKKJJKLKKKLKLKLLKLKKKKMLJJKKJLKLKLLKLKLLKKIIKKLKKKIKLKKKKJKKKLJKLKJJJKKKKJKLMLKKKJLLLMJJJKKLKLMKKLKKKKLLLLKKKJKLLLJKKKKLLKLJKKJKKKLJJKKKJIKIJLMKJKJJJKKKKKKKLLLLLKKJJGDAA@=:9642-("  $).38;>>@CEFHKMOOPQQQQQRQPQPOOQRRRRQPOPPPPQPQPPOPPQPPRRQQQQQQQPPPPRPOPQQOQPQPQQOQPQPOQPPQRQPQQOPQPPPPPQQOQOPQPPONQPPPPOPPPPPPQPPQRQOOPOQQQQPPQPPPPPQQQQPPOPOPPOPQOOQQPQPQPOPPPQPPPPPOPQPOQRPQQQPPQOOPPOQQPQQQPONNLIGFEC@=:872,&! #)/27;60*&!   #'-37;@FIKLNPRUVXZ[]\[\\[[\Z[[\ZY\\[[]]ZZ\[Z[\\\\\\[[[[Z[]\]\\\\[[\[\[[Z]]\[[^]\[[[\[ZZ\\[[\]\\]\\[\[\[[\Z[[[\[\[[[\]\\[\[[[[[\]]]\Z[\[[\\][\]]][[Z[[[[]\\\[YZ\\\]][ZZ[\\\[[[\\[\]\\]\\\][[[[\\\\[[]\[Z[\[[\[]\]\ZXWURPPNMJGD>:5/*%   $(-28<@DJMPRSUXZZ\_`a``aa``a__`a`_aaa`ba``a`_`ba`aaa`````_aabaaaaaa``a``_aaa``cba```a`___```abaaaaa````aaa```aa``aaaabbaabbba``ababa`````baa`abaa``_````baab`_abaaaa___`a`a```aaaaa``aa`ab``````````aa`_`````aaaaa`]\ZWVUSQNKHB?:4.*$   !',16:@DHMPTWXZ\^_`deeddfdeeeddeeedfgfegffeffdefedfeeeddedeeffffffeedefefeeeeefffgedefeeedfffffffefeedecffgeeefffdffefefffegfeffeffffedeeegfeeffeeefefeeefffeeeggffeedeeeedeeeddfffeddeffefeddedddeefdeeeeefedfeedefcb`]\ZXUSPKGC>93-($  %+05:=CIMRVZ\^`bdefjkkiiljjjkljkkkjlmlklkkjkljkkjjlkkkiijjkkkkkkklkkjkkklljjkkllllkjkkklkkllkkkklkljjjihkllkkkllljkjjkjjkljlkkkkjkkllkikkkllkjkljkjlmlkkklkljklmlkkkkjkkkkikkkjikkkkjjjkkjkkijkiijjkljklkkjkkjkjkjkkjheca`^[YUOLHB>83.)"  ")/49>CGMQW[_adfgjlmorpopqqooprqppqqrrspqppopqoqqqoqrppppoorqpppppqpqqppqqqooppqqqqpqrpqqqqrqppppqqrppoooqqppqqqqqoppopoopqppppqpoppqrrpqrpqqqoprqqoqrqqrqqpqqqrrqpoppppppppqpqopqpopoppqpopqooqpppnprqrsrpoppqpopqppomjhfeda^ZTPLFA<83,& $,28=CIMRV\`dfhkmoqsuwvuvvvutuwvvvvvwwxvuvuuuvuwwwuuwuuvwuuwvuvvvvvuvwvuvvvuuuuuuvuuvwuvvvvwvuuvvvvwvvuuvwvuuwwvvuuvvuuutuvvvvvwuuvuvwwvvwvuuvttwwvtuuuvwvuvwvvwvvuuvvvvvvvvvuvuvwvuvuuwwutvvuuvvvutvwvwxwutuuvutvwvvtromljieb^XTPKE@<6/)" !&.4;AHLPVZ`dhkmprsuwz|{yzzz{zzz{{{z{{||{zzz{{{z{{{zy|{z{{||{zz{z{zzzz{|zzzz{zzz{z{z{z{{{{{|{{zz|zz{{|{{z{{{{{{{z{{{{{{{{yyz{{z{{zzzzz{|{z{{zzzzy{|zyzyzz|zz{|zz{z{{{{||{{{{{{zzz{{zz{zz{zyz{zzzz{{yy{{z{{{{z{z{{z{||{ywtqpomigc]WSOID?92+$#*18?FLQU[^cimpruwxz|~~|{wutrnmhb\WRNHB<6.'   &.5ELSZ`glpuz~xsmke^WNHB<3,$%,3:AHOV]cjpuy}xrnhaYRLE?6.&   "*074.% "*3FNW^fow}zskd[RJC81)  %.7@HOXaiqz}umf]TKC:3+" '/7@HOZcks|vog_ULD<3+" '/7@IP[ckt|wpi`XNF<2*" (19AKS]emu~ļypjaYPH=4-$  *2:BLT^fovȿzqjbZQH?6/%  "+3=DNV`gpxü|rjc[RH@8/' #,5?FNWahpzƿ}tlc\TJ?8/' $.8@GOXbiq{~vmd]UKA90' &0:AIQYcls|¹xoe^UMD;2(   (1;BJRZdmu|ûyof^VME=4+# "*3;BKS\dmw~Žyph_XOF?6-%  #+5GOV^goyɿ|skd[TKB90(  %.6>GOX_gozɿ|umd[SJB90(  %.5>FOW_hpz|umd[QIB90(  $.6=ENV_ipy}uldZQIB81) %.5FMU^hpx}umd[RKB90(  %-5>FNV^iqy~umd[SKA91)! $,4=FNU^ipz~tle[SKA92)! $,4HOW`iry}ukcZSJA91) %.6>GNWajry~wlbZRJB90( $-6>FNWaiqz}vlbZRJB90'  $-5>ENW_gqz}vmd[RKB91(  $-5>ENV^gqy¹}tme[SKA92*  $-6=FMV_gpx¹|skd[TKA82*  %.7>FNV_hpx|tke\SKB81*   %.6>GOW^gqy¸}ule\SLA70)  %.6>GOW^gqy¸~wme\ULA70(  $/7>GOW^gqy¸~wmd\ULB81( $.7>GOW^gpx~wmd[TLC:1(  #-7>GOW^hpxvlcZSLB:1)  #-7>FOW^ipyukcZSKA90)  $,6=FOW_ipz~ukc[SKA90(  $+5GPW_how}tlcZRKC91(  $-6>GPW_hpx}ukc[SKB90(  $,4=GOW`iqy}vlc\SKC:0)! $+4=FNV`ipz}uld\TJC:1)! $+4>FMW`hpz}tkd\TJC91)! #-5?FNX_hqz}ukc\SKB91(! #.6?GOX_hrz~uld[TKB:1)" $-7>GNX_gry}ume\SKC92)!  $-7=GMW_gpy}ume\SJB92)   $.6=FMW`goz~umd[TJA92)  %.6>FNX`foz~tlc[TKA81)  $,4>GOW_gqz~tlcZTLA80(  %,4?HOV_gpz~umdZTLA80) %-4?HOV_gpz¹~ume\TLA80) $-4?GOW`hqy~ume]TKB81)  $,5?GOWajrz}umd\SJC91)  #+5?GOW`irz}ume\UKB81*  #,5?GOW`hrz}ule\UKB81) $-5>GNWahpz|tkd\SJB80' %,6>FNXbhoy{tld\RIB90'  $-5>FMWahnx{umd\RJB80(! #-6>GMXahny|vme\RJC91)! $-6>GOXahpy}uke\RJC91)! %-5>GPXaiqx}tkd\SIB91)  &.6?FOX`hqx¸|tlc[SIB:0'  &-7?ENY`hqx¹|skdZRJC90'  %-7>FNY_hqxº|skdZRKC90'  $-7>GNW_hpxº|tlcZSKC91(  $-6>GNV`hoy|tlc[SJC92)  $,5>HOW_gpy~tkd[RJB92)  %,4>HOW`hqy~tld[RJC91(  &-5>HOWahqy~umd[RJC91(  &.6=GOWahpy}ume[RJB81)  %.6=FOY`hpz}tme[SJA81)  $-6=GPX`hq{}sld[TJA91)  $-6=GPW_hqz~slc[TJA90(  %-6>GOW_hqy~tlc[TJA90'  %-6?GOW_hqy~umc[TKB80(  $-5?HPX`ipx¸}vlcZSIB90( $+4=GOW_ipx¹}vmd[SI@80( $,4=FNV_ipx¹}vmd[RI@80' $-5>FNV`hpx}vmd[RJA81' $-5?GOW`hoy}ukd[TKB92( $+4=FOWahpz|ulc\RIB:2(  $+4=FOW`ipz|ukc\RIC:2) $,4=FOW`ipz|ukc[RJC80) $,4=GPW`hpz¸{tlcZSKC8/(  %-5=HPW`ipx¹|umd[SKC:0' &.6>GOW`hox~tld\RJB91( &.6>GOW`ipy~tld\RJB91)  %-5=GOW`iqy~tld\SKB91)  %-5>GNXahoy}uld[SKC91)  %-5?GNXahoz|ulc\TLC90)! %-6?GOXaipy|umd[TLB90)! %-6=GOXaipy|uld[TJA91)! %-5=GNWaipy|ukd\SIA92*! &-4>HPW`irz}vld\SIB:3*! %,5?HQY`ir{}uld\RJC:2)  $,6?GQY`irz}tkd\RKB:2(  #,7>GPX`iry}skd[SKB:1(  $-5>HOY`hqy|tlcZTLC:0( %-5?GOY`hq{}tlc[TLC91( $.5>FOX_hq|~tlcZSKB91( #.6=FNW_hq{~tlcZSKB91) #-6=FMW`hpz~tlcZSKB92)  $,5>GOW_goy~umd\SKB92(! $,5>GPX`gpz}uld\SKB81)! $-5=GPW`hpz|ukd[RJB80(! $-6=GPW`hpy|ukd[QIB90'  #-7>FPX_gqy}tkd\RJA91' $.7>FPX_gqz~umd\RJB91)  $-6=GOW_hqz}tldZSKB91)  %-5=GOW_iqz}uldZSKB91) %-5=GPW_ipz}vmd[SJB91) $-5GNV^ipx~tkcZSKA:2) $-4>GNV`ipx}tkcZSJA90(! %.4=FOW`ipx|ukdZSIA80(! &/5=FOW_hqy|tld[QIA80(  %/5=GPX_hqy}umd[QJB91) %-5=GQY_iry~ume\RKD91) %,4=GQY`iry~ule\TKD90( %,4>GPZaiqy}ume\TLD:0' $,6>GOWajqy|tmdZRJD:0( %,5>GNWajqy}tldZRJC90' %,4>GNWaiqy}tkdZRJC90' %-4>HOV`hqy}ukc[RIB:1' $,4>GOW`hrz}vld[SIA:1' $-5>FOX_iqy}uld\TKB;1' $-5?FOY_iry|ukd\TKB;0( $-5?GOY_hrz|ukd[SJB:0(   $-5?HPX_hqz}vmdZSIB90(! $-5?HPX_gqz}vmcZRJC90(  $,6?GOW_hqyº|uld[RJC90( $,6>GOW`hqx»|tke\RJC90(  %,6=FOWaipx»|tke\RJB91)! &-5FNV`irzȿ}tkd\SHA9/& %/7?GOW`iqy~ukd\SH@80( %.7?FNX`ipx~vld\RHA91) %.6>FNX_how~vle\SIA90) %.5>FOX_gnw~tle\TKA90)  %.6>GPX_how}tld\SKA91)! $-7?HPX_hqzɿ~umd\RIB:0(! %.6>HOW^gqzɿ~umd\RIB90(  %.6>GOV_gqzȿ}umd[RIB80( %,46/&  )0:CIPX`fmuz~wqibZTNF=5-$ '09AFMU\ckqw~{tof_WQLD;3,$  %.6>DJRY`ims{~xpkd\UOIA91+" $,4:@GOV]ejqw~ztmf`XQKE>6.(  "*28>EMT[biouz|wqkc]VOHA<4+&  (.5;AIPW]dlrv{|xsmha[TME>82)" $*18?EMTY_gmqv|~xsojd^XPIB;3.&    '.5GNTZ`ehmtx{~~|yvpje`[WQIB;5.(  !(.5;CKQUZ`ciotvy{~}{ywuqlea[VRLF?83+% $+28@GMPTZ_eknpsuxy{~~zxwusokfa]VQNHB<50(!  !'/582,$ $,28>DHLQV[acehjknpsuvvvvttvwutuuvwvvvvuvwvwwvuwvvvwvvuwvuvvvvvvvvuuvwvvvvwvvwwuvuuvvvvvuwxvwvwvvvwvwvwwwutvwwvvuuvvvvvwvvwuuvvxvvvuvvvvuvuuxwvvvvvuvwvwvwvvwwwxvvvwuuuvwwwvuuuvvvvwxuuwvwwvutuvwwvuuuvtwwwvuvuuuuwvutsqnligeb]YSNJD@;5.(!  "*05:?DHLQW\_acegilnopqrrpprsqpqqrrqqqrqrrqrqqqrrqrsrqrqqqrrssrqqqpqqqqqqqrqqqrqqqsrrrqrqrrrrrrqrrrrrqqrrpprsrrqpqrrrqqrqqqppqqsqqqqqqrqqqqqsrpqqqppqrrsqrqrssssrrqrrpprrqrqqqqrsqqrrpprrrrqpqpqrrrqqqqprqqqpqqqqprrponligec`]ZVOJFB<82+$  ',0684.'   "',17:4.*% $)-05<@DGKMNPRRUXZ\]\[[Z\[Z[[\\ZZ\[[[[\]\[Z[[[[[[[[\Z[Z[Z[[[ZZ[Z[\[[Y[]][[[\\\[Z[\\[Z[[[[\\[Z[[\ZZYZ[\[[[[\[Z[\Z[[[\]Z[\[ZZ[\\\[[[ZZ\\[[\\[\\[\[[\\\\\\\ZZZZZ[\[ZZ[[[ZZZ[[\\[[ZZ\\Z[][Z\]\\[[\[[\\[[[[[ZZZ[\Z[\[[\ZWUSQNMKHEA=84/*%   $)-28<@BFHIKMNPSUVXXWVVWVUVWWWUVWWVVVVWWWVVWUVVVUWWVVVUTVVVVVVVVWVVUWYXVVUVWVUVWVWVUWVVVWWVVVWVVUUVVVVVWWXWUWWVWVVWXVVWXVUVWWXVUWUTVVVWWWWWWWWVVVWXXWWVWWWVUVWVVUVVVVUVWVWVUUUUWWUVXVVWXVVXWXWWWWVVVWWUVVVWUUWXVWVSQNLIHFD@=840+'! $)-37;=BBCEHIKNPQRQQQQRQPQQQQPRRRQQQOPRSRQQPQQPPRRQQRPOQQRRQQQQQQQPRRRQQPPQQPQRQQPPPQQQRRQQQRQPOPRQRRRRQQRPPQRRQQRSQQRRQPQQRRQQSPPQQQPRRQQRPQQQQQRRQPPRRRRPQQQQPQRPQPQSQQQQPPPQQPQSQQQRQQSRRRRRRQQRRRQPQQRPPRSQQOMLIGECB@=:4/+'#   %)/369<<=>BDEHKLLKKKKLKLKKKKLLLLKLKKLLMMLKLLLJKLLKKLLJKLLMKKMKKKKLLLLLMKJKMKLLMKJLJKKKLLMKMNMKIJLLLLLKKKLKJKMLLLLMKKLKKLKKLKKMMJLMLKJLLKKLJJMKLKLLKJKLLLLLKKKMLLLJKKKMKKLMLJLKKLMMKKKLMMMLKLLNMLLLLLLJKMLKKLLLKIGFDA@><;860+'#  !%+/235789<@@AEFGGFFFGFFEFFFFGFFEFGGHEGGFFFFFFFEEFFGFFFFEFEEGEFEEFGGFFGEEFGGHGGFFFFGGFGGGFGHIGEDFFEEEDGFFFFGHGHHFFEFGEEFFGFEFGGEFGFFFEGFEEEDGGGGGFFFFGFEFFFEFGFFEFFGEFFEFHHFFFFFGGFFEEGGFEEEFHGFFEEGFFGGFGGGEFDEB@>;985420-(#  "'*,.01357:;=@AABA@ABA@@BBAAB@@@ABBBABAAAAAAAAA@ABBABAA@A@AA@BA@ABBAAB@AABBBBAAAAABBBBABAABCBA@@@A@@?BA@ABBCBCBABAAB@@ABB@@AAA@@AAAAABAAA@?ABBBBAAABBA@@AA@AA@AAABBAAA@ABBA@AAA@AAAAABABAAA@BBAA@ABAABAABBB???@=;96420.,*)%   "$')+-022467:<<=<<=<<<<<=<=<;<<<<<=;<;<=====<=<===<=<<=<<=;<==<==<=<===<;==<;<===>>=<=>=;<>==<=<<<<=>=<<<>><===>==<<<<=<<<<<<;=<<<<=<==<;;;<====<<=<===<;;<<;<==>>=<===<=<=<;;;;;<==>=<===<==<<<==<==<<=<<;:;;8632.,**)'$   ##%(+-,.014667667666667687677766756667788767777877668777667878868688866776567778976787668788866667887668878778776676766766677866776787666677887777888656766687887788867786566667788867876777667767777766656530.-)'$$#"   "$''(*+.01100100000002312221110/11121100120232101222110012111102331122000112121011010112311011011201112222222112011120/01220/201011111011123212222001212112112222312211011112221110121112110212022011201/.+(($"  !"$&&)+,,++,+++++++,,+,,,+++**+-,,++*+,-+-.-+++,,,,,+++,+*+++,--,,-,+++,--,,++,,*+**+,,+,++++*+,+++,,,,---,,,,*++,-+*++-,**,+,++++,,+,+*,--,-,,,*+,,+,++,+,,-+,-,-,+,,--,,,,,++,++,+++,,++,--+,,+,,,++*(%""   !""&'(('((('''&'('&&'('&&&%%&'('&%&'''''((''&''&'''''&&%&'''(''&''((''((&&'(('&&&&'&&&'&&&'%&'&&&('''('('&'(&'&&&'''&((%%'&&&'&''&'('&('''((''&'((&&&&''&''&'((((&''(('('&'%%'&&&&&'((&''(('('''&&''&#   !"##"##$"""!"""!!"#"!! !! !""" !"!""""#""!!!!""""" ! !"""#! !"##""""!!"#""!!!!"!!!"!! " "" !#"!!#!""!!#!" "!"#"!#" "!!!"!"" """"#!!!##""!""#!!!!"" "!!!"###!!"##""" ! !!!!!!"#"!"!"""#""" !"!                                      deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/data/lumps/menufog.lmp0000644000175000017500000001000011357170242024242 0ustar keeskees99!,,EE999JRjjJ9EE^^JE9,!,!+)ajrrrjJRE9,!!!!,,!!,E,!!!!!99J^j^JJ9Jj^JE,,,,!%Jcsrr^^J9,!!,!!!,99EJRE!!9EJjjjRR^rRJD)()!%8Mi~rRJE!,E!!9Jj^9!9J^r^I3!!!%-;`r^RE!!9JJ!JrJ!!!,JjrrjD4! 1>]j^J9!E^^99jrjE9,9,,9ERrjP4#!'#=Jqrjrj^J9!JrE,JJj^^RJRJJEJ^rZ= 3LLk}rjrr^^E!,JJ!!,,JRj^jjRREJj`8%%DuȯŨrrjJ9!,!9JJ999!!!9J^jjrjRR^jiP0 +Yĵj^E99E^rRJRJ9!!EJRrjj^^^j͹~`P3/^}j^RR^rjRJ^RJ,!,,,EJ^^^^j^rvT,>enifeif]T^rj^omo^JRR^RE,REEEJRR^jrr{PayeRIENQE;Dir^Re{qQEER^r^Rj^RJJRJjraE=>HJE9>Nw}rJJEZuZE9E^jRRR^jXD@P``UB>PZ\j^^J,!,YrmN999J^rj^RRRjurJ>HgwYIDIDEE9!!>n~`>,,9EJ^RjRRRJJRrȫrrrr^NZP54Hw˗iFA>8!!)NnN3!!,99EE9EE9999ER{˵^R^^^L484%'RkLE8,!)bfb@,!,!,,,,!!!!!,,9Jmȳj^JRRc3,9EE,9^wr{fcirU/@N`VU]mZ%$@gq]5,9EE99!!Rrwwecoz>)!EaRVYms;09emN3/49E9JJE,!!9j}~aD!9QicVkwgcfifH7;f{{reQ>)9ALU^ZYRJE9J{şuRJJ^gn`{^LEEA@P^^YTPUr~j^^jyqmR@58/7AFZw̷{VMacr7 $'0=EFELV`nriky˼jjjrrjj^RQA4,1=879LnϣjPIby<$(,3'/Qc]MBJuR7Fc}k\QJII>;qw^F@7DFHUgLABHfrr^RE;/!(Mm{wmTNi`>';joTB;DEFcsZNL\\wzwj^^jrrrj^Q>0 )MfgU7(=`fa@0-BnnjVF43Jsk]^X\JQbjJ9,,,J^rrrj^L5'#580)'4DJ@408ArjE($1^yzfXaJ99EJrrrjE,!Jjrj]P,#>HMLH98<>7Pnz{}{rM(-F^QQJE,,9E^r^J9!!EjU' 7YwniQB589)-DY`jooT((99JE9,,9^rRE!!,Js>#!4IjjJ9!99'!>I\afQ+3EJRJ,,,Jr^E,9,,,9JrjjoE-(+YsjRE99Rrj^RRJRR99EjjJD4@@L]^^J99JV5(4HJPUfzjRE9E^rjRRR^JRr^jRE!!,Rr^JJEEJJRrrjRJ^gN0P\i}jJ99Jj^RRJR^RJRrrRR9EE!!!,Jj^^JJJJJjrrg, 5Ii{mYJE^rjRJJRRJ9JR^^^R9,!!,!!!,JrrjRREJ^F-IzoaX^jjREJJRE!,9EE,!!,,!!!E^rj^rjRJJ^rͼs3Iٱkjnuor^RR^jR!!!,9,!!,9E,,J^r^JJ^^̪`;#YjY^kj^jjE,EE,,!!!EjjJJJRj͹g<Zͧz`R^wrrr^,EEE,,!,,!!RrRJEE^rU#PÜs\Ve~^^jjE!,EEE,9999!!ErJJEEERrU)Akk}rJJRj^E!!,JJE99EJ9,!^jJJEE9J^jrjoveM- AjE,9Rjj^J,!!^^^RJRRE!9JJRJJJJ^jj^c^IA7+9R^J!!,9E999!,jrjjrR,!!9JRJRR^rjrjLHADNLUbjJ,9RJ,!E^jrR!,ERRRRRjrjM5H`eVNXanrzsrqyjJ,9JJ9!,JJRj^,,J^^JEJ^jjjI7TiaMIJNIJUPM>yyyyyyyxxxxxxxxwwwwwwwwwvvBBBAAA@@@@@?????>>yyyyyxxxxxxwwwwwwwwwwwwvvvvBBBAA@??>>>yyyxxxxwwwwwwwwwwwwwwvvvvvvvBA>yxxwwwwwwwwwwwwwwwwwvvvvvvvvvvwwwwwwwwwwwwwwwwwwvvvvvvvvvvvuuwwwwwwwwwwwwwwwwwvvvvvvvvvvuuuuuwwwwwwwwwwwwwwwvvvvvvvvvvuuuuuuuuwwwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuttwwwwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttwwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttwwwwwwwwvvvvvvvuuuuuuuuuuuuttttttttttwwwwwwvvvvvvvuuuuuuuuuuuuttttttttttttwwwwwvvvvvvuuuuuuuuuuuuttttttttttttttwwwvvvvvvuuuuuuuuuuuutttttttttttttttttwwvvvvvuuuuuuuuuuuutttttttttttttttttttvvvvvuuuuuuuuuuuutttttttttttttttttsssssvvvuuuuuuuuuuuutttttttttttttttssssssssrvuuuuuuuuuuuutttttttttttttssssssssssrrruuuuuuuuuuutttttttttttssssssssssssrrrrrruuuuuuuuutttttttttssssssssssssssrrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrruuutttssssssssssssssssssssrrrrrrrrrrrrqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppnnnnnmm$$#######!!!!!! nnnnnmmmm$$$$######!!!!!! nnnnnmmmmm$$$$######!!!!!! nnnnnmmmmmm&&$$$$$####""!!!!! nnnnnmmmmmml &&&$$$$$###"""!!!!! nnnnnmmmmmmll &&&$$$$$#"""""!!!! nnnnnmmmmmmlll &$$$$$""""""!!!! nnnnnmmmmmmllll $$$$"""""""!!! nnnnnmmmmmmllllk $$"""""""!!! nnnnnmmmmmmllllkk """"""""!! nnnnnmmmmmmllllkkk """""""!! nnnnnmmmmmmllllkkkk""""""! nnnnnmmmmmmllllkkkkk"""""! nnnnmmmmmmllllkkkkkjj"""" nnnmmmmmmllllkkkkkjjjH"" nnmmmmmmllllkkkkkjjjjHGG ||mmmmmllllkkkkkjjjjiGGG |||mmmllllkkkkkjjjjiiGGFFF||||mllllkkkkkjjjjiiiGFFFF||||{lllkkkkkjjjjiiiFFFFFF||{{{{{kkkkkjjjjiiiFFFFFEED{{{{{{zzzkkjjjjFFFEEDDDD{{{{zzzzzzzzFFEEEDDDDD{{zzzzzzzzzzEEEEDDDDDCBzzzzzzzzzzzzyyEEEDDDDDCCBBBAA???zzzzzzzzzzyyyyyyEEEDDDDCCBBBAAAAA@@?????zzzzzzzzyyyyyyyyyEEDDDCCCBBBAAAA@@@?????zzzzzzyyyyyyyyyyyyDDDCCCBBBAAAA@@@???????zzzzyyyyyyyyyyyyyyDDCCCCBBBAAAA@@@???????zzyyyyyyyyyyyyyyxxxCCCCBBBAAAA@@@@???????yyyyyyyyyyyyyyxxxxxxCCCBBBAAA@@@@???????yyyyyyyyyyyyxxxxxxxxxCCBBBAAAA@@@@??????>yyyyyyyyyyxxxxxxxxxxxwwCBBBAAA@@@@@?????>>yyyyyyyyxxxxxxxxxwwwwwwwBBBAAA@@@@@?????>>>yyyyyyxxxxxxxwwwwwwwwwwvvBBAAA@@@@@????>>>yyyyxxxxxwwwwwwwwwwwwwvvvvvBAAA@@@@@@???>>>>yyxxxwwwwwwwwwwwwwwwvvvvvvvvBAA@>>>>>xwwwwwwwwwwwwwwwwwwvvvvvvvvvv>>=wwwwwwwwwwwwwwwwwvvvvvvvvvvvuu==wwwwwwwwwwwwwwwwvvvvvvvvvvuuuuuwwwwwwwwwwwwwwvvvvvvvvvvuuuuuuuuwwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuutttwwwwwwwwwwvvvvvvvvuuuuuuuuuuuuttttttwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttttwwwwwwwvvvvvvvuuuuuuuuuuuutttttttttttwwwwwvvvvvvvuuuuuuuuuuuutttttttttttttwwwwvvvvvvuuuuuuuuuuuuttttttttttttttttwwvvvvvvuuuuuuuuuuuuttttttttttttttttttwvvvvvuuuuuuuuuuuuttttttttttttttttttssvvvvuuuuuuuuuuuuttttttttttttttttsssssssvvuuuuuuuuuuuuttttttttttttttsssssssssrruuuuuuuuuuuuttttttttttttsssssssssssrrrruuuuuuuuuuttttttttttsssssssssssssrrrrrrruuuuuuuuttttttttsssssssssssssssrrrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrqquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppnnnmm#####!!!!!! nnnmmmm#####!!!!!! nnnmmmmmm####""!!!!! nnnmmmmmml$###"""!!!!! nnnmmmmmmlll$$#"""""!!!! nnnmmmmmmllll $$$""""""!!!! nnnmmmmmmllllk $$$"""""""!!! nnnmmmmmmllllkk $$"""""""!!! nnnmmmmmmllllkkk $""""""""!! nnnmmmmmmllllkkkk"""""""!! nnnmmmmmmllllkkkkk"""""""! nnnmmmmmmllllkkkkkj"""""! nnnmmmmmmllllkkkkkjjj"""" nnnmmmmmmllllkkkkkjjjj""" nnmmmmmmllllkkkkkjjjji" nmmmmmmllllkkkkkjjjjiiG mmmmmmllllkkkkkjjjjiiiGF |mmmmllllkkkkkjjjjiiiFFF|||mllllkkkkkjjjjiiiFFFF|||llllkkkkkjjjjiiihFFFF|{{{{lkkkkkjjjjiiiFFFEED{{{{{zzkkkjjjjiiiFFEEEDDD{{{zzzzzzzjjjiiiEEEEDDDD{zzzzzzzzzzziiiEEEDDDDDCCzzzzzzzzzzzyyEEDDDDCCBBBA??zzzzzzzzzyyyyyyEDDDCCCBBBAAAA@@@?????zzzzzzzyyyyyyyyyDDDCCCBBBAAAAA@@??????zzzzzyyyyyyyyyyyyDCCCCBBBAAAA@@@???????zzzyyyyyyyyyyyyyyCCCCBBBAAAA@@@@???????zyyyyyyyyyyyyyyyxxCCCBBBAAAA@@@???????>yyyyyyyyyyyyyyxxxxxCBBBAAAA@@@@??????>>yyyyyyyyyyyyxxxxxxxxCBBBAAA@@@@@?????>>>yyyyyyyyyyxxxxxxxxxwwwBBAAAA@@@@?????>>>yyyyyyyyxxxxxxxwwwwwwwwBBAAA@@@@@????>>>>yyyyyyxxxxxwwwwwwwwwwwvvvBAAA@@@@@@???>>>>>yyyyxxxwwwwwwwwwwwwwwvvvvvAAA@@@@@???>>>>>=yyxwwwwwwwwwwwwwwwwvvvvvvvvAA@@@@@@??>>>>>==wwwwwwwwwwwwwwwwwwvvvvvvvvvv@>>>>===wwwwwwwwwwwwwwwwvvvvvvvvvvvuuu>===wwwwwwwwwwwwwwwvvvvvvvvvvuuuuuu===wwwwwwwwwwwwwvvvvvvvvvvuuuuuuuuuwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuttttwwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttwwwwwwwvvvvvvvvuuuuuuuuuuuuttttttttttwwwwwwvvvvvvvuuuuuuuuuuuuttttttttttttwwwwvvvvvvvuuuuuuuuuuuutttttttttttttttwwwvvvvvvuuuuuuuuuuuutttttttttttttttttwvvvvvvuuuuuuuuuuuutttttttttttttttttttvvvvvuuuuuuuuuuuutttttttttttttttttsssssvvvuuuuuuuuuuuutttttttttttttttssssssssrvuuuuuuuuuuuutttttttttttttssssssssssrrruuuuuuuuuuutttttttttttssssssssssssrrrrrruuuuuuuuutttttttttssssssssssssssrrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrrquuutttssssssssssssssssssssrrrrrrrrrrrrqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppnmm#!!!!!! nmmmm""!!!!! nmmmmmm"""!!!!! nmmmmmmll""""!!!! nmmmmmmllll""""!!!! nmmmmmmllllkk""""""!!! nmmmmmmllllkkk """"""!!! nmmmmmmllllkkkk"""""""!! nmmmmmmllllkkkkk"""""""!! nmmmmmmllllkkkkkj"""""""! nmmmmmmllllkkkkkjj"""""! nmmmmmmllllkkkkkjjj""""" nmmmmmmllllkkkkkjjjj""" nmmmmmmllllkkkkkjjjjii"" nmmmmmmllllkkkkkjjjjiii mmmmmmllllkkkkkjjjjiii mmmmmllllkkkkkjjjjiiiFmmmmllllkkkkkjjjjiiihFF|mmllllkkkkkjjjjiiihhFFF||llllkkkkkjjjjiiihhhFFF|{{llkkkkkjjjjiiihhhFFEED{{{{zkkkkjjjjiiihhhhEEEDD{{zzzzzzjjjjiiihhhhEEDDDDzzzzzzzzzzjiiihhhEEDDDDDCzzzzzzzzzzyyihhEDDDDCCBBBzzzzzzzzyyyyyyhDDDCCBBBAAAA????zzzzzzyyyyyyyyyyDDCCCBBBAAAA@@@??????zzzzyyyyyyyyyyyyCCCBBBAAAAA@@@??????zzyyyyyyyyyyyyyyCCCBBBAAAA@@@???????>yyyyyyyyyyyyyyyxxCBBBAAAA@@@@??????>>>yyyyyyyyyyyyyxxxxxBBBAAAA@@@@?????>>>yyyyyyyyyyyxxxxxxxxxBBAAAA@@@@?????>>>>yyyyyyyyyxxxxxxxxwwwwBBAAA@@@@@????>>>>>yyyyyyyxxxxxxwwwwwwwwwAAAA@@@@@???>>>>>=yyyyyxxxxwwwwwwwwwwwwvvvAAA@@@@@???>>>>>==yyyxxwwwwwwwwwwwwwwwvvvvvA@@@@@@??>>>>>===ywwwwwwwwwwwwwwwwwvvvvvvvvA@@@@@@?>>>>>====wwwwwwwwwwwwwwwwwvvvvvvvvvvv@@@@@?>>>>>====wwwwwwwwwwwwwwwvvvvvvvvvvvuuu>>>=====wwwwwwwwwwwwwwvvvvvvvvvvuuuuuu=====wwwwwwwwwwwwvvvvvvvvvvuuuuuuuuuwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuttttwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttwwwwwwvvvvvvvvuuuuuuuuuuuuttttttttttwwwwwvvvvvvvuuuuuuuuuuuutttttttttttttwwwvvvvvvvuuuuuuuuuuuuttttttttttttttttwwvvvvvvuuuuuuuuuuuuttttttttttttttttttvvvvvvuuuuuuuuuuuuttttttttttttttttttsssvvvvuuuuuuuuuuuuttttttttttttttttsssssssvvuuuuuuuuuuuuttttttttttttttsssssssssrruuuuuuuuuuuuttttttttttttsssssssssssrrrrruuuuuuuuuuttttttttttsssssssssssssrrrrrrruuuuuuuuttttttttsssssssssssssssrrrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrqquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppsssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppmm!!!! mmmm!!!! mmmmmm"!!!! mmmmmmll"!!!! mmmmmmllll""!!! mmmmmmllllkk"""!!! mmmmmmllllkkkk""""!! mmmmmmllllkkkkkj""""!! mmmmmmllllkkkkkjj""""""! mmmmmmllllkkkkkjjj""""""! mmmmmmllllkkkkkjjjj""""" mmmmmmllllkkkkkjjjji"""" mmmmmmllllkkkkkjjjjiii""" mmmmmmllllkkkkkjjjjiii mmmmmmllllkkkkkjjjjiii mmmmmllllkkkkkjjjjiiih mmmmllllkkkkkjjjjiiihhmmmllllkkkkkjjjjiiihhhFmmllllkkkkkjjjjiiihhhF|llllkkkkkjjjjiiihhhhFE{{llkkkkkjjjjiiihhhhhEE{{{kkkkkjjjjiiihhhhhggEDDD{zzzzzzjjjjiiihhhhhggEDDDDzzzzzzzzjjiiihhhhhDDDDCzzzzzzzzzyiihhhhDDDCCBBzzzzzzzyyyyyhhhDDCCCBBBAAzzzzzyyyyyyyyyhhCCCBBBAAAAA@@@??????zzzyyyyyyyyyyyyCCBBBAAAA@@@???????zyyyyyyyyyyyyyyyCBBBAAAAA@@@??????>>yyyyyyyyyyyyyyyxBBBAAAA@@@@?????>>>>yyyyyyyyyyyyyxxxxxBBAAAA@@@@?????>>>>>yyyyyyyyyyyxxxxxxxxBAAAA@@@@????>>>>>=yyyyyyyyyxxxxxxwwwwwwAAAA@@@@@???>>>>>==yyyyyyyxxxxwwwwwwwwwwwAAA@@@@@???>>>>>===yyyyyxxwwwwwwwwwwwwwvvvAA@@@@@??>>>>>====yyywwwwwwwwwwwwwwwwvvvvvv@@@@@@?>>>>>====wwwwwwwwwwwwwwwwwvvvvvvvvv@@@@@?>>>>>=====wwwwwwwwwwwwwwwwvvvvvvvvvvv@@@@@>>>>>======wwwwwwwwwwwwwwvvvvvvvvvvvuuu@@@>>>>>======>======yyyyyyyyyyyyyyyBBBAAAA@@@@?????>>>yyyyyyyyyyyyyyxxBAAAAA@@@?????>>>>yyyyyyyyyyyyxxxxxBAAAA@@@@????>>>>>=yyyyyyyyyyxxxxxxxwAAAA@@@@@???>>>>>===yyyyyyyyxxxxxwwwwwwwAAA@@@@???>>>>>====yyyyyyxxxwwwwwwwwwwwwA@@@@@??>>>>>====yyyyxwwwwwwwwwwwwwwvvvv@@@@@@?>>>>>=====yywwwwwwwwwwwwwwwwvvvvvv@@@@?>>>>>======wwwwwwwwwwwwwwwwvvvvvvvvv@@@@>>>>>======>>>>======<>>>======<<>>>======<<======<<<>yyyyyyyyyyyyyyBAAAAA@@@?????>>>yyyyyyyyyyyyyyxBAAAA@@@@????>>>>>yyyyyyyyyyyyxxxxAAAA@@@@???>>>>>==yyyyyyyyyyxxxxxwwAA@@@@???>>>>>====yyyyyyyyxxxwwwwwwwwA@@@@@??>>>>>=====yyyyyyxwwwwwwwwwwwww@@@@@?>>>>>======yyyywwwwwwwwwwwwwwvvvv@@@@?>>>>>======<>>>>======<>>>>======<<>>>======<<>>>======<<<>>======<<<>======<<<<>>>yyyyyyyyyyyyyxgAAAA@@@@???>>>>>=yyyyyyyyyyyxxxxAA@@@@???>>>>>===yyyyyyyyyxxxxwwwwA@@@@??>>>>>=====yyyyyyyxxwwwwwwwwww@@@@@?>>>>>======<>>>>======<<>>>>======<<>>>>======<<<>>>======<<<>>>======<<<<>>======<<<<>======<<<<<======<<<<<>>>>==yyyyyyyyyyyxxxfffffee@@@@??>>>>>====yyyyyyyyyxxwwwwwe@@@@?>>>>>======yyyyyyywwwwwwwwwww@@@?>>>>>======<<>>>>======<<<>>>>======<<<>>>======<<<<>>>======<<<<>>======<<<<<>======<<<<<<;wwwwwwwwwvvvvvvvvvvuuuuuuuu======<<<<<<;wwwwwwwvvvvvvvvvvuuuuuuuuuuu=====<<<<<<;;wwwwwwvvvvvvvvvuuuuuuuuuuuutt====<<<<<<;;;wwwwvvvvvvvvvuuuuuuuuuuuutttttt===<<<<<<;;;wwwvvvvvvvvuuuuuuuuuuuutttttttttt<<<;;;;wvvvvvvvvuuuuuuuuuuuutttttttttttttt;;;vvvvvvvuuuuuuuuuuuutttttttttttttttttvvvvvuuuuuuuuuuuutttttttttttttttttssvvvuuuuuuuuuuuutttttttttttttttsssssssvuuuuuuuuuuuutttttttttttttssssssssssrruuuuuuuuuuutttttttttttssssssssssssrrrrrruuuuuuuuutttttttttssssssssssssssrrrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrrquuutttssssssssssssssssssssrrrrrrrrrrrrqqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppppllkklkkkklkkkkkjjlkkkkkjjjjlkkkkkjjjjiiilkkkkkjjjjiiilkkkkkjjjjiiihhhlkkkkkjjjjiiihhhhhgglkkkkkjjjjiiihhhhhggglkkkkkjjjjiiihhhhhgggglkkkkkjjjjiiihhhhhggggflkkkkkjjjjiiihhhhhggggffflkkkkkjjjjiiihhhhhggggfffflkkkkkjjjjiiihhhhhggggffffkkkkkjjjjiiihhhhhggggfffffkkkkjjjjiiihhhhhggggfffffeekkkjjjjiiihhhhhggggfffffeeekkjjjjiiihhhhhggggfffffeeeekjjjjiiihhhhhggggfffffeeeeezzjjiiihhhhhggggfffffeeeeeezzyyiihhhhhggggfffffeeeeeedyyyyyyhhhhhggggfffffeeeeeeddyyyyyyyyhhhhggggfffffeeeeeedyyyyyyyyyyhggggfffffeeeeeeyyyyyyyyyyygggfffffeeeeeeyyyyyyyyyyxxgfffffeeeee@@>>>=====yyyyyyyyxwwwwwwffeeeee@@?>>>>>======>>>>======<<>>>>======<<<<>>>======<<<<<>>======<<<<<>======<<<<<<;wwwwwwwwwwwvvvvvvvvvvvu>======<<<<<<;;wwwwwwwwwvvvvvvvvvvvuuuuu======<<<<<<;;wwwwwwwwvvvvvvvvvvuuuuuuuu=====<<<<<<;;;wwwwwwvvvvvvvvvvuuuuuuuuuuu====<<<<<<;;;;wwwwwvvvvvvvvvuuuuuuuuuuuuttt==<<<<<<;;;;wwwvvvvvvvvvuuuuuuuuuuuuttttttt=<<<<<<;;;;;wwvvvvvvvvuuuuuuuuuuuuttttttttttt<<<<<<;;;;;;vvvvvvvvuuuuuuuuuuuutttttttttttttt;;;;;;:vvvvvvuuuuuuuuuuuuttttttttttttttttt;;;::vvvvuuuuuuuuuuuuttttttttttttttttssss:::vvuuuuuuuuuuuuttttttttttttttsssssssss::uuuuuuuuuuuuttttttttttttsssssssssssrrruuuuuuuuuuttttttttttsssssssssssssrrrrrruuuuuuuuttttttttsssssssssssssssrrrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrqqquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppsssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppsssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppsssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppsssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppppkkkkkkkkjjkkkkjjjjkkkkjjjjiiikkkkjjjjiiikkkkjjjjiiihhhkkkkjjjjiiihhhhhgggkkkkjjjjiiihhhhhggggfkkkkjjjjiiihhhhhggggffkkkkjjjjiiihhhhhggggfffkkkkjjjjiiihhhhhggggffffkkkkjjjjiiihhhhhggggfffffkkkkjjjjiiihhhhhggggfffffekkkkjjjjiiihhhhhggggfffffeeekkkjjjjiiihhhhhggggfffffeeeekkjjjjiiihhhhhggggfffffeeeeekjjjjiiihhhhhggggfffffeeeeeejjjjiiihhhhhggggfffffeeeeeedjjjiiihhhhhggggfffffeeeeeeddzyiiihhhhhggggfffffeeeeeedddyyyyyhhhhhggggfffffeeeeeeddddyyyyyyyhhhhggggfffffeeeeeeddddcyyyyyyyyhhggggfffffeeeeeeddddccyyyyyyyyyggggfffffeeeeeeddddccyyyyyyyyyyxgfffffeeeeeeddddyyyyyyyywwwwwfffeeeeeeddd=====>>>>======<<>>>======<<<<>>======<<<<<<;wwwwwwwwwwwwwvvvvvvvv>>======<<<<<<;;wwwwwwwwwwwvvvvvvvvvvv======<<<<<<;;;wwwwwwwwwwvvvvvvvvvvvuu=====<<<<<<;;;wwwwwwwwvvvvvvvvvvvuuuuu====<<<<<<;;;;wwwwwwwvvvvvvvvvvuuuuuuuu===<<<<<<;;;;;wwwwwvvvvvvvvvvuuuuuuuuuuu==<<<<<<;;;;;wwwwvvvvvvvvvuuuuuuuuuuuuttt<<<<<<;;;;;;wwvvvvvvvvvuuuuuuuuuuuuttttttt<<<<<;;;;;;:wvvvvvvvvuuuuuuuuuuuuttttttttttt<<<<;;;;;;::vvvvvvvuuuuuuuuuuuuttttttttttttttt<<<;;;;;;:::vvvvvuuuuuuuuuuuuttttttttttttttttts;;;;::::vvvuuuuuuuuuuuutttttttttttttttssssss;:::::vuuuuuuuuuuuutttttttttttttssssssssss::::uuuuuuuuuuutttttttttttssssssssssssrrrruuuuuuuuutttttttttssssssssssssssrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrrquuutttssssssssssssssssssssrrrrrrrrrrrrqqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppppssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppppppkkkjjkkjjjjkkjjjjiiikkjjjjiiikkjjjjiiihhhhkkjjjjiiihhhhhgggkkjjjjiiihhhhhggggfffkkjjjjiiihhhhhggggffffkkjjjjiiihhhhhggggfffffkkjjjjiiihhhhhggggfffffekkjjjjiiihhhhhggggfffffeekkjjjjiiihhhhhggggfffffeeekkjjjjiiihhhhhggggfffffeeeekkjjjjiiihhhhhggggfffffeeeeekjjjjiiihhhhhggggfffffeeeeeedjjjjiiihhhhhggggfffffeeeeeeddjjjiiihhhhhggggfffffeeeeeedddjjiiihhhhhggggfffffeeeeeeddddjiiihhhhhggggfffffeeeeeeddddcyyyhhhhhggggfffffeeeeeeddddccyyyyyhhhhhggggfffffeeeeeeddddcccyyyyyyyhhggggfffffeeeeeeddddccccyyyyyyyyggggfffffeeeeeeddddccccyyyyyyyyyggfffffeeeeeeddddcccyyyyyyywwwwwfffeeeeeeddddcccyyyywwwwwwwwwweeeeeeddddccc===<<>======<<<<======<<<<<<;wwwwwwwwwwwwvvvvvvvvdcc======<<<<<<;;;wwwwwwwwwwvvvvvvvvvvv=====<<<<<<;;;;wwwwwwwwwvvvvvvvvvvvuu====<<<<<<;;;;;wwwwwwwvvvvvvvvvvvuuuuu==<<<<<<;;;;;;wwwwwwvvvvvvvvvvuuuuuuuu=<<<<<<;;;;;;:wwwwvvvvvvvvvvuuuuuuuuuuuu<<<<<<;;;;;;::wwwvvvvvvvvvuuuuuuuuuuuuttt<<<<<;;;;;;:::wvvvvvvvvvuuuuuuuuuuuuttttttt<<<<;;;;;;::::vvvvvvvvuuuuuuuuuuuuttttttttttt<<;;;;;;:::::vvvvvvuuuuuuuuuuuuttttttttttttttt<;;;;;;::::::vvvvuuuuuuuuuuuuttttttttttttttttss;;;;;;::::::vvuuuuuuuuuuuuttttttttttttttsssssss;;;::::::uuuuuuuuuuuuttttttttttttsssssssssssr::::::uuuuuuuuuuttttttttttsssssssssssssrrrr:uuuuuuuuttttttttsssssssssssssssrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppsssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppsssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppsssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppsssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppppsssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppppppkjjkjjjjkjjjjiiikjjjjiiikjjjjiiihhhhkjjjjiiihhhhhgggkjjjjiiihhhhhggggffffkjjjjiiihhhhhggggfffffekjjjjiiihhhhhggggfffffeekjjjjiiihhhhhggggfffffeeekjjjjiiihhhhhggggfffffeeeekjjjjiiihhhhhggggfffffeeeeekjjjjiiihhhhhggggfffffeeeeeekjjjjiiihhhhhggggfffffeeeeeeddjjjjiiihhhhhggggfffffeeeeeedddjjjiiihhhhhggggfffffeeeeeeddddjjiiihhhhhggggfffffeeeeeeddddcjiiihhhhhggggfffffeeeeeeddddcciiihhhhhggggfffffeeeeeeddddcccyihhhhhggggfffffeeeeeeddddccccyyyyhhhhhggggfffffeeeeeeddddcccccyyyyyhhhggggfffffeeeeeeddddcccccbbyyyyyyyggggfffffeeeeeeddddcccccbbyyyyyyyyggfffffeeeeeeddddcccccbyyyyyywwwwffffeeeeeeddddcccccyyywwwwwwwwwfeeeeeeddddcccccwwwwwwwwwwwwwweeeeddddcccc<<< *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_items.c: */ // HEADER FILES ------------------------------------------------------------ #include #include "jdoom64.h" #include "g_defs.h" #include "p_player.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- /** * Default weapon definitions. * These are used if other (external) definitions are not found. */ weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES] = { { { // fist GM_ANY, {0, 0, 0, 0}, // type: clip | shell | cell | misl {0, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_PUNCHUP, S_PUNCHDOWN, S_PUNCH, S_PUNCH1, S_NULL }, 0, // raise sound id 0 // ready sound } }, { { // pistol GM_ANY, {1, 0, 0, 0}, // type: clip | shell | cell | misl {1, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_PISTOLUP, S_PISTOLDOWN, S_PISTOL, S_PISTOL1, S_PISTOLFLASH }, 0, // raise sound id 0 // ready sound } }, { { // shotgun GM_ANY, {0, 1, 0, 0}, // type: clip | shell | cell | misl {0, 1, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_SGUNUP, S_SGUNDOWN, S_SGUN, S_SGUN1, S_SGUNFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // chaingun GM_ANY, {1, 0, 0, 0}, // type: clip | shell | cell | misl {1, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_CHAINUP, S_CHAINDOWN, S_CHAIN, S_CHAIN1, S_CHAINFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // missile launcher GM_ANY, {0, 0, 0, 1}, // type: clip | shell | cell | misl {0, 0, 0, 1}, // pershot: clip | shell | cell | misl false, // autofire when raised if fire held { S_MISSILEUP, S_MISSILEDOWN, S_MISSILE, S_MISSILE1, S_MISSILEFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // plasma rifle GM_ANY, {0, 0, 1, 0}, // type: clip | shell | cell | misl {0, 0, 1, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_PLASMAUP, S_PLASMADOWN, S_PLASMA, S_PLASMA1, S_PLASMASHOCK1 }, 0, // raise sound id 0 // ready sound } }, { { // bfg 9000 GM_ANY, {0, 0, 1, 0}, // type: clip | shell | cell | misl {0, 0, 40, 0}, // pershot: clip | shell | cell | misl false, // autofire when raised if fire held { S_BFGUP, S_BFGDOWN, S_BFG, S_BFG1, S_BFGFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // chainsaw GM_ANY, {0, 0, 0, 0}, // type: clip | shell | cell | misl {0, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_SAWUP, S_SAWDOWN, S_SAW, S_SAW1, S_NULL }, SFX_SAWUP, // raise sound id SFX_SAWIDL // ready sound } }, { { // super shotgun GM_ANY, {0, 1, 0, 0}, // type: clip | shell | cell | misl {0, 2, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_DSGUNUP, S_DSGUNDOWN, S_DSGUN, S_DSGUN1, S_DSGUNFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // UNMAKER GM_ANY, {0, 0, 1, 0}, // type: clip | shell | cell | misl {0, 0, 1, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_UNKFUP, S_UNKFDOWN, S_UNKF, S_UNKF1, S_UNKFLASH1 }, 0, // raise sound id 0 // ready sound } } }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static const char* ammoTypeNames[NUM_AMMO_TYPES] = {"clip", "shell", "cell", "misl"}; // CODE -------------------------------------------------------------------- /** * Initialize ammo info. */ void P_InitAmmoInfo(void) { uint i; char buf[40]; for(i = 0; i < NUM_AMMO_TYPES; ++i) { // Max ammo. sprintf(buf, "Player|Max ammo|%s", ammoTypeNames[i]); GetDefInt(buf, &maxAmmo[i]); // Clip ammo. sprintf(buf, "Player|Clip ammo|%s", ammoTypeNames[i]); GetDefInt(buf, &clipAmmo[i]); } } /** * Initialize weapon info. */ void P_InitWeaponInfo(void) { #define WPINF "Weapon Info|" int i; int pclass = PCLASS_PLAYER; char buf[80]; char* data; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { //// \todo Only allows for one type of ammo per weapon. sprintf(buf, WPINF "%i|Type", i); if(Def_Get(DD_DEF_VALUE, buf, &data)) { memset(weaponInfo[i][pclass].mode[0].ammoType, 0, sizeof(int) * NUM_AMMO_TYPES); memset(weaponInfo[i][pclass].mode[0].perShot, 0, sizeof(int) * NUM_AMMO_TYPES); if(stricmp(data, "noammo")) { ammotype_t k; for(k = 0; k < NUM_AMMO_TYPES; ++k) { if(!stricmp(data, ammoTypeNames[k])) { weaponInfo[i][pclass].mode[0].ammoType[k] = true; sprintf(buf, WPINF "%i|Per shot", i); GetDefInt(buf, &weaponInfo[i][pclass].mode[0].perShot[k]); break; } } } } // end todo sprintf(buf, WPINF "%i|Up", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_UP]); sprintf(buf, WPINF "%i|Down", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_DOWN]); sprintf(buf, WPINF "%i|Ready", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_READY]); sprintf(buf, WPINF "%i|Atk", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_ATTACK]); sprintf(buf, WPINF "%i|Flash", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_FLASH]); sprintf(buf, WPINF "%i|Static", i); weaponInfo[i][pclass].mode[0].staticSwitch = GetDefInt(buf, 0); } /// \todo Get this info from values. P_InitWeaponSlots(); P_SetWeaponSlot(WT_FIRST, 1); P_SetWeaponSlot(WT_EIGHTH, 1); P_SetWeaponSlot(WT_SECOND, 2); P_SetWeaponSlot(WT_THIRD, 3); if(gameMode == commercial) P_SetWeaponSlot(WT_NINETH, 3); P_SetWeaponSlot(WT_FOURTH, 4); P_SetWeaponSlot(WT_FIFTH, 5); P_SetWeaponSlot(WT_SIXTH, 6); P_SetWeaponSlot(WT_SEVENTH, 7); P_SetWeaponSlot(WT_TENTH, 8); #undef WPINF } void P_InitPlayerValues(player_t *p) { int i; char buf[40]; GetDefInt("Player|Health", &p->health); GetDefInt("Player|Weapon", (int *) &p->readyWeapon); p->pendingWeapon = p->readyWeapon; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { sprintf(buf, "Weapon Info|%i|Owned", i); GetDefInt(buf, (int *) &p->weapons[i].owned); } for(i = 0; i < NUM_AMMO_TYPES; ++i) { sprintf(buf, "Player|Init ammo|%s", ammoTypeNames[i]); GetDefInt(buf, &p->ammo[i].owned); } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/m_random.c0000644000175000017500000000725111357170242022564 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.c: Random number LUT. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static int rndIndex = 0; static int prndIndex = 0; // Returns a 0-255 number static unsigned char rndTable[256] = { 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36, 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242, 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0, 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235, 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113, 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75, 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196, 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113, 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241, 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224, 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226, 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136, 120, 163, 236, 249 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * \note The returned value is calculated deterministically. * * @return A pseudo-random number from the table. */ byte P_Random(void) { prndIndex = (prndIndex + 1) & 0xff; return rndTable[prndIndex]; } /** * \note The returned value is NOT calculated deterministically. * * @return A pseudo-random number from the table. */ byte M_Random(void) { rndIndex = (rndIndex + 1) & 0xff; return rndTable[rndIndex]; } /** * Resets the seed for the random number generator. */ void M_ResetRandom(void) { rndIndex = prndIndex = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/tables.c0000644000175000017500000042273111357170242022246 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * tables.c: Lookup tables. * * In the order of appearance: * * int finetangent[4096] - Tangens LUT. * Should work with BAM fairly well (12 of 16bit, * effectively, by shifting). * * int finesine[10240] - Sine lookup. * Guess what, serves as cosine, too. * Remarkable thing is, how to use BAMs with this? * * int tantoangle[2049] - ArcTan LUT, * maps tan(angle) to angle fast. Gotta search. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // finecosine and finesine use the same array of values. fixed_t *finecosine = &finesine[FINEANGLES / 4]; int finetangent[4096] = { -170910304, -56965752, -34178904, -24413316, -18988036, -15535599, -13145455, -11392683, -10052327, -8994149, -8137527, -7429880, -6835455, -6329090, -5892567, -5512368, -5178251, -4882318, -4618375, -4381502, -4167737, -3973855, -3797206, -3635590, -3487165, -3350381, -3223918, -3106651, -2997613, -2895966, -2800983, -2712030, -2628549, -2550052, -2476104, -2406322, -2340362, -2277919, -2218719, -2162516, -2109087, -2058233, -2009771, -1963536, -1919378, -1877161, -1836758, -1798063, -1760956, -1725348, -1691149, -1658278, -1626658, -1596220, -1566898, -1538632, -1511367, -1485049, -1459630, -1435065, -1411312, -1388330, -1366084, -1344537, -1323658, -1303416, -1283783, -1264730, -1246234, -1228269, -1210813, -1193846, -1177345, -1161294, -1145673, -1130465, -1115654, -1101225, -1087164, -1073455, -1060087, -1047046, -1034322, -1021901, -1009774, -997931, -986361, -975054, -964003, -953199, -942633, -932298, -922186, -912289, -902602, -893117, -883829, -874730, -865817, -857081, -848520, -840127, -831898, -823827, -815910, -808143, -800521, -793041, -785699, -778490, -771411, -764460, -757631, -750922, -744331, -737853, -731486, -725227, -719074, -713023, -707072, -701219, -695462, -689797, -684223, -678737, -673338, -668024, -662792, -657640, -652568, -647572, -642651, -637803, -633028, -628323, -623686, -619117, -614613, -610174, -605798, -601483, -597229, -593033, -588896, -584815, -580789, -576818, -572901, -569035, -565221, -561456, -557741, -554074, -550455, -546881, -543354, -539870, -536431, -533034, -529680, -526366, -523094, -519861, -516667, -513512, -510394, -507313, -504269, -501261, -498287, -495348, -492443, -489571, -486732, -483925, -481150, -478406, -475692, -473009, -470355, -467730, -465133, -462565, -460024, -457511, -455024, -452564, -450129, -447720, -445337, -442978, -440643, -438332, -436045, -433781, -431540, -429321, -427125, -424951, -422798, -420666, -418555, -416465, -414395, -412344, -410314, -408303, -406311, -404338, -402384, -400448, -398530, -396630, -394747, -392882, -391034, -389202, -387387, -385589, -383807, -382040, -380290, -378555, -376835, -375130, -373440, -371765, -370105, -368459, -366826, -365208, -363604, -362013, -360436, -358872, -357321, -355783, -354257, -352744, -351244, -349756, -348280, -346816, -345364, -343924, -342495, -341078, -339671, -338276, -336892, -335519, -334157, -332805, -331464, -330133, -328812, -327502, -326201, -324910, -323629, -322358, -321097, -319844, -318601, -317368, -316143, -314928, -313721, -312524, -311335, -310154, -308983, -307819, -306664, -305517, -304379, -303248, -302126, -301011, -299904, -298805, -297714, -296630, -295554, -294485, -293423, -292369, -291322, -290282, -289249, -288223, -287204, -286192, -285186, -284188, -283195, -282210, -281231, -280258, -279292, -278332, -277378, -276430, -275489, -274553, -273624, -272700, -271782, -270871, -269965, -269064, -268169, -267280, -266397, -265519, -264646, -263779, -262917, -262060, -261209, -260363, -259522, -258686, -257855, -257029, -256208, -255392, -254581, -253774, -252973, -252176, -251384, -250596, -249813, -249035, -248261, -247492, -246727, -245966, -245210, -244458, -243711, -242967, -242228, -241493, -240763, -240036, -239314, -238595, -237881, -237170, -236463, -235761, -235062, -234367, -233676, -232988, -232304, -231624, -230948, -230275, -229606, -228941, -228279, -227621, -226966, -226314, -225666, -225022, -224381, -223743, -223108, -222477, -221849, -221225, -220603, -219985, -219370, -218758, -218149, -217544, -216941, -216341, -215745, -215151, -214561, -213973, -213389, -212807, -212228, -211652, -211079, -210509, -209941, -209376, -208815, -208255, -207699, -207145, -206594, -206045, -205500, -204956, -204416, -203878, -203342, -202809, -202279, -201751, -201226, -200703, -200182, -199664, -199149, -198636, -198125, -197616, -197110, -196606, -196105, -195606, -195109, -194614, -194122, -193631, -193143, -192658, -192174, -191693, -191213, -190736, -190261, -189789, -189318, -188849, -188382, -187918, -187455, -186995, -186536, -186080, -185625, -185173, -184722, -184274, -183827, -183382, -182939, -182498, -182059, -181622, -181186, -180753, -180321, -179891, -179463, -179037, -178612, -178190, -177769, -177349, -176932, -176516, -176102, -175690, -175279, -174870, -174463, -174057, -173653, -173251, -172850, -172451, -172053, -171657, -171263, -170870, -170479, -170089, -169701, -169315, -168930, -168546, -168164, -167784, -167405, -167027, -166651, -166277, -165904, -165532, -165162, -164793, -164426, -164060, -163695, -163332, -162970, -162610, -162251, -161893, -161537, -161182, -160828, -160476, -160125, -159775, -159427, -159079, -158734, -158389, -158046, -157704, -157363, -157024, -156686, -156349, -156013, -155678, -155345, -155013, -154682, -154352, -154024, -153697, -153370, -153045, -152722, -152399, -152077, -151757, -151438, -151120, -150803, -150487, -150172, -149859, -149546, -149235, -148924, -148615, -148307, -148000, -147693, -147388, -147084, -146782, -146480, -146179, -145879, -145580, -145282, -144986, -144690, -144395, -144101, -143808, -143517, -143226, -142936, -142647, -142359, -142072, -141786, -141501, -141217, -140934, -140651, -140370, -140090, -139810, -139532, -139254, -138977, -138701, -138426, -138152, -137879, -137607, -137335, -137065, -136795, -136526, -136258, -135991, -135725, -135459, -135195, -134931, -134668, -134406, -134145, -133884, -133625, -133366, -133108, -132851, -132594, -132339, -132084, -131830, -131576, -131324, -131072, -130821, -130571, -130322, -130073, -129825, -129578, -129332, -129086, -128841, -128597, -128353, -128111, -127869, -127627, -127387, -127147, -126908, -126669, -126432, -126195, -125959, -125723, -125488, -125254, -125020, -124787, -124555, -124324, -124093, -123863, -123633, -123404, -123176, -122949, -122722, -122496, -122270, -122045, -121821, -121597, -121374, -121152, -120930, -120709, -120489, -120269, -120050, -119831, -119613, -119396, -119179, -118963, -118747, -118532, -118318, -118104, -117891, -117678, -117466, -117254, -117044, -116833, -116623, -116414, -116206, -115998, -115790, -115583, -115377, -115171, -114966, -114761, -114557, -114354, -114151, -113948, -113746, -113545, -113344, -113143, -112944, -112744, -112546, -112347, -112150, -111952, -111756, -111560, -111364, -111169, -110974, -110780, -110586, -110393, -110200, -110008, -109817, -109626, -109435, -109245, -109055, -108866, -108677, -108489, -108301, -108114, -107927, -107741, -107555, -107369, -107184, -107000, -106816, -106632, -106449, -106266, -106084, -105902, -105721, -105540, -105360, -105180, -105000, -104821, -104643, -104465, -104287, -104109, -103933, -103756, -103580, -103404, -103229, -103054, -102880, -102706, -102533, -102360, -102187, -102015, -101843, -101671, -101500, -101330, -101159, -100990, -100820, -100651, -100482, -100314, -100146, -99979, -99812, -99645, -99479, -99313, -99148, -98982, -98818, -98653, -98489, -98326, -98163, -98000, -97837, -97675, -97513, -97352, -97191, -97030, -96870, -96710, -96551, -96391, -96233, -96074, -95916, -95758, -95601, -95444, -95287, -95131, -94975, -94819, -94664, -94509, -94354, -94200, -94046, -93892, -93739, -93586, -93434, -93281, -93129, -92978, -92826, -92675, -92525, -92375, -92225, -92075, -91926, -91777, -91628, -91480, -91332, -91184, -91036, -90889, -90742, -90596, -90450, -90304, -90158, -90013, -89868, -89724, -89579, -89435, -89292, -89148, -89005, -88862, -88720, -88577, -88435, -88294, -88152, -88011, -87871, -87730, -87590, -87450, -87310, -87171, -87032, -86893, -86755, -86616, -86479, -86341, -86204, -86066, -85930, -85793, -85657, -85521, -85385, -85250, -85114, -84980, -84845, -84710, -84576, -84443, -84309, -84176, -84043, -83910, -83777, -83645, -83513, -83381, -83250, -83118, -82987, -82857, -82726, -82596, -82466, -82336, -82207, -82078, -81949, -81820, -81691, -81563, -81435, -81307, -81180, -81053, -80925, -80799, -80672, -80546, -80420, -80294, -80168, -80043, -79918, -79793, -79668, -79544, -79420, -79296, -79172, -79048, -78925, -78802, -78679, -78557, -78434, -78312, -78190, -78068, -77947, -77826, -77705, -77584, -77463, -77343, -77223, -77103, -76983, -76864, -76744, -76625, -76506, -76388, -76269, -76151, -76033, -75915, -75797, -75680, -75563, -75446, -75329, -75213, -75096, -74980, -74864, -74748, -74633, -74517, -74402, -74287, -74172, -74058, -73944, -73829, -73715, -73602, -73488, -73375, -73262, -73149, -73036, -72923, -72811, -72699, -72587, -72475, -72363, -72252, -72140, -72029, -71918, -71808, -71697, -71587, -71477, -71367, -71257, -71147, -71038, -70929, -70820, -70711, -70602, -70494, -70385, -70277, -70169, -70061, -69954, -69846, -69739, -69632, -69525, -69418, -69312, -69205, -69099, -68993, -68887, -68781, -68676, -68570, -68465, -68360, -68255, -68151, -68046, -67942, -67837, -67733, -67629, -67526, -67422, -67319, -67216, -67113, -67010, -66907, -66804, -66702, -66600, -66498, -66396, -66294, -66192, -66091, -65989, -65888, -65787, -65686, -65586, -65485, -65385, -65285, -65185, -65085, -64985, -64885, -64786, -64687, -64587, -64488, -64389, -64291, -64192, -64094, -63996, -63897, -63799, -63702, -63604, -63506, -63409, -63312, -63215, -63118, -63021, -62924, -62828, -62731, -62635, -62539, -62443, -62347, -62251, -62156, -62060, -61965, -61870, -61775, -61680, -61585, -61491, -61396, -61302, -61208, -61114, -61020, -60926, -60833, -60739, -60646, -60552, -60459, -60366, -60273, -60181, -60088, -59996, -59903, -59811, -59719, -59627, -59535, -59444, -59352, -59261, -59169, -59078, -58987, -58896, -58805, -58715, -58624, -58534, -58443, -58353, -58263, -58173, -58083, -57994, -57904, -57815, -57725, -57636, -57547, -57458, -57369, -57281, -57192, -57104, -57015, -56927, -56839, -56751, -56663, -56575, -56487, -56400, -56312, -56225, -56138, -56051, -55964, -55877, -55790, -55704, -55617, -55531, -55444, -55358, -55272, -55186, -55100, -55015, -54929, -54843, -54758, -54673, -54587, -54502, -54417, -54333, -54248, -54163, -54079, -53994, -53910, -53826, -53741, -53657, -53574, -53490, -53406, -53322, -53239, -53156, -53072, -52989, -52906, -52823, -52740, -52657, -52575, -52492, -52410, -52327, -52245, -52163, -52081, -51999, -51917, -51835, -51754, -51672, -51591, -51509, -51428, -51347, -51266, -51185, -51104, -51023, -50942, -50862, -50781, -50701, -50621, -50540, -50460, -50380, -50300, -50221, -50141, -50061, -49982, -49902, -49823, -49744, -49664, -49585, -49506, -49427, -49349, -49270, -49191, -49113, -49034, -48956, -48878, -48799, -48721, -48643, -48565, -48488, -48410, -48332, -48255, -48177, -48100, -48022, -47945, -47868, -47791, -47714, -47637, -47560, -47484, -47407, -47331, -47254, -47178, -47102, -47025, -46949, -46873, -46797, -46721, -46646, -46570, -46494, -46419, -46343, -46268, -46193, -46118, -46042, -45967, -45892, -45818, -45743, -45668, -45593, -45519, -45444, -45370, -45296, -45221, -45147, -45073, -44999, -44925, -44851, -44778, -44704, -44630, -44557, -44483, -44410, -44337, -44263, -44190, -44117, -44044, -43971, -43898, -43826, -43753, -43680, -43608, -43535, -43463, -43390, -43318, -43246, -43174, -43102, -43030, -42958, -42886, -42814, -42743, -42671, -42600, -42528, -42457, -42385, -42314, -42243, -42172, -42101, -42030, -41959, -41888, -41817, -41747, -41676, -41605, -41535, -41465, -41394, -41324, -41254, -41184, -41113, -41043, -40973, -40904, -40834, -40764, -40694, -40625, -40555, -40486, -40416, -40347, -40278, -40208, -40139, -40070, -40001, -39932, -39863, -39794, -39726, -39657, -39588, -39520, -39451, -39383, -39314, -39246, -39178, -39110, -39042, -38973, -38905, -38837, -38770, -38702, -38634, -38566, -38499, -38431, -38364, -38296, -38229, -38161, -38094, -38027, -37960, -37893, -37826, -37759, -37692, -37625, -37558, -37491, -37425, -37358, -37291, -37225, -37158, -37092, -37026, -36959, -36893, -36827, -36761, -36695, -36629, -36563, -36497, -36431, -36365, -36300, -36234, -36168, -36103, -36037, -35972, -35907, -35841, -35776, -35711, -35646, -35580, -35515, -35450, -35385, -35321, -35256, -35191, -35126, -35062, -34997, -34932, -34868, -34803, -34739, -34675, -34610, -34546, -34482, -34418, -34354, -34289, -34225, -34162, -34098, -34034, -33970, -33906, -33843, -33779, -33715, -33652, -33588, -33525, -33461, -33398, -33335, -33272, -33208, -33145, -33082, -33019, -32956, -32893, -32830, -32767, -32705, -32642, -32579, -32516, -32454, -32391, -32329, -32266, -32204, -32141, -32079, -32017, -31955, -31892, -31830, -31768, -31706, -31644, -31582, -31520, -31458, -31396, -31335, -31273, -31211, -31150, -31088, -31026, -30965, -30904, -30842, -30781, -30719, -30658, -30597, -30536, -30474, -30413, -30352, -30291, -30230, -30169, -30108, -30048, -29987, -29926, -29865, -29805, -29744, -29683, -29623, -29562, -29502, -29441, -29381, -29321, -29260, -29200, -29140, -29080, -29020, -28959, -28899, -28839, -28779, -28719, -28660, -28600, -28540, -28480, -28420, -28361, -28301, -28241, -28182, -28122, -28063, -28003, -27944, -27884, -27825, -27766, -27707, -27647, -27588, -27529, -27470, -27411, -27352, -27293, -27234, -27175, -27116, -27057, -26998, -26940, -26881, -26822, -26763, -26705, -26646, -26588, -26529, -26471, -26412, -26354, -26295, -26237, -26179, -26120, -26062, -26004, -25946, -25888, -25830, -25772, -25714, -25656, -25598, -25540, -25482, -25424, -25366, -25308, -25251, -25193, -25135, -25078, -25020, -24962, -24905, -24847, -24790, -24732, -24675, -24618, -24560, -24503, -24446, -24389, -24331, -24274, -24217, -24160, -24103, -24046, -23989, -23932, -23875, -23818, -23761, -23704, -23647, -23591, -23534, -23477, -23420, -23364, -23307, -23250, -23194, -23137, -23081, -23024, -22968, -22911, -22855, -22799, -22742, -22686, -22630, -22573, -22517, -22461, -22405, -22349, -22293, -22237, -22181, -22125, -22069, -22013, -21957, -21901, -21845, -21789, -21733, -21678, -21622, -21566, -21510, -21455, -21399, -21343, -21288, -21232, -21177, -21121, -21066, -21010, -20955, -20900, -20844, -20789, -20734, -20678, -20623, -20568, -20513, -20457, -20402, -20347, -20292, -20237, -20182, -20127, -20072, -20017, -19962, -19907, -19852, -19797, -19742, -19688, -19633, -19578, -19523, -19469, -19414, -19359, -19305, -19250, -19195, -19141, -19086, -19032, -18977, -18923, -18868, -18814, -18760, -18705, -18651, -18597, -18542, -18488, -18434, -18380, -18325, -18271, -18217, -18163, -18109, -18055, -18001, -17946, -17892, -17838, -17784, -17731, -17677, -17623, -17569, -17515, -17461, -17407, -17353, -17300, -17246, -17192, -17138, -17085, -17031, -16977, -16924, -16870, -16817, -16763, -16710, -16656, -16603, -16549, -16496, -16442, -16389, -16335, -16282, -16229, -16175, -16122, -16069, -16015, -15962, -15909, -15856, -15802, -15749, -15696, -15643, -15590, -15537, -15484, -15431, -15378, -15325, -15272, -15219, -15166, -15113, -15060, -15007, -14954, -14901, -14848, -14795, -14743, -14690, -14637, -14584, -14531, -14479, -14426, -14373, -14321, -14268, -14215, -14163, -14110, -14057, -14005, -13952, -13900, -13847, -13795, -13742, -13690, -13637, -13585, -13533, -13480, -13428, -13375, -13323, -13271, -13218, -13166, -13114, -13062, -13009, -12957, -12905, -12853, -12800, -12748, -12696, -12644, -12592, -12540, -12488, -12436, -12383, -12331, -12279, -12227, -12175, -12123, -12071, -12019, -11967, -11916, -11864, -11812, -11760, -11708, -11656, -11604, -11552, -11501, -11449, -11397, -11345, -11293, -11242, -11190, -11138, -11086, -11035, -10983, -10931, -10880, -10828, -10777, -10725, -10673, -10622, -10570, -10519, -10467, -10415, -10364, -10312, -10261, -10209, -10158, -10106, -10055, -10004, -9952, -9901, -9849, -9798, -9747, -9695, -9644, -9592, -9541, -9490, -9438, -9387, -9336, -9285, -9233, -9182, -9131, -9080, -9028, -8977, -8926, -8875, -8824, -8772, -8721, -8670, -8619, -8568, -8517, -8466, -8414, -8363, -8312, -8261, -8210, -8159, -8108, -8057, -8006, -7955, -7904, -7853, -7802, -7751, -7700, -7649, -7598, -7547, -7496, -7445, -7395, -7344, -7293, -7242, -7191, -7140, -7089, -7038, -6988, -6937, -6886, -6835, -6784, -6733, -6683, -6632, -6581, -6530, -6480, -6429, -6378, -6327, -6277, -6226, -6175, -6124, -6074, -6023, -5972, -5922, -5871, -5820, -5770, -5719, -5668, -5618, -5567, -5517, -5466, -5415, -5365, -5314, -5264, -5213, -5162, -5112, -5061, -5011, -4960, -4910, -4859, -4808, -4758, -4707, -4657, -4606, -4556, -4505, -4455, -4404, -4354, -4303, -4253, -4202, -4152, -4101, -4051, -4001, -3950, -3900, -3849, -3799, -3748, -3698, -3648, -3597, -3547, -3496, -3446, -3395, -3345, -3295, -3244, -3194, -3144, -3093, -3043, -2992, -2942, -2892, -2841, -2791, -2741, -2690, -2640, -2590, -2539, -2489, -2439, -2388, -2338, -2288, -2237, -2187, -2137, -2086, -2036, -1986, -1935, -1885, -1835, -1784, -1734, -1684, -1633, -1583, -1533, -1483, -1432, -1382, -1332, -1281, -1231, -1181, -1131, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1131, 1181, 1231, 1281, 1332, 1382, 1432, 1483, 1533, 1583, 1633, 1684, 1734, 1784, 1835, 1885, 1935, 1986, 2036, 2086, 2137, 2187, 2237, 2288, 2338, 2388, 2439, 2489, 2539, 2590, 2640, 2690, 2741, 2791, 2841, 2892, 2942, 2992, 3043, 3093, 3144, 3194, 3244, 3295, 3345, 3395, 3446, 3496, 3547, 3597, 3648, 3698, 3748, 3799, 3849, 3900, 3950, 4001, 4051, 4101, 4152, 4202, 4253, 4303, 4354, 4404, 4455, 4505, 4556, 4606, 4657, 4707, 4758, 4808, 4859, 4910, 4960, 5011, 5061, 5112, 5162, 5213, 5264, 5314, 5365, 5415, 5466, 5517, 5567, 5618, 5668, 5719, 5770, 5820, 5871, 5922, 5972, 6023, 6074, 6124, 6175, 6226, 6277, 6327, 6378, 6429, 6480, 6530, 6581, 6632, 6683, 6733, 6784, 6835, 6886, 6937, 6988, 7038, 7089, 7140, 7191, 7242, 7293, 7344, 7395, 7445, 7496, 7547, 7598, 7649, 7700, 7751, 7802, 7853, 7904, 7955, 8006, 8057, 8108, 8159, 8210, 8261, 8312, 8363, 8414, 8466, 8517, 8568, 8619, 8670, 8721, 8772, 8824, 8875, 8926, 8977, 9028, 9080, 9131, 9182, 9233, 9285, 9336, 9387, 9438, 9490, 9541, 9592, 9644, 9695, 9747, 9798, 9849, 9901, 9952, 10004, 10055, 10106, 10158, 10209, 10261, 10312, 10364, 10415, 10467, 10519, 10570, 10622, 10673, 10725, 10777, 10828, 10880, 10931, 10983, 11035, 11086, 11138, 11190, 11242, 11293, 11345, 11397, 11449, 11501, 11552, 11604, 11656, 11708, 11760, 11812, 11864, 11916, 11967, 12019, 12071, 12123, 12175, 12227, 12279, 12331, 12383, 12436, 12488, 12540, 12592, 12644, 12696, 12748, 12800, 12853, 12905, 12957, 13009, 13062, 13114, 13166, 13218, 13271, 13323, 13375, 13428, 13480, 13533, 13585, 13637, 13690, 13742, 13795, 13847, 13900, 13952, 14005, 14057, 14110, 14163, 14215, 14268, 14321, 14373, 14426, 14479, 14531, 14584, 14637, 14690, 14743, 14795, 14848, 14901, 14954, 15007, 15060, 15113, 15166, 15219, 15272, 15325, 15378, 15431, 15484, 15537, 15590, 15643, 15696, 15749, 15802, 15856, 15909, 15962, 16015, 16069, 16122, 16175, 16229, 16282, 16335, 16389, 16442, 16496, 16549, 16603, 16656, 16710, 16763, 16817, 16870, 16924, 16977, 17031, 17085, 17138, 17192, 17246, 17300, 17353, 17407, 17461, 17515, 17569, 17623, 17677, 17731, 17784, 17838, 17892, 17946, 18001, 18055, 18109, 18163, 18217, 18271, 18325, 18380, 18434, 18488, 18542, 18597, 18651, 18705, 18760, 18814, 18868, 18923, 18977, 19032, 19086, 19141, 19195, 19250, 19305, 19359, 19414, 19469, 19523, 19578, 19633, 19688, 19742, 19797, 19852, 19907, 19962, 20017, 20072, 20127, 20182, 20237, 20292, 20347, 20402, 20457, 20513, 20568, 20623, 20678, 20734, 20789, 20844, 20900, 20955, 21010, 21066, 21121, 21177, 21232, 21288, 21343, 21399, 21455, 21510, 21566, 21622, 21678, 21733, 21789, 21845, 21901, 21957, 22013, 22069, 22125, 22181, 22237, 22293, 22349, 22405, 22461, 22517, 22573, 22630, 22686, 22742, 22799, 22855, 22911, 22968, 23024, 23081, 23137, 23194, 23250, 23307, 23364, 23420, 23477, 23534, 23591, 23647, 23704, 23761, 23818, 23875, 23932, 23989, 24046, 24103, 24160, 24217, 24274, 24331, 24389, 24446, 24503, 24560, 24618, 24675, 24732, 24790, 24847, 24905, 24962, 25020, 25078, 25135, 25193, 25251, 25308, 25366, 25424, 25482, 25540, 25598, 25656, 25714, 25772, 25830, 25888, 25946, 26004, 26062, 26120, 26179, 26237, 26295, 26354, 26412, 26471, 26529, 26588, 26646, 26705, 26763, 26822, 26881, 26940, 26998, 27057, 27116, 27175, 27234, 27293, 27352, 27411, 27470, 27529, 27588, 27647, 27707, 27766, 27825, 27884, 27944, 28003, 28063, 28122, 28182, 28241, 28301, 28361, 28420, 28480, 28540, 28600, 28660, 28719, 28779, 28839, 28899, 28959, 29020, 29080, 29140, 29200, 29260, 29321, 29381, 29441, 29502, 29562, 29623, 29683, 29744, 29805, 29865, 29926, 29987, 30048, 30108, 30169, 30230, 30291, 30352, 30413, 30474, 30536, 30597, 30658, 30719, 30781, 30842, 30904, 30965, 31026, 31088, 31150, 31211, 31273, 31335, 31396, 31458, 31520, 31582, 31644, 31706, 31768, 31830, 31892, 31955, 32017, 32079, 32141, 32204, 32266, 32329, 32391, 32454, 32516, 32579, 32642, 32705, 32767, 32830, 32893, 32956, 33019, 33082, 33145, 33208, 33272, 33335, 33398, 33461, 33525, 33588, 33652, 33715, 33779, 33843, 33906, 33970, 34034, 34098, 34162, 34225, 34289, 34354, 34418, 34482, 34546, 34610, 34675, 34739, 34803, 34868, 34932, 34997, 35062, 35126, 35191, 35256, 35321, 35385, 35450, 35515, 35580, 35646, 35711, 35776, 35841, 35907, 35972, 36037, 36103, 36168, 36234, 36300, 36365, 36431, 36497, 36563, 36629, 36695, 36761, 36827, 36893, 36959, 37026, 37092, 37158, 37225, 37291, 37358, 37425, 37491, 37558, 37625, 37692, 37759, 37826, 37893, 37960, 38027, 38094, 38161, 38229, 38296, 38364, 38431, 38499, 38566, 38634, 38702, 38770, 38837, 38905, 38973, 39042, 39110, 39178, 39246, 39314, 39383, 39451, 39520, 39588, 39657, 39726, 39794, 39863, 39932, 40001, 40070, 40139, 40208, 40278, 40347, 40416, 40486, 40555, 40625, 40694, 40764, 40834, 40904, 40973, 41043, 41113, 41184, 41254, 41324, 41394, 41465, 41535, 41605, 41676, 41747, 41817, 41888, 41959, 42030, 42101, 42172, 42243, 42314, 42385, 42457, 42528, 42600, 42671, 42743, 42814, 42886, 42958, 43030, 43102, 43174, 43246, 43318, 43390, 43463, 43535, 43608, 43680, 43753, 43826, 43898, 43971, 44044, 44117, 44190, 44263, 44337, 44410, 44483, 44557, 44630, 44704, 44778, 44851, 44925, 44999, 45073, 45147, 45221, 45296, 45370, 45444, 45519, 45593, 45668, 45743, 45818, 45892, 45967, 46042, 46118, 46193, 46268, 46343, 46419, 46494, 46570, 46646, 46721, 46797, 46873, 46949, 47025, 47102, 47178, 47254, 47331, 47407, 47484, 47560, 47637, 47714, 47791, 47868, 47945, 48022, 48100, 48177, 48255, 48332, 48410, 48488, 48565, 48643, 48721, 48799, 48878, 48956, 49034, 49113, 49191, 49270, 49349, 49427, 49506, 49585, 49664, 49744, 49823, 49902, 49982, 50061, 50141, 50221, 50300, 50380, 50460, 50540, 50621, 50701, 50781, 50862, 50942, 51023, 51104, 51185, 51266, 51347, 51428, 51509, 51591, 51672, 51754, 51835, 51917, 51999, 52081, 52163, 52245, 52327, 52410, 52492, 52575, 52657, 52740, 52823, 52906, 52989, 53072, 53156, 53239, 53322, 53406, 53490, 53574, 53657, 53741, 53826, 53910, 53994, 54079, 54163, 54248, 54333, 54417, 54502, 54587, 54673, 54758, 54843, 54929, 55015, 55100, 55186, 55272, 55358, 55444, 55531, 55617, 55704, 55790, 55877, 55964, 56051, 56138, 56225, 56312, 56400, 56487, 56575, 56663, 56751, 56839, 56927, 57015, 57104, 57192, 57281, 57369, 57458, 57547, 57636, 57725, 57815, 57904, 57994, 58083, 58173, 58263, 58353, 58443, 58534, 58624, 58715, 58805, 58896, 58987, 59078, 59169, 59261, 59352, 59444, 59535, 59627, 59719, 59811, 59903, 59996, 60088, 60181, 60273, 60366, 60459, 60552, 60646, 60739, 60833, 60926, 61020, 61114, 61208, 61302, 61396, 61491, 61585, 61680, 61775, 61870, 61965, 62060, 62156, 62251, 62347, 62443, 62539, 62635, 62731, 62828, 62924, 63021, 63118, 63215, 63312, 63409, 63506, 63604, 63702, 63799, 63897, 63996, 64094, 64192, 64291, 64389, 64488, 64587, 64687, 64786, 64885, 64985, 65085, 65185, 65285, 65385, 65485, 65586, 65686, 65787, 65888, 65989, 66091, 66192, 66294, 66396, 66498, 66600, 66702, 66804, 66907, 67010, 67113, 67216, 67319, 67422, 67526, 67629, 67733, 67837, 67942, 68046, 68151, 68255, 68360, 68465, 68570, 68676, 68781, 68887, 68993, 69099, 69205, 69312, 69418, 69525, 69632, 69739, 69846, 69954, 70061, 70169, 70277, 70385, 70494, 70602, 70711, 70820, 70929, 71038, 71147, 71257, 71367, 71477, 71587, 71697, 71808, 71918, 72029, 72140, 72252, 72363, 72475, 72587, 72699, 72811, 72923, 73036, 73149, 73262, 73375, 73488, 73602, 73715, 73829, 73944, 74058, 74172, 74287, 74402, 74517, 74633, 74748, 74864, 74980, 75096, 75213, 75329, 75446, 75563, 75680, 75797, 75915, 76033, 76151, 76269, 76388, 76506, 76625, 76744, 76864, 76983, 77103, 77223, 77343, 77463, 77584, 77705, 77826, 77947, 78068, 78190, 78312, 78434, 78557, 78679, 78802, 78925, 79048, 79172, 79296, 79420, 79544, 79668, 79793, 79918, 80043, 80168, 80294, 80420, 80546, 80672, 80799, 80925, 81053, 81180, 81307, 81435, 81563, 81691, 81820, 81949, 82078, 82207, 82336, 82466, 82596, 82726, 82857, 82987, 83118, 83250, 83381, 83513, 83645, 83777, 83910, 84043, 84176, 84309, 84443, 84576, 84710, 84845, 84980, 85114, 85250, 85385, 85521, 85657, 85793, 85930, 86066, 86204, 86341, 86479, 86616, 86755, 86893, 87032, 87171, 87310, 87450, 87590, 87730, 87871, 88011, 88152, 88294, 88435, 88577, 88720, 88862, 89005, 89148, 89292, 89435, 89579, 89724, 89868, 90013, 90158, 90304, 90450, 90596, 90742, 90889, 91036, 91184, 91332, 91480, 91628, 91777, 91926, 92075, 92225, 92375, 92525, 92675, 92826, 92978, 93129, 93281, 93434, 93586, 93739, 93892, 94046, 94200, 94354, 94509, 94664, 94819, 94975, 95131, 95287, 95444, 95601, 95758, 95916, 96074, 96233, 96391, 96551, 96710, 96870, 97030, 97191, 97352, 97513, 97675, 97837, 98000, 98163, 98326, 98489, 98653, 98818, 98982, 99148, 99313, 99479, 99645, 99812, 99979, 100146, 100314, 100482, 100651, 100820, 100990, 101159, 101330, 101500, 101671, 101843, 102015, 102187, 102360, 102533, 102706, 102880, 103054, 103229, 103404, 103580, 103756, 103933, 104109, 104287, 104465, 104643, 104821, 105000, 105180, 105360, 105540, 105721, 105902, 106084, 106266, 106449, 106632, 106816, 107000, 107184, 107369, 107555, 107741, 107927, 108114, 108301, 108489, 108677, 108866, 109055, 109245, 109435, 109626, 109817, 110008, 110200, 110393, 110586, 110780, 110974, 111169, 111364, 111560, 111756, 111952, 112150, 112347, 112546, 112744, 112944, 113143, 113344, 113545, 113746, 113948, 114151, 114354, 114557, 114761, 114966, 115171, 115377, 115583, 115790, 115998, 116206, 116414, 116623, 116833, 117044, 117254, 117466, 117678, 117891, 118104, 118318, 118532, 118747, 118963, 119179, 119396, 119613, 119831, 120050, 120269, 120489, 120709, 120930, 121152, 121374, 121597, 121821, 122045, 122270, 122496, 122722, 122949, 123176, 123404, 123633, 123863, 124093, 124324, 124555, 124787, 125020, 125254, 125488, 125723, 125959, 126195, 126432, 126669, 126908, 127147, 127387, 127627, 127869, 128111, 128353, 128597, 128841, 129086, 129332, 129578, 129825, 130073, 130322, 130571, 130821, 131072, 131324, 131576, 131830, 132084, 132339, 132594, 132851, 133108, 133366, 133625, 133884, 134145, 134406, 134668, 134931, 135195, 135459, 135725, 135991, 136258, 136526, 136795, 137065, 137335, 137607, 137879, 138152, 138426, 138701, 138977, 139254, 139532, 139810, 140090, 140370, 140651, 140934, 141217, 141501, 141786, 142072, 142359, 142647, 142936, 143226, 143517, 143808, 144101, 144395, 144690, 144986, 145282, 145580, 145879, 146179, 146480, 146782, 147084, 147388, 147693, 148000, 148307, 148615, 148924, 149235, 149546, 149859, 150172, 150487, 150803, 151120, 151438, 151757, 152077, 152399, 152722, 153045, 153370, 153697, 154024, 154352, 154682, 155013, 155345, 155678, 156013, 156349, 156686, 157024, 157363, 157704, 158046, 158389, 158734, 159079, 159427, 159775, 160125, 160476, 160828, 161182, 161537, 161893, 162251, 162610, 162970, 163332, 163695, 164060, 164426, 164793, 165162, 165532, 165904, 166277, 166651, 167027, 167405, 167784, 168164, 168546, 168930, 169315, 169701, 170089, 170479, 170870, 171263, 171657, 172053, 172451, 172850, 173251, 173653, 174057, 174463, 174870, 175279, 175690, 176102, 176516, 176932, 177349, 177769, 178190, 178612, 179037, 179463, 179891, 180321, 180753, 181186, 181622, 182059, 182498, 182939, 183382, 183827, 184274, 184722, 185173, 185625, 186080, 186536, 186995, 187455, 187918, 188382, 188849, 189318, 189789, 190261, 190736, 191213, 191693, 192174, 192658, 193143, 193631, 194122, 194614, 195109, 195606, 196105, 196606, 197110, 197616, 198125, 198636, 199149, 199664, 200182, 200703, 201226, 201751, 202279, 202809, 203342, 203878, 204416, 204956, 205500, 206045, 206594, 207145, 207699, 208255, 208815, 209376, 209941, 210509, 211079, 211652, 212228, 212807, 213389, 213973, 214561, 215151, 215745, 216341, 216941, 217544, 218149, 218758, 219370, 219985, 220603, 221225, 221849, 222477, 223108, 223743, 224381, 225022, 225666, 226314, 226966, 227621, 228279, 228941, 229606, 230275, 230948, 231624, 232304, 232988, 233676, 234367, 235062, 235761, 236463, 237170, 237881, 238595, 239314, 240036, 240763, 241493, 242228, 242967, 243711, 244458, 245210, 245966, 246727, 247492, 248261, 249035, 249813, 250596, 251384, 252176, 252973, 253774, 254581, 255392, 256208, 257029, 257855, 258686, 259522, 260363, 261209, 262060, 262917, 263779, 264646, 265519, 266397, 267280, 268169, 269064, 269965, 270871, 271782, 272700, 273624, 274553, 275489, 276430, 277378, 278332, 279292, 280258, 281231, 282210, 283195, 284188, 285186, 286192, 287204, 288223, 289249, 290282, 291322, 292369, 293423, 294485, 295554, 296630, 297714, 298805, 299904, 301011, 302126, 303248, 304379, 305517, 306664, 307819, 308983, 310154, 311335, 312524, 313721, 314928, 316143, 317368, 318601, 319844, 321097, 322358, 323629, 324910, 326201, 327502, 328812, 330133, 331464, 332805, 334157, 335519, 336892, 338276, 339671, 341078, 342495, 343924, 345364, 346816, 348280, 349756, 351244, 352744, 354257, 355783, 357321, 358872, 360436, 362013, 363604, 365208, 366826, 368459, 370105, 371765, 373440, 375130, 376835, 378555, 380290, 382040, 383807, 385589, 387387, 389202, 391034, 392882, 394747, 396630, 398530, 400448, 402384, 404338, 406311, 408303, 410314, 412344, 414395, 416465, 418555, 420666, 422798, 424951, 427125, 429321, 431540, 433781, 436045, 438332, 440643, 442978, 445337, 447720, 450129, 452564, 455024, 457511, 460024, 462565, 465133, 467730, 470355, 473009, 475692, 478406, 481150, 483925, 486732, 489571, 492443, 495348, 498287, 501261, 504269, 507313, 510394, 513512, 516667, 519861, 523094, 526366, 529680, 533034, 536431, 539870, 543354, 546881, 550455, 554074, 557741, 561456, 565221, 569035, 572901, 576818, 580789, 584815, 588896, 593033, 597229, 601483, 605798, 610174, 614613, 619117, 623686, 628323, 633028, 637803, 642651, 647572, 652568, 657640, 662792, 668024, 673338, 678737, 684223, 689797, 695462, 701219, 707072, 713023, 719074, 725227, 731486, 737853, 744331, 750922, 757631, 764460, 771411, 778490, 785699, 793041, 800521, 808143, 815910, 823827, 831898, 840127, 848520, 857081, 865817, 874730, 883829, 893117, 902602, 912289, 922186, 932298, 942633, 953199, 964003, 975054, 986361, 997931, 1009774, 1021901, 1034322, 1047046, 1060087, 1073455, 1087164, 1101225, 1115654, 1130465, 1145673, 1161294, 1177345, 1193846, 1210813, 1228269, 1246234, 1264730, 1283783, 1303416, 1323658, 1344537, 1366084, 1388330, 1411312, 1435065, 1459630, 1485049, 1511367, 1538632, 1566898, 1596220, 1626658, 1658278, 1691149, 1725348, 1760956, 1798063, 1836758, 1877161, 1919378, 1963536, 2009771, 2058233, 2109087, 2162516, 2218719, 2277919, 2340362, 2406322, 2476104, 2550052, 2628549, 2712030, 2800983, 2895966, 2997613, 3106651, 3223918, 3350381, 3487165, 3635590, 3797206, 3973855, 4167737, 4381502, 4618375, 4882318, 5178251, 5512368, 5892567, 6329090, 6835455, 7429880, 8137527, 8994149, 10052327, 11392683, 13145455, 15535599, 18988036, 24413316, 34178904, 56965752, 170910304 }; int finesine[10240] = { 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3541, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5748, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22433, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30426, 30471, 30515, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36555, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40300, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47860, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50065, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53911, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54308, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64601, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65534, 65534, 65534, 65533, 65533, 65532, 65532, 65531, 65531, 65530, 65530, 65529, 65528, 65527, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65516, 65515, 65514, 65513, 65511, 65510, 65508, 65507, 65505, 65504, 65502, 65501, 65499, 65497, 65496, 65494, 65492, 65490, 65488, 65486, 65484, 65482, 65480, 65478, 65476, 65474, 65472, 65470, 65467, 65465, 65463, 65460, 65458, 65455, 65453, 65450, 65448, 65445, 65442, 65440, 65437, 65434, 65431, 65429, 65426, 65423, 65420, 65417, 65414, 65411, 65408, 65404, 65401, 65398, 65395, 65391, 65388, 65385, 65381, 65378, 65374, 65371, 65367, 65363, 65360, 65356, 65352, 65349, 65345, 65341, 65337, 65333, 65329, 65325, 65321, 65317, 65313, 65309, 65305, 65300, 65296, 65292, 65287, 65283, 65279, 65274, 65270, 65265, 65260, 65256, 65251, 65246, 65242, 65237, 65232, 65227, 65222, 65217, 65212, 65207, 65202, 65197, 65192, 65187, 65182, 65177, 65171, 65166, 65161, 65155, 65150, 65144, 65139, 65133, 65128, 65122, 65117, 65111, 65105, 65099, 65094, 65088, 65082, 65076, 65070, 65064, 65058, 65052, 65046, 65040, 65033, 65027, 65021, 65015, 65008, 65002, 64995, 64989, 64982, 64976, 64969, 64963, 64956, 64949, 64943, 64936, 64929, 64922, 64915, 64908, 64902, 64895, 64887, 64880, 64873, 64866, 64859, 64852, 64844, 64837, 64830, 64822, 64815, 64808, 64800, 64793, 64785, 64777, 64770, 64762, 64754, 64747, 64739, 64731, 64723, 64715, 64707, 64699, 64691, 64683, 64675, 64667, 64659, 64651, 64642, 64634, 64626, 64617, 64609, 64600, 64592, 64584, 64575, 64566, 64558, 64549, 64540, 64532, 64523, 64514, 64505, 64496, 64487, 64478, 64469, 64460, 64451, 64442, 64433, 64424, 64414, 64405, 64396, 64387, 64377, 64368, 64358, 64349, 64339, 64330, 64320, 64310, 64301, 64291, 64281, 64271, 64261, 64252, 64242, 64232, 64222, 64212, 64202, 64192, 64181, 64171, 64161, 64151, 64140, 64130, 64120, 64109, 64099, 64088, 64078, 64067, 64057, 64046, 64035, 64025, 64014, 64003, 63992, 63981, 63971, 63960, 63949, 63938, 63927, 63915, 63904, 63893, 63882, 63871, 63859, 63848, 63837, 63825, 63814, 63803, 63791, 63779, 63768, 63756, 63745, 63733, 63721, 63709, 63698, 63686, 63674, 63662, 63650, 63638, 63626, 63614, 63602, 63590, 63578, 63565, 63553, 63541, 63528, 63516, 63504, 63491, 63479, 63466, 63454, 63441, 63429, 63416, 63403, 63390, 63378, 63365, 63352, 63339, 63326, 63313, 63300, 63287, 63274, 63261, 63248, 63235, 63221, 63208, 63195, 63182, 63168, 63155, 63141, 63128, 63114, 63101, 63087, 63074, 63060, 63046, 63032, 63019, 63005, 62991, 62977, 62963, 62949, 62935, 62921, 62907, 62893, 62879, 62865, 62850, 62836, 62822, 62808, 62793, 62779, 62764, 62750, 62735, 62721, 62706, 62692, 62677, 62662, 62648, 62633, 62618, 62603, 62588, 62573, 62558, 62543, 62528, 62513, 62498, 62483, 62468, 62453, 62437, 62422, 62407, 62391, 62376, 62360, 62345, 62329, 62314, 62298, 62283, 62267, 62251, 62236, 62220, 62204, 62188, 62172, 62156, 62141, 62125, 62108, 62092, 62076, 62060, 62044, 62028, 62012, 61995, 61979, 61963, 61946, 61930, 61913, 61897, 61880, 61864, 61847, 61831, 61814, 61797, 61780, 61764, 61747, 61730, 61713, 61696, 61679, 61662, 61645, 61628, 61611, 61594, 61577, 61559, 61542, 61525, 61507, 61490, 61473, 61455, 61438, 61420, 61403, 61385, 61367, 61350, 61332, 61314, 61297, 61279, 61261, 61243, 61225, 61207, 61189, 61171, 61153, 61135, 61117, 61099, 61081, 61062, 61044, 61026, 61007, 60989, 60971, 60952, 60934, 60915, 60897, 60878, 60859, 60841, 60822, 60803, 60785, 60766, 60747, 60728, 60709, 60690, 60671, 60652, 60633, 60614, 60595, 60576, 60556, 60537, 60518, 60499, 60479, 60460, 60441, 60421, 60402, 60382, 60363, 60343, 60323, 60304, 60284, 60264, 60244, 60225, 60205, 60185, 60165, 60145, 60125, 60105, 60085, 60065, 60045, 60025, 60004, 59984, 59964, 59944, 59923, 59903, 59883, 59862, 59842, 59821, 59801, 59780, 59759, 59739, 59718, 59697, 59677, 59656, 59635, 59614, 59593, 59572, 59551, 59530, 59509, 59488, 59467, 59446, 59425, 59404, 59382, 59361, 59340, 59318, 59297, 59276, 59254, 59233, 59211, 59190, 59168, 59146, 59125, 59103, 59081, 59059, 59038, 59016, 58994, 58972, 58950, 58928, 58906, 58884, 58862, 58840, 58818, 58795, 58773, 58751, 58729, 58706, 58684, 58662, 58639, 58617, 58594, 58572, 58549, 58527, 58504, 58481, 58459, 58436, 58413, 58390, 58367, 58345, 58322, 58299, 58276, 58253, 58230, 58207, 58183, 58160, 58137, 58114, 58091, 58067, 58044, 58021, 57997, 57974, 57950, 57927, 57903, 57880, 57856, 57833, 57809, 57785, 57762, 57738, 57714, 57690, 57666, 57642, 57618, 57594, 57570, 57546, 57522, 57498, 57474, 57450, 57426, 57402, 57377, 57353, 57329, 57304, 57280, 57255, 57231, 57206, 57182, 57157, 57133, 57108, 57083, 57059, 57034, 57009, 56984, 56959, 56935, 56910, 56885, 56860, 56835, 56810, 56785, 56760, 56734, 56709, 56684, 56659, 56633, 56608, 56583, 56557, 56532, 56507, 56481, 56456, 56430, 56404, 56379, 56353, 56328, 56302, 56276, 56250, 56225, 56199, 56173, 56147, 56121, 56095, 56069, 56043, 56017, 55991, 55965, 55938, 55912, 55886, 55860, 55833, 55807, 55781, 55754, 55728, 55701, 55675, 55648, 55622, 55595, 55569, 55542, 55515, 55489, 55462, 55435, 55408, 55381, 55354, 55327, 55300, 55274, 55246, 55219, 55192, 55165, 55138, 55111, 55084, 55056, 55029, 55002, 54974, 54947, 54920, 54892, 54865, 54837, 54810, 54782, 54755, 54727, 54699, 54672, 54644, 54616, 54588, 54560, 54533, 54505, 54477, 54449, 54421, 54393, 54365, 54337, 54308, 54280, 54252, 54224, 54196, 54167, 54139, 54111, 54082, 54054, 54026, 53997, 53969, 53940, 53911, 53883, 53854, 53826, 53797, 53768, 53739, 53711, 53682, 53653, 53624, 53595, 53566, 53537, 53508, 53479, 53450, 53421, 53392, 53363, 53334, 53304, 53275, 53246, 53216, 53187, 53158, 53128, 53099, 53069, 53040, 53010, 52981, 52951, 52922, 52892, 52862, 52832, 52803, 52773, 52743, 52713, 52683, 52653, 52624, 52594, 52564, 52534, 52503, 52473, 52443, 52413, 52383, 52353, 52322, 52292, 52262, 52231, 52201, 52171, 52140, 52110, 52079, 52049, 52018, 51988, 51957, 51926, 51896, 51865, 51834, 51803, 51773, 51742, 51711, 51680, 51649, 51618, 51587, 51556, 51525, 51494, 51463, 51432, 51401, 51369, 51338, 51307, 51276, 51244, 51213, 51182, 51150, 51119, 51087, 51056, 51024, 50993, 50961, 50929, 50898, 50866, 50834, 50803, 50771, 50739, 50707, 50675, 50644, 50612, 50580, 50548, 50516, 50484, 50452, 50420, 50387, 50355, 50323, 50291, 50259, 50226, 50194, 50162, 50129, 50097, 50065, 50032, 50000, 49967, 49935, 49902, 49869, 49837, 49804, 49771, 49739, 49706, 49673, 49640, 49608, 49575, 49542, 49509, 49476, 49443, 49410, 49377, 49344, 49311, 49278, 49244, 49211, 49178, 49145, 49112, 49078, 49045, 49012, 48978, 48945, 48911, 48878, 48844, 48811, 48777, 48744, 48710, 48676, 48643, 48609, 48575, 48542, 48508, 48474, 48440, 48406, 48372, 48338, 48304, 48271, 48237, 48202, 48168, 48134, 48100, 48066, 48032, 47998, 47963, 47929, 47895, 47860, 47826, 47792, 47757, 47723, 47688, 47654, 47619, 47585, 47550, 47516, 47481, 47446, 47412, 47377, 47342, 47308, 47273, 47238, 47203, 47168, 47133, 47098, 47063, 47028, 46993, 46958, 46923, 46888, 46853, 46818, 46783, 46747, 46712, 46677, 46642, 46606, 46571, 46536, 46500, 46465, 46429, 46394, 46358, 46323, 46287, 46252, 46216, 46180, 46145, 46109, 46073, 46037, 46002, 45966, 45930, 45894, 45858, 45822, 45786, 45750, 45714, 45678, 45642, 45606, 45570, 45534, 45498, 45462, 45425, 45389, 45353, 45316, 45280, 45244, 45207, 45171, 45135, 45098, 45062, 45025, 44989, 44952, 44915, 44879, 44842, 44806, 44769, 44732, 44695, 44659, 44622, 44585, 44548, 44511, 44474, 44437, 44400, 44363, 44326, 44289, 44252, 44215, 44178, 44141, 44104, 44067, 44029, 43992, 43955, 43918, 43880, 43843, 43806, 43768, 43731, 43693, 43656, 43618, 43581, 43543, 43506, 43468, 43430, 43393, 43355, 43317, 43280, 43242, 43204, 43166, 43128, 43091, 43053, 43015, 42977, 42939, 42901, 42863, 42825, 42787, 42749, 42711, 42672, 42634, 42596, 42558, 42520, 42481, 42443, 42405, 42366, 42328, 42290, 42251, 42213, 42174, 42136, 42097, 42059, 42020, 41982, 41943, 41904, 41866, 41827, 41788, 41750, 41711, 41672, 41633, 41595, 41556, 41517, 41478, 41439, 41400, 41361, 41322, 41283, 41244, 41205, 41166, 41127, 41088, 41048, 41009, 40970, 40931, 40891, 40852, 40813, 40773, 40734, 40695, 40655, 40616, 40576, 40537, 40497, 40458, 40418, 40379, 40339, 40300, 40260, 40220, 40180, 40141, 40101, 40061, 40021, 39982, 39942, 39902, 39862, 39822, 39782, 39742, 39702, 39662, 39622, 39582, 39542, 39502, 39462, 39422, 39382, 39341, 39301, 39261, 39221, 39180, 39140, 39100, 39059, 39019, 38979, 38938, 38898, 38857, 38817, 38776, 38736, 38695, 38655, 38614, 38573, 38533, 38492, 38451, 38411, 38370, 38329, 38288, 38248, 38207, 38166, 38125, 38084, 38043, 38002, 37961, 37920, 37879, 37838, 37797, 37756, 37715, 37674, 37633, 37592, 37551, 37509, 37468, 37427, 37386, 37344, 37303, 37262, 37220, 37179, 37137, 37096, 37055, 37013, 36972, 36930, 36889, 36847, 36805, 36764, 36722, 36681, 36639, 36597, 36556, 36514, 36472, 36430, 36388, 36347, 36305, 36263, 36221, 36179, 36137, 36095, 36053, 36011, 35969, 35927, 35885, 35843, 35801, 35759, 35717, 35675, 35633, 35590, 35548, 35506, 35464, 35421, 35379, 35337, 35294, 35252, 35210, 35167, 35125, 35082, 35040, 34997, 34955, 34912, 34870, 34827, 34785, 34742, 34699, 34657, 34614, 34571, 34529, 34486, 34443, 34400, 34358, 34315, 34272, 34229, 34186, 34143, 34100, 34057, 34015, 33972, 33929, 33886, 33843, 33799, 33756, 33713, 33670, 33627, 33584, 33541, 33498, 33454, 33411, 33368, 33325, 33281, 33238, 33195, 33151, 33108, 33065, 33021, 32978, 32934, 32891, 32847, 32804, 32760, 32717, 32673, 32630, 32586, 32542, 32499, 32455, 32411, 32368, 32324, 32280, 32236, 32193, 32149, 32105, 32061, 32017, 31974, 31930, 31886, 31842, 31798, 31754, 31710, 31666, 31622, 31578, 31534, 31490, 31446, 31402, 31357, 31313, 31269, 31225, 31181, 31136, 31092, 31048, 31004, 30959, 30915, 30871, 30826, 30782, 30738, 30693, 30649, 30604, 30560, 30515, 30471, 30426, 30382, 30337, 30293, 30248, 30204, 30159, 30114, 30070, 30025, 29980, 29936, 29891, 29846, 29801, 29757, 29712, 29667, 29622, 29577, 29533, 29488, 29443, 29398, 29353, 29308, 29263, 29218, 29173, 29128, 29083, 29038, 28993, 28948, 28903, 28858, 28812, 28767, 28722, 28677, 28632, 28586, 28541, 28496, 28451, 28405, 28360, 28315, 28269, 28224, 28179, 28133, 28088, 28042, 27997, 27952, 27906, 27861, 27815, 27770, 27724, 27678, 27633, 27587, 27542, 27496, 27450, 27405, 27359, 27313, 27268, 27222, 27176, 27131, 27085, 27039, 26993, 26947, 26902, 26856, 26810, 26764, 26718, 26672, 26626, 26580, 26534, 26488, 26442, 26396, 26350, 26304, 26258, 26212, 26166, 26120, 26074, 26028, 25982, 25936, 25889, 25843, 25797, 25751, 25705, 25658, 25612, 25566, 25520, 25473, 25427, 25381, 25334, 25288, 25241, 25195, 25149, 25102, 25056, 25009, 24963, 24916, 24870, 24823, 24777, 24730, 24684, 24637, 24591, 24544, 24497, 24451, 24404, 24357, 24311, 24264, 24217, 24171, 24124, 24077, 24030, 23984, 23937, 23890, 23843, 23796, 23750, 23703, 23656, 23609, 23562, 23515, 23468, 23421, 23374, 23327, 23280, 23233, 23186, 23139, 23092, 23045, 22998, 22951, 22904, 22857, 22810, 22763, 22716, 22668, 22621, 22574, 22527, 22480, 22433, 22385, 22338, 22291, 22243, 22196, 22149, 22102, 22054, 22007, 21960, 21912, 21865, 21817, 21770, 21723, 21675, 21628, 21580, 21533, 21485, 21438, 21390, 21343, 21295, 21248, 21200, 21153, 21105, 21057, 21010, 20962, 20915, 20867, 20819, 20772, 20724, 20676, 20629, 20581, 20533, 20485, 20438, 20390, 20342, 20294, 20246, 20199, 20151, 20103, 20055, 20007, 19959, 19912, 19864, 19816, 19768, 19720, 19672, 19624, 19576, 19528, 19480, 19432, 19384, 19336, 19288, 19240, 19192, 19144, 19096, 19048, 19000, 18951, 18903, 18855, 18807, 18759, 18711, 18663, 18614, 18566, 18518, 18470, 18421, 18373, 18325, 18277, 18228, 18180, 18132, 18084, 18035, 17987, 17939, 17890, 17842, 17793, 17745, 17697, 17648, 17600, 17551, 17503, 17455, 17406, 17358, 17309, 17261, 17212, 17164, 17115, 17067, 17018, 16970, 16921, 16872, 16824, 16775, 16727, 16678, 16629, 16581, 16532, 16484, 16435, 16386, 16338, 16289, 16240, 16191, 16143, 16094, 16045, 15997, 15948, 15899, 15850, 15802, 15753, 15704, 15655, 15606, 15557, 15509, 15460, 15411, 15362, 15313, 15264, 15215, 15167, 15118, 15069, 15020, 14971, 14922, 14873, 14824, 14775, 14726, 14677, 14628, 14579, 14530, 14481, 14432, 14383, 14334, 14285, 14236, 14187, 14138, 14089, 14040, 13990, 13941, 13892, 13843, 13794, 13745, 13696, 13646, 13597, 13548, 13499, 13450, 13401, 13351, 13302, 13253, 13204, 13154, 13105, 13056, 13007, 12957, 12908, 12859, 12810, 12760, 12711, 12662, 12612, 12563, 12514, 12464, 12415, 12366, 12316, 12267, 12218, 12168, 12119, 12069, 12020, 11970, 11921, 11872, 11822, 11773, 11723, 11674, 11624, 11575, 11525, 11476, 11426, 11377, 11327, 11278, 11228, 11179, 11129, 11080, 11030, 10981, 10931, 10882, 10832, 10782, 10733, 10683, 10634, 10584, 10534, 10485, 10435, 10386, 10336, 10286, 10237, 10187, 10137, 10088, 10038, 9988, 9939, 9889, 9839, 9790, 9740, 9690, 9640, 9591, 9541, 9491, 9442, 9392, 9342, 9292, 9243, 9193, 9143, 9093, 9043, 8994, 8944, 8894, 8844, 8794, 8745, 8695, 8645, 8595, 8545, 8496, 8446, 8396, 8346, 8296, 8246, 8196, 8147, 8097, 8047, 7997, 7947, 7897, 7847, 7797, 7747, 7697, 7648, 7598, 7548, 7498, 7448, 7398, 7348, 7298, 7248, 7198, 7148, 7098, 7048, 6998, 6948, 6898, 6848, 6798, 6748, 6698, 6648, 6598, 6548, 6498, 6448, 6398, 6348, 6298, 6248, 6198, 6148, 6098, 6048, 5998, 5948, 5898, 5848, 5798, 5748, 5697, 5647, 5597, 5547, 5497, 5447, 5397, 5347, 5297, 5247, 5197, 5146, 5096, 5046, 4996, 4946, 4896, 4846, 4796, 4745, 4695, 4645, 4595, 4545, 4495, 4445, 4394, 4344, 4294, 4244, 4194, 4144, 4093, 4043, 3993, 3943, 3893, 3843, 3792, 3742, 3692, 3642, 3592, 3541, 3491, 3441, 3391, 3341, 3291, 3240, 3190, 3140, 3090, 3039, 2989, 2939, 2889, 2839, 2788, 2738, 2688, 2638, 2587, 2537, 2487, 2437, 2387, 2336, 2286, 2236, 2186, 2135, 2085, 2035, 1985, 1934, 1884, 1834, 1784, 1733, 1683, 1633, 1583, 1532, 1482, 1432, 1382, 1331, 1281, 1231, 1181, 1130, 1080, 1030, 980, 929, 879, 829, 779, 728, 678, 628, 578, 527, 477, 427, 376, 326, 276, 226, 175, 125, 75, 25, -25, -75, -125, -175, -226, -276, -326, -376, -427, -477, -527, -578, -628, -678, -728, -779, -829, -879, -929, -980, -1030, -1080, -1130, -1181, -1231, -1281, -1331, -1382, -1432, -1482, -1532, -1583, -1633, -1683, -1733, -1784, -1834, -1884, -1934, -1985, -2035, -2085, -2135, -2186, -2236, -2286, -2336, -2387, -2437, -2487, -2537, -2588, -2638, -2688, -2738, -2788, -2839, -2889, -2939, -2989, -3039, -3090, -3140, -3190, -3240, -3291, -3341, -3391, -3441, -3491, -3541, -3592, -3642, -3692, -3742, -3792, -3843, -3893, -3943, -3993, -4043, -4093, -4144, -4194, -4244, -4294, -4344, -4394, -4445, -4495, -4545, -4595, -4645, -4695, -4745, -4796, -4846, -4896, -4946, -4996, -5046, -5096, -5146, -5197, -5247, -5297, -5347, -5397, -5447, -5497, -5547, -5597, -5647, -5697, -5748, -5798, -5848, -5898, -5948, -5998, -6048, -6098, -6148, -6198, -6248, -6298, -6348, -6398, -6448, -6498, -6548, -6598, -6648, -6698, -6748, -6798, -6848, -6898, -6948, -6998, -7048, -7098, -7148, -7198, -7248, -7298, -7348, -7398, -7448, -7498, -7548, -7598, -7648, -7697, -7747, -7797, -7847, -7897, -7947, -7997, -8047, -8097, -8147, -8196, -8246, -8296, -8346, -8396, -8446, -8496, -8545, -8595, -8645, -8695, -8745, -8794, -8844, -8894, -8944, -8994, -9043, -9093, -9143, -9193, -9243, -9292, -9342, -9392, -9442, -9491, -9541, -9591, -9640, -9690, -9740, -9790, -9839, -9889, -9939, -9988, -10038, -10088, -10137, -10187, -10237, -10286, -10336, -10386, -10435, -10485, -10534, -10584, -10634, -10683, -10733, -10782, -10832, -10882, -10931, -10981, -11030, -11080, -11129, -11179, -11228, -11278, -11327, -11377, -11426, -11476, -11525, -11575, -11624, -11674, -11723, -11773, -11822, -11872, -11921, -11970, -12020, -12069, -12119, -12168, -12218, -12267, -12316, -12366, -12415, -12464, -12514, -12563, -12612, -12662, -12711, -12760, -12810, -12859, -12908, -12957, -13007, -13056, -13105, -13154, -13204, -13253, -13302, -13351, -13401, -13450, -13499, -13548, -13597, -13647, -13696, -13745, -13794, -13843, -13892, -13941, -13990, -14040, -14089, -14138, -14187, -14236, -14285, -14334, -14383, -14432, -14481, -14530, -14579, -14628, -14677, -14726, -14775, -14824, -14873, -14922, -14971, -15020, -15069, -15118, -15167, -15215, -15264, -15313, -15362, -15411, -15460, -15509, -15557, -15606, -15655, -15704, -15753, -15802, -15850, -15899, -15948, -15997, -16045, -16094, -16143, -16191, -16240, -16289, -16338, -16386, -16435, -16484, -16532, -16581, -16629, -16678, -16727, -16775, -16824, -16872, -16921, -16970, -17018, -17067, -17115, -17164, -17212, -17261, -17309, -17358, -17406, -17455, -17503, -17551, -17600, -17648, -17697, -17745, -17793, -17842, -17890, -17939, -17987, -18035, -18084, -18132, -18180, -18228, -18277, -18325, -18373, -18421, -18470, -18518, -18566, -18614, -18663, -18711, -18759, -18807, -18855, -18903, -18951, -19000, -19048, -19096, -19144, -19192, -19240, -19288, -19336, -19384, -19432, -19480, -19528, -19576, -19624, -19672, -19720, -19768, -19816, -19864, -19912, -19959, -20007, -20055, -20103, -20151, -20199, -20246, -20294, -20342, -20390, -20438, -20485, -20533, -20581, -20629, -20676, -20724, -20772, -20819, -20867, -20915, -20962, -21010, -21057, -21105, -21153, -21200, -21248, -21295, -21343, -21390, -21438, -21485, -21533, -21580, -21628, -21675, -21723, -21770, -21817, -21865, -21912, -21960, -22007, -22054, -22102, -22149, -22196, -22243, -22291, -22338, -22385, -22433, -22480, -22527, -22574, -22621, -22668, -22716, -22763, -22810, -22857, -22904, -22951, -22998, -23045, -23092, -23139, -23186, -23233, -23280, -23327, -23374, -23421, -23468, -23515, -23562, -23609, -23656, -23703, -23750, -23796, -23843, -23890, -23937, -23984, -24030, -24077, -24124, -24171, -24217, -24264, -24311, -24357, -24404, -24451, -24497, -24544, -24591, -24637, -24684, -24730, -24777, -24823, -24870, -24916, -24963, -25009, -25056, -25102, -25149, -25195, -25241, -25288, -25334, -25381, -25427, -25473, -25520, -25566, -25612, -25658, -25705, -25751, -25797, -25843, -25889, -25936, -25982, -26028, -26074, -26120, -26166, -26212, -26258, -26304, -26350, -26396, -26442, -26488, -26534, -26580, -26626, -26672, -26718, -26764, -26810, -26856, -26902, -26947, -26993, -27039, -27085, -27131, -27176, -27222, -27268, -27313, -27359, -27405, -27450, -27496, -27542, -27587, -27633, -27678, -27724, -27770, -27815, -27861, -27906, -27952, -27997, -28042, -28088, -28133, -28179, -28224, -28269, -28315, -28360, -28405, -28451, -28496, -28541, -28586, -28632, -28677, -28722, -28767, -28812, -28858, -28903, -28948, -28993, -29038, -29083, -29128, -29173, -29218, -29263, -29308, -29353, -29398, -29443, -29488, -29533, -29577, -29622, -29667, -29712, -29757, -29801, -29846, -29891, -29936, -29980, -30025, -30070, -30114, -30159, -30204, -30248, -30293, -30337, -30382, -30426, -30471, -30515, -30560, -30604, -30649, -30693, -30738, -30782, -30826, -30871, -30915, -30959, -31004, -31048, -31092, -31136, -31181, -31225, -31269, -31313, -31357, -31402, -31446, -31490, -31534, -31578, -31622, -31666, -31710, -31754, -31798, -31842, -31886, -31930, -31974, -32017, -32061, -32105, -32149, -32193, -32236, -32280, -32324, -32368, -32411, -32455, -32499, -32542, -32586, -32630, -32673, -32717, -32760, -32804, -32847, -32891, -32934, -32978, -33021, -33065, -33108, -33151, -33195, -33238, -33281, -33325, -33368, -33411, -33454, -33498, -33541, -33584, -33627, -33670, -33713, -33756, -33799, -33843, -33886, -33929, -33972, -34015, -34057, -34100, -34143, -34186, -34229, -34272, -34315, -34358, -34400, -34443, -34486, -34529, -34571, -34614, -34657, -34699, -34742, -34785, -34827, -34870, -34912, -34955, -34997, -35040, -35082, -35125, -35167, -35210, -35252, -35294, -35337, -35379, -35421, -35464, -35506, -35548, -35590, -35633, -35675, -35717, -35759, -35801, -35843, -35885, -35927, -35969, -36011, -36053, -36095, -36137, -36179, -36221, -36263, -36305, -36347, -36388, -36430, -36472, -36514, -36555, -36597, -36639, -36681, -36722, -36764, -36805, -36847, -36889, -36930, -36972, -37013, -37055, -37096, -37137, -37179, -37220, -37262, -37303, -37344, -37386, -37427, -37468, -37509, -37551, -37592, -37633, -37674, -37715, -37756, -37797, -37838, -37879, -37920, -37961, -38002, -38043, -38084, -38125, -38166, -38207, -38248, -38288, -38329, -38370, -38411, -38451, -38492, -38533, -38573, -38614, -38655, -38695, -38736, -38776, -38817, -38857, -38898, -38938, -38979, -39019, -39059, -39100, -39140, -39180, -39221, -39261, -39301, -39341, -39382, -39422, -39462, -39502, -39542, -39582, -39622, -39662, -39702, -39742, -39782, -39822, -39862, -39902, -39942, -39982, -40021, -40061, -40101, -40141, -40180, -40220, -40260, -40299, -40339, -40379, -40418, -40458, -40497, -40537, -40576, -40616, -40655, -40695, -40734, -40773, -40813, -40852, -40891, -40931, -40970, -41009, -41048, -41087, -41127, -41166, -41205, -41244, -41283, -41322, -41361, -41400, -41439, -41478, -41517, -41556, -41595, -41633, -41672, -41711, -41750, -41788, -41827, -41866, -41904, -41943, -41982, -42020, -42059, -42097, -42136, -42174, -42213, -42251, -42290, -42328, -42366, -42405, -42443, -42481, -42520, -42558, -42596, -42634, -42672, -42711, -42749, -42787, -42825, -42863, -42901, -42939, -42977, -43015, -43053, -43091, -43128, -43166, -43204, -43242, -43280, -43317, -43355, -43393, -43430, -43468, -43506, -43543, -43581, -43618, -43656, -43693, -43731, -43768, -43806, -43843, -43880, -43918, -43955, -43992, -44029, -44067, -44104, -44141, -44178, -44215, -44252, -44289, -44326, -44363, -44400, -44437, -44474, -44511, -44548, -44585, -44622, -44659, -44695, -44732, -44769, -44806, -44842, -44879, -44915, -44952, -44989, -45025, -45062, -45098, -45135, -45171, -45207, -45244, -45280, -45316, -45353, -45389, -45425, -45462, -45498, -45534, -45570, -45606, -45642, -45678, -45714, -45750, -45786, -45822, -45858, -45894, -45930, -45966, -46002, -46037, -46073, -46109, -46145, -46180, -46216, -46252, -46287, -46323, -46358, -46394, -46429, -46465, -46500, -46536, -46571, -46606, -46642, -46677, -46712, -46747, -46783, -46818, -46853, -46888, -46923, -46958, -46993, -47028, -47063, -47098, -47133, -47168, -47203, -47238, -47273, -47308, -47342, -47377, -47412, -47446, -47481, -47516, -47550, -47585, -47619, -47654, -47688, -47723, -47757, -47792, -47826, -47860, -47895, -47929, -47963, -47998, -48032, -48066, -48100, -48134, -48168, -48202, -48236, -48271, -48304, -48338, -48372, -48406, -48440, -48474, -48508, -48542, -48575, -48609, -48643, -48676, -48710, -48744, -48777, -48811, -48844, -48878, -48911, -48945, -48978, -49012, -49045, -49078, -49112, -49145, -49178, -49211, -49244, -49278, -49311, -49344, -49377, -49410, -49443, -49476, -49509, -49542, -49575, -49608, -49640, -49673, -49706, -49739, -49771, -49804, -49837, -49869, -49902, -49935, -49967, -50000, -50032, -50065, -50097, -50129, -50162, -50194, -50226, -50259, -50291, -50323, -50355, -50387, -50420, -50452, -50484, -50516, -50548, -50580, -50612, -50644, -50675, -50707, -50739, -50771, -50803, -50834, -50866, -50898, -50929, -50961, -50993, -51024, -51056, -51087, -51119, -51150, -51182, -51213, -51244, -51276, -51307, -51338, -51369, -51401, -51432, -51463, -51494, -51525, -51556, -51587, -51618, -51649, -51680, -51711, -51742, -51773, -51803, -51834, -51865, -51896, -51926, -51957, -51988, -52018, -52049, -52079, -52110, -52140, -52171, -52201, -52231, -52262, -52292, -52322, -52353, -52383, -52413, -52443, -52473, -52503, -52534, -52564, -52594, -52624, -52653, -52683, -52713, -52743, -52773, -52803, -52832, -52862, -52892, -52922, -52951, -52981, -53010, -53040, -53069, -53099, -53128, -53158, -53187, -53216, -53246, -53275, -53304, -53334, -53363, -53392, -53421, -53450, -53479, -53508, -53537, -53566, -53595, -53624, -53653, -53682, -53711, -53739, -53768, -53797, -53826, -53854, -53883, -53911, -53940, -53969, -53997, -54026, -54054, -54082, -54111, -54139, -54167, -54196, -54224, -54252, -54280, -54308, -54337, -54365, -54393, -54421, -54449, -54477, -54505, -54533, -54560, -54588, -54616, -54644, -54672, -54699, -54727, -54755, -54782, -54810, -54837, -54865, -54892, -54920, -54947, -54974, -55002, -55029, -55056, -55084, -55111, -55138, -55165, -55192, -55219, -55246, -55274, -55300, -55327, -55354, -55381, -55408, -55435, -55462, -55489, -55515, -55542, -55569, -55595, -55622, -55648, -55675, -55701, -55728, -55754, -55781, -55807, -55833, -55860, -55886, -55912, -55938, -55965, -55991, -56017, -56043, -56069, -56095, -56121, -56147, -56173, -56199, -56225, -56250, -56276, -56302, -56328, -56353, -56379, -56404, -56430, -56456, -56481, -56507, -56532, -56557, -56583, -56608, -56633, -56659, -56684, -56709, -56734, -56760, -56785, -56810, -56835, -56860, -56885, -56910, -56935, -56959, -56984, -57009, -57034, -57059, -57083, -57108, -57133, -57157, -57182, -57206, -57231, -57255, -57280, -57304, -57329, -57353, -57377, -57402, -57426, -57450, -57474, -57498, -57522, -57546, -57570, -57594, -57618, -57642, -57666, -57690, -57714, -57738, -57762, -57785, -57809, -57833, -57856, -57880, -57903, -57927, -57950, -57974, -57997, -58021, -58044, -58067, -58091, -58114, -58137, -58160, -58183, -58207, -58230, -58253, -58276, -58299, -58322, -58345, -58367, -58390, -58413, -58436, -58459, -58481, -58504, -58527, -58549, -58572, -58594, -58617, -58639, -58662, -58684, -58706, -58729, -58751, -58773, -58795, -58818, -58840, -58862, -58884, -58906, -58928, -58950, -58972, -58994, -59016, -59038, -59059, -59081, -59103, -59125, -59146, -59168, -59190, -59211, -59233, -59254, -59276, -59297, -59318, -59340, -59361, -59382, -59404, -59425, -59446, -59467, -59488, -59509, -59530, -59551, -59572, -59593, -59614, -59635, -59656, -59677, -59697, -59718, -59739, -59759, -59780, -59801, -59821, -59842, -59862, -59883, -59903, -59923, -59944, -59964, -59984, -60004, -60025, -60045, -60065, -60085, -60105, -60125, -60145, -60165, -60185, -60205, -60225, -60244, -60264, -60284, -60304, -60323, -60343, -60363, -60382, -60402, -60421, -60441, -60460, -60479, -60499, -60518, -60537, -60556, -60576, -60595, -60614, -60633, -60652, -60671, -60690, -60709, -60728, -60747, -60766, -60785, -60803, -60822, -60841, -60859, -60878, -60897, -60915, -60934, -60952, -60971, -60989, -61007, -61026, -61044, -61062, -61081, -61099, -61117, -61135, -61153, -61171, -61189, -61207, -61225, -61243, -61261, -61279, -61297, -61314, -61332, -61350, -61367, -61385, -61403, -61420, -61438, -61455, -61473, -61490, -61507, -61525, -61542, -61559, -61577, -61594, -61611, -61628, -61645, -61662, -61679, -61696, -61713, -61730, -61747, -61764, -61780, -61797, -61814, -61831, -61847, -61864, -61880, -61897, -61913, -61930, -61946, -61963, -61979, -61995, -62012, -62028, -62044, -62060, -62076, -62092, -62108, -62125, -62141, -62156, -62172, -62188, -62204, -62220, -62236, -62251, -62267, -62283, -62298, -62314, -62329, -62345, -62360, -62376, -62391, -62407, -62422, -62437, -62453, -62468, -62483, -62498, -62513, -62528, -62543, -62558, -62573, -62588, -62603, -62618, -62633, -62648, -62662, -62677, -62692, -62706, -62721, -62735, -62750, -62764, -62779, -62793, -62808, -62822, -62836, -62850, -62865, -62879, -62893, -62907, -62921, -62935, -62949, -62963, -62977, -62991, -63005, -63019, -63032, -63046, -63060, -63074, -63087, -63101, -63114, -63128, -63141, -63155, -63168, -63182, -63195, -63208, -63221, -63235, -63248, -63261, -63274, -63287, -63300, -63313, -63326, -63339, -63352, -63365, -63378, -63390, -63403, -63416, -63429, -63441, -63454, -63466, -63479, -63491, -63504, -63516, -63528, -63541, -63553, -63565, -63578, -63590, -63602, -63614, -63626, -63638, -63650, -63662, -63674, -63686, -63698, -63709, -63721, -63733, -63745, -63756, -63768, -63779, -63791, -63803, -63814, -63825, -63837, -63848, -63859, -63871, -63882, -63893, -63904, -63915, -63927, -63938, -63949, -63960, -63971, -63981, -63992, -64003, -64014, -64025, -64035, -64046, -64057, -64067, -64078, -64088, -64099, -64109, -64120, -64130, -64140, -64151, -64161, -64171, -64181, -64192, -64202, -64212, -64222, -64232, -64242, -64252, -64261, -64271, -64281, -64291, -64301, -64310, -64320, -64330, -64339, -64349, -64358, -64368, -64377, -64387, -64396, -64405, -64414, -64424, -64433, -64442, -64451, -64460, -64469, -64478, -64487, -64496, -64505, -64514, -64523, -64532, -64540, -64549, -64558, -64566, -64575, -64584, -64592, -64601, -64609, -64617, -64626, -64634, -64642, -64651, -64659, -64667, -64675, -64683, -64691, -64699, -64707, -64715, -64723, -64731, -64739, -64747, -64754, -64762, -64770, -64777, -64785, -64793, -64800, -64808, -64815, -64822, -64830, -64837, -64844, -64852, -64859, -64866, -64873, -64880, -64887, -64895, -64902, -64908, -64915, -64922, -64929, -64936, -64943, -64949, -64956, -64963, -64969, -64976, -64982, -64989, -64995, -65002, -65008, -65015, -65021, -65027, -65033, -65040, -65046, -65052, -65058, -65064, -65070, -65076, -65082, -65088, -65094, -65099, -65105, -65111, -65117, -65122, -65128, -65133, -65139, -65144, -65150, -65155, -65161, -65166, -65171, -65177, -65182, -65187, -65192, -65197, -65202, -65207, -65212, -65217, -65222, -65227, -65232, -65237, -65242, -65246, -65251, -65256, -65260, -65265, -65270, -65274, -65279, -65283, -65287, -65292, -65296, -65300, -65305, -65309, -65313, -65317, -65321, -65325, -65329, -65333, -65337, -65341, -65345, -65349, -65352, -65356, -65360, -65363, -65367, -65371, -65374, -65378, -65381, -65385, -65388, -65391, -65395, -65398, -65401, -65404, -65408, -65411, -65414, -65417, -65420, -65423, -65426, -65429, -65431, -65434, -65437, -65440, -65442, -65445, -65448, -65450, -65453, -65455, -65458, -65460, -65463, -65465, -65467, -65470, -65472, -65474, -65476, -65478, -65480, -65482, -65484, -65486, -65488, -65490, -65492, -65494, -65496, -65497, -65499, -65501, -65502, -65504, -65505, -65507, -65508, -65510, -65511, -65513, -65514, -65515, -65516, -65518, -65519, -65520, -65521, -65522, -65523, -65524, -65525, -65526, -65527, -65527, -65528, -65529, -65530, -65530, -65531, -65531, -65532, -65532, -65533, -65533, -65534, -65534, -65534, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65534, -65534, -65534, -65533, -65533, -65532, -65532, -65531, -65531, -65530, -65530, -65529, -65528, -65527, -65527, -65526, -65525, -65524, -65523, -65522, -65521, -65520, -65519, -65518, -65516, -65515, -65514, -65513, -65511, -65510, -65508, -65507, -65505, -65504, -65502, -65501, -65499, -65497, -65496, -65494, -65492, -65490, -65488, -65486, -65484, -65482, -65480, -65478, -65476, -65474, -65472, -65470, -65467, -65465, -65463, -65460, -65458, -65455, -65453, -65450, -65448, -65445, -65442, -65440, -65437, -65434, -65431, -65429, -65426, -65423, -65420, -65417, -65414, -65411, -65408, -65404, -65401, -65398, -65395, -65391, -65388, -65385, -65381, -65378, -65374, -65371, -65367, -65363, -65360, -65356, -65352, -65349, -65345, -65341, -65337, -65333, -65329, -65325, -65321, -65317, -65313, -65309, -65305, -65300, -65296, -65292, -65287, -65283, -65279, -65274, -65270, -65265, -65260, -65256, -65251, -65246, -65242, -65237, -65232, -65227, -65222, -65217, -65212, -65207, -65202, -65197, -65192, -65187, -65182, -65177, -65171, -65166, -65161, -65155, -65150, -65144, -65139, -65133, -65128, -65122, -65117, -65111, -65105, -65099, -65094, -65088, -65082, -65076, -65070, -65064, -65058, -65052, -65046, -65040, -65033, -65027, -65021, -65015, -65008, -65002, -64995, -64989, -64982, -64976, -64969, -64963, -64956, -64949, -64943, -64936, -64929, -64922, -64915, -64908, -64902, -64895, -64887, -64880, -64873, -64866, -64859, -64852, -64844, -64837, -64830, -64822, -64815, -64808, -64800, -64793, -64785, -64777, -64770, -64762, -64754, -64747, -64739, -64731, -64723, -64715, -64707, -64699, -64691, -64683, -64675, -64667, -64659, -64651, -64642, -64634, -64626, -64617, -64609, -64601, -64592, -64584, -64575, -64566, -64558, -64549, -64540, -64532, -64523, -64514, -64505, -64496, -64487, -64478, -64469, -64460, -64451, -64442, -64433, -64424, -64414, -64405, -64396, -64387, -64377, -64368, -64358, -64349, -64339, -64330, -64320, -64310, -64301, -64291, -64281, -64271, -64261, -64252, -64242, -64232, -64222, -64212, -64202, -64192, -64181, -64171, -64161, -64151, -64140, -64130, -64120, -64109, -64099, -64088, -64078, -64067, -64057, -64046, -64035, -64025, -64014, -64003, -63992, -63981, -63971, -63960, -63949, -63938, -63927, -63915, -63904, -63893, -63882, -63871, -63859, -63848, -63837, -63825, -63814, -63803, -63791, -63779, -63768, -63756, -63745, -63733, -63721, -63709, -63698, -63686, -63674, -63662, -63650, -63638, -63626, -63614, -63602, -63590, -63578, -63565, -63553, -63541, -63528, -63516, -63504, -63491, -63479, -63466, -63454, -63441, -63429, -63416, -63403, -63390, -63378, -63365, -63352, -63339, -63326, -63313, -63300, -63287, -63274, -63261, -63248, -63235, -63221, -63208, -63195, -63182, -63168, -63155, -63141, -63128, -63114, -63101, -63087, -63074, -63060, -63046, -63032, -63019, -63005, -62991, -62977, -62963, -62949, -62935, -62921, -62907, -62893, -62879, -62865, -62850, -62836, -62822, -62808, -62793, -62779, -62764, -62750, -62735, -62721, -62706, -62692, -62677, -62662, -62648, -62633, -62618, -62603, -62588, -62573, -62558, -62543, -62528, -62513, -62498, -62483, -62468, -62453, -62437, -62422, -62407, -62391, -62376, -62360, -62345, -62329, -62314, -62298, -62283, -62267, -62251, -62236, -62220, -62204, -62188, -62172, -62156, -62141, -62125, -62108, -62092, -62076, -62060, -62044, -62028, -62012, -61995, -61979, -61963, -61946, -61930, -61913, -61897, -61880, -61864, -61847, -61831, -61814, -61797, -61780, -61764, -61747, -61730, -61713, -61696, -61679, -61662, -61645, -61628, -61611, -61594, -61577, -61559, -61542, -61525, -61507, -61490, -61473, -61455, -61438, -61420, -61403, -61385, -61367, -61350, -61332, -61314, -61297, -61279, -61261, -61243, -61225, -61207, -61189, -61171, -61153, -61135, -61117, -61099, -61081, -61062, -61044, -61026, -61007, -60989, -60971, -60952, -60934, -60915, -60897, -60878, -60859, -60841, -60822, -60803, -60785, -60766, -60747, -60728, -60709, -60690, -60671, -60652, -60633, -60614, -60595, -60576, -60556, -60537, -60518, -60499, -60479, -60460, -60441, -60421, -60402, -60382, -60363, -60343, -60323, -60304, -60284, -60264, -60244, -60225, -60205, -60185, -60165, -60145, -60125, -60105, -60085, -60065, -60045, -60025, -60004, -59984, -59964, -59944, -59923, -59903, -59883, -59862, -59842, -59821, -59801, -59780, -59759, -59739, -59718, -59697, -59677, -59656, -59635, -59614, -59593, -59572, -59551, -59530, -59509, -59488, -59467, -59446, -59425, -59404, -59382, -59361, -59340, -59318, -59297, -59276, -59254, -59233, -59211, -59189, -59168, -59146, -59125, -59103, -59081, -59059, -59038, -59016, -58994, -58972, -58950, -58928, -58906, -58884, -58862, -58840, -58818, -58795, -58773, -58751, -58729, -58706, -58684, -58662, -58639, -58617, -58594, -58572, -58549, -58527, -58504, -58481, -58459, -58436, -58413, -58390, -58367, -58345, -58322, -58299, -58276, -58253, -58230, -58207, -58183, -58160, -58137, -58114, -58091, -58067, -58044, -58021, -57997, -57974, -57950, -57927, -57903, -57880, -57856, -57833, -57809, -57785, -57762, -57738, -57714, -57690, -57666, -57642, -57618, -57594, -57570, -57546, -57522, -57498, -57474, -57450, -57426, -57402, -57377, -57353, -57329, -57304, -57280, -57255, -57231, -57206, -57182, -57157, -57133, -57108, -57083, -57059, -57034, -57009, -56984, -56959, -56935, -56910, -56885, -56860, -56835, -56810, -56785, -56760, -56734, -56709, -56684, -56659, -56633, -56608, -56583, -56557, -56532, -56507, -56481, -56456, -56430, -56404, -56379, -56353, -56328, -56302, -56276, -56250, -56225, -56199, -56173, -56147, -56121, -56095, -56069, -56043, -56017, -55991, -55965, -55938, -55912, -55886, -55860, -55833, -55807, -55781, -55754, -55728, -55701, -55675, -55648, -55622, -55595, -55569, -55542, -55515, -55489, -55462, -55435, -55408, -55381, -55354, -55327, -55300, -55274, -55246, -55219, -55192, -55165, -55138, -55111, -55084, -55056, -55029, -55002, -54974, -54947, -54920, -54892, -54865, -54837, -54810, -54782, -54755, -54727, -54699, -54672, -54644, -54616, -54588, -54560, -54533, -54505, -54477, -54449, -54421, -54393, -54365, -54337, -54308, -54280, -54252, -54224, -54196, -54167, -54139, -54111, -54082, -54054, -54026, -53997, -53969, -53940, -53911, -53883, -53854, -53826, -53797, -53768, -53739, -53711, -53682, -53653, -53624, -53595, -53566, -53537, -53508, -53479, -53450, -53421, -53392, -53363, -53334, -53304, -53275, -53246, -53216, -53187, -53158, -53128, -53099, -53069, -53040, -53010, -52981, -52951, -52922, -52892, -52862, -52832, -52803, -52773, -52743, -52713, -52683, -52653, -52624, -52594, -52564, -52534, -52503, -52473, -52443, -52413, -52383, -52353, -52322, -52292, -52262, -52231, -52201, -52171, -52140, -52110, -52079, -52049, -52018, -51988, -51957, -51926, -51896, -51865, -51834, -51803, -51773, -51742, -51711, -51680, -51649, -51618, -51587, -51556, -51525, -51494, -51463, -51432, -51401, -51369, -51338, -51307, -51276, -51244, -51213, -51182, -51150, -51119, -51087, -51056, -51024, -50993, -50961, -50929, -50898, -50866, -50834, -50803, -50771, -50739, -50707, -50675, -50644, -50612, -50580, -50548, -50516, -50484, -50452, -50420, -50387, -50355, -50323, -50291, -50259, -50226, -50194, -50162, -50129, -50097, -50065, -50032, -50000, -49967, -49935, -49902, -49869, -49837, -49804, -49771, -49739, -49706, -49673, -49640, -49608, -49575, -49542, -49509, -49476, -49443, -49410, -49377, -49344, -49311, -49278, -49244, -49211, -49178, -49145, -49112, -49078, -49045, -49012, -48978, -48945, -48911, -48878, -48844, -48811, -48777, -48744, -48710, -48676, -48643, -48609, -48575, -48542, -48508, -48474, -48440, -48406, -48372, -48338, -48305, -48271, -48237, -48202, -48168, -48134, -48100, -48066, -48032, -47998, -47963, -47929, -47895, -47860, -47826, -47792, -47757, -47723, -47688, -47654, -47619, -47585, -47550, -47516, -47481, -47446, -47412, -47377, -47342, -47307, -47273, -47238, -47203, -47168, -47133, -47098, -47063, -47028, -46993, -46958, -46923, -46888, -46853, -46818, -46783, -46747, -46712, -46677, -46642, -46606, -46571, -46536, -46500, -46465, -46429, -46394, -46358, -46323, -46287, -46251, -46216, -46180, -46145, -46109, -46073, -46037, -46002, -45966, -45930, -45894, -45858, -45822, -45786, -45750, -45714, -45678, -45642, -45606, -45570, -45534, -45498, -45462, -45425, -45389, -45353, -45316, -45280, -45244, -45207, -45171, -45135, -45098, -45062, -45025, -44989, -44952, -44915, -44879, -44842, -44806, -44769, -44732, -44695, -44659, -44622, -44585, -44548, -44511, -44474, -44437, -44400, -44363, -44326, -44289, -44252, -44215, -44178, -44141, -44104, -44067, -44029, -43992, -43955, -43918, -43880, -43843, -43806, -43768, -43731, -43693, -43656, -43618, -43581, -43543, -43506, -43468, -43430, -43393, -43355, -43317, -43280, -43242, -43204, -43166, -43128, -43091, -43053, -43015, -42977, -42939, -42901, -42863, -42825, -42787, -42749, -42711, -42672, -42634, -42596, -42558, -42520, -42481, -42443, -42405, -42366, -42328, -42290, -42251, -42213, -42174, -42136, -42097, -42059, -42020, -41982, -41943, -41904, -41866, -41827, -41788, -41750, -41711, -41672, -41633, -41595, -41556, -41517, -41478, -41439, -41400, -41361, -41322, -41283, -41244, -41205, -41166, -41127, -41087, -41048, -41009, -40970, -40931, -40891, -40852, -40813, -40773, -40734, -40695, -40655, -40616, -40576, -40537, -40497, -40458, -40418, -40379, -40339, -40299, -40260, -40220, -40180, -40141, -40101, -40061, -40021, -39982, -39942, -39902, -39862, -39822, -39782, -39742, -39702, -39662, -39622, -39582, -39542, -39502, -39462, -39422, -39382, -39341, -39301, -39261, -39221, -39180, -39140, -39100, -39059, -39019, -38979, -38938, -38898, -38857, -38817, -38776, -38736, -38695, -38655, -38614, -38573, -38533, -38492, -38451, -38411, -38370, -38329, -38288, -38248, -38207, -38166, -38125, -38084, -38043, -38002, -37961, -37920, -37879, -37838, -37797, -37756, -37715, -37674, -37633, -37592, -37550, -37509, -37468, -37427, -37386, -37344, -37303, -37262, -37220, -37179, -37137, -37096, -37055, -37013, -36972, -36930, -36889, -36847, -36805, -36764, -36722, -36681, -36639, -36597, -36556, -36514, -36472, -36430, -36388, -36347, -36305, -36263, -36221, -36179, -36137, -36095, -36053, -36011, -35969, -35927, -35885, -35843, -35801, -35759, -35717, -35675, -35633, -35590, -35548, -35506, -35464, -35421, -35379, -35337, -35294, -35252, -35210, -35167, -35125, -35082, -35040, -34997, -34955, -34912, -34870, -34827, -34785, -34742, -34699, -34657, -34614, -34571, -34529, -34486, -34443, -34400, -34358, -34315, -34272, -34229, -34186, -34143, -34100, -34057, -34015, -33972, -33929, -33886, -33843, -33799, -33756, -33713, -33670, -33627, -33584, -33541, -33498, -33454, -33411, -33368, -33325, -33281, -33238, -33195, -33151, -33108, -33065, -33021, -32978, -32934, -32891, -32847, -32804, -32760, -32717, -32673, -32630, -32586, -32542, -32499, -32455, -32411, -32368, -32324, -32280, -32236, -32193, -32149, -32105, -32061, -32017, -31974, -31930, -31886, -31842, -31798, -31754, -31710, -31666, -31622, -31578, -31534, -31490, -31446, -31402, -31357, -31313, -31269, -31225, -31181, -31136, -31092, -31048, -31004, -30959, -30915, -30871, -30826, -30782, -30738, -30693, -30649, -30604, -30560, -30515, -30471, -30426, -30382, -30337, -30293, -30248, -30204, -30159, -30114, -30070, -30025, -29980, -29936, -29891, -29846, -29801, -29757, -29712, -29667, -29622, -29577, -29533, -29488, -29443, -29398, -29353, -29308, -29263, -29218, -29173, -29128, -29083, -29038, -28993, -28948, -28903, -28858, -28812, -28767, -28722, -28677, -28632, -28586, -28541, -28496, -28451, -28405, -28360, -28315, -28269, -28224, -28179, -28133, -28088, -28042, -27997, -27952, -27906, -27861, -27815, -27770, -27724, -27678, -27633, -27587, -27542, -27496, -27450, -27405, -27359, -27313, -27268, -27222, -27176, -27131, -27085, -27039, -26993, -26947, -26902, -26856, -26810, -26764, -26718, -26672, -26626, -26580, -26534, -26488, -26442, -26396, -26350, -26304, -26258, -26212, -26166, -26120, -26074, -26028, -25982, -25936, -25889, -25843, -25797, -25751, -25705, -25658, -25612, -25566, -25520, -25473, -25427, -25381, -25334, -25288, -25241, -25195, -25149, -25102, -25056, -25009, -24963, -24916, -24870, -24823, -24777, -24730, -24684, -24637, -24591, -24544, -24497, -24451, -24404, -24357, -24311, -24264, -24217, -24171, -24124, -24077, -24030, -23984, -23937, -23890, -23843, -23796, -23750, -23703, -23656, -23609, -23562, -23515, -23468, -23421, -23374, -23327, -23280, -23233, -23186, -23139, -23092, -23045, -22998, -22951, -22904, -22857, -22810, -22763, -22716, -22668, -22621, -22574, -22527, -22480, -22432, -22385, -22338, -22291, -22243, -22196, -22149, -22102, -22054, -22007, -21960, -21912, -21865, -21817, -21770, -21723, -21675, -21628, -21580, -21533, -21485, -21438, -21390, -21343, -21295, -21248, -21200, -21153, -21105, -21057, -21010, -20962, -20915, -20867, -20819, -20772, -20724, -20676, -20629, -20581, -20533, -20485, -20438, -20390, -20342, -20294, -20246, -20199, -20151, -20103, -20055, -20007, -19959, -19912, -19864, -19816, -19768, -19720, -19672, -19624, -19576, -19528, -19480, -19432, -19384, -19336, -19288, -19240, -19192, -19144, -19096, -19048, -19000, -18951, -18903, -18855, -18807, -18759, -18711, -18663, -18614, -18566, -18518, -18470, -18421, -18373, -18325, -18277, -18228, -18180, -18132, -18084, -18035, -17987, -17939, -17890, -17842, -17793, -17745, -17697, -17648, -17600, -17551, -17503, -17455, -17406, -17358, -17309, -17261, -17212, -17164, -17115, -17067, -17018, -16970, -16921, -16872, -16824, -16775, -16727, -16678, -16629, -16581, -16532, -16484, -16435, -16386, -16338, -16289, -16240, -16191, -16143, -16094, -16045, -15997, -15948, -15899, -15850, -15802, -15753, -15704, -15655, -15606, -15557, -15509, -15460, -15411, -15362, -15313, -15264, -15215, -15167, -15118, -15069, -15020, -14971, -14922, -14873, -14824, -14775, -14726, -14677, -14628, -14579, -14530, -14481, -14432, -14383, -14334, -14285, -14236, -14187, -14138, -14089, -14040, -13990, -13941, -13892, -13843, -13794, -13745, -13696, -13647, -13597, -13548, -13499, -13450, -13401, -13351, -13302, -13253, -13204, -13154, -13105, -13056, -13007, -12957, -12908, -12859, -12810, -12760, -12711, -12662, -12612, -12563, -12514, -12464, -12415, -12366, -12316, -12267, -12217, -12168, -12119, -12069, -12020, -11970, -11921, -11872, -11822, -11773, -11723, -11674, -11624, -11575, -11525, -11476, -11426, -11377, -11327, -11278, -11228, -11179, -11129, -11080, -11030, -10981, -10931, -10882, -10832, -10782, -10733, -10683, -10634, -10584, -10534, -10485, -10435, -10386, -10336, -10286, -10237, -10187, -10137, -10088, -10038, -9988, -9939, -9889, -9839, -9790, -9740, -9690, -9640, -9591, -9541, -9491, -9442, -9392, -9342, -9292, -9243, -9193, -9143, -9093, -9043, -8994, -8944, -8894, -8844, -8794, -8745, -8695, -8645, -8595, -8545, -8496, -8446, -8396, -8346, -8296, -8246, -8196, -8147, -8097, -8047, -7997, -7947, -7897, -7847, -7797, -7747, -7697, -7648, -7598, -7548, -7498, -7448, -7398, -7348, -7298, -7248, -7198, -7148, -7098, -7048, -6998, -6948, -6898, -6848, -6798, -6748, -6698, -6648, -6598, -6548, -6498, -6448, -6398, -6348, -6298, -6248, -6198, -6148, -6098, -6048, -5998, -5948, -5898, -5848, -5798, -5747, -5697, -5647, -5597, -5547, -5497, -5447, -5397, -5347, -5297, -5247, -5197, -5146, -5096, -5046, -4996, -4946, -4896, -4846, -4796, -4745, -4695, -4645, -4595, -4545, -4495, -4445, -4394, -4344, -4294, -4244, -4194, -4144, -4093, -4043, -3993, -3943, -3893, -3843, -3792, -3742, -3692, -3642, -3592, -3541, -3491, -3441, -3391, -3341, -3291, -3240, -3190, -3140, -3090, -3039, -2989, -2939, -2889, -2839, -2788, -2738, -2688, -2638, -2588, -2537, -2487, -2437, -2387, -2336, -2286, -2236, -2186, -2135, -2085, -2035, -1985, -1934, -1884, -1834, -1784, -1733, -1683, -1633, -1583, -1532, -1482, -1432, -1382, -1331, -1281, -1231, -1181, -1130, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3542, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5747, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22432, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30427, 30471, 30516, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36556, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40299, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47861, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50064, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53912, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54309, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64600, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535 }; angle_t tantoangle[2049] = { 0, 333772, 667544, 1001315, 1335086, 1668857, 2002626, 2336395, 2670163, 3003929, 3337694, 3671457, 4005219, 4338979, 4672736, 5006492, 5340245, 5673995, 6007743, 6341488, 6675230, 7008968, 7342704, 7676435, 8010164, 8343888, 8677609, 9011325, 9345037, 9678744, 10012447, 10346145, 10679838, 11013526, 11347209, 11680887, 12014558, 12348225, 12681885, 13015539, 13349187, 13682829, 14016464, 14350092, 14683714, 15017328, 15350936, 15684536, 16018129, 16351714, 16685291, 17018860, 17352422, 17685974, 18019518, 18353054, 18686582, 19020100, 19353610, 19687110, 20020600, 20354080, 20687552, 21021014, 21354466, 21687906, 22021338, 22354758, 22688168, 23021568, 23354956, 23688332, 24021698, 24355052, 24688396, 25021726, 25355046, 25688352, 26021648, 26354930, 26688200, 27021456, 27354702, 27687932, 28021150, 28354356, 28687548, 29020724, 29353888, 29687038, 30020174, 30353296, 30686404, 31019496, 31352574, 31685636, 32018684, 32351718, 32684734, 33017736, 33350722, 33683692, 34016648, 34349584, 34682508, 35015412, 35348300, 35681172, 36014028, 36346868, 36679688, 37012492, 37345276, 37678044, 38010792, 38343524, 38676240, 39008936, 39341612, 39674272, 40006912, 40339532, 40672132, 41004716, 41337276, 41669820, 42002344, 42334848, 42667332, 42999796, 43332236, 43664660, 43997060, 44329444, 44661800, 44994140, 45326456, 45658752, 45991028, 46323280, 46655512, 46987720, 47319908, 47652072, 47984212, 48316332, 48648428, 48980500, 49312548, 49644576, 49976580, 50308556, 50640512, 50972444, 51304352, 51636236, 51968096, 52299928, 52631740, 52963524, 53295284, 53627020, 53958728, 54290412, 54622068, 54953704, 55285308, 55616888, 55948444, 56279972, 56611472, 56942948, 57274396, 57605816, 57937212, 58268576, 58599916, 58931228, 59262512, 59593768, 59924992, 60256192, 60587364, 60918508, 61249620, 61580704, 61911760, 62242788, 62573788, 62904756, 63235692, 63566604, 63897480, 64228332, 64559148, 64889940, 65220696, 65551424, 65882120, 66212788, 66543420, 66874024, 67204600, 67535136, 67865648, 68196120, 68526568, 68856984, 69187360, 69517712, 69848024, 70178304, 70508560, 70838776, 71168960, 71499112, 71829224, 72159312, 72489360, 72819376, 73149360, 73479304, 73809216, 74139096, 74468936, 74798744, 75128520, 75458264, 75787968, 76117632, 76447264, 76776864, 77106424, 77435952, 77765440, 78094888, 78424304, 78753688, 79083032, 79412336, 79741608, 80070840, 80400032, 80729192, 81058312, 81387392, 81716432, 82045440, 82374408, 82703336, 83032224, 83361080, 83689896, 84018664, 84347400, 84676096, 85004760, 85333376, 85661952, 85990488, 86318984, 86647448, 86975864, 87304240, 87632576, 87960872, 88289128, 88617344, 88945520, 89273648, 89601736, 89929792, 90257792, 90585760, 90913688, 91241568, 91569408, 91897200, 92224960, 92552672, 92880336, 93207968, 93535552, 93863088, 94190584, 94518040, 94845448, 95172816, 95500136, 95827416, 96154648, 96481832, 96808976, 97136080, 97463136, 97790144, 98117112, 98444032, 98770904, 99097736, 99424520, 99751256, 100077944, 100404592, 100731192, 101057744, 101384248, 101710712, 102037128, 102363488, 102689808, 103016080, 103342312, 103668488, 103994616, 104320696, 104646736, 104972720, 105298656, 105624552, 105950392, 106276184, 106601928, 106927624, 107253272, 107578872, 107904416, 108229920, 108555368, 108880768, 109206120, 109531416, 109856664, 110181872, 110507016, 110832120, 111157168, 111482168, 111807112, 112132008, 112456856, 112781648, 113106392, 113431080, 113755720, 114080312, 114404848, 114729328, 115053760, 115378136, 115702464, 116026744, 116350960, 116675128, 116999248, 117323312, 117647320, 117971272, 118295176, 118619024, 118942816, 119266560, 119590248, 119913880, 120237456, 120560984, 120884456, 121207864, 121531224, 121854528, 122177784, 122500976, 122824112, 123147200, 123470224, 123793200, 124116120, 124438976, 124761784, 125084528, 125407224, 125729856, 126052432, 126374960, 126697424, 127019832, 127342184, 127664472, 127986712, 128308888, 128631008, 128953072, 129275080, 129597024, 129918912, 130240744, 130562520, 130884232, 131205888, 131527480, 131849016, 132170496, 132491912, 132813272, 133134576, 133455816, 133776992, 134098120, 134419184, 134740176, 135061120, 135382000, 135702816, 136023584, 136344272, 136664912, 136985488, 137306016, 137626464, 137946864, 138267184, 138587456, 138907664, 139227808, 139547904, 139867920, 140187888, 140507776, 140827616, 141147392, 141467104, 141786752, 142106336, 142425856, 142745312, 143064720, 143384048, 143703312, 144022512, 144341664, 144660736, 144979744, 145298704, 145617584, 145936400, 146255168, 146573856, 146892480, 147211040, 147529536, 147847968, 148166336, 148484640, 148802880, 149121056, 149439152, 149757200, 150075168, 150393072, 150710912, 151028688, 151346400, 151664048, 151981616, 152299136, 152616576, 152933952, 153251264, 153568496, 153885680, 154202784, 154519824, 154836784, 155153696, 155470528, 155787296, 156104000, 156420624, 156737200, 157053696, 157370112, 157686480, 158002768, 158318976, 158635136, 158951216, 159267232, 159583168, 159899040, 160214848, 160530592, 160846256, 161161840, 161477376, 161792832, 162108208, 162423520, 162738768, 163053952, 163369040, 163684080, 163999040, 164313936, 164628752, 164943504, 165258176, 165572784, 165887312, 166201776, 166516160, 166830480, 167144736, 167458912, 167773008, 168087040, 168400992, 168714880, 169028688, 169342432, 169656096, 169969696, 170283216, 170596672, 170910032, 171223344, 171536576, 171849728, 172162800, 172475808, 172788736, 173101600, 173414384, 173727104, 174039728, 174352288, 174664784, 174977200, 175289536, 175601792, 175913984, 176226096, 176538144, 176850096, 177161984, 177473792, 177785536, 178097200, 178408784, 178720288, 179031728, 179343088, 179654368, 179965568, 180276704, 180587744, 180898720, 181209616, 181520448, 181831184, 182141856, 182452448, 182762960, 183073408, 183383760, 183694048, 184004240, 184314368, 184624416, 184934400, 185244288, 185554096, 185863840, 186173504, 186483072, 186792576, 187102000, 187411344, 187720608, 188029808, 188338912, 188647936, 188956896, 189265760, 189574560, 189883264, 190191904, 190500448, 190808928, 191117312, 191425632, 191733872, 192042016, 192350096, 192658096, 192966000, 193273840, 193581584, 193889264, 194196848, 194504352, 194811792, 195119136, 195426400, 195733584, 196040688, 196347712, 196654656, 196961520, 197268304, 197574992, 197881616, 198188144, 198494592, 198800960, 199107248, 199413456, 199719584, 200025616, 200331584, 200637456, 200943248, 201248960, 201554576, 201860128, 202165584, 202470960, 202776256, 203081456, 203386592, 203691632, 203996592, 204301472, 204606256, 204910976, 205215600, 205520144, 205824592, 206128960, 206433248, 206737456, 207041584, 207345616, 207649568, 207953424, 208257216, 208560912, 208864512, 209168048, 209471488, 209774832, 210078112, 210381296, 210684384, 210987408, 211290336, 211593184, 211895936, 212198608, 212501184, 212803680, 213106096, 213408432, 213710672, 214012816, 214314880, 214616864, 214918768, 215220576, 215522288, 215823920, 216125472, 216426928, 216728304, 217029584, 217330784, 217631904, 217932928, 218233856, 218534704, 218835472, 219136144, 219436720, 219737216, 220037632, 220337952, 220638192, 220938336, 221238384, 221538352, 221838240, 222138032, 222437728, 222737344, 223036880, 223336304, 223635664, 223934912, 224234096, 224533168, 224832160, 225131072, 225429872, 225728608, 226027232, 226325776, 226624240, 226922608, 227220880, 227519056, 227817152, 228115168, 228413088, 228710912, 229008640, 229306288, 229603840, 229901312, 230198688, 230495968, 230793152, 231090256, 231387280, 231684192, 231981024, 232277760, 232574416, 232870960, 233167440, 233463808, 233760096, 234056288, 234352384, 234648384, 234944304, 235240128, 235535872, 235831504, 236127056, 236422512, 236717888, 237013152, 237308336, 237603424, 237898416, 238193328, 238488144, 238782864, 239077488, 239372016, 239666464, 239960816, 240255072, 240549232, 240843312, 241137280, 241431168, 241724960, 242018656, 242312256, 242605776, 242899200, 243192512, 243485744, 243778896, 244071936, 244364880, 244657744, 244950496, 245243168, 245535744, 245828224, 246120608, 246412912, 246705104, 246997216, 247289216, 247581136, 247872960, 248164688, 248456320, 248747856, 249039296, 249330640, 249621904, 249913056, 250204128, 250495088, 250785968, 251076736, 251367424, 251658016, 251948512, 252238912, 252529200, 252819408, 253109520, 253399536, 253689456, 253979280, 254269008, 254558640, 254848176, 255137632, 255426976, 255716224, 256005376, 256294432, 256583392, 256872256, 257161024, 257449696, 257738272, 258026752, 258315136, 258603424, 258891600, 259179696, 259467696, 259755600, 260043392, 260331104, 260618704, 260906224, 261193632, 261480960, 261768176, 262055296, 262342320, 262629248, 262916080, 263202816, 263489456, 263776000, 264062432, 264348784, 264635024, 264921168, 265207216, 265493168, 265779024, 266064784, 266350448, 266636000, 266921472, 267206832, 267492096, 267777264, 268062336, 268347312, 268632192, 268916960, 269201632, 269486208, 269770688, 270055072, 270339360, 270623552, 270907616, 271191616, 271475488, 271759296, 272042976, 272326560, 272610048, 272893440, 273176736, 273459936, 273743040, 274026048, 274308928, 274591744, 274874432, 275157024, 275439520, 275721920, 276004224, 276286432, 276568512, 276850528, 277132416, 277414240, 277695936, 277977536, 278259040, 278540448, 278821728, 279102944, 279384032, 279665056, 279945952, 280226752, 280507456, 280788064, 281068544, 281348960, 281629248, 281909472, 282189568, 282469568, 282749440, 283029248, 283308960, 283588544, 283868032, 284147424, 284426720, 284705920, 284985024, 285264000, 285542912, 285821696, 286100384, 286378976, 286657440, 286935840, 287214112, 287492320, 287770400, 288048384, 288326240, 288604032, 288881696, 289159264, 289436768, 289714112, 289991392, 290268576, 290545632, 290822592, 291099456, 291376224, 291652896, 291929440, 292205888, 292482272, 292758528, 293034656, 293310720, 293586656, 293862496, 294138240, 294413888, 294689440, 294964864, 295240192, 295515424, 295790560, 296065600, 296340512, 296615360, 296890080, 297164704, 297439200, 297713632, 297987936, 298262144, 298536256, 298810240, 299084160, 299357952, 299631648, 299905248, 300178720, 300452128, 300725408, 300998592, 301271680, 301544640, 301817536, 302090304, 302362976, 302635520, 302908000, 303180352, 303452608, 303724768, 303996800, 304268768, 304540608, 304812320, 305083968, 305355520, 305626944, 305898272, 306169472, 306440608, 306711616, 306982528, 307253344, 307524064, 307794656, 308065152, 308335552, 308605856, 308876032, 309146112, 309416096, 309685984, 309955744, 310225408, 310494976, 310764448, 311033824, 311303072, 311572224, 311841280, 312110208, 312379040, 312647776, 312916416, 313184960, 313453376, 313721696, 313989920, 314258016, 314526016, 314793920, 315061728, 315329408, 315597024, 315864512, 316131872, 316399168, 316666336, 316933408, 317200384, 317467232, 317733984, 318000640, 318267200, 318533632, 318799968, 319066208, 319332352, 319598368, 319864288, 320130112, 320395808, 320661408, 320926912, 321192320, 321457632, 321722816, 321987904, 322252864, 322517760, 322782528, 323047200, 323311744, 323576192, 323840544, 324104800, 324368928, 324632992, 324896928, 325160736, 325424448, 325688096, 325951584, 326215008, 326478304, 326741504, 327004608, 327267584, 327530464, 327793248, 328055904, 328318496, 328580960, 328843296, 329105568, 329367712, 329629760, 329891680, 330153536, 330415264, 330676864, 330938400, 331199808, 331461120, 331722304, 331983392, 332244384, 332505280, 332766048, 333026752, 333287296, 333547776, 333808128, 334068384, 334328544, 334588576, 334848512, 335108352, 335368064, 335627712, 335887200, 336146624, 336405920, 336665120, 336924224, 337183200, 337442112, 337700864, 337959552, 338218112, 338476576, 338734944, 338993184, 339251328, 339509376, 339767296, 340025120, 340282848, 340540480, 340797984, 341055392, 341312704, 341569888, 341826976, 342083968, 342340832, 342597600, 342854272, 343110848, 343367296, 343623648, 343879904, 344136032, 344392064, 344648000, 344903808, 345159520, 345415136, 345670656, 345926048, 346181344, 346436512, 346691616, 346946592, 347201440, 347456224, 347710880, 347965440, 348219872, 348474208, 348728448, 348982592, 349236608, 349490528, 349744320, 349998048, 350251648, 350505152, 350758528, 351011808, 351264992, 351518048, 351771040, 352023872, 352276640, 352529280, 352781824, 353034272, 353286592, 353538816, 353790944, 354042944, 354294880, 354546656, 354798368, 355049952, 355301440, 355552800, 355804096, 356055264, 356306304, 356557280, 356808128, 357058848, 357309504, 357560032, 357810464, 358060768, 358311008, 358561088, 358811104, 359060992, 359310784, 359560480, 359810048, 360059520, 360308896, 360558144, 360807296, 361056352, 361305312, 361554144, 361802880, 362051488, 362300032, 362548448, 362796736, 363044960, 363293056, 363541024, 363788928, 364036704, 364284384, 364531936, 364779392, 365026752, 365274016, 365521152, 365768192, 366015136, 366261952, 366508672, 366755296, 367001792, 367248192, 367494496, 367740704, 367986784, 368232768, 368478656, 368724416, 368970080, 369215648, 369461088, 369706432, 369951680, 370196800, 370441824, 370686752, 370931584, 371176288, 371420896, 371665408, 371909792, 372154080, 372398272, 372642336, 372886304, 373130176, 373373952, 373617600, 373861152, 374104608, 374347936, 374591168, 374834304, 375077312, 375320224, 375563040, 375805760, 376048352, 376290848, 376533248, 376775520, 377017696, 377259776, 377501728, 377743584, 377985344, 378227008, 378468544, 378709984, 378951328, 379192544, 379433664, 379674688, 379915584, 380156416, 380397088, 380637696, 380878176, 381118560, 381358848, 381599040, 381839104, 382079072, 382318912, 382558656, 382798304, 383037856, 383277280, 383516640, 383755840, 383994976, 384233984, 384472896, 384711712, 384950400, 385188992, 385427488, 385665888, 385904160, 386142336, 386380384, 386618368, 386856224, 387093984, 387331616, 387569152, 387806592, 388043936, 388281152, 388518272, 388755296, 388992224, 389229024, 389465728, 389702336, 389938816, 390175200, 390411488, 390647680, 390883744, 391119712, 391355584, 391591328, 391826976, 392062528, 392297984, 392533312, 392768544, 393003680, 393238720, 393473632, 393708448, 393943168, 394177760, 394412256, 394646656, 394880960, 395115136, 395349216, 395583200, 395817088, 396050848, 396284512, 396518080, 396751520, 396984864, 397218112, 397451264, 397684288, 397917248, 398150080, 398382784, 398615424, 398847936, 399080320, 399312640, 399544832, 399776928, 400008928, 400240832, 400472608, 400704288, 400935872, 401167328, 401398720, 401629984, 401861120, 402092192, 402323136, 402553984, 402784736, 403015360, 403245888, 403476320, 403706656, 403936896, 404167008, 404397024, 404626944, 404856736, 405086432, 405316032, 405545536, 405774912, 406004224, 406233408, 406462464, 406691456, 406920320, 407149088, 407377760, 407606336, 407834784, 408063136, 408291392, 408519520, 408747584, 408975520, 409203360, 409431072, 409658720, 409886240, 410113664, 410340992, 410568192, 410795296, 411022304, 411249216, 411476032, 411702720, 411929312, 412155808, 412382176, 412608480, 412834656, 413060736, 413286720, 413512576, 413738336, 413964000, 414189568, 414415040, 414640384, 414865632, 415090784, 415315840, 415540800, 415765632, 415990368, 416215008, 416439552, 416663968, 416888288, 417112512, 417336640, 417560672, 417784576, 418008384, 418232096, 418455712, 418679200, 418902624, 419125920, 419349120, 419572192, 419795200, 420018080, 420240864, 420463552, 420686144, 420908608, 421130976, 421353280, 421575424, 421797504, 422019488, 422241344, 422463104, 422684768, 422906336, 423127776, 423349120, 423570400, 423791520, 424012576, 424233536, 424454368, 424675104, 424895744, 425116288, 425336736, 425557056, 425777280, 425997408, 426217440, 426437376, 426657184, 426876928, 427096544, 427316064, 427535488, 427754784, 427974016, 428193120, 428412128, 428631040, 428849856, 429068544, 429287168, 429505664, 429724064, 429942368, 430160576, 430378656, 430596672, 430814560, 431032352, 431250048, 431467616, 431685120, 431902496, 432119808, 432336992, 432554080, 432771040, 432987936, 433204736, 433421408, 433637984, 433854464, 434070848, 434287104, 434503296, 434719360, 434935360, 435151232, 435367008, 435582656, 435798240, 436013696, 436229088, 436444352, 436659520, 436874592, 437089568, 437304416, 437519200, 437733856, 437948416, 438162880, 438377248, 438591520, 438805696, 439019744, 439233728, 439447584, 439661344, 439875008, 440088576, 440302048, 440515392, 440728672, 440941824, 441154880, 441367872, 441580736, 441793472, 442006144, 442218720, 442431168, 442643552, 442855808, 443067968, 443280032, 443492000, 443703872, 443915648, 444127296, 444338880, 444550336, 444761696, 444972992, 445184160, 445395232, 445606176, 445817056, 446027840, 446238496, 446449088, 446659552, 446869920, 447080192, 447290400, 447500448, 447710432, 447920320, 448130112, 448339776, 448549376, 448758848, 448968224, 449177536, 449386720, 449595808, 449804800, 450013664, 450222464, 450431168, 450639776, 450848256, 451056640, 451264960, 451473152, 451681248, 451889248, 452097152, 452304960, 452512672, 452720288, 452927808, 453135232, 453342528, 453549760, 453756864, 453963904, 454170816, 454377632, 454584384, 454791008, 454997536, 455203968, 455410304, 455616544, 455822688, 456028704, 456234656, 456440512, 456646240, 456851904, 457057472, 457262912, 457468256, 457673536, 457878688, 458083744, 458288736, 458493600, 458698368, 458903040, 459107616, 459312096, 459516480, 459720768, 459924960, 460129056, 460333056, 460536960, 460740736, 460944448, 461148064, 461351584, 461554976, 461758304, 461961536, 462164640, 462367680, 462570592, 462773440, 462976160, 463178816, 463381344, 463583776, 463786144, 463988384, 464190560, 464392608, 464594560, 464796448, 464998208, 465199872, 465401472, 465602944, 465804320, 466005600, 466206816, 466407904, 466608896, 466809824, 467010624, 467211328, 467411936, 467612480, 467812896, 468013216, 468213440, 468413600, 468613632, 468813568, 469013440, 469213184, 469412832, 469612416, 469811872, 470011232, 470210528, 470409696, 470608800, 470807776, 471006688, 471205472, 471404192, 471602784, 471801312, 471999712, 472198048, 472396288, 472594400, 472792448, 472990400, 473188256, 473385984, 473583648, 473781216, 473978688, 474176064, 474373344, 474570528, 474767616, 474964608, 475161504, 475358336, 475555040, 475751648, 475948192, 476144608, 476340928, 476537184, 476733312, 476929376, 477125344, 477321184, 477516960, 477712640, 477908224, 478103712, 478299104, 478494400, 478689600, 478884704, 479079744, 479274656, 479469504, 479664224, 479858880, 480053408, 480247872, 480442240, 480636512, 480830656, 481024736, 481218752, 481412640, 481606432, 481800128, 481993760, 482187264, 482380704, 482574016, 482767264, 482960416, 483153472, 483346432, 483539296, 483732064, 483924768, 484117344, 484309856, 484502240, 484694560, 484886784, 485078912, 485270944, 485462880, 485654720, 485846464, 486038144, 486229696, 486421184, 486612576, 486803840, 486995040, 487186176, 487377184, 487568096, 487758912, 487949664, 488140320, 488330880, 488521312, 488711712, 488901984, 489092160, 489282240, 489472256, 489662176, 489851968, 490041696, 490231328, 490420896, 490610336, 490799712, 490988960, 491178144, 491367232, 491556224, 491745120, 491933920, 492122656, 492311264, 492499808, 492688256, 492876608, 493064864, 493253056, 493441120, 493629120, 493817024, 494004832, 494192544, 494380160, 494567712, 494755136, 494942496, 495129760, 495316928, 495504000, 495691008, 495877888, 496064704, 496251424, 496438048, 496624608, 496811040, 496997408, 497183680, 497369856, 497555936, 497741920, 497927840, 498113632, 498299360, 498484992, 498670560, 498856000, 499041376, 499226656, 499411840, 499596928, 499781920, 499966848, 500151680, 500336416, 500521056, 500705600, 500890080, 501074464, 501258752, 501442944, 501627040, 501811072, 501995008, 502178848, 502362592, 502546240, 502729824, 502913312, 503096704, 503280000, 503463232, 503646368, 503829408, 504012352, 504195200, 504377984, 504560672, 504743264, 504925760, 505108192, 505290496, 505472736, 505654912, 505836960, 506018944, 506200832, 506382624, 506564320, 506745952, 506927488, 507108928, 507290272, 507471552, 507652736, 507833824, 508014816, 508195744, 508376576, 508557312, 508737952, 508918528, 509099008, 509279392, 509459680, 509639904, 509820032, 510000064, 510180000, 510359872, 510539648, 510719328, 510898944, 511078432, 511257856, 511437216, 511616448, 511795616, 511974688, 512153664, 512332576, 512511392, 512690112, 512868768, 513047296, 513225792, 513404160, 513582432, 513760640, 513938784, 514116800, 514294752, 514472608, 514650368, 514828064, 515005664, 515183168, 515360608, 515537952, 515715200, 515892352, 516069440, 516246432, 516423328, 516600160, 516776896, 516953536, 517130112, 517306592, 517482976, 517659264, 517835488, 518011616, 518187680, 518363648, 518539520, 518715296, 518891008, 519066624, 519242144, 519417600, 519592960, 519768256, 519943424, 520118528, 520293568, 520468480, 520643328, 520818112, 520992800, 521167392, 521341888, 521516320, 521690656, 521864896, 522039072, 522213152, 522387168, 522561056, 522734912, 522908640, 523082304, 523255872, 523429376, 523602784, 523776096, 523949312, 524122464, 524295552, 524468512, 524641440, 524814240, 524986976, 525159616, 525332192, 525504640, 525677056, 525849344, 526021568, 526193728, 526365792, 526537760, 526709632, 526881440, 527053152, 527224800, 527396352, 527567840, 527739200, 527910528, 528081728, 528252864, 528423936, 528594880, 528765760, 528936576, 529107296, 529277920, 529448480, 529618944, 529789344, 529959648, 530129856, 530300000, 530470048, 530640000, 530809888, 530979712, 531149440, 531319072, 531488608, 531658080, 531827488, 531996800, 532166016, 532335168, 532504224, 532673184, 532842080, 533010912, 533179616, 533348288, 533516832, 533685312, 533853728, 534022048, 534190272, 534358432, 534526496, 534694496, 534862400, 535030240, 535197984, 535365632, 535533216, 535700704, 535868128, 536035456, 536202720, 536369888, 536536992, 536704000, 536870912 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- int SlopeDiv(unsigned num, unsigned den) { unsigned ans; if(den < 512) return SLOPERANGE; ans = (num << 3) / (den >> 8); return ans <= SLOPERANGE ? ans : SLOPERANGE; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_enemy.c0000644000175000017500000015525311357170242022432 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.c: Enemy thinking, AI. * * Action Pointer Functions that are associated with states/frames. * * Enemies are allways spawned with targetplayer = -1, threshold = 0 * Most monsters are spawned unaware of all players, * but some can be made preaware */ // HEADER FILES ------------------------------------------------------------ #include #include #include #ifdef MSVC # pragma optimize("g", off) #endif #include "jdoom64.h" #include "dmu_lib.h" #include "p_mapspec.h" #include "p_map.h" #include "p_actor.h" #include "p_door.h" #include "p_floor.h" // MACROS ------------------------------------------------------------------ #define FATSPREAD (ANG90/8) #define FAT_DELTAANGLE (85*ANGLE_1) // jd64 #define FAT_ARM_EXTENSION_SHORT (32) // jd64 #define FAT_ARM_EXTENSION_LONG (16) // jd64 #define FAT_ARM_HEIGHT (64) // jd64 #define SKULLSPEED (20) #define TRACEANGLE (0xc000000) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void C_DECL A_ReFire(player_t *player, pspdef_t *psp); void C_DECL A_Fall(mobj_t *actor); void C_DECL A_Fire(mobj_t *actor); void C_DECL A_SpawnFly(mobj_t *mo); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean bossKilled; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static mobj_t *corpseHit; static float dropoffDelta[2], floorZ; // Eight directional movement speeds. #define MOVESPEED_DIAGONAL (0.71716309f) static const float dirSpeed[8][2] = { {1, 0}, {MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {0, 1}, {-MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {-1, 0}, {-MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL}, {0, -1}, {MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL} }; #undef MOVESPEED_DIAGONAL // CODE -------------------------------------------------------------------- /** * If a monster yells at a player, it will alert other monsters to the * player's whereabouts. */ void P_NoiseAlert(mobj_t *target, mobj_t *emitter) { VALIDCOUNT++; P_RecursiveSound(target, P_GetPtrp(emitter->subsector, DMU_SECTOR), 0); } static boolean checkMeleeRange(mobj_t *actor) { mobj_t *pl; float dist, range; if(!actor->target) return false; pl = actor->target; dist = P_ApproxDistance(pl->pos[VX] - actor->pos[VX], pl->pos[VY] - actor->pos[VY]); if(!cfg.netNoMaxZMonsterMeleeAttack) { // Account for Z height difference. if(pl->pos[VZ] > actor->pos[VZ] + actor->height || pl->pos[VZ] + pl->height < actor->pos[VZ]) return false; } range = MELEERANGE - 20 + pl->info->radius; if(dist >= range) return false; if(!P_CheckSight(actor, actor->target)) return false; return true; } static boolean checkMissileRange(mobj_t *actor) { float dist; if(!P_CheckSight(actor, actor->target)) return false; if(actor->flags & MF_JUSTHIT) { // The target just hit the enemy. // So fight back! actor->flags &= ~MF_JUSTHIT; return true; } if(actor->reactionTime) return false; // Do not attack yet. // OPTIMIZE: get this from a global checksight. dist = P_ApproxDistance(actor->pos[VX] - actor->target->pos[VX], actor->pos[VY] - actor->target->pos[VY]) - 64; if(P_GetState(actor->type, SN_MELEE) == S_NULL) dist -= 128; // No melee attack, so fire more. if(actor->type == MT_CYBORG || actor->type == MT_SKULL) { dist /= 2; } if(dist > 200) dist = 200; if(actor->type == MT_CYBORG && dist > 160) dist = 160; if(P_Random() < dist) return false; return true; } /** * Move in the current direction. $dropoff_fix * * @return @c false, if the move is blocked. */ static boolean moveMobj(mobj_t *actor, boolean dropoff) { float pos[3], step[3]; linedef_t *ld; boolean good; if(actor->moveDir == DI_NODIR) return false; if((unsigned) actor->moveDir >= DI_NODIR) Con_Error("Weird actor->moveDir!"); step[VX] = actor->info->speed * dirSpeed[actor->moveDir][MX]; step[VY] = actor->info->speed * dirSpeed[actor->moveDir][MY]; pos[VX] = actor->pos[VX] + step[VX]; pos[VY] = actor->pos[VY] + step[VY]; // $dropoff_fix if(!P_TryMove(actor, pos[VX], pos[VY], dropoff, false)) { // Open any specials. if((actor->flags & MF_FLOAT) && floatOk) { // Must adjust height. if(actor->pos[VZ] < tmFloorZ) actor->pos[VZ] += FLOATSPEED; else actor->pos[VZ] -= FLOATSPEED; actor->flags |= MF_INFLOAT; return true; } if(!P_IterListSize(spechit)) return false; actor->moveDir = DI_NODIR; good = false; while((ld = P_PopIterList(spechit)) != NULL) { /** * If the special is not a door that can be opened, return false. * * $unstuck: This is what caused monsters to get stuck in * doortracks, because it thought that the monster freed itself * by opening a door, even if it was moving towards the * doortrack, and not the door itself. * * If a line blocking the monster is activated, return true 90% * of the time. If a line blocking the monster is not activated, * but some other line is, return false 90% of the time. * A bit of randomness is needed to ensure it's free from * lockups, but for most cases, it returns the correct result. * * Do NOT simply return false 1/4th of the time (causes monsters * to back out when they shouldn't, and creates secondary * stickiness). */ if(P_ActivateLine(ld, actor, 0, SPAC_USE)) good |= ld == blockLine ? 1 : 2; } if(!good || cfg.monstersStuckInDoors) return good; else return (P_Random() >= 230) || (good & 1); } else { P_MobjSetSRVO(actor, step[VX], step[VY]); actor->flags &= ~MF_INFLOAT; } // $dropoff_fix: fall more slowly, under gravity, if fellDown==true if(!(actor->flags & MF_FLOAT) && !fellDown) { if(actor->pos[VZ] > actor->floorZ) P_HitFloor(actor); actor->pos[VZ] = actor->floorZ; } return true; } /** * Attempts to move actor on in its current (ob->moveangle) direction. * If blocked by either a wall or an actor returns FALSE * If move is either clear or blocked only by a door, returns TRUE and sets... * If a door is in the way, an OpenDoor call is made to start it opening. */ static boolean tryMoveMobj(mobj_t *actor) { // $dropoff_fix if(!moveMobj(actor, false)) { return false; } actor->moveCount = P_Random() & 15; return true; } static void doNewChaseDir(mobj_t *actor, float deltaX, float deltaY) { dirtype_t xdir, ydir, tdir; dirtype_t olddir = actor->moveDir; dirtype_t turnaround = olddir; if(turnaround != DI_NODIR) // Find reverse direction. turnaround ^= 4; xdir = (deltaX > 10 ? DI_EAST : deltaX < -10 ? DI_WEST : DI_NODIR); ydir = (deltaY < -10 ? DI_SOUTH : deltaY > 10 ? DI_NORTH : DI_NODIR); // Try direct route. if(xdir != DI_NODIR && ydir != DI_NODIR && turnaround != (actor->moveDir = deltaY < 0 ? deltaX > 0 ? DI_SOUTHEAST : DI_SOUTHWEST : deltaX > 0 ? DI_NORTHEAST : DI_NORTHWEST) && tryMoveMobj(actor)) return; // Try other directions. if(P_Random() > 200 || fabs(deltaY) > fabs(deltaX)) { dirtype_t temp = xdir; xdir = ydir; ydir = temp; } if((xdir == turnaround ? xdir = DI_NODIR : xdir) != DI_NODIR && (actor->moveDir = xdir, tryMoveMobj(actor))) return; // Either moved forward or attacked. if((ydir == turnaround ? ydir = DI_NODIR : ydir) != DI_NODIR && (actor->moveDir = ydir, tryMoveMobj(actor))) return; // There is no direct path to the player, so pick another direction. if(olddir != DI_NODIR && (actor->moveDir = olddir, tryMoveMobj(actor))) return; // Randomly determine direction of search. if(P_Random() & 1) { for(tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) if(tdir != turnaround && (actor->moveDir = tdir, tryMoveMobj(actor))) return; } else { for(tdir = DI_SOUTHEAST; tdir != DI_EAST - 1; tdir--) if(tdir != turnaround && (actor->moveDir = tdir, tryMoveMobj(actor))) return; } if((actor->moveDir = turnaround) != DI_NODIR && !tryMoveMobj(actor)) actor->moveDir = DI_NODIR; } /** * Monsters try to move away from tall dropoffs. * * In Doom, they were never allowed to hang over dropoffs, and would remain * stuck if involuntarily forced over one. This logic, combined with * p_map.c::P_TryMove(), allows monsters to free themselves without making * them tend to hang over dropoffs. */ static boolean PIT_AvoidDropoff(linedef_t* line, void* data) { sector_t* backsector = P_GetPtrp(line, DMU_BACK_SECTOR); float* bbox = P_GetPtrp(line, DMU_BOUNDING_BOX); if(backsector && tmBBox[BOXRIGHT] > bbox[BOXLEFT] && tmBBox[BOXLEFT] < bbox[BOXRIGHT] && tmBBox[BOXTOP] > bbox[BOXBOTTOM] && // Linedef must be contacted tmBBox[BOXBOTTOM] < bbox[BOXTOP] && P_BoxOnLineSide(tmBBox, line) == -1) { sector_t* frontsector = P_GetPtrp(line, DMU_FRONT_SECTOR); float front = P_GetFloatp(frontsector, DMU_FLOOR_HEIGHT); float back = P_GetFloatp(backsector, DMU_FLOOR_HEIGHT); float d1[2]; angle_t angle; P_GetFloatpv(line, DMU_DXY, d1); // The monster must contact one of the two floors, and the other // must be a tall drop off (more than 24). if(back == floorZ && front < floorZ - 24) { angle = R_PointToAngle2(0, 0, d1[0], d1[1]); // Front side drop off. } else { if(front == floorZ && back < floorZ - 24) angle = R_PointToAngle2(d1[0], d1[1], 0, 0); // Back side drop off. else return true; } // Move away from drop off at a standard speed. // Multiple contacted linedefs are cumulative (e.g. hanging over corner) dropoffDelta[VX] -= FIX2FLT(finesine[angle >> ANGLETOFINESHIFT]) * 32; dropoffDelta[VY] += FIX2FLT(finecosine[angle >> ANGLETOFINESHIFT]) * 32; } return true; } /** * Driver for above */ static boolean avoidDropoff(mobj_t *actor) { floorZ = actor->pos[VZ]; // Remember floor height. dropoffDelta[VX] = dropoffDelta[VY] = 0; VALIDCOUNT++; // Check lines. P_MobjLinesIterator(actor, PIT_AvoidDropoff, 0); // Non-zero if movement prescribed. return !(dropoffDelta[VX] == 0 || dropoffDelta[VY] == 0); } static void newChaseDir(mobj_t *actor) { mobj_t *target = actor->target; float deltaX = target->pos[VX] - actor->pos[VX]; float deltaY = target->pos[VY] - actor->pos[VY]; if(actor->floorZ - actor->dropOffZ > 24 && actor->pos[VZ] <= actor->floorZ && !(actor->flags & (MF_DROPOFF | MF_FLOAT)) && !cfg.avoidDropoffs && avoidDropoff(actor)) { // Move away from dropoff. doNewChaseDir(actor, dropoffDelta[VX], dropoffDelta[VY]); // $dropoff_fix // If moving away from drop off, set movecount to 1 so that // small steps are taken to get monster away from drop off. actor->moveCount = 1; return; } doNewChaseDir(actor, deltaX, deltaY); } /** * If allaround is false, only look 180 degrees in front. * * @return @c true, if a player is targeted. */ static boolean lookForPlayers(mobj_t *actor, boolean allAround) { int c, stop, playerCount; player_t *player; angle_t an; float dist; playerCount = 0; for(c = 0; c < MAXPLAYERS; ++c) { if(players[c].plr->inGame) playerCount++; } // Are there any players? if(!playerCount) return false; c = 0; stop = (actor->lastLook - 1) & 3; for(;; actor->lastLook = (actor->lastLook + 1) & 3) { if(!players[actor->lastLook].plr->inGame) continue; if(c++ == 2 || actor->lastLook == stop) { // Done looking. return false; } player = &players[actor->lastLook]; if(player->health <= 0) continue; // Player is already dead. if(!P_CheckSight(actor, player->plr->mo)) continue; // Player is out of sight. if(!allAround) { an = R_PointToAngle2(actor->pos[VX], actor->pos[VY], player->plr->mo->pos[VX], player->plr->mo->pos[VY]); an -= actor->angle; if(an > ANG90 && an < ANG270) { dist = P_ApproxDistance(player->plr->mo->pos[VX] - actor->pos[VX], player->plr->mo->pos[VY] - actor->pos[VY]); // If real close, react anyway. if(dist > MELEERANGE) continue; // Behind back. } } actor->target = player->plr->mo; return true; } } static boolean massacreMobj(thinker_t* th, void* context) { int* count = (int*) context; mobj_t* mo = (mobj_t *) th; if(!mo->player && sentient(mo) && (mo->flags & MF_SHOOTABLE)) { P_DamageMobj(mo, NULL, NULL, 10000, false); (*count)++; } return true; // Continue iteration. } int P_Massacre(void) { int count = 0; // Only massacre when actually in a level. if(G_GetGameState() == GS_MAP) { DD_IterateThinkers(P_MobjThinker, massacreMobj, &count); } return count; } typedef struct { mobjtype_t type; size_t count; } countmobjoftypeparams_t; static boolean countMobjOfType(thinker_t* th, void* context) { countmobjoftypeparams_t *params = (countmobjoftypeparams_t*) context; mobj_t* mo = (mobj_t *) th; if(params->type == mo->type && mo->health > 0) params->count++; return true; // Continue iteration. } /** * DJS - Next up we have an obscene amount of repetion; 15(!) copies of * DOOM's A_KeenDie() with only very minor changes. * * \todo Replace this lot with XG (maybe need to add a new flag for * targeting "mobjs like me"). */ /** * kaiser - Used for special stuff. works only per monster!!! */ void C_DECL A_RectSpecial(mobj_t* actor) { countmobjoftypeparams_t params; int sound; mobj_t* mo; float pos[3]; switch(actor->info->deathSound) { case 0: return; case SFX_PODTH1: case SFX_PODTH2: case SFX_PODTH3: sound = SFX_PODTH1 + P_Random() % 3; break; case SFX_BGDTH1: case SFX_BGDTH2: sound = SFX_BGDTH1 + P_Random() % 2; break; default: sound = actor->info->deathSound; break; } // Check for bosses. if(actor->type == MT_CYBORG || actor->type == MT_BITCH) { // Full volume. S_StartSound(sound | DDSF_NO_ATTENUATION, NULL); actor->reactionTime += 30; // jd64 } else S_StartSound(sound, actor); memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += FIX2FLT((P_Random() - 128) << 11); pos[VY] += FIX2FLT((P_Random() - 128) << 11); pos[VZ] += actor->height / 2; if((mo = P_SpawnMobj3fv(MT_KABOOM, pos, P_Random() << 24, 0))) { S_StartSound(SFX_BAREXP, mo); mo->mom[MX] = FIX2FLT((P_Random() - 128) << 11); mo->mom[MY] = FIX2FLT((P_Random() - 128) << 11); mo->target = actor; } actor->reactionTime--; if(actor->reactionTime <= 0) { P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH) + 2); } // Check if there are no more Bitches left in the map. params.type = actor->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { // No Bitches left alive. linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4459; // jd64 was 666. EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); // jd64 was open. P_FreeDummyLine(dummyLine); } } /** * kaiser - Used for special stuff. works only per monster!!! */ void C_DECL A_PossSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4444; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_SposSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4445; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_TrooSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = (mo->type == MT_TROOP? 4446 : 4447); EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_SargSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4448; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_HeadSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4450; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_SkulSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4452; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_Bos2Special(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4453; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_BossSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4454; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_PainSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4455; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_FattSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4456; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_BabySpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4457; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * kaiser - used for special stuff. works only per monster!!! */ void C_DECL A_CybrSpecial(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 4458; EV_DoDoor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); } } /** * Stay in state until a player is sighted. */ void C_DECL A_Look(mobj_t *actor) { sector_t *sec = NULL; mobj_t *targ; sec = P_GetPtrp(actor->subsector, DMU_SECTOR); if(!sec) return; actor->threshold = 0; // Any shot will wake us up. targ = P_ToXSector(sec)->soundTarget; if(targ && (targ->flags & MF_SHOOTABLE)) { actor->target = targ; if(actor->flags & MF_AMBUSH) { if(P_CheckSight(actor, actor->target)) goto seeyou; } else goto seeyou; } if(!lookForPlayers(actor, false)) return; // Go into chase state. seeyou: if(actor->info->seeSound) { int sound; switch(actor->info->seeSound) { case SFX_POSIT1: case SFX_POSIT2: case SFX_POSIT3: sound = SFX_POSIT1 + P_Random() % 3; break; case SFX_BGSIT1: case SFX_BGSIT2: sound = SFX_BGSIT1 + P_Random() % 2; break; default: sound = actor->info->seeSound; break; } if(actor->flags2 & MF2_BOSS) { // Full volume. S_StartSound(sound | DDSF_NO_ATTENUATION, actor); } else { S_StartSound(sound, actor); } } P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } /** * Used by the demo cyborg to select the camera as a target on spawn. */ void C_DECL A_TargetCamera(mobj_t* actor) { int i; player_t* player; for(i = 0; i < MAXPLAYERS; ++i) { player = &players[i]; if(!player->plr->inGame || !player->plr->mo) continue; actor->target = player->plr->mo; return; } // Should never get here. Con_Error("A_TargetCamera: Could not find suitable target!"); } /** * Actor has a melee attack, so it tries to close as fast as possible. */ void C_DECL A_Chase(mobj_t* actor) { int delta; statenum_t state; // jd64 > if(actor->flags & MF_FLOAT) { int r = P_Random(); if(r < 64) actor->mom[MZ] += 1; else if(r < 128) actor->mom[MZ] -= 1; } // < d64tc if(actor->reactionTime) actor->reactionTime--; // Modify target threshold. if(actor->threshold) { if(!actor->target || actor->target->health <= 0) { actor->threshold = 0; } else actor->threshold--; } // Turn towards movement direction if not there yet. if(actor->moveDir < DI_NODIR) { actor->angle &= (7 << 29); delta = actor->angle - (actor->moveDir << 29); if(delta > 0) actor->angle -= ANG90 / 2; else if(delta < 0) actor->angle += ANG90 / 2; } if(!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { // Look for a new target. if(lookForPlayers(actor, true)) { // Got a new target. } else { P_MobjChangeState(actor, P_GetState(actor->type, SN_SPAWN)); } return; } // Do not attack twice in a row. if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if(!fastParm) newChaseDir(actor); return; } // Check for melee attack. if((state = P_GetState(actor->type, SN_MELEE)) != S_NULL && checkMeleeRange(actor)) { if(actor->info->attackSound) S_StartSound(actor->info->attackSound, actor); P_MobjChangeState(actor, state); return; } // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { if(!(!fastParm && actor->moveCount)) { if(checkMissileRange(actor)) { P_MobjChangeState(actor, state); actor->flags |= MF_JUSTATTACKED; return; } } } // Possibly choose another target. if(IS_NETGAME && !actor->threshold && !P_CheckSight(actor, actor->target)) { if(lookForPlayers(actor, true)) return; // Got a new target. } // Chase towards player. if(--actor->moveCount < 0 || !moveMobj(actor, false)) { newChaseDir(actor); } // Make active sound. if(actor->info->activeSound && P_Random() < 3) { S_StartSound(actor->info->activeSound, actor); } } void C_DECL A_RectChase(mobj_t* actor) { A_Chase(actor); } void C_DECL A_FaceTarget(mobj_t *actor) { if(!actor->target) return; actor->turnTime = true; // $visangle-facetarget actor->flags &= ~MF_AMBUSH; actor->angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], actor->target->pos[VX], actor->target->pos[VY]); if(actor->target->flags & MF_SHADOW) actor->angle += (P_Random() - P_Random()) << 21; } void C_DECL A_BspiFaceTarget(mobj_t* actor) { A_FaceTarget(actor); } void C_DECL A_PosAttack(mobj_t *actor) { int damage; angle_t angle; float slope; if(!actor->target) return; A_FaceTarget(actor); angle = actor->angle; slope = P_AimLineAttack(actor, angle, MISSILERANGE); S_StartSound(SFX_PISTOL, actor); angle += (P_Random() - P_Random()) << 20; damage = ((P_Random() % 5) + 1) * 3; P_LineAttack(actor, angle, MISSILERANGE, slope, damage); } void C_DECL A_SPosAttack(mobj_t *actor) { int i, damage; angle_t angle, bangle; float slope; if(!actor->target) return; S_StartSound(SFX_SHOTGN, actor); A_FaceTarget(actor); bangle = actor->angle; slope = P_AimLineAttack(actor, bangle, MISSILERANGE); for(i = 0; i < 3; ++i) { angle = bangle + ((P_Random() - P_Random()) << 20); damage = ((P_Random() % 5) + 1) * 3; P_LineAttack(actor, angle, MISSILERANGE, slope, damage); } } void C_DECL A_EMarineAttack2(mobj_t* actor) { // STUB: What is this meant to do? } void C_DECL A_SpidRefire(mobj_t *actor) { // Keep firing unless target got out of sight. A_FaceTarget(actor); if(P_Random() < 10) return; if(!actor->target || actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) { P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } } /** * d64tc: BspiAttack. Throw projectile. */ void BabyFire(mobj_t *actor, int type, boolean right) { #define BSPISPREAD (ANG90/8) //its cheap but it works #define BABY_DELTAANGLE (85*ANGLE_1) #define BABY_ARM_EXTENSION_SHORT (18) #define BABY_ARM_HEIGHT (24) mobj_t *mo; angle_t ang; float pos[3]; ang = actor->angle; if(right) ang += BABY_DELTAANGLE; else ang -= BABY_DELTAANGLE; ang >>= ANGLETOFINESHIFT; memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += BABY_ARM_EXTENSION_SHORT * FIX2FLT(finecosine[ang]); pos[VY] += BABY_ARM_EXTENSION_SHORT * FIX2FLT(finesine[ang]); pos[VZ] -= actor->floorClip + BABY_ARM_HEIGHT; mo = P_SpawnMotherMissile(type, pos[VX], pos[VY], pos[VZ], actor, actor->target); if(right) mo->angle += BSPISPREAD/6; else mo->angle -= BSPISPREAD/6; ang = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[ang]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[ang]); #undef BSPISPREAD #undef BABY_DELTAANGLE #undef BABY_ARM_EXTENSION_SHORT #undef BABY_ARM_HEIGHT } /** * Shoot two plasmaballs while aligned to cannon (should of been like this * in Doom 2! - kaiser). */ void C_DECL A_BspiAttack(mobj_t *actor) { BabyFire(actor, MT_ARACHPLAZ, false); BabyFire(actor, MT_ARACHPLAZ, true); } /** * Formerly A_BspiAttack? - DJS */ void C_DECL A_TroopAttack(mobj_t *actor) { mobjtype_t missileType; if(!actor->target) return; A_FaceTarget(actor); // Launch a missile. if(actor->type == MT_TROOP) missileType = MT_TROOPSHOT; else missileType = MT_NTROSHOT; P_SpawnMissile(missileType, actor, actor->target); } /** * Formerly A_TroopAttack? - DJS */ void C_DECL A_TroopClaw(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { S_StartSound(SFX_CLAW, actor); damage = (P_Random() % 8 + 1) * 3; P_DamageMobj(actor->target, actor, actor, damage, false); return; } } /** * Mother Demon: Floorfire attack. */ void C_DECL A_MotherFloorFire(mobj_t *actor) { /* #define FIRESPREAD (ANG90 / 8 * 4) mobj_t *mo; int an; */ if(!actor->target) return; A_FaceTarget(actor); S_StartSound(SFX_MTHATK, actor); /* mo = P_SpawnMissile(MT_FIREEND, actor, actor->target); mo = P_SpawnMissile(MT_FIREEND, actor, actor->target); mo->angle -= FIRESPREAD; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); mo = P_SpawnMissile(MT_FIREEND, actor, actor->target); mo->angle += FIRESPREAD; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); #undef FIRESPREAD */ } static void motherFire(mobj_t *actor, int type, angle_t angle, float distance, float height) { angle_t ang; float pos[3]; ang = actor->angle + angle; ang >>= ANGLETOFINESHIFT; memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += distance * FIX2FLT(finecosine[ang]); pos[VY] += distance * FIX2FLT(finesine[ang]); pos[VZ] += -actor->floorClip + height; P_SpawnMotherMissile(type, pos[VX], pos[VY], pos[VZ], actor, actor->target); } /** * d64tc: MotherDemon's Missle Attack code */ void C_DECL A_MotherMissle(mobj_t *actor) { #define MOTHER_DELTAANGLE (85*ANGLE_1) #define MOTHER_ARM_EXTENSION_SHORT (40) #define MOTHER_ARM_EXTENSION_LONG (55) #define MOTHER_ARM1_HEIGHT (128) #define MOTHER_ARM2_HEIGHT (128) #define MOTHER_ARM3_HEIGHT (64) #define MOTHER_ARM4_HEIGHT (64) // Fire 4 missiles at once. motherFire(actor, MT_BITCHBALL, -MOTHER_DELTAANGLE, MOTHER_ARM_EXTENSION_SHORT, MOTHER_ARM1_HEIGHT); motherFire(actor, MT_BITCHBALL, MOTHER_DELTAANGLE, MOTHER_ARM_EXTENSION_SHORT, MOTHER_ARM2_HEIGHT); motherFire(actor, MT_BITCHBALL, -MOTHER_DELTAANGLE, MOTHER_ARM_EXTENSION_LONG, MOTHER_ARM3_HEIGHT); motherFire(actor, MT_BITCHBALL, MOTHER_DELTAANGLE, MOTHER_ARM_EXTENSION_LONG, MOTHER_ARM4_HEIGHT); #undef MOTHER_DELTAANGLE #undef MOTHER_ARM_EXTENSION_SHORT #undef MOTHER_ARM_EXTENSION_LONG #undef MOTHER_ARM1_HEIGHT #undef MOTHER_ARM2_HEIGHT #undef MOTHER_ARM3_HEIGHT #undef MOTHER_ARM4_HEIGHT } /** * d64tc - Unused? */ void C_DECL A_SetFloorFire(mobj_t *actor) { /* mobj_t *mo; float pos[3]; actor->pos[VZ] = actor->floorZ; memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += FIX2FLT((P_Random() - P_Random()) << 10); pos[VY] += FIX2FLT((P_Random() - P_Random()) << 10); pos[VZ] = ONFLOORZ; if((mo = P_SpawnMobj3fv(MT_SPAWNFIRE, pos))) mo->target = actor->target; */ } /** * d64tc */ void C_DECL A_MotherBallExplode(mobj_t* spread) { int i; for(i = 0; i < 8; ++i) { angle_t angle = i * ANG45; mobj_t* shard; if((shard = P_SpawnMobj3fv(MT_HEADSHOT, spread->pos, angle, 0))) { unsigned int an = angle >> ANGLETOFINESHIFT; shard->target = spread->target; shard->mom[MX] = shard->info->speed * FIX2FLT(finecosine[an]); shard->mom[MY] = shard->info->speed * FIX2FLT(finesine[an]); } } } /** * d64tc: Spawns a smoke sprite during the missle attack. */ void C_DECL A_RectTracerPuff(mobj_t *smoke) { if(!smoke) return; P_SpawnMobj3fv(MT_MOTHERPUFF, smoke->pos, P_Random() << 24, 0); } void C_DECL A_SargAttack(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { damage = ((P_Random() % 10) + 1) * 4; P_DamageMobj(actor->target, actor, actor, damage, false); } } void C_DECL A_ShadowsAction1(mobj_t* actor) { // STUB: What is this meant to do? } void C_DECL A_ShadowsAction2(mobj_t* actor) { // STUB: What is this meant to do? } void C_DECL A_HeadAttack(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { damage = (P_Random() % 6 + 1) * 10; P_DamageMobj(actor->target, actor, actor, damage, false); return; } // Launch a missile. P_SpawnMissile(MT_HEADSHOT, actor, actor->target); } /** * Cyber Demon: Missile Attack. * * Heavily modified for d64tc. */ void C_DECL A_CyberAttack(mobj_t *actor) { #define CYBER_DELTAANGLE (85*ANGLE_1) #define CYBER_ARM_EXTENSION_SHORT (35) #define CYBER_ARM1_HEIGHT (68) angle_t ang; float pos[3]; // This aligns the rocket to the d64tc cyberdemon's rocket launcher. ang = (actor->angle + CYBER_DELTAANGLE) >> ANGLETOFINESHIFT; memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += CYBER_ARM_EXTENSION_SHORT * FIX2FLT(finecosine[ang]); pos[VY] += CYBER_ARM_EXTENSION_SHORT * FIX2FLT(finesine[ang]); pos[VZ] += -actor->floorClip + CYBER_ARM1_HEIGHT; P_SpawnMotherMissile(MT_CYBERROCKET, pos[VX], pos[VY], pos[VZ], actor, actor->target); #undef CYBER_DELTAANGLE #undef CYBER_ARM_EXTENSION_SHORT #undef CYBER_ARM1_HEIGHT } void C_DECL A_BruisAttack(mobj_t *actor) { int damage; mobjtype_t missileType; if(!actor->target) return; if(checkMeleeRange(actor)) { S_StartSound(SFX_CLAW, actor); damage = (P_Random() % 8 + 1) * 10; P_DamageMobj(actor->target, actor, actor, damage, false); return; } // Launch a missile. if(actor->type == MT_BRUISER) missileType = MT_BRUISERSHOTRED; else missileType = MT_BRUISERSHOT; P_SpawnMissile(missileType, actor, actor->target); } void C_DECL A_SkelMissile(mobj_t* actor) { mobj_t* mo; if(!actor->target) return; A_FaceTarget(actor); if((mo = P_SpawnMissile(MT_TRACER, actor, actor->target))) { mo->pos[VX] += mo->mom[MX]; mo->pos[VY] += mo->mom[MY]; mo->tracer = actor->target; } } void C_DECL A_Tracer(mobj_t* actor) { angle_t exact; float dist, slope; mobj_t* dest, *th; if((int) GAMETIC & 3) return; // Spawn a puff of smoke behind the rocket. P_SpawnCustomPuff(MT_ROCKETPUFF, actor->pos[VX], actor->pos[VY], actor->pos[VZ], actor->angle + ANG180); if((th = P_SpawnMobj3f(MT_SMOKE, actor->pos[VX] - actor->mom[MX], actor->pos[VY] - actor->mom[MY], actor->pos[VZ], actor->angle + ANG180, 0))) { th->mom[MZ] = 1; th->tics -= P_Random() & 3; if(th->tics < 1) th->tics = 1; } // Adjust direction. dest = actor->tracer; if(!dest || dest->health <= 0) return; // Change angle. exact = R_PointToAngle2(actor->pos[VX], actor->pos[VY], dest->pos[VX], dest->pos[VY]); if(exact != actor->angle) { if(exact - actor->angle > 0x80000000) { actor->angle -= TRACEANGLE; if(exact - actor->angle < 0x80000000) actor->angle = exact; } else { actor->angle += TRACEANGLE; if(exact - actor->angle > 0x80000000) actor->angle = exact; } } exact = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = FIX2FLT(FixedMul(actor->info->speed, finecosine[exact])); actor->mom[MY] = FIX2FLT(FixedMul(actor->info->speed, finesine[exact])); // Change slope. dist = P_ApproxDistance(dest->pos[VX] - actor->pos[VX], dest->pos[VY] - actor->pos[VY]); dist /= FIX2FLT(actor->info->speed); if(dist < 1) dist = 1; slope = (dest->pos[VZ] + 40 - actor->pos[VZ]) / dist; if(slope < actor->mom[MZ]) actor->mom[MZ] -= 1 / 8; else actor->mom[MZ] += 1 / 8; } void C_DECL A_SkelWhoosh(mobj_t *actor) { if(!actor->target) return; A_FaceTarget(actor); S_StartSound(SFX_SKESWG, actor); } void C_DECL A_SkelFist(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { damage = ((P_Random() % 10) + 1) * 6; S_StartSound(SFX_SKEPCH, actor); P_DamageMobj(actor->target, actor, actor, damage, false); } } void C_DECL A_FatRaise(mobj_t *actor) { A_FaceTarget(actor); S_StartSound(SFX_MANATK, actor); } /** * d64tc: Used for mancubus projectile. */ static void fatFire(mobj_t *actor, int type, angle_t spread, angle_t angle, float distance, float height) { mobj_t *mo; angle_t an; float pos[3]; an = (actor->angle + angle) >> ANGLETOFINESHIFT; memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += distance * FIX2FLT(finecosine[an]); pos[VY] += distance * FIX2FLT(finesine[an]); pos[VZ] += -actor->floorClip + height; mo = P_SpawnMotherMissile(type, pos[VX], pos[VY], pos[VZ], actor, actor->target); mo->angle += spread; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); } /** * d64tc */ void C_DECL A_FatAttack1(mobj_t *actor) { fatFire(actor, MT_FATSHOT, -(FATSPREAD / 4), -FAT_DELTAANGLE, FAT_ARM_EXTENSION_SHORT, FAT_ARM_HEIGHT); fatFire(actor, MT_FATSHOT, FATSPREAD * 1.5, FAT_DELTAANGLE, FAT_ARM_EXTENSION_LONG, FAT_ARM_HEIGHT); } /** * d64tc */ void C_DECL A_FatAttack2(mobj_t *actor) { fatFire(actor, MT_FATSHOT, -(FATSPREAD * 1.5), -FAT_DELTAANGLE, FAT_ARM_EXTENSION_LONG, FAT_ARM_HEIGHT); fatFire(actor, MT_FATSHOT, FATSPREAD / 4, FAT_DELTAANGLE, FAT_ARM_EXTENSION_SHORT, FAT_ARM_HEIGHT); } /** * d64tc */ void C_DECL A_FatAttack3(mobj_t *actor) { fatFire(actor, MT_FATSHOT, FATSPREAD / 4, FAT_DELTAANGLE, FAT_ARM_EXTENSION_SHORT, FAT_ARM_HEIGHT); fatFire(actor, MT_FATSHOT, -(FATSPREAD / 4), -FAT_DELTAANGLE, FAT_ARM_EXTENSION_SHORT, FAT_ARM_HEIGHT); } /** * LostSoul Attack: Fly at the player like a missile. */ void C_DECL A_SkullAttack(mobj_t *actor) { mobj_t *dest; uint an; float dist; if(!actor->target) return; dest = actor->target; actor->flags |= MF_SKULLFLY; S_StartSound(actor->info->attackSound, actor); A_FaceTarget(actor); an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = SKULLSPEED * FIX2FLT(finecosine[an]); actor->mom[MY] = SKULLSPEED * FIX2FLT(finesine[an]); dist = P_ApproxDistance(dest->pos[VX] - actor->pos[VX], dest->pos[VY] - actor->pos[VY]); dist /= SKULLSPEED; if(dist < 1) dist = 1; actor->mom[MZ] = (dest->pos[VZ] + (dest->height / 2) - actor->pos[VZ]) / dist; } /** * PainElemental Attack: Spawn a lost soul and launch it at the target. */ void C_DECL A_PainShootSkull(mobj_t *actor, angle_t angle) { float pos[3]; mobj_t* newmobj; uint an; float prestep; sector_t* sec; if(cfg.maxSkulls) { // Limit the number of MT_SKULL's we should spawn. countmobjoftypeparams_t params; // Count total number currently on the map. params.type = MT_SKULL; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(params.count > 20) return; // Too many, don't spit another. } an = angle >> ANGLETOFINESHIFT; prestep = 4 + 3 * ((actor->info->radius + MOBJINFO[MT_SKULL].radius) / 2); memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += prestep * FIX2FLT(finecosine[an]); pos[VY] += prestep * FIX2FLT(finesine[an]); pos[VZ] += 8; // Compat option to prevent spawning lost souls inside walls. if(!cfg.allowSkullsInWalls) { /** * Check whether the Lost Soul is being fired through a 1-sided * wall or an impassible line, or a "monsters can't cross" line. * If it is, then we don't allow the spawn. */ if(P_CheckSides(actor, pos[VX], pos[VY])) return; if(!(newmobj = P_SpawnMobj3fv(MT_SKULL, pos, angle, 0))) return; sec = P_GetPtrp(newmobj->subsector, DMU_SECTOR); // Check to see if the new Lost Soul's z value is above the // ceiling of its new sector, or below the floor. If so, kill it. if((newmobj->pos[VZ] > (P_GetFloatp(sec, DMU_CEILING_HEIGHT) - newmobj->height)) || (newmobj->pos[VZ] < P_GetFloatp(sec, DMU_FLOOR_HEIGHT))) { // Kill it immediately. P_DamageMobj(newmobj, actor, actor, 10000, false); return; } } else { // Use the original DOOM method. if(!(newmobj = P_SpawnMobj3fv(MT_SKULL, pos, angle, 0))) return; } // Check for movements, $dropoff_fix. if(!P_TryMove(newmobj, newmobj->pos[VX], newmobj->pos[VY], false, false)) { // Kill it immediately. P_DamageMobj(newmobj, actor, actor, 10000, false); return; } newmobj->target = actor->target; A_SkullAttack(newmobj); } /** * PainElemental Attack: Spawn a lost soul and launch it at the target. */ void C_DECL A_PainAttack(mobj_t *actor) { if(!actor->target) return; A_FaceTarget(actor); // jd64 - Shoots two lost souls from left and right side. A_PainShootSkull(actor, actor->angle + ANG270); A_PainShootSkull(actor, actor->angle + ANG90); } void C_DECL A_PainDie(mobj_t* actor) { angle_t an; A_Fall(actor); switch(P_Random() % 3) { case 0: an = ANG90; break; case 1: an = ANG180; break; case 2: an = ANG270; break; } A_PainShootSkull(actor, actor->angle + an); } /** * d64tc: Rocket Trail Puff * kaiser - Current Rocket Puff code unknown because I know squat. * A fixed version of the pain attack code. * * DJS - This looks to be doing something similar to the pain elemental * above in that it could possibily spawn mobjs in the void. In this * instance its of little consequence as they are just for fx. */ void A_Rocketshootpuff(mobj_t* actor, angle_t angle) { uint an; float prestep; float pos[3]; mobj_t* mo; an = angle >> ANGLETOFINESHIFT; prestep = 4 + 3 * (actor->info->radius + MOBJINFO[MT_ROCKETPUFF].radius) / 2; memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += prestep * FIX2FLT(finecosine[an]); pos[VY] += prestep * FIX2FLT(finesine[an]); pos[VZ] += 8; if((mo = P_SpawnMobj3fv(MT_ROCKETPUFF, pos, angle, 0))) { // Check for movements $dropoff_fix. if(!P_TryMove(mo, mo->pos[VX], mo->pos[VY], false, false)) { // Kill it immediately. P_DamageMobj(mo, actor, actor, 10000, false); } } } void C_DECL A_Scream(mobj_t *actor) { int sound; if(actor->player) { sound = SFX_PLDETH; // Default death sound. if(actor->health < -50) { // If the player dies less with less than -50% without gibbing. sound = SFX_PDIEHI; } S_StartSound(sound, actor); return; } switch(actor->info->deathSound) { case 0: return; case SFX_PODTH1: case SFX_PODTH2: case SFX_PODTH3: sound = SFX_PODTH1 + P_Random() % 3; break; case SFX_BGDTH1: case SFX_BGDTH2: sound = SFX_BGDTH1 + P_Random() % 2; break; default: sound = actor->info->deathSound; break; } // Check for bosses. if(actor->type == MT_BITCH) { // Full volume. S_StartSound(sound | DDSF_NO_ATTENUATION, NULL); actor->reactionTime += 30; // jd64 } else S_StartSound(sound, actor); } /** * d64tc */ void C_DECL A_CyberDeath(mobj_t* actor) { int i; mobj_t* mo; float pos[3]; linedef_t* dummyLine; countmobjoftypeparams_t params; memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += FIX2FLT((P_Random() - 128) << 11); pos[VY] += FIX2FLT((P_Random() - 128) << 11); pos[VZ] += actor->height / 2; if((mo = P_SpawnMobj3fv(MT_KABOOM, pos, P_Random() << 24, 0))) { S_StartSound(SFX_BAREXP, mo); mo->mom[MX] = FIX2FLT((P_Random() - 128) << 11); mo->mom[MY] = FIX2FLT((P_Random() - 128) << 11); mo->target = actor; } actor->reactionTime--; if(actor->reactionTime <= 0) { P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH) + 2); } S_StartSound(actor->info->deathSound | DDSF_NO_ATTENUATION, NULL); // Has the boss already been killed? if(bossKilled) return; if((gameMap != 31) && (gameMap != 32) && (gameMap != 34)) return; // Make sure there is a player alive for victory. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame && players[i].health > 0) break; if(i == MAXPLAYERS) return; // No one left alive, so do not end game. // Scan the remaining thinkers to see if all bosses are dead. params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(params.count) { // Other boss not dead. return; } if(gameMap == 31 || gameMap == 32) { dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoDoor(dummyLine, DT_BLAZERAISE); P_FreeDummyLine(dummyLine); return; } else if(gameMap == 34) { G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); } } /** * d64tc: Spawns a smoke sprite during the missle attack */ void C_DECL A_Rocketpuff(mobj_t *actor) { if(!actor) return; P_SpawnMobj3fv(MT_ROCKETPUFF, actor->pos, P_Random() << 24, 0); } /** * d64tc */ void C_DECL A_Lasersmoke(mobj_t *mo) { if(!mo) return; P_SpawnMobj3fv(MT_LASERDUST, mo->pos, P_Random() << 24, 0); } void C_DECL A_XScream(mobj_t *actor) { S_StartSound(SFX_SLOP, actor); } void C_DECL A_Pain(mobj_t *actor) { if(actor->info->painSound) S_StartSound(actor->info->painSound, actor); } void C_DECL A_Fall(mobj_t *actor) { // Actor is on ground, it can be walked over. actor->flags &= ~MF_SOLID; } void C_DECL A_Explode(mobj_t *mo) { P_RadiusAttack(mo, mo->target, 128, 127); } void C_DECL A_BarrelExplode(mobj_t* actor) { int i; linedef_t* dummyLine; countmobjoftypeparams_t params; S_StartSound(actor->info->deathSound, actor); P_RadiusAttack(actor, actor->target, 128, 127); // Has the boss already been killed? if(bossKilled) return; if(gameMap != 0) return; if(actor->type != MT_BARREL) return; // Make sure there is a player alive for victory. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame && players[i].health > 0) break; if(i == MAXPLAYERS) return; // No one left alive, so do not end game. // Scan the remaining thinkers to see if all bosses are dead. params.type = actor->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(params.count) { // Other boss not dead. return; } dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoDoor(dummyLine, DT_BLAZERAISE); P_FreeDummyLine(dummyLine); } /** * Possibly trigger special effects if on first boss level * * kaiser - Removed exit special at end to allow MT_FATSO to properly * work in Map33 for d64tc. */ void C_DECL A_BossDeath(mobj_t* mo) { int i; countmobjoftypeparams_t params; // Has the boss already been killed? if(bossKilled) return; if(gameMap != 29) return; if(mo->type != MT_BITCH) return; // Make sure there is a player alive for victory. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame && players[i].health > 0) break; if(i == MAXPLAYERS) return; // No one left alive, so do not end game. // Scan the remaining thinkers to see if all bosses are dead. params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(params.count) { // Other boss not dead. return; } G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); } void C_DECL A_Hoof(mobj_t *mo) { /** * \kludge Only play very loud sounds in map 8. * \todo: Implement a MAPINFO option for this. */ S_StartSound(SFX_HOOF | (gameMode != commercial && gameMap == 7 ? DDSF_NO_ATTENUATION : 0), mo); A_Chase(mo); } void C_DECL A_Metal(mobj_t *mo) { /** * \kludge Only play very loud sounds in map 8. * \todo: Implement a MAPINFO option for this. */ S_StartSound(SFX_MEAL | (gameMode != commercial && gameMap == 7 ? DDSF_NO_ATTENUATION : 0), mo); A_Chase(mo); } void C_DECL A_BabyMetal(mobj_t *mo) { S_StartSound(SFX_BSPWLK, mo); A_Chase(mo); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_spec.c0000644000175000017500000014403411357170242022242 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.c: Implements special effects. * * Texture animation, height or lighting changes according to adjacent * sectors, respective utility functions, etc. * * Line Tag handling. Line and Sector triggers. * * Events are operations triggered by using, crossing, * or shooting special lines, or by timed thinkers. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom64.h" #include "m_argv.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_mapspec.h" #include "p_player.h" #include "p_tick.h" #include "p_ceiling.h" #include "p_door.h" #include "p_floor.h" #include "p_plat.h" #include "p_switch.h" #include "d_netsv.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // Animating textures and planes // In Doomsday these are handled via DED definitions. // In BOOM they invented the ANIMATED lump for the same purpose. // This struct is directly read from the lump. // So its important we keep it aligned. #pragma pack(1) typedef struct animdef_s { /* Do NOT change these members in any way */ signed char istexture; // if false, it is a flat (instead of bool) char endname[9]; char startname[9]; int speed; } animdef_t; #pragma pack() // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void P_CrossSpecialLine(linedef_t *line, int side, mobj_t *thing); static void P_ShootSpecialLine(mobj_t *thing, linedef_t *line); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // These arrays are treated as a hardcoded replacements for data that can be // loaded from a lump, so we need to use little-endian byte ordering. static animdef_t animsShared[] = { {1, "CFACEC", "CFACEA", MACRO_LONG(4)}, {1, "SMONAD", "SMONAA", MACRO_LONG(8)}, {1, "SMONBD", "SMONBA", MACRO_LONG(2)}, {1, "SMONCD", "SMONCA", MACRO_LONG(8)}, {1, "SMONDD", "SMONDA", MACRO_LONG(4)}, {1, "SMONED", "SMONEA", MACRO_LONG(8)}, {1, "SPORTI", "SPORTA", MACRO_LONG(4)}, {1, "C307B", "C307", MACRO_LONG(8)}, {-1, "\0", "\0"} }; // CODE -------------------------------------------------------------------- /** * From PrBoom: * Load the table of animation definitions, checking for existence of * the start and end of each frame. If the start doesn't exist the sequence * is skipped, if the last doesn't exist, BOOM exits. * * Wall/Flat animation sequences, defined by name of first and last frame, * The full animation sequence is given using all lumps between the start * and end entry, in the order found in the WAD file. * * This routine modified to read its data from a predefined lump or * PWAD lump called ANIMATED rather than a static table in this module to * allow wad designers to insert or modify animation sequences. * * Lump format is an array of byte packed animdef_t structures, terminated * by a structure with istexture == -1. The lump can be generated from a * text source file using SWANTBLS.EXE, distributed with the BOOM utils. * The standard list of switches and animations is contained in the example * source text file DEFSWANI.DAT also in the BOOM util distribution. */ static void loadAnimDefs(animdef_t* animDefs) { int i; // Read structures until -1 is found for(i = 0; animDefs[i].istexture != -1 ; ++i) { int groupNum, ticsPerFrame, numFrames; material_namespace_t mnamespace = (animDefs[i].istexture? MN_TEXTURES : MN_FLATS); switch(mnamespace) { case MN_FLATS: { lumpnum_t startFrame, endFrame, n; if((startFrame = W_CheckNumForName(animDefs[i].startname)) == -1 || (endFrame = W_CheckNumForName(animDefs[i].endname)) == -1) continue; numFrames = endFrame - startFrame + 1; ticsPerFrame = LONG(animDefs[i].speed); if(numFrames < 2) Con_Error("P_InitPicAnims: bad cycle from %s to %s", animDefs[i].startname, animDefs[i].endname); if(startFrame && endFrame) { // We have a valid animation. // Create a new animation group for it. groupNum = R_CreateAnimGroup(AGF_SMOOTH); /** * Doomsday's group animation needs to know the texture/flat * numbers of ALL frames in the animation group so we'll * have to step through the directory adding frames as we * go. (DOOM only required the start/end texture/flat * numbers and would animate all textures/flats inbetween). */ VERBOSE(Con_Message("P_InitPicAnims: ADD (\"%s\" > \"%s\" %d)\n", animDefs[i].startname, animDefs[i].endname, ticsPerFrame)); // Add all frames from start to end to the group. if(endFrame > startFrame) { for(n = startFrame; n <= endFrame; n++) { materialnum_t frame = P_MaterialCheckNumForName(W_LumpName(n), MN_FLATS); if(frame != 0) R_AddToAnimGroup(groupNum, frame, ticsPerFrame, 0); } } else { for(n = endFrame; n >= startFrame; n--) { materialnum_t frame = P_MaterialCheckNumForName(W_LumpName(n), MN_FLATS); if(frame != 0) R_AddToAnimGroup(groupNum, frame, ticsPerFrame, 0); } } } break; } case MN_TEXTURES: { // Same as above but for texture groups. materialnum_t startFrame, endFrame, n; if((startFrame = P_MaterialCheckNumForName(animDefs[i].startname, MN_TEXTURES)) == 0 || (endFrame = P_MaterialCheckNumForName(animDefs[i].endname, MN_TEXTURES)) == 0) continue; numFrames = endFrame - startFrame + 1; ticsPerFrame = LONG(animDefs[i].speed); if(numFrames < 2) Con_Error("P_InitPicAnims: bad cycle from %s to %s", animDefs[i].startname, animDefs[i].endname); if(startFrame && endFrame) { groupNum = R_CreateAnimGroup(AGF_SMOOTH); VERBOSE(Con_Message("P_InitPicAnims: ADD (\"%s\" > \"%s\" %d)\n", animDefs[i].startname, animDefs[i].endname, ticsPerFrame)); /** * \fixme Here an assumption is made that MN_TEXTURES type * materials are registered in the same order as they are * defined in the TEXTURE(1...) lump(s). */ if(endFrame > startFrame) { for(n = startFrame; n <= endFrame; n++) R_AddToAnimGroup(groupNum, n, ticsPerFrame, 0); } else { for(n = endFrame; n >= startFrame; n--) R_AddToAnimGroup(groupNum, n, ticsPerFrame, 0); } } break; } default: Con_Error("loadAnimDefs: Internal Error, invalid namespace %i.", (int) mnamespace); } } } void P_InitPicAnims(void) { int lump; // Is there an ANIMATED lump? if((lump = W_CheckNumForName("ANIMATED")) > 0) { animdef_t* animDefs; /** * We'll support this BOOM extension by reading the data and then * registering the new animations into Doomsday using the animation * groups feature. * * Support for this extension should be considered depreciated. * All new features should be added, accessed via DED. */ Con_Message("P_InitPicAnims: \"ANIMATED\" lump found. " "Reading animations...\n"); animDefs = (animdef_t *)W_CacheLumpNum(lump, PU_STATIC); loadAnimDefs(animDefs); Z_Free(animDefs); VERBOSE(Con_Message("P_InitPicAnims: Done.\n")); } else { Con_Message("P_InitPicAnims: Registering default animations...\n"); loadAnimDefs(animsShared); } VERBOSE(Con_Message("P_InitPicAnims: Done.\n")); } boolean P_ActivateLine(linedef_t *ld, mobj_t *mo, int side, int actType) { switch(actType) { case SPAC_CROSS: P_CrossSpecialLine(ld, side, mo); return true; case SPAC_USE: return P_UseSpecialLine(mo, ld, side); case SPAC_IMPACT: P_ShootSpecialLine(mo, ld); return true; default: Con_Error("P_ActivateLine: Unknown Activation Type %i", actType); break; } return false; } /** * Called every time a thing origin is about to cross a line with * a non 0 special. */ void P_CrossSpecialLine(linedef_t *line, int side, mobj_t *thing) { int ok; xline_t *xline; // Extended functionality overrides old. if(XL_CrossLine(line, side, thing)) return; xline = P_ToXLine(line); // Triggers that other things can activate if(!thing->player) { // Things that should NOT trigger specials... switch(thing->type) { case MT_ROCKET: case MT_PLASMA: case MT_BFG: case MT_TROOPSHOT: case MT_HEADSHOT: case MT_BRUISERSHOT: case MT_BRUISERSHOTRED: // jd64 case MT_NTROSHOT: // jd64 return; break; default: break; } ok = 0; switch(xline->special) { case 39: // TELEPORT TRIGGER case 97: // TELEPORT RETRIGGER case 993: // jd64 case 125: // TELEPORT MONSTERONLY TRIGGER case 126: // TELEPORT MONSTERONLY RETRIGGER case 4: // RAISE DOOR case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER case 415: // jd64 ok = 1; break; } // Anything can trigger this line! if(xline->flags & ML_ALLTRIGGER) ok = 1; if(!ok) return; } // Note: could use some const's here. switch(xline->special) { // TRIGGERS. // All from here to RETRIGGERS. case 2: // Open Door EV_DoDoor(line, DT_OPEN); xline->special = 0; break; case 3: // Close Door EV_DoDoor(line, DT_CLOSE); xline->special = 0; break; case 4: // Raise Door EV_DoDoor(line, DT_NORMAL); xline->special = 0; break; case 5: // Raise Floor EV_DoFloor(line, FT_RAISEFLOOR); xline->special = 0; break; case 6: // Fast Ceiling Crush & Raise EV_DoCeiling(line, CT_CRUSHANDRAISEFAST); xline->special = 0; break; case 8: // Build Stairs EV_BuildStairs(line, build8); xline->special = 0; break; case 10: // PlatDownWaitUp EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0); xline->special = 0; break; case 12: // Light Turn On - brightest near EV_LightTurnOn(line, 0); xline->special = 0; break; case 13: // Light Turn On - max EV_LightTurnOn(line, 1); xline->special = 0; break; case 16: // Close Door 30 EV_DoDoor(line, DT_CLOSE30THENOPEN); xline->special = 0; break; case 17: // Start Light Strobing EV_StartLightStrobing(line); xline->special = 0; break; case 19: // Lower Floor EV_DoFloor(line, FT_LOWER); xline->special = 0; break; case 22: // Raise floor to nearest height and change texture EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); xline->special = 0; break; case 25: // Ceiling Crush and Raise EV_DoCeiling(line, CT_CRUSHANDRAISE); xline->special = 0; break; case 30: // Raise floor to shortest texture height // on either side of lines. EV_DoFloor(line, FT_RAISETOTEXTURE); xline->special = 0; break; case 35: // Lights Very Dark EV_LightTurnOn(line, 35.0f/255.0f); xline->special = 0; break; case 36: // Lower Floor (TURBO) EV_DoFloor(line, FT_LOWERTURBO); xline->special = 0; break; case 37: // LowerAndChange EV_DoFloor(line, FT_LOWERANDCHANGE); xline->special = 0; break; case 38: // Lower Floor To Lowest EV_DoFloor(line, FT_LOWERTOLOWEST); xline->special = 0; break; case 420: // jd64 EV_DoFloorAndCeiling(line, FT_TOHIGHESTPLUS8, CT_RAISETOHIGHEST); xline->special = 0; break; case 430: // jd64 EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP); break; case 431: // jd64 EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP); xline->special = 0; break; case 426: // jd64 EV_DoCeiling(line, CT_CUSTOM); break; case 427: // jd64 EV_DoCeiling(line, CT_CUSTOM); xline->special = 0; break; case 991: // jd64 // TELEPORT! EV_FadeSpawn(line, thing); xline->special = 0; break; case 993: // jd64 if(!thing->player) EV_FadeSpawn(line, thing); xline->special = 0; break; case 992: // jd64 // Lower Ceiling to Floor if(EV_DoCeiling(line, CT_LOWERTOFLOOR)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 994: // jd64 // FIXME: DJS - Might as well do this in XG. // Also, export this text string to DED. P_SetMessage(thing->player, "You've found a secret area!", false); thing->player->secretCount++; xline->special = 0; break; case 995: // jd64 // FIXME: DJS - Might as well do this in XG. P_SetMessage(thing->player, "You've found a shrine!", false); xline->special = 0; break; case 998: // jd64 // BE GONE! EV_FadeAway(line, thing); xline->special = 0; break; case 39: // TELEPORT! EV_Teleport(line, side, thing, true); xline->special = 0; break; case 40: // RaiseCeilingLowerFloor EV_DoCeiling(line, CT_RAISETOHIGHEST); EV_DoFloor(line, FT_LOWERTOLOWEST); xline->special = 0; break; case 44: // Ceiling Crush EV_DoCeiling(line, CT_LOWERANDCRUSH); xline->special = 0; break; case 52: // EXIT! G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); break; case 53: // Perpetual Platform Raise EV_DoPlat(line, PT_PERPETUALRAISE, 0); xline->special = 0; break; case 54: // Platform Stop P_PlatDeactivate(xline->tag); xline->special = 0; break; case 56: // Raise Floor Crush EV_DoFloor(line, FT_RAISEFLOORCRUSH); xline->special = 0; break; case 57: // Ceiling Crush Stop P_CeilingDeactivate(xline->tag); xline->special = 0; break; case 58: // Raise Floor 24 EV_DoFloor(line, FT_RAISE24); xline->special = 0; break; case 59: // Raise Floor 24 And Change EV_DoFloor(line, FT_RAISE24ANDCHANGE); xline->special = 0; break; case 104: // Turn lights off in sector(tag) EV_TurnTagLightsOff(line); xline->special = 0; break; case 108: // Blazing Door Raise (faster than TURBO!) EV_DoDoor(line, DT_BLAZERAISE); xline->special = 0; break; case 109: // Blazing Door Open (faster than TURBO!) EV_DoDoor(line, DT_BLAZEOPEN); xline->special = 0; break; case 100: // Build Stairs Turbo 16 EV_BuildStairs(line, turbo16); xline->special = 0; break; case 110: // Blazing Door Close (faster than TURBO!) EV_DoDoor(line, DT_BLAZECLOSE); xline->special = 0; break; case 119: // Raise floor to nearest surr. floor EV_DoFloor(line, FT_RAISEFLOORTONEAREST); xline->special = 0; break; case 121: // Blazing PlatDownWaitUpStay EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0); xline->special = 0; break; case 124: // Secret EXIT G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, true), 0, true); break; case 125: // TELEPORT MonsterONLY if(!thing->player) { EV_Teleport(line, side, thing, true); xline->special = 0; } break; case 130: // Raise Floor Turbo EV_DoFloor(line, FT_RAISEFLOORTURBO); xline->special = 0; break; case 141: // Silent Ceiling Crush & Raise EV_DoCeiling(line, CT_SILENTCRUSHANDRAISE); xline->special = 0; break; // RETRIGGERS. All from here till end. case 72: // Ceiling Crush EV_DoCeiling(line, CT_LOWERANDCRUSH); break; case 73: // Ceiling Crush and Raise EV_DoCeiling(line, CT_CRUSHANDRAISE); break; case 74: // Ceiling Crush Stop P_CeilingDeactivate(xline->tag); break; case 75: // Close Door EV_DoDoor(line, DT_CLOSE); break; case 76: // Close Door 30 EV_DoDoor(line, DT_CLOSE30THENOPEN); break; case 77: // Fast Ceiling Crush & Raise EV_DoCeiling(line, CT_CRUSHANDRAISEFAST); break; case 79: // Lights Very Dark EV_LightTurnOn(line, 35.0f/255.0f); break; case 80: // Light Turn On - brightest near EV_LightTurnOn(line, 0); break; case 81: // Light Turn On - max EV_LightTurnOn(line, 1); break; case 82: // Lower Floor To Lowest EV_DoFloor(line, FT_LOWERTOLOWEST); break; case 83: // Lower Floor EV_DoFloor(line, FT_LOWER); break; case 84: // LowerAndChange EV_DoFloor(line, FT_LOWERANDCHANGE); break; case 86: // Open Door EV_DoDoor(line, DT_OPEN); break; case 87: // Perpetual Platform Raise EV_DoPlat(line, PT_PERPETUALRAISE, 0); break; case 88: // PlatDownWaitUp EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0); break; case 415: // jd64 if(thing->player) EV_DoPlat(line, PT_UPWAITDOWNSTAY, 0); break; case 89: // Platform Stop P_PlatDeactivate(xline->tag); break; case 90: // Raise Door EV_DoDoor(line, DT_NORMAL); break; case 91: // Raise Floor EV_DoFloor(line, FT_RAISEFLOOR); break; case 92: // Raise Floor 24 EV_DoFloor(line, FT_RAISE24); break; case 93: // Raise Floor 24 And Change EV_DoFloor(line, FT_RAISE24ANDCHANGE); break; case 94: // Raise Floor Crush EV_DoFloor(line, FT_RAISEFLOORCRUSH); break; case 95: // Raise floor to nearest height // and change texture. EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); break; case 96: // Raise floor to shortest texture height // on either side of lines. EV_DoFloor(line, FT_RAISETOTEXTURE); break; case 97: // TELEPORT! EV_Teleport(line, side, thing, true); break; case 423: // jd64 // TELEPORT! (no fog) // FIXME: DJS - might as well do this in XG. EV_Teleport(line, side, thing, false); break; case 98: // Lower Floor (TURBO) EV_DoFloor(line, FT_LOWERTURBO); break; case 105: // Blazing Door Raise (faster than TURBO!) EV_DoDoor(line, DT_BLAZERAISE); break; case 106: // Blazing Door Open (faster than TURBO!) EV_DoDoor(line, DT_BLAZEOPEN); break; case 107: // Blazing Door Close (faster than TURBO!) EV_DoDoor(line, DT_BLAZECLOSE); break; case 120: // Blazing PlatDownWaitUpStay. EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0); break; case 126: // TELEPORT MonsterONLY. if(!thing->player) EV_Teleport(line, side, thing, true); break; case 128: // Raise To Nearest Floor EV_DoFloor(line, FT_RAISEFLOORTONEAREST); break; case 129: // Raise Floor Turbo EV_DoFloor(line, FT_RAISEFLOORTURBO); break; case 155: // jd64 // Raise Floor 512 // FIXME: DJS - again, might as well do this in XG. if(EV_DoFloor(line, FT_RAISE32)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); P_ToXLine(line)->special = 0; } break; } } /** * Called when a thing shoots a special line. */ void P_ShootSpecialLine(mobj_t *thing, linedef_t *line) { int ok; xline_t* xline = P_ToXLine(line); // Impacts that other things can activate. if(!thing->player) { ok = 0; switch(xline->special) { case 46: // OPEN DOOR IMPACT ok = 1; break; } if(!ok) return; } switch(xline->special) { case 24: // RAISE FLOOR EV_DoFloor(line, FT_RAISEFLOOR); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; break; case 46: // OPEN DOOR EV_DoDoor(line, DT_OPEN); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 47: // RAISE FLOOR NEAR AND CHANGE EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; break; case 191: // jd64 // LOWER FLOOR WAIT RAISE EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; } } /** * Called every tic frame that the player origin is in a special sector */ void P_PlayerInSpecialSector(player_t *player) { sector_t *sector = P_GetPtrp(player->plr->mo->subsector, DMU_SECTOR); // Falling, not all the way down yet? if(player->plr->mo->pos[VZ] != P_GetFixedp(sector, DMU_FLOOR_HEIGHT)) return; // Has hitten ground. switch(P_ToXSector(sector)->special) { case 5: // HELLSLIME DAMAGE if(!player->powers[PT_IRONFEET]) if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 10, false); break; case 7: // NUKAGE DAMAGE if(!player->powers[PT_IRONFEET]) if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 5, false); break; case 16: // SUPER HELLSLIME DAMAGE case 4: // STROBE HURT if(!player->powers[PT_IRONFEET] || (P_Random() < 5)) { if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 20, false); } break; case 9: // SECRET SECTOR player->secretCount++; P_ToXSector(sector)->special = 0; if(cfg.secretMsg) { P_SetMessage(player, "You've found a secret area!", false); // S_ConsoleSound(SFX_SECRET, 0, player - players); // jd64 } break; /* case 11: // EXIT SUPER DAMAGE! (for E1M8 finale) player->cheats &= ~CF_GODMODE; if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 20); if(player->health <= 10) G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, false); break; */ default: break; } } /** * Animate planes, scroll walls, etc. */ void P_UpdateSpecials(void) { float x, y; // jd64 added @c y, linedef_t* line; sidedef_t* side; // Extended lines and sectors. XG_Ticker(); // Animate line specials. if(P_IterListSize(linespecials)) { P_IterListResetIterator(linespecials, false); while((line = P_IterListIterator(linespecials)) != NULL) { switch(P_ToXLine(line)->special) { case 48: side = P_GetPtrp(line, DMU_SIDEDEF0); // EFFECT FIRSTCOL SCROLL + x = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X, x += 1); x = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X, x += 1); x = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X, x += 1); break; case 150: // jd64 side = P_GetPtrp(line, DMU_SIDEDEF0); // EFFECT FIRSTCOL SCROLL - x = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X, x -= 1); x = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X, x -= 1); x = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X, x -= 1); break; case 2561: // jd64 // Scroll_Texture_Up side = P_GetPtrp(line, DMU_SIDEDEF0); // EFFECT FIRSTCOL SCROLL + y = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y, y += 1); y = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y, y += 1); y = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y, y += 1); break; case 2562: // jd64 // Scroll_Texture_Down side = P_GetPtrp(line, DMU_SIDEDEF0); // EFFECT FIRSTCOL SCROLL + y = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y, y -= 1); y = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y, y -= 1); y = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y, y -= 1); break; case 2080: // jd64 // Scroll Up/Right side = P_GetPtrp(line, DMU_SIDEDEF0); y = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y, y += 1); y = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y, y += 1); y = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y, y += 1); x = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X, x -= 1); x = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X, x -= 1); x = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X, x -= 1); break; case 2614: // jd64 // Scroll Up/Left side = P_GetPtrp(line, DMU_SIDEDEF0); y = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_Y, y += 1); y = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y, y += 1); y = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y, y += 1); x = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X, x += 1); x = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X, x += 1); x = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X, x += 1); break; default: break; } } } } /** * d64tc */ void P_ThunderSector(void) { sector_t *sec = NULL; iterlist_t *list; if(!(P_Random() < 10)) return; list = P_GetSectorIterListForTag(20000, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(!(mapTime & 32)) { P_SetFloatp(sec, DMU_LIGHT_LEVEL, 1); S_StartSound(SFX_SSSIT, P_GetPtrp(sec, DMU_SOUND_ORIGIN)); } } } /** * After the map has been loaded, scan for specials that spawn thinkers. */ void P_SpawnSpecials(void) { uint i; linedef_t *line; xline_t *xline; iterlist_t *list; sector_t *sec; xsector_t *xsec; // Init special SECTORs. P_DestroySectorTagLists(); for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); if(xsec->tag) { list = P_GetSectorIterListForTag(xsec->tag, true); P_AddObjectToIterList(list, sec); } if(!xsec->special) continue; if(IS_CLIENT) { switch(xsec->special) { case 9: // SECRET SECTOR totalSecret++; break; } continue; } // jd64 > // DJS - yet more hacks! Why use the tag? switch(xsec->tag) { case 10000: case 10001: case 10002: case 10003: case 10004: P_SpawnGlowingLight(sec); break; case 11000: P_SpawnLightFlash(sec); break; case 12000: P_SpawnFireFlicker(sec); break; case 13000: P_SpawnLightBlink(sec); break; case 20000: P_SpawnGlowingLight(sec); break; } // < d64tc switch(xsec->special) { case 1: // FLICKERING LIGHTS P_SpawnLightFlash(sec); break; case 2: // STROBE FAST P_SpawnStrobeFlash(sec, FASTDARK, 0); break; case 3: // STROBE SLOW P_SpawnStrobeFlash(sec, SLOWDARK, 0); break; case 4: // STROBE FAST/DEATH SLIME P_SpawnStrobeFlash(sec, FASTDARK, 0); xsec->special = 4; break; case 8: // GLOWING LIGHT P_SpawnGlowingLight(sec); break; case 9: // SECRET SECTOR totalSecret++; break; case 10: // DOOR CLOSE IN 30 SECONDS P_SpawnDoorCloseIn30(sec); break; case 12: // SYNC STROBE SLOW P_SpawnStrobeFlash(sec, SLOWDARK, 1); break; case 13: // SYNC STROBE FAST P_SpawnStrobeFlash(sec, FASTDARK, 1); break; case 14: // DOOR RAISE IN 5 MINUTES P_SpawnDoorRaiseIn5Mins(sec); break; case 17: P_SpawnFireFlicker(sec); break; } } // Init animating line specials. P_EmptyIterList(linespecials); P_DestroyLineTagLists(); for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); xline = P_ToXLine(line); switch(xline->special) { case 48: // EFFECT FIRSTCOL SCROLL+ case 150: // jd64: wall scroll right case 2561: // jd64: wall scroll up case 2562: // jd64: wall scroll down case 2080: // jd64: wall scroll up/right case 2614: // jd64: wall scroll up/left P_AddObjectToIterList(linespecials, line); break; case 994: // jd64 // kaiser - be sure to have that linedef count the secrets. // FIXME: DJS - secret lines?? totalSecret++; break; } if(xline->tag) { list = P_GetLineIterListForTag(xline->tag, true); P_AddObjectToIterList(list, line); } } // Init extended generalized lines and sectors. XG_Init(); } boolean P_UseSpecialLine2(mobj_t* mo, linedef_t* line, int side) { xline_t* xline = P_ToXLine(line); // Err... // Use the back sides of VERY SPECIAL lines... if(side) { switch(xline->special) { case 124: // Sliding door open&close // UNUSED? break; default: return false; break; } } // Switches that other things can activate. if(!mo->player) { // Never open secret doors. if(xline->flags & ML_SECRET) return false; switch(xline->special) { case 1: // MANUAL DOOR RAISE case 32: // MANUAL BLUE case 33: // MANUAL RED case 34: // MANUAL YELLOW break; default: return false; break; } } // Do something. switch(xline->special) { // MANUALS case 1: // Vertical Door case 26: // Blue Door/Locked case 27: // Yellow Door /Locked case 28: // Red Door /Locked case 31: // Manual door open case 32: // Blue locked door open case 33: // Red locked door open case 34: // Yellow locked door open case 117: // Blazing door raise case 118: // Blazing door open case 525: // jd64 case 526: // jd64 case 527: // jd64 EV_VerticalDoor(line, mo); break; //UNUSED - Door Slide Open&Close // case 124: // EV_SlidingDoor (line, mo); // break; // SWITCHES case 7: // Build Stairs, if(EV_BuildStairs(line, build8)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 9: // Change Donut, if(EV_DoDonut(line)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 11: // Exit level, if(cyclingMaps && mapCycleNoExit) break; // Prevent zombies from exiting levels, if(mo->player && mo->player->health <= 0 && !cfg.zombiesCanExit) { S_StartSound(SFX_NOWAY, mo); return false; } P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_SWTCHX, false, 0); xline->special = 0; G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); break; case 14: // Raise Floor 32 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 15: // Raise Floor 24 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 18: // Raise Floor to next highest floor. if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 20: // Raise Plat next highest floor and change texture. if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 21: // PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 23: // Lower Floor to Lowest. if(EV_DoFloor(line, FT_LOWERTOLOWEST)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 29: // Raise Door. if(EV_DoDoor(line, DT_NORMAL)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 41: // Lower Ceiling to Floor. if(EV_DoCeiling(line, CT_LOWERTOFLOOR)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 71: // Turbo Lower Floor. if(EV_DoFloor(line, FT_LOWERTURBO)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 49: // Ceiling Crush And Raise. if(EV_DoCeiling(line, CT_CRUSHANDRAISE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 50: // Close Door. if(EV_DoDoor(line, DT_CLOSE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 51: // Secret EXIT. if(cyclingMaps && mapCycleNoExit) break; // Prevent zombies from exiting levels. if(mo->player && mo->player->health <= 0 && !cfg.zombiesCanExit) { S_StartSound(SFX_NOWAY, mo); return false; } P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, true), 0, true); break; case 55: // Raise Floor Crush. if(EV_DoFloor(line, FT_RAISEFLOORCRUSH)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 101: // Raise Floor. if(EV_DoFloor(line, FT_RAISEFLOOR)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 102: // Lower Floor to Surrounding floor height. if(EV_DoFloor(line, FT_LOWER)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 103: // Open Door. if(EV_DoDoor(line, DT_OPEN)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 111: // Blazing Door Raise (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZERAISE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 112: // Blazing Door Open (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZEOPEN)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 113: // Blazing Door Close (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZECLOSE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 122: // Blazing PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 127: // Build Stairs Turbo 16. if(EV_BuildStairs(line, turbo16)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 131: // Raise Floor Turbo. if(EV_DoFloor(line, FT_RAISEFLOORTURBO)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 133: // BlzOpenDoor BLUE. case 135: // BlzOpenDoor RED. case 137: // BlzOpenDoor YELLOW. if(EV_DoLockedDoor(line, DT_BLAZEOPEN, mo)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 140: // Raise Floor 512. if(EV_DoFloor(line, FT_RAISE512)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; // BUTTONS case 42: // Close Door. if(EV_DoDoor(line, DT_CLOSE)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 43: // Lower Ceiling to Floor. if(EV_DoCeiling(line, CT_LOWERTOFLOOR)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 45: // Lower Floor to Surrounding floor height. if(EV_DoFloor(line, FT_LOWER)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 60: // Lower Floor to Lowest. if(EV_DoFloor(line, FT_LOWERTOLOWEST)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 61: // Open Door. if(EV_DoDoor(line, DT_OPEN)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 62: // PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 1)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 63: // Raise Door. if(EV_DoDoor(line, DT_NORMAL)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 64: // Raise Floor to ceiling. if(EV_DoFloor(line, FT_RAISEFLOOR)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 66: // Raise Floor 24 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 67: // Raise Floor 32 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 65: // Raise Floor Crush. if(EV_DoFloor(line, FT_RAISEFLOORCRUSH)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 68: // Raise Plat to next highest floor and change texture. if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 69: // Raise Floor to next highest floor. if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 70: // Turbo Lower Floor. if(EV_DoFloor(line, FT_LOWERTURBO)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 114: // Blazing Door Raise (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZERAISE)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 115: // Blazing Door Open (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZEOPEN)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 116: // Blazing Door Close (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZECLOSE)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 123: // Blazing PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 132: // Raise Floor Turbo. if(EV_DoFloor(line, FT_RAISEFLOORTURBO)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 99: // BlzOpenDoor BLUE. case 134: // BlzOpenDoor RED. case 136: // BlzOpenDoor YELLOW. if(EV_DoLockedDoor(line, DT_BLAZERAISE, mo)) // jd64 was "DT_BLAZEOPEN" P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 138: // Light Turn On. EV_LightTurnOn(line, 1); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 139: // Light Turn Off. EV_LightTurnOn(line, 35.0f/255.0f); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 343: // jd64 - BlzOpenDoor LaserPowerup 1. case 344: // jd64 - BlzOpenDoor LaserPowerup 2. case 345: // jd64 - BlzOpenDoor LaserPowerup 3. if(EV_DoLockedDoor(line, DT_BLAZEOPEN, mo)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 414: // jd64 if(EV_DoPlat(line, PT_UPWAITDOWNSTAY, 1)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 416: // jd64 if(EV_DoFloorAndCeiling(line, FT_TOHIGHESTPLUS8, CT_RAISETOHIGHEST)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 424: // jd64 if(EV_DoCeiling(line, CT_CUSTOM)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 425: // jd64 if(EV_DoCeiling(line, CT_CUSTOM)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 428: // jd64 if(EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 429: // jd64 if(EV_DoFloor(line, FT_TOHIGHESTPLUSBITMIP)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_telept.c0000644000175000017500000003046611357170242022610 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.c: */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom64.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_map.h" #include "p_mapspec.h" #include "p_terraintype.h" #include "p_start.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle) { return P_SpawnMobj3f(MT_TFOG, x, y, TELEFOGHEIGHT, angle, MSF_Z_FLOOR); } typedef struct { sector_t* sec; mobjtype_t type; mobj_t* foundMobj; } findmobjparams_t; static boolean findMobj(thinker_t* th, void* context) { findmobjparams_t* params = (findmobjparams_t*) context; mobj_t* mo = (mobj_t *) th; // Must be of the correct type? if(params->type >= 0 && params->type != mo->type) return true; // Continue iteration. // Must be in the specified sector? if(params->sec && params->sec != P_GetPtrp(mo->subsector, DMU_SECTOR)) return true; // Continue iteration. // Found it! params->foundMobj = mo; return false; // Stop iteration. } static mobj_t* getTeleportDestination(short tag) { iterlist_t* list; list = P_GetSectorIterListForTag(tag, false); if(list) { sector_t* sec = NULL; findmobjparams_t params; params.type = MT_TELEPORTMAN; params.foundMobj = NULL; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { params.sec = sec; if(!DD_IterateThinkers(P_MobjThinker, findMobj, ¶ms)) { // Found one. return params.foundMobj; } } } return NULL; } int EV_Teleport(linedef_t* line, int side, mobj_t* mo, boolean spawnFog) { mobj_t* dest; if(mo->flags2 & MF2_NOTELEPORT) return 0; // Don't teleport if hit back of line, so you can get out of teleporter. if(side == 1) return 0; if((dest = getTeleportDestination(P_ToXLine(line)->tag)) != NULL) { // A suitable destination has been found. mobj_t* fog; uint an; float oldPos[3]; float aboveFloor; angle_t oldAngle; memcpy(oldPos, mo->pos, sizeof(mo->pos)); oldAngle = mo->angle; aboveFloor = mo->pos[VZ] - mo->floorZ; if(!P_TeleportMove(mo, dest->pos[VX], dest->pos[VY], false)) return 0; mo->pos[VZ] = mo->floorZ; if(spawnFog) { // Spawn teleport fog at source and destination. if((fog = P_SpawnMobj3fv(MT_TFOG, oldPos, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); an = dest->angle >> ANGLETOFINESHIFT; if((fog = P_SpawnMobj3f(MT_TFOG, dest->pos[VX] + 20 * FIX2FLT(finecosine[an]), dest->pos[VY] + 20 * FIX2FLT(finesine[an]), mo->pos[VZ], dest->angle + ANG180, 0))) { // Emit sound, where? S_StartSound(SFX_TELEPT, fog); } } mo->angle = dest->angle; if(mo->flags2 & MF2_FLOORCLIP) { mo->floorClip = 0; if(mo->pos[VZ] == P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } } mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; // Don't move for a bit. if(mo->player) { mo->reactionTime = 18; if(mo->player->powers[PT_FLIGHT] && aboveFloor > 0) { mo->pos[VZ] = mo->floorZ + aboveFloor; if(mo->pos[VZ] + mo->height > mo->ceilingZ) { mo->pos[VZ] = mo->ceilingZ - mo->height; } } else { //mo->dPlayer->clLookDir = 0; /* $unifiedangles */ mo->dPlayer->lookDir = 0; } mo->player->viewHeight = (float) cfg.plrViewHeight; mo->player->viewHeightDelta = 0; mo->player->viewZ = mo->pos[VZ] + mo->player->viewHeight; //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */ mo->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; } return 1; } return 0; } /** * d64tc * If the given doomed number is a type which fade spawns, this will return * the corresponding mobjtype. Else -1. * * DJS - Added in order to cleanup EV_FadeSpawn() somewhat. * \todo This is still far from ideal. An MF*_* flag would be better. */ static mobjtype_t isFadeSpawner(int doomEdNum) { typedef struct fadespawner_s { int doomEdNum; mobjtype_t type; } fadespawner_t; static const fadespawner_t spawners[] = { {7575, MT_SHOTGUN}, {7576, MT_CHAINGUN}, {7577, MT_SUPERSHOTGUN}, {7578, MT_MISC27}, {7579, MT_MISC28}, {7580, MT_MISC25}, {7581, MT_MISC11}, {7582, MT_MISC10}, {7583, MT_MISC0}, {7584, MT_MISC1}, {7585, MT_LASERGUN}, {7586, MT_LPOWERUP1}, {7587, MT_LPOWERUP2}, {7588, MT_LPOWERUP3}, {7589, MT_MEGA}, {7590, MT_MISC12}, {7591, MT_INS}, {7592, MT_INV}, {7593, MT_MISC13}, {7594, MT_MISC2}, {7595, MT_MISC3}, {7596, MT_MISC15}, {7597, MT_MISC16}, {7598, MT_MISC14}, {7599, MT_MISC22}, {7600, MT_MISC23}, {7601, MT_CLIP}, {7602, MT_MISC17}, {7603, MT_MISC18}, {7604, MT_MISC19}, {7605, MT_MISC20}, {7606, MT_MISC21}, {7607, MT_MISC24}, {7608, MT_POSSESSED}, {7609, MT_SHOTGUY}, {7610, MT_TROOP}, {7611, MT_NTROOP}, {7612, MT_SERGEANT}, {7613, MT_SHADOWS}, {7615, MT_HEAD}, {7617, MT_SKULL}, {7618, MT_PAIN}, {7619, MT_FATSO}, {7620, MT_BABY}, {7621, MT_CYBORG}, {7622, MT_BITCH}, {7623, MT_KNIGHT}, {7624, MT_BRUISER}, {7625, MT_MISC5}, {7626, MT_MISC8}, {7627, MT_MISC4}, {7628, MT_MISC9}, {7629, MT_MISC6}, {7630, MT_MISC7}, {-1, -1} // Terminator. }; int i; for(i = 0; spawners[i].doomEdNum; ++i) if(spawners[i].doomEdNum == doomEdNum) return spawners[i].type; return -1; } typedef struct { sector_t* sec; float spawnHeight; } fadespawnparams_t; static boolean fadeSpawn(thinker_t* th, void* context) { fadespawnparams_t* params = (fadespawnparams_t*) context; mobj_t* origin = (mobj_t *) th; mobjtype_t spawntype; if(params->sec && params->sec != P_GetPtrp(origin->subsector, DMU_SECTOR)) return true; // Contiue iteration. // Only fade spawn origins of a certain type. spawntype = isFadeSpawner(origin->info->doomEdNum); if(spawntype != -1) { angle_t an; mobj_t* mo; float pos[3]; an = origin->angle >> ANGLETOFINESHIFT; memcpy(pos, origin->pos, sizeof(pos)); pos[VX] += 20 * FIX2FLT(finecosine[an]); pos[VY] += 20 * FIX2FLT(finesine[an]); pos[VZ] = params->spawnHeight; if((mo = P_SpawnMobj3fv(spawntype, pos, origin->angle, 0))) { mo->translucency = 255; mo->spawnFadeTics = 0; mo->intFlags |= MIF_FADE; // Emit sound, where? S_StartSound(SFX_ITMBK, mo); if(MOBJINFO[spawntype].flags & MF_COUNTKILL) totalKills++; } } return true; // Continue iteration. } /** * d64tc * kaiser - This sets a thing spawn depending on thing type placed in * tagged sector. * \todo DJS - This is not a good design. There must be a better way * to do this using a new thing flag (MF_NOTSPAWNONSTART?). */ int EV_FadeSpawn(linedef_t* li, mobj_t* mo) { iterlist_t* list; list = P_GetSectorIterListForTag(P_ToXLine(li)->tag, false); if(list) { sector_t* sec; fadespawnparams_t params; params.spawnHeight = mo->pos[VZ]; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { params.sec = sec; DD_IterateThinkers(P_MobjThinker, fadeSpawn, ¶ms); } } return 0; } // Bitwise ops (for changeMobjFlags) typedef enum { BW_CLEAR, BW_SET, BW_XOR } bitwiseop_t; typedef struct { sector_t* sec; boolean notPlayers; int flags; bitwiseop_t op; } pit_changemobjflagsparams_t; boolean PIT_ChangeMobjFlags(thinker_t* th, void* context) { pit_changemobjflagsparams_t* params = (pit_changemobjflagsparams_t*) context; mobj_t* mo = (mobj_t*) th; if(params->sec && params->sec != P_GetPtrp(mo->subsector, DMU_SECTOR)) return true; // Continue iteration. if(params->notPlayers && mo->player) return true; // Continue iteration. switch(params->op) { case BW_CLEAR: mo->flags &= ~params->flags; break; case BW_SET: mo->flags |= params->flags; break; case BW_XOR: mo->flags ^= params->flags; break; default: Con_Error("PIT_ChangeMobjFlags: Unknown flag bit op %i\n", params->op); break; } return true; // Continue iteration. } /** * d64tc * kaiser - removes things in tagged sector! * DJS - actually, no it doesn't at least not directly. * * \fixme: It appears the MF_TELEPORT flag has been hijacked. */ int EV_FadeAway(linedef_t* line, mobj_t* thing) { sector_t* sec = NULL; iterlist_t* list; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(list) { pit_changemobjflagsparams_t params; params.flags = MF_TELEPORT; params.op = BW_SET; params.notPlayers = true; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { params.sec = sec; DD_IterateThinkers(P_MobjThinker, PIT_ChangeMobjFlags, ¶ms); } } return 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/wi_stuff.c0000644000175000017500000007110711357170242022617 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * wi_stuff.c: Intermission/stat screens - jDoom64 specific. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "jdoom64.h" #include "hu_stuff.h" #include "d_net.h" #include "p_start.h" // MACROS ------------------------------------------------------------------ #define NUM_TEAMS (4) // Color = team. // GLOBAL LOCATIONS #define WI_TITLEY (2) #define WI_SPACINGY (33) // SINGPLE-PLAYER STUFF #define SP_STATSX (50) #define SP_STATSY (50) #define SP_TIMEX (16) #define SP_TIMEY (SCREENHEIGHT-32) // NET GAME STUFF #define NG_STATSY (50) #define NG_STATSX (32 + star.width /2 + 32*!doFrags) #define NG_SPACINGX (64) // DEATHMATCH STUFF #define DM_MATRIXX (42) #define DM_MATRIXY (68) #define DM_SPACINGX (40) #define DM_TOTALSX (269) #define DM_KILLERSX (10) #define DM_KILLERSY (100) #define DM_VICTIMSX (5) #define DM_VICTIMSY (50) // TYPES ------------------------------------------------------------------- typedef struct teaminfo_s { int members; // 0 if team not present. int frags[NUM_TEAMS]; int totalFrags; // Kills minus suicides. int items; int kills; int secret; } teaminfo_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static teaminfo_t teamInfo[NUM_TEAMS]; // Used to accelerate or skip a stage. static int accelerateStage; static int spState, dmState, ngState; static int dmFrags[NUM_TEAMS][NUM_TEAMS]; static int dmTotals[NUM_TEAMS]; static int doFrags; // wbs->pnum static int me, myTeam; // Specifies current state. static interludestate_t state; // Contains information passed into intermission. static wbstartstruct_t *wbs; static wbplayerstruct_t *plrs; // wbs->plyr[] // Used for general timing. static int cnt; // Used for timing of background animation. static int bcnt; static int cntKills[NUM_TEAMS]; static int cntItems[NUM_TEAMS]; static int cntSecret[NUM_TEAMS]; static int cntFrags[NUM_TEAMS]; static int cntTime; static int cntPar; static int cntPause; static dpatch_t bg; // Background (map of levels). static dpatch_t percent; static dpatch_t colon; static dpatch_t num[10]; // 0-9 graphic. static dpatch_t minus; // Minus sign. static dpatch_t finished; // "Finished!" static dpatch_t entering; // "Entering" static dpatch_t sp_secret; // "secret" static dpatch_t kills; // "Kills" static dpatch_t secret; // "Scrt" static dpatch_t items; // "Items" static dpatch_t frags; // "Frags" static dpatch_t time; // "Time" static dpatch_t par; // "Par" static dpatch_t sucks; // "Sucks!" static dpatch_t killers; // "killers" static dpatch_t victims; // "victims" static dpatch_t total; // "Total" static dpatch_t star; // Player icon (alive). static dpatch_t bstar; // Player icon (dead). static dpatch_t p[MAXPLAYERS]; // "red P[1..MAXPLAYERS]" static dpatch_t bp[MAXPLAYERS]; // "gray P[1..MAXPLAYERS]" // CODE -------------------------------------------------------------------- void WI_slamBackground(void) { GL_DrawPatch(0, 0, bg.lump); } /** * Draws " Finished!" */ void WI_drawLF(void) { int y = WI_TITLEY; int mapnum; char *lname, *ptr; lname = (char *) DD_GetVariable(DD_MAP_NAME); if(gameMode == commercial) mapnum = wbs->currentMap; else mapnum = (wbs->episode * 8) + wbs->currentMap; ptr = strchr(lname, ':'); // Skip the E#M# or Level #. if(ptr) { lname = ptr + 1; while(*lname && isspace(*lname)) lname++; } // Draw WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &mapNamePatches[mapnum], lname, false, ALIGN_CENTER); // Draw "Finished!" y += (5 * mapNamePatches[mapnum].height) / 4; WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &finished, NULL, false, ALIGN_CENTER); } /** * Draws "Entering " */ void WI_drawEL(void) { int y = WI_TITLEY; char *lname = "", *ptr; ddmapinfo_t minfo; char levid[10]; P_GetMapLumpName(wbs->episode, wbs->nextMap, levid); // See if there is a level name. if(Def_Get(DD_DEF_MAP_INFO, levid, &minfo) && minfo.name) { if(Def_Get(DD_DEF_TEXT, minfo.name, &lname) == -1) lname = minfo.name; } ptr = strchr(lname, ':'); // Skip the E#M# or Level #. if(ptr) { lname = ptr + 1; while(*lname && isspace(*lname)) lname++; } // Draw "Entering" WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &entering, NULL, false, ALIGN_CENTER); // Draw level. y += (5 * mapNamePatches[wbs->nextMap].height) / 4; WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &mapNamePatches[(wbs->episode * 8) + wbs->nextMap], lname, false, ALIGN_CENTER); } void WI_initAnimatedBack(void) { // Nothing to do. } void WI_updateAnimatedBack(void) { // Nothing to do. } void WI_drawAnimatedBack(void) { // Nothing to do. } /** * Draws a number. * If digits > 0, then use that many digits minimum, otherwise only use as * many as necessary. * * @return New x position. */ int WI_drawNum(int x, int y, int n, int digits) { int fontwidth = num[0].width; int neg, temp; if(digits < 0) { if(!n) { // Make variable-length zeros 1 digit long. digits = 1; } else { // Figure out # of digits in # digits = 0; temp = n; while(temp) { temp /= 10; digits++; } } } neg = n < 0; if(neg) n = -n; // If non-number, do not draw it. if(n == 1994) return 0; // Draw the new number. while(digits--) { x -= fontwidth; WI_DrawPatch(x, y, 1, 1, 1, 1, &num[n % 10], NULL, false, ALIGN_LEFT); n /= 10; } // Draw a minus sign if necessary. if(neg) WI_DrawPatch(x -= 8, y, 1, 1, 1, 1, &minus, NULL, false, ALIGN_LEFT); return x; } void WI_drawPercent(int x, int y, int p) { if(p < 0) return; WI_DrawPatch(x, y, 1, 1, 1, 1, &percent, NULL, false, ALIGN_LEFT); WI_drawNum(x, y, p, -1); } /** * Display level completion time and par, or "sucks" message if overflow. */ void WI_drawTime(int x, int y, int t) { int div, n; if(t < 0) return; if(t <= 61 * 59) { div = 1; do { n = (t / div) % 60; x = WI_drawNum(x, y, n, 2) - colon.width; div *= 60; if(div == 60 || t / div) WI_DrawPatch(x, y, 1, 1, 1, 1, &colon, NULL, false, ALIGN_LEFT); } while(t / div); } else { // "sucks" WI_DrawPatch(x - sucks.width, y, 1, 1, 1, 1, &sucks, NULL, false, ALIGN_LEFT); } } void WI_End(void) { NetSv_Intermission(IMF_END, 0, 0); } void WI_initNoState(void) { state = ILS_NONE; accelerateStage = 0; cnt = 10; NetSv_Intermission(IMF_STATE, state, 0); } void WI_updateNoState(void) { WI_updateAnimatedBack(); if(!--cnt) { if(IS_CLIENT) return; WI_End(); G_WorldDone(); } } void WI_drawNoState(void) { // Nothing to do. } int WI_fragSum(int teamnum) { return teamInfo[teamnum].totalFrags; } void WI_initDeathmatchStats(void) { int i; state = ILS_SHOW_STATS; accelerateStage = 0; dmState = 1; cntPause = TICRATE; // Clear the on-screen counters. memset(dmTotals, 0, sizeof(dmTotals)); for(i = 0; i < NUM_TEAMS; ++i) memset(dmFrags[i], 0, sizeof(dmFrags[i])); WI_initAnimatedBack(); } void WI_updateDeathmatchStats(void) { int i, j; boolean stillTicking; WI_updateAnimatedBack(); if(accelerateStage && dmState != 4) { accelerateStage = 0; for(i = 0; i < NUM_TEAMS; ++i) { for(j = 0; j < NUM_TEAMS; ++j) { dmFrags[i][j] = teamInfo[i].frags[j]; } dmTotals[i] = WI_fragSum(i); } S_LocalSound(SFX_BAREXP, 0); dmState = 4; } if(dmState == 2) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { for(j = 0; j < NUM_TEAMS; ++j) { if(dmFrags[i][j] != teamInfo[i].frags[j]) { if(teamInfo[i].frags[j] < 0) dmFrags[i][j]--; else dmFrags[i][j]++; if(dmFrags[i][j] > 99) dmFrags[i][j] = 99; if(dmFrags[i][j] < -99) dmFrags[i][j] = -99; stillTicking = true; } } dmTotals[i] = WI_fragSum(i); if(dmTotals[i] > 99) dmTotals[i] = 99; if(dmTotals[i] < -99) dmTotals[i] = -99; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); dmState++; } } else if(dmState == 4) { if(accelerateStage) { S_LocalSound(SFX_SLOP, 0); WI_initNoState(); } } else if(dmState & 1) { if(!--cntPause) { dmState++; cntPause = TICRATE; } } } void WI_drawDeathmatchStats(void) { int i, j; int x, y; int w; int lh; // Line height. lh = WI_SPACINGY; WI_slamBackground(); // Draw animated background. WI_drawAnimatedBack(); WI_drawLF(); // Draw stat titles (top line). WI_DrawPatch(DM_TOTALSX - total.width / 2, DM_MATRIXY - WI_SPACINGY + 10, 1, 1, 1, 1, &total, NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_KILLERSX, DM_KILLERSY, 1, 1, 1, 1, &killers, NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, 1, 1, 1, 1, &victims, NULL, false, ALIGN_LEFT); // Draw P? x = DM_MATRIXX + DM_SPACINGX; y = DM_MATRIXY; for(i = 0; i < NUM_TEAMS; ++i) { if(teamInfo[i].members) { WI_DrawPatch(x - p[i].width / 2, DM_MATRIXY - WI_SPACINGY, 1, 1, 1, 1, &p[i], NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_MATRIXX - p[i].width / 2, y, 1, 1, 1, 1, &p[i], NULL, false, ALIGN_LEFT); if(i == myTeam) { WI_DrawPatch(x - p[i].width / 2, DM_MATRIXY - WI_SPACINGY, 1, 1, 1, 1, &bstar, NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_MATRIXX - p[i].width / 2, y, 1, 1, 1, 1, &star, NULL, false, ALIGN_LEFT); } // If more than 1 member, show the member count. if(teamInfo[i].members > 1) { char tmp[20]; sprintf(tmp, "%i", teamInfo[i].members); M_WriteText2(x - p[i].width / 2 + 1, DM_MATRIXY - WI_SPACINGY + p[i].height - 8, tmp, GF_FONTA, 1, 1, 1, 1); M_WriteText2(DM_MATRIXX - p[i].width / 2 + 1, y + p[i].height - 8, tmp, GF_FONTA, 1, 1, 1, 1); } } else { WI_DrawPatch(x - bp[i].width / 2, DM_MATRIXY - WI_SPACINGY, 1, 1, 1, 1, &bp[i], NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_MATRIXX - bp[i].width / 2, y, 1, 1, 1, 1, &bp[i], NULL, false, ALIGN_LEFT); } x += DM_SPACINGX; y += WI_SPACINGY; } // Draw stats. y = DM_MATRIXY + 10; w = num[0].width; for(i = 0; i < NUM_TEAMS; ++i) { x = DM_MATRIXX + DM_SPACINGX; if(teamInfo[i].members) { for(j = 0; j < NUM_TEAMS; ++j) { if(teamInfo[j].members) WI_drawNum(x + w, y, dmFrags[i][j], 2); x += DM_SPACINGX; } WI_drawNum(DM_TOTALSX + w, y, dmTotals[i], 2); } y += WI_SPACINGY; } } void WI_initNetgameStats(void) { int i; state = ILS_SHOW_STATS; accelerateStage = 0; ngState = 1; cntPause = TICRATE; memset(cntKills, 0, sizeof(cntKills)); memset(cntItems, 0, sizeof(cntItems)); memset(cntSecret, 0, sizeof(cntSecret)); memset(cntFrags, 0, sizeof(cntFrags)); doFrags = 0; for(i = 0; i < NUM_TEAMS; ++i) { doFrags += teamInfo[i].totalFrags; } doFrags = !doFrags; WI_initAnimatedBack(); } void WI_updateNetgameStats(void) { int i, fsum; boolean stillTicking; WI_updateAnimatedBack(); if(accelerateStage && ngState != 10) { accelerateStage = 0; for(i = 0; i < NUM_TEAMS; ++i) { cntKills[i] = (teamInfo[i].kills * 100) / wbs->maxKills; cntItems[i] = (teamInfo[i].items * 100) / wbs->maxItems; cntSecret[i] = (teamInfo[i].secret * 100) / wbs->maxSecret; if(doFrags) cntFrags[i] = teamInfo[i].totalFrags; } S_LocalSound(SFX_BAREXP, 0); ngState = 10; } if(ngState == 2) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntKills[i] += 2; if(cntKills[i] >= (teamInfo[i].kills * 100) / wbs->maxKills) cntKills[i] = (teamInfo[i].kills * 100) / wbs->maxKills; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); ngState++; } } else if(ngState == 4) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntItems[i] += 2; if(cntItems[i] >= (teamInfo[i].items * 100) / wbs->maxItems) cntItems[i] = (teamInfo[i].items * 100) / wbs->maxItems; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); ngState++; } } else if(ngState == 6) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntSecret[i] += 2; if(cntSecret[i] >= (teamInfo[i].secret * 100) / wbs->maxSecret) cntSecret[i] = (teamInfo[i].secret * 100) / wbs->maxSecret; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); ngState += 1 + 2 * !doFrags; } } else if(ngState == 8) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntFrags[i] += 1; if(cntFrags[i] >= (fsum = WI_fragSum(i))) cntFrags[i] = fsum; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_PLDETH, 0); ngState++; } } else if(ngState == 10) { if(accelerateStage) { S_LocalSound(SFX_SGCOCK, 0); WI_initNoState(); } } else if(ngState & 1) { if(!--cntPause) { ngState++; cntPause = TICRATE; } } } void WI_drawNetgameStats(void) { int i; int x, y; int pwidth = percent.width; WI_slamBackground(); // Draw animated background. WI_drawAnimatedBack(); WI_drawLF(); // Draw stat titles (top line). WI_DrawPatch(NG_STATSX + NG_SPACINGX - kills.width, NG_STATSY, 1, 1, 1, 1, &kills, NULL, false, ALIGN_LEFT); WI_DrawPatch(NG_STATSX + 2 * NG_SPACINGX - items.width, NG_STATSY, 1, 1, 1, 1, &items, NULL, false, ALIGN_LEFT); WI_DrawPatch(NG_STATSX + 3 * NG_SPACINGX - secret.width, NG_STATSY, 1, 1, 1, 1, &secret, NULL, false, ALIGN_LEFT); if(doFrags) WI_DrawPatch(NG_STATSX + 4 * NG_SPACINGX - frags.width, 1, 1, 1, 1, NG_STATSY, &frags, NULL, false, ALIGN_LEFT); // Draw stats. y = NG_STATSY + kills.height; for(i = 0; i < NUM_TEAMS; ++i) { if(!teamInfo[i].members) continue; x = NG_STATSX; WI_DrawPatch(x - p[i].width, y, 1, 1, 1, 1, &p[i], NULL, false, ALIGN_LEFT); // If more than 1 member, show the member count. if(teamInfo[i].members > 1) { char tmp[40]; sprintf(tmp, "%i", teamInfo[i].members); M_WriteText2(x - p[i].width + 1, y + p[i].height - 8, tmp, GF_FONTA, 1, 1, 1, 1); } if(i == myTeam) WI_DrawPatch(x - p[i].width, y, 1, 1, 1, 1, &star, NULL, false, ALIGN_LEFT); x += NG_SPACINGX; WI_drawPercent(x - pwidth, y + 10, cntKills[i]); x += NG_SPACINGX; WI_drawPercent(x - pwidth, y + 10, cntItems[i]); x += NG_SPACINGX; WI_drawPercent(x - pwidth, y + 10, cntSecret[i]); x += NG_SPACINGX; if(doFrags) WI_drawNum(x, y + 10, cntFrags[i], -1); y += WI_SPACINGY; } } void WI_initStats(void) { state = ILS_SHOW_STATS; accelerateStage = 0; spState = 1; cntKills[0] = cntItems[0] = cntSecret[0] = -1; cntTime = cntPar = -1; cntPause = TICRATE; WI_initAnimatedBack(); } void WI_updateStats(void) { WI_updateAnimatedBack(); if(accelerateStage && spState != 10) { accelerateStage = 0; cntKills[0] = (plrs[me].kills * 100) / wbs->maxKills; cntItems[0] = (plrs[me].items * 100) / wbs->maxItems; cntSecret[0] = (plrs[me].secret * 100) / wbs->maxSecret; cntTime = plrs[me].time; if(wbs->parTime != -1) cntPar = wbs->parTime; S_LocalSound(SFX_BAREXP, 0); spState = 10; } if(spState == 2) { cntKills[0] += 2; if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntKills[0] >= (plrs[me].kills * 100) / wbs->maxKills) { cntKills[0] = (plrs[me].kills * 100) / wbs->maxKills; S_LocalSound(SFX_BAREXP, 0); spState++; } } else if(spState == 4) { cntItems[0] += 2; if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntItems[0] >= (plrs[me].items * 100) / wbs->maxItems) { cntItems[0] = (plrs[me].items * 100) / wbs->maxItems; S_LocalSound(SFX_BAREXP, 0); spState++; } } else if(spState == 6) { cntSecret[0] += 2; if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntSecret[0] >= (plrs[me].secret * 100) / wbs->maxSecret) { cntSecret[0] = (plrs[me].secret * 100) / wbs->maxSecret; S_LocalSound(SFX_BAREXP, 0); spState++; } } else if(spState == 8) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntTime == -1) cntTime = 0; cntTime += TICRATE * 3; // Par time might not be defined so count up and stop on play time instead. if(cntTime >= plrs[me].time) { cntTime = plrs[me].time; cntPar = wbs->parTime; S_LocalSound(SFX_BAREXP, 0); spState++; } if(wbs->parTime != -1) { if(cntPar == -1) cntPar = 0; cntPar += TICRATE * 3; if(cntPar >= wbs->parTime) cntPar = wbs->parTime; } } else if(spState == 10) { if(accelerateStage) { S_LocalSound(SFX_SGCOCK, 0); WI_initNoState(); } } else if(spState & 1) { if(!--cntPause) { spState++; cntPause = TICRATE; } } } void WI_drawStats(void) { int lh; // Line height. lh = (3 * num[0].height) / 2; WI_slamBackground(); // Draw animated background. WI_drawAnimatedBack(); WI_drawLF(); WI_DrawPatch(SP_STATSX, SP_STATSY, 1, 1, 1, 1, &kills, NULL, false, ALIGN_LEFT); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cntKills[0]); WI_DrawPatch(SP_STATSX, SP_STATSY + lh, 1, 1, 1, 1, &items, NULL, false, ALIGN_LEFT); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY + lh, cntItems[0]); WI_DrawPatch(SP_STATSX, SP_STATSY + 2 * lh, 1, 1, 1, 1, &sp_secret, NULL, false, ALIGN_LEFT); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY + 2 * lh, cntSecret[0]); WI_DrawPatch(SP_TIMEX, SP_TIMEY, 1, 1, 1, 1, &time, NULL, false, ALIGN_LEFT); if(cntTime >= 0) WI_drawTime(SCREENWIDTH / 2 - SP_TIMEX, SP_TIMEY, cntTime / TICRATE); if(wbs->parTime != -1) { WI_DrawPatch(SCREENWIDTH / 2 + SP_TIMEX, SP_TIMEY, 1, 1, 1, 1, &par, NULL, false, ALIGN_LEFT); if(cntPar >= 0) WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cntPar / TICRATE); } } void WI_checkForAccelerate(void) { int i; player_t *player; // Check for button presses to skip delays. for(i = 0, player = players; i < MAXPLAYERS; ++i, player++) { if(players[i].plr->inGame) { if(player->brain.attack) { if(!player->attackDown) accelerateStage = 1; player->attackDown = true; } else player->attackDown = false; if(player->brain.use) { if(!player->useDown) accelerateStage = 1; player->useDown = true; } else player->useDown = false; } } } /** * Updates stuff each tick. */ void WI_Ticker(void) { // Counter for general background animation. bcnt++; WI_checkForAccelerate(); switch(state) { case ILS_SHOW_STATS: if(deathmatch) WI_updateDeathmatchStats(); else if(IS_NETGAME) WI_updateNetgameStats(); else WI_updateStats(); break; case ILS_NONE: default: WI_updateNoState(); break; } } void WI_loadData(void) { int i; char name[9]; strcpy(name, "INTERPIC"); // Background. R_CachePatch(&bg, name); // More hacks on minus sign. R_CachePatch(&minus, "WIMINUS"); for(i = 0; i < 10; ++i) { // Numbers 0-9 sprintf(name, "WINUM%d", i); // num[i] = W_CacheLumpName(name, PU_STATIC); R_CachePatch(&num[i], name); } // Percent sign. R_CachePatch(&percent, "WIPCNT"); // "finished" R_CachePatch(&finished, "WIF"); // "entering" R_CachePatch(&entering, "WIENTER"); // "kills" R_CachePatch(&kills, "WIOSTK"); // "scrt" R_CachePatch(&secret, "WIOSTS"); // "secret" R_CachePatch(&sp_secret, "WISCRT2"); //items R_CachePatch(&items, "WIOSTI"); // "frgs" R_CachePatch(&frags, "WIFRGS"); // ":" R_CachePatch(&colon, "WICOLON"); // "time" R_CachePatch(&time, "WITIME"); // "sucks" R_CachePatch(&sucks, "WISUCKS"); // "par" R_CachePatch(&par, "WIPAR"); // "killers" (vertical) R_CachePatch(&killers, "WIKILRS"); // "victims" (horiz) R_CachePatch(&victims, "WIVCTMS"); // "total" R_CachePatch(&total, "WIMSTT"); // your face //R_CachePatch(&star, "STFST01"); // dead face //R_CachePatch(&bstar, "STFDEAD0"); for(i = 0; i < MAXPLAYERS; ++i) { // "1,2,3,4" sprintf(name, "STPB%d", i); R_CachePatch(&p[i], name); // "1,2,3,4" sprintf(name, "WIBP%d", i + 1); R_CachePatch(&bp[i], name); } } void WI_Drawer(void) { switch(state) { case ILS_SHOW_STATS: if(deathmatch) WI_drawDeathmatchStats(); else if(IS_NETGAME) WI_drawNetgameStats(); else WI_drawStats(); break; case ILS_NONE: default: WI_drawNoState(); break; } } void WI_initVariables(wbstartstruct_t *wbstartstruct) { wbs = wbstartstruct; #ifdef RANGECHECK if(gameMode != commercial) { if(gameMode == retail) RNGCHECK(wbs->episode, 0, 3); else RNGCHECK(wbs->episode, 0, 2); } else { RNGCHECK(wbs->currentMap, 0, 8); RNGCHECK(wbs->nextMap, 0, 8); } RNGCHECK(wbs->pnum, 0, MAXPLAYERS); RNGCHECK(wbs->pnum, 0, MAXPLAYERS); #endif accelerateStage = 0; cnt = bcnt = 0; me = wbs->pNum; myTeam = cfg.playerColor[wbs->pNum]; plrs = wbs->plyr; if(!wbs->maxKills) wbs->maxKills = 1; if(!wbs->maxItems) wbs->maxItems = 1; if(!wbs->maxSecret) wbs->maxSecret = 1; } void WI_Init(wbstartstruct_t* wbstartstruct) { int i, j, k; teaminfo_t* tin; WI_initVariables(wbstartstruct); WI_loadData(); // Calculate team stats. memset(teamInfo, 0, sizeof(teamInfo)); for(i = 0, tin = teamInfo; i < NUM_TEAMS; ++i, tin++) { for(j = 0; j < MAXPLAYERS; j++) { // Is the player in this team? if(!plrs[j].inGame || cfg.playerColor[j] != i) continue; tin->members++; // Check the frags. for(k = 0; k < MAXPLAYERS; ++k) tin->frags[cfg.playerColor[k]] += plrs[j].frags[k]; // Counters. if(plrs[j].items > tin->items) tin->items = plrs[j].items; if(plrs[j].kills > tin->kills) tin->kills = plrs[j].kills; if(plrs[j].secret > tin->secret) tin->secret = plrs[j].secret; } // Calculate team's total frags. for(j = 0; j < NUM_TEAMS; ++j) { if(j == i) // Suicides are negative frags. tin->totalFrags -= tin->frags[j]; else tin->totalFrags += tin->frags[j]; } } if(deathmatch) WI_initDeathmatchStats(); else if(IS_NETGAME) WI_initNetgameStats(); else WI_initStats(); } void WI_SetState(interludestate_t st) { if(st == ILS_SHOW_STATS) WI_initStats(); if(st == ILS_NONE) WI_initNoState(); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_lights.c0000644000175000017500000002463011357170242022601 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.c: Handle Sector base lighting effects. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_mapspec.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void T_FireFlicker(fireflicker_t *flick) { float lightLevel; float amount; if(--flick->count) return; amount = ((P_Random() & 3) * 16) / 255.0f; lightLevel = P_GetFloatp(flick->sector, DMU_LIGHT_LEVEL); if(lightLevel - amount < flick->minLight) P_SetFloatp(flick->sector, DMU_LIGHT_LEVEL, flick->minLight); else P_SetFloatp(flick->sector, DMU_LIGHT_LEVEL, flick->maxLight - amount); flick->count = 4; } void P_SpawnFireFlicker(sector_t *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; fireflicker_t *flick; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. //P_ToXSector(sector)->special = 0; // jd64 flick = Z_Calloc(sizeof(*flick), PU_MAP, 0); flick->thinker.function = T_FireFlicker; DD_ThinkerAdd(&flick->thinker); flick->sector = sector; flick->count = 4; flick->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flick->minLight = otherLevel; else flick->minLight = lightLevel; flick->minLight += (16.0f/255.0f); } /** * Broken light flashing. */ void T_LightFlash(lightflash_t *flash) { float lightLevel; if(--flash->count) return; lightLevel = P_GetFloatp(flash->sector, DMU_LIGHT_LEVEL); if(lightLevel == flash->maxLight) { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->minLight); flash->count = (P_Random() & flash->minTime) + 1; } else { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->maxLight); flash->count = (P_Random() & flash->maxTime) + 1; } } /** * After the map has been loaded, scan each sector for specials that spawn * thinkers. */ void P_SpawnLightFlash(sector_t *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; lightflash_t *flash; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. //P_ToXSector(sector)->special = 0; // jd64 flash = Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = T_LightFlash; DD_ThinkerAdd(&flash->thinker); flash->sector = sector; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; flash->maxTime = 64; flash->minTime = 7; flash->count = (P_Random() & flash->maxTime) + 1; } /** * d64tc */ void T_LightBlink(lightblink_t *flash) { float lightlevel = P_GetFloatp(flash->sector, DMU_LIGHT_LEVEL); if(--flash->count) return; if(lightlevel == flash->maxLight) { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->minLight); flash->count = flash->minTime; } else { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->maxLight); flash->count = flash->maxTime; } } /** * d64tc */ void P_SpawnLightBlink(sector_t *sector) { lightblink_t *blink; blink = Z_Calloc(sizeof(*blink), PU_MAP, 0); blink->thinker.function = T_LightBlink; DD_ThinkerAdd(&blink->thinker); blink->sector = sector; blink->maxLight = P_GetFloatp(sector, DMU_LIGHT_LEVEL); blink->minLight = 0; blink->maxTime = blink->minTime = blink->count = 4; } /** * Strobe light flashing. */ void T_StrobeFlash(strobe_t *flash) { float lightLevel; if(--flash->count) return; lightLevel = P_GetFloatp(flash->sector, DMU_LIGHT_LEVEL); if(lightLevel == flash->minLight) { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->maxLight); flash->count = flash->brightTime; } else { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->minLight); flash->count = flash->darkTime; } } /** * After the map has been loaded, scan each sector for specials that spawn * thinkers. */ void P_SpawnStrobeFlash(sector_t *sector, int fastOrSlow, int inSync) { strobe_t *flash; float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; flash = Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = T_StrobeFlash; DD_ThinkerAdd(&flash->thinker); flash->sector = sector; flash->darkTime = fastOrSlow; flash->brightTime = STROBEBRIGHT; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; if(flash->minLight == flash->maxLight) flash->minLight = 0; // nothing special about it during gameplay P_ToXSector(sector)->special = 0; if(!inSync) flash->count = (P_Random() & 7) + 1; else flash->count = 1; } /* * Start strobing lights (usually from a trigger) */ void EV_StartLightStrobing(linedef_t *line) { sector_t *sec = NULL; iterlist_t *list; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(P_ToXSector(sec)->specialData) continue; P_SpawnStrobeFlash(sec, SLOWDARK, 0); } } void EV_TurnTagLightsOff(linedef_t *line) { sector_t *sec = NULL; iterlist_t *list; float lightLevel; float otherLevel; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { lightLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); otherLevel = DDMAXFLOAT; P_FindSectorSurroundingLowestLight(sec, &otherLevel); if(otherLevel < lightLevel) lightLevel = otherLevel; P_SetFloatp(sec, DMU_LIGHT_LEVEL, lightLevel); } } void EV_LightTurnOn(linedef_t *line, float max) { sector_t *sec = NULL; iterlist_t *list; float lightLevel, otherLevel; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; if(max != 0) lightLevel = max; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { // If Max = 0 means to search for the highest light level in the // surrounding sector. if(max == 0) { lightLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); otherLevel = DDMINFLOAT; P_FindSectorSurroundingHighestLight(sec, &otherLevel); if(otherLevel > lightLevel) lightLevel = otherLevel; } P_SetFloatp(sec, DMU_LIGHT_LEVEL, lightLevel); } } void T_Glow(glow_t *g) { float lightLevel = P_GetFloatp(g->sector, DMU_LIGHT_LEVEL); float glowDelta = (1.0f / 255.0f) * (float) GLOWSPEED; switch(g->direction) { case -1: // Down. lightLevel -= glowDelta; if(lightLevel <= g->minLight) { lightLevel += glowDelta; g->direction = 1; } break; case 1: // Up. lightLevel += glowDelta; if(lightLevel >= g->maxLight) { lightLevel -= glowDelta; g->direction = -1; } break; } P_SetFloatp(g->sector, DMU_LIGHT_LEVEL, lightLevel); } void P_SpawnGlowingLight(sector_t* sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; glow_t* g; g = Z_Calloc(sizeof(*g), PU_MAP, 0); g->thinker.function = T_Glow; DD_ThinkerAdd(&g->thinker); g->sector = sector; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) g->minLight = otherLevel; else g->minLight = lightLevel; g->maxLight = lightLevel; g->direction = -1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/acfnlink.c0000644000175000017500000001347111357170242022556 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- actionlink_t actionlinks[] = { {"A_BabyMetal", A_BabyMetal}, {"A_BFGsound", A_BFGsound}, {"A_BFGSpray", A_BFGSpray}, {"A_BossDeath", A_BossDeath}, {"A_BruisAttack", A_BruisAttack}, {"A_BspiAttack", A_BspiAttack}, {"A_Chase", A_Chase}, {"A_Chase", A_RectChase}, //jd64 {"A_CheckReload", A_CheckReload}, {"A_CyberAttack", A_CyberAttack}, {"A_Explode", A_Explode}, {"A_BarrelExplode", A_BarrelExplode}, //jd64 {"A_FaceTarget", A_FaceTarget}, {"A_BspiFaceTarget", A_BspiFaceTarget}, //jd64 {"A_Fall", A_Fall}, {"A_FatAttack1", A_FatAttack1}, {"A_FatAttack2", A_FatAttack2}, {"A_FatAttack3", A_FatAttack3}, {"A_FatRaise", A_FatRaise}, {"A_FireBFG", A_FireBFG}, {"A_FireCGun", A_FireCGun}, {"A_FireMissile", A_FireMissile}, {"A_FirePistol", A_FirePistol}, {"A_FirePlasma", A_FirePlasma}, {"A_Lasersmoke", A_Lasersmoke}, //jd64 {"A_FireSingleLaser", A_FireSingleLaser}, //jd64 {"A_FireDoubleLaser", A_FireDoubleLaser}, //jd64 {"A_FireDoubleLaser1", A_FireDoubleLaser1}, //jd64 {"A_FireDoubleLaser2", A_FireDoubleLaser2}, //jd64 {"A_FireShotgun", A_FireShotgun}, {"A_FireShotgun2", A_FireShotgun2}, {"A_GunFlash", A_GunFlash}, {"A_HeadAttack", A_HeadAttack}, {"A_Hoof", A_Hoof}, {"A_PossSpecial", A_PossSpecial}, //jd64 {"A_SposSpecial", A_SposSpecial}, //jd64 {"A_TrooSpecial", A_TrooSpecial}, //jd64 {"A_SargSpecial", A_SargSpecial}, //jd64 {"A_HeadSpecial", A_HeadSpecial}, //jd64 {"A_SkulSpecial", A_SkulSpecial}, //jd64 {"A_Bos2Special", A_Bos2Special}, //jd64 {"A_BossSpecial", A_BossSpecial}, //jd64 {"A_PainSpecial", A_PainSpecial}, //jd64 {"A_FattSpecial", A_FattSpecial}, //jd64 {"A_BabySpecial", A_BabySpecial}, //jd64 {"A_CybrSpecial", A_CybrSpecial}, //jd64 {"A_RectSpecial", A_RectSpecial}, //jd64 {"A_Light0", A_Light0}, {"A_Light1", A_Light1}, {"A_Light2", A_Light2}, {"A_LoadShotgun2", A_LoadShotgun2}, {"A_Look", A_Look}, {"A_Lower", A_Lower}, {"A_Metal", A_Metal}, {"A_OpenShotgun2", A_OpenShotgun2}, {"A_Pain", A_Pain}, {"A_PainAttack", A_PainAttack}, {"A_PainDie", A_PainDie}, {"A_Rocketpuff", A_Rocketpuff}, //jd64 {"A_PosAttack", A_PosAttack}, {"A_Punch", A_Punch}, {"A_Raise", A_Raise}, {"A_PlasmaShock", A_PlasmaShock}, {"A_ReFire", A_ReFire}, {"A_SargAttack", A_SargAttack}, {"A_Saw", A_Saw}, {"A_Scream", A_Scream}, {"A_CyberDeath", A_CyberDeath}, //jd64 {"A_SkelFist", A_SkelFist}, {"A_SkelMissile", A_SkelMissile}, {"A_SkelWhoosh", A_SkelWhoosh}, {"A_SkullAttack", A_SkullAttack}, {"A_SpidRefire", A_SpidRefire}, {"A_SPosAttack", A_SPosAttack}, {"A_Tracer", A_Tracer}, {"A_TroopAttack", A_TroopAttack}, {"A_TroopClaw", A_TroopClaw}, //jd64 {"A_MotherFloorFire", A_MotherFloorFire}, //jd64 {"A_MotherMissle", A_MotherMissle}, //jd64 {"A_SetFloorFire", A_SetFloorFire}, //jd64 {"A_MotherBallExplode", A_MotherBallExplode}, //jd64 {"A_RectTracerPuff", A_RectTracerPuff}, //jd64 {"A_WeaponReady", A_WeaponReady}, {"A_XScream", A_XScream}, {"A_TargetCamera", A_TargetCamera}, //jd64 {"A_ShadowsAction1", A_ShadowsAction1}, //jd64 {"A_ShadowsAction2", A_ShadowsAction2}, //jd64 {"A_EMarineAttack2", A_EMarineAttack2}, //jd64 {0, 0} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_setup.c0000644000175000017500000001526411357170242022452 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2002-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.c: Handle jDoom64 specific map data properties. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" #include "am_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Called during pre-init. * Register the map object data types we want to Doomsday to make public via * it's MPE interface. */ void P_RegisterMapObjs(void) { P_RegisterMapObj(MO_THING, "Thing"); P_RegisterMapObjProperty(MO_THING, MO_X, "X", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Y, "Y", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Z, "Z", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_ID, "ID", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_ANGLE, "Angle", DDVT_ANGLE); P_RegisterMapObjProperty(MO_THING, MO_DOOMEDNUM, "DoomEdNum", DDVT_INT); P_RegisterMapObjProperty(MO_THING, MO_FLAGS, "Flags", DDVT_INT); P_RegisterMapObj(MO_XLINEDEF, "XLinedef"); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TAG, "Tag", DDVT_SHORT); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TYPE, "Type", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_USETYPE, "UseType", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_FLAGS, "Flags", DDVT_SHORT); P_RegisterMapObjProperty(MO_XLINEDEF, MO_DRAWFLAGS, "DrawFlags", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TEXFLAGS, "TexFlags", DDVT_BYTE); P_RegisterMapObj(MO_XSECTOR, "XSector"); P_RegisterMapObjProperty(MO_XSECTOR, MO_TAG, "Tag", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_TYPE, "Type", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_FLAGS, "Flags", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_FLOORCOLOR, "FloorColor", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_CEILINGCOLOR, "CeilingColor", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_UNKNOWNCOLOR, "UnknownColor", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_WALLTOPCOLOR, "WallTopColor", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_WALLBOTTOMCOLOR, "WallBottomColor", DDVT_SHORT); P_RegisterMapObj(MO_LIGHT, "Light"); P_RegisterMapObjProperty(MO_LIGHT, MO_COLORR, "ColorR", DDVT_FLOAT); P_RegisterMapObjProperty(MO_LIGHT, MO_COLORG, "ColorG", DDVT_FLOAT); P_RegisterMapObjProperty(MO_LIGHT, MO_COLORB, "ColorB", DDVT_FLOAT); P_RegisterMapObjProperty(MO_LIGHT, MO_XX0, "XX0", DDVT_BYTE); P_RegisterMapObjProperty(MO_LIGHT, MO_XX1, "XX1", DDVT_BYTE); P_RegisterMapObjProperty(MO_LIGHT, MO_XX2, "XX2", DDVT_BYTE); } /** * \todo This is actually unnecessary. If we say that in the case of BOOM * overloaded texture names, rather than setting the surface material as * normal, the map converter should instead write to a property in XLinedef * which the game can then look up later. * * Doomsday will call this when loading the map data if it encounters a * value that it doesn't understand for a property IT handles. * * Doomsday thinks we might know what to do with it... * If we don't know what to do we'll return -1. * * @param id Index of the current element being read. * @param dtype DMU type identifier. * @param prop DMU property identifier. * @param type Data type id of the value pointed to by *data. * @param *data Ptr to the data value (has already been expanded, * size converted and endian converted where necessary). */ int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void *data) { switch(dtype) { case DMU_SURFACE: switch(prop) { case DMU_MATERIAL: /** * It could be a BOOM overloaded texture name? * In this context Doomsday expects either -1 (a bad texture name) * Or the id of a wall texture it should set to this section. * \todo Add code to determine what to do. */ break; default: break; } break; default: break; } return -1; // We ain't got a clue what to do with it... } /** * These status reports inform us of what Doomsday is doing to a particular * map data object (at any time) that we might want to react to. * * If we arn't interested in the report - we should simply return true and * take no further action. * * @param code ID code of the status report (enum in dd_share.h) * @param id Map data object id. * @param type Map data object type eg DMU_SECTOR. * @param data Any relevant data for this report (currently unused). */ int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void *data) { switch(code) { case DMUSC_LINE_FIRSTRENDERED: /** * Called the first time the given line is rendered. * *data is a pointer to int, giving the player id which has seen it. * We'll utilize this to mark it as being visible in the automap. */ AM_UpdateLinedef(AM_MapForPlayer(*(int *) data), id, true); break; default: break; } return 1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/d_refresh.c0000644000175000017500000003446611357170242022741 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_refresh.c: - jDoom64 specific */ // HEADER FILES ------------------------------------------------------------ #include #include "jdoom64.h" #include "hu_stuff.h" #include "hu_menu.h" #include "hu_pspr.h" #include "hu_msg.h" #include "am_map.h" #include "g_common.h" #include "r_common.h" #include "d_net.h" #include "f_infine.h" #include "x_hair.h" #include "g_controls.h" #include "p_mapsetup.h" #include "p_tick.h" #include "p_actor.h" #include "rend_automap.h" // MACROS ------------------------------------------------------------------ #define WINDOWHEIGHT (Get(DD_VIEWWINDOW_HEIGHT)) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void R_SetAllDoomsdayFlags(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float quitDarkenOpacity = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Draws a special filter over the screen (eg the inversing filter used * when in god mode). */ void R_DrawSpecialFilter(int pnum) { player_t* player = &players[pnum]; if(player->powers[PT_INVULNERABILITY]) { float x, y, w, h; float max = 30; float str, r, g, b; int t = player->powers[PT_INVULNERABILITY]; if(t < max) str = t / max; else if(t < 4 * 32 && !(t & 8)) str = .7f; else if(t > INVULNTICS - max) str = (INVULNTICS - t) / max; else str = 1; // Full inversion. // Draw an inversing filter. DGL_Disable(DGL_TEXTURING); DGL_BlendMode(BM_INVERSE); r = MINMAX_OF(0.f, str * 2, 1.f); g = MINMAX_OF(0.f, str * 2 - .4, 1.f); b = MINMAX_OF(0.f, str * 2 - .8, 1.f); R_GetViewWindow(&x, &y, &w, &h); DGL_DrawRect(x, y, w, h, r, g, b, 1); // Restore the normal rendering state. DGL_BlendMode(BM_NORMAL); DGL_Enable(DGL_TEXTURING); } } boolean R_GetFilterColor(float rgba[4], int filter) { if(!rgba) return false; // We have to choose the right color and alpha. if(filter >= STARTREDPALS && filter < STARTREDPALS + NUMREDPALS) { // Red. rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; rgba[CA] = (deathmatch? 1.0f : cfg.filterStrength) * filter / 9.f; return true; } if(filter >= STARTBONUSPALS && filter < STARTBONUSPALS + NUMBONUSPALS) { // Gold. rgba[CR] = 1; rgba[CG] = .8f; rgba[CB] = .5f; rgba[CA] = cfg.filterStrength * (filter - STARTBONUSPALS + 1) / 16.f; return true; } if(filter == 13) // RADIATIONPAL { // Green. rgba[CR] = 0; rgba[CG] = .7f; rgba[CB] = 0; rgba[CA] = cfg.filterStrength * .25f; return true; } if(filter) Con_Message("R_GetFilterColor: Real strange filter number: %d.\n", filter); return false; } /** * Show map name and author. */ void R_DrawMapTitle(void) { float alpha; int y = 12, mapnum; const char* lname, *lauthor; if(!cfg.mapTitle || actualMapTime > 6 * 35) return; // Make the text a bit smaller. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(160, y, 0); DGL_Scalef(.7f, .7f, 1); DGL_Translatef(-160, -y, 0); alpha = 1; if(actualMapTime < 35) alpha = actualMapTime / 35.0f; if(actualMapTime > 5 * 35) alpha = 1 - (actualMapTime - 5 * 35) / 35.0f; // Get the strings from Doomsday. lname = P_GetMapNiceName(); lauthor = P_GetMapAuthor(cfg.hideIWADAuthor); // Compose the mapnumber used to check the map name patches array. mapnum = gameMap; WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, alpha, &mapNamePatches[mapnum], lname, false, ALIGN_CENTER); y += 14; if(lauthor) { M_WriteText3(160 - M_StringWidth(lauthor, GF_FONTA) / 2, y, lauthor, GF_FONTA, .5f, .5f, .5f, alpha, false, true, 0); } DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } /** * Do not really change anything here, because Doomsday might be in the * middle of a refresh. The change will take effect next refresh. */ void R_SetViewSize(int blocks) { cfg.setSizeNeeded = true; if(cfg.setBlocks > 8) { int i; // When going fullscreen, force a hud show event (to reset the timer). for(i = 0; i < MAXPLAYERS; ++i) { ST_HUDUnHide(i, HUE_FORCE); } } cfg.setBlocks = blocks; } static void rendPlayerView(int player) { player_t* plr = &players[player]; float viewPos[3], viewPitch, pspriteOffsetY; angle_t viewAngle; int isFullBright = ((plr->powers[PT_INFRARED] > 4 * 32) || (plr->powers[PT_INFRARED] & 8) || plr->powers[PT_INVULNERABILITY] > 30); if(IS_CLIENT) { // Server updates mobj flags in NetSv_Ticker. R_SetAllDoomsdayFlags(); } viewPos[VX] = plr->plr->mo->pos[VX] + plr->viewOffset[VX]; viewPos[VY] = plr->plr->mo->pos[VY] + plr->viewOffset[VY]; viewPos[VZ] = plr->viewZ + plr->viewOffset[VZ]; viewAngle = plr->plr->mo->angle + (int) (ANGLE_MAX * -G_GetLookOffset(player)); viewPitch = plr->plr->lookDir; DD_SetVariable(DD_VIEW_X, &viewPos[VX]); DD_SetVariable(DD_VIEW_Y, &viewPos[VY]); DD_SetVariable(DD_VIEW_Z, &viewPos[VZ]); DD_SetVariable(DD_VIEW_ANGLE, &viewAngle); DD_SetVariable(DD_VIEW_PITCH, &viewPitch); pspriteOffsetY = HU_PSpriteYOffset(plr); DD_SetVariable(DD_PSPRITE_OFFSET_Y, &pspriteOffsetY); // $democam GL_SetFilter((plr->plr->flags & DDPF_VIEW_FILTER)? true : false); if(plr->plr->flags & DDPF_VIEW_FILTER) { const float* color = plr->plr->filterColor; GL_SetFilterColor(color[CR], color[CG], color[CB], color[CA]); } // How about fullbright? DD_SetInteger(DD_FULLBRIGHT, isFullBright); // Render the view with possible custom filters. R_RenderPlayerView(player); } static void rendHUD(int player) { player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; if(G_GetGameState() != GS_MAP) return; if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; plr = &players[player]; // These various HUD's will be drawn unless Doomsday advises not to if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { automapid_t map = AM_MapForPlayer(player); // Draw HUD displays only visible when the automap is open. if(AM_IsActive(map)) HU_DrawMapCounters(); // Do we need to render a full status bar at this point? if(!(AM_IsActive(map) && cfg.automapHudDisplay == 0) && !(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { if(true == (WINDOWHEIGHT == 200)) { // Fullscreen. Which mode? ST_Drawer(player, cfg.setBlocks - 8); } else { ST_Drawer(player, 0); } } HU_Drawer(player); } } /** * Draws the in-viewport display. * * @param layer @c 0 = bottom layer (before the viewport border). * @c 1 = top layer (after the viewport border). */ void D_Display(int layer) { int player = DISPLAYPLAYER; player_t* plr = &players[player]; float x, y, w, h; if(layer != 0) { rendHUD(player); return; } if(G_GetGameState() == GS_MAP) { // $democam: can be set on every frame. if(cfg.setBlocks > 10 || (P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { // Full screen. R_SetViewWindowTarget(0, 0, SCREENWIDTH, SCREENHEIGHT); } else { int w = cfg.setBlocks * 32; int h = cfg.setBlocks * 20; R_SetViewWindowTarget(SCREENWIDTH/2 - w/2, SCREENHEIGHT/2 - h/2, w, h); } R_GetViewWindow(&x, &y, &w, &h); } else { x = 0; y = 0; w = SCREENWIDTH; h = SCREENHEIGHT; } R_SetViewWindow((int) x, (int) y, (int) w, (int) h); switch(G_GetGameState()) { case GS_MAP: if(!(MN_CurrentMenuHasBackground() && Hu_MenuAlpha() >= 1) && !R_MapObscures(player, (int) x, (int) y, (int) w, (int) h)) { if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; rendPlayerView(player); R_DrawSpecialFilter(player); // Crosshair. if(!(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) // $democam X_Drawer(player); } // Draw the automap? AM_Drawer(player); break; case GS_STARTUP: DGL_Disable(DGL_TEXTURING); DGL_DrawRect(x, y, w, h, 0, 0, 0, 1); DGL_Enable(DGL_TEXTURING); break; default: break; } } void D_Display2(void) { switch(G_GetGameState()) { case GS_MAP: if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) break; // These various HUD's will be drawn unless Doomsday advises not to. if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { // Level information is shown for a few seconds in the // beginning of a level. R_DrawMapTitle(); } break; case GS_INTERMISSION: WI_Drawer(); break; case GS_WAITING: //gl.Clear(DGL_COLOR_BUFFER_BIT); //M_WriteText2(5, 188, "WAITING... PRESS ESC FOR MENU", GF_FONTA, 1, 0, 0, 1); break; default: break; } // Draw pause pic (but not if InFine active). if(paused && !fiActive) { WI_DrawPatch(SCREENWIDTH /2, 4, 1, 1, 1, 1, &m_pause, NULL, false, ALIGN_CENTER); } // InFine is drawn whenever active. FI_Drawer(); // Draw HUD displays; menu, messages. Hu_Drawer(); if(G_GetGameAction() == GA_QUIT) { DGL_Disable(DGL_TEXTURING); DGL_DrawRect(0, 0, 320, 200, 0, 0, 0, quitDarkenOpacity); DGL_Enable(DGL_TEXTURING); } } /** * Updates the mobj flags used by Doomsday with the state of our local flags * for the given mobj. */ void P_SetDoomsdayFlags(mobj_t* mo) { // Client mobjs can't be set here. if(IS_CLIENT && mo->ddFlags & DDMF_REMOTE) return; // Reset the flags for a new frame. mo->ddFlags &= DDMF_CLEAR_MASK; // Local objects aren't sent to clients. if(mo->flags & MF_LOCAL) mo->ddFlags |= DDMF_LOCAL; if(mo->flags & MF_SOLID) mo->ddFlags |= DDMF_SOLID; if(mo->flags & MF_NOGRAVITY) mo->ddFlags |= DDMF_NOGRAVITY; if(mo->flags2 & MF2_FLOATBOB) mo->ddFlags |= DDMF_NOGRAVITY | DDMF_BOB; if(mo->flags & MF_MISSILE) mo->ddFlags |= DDMF_MISSILE; if(mo->type == MT_LIGHTSOURCE) mo->ddFlags |= DDMF_ALWAYSLIT | DDMF_DONTDRAW; if(mo->info && mo->info->flags2 & MF2_ALWAYSLIT) mo->ddFlags |= DDMF_ALWAYSLIT; if(mo->flags2 & MF2_FLY) mo->ddFlags |= DDMF_FLY | DDMF_NOGRAVITY; // $democam: cameramen are invisible if(P_MobjIsCamera(mo)) mo->ddFlags |= DDMF_DONTDRAW; if((mo->flags & MF_CORPSE) && cfg.corpseTime && mo->corpseTics == -1) mo->ddFlags |= DDMF_DONTDRAW; // Choose which ddflags to set. if(mo->flags2 & MF2_DONTDRAW) { mo->ddFlags |= DDMF_DONTDRAW; return; // No point in checking the other flags. } if(mo->flags2 & MF2_LOGRAV) mo->ddFlags |= DDMF_LOWGRAVITY; // The torches often go into the ceiling. This'll prevent // them from 'jumping'. if(mo->type == MT_MISC41 || mo->type == MT_MISC42 || mo->type == MT_MISC43 || // tall torches mo->type == MT_MISC44 || mo->type == MT_MISC45 || mo->type == MT_MISC46) // short torches mo->ddFlags |= DDMF_NOFITBOTTOM; if(mo->flags & MF_BRIGHTSHADOW) mo->ddFlags |= DDMF_BRIGHTSHADOW; else if(mo->flags & MF_SHADOW) mo->ddFlags |= DDMF_SHADOW; if(((mo->flags & MF_VIEWALIGN) && !(mo->flags & MF_MISSILE)) || (mo->flags & MF_FLOAT) || ((mo->flags & MF_MISSILE) && !(mo->flags & MF_VIEWALIGN))) mo->ddFlags |= DDMF_VIEWALIGN; if(mo->flags & MF_TRANSLATION) mo->tmap = (mo->flags & MF_TRANSLATION) >> MF_TRANSSHIFT; } /** * Updates the status flags for all visible things. */ void R_SetAllDoomsdayFlags(void) { int i; int count = DD_GetInteger(DD_SECTOR_COUNT); mobj_t* iter; // Only visible things are in the sector thinglists, so this is good. for(i = 0; i < count; ++i) { for(iter = P_GetPtr(DMU_SECTOR, i, DMT_MOBJS); iter; iter = iter->sNext) P_SetDoomsdayFlags(iter); } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/d_console.c0000644000175000017500000002706311357170242022740 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_console.c: jDoom64 specific console stuff */ // HEADER FILES ------------------------------------------------------------ #include #include "jdoom64.h" #include "hu_stuff.h" #include "f_infine.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- DEFCC(CCmdCheatGod); DEFCC(CCmdCheatNoClip); DEFCC(CCmdCheatWarp); DEFCC(CCmdCheatReveal); DEFCC(CCmdCheatGive); DEFCC(CCmdCheatMassacre); DEFCC(CCmdCheatWhere); DEFCC(CCmdCheatLeaveMap); DEFCC(CCmdCheatSuicide); DEFCC(CCmdMakeLocal); DEFCC(CCmdSetCamera); DEFCC(CCmdSetViewLock); DEFCC(CCmdSetViewMode); DEFCC(CCmdCycleSpy); DEFCC(CCmdPlayDemo); DEFCC(CCmdRecordDemo); DEFCC(CCmdStopDemo); DEFCC(CCmdSpawnMobj); DEFCC(CCmdPrintPlayerCoords); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdScreenShot); DEFCC(CCmdViewSize); DEFCC(CCmdDoom64Font); DEFCC(CCmdConBackground); void G_UpdateEyeHeight(cvar_t* unused); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- material_t* consoleBG = NULL; float consoleZoom = 1; // Console variables. cvar_t gameCVars[] = { // Console {"con-zoom", 0, CVT_FLOAT, &consoleZoom, 0.1f, 100.0f}, // View/Refresh {"view-size", CVF_PROTECTED, CVT_INT, &cfg.screenBlocks, 3, 11}, {"hud-title", 0, CVT_BYTE, &cfg.mapTitle, 0, 1}, {"hud-title-author-noiwad", 0, CVT_BYTE, &cfg.hideIWADAuthor, 0, 1}, {"view-bob-height", 0, CVT_FLOAT, &cfg.bobView, 0, 1}, {"view-bob-weapon", 0, CVT_FLOAT, &cfg.bobWeapon, 0, 1}, {"view-bob-weapon-switch-lower", 0, CVT_BYTE, &cfg.bobWeaponLower, 0, 1}, {"view-filter-strength", 0, CVT_FLOAT, &cfg.filterStrength, 0, 1}, // Server-side options // Game state {"server-game-skill", 0, CVT_BYTE, &cfg.netSkill, 0, 4}, {"server-game-map", CVF_NO_MAX, CVT_BYTE, &cfg.netMap, 0, 0}, {"server-game-deathmatch", 0, CVT_BYTE, &cfg.netDeathmatch, 0, 2}, // Modifiers {"server-game-mod-damage", 0, CVT_BYTE, &cfg.netMobDamageModifier, 1, 100}, {"server-game-mod-health", 0, CVT_BYTE, &cfg.netMobHealthModifier, 1, 20}, {"server-game-mod-gravity", 0, CVT_INT, &cfg.netGravity, -1, 100}, // Items {"server-game-nobfg", 0, CVT_BYTE, &cfg.noNetBFG, 0, 1}, {"server-game-coop-nothing", 0, CVT_BYTE, &cfg.noCoopAnything, 0, 1}, {"server-game-coop-respawn-items", 0, CVT_BYTE, &cfg.coopRespawnItems, 0, 1}, {"server-game-coop-noweapons", 0, CVT_BYTE, &cfg.noCoopWeapons, 0, 1}, // Gameplay options {"server-game-jump", 0, CVT_BYTE, &cfg.netJumping, 0, 1}, {"server-game-bfg-freeaim", 0, CVT_BYTE, &cfg.netBFGFreeLook, 0, 1}, {"server-game-nomonsters", 0, CVT_BYTE, &cfg.netNoMonsters, 0, 1 }, {"server-game-respawn", 0, CVT_BYTE, &cfg.netRespawn, 0, 1}, {"server-game-radiusattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZRadiusAttack, 0, 1}, {"server-game-monster-meleeattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZMonsterMeleeAttack, 0, 1}, {"server-game-coop-nodamage", 0, CVT_BYTE, &cfg.noCoopDamage, 0, 1}, {"server-game-noteamdamage", 0, CVT_BYTE, &cfg.noTeamDamage, 0, 1}, // Misc {"server-game-deathmatch-killmsg", 0, CVT_BYTE, &cfg.killMessages, 0, 1}, {"server-game-announce-secret", 0, CVT_BYTE, &cfg.secretMsg, 0, 1}, // Player // Player data {"player-color", 0, CVT_BYTE, &cfg.netColor, 0, 3}, {"player-eyeheight", 0, CVT_INT, &cfg.plrViewHeight, 41, 54, G_UpdateEyeHeight}, // Movment {"player-move-speed", 0, CVT_FLOAT, &cfg.playerMoveSpeed, 0, 1}, {"player-jump", 0, CVT_INT, &cfg.jumpEnabled, 0, 1}, {"player-jump-power", 0, CVT_FLOAT, &cfg.jumpPower, 0, 100}, {"player-air-movement", 0, CVT_BYTE, &cfg.airborneMovement, 0, 32}, {"player-weapon-recoil", 0, CVT_BYTE, &cfg.weaponRecoil, 0, 1}, // Weapon switch preferences {"player-autoswitch", 0, CVT_BYTE, &cfg.weaponAutoSwitch, 0, 2}, {"player-autoswitch-ammo", 0, CVT_BYTE, &cfg.ammoAutoSwitch, 0, 2}, {"player-autoswitch-berserk", 0, CVT_BYTE, &cfg.berserkAutoSwitch, 0, 1}, {"player-autoswitch-notfiring", 0, CVT_BYTE, &cfg.noWeaponAutoSwitchIfFiring, 0, 1}, // Weapon Order preferences {"player-weapon-order0", 0, CVT_INT, &cfg.weaponOrder[0], 0, NUM_WEAPON_TYPES}, {"player-weapon-order1", 0, CVT_INT, &cfg.weaponOrder[1], 0, NUM_WEAPON_TYPES}, {"player-weapon-order2", 0, CVT_INT, &cfg.weaponOrder[2], 0, NUM_WEAPON_TYPES}, {"player-weapon-order3", 0, CVT_INT, &cfg.weaponOrder[3], 0, NUM_WEAPON_TYPES}, {"player-weapon-order4", 0, CVT_INT, &cfg.weaponOrder[4], 0, NUM_WEAPON_TYPES}, {"player-weapon-order5", 0, CVT_INT, &cfg.weaponOrder[5], 0, NUM_WEAPON_TYPES}, {"player-weapon-order6", 0, CVT_INT, &cfg.weaponOrder[6], 0, NUM_WEAPON_TYPES}, {"player-weapon-order7", 0, CVT_INT, &cfg.weaponOrder[7], 0, NUM_WEAPON_TYPES}, {"player-weapon-order8", 0, CVT_INT, &cfg.weaponOrder[8], 0, NUM_WEAPON_TYPES}, {"player-weapon-order9", 0, CVT_INT, &cfg.weaponOrder[9], 0, NUM_WEAPON_TYPES}, {"player-weapon-nextmode", 0, CVT_BYTE, &cfg.weaponNextMode, 0, 1}, // Misc {"player-camera-noclip", 0, CVT_INT, &cfg.cameraNoClip, 0, 1}, {"player-death-lookup", 0, CVT_BYTE, &cfg.deathLookUp, 0, 1}, // Compatibility options {"game-maxskulls", 0, CVT_BYTE, &cfg.maxSkulls, 0, 1}, {"game-skullsinwalls", 0, CVT_BYTE, &cfg.allowSkullsInWalls, 0, 1}, {"game-anybossdeath666", 0, CVT_BYTE, &cfg.anyBossDeath, 0, 1}, {"game-monsters-stuckindoors", 0, CVT_BYTE, &cfg.monstersStuckInDoors, 0, 1}, {"game-objects-neverhangoverledges", 0, CVT_BYTE, &cfg.avoidDropoffs, 0, 1}, {"game-objects-clipping", 0, CVT_BYTE, &cfg.moveBlock, 0, 1}, {"game-zombiescanexit", 0, CVT_BYTE, &cfg.zombiesCanExit, 0, 1}, {"game-player-wallrun-northonly", 0, CVT_BYTE, &cfg.wallRunNorthOnly, 0, 1}, {"game-objects-falloff", 0, CVT_BYTE, &cfg.fallOff, 0, 1}, {"game-zclip", 0, CVT_BYTE, &cfg.moveCheckZ, 0, 1}, {"game-corpse-sliding", 0, CVT_BYTE, &cfg.slidingCorpses, 0, 1}, // Game state {"game-fastmonsters", 0, CVT_BYTE, &fastParm, 0, 1}, // Gameplay {"game-corpse-time", CVF_NO_MAX, CVT_INT, &cfg.corpseTime, 0, 0}, // Misc {"msg-echo", 0, CVT_BYTE, &cfg.echoMsg, 0, 1}, {NULL} }; // Console commands ccmd_t gameCCmds[] = { {"spy", "", CCmdCycleSpy}, {"screenshot", "", CCmdScreenShot}, {"viewsize", "s", CCmdViewSize}, // $cheats {"god", NULL, CCmdCheatGod}, {"noclip", NULL, CCmdCheatNoClip}, {"warp", "i", CCmdCheatWarp}, {"reveal", "i", CCmdCheatReveal}, {"give", NULL, CCmdCheatGive}, {"kill", "", CCmdCheatMassacre}, {"leavemap", "", CCmdCheatLeaveMap}, {"suicide", NULL, CCmdCheatSuicide}, {"where", "", CCmdCheatWhere}, {"doom64font", "", CCmdDoom64Font}, {"conbg", "s", CCmdConBackground}, // $infine {"startinf", "s", CCmdStartInFine}, {"stopinf", "", CCmdStopInFine}, {"stopfinale", "", CCmdStopInFine}, {"spawnmobj", NULL, CCmdSpawnMobj}, {"coord", "", CCmdPrintPlayerCoords}, // $democam {"makelocp", "i", CCmdMakeLocal}, {"makecam", "i", CCmdSetCamera}, {"setlock", NULL, CCmdSetViewLock}, {"lockmode", "i", CCmdSetViewLock}, {"viewmode", NULL, CCmdSetViewMode}, {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Add the console variables and commands. */ void G_ConsoleRegistration(void) { uint i; for(i = 0; gameCVars[i].name; ++i) Con_AddVariable(&gameCVars[i]); for(i = 0; gameCCmds[i].name; ++i) Con_AddCommand(&gameCCmds[i]); } /** * Settings for console background drawing. * Called EVERY FRAME by the console drawer. */ void D_ConsoleBg(int *width, int *height) { if(consoleBG) { DGL_SetMaterial(consoleBG); *width = (int) (64 * consoleZoom); *height = (int) (64 * consoleZoom); } else { DGL_SetNoMaterial(); *width = *height = 0; } } /** * Called when the player-eyeheight cvar is changed. */ void G_UpdateEyeHeight(cvar_t* unused) { player_t* plr = &players[CONSOLEPLAYER]; if(!(plr->plr->flags & DDPF_CAMERA)) plr->viewHeight = (float) cfg.plrViewHeight; } /** * Draw (char *) text in the game's font. * Called by the console drawer. */ int ConTextOut(const char* text, int x, int y) { M_WriteText3(x, y, text, GF_FONTA, -1, -1, -1, -1, false, false, 0); return 0; } /** * Get the visual width of (char*) text in the game's font. */ int ConTextWidth(const char* text) { return M_StringWidth(text, GF_FONTA); } /** * Console command to take a screenshot (duh). */ DEFCC(CCmdScreenShot) { G_ScreenShot(); return true; } /** * Console command to change the size of the view window. */ DEFCC(CCmdViewSize) { int min = 3, max = 11, *val = &cfg.screenBlocks; if(argc != 2) { Con_Printf("Usage: %s (size)\n", argv[0]); Con_Printf("Size can be: +, -, (num).\n"); return true; } // Adjust/set the value if(!stricmp(argv[1], "+")) (*val)++; else if(!stricmp(argv[1], "-")) (*val)--; else *val = strtol(argv[1], NULL, 0); // Clamp it if(*val < min) *val = min; if(*val > max) *val = max; // Update the view size if necessary. R_SetViewSize(cfg.screenBlocks); return true; } /** * Configure the console to use the game's font. */ DEFCC(CCmdDoom64Font) { ddfont_t cfont; cfont.flags = DDFONT_WHITE; cfont.height = 8; cfont.sizeX = 1.5f; cfont.sizeY = 2; cfont.drawText = ConTextOut; cfont.getWidth = ConTextWidth; cfont.filterText = NULL; Con_SetFont(&cfont); return true; } /** * Configure the console background. */ DEFCC(CCmdConBackground) { material_t* mat; if(!stricmp(argv[1], "off") || !stricmp(argv[1], "none")) { consoleBG = NULL; return true; } if((mat = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(argv[1], MN_ANY)))) consoleBG = mat; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_sound.c0000644000175000017500000000632411357170242022437 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" #include "dmu_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Start the song for the specified map. */ void S_MapMusic(uint episode, uint map) { ddmapinfo_t mapInfo; char mapId[8]; P_GetMapLumpName(episode, map, mapId); if(Def_Get(DD_DEF_MAP_INFO, mapId, &mapInfo)) { if(S_StartMusicNum(mapInfo.music, true)) { // Set the game status cvar for the map music. gsvMapMusic = mapInfo.music; } } } /** * Doom-like sector sounds: when a new sound starts, stop any old ones * from the same origin. * * @param sec Sector in which the sound should be played. * @param origin Origin of the sound (center/floor/ceiling). * @param id ID number of the sound to be played. */ void S_SectorSound(sector_t* sec, int origin, int id) { mobj_t* centerOrigin, *floorOrigin, *ceilingOrigin; centerOrigin = (mobj_t *) P_GetPtrp(sec, DMU_SOUND_ORIGIN); floorOrigin = (mobj_t *) P_GetPtrp(sec, DMU_FLOOR_SOUND_ORIGIN); ceilingOrigin = (mobj_t *) P_GetPtrp(sec, DMU_CEILING_SOUND_ORIGIN); S_StopSound(0, centerOrigin); S_StopSound(0, floorOrigin); S_StopSound(0, ceilingOrigin); switch(origin) { case SORG_FLOOR: S_StartSound(id, floorOrigin); break; case SORG_CEILING: S_StartSound(id, ceilingOrigin); break; case SORG_CENTER: default: S_StartSound(id, centerOrigin); break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/d_api.c0000644000175000017500000001222611357170242022042 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_api.c: Doomsday API setup and interaction - jDoom64 specific */ // HEADER FILES ------------------------------------------------------------ #include #include "jdoom64.h" #include "d_netsv.h" #include "d_net.h" #include "hu_menu.h" #include "xgclass.h" #include "g_update.h" #include "p_mapsetup.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The interface to the Doomsday engine. game_import_t gi; game_export_t gx; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Get a 32-bit integer value. */ int G_GetInteger(int id) { switch(id) { case DD_GAME_DMUAPI_VER: return DMUAPI_VER; default: break; } // ID not recognized, return NULL. return 0; } /** * Get a pointer to the value of a variable. Added for 64-bit support. */ void *G_GetVariable(int id) { static float bob[2]; switch(id) { case DD_GAME_NAME: return GAMENAMETEXT; case DD_GAME_NICENAME: return GAME_NICENAME; case DD_GAME_ID: return GAMENAMETEXT " " GAME_VERSION_TEXT; case DD_GAME_MODE: return gameModeString; case DD_GAME_CONFIG: return gameConfigString; case DD_VERSION_SHORT: return GAME_VERSION_TEXT; case DD_VERSION_LONG: return GAME_VERSION_TEXTLONG "\n" GAME_DETAILS; case DD_ACTION_LINK: return actionlinks; case DD_XGFUNC_LINK: return xgClasses; case DD_PSPRITE_BOB_X: R_GetWeaponBob(CONSOLEPLAYER, &bob[0], NULL); return &bob[0]; case DD_PSPRITE_BOB_Y: R_GetWeaponBob(CONSOLEPLAYER, NULL, &bob[1]); return &bob[1]; default: break; } // ID not recognized, return NULL. return 0; } /** * Takes a copy of the engine's entry points and exported data. Returns * a pointer to the structure that contains our entry points and exports. */ game_export_t *GetGameAPI(game_import_t *imports) { // Take a copy of the imports, but only copy as much data as is // allowed and legal. memset(&gi, 0, sizeof(gi)); memcpy(&gi, imports, MIN_OF(sizeof(game_import_t), imports->apiSize)); // Clear all of our exports. memset(&gx, 0, sizeof(gx)); // Fill in the data for the exports. gx.apiSize = sizeof(gx); gx.PreInit = G_PreInit; gx.PostInit = G_PostInit; gx.Shutdown = G_Shutdown; gx.Ticker = G_Ticker; gx.G_Drawer = D_Display; gx.G_Drawer2 = D_Display2; gx.PrivilegedResponder = (boolean (*)(event_t *)) G_PrivilegedResponder; gx.FallbackResponder = NULL; //Hu_MenuResponder; gx.G_Responder = G_Responder; gx.MobjThinker = P_MobjThinker; gx.MobjFriction = (float (*)(void *)) P_MobjGetFriction; gx.EndFrame = G_EndFrame; gx.ConsoleBackground = D_ConsoleBg; gx.UpdateState = G_UpdateState; #undef Get gx.GetInteger = G_GetInteger; gx.GetVariable = G_GetVariable; gx.NetServerStart = D_NetServerStarted; gx.NetServerStop = D_NetServerClose; gx.NetConnect = D_NetConnect; gx.NetDisconnect = D_NetDisconnect; gx.NetPlayerEvent = D_NetPlayerEvent; gx.NetWorldEvent = D_NetWorldEvent; gx.HandlePacket = D_HandlePacket; gx.NetWriteCommands = D_NetWriteCommands; gx.NetReadCommands = D_NetReadCommands; // Data structure sizes. gx.ticcmdSize = sizeof(ticcmd_t); gx.mobjSize = sizeof(mobj_t); gx.polyobjSize = sizeof(polyobj_t); gx.SetupForMapData = P_SetupForMapData; // These really need better names. Ideas? gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; return &gx; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_mobj.c0000644000175000017500000011031311357170242022230 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.c: Moving object handling. Spawn functions. */ #ifdef MSVC # pragma optimize("g", off) #endif // HEADER FILES ------------------------------------------------------------ #include #include #include #include "jdoom64.h" #include "dmu_lib.h" #include "hu_stuff.h" #include "g_common.h" #include "p_map.h" #include "p_terraintype.h" #include "p_player.h" #include "p_tick.h" #include "p_actor.h" #include "p_start.h" // MACROS ------------------------------------------------------------------ #define VANISHTICS (2*TICSPERSEC) #define SPAWNFADETICS (1*TICSPERSEC) #define MAX_BOB_OFFSET (8) #define NOMOMENTUM_THRESHOLD (0.000001f) #define WALKSTOP_THRESHOLD (0.062484741f) // FIX2FLT(0x1000-1) #define STANDSPEED (1.0f/2) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- const terraintype_t* P_MobjGetFloorTerrainType(mobj_t* mo) { sector_t* sec = P_GetPtrp(mo->subsector, DMU_SECTOR); return P_GetPlaneMaterialType(sec, PLN_FLOOR); } /** * @return @c true, if the mobj is still present. */ boolean P_MobjChangeState(mobj_t* mobj, statenum_t state) { state_t* st; do { if(state == S_NULL) { mobj->state = (state_t *) S_NULL; P_MobjRemove(mobj, false); return false; } P_MobjSetState(mobj, state); st = &STATES[state]; mobj->turnTime = false; // $visangle-facetarget // Modified handling. // Call action functions when the state is set if(st->action) st->action(mobj); state = st->nextState; } while(!mobj->tics); return true; } void P_ExplodeMissile(mobj_t *mo) { if(IS_CLIENT) { // Clients won't explode missiles. P_MobjChangeState(mo, S_NULL); return; } mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); mo->tics -= P_Random() & 3; if(mo->tics < 1) mo->tics = 1; if(mo->flags & MF_MISSILE) { mo->flags &= ~MF_MISSILE; mo->flags |= MF_VIEWALIGN; // Remove the brightshadow flag. if(mo->flags & MF_BRIGHTSHADOW) mo->flags &= ~MF_BRIGHTSHADOW; if(mo->flags & MF_BRIGHTEXPLODE) mo->flags |= MF_BRIGHTSHADOW; } if(mo->info->deathSound) S_StartSound(mo->info->deathSound, mo); } void P_FloorBounceMissile(mobj_t *mo) { mo->mom[MZ] = -mo->mom[MZ]; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); } /** * @return The ground friction factor for the mobj. */ float P_MobjGetFriction(mobj_t *mo) { if((mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && !mo->onMobj) { return FRICTION_FLY; } return XS_Friction(P_GetPtrp(mo->subsector, DMU_SECTOR)); } static boolean isInWalkState(player_t* pl) { return pl->plr->mo->state - STATES - PCLASS_INFO(pl->class)->runState < 4; } static float getFriction(mobj_t* mo) { if((mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && !mo->onMobj) { // Airborne friction. return FRICTION_FLY; } #if __JHERETIC__ if(P_ToXSector(P_GetPtrp(mo->subsector, DMU_SECTOR))->special == 15) { // Friction_Low return FRICTION_LOW; } #endif return P_MobjGetFriction(mo); } void P_MobjMoveXY(mobj_t* mo) { float pos[3], mom[3]; player_t* player; boolean largeNegative; // $democam: cameramen have their own movement code if(P_CameraXYMovement(mo)) return; mom[MX] = MINMAX_OF(-MAXMOVE, mo->mom[MX], MAXMOVE); mom[MY] = MINMAX_OF(-MAXMOVE, mo->mom[MY], MAXMOVE); mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; if(mom[MX] == 0 && mom[MY] == 0) { if(mo->flags & MF_SKULLFLY) { // The skull slammed into something. mo->flags &= ~MF_SKULLFLY; mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN)); } return; } player = mo->player; do { /** * DOOM.exe bug fix: * Large negative displacements were never considered. This explains the * tendency for Mancubus fireballs to pass through walls. */ largeNegative = false; if(!cfg.moveBlock && (mom[MX] < -MAXMOVE / 2 || mom[MY] < -MAXMOVE / 2)) { // Make an exception for "north-only wallrunning". if(!(cfg.wallRunNorthOnly && mo->wallRun)) largeNegative = true; } if(largeNegative || mom[MX] > MAXMOVE / 2 || mom[MY] > MAXMOVE / 2) { pos[VX] = mo->pos[VX] + mom[VX] / 2; pos[VY] = mo->pos[VY] + mom[VY] / 2; mom[VX] /= 2; mom[VY] /= 2; } else { pos[VX] = mo->pos[VX] + mom[MX]; pos[VY] = mo->pos[VY] + mom[MY]; mom[MX] = mom[MY] = 0; } // If mobj was wallrunning - stop. if(mo->wallRun) mo->wallRun = false; // $dropoff_fix. if(!P_TryMove(mo, pos[VX], pos[VY], true, false)) { // Blocked move. if(mo->flags2 & MF2_SLIDE) { // Try to slide along it. P_SlideMove(mo); } else if(mo->flags & MF_MISSILE) { sector_t* backSec; //// kludge: Prevent missiles exploding against the sky. if(ceilingLine && (backSec = P_GetPtrp(ceilingLine, DMU_BACK_SECTOR))) { material_t* mat = P_GetPtrp(backSec, DMU_CEILING_MATERIAL); if((P_GetIntp(mat, DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] > P_GetFloatp(backSec, DMU_CEILING_HEIGHT)) { P_MobjRemove(mo, false); return; } } if(floorLine && (backSec = P_GetPtrp(floorLine, DMU_BACK_SECTOR))) { material_t* mat = P_GetPtrp(backSec, DMU_FLOOR_MATERIAL); if((P_GetIntp(mat, DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] < P_GetFloatp(backSec, DMU_FLOOR_HEIGHT)) { P_MobjRemove(mo, false); return; } } //// kludge end. P_ExplodeMissile(mo); } else { mo->mom[MX] = mo->mom[MY] = 0; } } } while(!INRANGE_OF(mom[MX], 0, NOMOMENTUM_THRESHOLD) || !INRANGE_OF(mom[MY], 0, NOMOMENTUM_THRESHOLD)); // Slow down. if(player && (P_GetPlayerCheats(player) & CF_NOMOMENTUM)) { // Debug option for no sliding at all. mo->mom[MX] = mo->mom[MY] = 0; return; } if(mo->flags & (MF_MISSILE | MF_SKULLFLY)) return; // No friction for missiles ever. if(mo->pos[VZ] > mo->floorZ && !mo->onMobj && !(mo->flags2 & MF2_FLY)) return; // No friction when falling. if(cfg.slidingCorpses) { // $dropoff_fix: Add objects falling off ledges, does not apply to // players. if(((mo->flags & MF_CORPSE) || (mo->intFlags & MIF_FALLING)) && !mo->player) { // Do not stop sliding if halfway off a step with some momentum. if(mo->mom[MX] > (1.0f / 4) || mo->mom[MX] < -(1.0f / 4) || mo->mom[MY] > (1.0f / 4) || mo->mom[MY] < -(1.0f / 4)) { if(mo->floorZ != P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) return; } } } // Stop player walking animation. if((!player || (!(player->plr->cmd.forwardMove | player->plr->cmd.sideMove) && player->plr->mo != mo /* $voodoodolls: Stop animating. */)) && INRANGE_OF(mo->mom[MX], 0, WALKSTOP_THRESHOLD) && INRANGE_OF(mo->mom[MY], 0, WALKSTOP_THRESHOLD)) { // If in a walking frame, stop moving. if(player && isInWalkState(player) && player->plr->mo == mo) P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->normalState); // $voodoodolls: Do not zero mom! if(!(player && player->plr->mo != mo)) mo->mom[MX] = mo->mom[MY] = 0; // $voodoodolls: Stop view bobbing if this isn't a voodoo doll. if(player && player->plr->mo == mo) player->bob = 0; } else { float friction = getFriction(mo); mo->mom[MX] *= friction; mo->mom[MY] *= friction; } } /* static boolean PIT_Splash(sector_t *sector, void *data) { mobj_t *mo = data; float floorheight; floorheight = P_GetFloatp(sector, DMU_FLOOR_HEIGHT); // Is the mobj touching the floor of this sector? if(mo->pos[VZ] < floorheight && mo->pos[VZ] + mo->height / 2 > floorheight) { //// \todo Play a sound, spawn a generator, etc. } // Continue checking. return true; } */ void P_HitFloor(mobj_t* mo) { //P_MobjSectorsIterator(mo, PIT_Splash, mo); } void P_MobjMoveZ(mobj_t* mo) { float gravity, dist, delta; gravity = XS_Gravity(P_GetPtrp(mo->subsector, DMU_SECTOR)); // $democam: cameramen get special z movement. if(P_CameraZMovement(mo)) return; // $voodoodolls: Check for smooth step up unless a voodoo doll. if(mo->player && mo->player->plr->mo == mo && mo->pos[VZ] < mo->floorZ) { mo->player->viewHeight -= mo->floorZ - mo->pos[VZ]; mo->player->viewHeightDelta = (cfg.plrViewHeight - mo->player->viewHeight) / 8; } // Adjust height. mo->pos[VZ] += mo->mom[MZ]; if((mo->flags2 & MF2_FLY) && mo->onMobj && mo->pos[VZ] > mo->onMobj->pos[VZ] + mo->onMobj->height) mo->onMobj = NULL; // We were on a mobj, we are NOT now. if(!((mo->flags ^ MF_FLOAT) & (MF_FLOAT | MF_SKULLFLY | MF_INFLOAT)) && mo->target && !P_MobjIsCamera(mo->target)) { // Float down towards target if too close. dist = P_ApproxDistance(mo->pos[VX] - mo->target->pos[VX], mo->pos[VY] - mo->target->pos[VY]); //delta = (mo->target->pos[VZ] + (mo->height / 2)) - mo->pos[VZ]; delta = (mo->target->pos[VZ] + mo->target->height / 2) - (mo->pos[VZ] + mo->height / 2); // Don't go INTO the target. if(!(dist < mo->radius + mo->target->radius && fabs(delta) < mo->height + mo->target->height)) { if(delta < 0 && dist < -(delta * 3)) { mo->pos[VZ] -= FLOATSPEED; P_MobjSetSRVOZ(mo, -FLOATSPEED); } else if(delta > 0 && dist < (delta * 3)) { mo->pos[VZ] += FLOATSPEED; P_MobjSetSRVOZ(mo, FLOATSPEED); } } } // Do some fly-bobbing. if(mo->player && (mo->flags2 & MF2_FLY) && mo->pos[VZ] > mo->floorZ && !mo->onMobj && (mapTime & 2)) { mo->pos[VZ] += FIX2FLT(finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]); } // Clip movement. Another thing? // jd64 > // DJS - FIXME! if(mo->pos[VZ] <= mo->floorZ && (mo->flags & MF_MISSILE)) { // Hit the floor mo->pos[VZ] = mo->floorZ; P_ExplodeMissile(mo); return; } // < d64tc // Clip movement. Another thing? if(mo->onMobj && mo->pos[VZ] <= mo->onMobj->pos[VZ] + mo->onMobj->height) { if(mo->mom[MZ] < 0) { if(mo->player && mo->mom[MZ] < -gravity * 8 && !(mo->flags2 & MF2_FLY)) { // Squat down. // Decrease viewheight for a moment after hitting the ground // (hard), and utter appropriate sound. mo->player->viewHeightDelta = mo->mom[MZ] / 8; if(mo->player->health > 0) S_StartSound(SFX_OOF, mo); } mo->mom[MZ] = 0; } if(mo->mom[MZ] == 0) mo->pos[VZ] = mo->onMobj->pos[VZ] + mo->onMobj->height; if((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) { P_ExplodeMissile(mo); return; } } // jd64 > // MotherDemon's Fire attacks can climb up/down stairs // DJS - FIXME! #if 0 if((mo->flags & MF_MISSILE) && (mo->type == MT_FIREEND)) { mo->pos[VZ] = mo->floorZ; if(mo->type == MT_FIREEND) { return; } else { P_ExplodeMissile(mo); return; } } #endif // < d64tc // The floor. if(mo->pos[VZ] <= mo->floorZ) { // Hit the floor. boolean movingDown; // Note (id): // somebody left this after the setting momz to 0, // kinda useless there. // // cph - This was the a bug in the linuxdoom-1.10 source which // caused it not to sync Doom 2 v1.9 demos. Someone // added the above comment and moved up the following code. So // demos would desync in close lost soul fights. // Note that this only applies to original Doom 1 or Doom2 demos - not // Final Doom and Ultimate Doom. So we test demo_compatibility *and* // gameMission. (Note we assume that Doom1 is always Ult Doom, which // seems to hold for most published demos.) // // fraggle - cph got the logic here slightly wrong. There are three // versions of Doom 1.9: // // * The version used in registered doom 1.9 + doom2 - no bounce // * The version used in ultimate doom - has bounce // * The version used in final doom - has bounce // // So we need to check that this is either retail or commercial // (but not doom2) int correctLostSoulBounce = true; if(correctLostSoulBounce && (mo->flags & MF_SKULLFLY)) { // The skull slammed into something. mo->mom[MZ] = -mo->mom[MZ]; } if(movingDown = (mo->mom[MZ] < 0)) { if(mo->player && mo->player->plr->mo == mo && mo->mom[MZ] < -gravity * 8 && !(mo->flags2 & MF2_FLY)) { // Squat down. // Decrease viewheight for a moment after hitting the ground // (hard), and utter appropriate sound. mo->player->viewHeightDelta = mo->mom[MZ] / 8; mo->player->jumpTics = 10; /** * DOOM bug: * Dead players would grunt when hitting the ground (e.g., * after an archvile attack). */ if(mo->player->health > 0) S_StartSound(SFX_OOF, mo); } } mo->pos[VZ] = mo->floorZ; if(movingDown) P_HitFloor(mo); /** * See lost soul bouncing comment above. We need this here for bug * compatibility with original Doom2 v1.9 - if a soul is charging * and hit by a raising floor this would incorrectly reverse it's * Y momentum. */ if(!correctLostSoulBounce && (mo->flags & MF_SKULLFLY)) mo->mom[MZ] = -mo->mom[MZ]; if(!((mo->flags ^ MF_MISSILE) & (MF_MISSILE | MF_NOCLIP))) { if(mo->flags2 & MF2_FLOORBOUNCE) { P_FloorBounceMissile(mo); return; } else { P_ExplodeMissile(mo); return; } } if(movingDown && mo->mom[MZ] < 0) mo->mom[MZ] = 0; } else if(mo->flags2 & MF2_LOGRAV) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= (gravity / 8); } else if(!(mo->flags & MF_NOGRAVITY)) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; } if(mo->pos[VZ] + mo->height > mo->ceilingZ) { // Hit the ceiling. if(mo->mom[MZ] > 0) mo->mom[MZ] = 0; mo->pos[VZ] = mo->ceilingZ - mo->height; if(mo->flags & MF_SKULLFLY) { // The skull slammed into something. mo->mom[MZ] = -mo->mom[MZ]; } if(!((mo->flags ^ MF_MISSILE) & (MF_MISSILE | MF_NOCLIP))) { // Don't explode against sky. if(P_GetIntp(P_GetPtrp(mo->subsector, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) { P_MobjRemove(mo, false); } else { P_ExplodeMissile(mo); } } } } void P_NightmareRespawn(mobj_t* mobj) { mobj_t* mo; // Something is occupying it's position? if(!P_CheckPosition2f(mobj, mobj->spawnSpot.pos[VX], mobj->spawnSpot.pos[VY])) return; // No respwan. if((mo = P_SpawnMobj3fv(mobj->type, mobj->spawnSpot.pos, mobj->spawnSpot.angle, mobj->spawnSpot.flags))) { mo->reactionTime = 18; // Spawn a teleport fog at old spot. if((mo = P_SpawnMobj3f(MT_TFOG, mobj->pos[VX], mobj->pos[VY], 0, mobj->angle, MSF_Z_FLOOR))) S_StartSound(SFX_TELEPT, mo); // Spawn a teleport fog at the new spot. if((mo = P_SpawnMobj3fv(MT_TFOG, mobj->spawnSpot.pos, mobj->spawnSpot.angle, mobj->spawnSpot.flags))) S_StartSound(SFX_TELEPT, mo); } // Remove the old monster. P_MobjRemove(mobj, true); } void P_MobjThinker(mobj_t *mobj) { if(mobj->ddFlags & DDMF_REMOTE) return; // Remote mobjs are handled separately. // Spectres get selector = 1. if(mobj->type == MT_SHADOWS) mobj->selector = (mobj->selector & ~DDMOBJ_SELECTOR_MASK) | 1; // The first three bits of the selector special byte contain a // relative health level. P_UpdateHealthBits(mobj); #if __JHERETIC__ // Lightsources must stay where they're hooked. if(mobj->type == MT_LIGHTSOURCE) { if(mobj->moveDir > 0) mobj->pos[VZ] = P_GetFloatp(mobj->subsector, DMU_FLOOR_HEIGHT); else mobj->pos[VZ] = P_GetFixedp(mobj->subsector, DMU_CEILING_HEIGHT); mobj->pos[VZ] += FIX2FLT(mobj->moveDir); return; } #endif // Handle X and Y momentums. if(mobj->mom[MX] != 0 || mobj->mom[MY] != 0 || (mobj->flags & MF_SKULLFLY)) { P_MobjMoveXY(mobj); //// \fixme decent NOP/NULL/Nil function pointer please. if(mobj->thinker.function == NOPFUNC) return; // Mobj was removed. } if(mobj->flags2 & MF2_FLOATBOB) { // Floating item bobbing motion. // Keep it on the floor. mobj->pos[VZ] = mobj->floorZ; mobj->floorClip = 0; if(mobj->floorClip < -MAX_BOB_OFFSET) { // We don't want it going through the floor. mobj->floorClip = -MAX_BOB_OFFSET; } } else if(mobj->pos[VZ] != mobj->floorZ || mobj->mom[MZ] != 0) { P_MobjMoveZ(mobj); if(mobj->thinker.function != P_MobjThinker) // Must've been removed. return; // Mobj was removed. } // Non-sentient objects at rest. else if(!(mobj->mom[MX] == 0 && mobj->mom[MY] == 0) && !sentient(mobj) && !(mobj->player) && !((mobj->flags & MF_CORPSE) && cfg.slidingCorpses)) { // Objects fall off ledges if they are hanging off slightly push // off of ledge if hanging more than halfway off if(mobj->pos[VZ] > mobj->dropOffZ && // Only objects contacting dropoff. !(mobj->flags & MF_NOGRAVITY) && cfg.fallOff) { P_ApplyTorque(mobj); } else { mobj->intFlags &= ~MIF_FALLING; mobj->gear = 0; // Reset torque. } } if(cfg.slidingCorpses) { if(((mobj->flags & MF_CORPSE)? mobj->pos[VZ] > mobj->dropOffZ : mobj->pos[VZ] - mobj->dropOffZ > 24) && // Only objects contacting drop off !(mobj->flags & MF_NOGRAVITY)) // Only objects which fall. { P_ApplyTorque(mobj); // Apply torque. } else { mobj->intFlags &= ~MIF_FALLING; mobj->gear = 0; // Reset torque. } } // $vanish: dead monsters disappear after some time. if(cfg.corpseTime && (mobj->flags & MF_CORPSE) && mobj->corpseTics != -1) { if(++mobj->corpseTics < cfg.corpseTime * TICSPERSEC) { mobj->translucency = 0; // Opaque. } else if(mobj->corpseTics < cfg.corpseTime * TICSPERSEC + VANISHTICS) { // Translucent during vanishing. mobj->translucency = ((mobj->corpseTics - cfg.corpseTime * TICSPERSEC) * 255) / VANISHTICS; } else { // Too long; get rid of the corpse. mobj->corpseTics = -1; return; } } // jd64 > // Fade monsters upon spawning. if(mobj->intFlags & MIF_FADE) { if(++mobj->spawnFadeTics < SPAWNFADETICS) { mobj->translucency = MINMAX_OF(0, 255 - 255 * mobj->spawnFadeTics / SPAWNFADETICS, 255); } else { mobj->intFlags &= ~MIF_FADE; mobj->translucency = 0; } } // < d64tc // Cycle through states, calling action functions at transitions. if(mobj->tics != -1) { mobj->tics--; P_MobjAngleSRVOTicker(mobj); // "angle-servo"; smooth actor turning. // You can cycle through multiple STATES in a tic. if(!mobj->tics) { P_MobjClearSRVO(mobj); if(!P_MobjChangeState(mobj, mobj->state->nextState)) return; // Freed itself. } } else if(!IS_CLIENT) { // Check for nightmare respawn. if(!(mobj->flags & MF_COUNTKILL)) return; if(!respawnMonsters) return; mobj->moveCount++; if(mobj->moveCount < 12 * 35) return; if(mapTime & 31) return; if(P_Random() > 4) return; P_NightmareRespawn(mobj); } } /** * Spawns a mobj of "type" at the specified position. */ mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags) { mobj_t* mo; mobjinfo_t* info; float space; int ddflags = 0; if(type < MT_FIRST || type >= Get(DD_NUMMOBJTYPES)) { #ifdef _DEBUG Con_Error("P_SpawnMobj: Illegal mo type %i.\n", type); #endif return NULL; } info = &MOBJINFO[type]; // Clients only spawn local objects. if(!(info->flags & MF_LOCAL) && IS_CLIENT) return NULL; // Not for deathmatch? if(deathmatch && (info->flags & MF_NOTDMATCH)) return NULL; // Check for specific disabled objects. if(IS_NETGAME) { // Cooperative weapons? if(cfg.noCoopWeapons && !deathmatch && type >= MT_CLIP && type <= MT_SUPERSHOTGUN) return NULL; // Don't spawn any special objects in coop? if(cfg.noCoopAnything && !deathmatch) return NULL; // BFG disabled in netgames? if(cfg.noNetBFG && type == MT_MISC25) return NULL; } // Don't spawn any monsters if -noMonstersParm. if(noMonstersParm && ((info->flags & MF_COUNTKILL) || type == MT_SKULL)) return NULL; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; mo = P_MobjCreate(P_MobjThinker, x, y, z, angle, info->radius, info->height, ddflags); mo->type = type; mo->info = info; mo->flags = info->flags; mo->flags2 = info->flags2; mo->flags3 = info->flags3; mo->damage = info->damage; mo->health = info->spawnHealth * (IS_NETGAME ? cfg.netMobHealthModifier : 1); mo->moveDir = DI_NODIR; mo->reactionTime = info->reactionTime; mo->lastLook = P_Random() % MAXPLAYERS; // Must link before setting state (ID assigned for the mo). P_MobjSetState(mo, P_GetState(mo->type, SN_SPAWN)); // Set subsector and/or block links. P_MobjSetPosition(mo); mo->floorZ = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); mo->dropOffZ = mo->floorZ; mo->ceilingZ = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); if((spawnFlags & MSF_Z_CEIL) || (info->flags & MF_SPAWNCEILING)) { mo->pos[VZ] = mo->ceilingZ - mo->info->height - z; } else if((spawnFlags & MSF_Z_RANDOM) || (info->flags2 & MF2_SPAWNFLOAT)) { space = mo->ceilingZ - mo->info->height - mo->floorZ; if(space > 48) { space -= 40; mo->pos[VZ] = ((space * P_Random()) / 256) + mo->floorZ + 40; } else { mo->pos[VZ] = mo->floorZ; } } else if(spawnFlags & MSF_Z_FLOOR) { mo->pos[VZ] = mo->floorZ + z; } /*if(spawnFlags & MTF_FLOAT) { mo->pos[VZ] += 96; mo->flags |= (MF_FLOAT | MF_NOGRAVITY); }*/ if(spawnFlags & MSF_DEAF) mo->flags |= MF_AMBUSH; mo->floorClip = 0; if((mo->flags2 & MF2_FLOORCLIP) && mo->pos[VZ] == P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } /*if(spawnFlags & MTF_WALKOFF) mo->flags |= (MF_FLOAT | MF_DROPOFF); if(spawnFlags & MTF_TRANSLUCENT) mo->flags |= MF_SHADOW;*/ // Copy spawn attributes to the new mobj. mo->spawnSpot.pos[VX] = x; mo->spawnSpot.pos[VY] = y; mo->spawnSpot.pos[VZ] = z; mo->spawnSpot.angle = angle; mo->spawnSpot.flags = spawnFlags; return mo; } mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags) { return P_SpawnMobj3f(type, pos[VX], pos[VY], pos[VZ], angle, spawnFlags); } mobj_t* P_SpawnCustomPuff(mobjtype_t type, float x, float y, float z, angle_t angle) { mobj_t* mo; // Clients do not spawn puffs. if(IS_CLIENT) return NULL; z += FIX2FLT((P_Random() - P_Random()) << 10); if((mo = P_SpawnMobj3f(type, x, y, z, angle, 0))) { mo->mom[MZ] = FIX2FLT(FRACUNIT); mo->tics -= P_Random() & 3; // Make it last at least one tic. if(mo->tics < 1) mo->tics = 1; } return mo; } void P_SpawnPuff(float x, float y, float z, angle_t angle) { mobj_t* th = P_SpawnCustomPuff(MT_PUFF, x, y, z, angle); // Don't make punches spark on the wall. if(th && attackRange == MELEERANGE) P_MobjChangeState(th, S_PUFF3); } void P_SpawnBlood(float x, float y, float z, int damage, angle_t angle) { mobj_t* mo; z += FIX2FLT((P_Random() - P_Random()) << 10); if((mo = P_SpawnMobj3f(MT_BLOOD, x, y, z, angle, 0))) { mo->mom[MZ] = 2; mo->tics -= P_Random() & 3; if(mo->tics < 1) mo->tics = 1; if(damage <= 12 && damage >= 9) P_MobjChangeState(mo, S_BLOOD2); else if(damage < 9) P_MobjChangeState(mo, S_BLOOD3); } } /** * Moves the missile forward a bit and possibly explodes it right there. * * @param th The missile to be checked. * * @return @c true, if the missile is at a valid location else * @c false */ boolean P_CheckMissileSpawn(mobj_t *th) { th->tics -= P_Random() & 3; if(th->tics < 1) th->tics = 1; // Move forward slightly so an angle can be computed if it explodes // immediately. th->pos[VX] += th->mom[MX] / 2; th->pos[VY] += th->mom[MY] / 2; th->pos[VZ] += th->mom[MZ] / 2; if(!P_TryMove(th, th->pos[VX], th->pos[VY], false, false)) { P_ExplodeMissile(th); return false; } return true; } /** * Tries to aim at a nearby monster if source is a player. Else aim is * taken at dest. * * @param source The mobj doing the shooting. * @param dest The mobj being shot at. Can be @c NULL if source * is a player. * @param type The type of mobj to be shot. * * @return Pointer to the newly spawned missile. */ mobj_t* P_SpawnMissile(mobjtype_t type, mobj_t* source, mobj_t* dest) { float pos[3]; mobj_t* th = 0; unsigned int an; angle_t angle = 0; float dist = 0; float slope = 0; float spawnZOff = 0; memcpy(pos, source->pos, sizeof(pos)); if(source->player) { // See which target is to be aimed at. angle = source->angle; slope = P_AimLineAttack(source, angle, 16 * 64); if(!cfg.noAutoAim) if(!lineTarget) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget) { angle = source->angle; slope = tan(LOOKDIR2RAD(source->dPlayer->lookDir)) / 1.2f; } } if(!P_MobjIsCamera(source->player->plr->mo)) spawnZOff = cfg.plrViewHeight - 9 + source->player->plr->lookDir / 173; } else { spawnZOff = 32; } pos[VZ] += spawnZOff; pos[VZ] -= source->floorClip; angle = R_PointToAngle2(pos[VX], pos[VY], dest->pos[VX], dest->pos[VY]); if(!source->player) { // Fuzzy player. if(dest->flags & MF_SHADOW) angle += (P_Random() - P_Random()) << 20; } if(!(th = P_SpawnMobj3fv(type, pos, angle, 0))) return NULL; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Where it came from. an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); /*if(source->player) { // Allow free-aim with the BFG in deathmatch? if(deathmatch && cfg.netBFGFreeLook == 0 && type == MT_BFG) th->mom[MZ] = 0; else th->mom[MZ] = th->info->speed * slope; } else*/ { dist = P_ApproxDistance(dest->pos[VX] - pos[VX], dest->pos[VY] - pos[VY]); dist /= th->info->speed; if(dist < 1) dist = 1; th->mom[MZ] = (dest->pos[VZ] - source->pos[VZ]) / dist; } // Make sure the speed is right (in 3D). dist = P_ApproxDistance(P_ApproxDistance(th->mom[MX], th->mom[MY]), th->mom[MZ]); if(dist < 1) dist = 1; dist = th->info->speed / dist; th->mom[MX] *= dist; th->mom[MY] *= dist; th->mom[MZ] *= dist; if(P_CheckMissileSpawn(th)) return th; return NULL; } /** * d64tc * DJS - It would appear this routine has been stolen from HEXEN and then * butchered... * FIXME: Make sure this still works correctly. */ mobj_t* P_SPMAngle(mobjtype_t type, mobj_t *source, angle_t sourceAngle) { mobj_t *th; uint an; angle_t angle; float pos[3], slope, spawnZOff; float fangle = LOOKDIR2RAD(source->player->plr->lookDir), movfactor = 1; pos[VX] = source->pos[VX]; pos[VY] = source->pos[VY]; pos[VZ] = source->pos[VZ]; // See which target is to be aimed at. angle = sourceAngle; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget) { angle = sourceAngle; slope = sin(fangle) / 1.2; movfactor = cos(fangle); } } if(!P_MobjIsCamera(source->player->plr->mo)) spawnZOff = cfg.plrViewHeight - 9 + source->player->plr->lookDir / 173; else spawnZOff = 0; pos[VZ] += spawnZOff; pos[VZ] -= source->floorClip; if((th = P_SpawnMobj3fv(type, pos, angle, 0))) { th->target = source; an = angle >> ANGLETOFINESHIFT; th->mom[MX] = movfactor * th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = movfactor * th->info->speed * FIX2FLT(finesine[an]); th->mom[MZ] = th->info->speed * slope; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); P_CheckMissileSpawn(th); } return th; } /** * d64tc */ mobj_t* P_SpawnMotherMissile(mobjtype_t type, float x, float y, float z, mobj_t *source, mobj_t *dest) { mobj_t *th; uint an; angle_t angle; float dist; z -= source->floorClip; angle = R_PointToAngle2(x, y, dest->pos[VX], dest->pos[VY]); if(dest->flags & MF_SHADOW) // Invisible target { angle += (P_Random() - P_Random()) << 21; } if(!(th = P_SpawnMobj3f(type, x, y, z, angle, 0))) return NULL; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Originator an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); dist = P_ApproxDistance(dest->pos[VX] - x, dest->pos[VY] - y); dist /= th->info->speed; if(dist < 1) dist = 1; th->mom[MZ] = (dest->pos[VZ] - z + 30) / dist; P_CheckMissileSpawn(th); return th; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/st_stuff.c0000644000175000017500000004132111357170242022621 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.c: Fullscreen HUD code. * * Does palette indicators as well (red pain/berserk, bright pickup) */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom64.h" #include "d_net.h" #include "st_lib.h" #include "hu_stuff.h" #include "am_map.h" #include "p_tick.h" // for P_IsPaused #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // Radiation suit, green shift. #define RADIATIONPAL 13 // Frags pos. #define ST_FRAGSX 138 #define ST_FRAGSY 171 #define ST_FRAGSWIDTH 2 // TYPES ------------------------------------------------------------------- typedef struct { boolean stopped; int hideTics; float hideAmount; float alpha; // Fullscreen hud alpha value. boolean firstTime; // ST_Start() has just been called. boolean blended; // Whether to use alpha blending. boolean statusbarActive; // Whether the HUD is on. int currentFragsCount; // Number of frags so far in deathmatch. // Widgets: st_number_t wFrags; // In deathmatch only, summary of frags stats. } hudstate_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static hudstate_t hudStates[MAXPLAYERS]; // 0-9, tall numbers. static dpatch_t tallnum[10]; // CVARs for the HUD/Statusbar. cvar_t sthudCVars[] = { // HUD scale {"hud-scale", 0, CVT_FLOAT, &cfg.hudScale, 0.1f, 10}, // HUD colour + alpha {"hud-color-r", 0, CVT_FLOAT, &cfg.hudColor[0], 0, 1}, {"hud-color-g", 0, CVT_FLOAT, &cfg.hudColor[1], 0, 1}, {"hud-color-b", 0, CVT_FLOAT, &cfg.hudColor[2], 0, 1}, {"hud-color-a", 0, CVT_FLOAT, &cfg.hudColor[3], 0, 1}, {"hud-icon-alpha", 0, CVT_FLOAT, &cfg.hudIconAlpha, 0, 1}, // HUD icons {"hud-health", 0, CVT_BYTE, &cfg.hudShown[HUD_HEALTH], 0, 1}, {"hud-armor", 0, CVT_BYTE, &cfg.hudShown[HUD_ARMOR], 0, 1}, {"hud-ammo", 0, CVT_BYTE, &cfg.hudShown[HUD_AMMO], 0, 1}, {"hud-keys", 0, CVT_BYTE, &cfg.hudShown[HUD_KEYS], 0, 1}, {"hud-power", 0, CVT_BYTE, &cfg.hudShown[HUD_INVENTORY], 0, 1}, // HUD displays {"hud-frags", 0, CVT_BYTE, &cfg.hudShown[HUD_FRAGS], 0, 1}, {"hud-timer", 0, CVT_FLOAT, &cfg.hudTimer, 0, 60}, {"hud-unhide-damage", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_DAMAGE], 0, 1}, {"hud-unhide-pickup-health", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_HEALTH], 0, 1}, {"hud-unhide-pickup-armor", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_ARMOR], 0, 1}, {"hud-unhide-pickup-powerup", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_POWER], 0, 1}, {"hud-unhide-pickup-weapon", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_WEAPON], 0, 1}, {"hud-unhide-pickup-ammo", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_AMMO], 0, 1}, {"hud-unhide-pickup-key", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_KEY], 0, 1}, {NULL} }; // CODE -------------------------------------------------------------------- /** * Register CVARs and CCmds for the HUD/Status bar */ void ST_Register(void) { uint i; for(i = 0; sthudCVars[i].name; ++i) Con_AddVariable(sthudCVars + i); } /** * Unhides the current HUD display if hidden. * * @param player The player whoose HUD to (maybe) unhide. * @param event The HUD Update Event type to check for triggering. */ void ST_HUDUnHide(int player, hueevent_t ev) { player_t* plr; if(ev < HUE_FORCE || ev > NUMHUDUNHIDEEVENTS) return; plr = &players[player]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) return; if(ev == HUE_FORCE || cfg.hudUnHide[ev]) { hudStates[player].hideTics = (cfg.hudTimer * TICSPERSEC); hudStates[player].hideAmount = 0; } } void ST_updateWidgets(int player) { int i; player_t* plr = &players[player]; hudstate_t* hud = &hudStates[player]; // Used by wFrags widget. hud->currentFragsCount = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; hud->currentFragsCount += plr->frags[i] * (i != player ? 1 : -1); } } void ST_Ticker(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; hudstate_t* hud = &hudStates[i]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) continue; if(!P_IsPaused()) { if(cfg.hudTimer == 0) { hud->hideTics = hud->hideAmount = 0; } else { if(hud->hideTics > 0) hud->hideTics--; if(hud->hideTics == 0 && cfg.hudTimer > 0 && hud->hideAmount < 1) hud->hideAmount += 0.1f; } ST_updateWidgets(i); } } } void ST_doPaletteStuff(int player) { int palette = 0, cnt, bzc; player_t* plr = &players[player]; cnt = plr->damageCount; if(plr->powers[PT_STRENGTH]) { // Slowly fade the berzerk out. bzc = 12 - (plr->powers[PT_STRENGTH] >> 6); if(bzc > cnt) cnt = bzc; } if(cnt) { palette = (cnt + 7) >> 3; if(palette >= NUMREDPALS) palette = NUMREDPALS - 1; palette += STARTREDPALS; } else if(plr->bonusCount) { palette = (plr->bonusCount + 7) >> 3; if(palette >= NUMBONUSPALS) palette = NUMBONUSPALS - 1; palette += STARTBONUSPALS; } else if(plr->powers[PT_IRONFEET] > 4 * 32 || plr->powers[PT_IRONFEET] & 8) { palette = RADIATIONPAL; } // $democam if(palette) { plr->plr->flags |= DDPF_VIEW_FILTER; R_GetFilterColor(plr->plr->filterColor, palette); } else plr->plr->flags &= ~DDPF_VIEW_FILTER; } static void drawWidgets(hudstate_t* hud) { if(deathmatch) STlib_DrawNum(&hud->wFrags, hud->alpha); } void ST_doRefresh(int player) { hudstate_t* hud; if(player < 0 || player > MAXPLAYERS) return; hud = &hudStates[player]; hud->firstTime = false; drawWidgets(hud); } void ST_HUDSpriteSize(int sprite, int *w, int *h) { spriteinfo_t sprInfo; R_GetSpriteInfo(sprite, 0, &sprInfo); *w = sprInfo.width; *h = sprInfo.height; } void ST_drawHUDSprite(int sprite, float x, float y, hotloc_t hotspot, float scale, float alpha, boolean flip) { int w, h, w2, h2; float s, t; spriteinfo_t sprInfo; if(!(alpha > 0)) return; alpha = MINMAX_OF(0.f, alpha, 1.f); R_GetSpriteInfo(sprite, 0, &sprInfo); w = sprInfo.width; h = sprInfo.height; w2 = M_CeilPow2(w); h2 = M_CeilPow2(h); switch(hotspot) { case HOT_BRIGHT: y -= h * scale; case HOT_TRIGHT: x -= w * scale; break; case HOT_BLEFT: y -= h * scale; break; } DGL_SetPSprite(sprInfo.material); // Let's calculate texture coordinates. // To remove a possible edge artifact, move the corner a bit up/left. s = (w - 0.4f) / w2; t = (h - 0.4f) / h2; DGL_Color4f(1, 1, 1, alpha); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, flip * s, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, !flip * s, 0); DGL_Vertex2f(x + w * scale, y); DGL_TexCoord2f(0, !flip * s, t); DGL_Vertex2f(x + w * scale, y + h * scale); DGL_TexCoord2f(0, flip * s, t); DGL_Vertex2f(x, y + h * scale); DGL_End(); } void ST_doFullscreenStuff(int player) { static const int ammo_sprite[NUM_AMMO_TYPES] = { SPR_AMMO, SPR_SBOX, SPR_CELL, SPR_RCKT }; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; char buf[20]; int w, h, pos = 0, oldPos = 0, spr,i; int h_width = 320 / cfg.hudScale; int h_height = 200 / cfg.hudScale; float textalpha = hud->alpha - hud->hideAmount - ( 1 - cfg.hudColor[3]); float iconalpha = hud->alpha - hud->hideAmount - ( 1 - cfg.hudIconAlpha); textalpha = MINMAX_OF(0.f, textalpha, 1.f); iconalpha = MINMAX_OF(0.f, iconalpha, 1.f); if(IS_NETGAME && deathmatch && cfg.hudShown[HUD_FRAGS]) { // Display the frag counter. i = 199 - HUDBORDERY; if(cfg.hudShown[HUD_HEALTH]) { i -= 18 * cfg.hudScale; } sprintf(buf, "FRAGS:%i", hud->currentFragsCount); M_WriteText2(HUDBORDERX, i, buf, GF_FONTA, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textalpha); } // Setup the scaling matrix. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Scalef(cfg.hudScale, cfg.hudScale, 1); // Draw the visible HUD data, first health. if(cfg.hudShown[HUD_HEALTH]) { sprintf(buf, "HEALTH"); pos = M_StringWidth(buf, GF_FONTA)/2; M_WriteText2(HUDBORDERX, h_height - HUDBORDERY - M_StringHeight("A", GF_FONTA) - 4, buf, GF_FONTA, 1, 1, 1, iconalpha); sprintf(buf, "%i", plr->health); M_WriteText2(HUDBORDERX + pos - (M_StringWidth(buf, GF_FONTB)/2), h_height - HUDBORDERY, buf, GF_FONTB, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textalpha); oldPos = pos; pos = HUDBORDERX * 2 + M_StringWidth(buf, GF_FONTB); } // Keys | use a bit of extra scale. if(cfg.hudShown[HUD_KEYS]) { Draw_BeginZoom(0.75f, pos , h_height - HUDBORDERY); for(i = 0; i < 3; ++i) { spr = 0; if(plr-> keys[i == 0 ? KT_REDCARD : i == 1 ? KT_YELLOWCARD : KT_BLUECARD]) spr = i == 0 ? SPR_RKEY : i == 1 ? SPR_YKEY : SPR_BKEY; if(plr-> keys[i == 0 ? KT_REDSKULL : i == 1 ? KT_YELLOWSKULL : KT_BLUESKULL]) spr = i == 0 ? SPR_RSKU : i == 1 ? SPR_YSKU : SPR_BSKU; if(spr) { ST_drawHUDSprite(spr, pos, h_height - 2, HOT_BLEFT, 1, iconalpha, false); ST_HUDSpriteSize(spr, &w, &h); pos += w + 2; } } Draw_EndZoom(); } pos = oldPos; // Inventory if(cfg.hudShown[HUD_INVENTORY]) { if(P_InventoryCount(player, IIT_DEMONKEY1)) { spr = SPR_ART1; ST_HUDSpriteSize(spr, &w, &h); ST_drawHUDSprite(spr, HUDBORDERX + pos -w/2, h_height - 44, HOT_BLEFT, 1, iconalpha, false); } if(P_InventoryCount(player, IIT_DEMONKEY2)) { spr = SPR_ART2; ST_HUDSpriteSize(spr, &w, &h); ST_drawHUDSprite(spr, HUDBORDERX + pos -w/2, h_height - 84, HOT_BLEFT, 1, iconalpha, false); } if(P_InventoryCount(player, IIT_DEMONKEY3)) { spr = SPR_ART3; ST_HUDSpriteSize(spr, &w, &h); ST_drawHUDSprite(spr, HUDBORDERX + pos -w/2, h_height - 124, HOT_BLEFT, 1, iconalpha, false); } } if(cfg.hudShown[HUD_AMMO]) { ammotype_t ammotype; //// \todo Only supports one type of ammo per weapon. //// for each type of ammo this weapon takes. for(ammotype=0; ammotype < NUM_AMMO_TYPES; ++ammotype) { if(!weaponInfo[plr->readyWeapon][plr->class].mode[0].ammoType[ammotype]) continue; sprintf(buf, "%i", plr->ammo[ammotype]); pos = (h_width/2) - (M_StringWidth(buf, GF_FONTB)/2); M_WriteText2(pos, h_height - HUDBORDERY, buf, GF_FONTB, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textalpha); break; } } pos = h_width - 1; if(cfg.hudShown[HUD_ARMOR]) { sprintf(buf, "ARMOR"); w = M_StringWidth(buf, GF_FONTA); M_WriteText2(h_width - w - HUDBORDERX, h_height - HUDBORDERY - M_StringHeight("A", GF_FONTA) - 4, buf, GF_FONTA, 1, 1, 1, iconalpha); sprintf(buf, "%i", plr->armorPoints); M_WriteText2(h_width - (w/2) - (M_StringWidth(buf, GF_FONTB)/2) - HUDBORDERX, h_height - HUDBORDERY, buf, GF_FONTB, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textalpha); } DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } void ST_Drawer(int player, int fullscreenmode) { hudstate_t* hud; player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; hud = &hudStates[player]; hud->firstTime = hud->firstTime; hud->statusbarActive = (fullscreenmode < 2) || (AM_IsActive(AM_MapForPlayer(player)) && (cfg.automapHudDisplay == 0 || cfg.automapHudDisplay == 2)); // Do palette shifts. ST_doPaletteStuff(player); // Fade in/out the fullscreen HUD. if(hud->statusbarActive) { if(hud->alpha > 0.0f) { hud->statusbarActive = 0; hud->alpha-=0.1f; } } else { if(fullscreenmode == 3) { if(hud->alpha > 0.0f) { hud->alpha-=0.1f; fullscreenmode = 2; } } else { if(hud->alpha < 1.0f) hud->alpha += 0.1f; } } // Always try to render statusbar with alpha in fullscreen modes. if(fullscreenmode) hud->blended = 1; else hud->blended = 0; ST_doFullscreenStuff(player); } void ST_loadGraphics(void) { int i; char namebuf[9]; // Load the numbers, tall and short. for(i = 0; i < 10; ++i) { sprintf(namebuf, "STTNUM%d", i); R_CachePatch(&tallnum[i], namebuf); } } void ST_loadData(void) { ST_loadGraphics(); } static void initData(hudstate_t* hud) { int player = hud - hudStates; hud->firstTime = true; hud->statusbarActive = true; hud->blended = false; hud->stopped = true; hud->alpha = 0.f; ST_HUDUnHide(player, HUE_FORCE); } void ST_createWidgets(int player) { hudstate_t* hud = &hudStates[player]; // Frags sum. STlib_InitNum(&hud->wFrags, ST_FRAGSX, ST_FRAGSY, tallnum, &hud->currentFragsCount, ST_FRAGSWIDTH, 1); } void ST_Start(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(!hud->stopped) ST_Stop(player); initData(hud); ST_createWidgets(player); hud->stopped = false; } void ST_Stop(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(hud->stopped) return; hud->stopped = true; } void ST_Init(void) { ST_loadData(); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_inter.c0000644000175000017500000010704111357170242022426 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.c: Handling interactions (i.e., collisions). */ #ifdef MSVC # pragma optimize("g", off) #endif // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" #include "am_map.h" #include "d_net.h" #include "dmu_lib.h" #include "p_player.h" #include "p_map.h" #include "p_user.h" #include "p_tick.h" #include "p_actor.h" #include "p_inventory.h" #include "p_start.h" // MACROS ------------------------------------------------------------------ #define BONUSADD (6) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // A weapon is found with two clip loads, a big item has five clip loads. int maxAmmo[NUM_AMMO_TYPES] = { 200, 50, 300, 50 }; int clipAmmo[NUM_AMMO_TYPES] = { 10, 4, 20, 1 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * @param player Player to be given ammo. * @param ammo Type of ammo to be given. * @param num Number of clip loads, not the individual count. * * @return @c false, if the ammo can't be picked up at all. */ boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int num) { if(ammo == AT_NOAMMO) return false; if(ammo < 0 || ammo > NUM_AMMO_TYPES) Con_Error("P_GiveAmmo: bad type %i", ammo); if(!(player->ammo[ammo].owned < player->ammo[ammo].max)) return false; if(num) num *= clipAmmo[ammo]; else num = clipAmmo[ammo] / 2; if(gameSkill == SM_BABY) { // Give double ammo in trainer mode. num <<= 1; } // We are about to receive some more ammo. Does the player want to // change weapon automatically? P_MaybeChangeWeapon(player, WT_NOCHANGE, ammo, false); if(player->ammo[ammo].owned + num > player->ammo[ammo].max) player->ammo[ammo].owned = player->ammo[ammo].max; else player->ammo[ammo].owned += num; player->update |= PSF_AMMO; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_AMMO); return true; } /** * The weapon name may have a MF_DROPPED flag ored in. */ boolean P_GiveWeapon(player_t *player, weapontype_t weapon, boolean dropped) { ammotype_t i; boolean gaveAmmo = false; boolean gaveWeapon; int numClips; if(IS_NETGAME && (deathmatch != 2) && !dropped) { // leave placed weapons forever on net games if(player->weapons[weapon].owned) return false; player->bonusCount += BONUSADD; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. if(deathmatch) numClips = 5; else numClips = 2; if(P_GiveAmmo(player, i, numClips)) gaveAmmo = true; // At least ONE type of ammo was given. } // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, deathmatch == 1); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); S_ConsoleSound(SFX_WPNUP, NULL, player - players); return false; } else { // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. // Give one clip with a dropped weapon, two clips with a found // weapon. if(dropped) numClips = 1; else numClips = 2; if(P_GiveAmmo(player, i, numClips)) gaveAmmo = true; // At least ONE type of ammo was given. } if(player->weapons[weapon].owned) gaveWeapon = false; else { gaveWeapon = true; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false); } // Maybe unhide the HUD? if(gaveWeapon) ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); return (gaveWeapon || gaveAmmo); } } /** * Returns false if the body isn't needed at all */ boolean P_GiveBody(player_t *player, int num) { if(player->health >= maxHealth) return false; player->health += num; if(player->health > maxHealth) player->health = maxHealth; player->plr->mo->health = player->health; player->update |= PSF_HEALTH; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_HEALTH); return true; } /** * @return @c true, iff the armor was given. */ boolean P_GiveArmor(player_t* plr, int type, int points) { if(plr->armorPoints >= points) return false; // Don't pick up. P_PlayerSetArmorType(plr, type); P_PlayerGiveArmorBonus(plr, points - plr->armorPoints); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); return true; } void P_GiveKey(player_t* player, keytype_t card) { if(player->keys[card]) return; player->bonusCount = BONUSADD; player->keys[card] = 1; player->update |= PSF_KEYS; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_KEY); } /** * d64tc */ boolean P_GiveItem(player_t* player, inventoryitemtype_t item) { if(!P_InventoryGive(player - players, item, false)) return false; player->bonusCount = BONUSADD; return true; } void P_GiveBackpack(player_t *player) { int i; if(!player->backpack) { player->update |= PSF_MAX_AMMO; for(i = 0; i < NUM_AMMO_TYPES; ++i) player->ammo[i].max *= 2; player->backpack = true; } for(i = 0; i < NUM_AMMO_TYPES; ++i) P_GiveAmmo(player, i, 1); P_SetMessage(player, GOTBACKPACK, false); } boolean P_GivePower(player_t* player, int power) { player->update |= PSF_POWERS; switch(power) { case PT_INVULNERABILITY: player->powers[power] = INVULNTICS; break; case PT_INVISIBILITY: player->powers[power] = INVISTICS; player->plr->mo->flags |= MF_SHADOW;; break; case PT_FLIGHT: player->powers[power] = 1; player->plr->mo->flags2 |= MF2_FLY; player->plr->mo->flags |= MF_NOGRAVITY; if(player->plr->mo->pos[VZ] <= player->plr->mo->floorZ) { player->flyHeight = 10; // Thrust the player in the air a bit. player->plr->mo->flags |= DDPF_FIXMOM; } break; case PT_INFRARED: player->powers[power] = INFRATICS; break; case PT_IRONFEET: player->powers[power] = IRONTICS; break; case PT_STRENGTH: P_GiveBody(player, maxHealth); player->powers[power] = 1; break; default: if(player->powers[power]) return false; // Already got it. player->powers[power] = 1; break; } if(power == PT_ALLMAP) AM_RevealMap(AM_MapForPlayer(player - players), true); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_POWER); return true; } boolean P_TakePower(player_t* player, int power) { mobj_t* plrmo = player->plr->mo; player->update |= PSF_POWERS; if(player->powers[PT_FLIGHT]) { if(plrmo->pos[VZ] != plrmo->floorZ && cfg.lookSpring) { player->centering = true; } plrmo->flags2 &= ~MF2_FLY; plrmo->flags &= ~MF_NOGRAVITY; player->powers[power] = 0; return true; } if(!player->powers[power]) return false; // Don't got it. player->powers[power] = 0; return true; } typedef enum { IT_NONE = 0, IT_HEALTH_PACK, IT_HEALTH_KIT, IT_HEALTH_BONUS, IT_HEALTH_SOULSPHERE, IT_ARMOR_GREEN, IT_ARMOR_BLUE, IT_ARMOR_BONUS, IT_WEAPON_BFG, IT_WEAPON_CHAINGUN, IT_WEAPON_CHAINSAW, IT_WEAPON_RLAUNCHER, IT_WEAPON_PLASMARIFLE, IT_WEAPON_SHOTGUN, IT_WEAPON_SSHOTGUN, IT_WEAPON_LASERGUN, IT_AMMO_CLIP, IT_AMMO_CLIP_BOX, IT_AMMO_ROCKET, IT_AMMO_ROCKET_BOX, IT_AMMO_CELL, IT_AMMO_CELL_BOX, IT_AMMO_SHELL, IT_AMMO_SHELL_BOX, IT_KEY_BLUE, IT_KEY_YELLOW, IT_KEY_RED, IT_KEY_BLUESKULL, IT_KEY_YELLOWSKULL, IT_KEY_REDSKULL, IT_INVUL, IT_BESERK, IT_INVIS, IT_SUIT, IT_ALLMAP, IT_VISOR, IT_BACKPACK, IT_MEGASPHERE, IT_DEMONKEY1, IT_DEMONKEY2, IT_DEMONKEY3 } itemtype_t; static itemtype_t getItemTypeBySprite(spritetype_e sprite) { static const struct item_s { itemtype_t type; spritetype_e sprite; } items[] = { { IT_HEALTH_PACK, SPR_STIM }, { IT_HEALTH_KIT, SPR_MEDI }, { IT_HEALTH_BONUS, SPR_BON1 }, { IT_HEALTH_SOULSPHERE, SPR_SOUL }, { IT_ARMOR_GREEN, SPR_ARM1 }, { IT_ARMOR_BLUE, SPR_ARM2 }, { IT_ARMOR_BONUS, SPR_BON2 }, { IT_WEAPON_BFG, SPR_BFUG }, { IT_WEAPON_CHAINGUN, SPR_MGUN }, { IT_WEAPON_CHAINSAW, SPR_CSAW }, { IT_WEAPON_RLAUNCHER, SPR_LAUN }, { IT_WEAPON_PLASMARIFLE, SPR_PLSM }, { IT_WEAPON_SHOTGUN, SPR_SHOT }, { IT_WEAPON_SSHOTGUN, SPR_SGN2 }, { IT_WEAPON_LASERGUN, SPR_LSRG }, { IT_AMMO_CLIP, SPR_CLIP }, { IT_AMMO_CLIP_BOX, SPR_AMMO }, { IT_AMMO_ROCKET, SPR_RCKT }, { IT_AMMO_ROCKET_BOX, SPR_BROK }, { IT_AMMO_CELL, SPR_CELL }, { IT_AMMO_CELL_BOX, SPR_CELP }, { IT_AMMO_SHELL, SPR_SHEL }, { IT_AMMO_SHELL_BOX, SPR_SBOX }, { IT_KEY_BLUE, SPR_BKEY }, { IT_KEY_YELLOW, SPR_YKEY }, { IT_KEY_RED, SPR_RKEY }, { IT_KEY_BLUESKULL, SPR_BSKU }, { IT_KEY_YELLOWSKULL, SPR_YSKU }, { IT_KEY_REDSKULL, SPR_RSKU }, { IT_INVUL, SPR_PINV }, { IT_BESERK, SPR_PSTR }, { IT_INVIS, SPR_PINS }, { IT_SUIT, SPR_SUIT }, { IT_ALLMAP, SPR_PMAP }, { IT_VISOR, SPR_PVIS }, { IT_BACKPACK, SPR_BPAK }, { IT_MEGASPHERE, SPR_MEGA }, { IT_DEMONKEY1, SPR_ART1 }, { IT_DEMONKEY2, SPR_ART2 }, { IT_DEMONKEY3, SPR_ART3 }, { IT_NONE, 0 } }; uint i; for(i = 0; items[i].type != IT_NONE; ++i) if(items[i].sprite == sprite) return items[i].type; return IT_NONE; } /** * @param plr Player being given item. * @param item Type of item being given. * @param dropped @c true = the item was dropped by some entity. * * @return @c true iff the item should be destroyed. */ static boolean giveItem(player_t* plr, itemtype_t item, boolean dropped) { if(!plr) return false; switch(item) { case IT_ARMOR_GREEN: if(!P_GiveArmor(plr, armorClass[0], armorPoints[MINMAX_OF(0, armorClass[0] - 1, 1)])) return false; P_SetMessage(plr, GOTARMOR, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ARMOR_BLUE: if(!P_GiveArmor(plr, armorClass[1], armorPoints[MINMAX_OF(0, armorClass[1] - 1, 1)])) return false; P_SetMessage(plr, GOTMEGA, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ARMOR_BONUS: if(!plr->armorType) P_PlayerSetArmorType(plr, armorClass[0]); if(plr->armorPoints < armorPoints[1]) P_PlayerGiveArmorBonus(plr, 2); P_SetMessage(plr, GOTARMBONUS, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); break; case IT_HEALTH_BONUS: //plr->health++; // Can go over 100% plr->health += 2; // jd64 Can go over 100% if(plr->health > healthLimit) plr->health = healthLimit; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_SetMessage(plr, GOTHTHBONUS, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); break; case IT_HEALTH_SOULSPHERE: plr->health += soulSphereHealth; if(plr->health > soulSphereLimit) plr->health = soulSphereLimit; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_SetMessage(plr, GOTSUPER, false); S_ConsoleSound(SFX_GETPOW, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); break; case IT_MEGASPHERE: if(gameMode != commercial) return false; plr->health = megaSphereHealth; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_GiveArmor(plr, armorClass[1], armorPoints[MINMAX_OF(0, armorClass[1] - 1, 1)]); P_SetMessage(plr, GOTMSPHERE, false); S_ConsoleSound(SFX_GETPOW, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); break; case IT_KEY_BLUE: if(!plr->keys[KT_BLUECARD]) P_SetMessage(plr, GOTBLUECARD, false); P_GiveKey(plr, KT_BLUECARD); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_YELLOW: if(!plr->keys[KT_YELLOWCARD]) P_SetMessage(plr, GOTYELWCARD, false); P_GiveKey(plr, KT_YELLOWCARD); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_RED: if(!plr->keys[KT_REDCARD]) P_SetMessage(plr, GOTREDCARD, false); P_GiveKey(plr, KT_REDCARD); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_BLUESKULL: if(!plr->keys[KT_BLUESKULL]) P_SetMessage(plr, GOTBLUESKUL, false); P_GiveKey(plr, KT_BLUESKULL); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_YELLOWSKULL: if(!plr->keys[KT_YELLOWSKULL]) P_SetMessage(plr, GOTYELWSKUL, false); P_GiveKey(plr, KT_YELLOWSKULL); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_REDSKULL: if(!plr->keys[KT_REDSKULL]) P_SetMessage(plr, GOTREDSKULL, false); P_GiveKey(plr, KT_REDSKULL); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_HEALTH_PACK: if(!P_GiveBody(plr, 10)) return false; P_SetMessage(plr, GOTSTIM, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_HEALTH_KIT: { int oldHealth = plr->health; /** * DOOM bug: * The following test was originaly placed AFTER the call to * P_GiveBody thereby making the first outcome impossible as * the medikit gives 25 points of health. This resulted that * the GOTMEDINEED "Picked up a medikit that you REALLY need" * was never used. */ if(!P_GiveBody(plr, 25)) return false; P_SetMessage(plr, GET_TXT((oldHealth < 25)? TXT_GOTMEDINEED : TXT_GOTMEDIKIT), false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; } case IT_INVUL: if(!P_GivePower(plr, PT_INVULNERABILITY)) return false; P_SetMessage(plr, GOTINVUL, false); S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_BESERK: if(!P_GivePower(plr, PT_STRENGTH)) return false; P_SetMessage(plr, GOTBERSERK, false); if(plr->readyWeapon != WT_FIRST && cfg.berserkAutoSwitch) { plr->pendingWeapon = WT_FIRST; plr->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; } S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_INVIS: if(!P_GivePower(plr, PT_INVISIBILITY)) return false; P_SetMessage(plr, GOTINVIS, false); S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_SUIT: if(!P_GivePower(plr, PT_IRONFEET)) return false; P_SetMessage(plr, GOTSUIT, false); S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_ALLMAP: if(!P_GivePower(plr, PT_ALLMAP)) return false; P_SetMessage(plr, GOTMAP, false); S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_VISOR: if(!P_GivePower(plr, PT_INFRARED)) return false; P_SetMessage(plr, GOTVISOR, false); S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_AMMO_CLIP: if(!P_GiveAmmo(plr, AT_CLIP, dropped? 0 : 1)) return false; P_SetMessage(plr, GOTCLIP, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CLIP_BOX: if(!P_GiveAmmo(plr, AT_CLIP, 5)) return false; P_SetMessage(plr, GOTCLIPBOX, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_ROCKET: if(!P_GiveAmmo(plr, AT_MISSILE, 1)) return false; P_SetMessage(plr, GOTROCKET, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_ROCKET_BOX: if(!P_GiveAmmo(plr, AT_MISSILE, 5)) return false; P_SetMessage(plr, GOTROCKBOX, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CELL: if(!P_GiveAmmo(plr, AT_CELL, 1)) return false; P_SetMessage(plr, GOTCELL, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CELL_BOX: if(!P_GiveAmmo(plr, AT_CELL, 5)) return false; P_SetMessage(plr, GOTCELLBOX, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SHELL: if(!P_GiveAmmo(plr, AT_SHELL, 1)) return false; P_SetMessage(plr, GOTSHELLS, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SHELL_BOX: if(!P_GiveAmmo(plr, AT_SHELL, 5)) return false; P_SetMessage(plr, GOTSHELLBOX, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_BACKPACK: P_GiveBackpack(plr); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_WEAPON_BFG: if(!P_GiveWeapon(plr, WT_SEVENTH, dropped)) return false; P_SetMessage(plr, GOTBFG9000, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_CHAINGUN: if(!P_GiveWeapon(plr, WT_FOURTH, dropped)) return false; P_SetMessage(plr, GOTCHAINGUN, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_CHAINSAW: if(!P_GiveWeapon(plr, WT_EIGHTH, dropped)) return false; P_SetMessage(plr, GOTCHAINSAW, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_RLAUNCHER: if(!P_GiveWeapon(plr, WT_FIFTH, dropped)) return false; P_SetMessage(plr, GOTLAUNCHER, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_PLASMARIFLE: if(!P_GiveWeapon(plr, WT_SIXTH, dropped)) return false; P_SetMessage(plr, GOTPLASMA, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_SHOTGUN: if(!P_GiveWeapon(plr, WT_THIRD, dropped)) return false; P_SetMessage(plr, GOTSHOTGUN, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_SSHOTGUN: if(!P_GiveWeapon(plr, WT_NINETH, dropped)) return false; P_SetMessage(plr, GOTSHOTGUN2, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_LASERGUN: if(!P_GiveWeapon(plr, WT_TENTH, dropped)) return false; P_SetMessage(plr, GOTUNMAKER, false); S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_DEMONKEY1: if(P_InventoryCount(plr - players, IIT_DEMONKEY1)) { if(!(mapTime & 0x1f)) P_SetMessage(plr, NGOTPOWERUP1, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); return false; //Don't destroy item, can be collected later by other players. } else { P_GiveItem(plr, IIT_DEMONKEY1); P_SetMessage(plr, GOTPOWERUP1, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } break; case IT_DEMONKEY2: if(P_InventoryCount(plr - players, IIT_DEMONKEY2)) { if(!(mapTime & 0x1f)) P_SetMessage(plr, NGOTPOWERUP2, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); return false; //Don't destroy item, can be collected later by other players. } else { P_GiveItem(plr, IIT_DEMONKEY2); P_SetMessage(plr, GOTPOWERUP2, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } break; case IT_DEMONKEY3: if(P_InventoryCount(plr - players, IIT_DEMONKEY3)) { if(!(mapTime & 0x1f)) P_SetMessage(plr, NGOTPOWERUP3, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); return false; //Don't destroy item, can be collected later by other players. } else { P_GiveItem(plr, IIT_DEMONKEY3); P_SetMessage(plr, GOTPOWERUP3, false); S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); } break; default: Con_Error("giveItem: Unknown item %i.", (int) item); } return true; } void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) { player_t* player; float delta; itemtype_t item; delta = special->pos[VZ] - toucher->pos[VZ]; if(delta > toucher->height || delta < -8) { // Out of reach. return; } // Dead thing touching (can happen with a sliding player corpse). if(toucher->health <= 0) return; player = toucher->player; // Identify by sprite. if((item = getItemTypeBySprite(special->sprite)) != IT_NONE) { if(!giveItem(player, item, (special->flags & MF_DROPPED)? true : false)) return; // Don't destroy the item. } else { Con_Message("P_TouchSpecialMobj: Unknown gettable thing %i.\n", (int) special->type); } if(special->flags & MF_COUNTITEM) player->itemCount++; P_MobjRemove(special, false); player->bonusCount += BONUSADD; } void P_KillMobj(mobj_t *source, mobj_t *target, boolean stomping) { mobjtype_t item; mobj_t* mo; unsigned int an; angle_t angle; statenum_t state; if(!target) // nothing to kill return; target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY); if(target->type != MT_SKULL) target->flags &= ~MF_NOGRAVITY; target->flags |= MF_CORPSE | MF_DROPOFF; target->flags2 &= ~MF2_PASSMOBJ; target->corpseTics = 0; // target->height >>= 2; // jd64 if(source && source->player) { // Count for intermission. if(target->flags & MF_COUNTKILL) source->player->killCount++; if(target->player) { source->player->frags[target->player - players]++; NetSv_FragsForAll(source->player); NetSv_KillMessage(source->player, target->player, stomping); } } else if(!IS_NETGAME && (target->flags & MF_COUNTKILL)) { // Count all monster deaths, even those caused by other monsters. players[0].killCount++; } if(target->player) { // Count environment kills against the player. if(!source) { target->player->frags[target->player - players]++; NetSv_FragsForAll(target->player); NetSv_KillMessage(target->player, target->player, stomping); } target->flags &= ~MF_SOLID; target->flags2 &= ~MF2_FLY; target->player->powers[PT_FLIGHT] = 0; target->player->playerState = PST_DEAD; target->player->rebornWait = PLAYER_REBORN_TICS; target->player->update |= PSF_STATE; target->player->plr->flags |= DDPF_DEAD; P_DropWeapon(target->player); // Don't die with the automap open. AM_Open(AM_MapForPlayer(target->player - players), false, false); } if((state = P_GetState(target->type, SN_XDEATH)) != S_NULL && target->health < -target->info->spawnHealth) { // Extreme death. P_MobjChangeState(target, state); } else { // Normal death. P_MobjChangeState(target, P_GetState(target->type, SN_DEATH)); } target->tics -= P_Random() & 3; if(target->tics < 1) target->tics = 1; // Drop stuff. // This determines the kind of object spawned during the death frame // of a thing. switch(target->type) { case MT_POSSESSED: //case MT_TROOP: // jd64 item = MT_CLIP; break; case MT_SHOTGUY: item = MT_SHOTGUN; break; default: return; } // Don't drop at the exact same place, causes Z flickering with // 3D sprites. angle = P_Random() << 24; an = angle >> ANGLETOFINESHIFT; if((mo = P_SpawnMobj3f(item, target->pos[VX] + 3 * FIX2FLT(finecosine[an]), target->pos[VY] + 3 * FIX2FLT(finesine[an]), 0, angle, MSF_Z_FLOOR))) { mo->flags |= MF_DROPPED; // Special versions of items. } } /** * Damages both enemies and players * Source and inflictor are the same for melee attacks. * Source can be NULL for slime, barrel explosions * and other environmental stuff. * * @param inflictor Mobj that caused the damage creature or missile, * can be NULL (slime, etc). * @param source Mobj to target after taking damage, creature or NULL. * * @return Actual amount of damage done. */ int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damageP, boolean stomping) { // Follow a player exlusively for 3 seconds. #define BASETHRESHOLD (100) uint an; angle_t angle; int saved; player_t* player; float thrust; int temp; int originalHealth; // The actual damage (== damageP * netMobDamageModifier for any // non-player mobj). int damage = damageP; if(!target) return 0; // Wha? originalHealth = target->health; // Clients can't harm anybody. if(IS_CLIENT) return 0; if(!(target->flags & MF_SHOOTABLE)) return 0; // Shouldn't happen... if(target->health <= 0) return 0; // Player specific. if(target->player) { // Check if player-player damage is disabled. if(source && source->player && source->player != target->player) { // Co-op damage disabled? if(IS_NETGAME && !deathmatch && cfg.noCoopDamage) return 0; // Same color, no damage? if(cfg.noTeamDamage && cfg.playerColor[target->player - players] == cfg.playerColor[source->player - players]) return 0; } } if(target->flags & MF_SKULLFLY) { target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0; } player = target->player; if(player && gameSkill == SM_BABY) damage >>= 1; // take half damage in trainer mode // jd64 > #if 0 if(inflictor && inflictor->type == MT_FIREEND) { // Special for Motherdemon attack #if 0 /** DJS - This was originally in a sub routine called P_TouchMotherFire * but due to the fact that @c player, was not initialized * this likely does not work the way kaiser expected it to. * What would actually happen is not certain but I would guess it * would most likely simply return without doing anything at all. * \todo SHOULD this be fixed? Or is something implemented elsewhere * which does what this was attempting to do? */ int damage; player_t *player; if(player = target->player) { damage = ((P_Random() % 10) + 1) * 8; P_DamageMobj(target, NULL, NULL, damage); player->plr->mo->momz = 16; player->jumpTics = 24; } #endif return; } #endif // < d64tc // Use the cvar damage multiplier netMobDamageModifier only if the // inflictor is not a player. if(inflictor && !inflictor->player && (!source || (source && !source->player))) { // damage = (int) ((float) damage * netMobDamageModifier); if(IS_NETGAME) damage *= cfg.netMobDamageModifier; } // Some close combat weapons should not inflict thrust and push the // victim out of reach, thus kick away unless using the chainsaw. if(inflictor && !(target->flags & MF_NOCLIP) && (!source || !source->player || source->player->readyWeapon != WT_EIGHTH) && !(inflictor->flags2 & MF2_NODMGTHRUST)) { angle = R_PointToAngle2(inflictor->pos[VX], inflictor->pos[VY], target->pos[VX], target->pos[VY]); thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass); // Make fall forwards sometimes. if(damage < 40 && damage > target->health && target->pos[VZ] - inflictor->pos[VZ] > 64 && (P_Random() & 1)) { angle += ANG180; thrust *= 4; } an = angle >> ANGLETOFINESHIFT; target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); if(target->dPlayer) { // Only fix momentum. Otherwise clients will find it difficult // to escape from the damage inflictor. target->dPlayer->flags |= DDPF_FIXMOM; } // $dropoff_fix: thrust objects hanging off ledges. if(target->intFlags & MIF_FALLING && target->gear >= MAXGEAR) target->gear = 0; } // Player specific. if(player) { // End of game hell hack. if(P_ToXSectorOfSubsector(target->subsector)->special == 11 && damage >= target->health) { damage = target->health - 1; } // Below certain threshold, ignore damage in GOD mode, or with // INVUL power. if(damage < 1000 && ((P_GetPlayerCheats(player) & CF_GODMODE) || player->powers[PT_INVULNERABILITY])) { return 0; } if(player->armorType) { if(player->armorType == 1) saved = damage / 3; else saved = damage / 2; if(player->armorPoints <= saved) { // Armor is used up. saved = player->armorPoints; player->armorType = 0; } player->armorPoints -= saved; player->update |= PSF_ARMOR_POINTS; damage -= saved; } player->health -= damage; if(player->health < 0) player->health = 0; player->update |= PSF_HEALTH; player->attacker = source; player->damageCount += damage; // Add damage after armor / invuln. if(player->damageCount > 100) player->damageCount = 100; // Teleport stomp does 10k points... temp = damage < 100 ? damage : 100; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_DAMAGE); } // How about some particles, yes? // Only works when both target and inflictor are real mobjs. P_SpawnDamageParticleGen(target, inflictor, damage); // Do the damage. target->health -= damage; if(target->health > 0) { // Still alive, phew! if((P_Random() < target->info->painChance) && !(target->flags & MF_SKULLFLY)) { statenum_t state; target->flags |= MF_JUSTHIT; // Fight back! if((state = P_GetState(target->type, SN_PAIN)) != S_NULL) P_MobjChangeState(target, state); } target->reactionTime = 0; // We're awake now... if(source && (!target->threshold && !(source->flags3 & MF3_NOINFIGHT)) && source != target) { statenum_t state; // If not intent on another player, chase after this one. target->target = source; target->threshold = BASETHRESHOLD; if((state = P_GetState(target->type, SN_SEE)) != S_NULL && target->state == &STATES[P_GetState(target->type, SN_SPAWN)]) P_MobjChangeState(target, state); } } else { P_KillMobj(source, target, stomping); } return originalHealth - target->health; #undef BASETHRESHOLD } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_pspr.c0000644000175000017500000005364611357170242022304 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.c: Weapon sprite animation, weapon objects. * * Action functions for weapons. */ #ifdef MSVC // Sumtin' 'ere messes with poor ol' MSVC's head... # pragma optimize("g",off) #endif // HEADER FILES ------------------------------------------------------------ #include #include #include #include "jdoom64.h" #include "d_net.h" #include "p_player.h" #include "p_map.h" #include "p_tick.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ #define LOWERSPEED 6 #define RAISESPEED 6 #define WEAPONBOTTOM 128 #define WEAPONTOP 32 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static float swing[2]; static float bulletSlope; // CODE -------------------------------------------------------------------- void R_GetWeaponBob(int player, float* x, float* y) { if(x) { *x = 1 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finecosine[(128 * mapTime) & FINEMASK]); } if(y) { *y = 32 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finesine[(128 * mapTime) & FINEMASK & (FINEANGLES / 2 - 1)]); } } void P_SetPsprite(player_t *player, int position, statenum_t stnum) { pspdef_t *psp; state_t *state; psp = &player->pSprites[position]; do { if(!stnum) { // Object removed itself. psp->state = NULL; break; } state = &STATES[stnum]; psp->state = state; psp->tics = state->tics; // Could be 0. if(state->misc[0]) { // Coordinate set. psp->pos[VX] = (float) state->misc[0]; psp->pos[VY] = (float) state->misc[1]; } // Call action routine. // Modified handling. if(state->action) { state->action(player, psp); if(!psp->state) break; } stnum = psp->state->nextState; } while(!psp->tics); // An initial state of 0 could cycle through. } /** * Starts bringing the pending weapon up from the bottom of the screen. */ void P_BringUpWeapon(player_t *player) { weaponmodeinfo_t *wminfo; wminfo = WEAPON_INFO(player->pendingWeapon, player->class, 0); if(player->pendingWeapon == WT_NOCHANGE) player->pendingWeapon = player->readyWeapon; if(wminfo->raiseSound) S_StartSoundEx(wminfo->raiseSound, player->plr->mo); player->pendingWeapon = WT_NOCHANGE; player->pSprites[ps_weapon].pos[VY] = WEAPONBOTTOM; P_SetPsprite(player, ps_weapon, wminfo->states[WSN_UP]); } void P_FireWeapon(player_t *player) { statenum_t newstate; if(!P_CheckAmmo(player)) return; // Psprite state. player->plr->pSprites[0].state = DDPSP_FIRE; P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackState); newstate = weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_ATTACK]; P_SetPsprite(player, ps_weapon, newstate); NetSv_PSpriteChange(player - players, newstate); P_NoiseAlert(player->plr->mo, player->plr->mo); } /** * Player died, so put the weapon away. */ void P_DropWeapon(player_t *player) { P_SetPsprite(player, ps_weapon, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_DOWN]); } /** * The player can fire the weapon or change to another weapon at this time. * Follows after getting weapon up, or after previous attack/fire sequence. */ void C_DECL A_WeaponReady(player_t* player, pspdef_t* psp) { weaponmodeinfo_t* wminfo; // Enable the pspr Y offset (might be disabled in A_Lower). DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); // Get out of attack state. if(player->plr->mo->state == &STATES[PCLASS_INFO(player->class)->attackState] || player->plr->mo->state == &STATES[PCLASS_INFO(player->class)->attackEndState]) { P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->normalState); } if(player->readyWeapon != WT_NOCHANGE) { wminfo = WEAPON_INFO(player->readyWeapon, player->class, 0); // A weaponready sound? if(psp->state == &STATES[wminfo->states[WSN_READY]] && wminfo->readySound) S_StartSound(wminfo->readySound, player->plr->mo); // Check for change. If player is dead, put the weapon away. if(player->pendingWeapon != WT_NOCHANGE || !player->health) { // (pending weapon should allready be validated) P_SetPsprite(player, ps_weapon, wminfo->states[WSN_DOWN]); return; } } // Check for autofire. if(player->brain.attack) { wminfo = WEAPON_INFO(player->readyWeapon, player->class, 0); if(!player->attackDown || wminfo->autoFire) { player->attackDown = true; P_FireWeapon(player); return; } } else player->attackDown = false; // Bob the weapon based on movement speed. R_GetWeaponBob(player - players, &psp->pos[0], &psp->pos[1]); // Psprite state. player->plr->pSprites[0].state = DDPSP_BOBBING; } /** * The player can re-fire the weapon without lowering it entirely. */ void C_DECL A_ReFire(player_t *player, pspdef_t *psp) { // Check for fire (if a weaponchange is pending, let it go through // instead). if((player->brain.attack) && player->pendingWeapon == WT_NOCHANGE && player->health) { player->refire++; P_FireWeapon(player); } else { player->refire = 0; P_CheckAmmo(player); } } void C_DECL A_CheckReload(player_t *player, pspdef_t *psp) { P_CheckAmmo(player); } /** * Lowers current weapon, and changes weapon at bottom. */ void C_DECL A_Lower(player_t *player, pspdef_t *psp) { psp->pos[VY] += LOWERSPEED; // Psprite state. player->plr->pSprites[0].state = DDPSP_DOWN; // Should we disable the lowering? if(!cfg.bobWeaponLower || weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 0); } // Is already down. if(psp->pos[VY] < WEAPONBOTTOM) return; // Player is dead. if(player->playerState == PST_DEAD) { psp->pos[VY] = WEAPONBOTTOM; // Don't bring weapon back up. return; } if(player->readyWeapon == WT_SIXTH) // jd64 P_SetPsprite(player, ps_flash, S_NULL); // The old weapon has been lowered off the screen, so change the weapon // and start raising it. if(!player->health) { // Player is dead, so keep the weapon off screen. P_SetPsprite(player, ps_weapon, S_NULL); return; } player->readyWeapon = player->pendingWeapon; player->update |= PSF_READY_WEAPON; // Should we suddenly lower the weapon? if(cfg.bobWeaponLower && !weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); } P_BringUpWeapon(player); } void C_DECL A_Raise(player_t *player, pspdef_t *psp) { statenum_t newstate; // Psprite state. player->plr->pSprites[0].state = DDPSP_UP; // Should we disable the lowering? if(!cfg.bobWeaponLower || weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 0); } P_SetPsprite(player, ps_flash, S_NULL); psp->pos[VY] -= RAISESPEED; if(psp->pos[VY] > WEAPONTOP) return; // Enable the pspr Y offset once again. DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); psp->pos[VY] = WEAPONTOP; // The weapon has been raised all the way, so change to the ready state. newstate = weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_READY]; P_SetPsprite(player, ps_weapon, newstate); } void C_DECL A_PlasmaShock(player_t* pl, pspdef_t* psp) { S_StartSound(SFX_PSIDL, pl->plr->mo); P_SetPsprite(pl, ps_flash, S_PLASMASHOCK1); } void C_DECL A_GunFlash(player_t *player, pspdef_t *psp) { P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); } void C_DECL A_Punch(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; damage = (P_Random() % 10 + 1) * 2; if(player->powers[PT_STRENGTH]) damage *= 10; angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; slope = P_AimLineAttack(player->plr->mo, angle, PLRMELEERANGE); P_LineAttack(player->plr->mo, angle, PLRMELEERANGE, slope, damage); // Turn to face target. if(lineTarget) { S_StartSound(SFX_PUNCH, player->plr->mo); player->plr->mo->angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); player->plr->flags |= DDPF_FIXANGLES; } } void C_DECL A_Saw(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; damage = (float) (P_Random() % 10 + 1) * 2; angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; // Use meleerange + 1 so the puff doesn't skip the flash. slope = P_AimLineAttack(player->plr->mo, angle, PLRMELEERANGE + 1); P_LineAttack(player->plr->mo, angle, PLRMELEERANGE + 1, slope, damage); if(!lineTarget) { S_StartSound(SFX_SAWFUL, player->plr->mo); return; } S_StartSound(SFX_SAWHIT, player->plr->mo); // Turn to face target. angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); if(angle - player->plr->mo->angle > ANG180) { if(angle - player->plr->mo->angle < -ANG90 / 32) // jd64 was "/ 20" player->plr->mo->angle = angle + ANG90 / 32; // jd64 was "/ 21" else player->plr->mo->angle -= ANG90 / 20; } else { if(angle - player->plr->mo->angle > ANG90 / 32) // jd64 was "/ 20" player->plr->mo->angle = angle - ANG90 / 32; // jd64 was "/ 21" else player->plr->mo->angle += ANG90 / 20; } player->plr->mo->flags |= MF_JUSTATTACKED; } void C_DECL A_FireMissile(player_t *player, pspdef_t *psp) { P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_SpawnMissile(MT_ROCKET, player->plr->mo, NULL); // jd64 > if(cfg.weaponRecoil) { angle_t angle = player->plr->mo->angle + ANG180; uint an = angle >> ANGLETOFINESHIFT; player->plr->mo->mom[MX] += 4 * FIX2FLT(finecosine[an]); player->plr->mo->mom[MY] += 4 * FIX2FLT(finesine[an]); } // < d64tc } void C_DECL A_FireBFG(player_t* player, pspdef_t* psp) { P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_SpawnMissile(MT_BFG, player->plr->mo, NULL); } void C_DECL A_FirePlasma(player_t* player, pspdef_t* psp) { P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH] + (P_Random() & 1)); //P_SetPsprite(player, ps_flash, S_NULL); // jd64 wha? player->update |= PSF_AMMO; if(IS_CLIENT) return; P_SpawnMissile(MT_PLASMA, player->plr->mo, NULL); } /** * d64tc */ void C_DECL A_FireSingleLaser(player_t *player, pspdef_t *psp) { int plrNum = player - players; mobj_t* pmo; short laserPower; P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); player->update |= PSF_AMMO; if(IS_CLIENT) return; pmo = player->plr->mo; laserPower = 0; if(P_InventoryCount(plrNum, IIT_DEMONKEY1)) laserPower++; if(P_InventoryCount(plrNum, IIT_DEMONKEY2)) laserPower++; if(P_InventoryCount(plrNum, IIT_DEMONKEY3)) laserPower++; switch(laserPower) { case 0: P_SpawnMissile(MT_LASERSHOTWEAK, player->plr->mo, NULL); break; case 1: P_SpawnMissile(MT_LASERSHOT, player->plr->mo, NULL); break; case 2: P_SPMAngle(MT_LASERSHOT, pmo, pmo->angle - (ANG45 / 8)); P_SPMAngle(MT_LASERSHOT, pmo, pmo->angle + (ANG45 / 8)); break; case 3: P_SpawnMissile(MT_LASERSHOT, pmo, NULL); P_SPMAngle(MT_LASERSHOT, pmo, pmo->angle - (ANG45 / 6)); P_SPMAngle(MT_LASERSHOT, pmo, pmo->angle + (ANG45 / 6)); break; } } /** * d64tc */ static void fireDoubleLaser(player_t* player, pspdef_t* psp, angle_t angleDelta) { mobj_t* pmo; P_ShotAmmo(player); pmo = player->plr->mo; player->update |= PSF_AMMO; if(IS_CLIENT) return; P_SpawnMissile(MT_LASERSHOT, pmo, NULL); P_SPMAngle(MT_LASERSHOT, pmo, pmo->angle - angleDelta); P_SPMAngle(MT_LASERSHOT, pmo, pmo->angle + angleDelta); } /** * d64tc */ void C_DECL A_FireDoubleLaser(player_t *player, pspdef_t *psp) { fireDoubleLaser(player, psp, ANG45 / 8); } /** * d64tc */ void C_DECL A_FireDoubleLaser1(player_t *player, pspdef_t *psp) { fireDoubleLaser(player, psp, ANG45 / 4); } /** * d64tc */ void C_DECL A_FireDoubleLaser2(player_t *player, pspdef_t *psp) { fireDoubleLaser(player, psp, ANG45 / 3); } /** * Sets a slope so a near miss is at aproximately the height of the * intended target. */ void P_BulletSlope(mobj_t *mo) { angle_t angle; // See which target is to be aimed at. angle = mo->angle; bulletSlope = P_AimLineAttack(mo, angle, 16 * 64); if(!cfg.noAutoAim) { if(!lineTarget) { angle += 1 << 26; bulletSlope = P_AimLineAttack(mo, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; bulletSlope = P_AimLineAttack(mo, angle, 16 * 64); } if(!lineTarget) { angle += 2 << 26; bulletSlope = tan(LOOKDIR2RAD(mo->dPlayer->lookDir)) / 1.2; } } } } void P_GunShot(mobj_t *mo, boolean accurate) { angle_t angle; int damage; damage = 5 * (P_Random() % 3 + 1); angle = mo->angle; if(!accurate) angle += (P_Random() - P_Random()) << 18; P_LineAttack(mo, angle, MISSILERANGE, bulletSlope, damage); } void C_DECL A_FirePistol(player_t *player, pspdef_t *psp) { S_StartSound(SFX_PISTOL, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_BulletSlope(player->plr->mo); P_GunShot(player->plr->mo, !player->refire); } void C_DECL A_FireShotgun(player_t *player, pspdef_t *psp) { int i; S_StartSound(SFX_SHOTGN, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_BulletSlope(player->plr->mo); for(i = 0; i < 7; ++i) P_GunShot(player->plr->mo, false); } void C_DECL A_FireShotgun2(player_t *player, pspdef_t *psp) { int i; angle_t angle; int damage; S_StartSound(SFX_DSHTGN, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_BulletSlope(player->plr->mo); // jd64 > if(cfg.weaponRecoil) { uint an; player->plr->mo->angle += ANG90/90; an = (player->plr->mo->angle + ANG180) >> ANGLETOFINESHIFT; player->plr->mo->mom[MX] += 4 * FIX2FLT(finecosine[an]); player->plr->mo->mom[MY] += 4 * FIX2FLT(finesine[an]); } // < d64tc for(i = 0; i < 20; ++i) { damage = 5 * (P_Random() % 3 + 1); angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 19; P_LineAttack(player->plr->mo, angle, MISSILERANGE, bulletSlope + FIX2FLT((P_Random() - P_Random()) << 5), damage); } } void C_DECL A_OpenShotgun2(player_t *player, pspdef_t *psp) { S_StartSound(SFX_DBOPN, player->plr->mo); } void C_DECL A_LoadShotgun2(player_t *player, pspdef_t *psp) { S_StartSound(SFX_DBLOAD, player->plr->mo); } void C_DECL A_FireCGun(player_t *player, pspdef_t *psp) { S_StartSound(SFX_PISTOL, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH] + psp->state - &STATES[S_CHAIN1]); player->update |= PSF_AMMO; if(IS_CLIENT) return; psp->pos[VY] = WEAPONTOP + FIX2FLT((P_Random() & 8) - 2); // jd64 P_BulletSlope(player->plr->mo); // jd64 > if(cfg.weaponRecoil) { // Nice little recoil effect. player->plr->mo->angle += ANG90/256; } // < d64tc P_GunShot(player->plr->mo, !player->refire); } void C_DECL A_Light0(player_t *player, pspdef_t *psp) { player->plr->extraLight = 0; } void C_DECL A_Light1(player_t *player, pspdef_t *psp) { player->plr->extraLight = 1; } void C_DECL A_Light2(player_t *player, pspdef_t *psp) { player->plr->extraLight = 2; } /** * Spawn a BFG explosion on every monster in view. */ void C_DECL A_BFGSpray(mobj_t *mo) { int i, j, damage; angle_t angle; // Offset angles from its attack angle. for(i = 0; i < 40; ++i) { angle = mo->angle - ANG90 / 2 + ANG90 / 40 * i; // mo->target is the originator (player) of the missile. P_AimLineAttack(mo->target, angle, 16 * 64); if(!lineTarget) continue; P_SpawnMobj3f(MT_EXTRABFG, lineTarget->pos[VX], lineTarget->pos[VY], lineTarget->pos[VZ] + lineTarget->height / 4, angle + ANG180, 0); damage = 0; for(j = 0; j < 15; ++j) damage += (P_Random() & 7) + 1; P_DamageMobj(lineTarget, mo->target, mo->target, damage, false); } } void C_DECL A_BFGsound(player_t *player, pspdef_t *psp) { S_StartSound(SFX_BFG, player->plr->mo); } /** * Called at start of level for each player. */ void P_SetupPsprites(player_t* player) { int i; // Remove all psprites. for(i = 0; i < NUMPSPRITES; ++i) player->pSprites[i].state = NULL; // Spawn the gun. if(player->pendingWeapon == WT_NOCHANGE) player->pendingWeapon = player->readyWeapon; P_BringUpWeapon(player); } /** * Called every tic by player thinking routine. */ void P_MovePsprites(player_t *player) { int i; pspdef_t *psp; state_t *state; psp = &player->pSprites[0]; for(i = 0; i < NUMPSPRITES; ++i, psp++) { // A null state means not active. state = psp->state; if(state) { // Decrease tic count and possibly change state. // A -1 tic count never changes. if(psp->tics != -1) { psp->tics--; if(!psp->tics) P_SetPsprite(player, i, psp->state->nextState); } } } player->pSprites[ps_flash].pos[VX] = player->pSprites[ps_weapon].pos[VX]; player->pSprites[ps_flash].pos[VY] = player->pSprites[ps_weapon].pos[VY]; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/m_cheat.c0000644000175000017500000003754611357170242022402 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_cheat.c: Cheat sequence checking. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom64.h" #include "f_infine.h" #include "d_net.h" #include "g_common.h" #include "p_player.h" #include "am_map.h" #include "hu_menu.h" #include "hu_msg.h" #include "dmu_lib.h" #include "p_user.h" #include "p_start.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { unsigned char* sequence; size_t length, pos; int args[2]; int currentArg; } cheatseq_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void Cht_LaserFunc(player_t* p); void Cht_GodFunc(player_t* plr); void Cht_GiveWeaponsFunc(player_t* plr); void Cht_GiveAmmoFunc(player_t* plr); void Cht_GiveKeysFunc(player_t* plr); void Cht_NoClipFunc(player_t* plr); void Cht_GiveArmorFunc(player_t* plr); boolean Cht_WarpFunc(player_t* plr, cheatseq_t* cheat); boolean Cht_PowerUpFunc(player_t* plr, cheatseq_t* cheat); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static boolean cheatsEnabled(void) { return !IS_NETGAME; } void Cht_GodFunc(player_t* plr) { plr->cheats ^= CF_GODMODE; plr->update |= PSF_STATE; if(P_GetPlayerCheats(plr) & CF_GODMODE) { if(plr->plr->mo) plr->plr->mo->health = maxHealth; plr->health = godModeHealth; plr->update |= PSF_HEALTH; } P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_GODMODE) ? STSTR_DQDON : STSTR_DQDOFF), false); } void Cht_SuicideFunc(player_t* plr) { P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); } void Cht_GiveArmorFunc(player_t* plr) { plr->armorPoints = armorPoints[1]; plr->armorType = armorClass[1]; plr->update |= PSF_STATE | PSF_ARMOR_POINTS; } void Cht_GiveWeaponsFunc(player_t* plr) { int i; plr->update |= PSF_OWNED_WEAPONS; for(i = 0; i < NUM_WEAPON_TYPES; ++i) plr->weapons[i].owned = true; } void Cht_GiveAmmoFunc(player_t* plr) { int i; plr->update |= PSF_AMMO; for(i = 0; i < NUM_AMMO_TYPES; ++i) plr->ammo[i].owned = plr->ammo[i].max; } void Cht_GiveKeysFunc(player_t* plr) { int i; plr->update |= PSF_KEYS; for(i = 0; i < NUM_KEY_TYPES; ++i) plr->keys[i] = true; } void Cht_NoClipFunc(player_t* plr) { plr->cheats ^= CF_NOCLIP; plr->update |= PSF_STATE; P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_NOCLIP) ? STSTR_NCON : STSTR_NCOFF), false); } boolean Cht_WarpFunc(player_t* plr, cheatseq_t* cheat) { uint epsd, map; epsd = 0; map = (cheat->args[0] - '0') * 10 + cheat->args[1] - '0'; if(map != 0) map -= 1; // Catch invalid maps. if(!G_ValidateMap(&epsd, &map)) return false; P_SetMessage(plr, STSTR_CLEV, false); // Clear the menu if open. Hu_MenuCommand(MCMD_CLOSE); // So be it. briefDisabled = true; G_DeferedInitNew(gameSkill, epsd, map); return true; } boolean Cht_PowerUpFunc(player_t* plr, cheatseq_t* cheat) { static const char args[] = { 'v', 's', 'i', 'r', 'a', 'l' }; size_t i, numArgs = sizeof(args) / sizeof(args[0]); for(i = 0; i < numArgs; ++i) { powertype_t type; if(cheat->args[0] != args[i]) continue; type = (powertype_t) i; if(!plr->powers[type]) { P_GivePower(plr, type); P_SetMessage(plr, STSTR_BEHOLDX, false); } else if(type == PT_STRENGTH || type == PT_FLIGHT || type == PT_ALLMAP) { P_TakePower(plr, type); P_SetMessage(plr, STSTR_BEHOLDX, false); } return true; } return false; } void printDebugInfo(player_t* plr) { char lumpName[9], textBuffer[256]; subsector_t* sub; if(!plr->plr->mo || !userGame) return; P_GetMapLumpName(gameEpisode, gameMap, lumpName); sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", lumpName, plr->plr->mo->pos[VX], plr->plr->mo->pos[VY], plr->plr->mo->pos[VZ]); P_SetMessage(plr, textBuffer, false); // Also print some information to the console. Con_Message(textBuffer); sub = plr->plr->mo->subsector; Con_Message("\nSubsector %i:\n", P_ToIndex(sub)); Con_Message(" FloorZ:%g Material:%s\n", P_GetFloatp(sub, DMU_FLOOR_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_FLOOR_MATERIAL))); Con_Message(" CeilingZ:%g Material:%s\n", P_GetFloatp(sub, DMU_CEILING_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_CEILING_MATERIAL))); Con_Message("Player height:%g Player radius:%g\n", plr->plr->mo->height, plr->plr->mo->radius); } /** * Laser powerup cheat code ddslia for all laser powerups. * Each time the plr enters the code, plr gains a powerup. * When entered again, plr recieves next powerup. */ void Cht_LaserFunc(player_t* p) { if(P_InventoryGive(p - players, IIT_DEMONKEY1, true)) { P_SetMessage(p, STSTR_BEHOLDX, false); return; } if(P_InventoryGive(p - players, IIT_DEMONKEY2, true)) { P_SetMessage(p, STSTR_BEHOLDX, false); return; } if(P_InventoryGive(p - players, IIT_DEMONKEY3, true)) P_SetMessage(p, STSTR_BEHOLDX, false); } DEFCC(CCmdCheatGod) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("god"); } else { player_t* plr = &players[CONSOLEPLAYER]; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { int i = atoi(argv[1]); if(i < 0 || i >= MAXPLAYERS) return false; plr = &players[i]; } else plr = &players[CONSOLEPLAYER]; if(!plr->plr->inGame) return false; Cht_GodFunc(plr); } } return true; } DEFCC(CCmdCheatNoClip) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("noclip"); } else { player_t* plr = &players[CONSOLEPLAYER]; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { int i = atoi(argv[1]); if(i < 0 || i >= MAXPLAYERS) return false; plr = &players[i]; } else plr = &players[CONSOLEPLAYER]; if(!plr->plr->inGame) return false; Cht_NoClipFunc(&players[CONSOLEPLAYER]); } } return true; } static int suicideResponse(msgresponse_t response, void* context) { if(response == MSG_YES) { if(IS_NETGAME && IS_CLIENT) NetCl_CheatRequest("suicide"); else Cht_SuicideFunc(&players[CONSOLEPLAYER]); } return true; } DEFCC(CCmdCheatSuicide) { if(G_GetGameState() == GS_MAP) { player_t* plr; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { int i = atoi(argv[1]); if(i < 0 || i >= MAXPLAYERS) return false; plr = &players[i]; } else plr = &players[CONSOLEPLAYER]; if(!plr->plr->inGame) return false; if(plr->playerState == PST_DEAD) return false; if(!IS_NETGAME || IS_CLIENT) { Hu_MsgStart(MSG_YESNO, SUICIDEASK, suicideResponse, NULL); return true; } Cht_SuicideFunc(plr); return true; } else { Hu_MsgStart(MSG_ANYKEY, SUICIDEOUTMAP, NULL, NULL); } return true; } DEFCC(CCmdCheatWarp) { cheatseq_t cheat; int num; if(!cheatsEnabled()) return false; if(argc != 2) return false; num = atoi(argv[1]); cheat.args[0] = num / 10 + '0'; cheat.args[1] = num % 10 + '0'; Cht_WarpFunc(&players[CONSOLEPLAYER], &cheat); return true; } DEFCC(CCmdCheatReveal) { int option; automapid_t map; if(!cheatsEnabled()) return false; map = AM_MapForPlayer(CONSOLEPLAYER); AM_SetCheatLevel(map, 0); AM_RevealMap(map, false); option = atoi(argv[1]); if(option < 0 || option > 3) return false; if(option == 1) AM_RevealMap(map, true); else if(option != 0) AM_SetCheatLevel(map, option -1); return true; } DEFCC(CCmdCheatGive) { char buf[100]; player_t* plr = &players[CONSOLEPLAYER]; size_t i, stuffLen; if(IS_CLIENT) { if(argc != 2) return false; sprintf(buf, "give %s", argv[1]); NetCl_CheatRequest(buf); return true; } if(IS_NETGAME && !netSvAllowCheats) return false; if(argc != 2 && argc != 3) { Con_Printf("Usage:\n give (stuff)\n"); Con_Printf(" give (stuff) (plr)\n"); Con_Printf("Stuff consists of one or more of (type:id). " "If no id; give all of type:\n"); Con_Printf(" a - ammo\n"); Con_Printf(" b - berserk\n"); Con_Printf(" f - the power of flight\n"); Con_Printf(" g - light amplification visor\n"); Con_Printf(" h - health\n"); Con_Printf(" i - invulnerability\n"); Con_Printf(" k - key cards/skulls\n"); Con_Printf(" m - computer area map\n"); Con_Printf(" p - backpack full of ammo\n"); Con_Printf(" r - armor\n"); Con_Printf(" s - radiation shielding suit\n"); Con_Printf(" v - invisibility\n"); Con_Printf(" w - weapons\n"); Con_Printf("Example: 'give arw' corresponds the cheat IDFA.\n"); Con_Printf("Example: 'give w2k1' gives weapon two and key one.\n"); return true; } if(argc == 3) { i = atoi(argv[2]); if(i < 0 || i >= MAXPLAYERS) return false; plr = &players[i]; } if(G_GetGameState() != GS_MAP) { Con_Printf("Can only \"give\" when in a game!\n"); return true; } if(!plr->plr->inGame) return true; // Can't give to a plr who's not playing. strcpy(buf, argv[1]); // Stuff is the 2nd arg. strlwr(buf); stuffLen = strlen(buf); for(i = 0; buf[i]; ++i) { switch(buf[i]) { case 'a': { boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_AMMO_TYPES) { // Give one specific ammo type. plr->update |= PSF_AMMO; plr->ammo[idx].owned = plr->ammo[idx].max; giveAll = false; i++; } } if(giveAll) { Cht_GiveAmmoFunc(plr); } break; } case 'b': { cheatseq_t cheat; cheat.args[0] = PT_STRENGTH; Cht_PowerUpFunc(plr, &cheat); break; } case 'f': { cheatseq_t cheat; cheat.args[0] = PT_FLIGHT; Cht_PowerUpFunc(plr, &cheat); break; } case 'g': { cheatseq_t cheat; cheat.args[0] = PT_INFRARED; Cht_PowerUpFunc(plr, &cheat); break; } case 'h': P_GiveBody(plr, healthLimit); break; case 'i': { cheatseq_t cheat; cheat.args[0] = PT_INVULNERABILITY; Cht_PowerUpFunc(plr, &cheat); break; } case 'k': { boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_KEY_TYPES) { // Give one specific key. plr->update |= PSF_KEYS; plr->keys[idx] = true; giveAll = false; i++; } } if(giveAll) { Cht_GiveKeysFunc(plr); } break; } case 'm': { cheatseq_t cheat; cheat.args[0] = PT_ALLMAP; Cht_PowerUpFunc(plr, &cheat); break; } case 'p': P_GiveBackpack(plr); break; case 'r': Cht_GiveArmorFunc(plr); break; case 's': { cheatseq_t cheat; cheat.args[0] = PT_IRONFEET; Cht_PowerUpFunc(plr, &cheat); break; } case 'v': { cheatseq_t cheat; cheat.args[0] = PT_INVISIBILITY; Cht_PowerUpFunc(plr, &cheat); break; } case 'w': { boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_WEAPON_TYPES) { // Give one specific weapon. P_GiveWeapon(plr, idx, false); giveAll = false; i++; } } if(giveAll) { Cht_GiveWeaponsFunc(plr); } break; } default: // Unrecognized Con_Printf("What do you mean, '%c'?\n", buf[i]); break; } } return true; } DEFCC(CCmdCheatMassacre) { Con_Printf("%i monsters killed.\n", P_Massacre()); return true; } DEFCC(CCmdCheatWhere) { printDebugInfo(&players[CONSOLEPLAYER]); return true; } /** * Exit the current map and go to the intermission. */ DEFCC(CCmdCheatLeaveMap) { if(!cheatsEnabled()) return false; if(G_GetGameState() != GS_MAP) { S_LocalSound(SFX_OOF, NULL); Con_Printf("Can only exit a map when in a game!\n"); return true; } G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/d_main.c0000644000175000017500000003477611357170242022233 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_main.c: Initialization - jDoom64 specifc. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom64.h" #include "m_argv.h" #include "hu_stuff.h" #include "hu_menu.h" #include "hu_log.h" #include "hu_msg.h" #include "p_saveg.h" #include "p_mapspec.h" #include "p_switch.h" #include "am_map.h" #include "g_defs.h" #include "p_inventory.h" #include "p_player.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int verbose; boolean devParm; // checkparm of -devparm boolean noMonstersParm; // checkparm of -nomonsters boolean respawnParm; // checkparm of -respawn boolean fastParm; // checkparm of -fast boolean turboParm; // checkparm of -turbo float turboMul; // multiplier for turbo boolean monsterInfight; skillmode_t startSkill; uint startEpisode; uint startMap; boolean autoStart; FILE *debugFile; gamemode_t gameMode; int gameModeBits; // This is returned in D_Get(DD_GAME_MODE), max 16 chars. char gameModeString[17]; // Print title for every printed line. char title[128]; // Demo loop. int demoSequence; int pageTic; char *pageName; // The patches used in drawing the view border. char *borderLumps[] = { "FTILEABC", "brdr_t", "brdr_r", "brdr_b", "brdr_l", "brdr_tl", "brdr_tr", "brdr_br", "brdr_bl" }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Attempt to change the current game mode. Can only be done when not * actually in a level. * * \todo Doesn't actually do anything yet other than set the game mode * global vars. * * @param mode The game mode to change to. * * @return boolean @c true, if we changed game modes successfully. */ boolean G_SetGameMode(gamemode_t mode) { gameMode = mode; if(G_GetGameState() == GS_MAP) return false; switch(mode) { case commercial: gameModeBits = GM_COMMERCIAL; break; case indetermined: // Well, no IWAD found. gameModeBits = GM_INDETERMINED; break; default: Con_Error("G_SetGameMode: Unknown gamemode %i", mode); } return true; } /** * Check which known IWADs are found. The purpose of this routine is to * find out which IWADs the user lets us to know about, but we don't * decide which one gets loaded or even see if the WADs are actually * there. The default location for IWADs is Data\GAMENAMETEXT\. */ void G_DetectIWADs(void) { int k; char fn[256]; // The '}' means the paths are affected by the base path. char *paths[] = { "}data\\"GAMENAMETEXT"\\", "}data\\", "}", "}iwads\\", "", 0 }; // Tell the engine about all the possible IWADs. for(k = 0; paths[k]; ++k) { sprintf(fn, "%s%s", paths[k], "doom64.wad"); DD_AddIWAD(fn); } } static boolean lumpsFound(char **list) { for(; *list; list++) if(W_CheckNumForName(*list) == -1) return false; return true; } /** * Checks availability of IWAD files by name, to determine whether * registered/commercial features should be executed (notably loading * PWAD's). */ static void identifyFromData(void) { typedef struct { char **lumps; gamemode_t mode; } identify_t; char *commercialLumps[] = { // List of lumps to detect registered with. "map01", "map02", "map38", "f_suck", NULL }; identify_t list[] = { {commercialLumps, commercial}, }; int i, num = sizeof(list) / sizeof(identify_t); // Now we must look at the lumps. for(i = 0; i < num; ++i) { // If all the listed lumps are found, selection is made. // All found? if(lumpsFound(list[i].lumps)) { G_SetGameMode(list[i].mode); return; } } // A detection couldn't be made. G_SetGameMode(commercial); // Assume the minimum. Con_Message("\nIdentifyVersion: DOOM64 version unknown.\n" "** Important data might be missing! **\n\n"); } /** * gameMode, gameMission and the gameModeString are set. */ void G_IdentifyVersion(void) { identifyFromData(); // The game mode string is returned in DD_Get(DD_GAME_MODE). // It is sent out in netgames, and the pcl_hello2 packet contains it. // A client can't connect unless the same game mode is used. memset(gameModeString, 0, sizeof(gameModeString)); strcpy(gameModeString, "doom64"); } /** * Pre Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PreInit(void) { int i; G_SetGameMode(indetermined); // Config defaults. The real settings are read from the .cfg files // but these will be used no such files are found. memset(&cfg, 0, sizeof(cfg)); cfg.playerMoveSpeed = 1; cfg.dclickUse = false; cfg.povLookAround = true; cfg.screenBlocks = cfg.setBlocks = 10; cfg.echoMsg = true; cfg.lookSpeed = 3; cfg.turnSpeed = 1; cfg.usePatchReplacement = 2; // Use built-in replacements if available. cfg.menuScale = .9f; cfg.menuGlitter = .5f; cfg.menuShadow = 0.33f; cfg.menuQuitSound = true; cfg.menuEffects = 1; // Do type-in effect. cfg.flashColor[0] = .7f; cfg.flashColor[1] = .9f; cfg.flashColor[2] = 1; cfg.flashSpeed = 4; cfg.turningSkull = false; cfg.hudShown[HUD_HEALTH] = true; cfg.hudShown[HUD_ARMOR] = true; cfg.hudShown[HUD_AMMO] = true; cfg.hudShown[HUD_KEYS] = true; cfg.hudShown[HUD_FRAGS] = true; cfg.hudShown[HUD_INVENTORY] = false; // They will be visible when the automap is. for(i = 0; i < NUMHUDUNHIDEEVENTS; ++i) // When the hud/statusbar unhides. cfg.hudUnHide[i] = 1; cfg.hudScale = .6f; cfg.hudColor[0] = 1; cfg.hudColor[1] = cfg.hudColor[2] = 0; cfg.hudColor[3] = 0.75f; cfg.hudFog = 1; cfg.hudIconAlpha = 0.5f; cfg.xhairSize = .5f; cfg.xhairVitality = false; cfg.xhairColor[0] = 1; cfg.xhairColor[1] = 1; cfg.xhairColor[2] = 1; cfg.xhairColor[3] = 1; cfg.filterStrength = .8f; cfg.moveCheckZ = true; cfg.jumpPower = 9; cfg.airborneMovement = 1; cfg.weaponAutoSwitch = 1; // "If better" mode. cfg.noWeaponAutoSwitchIfFiring = false; cfg.ammoAutoSwitch = 0; // Never. cfg.secretMsg = true; cfg.slidingCorpses = false; cfg.fastMonsters = false; cfg.netJumping = true; cfg.netMap = 0; cfg.netSkill = SM_MEDIUM; cfg.netColor = 4; cfg.netBFGFreeLook = 0; // Allow free-aim 0=none 1=not BFG 2=All. cfg.netMobDamageModifier = 1; cfg.netMobHealthModifier = 1; cfg.netGravity = -1; // Use map default. cfg.plrViewHeight = DEFAULT_PLAYER_VIEWHEIGHT; cfg.mapTitle = true; cfg.hideIWADAuthor = true; cfg.menuColor[0] = 1; cfg.menuColor2[0] = 1; cfg.menuSlam = false; cfg.menuHotkeys = true; cfg.askQuickSaveLoad = true; cfg.maxSkulls = true; cfg.allowSkullsInWalls = false; cfg.anyBossDeath = false; cfg.monstersStuckInDoors = false; cfg.avoidDropoffs = true; cfg.moveBlock = false; cfg.fallOff = true; cfg.automapCustomColors = 0; // Never. cfg.automapL0[0] = .4f; // Unseen areas. cfg.automapL0[1] = .4f; cfg.automapL0[2] = .4f; cfg.automapL1[0] = 1.f; // Onesided lines. cfg.automapL1[1] = 0.f; cfg.automapL1[2] = 0.f; cfg.automapL2[0] = .77f; // Floor height change lines. cfg.automapL2[1] = .6f; cfg.automapL2[2] = .325f; cfg.automapL3[0] = 1.f; // Ceiling change lines. cfg.automapL3[1] = .95f; cfg.automapL3[2] = 0.f; cfg.automapMobj[0] = 0.f; cfg.automapMobj[1] = 1.f; cfg.automapMobj[2] = 0.f; cfg.automapBack[0] = 0.f; cfg.automapBack[1] = 0.f; cfg.automapBack[2] = 0.f; cfg.automapOpacity = .7f; cfg.automapLineAlpha = .7f; cfg.automapShowDoors = true; cfg.automapDoorGlow = 8; cfg.automapHudDisplay = 2; cfg.automapRotate = true; cfg.automapBabyKeys = false; cfg.automapZoomSpeed = .1f; cfg.automapPanSpeed = .5f; cfg.automapPanResetOnOpen = true; cfg.automapOpenSeconds = AUTOMAP_OPEN_SECONDS; cfg.counterCheatScale = .7f; // From jHeretic. cfg.msgShow = true; cfg.msgCount = 1; cfg.msgScale = .8f; cfg.msgUptime = 5; cfg.msgAlign = ALIGN_LEFT; cfg.msgBlink = 5; cfg.msgColor[0] = cfg.msgColor[1] = cfg.msgColor[2] = 1; cfg.chatBeep = 1; cfg.killMessages = true; cfg.bobWeapon = 1; cfg.bobView = 1; cfg.bobWeaponLower = true; cfg.cameraNoClip = true; cfg.weaponOrder[0] = WT_TENTH; cfg.weaponOrder[1] = WT_SIXTH; cfg.weaponOrder[2] = WT_NINETH; cfg.weaponOrder[3] = WT_FOURTH; cfg.weaponOrder[4] = WT_THIRD; cfg.weaponOrder[5] = WT_SECOND; cfg.weaponOrder[6] = WT_EIGHTH; cfg.weaponOrder[7] = WT_FIFTH; cfg.weaponOrder[8] = WT_SEVENTH; cfg.weaponOrder[9] = WT_FIRST; cfg.weaponRecoil = true; cfg.berserkAutoSwitch = true; // Do the common pre init routine. G_CommonPreInit(); } /** * Post Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PostInit(void) { int p; filename_t file; char mapStr[6]; // Common post init routine. G_CommonPostInit(); // Initialize ammo info. P_InitAmmoInfo(); // Initialize weapon info. P_InitWeaponInfo(); // Print a game mode banner with rulers. Con_FPrintf(CBLF_RULER | CBLF_WHITE | CBLF_CENTER, "Doom64 Startup\n"); Con_FPrintf(CBLF_RULER, ""); // Game parameters. monsterInfight = GetDefInt("AI|Infight", 0); // Get skill / episode / map from parms. gameSkill = startSkill = SM_NOITEMS; startEpisode = 0; startMap = 0; autoStart = false; // Game mode specific settings // None. // Command line options noMonstersParm = ArgCheck("-nomonsters"); respawnParm = ArgCheck("-respawn"); fastParm = ArgCheck("-fast"); devParm = ArgCheck("-devparm"); if(ArgCheck("-altdeath")) cfg.netDeathmatch = 2; else if(ArgCheck("-deathmatch")) cfg.netDeathmatch = 1; p = ArgCheck("-skill"); if(p && p < myargc - 1) { startSkill = Argv(p + 1)[0] - '1'; autoStart = true; } p = ArgCheck("-timer"); if(p && p < myargc - 1 && deathmatch) { int time; time = atoi(Argv(p + 1)); Con_Message("Levels will end after %d minute", time); if(time > 1) Con_Message("s"); Con_Message(".\n"); } p = ArgCheck("-warp"); if(p && p < myargc - 1) { startMap = atoi(Argv(p + 1)) - '1'; autoStart = true; } // Turbo option. p = ArgCheck("-turbo"); turboMul = 1.0f; if(p) { int scale = 200; turboParm = true; if(p < myargc - 1) scale = atoi(Argv(p + 1)); if(scale < 10) scale = 10; if(scale > 400) scale = 400; Con_Message("turbo scale: %i%%\n", scale); turboMul = scale / 100.f; } // Are we autostarting? if(autoStart) { Con_Message("Warp to Episode %d, Map %d, Skill %d\n", startEpisode+1, startMap+1, startSkill + 1); } // Load a saved game? p = ArgCheck("-loadgame"); if(p && p < myargc - 1) { SV_GetSaveGameFileName(file, Argv(p + 1)[0] - '0', FILENAME_T_MAXLEN); G_LoadGame(file); } // Check valid episode and map. if((autoStart || IS_NETGAME)) { sprintf(mapStr, "MAP%2.2d", startMap+1); if(!W_CheckNumForName(mapStr)) { startEpisode = 0; startMap = 0; } } // Print a string showing the state of the game parameters. Con_Message("Game state parameters:%s%s%s%s%s\n", noMonstersParm? " nomonsters" : "", respawnParm? " respawn" : "", fastParm? " fast" : "", turboParm? " turbo" : "", (cfg.netDeathmatch ==1)? " deathmatch" : (cfg.netDeathmatch ==2)? " altdeath" : ""); if(G_GetGameAction() != GA_LOADGAME) { if(autoStart || IS_NETGAME) { G_DeferedInitNew(startSkill, startEpisode, startMap); } else { G_StartTitle(); // Start up intro loop. } } } void G_Shutdown(void) { Hu_MsgShutdown(); Hu_UnloadData(); Hu_LogShutdown(); P_DestroyIterList(spechit); P_DestroyIterList(linespecials); P_DestroyLineTagLists(); P_DestroySectorTagLists(); P_ShutdownInventory(); AM_Shutdown(); P_FreeWeaponSlots(); } void G_EndFrame(void) { // Nothing to do. } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/g_ctrl.c0000644000175000017500000000653011357170242022241 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.c: Control bindings - jDoom64 specifc */ // HEADER FILES ------------------------------------------------------------ #include "jdoom64.h" #include "g_controls.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Register all the various player controls with Doomsday. */ void G_RegisterPlayerControls(void) { /* typedef struct { char *command; // The command to execute. } control_t; control_t axisCts[] = { {"WALK"}, {"SIDESTEP"}, {"turn"}, {"ZFLY"}, {"look"}, {"MAPPANX"}, {"MAPPANY"}, {""} // terminate }; control_t toggleCts[] = { {"ATTACK"}, {"USE"}, {"strafe"}, {"SPEED"}, {"JUMP"}, {"mlook"}, {"jlook"}, {"mzoomin"}, {"mzoomout"}, {""} // terminate }; control_t impulseCts[] = { {"falldown"}, {"lookcntr"}, {"weap1"}, {"weapon1"}, {"weapon2"}, {"weap3"}, {"weapon3"}, {"weapon4"}, {"weapon5"}, {"weapon6"}, {"weapon7"}, {"weapon8"}, {"weapon9"}, {"weapon10"}, // Laser. {"nextwpn"}, {"prevwpn"}, {"demostop"}, {""} // terminate }; uint i; // Axis controls. for(i = 0; axisCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_AXIS, axisCts[i].command); } // Toggle controls. for(i = 0; toggleCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_TOGGLE, toggleCts[i].command); } // Impulse controls. for(i = 0; impulseCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_IMPULSE, impulseCts[i].command); } */ } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/src/p_maputl.c0000644000175000017500000001425711357170242022615 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputl.c: Movement/collision map utility functions. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom64.h" #include "dmu_lib.h" #include "p_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Apply "torque" to objects hanging off of ledges, so that they fall off. * It's not really torque, since Doom has no concept of rotation, but it's * a convincing effect which avoids anomalies such as lifeless objects * hanging more than halfway off of ledges, and allows objects to roll off * of the edges of moving lifts, or to slide up and then back down stairs, * or to fall into a ditch. * * If more than one linedef is contacted, the effects are cumulative, so * balancing is possible. */ static boolean PIT_ApplyTorque(linedef_t* ld, void* data) { mobj_t* mo = tmThing; float dist; sector_t* frontsec, *backsec; float ffloor, bfloor; float d1[2], vtx[2]; if(tmThing->player) return true; // Skip players! if(!(frontsec = P_GetPtrp(ld, DMU_FRONT_SECTOR)) || !(backsec = P_GetPtrp(ld, DMU_BACK_SECTOR))) return true; // Shouldn't ever happen. ffloor = P_GetFloatp(frontsec, DMU_FLOOR_HEIGHT); bfloor = P_GetFloatp(backsec, DMU_FLOOR_HEIGHT); P_GetFloatpv(ld, DMU_DXY, d1); P_GetFloatpv(P_GetPtrp(ld, DMU_VERTEX0), DMU_XY, vtx); // Lever-arm: dist = +d1[0] * mo->pos[VY] - d1[1] * mo->pos[VX] - d1[0] * vtx[VY] + d1[1] * vtx[VX]; if((dist < 0 && ffloor < mo->pos[VZ] && bfloor >= mo->pos[VZ]) || (dist >= 0 && bfloor < mo->pos[VZ] && ffloor >= mo->pos[VZ])) { // At this point, we know that the object straddles a two-sided // linedef, and that the object's center of mass is above-ground. float x = fabs(d1[0]), y = fabs(d1[1]); if(y > x) { float tmp = x; x = y; y = tmp; } y = FIX2FLT(finesine[(tantoangle[FLT2FIX(y / x) >> DBITS] + ANG90) >> ANGLETOFINESHIFT]); /** * Momentum is proportional to distance between the object's center * of mass and the pivot linedef. * * It is scaled by 2^(OVERDRIVE - gear). When gear is increased, the * momentum gradually decreases to 0 for the same amount of * pseudotorque, so that oscillations are prevented, yet it has a * chance to reach equilibrium. */ if(mo->gear < OVERDRIVE) dist = (dist * FIX2FLT(FLT2FIX(y) << -(mo->gear - OVERDRIVE))) / x; else dist = (dist * FIX2FLT(FLT2FIX(y) >> +(mo->gear - OVERDRIVE))) / x; // Apply momentum away from the pivot linedef. x = d1[1] * dist; y = d1[0] * dist; // Avoid moving too fast all of a sudden (step into "overdrive"). dist = (x * x) + (y * y); while(dist > 4 && mo->gear < MAXGEAR) { ++mo->gear; x /= 2; y /= 2; dist /= 2; } mo->mom[MX] -= x; mo->mom[MY] += y; } return true; } /** * Applies "torque" to objects, based on all contacted linedefs. * $dropoff_fix */ void P_ApplyTorque(mobj_t *mo) { int flags = mo->intFlags; // Corpse sliding anomalies, made configurable. if(!cfg.slidingCorpses) return; tmThing = mo; // Use VALIDCOUNT to prevent checking the same line twice. VALIDCOUNT++; P_MobjLinesIterator(mo, PIT_ApplyTorque, 0); // If any momentum, mark object as 'falling' using engine-internal // flags. if(mo->mom[MX] != 0 || mo->mom[MY] != 0) mo->intFlags |= MIF_FALLING; else // Clear the engine-internal flag indicating falling object. mo->intFlags &= ~MIF_FALLING; /** * If the object has been moving, step up the gear. This helps reach * equilibrium and avoid oscillations. * * DOOM has no concept of potential energy, much less of rotation, so we * have to creatively simulate these systems somehow :) */ // If not falling for a while, reset it to full strength. if(!((mo->intFlags | flags) & MIF_FALLING)) mo->gear = 0; else if(mo->gear < MAXGEAR) // Else if not at max gear, move up a gear. mo->gear++; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/config/0000755000175000017500000000000011523516204021272 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/config/startup.cfg0000644000175000017500000000122211357170242023455 0ustar keeskees# # -=- jDoom64 Startup -=- # # This file is included with all versions, which means that it gets # overwritten on each upgrade. Give all custom permanent commands in # autoexec.cfg or user.cfg. # These are the original colors. Uncomment to use. #uicolor text .85 .87 1 #uicolor shadow 0 0 0 #uicolor bglight .015 .2 .4 #uicolor bgmed .01 .125 .25 #uicolor bgdark .0035 .05 .1 #uicolor borhigh 1 1 1 #uicolor bormed 0 0 0 #uicolor borlow .015 .2 .4 # The font. #font name fixed12 # Keymap. #keymap default.dkm # The user config file can contain anything the user wants to execute # before the main startup begins. exec user.cfg deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/0000755000175000017500000000000011523516204021450 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/m_random.h0000644000175000017500000000221111357170242023414 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.h: Random numbers. */ #ifndef __M_RANDOM_H__ #define __M_RANDOM_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif byte P_Random(void); byte M_Random(void); void M_ResetRandom(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/r_defs.h0000644000175000017500000001022011357170242023061 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_defs.h: shared data struct definitions. */ #ifndef __R_DEFS__ #define __R_DEFS__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "p_xg.h" #define SP_floororigheight planes[PLN_FLOOR].origHeight #define SP_ceilorigheight planes[PLN_CEILING].origHeight // Stair build flags. #define BL_BUILT 0x1 #define BL_WAS_BUILT 0x2 #define BL_SPREADED 0x4 typedef struct xsector_s { short special; short tag; // 0 = untraversed, 1,2 = sndlines -1 int soundTraversed; // thing that made a sound (or null) struct mobj_s* soundTarget; // thinker_t for reversable actions void* specialData; byte blFlags; // Used during stair building. // stone, metal, heavy, etc... byte seqType; // NOT USED ATM struct { float origHeight; } planes[2]; // {floor, ceiling} float origLight; float origRGB[3]; xgsector_t* xg; } xsector_t; /** * xline_t flags: */ #define ML_BLOCKMONSTERS 2 // Blocks monsters only. #define ML_SECRET 32 // In AutoMap: don't map as two sided: IT'S A SECRET! #define ML_SOUNDBLOCK 64 // Sound rendering: don't let sound cross two of these. #define ML_DONTDRAW 128 // Don't draw on the automap at all. #define ML_MAPPED 256 // Set if already seen, thus drawn in automap. // FIXME! DJS - This is important! // Doom64tc unfortunetly used non standard values for the linedef flags // it implemented from BOOM. It will make life simpler if we simply // update the Doom64TC IWAD rather than carry this on much further as // once jDoom64 is released with 1.9.0 I imagine we'll see a bunch // PWADs start cropping up. //#define ML_PASSUSE 512 // Allows a USE action to pass through a linedef with a special //#define ML_ALLTRIGGER 1024 // If set allows any mobj to trigger the linedef's special //#define ML_INVALID 2048 // If set ALL flags NOT in DOOM v1.9 will be zeroed upon map load. ML_BLOCKING -> ML_MAPPED inc will persist. //#define VALIDMASK 0x000001ff #define ML_ALLTRIGGER 512 // Anything can use linedef if this is set - kaiser #define ML_PASSUSE 1024 #define ML_BLOCKALL 2048 typedef struct xline_s { short special; short tag; short flags; // Has been rendered at least once and needs to appear in the map, // for each player. boolean mapped[MAXPLAYERS]; int validCount; // Extended generalized lines. xgline_t* xg; // jDoom64 specific: short useOn; } xline_t; // Our private map data structures. extern xsector_t* xsectors; extern xline_t* xlines; // If true we are in the process of setting up a map. extern boolean mapSetup; xline_t* P_ToXLine(linedef_t* line); xsector_t* P_ToXSector(sector_t* sector); xsector_t* P_ToXSectorOfSubsector(subsector_t* sub); xline_t* P_GetXLine(uint index); xsector_t* P_GetXSector(uint index); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/wi_stuff.h0000644000175000017500000000501211357170242023450 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * wi_stuff.h: Intermission screens */ #ifndef __WI_STUFF_H__ #define __WI_STUFF_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // Structure passed e.g. to WI_Init(wb) typedef struct { boolean inGame; // Whether the player is in game. // Player stats, kills, collected items etc. int kills; int items; int secret; int time; int frags[MAXPLAYERS]; int score; // Current score on entry, modified on return. } wbplayerstruct_t; typedef struct { uint episode; boolean didSecret; // If true, splash the secret level. uint currentMap, nextMap; // This and next maps. int maxKills; int maxItems; int maxSecret; int maxFrags; int parTime; int pNum; // Index of this player in game. wbplayerstruct_t plyr[MAXPLAYERS]; } wbstartstruct_t; // States for the intermission typedef enum { ILS_NONE = -1, ILS_SHOW_STATS, ILS_SHOW_NEXTMAP } interludestate_t; // Called by main loop, animate the intermission. void WI_Ticker(void); // Called by main loop, // draws the intermission directly into the screen buffer. void WI_Drawer(void); // Setup for an intermission screen. void WI_Init(wbstartstruct_t *wbstartstruct); void WI_SetState(interludestate_t st); void WI_End(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/doomtype.h0000644000175000017500000000362511357170242023472 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomtype_.h: Simple basic typedefs, isolated here to make it easier * separating modules. */ #ifndef __DOOMTYPE_H__ #define __DOOMTYPE_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // Predefined with some OS. #ifdef UNIX #include #define MAXCHAR SCHAR_MAX #define MAXSHORT SHRT_MAX #define MAXINT INT_MAX #define MAXLONG LONG_MAX #define MINCHAR SCHAR_MIN #define MINSHORT SHRT_MIN #define MININT INT_MIN #define MINLONG LONG_MIN #else /* not UNIX */ #define MAXCHAR ((char)0x7f) #define MAXSHORT ((short)0x7fff) // Max pos 32-bit int. #define MAXINT ((int)0x7fffffff) #define MAXLONG ((long)0x7fffffff) #define MINCHAR ((char)0x80) #define MINSHORT ((short)0x8000) // Max negative 32-bit integer. #define MININT ((int)0x80000000) #define MINLONG ((long)0x80000000) #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_telept.h0000644000175000017500000000316311357170242023443 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.h: */ #ifndef __P_TELEPT_H__ #define __P_TELEPT_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "doomsday.h" #include "p_mobj.h" // Define values for map objects #define MO_TELEPORTMAN (14) #define TELEFOGHEIGHT (0) int EV_Teleport(linedef_t *line, int side, mobj_t *thing, boolean spawnFog); int EV_FadeSpawn(linedef_t *line, mobj_t *thing); int EV_FadeAway(linedef_t *line, mobj_t *thing); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_enemy.h0000644000175000017500000000234111357170242023260 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.h: Enemy thinking, AI (jDoom64-specific). */ #ifndef __P_ENEMY_H__ #define __P_ENEMY_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif extern boolean bossKilled; void P_SpawnBrainTargets(void); void P_NoiseAlert(mobj_t *target, mobj_t *emmiter); int P_Massacre(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_player.h0000644000175000017500000001071511357170242023427 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_player.h: Player data structures. */ #ifndef __D_PLAYER_H__ #define __D_PLAYER_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // The player data structure depends on a number of other structs: items // (internal inventory), animation states (closely tied to the sprites used // to represent them, unfortunately). #include "d_items.h" #include "p_pspr.h" // In addition, the player is just a special case of the generic moving // object/actor. #include "p_mobj.h" #include "g_controls.h" #ifdef __GNUG__ #pragma interface #endif /** * Player states. */ typedef enum { PST_LIVE, // Playing or camping. PST_DEAD, // Dead on the ground, view follows killer. PST_REBORN // Ready to restart/respawn??? } playerstate_t; /** * Flags for cheats currently activated by player: */ #define CF_NOCLIP (1) // No clipping, walk through barriers. #define CF_GODMODE (2) // No damage, no health loss. #define CF_NOMOMENTUM (4) // Not really a cheat, just a debug aid. typedef struct player_s { ddplayer_t* plr; // Pointer to the engine's player data. playerstate_t playerState; playerclass_t class; // player class type playerbrain_t brain; // This is only used between maps, mo->health is used during maps. int health; int armorPoints; // Armor type is 0-2. int armorType; // Power ups. invinc and invis are tic counters. int powers[NUM_POWER_TYPES]; boolean keys[NUM_KEY_TYPES]; boolean backpack; int frags[MAXPLAYERS]; weapontype_t readyWeapon; // Is wp_nochange if not changing. weapontype_t pendingWeapon; struct playerweapon_s { boolean owned; } weapons[NUM_WEAPON_TYPES]; struct playerammo_s { int owned; int max; } ammo[NUM_AMMO_TYPES]; // True if button down last tic. int attackDown; int useDown; // Bit flags, for cheats and debug. See cheat_t, above. int cheats; // Refired shots are less accurate. int refire; // For intermission stats. int killCount; int itemCount; int secretCount; // For screen flashing (red or bright). int damageCount; int bonusCount; // Who did damage (NULL for floors/ceilings). mobj_t* attacker; // Player skin colorshift, 0-3 for which color to draw player. int colorMap; // Overlay view sprites (gun, etc). pspdef_t pSprites[NUMPSPRITES]; // True if secret map has been done. boolean didSecret; int jumpTics; // The player can jump if this counter is zero. int airCounter; int rebornWait; // The player can be reborn if this counter is zero. boolean centering; // The player's view pitch is centering back to zero. int update, startSpot; float viewOffset[3]; // Relative to position of the player mobj. float viewZ; // Focal origin above r.z. float viewHeight; // Base height above floor for viewZ. float viewHeightDelta; float bob; // Bounded/scaled total momentum. // Target view to a mobj (NULL=disabled). mobj_t* viewLock; // $democam int lockFull; int flyHeight; } player_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_items.h0000644000175000017500000000452211357170242023253 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_items.h: Items key cards, weapon, ammunition. */ #ifndef __D_ITEMS__ #define __D_ITEMS__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "doomdef.h" #define WEAPON_INFO(weaponnum, pclass, fmode) (&weaponInfo[weaponnum][pclass].mode[fmode]) typedef enum { WSN_UP, WSN_DOWN, WSN_READY, WSN_ATTACK, WSN_FLASH, NUM_WEAPON_STATE_NAMES } weaponstatename_t; typedef struct { int gameModeBits; // Game modes, weapon is available in. int ammoType[NUM_AMMO_TYPES]; // required ammo types. int perShot[NUM_AMMO_TYPES]; // Ammo used per shot of each type. boolean autoFire; // (True)= fire when raised if fire held. int states[NUM_WEAPON_STATE_NAMES]; int raiseSound; // Sound played when weapon is raised. int readySound; // Sound played WHILE weapon is readyied int staticSwitch; // Weapon is not lowered during switch. } weaponmodeinfo_t; // Weapon info: sprite frames, ammunition use. typedef struct { weaponmodeinfo_t mode[NUMWEAPLEVELS]; } weaponinfo_t; extern weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES]; void P_InitAmmoInfo(void); void P_InitWeaponInfo(void); void P_InitPlayerValues(struct player_s *p); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/info.h0000644000175000017500000007230511357170242022566 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * info.h: Sprite, state, mobjtype and text identifiers. */ #ifndef __INFO_CONSTANTS_H__ #define __INFO_CONSTANTS_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // Sprites. typedef enum { //SPR_SPOT, SPR_PLAY, SPR_SARG, SPR_FATT, SPR_POSS, SPR_TROO, SPR_HEAD, SPR_BOSS, SPR_SKUL, SPR_BSPI, SPR_CYBR, SPR_PAIN, SPR_RECT, SPR_MISL, SPR_PLSS, SPR_BFS1, //SPR_LASS, SPR_BAL1, SPR_BAL3, //SPR_BAL2, //SPR_BAL7, //SPR_BAL8, SPR_APLS, SPR_MANF, //SPR_TRCR, SPR_DART, SPR_FIRE, //SPR_RBAL, //SPR_PUF2, //SPR_PUF3, SPR_PUFF, SPR_BLUD, //SPR_A027, SPR_TFOG, SPR_BFE2, SPR_ARM1, SPR_ARM2, SPR_BON1, SPR_BON2, SPR_BKEY, SPR_RKEY, SPR_YKEY, SPR_YSKU, SPR_RSKU, SPR_BSKU, SPR_ART1, SPR_ART2, SPR_ART3, SPR_STIM, SPR_MEDI, SPR_SOUL, SPR_PINV, SPR_PSTR, SPR_PINS, SPR_SUIT, SPR_PMAP, SPR_PVIS, SPR_MEGA, SPR_CLIP, SPR_AMMO, SPR_RCKT, SPR_BROK, SPR_CELL, SPR_CELP, SPR_SHEL, SPR_SBOX, SPR_BPAK, SPR_BFUG, SPR_CSAW, SPR_MGUN, SPR_LAUN, SPR_PLSM, SPR_SHOT, SPR_SGN2, SPR_LSRG, SPR_CAND, SPR_BAR1, //SPR_LMP1, //SPR_LMP2, //SPR_A031, //SPR_A030, //SPR_A032, //SPR_A033, //SPR_A034, //SPR_BFLM, //SPR_RFLM, //SPR_YFLM, //SPR_A006, //SPR_A021, //SPR_A003, //SPR_A020, //SPR_A014, //SPR_A016, //SPR_A008, //SPR_A007, //SPR_A015, //SPR_A001, //SPR_A012, //SPR_A010, //SPR_A018, //SPR_A017, //SPR_A026, //SPR_A022, //SPR_A028, //SPR_A029, //SPR_A035, //SPR_A036, //SPR_TRE3, SPR_TRE2, SPR_TRE1, //SPR_A013, //SPR_A019, //SPR_A004, //SPR_A005, //SPR_A023, SPR_SAWG, SPR_PUNG, SPR_PISG, SPR_SHT1, SPR_SHT2, SPR_CHGG, SPR_ROCK, SPR_PLAS, SPR_BFGG, SPR_LASR, /** * Sprites below here are either unused or need to take indices above. */ SPR_PLSE, SPR_BFE1, SPR_IFOG, SPR_SPOS, SPR_FATB, SPR_FBXP, SPR_SKEL, SPR_BAL7, SPR_BOS2, SPR_BON4, SPR_COLU, SPR_SMT2, SPR_GOR1, SPR_POL2, SPR_POL5, SPR_POL4, SPR_POL3, SPR_POL1, SPR_POL6, SPR_GOR2, SPR_GOR3, SPR_GOR4, SPR_GOR5, SPR_SMIT, SPR_COL1, SPR_COL2, SPR_COL3, SPR_COL4, SPR_CBRA, SPR_COL6, SPR_ELEC, SPR_TBLU, SPR_TGRN, SPR_TRED, SPR_SMBT, SPR_SMGT, SPR_SMRT, SPR_HDB1, SPR_HDB2, SPR_HDB3, SPR_HDB4, SPR_HDB5, SPR_HDB6, SPR_POB1, SPR_POB2, SPR_BRS1, SPR_TLMP, SPR_TLP2, SPR_NTRO, SPR_BRNR, SPR_NMBL, SPR_SMOK, SPR_LAZR, SPR_LPUF, SPR_MBAL, SPR_MPUF, NUMSPRITES } spritetype_e; // States. typedef enum { S_NULL, S_LIGHTDONE, S_PLAY, S_PLAY_RUN1, S_PLAY_RUN2, S_PLAY_RUN3, S_PLAY_RUN4, S_PLAY_ATK1, S_PLAY_ATK2, S_PLAY_PAIN, S_PLAY_PAIN2, S_PLAY_DIE1, S_PLAY_DIE2, S_PLAY_DIE3, S_PLAY_DIE4, S_PLAY_DIE5, S_PLAY_DIE6, S_PLAY_XDIE1, S_PLAY_XDIE2, S_PLAY_XDIE3, S_PLAY_XDIE4, S_PLAY_XDIE5, S_PLAY_XDIE6, S_PLAY_XDIE7, S_PLAY_XDIE8, S_PLAY_XDIE9, S_EMARP_STND, S_EMARP_RUN1, S_EMARP_RUN2, S_EMARP_RUN3, S_EMARP_RUN4, S_EMARP_ATK1, S_EMARP_ATK2, S_EMARP_ATK3, S_EMARP_ATK4, S_EMARP_ATK5, S_EMARP_ATK6, S_EMARP_PAIN, S_EMARP_PAIN2, S_EMARP_ATKB1, S_EMARP_ATKB2, S_EMARP_ATKB3, S_EMARP_ATKB4, S_EMARP_ATKB5, S_EMARP_ATKB6, S_SARG_STND, S_SARG_STND2, S_SARG_RUN1, S_SARG_RUN2, S_SARG_RUN3, S_SARG_RUN4, S_SARG_RUN5, S_SARG_RUN6, S_SARG_RUN7, S_SARG_RUN8, S_SARG_ATK1, S_SARG_ATK2, S_SARG_ATK3, S_SARG_PAIN, S_SARG_PAIN2, S_SARG_DIE1, S_SARG_DIE2, S_SARG_DIE3, S_SARG_DIE4, S_SARG_DIE5, S_SARG_DIE6, S_SHAD_RUN, S_SHAD_ATK, S_SHAD_PAIN, S_SHAD_DIE, S_FATT_STND, S_FATT_STND2, S_FATT_RUN1, S_FATT_RUN2, S_FATT_RUN3, S_FATT_RUN4, S_FATT_RUN5, S_FATT_RUN6, S_FATT_RUN7, S_FATT_RUN8, S_FATT_RUN9, S_FATT_RUN10, S_FATT_RUN11, S_FATT_RUN12, S_FATT_ATK1, S_FATT_ATK2, S_FATT_ATK3, S_FATT_ATK4, S_FATT_ATK5, S_FATT_ATK6, S_FATT_ATK7, S_FATT_PAIN, S_FATT_PAIN2, S_FATT_DIE1, S_FATT_DIE2, S_FATT_DIE3, S_FATT_DIE4, S_FATT_DIE5, S_FATT_DIE6, S_POSS_STND, S_POSS_STND2, S_POSS_RUN1, S_POSS_RUN2, S_POSS_RUN3, S_POSS_RUN4, S_POSS_RUN5, S_POSS_RUN6, S_POSS_RUN7, S_POSS_RUN8, S_POSS_ATK1, S_POSS_ATK2, S_POSS_ATK3, S_POSS_PAIN, S_POSS_PAIN2, S_POSS_DIE1, S_POSS_DIE2, S_POSS_DIE3, S_POSS_DIE4, S_POSS_DIE5, S_POSS_XDIE1, S_POSS_XDIE2, S_POSS_XDIE3, S_POSS_XDIE4, S_POSS_XDIE5, S_POSS_XDIE6, S_POSS_XDIE7, S_POSS_XDIE8, S_POSS_XDIE9, S_SPOS_STND, S_SPOS_STND2, S_SPOS_RUN1, S_SPOS_RUN2, S_SPOS_RUN3, S_SPOS_RUN4, S_SPOS_RUN5, S_SPOS_RUN6, S_SPOS_RUN7, S_SPOS_RUN8, S_SPOS_ATK1, S_SPOS_ATK2, S_SPOS_ATK3, S_SPOS_PAIN, S_SPOS_PAIN2, S_SPOS_DIE1, S_SPOS_DIE2, S_SPOS_DIE3, S_SPOS_DIE4, S_SPOS_DIE5, S_SPOS_XDIE1, S_SPOS_XDIE2, S_SPOS_XDIE3, S_SPOS_XDIE4, S_SPOS_XDIE5, S_SPOS_XDIE6, S_SPOS_XDIE7, S_SPOS_XDIE8, S_SPOS_XDIE9, S_TROO_STND, S_TROO_STND2, S_TROO_RUN1, S_TROO_RUN2, S_TROO_RUN3, S_TROO_RUN4, S_TROO_RUN5, S_TROO_RUN6, S_TROO_RUN7, S_TROO_RUN8, S_TROO_MEL1, S_TROO_MEL2, S_TROO_MEL3, S_TROO_ATK1, S_TROO_ATK2, S_TROO_ATK3, S_TROO_PAIN, S_TROO_PAIN2, S_TROO_DIE1, S_TROO_DIE2, S_TROO_DIE3, S_TROO_DIE4, S_TROO_DIE5, S_TROO_XDIE1, S_TROO_XDIE2, S_TROO_XDIE3, S_TROO_XDIE4, S_TROO_XDIE5, S_TROO_XDIE6, S_TROO_XDIE7, S_TROO_XDIE8, S_NTRO_STND, S_NTRO_STND2, S_NTRO_RUN1, S_NTRO_RUN2, S_NTRO_RUN3, S_NTRO_RUN4, S_NTRO_RUN5, S_NTRO_RUN6, S_NTRO_RUN7, S_NTRO_RUN8, S_NTRO_MEL1, S_NTRO_MEL2, S_NTRO_MEL3, S_NTRO_ATK1, S_NTRO_ATK2, S_NTRO_ATK3, S_NTRO_PAIN, S_NTRO_PAIN2, S_NTRO_DIE1, S_NTRO_DIE2, S_NTRO_DIE3, S_NTRO_DIE4, S_NTRO_DIE5, S_NTRO_XDIE1, S_NTRO_XDIE2, S_NTRO_XDIE3, S_NTRO_XDIE4, S_NTRO_XDIE5, S_NTRO_XDIE6, S_NTRO_XDIE7, S_NTRO_XDIE8, S_HEAD_STND, S_HEAD_STND2, S_HEAD_STND3, S_HEAD_STND4, S_HEAD_RUN1, S_HEAD_RUN2, S_HEAD_RUN3, S_HEAD_RUN4, S_HEAD_RUN5, S_HEAD_RUN6, S_HEAD_RUN7, S_HEAD_RUN8, S_HEAD_ATK1, S_HEAD_ATK2, S_HEAD_ATK3, S_HEAD_ATK4, S_HEAD_PAIN, S_HEAD_PAIN2, S_HEAD_PAIN3, S_HEAD_DIE1, S_HEAD_DIE2, S_HEAD_DIE3, S_HEAD_DIE4, S_HEAD_DIE5, S_HEAD_DIE6, S_BOSS_STND, S_BOSS_STND2, S_BOSS_RUN1, S_BOSS_RUN2, S_BOSS_RUN3, S_BOSS_RUN4, S_BOSS_RUN5, S_BOSS_RUN6, S_BOSS_RUN7, S_BOSS_RUN8, S_BOSS_ATK1, S_BOSS_ATK2, S_BOSS_ATK3, S_BOSS_PAIN, S_BOSS_PAIN2, S_BOSS_DIE1, S_BOSS_DIE2, S_BOSS_DIE3, S_BOSS_DIE4, S_BOSS_DIE5, S_BOSS_DIE6, S_BOS2_STND, S_BOS2_STND2, S_BOS2_RUN1, S_BOS2_RUN2, S_BOS2_RUN3, S_BOS2_RUN4, S_BOS2_RUN5, S_BOS2_RUN6, S_BOS2_RUN7, S_BOS2_RUN8, S_BOS2_ATK1, S_BOS2_ATK2, S_BOS2_ATK3, S_BOS2_PAIN, S_BOS2_PAIN2, S_BOS2_DIE1, S_BOS2_DIE2, S_BOS2_DIE3, S_BOS2_DIE4, S_BOS2_DIE5, S_BOS2_DIE6, S_SKULL_STND, S_SKULL_STND2, S_SKULL_STND3, S_SKULL_RUN1, S_SKULL_RUN2, S_SKULL_RUN3, S_SKULL_ATK1, S_SKULL_ATK2, S_SKULL_ATK3, S_SKULL_ATK4, S_SKULL_PAIN, S_SKULL_PAIN2, S_SKULL_DIE1, S_SKULL_DIE2, S_SKULL_DIE3, S_SKULL_DIE4, S_SKULL_DIE5, S_SKULL_DIE6, S_SKULL_DIE7, S_SKULL_DIE8, S_SKULL_DIE9, S_SKULL_DIE10, S_BSPI_STND, S_BSPI_STND2, S_BSPI_SIGHT, S_BSPI_RUN1, S_BSPI_RUN2, S_BSPI_RUN3, S_BSPI_RUN4, S_BSPI_RUN5, S_BSPI_RUN6, S_BSPI_RUN7, S_BSPI_RUN8, S_BSPI_ATK1, S_BSPI_ATK2, S_BSPI_ATK3, S_BSPI_PAIN, S_BSPI_PAIN2, S_BSPI_DIE1, S_BSPI_DIE2, S_BSPI_DIE3, S_BSPI_DIE4, S_BSPI_DIE5, S_BSPI_DIE6, S_CYBER_STND, S_CYBER_RUN1, S_CYBER_RUN2, S_CYBER_RUN3, S_CYBER_RUN4, S_CYBER_RUN5, S_CYBER_RUN6, S_CYBER_RUN7, S_CYBER_RUN8, S_CYBER_ATK1, S_CYBER_ATK2, S_CYBER_ATK3, S_CYBER_ATK4, S_CYBER_ATK5, S_CYBER_ATK6, S_CYBER_PAIN, S_CYBER_DIE1, S_CYBER_DIE2, S_CYBER_DIE3, S_CYBER_DIE4, S_CYBER_DIE5, S_CYBER_DIE6, S_CYBER_DIE7, S_CYBER_DIE8, S_CYBER_DIE9, S_DCYBER_STND, S_DCYBER_ATK1, S_DCYBER_ATK2, S_PAIN_STND, S_PAIN_SEE, S_PAIN_ATK1, S_PAIN_ATK2, S_PAIN_ATK3, S_PAIN_ATK4, S_PAIN_PAIN, S_PAIN_PAIN2, S_PAIN_DIE1, S_PAIN_DIE2, S_PAIN_DIE3, S_PAIN_DIE4, S_PAIN_DIE5, S_PAIN_DIE6, S_PAIN_DIE7, S_PAIN_DIE8, S_RECT_STND, S_RECT_STND2, S_RECT_STND3, S_RECT_STND4, S_RECT_RUN1, S_RECT_RUN2, S_RECT_RUN3, S_RECT_RUN4, S_RECT_RUN5, S_RECT_RUN6, S_RECT_RUN7, S_RECT_RUN8, S_RECT_RUN9, S_RECT_RUN10, S_RECT_RUN11, S_RECT_RUN12, S_RECT_ATK1, S_RECT_ATK2, S_RECT_ATK3, S_RECT_ATK4, S_RECT_ATK5, S_RECT_PAIN, S_RECT_DIE1, S_RECT_DIE2, S_RECT_DIE3, S_RECT_DIE4, S_RECT_DIE5, S_RECT_DIE6, S_RECT_DIE7, S_BAL3, S_BAL32, S_BAL33, S_BAL3EXP, S_BAL3EXP2, S_BAL3EXP3, S_BAL3EXP4, S_BAL3EXP5, S_BAL3EXP6, S_BRBALL1, S_BRBALL2, S_BRBALLX1, S_BRBALLX2, S_BRBALLX3, S_BRBALLX4, S_BRBALLX5, S_BRBALLX6, S_ARACH_PLAZ, S_ARACH_PLAZ2, S_ARACH_PLEX, S_ARACH_PLEX2, S_ARACH_PLEX3, S_ARACH_PLEX4, S_ARACH_PLEX5, S_ARACH_PLEX6, S_FATSHOT1, S_FATSHOT2, S_FATSHOT3, S_FATSHOTX1, S_FATSHOTX2, S_FATSHOTX3, S_FATSHOTX4, S_FATSHOTX5, S_FATSHOTX6, S_TSHOT6_STND, S_TSHOT6_STND2, S_TSHOT6_RUN1, S_TSHOT6_RUN2, S_TSHOT6_RUN3, S_TSHOT6_RUN4, S_TSHOT6_RUN5, S_TSHOT6_RUN6, S_DART, S_MPUFF1, S_MPUFF2, S_MPUFF3, S_MPUFF4, S_MPUFF5, S_RPUFF1, S_RPUFF2, S_RPUFF3, S_RPUFF4, S_RPUFF5, S_SMOKE1, S_SMOKE2, S_SMOKE3, S_SMOKE4, S_SMOKE5, S_PUFF1, S_PUFF2, S_PUFF3, S_PUFF4, S_PUFF5, S_PUFF6, S_BLOOD1, S_BLOOD2, S_BLOOD3, S_BLOOD4, S_TBALL1, S_TBALL2, S_TBALL3, S_TBALLX1, S_TBALLX2, S_TBALLX3, S_TBALLX4, S_TBALLX5, S_TBALLX6, S_PLASBALL, S_PLASBALL2, S_PLASEXP, S_PLASEXP2, S_PLASEXP3, S_PLASEXP4, S_PLASEXP5, S_PLASEXP6, S_ROCKET, S_ROCKET2, S_BFGSHOT, S_BFGSHOT2, S_BFGLAND, S_BFGLAND2, S_BFGLAND3, S_BFGLAND4, S_BFGLAND5, S_BFGLAND6, S_BFGEXP, S_BFGEXP2, S_BFGEXP3, S_BFGEXP4, S_BFGEXP5, S_BFGEXP6, S_EXPLODE0, S_EXPLODE1, S_EXPLODE2, S_EXPLODE3, S_EXPLODE4, S_EXPLODE5, S_TFOG, S_TFOG2, S_TFOG3, S_TFOG4, S_TFOG5, S_TFOG6, S_TFOG7, S_TFOG8, S_TFOG9, S_TFOG10, S_TFOG11, S_TFOG12, S_ARM1, S_ARM1A, S_ARM2, S_ARM2A, S_BON1, S_BON1A, S_BON1B, S_BON1C, S_BON2, S_BON2A, S_BON2B, S_BON2C, S_BON2D, S_BON2E, S_BKEY, S_BKEY2, S_RKEY, S_RKEY2, S_YKEY, S_YKEY2, S_YSKULL, S_YSKULL2, S_RSKULL, S_RSKULL2, S_BSKULL, S_BSKULL2, S_ART1, S_ART12, S_ART13, S_ART14, S_ART15, S_ART16, S_ART17, S_ART18, S_ART2, S_ART22, S_ART23, S_ART24, S_ART25, S_ART26, S_ART27, S_ART28, S_ART3, S_ART32, S_ART33, S_ART34, S_ART35, S_ART36, S_ART37, S_ART38, S_STIM, S_MEDI, S_SOUL, S_SOUL2, S_SOUL3, S_SOUL4, S_SOUL5, S_SOUL6, S_PINV, S_PINV2, S_PINV3, S_PINV4, S_PINV5, S_PINV6, S_PSTR, S_PINS, S_PINS2, S_PINS3, S_PINS4, S_PINS5, S_PINS6, S_SUIT, S_SUIT2, S_PMAP, S_PMAP2, S_PMAP3, S_PMAP4, S_PVIS, S_PVIS2, S_MEGA, S_MEGA2, S_MEGA3, S_MEGA4, S_MEGA5, S_MEGA6, S_CLIP, S_AMMO, S_ROCK, S_BROK, S_CELL, S_CELP, S_SHEL, S_SBOX, S_BPAK, S_BFUG, S_CSAW, S_MGUN, S_LAUN, S_PLSM, S_SHOT, S_SHOT2, S_LSRG, S_CANDLE, S_CANDLE2, S_BAR1, S_BAR2, S_BAR3, S_BAR4, S_BAR5, S_SAW, S_SAWB, S_SAWDOWN, S_SAWUP, S_SAW1, S_SAW2, S_SAW3, S_PUNCH, S_PUNCHDOWN, S_PUNCHUP, S_PUNCH1, S_PUNCH2, S_PUNCH3, S_PUNCH4, S_PUNCH5, S_PISTOL, S_PISTOLDOWN, S_PISTOLUP, S_PISTOL1, S_PISTOL2, S_PISTOL3, S_PISTOL4, S_PISTOL5, S_PISTOLFLASH, S_SGUN, S_SGUNDOWN, S_SGUNUP, S_SGUN1, S_SGUN2, S_SGUN3, S_SGUN4, S_SGUN5, S_SGUN6, S_SGUNFLASH1, S_DSGUN, S_DSGUNDOWN, S_DSGUNUP, S_DSGUN1, S_DSGUN2, S_DSGUN3, S_DSGUN4, S_DSGUN5, S_DSGUN6, S_DSGUN7, S_DSGUN8, S_DSGUN9, S_DSGUN10, S_DSGUNFLASH1, S_CHAIN, S_CHAINDOWN, S_CHAINUP, S_CHAIN1, S_CHAIN2, S_CHAIN3, S_CHAINFLASH1, S_CHAINFLASH2, S_MISSILE, S_MISSILEDOWN, S_MISSILEUP, S_MISSILE1, S_MISSILE2, S_MISSILE3, S_MISSILEFLASH1, S_MISSILEFLASH2, S_MISSILEFLASH3, S_MISSILEFLASH4, S_PLASMA, S_PLASMADOWN, S_PLASMAUP, S_PLASMAUP2, S_PLASMA1, S_PLASMA2, S_PLASMA3, S_PLASMASHOCK1, S_PLASMASHOCK2, S_PLASMASHOCK3, S_BFG, S_BFGDOWN, S_BFGUP, S_BFG1, S_BFG2, S_BFG3, S_BFG4, S_BFGFLASH1, S_BFGFLASH2, S_BFGFLASH3, S_UNKF, S_UNKFDOWN, S_UNKFUP, S_UNKF1, S_UNKF2, S_UNKFLASH1, S_COLU, S_DARTHIT, S_DARTHIT2, S_DARTHIT3, S_DARTHIT4, S_DARTHIT5, S_DARTHIT6, S_BLOODYTWITCH, S_DEADTORSO, S_DEADBOTTOM, S_HEADSONSTICK, S_GIBS, S_HEADONASTICK, S_HEADCANDLES, S_DEADSTICK, S_LIVESTICK, S_LIVESTICK2, S_MEAT2, S_MEAT3, S_MEAT4, S_MEAT5, S_STALAGTITE, S_TALLGRNCOL, S_SHRTGRNCOL, S_TALLREDCOL, S_SHRTREDCOL, S_CANDELABRA, S_SKULLCOL, S_TORCHTREE, S_BIGTREE, S_TECHPILLAR, S_BLUETORCH, S_BLUETORCH2, S_BLUETORCH3, S_BLUETORCH4, S_GREENTORCH, S_GREENTORCH2, S_GREENTORCH3, S_GREENTORCH4, S_REDTORCH, S_REDTORCH2, S_REDTORCH3, S_REDTORCH4, S_BTORCHSHRT, S_BTORCHSHRT2, S_BTORCHSHRT3, S_BTORCHSHRT4, S_BTORCHSHRT5, S_GTORCHSHRT, S_GTORCHSHRT2, S_GTORCHSHRT3, S_GTORCHSHRT4, S_GTORCHSHRT5, S_RTORCHSHRT, S_RTORCHSHRT2, S_RTORCHSHRT3, S_RTORCHSHRT4, S_RTORCHSHRT5, S_YFIREBALL1, S_YFIREBALL2, S_YFIREBALL3, S_YFIREBALL4, S_YFIREBALL5, S_BFIREBALL1, S_BFIREBALL2, S_BFIREBALL3, S_BFIREBALL4, S_RFIREBALL1, S_RFIREBALL2, S_RFIREBALL3, S_RFIREBALL4, S_Y2FIREBALL1, S_Y2FIREBALL2, S_Y2FIREBALL3, S_Y2FIREBALL4, S_B2FIREBALL1, S_B2FIREBALL2, S_B2FIREBALL3, S_B2FIREBALL4, S_R2FIREBALL1, S_R2FIREBALL2, S_R2FIREBALL3, S_R2FIREBALL4, S_HANGNOGUTS, S_HANGBNOBRAIN, S_HANGTLOOKDN, S_HANGTSKULL, S_HANGTLOOKUP, S_HANGTNOBRAIN, S_COLONGIBS, S_SMALLPOOL, S_BRAINSTEM, S_BRNRBALL1, S_BRNRBALL2, S_BRNRBALLX1, S_BRNRBALLX2, S_BRNRBALLX3, S_BRNRBALLX4, S_BRNRBALLX5, S_BRNRBALLX6, S_NMBL1, S_NMBL2, S_NMBL3, S_NMBLX1, S_NMBLX2, S_NMBLX3, S_NMBLX4, S_NMBLX5, S_NMBLX6, S_LAZR1, S_LAZR2, S_LAZRDTH, S_LAZRDTH2, S_LAZRDTH3, S_LAZRDTH4, S_LAZRDTH5, S_LAZRDTH6, S_LAZRDTH7, S_LAZRDTH8, S_LAZRDTH9, S_LAZRDTH10, S_LAZRDUST, S_LAZRW1, S_LAZRW2, S_RTRACER1, S_RTRACER2, S_RTRACEREXP, S_TECHLAMP, S_TECH2LAMP, S_TRACER, S_TRACER2, S_TRACER3, S_TRACEEXP1, S_TRACEEXP2, S_TRACEEXP3, S_TRACEEXP4, S_TRACEEXP5, S_TRACEEXP6, S_DISSOUL1, S_DISSOUL2, S_DISSOUL3, S_DISSOUL4, S_DISSOUL5, S_DISSOUL6, S_DISSOUL7, S_DISSOUL8, S_DISSOUL9, S_DBKEY1, S_DBKEY2, S_DBKEY3, S_DBKEY4, S_DBKEY5, S_DBKEY6, S_DBKEY7, S_DBKEY8, S_DBKEY9, S_DBKEY10, S_DBKEY11, S_DBKEY12, S_DBKEY13, S_DBKEY14, S_DBKEY15, S_DBKEY16, S_DBKEY17, S_DBKEY18, S_DBKEY19, S_IFOG, S_IFOG01, S_IFOG02, S_IFOG2, S_IFOG3, S_IFOG4, S_IFOG5, S_SMALL_WHITE_LIGHT, S_TEMPSOUNDORIGIN1, NUMSTATES } statenum_t; // Map objects. typedef enum { MT_NONE = -1, MT_FIRST = 0, MT_PLAYER = MT_FIRST, MT_EMARINEL, MT_EMARINEP, MT_EMARINES, MT_POSSESSED, MT_SHOTGUY, MT_TRACER, MT_SMOKE, MT_FATSO, MT_FATSHOT, MT_TROOP, MT_SERGEANT, MT_SHADOWS, MT_HEAD, MT_BRUISER, MT_BRUISERSHOT, MT_KNIGHT, MT_SKULL, MT_BABY, MT_CYBORG, MT_DCYBORG, MT_PAIN, MT_EMARINER, MT_BARREL, MT_TROOPSHOT, MT_HEADSHOT, MT_ROCKET, MT_CYBERROCKET, MT_PLASMA, MT_BFG, MT_ARACHPLAZ, MT_PUFF, MT_BLOOD, MT_TFOG, MT_IFOG, MT_TELEPORTMAN, MT_EXTRABFG, MT_MISC0, MT_MISC1, MT_MISC2, MT_MISC3, MT_MISC4, MT_MISC5, MT_MISC6, MT_MISC7, MT_MISC8, MT_MISC9, MT_MISC10, MT_MISC11, MT_MISC12, MT_INV, MT_MISC13, MT_INS, MT_MISC14, MT_MISC15, MT_MISC16, MT_MEGA, MT_CLIP, MT_MISC17, MT_MISC18, MT_MISC19, MT_MISC20, MT_MISC21, MT_MISC22, MT_MISC23, MT_MISC24, MT_MISC25, MT_CHAINGUN, MT_MISC26, MT_MISC27, MT_MISC28, MT_SHOTGUN, MT_SUPERSHOTGUN, MT_MISC29, MT_MISC30, MT_MISC31, MT_MISC32, MT_MISC33, MT_MISC34, MT_MISC35, MT_MISC36, MT_MISC40, MT_MISC41, MT_MISC42, MT_MISC43, MT_MISC44, MT_MISC45, MT_MISC46, MT_MISC47, MT_MISC48, MT_MISC49, MT_MISC50, MT_MISC51, MT_MISC52, MT_MISC53, MT_MISC54, MT_MISC55, MT_MISC56, MT_MISC57, MT_MISC58, MT_MISC59, MT_MISC60, MT_MISC68, MT_MISC69, MT_MISC70, MT_MISC71, MT_MISC72, MT_MISC73, MT_MISC74, MT_MISC75, MT_MISC76, MT_MISC78, MT_MISC79, MT_MISC80, MT_MISC81, MT_MISC82, MT_MISC83, MT_MISC84, MT_MISC85, MT_MISC86, MT_BRUISERSHOTRED, MT_NTROSHOT, MT_ROCKETPUFF, MT_LASERGUN, MT_LASERSHOT, MT_LASERDUST, MT_LPOWERUP1, MT_LPOWERUP2, MT_LPOWERUP3, MT_LASERSHOTWEAK, MT_BITCH, MT_BITCHBALL, MT_MOTHERPUFF, MT_DART, //LIST OF SPAWN THINGS - SAMUEL MT_TELEPORTSHOT, MT_TELEPORTCHAIN, MT_TELEPORTSSHOT, MT_TELEPORTROCKET, MT_TELEPORTPLASMA, MT_TELEPORTBFG, MT_TELEPORTMEDKIT, MT_TELEPORTSTIM, MT_TELEPORTARMOR1, MT_TELEPORTARMOR2, MT_TELEPORTLASER, MT_TELEPORTLKEY1, MT_TELEPORTLKEY2, MT_TELEPORTLKEY3, MT_TELEPORTMEGA, MT_TELEPORTSOUL, MT_TELEPORTBLUR, MT_TELEPORTINVUL, MT_TELEPORTBERSERK, MT_TELEPORTPOTION, MT_TELEPORTHELMET, MT_TELEPORTMAP, MT_TELEPORTLIGHT, MT_TELEPORTSUIT, MT_TELEPORTSHELL, MT_TELEPORTSBOX, MT_TELEPORTCLIP, MT_TELEPORTBULLETS, MT_TELEPORTRROCKET, MT_TELEPORTRBOX, MT_TELEPORTCELL, MT_TELEPORTCBOX, MT_TELEPORTBACKPACK, MT_TELEPORTPOSS, MT_TELEPORTSPOS, MT_TELEPORTTROOP, MT_TELEPORTNTROP, MT_TELEPORTSARG, MT_TELEPORTSARG2, MT_TELEPORTNSARG, MT_TELEPORTHEAD, MT_TELEPORTHEAD2, MT_TELEPORTLOSTSOUL, MT_TELEPORTPAIN, MT_TELEPORTFATSO, MT_TELEPORTBABY, MT_TELEPORTCYBORG, MT_TELEPORTBITCH, MT_TELEPORTKNIGHT, MT_TELEPORTBARON, MT_TELEPORTRKEY, MT_TELEPORTRKEY2, MT_TELEPORTBKEY, MT_TELEPORTBKEY2, MT_TELEPORTYKEY, MT_TELEPORTYKEY2, MT_NTROOP, MT_KABOOM, MT_LIGHTSOURCE, MT_TEMPSOUNDORIGIN, MT_FAKEKNIGHT, MT_FAKETROOP, MT_FAKESHADOWS, MT_FAKESKULL, MT_F_BRUISER, MT_TRACER6, MT_YELLOWFIREBALL, MT_BLUEFIREBALL, MT_REDFIREBALL, MT_YELLOWFIREBALL2, MT_BLUEFIREBALL2, MT_REDFIREBALL2, MT_FSHOTGUY, MT_FDEMON, MT_FPAIN, MT_DISSOUL, MT_DISBKEY, MT_FBABY, MT_FFATSO, NUMMOBJTYPES } mobjtype_t; // Text. typedef enum { TXT_PRESSKEY, TXT_PRESSYN, TXT_QUITMSG, TXT_LOADNET, TXT_QLOADNET, TXT_QSAVESPOT, TXT_SAVEDEAD, TXT_QSPROMPT, TXT_QLPROMPT, TXT_NEWGAME, TXT_MSGOFF, TXT_MSGON, TXT_NETEND, TXT_ENDGAME, TXT_GAMMALVL0, TXT_GAMMALVL1, TXT_GAMMALVL2, TXT_GAMMALVL3, TXT_GAMMALVL4, TXT_EMPTYSTRING, TXT_GOTARMOR, TXT_GOTMEGA, TXT_GOTHTHBONUS, TXT_GOTARMBONUS, TXT_GOTSTIM, TXT_GOTMEDINEED, TXT_GOTMEDIKIT, TXT_GOTSUPER, TXT_GOTBLUECARD, TXT_GOTYELWCARD, TXT_GOTREDCARD, TXT_GOTBLUESKUL, TXT_GOTYELWSKUL, TXT_GOTREDSKULL, TXT_GOTINVUL, TXT_GOTBERSERK, TXT_GOTINVIS, TXT_GOTSUIT, TXT_GOTMAP, TXT_GOTVISOR, TXT_GOTMSPHERE, TXT_GOTCLIP, TXT_GOTCLIPBOX, TXT_GOTROCKET, TXT_GOTROCKBOX, TXT_GOTCELL, TXT_GOTCELLBOX, TXT_GOTSHELLS, TXT_GOTSHELLBOX, TXT_GOTBACKPACK, TXT_GOTBFG9000, TXT_GOTCHAINGUN, TXT_GOTCHAINSAW, TXT_GOTLAUNCHER, TXT_GOTPLASMA, TXT_GOTSHOTGUN, TXT_GOTSHOTGUN2, TXT_GOTUNMAKER, TXT_NGOTUNMAKER, TXT_UNMAKERCHARGE, TXT_GOTPOWERUP1, TXT_NGOTPOWERUP1, TXT_GOTPOWERUP2, TXT_NGOTPOWERUP2, TXT_GOTPOWERUP3, TXT_NGOTPOWERUP3, TXT_PD_OPNPOWERUP, TXT_PD_BLUEO, TXT_PD_REDO, TXT_PD_YELLOWO, TXT_PD_BLUEK, TXT_PD_REDK, TXT_PD_YELLOWK, TXT_GGSAVED, TXT_HUSTR_MSGU, TXT_HUSTR_MAP01, TXT_HUSTR_MAP02, TXT_HUSTR_MAP03, TXT_HUSTR_MAP04, TXT_HUSTR_MAP05, TXT_HUSTR_MAP06, TXT_HUSTR_MAP07, TXT_HUSTR_MAP08, TXT_HUSTR_MAP09, TXT_HUSTR_MAP10, TXT_HUSTR_MAP11, TXT_HUSTR_MAP12, TXT_HUSTR_MAP13, TXT_HUSTR_MAP14, TXT_HUSTR_MAP15, TXT_HUSTR_MAP16, TXT_HUSTR_MAP17, TXT_HUSTR_MAP18, TXT_HUSTR_MAP19, TXT_HUSTR_MAP20, TXT_HUSTR_MAP21, TXT_HUSTR_MAP22, TXT_HUSTR_MAP23, TXT_HUSTR_MAP24, TXT_HUSTR_MAP25, TXT_HUSTR_MAP26, TXT_HUSTR_MAP27, TXT_HUSTR_MAP28, TXT_HUSTR_MAP29, TXT_HUSTR_MAP30, TXT_HUSTR_MAP31, TXT_HUSTR_MAP32, TXT_HUSTR_MAP33, TXT_HUSTR_CHATMACRO0, TXT_HUSTR_CHATMACRO1, TXT_HUSTR_CHATMACRO2, TXT_HUSTR_CHATMACRO3, TXT_HUSTR_CHATMACRO4, TXT_HUSTR_CHATMACRO5, TXT_HUSTR_CHATMACRO6, TXT_HUSTR_CHATMACRO7, TXT_HUSTR_CHATMACRO8, TXT_HUSTR_CHATMACRO9, TXT_HUSTR_TALKTOSELF1, TXT_HUSTR_TALKTOSELF2, TXT_HUSTR_TALKTOSELF3, TXT_HUSTR_TALKTOSELF4, TXT_HUSTR_TALKTOSELF5, TXT_HUSTR_MESSAGESENT, TXT_HUSTR_PLRGREEN, TXT_HUSTR_PLRINDIGO, TXT_HUSTR_PLRBROWN, TXT_HUSTR_PLRRED, TXT_AMSTR_FOLLOWON, TXT_AMSTR_FOLLOWOFF, TXT_AMSTR_GRIDON, TXT_AMSTR_GRIDOFF, TXT_AMSTR_MARKEDSPOT, TXT_AMSTR_MARKSCLEARED, TXT_STSTR_MUS, TXT_STSTR_NOMUS, TXT_STSTR_DQDON, TXT_STSTR_DQDOFF, TXT_STSTR_KFAADDED, TXT_STSTR_FAADDED, TXT_STSTR_NCON, TXT_STSTR_NCOFF, TXT_STSTR_BEHOLD, TXT_STSTR_BEHOLDX, TXT_STSTR_CHOPPERS, TXT_STSTR_CLEV, TXT_C1TEXT, TXT_C2TEXT, TXT_C3TEXT, TXT_C4TEXT, TXT_CC_ZOMBIE, TXT_CC_SHOTGUN, TXT_CC_IMP, TXT_CC_DEMON, TXT_CC_LOST, TXT_CC_CACO, TXT_CC_HELL, TXT_CC_BARON, TXT_CC_ARACH, TXT_CC_PAIN, TXT_CC_MANCU, TXT_CC_CYBER, TXT_CC_NTROOP, TXT_CC_BITCH, TXT_CC_HERO, TXT_QUITMESSAGE1, TXT_QUITMESSAGE2, TXT_QUITMESSAGE3, TXT_QUITMESSAGE4, TXT_QUITMESSAGE5, TXT_QUITMESSAGE6, TXT_QUITMESSAGE7, TXT_QUITMESSAGE8, TXT_QUITMESSAGE9, TXT_QUITMESSAGE10, TXT_QUITMESSAGE11, TXT_QUITMESSAGE12, TXT_QUITMESSAGE13, TXT_QUITMESSAGE14, TXT_QUITMESSAGE15, TXT_QUITMESSAGE16, TXT_QUITMESSAGE17, TXT_QUITMESSAGE18, TXT_QUITMESSAGE19, TXT_QUITMESSAGE20, TXT_QUITMESSAGE21, TXT_QUITMESSAGE22, TXT_JOINNET, TXT_SAVENET, TXT_CLNETLOAD, TXT_LOADMISSING, TXT_FINALEFLAT_C2, TXT_FINALEFLAT_C1, TXT_FINALEFLAT_C3, TXT_FINALEFLAT_C4, TXT_FINALEFLAT_C5, TXT_FINALEFLAT_C6, TXT_FINALEFLAT_C7, TXT_FINALEFLAT_C8, TXT_FINALEFLAT_C9, TXT_KILLMSG_SUICIDE, TXT_KILLMSG_WEAPON0, TXT_KILLMSG_PISTOL, TXT_KILLMSG_SHOTGUN, TXT_KILLMSG_CHAINGUN, TXT_KILLMSG_MISSILE, TXT_KILLMSG_PLASMA, TXT_KILLMSG_BFG, TXT_KILLMSG_CHAINSAW, TXT_KILLMSG_SUPERSHOTGUN, TXT_KILLMSG_UNMAKER, TXT_KILLMSG_STOMP, TXT_AMSTR_ROTATEON, TXT_AMSTR_ROTATEOFF, TXT_WEAPON1, TXT_WEAPON2, TXT_WEAPON3, TXT_WEAPON4, TXT_WEAPON5, TXT_WEAPON6, TXT_WEAPON7, TXT_WEAPON8, TXT_WEAPON9, TXT_WEAPON10, TXT_SKILL1, TXT_SKILL2, TXT_SKILL3, TXT_SKILL4, TXT_KEY1, TXT_KEY2, TXT_KEY3, TXT_KEY4, TXT_KEY5, TXT_KEY6, TXT_DEMONKEY1, TXT_DEMONKEY2, TXT_DEMONKEY3, TXT_SAVEOUTMAP, TXT_ENDNOGAME, TXT_SUICIDEOUTMAP, TXT_SUICIDEASK, TXT_PICKGAMETYPE, TXT_SINGLEPLAYER, TXT_MULTIPLAYER, TXT_NOTDESIGNEDFOR, TXT_GAMESETUP, TXT_PLAYERSETUP, NUMTEXT } textenum_t; // Sounds. typedef enum { SFX_NONE, SFX_PISTOL, SFX_SHOTGN, SFX_SGCOCK, SFX_DSHTGN, SFX_DBOPN, SFX_DBCLS, SFX_DBLOAD, SFX_PLASMA, SFX_BFG, SFX_SAWUP, SFX_SAWIDL, SFX_SAWFUL, SFX_SAWHIT, SFX_RLAUNC, SFX_RXPLOD, SFX_FIRSHT, SFX_FIRXPL, SFX_PSTART, SFX_PSTOP, SFX_DOROPN, SFX_DORCLS, SFX_STNMOV, SFX_SWTCHN, SFX_SWTCHX, SFX_PLPAIN, SFX_DMPAIN, SFX_POPAIN, SFX_VIPAIN, SFX_MNPAIN, SFX_PEPAIN, SFX_SLOP, SFX_ITEMUP, SFX_WPNUP, SFX_OOF, SFX_TELEPT, SFX_POSIT1, SFX_POSIT2, SFX_POSIT3, SFX_BGSIT1, SFX_BGSIT2, SFX_SGTSIT, SFX_CACSIT, SFX_BRSSIT, SFX_CYBSIT, SFX_BSPSIT, SFX_KNTSIT, SFX_VILSIT, SFX_MANSIT, SFX_PESIT, SFX_SKLATK, SFX_SGTATK, SFX_SKEPCH, SFX_VILATK, SFX_CLAW, SFX_SKESWG, SFX_PLDETH, SFX_PDIEHI, SFX_PODTH1, SFX_PODTH2, SFX_PODTH3, SFX_BGDTH1, SFX_BGDTH2, SFX_SGTDTH, SFX_CACDTH, SFX_SKLDTH, SFX_BRSDTH, SFX_CYBDTH, SFX_BSPDTH, SFX_VILDTH, SFX_KNTDTH, SFX_PEDTH, SFX_SKEDTH, SFX_POSACT, SFX_BGACT, SFX_DMACT, SFX_BSPACT, SFX_BSPWLK, SFX_VILACT, SFX_NOWAY, SFX_BAREXP, SFX_PUNCH, SFX_HOOF, SFX_MEAL, SFX_CHGUN, SFX_TINK, SFX_BDOPN, SFX_BDCLS, SFX_ITMBK, SFX_FLAME, SFX_FLAMST, SFX_GETPOW, SFX_MANATK, SFX_MANDTH, SFX_SSSIT, SFX_SSDTH, SFX_SKEACT, SFX_SKESIT, SFX_SKEATK, SFX_RADIO, // jd64 > SFX_PSIDL, SFX_LASER, SFX_MTHATK, SFX_MTHSIT, SFX_MTHPAI, SFX_MTHACT, SFX_MTHDTH, SFX_HTIME, // < D64TC SFX_SECRET, NUMSFX } sfxenum_t; /** * Music. * These ids are no longer used. All tracks are played by ident. typedef enum { MUS_NONE, MUS_RUNNIN, MUS_STALKS, MUS_COUNTD, MUS_BETWEE, MUS_DOOM, MUS_THE_DA, MUS_DDTBLU, MUS_DEAD, MUS_STLKS2, MUS_THEDA2, MUS_DOOM2, MUS_DDTBL2, MUS_RUNNI2, MUS_STLKS3, MUS_SHAWN2, MUS_COUNT2, MUS_DDTBL3, MUS_AMPIE, MUS_EVIL, MUS_READ_M, MUS_DM2TTL, MUS_DM2INT, NUMMUSIC } musicenum_t;*/ #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/st_stuff.h0000644000175000017500000000425111357170242023463 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.h: Statusbar code jDoom64 - specific. * * Does palette indicators as well (red pain/berserk, bright pickup) */ #ifndef __ST_STUFF_H__ #define __ST_STUFF_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // Palette indices. // For damage/bonus red-/gold-shifts #define STARTREDPALS (1) #define STARTBONUSPALS (9) #define NUMREDPALS (8) #define NUMBONUSPALS (4) #define HUDBORDERX (14) #define HUDBORDERY (18) typedef enum hotloc_e { HOT_TLEFT, HOT_TRIGHT, HOT_BRIGHT, HOT_BLEFT } hotloc_t; // Called by main loop. void ST_Ticker(void); // Called by main loop. void ST_Drawer(int player, int fullscreenmode); void ST_Start(int player); void ST_Stop(int player); // Called by startup code. void ST_Register(void); void ST_Init(void); // Called when it might be neccessary for the hud to unhide. void ST_HUDUnHide(int player, hueevent_t event); void ST_HUDSpriteSize(int sprite, int *w, int *h); void ST_drawHUDSprite(int sprite, float x, float y, hotloc_t hotspot, float scale, float alpha, boolean flip); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_lights.h0000644000175000017500000000626311357170242023444 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.c: Handle Sector base lighting effects. */ #ifndef __P_LIGHTS_H__ #define __P_LIGHTS_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #define GLOWSPEED (8) #define STROBEBRIGHT (5) #define FASTDARK (15) #define SLOWDARK (35) typedef struct { thinker_t thinker; sector_t* sector; int count; float maxLight; float minLight; } fireflicker_t; typedef struct { thinker_t thinker; sector_t* sector; int count; float maxLight; float minLight; int maxTime; int minTime; } lightflash_t; typedef struct { thinker_t thinker; sector_t* sector; int count; float maxLight; float minLight; int maxTime; int minTime; } lightblink_t; typedef struct { thinker_t thinker; sector_t* sector; int count; float minLight; float maxLight; int darkTime; int brightTime; } strobe_t; typedef struct { thinker_t thinker; sector_t* sector; float minLight; float maxLight; int direction; } glow_t; void T_FireFlicker(fireflicker_t* flick); void P_SpawnFireFlicker(sector_t* sector); void T_LightFlash(lightflash_t* flash); void P_SpawnLightFlash(sector_t* sector); void T_LightBlink(lightblink_t* flash); void P_SpawnLightBlink(sector_t* sector); void T_StrobeFlash(strobe_t* flash); void P_SpawnStrobeFlash(sector_t* sector, int fastOrSlow, int inSync); void T_Glow(glow_t* g); void P_SpawnGlowingLight(sector_t* sector); void EV_StartLightStrobing(linedef_t* line); void EV_TurnTagLightsOff(linedef_t* line); void EV_LightTurnOn(linedef_t* line, float max); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_api.h0000644000175000017500000000242611357170242022704 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_api.c: Doomsday API setup and interaction - jDoom64 specific */ #ifndef __D_API_H__ #define __D_API_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "dd_api.h" extern game_import_t gi; extern game_export_t gx; int G_GetInteger(int id); void *G_GetVariable(int id); game_export_t *GetGameAPI(game_import_t *imports); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_sound.h0000644000175000017500000000234711357170242023301 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sound.h: */ #ifndef __P_SOUND_H__ #define __P_SOUND_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "doomsday.h" enum { SORG_CENTER, SORG_FLOOR, SORG_CEILING }; void S_MapMusic(uint episode, uint map); void S_SectorSound(sector_t* sec, int origin, int id); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/mn_def.h0000644000175000017500000000670611357170242023065 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * mn_def.h: Menu defines and types. */ #ifndef __MENU_DEFS_H__ #define __MENU_DEFS_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "hu_stuff.h" #include "r_defs.h" #include "m_defs.h" // Macros #define LEFT_DIR 0 #define RIGHT_DIR 1 #define DIR_MASK 0x1 #define ITEM_HEIGHT 20 #define SLOTTEXTLEN 16 #define ASCII_CURSOR '[' #define LINEHEIGHT 16 #define LINEHEIGHT_B 15 #define LINEHEIGHT_A 8 #define MENUCURSOR_OFFSET_X -6 #define MENUCURSOR_OFFSET_Y -2 #define MENUCURSOR_TICSPERFRAME 6 #define CURSORPREF "M_SKULL%d" #define SKULLBASELMP "M_SKL00" #define NUMCURSORS 8 #define NUMSAVESLOTS 8 #define MAX_EDIT_LEN 256 // Types typedef struct { char text[MAX_EDIT_LEN]; char oldtext[MAX_EDIT_LEN]; // If the current edit is canceled... int firstVisible; } editfield_t; typedef enum { MENU_MAIN, MENU_NEWGAME, MENU_SKILL, MENU_OPTIONS, MENU_OPTIONS2, MENU_GAMEPLAY, MENU_HUD, MENU_MAP, MENU_LOAD, MENU_SAVE, MENU_MULTIPLAYER, MENU_GAMESETUP, MENU_PLAYERSETUP, MENU_WEAPONS, MENU_CONTROLS, MENU_NONE } menutype_t; extern int menuTime; extern boolean shiftdown; extern menu_t *currentMenu; extern short itemOn; extern menu_t MapDef; // Multiplayer menus. extern menu_t MultiplayerMenu; extern menu_t GameSetupMenu; extern menu_t PlayerSetupMenu; void M_DrawTitle(char *text, int y); void M_WriteMenuText(const menu_t *menu, int index, const char *text); // Color widget. void DrawColorWidget(); void SCColorWidget(int index, void *data); void M_WGCurrentColor(int option, void *data); void M_DrawSaveLoadBorder(int x, int y, int width); void M_SetupNextMenu(menu_t *menu); void M_DrawThermo(int x, int y, int thermWidth, int thermDot); void MN_DrawSlider(const menu_t *menu, int item, int width, int slot); void MN_DrawColorBox(const menu_t *menu, int index, float r, float g, float b, float a); void M_StartControlPanel(void); void M_FloatMod10(float *variable, int option); void SCEnterMultiplayerMenu(int option, void *data); void MN_TickerEx(void); // The extended ticker. void M_ToggleVar(int option, void* context); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/m_cheat.h0000644000175000017500000000201511357170242023222 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef M_CHEAT_H #define M_CHEAT_H #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #endif /* M_CHEAT_H */ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_englsh.h0000644000175000017500000002373411357170242023420 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_englsh.h: Printed strings for translation (native is English). */ #ifndef __D_ENGLSH_H__ #define __D_ENGLSH_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #define GET_TXT(x) ((*gi.text)[x].text) #define D_DEVSTR GET_TXT(TXT_D_DEVSTR) #define PRESSKEY GET_TXT(TXT_PRESSKEY) #define PRESSYN GET_TXT(TXT_PRESSYN) #define QUITMSG GET_TXT(TXT_QUITMSG) #define LOADNET GET_TXT(TXT_LOADNET) #define QLOADNET GET_TXT(TXT_QLOADNET) #define QSAVESPOT GET_TXT(TXT_QSAVESPOT) #define SAVEDEAD GET_TXT(TXT_SAVEDEAD) #define SAVEOUTMAP GET_TXT(TXT_SAVEOUTMAP) #define SAVENET GET_TXT(TXT_SAVENET) #define QSPROMPT GET_TXT(TXT_QSPROMPT) #define QLPROMPT GET_TXT(TXT_QLPROMPT) #define NEWGAME GET_TXT(TXT_NEWGAME) #define SWSTRING GET_TXT(TXT_SWSTRING) #define MSGOFF GET_TXT(TXT_MSGOFF) #define MSGON GET_TXT(TXT_MSGON) #define NETEND GET_TXT(TXT_NETEND) #define ENDGAME GET_TXT(TXT_ENDGAME) #define ENDNOGAME GET_TXT(TXT_ENDNOGAME) #define SUICIDEOUTMAP GET_TXT(TXT_SUICIDEOUTMAP) #define SUICIDEASK GET_TXT(TXT_SUICIDEASK) #define GAMMALVL0 GET_TXT(TXT_GAMMALVL0) #define GAMMALVL1 GET_TXT(TXT_GAMMALVL1) #define GAMMALVL2 GET_TXT(TXT_GAMMALVL2) #define GAMMALVL3 GET_TXT(TXT_GAMMALVL3) #define GAMMALVL4 GET_TXT(TXT_GAMMALVL4) #define EMPTYSTRING GET_TXT(TXT_EMPTYSTRING) #define GOTARMOR GET_TXT(TXT_GOTARMOR) #define GOTMEGA GET_TXT(TXT_GOTMEGA) #define GOTHTHBONUS GET_TXT(TXT_GOTHTHBONUS) #define GOTARMBONUS GET_TXT(TXT_GOTARMBONUS) #define GOTSTIM GET_TXT(TXT_GOTSTIM) #define GOTMEDINEED GET_TXT(TXT_GOTMEDINEED) #define GOTMEDIKIT GET_TXT(TXT_GOTMEDIKIT) #define GOTSUPER GET_TXT(TXT_GOTSUPER) #define GOTBLUECARD GET_TXT(TXT_GOTBLUECARD) #define GOTYELWCARD GET_TXT(TXT_GOTYELWCARD) #define GOTREDCARD GET_TXT(TXT_GOTREDCARD) #define GOTBLUESKUL GET_TXT(TXT_GOTBLUESKUL) #define GOTYELWSKUL GET_TXT(TXT_GOTYELWSKUL) #define GOTREDSKULL GET_TXT(TXT_GOTREDSKULL) #define GOTINVUL GET_TXT(TXT_GOTINVUL) #define GOTBERSERK GET_TXT(TXT_GOTBERSERK) #define GOTINVIS GET_TXT(TXT_GOTINVIS) #define GOTSUIT GET_TXT(TXT_GOTSUIT) #define GOTMAP GET_TXT(TXT_GOTMAP) #define GOTVISOR GET_TXT(TXT_GOTVISOR) #define GOTMSPHERE GET_TXT(TXT_GOTMSPHERE) #define GOTCLIP GET_TXT(TXT_GOTCLIP) #define GOTCLIPBOX GET_TXT(TXT_GOTCLIPBOX) #define GOTROCKET GET_TXT(TXT_GOTROCKET) #define GOTROCKBOX GET_TXT(TXT_GOTROCKBOX) #define GOTCELL GET_TXT(TXT_GOTCELL) #define GOTCELLBOX GET_TXT(TXT_GOTCELLBOX) #define GOTSHELLS GET_TXT(TXT_GOTSHELLS) #define GOTSHELLBOX GET_TXT(TXT_GOTSHELLBOX) #define GOTBACKPACK GET_TXT(TXT_GOTBACKPACK) #define GOTBFG9000 GET_TXT(TXT_GOTBFG9000) #define GOTCHAINGUN GET_TXT(TXT_GOTCHAINGUN) #define GOTCHAINSAW GET_TXT(TXT_GOTCHAINSAW) #define GOTLAUNCHER GET_TXT(TXT_GOTLAUNCHER) #define GOTPLASMA GET_TXT(TXT_GOTPLASMA) #define GOTSHOTGUN GET_TXT(TXT_GOTSHOTGUN) #define GOTSHOTGUN2 GET_TXT(TXT_GOTSHOTGUN2) #define GOTUNMAKER GET_TXT(TXT_GOTUNMAKER) // jd64 #define NGOTUNMAKER GET_TXT(TXT_NGOTUNMAKER) // jd64 #define UNMAKERCHARGE GET_TXT(TXT_UNMAKERCHARGE) // jd64 #define GOTPOWERUP1 GET_TXT(TXT_GOTPOWERUP1) // d64TC #define NGOTPOWERUP1 GET_TXT(TXT_NGOTPOWERUP1) // d64TC #define GOTPOWERUP2 GET_TXT(TXT_GOTPOWERUP2) // d64TC #define NGOTPOWERUP2 GET_TXT(TXT_NGOTPOWERUP2) // d64TC #define GOTPOWERUP3 GET_TXT(TXT_GOTPOWERUP3) // d64TC #define NGOTPOWERUP3 GET_TXT(TXT_NGOTPOWERUP3) // d64TC #define PD_OPNPOWERUP GET_TXT(TXT_PD_OPNPOWERUP) // d64TC #define PD_BLUEO GET_TXT(TXT_PD_BLUEO) #define PD_REDO GET_TXT(TXT_PD_REDO) #define PD_YELLOWO GET_TXT(TXT_PD_YELLOWO) #define PD_BLUEK GET_TXT(TXT_PD_BLUEK) #define PD_REDK GET_TXT(TXT_PD_REDK) #define PD_YELLOWK GET_TXT(TXT_PD_YELLOWK) #define TXT_GAMESAVED GET_TXT(TXT_GGSAVED) #define HUSTR_MSGU GET_TXT(TXT_HUSTR_MSGU) #define HUSTR_CHATMACRO1 GET_TXT(TXT_HUSTR_CHATMACRO1) #define HUSTR_CHATMACRO2 GET_TXT(TXT_HUSTR_CHATMACRO2) #define HUSTR_CHATMACRO3 GET_TXT(TXT_HUSTR_CHATMACRO3) #define HUSTR_CHATMACRO4 GET_TXT(TXT_HUSTR_CHATMACRO4) #define HUSTR_CHATMACRO5 GET_TXT(TXT_HUSTR_CHATMACRO5) #define HUSTR_CHATMACRO6 GET_TXT(TXT_HUSTR_CHATMACRO6) #define HUSTR_CHATMACRO7 GET_TXT(TXT_HUSTR_CHATMACRO7) #define HUSTR_CHATMACRO8 GET_TXT(TXT_HUSTR_CHATMACRO8) #define HUSTR_CHATMACRO9 GET_TXT(TXT_HUSTR_CHATMACRO9) #define HUSTR_CHATMACRO0 GET_TXT(TXT_HUSTR_CHATMACRO0) #define HUSTR_TALKTOSELF1 GET_TXT(TXT_HUSTR_TALKTOSELF1) #define HUSTR_TALKTOSELF2 GET_TXT(TXT_HUSTR_TALKTOSELF2) #define HUSTR_TALKTOSELF3 GET_TXT(TXT_HUSTR_TALKTOSELF3) #define HUSTR_TALKTOSELF4 GET_TXT(TXT_HUSTR_TALKTOSELF4) #define HUSTR_TALKTOSELF5 GET_TXT(TXT_HUSTR_TALKTOSELF5) #define HUSTR_MESSAGESENT GET_TXT(TXT_HUSTR_MESSAGESENT) /** * The following should NOT be changed unless it seems just AWFULLY * necessary! */ #define HUSTR_PLRGREEN GET_TXT(TXT_HUSTR_PLRGREEN) #define HUSTR_PLRINDIGO GET_TXT(TXT_HUSTR_PLRINDIGO) #define HUSTR_PLRBROWN GET_TXT(TXT_HUSTR_PLRBROWN) #define HUSTR_PLRRED GET_TXT(TXT_HUSTR_PLRRED) //// \fixme What are these doing here?? #define HUSTR_KEYGREEN 'g' #define HUSTR_KEYINDIGO 'i' #define HUSTR_KEYBROWN 'b' #define HUSTR_KEYRED 'r' #define AMSTR_FOLLOWON GET_TXT(TXT_AMSTR_FOLLOWON) #define AMSTR_FOLLOWOFF GET_TXT(TXT_AMSTR_FOLLOWOFF) #define AMSTR_ROTATEON GET_TXT(TXT_AMSTR_ROTATEON) #define AMSTR_ROTATEOFF GET_TXT(TXT_AMSTR_ROTATEOFF) #define AMSTR_GRIDON GET_TXT(TXT_AMSTR_GRIDON) #define AMSTR_GRIDOFF GET_TXT(TXT_AMSTR_GRIDOFF) #define AMSTR_MARKEDSPOT GET_TXT(TXT_AMSTR_MARKEDSPOT) #define AMSTR_MARKSCLEARED GET_TXT(TXT_AMSTR_MARKSCLEARED) // Key names: #define KEY1 GET_TXT(TXT_KEY1) #define KEY2 GET_TXT(TXT_KEY2) #define KEY3 GET_TXT(TXT_KEY3) #define KEY4 GET_TXT(TXT_KEY4) #define KEY5 GET_TXT(TXT_KEY5) #define KEY6 GET_TXT(TXT_KEY6) // Weapon names: #define WEAPON1 GET_TXT(TXT_WEAPON1) #define WEAPON2 GET_TXT(TXT_WEAPON2) #define WEAPON3 GET_TXT(TXT_WEAPON3) #define WEAPON4 GET_TXT(TXT_WEAPON4) #define WEAPON5 GET_TXT(TXT_WEAPON5) #define WEAPON6 GET_TXT(TXT_WEAPON6) #define WEAPON7 GET_TXT(TXT_WEAPON7) #define WEAPON8 GET_TXT(TXT_WEAPON8) #define WEAPON9 GET_TXT(TXT_WEAPON9) #define WEAPON10 GET_TXT(TXT_WEAPON10) // jd64 #define STSTR_MUS GET_TXT(TXT_STSTR_MUS) #define STSTR_NOMUS GET_TXT(TXT_STSTR_NOMUS) #define STSTR_DQDON GET_TXT(TXT_STSTR_DQDON) #define STSTR_DQDOFF GET_TXT(TXT_STSTR_DQDOFF) #define STSTR_KFAADDED GET_TXT(TXT_STSTR_KFAADDED) #define STSTR_FAADDED GET_TXT(TXT_STSTR_FAADDED) #define STSTR_NCON GET_TXT(TXT_STSTR_NCON) #define STSTR_NCOFF GET_TXT(TXT_STSTR_NCOFF) #define STSTR_BEHOLD GET_TXT(TXT_STSTR_BEHOLD) #define STSTR_BEHOLDX GET_TXT(TXT_STSTR_BEHOLDX) #define STSTR_CHOPPERS GET_TXT(TXT_STSTR_CHOPPERS) #define STSTR_CLEV GET_TXT(TXT_STSTR_CLEV) #define C1TEXT GET_TXT(TXT_C1TEXT) #define C2TEXT GET_TXT(TXT_C2TEXT) #define C3TEXT GET_TXT(TXT_C3TEXT) #define C4TEXT GET_TXT(TXT_C4TEXT) #define C5TEXT GET_TXT(TXT_C5TEXT) #define C6TEXT GET_TXT(TXT_C6TEXT) #define C7TEXT GET_TXT(TXT_C7TEXT) // jd64 #define C8TEXT GET_TXT(TXT_C8TEXT) // jd64 #define C9TEXT GET_TXT(TXT_C9TEXT) // jd64 #define CC_ZOMBIE GET_TXT(TXT_CC_ZOMBIE) #define CC_SHOTGUN GET_TXT(TXT_CC_SHOTGUN) #define CC_IMP GET_TXT(TXT_CC_IMP) #define CC_DEMON GET_TXT(TXT_CC_DEMON) #define CC_LOST GET_TXT(TXT_CC_LOST) #define CC_CACO GET_TXT(TXT_CC_CACO) #define CC_HELL GET_TXT(TXT_CC_HELL) #define CC_BARON GET_TXT(TXT_CC_BARON) #define CC_ARACH GET_TXT(TXT_CC_ARACH) #define CC_PAIN GET_TXT(TXT_CC_PAIN) #define CC_MANCU GET_TXT(TXT_CC_MANCU) #define CC_CYBER GET_TXT(TXT_CC_CYBER) #define CC_NTROOP GET_TXT(TXT_CC_NTROOP) // jd64 #define CC_BITCH GET_TXT(TXT_CC_BITCH) // jd64 #define CC_HERO GET_TXT(TXT_CC_HERO) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/g_ctrl.h0000644000175000017500000000225211357170242023077 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.h: Player control setup. */ #ifndef __G_CTRL_H__ #define __G_CTRL_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif void G_RegisterPlayerControls(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_pspr.h0000644000175000017500000000354211357170242023133 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.h: Sprite animation. */ #ifndef __P_PSPR_H__ #define __P_PSPR_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif /** * Overlay psprites are scaled shapes drawn directly on the view screen, * coordinates are given for a 320*200 view screen. */ typedef enum { ps_weapon, ps_flash, NUMPSPRITES } psprnum_t; typedef struct { state_t* state; // A NULL state means not active. int tics; float pos[2]; // [x, y] } pspdef_t; void P_SetupPsprites(struct player_s* curplayer); void P_MovePsprites(struct player_s* curplayer); void P_DropWeapon(struct player_s* player); void P_SetPsprite(struct player_s* player, int position, statenum_t stnum); void R_GetWeaponBob(int player, float* x, float* y); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/dstrings.h0000644000175000017500000000247411357170242023470 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2006 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dstrings.h: */ #ifndef __DSTRINGS_H__ #define __DSTRINGS_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // All important printed strings. #include "d_englsh.h" // QuitDOOM messages: #define NUM_QUITMESSAGES 22 extern char *endmsg[NUM_QUITMESSAGES + 1]; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/version.h0000644000175000017500000000330711357170242023314 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __JDOOM64_VERSION_H__ #define __JDOOM64_VERSION_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #ifndef JDOOM64_VER_ID # ifdef _DEBUG # define JDOOM64_VER_ID "+D Doomsday" # else # define JDOOM64_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define GAMENAMETEXT "jdoom64" // Presented to the user in dialogs, messages etc. #define GAME_NICENAME "jDoom64" #define GAME_DETAILS "jDoom64 is based on jDoom-1.15." #define GAME_VERSION_TEXT "0.8.1" #define GAME_VERSION_TEXTLONG "Version" GAME_VERSION_TEXT " " __DATE__ " (" JDOOM64_VER_ID ")" #define GAME_VERSION_NUMBER 0,8,1,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_mobj.h0000644000175000017500000003316411357170242023101 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.h: Map Objects, Mobj, definition and handling jDoom64 - specific. */ #ifndef __P_MOBJ__ #define __P_MOBJ__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // Basics. #include "tables.h" #include "p_terraintype.h" #include "d_think.h" #include "info.h" #define FRICTION_NORMAL (0.90625f) #define FRICTION_FLY (0.91796875f) #define FRICTION_HIGH (0.5f) // Player radius for movement checking. #define PLAYERRADIUS (25) // MAXRADIUS is for precalculated sector block boxes the spider demon is // larger, but we do not have any moving sectors nearby. #define MAXRADIUS (32) #define MAXMOVE (30) #define USERANGE (64) #define MELEERANGE (64) #define PLRMELEERANGE (80) // jd64 wide player radius. #define MISSILERANGE (32 * 64) #define FLOATSPEED (4) #define MAXHEALTH (maxHealth) //100 #define VIEWHEIGHT (54) // GMJ 02/02/02 #define sentient(mobj) ((mobj)->health > 0 && P_GetState((mobj)->type, SN_SEE)) /** * NOTES: mobj_t * * mobj_ts are used to tell the refresh where to draw an image, * tell the world simulation when objects are contacted, * and tell the sound driver how to position a sound. * * The refresh uses the next and prev links to follow * lists of things in sectors as they are being drawn. * The sprite, frame, and angle elements determine which patch_t * is used to draw the sprite if it is visible. * The sprite and frame values are allmost allways set * from state_t structures. * The statescr.exe utility generates the states.h and states.c * files that contain the sprite/frame numbers from the * statescr.txt source file. * The xyz origin point represents a point at the bottom middle * of the sprite (between the feet of a biped). * This is the default origin position for patch_ts grabbed * with lumpy.exe. * A walking creature will have its z equal to the floor * it is standing on. * * The sound code uses the x,y, and subsector fields * to do stereo positioning of any sound effited by the mobj_t. * * The play simulation uses the blocklinks, x,y,z, radius, height * to determine when mobj_ts are touching each other, * touching lines in the map, or hit by trace lines (gunshots, * lines of sight, etc). * The mobj_t->flags element has various bit flags * used by the simulation. * * Every mobj_t is linked into a single sector * based on its origin coordinates. * The subsector_t is found with R_PointInSubsector(x,y), * and the sector_t can be found with subsector->sector. * The sector links are only used by the rendering code, * the play simulation does not care about them at all. * * Any mobj_t that needs to be acted upon by something else * in the play world (block movement, be shot, etc) will also * need to be linked into the blockmap. * If the thing has the MF_NOBLOCK flag set, it will not use * the block links. It can still interact with other things, * but only as the instigator (missiles will run into other * things, but nothing can run into a missile). * Each block in the grid is 128*128 units, and knows about * every linedef_t that it contains a piece of, and every * interactable mobj_t that has its origin contained. * * A valid mobj_t is a mobj_t that has the proper subsector_t * filled in for its xy coordinates and is linked into the * sector from which the subsector was made, or has the * MF_NOSECTOR flag set (the subsector_t needs to be valid * even if MF_NOSECTOR is set). * Links should only be modified by the P_[Un]SetThingPosition() * functions. * Do not change the MF_NO? flags while a thing is valid. * * Any questions? */ /** * Mobj flags * * \attention IMPORTANT - Keep this current!!! * LEGEND: * p = Flag is persistent (never changes in-game). * i = Internal use (not to be used in defintions). * * \todo Persistent flags (p) don't need to be included in save games or sent to * clients in netgames. We should collect those in to a const flags setting which * is set only once when the mobj is spawned. * * \todo All flags for internal use only (i) should be put in another var and the * flags removed from those defined in GAME/objects.DED */ // --- mobj.flags --- #define MF_SPECIAL 0x00000001 // Call P_SpecialThing when touched. #define MF_SOLID 0x00000002 // Blocks. #define MF_SHOOTABLE 0x00000004 // Can be hit. #define MF_NOSECTOR 0x00000008 // (p) Don't use the sector links (invisible but touchable). #define MF_NOBLOCKMAP 0x00000010 // (p) Don't use the blocklinks (inert but displayable) #define MF_AMBUSH 0x00000020 // Not to be activated by sound, deaf monster. #define MF_JUSTHIT 0x00000040 // Will try to attack right back. #define MF_JUSTATTACKED 0x00000080 // Will take at least one step before attacking. #define MF_SPAWNCEILING 0x00000100 // (p) Hang from ceiling instead of stand on floor. #define MF_NOGRAVITY 0x00000200 // Don't apply gravity (every tic). // Movement flags. #define MF_DROPOFF 0x00000400 // This allows jumps from high places. #define MF_PICKUP 0x00000800 // For players, will pick up items. #define MF_NOCLIP 0x00001000 // (i) Player cheat. //#define MF_??? 0x00002000 // unused #define MF_FLOAT 0x00004000 // Allow moves to any height, no gravity. #define MF_TELEPORT 0x00008000 // (p) Don't cross lines or look at heights on teleport. #define MF_MISSILE 0x00010000 // Don't hit same species, explode on block. #define MF_DROPPED 0x00020000 // (i) Dropped by a demon, not level spawned. #define MF_SHADOW 0x00040000 // Use fuzzy draw (shadow demons or spectres). #define MF_NOBLOOD 0x00080000 // Don't bleed when shot (use puff). #define MF_CORPSE 0x00100000 // (i) Don't stop moving halfway off a step. #define MF_INFLOAT 0x00200000 // Floating to a height for a move, // don't auto float to target's height. #define MF_COUNTKILL 0x00400000 // count towards intermission kill total #define MF_COUNTITEM 0x00800000 // count towards intermission item total #define MF_SKULLFLY 0x01000000 // (i) skull in flight. #define MF_NOTDMATCH 0x02000000 // (p) not spawned in deathmatch mode (e.g. key cards). #define MF_TRANSLATION 0x0c000000 // (i) if 0x4 0x8 or 0xc, use a translation #define MF_TRANSSHIFT 26 // (N/A) table for player colormaps #define MF_LOCAL 0x10000000 // (p) Won't be sent to clients. #define MF_BRIGHTSHADOW 0x20000000 #define MF_BRIGHTEXPLODE 0x40000000 // Make this brightshadow when exploding. #define MF_VIEWALIGN 0x80000000 /* * The following flags are obsolete in a particular mobj version. * They will automatically be cleared when loading an old save game. */ #define MF_V6OBSOLETE (0x00002000) // (MF_SLIDE) // --- mobj.flags2 --- (added in MOBJ_SAVEVERSION 6) #define MF2_LOGRAV 0x00000001 // alternate gravity setting //#define MF2_WINDTHRUST 0x00000002 // (p) gets pushed around by the wind specials // Not in jDoom since there are no built-in wind specials. #define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor #define MF2_THRUGHOST 0x00000008 // (p) missile will pass through ghosts #define MF2_FLY 0x00000010 // (i) fly mode is active #define MF2_FLOORCLIP 0x00000020 // if feet are allowed to be clipped #define MF2_SPAWNFLOAT 0x00000040 // (p) spawn random float z #define MF2_NOTELEPORT 0x00000080 // does not teleport #define MF2_RIP 0x00000100 // (p) missile rips through solid targets #define MF2_PUSHABLE 0x00000200 // can be pushed by other moving mobjs #define MF2_SLIDE 0x00000400 // slides against walls #define MF2_ALWAYSLIT 0x00000800 #define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, // this flag will allow the mobj to // pass over/under other mobjs. #define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs #define MF2_INFZBOMBDAMAGE 0x00004000 // (p) Don't check z height with radius attacks #define MF2_BOSS 0x00008000 // (p) mobj is a major boss //#define MF2_FIREDAMAGE 0x00010000 // does fire damage - Not in jDoom #define MF2_NODMGTHRUST 0x00020000 // does not thrust target when // damaging #define MF2_TELESTOMP 0x00040000 // mobj can stomp another #define MF2_FLOATBOB 0x00080000 // (p) use float bobbing z movement #define MF2_DONTDRAW 0X00100000 // don't generate a vissprite // --- mobj.flags3 --- #define MF3_NOINFIGHT 0x00000001 // Mobj will never be targeted for in-fighting // --- mobj.intflags --- // Internal mobj flags cannot be set using an external definition. #define MIF_FALLING 0x00000001 // $dropoff_fix: Object is falling from a ledge. #define MIF_FADE 0x00000002 // jd64 /* * end mobj flags */ // For torque simulation: #define OVERDRIVE 6 #define MAXGEAR (OVERDRIVE+16) typedef enum dirtype_s { DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_NODIR, NUMDIRS } dirtype_t; // Map Object definition. typedef struct mobj_s { // Defined in dd_share.h; required mobj elements. DD_BASE_MOBJ_ELEMENTS() // Doom64-specific data: mobjinfo_t *info; // &mobjinfo[mobj->type] int damage; // For missiles int flags; int flags2; int flags3; int health; // Movement direction, movement generation (zig-zagging). int moveDir; // 0-7 int moveCount; // when 0, select a new dir // Thing being chased/attacked (or NULL), // also the originator for missiles. struct mobj_s *target; // If >0, the target will be chased // no matter what (even if shot) int threshold; int intFlags; // internal flags float dropOffZ; // $dropoff_fix short gear; // used in torque simulation boolean wallRun; // true = last move was the result of a wallrun // Additional info record for player avatars only. // Only valid if type == MT_PLAYER struct player_s *player; // Player number last looked for. int lastLook; // For nightmare/multiplayer respawn. struct { float pos[3]; angle_t angle; int flags; // MSF_* flags } spawnSpot; // Thing being chased/attacked for tracers. struct mobj_s *tracer; int turnTime; // $visangle-facetarget int corpseTics; // $vanish: how long has this been dead? int spawnFadeTics; } mobj_t; typedef struct polyobj_s { // Defined in dd_share.h; required polyobj elements. DD_BASE_POLYOBJ_ELEMENTS() // Doom64-specific data: } polyobj_t; void P_ExplodeMissile(mobj_t* mo); float P_MobjGetFriction(mobj_t* mo); mobj_t* P_SPMAngle(mobjtype_t type, mobj_t* source, angle_t angle); mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags); mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags); void P_SpawnPuff(float x, float y, float z, angle_t angle); mobj_t* P_SpawnCustomPuff(mobjtype_t type, float x, float y, float z, angle_t angle); void P_SpawnBlood(float x, float y, float z, int damage, angle_t angle); mobj_t* P_SpawnMissile(mobjtype_t type, mobj_t* source, mobj_t* dest); mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle); mobj_t* P_SpawnMotherMissile(mobjtype_t type, float x, float y, float z, mobj_t* source, mobj_t* dest); boolean P_MobjChangeState(mobj_t* mo, statenum_t state); void P_MobjThinker(mobj_t* mo); const terraintype_t* P_MobjGetFloorTerrainType(mobj_t* mo); void P_RipperBlood(mobj_t* mo); void P_SetDoomsdayFlags(mobj_t* mo); void P_HitFloor(mobj_t* mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/jdoom64.h0000644000175000017500000000446711357170242023121 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jdoom64.h: All jDoom64 Headers * * A convenience header for including all jDoom64 headers. */ #ifndef __JDOOM64_CONVENIENCE_H__ #define __JDOOM64_CONVENIENCE_H__ #include "../../jdoom64/include/acfnlink.h" #include "../../jdoom64/include/d_api.h" #include "../../jdoom64/include/d_config.h" #include "../../jdoom64/include/d_console.h" #include "../../jdoom64/include/d_main.h" #include "../../jdoom64/include/d_refresh.h" #include "../../jdoom64/include/doomdef.h" #include "../../jdoom64/include/dstrings.h" #include "../../jdoom64/include/g_game.h" #include "../../jdoom64/include/g_ctrl.h" #include "../../jdoom64/include/doomtype.h" #include "../../jdoom64/include/info.h" #include "../../jdoom64/include/m_cheat.h" #include "../../jdoom64/include/m_random.h" #include "../../jdoom64/include/m_menu.h" #include "../../jdoom64/include/mn_def.h" #include "../../jdoom64/include/p_enemy.h" #include "../../jdoom64/include/p_inter.h" #include "../../jdoom64/include/p_lights.h" #include "../../jdoom64/include/p_maputl.h" #include "../../jdoom64/include/p_pspr.h" #include "../../jdoom64/include/p_setup.h" #include "../../jdoom64/include/p_sound.h" #include "../../jdoom64/include/p_spec.h" #include "../../jdoom64/include/p_telept.h" #include "../../jdoom64/include/r_defs.h" #include "../../jdoom64/include/st_stuff.h" #include "../../jdoom64/include/tables.h" #include "../../jdoom64/include/wi_stuff.h" #endif // __JDOOM64_CONVENIENCE_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_spec.h0000644000175000017500000000520711357170242023101 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.h: World texture animation, height or lighting changes * according to adjacent sectors, respective utility functions, etc. * * Line Tag handling. Line and Sector triggers. * * Events are operations triggered by using, crossing, or shooting special * lines, or by timed thinkers. */ #ifndef __P_SPEC__ #define __P_SPEC__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "d_player.h" // Base plane ids. enum { PLN_FLOOR, PLN_CEILING }; // Special activation types: #define SPAC_CROSS 0 // Player crosses linedef. #define SPAC_USE 1 // Player uses linedef. #define SPAC_IMPACT 3 // Projectile hits linedef. // at game start void P_InitPicAnims(void); // at map load void P_SpawnSpecials(void); // every tic void P_UpdateSpecials(void); void P_ThunderSector(void); // jd64 boolean P_ActivateLine(linedef_t *ld, mobj_t *mo, int side, int activationType); void P_PlayerInSpecialSector(player_t *player); typedef enum { ok, crushed, pastdest } result_e; typedef enum { build8, // slowly build by 8 turbo16 // quickly build by 16 } stair_e; int EV_BuildStairs(linedef_t *line, stair_e type); result_e T_MovePlane(sector_t* sector, float speed, float dest, int crush, int floorOrCeiling, int direction); int EV_DoDonut(linedef_t *line); boolean P_UseSpecialLine2(mobj_t* mo, linedef_t* line, int side); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_console.h0000644000175000017500000000240611357170242023573 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_console.h: Console settings and commands jDoom64 - specific. */ #ifndef __D_CONSOLE_H__ #define __D_CONSOLE_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif void G_ConsoleRegistration(void); void D_ConsoleBg(int *width, int *height); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_setup.h0000644000175000017500000000367611357170242023317 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.h: Map setup routines */ #ifndef __P_SETUP_H__ #define __P_SETUP_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif // Map objects and their properties: enum { MO_NONE = 0, MO_THING, MO_XLINEDEF, MO_XSECTOR, MO_LIGHT, MO_X, MO_Y, MO_Z, MO_ID, MO_ANGLE, MO_TYPE, MO_DOOMEDNUM, MO_USETYPE, MO_FLAGS, MO_TAG, MO_DRAWFLAGS, MO_TEXFLAGS, MO_COLORR, MO_COLORG, MO_COLORB, MO_FLOORCOLOR, MO_CEILINGCOLOR, MO_UNKNOWNCOLOR, MO_WALLTOPCOLOR, MO_WALLBOTTOMCOLOR, MO_XX0, MO_XX1, MO_XX2 }; void P_Init(void); void P_RegisterMapObjs(void); int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void* data); int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void* data); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/acfnlink.h0000644000175000017500000000752111357170242023416 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * acfnlink.h: */ #ifndef __ACTION_LINK_H__ #define __ACTION_LINK_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "dd_share.h" typedef struct { char *name; // Name of the routine. void (C_DECL *func)(); // Pointer to the function. } actionlink_t; extern actionlink_t actionlinks[]; void C_DECL A_BabyMetal(); void C_DECL A_BFGsound(); void C_DECL A_BFGSpray(); void C_DECL A_BossDeath(); void C_DECL A_BruisAttack(); void C_DECL A_BspiAttack(); void C_DECL A_Chase(); void C_DECL A_RectChase(); void C_DECL A_CheckReload(); void C_DECL A_CyberAttack(); void C_DECL A_Explode(); void C_DECL A_BarrelExplode(); void C_DECL A_FaceTarget(); void C_DECL A_BspiFaceTarget(); void C_DECL A_Fall(); void C_DECL A_FatAttack1(); void C_DECL A_FatAttack2(); void C_DECL A_FatAttack3(); void C_DECL A_FatRaise(); void C_DECL A_FireBFG(); void C_DECL A_FireCGun(); void C_DECL A_FireMissile(); void C_DECL A_FirePistol(); void C_DECL A_FirePlasma(); void C_DECL A_FireShotgun(); void C_DECL A_FireShotgun2(); void C_DECL A_GunFlash(); void C_DECL A_HeadAttack(); void C_DECL A_Hoof(); void C_DECL A_Light0(); void C_DECL A_Light1(); void C_DECL A_Light2(); void C_DECL A_LoadShotgun2(); void C_DECL A_Look(); void C_DECL A_Lower(); void C_DECL A_Metal(); void C_DECL A_OpenShotgun2(); void C_DECL A_Pain(); void C_DECL A_PainAttack(); void C_DECL A_PainDie(); void C_DECL A_PosAttack(); void C_DECL A_Punch(); void C_DECL A_Raise(); void C_DECL A_PlasmaShock(); void C_DECL A_ReFire(); void C_DECL A_SargAttack(); void C_DECL A_Saw(); void C_DECL A_Scream(); void C_DECL A_SkelFist(); void C_DECL A_SkelMissile(); void C_DECL A_SkelWhoosh(); void C_DECL A_SkullAttack(); void C_DECL A_SpidRefire(); void C_DECL A_SPosAttack(); void C_DECL A_Tracer(); void C_DECL A_TroopAttack(); void C_DECL A_WeaponReady(); void C_DECL A_XScream(); //jd64 void C_DECL A_Lasersmoke(); void C_DECL A_FireSingleLaser(); void C_DECL A_FireDoubleLaser(); void C_DECL A_FireDoubleLaser1(); void C_DECL A_FireDoubleLaser2(); void C_DECL A_PossSpecial(); void C_DECL A_SposSpecial(); void C_DECL A_TrooSpecial(); void C_DECL A_SargSpecial(); void C_DECL A_HeadSpecial(); void C_DECL A_SkulSpecial(); void C_DECL A_Bos2Special(); void C_DECL A_BossSpecial(); void C_DECL A_PainSpecial(); void C_DECL A_FattSpecial(); void C_DECL A_BabySpecial(); void C_DECL A_CybrSpecial(); void C_DECL A_RectSpecial(); void C_DECL A_Rocketpuff(); void C_DECL A_CyberDeath(); void C_DECL A_TroopClaw(); void C_DECL A_MotherFloorFire(); void C_DECL A_MotherMissle(); void C_DECL A_SetFloorFire(); void C_DECL A_MotherBallExplode(); void C_DECL A_RectTracerPuff(); void C_DECL A_TargetCamera(); void C_DECL A_ShadowsAction1(); void C_DECL A_ShadowsAction2(); void C_DECL A_EMarineAttack2(); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/doomdef.h0000644000175000017500000001517211357170242023247 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomdef.h: Internally used data structures for virtually everything, * key definitions, lots of other stuff. */ #ifndef __DOOMDEF_H__ #define __DOOMDEF_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #ifdef WIN32 #pragma warning(disable:4244) #endif #include "doomsday.h" #include "dd_api.h" #include "version.h" #include "info.h" #define Set DD_SetInteger #define Get DD_GetInteger #define CONFIGFILE GAMENAMETEXT".cfg" #define DEFSFILE GAMENAMETEXT"\\"GAMENAMETEXT".ded" #define DATAPATH "}data\\"GAMENAMETEXT"\\" #define STARTUPWAD "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".wad" #define STARTUPPK3 "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".pk3" // // Global parameters/defines. // #define MOBJINFO (*gi.mobjInfo) #define STATES (*gi.states) #define VALIDCOUNT (*gi.validCount) // Verbose messages. #define VERBOSE(code) { if(verbose >= 1) { code; } } #define VERBOSE2(code) { if(verbose >= 2) { code; } } /** * Game mode handling - identify IWAD version to handle IWAD dependant * animations, game logic etc. */ typedef enum { commercial, // DOOM 2 retail, E1 M34 indetermined, // Well, no IWAD found. NUM_GAME_MODES } gamemode_t; // Game mode bits for the above. #define GM_COMMERCIAL 0x1 #define GM_INDETERMINED 0x16 // Well, no IWAD found. #define GM_ANY (GM_COMMERCIAL) #define SCREENWIDTH 320 #define SCREENHEIGHT 200 #define SCREEN_MUL 1 // The maximum number of players, multiplayer/networking. #define MAXPLAYERS 16 // State updates, number of tics / second. #define TICRATE 35 /** * The current (high-level) state of the game: whether we are playing, * gazing at the intermission screen, the game final animation, or a demo. */ typedef enum gamestate_e { GS_STARTUP, GS_MAP, GS_INTERMISSION, GS_FINALE, GS_WAITING, GS_INFINE, NUM_GAME_STATES } gamestate_t; // Game state change actions. typedef enum { GA_NONE, GA_LOADMAP, GA_NEWGAME, GA_LOADGAME, GA_SAVEGAME, GA_MAPCOMPLETED, GA_VICTORY, GA_LEAVEMAP, GA_SCREENSHOT, GA_QUIT } gameaction_t; // // Player Classes // typedef enum { PCLASS_PLAYER, NUM_PLAYER_CLASSES } playerclass_t; #define PCLASS_INFO(class) (&classInfo[class]) typedef struct classinfo_s{ char* niceName; boolean userSelectable; mobjtype_t mobjType; int normalState; int runState; int attackState; int attackEndState; int maxArmor; fixed_t maxMove; fixed_t forwardMove[2]; // [walk, run]. fixed_t sideMove[2]; // [walk, run]. int moveMul; // Multiplier for above. int turnSpeed[3]; // [normal, speed, initial] int jumpTics; // Wait in between jumps. int failUseSound; // Sound played when a use fails. } classinfo_t; extern classinfo_t classInfo[NUM_PLAYER_CLASSES]; typedef enum { SM_NOITEMS = -1, // skill mode 0 SM_BABY = 0, SM_EASY, SM_MEDIUM, SM_HARD, NUM_SKILL_MODES } skillmode_t; // // Key cards. // typedef enum { KT_BLUECARD, KT_YELLOWCARD, KT_REDCARD, KT_BLUESKULL, KT_YELLOWSKULL, KT_REDSKULL, NUM_KEY_TYPES } keytype_t; /** * Inventory Item Types: */ typedef enum { IIT_NONE = 0, IIT_FIRST = 1, IIT_DEMONKEY1 = IIT_FIRST, IIT_DEMONKEY2, IIT_DEMONKEY3, NUM_INVENTORYITEM_TYPES } inventoryitemtype_t; #define MAXINVITEMCOUNT 16 // The defined weapons, // including a marker indicating // user has not changed weapon. typedef enum { WT_FIRST, // fist WT_SECOND, // pistol WT_THIRD, // shotgun WT_FOURTH, // chaingun WT_FIFTH, // missile launcher WT_SIXTH, // plasma rifle WT_SEVENTH, // bfg WT_EIGHTH, // chainsaw WT_NINETH, // supershotgun WT_TENTH, // unmaker NUM_WEAPON_TYPES, // No pending weapon change. WT_NOCHANGE } weapontype_t; #define NUMWEAPLEVELS 1 // DOOM weapons have 1 power level. // Ammunition types defined. typedef enum { AT_CLIP, // Pistol / chaingun ammo. AT_SHELL, // Shotgun / double barreled shotgun. AT_CELL, // Plasma rifle, BFG. AT_MISSILE, // Missile launcher. NUM_AMMO_TYPES, AT_NOAMMO // Unlimited for chainsaw / fist. } ammotype_t; // Power ups. typedef enum { PT_INVULNERABILITY, PT_STRENGTH, PT_INVISIBILITY, PT_IRONFEET, PT_ALLMAP, PT_INFRARED, PT_FLIGHT, NUM_POWER_TYPES } powertype_t; /** * Power up durations, how many seconds till expiration, assuming TICRATE * is 35 ticks/second. */ typedef enum { INVULNTICS = (30 * TICRATE), INVISTICS = (60 * TICRATE), INFRATICS = (120 * TICRATE), IRONTICS = (60 * TICRATE) } powerduration_t; enum { VX, VY, VZ }; // Vertex indices. enum { CR, CG, CB, CA }; // Color indices. #define IS_SERVER (Get(DD_SERVER)) #define IS_CLIENT (Get(DD_CLIENT)) #define IS_NETGAME (Get(DD_NETGAME)) #define IS_DEDICATED (Get(DD_DEDICATED)) #define CVAR(typ, x) (*((typ)*) Con_GetVariable(x)->ptr) #define CONSOLEPLAYER (Get(DD_CONSOLEPLAYER)) #define DISPLAYPLAYER (Get(DD_DISPLAYPLAYER)) #define GAMETIC (*((timespan_t*) DD_GetVariable(DD_GAMETIC))) #define SFXVOLUME (Get(DD_SFX_VOLUME) / 17) #define MUSICVOLUME (Get(DD_MUSIC_VOLUME) / 17) #define DEFAULT_PLAYER_VIEWHEIGHT (54) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_maputl.h0000644000175000017500000000271011357170242023445 0ustar keeskees/**\file *\section License * License: GPL + jHeretic/jHexen Exception * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputl.h: Movement/collision utility functions jDoom64 - specific. */ #ifndef __P_MAPUTL_H__ #define __P_MAPUTL_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "p_mobj.h" #define OPENRANGE (*(float*) DD_GetVariable(DD_OPENRANGE)) #define OPENTOP (*(float*) DD_GetVariable(DD_OPENTOP)) #define OPENBOTTOM (*(float*) DD_GetVariable(DD_OPENBOTTOM)) #define LOWFLOOR (*(float*) DD_GetVariable(DD_LOWFLOOR)) void P_ApplyTorque(mobj_t *mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/p_inter.h0000644000175000017500000000367511357170242023277 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.h: Handling mobj vs mobj interactions (i.e., collisions). */ #ifndef __P_INTER_H__ #define __P_INTER_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif extern int maxAmmo[]; extern int clipAmmo[]; boolean P_GivePower(player_t* plr, int); boolean P_TakePower(player_t* plr, int power); void P_GiveKey(player_t* plr, keytype_t keyType); boolean P_GiveBody(player_t* plr, int num); void P_GiveBackpack(player_t* plr); boolean P_GiveWeapon(player_t* plr, weapontype_t weapon, boolean dropped); boolean P_GiveArmor(player_t* plr, int type, int points); void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher); int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage, boolean stomping); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_think.h0000644000175000017500000000336011357170242023246 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_think.h: MapObj data. * * Map Objects or mobjs are actors, entities, thinker, take-your-pick... * anything that moves, acts, or suffers state changes of more or less * violent nature. */ #ifndef __D_THINK__ #define __D_THINK__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif /** * Experimental stuff. * To compile this as "ANSI C with classes" we will need to handle the * various action functions cleanly. */ typedef void (*actionf_v) (); typedef void (*actionf_p1) (void *); typedef void (*actionf_p2) (void *, void *); #define NOPFUNC ((actionf_v) (-1)) typedef union { actionf_p1 acp1; actionf_v acv; actionf_p2 acp2; } actionf_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_refresh.h0000644000175000017500000000267411357170242023576 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_refresh.h: */ #ifndef __D_REFRESH_H__ #define __D_REFRESH_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "p_mobj.h" extern float quitDarkenOpacity; void D_Display(int layer); void D_Display2(void); void R_SetViewSize(int blocks); void R_DrawSpecialFilter(int pnum); void R_DrawMapTitle(void); void P_SetDoomsdayFlags(mobj_t* mo); void R_SetAllDoomsdayFlags(void); boolean R_GetFilterColor(float rgba[4], int filter); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_config.h0000644000175000017500000001625311357170242023403 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2003-2005 Samuel Villarreal * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_config.h: jDoom64 configuration. * Global settings. Most of these are console variables. */ #ifndef __JDOOM64_SETTINGS_H__ #define __JDOOM64_SETTINGS_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "doomdef.h" enum { HUD_HEALTH, HUD_ARMOR, HUD_AMMO, HUD_KEYS, HUD_FRAGS, HUD_INVENTORY, // jd64 NUMHUDDISPLAYS }; // Hud Unhide Events (the hud will unhide on these events if enabled). typedef enum { HUE_FORCE = -1, HUE_ON_DAMAGE, HUE_ON_PICKUP_HEALTH, HUE_ON_PICKUP_ARMOR, HUE_ON_PICKUP_POWER, HUE_ON_PICKUP_WEAPON, HUE_ON_PICKUP_AMMO, HUE_ON_PICKUP_KEY, NUMHUDUNHIDEEVENTS } hueevent_t; // WARNING: Do not use the boolean type. Its size can be either 1 or 4 bytes // depending on build settings. typedef struct jdoom64_config_s { float playerMoveSpeed; int dclickUse; int useMLook; // Mouse look (mouse Y => viewpitch). int useJLook; // Joy look (joy Y => viewpitch). int alwaysRun; // Always run. int noAutoAim; // No auto-aiming? int jLookDeltaMode; int lookSpring; float lookSpeed; float turnSpeed; byte povLookAround; int jumpEnabled; float jumpPower; int airborneMovement; byte setSizeNeeded; int setBlocks; int screenBlocks; byte deathLookUp; // Look up when killed. byte slidingCorpses; byte fastMonsters; byte echoMsg; float menuScale; int menuEffects; int hudFog; float menuGlitter; float menuShadow; int menuQuitSound; byte menuSlam; byte menuHotkeys; byte askQuickSaveLoad; float flashColor[3]; int flashSpeed; byte turningSkull; byte hudShown[NUMHUDDISPLAYS]; // HUD data visibility. float hudScale; // How to scale HUD data? float hudColor[4]; float hudIconAlpha; float hudTimer; // Number of seconds until the hud auto-hides. byte hudUnHide[NUMHUDUNHIDEEVENTS]; // When the hud unhides. byte usePatchReplacement; byte moveCheckZ; // If true, mobjs can move over/under each other. byte weaponAutoSwitch; byte noWeaponAutoSwitchIfFiring; byte ammoAutoSwitch; byte berserkAutoSwitch; int weaponOrder[NUM_WEAPON_TYPES]; byte weaponNextMode; // if true use the weaponOrder for next/previous. byte weaponRecoil; // jd64 byte secretMsg; float filterStrength; int plrViewHeight; byte mapTitle, hideIWADAuthor; float menuColor[3]; float menuColor2[3]; byte noCoopDamage; byte noTeamDamage; byte noCoopWeapons; byte noCoopAnything; byte noNetBFG; byte coopRespawnItems; /** * Compatibility options. * \todo Put these into an array so we can use a bit array to change * multiple options based on a compatibility mode (ala PrBoom). */ byte maxSkulls; byte allowSkullsInWalls; byte anyBossDeath; byte monstersStuckInDoors; byte avoidDropoffs; byte moveBlock; // Dont handle large negative movement in P_TryMove. byte wallRunNorthOnly; // If handle large make exception for wallrunning byte zombiesCanExit; // Zombie players can exit maps. byte fallOff; // Objects fall under their own weight. byte counterCheat; float counterCheatScale; // Automap stuff. /* int automapPos; float automapWidth; float automapHeight;*/ float automapMobj[3]; float automapL0[3]; float automapL1[3]; float automapL2[3]; float automapL3[3]; float automapBack[3]; float automapOpacity; float automapLineAlpha; byte automapRotate; int automapHudDisplay; int automapCustomColors; byte automapShowDoors; float automapDoorGlow; byte automapBabyKeys; float automapZoomSpeed; float automapPanSpeed; byte automapPanResetOnOpen; float automapOpenSeconds; int msgCount; float msgScale; float msgUptime; int msgBlink; int msgAlign; byte msgShow; float msgColor[3]; char *chatMacros[10]; byte chatBeep; int corpseTime; byte killMessages; float bobWeapon, bobView; byte bobWeaponLower; int cameraNoClip; // Crosshair. int xhair; float xhairSize; byte xhairVitality; float xhairColor[4]; // Network. byte netDeathmatch; byte netBFGFreeLook; // Allow free-aim with BFG. byte netMobDamageModifier; // Multiplier for non-player mobj damage. byte netMobHealthModifier; // Health modifier for non-player mobjs. int netGravity; // Multiplayer custom gravity. byte netNoMaxZRadiusAttack; // Radius attacks are infinitely tall. byte netNoMaxZMonsterMeleeAttack; // Melee attacks are infinitely tall. byte netNoMonsters; byte netRespawn; byte netJumping; byte netMap; byte netSkill; byte netSlot; byte netColor; int playerColor[MAXPLAYERS]; } game_config_t; extern game_config_t cfg; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/tables.h0000644000175000017500000000401511357170242023076 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * Lookup tables. */ #ifndef __TABLES__ #define __TABLES__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "doomsday.h" #define PI 3.141592657 //#include "m_fixed.h" #define FINEANGLES 8192 #define FINEMASK (FINEANGLES-1) // 0x100000000 to 0x2000 #define ANGLETOFINESHIFT 19 // Effective size is 10240. extern fixed_t finesine[5 * FINEANGLES / 4]; // Re-use data, is just PI/2 pahse shift. extern fixed_t *finecosine; // Effective size is 4096. extern fixed_t finetangent[FINEANGLES / 2]; // Binary Angle Measument, BAM. #define ANG45 0x20000000 #define ANG90 0x40000000 #define ANG180 0x80000000 #define ANG270 0xc0000000 #define SLOPERANGE 2048 #define SLOPEBITS 11 #define DBITS (FRACBITS-SLOPEBITS) // Effective size is 2049; // The +1 size is to handle the case when x==y // without additional checking. extern angle_t tantoangle[SLOPERANGE + 1]; // Utility function, // called by R_PointToAngle. int SlopeDiv(unsigned num, unsigned den); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/g_game.h0000644000175000017500000000667111357170242023055 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_game.h: Top-level (common) game routines jDoom64 - specific. */ #ifndef __G_GAME_H__ #define __G_GAME_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "doomdef.h" #include "d_player.h" #include "wi_stuff.h" extern player_t players[MAXPLAYERS]; extern uint nextMap; extern skillmode_t gameSkill; extern uint gameEpisode; extern uint gameMap; extern uint nextMap; // If non zero this will be the next map. extern boolean secretExit; extern int totalKills, totalItems, totalSecret; extern boolean respawnMonsters; extern wbstartstruct_t wmInfo; extern boolean userGame; extern int mapStartTic; extern int bodyQueueSlot; extern boolean deathmatch; extern boolean paused; extern boolean precache; extern int gsvMapMusic; void G_Register(void); void G_CommonPreInit(void); void G_CommonPostInit(void); void R_InitRefresh(void); void G_DeathMatchSpawnPlayer(int playernum); void G_PrintMapList(void); boolean G_ValidateMap(uint* episode, uint* map); uint G_GetMapNumber(uint episode, uint map); void G_InitNew(skillmode_t skill, uint episode, uint map); // Can be called by the startup code or Hu_MenuResponder. // A normal game starts at map 1, // but a warp test can start elsewhere void G_DeferedInitNew(skillmode_t skill, uint episode, uint map); void G_DeferedPlayDemo(char* demo); // Can be called by the startup code or Hu_MenuResponder, // calls P_SetupMap or W_EnterWorld. void G_LoadGame(const char* name); void G_DoLoadGame(void); // Called by Hu_MenuResponder. void G_SaveGame(int slot, const char* description); void G_StopDemo(void); void G_DemoEnds(void); void G_DemoAborted(void); // Confusing no? void G_DoReborn(int playernum); void G_PlayerReborn(int player); void G_LeaveMap(uint newMap, uint entryPoint, boolean secretExit); uint G_GetNextMap(uint episode, uint map, boolean secretExit); boolean P_MapExists(uint episode, uint map); void G_WorldDone(void); void G_Ticker(timespan_t ticLength); boolean G_Responder(event_t* ev); void G_ScreenShot(void); void G_PrepareWIData(void); void G_QueueBody(mobj_t* body); void P_GetMapLumpName(uint episode, uint map, char* lumpName); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/d_main.h0000644000175000017500000000374211357170242023061 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_main.h: */ #ifndef __D_MAIN_H__ #define __D_MAIN_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include #include "doomdef.h" extern int verbose; extern boolean devParm; extern boolean noMonstersParm; extern boolean respawnParm; extern boolean fastParm; extern boolean turboParm; extern float turboMul; extern skillmode_t startSkill; extern uint startEpisode; extern uint startMap; extern boolean autoStart; extern FILE *debugFile; extern gamemode_t gameMode; extern int gameModeBits; extern char gameModeString[]; extern boolean monsterInfight; extern char title[]; extern int demoSequence; extern int pageTic; extern char *pageName; extern char *borderLumps[]; void G_PostInit(void); void G_PreInit(void); void G_DetectIWADs(void); void G_IdentifyVersion(void); void G_Shutdown(void); void G_EndFrame(void); void G_Ticker(timespan_t ticLength); boolean G_SetGameMode(gamemode_t mode); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/include/m_menu.h0000644000175000017500000000247211357170242023111 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_menu.h: Menu widget stuff, episode selection and such. */ #ifndef __M_MENU_H__ #define __M_MENU_H__ #ifndef __JDOOM64__ # error "Using jDoom64 headers without __JDOOM64__" #endif #include "hu_stuff.h" void M_LoadData(void); boolean MN_CurrentMenuHasBackground(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/0000755000175000017500000000000011523516204020746 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/special.ded0000644000175000017500000000012311357170242023043 0ustar keeskees# jDoom64: Special Effects Header { Version = 5; } Include "particles.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/skies.ded0000644000175000017500000000152211357170242022545 0ustar keeskees# jDoom64: Skies Sky { ID = "skya"; Height = 0.49; Horizon offset = -0.105; Layer 1 { Flags = enable; Texture = "F_SKYA"; }; } Copy Sky { ID = "skyb"; Layer 1 { Texture = "F_SKYB"; }; } Copy Sky { ID = "skyc"; Layer 1 { Texture = "F_SKYC"; }; } Copy Sky { ID = "skyd"; Layer 1 { Texture = "F_SKYD"; }; } Copy Sky { ID = "skye"; Layer 1 { Texture = "F_SKYE"; }; } Copy Sky { ID = "skyf"; Layer 1 { Texture = "F_SKYF"; }; } Copy Sky { ID = "skyg"; Layer 1 { Texture = "F_SKYG"; }; } Copy Sky { ID = "skyh"; Layer 1 { Texture = "F_SKYH"; }; } Copy Sky { ID = "skyi"; Layer 1 { Texture = "F_SKYI"; }; } Copy Sky { ID = "skyj"; Layer 1 { Texture = "F_SKYJ"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/values.ded0000644000175000017500000001112311357170242022724 0ustar keeskees# jDoom64: Values # (mind yur speling; jDoom64 uses only the identifiers it knows about) # # The strings from all Values definition blocks are merged together. # This means you don't have to add all your values here; they can be # in a Values block in another file. Header { Version = 5; } # The "Patch Replacement" values are used to replace patches with # strings of text. The replacement overrides any checks for external # resources. Only patches in an IWAD can be replaced; this is required # because existing PWADs may replace the original text patches with # their own graphics. # # The replacement is done by searching a value in the "Patch # Replacement" block that matches the lump name of the patch to be # replaced. The text string may optionally contain parameters that # control how the string is displayed. The parameters must be placed # inside braces. If a parameter block is present, the actual text # string begins from the first character following the closing brace. # # "{fonta, scale=2}C{scale=1}APITAL" # # Whitespace inside a parameter block is ignored. Use a comma or a # semicolon to separate parameters. The parameters and their default # values are: # # fonta Use the small font. # fontb Use the large font (the default). # r=1.0 Red color component (0..1). # g=0.0 Green color component (0..1). # b=0.0 Blue color component (0..1). # x=0 Offset to the X coordinate. # y=0 Offset to the Y coordinate. # scale=1.0 Uniform scaling factor (both X and Y). # scalex=1.0 X scaling factor. # scaley=1.0 Y scaling factor. # angle=0.0 Rotation angle (around initial origin). # flash Enable flashy type-in effect. # noflash Disable it (the default). # case Enable case-based scaling. # nocase Disable it (the default). # ups=1.25 Upper case Y scale. # upo=0.0 Upper case Y offset. # los=1.0 Lower case Y scale. # loo=3.0 Lower case Y offset. # break Start a new line. # # An example: # # Values { # Patch Replacement { # M_DOOM = "{R=.5; G=1; B=.5; scale=3}G{scale=2;y=10}ONE { # scale=3;y=0}F{ scale = 2; y = 10 }I{break}SHING"; # }; # } Values { Player { Health = "100"; # Initial health. Max health = "100"; # Maximum health. Health limit = "200"; # Absolute health limit. Green armor = "100"; Blue armor = "200"; Max ammo { Clip = "200"; Shell = "50"; Cell = "300"; Misl = "50"; }; Clip ammo { Clip = "10"; Shell = "4"; Cell = "20"; Misl = "1"; }; }; # Weapon Info|*|Static defaults to "0". # "1" will prevent the lowering of the HUD weapon when doing a switch. Weapon Info { 0 { Type = "noammo"; Up = "PUNCHUP"; Down = "PUNCHDOWN"; Ready = "PUNCH"; Atk = "PUNCH1"; Flash = "NULL"; }; 1 { Type = "clip"; Per shot = "1"; Up = "PISTOLUP"; Down = "PISTOLDOWN"; Ready = "PISTOL"; Atk = "PISTOL1"; Flash = "PISTOLFLASH"; }; 2 { Type = "shell"; Per shot = "1"; Up = "SGUNUP"; Down = "SGUNDOWN"; Ready = "SGUN"; Atk = "SGUN1"; Flash = "SGUNFLASH1"; }; 3 { Type = "clip"; Per shot = "1"; Up = "CHAINUP"; Down = "CHAINDOWN"; Ready = "CHAIN"; Atk = "CHAIN1"; Flash = "CHAINFLASH1"; }; 4 { Type = "misl"; Per shot = "1"; Up = "MISSILEUP"; Down = "MISSILEDOWN"; Ready = "MISSILE"; Atk = "MISSILE1"; Flash = "MISSILEFLASH1"; }; 5 { Type = "cell"; Per shot = "1"; Up = "PLASMAUP"; Down = "PLASMADOWN"; Ready = "PLASMA"; Atk = "PLASMA1"; Flash = "PLASMASHOCK1"; }; 6 { Type = "cell"; Per shot = "40"; Up = "BFGUP"; Down = "BFGDOWN"; Ready = "BFG"; Atk = "BFG1"; Flash = "BFGFLASH1"; }; 7 { Type = "noammo"; Up = "SAWUP"; Down = "SAWDOWN"; Ready = "SAW"; Atk = "SAW1"; Flash = "NULL"; }; 8 { Type = "shell"; Per shot = "2"; Up = "DSGUNUP"; Down = "DSGUNDOWN"; Ready = "DSGUN"; Atk = "DSGUN1"; Flash = "DSGUNFLASH1"; }; 9 { Type = "cell"; Per shot = "1"; Up = "UNKFUP"; Down = "UNKFDOWN"; Ready = "UNKF"; Atk = "UNKF1"; Flash = "UNKFLASH1"; }; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/flags.ded0000644000175000017500000000461111357170242022525 0ustar keeskees# jDoom64: Flags # Mobj flags: Flag { ID = "mf_special"; Value = 0x1; } Flag { ID = "mf_solid"; Value = 0x2; } Flag { ID = "mf_shootable"; Value = 0x4; } Flag { ID = "mf_nosector"; Value = 0x8; } Flag { ID = "mf_noblockmap"; Value = 0x10; } Flag { ID = "mf_ambush"; Value = 0x20; } Flag { ID = "mf_justhit"; Value = 0x40; } Flag { ID = "mf_justattacked"; Value = 0x80; } Flag { ID = "mf_spawnceiling"; Value = 0x100; } Flag { ID = "mf_nogravity"; Value = 0x200; } Flag { ID = "mf_dropoff"; Value = 0x400; } Flag { ID = "mf_pickup"; Value = 0x800; } Flag { ID = "mf_noclip"; Value = 0x1000; } Flag { ID = "mf_float"; Value = 0x4000; } Flag { ID = "mf_teleport"; Value = 0x8000; } Flag { ID = "mf_missile"; Value = 0x10000; } Flag { ID = "mf_dropped"; Value = 0x20000; } Flag { ID = "mf_shadow"; Value = 0x40000; } Flag { ID = "mf_noblood"; Value = 0x80000; } Flag { ID = "mf_corpse"; Value = 0x100000; } Flag { ID = "mf_infloat"; Value = 0x200000; } Flag { ID = "mf_countkill"; Value = 0x400000; } Flag { ID = "mf_countitem"; Value = 0x800000; } Flag { ID = "mf_skullfly"; Value = 0x1000000; } Flag { ID = "mf_notdmatch"; Value = 0x2000000; } Flag { ID = "mf_translation"; Value = 0xC000000; } Flag { ID = "mf_transshift"; Value = 0x1A; } Flag { ID = "mf_local"; Value = 0x10000000; } Flag { ID = "mf_brightshadow"; Value = 0x20000000; } Flag { ID = "mf_brightexplode"; Value = 0x40000000; } Flag { ID = "mf_viewalign"; Value = 0x80000000; } # Mobj flags2: Flag { ID = "mf2_lograv"; Value = 0x1; } Flag { ID = "mf2_floorbounce"; Value = 0x4; } Flag { ID = "mf2_thrughost"; Value = 0x8; } Flag { ID = "mf2_fly"; Value = 0x10; } Flag { ID = "mf2_floorclip"; Value = 0x20; } Flag { ID = "mf2_spawnfloat"; Value = 0x40; } Flag { ID = "mf2_noteleport"; Value = 0x80; } Flag { ID = "mf2_rip"; Value = 0x100; } Flag { ID = "mf2_pushable"; Value = 0x200; } Flag { ID = "mf2_slide"; Value = 0x400; } Flag { ID = "mf2_alwayslit"; Value = 0x800; } Flag { ID = "mf2_passmobj"; Value = 0x1000; } Flag { ID = "mf2_cannotpush"; Value = 0x2000; } Flag { ID = "mf2_radiusattacknomaxz"; Value = 0x4000; } Flag { ID = "mf2_boss"; Value = 0x8000; } Flag { ID = "mf2_nodmgthrust"; Value = 0x20000; } Flag { ID = "mf2_telestomp"; Value = 0x40000; } Flag { ID = "mf2_floatbob"; Value = 0x80000; } Flag { ID = "mf2_dontdraw"; Value = 0x100000; } # Mobj flags3: Flag { ID = "mf3_noinfight"; Value = 0x1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/decorlights.ded0000644000175000017500000000053111357170242023735 0ustar keeskees# # jDoom64: Light decorations. # # The default flags allow using these only with the original textures. # Use "dcf_pwad" and "dcf_ext" to allow using with PWAD and external # resources. # # There can only be one decoration per texture/flat. Newer decorations # override older ones. # # One decoration can specify up to 16 lights. # deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/maps.ded0000644000175000017500000001243411357170242022373 0ustar keeskees# jDoom64: Maps # Used for any maps without a map info definition Map Info { ID = "*"; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP01"; Name = "HUSTR_MAP01"; Author = "Midway"; Par time = 90; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP02"; Name = "HUSTR_MAP02"; Author = "Midway"; Par time = 120; Gravity = 1; Sky = "skyd"; } Map Info { ID = "MAP03"; Name = "HUSTR_MAP03"; Author = "Midway"; Par time = 120; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP04"; Name = "HUSTR_MAP04"; Author = "Midway"; Par time = 120; Gravity = 1; Sky = "skyd"; } Map Info { ID = "MAP05"; Name = "HUSTR_MAP05"; Author = "Midway"; Par time = 130; Gravity = 1; Sky = "skyd"; } Map Info { ID = "MAP06"; Name = "HUSTR_MAP06"; Author = "Midway"; Par time = 150; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP07"; Name = "HUSTR_MAP07"; Author = "Midway"; Par time = 240; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP08"; Name = "HUSTR_MAP08"; Author = "Midway"; Par time = 120; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP09"; Name = "HUSTR_MAP09"; Author = "Midway"; Par time = 240; Gravity = 1; Sky = "skye"; } Map Info { ID = "MAP10"; Name = "HUSTR_MAP10"; Author = "Midway"; Par time = 120; Gravity = 1; Sky = "skyb"; } Map Info { ID = "MAP11"; Name = "HUSTR_MAP11"; Author = "Midway"; Par time = 190; Gravity = 1; Sky = "skyc"; } Map Info { ID = "MAP12"; Name = "HUSTR_MAP12"; Author = "Midway"; Par time = 180; Gravity = 1; Sky = "skyc"; } Map Info { ID = "MAP13"; Name = "HUSTR_MAP13"; Author = "Midway"; Par time = 160; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP14"; Name = "HUSTR_MAP14"; Author = "Midway"; Par time = 120; Gravity = 1; Sky = "skyc"; } Map Info { ID = "MAP15"; Name = "HUSTR_MAP15"; Author = "Midway"; Par time = 190; Gravity = 1; Sky = "skye"; } Map Info { ID = "MAP16"; Name = "HUSTR_MAP16"; Author = "Midway"; Music = "stalks"; Par time = 120; Gravity = 1; Sky = "skyb"; } Map Info { ID = "MAP17"; Name = "HUSTR_MAP17"; Author = "Midway"; Par time = 240; Gravity = 1; Flags = "mif_fog"; Fog color R = 1.0; Fog color G = 0.5; Fog color B = 0; Fog start = 400; Fog end = 3000; Sky = "skyb"; } Map Info { ID = "MAP18"; Name = "HUSTR_MAP18"; Author = "Midway"; Par time = 160; Gravity = 1; Sky = "skye"; } Map Info { ID = "MAP19"; Name = "HUSTR_MAP19"; Author = "Midway"; Par time = 90; Gravity = 1; Sky = "skyb"; } Map Info { ID = "MAP20"; Name = "HUSTR_MAP20"; Author = "Midway"; Par time = 180; Gravity = 1; Sky = "skye"; } Map Info { ID = "MAP21"; Name = "HUSTR_MAP21"; Author = "Midway"; Par time = 180; Gravity = 1; Sky = "skyc"; } Map Info { ID = "MAP22"; Name = "HUSTR_MAP22"; Author = "Midway"; Music = "doom"; Par time = 120; Gravity = 1; Sky = "skyf"; } Map Info { ID = "MAP23"; Name = "HUSTR_MAP23"; Author = "Midway"; Music = "ddtblu"; Par time = 240; Gravity = 1; Sky = "skyg"; } Map Info { ID = "MAP24"; Name = "HUSTR_MAP24"; Author = "Midway"; Music = "theda2"; Par time = 180; Gravity = 1; Sky = "skyg"; } Map Info { ID = "MAP25"; Name = "HUSTR_MAP25"; Author = "Midway"; Music = "betwee"; Par time = 90; Gravity = 1; Flags = "mif_fog"; Fog color R = 0; Fog color G = 1.0; Fog color B = 1.0; Fog start = 400; Fog end = 3000; Sky = "skya"; } Map Info { ID = "MAP26"; Name = "HUSTR_MAP26"; Author = "Midway"; Music = "theda2"; Par time = 30; Gravity = 1; Flags = "mif_fog"; Fog color R = 0; Fog color G = 1; Fog color B = 1; Fog start = 100; Fog end = 2000; Sky = "skyh"; } Map Info { ID = "MAP27"; Name = "HUSTR_MAP27"; Author = "Midway"; Gravity = 1; Music = "messag"; Par time = 30; Flags = "mif_fog"; Fog color R = 1.0; Fog color G = 0.5; Fog color B = 0; Fog start = 100; Fog end = 2000; Sky = "skyb"; } Map Info { ID = "MAP28"; Name = "HUSTR_MAP28"; Author = "Midway"; Music = "doom2"; Par time = 400; Gravity = 1; Sky = "skyf"; } Map Info { ID = "MAP29"; Name = "HUSTR_MAP29"; Author = "Midway"; Music = "messag"; Par time = 190; Gravity = 1; Sky = "skya"; } Map Info { ID = "MAP30"; Name = "HUSTR_MAP30"; Author = "Midway"; Music = "runni2"; Par time = 160; Gravity = 1; Sky = "skyi"; } Map Info { ID = "MAP31"; Name = "HUSTR_MAP31"; Author = "Midway"; Music = "the_da"; Par time = 120; Gravity = 1; Flags = "mif_fog"; Fog color R = 0; Fog color G = 1.0; Fog color B = 1.0; Fog start = 100; Fog end = 2000; Sky = "skyj"; } Map Info { ID = "MAP32"; Name = "HUSTR_MAP32"; Author = "Midway"; Music = "betwee"; Par time = 90; Gravity = 1; Sky = "skyg"; } Map Info { ID = "MAP33"; Name = "HUSTR_MAP33"; Author = "Midway"; Music = "evil"; Par time = 30; Gravity = 1; Sky = "skya"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/anim.ded0000644000175000017500000000333311357170242022355 0ustar keeskees# jDoom64: Additional Animation Sequences # # DOOM64 has predefined texture animation sequences. # In order to remain compatible with existing WADs, jDoom64 builds # animations from these predefined sequences and creates texture # animation groups for them. The flags "tgf_smooth" and # "tgf_first_only" are set for each group. # # Additional sequences can be defined using Group definitions. Header { Version = 6; } # # Precache groups. # Group { Flags = precache; Texture { ID = "SWXCA"; Tics = 0; }; Texture { ID = "SWXCB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXCKA"; Tics = 0; }; Texture { ID = "SWXCKB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXCKLA"; Tics = 0; }; Texture { ID = "SWXCKLB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXCLA"; Tics = 0; }; Texture { ID = "SWXCLB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXHCA"; Tics = 0; }; Texture { ID = "SWXHCB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXSAA"; Tics = 0; }; Texture { ID = "SWXSAB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXSCA"; Tics = 0; }; Texture { ID = "SWXSCB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXSDA"; Tics = 0; }; Texture { ID = "SWXSDB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXSEA"; Tics = 0; }; Texture { ID = "SWXSEB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXSFA"; Tics = 0; }; Texture { ID = "SWXSFB"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SWXSGA"; Tics = 0; }; Texture { ID = "SWXSGB"; Tics = 0; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/materials.ded0000644000175000017500000000146711357170242023420 0ustar keeskees# jDoom64: Material Enhancements # # Patch the Material definitions created automatically # by the engine, adding new effects to them. Header { Version = 6; } # # Skymasked textures: # Material { ID = "F_SKYA"; Namespace = textures; Flags = skymask; } * Material { ID = "F_SKYB"; } * Material { ID = "F_SKYC"; } * Material { ID = "F_SKYD"; } * Material { ID = "F_SKYE"; } * Material { ID = "F_SKYF"; } * Material { ID = "F_SKYG"; } * Material { ID = "F_SKYH"; } * Material { ID = "F_SKYI"; } * Material { ID = "F_SKYJ"; } * Material { ID = "F_SKYK"; } # # Glowing textures: # Material { ID = "CBTRAKA"; Namespace = textures; Flags = glow; } * Material { ID = "CRTRAKA"; } * Material { ID = "CYTRAKA"; } * Material { ID = "SEXIT"; } * Material { ID = "SEXITA"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/audio.ded0000644000175000017500000010331711357170242022535 0ustar keeskees# jDoom64: Music and Sound Effects Header { Version = 5; } #####====--- MUSIC ---====##### Music { ID = "None"; } Music { ID = "inter"; Lump = "D_INTER"; } Music { ID = "intro"; Lump = "D_INTRO"; } Music { ID = "bunny"; Lump = "D_BUNNY"; } Music { ID = "victor"; Lump = "D_VICTOR"; } Music { ID = "introa"; Lump = "D_INTROA"; } Music { ID = "runnin"; Lump = "D_RUNNIN"; } Music { ID = "stalks"; Lump = "D_STALKS"; } Music { ID = "countd"; Lump = "D_COUNTD"; } Music { ID = "betwee"; Lump = "D_BETWEE"; } Music { ID = "doom"; Lump = "D_DOOM"; } Music { ID = "the_da"; Lump = "D_THE_DA"; } Music { ID = "shawn"; Lump = "D_SHAWN"; } Music { ID = "ddtblu"; Lump = "D_DDTBLU"; } Music { ID = "in_cit"; Lump = "D_IN_CIT"; } Music { ID = "dead"; Lump = "D_DEAD"; } Music { ID = "stlks2"; Lump = "D_STLKS2"; } Music { ID = "theda2"; Lump = "D_THEDA2"; } Music { ID = "doom2"; Lump = "D_DOOM2"; } Music { ID = "ddtbl2"; Lump = "D_DDTBL2"; } Music { ID = "runni2"; Lump = "D_RUNNI2"; } Music { ID = "dead2"; Lump = "D_DEAD2"; } Music { ID = "stlks3"; Lump = "D_STLKS3"; } Music { ID = "romero"; Lump = "D_ROMERO"; } Music { ID = "shawn2"; Lump = "D_SHAWN2"; } Music { ID = "messag"; Lump = "D_MESSAG"; } Music { ID = "count2"; Lump = "D_COUNT2"; } Music { ID = "ddtbl3"; Lump = "D_DDTBL3"; } Music { ID = "ampie"; Lump = "D_AMPIE"; } Music { ID = "theda3"; Lump = "D_THEDA3"; } Music { ID = "adrian"; Lump = "D_ADRIAN"; } Music { ID = "messg2"; Lump = "D_MESSG2"; } Music { ID = "romer2"; Lump = "D_ROMER2"; } Music { ID = "tense"; Lump = "D_TENSE"; } Music { ID = "shawn3"; Lump = "D_SHAWN3"; } Music { ID = "openin"; Lump = "D_OPENIN"; } Music { ID = "evil"; Lump = "D_EVIL"; } Music { ID = "ultima"; Lump = "D_ULTIMA"; } Music { ID = "read_m"; Lump = "D_READ_M"; } Music { ID = "dm2ttl"; Lump = "D_DM2TTL"; } Music { ID = "dm2int"; Lump = "D_DM2INT"; } #####====--- SOUND EFFECTS ---====##### Sound { ID = "None"; Link pitch = -1; Link volume = -1; Max channels = -1; } Sound { ID = "pistol"; Flags = "sf_shift2"; Lump = "DSPISTOL"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "shotgn"; Flags = "sf_shift2"; Lump = "DSSHOTGN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = 4; } Sound { ID = "sgcock"; Flags = "sf_shift2"; Lump = "DSSGCOCK"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dshtgn"; Flags = "sf_shift2"; Lump = "DSDSHTGN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbopn"; Flags = "sf_shift2"; Lump = "DSDBOPN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbcls"; Flags = "sf_shift2"; Lump = "DSDBCLS"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbload"; Flags = "sf_shift2"; Lump = "DSDBLOAD"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "plasma"; Flags = "sf_shift2"; Lump = "DSPLASMA"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = 4; } Sound { ID = "bfg"; Flags = "sf_shift2"; Lump = "DSBFG"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "sawup"; Flags = "sf_shift"; Lump = "DSSAWUP"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "sawidl"; Flags = "sf_shift"; Lump = "DSSAWIDL"; Link pitch = -1; Link volume = -1; Priority = 118; Max channels = -1; Group = 1; } Sound { ID = "sawful"; Flags = "sf_shift"; Lump = "DSSAWFUL"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "sawhit"; Flags = "sf_shift sf_dontstop"; Lump = "DSSAWHIT"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "rlaunc"; Flags = "sf_shift2"; Lump = "DSRLAUNC"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "rxplod"; Flags = "sf_shift2 sf_dontstop"; Lump = "DSRXPLOD"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "firsht"; Flags = "sf_shift2"; Lump = "DSFIRSHT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "firxpl"; Flags = "sf_shift2 sf_dontstop"; Lump = "DSFIRXPL"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = 2; } Sound { ID = "pstart"; Flags = "sf_shift2"; Lump = "DSPSTART"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "pstop"; Flags = "sf_shift2"; Lump = "DSPSTOP"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "doropn"; Flags = "sf_shift2"; Lump = "DSDOROPN"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "dorcls"; Flags = "sf_shift2"; Lump = "DSDORCLS"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "stnmov"; Flags = "sf_shift2"; Lump = "DSSTNMOV"; Link pitch = -1; Link volume = -1; Priority = 119; Max channels = -1; } Sound { ID = "swtchn"; Flags = "sf_shift2"; Lump = "DSSWTCHN"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "swtchx"; Flags = "sf_shift2"; Lump = "DSSWTCHX"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "plpain"; Flags = "sf_shift2"; Lump = "DSPLPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "dmpain"; Flags = "sf_shift2"; Lump = "DSDMPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "popain"; Flags = "sf_shift2"; Lump = "DSPOPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "vipain"; Flags = "sf_shift2"; Lump = "DSVIPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "mnpain"; Flags = "sf_shift2"; Lump = "DSMNPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "pepain"; Flags = "sf_shift2"; Lump = "DSPEPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "slop"; Flags = "sf_shift2"; Lump = "DSSLOP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "itemup"; Lump = "DSITEMUP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = 1; } Sound { ID = "wpnup"; Flags = "sf_shift2"; Lump = "DSWPNUP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = 1; } Sound { ID = "oof"; Flags = "sf_shift2"; Lump = "DSOOF"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "telept"; Flags = "sf_shift2"; Lump = "DSTELEPT"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "posit1"; Flags = "sf_shift2"; Lump = "DSPOSIT1"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "posit2"; Flags = "sf_shift2"; Lump = "DSPOSIT2"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "posit3"; Flags = "sf_shift2"; Lump = "DSPOSIT3"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "bgsit1"; Flags = "sf_shift2"; Lump = "DSBGSIT1"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "bgsit2"; Flags = "sf_shift2"; Lump = "DSBGSIT2"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "sgtsit"; Flags = "sf_shift2"; Lump = "DSSGTSIT"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "cacsit"; Flags = "sf_shift2"; Lump = "DSCACSIT"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "brssit"; Flags = "sf_shift2"; Lump = "DSBRSSIT"; Link pitch = -1; Link volume = -1; Priority = 94; Max channels = 1; } Sound { ID = "cybsit"; Flags = "sf_shift2"; Lump = "DSCYBSIT"; Link pitch = -1; Link volume = -1; Priority = 92; Max channels = 1; } Sound { ID = "bspsit"; Flags = "sf_shift2"; Lump = "DSBSPSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "kntsit"; Flags = "sf_shift2"; Lump = "DSKNTSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "vilsit"; Flags = "sf_shift2"; Lump = "DSVILSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "mansit"; Flags = "sf_shift2"; Lump = "DSMANSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "pesit"; Flags = "sf_shift2"; Lump = "DSPESIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "sklatk"; Flags = "sf_shift2"; Lump = "DSSKLATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sgtatk"; Flags = "sf_shift2"; Lump = "DSSGTATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skepch"; Flags = "sf_shift2"; Lump = "DSSKEPCH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "vilatk"; Flags = "sf_shift2"; Lump = "DSVILATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "claw"; Flags = "sf_shift2"; Lump = "DSCLAW"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeswg"; Flags = "sf_shift2"; Lump = "DSSKESWG"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "pldeth"; Flags = "sf_shift2"; Lump = "DSPLDETH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "pdiehi"; Flags = "sf_shift2"; Lump = "DSPDIEHI"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "podth1"; Flags = "sf_shift2"; Lump = "DSPODTH1"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "podth2"; Flags = "sf_shift2"; Lump = "DSPODTH2"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "podth3"; Flags = "sf_shift2"; Lump = "DSPODTH3"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bgdth1"; Flags = "sf_shift2"; Lump = "DSBGDTH1"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bgdth2"; Flags = "sf_shift2"; Lump = "DSBGDTH2"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sgtdth"; Flags = "sf_shift2"; Lump = "DSSGTDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "cacdth"; Flags = "sf_shift2"; Lump = "DSCACDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skldth"; Flags = "sf_shift2"; Lump = "DSSKLDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "brsdth"; Flags = "sf_shift2"; Lump = "DSBRSDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "cybdth"; Flags = "sf_shift2"; Lump = "DSCYBDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "bspdth"; Flags = "sf_shift2"; Lump = "DSBSPDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "vildth"; Flags = "sf_shift2"; Lump = "DSVILDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "kntdth"; Flags = "sf_shift2"; Lump = "DSKNTDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "pedth"; Flags = "sf_shift2"; Lump = "DSPEDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "skedth"; Flags = "sf_shift2"; Lump = "DSSKEDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "posact"; Flags = "sf_shift2"; Lump = "DSPOSACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "bgact"; Flags = "sf_shift2"; Lump = "DSBGACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "dmact"; Flags = "sf_shift2"; Lump = "DSDMACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "bspact"; Flags = "sf_shift2"; Lump = "DSBSPACT"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "bspwlk"; Flags = "sf_shift2"; Lump = "DSBSPWLK"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "vilact"; Flags = "sf_shift2"; Lump = "DSVILACT"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "noway"; Flags = "sf_shift2"; Lump = "DSNOWAY"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "barexp"; Flags = "sf_shift2 sf_dontstop"; Lump = "DSBAREXP"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "punch"; Flags = "sf_shift2"; Lump = "DSPUNCH"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "hoof"; Flags = "sf_shift2"; Lump = "DSHOOF"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "metal"; Flags = "sf_shift2"; Lump = "DSMETAL"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "chgun"; Flags = "sf_shift2"; Lump = "DSCHGUN"; Link = "pistol"; Link pitch = 150; Priority = 64; Max channels = -1; } Sound { ID = "tink"; Lump = "DSTINK"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "bdopn"; Flags = "sf_shift2"; Lump = "DSBDOPN"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "bdcls"; Flags = "sf_shift2"; Lump = "DSBDCLS"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "itmbk"; Flags = "sf_shift2"; Lump = "DSITMBK"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "flame"; Flags = "sf_shift2"; Lump = "DSFLAME"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "flamst"; Flags = "sf_shift2"; Lump = "DSFLAMST"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "getpow"; Flags = "sf_shift2"; Lump = "DSGETPOW"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "manatk"; Flags = "sf_shift2"; Lump = "DSMANATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "mandth"; Flags = "sf_shift2"; Lump = "DSMANDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sssit"; Flags = "sf_shift2"; Lump = "DSSSSIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "ssdth"; Flags = "sf_shift2"; Lump = "DSSSDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeact"; Flags = "sf_shift2"; Lump = "DSSKEACT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skesit"; Flags = "sf_shift2"; Lump = "DSSKESIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeatk"; Flags = "sf_shift2"; Lump = "DSSKEATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "radio"; Lump = "DSRADIO"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "psidl"; Lump = "DSPSIDL"; Link pitch = -1; Link volume = -1; Priority = 16; Max channels = 2; } Sound { ID = "laser"; Lump = "DSLASER"; Flags = "sf_dontstop"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = 1; } Sound { ID = "mthatk"; Lump = "DSMTHATK"; Link pitch = -1; Link volume = -1; Priority = 80; Max channels = 1; } Sound { ID = "mthsit"; Lump = "DSMTHSIT"; Link pitch = -1; Link volume = -1; Priority = 80; Max channels = 1; } Sound { ID = "mthpai"; Lump = "DSMTHPAI"; Link pitch = -1; Link volume = -1; Priority = 80; Max channels = 1; } Sound { ID = "mthact"; Lump = "DSMTHACT"; Link pitch = -1; Link volume = -1; Priority = 80; Max channels = 1; } Sound { ID = "mthdth"; Lump = "DSMTHDTH"; Link pitch = -1; Link volume = -1; Priority = 80; Max channels = 1; } Sound { ID = "htime"; Flags = "sf_shift2"; Lump = "DSHTIME"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "secret"; Flags = "sf_shift2"; Lump = "DSGETPOW"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Texture Environment { ID = "Metal"; Texture { ID = "BIGDOOR1"; }; Texture { ID = "BIGDOOR2"; }; Texture { ID = "BIGDOOR4"; }; Texture { ID = "COMP2"; }; Texture { ID = "COMPSPAN"; }; Texture { ID = "COMPSTA1"; }; Texture { ID = "COMPSTA2"; }; Texture { ID = "COMPTALL"; }; Texture { ID = "COMPUTE1"; }; Texture { ID = "COMPUTE2"; }; Texture { ID = "DOOR1"; }; Texture { ID = "DOOR3"; }; Texture { ID = "DOORBLU"; }; Texture { ID = "DOORRED"; }; Texture { ID = "DOORSTOP"; }; Texture { ID = "DOORYEL"; }; Texture { ID = "EXITDOOR"; }; Texture { ID = "EXITSIGN"; }; Texture { ID = "LITE3"; }; Texture { ID = "LITE4"; }; Texture { ID = "LITE5"; }; Texture { ID = "LITEBLU1"; }; Texture { ID = "LITEBLU2"; }; Texture { ID = "LITEBLU3"; }; Texture { ID = "LITEBLU4"; }; Texture { ID = "METAL1"; }; Texture { ID = "PLANET1"; }; Texture { ID = "PLAT1"; }; Texture { ID = "REDWALL1"; }; Texture { ID = "SHAWN2"; }; Texture { ID = "STARG1"; }; Texture { ID = "STARG3"; }; Texture { ID = "STARGR1"; }; Texture { ID = "STARTAN1"; }; Texture { ID = "STARTAN2"; }; Texture { ID = "STARTAN3"; }; Texture { ID = "STEP4"; }; Texture { ID = "SUPPORT2"; }; Texture { ID = "SW1COMM"; }; Texture { ID = "SW1COMP"; }; Texture { ID = "SW1METAL"; }; Texture { ID = "SW1STARG"; }; Texture { ID = "SW1STRTN"; }; Texture { ID = "SW2COMM"; }; Texture { ID = "SW2COMP"; }; Texture { ID = "SW2METAL"; }; Texture { ID = "SW2STARG"; }; Texture { ID = "SW2STRTN"; }; Texture { ID = "BIGDOOR3"; }; Texture { ID = "COMPWERD"; }; Texture { ID = "DOORBLU2"; }; Texture { ID = "DOORRED2"; }; Texture { ID = "DOORYEL2"; }; Texture { ID = "GRAY2"; }; Texture { ID = "GRAYPOIS"; }; Texture { ID = "ICKDOOR1"; }; Texture { ID = "LITEMET"; }; Texture { ID = "LITERED"; }; Texture { ID = "LITESTON"; }; Texture { ID = "METAL"; }; Texture { ID = "SHAWN1"; }; Texture { ID = "SHAWN3"; }; Texture { ID = "STARBR2"; }; Texture { ID = "STARG2"; }; Texture { ID = "STARGR2"; }; Texture { ID = "SUPPORT3"; }; Texture { ID = "BRONZE1"; }; Texture { ID = "BRONZE2"; }; Texture { ID = "BRONZE3"; }; Texture { ID = "BRONZE4"; }; Texture { ID = "METAL2"; }; Texture { ID = "METAL3"; }; Texture { ID = "METAL4"; }; Texture { ID = "METAL5"; }; Texture { ID = "METAL6"; }; Texture { ID = "METAL7"; }; Texture { ID = "MODWALL3"; }; Texture { ID = "MODWALL4"; }; Texture { ID = "PIPES"; }; Texture { ID = "SILVER1"; }; Texture { ID = "SILVER2"; }; Texture { ID = "SILVER3"; }; Texture { ID = "SPACEW3"; }; Texture { ID = "SPACEW4"; }; Texture { ID = "SPCDOOR1"; }; Texture { ID = "SPCDOOR2"; }; Texture { ID = "SPCDOOR3"; }; Texture { ID = "SW1MET2"; }; Texture { ID = "SW2MET2"; }; Texture { ID = "SW1TEK"; }; Texture { ID = "SW2TEK"; }; Texture { ID = "SW1WDMET"; }; Texture { ID = "SW2WDMET"; }; Texture { ID = "TEKBRON1"; }; Texture { ID = "TEKBRON2"; }; Texture { ID = "TEKGREN1"; }; Texture { ID = "TEKGREN2"; }; Texture { ID = "TEKGREN3"; }; Texture { ID = "TEKGREN4"; }; Texture { ID = "TEKGREN5"; }; Texture { ID = "WOODMET1"; }; Texture { ID = "WOODMET2"; }; Texture { ID = "WOODMET3"; }; Texture { ID = "WOODMET4"; }; Texture { ID = "ZDOORB1"; }; Texture { ID = "ZDOORF1"; }; Texture { ID = "ZELDOOR"; }; Texture { ID = "ZZWOLF10"; }; Texture { ID = "ZZZFACE6"; }; Texture { ID = "ZZZFACE7"; }; Texture { ID = "ZZZFACE8"; }; Texture { ID = "ZZZFACE9"; }; } Texture Environment { ID = "Rock"; Texture { ID = "AASTINKY"; }; Texture { ID = "BRNPOIS"; }; Texture { ID = "BRNPOIS2"; }; Texture { ID = "BROWN1"; }; Texture { ID = "BROWN144"; }; Texture { ID = "BROWN96"; }; Texture { ID = "BROWNGRN"; }; Texture { ID = "BROWNHUG"; }; Texture { ID = "BROWNPIP"; }; Texture { ID = "COMPUTE3"; }; Texture { ID = "GRAY4"; }; Texture { ID = "GRAY5"; }; Texture { ID = "GRAY7"; }; Texture { ID = "GRAYTALL"; }; Texture { ID = "LITE2"; }; Texture { ID = "NUKE24"; }; Texture { ID = "NUKEDGE1"; }; Texture { ID = "STEP6"; }; Texture { ID = "STONE"; }; Texture { ID = "STONE2"; }; Texture { ID = "STONE3"; }; Texture { ID = "STONE4"; }; Texture { ID = "STONE5"; }; Texture { ID = "STONE6"; }; Texture { ID = "STONE7"; }; Texture { ID = "STONPOIS"; }; Texture { ID = "SW1BRCOM"; }; Texture { ID = "SW1BRN1"; }; Texture { ID = "SW1BRN2"; }; Texture { ID = "SW1BRGRN"; }; Texture { ID = "SW1BROWN"; }; Texture { ID = "SW1EXIT"; }; Texture { ID = "SW1GRAY"; }; Texture { ID = "SW1GRAY1"; }; Texture { ID = "SW1STON1"; }; Texture { ID = "SW1STON2"; }; Texture { ID = "SW1STONE"; }; Texture { ID = "SW2BRCOM"; }; Texture { ID = "SW2BRN1"; }; Texture { ID = "SW2BRN2"; }; Texture { ID = "SW2BRGRN"; }; Texture { ID = "SW2BROWN"; }; Texture { ID = "SW2EXIT"; }; Texture { ID = "SW2GRAY"; }; Texture { ID = "SW2GRAY1"; }; Texture { ID = "SW2STON1"; }; Texture { ID = "SW2STON2"; }; Texture { ID = "SW2STONE"; }; Texture { ID = "BIGDOOR5"; }; Texture { ID = "BROWNWEL"; }; Texture { ID = "CEMENT1"; }; Texture { ID = "CEMENT2"; }; Texture { ID = "CEMENT3"; }; Texture { ID = "CEMENT4"; }; Texture { ID = "CEMENT5"; }; Texture { ID = "CEMENT6"; }; Texture { ID = "CEMENT7"; }; Texture { ID = "CEMENT8"; }; Texture { ID = "CEMENT9"; }; Texture { ID = "CEMPOIS"; }; Texture { ID = "DOORHI"; }; Texture { ID = "EXITSTON"; }; Texture { ID = "FIREMAG1"; }; Texture { ID = "FIREMAG2"; }; Texture { ID = "FIREMAG3"; }; Texture { ID = "FIREWALL"; }; Texture { ID = "FIREWALA"; }; Texture { ID = "FIREWALB"; }; Texture { ID = "GRAY1"; }; Texture { ID = "GRAYBIG"; }; Texture { ID = "GRAYDANG"; }; Texture { ID = "GSTFONT1"; }; Texture { ID = "GSTFONT2"; }; Texture { ID = "GSTFONT3"; }; Texture { ID = "GSTGARG"; }; Texture { ID = "GSTLION"; }; Texture { ID = "GSTONE1"; }; Texture { ID = "GSTONE2"; }; Texture { ID = "GSTSATYR"; }; Texture { ID = "ICKWALL1"; }; Texture { ID = "ICKWALL2"; }; Texture { ID = "ICKWALL3"; }; Texture { ID = "ICKWALL4"; }; Texture { ID = "ICKWALL5"; }; Texture { ID = "ICKWALL6"; }; Texture { ID = "ICKWALL7"; }; Texture { ID = "LITE96"; }; Texture { ID = "MARBFAC2"; }; Texture { ID = "MARBFAC3"; }; Texture { ID = "MARBFAC4"; }; Texture { ID = "MARBFACE"; }; Texture { ID = "MARBLE1"; }; Texture { ID = "MARBLE2"; }; Texture { ID = "MARBLE3"; }; Texture { ID = "MARBLOD1"; }; Texture { ID = "REDWALL"; }; Texture { ID = "ROCKRED1"; }; Texture { ID = "ROCKRED2"; }; Texture { ID = "ROCKRED3"; }; Texture { ID = "SP_DUDE1"; }; Texture { ID = "SP_DUDE2"; }; Texture { ID = "SP_DUDE6"; }; Texture { ID = "SP_HOT1"; }; Texture { ID = "SP_ROCK1"; }; Texture { ID = "SP_ROCK2"; }; Texture { ID = "STONGARG"; }; Texture { ID = "SW1CMT"; }; Texture { ID = "SW1GSTON"; }; Texture { ID = "SW1HOT"; }; Texture { ID = "SW2CMT"; }; Texture { ID = "SW2GSTON"; }; Texture { ID = "SW2HOT"; }; Texture { ID = "WOOD5"; }; Texture { ID = "ASHWALL2"; }; Texture { ID = "ASHWALL3"; }; Texture { ID = "ASHWALL4"; }; Texture { ID = "ASHWALL6"; }; Texture { ID = "ASHWALL7"; }; Texture { ID = "BIGBRIK1"; }; Texture { ID = "BIGBRIK2"; }; Texture { ID = "BIGBRIK3"; }; Texture { ID = "BLAKWAL1"; }; Texture { ID = "BLAKWAL2"; }; Texture { ID = "BRICK1"; }; Texture { ID = "BRICK2"; }; Texture { ID = "BRICK3"; }; Texture { ID = "BRICK4"; }; Texture { ID = "BRICK5"; }; Texture { ID = "BRICK6"; }; Texture { ID = "BRICK7"; }; Texture { ID = "BRICK8"; }; Texture { ID = "BRICK9"; }; Texture { ID = "BRICK10"; }; Texture { ID = "BRICK11"; }; Texture { ID = "BRICK12"; }; Texture { ID = "BRICKLIT"; }; Texture { ID = "BSTONE1"; }; Texture { ID = "BSTONE2"; }; Texture { ID = "BSTONE3"; }; Texture { ID = "CRACKLE2"; }; Texture { ID = "CRACKLE4"; }; Texture { ID = "MARBGRAY"; }; Texture { ID = "MIDBRONZ"; }; Texture { ID = "MODWALL1"; }; Texture { ID = "MODWALL2"; }; Texture { ID = "PANEL6"; }; Texture { ID = "PANEL7"; }; Texture { ID = "PANEL8"; }; Texture { ID = "PANEL9"; }; Texture { ID = "PIPEWAL1"; }; Texture { ID = "PIPEWAL2"; }; Texture { ID = "ROCK1"; }; Texture { ID = "ROCK2"; }; Texture { ID = "ROCK3"; }; Texture { ID = "ROCK4"; }; Texture { ID = "ROCK5"; }; Texture { ID = "SPACEW2"; }; Texture { ID = "SPCDOOR4"; }; Texture { ID = "SW1BRIK"; }; Texture { ID = "SW2BRIK"; }; Texture { ID = "SW1MOD1"; }; Texture { ID = "SW2MOD1"; }; Texture { ID = "SW1ROCK"; }; Texture { ID = "SW2ROCK"; }; Texture { ID = "SW1SKULL"; }; Texture { ID = "SW2SKULL"; }; Texture { ID = "SW1STON6"; }; Texture { ID = "SW2STON6"; }; Texture { ID = "SW1ZIM"; }; Texture { ID = "SW2ZIM"; }; Texture { ID = "TANROCK2"; }; Texture { ID = "TANROCK3"; }; Texture { ID = "TANROCK4"; }; Texture { ID = "TANROCK5"; }; Texture { ID = "TANROCK7"; }; Texture { ID = "TANROCK8"; }; Texture { ID = "TEKLITE"; }; Texture { ID = "TEKLITE2"; }; Texture { ID = "ZIMMER1"; }; Texture { ID = "ZIMMER2"; }; Texture { ID = "ZIMMER3"; }; Texture { ID = "ZIMMER4"; }; Texture { ID = "ZIMMER5"; }; Texture { ID = "ZIMMER7"; }; Texture { ID = "ZIMMER8"; }; Texture { ID = "ZZWOLF1"; }; Texture { ID = "ZZWOLF11"; }; Texture { ID = "ZZWOLF2"; }; Texture { ID = "ZZWOLF9"; }; Texture { ID = "ZZZFACE1"; }; Texture { ID = "ZZZFACE2"; }; Texture { ID = "ZZZFACE3"; }; Texture { ID = "ZZZFACE4"; }; Texture { ID = "ZZZFACE5"; }; } Texture Environment { ID = "Wood"; Texture { ID = "BRNBIGC"; }; Texture { ID = "BRNBIGL"; }; Texture { ID = "BRNBIGR"; }; Texture { ID = "BRNSMAL1"; }; Texture { ID = "BRNSMAL2"; }; Texture { ID = "BRNSMALC"; }; Texture { ID = "BRNSMALL"; }; Texture { ID = "BRNSMALR"; }; Texture { ID = "COMPTILE"; }; Texture { ID = "DOORTRAK"; }; Texture { ID = "NUKESLAD"; }; Texture { ID = "PIPE2"; }; Texture { ID = "SLADPOIS"; }; Texture { ID = "SLADRIP1"; }; Texture { ID = "SLADRIP2"; }; Texture { ID = "SLADRIP3"; }; Texture { ID = "SLADWALL"; }; Texture { ID = "STEP1"; }; Texture { ID = "STEP2"; }; Texture { ID = "STEP3"; }; Texture { ID = "STEP5"; }; Texture { ID = "SW1PIPE"; }; Texture { ID = "SW1SLAD"; }; Texture { ID = "SW2PIPE"; }; Texture { ID = "SW2SLAD"; }; Texture { ID = "TEKWALL1"; }; Texture { ID = "TEKWALL2"; }; Texture { ID = "TEKWALL3"; }; Texture { ID = "TEKWALL4"; }; Texture { ID = "TEKWALL5"; }; Texture { ID = "TEKWALL6"; }; Texture { ID = "BIGDOOR6"; }; Texture { ID = "BIGDOOR7"; }; Texture { ID = "BLODGR1"; }; Texture { ID = "BLODGR2"; }; Texture { ID = "BLODGR3"; }; Texture { ID = "BLODGR4"; }; Texture { ID = "BLODRIP1"; }; Texture { ID = "BLODRIP2"; }; Texture { ID = "BLODRIP3"; }; Texture { ID = "BLODRIP4"; }; Texture { ID = "COMPOHSO"; }; Texture { ID = "CRATE1"; }; Texture { ID = "CRATE2"; }; Texture { ID = "CRATELIT"; }; Texture { ID = "CRATINY"; }; Texture { ID = "CRATWIDE"; }; Texture { ID = "FIREBLU1"; }; Texture { ID = "FIREBLU2"; }; Texture { ID = "FIRELAVA"; }; Texture { ID = "FIRELAV2"; }; Texture { ID = "FIRELAV3"; }; Texture { ID = "GRAYVINE"; }; Texture { ID = "GSTVINE1"; }; Texture { ID = "GSTVINE2"; }; Texture { ID = "PIPE1"; }; Texture { ID = "PIPE4"; }; Texture { ID = "PIPE6"; }; Texture { ID = "SKINCUT"; }; Texture { ID = "SKINLOW"; }; Texture { ID = "SKINMET1"; }; Texture { ID = "SKINMET2"; }; Texture { ID = "SKINSYMB"; }; Texture { ID = "SKINTEK1"; }; Texture { ID = "SKINTEK2"; }; Texture { ID = "SKSPINE1"; }; Texture { ID = "SKSPINE2"; }; Texture { ID = "SKULWAL3"; }; Texture { ID = "SKULWALL"; }; Texture { ID = "SLADSKUL"; }; Texture { ID = "SP_DUDE3"; }; Texture { ID = "SP_DUDE4"; }; Texture { ID = "SP_DUDE5"; }; Texture { ID = "STEPLAD1"; }; Texture { ID = "STEPTOP"; }; Texture { ID = "SW1GARG"; }; Texture { ID = "SW1LION"; }; Texture { ID = "SW1SATYR"; }; Texture { ID = "SW1VINE"; }; Texture { ID = "SW1WOOD"; }; Texture { ID = "SW2GARG"; }; Texture { ID = "SW2LION"; }; Texture { ID = "SW2SATYR"; }; Texture { ID = "SW2VINE"; }; Texture { ID = "SW2WOOD"; }; Texture { ID = "WOOD1"; }; Texture { ID = "WOOD3"; }; Texture { ID = "WOOD4"; }; Texture { ID = "WOOD10"; }; Texture { ID = "WOOD12"; }; Texture { ID = "WOOD6"; }; Texture { ID = "WOOD7"; }; Texture { ID = "WOOD8"; }; Texture { ID = "WOOD9"; }; Texture { ID = "WOODGARG"; }; Texture { ID = "WOODSKUL"; }; Texture { ID = "AASHITTY"; }; Texture { ID = "BRWINDOW"; }; Texture { ID = "MIDSPACE"; }; Texture { ID = "PANBORD1"; }; Texture { ID = "PANBORD2"; }; Texture { ID = "PANCASE1"; }; Texture { ID = "PANCASE2"; }; Texture { ID = "PANEL1"; }; Texture { ID = "PANEL2"; }; Texture { ID = "PANEL3"; }; Texture { ID = "PANEL4"; }; Texture { ID = "PANEL5"; }; Texture { ID = "SP_DUDE7"; }; Texture { ID = "SP_DUDE8"; }; Texture { ID = "STUCCO"; }; Texture { ID = "STUCCO1"; }; Texture { ID = "STUCCO2"; }; Texture { ID = "STUCCO3"; }; Texture { ID = "SW1PANEL"; }; Texture { ID = "SW2PANEL"; }; Texture { ID = "WOODVERT"; }; Texture { ID = "ZZWOLF13"; }; Texture { ID = "ZZWOLF5"; }; } Texture Environment { ID = "Cloth"; Texture { ID = "SW1DIRT"; }; Texture { ID = "SW2DIRT"; }; Texture { ID = "ASHWALL"; }; Texture { ID = "BROVINE"; }; Texture { ID = "BROVINE2"; }; Texture { ID = "COMPBLUE"; }; Texture { ID = "MIDBRN1"; }; Texture { ID = "MIDGRATE"; }; Texture { ID = "MIDVINE1"; }; Texture { ID = "MIDVINE2"; }; Texture { ID = "NUKEPOIS"; }; Texture { ID = "SKIN2"; }; Texture { ID = "SKINBORD"; }; Texture { ID = "SKINEDGE"; }; Texture { ID = "SKINFACE"; }; Texture { ID = "SKINSCAB"; }; Texture { ID = "SKSNAKE1"; }; Texture { ID = "SKSNAKE2"; }; Texture { ID = "SP_FACE1"; }; Texture { ID = "SP_FACE2"; }; Texture { ID = "SW1BLUE"; }; Texture { ID = "SW1SKIN"; }; Texture { ID = "SW2BLUE"; }; Texture { ID = "SW2SKIN"; }; Texture { ID = "BFALL1"; }; Texture { ID = "BFALL2"; }; Texture { ID = "BFALL3"; }; Texture { ID = "BFALL4"; }; Texture { ID = "DBRAIN1"; }; Texture { ID = "DBRAIN2"; }; Texture { ID = "DBRAIN3"; }; Texture { ID = "DBRAIN4"; }; Texture { ID = "MIDBARS1"; }; Texture { ID = "MIDBARS3"; }; Texture { ID = "PANBLACK"; }; Texture { ID = "PANBLUE"; }; Texture { ID = "PANBOOK"; }; Texture { ID = "PANRED"; }; Texture { ID = "SFALL1"; }; Texture { ID = "SFALL2"; }; Texture { ID = "SFALL3"; }; Texture { ID = "SFALL4"; }; Texture { ID = "SK_LEFT"; }; Texture { ID = "SK_RIGHT"; }; Texture { ID = "SLOPPY1"; }; Texture { ID = "SLOPPY2"; }; Texture { ID = "ZZWOLF12"; }; Texture { ID = "ZZWOLF3"; }; Texture { ID = "ZZWOLF4"; }; Texture { ID = "ZZWOLF6"; }; Texture { ID = "ZZWOLF7"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/d2_ogg_Audio.ded0000644000175000017500000010330111357170242023707 0ustar keeskees# jDoom 1.12.1: Audio # Need help with DED syntax? See DEDDoc.txt. Header { Version = 5; Sfx prefix = "sfx_"; Mus prefix = "mus_"; } Flag { ID = "sf_shift"; Value = 0x1; } Flag { ID = "sf_shift2"; Value = 0x2; } Flag { ID = "sf_exclude"; Value = 0x4; } Flag { ID = "sf_nodist"; Value = 0x8; } Flag { ID = "sf_repeat"; Value = 0x10; } Music { ID = "None"; } Music { ID = "inter"; Lump = "D_INTER"; Ext = "music\de2m3.ogg"; } Music { ID = "intro"; Lump = "D_INTRO"; Ext = "music\dintro.ogg"; } Music { ID = "bunny"; Lump = "D_BUNNY"; Ext = "music\dbunny.ogg"; } Music { ID = "victor"; Lump = "D_VICTOR"; Ext = "music\dvictor.ogg"; } Music { ID = "introa"; Lump = "D_INTROA"; Ext = "music\dintroa.ogg"; } Music { ID = "runnin"; Lump = "D_RUNNIN"; Ext = "music\d2runnin.ogg"; } Music { ID = "stalks"; Lump = "D_STALKS"; Ext = "music\d2stalks.ogg"; } Music { ID = "countd"; Lump = "D_COUNTD"; Ext = "music\d2countd.ogg"; } Music { ID = "betwee"; Lump = "D_BETWEE"; Ext = "music\d2betwee.ogg"; } Music { ID = "doom"; Lump = "D_DOOM"; Ext = "music\d2doom.ogg"; } Music { ID = "the_da"; Lump = "D_THE_DA"; Ext = "music\d2the_da.ogg"; } Music { ID = "shawn"; Lump = "D_SHAWN"; Ext = "music\d2shawn.ogg"; } Music { ID = "ddtblu"; Lump = "D_DDTBLU"; Ext = "music\d2ddtblu.ogg"; } Music { ID = "in_cit"; Lump = "D_IN_CIT"; Ext = "music\d2in_cit.ogg"; } Music { ID = "dead"; Lump = "D_DEAD"; Ext = "music\d2dead.ogg"; } Music { ID = "stlks2"; Lump = "D_STLKS2"; Ext = "music\d2stalks.ogg"; } Music { ID = "theda2"; Lump = "D_THEDA2"; Ext = "music\d2the_da.ogg"; } Music { ID = "doom2"; Lump = "D_DOOM2"; Ext = "music\d2doom.ogg"; } Music { ID = "ddtbl2"; Lump = "D_DDTBL2"; Ext = "music\d2ddtblu.ogg"; } Music { ID = "runni2"; Lump = "D_RUNNI2"; Ext = "music\d2runnin.ogg"; } Music { ID = "dead2"; Lump = "D_DEAD2"; Ext = "music\d2dead.ogg"; } Music { ID = "stlks3"; Lump = "D_STLKS3"; Ext = "music\d2stalks.ogg"; } Music { ID = "romero"; Lump = "D_ROMERO"; Ext = "music\d2romero.ogg"; } Music { ID = "shawn2"; Lump = "D_SHAWN2"; Ext = "music\d2shawn.ogg"; } Music { ID = "messag"; Lump = "D_MESSAG"; Ext = "music\d2messag.ogg"; } Music { ID = "count2"; Lump = "D_COUNT2"; Ext = "music\d2countd.ogg"; } Music { ID = "ddtbl3"; Lump = "D_DDTBL3"; Ext = "music\d2ddtblu.ogg"; } Music { ID = "ampie"; Lump = "D_AMPIE"; Ext = "music\d2ampie.ogg"; } Music { ID = "theda3"; Lump = "D_THEDA3"; Ext = "music\d2the_da.ogg"; } Music { ID = "adrian"; Lump = "D_ADRIAN"; Ext = "music\d2adrian.ogg"; } Music { ID = "messg2"; Lump = "D_MESSG2"; Ext = "music\d2messag.ogg"; } Music { ID = "romer2"; Lump = "D_ROMER2"; Ext = "music\d2romero.ogg"; } Music { ID = "tense"; Lump = "D_TENSE"; Ext = "music\d2tense.ogg"; } Music { ID = "shawn3"; Lump = "D_SHAWN3"; Ext = "music\d2shawn.ogg"; } Music { ID = "openin"; Lump = "D_OPENIN"; Ext = "music\d2openin.ogg"; } Music { ID = "evil"; Lump = "D_EVIL"; Ext = "music\d2evil.ogg"; } Music { ID = "ultima"; Lump = "D_ULTIMA"; Ext = "music\d2ultima.ogg"; } Music { ID = "read_m"; Lump = "D_READ_M"; Ext = "music\d2read_m.ogg"; } Music { ID = "dm2ttl"; Lump = "D_DM2TTL"; Ext = "music\d2dm2ttl.ogg"; } Music { ID = "dm2int"; Lump = "D_DM2INT"; Ext = "music\d2dm2int.ogg"; } Sound { ID = "None"; Link pitch = -1; Link volume = -1; Max channels = -1; } Sound { ID = "pistol"; Flags = "sf_shift2"; Lump = "DSPISTOL"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "shotgn"; Flags = "sf_shift2"; Lump = "DSSHOTGN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = 4; } Sound { ID = "sgcock"; Flags = "sf_shift2"; Lump = "DSSGCOCK"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dshtgn"; Flags = "sf_shift2"; Lump = "DSDSHTGN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbopn"; Flags = "sf_shift2"; Lump = "DSDBOPN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbcls"; Flags = "sf_shift2"; Lump = "DSDBCLS"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbload"; Flags = "sf_shift2"; Lump = "DSDBLOAD"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "plasma"; Flags = "sf_shift2"; Lump = "DSPLASMA"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = 4; } Sound { ID = "bfg"; Flags = "sf_shift2"; Lump = "DSBFG"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "sawup"; Flags = "sf_shift"; Lump = "DSSAWUP"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "sawidl"; Flags = "sf_shift"; Lump = "DSSAWIDL"; Link pitch = -1; Link volume = -1; Priority = 118; Max channels = -1; Group = 1; } Sound { ID = "sawful"; Flags = "sf_shift"; Lump = "DSSAWFUL"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "sawhit"; Flags = "sf_shift"; Lump = "DSSAWHIT"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "rlaunc"; Flags = "sf_shift2"; Lump = "DSRLAUNC"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "rxplod"; Flags = "sf_shift2"; Lump = "DSRXPLOD"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "firsht"; Flags = "sf_shift2"; Lump = "DSFIRSHT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "firxpl"; Flags = "sf_shift2"; Lump = "DSFIRXPL"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = 4; } Sound { ID = "pstart"; Flags = "sf_shift2"; Lump = "DSPSTART"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "pstop"; Flags = "sf_shift2"; Lump = "DSPSTOP"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "doropn"; Flags = "sf_shift2"; Lump = "DSDOROPN"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "dorcls"; Flags = "sf_shift2"; Lump = "DSDORCLS"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "stnmov"; Flags = "sf_shift2"; Lump = "DSSTNMOV"; Link pitch = -1; Link volume = -1; Priority = 119; Max channels = -1; } Sound { ID = "swtchn"; Flags = "sf_shift2"; Lump = "DSSWTCHN"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "swtchx"; Flags = "sf_shift2"; Lump = "DSSWTCHX"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "plpain"; Flags = "sf_shift2"; Lump = "DSPLPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "dmpain"; Flags = "sf_shift2"; Lump = "DSDMPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "popain"; Flags = "sf_shift2"; Lump = "DSPOPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "vipain"; Flags = "sf_shift2"; Lump = "DSVIPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "mnpain"; Flags = "sf_shift2"; Lump = "DSMNPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "pepain"; Flags = "sf_shift2"; Lump = "DSPEPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "slop"; Flags = "sf_shift2"; Lump = "DSSLOP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "itemup"; Lump = "DSITEMUP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = 1; } Sound { ID = "wpnup"; Flags = "sf_shift2"; Lump = "DSWPNUP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = 1; } Sound { ID = "oof"; Flags = "sf_shift2"; Lump = "DSOOF"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "telept"; Flags = "sf_shift2"; Lump = "DSTELEPT"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "posit1"; Flags = "sf_shift2"; Lump = "DSPOSIT1"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "posit2"; Flags = "sf_shift2"; Lump = "DSPOSIT2"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "posit3"; Flags = "sf_shift2"; Lump = "DSPOSIT3"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "bgsit1"; Flags = "sf_shift2"; Lump = "DSBGSIT1"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "bgsit2"; Flags = "sf_shift2"; Lump = "DSBGSIT2"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "sgtsit"; Flags = "sf_shift2"; Lump = "DSSGTSIT"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "cacsit"; Flags = "sf_shift2"; Lump = "DSCACSIT"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "brssit"; Flags = "sf_shift2"; Lump = "DSBRSSIT"; Link pitch = -1; Link volume = -1; Priority = 94; Max channels = 1; } Sound { ID = "cybsit"; Flags = "sf_shift2"; Lump = "DSCYBSIT"; Link pitch = -1; Link volume = -1; Priority = 92; Max channels = 1; } Sound { ID = "bspsit"; Flags = "sf_shift2"; Lump = "DSBSPSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "kntsit"; Flags = "sf_shift2"; Lump = "DSKNTSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "vilsit"; Flags = "sf_shift2"; Lump = "DSVILSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "mansit"; Flags = "sf_shift2"; Lump = "DSMANSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "pesit"; Flags = "sf_shift2"; Lump = "DSPESIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "sklatk"; Flags = "sf_shift2"; Lump = "DSSKLATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sgtatk"; Flags = "sf_shift2"; Lump = "DSSGTATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skepch"; Flags = "sf_shift2"; Lump = "DSSKEPCH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "vilatk"; Flags = "sf_shift2"; Lump = "DSVILATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "claw"; Flags = "sf_shift2"; Lump = "DSCLAW"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeswg"; Flags = "sf_shift2"; Lump = "DSSKESWG"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "pldeth"; Flags = "sf_shift2"; Lump = "DSPLDETH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "pdiehi"; Flags = "sf_shift2"; Lump = "DSPDIEHI"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "podth1"; Flags = "sf_shift2"; Lump = "DSPODTH1"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "podth2"; Flags = "sf_shift2"; Lump = "DSPODTH2"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "podth3"; Flags = "sf_shift2"; Lump = "DSPODTH3"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bgdth1"; Flags = "sf_shift2"; Lump = "DSBGDTH1"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bgdth2"; Flags = "sf_shift2"; Lump = "DSBGDTH2"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sgtdth"; Flags = "sf_shift2"; Lump = "DSSGTDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "cacdth"; Flags = "sf_shift2"; Lump = "DSCACDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skldth"; Flags = "sf_shift2"; Lump = "DSSKLDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "brsdth"; Flags = "sf_shift2"; Lump = "DSBRSDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "cybdth"; Flags = "sf_shift2"; Lump = "DSCYBDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "bspdth"; Flags = "sf_shift2"; Lump = "DSBSPDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "vildth"; Flags = "sf_shift2"; Lump = "DSVILDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "kntdth"; Flags = "sf_shift2"; Lump = "DSKNTDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "pedth"; Flags = "sf_shift2"; Lump = "DSPEDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "skedth"; Flags = "sf_shift2"; Lump = "DSSKEDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "posact"; Flags = "sf_shift2"; Lump = "DSPOSACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "bgact"; Flags = "sf_shift2"; Lump = "DSBGACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "dmact"; Flags = "sf_shift2"; Lump = "DSDMACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "bspact"; Flags = "sf_shift2"; Lump = "DSBSPACT"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "bspwlk"; Flags = "sf_shift2"; Lump = "DSBSPWLK"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "vilact"; Flags = "sf_shift2"; Lump = "DSVILACT"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "noway"; Flags = "sf_shift2"; Lump = "DSNOWAY"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "barexp"; Flags = "sf_shift2"; Lump = "DSBAREXP"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "punch"; Flags = "sf_shift2"; Lump = "DSPUNCH"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "hoof"; Flags = "sf_shift2"; Lump = "DSHOOF"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "metal"; Flags = "sf_shift2"; Lump = "DSMETAL"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "chgun"; Flags = "sf_shift2"; Lump = "DSCHGUN"; Link = "pistol"; Link pitch = 150; Priority = 64; Max channels = -1; } Sound { ID = "tink"; Lump = "DSTINK"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "bdopn"; Flags = "sf_shift2"; Lump = "DSBDOPN"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "bdcls"; Flags = "sf_shift2"; Lump = "DSBDCLS"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "itmbk"; Flags = "sf_shift2"; Lump = "DSITMBK"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "flame"; Flags = "sf_shift2"; Lump = "DSFLAME"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "flamst"; Flags = "sf_shift2"; Lump = "DSFLAMST"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "getpow"; Flags = "sf_shift2"; Lump = "DSGETPOW"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "manatk"; Flags = "sf_shift2"; Lump = "DSMANATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "mandth"; Flags = "sf_shift2"; Lump = "DSMANDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sssit"; Flags = "sf_shift2"; Lump = "DSSSSIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "ssdth"; Flags = "sf_shift2"; Lump = "DSSSDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeact"; Flags = "sf_shift2"; Lump = "DSSKEACT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skesit"; Flags = "sf_shift2"; Lump = "DSSKESIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeatk"; Flags = "sf_shift2"; Lump = "DSSKEATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "radio"; Lump = "DSRADIO"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Texture Environment { ID = "Metal"; Texture { ID = "BIGDOOR1"; }; Texture { ID = "BIGDOOR2"; }; Texture { ID = "BIGDOOR4"; }; Texture { ID = "COMP2"; }; Texture { ID = "COMPSPAN"; }; Texture { ID = "COMPSTA1"; }; Texture { ID = "COMPSTA2"; }; Texture { ID = "COMPTALL"; }; Texture { ID = "COMPUTE1"; }; Texture { ID = "COMPUTE2"; }; Texture { ID = "DOOR1"; }; Texture { ID = "DOOR3"; }; Texture { ID = "DOORBLU"; }; Texture { ID = "DOORRED"; }; Texture { ID = "DOORSTOP"; }; Texture { ID = "DOORYEL"; }; Texture { ID = "EXITDOOR"; }; Texture { ID = "EXITSIGN"; }; Texture { ID = "LITE3"; }; Texture { ID = "LITE4"; }; Texture { ID = "LITE5"; }; Texture { ID = "LITEBLU1"; }; Texture { ID = "LITEBLU2"; }; Texture { ID = "LITEBLU3"; }; Texture { ID = "LITEBLU4"; }; Texture { ID = "METAL1"; }; Texture { ID = "PLANET1"; }; Texture { ID = "PLAT1"; }; Texture { ID = "REDWALL1"; }; Texture { ID = "SHAWN2"; }; Texture { ID = "STARG1"; }; Texture { ID = "STARG3"; }; Texture { ID = "STARGR1"; }; Texture { ID = "STARTAN1"; }; Texture { ID = "STARTAN2"; }; Texture { ID = "STARTAN3"; }; Texture { ID = "STEP4"; }; Texture { ID = "SUPPORT2"; }; Texture { ID = "SW1COMM"; }; Texture { ID = "SW1COMP"; }; Texture { ID = "SW1METAL"; }; Texture { ID = "SW1STARG"; }; Texture { ID = "SW1STRTN"; }; Texture { ID = "SW2COMM"; }; Texture { ID = "SW2COMP"; }; Texture { ID = "SW2METAL"; }; Texture { ID = "SW2STARG"; }; Texture { ID = "SW2STRTN"; }; Texture { ID = "BIGDOOR3"; }; Texture { ID = "COMPWERD"; }; Texture { ID = "DOORBLU2"; }; Texture { ID = "DOORRED2"; }; Texture { ID = "DOORYEL2"; }; Texture { ID = "GRAY2"; }; Texture { ID = "GRAYPOIS"; }; Texture { ID = "ICKDOOR1"; }; Texture { ID = "LITEMET"; }; Texture { ID = "LITERED"; }; Texture { ID = "LITESTON"; }; Texture { ID = "METAL"; }; Texture { ID = "SHAWN1"; }; Texture { ID = "SHAWN3"; }; Texture { ID = "STARBR2"; }; Texture { ID = "STARG2"; }; Texture { ID = "STARGR2"; }; Texture { ID = "SUPPORT3"; }; Texture { ID = "BRONZE1"; }; Texture { ID = "BRONZE2"; }; Texture { ID = "BRONZE3"; }; Texture { ID = "BRONZE4"; }; Texture { ID = "METAL2"; }; Texture { ID = "METAL3"; }; Texture { ID = "METAL4"; }; Texture { ID = "METAL5"; }; Texture { ID = "METAL6"; }; Texture { ID = "METAL7"; }; Texture { ID = "MODWALL3"; }; Texture { ID = "MODWALL4"; }; Texture { ID = "PIPES"; }; Texture { ID = "SILVER1"; }; Texture { ID = "SILVER2"; }; Texture { ID = "SILVER3"; }; Texture { ID = "SPACEW3"; }; Texture { ID = "SPACEW4"; }; Texture { ID = "SPCDOOR1"; }; Texture { ID = "SPCDOOR2"; }; Texture { ID = "SPCDOOR3"; }; Texture { ID = "SW1MET2"; }; Texture { ID = "SW2MET2"; }; Texture { ID = "SW1TEK"; }; Texture { ID = "SW2TEK"; }; Texture { ID = "SW1WDMET"; }; Texture { ID = "SW2WDMET"; }; Texture { ID = "TEKBRON1"; }; Texture { ID = "TEKBRON2"; }; Texture { ID = "TEKGREN1"; }; Texture { ID = "TEKGREN2"; }; Texture { ID = "TEKGREN3"; }; Texture { ID = "TEKGREN4"; }; Texture { ID = "TEKGREN5"; }; Texture { ID = "WOODMET1"; }; Texture { ID = "WOODMET2"; }; Texture { ID = "WOODMET3"; }; Texture { ID = "WOODMET4"; }; Texture { ID = "ZDOORB1"; }; Texture { ID = "ZDOORF1"; }; Texture { ID = "ZELDOOR"; }; Texture { ID = "ZZWOLF10"; }; Texture { ID = "ZZZFACE6"; }; Texture { ID = "ZZZFACE7"; }; Texture { ID = "ZZZFACE8"; }; Texture { ID = "ZZZFACE9"; }; } Texture Environment { ID = "Rock"; Texture { ID = "AASTINKY"; }; Texture { ID = "BRNPOIS"; }; Texture { ID = "BRNPOIS2"; }; Texture { ID = "BROWN1"; }; Texture { ID = "BROWN144"; }; Texture { ID = "BROWN96"; }; Texture { ID = "BROWNGRN"; }; Texture { ID = "BROWNHUG"; }; Texture { ID = "BROWNPIP"; }; Texture { ID = "COMPUTE3"; }; Texture { ID = "GRAY4"; }; Texture { ID = "GRAY5"; }; Texture { ID = "GRAY7"; }; Texture { ID = "GRAYTALL"; }; Texture { ID = "LITE2"; }; Texture { ID = "NUKE24"; }; Texture { ID = "NUKEDGE1"; }; Texture { ID = "STEP6"; }; Texture { ID = "STONE"; }; Texture { ID = "STONE2"; }; Texture { ID = "STONE3"; }; Texture { ID = "STONE4"; }; Texture { ID = "STONE5"; }; Texture { ID = "STONE6"; }; Texture { ID = "STONE7"; }; Texture { ID = "STONPOIS"; }; Texture { ID = "SW1BRCOM"; }; Texture { ID = "SW1BRN1"; }; Texture { ID = "SW1BRN2"; }; Texture { ID = "SW1BRGRN"; }; Texture { ID = "SW1BROWN"; }; Texture { ID = "SW1EXIT"; }; Texture { ID = "SW1GRAY"; }; Texture { ID = "SW1GRAY1"; }; Texture { ID = "SW1STON1"; }; Texture { ID = "SW1STON2"; }; Texture { ID = "SW1STONE"; }; Texture { ID = "SW2BRCOM"; }; Texture { ID = "SW2BRN1"; }; Texture { ID = "SW2BRN2"; }; Texture { ID = "SW2BRGRN"; }; Texture { ID = "SW2BROWN"; }; Texture { ID = "SW2EXIT"; }; Texture { ID = "SW2GRAY"; }; Texture { ID = "SW2GRAY1"; }; Texture { ID = "SW2STON1"; }; Texture { ID = "SW2STON2"; }; Texture { ID = "SW2STONE"; }; Texture { ID = "BIGDOOR5"; }; Texture { ID = "BROWNWEL"; }; Texture { ID = "CEMENT1"; }; Texture { ID = "CEMENT2"; }; Texture { ID = "CEMENT3"; }; Texture { ID = "CEMENT4"; }; Texture { ID = "CEMENT5"; }; Texture { ID = "CEMENT6"; }; Texture { ID = "CEMENT7"; }; Texture { ID = "CEMENT8"; }; Texture { ID = "CEMENT9"; }; Texture { ID = "CEMPOIS"; }; Texture { ID = "DOORHI"; }; Texture { ID = "EXITSTON"; }; Texture { ID = "FIREMAG1"; }; Texture { ID = "FIREMAG2"; }; Texture { ID = "FIREMAG3"; }; Texture { ID = "FIREWALL"; }; Texture { ID = "FIREWALA"; }; Texture { ID = "FIREWALB"; }; Texture { ID = "GRAY1"; }; Texture { ID = "GRAYBIG"; }; Texture { ID = "GRAYDANG"; }; Texture { ID = "GSTFONT1"; }; Texture { ID = "GSTFONT2"; }; Texture { ID = "GSTFONT3"; }; Texture { ID = "GSTGARG"; }; Texture { ID = "GSTLION"; }; Texture { ID = "GSTONE1"; }; Texture { ID = "GSTONE2"; }; Texture { ID = "GSTSATYR"; }; Texture { ID = "ICKWALL1"; }; Texture { ID = "ICKWALL2"; }; Texture { ID = "ICKWALL3"; }; Texture { ID = "ICKWALL4"; }; Texture { ID = "ICKWALL5"; }; Texture { ID = "ICKWALL6"; }; Texture { ID = "ICKWALL7"; }; Texture { ID = "LITE96"; }; Texture { ID = "MARBFAC2"; }; Texture { ID = "MARBFAC3"; }; Texture { ID = "MARBFAC4"; }; Texture { ID = "MARBFACE"; }; Texture { ID = "MARBLE1"; }; Texture { ID = "MARBLE2"; }; Texture { ID = "MARBLE3"; }; Texture { ID = "MARBLOD1"; }; Texture { ID = "REDWALL"; }; Texture { ID = "ROCKRED1"; }; Texture { ID = "ROCKRED2"; }; Texture { ID = "ROCKRED3"; }; Texture { ID = "SP_DUDE1"; }; Texture { ID = "SP_DUDE2"; }; Texture { ID = "SP_DUDE6"; }; Texture { ID = "SP_HOT1"; }; Texture { ID = "SP_ROCK1"; }; Texture { ID = "SP_ROCK2"; }; Texture { ID = "STONGARG"; }; Texture { ID = "SW1CMT"; }; Texture { ID = "SW1GSTON"; }; Texture { ID = "SW1HOT"; }; Texture { ID = "SW2CMT"; }; Texture { ID = "SW2GSTON"; }; Texture { ID = "SW2HOT"; }; Texture { ID = "WOOD5"; }; Texture { ID = "ASHWALL2"; }; Texture { ID = "ASHWALL3"; }; Texture { ID = "ASHWALL4"; }; Texture { ID = "ASHWALL6"; }; Texture { ID = "ASHWALL7"; }; Texture { ID = "BIGBRIK1"; }; Texture { ID = "BIGBRIK2"; }; Texture { ID = "BIGBRIK3"; }; Texture { ID = "BLAKWAL1"; }; Texture { ID = "BLAKWAL2"; }; Texture { ID = "BRICK1"; }; Texture { ID = "BRICK2"; }; Texture { ID = "BRICK3"; }; Texture { ID = "BRICK4"; }; Texture { ID = "BRICK5"; }; Texture { ID = "BRICK6"; }; Texture { ID = "BRICK7"; }; Texture { ID = "BRICK8"; }; Texture { ID = "BRICK9"; }; Texture { ID = "BRICK10"; }; Texture { ID = "BRICK11"; }; Texture { ID = "BRICK12"; }; Texture { ID = "BRICKLIT"; }; Texture { ID = "BSTONE1"; }; Texture { ID = "BSTONE2"; }; Texture { ID = "BSTONE3"; }; Texture { ID = "CRACKLE2"; }; Texture { ID = "CRACKLE4"; }; Texture { ID = "MARBGRAY"; }; Texture { ID = "MIDBRONZ"; }; Texture { ID = "MODWALL1"; }; Texture { ID = "MODWALL2"; }; Texture { ID = "PANEL6"; }; Texture { ID = "PANEL7"; }; Texture { ID = "PANEL8"; }; Texture { ID = "PANEL9"; }; Texture { ID = "PIPEWAL1"; }; Texture { ID = "PIPEWAL2"; }; Texture { ID = "ROCK1"; }; Texture { ID = "ROCK2"; }; Texture { ID = "ROCK3"; }; Texture { ID = "ROCK4"; }; Texture { ID = "ROCK5"; }; Texture { ID = "SPACEW2"; }; Texture { ID = "SPCDOOR4"; }; Texture { ID = "SW1BRIK"; }; Texture { ID = "SW2BRIK"; }; Texture { ID = "SW1MOD1"; }; Texture { ID = "SW2MOD1"; }; Texture { ID = "SW1ROCK"; }; Texture { ID = "SW2ROCK"; }; Texture { ID = "SW1SKULL"; }; Texture { ID = "SW2SKULL"; }; Texture { ID = "SW1STON6"; }; Texture { ID = "SW2STON6"; }; Texture { ID = "SW1ZIM"; }; Texture { ID = "SW2ZIM"; }; Texture { ID = "TANROCK2"; }; Texture { ID = "TANROCK3"; }; Texture { ID = "TANROCK4"; }; Texture { ID = "TANROCK5"; }; Texture { ID = "TANROCK7"; }; Texture { ID = "TANROCK8"; }; Texture { ID = "TEKLITE"; }; Texture { ID = "TEKLITE2"; }; Texture { ID = "ZIMMER1"; }; Texture { ID = "ZIMMER2"; }; Texture { ID = "ZIMMER3"; }; Texture { ID = "ZIMMER4"; }; Texture { ID = "ZIMMER5"; }; Texture { ID = "ZIMMER7"; }; Texture { ID = "ZIMMER8"; }; Texture { ID = "ZZWOLF1"; }; Texture { ID = "ZZWOLF11"; }; Texture { ID = "ZZWOLF2"; }; Texture { ID = "ZZWOLF9"; }; Texture { ID = "ZZZFACE1"; }; Texture { ID = "ZZZFACE2"; }; Texture { ID = "ZZZFACE3"; }; Texture { ID = "ZZZFACE4"; }; Texture { ID = "ZZZFACE5"; }; } Texture Environment { ID = "Wood"; Texture { ID = "BRNBIGC"; }; Texture { ID = "BRNBIGL"; }; Texture { ID = "BRNBIGR"; }; Texture { ID = "BRNSMAL1"; }; Texture { ID = "BRNSMAL2"; }; Texture { ID = "BRNSMALC"; }; Texture { ID = "BRNSMALL"; }; Texture { ID = "BRNSMALR"; }; Texture { ID = "COMPTILE"; }; Texture { ID = "DOORTRAK"; }; Texture { ID = "NUKESLAD"; }; Texture { ID = "PIPE2"; }; Texture { ID = "SLADPOIS"; }; Texture { ID = "SLADRIP1"; }; Texture { ID = "SLADRIP2"; }; Texture { ID = "SLADRIP3"; }; Texture { ID = "SLADWALL"; }; Texture { ID = "STEP1"; }; Texture { ID = "STEP2"; }; Texture { ID = "STEP3"; }; Texture { ID = "STEP5"; }; Texture { ID = "SW1PIPE"; }; Texture { ID = "SW1SLAD"; }; Texture { ID = "SW2PIPE"; }; Texture { ID = "SW2SLAD"; }; Texture { ID = "TEKWALL1"; }; Texture { ID = "TEKWALL2"; }; Texture { ID = "TEKWALL3"; }; Texture { ID = "TEKWALL4"; }; Texture { ID = "TEKWALL5"; }; Texture { ID = "TEKWALL6"; }; Texture { ID = "BIGDOOR6"; }; Texture { ID = "BIGDOOR7"; }; Texture { ID = "BLODGR1"; }; Texture { ID = "BLODGR2"; }; Texture { ID = "BLODGR3"; }; Texture { ID = "BLODGR4"; }; Texture { ID = "BLODRIP1"; }; Texture { ID = "BLODRIP2"; }; Texture { ID = "BLODRIP3"; }; Texture { ID = "BLODRIP4"; }; Texture { ID = "COMPOHSO"; }; Texture { ID = "CRATE1"; }; Texture { ID = "CRATE2"; }; Texture { ID = "CRATELIT"; }; Texture { ID = "CRATINY"; }; Texture { ID = "CRATWIDE"; }; Texture { ID = "FIREBLU1"; }; Texture { ID = "FIREBLU2"; }; Texture { ID = "FIRELAVA"; }; Texture { ID = "FIRELAV2"; }; Texture { ID = "FIRELAV3"; }; Texture { ID = "GRAYVINE"; }; Texture { ID = "GSTVINE1"; }; Texture { ID = "GSTVINE2"; }; Texture { ID = "PIPE1"; }; Texture { ID = "PIPE4"; }; Texture { ID = "PIPE6"; }; Texture { ID = "SKINCUT"; }; Texture { ID = "SKINLOW"; }; Texture { ID = "SKINMET1"; }; Texture { ID = "SKINMET2"; }; Texture { ID = "SKINSYMB"; }; Texture { ID = "SKINTEK1"; }; Texture { ID = "SKINTEK2"; }; Texture { ID = "SKSPINE1"; }; Texture { ID = "SKSPINE2"; }; Texture { ID = "SKULWAL3"; }; Texture { ID = "SKULWALL"; }; Texture { ID = "SLADSKUL"; }; Texture { ID = "SP_DUDE3"; }; Texture { ID = "SP_DUDE4"; }; Texture { ID = "SP_DUDE5"; }; Texture { ID = "STEPLAD1"; }; Texture { ID = "STEPTOP"; }; Texture { ID = "SW1GARG"; }; Texture { ID = "SW1LION"; }; Texture { ID = "SW1SATYR"; }; Texture { ID = "SW1VINE"; }; Texture { ID = "SW1WOOD"; }; Texture { ID = "SW2GARG"; }; Texture { ID = "SW2LION"; }; Texture { ID = "SW2SATYR"; }; Texture { ID = "SW2VINE"; }; Texture { ID = "SW2WOOD"; }; Texture { ID = "WOOD1"; }; Texture { ID = "WOOD3"; }; Texture { ID = "WOOD4"; }; Texture { ID = "WOOD10"; }; Texture { ID = "WOOD12"; }; Texture { ID = "WOOD6"; }; Texture { ID = "WOOD7"; }; Texture { ID = "WOOD8"; }; Texture { ID = "WOOD9"; }; Texture { ID = "WOODGARG"; }; Texture { ID = "WOODSKUL"; }; Texture { ID = "AASHITTY"; }; Texture { ID = "BRWINDOW"; }; Texture { ID = "MIDSPACE"; }; Texture { ID = "PANBORD1"; }; Texture { ID = "PANBORD2"; }; Texture { ID = "PANCASE1"; }; Texture { ID = "PANCASE2"; }; Texture { ID = "PANEL1"; }; Texture { ID = "PANEL2"; }; Texture { ID = "PANEL3"; }; Texture { ID = "PANEL4"; }; Texture { ID = "PANEL5"; }; Texture { ID = "SP_DUDE7"; }; Texture { ID = "SP_DUDE8"; }; Texture { ID = "STUCCO"; }; Texture { ID = "STUCCO1"; }; Texture { ID = "STUCCO2"; }; Texture { ID = "STUCCO3"; }; Texture { ID = "SW1PANEL"; }; Texture { ID = "SW2PANEL"; }; Texture { ID = "WOODVERT"; }; Texture { ID = "ZZWOLF13"; }; Texture { ID = "ZZWOLF5"; }; } Texture Environment { ID = "Cloth"; Texture { ID = "SW1DIRT"; }; Texture { ID = "SW2DIRT"; }; Texture { ID = "ASHWALL"; }; Texture { ID = "BROVINE"; }; Texture { ID = "BROVINE2"; }; Texture { ID = "COMPBLUE"; }; Texture { ID = "MIDBRN1"; }; Texture { ID = "MIDGRATE"; }; Texture { ID = "MIDVINE1"; }; Texture { ID = "MIDVINE2"; }; Texture { ID = "NUKEPOIS"; }; Texture { ID = "SKIN2"; }; Texture { ID = "SKINBORD"; }; Texture { ID = "SKINEDGE"; }; Texture { ID = "SKINFACE"; }; Texture { ID = "SKINSCAB"; }; Texture { ID = "SKSNAKE1"; }; Texture { ID = "SKSNAKE2"; }; Texture { ID = "SP_FACE1"; }; Texture { ID = "SP_FACE2"; }; Texture { ID = "SW1BLUE"; }; Texture { ID = "SW1SKIN"; }; Texture { ID = "SW2BLUE"; }; Texture { ID = "SW2SKIN"; }; Texture { ID = "BFALL1"; }; Texture { ID = "BFALL2"; }; Texture { ID = "BFALL3"; }; Texture { ID = "BFALL4"; }; Texture { ID = "DBRAIN1"; }; Texture { ID = "DBRAIN2"; }; Texture { ID = "DBRAIN3"; }; Texture { ID = "DBRAIN4"; }; Texture { ID = "MIDBARS1"; }; Texture { ID = "MIDBARS3"; }; Texture { ID = "PANBLACK"; }; Texture { ID = "PANBLUE"; }; Texture { ID = "PANBOOK"; }; Texture { ID = "PANRED"; }; Texture { ID = "SFALL1"; }; Texture { ID = "SFALL2"; }; Texture { ID = "SFALL3"; }; Texture { ID = "SFALL4"; }; Texture { ID = "SK_LEFT"; }; Texture { ID = "SK_RIGHT"; }; Texture { ID = "SLOPPY1"; }; Texture { ID = "SLOPPY2"; }; Texture { ID = "ZZWOLF12"; }; Texture { ID = "ZZWOLF3"; }; Texture { ID = "ZZWOLF4"; }; Texture { ID = "ZZWOLF6"; }; Texture { ID = "ZZWOLF7"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/particles.ded0000644000175000017500000002426511357170242023426 0ustar keeskees# jDoom64: Particle Effects Header { Version = 6; } SkipIf -nodefaultfx; ######=====---- PLAYER WEAPONS ----=====###### # Rocket smoke trail. Generator { State = "ROCKET"; Flags = spawn; Center { -16 0 8 }; Speed = .8; Speed rnd = 1; Spawn age = -1; Max age = 1200; Particles = 150; Spawn rate = 1.4; Spawn Rnd = 0.4; Vector { 0 0 0 }; Vector rnd = 1; Stage { Type = point; Tics = 2; Rnd = .2; Radius = 5; Color { .55 .55 .4 .6 }; }; Stage { Type = point; Tics = 15; Radius = 6; Color { .4 .4 .4 .3 }; Resistance = 0.01; }; Stage { Type = point; Tics = 130; Radius = 22; Bounce = 0; Resistance = 0.1; Gravity = 0; Color { 0.3 0.3 0.36 0.15 }; }; Stage { Type = point; Radius = 30; Color { 0.2 0.2 0.22 0 }; }; } # Bullet ricochet. Happens pretty rarely. Generator { State = "PUFF1"; Flags = blend; Speed = 20; Speed rnd = 0.1; Spawn age = 2; Max age = 50; Particles = 20; Spawn rate = .65; Spawn rnd = 1; Vector rnd = 1; Stage { Type = line; Flags = bright; Tics = 20; Rnd = 0.5; Radius = 1; Color { 1 1 .9 1 }; Bounce = 0.5; Resistance = 0.01; Gravity = 0.04; }; Stage { Type = line; Flags = bright; Tics = 10; Rnd = 0.5; Radius = 1; Color { 1 .9 .3 .5 }; Bounce = 0.5; Resistance = 0.01; Gravity = 0.04; }; Stage { Type = line; Flags = bright; Radius = 1; Resistance = 0.01; Gravity = 0.02; }; } # Plasma sparks (blue). Generator { State = "PLASEXP"; Flags = blend; Speed = 3; Speed rnd = 0.8; Spawn age = 3; Spawn radius = 20; Max age = 50; Particles = 30; Spawn rate = 10; Spawn rnd = 1; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 5; Rnd = 0.5; Radius = 15; Color { 1 1 1 .7 }; Resistance = 0.3; }; Stage { Type = point; Flags = bright; Tics = 20; Rnd = 0.5; Radius = 13; Color { .45 .5 1 .4 }; Resistance = 0.3; }; Stage { Type = point; Flags = bright; Tics = 10; Rnd = 0.5; Radius = 12; Color { .05 .15 1 .4 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Color { .2 .2 1 0 }; Radius = 10; }; } # BFG explosion effect. Generator { State = "BFGLAND"; Flags = blend; Speed = 7; Speed rnd = 0.2; Spawn radius = 10; Spawn age = 7; Max age = 70; Particles = 200; Spawn rate = 25; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 30; Rnd = 0.2; Radius = 4; Bounce = 0.8; Resistance = .03; Gravity = 0.01; Color { 1 1 1 1 }; }; Stage { Type = point; Flags = bright; Radius = 3; Tics = 30; Resistance = .05; Gravity = 0.02; Color { .5 1 .5 .8 }; }; Stage { Type = point; Flags = bright; Tics = 3; Color { 0 1 0 .5 }; }; } ######=====---- MONSTERS ----=====###### # Baby Spider plasma sparks (yellow-green). Generator { State = "ARACH_PLEX"; Flags = blend; Speed = 3; Speed rnd = 0.8; Spawn age = 3; Spawn radius = 20; Max age = 50; Particles = 30; Spawn rate = 10; Spawn rnd = 1; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 5; Rnd = 0.5; Radius = 15; Color { 1 1 1 .7 }; Resistance = 0.3; }; Stage { Type = point; Flags = bright; Tics = 20; Rnd = 0.5; Radius = 13; Color { 1 .9 .5 .4 }; Resistance = 0.3; }; Stage { Type = point; Flags = bright; Tics = 10; Rnd = 0.5; Radius = 12; Color { .5 1 .2 .4 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Color { 0 .6 0 0 }; Radius = 10; }; } ######=====---- EXPLOSIONS ----=====###### # Rocket explosions. Generator { State = "EXPLODE1"; Center { 0 0 5 }; Flags = blend; Speed = 8; Speed rnd = 0.5; Spawn age = 2; Spawn radius = 15; Max age = 200; Particles = 100; Spawn rate = 14; Spawn Rnd = 0.1; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 20; Rnd = .5; Radius = 18; Color { 1 1 1 1 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 13; Rnd = .5; Radius = 17; Color { 1 .9 .5 .7 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 7; Rnd = 0.2; Radius = 10; Color { .6 .5 .2 .5 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 20; Rnd = .8; Radius = 12; Color { .4 .4 .42 .3 }; Resistance = 0.5; }; Stage { Type = point; Radius = 5; Color { .2 .2 .2 0 }; }; } # Mancubus rocket explosion. Copy Generator { State = "FATSHOTX1"; Spawn rate = 15; } # Barrel explosion. Copy Generator { State = "BEXP5"; Flags = blend | srcvel; Center { 0 0 20 }; } # Rocket sparks. Generator { State = "EXPLODE0"; Speed = 10; Speed rnd = 0.9; Spawn age = 2; Spawn radius = 3; Max age = 200; Particles = 100; Spawn rate = 30; Spawn Rnd = 0.3; Vector { 0 0 0 }; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 25; Rnd = 0.5; Radius = 2; Bounce = 0.3; Resistance = 0.02; Gravity = 0.1; Color { 1 1 1 1 }; }; Stage { Type = point; Flags = bright; Tics = 15; Rnd = 0.5; Radius = 1.5; Bounce = 0.3; Resistance = 0.03; Gravity = 0.1; Color { 1 1 .5 1 }; }; Stage { Type = point; Tics = 7; Radius = 1.25; Bounce = 0.3; Resistance = 0.1; Gravity = 0.1; Color { .7 .4 .1 1 }; }; Stage { Type = point; Tics = 7; Radius = 1; Bounce = 0.3; Resistance = 0.1; Gravity = 0.1; Radius = 1; Color { .5 .2 0 .7 }; }; Stage { Type = point; Tics = 30; Radius = 10; Resistance = 0.2; Gravity = 0.01; Color { .3 .3 .3 .3 }; }; Stage { Type = point; Tics = 30; Radius = 20; Resistance = 0.2; Gravity = 0.01; Color { .15 .15 .15 .15 }; }; Stage { Type = point; Radius = 10; }; } # Low-energy (small and red) explosion. Red fireballs. Generator { State = "TBALLX1"; Flags = blend; Center { 0 0 14 }; Speed = 5; Speed rnd = 0.6; Spawn age = 2; Spawn radius = 12; Max age = 200; Particles = 50; Spawn rate = 20; Spawn Rnd = 0.2; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 12; Rnd = .5; Radius = 15; Color { 1 .9 .5 .8 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 10; Rnd = .5; Radius = 13; Color { 1 .7 .5 .7 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 15; Rnd = 0.2; Radius = 10; Color { 1 .2 .1 .5 }; Resistance = 0.2; }; Stage { Type = point; Radius = 10; Color { .5 0 0 0 }; }; } Copy Generator { State = "RBALLX1"; } Copy Generator { State = "TRACEEXP1"; } # Skull explosion. Copy Generator { State = "SKULL_DIE3"; Center { 0 0 24 }; Flags = blend; Speed = 4; Speed rnd = 0.8; Spawn age = 2; Spawn radius = 30; Max age = 200; Particles = 100; Spawn rate = 30; Spawn rnd = 0.1; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 6; Rnd = .5; Radius = 13; Color { 1 1 1 1 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 13; Rnd = .6; Radius = 12; Color { 1 .8 .5 1 }; Resistance = 0.3; Gravity = -0.15; }; Stage { Type = point; Flags = bright; Tics = 13; Rnd = .7; Radius = 15; Color { 1 .3 .1 .7 }; Resistance = 0.2; Gravity = -0.15; }; Stage { Type = point; Flags = bright; Tics = 10; Rnd = .8; Radius = 13; Color { .5 .1 .1 .3 }; Resistance = 0.2; Gravity = -0.15; }; Stage { Type = point; Radius = 10; }; } # Pain Elemental death explosion. Copy Generator { State = "PAIN_DIE3"; } # Green blast explosion. Generator { State = "BRBALLX1"; Flags = blend; Center { 0 0 -4 }; Speed = 3; Speed rnd = 0.6; Spawn age = 2; Spawn radius = 14; Max age = 200; Particles = 50; Spawn rate = 20; Spawn Rnd = 0.2; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 12; Rnd = .5; Radius = 10; Color { .5 1 .5 .8 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 10; Rnd = .5; Radius = 8; Color { .2 1 .2 .7 }; Resistance = 0.2; }; Stage { Type = point; Flags = bright; Tics = 15; Rnd = 0.2; Radius = 6; Color { 0 1 0 .5 }; Resistance = 0.2; }; Stage { Type = point; Radius = 10; Color { 0 .5 0 0 }; }; } ######=====---- DAMAGE ----=====###### # Gibbed blood spurt. Generator { State = "POSS_XDIE2"; Flags = srcvel; Center { 0 0 30 }; Speed = 6; Speed rnd = 0.7; Spawn age = 4; Max age = 300; Particles = 200; Spawn rate = 30; Spawn Rnd = 0.1; Vector rnd = 1; Stage { Type = point; Flags = flat | stagetouch; Radius = 1.5; Color { .7 0 0 .7 }; Tics = 300; Resistance = 0.01; Gravity = 0.15; }; Stage { Type = point; Flags = flat; Radius = 16; Radius rnd = 0.8; Color { .7 0 0 .5 }; Tics = 200; Resistance = 1; }; Stage { Type = point; Radius = 9; Radius rnd = 0.8; Color { .45 0 0 0 }; }; } Copy Generator { State = "PLAY_XDIE2"; } Copy Generator { State = "SPOS_XDIE2"; } Copy Generator { State = "TROO_XDIE2"; } Copy Generator { State = "SSWV_XDIE2"; } # Pink demon death blood. Copy Generator { State = "SARG_DIE1"; Speed = 4; Spawn age = 3; Spawn rate = 20; } Copy Generator { State = "FATT_DIE2"; } # Trooper death blood. Copy Generator { State = "TROO_DIE1"; Speed = 3; Spawn age = 2; Spawn rate = 15; } # Arachnotron death. Copy Generator { State = "BSPI_DIE2"; } # Cacodemon death. Copy Generator { State = "HEAD_DIE3"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/jdoom64.ded0000644000175000017500000000117511357170242022715 0ustar keeskees# # -=- jDoom64 Definitions -=- # # This file is overwritten on every upgrade. Add custom definitions # to User.ded. # # For information about DED syntax and semantics, see Doc\DEDDoc.txt. # Header { Version = 5; Default model scale = 1.2; Model path = "data\jdoom64\models"; } Include "flags.ded"; Include "objects.ded"; Include "sprites.ded"; Include "materials.ded"; Include "anim.ded"; Include "audio.ded"; Include "special.ded"; Include "lights.ded"; Include "skies.ded"; Include "maps.ded"; Include "finales.ded"; Include "text.ded"; Include "values.ded"; IncludeIf Not -noauto "auto\*.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/objects.ded0000644000175000017500000070336111357170242023072 0ustar keeskees# jDoom64: Objects # # Order of definitions is very important here! # Only add new States and Things *after* the existing definitions. Header { Version = 6; } Thing { ID = "PLAYER"; DoomEd number = -1; Spawn state = "PLAY"; See state = "PLAY_RUN1"; Pain state = "PLAY_PAIN"; Melee state = "NULL"; Missile state = "PLAY_ATK1"; Death state = "PLAY_DIE1"; Xdeath state = "PLAY_XDIE1"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "plpain"; Death sound = "pldeth"; Active sound = "None"; Pain chance = 255; Spawn health = 100; Radius = 18; Height = 56; Mass = 100; Flags = solid | shootable | dropoff | pickup; Flags2 = slide | passmobj | telestomp; } Thing { ID = "EMARINEL"; DoomEd number = 64; Spawn state = "EMARP_STND"; See state = "EMARP_RUN1"; Pain state = "EMARP_PAIN"; Melee state = "NULL"; Missile state = "EMARP_ATK1"; Death state = "PLAY_XDIE1"; Xdeath state = "PLAY_XDIE1"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "plpain"; Death sound = "pldeth"; Active sound = "None"; Pain chance = 170; Spawn health = 30; Speed = 30; Radius = 25; Height = 56; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "EMARINEP"; DoomEd number = 235; Spawn state = "EMARP_STND"; See state = "EMARP_RUN1"; Pain state = "EMARP_PAIN"; Melee state = "NULL"; Missile state = "EMARP_ATKB1"; Death state = "PLAY_DIE1"; Xdeath state = "PLAY_XDIE1"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "plpain"; Death sound = "pldeth"; Active sound = "None"; Pain chance = 170; Spawn health = 9999; Speed = 30; Radius = 25; Height = 56; Mass = 100; Flags = solid | shootable | countkill; Flags2 = slide | passmobj | telestomp; } Thing { ID = "EMARINES"; DoomEd number = 65; Spawn state = "EMARP_STND"; See state = "EMARP_RUN1"; Pain state = "EMARP_PAIN"; Melee state = "NULL"; Missile state = "EMARP_ATK1"; Death state = "PLAY_XDIE1"; Xdeath state = "PLAY_XDIE1"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "plpain"; Death sound = "pldeth"; Active sound = "None"; Pain chance = 170; Spawn health = 30; Speed = 30; Radius = 25; Height = 56; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "POSSESSED"; Name = "Zombieman"; DoomEd number = 3004; Spawn state = "POSS_STND"; See state = "POSS_RUN1"; Pain state = "POSS_PAIN"; Melee state = "NULL"; Missile state = "POSS_ATK1"; Death state = "POSS_DIE1"; Xdeath state = "POSS_XDIE1"; Raise state = "NULL"; See sound = "posit1"; Attack sound = "pistol"; Pain sound = "popain"; Death sound = "podth1"; Active sound = "posact"; Reaction time = 8; Pain chance = 200; Spawn health = 20; Speed = 8; Radius = 31; Height = 72; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SHOTGUY"; Name = "Shotgun Guy"; DoomEd number = 9; Spawn state = "SPOS_STND"; See state = "SPOS_RUN1"; Pain state = "SPOS_PAIN"; Melee state = "NULL"; Missile state = "SPOS_ATK1"; Death state = "SPOS_DIE1"; Xdeath state = "SPOS_XDIE1"; Raise state = "NULL"; See sound = "posit2"; Attack sound = "None"; Pain sound = "popain"; Death sound = "podth2"; Active sound = "posact"; Reaction time = 8; Pain chance = 170; Spawn health = 30; Speed = 8; Radius = 31; Height = 72; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "TRACER"; DoomEd number = -1; Spawn state = "TRACER"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "TRACEEXP1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "skeatk"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 11; Height = 8; Mass = 100; Damage = 10; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "SMOKE"; DoomEd number = -1; Spawn state = "SMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "FATSO"; Name = "Mancubus"; DoomEd number = 67; Spawn state = "FATT_STND"; See state = "FATT_RUN1"; Pain state = "FATT_PAIN"; Melee state = "NULL"; Missile state = "FATT_ATK1"; Death state = "FATT_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "mansit"; Attack sound = "None"; Pain sound = "mnpain"; Death sound = "mandth"; Active sound = "posact"; Reaction time = 8; Pain chance = 80; Spawn health = 600; Speed = 8; Radius = 64; Height = 64; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FATSHOT"; DoomEd number = -1; Spawn state = "FATSHOT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "FATSHOTX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 6; Height = 8; Mass = 100; Damage = 8; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "TROOP"; Name = "Imp"; DoomEd number = 3001; Spawn state = "TROO_STND"; See state = "TROO_RUN1"; Pain state = "TROO_PAIN"; Melee state = "TROO_MEL1"; Missile state = "TROO_ATK1"; Death state = "TROO_DIE1"; Xdeath state = "TROO_XDIE1"; Raise state = "NULL"; See sound = "bgsit1"; Attack sound = "None"; Pain sound = "popain"; Death sound = "bgdth1"; Active sound = "bgact"; Reaction time = 8; Pain chance = 200; Spawn health = 60; Speed = 8; Radius = 32; Height = 72; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SERGEANT"; Name = "Demon"; DoomEd number = 3002; Spawn state = "SARG_STND"; See state = "SARG_RUN1"; Pain state = "SARG_PAIN"; Melee state = "SARG_ATK1"; Missile state = "NULL"; Death state = "SARG_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "sgtsit"; Attack sound = "sgtatk"; Pain sound = "dmpain"; Death sound = "sgtdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 180; Spawn health = 150; Speed = 10; Radius = 32; Height = 56; Mass = 400; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SHADOWS"; Name = "Spectre"; DoomEd number = 58; Spawn state = "SARG_STND"; See state = "SHAD_RUN"; Pain state = "SHAD_PAIN"; Melee state = "SHAD_ATK"; Missile state = "NULL"; Death state = "SHAD_DIE"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "sgtsit"; Attack sound = "sgtatk"; Pain sound = "dmpain"; Death sound = "sgtdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 180; Spawn health = 150; Speed = 10; Radius = 32; Height = 56; Mass = 400; Flags = solid | shootable | shadow | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "HEAD"; Name = "Cacodemon"; DoomEd number = 3005; Spawn state = "HEAD_STND"; See state = "HEAD_RUN1"; Pain state = "HEAD_PAIN"; Melee state = "NULL"; Missile state = "HEAD_ATK1"; Death state = "HEAD_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "cacsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "cacdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 128; Spawn health = 400; Speed = 8; Radius = 39; Height = 88; Mass = 400; Flags = solid | shootable | float | nogravity | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "BRUISER"; Name = "Baron of Hell"; DoomEd number = 3003; Spawn state = "BOSS_STND"; See state = "BOSS_RUN1"; Pain state = "BOSS_PAIN"; Melee state = "BOSS_ATK1"; Missile state = "BOSS_ATK1"; Death state = "BOSS_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "brssit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "brsdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 50; Spawn health = 1000; Speed = 8; Radius = 24; Height = 80; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "BRUISERSHOT"; DoomEd number = -1; Spawn state = "BRBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BRBALLX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 6; Height = 8; Mass = 100; Damage = 8; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "KNIGHT"; Name = "Hell Knight"; DoomEd number = 69; Spawn state = "BOS2_STND"; See state = "BOS2_RUN1"; Pain state = "BOS2_PAIN"; Melee state = "BOS2_ATK1"; Missile state = "BOS2_ATK1"; Death state = "BOS2_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "kntsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "kntdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 50; Spawn health = 500; Speed = 8; Radius = 32; Height = 80; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SKULL"; Name = "Lost Soul"; DoomEd number = 3006; Spawn state = "SKULL_STND"; See state = "SKULL_RUN1"; Pain state = "SKULL_PAIN"; Melee state = "NULL"; Missile state = "SKULL_ATK1"; Death state = "SKULL_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "sklatk"; Pain sound = "dmpain"; Death sound = "firxpl"; Active sound = "dmact"; Reaction time = 8; Pain chance = 256; Spawn health = 50; Speed = 12; Radius = 16; Height = 56; Mass = 50; Damage = 3; Flags = solid | shootable | float | nogravity; Flags2 = passmobj | telestomp; } Thing { ID = "BABY"; Name = "Arachnotron"; DoomEd number = 68; Spawn state = "BSPI_STND"; See state = "BSPI_SEE"; Pain state = "BSPI_PAIN"; Melee state = "NULL"; Missile state = "BSPI_ATK1"; Death state = "BSPI_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "bspsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "bspdth"; Active sound = "bspact"; Reaction time = 8; Pain chance = 128; Spawn health = 500; Speed = 12; Radius = 64; Height = 64; Mass = 600; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "CYBORG"; Name = "Cyberdemon"; DoomEd number = 16; Spawn state = "CYBER_STND"; See state = "CYBER_RUN1"; Pain state = "CYBER_PAIN"; Melee state = "NULL"; Missile state = "CYBER_ATK1"; Death state = "CYBER_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "cybsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "cybdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 20; Spawn health = 4000; Speed = 16; Radius = 40; Height = 160; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp | boss; } Thing { ID = "DCYBORG"; Name = "DCyberdemon"; DoomEd number = 16; Spawn state = "DCYBER_STND"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "DCYBER_ATK1"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "cybsit"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "dmact"; Reaction time = 8; Pain chance = 20; Spawn health = 4000; Speed = 0; Radius = 40; Height = 110; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp | boss; } Thing { ID = "PAIN"; Name = "Pain Elemental"; DoomEd number = 71; Spawn state = "PAIN_STND"; See state = "PAIN_SEE"; Pain state = "PAIN_PAIN"; Melee state = "NULL"; Missile state = "PAIN_ATK1"; Death state = "PAIN_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "pesit"; Attack sound = "None"; Pain sound = "pepain"; Death sound = "pedth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 128; Spawn health = 400; Speed = 8; Radius = 31; Height = 56; Mass = 400; Flags = solid | shootable | float | nogravity | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "EMARINER"; DoomEd number = 88; Spawn state = "BRAIN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "plpain"; Death sound = "pldeth"; Active sound = "None"; Pain chance = 170; Spawn health = 30; Speed = 30; Radius = 25; Height = 56; Mass = 100; Flags = solid; } Thing { ID = "BARREL"; DoomEd number = 2035; Spawn state = "BAR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BAR2"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 20; Radius = 10; Height = 42; Mass = 100; Flags = solid | shootable | noblood; Flags2 = telestomp; } Thing { ID = "TROOPSHOT"; DoomEd number = -1; Spawn state = "TBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "TBALLX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 8; Mass = 100; Damage = 3; Flags = brightexplode | dropoff | missile | noblockmap | nogravity | brightshadow; Flags2 = noteleport; } Thing { ID = "HEADSHOT"; DoomEd number = -1; Spawn state = "BAL3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BAL3EXP"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 18; Radius = 11; Height = 8; Mass = 100; Damage = 10; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "ROCKET"; DoomEd number = -1; Spawn state = "ROCKET"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "EXPLODE0"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "rlaunc"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 30; Radius = 11; Height = 8; Mass = 100; Damage = 20; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "CYBERROCKET"; DoomEd number = -1; Spawn state = "ROCKET"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "EXPLODE0"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "rlaunc"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 30; Radius = 11; Height = 8; Mass = 100; Damage = 20; Flags = missile | noblockmap | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "PLASMA"; DoomEd number = -1; Spawn state = "PLASBALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "PLASEXP"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "plasma"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 7; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "BFG"; DoomEd number = -1; Spawn state = "BFGSHOT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BFGLAND"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "rxplod"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 100; Flags = noblockmap | missile | dropoff | nogravity | brightexplode | brightshadow; Flags2 = noteleport; } Thing { ID = "ARACHPLAZ"; DoomEd number = -1; Spawn state = "ARACH_PLAZ"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "ARACH_PLEX"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "plasma"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 5; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "PUFF"; DoomEd number = -1; Spawn state = "PUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 8; Mass = 100; Flags = noblockmap | nogravity | viewalign; Flags2 = cannotpush | noteleport; } Thing { ID = "BLOOD"; DoomEd number = -1; Spawn state = "BLOOD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | viewalign; Flags2 = cannotpush | noteleport; } Thing { ID = "TFOG"; DoomEd number = -1; Spawn state = "TFOG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity | brightshadow; Flags2 = cannotpush | noteleport; } Thing { ID = "IFOG"; DoomEd number = -1; Spawn state = "TFOG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "TELEPORTMAN"; DoomEd number = 14; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; Flags2 = cannotpush; } Thing { ID = "EXTRABFG"; DoomEd number = -1; Spawn state = "BFGEXP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity | brightshadow; Flags2 = cannotpush | noteleport; } Thing { ID = "MISC0"; DoomEd number = 2018; Spawn state = "ARM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC1"; DoomEd number = 2019; Spawn state = "ARM2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC2"; DoomEd number = 2014; Spawn state = "BON1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC3"; DoomEd number = 2015; Spawn state = "BON2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC4"; DoomEd number = 5; Spawn state = "BKEY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC5"; DoomEd number = 13; Spawn state = "RKEY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC6"; DoomEd number = 6; Spawn state = "YKEY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC7"; DoomEd number = 39; Spawn state = "YSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC8"; DoomEd number = 38; Spawn state = "RSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC9"; DoomEd number = 40; Spawn state = "BSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC10"; DoomEd number = 2011; Spawn state = "STIM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC11"; DoomEd number = 2012; Spawn state = "MEDI"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC12"; DoomEd number = 2013; Spawn state = "SOUL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "INV"; DoomEd number = 2022; Spawn state = "PINV"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC13"; DoomEd number = 2023; Spawn state = "PSTR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "INS"; DoomEd number = 2024; Spawn state = "PINS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC14"; DoomEd number = 2025; Spawn state = "SUIT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC15"; DoomEd number = 2026; Spawn state = "PMAP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC16"; DoomEd number = 2045; Spawn state = "PVIS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MEGA"; DoomEd number = 83; Spawn state = "MEGA"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "CLIP"; DoomEd number = 2007; Spawn state = "CLIP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC17"; DoomEd number = 2048; Spawn state = "AMMO"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC18"; DoomEd number = 2010; Spawn state = "RCKT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC19"; DoomEd number = 2046; Spawn state = "BROK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC20"; DoomEd number = 2047; Spawn state = "CELL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC21"; DoomEd number = 17; Spawn state = "CELP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC22"; DoomEd number = 2008; Spawn state = "SHEL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC23"; DoomEd number = 2049; Spawn state = "SBOX"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC24"; DoomEd number = 8; Spawn state = "BPAK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC25"; Name = "BFG 9000"; DoomEd number = 2006; Spawn state = "BFUG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "CHAINGUN"; DoomEd number = 2002; Spawn state = "MGUN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC26"; DoomEd number = 2005; Spawn state = "CSAW"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC27"; DoomEd number = 2003; Spawn state = "LAUN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC28"; DoomEd number = 2004; Spawn state = "PLSM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "SHOTGUN"; DoomEd number = 2001; Spawn state = "SHOT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "SUPERSHOTGUN"; DoomEd number = 82; Spawn state = "SHOT2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC29"; DoomEd number = 85; Spawn state = "TECHLAMP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 80; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC30"; DoomEd number = 86; Spawn state = "TECH2LAMP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC31"; DoomEd number = 2028; Spawn state = "COLU"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 48; Mass = 100; Flags = nogravity | spawnceiling | local; } Thing { ID = "MISC32"; DoomEd number = 30; Spawn state = "TALLGRNCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 53; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC33"; DoomEd number = 31; Spawn state = "SHRTGRNCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC34"; DoomEd number = 32; Spawn state = "TALLREDCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 53; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC35"; DoomEd number = 33; Spawn state = "SHRTREDCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC36"; DoomEd number = 37; Spawn state = "SKULLCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC40"; DoomEd number = 43; Spawn state = "TORCHTREE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 70; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC41"; DoomEd number = 44; Spawn state = "BLUETORCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "MISC42"; DoomEd number = 45; Spawn state = "GREENTORCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "MISC43"; DoomEd number = 46; Spawn state = "REDTORCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "MISC44"; DoomEd number = 55; Spawn state = "BTORCHSHRT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = nogravity | spawnceiling; } Thing { ID = "MISC45"; DoomEd number = 56; Spawn state = "GTORCHSHRT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = nogravity | spawnceiling; } Thing { ID = "MISC46"; DoomEd number = 57; Spawn state = "RTORCHSHRT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = nogravity | spawnceiling; } Thing { ID = "MISC47"; DoomEd number = 47; Spawn state = "STALAGTITE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC48"; DoomEd number = 48; Spawn state = "TECHPILLAR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 128; Mass = 100; Flags = nogravity | local | spawnceiling; } Thing { ID = "MISC49"; DoomEd number = 34; Spawn state = "CANDLE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = local; } Thing { ID = "MISC50"; DoomEd number = 35; Spawn state = "CANDELABRA"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC51"; DoomEd number = 49; Spawn state = "BLOODYTWITCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 68; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC52"; DoomEd number = 50; Spawn state = "MEAT2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 84; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC53"; DoomEd number = 51; Spawn state = "MEAT3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 84; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC54"; DoomEd number = 52; Spawn state = "MEAT4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 68; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC55"; DoomEd number = 53; Spawn state = "MEAT5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 52; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC56"; DoomEd number = 59; Spawn state = "MEAT2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 84; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC57"; DoomEd number = 60; Spawn state = "MEAT4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 68; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC58"; DoomEd number = 61; Spawn state = "MEAT3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 52; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC59"; DoomEd number = 62; Spawn state = "MEAT5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 52; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC60"; DoomEd number = 63; Spawn state = "BLOODYTWITCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 68; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC68"; DoomEd number = 10; Spawn state = "PLAY_XDIE9"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC69"; DoomEd number = 12; Spawn state = "PLAY_XDIE9"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC70"; DoomEd number = 28; Spawn state = "HEADSONSTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 67; Mass = 100; Flags = local; } Thing { ID = "MISC71"; DoomEd number = 24; Spawn state = "GIBS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags2 = cannotpush; } Thing { ID = "MISC72"; DoomEd number = 27; Spawn state = "HEADONASTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 56; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC73"; DoomEd number = 29; Spawn state = "HEADCANDLES"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 43; Mass = 100; Flags = local; } Thing { ID = "MISC74"; DoomEd number = 25; Spawn state = "DEADSTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 66; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC75"; DoomEd number = 26; Spawn state = "LIVESTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 66; Mass = 100; Flags = local; } Thing { ID = "MISC76"; DoomEd number = 54; Spawn state = "BIGTREE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 32; Height = 124; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC78"; DoomEd number = 73; Spawn state = "HANGNOGUTS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 88; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC79"; DoomEd number = 74; Spawn state = "HANGBNOBRAIN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 88; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC80"; DoomEd number = 75; Spawn state = "HANGTLOOKDN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC81"; DoomEd number = 76; Spawn state = "HANGTSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC82"; DoomEd number = 77; Spawn state = "HANGTLOOKUP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC83"; DoomEd number = 78; Spawn state = "HANGTNOBRAIN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC84"; DoomEd number = 79; Spawn state = "COLONGIBS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap; } Thing { ID = "MISC85"; DoomEd number = 80; Spawn state = "SMALLPOOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap; } Thing { ID = "MISC86"; DoomEd number = 81; Spawn state = "BRAINSTEM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 64; Mass = 100; Flags = solid | local; Flags2 = noteleport; } Thing { ID = "BRUISERSHOTRED"; DoomEd number = -1; Spawn state = "BRNRBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BRNRBALLX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 6; Height = 8; Mass = 100; Damage = 8; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "NTROSHOT"; DoomEd number = -1; Spawn state = "NMBL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NMBLX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 16; Radius = 6; Height = 8; Mass = 100; Damage = 3; Flags = brightexplode | dropoff | missile | noblockmap | nogravity | brightshadow; Flags2 = cannotpush | noteleport; } Thing { ID = "ROCKETPUFF"; DoomEd number = -1; Spawn state = "RPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 8; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "LASERGUN"; DoomEd number = 2009; Spawn state = "LSRG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "LASERSHOT"; DoomEd number = -1; Spawn state = "LAZR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "LAZRDTH"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "laser"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 32; Radius = 13; Height = 8; Mass = 100; Damage = 10; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "LASERDUST"; DoomEd number = -1; Spawn state = "LAZRDUST"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 32; Radius = 13; Height = 8; Mass = 100; Damage = 0; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "LPOWERUP1"; DoomEd number = 4000; Spawn state = "ART1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "LPOWERUP2"; DoomEd number = 4001; Spawn state = "ART2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "LPOWERUP3"; DoomEd number = 4002; Spawn state = "ART3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "LASERSHOTWEAK"; DoomEd number = -1; Spawn state = "LAZRW1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "LAZRDTH"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "laser"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 32; Radius = 13; Height = 8; Mass = 100; Damage = 5; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "RECT"; DoomEd number = 5000; Spawn state = "RECT_STND"; See state = "RECT_RUN1"; Pain state = "RECT_PAIN"; Melee state = "NULL"; Missile state = "RECT_ATK1"; Death state = "RECT_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "mthsit"; Attack sound = "mthatk"; Pain sound = "mthpai"; Death sound = "mthdth"; Active sound = "mthact"; Reaction time = 1; Spawn health = 5300; Speed = 32; Radius = 40; Height = 110; Mass = 1000; Pain chance = 20; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "BITCHBALL"; DoomEd number = -1; Spawn state = "RTRACER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "RTRACEREXP"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "skeatk"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 11; Height = 8; Mass = 100; Damage = 10; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = passmobj | cannotpush | noteleport; } Thing { ID = "MOTHERPUFF"; DoomEd number = -1; Spawn state = "MPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 8; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "DART"; DoomEd number = -1; Spawn state = "DART"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "DARTHIT"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "SKESWG"; Attack sound = "None"; Pain sound = "None"; Death sound = "ssdth"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 16; Radius = 13; Height = 8; Mass = 100; Damage = 4; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = passmobj | cannotpush; } Thing { ID = "TELEPORTSHOT"; DoomEd number = 7575; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTCHAIN"; DoomEd number = 7576; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSSHOT"; DoomEd number = 7577; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTROCKET"; DoomEd number = 7578; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTPLASMA"; DoomEd number = 7579; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBFG"; DoomEd number = 7580; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTMEDKIT"; DoomEd number = 7581; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSTIM"; DoomEd number = 7582; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTARMOR1"; DoomEd number = 7583; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTARMOR2"; DoomEd number = 7584; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTLASER"; DoomEd number = 7585; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTLKEY1"; DoomEd number = 7586; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTLKEY2"; DoomEd number = 7587; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTLKEY3"; DoomEd number = 7588; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTMEGA"; DoomEd number = 7589; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSOUL"; DoomEd number = 7590; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBLUR"; DoomEd number = 7591; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTINVUL"; DoomEd number = 7592; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBERSERK"; DoomEd number = 7593; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTPOTION"; DoomEd number = 7594; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTHELMET"; DoomEd number = 7595; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTMAP"; DoomEd number = 7596; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTLIGHT"; DoomEd number = 7597; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSUIT"; DoomEd number = 7598; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSHELL"; DoomEd number = 7599; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSBOX"; DoomEd number = 7600; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTCLIP"; DoomEd number = 7601; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBULLETS"; DoomEd number = 7602; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTRROCKET"; DoomEd number = 7603; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTRRBOX"; DoomEd number = 7604; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTCELL"; DoomEd number = 7605; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTCBOX"; DoomEd number = 7606; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBACKPACK"; DoomEd number = 7607; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTPOSS"; DoomEd number = 7608; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSPOS"; DoomEd number = 7609; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTTROOP"; DoomEd number = 7610; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTNTROP"; DoomEd number = 7611; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSARG"; DoomEd number = 7612; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTSARG2"; DoomEd number = 7613; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTNSARG"; DoomEd number = 7614; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTHEAD"; DoomEd number = 7615; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTHEAD2"; DoomEd number = 7616; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTLOSTSOUL"; DoomEd number = 7617; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTPAIN"; DoomEd number = 7618; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTFATSO"; DoomEd number = 7619; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBABY"; DoomEd number = 7620; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTCYBORG"; DoomEd number = 7621; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBITCH"; DoomEd number = 7622; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTKNIGHT"; DoomEd number = 7623; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBARON"; DoomEd number = 7624; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTRKEY"; DoomEd number = 7625; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTRKEY2"; DoomEd number = 7626; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBKEY"; DoomEd number = 7627; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTBKEY2"; DoomEd number = 7628; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTYKEY"; DoomEd number = 7629; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "TELEPORTYKEY2"; DoomEd number = 7630; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; } Thing { ID = "NTROOP"; Name = "Nightmare Imp"; DoomEd number = 400; Spawn state = "NTRO_STND"; See state = "NTRO_RUN1"; Pain state = "NTRO_PAIN"; Melee state = "NTRO_MEL1"; Missile state = "NTRO_ATK1"; Death state = "NTRO_DIE1"; Xdeath state = "NTRO_XDIE1"; Raise state = "NULL"; See sound = "bgsit1"; Attack sound = "None"; Pain sound = "popain"; Death sound = "bgdth1"; Active sound = "bgact"; Reaction time = 8; Pain chance = 200; Spawn health = 60; Speed = 14; Radius = 32; Height = 72; Mass = 100; Flags = solid | shootable | countkill | brightshadow; } Thing { ID = "KABOOM"; DoomEd number = -1; Spawn state = "EXPLODE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "EXPLODE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "rlaunc"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 11; Height = 8; Mass = 100; Damage = 20; Flags = noblockmap | dropoff | nogravity | brightexplode | float | noclip; } Thing { ID = "LIGHTSOURCE"; DoomEd number = 5000; Spawn state = "SMALL_WHITE_LIGHT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Radius = 16; Height = 16; Mass = 100; Flags = local | noblockmap | nogravity; } Thing { ID = "TEMPSOUNDORIGIN"; DoomEd number = -1; Spawn state = "TEMPSOUNDORIGIN1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Radius = 1; Height = 1; Mass = 100; Flags = local | nosector | noblockmap | nogravity; } Thing { ID = "FAKEKNIGHT"; Name = "Fake Hell Knight"; DoomEd number = 222; Spawn state = "BOS2_STND"; See state = "BOS2_RUN1"; Pain state = "BOS2_PAIN"; Melee state = "BOS2_ATK1"; Missile state = "BOS2_ATK1"; Death state = "BOS2_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "kntsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "kntdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 50; Spawn health = 500; Speed = 8; Radius = 32; Height = 64; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FAKETROOP"; Name = "Fake Imp"; DoomEd number = 223; Spawn state = "TROO_STND"; See state = "TROO_RUN1"; Pain state = "TROO_PAIN"; Melee state = "TROO_MEL1"; Missile state = "TROO_ATK1"; Death state = "TROO_DIE1"; Xdeath state = "TROO_XDIE1"; Raise state = "NULL"; See sound = "bgsit1"; Attack sound = "None"; Pain sound = "popain"; Death sound = "bgdth1"; Active sound = "bgact"; Reaction time = 8; Pain chance = 200; Spawn health = 60; Speed = 8; Radius = 32; Height = 72; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FAKESHADOWS"; Name = "Fake Spectre"; DoomEd number = 224; Spawn state = "SARG_STND"; See state = "SHAD_RUN"; Pain state = "SHAD_PAIN"; Melee state = "SHAD_ATK"; Missile state = "NULL"; Death state = "SHAD_DIE"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "sgtsit"; Attack sound = "sgtatk"; Pain sound = "dmpain"; Death sound = "sgtdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 180; Spawn health = 150; Speed = 10; Radius = 32; Height = 56; Mass = 400; Flags = solid | shootable | shadow | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FAKESKULL"; Name = "Fake Lost Soul"; DoomEd number = 225; Spawn state = "SKULL_STND"; See state = "SKULL_RUN1"; Pain state = "SKULL_PAIN"; Melee state = "NULL"; Missile state = "SKULL_ATK1"; Death state = "SKULL_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "sklatk"; Pain sound = "dmpain"; Death sound = "firxpl"; Active sound = "dmact"; Reaction time = 8; Pain chance = 256; Spawn health = 100; Speed = 8; Radius = 16; Height = 56; Mass = 50; Damage = 3; Flags = solid | shootable | float | nogravity; Flags2 = passmobj | telestomp; } Thing { ID = "F_BRUISER"; Name = "Fake Baron"; DoomEd number = 226; Spawn state = "BOSS_STND"; See state = "BOSS_RUN1"; Pain state = "BOSS_PAIN"; Melee state = "BOSS_ATK1"; Missile state = "BOSS_ATK1"; Death state = "BOSS_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "brssit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "brsdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 50; Spawn health = 1000; Speed = 8; Radius = 24; Height = 80; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "TRACER6"; Name = "Tracer 6 Shot"; DoomEd number = 227; Spawn state = "TSHOT6_STND"; See state = "TSHOT6_RUN1"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 0; Pain chance = 180; Spawn health = 500; Speed = 0; Radius = 8; Height = 32; Mass = 400; Flags = dropoff | nogravity | float; } Thing { ID = "YELLOWFIREBALL"; DoomEd number = 747; Spawn state = "YFIREBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "BLUEFIREBALL"; DoomEd number = 748; Spawn state = "BFIREBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "REDFIREBALL"; DoomEd number = 749; Spawn state = "RFIREBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "YELLOWFIREBALL2"; DoomEd number = 750; Spawn state = "Y2FIREBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "BLUEFIREBALL2"; DoomEd number = 751; Spawn state = "B2FIREBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "REDFIREBALL2"; DoomEd number = 752; Spawn state = "R2FIREBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = local; } Thing { ID = "FSHOTGUY"; Name = "Fake Shotgun Guy"; DoomEd number = 228; Spawn state = "SPOS_STND"; See state = "SPOS_RUN1"; Pain state = "SPOS_PAIN"; Melee state = "NULL"; Missile state = "SPOS_ATK1"; Death state = "SPOS_DIE1"; Xdeath state = "SPOS_XDIE1"; Raise state = "NULL"; See sound = "posit2"; Attack sound = "None"; Pain sound = "popain"; Death sound = "podth2"; Active sound = "posact"; Reaction time = 8; Pain chance = 170; Spawn health = 30; Speed = 8; Radius = 31; Height = 72; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FDEMON"; Name = "Fake Demon"; DoomEd number = 229; Spawn state = "SARG_STND"; See state = "SARG_RUN1"; Pain state = "SARG_PAIN"; Melee state = "SARG_ATK1"; Missile state = "NULL"; Death state = "SARG_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "sgtsit"; Attack sound = "sgtatk"; Pain sound = "dmpain"; Death sound = "sgtdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 180; Spawn health = 150; Speed = 10; Radius = 32; Height = 56; Mass = 400; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FPAIN"; Name = "Fake Pain Elemental"; DoomEd number = 230; Spawn state = "PAIN_STND"; See state = "PAIN_SEE"; Pain state = "PAIN_PAIN"; Melee state = "NULL"; Missile state = "PAIN_ATK1"; Death state = "PAIN_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "pesit"; Attack sound = "None"; Pain sound = "pepain"; Death sound = "pedth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 128; Spawn health = 400; Speed = 8; Radius = 31; Height = 56; Mass = 400; Flags = solid | shootable | float | nogravity | countkill | spawnceiling; Flags2 = passmobj | telestomp; } Thing { ID = "DISSOUL"; Name = "Dissapearing Soulsphere"; DoomEd number = 231; Spawn state = "DISSOUL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "DISBKEY1"; DoomEd number = 233; Spawn state = "DBKEY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "FBABY"; Name = "Fake Arachnotron"; DoomEd number = 234; Spawn state = "BSPI_STND"; See state = "BSPI_SEE"; Pain state = "BSPI_PAIN"; Melee state = "NULL"; Missile state = "BSPI_ATK1"; Death state = "BSPI_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "bspsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "bspdth"; Active sound = "bspact"; Reaction time = 8; Pain chance = 128; Spawn health = 500; Speed = 12; Radius = 64; Height = 64; Mass = 600; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FFATSO"; Name = "Fake Mancubus"; DoomEd number = 235; Spawn state = "FATT_STND"; See state = "FATT_RUN1"; Pain state = "FATT_PAIN"; Melee state = "NULL"; Missile state = "FATT_ATK1"; Death state = "FATT_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "mansit"; Attack sound = "None"; Pain sound = "mnpain"; Death sound = "mandth"; Active sound = "posact"; Reaction time = 8; Pain chance = 80; Spawn health = 600; Speed = 8; Radius = 64; Height = 64; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } State { ID = "NULL"; Sprite = "TROO"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "LIGHTDONE"; Sprite = "SHT1"; Frame = 4; Tics = 0; Action = "A_Light0"; Next state = "NULL"; } State { ID = "PLAY"; Sprite = "PLAY"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PLAY_RUN1"; Sprite = "PLAY"; Frame = 0; Tics = 4; Next state = "PLAY_RUN2"; } State { ID = "PLAY_RUN2"; Sprite = "PLAY"; Frame = 1; Tics = 4; Next state = "PLAY_RUN3"; } State { ID = "PLAY_RUN3"; Sprite = "PLAY"; Frame = 2; Tics = 4; Next state = "PLAY_RUN4"; } State { ID = "PLAY_RUN4"; Sprite = "PLAY"; Frame = 3; Tics = 4; Next state = "PLAY_RUN1"; } State { ID = "PLAY_ATK1"; Sprite = "PLAY"; Frame = 4; Tics = 12; Next state = "PLAY"; } State { ID = "PLAY_ATK2"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "PLAY"; } State { ID = "PLAY_PAIN"; Sprite = "PLAY"; Frame = 6; Tics = 4; Next state = "PLAY_PAIN2"; } State { ID = "PLAY_PAIN2"; Sprite = "PLAY"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "PLAY"; } State { ID = "PLAY_DIE1"; Sprite = "PLAY"; Frame = 7; Tics = 10; Next state = "PLAY_DIE2"; } State { ID = "PLAY_DIE2"; Sprite = "PLAY"; Frame = 8; Tics = 10; Action = "A_Scream"; Next state = "PLAY_DIE3"; } State { ID = "PLAY_DIE3"; Sprite = "PLAY"; Frame = 9; Tics = 10; Next state = "PLAY_DIE4"; } State { ID = "PLAY_DIE4"; Sprite = "PLAY"; Frame = 10; Tics = 10; Next state = "PLAY_DIE5"; } State { ID = "PLAY_DIE5"; Sprite = "PLAY"; Frame = 11; Tics = 10; Next state = "PLAY_DIE6"; } State { ID = "PLAY_DIE6"; Sprite = "PLAY"; Frame = 12; Tics = -1; Next state = "NULL"; } State { ID = "PLAY_XDIE1"; Sprite = "PLAY"; Frame = 13; Tics = 5; Next state = "PLAY_XDIE2"; } State { ID = "PLAY_XDIE2"; Sprite = "PLAY"; Frame = 14; Tics = 5; Action = "A_XScream"; Next state = "PLAY_XDIE3"; } State { ID = "PLAY_XDIE3"; Sprite = "PLAY"; Frame = 15; Tics = 5; Next state = "PLAY_XDIE4"; } State { ID = "PLAY_XDIE4"; Sprite = "PLAY"; Frame = 16; Tics = 5; Next state = "PLAY_XDIE5"; } State { ID = "PLAY_XDIE5"; Sprite = "PLAY"; Frame = 17; Tics = 5; Next state = "PLAY_XDIE6"; } State { ID = "PLAY_XDIE6"; Sprite = "PLAY"; Frame = 18; Tics = 5; Next state = "PLAY_XDIE7"; } State { ID = "PLAY_XDIE7"; Sprite = "PLAY"; Frame = 19; Tics = 5; Next state = "PLAY_XDIE8"; } State { ID = "PLAY_XDIE8"; Sprite = "PLAY"; Frame = 20; Tics = 5; Next state = "PLAY_XDIE9"; } State { ID = "PLAY_XDIE9"; Sprite = "PLAY"; Frame = 21; Tics = -1; Next state = "NULL"; } State { ID = "EMARP_STND"; Sprite = "PLAY"; Frame = 4; Tics = 10; Action = "A_Look"; Next state = "EMARP_STND2"; } State { ID = "EMARP_RUN1"; Sprite = "PLAY"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "EMARP_RUN2"; } State { ID = "EMARP_RUN2"; Sprite = "PLAY"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "EMARP_RUN3"; } State { ID = "EMARP_RUN3"; Sprite = "PLAY"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "EMARP_RUN4"; } State { ID = "EMARP_RUN4"; Sprite = "PLAY"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "EMARP_RUN1"; } State { ID = "EMARP_ATK1"; Sprite = "PLAY"; Frame = 4; Tics = 4; Action = "A_PosAttack"; Next state = "EMARP_ATK2"; } State { ID = "EMARP_ATK2"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_PosAttack"; Next state = "EMARP_ATK3"; } State { ID = "EMARP_ATK3"; Sprite = "PLAY"; Frame = 4; Tics = 4; Action = "A_PosAttack"; Next state = "EMARP_ATK4"; } State { ID = "EMARP_ATK4"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_PosAttack"; Next state = "EMARP_ATK5"; } State { ID = "EMARP_ATK5"; Sprite = "PLAY"; Frame = 4; Tics = 4; Action = "A_PosAttack"; Next state = "EMARP_ATK5"; } State { ID = "EMARP_ATK6"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_PosAttack"; Next state = "EMARP_RUN1"; } State { ID = "EMARP_PAIN"; Sprite = "PLAY"; Frame = 6; Tics = 4; Next state = "EMARP_PAIN2"; } State { ID = "EMARP_PAIN2"; Sprite = "PLAY"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "EMARP_RUN1"; } State { ID = "EMARP_ATKB1"; Sprite = "PLAY"; Frame = 4; Tics = 4; Action = "A_EMarineAttack2"; Next state = "EMARP_ATKB2"; } State { ID = "EMARP_ATKB2"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_EMarineAttack2"; Next state = "EMARP_ATKB3"; } State { ID = "EMARP_ATKB3"; Sprite = "PLAY"; Frame = 4; Tics = 4; Action = "A_EMarineAttack2"; Next state = "EMARP_ATKB4"; } State { ID = "EMARP_ATKB4"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_EMarineAttack2"; Next state = "EMARP_ATKB5"; } State { ID = "EMARP_ATKB5"; Sprite = "PLAY"; Frame = 4; Tics = 4; Action = "A_EMarineAttack2"; Next state = "EMARP_ATKB6"; } State { ID = "EMARP_ATKB6"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_EMarineAttack2"; Next state = "EMARP_RUN1"; } State { ID = "SARG_STND"; Sprite = "SARG"; Frame = 1; Tics = 8; Action = "A_Look"; Next state = "SARG_STND2"; } State { ID = "SARG_STND2"; Sprite = "SARG"; Frame = 3; Tics = 8; Action = "A_Look"; Next state = "SARG_STND"; } State { ID = "SARG_RUN1"; Sprite = "SARG"; Frame = 0; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN2"; } State { ID = "SARG_RUN2"; Sprite = "SARG"; Frame = 0; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN3"; } State { ID = "SARG_RUN3"; Sprite = "SARG"; Frame = 1; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN4"; } State { ID = "SARG_RUN4"; Sprite = "SARG"; Frame = 1; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN5"; } State { ID = "SARG_RUN5"; Sprite = "SARG"; Frame = 2; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN6"; } State { ID = "SARG_RUN6"; Sprite = "SARG"; Frame = 2; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN7"; } State { ID = "SARG_RUN7"; Sprite = "SARG"; Frame = 3; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN8"; } State { ID = "SARG_RUN8"; Sprite = "SARG"; Frame = 3; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN1"; } State { ID = "SARG_ATK1"; Sprite = "SARG"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "SARG_ATK2"; } State { ID = "SARG_ATK2"; Sprite = "SARG"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "SARG_ATK3"; } State { ID = "SARG_ATK3"; Sprite = "SARG"; Frame = 6; Tics = 8; Action = "A_SargAttack"; Next state = "SARG_RUN1"; } State { ID = "SARG_PAIN"; Sprite = "SARG"; Frame = 7; Tics = 2; Next state = "SARG_PAIN2"; } State { ID = "SARG_PAIN2"; Sprite = "SARG"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "SARG_RUN1"; } State { ID = "SARG_DIE1"; Sprite = "SARG"; Frame = 8; Tics = 8; Next state = "SARG_DIE2"; } State { ID = "SARG_DIE2"; Sprite = "SARG"; Frame = 9; Tics = 8; Action = "A_Scream"; Next state = "SARG_DIE3"; } State { ID = "SARG_DIE3"; Sprite = "SARG"; Frame = 10; Tics = 4; Next state = "SARG_DIE4"; } State { ID = "SARG_DIE4"; Sprite = "SARG"; Frame = 11; Tics = 4; Action = "A_SargSpecial"; Next state = "SARG_DIE5"; } State { ID = "SARG_DIE5"; Sprite = "SARG"; Frame = 12; Tics = 4; Action = "A_Fall"; Next state = "SARG_DIE6"; } State { ID = "SARG_DIE6"; Sprite = "SARG"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "SHAD_RUN"; Sprite = "SARG"; Frame = 0; Tics = 1; Action = "A_ShadowsAction1"; Next state = "SARG_RUN1"; } State { ID = "SHAD_ATK"; Sprite = "SARG"; Frame = 4; Tics = 1; Action = "A_ShadowsAction1"; Next state = "SARG_ATK1"; } State { ID = "SHAD_PAIN"; Sprite = "SARG"; Frame = 7; Tics = 1; Action = "A_ShadowsAction1"; Next state = "SARG_PAIN"; } State { ID = "SHAD_DIE"; Sprite = "SARG"; Frame = 8; Tics = 1; Action = "A_ShadowsAction2"; Next state = "SARG_DIE1"; } State { ID = "FATT_STND"; Sprite = "FATT"; Frame = 0; Tics = 15; Action = "A_Look"; Next state = "FATT_STND2"; } State { ID = "FATT_STND2"; Sprite = "FATT"; Frame = 1; Tics = 15; Action = "A_Look"; Next state = "FATT_STND"; } State { ID = "FATT_RUN1"; Sprite = "FATT"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN2"; } State { ID = "FATT_RUN2"; Sprite = "FATT"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN3"; } State { ID = "FATT_RUN3"; Sprite = "FATT"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN4"; } State { ID = "FATT_RUN4"; Sprite = "FATT"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN5"; } State { ID = "FATT_RUN5"; Sprite = "FATT"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN6"; } State { ID = "FATT_RUN6"; Sprite = "FATT"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN7"; } State { ID = "FATT_RUN7"; Sprite = "FATT"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN8"; } State { ID = "FATT_RUN8"; Sprite = "FATT"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN9"; } State { ID = "FATT_RUN9"; Sprite = "FATT"; Frame = 4; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN10"; } State { ID = "FATT_RUN10"; Sprite = "FATT"; Frame = 4; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN11"; } State { ID = "FATT_RUN11"; Sprite = "FATT"; Frame = 5; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN12"; } State { ID = "FATT_RUN12"; Sprite = "FATT"; Frame = 5; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN1"; } State { ID = "FATT_ATK1"; Sprite = "FATT"; Frame = 7; Tics = 20; Action = "A_FatRaise"; Next state = "FATT_ATK2"; } State { ID = "FATT_ATK2"; Sprite = "FATT"; Frame = 6; Flags = fullbright; Tics = 10; Action = "A_FatAttack1"; Next state = "FATT_ATK3"; } State { ID = "FATT_ATK3"; Sprite = "FATT"; Frame = 7; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_ATK4"; } State { ID = "FATT_ATK4"; Sprite = "FATT"; Frame = 6; Flags = fullbright; Tics = 5; Action = "A_FatAttack2"; Next state = "FATT_ATK5"; } State { ID = "FATT_ATK5"; Sprite = "FATT"; Frame = 7; Tics = 10; Action = "A_FaceTarget"; Next state = "FATT_ATK6"; } State { ID = "FATT_ATK6"; Sprite = "FATT"; Frame = 6; Flags = fullbright; Tics = 5; Action = "A_FatAttack3"; Next state = "FATT_ATK7"; } State { ID = "FATT_ATK7"; Sprite = "FATT"; Frame = 7; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_RUN1"; } State { ID = "FATT_PAIN"; Sprite = "FATT"; Frame = 8; Tics = 3; Next state = "FATT_PAIN2"; } State { ID = "FATT_PAIN2"; Sprite = "FATT"; Frame = 8; Tics = 3; Action = "A_Pain"; Next state = "FATT_RUN1"; } State { ID = "FATT_DIE1"; Sprite = "FATT"; Frame = 9; Tics = 6; Next state = "FATT_DIE2"; } State { ID = "FATT_DIE2"; Sprite = "FATT"; Frame = 10; Tics = 6; Action = "A_Scream"; Next state = "FATT_DIE3"; } State { ID = "FATT_DIE3"; Sprite = "FATT"; Frame = 11; Tics = 6; Action = "A_FattSpecial"; Next state = "FATT_DIE4"; } State { ID = "FATT_DIE4"; Sprite = "FATT"; Frame = 12; Tics = 6; Next state = "FATT_DIE5"; } State { ID = "FATT_DIE5"; Sprite = "FATT"; Frame = 13; Tics = 6; Action = "A_Fall"; Next state = "FATT_DIE6"; } State { ID = "FATT_DIE6"; Sprite = "FATT"; Frame = 14; Tics = -1; Next state = "NULL"; } State { ID = "POSS_STND"; Sprite = "POSS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "POSS_STND2"; } State { ID = "POSS_STND2"; Sprite = "POSS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "POSS_STND"; } State { ID = "POSS_RUN1"; Sprite = "POSS"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN2"; } State { ID = "POSS_RUN2"; Sprite = "POSS"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN3"; } State { ID = "POSS_RUN3"; Sprite = "POSS"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN4"; } State { ID = "POSS_RUN4"; Sprite = "POSS"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN5"; } State { ID = "POSS_RUN5"; Sprite = "POSS"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN6"; } State { ID = "POSS_RUN6"; Sprite = "POSS"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN7"; } State { ID = "POSS_RUN7"; Sprite = "POSS"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN8"; } State { ID = "POSS_RUN8"; Sprite = "POSS"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN1"; } State { ID = "POSS_ATK1"; Sprite = "POSS"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "POSS_ATK2"; } State { ID = "POSS_ATK2"; Sprite = "POSS"; Frame = 5; Tics = 8; Action = "A_PosAttack"; Next state = "POSS_ATK3"; } State { ID = "POSS_ATK3"; Sprite = "POSS"; Frame = 4; Tics = 8; Next state = "POSS_RUN1"; } State { ID = "POSS_PAIN"; Sprite = "POSS"; Frame = 6; Tics = 3; Next state = "POSS_PAIN2"; } State { ID = "POSS_PAIN2"; Sprite = "POSS"; Frame = 6; Tics = 3; Action = "A_Pain"; Next state = "POSS_RUN1"; } State { ID = "POSS_DIE1"; Sprite = "POSS"; Frame = 7; Tics = 5; Next state = "POSS_DIE2"; } State { ID = "POSS_DIE2"; Sprite = "POSS"; Frame = 8; Tics = 5; Action = "A_Scream"; Next state = "POSS_DIE3"; } State { ID = "POSS_DIE3"; Sprite = "POSS"; Frame = 9; Tics = 5; Action = "A_PossSpecial"; Next state = "POSS_DIE4"; } State { ID = "POSS_DIE4"; Sprite = "POSS"; Frame = 10; Tics = 5; Action = "A_Fall"; Next state = "POSS_DIE5"; } State { ID = "POSS_DIE5"; Sprite = "POSS"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "POSS_XDIE1"; Sprite = "POSS"; Frame = 12; Tics = 5; Next state = "POSS_XDIE2"; } State { ID = "POSS_XDIE2"; Sprite = "POSS"; Frame = 13; Tics = 5; Action = "A_XScream"; Next state = "POSS_XDIE3"; } State { ID = "POSS_XDIE3"; Sprite = "POSS"; Frame = 14; Tics = 5; Action = "A_PossSpecial"; Next state = "POSS_XDIE4"; } State { ID = "POSS_XDIE4"; Sprite = "POSS"; Frame = 15; Tics = 5; Next state = "POSS_XDIE5"; } State { ID = "POSS_XDIE5"; Sprite = "POSS"; Frame = 16; Tics = 5; Next state = "POSS_XDIE6"; } State { ID = "POSS_XDIE6"; Sprite = "POSS"; Frame = 17; Tics = 5; Next state = "POSS_XDIE7"; } State { ID = "POSS_XDIE7"; Sprite = "POSS"; Frame = 18; Tics = 5; Next state = "POSS_XDIE8"; } State { ID = "POSS_XDIE8"; Sprite = "POSS"; Frame = 19; Tics = 5; Action = "A_Fall"; Next state = "POSS_XDIE9"; } State { ID = "POSS_XDIE9"; Sprite = "POSS"; Frame = 20; Tics = -1; Next state = "NULL"; } State { ID = "SPOS_STND"; Sprite = "SPOS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SPOS_STND2"; } State { ID = "SPOS_STND2"; Sprite = "SPOS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SPOS_STND"; } State { ID = "SPOS_RUN1"; Sprite = "SPOS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN2"; } State { ID = "SPOS_RUN2"; Sprite = "SPOS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN3"; } State { ID = "SPOS_RUN3"; Sprite = "SPOS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN4"; } State { ID = "SPOS_RUN4"; Sprite = "SPOS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN5"; } State { ID = "SPOS_RUN5"; Sprite = "SPOS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN6"; } State { ID = "SPOS_RUN6"; Sprite = "SPOS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN7"; } State { ID = "SPOS_RUN7"; Sprite = "SPOS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN8"; } State { ID = "SPOS_RUN8"; Sprite = "SPOS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN1"; } State { ID = "SPOS_ATK1"; Sprite = "SPOS"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "SPOS_ATK2"; } State { ID = "SPOS_ATK2"; Sprite = "SPOS"; Frame = 5; Tics = 10; Action = "A_SPosAttack"; Next state = "SPOS_ATK3"; } State { ID = "SPOS_ATK3"; Sprite = "SPOS"; Frame = 4; Tics = 10; Next state = "SPOS_RUN1"; } State { ID = "SPOS_PAIN"; Sprite = "SPOS"; Frame = 6; Tics = 3; Next state = "SPOS_PAIN2"; } State { ID = "SPOS_PAIN2"; Sprite = "SPOS"; Frame = 6; Tics = 3; Action = "A_Pain"; Next state = "SPOS_RUN1"; } State { ID = "SPOS_DIE1"; Sprite = "SPOS"; Frame = 7; Tics = 5; Next state = "SPOS_DIE2"; } State { ID = "SPOS_DIE2"; Sprite = "SPOS"; Frame = 8; Tics = 5; Action = "A_Scream"; Next state = "SPOS_DIE3"; } State { ID = "SPOS_DIE3"; Sprite = "SPOS"; Frame = 9; Tics = 5; Action = "A_SposSpecial"; Next state = "SPOS_DIE4"; } State { ID = "SPOS_DIE4"; Sprite = "SPOS"; Frame = 10; Tics = 5; Action = "A_Fall"; Next state = "SPOS_DIE5"; } State { ID = "SPOS_DIE5"; Sprite = "SPOS"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "SPOS_XDIE1"; Sprite = "SPOS"; Frame = 12; Tics = 5; Next state = "SPOS_XDIE2"; } State { ID = "SPOS_XDIE2"; Sprite = "SPOS"; Frame = 13; Tics = 5; Action = "A_XScream"; Next state = "SPOS_XDIE3"; } State { ID = "SPOS_XDIE3"; Sprite = "SPOS"; Frame = 14; Tics = 5; Action = "A_SposSpecial"; Next state = "SPOS_XDIE4"; } State { ID = "SPOS_XDIE4"; Sprite = "SPOS"; Frame = 15; Tics = 5; Next state = "SPOS_XDIE5"; } State { ID = "SPOS_XDIE5"; Sprite = "SPOS"; Frame = 16; Tics = 5; Next state = "SPOS_XDIE6"; } State { ID = "SPOS_XDIE6"; Sprite = "SPOS"; Frame = 17; Tics = 5; Next state = "SPOS_XDIE7"; } State { ID = "SPOS_XDIE7"; Sprite = "SPOS"; Frame = 18; Tics = 5; Next state = "SPOS_XDIE8"; } State { ID = "SPOS_XDIE8"; Sprite = "SPOS"; Frame = 19; Tics = 5; Action = "A_Fall"; Next state = "SPOS_XDIE9"; } State { ID = "SPOS_XDIE9"; Sprite = "SPOS"; Frame = 20; Tics = -1; Next state = "NULL"; } State { ID = "TROO_STND"; Sprite = "TROO"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "TROO_STND2"; } State { ID = "TROO_STND2"; Sprite = "TROO"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "TROO_STND"; } State { ID = "TROO_RUN1"; Sprite = "TROO"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN2"; } State { ID = "TROO_RUN2"; Sprite = "TROO"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN3"; } State { ID = "TROO_RUN3"; Sprite = "TROO"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN4"; } State { ID = "TROO_RUN4"; Sprite = "TROO"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN5"; } State { ID = "TROO_RUN5"; Sprite = "TROO"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN6"; } State { ID = "TROO_RUN6"; Sprite = "TROO"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN7"; } State { ID = "TROO_RUN7"; Sprite = "TROO"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN8"; } State { ID = "TROO_RUN8"; Sprite = "TROO"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN1"; } State { ID = "TROO_MEL1"; Sprite = "TROO"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "TROO_MEL2"; } State { ID = "TROO_MEL2"; Sprite = "TROO"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "TROO_MEL3"; } State { ID = "TROO_MEL3"; Sprite = "TROO"; Frame = 6; Tics = 6; Action = "A_TroopClaw"; Next state = "TROO_RUN1"; } State { ID = "TROO_ATK1"; Sprite = "TROO"; Frame = 8; Tics = 8; Action = "A_FaceTarget"; Next state = "TROO_ATK2"; } State { ID = "TROO_ATK2"; Sprite = "TROO"; Frame = 9; Tics = 8; Action = "A_FaceTarget"; Next state = "TROO_ATK3"; } State { ID = "TROO_ATK3"; Sprite = "TROO"; Frame = 10; Tics = 6; Action = "A_TroopAttack"; Next state = "TROO_RUN1"; } State { ID = "TROO_PAIN"; Sprite = "TROO"; Frame = 7; Tics = 2; Next state = "TROO_PAIN2"; } State { ID = "TROO_PAIN2"; Sprite = "TROO"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "TROO_RUN1"; } State { ID = "TROO_DIE1"; Sprite = "TROO"; Frame = 11; Tics = 8; Next state = "TROO_DIE2"; } State { ID = "TROO_DIE2"; Sprite = "TROO"; Frame = 12; Tics = 8; Action = "A_Scream"; Next state = "TROO_DIE3"; } State { ID = "TROO_DIE3"; Sprite = "TROO"; Frame = 13; Tics = 6; Action = "A_TrooSpecial"; Next state = "TROO_DIE4"; } State { ID = "TROO_DIE4"; Sprite = "TROO"; Frame = 14; Tics = 6; Action = "A_Fall"; Next state = "TROO_DIE5"; } State { ID = "TROO_DIE5"; Sprite = "TROO"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "TROO_XDIE1"; Sprite = "TROO"; Frame = 16; Tics = 5; Next state = "TROO_XDIE2"; } State { ID = "TROO_XDIE2"; Sprite = "TROO"; Frame = 17; Tics = 5; Action = "A_XScream"; Next state = "TROO_XDIE3"; } State { ID = "TROO_XDIE3"; Sprite = "TROO"; Frame = 18; Tics = 5; Next state = "TROO_XDIE4"; } State { ID = "TROO_XDIE4"; Sprite = "TROO"; Frame = 19; Tics = 5; Action = "A_TrooSpecial"; Next state = "TROO_XDIE5"; } State { ID = "TROO_XDIE5"; Sprite = "TROO"; Frame = 20; Tics = 5; Next state = "TROO_XDIE6"; } State { ID = "TROO_XDIE6"; Sprite = "TROO"; Frame = 21; Tics = 5; Next state = "TROO_XDIE7"; } State { ID = "TROO_XDIE7"; Sprite = "TROO"; Frame = 22; Tics = 5; Action = "A_Fall"; Next state = "TROO_XDIE8"; } State { ID = "TROO_XDIE8"; Sprite = "TROO"; Frame = 23; Tics = -1; Next state = "NULL"; } State { ID = "NTRO_STND"; Sprite = "NTRO"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "NTRO_STND2"; } State { ID = "NTRO_STND2"; Sprite = "NTRO"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "NTRO_STND"; } State { ID = "NTRO_RUN1"; Sprite = "NTRO"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN2"; } State { ID = "NTRO_RUN2"; Sprite = "NTRO"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN3"; } State { ID = "NTRO_RUN3"; Sprite = "NTRO"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN4"; } State { ID = "NTRO_RUN4"; Sprite = "NTRO"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN5"; } State { ID = "NTRO_RUN5"; Sprite = "NTRO"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN6"; } State { ID = "NTRO_RUN6"; Sprite = "NTRO"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN7"; } State { ID = "NTRO_RUN7"; Sprite = "NTRO"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN8"; } State { ID = "NTRO_RUN8"; Sprite = "NTRO"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "NTRO_RUN1"; } State { ID = "NTRO_MEL1"; Sprite = "NTRO"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "NTRO_MEL2"; } State { ID = "NTRO_MEL2"; Sprite = "NTRO"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "NTRO_MEL3"; } State { ID = "NTRO_MEL3"; Sprite = "NTRO"; Frame = 6; Tics = 6; Action = "A_TroopClaw"; Next state = "NTRO_RUN1"; } State { ID = "NTRO_ATK1"; Sprite = "NTRO"; Frame = 8; Tics = 8; Action = "A_FaceTarget"; Next state = "NTRO_ATK2"; } State { ID = "NTRO_ATK2"; Sprite = "NTRO"; Frame = 9; Tics = 8; Action = "A_FaceTarget"; Next state = "NTRO_ATK3"; } State { ID = "NTRO_ATK3"; Sprite = "NTRO"; Frame = 10; Tics = 6; Action = "A_TroopAttack"; Next state = "NTRO_RUN1"; } State { ID = "NTRO_PAIN"; Sprite = "NTRO"; Frame = 7; Tics = 2; Next state = "NTRO_PAIN2"; } State { ID = "NTRO_PAIN2"; Sprite = "NTRO"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "NTRO_RUN1"; } State { ID = "NTRO_DIE1"; Sprite = "NTRO"; Frame = 11; Tics = 8; Next state = "NTRO_DIE2"; } State { ID = "NTRO_DIE2"; Sprite = "NTRO"; Frame = 12; Tics = 8; Action = "A_Scream"; Next state = "NTRO_DIE3"; } State { ID = "NTRO_DIE3"; Sprite = "NTRO"; Frame = 13; Tics = 6; Action = "A_TrooSpecial"; Next state = "NTRO_DIE4"; } State { ID = "NTRO_DIE4"; Sprite = "NTRO"; Frame = 14; Tics = 6; Action = "A_Fall"; Next state = "NTRO_DIE5"; } State { ID = "NTRO_DIE5"; Sprite = "NTRO"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "NTRO_XDIE1"; Sprite = "NTRO"; Frame = 16; Tics = 5; Next state = "NTRO_XDIE2"; } State { ID = "NTRO_XDIE2"; Sprite = "NTRO"; Frame = 17; Tics = 5; Action = "A_XScream"; Next state = "NTRO_XDIE3"; } State { ID = "NTRO_XDIE3"; Sprite = "NTRO"; Frame = 18; Tics = 5; Next state = "NTRO_XDIE4"; } State { ID = "NTRO_XDIE4"; Sprite = "NTRO"; Frame = 19; Tics = 5; Action = "A_TrooSpecial"; Next state = "NTRO_XDIE5"; } State { ID = "NTRO_XDIE5"; Sprite = "NTRO"; Frame = 20; Tics = 5; Next state = "NTRO_XDIE6"; } State { ID = "NTRO_XDIE6"; Sprite = "NTRO"; Frame = 21; Tics = 5; Next state = "NTRO_XDIE7"; } State { ID = "NTRO_XDIE7"; Sprite = "NTRO"; Frame = 22; Tics = 5; Action = "A_Fall"; Next state = "NTRO_XDIE8"; } State { ID = "NTRO_XDIE8"; Sprite = "NTRO"; Frame = 23; Tics = -1; Next state = "NULL"; } State { ID = "HEAD_STND"; Sprite = "HEAD"; Frame = 0; Tics = 15; Action = "A_Look"; Next state = "HEAD_STND2"; } State { ID = "HEAD_STND2"; Sprite = "HEAD"; Frame = 1; Tics = 15; Action = "A_Look"; Next state = "HEAD_STND3"; } State { ID = "HEAD_STND3"; Sprite = "HEAD"; Frame = 2; Tics = 15; Action = "A_Look"; Next state = "HEAD_STND4"; } State { ID = "HEAD_STND4"; Sprite = "HEAD"; Frame = 3; Tics = 15; Action = "A_Look"; Next state = "HEAD_STND"; } State { ID = "HEAD_RUN1"; Sprite = "HEAD"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN2"; } State { ID = "HEAD_RUN2"; Sprite = "HEAD"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN3"; } State { ID = "HEAD_RUN3"; Sprite = "HEAD"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN4"; } State { ID = "HEAD_RUN4"; Sprite = "HEAD"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN5"; } State { ID = "HEAD_RUN5"; Sprite = "HEAD"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN6"; } State { ID = "HEAD_RUN6"; Sprite = "HEAD"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN7"; } State { ID = "HEAD_RUN7"; Sprite = "HEAD"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN8"; } State { ID = "HEAD_RUN8"; Sprite = "HEAD"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN1"; } State { ID = "HEAD_ATK1"; Sprite = "HEAD"; Frame = 4; Tics = 5; Action = "A_FaceTarget"; Next state = "HEAD_ATK2"; } State { ID = "HEAD_ATK2"; Sprite = "HEAD"; Frame = 5; Tics = 5; Action = "A_FaceTarget"; Next state = "HEAD_ATK3"; } State { ID = "HEAD_ATK3"; Sprite = "HEAD"; Frame = 6; Tics = 5; Action = "A_FaceTarget"; Next state = "HEAD_ATK4"; } State { ID = "HEAD_ATK4"; Sprite = "HEAD"; Frame = 6; Tics = 0; Action = "A_HeadAttack"; Next state = "HEAD_RUN1"; } State { ID = "HEAD_PAIN"; Sprite = "HEAD"; Frame = 1; Tics = 3; Next state = "HEAD_PAIN2"; } State { ID = "HEAD_PAIN2"; Sprite = "HEAD"; Frame = 1; Tics = 3; Action = "A_Pain"; Next state = "HEAD_PAIN3"; } State { ID = "HEAD_PAIN3"; Sprite = "HEAD"; Frame = 1; Tics = 6; Next state = "HEAD_RUN1"; } State { ID = "HEAD_DIE1"; Sprite = "HEAD"; Frame = 7; Tics = 8; Next state = "HEAD_DIE2"; } State { ID = "HEAD_DIE2"; Sprite = "HEAD"; Frame = 8; Tics = 8; Action = "A_Scream"; Next state = "HEAD_DIE3"; } State { ID = "HEAD_DIE3"; Sprite = "HEAD"; Frame = 9; Tics = 8; Next state = "HEAD_DIE4"; } State { ID = "HEAD_DIE4"; Sprite = "HEAD"; Frame = 10; Tics = 8; Action = "A_HeadSpecial"; Next state = "HEAD_DIE5"; } State { ID = "HEAD_DIE5"; Sprite = "HEAD"; Frame = 11; Tics = 8; Action = "A_Fall"; Next state = "HEAD_DIE6"; } State { ID = "HEAD_DIE6"; Sprite = "HEAD"; Frame = 12; Tics = -1; Next state = "NULL"; } State { ID = "BOSS_STND"; Sprite = "BOSS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BOSS_STND2"; } State { ID = "BOSS_STND2"; Sprite = "BOSS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "BOSS_STND"; } State { ID = "BOSS_RUN1"; Sprite = "BOSS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN2"; } State { ID = "BOSS_RUN2"; Sprite = "BOSS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN3"; } State { ID = "BOSS_RUN3"; Sprite = "BOSS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN4"; } State { ID = "BOSS_RUN4"; Sprite = "BOSS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN5"; } State { ID = "BOSS_RUN5"; Sprite = "BOSS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN6"; } State { ID = "BOSS_RUN6"; Sprite = "BOSS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN7"; } State { ID = "BOSS_RUN7"; Sprite = "BOSS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN8"; } State { ID = "BOSS_RUN8"; Sprite = "BOSS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN1"; } State { ID = "BOSS_ATK1"; Sprite = "BOSS"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "BOSS_ATK2"; } State { ID = "BOSS_ATK2"; Sprite = "BOSS"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "BOSS_ATK3"; } State { ID = "BOSS_ATK3"; Sprite = "BOSS"; Frame = 6; Tics = 8; Action = "A_BruisAttack"; Next state = "BOSS_RUN1"; } State { ID = "BOSS_PAIN"; Sprite = "BOSS"; Frame = 7; Tics = 2; Next state = "BOSS_PAIN2"; } State { ID = "BOSS_PAIN2"; Sprite = "BOSS"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "BOSS_RUN1"; } State { ID = "BOSS_DIE1"; Sprite = "BOSS"; Frame = 8; Tics = 8; Next state = "BOSS_DIE2"; } State { ID = "BOSS_DIE2"; Sprite = "BOSS"; Frame = 9; Tics = 8; Action = "A_Scream"; Next state = "BOSS_DIE3"; } State { ID = "BOSS_DIE3"; Sprite = "BOSS"; Frame = 10; Tics = 8; Next state = "BOSS_DIE4"; } State { ID = "BOSS_DIE4"; Sprite = "BOSS"; Frame = 11; Tics = 8; Action = "A_BossSpecial"; Next state = "BOSS_DIE5"; } State { ID = "BOSS_DIE5"; Sprite = "BOSS"; Frame = 12; Tics = 8; Action = "A_Fall"; Next state = "BOSS_DIE6"; } State { ID = "BOSS_DIE6"; Sprite = "BOSS"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "BOS2_STND"; Sprite = "BOS2"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BOS2_STND2"; } State { ID = "BOS2_STND2"; Sprite = "BOS2"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "BOS2_STND"; } State { ID = "BOS2_RUN1"; Sprite = "BOS2"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN2"; } State { ID = "BOS2_RUN2"; Sprite = "BOS2"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN3"; } State { ID = "BOS2_RUN3"; Sprite = "BOS2"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN4"; } State { ID = "BOS2_RUN4"; Sprite = "BOS2"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN5"; } State { ID = "BOS2_RUN5"; Sprite = "BOS2"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN6"; } State { ID = "BOS2_RUN6"; Sprite = "BOS2"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN7"; } State { ID = "BOS2_RUN7"; Sprite = "BOS2"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN8"; } State { ID = "BOS2_RUN8"; Sprite = "BOS2"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN1"; } State { ID = "BOS2_ATK1"; Sprite = "BOS2"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "BOS2_ATK2"; } State { ID = "BOS2_ATK2"; Sprite = "BOS2"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "BOS2_ATK3"; } State { ID = "BOS2_ATK3"; Sprite = "BOS2"; Frame = 6; Tics = 8; Action = "A_BruisAttack"; Next state = "BOS2_RUN1"; } State { ID = "BOS2_PAIN"; Sprite = "BOS2"; Frame = 7; Tics = 2; Next state = "BOS2_PAIN2"; } State { ID = "BOS2_PAIN2"; Sprite = "BOS2"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "BOS2_RUN1"; } State { ID = "BOS2_DIE1"; Sprite = "BOS2"; Frame = 8; Tics = 8; Next state = "BOS2_DIE2"; } State { ID = "BOS2_DIE2"; Sprite = "BOS2"; Frame = 9; Tics = 8; Action = "A_Scream"; Next state = "BOS2_DIE3"; } State { ID = "BOS2_DIE3"; Sprite = "BOS2"; Frame = 10; Tics = 8; Next state = "BOS2_DIE4"; } State { ID = "BOS2_DIE4"; Sprite = "BOS2"; Frame = 11; Tics = 8; Action = "A_BossSpecial"; Next state = "BOS2_DIE5"; } State { ID = "BOS2_DIE5"; Sprite = "BOS2"; Frame = 12; Tics = 8; Action = "A_Fall"; Next state = "BOS2_DIE6"; } State { ID = "BOS2_DIE6"; Sprite = "BOS2"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "SKULL_STND"; Sprite = "SKUL"; Frame = 0; Tics = 5; Action = "A_Look"; Next state = "SKULL_STND2"; } State { ID = "SKULL_STND2"; Sprite = "SKUL"; Frame = 1; Tics = 5; Action = "A_Look"; Next state = "SKULL_STND3"; } State { ID = "SKULL_STND3"; Sprite = "SKUL"; Frame = 2; Tics = 5; Action = "A_Look"; Next state = "SKULL_STND"; } State { ID = "SKULL_RUN1"; Sprite = "SKUL"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SKULL_RUN2"; } State { ID = "SKULL_RUN2"; Sprite = "SKUL"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SKULL_RUN3"; } State { ID = "SKULL_RUN3"; Sprite = "SKUL"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SKULL_RUN1"; } State { ID = "SKULL_ATK1"; Sprite = "SKUL"; Frame = 3; Tics = 6; Action = "A_FaceTarget"; Next state = "SKULL_ATK2"; } State { ID = "SKULL_ATK2"; Sprite = "SKUL"; Frame = 4; Tics = 4; Action = "A_SkullAttack"; Next state = "SKULL_ATK3"; } State { ID = "SKULL_ATK3"; Sprite = "SKUL"; Frame = 3; Tics = 4; Next state = "SKULL_ATK4"; } State { ID = "SKULL_ATK4"; Sprite = "SKUL"; Frame = 4; Tics = 4; Next state = "SKULL_ATK3"; } State { ID = "SKULL_PAIN"; Sprite = "SKUL"; Frame = 5; Tics = 3; Next state = "SKULL_PAIN2"; } State { ID = "SKULL_PAIN2"; Sprite = "SKUL"; Frame = 5; Tics = 3; Action = "A_Pain"; Next state = "SKULL_RUN1"; } State { ID = "SKULL_DIE1"; Sprite = "SKUL"; Frame = 6; Flags = fullbright; Tics = 5; Next state = "SKULL_DIE2"; } State { ID = "SKULL_DIE2"; Sprite = "SKUL"; Frame = 7; Flags = fullbright; Tics = 5; Action = "A_Scream"; Next state = "SKULL_DIE3"; } State { ID = "SKULL_DIE3"; Sprite = "SKUL"; Frame = 8; Flags = fullbright; Tics = 5; Next state = "SKULL_DIE4"; } State { ID = "SKULL_DIE4"; Sprite = "SKUL"; Frame = 9; Flags = fullbright; Tics = 5; Action = "A_Fall"; Next state = "SKULL_DIE5"; } State { ID = "SKULL_DIE5"; Sprite = "SKUL"; Frame = 10; Flags = fullbright; Tics = 4; Action = "A_SkulSpecial"; Next state = "SKULL_DIE6"; } State { ID = "SKULL_DIE6"; Sprite = "SKUL"; Frame = 11; Flags = fullbright; Tics = 3; Next state = "SKULL_DIE7"; } State { ID = "SKULL_DIE7"; Sprite = "SKUL"; Frame = 12; Flags = fullbright; Tics = 2; Next state = "SKULL_DIE8"; } State { ID = "SKULL_DIE8"; Sprite = "SKUL"; Frame = 13; Flags = fullbright; Tics = 2; Next state = "SKULL_DIE9"; } State { ID = "SKULL_DIE9"; Sprite = "SKUL"; Frame = 14; Flags = fullbright; Tics = 1; Next state = "SKULL_DIE10"; } State { ID = "SKULL_DIE10"; Sprite = "SKUL"; Frame = 15; Flags = fullbright; Tics = 1; Next state = "NULL"; } State { ID = "BSPI_STND"; Sprite = "BSPI"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BSPI_STND2"; } State { ID = "BSPI_STND2"; Sprite = "BSPI"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "BSPI_STND"; } State { ID = "BSPI_SEE"; Sprite = "BSPI"; Frame = 0; Tics = 20; Next state = "BSPI_RUN1"; } State { ID = "BSPI_RUN1"; Sprite = "BSPI"; Frame = 0; Tics = 3; Action = "A_BabyMetal"; Next state = "BSPI_RUN2"; } State { ID = "BSPI_RUN2"; Sprite = "BSPI"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN3"; } State { ID = "BSPI_RUN3"; Sprite = "BSPI"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN4"; } State { ID = "BSPI_RUN4"; Sprite = "BSPI"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN5"; } State { ID = "BSPI_RUN5"; Sprite = "BSPI"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN6"; } State { ID = "BSPI_RUN6"; Sprite = "BSPI"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN7"; } State { ID = "BSPI_RUN7"; Sprite = "BSPI"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN8"; } State { ID = "BSPI_RUN8"; Sprite = "BSPI"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN1"; } State { ID = "BSPI_ATK1"; Sprite = "BSPI"; Frame = 0; Tics = 15; Action = "A_BspiFaceTarget"; Next state = "BSPI_ATK2"; } State { ID = "BSPI_ATK2"; Sprite = "BSPI"; Frame = 4; Flags = fullbright; Tics = 6; Action = "A_BspiAttack"; Next state = "BSPI_ATK3"; } State { ID = "BSPI_ATK3"; Sprite = "BSPI"; Frame = 4; Flags = fullbright; Tics = 1; Action = "A_SpidRefire"; Next state = "BSPI_ATK2"; } State { ID = "BSPI_PAIN"; Sprite = "BSPI"; Frame = 5; Tics = 3; Next state = "BSPI_PAIN2"; } State { ID = "BSPI_PAIN2"; Sprite = "BSPI"; Frame = 5; Tics = 3; Action = "A_Pain"; Next state = "BSPI_RUN1"; } State { ID = "BSPI_DIE1"; Sprite = "BSPI"; Frame = 6; Tics = 20; Action = "A_Scream"; Next state = "BSPI_DIE2"; } State { ID = "BSPI_DIE2"; Sprite = "BSPI"; Frame = 7; Tics = 7; Action = "A_BabySpecial"; Next state = "BSPI_DIE3"; } State { ID = "BSPI_DIE3"; Sprite = "BSPI"; Frame = 8; Tics = 7; Next state = "BSPI_DIE4"; } State { ID = "BSPI_DIE4"; Sprite = "BSPI"; Frame = 9; Tics = 7; Next state = "BSPI_DIE5"; } State { ID = "BSPI_DIE5"; Sprite = "BSPI"; Frame = 10; Tics = 7; Action = "A_Fall"; Next state = "BSPI_DIE6"; } State { ID = "BSPI_DIE6"; Sprite = "BSPI"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "CYBER_STND"; Sprite = "CYBR"; Frame = 5; Tics = 10; Action = "A_Look"; Next state = "CYBER_STND"; } State { ID = "CYBER_RUN1"; Sprite = "CYBR"; Frame = 0; Tics = 4; Action = "A_Hoof"; Next state = "CYBER_RUN2"; } State { ID = "CYBER_RUN2"; Sprite = "CYBR"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "CYBER_RUN3"; } State { ID = "CYBER_RUN3"; Sprite = "CYBR"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "CYBER_RUN4"; } State { ID = "CYBER_RUN4"; Sprite = "CYBR"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "CYBER_RUN5"; } State { ID = "CYBER_RUN5"; Sprite = "CYBR"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "CYBER_RUN6"; } State { ID = "CYBER_RUN6"; Sprite = "CYBR"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "CYBER_RUN7"; } State { ID = "CYBER_RUN7"; Sprite = "CYBR"; Frame = 3; Tics = 4; Action = "A_Metal"; Next state = "CYBER_RUN8"; } State { ID = "CYBER_RUN8"; Sprite = "CYBR"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "CYBER_RUN1"; } State { ID = "CYBER_ATK1"; Sprite = "CYBR"; Frame = 4; Flags = fullbright; Tics = 6; Action = "A_FaceTarget"; Next state = "CYBER_ATK2"; } State { ID = "CYBER_ATK2"; Sprite = "CYBR"; Frame = 5; Tics = 12; Action = "A_CyberAttack"; Next state = "CYBER_ATK3"; } State { ID = "CYBER_ATK3"; Sprite = "CYBR"; Frame = 4; Flags = fullbright; Tics = 12; Action = "A_FaceTarget"; Next state = "CYBER_ATK4"; } State { ID = "CYBER_ATK4"; Sprite = "CYBR"; Frame = 5; Tics = 12; Action = "A_CyberAttack"; Next state = "CYBER_ATK5"; } State { ID = "CYBER_ATK5"; Sprite = "CYBR"; Frame = 4; Flags = fullbright; Tics = 12; Action = "A_FaceTarget"; Next state = "CYBER_ATK6"; } State { ID = "CYBER_ATK6"; Sprite = "CYBR"; Frame = 5; Tics = 12; Action = "A_CyberAttack"; Next state = "CYBER_RUN1"; } State { ID = "CYBER_PAIN"; Sprite = "CYBR"; Frame = 6; Tics = 10; Action = "A_Pain"; Next state = "CYBER_RUN1"; } State { ID = "CYBER_DIE1"; Sprite = "CYBR"; Frame = 6; Tics = 30; Action = "A_CyberDeath"; Next state = "CYBER_DIE2"; } State { ID = "CYBER_DIE2"; Sprite = "CYBR"; Frame = 7; Tics = 8; Next state = "CYBER_DIE2"; } State { ID = "CYBER_DIE3"; Sprite = "CYBR"; Frame = 8; Tics = 7; Next state = "CYBER_DIE4"; } State { ID = "CYBER_DIE4"; Sprite = "CYBR"; Frame = 9; Tics = 6; Next state = "CYBER_DIE5"; } State { ID = "CYBER_DIE5"; Sprite = "CYBR"; Frame = 10; Tics = 5; Next state = "CYBER_DIE6"; } State { ID = "CYBER_DIE6"; Sprite = "CYBR"; Frame = 11; Tics = 4; Action = "A_CybrSpecial"; Next state = "CYBER_DIE7"; } State { ID = "CYBER_DIE7"; Sprite = "CYBR"; Frame = 12; Tics = 4; Next state = "CYBER_DIE8"; } State { ID = "CYBER_DIE8"; Sprite = "CYBR"; Frame = 13; Tics = 4; Action = "A_Fall"; Next state = "CYBER_DIE9"; } State { ID = "CYBER_DIE9"; Sprite = "CYBR"; Frame = 14; Tics = -1; Next state = "NULL"; } State { ID = "DCYBER_STND"; Sprite = "CYBR"; Frame = 5; Tics = 1; Action = "A_TargetCamera"; Next state = "DCYBER_STND2"; } State { ID = "DCYBER_ATK1"; Sprite = "CYBR"; Frame = 4; Flags = fullbright; Tics = 18; Action = "A_CyberAttack"; Next state = "DCYBER_ATK2"; } State { ID = "DCYBER_ATK2"; Sprite = "CYBR"; Frame = 5; Tics = 18; Action = "A_FaceTarget"; Next state = "DCYBER_ATK1"; } State { ID = "PAIN_STND"; Sprite = "PAIN"; Frame = 0; Tics = 5; Action = "A_Look"; Next state = "PAIN_STND"; } State { ID = "PAIN_SEE"; Sprite = "PAIN"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "PAIN_SEE"; } State { ID = "PAIN_ATK1"; Sprite = "PAIN"; Frame = 1; Flags = fullbright; Tics = 5; Action = "A_FaceTarget"; Next state = "PAIN_ATK2"; } State { ID = "PAIN_ATK2"; Sprite = "PAIN"; Frame = 1; Flags = fullbright; Tics = 5; Action = "A_FaceTarget"; Next state = "PAIN_ATK3"; } State { ID = "PAIN_ATK3"; Sprite = "PAIN"; Frame = 2; Flags = fullbright; Tics = 5; Action = "A_FaceTarget"; Next state = "PAIN_ATK4"; } State { ID = "PAIN_ATK4"; Sprite = "PAIN"; Frame = 2; Flags = fullbright; Tics = 0; Action = "A_PainAttack"; Next state = "PAIN_SEE"; } State { ID = "PAIN_PAIN"; Sprite = "PAIN"; Frame = 3; Tics = 6; Next state = "PAIN_PAIN2"; } State { ID = "PAIN_PAIN2"; Sprite = "PAIN"; Frame = 3; Tics = 6; Action = "A_Pain"; Next state = "PAIN_SEE"; } State { ID = "PAIN_DIE1"; Sprite = "PAIN"; Frame = 4; Flags = fullbright; Tics = 8; Next state = "PAIN_DIE2"; } State { ID = "PAIN_DIE2"; Sprite = "PAIN"; Frame = 5; Flags = fullbright; Tics = 8; Action = "A_Scream"; Next state = "PAIN_DIE3"; } State { ID = "PAIN_DIE3"; Sprite = "PAIN"; Frame = 6; Flags = fullbright; Tics = 8; Action = "A_PainSpecial"; Next state = "PAIN_DIE4"; } State { ID = "PAIN_DIE4"; Sprite = "PAIN"; Frame = 7; Flags = fullbright; Tics = 8; Action = "A_PainDie"; Next state = "PAIN_DIE5"; } State { ID = "PAIN_DIE5"; Sprite = "PAIN"; Frame = 8; Flags = fullbright; Tics = 8; Action = "A_PainDie"; Next state = "PAIN_DIE6"; } State { ID = "PAIN_DIE6"; Sprite = "PAIN"; Frame = 9; Flags = fullbright; Tics = 8; Action = "A_PainDie"; Next state = "PAIN_DIE7"; } State { ID = "PAIN_DIE7"; Sprite = "PAIN"; Frame = 10; Flags = fullbright; Tics = 8; Next state = "PAIN_DIE8"; } State { ID = "PAIN_DIE8"; Sprite = "PAIN"; Frame = 11; Flags = fullbright; Tics = 8; Next state = "NULL"; } State { ID = "RECT_STND"; Sprite = "RECT"; Frame = 0; Tics = 8; Action = "A_Look"; Next state = "RECT_STND2"; } State { ID = "RECT_STND2"; Sprite = "RECT"; Frame = 1; Tics = 8; Action = "A_Look"; Next state = "RECT_STND3"; } State { ID = "RECT_STND3"; Sprite = "RECT"; Frame = 2; Tics = 8; Action = "A_Look"; Next state = "RECT_STND4"; } State { ID = "RECT_STND4"; Sprite = "RECT"; Frame = 3; Tics = 8; Action = "A_Look"; Next state = "RECT_STND"; } State { ID = "RECT_RUN1"; Sprite = "RECT"; Frame = 0; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN2"; } State { ID = "RECT_RUN2"; Sprite = "RECT"; Frame = 0; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN3"; } State { ID = "RECT_RUN3"; Sprite = "RECT"; Frame = 0; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN4"; } State { ID = "RECT_RUN4"; Sprite = "RECT"; Frame = 1; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN5"; } State { ID = "RECT_RUN5"; Sprite = "RECT"; Frame = 1; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN6"; } State { ID = "RECT_RUN6"; Sprite = "RECT"; Frame = 1; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN7"; } State { ID = "RECT_RUN7"; Sprite = "RECT"; Frame = 2; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN8"; } State { ID = "RECT_RUN8"; Sprite = "RECT"; Frame = 2; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN9"; } State { ID = "RECT_RUN9"; Sprite = "RECT"; Frame = 2; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN10"; } State { ID = "RECT_RUN10"; Sprite = "RECT"; Frame = 3; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN11"; } State { ID = "RECT_RUN11"; Sprite = "RECT"; Frame = 3; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN12"; } State { ID = "RECT_RUN12"; Sprite = "RECT"; Frame = 3; Tics = 3; Action = "A_RectChase"; Next state = "RECT_RUN1"; } State { ID = "RECT_ATK1"; Sprite = "RECT"; Frame = 4; Tics = 12; Action = "A_FaceTarget"; Next state = "RECT_ATK2"; } State { ID = "RECT_ATK2"; Sprite = "RECT"; Frame = 6; Tics = 12; Action = "A_MotherFloorFire"; Next state = "RECT_ATK3"; } State { ID = "RECT_ATK3"; Sprite = "RECT"; Frame = 4; Tics = 12; Action = "A_FaceTarget"; Next state = "RECT_ATK4"; } State { ID = "RECT_ATK4"; Sprite = "RECT"; Frame = 5; Tics = 12; Action = "A_MotherMissle"; Next state = "RECT_ATK5"; } State { ID = "RECT_ATK5"; Sprite = "RECT"; Frame = 4; Tics = 12; Action = "A_SpidRefire"; Next state = "RECT_ATK2"; } State { ID = "RECT_PAIN"; Sprite = "RECT"; Frame = 7; Tics = 18; Action = "A_Pain"; Next state = "RECT_ATK1"; } State { ID = "RECT_DIE1"; Sprite = "RECT"; Frame = 8; Tics = 60; Action = "A_RectSpecial"; Next state = "RECT_DIE2"; } State { ID = "RECT_DIE2"; Sprite = "RECT"; Frame = 9; Tics = 8; Next state = "RECT_DIE2"; } State { ID = "RECT_DIE3"; Sprite = "RECT"; Frame = 10; Tics = 8; Next state = "RECT_DIE4"; } State { ID = "RECT_DIE4"; Sprite = "RECT"; Frame = 11; Tics = 5; Next state = "RECT_DIE5"; } State { ID = "RECT_DIE5"; Sprite = "RECT"; Frame = 12; Tics = 4; Next state = "RECT_DIE6"; } State { ID = "RECT_DIE6"; Sprite = "RECT"; Frame = 13; Tics = 3; Action = "A_Fall"; Next state = "RECT_DIE7"; } State { ID = "RECT_DIE7"; Sprite = "RECT"; Frame = 14; Tics = 2; Next state = "NULL"; } State { ID = "BAL3"; Sprite = "BAL3"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BAL32"; } State { ID = "BAL32"; Sprite = "BAL3"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BAL33"; } State { ID = "BAL33"; Sprite = "BAL3"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "BAL3"; } State { ID = "BAL3EXP"; Sprite = "BAL3"; Frame = 3; Flags = fullbright; Tics = 2; Next state = "BAL3EXP2"; } State { ID = "BAL3EXP2"; Sprite = "BAL3"; Frame = 4; Flags = fullbright; Tics = 2; Next state = "BAL3EXP3"; } State { ID = "BAL3EXP3"; Sprite = "BAL3"; Frame = 5; Flags = fullbright; Tics = 2; Next state = "BAL3EXP4"; } State { ID = "BAL3EXP4"; Sprite = "BAL3"; Frame = 6; Flags = fullbright; Tics = 2; Next state = "BAL3EXP5"; } State { ID = "BAL3EXP5"; Sprite = "BAL3"; Frame = 7; Flags = fullbright; Tics = 2; Next state = "BAL3EXP6"; } State { ID = "BAL3EXP6"; Sprite = "BAL3"; Frame = 8; Flags = fullbright; Tics = 2; Next state = "NULL"; } State { ID = "BRBALL1"; Sprite = "BAL7"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BRBALL2"; } State { ID = "BRBALL2"; Sprite = "BAL7"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BRBALL1"; } State { ID = "BRBALLX1"; Sprite = "BAL7"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "BRBALLX2"; } State { ID = "BRBALLX2"; Sprite = "BAL7"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "BRBALLX3"; } State { ID = "BRBALLX3"; Sprite = "BAL7"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "BRBALLX4"; } State { ID = "BRBALLX4"; Sprite = "BAL7"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "BRBALLX5"; } State { ID = "BRBALLX5"; Sprite = "BAL7"; Frame = 6; Flags = fullbright; Tics = 6; Next state = "BRBALLX6"; } State { ID = "BRBALLX6"; Sprite = "BAL7"; Frame = 7; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "ARACH_PLAZ"; Sprite = "APLS"; Frame = 0; Flags = fullbright; Tics = 2; Next state = "ARACH_PLAZ2"; } State { ID = "ARACH_PLAZ2"; Sprite = "APLS"; Frame = 1; Flags = fullbright; Tics = 2; Next state = "ARACH_PLAZ"; } State { ID = "ARACH_PLEX"; Sprite = "APLS"; Frame = 2; Flags = fullbright; Tics = 3; Next state = "ARACH_PLEX2"; } State { ID = "ARACH_PLEX2"; Sprite = "APLS"; Frame = 3; Flags = fullbright; Tics = 3; Next state = "ARACH_PLEX3"; } State { ID = "ARACH_PLEX3"; Sprite = "APLS"; Frame = 4; Flags = fullbright; Tics = 3; Next state = "ARACH_PLEX4"; } State { ID = "ARACH_PLEX4"; Sprite = "APLS"; Frame = 4; Flags = fullbright; Tics = 3; Next state = "ARACH_PLEX5"; } State { ID = "ARACH_PLEX5"; Sprite = "APLS"; Frame = 6; Flags = fullbright; Tics = 3; Next state = "ARACH_PLEX6"; } State { ID = "ARACH_PLEX6"; Sprite = "APLS"; Frame = 7; Flags = fullbright; Tics = 3; Next state = "NULL"; } State { ID = "FATSHOT1"; Sprite = "MANF"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "FATSHOT2"; } State { ID = "FATSHOT2"; Sprite = "MANF"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "FATSHOT3"; } State { ID = "FATSHOT3"; Sprite = "MANF"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "FATSHOT1"; } State { ID = "FATSHOTX1"; Sprite = "MANF"; Frame = 3; Flags = fullbright; Tics = 8; Next state = "FATSHOTX2"; } State { ID = "FATSHOTX2"; Sprite = "MANF"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "FATSHOTX3"; } State { ID = "FATSHOTX3"; Sprite = "MANF"; Frame = 5; Flags = fullbright; Tics = 4; Next state = "FATSHOTX4"; } State { ID = "FATSHOTX4"; Sprite = "MANF"; Frame = 6; Flags = fullbright; Tics = 4; Next state = "FATSHOTX5"; } State { ID = "FATSHOTX5"; Sprite = "MANF"; Frame = 7; Flags = fullbright; Tics = 4; Next state = "FATSHOTX6"; } State { ID = "FATSHOTX6"; Sprite = "MANF"; Frame = 8; Flags = fullbright; Tics = 4; Next state = "NULL"; } State { ID = "TSHOT6_STND"; Sprite = "DART"; Frame = 7; Tics = 10; Action = "A_Look"; Next state = "TSHOT6_STND2"; } State { ID = "TSHOT6_STND2"; Sprite = "DART"; Frame = 7; Tics = 10; Action = "A_Look"; Next state = "TSHOT6_STND"; } State { ID = "TSHOT6_RUN1"; Sprite = "DART"; Frame = 7; Tics = 32; Action = "A_SkelMissile"; Next state = "TSHOT6_RUN2"; } State { ID = "TSHOT6_RUN2"; Sprite = "DART"; Frame = 7; Tics = 32; Action = "A_SkelMissile"; Next state = "TSHOT6_RUN3"; } State { ID = "TSHOT6_RUN3"; Sprite = "DART"; Frame = 7; Tics = 32; Action = "A_SkelMissile"; Next state = "TSHOT6_RUN4"; } State { ID = "TSHOT6_RUN4"; Sprite = "DART"; Frame = 7; Tics = 32; Action = "A_SkelMissile"; Next state = "TSHOT6_RUN5"; } State { ID = "TSHOT6_RUN5"; Sprite = "DART"; Frame = 7; Tics = 32; Action = "A_SkelMissile"; Next state = "TSHOT6_RUN6"; } State { ID = "TSHOT6_RUN6"; Sprite = "DART"; Frame = 7; Tics = 32; Action = "A_SkelMissile"; Next state = "NULL"; } State { ID = "DART"; Sprite = "DART"; Frame = 0; Flags = fullbright | noautolight; Tics = -1; Next state = "NULL"; } State { ID = "MPUFF1"; Sprite = "MPUF"; Frame = 0; Flags = fullbright; Tics = 2; Next state = "MPUFF2"; } State { ID = "MPUFF2"; Sprite = "MPUF"; Frame = 1; Flags = fullbright; Tics = 2; Next state = "MPUFF3"; } State { ID = "MPUFF3"; Sprite = "MPUF"; Frame = 2; Flags = fullbright; Tics = 2; Next state = "MPUFF4"; } State { ID = "MPUFF4"; Sprite = "MPUF"; Frame = 3; Flags = fullbright; Tics = 2; Next state = "MPUFF5"; } State { ID = "MPUFF5"; Sprite = "MPUF"; Frame = 4; Flags = fullbright; Tics = 2; Next state = "NULL"; } State { ID = "RPUFF1"; Sprite = "SMOK"; Frame = 0; Tics = 2; Next state = "RPUFF2"; } State { ID = "RPUFF2"; Sprite = "SMOK"; Frame = 1; Tics = 2; Next state = "RPUFF3"; } State { ID = "RPUFF3"; Sprite = "SMOK"; Frame = 2; Tics = 2; Next state = "RPUFF4"; } State { ID = "RPUFF4"; Sprite = "SMOK"; Frame = 3; Tics = 2; Next state = "RPUFF5"; } State { ID = "RPUFF5"; Sprite = "SMOK"; Frame = 4; Tics = 2; Next state = "NULL"; } State { ID = "SMOKE1"; Sprite = "PUFF"; Frame = 1; Tics = 4; Next state = "SMOKE2"; } State { ID = "SMOKE2"; Sprite = "PUFF"; Frame = 2; Tics = 4; Next state = "SMOKE3"; } State { ID = "SMOKE3"; Sprite = "PUFF"; Frame = 1; Tics = 4; Next state = "SMOKE4"; } State { ID = "SMOKE4"; Sprite = "PUFF"; Frame = 2; Tics = 4; Next state = "SMOKE5"; } State { ID = "SMOKE5"; Sprite = "PUFF"; Frame = 3; Tics = 4; Next state = "NULL"; } State { ID = "PUFF1"; Sprite = "PUFF"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "PUFF2"; } State { ID = "PUFF2"; Sprite = "PUFF"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "PUFF3"; } State { ID = "PUFF3"; Sprite = "PUFF"; Frame = 2; Tics = 3; Next state = "PUFF4"; } State { ID = "PUFF4"; Sprite = "PUFF"; Frame = 3; Tics = 3; Next state = "PUFF5"; } State { ID = "PUFF5"; Sprite = "PUFF"; Frame = 4; Tics = 3; Next state = "PUFF6"; } State { ID = "PUFF6"; Sprite = "PUFF"; Frame = 5; Tics = 3; Next state = "NULL"; } State { ID = "BLOOD1"; Sprite = "BLUD"; Frame = 0; Tics = 6; Next state = "BLOOD2"; } State { ID = "BLOOD2"; Sprite = "BLUD"; Frame = 1; Tics = 6; Next state = "BLOOD3"; } State { ID = "BLOOD3"; Sprite = "BLUD"; Frame = 2; Tics = 6; Next state = "BLOOD4"; } State { ID = "BLOOD4"; Sprite = "BLUD"; Frame = 3; Tics = 6; Next state = "NULL"; } State { ID = "TBALL1"; Sprite = "BAL1"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "TBALL2"; } State { ID = "TBALL2"; Sprite = "BAL1"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "TBALL3"; } State { ID = "TBALL3"; Sprite = "BAL1"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "TBALL1"; } State { ID = "TBALLX1"; Sprite = "BAL1"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "TBALLX2"; } State { ID = "TBALLX2"; Sprite = "BAL1"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "TBALLX3"; } State { ID = "TBALLX3"; Sprite = "BAL1"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "TBALLX4"; } State { ID = "TBALLX4"; Sprite = "BAL1"; Frame = 6; Flags = fullbright; Tics = 6; Next state = "TBALLX5"; } State { ID = "TBALLX5"; Sprite = "BAL1"; Frame = 7; Flags = fullbright; Tics = 6; Next state = "TBALLX6"; } State { ID = "TBALLX6"; Sprite = "BAL1"; Frame = 8; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "PLASBALL"; Sprite = "PLSS"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "PLASBALL2"; } State { ID = "PLASBALL2"; Sprite = "PLSS"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PLASBALL"; } State { ID = "PLASEXP"; Sprite = "PLSE"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "PLASEXP2"; } State { ID = "PLASEXP2"; Sprite = "PLSE"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "PLASEXP3"; } State { ID = "PLASEXP3"; Sprite = "PLSE"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "PLASEXP4"; } State { ID = "PLASEXP4"; Sprite = "PLSE"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "PLASEXP5"; } State { ID = "PLASEXP5"; Sprite = "PLSE"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "PLASEXP6"; } State { ID = "PLASEXP6"; Sprite = "PLSE"; Frame = 5; Flags = fullbright; Tics = 4; Next state = "NULL"; } State { ID = "ROCKET"; Sprite = "MISL"; Frame = 0; Tics = 2; Next state = "ROCKET2"; } State { ID = "ROCKET2"; Sprite = "MISL"; Frame = 0; Tics = 1; Action = "A_Rocketpuff"; Next state = "ROCKET"; } State { ID = "BFGSHOT"; Sprite = "BFS1"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BFGSHOT2"; } State { ID = "BFGSHOT2"; Sprite = "BFS1"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BFGSHOT"; } State { ID = "BFGLAND"; Sprite = "BFE1"; Frame = 0; Flags = fullbright; Tics = 8; Next state = "BFGLAND2"; } State { ID = "BFGLAND2"; Sprite = "BFE1"; Frame = 1; Flags = fullbright; Tics = 8; Next state = "BFGLAND3"; } State { ID = "BFGLAND3"; Sprite = "BFE1"; Frame = 2; Flags = fullbright; Tics = 8; Action = "A_BFGSpray"; Next state = "BFGLAND4"; } State { ID = "BFGLAND4"; Sprite = "BFE1"; Frame = 3; Flags = fullbright; Tics = 8; Next state = "BFGLAND5"; } State { ID = "BFGLAND5"; Sprite = "BFE1"; Frame = 4; Flags = fullbright; Tics = 8; Next state = "BFGLAND6"; } State { ID = "BFGLAND6"; Sprite = "BFE1"; Frame = 5; Flags = fullbright; Tics = 8; Next state = "NULL"; } State { ID = "BFGEXP"; Sprite = "BFE2"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BFGEXP2"; } State { ID = "BFGEXP2"; Sprite = "BFE2"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "BFGEXP3"; } State { ID = "BFGEXP3"; Sprite = "BFE2"; Frame = 2; Flags = fullbright; Tics = 2; Next state = "BFGEXP4"; } State { ID = "BFGEXP4"; Sprite = "BFE2"; Frame = 3; Flags = fullbright; Tics = 2; Next state = "BFGEXP5"; } State { ID = "BFGEXP5"; Sprite = "BFE2"; Frame = 4; Flags = fullbright; Tics = 2; Next state = "BFGEXP6"; } State { ID = "BFGEXP6"; Sprite = "BFE2"; Frame = 5; Flags = fullbright; Tics = 2; Next state = "NULL"; } State { ID = "EXPLODE0"; Sprite = "MISL"; Frame = 0; Flags = fullbright; Next state = "EXPLODE1"; } State { ID = "EXPLODE1"; Sprite = "MISL"; Frame = 1; Flags = fullbright; Tics = 8; Action = "A_Explode"; Next state = "EXPLODE2"; } State { ID = "EXPLODE2"; Sprite = "MISL"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "EXPLODE3"; } State { ID = "EXPLODE3"; Sprite = "MISL"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "EXPLODE4"; } State { ID = "EXPLODE4"; Sprite = "MISL"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "EXPLODE5"; } State { ID = "EXPLODE5"; Sprite = "MISL"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "NULL"; } State { ID = "TFOG"; Sprite = "TFOG"; Frame = 4; Flags = fullbright; Tics = 3; Next state = "TFOG2"; } State { ID = "TFOG2"; Sprite = "TFOG"; Frame = 3; Flags = fullbright; Tics = 3; Next state = "TFOG3"; } State { ID = "TFOG3"; Sprite = "TFOG"; Frame = 2; Flags = fullbright; Tics = 3; Next state = "TFOG4"; } State { ID = "TFOG4"; Sprite = "TFOG"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "TFOG5"; } State { ID = "TFOG5"; Sprite = "TFOG"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "TFOG6"; } State { ID = "TFOG6"; Sprite = "TFOG"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "TFOG7"; } State { ID = "TFOG7"; Sprite = "TFOG"; Frame = 2; Flags = fullbright; Tics = 3; Next state = "TFOG8"; } State { ID = "TFOG8"; Sprite = "TFOG"; Frame = 3; Flags = fullbright; Tics = 3; Next state = "TFOG9"; } State { ID = "TFOG9"; Sprite = "TFOG"; Frame = 4; Flags = fullbright; Tics = 3; Next state = "TFOG10"; } State { ID = "TFOG10"; Sprite = "TFOG"; Frame = 5; Flags = fullbright; Tics = 3; Next state = "TFOG11"; } State { ID = "TFOG11"; Sprite = "TFOG"; Frame = 6; Flags = fullbright; Tics = 3; Next state = "TFOG12"; } State { ID = "TFOG12"; Sprite = "TFOG"; Frame = 7; Flags = fullbright; Tics = 3; Next state = "NULL"; } State { ID = "ARM1"; Sprite = "ARM1"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "ARM1A"; } State { ID = "ARM1A"; Sprite = "ARM1"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "ARM1"; } State { ID = "ARM2"; Sprite = "ARM2"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "ARM2A"; } State { ID = "ARM2A"; Sprite = "ARM2"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "ARM2"; } State { ID = "BON1"; Sprite = "BON1"; Frame = 0; Tics = 3; Next state = "BON1A"; } State { ID = "BON1A"; Sprite = "BON1"; Frame = 1; Tics = 3; Next state = "BON1B"; } State { ID = "BON1B"; Sprite = "BON1"; Frame = 2; Tics = 3; Next state = "BON1C"; } State { ID = "BON1C"; Sprite = "BON1"; Frame = 3; Tics = 3; Next state = "BON1"; } State { ID = "BON2"; Sprite = "BON2"; Frame = 0; Tics = 3; Next state = "BON2A"; } State { ID = "BON2A"; Sprite = "BON2"; Frame = 1; Tics = 3; Next state = "BON2B"; } State { ID = "BON2B"; Sprite = "BON2"; Frame = 2; Tics = 3; Next state = "BON2C"; } State { ID = "BON2C"; Sprite = "BON2"; Frame = 2; Tics = 3; Next state = "BON2D"; } State { ID = "BON2D"; Sprite = "BON2"; Frame = 2; Tics = 3; Next state = "BON2E"; } State { ID = "BON2E"; Sprite = "BON2"; Frame = 1; Tics = 3; Next state = "BON2"; } State { ID = "BKEY"; Sprite = "BKEY"; Frame = 0; Tics = 5; Next state = "BKEY2"; } State { ID = "BKEY2"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "BKEY"; } State { ID = "RKEY"; Sprite = "RKEY"; Frame = 0; Tics = 5; Next state = "RKEY2"; } State { ID = "RKEY2"; Sprite = "RKEY"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "RKEY"; } State { ID = "YKEY"; Sprite = "YKEY"; Frame = 0; Tics = 5; Next state = "YKEY2"; } State { ID = "YKEY2"; Sprite = "YKEY"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "YKEY"; } State { ID = "YSKULL"; Sprite = "YSKU"; Frame = 0; Tics = 5; Next state = "YSKULL2"; } State { ID = "YSKULL2"; Sprite = "YSKU"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "YSKULL"; } State { ID = "RSKULL"; Sprite = "RSKU"; Frame = 0; Tics = 5; Next state = "RSKULL2"; } State { ID = "RSKULL2"; Sprite = "RSKU"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "RSKULL"; } State { ID = "BSKULL"; Sprite = "BSKU"; Frame = 0; Tics = 5; Next state = "BSKULL2"; } State { ID = "BSKULL2"; Sprite = "BSKU"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "BSKULL"; } State { ID = "ART1"; Sprite = "ART1"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "ART12"; } State { ID = "ART12"; Sprite = "ART1"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "ART13"; } State { ID = "ART13"; Sprite = "ART1"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "ART14"; } State { ID = "ART14"; Sprite = "ART1"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "ART15"; } State { ID = "ART15"; Sprite = "ART1"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "ART16"; } State { ID = "ART16"; Sprite = "ART1"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "ART17"; } State { ID = "ART17"; Sprite = "ART1"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "ART18"; } State { ID = "ART18"; Sprite = "ART1"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "ART1"; } State { ID = "ART2"; Sprite = "ART2"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "ART22"; } State { ID = "ART22"; Sprite = "ART2"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "ART23"; } State { ID = "ART23"; Sprite = "ART2"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "ART24"; } State { ID = "ART24"; Sprite = "ART2"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "ART25"; } State { ID = "ART25"; Sprite = "ART2"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "ART26"; } State { ID = "ART26"; Sprite = "ART2"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "ART27"; } State { ID = "ART27"; Sprite = "ART2"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "ART28"; } State { ID = "ART28"; Sprite = "ART2"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "ART2"; } State { ID = "ART3"; Sprite = "ART3"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "ART32"; } State { ID = "ART32"; Sprite = "ART3"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "ART33"; } State { ID = "ART33"; Sprite = "ART3"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "ART34"; } State { ID = "ART34"; Sprite = "ART3"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "ART35"; } State { ID = "ART35"; Sprite = "ART3"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "ART36"; } State { ID = "ART36"; Sprite = "ART3"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "ART37"; } State { ID = "ART37"; Sprite = "ART3"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "ART38"; } State { ID = "ART38"; Sprite = "ART3"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "ART3"; } State { ID = "STIM"; Sprite = "STIM"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEDI"; Sprite = "MEDI"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SOUL"; Sprite = "SOUL"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "SOUL2"; } State { ID = "SOUL2"; Sprite = "SOUL"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "SOUL3"; } State { ID = "SOUL3"; Sprite = "SOUL"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "SOUL4"; } State { ID = "SOUL4"; Sprite = "SOUL"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "SOUL5"; } State { ID = "SOUL5"; Sprite = "SOUL"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "SOUL6"; } State { ID = "SOUL6"; Sprite = "SOUL"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "SOUL"; } State { ID = "PINV"; Sprite = "PINV"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "PINV2"; } State { ID = "PINV2"; Sprite = "PINV"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PINV3"; } State { ID = "PINV3"; Sprite = "PINV"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "PINV4"; } State { ID = "PINV4"; Sprite = "PINV"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "PINV5"; } State { ID = "PINV5"; Sprite = "PINV"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "PINV6"; } State { ID = "PINV6"; Sprite = "PINV"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PINV"; } State { ID = "PSTR"; Sprite = "PSTR"; Frame = 0; Flags = fullbright | noautolight; Tics = -1; Next state = "NULL"; } State { ID = "PINS"; Sprite = "PINS"; Frame = 0; Flags = fullbright; Tics = 2; Next state = "PINS2"; } State { ID = "PINS2"; Sprite = "PINS"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "PINS3"; } State { ID = "PINS3"; Sprite = "PINS"; Frame = 2; Flags = fullbright; Tics = 2; Next state = "PINS4"; } State { ID = "PINS4"; Sprite = "PINS"; Frame = 3; Flags = fullbright; Tics = 1; Next state = "PINS5"; } State { ID = "PINS5"; Sprite = "PINS"; Frame = 1; Flags = fullbright; Tics = 2; Next state = "PINS6"; } State { ID = "PINS6"; Sprite = "PINS"; Frame = 2; Flags = fullbright; Tics = 1; Next state = "PINS"; } State { ID = "SUIT"; Sprite = "SUIT"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "SUIT2"; } State { ID = "SUIT2"; Sprite = "SUIT"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "SUIT"; } State { ID = "PMAP"; Sprite = "PMAP"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "PMAP2"; } State { ID = "PMAP2"; Sprite = "PMAP"; Frame = 1; Flags = fullbright; Tics = 5; Next state = "PMAP3"; } State { ID = "PMAP3"; Sprite = "PMAP"; Frame = 2; Flags = fullbright; Tics = 5; Next state = "PMAP4"; } State { ID = "PMAP4"; Sprite = "PMAP"; Frame = 3; Flags = fullbright; Tics = 5; Next state = "PMAP"; } State { ID = "PVIS"; Sprite = "PVIS"; Frame = 0; Flags = fullbright | noautolight; Tics = 3; Next state = "PVIS2"; } State { ID = "PVIS2"; Sprite = "PVIS"; Frame = 1; Tics = 3; Next state = "PVIS"; } State { ID = "MEGA"; Sprite = "MEGA"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "MEGA2"; } State { ID = "MEGA2"; Sprite = "MEGA"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "MEGA3"; } State { ID = "MEGA3"; Sprite = "MEGA"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "MEGA4"; } State { ID = "MEGA4"; Sprite = "MEGA"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "MEGA5"; } State { ID = "MEGA5"; Sprite = "MEGA"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "MEGA6"; } State { ID = "MEGA6"; Sprite = "MEGA"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "MEGA"; } State { ID = "CLIP"; Sprite = "CLIP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "AMMO"; Sprite = "AMMO"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "RCKT"; Sprite = "RCKT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BROK"; Sprite = "BROK"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CELL"; Sprite = "CELL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CELP"; Sprite = "CELP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHEL"; Sprite = "SHEL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SBOX"; Sprite = "SBOX"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BPAK"; Sprite = "BPAK"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BFUG"; Sprite = "BFUG"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CSAW"; Sprite = "CSAW"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MGUN"; Sprite = "MGUN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "LAUN"; Sprite = "LAUN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PLSM"; Sprite = "PLSM"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHOT"; Sprite = "SHOT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHOT2"; Sprite = "SGN2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "LSRG"; Sprite = "LSRG"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CANDLE"; Sprite = "CAND"; Frame = 0; Tics = 2; Next state = "CANDLE2"; } State { ID = "CANDLE2"; Sprite = "CAND"; Frame = 1; Tics = 2; Next state = "CANDLE"; } State { ID = "BAR1"; Sprite = "BAR1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BAR2"; Sprite = "BAR1"; Frame = 1; Tics = 5; Next state = "BAR3"; } State { ID = "BAR3"; Sprite = "BAR1"; Frame = 2; Tics = 5; Next state = "BAR4"; } State { ID = "BAR4"; Sprite = "BAR1"; Frame = 3; Tics = 5; Next state = "BAR5"; } State { ID = "BAR5"; Sprite = "BAR1"; Frame = 4; Flags = fullbright; Tics = 5; Action = "A_BarrelExplode"; Next state = "NULL"; } State { ID = "SAW"; Sprite = "SAWG"; Frame = 0; Tics = 4; Action = "A_WeaponReady"; Next state = "SAWB"; } State { ID = "SAWB"; Sprite = "SAWG"; Frame = 1; Tics = 4; Action = "A_WeaponReady"; Next state = "SAW"; } State { ID = "SAWDOWN"; Sprite = "SAWG"; Frame = 1; Tics = 1; Action = "A_Lower"; Next state = "SAWDOWN"; } State { ID = "SAWUP"; Sprite = "SAWG"; Frame = 1; Tics = 1; Action = "A_Raise"; Next state = "SAWUP"; } State { ID = "SAW1"; Sprite = "SAWG"; Frame = 2; Tics = 2; Action = "A_Saw"; Next state = "SAW2"; } State { ID = "SAW2"; Sprite = "SAWG"; Frame = 3; Tics = 2; Action = "A_Saw"; Next state = "SAW3"; } State { ID = "SAW3"; Sprite = "SAWG"; Frame = 3; Tics = 0; Action = "A_ReFire"; Next state = "SAW"; } State { ID = "PUNCH"; Sprite = "PUNG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PUNCH"; } State { ID = "PUNCHDOWN"; Sprite = "PUNG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PUNCHDOWN"; } State { ID = "PUNCHUP"; Sprite = "PUNG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PUNCHUP"; } State { ID = "PUNCH1"; Sprite = "PUNG"; Frame = 1; Tics = 4; Next state = "PUNCH2"; } State { ID = "PUNCH2"; Sprite = "PUNG"; Frame = 2; Tics = 4; Action = "A_Punch"; Next state = "PUNCH3"; } State { ID = "PUNCH3"; Sprite = "PUNG"; Frame = 3; Tics = 5; Next state = "PUNCH4"; } State { ID = "PUNCH4"; Sprite = "PUNG"; Frame = 2; Tics = 4; Next state = "PUNCH5"; } State { ID = "PUNCH5"; Sprite = "PUNG"; Frame = 1; Tics = 5; Action = "A_ReFire"; Next state = "PUNCH"; } State { ID = "PISTOL"; Sprite = "PISG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PISTOL"; } State { ID = "PISTOLDOWN"; Sprite = "PISG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PISTOLDOWN"; } State { ID = "PISTOLUP"; Sprite = "PISG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PISTOLUP"; } State { ID = "PISTOL1"; Sprite = "PISG"; Frame = 0; Tics = 2; Next state = "PISTOL2"; } State { ID = "PISTOL2"; Sprite = "PISG"; Frame = 1; Tics = 1; Action = "A_FirePistol"; Next state = "PISTOL3"; } State { ID = "PISTOL3"; Sprite = "PISG"; Frame = 2; Tics = 5; Next state = "PISTOL4"; } State { ID = "PISTOL4"; Sprite = "PISG"; Frame = 1; Tics = 5; Next state = "PISTOL5"; } State { ID = "PISTOL5"; Sprite = "PISG"; Frame = 1; Tics = 1; Action = "A_ReFire"; Next state = "PISTOL"; } State { ID = "PISTOLFLASH"; Sprite = "PISG"; Frame = 3; Flags = fullbright; Tics = 3; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "SGUN"; Sprite = "SHT1"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "SGUN"; } State { ID = "SGUNDOWN"; Sprite = "SHT1"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "SGUNDOWN"; } State { ID = "SGUNUP"; Sprite = "SHT1"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "SGUNUP"; } State { ID = "SGUN1"; Sprite = "SHT1"; Frame = 0; Tics = 2; Next state = "SGUN2"; } State { ID = "SGUN2"; Sprite = "SHT1"; Frame = 0; Tics = 4; Action = "A_FireShotgun"; Next state = "SGUN3"; } State { ID = "SGUN3"; Sprite = "SHT1"; Frame = 1; Tics = 18; Next state = "SGUN6"; } State { ID = "SGUN4"; Sprite = "SHT1"; Frame = 2; Tics = 5; Next state = "SGUN5"; } State { ID = "SGUN5"; Sprite = "SHT1"; Frame = 0; Tics = 3; Next state = "SGUN6"; } State { ID = "SGUN6"; Sprite = "SHT1"; Frame = 0; Tics = 7; Action = "A_ReFire"; Next state = "SGUN"; } State { ID = "SGUNFLASH1"; Sprite = "SHT1"; Frame = 3; Flags = fullbright; Tics = 4; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "DSGUN"; Sprite = "SHT2"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "DSGUN"; } State { ID = "DSGUNDOWN"; Sprite = "SHT2"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "DSGUNDOWN"; } State { ID = "DSGUNUP"; Sprite = "SHT2"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "DSGUNUP"; } State { ID = "DSGUN1"; Sprite = "SHT2"; Frame = 0; Tics = 1; Next state = "DSGUN2"; } State { ID = "DSGUN2"; Sprite = "SHT2"; Frame = 0; Tics = 4; Action = "A_FireShotgun2"; Next state = "DSGUN3"; } State { ID = "DSGUN3"; Sprite = "SHT2"; Frame = 1; Tics = 7; Next state = "DSGUN4"; } State { ID = "DSGUN4"; Sprite = "SHT2"; Frame = 1; Tics = 5; Action = "A_CheckReload"; Next state = "DSGUN5"; } State { ID = "DSGUN5"; Sprite = "SHT2"; Frame = 1; Tics = 5; Next state = "DSGUN6"; } State { ID = "DSGUN6"; Sprite = "SHT2"; Frame = 1; Tics = 5; Next state = "DSGUN7"; } State { ID = "DSGUN7"; Sprite = "SHT2"; Frame = 1; Tics = 5; Next state = "DSGUN8"; } State { ID = "DSGUN8"; Sprite = "SHT2"; Frame = 1; Tics = 5; Action = "A_OpenShotgun2"; Next state = "DSGUN9"; } State { ID = "DSGUN9"; Sprite = "SHT2"; Frame = 2; Tics = 4; Action = "A_LoadShotgun2"; Next state = "DSGUN10"; } State { ID = "DSGUN10"; Sprite = "SHT2"; Frame = 0; Tics = 5; Action = "A_ReFire"; Next state = "DSGUN"; } State { ID = "DSGUNFLASH1"; Sprite = "SHT2"; Frame = 3; Flags = fullbright; Tics = 4; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "CHAIN"; Sprite = "CHGG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CHAIN"; } State { ID = "CHAINDOWN"; Sprite = "CHGG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "CHAINDOWN"; } State { ID = "CHAINUP"; Sprite = "CHGG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "CHAINUP"; } State { ID = "CHAIN1"; Sprite = "CHGG"; Frame = 0; Tics = 3; Action = "A_FireCGun"; Next state = "CHAIN2"; } State { ID = "CHAIN2"; Sprite = "CHGG"; Frame = 1; Tics = 3; Action = "A_FireCGun"; Next state = "CHAIN3"; } State { ID = "CHAIN3"; Sprite = "CHGG"; Frame = 1; Tics = 0; Action = "A_ReFire"; Next state = "CHAIN"; } State { ID = "CHAINFLASH1"; Sprite = "CHGG"; Frame = 3; Flags = fullbright; Tics = 3; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "CHAINFLASH2"; Sprite = "CHGG"; Frame = 2; Flags = fullbright; Tics = 3; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "MISSILE"; Sprite = "ROCK"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MISSILE"; } State { ID = "MISSILEDOWN"; Sprite = "ROCK"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "MISSILEDOWN"; } State { ID = "MISSILEUP"; Sprite = "ROCK"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "MISSILEUP"; } State { ID = "MISSILE1"; Sprite = "ROCK"; Frame = 1; Tics = 8; Action = "A_GunFlash"; Next state = "MISSILE2"; } State { ID = "MISSILE2"; Sprite = "ROCK"; Frame = 1; Tics = 10; Action = "A_FireMissile"; Next state = "MISSILE3"; } State { ID = "MISSILE3"; Sprite = "ROCK"; Frame = 1; Tics = 0; Action = "A_ReFire"; Next state = "MISSILE"; } State { ID = "MISSILEFLASH1"; Sprite = "ROCK"; Frame = 2; Flags = fullbright; Tics = 3; Action = "A_Light1"; Next state = "MISSILEFLASH2"; } State { ID = "MISSILEFLASH2"; Sprite = "ROCK"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "MISSILEFLASH3"; } State { ID = "MISSILEFLASH3"; Sprite = "ROCK"; Frame = 4; Flags = fullbright; Tics = 4; Action = "A_Light2"; Next state = "MISSILEFLASH4"; } State { ID = "MISSILEFLASH4"; Sprite = "ROCK"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "PLASMA"; Sprite = "PLAS"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PLASMA"; } State { ID = "PLASMADOWN"; Sprite = "PLAS"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PLASMADOWN"; } State { ID = "PLASMAUP"; Sprite = "PLAS"; Frame = 0; Tics = 0; Action = "A_PlasmaShock"; Next state = "PLASMAUP2"; } State { ID = "PLASMAUP2"; Sprite = "PLAS"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PLASMAUP2"; } State { ID = "PLASMA1"; Sprite = "PLAS"; Frame = 4; Flags = fullbright; Tics = 2; Action = "A_FirePlasma"; Next state = "PLASMA2"; } State { ID = "PLASMA2"; Sprite = "PLAS"; Frame = 0; Tics = 2; Action = "A_PlasmaShock"; Next state = "PLASMA3"; } State { ID = "PLASMA3"; Sprite = "PLAS"; Frame = 0; Tics = 1; Action = "A_ReFire"; Next state = "PLASMA"; } State { ID = "PLASMASHOCK1"; Sprite = "PLAS"; Frame = 1; Tics = 2; Next state = "PLASMASHOCK2"; } State { ID = "PLASMASHOCK2"; Sprite = "PLAS"; Frame = 2; Tics = 2; Next state = "PLASMASHOCK3"; } State { ID = "PLASMASHOCK3"; Sprite = "PLAS"; Frame = 3; Tics = 2; Next state = "PLASMASHOCK1"; } State { ID = "BFG"; Sprite = "BFGG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "BFG"; } State { ID = "BFGDOWN"; Sprite = "BFGG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "BFGDOWN"; } State { ID = "BFGUP"; Sprite = "BFGG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "BFGUP"; } State { ID = "BFG1"; Sprite = "BFGG"; Frame = 0; Tics = 20; Action = "A_BFGsound"; Next state = "BFG2"; } State { ID = "BFG2"; Sprite = "BFGG"; Frame = 1; Tics = 10; Action = "A_GunFlash"; Next state = "BFG3"; } State { ID = "BFG3"; Sprite = "BFGG"; Frame = 1; Tics = 10; Action = "A_FireBFG"; Next state = "BFG4"; } State { ID = "BFG4"; Sprite = "BFGG"; Frame = 1; Tics = 20; Action = "A_ReFire"; Next state = "BFG"; } State { ID = "BFGFLASH1"; Sprite = "BFGG"; Frame = 2; Flags = fullbright; Tics = 8; Action = "A_Light1"; Next state = "BFGFLASH2"; } State { ID = "BFGFLASH2"; Sprite = "BFGG"; Frame = 3; Flags = fullbright; Tics = 5; Action = "A_Light2"; Next state = "BFGFLASH3"; } State { ID = "BFGFLASH3"; Sprite = "BFGG"; Frame = 4; Flags = fullbright; Tics = 3; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "UNKF"; Sprite = "LASR"; Frame = 0; Tics = 2; Action = "A_WeaponReady"; Next state = "UNKF"; } State { ID = "UNKFDOWN"; Sprite = "LASR"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "UNKFDOWN"; } State { ID = "UNKFUP"; Sprite = "LASR"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "UNKFUP"; } State { ID = "UNKF1"; Sprite = "LASR"; Frame = 0; Tics = 8; Action = "A_FireSingleLaser"; Next state = "UNKF2"; } State { ID = "UNKF2"; Sprite = "LASR"; Frame = 0; Tics = 3; Action = "A_ReFire"; Next state = "UNKF"; } State { ID = "UNKFLASH1"; Sprite = "LASR"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "LIGHTDONE"; } State { ID = "COLU"; Sprite = "COLU"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "DARTHIT"; Sprite = "DART"; Frame = 1; Tics = 4; Next state = "DARTHIT2"; } State { ID = "DARTHIT2"; Sprite = "DART"; Frame = 2; Tics = 4; Next state = "DARTHIT3"; } State { ID = "DARTHIT3"; Sprite = "DART"; Frame = 3; Tics = 4; Next state = "DARTHIT4"; } State { ID = "DARTHIT4"; Sprite = "DART"; Frame = 4; Tics = 4; Next state = "DARTHIT5"; } State { ID = "DARTHIT5"; Sprite = "DART"; Frame = 5; Tics = 4; Next state = "DARTHIT6"; } State { ID = "DARTHIT6"; Sprite = "DART"; Frame = 6; Tics = 4; Next state = "NULL"; } State { ID = "BLOODYTWITCH"; Sprite = "GOR1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEADTORSO"; Sprite = "PLAY"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "DEADBOTTOM"; Sprite = "PLAY"; Frame = 18; Tics = -1; Next state = "NULL"; } State { ID = "HEADSONSTICK"; Sprite = "POL2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "GIBS"; Sprite = "POL5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HEADONASTICK"; Sprite = "POL4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HEADCANDLES"; Sprite = "POL3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEADSTICK"; Sprite = "POL1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "LIVESTICK"; Sprite = "POL6"; Frame = 0; Tics = 6; Next state = "LIVESTICK2"; } State { ID = "LIVESTICK2"; Sprite = "POL6"; Frame = 1; Tics = 8; Next state = "LIVESTICK"; } State { ID = "MEAT2"; Sprite = "GOR2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEAT3"; Sprite = "GOR3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEAT4"; Sprite = "GOR4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEAT5"; Sprite = "GOR5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "STALAGTITE"; Sprite = "SMIT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TALLGRNCOL"; Sprite = "COL1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHRTGRNCOL"; Sprite = "COL2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TALLREDCOL"; Sprite = "COL3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHRTREDCOL"; Sprite = "COL4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CANDELABRA"; Sprite = "CBRA"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SKULLCOL"; Sprite = "COL6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TORCHTREE"; Sprite = "TRE1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BIGTREE"; Sprite = "TRE2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TECHPILLAR"; Sprite = "ELEC"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "BLUETORCH"; Sprite = "TBLU"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BLUETORCH2"; } State { ID = "BLUETORCH2"; Sprite = "TBLU"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BLUETORCH3"; } State { ID = "BLUETORCH3"; Sprite = "TBLU"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "BLUETORCH4"; } State { ID = "BLUETORCH4"; Sprite = "TBLU"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "BLUETORCH"; } State { ID = "GREENTORCH"; Sprite = "TGRN"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "GREENTORCH2"; } State { ID = "GREENTORCH2"; Sprite = "TGRN"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "GREENTORCH3"; } State { ID = "GREENTORCH3"; Sprite = "TGRN"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "GREENTORCH4"; } State { ID = "GREENTORCH4"; Sprite = "TGRN"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "GREENTORCH"; } State { ID = "REDTORCH"; Sprite = "TRED"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "REDTORCH2"; } State { ID = "REDTORCH2"; Sprite = "TRED"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "REDTORCH3"; } State { ID = "REDTORCH3"; Sprite = "TRED"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "REDTORCH4"; } State { ID = "REDTORCH4"; Sprite = "TRED"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "REDTORCH"; } State { ID = "BTORCHSHRT"; Sprite = "SMBT"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT2"; } State { ID = "BTORCHSHRT2"; Sprite = "SMBT"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT3"; } State { ID = "BTORCHSHRT3"; Sprite = "SMBT"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT4"; } State { ID = "BTORCHSHRT4"; Sprite = "SMBT"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT5"; } State { ID = "BTORCHSHRT5"; Sprite = "SMBT"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT"; } State { ID = "GTORCHSHRT"; Sprite = "SMGT"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT2"; } State { ID = "GTORCHSHRT2"; Sprite = "SMGT"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT3"; } State { ID = "GTORCHSHRT3"; Sprite = "SMGT"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT4"; } State { ID = "GTORCHSHRT4"; Sprite = "SMGT"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT5"; } State { ID = "GTORCHSHRT5"; Sprite = "SMGT"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT"; } State { ID = "RTORCHSHRT"; Sprite = "SMRT"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT2"; } State { ID = "RTORCHSHRT2"; Sprite = "SMRT"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT3"; } State { ID = "RTORCHSHRT3"; Sprite = "SMRT"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT4"; } State { ID = "RTORCHSHRT4"; Sprite = "SMRT"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT5"; } State { ID = "RTORCHSHRT5"; Sprite = "SMRT"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT"; } State { ID = "YFIREBALL1"; Sprite = "FIRE"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "YFIREBALL2"; } State { ID = "YFIREBALL2"; Sprite = "FIRE"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "YFIREBALL3"; } State { ID = "YFIREBALL3"; Sprite = "FIRE"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "YFIREBALL4"; } State { ID = "YFIREBALL4"; Sprite = "FIRE"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "YFIREBALL5"; } State { ID = "YFIREBALL5"; Sprite = "FIRE"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "YFIREBALL1"; } State { ID = "BFIREBALL1"; Sprite = "TBLU"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "BFIREBALL2"; } State { ID = "BFIREBALL2"; Sprite = "TBLU"; Frame = 5; Flags = fullbright; Tics = 4; Next state = "BFIREBALL3"; } State { ID = "BFIREBALL3"; Sprite = "TBLU"; Frame = 6; Flags = fullbright; Tics = 4; Next state = "BFIREBALL4"; } State { ID = "BFIREBALL4"; Sprite = "TBLU"; Frame = 7; Flags = fullbright; Tics = 4; Next state = "BFIREBALL1"; } State { ID = "RFIREBALL1"; Sprite = "TRED"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "RFIREBALL2"; } State { ID = "RFIREBALL2"; Sprite = "TRED"; Frame = 5; Flags = fullbright; Tics = 4; Next state = "RFIREBALL3"; } State { ID = "RFIREBALL3"; Sprite = "TRED"; Frame = 6; Flags = fullbright; Tics = 4; Next state = "RFIREBALL4"; } State { ID = "RFIREBALL4"; Sprite = "TRED"; Frame = 7; Flags = fullbright; Tics = 4; Next state = "RFIREBALL1"; } State { ID = "Y2FIREBALL1"; Sprite = "TGRN"; Frame = 8; Flags = fullbright; Tics = 4; Next state = "Y2FIREBALL2"; } State { ID = "Y2FIREBALL2"; Sprite = "TGRN"; Frame = 9; Flags = fullbright; Tics = 4; Next state = "Y2FIREBALL3"; } State { ID = "Y2FIREBALL3"; Sprite = "TGRN"; Frame = 10; Flags = fullbright; Tics = 4; Next state = "Y2FIREBALL4"; } State { ID = "Y2FIREBALL4"; Sprite = "TGRN"; Frame = 11; Flags = fullbright; Tics = 4; Next state = "Y2FIREBALL1"; } State { ID = "B2FIREBALL1"; Sprite = "TBLU"; Frame = 8; Flags = fullbright; Tics = 4; Next state = "B2FIREBALL2"; } State { ID = "B2FIREBALL2"; Sprite = "TBLU"; Frame = 9; Flags = fullbright; Tics = 4; Next state = "B2FIREBALL3"; } State { ID = "B2FIREBALL3"; Sprite = "TBLU"; Frame = 10; Flags = fullbright; Tics = 4; Next state = "B2FIREBALL4"; } State { ID = "B2FIREBALL4"; Sprite = "TBLU"; Frame = 11; Flags = fullbright; Tics = 4; Next state = "B2FIREBALL1"; } State { ID = "R2FIREBALL1"; Sprite = "TRED"; Frame = 8; Flags = fullbright; Tics = 4; Next state = "R2FIREBALL2"; } State { ID = "R2FIREBALL2"; Sprite = "TRED"; Frame = 9; Flags = fullbright; Tics = 4; Next state = "R2FIREBALL3"; } State { ID = "R2FIREBALL3"; Sprite = "TRED"; Frame = 10; Flags = fullbright; Tics = 4; Next state = "R2FIREBALL4"; } State { ID = "R2FIREBALL4"; Sprite = "TRED"; Frame = 11; Flags = fullbright; Tics = 4; Next state = "R2FIREBALL1"; } State { ID = "HANGNOGUTS"; Sprite = "HDB1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGBNOBRAIN"; Sprite = "HDB2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTLOOKDN"; Sprite = "HDB3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTSKULL"; Sprite = "HDB4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTLOOKUP"; Sprite = "HDB5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTNOBRAIN"; Sprite = "HDB6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "COLONGIBS"; Sprite = "POB1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SMALLPOOL"; Sprite = "POB2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BRAINSTEM"; Sprite = "BRS1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BRNRBALL1"; Sprite = "BRNR"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BRNRBALL2"; } State { ID = "BRNRBALL2"; Sprite = "BRNR"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BRNRBALL1"; } State { ID = "BRNRBALLX1"; Sprite = "BRNR"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "BRNRBALLX2"; } State { ID = "BRNRBALLX2"; Sprite = "BRNR"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "BRNRBALLX3"; } State { ID = "BRNRBALLX3"; Sprite = "BRNR"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "BRNRBALLX4"; } State { ID = "BRNRBALLX4"; Sprite = "BRNR"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "BRNRBALLX5"; } State { ID = "BRNRBALLX5"; Sprite = "BRNR"; Frame = 6; Flags = fullbright; Tics = 6; Next state = "BRNRBALLX6"; } State { ID = "BRNRBALLX6"; Sprite = "BRNR"; Frame = 7; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "NMBL1"; Sprite = "NMBL"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "NMBL2"; } State { ID = "NMBL2"; Sprite = "NMBL"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "NMBL3"; } State { ID = "NMBL3"; Sprite = "NMBL"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "NMBL1"; } State { ID = "NMBLX1"; Sprite = "NMBL"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "NMBLX2"; } State { ID = "NMBLX2"; Sprite = "NMBL"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "NMBLX3"; } State { ID = "NMBLX3"; Sprite = "NMBL"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "NMBLX4"; } State { ID = "NMBLX4"; Sprite = "NMBL"; Frame = 6; Flags = fullbright; Tics = 6; Next state = "NMBLX5"; } State { ID = "NMBLX5"; Sprite = "NMBL"; Frame = 7; Flags = fullbright; Tics = 6; Next state = "NMBLX6"; } State { ID = "NMBLX6"; Sprite = "NMBL"; Frame = 8; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "LAZR1"; Sprite = "LAZR"; Frame = 0; Flags = fullbright; Tics = 1; Action = "A_Lasersmoke"; Next state = "LAZR2"; } State { ID = "LAZR2"; Sprite = "LAZR"; Frame = 1; Flags = fullbright; Tics = 1; Action = "A_Lasersmoke"; Next state = "LAZR1"; } State { ID = "LAZRDTH"; Sprite = "LPUF"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "LAZRDTH2"; } State { ID = "LAZRDTH2"; Sprite = "LPUF"; Frame = 1; Flags = fullbright; Tics = 3; Next state = "LAZRDTH3"; } State { ID = "LAZRDTH3"; Sprite = "LPUF"; Frame = 3; Flags = fullbright; Tics = 3; Next state = "LAZRDTH4"; } State { ID = "LAZRDTH4"; Sprite = "LPUF"; Frame = 4; Flags = fullbright; Tics = 3; Next state = "LAZRDTH5"; } State { ID = "LAZRDTH5"; Sprite = "LPUF"; Frame = 5; Flags = fullbright; Tics = 3; Next state = "LAZRDTH6"; } State { ID = "LAZRDTH6"; Sprite = "LPUF"; Frame = 6; Flags = fullbright; Tics = 3; Next state = "LAZRDTH7"; } State { ID = "LAZRDTH7"; Sprite = "LPUF"; Frame = 7; Flags = fullbright; Tics = 3; Next state = "LAZRDTH8"; } State { ID = "LAZRDTH8"; Sprite = "LPUF"; Frame = 8; Flags = fullbright; Tics = 3; Next state = "LAZRDTH9"; } State { ID = "LAZRDTH9"; Sprite = "LPUF"; Frame = 9; Flags = fullbright; Tics = 3; Next state = "LAZRDTH10"; } State { ID = "LAZRDTH10"; Sprite = "LPUF"; Frame = 10; Flags = fullbright; Tics = 3; Next state = "NULL"; } State { ID = "LAZRDUST"; Sprite = "LPUF"; Frame = 2; Flags = fullbright; Tics = 8; Next state = "NULL"; } State { ID = "LAZRW1"; Sprite = "LAZR"; Frame = 0; Flags = fullbright; Tics = 1; Next state = "LAZRW2"; } State { ID = "LAZRW2"; Sprite = "LAZR"; Frame = 1; Flags = fullbright; Tics = 1; Next state = "LAZRW1"; } State { ID = "RTRACER1"; Sprite = "MBAL"; Frame = 0; Flags = fullbright; Tics = 2; Action = "A_RectTracerPuff"; Next state = "RTRACER2"; } State { ID = "RTRACER2"; Sprite = "MBAL"; Frame = 1; Flags = fullbright; Tics = 2; Action = "A_RectTracerPuff"; Next state = "RTRACER1"; } State { ID = "RTRACEREXP"; Sprite = "BRNR"; Frame = 2; Flags = fullbright; Tics = 6; Action = "A_MotherBallExplode"; Next state = "BRNRBALLX2"; } State { ID = "TECHLAMP"; Sprite = "TLMP"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "TECH2LAMP"; Sprite = "TLP2"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "TRACER"; Sprite = "MANF"; Frame = 0; Flags = fullbright; Tics = 2; Action = "A_Tracer"; Next state = "TRACER2"; } State { ID = "TRACER2"; Sprite = "MANF"; Frame = 1; Flags = fullbright; Tics = 2; Action = "A_Tracer"; Next state = "TRACER3"; } State { ID = "TRACER3"; Sprite = "MANF"; Frame = 2; Flags = fullbright; Tics = 2; Action = "A_Tracer"; Next state = "TRACER"; } State { ID = "TRACEEXP1"; Sprite = "MANF"; Frame = 3; Flags = fullbright; Tics = 8; Next state = "TRACEEXP2"; } State { ID = "TRACEEXP2"; Sprite = "MANF"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "TRACEEXP3"; } State { ID = "TRACEEXP3"; Sprite = "MANF"; Frame = 5; Flags = fullbright; Tics = 4; Next state = "TRACEEXP4"; } State { ID = "TRACEEXP4"; Sprite = "MANF"; Frame = 6; Flags = fullbright; Tics = 4; Next state = "TRACEEXP5"; } State { ID = "TRACEEXP5"; Sprite = "MANF"; Frame = 7; Flags = fullbright; Tics = 2; Next state = "TRACEEXP6"; } State { ID = "TRACEEXP6"; Sprite = "MANF"; Frame = 8; Flags = fullbright; Tics = 2; Next state = "NULL"; } State { ID = "DISSOUL1"; Sprite = "SOUL"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "DISSOUL2"; } State { ID = "DISSOUL2"; Sprite = "SOUL"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "DISSOUL3"; } State { ID = "DISSOUL3"; Sprite = "SOUL"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "DISSOUL4"; } State { ID = "DISSOUL4"; Sprite = "SOUL"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "DISSOUL5"; } State { ID = "DISSOUL5"; Sprite = "SOUL"; Frame = 3; Flags = fullbright; Tics = 10; Next state = "DISSOUL6"; } State { ID = "DISSOUL6"; Sprite = "SOUL"; Frame = 7; Flags = fullbright; Tics = 5; Next state = "DISSOUL7"; } State { ID = "DISSOUL7"; Sprite = "SOUL"; Frame = 6; Flags = fullbright; Tics = 5; Next state = "DISSOUL8"; } State { ID = "DISSOUL8"; Sprite = "SOUL"; Frame = 5; Flags = fullbright; Tics = 5; Next state = "DISSOUL9"; } State { ID = "DISSOUL9"; Sprite = "SOUL"; Frame = 4; Flags = fullbright; Tics = 5; Next state = "NULL"; } State { ID = "DBKEY1"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY2"; } State { ID = "DBKEY2"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY3"; } State { ID = "DBKEY3"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY4"; } State { ID = "DBKEY4"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY5"; } State { ID = "DBKEY5"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY6"; } State { ID = "DBKEY6"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY7"; } State { ID = "DBKEY7"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY8"; } State { ID = "DBKEY8"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY9"; } State { ID = "DBKEY9"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 3; Next state = "DBKEY10"; } State { ID = "DBKEY10"; Sprite = "BKEY"; Frame = 0; Flags = fullbright; Tics = 10; Next state = "DBKEY11"; } State { ID = "DBKEY11"; Sprite = "BKEY"; Frame = 10; Flags = fullbright; Tics = 3; Next state = "DBKEY12"; } State { ID = "DBKEY12"; Sprite = "BKEY"; Frame = 9; Flags = fullbright; Tics = 3; Next state = "DBKEY13"; } State { ID = "DBKEY13"; Sprite = "BKEY"; Frame = 8; Flags = fullbright; Tics = 3; Next state = "DBKEY14"; } State { ID = "DBKEY14"; Sprite = "BKEY"; Frame = 7; Flags = fullbright; Tics = 3; Next state = "DBKEY15"; } State { ID = "DBKEY15"; Sprite = "BKEY"; Frame = 6; Flags = fullbright; Tics = 3; Next state = "DBKEY16"; } State { ID = "DBKEY16"; Sprite = "BKEY"; Frame = 5; Flags = fullbright; Tics = 3; Next state = "DBKEY17"; } State { ID = "DBKEY17"; Sprite = "BKEY"; Frame = 4; Flags = fullbright; Tics = 3; Next state = "DBKEY18"; } State { ID = "DBKEY18"; Sprite = "BKEY"; Frame = 3; Flags = fullbright; Tics = 3; Next state = "DBKEY19"; } State { ID = "DBKEY19"; Sprite = "BKEY"; Frame = 2; Flags = fullbright; Tics = 3; Next state = "NULL"; } State { ID = "IFOG"; Sprite = "IFOG"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "IFOG01"; } State { ID = "IFOG01"; Sprite = "IFOG"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "IFOG02"; } State { ID = "IFOG02"; Sprite = "IFOG"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "IFOG2"; } State { ID = "IFOG2"; Sprite = "IFOG"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "IFOG3"; } State { ID = "IFOG3"; Sprite = "IFOG"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "IFOG4"; } State { ID = "IFOG4"; Sprite = "IFOG"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "IFOG5"; } State { ID = "IFOG5"; Sprite = "IFOG"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "SMALL_WHITE_LIGHT"; Sprite = "APLS"; Frame = 4; Tics = -1; Next state = "NULL"; } State { ID = "TEMPSOUNDORIGIN1"; Tics = 175; Next state = "NULL"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/text.ded0000644000175000017500000004506711357170242022427 0ustar keeskees# jDoom64: Text Strings # # Do not change the order of these definitions! # Header { Version = 5; } Text { ID = "PRESSKEY"; Text = "Press a key."; } Text { ID = "PRESSYN"; Text = "Press %1 or %2."; } Text { ID = "QUITMSG"; Text = "Are you sure you want to\nquit this great game?"; } Text { ID = "LOADNET"; Text = "You can't load while in a net game!"; } Text { ID = "QLOADNET"; Text = "You can't quickload during a netgame!"; } Text { ID = "QSAVESPOT"; Text = "You haven't picked a quicksave slot yet!"; } Text { ID = "SAVEDEAD"; Text = "You can't save if you aren't playing!"; } Text { ID = "QSPROMPT"; Text = "Quicksave over your game named\n\n'%s'?"; } Text { ID = "QLPROMPT"; Text = "Do you want to quickload the game named\n\n'%s'?"; } Text { ID = "NEWGAME"; Text = "You can't start a new game\nwhile in a network game."; } Text { ID = "MSGOFF"; Text = "Messages OFF"; } Text { ID = "MSGON"; Text = "Messages ON"; } Text { ID = "NETEND"; Text = "You can't end a netgame!"; } Text { ID = "ENDGAME"; Text = "Are you sure you want to end the game?"; } Text { ID = "GAMMALVL0"; Text = "Gamma correction OFF"; } Text { ID = "GAMMALVL1"; Text = "Gamma correction level 1"; } Text { ID = "GAMMALVL2"; Text = "Gamma correction level 2"; } Text { ID = "GAMMALVL3"; Text = "Gamma correction level 3"; } Text { ID = "GAMMALVL4"; Text = "Gamma correction level 4"; } Text { ID = "EMPTYSTRING"; Text = "Empty slot"; } Text { ID = "GOTARMOR"; Text = "Picked up the armor."; } Text { ID = "GOTMEGA"; Text = "Picked up the MegaArmor!"; } Text { ID = "GOTHTHBONUS"; Text = "Picked up a health bonus."; } Text { ID = "GOTARMBONUS"; Text = "Picked up an armor bonus."; } Text { ID = "GOTSTIM"; Text = "Picked up a stimpack."; } Text { ID = "GOTMEDINEED"; Text = "Picked up a medikit that you REALLY need!"; } Text { ID = "GOTMEDIKIT"; Text = "Picked up a medikit."; } Text { ID = "GOTSUPER"; Text = "Supercharge!"; } Text { ID = "GOTBLUECARD"; Text = "Picked up a blue keycard."; } Text { ID = "GOTYELWCARD"; Text = "Picked up a yellow keycard."; } Text { ID = "GOTREDCARD"; Text = "Picked up a red keycard."; } Text { ID = "GOTBLUESKUL"; Text = "Picked up a blue skull key."; } Text { ID = "GOTYELWSKUL"; Text = "Picked up a yellow skull key."; } Text { ID = "GOTREDSKULL"; Text = "Picked up a red skull key."; } Text { ID = "GOTINVUL"; Text = "Invulnerability!"; } Text { ID = "GOTBERSERK"; Text = "Berserk!"; } Text { ID = "GOTINVIS"; Text = "Partial Invisibility"; } Text { ID = "GOTSUIT"; Text = "Radiation Shielding Suit"; } Text { ID = "GOTMAP"; Text = "Computer Area Map"; } Text { ID = "GOTVISOR"; Text = "Light Amplification Visor"; } Text { ID = "GOTMSPHERE"; Text = "MegaSphere!"; } Text { ID = "GOTCLIP"; Text = "Picked up a clip."; } Text { ID = "GOTCLIPBOX"; Text = "Picked up a box of bullets."; } Text { ID = "GOTROCKET"; Text = "Picked up a rocket."; } Text { ID = "GOTROCKBOX"; Text = "Picked up a box of rockets."; } Text { ID = "GOTCELL"; Text = "Picked up an energy cell."; } Text { ID = "GOTCELLBOX"; Text = "Picked up an energy cell pack."; } Text { ID = "GOTSHELLS"; Text = "Picked up 4 shotgun shells."; } Text { ID = "GOTSHELLBOX"; Text = "Picked up a box of shotgun shells."; } Text { ID = "GOTBACKPACK"; Text = "Picked up a backpack full of ammo!"; } Text { ID = "GOTBFG9000"; Text = "You got the BFG9000! Oh, yes."; } Text { ID = "GOTCHAINGUN"; Text = "You got the chaingun!"; } Text { ID = "GOTCHAINSAW"; Text = "A chainsaw! Find some meat!"; } Text { ID = "GOTLAUNCHER"; Text = "You got the rocket launcher!"; } Text { ID = "GOTPLASMA"; Text = "You got the plasma gun!"; } Text { ID = "GOTSHOTGUN"; Text = "You got the shotgun!"; } Text { ID = "GOTSHOTGUN2"; Text = "You got the super shotgun!"; } Text { ID = "GOTUNMAKER"; Text = "What the !@#$%^&* is this?!"; } Text { ID = "NGOTUNMAKER"; Text = "You need the Unmaker!"; } Text { ID = "UNMAKERCHARGE"; Text = "Your Unmaker must recharge!"; } Text { ID = "GOTPOWERUP1"; Text = "You have a feeling that it wasn't meant to be touched.."; } Text { ID = "NGOTPOWERUP1"; Text = "You don't have the will to touch this..."; } Text { ID = "GOTPOWERUP2"; Text = "What is this used for?"; } Text { ID = "NGOTPOWERUP2"; Text = "You don't have the courage to touch this..."; } Text { ID = "GOTPOWERUP3"; Text = "It looks like some sort of key..."; } Text { ID = "NGOTPOWERUP3"; Text = "You don't have the ability to touch this..."; } Text { ID = "PD_OPNPOWERUP"; Text = "You lack the ability to activate it..."; } Text { ID = "PD_BLUEO"; Text = "You need a %1 to activate this object"; } Text { ID = "PD_REDO"; Text = "You need a %1 to activate this object"; } Text { ID = "PD_YELLOWO"; Text = "You need a %1 to activate this object"; } Text { ID = "PD_BLUEK"; Text = "You need a %1 to open this door"; } Text { ID = "PD_REDK"; Text = "You need a %1 to open this door"; } Text { ID = "PD_YELLOWK"; Text = "You need a %1 to open this door"; } Text { ID = "GGSAVED"; Text = "Game saved."; } Text { ID = "HUSTR_MSGU"; Text = "[Message unsent]"; } Text { ID = "HUSTR_MAP01"; Text = "Map 1: Staging Area"; } Text { ID = "HUSTR_MAP02"; Text = "Map 2: The Terraformer"; } Text { ID = "HUSTR_MAP03"; Text = "Map 3: Main Engineering"; } Text { ID = "HUSTR_MAP04"; Text = "Map 4: Holding Area"; } Text { ID = "HUSTR_MAP05"; Text = "Map 5: Tech Center"; } Text { ID = "HUSTR_MAP06"; Text = "Map 6: Alpha Quadrant"; } Text { ID = "HUSTR_MAP07"; Text = "Map 7: Research Lab"; } Text { ID = "HUSTR_MAP08"; Text = "Map 8: Final Outpost"; } Text { ID = "HUSTR_MAP09"; Text = "Map 9: Even Simpler"; } Text { ID = "HUSTR_MAP10"; Text = "Map 10: The Bleeding"; } Text { ID = "HUSTR_MAP11"; Text = "Map 11: Terror Core"; } Text { ID = "HUSTR_MAP12"; Text = "Map 12: Altar of Pain"; } Text { ID = "HUSTR_MAP13"; Text = "Map 13: Dark Citadel"; } Text { ID = "HUSTR_MAP14"; Text = "Map 14: Eye of the Storm"; } Text { ID = "HUSTR_MAP15"; Text = "Map 15: Dark Entires"; } Text { ID = "HUSTR_MAP16"; Text = "Map 16: Blood Keep"; } Text { ID = "HUSTR_MAP17"; Text = "Map 17: Watch Your Step"; } Text { ID = "HUSTR_MAP18"; Text = "Map 18: Spawned Fear"; } Text { ID = "HUSTR_MAP19"; Text = "Map 19: The Spiral"; } Text { ID = "HUSTR_MAP20"; Text = "Map 20: Breakdown"; } Text { ID = "HUSTR_MAP21"; Text = "Map 21: Pitfalls"; } Text { ID = "HUSTR_MAP22"; Text = "Map 22: Burnt Offerings"; } Text { ID = "HUSTR_MAP23"; Text = "Map 23: Unholy Temple"; } Text { ID = "HUSTR_MAP24"; Text = "Map 24: No Escape"; } Text { ID = "HUSTR_MAP25"; Text = "Map 25: Cat And Mouse"; } Text { ID = "HUSTR_MAP26"; Text = "Map 26: Hardcore"; } Text { ID = "HUSTR_MAP27"; Text = "Map 27: Playground"; } Text { ID = "HUSTR_MAP28"; Text = "Map 28: The Absolution"; } Text { ID = "HUSTR_MAP29"; Text = "Map 29: Outpost Omega"; } Text { ID = "HUSTR_MAP30"; Text = "Map 30: The Lair"; } Text { ID = "HUSTR_MAP31"; Text = "Map 31: In The Void"; } Text { ID = "HUSTR_MAP32"; Text = "Map 32: Hectic"; } Text { ID = "HUSTR_MAP33"; Text = "Map 33: The Unknown"; } Text { ID = "HUSTR_CHATMACRO0"; Text = "No"; } Text { ID = "HUSTR_CHATMACRO1"; Text = "I'm ready to kick butt!"; } Text { ID = "HUSTR_CHATMACRO2"; Text = "I'm OK."; } Text { ID = "HUSTR_CHATMACRO3"; Text = "I'm not looking too good!"; } Text { ID = "HUSTR_CHATMACRO4"; Text = "Help!"; } Text { ID = "HUSTR_CHATMACRO5"; Text = "You suck!"; } Text { ID = "HUSTR_CHATMACRO6"; Text = "Next time, scumbag..."; } Text { ID = "HUSTR_CHATMACRO7"; Text = "Come here!"; } Text { ID = "HUSTR_CHATMACRO8"; Text = "I'll take care of it."; } Text { ID = "HUSTR_CHATMACRO9"; Text = "Yes"; } Text { ID = "HUSTR_TALKTOSELF1"; Text = "You mumble to yourself"; } Text { ID = "HUSTR_TALKTOSELF2"; Text = "Who's there?"; } Text { ID = "HUSTR_TALKTOSELF3"; Text = "You scare yourself"; } Text { ID = "HUSTR_TALKTOSELF4"; Text = "You start to rave"; } Text { ID = "HUSTR_TALKTOSELF5"; Text = "You've lost it..."; } Text { ID = "HUSTR_MESSAGESENT"; Text = "[Message Sent]"; } Text { ID = "HUSTR_PLRGREEN"; Text = "Green: "; } Text { ID = "HUSTR_PLRINDIGO"; Text = "Indigo: "; } Text { ID = "HUSTR_PLRBROWN"; Text = "Brown: "; } Text { ID = "HUSTR_PLRRED"; Text = "Red: "; } Text { ID = "AMSTR_FOLLOWON"; Text = "Follow Mode ON"; } Text { ID = "AMSTR_FOLLOWOFF"; Text = "Follow Mode OFF"; } Text { ID = "AMSTR_GRIDON"; Text = "Grid ON"; } Text { ID = "AMSTR_GRIDOFF"; Text = "Grid OFF"; } Text { ID = "AMSTR_MARKEDSPOT"; Text = "Marked Spot"; } Text { ID = "AMSTR_MARKSCLEARED"; Text = "All Marks Cleared"; } Text { ID = "STSTR_MUS"; Text = "Music Change"; } Text { ID = "STSTR_NOMUS"; Text = "Impossible selection"; } Text { ID = "STSTR_DQDON"; Text = "You feel immortal"; } Text { ID = "STSTR_DQDOFF"; Text = "You feel mortal"; } Text { ID = "STSTR_KFAADDED"; Text = "Stuff given"; } Text { ID = "STSTR_FAADDED"; Text = "Weapons given"; } Text { ID = "STSTR_NCON"; Text = "No Clipping Mode ON"; } Text { ID = "STSTR_NCOFF"; Text = "No Clipping Mode OFF"; } Text { ID = "STSTR_BEHOLD"; Text = "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"; } Text { ID = "STSTR_BEHOLDX"; Text = "Power-up toggled"; } Text { ID = "STSTR_CHOPPERS"; Text = "... doesn't suck - GM"; } Text { ID = "STSTR_CLEV"; Text = "Warping...."; } Text { ID = "C1TEXT"; Text = "You cackle as the familiarity of the situation\n occurs to you. The gateway to the Demon's Domain\n was too accessible. You realize the Demons mock\n you with their invitation. It does not matter...\n The Demons spawn like rats and you have the\n Grade AAA UAC poison they crave.\n\n Your blood thirsty scream shatters the teleport\n haze. Once again you find yourself amidst..."; } Text { ID = "C2TEXT"; Text = "You smile.\n What strange place have you stumbled upon?\n The Demons did not expect you to survive this far.\n You feel their Demonic presence waiting for you...\n\n Let them taste their guts!"; } Text { ID = "C3TEXT"; Text = "You wretch as a strange acrid odor assaults you.\n Death and Demon carcass!\n No nightmare could have prepared you for this.\n You realize this place was not meant for living\n Humans."; } Text { ID = "C4TEXT"; Text = "Finally...\nThe mother of all Demons is dead!\n The blood purs from your eyes as you stand in\n difiance.\n As the only marine to endure the slaughter-\n you decide to remain in Hell and ensure no Demon\n ever rises again. The end."; } Text { ID = "CC_ZOMBIE"; Text = "Zombieman"; } Text { ID = "CC_SHOTGUN"; Text = "Shotgun Guy"; } Text { ID = "CC_IMP"; Text = "Imp"; } Text { ID = "CC_DEMON"; Text = "Demon"; } Text { ID = "CC_LOST"; Text = "Lost Soul"; } Text { ID = "CC_CACO"; Text = "Cacodemon"; } Text { ID = "CC_HELL"; Text = "Hell Knight"; } Text { ID = "CC_BARON"; Text = "Baron of Hell"; } Text { ID = "CC_ARACH"; Text = "Arachnotron"; } Text { ID = "CC_PAIN"; Text = "Pain Elemental"; } Text { ID = "CC_MANCU"; Text = "Mancubus"; } Text { ID = "CC_CYBER"; Text = "Cyberdemon"; } Text { ID = "CC_NTROOP"; Text = "Nightmare Imp"; } Text { ID = "CC_BITCH"; Text = "Motherdemon"; } Text { ID = "CC_HERO"; Text = "Our hero"; } Text { ID = "QUITMESSAGE1"; Text = "Hey don't quit now, we are barely \non map 1!"; } Text { ID = "QUITMESSAGE2"; Text = "Demons own your sorry ass..."; } Text { ID = "QUITMESSAGE3"; Text = "Hell will come upon you..."; } Text { ID = "QUITMESSAGE4"; Text = "I guess you find this boring..."; } Text { ID = "QUITMESSAGE5"; Text = "Don't think about leaving \nor else I'll send a \n Nightmare Demon after your ass..."; } Text { ID = "QUITMESSAGE6"; Text = "Fine, get out chicken shit..."; } Text { ID = "QUITMESSAGE7"; Text = "Go ahead and leave. See if I care."; } Text { ID = "QUITMESSAGE8"; Text = "Quit?! We are not done with you yet!"; } Text { ID = "QUITMESSAGE9"; Text = "Fine, go back playing your \nStupid Counterstrike games."; } Text { ID = "QUITMESSAGE10"; Text = "Fine, go back playing your \nStupid UT 2003 games."; } Text { ID = "QUITMESSAGE11"; Text = "Fine, go back playing your \nStupid Quake 3 games."; } Text { ID = "QUITMESSAGE12"; Text = "Look, bud. You leave now\nand you forfeit your body count!"; } Text { ID = "QUITMESSAGE13"; Text = "Just leave. When you come\nback, I'll be waiting with a bat."; } Text { ID = "QUITMESSAGE14"; Text = "You're lucky I don't smack\nYou for thinking about leaving."; } Text { ID = "QUITMESSAGE15"; Text = "Prescience of mind is\nno substitute for courage."; } Text { ID = "QUITMESSAGE16"; Text = "Seems this is too much for you..."; } Text { ID = "QUITMESSAGE17"; Text = "Return as an apostate to be\neternally welcomed."; } Text { ID = "QUITMESSAGE18"; Text = "To abandon the cause\ncan only presage disaster."; } Text { ID = "QUITMESSAGE19"; Text = "Quit now? You big baby..."; } Text { ID = "QUITMESSAGE20"; Text = "Dost the demesne win?\nDost its inhabitants prevail?\nIs this the end?"; } Text { ID = "QUITMESSAGE21"; Text = "Your mom is the Motherdemon herself..."; } Text { ID = "QUITMESSAGE22"; Text = "Escape if you will, but these\ndark corridors haunt you forever..."; } Text { ID = "JOINNET"; Text = "You're already in a network game!"; } Text { ID = "SAVENET"; Text = "You can't save while in a net game!"; } Text { ID = "CLNETLOAD"; Text = "Server loading saved game..."; } Text { ID = "LOADMISSING"; Text = "You weren't in the server's savegame."; } Text { ID = "FINALEFLAT_C2"; Text = "RROCK14"; } Text { ID = "FINALEFLAT_C1"; Text = "SLIME16"; } Text { ID = "FINALEFLAT_C3"; Text = "RROCK07"; } Text { ID = "FINALEFLAT_C4"; Text = "RROCK17"; } Text { ID = "FINALEFLAT_C5"; Text = "RROCK13"; } Text { ID = "FINALEFLAT_C6"; Text = "RROCK19"; } Text { ID = "FINALEFLAT_C7"; Text = "RROCK19"; } Text { ID = "FINALEFLAT_C8"; Text = "RROCK19"; } Text { ID = "FINALEFLAT_C9"; Text = "RROCK19"; } Text { ID = "KILLMSG_SUICIDE"; Text = "%1 commits suicide!"; } Text { ID = "KILLMSG_WEAPON0"; Text = "%1 beat %2 with bare hands!"; } Text { ID = "KILLMSG_PISTOL"; Text = "%2 was gunned down by %1."; } Text { ID = "KILLMSG_SHOTGUN"; Text = "%1 shot %2 to bloody bits."; } Text { ID = "KILLMSG_CHAINGUN"; Text = "%2 was poisoned by %1's lead."; } Text { ID = "KILLMSG_MISSILE"; Text = "%2 rode %1's rocket. Splat!"; } Text { ID = "KILLMSG_PLASMA"; Text = "%2 got burnt in %1's plasma."; } Text { ID = "KILLMSG_BFG"; Text = "%2 was scorched by %1's BFG!"; } Text { ID = "KILLMSG_CHAINSAW"; Text = "%1 slaughtered %2 with a buzz!"; } Text { ID = "KILLMSG_SUPERSHOTGUN"; Text = "%1 blasted %2 to tiny bits."; } Text { ID = "KILLMSG_UNMAKER"; Text = "%1 was unmade by %2"; } Text { ID = "KILLMSG_STOMP"; Text = "%1 stomped %2!!"; } Text { ID = "AMSTR_ROTATEON"; Text = "Rotate mode ON"; } Text { ID = "AMSTR_ROTATEOFF"; Text = "Rotate mode OFF"; } Text { ID = "WEAPON1"; Text = "Fist"; } Text { ID = "WEAPON2"; Text = "Pistol"; } Text { ID = "WEAPON3"; Text = "Shotgun"; } Text { ID = "WEAPON4"; Text = "Chaingun"; } Text { ID = "WEAPON5"; Text = "Rocket Launcher"; } Text { ID = "WEAPON6"; Text = "Plasma Rifle"; } Text { ID = "WEAPON7"; Text = "BFG 9000"; } Text { ID = "WEAPON8"; Text = "Chainsaw"; } Text { ID = "WEAPON9"; Text = "Super Shotgun"; } Text { ID = "WEAPON10"; Text = "Unmaker"; } Text { ID = "SKILL1"; Text = "Be Gentle!"; } Text { ID = "SKILL2"; Text = "Bring it on!"; } Text { ID = "SKILL3"; Text = "I own Doom!"; } Text { ID = "SKILL4"; Text = "Watch me die!"; } Text { ID = "KEY1"; Text = "Blue Keycard"; } Text { ID = "KEY2"; Text = "Yellow Keycard"; } Text { ID = "KEY3"; Text = "Red Keycard"; } Text { ID = "KEY4"; Text = "Blue Skull Key"; } Text { ID = "KEY5"; Text = "Yellow Skull Key"; } Text { ID = "KEY6"; Text = "Red Skull Key"; } Text { ID = "DEMONKEY1"; Text = "Blue Demon Key"; } Text { ID = "DEMONKEY2"; Text = "Yellow Demon Key"; } Text { ID = "DEMONKEY3"; Text = "Red Demon Key"; } Text { ID = "SAVEOUTMAP"; Text = "You can't save if you aren't in a map!"; } Text { ID = "ENDNOGAME"; Text = "You can't end a game that hasn't even begun!"; } Text { ID = "SUICIDEOUTMAP"; Text = "You can't suicide if you aren't in a map!"; } Text { ID = "SUICIDEASK"; Text = "Are you sure you want to suicide?"; } Text { ID = "PICKGAMETYPE"; Text = "Choose game type"; } Text { ID = "SINGLEPLAYER"; Text = "Singleplayer"; } Text { ID = "MULTIPLAYER"; Text = "Multiplayer"; } Text { ID = "NOTDESIGNEDFOR"; Text = "Not designed for %1."; } Text { ID = "GAMESETUP"; Text = "Game Setup"; } Text { ID = "PLAYERSETUP"; Text = "Player Setup"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/finales.ded0000644000175000017500000000257111357170242023055 0ustar keeskees# jDoom64: Intermissions and Finales # (see Doc\InFine.txt) Header { Version = 5; } InFine { ID = "title"; Script { # There is no skipping during the titlescreen loop. NoSkip # Any event shows the menu. Trigger MARKER title_loop Patch back 0 0 "TITLEPIC" MusicOnce "dm2ttl" Wait 13 # Original was 11; this'll play the whole song. ; GOTO title_loop }; } # I'm using "textdef" to allow compatibility with DeHackEd. # A better way would just be to use "text" and define the text # in the script, no need to go about modifying the Text defs. Finale { Before = "MAP09"; Script { music "read_m" wait 0.5 textdef msg 10 10 "C1TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP13"; Script { music "read_m" wait 0.5 textdef msg 10 10 "C2TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP31"; Script { music "read_m" wait 0.5 textdef msg 10 10 "C3TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { After = "MAP28"; Script { music "read_m" wait 0.5 textdef msg 10 10 "C4TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/lights.ded0000644000175000017500000000061111357170242022717 0ustar keeskees# jDoom64: Lights SkipIf -nodefaultfx; #####====--- LIGHT SOURCE PROPERTIES ---====##### # The default properties of all light-emitting objects are determined # automatically by the engine. Light { State = "COLU"; Size = 0.6; } Light { State = "PLASBALL"; Flags = nohalo; } Light { State = "PLASBALL2"; Flags = nohalo; } Include "decorlights.ded" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/defs/sprites.ded0000644000175000017500000000671711357170242023133 0ustar keeskees# jDoom64: Sprites # # Order of definitions is very important here! # Only add new Sprites *after* the existing definitions. Header { Version = 5; } Sprite { ID = "PLAY"; } Sprite { ID = "SARG"; } Sprite { ID = "FATT"; } Sprite { ID = "POSS"; } Sprite { ID = "TROO"; } Sprite { ID = "HEAD"; } Sprite { ID = "BOSS"; } Sprite { ID = "SKUL"; } Sprite { ID = "BSPI"; } Sprite { ID = "CYBR"; } Sprite { ID = "PAIN"; } Sprite { ID = "RECT"; } Sprite { ID = "MISL"; } Sprite { ID = "PLSS"; } Sprite { ID = "BFS1"; } Sprite { ID = "BAL1"; } Sprite { ID = "BAL3"; } Sprite { ID = "APLS"; } Sprite { ID = "MANF"; } Sprite { ID = "DART"; } Sprite { ID = "FIRE"; } Sprite { ID = "PUFF"; } Sprite { ID = "BLUD"; } Sprite { ID = "TFOG"; } Sprite { ID = "BFE2"; } Sprite { ID = "ARM1"; } Sprite { ID = "ARM2"; } Sprite { ID = "BON1"; } Sprite { ID = "BON2"; } Sprite { ID = "BKEY"; } Sprite { ID = "RKEY"; } Sprite { ID = "YKEY"; } Sprite { ID = "YSKU"; } Sprite { ID = "RSKU"; } Sprite { ID = "BSKU"; } Sprite { ID = "ART1"; } Sprite { ID = "ART2"; } Sprite { ID = "ART3"; } Sprite { ID = "STIM"; } Sprite { ID = "MEDI"; } Sprite { ID = "SOUL"; } Sprite { ID = "PINV"; } Sprite { ID = "PSTR"; } Sprite { ID = "PINS"; } Sprite { ID = "SUIT"; } Sprite { ID = "PMAP"; } Sprite { ID = "PVIS"; } Sprite { ID = "MEGA"; } Sprite { ID = "CLIP"; } Sprite { ID = "AMMO"; } Sprite { ID = "RCKT"; } Sprite { ID = "BROK"; } Sprite { ID = "CELL"; } Sprite { ID = "CELP"; } Sprite { ID = "SHEL"; } Sprite { ID = "SBOX"; } Sprite { ID = "BPAK"; } Sprite { ID = "BFUG"; } Sprite { ID = "CSAW"; } Sprite { ID = "MGUN"; } Sprite { ID = "LAUN"; } Sprite { ID = "PLSM"; } Sprite { ID = "SHOT"; } Sprite { ID = "SGN2"; } Sprite { ID = "LSRG"; } Sprite { ID = "CAND"; } Sprite { ID = "BAR1"; } Sprite { ID = "TRE2"; } Sprite { ID = "TRE1"; } Sprite { ID = "SAWG"; } Sprite { ID = "PUNG"; } Sprite { ID = "PISG"; } Sprite { ID = "SHT1"; } Sprite { ID = "SHT2"; } Sprite { ID = "CHGG"; } Sprite { ID = "ROCK"; } Sprite { ID = "PLAS"; } Sprite { ID = "BFGG"; } Sprite { ID = "LASR"; } Sprite { ID = "PLSE"; } Sprite { ID = "BFE1"; } Sprite { ID = "IFOG"; } Sprite { ID = "SPOS"; } Sprite { ID = "FATB"; } Sprite { ID = "FBXP"; } Sprite { ID = "SKEL"; } Sprite { ID = "BAL7"; } Sprite { ID = "BOS2"; } Sprite { ID = "BON4"; } Sprite { ID = "COLU"; } Sprite { ID = "SMT2"; } Sprite { ID = "GOR1"; } Sprite { ID = "POL2"; } Sprite { ID = "POL5"; } Sprite { ID = "POL4"; } Sprite { ID = "POL3"; } Sprite { ID = "POL1"; } Sprite { ID = "POL6"; } Sprite { ID = "GOR2"; } Sprite { ID = "GOR3"; } Sprite { ID = "GOR4"; } Sprite { ID = "GOR5"; } Sprite { ID = "SMIT"; } Sprite { ID = "COL1"; } Sprite { ID = "COL2"; } Sprite { ID = "COL3"; } Sprite { ID = "COL4"; } Sprite { ID = "CBRA"; } Sprite { ID = "COL6"; } Sprite { ID = "ELEC"; } Sprite { ID = "TBLU"; } Sprite { ID = "TGRN"; } Sprite { ID = "TRED"; } Sprite { ID = "SMBT"; } Sprite { ID = "SMGT"; } Sprite { ID = "SMRT"; } Sprite { ID = "HDB1"; } Sprite { ID = "HDB2"; } Sprite { ID = "HDB3"; } Sprite { ID = "HDB4"; } Sprite { ID = "HDB5"; } Sprite { ID = "HDB6"; } Sprite { ID = "POB1"; } Sprite { ID = "POB2"; } Sprite { ID = "BRS1"; } Sprite { ID = "TLMP"; } Sprite { ID = "TLP2"; } Sprite { ID = "NTRO"; } Sprite { ID = "BRNR"; } Sprite { ID = "NMBL"; } Sprite { ID = "SMOK"; } Sprite { ID = "LAZR"; } Sprite { ID = "LPUF"; } Sprite { ID = "MBAL"; } Sprite { ID = "MPUF"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom64/CMakeLists.txt0000644000175000017500000000355311357170242022576 0ustar keeskees## deng build scripts. ## Copyright 2006 - 2007 Jamie Jones ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/plugins/common/include ) FILE(GLOB COMMON_PLUGIN_SOURCES ${CMAKE_SOURCE_DIR}/plugins/common/src/*.c) ################################################################################ ######################## Doom64TC Game Plugin ################################## ADD_DEFINITIONS (-D__JDOOM64__ ) #ADD_DEFINITIONS (-D__JDOOM__ ) INCLUDE_DIRECTORIES ( include ) FILE(GLOB DOOM64TC_SOURCES src/*.c) ADD_LIBRARY (jdoom64 SHARED ${DOOM64TC_SOURCES} ${COMMON_PLUGIN_SOURCES} ) IF (APPLE) SET_TARGET_PROPERTIES (jdoom64 PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -bundle -bundle_loader doomsday") ENDIF (APPLE) ################################################################################ ######################## Install Targets ###################################### INSTALL(TARGETS jdoom64 RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/0000755000175000017500000000000011523516204020033 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/0000755000175000017500000000000011357170242020625 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/hu_log.c0000644000175000017500000006060111357170242022251 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_log.c: Player's game message log. * * \todo Chat widget is here and should be moved. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "hu_log.h" #include "hu_stuff.h" #include "p_tick.h" // for P_IsPaused() #include "d_net.h" // MACROS ------------------------------------------------------------------ #define LOG_MAX_MESSAGES (8) #define LOG_MSG_FLASHFADETICS (1*TICSPERSEC) #define LOG_MSG_TIMEOUT (4*TICRATE) // Local Message flags: #define MF_JUSTADDED (0x1) // TYPES ------------------------------------------------------------------- typedef struct logmsg_s { char* text; size_t maxLen; uint ticsRemain, tics; byte flags; } logmsg_t; typedef struct msglog_s { boolean visible; boolean notToBeFuckedWith; boolean dontFuckWithMe; logmsg_t msgs[LOG_MAX_MESSAGES]; uint msgCount; // Number of used msg slots. uint nextMsg; // Index of the next slot to be used in msgs. uint numVisibleMsgs; // Number of visible messages. int timer; // Auto-hide timer. float yOffset; // Scroll-up offset. } msglog_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static msglog_t msgLogs[MAXPLAYERS]; cvar_t msgLogCVars[] = { // Behaviour {"msg-count", 0, CVT_INT, &cfg.msgCount, 0, 8}, {"msg-uptime", 0, CVT_FLOAT, &cfg.msgUptime, 1, 60}, // Display {"msg-align", 0, CVT_INT, &cfg.msgAlign, 0, 2}, {"msg-blink", CVF_NO_MAX, CVT_INT, &cfg.msgBlink, 0, 0}, {"msg-scale", CVF_NO_MAX, CVT_FLOAT, &cfg.msgScale, 0, 0}, {"msg-show", 0, CVT_BYTE, &cfg.msgShow, 0, 1}, // Colour defaults {"msg-color-r", 0, CVT_FLOAT, &cfg.msgColor[CR], 0, 1}, {"msg-color-g", 0, CVT_FLOAT, &cfg.msgColor[CG], 0, 1}, {"msg-color-b", 0, CVT_FLOAT, &cfg.msgColor[CB], 0, 1}, {NULL} }; // CODE -------------------------------------------------------------------- /** * Called during the PreInit of each game during start up. * Register Cvars and CCmds for the opperation/look of the message log. */ void Hu_LogRegister(void) { int i; for(i = 0; msgLogCVars[i].name; ++i) Con_AddVariable(msgLogCVars + i); } /** * Adds the given message to the buffer. * * @param log Ptr to the msglog to add the message to. * @param txt The message to be added. * @param tics The length of time the message should be visible. */ static void logPush(msglog_t* log, const char* txt, int tics) { size_t len; logmsg_t* msg; if(!txt || !txt[0]) return; len = strlen(txt); msg = &log->msgs[log->nextMsg]; if(len >= msg->maxLen) { msg->maxLen = len+1; msg->text = realloc(msg->text, msg->maxLen); } memset(msg->text, 0, msg->maxLen); dd_snprintf(msg->text, msg->maxLen, "%s", txt); msg->ticsRemain = msg->tics = tics; msg->flags = MF_JUSTADDED; if(log->nextMsg < LOG_MAX_MESSAGES - 1) log->nextMsg++; else log->nextMsg = 0; if(log->msgCount < LOG_MAX_MESSAGES) log->msgCount++; if(log->numVisibleMsgs < (unsigned) cfg.msgCount) log->numVisibleMsgs++; log->notToBeFuckedWith = log->dontFuckWithMe; log->dontFuckWithMe = 0; // Reset the auto-hide timer. log->timer = LOG_MSG_TIMEOUT; log->visible = true; } /** * Remove the oldest message from the msglog. * * @param log Ptr to the msglog. */ static void logPop(msglog_t* log) { int oldest; logmsg_t* msg; if(log->numVisibleMsgs == 0) return; oldest = (unsigned) log->nextMsg - log->numVisibleMsgs; if(oldest < 0) oldest += LOG_MAX_MESSAGES; msg = &log->msgs[oldest]; msg->ticsRemain = 10; msg->flags &= ~MF_JUSTADDED; log->numVisibleMsgs--; } /** * Tick the given msglog. Jobs include ticking messages and adjusting values * used when drawing the buffer for animation. * * @param log Ptr to the msglog to tick. */ static void logTicker(msglog_t* log) { int i; // Don't tick if the game is paused. if(P_IsPaused()) return; // All messags tic away. When lower than lineheight, offset the y origin // of the message log. When zero, the earliest is pop'd. for(i = 0; i < LOG_MAX_MESSAGES; ++i) { logmsg_t* msg = &log->msgs[i]; if(msg->ticsRemain > 0) msg->ticsRemain--; } if(log->numVisibleMsgs) { int oldest; logmsg_t* msg; oldest = (unsigned) log->nextMsg - log->numVisibleMsgs; if(oldest < 0) oldest += LOG_MAX_MESSAGES; msg = &log->msgs[oldest]; log->yOffset = 0; if(msg->ticsRemain == 0) { logPop(log); } else { if(msg->ticsRemain <= LINEHEIGHT_A) log->yOffset = LINEHEIGHT_A - msg->ticsRemain; } } // Tic the auto-hide timer. if(log->timer > 0) log->timer--; if(log->timer == 0) { log->visible = false; log->notToBeFuckedWith = false; } } /** * Draws the contents of the given msglog to the screen. * * @param log Ptr to the msglog to draw. */ static void logDrawer(msglog_t* log) { uint i, numVisible; int n, x, y; // How many messages should we print? switch(cfg.msgAlign) { default: case ALIGN_LEFT: x = 0; break; case ALIGN_CENTER: x = SCREENWIDTH/2; break; case ALIGN_RIGHT: x = SCREENWIDTH; break; } // First 'num' messages starting from the first one. numVisible = MIN_OF(log->numVisibleMsgs, (unsigned) cfg.msgCount); n = log->nextMsg - numVisible; if(n < 0) n += LOG_MAX_MESSAGES; y = 0; Draw_BeginZoom(cfg.msgScale, x, 0); DGL_Translatef(0, -log->yOffset, 0); for(i = 0; i < numVisible; ++i, y += LINEHEIGHT_A) { logmsg_t* msg = &log->msgs[n]; float col[4]; // Default colour and alpha. col[CR] = cfg.msgColor[CR]; col[CG] = cfg.msgColor[CG]; col[CB] = cfg.msgColor[CB]; col[CA] = 1; if(msg->flags & MF_JUSTADDED) { uint msgTics, td, blinkSpeed = cfg.msgBlink; msgTics = msg->tics - msg->ticsRemain; td = (cfg.msgUptime * TICSPERSEC) - msg->ticsRemain; if((td & 2) && blinkSpeed != 0 && msgTics < blinkSpeed) { // Flash color. col[CR] = col[CG] = col[CB] = 1; } else if(blinkSpeed != 0 && msgTics < blinkSpeed + LOG_MSG_FLASHFADETICS && msgTics >= blinkSpeed) { int c; // Fade color to normal. for(c = 0; c < 3; ++c) col[c] += ((1.0f - col[c]) / LOG_MSG_FLASHFADETICS) * (blinkSpeed + LOG_MSG_FLASHFADETICS - msgTics); } } else { // Fade alpha out. if(i == 0 && msg->ticsRemain <= LINEHEIGHT_A) col[CA] = msg->ticsRemain / (float) LINEHEIGHT_A * .9f; } // Draw using param text. // Messages may use the params to override the way the message is // is displayed, e.g. colour (Hexen's important messages). WI_DrawParamText(x, 1 + y, msg->text, GF_FONTA, col[CR], col[CG], col[CB], col[CA], false, false, cfg.msgAlign); n = (n < LOG_MAX_MESSAGES - 1)? n + 1 : 0; } Draw_EndZoom(); } /** * Initialize the message log of the specified player. Typically called after * map load or when said player enters the world. * * @param player Player (local) number whose message log to init. */ void Hu_LogStart(int player) { player_t* plr; msglog_t* log; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; log = &msgLogs[player]; memset(log, 0, sizeof(msglog_t)); } /** * Called during final shutdown. */ void Hu_LogShutdown(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { msglog_t* log = &msgLogs[i]; int j; for(j = 0; j < LOG_MAX_MESSAGES; ++j) { logmsg_t* msg = &log->msgs[j]; if(msg->text) free(msg->text); msg->text = NULL; msg->maxLen = 0; } log->msgCount = log->numVisibleMsgs = 0; } } /** * Called TICSPERSEC times a second. */ void Hu_LogTicker(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { logTicker(&msgLogs[i]); } } /** * Draw the message log of the specified player. * * @param player Player (local) number whose message log to draw. */ void Hu_LogDrawer(int player) { if(cfg.msgShow) { logDrawer(&msgLogs[player]); } } /** * Post a message to the specified player's log. * * @param player Player (local) number whose log to post to. * @param flags LMF_* flags * LMF_NOHIDE: * Always display this message regardless whether the * player's message log has been hidden. * LMF_YELLOW: * Prepend the YELLOW param string to msg. * @param msg Message text to be posted. */ void Hu_LogPost(int player, byte flags, const char* msg) { #define YELLOW_FMT "{r=1; g=0.7; b=0.3;}" #define YELLOW_FMT_LEN 19 #define SMALLBUF_MAXLEN 128 player_t* plr; msglog_t* log; if(!msg || !msg[0]) return; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; log = &msgLogs[player]; if(!log->notToBeFuckedWith || log->dontFuckWithMe) { char smallBuf[SMALLBUF_MAXLEN+1]; char* bigBuf = NULL, *p; size_t requiredLen = strlen(msg) + ((flags & LMF_YELLOW)? YELLOW_FMT_LEN : 0); if(requiredLen <= SMALLBUF_MAXLEN) { p = smallBuf; } else { bigBuf = malloc(requiredLen + 1); p = bigBuf; } p[requiredLen] = '\0'; if(flags & LMF_YELLOW) sprintf(p, YELLOW_FMT "%s", msg); else sprintf(p, "%s", msg); logPush(log, p, cfg.msgUptime * TICSPERSEC); if(bigBuf) free(bigBuf); } #undef YELLOW_FMT #undef YELLOW_FMT_LEN #undef SMALLBUF_MAXLEN } /** * Rewind the message log of the specified player, making the last few * messages visible again. * * @param player Player (local) number whose message log to refresh. */ void Hu_LogRefresh(int player) { uint i; int n; player_t* plr; msglog_t* log; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; log = &msgLogs[player]; log->visible = true; log->numVisibleMsgs = MIN_OF((unsigned) cfg.msgCount, MIN_OF(log->msgCount, (unsigned) LOG_MAX_MESSAGES)); // Reset the auto-hide timer. log->timer = LOG_MSG_TIMEOUT; // Refresh the messages. n = log->nextMsg - log->numVisibleMsgs; if(n < 0) n += LOG_MAX_MESSAGES; for(i = 0; i < log->numVisibleMsgs; ++i) { logmsg_t* msg = &log->msgs[n]; // Change the tics remaining to that at post time plus a small bonus // so that they don't all disappear at once. msg->ticsRemain = msg->tics + i * (TICSPERSEC >> 2); msg->flags &= ~MF_JUSTADDED; n = (n < LOG_MAX_MESSAGES - 1)? n + 1 : 0; } } /** * Empty the message log of the specified player. * * @param player Player (local) number whose message log to empty. */ void Hu_LogEmpty(int player) { player_t* plr; msglog_t* log; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; log = &msgLogs[player]; while(log->numVisibleMsgs) logPop(log); } /**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_chat.c: HUD chat widget. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "hu_stuff.h" #include "hu_log.h" #include "hu_lib.h" #include "p_tick.h" // for P_IsPaused() #include "g_common.h" #include "g_controls.h" #include "d_net.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- #if __JHEXEN__ enum { CT_PLR_BLUE = 1, CT_PLR_RED, CT_PLR_YELLOW, CT_PLR_GREEN, CT_PLR_PLAYER5, CT_PLR_PLAYER6, CT_PLR_PLAYER7, CT_PLR_PLAYER8 }; #endif // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdMsgAction); DEFCC(CCmdLocalMessage); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void closeChat(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean shiftdown = false; boolean chatOn; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ char* player_names[4]; int player_names_idx[] = { TXT_HUSTR_PLRGREEN, TXT_HUSTR_PLRINDIGO, TXT_HUSTR_PLRBROWN, TXT_HUSTR_PLRRED }; #else char* player_names[8]; int player_names_idx[] = { CT_PLR_BLUE, CT_PLR_RED, CT_PLR_YELLOW, CT_PLR_GREEN, CT_PLR_PLAYER5, CT_PLR_PLAYER6, CT_PLR_PLAYER7, CT_PLR_PLAYER8 }; #endif cvar_t chatCVars[] = { // Chat macros {"chat-macro0", 0, CVT_CHARPTR, &cfg.chatMacros[0], 0, 0}, {"chat-macro1", 0, CVT_CHARPTR, &cfg.chatMacros[1], 0, 0}, {"chat-macro2", 0, CVT_CHARPTR, &cfg.chatMacros[2], 0, 0}, {"chat-macro3", 0, CVT_CHARPTR, &cfg.chatMacros[3], 0, 0}, {"chat-macro4", 0, CVT_CHARPTR, &cfg.chatMacros[4], 0, 0}, {"chat-macro5", 0, CVT_CHARPTR, &cfg.chatMacros[5], 0, 0}, {"chat-macro6", 0, CVT_CHARPTR, &cfg.chatMacros[6], 0, 0}, {"chat-macro7", 0, CVT_CHARPTR, &cfg.chatMacros[7], 0, 0}, {"chat-macro8", 0, CVT_CHARPTR, &cfg.chatMacros[8], 0, 0}, {"chat-macro9", 0, CVT_CHARPTR, &cfg.chatMacros[9], 0, 0}, {"chat-beep", 0, CVT_BYTE, &cfg.chatBeep, 0, 1}, {NULL} }; // Console commands for the chat widget and message log. ccmd_t chatCCmds[] = { {"chatcancel", "", CCmdMsgAction}, {"chatcomplete", "", CCmdMsgAction}, {"chatdelete", "", CCmdMsgAction}, {"chatsendmacro", NULL, CCmdMsgAction}, {"beginchat", NULL, CCmdMsgAction}, {"message", "s", CCmdLocalMessage}, {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int chatTo = 0; // 0=all, 1=player 0, etc. static hu_text_t chat; static hu_text_t chatBuffer[MAXPLAYERS]; static boolean chatAlwaysOff = false; // CODE -------------------------------------------------------------------- /** * Called during the PreInit of each game during start up. * Register Cvars and CCmds for the opperation/look of the (message) log. */ void Chat_Register(void) { int i; for(i = 0; chatCVars[i].name; ++i) Con_AddVariable(chatCVars + i); for(i = 0; chatCCmds[i].name; ++i) Con_AddCommand(chatCCmds + i); } /** * Called by HU_init(). */ void Chat_Init(void) { int i; // Setup strings. for(i = 0; i < 10; ++i) { if(!cfg.chatMacros[i]) // Don't overwrite if already set. cfg.chatMacros[i] = GET_TXT(TXT_HUSTR_CHATMACRO0 + i); } } /** * Called by HU_Start(). */ void Chat_Start(void) { int i; // Create the chat widget HUlib_initText(&chat, 0, M_CharHeight('A', GF_FONTA) + 1, &chatOn); for(i = 0; i < MAXPLAYERS; ++i) { Chat_Open(i, false); // Create the input buffers. HUlib_initText(&chatBuffer[i], 0, 0, &chatAlwaysOff); } } void Chat_Open(int player, boolean open) { if(open) { chatOn = true; chatTo = player; HUlib_resetText(&chat); // Enable the chat binding class DD_Execute(true, "activatebcontext chat"); } else { if(chatOn) { chatOn = false; // Disable the chat binding class DD_Execute(true, "deactivatebcontext chat"); } } } boolean Chat_Responder(event_t* ev) { boolean eatkey = false; unsigned char c; if(!chatOn || G_GetGameState() != GS_MAP) return false; if(ev->type != EV_KEY) return false; if(ev->data1 == DDKEY_RSHIFT) { shiftdown = (ev->state == EVS_DOWN || ev->state == EVS_REPEAT); return false; } if(ev->state != EVS_DOWN) return false; c = (unsigned char) ev->data1; if(shiftdown) c = shiftXForm[c]; eatkey = HUlib_keyInText(&chat, c); return eatkey; } void Chat_Drawer(int player) { if(player == CONSOLEPLAYER) HUlib_drawText(&chat, GF_FONTA); } /** * Sends a string to other player(s) as a chat message. */ static void sendMessage(const char* msg) { char buff[256]; int i; if(chatTo == 0) { // Send the message to the other players explicitly, if(!IS_NETGAME) { // Send it locally. for(i = 0; i < MAXPLAYERS; ++i) { D_NetMessageNoSound(i, msg); } } else { strcpy(buff, "chat "); M_StrCatQuoted(buff, msg, 256); DD_Execute(false, buff); } } else { // Send to all of the destination color. chatTo -= 1; for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame && cfg.playerColor[i] == chatTo) { if(!IS_NETGAME) { // Send it locally. D_NetMessageNoSound(i, msg); } else { sprintf(buff, "chatNum %d ", i); M_StrCatQuoted(buff, msg, 256); DD_Execute(false, buff); } } } #if __JDOOM__ if(gameMode == commercial) S_LocalSound(SFX_RADIO, 0); else S_LocalSound(SFX_TINK, 0); #elif __JDOOM64__ S_LocalSound(SFX_RADIO, 0); #endif } /** * Sets the chat buffer to a chat macro string. */ static boolean sendMacro(int player, int num) { if(num >= 0 && num < 9) { // Leave chat mode and notify that it was sent. if(chatOn) Chat_Open(player, false); sendMessage(cfg.chatMacros[num]); return true; } return false; } /** * Display a local game message. */ DEFCC(CCmdLocalMessage) { D_NetMessageNoSound(CONSOLEPLAYER, argv[1]); return true; } /** * Handles controls (console commands) for the chat widget. */ DEFCC(CCmdMsgAction) { int toPlayer; if(G_GetGameAction() == GA_QUIT) return false; if(chatOn) { if(!stricmp(argv[0], "chatcomplete")) // send the message { Chat_Open(CONSOLEPLAYER, false); if(chat.l.len) { sendMessage(chat.l.l); } } else if(!stricmp(argv[0], "chatcancel")) // close chat { Chat_Open(CONSOLEPLAYER, false); } else if(!stricmp(argv[0], "chatdelete")) { HUlib_delCharFromText(&chat); } } if(!stricmp(argv[0], "chatsendmacro")) // send a chat macro { int macroNum; if(argc < 2 || argc > 3) { Con_Message("Usage: %s (player) (macro number)\n", argv[0]); Con_Message("Send a chat macro to other player(s).\n" "If (player) is omitted, the message will be sent to all players.\n"); return true; } if(argc == 3) { toPlayer = atoi(argv[1]); if(toPlayer < 0 || toPlayer > 3) { // Bad destination. Con_Message("Invalid player number \"%i\". Should be 0-3\n", toPlayer); return false; } toPlayer = toPlayer + 1; } else toPlayer = 0; macroNum = atoi(((argc == 3)? argv[2] : argv[1])); if(!sendMacro(CONSOLEPLAYER, macroNum)) { Con_Message("Invalid macro number\n"); return false; } } else if(!stricmp(argv[0], "beginchat")) // begin chat mode { if(chatOn) return false; if(argc == 2) { toPlayer = atoi(argv[1]); if(toPlayer < 0 || toPlayer > 3) { // Bad destination. Con_Message("Invalid player number \"%i\". Should be 0-3\n", toPlayer); return false; } toPlayer = toPlayer + 1; } else toPlayer = 0; Chat_Open(toPlayer, true); } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/m_multi.c0000644000175000017500000006661411357170242022454 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_multi.c: Multiplayer Menu (for jDoom, jHeretic and jHexen). * * Contains an extension for edit fields. * \todo Remove unnecessary SC* declarations and other unused code. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "hu_stuff.h" #include "hu_menu.h" // MACROS ------------------------------------------------------------------ #define SLOT_WIDTH (200) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void DrawMultiplayerMenu(void); void DrawGameSetupMenu(void); void DrawPlayerSetupMenu(void); void SCEnterHostMenu(int option, void* data); void SCEnterJoinMenu(int option, void* data); void SCEnterGameSetup(int option, void* data); void SCSetProtocol(int option, void* data); void SCGameSetupFunc(int option, void* data); void SCGameSetupEpisode(int option, void* data); void SCGameSetupMap(int option, void* data); void SCGameSetupSkill(int option, void* data); void SCGameSetupDeathmatch(int option, void* data); void SCGameSetupDamageMod(int option, void* data); void SCGameSetupHealthMod(int option, void* data); void SCGameSetupGravity(int option, void* data); void SCOpenServer(int option, void* data); void SCCloseServer(int option, void* data); void SCChooseHost(int option, void* data); void SCStartStopDisconnect(int option, void* data); void SCEnterPlayerSetupMenu(int option, void* data); void SCPlayerClass(int option, void* data); void SCPlayerColor(int option, void* data); void SCAcceptPlayer(int option, void* data); void ResetJoinMenuItems(); // Edit fields. void DrawEditField(menu_t* menu, int index, editfield_t* ef); void SCEditField(int efptr, void* data); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- editfield_t* ActiveEdit = NULL; // No active edit field by default. editfield_t plrNameEd; int CurrentPlrFrame = 0; menuitem_t MultiplayerItems[] = { {ITT_EFUNC, 0, "player setup", SCEnterPlayerSetupMenu, 0 }, {ITT_EFUNC, 0, "join game", SCEnterJoinMenu, 0 }, {ITT_EFUNC, 0, "host game", SCEnterHostMenu, 0 }, }; menuitem_t MultiplayerServerItems[] = { {ITT_EFUNC, 0, "player setup", SCEnterPlayerSetupMenu, 0 }, {ITT_EFUNC, 0, "game setup", SCEnterHostMenu, 0 }, {ITT_EFUNC, 0, "close server", SCCloseServer, 0 } }; menuitem_t MultiplayerClientItems[] = { {ITT_EFUNC, 0, "player setup", SCEnterPlayerSetupMenu, 0 }, {ITT_EFUNC, 0, "disconnect", SCEnterJoinMenu, 0 } }; menu_t MultiplayerMenu = { 0, 116, 70, DrawMultiplayerMenu, 3, MultiplayerItems, 0, MENU_NEWGAME, GF_FONTA,cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, 3 }; #if __JHEXEN__ || __JSTRIFE__ # define NUM_GAMESETUP_ITEMS 11 menuitem_t GameSetupItems1[] = { {ITT_LRFUNC, 0, "MAP:", SCGameSetupMap, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_LRFUNC, 0, "SKILL:", SCGameSetupSkill, 0}, {ITT_EFUNC, 0, "DEATHMATCH:", SCGameSetupFunc, 0, NULL, &cfg.netDeathmatch }, {ITT_EFUNC, 0, "MONSTERS:", SCGameSetupFunc, 0, NULL, &cfg.netNoMonsters }, {ITT_EFUNC, 0, "RANDOM CLASSES:", SCGameSetupFunc, 0, NULL, &cfg.netRandomClass }, {ITT_EFUNC, 0, "NO MAX Z RADIUS ATTACKS", SCGameSetupFunc, 0, NULL, &cfg.netNoMaxZRadiusAttack }, {ITT_LRFUNC, 0, "DAMAGE MULTIPLIER:", SCGameSetupDamageMod, 0}, {ITT_LRFUNC, 0, "HEALTH MULTIPLIER:", SCGameSetupHealthMod, 0}, {ITT_LRFUNC, 0, "GRAVITY MULTIPLIER:", SCGameSetupGravity, 0}, {ITT_EFUNC, 0, "PROCEED...", SCOpenServer, 0} }; #else # if __JHERETIC__ # define NUM_GAMESETUP_ITEMS 14 menuitem_t GameSetupItems1[] = // for Heretic { {ITT_LRFUNC, 0, "EPISODE :", SCGameSetupEpisode, 0}, {ITT_LRFUNC, 0, "MAP :", SCGameSetupMap, 0}, {ITT_LRFUNC, 0, "SKILL :", SCGameSetupSkill, 0}, {ITT_LRFUNC, 0, "DEATHMATCH :", SCGameSetupDeathmatch, 0}, {ITT_EFUNC, 0, "MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netNoMonsters }, {ITT_EFUNC, 0, "RESPAWN MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netRespawn }, {ITT_EFUNC, 0, "ALLOW JUMPING :", SCGameSetupFunc, 0, NULL, &cfg.netJumping }, {ITT_EFUNC, 0, "NO COOP DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noCoopDamage }, {ITT_EFUNC, 0, "NO TEAM DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noTeamDamage }, {ITT_EFUNC, 0, "NO MAX Z RADIUS ATTACKS", SCGameSetupFunc, 0, NULL, &cfg.netNoMaxZRadiusAttack }, {ITT_LRFUNC, 0, "DAMAGE MULTIPLIER:", SCGameSetupDamageMod, 0}, {ITT_LRFUNC, 0, "HEALTH MULTIPLIER:", SCGameSetupHealthMod, 0}, {ITT_LRFUNC, 0, "GRAVITY MULTIPLIER:", SCGameSetupGravity, 0}, {ITT_EFUNC, 0, "PROCEED...", SCOpenServer, 0 } }; # elif __JDOOM__ # define NUM_GAMESETUP_ITEMS 19 menuitem_t GameSetupItems1[] = // for Doom 1 { {ITT_LRFUNC, 0, "EPISODE :", SCGameSetupEpisode, 0}, {ITT_LRFUNC, 0, "MAP :", SCGameSetupMap, 0}, {ITT_LRFUNC, 0, "SKILL :", SCGameSetupSkill, 0}, {ITT_LRFUNC, 0, "MODE :", SCGameSetupDeathmatch, 0}, {ITT_EFUNC, 0, "MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netNoMonsters }, {ITT_EFUNC, 0, "RESPAWN MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netRespawn }, {ITT_EFUNC, 0, "ALLOW JUMPING :", SCGameSetupFunc, 0, NULL, &cfg.netJumping }, {ITT_EFUNC, 0, "ALLOW BFG AIMING :", SCGameSetupFunc, 0, NULL, &cfg.netBFGFreeLook}, {ITT_EFUNC, 0, "NO COOP DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noCoopDamage }, {ITT_EFUNC, 0, "NO COOP WEAPONS :", SCGameSetupFunc, 0, NULL, &cfg.noCoopWeapons }, {ITT_EFUNC, 0, "NO COOP OBJECTS :", SCGameSetupFunc, 0, NULL, &cfg.noCoopAnything }, {ITT_EFUNC, 0, "COOP ITEMS RESPAWN :", SCGameSetupFunc, 0, NULL, &cfg.coopRespawnItems }, {ITT_EFUNC, 0, "NO BFG 9000 :", SCGameSetupFunc, 0, NULL, &cfg.noNetBFG }, {ITT_EFUNC, 0, "NO TEAM DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noTeamDamage }, {ITT_EFUNC, 0, "NO MAX Z RADIUS ATTACKS", SCGameSetupFunc, 0, NULL, &cfg.netNoMaxZRadiusAttack }, {ITT_LRFUNC, 0, "DAMAGE MULTIPLIER:", SCGameSetupDamageMod, 0}, {ITT_LRFUNC, 0, "HEALTH MULTIPLIER:", SCGameSetupHealthMod, 0}, {ITT_LRFUNC, 0, "GRAVITY MULTIPLIER:", SCGameSetupGravity, 0}, {ITT_EFUNC, 0, "PROCEED...", SCOpenServer, 0 } }; menuitem_t GameSetupItems2[] = // for Doom 2 { {ITT_LRFUNC, 0, "MAP :", SCGameSetupMap, 0}, {ITT_LRFUNC, 0, "SKILL :", SCGameSetupSkill, 0}, {ITT_LRFUNC, 0, "MODE :", SCGameSetupDeathmatch, 0}, {ITT_EFUNC, 0, "MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netNoMonsters }, {ITT_EFUNC, 0, "RESPAWN MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netRespawn }, {ITT_EFUNC, 0, "ALLOW JUMPING :", SCGameSetupFunc, 0, NULL, &cfg.netJumping }, {ITT_EFUNC, 0, "ALLOW BFG AIMING :", SCGameSetupFunc, 0, NULL, &cfg.netBFGFreeLook}, {ITT_EFUNC, 0, "NO COOP DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noCoopDamage }, {ITT_EFUNC, 0, "NO COOP WEAPONS :", SCGameSetupFunc, 0, NULL, &cfg.noCoopWeapons }, {ITT_EFUNC, 0, "NO COOP OBJECTS :", SCGameSetupFunc, 0, NULL, &cfg.noCoopAnything }, {ITT_EFUNC, 0, "COOP ITEMS RESPAWN :", SCGameSetupFunc, 0, NULL, &cfg.coopRespawnItems }, {ITT_EFUNC, 0, "NO BFG 9000 :", SCGameSetupFunc, 0, NULL, &cfg.noNetBFG }, {ITT_EFUNC, 0, "NO TEAM DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noTeamDamage }, {ITT_EFUNC, 0, "NO MAX Z RADIUS ATTACKS", SCGameSetupFunc, 0, NULL, &cfg.netNoMaxZRadiusAttack }, {ITT_LRFUNC, 0, "DAMAGE MULTIPLIER:", SCGameSetupDamageMod, 0}, {ITT_LRFUNC, 0, "HEALTH MULTIPLIER:", SCGameSetupHealthMod, 0}, {ITT_LRFUNC, 0, "GRAVITY MULTIPLIER:", SCGameSetupGravity, 0}, {ITT_EFUNC, 0, "PROCEED...", SCOpenServer, 0 } }; # elif __JDOOM64__ # define NUM_GAMESETUP_ITEMS 18 menuitem_t GameSetupItems1[] = { {ITT_LRFUNC, 0, "MAP :", SCGameSetupMap, 0}, {ITT_LRFUNC, 0, "SKILL :", SCGameSetupSkill, 0}, {ITT_LRFUNC, 0, "MODE :", SCGameSetupDeathmatch, 0}, {ITT_EFUNC, 0, "MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netNoMonsters }, {ITT_EFUNC, 0, "RESPAWN MONSTERS :", SCGameSetupFunc, 0, NULL, &cfg.netRespawn }, {ITT_EFUNC, 0, "ALLOW JUMPING :", SCGameSetupFunc, 0, NULL, &cfg.netJumping }, {ITT_EFUNC, 0, "ALLOW BFG AIMING :", SCGameSetupFunc, 0, NULL, &cfg.netBFGFreeLook}, {ITT_EFUNC, 0, "NO COOP DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noCoopDamage }, {ITT_EFUNC, 0, "NO COOP WEAPONS :", SCGameSetupFunc, 0, NULL, &cfg.noCoopWeapons }, {ITT_EFUNC, 0, "NO COOP OBJECTS :", SCGameSetupFunc, 0, NULL, &cfg.noCoopAnything }, {ITT_EFUNC, 0, "COOP ITEMS RESPAWN :", SCGameSetupFunc, 0, NULL, &cfg.coopRespawnItems }, {ITT_EFUNC, 0, "NO BFG 9000 :", SCGameSetupFunc, 0, NULL, &cfg.noNetBFG }, {ITT_EFUNC, 0, "NO TEAM DAMAGE :", SCGameSetupFunc, 0, NULL, &cfg.noTeamDamage }, {ITT_EFUNC, 0, "NO MAX Z RADIUS ATTACKS", SCGameSetupFunc, 0, NULL, &cfg.netNoMaxZRadiusAttack }, {ITT_LRFUNC, 0, "DAMAGE MULTIPLIER:", SCGameSetupDamageMod, 0}, {ITT_LRFUNC, 0, "HEALTH MULTIPLIER:", SCGameSetupHealthMod, 0}, {ITT_LRFUNC, 0, "GRAVITY MULTIPLIER:", SCGameSetupGravity, 0}, {ITT_EFUNC, 0, "PROCEED...", SCOpenServer, 0 } }; # endif #endif menu_t GameSetupMenu = { 0, # if __JDOOM__ || __JDOOM64__ 90, 54, # elif __JHERETIC__ 74, 64, # elif __JHEXEN__ || __JSTRIFE__ 90, 64, # endif DrawGameSetupMenu, NUM_GAMESETUP_ITEMS, GameSetupItems1, 0, MENU_MULTIPLAYER, GF_FONTA, //1, 0, 0, cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, NUM_GAMESETUP_ITEMS }; #if __JHEXEN__ || __JSTRIFE__ # define NUM_PLAYERSETUP_ITEMS 6 #else # define NUM_PLAYERSETUP_ITEMS 6 #endif menuitem_t PlayerSetupItems[] = { {ITT_EFUNC, 0, "", SCEditField, 0, NULL, &plrNameEd }, {ITT_EMPTY, 0, NULL, NULL, 0}, #if __JHEXEN__ {ITT_LRFUNC, 0, "Class:", SCPlayerClass, 0}, #else {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_LRFUNC, 0, "Color:", SCPlayerColor, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EFUNC, 0, "Accept Changes", SCAcceptPlayer, 0 } }; menu_t PlayerSetupMenu = { 0, 60, 52, DrawPlayerSetupMenu, NUM_PLAYERSETUP_ITEMS, PlayerSetupItems, 0, MENU_MULTIPLAYER, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B, 0, NUM_PLAYERSETUP_ITEMS }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int plrColor; #if __JHEXEN__ static int plrClass; #endif // CODE -------------------------------------------------------------------- int Executef(int silent, char* format, ...) { va_list argptr; char buffer[512]; va_start(argptr, format); dd_vsnprintf(buffer, sizeof(buffer), format, argptr); va_end(argptr); return DD_Execute(silent, buffer); } void DrANumber(int number, int x, int y) { char buff[40]; sprintf(buff, "%i", number); M_WriteText2(x, y, buff, GF_FONTA, 1, 1, 1, Hu_MenuAlpha()); } void MN_DrCenterTextA_CS(char* text, int centerX, int y) { M_WriteText2(centerX - M_StringWidth(text, GF_FONTA) / 2, y, text, GF_FONTA, 1, 0, 0, Hu_MenuAlpha()); } void MN_DrCenterTextB_CS(char *text, int centerX, int y) { M_WriteText2(centerX - M_StringWidth(text, GF_FONTB) / 2, y, text, GF_FONTB, 1, 0, 0, Hu_MenuAlpha()); } void DrawMultiplayerMenu(void) { M_DrawTitle(GET_TXT(TXT_MULTIPLAYER), MultiplayerMenu.y - 30); } void DrawGameSetupMenu(void) { char* boolText[] = {"NO", "YES"}; char* skillText[] = {"BABY", "EASY", "MEDIUM", "HARD", "NIGHTMARE"}; #if __JDOOM__ || __JDOOM64__ //char* freeLookText[3] = {"NO", "NOT BFG", "ALL"}; char* dmText[] = {"COOPERATIVE", "DEATHMATCH 1", "DEATHMATCH 2"}; #else char* dmText[] = {"NO", "YES", "YES"}; #endif char buf[50]; menu_t* menu = &GameSetupMenu; int idx; #if __JHEXEN__ char* mapName = P_GetMapName(P_TranslateMap(cfg.netMap)); #elif __JSTRIFE__ char* mapName = "unnamed"; #endif M_DrawTitle(GET_TXT(TXT_GAMESETUP), menu->y - 20); idx = 0; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ # if __JDOOM__ || __JHERETIC__ # if __JDOOM__ if(gameMode != commercial) # endif { sprintf(buf, "%u", cfg.netEpisode+1); M_WriteMenuText(menu, idx++, buf); } # endif sprintf(buf, "%u", cfg.netMap+1); M_WriteMenuText(menu, idx++, buf); M_WriteMenuText(menu, idx++, skillText[cfg.netSkill]); M_WriteMenuText(menu, idx++, dmText[cfg.netDeathmatch]); M_WriteMenuText(menu, idx++, boolText[!cfg.netNoMonsters]); M_WriteMenuText(menu, idx++, boolText[cfg.netRespawn]); M_WriteMenuText(menu, idx++, boolText[cfg.netJumping]); # if __JDOOM__ || __JDOOM64__ M_WriteMenuText(menu, idx++, boolText[cfg.netBFGFreeLook]); # endif // __JDOOM__ || __JDOOM64__ M_WriteMenuText(menu, idx++, boolText[cfg.noCoopDamage]); # if __JDOOM__ || __JDOOM64__ M_WriteMenuText(menu, idx++, boolText[cfg.noCoopWeapons]); M_WriteMenuText(menu, idx++, boolText[cfg.noCoopAnything]); M_WriteMenuText(menu, idx++, boolText[cfg.coopRespawnItems]); M_WriteMenuText(menu, idx++, boolText[cfg.noNetBFG]); # endif // __JDOOM__ || __JDOOM64__ M_WriteMenuText(menu, idx++, boolText[cfg.noTeamDamage]); #elif __JHEXEN__ || __JSTRIFE__ sprintf(buf, "%u", cfg.netMap+1); M_WriteMenuText(menu, idx++, buf); M_WriteText2(160 - M_StringWidth(mapName, GF_FONTA) / 2, menu->y + menu->itemHeight, mapName, GF_FONTA, 1, 0.7f, 0.3f, Hu_MenuAlpha()); idx++; M_WriteMenuText(menu, idx++, skillText[cfg.netSkill]); M_WriteMenuText(menu, idx++, dmText[cfg.netDeathmatch]); M_WriteMenuText(menu, idx++, boolText[!cfg.netNoMonsters]); M_WriteMenuText(menu, idx++, boolText[cfg.netRandomClass]); #endif // __JHEXEN__ M_WriteMenuText(menu, idx++, boolText[cfg.netNoMaxZRadiusAttack]); sprintf(buf, "%i", cfg.netMobDamageModifier); M_WriteMenuText(menu, idx++, buf); sprintf(buf, "%i", cfg.netMobHealthModifier); M_WriteMenuText(menu, idx++, buf); if(cfg.netGravity != -1) sprintf(buf, "%i", cfg.netGravity); else sprintf(buf, "MAP DEFAULT"); M_WriteMenuText(menu, idx++, buf); } void DrawPlayerSetupMenu(void) { #define AVAILABLE_WIDTH 38 #define AVAILABLE_HEIGHT 52 spriteinfo_t sprInfo; menu_t* menu = &PlayerSetupMenu; int useColor = plrColor; float menuAlpha = Hu_MenuAlpha(); int tclass = 0; #if __JHEXEN__ int numColors = 8; static const int sprites[3] = {SPR_PLAY, SPR_CLER, SPR_MAGE}; #else int plrClass = 0; int numColors = 4; static const int sprites[3] = {SPR_PLAY, SPR_PLAY, SPR_PLAY}; #endif float x, y, w, h, w2, h2; float s, t, scale; M_DrawTitle(GET_TXT(TXT_PLAYERSETUP), menu->y - 28); DrawEditField(menu, 0, &plrNameEd); if(useColor == numColors) useColor = menuTime / 5 % numColors; #if __JHEXEN__ R_GetTranslation(plrClass, useColor, &tclass, &useColor); #endif // Draw the color selection as a random player frame. R_GetSpriteInfo(sprites[plrClass], CurrentPlrFrame, &sprInfo); x = 162; #if __JDOOM__ || __JDOOM64__ y = menu->y + 70; #elif __JHERETIC__ y = menu->y + 80; #else y = menu->y + 90; #endif w = sprInfo.width; h = sprInfo.height; w2 = M_CeilPow2(w); h2 = M_CeilPow2(h); // Let's calculate texture coordinates. // To remove a possible edge artifact, move the corner a bit up/left. s = (w - 0.4f) / w2 + 1.f / sprInfo.offset; t = (h - 0.4f) / h2 + 1.f / sprInfo.topOffset; if(h > w) scale = AVAILABLE_HEIGHT / h; else scale = AVAILABLE_WIDTH / w; w *= scale; h *= scale; x -= sprInfo.width / 2 * scale; y -= sprInfo.height * scale; DGL_SetTranslatedSprite(sprInfo.material, tclass, useColor); DGL_Color4f(1, 1, 1, menuAlpha); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0 * s, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1 * s, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1 * s, t); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0 * s, t); DGL_Vertex2f(x, y + h); DGL_End(); if(plrColor == numColors) { M_WriteText2(184, #if __JDOOM__ || __JDOOM64__ menu->y + 49, #elif __JHERETIC__ menu->y + 65, #else menu->y + 64, #endif "AUTOMATIC", GF_FONTA, 1, 1, 1, menuAlpha); } #undef AVAILABLE_WIDTH #undef AVAILABLE_HEIGHT } void SCEnterMultiplayerMenu(int option, void* data) { int count; // Choose the correct items for the Game Setup menu. #if __JDOOM__ if(gameMode == commercial) { GameSetupMenu.items = GameSetupItems2; GameSetupMenu.itemCount = GameSetupMenu.numVisItems = NUM_GAMESETUP_ITEMS - 1; } else #endif { GameSetupMenu.items = GameSetupItems1; GameSetupMenu.itemCount = GameSetupMenu.numVisItems = NUM_GAMESETUP_ITEMS; } // Show the appropriate menu. if(IS_NETGAME) { MultiplayerMenu.items = IS_SERVER ? MultiplayerServerItems : MultiplayerClientItems; count = IS_SERVER ? 3 : 2; } else { MultiplayerMenu.items = MultiplayerItems; count = 3; } MultiplayerMenu.itemCount = MultiplayerMenu.numVisItems = count; MultiplayerMenu.lastOn = 0; M_SetupNextMenu(&MultiplayerMenu); } void SCEnterHostMenu(int option, void* data) { SCEnterGameSetup(0, NULL); } void SCEnterJoinMenu(int option, void* data) { if(IS_NETGAME) { DD_Execute(false, "net disconnect"); Hu_MenuCommand(MCMD_CLOSE); return; } DD_Execute(false, "net setup client"); } void SCEnterGameSetup(int option, void* data) { // See to it that the episode and map numbers are correct. #if __JDOOM64__ if(cfg.netMap > 31) cfg.netMap = 31; #elif __JDOOM__ if(gameMode == commercial) { cfg.netEpisode = 0; } else if(gameMode == retail) { if(cfg.netEpisode > 3) cfg.netEpisode = 3; if(cfg.netMap > 8) cfg.netMap = 8; } else if(gameMode == registered) { if(cfg.netEpisode > 2) cfg.netEpisode = 2; if(cfg.netMap > 8) cfg.netMap = 8; } else if(gameMode == shareware) { cfg.netEpisode = 0; if(cfg.netMap > 8) cfg.netMap = 8; } #elif __JHERETIC__ if(cfg.netMap > 8) cfg.netMap = 8; if(cfg.netEpisode > 5) cfg.netEpisode = 5; if(cfg.netEpisode == 5 && cfg.netMap > 2) cfg.netMap = 2; #elif __JHEXEN__ || __JSTRIFE__ if(cfg.netMap > 30) cfg.netMap = 30; #endif M_SetupNextMenu(&GameSetupMenu); } void SCGameSetupFunc(int option, void* data) { byte* ptr = data; *ptr ^= 1; } void SCGameSetupDeathmatch(int option, void* data) { if(option == RIGHT_DIR) { #if __JDOOM__ || __JDOOM64__ if(cfg.netDeathmatch < 2) #else if(cfg.netDeathmatch < 1) #endif cfg.netDeathmatch++; } else if(cfg.netDeathmatch > 0) { cfg.netDeathmatch--; } } #if __JDOOM__ || __JHERETIC__ void SCGameSetupEpisode(int option, void* data) { # if __JDOOM__ if(gameMode == shareware) { cfg.netEpisode = 0; return; } if(option == RIGHT_DIR) { if(cfg.netEpisode < (gameMode == retail ? 3 : 2)) cfg.netEpisode++; } else if(cfg.netEpisode != 0) { cfg.netEpisode--; } # elif __JHERETIC__ if(shareware) { cfg.netEpisode = 0; return; } if(option == RIGHT_DIR) { if(cfg.netEpisode < (gameMode == extended? 5 : 2)) cfg.netEpisode++; } else if(cfg.netEpisode != 0) { cfg.netEpisode--; } if(cfg.netMap > (cfg.netEpisode == 5? 2 : 8)) cfg.netMap = (cfg.netEpisode == 5? 2 : 8); # endif } #endif void SCGameSetupMap(int option, void* data) { if(option == RIGHT_DIR) { #if __JDOOM64__ if(cfg.netMap < 31) cfg.netMap++; #elif __JDOOM__ if(cfg.netMap < (gameMode == commercial ? 31 : 8)) cfg.netMap++; #elif __JHERETIC__ if(cfg.netMap < (cfg.netEpisode == 5? 2 : 8)) cfg.netMap++; #elif __JHEXEN__ || __JSTRIFE__ if(cfg.netMap < 30) cfg.netMap++; #endif } else if(cfg.netMap != 0) { cfg.netMap--; } } void SCGameSetupSkill(int option, void* data) { if(option == RIGHT_DIR) { if(cfg.netSkill < NUM_SKILL_MODES - 1) cfg.netSkill++; } else if(cfg.netSkill > 0) { cfg.netSkill--; } } void SCOpenServer(int option, void* data) { if(IS_NETGAME) { // Game already running, just change map. #if __JHEXEN__ || __JSTRIFE__ Executef(false, "setmap %u", cfg.netMap+1); #elif __JDOOM64__ Executef(false, "setmap 1 %u", cfg.netMap+1); #else Executef(false, "setmap %u %u", cfg.netEpisode+1, cfg.netMap+1); #endif Hu_MenuCommand(MCMD_CLOSE); return; } // Go to DMI to setup server. DD_Execute(false, "net setup server"); } void SCCloseServer(int option, void* data) { DD_Execute(false, "net server close"); Hu_MenuCommand(MCMD_CLOSE); } void SCEnterPlayerSetupMenu(int option, void* data) { strncpy(plrNameEd.text, *(char **) Con_GetVariable("net-name")->ptr, 255); plrColor = cfg.netColor; #if __JHEXEN__ plrClass = cfg.netClass; #endif M_SetupNextMenu(&PlayerSetupMenu); } #if __JHEXEN__ void SCPlayerClass(int option, void* data) { if(option == RIGHT_DIR) { if(plrClass < 2) plrClass++; } else if(plrClass > 0) plrClass--; } #endif void SCPlayerColor(int option, void* data) { if(option == RIGHT_DIR) { #if __JHEXEN__ if(plrColor < 8) plrColor++; #else if(plrColor < 4) plrColor++; #endif } else if(plrColor > 0) plrColor--; } void SCAcceptPlayer(int option, void* data) { char buf[300]; cfg.netColor = plrColor; #if __JHEXEN__ cfg.netClass = plrClass; #endif strcpy(buf, "net-name "); M_StrCatQuoted(buf, plrNameEd.text, 300); DD_Execute(false, buf); if(IS_NETGAME) { sprintf(buf, "setname "); M_StrCatQuoted(buf, plrNameEd.text, 300); DD_Execute(false, buf); #if __JHEXEN__ // Must do 'setclass' first; the real class and color do not change // until the server sends us a notification -- this means if we do // 'setcolor' first, the 'setclass' after it will override the color // change (or such would appear to be the case). Executef(false, "setclass %i", plrClass); #endif Executef(false, "setcolor %i", plrColor); } M_SetupNextMenu(&MultiplayerMenu); } void SCGameSetupDamageMod(int option, void* data) { if(option == RIGHT_DIR) { if(cfg.netMobDamageModifier < 100) cfg.netMobDamageModifier++; } else if(cfg.netMobDamageModifier > 1) cfg.netMobDamageModifier--; } void SCGameSetupHealthMod(int option, void* data) { if(option == RIGHT_DIR) { if(cfg.netMobHealthModifier < 20) cfg.netMobHealthModifier++; } else if(cfg.netMobHealthModifier > 1) cfg.netMobHealthModifier--; } void SCGameSetupGravity(int option, void* data) { if(option == RIGHT_DIR) { if(cfg.netGravity < 100) cfg.netGravity++; } else if(cfg.netGravity > -1) // -1 = map default, 0 = zero gravity. cfg.netGravity--; } /** * The extended ticker. */ void MN_TickerEx(void) { static int frameTimer = 0; if(currentMenu == &PlayerSetupMenu) { if(frameTimer++ >= 14) { frameTimer = 0; CurrentPlrFrame = M_Random() % 8; } } } int Ed_VisibleSlotChars(char* text, int (*widthFunc) (const char* text, gamefontid_t font)) { char cbuf[2] = { 0, 0 }; int i, w; for(i = 0, w = 0; text[i]; ++i) { cbuf[0] = text[i]; w += widthFunc(cbuf, GF_FONTA); if(w > SLOT_WIDTH) break; } return i; } void Ed_MakeCursorVisible(void) { char buf[MAX_EDIT_LEN + 1]; int i, len, vis; strcpy(buf, ActiveEdit->text); strupr(buf); strcat(buf, "_"); // The cursor. len = strlen(buf); for(i = 0; i < len; i++) { vis = Ed_VisibleSlotChars(buf + i, M_StringWidth); if(i + vis >= len) { ActiveEdit->firstVisible = i; break; } } } #if __JDOOM__ || __JDOOM64__ #define EDITFIELD_BOX_YOFFSET 3 #else #define EDITFIELD_BOX_YOFFSET 5 #endif void DrawEditField(menu_t* menu, int index, editfield_t* ef) { int vis; char buf[MAX_EDIT_LEN + 1], *text; int width = M_StringWidth("a", GF_FONTA) * 27; strcpy(buf, ef->text); strupr(buf); if(ActiveEdit == ef && menuTime & 0x8) strcat(buf, "_"); text = buf + ef->firstVisible; vis = Ed_VisibleSlotChars(text, M_StringWidth); text[vis] = 0; M_DrawSaveLoadBorder(menu->x - 8, menu->y + EDITFIELD_BOX_YOFFSET + (menu->itemHeight * index), width + 16); M_WriteText2(menu->x, menu->y + EDITFIELD_BOX_YOFFSET + 1 + (menu->itemHeight * index), text, GF_FONTA, 1, 1, 1, Hu_MenuAlpha()); } void SCEditField(int efptr, void* data) { editfield_t* ef = data; // Activate this edit field. ActiveEdit = ef; strcpy(ef->oldtext, ef->text); Ed_MakeCursorVisible(); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/m_ctrl.c0000644000175000017500000006262011357170242022257 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_ctrl.c: Common controls menu. */ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "hu_menu.h" #include "hu_stuff.h" // MACROS ------------------------------------------------------------------ #define NUM_CONTROLS_ITEMS 0 // Control config flags. #define CCF_NON_INVERSE 0x1 #define CCF_INVERSE 0x2 #define CCF_STAGED 0x4 #define CCF_REPEAT 0x8 #define CCF_SIDESTEP_MODIFIER 0x10 #define BIND_GAP 2 #define SMALL_SCALE .75f // Binding iteration flags for M_IterateBindings(). #define MIBF_IGNORE_REPEATS 0x1 // TYPES ------------------------------------------------------------------- typedef enum { MIBT_KEY, MIBT_MOUSE, MIBT_JOY } bindingitertype_t; /** Menu items in the Controls menu are created based on this data. */ typedef struct controlconfig_s { const char* itemText; const char* bindContext; const char* controlName; const char* command; int flags; // Automatically set: menuitem_t* item; } controlconfig_t; typedef struct bindingdrawerdata_s { int x; int y; } bindingdrawerdata_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void M_DrawControlsMenu(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void M_IterateBindings(controlconfig_t* cc, const char* bindings, int flags, void* data, void (*callback)(bindingitertype_t type, int bid, const char* event, boolean isInverse, void *data)); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- static menuitem_t* ControlsItems; #if __JDOOM__ || __JDOOM64__ menu_t ControlsDef = { MNF_NOHOTKEYS | MNF_DELETEFUNC, 32, 40, M_DrawControlsMenu, 0, NULL, 1, MENU_OPTIONS, GF_FONTA, //1, 0, 0, cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, 17, { 17, 40 } }; #endif #ifdef __JHERETIC__ menu_t ControlsDef = { MNF_NOHOTKEYS | MNF_DELETEFUNC, 32, 26, M_DrawControlsMenu, 0, NULL, 1, MENU_OPTIONS, GF_FONTA, //1, 0, 0, cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, 15, { 15, 26 } }; #endif #ifdef __JHEXEN__ menu_t ControlsDef = { MNF_NOHOTKEYS | MNF_DELETEFUNC, 32, 21, M_DrawControlsMenu, 0, NULL, 1, MENU_OPTIONS, GF_FONTA, //1, 0, 0, cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, 16, { 16, 21 } }; #endif // PUBLIC DATA DEFINITIONS ------------------------------------------------- controlconfig_t* grabbing = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static controlconfig_t controlConfig[] = { { "movement" }, { "forward", 0, "walk", 0, CCF_NON_INVERSE }, { "backward", 0, "walk", 0, CCF_INVERSE }, { "strafe left", 0, "sidestep", 0, CCF_INVERSE }, { "strafe right", 0, "sidestep", 0, CCF_NON_INVERSE }, { "turn left", 0, "turn", 0, CCF_STAGED | CCF_INVERSE | CCF_SIDESTEP_MODIFIER }, { "turn right", 0, "turn", 0, CCF_STAGED | CCF_NON_INVERSE | CCF_SIDESTEP_MODIFIER }, { "jump", 0, 0, "impulse jump" }, { "use", 0, 0, "impulse use" }, { "fly up", 0, "zfly", 0, CCF_STAGED | CCF_NON_INVERSE }, { "fly down", 0, "zfly", 0, CCF_STAGED | CCF_INVERSE }, { "fall to ground", 0, 0, "impulse falldown" }, { "speed", 0, "speed" }, { "strafe", 0, "strafe" }, { NULL }, { "looking" }, { "look up", 0, "look", 0, CCF_STAGED | CCF_NON_INVERSE }, { "look down", 0, "look", 0, CCF_STAGED | CCF_INVERSE }, { "look center", 0, 0, "impulse lookcenter" }, { NULL }, { "weapons" }, { "attack/fire", 0, "attack" }, { "next weapon", 0, 0, "impulse nextweapon" }, { "previous weapon", 0, 0, "impulse prevweapon" }, #if __JDOOM__ || __JDOOM64__ { "fist/chainsaw", 0, 0, "impulse weapon1" }, { "chainsaw/fist", 0, 0, "impulse weapon8" }, { "pistol", 0, 0, "impulse weapon2" }, { "shotgun/super sg", 0, 0, "impulse weapon3" }, { "super sg/shotgun", 0, 0, "impulse weapon9" }, { "chaingun", 0, 0, "impulse weapon4" }, { "rocket launcher", 0, 0, "impulse weapon5" }, { "plasma rifle", 0, 0, "impulse weapon6" }, { "bfg 9000", 0, 0, "impulse weapon7" }, #endif #if __JDOOM64__ { "unmaker", 0, 0, "impulse weapon10" }, #endif #if __JHERETIC__ { "staff/gauntlets", 0, 0, "impulse weapon1" }, { "elvenwand", 0, 0, "impulse weapon2" }, { "crossbow", 0, 0, "impulse weapon3" }, { "dragon claw", 0, 0, "impulse weapon4" }, { "hellstaff", 0, 0, "impulse weapon5" }, { "phoenix rod", 0, 0, "impulse weapon6" }, { "firemace", 0, 0, "impulse weapon7" }, #endif #if __JHEXEN__ { "weapon 1", 0, 0, "impulse weapon1" }, { "weapon 2", 0, 0, "impulse weapon2" }, { "weapon 3", 0, 0, "impulse weapon3" }, { "weapon 4", 0, 0, "impulse weapon4" }, #endif #if __JHERETIC__ || __JHEXEN__ { NULL }, { "inventory" }, { "move left", 0, 0, "impulse previtem", CCF_REPEAT }, { "move right", 0, 0, "impulse nextitem", CCF_REPEAT }, { "use item", 0, 0, "impulse useitem" }, { "panic!", 0, 0, "impulse panic" }, #endif #ifdef __JHERETIC__ { (const char*) TXT_TXT_INV_INVULNERABILITY, 0, 0, "impulse invulnerability" }, { (const char*) TXT_TXT_INV_INVISIBILITY, 0, 0, "impulse invisibility" }, { (const char*) TXT_TXT_INV_HEALTH, 0, 0, "impulse health" }, { (const char*) TXT_TXT_INV_SUPERHEALTH, 0, 0, "impulse superhealth" }, { (const char*) TXT_TXT_INV_TOMEOFPOWER, 0, 0, "impulse tome" }, { (const char*) TXT_TXT_INV_TORCH, 0, 0, "impulse torch" }, { (const char*) TXT_TXT_INV_FIREBOMB, 0, 0, "impulse firebomb" }, { (const char*) TXT_TXT_INV_EGG, 0, 0, "impulse egg" }, { (const char*) TXT_TXT_INV_FLY, 0, 0, "impulse fly" }, { (const char*) TXT_TXT_INV_TELEPORT, 0, 0, "impulse teleport" }, #endif #ifdef __JHEXEN__ { (const char*) TXT_TXT_INV_TORCH, 0, 0, "impulse torch" }, { (const char*) TXT_TXT_INV_HEALTH, 0, 0, "impulse health" }, { (const char*) TXT_TXT_INV_SUPERHEALTH, 0, 0, "impulse mysticurn" }, { (const char*) TXT_TXT_INV_BOOSTMANA, 0, 0, "impulse krater" }, { (const char*) TXT_TXT_INV_SPEED, 0, 0, "impulse speedboots" }, { (const char*) TXT_TXT_INV_BLASTRADIUS, 0, 0, "impulse blast" }, { (const char*) TXT_TXT_INV_TELEPORT, 0, 0, "impulse teleport" }, { (const char*) TXT_TXT_INV_TELEPORTOTHER, 0, 0, "impulse teleportother" }, { (const char*) TXT_TXT_INV_POISONBAG, 0, 0, "impulse poisonbag" }, { (const char*) TXT_TXT_INV_INVULNERABILITY, 0, 0, "impulse invulnerability" }, { (const char*) TXT_TXT_INV_SUMMON, 0, 0, "impulse darkservant" }, { (const char*) TXT_TXT_INV_EGG, 0, 0, "impulse egg" }, #endif { NULL }, { "chat" }, { "open chat", 0, 0, "beginchat" }, #if __JDOOM__ || __JDOOM64__ { "green chat", 0, 0, "beginchat 0" }, { "indigo chat", 0, 0, "beginchat 1" }, { "brown chat", 0, 0, "beginchat 2" }, { "red chat", 0, 0, "beginchat 3" }, #endif #if __JHERETIC__ { "green chat", 0, 0, "beginchat 0" }, { "yellow chat", 0, 0, "beginchat 1" }, { "red chat", 0, 0, "beginchat 2" }, { "blue chat", 0, 0, "beginchat 3" }, #endif { "send message", "chat", 0, "chatcomplete" }, { "cancel message", "chat", 0, "chatcancel" }, { "macro 1", "chat", 0, "chatsendmacro 0" }, { "macro 2", "chat", 0, "chatsendmacro 1" }, { "macro 3", "chat", 0, "chatsendmacro 2" }, { "macro 4", "chat", 0, "chatsendmacro 3" }, { "macro 5", "chat", 0, "chatsendmacro 4" }, { "macro 6", "chat", 0, "chatsendmacro 5" }, { "macro 7", "chat", 0, "chatsendmacro 6" }, { "macro 8", "chat", 0, "chatsendmacro 7" }, { "macro 9", "chat", 0, "chatsendmacro 8" }, { "macro 10", "chat", 0, "chatsendmacro 9" }, { "backspace", "chat", 0, "chatdelete" }, { NULL }, { "map" }, { "show/hide map", 0, 0, "impulse automap" }, { "zoom in", 0, "mapzoom", 0, CCF_NON_INVERSE }, { "zoom out", 0, "mapzoom", 0, CCF_INVERSE }, { "zoom maximum", "map", 0, "impulse zoommax" }, { "pan left", 0, "mappanx", 0, CCF_INVERSE }, { "pan right", 0, "mappanx", 0, CCF_NON_INVERSE }, { "pan up", 0, "mappany", 0, CCF_NON_INVERSE }, { "pan down", 0, "mappany", 0, CCF_INVERSE }, { "toggle follow", "map", 0, "impulse follow" }, { "toggle rotation", "map", 0, "impulse rotate" }, { "add mark", "map", 0, "impulse addmark" }, { "clear marks", "map", 0, "impulse clearmarks" }, { NULL }, { "hud" }, { "show hud", 0, 0, "impulse showhud" }, { "show score", 0, 0, "impulse showscore", CCF_REPEAT }, { "smaller view", 0, 0, "viewsize -", CCF_REPEAT }, { "larger view", 0, 0, "viewsize +", CCF_REPEAT }, { "message refresh", 0, 0, "impulse msgrefresh" }, { NULL }, { "shortcuts" }, { "pause game", 0, 0, "pause" }, #if !__JDOOM64__ { "help screen", "shortcut", 0, "helpscreen" }, #endif { "end game", "shortcut", 0, "endgame" }, { "save game", "shortcut", 0, "savegame" }, { "load game", "shortcut", 0, "loadgame" }, { "quick save", "shortcut", 0, "quicksave" }, { "quick load", "shortcut", 0, "quickload" }, { "sound options", "shortcut", 0, "soundmenu" }, { "toggle messages", "shortcut", 0, "togglemsgs" }, { "gamma correction", "shortcut", 0, "togglegamma" }, { "screenshot", "shortcut", 0, "screenshot" }, { "quit", "shortcut", 0, "quit" }, { NULL }, { "menu" }, { "show/hide menu", "shortcut", 0, "menu" }, { "previous menu", "menu", 0, "menuback" }, { "move up", "menu", 0, "menuup", CCF_REPEAT }, { "move down", "menu", 0, "menudown", CCF_REPEAT }, { "move left", "menu", 0, "menuleft", CCF_REPEAT }, { "move right", "menu", 0, "menuright", CCF_REPEAT }, { "select", "menu", 0, "menuselect" }, { NULL }, { "on-screen questions" }, { "answer yes", "message", 0, "messageyes" }, { "answer no", "message", 0, "messageno" }, { "cancel", "message", 0, "messagecancel" }, }; // CODE -------------------------------------------------------------------- static void M_DeleteBinding(bindingitertype_t type, int bid, const char* name, boolean isInverse, void* data) { DD_Executef(true, "delbind %i", bid); } static void M_EFuncControlConfig(int option, void* data) { controlconfig_t* cc = data; char buf[1024]; if(option == -1) { if(cc->controlName) { B_BindingsForControl(0, cc->controlName, BFCI_BOTH, buf, sizeof(buf)); } else { B_BindingsForCommand(cc->command, buf, sizeof(buf)); } M_IterateBindings(cc, buf, 0, NULL, M_DeleteBinding); } else { // Start grabbing for this control. grabbing = cc; DD_SetInteger(DD_SYMBOLIC_ECHO, true); } } void M_InitControlsMenu(void) { int i, count = sizeof(controlConfig) / sizeof(controlConfig[0]); VERBOSE( Con_Message("M_InitControlsMenu: Creating controls items.\n") ); // Allocate the menu items array. ControlsItems = Z_Calloc(sizeof(menuitem_t) * count, PU_STATIC, 0); for(i = 0; i < count; ++i) { controlconfig_t* cc = &controlConfig[i]; menuitem_t* item = &ControlsItems[i]; cc->item = item; if(cc->itemText && ((unsigned int) cc->itemText < NUMTEXT)) { item->text = GET_TXT((unsigned int)cc->itemText); } else { item->text = (char*) cc->itemText; } // Inert items. if(!cc->itemText || (!cc->command && !cc->controlName)) { item->type = ITT_EMPTY; } else { item->type = ITT_EFUNC; item->func = M_EFuncControlConfig; item->data = cc; } } ControlsDef.items = ControlsItems; ControlsDef.itemCount = count; } static void M_DrawSmallText(int x, int y, const char* text) { int height = M_StringHeight(text, GF_FONTA); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(x, y + height/2, 0); DGL_Scalef(SMALL_SCALE, SMALL_SCALE, 1); DGL_Translatef(-x, -y - height/2, 0); M_WriteText2(x, y, text, GF_FONTA, 1, 1, 1, Hu_MenuAlpha()); DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } static void M_DrawBinding(bindingitertype_t type, int bid, const char* name, boolean isInverse, void *data) { #if __JHERETIC__ static const float bgRGB[] = { 0, .5f, 0 }; #elif __JHEXEN__ static const float bgRGB[] = { .5f, 0, 0 }; #else static const float bgRGB[] = { 0, 0, 0 }; #endif bindingdrawerdata_t* d = data; int width, height; if(type == MIBT_KEY) { width = M_StringWidth(name, GF_FONTA); height = M_StringHeight(name, GF_FONTA); DGL_SetNoMaterial(); DGL_DrawRect(d->x, d->y, width*SMALL_SCALE + 2, height, bgRGB[0], bgRGB[1], bgRGB[2], Hu_MenuAlpha() * .6f); M_DrawSmallText(d->x + 1, d->y, name); d->x += width * SMALL_SCALE + 2 + BIND_GAP; } else { char temp[256]; sprintf(temp, "%s%c%s", type == MIBT_MOUSE? "mouse" : "joy", isInverse? '-' : '+', name); width = M_StringWidth(temp, GF_FONTA); height = M_StringHeight(temp, GF_FONTA); M_DrawSmallText(d->x, d->y, temp); d->x += width * SMALL_SCALE + BIND_GAP; } } static const char* findInString(const char* str, const char* token, int n) { int tokenLen = strlen(token); const char* at = strstr(str, token); if(!at) { // Not there at all. return NULL; } if(at - str <= n - tokenLen) { return at; } // Past the end. return NULL; } void M_IterateBindings(controlconfig_t* cc, const char* bindings, int flags, void* data, void (*callback)(bindingitertype_t type, int bid, const char* event, boolean isInverse, void *data)) { const char* ptr = strchr(bindings, ':'); const char* begin, *end, *end2, *k, *bindingStart, *bindingEnd; int bid; char buf[80], *b; boolean isInverse; memset(buf, 0, sizeof(buf)); while(ptr) { // Read the binding identifier. for(k = ptr; k > bindings && *k != '@'; --k); if(*k == '@') { for(begin = k - 1; begin > bindings && isdigit(*(begin - 1)); --begin); bid = strtol(begin, NULL, 10); } else { // No identifier?? bid = 0; } // Find the end of the entire binding. bindingStart = k + 1; bindingEnd = strchr(bindingStart, '@'); if(!bindingEnd) { // Then point to the end of the string. bindingEnd = strchr(k + 1, 0); } ptr++; end = strchr(ptr, '-'); if(!end) return; end++; b = buf; while(*end && *end != ' ' && *end != '-' && *end != '+') { *b++ = *end++; } *b = 0; end2 = strchr(end, ' '); if(!end2) end = end + strlen(end); // Then point to the end. else end = end2; if(!findInString(bindingStart, "modifier-1-down", bindingEnd - bindingStart) && (!(flags & MIBF_IGNORE_REPEATS) || !findInString(ptr, "-repeat", end - ptr))) { isInverse = (findInString(ptr, "-inverse", end - ptr) != NULL); if(!strncmp(ptr, "key", 3) || strstr(ptr, "-button") || !strncmp(ptr, "mouse-left", 10) || !strncmp(ptr, "mouse-middle", 12) || !strncmp(ptr, "mouse-right", 11)) { if(((cc->flags & CCF_INVERSE) && isInverse) || ((cc->flags & CCF_NON_INVERSE) && !isInverse) || !(cc->flags & (CCF_INVERSE | CCF_NON_INVERSE))) { callback(!strncmp(ptr, "key", 3)? MIBT_KEY : !strncmp(ptr, "mouse", 5)? MIBT_MOUSE : MIBT_JOY, bid, buf, isInverse, data); } } else { if(!(cc->flags & (CCF_INVERSE | CCF_NON_INVERSE)) || (cc->flags & CCF_INVERSE)) { isInverse = !isInverse; } if(!strncmp(ptr, "joy", 3)) { callback(MIBT_JOY, bid, buf, isInverse, data); } else if(!strncmp(ptr, "mouse", 5)) { callback(MIBT_MOUSE, bid, buf, isInverse, data); } } } ptr = end; while(*ptr == ' ') ptr++; ptr = strchr(ptr, ':'); } } /** * M_DrawControlsMenu */ void M_DrawControlsMenu(void) { int i; char buf[1024]; #if __JHERETIC__ || __JHEXEN__ char* token; #endif const menu_t* menu = &ControlsDef; const menuitem_t* item = menu->items + menu->firstItem; #if __JDOOM__ || __JDOOM64__ M_DrawTitle("CONTROLS", menu->y - 28); Hu_MenuPageString(buf, menu); M_WriteText2(160 - M_StringWidth(buf, GF_FONTA) / 2, menu->y - 12, buf, GF_FONTA, 1, .7f, .3f, Hu_MenuAlpha()); #else M_WriteText2(120, 100 - 98/cfg.menuScale, "CONTROLS", GF_FONTB, cfg.menuColor[0], cfg.menuColor[1], cfg.menuColor[2], Hu_MenuAlpha()); DGL_Color4f(1, 1, 1, Hu_MenuAlpha()); // Draw the page arrows. token = (!menu->firstItem || menuTime & 8) ? "invgeml2" : "invgeml1"; GL_DrawPatch_CS(menu->x, menu->y - 12, W_GetNumForName(token)); token = (menu->firstItem + menu->numVisItems >= menu->itemCount || menuTime & 8) ? "invgemr2" : "invgemr1"; GL_DrawPatch_CS(312 - menu->x, menu->y - 12, W_GetNumForName(token)); #endif strcpy(buf, "Select to assign new, [Del] to clear"); M_WriteText2(160 - M_StringWidth(buf, GF_FONTA) / 2, 100 + (95/cfg.menuScale) - M_StringHeight(buf, GF_FONTA), buf, GF_FONTA, #if __JDOOM__ 1, .7f, .3f, #else 1, 1, 1, #endif Hu_MenuAlpha()); for(i = 0; i < menu->numVisItems && menu->firstItem + i < menu->itemCount; i++, item++) { controlconfig_t* cc = item->data; bindingdrawerdata_t draw; if(item->type != ITT_EFUNC) continue; if(cc->controlName) { B_BindingsForControl(0, cc->controlName, BFCI_BOTH, buf, sizeof(buf)); } else { B_BindingsForCommand(cc->command, buf, sizeof(buf)); } #if __JHEXEN__ draw.x = menu->x + 154; #else draw.x = menu->x + 134; #endif draw.y = menu->y + (i * menu->itemHeight); M_IterateBindings(cc, buf, MIBF_IGNORE_REPEATS, &draw, M_DrawBinding); } } void M_ControlGrabDrawer(void) { const char* text; if(!grabbing) return; DGL_SetNoMaterial(); DGL_DrawRect(0, 0, 320, 200, 0, 0, 0, .7f); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(160, 100, 0); DGL_Scalef(SMALL_SCALE, SMALL_SCALE, 1); DGL_Translatef(-160, -100, 0); text = "press key or move controller for"; M_WriteText2(160 - M_StringWidth(text, GF_FONTA)/2, 98 - M_StringHeight(text, GF_FONTA), text, GF_FONTA, .75f, .75f, .75f, 1); M_WriteText2(160 - M_StringWidth(grabbing->item->text, GF_FONTB)/2, 102, grabbing->item->text, GF_FONTB, 1, 1, 1, 1); DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } int M_ControlsPrivilegedResponder(event_t* ev) { // We're interested in key or button down events. if(grabbing && ev->type == EV_SYMBOLIC) { char cmd[512]; const char* symbol = 0; const char* bindContext = "game"; if(sizeof(const char*) == sizeof(ev->data1)) // 32-bit { symbol = (const char*) ev->data1; } else // 64-bit { symbol = (const char*)(((int64_t)ev->data1) | (((int64_t)ev->data2)) << 32); } if(strncmp(symbol, "echo-", 5)) { return false; } if(!strncmp(symbol, "echo-key-", 9) && strcmp(symbol + strlen(symbol) - 5, "-down")) { return false; } if(grabbing->bindContext) { bindContext = grabbing->bindContext; } if(grabbing->command) { sprintf(cmd, "bindevent {%s:%s} {%s}", bindContext, &symbol[5], grabbing->command); // Check for repeats. if(grabbing->flags & CCF_REPEAT) { const char* downPtr = 0; char temp[256]; downPtr = strstr(symbol + 5, "-down"); if(downPtr) { char temp2[256]; memset(temp2, 0, sizeof(temp2)); strncpy(temp2, symbol + 5, downPtr - symbol - 5); sprintf(temp, "; bindevent {%s:%s-repeat} {%s}", bindContext, temp2, grabbing->command); strcat(cmd, temp); } } } else if(grabbing->controlName) { // Have to exclude the state part. boolean inv = (grabbing->flags & CCF_INVERSE) != 0; boolean isStaged = (grabbing->flags & CCF_STAGED) != 0; char temp3[256]; char extra[256]; const char* end = strchr(symbol + 5, '-'); end = strchr(end + 1, '-'); if(!end) { Con_Error("what! %s\n", symbol); } memset(temp3, 0, sizeof(temp3)); strncpy(temp3, symbol + 5, end - symbol - 5); // Check for inverse. if(!strncmp(end, "-neg", 4)) { inv = !inv; } if(isStaged && (!strncmp(temp3, "key-", 4) || strstr(temp3, "-button") || !strcmp(temp3, "mouse-left") || !strcmp(temp3, "mouse-middle") || !strcmp(temp3, "mouse-right"))) { // Staging is for keys and buttons. strcat(temp3, "-staged"); } if(inv) { strcat(temp3, "-inverse"); } strcpy(extra, ""); if(grabbing->flags & CCF_SIDESTEP_MODIFIER) { sprintf(cmd, "bindcontrol sidestep {%s + modifier-1-down}", temp3); DD_Execute(true, cmd); strcpy(extra, " + modifier-1-up"); } sprintf(cmd, "bindcontrol {%s} {%s%s}", grabbing->controlName, temp3, extra); } VERBOSE( Con_Message("M_ControlsPrivilegedResponder: %s\n", cmd) ); DD_Execute(true, cmd); /* // We shall issue a silent console command, but first we need // a textual representation of the ev. B_FormEventString(evname, ev->type, ev->state, ev->data1); // If this binding already exists, remove it. sprintf(cmd, "%s%s", grabbing->flags & CLF_ACTION ? "+" : "", grabbing->command); memset(buff, 0, sizeof(buff)); // Check for bindings in this class only? if(B_BindingsForCommand(cmd, buff, grabbing->bindContext, false)) if(findtoken(buff, evname, " ")) // Get rid of it? { del = true; strcpy(buff, ""); } if(!del) sprintf(buff, "\"%s\"", grabbing->command); sprintf(cmd, "%s bdc%d %s %s", grabbing->flags & CLF_REPEAT ? "bindr" : "bind", grabbing->bindContext, evname + 1, buff); DD_Execute(false, cmd); */ // We've finished the grab. grabbing = 0; DD_SetInteger(DD_SYMBOLIC_ECHO, false); S_LocalSound(SFX_MENU_ACCEPT, NULL); return true; } return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_inventory.c0000644000175000017500000004422111357170242023350 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inventory.c: Common code for the player's inventory. * * \note The visual representation of the inventory is handled separately, * in the HUD code. */ #if defined(__JHERETIC__) || defined(__JHEXEN__) || defined(__JDOOM64__) // HEADER FILES ------------------------------------------------------------ #include #include #if __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JDOOM64__ # include "jdoom64.h" #endif #include "p_player.h" #include "d_net.h" #include "p_inventory.h" #include "hu_inventory.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct inventoryitem_s { int useCount; struct inventoryitem_s* next; } inventoryitem_t; typedef struct { inventoryitem_t* items[NUM_INVENTORYITEM_TYPES-1]; inventoryitemtype_t readyItem; } playerinventory_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int didUseItem = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static const def_invitem_t itemDefs[NUM_INVENTORYITEM_TYPES-1] = { #if __JHERETIC__ {IIF_USE_PANIC, "TXT_ARTIINVULNERABILITY", "A_Invulnerability", "artiuse", "ARTIINVU", CTL_INVULNERABILITY}, {IIF_USE_PANIC, "TXT_ARTIINVISIBILITY", "A_Invisibility", "artiuse", "ARTIINVS", CTL_INVISIBILITY}, {IIF_USE_PANIC, "TXT_ARTIHEALTH", "A_Health", "artiuse", "ARTIPTN2", CTL_HEALTH}, {IIF_USE_PANIC, "TXT_ARTISUPERHEALTH", "A_SuperHealth", "artiuse", "ARTISPHL", CTL_SUPER_HEALTH}, {IIF_USE_PANIC, "TXT_ARTITOMEOFPOWER", "A_TombOfPower", "artiuse", "ARTIPWBK", CTL_TOME_OF_POWER}, {IIF_USE_PANIC, "TXT_ARTITORCH", "A_Torch", "artiuse", "ARTITRCH", CTL_TORCH}, {IIF_USE_PANIC, "TXT_ARTIFIREBOMB", "A_FireBomb", "artiuse", "ARTIFBMB", CTL_FIREBOMB}, {IIF_USE_PANIC, "TXT_ARTIEGG", "A_Egg", "artiuse", "ARTIEGGC", CTL_EGG}, {IIF_USE_PANIC, "TXT_ARTIFLY", "A_Wings", "artiuse", "ARTISOAR", CTL_FLY}, {IIF_USE_PANIC, "TXT_ARTITELEPORT", "A_Teleport", "artiuse", "ARTIATLP", CTL_TELEPORT}, #elif __JHEXEN__ {IIF_USE_PANIC, "TXT_ARTIINVULNERABILITY", "A_Invulnerability", "ARTIFACT_USE", "ARTIINVU", CTL_INVULNERABILITY}, {IIF_USE_PANIC, "TXT_ARTIHEALTH", "A_Health", "ARTIFACT_USE", "ARTIPTN2", CTL_HEALTH}, {IIF_USE_PANIC, "TXT_ARTISUPERHEALTH", "A_SuperHealth", "ARTIFACT_USE", "ARTISPHL", CTL_MYSTIC_URN}, {IIF_USE_PANIC, "TXT_ARTIHEALINGRADIUS", "A_HealRadius", "ARTIFACT_USE", "ARTIHRAD", -1}, {IIF_USE_PANIC, "TXT_ARTISUMMON", "A_SummonTarget", "ARTIFACT_USE", "ARTISUMN", CTL_DARK_SERVANT}, {IIF_USE_PANIC, "TXT_ARTITORCH", "A_Torch", "ARTIFACT_USE", "ARTITRCH", CTL_TORCH}, {IIF_USE_PANIC, "TXT_ARTIEGG", "A_Egg", "ARTIFACT_USE", "ARTIPORK", CTL_EGG}, {IIF_USE_PANIC, "TXT_ARTIFLY", "A_Wings", "ARTIFACT_USE", "ARTISOAR", CTL_FLY}, {IIF_USE_PANIC, "TXT_ARTIBLASTRADIUS", "A_BlastRadius", "ARTIFACT_USE", "ARTIBLST", CTL_BLAST_RADIUS}, {IIF_USE_PANIC, "TXT_ARTIPOISONBAG", "A_PoisonBag", "ARTIFACT_USE", "ARTIPSBG", CTL_POISONBAG}, {IIF_USE_PANIC, "TXT_ARTITELEPORTOTHER", "A_TeleportOther", "ARTIFACT_USE", "ARTITELO", CTL_TELEPORT_OTHER}, {IIF_USE_PANIC, "TXT_ARTISPEED", "A_Speed", "ARTIFACT_USE", "ARTISPED", CTL_SPEED_BOOTS}, {IIF_USE_PANIC, "TXT_ARTIBOOSTMANA", "A_BoostMana", "ARTIFACT_USE", "ARTIBMAN", CTL_KRATER}, {IIF_USE_PANIC, "TXT_ARTIBOOSTARMOR", "A_BoostArmor", "ARTIFACT_USE", "ARTIBRAC", -1}, {IIF_USE_PANIC, "TXT_ARTITELEPORT", "A_Teleport", "ARTIFACT_USE", "ARTIATLP", CTL_TELEPORT}, {0, "TXT_ARTIPUZZSKULL", "A_PuzzSkull", "PUZZLE_SUCCESS", "ARTISKLL", -1}, {0, "TXT_ARTIPUZZGEMBIG", "A_PuzzGemBig", "PUZZLE_SUCCESS", "ARTIBGEM", -1}, {0, "TXT_ARTIPUZZGEMRED", "A_PuzzGemRed", "PUZZLE_SUCCESS", "ARTIGEMR", -1}, {0, "TXT_ARTIPUZZGEMGREEN1", "A_PuzzGemGreen1", "PUZZLE_SUCCESS", "ARTIGEMG", -1}, {0, "TXT_ARTIPUZZGEMGREEN2", "A_PuzzGemGreen2", "PUZZLE_SUCCESS", "ARTIGMG2", -1}, {0, "TXT_ARTIPUZZGEMBLUE1", "A_PuzzGemBlue1", "PUZZLE_SUCCESS", "ARTIGEMB", -1}, {0, "TXT_ARTIPUZZGEMBLUE2", "A_PuzzGemBlue2", "PUZZLE_SUCCESS", "ARTIGMB2", -1}, {0, "TXT_ARTIPUZZBOOK1", "A_PuzzBook1", "PUZZLE_SUCCESS", "ARTIBOK1", -1}, {0, "TXT_ARTIPUZZBOOK2", "A_PuzzBook2", "PUZZLE_SUCCESS", "ARTIBOK2", -1}, {0, "TXT_ARTIPUZZSKULL2", "A_PuzzSkull2", "PUZZLE_SUCCESS", "ARTISKL2", -1}, {0, "TXT_ARTIPUZZFWEAPON", "A_PuzzFWeapon", "PUZZLE_SUCCESS", "ARTIFWEP", -1}, {0, "TXT_ARTIPUZZCWEAPON", "A_PuzzCWeapon", "PUZZLE_SUCCESS", "ARTICWEP", -1}, {0, "TXT_ARTIPUZZMWEAPON", "A_PuzzMWeapon", "PUZZLE_SUCCESS", "ARTIMWEP", -1}, {0, "TXT_ARTIPUZZGEAR1", "A_PuzzGear1", "PUZZLE_SUCCESS", "ARTIGEAR", -1}, {0, "TXT_ARTIPUZZGEAR2", "A_PuzzGear2", "PUZZLE_SUCCESS", "ARTIGER2", -1}, {0, "TXT_ARTIPUZZGEAR3", "A_PuzzGear3", "PUZZLE_SUCCESS", "ARTIGER3", -1}, {0, "TXT_ARTIPUZZGEAR4", "A_PuzzGear4", "PUZZLE_SUCCESS", "ARTIGER4", -1} #elif __JDOOM64__ {IIF_READY_ALWAYS, "DEMONKEY1", "", "", "", -1}, {IIF_READY_ALWAYS, "DEMONKEY2", "", "", "", -1}, {IIF_READY_ALWAYS, "DEMONKEY3", "", "", "", -1} #endif }; static invitem_t invItems[NUM_INVENTORYITEM_TYPES - 1]; static playerinventory_t inventories[MAXPLAYERS]; // CODE -------------------------------------------------------------------- static __inline const def_invitem_t* itemDefForType(inventoryitemtype_t type) { return &itemDefs[type - 1]; } static inventoryitem_t* allocItem(void) { return malloc(sizeof(inventoryitem_t)); } static void freeItem(inventoryitem_t* item) { free(item); } static __inline unsigned int countItems2(const playerinventory_t* inv, inventoryitemtype_t type) { unsigned int count; const inventoryitem_t* item; count = 0; for(item = inv->items[type-1]; item; item = item->next) count++; return count; } static unsigned int countItems(const playerinventory_t* inv, inventoryitemtype_t type) { if(type == IIT_NONE) { inventoryitemtype_t i; unsigned int count; count = 0; for(i = IIT_FIRST; i < NUM_INVENTORYITEM_TYPES; ++i) count += countItems2(inv, i); return count; } return countItems2(inv, type); } static boolean useItem(playerinventory_t* inv, inventoryitemtype_t type, boolean panic) { int plrnum; const invitem_t* item; if(!countItems(inv, type)) return false; // That was a non-starter. plrnum = inv - inventories; item = &invItems[type-1]; // Is this usable? if(!item->action) return false; // No. // How about when panicked? if(panic) { const def_invitem_t* def = itemDefForType(type); if(!(def->flags & IIF_USE_PANIC)) return false; } /** * \kludge * Action ptrs do not currently support return values. For now, rather * than rewrite each invitem use routine, use a global var to get the * result. Ugly. */ didUseItem = false; item->action(players[plrnum].plr->mo); return didUseItem; } static boolean giveItem(playerinventory_t* inv, inventoryitemtype_t type) { unsigned int count = countItems(inv, type); inventoryitem_t* item; #if __JHEXEN__ // Can't carry more than 1 puzzle item in coop netplay. if(count && type >= IIT_FIRSTPUZZITEM && IS_NETGAME && !deathmatch) return false; #endif // Carrying the maximum allowed number of these items? if(count >= MAXINVITEMCOUNT) return false; item = allocItem(); item->useCount = 0; item->next = inv->items[type-1]; inv->items[type-1] = item; return true; } static int takeItem(playerinventory_t* inv, inventoryitemtype_t type) { inventoryitem_t* next; if(!inv->items[type - 1]) return false; // Don't have one to take. next = inv->items[type - 1]->next; freeItem(inv->items[type -1]); inv->items[type - 1] = next; if(!inv->items[type - 1]) { // Took last item of this type. if(inv->readyItem == type) inv->readyItem = IIT_NONE; } return true; } static int tryTakeItem(playerinventory_t* inv, inventoryitemtype_t type) { if(takeItem(inv, type)) { // An item was taken. int player = inv - inventories; players[player].update |= PSF_INVENTORY; #if __JHERETIC__ || __JHEXEN__ // Inform the HUD. Hu_InventoryMarkDirty(player); // Set position markers and set the next readyItem? if(inv->readyItem == IIT_NONE) Hu_InventoryMove(player, -1, false, true); #endif return true; } return false; } static int tryUseItem(playerinventory_t* inv, inventoryitemtype_t type, int panic) { if(useItem(inv, type, panic)) { // Item was used. return tryTakeItem(inv, type); } return false; } const def_invitem_t* P_GetInvItemDef(inventoryitemtype_t type) { assert(type >= IIT_FIRST && type < NUM_INVENTORYITEM_TYPES); return itemDefForType(type); } static acfnptr_t getActionPtr(const char* name) { actionlink_t* link = actionlinks; if(!name || !name[0]) return NULL; for(; link->name; link++) if(!strcmp(name, link->name)) return link->func; return NULL; } /** * Called during (post-engine) init and after updating game/engine state. */ void P_InitInventory(void) { int i; memset(invItems, 0, sizeof(invItems)); for(i = 0; i < NUM_INVENTORYITEM_TYPES - 1; ++i) { inventoryitemtype_t type = IIT_FIRST + i; const def_invitem_t* def = P_GetInvItemDef(type); invitem_t* data = &invItems[i]; data->type = type; data->niceName = Def_Get(DD_DEF_TEXT, (char*) def->niceName, NULL); data->action = getActionPtr(def->action); data->useSnd = Def_Get(DD_DEF_SOUND, (char*) def->useSnd, NULL); data->patchLump = W_CheckNumForName(def->patch); } memset(inventories, 0, sizeof(inventories)); } /** * Called once, during shutdown. */ void P_ShutdownInventory(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { P_InventoryEmpty(i); } } const invitem_t* P_GetInvItem(int id) { if(id < 0 || id >= NUM_INVENTORYITEM_TYPES - 1) return NULL; return &invItems[id]; } /** * Should be called only outside of normal play (e.g., when starting a new * game or similar). * * @param player Player to empty the inventory of. */ void P_InventoryEmpty(int player) { inventoryitemtype_t i; playerinventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return; inv = &inventories[player]; for(i = 0; i < NUM_INVENTORYITEM_TYPES - 1; ++i) { if(inv->items[i]) { inventoryitem_t* item, *n; item = inv->items[i]; do { n = item->next; freeItem(item); item = n; } while(item); } } memset(inv->items, 0, sizeof(inv->items[0]) * (NUM_INVENTORYITEM_TYPES-1)); inv->readyItem = IIT_NONE; } /** * Retrieve the number of items possessed by the player. * * @param player Player to check the inventory of. * @param type Type requirement, limits the count to the * specified type else @c IIT_NONE to count all. * @return Result. */ unsigned int P_InventoryCount(int player, inventoryitemtype_t type) { if(player < 0 || player >= MAXPLAYERS) return 0; if(!(type == IIT_NONE || (type >= IIT_FIRST && type < NUM_INVENTORYITEM_TYPES))) return 0; return countItems(&inventories[player], type); } /** * Attempt to ready an item (or unready a currently readied item). * * @param player Player to change the ready item of. * @param type Item type to be readied. * * @return Non-zero iff successful. */ int P_InventorySetReadyItem(int player, inventoryitemtype_t type) { playerinventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return 0; if(type < IIT_NONE || type >= NUM_INVENTORYITEM_TYPES) return 0; inv = &inventories[player]; if(type == IIT_NONE || countItems(inv, type)) { // A valid ready request. boolean mustEquip = true; if(type != IIT_NONE) { const def_invitem_t* def = P_GetInvItemDef(type); mustEquip = ((def->flags & IIF_READY_ALWAYS)? false : true); } if(mustEquip && inv->readyItem != type) { // Make it so. inv->readyItem = type; #if __JHERETIC__ || __JHEXEN__ // Inform the HUD. Hu_InventoryMarkDirty(player); #endif } return 1; } return 0; } /** * @return The currently readied item, else @c IIT_NONE. */ inventoryitemtype_t P_InventoryReadyItem(int player) { if(player < 0 || player >= MAXPLAYERS) return IIT_NONE; return inventories[player].readyItem; } /** * Give one item of the specified type to the player. * * @param player Player to give the item to. * @param type Type of item to give. * @param silent Non-zero = don't alert the player. * * @return Non-zero iff an item of the specified type was * successfully given to the player. */ int P_InventoryGive(int player, inventoryitemtype_t type, int silent) { unsigned int oldNumItems; playerinventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return 0; if(!(type >= IIT_FIRST && type < NUM_INVENTORYITEM_TYPES)) return 0; inv = &inventories[player]; oldNumItems = countItems(inv, IIT_NONE); if(giveItem(inv, type)) { // Item was given. players[player].update |= PSF_INVENTORY; #if __JHERETIC__ || __JHEXEN__ // Inform the HUD. Hu_InventoryMarkDirty(player); #endif if(oldNumItems == 0) { // This is the first item the player has been given; ready it. const def_invitem_t* def = P_GetInvItemDef(type); if(!(def->flags & IIF_READY_ALWAYS)) { inv->readyItem = type; #if __JHERETIC__ || __JHEXEN__ Hu_InventorySelect(player, type); #endif } } // Maybe unhide the HUD? #if __JHERETIC__ || __JHEXEN__ if(!silent) ST_HUDUnHide(player, HUE_ON_PICKUP_INVITEM); #endif return 1; } return 0; } /** * Take one of the specified items from the player (if owned). * * @param player Player to take the item from. * @param type Type of item being taken. * @param silent Non-zero = don't alert the player. * * @return Non-zero iff an item of the specified type was * successfully taken from the player. */ int P_InventoryTake(int player, inventoryitemtype_t type, int silent) { playerinventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return 0; if(!(type >= IIT_FIRST && type < NUM_INVENTORYITEM_TYPES)) return 0; inv = &inventories[player]; return tryTakeItem(inv, type); } /** * Attempt to use an item of the specified type. * * @param player Player using the item. * @param type The type of item being used ELSE * IIT_NONE = Ignored. * NUM_INVENTORYITEM_TYPES = Panic. Use one of everything!! * @param silent Non-zero - don't alert the player. * * @return Non-zero iff one (or more) item was successfully * used by the player. */ int P_InventoryUse(int player, inventoryitemtype_t type, int silent) { inventoryitemtype_t lastUsed = IIT_NONE; playerinventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return false; if(!(type >= IIT_FIRST || type <= NUM_INVENTORYITEM_TYPES)) return false; inv = &inventories[player]; if(type != NUM_INVENTORYITEM_TYPES) { if(tryUseItem(inv, type, false)) lastUsed = type; } else { // Panic! Use one of each item that is usable when panicked. inventoryitemtype_t i; for(i = IIT_FIRST; i < NUM_INVENTORYITEM_TYPES; ++i) if(tryUseItem(inv, i, true)) lastUsed = i; } if(lastUsed == IIT_NONE) { // Failed to use an item. // Set current to the next available? #if __JHERETIC__ || __JHEXEN__ if(type != NUM_INVENTORYITEM_TYPES && cfg.inventoryUseNext) { # if __JHEXEN__ if(lastUsed < IIT_FIRSTPUZZITEM) # endif Hu_InventoryMove(player, -1, false, true); } #endif return false; } if(!silent) { invitem_t* item = &invItems[lastUsed-1]; S_ConsoleSound(item->useSnd, NULL, player); #if __JHERETIC__ || __JHEXEN__ ST_FlashCurrentItem(player); #endif } return true; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_user.c0000644000175000017500000014676111357170242022305 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2000-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_user.c : Player related stuff. * * Bobbing POV/weapon, movement, pending weapon... */ // HEADER FILES ------------------------------------------------------------ #include #if __JDOOM__ # include "jdoom.h" # include "g_common.h" #elif __JDOOM64__ # include "jdoom64.h" # include "g_common.h" #elif __JHERETIC__ # include "jheretic.h" # include "g_common.h" # include "r_common.h" # include "p_inventory.h" #elif __JHEXEN__ # include # include "jhexen.h" # include "p_inventory.h" #endif #include "p_player.h" #include "p_tick.h" // for P_IsPaused() #include "p_view.h" #include "d_net.h" #include "p_player.h" #include "p_map.h" #include "p_user.h" #include "g_common.h" #include "am_map.h" #include "hu_log.h" #if __JHERETIC__ || __JHEXEN__ #include "hu_inventory.h" #endif // MACROS ------------------------------------------------------------------ #define ANG5 (ANG90/18) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- #if __JHERETIC__ || __JHEXEN__ boolean P_TestMobjLocation(mobj_t *mobj); #endif // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean onground; int maxHealth; // 100 #if __JDOOM__ || __JDOOM64__ int healthLimit; // 200 int godModeHealth; // 100 int soulSphereLimit; // 200 int megaSphereHealth; // 200 int soulSphereHealth; // 100 int armorPoints[4]; // Green, blue, IDFA and IDKFA points. int armorClass[4]; // Green, blue, IDFA and IDKFA armor classes. #endif #if __JDOOM__ || __JDOOM64__ classinfo_t classInfo[NUM_PLAYER_CLASSES] = { { // Player NULL, true, MT_PLAYER, S_PLAY, S_PLAY_RUN1, S_PLAY_ATK1, S_PLAY_ATK2, 20, 0x3C, {0x19, 0x32}, {0x18, 0x28}, 2048, {640, 1280}, 24, SFX_NOWAY } }; #elif __JHERETIC__ classinfo_t classInfo[NUM_PLAYER_CLASSES] = { { // Player NULL, true, MT_PLAYER, S_PLAY, S_PLAY_RUN1, S_PLAY_ATK1, S_PLAY_ATK2, 20, 0x3C, {0x19, 0x32}, {0x18, 0x28}, 2048, {640, 1280}, 24, SFX_NONE }, { // Chicken NULL, false, MT_CHICPLAYER, S_CHICPLAY, S_CHICPLAY_RUN1, S_CHICPLAY_ATK1, S_CHICPLAY_ATK1, 20, 0x3C, {0x19, 0x32}, {0x18, 0x28}, 2500, {640, 1280}, 24, SFX_NONE }, }; #elif __JHEXEN__ classinfo_t classInfo[NUM_PLAYER_CLASSES] = { { // Fighter NULL, true, MT_PLAYER_FIGHTER, S_FPLAY, S_FPLAY_RUN1, S_FPLAY_ATK1, S_FPLAY_ATK2, 20, 15 * FRACUNIT, 0x3C, {0x1D, 0x3C}, {0x1B, 0x3B}, 2048, {640, 1280}, 18, SFX_PLAYER_FIGHTER_FAILED_USE, {25 * FRACUNIT, 20 * FRACUNIT, 15 * FRACUNIT, 5 * FRACUNIT}, {190, 225, 234} }, { // Cleric NULL, true, MT_PLAYER_CLERIC, S_CPLAY, S_CPLAY_RUN1, S_CPLAY_ATK1, S_CPLAY_ATK3, 18, 10 * FRACUNIT, 0x32, {0x19, 0x32}, {0x18, 0x28}, 2048, {640, 1280}, 18, SFX_PLAYER_CLERIC_FAILED_USE, {10 * FRACUNIT, 25 * FRACUNIT, 5 * FRACUNIT, 20 * FRACUNIT}, {190, 212, 225} }, { // Mage NULL, true, MT_PLAYER_MAGE, S_MPLAY, S_MPLAY_RUN1, S_MPLAY_ATK1, S_MPLAY_ATK2, 16, 5 * FRACUNIT, 0x2D, {0x16, 0x2E}, {0x15, 0x25}, 2048, {640, 1280}, 18, SFX_PLAYER_MAGE_FAILED_USE, {5 * FRACUNIT, 15 * FRACUNIT, 10 * FRACUNIT, 25 * FRACUNIT}, {190, 205, 224} }, { // Pig NULL, false, MT_PIGPLAYER, S_PIGPLAY, S_PIGPLAY_RUN1, S_PIGPLAY_ATK1, S_PIGPLAY_ATK1, 1, 0, 0x31, {0x18, 0x31}, {0x17, 0x27}, 2048, {640, 1280}, 18, SFX_NONE, {0, 0, 0, 0}, {0, 0, 0} }, }; #endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ #if __JHERETIC__ || __JHEXEN__ static int newTorch[MAXPLAYERS]; // Used in the torch flicker effect. static int newTorchDelta[MAXPLAYERS]; #endif // CODE -------------------------------------------------------------------- /** * Moves the given origin along a given angle. */ void P_Thrust(player_t *player, angle_t angle, float move) { mobj_t* mo = player->plr->mo; uint an = angle >> ANGLETOFINESHIFT; /*float xmul=1, ymul=1; // How about Quake-flying? -- jk if(quakeFly) { float ang = LOOKDIR2RAD(player->plr->lookDir); xmul = ymul = cos(ang); mo->mom[MZ] += sin(ang) * move; }*/ if(!(player->powers[PT_FLIGHT] && !(mo->pos[VZ] <= mo->floorZ))) { #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ sector_t* sec = P_GetPtrp(mo->subsector, DMU_SECTOR); #endif #if __JHEXEN__ const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); #endif #if __JHEXEN__ if(tt->flags & TTF_FRICTION_LOW) { move /= 2; } #elif __JHERETIC__ if(P_ToXSector(sec)->special == 15) // Friction_Low { move /= 4; } else #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ { move *= XS_ThrustMul(sec); } #endif } mo->mom[MX] += move * FIX2FLT(finecosine[an]); mo->mom[MY] += move * FIX2FLT(finesine[an]); } /** * Returns true if the player is currently standing on ground * or on top of another mobj. */ boolean P_IsPlayerOnGround(player_t *player) { boolean onground = (player->plr->mo->pos[VZ] <= player->plr->mo->floorZ); #if __JHEXEN__ if((player->plr->mo->onMobj) && !onground) { onground = true; //(player->plr->mo->pos[VZ] <= on->pos[VZ] + on->height); } #else if(player->plr->mo->onMobj && !onground && !(player->plr->mo->flags2 & MF2_FLY)) { mobj_t *on = player->plr->mo->onMobj; onground = (player->plr->mo->pos[VZ] <= on->pos[VZ] + on->height); } #endif return onground; } /** * Will make the player jump if the latest command so instructs, * providing that jumping is possible. */ void P_CheckPlayerJump(player_t *player) { float power = (IS_CLIENT ? netJumpPower : cfg.jumpPower); if(player->plr->flags & DDPF_CAMERA) return; // Cameras don't jump. // Check if we are allowed to jump. if(cfg.jumpEnabled && power > 0 && P_IsPlayerOnGround(player) && player->brain.jump && player->jumpTics <= 0) { // Jump, then! #if __JHEXEN__ if(player->morphTics) // Pigs don't jump that high. player->plr->mo->mom[MZ] = (2 * power / 3); else #endif player->plr->mo->mom[MZ] = power; player->jumpTics = PCLASS_INFO(player->class)->jumpTics; #if __JHEXEN__ player->plr->mo->onMobj = NULL; #endif } } void P_MovePlayer(player_t *player) { ddplayer_t *dp = player->plr; mobj_t *plrmo = player->plr->mo; //ticcmd_t *cmd = &player->plr->cmd; playerbrain_t *brain = &player->brain; classinfo_t *pClassInfo = PCLASS_INFO(player->class); int speed; float forwardMove, sideMove; // Change the angle if possible. /* $unifiedangles */ /*if(IS_SERVER && player != &players[0]) { if(dp->fixCounter.angles == dp->fixAcked.angles) // all acked? { #ifdef _DEBUG VERBOSE2( Con_Message("Server accepts client %i angle from command (ang=%i).\n", player - players, cmd->angle) ); #endif // Accept the client's version of the angles. plrmo->angle = cmd->angle << 16; dp->lookDir = cmd->pitch / (float) DDMAXSHORT *110; } }*/ // Slow > fast. Fast > slow. speed = brain->speed; if(cfg.alwaysRun) speed = !speed; // Do not let the player control movement if not onground. onground = P_IsPlayerOnGround(player); if(dp->flags & DDPF_CAMERA) // $democam { static const fixed_t cameraSpeed[2] = {0x19, 0x31}; // Cameramen have a 3D thrusters! P_Thrust3D(player, plrmo->angle, dp->lookDir, brain->forwardMove * cameraSpeed[speed] * 2048, brain->sideMove * cameraSpeed[speed] * 2048); } else { // 'Move while in air' hack (server doesn't know about this!!). // Movement while in air traditionally disabled. float maxMove = FIX2FLT(pClassInfo->maxMove); int movemul = (onground || (plrmo->flags2 & MF2_FLY))? pClassInfo->moveMul : (cfg.airborneMovement? cfg.airborneMovement * 64 : 0); if(!brain->lunge) { forwardMove = FIX2FLT(pClassInfo->forwardMove[speed]) * turboMul * MIN_OF(brain->forwardMove, 1); sideMove = FIX2FLT(pClassInfo->sideMove[speed]) * turboMul * MIN_OF(brain->sideMove, 1); #if __JHEXEN__ if(player->powers[PT_SPEED] && !player->morphTics) { // Adjust for a player with the speed power. forwardMove = (3 * forwardMove) / 2; sideMove = (3 * sideMove) / 2; } #endif // Players can opt to reduce their maximum possible movement speed. if((int) cfg.playerMoveSpeed != 1) { // A divsor has been specified, apply it. float m = MINMAX_OF(0.f, cfg.playerMoveSpeed, 1.f); forwardMove *= m; sideMove *= m; } // Make sure it's within valid bounds. forwardMove = MINMAX_OF(-maxMove, forwardMove, maxMove); sideMove = MINMAX_OF(-maxMove, sideMove, maxMove); } else { // Do the lunge. /** * \note Normal valid range clamp not used with lunge as with * it; the amount of forward velocity is not sufficent to * prevent the player from easily backing out while lunging. */ forwardMove = FIX2FLT(0xc800 / 512); sideMove = 0; } if(forwardMove != 0 && movemul) { P_Thrust(player, plrmo->angle, forwardMove * movemul); } if(sideMove != 0 && movemul) { P_Thrust(player, plrmo->angle - ANG90, sideMove * movemul); } if((forwardMove != 0 || sideMove != 0) && player->plr->mo->state == &STATES[pClassInfo->normalState]) { P_MobjChangeState(player->plr->mo, pClassInfo->runState); } //P_CheckPlayerJump(player); // done in a different place } #if __JHEXEN__ // Look up/down using the delta. /* if(cmd->lookdirdelta) { float fd = cmd->lookdirdelta / DELTAMUL; float delta = fd * fd; if(cmd->lookdirdelta < 0) delta = -delta; player->plr->lookDir += delta; } */ // 110 corresponds 85 degrees. if(player->plr->lookDir > 110) player->plr->lookDir = 110; if(player->plr->lookDir < -110) player->plr->lookDir = -110; #endif } /** * Fall on your ass when dying. Decrease viewheight to floor height. */ void P_DeathThink(player_t* player) { #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ angle_t angle; #endif angle_t delta; int lookDelta; if(player->rebornWait > 0) player->rebornWait--; P_MovePsprites(player); onground = (player->plr->mo->pos[VZ] <= player->plr->mo->floorZ); #if __JDOOM__ || __JDOOM64__ if(cfg.deathLookUp) #elif __JHERETIC__ if(player->plr->mo->type == MT_BLOODYSKULL) #elif __JHEXEN__ if(player->plr->mo->type == MT_BLOODYSKULL || player->plr->mo->type == MT_ICECHUNK) #endif { // Flying bloody skull player->viewHeight = 6; player->viewHeightDelta = 0; if(onground) { if(player->plr->lookDir < 60) { lookDelta = (60 - player->plr->lookDir) / 8; if(lookDelta < 1 && (mapTime & 1)) { lookDelta = 1; } else if(lookDelta > 6) { lookDelta = 6; } player->plr->lookDir += lookDelta; player->plr->flags |= DDPF_INTERPITCH; } } } #if __JHEXEN__ else if(!(player->plr->mo->flags2 & MF2_ICEDAMAGE)) // (if not frozen) #else else // fall to the ground #endif { if(player->viewHeight > 6) player->viewHeight -= 1; if(player->viewHeight < 6) player->viewHeight = 6; player->viewHeightDelta = 0; #if __JHERETIC__ || __JHEXEN__ if(player->plr->lookDir > 0) player->plr->lookDir -= 6; else if(player->plr->lookDir < 0) player->plr->lookDir += 6; if(abs((int) player->plr->lookDir) < 6) player->plr->lookDir = 0; #endif player->plr->flags |= DDPF_INTERPITCH; } #if __JHEXEN__ player->update |= PSF_VIEW_HEIGHT; #endif P_CalcHeight(player); // In netgames we won't keep tracking the killer. if( #if !__JHEXEN__ !IS_NETGAME && #endif player->attacker && player->attacker != player->plr->mo) { #if __JHEXEN__ int dir = P_FaceMobj(player->plr->mo, player->attacker, &delta); if(delta < ANGLE_1 * 10) { // Looking at killer, so fade damage and poison counters if(player->damageCount) { player->damageCount--; } if(player->poisonCount) { player->poisonCount--; } } delta = delta / 8; if(delta > ANGLE_1 * 5) { delta = ANGLE_1 * 5; } if(dir) player->plr->mo->angle += delta; // Turn clockwise else player->plr->mo->angle -= delta; // Turn counter clockwise #else angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], player->attacker->pos[VX], player->attacker->pos[VY]); delta = angle - player->plr->mo->angle; if(delta < ANG5 || delta > (unsigned) -ANG5) { // Looking at killer, so fade damage flash down. player->plr->mo->angle = angle; if(player->damageCount) player->damageCount--; } else if(delta < ANG180) player->plr->mo->angle += ANG5; // Turn clockwise else player->plr->mo->angle -= ANG5; // Turn counter clockwise player->plr->flags |= DDPF_INTERYAW; #endif } else { if(player->damageCount) player->damageCount--; #if __JHEXEN__ if(player->poisonCount) player->poisonCount--; #endif } if(!(player->rebornWait > 0) && player->brain.doReborn) { if(IS_CLIENT) { NetCl_PlayerActionRequest(player, GPA_USE); } else { P_PlayerReborn(player); } } } /** * Called when a dead player wishes to be reborn. * * @param player Player that wishes to be reborn. */ void P_PlayerReborn(player_t* player) { player->playerState = PST_REBORN; #if __JHERETIC__ || __JHEXEN__ player->plr->flags &= ~DDPF_VIEW_FILTER; newTorch[player - players] = 0; newTorchDelta[player - players] = 0; # if __JHEXEN__ player->plr->mo->special1 = player->class; if(player->plr->mo->special1 > 2) { player->plr->mo->special1 = 0; } # endif // Let the mobj know the player has entered the reborn state. Some // mobjs need to know when it's ok to remove themselves. player->plr->mo->special2 = 666; #endif } #if __JHERETIC__ || __JHEXEN__ void P_MorphThink(player_t *player) { mobj_t *pmo; #if __JHEXEN__ if(player->morphTics & 15) return; pmo = player->plr->mo; //// \fixme: Replace equality to zero checks with mom in-range. if(pmo->mom[MX] == 0 && pmo->mom[MY] == 0 && P_Random() < 64) { // Snout sniff P_SetPspriteNF(player, ps_weapon, S_SNOUTATK2); S_StartSound(SFX_PIG_ACTIVE1, pmo); // snort return; } if(P_Random() < 48) { if(P_Random() < 128) S_StartSound(SFX_PIG_ACTIVE1, pmo); else S_StartSound(SFX_PIG_ACTIVE2, pmo); } # else if(player->health > 0) P_UpdateBeak(player, &player->pSprites[ps_weapon]); // Handle beak movement if(player->chickenPeck) { // Chicken attack counter. player->chickenPeck -= 3; } if(IS_CLIENT || player->morphTics & 15) return; pmo = player->plr->mo; //// \fixme: Replace equality to zero checks with mom in-range. if(pmo->mom[MX] == 0 && pmo->mom[MY] == 0 && P_Random() < 160) { // Twitch view angle pmo->angle += (P_Random() - P_Random()) << 19; } if(pmo->pos[VZ] <= pmo->floorZ && (P_Random() < 32)) { // Jump and noise pmo->mom[MZ] += 1; P_MobjChangeState(pmo, S_CHICPLAY_PAIN); return; } if(P_Random() < 48) { // Just noise. S_StartSound(SFX_CHICACT, pmo); } # endif } /** * \todo Need to replace this as it comes straight from Hexen. */ boolean P_UndoPlayerMorph(player_t *player) { mobj_t* fog = 0, *mo = 0, *pmo = 0; float pos[3]; unsigned int an; angle_t angle; int playerNum; weapontype_t weapon; int oldFlags, oldFlags2, oldBeast; # if __JHEXEN__ player->update |= PSF_MORPH_TIME | PSF_POWERS | PSF_HEALTH; # endif pmo = player->plr->mo; memcpy(pos, pmo->pos, sizeof(pos)); angle = pmo->angle; weapon = pmo->special1; oldFlags = pmo->flags; oldFlags2 = pmo->flags2; # if __JHEXEN__ oldBeast = pmo->type; # else oldBeast = MT_CHICPLAYER; # endif P_MobjChangeState(pmo, S_FREETARGMOBJ); playerNum = P_GetPlayerNum(player); # if __JHEXEN__ mo = P_SpawnMobj3fv(PCLASS_INFO(cfg.playerClass[playerNum])->mobjType, pos, angle, 0); # else mo = P_SpawnMobj3fv(MT_PLAYER, pos, angle, 0); # endif if(!mo) return false; if(P_TestMobjLocation(mo) == false) { // Didn't fit P_MobjRemove(mo, false); if((mo = P_SpawnMobj3fv(oldBeast, pos, angle, 0))) { mo->health = player->health; mo->special1 = weapon; mo->player = player; mo->dPlayer = player->plr; mo->flags = oldFlags; mo->flags2 = oldFlags2; player->plr->mo = mo; player->morphTics = 2 * 35; } return false; } # if __JHEXEN__ if(player->class == PCLASS_FIGHTER) { // The first type should be blue, and the third should be the // Fighter's original gold color if(playerNum == 0) mo->flags |= 2 << MF_TRANSSHIFT; else if(playerNum != 2) mo->flags |= playerNum << MF_TRANSSHIFT; } else # endif if(playerNum != 0) { // Set color translation bits for player sprites mo->flags |= playerNum << MF_TRANSSHIFT; } mo->player = player; mo->dPlayer = player->plr; mo->reactionTime = 18; if(oldFlags2 & MF2_FLY) { mo->flags2 |= MF2_FLY; mo->flags |= MF_NOGRAVITY; } player->morphTics = 0; # if __JHERETIC__ player->powers[PT_WEAPONLEVEL2] = 0; # endif player->health = mo->health = maxHealth; player->plr->mo = mo; # if __JHERETIC__ player->class = PCLASS_PLAYER; # else player->class = cfg.playerClass[playerNum]; # endif an = angle >> ANGLETOFINESHIFT; // REWRITE ME - I MATCH HEXEN UNTIL HERE if((fog = P_SpawnMobj3f(MT_TFOG, pos[VX] + 20 * FIX2FLT(finecosine[an]), pos[VY] + 20 * FIX2FLT(finesine[an]), pos[VZ] + TELEFOGHEIGHT, angle + ANG180, 0))) { # if __JHERETIC__ S_StartSound(SFX_TELEPT, fog); # else S_StartSound(SFX_TELEPORT, fog); # endif } P_PostMorphWeapon(player, weapon); player->update |= PSF_MORPH_TIME | PSF_HEALTH; player->plr->flags |= DDPF_FIXPOS | DDPF_FIXMOM; return true; } #endif /** * Called once per tick by P_Ticker. * This routine does all the thinking for the console player during * netgames. * * FIXME: This should be removed in favor of the regular P_PlayerThink, which * is supposed to handle all thinking regardless of whether it's a client * or a server doing the thinking. */ void P_ClientSideThink(void) { player_t *pl; ddplayer_t *dpl; mobj_t *mo; /* int i; ticcmd_t *cmd; int fly; */ if(!IS_CLIENT || !Get(DD_GAME_READY)) return; pl = &players[CONSOLEPLAYER]; dpl = pl->plr; mo = dpl->mo; // Applicable parts of the regular P_PlayerThink routine will be used. P_PlayerThink(pl, 1.0/TICSPERSEC); /* if(!mo) return; if(pl->playerState == PST_DEAD) { P_DeathThink(pl); } cmd = &pl->cmd; // The latest local command. P_CalcHeight(pl); #if __JHEXEN__ if(pl->morphTics > 0) pl->morphTics--; #endif // Powers tic away. for(i = 0; i < NUM_POWER_TYPES; i++) { switch (i) { #if __JDOOM__ || __JDOOM64__ case PT_INVULNERABILITY: case PT_INVISIBILITY: case PT_IRONFEET: case PT_INFRARED: case PT_STRENGTH: #elif __JHERETIC__ case PT_INVULNERABILITY: case PT_WEAPONLEVEL2: case PT_INVISIBILITY: case PT_FLIGHT: case PT_INFRARED: #elif __JHEXEN__ case PT_INVULNERABILITY: case PT_INFRARED: case PT_FLIGHT: case PT_SPEED: case PT_MINOTAUR: #endif if(pl->powers[i] > 0) pl->powers[i]--; else pl->powers[i] = 0; break; } } // Jumping. if(pl->jumpTics) pl->jumpTics--; P_CheckPlayerJump(pl); // Flying. fly = cmd->fly; //lookfly >> 4; if(fly && pl->powers[PT_FLIGHT]) { if(fly != TOCENTER) { pl->flyHeight = fly * 2; if(!(mo->ddFlags & DDMF_FLY)) { // Start flying. // mo->ddFlags |= DDMF_FLY | DDMF_NOGRAVITY; } } else { // mo->ddFlags &= ~(DDMF_FLY | DDMF_NOGRAVITY); } } // We are flying when the Fly flag is set. if(mo->ddFlags & DDMF_FLY) { // If we were on a mobj, we are NOT now. if(mo->onMobj) mo->onMobj = NULL; // Keep the fly flag in sync. mo->flags2 |= MF2_FLY; mo->mom[MZ] = (float) pl->flyHeight; if(pl->flyHeight) pl->flyHeight /= 2; // Do some fly-bobbing. if(mo->pos[VZ] > mo->floorZ && (mo->flags2 & MF2_FLY) && !mo->onMobj && (mapTime & 2)) mo->pos[VZ] += FIX2FLT(finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]); } #if __JHEXEN__ else { // Clear the Fly flag. mo->flags2 &= ~MF2_FLY; } #endif */ #if __JHEXEN__ /* if(P_ToXSector(P_GetPtrp(mo->subsector, DMU_SECTOR))->special) P_PlayerInSpecialSector(pl); */ // Set CONSOLEPLAYER thrust multiplier. if(mo->pos[VZ] > mo->floorZ) // Airborne? { float mul = (mo->ddFlags & DDMF_FLY) ? 1 : 0; DD_SetVariable(DD_CPLAYER_THRUST_MUL, &mul); } else { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); float mul = ((tt->flags & TTF_FRICTION_LOW) ? (1.0f / 2) : 1); DD_SetVariable(DD_CPLAYER_THRUST_MUL, &mul); } #else // Set the proper thrust multiplier. XG gives this quite easily. // (The thrust multiplier is used by Cl_MovePlayer, the movement // "predictor"; almost all clientside movement is handled by that // routine, in fact.) { float mul = XS_ThrustMul(P_GetPtrp(mo->subsector, DMU_SECTOR)); DD_SetVariable(DD_CPLAYER_THRUST_MUL, &mul); } #endif // Update view angles. The server fixes them if necessary. /*mo->angle = dpl->clAngle; dpl->lookDir = dpl->clLookDir;*/ /* $unifiedangles */ } void P_PlayerThinkState(player_t *player) { if(player->plr->mo) { mobj_t *plrmo = player->plr->mo; // jDoom // Selector 0 = Generic (used by default) // Selector 1 = Fist // Selector 2 = Pistol // Selector 3 = Shotgun // Selector 4 = Fist // Selector 5 = Chaingun // Selector 6 = Missile // Selector 7 = Plasma // Selector 8 = BFG // Selector 9 = Chainsaw // Selector 10 = Super shotgun // jHexen // Selector 0 = Generic (used by default) // Selector 1..4 = Weapon 1..4 plrmo->selector = (plrmo->selector & ~DDMOBJ_SELECTOR_MASK) | (player->readyWeapon + 1); // Reactiontime is used to prevent movement for a bit after a teleport. if(plrmo->reactionTime > 0) { plrmo->reactionTime--; } else { plrmo->reactionTime = 0; } } if(player->playerState != PST_DEAD) { // Clear the view angle interpolation flags by default. player->plr->flags &= ~(DDPF_INTERYAW | DDPF_INTERPITCH); } } void P_PlayerThinkCheat(player_t *player) { if(player->plr->mo) { mobj_t *plrmo = player->plr->mo; // fixme: do this in the cheat code if(P_GetPlayerCheats(player) & CF_NOCLIP) plrmo->flags |= MF_NOCLIP; else plrmo->flags &= ~MF_NOCLIP; } } void P_PlayerThinkAttackLunge(player_t *player) { mobj_t* plrmo = player->plr->mo; // Normally we don't lunge. player->brain.lunge = false; if(plrmo && (plrmo->flags & MF_JUSTATTACKED)) { player->brain.lunge = true; plrmo->flags &= ~MF_JUSTATTACKED; player->plr->flags |= DDPF_FIXANGLES; } } /** * @return @c true, if thinking should be stopped. Otherwise, * @c false. */ boolean P_PlayerThinkDeath(player_t *player) { if(player->playerState == PST_DEAD) { P_DeathThink(player); return true; // stop! } return false; // don't stop } void P_PlayerThinkMorph(player_t *player) { #if __JHERETIC__ || __JHEXEN__ if(player->morphTics) { P_MorphThink(player); if(!--player->morphTics) { // Attempt to undo the pig/chicken. P_UndoPlayerMorph(player); } } #endif } void P_PlayerThinkMove(player_t *player) { mobj_t *plrmo = player->plr->mo; // Move around. // Reactiontime is used to prevent movement for a bit after a teleport. if(plrmo && !plrmo->reactionTime) { P_MovePlayer(player); #if __JHEXEN__ plrmo = player->plr->mo; if(player->powers[PT_SPEED] && !(mapTime & 1) && P_ApproxDistance(plrmo->mom[MX], plrmo->mom[MY]) > 12) { mobj_t* speedMo; int playerNum; if((speedMo = P_SpawnMobj3fv(MT_PLAYER_SPEED, plrmo->pos, plrmo->angle, 0))) { playerNum = P_GetPlayerNum(player); if(player->class == PCLASS_FIGHTER) { // The first type should be blue, and the // third should be the Fighter's original gold color. if(playerNum == 0) { speedMo->flags |= 2 << MF_TRANSSHIFT; } else if(playerNum != 2) { speedMo->flags |= playerNum << MF_TRANSSHIFT; } } else if(playerNum) { // Set color translation bits for player sprites. speedMo->flags |= playerNum << MF_TRANSSHIFT; } speedMo->target = plrmo; speedMo->special1 = player->class; if(speedMo->special1 > 2) { speedMo->special1 = 0; } speedMo->sprite = plrmo->sprite; speedMo->floorClip = plrmo->floorClip; if(player == &players[CONSOLEPLAYER]) { speedMo->flags2 |= MF2_DONTDRAW; } } } #endif } } void P_PlayerThinkFly(player_t *player) { mobj_t *plrmo = player->plr->mo; // Reactiontime is used to prevent movement for a bit after a teleport. if(plrmo->reactionTime) return; // Is flying allowed? if(player->plr->flags & DDPF_CAMERA) return; if(player->brain.fallDown) { plrmo->flags2 &= ~MF2_FLY; plrmo->flags &= ~MF_NOGRAVITY; } else if(player->brain.upMove != 0 && player->powers[PT_FLIGHT]) { player->flyHeight = player->brain.upMove * 10; if(!(plrmo->flags2 & MF2_FLY)) { plrmo->flags2 |= MF2_FLY; plrmo->flags |= MF_NOGRAVITY; #if __JHEXEN__ if(plrmo->mom[MZ] <= -39) { // Stop falling scream. S_StopSound(0, plrmo); } #endif } } // Apply Z momentum based on flight speed. if(plrmo->flags2 & MF2_FLY) { plrmo->mom[MZ] = (float) player->flyHeight; if(player->flyHeight) { player->flyHeight /= 2; } } } void P_PlayerThinkJump(player_t *player) { if(player->plr->mo->reactionTime) return; // Not yet. // Jumping. if(player->jumpTics) player->jumpTics--; P_CheckPlayerJump(player); } void P_PlayerThinkView(player_t* player) { P_CalcHeight(player); } void P_PlayerThinkSpecial(player_t* player) { if(P_ToXSector(P_GetPtrp(player->plr->mo->subsector, DMU_SECTOR))->special) P_PlayerInSpecialSector(player); #if __JHEXEN__ P_PlayerOnSpecialFloor(player); #endif } #if __JHERETIC__ || __JHEXEN__ /** * For inventory management, could be done client-side. */ void P_PlayerThinkInventory(player_t* player) { int pnum = player - players; if(player->brain.cycleInvItem) { if(!Hu_InventoryIsOpen(pnum)) { Hu_InventoryOpen(pnum, true); return; } Hu_InventoryMove(pnum, player->brain.cycleInvItem, cfg.inventoryWrap, false); } } #endif void P_PlayerThinkSounds(player_t* player) { #if __JHEXEN__ mobj_t* plrmo = player->plr->mo; switch(player->class) { case PCLASS_FIGHTER: if(plrmo->mom[MZ] <= -35 && plrmo->mom[MZ] >= -40 && !player->morphTics && !S_IsPlaying(SFX_PLAYER_FIGHTER_FALLING_SCREAM, plrmo)) { S_StartSound(SFX_PLAYER_FIGHTER_FALLING_SCREAM, plrmo); } break; case PCLASS_CLERIC: if(plrmo->mom[MZ] <= -35 && plrmo->mom[MZ] >= -40 && !player->morphTics && !S_IsPlaying(SFX_PLAYER_CLERIC_FALLING_SCREAM, plrmo)) { S_StartSound(SFX_PLAYER_CLERIC_FALLING_SCREAM, plrmo); } break; case PCLASS_MAGE: if(plrmo->mom[MZ] <= -35 && plrmo->mom[MZ] >= -40 && !player->morphTics && !S_IsPlaying(SFX_PLAYER_MAGE_FALLING_SCREAM, plrmo)) { S_StartSound(SFX_PLAYER_MAGE_FALLING_SCREAM, plrmo); } break; default: break; } #endif } void P_PlayerThinkItems(player_t* player) { #if __JHERETIC__ || __JHEXEN__ inventoryitemtype_t i, type = IIT_NONE; // What to use? int pnum = player - players; if(player->brain.useInvItem) { type = P_InventoryReadyItem(pnum); } // Inventory item hot keys. for(i = IIT_FIRST; i < NUM_INVENTORYITEM_TYPES; ++i) { const def_invitem_t* def = P_GetInvItemDef(i); if(def->hotKeyCtrlIdent != -1 && P_GetImpulseControlState(pnum, def->hotKeyCtrlIdent)) { type = i; break; } } // Panic? if(type == IIT_NONE && P_GetImpulseControlState(pnum, CTL_PANIC)) type = NUM_INVENTORYITEM_TYPES; if(type != IIT_NONE) { // Use one (or more) inventory items. P_InventoryUse(pnum, type, false); } #endif #if __JHERETIC__ || __JHEXEN__ if(player->brain.upMove > 0 && !player->powers[PT_FLIGHT]) { // Start flying automatically. P_InventoryUse(pnum, IIT_FLY, false); } #endif } void P_PlayerThinkWeapons(player_t* player) { playerbrain_t* brain = &player->brain; weapontype_t oldweapon = player->pendingWeapon; weapontype_t newweapon = WT_NOCHANGE; // Check for weapon change. #if __JHERETIC__ || __JHEXEN__ if(brain->changeWeapon != WT_NOCHANGE && !player->morphTics) #else if(brain->changeWeapon != WT_NOCHANGE) #endif { // Direct slot selection. weapontype_t cand, first; // Is this a same-slot weapon cycle? if(P_GetWeaponSlot(brain->changeWeapon) == P_GetWeaponSlot(player->readyWeapon)) { // Yes. cand = player->readyWeapon; } else { // No. cand = brain->changeWeapon; } first = cand = P_WeaponSlotCycle(cand, brain->cycleWeapon < 0); do { if(player->weapons[cand].owned) newweapon = cand; } while(newweapon == WT_NOCHANGE && (cand = P_WeaponSlotCycle(cand, brain->cycleWeapon < 0)) != first); } else if(brain->cycleWeapon) { // Linear cycle. newweapon = P_PlayerFindWeapon(player, brain->cycleWeapon < 0); } if(newweapon != WT_NOCHANGE && newweapon != player->readyWeapon) { if(weaponInfo[newweapon][player->class].mode[0].gameModeBits & gameModeBits) { player->pendingWeapon = newweapon; } } if(player->pendingWeapon != oldweapon) { #if __JDOOM__ || __JDOOM64__ player->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; #elif __JHEXEN__ player->update |= PSF_PENDING_WEAPON; #endif } } void P_PlayerThinkUse(player_t *player) { if(IS_NETGAME && IS_SERVER && player != &players[CONSOLEPLAYER]) { // Clients send use requests instead. return; } // Check for use. if(player->brain.use) { if(!player->useDown) { P_UseLines(player); player->useDown = true; } } else { player->useDown = false; } } void P_PlayerThinkPsprites(player_t *player) { // Cycle psprites. P_MovePsprites(player); } void P_PlayerThinkHUD(player_t* player) { playerbrain_t* brain = &player->brain; if(brain->hudShow) ST_HUDUnHide(player - players, HUE_FORCE); if(brain->scoreShow) HU_ScoreBoardUnHide(player - players); if(brain->logRefresh) Hu_LogRefresh(player - players); } void P_PlayerThinkMap(player_t* player) { uint plnum = player - players; playerbrain_t* brain = &player->brain; automapid_t map = AM_MapForPlayer(plnum); if(brain->mapToggle) AM_Open(map, !AM_IsActive(map), false); if(brain->mapFollow) AM_ToggleFollow(map); if(brain->mapRotate) AM_SetViewRotate(map, 2); // 2 = toggle. if(brain->mapZoomMax) AM_ToggleZoomMax(map); if(brain->mapMarkAdd) { mobj_t* pmo = player->plr->mo; AM_AddMark(map, pmo->pos[VX], pmo->pos[VY], pmo->pos[VZ]); } if(brain->mapMarkClearAll) AM_ClearMarks(map); } void P_PlayerThinkPowers(player_t* player) { // Counters, time dependend power ups. #if __JDOOM__ || __JDOOM64__ // Strength counts up to diminish fade. if(player->powers[PT_STRENGTH]) player->powers[PT_STRENGTH]++; if(player->powers[PT_IRONFEET]) player->powers[PT_IRONFEET]--; #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ if(player->powers[PT_INVULNERABILITY]) player->powers[PT_INVULNERABILITY]--; if(player->powers[PT_INVISIBILITY]) { if(!--player->powers[PT_INVISIBILITY]) player->plr->mo->flags &= ~MF_SHADOW; } #endif #if __JDOOM__ || __JDOOM64__ || __JHEXEN__ if(player->powers[PT_INFRARED]) player->powers[PT_INFRARED]--; #endif if(player->damageCount) player->damageCount--; if(player->bonusCount) player->bonusCount--; #if __JHERETIC__ || __JHEXEN__ # if __JHERETIC__ if(player->powers[PT_FLIGHT]) # elif __JHEXEN__ if(player->powers[PT_FLIGHT] && IS_NETGAME) # endif { if(!--player->powers[PT_FLIGHT]) { if(player->plr->mo->pos[VZ] != player->plr->mo->floorZ && cfg.lookSpring) { player->centering = true; } player->plr->mo->flags2 &= ~MF2_FLY; player->plr->mo->flags &= ~MF_NOGRAVITY; } } #endif #if __JHERETIC__ if(player->powers[PT_WEAPONLEVEL2]) { if(!--player->powers[PT_WEAPONLEVEL2]) { if((player->readyWeapon == WT_SIXTH) && (player->pSprites[ps_weapon].state != &STATES[S_PHOENIXREADY]) && (player->pSprites[ps_weapon].state != &STATES[S_PHOENIXUP])) { P_SetPsprite(player, ps_weapon, S_PHOENIXREADY); player->ammo[AT_FIREORB].owned = MAX_OF(0, player->ammo[AT_FIREORB].owned - USE_PHRD_AMMO_2); player->refire = 0; player->update |= PSF_AMMO; } else if((player->readyWeapon == WT_EIGHTH) || (player->readyWeapon == WT_FIRST)) { player->pendingWeapon = player->readyWeapon; player->update |= PSF_PENDING_WEAPON; } } } #endif // Colormaps #if __JHERETIC__ || __JHEXEN__ if(player->powers[PT_INFRARED]) { if(player->powers[PT_INFRARED] <= BLINKTHRESHOLD) { if(player->powers[PT_INFRARED] & 8) { player->plr->fixedColorMap = 0; } else { player->plr->fixedColorMap = 1; } } else if(!(mapTime & 16)) /* && player == &players[CONSOLEPLAYER]) */ { ddplayer_t *dp = player->plr; int playerNumber = player - players; if(newTorch[playerNumber]) { if(dp->fixedColorMap + newTorchDelta[playerNumber] > 7 || dp->fixedColorMap + newTorchDelta[playerNumber] < 1 || newTorch[playerNumber] == dp->fixedColorMap) { newTorch[playerNumber] = 0; } else { dp->fixedColorMap += newTorchDelta[playerNumber]; } } else { newTorch[playerNumber] = (M_Random() & 7) + 1; newTorchDelta[playerNumber] = (newTorch[playerNumber] == dp->fixedColorMap) ? 0 : ((newTorch[playerNumber] > dp->fixedColorMap) ? 1 : -1); } } } else { player->plr->fixedColorMap = 0; } #endif #if __JHEXEN__ if(player->powers[PT_INVULNERABILITY]) { if(player->class == PCLASS_CLERIC) { if(!(mapTime & 7) && (player->plr->mo->flags & MF_SHADOW) && !(player->plr->mo->flags2 & MF2_DONTDRAW)) { player->plr->mo->flags &= ~MF_SHADOW; if(!(player->plr->mo->flags & MF_ALTSHADOW)) { player->plr->mo->flags2 |= MF2_DONTDRAW | MF2_NONSHOOTABLE; } } if(!(mapTime & 31)) { if(player->plr->mo->flags2 & MF2_DONTDRAW) { if(!(player->plr->mo->flags & MF_SHADOW)) { player->plr->mo->flags |= MF_SHADOW | MF_ALTSHADOW; } else { player->plr->mo->flags2 &= ~(MF2_DONTDRAW | MF2_NONSHOOTABLE); } } else { player->plr->mo->flags |= MF_SHADOW; player->plr->mo->flags &= ~MF_ALTSHADOW; } } } if(!(--player->powers[PT_INVULNERABILITY])) { player->plr->mo->flags2 &= ~(MF2_INVULNERABLE | MF2_REFLECTIVE); if(player->class == PCLASS_CLERIC) { player->plr->mo->flags2 &= ~(MF2_DONTDRAW | MF2_NONSHOOTABLE); player->plr->mo->flags &= ~(MF_SHADOW | MF_ALTSHADOW); } } } if(player->powers[PT_MINOTAUR]) { player->powers[PT_MINOTAUR]--; } if(player->powers[PT_SPEED]) { player->powers[PT_SPEED]--; } if(player->poisonCount && !(mapTime & 15)) { player->poisonCount -= 5; if(player->poisonCount < 0) { player->poisonCount = 0; } P_PoisonDamage(player, player->poisoner, 1, true); } #endif // __JHEXEN__ } /** * Handles the updating of the player's view angles depending on the game * input controllers. Control states are queried from the engine. Note * that this is done as often as possible (i.e., on every frame) so that * changes will be smooth and lag-free. * * @param player Player doing the thinking. * @param ticLength Time to think, in seconds. Use as a multiplier. * Note that original game logic was always using a * tick duration of 1/35 seconds. */ void P_PlayerThinkLookAround(player_t* player, timespan_t ticLength) { int playerNum = player - players; ddplayer_t* plr = player->plr; float vel, off, turnSpeed; float offsetSensitivity = 100; /// \fixme Should be done engine-side, mouse sensitivity! classinfo_t* pClassInfo = PCLASS_INFO(player->class); if(!plr->mo || player->playerState == PST_DEAD || player->viewLock) return; // Nothing to control. turnSpeed = pClassInfo->turnSpeed[0] * TICRATE; // Check for extra speed. P_GetControlState(playerNum, CTL_SPEED, &vel, NULL); if((vel != 0) ^ (cfg.alwaysRun != 0)) { // Hurry, good man! turnSpeed = pClassInfo->turnSpeed[1] * TICRATE; } // Yaw. if(!((plr->mo->flags & MF_JUSTATTACKED) || player->brain.lunge)) { P_GetControlState(playerNum, CTL_TURN, &vel, &off); plr->mo->angle -= FLT2FIX(turnSpeed * vel * ticLength) + (fixed_t)(offsetSensitivity * off / 180 * ANGLE_180); } // Look center requested? if(P_GetImpulseControlState(playerNum, CTL_LOOK_CENTER)) player->centering = true; P_GetControlState(playerNum, CTL_LOOK, &vel, &off); if(player->centering) { // Automatic vertical look centering. float step = 8 * ticLength * TICRATE; if(plr->lookDir > step) { plr->lookDir -= step; } else if(plr->lookDir < -step) { plr->lookDir += step; } else { plr->lookDir = 0; player->centering = false; } } else { // Pitch as controlled by CTL_LOOK. plr->lookDir += 110.f/85.f * ((640 * TICRATE)/65535.f*360 * vel * ticLength + offsetSensitivity * off); if(plr->lookDir < -110) plr->lookDir = -110; else if(plr->lookDir > 110) plr->lookDir = 110; } } void P_PlayerThinkUpdateControls(player_t* player) { int playerNum = player - players; float vel, off, offsetSensitivity = 100; int i; boolean strafe = false; playerbrain_t *brain = &player->brain; boolean oldAttack = brain->attack; // Check for speed. P_GetControlState(playerNum, CTL_SPEED, &vel, 0); brain->speed = (vel != 0); // Check for strafe. P_GetControlState(playerNum, CTL_MODIFIER_1, &vel, 0); strafe = (vel != 0); // Move status. P_GetControlState(playerNum, CTL_WALK, &vel, &off); brain->forwardMove = off * offsetSensitivity + vel; P_GetControlState(playerNum, CTL_SIDESTEP, &vel, &off); // Saturate sidestep. vel = (vel > 0? 1 : vel < 0? -1 : 0); brain->sideMove = off * offsetSensitivity + vel; // Flight. P_GetControlState(playerNum, CTL_ZFLY, &vel, &off); brain->upMove = off + vel; if(P_GetImpulseControlState(playerNum, CTL_FALL_DOWN)) { brain->fallDown = true; } else { brain->fallDown = false; } // Check for look centering based on lookSpring. if(cfg.lookSpring && (fabs(brain->forwardMove) > .333f || fabs(brain->sideMove > .333f))) { // Center view when mlook released w/lookspring, or when moving. player->centering = true; } // Jump. brain->jump = (P_GetImpulseControlState(playerNum, CTL_JUMP) != 0); // Use. brain->use = (P_GetImpulseControlState(playerNum, CTL_USE) != 0); // Fire. P_GetControlState(playerNum, CTL_ATTACK, &vel, &off); brain->attack = (vel + off != 0); // Once dead, the intended action for a given control state change, // changes. Here we interpret Use and Fire as "I wish to be Reborn". brain->doReborn = false; if(player->playerState == PST_DEAD) { if(brain->use || (brain->attack && !oldAttack)) brain->doReborn = true; } // Weapon cycling. if(P_GetImpulseControlState(playerNum, CTL_NEXT_WEAPON)) { brain->cycleWeapon = +1; } else if(P_GetImpulseControlState(playerNum, CTL_PREV_WEAPON)) { brain->cycleWeapon = -1; } else { brain->cycleWeapon = 0; } // Weapons. brain->changeWeapon = WT_NOCHANGE; for(i = 0; i < NUM_WEAPON_TYPES && (CTL_WEAPON1 + i <= CTL_WEAPON0); i++) if(P_GetImpulseControlState(playerNum, CTL_WEAPON1 + i)) { brain->changeWeapon = i; brain->cycleWeapon = +1; // Direction for same-slot cycle. #if __JDOOM__ || __JDOOM64__ if(i == WT_EIGHTH || i == WT_NINETH) brain->cycleWeapon = -1; #elif __JHERETIC__ if(i == WT_EIGHTH) brain->cycleWeapon = -1; #endif } #if __JHERETIC__ || __JHEXEN__ // Inventory items. brain->useInvItem = false; if(P_GetImpulseControlState(playerNum, CTL_USE_ITEM)) { // If the inventory is visible, close it (depending on cfg.chooseAndUse). if(Hu_InventoryIsOpen(player - players)) { Hu_InventoryOpen(player - players, false); // close the inventory if(cfg.inventoryUseImmediate) brain->useInvItem = true; } else { brain->useInvItem = true; } } if(P_GetImpulseControlState(playerNum, CTL_NEXT_ITEM)) { brain->cycleInvItem = +1; } else if(P_GetImpulseControlState(playerNum, CTL_PREV_ITEM)) { brain->cycleInvItem = -1; } else { brain->cycleInvItem = 0; } #endif // HUD. brain->hudShow = (P_GetImpulseControlState(playerNum, CTL_HUD_SHOW) != 0); brain->scoreShow = (P_GetImpulseControlState(playerNum, CTL_SCORE_SHOW) != 0); brain->logRefresh = (P_GetImpulseControlState(playerNum, CTL_LOG_REFRESH) != 0); // Automap. brain->mapToggle = (P_GetImpulseControlState(playerNum, CTL_MAP) != 0); brain->mapZoomMax = (P_GetImpulseControlState(playerNum, CTL_MAP_ZOOM_MAX) != 0); brain->mapFollow = (P_GetImpulseControlState(playerNum, CTL_MAP_FOLLOW) != 0); brain->mapRotate = (P_GetImpulseControlState(playerNum, CTL_MAP_ROTATE) != 0); brain->mapMarkAdd = (P_GetImpulseControlState(playerNum, CTL_MAP_MARK_ADD) != 0); brain->mapMarkClearAll = (P_GetImpulseControlState(playerNum, CTL_MAP_MARK_CLEAR_ALL) != 0); } /** * Main thinker function for players. Handles both single player and * multiplayer games, as well as all the different types of players * (normal/camera). * * Functionality is divided to various other functions whose name begins * with "P_PlayerThink". * * @param player Player that is doing the thinking. * @param ticLength How much time has passed in the game world, in * seconds. For instance, to be used as a multiplier * on turning. */ void P_PlayerThink(player_t *player, timespan_t ticLength) { if(P_IsPaused()) return; if(G_GetGameState() != GS_MAP) { // Just check the controls in case some UI stuff is relying on them // (like intermission). P_PlayerThinkUpdateControls(player); return; } P_PlayerThinkState(player); // Adjust turn angles and look direction. This is done in fractional time. P_PlayerThinkLookAround(player, ticLength); if(!M_CheckTrigger(DD_GetVariable(DD_SHARED_FIXED_TRIGGER), ticLength)) return; // It's too soon. #if __JHEXEN__ player->worldTimer++; #endif P_PlayerThinkUpdateControls(player); if(!IS_CLIENT) // Locally only. { P_PlayerThinkCamera(player); // $democam P_PlayerThinkCheat(player); } P_PlayerThinkHUD(player); if(P_PlayerThinkDeath(player)) return; // I'm dead! if(!IS_CLIENT) // Locally only. { P_PlayerThinkMorph(player); P_PlayerThinkAttackLunge(player); P_PlayerThinkMove(player); } P_PlayerThinkFly(player); P_PlayerThinkJump(player); P_PlayerThinkView(player); P_PlayerThinkSpecial(player); if(!IS_CLIENT) // Locally only. { P_PlayerThinkSounds(player); #if __JHERETIC__ || __JHEXEN__ P_PlayerThinkInventory(player); #endif P_PlayerThinkItems(player); } P_PlayerThinkUse(player); P_PlayerThinkWeapons(player); P_PlayerThinkPsprites(player); P_PlayerThinkPowers(player); P_PlayerThinkMap(player); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_xgfile.c0000644000175000017500000003326611357170242022600 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_xgfile.c: Extended Generalized Line Types. * * Writes XG data to file. Parses DD_XGDATA lumps. */ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "p_xg.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef enum xgsegenum_e { XGSEG_END, XGSEG_LINE, XGSEG_SECTOR } xgsegenum_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean xgDataLumps = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static FILE* file; static const byte* readptr; static linetype_t*linetypes = 0; static int num_linetypes = 0; static sectortype_t* sectypes; static int num_sectypes; // CODE -------------------------------------------------------------------- static void WriteByte(byte b) { fputc(b, file); } static void WriteShort(short s) { s = SHORT(s); fwrite(&s, 2, 1, file); } static void WriteLong(long l) { l = LONG(l); fwrite(&l, 4, 1, file); } static void WriteFloat(float f) { f = FLOAT(f); fwrite(&f, 4, 1, file); } /*void Write(void *data, int len) { fwrite(data, len, 1, file); } */ static void WriteString(char *str) { int len; if(!str) { WriteShort(0); return; } len = strlen(str); WriteShort(len); //Write(str, len); fwrite(str, len, 1, file); } static byte ReadByte(void) { return *readptr++; } static short ReadShort(void) { short s = *(const short *) readptr; readptr += 2; // Swap the bytes. //s = (s<<8) + (s>>8); return SHORT(s); } static long ReadLong(void) { long l = *(const long *) readptr; readptr += 4; // Swap the bytes. //l = (l<<24) + (l>>24) + ((l & 0xff0000) >> 8) + ((l & 0xff00) << 8); return LONG(l); } static float ReadFloat(void) { long f = ReadLong(); float returnValue = 0; memcpy(&returnValue, &f, 4); return returnValue; } /** * I could just return a pointer to the string, but that risks losing * it somewhere. Now we can be absolutely sure it can't be lost. */ static void ReadString(char** str) { int len = ReadShort(); if(!len) // Null string? { *str = 0; return; } if(len < 0) Con_Error("ReadString: Bogus len!\n"); // Allocate memory for the string. *str = Z_Malloc(len + 1, PU_STATIC, 0); memcpy(*str, readptr, len); readptr += len; (*str)[len] = 0; } #if 0 // No longer supported. void XG_WriteTypes(FILE* f) { int i, k; int linecount = 0, sectorcount = 0; char buff[6]; linetype_t line; sectortype_t sec; file = f; // The first four four bytes are a header. // They will be updated with the real counts afterwards. WriteShort(0); // Number of lines & sectors (two shorts). WriteShort(0); // This is a very simple way to get the definitions. for(i = 1; i < 65536; ++i) { sprintf(buff, "%i", i); if(!Def_Get(DD_DEF_LINE_TYPE, buff, &line)) continue; linecount++; // Write marker. WriteByte(XGSEG_LINE); WriteShort(line.id); WriteLong(line.flags); WriteLong(line.flags2); WriteLong(line.flags3); WriteShort(line.lineClass); WriteByte(line.actType); WriteShort(line.actCount); WriteFloat(line.actTime); WriteLong(line.actTag); for(k = 0; k < DDLT_MAX_APARAMS; ++k) WriteLong(line.aparm[k]); WriteFloat(line.tickerStart); WriteFloat(line.tickerEnd); WriteLong(line.tickerInterval); WriteShort(line.actSound); WriteShort(line.deactSound); WriteShort(line.evChain); WriteShort(line.actChain); WriteShort(line.deactChain); WriteByte(line.wallSection); WriteShort(line.actMaterial); WriteShort(line.deactMaterial); WriteString(line.actMsg); WriteString(line.deactMsg); WriteFloat(line.materialMoveAngle); WriteFloat(line.materialMoveSpeed); for(k = 0; k < DDLT_MAX_PARAMS; ++k) WriteLong(line.iparm[k]); for(k = 0; k < DDLT_MAX_PARAMS; ++k) WriteFloat(line.fparm[k]); for(k = 0; k < DDLT_MAX_SPARAMS; k++) WriteString(line.sparm[k]); } // Then the sectors. for(i = 1; i < 65536; ++i) { sprintf(buff, "%i", i); if(!Def_Get(DD_DEF_SECTOR_TYPE, buff, &sec)) continue; sectorcount++; // Write marker. WriteByte(XGSEG_SECTOR); WriteShort(sec.id); WriteLong(sec.flags); WriteLong(sec.actTag); for(k = 0; k < DDLT_MAX_CHAINS; ++k) WriteLong(sec.chain[k]); for(k = 0; k < DDLT_MAX_CHAINS; ++k) WriteLong(sec.chainFlags[k]); for(k = 0; k < DDLT_MAX_CHAINS; ++k) WriteFloat(sec.start[k]); for(k = 0; k < DDLT_MAX_CHAINS; ++k) WriteFloat(sec.end[k]); for(k = 0; k < DDLT_MAX_CHAINS; ++k) { WriteFloat(sec.interval[k][0]); WriteFloat(sec.interval[k][1]); } for(k = 0; k < DDLT_MAX_CHAINS; ++k) WriteLong(sec.count[k]); WriteShort(sec.ambientSound); WriteFloat(sec.soundInterval[0]); WriteFloat(sec.soundInterval[1]); WriteFloat(sec.materialMoveAngle[0]); WriteFloat(sec.materialMoveAngle[1]); WriteFloat(sec.materialMoveSpeed[0]); WriteFloat(sec.materialMoveSpeed[1]); WriteFloat(sec.windAngle); WriteFloat(sec.windSpeed); WriteFloat(sec.verticalWind); WriteFloat(sec.gravity); WriteFloat(sec.friction); WriteString(sec.lightFunc); WriteShort(sec.lightInterval[0]); WriteShort(sec.lightInterval[1]); WriteString(sec.colFunc[0]); WriteString(sec.colFunc[1]); WriteString(sec.colFunc[2]); for(k = 0; k < 3; ++k) { WriteShort(sec.colInterval[k][0]); WriteShort(sec.colInterval[k][1]); } WriteString(sec.floorFunc); WriteFloat(sec.floorMul); WriteFloat(sec.floorOff); WriteShort(sec.floorInterval[0]); WriteShort(sec.floorInterval[1]); WriteString(sec.ceilFunc); WriteFloat(sec.ceilMul); WriteFloat(sec.ceilOff); WriteShort(sec.ceilInterval[0]); WriteShort(sec.ceilInterval[1]); } // Write the end marker. WriteByte(XGSEG_END); // Update header. rewind(file); WriteShort(linecount); WriteShort(sectorcount); } #endif void XG_ReadXGLump(char* name) { lumpnum_t lump; void* buf; int lc = 0, sc = 0, i; linetype_t* li; sectortype_t* sec; boolean done = false; if((lump = W_CheckNumForName(name)) < 0) return; // No such lump. xgDataLumps = true; Con_Message("XG_ReadTypes: Reading XG types from DDXGDATA.\n"); buf = malloc(W_LumpLength(lump)); W_ReadLump(lump, buf); readptr = buf; num_linetypes = ReadShort(); num_sectypes = ReadShort(); // Allocate the arrays. linetypes = Z_Calloc(sizeof(*linetypes) * num_linetypes, PU_STATIC, 0); sectypes = Z_Calloc(sizeof(*sectypes) * num_sectypes, PU_STATIC, 0); while(!done) { // Get next segment. switch(ReadByte()) { case XGSEG_END: done = true; break; case XGSEG_LINE: li = linetypes + lc++; // Read the def. li->id = ReadShort(); li->flags = ReadLong(); li->flags2 = ReadLong(); li->flags3 = ReadLong(); li->lineClass = ReadShort(); li->actType = ReadByte(); li->actCount = ReadShort(); li->actTime = ReadFloat(); li->actTag = ReadLong(); for(i = 0; i < DDLT_MAX_APARAMS; ++i) li->aparm[i] = ReadLong(); li->tickerStart = ReadFloat(); li->tickerEnd = ReadFloat(); li->tickerInterval = ReadLong(); li->actSound = ReadShort(); li->deactSound = ReadShort(); li->evChain = ReadShort(); li->actChain = ReadShort(); li->deactChain = ReadShort(); li->wallSection = ReadByte(); li->actMaterial = /* \fixme Convert texture idx to material idx */ ReadShort(); li->deactMaterial = /* \fixme Convert texture idx to material idx */ ReadShort(); ReadString(&li->actMsg); ReadString(&li->deactMsg); li->materialMoveAngle = ReadFloat(); li->materialMoveSpeed = ReadFloat(); for(i = 0; i < DDLT_MAX_PARAMS; ++i) li->iparm[i] = ReadLong(); for(i = 0; i < DDLT_MAX_PARAMS; ++i) li->fparm[i] = ReadFloat(); for(i = 0; i < DDLT_MAX_SPARAMS; ++i) ReadString(&li->sparm[i]); break; case XGSEG_SECTOR: sec = sectypes + sc++; // Read the def. sec->id = ReadShort(); sec->flags = ReadLong(); sec->actTag = ReadLong(); for(i = 0; i < DDLT_MAX_CHAINS; ++i) sec->chain[i] = ReadLong(); for(i = 0; i < DDLT_MAX_CHAINS; ++i) sec->chainFlags[i] = ReadLong(); for(i = 0; i < DDLT_MAX_CHAINS; ++i) sec->start[i] = ReadFloat(); for(i = 0; i < DDLT_MAX_CHAINS; ++i) sec->end[i] = ReadFloat(); for(i = 0; i < DDLT_MAX_CHAINS; ++i) { sec->interval[i][0] = ReadFloat(); sec->interval[i][1] = ReadFloat(); } for(i = 0; i < DDLT_MAX_CHAINS; ++i) sec->count[i] = ReadLong(); sec->ambientSound = ReadShort(); sec->soundInterval[0] = ReadFloat(); sec->soundInterval[1] = ReadFloat(); sec->materialMoveAngle[0] = ReadFloat(); sec->materialMoveAngle[1] = ReadFloat(); sec->materialMoveSpeed[0] = ReadFloat(); sec->materialMoveSpeed[1] = ReadFloat(); sec->windAngle = ReadFloat(); sec->windSpeed = ReadFloat(); sec->verticalWind = ReadFloat(); sec->gravity = ReadFloat(); sec->friction = ReadFloat(); ReadString(&sec->lightFunc); sec->lightInterval[0] = ReadShort(); sec->lightInterval[1] = ReadShort(); ReadString(&sec->colFunc[0]); ReadString(&sec->colFunc[1]); ReadString(&sec->colFunc[2]); for(i = 0; i < 3; ++i) { sec->colInterval[i][0] = ReadShort(); sec->colInterval[i][1] = ReadShort(); } ReadString(&sec->floorFunc); sec->floorMul = ReadFloat(); sec->floorOff = ReadFloat(); sec->floorInterval[0] = ReadShort(); sec->floorInterval[1] = ReadShort(); ReadString(&sec->ceilFunc); sec->ceilMul = ReadFloat(); sec->ceilOff = ReadFloat(); sec->ceilInterval[0] = ReadShort(); sec->ceilInterval[1] = ReadShort(); break; default: Con_Error("XG_ReadXGLump: Bad segment!\n"); } } free(buf); } /** * See if any line or sector types are saved in a DDXGDATA lump. */ void XG_ReadTypes(void) { num_linetypes = 0; num_sectypes = 0; if(linetypes) Z_Free(linetypes); if(sectypes) Z_Free(sectypes); linetypes = 0; sectypes = 0; XG_ReadXGLump("DDXGDATA"); } linetype_t* XG_GetLumpLine(int id) { int i; for(i = 0; i < num_linetypes; ++i) if(linetypes[i].id == id) return linetypes + i; return NULL; // Not found. } sectortype_t *XG_GetLumpSector(int id) { int i; for(i = 0; i < num_sectypes; ++i) if(sectypes[i].id == id) return sectypes + i; return NULL; // Not found. } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/dmu_lib.c0000644000175000017500000002134011357170242022404 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dmu_lib.c: Helper routines for accessing the DMU API */ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "dmu_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- linedef_t* P_AllocDummyLine(void) { xline_t* extra = Z_Calloc(sizeof(xline_t), PU_STATIC, 0); return P_AllocDummy(DMU_LINEDEF, extra); } void P_FreeDummyLine(linedef_t* line) { Z_Free(P_DummyExtraData(line)); P_FreeDummy(line); } /** * Copies all (changeable) properties from one line to another including the * extended properties. */ void P_CopyLine(linedef_t* dest, linedef_t* src) { int i, sidx; sidedef_t* sidefrom, *sideto; xline_t* xsrc = P_ToXLine(src); xline_t* xdest = P_ToXLine(dest); if(src == dest) return; // no point copying self // Copy the built-in properties for(i = 0; i < 2; ++i) // For each side { sidx = (i==0? DMU_SIDEDEF0 : DMU_SIDEDEF1); sidefrom = P_GetPtrp(src, sidx); sideto = P_GetPtrp(dest, sidx); if(!sidefrom || !sideto) continue; #if 0 // P_Copyp is not implemented in Doomsday yet. P_Copyp(DMU_TOP_MATERIAL_OFFSET_XY, sidefrom, sideto); P_Copyp(DMU_TOP_MATERIAL, sidefrom, sideto); P_Copyp(DMU_TOP_COLOR, sidefrom, sideto); P_Copyp(DMU_MIDDLE_MATERIAL, sidefrom, sideto); P_Copyp(DMU_MIDDLE_COLOR, sidefrom, sideto); P_Copyp(DMU_MIDDLE_BLENDMODE, sidefrom, sideto); P_Copyp(DMU_BOTTOM_MATERIAL, sidefrom, sideto); P_Copyp(DMU_BOTTOM_COLOR, sidefrom, sideto); #else { float temp[4]; float itemp[2]; P_SetPtrp(sideto, DMU_TOP_MATERIAL, P_GetPtrp(sidefrom, DMU_TOP_MATERIAL)); P_GetFloatpv(sidefrom, DMU_TOP_MATERIAL_OFFSET_XY, itemp); P_SetFloatpv(sideto, DMU_TOP_MATERIAL_OFFSET_XY, itemp); P_GetFloatpv(sidefrom, DMU_TOP_COLOR, temp); P_SetFloatpv(sideto, DMU_TOP_COLOR, temp); P_SetPtrp(sideto, DMU_MIDDLE_MATERIAL, P_GetPtrp(sidefrom, DMU_MIDDLE_MATERIAL)); P_GetFloatpv(sidefrom, DMU_MIDDLE_COLOR, temp); P_GetFloatpv(sidefrom, DMU_MIDDLE_MATERIAL_OFFSET_XY, itemp); P_SetFloatpv(sideto, DMU_MIDDLE_MATERIAL_OFFSET_XY, itemp); P_SetFloatpv(sideto, DMU_MIDDLE_COLOR, temp); P_SetIntp(sideto, DMU_MIDDLE_BLENDMODE, P_GetIntp(sidefrom, DMU_MIDDLE_BLENDMODE)); P_SetPtrp(sideto, DMU_BOTTOM_MATERIAL, P_GetPtrp(sidefrom, DMU_BOTTOM_MATERIAL)); P_GetFloatpv(sidefrom, DMU_BOTTOM_MATERIAL_OFFSET_XY, itemp); P_SetFloatpv(sideto, DMU_BOTTOM_MATERIAL_OFFSET_XY, itemp); P_GetFloatpv(sidefrom, DMU_BOTTOM_COLOR, temp); P_SetFloatpv(sideto, DMU_BOTTOM_COLOR, temp); } #endif } // Copy the extended properties too #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ xdest->special = xsrc->special; if(xsrc->xg && xdest->xg) memcpy(xdest->xg, xsrc->xg, sizeof(*xdest->xg)); else xdest->xg = NULL; #else xdest->special = xsrc->special; xdest->arg1 = xsrc->arg1; xdest->arg2 = xsrc->arg2; xdest->arg3 = xsrc->arg3; xdest->arg4 = xsrc->arg4; xdest->arg5 = xsrc->arg5; #endif } /** * Copies all (changeable) properties from one sector to another including * the extended properties. */ void P_CopySector(sector_t* dest, sector_t* src) { xsector_t* xsrc = P_ToXSector(src); xsector_t* xdest = P_ToXSector(dest); if(src == dest) return; // no point copying self. // Copy the built-in properties. #if 0 // P_Copyp is not implemented in Doomsday yet. P_Copyp(DMU_LIGHT_LEVEL, src, dest); P_Copyp(DMU_COLOR, src, dest); P_Copyp(DMU_FLOOR_HEIGHT, src, dest); P_Copyp(DMU_FLOOR_MATERIAL, src, dest); P_Copyp(DMU_FLOOR_COLOR, src, dest); P_Copyp(DMU_FLOOR_MATERIAL_OFFSET_XY, src, dest); P_Copyp(DMU_FLOOR_SPEED, src, dest); P_Copyp(DMU_FLOOR_TARGET_HEIGHT, src, dest); P_Copyp(DMU_CEILING_HEIGHT, src, dest); P_Copyp(DMU_CEILING_MATERIAL, src, dest); P_Copyp(DMU_CEILING_COLOR, src, dest); P_Copyp(DMU_CEILING_MATERIAL_OFFSET_XY, src, dest); P_Copyp(DMU_CEILING_SPEED, src, dest); P_Copyp(DMU_CEILING_TARGET_HEIGHT, src, dest); #else { float ftemp[4]; P_SetFloatp(dest, DMU_LIGHT_LEVEL, P_GetFloatp(src, DMU_LIGHT_LEVEL)); P_GetFloatpv(src, DMU_COLOR, ftemp); P_SetFloatpv(dest, DMU_COLOR, ftemp); P_SetFloatp(dest, DMU_FLOOR_HEIGHT, P_GetFloatp(src, DMU_FLOOR_HEIGHT)); P_SetPtrp(dest, DMU_FLOOR_MATERIAL, P_GetPtrp(src, DMU_FLOOR_MATERIAL)); P_GetFloatpv(src, DMU_FLOOR_COLOR, ftemp); P_SetFloatpv(dest, DMU_FLOOR_COLOR, ftemp); P_GetFloatpv(src, DMU_FLOOR_MATERIAL_OFFSET_XY, ftemp); P_SetFloatpv(dest, DMU_FLOOR_MATERIAL_OFFSET_XY, ftemp); P_SetIntp(dest, DMU_FLOOR_SPEED, P_GetIntp(src, DMU_FLOOR_SPEED)); P_SetFloatp(dest, DMU_FLOOR_TARGET_HEIGHT, P_GetFloatp(src, DMU_FLOOR_TARGET_HEIGHT)); P_SetFloatp(dest, DMU_CEILING_HEIGHT, P_GetFloatp(src, DMU_CEILING_HEIGHT)); P_SetPtrp(dest, DMU_CEILING_MATERIAL, P_GetPtrp(src, DMU_CEILING_MATERIAL)); P_GetFloatpv(src, DMU_CEILING_COLOR, ftemp); P_SetFloatpv(dest, DMU_CEILING_COLOR, ftemp); P_GetFloatpv(src, DMU_CEILING_MATERIAL_OFFSET_XY, ftemp); P_SetFloatpv(dest, DMU_CEILING_MATERIAL_OFFSET_XY, ftemp); P_SetIntp(dest, DMU_CEILING_SPEED, P_GetIntp(src, DMU_CEILING_SPEED)); P_SetFloatp(dest, DMU_CEILING_TARGET_HEIGHT, P_GetFloatp(src, DMU_CEILING_TARGET_HEIGHT)); } #endif // Copy the extended properties too #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ xdest->special = xsrc->special; xdest->soundTraversed = xsrc->soundTraversed; xdest->soundTarget = xsrc->soundTarget; #if __JHERETIC__ xdest->seqType = xsrc->seqType; #endif xdest->SP_floororigheight = xsrc->SP_floororigheight; xdest->SP_ceilorigheight = xsrc->SP_ceilorigheight; xdest->origLight = xsrc->origLight; memcpy(xdest->origRGB, xsrc->origRGB, sizeof(float) * 3); if(xsrc->xg && xdest->xg) memcpy(xdest->xg, xsrc->xg, sizeof(*xdest->xg)); else xdest->xg = NULL; #else xdest->special = xsrc->special; xdest->soundTraversed = xsrc->soundTraversed; xdest->soundTarget = xsrc->soundTarget; xdest->seqType = xsrc->seqType; #endif } float P_SectorLight(sector_t* sector) { return P_GetFloatp(sector, DMU_LIGHT_LEVEL); } void P_SectorSetLight(sector_t* sector, float level) { P_SetFloatp(sector, DMU_LIGHT_LEVEL, level); } void P_SectorModifyLight(sector_t* sector, float value) { float level = MINMAX_OF(0.f, P_SectorLight(sector) + value, 1.f); P_SectorSetLight(sector, level); } void P_SectorModifyLightx(sector_t* sector, fixed_t value) { P_SetFloatp(sector, DMU_LIGHT_LEVEL, P_SectorLight(sector) + FIX2FLT(value) / 255.0f); } void* P_SectorSoundOrigin(sector_t* sec) { return P_GetPtrp(sec, DMU_SOUND_ORIGIN); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_plat.c0000644000175000017500000003677111357170242022266 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Martin Eyre *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_plats.c : Elevators and platforms, raising/lowering. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "dmu_lib.h" #include "p_mapspec.h" #include "p_tick.h" #include "p_plat.h" // MACROS ------------------------------------------------------------------ // Sounds played by the platforms when changing state or moving. // jHexen uses sound sequences, so it's are defined as 'SFX_NONE'. #if __JDOOM__ # define SFX_PLATFORMSTART (SFX_PSTART) # define SFX_PLATFORMMOVE (SFX_STNMOV) # define SFX_PLATFORMSTOP (SFX_PSTOP) #elif __JDOOM64__ # define SFX_PLATFORMSTART (SFX_PSTART) # define SFX_PLATFORMMOVE (SFX_STNMOV) # define SFX_PLATFORMSTOP (SFX_PSTOP) #elif __JHERETIC__ # define SFX_PLATFORMSTART (SFX_PSTART) # define SFX_PLATFORMMOVE (SFX_STNMOV) # define SFX_PLATFORMSTOP (SFX_PSTOP) #elif __JHEXEN__ # define SFX_PLATFORMSTART (SFX_NONE) # define SFX_PLATFORMMOVE (SFX_NONE) # define SFX_PLATFORMSTOP (SFX_NONE) #endif // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Called when a moving plat needs to be removed. * * @param plat Ptr to the plat to remove. */ static void stopPlat(plat_t* plat) { P_ToXSector(plat->sector)->specialData = NULL; #if __JHEXEN__ P_TagFinished(P_ToXSector(plat->sector)->tag); #endif DD_ThinkerRemove(&plat->thinker); } /** * Move a plat up and down. * * @param plat Ptr to the plat to be moved. */ void T_PlatRaise(plat_t* plat) { result_e res; switch(plat->state) { case PS_UP: res = T_MovePlane(plat->sector, plat->speed, plat->high, plat->crush, 0, 1); // Play a "while-moving" sound? #if __JHERETIC__ if(!(mapTime & 31)) S_SectorSound(plat->sector, SORG_FLOOR, SFX_PLATFORMMOVE); #endif #if __JDOOM__ || __JDOOM64__ if(plat->type == PT_RAISEANDCHANGE || plat->type == PT_RAISETONEARESTANDCHANGE) { if(!(mapTime & 7)) S_SectorSound(plat->sector, SORG_FLOOR, SFX_PLATFORMMOVE); } #endif if(res == crushed && (!plat->crush)) { plat->count = plat->wait; plat->state = PS_DOWN; #if __JHEXEN__ SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM); #else # if __JDOOM64__ if(plat->type != PT_DOWNWAITUPDOOR) // jd64 added test # endif S_SectorSound(plat->sector, SORG_FLOOR, SFX_PLATFORMSTART); #endif } else { if(res == pastdest) { plat->count = plat->wait; plat->state = PS_WAIT; #if __JHEXEN__ SN_StopSequenceInSec(plat->sector); #else S_SectorSound(plat->sector, SORG_FLOOR, SFX_PLATFORMSTOP); #endif switch(plat->type) { case PT_DOWNWAITUPSTAY: #if __JHEXEN__ case PT_DOWNBYVALUEWAITUPSTAY: #else # if !__JHERETIC__ case PT_DOWNWAITUPSTAYBLAZE: case PT_RAISETONEARESTANDCHANGE: # endif # if __JDOOM64__ case PT_DOWNWAITUPPLUS16STAYBLAZE: // jd64 case PT_DOWNWAITUPDOOR: // jd64 # endif case PT_RAISEANDCHANGE: #endif stopPlat(plat); break; default: break; } } } break; case PS_DOWN: res = T_MovePlane(plat->sector, plat->speed, plat->low, false, 0, -1); if(res == pastdest) { plat->count = plat->wait; plat->state = PS_WAIT; #if __JHEXEN__ || __JDOOM64__ switch(plat->type) { # if __JHEXEN__ case PT_UPBYVALUEWAITDOWNSTAY: # endif case PT_UPWAITDOWNSTAY: stopPlat(plat); break; default: break; } #endif #if __JHEXEN__ SN_StopSequenceInSec(plat->sector); #else S_SectorSound(plat->sector, SORG_FLOOR, SFX_PLATFORMSTOP); #endif } else { // Play a "while-moving" sound? #if __JHERETIC__ if(!(mapTime & 31)) S_SectorSound(plat->sector, SORG_FLOOR, SFX_PLATFORMMOVE); #endif } break; case PS_WAIT: if(!--plat->count) { if(P_GetFloatp(plat->sector, DMU_FLOOR_HEIGHT) == plat->low) plat->state = PS_UP; else plat->state = PS_DOWN; #if __JHEXEN__ SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM); #else S_SectorSound(plat->sector, SORG_FLOOR, SFX_PLATFORMSTART); #endif } break; default: break; } } #if __JHEXEN__ static int doPlat(linedef_t *line, int tag, byte *args, plattype_e type, int amount) #else static int doPlat(linedef_t *line, int tag, plattype_e type, int amount) #endif { int rtn = 0; float floorHeight; plat_t *plat; sector_t *sec = NULL; #if !__JHEXEN__ sector_t *frontSector = P_GetPtrp(line, DMU_FRONT_SECTOR); #endif xsector_t *xsec; iterlist_t *list; list = P_GetSectorIterListForTag(tag, false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { xsec = P_ToXSector(sec); if(xsec->specialData) continue; // Find lowest & highest floors around sector rtn = 1; plat = Z_Calloc(sizeof(*plat), PU_MAP, 0); plat->thinker.function = T_PlatRaise; DD_ThinkerAdd(&plat->thinker); plat->type = type; plat->sector = sec; xsec->specialData = plat; plat->crush = false; plat->tag = tag; #if __JHEXEN__ plat->speed = (float) args[1] * (1.0 / 8); #endif floorHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); switch(type) { #if !__JHEXEN__ case PT_RAISETONEARESTANDCHANGE: plat->speed = PLATSPEED * .5; P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL)); { float nextFloor; if(P_FindSectorSurroundingNextHighestFloor(sec, floorHeight, &nextFloor)) plat->high = nextFloor; else plat->high = floorHeight; } plat->wait = 0; plat->state = PS_UP; // No more damage if applicable. xsec->special = 0; S_SectorSound(sec, SORG_FLOOR, SFX_PLATFORMMOVE); break; case PT_RAISEANDCHANGE: plat->speed = PLATSPEED * .5; P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_GetPtrp(frontSector, DMU_FLOOR_MATERIAL)); plat->high = floorHeight + amount; plat->wait = 0; plat->state = PS_UP; S_SectorSound(sec, SORG_FLOOR, SFX_PLATFORMMOVE); break; #endif case PT_DOWNWAITUPSTAY: P_FindSectorSurroundingLowestFloor(sec, P_GetFloatp(sec, DMU_FLOOR_HEIGHT), &plat->low); #if __JHEXEN__ plat->low += 8; #else plat->speed = PLATSPEED * 4; #endif if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->state = PS_DOWN; #if __JHEXEN__ plat->wait = (int) args[2]; #else plat->wait = PLATWAIT * TICSPERSEC; #endif #if !__JHEXEN__ S_SectorSound(sec, SORG_FLOOR, SFX_PLATFORMSTART); #endif break; #if __JDOOM64__ || __JHEXEN__ case PT_UPWAITDOWNSTAY: P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high); if(plat->high < floorHeight) plat->high = floorHeight; plat->low = floorHeight; plat->state = PS_UP; # if __JHEXEN__ plat->wait = (int) args[2]; # else plat->wait = PLATWAIT * TICSPERSEC; # endif # if __JDOOM64__ plat->speed = PLATSPEED * 8; S_SectorSound(sec, SORG_FLOOR, SFX_PLATFORMSTART); # endif break; #endif #if __JDOOM64__ case PT_DOWNWAITUPDOOR: // jd64 plat->speed = PLATSPEED * 8; P_FindSectorSurroundingLowestFloor(sec, P_GetFloatp(sec, DMU_FLOOR_HEIGHT), &plat->low); if(plat->low > floorHeight) plat->low = floorHeight; if(plat->low != floorHeight) plat->low += 6; plat->high = floorHeight; plat->wait = 50 * PLATWAIT; plat->state = PS_DOWN; break; #endif #if __JHEXEN__ case PT_DOWNBYVALUEWAITUPSTAY: plat->low = floorHeight - (float) args[3] * 8; if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->wait = (int) args[2]; plat->state = PS_DOWN; break; case PT_UPBYVALUEWAITDOWNSTAY: plat->high = floorHeight + (float) args[3] * 8; if(plat->high < floorHeight) plat->high = floorHeight; plat->low = floorHeight; plat->wait = (int) args[2]; plat->state = PS_UP; break; #endif #if __JDOOM__ || __JDOOM64__ case PT_DOWNWAITUPSTAYBLAZE: plat->speed = PLATSPEED * 8; P_FindSectorSurroundingLowestFloor(sec, P_GetFloatp(sec, DMU_FLOOR_HEIGHT), &plat->low); if(plat->low > floorHeight) plat->low = floorHeight; plat->high = floorHeight; plat->wait = PLATWAIT * TICSPERSEC; plat->state = PS_DOWN; S_SectorSound(sec, SORG_FLOOR, SFX_PLATFORMSTART); break; #endif case PT_PERPETUALRAISE: P_FindSectorSurroundingLowestFloor(sec, P_GetFloatp(sec, DMU_FLOOR_HEIGHT), &plat->low); #if __JHEXEN__ plat->low += 8; #else plat->speed = PLATSPEED; #endif if(plat->low > floorHeight) plat->low = floorHeight; P_FindSectorSurroundingHighestFloor(sec, -500, &plat->high); if(plat->high < floorHeight) plat->high = floorHeight; plat->state = P_Random() & 1; #if __JHEXEN__ plat->wait = (int) args[2]; #else plat->wait = PLATWAIT * TICSPERSEC; #endif #if !__JHEXEN__ S_SectorSound(sec, SORG_FLOOR, SFX_PLATFORMSTART); #endif break; default: break; } #if __JHEXEN__ SN_StartSequenceInSec(plat->sector, SEQ_PLATFORM); #endif } return rtn; } /** * Do Platforms. * * @param amount: is only used for SOME platforms. */ #if __JHEXEN__ int EV_DoPlat(linedef_t *line, byte *args, plattype_e type, int amount) #else int EV_DoPlat(linedef_t *line, plattype_e type, int amount) #endif { #if __JHEXEN__ return doPlat(line, (int) args[0], args, type, amount); #else int rtn = 0; xline_t* xline = P_ToXLine(line); // Activate all plats that are in stasis. switch(type) { case PT_PERPETUALRAISE: rtn = P_PlatActivate(xline->tag); break; default: break; } return doPlat(line, xline->tag, type, amount) || rtn; #endif } #if !__JHEXEN__ typedef struct { short tag; int count; } activateplatparams_t; static boolean activatePlat(thinker_t* th, void* context) { plat_t* plat = (plat_t*) th; activateplatparams_t* params = (activateplatparams_t*) context; if(plat->tag == (int) params->tag && plat->thinker.inStasis) { plat->state = plat->oldState; DD_ThinkerSetStasis(&plat->thinker, false); params->count++; } return true; // Contiue iteration. } /** * Activate a plat that has been put in stasis * (stopped perpetual floor, instant floor/ceil toggle) * * @param tag Tag of plats that should be reactivated. */ int P_PlatActivate(short tag) { activateplatparams_t params; params.tag = tag; params.count = 0; DD_IterateThinkers(T_PlatRaise, activatePlat, ¶ms); return params.count; } #endif typedef struct { short tag; int count; } deactivateplatparams_t; static boolean deactivatePlat(thinker_t* th, void* context) { plat_t* plat = (plat_t*) th; deactivateplatparams_t* params = (deactivateplatparams_t*) context; #if __JHEXEN__ // For THE one with the tag. if(plat->tag == params->tag) { // Destroy it. stopPlat(plat); params->count++; return false; // Stop iteration. } #else // For one with the tag and not in stasis. if(plat->tag == (int) params->tag && !plat->thinker.inStasis) { // Put it in stasis. plat->oldState = plat->state; DD_ThinkerSetStasis(&plat->thinker, true); params->count++; } #endif return true; // Continue iteration. } /** * Handler for "stop perpetual floor" linedef type. * * @param tag Tag of plats to put into stasis. * * @return Number of plats put into stasis. */ int P_PlatDeactivate(short tag) { deactivateplatparams_t params; params.tag = tag; params.count = 0; DD_IterateThinkers(T_PlatRaise, deactivatePlat, ¶ms); return params.count; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/f_infine.c0000644000175000017500000021072711357170242022557 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * f_infine.c : The "In Fine" finale engine. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "hu_log.h" #include "hu_stuff.h" #include "f_infine.h" #include "g_common.h" #include "d_net.h" #include "p_player.h" #include "am_map.h" #include "p_tick.h" #include "p_start.h" // MACROS ------------------------------------------------------------------ #define STACK_SIZE (16) // Size of the InFine state stack. #define MAX_TOKEN_LEN (8192) #define MAX_SEQUENCE (64) #define MAX_PICS (128) #define MAX_TEXT (64) #define MAX_HANDLERS (128) #define FI_REPEAT (-2) // TYPES ------------------------------------------------------------------- typedef char handle_t[32]; typedef struct ficmd_s { char* token; int operands; void (*func) (void); boolean whenSkipping; boolean whenCondSkipping; // Skipping because condition failed. } ficmd_t; typedef struct fivalue_s { float value; float target; int steps; } fivalue_t; typedef struct fi_obj_s { boolean used; handle_t handle; fivalue_t color[4]; fivalue_t scale[2]; fivalue_t x, y; fivalue_t angle; } fiobj_t; typedef struct fipic_s { fiobj_t object; struct fipicflags_s { char is_patch:1; // Raw image or patch. char done:1; // Animation finished (or repeated). char is_rect:1; char is_ximage:1; // External graphics resource. } flags; int seq; int seqWait[MAX_SEQUENCE], seqTimer; int lump[MAX_SEQUENCE]; char flip[MAX_SEQUENCE]; short sound[MAX_SEQUENCE]; // For rectangle-objects. fivalue_t otherColor[4]; fivalue_t edgeColor[4]; fivalue_t otherEdgeColor[4]; } fipic_t; typedef struct fitext_s { fiobj_t object; struct fitextflags_s { char centered:1; char font_b:1; char all_visible:1; } flags; int scrollWait, scrollTimer; // Automatic scrolling upwards. int pos; int wait, timer; int lineheight; char* text; } fitext_t; typedef struct fihandler_s { int code; handle_t marker; } fihandler_t; typedef struct fistate_s { char* script; // A copy of the script. char* cp; // The command cursor. infinemode_t mode; int overlayGameState; // Overlay scripts run only in one gameMode. int timer; boolean conditions[NUM_FICONDS]; int inTime; boolean canSkip, skipping; int doLevel; // Level of DO-skipping. int wait; boolean suspended, paused, eatEvents, showMenu; boolean gotoSkip, skipNext, lastSkipped; handle_t gotoTarget; fitext_t* waitingText; fipic_t* waitingPic; fihandler_t keyHandlers[MAX_HANDLERS]; material_t* bgMaterial; fivalue_t bgColor[4]; fivalue_t imgColor[4]; fivalue_t imgOffset[2]; fivalue_t filter[4]; fivalue_t textColor[9][3]; fipic_t pics[MAX_PICS]; fitext_t text[MAX_TEXT]; } fistate_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void FI_InitValue(fivalue_t* val, float num); int FI_TextObjectLength(fitext_t* tex); // Command functions. void FIC_Do(void); void FIC_End(void); void FIC_BGFlat(void); void FIC_BGTexture(void); void FIC_NoBGMaterial(void); void FIC_Wait(void); void FIC_WaitText(void); void FIC_WaitAnim(void); void FIC_Tic(void); void FIC_InTime(void); void FIC_Color(void); void FIC_ColorAlpha(void); void FIC_Pause(void); void FIC_CanSkip(void); void FIC_NoSkip(void); void FIC_SkipHere(void); void FIC_Events(void); void FIC_NoEvents(void); void FIC_OnKey(void); void FIC_UnsetKey(void); void FIC_If(void); void FIC_IfNot(void); void FIC_Else(void); void FIC_GoTo(void); void FIC_Marker(void); void FIC_Image(void); void FIC_ImageAt(void); void FIC_XImage(void); void FIC_Delete(void); void FIC_Patch(void); void FIC_SetPatch(void); void FIC_Anim(void); void FIC_AnimImage(void); void FIC_StateAnim(void); void FIC_Repeat(void); void FIC_ClearAnim(void); void FIC_PicSound(void); void FIC_ObjectOffX(void); void FIC_ObjectOffY(void); void FIC_ObjectScaleX(void); void FIC_ObjectScaleY(void); void FIC_ObjectScale(void); void FIC_ObjectScaleXY(void); void FIC_ObjectRGB(void); void FIC_ObjectAlpha(void); void FIC_ObjectAngle(void); void FIC_Rect(void); void FIC_FillColor(void); void FIC_EdgeColor(void); void FIC_OffsetX(void); void FIC_OffsetY(void); void FIC_Sound(void); void FIC_SoundAt(void); void FIC_SeeSound(void); void FIC_DieSound(void); void FIC_Music(void); void FIC_MusicOnce(void); void FIC_Filter(void); void FIC_Text(void); void FIC_TextFromDef(void); void FIC_TextFromLump(void); void FIC_SetText(void); void FIC_SetTextDef(void); void FIC_DeleteText(void); void FIC_FontA(void); void FIC_FontB(void); void FIC_TextColor(void); void FIC_TextRGB(void); void FIC_TextAlpha(void); void FIC_TextOffX(void); void FIC_TextOffY(void); void FIC_TextCenter(void); void FIC_TextNoCenter(void); void FIC_TextScroll(void); void FIC_TextPos(void); void FIC_TextRate(void); void FIC_TextLineHeight(void); void FIC_NoMusic(void); void FIC_TextScaleX(void); void FIC_TextScaleY(void); void FIC_TextScale(void); void FIC_PlayDemo(void); void FIC_Command(void); void FIC_ShowMenu(void); void FIC_NoShowMenu(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean briefDisabled = false; // PRIVATE DATA DEFINITIONS ------------------------------------------------ boolean fiActive = false; boolean fiCmdExecuted = false; // Set to true after first command. // Time is measured in seconds. // Colors are floating point and [0,1]. static ficmd_t fiCommands[] = { // Run Control {"DO", 0, FIC_Do, true, true}, {"END", 0, FIC_End}, {"IF", 1, FIC_If}, // if (value-id) {"IFNOT", 1, FIC_IfNot}, // ifnot (value-id) {"ELSE", 0, FIC_Else}, {"GOTO", 1, FIC_GoTo}, // goto (marker) {"MARKER", 1, FIC_Marker, true}, {"in", 1, FIC_InTime}, // in (time) {"pause", 0, FIC_Pause}, {"tic", 0, FIC_Tic}, {"wait", 1, FIC_Wait}, // wait (time) {"waittext", 1, FIC_WaitText}, // waittext (handle) {"waitanim", 1, FIC_WaitAnim}, // waitanim (handle) {"canskip", 0, FIC_CanSkip}, {"noskip", 0, FIC_NoSkip}, {"skiphere", 0, FIC_SkipHere, true}, {"events", 0, FIC_Events}, {"noevents", 0, FIC_NoEvents}, {"onkey", 2, FIC_OnKey}, // onkey (keyname) (marker) {"unsetkey", 1, FIC_UnsetKey}, // unsetkey (keyname) // Screen Control {"color", 3, FIC_Color}, // color (red) (green) (blue) {"coloralpha", 4, FIC_ColorAlpha}, // coloralpha (r) (g) (b) (a) {"flat", 1, FIC_BGFlat}, // flat (flat-id) {"texture", 1, FIC_BGTexture}, // texture (texture-id) {"noflat", 0, FIC_NoBGMaterial}, {"notexture", 0, FIC_NoBGMaterial}, {"offx", 1, FIC_OffsetX}, // offx (x) {"offy", 1, FIC_OffsetY}, // offy (y) {"filter", 4, FIC_Filter}, // filter (r) (g) (b) (a) // Audio {"sound", 1, FIC_Sound}, // sound (snd) {"soundat", 2, FIC_SoundAt}, // soundat (snd) (vol:0-1) {"seesound", 1, FIC_SeeSound}, // seesound (mobjtype) {"diesound", 1, FIC_DieSound}, // diesound (mobjtype) {"music", 1, FIC_Music}, // music (musicname) {"musiconce", 1, FIC_MusicOnce}, // musiconce (musicname) {"nomusic", 0, FIC_NoMusic}, // Objects {"del", 1, FIC_Delete}, // del (handle) {"x", 2, FIC_ObjectOffX}, // x (handle) (x) {"y", 2, FIC_ObjectOffY}, // y (handle) (y) {"sx", 2, FIC_ObjectScaleX}, // sx (handle) (x) {"sy", 2, FIC_ObjectScaleY}, // sy (handle) (y) {"scale", 2, FIC_ObjectScale}, // scale (handle) (factor) {"scalexy", 3, FIC_ObjectScaleXY}, // scalexy (handle) (x) (y) {"rgb", 4, FIC_ObjectRGB}, // rgb (handle) (r) (g) (b) {"alpha", 2, FIC_ObjectAlpha}, // alpha (handle) (alpha) {"angle", 2, FIC_ObjectAngle}, // angle (handle) (degrees) // Rects {"rect", 5, FIC_Rect}, // rect (hndl) (x) (y) (w) (h) {"fillcolor", 6, FIC_FillColor}, // fillcolor (h) (top/bottom/both) (r) (g) (b) (a) {"edgecolor", 6, FIC_EdgeColor}, // edgecolor (h) (top/bottom/both) (r) (g) (b) (a) // Pics {"image", 2, FIC_Image}, // image (handle) (raw-image-lump) {"imageat", 4, FIC_ImageAt}, // imageat (handle) (x) (y) (raw) {"ximage", 2, FIC_XImage}, // ximage (handle) (ext-gfx-filename) {"patch", 4, FIC_Patch}, // patch (handle) (x) (y) (patch) {"set", 2, FIC_SetPatch}, // set (handle) (lump) {"clranim", 1, FIC_ClearAnim}, // clranim (handle) {"anim", 3, FIC_Anim}, // anim (handle) (patch) (time) {"imageanim", 3, FIC_AnimImage}, // imageanim (hndl) (raw-img) (time) {"picsound", 2, FIC_PicSound}, // picsound (hndl) (sound) {"repeat", 1, FIC_Repeat}, // repeat (handle) {"states", 3, FIC_StateAnim}, // states (handle) (state) (count) // Text {"text", 4, FIC_Text}, // text (hndl) (x) (y) (string) {"textdef", 4, FIC_TextFromDef}, // textdef (hndl) (x) (y) (txt-id) {"textlump", 4, FIC_TextFromLump}, // textlump (hndl) (x) (y) (lump) {"settext", 2, FIC_SetText}, // settext (handle) (newtext) {"settextdef", 2, FIC_SetTextDef}, // settextdef (handle) (txt-id) {"precolor", 4, FIC_TextColor}, // precolor (num) (r) (g) (b) {"center", 1, FIC_TextCenter}, // center (handle) {"nocenter", 1, FIC_TextNoCenter}, // nocenter (handle) {"scroll", 2, FIC_TextScroll}, // scroll (handle) (speed) {"pos", 2, FIC_TextPos}, // pos (handle) (pos) {"rate", 2, FIC_TextRate}, // rate (handle) (rate) {"fonta", 1, FIC_FontA}, // fonta (handle) {"fontb", 1, FIC_FontB}, // fontb (handle) {"linehgt", 2, FIC_TextLineHeight}, // linehgt (hndl) (hgt) // Game Control {"playdemo", 1, FIC_PlayDemo}, // playdemo (filename) {"cmd", 1, FIC_Command}, // cmd (console command) {"trigger", 0, FIC_ShowMenu}, {"notrigger", 0, FIC_NoShowMenu}, // Deprecated Pic commands {"delpic", 1, FIC_Delete}, // delpic (handle) // Deprecated Text commands {"deltext", 1, FIC_DeleteText}, // deltext (hndl) {"textrgb", 4, FIC_TextRGB}, // textrgb (handle) (r) (g) (b) {"textalpha", 2, FIC_TextAlpha}, // textalpha (handle) (alpha) {"tx", 2, FIC_TextOffX}, // tx (handle) (x) {"ty", 2, FIC_TextOffY}, // ty (handle) (y) {"tsx", 2, FIC_TextScaleX}, // tsx (handle) (x) {"tsy", 2, FIC_TextScaleY}, // tsy (handle) (y) {"textscale", 3, FIC_TextScale}, // textscale (handle) (x) (y) {NULL, 0, NULL} }; static fistate_t fiStateStack[STACK_SIZE]; static fistate_t* fi; // Pointer to the current state in the stack. static char fiToken[MAX_TOKEN_LEN]; static fipic_t fiDummyPic; static fitext_t fiDummyText; static boolean conditionPresets[NUM_FICONDS]; // CODE -------------------------------------------------------------------- /** * Clear the InFine state to the default, blank state. * The 'fi' pointer must be set before calling this function. */ void FI_ClearState(void) { int i, c; // General game state. G_SetGameAction(GA_NONE); if(fi->mode != FIMODE_OVERLAY) { G_ChangeGameState(GS_INFINE); // Close the automap for all local players. for(i = 0; i < MAXPLAYERS; ++i) AM_Open(AM_MapForPlayer(i), false, true); } fiActive = true; fiCmdExecuted = false; // Nothing is drawn until a cmd has been executed. fi->suspended = false; fi->timer = 0; fi->canSkip = true; // By default skipping is enabled. fi->skipping = false; fi->wait = 0; // Not waiting for anything. fi->inTime = 0; // Interpolation is off. fi->bgMaterial = NULL; // No background material. fi->paused = false; fi->gotoSkip = false; fi->skipNext = false; fi->waitingText = NULL; fi->waitingPic = NULL; memset(fi->gotoTarget, 0, sizeof(fi->gotoTarget)); GL_SetFilter(false); // Clear the current filter. for(i = 0; i < 4; ++i) { FI_InitValue(fi->bgColor + i, 1); } memset(fi->pics, 0, sizeof(fi->pics)); memset(fi->imgOffset, 0, sizeof(fi->imgOffset)); memset(fi->text, 0, sizeof(fi->text)); memset(fi->filter, 0, sizeof(fi->filter)); for(i = 0; i < 9; ++i) { for(c = 0; c < 3; ++c) FI_InitValue(&fi->textColor[i][c], 1); } } void FI_NewState(const char *script) { int size; if(!fi) { // Start from the bottom of the stack. fi = fiStateStack; } else { // Get the next state from the stack. fi++; if(fi == fiStateStack + STACK_SIZE) { Con_Error("FI_NewState: InFine state stack overflow.\n"); } } #ifdef _DEBUG // Is the stack leaking? Con_Printf("FI_NewState: Assigned index %i.\n", fi - fiStateStack); #endif memset(fi, 0, sizeof(*fi)); // Take a copy of the script. size = strlen(script); fi->script = Z_Malloc(size + 1, PU_STATIC, 0); memcpy(fi->script, script, size); fi->script[size] = '\0'; // Init the cursor, too. fi->cp = fi->script; } void FI_DeleteXImage(fipic_t *pic) { DGL_DeleteTextures(1, (DGLuint*)&pic->lump[0]); pic->lump[0] = 0; pic->flags.is_ximage = false; } void FI_PopState(void) { int i; #ifdef _DEBUG Con_Printf("FI_PopState: fi=%p (%i)\n", fi, fi - fiStateStack); #endif if(!fi) { #ifdef _DEBUG Con_Printf("FI_PopState: Pop in NULL state!\n"); #endif return; } // Free the current state. Z_Free(fi->script); // Free all text strings. for(i = 0; i < MAX_TEXT; ++i) { if(fi->text[i].text) { Z_Free(fi->text[i].text); } } // Delete external images. for(i = 0; i < MAX_PICS; ++i) { if(fi->pics[i].flags.is_ximage) { FI_DeleteXImage(fi->pics + i); } } memset(fi, 0, sizeof(*fi)); // Should we go back to NULL? if(fi == fiStateStack) { fi = NULL; fiActive = false; } else { // Return to previous state. fi--; } } /** * Reset the entire InFine state stack. This is called when a new game * is started. */ void FI_Reset(void) { /* if(IS_CLIENT) { #ifdef _DEBUG Con_Printf("FI_Reset: Called in client mode! (not reseting)\n"); #endif return; } */ // The state is suspended when the PlayDemo command is used. // Being suspended means that InFine is currently not active, but // will be restored at a later time. if(fi && fi->suspended) return; // Pop all the states. while(fi) FI_PopState(); fiActive = false; G_ChangeGameState(GS_WAITING); } /** * Start playing the given script. */ void FI_Start(char *finalescript, infinemode_t mode) { int i; if(mode == FIMODE_LOCAL && IS_DEDICATED) { // Dedicated servers don't play local scripts. #ifdef _DEBUG Con_Printf("FI_Start: No local scripts in dedicated mode.\n"); #endif return; } #ifdef _DEBUG Con_Printf("FI_Start: mode=%i '%.30s'\n", mode, finalescript); #endif // Init InFine state. FI_NewState(finalescript); fi->mode = mode; // Clear the message queue for all local players. for(i = 0; i < MAXPLAYERS; ++i) Hu_LogEmpty(i); FI_ClearState(); if(!IS_CLIENT) { // We are able to figure out the truth values of all the // conditions. #if __JHEXEN__ fi->conditions[FICOND_SECRET] = false; // Current hub has been completed? fi->conditions[FICOND_LEAVEHUB] = (P_GetMapCluster(gameMap) != P_GetMapCluster(nextMap)); #else fi->conditions[FICOND_SECRET] = secretExit; // Only Hexen has hubs. fi->conditions[FICOND_LEAVEHUB] = false; #endif } else { // Clients use the server-provided presets. We may not have // enough info to figure out the real values otherwise. for(i = 0; i < NUM_FICONDS; ++i) { fi->conditions[i] = conditionPresets[i]; } } if(mode == FIMODE_OVERLAY) { // Overlay scripts stop when the gameMode changes. fi->overlayGameState = G_GetGameState(); } if(mode != FIMODE_LOCAL) { // Tell clients to start this script. NetSv_Finale(FINF_BEGIN | (mode == FIMODE_AFTER ? FINF_AFTER : mode == FIMODE_OVERLAY ? FINF_OVERLAY : 0), finalescript, fi->conditions, NUM_FICONDS); } memset(&fiDummyText, 0, sizeof(fiDummyText)); } /** * Stop playing the script and go to next game state. */ void FI_End(void) { int oldMode; if(!fiActive || !fi->canSkip) return; oldMode = fi->mode; // This'll set fi to NULL. FI_PopState(); #ifdef _DEBUG Con_Printf("FI_End\n"); #endif if(oldMode != FIMODE_LOCAL) { // Tell clients to stop the finale. NetSv_Finale(FINF_END, 0, NULL, 0); } // If no more scripts are left, go to the next game mode. if(!fiActive) { if(oldMode == FIMODE_AFTER) // A map has been completed. { if(IS_CLIENT) { #if __JHEXEN__ || __JSTRIFE__ Draw_TeleportIcon(); #endif return; } G_SetGameAction(GA_MAPCOMPLETED); // Don't play the debriefing again. briefDisabled = true; } else if(oldMode == FIMODE_BEFORE) { // Enter the map, this was a briefing. G_ChangeGameState(GS_MAP); S_MapMusic(gameEpisode, gameMap); mapStartTic = (int) GAMETIC; mapTime = actualMapTime = 0; } else if(oldMode == FIMODE_LOCAL) { G_ChangeGameState(GS_WAITING); } } } /** * Set the truth value of a condition. Used by clients after they've * received a GPT_FINALE2 packet. */ void FI_SetCondition(int index, boolean value) { if(index < 0 || index >= NUM_FICONDS) return; conditionPresets[index] = value; #ifdef _DEBUG Con_Printf("FI_SetCondition: %i = %s\n", index, value ? "true" : "false"); #endif } DEFCC(CCmdStartInFine) { char *script; if(fiActive) return false; if(!Def_Get(DD_DEF_FINALE, argv[1], &script)) { Con_Printf("Script \"%s\" is not defined.\n", argv[1]); return false; } // The overlay mode doesn't affect the current game mode. FI_Start(script, (G_GetGameState() == GS_MAP? FIMODE_OVERLAY : FIMODE_LOCAL)); return true; } DEFCC(CCmdStopInFine) { if(!fiActive) return false; fi->canSkip = true; FI_End(); return true; } /** * Check if there is a finale before the map. * Returns true if a finale was found. */ int FI_Briefing(uint episode, uint map, ddfinale_t* fin) { char mid[20]; // If we're already in the INFINE state, don't start a finale. if(briefDisabled || G_GetGameState() == GS_INFINE || IS_CLIENT || Get(DD_PLAYBACK)) return false; // Is there such a finale definition? P_GetMapLumpName(episode, map, mid); return Def_Get(DD_DEF_FINALE_BEFORE, mid, fin); } /** * Check if there is a finale after the map. * Returns true if a finale was found. */ int FI_Debriefing(uint episode, uint map, ddfinale_t* fin) { char mid[20]; // If we're already in the INFINE state, don't start a finale. if(briefDisabled) return false; #if __JHEXEN__ if(cfg.overrideHubMsg && G_GetGameState() == GS_MAP && !(nextMap == DDMAXINT && nextMapEntryPoint == DDMAXINT) && P_GetMapCluster(map) != P_GetMapCluster(nextMap)) return false; #endif if(G_GetGameState() == GS_INFINE || IS_CLIENT || Get(DD_PLAYBACK)) return false; // Is there such a finale definition? P_GetMapLumpName(episode, map, mid); return Def_Get(DD_DEF_FINALE_AFTER, mid, fin); } void FI_DemoEnds(void) { if(fi && fi->suspended) { int i; // Restore the InFine state. fi->suspended = false; fiActive = true; G_ChangeGameState(GS_INFINE); G_SetGameAction(GA_NONE); for(i = 0; i < MAXPLAYERS; ++i) AM_Open(AM_MapForPlayer(i), false, true); } } char* FI_GetToken(void) { char* out; if(!fi) return NULL; // Skip whitespace. while(*fi->cp && isspace(*fi->cp)) fi->cp++; if(!*fi->cp) return NULL; // The end has been reached. out = fiToken; if(*fi->cp == '"') // A string? { for(fi->cp++; *fi->cp; fi->cp++) { if(*fi->cp == '"') { fi->cp++; // Convert double quotes to single ones. if(*fi->cp != '"') break; } *out++ = *fi->cp; } } else { while(!isspace(*fi->cp) && *fi->cp) *out++ = *fi->cp++; } *out++ = 0; return fiToken; } int FI_GetInteger(void) { return strtol(FI_GetToken(), NULL, 0); } float FI_GetFloat(void) { return strtod(FI_GetToken(), NULL); } /** * Reads the next token, which should be floating point number. It is * considered seconds, and converted to tics. */ int FI_GetTics(void) { return (int) (FI_GetFloat() * 35 + 0.5); } /** * Execute one (the next) command, advance script cursor. */ void FI_Execute(char * cmd) { int i, k; char* oldcp; // Semicolon terminates DO-blocks. if(!strcmp(cmd, ";")) { if(fi->doLevel > 0) { if(--fi->doLevel == 0) { // The DO-skip has been completed. fi->skipNext = false; fi->lastSkipped = true; } } return; } // We're now going to execute a command. fiCmdExecuted = true; // Is this a command we know how to execute? for(i = 0; fiCommands[i].token; ++i) { if(!stricmp(cmd, fiCommands[i].token)) { // Check that there are enough operands. // k stays at zero if the number of operands is correct. oldcp = fi->cp; for(k = fiCommands[i].operands; k > 0; k--) { if(!FI_GetToken()) { fi->cp = oldcp; Con_Message("FI_Execute: \"%s\" has too few operands.\n", fiCommands[i].token); break; } } // Should we skip this command? if((fi->skipNext && !fiCommands[i].whenCondSkipping) || ((fi->skipping || fi->gotoSkip) && !fiCommands[i].whenSkipping)) { // While not DO-skipping, the condskip has now been done. if(!fi->doLevel) { if(fi->skipNext) fi->lastSkipped = true; fi->skipNext = false; } return; } // If there were enough operands, execute the command. fi->cp = oldcp; if(!k) fiCommands[i].func(); // The END command may clear the current state. if(!fi) return; // Now we've executed the latest command. fi->lastSkipped = false; return; } } // The command was not found! Con_Message("FI_Execute: Unknown command \"%s\".\n", cmd); } /** * @return @c true, if a command was found. * @c false if there are no more commands in the script. */ int FI_ExecuteNextCommand(void) { char* cmd = FI_GetToken(); if(!cmd) return false; FI_Execute(cmd); return true; } void FI_InitValue(fivalue_t* val, float num) { val->target = val->value = num; val->steps = 0; } void FI_SetValue(fivalue_t* val, float num) { val->target = num; val->steps = fi->inTime; if(!val->steps) val->value = val->target; } void FI_ValueThink(fivalue_t* val) { if(val->steps <= 0) { val->steps = 0; val->value = val->target; return; } val->value += (val->target - val->value) / val->steps; val->steps--; } void FI_ValueArrayThink(fivalue_t* val, int num) { int i; for(i = 0; i < num; ++i) FI_ValueThink(val + i); } fihandler_t* FI_GetHandler(int code) { int i; fihandler_t* vacant = NULL; for(i = 0; i < MAX_HANDLERS; ++i) { // Use this if a suitable handler is not already set? if(!vacant && !fi->keyHandlers[i].code) vacant = fi->keyHandlers + i; if(fi->keyHandlers[i].code == code) { return fi->keyHandlers + i; } } // May be NULL, if no more handlers available. return vacant; } void FI_ClearAnimation(fipic_t* pic) { // Kill the old texture. if(pic->flags.is_ximage) FI_DeleteXImage(pic); memset(pic->lump, -1, sizeof(pic->lump)); memset(pic->flip, 0, sizeof(pic->flip)); memset(pic->sound, -1, sizeof(pic->sound)); memset(pic->seqWait, 0, sizeof(pic->seqWait)); pic->seq = 0; pic->flags.done = true; } int FI_GetNextSeq(fipic_t* pic) { int i; for(i = 0; i < MAX_SEQUENCE; ++i) { if(pic->lump[i] <= 0) break; } return i; } fipic_t* FI_FindPic(const char* handle) { int i; if(!handle) return NULL; for(i = 0; i < MAX_PICS; ++i) { if(fi->pics[i].object.used && !stricmp(fi->pics[i].object.handle, handle)) { return &fi->pics[i]; } } return NULL; } void FI_InitRect(fipic_t* pic) { int i; FI_InitValue(&pic->object.x, 0); FI_InitValue(&pic->object.y, 0); FI_InitValue(&pic->object.scale[0], 1); FI_InitValue(&pic->object.scale[1], 1); // Default colors. for(i = 0; i < 4; ++i) { FI_InitValue(&pic->object.color[i], 1); FI_InitValue(&pic->otherColor[i], 1); // Edge alpha is zero by default. FI_InitValue(&pic->edgeColor[i], i < 3 ? 1 : 0); FI_InitValue(&pic->otherEdgeColor[i], i < 3 ? 1 : 0); } } fitext_t* FI_FindText(const char* handle) { int i; for(i = 0; i < MAX_TEXT; ++i) { if(fi->text[i].object.used && !stricmp(fi->text[i].object.handle, handle)) { return &fi->text[i]; } } return NULL; } fiobj_t* FI_FindObject(const char* handle) { fipic_t* pic; fitext_t* text; // First check all pics. if((pic = FI_FindPic(handle)) != NULL) { return &pic->object; } // Then check text objects. if((text = FI_FindText(handle)) != NULL) { return &text->object; } return NULL; } fipic_t* FI_GetPic(const char* handle) { int i; fipic_t* unused = NULL; for(i = 0; i < MAX_PICS; ++i) { if(!fi->pics[i].object.used) { if(!unused) unused = &fi->pics[i]; continue; } if(!stricmp(fi->pics[i].object.handle, handle)) return &fi->pics[i]; } // Allocate an empty one. if(!unused) { Con_Message("FI_GetPic: No room for \"%s\".", handle); return &fiDummyPic; // No more space. } memset(unused, 0, sizeof(*unused)); strncpy(unused->object.handle, handle, sizeof(unused->object.handle) - 1); unused->object.used = true; for(i = 0; i < 4; ++i) FI_InitValue(&unused->object.color[i], 1); for(i = 0; i < 2; ++i) FI_InitValue(&unused->object.scale[i], 1); FI_ClearAnimation(unused); return unused; } fitext_t* FI_GetText(char* handle) { int i; fitext_t* unused = NULL; for(i = 0; i < MAX_TEXT; ++i) { if(!fi->text[i].object.used) { if(!unused) unused = &fi->text[i]; continue; } if(!stricmp(fi->text[i].object.handle, handle)) return &fi->text[i]; } // Allocate an empty one. if(!unused) { Con_Message("FI_GetText: No room for \"%s\".", handle); return &fiDummyText; // No more space. } if(unused->text) Z_Free(unused->text); memset(unused, 0, sizeof(*unused)); strncpy(unused->object.handle, handle, sizeof(unused->object.handle) - 1); unused->object.used = true; unused->wait = 3; #if __JDOOM__ unused->lineheight = 11; FI_InitValue(&unused->object.color[0], 1); // Red text by default. #else unused->lineheight = 9; // White text. for(i = 0; i < 3; ++i) FI_InitValue(&unused->object.color[i], 1); #endif FI_InitValue(&unused->object.color[3], 1); // Opaque. for(i = 0; i < 2; ++i) FI_InitValue(&unused->object.scale[i], 1); return unused; } void FI_SetText(fitext_t* tex, char* str) { size_t len = strlen(str) + 1; if(tex->text) Z_Free(tex->text); // Free any previous text. tex->text = Z_Malloc(len, PU_STATIC, 0); memcpy(tex->text, str, len); } void FI_ObjectThink(fiobj_t* obj) { FI_ValueThink(&obj->x); FI_ValueThink(&obj->y); FI_ValueArrayThink(obj->scale, 2); FI_ValueArrayThink(obj->color, 4); FI_ValueThink(&obj->angle); } void FI_Ticker(void) { int i, k, last = 0; fipic_t* pic; fitext_t* tex; if(!fiActive) return; if(fi->mode == FIMODE_OVERLAY) { // Has the game mode changed? if(fi->overlayGameState != G_GetGameState()) { // Overlay scripts don't survive this... FI_End(); return; } } fi->timer++; // Interpolateable values. FI_ValueArrayThink(fi->bgColor, 4); FI_ValueArrayThink(fi->imgOffset, 2); FI_ValueArrayThink(fi->filter, 4); for(i = 0; i < 9; ++i) FI_ValueArrayThink(fi->textColor[i], 3); for(i = 0, pic = fi->pics; i < MAX_PICS; ++i, pic++) { if(!pic->object.used) continue; FI_ObjectThink(&pic->object); FI_ValueArrayThink(pic->otherColor, 4); FI_ValueArrayThink(pic->edgeColor, 4); FI_ValueArrayThink(pic->otherEdgeColor, 4); // If animating, decrease the sequence timer. if(pic->seqWait[pic->seq]) { if(--pic->seqTimer <= 0) { // Advance the sequence position. k = next pos. k = pic->seq + 1; if(k == MAX_SEQUENCE || pic->lump[k] == FI_REPEAT) { // Rewind back to beginning. k = 0; pic->flags.done = true; } else if(pic->lump[k] <= 0) { // This is the end. Stop sequence. pic->seqWait[k = pic->seq] = 0; pic->flags.done = true; } // Advance to the next pos. pic->seq = k; pic->seqTimer = pic->seqWait[k]; // Play a sound? if(pic->sound[k] > 0) S_LocalSound(pic->sound[k], NULL); } } } // Text objects. for(i = 0, tex = fi->text; i < MAX_TEXT; ++i, tex++) { if(!tex->object.used) continue; FI_ObjectThink(&tex->object); if(tex->wait) { if(--tex->timer <= 0) { tex->timer = tex->wait; tex->pos++; } } if(tex->scrollWait) { if(--tex->scrollTimer <= 0) { tex->scrollTimer = tex->scrollWait; tex->object.y.target -= 1; tex->object.y.steps = tex->scrollWait; } } // Is the text object fully visible? tex->flags.all_visible = (!tex->wait || tex->pos >= FI_TextObjectLength(tex)); } // If we're waiting, don't execute any commands. if(fi->wait && --fi->wait) return; // If we're paused we can't really do anything. if(fi->paused) return; // If we're waiting for a text to finish typing, do nothing. if(fi->waitingText) { if(!fi->waitingText->flags.all_visible) return; fi->waitingText = NULL; } // Waiting for an animation to reach its end? if(fi->waitingPic) { if(!fi->waitingPic->flags.done) return; fi->waitingPic = NULL; } // Execute commands until a wait time is set or we reach the end of // the script. If the end is reached, the finale really ends (FI_End). while(fiActive && !fi->wait && !fi->waitingText && !fi->waitingPic && !last) last = !FI_ExecuteNextCommand(); // The script has ended! if(last) FI_End(); } void FI_SkipTo(const char* marker) { memset(fi->gotoTarget, 0, sizeof(fi->gotoTarget)); strncpy(fi->gotoTarget, marker, sizeof(fi->gotoTarget) - 1); // Start skipping until the marker is found. fi->gotoSkip = true; // Stop any waiting. fi->wait = 0; fi->waitingText = NULL; fi->waitingPic = NULL; // Rewind the script so we can jump anywhere. fi->cp = fi->script; } /** * The user has requested a skip. Returns true if the skip was done. */ int FI_SkipRequest(void) { fi->waitingText = NULL; // Stop waiting for things. fi->waitingPic = NULL; if(fi->paused) { // Un-pause. fi->paused = false; fi->wait = 0; return true; } if(fi->canSkip) { // Start skipping ahead. fi->skipping = true; fi->wait = 0; return true; } return fi->eatEvents; } /** * @return @c true, if the event should open the menu. */ boolean FI_IsMenuTrigger(event_t* ev) { if(!fiActive) return false; return fi->showMenu; } int FI_AteEvent(event_t *ev) { // We'll never eat up events. if(ev->state == EVS_UP) return false; return fi->eatEvents; } int FI_Responder(event_t* ev) { int i; if(!fiActive || IS_CLIENT) return false; // During the first ~second disallow all events/skipping. if(fi->timer < 20) return FI_AteEvent(ev); if(ev->type == EV_KEY && ev->state == EVS_DOWN && ev->data1) { // Any handlers for this key event? for(i = 0; i < MAX_HANDLERS; i++) { if(fi->keyHandlers[i].code == ev->data1) { FI_SkipTo(fi->keyHandlers[i].marker); return FI_AteEvent(ev); } } } // If we can't skip, there's no interaction of any kind. if(!fi->canSkip && !fi->paused) return FI_AteEvent(ev); // We are only interested in key/button down presses. if(ev->type != EV_KEY || ev->state != EVS_DOWN) return FI_AteEvent(ev); // We're not interested in the Escape key. if(ev->type == EV_KEY && ev->state == EVS_DOWN && ev->data1 == DDKEY_ESCAPE) return FI_AteEvent(ev); // Servers tell clients to skip. NetSv_Finale(FINF_SKIP, 0, NULL, 0); return FI_SkipRequest(); } int FI_FilterChar(int ch) { // Filter it. if(ch == '_') ch = '['; else if(ch == '\\') ch = '/'; else if(ch < ' ' || ch > 'z') ch = ' '; // We don't have this char. return ch; } int FI_CharWidth(int ch, boolean fontb) { ch = FI_FilterChar(ch); return M_CharWidth(ch, fontb? GF_FONTB : GF_FONTA); } int FI_GetLineWidth(char* text, boolean fontb) { int width = 0; for(; *text; text++) { if(*text == '\\') { if(!*++text) break; if(*text == 'n') break; if(*text >= '0' && *text <= '9') continue; if(*text == 'w' || *text == 'W' || *text == 'p' || *text == 'P') continue; } width += FI_CharWidth(*text, fontb); } return width; } int FI_DrawChar(int x, int y, int ch, boolean fontb) { ch = FI_FilterChar(ch); M_DrawChar(x, y, ch, fontb? GF_FONTB : GF_FONTA); return FI_CharWidth(ch, fontb); } void FI_UseColor(fivalue_t *color, int components) { if(components == 3) { DGL_Color3f(color[0].value, color[1].value, color[2].value); } else if(components == 4) { DGL_Color4f(color[0].value, color[1].value, color[2].value, color[3].value); } } void FI_UseTextColor(fitext_t *tex, int idx) { if(!idx) { // The default color of the text. FI_UseColor(tex->object.color, 4); } else { DGL_Color4f(fi->textColor[idx - 1][0].value, fi->textColor[idx - 1][1].value, fi->textColor[idx - 1][2].value, tex->object.color[3].value); } } /** * @return The length as a counter. */ int FI_TextObjectLength(fitext_t *tex) { int cnt; char *ptr; float secondLen = (tex->wait ? 35.0f / tex->wait : 0); for(cnt = 0, ptr = tex->text; *ptr; ptr++) { if(*ptr == '\\') // Escape? { if(!*++ptr) break; if(*ptr == 'w') cnt += secondLen / 2; if(*ptr == 'W') cnt += secondLen; if(*ptr == 'p') cnt += 5 * secondLen; if(*ptr == 'P') cnt += 10 * secondLen; if((*ptr >= '0' && *ptr <= '9') || *ptr == 'n' || *ptr == 'N') continue; } cnt++; // An actual character. } return cnt; } void FI_Rotate(float angle) { // Counter the VGA aspect ratio. DGL_Scalef(1, 200.0f / 240.0f, 1); DGL_Rotatef(angle, 0, 0, 1); DGL_Scalef(1, 240.0f / 200.0f, 1); } void FI_DrawText(fitext_t *tex) { int cnt, x = 0, y = 0; char *ptr; int linew = -1; int ch; DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(tex->object.x.value, tex->object.y.value, 0); FI_Rotate(tex->object.angle.value); DGL_Scalef(tex->object.scale[0].value, tex->object.scale[1].value, 1); // Set color zero (the normal color). FI_UseTextColor(tex, 0); // Draw it. for(cnt = 0, ptr = tex->text; *ptr && (!tex->wait || cnt < tex->pos); ptr++) { if(linew < 0) linew = FI_GetLineWidth(ptr, tex->flags.font_b); ch = *ptr; if(*ptr == '\\') // Escape? { if(!*++ptr) break; // Change of color. if(*ptr >= '0' && *ptr <= '9') { FI_UseTextColor(tex, *ptr - '0'); continue; } // 'w' = half a second wait, 'W' = second's wait if(*ptr == 'w' || *ptr == 'W') // Wait? { if(tex->wait) cnt += (int) (35.0 / tex->wait / (*ptr == 'w' ? 2 : 1)); continue; } // 'p' = 5 second wait, 'P' = 10 second wait if(*ptr == 'p' || *ptr == 'P') // Longer pause? { if(tex->wait) cnt += (int) (35.0 / tex->wait * (*ptr == 'p' ? 5 : 10)); continue; } if(*ptr == 'n' || *ptr == 'N') // Newline? { x = 0; y += tex->lineheight; linew = -1; cnt++; // Include newlines in the wait count. continue; } if(*ptr == '_') ch = ' '; } // Let's do Y-clipping (in case of tall text blocks). if(tex->object.scale[1].value * y + tex->object.y.value >= -tex->object.scale[1].value * tex->lineheight && tex->object.scale[1].value * y + tex->object.y.value < 200) { x += FI_DrawChar(tex->flags.centered ? x - linew / 2 : x, y, ch, tex->flags.font_b); } cnt++; // Actual character drawn. } DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } void FI_GetTurnCenter(fipic_t *pic, float *center) { if(pic->flags.is_rect) { center[VX] = center[VY] = .5f; } else if(pic->flags.is_patch) { patchinfo_t info; if(R_GetPatchInfo(pic->lump[pic->seq], &info)) { center[VX] = info.width / 2 - info.offset; center[VY] = info.height / 2 - info.topOffset; } else { center[VX] = center[VY] = 0; } } else { center[VX] = 160; center[VY] = 100; } center[VX] *= pic->object.scale[VX].value; center[VY] *= pic->object.scale[VY].value; } /** * Drawing is the most complex task here. */ void FI_Drawer(void) { int i, sq; float mid[2]; fipic_t *pic; fitext_t *tex; // Don't draw anything until we are sure the script has started. if(!fiActive || !fiCmdExecuted) return; // Draw the background. if(fi->bgMaterial) { FI_UseColor(fi->bgColor, 4); DGL_SetMaterial(fi->bgMaterial); DGL_DrawRectTiled(0, 0, 320, 200, 64, 64); } else { // Just clear the screen, then. DGL_Disable(DGL_TEXTURING); DGL_DrawRect(0, 0, 320, 200, fi->bgColor[0].value, fi->bgColor[1].value, fi->bgColor[2].value, fi->bgColor[3].value); DGL_Enable(DGL_TEXTURING); } // Draw images. for(i = 0, pic = fi->pics; i < MAX_PICS; i++, pic++) { // Fully transparent pics will not be drawn. if(!pic->object.used || pic->object.color[3].value == 0) continue; sq = pic->seq; DGL_SetNoMaterial(); // Hmm... FI_UseColor(pic->object.color, 4); FI_GetTurnCenter(pic, mid); // Setup the transformation. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(pic->object.x.value - fi->imgOffset[0].value, pic->object.y.value - fi->imgOffset[1].value, 0); DGL_Translatef(mid[VX], mid[VY], 0); FI_Rotate(pic->object.angle.value); // Move to origin. DGL_Translatef(-mid[VX], -mid[VY], 0); DGL_Scalef((pic->flip[sq] ? -1 : 1) * pic->object.scale[0].value, pic->object.scale[1].value, 1); // Draw it. if(pic->flags.is_rect) { if(pic->flags.is_ximage) { DGL_Enable(DGL_TEXTURING); DGL_Bind(pic->lump[sq]); } else { // The fill. DGL_Disable(DGL_TEXTURING); } DGL_Begin(DGL_QUADS); { FI_UseColor(pic->object.color, 4); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(0, 0); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(1, 0); FI_UseColor(pic->otherColor, 4); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(1, 1); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(0, 1); } DGL_End(); // The edges never have a texture. DGL_Disable(DGL_TEXTURING); DGL_Begin(DGL_LINES); { FI_UseColor(pic->edgeColor, 4); DGL_Vertex2f(0, 0); DGL_Vertex2f(1, 0); DGL_Vertex2f(1, 0); FI_UseColor(pic->otherEdgeColor, 4); DGL_Vertex2f(1, 1); DGL_Vertex2f(1, 1); DGL_Vertex2f(0, 1); DGL_Vertex2f(0, 1); FI_UseColor(pic->edgeColor, 4); DGL_Vertex2f(0, 0); } DGL_End(); DGL_Enable(DGL_TEXTURING); } else if(pic->flags.is_patch) { GL_DrawPatch_CS(0, 0, pic->lump[sq]); } else { //// \fixme The raw screen drawer should not ignore rotation. //// It should allow the caller to set up a transformation matrix. GL_DrawRawScreen_CS(pic->lump[sq], pic->object.x.value - fi->imgOffset[0].value, pic->object.y.value - fi->imgOffset[1].value, (pic->flip[sq] ? -1 : 1) * pic->object.scale[0].value, pic->object.scale[1].value); } // Restore original transformation. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } // Draw text. for(i = 0, tex = fi->text; i < MAX_TEXT; i++, tex++) { if(!tex->object.used || !tex->text) continue; FI_DrawText(tex); } // Filter on top of everything. if(fi->filter[3].value > 0) { // Only draw if necessary. DGL_Disable(DGL_TEXTURING); FI_UseColor(fi->filter, 4); DGL_Begin(DGL_QUADS); DGL_Vertex2f(0, 0); DGL_Vertex2f(320, 0); DGL_Vertex2f(320, 200); DGL_Vertex2f(0, 200); DGL_End(); DGL_Enable(DGL_TEXTURING); } } /** * Command functions can only call FI_GetToken once for each operand. * Otherwise the script cursor ends up in the wrong place. */ void FIC_Do(void) { // This command is called even when (cond)skipping. if(fi->skipNext) { // A conditional skip has been issued. // We'll go into DO-skipping mode. skipnext won't be cleared // until the matching semicolon is found. fi->doLevel++; } } void FIC_End(void) { fi->wait = 1; FI_End(); } void FIC_BGFlat(void) { fi->bgMaterial = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(FI_GetToken(), MN_FLATS)); } void FIC_BGTexture(void) { fi->bgMaterial = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(FI_GetToken(), MN_TEXTURES)); } void FIC_NoBGMaterial(void) { fi->bgMaterial = NULL; } void FIC_InTime(void) { fi->inTime = FI_GetTics(); } void FIC_Tic(void) { fi->wait = 1; } void FIC_Wait(void) { fi->wait = FI_GetTics(); } void FIC_WaitText(void) { fi->waitingText = FI_GetText(FI_GetToken()); } void FIC_WaitAnim(void) { fi->waitingPic = FI_GetPic(FI_GetToken()); } void FIC_Color(void) { int i; for(i = 0; i < 3; ++i) FI_SetValue(fi->bgColor + i, FI_GetFloat()); } void FIC_ColorAlpha(void) { int i; for(i = 0; i < 4; i++) FI_SetValue(fi->bgColor + i, FI_GetFloat()); } void FIC_Pause(void) { fi->paused = true; fi->wait = 1; } void FIC_CanSkip(void) { fi->canSkip = true; } void FIC_NoSkip(void) { fi->canSkip = false; } void FIC_SkipHere(void) { fi->skipping = false; } void FIC_Events(void) { // Script will eat all input events. fi->eatEvents = true; } void FIC_NoEvents(void) { // Script will pass unprocessed events to other responders. fi->eatEvents = false; } void FIC_OnKey(void) { int code; fihandler_t *handler; // First argument is the key identifier. code = DD_GetKeyCode(FI_GetToken()); // Read the marker name into fiToken. FI_GetToken(); // Find an empty handler. if((handler = FI_GetHandler(code)) != NULL) { handler->code = code; strncpy(handler->marker, fiToken, sizeof(handler->marker) - 1); } } void FIC_UnsetKey(void) { fihandler_t *handler = FI_GetHandler(DD_GetKeyCode(FI_GetToken())); if(handler) { handler->code = 0; memset(handler->marker, 0, sizeof(handler->marker)); } } void FIC_If(void) { boolean val = false; FI_GetToken(); // Let's see if we know this id. if(!stricmp(fiToken, "secret")) { // Secret exit was used? val = fi->conditions[FICOND_SECRET]; } else if(!stricmp(fiToken, "netgame")) { val = IS_NETGAME; } else if(!stricmp(fiToken, "deathmatch")) { val = deathmatch != false; } else if(!stricmp(fiToken, "shareware")) { #if __JDOOM__ val = (gameMode == shareware); #elif __JHERETIC__ val = shareware != false; #else val = false; // Hexen has no shareware. #endif } // Generic game mode string checking. else if(!strnicmp(fiToken, "mode:", 5)) { val = !stricmp(fiToken + 5, (char *) G_GetVariable(DD_GAME_MODE)); } #if __JDOOM__ // Game modes. else if(!stricmp(fiToken, "ultimate")) { val = (gameMode == retail); } else if(!stricmp(fiToken, "commercial")) { val = (gameMode == commercial); } #endif else if(!stricmp(fiToken, "leavehub")) { // Current hub has been completed? val = fi->conditions[FICOND_LEAVEHUB]; } #if __JHEXEN__ // Player classes. else if(!stricmp(fiToken, "fighter")) val = (cfg.playerClass[CONSOLEPLAYER] == PCLASS_FIGHTER); else if(!stricmp(fiToken, "cleric")) val = (cfg.playerClass[CONSOLEPLAYER] == PCLASS_CLERIC); else if(!stricmp(fiToken, "mage")) val = (cfg.playerClass[CONSOLEPLAYER] == PCLASS_MAGE); #endif else { Con_Message("FIC_If: Unknown condition \"%s\".\n", fiToken); } // Skip the next command if the value is false. fi->skipNext = !val; } void FIC_IfNot(void) { // This is the same as "if" but the skip condition is the opposite. FIC_If(); fi->skipNext = !fi->skipNext; } void FIC_Else(void) { // The only time the ELSE condition doesn't skip is immediately // after a skip. fi->skipNext = !fi->lastSkipped; } void FIC_GoTo(void) { FI_SkipTo(FI_GetToken()); } void FIC_Marker(void) { FI_GetToken(); // Does it match the goto string? if(!stricmp(fi->gotoTarget, fiToken)) fi->gotoSkip = false; } void FIC_Delete(void) { fiobj_t* obj = FI_FindObject(FI_GetToken()); if(obj) { obj->used = false; } } void FIC_Image(void) { fipic_t* pic = FI_GetPic(FI_GetToken()); const char* name = FI_GetToken(); FI_ClearAnimation(pic); if((pic->lump[0] = W_CheckNumForName(name)) == -1) Con_Message("FIC_Image: Warning, missing lump \"%s\".\n", name); pic->flags.is_patch = false; pic->flags.is_rect = false; pic->flags.is_ximage = false; } void FIC_ImageAt(void) { fipic_t* pic = FI_GetPic(FI_GetToken()); const char* name; FI_InitValue(&pic->object.x, FI_GetFloat()); FI_InitValue(&pic->object.y, FI_GetFloat()); FI_ClearAnimation(pic); name = FI_GetToken(); if((pic->lump[0] = W_CheckNumForName(name)) == -1) Con_Message("FIC_ImageAt: Warning, missing lump \"%s\".\n", name); pic->flags.is_patch = false; pic->flags.is_rect = false; pic->flags.is_ximage = false; } void FIC_XImage(void) { fipic_t* pic = FI_GetPic(FI_GetToken()); const char* fileName; FI_ClearAnimation(pic); // Load the external resource. fileName = FI_GetToken(); if((pic->lump[0] = GL_LoadGraphics(DDRC_GRAPHICS, fileName, LGM_NORMAL, false, true, 0)) == 0) Con_Message("FIC_XImage: Warning, missing graphic \"%s\".\n", fileName); pic->flags.is_patch = false; pic->flags.is_rect = true; pic->flags.is_ximage = true; } void FIC_Patch(void) { fipic_t* pic = FI_GetPic(FI_GetToken()); const char* name; FI_InitValue(&pic->object.x, FI_GetFloat()); FI_InitValue(&pic->object.y, FI_GetFloat()); FI_ClearAnimation(pic); name = FI_GetToken(); if((pic->lump[0] = W_CheckNumForName(name)) == -1) Con_Message("FIC_Patch: Warning, missing lump \"%s\".\n", name); pic->flags.is_patch = true; pic->flags.is_rect = false; } void FIC_SetPatch(void) { int num; fipic_t* pic = FI_GetPic(FI_GetToken()); const char* name = FI_GetToken(); if((num = W_CheckNumForName(name))!= -1) { pic->lump[0] = num; pic->flags.is_patch = true; pic->flags.is_rect = false; } else { Con_Message("FIC_SetPatch: Warning, missing lump \"%s\".\n", name); } } void FIC_ClearAnim(void) { fipic_t* pic = FI_GetPic(FI_GetToken()); FI_ClearAnimation(pic); } void FIC_Anim(void) { fipic_t *pic = FI_GetPic(FI_GetToken()); int i, lump, time; const char* name = FI_GetToken(); if((lump = W_CheckNumForName(name)) == -1) Con_Message("FIC_Anim: Warning, lump \"%s\" not found.\n", name); time = FI_GetTics(); // Find the next sequence spot. i = FI_GetNextSeq(pic); if(i == MAX_SEQUENCE) { Con_Message("FIC_Anim: Warning, too many frames in anim sequence " "(max %i).\n", MAX_SEQUENCE); return; // Can't do it... } pic->lump[i] = lump; pic->seqWait[i] = time; pic->flags.is_patch = true; pic->flags.done = false; } void FIC_AnimImage(void) { fipic_t *pic = FI_GetPic(FI_GetToken()); int i, lump, time; const char* name = FI_GetToken(); if((lump = W_CheckNumForName(name)) == -1) Con_Message("FIC_AnimImage: Warning, lump \"%s\" not found.\n", name); time = FI_GetTics(); // Find the next sequence spot. i = FI_GetNextSeq(pic); if(i == MAX_SEQUENCE) { Con_Message("FIC_AnimImage: Warning, too many frames in anim sequence " "(max %i).\n", MAX_SEQUENCE); return; // Can't do it... } pic->lump[i] = lump; pic->seqWait[i] = time; pic->flags.is_patch = false; pic->flags.is_rect = false; pic->flags.done = false; } void FIC_Repeat(void) { fipic_t *pic = FI_GetPic(FI_GetToken()); int i = FI_GetNextSeq(pic); if(i == MAX_SEQUENCE) return; pic->lump[i] = FI_REPEAT; } void FIC_StateAnim(void) { fipic_t *pic = FI_GetPic(FI_GetToken()); int i; int s = Def_Get(DD_DEF_STATE, FI_GetToken(), 0); int count = FI_GetInteger(); spriteinfo_t sinf; // Animate N states starting from the given one. pic->flags.is_patch = true; pic->flags.is_rect = false; pic->flags.done = false; for(; count > 0 && s > 0; count--) { state_t *st = &STATES[s]; i = FI_GetNextSeq(pic); if(i == MAX_SEQUENCE) break; // No room! R_GetSpriteInfo(st->sprite, st->frame & 0x7fff, &sinf); pic->lump[i] = sinf.realLump; pic->flip[i] = sinf.flip; pic->seqWait[i] = st->tics; if(pic->seqWait[i] == 0) pic->seqWait[i] = 1; // Go to the next state. s = st->nextState; } } void FIC_PicSound(void) { fipic_t *pic = FI_GetPic(FI_GetToken()); int i; i = FI_GetNextSeq(pic) - 1; if(i < 0) i = 0; pic->sound[i] = Def_Get(DD_DEF_SOUND, FI_GetToken(), 0); } void FIC_ObjectOffX(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); float value = FI_GetFloat(); if(obj) { FI_SetValue(&obj->x, value); } } void FIC_ObjectOffY(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); float value = FI_GetFloat(); if(obj) { FI_SetValue(&obj->y, value); } } void FIC_ObjectRGB(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); fipic_t *pic = FI_FindPic(obj ? obj->handle : NULL); int i; for(i = 0; i < 3; ++i) { if(obj) { float value = FI_GetFloat(); FI_SetValue(obj->color + i, value); if(pic && pic->flags.is_rect) { // This affects all the colors. FI_SetValue(pic->otherColor + i, value); FI_SetValue(pic->edgeColor + i, value); FI_SetValue(pic->otherEdgeColor + i, value); } } else { FI_GetFloat(); } } } void FIC_ObjectAlpha(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); fipic_t *pic = FI_FindPic(obj ? obj->handle : NULL); float value = FI_GetFloat(); if(obj) { FI_SetValue(obj->color + 3, value); if(pic && pic->flags.is_rect) { FI_SetValue(pic->otherColor + 3, value); /*FI_SetValue(pic->edgeColor + 3, value); FI_SetValue(pic->otherEdgeColor + 3, value); */ } } } void FIC_ObjectScaleX(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); float value = FI_GetFloat(); if(obj) { FI_SetValue(&obj->scale[0], value); } } void FIC_ObjectScaleY(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); float value = FI_GetFloat(); if(obj) { FI_SetValue(&obj->scale[1], value); } } void FIC_ObjectScale(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); float value = FI_GetFloat(); if(obj) { FI_SetValue(&obj->scale[0], value); FI_SetValue(&obj->scale[1], value); } } void FIC_ObjectScaleXY(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); float x = FI_GetFloat(); float y = FI_GetFloat(); if(obj) { FI_SetValue(&obj->scale[0], x); FI_SetValue(&obj->scale[1], y); } } void FIC_ObjectAngle(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); float value = FI_GetFloat(); if(obj) { FI_SetValue(&obj->angle, value); } } void FIC_Rect(void) { fipic_t *pic = FI_GetPic(FI_GetToken()); FI_InitRect(pic); // Position and size. FI_InitValue(&pic->object.x, FI_GetFloat()); FI_InitValue(&pic->object.y, FI_GetFloat()); FI_InitValue(&pic->object.scale[0], FI_GetFloat()); FI_InitValue(&pic->object.scale[1], FI_GetFloat()); pic->flags.is_rect = true; pic->flags.is_patch = false; pic->flags.is_ximage = false; pic->flags.done = true; } void FIC_FillColor(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); fipic_t *pic; int which = 0; int i; float color; if(!obj) { // Skip the parms. for(i = 0; i < 5; ++i) FI_GetToken(); return; } pic = FI_GetPic(obj->handle); // Which colors to modify? FI_GetToken(); if(!stricmp(fiToken, "top")) which |= 1; else if(!stricmp(fiToken, "bottom")) which |= 2; else which = 3; for(i = 0; i < 4; ++i) { color = FI_GetFloat(); if(which & 1) FI_SetValue(obj->color + i, color); if(which & 2) FI_SetValue(pic->otherColor + i, color); } } void FIC_EdgeColor(void) { fiobj_t *obj = FI_FindObject(FI_GetToken()); fipic_t *pic; int which = 0; int i; float color; if(!obj) { // Skip the parms. for(i = 0; i < 5; ++i) FI_GetToken(); return; } pic = FI_GetPic(obj->handle); // Which colors to modify? FI_GetToken(); if(!stricmp(fiToken, "top")) which |= 1; else if(!stricmp(fiToken, "bottom")) which |= 2; else which = 3; for(i = 0; i < 4; ++i) { color = FI_GetFloat(); if(which & 1) FI_SetValue(pic->edgeColor + i, color); if(which & 2) FI_SetValue(pic->otherEdgeColor + i, color); } } void FIC_OffsetX(void) { FI_SetValue(fi->imgOffset, FI_GetFloat()); } void FIC_OffsetY(void) { FI_SetValue(fi->imgOffset + 1, FI_GetFloat()); } void FIC_Sound(void) { int num = Def_Get(DD_DEF_SOUND, FI_GetToken(), NULL); if(num > 0) S_LocalSound(num, NULL); } void FIC_SoundAt(void) { int num = Def_Get(DD_DEF_SOUND, FI_GetToken(), NULL); float vol = FI_GetFloat(); if(vol > 1) vol = 1; if(vol > 0 && num > 0) S_LocalSoundAtVolume(num, NULL, vol); } void FIC_SeeSound(void) { int num = Def_Get(DD_DEF_MOBJ, FI_GetToken(), NULL); if(num < 0 || MOBJINFO[num].seeSound <= 0) return; S_LocalSound(MOBJINFO[num].seeSound, NULL); } void FIC_DieSound(void) { int num = Def_Get(DD_DEF_MOBJ, FI_GetToken(), NULL); if(num < 0 || MOBJINFO[num].deathSound <= 0) return; S_LocalSound(MOBJINFO[num].deathSound, NULL); } void FIC_Music(void) { S_StartMusic(FI_GetToken(), true); } void FIC_MusicOnce(void) { S_StartMusic(FI_GetToken(), false); } void FIC_Filter(void) { int i; for(i = 0; i < 4; ++i) FI_SetValue(fi->filter + i, FI_GetFloat()); } void FIC_Text(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_InitValue(&tex->object.x, FI_GetFloat()); FI_InitValue(&tex->object.y, FI_GetFloat()); FI_SetText(tex, FI_GetToken()); tex->pos = 0; // Restart the text. } void FIC_TextFromDef(void) { fitext_t *tex = FI_GetText(FI_GetToken()); char *str; FI_InitValue(&tex->object.x, FI_GetFloat()); FI_InitValue(&tex->object.y, FI_GetFloat()); if(!Def_Get(DD_DEF_TEXT, FI_GetToken(), &str)) str = "(undefined)"; // Not found! FI_SetText(tex, str); tex->pos = 0; // Restart the text. } void FIC_TextFromLump(void) { fitext_t *tex = FI_GetText(FI_GetToken()); int lnum; FI_InitValue(&tex->object.x, FI_GetFloat()); FI_InitValue(&tex->object.y, FI_GetFloat()); lnum = W_CheckNumForName(FI_GetToken()); if(lnum < 0) { FI_SetText(tex, "(not found)"); } else { size_t i, incount, buflen; const char* data; char* str, *out; // Load the lump. data = W_CacheLumpNum(lnum, PU_STATIC); incount = W_LumpLength(lnum); str = Z_Malloc(buflen = 2 * incount + 1, PU_STATIC, 0); memset(str, 0, buflen); for(i = 0, out = str; i < incount; ++i) { if(data[i] == '\n') { *out++ = '\\'; *out++ = 'n'; } else { *out++ = data[i]; } } W_ChangeCacheTag(lnum, PU_CACHE); FI_SetText(tex, str); Z_Free(str); } tex->pos = 0; // Restart. } void FIC_SetText(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_SetText(tex, FI_GetToken()); } void FIC_SetTextDef(void) { fitext_t *tex = FI_GetText(FI_GetToken()); char *str; if(!Def_Get(DD_DEF_TEXT, FI_GetToken(), &str)) str = "(undefined)"; // Not found! FI_SetText(tex, str); } void FIC_DeleteText(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->object.used = false; if(tex->text) { // Free the memory allocated for the text string. Z_Free(tex->text); tex->text = NULL; } } void FIC_TextColor(void) { int idx = FI_GetInteger(), c; if(idx < 1) idx = 1; if(idx > 9) idx = 9; for(c = 0; c < 3; ++c) FI_SetValue(&fi->textColor[idx - 1][c], FI_GetFloat()); } void FIC_TextRGB(void) { int i; fitext_t *tex = FI_GetText(FI_GetToken()); for(i = 0; i < 3; ++i) FI_SetValue(&tex->object.color[i], FI_GetFloat()); } void FIC_TextAlpha(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_SetValue(&tex->object.color[3], FI_GetFloat()); } void FIC_TextOffX(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_SetValue(&tex->object.x, FI_GetFloat()); } void FIC_TextOffY(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_SetValue(&tex->object.y, FI_GetFloat()); } void FIC_TextCenter(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->flags.centered = true; } void FIC_TextNoCenter(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->flags.centered = false; } void FIC_TextScroll(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->scrollTimer = 0; tex->scrollWait = FI_GetInteger(); } void FIC_TextPos(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->pos = FI_GetInteger(); } void FIC_TextRate(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->wait = FI_GetInteger(); } void FIC_TextLineHeight(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->lineheight = FI_GetInteger(); } void FIC_FontA(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->flags.font_b = false; // Set line height to font A. #if __JDOOM__ tex->lineheight = 11; #else tex->lineheight = 9; #endif } void FIC_FontB(void) { fitext_t *tex = FI_GetText(FI_GetToken()); tex->flags.font_b = true; #if __JDOOM__ tex->lineheight = 15; #else tex->lineheight = 20; #endif } void FIC_NoMusic(void) { // Stop the currently playing song. S_StopMusic(); } void FIC_TextScaleX(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_SetValue(&tex->object.scale[0], FI_GetFloat()); } void FIC_TextScaleY(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_SetValue(&tex->object.scale[1], FI_GetFloat()); } void FIC_TextScale(void) { fitext_t *tex = FI_GetText(FI_GetToken()); FI_SetValue(&tex->object.scale[0], FI_GetFloat()); FI_SetValue(&tex->object.scale[1], FI_GetFloat()); } void FIC_PlayDemo(void) { // Mark the current state as suspended, so we know to resume it when // the demo ends. fi->suspended = true; fiActive = false; // The only argument is the demo file name. // Start playing the demo. if(!DD_Executef(true, "playdemo \"%s\"", FI_GetToken())) { // Demo playback failed. Here we go again... FI_DemoEnds(); } } void FIC_Command(void) { DD_Executef(false, FI_GetToken()); } void FIC_ShowMenu(void) { fi->showMenu = true; } void FIC_NoShowMenu(void) { fi->showMenu = false; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/x_hair.c0000644000175000017500000001376311357170242022255 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_hair.c: Crosshairs, drawing and config. * * \todo Use the vector graphic routines currently in the automap here. */ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "x_hair.h" #include "p_user.h" // MACROS ------------------------------------------------------------------ #define MAX_XLINES 16 // TYPES ------------------------------------------------------------------- typedef struct crosspoint_s { float x, y; } crosspoint_t; typedef struct crossline_s { crosspoint_t a, b; } crossline_t; typedef struct cross_s { int numLines; crossline_t lines[MAX_XLINES]; } cross_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- #define XL(x1,y1,x2,y2) {{x1,y1},{x2,y2}} cross_t crosshairs[NUM_XHAIRS] = { // + (open center) {4, {XL(-1, 0, -.4f, 0), XL(0, -1, 0, -.4f), XL(1, 0, .4f, 0), XL(0, 1, 0, .4f)}}, // > < {4, {XL(-1, -.714f, -.286f, 0), XL(-1, .714f, -.286f, 0), XL(1, -.714f, .286f, 0), XL(1, .714f, .286f, 0)}}, // square {4, {XL(-1, -1, -1, 1), XL(-1, 1, 1, 1), XL(1, 1, 1, -1), XL(1, -1, -1, -1)}}, // square (open center) {8, {XL(-1, -1, -1, -.5f), XL(-1, .5f, -1, 1), XL(-1, 1, -.5f, 1), XL(.5f, 1, 1, 1), XL(1, 1, 1, .5f), XL(1, -.5f, 1, -1), XL(1, -1, .5f, -1), XL(-.5f, -1, -1, -1)}}, // diamond {4, {XL(0, -1, 1, 0), XL(1, 0, 0, 1), XL(0, 1, -1, 0), XL(-1, 0, 0, -1)}}, // ^ {2, {XL(-1, -1, 0, 0), XL(0, 0, 1, -1)}} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CVARs for the crosshair cvar_t xhairCVars[] = { {"view-cross-type", 0, CVT_INT, &cfg.xhair, 0, NUM_XHAIRS}, {"view-cross-size", 0, CVT_FLOAT, &cfg.xhairSize, 0, 1}, {"view-cross-vitality", 0, CVT_BYTE, &cfg.xhairVitality, 0, 1}, {"view-cross-r", 0, CVT_FLOAT, &cfg.xhairColor[0], 0, 1}, {"view-cross-g", 0, CVT_FLOAT, &cfg.xhairColor[1], 0, 1}, {"view-cross-b", 0, CVT_FLOAT, &cfg.xhairColor[2], 0, 1}, {"view-cross-a", 0, CVT_FLOAT, &cfg.xhairColor[3], 0, 1}, {NULL} }; // CODE -------------------------------------------------------------------- /** * Register CVARs and CCmds for the crosshair. */ void X_Register(void) { int i; for(i = 0; xhairCVars[i].name; ++i) Con_AddVariable(xhairCVars + i); } void X_Drawer(int player) { #define XHAIR_LINE_WIDTH 1.f int i, xhair = MINMAX_OF(0, cfg.xhair, NUM_XHAIRS), centerX, centerY; float alpha, scale, oldLineWidth; ddplayer_t* plr = players[player].plr; cross_t* cross; alpha = MINMAX_OF(0, cfg.xhairColor[3], 1); // Is there a crosshair to draw? if(xhair == 0 || !(alpha > 0)) return; scale = .125f + MINMAX_OF(0, cfg.xhairSize, 1) * .125f * 80; centerX = Get(DD_VIEWWINDOW_X) + (Get(DD_VIEWWINDOW_WIDTH) / 2); centerY = Get(DD_VIEWWINDOW_Y) + (Get(DD_VIEWWINDOW_HEIGHT) / 2); DGL_MatrixMode(DGL_PROJECTION); DGL_PushMatrix(); DGL_LoadIdentity(); DGL_Ortho(0, 0, 320, 200, -1, 1); DGL_Translatef(centerX, centerY, 0); DGL_Scalef(scale, scale, 1); cross = &crosshairs[xhair - 1]; if(cfg.xhairVitality) { // Color the crosshair according to how close the player is to death. #define HUE_DEAD 0.f #define HUE_LIVE .3f float vitalColor[4]; R_HSVToRGB(vitalColor, HUE_DEAD + (HUE_LIVE - HUE_DEAD) * MINMAX_OF(0, (float) plr->mo->health / maxHealth, 1), 1, 1); vitalColor[3] = alpha; DGL_Color4fv(vitalColor); #undef HUE_DEAD #undef HUE_LIVE } else { float color[4]; color[0] = MINMAX_OF(0, cfg.xhairColor[0], 1); color[1] = MINMAX_OF(0, cfg.xhairColor[1], 1); color[2] = MINMAX_OF(0, cfg.xhairColor[2], 1); color[3] = alpha; DGL_Color4fv(color); } oldLineWidth = DGL_GetFloat(DGL_LINE_WIDTH); DGL_SetFloat(DGL_LINE_WIDTH, XHAIR_LINE_WIDTH); DGL_Disable(DGL_TEXTURING); DGL_Begin(DGL_LINES); for(i = 0; i < cross->numLines; ++i) { crossline_t* xline = &cross->lines[i]; DGL_Vertex2f(xline->a.x, xline->a.y); DGL_Vertex2f(xline->b.x, xline->b.y); } DGL_End(); // Restore the previous state. DGL_SetFloat(DGL_LINE_WIDTH, oldLineWidth); DGL_Enable(DGL_TEXTURING); DGL_PopMatrix(); #undef XHAIR_LINE_WIDTH } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/d_net.c0000644000175000017500000004726711357170242022102 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_net.c : Common code related to net games. * * Connecting to/from a netgame server. * Netgame events (player and world) and netgame commands. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "g_common.h" #include "d_net.h" #include "p_player.h" #include "hu_menu.h" #include "p_start.h" // MACROS ------------------------------------------------------------------ // TYPES -------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdSetColor); DEFCC(CCmdSetMap); #if __JHEXEN__ DEFCC(CCmdSetClass); #endif // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void D_NetMessageEx(int player, const char* msg, boolean playSound); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern int netSvAllowSendMsg; // PUBLIC DATA DEFINITIONS ------------------------------------------------- char msgBuff[NETBUFFER_MAXMESSAGE]; float netJumpPower = 9; // Net code related console commands ccmd_t netCCmds[] = { {"setcolor", "i", CCmdSetColor}, #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ {"setmap", "ii", CCmdSetMap}, #else {"setmap", "i", CCmdSetMap}, #endif #if __JHEXEN__ {"setclass", "i", CCmdSetClass, CMDF_NO_DEDICATED}, #endif {"startcycle", "", CCmdMapCycle}, {"endcycle", "", CCmdMapCycle}, {NULL} }; // Net code related console variables cvar_t netCVars[] = { {"MapCycle", CVF_HIDE | CVF_NO_ARCHIVE, CVT_CHARPTR, &mapCycle}, {"server-game-mapcycle", 0, CVT_CHARPTR, &mapCycle}, {"server-game-mapcycle-noexit", 0, CVT_BYTE, &mapCycleNoExit, 0, 1}, {"server-game-cheat", 0, CVT_INT, &netSvAllowCheats, 0, 1}, {NULL} }; // PRIVATE DATA ------------------------------------------------------------- // CODE --------------------------------------------------------------------- /** * Register the console commands and variables of the common netcode. */ void D_NetConsoleRegistration(void) { int i; for(i = 0; netCCmds[i].name; ++i) Con_AddCommand(netCCmds + i); for(i = 0; netCVars[i].name; ++i) Con_AddVariable(netCVars + i); } /** * Called when the network server starts. * * Duties include: * Updating global state variables and initializing all players' settings */ int D_NetServerStarted(int before) { uint netMap, netEpisode; if(before) return true; G_StopDemo(); // We're the server, so... cfg.playerColor[0] = PLR_COLOR(0, cfg.netColor); #if __JHEXEN__ cfg.playerClass[0] = cfg.netClass; #elif __JHERETIC__ cfg.playerClass[0] = PCLASS_PLAYER; #endif // Set the game parameters. deathmatch = cfg.netDeathmatch; noMonstersParm = cfg.netNoMonsters; cfg.jumpEnabled = cfg.netJumping; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ respawnMonsters = cfg.netRespawn; #endif #if __JHEXEN__ randomClassParm = cfg.netRandomClass; #endif // Hexen has translated map numbers. #if __JHEXEN__ netMap = P_TranslateMap(cfg.netMap); #else netMap = cfg.netMap; #endif #if __JDOOM64__ netEpisode = 0; #else netEpisode = cfg.netEpisode; #endif G_InitNew(cfg.netSkill, netEpisode, netMap); // Close the menu, the game begins!! Hu_MenuCommand(MCMD_CLOSE); return true; } /** * Called when a network server closes. * * Duties include: * Restoring global state variables */ int D_NetServerClose(int before) { if(!before) { // Restore normal game state. deathmatch = false; noMonstersParm = false; #if __JHEXEN__ randomClassParm = false; #endif D_NetMessage(CONSOLEPLAYER, "NETGAME ENDS"); } return true; } int D_NetConnect(int before) { // We do nothing before the actual connection is made. if(before) return true; // After connecting we tell the server a bit about ourselves. NetCl_SendPlayerInfo(); // Close the menu, the game begins!! // advancedemo = false; Hu_MenuCommand(MCMD_CLOSE); return true; } int D_NetDisconnect(int before) { if(before) return true; // Restore normal game state. deathmatch = false; noMonstersParm = false; #if __JHEXEN__ randomClassParm = false; #endif // Start demo. G_StartTitle(); return true; } void* D_NetWriteCommands(int numCommands, void* data) { // It's time to send ticcmds to the server. // 'plrNumber' contains the number of commands. return NetCl_WriteCommands(data, numCommands); } void* D_NetReadCommands(size_t pktLength, void* data) { // Read ticcmds sent by a client. // 'plrNumber' is the length of the packet. return NetSv_ReadCommands(data, pktLength); } long int D_NetPlayerEvent(int plrNumber, int peType, void *data) { // If this isn't a netgame, we won't react. if(!IS_NETGAME) return true; if(peType == DDPE_ARRIVAL) { boolean showmsg = true; if(IS_SERVER) { NetSv_NewPlayerEnters(plrNumber); } else if(plrNumber == CONSOLEPLAYER) { // We have arrived, the game should be begun. Con_Message("PE: (client) arrived in netgame.\n"); G_ChangeGameState(GS_WAITING); showmsg = false; } else { // Client responds to new player? Con_Message("PE: (client) player %i has arrived.\n", plrNumber); G_DoReborn(plrNumber); //players[plrNumber].playerstate = PST_REBORN; } if(showmsg) { // Print a notification. dd_snprintf(msgBuff, NETBUFFER_MAXMESSAGE, "%s joined the game", Net_GetPlayerName(plrNumber)); D_NetMessage(CONSOLEPLAYER, msgBuff); } } else if(peType == DDPE_EXIT) { Con_Message("PE: player %i has left.\n", plrNumber); players[plrNumber].playerState = PST_GONE; // Print a notification. dd_snprintf(msgBuff, NETBUFFER_MAXMESSAGE, "%s left the game", Net_GetPlayerName(plrNumber)); D_NetMessage(CONSOLEPLAYER, msgBuff); if(IS_SERVER) P_DealPlayerStarts(0); } // DDPE_CHAT_MESSAGE occurs when a PKT_CHAT is received. // Here we will only display the message (if not a local message). else if(peType == DDPE_CHAT_MESSAGE && plrNumber != CONSOLEPLAYER) { int i, num, oldecho = cfg.echoMsg; // Count the number of players. for(i = num = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) num++; dd_snprintf(msgBuff, NETBUFFER_MAXMESSAGE, "%s: %s", Net_GetPlayerName(plrNumber), (const char *) data); // The chat message is already echoed by the console. cfg.echoMsg = false; D_NetMessageEx(CONSOLEPLAYER, msgBuff, (cfg.chatBeep? true : false)); cfg.echoMsg = oldecho; } return true; } int D_NetWorldEvent(int type, int parm, void *data) { int i; switch (type) { // // Server events: // case DDWE_HANDSHAKE: { boolean newPlayer = *((boolean*) data); // A new player is entering the game. We as a server should send him // the handshake packet(s) to update his world. // If 'data' is zero, this is a re-handshake that's used to // begin demos. Con_Message("D_NetWorldEvent: Sending a %shandshake to player %i.\n", newPlayer ? "" : "(re)", parm); // Mark new player for update. players[parm].update |= PSF_REBORN; // First, the game state. NetSv_SendGameState(GSF_CHANGE_MAP | GSF_CAMERA_INIT | (newPlayer ? 0 : GSF_DEMO), parm); // Send info about all players to the new one. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame && i != parm) NetSv_SendPlayerInfo(i, parm); // Send info about our jump power. NetSv_SendJumpPower(parm, cfg.jumpEnabled ? cfg.jumpPower : 0); NetSv_Paused(paused); break; } // // Client events: // #if 0 case DDWE_PROJECTILE: # ifdef _DEBUG if(parm > 32) // Too many? gi.Error("D_NetWorldEvent: Too many missiles (%i).\n", parm); # endif // Projectile data consists of shorts. for(ptr = *(short **) data, i = 0; i < parm; ++i) { flags = *(unsigned short *) ptr & DDMS_FLAG_MASK; mtype = *(unsigned short *) ptr & ~DDMS_FLAG_MASK; ptr++; x = *ptr++ << 16; y = *ptr++ << 16; z = *ptr++ << 16; momx = momy = momz = 0; if(flags & DDMS_MOVEMENT_XY) { momx = *ptr++ << 8; momy = *ptr++ << 8; } if(flags & DDMS_MOVEMENT_Z) { momz = *ptr++ << 8; } NetCl_SpawnMissile(mtype, x, y, z, momx, momy, momz); } // Update pointer. *(short **) data = ptr; break; #endif case DDWE_SECTOR_SOUND: // High word: sector number, low word: sound id. if(parm & 0xffff) S_StartSound(parm & 0xffff, (mobj_t *) P_GetPtr(DMU_SECTOR, parm >> 16, DMU_SOUND_ORIGIN)); else S_StopSound(0, (mobj_t *) P_GetPtr(DMU_SECTOR, parm >> 16, DMU_SOUND_ORIGIN)); break; case DDWE_DEMO_END: // Demo playback has ended. Advance demo sequence. if(parm) // Playback was aborted. G_DemoAborted(); else // Playback ended normally. G_DemoEnds(); // Restore normal game state. deathmatch = false; noMonstersParm = false; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ respawnMonsters = false; #endif #if __JHEXEN__ randomClassParm = false; #endif break; default: return false; } return true; } void D_HandlePacket(int fromplayer, int type, void *data, size_t length) { byte *bData = data; // // Server events. // if(IS_SERVER) { switch (type) { case GPT_PLAYER_INFO: // A player has changed color or other settings. NetSv_ChangePlayerInfo(fromplayer, data); break; case GPT_CHEAT_REQUEST: NetSv_DoCheat(fromplayer, data); break; case GPT_ACTION_REQUEST: NetSv_DoAction(fromplayer, data); break; } return; } // // Client events. // switch (type) { case GPT_GAME_STATE: Con_Printf("Received GTP_GAME_STATE\n"); NetCl_UpdateGameState(data); // Tell the engine we're ready to proceed. It'll start handling // the world updates after this variable is set. Set(DD_GAME_READY, true); break; case GPT_MESSAGE: dd_snprintf(msgBuff, NETBUFFER_MAXMESSAGE, "%s", (char*) data); P_SetMessage(&players[CONSOLEPLAYER], msgBuff, false); break; #if __JHEXEN__ || __JSTRIFE__ case GPT_YELLOW_MESSAGE: dd_snprintf(msgBuff, NETBUFFER_MAXMESSAGE, "%s", (char*) data); P_SetYellowMessage(&players[CONSOLEPLAYER], msgBuff, false); break; #endif case GPT_CONSOLEPLAYER_STATE: NetCl_UpdatePlayerState(data, CONSOLEPLAYER); break; case GPT_CONSOLEPLAYER_STATE2: NetCl_UpdatePlayerState2(data, CONSOLEPLAYER); break; case GPT_PLAYER_STATE: NetCl_UpdatePlayerState(bData + 1, bData[0]); break; case GPT_PLAYER_STATE2: NetCl_UpdatePlayerState2(bData + 1, bData[0]); break; case GPT_PSPRITE_STATE: NetCl_UpdatePSpriteState(data); break; case GPT_INTERMISSION: NetCl_Intermission(data); break; case GPT_FINALE: case GPT_FINALE2: NetCl_Finale(type, data); break; case GPT_PLAYER_INFO: NetCl_UpdatePlayerInfo(data); break; #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ case GPT_CLASS: players[CONSOLEPLAYER].class = bData[0]; break; #endif case GPT_SAVE: NetCl_SaveGame(data); break; case GPT_LOAD: NetCl_LoadGame(data); break; case GPT_PAUSE: NetCl_Paused(bData[0]); break; case GPT_JUMP_POWER: NetCl_UpdateJumpPower(data); break; default: Con_Message("H_HandlePacket: Received unknown packet, " "type=%i.\n", type); } } /** * Plays a (local) chat sound. */ void D_ChatSound(void) { #if __JHEXEN__ S_LocalSound(SFX_CHAT, NULL); #elif __JSTRIFE__ S_LocalSound(SFX_CHAT, NULL); #elif __JHERETIC__ S_LocalSound(SFX_CHAT, NULL); #else # if __JDOOM__ if(gameMode == commercial) S_LocalSound(SFX_RADIO, NULL); else # endif S_LocalSound(SFX_TINK, NULL); #endif } /** * Show a message on screen, optionally accompanied by Chat sound effect. * * @param player Player number to send the message to. * @param playSound @c true = play the chat sound. */ static void D_NetMessageEx(int player, const char* msg, boolean playSound) { player_t* plr; if(player < 0 || player > MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; dd_snprintf(msgBuff, NETBUFFER_MAXMESSAGE, "%s", msg); // This is intended to be a local message. // Let's make sure P_SetMessage doesn't forward it anywhere. netSvAllowSendMsg = false; P_SetMessage(plr, msgBuff, false); if(playSound) D_ChatSound(); netSvAllowSendMsg = true; } /** * Show message on screen and play chat sound. * * @param msg Ptr to the message to print. */ void D_NetMessage(int player, const char* msg) { D_NetMessageEx(player, msg, true); } /** * Show message on screen. * * @param msg */ void D_NetMessageNoSound(int player, const char* msg) { D_NetMessageEx(player, msg, false); } /** * Issues a damage request when a client is trying to damage another player's * mobj. * * @return @c true = no further processing of the damage * should be done else, process the damage as * normally. */ boolean D_NetDamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage) { if(!source || !source->player) { return false; } if(IS_SERVER && source->player - players > 0) { // A client is trying to do damage. #if _DEBUG Con_Message("P_DamageMobj2: Server ignores client's damage on svside.\n"); #endif //// \todo Damage requests have not been fully implemented yet. return false; //return true; } else if(IS_CLIENT && source->player - players == CONSOLEPLAYER) { #if _DEBUG Con_Message("P_DamageMobj2: Client should request damage on mobj %p.\n", target); #endif return true; } #if _DEBUG Con_Message("P_DamageMobj2: Allowing normal damage in netgame.\n"); #endif // Process as normal damage. return false; } /** * Console command to change the players' colors. */ DEFCC(CCmdSetColor) { #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ int numColors = 4; #endif cfg.netColor = atoi(argv[1]); if(IS_SERVER) // A local player? { int player = CONSOLEPLAYER; if(IS_DEDICATED) return false; // Server players, must be treated as a special case because this is // a local mobj we're dealing with. We'll change the color translation // bits directly. cfg.playerColor[player] = PLR_COLOR(player, cfg.netColor); // Change the color of the mobj (translation flags). players[player].plr->mo->flags &= ~MF_TRANSLATION; #if __JHEXEN__ // Additional difficulty is caused by the fact that the Fighter's // colors 0 (blue) and 2 (yellow) must be swapped. players[player].plr->mo->flags |= (cfg.playerClass[player] == PCLASS_FIGHTER ? (cfg.playerColor[player] == 0 ? 2 : cfg.playerColor[player] == 2 ? 0 : cfg.playerColor[player]) : cfg. playerColor[player]) << MF_TRANSSHIFT; players[player].colorMap = cfg.playerColor[player]; #else players[player].plr->mo->flags |= cfg.playerColor[player] << MF_TRANSSHIFT; #endif // Tell the clients about the change. NetSv_SendPlayerInfo(player, DDSP_ALL_PLAYERS); } else { // Tell the server about the change. NetCl_SendPlayerInfo(); } return true; } /** * Console command to change the players' class. */ #if __JHEXEN__ DEFCC(CCmdSetClass) { playerclass_t newClass = atoi(argv[1]); if(!(newClass < NUM_PLAYER_CLASSES)) return false; if(!PCLASS_INFO(newClass)->userSelectable) return false; cfg.netClass = newClass; if(IS_CLIENT) { // Tell the server that we've changed our class. NetCl_SendPlayerInfo(); } else { P_PlayerChangeClass(&players[CONSOLEPLAYER], cfg.netClass); } return true; } #endif /** * Console command to change the current map. */ DEFCC(CCmdSetMap) { uint ep, map; // Only the server can change the map. if(!IS_SERVER) return false; #if __JDOOM__ || __JHERETIC__ if(argc != 3) { Con_Printf("Usage: %s (episode) (map)\n", argv[0]); return true; } #else if(argc != 2) { Con_Printf("Usage: %s (map)\n", argv[0]); return true; } #endif // Update game mode. deathmatch = cfg.netDeathmatch; noMonstersParm = cfg.netNoMonsters; #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ respawnMonsters = cfg.netRespawn; #endif #if __JHEXEN__ randomClassParm = cfg.netRandomClass; #endif cfg.jumpEnabled = cfg.netJumping; #if __JDOOM__ || __JHERETIC__ ep = atoi(argv[1]); if(ep != 0) ep -= 1; #else ep = 0; #endif #if __JDOOM__ || __JHERETIC__ map = atoi(argv[2]); if(map != 0) map -= 1; #else map = atoi(argv[1]); if(map != 0) map -= 1; #endif #if __JHEXEN__ map = P_TranslateMap(map); #endif // Use the configured network skill level for the new map. G_DeferedInitNew(cfg.netSkill, ep, map); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/hu_lib.c0000644000175000017500000001060211357170242022232 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_lib.c: Heads-up text and input code. */ // HEADER FILES ------------------------------------------------------------ #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "hu_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void HUlib_init(void) { // Nothing to do... } void HUlib_clearTextLine(hu_textline_t *t) { t->len = 0; t->l[0] = 0; t->needsupdate = true; } void HUlib_initTextLine(hu_textline_t *t, int x, int y) { t->x = x; t->y = y; HUlib_clearTextLine(t); } boolean HUlib_addCharToTextLine(hu_textline_t* t, char ch) { if(t->len == HU_MAXLINELENGTH) return false; t->l[t->len++] = ch; t->l[t->len] = 0; t->needsupdate = 4; return true; } boolean HUlib_delCharFromTextLine(hu_textline_t *t) { if(!t->len) return false; t->l[--t->len] = 0; t->needsupdate = 4; return true; } void HUlib_drawTextLine(hu_textline_t* l, gamefontid_t font, boolean drawcursor) { HUlib_drawTextLine2(l->x, l->y, l->l, l->len, font, drawcursor); } /** * Sorta called by HU_Erase and just better darn get things straight. */ void HUlib_eraseTextLine(hu_textline_t* l) { if(l->needsupdate) l->needsupdate--; } void HUlib_initText(hu_text_t* it, int x, int y, boolean* on) { it->lm = 0; // Default left margin is start of text. it->on = on; it->laston = true; HUlib_initTextLine(&it->l, x, y); } /** * Adheres to the left margin restriction */ void HUlib_delCharFromText(hu_text_t* it) { if(it->l.len != it->lm) HUlib_delCharFromTextLine(&it->l); } void HUlib_eraseLineFromText(hu_text_t* it) { while(it->lm != it->l.len) HUlib_delCharFromTextLine(&it->l); } /** * Resets left margin as well. */ void HUlib_resetText(hu_text_t* it) { it->lm = 0; HUlib_clearTextLine(&it->l); } void HUlib_addPrefixToText(hu_text_t* it, char* str) { while(*str) HUlib_addCharToTextLine(&it->l, *(str++)); it->lm = it->l.len; } /** * Wrapper function for handling general keyed input. * * @return @c true, if it ate the key. */ boolean HUlib_keyInText(hu_text_t* it, unsigned char ch) { if(ch >= ' ' && ch <= 'z') { HUlib_addCharToTextLine(&it->l, (char) ch); return true; } return false; } void HUlib_drawText(hu_text_t* it, gamefontid_t font) { hu_textline_t* l = &it->l; if(!*it->on) return; HUlib_drawTextLine(l, font, true); } void HUlib_eraseText(hu_text_t* it) { if(it->laston && !*it->on) it->l.needsupdate = 4; HUlib_eraseTextLine(&it->l); it->laston = *it->on; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/d_netcl.c0000644000175000017500000006062511357170242022412 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_netcl.c : Common code related to net games (client-side). */ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "am_map.h" #include "p_saveg.h" #include "d_net.h" #include "d_netsv.h" #include "f_infine.h" #include "p_player.h" #include "p_map.h" #include "g_common.h" #include "p_actor.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static byte *readbuffer; // CODE -------------------------------------------------------------------- // Mini-Msg routines. void NetCl_SetReadBuffer(byte *data) { readbuffer = data; } byte NetCl_ReadByte(void) { return *readbuffer++; } short NetCl_ReadShort(void) { readbuffer += 2; return SHORT( *(short *) (readbuffer - 2) ); } int NetCl_ReadLong(void) { readbuffer += 4; return LONG( *(int *) (readbuffer - 4) ); } void NetCl_Read(byte *buf, int len) { memcpy(buf, readbuffer, len); readbuffer += len; } #if __JDOOM__ int NetCl_IsCompatible(int other, int us) { char comp[5][5] = // [other][us] { {1, 1, 0, 1, 0}, {0, 1, 0, 1, 0}, {0, 0, 1, 0, 0}, {0, 0, 0, 1, 0}, {0, 0, 0, 0, 0} }; /* shareware, // DOOM 1 shareware, E1, M9 registered, // DOOM 1 registered, E3, M27 commercial, // DOOM 2 retail, E1 M34 retail, // DOOM 1 retail, E4, M36 */ return comp[other][us]; } #endif void NetCl_UpdateGameState(byte *data) { byte gsGameMode = 0; byte gsFlags = 0; byte gsEpisode = 0; byte gsMap = 0; byte gsDeathmatch = 0; byte gsMonsters = 0; byte gsRespawn = 0; byte gsJumping = 0; byte gsSkill = 0; float gsGravity = 0; gsGameMode = data[0]; gsFlags = data[1]; gsEpisode = data[2]-1; gsMap = data[3]-1; gsDeathmatch = data[4] & 0x3; gsMonsters = (data[4] & 0x4? true : false); gsRespawn = (data[4] & 0x8? true : false); gsJumping = (data[4] & 0x10? true : false); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ gsSkill = (data[4] >> 5); #else gsSkill = data[5] & 0x7; #endif gsGravity = FIX2FLT((data[6] << 8) | (data[7] << 16)); // Demo game state changes are only effective during demo playback. if(gsFlags & GSF_DEMO && !Get(DD_PLAYBACK)) return; #if __JDOOM__ if(!NetCl_IsCompatible(gsGameMode, gameMode)) { // Wrong game mode! This is highly irregular! Con_Message("NetCl_UpdateGameState: Game mode mismatch!\n"); // Stop the demo if one is being played. DD_Execute(false, "stopdemo"); return; } #endif deathmatch = gsDeathmatch; noMonstersParm = !gsMonsters; #if !__JHEXEN__ respawnMonsters = gsRespawn; #endif // Some statistics. #if __JHEXEN__ || __JSTRIFE__ Con_Message("Game state: Map=%u Skill=%i %s\n", gsMap+1, gsSkill, deathmatch == 1 ? "Deathmatch" : deathmatch == 2 ? "Deathmatch2" : "Co-op"); #else Con_Message("Game state: Map=%u Episode=%u Skill=%i %s\n", gsMap+1, gsEpisode+1, gsSkill, deathmatch == 1 ? "Deathmatch" : deathmatch == 2 ? "Deathmatch2" : "Co-op"); #endif #if !__JHEXEN__ Con_Message(" Respawn=%s Monsters=%s Jumping=%s Gravity=%.1f\n", respawnMonsters ? "yes" : "no", !noMonstersParm ? "yes" : "no", gsJumping ? "yes" : "no", gsGravity); #else Con_Message(" Monsters=%s Jumping=%s Gravity=%.1f\n", !noMonstersParm ? "yes" : "no", gsJumping ? "yes" : "no", gsGravity); #endif // Start reading after the GS packet. #if __JHEXEN__ || __JSTRIFE__ NetCl_SetReadBuffer(data + 16); #else NetCl_SetReadBuffer(data + 8); #endif // Do we need to change the map? if(gsFlags & GSF_CHANGE_MAP) { G_InitNew(gsSkill, gsEpisode, gsMap); } else { gameSkill = gsSkill; gameEpisode = gsEpisode; gameMap = gsMap; } // Set gravity. DD_SetVariable(DD_GRAVITY, &gsGravity); // Camera init included? if(gsFlags & GSF_CAMERA_INIT) { player_t *pl = &players[CONSOLEPLAYER]; mobj_t *mo; mo = pl->plr->mo; if(mo) { P_MobjUnsetPosition(mo); mo->pos[VX] = (float) NetCl_ReadShort(); mo->pos[VY] = (float) NetCl_ReadShort(); mo->pos[VZ] = (float) NetCl_ReadShort(); P_MobjSetPosition(mo); mo->angle = NetCl_ReadShort() << 16; /* $unifiedangles */ // Update floorz and ceilingz. #if __JDOOM__ || __JDOOM64__ P_CheckPosition3fv(mo, mo->pos); #else P_CheckPosition2f(mo, mo->pos[VX], mo->pos[VY]); #endif mo->floorZ = tmFloorZ; mo->ceilingZ = tmCeilingZ; } else // mo == NULL { Con_Message("NetCl_UpdateGameState: Got camera init, but player has no mobj.\n"); Con_Message(" Pos=%i,%i,%i Angle=%i\n", NetCl_ReadShort(), NetCl_ReadShort(), NetCl_ReadShort(), NetCl_ReadShort()); } } // Tell the server we're ready to begin receiving frames. Net_SendPacket(DDSP_CONFIRM, DDPT_OK, NULL, 0); } void NetCl_UpdatePlayerState2(byte *data, int plrNum) { player_t *pl = &players[plrNum]; unsigned int flags; //int oldstate = pl->playerState; byte b; int i, k; if(!Get(DD_GAME_READY)) { #ifdef _DEBUG Con_Message("NetCl_UpdatePlayerState2: Discarded because game isn't ready.\n"); #endif return; } NetCl_SetReadBuffer(data); flags = NetCl_ReadLong(); if(flags & PSF2_OWNED_WEAPONS) { boolean val; k = NetCl_ReadShort(); for(i = 0; i < NUM_WEAPON_TYPES; ++i) { val = (k & (1 << i)) != 0; // Maybe unhide the HUD? if(val == true && pl->weapons[i].owned == false) ST_HUDUnHide(pl - players, HUE_ON_PICKUP_WEAPON); pl->weapons[i].owned = val; } } if(flags & PSF2_STATE) { b = NetCl_ReadByte(); pl->playerState = b & 0xf; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ pl->armorType = b >> 4; #endif #ifdef _DEBUG Con_Message("NetCl_UpdatePlayerState2: New state = %i\n", pl->playerState); #endif // Set or clear the DEAD flag for this player. if(pl->playerState == PST_LIVE) pl->plr->flags &= ~DDPF_DEAD; else pl->plr->flags |= DDPF_DEAD; //if(pl->playerState != oldstate) { P_SetupPsprites(pl); } pl->cheats = NetCl_ReadByte(); // Set or clear the NOCLIP flag. if(P_GetPlayerCheats(pl) & CF_NOCLIP) pl->plr->flags |= DDPF_NOCLIP; else pl->plr->flags &= ~DDPF_NOCLIP; } } void NetCl_UpdatePlayerState(byte *data, int plrNum) { int i; player_t *pl = &players[plrNum]; byte b; unsigned short flags, s; if(!Get(DD_GAME_READY)) return; NetCl_SetReadBuffer(data); flags = NetCl_ReadShort(); //Con_Printf("NetCl_UpdPlrState: fl=%x\n", flags); if(flags & PSF_STATE) // and armor type (the same bit) { b = NetCl_ReadByte(); pl->playerState = b & 0xf; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ pl->armorType = b >> 4; #endif // Set or clear the DEAD flag for this player. if(pl->playerState == PST_LIVE) pl->plr->flags &= ~DDPF_DEAD; else pl->plr->flags |= DDPF_DEAD; //if(oldstate != pl->playerState) // && oldstate == PST_DEAD) { P_SetupPsprites(pl); } } if(flags & PSF_HEALTH) { int health = NetCl_ReadByte(); if(health < pl->health) ST_HUDUnHide(plrNum, HUE_ON_DAMAGE); pl->health = health; pl->plr->mo->health = pl->health; } if(flags & PSF_ARMOR_POINTS) { byte ap; #if __JHEXEN__ for(i = 0; i < NUMARMOR; ++i) { ap = NetCl_ReadByte(); // Maybe unhide the HUD? if(ap >= pl->armorPoints[i] && pl == &players[CONSOLEPLAYER]) ST_HUDUnHide(plrNum, HUE_ON_PICKUP_ARMOR); pl->armorPoints[i] = ap; } #else ap = NetCl_ReadByte(); // Maybe unhide the HUD? if(ap >= pl->armorPoints) ST_HUDUnHide(plrNum, HUE_ON_PICKUP_ARMOR); pl->armorPoints = ap; #endif } #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ if(flags & PSF_INVENTORY) { uint i, count; for(i = 0; i < NUM_INVENTORYITEM_TYPES; ++i) { inventoryitemtype_t type = IIT_FIRST + i; uint j, count = P_InventoryCount(plrNum, type); for(j = 0; j < count; ++j) P_InventoryTake(plrNum, type, true); } count = NetCl_ReadByte(); for(i = 0; i < count; ++i) { inventoryitemtype_t type; uint j, num; s = NetCl_ReadShort(); type = s & 0xff; num = s >> 8; for(j = 0; j < num; ++j) P_InventoryGive(plrNum, type, true); } } #endif if(flags & PSF_POWERS) { b = NetCl_ReadByte(); // Only the non-zero powers are included in the message. #if __JHEXEN__ || __JSTRIFE__ for(i = 0; i < NUM_POWER_TYPES - 1; ++i) { byte val = ((b & (1 << i))? (NetCl_ReadByte() * 35) : 0); // Maybe unhide the HUD? if(val > pl->powers[i]) ST_HUDUnHide(pl - players, HUE_ON_PICKUP_POWER); pl->powers[i + 1] = val; } #else for(i = 0; i < NUM_POWER_TYPES; ++i) { # if __JDOOM__ || __JDOOM64__ if(i == PT_IRONFEET || i == PT_STRENGTH) continue; # endif { int val = ((b & (1 << i))? (NetCl_ReadByte() * 35) : 0); // Maybe unhide the HUD? if(val > pl->powers[i]) ST_HUDUnHide(plrNum, HUE_ON_PICKUP_POWER); pl->powers[i] = val; } } #endif } if(flags & PSF_KEYS) { b = NetCl_ReadByte(); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ for(i = 0; i < NUM_KEY_TYPES; ++i) { boolean val = (b & (1 << i)) != 0; // Maybe unhide the HUD? if(val && !pl->keys[i]) ST_HUDUnHide(plrNum, HUE_ON_PICKUP_KEY); pl->keys[i] = val; } #endif } if(flags & PSF_FRAGS) { memset(pl->frags, 0, sizeof(pl->frags)); // First comes the number of frag counts included. for(i = NetCl_ReadByte(); i > 0; i--) { s = NetCl_ReadShort(); pl->frags[s >> 12] = s & 0xfff; } /*// A test... Con_Printf("Frags update: "); for(i=0; i<4; i++) Con_Printf("%i ", pl->frags[i]); Con_Printf("\n"); */ } if(flags & PSF_OWNED_WEAPONS) { boolean val; b = NetCl_ReadByte(); for(i = 0; i < NUM_WEAPON_TYPES; ++i) { val = (b & (1 << i)) != 0; // Maybe unhide the HUD? if(val == true && pl->weapons[i].owned == false) ST_HUDUnHide(plrNum, HUE_ON_PICKUP_WEAPON); pl->weapons[i].owned = val; } } if(flags & PSF_AMMO) { for(i = 0; i < NUM_AMMO_TYPES; ++i) { #if __JHEXEN__ || __JSTRIFE__ int val = (int) NetCl_ReadByte(); #else int val = NetCl_ReadShort(); #endif // Maybe unhide the HUD? if(val > pl->ammo[i].owned) ST_HUDUnHide(plrNum, HUE_ON_PICKUP_AMMO); pl->ammo[i].owned = val; } } if(flags & PSF_MAX_AMMO) { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Hexen has no use for max ammo. for(i = 0; i < NUM_AMMO_TYPES; i++) pl->ammo[i].max = NetCl_ReadShort(); #endif } if(flags & PSF_COUNTERS) { pl->killCount = NetCl_ReadShort(); pl->itemCount = NetCl_ReadByte(); pl->secretCount = NetCl_ReadByte(); /*Con_Printf( "plr%i: kills=%i items=%i secret=%i\n", pl-players, pl->killCount, pl->itemCount, pl->secretCount); */ } if(flags & PSF_PENDING_WEAPON || flags & PSF_READY_WEAPON) { b = NetCl_ReadByte(); if(flags & PSF_PENDING_WEAPON) { pl->pendingWeapon = b & 0xf; } if(flags & PSF_READY_WEAPON) { pl->readyWeapon = b >> 4; #if _DEBUG Con_Message("NetCl_UpdatePlayerState: readyweapon=%i\n", pl->readyWeapon); #endif } } if(flags & PSF_VIEW_HEIGHT) { pl->viewHeight = (float) NetCl_ReadByte(); } #if __JHERETIC || __JHEXEN__ || __JSTRIFE__ if(flags & PSF_MORPH_TIME) { pl->morphTics = NetCl_ReadByte() * 35; } #endif #if __JHEXEN__ || __JSTRIFE__ if(flags & PSF_LOCAL_QUAKE) { localQuakeHappening[plrNum] = NetCl_ReadByte(); } #endif } void NetCl_UpdatePSpriteState(byte *data) { // Not used. /* unsigned short s; NetCl_SetReadBuffer(data); s = NetCl_ReadShort(); P_SetPsprite(&players[CONSOLEPLAYER], ps_weapon, s); */ } void NetCl_Intermission(byte* data) { int flags; NetCl_SetReadBuffer(data); flags = NetCl_ReadByte(); //Con_Printf( "NetCl_Intermission: flags=%x\n", flags); if(flags & IMF_BEGIN) { uint i; // Close any automaps left open at the end of the previous map. for(i = 0; i < MAXPLAYERS; ++i) AM_Open(AM_MapForPlayer(i), false, true); GL_SetFilter(false); #if __JHEXEN__ SN_StopAllSequences(); #endif // @fixme jHeretic does not transmit the intermission info! #if __JDOOM__ || __JDOOM64__ wmInfo.maxKills = NetCl_ReadShort(); wmInfo.maxItems = NetCl_ReadShort(); wmInfo.maxSecret = NetCl_ReadShort(); wmInfo.nextMap = NetCl_ReadByte(); wmInfo.currentMap = NetCl_ReadByte(); wmInfo.didSecret = NetCl_ReadByte(); wmInfo.episode = gameEpisode; G_PrepareWIData(); #elif __JHERETIC__ wmInfo.episode = gameEpisode; #elif __JHEXEN__ nextMap = NetCl_ReadByte(); nextMapEntryPoint = NetCl_ReadByte(); #endif #if __JDOOM__ || __JDOOM64__ WI_Init(&wmInfo); #elif __JHERETIC__ IN_Init(&wmInfo); #elif __JHEXEN__ IN_Init(); #endif #if __JDOOM64__ S_StartMusic("dm2int", true); #elif __JDOOM__ S_StartMusic(gameMode == commercial? "dm2int" : "inter", true); #elif __JHERETIC__ S_StartMusic("intr", true); #elif __JHEXEN__ S_StartMusic("hub", true); #endif G_ChangeGameState(GS_INTERMISSION); } if(flags & IMF_END) { #if __JDOOM__ || __JDOOM64__ WI_End(); #elif __JHERETIC__ || __JHEXEN__ IN_Stop(); #endif } if(flags & IMF_STATE) { #if __JDOOM__ || __JDOOM64__ WI_SetState(NetCl_ReadByte()); #elif __JHERETIC__ || __JHEXEN__ interState = (int) NetCl_ReadByte(); #endif } #if __JHERETIC__ if(flags & IMF_TIME) interTime = NetCl_ReadShort(); #endif } /** * This is where clients start their InFine interludes. */ void NetCl_Finale(int packetType, byte *data) { int flags, len, numConds, i; byte *script = NULL; NetCl_SetReadBuffer(data); flags = NetCl_ReadByte(); if(flags & FINF_SCRIPT) { // First read the values of the conditions. if(packetType == GPT_FINALE2) { numConds = NetCl_ReadByte(); for(i = 0; i < numConds; ++i) { FI_SetCondition(i, NetCl_ReadByte()); } } // Read the script into map-scope memory. It will be freed // when the next map is loaded. len = strlen((char*)readbuffer); script = Z_Malloc(len + 1, PU_MAP, 0); strcpy((char*)script, (char*)readbuffer); } if(flags & FINF_BEGIN && script) { // Start the script. FI_Start((char*)script, (flags & FINF_AFTER) ? FIMODE_AFTER : (flags & FINF_OVERLAY) ? FIMODE_OVERLAY : FIMODE_BEFORE); } if(flags & FINF_END) { // Stop InFine. FI_End(); } if(flags & FINF_SKIP) { FI_SkipRequest(); } } /** * Clients have other players' info, but it's only "FYI"; they don't * really need it. */ void NetCl_UpdatePlayerInfo(byte *data) { int num; NetCl_SetReadBuffer(data); num = NetCl_ReadByte(); cfg.playerColor[num] = NetCl_ReadByte(); #if __JHEXEN__ || __JHERETIC__ cfg.playerClass[num] = NetCl_ReadByte(); players[num].class = cfg.playerClass[num]; #endif #if __JDOOM__ || __JSTRIFE__ || __JDOOM64__ Con_Printf("NetCl_UpdatePlayerInfo: pl=%i color=%i\n", num, cfg.playerColor[num]); #else Con_Printf("NetCl_UpdatePlayerInfo: pl=%i color=%i class=%i\n", num, cfg.playerColor[num], cfg.playerClass[num]); #endif } /** * Send CONSOLEPLAYER's settings to the server. */ void NetCl_SendPlayerInfo() { byte buffer[10], *ptr = buffer; if(!IS_CLIENT) return; *ptr++ = cfg.netColor; #if __JHEXEN__ *ptr++ = cfg.netClass; #elif __JHERETIC__ *ptr++ = PCLASS_PLAYER; #endif Net_SendPacket(DDSP_ORDERED, GPT_PLAYER_INFO, buffer, ptr - buffer); } void NetCl_SaveGame(void *data) { if(Get(DD_PLAYBACK)) return; SV_SaveClient(*(unsigned int *) data); #if __JDOOM__ || __JDOOM64__ P_SetMessage(&players[CONSOLEPLAYER], TXT_GAMESAVED, false); #endif } void NetCl_LoadGame(void *data) { if(!IS_CLIENT) return; if(Get(DD_PLAYBACK)) return; SV_LoadClient(*(unsigned int *) data); // Net_SendPacket(DDSP_RELIABLE, GPT_LOAD, &con, 1); #if __JDOOM__ || __JDOOM64__ P_SetMessage(&players[CONSOLEPLAYER], GET_TXT(TXT_CLNETLOAD), false); #endif } /** * Pause or unpause the game. */ void NetCl_Paused(boolean setPause) { paused = (setPause != 0); DD_SetInteger(DD_CLIENT_PAUSED, paused); } /** * \kludge Write a DDPT_COMMANDS (32) packet. Returns a pointer to a static * buffer that contains the data (kludge to work around the parameter * passing from the engine). */ void *NetCl_WriteCommands(ticcmd_t *cmd, int count) { static byte msg[1024]; // A shared buffer. int i; ushort *size = (ushort *) msg; byte *out = msg + 2, *flags, *start = out; ticcmd_t prev; // Always compare against the previous command. memset(&prev, 0, sizeof(prev)); for(i = 0; i < count; ++i, cmd++) { flags = out++; *flags = 0; // What has changed? if(cmd->forwardMove != prev.forwardMove) { *flags |= CMDF_FORWARDMOVE; *out++ = cmd->forwardMove; } if(cmd->sideMove != prev.sideMove) { *flags |= CMDF_SIDEMOVE; *out++ = cmd->sideMove; } if(cmd->angle != prev.angle) { *flags |= CMDF_ANGLE; *(unsigned short *) out = SHORT(cmd->angle); out += 2; } if(cmd->pitch != prev.pitch) { *flags |= CMDF_LOOKDIR; *(short *) out = SHORT(cmd->pitch); out += 2; } if(cmd->actions != prev.actions) { *flags |= CMDF_BUTTONS; *out++ = cmd->actions; } /* // Compile the button flags. buttons = 0; // Client sends player action requests sent instead. if(!IS_CLIENT) { if(cmd->attack) buttons |= CMDF_BTN_ATTACK; if(cmd->use) buttons |= CMDF_BTN_USE; } if(cmd->jump) buttons |= CMDF_BTN_JUMP; if(cmd->pause) buttons |= CMDF_BTN_PAUSE; // Always include nonzero buttons. if(buttons != 0) { *flags |= CMDF_BUTTONS; *out++ = buttons; } if(cmd->fly != prev.fly) { *flags |= CMDF_LOOKFLY; *out++ = cmd->fly; } if(cmd->arti != prev.arti) { *flags |= CMDF_ARTI; *out++ = cmd->arti; } if(cmd->changeWeapon != prev.changeWeapon) { *flags |= CMDF_CHANGE_WEAPON; *(short *) out = SHORT(cmd->changeWeapon); out += 2; } */ memcpy(&prev, cmd, sizeof(*cmd)); } // First two bytes contain the size of the buffer (not included in // the actual packet). *size = out - start; return msg; } /** * Send a GPT_CHEAT_REQUEST packet to the server. If the server is allowing * netgame cheating, the cheat will be executed on the server. */ void NetCl_CheatRequest(const char *command) { char msg[40]; // Copy the cheat command into a NULL-terminated buffer. memset(msg, 0, sizeof(msg)); strncpy(msg, command, sizeof(msg) - 1); if(IS_CLIENT) Net_SendPacket(DDSP_CONFIRM, GPT_CHEAT_REQUEST, msg, strlen(msg) + 1); else NetSv_DoCheat(CONSOLEPLAYER, msg); } /** * Set the jump power used in client mode. */ void NetCl_UpdateJumpPower(void *data) { netJumpPower = FLOAT( *(float *) data ); #ifdef _DEBUG Con_Printf("NetCl_UpdateJumpPower: %g\n", netJumpPower); #endif } /** * Sends a player action request. The server will execute the action. * This is more reliable than sending via the ticcmds, as the client will * determine exactly when and where the action takes place. On serverside, * the clients position and angle may not be up to date when a ticcmd * arrives. */ void NetCl_PlayerActionRequest(player_t *player, int actionType) { #define MSG_SIZE (28) char msg[MSG_SIZE]; int *ptr = (int*) msg; if(!IS_CLIENT) return; #ifdef _DEBUG Con_Message("NetCl_PlayerActionRequest: Player %i, action %i.\n", player - players, actionType); #endif // Type of the request. *ptr++ = LONG(actionType); // Position of the action. *ptr++ = LONG(FLT2FIX(player->plr->mo->pos[VX])); *ptr++ = LONG(FLT2FIX(player->plr->mo->pos[VY])); *ptr++ = LONG(FLT2FIX(player->plr->mo->pos[VZ])); // Which way is the player looking at? *ptr++ = LONG(player->plr->mo->angle); *ptr++ = LONG(FLT2FIX(player->plr->lookDir)); // Currently active weapon. *ptr++ = LONG(player->readyWeapon); Net_SendPacket(DDSP_CONFIRM, GPT_ACTION_REQUEST, msg, MSG_SIZE); #undef MSG_SIZE } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/hu_pspr.c0000644000175000017500000001335211357170242022455 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_pspr.c: Common HUD psprite handling. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "g_controls.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ #if __JHERETIC__ static float PSpriteSY[NUM_PLAYER_CLASSES][NUM_WEAPON_TYPES] = { // Player { 0, 5, 15, 15, 15, 15, 15, 15}, // Chicken {15, 15, 15, 15, 15, 15, 15, 15} }; #endif #if __JHEXEN__ static float PSpriteSY[NUM_PLAYER_CLASSES][NUM_WEAPON_TYPES] = { // Fighter {0, -12, -10, 10}, // Cleric {-8, 10, 10, 0}, // Mage {9, 20, 20, 20}, // Pig {10, 10, 10, 10} }; #endif // CODE -------------------------------------------------------------------- /** * Calculates the Y offset for the player's psprite. The offset depends * on the size of the game window. */ float HU_PSpriteYOffset(player_t* pl) { int viewWindowHeight = Get(DD_VIEWWINDOW_HEIGHT); float offy = (cfg.plrViewHeight - DEFAULT_PLAYER_VIEWHEIGHT) * 2; #if __JHERETIC__ if(viewWindowHeight == SCREENHEIGHT) offy += PSpriteSY[pl->morphTics? PCLASS_CHICKEN : pl->class][pl->readyWeapon]; #elif __JHEXEN__ if(viewWindowHeight == SCREENHEIGHT) offy += PSpriteSY[pl->morphTics? PCLASS_PIG : pl->class][pl->readyWeapon]; #endif #if __JDOOM__ || __JHERETIC__ || __JHEXEN__ // If the status bar is visible, the sprite is moved up a bit. if(viewWindowHeight < SCREENHEIGHT) offy -= (float) (ST_HEIGHT - 2) * (cfg.statusbarScale / 20.f) - 20; #endif return offy; } /** * Calculates the Y offset for the player's psprite. The offset depends * on the size of the game window. */ void HU_UpdatePlayerSprite(int pnum) { int i; pspdef_t *psp; ddpsprite_t *ddpsp; float fov = 90; //*(float*) Con_GetVariable("r_fov")->ptr; player_t *pl = players + pnum; for(i = 0; i < NUMPSPRITES; ++i) { psp = pl->pSprites + i; ddpsp = pl->plr->pSprites + i; if(!psp->state) // A NULL state? { //ddpsp->sprite = -1; ddpsp->statePtr = 0; continue; } ddpsp->statePtr = psp->state; ddpsp->tics = psp->tics; ddpsp->flags = 0; // Fullbright? if((psp->state->flags & STF_FULLBRIGHT) || (pl->powers[PT_INFRARED] > 4 * 32) || (pl->powers[PT_INFRARED] & 8) # if __JDOOM__ || __JDOOM64__ || (pl->powers[PT_INVULNERABILITY] > 30) # endif ) { ddpsp->flags |= DDPSPF_FULLBRIGHT; } // Translucent? ddpsp->alpha = 1; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ if((pl->powers[PT_INVISIBILITY] > 4 * 32) || (pl->powers[PT_INVISIBILITY] & 8)) { // shadow draw ddpsp->alpha = .25f; } #elif __JHEXEN__ if(pl->powers[PT_INVULNERABILITY] && pl->class == PCLASS_CLERIC) { if(pl->powers[PT_INVULNERABILITY] > 4 * 32) { if(pl->plr->mo->flags2 & MF2_DONTDRAW) { // don't draw the psprite ddpsp->alpha = .333f; } else if(pl->plr->mo->flags & MF_SHADOW) { ddpsp->alpha = .666f; } } else if(pl->powers[PT_INVULNERABILITY] & 8) { ddpsp->alpha = .333f; } } #endif // Offset from center. ddpsp->pos[VX] = psp->pos[VX] - G_GetLookOffset(pnum) * 1300; if(fov > 90) fov = 90; ddpsp->pos[VY] = psp->pos[VY] + (90 - fov) / 90 * 80; } } /** * Updates the state of the player sprites (gives their data to the * engine so it can render them). Servers handle psprites of all players. */ void HU_UpdatePsprites(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { if(!IS_CLIENT || CONSOLEPLAYER == i) { HU_UpdatePlayerSprite(i); } } } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_mapspec.c0000644000175000017500000004563111357170242022751 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mapspec.c: * * Line Tag handling. Line and Sector groups. Specialized iteration * routines, respective utility functions... */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_mapspec.h" #include "p_terraintype.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct taglist_s { int tag; iterlist_t *list; } taglist_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- iterlist_t *spechit; // for crossed line specials. iterlist_t *linespecials; // for surfaces that tick eg wall scrollers. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static taglist_t *lineTagLists = NULL; static int numLineTagLists = 0; static taglist_t *sectorTagLists = NULL; static int numSectorTagLists = 0; // CODE -------------------------------------------------------------------- /** * */ void P_DestroyLineTagLists(void) { int i; if(numLineTagLists == 0) return; for(i = 0; i < numLineTagLists; ++i) { P_EmptyIterList(lineTagLists[i].list); P_DestroyIterList(lineTagLists[i].list); } free(lineTagLists); lineTagLists = NULL; numLineTagLists = 0; } /** * */ iterlist_t *P_GetLineIterListForTag(int tag, boolean createNewList) { int i; taglist_t *tagList; // Do we have an existing list for this tag? for(i = 0; i < numLineTagLists; ++i) if(lineTagLists[i].tag == tag) return lineTagLists[i].list; if(!createNewList) return NULL; // Nope, we need to allocate another. numLineTagLists++; lineTagLists = realloc(lineTagLists, sizeof(taglist_t) * numLineTagLists); tagList = &lineTagLists[numLineTagLists - 1]; tagList->tag = tag; return (tagList->list = P_CreateIterList()); } /** * */ void P_DestroySectorTagLists(void) { int i; if(numSectorTagLists == 0) return; for(i = 0; i < numSectorTagLists; ++i) { P_EmptyIterList(sectorTagLists[i].list); P_DestroyIterList(sectorTagLists[i].list); } free(sectorTagLists); sectorTagLists = NULL; numSectorTagLists = 0; } /** * */ iterlist_t *P_GetSectorIterListForTag(int tag, boolean createNewList) { int i; taglist_t *tagList; // Do we have an existing list for this tag? for(i = 0; i < numSectorTagLists; ++i) if(sectorTagLists[i].tag == tag) return sectorTagLists[i].list; if(!createNewList) return NULL; // Nope, we need to allocate another. numSectorTagLists++; sectorTagLists = realloc(sectorTagLists, sizeof(taglist_t) * numSectorTagLists); tagList = §orTagLists[numSectorTagLists - 1]; tagList->tag = tag; return (tagList->list = P_CreateIterList()); } /** * Get the sector on the other side of the line that is NOT the given sector. * * @param line Ptr to the line to test. * @param sec Reference sector to compare against. * * @return Ptr to the other sector or @c NULL if the specified * line is NOT twosided. */ sector_t *P_GetNextSector(linedef_t *line, sector_t *sec) { sector_t *frontSec; if(!sec || !line) return NULL; frontSec = P_GetPtrp(line, DMU_FRONT_SECTOR); if(!frontSec) return NULL; if(frontSec == sec) return P_GetPtrp(line, DMU_BACK_SECTOR); return frontSec; } #define FELLF_MIN 0x1 // Get minimum. If not set, get maximum. typedef struct findlightlevelparams_s { sector_t *baseSec; byte flags; float val; sector_t *foundSec; } findlightlevelparams_t; int findExtremalLightLevelInAdjacentSectors(void *ptr, void *context) { linedef_t *line = (linedef_t*) ptr; findlightlevelparams_t *params = (findlightlevelparams_t*) context; sector_t *other; other = P_GetNextSector(line, params->baseSec); if(other) { float lightLevel = P_GetFloatp(other, DMU_LIGHT_LEVEL); if(params->flags & FELLF_MIN) { if(lightLevel < params->val) { params->val = lightLevel; params->foundSec = other; if(params->val <= 0) return 0; // Stop iteration. Can't get any darker. } } else { if(lightLevel > params->val) { params->val = lightLevel; params->foundSec = other; if(params->val >= 1) return 0; // Stop iteration. Can't get any brighter. } } } return 1; // Continue iteration. } /** * Find the sector with the lowest light level in surrounding sectors. */ sector_t* P_FindSectorSurroundingLowestLight(sector_t *sec, float *val) { findlightlevelparams_t params; params.val = DDMAXFLOAT; params.baseSec = sec; params.flags = FELLF_MIN; params.foundSec = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findExtremalLightLevelInAdjacentSectors); if(*val) *val = params.val; return params.foundSec; } /** * Find the sector with the highest light level in surrounding sectors. */ sector_t* P_FindSectorSurroundingHighestLight(sector_t *sec, float *val) { findlightlevelparams_t params; params.val = DDMINFLOAT; params.baseSec = sec; params.flags = 0; params.foundSec = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findExtremalLightLevelInAdjacentSectors); if(val) *val = params.val; return params.foundSec; } #define FNLLF_ABOVE 0x1 // Get next above, if not set get next below. typedef struct findnextlightlevelparams_s { sector_t *baseSec; float baseLight; byte flags; float val; sector_t *foundSec; } findnextlightlevelparams_t; int findNextLightLevel(void *ptr, void *context) { linedef_t *li = (linedef_t*) ptr; findnextlightlevelparams_t *params = (findnextlightlevelparams_t*) context; sector_t *other; other = P_GetNextSector(li, params->baseSec); if(other) { float otherLight = P_GetFloatp(other, DMU_LIGHT_LEVEL); if(params->flags & FNLLF_ABOVE) { if(otherLight < params->val && otherLight > params->baseLight) { params->val = otherLight; params->foundSec = other; if(!(params->val > 0)) return 0; // Stop iteration. Can't get any darker. } } else { if(otherLight > params->val && otherLight < params->baseLight) { params->val = otherLight; params->foundSec = other; if(!(params->val < 1)) return 0; // Stop iteration. Can't get any brighter. } } } return 1; // Continue iteration. } /** * Find the sector with the lowest light level in surrounding sectors. */ sector_t* P_FindSectorSurroundingNextLowestLight(sector_t *sec, float baseLight, float *val) { findnextlightlevelparams_t params; params.baseSec = sec; params.baseLight = baseLight; params.flags = 0; params.foundSec = NULL; params.val = DDMINFLOAT; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findNextLightLevel); if(*val) *val = params.val; return params.foundSec; } /** * Find the sector with the next highest light level in surrounding sectors. */ sector_t* P_FindSectorSurroundingNextHighestLight(sector_t *sec, float baseLight, float *val) { findnextlightlevelparams_t params; params.baseSec = sec; params.baseLight = baseLight; params.flags = FNLLF_ABOVE; params.foundSec = NULL; params.val = DDMAXFLOAT; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findNextLightLevel); if(*val) *val = params.val; return params.foundSec; } #define FEPHF_MIN 0x1 // Get minium. If not set, get maximum. #define FEPHF_FLOOR 0x2 // Get floors. If not set, get ceilings. typedef struct findextremalplaneheightparams_s { sector_t *baseSec; byte flags; float val; sector_t *foundSec; } findextremalplaneheightparams_t; int findExtremalPlaneHeight(void *ptr, void *context) { linedef_t *ln = (linedef_t*) ptr; findextremalplaneheightparams_t *params = (findextremalplaneheightparams_t*) context; sector_t *other; other = P_GetNextSector(ln, params->baseSec); if(other) { float height = P_GetFloatp(other, ((params->flags & FEPHF_FLOOR)? DMU_FLOOR_HEIGHT : DMU_CEILING_HEIGHT)); if(params->flags & FEPHF_MIN) { if(height < params->val) { params->val = height; params->foundSec = other; } } else { if(height > params->val) { params->val = height; params->foundSec = other; } } } return 1; // Continue iteration. } /** * Find the sector with the lowest floor height in surrounding sectors. */ sector_t* P_FindSectorSurroundingLowestFloor(sector_t* sec, float max, float* val) { findextremalplaneheightparams_t params; params.baseSec = sec; params.flags = FEPHF_MIN | FEPHF_FLOOR; params.val = max; params.foundSec = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findExtremalPlaneHeight); if(val) *val = params.val; return params.foundSec; } /** * Find the sector with the highest floor height in surrounding sectors. */ sector_t* P_FindSectorSurroundingHighestFloor(sector_t* sec, float min, float* val) { findextremalplaneheightparams_t params; params.baseSec = sec; params.flags = FEPHF_FLOOR; params.val = min; params.foundSec = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findExtremalPlaneHeight); if(val) *val = params.val; return params.foundSec; } /** * Find lowest ceiling in the surrounding sector. */ sector_t* P_FindSectorSurroundingLowestCeiling(sector_t *sec, float max, float *val) { findextremalplaneheightparams_t params; params.baseSec = sec; params.flags = FEPHF_MIN; params.val = max; params.foundSec = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findExtremalPlaneHeight); if(val) *val = params.val; return params.foundSec; } /** * Find highest ceiling in the surrounding sectors. */ sector_t* P_FindSectorSurroundingHighestCeiling(sector_t *sec, float min, float *val) { findextremalplaneheightparams_t params; params.baseSec = sec; params.flags = 0; params.val = min; params.foundSec = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findExtremalPlaneHeight); if(val) *val = params.val; return params.foundSec; } #define FNPHF_FLOOR 0x1 // Get floors, if not set get ceilings. #define FNPHF_ABOVE 0x2 // Get next above, if not set get next below. typedef struct findnextplaneheightparams_s { sector_t *baseSec; float baseHeight; byte flags; float val; sector_t *foundSec; } findnextplaneheightparams_t; int findNextPlaneHeight(void *ptr, void *context) { linedef_t *li = (linedef_t*) ptr; findnextplaneheightparams_t *params = (findnextplaneheightparams_t*) context; sector_t *other; other = P_GetNextSector(li, params->baseSec); if(other) { float otherHeight = P_GetFloatp(other, ((params->flags & FNPHF_FLOOR)? DMU_FLOOR_HEIGHT : DMU_CEILING_HEIGHT)); if(params->flags & FNPHF_ABOVE) { if(otherHeight < params->val && otherHeight > params->baseHeight) { params->val = otherHeight; params->foundSec = other; } } else { if(otherHeight > params->val && otherHeight < params->baseHeight) { params->val = otherHeight; params->foundSec = other; } } } return 1; // Continue iteration. } /** * Find the sector with the next highest floor in surrounding sectors. */ sector_t* P_FindSectorSurroundingNextHighestFloor(sector_t *sec, float baseHeight, float *val) { findnextplaneheightparams_t params; params.baseSec = sec; params.baseHeight = baseHeight; params.flags = FNPHF_FLOOR | FNPHF_ABOVE; params.foundSec = NULL; params.val = DDMAXFLOAT; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findNextPlaneHeight); if(val) *val = params.val; return params.foundSec; } /** * Find the sector with the next highest ceiling in surrounding sectors. */ sector_t* P_FindSectorSurroundingNextHighestCeiling(sector_t *sec, float baseHeight, float *val) { findnextplaneheightparams_t params; params.baseSec = sec; params.baseHeight = baseHeight; params.flags = FNPHF_ABOVE; params.foundSec = NULL; params.val = DDMAXFLOAT; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findNextPlaneHeight); if(val) *val = params.val; return params.foundSec; } /** * Find the sector with the next lowest floor in surrounding sectors. */ sector_t* P_FindSectorSurroundingNextLowestFloor(sector_t *sec, float baseHeight, float *val) { findnextplaneheightparams_t params; params.baseSec = sec; params.baseHeight = baseHeight; params.flags = FNPHF_FLOOR; params.foundSec = NULL; params.val = DDMINFLOAT; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findNextPlaneHeight); if(val) *val = params.val; return params.foundSec; } /** * Find the sector with the next lowest ceiling in surrounding sectors. */ sector_t* P_FindSectorSurroundingNextLowestCeiling(sector_t *sec, float baseHeight, float *val) { findnextplaneheightparams_t params; params.baseSec = sec; params.baseHeight = baseHeight; params.flags = 0; params.foundSec = NULL; params.val = DDMINFLOAT; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findNextPlaneHeight); if(val) *val = params.val; return params.foundSec; } typedef struct spreadsoundtoneighborsparams_s { sector_t *baseSec; int soundBlocks; mobj_t *soundTarget; } spreadsoundtoneighborsparams_t; int spreadSoundToNeighbors(void *ptr, void *context) { linedef_t *li = (linedef_t*) ptr; spreadsoundtoneighborsparams_t *params = (spreadsoundtoneighborsparams_t*) context; sector_t *frontSec, *backSec; frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR); backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(frontSec && backSec) { P_LineOpening(li); if(OPENRANGE > 0) { sector_t *other; xline_t *xline; if(frontSec == params->baseSec) other = backSec; else other = frontSec; xline = P_ToXLine(li); if(xline->flags & ML_SOUNDBLOCK) { if(!params->soundBlocks) P_RecursiveSound(params->soundTarget, other, 1); } else { P_RecursiveSound(params->soundTarget, other, params->soundBlocks); } } } return 1; // Continue iteration. } /** * Recursively traverse adjacent sectors, sound blocking lines cut off * traversal. Called by P_NoiseAlert. */ void P_RecursiveSound(struct mobj_s *soundTarget, sector_t *sec, int soundBlocks) { spreadsoundtoneighborsparams_t params; xsector_t *xsec = P_ToXSector(sec); // Wake up all monsters in this sector. if(P_GetIntp(sec, DMU_VALID_COUNT) == VALIDCOUNT && xsec->soundTraversed <= soundBlocks + 1) return; // Already flooded. P_SetIntp(sec, DMU_VALID_COUNT, VALIDCOUNT); xsec->soundTraversed = soundBlocks + 1; xsec->soundTarget = soundTarget; params.baseSec = sec; params.soundBlocks = soundBlocks; params.soundTarget = soundTarget; P_Iteratep(sec, DMU_LINEDEF, ¶ms, spreadSoundToNeighbors); } /** * Returns the material type of the specified sector, plane. * * @param sec The sector to check. * @param plane The plane id to check. */ const terraintype_t* P_GetPlaneMaterialType(sector_t* sec, int plane) { return P_TerrainTypeForMaterial( P_GetPtrp(sec, (plane? DMU_CEILING_MATERIAL : DMU_FLOOR_MATERIAL))); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_actor.c0000644000175000017500000003332511357170242022426 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_actor.c: Common code relating to mobjs. * * Mobj management, movement smoothing etc. */ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "p_tick.h" #include "p_actor.h" // MACROS ------------------------------------------------------------------ #define MIN_STEP ((10 * ANGLE_1) >> 16) // degrees per tic #define MAX_STEP (ANG90 >> 16) #if __JDOOM64__ # define RESPAWNTICS (4 * TICSPERSEC) #else # define RESPAWNTICS (30 * TICSPERSEC) #endif // TYPES ------------------------------------------------------------------- typedef struct spawnqueuenode_s { int startTime; int minTics; // Minimum number of tics before respawn. void (*callback) (mobj_t* mo, void* context); void* context; float pos[3]; angle_t angle; mobjtype_t type; int spawnFlags; // MSF_* flags struct spawnqueuenode_s* next; } spawnqueuenode_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static spawnqueuenode_t* spawnQueueHead = NULL, *unusedNodes = NULL; // CODE -------------------------------------------------------------------- void P_SpawnTelefog(mobj_t* mo, void* context) { #if __JDOOM__ || __JDOOM64__ S_StartSound(SFX_ITMBK, mo); #else S_StartSound(SFX_RESPAWN, mo); #endif # if __JDOOM64__ mo->translucency = 255; mo->spawnFadeTics = 0; mo->intFlags |= MIF_FADE; # elif __JDOOM__ // Spawn the item teleport fog at the new spot. P_SpawnMobj3fv(MT_IFOG, mo->pos, mo->angle, 0); # endif } /** * Removes the given mobj from the world. * * @param mo The mobj to be removed. * @param noRespawn Disable the automatical respawn which occurs * with mobjs of certain type(s) (also dependant on * the current gamemode). * Generally this should be @c false. */ void P_MobjRemove(mobj_t* mo, boolean noRespawn) { #if __JDOOM__ || __JDOOM64__ if(!noRespawn) { if( # if __JDOOM__ // Only respawn items in deathmatch 2 and optionally in coop. !(deathmatch != 2 && (!cfg.coopRespawnItems || !IS_NETGAME || deathmatch)) && # endif /*#elif __JDOOM64__ (spot->flags & MTF_RESPAWN) && # endif*/ (mo->flags & MF_SPECIAL) && !(mo->flags & MF_DROPPED) # if __JDOOM__ || __JDOOM64__ && (mo->type != MT_INV) && (mo->type != MT_INS) # endif ) { P_DeferSpawnMobj3fv(RESPAWNTICS, mo->type, mo->spawnSpot.pos, mo->spawnSpot.angle, mo->spawnSpot.flags, P_SpawnTelefog, NULL); } } #endif #if __JHEXEN__ if((mo->flags & MF_COUNTKILL) && (mo->flags & MF_CORPSE)) { A_DeQueueCorpse(mo); } P_MobjRemoveFromTIDList(mo); #endif P_MobjDestroy(mo); } /** * Called after a move to link the mobj back into the world. */ void P_MobjSetPosition(mobj_t* mo) { int flags = DDLINK_BLOCKMAP; if(!(mo->flags & MF_NOSECTOR)) flags |= DDLINK_SECTOR; P_MobjLink(mo, flags); } /** * Unlinks a mobj from the world so that it can be moved. */ void P_MobjUnsetPosition(mobj_t* mo) { P_MobjUnlink(mo); } /** * The actor has taken a step, set the corresponding short-range visual * offset. */ void P_MobjSetSRVO(mobj_t* mo, float stepx, float stepy) { mo->srvo[VX] = -stepx; mo->srvo[VY] = -stepy; } /** * The actor has taken a step, set the corresponding short-range visual * offset. */ void P_MobjSetSRVOZ(mobj_t* mo, float stepz) { mo->srvo[VZ] = -stepz; } /** * Turn visual angle towards real angle. An engine cvar controls whether * the visangle or the real angle is used in rendering. * Real-life analogy: angular momentum (you can't suddenly just take a * 90 degree turn in zero time). */ void P_MobjAngleSRVOTicker(mobj_t* mo) { short target, step, diff; int lstep, hgt; // Check requirements. if(mo->flags & MF_MISSILE || !(mo->flags & MF_COUNTKILL)) { mo->visAngle = mo->angle >> 16; return; // This is not for us. } target = mo->angle >> 16; diff = target - mo->visAngle; if(mo->turnTime) { if(mo->tics) step = abs(diff) / mo->tics; else step = abs(diff); if(!step) step = 1; } else { // Calculate a good step size. // Thing height and diff taken into account. hgt = (int) mo->height; if(hgt < 30) hgt = 30; if(hgt > 60) hgt = 60; lstep = abs(diff) * 8 / hgt; if(lstep < MIN_STEP) lstep = MIN_STEP; if(lstep > MAX_STEP) lstep = MAX_STEP; step = lstep; } // Do the step. if(abs(diff) <= step) mo->visAngle = target; else if(diff > 0) mo->visAngle += step; else if(diff < 0) mo->visAngle -= step; } /** * The thing's timer has run out, which means the thing has completed its * step. Or there has been a teleport. */ void P_MobjClearSRVO(mobj_t* mo) { memset(mo->srvo, 0, sizeof(mo->srvo)); } boolean P_MobjIsCamera(const mobj_t* mo) { // Client mobjs do not have thinkers and thus cannot be cameras. return (mo && mo->thinker.function && mo->player && (mo->player->plr->flags & DDPF_CAMERA)); } /** * The first three bits of the selector special byte contain a relative * health level. */ void P_UpdateHealthBits(mobj_t* mobj) { int i; if(mobj->info && mobj->info->spawnHealth > 0) { mobj->selector &= DDMOBJ_SELECTOR_MASK; // Clear high byte. i = (mobj->health << 3) / mobj->info->spawnHealth; if(i > 7) i = 7; if(i < 0) i = 0; mobj->selector |= i << DDMOBJ_SELECTOR_SHIFT; } } /** * Given a mobjtype, lookup the statenum associated to the named state. * * @param mobjType Type of mobj. * @param name State name identifier. * * @return Statenum of the associated state ELSE @c, S_NULL. */ statenum_t P_GetState(mobjtype_t type, statename_t name) { if(type < MT_FIRST || type >= Get(DD_NUMMOBJTYPES)) return S_NULL; if(name < 0 || name >= NUM_STATE_NAMES) return S_NULL; return MOBJINFO[type].states[name]; } void P_RipperBlood(mobj_t* actor) { mobj_t* mo; float pos[3]; pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = actor->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - P_Random()) << 12); pos[VY] += FIX2FLT((P_Random() - P_Random()) << 12); pos[VZ] += FIX2FLT((P_Random() - P_Random()) << 12); if((mo = P_SpawnMobj3fv(MT_BLOOD, pos, actor->angle, 0))) { #if __JHERETIC__ mo->flags |= MF_NOGRAVITY; #endif mo->mom[MX] = actor->mom[MX] / 2; mo->mom[MY] = actor->mom[MY] / 2; mo->tics += P_Random() & 3; } } static spawnqueuenode_t* allocateNode(void) { #define SPAWNQUEUENODE_BATCHSIZE 32 spawnqueuenode_t* n; if(unusedNodes) { // There are existing nodes we can re-use. n = unusedNodes; unusedNodes = unusedNodes->next; n->next = NULL; } else { // We need to allocate more. size_t i; spawnqueuenode_t* storage = Z_Malloc(sizeof(*n) * SPAWNQUEUENODE_BATCHSIZE, PU_STATIC, 0); // Add all but one to the unused node list. for(i = 0; i < SPAWNQUEUENODE_BATCHSIZE-1; ++i) { n = storage++; n->next = unusedNodes; unusedNodes = n; } n = storage; } return n; #undef SPAWNQUEUENODE_BATCHSIZE } static void freeNode(spawnqueuenode_t* node, boolean recycle) { // Find this node in the spawn queue and unlink it if found. if(spawnQueueHead) { if(spawnQueueHead == node) { spawnQueueHead = spawnQueueHead->next; } else { spawnqueuenode_t* n; for(n = spawnQueueHead; n->next; n = n->next) { if(n->next == node) n->next = n->next->next; } } } if(recycle) { // Recycle this node for later use. node->next = unusedNodes; unusedNodes = node; return; } Z_Free(node); } static spawnqueuenode_t* dequeueSpawn(void) { spawnqueuenode_t* n = spawnQueueHead; if(spawnQueueHead) spawnQueueHead = spawnQueueHead->next; return n; } static void emptySpawnQueue(boolean recycle) { if(spawnQueueHead) { spawnqueuenode_t* n; while((n = dequeueSpawn())) freeNode(n, recycle); } spawnQueueHead = NULL; } static void enqueueSpawn(int minTics, mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags, void (*callback) (mobj_t* mo, void* context), void* context) { spawnqueuenode_t* n = allocateNode(); n->type = type; n->pos[VX] = x; n->pos[VY] = y; n->pos[VZ] = z; n->angle = angle; n->spawnFlags = spawnFlags; n->startTime = mapTime; n->minTics = minTics; n->callback = callback; n->context = context; if(spawnQueueHead) { // Find the correct insertion point. if(spawnQueueHead->next) { spawnqueuenode_t* l = spawnQueueHead; while(l->next && l->next->minTics - (mapTime - l->next->startTime) <= minTics) l = l->next; n->next = (l->next? l->next : NULL); l->next = n; } else { // After or before the head? if(spawnQueueHead->minTics - (mapTime - spawnQueueHead->startTime) <= minTics) { n->next = NULL; spawnQueueHead->next = n; } else { n->next = spawnQueueHead; spawnQueueHead = n; } } } else { n->next = NULL; spawnQueueHead = n; } } static mobj_t* doDeferredSpawn(void) { mobj_t* mo = NULL; // Anything due to spawn? if(spawnQueueHead && mapTime - spawnQueueHead->startTime >= spawnQueueHead->minTics) { spawnqueuenode_t* n = dequeueSpawn(); // Spawn it. if((mo = P_SpawnMobj3fv(n->type, n->pos, n->angle, n->spawnFlags))) { if(n->callback) n->callback(mo, n->context); } freeNode(n, true); } return mo; } /** * Deferred mobj spawning until at least @minTics have passed. * Spawn behavior is otherwise exactly the same as an immediate spawn, via * P_SpawnMobj* */ void P_DeferSpawnMobj3f(int minTics, mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags, void (*callback) (mobj_t* mo, void* context), void* context) { if(minTics > 0) { enqueueSpawn(minTics, type, x, y, z, angle, spawnFlags, callback, context); } else // Spawn immediately. { mobj_t* mo; if((mo = P_SpawnMobj3f(type, x, y, z, angle, spawnFlags))) { if(callback) callback(mo, context); } } } void P_DeferSpawnMobj3fv(int minTics, mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags, void (*callback) (mobj_t* mo, void* context), void* context) { if(minTics > 0) { enqueueSpawn(minTics, type, pos[VX], pos[VY], pos[VZ], angle, spawnFlags, callback, context); } else // Spawn immediately. { mobj_t* mo; if((mo = P_SpawnMobj3fv(type, pos, angle, spawnFlags))) { if(callback) callback(mo, context); } } } /** * Called 35 times per second by P_DoTick. */ void P_DoDeferredSpawns(void) { while(doDeferredSpawn()); } void P_PurgeDeferredSpawns(void) { emptySpawnQueue(true); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/g_update.c0000644000175000017500000001156311357170242022567 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_update.c: Routines to call when updating the state of the engine * * \bug Not 64bit clean: In function 'G_RestoreState': cast from pointer to integer of different size */ // HEADER FILES ------------------------------------------------------------ #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" # include "m_cheat.h" #endif #include "hu_pspr.h" #include "hu_menu.h" #include "rend_automap.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ #define MANGLE_STATE(x) ((state_t*) ((x)? (x)-STATES : -1)) #define RESTORE_STATE(x) ((int)(x)==-1? NULL : &STATES[(int)(x)]) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static boolean mangleMobj(thinker_t* th, void* context) { mobj_t* mo = (mobj_t *) th; mo->state = MANGLE_STATE(mo->state); mo->info = (mobjinfo_t *) (mo->info - MOBJINFO); return true; // Continue iteration. } static boolean restoreMobj(thinker_t* th, void* context) { mobj_t* mo = (mobj_t *) th; mo->state = RESTORE_STATE(mo->state); mo->info = &MOBJINFO[(int) mo->info]; return true; // Continue iteration. } /** * Called before the engine re-inits the definitions. After that all the * state, info, etc. pointers will be obsolete. */ void G_MangleState(void) { int i; DD_IterateThinkers(P_MobjThinker, mangleMobj, NULL); for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; int k; for(k = 0; k < NUMPSPRITES; ++k) plr->pSprites[k].state = MANGLE_STATE(plr->pSprites[k].state); } } void G_RestoreState(void) { int i; DD_IterateThinkers(P_MobjThinker, restoreMobj, NULL); for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; int k; for(k = 0; k < NUMPSPRITES; ++k) plr->pSprites[k].state = RESTORE_STATE(plr->pSprites[k].state); } HU_UpdatePsprites(); } /** * Handles engine updates and renderer restarts. */ void G_UpdateState(int step) { switch(step) { case DD_GAME_MODE: // Set the game mode string. G_IdentifyVersion(); break; case DD_PRE: G_MangleState(); break; case DD_POST: G_RestoreState(); R_InitRefresh(); P_Init(); //// \fixme Detect gameMode changes (GM_DOOM -> GM_DOOM2, for instance). #if !__JHEXEN__ XG_Update(); #endif #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ P_InitInventory(); #endif #if __JHERETIC__ || __JHEXEN__ ST_Init(); #endif Hu_MenuInit(); #if __JHEXEN__ S_ParseSndInfoLump(); #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ S_MapMusic(gameEpisode, gameMap); #endif break; case DD_RENDER_RESTART_PRE: // Free the background fog effect texture. Hu_UnloadData(); // Free the automap mask texture. Rend_AutomapUnloadData(); break; case DD_RENDER_RESTART_POST: // Reload the background fog effect texture. Hu_LoadData(); // Reload the automap mask texture. Rend_AutomapLoadData(); break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_floor.c0000644000175000017500000012546411357170242022445 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Martin Eyre *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_floors.c: Moving floors. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "dmu_lib.h" #include "p_map.h" #include "p_mapspec.h" #include "p_tick.h" #include "p_floor.h" #if __JHEXEN__ || __JDOOM64__ #include "p_ceiling.h" #endif // MACROS ------------------------------------------------------------------ #if __JHERETIC__ # define SFX_FLOORMOVE (SFX_DORMOV) #else # define SFX_FLOORMOVE (SFX_STNMOV) #endif #if __JHEXEN__ #define STAIR_SECTOR_TYPE 26 #define STAIR_QUEUE_SIZE 32 #endif // TYPES ------------------------------------------------------------------- #if __JHEXEN__ typedef struct stairqueue_s { sector_t* sector; int type; float height; } stairqueue_t; // Global vars for stair building, in a struct for neatness. typedef struct stairdata_s { float stepDelta; int direction; float speed; material_t* material; int startDelay; int startDelayDelta; int textureChange; float startHeight; } stairdata_t; #endif // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- #if __JHEXEN__ static void enqueueStairSector(sector_t *sec, int type, float height); #endif // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ #if __JHEXEN__ stairdata_t stairData; stairqueue_t stairQueue[STAIR_QUEUE_SIZE]; static int stairQueueHead; static int stairQueueTail; #endif // CODE -------------------------------------------------------------------- /** * Move a plane (floor or ceiling) and check for crushing. */ result_e T_MovePlane(sector_t* sector, float speed, float dest, int crush, int isCeiling, int direction) { boolean flag; float lastpos; float floorheight, ceilingheight; int ptarget = (isCeiling? DMU_CEILING_TARGET_HEIGHT : DMU_FLOOR_TARGET_HEIGHT); int pspeed = (isCeiling? DMU_CEILING_SPEED : DMU_FLOOR_SPEED); // Let the engine know about the movement of this plane. P_SetFloatp(sector, ptarget, dest); P_SetFloatp(sector, pspeed, speed); floorheight = P_GetFloatp(sector, DMU_FLOOR_HEIGHT); ceilingheight = P_GetFloatp(sector, DMU_CEILING_HEIGHT); switch(isCeiling) { case 0: // FLOOR switch(direction) { case -1: // DOWN if(floorheight - speed < dest) { // The move is complete. lastpos = floorheight; P_SetFloatp(sector, DMU_FLOOR_HEIGHT, dest); flag = P_ChangeSector(sector, crush); if(flag == true) { // Oh no, the move failed. P_SetFloatp(sector, DMU_FLOOR_HEIGHT, lastpos); P_SetFloatp(sector, ptarget, lastpos); P_ChangeSector(sector, crush); } #if __JHEXEN__ P_SetFloatp(sector, pspeed, 0); #endif return pastdest; } else { lastpos = floorheight; P_SetFloatp(sector, DMU_FLOOR_HEIGHT, floorheight - speed); flag = P_ChangeSector(sector, crush); if(flag == true) { P_SetFloatp(sector, DMU_FLOOR_HEIGHT, lastpos); P_SetFloatp(sector, ptarget, lastpos); #if __JHEXEN__ P_SetFloatp(sector, pspeed, 0); #endif P_ChangeSector(sector, crush); return crushed; } } break; case 1: // UP if(floorheight + speed > dest) { // The move is complete. lastpos = floorheight; P_SetFloatp(sector, DMU_FLOOR_HEIGHT, dest); flag = P_ChangeSector(sector, crush); if(flag == true) { // Oh no, the move failed. P_SetFloatp(sector, DMU_FLOOR_HEIGHT, lastpos); P_SetFloatp(sector, ptarget, lastpos); P_ChangeSector(sector, crush); } #if __JHEXEN__ P_SetFloatp(sector, pspeed, 0); #endif return pastdest; } else { // COULD GET CRUSHED lastpos = floorheight; P_SetFloatp(sector, DMU_FLOOR_HEIGHT, floorheight + speed); flag = P_ChangeSector(sector, crush); if(flag == true) { #if !__JHEXEN__ if(crush) return crushed; #endif P_SetFloatp(sector, DMU_FLOOR_HEIGHT, lastpos); P_SetFloatp(sector, ptarget, lastpos); #if __JHEXEN__ P_SetFloatp(sector, pspeed, 0); #endif P_ChangeSector(sector, crush); return crushed; } } break; default: break; } break; case 1: // CEILING switch(direction) { case -1: // DOWN if(ceilingheight - speed < dest) { // The move is complete. lastpos = ceilingheight; P_SetFloatp(sector, DMU_CEILING_HEIGHT, dest); flag = P_ChangeSector(sector, crush); if(flag == true) { P_SetFloatp(sector, DMU_CEILING_HEIGHT, lastpos); P_SetFloatp(sector, ptarget, lastpos); P_ChangeSector(sector, crush); } #if __JHEXEN__ P_SetFloatp(sector, pspeed, 0); #endif return pastdest; } else { // COULD GET CRUSHED lastpos = ceilingheight; P_SetFloatp(sector, DMU_CEILING_HEIGHT, ceilingheight - speed); flag = P_ChangeSector(sector, crush); if(flag == true) { #if !__JHEXEN__ if(crush) return crushed; #endif P_SetFloatp(sector, DMU_CEILING_HEIGHT, lastpos); P_SetFloatp(sector, ptarget, lastpos); #if __JHEXEN__ P_SetFloatp(sector, pspeed, 0); #endif P_ChangeSector(sector, crush); return crushed; } } break; case 1: // UP if(ceilingheight + speed > dest) { // The move is complete. lastpos = ceilingheight; P_SetFloatp(sector, DMU_CEILING_HEIGHT, dest); flag = P_ChangeSector(sector, crush); if(flag == true) { P_SetFloatp(sector, DMU_CEILING_HEIGHT, lastpos); P_SetFloatp(sector, ptarget, lastpos); P_ChangeSector(sector, crush); } #if __JHEXEN__ P_SetFloatp(sector, pspeed, 0); #endif return pastdest; } else { lastpos = ceilingheight; P_SetFloatp(sector, DMU_CEILING_HEIGHT, ceilingheight + speed); flag = P_ChangeSector(sector, crush); } break; default: break; } break; default: break; } return ok; } /** * Move a floor to it's destination (up or down). */ void T_MoveFloor(floor_t* floor) { result_e res; #if __JHEXEN__ if(floor->resetDelayCount) { floor->resetDelayCount--; if(!floor->resetDelayCount) { floor->floorDestHeight = floor->resetHeight; floor->state = ((floor->state == FS_UP)? FS_DOWN : FS_UP); floor->resetDelay = 0; floor->delayCount = 0; floor->delayTotal = 0; } } if(floor->delayCount) { floor->delayCount--; if(!floor->delayCount && floor->material) { P_SetPtrp(floor->sector, DMU_FLOOR_MATERIAL, floor->material); } return; } #endif res = T_MovePlane(floor->sector, floor->speed, floor->floorDestHeight, floor->crush, 0, floor->state); #if __JHEXEN__ if(floor->type == FT_RAISEBUILDSTEP) { if((floor->state == FS_UP && P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) >= floor->stairsDelayHeight) || (floor->state == FS_DOWN && P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) <= floor->stairsDelayHeight)) { floor->delayCount = floor->delayTotal; floor->stairsDelayHeight += floor->stairsDelayHeightDelta; } } #endif #if !__JHEXEN__ if(!(mapTime & 7)) S_SectorSound(floor->sector, SORG_FLOOR, SFX_FLOORMOVE); #endif if(res == pastdest) { xsector_t *xsec = P_ToXSector(floor->sector); P_SetFloatp(floor->sector, DMU_FLOOR_SPEED, 0); #if __JHEXEN__ SN_StopSequence(P_GetPtrp(floor->sector, DMU_SOUND_ORIGIN)); #else # if __JHERETIC__ if(floor->type == FT_RAISEBUILDSTEP) # endif S_SectorSound(floor->sector, SORG_FLOOR, SFX_PSTOP); #endif #if __JHEXEN__ if(floor->delayTotal) floor->delayTotal = 0; if(floor->resetDelay) { // floor->resetDelayCount = floor->resetDelay; // floor->resetDelay = 0; return; } #endif xsec->specialData = NULL; #if __JHEXEN__ if(floor->material) { P_SetPtrp(floor->sector, DMU_FLOOR_MATERIAL, floor->material); } #else if(floor->state == FS_UP) { switch(floor->type) { case FT_RAISEDONUT: xsec->special = floor->newSpecial; P_SetPtrp(floor->sector, DMU_FLOOR_MATERIAL, floor->material); break; default: break; } } else if(floor->state == FS_DOWN) { switch(floor->type) { case FT_LOWERANDCHANGE: xsec->special = floor->newSpecial; P_SetPtrp(floor->sector, DMU_FLOOR_MATERIAL, floor->material); break; default: break; } } #endif #if __JHEXEN__ P_TagFinished(P_ToXSector(floor->sector)->tag); #endif DD_ThinkerRemove(&floor->thinker); } } typedef struct findlineinsectorsmallestbottommaterialparams_s { sector_t *baseSec; int minSize; linedef_t *foundLine; } findlineinsectorsmallestbottommaterialparams_t; int findLineInSectorSmallestBottomMaterial(void *ptr, void *context) { linedef_t* li = (linedef_t*) ptr; findlineinsectorsmallestbottommaterialparams_t* params = (findlineinsectorsmallestbottommaterialparams_t*) context; sector_t* frontSec, *backSec; frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR); backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(frontSec && backSec) { sidedef_t* side; material_t* mat; side = P_GetPtrp(li, DMU_SIDEDEF0); mat = P_GetPtrp(side, DMU_BOTTOM_MATERIAL); /** * Emulate DOOM.exe behaviour. In the instance where no material is * present, the height is taken from the very first texture. */ if(!mat) mat = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForIndex(0, MN_TEXTURES)); if(mat) { int height = P_GetIntp(mat, DMU_HEIGHT); if(height < params->minSize) { params->minSize = height; params->foundLine = li; } } side = P_GetPtrp(li, DMU_SIDEDEF1); mat = P_GetPtrp(side, DMU_BOTTOM_MATERIAL); if(!mat) mat = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForIndex(0, MN_TEXTURES)); if(mat) { int height = P_GetIntp(mat, DMU_HEIGHT); if(height < params->minSize) { params->minSize = height; params->foundLine = li; } } } return 1; // Continue iteration. } linedef_t* P_FindLineInSectorSmallestBottomMaterial(sector_t *sec, int *val) { findlineinsectorsmallestbottommaterialparams_t params; params.baseSec = sec; params.minSize = DDMAXINT; params.foundLine = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findLineInSectorSmallestBottomMaterial); if(val) *val = params.minSize; return params.foundLine; } #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ /** * Find the first sector which shares a border to the specified sector * and whose floor height matches that specified. * * @note Behaviour here is dependant upon the order of the sector-linked * LineDefs list. This is necessary to emulate the flawed algorithm used in * DOOM.exe In addition, this algorithm was further broken in Heretic as the * test which compares floor heights was removed. * * @important DO NOT USE THIS ANYWHERE ELSE! */ typedef struct findfirstneighbouratfloorheightparams_s { sector_t* baseSec; float height; sector_t* foundSec; } findfirstneighbouratfloorheightparams_t; static int findFirstNeighbourAtFloorHeight(void* ptr, void* context) { linedef_t* ln = (linedef_t*) ptr; findfirstneighbouratfloorheightparams_t* params = (findfirstneighbouratfloorheightparams_t*) context; sector_t* other; other = P_GetNextSector(ln, params->baseSec); # if __JDOOM__ || __JDOOM64__ if(other && P_GetFloatp(other, DMU_FLOOR_HEIGHT) == params->height) # elif __JHERETIC__ if(other) # endif { params->foundSec = other; return 0; // Stop iteration. } return 1; // Continue iteration. } static sector_t* findSectorSurroundingAtFloorHeight(sector_t* sec, float height) { findfirstneighbouratfloorheightparams_t params; params.baseSec = sec; params.foundSec = NULL; params.height = height; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findFirstNeighbourAtFloorHeight); return params.foundSec; } #endif /** * Handle moving floors. */ #if __JHEXEN__ int EV_DoFloor(linedef_t *line, byte *args, floortype_e floortype) #else int EV_DoFloor(linedef_t *line, floortype_e floortype) #endif { #if !__JHEXEN__ sector_t *frontsector; #endif int rtn = 0; xsector_t *xsec; sector_t *sec = NULL; floor_t *floor = NULL; iterlist_t *list; #if __JHEXEN__ int tag = (int) args[0]; #else int tag = P_ToXLine(line)->tag; #endif #if __JDOOM64__ // jd64 > bitmip? wha? float bitmipL = 0, bitmipR = 0; sidedef_t *front = P_GetPtrp(line, DMU_SIDEDEF0); sidedef_t *back = P_GetPtrp(line, DMU_SIDEDEF1); bitmipL = P_GetFloatp(front, DMU_MIDDLE_MATERIAL_OFFSET_X); if(back) bitmipR = P_GetFloatp(back, DMU_MIDDLE_MATERIAL_OFFSET_X); // < d64tc #endif list = P_GetSectorIterListForTag(tag, false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { xsec = P_ToXSector(sec); // If already moving, keep going... if(xsec->specialData) continue; rtn = 1; // New floor thinker. floor = Z_Calloc(sizeof(*floor), PU_MAP, 0); floor->thinker.function = T_MoveFloor; DD_ThinkerAdd(&floor->thinker); xsec->specialData = floor; floor->type = floortype; floor->crush = false; #if __JHEXEN__ floor->speed = (float) args[1] * (1.0 / 8); if(floortype == FT_LOWERMUL8INSTANT || floortype == FT_RAISEMUL8INSTANT) { floor->speed = 2000; } #endif switch(floortype) { case FT_LOWER: floor->state = FS_DOWN; floor->sector = sec; #if !__JHEXEN__ floor->speed = FLOORSPEED; # if __JDOOM64__ floor->speed *= 4; # endif #endif P_FindSectorSurroundingHighestFloor(sec, -500, &floor->floorDestHeight); break; case FT_LOWERTOLOWEST: floor->state = FS_DOWN; floor->sector = sec; #if !__JHEXEN__ floor->speed = FLOORSPEED; # if __JDOOM64__ floor->speed *= 4; # endif #endif P_FindSectorSurroundingLowestFloor(sec, P_GetFloatp(sec, DMU_FLOOR_HEIGHT), &floor->floorDestHeight); break; #if __JHEXEN__ case FT_LOWERBYVALUE: floor->state = FS_DOWN; floor->sector = sec; floor->floorDestHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) - (float) args[2]; break; case FT_LOWERMUL8INSTANT: case FT_LOWERBYVALUEMUL8: floor->state = FS_DOWN; floor->sector = sec; floor->floorDestHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) - (float) args[2] * 8; break; #endif #if !__JHEXEN__ case FT_LOWERTURBO: floor->state = FS_DOWN; floor->sector = sec; floor->speed = FLOORSPEED * 4; P_FindSectorSurroundingHighestFloor(sec, -500, &floor->floorDestHeight); # if __JHERETIC__ floor->floorDestHeight += 8; # else if(floor->floorDestHeight != P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) floor->floorDestHeight += 8; # endif break; #endif #if __JDOOM64__ case FT_TOHIGHESTPLUS8: // jd64 floor->state = FS_DOWN; floor->sector = sec; floor->speed = FLOORSPEED; P_FindSectorSurroundingHighestFloor(sec, -500, &floor->floorDestHeight); if(floor->floorDestHeight != P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) floor->floorDestHeight += 8; break; case FT_TOHIGHESTPLUSBITMIP: // jd64 if(bitmipR > 0) { floor->state = FS_DOWN; floor->sector = sec; floor->speed = FLOORSPEED * bitmipL; P_FindSectorSurroundingHighestFloor(sec, -500, &floor->floorDestHeight); if(floor->floorDestHeight != P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) floor->floorDestHeight += bitmipR; } else { floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED * bitmipL; floor->floorDestHeight = P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) - bitmipR; } break; case FT_CUSTOMCHANGESEC: // jd64 floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED * 16; floor->floorDestHeight = P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT); //// \kludge fake the engine into accepting this special P_ToXSector(sec)->special = bitmipR; // < KLUDGE break; #endif case FT_RAISEFLOORCRUSH: #if __JHEXEN__ floor->crush = (int) args[2]; // arg[2] = crushing value #else floor->crush = true; #endif floor->state = FS_UP; floor->sector = sec; #if !__JHEXEN__ floor->speed = FLOORSPEED; # if __JDOOM64__ floor->speed *= 4; # endif #endif #if __JHEXEN__ floor->floorDestHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT)-8; #else P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &floor->floorDestHeight); if(floor->floorDestHeight > P_GetFloatp(sec, DMU_CEILING_HEIGHT)) floor->floorDestHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT); floor->floorDestHeight -= 8 * (floortype == FT_RAISEFLOORCRUSH); #endif break; case FT_RAISEFLOOR: floor->state = FS_UP; floor->sector = sec; #if !__JHEXEN__ floor->speed = FLOORSPEED; # if __JDOOM64__ floor->speed *= 4; # endif #endif P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &floor->floorDestHeight); if(floor->floorDestHeight > P_GetFloatp(sec, DMU_CEILING_HEIGHT)) floor->floorDestHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT); #if !__JHEXEN__ floor->floorDestHeight -= 8 * (floortype == FT_RAISEFLOORCRUSH); #endif break; #if __JDOOM__ || __JDOOM64__ case FT_RAISEFLOORTURBO: floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED * 4; # if __JDOOM64__ floor->speed *= 2; # endif { float floorHeight, nextFloor; floorHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); if(P_FindSectorSurroundingNextHighestFloor(sec, floorHeight, &nextFloor)) floor->floorDestHeight = nextFloor; else floor->floorDestHeight = floorHeight; } break; #endif case FT_RAISEFLOORTONEAREST: floor->state = FS_UP; floor->sector = sec; #if !__JHEXEN__ floor->speed = FLOORSPEED; # if __JDOOM64__ floor->speed *= 8; # endif #endif { float floorHeight, nextFloor; floorHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); if(P_FindSectorSurroundingNextHighestFloor(sec, floorHeight, &nextFloor)) floor->floorDestHeight = nextFloor; else floor->floorDestHeight = floorHeight; } break; #if __JHEXEN__ case FT_RAISEFLOORBYVALUE: floor->state = FS_UP; floor->sector = sec; floor->floorDestHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + (float) args[2]; break; case FT_RAISEMUL8INSTANT: case FT_RAISEBYVALUEMUL8: floor->state = FS_UP; floor->sector = sec; floor->floorDestHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + (float) args[2] * 8; break; case FT_TOVALUEMUL8: floor->sector = sec; floor->floorDestHeight = (float) args[2] * 8; if(args[3]) floor->floorDestHeight = -floor->floorDestHeight; if(floor->floorDestHeight > P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) floor->state = FS_UP; else if(floor->floorDestHeight < P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) floor->state = FS_DOWN; else rtn = 0; // Already at lowest position. break; #endif #if !__JHEXEN__ case FT_RAISE24: floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED; # if __JDOOM64__ floor->speed *= 8; # endif floor->floorDestHeight = P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) + 24; break; #endif #if !__JHEXEN__ case FT_RAISE24ANDCHANGE: floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED; # if __JDOOM64__ floor->speed *= 8; # endif floor->floorDestHeight = P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) + 24; frontsector = P_GetPtrp(line, DMU_FRONT_SECTOR); P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_GetPtrp(frontsector, DMU_FLOOR_MATERIAL)); xsec->special = P_ToXSector(frontsector)->special; break; #if __JDOOM__ || __JDOOM64__ case FT_RAISE512: floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED; floor->floorDestHeight = P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) + 512; break; #endif # if __JDOOM64__ case FT_RAISE32: // jd64 floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED * 8; floor->floorDestHeight = P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) + 32; break; # endif case FT_RAISETOTEXTURE: { int minSize = DDMAXINT; floor->state = FS_UP; floor->sector = sec; floor->speed = FLOORSPEED; P_FindLineInSectorSmallestBottomMaterial(sec, &minSize); floor->floorDestHeight = P_GetFloatp(floor->sector, DMU_FLOOR_HEIGHT) + (float) minSize; } break; case FT_LOWERANDCHANGE: floor->state = FS_DOWN; floor->sector = sec; floor->speed = FLOORSPEED; P_FindSectorSurroundingLowestFloor(sec, P_GetFloatp(sec, DMU_FLOOR_HEIGHT), &floor->floorDestHeight); floor->material = P_GetPtrp(sec, DMU_FLOOR_MATERIAL); { sector_t* otherSec = findSectorSurroundingAtFloorHeight(sec, floor->floorDestHeight); if(otherSec) { floor->material = P_GetPtrp(otherSec, DMU_FLOOR_MATERIAL); floor->newSpecial = P_ToXSector(otherSec)->special; } } break; #endif default: #if __JHEXEN__ rtn = 0; #endif break; } } #if __JHEXEN__ if(rtn && floor) { SN_StartSequence(P_GetPtrp(floor->sector, DMU_SOUND_ORIGIN), SEQ_PLATFORM + P_ToXSector(floor->sector)->seqType); } #endif return rtn; } #if __JHEXEN__ typedef struct { int type; float height; } findsectorneighborsforstairbuildparams_t; static int findSectorNeighborsForStairBuild(void* ptr, void* context) { linedef_t* li = (linedef_t*) ptr; findsectorneighborsforstairbuildparams_t* params = (findsectorneighborsforstairbuildparams_t*) context; sector_t* frontSec, *backSec; xsector_t* xsec; frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR); if(!frontSec) return 1; // Continue iteration. backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(!backSec) return 1; // Continue iteration. xsec = P_ToXSector(frontSec); if(xsec->special == params->type + STAIR_SECTOR_TYPE && !xsec->specialData && P_GetPtrp(frontSec, DMU_FLOOR_MATERIAL) == stairData.material && P_GetIntp(frontSec, DMU_VALID_COUNT) != VALIDCOUNT) { enqueueStairSector(frontSec, params->type ^ 1, params->height); P_SetIntp(frontSec, DMU_VALID_COUNT, VALIDCOUNT); } xsec = P_ToXSector(backSec); if(xsec->special == params->type + STAIR_SECTOR_TYPE && !xsec->specialData && P_GetPtrp(backSec, DMU_FLOOR_MATERIAL) == stairData.material && P_GetIntp(backSec, DMU_VALID_COUNT) != VALIDCOUNT) { enqueueStairSector(backSec, params->type ^ 1, params->height); P_SetIntp(backSec, DMU_VALID_COUNT, VALIDCOUNT); } return 1; // Continue iteration. } #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ /** * @note Behaviour here is dependant upon the order of the sector-linked * LineDefs list. This is necessary to emulate the flawed algorithm used in * DOOM.exe In addition, this algorithm was further broken in Heretic as the * test which compares floor heights was removed. * * @important DO NOT USE THIS ANYWHERE ELSE! */ typedef struct spreadsectorparams_s { sector_t* baseSec; material_t* material; sector_t* foundSec; float height, stairSize; } spreadsectorparams_t; int findAdjacentSectorForSpread(void* ptr, void* context) { linedef_t* li = (linedef_t*) ptr; spreadsectorparams_t* params = (spreadsectorparams_t*) context; sector_t* frontSec, *backSec; xsector_t* xsec; frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR); if(!frontSec) return 1; // Continue iteration. if(params->baseSec != frontSec) return 1; // Continue iteration. backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(!backSec) return 1; // Continue iteration. if(P_GetPtrp(backSec, DMU_FLOOR_MATERIAL) != params->material) return 1; // Continue iteration. /** * @note The placement of this step height addition is vital to ensure * the exact behaviour of the original DOOM algorithm. Logically this * should occur after the test below... */ params->height += params->stairSize; xsec = P_ToXSector(backSec); if(xsec->specialData) return 1; // Continue iteration. // This looks good. params->foundSec = backSec; return 0; // Stop iteration. } #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ int EV_BuildStairs(linedef_t* line, stair_e type) { int rtn = 0; xsector_t* xsec; sector_t* sec = NULL; floor_t* floor; float height = 0, stairsize = 0; float speed = 0; iterlist_t* list; spreadsectorparams_t params; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { xsec = P_ToXSector(sec); // Already moving? If so, keep going... if(xsec->specialData) continue; // New floor thinker. rtn = 1; floor = Z_Calloc(sizeof(*floor), PU_MAP, 0); floor->thinker.function = T_MoveFloor; DD_ThinkerAdd(&floor->thinker); xsec->specialData = floor; floor->state = FS_UP; floor->sector = sec; switch(type) { #if __JHERETIC__ case build8: stairsize = 8; break; case build16: stairsize = 16; break; #else case build8: speed = FLOORSPEED * .25; stairsize = 8; break; case turbo16: speed = FLOORSPEED * 4; stairsize = 16; break; #endif default: break; } #if __JHERETIC__ floor->type = FT_RAISEBUILDSTEP; speed = FLOORSPEED; floor->speed = speed; #else floor->speed = speed; #endif height = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + stairsize; floor->floorDestHeight = height; // Find next sector to raise. // 1. Find 2-sided line with a front side in the same sector. // 2. Other side is the next sector to raise. params.baseSec = sec; params.material = P_GetPtrp(sec, DMU_FLOOR_MATERIAL); params.foundSec = NULL; params.height = height; params.stairSize = stairsize; while(!P_Iteratep(params.baseSec, DMU_LINEDEF, ¶ms, findAdjacentSectorForSpread)) { // We found another sector to spread to. floor = Z_Calloc(sizeof(*floor), PU_MAP, 0); floor->thinker.function = T_MoveFloor; DD_ThinkerAdd(&floor->thinker); P_ToXSector(params.foundSec)->specialData = floor; #if __JHERETIC__ floor->type = FT_RAISEBUILDSTEP; #endif floor->state = FS_UP; floor->speed = speed; floor->sector = params.foundSec; floor->floorDestHeight = params.height; // Prepare for the next pass. params.baseSec = params.foundSec; params.foundSec = NULL; } } return rtn; } #endif #if __JHEXEN__ static void enqueueStairSector(sector_t *sec, int type, float height) { if((stairQueueTail + 1) % STAIR_QUEUE_SIZE == stairQueueHead) { Con_Error("BuildStairs: Too many branches located.\n"); } stairQueue[stairQueueTail].sector = sec; stairQueue[stairQueueTail].type = type; stairQueue[stairQueueTail].height = height; stairQueueTail = (stairQueueTail + 1) % STAIR_QUEUE_SIZE; } static sector_t *dequeueStairSector(int *type, float *height) { sector_t *sec; if(stairQueueHead == stairQueueTail) { // Queue is empty. return NULL; } *type = stairQueue[stairQueueHead].type; *height = stairQueue[stairQueueHead].height; sec = stairQueue[stairQueueHead].sector; stairQueueHead = (stairQueueHead + 1) % STAIR_QUEUE_SIZE; return sec; } static void processStairSector(sector_t *sec, int type, float height, stairs_e stairsType, int delay, int resetDelay) { floor_t *floor; findsectorneighborsforstairbuildparams_t params; height += stairData.stepDelta; floor = Z_Calloc(sizeof(*floor), PU_MAP, 0); floor->thinker.function = T_MoveFloor; DD_ThinkerAdd(&floor->thinker); P_ToXSector(sec)->specialData = floor; floor->type = FT_RAISEBUILDSTEP; floor->state = (stairData.direction == -1? FS_DOWN : FS_UP); floor->sector = sec; floor->floorDestHeight = height; switch(stairsType) { case STAIRS_NORMAL: floor->speed = stairData.speed; if(delay) { floor->delayTotal = delay; floor->stairsDelayHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + stairData.stepDelta; floor->stairsDelayHeightDelta = stairData.stepDelta; } floor->resetDelay = resetDelay; floor->resetDelayCount = resetDelay; floor->resetHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); break; case STAIRS_SYNC: floor->speed = stairData.speed * ((height - stairData.startHeight) / stairData.stepDelta); floor->resetDelay = delay; //arg4 floor->resetDelayCount = delay; floor->resetHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); break; default: break; } SN_StartSequence(P_GetPtrp(sec, DMU_SOUND_ORIGIN), SEQ_PLATFORM + P_ToXSector(sec)->seqType); params.type = type; params.height = height; // Find all neigboring sectors with sector special equal to type and add // them to the stairbuild queue. P_Iteratep(sec, DMU_LINEDEF, ¶ms, findSectorNeighborsForStairBuild); } #endif /** * @param direction Positive = up. Negative = down. */ #if __JHEXEN__ int EV_BuildStairs(linedef_t* line, byte* args, int direction, stairs_e stairsType) { float height; int delay; int type; int resetDelay; sector_t* sec = NULL, *qSec; iterlist_t* list; // Set global stairs variables stairData.textureChange = 0; stairData.direction = direction; stairData.stepDelta = stairData.direction * (float) args[2]; stairData.speed = (float) args[1] * (1.0 / 8); resetDelay = (int) args[4]; delay = (int) args[3]; if(stairsType == STAIRS_PHASED) { stairData.startDelay = stairData.startDelayDelta = (int) args[3]; resetDelay = stairData.startDelayDelta; delay = 0; stairData.textureChange = (int) args[4]; } VALIDCOUNT++; list = P_GetSectorIterListForTag((int) args[0], false); if(!list) return 0; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { stairData.material = P_GetPtrp(sec, DMU_FLOOR_MATERIAL); stairData.startHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); // ALREADY MOVING? IF SO, KEEP GOING... if(P_ToXSector(sec)->specialData) continue; // Already moving, so keep going... enqueueStairSector(sec, 0, P_GetFloatp(sec, DMU_FLOOR_HEIGHT)); P_ToXSector(sec)->special = 0; } while((qSec = dequeueStairSector(&type, &height)) != NULL) { processStairSector(qSec, type, height, stairsType, delay, resetDelay); } return 1; } #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ typedef struct { sector_t* sector; linedef_t* foundLineDef; } findfirsttwosidedparams_t; int findFirstTwosided(void *ptr, void *context) { linedef_t* li = (linedef_t*) ptr; findfirsttwosidedparams_t* params = (findfirsttwosidedparams_t*) context; sector_t* backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(backSec && !(params->sector && backSec == params->sector)) { params->foundLineDef = li; return 0; // Stop iteration, this will do. } return 1; // Continue iteration. } #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ int EV_DoDonut(linedef_t* line) { int rtn = 0; sector_t* sec, *outer, *ring; iterlist_t* list; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { findfirsttwosidedparams_t params; // Already moving? If so, keep going... if(P_ToXSector(sec)->specialData) continue; rtn = 1; outer = ring = NULL; params.sector = NULL; params.foundLineDef = NULL; if(!P_Iteratep(sec, DMU_LINEDEF, ¶ms, findFirstTwosided)) { ring = P_GetPtrp(params.foundLineDef, DMU_BACK_SECTOR); if(ring == sec) ring = P_GetPtrp(params.foundLineDef, DMU_FRONT_SECTOR); params.sector = sec; params.foundLineDef = NULL; if(!P_Iteratep(ring, DMU_LINEDEF, ¶ms, findFirstTwosided)) outer = P_GetPtrp(params.foundLineDef, DMU_BACK_SECTOR); } if(outer && ring) { // Found both parts of the donut. floor_t* floor; float destHeight = P_GetFloatp(outer, DMU_FLOOR_HEIGHT); // Spawn rising slime. floor = Z_Calloc(sizeof(*floor), PU_MAP, 0); floor->thinker.function = T_MoveFloor; DD_ThinkerAdd(&floor->thinker); P_ToXSector(ring)->specialData = floor; floor->type = FT_RAISEDONUT; floor->crush = false; floor->state = FS_UP; floor->sector = ring; floor->speed = FLOORSPEED * .5; floor->material = P_GetPtrp(outer, DMU_FLOOR_MATERIAL); floor->newSpecial = 0; floor->floorDestHeight = destHeight; // Spawn lowering donut-hole. floor = Z_Calloc(sizeof(*floor), PU_MAP, 0); floor->thinker.function = T_MoveFloor; DD_ThinkerAdd(&floor->thinker); P_ToXSector(sec)->specialData = floor; floor->type = FT_LOWER; floor->crush = false; floor->state = FS_DOWN; floor->sector = sec; floor->speed = FLOORSPEED * .5; floor->floorDestHeight = destHeight; } } return rtn; } #endif #if __JHEXEN__ static boolean stopFloorCrush(thinker_t* th, void* context) { boolean* found = (boolean*) context; floor_t* floor = (floor_t *) th; if(floor->type == FT_RAISEFLOORCRUSH) { // Completely remove the crushing floor SN_StopSequence(P_GetPtrp(floor->sector, DMU_SOUND_ORIGIN)); P_ToXSector(floor->sector)->specialData = NULL; P_TagFinished(P_ToXSector(floor->sector)->tag); DD_ThinkerRemove(&floor->thinker); (*found) = true; } return true; // Continue iteration. } int EV_FloorCrushStop(linedef_t* line, byte* args) { boolean found = false; DD_IterateThinkers(T_MoveFloor, stopFloorCrush, &found); return (found? 1 : 0); } #endif #if __JHEXEN__ || __JDOOM64__ # if __JHEXEN__ int EV_DoFloorAndCeiling(linedef_t *line, byte *args, int ftype, int ctype) # else int EV_DoFloorAndCeiling(linedef_t* line, int ftype, int ctype) # endif { # if __JHEXEN__ int tag = (int) args[0]; # else int tag = P_ToXLine(line)->tag; # endif boolean floor, ceiling; sector_t* sec = NULL; iterlist_t* list; list = P_GetSectorIterListForTag(tag, false); if(!list) return 0; /** \kludge * Due to the fact that sectors can only have one special thinker * linked at a time, this routine manually removes the link before * then creating a second thinker for the sector. * In order to commonize this we should maintain seperate links in * xsector_t for each type of special (not thinker type) i.e: * * floor, ceiling, lightlevel * * Note: floor and ceiling are capable of moving at different speeds * and with different target heights, we must remain compatible. */ # if __JHEXEN__ floor = EV_DoFloor(line, args, ftype); # else floor = EV_DoFloor(line, ftype); # endif P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { P_ToXSector(sec)->specialData = NULL; } # if __JHEXEN__ ceiling = EV_DoCeiling(line, args, ctype); # else ceiling = EV_DoCeiling(line, ctype); # endif // < KLUDGE return (floor | ceiling); } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_tick.c0000644000175000017500000001151511357170242022245 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_tick.c: Top-level tick stuff. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "p_actor.h" #include "g_common.h" #include "g_controls.h" #include "p_player.h" #include "p_user.h" #include "hu_menu.h" #include "hu_msg.h" #include "d_netsv.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void P_ClientSideThink(void); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int mapTime; int actualMapTime; int timerGame; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * @return @c true, if the game is currently paused. */ boolean P_IsPaused(void) { return paused || (!IS_NETGAME && (Hu_MenuIsActive() || Hu_IsMessageActive())); } /** * This is called at all times, no matter gamestate. */ void P_RunPlayers(timespan_t ticLength) { uint i; boolean isPaused = P_IsPaused(); //ticcmd_t command; //boolean gotCommands; // This is not for clients. if(IS_CLIENT) return; // Each player gets to think one cmd. // For the local player, this is always the cmd of the current tick. // For remote players, this might be a predicted cmd or a real cmd // from the past. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) { /* // We will combine all the waiting commands into this // buffer. memset(&command, 0, sizeof(command)); // Get all the commands for the player. gotCommands = false; while(Net_GetTicCmd(&players[i].plr->cmd, i)) { P_MergeCommand(&command, &players[i].plr->cmd); gotCommands = true; // Local players run one tic at a time. if(players[i].plr->flags & DDPF_LOCAL) break; } if(gotCommands) { // The new merged command will be the one that the // player uses for thinking on this tick. memcpy(&players[i].plr->cmd, &command, sizeof(command)); } // Check for special buttons (pause and netsave). G_SpecialButton(i); */ // The player thinks. P_PlayerThink(&players[i], ticLength); } } /** * Called 35 times per second. * The heart of play sim. */ void P_DoTick(void) { // If the game is paused, nothing will happen. if(paused) return; actualMapTime++; if(!IS_CLIENT && timerGame && !paused) { if(!--timerGame) { G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); } } // Pause if in menu and at least one tic has been run. if(!IS_NETGAME && (Hu_MenuIsActive() || Hu_IsMessageActive()) && !Get(DD_PLAYBACK) && mapTime > 1) return; DD_RunThinkers(); P_UpdateSpecials(); #if __JDOOM64__ P_ThunderSector(); #endif P_DoDeferredSpawns(); #if __JHERETIC__ P_AmbientSound(); #endif #if __JHEXEN__ P_AnimateSurfaces(); #endif P_ClientSideThink(); // For par times, among other things. mapTime++; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_switch.c0000644000175000017500000003457511357170242022627 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_switch.c: Switches, buttons. Two-state animation. Exits. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "d_net.h" #include "dmu_lib.h" #include "p_plat.h" #include "p_switch.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- #if __JHEXEN__ switchlist_t switchInfo[] = { {"SW_1_UP", "SW_1_DN", SFX_SWITCH1}, {"SW_2_UP", "SW_2_DN", SFX_SWITCH1}, {"VALVE1", "VALVE2", SFX_VALVE_TURN}, {"SW51_OFF", "SW51_ON", SFX_SWITCH2}, {"SW52_OFF", "SW52_ON", SFX_SWITCH2}, {"SW53_UP", "SW53_DN", SFX_ROPE_PULL}, {"PUZZLE5", "PUZZLE9", SFX_SWITCH1}, {"PUZZLE6", "PUZZLE10", SFX_SWITCH1}, {"PUZZLE7", "PUZZLE11", SFX_SWITCH1}, {"PUZZLE8", "PUZZLE12", SFX_SWITCH1}, {"\0", "\0", 0} }; #else // This array is treated as a hardcoded replacement for data that can be loaded // from a lump, so we need to use little-endian byte ordering. switchlist_t switchInfo[] = { # if __JHERETIC__ {"SW1OFF", "SW1ON", MACRO_SHORT(1)}, {"SW2OFF", "SW2ON", MACRO_SHORT(1)}, # elif __JDOOM64__ {"SWXCA", "SWXCB", MACRO_SHORT(1)}, {"SWXCKA", "SWXCKB", MACRO_SHORT(1)}, {"SWXCKLA", "SWXCKLB", MACRO_SHORT(1)}, {"SWXCLA", "SWXCLB", MACRO_SHORT(1)}, {"SWXHCA", "SWXHCB", MACRO_SHORT(1)}, {"SWXSAA", "SWXSAB", MACRO_SHORT(1)}, {"SWXSCA", "SWXSCB", MACRO_SHORT(1)}, {"SWXSDA", "SWXSDB", MACRO_SHORT(1)}, {"SWXSEA", "SWXSEB", MACRO_SHORT(1)}, {"SWXSFA", "SWXSFB", MACRO_SHORT(1)}, {"SWXSGA", "SWXSGB", MACRO_SHORT(1)}, # elif __JDOOM__ // Doom shareware episode 1 switches {"SW1BRCOM", "SW2BRCOM", MACRO_SHORT(1)}, {"SW1BRN1", "SW2BRN1", MACRO_SHORT(1)}, {"SW1BRN2", "SW2BRN2", MACRO_SHORT(1)}, {"SW1BRNGN", "SW2BRNGN", MACRO_SHORT(1)}, {"SW1BROWN", "SW2BROWN", MACRO_SHORT(1)}, {"SW1COMM", "SW2COMM", MACRO_SHORT(1)}, {"SW1COMP", "SW2COMP", MACRO_SHORT(1)}, {"SW1DIRT", "SW2DIRT", MACRO_SHORT(1)}, {"SW1EXIT", "SW2EXIT", MACRO_SHORT(1)}, {"SW1GRAY", "SW2GRAY", MACRO_SHORT(1)}, {"SW1GRAY1", "SW2GRAY1", MACRO_SHORT(1)}, {"SW1METAL", "SW2METAL", MACRO_SHORT(1)}, {"SW1PIPE", "SW2PIPE", MACRO_SHORT(1)}, {"SW1SLAD", "SW2SLAD", MACRO_SHORT(1)}, {"SW1STARG", "SW2STARG", MACRO_SHORT(1)}, {"SW1STON1", "SW2STON1", MACRO_SHORT(1)}, {"SW1STON2", "SW2STON2", MACRO_SHORT(1)}, {"SW1STONE", "SW2STONE", MACRO_SHORT(1)}, {"SW1STRTN", "SW2STRTN", MACRO_SHORT(1)}, // Doom registered episodes 2&3 switches {"SW1BLUE", "SW2BLUE", MACRO_SHORT(2)}, {"SW1CMT", "SW2CMT", MACRO_SHORT(2)}, {"SW1GARG", "SW2GARG", MACRO_SHORT(2)}, {"SW1GSTON", "SW2GSTON", MACRO_SHORT(2)}, {"SW1HOT", "SW2HOT", MACRO_SHORT(2)}, {"SW1LION", "SW2LION", MACRO_SHORT(2)}, {"SW1SATYR", "SW2SATYR", MACRO_SHORT(2)}, {"SW1SKIN", "SW2SKIN", MACRO_SHORT(2)}, {"SW1VINE", "SW2VINE", MACRO_SHORT(2)}, {"SW1WOOD", "SW2WOOD", MACRO_SHORT(2)}, // Doom II switches {"SW1PANEL", "SW2PANEL", MACRO_SHORT(3)}, {"SW1ROCK", "SW2ROCK", MACRO_SHORT(3)}, {"SW1MET2", "SW2MET2", MACRO_SHORT(3)}, {"SW1WDMET", "SW2WDMET", MACRO_SHORT(3)}, {"SW1BRIK", "SW2BRIK", MACRO_SHORT(3)}, {"SW1MOD1", "SW2MOD1", MACRO_SHORT(3)}, {"SW1ZIM", "SW2ZIM", MACRO_SHORT(3)}, {"SW1STON6", "SW2STON6", MACRO_SHORT(3)}, {"SW1TEK", "SW2TEK", MACRO_SHORT(3)}, {"SW1MARB", "SW2MARB", MACRO_SHORT(3)}, {"SW1SKULL", "SW2SKULL", MACRO_SHORT(3)}, # endif {"\0", "\0", MACRO_SHORT(0)} }; #endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ static material_t** switchlist; static int max_numswitches; static int numswitches; // CODE -------------------------------------------------------------------- /** * Called at game initialization or when the engine's state must be updated * (eg a new WAD is loaded at runtime). This routine will populate the list * of known switches and buttons. This enables their texture to change when * activated, and in the case of buttons, change back after a timeout. */ #if __JHEXEN__ void P_InitSwitchList(void) { int i; int index; for(index = 0, i = 0; ; ++i) { if(index+1 >= max_numswitches) { switchlist = realloc(switchlist, sizeof(*switchlist) * (max_numswitches = max_numswitches ? max_numswitches*2 : 8)); } if(!switchInfo[i].soundID) break; switchlist[index++] = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(switchInfo[i].name1, MN_TEXTURES)); switchlist[index++] = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(switchInfo[i].name2, MN_TEXTURES)); } numswitches = index / 2; switchlist[index] = NULL; } #else /** * Called at game initialization or when the engine's state must be updated * (eg a new WAD is loaded at runtime). This routine will populate the list * of known switches and buttons. This enables their texture to change when * activated, and in the case of buttons, change back after a timeout. * * This routine modified to read its data from a predefined lump or * PWAD lump called SWITCHES rather than a static table in this module to * allow wad designers to insert or modify switches. * * Lump format is an array of byte packed switchlist_t structures, terminated * by a structure with episode == -0. The lump can be generated from a * text source file using SWANTBLS.EXE, distributed with the BOOM utils. * The standard list of switches and animations is contained in the example * source text file DEFSWANI.DAT also in the BOOM util distribution. */ /* * DJS - We'll support this BOOM extension but we should discourage it's use * and instead implement a better method for creating new switches. */ void P_InitSwitchList(void) { int i, index, episode; int lump = W_CheckNumForName("SWITCHES"); switchlist_t *sList = switchInfo; # if __JHERETIC__ if(gameMode == shareware) episode = 1; else episode = 2; # else # if __JDOOM__ if(gameMode == registered || gameMode == retail) episode = 2; else if(gameMode == commercial) episode = 3; else # endif episode = 1; # endif // Has a custom SWITCHES lump been loaded? if(lump > 0) { Con_Message("P_InitSwitchList: \"SWITCHES\" lump found. Reading switches...\n"); sList = (switchlist_t *) W_CacheLumpNum(lump, PU_STATIC); } for(index = 0, i = 0; ; ++i) { if(index+1 >= max_numswitches) { switchlist = realloc(switchlist, sizeof(*switchlist) * (max_numswitches = max_numswitches ? max_numswitches*2 : 8)); } if(SHORT(sList[i].episode) <= episode) { if(!SHORT(sList[i].episode)) break; switchlist[index++] = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(sList[i].name1, MN_TEXTURES)); switchlist[index++] = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(sList[i].name2, MN_TEXTURES)); VERBOSE(Con_Message("P_InitSwitchList: ADD (\"%s\" | \"%s\" #%d)\n", sList[i].name1, sList[i].name2, SHORT(sList[i].episode))); } } numswitches = index / 2; switchlist[index] = NULL; } #endif material_t* P_GetSwitch(material_t* mat, const switchlist_t** info) { int i; if(!mat) return NULL; for(i = 0; i < numswitches * 2; ++i) { if(switchlist[i] == mat) { if(info) *info = &switchInfo[i / 2]; return switchlist[i^1]; } } return NULL; } void T_MaterialChanger(materialchanger_t* mchanger) { if(!(--mchanger->timer)) { P_SetPtrp(mchanger->side, mchanger->ssurfaceID == SID_MIDDLE? DMU_MIDDLE_MATERIAL : mchanger->ssurfaceID == SID_TOP? DMU_TOP_MATERIAL : DMU_BOTTOM_MATERIAL, mchanger->material); #if __JDOOM__ || __JDOOM64__ S_StartSound(SFX_SWTCHN, P_GetPtrp( P_GetPtrp(mchanger->side, DMU_SECTOR), DMU_SOUND_ORIGIN)); #elif __JHERETIC__ S_StartSound(SFX_SWITCH, P_GetPtrp( P_GetPtrp(mchanger->side, DMU_SECTOR), DMU_SOUND_ORIGIN)); #endif DD_ThinkerRemove(&mchanger->thinker); } } void P_SpawnMaterialChanger(sidedef_t* side, sidedefsurfaceid_t ssurfaceID, material_t* mat, int tics) { materialchanger_t* mchanger; mchanger = Z_Calloc(sizeof(*mchanger), PU_MAP, 0); mchanger->thinker.function = T_MaterialChanger; DD_ThinkerAdd(&mchanger->thinker); mchanger->side = side; mchanger->ssurfaceID = ssurfaceID; mchanger->material = mat; mchanger->timer = tics; } typedef struct { sidedef_t* side; sidedefsurfaceid_t ssurfaceID; } findmaterialchangerparams_t; boolean findMaterialChanger(thinker_t* th, void* data) { materialchanger_t* mchanger = (materialchanger_t*) th; findmaterialchangerparams_t* params = (findmaterialchangerparams_t*) data; if(mchanger->side == params->side && mchanger->ssurfaceID == params->ssurfaceID) return false; // Stop iteration. return true; // Keep looking. } void P_StartButton(sidedef_t* side, sidedefsurfaceid_t ssurfaceID, material_t* mat, int tics) { findmaterialchangerparams_t params; params.side = side; params.ssurfaceID = ssurfaceID; // See if a material change has already been queued. if(!DD_IterateThinkers(T_MaterialChanger, findMaterialChanger, ¶ms)) return; P_SpawnMaterialChanger(side, ssurfaceID, mat, tics); } /** * @param side Sidedef where the surface to be changed is found. * @param ssurfaceID Id of the sidedef surface to be changed. * @param sound If non-zero, play this sound, ELSE the sound to * play will be taken from the switchinfo. Note that * a sound will play iff a switch state change occurs * and param silent is non-zero. * @param silent @c true = no sound will be played. * @param tics @c <= 0 = A permanent change. * @c > 0 = Change back after this many tics. */ boolean P_ToggleSwitch2(sidedef_t* side, sidedefsurfaceid_t ssurfaceID, int sound, boolean silent, int tics) { material_t* mat, *current; const switchlist_t* info; current = P_GetPtrp(side, ssurfaceID == SID_MIDDLE? DMU_MIDDLE_MATERIAL : ssurfaceID == SID_TOP? DMU_TOP_MATERIAL : DMU_BOTTOM_MATERIAL); if((mat = P_GetSwitch(current, &info))) { if(!silent) { // \todo Get these defaults from switchinfo. if(!sound) { #if __JHEXEN__ sound = info->soundID; #elif __JHERETIC__ sound = SFX_SWITCH; #else sound = SFX_SWTCHN; #endif } S_StartSound(sound, P_GetPtrp(P_GetPtrp(side, DMU_SECTOR), DMU_SOUND_ORIGIN)); } P_SetPtrp(side, ssurfaceID == SID_MIDDLE? DMU_MIDDLE_MATERIAL : ssurfaceID == SID_TOP? DMU_TOP_MATERIAL : DMU_BOTTOM_MATERIAL, mat); if(tics > 0) P_StartButton(side, ssurfaceID, current, tics); return true; } return false; } /** * @param side Sidedef where the switch to be changed is found. * @param sound If non-zero, play this sound, ELSE the sound to * play will be taken from the switchinfo. Note that * a sound will play iff a switch state change occurs * and param silent is non-zero. * @param silent @c true = no sound will be played. * @param tics @c <= 0 = A permanent change. * @c > 0 = Change back after this many tics. */ boolean P_ToggleSwitch(sidedef_t* side, int sound, boolean silent, int tics) { if(P_ToggleSwitch2(side, SID_TOP, sound, silent, tics)) return true; if(P_ToggleSwitch2(side, SID_MIDDLE, sound, silent, tics)) return true; if(P_ToggleSwitch2(side, SID_BOTTOM, sound, silent, tics)) return true; return false; } #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ /** * Called when a mobj "uses" a linedef. */ boolean P_UseSpecialLine(mobj_t* mo, linedef_t* line, int side) { // Extended functionality overrides old. if(XL_UseLine(line, side, mo)) return true; return P_UseSpecialLine2(mo, line, side); } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_mapsetup.c0000644000175000017500000007417711357170242023166 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.c: Common map setup routines. * * Management of extended map data objects (eg xlines) is done here */ // HEADER FILES ------------------------------------------------------------ #include #include // has isspace #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" # include "hu_stuff.h" #elif __JHEXEN__ # include "jhexen.h" # include "p_start.h" #endif #include "p_actor.h" #include "dmu_lib.h" #include "r_common.h" #include "p_mapsetup.h" #include "am_map.h" #include "p_tick.h" #include "p_start.h" #include "hu_pspr.h" // MACROS ------------------------------------------------------------------ #if __JDOOM64__ # define TOLIGHTIDX(c) (!((c) >> 8)? 0 : ((c) - 0x100) + 1) #endif // TYPES ------------------------------------------------------------------- typedef struct { int gameModeBits; mobjtype_t type; } mobjtype_precachedata_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void P_ResetWorldState(void); static void P_FinalizeMap(void); static void P_PrintMapBanner(uint episode, uint map); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Our private map data structures xsector_t* xsectors; xline_t* xlines; // If true we are in the process of setting up a map boolean mapSetup; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Converts a line to an xline. */ xline_t* P_ToXLine(linedef_t* line) { if(!line) return NULL; // Is it a dummy? if(P_IsDummy(line)) { return P_DummyExtraData(line); } else { return &xlines[P_ToIndex(line)]; } } /** * Converts a sector to an xsector. */ xsector_t* P_ToXSector(sector_t* sector) { if(!sector) return NULL; // Is it a dummy? if(P_IsDummy(sector)) { return P_DummyExtraData(sector); } else { return &xsectors[P_ToIndex(sector)]; } } /** * Given a subsector - find its parent xsector. */ xsector_t* P_ToXSectorOfSubsector(subsector_t* sub) { sector_t* sec; if(!sub) return NULL; sec = P_GetPtrp(sub, DMU_SECTOR); // Is it a dummy? if(P_IsDummy(sec)) { return P_DummyExtraData(sec); } else { return &xsectors[P_ToIndex(sec)]; } } /** * Given the index of an xline, return it. * * \note: This routine cannot be used with dummy lines! * * @param Index of the xline to return. * * @return Ptr to xline_t. */ xline_t* P_GetXLine(uint index) { if(index >= numlines) return NULL; return &xlines[index]; } /** * Given the index of an xsector, return it. * * \note: This routine cannot be used with dummy sectors! * * @param Index of the xsector to return. * * @return Ptr to xsector_t. */ xsector_t* P_GetXSector(uint index) { if(index >= numsectors) return NULL; return &xsectors[index]; } /** * Doomsday calls this (before any data is read) for each type of map object * at the start of the map load process. This is to allow us (the game) to * do any initialization we need. For example if we maintain our own data * for lines (the xlines) we'll do all allocation and init here. * * @param type (DMU object type) The id of the data type being setup. * @param num The number of elements of "type" Doomsday is creating. */ void P_SetupForMapData(int type, uint num) { switch(type) { case DMU_SECTOR: if(num > 0) xsectors = Z_Calloc(num * sizeof(xsector_t), PU_MAP, 0); else xsectors = NULL; break; case DMU_LINEDEF: if(num > 0) xlines = Z_Calloc(num * sizeof(xline_t), PU_MAP, 0); else xlines = NULL; break; default: break; } } #if __JDOOM64__ static void getSurfaceColor(uint idx, float rgba[4]) { if(!idx) { rgba[0] = rgba[1] = rgba[2] = rgba[3] = 1; } else { rgba[0] = P_GetGMOFloat(MO_LIGHT, idx-1, MO_COLORR); rgba[1] = P_GetGMOFloat(MO_LIGHT, idx-1, MO_COLORG); rgba[2] = P_GetGMOFloat(MO_LIGHT, idx-1, MO_COLORB); rgba[3] = 1; } } typedef struct applysurfacecolorparams_s { sector_t* frontSec; float topColor[4]; float bottomColor[4]; } applysurfacecolorparams_t; int applySurfaceColor(void* obj, void* context) { #define LDF_NOBLENDTOP 32 #define LDF_NOBLENDBOTTOM 64 #define LDF_BLEND 128 #define LTF_SWAPCOLORS 4 linedef_t* li = (linedef_t*) obj; applysurfacecolorparams_t* params = (applysurfacecolorparams_t*) context; byte dFlags = P_GetGMOByte(MO_XLINEDEF, P_ToIndex(li), MO_DRAWFLAGS); byte tFlags = P_GetGMOByte(MO_XLINEDEF, P_ToIndex(li), MO_TEXFLAGS); if((dFlags & LDF_BLEND) && params->frontSec == P_GetPtrp(li, DMU_FRONT_SECTOR)) { sidedef_t* side = P_GetPtrp(li, DMU_SIDEDEF0); if(side) { int flags; float* top, *bottom; top = (tFlags & LTF_SWAPCOLORS)? params->bottomColor : params->topColor; bottom = (tFlags & LTF_SWAPCOLORS)? params->topColor : params->bottomColor; P_SetFloatpv(side, DMU_TOP_COLOR, top); P_SetFloatpv(side, DMU_BOTTOM_COLOR, bottom); flags = P_GetIntp(side, DMU_FLAGS); if(!(dFlags & LDF_NOBLENDTOP)) flags |= SDF_BLENDTOPTOMID; if(!(dFlags & LDF_NOBLENDBOTTOM)) flags |= SDF_BLENDBOTTOMTOMID; P_SetIntp(side, DMU_FLAGS, flags); } } if((dFlags & LDF_BLEND) && params->frontSec == P_GetPtrp(li, DMU_BACK_SECTOR)) { sidedef_t* side = P_GetPtrp(li, DMU_SIDEDEF1); if(side) { int flags; float* top, *bottom; top = /*(tFlags & LTF_SWAPCOLORS)? params->bottomColor :*/ params->topColor; bottom = /*(tFlags & LTF_SWAPCOLORS)? params->topColor :*/ params->bottomColor; P_SetFloatpv(side, DMU_TOP_COLOR, top); P_SetFloatpv(side, DMU_BOTTOM_COLOR, bottom); flags = P_GetIntp(side, DMU_FLAGS); if(!(dFlags & LDF_NOBLENDTOP)) flags |= SDF_BLENDTOPTOMID; if(!(dFlags & LDF_NOBLENDBOTTOM)) flags |= SDF_BLENDBOTTOMTOMID; P_SetIntp(side, DMU_FLAGS, flags); } } return 1; // Continue iteration } #endif static boolean checkMapSpotSpawnFlags(const mapspot_t* spot) { #if __JHEXEN__ static unsigned int classFlags[] = { MSF_FIGHTER, MSF_CLERIC, MSF_MAGE }; #endif int spawnMask; // Don't spawn things flagged for Multiplayer if we're not in a netgame. if(!IS_NETGAME && (spot->flags & MSF_NOTSINGLE)) return false; // Don't spawn things flagged for Not Deathmatch if we're deathmatching. if(deathmatch && (spot->flags & MSF_NOTDM)) return false; // Don't spawn things flagged for Not Coop if we're coop'in. if(IS_NETGAME && !deathmatch && (spot->flags & MSF_NOTCOOP)) return false; // Check for appropriate skill level. if(gameSkill == SM_BABY || gameSkill == SM_EASY) spawnMask = MSF_EASY; else if(gameSkill == SM_HARD #if !__JDOOM64__ || gameSkill == SM_NIGHTMARE #endif ) spawnMask = MSF_HARD; else spawnMask = MSF_MEDIUM; if(!(spot->flags & spawnMask)) return false; #if __JHEXEN__ // Check current character classes with spawn flags. if(IS_NETGAME == false) { // Single player. if((spot->flags & classFlags[cfg.playerClass[0]]) == 0) { // Not for current class. return false; } } else if(deathmatch == false) { // Cooperative. int i; spawnMask = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { spawnMask |= classFlags[cfg.playerClass[i]]; } } // No players are in the game when a dedicated server is started. // In this case, we'll be generous and spawn stuff for all the // classes. if(!spawnMask) { spawnMask |= MSF_FIGHTER | MSF_CLERIC | MSF_MAGE; } if((spot->flags & spawnMask) == 0) { return false; } } #endif return true; } static void P_LoadMapObjs(void) { uint i; for(i = 0; i < numlines; ++i) { xline_t* xl = &xlines[i]; xl->flags = P_GetGMOShort(MO_XLINEDEF, i, MO_FLAGS); #if __JHEXEN__ xl->special = P_GetGMOByte(MO_XLINEDEF, i, MO_TYPE); xl->arg1 = P_GetGMOByte(MO_XLINEDEF, i, MO_ARG0); xl->arg2 = P_GetGMOByte(MO_XLINEDEF, i, MO_ARG1); xl->arg3 = P_GetGMOByte(MO_XLINEDEF, i, MO_ARG2); xl->arg4 = P_GetGMOByte(MO_XLINEDEF, i, MO_ARG3); xl->arg5 = P_GetGMOByte(MO_XLINEDEF, i, MO_ARG4); #else # if __JDOOM64__ xl->special = P_GetGMOByte(MO_XLINEDEF, i, MO_TYPE); # else xl->special = P_GetGMOShort(MO_XLINEDEF, i, MO_TYPE); # endif xl->tag = P_GetGMOShort(MO_XLINEDEF, i, MO_TAG); #endif } for(i = 0; i < numsectors; ++i) { xsector_t* xsec = &xsectors[i]; xsec->special = P_GetGMOShort(MO_XSECTOR, i, MO_TYPE); xsec->tag = P_GetGMOShort(MO_XSECTOR, i, MO_TAG); #if __JDOOM64__ { applysurfacecolorparams_t params; float rgba[4]; sector_t* sec = P_ToPtr(DMU_SECTOR, i); getSurfaceColor(TOLIGHTIDX( P_GetGMOShort(MO_XSECTOR, i, MO_FLOORCOLOR)), rgba); P_SetFloatpv(sec, DMU_FLOOR_COLOR, rgba); getSurfaceColor(TOLIGHTIDX( P_GetGMOShort(MO_XSECTOR, i, MO_CEILINGCOLOR)), rgba); P_SetFloatpv(sec, DMU_CEILING_COLOR, rgba); // Now set the side surface colors. params.frontSec = sec; getSurfaceColor(TOLIGHTIDX( P_GetGMOShort(MO_XSECTOR, i, MO_WALLTOPCOLOR)), params.topColor); getSurfaceColor(TOLIGHTIDX( P_GetGMOShort(MO_XSECTOR, i, MO_WALLBOTTOMCOLOR)), params.bottomColor); P_Iteratep(sec, DMU_LINEDEF, ¶ms, applySurfaceColor); } #endif } numMapSpots = P_CountGameMapObjs(MO_THING); if(numMapSpots > 0) mapSpots = Z_Malloc(numMapSpots * sizeof(mapspot_t), PU_MAP, 0); else mapSpots = NULL; for(i = 0; i < numMapSpots; ++i) { mapspot_t* spot = &mapSpots[i]; spot->pos[VX] = P_GetGMOFloat(MO_THING, i, MO_X); spot->pos[VY] = P_GetGMOFloat(MO_THING, i, MO_Y); spot->pos[VZ] = P_GetGMOFloat(MO_THING, i, MO_Z); spot->doomEdNum = P_GetGMOInt(MO_THING, i, MO_DOOMEDNUM); spot->flags = P_GetGMOInt(MO_THING, i, MO_FLAGS); spot->angle = P_GetGMOAngle(MO_THING, i, MO_ANGLE); #if __JHEXEN__ spot->tid = P_GetGMOShort(MO_THING, i, MO_ID); spot->special = P_GetGMOByte(MO_THING, i, MO_SPECIAL); spot->arg1 = P_GetGMOByte(MO_THING, i, MO_ARG0); spot->arg2 = P_GetGMOByte(MO_THING, i, MO_ARG1); spot->arg3 = P_GetGMOByte(MO_THING, i, MO_ARG2); spot->arg4 = P_GetGMOByte(MO_THING, i, MO_ARG3); spot->arg5 = P_GetGMOByte(MO_THING, i, MO_ARG4); #endif #if __JHERETIC__ // Ambient sound origin? if(spot->doomEdNum >= 1200 && spot->doomEdNum < 1300) { P_AddAmbientSfx(spot->doomEdNum - 1200); continue; } #elif __JHEXEN__ // Sound sequence origin? if(spot->doomEdNum >= 1400 && spot->doomEdNum < 1410) { subsector_t* ssec = R_PointInSubsector(spot->pos[VX], spot->pos[VY]); xsector_t* xsector = P_ToXSector(P_GetPtrp(ssec, DMU_SECTOR)); xsector->seqType = spot->doomEdNum - 1400; continue; } // Polyobject origin? if(spot->doomEdNum >= 3000 && spot->doomEdNum < 3003) continue; // Not spawned. #endif switch(spot->doomEdNum) { default: // A spot that should auto-spawn one (or more) mobjs. { mobjtype_t type; if(!checkMapSpotSpawnFlags(spot)) continue; // Find which type to spawn. if((type = P_DoomEdNumToMobjType(spot->doomEdNum)) != MT_NONE) { // A known type; spawn it! mobj_t* mo; /*#if _DEBUG Con_Message("spawning x:[%g, %g, %g] angle:%i ednum:%i flags:%i\n", spot->pos[VX], spot->pos[VY], spot->pos[VZ], spot->angle, spot->doomedNum, spot->flags); #endif*/ if((mo = P_SpawnMobj3fv(type, spot->pos, spot->angle, spot->flags))) { if(mo->tics > 0) mo->tics = 1 + (P_Random() % mo->tics); #if __JHEXEN__ mo->tid = spot->tid; mo->special = spot->special; mo->args[0] = spot->arg1; mo->args[1] = spot->arg2; mo->args[2] = spot->arg3; mo->args[3] = spot->arg4; mo->args[4] = spot->arg5; #endif #if __JHEXEN__ if(mo->flags2 & MF2_FLOATBOB) mo->special1 = FLT2FIX(spot->pos[VZ]); #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ if(mo->flags & MF_COUNTKILL) totalKills++; if(mo->flags & MF_COUNTITEM) totalItems++; #endif } } else { Con_Message("spawnMapThing: Warning, unknown thing num %i " "at [%g, %g, %g].\n", spot->doomEdNum, spot->pos[VX], spot->pos[VY], spot->pos[VZ]); } break; } case 11: // Player start (deathmatch). P_CreatePlayerStart(0, 0, true, spot->pos[VX], spot->pos[VY], spot->pos[VZ], spot->angle, spot->flags); break; case 1: // Player starts 1 through 4. case 2: case 3: case 4: { #if __JHEXEN__ uint entryPoint = spot->arg1; #else uint entryPoint = 0; #endif P_CreatePlayerStart(spot->doomEdNum, entryPoint, false, spot->pos[VX], spot->pos[VY], spot->pos[VZ], spot->angle, spot->flags); break; } #if __JHERETIC__ case 56: // Boss spot. P_AddBossSpot(spot->pos[VX], spot->pos[VY], spot->angle); break; case 2002: if(gameMode != shareware) P_AddMaceSpot(spot->pos[VX], spot->pos[VY], spot->angle); break; #endif #if __JHEXEN__ case 9100: // Player starts 5 through 8. case 9101: case 9102: case 9103: P_CreatePlayerStart(5 + spot->doomEdNum - 9100, spot->arg1, false, spot->pos[VX], spot->pos[VY], spot->pos[VZ], spot->angle, spot->flags); break; #endif } } if(deathmatch) { int i; uint numDMStarts = P_GetNumPlayerStarts(true), playerCount = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) playerCount++; } if(numDMStarts < playerCount) { Con_Error("P_SetupMap: Player count (%d) exceeds deathmatch " "spots (%d).", playerCount, numDMStarts); } } } /** * \todo This should be done in the map converter plugin, not here. */ static void interpretLinedefFlags(void) { #define ML_BLOCKING 1 // Solid, is an obstacle. #define ML_TWOSIDED 4 // Backside will not be present at all if not two sided. #define ML_DONTPEGTOP 8 // Upper texture unpegged. #define ML_DONTPEGBOTTOM 16 // Lower texture unpegged. #if __JDOOM64__ # define MLT_MIRRORH 64 // Mirror textures horizontally. # define MLT_MIRRORV 128 // Mirror textures vertically. #endif uint i; // Interpret the archived map linedef flags and update accordingly. for(i = 0; i < numlines; ++i) { int flags = 0; xline_t* xline = &xlines[i]; /** * Zero unused flags if ML_INVALID is set. * * \attention "This has been found to be necessary because of errors * in Ultimate DOOM's E2M7, where around 1000 linedefs have * the value 0xFE00 masked into the flags value. * There could potentially be many more maps with this problem, * as it is well-known that Hellmaker wads set all bits in * mapthings that it does not understand." * Thanks to Quasar for the heads up. */ #if !__JHEXEN__ /** * \fixme This applies only to DOOM format maps but the game doesn't * know what format the map is in (and shouldn't really) but the * engine doesn't know if the game wants to do this... */ # if !__JDOOM64__ /** * \attention DJS - Can't do this with Doom64TC as it has used the * ML_INVALID bit for another purpose... doh! */ if(xline->flags & ML_INVALID) xline->flags &= VALIDMASK; # endif #endif if(xline->flags & ML_BLOCKING) { flags |= DDLF_BLOCKING; xline->flags &= ~ML_BLOCKING; } if(xline->flags & ML_TWOSIDED) { xline->flags &= ~ML_TWOSIDED; } if(xline->flags & ML_DONTPEGTOP) { flags |= DDLF_DONTPEGTOP; xline->flags &= ~ML_DONTPEGTOP; } if(xline->flags & ML_DONTPEGBOTTOM) { flags |= DDLF_DONTPEGBOTTOM; xline->flags &= ~ML_DONTPEGBOTTOM; } if(xline->flags & ML_MAPPED) { int p; // Update the automap(s) with all immediately visible lines. for(p = 0; p < MAXPLAYERS; ++p) AM_UpdateLinedef(AM_MapForPlayer(p), i, true); xline->flags &= ~ML_MAPPED; } P_SetInt(DMU_LINEDEF, i, DMU_FLAGS, flags); } #undef ML_BLOCKING #undef ML_TWOSIDED #undef ML_DONTPEGTOP #undef ML_DONTPEGBOTTOM #if __JDOOM64__ # undef MLT_MIRRORH # undef MLT_MIRRORV #endif } typedef struct setupmapparams_s { uint episode; uint map; int playerMask; // Unused? skillmode_t skill; } setupmapparams_t; int P_SetupMapWorker(void* ptr) { setupmapparams_t* param = ptr; char mapID[9]; // It begins... mapSetup = true; // The engine manages polyobjects, so reset the count. DD_SetInteger(DD_POLYOBJ_COUNT, 0); P_ResetWorldState(); // Let the engine know that we are about to start setting up a map. R_SetupMap(DDSMM_INITIALIZE, 0); // Initialize The Logical Sound Manager. S_MapChange(); Z_FreeTags(PU_MAP, PU_PURGELEVEL - 1); P_GetMapLumpName(param->episode, param->map, mapID); if(!P_LoadMap(mapID)) { Con_Error("P_SetupMap: Failed loading map \"%s\".\n", mapID); } DD_InitThinkers(); #if __JHERETIC__ P_InitAmbientSound(); #endif P_LoadMapObjs(); #if __JDOOM__ if(gameMode == commercial) P_SpawnBrainTargets(); #endif #if __JHERETIC__ if(maceSpotCount) { // Sometimes doesn't show up if not in deathmatch. if(!(!deathmatch && P_Random() < 64)) { const mapspot_t* spot = &maceSpots[P_Random() % maceSpotCount]; P_SpawnMobj3f(MT_WMACE, spot->pos[VX], spot->pos[VY], 0, spot->angle, MSF_Z_FLOOR); } } #endif #if __JHEXEN__ P_CreateTIDList(); P_InitCreatureCorpseQueue(false); // false = do NOT scan for corpses PO_InitForMap(); #endif interpretLinedefFlags(); #if __JHEXEN__ Con_Message("Load ACS scripts\n"); // \fixme Custom map data format support P_LoadACScripts(W_GetNumForName(mapID) + 11 /*ML_BEHAVIOR*/); // ACS object code #endif P_DealPlayerStarts(0); P_SpawnPlayers(); HU_UpdatePsprites(); // Set up world state. P_SpawnSpecials(); // Preload graphics. if(precache) { #if __JDOOM__ static const mobjtype_precachedata_t types[] = { { GM_ANY, MT_SKULL }, // Missiles: { GM_ANY, MT_BRUISERSHOT }, { GM_ANY, MT_TROOPSHOT }, { GM_ANY, MT_HEADSHOT }, { GM_ANY, MT_ROCKET }, { GM_NOTSHAREWARE, MT_PLASMA }, { GM_NOTSHAREWARE, MT_BFG }, { GM_DOOM2, MT_ARACHPLAZ }, { GM_DOOM2, MT_FATSHOT }, // Potentially dropped weapons: { GM_ANY, MT_CLIP }, { GM_ANY, MT_SHOTGUN }, { GM_ANY, MT_CHAINGUN }, // Misc effects: { GM_DOOM2, MT_FIRE }, { GM_ANY, MT_TRACER }, { GM_ANY, MT_SMOKE }, { GM_DOOM2, MT_FATSHOT }, { GM_ANY, MT_BLOOD }, { GM_ANY, MT_PUFF }, { GM_ANY, MT_TFOG }, // Teleport FX. { GM_ANY, MT_EXTRABFG }, { GM_ANY, MT_ROCKETPUFF }, { 0, 0} }; uint i; #endif R_PrecacheMap(); R_PrecachePSprites(); #if __JDOOM__ for(i = 0; types[i].type != 0; ++i) if(types[i].gameModeBits & gameModeBits) R_PrecacheMobjNum(types[i].type); if(IS_NETGAME) R_PrecacheMobjNum(MT_IFOG); #endif } if(IS_SERVER) R_SetAllDoomsdayFlags(); P_FinalizeMap(); // Someone may want to do something special now that the map has been // fully set up. R_SetupMap(DDSMM_FINALIZE, 0); P_PrintMapBanner(param->episode, param->map); // It ends. mapSetup = false; Con_BusyWorkerEnd(); return 0; } /** * Loads map and glnode data for the requested episode and map. */ void P_SetupMap(uint episode, uint map, int playerMask, skillmode_t skill) { setupmapparams_t param; param.episode = episode; param.map = map; param.playerMask = playerMask; // Unused? param.skill = skill; DD_Executef(true, "texreset raw"); // Delete raw images to save memory. // \todo Use progress bar mode and update progress during the setup. Con_Busy(BUSYF_ACTIVITY | /*BUSYF_PROGRESS_BAR |*/ BUSYF_TRANSITION | (verbose? BUSYF_CONSOLE_OUTPUT : 0), "Loading map...", P_SetupMapWorker, ¶m); AM_InitForMap(); R_SetupMap(DDSMM_AFTER_BUSY, 0); #if __JHEXEN__ { int i; // Load colormap and set the fullbright flag i = P_GetMapFadeTable(map); if(i == W_GetNumForName("COLORMAP")) { // We don't want fog in this case. GL_UseFog(false); } else { // Probably fog ... don't use fullbright sprites if(i == W_GetNumForName("FOGMAP")) { // Tell the renderer to turn on the fog. GL_UseFog(true); } } } #endif } /** * Called during map setup when beginning to load a new map. */ static void P_ResetWorldState(void) { int i, parm; #if __JDOOM__ || __JDOOM64__ wmInfo.maxFrags = 0; wmInfo.parTime = -1; // Only used with 666/7 specials bossKilled = false; #endif #if __JDOOM__ // Brain info numBrainTargets = 0; numBrainTargetsAlloc = -1; brain.targetOn = 0; brain.easy = 0; // Always init easy to 0. #endif #if __JHERETIC__ maceSpotCount = 0; maceSpots = NULL; bossSpotCount = 0; bossSpots = NULL; #endif P_PurgeDeferredSpawns(); #if !__JHEXEN__ totalKills = totalItems = totalSecret = 0; #endif timerGame = 0; if(deathmatch) { parm = ArgCheck("-timer"); if(parm && parm < Argc() - 1) { timerGame = atoi(Argv(parm + 1)) * 35 * 60; } } for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; automapid_t map = AM_MapForPlayer(i); plr->killCount = plr->secretCount = plr->itemCount = 0; // Initial height of PointOfView; will be set by player think. plr->viewZ = 1; AM_SetCheatLevel(map, 0); AM_RevealMap(map, false); } #if __JDOOM__ || __JDOOM64__ bodyQueueSlot = 0; #endif P_DestroyPlayerStarts(); mapTime = actualMapTime = 0; } /** * Do any map finalization including any game-specific stuff. */ static void P_FinalizeMap(void) { #if __JDOOM__ || __JDOOM64__ // Adjust slime lower wall textures (a hack!). // This will hide the ugly green bright line that would otherwise be // visible due to texture repeating and interpolation. { uint i, k; material_t* mat = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName("NUKE24", MN_TEXTURES)); material_t* bottomMat, *midMat; float yoff; sidedef_t* sidedef; linedef_t* line; for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); for(k = 0; k < 2; ++k) { sidedef = P_GetPtrp(line, k == 0? DMU_SIDEDEF0 : DMU_SIDEDEF1); if(sidedef) { bottomMat = P_GetPtrp(sidedef, DMU_BOTTOM_MATERIAL); midMat = P_GetPtrp(sidedef, DMU_MIDDLE_MATERIAL); if(bottomMat == mat && midMat == NULL) { yoff = P_GetFloatp(sidedef, DMU_BOTTOM_MATERIAL_OFFSET_Y); P_SetFloatp(sidedef, DMU_BOTTOM_MATERIAL_OFFSET_Y, yoff + 1.0f); } } } } } #elif __JHEXEN__ // Check if the map should have lightening. P_InitLightning(); SN_StopAllSequences(); #endif // Do some fine tuning with mobj placement and orientation. P_MoveThingsOutOfWalls(); #if __JHERETIC__ P_TurnGizmosAwayFromDoors(); #endif } const char* P_GetMapNiceName(void) { const char* lname, *ptr; lname = (char*) DD_GetVariable(DD_MAP_NAME); #if __JHEXEN__ // In jHexen we can look in the MAPINFO for the map name. if(!lname) lname = P_GetMapName(gameMap); #endif if(!lname || !lname[0]) return NULL; // Skip the ExMx part. ptr = strchr(lname, ':'); if(ptr) { lname = ptr + 1; while(*lname && isspace(*lname)) lname++; } return lname; } const char* P_GetMapAuthor(boolean surpressIWADAuthors) { const char* author = (const char*) DD_GetVariable(DD_MAP_AUTHOR); if(!author || !author[0]) return NULL; if(surpressIWADAuthors) { char lumpName[9]; P_GetMapLumpName(gameEpisode, gameMap, lumpName); if(W_IsFromIWAD(W_GetNumForName(lumpName))) return NULL; // @kludge We need DED Reader 2.0 to handle this the Right Way... { # if __JDOOM__ static const char* iwadAuthors[] = { "id Software", "id Software", "Team TNT", "Dario Casali and Milo Casali" }; if(!stricmp(author, iwadAuthors[gameMission])) return NULL; # elif __JDOOM64__ if(!stricmp(author, "Midway")) return NULL; # else /* __JHERETIC__ || __JHEXEN__ */ if(!stricmp(author, "raven software")) return NULL; # endif } } return author; } #if !__JHEXEN__ static boolean isIWADMap(uint episode, uint map) { char lumpName[9]; P_GetMapLumpName(episode, map, lumpName); return W_IsFromIWAD(W_GetNumForName(lumpName)); } #endif /** * Prints a banner to the console containing information pertinent to the * current map (e.g. map name, author...). */ static void P_PrintMapBanner(uint episode, uint map) { const char* lname; Con_Printf("\n"); lname = P_GetMapNiceName(); if(lname) { char name[64]; #if __JHEXEN__ dd_snprintf(name, 64, "Map %u (%u): %s", P_GetMapWarpTrans(map)+1, map+1, lname); #else dd_snprintf(name, 64, "Map %u: %s", map+1, lname); #endif Con_FPrintf(CBLF_LIGHT | CBLF_BLUE, "%s\n", name); } #if !__JHEXEN__ { static const char* unknownAuthorStr = "Unknown"; const char* lauthor; lauthor = P_GetMapAuthor(!isIWADMap(episode, map)); if(!lauthor) lauthor = unknownAuthorStr; Con_FPrintf(CBLF_LIGHT | CBLF_BLUE, "Author: %s\n", lauthor); } #endif Con_Printf("\n"); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/g_controls.c0000644000175000017500000011723011357170242023146 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 1999-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_controls.c: Game controls, ticcmd building/merging */ // HEADER FILES ------------------------------------------------------------ #include // required for sqrt, fabs #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" # include "p_inventory.h" #elif __JHEXEN__ # include "jhexen.h" # include "p_inventory.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "g_controls.h" #include "p_tick.h" // for P_IsPaused() #include "d_netsv.h" #include "hu_menu.h" #include "hu_msg.h" #include "g_common.h" // MACROS ------------------------------------------------------------------ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ # define GOTWPN(x) (plr->weaponOwned[x]) # define ISWPN(x) (plr->readyWeapon == x) #endif #define SLOWTURNTICS (6) #define JOY(x) ((x) / 100) #define TOCENTER (-8) #define DELTAMUL (6.324555320) // Used when calculating ticcmd_t.lookdirdelta // TYPES ------------------------------------------------------------------- typedef struct pcontrolstate_s { // Looking around. float targetLookOffset; float lookOffset; boolean mlookPressed; // For accelerative turning: float turnheld; float lookheld; int dclicktime; int dclickstate; int dclicks; int dclicktime2; int dclickstate2; int dclicks2; } pcontrolstate_t; // Joystick axes. typedef enum joyaxis_e { JA_X, JA_Y, JA_Z, JA_RX, JA_RY, JA_RZ, JA_SLIDER0, JA_SLIDER1, NUM_JOYSTICK_AXES } joyaxis_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- int M_ControlsPrivilegedResponder(event_t *event); // m_ctrl.c // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC( CCmdDefaultGameBinds ); DEFCC( CCmdPause ); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern boolean sendpause; // PUBLIC DATA DEFINITIONS ------------------------------------------------- /* // Binding classes (for the dynamic event responder chain) bindcontext_t BindClasses[] = { {"map", GBC_CLASS1, 0, 0}, {"mapfollowoff", GBC_CLASS2, 0, 0}, {"menu", GBC_CLASS3, 0, BCF_ABSOLUTE}, {"menuhotkey", GBC_MENUHOTKEY, 1, 0}, {"chat", GBC_CHAT, 0, 0}, {"message", GBC_MESSAGE, 0, BCF_ABSOLUTE}, {NULL} }; */ // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Input devices; state controls. static int povangle = -1; // -1 means centered (really 0 - 7). static float mousex; static float mousey; // Player control state. static pcontrolstate_t controlStates[MAXPLAYERS]; // CVars for control/input cvar_t controlCVars[] = { // Control (options/preferences) {"ctl-aim-noauto", 0, CVT_INT, &cfg.noAutoAim, 0, 1}, {"ctl-turn-speed", 0, CVT_FLOAT, &cfg.turnSpeed, 1, 5}, {"ctl-run", 0, CVT_INT, &cfg.alwaysRun, 0, 1}, {"ctl-use-dclick", 0, CVT_INT, &cfg.dclickUse, 0, 1}, #if __JHERETIC__ || __JHEXEN__ {"ctl-inventory-mode", 0, CVT_BYTE, &cfg.inventorySelectMode, 0, 1}, {"ctl-inventory-wrap", 0, CVT_BYTE, &cfg.inventoryWrap, 0, 1}, {"ctl-inventory-use-immediate", 0, CVT_BYTE, &cfg.inventoryUseImmediate, 0, 1}, {"ctl-inventory-use-next", 0, CVT_BYTE, &cfg.inventoryUseNext, 0, 1}, #endif {"ctl-look-speed", 0, CVT_FLOAT, &cfg.lookSpeed, 1, 5}, {"ctl-look-spring", 0, CVT_INT, &cfg.lookSpring, 0, 1}, {"ctl-look-mouse", 0, CVT_INT, &cfg.useMLook, 0, 1}, {"ctl-look-pov", 0, CVT_BYTE, &cfg.povLookAround, 0, 1}, {"ctl-look-joy", 0, CVT_INT, &cfg.useJLook, 0, 1}, {"ctl-look-joy-delta", 0, CVT_INT, &cfg.jLookDeltaMode, 0, 1}, {NULL} }; ccmd_t controlCmds[] = { { "defaultgamebindings", "", CCmdDefaultGameBinds }, { "pause", "", CCmdPause }, { NULL } }; // CODE -------------------------------------------------------------------- /** * Register the CVars and CCmds for input/controls. */ void G_ControlRegister(void) { uint i; for(i = 0; controlCVars[i].name; ++i) Con_AddVariable(controlCVars + i); for(i = 0; controlCmds[i].name; ++i) Con_AddCommand(controlCmds + i); // FIXME: Is this is the proper place, this being a console registering function? P_NewPlayerControl(CTL_WALK, CTLT_NUMERIC, "walk", "game"); P_NewPlayerControl(CTL_SIDESTEP, CTLT_NUMERIC, "sidestep", "game"); P_NewPlayerControl(CTL_ZFLY, CTLT_NUMERIC, "zfly", "game"); P_NewPlayerControl(CTL_TURN, CTLT_NUMERIC, "turn", "game"); P_NewPlayerControl(CTL_LOOK, CTLT_NUMERIC, "look", "game"); P_NewPlayerControl(CTL_SPEED, CTLT_NUMERIC, "speed", "game"); P_NewPlayerControl(CTL_MODIFIER_1, CTLT_NUMERIC, "strafe", "game"); P_NewPlayerControl(CTL_ATTACK, CTLT_NUMERIC, "attack", "game"); P_NewPlayerControl(CTL_USE, CTLT_IMPULSE, "use", "game"); P_NewPlayerControl(CTL_LOOK_CENTER, CTLT_IMPULSE, "lookcenter", "game"); P_NewPlayerControl(CTL_FALL_DOWN, CTLT_IMPULSE, "falldown", "game"); P_NewPlayerControl(CTL_JUMP, CTLT_IMPULSE, "jump", "game"); P_NewPlayerControl(CTL_WEAPON1, CTLT_IMPULSE, "weapon1", "game"); P_NewPlayerControl(CTL_WEAPON2, CTLT_IMPULSE, "weapon2", "game"); P_NewPlayerControl(CTL_WEAPON3, CTLT_IMPULSE, "weapon3", "game"); P_NewPlayerControl(CTL_WEAPON4, CTLT_IMPULSE, "weapon4", "game"); P_NewPlayerControl(CTL_WEAPON5, CTLT_IMPULSE, "weapon5", "game"); P_NewPlayerControl(CTL_WEAPON6, CTLT_IMPULSE, "weapon6", "game"); P_NewPlayerControl(CTL_WEAPON7, CTLT_IMPULSE, "weapon7", "game"); P_NewPlayerControl(CTL_WEAPON8, CTLT_IMPULSE, "weapon8", "game"); P_NewPlayerControl(CTL_WEAPON9, CTLT_IMPULSE, "weapon9", "game"); P_NewPlayerControl(CTL_WEAPON0, CTLT_IMPULSE, "weapon0", "game"); #if __JDOOM64__ P_NewPlayerControl(CTL_WEAPON10, CTLT_IMPULSE, "weapon10", "game"); #endif P_NewPlayerControl(CTL_NEXT_WEAPON, CTLT_IMPULSE, "nextweapon", "game"); P_NewPlayerControl(CTL_PREV_WEAPON, CTLT_IMPULSE, "prevweapon", "game"); #if __JHERETIC__ || __JHEXEN__ P_NewPlayerControl(CTL_USE_ITEM, CTLT_IMPULSE, "useitem", "game"); P_NewPlayerControl(CTL_NEXT_ITEM, CTLT_IMPULSE, "nextitem", "game"); P_NewPlayerControl(CTL_PREV_ITEM, CTLT_IMPULSE, "previtem", "game"); P_NewPlayerControl(CTL_PANIC, CTLT_IMPULSE, "panic", "game"); #endif #if __JHERETIC__ P_NewPlayerControl(CTL_TOME_OF_POWER, CTLT_IMPULSE, "tome", "game"); P_NewPlayerControl(CTL_INVISIBILITY, CTLT_IMPULSE, "invisibility", "game"); P_NewPlayerControl(CTL_FLY, CTLT_IMPULSE, "fly", "game"); P_NewPlayerControl(CTL_TORCH, CTLT_IMPULSE, "torch", "game"); P_NewPlayerControl(CTL_HEALTH, CTLT_IMPULSE, "health", "game"); P_NewPlayerControl(CTL_SUPER_HEALTH, CTLT_IMPULSE, "superhealth", "game"); P_NewPlayerControl(CTL_TELEPORT, CTLT_IMPULSE, "teleport", "game"); P_NewPlayerControl(CTL_FIREBOMB, CTLT_IMPULSE, "firebomb", "game"); P_NewPlayerControl(CTL_INVULNERABILITY, CTLT_IMPULSE, "invulnerability", "game"); P_NewPlayerControl(CTL_EGG, CTLT_IMPULSE, "egg", "game"); #endif #if __JHEXEN__ P_NewPlayerControl(CTL_FLY, CTLT_IMPULSE, "fly", "game"); P_NewPlayerControl(CTL_TORCH, CTLT_IMPULSE, "torch", "game"); P_NewPlayerControl(CTL_HEALTH, CTLT_IMPULSE, "health", "game"); P_NewPlayerControl(CTL_MYSTIC_URN, CTLT_IMPULSE, "mysticurn", "game"); P_NewPlayerControl(CTL_KRATER, CTLT_IMPULSE, "krater", "game"); P_NewPlayerControl(CTL_SPEED_BOOTS, CTLT_IMPULSE, "speedboots", "game"); P_NewPlayerControl(CTL_BLAST_RADIUS, CTLT_IMPULSE, "blast", "game"); P_NewPlayerControl(CTL_TELEPORT, CTLT_IMPULSE, "teleport", "game"); P_NewPlayerControl(CTL_TELEPORT_OTHER, CTLT_IMPULSE, "teleportother", "game"); P_NewPlayerControl(CTL_POISONBAG, CTLT_IMPULSE, "poisonbag", "game"); P_NewPlayerControl(CTL_FIREBOMB, CTLT_IMPULSE, "firebomb", "game"); P_NewPlayerControl(CTL_INVULNERABILITY, CTLT_IMPULSE, "invulnerability", "game"); P_NewPlayerControl(CTL_DARK_SERVANT, CTLT_IMPULSE, "darkservant", "game"); P_NewPlayerControl(CTL_EGG, CTLT_IMPULSE, "egg", "game"); #endif P_NewPlayerControl(CTL_LOG_REFRESH, CTLT_IMPULSE, "msgrefresh", "game"); P_NewPlayerControl(CTL_MAP, CTLT_IMPULSE, "automap", "game"); P_NewPlayerControl(CTL_MAP_PAN_X, CTLT_NUMERIC, "mappanx", "map-freepan"); P_NewPlayerControl(CTL_MAP_PAN_Y, CTLT_NUMERIC, "mappany", "map-freepan"); P_NewPlayerControl(CTL_MAP_ZOOM, CTLT_NUMERIC, "mapzoom", "map"); P_NewPlayerControl(CTL_MAP_ZOOM_MAX, CTLT_IMPULSE, "zoommax", "map"); P_NewPlayerControl(CTL_MAP_FOLLOW, CTLT_IMPULSE, "follow", "map"); P_NewPlayerControl(CTL_MAP_ROTATE, CTLT_IMPULSE, "rotate", "map"); P_NewPlayerControl(CTL_MAP_MARK_ADD, CTLT_IMPULSE, "addmark", "map"); P_NewPlayerControl(CTL_MAP_MARK_CLEAR_ALL, CTLT_IMPULSE, "clearmarks", "map"); P_NewPlayerControl(CTL_HUD_SHOW, CTLT_IMPULSE, "showhud", "game"); P_NewPlayerControl(CTL_SCORE_SHOW, CTLT_IMPULSE, "showscore", "game"); } DEFCC( CCmdDefaultGameBinds ) { // TODO: When the actual bindings setup UI is done, these default bindings // should be generated by the engine based on some higher level metadata, // described in a text file. // Traditional key bindings plus WASD and mouse look, and reasonable // joystick defaults. const char* binds[] = { // Basic movement: "bindcontrol attack key-ctrl", "bindcontrol speed key-shift", "bindcontrol strafe key-alt", "bindcontrol walk key-up", "bindcontrol walk key-w", "bindcontrol walk key-down-inverse", "bindcontrol walk key-s-inverse", "bindcontrol sidestep key-period", "bindcontrol sidestep key-d", "bindcontrol sidestep key-right+modifier-1-down", "bindcontrol sidestep key-comma-inverse", "bindcontrol sidestep key-a-inverse", "bindcontrol sidestep key-left-inverse+modifier-1-down", "bindcontrol zfly key-pgup-staged", "bindcontrol zfly key-e-staged", "bindcontrol zfly key-ins-staged-inverse", "bindcontrol zfly key-q-staged-inverse", "bindevent key-home-down {impulse falldown}", "bindevent key-f-down {impulse falldown}", "bindcontrol turn key-left-staged-inverse+modifier-1-up", "bindcontrol turn key-right-staged+modifier-1-up", "bindcontrol look key-delete-staged", "bindcontrol look key-pgdown-staged-inverse", "bindevent key-end-down {impulse lookcenter}", "bindevent key-slash {impulse jump}", "bindevent key-space-down {impulse use}", "bindevent sym-control-doubleclick-positive-walk {impulse use %p}", // Weapon keys: "bindevent key-1 {impulse weapon1}", "bindevent key-2 {impulse weapon2}", "bindevent key-3 {impulse weapon3}", "bindevent key-4 {impulse weapon4}", #ifndef __JHEXEN__ "bindevent key-5 {impulse weapon5}", "bindevent key-6 {impulse weapon6}", "bindevent key-7 {impulse weapon7}", "bindevent key-8 {impulse weapon8}", "bindevent key-9 {impulse weapon9}", #endif #ifdef __JDOOM64__ "bindevent key-0 {impulse weapon10}", #endif #ifdef __JHERETIC__ "bindevent key-backspace {impulse tome}", #endif #ifdef __JHEXEN__ "bindevent key-backspace {impulse panic}", "bindevent key-backslash {impulse health}", "bindevent key-9 {impulse blast}", "bindevent key-8 {impulse teleport}", "bindevent key-7 {impulse teleportother}", "bindevent key-5 {impulse invulnerability}", "bindevent key-6 {impulse egg}", #endif #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ "bindevent key-sqbracketleft {impulse previtem}", "bindevent key-sqbracketleft-repeat {impulse previtem}", "bindevent key-sqbracketright {impulse nextitem}", "bindevent key-sqbracketright-repeat {impulse nextitem}", "bindevent key-return {impulse useitem}", #endif // Player controls: mouse "bindcontrol turn mouse-x+modifier-1-up", "bindcontrol sidestep mouse-x+modifier-1-down", "bindcontrol look mouse-y", "bindcontrol attack mouse-left", "bindevent mouse-right-down {impulse use}", "bindevent mouse-wheelup {impulse nextweapon}", "bindevent mouse-wheeldown {impulse prevweapon}", // Player controls: joystick "bindcontrol turn joy-x+modifier-1-up", "bindcontrol sidestep joy-x+modifier-1-down", "bindcontrol walk joy-y-inverse", // Chat events: "bindevent key-t beginchat", "bindevent key-g {beginchat 0}", "bindevent key-y {beginchat 1}", "bindevent key-r {beginchat 2}", "bindevent key-b {beginchat 3}", "bindevent chat:key-return chatcomplete", "bindevent chat:key-escape chatcancel", "bindevent chat:key-f1 {chatsendmacro 0}", "bindevent chat:key-f2 {chatsendmacro 1}", "bindevent chat:key-f3 {chatsendmacro 2}", "bindevent chat:key-f4 {chatsendmacro 3}", "bindevent chat:key-f5 {chatsendmacro 4}", "bindevent chat:key-f6 {chatsendmacro 5}", "bindevent chat:key-f7 {chatsendmacro 6}", "bindevent chat:key-f8 {chatsendmacro 7}", "bindevent chat:key-f9 {chatsendmacro 8}", "bindevent chat:key-f10 {chatsendmacro 9}", "bindevent chat:key-backspace chatdelete", // Map events: "bindevent key-tab {impulse automap}", "bindevent map:key-f {impulse follow}", "bindevent map:key-r {impulse rotate}", "bindcontrol mapzoom key-equals", "bindcontrol mapzoom key-minus-inverse", "bindevent map:key-0 {impulse zoommax}", "bindevent map:key-m {impulse addmark}", "bindevent map:key-c {impulse clearmarks}", "bindcontrol mappany key-up", "bindcontrol mappany key-w", "bindcontrol mappany key-down-inverse", "bindcontrol mappany key-s-inverse", "bindcontrol mappanx key-right", "bindcontrol mappanx key-d", "bindcontrol mappanx key-left-inverse", "bindcontrol mappanx key-a-inverse", // UI events: "bindevent shortcut:key-esc menu", #if !__JDOOM64__ "bindevent shortcut:key-f1 helpscreen", #endif "bindevent shortcut:key-f2 savegame", "bindevent shortcut:key-f3 loadgame", "bindevent shortcut:key-f4 soundmenu", "bindevent shortcut:key-f6 quicksave", "bindevent shortcut:key-f7 endgame", "bindevent shortcut:key-f8 togglemsgs", "bindevent shortcut:key-f9 quickload", "bindevent shortcut:key-f10 quit", "bindevent shortcut:key-f11 togglegamma", "bindevent shortcut:key-f12 screenshot", "bindevent key-pause pause", "bindevent key-p pause", "bindevent key-h {impulse showhud}", "bindevent key-backslash-down {impulse showscore}", "bindevent key-backslash-repeat {impulse showscore}", "bindevent key-minus-down {viewsize -}", "bindevent key-minus-repeat {viewsize -}", "bindevent key-equals-down {viewsize +}", "bindevent key-equals-repeat {viewsize +}", // Player message log: #if !defined(__JHEXEN__) && !defined(__JHERETIC__) "bindevent key-return {impulse msgrefresh}", #endif // Menu events: "bindevent menu:key-backspace menuback", "bindevent menu:mouse-right-down menuback", "bindevent menu:key-up menuup", "bindevent menu:key-up-repeat menuup", "bindevent menu:key-w menuup", "bindevent menu:key-w-repeat menuup", "bindevent menu:key-down menudown", "bindevent menu:key-down-repeat menudown", "bindevent menu:key-s menudown", "bindevent menu:key-s-repeat menudown", "bindevent menu:key-left menuleft", "bindevent menu:key-left-repeat menuleft", "bindevent menu:key-a menuleft", "bindevent menu:key-a-repeat menuleft", "bindevent menu:key-right menuright", "bindevent menu:key-right-repeat menuright", "bindevent menu:key-d menuright", "bindevent menu:key-d-repeat menuright", "bindevent menu:key-return menuselect", "bindevent menu:mouse-left-down menuselect", "bindevent menu:key-delete menudelete", "bindevent menu:key-pgup menupageup", "bindevent menu:key-pgup-repeat menupageup", "bindevent menu:key-pgdown menupagedown", "bindevent menu:key-pgdown-repeat menupagedown", // On-screen messages: "bindevent message:key-y messageyes", "bindevent message:key-n messageno", "bindevent message:key-escape messagecancel", NULL }; int i; for(i = 0; binds[i]; ++i) DD_Execute(false, binds[i]); return true; } /** * Registers the additional bind classes the game requires * * (Doomsday manages the bind class stack which forms the dynamic event * responder chain). */ void G_RegisterBindClasses(void) { /* uint i; Con_Message("G_PreInit: Registering Bind Classes...\n"); for(i = 0; BindClasses[i].name; ++i) DD_AddBindClass(BindClasses + i); */ // FIXME: Move the game's binding class creation here. } DEFCC( CCmdPause ) { if(G_GetGameAction() == GA_QUIT) return false; // Toggle pause. G_SetPause(!(paused & 1)); return true; } void G_SetPause(boolean yes) { if(Hu_MenuIsActive() || Hu_IsMessageActive()) return; // No change. if(yes) paused |= 1; else paused &= ~1; if(paused) { // This will stop all sounds from all origins. S_StopSound(0, 0); } else { // Any impulses or accumulated relative offsets that occured // during the pause should be ignored. DD_Execute(true, "resetctlaccum"); } // Servers are responsible for informing clients about // pauses in the game. NetSv_Paused(paused); } /** * Retrieve the look offset for the given player. */ float G_GetLookOffset(int pnum) { return controlStates[pnum].lookOffset; } /* * Offset is in 'angles', where 110 corresponds 85 degrees. * The delta has higher precision with small offsets. */ #if 0 char G_MakeLookDelta(float offset) { boolean minus = offset < 0; offset = sqrt(fabs(offset)) * DELTAMUL; if(minus) offset = -offset; // It's only a char... if(offset > 127) offset = 127; if(offset < -128) offset = -128; return (signed char) offset; } /** * Turn client angle. */ static void G_AdjustAngle(player_t *player, int turn, float elapsed) { if(!player->plr->mo || player->playerState == PST_DEAD || player->viewLock) return; // Sorry, can't help you, pal. /* $unifiedangles */ player->plr->mo->angle += FLT2FIX(cfg.turnSpeed * elapsed * 35.f * turn); } static void G_AdjustLookDir(player_t *player, int look, float elapsed) { ddplayer_t *ddplr = player->plr; if(look) { if(look == TOCENTER) { player->centering = true; } else { ddplr->lookDir += cfg.lookSpeed * look * elapsed * 35; /* $unifiedangles */ } } if(player->centering) { float step = 8 * elapsed * 35; /* $unifiedangles */ if(ddplr->lookDir > step) { ddplr->lookDir -= step; } else if(ddplr->lookDir < -step) { ddplr->lookDir += step; } else { ddplr->lookDir = 0; player->centering = false; } } } #endif /** * Updates the viewers' look angle. * Called every tic by G_Ticker. */ void G_LookAround(int pnum) { pcontrolstate_t *cstate = &controlStates[pnum]; if(povangle != -1) { cstate->targetLookOffset = povangle / 8.0f; if(cstate->targetLookOffset == .5f) { if(cstate->lookOffset < 0) cstate->targetLookOffset = -.5f; } else if(cstate->targetLookOffset > .5) cstate->targetLookOffset -= 1; } else cstate->targetLookOffset = 0; if(cstate->targetLookOffset != cstate->lookOffset && cfg.povLookAround) { float diff = (cstate->targetLookOffset - cstate->lookOffset) / 2; // Clamp it. if(diff > .075f) diff = .075f; if(diff < -.075f) diff = -.075f; cstate->lookOffset += diff; } } #if 0 /** * Builds a ticcmd from all of the available inputs. */ void G_BuildTiccmd(ticcmd_t *cmd, float elapsedTime) { player_t *cplr = &players[CONSOLEPLAYER]; memset(cmd, 0, sizeof(*cmd)); // During demo playback, all cmds will be blank. if(Get(DD_PLAYBACK)) return; G_UpdateCmdControls(cmd, CONSOLEPLAYER, elapsedTime); G_SetCmdViewAngles(cmd, cplr); // special buttons if(sendpause) { sendpause = false; // Clients can't pause anything. if(!IS_CLIENT) cmd->pause = true; } if(IS_CLIENT) { // Clients mirror their local commands.#endif memcpy(&players[CONSOLEPLAYER].cmd, cmd, sizeof(*cmd)); } } /* * Combine the source ticcmd with the destination ticcmd. This is * done when there are multiple ticcmds to execute on a single game * tick. */ void G_MergeTiccmd(ticcmd_t *dest, ticcmd_t *src) { dest->forwardMove = src->forwardMove; dest->sideMove = src->sideMove; dest->angle = src->angle; dest->pitch = src->pitch; dest->fly = src->fly; if(src->arti) dest->arti = src->arti; if(src->changeWeapon) dest->changeWeapon = src->changeWeapon; dest->attack |= src->attack; dest->use |= src->use; dest->jump |= src->jump; dest->pause |= src->pause; } /** * Response to in-game control actions (movement, inventory etc). * Updates the ticcmd with the current control states. */ static void G_UpdateCmdControls(ticcmd_t *cmd, int pnum, float elapsedTime) { float elapsedTics = elapsedTime * 35; boolean pausestate = P_IsPaused(); int i; boolean strafe = 0; boolean bstrafe = 0; int speed = 0; int turnSpeed = 0, fwdMoveSpeed = 0, sideMoveSpeed = 0; int forward = 0; int side = 0; int turn = 0; int joyturn = 0, joystrafe = 0, joyfwd = 0, joylook = 0; int *axes[5] = { 0, &joyfwd, &joyturn, &joystrafe, &joylook }; int look = 0, lspeed = 0; int flyheight = 0; pcontrolstate_t *cstate = &controlStates[pnum]; player_t *plr = &players[pnum]; classinfo_t *pClassInfo = PCLASS_INFO(plr->class); // Check the joystick axes. for(i = 0; i < 8; i++) if(axes[cfg.joyaxis[i]]) *axes[cfg.joyaxis[i]] += joymove[i]; strafe = PLAYER_ACTION(pnum, A_STRAFE); speed = PLAYER_ACTION(pnum, A_SPEED); // Walk -> run, run -> walk. if(cfg.alwaysRun) speed = !speed; // Use two stage accelerative turning on the keyboard and joystick. if(joyturn < -0 || joyturn > 0 || PLAYER_ACTION(pnum, A_TURNRIGHT) || PLAYER_ACTION(pnum, A_TURNLEFT)) cstate->turnheld += elapsedTics; else cstate->turnheld = 0; // Determine the appropriate look speed based on how long the key // has been held down. if(PLAYER_ACTION(pnum, A_LOOKDOWN) || PLAYER_ACTION(pnum, A_LOOKUP)) cstate->lookheld += elapsedTics; else cstate->lookheld = 0; if(cstate->lookheld < SLOWTURNTICS) lspeed = 1; else lspeed = 2; // Return the max speed for the player's class. //// \fixme the Turbo movement multiplier should happen server-side! sideMoveSpeed = pClassInfo->sidemove[speed] * turboMul; fwdMoveSpeed = pClassInfo->forwardmove[speed] * turboMul; turnSpeed = pClassInfo->turnSpeed[(cstate->turnheld < SLOWTURNTICS ? 2 : speed)]; // let movement keys cancel each other out if(strafe) { if(PLAYER_ACTION(pnum, A_TURNRIGHT)) side += sideMoveSpeed; if(PLAYER_ACTION(pnum, A_TURNLEFT)) side -= sideMoveSpeed; // Swap strafing and turning. i = joystrafe; joystrafe = joyturn; joyturn = i; } else { if(PLAYER_ACTION(pnum, A_TURNRIGHT)) turn -= turnSpeed; if(PLAYER_ACTION(pnum, A_TURNLEFT)) turn += turnSpeed; } // Joystick turn. if(joyturn > 0) turn -= turnSpeed * JOY(joyturn); if(joyturn < -0) turn += turnSpeed * JOY(-joyturn); // Joystick strafe. if(joystrafe < -0) side -= sideMoveSpeed * JOY(-joystrafe); if(joystrafe > 0) side += sideMoveSpeed * JOY(joystrafe); if(joyfwd < -0) forward += fwdMoveSpeed * JOY(-joyfwd); if(joyfwd > 0) forward -= fwdMoveSpeed * JOY(joyfwd); if(PLAYER_ACTION(pnum, A_FORWARD)) forward += fwdMoveSpeed; if(PLAYER_ACTION(pnum, A_BACKWARD)) forward -= fwdMoveSpeed; if(PLAYER_ACTION(pnum, A_STRAFERIGHT)) side += sideMoveSpeed; if(PLAYER_ACTION(pnum, A_STRAFELEFT)) side -= sideMoveSpeed; // Look up/down/center keys if(!cfg.lookSpring || (cfg.lookSpring && !forward)) { if(PLAYER_ACTION(pnum, A_LOOKUP)) { look = lspeed; } if(PLAYER_ACTION(pnum, A_LOOKDOWN)) { look = -lspeed; } if(PLAYER_ACTION(pnum, A_LOOKCENTER)) { look = TOCENTER; } } // Fly up/down/drop keys if(PLAYER_ACTION(pnum, A_FLYUP)) // note that the actual flyheight will be twice this flyheight = 5; if(PLAYER_ACTION(pnum, A_FLYDOWN)) flyheight = -5; if(PLAYER_ACTION(pnum, A_FLYCENTER)) { flyheight = TOCENTER; #if __JHERETIC__ if(!cfg.useMLook) // only in jHeretic look = TOCENTER; #else look = TOCENTER; #endif } #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ // Use artifact key if(PLAYER_ACTION(pnum, A_USEARTIFACT)) { if(Hu_InventoryIsOpen()) { plr->readyItem = plr->inventory[plr->invPtr].type; Hu_InventoryOpen(plr - players, false); // close the inventory if(cfg.chooseAndUse) cmd->arti = plr->inventory[plr->invPtr].type; else cmd->arti = 0; usearti = false; } else if(usearti) { cmd->arti = plr->inventory[plr->invPtr].type; usearti = false; } } #endif // // Artifact hot keys // #if __JHERETIC__ // Check Tome of Power and other artifact hotkeys. if(PLAYER_ACTION(pnum, A_TOMEOFPOWER) && !cmd->arti && !plr->powers[PT_WEAPONLEVEL2]) { PLAYER_ACTION(pnum, A_TOMEOFPOWER) = false; cmd->arti = IIT_TOMBOFPOWER; } for(i = 0; ArtifactHotkeys[i].artifact != IIT_NONE && !cmd->arti; i++) { if(PLAYER_ACTION(pnum, ArtifactHotkeys[i].action)) { PLAYER_ACTION(pnum, ArtifactHotkeys[i].action) = false; cmd->arti = ArtifactHotkeys[i].artifact; break; } } #endif #if __JHEXEN__ || __JSTRIFE__ if(PLAYER_ACTION(pnum, A_PANIC) && !cmd->arti) { PLAYER_ACTION(pnum, A_PANIC) = false; // Use one of each artifact cmd->arti = NUM_INVENTORYITEM_TYPES; } else if(plr->plr->mo && PLAYER_ACTION(pnum, A_HEALTH) && !cmd->arti && (plr->plr->mo->health < maxHealth)) { PLAYER_ACTION(pnum, A_HEALTH) = false; cmd->arti = IIT_HEALTH; } else if(PLAYER_ACTION(pnum, A_POISONBAG) && !cmd->arti) { PLAYER_ACTION(pnum, A_POISONBAG) = false; cmd->arti = IIT_POISONBAG; } else if(PLAYER_ACTION(pnum, A_BLASTRADIUS) && !cmd->arti) { PLAYER_ACTION(pnum, A_BLASTRADIUS) = false; cmd->arti = IIT_BLASTRADIUS; } else if(PLAYER_ACTION(pnum, A_TELEPORT) && !cmd->arti) { PLAYER_ACTION(pnum, A_TELEPORT) = false; cmd->arti = IIT_TELEPORT; } else if(PLAYER_ACTION(pnum, A_TELEPORTOTHER) && !cmd->arti) { PLAYER_ACTION(pnum, A_TELEPORTOTHER) = false; cmd->arti = IIT_TELEPORTOTHER; } else if(PLAYER_ACTION(pnum, A_EGG) && !cmd->arti) { PLAYER_ACTION(pnum, A_EGG) = false; cmd->arti = IIT_EGG; } else if(PLAYER_ACTION(pnum, A_INVULNERABILITY) && !cmd->arti && !plr->powers[PT_INVULNERABILITY]) { PLAYER_ACTION(pnum, A_INVULNERABILITY) = false; cmd->arti = IIT_INVULNERABILITY; } else if(PLAYER_ACTION(pnum, A_MYSTICURN) && !cmd->arti) { PLAYER_ACTION(pnum, A_MYSTICURN) = false; cmd->arti = IIT_SUPERHEALTH; } else if(PLAYER_ACTION(pnum, A_TORCH) && !cmd->arti) { PLAYER_ACTION(pnum, A_TORCH) = false; cmd->arti = IIT_TORCH; } else if(PLAYER_ACTION(pnum, A_KRATER) && !cmd->arti) { PLAYER_ACTION(pnum, A_KRATER) = false; cmd->arti = IIT_BOOSTMANA; } else if(PLAYER_ACTION(pnum, A_SPEEDBOOTS) & !cmd->arti) { PLAYER_ACTION(pnum, A_SPEEDBOOTS) = false; cmd->arti = IIT_SPEED; } else if(PLAYER_ACTION(pnum, A_DARKSERVANT) && !cmd->arti) { PLAYER_ACTION(pnum, A_DARKSERVANT) = false; cmd->arti = IIT_SUMMON; } #endif // Buttons if(PLAYER_ACTION(pnum, A_FIRE)) cmd->attack = true; if(PLAYER_ACTION(pnum, A_USE)) { cmd->use = true; // clear double clicks if hit use button cstate->dclicks = 0; } if(PLAYER_ACTION(pnum, A_JUMP)) cmd->jump = true; #if __JDOOM__ || __JDOOM64__ // Determine whether a weapon change should be done. if(PLAYER_ACTION(pnum, A_WEAPONCYCLE1)) // Fist/chainsaw. { if(ISWPN(WT_FIRST) && GOTWPN(WT_EIGHTH)) i = WT_EIGHTH; else if(ISWPN(WT_EIGHTH)) i = WT_FIRST; else if(GOTWPN(WT_EIGHTH)) i = WT_EIGHTH; else i = WT_FIRST; cmd->changeWeapon = i + 1; } else if(PLAYER_ACTION(pnum, A_WEAPONCYCLE2)) // Shotgun/super sg. { if(ISWPN(WT_THIRD) && GOTWPN(WT_NINETH) && gameMode == commercial) i = WT_NINETH; else if(ISWPN(WT_NINETH)) i = WT_THIRD; else if(GOTWPN(WT_NINETH) && gameMode == commercial) i = WT_NINETH; else i = WT_THIRD; cmd->changeWeapon = i + 1; } else #elif __JHERETIC__ // Determine whether a weapon change should be done. if(PLAYER_ACTION(pnum, A_WEAPONCYCLE1)) // Staff/Gauntlets. { if(ISWPN(WT_FIRST) && GOTWPN(WT_EIGHTH)) i = WT_EIGHTH; else if(ISWPN(WT_EIGHTH)) i = WT_FIRST; else if(GOTWPN(WT_EIGHTH)) i = WT_EIGHTH; else i = WT_FIRST; cmd->changeWeapon = i + 1; } else #endif { // Take the first weapon action. for(i = 0; i < NUM_WEAPON_TYPES; i++) if(PLAYER_ACTION(pnum, A_WEAPON1 + i)) { cmd->changeWeapon = i + 1; break; } } if(PLAYER_ACTION(pnum, A_NEXTWEAPON) || PLAYER_ACTION(pnum, A_PREVIOUSWEAPON)) { cmd->changeWeapon = (PLAYER_ACTION(pnum, A_NEXTWEAPON) ? TICCMD_NEXT_WEAPON : TICCMD_PREV_WEAPON); } // forward double click if(PLAYER_ACTION(pnum, A_FORWARD) != cstate->dclickstate && cstate->dclicktime > 1 && cfg.dclickUse) { cstate->dclickstate = PLAYER_ACTION(pnum, A_FORWARD); if(cstate->dclickstate) cstate->dclicks++; if(cstate->dclicks == 2) { cmd->use = true; cstate->dclicks = 0; } else cstate->dclicktime = 0; } else { cstate->dclicktime++; if(cstate->dclicktime > 20) { cstate->dclicks = 0; cstate->dclickstate = 0; } } // strafe double click bstrafe = strafe; if(bstrafe != cstate->dclickstate2 && cstate->dclicktime2 > 1 && cfg.dclickUse) { cstate->dclickstate2 = bstrafe; if(cstate->dclickstate2) cstate->dclicks2++; if(cstate->dclicks2 == 2) { cmd->use = true; cstate->dclicks2 = 0; } else cstate->dclicktime2 = 0; } else { cstate->dclicktime2++; if(cstate->dclicktime2 > 20) { cstate->dclicks2 = 0; cstate->dclickstate2 = 0; } } // Mouse strafe and turn (X axis). if(strafe) side += mousex * 2; else if(mousex) { // Mouse angle changes are immediate. if(!pausestate && plr->plr->mo && plr->playerState != PST_DEAD) { plr->plr->mo->angle += FLT2FIX(mousex * -8); //G_AdjustAngle(plr, mousex * -8, 1); } } if(!pausestate) { // Speed based turning. G_AdjustAngle(plr, turn, elapsedTime); if(strafe || (!cfg.useMLook && !PLAYER_ACTION(pnum, A_MLOOK)) || plr->playerState == PST_DEAD) { forward += 8 * mousey * elapsedTics; } else { float adj = (FLT2FIX(mousey * 8) / (float) ANGLE_180) * 180 * 110.0 / 85.0; if(cfg.mlookInverseY) adj = -adj; plr->plr->lookDir += adj; /* $unifiedangles */ } if(cfg.useJLook) { if(cfg.jLookDeltaMode) /* $unifiedangles */ plr->plr->lookDir += joylook / 20.0f * cfg.lookSpeed * (cfg.jlookInverseY ? -1 : 1) * elapsedTics; else plr->plr->lookDir = joylook * 1.1f * (cfg.jlookInverseY ? -1 : 1); } } G_ResetMousePos(); #define MAXPLMOVE pClassInfo->maxmove if(forward > MAXPLMOVE) forward = MAXPLMOVE; else if(forward < -MAXPLMOVE) forward = -MAXPLMOVE; if(side > MAXPLMOVE) side = MAXPLMOVE; else if(side < -MAXPLMOVE) side = -MAXPLMOVE; #if __JHEXEN__ if(plr->powers[PT_SPEED] && !plr->morphTics) { // Adjust for a player with a speed artifact forward = (3 * forward) >> 1; side = (3 * side) >> 1; } #endif if(cfg.playerMoveSpeed > 1) cfg.playerMoveSpeed = 1; cmd->forwardMove += forward * cfg.playerMoveSpeed; cmd->sideMove += side * cfg.playerMoveSpeed;; if(cfg.lookSpring && !PLAYER_ACTION(pnum, A_MLOOK) && (cmd->forwardMove > MAXPLMOVE / 3 || cmd->forwardMove < -MAXPLMOVE / 3 || cmd->sideMove > MAXPLMOVE / 3 || cmd->sideMove < -MAXPLMOVE / 3 || cstate->mlookPressed)) { // Center view when mlook released w/lookspring, or when moving. look = TOCENTER; } if(plr->playerState == PST_LIVE && !pausestate) G_AdjustLookDir(plr, look, elapsedTime); cmd->fly = flyheight; // Store the current mlook key state. cstate->mlookPressed = PLAYER_ACTION(pnum, A_MLOOK); } #endif /** * Clear all controls for the given player. * * @param player Player number of whose controls to reset. If * negative; clear ALL player's controls. */ void G_ControlReset(int player) { DD_Execute(true, "resetctlaccum"); } /** * Handles special controls, such as pause. */ /*void G_SpecialButton(int pnum) { player_t *pl = &players[pnum]; if(pl->plr->inGame) { if(pl->plr->cmd.actions & BT_SPECIAL) { switch(pl->plr->cmd.actions & BT_SPECIALMASK) { case BTS_PAUSE: paused ^= 1; if(paused) { // This will stop all sounds from all origins. S_StopSound(0, 0); } // Servers are responsible for informing clients about // pauses in the game. NetSv_Paused(paused); pl->plr->cmd.actions = 0; break; default: break; } } } } */ /** * Called by G_Responder. * Depending on the type of the event we may wish to eat it before * it is sent to the engine to check for bindings. * * \todo all controls should be handled by the engine. * Merge in engine-side axis controls from 1.8 alpha. * * @return boolean (True) If the event should be checked for bindings */ boolean G_AdjustControlState(event_t* ev) { /* switch (ev->type) { case EV_KEY: return false; // always let key events filter down case EV_MOUSE_AXIS: mousex += (float)(ev->data1 * (1 + cfg.mouseSensiX/5.0f)) / DD_MICKEY_ACCURACY; mousey += (float)(ev->data2 * (1 + cfg.mouseSensiY/5.0f)) / DD_MICKEY_ACCURACY; return true; // eat events case EV_MOUSE_BUTTON: return false; // always let mouse button events filter down case EV_JOY_AXIS: // Joystick movement joymove[JA_X] = ev->data1; joymove[JA_Y] = ev->data2; joymove[JA_Z] = ev->data3; joymove[JA_RX] = ev->data4; joymove[JA_RY] = ev->data5; joymove[JA_RZ] = ev->data6; return true; // eat events case EV_JOY_SLIDER: // Joystick slider movement joymove[JA_SLIDER0] = ev->data1; joymove[JA_SLIDER1] = ev->data2; return true; case EV_JOY_BUTTON: return false; // always let joy button events filter down case EV_POV: if(!automapactive && !Hu_MenuIsActive()) { if(ev->state == EVS_UP) povangle = -1; else povangle = ev->data1; // If looking around with PoV, don't allow bindings. if(cfg.povLookAround) return true; } break; default: break; } */ return false; } /** * Resets the mouse position to 0,0 * Called e.g. when starting a new map. */ void G_ResetMousePos(void) { mousex = mousey = 0.f; } /** * Resets the look offsets. * Called e.g. when starting a new map. */ void G_ResetLookOffset(int pnum) { pcontrolstate_t *cstate = &controlStates[pnum]; cstate->lookOffset = 0; cstate->targetLookOffset = 0; cstate->lookheld = 0; } int G_PrivilegedResponder(event_t* ev) { if(M_ControlsPrivilegedResponder(ev)) { return true; } // Process the screen shot key right away. if(devParm && ev->type == EV_KEY && ev->data1 == DDKEY_F1) { if(ev->state == EVS_DOWN) G_ScreenShot(); return true; // All F1 events are eaten. } return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/hu_menu.c0000644000175000017500000034160111357170242022436 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_menu.c: Common selection menu, options, episode etc. * Sliders and icons. Kinda widget stuff. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "m_argv.h" #include "hu_log.h" #include "hu_msg.h" #include "hu_stuff.h" #include "f_infine.h" #include "am_map.h" #include "x_hair.h" #include "p_player.h" #include "g_controls.h" #include "p_saveg.h" #include "g_common.h" #include "hu_menu.h" #include "r_common.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct rgba_s { float *r, *g, *b, *a; } rgba_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern void Ed_MakeCursorVisible(void); void M_InitControlsMenu(void); void M_ControlGrabDrawer(void); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void M_NewGame(int option, void* context); void M_Episode(int option, void* context); // Does nothing in jHEXEN void M_ChooseClass(int option, void* context); // Does something only in jHEXEN void M_ChooseSkill(int option, void* context); void M_LoadGame(int option, void* context); void M_SaveGame(int option, void* context); void M_GameFiles(int option, void* context); // Does nothing in jDOOM void M_EndGame(int option, void* context); #if !__JDOOM64__ void M_ReadThis(int option, void* context); void M_ReadThis2(int option, void* context); # if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ void M_ReadThis3(int option, void* context); # endif #endif void M_QuitDOOM(int option, void* context); void M_OpenDCP(int option, void* context); void M_ChangeMessages(int option, void* context); void M_HUDHideTime(int option, void* context); void M_MessageUptime(int option, void* context); #if __JHERETIC__ || __JHEXEN__ void M_InventoryHideTime(int option, void* context); void M_InventorySlotMaxVis(int option, void* context); #endif void M_WeaponAutoSwitch(int option, void* context); void M_AmmoAutoSwitch(int option, void* context); void M_HUDInfo(int option, void* context); void M_HUDScale(int option, void* context); void M_SfxVol(int option, void* context); void M_WeaponOrder(int option, void* context); void M_MusicVol(int option, void* context); void M_SizeDisplay(int option, void* context); #if !__JDOOM64__ void M_SizeStatusBar(int option, void* context); void M_StatusBarOpacity(int option, void* context); #endif void M_HUDRed(int option, void* context); void M_HUDGreen(int option, void* context); void M_HUDBlue(int option, void* context); void M_FinishReadThis(int option, void* context); void M_LoadSelect(int option, void* context); void M_SaveSelect(int option, void* context); void M_Xhair(int option, void* context); void M_XhairSize(int option, void* context); #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ void M_KillCounter(int option, void* data); void M_ItemCounter(int option, void* data); void M_SecretCounter(int option, void* data); #endif static void M_QuickSave(void); static void M_QuickLoad(void); #if __JDOOM64__ void M_WeaponRecoil(int option, void* context); #endif void M_DrawMainMenu(void); void M_DrawNewGameMenu(void); void M_DrawReadThis(void); void M_DrawSkillMenu(void); void M_DrawClassMenu(void); // Does something only in jHEXEN void M_DrawEpisode(void); // Does nothing in jHEXEN void M_DrawOptions(void); void M_DrawOptions2(void); void M_DrawGameplay(void); void M_DrawHUDMenu(void); #if __JHERETIC__ || __JHEXEN__ void M_DrawInventoryMenu(void); #endif void M_DrawMapMenu(void); void M_DrawWeaponMenu(void); void M_DrawLoad(void); void M_DrawSave(void); void M_DrawFilesMenu(void); void M_DrawBackgroundBox(float x, float y, float w, float h, float r, float g, float b, float a, boolean background, int border); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern editfield_t* ActiveEdit; extern char* weaponNames[]; extern menu_t ControlsDef; // PUBLIC DATA DEFINITIONS ------------------------------------------------- #if __JDOOM__ || __JDOOM64__ /// The end message strings will be initialized in Hu_MenuInit(). char* endmsg[NUM_QUITMESSAGES + 1]; #endif menu_t* currentMenu; // -1 = no quicksave slot picked! int quickSaveSlot; char tempstring[80]; // Old save description before edit. char saveOldString[HU_SAVESTRINGSIZE+1]; char savegamestrings[10][HU_SAVESTRINGSIZE+1]; // We are going to be entering a savegame string. int saveStringEnter; int saveSlot; // Which slot to save in. int saveCharIndex; // Which char we're editing. char endstring[160]; static char* yesno[2] = {"NO", "YES"}; #if __JDOOM__ || __JHERETIC__ int epi; #endif int menu_color = 0; float skull_angle = 0; int frame; // Used by any graphic animations that need to be pumped. int menuTime; short itemOn; // Menu item skull is on. short previtemOn; // Menu item skull was last on (for restoring when leaving widget control). short skullAnimCounter; // Skull animation counter. short whichSkull; // Which skull to draw. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean menuActive; static float menuAlpha = 0; // Alpha level for the entire menu. static float menuTargetAlpha = 0; // Target alpha for the entire UI. #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ static int SkullBaseLump; #endif static int cursors = NUMCURSORS; dpatch_t cursorst[NUMCURSORS]; #if __JHEXEN__ static int MenuPClass; #endif static rgba_t widgetcolors[] = { // Ptrs to colors editable with the colour widget { &cfg.automapL0[0], &cfg.automapL0[1], &cfg.automapL0[2], NULL }, { &cfg.automapL1[0], &cfg.automapL1[1], &cfg.automapL1[2], NULL }, { &cfg.automapL2[0], &cfg.automapL2[1], &cfg.automapL2[2], NULL }, { &cfg.automapL3[0], &cfg.automapL3[1], &cfg.automapL3[2], NULL }, { &cfg.automapBack[0], &cfg.automapBack[1], &cfg.automapBack[2], NULL }, { &cfg.hudColor[0], &cfg.hudColor[1], &cfg.hudColor[2], &cfg.hudColor[3] }, { &cfg.automapMobj[0], &cfg.automapMobj[1], &cfg.automapMobj[2], NULL }, { &cfg.xhairColor[0], &cfg.xhairColor[1], &cfg.xhairColor[2], &cfg.xhairColor[3]} }; static boolean widgetEdit = false; // No active widget by default. static boolean rgba = false; // Used to swap between rgb / rgba modes for the color widget. static int editcolorindex = 0; // The index of the widgetcolors array of the item being currently edited. static float currentcolor[4] = {0, 0, 0, 0}; // Used by the widget as temporay values. // Used to fade out the background a little when a widget is active. static float menu_calpha = 0; static int quicksave; static int quickload; static char notDesignedForMessage[80]; #if __JDOOM__ || __JDOOM64__ static dpatch_t m_doom; static dpatch_t m_newg; static dpatch_t m_skill; static dpatch_t m_episod; static dpatch_t m_ngame; static dpatch_t m_option; static dpatch_t m_loadg; static dpatch_t m_saveg; static dpatch_t m_rdthis; static dpatch_t m_quitg; static dpatch_t m_optttl; static dpatch_t dpLSLeft; static dpatch_t dpLSRight; static dpatch_t dpLSCntr; # if __JDOOM__ static dpatch_t credit; static dpatch_t help; static dpatch_t help1; static dpatch_t help2; # endif #endif #if __JHERETIC__ || __JHEXEN__ static dpatch_t m_htic; static dpatch_t dpFSlot; #endif #if __JHERETIC__ || __JHEXEN__ # define READTHISID 3 #elif !__JDOOM64__ # define READTHISID 4 #endif menuitem_t MainItems[] = { #if __JDOOM__ {ITT_SETMENU, 0, "{case}New Game", NULL, MENU_NEWGAME, &m_ngame}, {ITT_SETMENU, 0, "{case}Options", NULL, MENU_OPTIONS, &m_option}, {ITT_EFUNC, 0, "{case}Load Game", M_LoadGame, 0, &m_loadg}, {ITT_EFUNC, 0, "{case}Save Game", M_SaveGame, 0, &m_saveg}, {ITT_EFUNC, 0, "{case}Read This!", M_ReadThis, 0, &m_rdthis}, {ITT_EFUNC, 0, "{case}Quit Game", M_QuitDOOM, 0, &m_quitg} #elif __JDOOM64__ {ITT_SETMENU, 0, "{case}New Game", NULL, MENU_NEWGAME}, {ITT_SETMENU, 0, "{case}Options", NULL, MENU_OPTIONS}, {ITT_EFUNC, 0, "{case}Load Game", M_LoadGame, 0}, {ITT_EFUNC, 0, "{case}Save Game", M_SaveGame, 0}, {ITT_EFUNC, 0, "{case}Quit Game", M_QuitDOOM, 0} #else {ITT_SETMENU, 0, "new game", NULL, MENU_NEWGAME}, {ITT_SETMENU, 0, "options", NULL, MENU_OPTIONS}, {ITT_SETMENU, 0, "game files", NULL, MENU_FILES}, {ITT_EFUNC, 0, "info", M_ReadThis, 0}, {ITT_EFUNC, 0, "quit game", M_QuitDOOM, 0} #endif }; menu_t MainDef = { #if __JHEXEN__ 0, 110, 50, M_DrawMainMenu, 5, MainItems, 0, MENU_NONE, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B, 0, 5 #elif __JHERETIC__ 0, 110, 56, M_DrawMainMenu, 5, MainItems, 0, MENU_NONE, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B, 0, 5 #elif __JSTRIFE__ 0, 97, 64, M_DrawMainMenu, 6, MainItems, 0, MENU_NONE, GF_FONTA, cfg.menuColor, NULL, false, LINEHEIGHT_B + 1, 0, 6 #elif __JDOOM64__ 0, 97, 64, M_DrawMainMenu, 5, MainItems, 0, MENU_NONE, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B + 1, 0, 5 #else 0, 97, 64, M_DrawMainMenu, 6, MainItems, 0, MENU_NONE, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B + 1, 0, 6 #endif }; menuitem_t NewGameItems[] = { {ITT_EFUNC, 0, "S", M_NewGame, 0}, {ITT_EFUNC, 0, "M", SCEnterMultiplayerMenu, 0} }; menu_t NewGameDef = { #if __JHEXEN__ 0, 110, 50, M_DrawNewGameMenu, 2, NewGameItems, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B, 0, 2 #elif __JHERETIC__ 0, 110, 64, M_DrawNewGameMenu, 2, NewGameItems, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B, 0, 2 #elif __JSTRIFE__ 0, 97, 64, M_DrawNewGameMenu, 2, NewGameItems, 0, MENU_MAIN, GF_FONTA, cfg.menuColor, NULL, false, LINEHEIGHT_B + 1, 0, 2 #elif __JDOOM64__ 0, 97, 64, M_DrawNewGameMenu, 2, NewGameItems, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B + 1, 0, 2 #else 0, 97, 64, M_DrawNewGameMenu, 2, NewGameItems, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B + 1, 0, 2 #endif }; #if __JHEXEN__ static menuitem_t* ClassItems; menu_t ClassDef = { 0, 66, 66, M_DrawClassMenu, 0, NULL, 0, MENU_NEWGAME, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT_B + 1, 0, 0 }; #endif #if __JDOOM__ || __JHERETIC__ static menuitem_t* EpisodeItems; #endif #if __JDOOM__ || __JHERETIC__ menu_t EpiDef = { 0, 48, # if __JDOOM__ 63, # else 50, # endif M_DrawEpisode, 0, NULL, 0, MENU_NEWGAME, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT + 1, 0, 0 }; #endif #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ static menuitem_t FilesItems[] = { {ITT_EFUNC, 0, "load game", M_LoadGame, 0}, {ITT_EFUNC, 0, "save game", M_SaveGame, 0} }; static menu_t FilesMenu = { 0, 110, 60, M_DrawFilesMenu, 2, FilesItems, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT + 1, 0, 2 }; #endif static menuitem_t LoadItems[] = { {ITT_EFUNC, 0, NULL, M_LoadSelect, 0}, {ITT_EFUNC, 0, NULL, M_LoadSelect, 1}, {ITT_EFUNC, 0, NULL, M_LoadSelect, 2}, {ITT_EFUNC, 0, NULL, M_LoadSelect, 3}, {ITT_EFUNC, 0, NULL, M_LoadSelect, 4}, {ITT_EFUNC, 0, NULL, M_LoadSelect, 5}, #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ {ITT_EFUNC, 0, NULL, M_LoadSelect, 6}, {ITT_EFUNC, 0, NULL, M_LoadSelect, 7} #endif }; static menu_t LoadDef = { 0, #if __JDOOM__ || __JDOOM64__ 80, 44, #else 80, 30, #endif M_DrawLoad, NUMSAVESLOTS, LoadItems, 0, MENU_MAIN, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A + 8, 0, NUMSAVESLOTS }; static menuitem_t SaveItems[] = { {ITT_EFUNC, 0, NULL, M_SaveSelect, 0}, {ITT_EFUNC, 0, NULL, M_SaveSelect, 1}, {ITT_EFUNC, 0, NULL, M_SaveSelect, 2}, {ITT_EFUNC, 0, NULL, M_SaveSelect, 3}, {ITT_EFUNC, 0, NULL, M_SaveSelect, 4}, {ITT_EFUNC, 0, NULL, M_SaveSelect, 5}, #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ {ITT_EFUNC, 0, NULL, M_SaveSelect, 6}, {ITT_EFUNC, 0, NULL, M_SaveSelect, 7} #endif }; static menu_t SaveDef = { 0, #if __JDOOM__ || __JDOOM64__ 80, 44, #else 80, 30, #endif M_DrawSave, NUMSAVESLOTS, SaveItems, 0, MENU_MAIN, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A + 8, 0, NUMSAVESLOTS }; #if __JSTRIFE__ static menuitem_t SkillItems[] = { {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_BABY}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_EASY}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_MEDIUM}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_HARD}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_NIGHTMARE} }; static menu_t SkillDef = { 0, 120, 44, M_DrawSkillMenu, 5, SkillItems, 2, MENU_NEWGAME, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT, 0, 5 }; #elif __JHEXEN__ static menuitem_t SkillItems[] = { {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_BABY}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_EASY}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_MEDIUM}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_HARD}, {ITT_EFUNC, 0, NULL, M_ChooseSkill, SM_NIGHTMARE} }; static menu_t SkillDef = { 0, 120, 44, M_DrawSkillMenu, 5, SkillItems, 2, MENU_CLASS, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT, 0, 5 }; #elif __JHERETIC__ static menuitem_t SkillItems[] = { {ITT_EFUNC, 0, "W", M_ChooseSkill, SM_BABY}, {ITT_EFUNC, 0, "Y", M_ChooseSkill, SM_EASY}, {ITT_EFUNC, 0, "B", M_ChooseSkill, SM_MEDIUM}, {ITT_EFUNC, 0, "S", M_ChooseSkill, SM_HARD}, {ITT_EFUNC, 0, "P", M_ChooseSkill, SM_NIGHTMARE} }; static menu_t SkillDef = { 0, 38, 30, M_DrawSkillMenu, 5, SkillItems, 2, MENU_EPISODE, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT, 0, 5 }; #elif __JDOOM64__ static menuitem_t SkillItems[] = { {ITT_EFUNC, 0, "I", M_ChooseSkill, 0, &skillModeNames[0]}, {ITT_EFUNC, 0, "H", M_ChooseSkill, 1, &skillModeNames[1]}, {ITT_EFUNC, 0, "H", M_ChooseSkill, 2, &skillModeNames[2]}, {ITT_EFUNC, 0, "U", M_ChooseSkill, 3, &skillModeNames[3]}, }; static menu_t SkillDef = { 0, 48, 63, M_DrawSkillMenu, 4, SkillItems, 2, MENU_NEWGAME, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT, 0, 4 }; #else static menuitem_t SkillItems[] = { // Text defs TXT_SKILL1..5. {ITT_EFUNC, 0, "I", M_ChooseSkill, 0, &skillModeNames[0]}, {ITT_EFUNC, 0, "H", M_ChooseSkill, 1, &skillModeNames[1]}, {ITT_EFUNC, 0, "H", M_ChooseSkill, 2, &skillModeNames[2]}, {ITT_EFUNC, 0, "U", M_ChooseSkill, 3, &skillModeNames[3]}, {ITT_EFUNC, MIF_NOTALTTXT, "N", M_ChooseSkill, 4, &skillModeNames[4]} }; static menu_t SkillDef = { 0, 48, 63, M_DrawSkillMenu, 5, SkillItems, 2, MENU_EPISODE, GF_FONTB, cfg.menuColor, NULL, false, LINEHEIGHT, 0, 5 }; #endif static menuitem_t OptionsItems[] = { {ITT_EFUNC, 0, "end game", M_EndGame, 0}, {ITT_EFUNC, 0, "control panel", M_OpenDCP, 0}, {ITT_SETMENU, 0, "controls", NULL, MENU_CONTROLS}, {ITT_SETMENU, 0, "gameplay", NULL, MENU_GAMEPLAY}, {ITT_SETMENU, 0, "hud", NULL, MENU_HUD}, {ITT_SETMENU, 0, "automap", NULL, MENU_MAP}, {ITT_SETMENU, 0, "weapons", NULL, MENU_WEAPONS}, #if __JHERETIC__ || __JHEXEN__ {ITT_SETMENU, 0, "inventory", NULL, MENU_INVENTORY}, #endif {ITT_SETMENU, 0, "sound", NULL, MENU_OPTIONS2}, {ITT_EFUNC, 0, "mouse", M_OpenDCP, 2}, {ITT_EFUNC, 0, "joystick", M_OpenDCP, 2} }; static menu_t OptionsDef = { 0, 110, 63, M_DrawOptions, #if __JHERETIC__ || __JHEXEN__ 11, #else 10, #endif OptionsItems, 0, MENU_MAIN, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, #if __JHERETIC__ || __JHEXEN__ 11 #else 10 #endif }; static menuitem_t Options2Items[] = { {ITT_LRFUNC, 0, "SFX VOLUME :", M_SfxVol, 0}, #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_LRFUNC, 0, "MUSIC VOLUME :", M_MusicVol, 0}, #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_EFUNC, 0, "OPEN AUDIO PANEL", M_OpenDCP, 1}, }; static menu_t Options2Def = { 0, #if __JHEXEN__ || __JSTRIFE__ 70, 25, #elif __JHERETIC__ 70, 30, #elif __JDOOM__ || __JDOOM64__ 70, 40, #endif M_DrawOptions2, #if __JDOOM__ || __JDOOM64__ 3, Options2Items, #else 7, Options2Items, #endif 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, #if __JDOOM__ || __JDOOM64__ 0, 3 #else 0, 7 #endif }; #if !__JDOOM64__ menuitem_t ReadItems1[] = { {ITT_EFUNC, 0, "", M_ReadThis2, 0} }; menu_t ReadDef1 = { MNF_NOSCALE, 280, 185, M_DrawReadThis, 1, ReadItems1, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, "HELP1", #if __JDOOM__ false, #else true, #endif LINEHEIGHT, 0, 1 }; menuitem_t ReadItems2[] = { # if __JDOOM__ {ITT_EFUNC, 0, "", M_FinishReadThis, 0} # else {ITT_EFUNC, 0, "", M_ReadThis3, 0} // heretic and hexen have 3 readthis screens. # endif }; menu_t ReadDef2 = { MNF_NOSCALE, 330, 175, M_DrawReadThis, 1, ReadItems2, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, "HELP2", #if __JDOOM__ false, #else true, #endif LINEHEIGHT, 0, 1 }; # if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ menuitem_t ReadItems3[] = { {ITT_EFUNC, 0, "", M_FinishReadThis, 0} }; menu_t ReadDef3 = { MNF_NOSCALE, 330, 175, M_DrawReadThis, 1, ReadItems3, 0, MENU_MAIN, GF_FONTB, cfg.menuColor, "CREDIT", true, LINEHEIGHT, 0, 1 }; # endif #endif static menuitem_t HUDItems[] = { {ITT_LRFUNC, 0, "Screen size :", M_SizeDisplay, 0}, #if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif #if __JDOOM__ {ITT_EFUNC, 0, "Single key display :", M_ToggleVar, 0, NULL, "hud-keys-combine"}, #endif {ITT_EFUNC, 0, "Show messages :", M_ChangeMessages, 0}, {ITT_LRFUNC, 0, "Message uptime :", M_MessageUptime, 0}, {ITT_LRFUNC, 0, "Auto-hide :", M_HUDHideTime, 0}, {ITT_EMPTY, 0, "Un-hide events", NULL, 0}, {ITT_EFUNC, 0, "Receive damage :", M_ToggleVar, 0, NULL, "hud-unhide-damage"}, {ITT_EFUNC, 0, "Pickup health :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-health"}, {ITT_EFUNC, 0, "Pickup armor :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-armor"}, {ITT_EFUNC, 0, "Pickup powerup :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-powerup"}, {ITT_EFUNC, 0, "Pickup weapon :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-weapon"}, #if __JHEXEN__ {ITT_EFUNC, 0, "Pickup mana :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-ammo"}, #else {ITT_EFUNC, 0, "Pickup ammo :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-ammo"}, #endif {ITT_EFUNC, 0, "Pickup key :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-key"}, #if __JHERETIC__ || __JHEXEN__ {ITT_EFUNC, 0, "Pickup item :", M_ToggleVar, 0, NULL, "hud-unhide-pickup-invitem"}, #endif {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, "Crosshair", NULL, 0}, {ITT_LRFUNC, 0, "Symbol :", M_Xhair, 0}, {ITT_LRFUNC, 0, "Size :", M_XhairSize, 0}, #if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_EFUNC, 0, "Vitality color :", M_ToggleVar, 0, NULL, "view-cross-vitality"}, {ITT_EFUNC, 0, " color", SCColorWidget, 7 }, #if __JDOOM__ || __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, "Status bar", NULL, 0}, {ITT_LRFUNC, 0, "Size :", M_SizeStatusBar, 0}, # if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, # endif {ITT_LRFUNC, 0, "Opacity :", M_StatusBarOpacity, 0}, # if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, # endif #endif #if __JDOOM__ || __JDOOM64__ {ITT_EMPTY, 0, NULL, NULL, 0}, #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ {ITT_EMPTY, 0, "Counters", NULL, 0 }, {ITT_LRFUNC, 0, "Kills :", M_KillCounter, 0 }, {ITT_LRFUNC, 0, "Items :", M_ItemCounter, 0 }, {ITT_LRFUNC, 0, "Secrets :", M_SecretCounter, 0 }, #endif #if __JDOOM__ || __JDOOM64__ // Push the fullscreen options onto the next page. {ITT_EMPTY, 0, NULL, NULL, 0}, #endif #if __JHERETIC__ {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_EMPTY, 0, "Fullscreen HUD", NULL, 0}, {ITT_LRFUNC, 0, "Scale :", M_HUDScale, 0}, #if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_EFUNC, 0, " color", SCColorWidget, 5}, #if __JHEXEN__ {ITT_EFUNC, 0, "Show mana :", M_ToggleVar, 0, NULL, "hud-mana" }, #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ {ITT_EFUNC, 0, "Show ammo :", M_ToggleVar, 0, NULL, "hud-ammo" }, {ITT_EFUNC, 0, "Show armor :", M_ToggleVar, 0, NULL, "hud-armor" }, #endif #if __JDOOM64__ {ITT_EFUNC, 0, "Show power keys :", M_ToggleVar, 0, NULL, "hud-power" }, #endif #if __JDOOM__ {ITT_EFUNC, 0, "Show face :", M_ToggleVar, 0, NULL, "hud-face"}, #endif {ITT_EFUNC, 0, "Show health :", M_ToggleVar, 0, NULL, "hud-health"}, #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ {ITT_EFUNC, 0, "Show keys :", M_ToggleVar, 0, NULL, "hud-keys"}, #endif #if __JHERETIC__ || __JHEXEN__ {ITT_EFUNC, 0, "Show item :", M_ToggleVar, 0, NULL, "hud-item" }, #endif }; static menu_t HUDDef = { 0, #if __JDOOM__ || __JDOOM64__ 80, 40, #else 80, 28, #endif M_DrawHUDMenu, #if __JHEXEN__ 39, HUDItems, #elif __JHERETIC__ 46, HUDItems, #elif __JDOOM64__ 33, HUDItems, #elif __JDOOM__ 37, HUDItems, #endif 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, #if __JHEXEN__ 0, 15 // 21 #elif __JHERETIC__ 0, 15 // 23 #elif __JDOOM64__ 0, 19 #elif __JDOOM__ 0, 19 #endif }; #if __JHERETIC__ || __JHEXEN__ static menuitem_t InventoryItems[] = { {ITT_EFUNC, 0, "Select mode : ", M_ToggleVar, 0, NULL, "ctl-inventory-mode"}, {ITT_EFUNC, 0, "Wrap around :", M_ToggleVar, 0, NULL, "ctl-inventory-wrap"}, {ITT_EFUNC, 0, "Choose and use :", M_ToggleVar, 0, NULL, "ctl-inventory-use-immediate"}, {ITT_EFUNC, 0, "Select next if use failed :", M_ToggleVar, 0, NULL, "ctl-inventory-use-next"}, {ITT_LRFUNC, 0, "Auto-hide :", M_InventoryHideTime, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, "Full-screen HUD", NULL, 0}, {ITT_LRFUNC, 0, "Max visible slots :", M_InventorySlotMaxVis, 0, NULL, "hud-inventory-slot-max"}, {ITT_EFUNC, 0, "Show empty slots :", M_ToggleVar, 0, NULL, "hud-inventory-slot-showempty"} }; static menu_t InventoryDef = { 0, 78, 48, M_DrawInventoryMenu, 9, InventoryItems, 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, 9 }; #endif static menuitem_t WeaponItems[] = { {ITT_EMPTY, 0, "Priority order", NULL, 0}, {ITT_LRFUNC, 0, "1 :", M_WeaponOrder, 0 << NUM_WEAPON_TYPES }, {ITT_LRFUNC, 0, "2 :", M_WeaponOrder, 1 << NUM_WEAPON_TYPES }, {ITT_LRFUNC, 0, "3 :", M_WeaponOrder, 2 << NUM_WEAPON_TYPES }, {ITT_LRFUNC, 0, "4 :", M_WeaponOrder, 3 << NUM_WEAPON_TYPES }, #if !__JHEXEN__ {ITT_LRFUNC, 0, "5 :", M_WeaponOrder, 4 << NUM_WEAPON_TYPES }, {ITT_LRFUNC, 0, "6 :", M_WeaponOrder, 5 << NUM_WEAPON_TYPES }, {ITT_LRFUNC, 0, "7 :", M_WeaponOrder, 6 << NUM_WEAPON_TYPES }, {ITT_LRFUNC, 0, "8 :", M_WeaponOrder, 7 << NUM_WEAPON_TYPES }, #endif #if __JDOOM__ || __JDOOM64__ {ITT_LRFUNC, 0, "9 :", M_WeaponOrder, 8 << NUM_WEAPON_TYPES }, #endif #if __JDOOM64__ {ITT_LRFUNC, 0, "10 :", M_WeaponOrder, 9 << NUM_WEAPON_TYPES }, #endif {ITT_EFUNC, 0, "Use with Next/Previous :", M_ToggleVar, 0, NULL, "player-weapon-nextmode"}, {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, "AUTOSWITCH", NULL, 0}, {ITT_LRFUNC, 0, "PICKUP WEAPON :", M_WeaponAutoSwitch, 0}, {ITT_EFUNC, 0, " IF NOT FIRING :", M_ToggleVar, 0, NULL, "player-autoswitch-notfiring"}, {ITT_LRFUNC, 0, "PICKUP AMMO :", M_AmmoAutoSwitch, 0}, #if __JDOOM__ || __JDOOM64__ {ITT_EFUNC, 0, "PICKUP BERSERK :", M_ToggleVar, 0, NULL, "player-autoswitch-berserk"} #endif }; static menu_t WeaponDef = { MNF_NOHOTKEYS, #if __JDOOM__ || __JDOOM64__ 68, 34, #else 78, 28, #endif M_DrawWeaponMenu, #if __JDOOM64__ 18, WeaponItems, #elif __JDOOM__ 17, WeaponItems, #elif __JHERETIC__ 15, WeaponItems, #elif __JHEXEN__ 11, WeaponItems, #endif 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, #if __JDOOM64__ 0, 21 #elif __JDOOM__ 0, 20 #elif __JHERETIC__ 0, 18 #elif __JHEXEN__ 0, 14 #endif }; static menuitem_t GameplayItems[] = { {ITT_EFUNC, 0, "ALWAYS RUN :", M_ToggleVar, 0, NULL, "ctl-run"}, {ITT_EFUNC, 0, "USE LOOKSPRING :", M_ToggleVar, 0, NULL, "ctl-look-spring"}, {ITT_EFUNC, 0, "USE AUTOAIM :", M_ToggleVar, 0, NULL, "ctl-aim-noauto"}, #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ || __JSTRIFE__ {ITT_EFUNC, 0, "ALLOW JUMPING :", M_ToggleVar, 0, NULL, "player-jump"}, #endif #if __JDOOM64__ { ITT_EFUNC, 0, "WEAPON RECOIL : ", M_WeaponRecoil, 0 }, #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, "COMPATIBILITY", NULL, 0 }, # if __JDOOM__ || __JDOOM64__ {ITT_EFUNC, 0, "ANY BOSS TRIGGER 666 :", M_ToggleVar, 0, NULL, "game-anybossdeath666"}, # if !__JDOOM64__ {ITT_EFUNC, 0, "AV RESURRECTS GHOSTS :", M_ToggleVar, 0, NULL, "game-raiseghosts"}, # endif {ITT_EFUNC, 0, "PE LIMITED TO 21 LOST SOULS :", M_ToggleVar, 0, NULL, "game-maxskulls"}, {ITT_EFUNC, 0, "LS CAN GET STUCK INSIDE WALLS :", M_ToggleVar, 0, NULL, "game-skullsinwalls"}, # endif # if __JDOOM__ || __JHERETIC__ || __JDOOM64__ {ITT_EFUNC, 0, "MONSTERS CAN GET STUCK IN DOORS :", M_ToggleVar, 0, NULL, "game-monsters-stuckindoors"}, {ITT_EFUNC, 0, "SOME OBJECTS NEVER HANG OVER LEDGES :", M_ToggleVar, 0, NULL, "game-objects-neverhangoverledges"}, {ITT_EFUNC, 0, "OBJECTS FALL UNDER OWN WEIGHT :", M_ToggleVar, 0, NULL, "game-objects-falloff"}, {ITT_EFUNC, 0, "CORPSES SLIDE DOWN STAIRS :", M_ToggleVar, 0, NULL, "game-corpse-sliding"}, {ITT_EFUNC, 0, "USE EXACTLY DOOM'S CLIPPING CODE :", M_ToggleVar, 0, NULL, "game-objects-clipping"}, {ITT_EFUNC, 0, " ^IFNOT NORTHONLY WALLRUNNING :", M_ToggleVar, 0, NULL, "game-player-wallrun-northonly"}, # endif # if __JDOOM__ || __JDOOM64__ {ITT_EFUNC, 0, "ZOMBIE PLAYERS CAN EXIT MAPS :", M_ToggleVar, 0, NULL, "game-zombiescanexit"}, {ITT_EFUNC, 0, "FIX OUCH FACE :", M_ToggleVar, 0, NULL, "hud-face-ouchfix"}, {ITT_EFUNC, 0, "FIX WEAPON SLOT DISPLAY :", M_ToggleVar, 0, NULL, "hud-status-weaponslots-ownedfix"} # endif #endif }; #if __JHEXEN__ static menu_t GameplayDef = { 0, 88, 25, M_DrawGameplay, 3, GameplayItems, 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, 0, 3 }; #else static menu_t GameplayDef = { 0, #if __JHERETIC__ 30, 30, #else 30, 40, #endif M_DrawGameplay, #if __JDOOM64__ 17, GameplayItems, #elif __JDOOM__ 19, GameplayItems, #else 12, GameplayItems, #endif 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, #if __JDOOM64__ 0, 17 #elif __JDOOM__ 0, 19 #else 0, 12 #endif }; #endif menu_t* menulist[] = { &MainDef, &NewGameDef, #if __JHEXEN__ &ClassDef, #endif #if __JDOOM__ || __JHERETIC__ &EpiDef, #endif &SkillDef, &OptionsDef, &Options2Def, &GameplayDef, &HUDDef, &MapDef, #if __JHERETIC__ || __JHEXEN__ &FilesMenu, #endif &LoadDef, &SaveDef, &MultiplayerMenu, &GameSetupMenu, &PlayerSetupMenu, #if __JHERETIC__ || __JHEXEN__ &InventoryDef, #endif &WeaponDef, &ControlsDef, NULL }; static menuitem_t ColorWidgetItems[] = { {ITT_LRFUNC, 0, "red : ", M_WGCurrentColor, 0, NULL, ¤tcolor[0] }, #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_LRFUNC, 0, "green :", M_WGCurrentColor, 0, NULL, ¤tcolor[1] }, #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_LRFUNC, 0, "blue : ", M_WGCurrentColor, 0, NULL, ¤tcolor[2] }, #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ {ITT_EMPTY, 0, NULL, NULL, 0}, {ITT_EMPTY, 0, NULL, NULL, 0}, #endif {ITT_LRFUNC, 0, "alpha :", M_WGCurrentColor, 0, NULL, ¤tcolor[3] }, }; static menu_t ColorWidgetMnu = { MNF_NOHOTKEYS, 98, 60, NULL, #if __JDOOM__ || __JDOOM64__ 4, ColorWidgetItems, #else 10, ColorWidgetItems, #endif 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, #if __JDOOM__ || __JDOOM64__ 0, 4 #else 0, 10 #endif }; // Cvars for the menu: cvar_t menuCVars[] = { {"menu-scale", 0, CVT_FLOAT, &cfg.menuScale, .1f, 1}, {"menu-flash-r", 0, CVT_FLOAT, &cfg.flashColor[0], 0, 1}, {"menu-flash-g", 0, CVT_FLOAT, &cfg.flashColor[1], 0, 1}, {"menu-flash-b", 0, CVT_FLOAT, &cfg.flashColor[2], 0, 1}, {"menu-flash-speed", 0, CVT_INT, &cfg.flashSpeed, 0, 50}, {"menu-turningskull", 0, CVT_BYTE, &cfg.turningSkull, 0, 1}, {"menu-effect", 0, CVT_INT, &cfg.menuEffects, 0, 1}, {"menu-color-r", 0, CVT_FLOAT, &cfg.menuColor[0], 0, 1}, {"menu-color-g", 0, CVT_FLOAT, &cfg.menuColor[1], 0, 1}, {"menu-color-b", 0, CVT_FLOAT, &cfg.menuColor[2], 0, 1}, {"menu-colorb-r", 0, CVT_FLOAT, &cfg.menuColor2[0], 0, 1}, {"menu-colorb-g", 0, CVT_FLOAT, &cfg.menuColor2[1], 0, 1}, {"menu-colorb-b", 0, CVT_FLOAT, &cfg.menuColor2[2], 0, 1}, {"menu-glitter", 0, CVT_FLOAT, &cfg.menuGlitter, 0, 1}, {"menu-fog", 0, CVT_INT, &cfg.hudFog, 0, 5}, {"menu-shadow", 0, CVT_FLOAT, &cfg.menuShadow, 0, 1}, {"menu-patch-replacement", 0, CVT_BYTE, &cfg.usePatchReplacement, 0, 2}, {"menu-slam", 0, CVT_BYTE, &cfg.menuSlam, 0, 1}, {"menu-quick-ask", 0, CVT_BYTE, &cfg.askQuickSaveLoad, 0, 1}, {"menu-hotkeys", 0, CVT_BYTE, &cfg.menuHotkeys, 0, 1}, #if __JDOOM__ || __JDOOM64__ {"menu-quitsound", 0, CVT_INT, &cfg.menuQuitSound, 0, 1}, #endif {NULL} }; // Console commands for the menu: ccmd_t menuCCmds[] = { {"menu", "", CCmdMenuAction}, {"menuup", "", CCmdMenuAction}, {"menudown", "", CCmdMenuAction}, {"menupageup", "", CCmdMenuAction}, {"menupagedown","", CCmdMenuAction}, {"menuleft", "", CCmdMenuAction}, {"menuright", "", CCmdMenuAction}, {"menuselect", "", CCmdMenuAction}, {"menudelete", "", CCmdMenuAction}, {"menuback", "", CCmdMenuAction}, {"helpscreen", "", CCmdMenuAction}, {"savegame", "", CCmdMenuAction}, {"loadgame", "", CCmdMenuAction}, {"soundmenu", "", CCmdMenuAction}, {"quicksave", "", CCmdMenuAction}, {"endgame", "", CCmdMenuAction}, {"togglemsgs", "", CCmdMenuAction}, {"quickload", "", CCmdMenuAction}, {"quit", "", CCmdMenuAction}, {"togglegamma", "", CCmdMenuAction}, {NULL} }; // Code ------------------------------------------------------------------- /** * Called during the PreInit of each game during start up * Register Cvars and CCmds for the opperation/look of the menu. */ void Hu_MenuRegister(void) { int i; for(i = 0; menuCVars[i].name; ++i) Con_AddVariable(menuCVars + i); for(i = 0; menuCCmds[i].name; ++i) Con_AddCommand(menuCCmds + i); } /** * Load any resources the menu needs. */ void M_LoadData(void) { int i; char buffer[9]; // Load the cursor patches for(i = 0; i < cursors; ++i) { sprintf(buffer, CURSORPREF, i+1); R_CachePatch(&cursorst[i], buffer); } #if __JDOOM__ || __JDOOM64__ R_CachePatch(&m_doom, "M_DOOM"); R_CachePatch(&m_newg, "M_NEWG"); R_CachePatch(&m_skill, "M_SKILL"); R_CachePatch(&m_episod, "M_EPISOD"); R_CachePatch(&m_ngame, "M_NGAME"); R_CachePatch(&m_option, "M_OPTION"); R_CachePatch(&m_loadg, "M_LOADG"); R_CachePatch(&m_saveg, "M_SAVEG"); R_CachePatch(&m_rdthis, "M_RDTHIS"); R_CachePatch(&m_quitg, "M_QUITG"); R_CachePatch(&m_optttl, "M_OPTTTL"); R_CachePatch(&dpLSLeft, "M_LSLEFT"); R_CachePatch(&dpLSRight, "M_LSRGHT"); R_CachePatch(&dpLSCntr, "M_LSCNTR"); # if __JDOOM__ if(gameMode == retail || gameMode == commercial) R_CachePatch(&credit, "CREDIT"); if(gameMode == commercial) R_CachePatch(&help, "HELP"); if(gameMode == shareware || gameMode == registered || gameMode == retail) R_CachePatch(&help1, "HELP1"); if(gameMode == shareware || gameMode == registered) R_CachePatch(&help2, "HELP2"); # endif #endif #if __JHERETIC__ || __JHEXEN__ R_CachePatch(&m_htic, "M_HTIC"); R_CachePatch(&dpFSlot, "M_FSLOT"); #endif } #if __JDOOM__ || __JHERETIC__ /** * Construct the episode selection menu. */ void M_InitEpisodeMenu(void) { int i, maxw, w, numEpisodes; #if __JDOOM__ switch(gameMode) { case commercial: numEpisodes = 0; break; case retail: numEpisodes = 4; break; // In shareware, episodes 2 and 3 are handled, branching to an ad screen. default: numEpisodes = 3; break; } #else // __JHERETIC__ if(gameMode == extended) numEpisodes = 6; else numEpisodes = 3; #endif // Allocate the menu items array. EpisodeItems = Z_Calloc(sizeof(menuitem_t) * numEpisodes, PU_STATIC, 0); for(i = 0, maxw = 0; i < numEpisodes; ++i) { menuitem_t* item = &EpisodeItems[i]; item->type = ITT_EFUNC; item->func = M_Episode; item->option = i; item->text = GET_TXT(TXT_EPISODE1 + i); w = M_StringWidth(item->text, EpiDef.font); if(w > maxw) maxw = w; # if __JDOOM__ item->patch = &episodeNamePatches[i]; # endif } // Finalize setup. EpiDef.items = EpisodeItems; EpiDef.itemCount = numEpisodes; EpiDef.numVisItems = MIN_OF(EpiDef.itemCount, 10); EpiDef.x = 160 - maxw / 2 + 12; // Center the menu appropriately. } #endif #if __JHEXEN__ /** * Construct the player class selection menu. */ void M_InitPlayerClassMenu(void) { uint i, n, count; // First determine the number of selectable player classes. count = 0; for(i = 0; i < NUM_PLAYER_CLASSES; ++i) { classinfo_t* info = PCLASS_INFO(i); if(info->userSelectable) count++; } // Allocate the menu items array. ClassItems = Z_Calloc(sizeof(menuitem_t) * (count + 1), PU_STATIC, 0); // Add the selectable classes. n = i = 0; while(n < count) { classinfo_t* info = PCLASS_INFO(i++); menuitem_t* item; if(!info->userSelectable) continue; item = &ClassItems[n]; item->type = ITT_EFUNC; item->func = M_ChooseClass; item->option = n; item->text = info->niceName; n++; } // Add the random class option. ClassItems[n].type = ITT_EFUNC; ClassItems[n].func = M_ChooseClass; ClassItems[n].option = -1; ClassItems[n].text = GET_TXT(TXT_RANDOMPLAYERCLASS); // Finalize setup. ClassDef.items = ClassItems; ClassDef.itemCount = count + 1; ClassDef.numVisItems = MIN_OF(ClassDef.itemCount, 10); } #endif /** * Menu initialization. * Called during (post-engine) init and after updating game/engine state. * * Initializes the various vars, fonts, adjust the menu structs and * anything else that needs to be done before the menu can be used. */ void Hu_MenuInit(void) { #if !__JDOOM64__ menuitem_t *item; #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ int i, w, maxw; #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ R_GetGammaMessageStrings(); #endif #if __JDOOM__ || __JDOOM64__ // Quit messages. endmsg[0] = GET_TXT(TXT_QUITMSG); for(i = 1; i <= NUM_QUITMESSAGES; ++i) endmsg[i] = GET_TXT(TXT_QUITMESSAGE1 + i - 1); #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ // Skill names. for(i = 0, maxw = 0; i < NUM_SKILL_MODES; ++i) { SkillItems[i].text = GET_TXT(TXT_SKILL1 + i); w = M_StringWidth(SkillItems[i].text, SkillDef.font); if(w > maxw) maxw = w; } // Center the skill menu appropriately. SkillDef.x = 160 - maxw / 2 + 12; #endif // Play modes. NewGameItems[0].text = GET_TXT(TXT_SINGLEPLAYER); NewGameItems[1].text = GET_TXT(TXT_MULTIPLAYER); currentMenu = &MainDef; menuActive = false; DD_Execute(true, "deactivatebcontext menu"); menuAlpha = menuTargetAlpha = 0; M_LoadData(); itemOn = currentMenu->lastOn; whichSkull = 0; skullAnimCounter = MENUCURSOR_TICSPERFRAME; quickSaveSlot = -1; #if __JDOOM__ // Here we catch version dependencies, like HELP1/2, and four episodes. switch(gameMode) { case commercial: item = &MainItems[4]; // Read This! item->func = M_QuitDOOM; item->text = "{case}Quit Game"; item->patch = &m_quitg; MainDef.itemCount = 5; MainDef.y += 8; SkillDef.prevMenu = MENU_NEWGAME; ReadDef1.x = 330; ReadDef1.y = 165; ReadDef1.background = "HELP"; ReadDef1.backgroundIsRaw = false; ReadDef2.background = "CREDIT"; ReadDef2.backgroundIsRaw = false; ReadItems1[0].func = M_FinishReadThis; break; case shareware: // Episode 2 and 3 are handled, branching to an ad screen. case registered: ReadDef1.background = "HELP1"; ReadDef1.backgroundIsRaw = false; ReadDef2.background = "HELP2"; ReadDef2.backgroundIsRaw = false; break; case retail: ReadDef1.background = "HELP1"; ReadDef2.background = "CREDIT"; break; default: break; } #else # if !__JDOOM64__ item = &MainItems[READTHISID]; // Read This! item->func = M_ReadThis; # endif #endif #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ SkullBaseLump = W_GetNumForName(SKULLBASELMP); #endif #if __JDOOM__ || __JHERETIC__ M_InitEpisodeMenu(); #endif #if __JHEXEN__ M_InitPlayerClassMenu(); #endif M_InitControlsMenu(); } /** * @return @c true, iff the menu is currently active (open). */ boolean Hu_MenuIsActive(void) { return menuActive; } /** * Set the alpha level of the entire menu. * * @param alpha Alpha level to set the menu too (0...1) */ void Hu_MenuSetAlpha(float alpha) { // The menu's alpha will start moving towards this target value. menuTargetAlpha = alpha; } /** * @return Current alpha level of the menu. */ float Hu_MenuAlpha(void) { return menuAlpha; } /** * Updates on Game Tick. */ void Hu_MenuTicker(timespan_t time) { #define MENUALPHA_FADE_STEP (.07f) float diff; static trigger_t fixed = { 1 / 35.0 }; if(!M_RunTrigger(&fixed, time)) return; typeInTime++; // Move towards the target alpha level for the entire menu. diff = menuTargetAlpha - menuAlpha; if(fabs(diff) > MENUALPHA_FADE_STEP) { menuAlpha += MENUALPHA_FADE_STEP * (diff > 0? 1 : -1); } else { menuAlpha = menuTargetAlpha; } if(menuActive || menuAlpha > 0) { float rewind = 20; // Fade in/out the widget background filter if(widgetEdit) { if(menu_calpha < 0.5f) menu_calpha += .1f; if(menu_calpha > 0.5f) menu_calpha = 0.5f; } else { if(menu_calpha > 0) menu_calpha -= .1f; if(menu_calpha < 0) menu_calpha = 0; } // Animate the cursor patches if(--skullAnimCounter <= 0) { whichSkull++; skullAnimCounter = MENUCURSOR_TICSPERFRAME; if(whichSkull > cursors-1) whichSkull = 0; } menuTime++; menu_color += cfg.flashSpeed; if(menu_color >= 100) menu_color -= 100; if(cfg.turningSkull && itemOn >= 0 && itemOn < currentMenu->itemCount && currentMenu->items[itemOn].type == ITT_LRFUNC) skull_angle += 5; else if(skull_angle != 0) { if(skull_angle <= rewind || skull_angle >= 360 - rewind) skull_angle = 0; else if(skull_angle < 180) skull_angle -= rewind; else skull_angle += rewind; } if(skull_angle >= 360) skull_angle -= 360; // Used for jHeretic's rotating skulls frame = (menuTime / 3) % 18; } if(menuActive) MN_TickerEx(); #undef MENUALPHA_FADE_STEP } void Hu_MenuPageString(char* page, const menu_t* menu) { sprintf(page, "PAGE %i/%i", (menu->firstItem + menu->numVisItems/2) / menu->numVisItems + 1, (menu->itemCount + menu->numVisItems/2) / menu->numVisItems); } static void M_UpdateMenuVisibleItems(void) { if(!currentMenu) return; if(!widgetEdit) { currentMenu->firstItem = MAX_OF(0, itemOn - currentMenu->numVisItems/2); currentMenu->firstItem = MIN_OF(currentMenu->firstItem, currentMenu->itemCount - currentMenu->numVisItems); currentMenu->firstItem = MAX_OF(0, currentMenu->firstItem); } else { currentMenu->firstItem = currentMenu->firstItem; } } void M_SetupNextMenu(menu_t* menudef) { if(!menudef) return; currentMenu = menudef; if(!widgetEdit) { // Have we been to this menu before? // If so move the cursor to the last selected item if(currentMenu->lastOn >= 0) { itemOn = currentMenu->lastOn; } else { // Select the first active item in this menu. int i; for(i = 0; i < menudef->itemCount; ++i) { if(menudef->items[i].type != ITT_EMPTY) break; } if(i >= menudef->itemCount) itemOn = -1; else itemOn = i; } } else { itemOn = 0; } M_UpdateMenuVisibleItems(); menu_color = 0; skull_angle = 0; typeInTime = 0; } /** * @return @c true, if the menu is active and there is a * background for this page. */ boolean MN_CurrentMenuHasBackground(void) { if(!menuActive) return false; return (currentMenu->background && W_CheckNumForName(currentMenu->background) != -1); } /** * This is the main menu drawing routine (called every tic by the drawing * loop) Draws the current menu 'page' by calling the funcs attached to * each menu item. */ void Hu_MenuDrawer(void) { int i; int pos[2], offset[2], width, height; float scale; boolean allowScaling = (!(currentMenu->flags & MNF_NOSCALE)? true : false); // Popped at the end of the function. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); // Setup matrix. if(menuActive || menuAlpha > 0) { // If there is a menu background raw lump, draw it instead of the // background effect. if(currentMenu->background) { lumpnum_t lump = W_CheckNumForName(currentMenu->background); if(lump != -1) { DGL_Color4f(1, 1, 1, menuAlpha); if(currentMenu->backgroundIsRaw) GL_DrawRawScreen_CS(lump, 0, 0, 1, 1); else GL_DrawPatch_CS(0, 0, lump); } } // Allow scaling? if(allowScaling) { // Scale by the menuScale. DGL_MatrixMode(DGL_MODELVIEW); DGL_Translatef(160, 100, 0); DGL_Scalef(cfg.menuScale, cfg.menuScale, 1); DGL_Translatef(-160, -100, 0); } } if(!menuActive && !(menuAlpha > 0)) goto end_draw_menu; if(allowScaling && currentMenu->unscaled.numVisItems) { currentMenu->numVisItems = currentMenu->unscaled.numVisItems / cfg.menuScale; currentMenu->y = 110 - (110 - currentMenu->unscaled.y) / cfg.menuScale; /* if(currentMenu->firstItem && currentMenu->firstItem < currentMenu->numVisItems) { // Make sure all pages are divided correctly. currentMenu->firstItem = 0; } if(itemOn - currentMenu->firstItem >= currentMenu->numVisItems) { itemOn = currentMenu->firstItem + currentMenu->numVisItems - 1; } */ } if(currentMenu->drawFunc) currentMenu->drawFunc(); // Call Draw routine. pos[VX] = currentMenu->x; pos[VY] = currentMenu->y; if(menuAlpha > 0.0125f) { for(i = currentMenu->firstItem; i < currentMenu->itemCount && i < currentMenu->firstItem + currentMenu->numVisItems; ++i) { float t, r, g, b; // Which color? #if __JDOOM__ || __JDOOM64__ if(!cfg.usePatchReplacement) { r = 1; g = b = 0; } else { #endif if(currentMenu->items[i].type == ITT_EMPTY) { #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ r = cfg.menuColor[0]; g = cfg.menuColor[1]; b = cfg.menuColor[2]; #else // FIXME r = 1; g = .7f; b = .3f; #endif } else if(itemOn == i && !widgetEdit && cfg.usePatchReplacement) { // Selection! if(menu_color <= 50) t = menu_color / 50.0f; else t = (100 - menu_color) / 50.0f; r = currentMenu->color[0] * t + cfg.flashColor[0] * (1 - t); g = currentMenu->color[1] * t + cfg.flashColor[1] * (1 - t); b = currentMenu->color[2] * t + cfg.flashColor[2] * (1 - t); } else { r = currentMenu->color[0]; g = currentMenu->color[1]; b = currentMenu->color[2]; } #if __JDOOM__ || __JDOOM64__ } #endif if(currentMenu->items[i].patch) { WI_DrawPatch(pos[VX], pos[VY], r, g, b, menuAlpha, currentMenu->items[i].patch, (currentMenu->items[i].flags & MIF_NOTALTTXT)? NULL : currentMenu->items[i].text, true, ALIGN_LEFT); } else if(currentMenu->items[i].text) { WI_DrawParamText(pos[VX], pos[VY], currentMenu->items[i].text, currentMenu->font, r, g, b, menuAlpha, false, cfg.usePatchReplacement? true : false, ALIGN_LEFT); } pos[VY] += currentMenu->itemHeight; } // Draw the colour widget? if(widgetEdit) { Draw_BeginZoom(0.5f, 160, 100); DrawColorWidget(); } // Draw the menu cursor. if(allowScaling) { int hasFocus = MAX_OF(0, itemOn); menu_t* mn = (widgetEdit? &ColorWidgetMnu : currentMenu); scale = mn->itemHeight / (float) LINEHEIGHT; width = cursorst[whichSkull].width; height = cursorst[whichSkull].height; offset[VX] = mn->x + MENUCURSOR_OFFSET_X * scale; offset[VX] -= width / 2 * scale; offset[VY] = mn->y + MENUCURSOR_OFFSET_Y * scale; offset[VY] += (hasFocus - mn->firstItem) * mn->itemHeight + mn->itemHeight / 2; DGL_SetPatch(cursorst[whichSkull].lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(offset[VX], offset[VY], 0); DGL_Scalef(scale, scale, 1); if(skull_angle) DGL_Rotatef(skull_angle, 0, 0, 1); DGL_DrawRect(-width/2.f, -height/2.f, width, height, 1, 1, 1, menuAlpha); DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } if(widgetEdit) { Draw_EndZoom(); } } end_draw_menu: // Restore original matrices. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); M_ControlGrabDrawer(); } void Hu_MenuNavigatePage(menu_t* menu, int pageDelta) { int hasFocus = MAX_OF(0, itemOn), oldOnItem = hasFocus; if(pageDelta < 0) { hasFocus = MAX_OF(0, hasFocus - menu->numVisItems); } else { hasFocus = MIN_OF(menu->itemCount-1, hasFocus + menu->numVisItems); } // Don't land on empty items. while(menu->items[hasFocus].type == ITT_EMPTY && (hasFocus > 0)) hasFocus--; while(menu->items[hasFocus].type == ITT_EMPTY && hasFocus < menu->itemCount) hasFocus++; if(hasFocus != oldOnItem) { itemOn = hasFocus; // Make a sound, too. S_LocalSound(SFX_MENU_NAV_RIGHT, NULL); } M_UpdateMenuVisibleItems(); } /** * Execute a menu navigation/action command. */ void Hu_MenuCommand(menucommand_e cmd) { if(cmd == MCMD_CLOSE || cmd == MCMD_CLOSEFAST) { Hu_FogEffectSetAlphaTarget(0); if(cmd == MCMD_CLOSEFAST) { // Hide the menu instantly. menuAlpha = menuTargetAlpha = 0; } else { menuTargetAlpha = 0; } if(menuActive) { currentMenu->lastOn = itemOn; menuActive = false; if(cmd != MCMD_CLOSEFAST) S_LocalSound(SFX_MENU_CLOSE, NULL); // Disable the menu binding class DD_Execute(true, "deactivatebcontext menu"); } return; } if(!menuActive) { if(cmd == MCMD_OPEN) { S_LocalSound(SFX_MENU_OPEN, NULL); Con_Open(false); Hu_FogEffectSetAlphaTarget(1); Hu_MenuSetAlpha(1); menuActive = true; menu_color = 0; menuTime = 0; skull_angle = 0; currentMenu = &MainDef; itemOn = currentMenu->lastOn; typeInTime = 0; // Enable the menu binding class DD_Execute(true, "activatebcontext menu"); B_SetContextFallback("menu", Hu_MenuResponder); } } else { int i, hasFocus; int firstVI, lastVI; // first and last visible item int itemCountOffset = 0; const menuitem_t* item; menu_t* menu = currentMenu; boolean updateLastOn = true; if(widgetEdit) { menu = &ColorWidgetMnu; if(!rgba) itemCountOffset = 1; } if(itemOn < 0) updateLastOn = false; hasFocus = MAX_OF(0, itemOn); firstVI = menu->firstItem; lastVI = firstVI + menu->numVisItems - 1 - itemCountOffset; if(lastVI > menu->itemCount - 1 - itemCountOffset) lastVI = menu->itemCount - 1 - itemCountOffset; item = &menu->items[hasFocus]; if(updateLastOn) menu->lastOn = itemOn; switch(cmd) { default: Con_Error("Internal Error: Menu cmd %i not handled in " "Hu_MenuCommand.", (int) cmd); break; // Unreachable. case MCMD_OPEN: // Ignore. break; case MCMD_NAV_LEFT: if(item->type == ITT_LRFUNC && item->func != NULL) { S_LocalSound(SFX_MENU_SLIDER_MOVE, NULL); item->func(LEFT_DIR | item->option, item->data); } break; case MCMD_NAV_RIGHT: if(item->type == ITT_LRFUNC && item->func != NULL) { S_LocalSound(SFX_MENU_SLIDER_MOVE, NULL); item->func(RIGHT_DIR | item->option, item->data); } break; case MCMD_NAV_PAGEUP: case MCMD_NAV_PAGEDOWN: S_LocalSound(SFX_MENU_NAV_UP, NULL); Hu_MenuNavigatePage(menu, cmd == MCMD_NAV_PAGEUP? -1 : +1); break; case MCMD_NAV_DOWN: i = 0; do { if(hasFocus + 1 > menu->itemCount - 1) hasFocus = 0; else hasFocus++; } while(menu->items[hasFocus].type == ITT_EMPTY && i++ < menu->itemCount); itemOn = hasFocus; menu_color = 0; S_LocalSound(SFX_MENU_NAV_UP, NULL); M_UpdateMenuVisibleItems(); break; case MCMD_NAV_UP: i = 0; do { if(hasFocus <= 0) hasFocus = menu->itemCount - 1; else hasFocus--; } while(menu->items[hasFocus].type == ITT_EMPTY && i++ < menu->itemCount); itemOn = hasFocus; menu_color = 0; S_LocalSound(SFX_MENU_NAV_UP, NULL); M_UpdateMenuVisibleItems(); break; case MCMD_NAV_OUT: menu->lastOn = hasFocus; if(menu->prevMenu == MENU_NONE) { menu->lastOn = hasFocus; S_LocalSound(SFX_MENU_CLOSE, NULL); Hu_MenuCommand(MCMD_CLOSE); } else { S_LocalSound(SFX_MENU_CANCEL, NULL); M_SetupNextMenu(menulist[menu->prevMenu]); } break; case MCMD_DELETE: if(menu->flags & MNF_DELETEFUNC) { if(item->func) { S_LocalSound(SFX_MENU_CANCEL, NULL); item->func(-1, item->data); } } break; case MCMD_SELECT: if(item->type == ITT_SETMENU) { S_LocalSound(SFX_MENU_ACCEPT, NULL); M_SetupNextMenu(menulist[item->option]); } else if(item->func != NULL) { menu->lastOn = hasFocus; if(item->type == ITT_LRFUNC) { S_LocalSound(SFX_MENU_CYCLE, NULL); item->func(RIGHT_DIR | item->option, item->data); } else if(item->type == ITT_EFUNC) { S_LocalSound(SFX_MENU_CYCLE, NULL); item->func(item->option, item->data); } } break; } } } /** * Responds to alphanumeric input for edit fields. */ boolean M_EditResponder(event_t *ev) { int ch = -1; char* ptr; if(!saveStringEnter && !ActiveEdit) return false; if(ev->type != EV_KEY) return false; if(ev->data1 == DDKEY_RSHIFT) { shiftdown = (ev->state == EVS_DOWN || ev->state == EVS_REPEAT); return true; } if(!(ev->state == EVS_DOWN || ev->state == EVS_REPEAT)) return false; ch = ev->data1; if(ch >= ' ' && ch <= 'z') { if(shiftdown) ch = shiftXForm[ch]; if(saveStringEnter) { if(saveCharIndex < HU_SAVESTRINGSIZE && M_StringWidth(savegamestrings[saveSlot], GF_FONTA) < (HU_SAVESTRINGSIZE - 1) * 8) { savegamestrings[saveSlot][saveCharIndex++] = ch; savegamestrings[saveSlot][saveCharIndex] = 0; } } else { // Filter out nasty characters. if(ch == '%') return true; if(strlen(ActiveEdit->text) < MAX_EDIT_LEN - 2) { ptr = ActiveEdit->text + strlen(ActiveEdit->text); ptr[0] = ch; ptr[1] = 0; Ed_MakeCursorVisible(); } } return true; } return false; } /** * Handles the hotkey selection in the menu. * * @return @c true, if it ate the event. */ int Hu_MenuResponder(event_t* ev) { menu_t* menu; if(!menuActive || widgetEdit) return false; menu = currentMenu; /** * Handle navigation by "hotkeys", if enabled. * * The first ASCII character of a menu item's text string is used * as a "hotkey" shortcut to allow navigating directly to that item. */ if(cfg.menuHotkeys && !(menu->flags & MNF_NOHOTKEYS) && ev->type == EV_KEY && (ev->state == EVS_DOWN || ev->state == EVS_REPEAT)) { int i, first, last; // First and last, visible menu items. int cand = toupper(ev->data1); first = last = menu->firstItem; last += menu->numVisItems - 1; if(last > menu->itemCount - 1) last = menu->itemCount - 1; menu->lastOn = itemOn; for(i = first; i <= last; ++i) { const menuitem_t* item = &menu->items[i]; if(item->text && item->text[0] && item->type != ITT_EMPTY) { const char* ch = item->text; boolean inParamBlock = false; /** * Skip over any paramater blocks, we are only interested * in the first (drawable) ASCII character. * * \assume Item text strings are '\0' terminated. */ do { if(!ch) break; if(inParamBlock) { if(*ch == '}') inParamBlock = false; } else { if(*ch == '{') { inParamBlock = true; } else if(!(*ch == ' ' || *ch == '\n')) { break; // First drawable character found. } } } while(*ch++); if(ch && *ch == cand) { itemOn = i; return true; } } } } return false; } /** * The colour widget edits the "hot" currentcolour[] * The widget responder handles setting the specified vars to that of the * currentcolour. * * \fixme The global value rgba (fixme!) is used to control if rgb or rgba input * is needed, as defined in the widgetcolors array. */ void DrawColorWidget(void) { int w = 0; menu_t *menu = &ColorWidgetMnu; if(widgetEdit) { #if __JDOOM__ || __JDOOM64__ w = 38; #else w = 46; #endif M_DrawBackgroundBox(menu->x -30, menu->y -40, #if __JDOOM__ || __JDOOM64__ 160, (rgba? 85 : 75), #else 180, (rgba? 170 : 140), #endif 1, 1, 1, menuAlpha, true, BORDERUP); DGL_SetNoMaterial(); DGL_DrawRect(menu->x+w, menu->y-30, 24, 22, currentcolor[0], currentcolor[1], currentcolor[2], currentcolor[3]); M_DrawBackgroundBox(menu->x+w, menu->y-30, 24, 22, 1, 1, 1, menuAlpha, false, BORDERDOWN); #if __JDOOM__ || __JDOOM64__ MN_DrawSlider(menu, 0, 11, currentcolor[0] * 10 + .25f); M_WriteText3(menu->x, menu->y, ColorWidgetItems[0].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); MN_DrawSlider(menu, 1, 11, currentcolor[1] * 10 + .25f); M_WriteText3(menu->x, menu->y + (LINEHEIGHT_A), ColorWidgetItems[1].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); MN_DrawSlider(menu, 2, 11, currentcolor[2] * 10 + .25f); M_WriteText3(menu->x, menu->y + (LINEHEIGHT_A * 2), ColorWidgetItems[2].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); #else MN_DrawSlider(menu, 1, 11, currentcolor[0] * 10 + .25f); M_WriteText3(menu->x, menu->y, ColorWidgetItems[0].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); MN_DrawSlider(menu, 4, 11, currentcolor[1] * 10 + .25f); M_WriteText3(menu->x, menu->y + (LINEHEIGHT_A * 3), ColorWidgetItems[3].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); MN_DrawSlider(menu, 7, 11, currentcolor[2] * 10 + .25f); M_WriteText3(menu->x, menu->y + (LINEHEIGHT_A * 6), ColorWidgetItems[6].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); #endif if(rgba) { #if __JDOOM__ || __JDOOM64__ MN_DrawSlider(menu, 3, 11, currentcolor[3] * 10 + .25f); M_WriteText3(menu->x, menu->y + (LINEHEIGHT_A * 3), ColorWidgetItems[3].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); #else MN_DrawSlider(menu, 10, 11, currentcolor[3] * 10 + .25f); M_WriteText3(menu->x, menu->y + (LINEHEIGHT_A * 9), ColorWidgetItems[9].text, GF_FONTA, 1, 1, 1, menuAlpha, true, true, 0); #endif } } } /** * Inform the menu to activate the color widget * An intermediate step. Used to copy the existing rgba values pointed * to by the index (these match an index in the widgetcolors array) into * the "hot" currentcolor[] slots. Also switches between rgb/rgba input. */ void SCColorWidget(int index, void* context) { currentcolor[0] = *widgetcolors[index].r; currentcolor[1] = *widgetcolors[index].g; currentcolor[2] = *widgetcolors[index].b; // Set the index of the colour being edited editcolorindex = index; // Remember the position of the Skull on the main menu previtemOn = itemOn; // Set the start position to 0; itemOn = 0; // Do we want rgb or rgba sliders? if(widgetcolors[index].a) { rgba = true; currentcolor[3] = *widgetcolors[index].a; } else { rgba = false; currentcolor[3] = 1.0f; } // Activate the widget widgetEdit = true; } void M_ToggleVar(int index, void* context) { char* cvarname; if(!context) return; cvarname = (char*) context; DD_Executef(true, "toggle %s", cvarname); } void M_DrawTitle(char *text, int y) { WI_DrawParamText(160 - M_StringWidth(text, GF_FONTB) / 2, y, text, GF_FONTB, cfg.menuColor[0], cfg.menuColor[1], cfg.menuColor[2], menuAlpha, true, true, ALIGN_LEFT); } boolean MN_IsItemVisible(const menu_t* menu, int item) { if(item < menu->firstItem || item >= menu->firstItem + menu->numVisItems) return false; return true; } void M_WriteMenuText(const menu_t* menu, int index, const char* text) { int off = 0; if(!MN_IsItemVisible(menu, index)) return; if(menu->items[index].text) off = M_StringWidth(menu->items[index].text, menu->font) + 4; M_WriteText3(menu->x + off, menu->y + menu->itemHeight * (index - menu->firstItem), text, menu->font, 1, 1, 1, menuAlpha, true, true, 0); } /** * User wants to load this game */ void M_LoadSelect(int option, void* context) { menu_t* menu = &SaveDef; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ filename_t name; #endif menu->lastOn = option; Hu_MenuCommand(MCMD_CLOSEFAST); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ SV_GetSaveGameFileName(name, option, FILENAME_T_MAXLEN); G_LoadGame(name); #else G_LoadGame(option); #endif } /** * User wants to save. Start string input for Hu_MenuResponder */ void M_SaveSelect(int option, void* context) { menu_t* menu = &LoadDef; // we are going to be intercepting all chars saveStringEnter = 1; menu->lastOn = saveSlot = option; strncpy(saveOldString, savegamestrings[option], HU_SAVESTRINGSIZE); if(!strcmp(savegamestrings[option], EMPTYSTRING)) savegamestrings[option][0] = 0; saveCharIndex = strlen(savegamestrings[option]); } void M_DrawMainMenu(void) { #if __JHEXEN__ int frame; frame = (menuTime / 5) % 7; DGL_Color4f(1, 1, 1, menuAlpha); GL_DrawPatch_CS(88, 0, m_htic.lump); GL_DrawPatch_CS(37, 80, SkullBaseLump + (frame + 2) % 7); GL_DrawPatch_CS(278, 80, SkullBaseLump + frame); #elif __JHERETIC__ WI_DrawPatch(88, 0, 1, 1, 1, menuAlpha, &m_htic, NULL, false, ALIGN_LEFT); DGL_Color4f(1, 1, 1, menuAlpha); GL_DrawPatch_CS(40, 10, SkullBaseLump + (17 - frame)); GL_DrawPatch_CS(232, 10, SkullBaseLump + frame); #elif __JDOOM__ || __JDOOM64__ WI_DrawPatch(94, 2, 1, 1, 1, menuAlpha, &m_doom, NULL, false, ALIGN_LEFT); #elif __JSTRIFE__ menu_t *menu = &MainDef; int yoffset = 0; WI_DrawPatch(84, 2, 1, 1, 1, menuAlpha, W_GetNumForName("M_STRIFE"), NULL, false, ALIGN_LEFT); WI_DrawPatch(menu->x, menu->y + yoffset, 1, 1, 1, menuAlpha, W_GetNumForName("M_NGAME"), NULL, false, ALIGN_LEFT); WI_DrawPatch(menu->x, menu->y + (yoffset+= menu->itemHeight), 1, 1, 1, menuAlpha, W_GetNumForName("M_NGAME"), NULL, false, ALIGN_LEFT); WI_DrawPatch(menu->x, menu->y + (yoffset+= menu->itemHeight), 1, 1, 1, menuAlpha, W_GetNumForName("M_OPTION"), NULL, false, ALIGN_LEFT); WI_DrawPatch(menu->x, menu->y + (yoffset+= menu->itemHeight), 1, 1, 1, menuAlpha, W_GetNumForName("M_LOADG"), NULL, false, ALIGN_LEFT); WI_DrawPatch(menu->x, menu->y + (yoffset+= menu->itemHeight), 1, 1, 1, menuAlpha, W_GetNumForName("M_SAVEG"), NULL, false, ALIGN_LEFT); WI_DrawPatch(menu->x, menu->y + (yoffset+= menu->itemHeight), 1, 1, 1, menuAlpha, W_GetNumForName("M_RDTHIS"), NULL, false, ALIGN_LEFT); WI_DrawPatch(menu->x, menu->y + (yoffset+= menu->itemHeight), 1, 1, 1, menuAlpha, W_GetNumForName("M_QUITG"), NULL, false, ALIGN_LEFT); #endif } void M_DrawNewGameMenu(void) { menu_t* menu = &NewGameDef; M_DrawTitle(GET_TXT(TXT_PICKGAMETYPE), menu->y - 30); } void M_DrawReadThis(void) { #if __JDOOM__ // The background is handled elsewhere, just draw the cursor. GL_DrawPatch(298, 160, cursorst[whichSkull].lump); #endif } #if __JHERETIC__ static void composeNotDesignedForMessage(const char* str) { char* buf = notDesignedForMessage, *in, tmp[2]; buf[0] = 0; tmp[1] = 0; // Get the message template. in = GET_TXT(TXT_NOTDESIGNEDFOR); for(; *in; in++) { if(in[0] == '%') { if(in[1] == '1') { strcat(buf, str); in++; continue; } if(in[1] == '%') in++; } tmp[0] = *in; strcat(buf, tmp); } } #endif #if __JHEXEN__ void M_DrawClassMenu(void) { #define BG_X (174) #define BG_Y (8) menu_t* menu = &ClassDef; int pClass; spriteinfo_t sprInfo; int tmap = 1, hasFocus = MAX_OF(0, itemOn); static char* boxLumpName[3] = { "m_fbox", "m_cbox", "m_mbox" }; M_WriteText3(34, 24, "CHOOSE CLASS:", GF_FONTB, menu->color[0], menu->color[1], menu->color[2], menuAlpha, true, true, 0); pClass = menu->items[hasFocus].option; if(pClass < 0) { // Random class. // Number of user-selectable classes. pClass = (menuTime / 5) % (menu->itemCount - 1); } R_GetSpriteInfo(STATES[PCLASS_INFO(pClass)->normalState].sprite, ((menuTime >> 3) & 3), &sprInfo); DGL_Color4f(1, 1, 1, menuAlpha); GL_DrawPatch_CS(BG_X, BG_Y, W_GetNumForName(boxLumpName[pClass % 3])); // Fighter's colors are a bit different. if(pClass == PCLASS_FIGHTER) tmap = 2; DGL_SetTranslatedSprite(sprInfo.material, 1, tmap); DGL_DrawRect(BG_X + 56 - sprInfo.offset, BG_Y + 78 - sprInfo.topOffset, M_CeilPow2(sprInfo.width), M_CeilPow2(sprInfo.height), 1, 1, 1, menuAlpha); #undef BG_X #undef BG_Y } #endif #if __JDOOM__ || __JHERETIC__ void M_DrawEpisode(void) { menu_t* menu = &EpiDef; #if __JHERETIC__ M_DrawTitle("WHICH EPISODE?", 4); /** * \kludge Inform the user episode 6 is designed for deathmatch only. */ if(itemOn >= 0 && menu->items[itemOn].option == 5) { const char* str = notDesignedForMessage; composeNotDesignedForMessage(GET_TXT(TXT_SINGLEPLAYER)); M_WriteText3(160 - M_StringWidth(str, GF_FONTA) / 2, 200 - M_StringHeight(str, GF_FONTA) - 2, str, GF_FONTA, cfg.menuColor2[0], cfg.menuColor2[1], cfg.menuColor2[2], menuAlpha, true, true, 0); } #else // __JDOOM__ WI_DrawPatch(50, 40, menu->color[0], menu->color[1], menu->color[2], menuAlpha, &m_episod, "{case}Which Episode{scaley=1.25,y=-3}?", true, ALIGN_LEFT); #endif } #endif void M_DrawSkillMenu(void) { #if __JHEXEN__ || __JSTRIFE__ M_DrawTitle("CHOOSE SKILL LEVEL:", 16); #elif __JHERETIC__ M_DrawTitle("SKILL LEVEL?", 4); #elif __JDOOM__ || __JDOOM64__ menu_t *menu = &SkillDef; WI_DrawPatch(96, 14, menu->color[0], menu->color[1], menu->color[2], menuAlpha, &m_newg, "{case}NEW GAME", true, ALIGN_LEFT); WI_DrawPatch(54, 38, menu->color[0], menu->color[1], menu->color[2], menuAlpha, &m_skill, "{case}Choose Skill Level:", true, ALIGN_LEFT); #endif } void M_DrawFilesMenu(void) { // clear out the quicksave/quickload stuff quicksave = 0; quickload = 0; } /** * Read the strings from the savegame files. */ static boolean readSaveString(char* str, const char* fileName, size_t len) { if(!SV_GetSaveDescription(str, fileName, len)) { strncpy(str, EMPTYSTRING, len); return false; } return true; } static void updateSaveList(void) { int i; filename_t fileName; for(i = 0; i < NUMSAVESLOTS; ++i) { menuitem_t* loadSlot = &LoadItems[i]; SV_GetSaveGameFileName(fileName, i, FILENAME_T_MAXLEN); memset(savegamestrings[i], 0, HU_SAVESTRINGSIZE); if(readSaveString(savegamestrings[i], fileName, HU_SAVESTRINGSIZE)) { loadSlot->type = ITT_EFUNC; } else { loadSlot->type = ITT_EMPTY; } } } #if __JDOOM__ || __JDOOM64__ #define SAVEGAME_BOX_YOFFSET 3 #else #define SAVEGAME_BOX_YOFFSET 5 #endif void M_DrawLoad(void) { int i; menu_t* menu = &LoadDef; float t, r, g, b; int width = M_StringWidth("a", menu->font) * (HU_SAVESTRINGSIZE - 1); #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ M_DrawTitle("LOAD GAME", 4); #else WI_DrawPatch(72, 24, menu->color[0], menu->color[1], menu->color[2], menuAlpha, &m_loadg, "{case}LOAD GAME", true, ALIGN_LEFT); #endif if(menu_color <= 50) t = menu_color / 50.0f; else t = (100 - menu_color) / 50.0f; r = currentMenu->color[0] * t + cfg.flashColor[0] * (1 - t); g = currentMenu->color[1] * t + cfg.flashColor[1] * (1 - t); b = currentMenu->color[2] * t + cfg.flashColor[2] * (1 - t); for(i = 0; i < NUMSAVESLOTS; ++i) { M_DrawSaveLoadBorder(LoadDef.x - 8, SAVEGAME_BOX_YOFFSET + LoadDef.y + (menu->itemHeight * i), width + 16); M_WriteText3(LoadDef.x, SAVEGAME_BOX_YOFFSET + LoadDef.y + 1 + (menu->itemHeight * i), savegamestrings[i], menu->font, i == itemOn? r : menu->color[0], i == itemOn? g : menu->color[1], i == itemOn? b : menu->color[2], menuAlpha, true, true, 0); } } void M_DrawSave(void) { int i; menu_t* menu = &SaveDef; float t, r, g, b; int width = M_StringWidth("a", menu->font) * (HU_SAVESTRINGSIZE - 1); #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ M_DrawTitle("SAVE GAME", 4); #else WI_DrawPatch(72, 24, menu->color[0], menu->color[1], menu->color[2], menuAlpha, &m_saveg, "{case}SAVE GAME", true, ALIGN_LEFT); #endif if(menu_color <= 50) t = menu_color / 50.0f; else t = (100 - menu_color) / 50.0f; r = currentMenu->color[0] * t + cfg.flashColor[0] * (1 - t); g = currentMenu->color[1] * t + cfg.flashColor[1] * (1 - t); b = currentMenu->color[2] * t + cfg.flashColor[2] * (1 - t); for(i = 0; i < NUMSAVESLOTS; ++i) { M_DrawSaveLoadBorder(SaveDef.x - 8, SAVEGAME_BOX_YOFFSET + SaveDef.y + (menu->itemHeight * i), width + 16); M_WriteText3(SaveDef.x, SAVEGAME_BOX_YOFFSET + SaveDef.y + 1 + (menu->itemHeight * i), savegamestrings[i], menu->font, i == itemOn? r : menu->color[0], i == itemOn? g : menu->color[1], i == itemOn? b : menu->color[2], menuAlpha, true, true, 0); } if(saveStringEnter) { size_t len = strlen(savegamestrings[saveSlot]); if(len < HU_SAVESTRINGSIZE) { i = M_StringWidth(savegamestrings[saveSlot], GF_FONTA); M_WriteText3(SaveDef.x + i, SAVEGAME_BOX_YOFFSET + SaveDef.y + 1 + (menu->itemHeight * saveSlot), "_", GF_FONTA, r, g, b, menuAlpha, true, true, 0); } } } /** * Draw border for the savegame description */ void M_DrawSaveLoadBorder(int x, int y, int width) { #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ DGL_Color4f(1, 1, 1, menuAlpha); GL_DrawPatch_CS(x - 8, y - 4, dpFSlot.lump); #else DGL_Color4f(1, 1, 1, menuAlpha); DGL_SetPatch(dpLSLeft.lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(x, y - 3, dpLSLeft.width, dpLSLeft.height, 1, 1, 1, menuAlpha); DGL_SetPatch(dpLSRight.lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(x + width - dpLSRight.width, y - 3, dpLSRight.width, dpLSRight.height, 1, 1, 1, menuAlpha); DGL_SetPatch(dpLSCntr.lump, DGL_REPEAT, DGL_REPEAT); DGL_DrawRectTiled(x + dpLSLeft.width, y - 3, width - dpLSLeft.width - dpLSRight.width, 14, 8, 14); #endif } int M_QuickSaveResponse(msgresponse_t response, void* context) { if(response == MSG_YES) G_SaveGame(quickSaveSlot, savegamestrings[quickSaveSlot]); return true; } /** * Called via the bindings mechanism when a player wishes to save their * game to a preselected save slot. */ static void M_QuickSave(void) { player_t* player = &players[CONSOLEPLAYER]; if(player->playerState == PST_DEAD || Get(DD_PLAYBACK)) { S_LocalSound(SFX_QUICKSAVE_PROMPT, NULL); Hu_MsgStart(MSG_ANYKEY, SAVEDEAD, NULL, NULL); return; } if(G_GetGameState() != GS_MAP) { S_LocalSound(SFX_QUICKSAVE_PROMPT, NULL); Hu_MsgStart(MSG_ANYKEY, SAVEOUTMAP, NULL, NULL); return; } if(quickSaveSlot < 0) { Hu_MenuCommand(MCMD_OPEN); updateSaveList(); M_SetupNextMenu(&SaveDef); quickSaveSlot = -2; // Means to pick a slot now. return; } sprintf(tempstring, QSPROMPT, savegamestrings[quickSaveSlot]); if(!cfg.askQuickSaveLoad) { S_LocalSound(SFX_MENU_ACCEPT, NULL); G_SaveGame(quickSaveSlot, savegamestrings[quickSaveSlot]); return; } S_LocalSound(SFX_QUICKSAVE_PROMPT, NULL); Hu_MsgStart(MSG_YESNO, tempstring, M_QuickSaveResponse, NULL); } int M_QuickLoadResponse(msgresponse_t response, void* context) { if(response == MSG_YES) { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ filename_t name; SV_GetSaveGameFileName(name, quickSaveSlot, FILENAME_T_MAXLEN); G_LoadGame(name); #else G_LoadGame(quickSaveSlot); #endif } return true; } static void M_QuickLoad(void) { if(IS_NETGAME) { S_LocalSound(SFX_QUICKLOAD_PROMPT, NULL); Hu_MsgStart(MSG_ANYKEY, QLOADNET, NULL, NULL); return; } if(quickSaveSlot < 0) { S_LocalSound(SFX_QUICKLOAD_PROMPT, NULL); Hu_MsgStart(MSG_ANYKEY, QSAVESPOT, NULL, NULL); return; } sprintf(tempstring, QLPROMPT, savegamestrings[quickSaveSlot]); if(!cfg.askQuickSaveLoad) { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ filename_t name; SV_GetSaveGameFileName(name, quickSaveSlot, FILENAME_T_MAXLEN); G_LoadGame(name); #else G_LoadGame(quickSaveSlot); #endif S_LocalSound(SFX_MENU_ACCEPT, NULL); return; } S_LocalSound(SFX_QUICKLOAD_PROMPT, NULL); Hu_MsgStart(MSG_YESNO, tempstring, M_QuickLoadResponse, NULL); } #if !__JDOOM64__ void M_ReadThis(int option, void* context) { option = 0; M_SetupNextMenu(&ReadDef1); } void M_ReadThis2(int option, void* context) { option = 0; M_SetupNextMenu(&ReadDef2); } # if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ void M_ReadThis3(int option, void* context) { option = 0; M_SetupNextMenu(&ReadDef3); } # endif void M_FinishReadThis(int option, void* context) { option = 0; M_SetupNextMenu(&MainDef); } #endif void M_DrawOptions(void) { menu_t* menu = &OptionsDef; #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ M_DrawTitle("OPTIONS", menu->y - 32); #else # if __JDOOM64__ WI_DrawPatch(160, menu->y - 20, cfg.menuColor[0], cfg.menuColor[1], cfg.menuColor[2], menuAlpha, 0, "{case}OPTIONS", true, ALIGN_CENTER); #else WI_DrawPatch(160, menu->y - 20, cfg.menuColor[0], cfg.menuColor[1], cfg.menuColor[2], menuAlpha, &m_optttl, "{case}OPTIONS", true, ALIGN_CENTER); # endif #endif } void M_DrawOptions2(void) { menu_t* menu = &Options2Def; #if __JDOOM__ || __JDOOM64__ M_DrawTitle("SOUND OPTIONS", menu->y - 20); MN_DrawSlider(menu, 0, 16, SFXVOLUME); MN_DrawSlider(menu, 1, 16, MUSICVOLUME); #else M_DrawTitle("SOUND OPTIONS", 0); MN_DrawSlider(menu, 1, 16, SFXVOLUME); MN_DrawSlider(menu, 4, 16, MUSICVOLUME); #endif } void M_DrawGameplay(void) { int idx = 0; menu_t* menu = &GameplayDef; #if __JHEXEN__ M_DrawTitle("GAMEPLAY", 0); M_WriteMenuText(menu, idx++, yesno[cfg.alwaysRun != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.lookSpring != 0]); M_WriteMenuText(menu, idx++, yesno[!cfg.noAutoAim]); #else # if __JHERETIC__ M_DrawTitle("GAMEPLAY", 4); # else M_DrawTitle("GAMEPLAY", menu->y - 20); # endif M_WriteMenuText(menu, idx++, yesno[cfg.alwaysRun != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.lookSpring != 0]); M_WriteMenuText(menu, idx++, yesno[!cfg.noAutoAim]); M_WriteMenuText(menu, idx++, yesno[cfg.jumpEnabled != 0]); # if __JDOOM64__ M_WriteMenuText(menu, idx++, yesno[cfg.weaponRecoil != 0]); idx = 7; # else idx = 6; # endif # if __JDOOM__ || __JDOOM64__ M_WriteMenuText(menu, idx++, yesno[cfg.anyBossDeath != 0]); # if !__JDOOM64__ M_WriteMenuText(menu, idx++, yesno[cfg.raiseGhosts != 0]); # endif M_WriteMenuText(menu, idx++, yesno[cfg.maxSkulls != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.allowSkullsInWalls != 0]); # endif # if __JDOOM__ || __JHERETIC__ || __JDOOM64__ M_WriteMenuText(menu, idx++, yesno[cfg.monstersStuckInDoors != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.avoidDropoffs != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.fallOff != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.slidingCorpses != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.moveBlock != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.wallRunNorthOnly != 0]); # endif # if __JDOOM__ || __JDOOM64__ M_WriteMenuText(menu, idx++, yesno[cfg.zombiesCanExit != 0]); # endif # if __JDOOM__ M_WriteMenuText(menu, idx++, yesno[cfg.fixOuchFace != 0]); M_WriteMenuText(menu, idx++, yesno[cfg.fixStatusbarOwnedWeapons != 0]); # endif #endif } void M_DrawWeaponMenu(void) { menu_t *menu = &WeaponDef; int i = 0; char *autoswitch[] = { "NEVER", "IF BETTER", "ALWAYS" }; #if __JHEXEN__ char *weaponids[] = { "First", "Second", "Third", "Fourth"}; #endif #if __JDOOM__ || __JDOOM64__ byte berserkAutoSwitch = cfg.berserkAutoSwitch; #endif M_DrawTitle("WEAPONS", menu->y - 26); /** * \kludge Inform the user how to change the order. */ if(itemOn - 1 >= 0 && itemOn - 1 < NUM_WEAPON_TYPES) { const char* str = "Use left/right to move weapon up/down"; M_WriteText3(160 - M_StringWidth(str, GF_FONTA) / 2, 200 - M_StringHeight(str, GF_FONTA) - 2, str, GF_FONTA, cfg.menuColor2[0], cfg.menuColor2[1], cfg.menuColor2[2], menuAlpha, true, true, 0); } for(i = 0; i < NUM_WEAPON_TYPES; ++i) { #if __JDOOM__ || __JDOOM64__ M_WriteMenuText(menu, 1+i, GET_TXT(TXT_WEAPON1 + cfg.weaponOrder[i])); #elif __JHERETIC__ /** * \fixme We should allow different weapon preferences per player * class. However, since the only other class in jHeretic is the * chicken which has only 1 weapon anyway -we'll just show the * names of the player's weapons for now. */ M_WriteMenuText(menu, 1+i, GET_TXT(TXT_TXT_WPNSTAFF + cfg.weaponOrder[i])); #elif __JHEXEN__ /** * \fixme We should allow different weapon preferences per player * class. Then we can show the real names here. */ M_WriteMenuText(menu, 1+i, weaponids[cfg.weaponOrder[i]]); #endif } #if __JHEXEN__ M_WriteMenuText(menu, 5, yesno[cfg.weaponNextMode]); M_WriteMenuText(menu, 8, autoswitch[cfg.weaponAutoSwitch]); M_WriteMenuText(menu, 9, yesno[cfg.noWeaponAutoSwitchIfFiring]); M_WriteMenuText(menu, 10, autoswitch[cfg.ammoAutoSwitch]); #elif __JHERETIC__ M_WriteMenuText(menu, 9, yesno[cfg.weaponNextMode]); M_WriteMenuText(menu, 12, autoswitch[cfg.weaponAutoSwitch]); M_WriteMenuText(menu, 13, yesno[cfg.noWeaponAutoSwitchIfFiring]); M_WriteMenuText(menu, 14, autoswitch[cfg.ammoAutoSwitch]); #elif __JDOOM64__ M_WriteMenuText(menu, 11, yesno[cfg.weaponNextMode]); M_WriteMenuText(menu, 14, autoswitch[cfg.weaponAutoSwitch]); M_WriteMenuText(menu, 15, yesno[cfg.noWeaponAutoSwitchIfFiring]); M_WriteMenuText(menu, 16, autoswitch[cfg.ammoAutoSwitch]); M_WriteMenuText(menu, 17, yesno[berserkAutoSwitch != 0]); #elif __JDOOM__ M_WriteMenuText(menu, 10, yesno[cfg.weaponNextMode]); M_WriteMenuText(menu, 13, autoswitch[cfg.weaponAutoSwitch]); M_WriteMenuText(menu, 14, yesno[cfg.noWeaponAutoSwitchIfFiring]); M_WriteMenuText(menu, 15, autoswitch[cfg.ammoAutoSwitch]); M_WriteMenuText(menu, 16, yesno[berserkAutoSwitch != 0]); #endif } void M_WeaponOrder(int option, void* context) { int choice = option >> NUM_WEAPON_TYPES; int temp; if(option & RIGHT_DIR) { if(choice < NUM_WEAPON_TYPES-1) { temp = cfg.weaponOrder[choice+1]; cfg.weaponOrder[choice+1] = cfg.weaponOrder[choice]; cfg.weaponOrder[choice] = temp; itemOn++; } } else { if(choice > 0) { temp = cfg.weaponOrder[choice]; cfg.weaponOrder[choice] = cfg.weaponOrder[choice-1]; cfg.weaponOrder[choice-1] = temp; itemOn--; } } } void M_WeaponAutoSwitch(int option, void* context) { if(option == RIGHT_DIR) { if(cfg.weaponAutoSwitch < 2) cfg.weaponAutoSwitch++; } else if(cfg.weaponAutoSwitch > 0) cfg.weaponAutoSwitch--; } void M_AmmoAutoSwitch(int option, void* context) { if(option == RIGHT_DIR) { if(cfg.ammoAutoSwitch < 2) cfg.ammoAutoSwitch++; } else if(cfg.ammoAutoSwitch > 0) cfg.ammoAutoSwitch--; } #if __JHERETIC__ || __JHEXEN__ void M_DrawInventoryMenu(void) { menu_t* menu = &InventoryDef; int idx = 0; static char* modeNames[2] = { "Cursor", "Scroll" }; M_DrawTitle("Inventory Options", menu->y - 28); M_WriteMenuText(menu, idx++, modeNames[cfg.inventorySelectMode? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.inventoryWrap? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.inventoryUseImmediate? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.inventoryUseNext? 1 : 0]); // Auto-hide option: { char secString[11]; const char* str; uint seconds = MINMAX_OF(0, cfg.inventoryTimer, 30); if(seconds > 0) { memset(secString, 0, sizeof(secString)); dd_snprintf(secString, 11, "%2u seconds", seconds); str = secString; } else str = "Disabled"; M_WriteMenuText(menu, idx++, str); } idx += 2; { char buff[3]; const char* str; uint val = MINMAX_OF(0, cfg.inventorySlotMaxVis, 16); if(val > 0) { memset(buff, 0, sizeof(buff)); dd_snprintf(buff, 3, "%2u", val); str = buff; } else str = "Automatic"; M_WriteMenuText(menu, idx++, str); M_WriteMenuText(menu, idx++, yesno[cfg.inventorySlotShowEmpty? 1 : 0]); } } #endif /** * @todo This could use a cleanup. */ void M_DrawHUDMenu(void) { int idx;//, page; menu_t* menu = &HUDDef; #if __JDOOM__ || __JDOOM64__ char buf[1024]; #endif #if __JHERETIC__ || __JHEXEN__ char* token; #endif char* xhairnames[7] = { "NONE", "CROSS", "ANGLES", "SQUARE", "OPEN SQUARE", "DIAMOND", "V" }; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ static char* countnames[4] = { "HIDDEN", "COUNT", "PERCENT", "COUNT+PCNT" }; #endif M_DrawTitle("HUD options", menu->y - 28); #if __JDOOM__ || __JDOOM64__ Hu_MenuPageString(buf, menu); M_WriteText3(160 - M_StringWidth(buf, GF_FONTA) / 2, menu->y - 12, buf, GF_FONTA, 1, .7f, .3f, Hu_MenuAlpha(), true, true, 0); #else DGL_Color4f(1, 1, 1, Hu_MenuAlpha()); // Draw the page arrows. token = (!menu->firstItem || menuTime & 8) ? "invgeml2" : "invgeml1"; GL_DrawPatch_CS(menu->x, menu->y - 22, W_GetNumForName(token)); token = (menu->firstItem + menu->numVisItems >= menu->itemCount || menuTime & 8) ? "invgemr2" : "invgemr1"; GL_DrawPatch_CS(312 - menu->x, menu->y - 22, W_GetNumForName(token)); #endif idx = 0; #if __JHERETIC__ || __JHEXEN__ idx++; #endif MN_DrawSlider(menu, idx++, 11, cfg.screenBlocks - 3); #if __JHERETIC__ || __JHEXEN__ idx++; #endif #if __JDOOM__ M_WriteMenuText(menu, idx++, yesno[cfg.hudKeysCombine]); #endif M_WriteMenuText(menu, idx++, yesno[cfg.msgShow != 0]); { char secString[11]; const char* str; uint seconds = MINMAX_OF(1, cfg.msgUptime, 30); memset(secString, 0, sizeof(secString)); dd_snprintf(secString, 11, "%2u %s", seconds, seconds > 1? "seconds" : "second"); str = secString; M_WriteMenuText(menu, idx++, str); } // Auto-hide HUD options: { char secString[11]; const char* str; uint seconds = MINMAX_OF(0, cfg.hudTimer, 30); if(seconds > 0) { memset(secString, 0, sizeof(secString)); dd_snprintf(secString, 11, "%2u %s", seconds, seconds > 1? "seconds" : "second"); str = secString; } else str = "Disabled"; M_WriteMenuText(menu, idx++, str); } idx++; M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_DAMAGE]? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_PICKUP_HEALTH]? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_PICKUP_ARMOR]? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_PICKUP_POWER]? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_PICKUP_WEAPON]? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_PICKUP_AMMO]? 1 : 0]); M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_PICKUP_KEY]? 1 : 0]); #if __JHERETIC__ || __JHEXEN__ M_WriteMenuText(menu, idx++, yesno[cfg.hudUnHide[HUE_ON_PICKUP_INVITEM]? 1 : 0]); #endif #if __JDOOM__ || __JDOOM64__ idx++; #endif // Crosshair options: idx++; #if __JHERETIC__ || __JHEXEN__ idx++; #endif M_WriteMenuText(menu, idx++, xhairnames[cfg.xhair]); #if __JHERETIC__ || __JHEXEN__ idx++; #endif MN_DrawSlider(menu, idx++, 11, cfg.xhairSize * 10 + .25f); #if __JHERETIC__ || __JHEXEN__ idx++; #endif M_WriteMenuText(menu, idx++, yesno[cfg.xhairVitality != 0]); MN_DrawColorBox(menu, idx++, cfg.xhairColor[0], cfg.xhairColor[1], cfg.xhairColor[2], cfg.xhairColor[3]); #if __JHERETIC__ || __JHEXEN__ idx++; #endif #if !__JDOOM64__ // Statusbar options: idx += 2; MN_DrawSlider(menu, idx++, 20, cfg.statusbarScale - 1); #if __JHERETIC__ || __JHEXEN__ idx += 2; #endif MN_DrawSlider(menu, idx++, 11, cfg.statusbarOpacity * 10 + .25f); #if __JDOOM__ || __JDOOM64__ idx++; #endif #endif #if __JHERETIC__ || __JHEXEN__ idx++; #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ // Counters: idx++; M_WriteMenuText(menu, idx++, countnames[(cfg.counterCheat & 0x1) | ((cfg.counterCheat & 0x8) >> 2)]); M_WriteMenuText(menu, idx++, countnames[((cfg.counterCheat & 0x2) >> 1) | ((cfg.counterCheat & 0x10) >> 3)]); M_WriteMenuText(menu, idx++, countnames[((cfg.counterCheat & 0x4) >> 2) | ((cfg.counterCheat & 0x20) >> 4)]); #endif // Fullscreen HUD options: idx += 2; #if __JHERETIC__ idx++; #endif MN_DrawSlider(menu, idx++, 8, cfg.hudScale * 10 - 3 + .5f); #if __JHERETIC__ || __JHEXEN__ idx++; #endif MN_DrawColorBox(menu, idx++, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], cfg.hudColor[3]); #if __JHEXEN__ M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_MANA]]); #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_AMMO]]); M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_ARMOR]]); #endif #if __JDOOM64__ M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_INVENTORY]]); #endif #if __JDOOM__ M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_FACE]]); #endif M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_HEALTH]]); #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_KEYS]]); #endif #if __JHERETIC__ || __JHEXEN__ M_WriteMenuText(menu, idx++, yesno[cfg.hudShown[HUD_CURRENTITEM]]); #endif } void M_FloatMod10(float *variable, int option) { int val = (*variable + .05f) * 10; if(option == RIGHT_DIR) { if(val < 10) val++; } else if(val > 0) val--; *variable = val / 10.0f; } /** * Set the show kills counter */ void M_KillCounter(int option, void *data) { int op = (cfg.counterCheat & 0x1) | ((cfg.counterCheat & 0x8) >> 2); op += option == RIGHT_DIR ? 1 : -1; if(op < 0) op = 0; if(op > 3) op = 3; cfg.counterCheat &= ~0x9; cfg.counterCheat |= (op & 0x1) | ((op & 0x2) << 2); } /** * Set the show items counter */ void M_ItemCounter(int option, void *data) { int op = ((cfg.counterCheat & 0x2) >> 1) | ((cfg.counterCheat & 0x10) >> 3); op += option == RIGHT_DIR ? 1 : -1; if(op < 0) op = 0; if(op > 3) op = 3; cfg.counterCheat &= ~0x12; cfg.counterCheat |= ((op & 0x1) << 1) | ((op & 0x2) << 3); } /** * Set the show secrets counter */ void M_SecretCounter(int option, void *data) { int op = ((cfg.counterCheat & 0x4) >> 2) | ((cfg.counterCheat & 0x20) >> 4); op += option == RIGHT_DIR ? 1 : -1; if(op < 0) op = 0; if(op > 3) op = 3; cfg.counterCheat &= ~0x24; cfg.counterCheat |= ((op & 0x1) << 2) | ((op & 0x2) << 4); } void M_Xhair(int option, void* context) { #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ cfg.xhair += option == RIGHT_DIR ? 1 : -1; if(cfg.xhair < 0) cfg.xhair = 0; if(cfg.xhair > NUM_XHAIRS) cfg.xhair = NUM_XHAIRS; #else if(option == RIGHT_DIR) { if(cfg.xhair < NUM_XHAIRS) cfg.xhair++; } else if(cfg.xhair > 0) cfg.xhair--; #endif } void M_XhairSize(int option, void* context) { M_FloatMod10(&cfg.xhairSize, option); } #if __JDOOM64__ void M_WeaponRecoil(int option, void* context) { cfg.weaponRecoil = !cfg.weaponRecoil; } #endif #if !__JDOOM64__ void M_SizeStatusBar(int option, void* context) { if(option == RIGHT_DIR) { if(cfg.statusbarScale < 20) cfg.statusbarScale++; } else if(cfg.statusbarScale > 1) cfg.statusbarScale--; ST_HUDUnHide(CONSOLEPLAYER, HUE_FORCE); R_SetViewSize(cfg.screenBlocks); } void M_StatusBarOpacity(int option, void* context) { M_FloatMod10(&cfg.statusbarOpacity, option); ST_HUDUnHide(CONSOLEPLAYER, HUE_FORCE); } #endif void M_WGCurrentColor(int option, void* context) { M_FloatMod10(context, option); } void M_NewGame(int option, void* context) { if(IS_NETGAME) { Hu_MsgStart(MSG_ANYKEY, NEWGAME, NULL, NULL); return; } #if __JHEXEN__ M_SetupNextMenu(&ClassDef); #elif __JHERETIC__ M_SetupNextMenu(&EpiDef); #elif __JDOOM64__ || __JSTRIFE__ M_SetupNextMenu(&SkillDef); #else // __JDOOM__ if(gameMode == commercial) M_SetupNextMenu(&SkillDef); else M_SetupNextMenu(&EpiDef); #endif } int M_QuitResponse(msgresponse_t response, void* context) { if(response == MSG_YES) { G_SetGameAction(GA_QUIT); } return true; } void M_QuitDOOM(int option, void* context) { const char* endString; #if __JDOOM__ || __JDOOM64__ endString = endmsg[((int) GAMETIC % (NUM_QUITMESSAGES + 1))]; #else endString = GET_TXT(TXT_QUITMSG); #endif Con_Open(false); Hu_MsgStart(MSG_YESNO, endString, M_QuitResponse, NULL); } int M_EndGameResponse(msgresponse_t response, void* context) { if(response == MSG_YES) { G_StartTitle(); return true; } return true; } void M_EndGame(int option, void* context) { if(!userGame) { Hu_MsgStart(MSG_ANYKEY, ENDNOGAME, NULL, NULL); return; } if(IS_NETGAME) { Hu_MsgStart(MSG_ANYKEY, NETEND, NULL, NULL); return; } Hu_MsgStart(MSG_YESNO, ENDGAME, M_EndGameResponse, NULL); } void M_ChangeMessages(int option, void* context) { cfg.msgShow = !cfg.msgShow; P_SetMessage(players + CONSOLEPLAYER, !cfg.msgShow ? MSGOFF : MSGON, true); } void M_HUDHideTime(int option, void* context) { int val = cfg.hudTimer; if(option == RIGHT_DIR) { if(val < 30) val++; } else if(val > 0) val--; cfg.hudTimer = val; } void M_MessageUptime(int option, void* context) { int val = cfg.msgUptime; if(option == RIGHT_DIR) { if(val < 30) val++; } else if(val > 1) val--; cfg.msgUptime = val; } #if __JHERETIC__ || __JHEXEN__ void M_InventoryHideTime(int option, void* context) { int val = cfg.inventoryTimer; if(option == RIGHT_DIR) { if(val < 30) val++; } else if(val > 0) val--; cfg.inventoryTimer = val; } void M_InventorySlotMaxVis(int option, void* context) { char* cvarname; int val = cfg.inventorySlotMaxVis; if(option == RIGHT_DIR) { if(val < 16) val++; } else if(val > 0) val--; if(!context) return; cvarname = (char*) context; Con_SetInteger(cvarname, val, false); } #endif void M_HUDScale(int option, void* context) { int val = (cfg.hudScale + .05f) * 10; if(option == RIGHT_DIR) { if(val < 10) val++; } else if(val > 3) val--; cfg.hudScale = val / 10.0f; ST_HUDUnHide(CONSOLEPLAYER, HUE_FORCE); } #if __JDOOM__ || __JDOOM64__ void M_HUDRed(int option, void* context) { M_FloatMod10(&cfg.hudColor[0], option); } void M_HUDGreen(int option, void* context) { M_FloatMod10(&cfg.hudColor[1], option); } void M_HUDBlue(int option, void* context) { M_FloatMod10(&cfg.hudColor[2], option); } #endif void M_LoadGame(int option, void* context) { if(IS_CLIENT && !Get(DD_PLAYBACK)) { Hu_MsgStart(MSG_ANYKEY, LOADNET, NULL, NULL); return; } updateSaveList(); M_SetupNextMenu(&LoadDef); } /** * Called via the menu or the control bindings mechanism when the player * wishes to save their game. */ void M_SaveGame(int option, void* context) { player_t* player = &players[CONSOLEPLAYER]; if(player->playerState == PST_DEAD || Get(DD_PLAYBACK)) { Hu_MsgStart(MSG_ANYKEY, SAVEDEAD, NULL, NULL); return; } if(G_GetGameState() != GS_MAP) { Hu_MsgStart(MSG_ANYKEY, SAVEOUTMAP, NULL, NULL); return; } if(IS_CLIENT) { #if __JDOOM__ || __JDOOM64__ Hu_MsgStart(MSG_ANYKEY, SAVENET, NULL, NULL); #endif return; } Hu_MenuCommand(MCMD_OPEN); updateSaveList(); M_SetupNextMenu(&SaveDef); } void M_ChooseClass(int option, void* context) { #if __JHEXEN__ if(IS_NETGAME) { P_SetMessage(&players[CONSOLEPLAYER], "YOU CAN'T START A NEW GAME FROM WITHIN A NETGAME!", false); return; } if(option < 0) { // Random class. // Number of user-selectable classes. MenuPClass = (menuTime / 5) % (ClassDef.itemCount - 1); } else { MenuPClass = option; } switch(MenuPClass) { case PCLASS_FIGHTER: SkillDef.x = 120; SkillItems[0].text = GET_TXT(TXT_SKILLF1); SkillItems[1].text = GET_TXT(TXT_SKILLF2); SkillItems[2].text = GET_TXT(TXT_SKILLF3); SkillItems[3].text = GET_TXT(TXT_SKILLF4); SkillItems[4].text = GET_TXT(TXT_SKILLF5); break; case PCLASS_CLERIC: SkillDef.x = 116; SkillItems[0].text = GET_TXT(TXT_SKILLC1); SkillItems[1].text = GET_TXT(TXT_SKILLC2); SkillItems[2].text = GET_TXT(TXT_SKILLC3); SkillItems[3].text = GET_TXT(TXT_SKILLC4); SkillItems[4].text = GET_TXT(TXT_SKILLC5); break; case PCLASS_MAGE: SkillDef.x = 112; SkillItems[0].text = GET_TXT(TXT_SKILLM1); SkillItems[1].text = GET_TXT(TXT_SKILLM2); SkillItems[2].text = GET_TXT(TXT_SKILLM3); SkillItems[3].text = GET_TXT(TXT_SKILLM4); SkillItems[4].text = GET_TXT(TXT_SKILLM5); break; } M_SetupNextMenu(&SkillDef); #endif } #if __JDOOM__ || __JHERETIC__ void M_Episode(int option, void* context) { #if __JHERETIC__ if(shareware && option) { Hu_MsgStart(MSG_ANYKEY, SWSTRING, NULL, NULL); M_SetupNextMenu(&ReadDef1); return; } #else if(gameMode == shareware && option) { Hu_MsgStart(MSG_ANYKEY, SWSTRING, NULL, NULL); M_SetupNextMenu(&ReadDef1); return; } #endif epi = option; M_SetupNextMenu(&SkillDef); } #endif #if __JDOOM__ || __JHERETIC__ int M_VerifyNightmare(msgresponse_t response, void* context) { if(response == MSG_YES) { Hu_MenuCommand(MCMD_CLOSEFAST); G_DeferedInitNew(SM_NIGHTMARE, epi, 0); } return true; } #endif void M_ChooseSkill(int option, void* context) { #if __JHEXEN__ Hu_MenuCommand(MCMD_CLOSEFAST); cfg.playerClass[CONSOLEPLAYER] = MenuPClass; G_DeferredNewGame(option); #else # if __JDOOM__ || __JSTRIFE__ if(option == SM_NIGHTMARE) { Hu_MsgStart(MSG_YESNO, NIGHTMARE, M_VerifyNightmare, NULL); return; } # endif Hu_MenuCommand(MCMD_CLOSEFAST); # if __JDOOM64__ G_DeferedInitNew(option, 0, 0); # else G_DeferedInitNew(option, epi, 0); # endif #endif } void M_SfxVol(int option, void* context) { int vol = SFXVOLUME; if(option == RIGHT_DIR) { if(vol < 15) vol++; } else { if(vol > 0) vol--; } Set(DD_SFX_VOLUME, vol * 17); } void M_MusicVol(int option, void* context) { int vol = MUSICVOLUME; if(option == RIGHT_DIR) { if(vol < 15) vol++; } else { if(vol > 0) vol--; } Set(DD_MUSIC_VOLUME, vol * 17); } void M_SizeDisplay(int option, void* context) { if(option == RIGHT_DIR) { #if __JDOOM64__ if(cfg.screenBlocks < 11) #else if(cfg.screenBlocks < 13) #endif { cfg.screenBlocks++; } } else if(cfg.screenBlocks > 3) { cfg.screenBlocks--; } R_SetViewSize(cfg.screenBlocks); } void M_OpenDCP(int option, void* context) { #define NUM_PANEL_NAMES 3 static const char *panelNames[] = { "panel", "panel audio", "panel input" }; int idx = option; if(idx < 0 || idx > NUM_PANEL_NAMES - 1) idx = 0; Hu_MenuCommand(MCMD_CLOSEFAST); DD_Execute(true, panelNames[idx]); #undef NUM_PANEL_NAMES } void MN_DrawColorBox(const menu_t* menu, int index, float r, float g, float b, float a) { #define COLORBOX_OFFSET_Y (-.5f) float x = menu->x, y = menu->y, w, h; if(!MN_IsItemVisible(menu, index)) return; y += menu->itemHeight * (index - menu->firstItem); h = menu->itemHeight; y += h / 2; x += h / 2; h /= 4; y -= h / 2; y += COLORBOX_OFFSET_Y; w = h; M_DrawBackgroundBox(x, y, w, h, 1, 1, 1, menuAlpha, true, 1); DGL_SetNoMaterial(); DGL_DrawRect(x, y, w, h, r, g, b, (a < 0? 1 : a) * menuAlpha); #undef COLORBOX_OFFSET_Y } /** * Draws a menu slider control */ void MN_DrawSlider(const menu_t* menu, int item, int width, int slot) { #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ int x; int y; if(!MN_IsItemVisible(menu, item)) return; x = menu->x + 24; y = menu->y + 2 + (menu->itemHeight * (item - menu->firstItem)); M_DrawSlider(x, y, width, slot, menuAlpha); #else int x = 0, y = 0; int height = menu->itemHeight - 1; float scale = height / 13.0f; if(!MN_IsItemVisible(menu, item)) return; if(menu->items[item].text) x = M_StringWidth(menu->items[item].text, menu->font); x += menu->x + 6; y = menu->y + menu->itemHeight * (item - menu->firstItem); M_DrawSlider(x, y, width, height, slot, menuAlpha); #endif } /** * Routes menu commands, actions and navigation. */ DEFCC(CCmdMenuAction) { int mode = 0; if(G_GetGameAction() == GA_QUIT) return false; if(!menuActive) { if(!stricmp(argv[0], "menu") && !chatOn) // Open menu. { Hu_MenuCommand(MCMD_OPEN); return true; } } else { // Determine what state the menu is in currently if(ActiveEdit) mode = 1; else if(widgetEdit) mode = 2; else if(saveStringEnter) mode = 3; #if !__JDOOM64__ else { if(currentMenu == &ReadDef1 || currentMenu == &ReadDef2 # if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ || currentMenu == &ReadDef3 # endif ) mode = 4; } #endif if(!stricmp(argv[0], "menuup")) { switch(mode) { case 2: // Widget edit if(!widgetEdit) break; // Fall through. case 0: // Menu nav Hu_MenuCommand(MCMD_NAV_UP); break; default: break; } return true; } else if(!stricmp(argv[0], "menudown")) { switch(mode) { case 2: // Widget edit if(!widgetEdit) break; // Fall through. case 0: // Menu nav Hu_MenuCommand(MCMD_NAV_DOWN); break; default: break; } return true; } else if(!stricmp(argv[0], "menupagedown")) { switch(mode) { case 0: // Menu nav case 2: // Widget edit Hu_MenuCommand(MCMD_NAV_PAGEDOWN); break; } return true; } else if(!stricmp(argv[0], "menupageup")) { switch(mode) { case 0: // Menu nav case 2: // Widget edit Hu_MenuCommand(MCMD_NAV_PAGEUP); break; } return true; } else if(!stricmp(argv[0], "menuleft")) { switch(mode) { case 0: // Menu nav case 2: // Widget edit Hu_MenuCommand(MCMD_NAV_LEFT); break; default: break; } return true; } else if(!stricmp(argv[0], "menuright")) { switch(mode) { case 0: // Menu nav case 2: // Widget edit Hu_MenuCommand(MCMD_NAV_RIGHT); break; default: break; } return true; } else if(!stricmp(argv[0], "menudelete")) { if(!mode) { Hu_MenuCommand(MCMD_DELETE); } return true; } else if(!stricmp(argv[0], "menuselect")) { switch(mode) { case 4: // In helpscreens case 0: // Menu nav Hu_MenuCommand(MCMD_SELECT); break; case 1: // Edit Field ActiveEdit->firstVisible = 0; ActiveEdit = NULL; S_LocalSound(SFX_MENU_ACCEPT, NULL); break; case 2: // Widget edit // Set the new color *widgetcolors[editcolorindex].r = currentcolor[0]; *widgetcolors[editcolorindex].g = currentcolor[1]; *widgetcolors[editcolorindex].b = currentcolor[2]; if(rgba) *widgetcolors[editcolorindex].a = currentcolor[3]; // Restore the position of the skull itemOn = previtemOn; widgetEdit = false; S_LocalSound(SFX_MENU_ACCEPT, NULL); break; case 3: // Save string edit: Save saveStringEnter = 0; if(savegamestrings[saveSlot][0]) { // Picked a quicksave slot yet? if(quickSaveSlot == -2) quickSaveSlot = saveSlot; S_LocalSound(SFX_MENU_ACCEPT, NULL); G_SaveGame(saveSlot, savegamestrings[saveSlot]); Hu_MenuCommand(MCMD_CLOSEFAST); } break; } return true; } else if(!stricmp(argv[0], "menuback")) { int c; switch(mode) { case 0: // Menu nav: Previous menu Hu_MenuCommand(MCMD_NAV_OUT); break; case 1: // Edit Field: Del char c = strlen(ActiveEdit->text); if(c > 0) ActiveEdit->text[c - 1] = 0; Ed_MakeCursorVisible(); break; case 2: // Widget edit: Close widget // Restore the position of the skull itemOn = previtemOn; widgetEdit = false; S_LocalSound(SFX_MENU_CANCEL, NULL); break; case 3: // Save string edit: Del char if(saveCharIndex > 0) { saveCharIndex--; savegamestrings[saveSlot][saveCharIndex] = 0; } break; } return true; } else if(!stricmp(argv[0], "menu")) { switch(mode) { case 0: // Menu nav: Close menu Hu_MenuCommand(MCMD_CLOSE); break; case 1: // Edit Field ActiveEdit->firstVisible = 0; strcpy(ActiveEdit->text, ActiveEdit->oldtext); ActiveEdit = NULL; break; case 2: // Widget edit: Close widget // Restore the position of the skull itemOn = previtemOn; widgetEdit = false; S_LocalSound(SFX_MENU_CLOSE, NULL); break; case 3: // Save string edit: Cancel saveStringEnter = 0; strcpy(&savegamestrings[saveSlot][0], saveOldString); break; case 4: // In helpscreens: Exit and close menu M_SetupNextMenu(&MainDef); Hu_MenuCommand(MCMD_CLOSEFAST); break; } return true; } } // Hotkey shortcuts. #if !__JDOOM64__ if(!stricmp(argv[0], "helpscreen")) { Hu_MenuCommand(MCMD_OPEN); menuTime = 0; # if __JDOOM__ if(gameMode == retail) currentMenu = &ReadDef2; else # endif currentMenu = &ReadDef1; } else #endif if(!stricmp(argv[0], "SaveGame")) { menuTime = 0; M_SaveGame(0, NULL); } else if(!stricmp(argv[0], "LoadGame")) { Hu_MenuCommand(MCMD_OPEN); menuTime = 0; M_LoadGame(0, NULL); } else if(!stricmp(argv[0], "SoundMenu")) { Hu_MenuCommand(MCMD_OPEN); menuTime = 0; currentMenu = &Options2Def; } else if(!stricmp(argv[0], "QuickSave")) { menuTime = 0; M_QuickSave(); } else if(!stricmp(argv[0], "EndGame")) { menuTime = 0; M_EndGame(0, NULL); } else if(!stricmp(argv[0], "ToggleMsgs")) { menuTime = 0; M_ChangeMessages(0, NULL); } else if(!stricmp(argv[0], "QuickLoad")) { menuTime = 0; M_QuickLoad(); } else if(!stricmp(argv[0], "quit")) { if(IS_DEDICATED) DD_Execute(true, "quit!"); else { S_LocalSound(SFX_MENU_CANCEL, NULL); menuTime = 0; M_QuitDOOM(0, NULL); } } else if(!stricmp(argv[0], "ToggleGamma")) { R_CycleGammaLevel(); } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/am_map.c0000644000175000017500000016453611357170242022242 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * am_map.c : Automap, automap menu and related code. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "p_mapsetup.h" #include "hu_stuff.h" #include "hu_menu.h" #include "am_map.h" #include "g_common.h" #include "r_common.h" #include "p_player.h" #include "g_controls.h" #include "p_tick.h" #include "p_automap.h" #include "rend_automap.h" // MACROS ------------------------------------------------------------------ #define R (1.0f) vgline_t keysquare[] = { {{0, 0}, {R / 4, -R / 2}}, {{R / 4, -R / 2}, {R / 2, -R / 2}}, {{R / 2, -R / 2}, {R / 2, R / 2}}, {{R / 2, R / 2}, {R / 4, R / 2}}, {{R / 4, R / 2}, {0, 0}}, // Handle part type thing. {{0, 0}, {-R, 0}}, // Stem. {{-R, 0}, {-R, -R / 2}}, // End lockpick part. {{-3 * R / 4, 0}, {-3 * R / 4, -R / 4}} }; vgline_t thintriangle_guy[] = { {{-R / 2, R - R / 2}, {R, 0}}, // > {{R, 0}, {-R / 2, -R + R / 2}}, {{-R / 2, -R + R / 2}, {-R / 2, R - R / 2}} // |> }; #if __JDOOM__ || __JDOOM64__ vgline_t player_arrow[] = { {{-R + R / 8, 0}, {R, 0}}, // ----- {{R, 0}, {R - R / 2, R / 4}}, // -----> {{R, 0}, {R - R / 2, -R / 4}}, {{-R + R / 8, 0}, {-R - R / 8, R / 4}}, // >----> {{-R + R / 8, 0}, {-R - R / 8, -R / 4}}, {{-R + 3 * R / 8, 0}, {-R + R / 8, R / 4}}, // >>---> {{-R + 3 * R / 8, 0}, {-R + R / 8, -R / 4}} }; vgline_t cheat_player_arrow[] = { {{-R + R / 8, 0}, {R, 0}}, // ----- {{R, 0}, {R - R / 2, R / 6}}, // -----> {{R, 0}, {R - R / 2, -R / 6}}, {{-R + R / 8, 0}, {-R - R / 8, R / 6}}, // >-----> {{-R + R / 8, 0}, {-R - R / 8, -R / 6}}, {{-R + 3 * R / 8, 0}, {-R + R / 8, R / 6}}, // >>-----> {{-R + 3 * R / 8, 0}, {-R + R / 8, -R / 6}}, {{-R / 2, 0}, {-R / 2, -R / 6}}, // >>-d---> {{-R / 2, -R / 6}, {-R / 2 + R / 6, -R / 6}}, {{-R / 2 + R / 6, -R / 6}, {-R / 2 + R / 6, R / 4}}, {{-R / 6, 0}, {-R / 6, -R / 6}}, // >>-dd--> {{-R / 6, -R / 6}, {0, -R / 6}}, {{0, -R / 6}, {0, R / 4}}, {{R / 6, R / 4}, {R / 6, -R / 7}}, // >>-ddt-> {{R / 6, -R / 7}, {R / 6 + R / 32, -R / 7 - R / 32}}, {{R / 6 + R / 32, -R / 7 - R / 32}, {R / 6 + R / 10, -R / 7}} }; #elif __JHERETIC__ vgline_t player_arrow[] = { {{-R + R / 4, 0}, {0, 0}}, // center line. {{-R + R / 4, R / 8}, {R, 0}}, // blade {{-R + R / 4, -R / 8}, {R, 0}}, {{-R + R / 4, -R / 4}, {-R + R / 4, R / 4}}, // crosspiece {{-R + R / 8, -R / 4}, {-R + R / 8, R / 4}}, {{-R + R / 8, -R / 4}, {-R + R / 4, -R / 4}}, //crosspiece connectors {{-R + R / 8, R / 4}, {-R + R / 4, R / 4}}, {{-R - R / 4, R / 8}, {-R - R / 4, -R / 8}}, //pommel {{-R - R / 4, R / 8}, {-R + R / 8, R / 8}}, {{-R - R / 4, -R / 8}, {-R + R / 8, -R / 8}} }; vgline_t cheat_player_arrow[] = { {{-R + R / 8, 0}, {R, 0}}, // ----- {{R, 0}, {R - R / 2, R / 6}}, // -----> {{R, 0}, {R - R / 2, -R / 6}}, {{-R + R / 8, 0}, {-R - R / 8, R / 6}}, // >-----> {{-R + R / 8, 0}, {-R - R / 8, -R / 6}}, {{-R + 3 * R / 8, 0}, {-R + R / 8, R / 6}}, // >>-----> {{-R + 3 * R / 8, 0}, {-R + R / 8, -R / 6}}, {{-R / 2, 0}, {-R / 2, -R / 6}}, // >>-d---> {{-R / 2, -R / 6}, {-R / 2 + R / 6, -R / 6}}, {{-R / 2 + R / 6, -R / 6}, {-R / 2 + R / 6, R / 4}}, {{-R / 6, 0}, {-R / 6, -R / 6}}, // >>-dd--> {{-R / 6, -R / 6}, {0, -R / 6}}, {{0, -R / 6}, {0, R / 4}}, {{R / 6, R / 4}, {R / 6, -R / 7}}, // >>-ddt-> {{R / 6, -R / 7}, {R / 6 + R / 32, -R / 7 - R / 32}}, {{R / 6 + R / 32, -R / 7 - R / 32}, {R / 6 + R / 10, -R / 7}} }; #elif __JHEXEN__ vgline_t player_arrow[] = { {{-R + R / 4, 0}, {0, 0}}, // center line. {{-R + R / 4, R / 8}, {R, 0}}, // blade {{-R + R / 4, -R / 8}, {R, 0}}, {{-R + R / 4, -R / 4}, {-R + R / 4, R / 4}}, // crosspiece {{-R + R / 8, -R / 4}, {-R + R / 8, R / 4}}, {{-R + R / 8, -R / 4}, {-R + R / 4, -R / 4}}, //crosspiece connectors {{-R + R / 8, R / 4}, {-R + R / 4, R / 4}}, {{-R - R / 4, R / 8}, {-R - R / 4, -R / 8}}, //pommel {{-R - R / 4, R / 8}, {-R + R / 8, R / 8}}, {{-R - R / 4, -R / 8}, {-R + R / 8, -R / 8}} }; #endif #undef R // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // Menu routines. void M_DrawMapMenu(void); void M_MapPosition(int option, void* data); void M_MapWidth(int option, void* data); void M_MapHeight(int option, void* data); void M_MapOpacity(int option, void* data); void M_MapLineAlpha(int option, void* data); void M_MapDoorColors(int option, void* data); void M_MapDoorGlow(int option, void* data); void M_MapRotate(int option, void* data); void M_MapStatusbar(int option, void* data); void M_MapCustomColors(int option, void* data); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void registerSpecialLine(automapcfg_t* cfg, int cheatLevel, int lineSpecial, int sided, float r, float g, float b, float a, blendmode_t blendmode, glowtype_t glowType, float glowAlpha, float glowWidth, boolean scaleGlowWithView); static void setColorAndAlpha(automapcfg_t* cfg, int objectname, float r, float g, float b, float a); static void findMinMaxBoundaries(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- cvar_t mapCVars[] = { {"map-opacity", 0, CVT_FLOAT, &cfg.automapOpacity, 0, 1}, {"map-alpha-lines", 0, CVT_FLOAT, &cfg.automapLineAlpha, 0, 1}, #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ {"map-babykeys", 0, CVT_BYTE, &cfg.automapBabyKeys, 0, 1}, #endif {"map-background-r", 0, CVT_FLOAT, &cfg.automapBack[0], 0, 1}, {"map-background-g", 0, CVT_FLOAT, &cfg.automapBack[1], 0, 1}, {"map-background-b", 0, CVT_FLOAT, &cfg.automapBack[2], 0, 1}, {"map-customcolors", 0, CVT_INT, &cfg.automapCustomColors, 0, 1}, {"map-mobj-r", 0, CVT_FLOAT, &cfg.automapMobj[0], 0, 1}, {"map-mobj-g", 0, CVT_FLOAT, &cfg.automapMobj[1], 0, 1}, {"map-mobj-b", 0, CVT_FLOAT, &cfg.automapMobj[2], 0, 1}, {"map-wall-r", 0, CVT_FLOAT, &cfg.automapL1[0], 0, 1}, {"map-wall-g", 0, CVT_FLOAT, &cfg.automapL1[1], 0, 1}, {"map-wall-b", 0, CVT_FLOAT, &cfg.automapL1[2], 0, 1}, {"map-wall-unseen-r", 0, CVT_FLOAT, &cfg.automapL0[0], 0, 1}, {"map-wall-unseen-g", 0, CVT_FLOAT, &cfg.automapL0[1], 0, 1}, {"map-wall-unseen-b", 0, CVT_FLOAT, &cfg.automapL0[2], 0, 1}, {"map-wall-floorchange-r", 0, CVT_FLOAT, &cfg.automapL2[0], 0, 1}, {"map-wall-floorchange-g", 0, CVT_FLOAT, &cfg.automapL2[1], 0, 1}, {"map-wall-floorchange-b", 0, CVT_FLOAT, &cfg.automapL2[2], 0, 1}, {"map-wall-ceilingchange-r", 0, CVT_FLOAT, &cfg.automapL3[0], 0, 1}, {"map-wall-ceilingchange-g", 0, CVT_FLOAT, &cfg.automapL3[1], 0, 1}, {"map-wall-ceilingchange-b", 0, CVT_FLOAT, &cfg.automapL3[2], 0, 1}, {"map-door-colors", 0, CVT_BYTE, &cfg.automapShowDoors, 0, 1}, {"map-door-glow", 0, CVT_FLOAT, &cfg.automapDoorGlow, 0, 200}, {"map-huddisplay", 0, CVT_INT, &cfg.automapHudDisplay, 0, 2}, {"map-pan-speed", 0, CVT_FLOAT, &cfg.automapPanSpeed, 0, 1}, {"map-pan-resetonopen", 0, CVT_BYTE, &cfg.automapPanResetOnOpen, 0, 1}, {"map-rotate", 0, CVT_BYTE, &cfg.automapRotate, 0, 1}, {"map-zoom-speed", 0, CVT_FLOAT, &cfg.automapZoomSpeed, 0, 1}, {"map-open-timer", CVF_NO_MAX, CVT_FLOAT, &cfg.automapOpenSeconds, 0, 0}, {"rend-dev-freeze-map", CVF_NO_ARCHIVE, CVT_BYTE, &freezeMapRLs, 0, 1}, {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static automap_t automaps[MAXPLAYERS]; static automapcfg_t automapCFGs[MAXPLAYERS]; static vectorgrap_t* vectorGraphs[NUM_VECTOR_GRAPHS]; // CODE -------------------------------------------------------------------- static __inline automap_t* getAutomap(automapid_t id) { if(id == 0 || id > MAXPLAYERS) { #if _DEBUG Con_Error("getAutomap: Invalid map id %i.", id); #endif return NULL; } return &automaps[id-1]; } static __inline automapcfg_t* getAutomapCFG(automapid_t id) { if(id == 0 || id > MAXPLAYERS) { #if _DEBUG Con_Error("getAutomapCFG: Invalid map id %i.", id); #endif return NULL; } return &automapCFGs[id-1]; } automapid_t AM_MapForPlayer(int plrnum) { if(plrnum < 0 || plrnum >= MAXPLAYERS) { #if _DEBUG Con_Error("AM_MapForPlayer: Invalid player num %i.", plrnum); #endif return 0; } return ((automapid_t) plrnum) + 1; // 1-based index. } void AM_GetMapColor(float* rgb, const float* uColor, int palidx, boolean customPal) { if((!customPal && !cfg.automapCustomColors) || (customPal && cfg.automapCustomColors != 2)) { R_GetColorPaletteRGBf(0, rgb, palidx, false); return; } rgb[0] = uColor[0]; rgb[1] = uColor[1]; rgb[2] = uColor[2]; } vectorgrap_t* AM_GetVectorGraph(vectorgrapname_t id) { vectorgrap_t* vg; vgline_t* lines; if(id > NUM_VECTOR_GRAPHS - 1) return NULL; if(vectorGraphs[id]) return vectorGraphs[id]; // Not loaded yet. { uint i, linecount; vg = vectorGraphs[id] = malloc(sizeof(*vg)); switch(id) { case VG_KEYSQUARE: lines = keysquare; linecount = sizeof(keysquare) / sizeof(vgline_t); break; case VG_TRIANGLE: lines = thintriangle_guy; linecount = sizeof(thintriangle_guy) / sizeof(vgline_t); break; case VG_ARROW: lines = player_arrow; linecount = sizeof(player_arrow) / sizeof(vgline_t); break; #if !__JHEXEN__ case VG_CHEATARROW: lines = cheat_player_arrow; linecount = sizeof(cheat_player_arrow) / sizeof(vgline_t); break; #endif default: Con_Error("AM_GetVectorGraph: Unknown id %i.", id); break; } vg->lines = malloc(linecount * sizeof(vgline_t)); vg->count = linecount; vg->dlist = 0; for(i = 0; i < linecount; ++i) memcpy(&vg->lines[i], &lines[i], sizeof(vgline_t)); } return vg; } const automapcfg_t* AM_GetMapConfig(automapid_t id) { return getAutomapCFG(id); } const mapobjectinfo_t* AM_GetMapObjectInfo(automapid_t id, int objectname) { automapcfg_t* cfg; if(objectname == AMO_NONE) return NULL; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("getMapObjectInfo: Unknown object %i.", objectname); if(!(cfg = getAutomapCFG(id))) return NULL; switch(objectname) { case AMO_UNSEENLINE: return &cfg->mapObjectInfo[MOL_LINEDEF_UNSEEN]; case AMO_SINGLESIDEDLINE: return &cfg->mapObjectInfo[MOL_LINEDEF]; case AMO_TWOSIDEDLINE: return &cfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED]; case AMO_FLOORCHANGELINE: return &cfg->mapObjectInfo[MOL_LINEDEF_FLOOR]; case AMO_CEILINGCHANGELINE: return &cfg->mapObjectInfo[MOL_LINEDEF_CEILING]; default: Con_Error("AM_GetMapObjectInfo: No info for object %i.", objectname); } return NULL; } const mapobjectinfo_t* AM_GetInfoForSpecialLine(automapid_t id, int special, const sector_t* frontsector, const sector_t* backsector) { mapobjectinfo_t* info = NULL; if(special > 0) { uint i; automapcfg_t* cfg; if(!(cfg = getAutomapCFG(id))) return NULL; for(i = 0; i < cfg->numSpecialLines && !info; ++i) { automapspecialline_t *sl = &cfg->specialLines[i]; // Is there a line special restriction? if(sl->special) { if(sl->special != special) continue; } // Is there a sided restriction? if(sl->sided) { if(sl->sided == 1 && backsector && frontsector) continue; else if(sl->sided == 2 && (!backsector || !frontsector)) continue; } // Is there a cheat level restriction? if(sl->cheatLevel > cfg->cheating) continue; // This is the one! info = &sl->info; } } return info; } /** * Register cvars and ccmds for the automap * Called during the PreInit of each game */ void AM_Register(void) { uint i; for(i = 0; mapCVars[i].name; ++i) Con_AddVariable(&mapCVars[i]); } static void initAutomapConfig(int player) { automapcfg_t* mcfg = &automapCFGs[player]; float rgb[3]; boolean customPal = !W_IsFromIWAD(W_GetNumForName("PLAYPAL")); // Initialize. // \fixme Put these values into an array (or read from a lump?). mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].glow = NO_GLOW; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].glowAlpha = 1; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].glowWidth = 10; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].blendMode = BM_NORMAL; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].scaleWithView = false; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].rgba[0] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].rgba[1] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].rgba[2] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_UNSEEN].rgba[3] = 1; mcfg->mapObjectInfo[MOL_LINEDEF].glow = NO_GLOW; mcfg->mapObjectInfo[MOL_LINEDEF].glowAlpha = 1; mcfg->mapObjectInfo[MOL_LINEDEF].glowWidth = 10; mcfg->mapObjectInfo[MOL_LINEDEF].blendMode = BM_NORMAL; mcfg->mapObjectInfo[MOL_LINEDEF].scaleWithView = false; mcfg->mapObjectInfo[MOL_LINEDEF].rgba[0] = 1; mcfg->mapObjectInfo[MOL_LINEDEF].rgba[1] = 1; mcfg->mapObjectInfo[MOL_LINEDEF].rgba[2] = 1; mcfg->mapObjectInfo[MOL_LINEDEF].rgba[3] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].glow = NO_GLOW; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].glowAlpha = 1; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].glowWidth = 10; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].blendMode = BM_NORMAL; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].scaleWithView = false; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].rgba[0] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].rgba[1] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].rgba[2] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED].rgba[3] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].glow = NO_GLOW; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].glowAlpha = 1; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].glowWidth = 10; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].blendMode = BM_NORMAL; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].scaleWithView = false; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].rgba[0] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].rgba[1] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].rgba[2] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_FLOOR].rgba[3] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].glow = NO_GLOW; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].glowAlpha = 1; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].glowWidth = 10; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].blendMode = BM_NORMAL; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].scaleWithView = false; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].rgba[0] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].rgba[1] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].rgba[2] = 1; mcfg->mapObjectInfo[MOL_LINEDEF_CEILING].rgba[3] = 1; // Register lines we want to display in a special way. #if __JDOOM__ || __JDOOM64__ // Blue locked door, open. registerSpecialLine(mcfg, 0, 32, 2, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Blue locked door, locked. registerSpecialLine(mcfg, 0, 26, 2, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 99, 0, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 133, 0, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Red locked door, open. registerSpecialLine(mcfg, 0, 33, 2, .682f, 0, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Red locked door, locked. registerSpecialLine(mcfg, 0, 28, 2, .682f, 0, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 134, 2, .682f, 0, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 135, 2, .682f, 0, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Yellow locked door, open. registerSpecialLine(mcfg, 0, 34, 2, .905f, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Yellow locked door, locked. registerSpecialLine(mcfg, 0, 27, 2, .905f, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 136, 2, .905f, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 137, 2, .905f, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Exit switch. registerSpecialLine(mcfg, 1, 11, 1, 0, 1, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Exit cross line. registerSpecialLine(mcfg, 1, 52, 2, 0, 1, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Secret Exit switch. registerSpecialLine(mcfg, 1, 51, 1, 0, 1, 1, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Secret Exit cross line. registerSpecialLine(mcfg, 2, 124, 2, 0, 1, 1, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); #elif __JHERETIC__ // Blue locked door. registerSpecialLine(mcfg, 0, 26, 2, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Blue switch? registerSpecialLine(mcfg, 0, 32, 0, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Yellow locked door. registerSpecialLine(mcfg, 0, 27, 2, .905f, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Yellow switch? registerSpecialLine(mcfg, 0, 34, 0, .905f, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Green locked door. registerSpecialLine(mcfg, 0, 28, 2, 0, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Green switch? registerSpecialLine(mcfg, 0, 33, 0, 0, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); #elif __JHEXEN__ // A locked door (all are green). registerSpecialLine(mcfg, 0, 13, 0, 0, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 83, 0, 0, .9f, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Intra-map teleporters (all are blue). registerSpecialLine(mcfg, 0, 70, 2, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); registerSpecialLine(mcfg, 0, 71, 2, 0, 0, .776f, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Inter-map teleport. registerSpecialLine(mcfg, 0, 74, 2, .682f, 0, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); // Game-winning exit. registerSpecialLine(mcfg, 0, 75, 2, .682f, 0, 0, 1, BM_NORMAL, TWOSIDED_GLOW, .75f, 5, true); #endif AM_SetVectorGraphic(mcfg, AMO_THING, VG_TRIANGLE); /*AM_GetMapColor(rgb, cfg.automapMobj, THINGCOLORS, customPal); setColorAndAlpha(mcfg, AMO_THING, rgb[0], rgb[1], rgb[2], 1);*/ AM_SetVectorGraphic(mcfg, AMO_THINGPLAYER, VG_ARROW); #if __JHERETIC__ || __JHEXEN__ if(W_CheckNumForName("AUTOPAGE") == -1) { setColorAndAlpha(mcfg, AMO_BACKGROUND, .55f, .45f, .35f, cfg.automapOpacity); } else { AM_GetMapColor(rgb, cfg.automapBack, WHITE, customPal); setColorAndAlpha(mcfg, AMO_BACKGROUND, rgb[0], rgb[1], rgb[2], cfg.automapOpacity); } #else AM_GetMapColor(rgb, cfg.automapBack, BACKGROUND, customPal); setColorAndAlpha(mcfg, AMO_BACKGROUND, rgb[0], rgb[1], rgb[2], cfg.automapOpacity); #endif AM_GetMapColor(rgb, cfg.automapL0, GRAYS+3, customPal); setColorAndAlpha(mcfg, AMO_UNSEENLINE, rgb[0], rgb[1], rgb[2], 1); AM_GetMapColor(rgb, cfg.automapL1, WALLCOLORS, customPal); setColorAndAlpha(mcfg, AMO_SINGLESIDEDLINE, rgb[0], rgb[1], rgb[2], 1); AM_GetMapColor(rgb, cfg.automapL0, TSWALLCOLORS, customPal); setColorAndAlpha(mcfg, AMO_TWOSIDEDLINE, rgb[0], rgb[1], rgb[2], 1); AM_GetMapColor(rgb, cfg.automapL2, FDWALLCOLORS, customPal); setColorAndAlpha(mcfg, AMO_FLOORCHANGELINE, rgb[0], rgb[1], rgb[2], 1); AM_GetMapColor(rgb, cfg.automapL3, CDWALLCOLORS, customPal); setColorAndAlpha(mcfg, AMO_CEILINGCHANGELINE, rgb[0], rgb[1], rgb[2], 1); // Setup map config based on player's config. // \todo All players' maps work from the same config! mcfg->followPlayer = player; mcfg->lineGlowScale = cfg.automapDoorGlow; mcfg->glowingLineSpecials = cfg.automapShowDoors; mcfg->panSpeed = cfg.automapPanSpeed; mcfg->panResetOnOpen = cfg.automapPanResetOnOpen; mcfg->zoomSpeed = cfg.automapZoomSpeed; mcfg->openSeconds = cfg.automapOpenSeconds; } /** * Called during init. */ void AM_Init(void) { uint i; float scrwidth, scrheight; memset(vectorGraphs, 0, sizeof(vectorGraphs)); scrwidth = Get(DD_WINDOW_WIDTH); scrheight = Get(DD_WINDOW_HEIGHT); Rend_AutomapInit(); Rend_AutomapLoadData(); memset(&automaps, 0, sizeof(automaps)); memset(&automapCFGs, 0, sizeof(automapCFGs)); for(i = 0; i < MAXPLAYERS; ++i) { automap_t* map = &automaps[i]; initAutomapConfig(i); // Initialize the map. map->oldViewScale = 1; map->window.oldX = map->window.x = 0; map->window.oldY = map->window.y = 0; map->window.oldWidth = map->window.width = scrwidth; map->window.oldHeight = map->window.height = scrheight; map->alpha = map->targetAlpha = map->oldAlpha = 0; Automap_SetViewScaleTarget(map, 1); Automap_SetViewRotate(map, cfg.automapRotate); Automap_SetMaxLocationTargetDelta(map, 128); // In world units. Automap_SetWindowTarget(map, 0, 0, scrwidth, scrheight); } } /** * Called during shutdown. */ void AM_Shutdown(void) { uint i; if(IS_DEDICATED) return; // nothing to do. Rend_AutomapUnloadData(); // Vector graphics. for(i = 0; i < NUM_VECTOR_GRAPHS; ++i) { vectorgrap_t *vg = vectorGraphs[i]; if(vg) { if(vg->dlist) DGL_DeleteLists(vg->dlist, 1); free(vg->lines); free(vg); } } } /** * Called during the finalization stage of map loading (after all geometry). */ void AM_InitForMap(void) { uint i; if(IS_DEDICATED) return; // nothing to do. // Find the world boundary points shared by all maps. findMinMaxBoundaries(); // Setup all players' maps. for(i = 0; i < MAXPLAYERS; ++i) { automap_t* map = &automaps[i]; automapcfg_t* mcfg = &automapCFGs[i]; mcfg->revealed = false; Automap_SetWindowFullScreenMode(map, true); // Determine the map view scale factors. Automap_SetViewScaleTarget(map, map->forceMaxScale? 0 : .45f); // zero clamped to minScaleMTOF Automap_ClearMarks(map); #if !__JHEXEN__ if(gameSkill == SM_BABY && cfg.automapBabyKeys) map->flags |= AMF_REND_KEYS; if(!IS_NETGAME && mcfg->cheating) AM_SetVectorGraphic(mcfg, AMO_THINGPLAYER, VG_CHEATARROW); #endif // If the map has been left open; close it. AM_Open(AM_MapForPlayer(i), false, true); // Reset position onto the follow player. if(players[mcfg->followPlayer].plr->mo) { mobj_t* mo = players[mcfg->followPlayer].plr->mo; Automap_SetLocationTarget(map, mo->pos[VX], mo->pos[VY]); } } Rend_AutomapInitForMap(); } /** * Start the automap. */ void AM_Open(automapid_t id, boolean yes, boolean fast) { automap_t* map; automapcfg_t* mcfg; if(G_GetGameState() != GS_MAP) return; if(!(mcfg = getAutomapCFG(id))) return; if(!players[mcfg->followPlayer].plr->inGame) return; map = getAutomap(id); if(yes) { if(Automap_IsActive(map)) return; // Already active. DD_Execute(true, "activatebcontext map"); if(map->panMode) DD_Execute(true, "activatebcontext map-freepan"); } else { if(!Automap_IsActive(map)) return; // Already in-active. DD_Execute(true, "deactivatebcontext map"); DD_Execute(true, "deactivatebcontext map-freepan"); } Automap_Open(map, yes, fast); if(yes) { if(!players[mcfg->followPlayer].plr->inGame) { // Set viewer target to the center of the map. float aabb[4]; Automap_GetInViewAABB(map, &aabb[BOXLEFT], &aabb[BOXRIGHT], &aabb[BOXBOTTOM], &aabb[BOXTOP]); Automap_SetLocationTarget(map, (aabb[BOXRIGHT] - aabb[BOXLEFT]) / 2, (aabb[BOXTOP] - aabb[BOXBOTTOM]) / 2); Automap_SetViewAngleTarget(map, 0); } else { // The map's target player is available. mobj_t* mo = players[mcfg->followPlayer].plr->mo; if(!(map->panMode && !mcfg->panResetOnOpen)) Automap_SetLocationTarget(map, mo->pos[0], mo->pos[1]); if(map->panMode && mcfg->panResetOnOpen) { float angle; /* $unifiedangles */ if(map->rotate) angle = (mo->angle - ANGLE_90) / (float) ANGLE_MAX * 360; else angle = 0; Automap_SetViewAngleTarget(map, angle); } } } } /** * Translates from map to automap window coordinates. */ float AM_MapToFrame(automapid_t id, float val) { automap_t* map; if(IS_DEDICATED) Con_Error("AM_MapToFrame: Not available in dedicated mode."); if(!(map = getAutomap(id))) return 0; return Automap_MapToFrame(map, val); } /** * Translates from automap window to map coordinates. */ float AM_FrameToMap(automapid_t id, float val) { automap_t* map; if(IS_DEDICATED) Con_Error("AM_MapToFrame: Not available in dedicated mode."); if(!(map = getAutomap(id))) return 0; return Automap_FrameToMap(map, val); } void AM_SetWindowTarget(automapid_t id, int x, int y, int w, int h) { automap_t* map; if(IS_DEDICATED) return; // Just ignore. if(!(map = getAutomap(id))) return; Automap_SetWindowTarget(map, x, y, w, h); } void AM_GetWindow(automapid_t id, float* x, float* y, float* w, float* h) { automap_t* map; if(IS_DEDICATED) Con_Error("AM_GetWindow: Not available in dedicated mode."); if(!(map = getAutomap(id))) return; Automap_GetWindow(map, x, y, w, h); } void AM_SetWindowFullScreenMode(automapid_t id, int value) { automap_t* map; if(IS_DEDICATED) return; // Just ignore. if(!(map = getAutomap(id))) return; Automap_SetWindowFullScreenMode(map, value); } boolean AM_IsMapWindowInFullScreenMode(automapid_t id) { automap_t* map; if(IS_DEDICATED) Con_Error("AM_IsMapWindowInFullScreenMode: Not available in " "dedicated mode."); if(!(map = getAutomap(id))) return false; return map->fullScreenMode; } void AM_SetViewTarget(automapid_t id, float x, float y) { automap_t* map; if(IS_DEDICATED) return; // Just ignore. if(!(map = getAutomap(id))) return; Automap_SetLocationTarget(map, x, y); } void AM_GetViewPosition(automapid_t id, float* x, float* y) { automap_t* map; if(!(map = getAutomap(id))) return; Automap_GetLocation(map, x, y); } void AM_GetViewParallaxPosition(automapid_t id, float* x, float* y) { automap_t* map; if(!(map = getAutomap(id))) return; Automap_GetViewParallaxPosition(map, x, y); } float AM_ViewAngle(automapid_t id) { automap_t* map; if(!(map = getAutomap(id))) return 0; return Automap_GetViewAngle(map); } void AM_SetViewScaleTarget(automapid_t id, float scale) { automap_t* map; if(!(map = getAutomap(id))) return; Automap_SetViewScaleTarget(map, scale); } void AM_SetViewAngleTarget(automapid_t id, float angle) { automap_t* map; if(!(map = getAutomap(id))) return; Automap_SetViewAngleTarget(map, angle); } float AM_MapToFrameMultiplier(automapid_t id) { automap_t* map; if(!(map = getAutomap(id))) return 1; return Automap_MapToFrameMultiplier(map); } boolean AM_IsActive(automapid_t id) { automap_t* map; if(IS_DEDICATED) return false; // Never. if(!(map = getAutomap(id))) return false; return Automap_IsActive(map); } void AM_SetViewRotate(automapid_t id, int offOnToggle) { automap_t* map; automapcfg_t* mcfg; if(IS_DEDICATED) return; // Ignore. if(!(map = getAutomap(id))) return; mcfg = getAutomapCFG(id); if(offOnToggle == 2) cfg.automapRotate = !cfg.automapRotate; else cfg.automapRotate = (offOnToggle? true : false); Automap_SetViewRotate(map, cfg.automapRotate); P_SetMessage(&players[mcfg->followPlayer], (map->rotate ? AMSTR_ROTATEON : AMSTR_ROTATEOFF), false); } /** * Update the specified player's automap. * * @param id Id of the map being updated. * @param lineIdx Idx of the line being added to the map. * @param visible @c true= mark the line as visible, else hidden. */ void AM_UpdateLinedef(automapid_t id, uint lineIdx, boolean visible) { automapcfg_t* mcfg; xline_t* xline; if(!(mcfg = getAutomapCFG(id))) return; if(lineIdx >= numlines) return; xline = P_GetXLine(lineIdx); // Will we need to rebuild one or more display lists? if(xline->mapped[mcfg->followPlayer] != visible) Rend_AutomapRebuild(id - 1); xline->mapped[mcfg->followPlayer] = visible; } void AM_RevealMap(automapid_t id, boolean on) { automapcfg_t* cfg; if(!(cfg = getAutomapCFG(id))) return; if(cfg->revealed != on) { cfg->revealed = on; Rend_AutomapRebuild(id - 1); } } boolean AM_IsRevealed(automapid_t id) { automapcfg_t* cfg; if(!(cfg = getAutomapCFG(id))) return false; return cfg->revealed; } /** * Clears markpoint array. */ void AM_ClearMarks(automapid_t id) { automap_t* map; automapcfg_t* mcfg; if(IS_DEDICATED) return; // Just ignore. if(!(map = getAutomap(id))) return; mcfg = getAutomapCFG(id); Automap_ClearMarks(map); P_SetMessage(&players[mcfg->followPlayer], AMSTR_MARKSCLEARED, false); Con_Printf("All markers cleared on automap.\n"); } /** * Adds a marker at the specified X/Y location. */ int AM_AddMark(automapid_t id, float x, float y, float z) { static char buffer[20]; automap_t* map; int newMark; if(!(map = getAutomap(id))) return -1; newMark = Automap_AddMark(map, x, y, z); if(newMark != -1) { automapcfg_t* mcfg = getAutomapCFG(id); sprintf(buffer, "%s %d", AMSTR_MARKEDSPOT, newMark); P_SetMessage(&players[mcfg->followPlayer], buffer, false); } return newMark; } boolean AM_GetMark(automapid_t id, uint mark, float* x, float* y, float* z) { automap_t* map; if(!(map = getAutomap(id))) return false; return Automap_GetMark(map, mark, x, y, z); } void AM_ToggleZoomMax(automapid_t id) { automap_t* map; if(IS_DEDICATED) return; // Ignore. if(!(map = getAutomap(id))) return; Automap_ToggleZoomMax(map); Con_Printf("Maximum zoom %s in automap.\n", map->forceMaxScale? "ON":"OFF"); } void AM_ToggleFollow(automapid_t id) { automap_t* map; automapcfg_t* mcfg; if(IS_DEDICATED) return; // Ignore. if(!(map = getAutomap(id))) return; mcfg = getAutomapCFG(id); Automap_ToggleFollow(map); // Enable/disable the pan mode binding class DD_Executef(true, "%sactivatebcontext map-freepan", !map->panMode? "de" : ""); P_SetMessage(&players[mcfg->followPlayer], (map->panMode ? AMSTR_FOLLOWOFF : AMSTR_FOLLOWON), false); } /** * @return Current alpha level of the automap. */ float AM_GlobalAlpha(automapid_t id) { automap_t* map; if(IS_DEDICATED) Con_Error("AM_GlobalAlpha: Not available in dedicated mode."); if(!(map = getAutomap(id))) return 0; return Automap_GetOpacity(map); } int AM_GetFlags(automapid_t id) { automap_t* map; if(!(map = getAutomap(id))) return 0; return Automap_GetFlags(map); } static void setColor(automapcfg_t* cfg, int objectname, float r, float g, float b) { mapobjectinfo_t* info; if(objectname == AMO_NONE) return; // Ignore. if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_SetColor: Unknown object %i.", objectname); r = MINMAX_OF(0, r, 1); g = MINMAX_OF(0, g, 1); b = MINMAX_OF(0, b, 1); // Check special cases first, if(objectname == AMO_BACKGROUND) { cfg->backgroundRGBA[0] = r; cfg->backgroundRGBA[1] = g; cfg->backgroundRGBA[2] = b; return; } // It must be an object with a name. switch(objectname) { case AMO_UNSEENLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_UNSEEN]; break; case AMO_SINGLESIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF]; break; case AMO_TWOSIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED]; break; case AMO_FLOORCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_FLOOR]; break; case AMO_CEILINGCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_CEILING]; break; default: Con_Error("AM_SetColor: Object %i does not use color.", objectname); break; } info->rgba[0] = r; info->rgba[1] = g; info->rgba[2] = b; // We will need to rebuild one or more display lists. Rend_AutomapRebuild(cfg - automapCFGs); } void AM_SetColor(automapid_t id, int objectname, float r, float g, float b) { automapcfg_t* cfg; if(IS_DEDICATED) return; // Ignore. if(!(cfg = getAutomapCFG(id))) return; setColor(cfg, objectname, r, g, b); } void AM_GetColor(automapid_t id, int objectname, float* r, float* g, float* b) { automapcfg_t* cfg; mapobjectinfo_t* info = NULL; if(IS_DEDICATED) Con_Error("AM_GetColor: Not available in dedicated mode."); if(!(cfg = getAutomapCFG(id))) return; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_SetColor: Unknown object %i.", objectname); // Check special cases first. if(objectname == AMO_BACKGROUND) { if(r) *r = cfg->backgroundRGBA[0]; if(g) *g = cfg->backgroundRGBA[1]; if(b) *b = cfg->backgroundRGBA[2]; return; } // It must be an object with an info. switch(objectname) { case AMO_UNSEENLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_UNSEEN]; break; case AMO_SINGLESIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF]; break; case AMO_TWOSIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED]; break; case AMO_FLOORCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_FLOOR]; break; case AMO_CEILINGCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_CEILING]; break; default: Con_Error("AM_GetColor: Object %i does not use color.", objectname); break; } if(r) *r = info->rgba[0]; if(g) *g = info->rgba[1]; if(b) *b = info->rgba[2]; } static void setColorAndAlpha(automapcfg_t* cfg, int objectname, float r, float g, float b, float a) { mapobjectinfo_t* info = NULL; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_SetColorAndAlpha: Unknown object %i.", objectname); r = MINMAX_OF(0, r, 1); g = MINMAX_OF(0, g, 1); b = MINMAX_OF(0, b, 1); a = MINMAX_OF(0, a, 1); // Check special cases first. if(objectname == AMO_BACKGROUND) { cfg->backgroundRGBA[0] = r; cfg->backgroundRGBA[1] = g; cfg->backgroundRGBA[2] = b; cfg->backgroundRGBA[3] = a; return; } // It must be an object with an info. switch(objectname) { case AMO_UNSEENLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_UNSEEN]; break; case AMO_SINGLESIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF]; break; case AMO_TWOSIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED]; break; case AMO_FLOORCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_FLOOR]; break; case AMO_CEILINGCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_CEILING]; break; default: Con_Error("AM_SetColorAndAlpha: Object %i does not use color/alpha.", objectname); break; } info->rgba[0] = r; info->rgba[1] = g; info->rgba[2] = b; info->rgba[3] = a; // We will need to rebuild one or more display lists. Rend_AutomapRebuild(cfg - automapCFGs); } void AM_SetColorAndAlpha(automapid_t id, int objectname, float r, float g, float b, float a) { automapcfg_t* cfg; if(IS_DEDICATED) return; // Just ignore. if(!(cfg = getAutomapCFG(id))) return; setColorAndAlpha(cfg, objectname, r, g, b, a); } void AM_GetColorAndAlpha(automapid_t id, int objectname, float* r, float* g, float* b, float* a) { automapcfg_t* cfg; mapobjectinfo_t* info = NULL; if(IS_DEDICATED) Con_Error("AM_GetColorAndAlpha: Not available in dedicated mode."); if(!(cfg = getAutomapCFG(id))) return; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_GetColorAndAlpha: Unknown object %i.", objectname); // Check special cases first. if(objectname == AMO_BACKGROUND) { if(r) *r = cfg->backgroundRGBA[0]; if(g) *g = cfg->backgroundRGBA[1]; if(b) *b = cfg->backgroundRGBA[2]; if(a) *a = cfg->backgroundRGBA[3]; return; } // It must be an object with an info. switch(objectname) { case AMO_UNSEENLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_UNSEEN]; break; case AMO_SINGLESIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF]; break; case AMO_TWOSIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED]; break; case AMO_FLOORCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_FLOOR]; break; case AMO_CEILINGCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_CEILING]; break; default: Con_Error("AM_GetColorAndAlpha: Object %i does not use color/alpha.", objectname); break; } if(r) *r = info->rgba[0]; if(g) *g = info->rgba[1]; if(b) *b = info->rgba[2]; if(a) *a = info->rgba[3]; } void AM_SetBlendmode(automapid_t id, int objectname, blendmode_t blendmode) { automapcfg_t* cfg; mapobjectinfo_t* info = NULL; if(IS_DEDICATED) return; // Just ignore. if(!(cfg = getAutomapCFG(id))) return; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_SetBlendmode: Unknown object %i.", objectname); // It must be an object with an info. switch(objectname) { case AMO_UNSEENLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_UNSEEN]; break; case AMO_SINGLESIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF]; break; case AMO_TWOSIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED]; break; case AMO_FLOORCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_FLOOR]; break; case AMO_CEILINGCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_CEILING]; break; default: Con_Error("AM_SetBlendmode: Object %i does not support blending modes.", objectname); break; } info->blendMode = blendmode; // We will need to rebuild one or more display lists. Rend_AutomapRebuild(id - 1); } void AM_SetGlow(automapid_t id, int objectname, glowtype_t type, float size, float alpha, boolean canScale) { automapcfg_t* cfg; mapobjectinfo_t* info = NULL; if(IS_DEDICATED) return; // Just ignore. if(!(cfg = getAutomapCFG(id))) return; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_SetGlow: Unknown object %i.", objectname); size = MINMAX_OF(0, size, 100); alpha = MINMAX_OF(0, alpha, 1); switch(objectname) { case AMO_UNSEENLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_UNSEEN]; break; case AMO_SINGLESIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF]; break; case AMO_TWOSIDEDLINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_TWOSIDED]; break; case AMO_FLOORCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_FLOOR]; break; case AMO_CEILINGCHANGELINE: info = &cfg->mapObjectInfo[MOL_LINEDEF_CEILING]; break; default: Con_Error("AM_SetGlow: Object %i does not support glow.", objectname); break; } info->glow = type; info->glowAlpha = alpha; info->glowWidth = size; info->scaleWithView = canScale; // We will need to rebuild one or more display lists. Rend_AutomapRebuild(id - 1); } void AM_SetVectorGraphic(automapcfg_t* cfg, int objectname, int vgname) { if(!cfg) return; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_SetVectorGraphic: Unknown object %i.", objectname); switch(objectname) { case AMO_THING: cfg->vectorGraphicForThing = vgname; break; case AMO_THINGPLAYER: cfg->vectorGraphicForPlayer = vgname; break; default: Con_Error("AM_SetVectorGraphic: Object %i does not support vector " "graphic.", objectname); break; } } vectorgrapname_t AM_GetVectorGraphic(const automapcfg_t* cfg, int objectname) { if(!cfg) return VG_NONE; if(objectname < 0 || objectname >= AMO_NUMOBJECTS) Con_Error("AM_GetVectorGraphic: Unknown object %i.", objectname); switch(objectname) { case AMO_THING: return cfg->vectorGraphicForThing; case AMO_THINGPLAYER: return cfg->vectorGraphicForPlayer; default: Con_Error("AM_GetVectorGraphic: Object %i does not support vector " "graphic.", objectname); break; } return VG_NONE; } static void registerSpecialLine(automapcfg_t* cfg, int cheatLevel, int lineSpecial, int sided, float r, float g, float b, float a, blendmode_t blendmode, glowtype_t glowType, float glowAlpha, float glowWidth, boolean scaleGlowWithView) { uint i; automapspecialline_t* line, *p; // Later re-registrations override earlier ones. i = 0; line = NULL; while(i < cfg->numSpecialLines && !line) { p = &cfg->specialLines[i]; if(p->special == lineSpecial && p->cheatLevel == cheatLevel) line = p; else i++; } if(!line) // It must be a new one. { // Any room for a new special line? if(cfg->numSpecialLines >= AM_MAXSPECIALLINES) Con_Error("AM_RegisterSpecialLine: No available slot."); line = &cfg->specialLines[cfg->numSpecialLines++]; } line->cheatLevel = cheatLevel; line->special = lineSpecial; line->sided = sided; line->info.rgba[0] = MINMAX_OF(0, r, 1); line->info.rgba[1] = MINMAX_OF(0, g, 1); line->info.rgba[2] = MINMAX_OF(0, b, 1); line->info.rgba[3] = MINMAX_OF(0, a, 1); line->info.glow = glowType; line->info.glowAlpha = MINMAX_OF(0, glowAlpha, 1); line->info.glowWidth = glowWidth; line->info.scaleWithView = scaleGlowWithView; line->info.blendMode = blendmode; // We will need to rebuild one or more display lists. Rend_AutomapRebuild(cfg - automapCFGs); } void AM_RegisterSpecialLine(automapid_t id, int cheatLevel, int lineSpecial, int sided, float r, float g, float b, float a, blendmode_t blendmode, glowtype_t glowType, float glowAlpha, float glowWidth, boolean scaleGlowWithView) { automapcfg_t* cfg; if(!(cfg = getAutomapCFG(id))) return; if(cheatLevel < 0 || cheatLevel > 4) Con_Error("AM_RegisterSpecialLine: cheatLevel '%i' out of range {0-4}.", cheatLevel); if(lineSpecial < 0) Con_Error("AM_RegisterSpecialLine: lineSpecial '%i' is negative.", lineSpecial); if(sided < 0 || sided > 2) Con_Error("AM_RegisterSpecialLine: sided '%i' is invalid.", sided); registerSpecialLine(cfg, cheatLevel, lineSpecial, sided, r, g, b, a, blendmode, glowType, glowAlpha, glowWidth, scaleGlowWithView); } void AM_SetCheatLevel(automapid_t id, int level) { int flags; automap_t* map; automapcfg_t* mcfg; if(!(map = getAutomap(id))) return; mcfg = getAutomapCFG(id); mcfg->cheating = level; flags = Automap_GetFlags(map); if(mcfg->cheating >= 1) flags |= AMF_REND_ALLLINES; else flags &= ~AMF_REND_ALLLINES; if(mcfg->cheating == 2) flags |= (AMF_REND_THINGS | AMF_REND_XGLINES); else flags &= ~(AMF_REND_THINGS | AMF_REND_XGLINES); if(mcfg->cheating >= 2) flags |= (AMF_REND_VERTEXES | AMF_REND_LINE_NORMALS); else flags &= ~(AMF_REND_VERTEXES | AMF_REND_LINE_NORMALS); Automap_SetFlags(map, flags); // We will need to rebuild one or more display lists. Rend_AutomapRebuild(id - 1); } void AM_IncMapCheatLevel(automapid_t id) { int flags; automap_t* map; automapcfg_t* mcfg; if(!(map = getAutomap(id))) return; mcfg = getAutomapCFG(id); mcfg->cheating = (mcfg->cheating + 1) % 3; flags = Automap_GetFlags(map); if(mcfg->cheating) flags |= AMF_REND_ALLLINES; else flags &= ~AMF_REND_ALLLINES; if(mcfg->cheating == 2) flags |= (AMF_REND_THINGS | AMF_REND_XGLINES); else flags &= ~(AMF_REND_THINGS | AMF_REND_XGLINES); Automap_SetFlags(map, flags); // We will need to rebuild one or more display lists. Rend_AutomapRebuild(id - 1); } /** * Determines bounding box of all the map's vertexes. */ static void findMinMaxBoundaries(void) { uint i; float pos[2], lowX, hiX, lowY, hiY; lowX = lowY = DDMAXFLOAT; hiX = hiY = -DDMAXFLOAT; for(i = 0; i < numvertexes; ++i) { P_GetFloatv(DMU_VERTEX, i, DMU_XY, pos); if(pos[VX] < lowX) lowX = pos[VX]; else if(pos[VX] > hiX) hiX = pos[VX]; if(pos[VY] < lowY) lowY = pos[VY]; else if(pos[VY] > hiY) hiY = pos[VY]; } for(i = 0; i < MAXPLAYERS; ++i) { automap_t* map = &automaps[i]; Automap_SetMinScale(map, 2 * PLAYERRADIUS); Automap_SetWorldBounds(map, lowX, hiX, lowY, hiY); } } /** * Called each tic for each player's automap if they are in-game. */ static void mapTicker(automap_t* map) { int playerNum; float panX[2], panY[2], zoomVel, zoomSpeed; player_t* mapPlayer; mobj_t* mo; automapcfg_t* mcfg; float scrwidth = DD_GetInteger(DD_WINDOW_WIDTH); float scrheight = DD_GetInteger(DD_WINDOW_HEIGHT); float newX, newY, newWidth, newHeight; if(!map) return; playerNum = map - automaps; mapPlayer = &players[playerNum]; mcfg = &automapCFGs[playerNum]; mo = players[mcfg->followPlayer].plr->mo; // Check the state of the controls. Done here so that offsets don't accumulate // unnecessarily, as they would, if left unread. P_GetControlState(playerNum, CTL_MAP_PAN_X, &panX[0], &panX[1]); P_GetControlState(playerNum, CTL_MAP_PAN_Y, &panY[0], &panY[1]); if(!(/*(mapPlayer->plr->flags & DDPF_LOCAL) &&*/ mapPlayer->plr->inGame)) return; // Move towards the target alpha level for the automap. if(++map->alphaTimer < mcfg->openSeconds * TICSPERSEC) map->alpha = LERP(map->oldAlpha, map->targetAlpha, map->alphaTimer / (mcfg->openSeconds * TICSPERSEC)); else map->alpha = map->targetAlpha; // If the automap is not active do nothing else. if(!map->active) return; // // Update per tic, driven controls. // // Map view zoom contol. zoomSpeed = (1 + mcfg->zoomSpeed); if(players[playerNum].brain.speed) zoomSpeed *= 1.5f; P_GetControlState(playerNum, CTL_MAP_ZOOM, &zoomVel, NULL); // ignores rel offset -jk if(zoomVel > 0) // zoom in { Automap_SetViewScaleTarget(map, map->viewScale * zoomSpeed); } else if(zoomVel < 0) // zoom out { Automap_SetViewScaleTarget(map, map->viewScale / zoomSpeed); } // Map viewer location paning control. if(map->panMode || !players[mcfg->followPlayer].plr->inGame) { float xy[2] = { 0, 0 }; // deltas // DOOM.EXE pans the automap at 140 fixed pixels per second. float panUnitsPerTic = (Automap_FrameToMap(map, FIXXTOSCREENX(140)) / TICSPERSEC) * (2 * mcfg->panSpeed); if(panUnitsPerTic < 8) panUnitsPerTic = 8; xy[VX] = panX[0] * panUnitsPerTic + panX[1]; xy[VY] = panY[0] * panUnitsPerTic + panY[1]; V2_Rotate(xy, map->angle / 360 * 2 * PI); if(xy[VX] || xy[VY]) Automap_SetLocationTarget(map, map->viewX + xy[VX], map->viewY + xy[VY]); } else // Camera follows the player { float angle; Automap_SetLocationTarget(map, mo->pos[VX], mo->pos[VY]); /* $unifiedangles */ if(map->rotate) angle = (mo->angle - ANGLE_90) / (float) ANGLE_MAX * 360; else angle = 0; Automap_SetViewAngleTarget(map, angle); } // Determine whether the available space has changed and thus whether // the position and/or size of the automap must therefore change too. R_GetViewWindow(&newX, &newY, &newWidth, &newHeight); Automap_UpdateWindow(map, FIXXTOSCREENX(newX), FIXYTOSCREENY(newY), FIXXTOSCREENX(newWidth), FIXYTOSCREENY(newHeight)); Automap_RunTic(map); } /** * Updates on Game Tick. */ void AM_Ticker(void) { uint i; if(IS_DEDICATED) return; // Nothing to do. // All maps get to tick if their player is in-game. for(i = 0; i < MAXPLAYERS; ++i) { mapTicker(&automaps[i]); } } void AM_Drawer(int player) { if(IS_DEDICATED) return; // Nothing to do. if(player < 0 || player > MAXPLAYERS) return; Rend_Automap(player, getAutomap(AM_MapForPlayer(player))); } // ------------------------------------------------------------------------------ // Automap Menu //------------------------------------------------------------------------------- menuitem_t MAPItems[] = { {ITT_LRFUNC, 0, "opacity :", M_MapOpacity, 0}, #if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0 }, {ITT_EMPTY, 0, NULL, NULL, 0 }, #endif {ITT_LRFUNC, 0, "line alpha :", M_MapLineAlpha, 0 }, #if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0 }, {ITT_EMPTY, 0, NULL, NULL, 0 }, #endif {ITT_LRFUNC, 0, "hud display :", M_MapStatusbar, 0 }, {ITT_EFUNC, 0, "door colors :", M_MapDoorColors, 0 }, {ITT_LRFUNC, 0, "door glow : ", M_MapDoorGlow, 0 }, #if __JHERETIC__ || __JHEXEN__ {ITT_EMPTY, 0, NULL, NULL, 0 }, {ITT_EMPTY, 0, NULL, NULL, 0 }, #endif #if __JDOOM__ || __JDOOM64__ {ITT_EMPTY, 0, NULL, NULL, 0 }, #endif {ITT_LRFUNC, 0, "use custom colors :", M_MapCustomColors, 0 }, {ITT_EFUNC, 0, " wall", SCColorWidget, 1 }, {ITT_EFUNC, 0, " floor height change", SCColorWidget, 2 }, {ITT_EFUNC, 0, " ceiling height change", SCColorWidget, 3 }, {ITT_EFUNC, 0, " unseen", SCColorWidget, 0 }, {ITT_EFUNC, 0, " thing", SCColorWidget, 6 }, {ITT_EFUNC, 0, " background", SCColorWidget, 4 }, }; menu_t MapDef = { 0, #if __JDOOM__ || __JDOOM64__ 70, 40, #else 64, 28, #endif M_DrawMapMenu, #if __JHERETIC__ || __JHEXEN__ 18, MAPItems, #else 13, MAPItems, #endif 0, MENU_OPTIONS, GF_FONTA, cfg.menuColor2, NULL, false, LINEHEIGHT_A, #if __JHERETIC__ || __JHEXEN__ 0, 11 #else 0, 13 #endif }; /** * Draws the automap options menu */ void M_DrawMapMenu(void) { static char* hudviewnames[3] = { "NONE", "CURRENT", "STATUSBAR" }; static char* yesno[2] = { "NO", "YES" }; static char* customColors[3] = { "NEVER", "AUTO", "ALWAYS" }; float menuAlpha; uint idx; #if __JHERETIC__ || __JHEXEN__ char* token; #endif const menu_t* menu = &MapDef; menuAlpha = Hu_MenuAlpha(); M_DrawTitle("Automap OPTIONS", menu->y - 26); #if __JHERETIC__ || __JHEXEN__ DGL_Color4f(1, 1, 1, Hu_MenuAlpha()); // Draw the page arrows. token = (!menu->firstItem || menuTime & 8) ? "invgeml2" : "invgeml1"; GL_DrawPatch_CS(menu->x, menu->y - 22, W_GetNumForName(token)); token = (menu->firstItem + menu->numVisItems >= menu->itemCount || menuTime & 8) ? "invgemr2" : "invgemr1"; GL_DrawPatch_CS(312 - menu->x, menu->y - 22, W_GetNumForName(token)); #endif idx = 0; #if __JHERETIC__ || __JHEXEN__ idx++; #endif MN_DrawSlider(menu, idx++, 11, cfg.automapOpacity * 10 + .5f); #if __JHERETIC__ || __JHEXEN__ idx+= 2; #endif MN_DrawSlider(menu, idx++, 11, cfg.automapLineAlpha * 10 + .5f); #if __JHERETIC__ || __JHEXEN__ idx++; #endif M_WriteMenuText(menu, idx++, hudviewnames[cfg.automapHudDisplay % 3]); M_WriteMenuText(menu, idx++, yesno[cfg.automapShowDoors]); #if __JHERETIC__ || __JHEXEN__ idx++; #endif MN_DrawSlider(menu, idx++, 21, (cfg.automapDoorGlow - 1) / 10 + .5f ); idx++; M_WriteMenuText(menu, idx++, customColors[cfg.automapCustomColors % 3]); MN_DrawColorBox(menu, idx++, cfg.automapL1[0], cfg.automapL1[1], cfg.automapL1[2], 1); MN_DrawColorBox(menu, idx++, cfg.automapL2[0], cfg.automapL2[1], cfg.automapL2[2], 1); MN_DrawColorBox(menu, idx++, cfg.automapL3[0], cfg.automapL3[1], cfg.automapL3[2], 1); MN_DrawColorBox(menu, idx++, cfg.automapL0[0], cfg.automapL0[1], cfg.automapL0[2], 1); MN_DrawColorBox(menu, idx++, cfg.automapMobj[0], cfg.automapMobj[1], cfg.automapMobj[2], 1); MN_DrawColorBox(menu, idx, cfg.automapBack[0], cfg.automapBack[1], cfg.automapBack[2], 1); } /** * Set automap line alpha */ void M_MapOpacity(int option, void* data) { M_FloatMod10(&cfg.automapOpacity, option); } /** * Set automap line alpha */ void M_MapLineAlpha(int option, void* data) { M_FloatMod10(&cfg.automapLineAlpha, option); } /** * Set show line/teleport lines in different color */ void M_MapDoorColors(int option, void *data) { cfg.automapShowDoors = !cfg.automapShowDoors; } /** * Set glow line amount */ void M_MapDoorGlow(int option, void *data) { if(option == RIGHT_DIR) { if(cfg.automapDoorGlow < 200) cfg.automapDoorGlow++; } else if(cfg.automapDoorGlow > 0) cfg.automapDoorGlow--; } /** * Set rotate mode */ void M_MapRotate(int option, void *data) { cfg.automapRotate = !cfg.automapRotate; Automap_SetViewRotate(getAutomap(AM_MapForPlayer(CONSOLEPLAYER)), cfg.automapRotate); } /** * Set which HUD to draw when in automap */ void M_MapStatusbar(int option, void *data) { if(option == RIGHT_DIR) { if(cfg.automapHudDisplay < 2) cfg.automapHudDisplay++; } else if(cfg.automapHudDisplay > 0) cfg.automapHudDisplay--; } void M_MapCustomColors(int option, void* data) { if(option == RIGHT_DIR) { if(cfg.automapCustomColors < 2) cfg.automapCustomColors++; } else if(cfg.automapCustomColors > 0) cfg.automapCustomColors--; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_xgline.c0000644000175000017500000026765611357170242022624 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_xgline.c: Extended Generalized Line Types. * * Implements all XG line interactions on a map */ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "dmu_lib.h" #include "p_mapsetup.h" #include "d_net.h" #include "p_xgline.h" #include "p_xgsec.h" #include "p_player.h" #include "p_map.h" #include "p_mapspec.h" #include "p_terraintype.h" #include "p_tick.h" #include "p_switch.h" // MACROS ------------------------------------------------------------------ #define XLTIMER_STOPPED 1 // Timer stopped. #define EVTYPESTR(evtype) (evtype == XLE_CHAIN? "CHAIN" \ : evtype == XLE_CROSS? "CROSS" \ : evtype == XLE_USE? "USE" \ : evtype == XLE_SHOOT? "SHOOT" \ : evtype == XLE_HIT? "HIT" \ : evtype == XLE_TICKER? "TICKER" \ : evtype == XLE_AUTO? "AUTO" \ : evtype == XLE_FORCED? "FORCED" \ : evtype == XLE_FUNC? "FUNCTION" : "???") #define LREFTYPESTR(reftype) (reftype == LREF_NONE? "NONE" \ : reftype == LREF_SELF? "SELF" \ : reftype == LREF_TAGGED? "TAGGED LINES" \ : reftype == LREF_LINE_TAGGED? "LINE TAGGED LINES" \ : reftype == LREF_ACT_TAGGED? "ACT TAGGED LINES" \ : reftype == LREF_INDEX? "INDEXED LINE" \ : reftype == LREF_ALL? "ALL LINES" : "???") #define LPREFTYPESTR(reftype) (reftype == LPREF_NONE? "NONE" \ : reftype == LPREF_MY_FLOOR? "MY FLOOR" \ : reftype == LPREF_TAGGED_FLOORS? "TAGGED FLOORS" \ : reftype == LPREF_LINE_TAGGED_FLOORS? "LINE TAGGED FLOORS" \ : reftype == LPREF_ACT_TAGGED_FLOORS? "ACT TAGGED FLOORS" \ : reftype == LPREF_INDEX_FLOOR? "INDEXED FLOOR" \ : reftype == LPREF_ALL_FLOORS? "ALL FLOORS" \ : reftype == LPREF_MY_CEILING? "MY CEILING" \ : reftype == LPREF_TAGGED_CEILINGS? "TAGGED CEILINGS" \ : reftype == LPREF_LINE_TAGGED_CEILINGS? "LINE TAGGED CEILINGS" \ : reftype == LPREF_ACT_TAGGED_CEILINGS? "ACT TAGGED CEILINGS" \ : reftype == LPREF_INDEX_CEILING? "INDEXED CEILING" \ : reftype == LPREF_ALL_CEILINGS? "ALL CEILINGS" \ : reftype == LPREF_SPECIAL? "SPECIAL" \ : reftype == LPREF_BACK_FLOOR? "BACK FLOOR" \ : reftype == LPREF_BACK_CEILING? "BACK CEILING" \ : reftype == LPREF_THING_EXIST_FLOORS? "SECTORS WITH THING - FLOOR" \ : reftype == LPREF_THING_EXIST_CEILINGS? "SECTORS WITH THING - CEILING" \ : reftype == LPREF_THING_NOEXIST_FLOORS? "SECTORS WITHOUT THING - FLOOR" \ : reftype == LPREF_THING_NOEXIST_CEILINGS? "SECTORS WITHOUT THING - CEILING" : "???") #define LSREFTYPESTR(reftype) (reftype == LSREF_NONE? "NONE" \ : reftype == LSREF_MY? "MY SECTOR" \ : reftype == LSREF_TAGGED? "TAGGED SECTORS" \ : reftype == LSREF_LINE_TAGGED? "LINE TAGGED SECTORS" \ : reftype == LSREF_ACT_TAGGED? "ACT TAGGED SECTORS" \ : reftype == LSREF_INDEX? "INDEXED SECTOR" \ : reftype == LSREF_ALL? "ALL SECTORS" \ : reftype == LSREF_BACK? "BACK SECTOR" \ : reftype == LSREF_THING_EXIST? "SECTORS WITH THING" \ : reftype == LSREF_THING_NOEXIST? "SECTORS WITHOUT THING" : "???") #define TO_DMU_TOP_COLOR(x) ((x) == 0? DMU_TOP_COLOR_RED \ : (x) == 1? DMU_TOP_COLOR_GREEN \ : DMU_TOP_COLOR_BLUE) #define TO_DMU_MIDDLE_COLOR(x) ((x) == 0? DMU_MIDDLE_COLOR_RED \ : (x) == 1? DMU_MIDDLE_COLOR_GREEN \ : (x) == 2? DMU_MIDDLE_COLOR_BLUE \ : DMU_MIDDLE_ALPHA) #define TO_DMU_BOTTOM_COLOR(x) ((x) == 0? DMU_BOTTOM_COLOR_RED \ : (x) == 1? DMU_BOTTOM_COLOR_GREEN \ : DMU_BOTTOM_COLOR_BLUE) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void XL_ChangeMaterial(linedef_t* line, int sidenum, int section, material_t* mat, blendmode_t blend, byte rgba[4], int flags); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- int C_DECL XL_DoChainSequence(); int C_DECL XL_DoDamage(); int C_DECL XL_DoPower(); int C_DECL XL_DoKey(); int C_DECL XL_DoExplode(); int C_DECL XL_DoCommand(); int C_DECL XLTrav_ChangeLineType(); int C_DECL XLTrav_Activate(); int C_DECL XLTrav_Music(); int C_DECL XLTrav_LineCount(); int C_DECL XLTrav_LeaveMap(); int C_DECL XLTrav_DisableLine(); int C_DECL XLTrav_EnableLine(); int C_DECL XLTrav_ChangeWallMaterial(); int C_DECL XLTrav_LineTeleport(); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int xgDev = 0; // Print dev messages. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static linetype_t typebuffer; static char msgbuf[80]; struct mobj_s dummyThing; /* ADD NEW XG CLASSES TO THE END - ORIGINAL INDICES MUST STAY THE SAME!!! */ xgclass_t xgClasses[NUMXGCLASSES] = { { NULL, NULL, TRAV_NONE, 0, 1, 0, "None" }, // Dummy class (has no functions but enables use of secondary actions) (no params) { XL_DoChainSequence, NULL, TRAV_NONE, 0, 1, 0, "Chain Sequence", // Excute a chain of other XG line types (a zero ends the list) {{XGPF_INT, "Chain Flags", "chsf_", 0}, // ip0: (chsf_) chain sequence flags {XGPF_INT, "Line Type 0", "", -1}, // ip1: Type to execute {XGPF_INT, "Line Type 1", "", -1}, // ip2: "" "" "" {XGPF_INT, "Line Type 2", "", -1}, // ip3: "" "" "" {XGPF_INT, "Line Type 3", "", -1}, // ip4: "" "" "" {XGPF_INT, "Line Type 4", "", -1}, // ip5: "" "" "" {XGPF_INT, "Line Type 5", "", -1}, // ip6: "" "" "" {XGPF_INT, "Line Type 6", "", -1}, // ip7: "" "" "" {XGPF_INT, "Line Type 7", "", -1}, // ip8: "" "" "" {XGPF_INT, "Line Type 8", "", -1}, // ip9: "" "" "" {XGPF_INT, "Line Type 9", "", -1}, // ip10: "" "" "" {XGPF_INT, "Line Type 10", "", -1}, // ip11: "" "" "" {XGPF_INT, "Line Type 11", "", -1}, // ip12: "" "" "" {XGPF_INT, "Line Type 12", "", -1}, // ip13: "" "" "" {XGPF_INT, "Line Type 13", "", -1}, // ip14: "" "" "" {XGPF_INT, "Line Type 14", "", -1}, // ip15: "" "" "" {XGPF_INT, "Line Type 15", "", -1}, // ip16: "" "" "" {XGPF_INT, "Line Type 16", "", -1}, // ip17: "" "" "" {XGPF_INT, "Line Type 17", "", -1}, // ip18: "" "" "" {XGPF_INT, "Line Type 18", "", -1} }}, // ip19: "" "" "" { XSTrav_MovePlane, XS_InitMovePlane, TRAV_PLANES, 0, 1, 0, "Move Plane", // Move one or more planes. Optionaly change textures/types on start/end {{XGPF_INT, "Target Ref", "lpref_", 0}, // ip0: (plane ref) plane(s) to move. {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Destination Ref", "spref_", 2}, // ip2: destination height type (zero, relative to current, surrounding highest/lowest floor/ceiling) {XGPF_INT, "Move Flags", "pmf_", 3}, // ip3: flags (PMF_*) {XGPF_INT, "Start Sound", "", 4 | MAP_SND}, // ip4: start sound {XGPF_INT, "End Sound", "", 5 | MAP_SND}, // ip5: end sound {XGPF_INT, "Move Sound", "", 6 | MAP_SND}, // ip6: move sound {XGPF_INT, "Start Material Ref", "spref_", 7}, // ip7: start texture origin (uses same ids as i2) (spec: use ip8 as tex num) {XGPF_INT, "Start Material Num", "", 8 | MAP_MATERIAL}, // ip8: data component or number/name of flat {XGPF_INT, "End Material Ref", "spref_", 9}, // ip9: end texture origin (uses same ids as i2) (spec: use ip10 as tex num) {XGPF_INT, "End Material Num", "", 10 | MAP_MATERIAL}, // ip10: data component or number/name of flat {XGPF_INT, "Start Type Ref", "lpref_", 11}, // ip11: (plane ref) start sector type (spec: use i12 as type ID) {XGPF_INT, "Start Type Num", "", -1}, // ip12: data component or type ID {XGPF_INT, "End Type Ref", "lpref_", 13}, // ip13: (plane ref) end sector type (spec: use i14 as type ID) {XGPF_INT, "End Type Num", "", -1} }}, // ip14: data component or type ID { XSTrav_BuildStairs, XS_InitStairBuilder, TRAV_PLANES, 0, 1, 0, "Build Stairs", // Moves one or more planes, incrementing their height with each move {{XGPF_INT, "Target Ref", "lpref_", 0}, // ip0: (plane ref) plane to start from {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Spread Material", "", -1}, // ip2: (true/false) stop when texture changes {XGPF_INT, "Spread Build", "", -1}, // ip3: (true/false) spread build? {XGPF_INT, "Start Sound", "", 4 | MAP_SND}, // ip4: start build sound (doesn't wait) {XGPF_INT, "Step Start Sound", "", 5 | MAP_SND}, // ip5: step start sound {XGPF_INT, "Step End Sound", "", 6 | MAP_SND}, // ip6: step end sound {XGPF_INT, "Step Move Sound", "", 7 | MAP_SND} }}, // ip7: step move sound { XL_DoDamage, NULL, TRAV_NONE, 0, 1, 0, "Damage", // Deals health damage to the activator {{XGPF_INT, "Min Delta", "", -1}, // ip0: min damage delta {XGPF_INT, "Max Delta", "", -1}, // ip1: max damage delta {XGPF_INT, "Min Limit", "", -1}, // ip2: min limit (wont damage if health bellow) {XGPF_INT, "Max Limit", "", -1} }}, // ip3: max limit (wont damage if health above) { XL_DoPower, NULL, TRAV_NONE, 0, 1, 0, "Power", // Deals armor damage to the activator (must be a player) {{XGPF_INT, "Min Delta", "", -1}, // ip0: min power delta {XGPF_INT, "Max Delta", "", -1}, // ip1: max power delta {XGPF_INT, "Min Limit", "", -1}, // ip2: min limit {XGPF_INT, "Max Limit", "", -1} }}, // ip3: max limit { XLTrav_ChangeLineType, NULL, TRAV_LINES, 0, 1, 0, "Line Type", // Changes a line's type (must be an XG type) {{XGPF_INT, "Target Ref", "lref_", 0}, // ip0: (line ref) line(s) to change {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Line Type", "", -1} }}, // ip2: new type (must be an XG line type) { XSTrav_SectorType, NULL, TRAV_SECTORS, 0, 1, 0, "Sector Type", // Changes a sector's type (must be an XG type) {{XGPF_INT, "Target Ref", "lsref_", 0}, // ip0: (sector ref) sector(s) to change {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Sector Type", "", -1} }}, // ip2: new type (zero or an XG sector type) { XSTrav_SectorLight, NULL, TRAV_SECTORS, 0, 1, 0, "Sector Light", // Change the light level and/or color of the target sector(s). {{XGPF_INT, "Target Ref", "lsref_", 0}, // ip0: (sector ref) sector(s) to change {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Change Light", "", -1}, // ip2: if non-zero light level will be changed {XGPF_INT, "Change Color", "", -1}, // ip3: if non-zero colour will be changed {XGPF_INT, "Light Ref", "lightref_", 4}, // ip4: (light ref) sector to get the initial light delta from. // lightref_none makes ip5 an absolute value {XGPF_INT, "Light Delta", "", -1}, // ip5: offset to the delta or absolute value {XGPF_INT, "Color Ref", "lightref_", 6}, // ip6: (light ref) sector to get the initial colour deltas from. // lightref_none makes ip7-9 absolute values {XGPF_INT, "Red Delta", "", -1}, // ip7: offset to red delta {XGPF_INT, "Green Delta", "", -1}, // ip8: offset to green delta {XGPF_INT, "Blue Delta", "", -1} }}, // ip9: offset to blue delta { XLTrav_Activate, NULL, TRAV_LINES, 0, 1, 0, "Activate", // Sends a chain event to all the referenced lines {{XGPF_INT, "Target Ref", "lref_", 0}, // ip0: (line ref) line(s) to activate {XGPF_INT, "Target Num", "", -1} }}, // ip1: { XL_DoKey, NULL, TRAV_NONE, 0, 1, 0, "Key", // Gives/takes keys to/from the activator (must be a player) // Params are bitfields! Bit 1 (0x1) corresponds key 1, bit 2 (0x2) key 2, etc. {{XGPF_INT, "Give Keys", "", -1}, // ip0: keys to give {XGPF_INT, "Take Keys", "", -1} }}, // ip1: keys to take away. { XLTrav_Music, NULL, TRAV_LINES, 2, 3, 0, "Music", // Changes the music track being played {{XGPF_INT, "Song ID", "ldref_", 0 | MAP_MUS}, // ip0: song id/name or (line data ref from ip2) {XGPF_INT, "Play Looped", "", -1}, // ip1: non-zero means play looped {XGPF_INT, "Data Ref", "lref_", 2}, // ip2: (line ref) used with line data ref eg set music track to line-tag {XGPF_INT, "Data Num", "", -1} }}, // ip3: { XLTrav_LineCount, NULL, TRAV_LINES, 0, 1, 0, "Line Count", // Changes the XG line(s)' internal activation counter {{XGPF_INT, "Target Ref", "lref_", 0}, // ip0: (line ref) line(s) to change {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Set Absolute", "", -1}, // ip2: non-zero makes ip3 absolute {XGPF_INT, "Count Delta", "", -1} }}, // ip3: count delta or absolute { XLTrav_LeaveMap, NULL, TRAV_LINES, 1, 2, 0, "Leave Map", // Exits the current map {{XGPF_INT, "Secret Exit", "", -1}, // ip0: non-zero goto secret map {XGPF_INT, "Data Ref", "lref_", 1}, // ip1: (line ref) line to acquire (line data ref) from {XGPF_INT, "Data Num", "", -1}, // ip2: {XGPF_INT, "Goto Map", "ldref_", 3} }}, // ip3: map ID or (line data ref from ip1) { XLTrav_DisableLine, NULL, TRAV_LINES, 0, 1, 0, "Disable Line", // Disables the referenced line(s) if active {{XGPF_INT, "Target Ref", "lref_", 0}, // ip0: (line ref) line(s) to disable {XGPF_INT, "Target Num", "", -1} }}, // ip1: { XLTrav_EnableLine, NULL, TRAV_LINES, 0, 1, 0, "Enable Line", // Enables the referenced line(s) if active. {{XGPF_INT, "Target Ref", "lref_", 0}, // ip0: (line ref) line(s) to enable {XGPF_INT, "Target Num", "", -1} }}, // ip1: { XL_DoExplode, NULL, TRAV_NONE, 0, 1, 0, "Explode" }, // Explodes the activator (no params). { XSTrav_PlaneMaterial, NULL, TRAV_PLANES, 0, 1, 0, "Plane Material", // Change the material and/or surface color of a plane. {{XGPF_INT, "Target Ref", "lpref_", 0}, // ip0 : (plane ref) plane(s) to change {XGPF_INT, "Target Num", "", -1}, // ip1 : ref data {XGPF_INT, "Material Ref", "spref_", 2}, // ip2 : Texture ref {XGPF_INT, "Material Num", "", 3 | MAP_MATERIAL}, // ip3 : texture number (flat), used with SPREF_NONE {XGPF_INT, "Red Delta", "", -1}, // ip4 : plane surface color (red) {XGPF_INT, "Green Delta", "", -1}, // ip5 : "" (green) {XGPF_INT, "Blue Delta", "", -1} }}, // ip6 : "" (blue) { XLTrav_ChangeWallMaterial, NULL, TRAV_LINES, 0, 1, 0, "Wall Material", // Changes material(s) on the referenced line(s). // Changes surface colour(s), alpha, mid textue blendmode and sidedef flags {{XGPF_INT, "Target Ref", "lref_", 0}, // ip0: (line ref) line(s) to change {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Side Num", "", -1}, // ip2: non-zero change the back side {XGPF_INT, "Top Material", "", 3 | MAP_MATERIAL}, // ip3: top texture to change to (blank indicates no change) {XGPF_INT, "Middle Material", "", 4 | MAP_MATERIAL}, // ip4: middle texture to change to (blank indicates no change) {XGPF_INT, "Bottom Material", "", 5 | MAP_MATERIAL}, // ip5: bottom texture to change to (blank indicates no change) {XGPF_INT, "Set Mid If None", "", -1}, // ip6: set mid texture even if previously zero {XGPF_INT, "Sidedef Flags", "sdf_", 7}, // ip7: (sdf_) sidedef flags (used with surface colour blending, fullbright etc) {XGPF_INT, "Middle Blendmode", "bm_", 8}, // ip8: (bm_) middle texture blendmode {XGPF_INT, "Top Red Delta", "", -1}, // ip9: {XGPF_INT, "Top Green Delta", "", -1}, // ip10: {XGPF_INT, "Top Blue Delta", "", -1}, // ip11: {XGPF_INT, "Middle Red Delta", "", -1}, // ip12: {XGPF_INT, "Middle Green Delta", "", -1}, // ip13: {XGPF_INT, "Middle Blue Delta", "", -1}, // ip14: {XGPF_INT, "Middle Alpha Delta", "", -1}, // ip15: {XGPF_INT, "Bottom Red Delta", "", -1}, // ip16: {XGPF_INT, "Bottom Green Delta", "", -1}, // ip17: {XGPF_INT, "Bottom Blue Delta", "", -1} }}, // ip18: { XL_DoCommand, NULL, TRAV_NONE, 0, 1, 0, "Command" }, // Executes a console command (CCmd) { XSTrav_SectorSound, NULL, TRAV_SECTORS, 0, 1, 0, "Sector Sound", // Plays a sound in sector(s) {{XGPF_INT, "Target Ref", "lsref_", 0}, // ip0: (sector ref) sector(s) to play the sound in {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Sound ID", "", 2 | MAP_SND}, // ip2: sound name/id to play {XGPF_INT, "Origin", "", -1} }}, // ip3: non-zero = play from a specific origin (1=floor, 2=ceiling) else 0=center { XSTrav_MimicSector, NULL, TRAV_SECTORS, 0, 1, 0, "Mimic Sector", // Copies all properties from target sector to destination sector(s) {{XGPF_INT, "Target Ref", "lsref_", 0}, // ip0: (sector ref) sector(s) to change {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "Mimic Ref", "spref_", 2}, // ip2: (spref) sector to mimic {XGPF_INT, "Mimic Num", "", -1} }}, // ip3: { XSTrav_Teleport, NULL, TRAV_SECTORS, 0, 1, 0, "Teleport", // Teleports the activator to the first teleport exit in the target sector {{XGPF_INT, "Target Ref", "lsref_", 0}, // ip0: (sector ref) sector(s) to teleport to (first acceptable target is used) {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "No Flash", "", -1}, // ip2: non-zero = no flash (or sound) {XGPF_INT, "No Sound", "", -1}, // ip3: non-zero = no sound {XGPF_INT, "Always Stomp", "", -1} }}, // ip4: non-zero = Always telefrag { XLTrav_LineTeleport, NULL, TRAV_LINES, 0, 1, 1 | XLE_CROSS, "Line Teleport", // Teleports the activator to the referenced line {{XGPF_INT, "Target Ref", "lref_", 0}, // ip0: (line ref) teleport destination {XGPF_INT, "Target Num", "", -1}, // ip1: {XGPF_INT, "No Flash", "", -1}, // ip2: non-zero = spawn MT_TFOG {XGPF_INT, "Teleport Sound", "", 3 | MAP_SND}, // ip3: sound ID/name to play (or silent) {XGPF_INT, "Exit Side", "", -1}, // ip4: non-zero = exit from the back of the target line {XGPF_INT, "Always Stomp", "", -1} }} // ip5: non-zero = Always telefrag }; cvar_t xgCVars[] = { {"xg-dev", CVF_NO_ARCHIVE, CVT_INT, &xgDev, 0, 1}, {NULL} }; ccmd_t xgCCmds[] = { {"movefloor", NULL, CCmdMovePlane}, {"moveceil", NULL, CCmdMovePlane}, {"movesec", NULL, CCmdMovePlane}, {NULL} }; // CODE -------------------------------------------------------------------- /** * Register XG CCmds & CVars (called during pre init) */ void XG_Register(void) { int i; for(i = 0; xgCVars[i].name; ++i) Con_AddVariable(xgCVars + i); for(i = 0; xgCCmds[i].name; ++i) Con_AddCommand(xgCCmds + i); } /** * Debug message printer. */ void XG_Dev(const char* format, ...) { static char buffer[2000]; va_list args; if(!xgDev) return; va_start(args, format); dd_vsnprintf(buffer, sizeof(buffer), format, args); strcat(buffer, "\n"); Con_Message(buffer); va_end(args); } /** * Init XG data for the map. */ void XG_Init(void) { XL_Init(); // Init lines. XS_Init(); // Init sectors. } void XG_Ticker(void) { // Nothing to do. } /** * This is called during an engine reset. Disables all XG functionality! */ void XG_Update(void) { // Clients rely on the server, they don't do XG themselves. if(IS_CLIENT) return; XG_ReadTypes(); XS_Update(); XL_Update(); } /** * Adds the given binary format line type to the generated types array */ int XL_AddAutoGenType(linetype_t* newtype) { return true; } /** * Converts a line ID number to a line type (BOOM support). */ int XL_AutoGenType(int id, linetype_t* outptr) { return false; // Cos we don't work yet. #if 0 linetype_t *l; // Do the magic // is the ID in the range 12160 -> 32768 if(!(id >= 12160 && id <= 32768)) return false; // Have we already generated a line of this type? if(1) { // Then return a ptr to it outptr = l; return true; } // Which bitfield format are we generating from? if(1) //XG format { /* // Generate the new line type l->id = id; l->flags = def->flags[0]; l->flags2 = def->flags[1]; l->flags3 = def->flags[2]; l->lineClass = def->lineClass; l->actType = def->actType; l->actCount = def->actCount; l->actTime = def->actTime; // l->actTag = def->actTag; for(i = 0; i < 10; i++) { if(i == 9) l->aparm[i] = Def_GetMobjNum(def->aparm9); else l->aparm[i] = def->aparm[i]; } // l->tickerStart = def->tickerStart; // l->tickerEnd = def->tickerEnd; // l->tickerInterval = def->tickerInterval; l->actSound = Friendly(Def_GetSoundNum(def->actSound)); l->deactSound = Friendly(Def_GetSoundNum(def->deactSound)); l->evChain = def->evChain; l->actChain = def->actChain; l->deactChain = def->deactChain; l->actLineType = def->actLineType; l->deactLineType = def->deactLineType; l->wallSection = def->wallSection; l->actTex = Friendly(R_CheckTextureNumForName(def->actTex)); l->deactTex = Friendly(R_CheckTextureNumForName(def->deactTex)); l->actMsg = def->actMsg; l->deactMsg = def->deactMsg; l->texMoveAngle = def->texMoveAngle; l->texMoveSpeed = def->texMoveSpeed;*/ // Add it to the generated line types array XL_AddAutoGenType(l); outptr = l; } #if __JDOOM__ || __JDOOM64__ else // BOOM format { // Generate the new line type outptr = l; } #endif return true; #endif } /** * @return @c true, if the type is defined. */ linetype_t* XL_GetType(int id) { linetype_t* ptr; char buff[6]; // Try finding it from the DDXGDATA lump. ptr = XG_GetLumpLine(id); if(ptr) { // Got it! memcpy(&typebuffer, ptr, sizeof(*ptr)); return &typebuffer; } // Does Doomsday have a definition for this? dd_snprintf(buff, 6, "%i", id); if(Def_Get(DD_DEF_LINE_TYPE, buff, &typebuffer)) return &typebuffer; // Is this a type we can generate automatically? if(XL_AutoGenType(id, &typebuffer)) return &typebuffer; // A definition was not found. return NULL; } int XG_RandomInt(int min, int max) { float x; if(max == min) return max; x = M_Random() / 256.0f; // Never reaches 1. return (int) (min + x * (max - min) + x); } float XG_RandomPercentFloat(float value, int percent) { float i = (2 * M_Random() / 255.0f - 1) * percent / 100.0f; return value * (1 + i); } boolean findXLThinker(thinker_t* th, void* context) { xlthinker_t* xl = (xlthinker_t*) th; if(xl->line == (linedef_t*) context) return false; // Stop iteration, we've found it. return true; // Continue iteration. } /** * Looks for line type definition and sets the line type if one is found. */ void XL_SetLineType(linedef_t* line, int id) { xline_t* xline = P_ToXLine(line); if(XL_GetType(id)) { xline->special = id; // Allocate memory for the line type data. if(!xline->xg) xline->xg = Z_Malloc(sizeof(xgline_t), PU_MAP, 0); // Init the extended line state. xline->xg->disabled = false; xline->xg->timer = 0; xline->xg->tickerTimer = 0; memcpy(&xline->xg->info, &typebuffer, sizeof(linetype_t)); // Initial active state. xline->xg->active = (typebuffer.flags & LTF_ACTIVE) != 0; xline->xg->activator = &dummyThing; XG_Dev("XL_SetLineType: Line %i (%s), ID %i.", P_ToIndex(line), xgClasses[xline->xg->info.lineClass].className, id); // If there is not already an xlthinker for this line, create one. if(DD_IterateThinkers(XL_Thinker, findXLThinker, line)) { // Not created one yet. xlthinker_t* xl = Z_Calloc(sizeof(*xl), PU_MAP, 0); xl->thinker.function = XL_Thinker; DD_ThinkerAdd(&xl->thinker); xl->line = line; } } else if(id) { XG_Dev("XL_SetLineType: Line %i, type %i NOT DEFINED.", P_ToIndex(line), id); } } /** * Initialize extended lines for the map. */ void XL_Init(void) { uint i; linedef_t* line; memset(&dummyThing, 0, sizeof(dummyThing)); // Clients rely on the server, they don't do XG themselves. if(IS_CLIENT) return; for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); P_ToXLine(line)->xg = 0; XL_SetLineType(line, P_ToXLine(line)->special); } } /** * Executes the specified function on all planes that match the reference * (reftype). * * @return @c true, iff all callbacks return @c true. */ int XL_TraversePlanes(linedef_t* line, int refType, int ref, void* data, void* context, boolean travsectors, mobj_t* activator, int (C_DECL *func)()) { int tag; mobj_t* mo; boolean ok, findSecTagged; sector_t* sec, *frontSec, *backSec; xsector_t* xsec; if(xgDev) { char buff[50]; if(ref) sprintf(buff, ": %i", ref); XG_Dev("XL_Traverse%s: Line %i, ref (%s%s)", travsectors? "Sectors":"Planes", P_ToIndex(line), travsectors? LSREFTYPESTR(refType) : LPREFTYPESTR(refType), ref? buff: ""); } if(refType == LPREF_NONE) return false; // This is not a reference! frontSec = P_GetPtrp(line, DMU_FRONT_SECTOR); backSec = P_GetPtrp(line, DMU_BACK_SECTOR); // References to a single plane if(refType == LPREF_MY_FLOOR || refType == LPREF_MY_CEILING) { if(frontSec) { return func(frontSec, refType == LPREF_MY_CEILING? true:false, data, context, activator); } XG_Dev(" Line %i has no front sector!", P_ToIndex(line)); } if(refType == LPREF_BACK_FLOOR || refType == LPREF_BACK_CEILING) { if(backSec) { return func(backSec, refType == LPREF_BACK_CEILING? true:false, data, context, activator); } XG_Dev(" Line %i has no back sector!", P_ToIndex(line)); } if(refType == LPREF_INDEX_FLOOR) return func(P_ToPtr(DMU_SECTOR, ref), false, data, context, activator); if(refType == LPREF_INDEX_CEILING) return func(P_ToPtr(DMU_SECTOR, ref), true, data, context, activator); // Can we use the tagged sector lists? findSecTagged = false; if(refType == LPREF_TAGGED_FLOORS || refType == LPREF_TAGGED_CEILINGS) { findSecTagged = true; tag = ref; } else if(refType == LPREF_LINE_TAGGED_FLOORS || refType == LPREF_LINE_TAGGED_CEILINGS) { findSecTagged = true; tag = P_ToXLine(line)->tag; } // References to multiple planes if(findSecTagged) { // Use tagged sector lists for these (speed). iterlist_t* list; list = P_GetSectorIterListForTag(tag, false); if(list) { // Find the first sector with the tag. P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { xsec = P_ToXSector(sec); if(refType == LPREF_TAGGED_FLOORS || refType == LPREF_TAGGED_CEILINGS) { if(!func(sec, refType == LPREF_TAGGED_CEILINGS, data, context, activator)) return false; } if(refType == LPREF_LINE_TAGGED_FLOORS || refType == LPREF_LINE_TAGGED_CEILINGS) { if(!func(sec, refType == LPREF_LINE_TAGGED_CEILINGS, data, context, activator)) return false; } } } } else { uint i; for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); if(refType == LPREF_ALL_FLOORS || refType == LPREF_ALL_CEILINGS) { if(!func(sec, refType == LPREF_ALL_CEILINGS, data, context, activator)) return false; } if((refType == LPREF_ACT_TAGGED_FLOORS || refType == LPREF_ACT_TAGGED_CEILINGS) && xsec->xg && xsec->xg->info.actTag == ref) { if(!func(sec, refType == LPREF_ACT_TAGGED_CEILINGS, data, context, activator)) return false; } // Reference all sectors with (at least) one mobj of specified // type inside. if(refType == LPREF_THING_EXIST_FLOORS || refType == LPREF_THING_EXIST_CEILINGS) { ok = true; for(mo = P_GetPtrp(sec, DMT_MOBJS); ok && mo; mo = mo->sNext) { if(mo->type == P_ToXLine(line)->xg->info.aparm[9]) { XG_Dev(" Thing of type %i found in sector id %i.", P_ToXLine(line)->xg->info.aparm[9], i); if(!func(sec, refType == LPREF_THING_EXIST_CEILINGS, data, context, activator)) return false; ok = false; } } } // Reference all sectors with NONE of the specified mobj type // inside. if(refType == LPREF_THING_NOEXIST_FLOORS || refType == LPREF_THING_NOEXIST_CEILINGS) { ok = true; for(mo = P_GetPtrp(sec, DMT_MOBJS); ok && mo; mo = mo->sNext) { if(mo->type != P_ToXLine(line)->xg->info.aparm[9]) continue; else ok = false; } if(ok) { XG_Dev(" No things of type %i found in sector id %i.", P_ToXLine(line)->xg->info.aparm[9], i); if(!func(sec, refType == LPREF_THING_NOEXIST_CEILINGS, data, context, activator)) return false; } } } } return true; } /** * Executes the specified function on all lines that match the reference * 'rtype'. * * @return @c false if 'func' returns @c false, otherwise * @c true. Stops checking when false is returned. */ int XL_TraverseLines(linedef_t* line, int rtype, int ref, void* data, void* context, mobj_t* activator, int (C_DECL *func)()) { uint i; int tag; int reftype = rtype; char buff[50]; linedef_t* iter; boolean findLineTagged; // Binary XG data from DD_XGDATA uses the old flag values. // Add one to the ref type. if(xgDataLumps) reftype+= 1; if(ref) sprintf(buff," : %i",ref); XG_Dev("XL_TraverseLines: Line %i, ref (%s%s)", P_ToIndex(line), LREFTYPESTR(reftype), ref? buff : ""); if(reftype == LREF_NONE) return func(NULL, true, data, context, activator); // Not a real reference // References to single lines if(reftype == LREF_SELF) // Traversing self is simple. return func(line, true, data, context, activator); if(reftype == LREF_INDEX) return func(P_ToPtr(DMU_LINEDEF, ref), true, data, context, activator); // Can we use the tagged line lists? findLineTagged = false; if(reftype == LREF_TAGGED) { findLineTagged = true; tag = ref; } else if(reftype == LREF_LINE_TAGGED) { findLineTagged = true; tag = P_ToXLine(line)->tag; } // References to multiple lines if(findLineTagged) { // Use tagged line lists for these (speed). iterlist_t *list = P_GetLineIterListForTag(tag, false); if(list) { P_IterListResetIterator(list, true); while((iter = P_IterListIterator(list)) != NULL) { if(reftype == LREF_TAGGED) { if(!func(iter, true, data, context, activator)) return false; } else if(reftype == LREF_LINE_TAGGED) { // Ref is true if line itself should be excluded. if(!ref || iter != line) if(!func(iter, true, data, context, activator)) return false; } } } } else { for(i = 0; i < numlines; ++i) { iter = P_ToPtr(DMU_LINEDEF, i); if(reftype == LREF_ALL) { if(!func(iter, true, data, context, activator)) return false; } else if(reftype == LREF_ACT_TAGGED) { xline_t *xl = P_ToXLine(iter); if(xl->xg && xl->xg->info.actTag == ref) if(!func(iter, true, data, context, activator)) return false; } } } return true; } /** * @return Value as determined by the reference type from the * specified linedef, using data from either the linedef * itself or context (will always be linetype_t). */ int XL_ValidateLineRef(linedef_t* line, int reftype, void* context, char* parmname) { int answer = 0; sidedef_t* side; switch(reftype) { case LDREF_ID: // Line ID. answer = P_ToIndex(line); XG_Dev("XL_ValidateLineRef: Using Line ID (%i) as %s", answer, parmname); break; case LDREF_SPECIAL: // Line Special. answer = P_ToXLine(line)->special; XG_Dev("XL_ValidateLineRef: Using Line Special (%i) as %s", answer, parmname); break; case LDREF_TAG: // Line Tag. answer = P_ToXLine(line)->tag; XG_Dev("XL_ValidateLineRef: Using Line Tag (%i) as %s", answer, parmname); break; case LDREF_ACTTAG: // Line ActTag. if(!P_ToXLine(line)->xg) { XG_Dev("XL_ValidateLineRef: REFERENCE NOT AN XG LINE"); break; } if(!P_ToXLine(line)->xg->info.actTag) { XG_Dev("XL_ValidateLineRef: REFERENCE DOESNT HAVE AN ACT TAG"); break; } answer = P_ToXLine(line)->xg->info.actTag; XG_Dev("XL_ValidateLineRef: Using Line ActTag (%i) as %s", answer, parmname); break; case LDREF_COUNT: // Line count. if(!P_ToXLine(line)->xg) { XG_Dev("XL_ValidateLineRef: REFERENCE NOT AN XG LINE"); break; } answer = P_ToXLine(line)->xg->info.actCount; XG_Dev("XL_ValidateLineRef: Using Line Count (%i) as %s", answer, parmname); break; case LDREF_ANGLE: // Line angle. { float d1[2]; P_GetFloatpv(line, DMU_DXY, d1); answer = R_PointToAngle2(0, 0, d1[0], d1[1]) / (float) ANGLE_MAX * 360; XG_Dev("XL_ValidateLineRef: Using Line Angle (%i) as %s", answer, parmname); break; } case LDREF_LENGTH: // Line length. // Answer should be in map units. answer = P_GetFixedp(line, DMU_LENGTH) >> FRACBITS; XG_Dev("XL_ValidateLineRef: Using Line Length (%i) as %s", answer, parmname); break; case LDREF_TOP_OFFSETX: // Can this ever fail? side = P_GetPtrp(line, DMU_SIDEDEF0); if(!side) { XG_Dev("XL_ValidateLineRef: REFERENCE MISSING FRONT SIDEDEF!"); break; } answer = P_GetIntp(side, DMU_TOP_MATERIAL_OFFSET_X); XG_Dev("XL_ValidateLineRef: Using Line Top X Offset (%i) as %s", answer, parmname); break; case LDREF_TOP_OFFSETY: // Can this ever fail? side = P_GetPtrp(line, DMU_SIDEDEF0); if(!side) { XG_Dev("XL_ValidateLineRef: REFERENCE MISSING FRONT SIDEDEF!"); break; } answer = P_GetIntp(side, DMU_TOP_MATERIAL_OFFSET_Y); XG_Dev("XL_ValidateLineRef: Using Line Top Y Offset (%i) as %s", answer, parmname); break; case LDREF_MIDDLE_OFFSETX: // Can this ever fail? side = P_GetPtrp(line, DMU_SIDEDEF0); if(!side) { XG_Dev("XL_ValidateLineRef: REFERENCE MISSING FRONT SIDEDEF!"); break; } answer = P_GetIntp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); XG_Dev("XL_ValidateLineRef: Using Line Middle X Offset (%i) as %s", answer, parmname); break; case LDREF_MIDDLE_OFFSETY: // Can this ever fail? side = P_GetPtrp(line, DMU_SIDEDEF0); if(!side) { XG_Dev("XL_ValidateLineRef: REFERENCE MISSING FRONT SIDEDEF!"); break; } answer = P_GetIntp(side, DMU_MIDDLE_MATERIAL_OFFSET_Y); XG_Dev("XL_ValidateLineRef: Using Line Middle Y Offset (%i) as %s", answer, parmname); break; case LDREF_BOTTOM_OFFSETX: // Can this ever fail? side = P_GetPtrp(line, DMU_SIDEDEF0); if(!side) { XG_Dev("XL_ValidateLineRef: REFERENCE MISSING FRONT SIDEDEF!"); break; } answer = P_GetIntp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); XG_Dev("XL_ValidateLineRef: Using Line Bottom X Offset (%i) as %s", answer, parmname); break; case LDREF_BOTTOM_OFFSETY: // Can this ever fail? side = P_GetPtrp(line, DMU_SIDEDEF0); if(!side) { XG_Dev("XL_ValidateLineRef: REFERENCE MISSING FRONT SIDEDEF!"); break; } answer = P_GetIntp(side, DMU_BOTTOM_MATERIAL_OFFSET_Y); XG_Dev("XL_ValidateLineRef: Using Line Bottom Y Offset (%i) as %s", answer, parmname); break; default: // Could be explicit, return the actual int value answer = reftype; break; } return answer; } /** * Executes the lines' function as defined by its class. */ void XL_DoFunction(linetype_t* info, linedef_t* line, int sideNum, mobj_t* actThing, int evType) { xgclass_t* xgClass = &xgClasses[info->lineClass]; XG_Dev("XL_DoFunction: Line %i, side %i, activator id %i, event %s", P_ToIndex(line), sideNum, actThing ? actThing->thinker.id : 0, EVTYPESTR(evType)); XG_Dev(" Executing class: %s (0x%X)...", xgClass->className, info->lineClass); // Does this class only work with certain events? if(xgClass->evTypeFlags > 0) { if(!(xgClass->evTypeFlags & evType)) { XG_Dev(" THIS CLASS DOES NOT SUPPORT %s EVENTS!", EVTYPESTR(evType)); return; } } // Does this class have an init function? if(xgClass->initFunc) xgClass->initFunc(line); // Does this class have a do function? if(xgClass->doFunc) { // Do we need to traverse? switch(xgClass->traverse) { case TRAV_NONE: // No need for traversal, call the doFunc xgClass->doFunc(line, true, line, info, actThing); break; case TRAV_LINES: // Traverse lines, executing doFunc for each XL_TraverseLines(line, info->iparm[xgClass->travRef], info->iparm[xgClass->travData], line, info, actThing, xgClass->doFunc); break; case TRAV_PLANES: // Traverse planes, executing doFunc for each case TRAV_SECTORS: XL_TraversePlanes(line, info->iparm[xgClass->travRef], info->iparm[xgClass->travData], line, info, xgClass->traverse == TRAV_SECTORS? true : false, actThing, xgClass->doFunc); break; } } } int C_DECL XLTrav_QuickActivate(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { xline_t* xline = P_ToXLine(line); if(xline->xg) { xline->xg->active = (context? true : false); xline->xg->timer = XLTIMER_STOPPED; // Stop timer. } } return true; // Continue iteration. } /** * @return @c true, if the line is active. */ int C_DECL XLTrav_CheckLine(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { xline_t* xline = P_ToXLine(line); if(!xline->xg) return false; // Stop checking! return (xline->xg->active == true) == (context? true : false); } return true; // Continue iteration. } /** * @param data If @c true, the line will receive a chain event if * inactive. * If @c false, the line will receive a chain event if * active. */ int C_DECL XLTrav_SmartActivate(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { xline_t* xline = P_ToXLine(line); if(xline->xg) { if((context? true : false) != xline->xg->active) XL_LineEvent(XLE_CHAIN, 0, line, 0, context2); } } return true; // Continue iteration. } // // XG Line Type Classes which don't require traversal // int C_DECL XL_DoChainSequence(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { xline_t* xline = P_ToXLine(line); if(xline->xg) { linetype_t* info = context2; xline->xg->chIdx = 1; // This is the first. // Start counting the first interval. xline->xg->chTimer = XG_RandomPercentFloat(info->fparm[1], info->fparm[0]); } } return true; } int C_DECL XL_DoDamage(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { linetype_t* info = context2; if(!activator) { /* if(evtype == XLE_FUNC) XG_Dev(" Sector Functions don't have activators! Use a Sector Chain instead."); else*/ XG_Dev(" No activator! Can't damage anything."); return false; } if(activator->health > info->iparm[2]) { // Iparms define the min and max damage to inflict. // The real amount is random. int i = XG_RandomInt(info->iparm[0], info->iparm[1]); if(i > 0) { P_DamageMobj(activator, 0, 0, i, false); } else if(i < 0 && activator->health < info->iparm[3]) { int origHealth = activator->health; // Don't go above a given level. activator->health = MIN_OF(activator->health-i, info->iparm[3]); // Need to signal an update? if(activator->player && activator->health != origHealth) { activator->player->health = activator->health; activator->player->update |= PSF_HEALTH; } } } return true; } int C_DECL XL_DoPower(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { player_t* player = 0; linetype_t* info = context2; int delta; if(activator) player = activator->player; if(!player) // Must be a player. { /* if(evtype == XLE_FUNC) XG_Dev(" Sector Functions don't have activators! Use a Sector Chain instead."); else*/ XG_Dev(" Activator MUST be a player..."); return false; } delta = XG_RandomInt(info->iparm[0], info->iparm[1]); if(delta > 0) { if(player->armorPoints + delta >= info->iparm[3]) delta = info->iparm[3] - player->armorPoints; } else { if(player->armorPoints + delta <= info->iparm[2]) delta = info->iparm[2] - player->armorPoints; } if(delta) { if(!player->armorType) P_PlayerSetArmorType(player, 1); P_PlayerGiveArmorBonus(player, delta); } return true; } int C_DECL XL_DoKey(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { int i; player_t* player = 0; linetype_t* info = context2; if(activator) player = activator->player; if(!player) // Must be a player. { /* if(evtype == XLE_FUNC) XG_Dev(" Sector Functions don't have activators! Use a Sector Chain instead."); else*/ XG_Dev(" Activator MUST be a player..."); return false; } for(i = 0; i < NUM_KEY_TYPES; ++i) { if(info->iparm[0] & (1 << i)) P_GiveKey(player, i); if(info->iparm[1] & (1 << i)) player->keys[i] = false; } return true; } int C_DECL XL_DoExplode(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(!activator) { /* if(evtype == XLE_FUNC) XG_Dev(" Sector Functions don't have activators! Use a Sector Chain instead."); else*/ XG_Dev(" No activator! Can't explode anything."); return false; } P_ExplodeMissile(activator); return true; } int C_DECL XL_DoCommand(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { linetype_t* info = context2; DD_Execute(true, info->sparm[0]); return true; } // // Following classes require traversal hence "Trav_" // int C_DECL XLTrav_ChangeLineType(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { linetype_t* info = context2; XL_SetLineType(line, info->iparm[2]); } return true; // Keep looking. } int C_DECL XLTrav_ChangeWallMaterial(linedef_t* line, boolean dummy, void* context, void *context2, mobj_t* activator) { linetype_t* info = context2; sidedef_t* side; blendmode_t blend = BM_NORMAL; byte rgba[4]; material_t* mat = NULL; if(!line) return true; // Continue iteration. // i2: sidenum // i3: top material (zero if no change) // i4: mid material (zero if no change, -1 to remove) // i5: bottom material (zero if no change) // i6: (true/false) set midtexture even if previously zero // i7: sdf_* flags // i8: mid blendmode // i9: top red // i10: top green // i11: top blue // i12: mid red // i13: mid green // i14: mid blue // i15: mid alpha // i16: bottom red // i17: bottom green // i18: bottom blue // Is there a sidedef? if(info->iparm[2]) { if(!P_GetPtrp(line, DMU_BACK_SECTOR)) return true; side = P_GetPtrp(line, DMU_SIDEDEF1); } else { if(!P_GetPtrp(line, DMU_FRONT_SECTOR)) return true; side = P_GetPtrp(line, DMU_SIDEDEF0); } XG_Dev("XLTrav_ChangeWallTexture: Line %i", P_ToIndex(line)); rgba[0] = info->iparm[9]; rgba[1] = info->iparm[10]; rgba[2] = info->iparm[11]; XL_ChangeMaterial(line, info->iparm[2], LWS_UPPER, P_ToPtr(DMU_MATERIAL, info->iparm[3]), blend, rgba, info->iparm[7]); rgba[0] = info->iparm[12]; rgba[1] = info->iparm[13]; rgba[2] = info->iparm[14]; rgba[3] = info->iparm[15]; if(info->iparm[4] && (P_GetPtrp(side, DMU_MIDDLE_MATERIAL) || info->iparm[6])) { if(!P_GetPtrp(line, DMU_BACK_SECTOR) && info->iparm[4] == -1) mat = NULL; else mat = P_ToPtr(DMU_MATERIAL, info->iparm[4]); } XL_ChangeMaterial(line, info->iparm[2], LWS_MID, mat, info->iparm[8], rgba, info->iparm[7]); rgba[0] = info->iparm[16]; rgba[1] = info->iparm[17]; rgba[2] = info->iparm[18]; XL_ChangeMaterial(line, info->iparm[2], LWS_LOWER, P_ToPtr(DMU_MATERIAL, info->iparm[5]), blend, rgba, info->iparm[7]); return true; } int C_DECL XLTrav_Activate(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) XL_LineEvent(XLE_CHAIN, 0, line, 0, activator); return true; // Keep looking. } int C_DECL XLTrav_LineCount(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { xline_t* xline = P_ToXLine(line); linetype_t* info = context2; if(xline->xg) { if(info->iparm[2]) xline->xg->info.actCount = info->iparm[3]; else xline->xg->info.actCount += info->iparm[3]; } } return true; } int C_DECL XLTrav_Music(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { int song = 0; int temp = 0; linetype_t* info = context2; if(info->iparm[2] == LREF_NONE) { // The old format, use ip0 explicitly. song = info->iparm[0]; } else // We might possibly have a data reference to evaluate. { if(info->iparm[2] == LREF_NONE) // (ip0) will be used to determine next map. { song = info->iparm[0]; } else if(line) { // Evaluate ip0 for a data reference. temp = XL_ValidateLineRef(line, info->iparm[0], context2, "Music ID"); if(!temp) XG_Dev("XLTrav_Music: Reference data not valid. Song not changed"); else song = temp; } } //// \fixme Add code to validate song id here. if(song) { XG_Dev("XLTrav_Music: Play Music ID (%i)%s", song, info->iparm[1]? " looped.":"."); S_StartMusicNum(song, info->iparm[1]); } return false; // Only do this once! } int C_DECL XLTrav_LineTeleport(linedef_t* newLine, boolean dummy, void* context, void* context2, mobj_t* mobj) { // Maximum units to move object to avoid hiccups. #define FUDGEFACTOR 10 int fudge = FUDGEFACTOR; int side = 0, stepDown; unsigned int an; mobj_t* flash; linedef_t* line = (linedef_t *) context; linetype_t* info = (linetype_t *) context2; vertex_t* newV1, *newV2, *oldV1, *oldV2; sector_t* newFrontSec, *newBackSec; float newX, newY, newZ, pos, s, c; float oldLineDelta[2], newLineDelta[2]; angle_t angle; // Don't teleport things marked noteleport! if(mobj->flags2 & MF2_NOTELEPORT) { XG_Dev("XLTrav_LineTeleport: Activator can't be teleported (THING is unteleportable)"); return false; // No point continuing... } if(!line) return true; // Continue iteration. // We shouldn't be trying to teleport to the same line if(newLine == line) { XG_Dev("XLTrav_LineTeleport: Target == Origin. Continuing search..."); return true; // Keep looking } // Retrieve a few properties to make this look neater. oldV1 = P_GetPtrp(line, DMU_VERTEX0); oldV2 = P_GetPtrp(line, DMU_VERTEX1); P_GetFloatpv(line, DMU_DXY, oldLineDelta); newV1 = P_GetPtrp(newLine, DMU_VERTEX0); newV2 = P_GetPtrp(newLine, DMU_VERTEX1); P_GetFloatpv(newLine, DMU_DXY, newLineDelta); newFrontSec = P_GetPtrp(newLine, DMU_FRONT_SECTOR); newBackSec = P_GetPtrp(newLine, DMU_BACK_SECTOR); // i2: 1 = Spawn Fog // i3: Sound = Sound to play // i4: 1 = reversed // i5: 1 = always telestomp XG_Dev("XLTrav_LineTeleport: %s, %s, %s", info->iparm[2]? "Spawn Flash":"No Flash", info->iparm[3]? "Play Sound":"Silent", info->iparm[4]? "Reversed":"Normal."); // Spawn flash at the old position? if(info->iparm[2]) { if((flash = P_SpawnMobj3fv(MT_TFOG, mobj->pos, mobj->angle + ANG180, 0))) { // Play a sound? if(info->iparm[3]) S_StartSound(info->iparm[3], flash); } } // Get the thing's position along the source linedef if(fabs(oldLineDelta[0]) > fabs(oldLineDelta[1])) pos = (mobj->pos[VX] - P_GetFloatp(oldV1, DMU_X)) / oldLineDelta[0]; else pos = (mobj->pos[VY] - P_GetFloatp(oldV1, DMU_Y)) / oldLineDelta[1]; // Get the angle between the two linedefs, for rotating orientation and // momentum. Rotate 180 degrees, and flip the position across the exit // linedef, if reversed. angle = (info->iparm[4] ? pos = 1 - pos, 0 : ANG180) + R_PointToAngle2(0, 0, newLineDelta[0], newLineDelta[1]) - R_PointToAngle2(0, 0, oldLineDelta[0], oldLineDelta[1]); // Interpolate position across the exit linedef. newX = P_GetFloatp(newV2, DMU_X) - (pos * newLineDelta[0]); newY = P_GetFloatp(newV2, DMU_Y) - (pos * newLineDelta[1]); // Sine, cosine of angle adjustment s = FIX2FLT(finesine[angle >> ANGLETOFINESHIFT]); c = FIX2FLT(finecosine[angle >> ANGLETOFINESHIFT]); // Whether walking towards first side of exit linedef steps down if(P_GetFloatp(newFrontSec, DMU_FLOOR_HEIGHT) < P_GetFloatp(newBackSec, DMU_FLOOR_HEIGHT)) stepDown = true; else stepDown = false; // Height of thing above ground. newZ = mobj->pos[VZ] - mobj->floorZ; /** * Side to exit the linedef on positionally. * * \note * This flag concerns exit position, not momentum. Due to potential for * round-off error, the thing can land on either the left or the right * side of the exit linedef, and steps must be taken to make sure it * does not end up on the wrong side. * * Exit momentum is always towards side 1 in a reversed teleporter, and * always towards side 0 otherwise. * * Exiting positionally on side 1 is always safe, as far as avoiding * oscillations and stuck-in-wall problems, but may not be optimum for * non-reversed teleporters. * * Exiting on side 0 can cause oscillations if momentum is towards side * 1, as it is with reversed teleporters. * * Exiting on side 1 slightly improves player viewing when going down a * step on a non-reversed teleporter. */ if(!info->iparm[4] || (mobj->player && stepDown)) side = 1; // Make sure we are on correct side of exit linedef. while(P_PointOnLinedefSide(newX, newY, newLine) != side && --fudge >= 0) { if(fabs(newLineDelta[0]) > fabs(newLineDelta[1])) newY -= FIX2FLT((newLineDelta[0] < 0) != side ? -1 : 1); else newX += FIX2FLT((newLineDelta[1] < 0) != side ? -1 : 1); } // Do the Teleport if(!P_TeleportMove(mobj, newX, newY, (info->iparm[5] > 0? true : false))) { XG_Dev("XLTrav_Teleport: Something went horribly wrong... aborting."); return false; } // Adjust z position to be same height above ground as before. Ground // level at the exit is measured as the higher of the two floor heights // at the exit linedef. if(stepDown) mobj->pos[VZ] = newZ + P_GetFloatp(newFrontSec, DMU_FLOOR_HEIGHT); else mobj->pos[VZ] = newZ + P_GetFloatp(newBackSec, DMU_FLOOR_HEIGHT); // Rotate mobj's orientation according to difference in linedef angles. mobj->angle += angle; // Update momentum of mobj crossing teleporter linedef? newX = mobj->mom[MX]; newY = mobj->mom[MY]; // Rotate mobj's momentum to come out of exit just like it entered. mobj->mom[MX] = (newX * c) - (newY * s); mobj->mom[MY] = (newY * c) + (newX * s); // Feet clipped? if(mobj->flags2 & MF2_FLOORCLIP) { mobj->floorClip = 0; if(mobj->pos[VZ] == P_GetFloatp(mobj->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mobj); if(tt->flags & TTF_FLOORCLIP) { mobj->floorClip = 10; } } } // Spawn flash at the new position? if(info->iparm[2]) { an = mobj->angle >> ANGLETOFINESHIFT; if((flash = P_SpawnMobj3f(MT_TFOG, mobj->pos[VX] + 24 * FIX2FLT(finecosine[an]), mobj->pos[VY] + 24 * FIX2FLT(finesine[an]), mobj->pos[VZ], mobj->angle + ANG180, 0))) { // Play a sound? if(info->iparm[3]) S_StartSound(info->iparm[3], flash); } } // Adjust the player's view, incase there has been a height change if(mobj->player) { mobj->player->viewZ = mobj->pos[VZ] + mobj->player->viewHeight; mobj->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; } return false; // Do this only once! #undef FUDGEFACTOR } boolean XL_ValidateMap(uint* map, int type) { boolean result; uint bMap = *map, episode; #if __JDOOM__ if(gameMode == commercial || gameMode == shareware) episode = 0; else episode = gameEpisode; #elif __JDOOM64__ episode = 0; #elif __JHERETIC__ episode = gameEpisode; #endif if(!(result = G_ValidateMap(&episode, map))) XG_Dev("XLTrav_LeaveMap: NOT A VALID MAP NUMBER %u, " "next map will be %u.", bMap, *map+1); return result; } int C_DECL XLTrav_LeaveMap(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { uint map = 0; int temp = 0; linetype_t* info = context2; boolean mapSpecified = false; // Is this a secret exit? if(info->iparm[0] > 0) { G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, true), 0, true); return false; } if(info->iparm[1] == LREF_NONE) { // (ip3) will be used to determine next map. if(info->iparm[3]) { map = info->iparm[3]-1; mapSpecified = XL_ValidateMap(&map, 0); } } else { // We might possibly have a data reference to evaluate. if(line) { temp = XL_ValidateLineRef(line,info->iparm[3], context2, "Map Number"); if(temp > 0) { map = temp-1; mapSpecified = XL_ValidateMap(&map, info->iparm[3]); } } if(!mapSpecified) XG_Dev("XLTrav_LeaveMap: Reference data not valid. " "Next map as normal"); } if(mapSpecified) { XG_Dev("XLTrav_LeaveMap: Next map set to %u", map+1); map = G_GetMapNumber(gameEpisode, map); } else { map = G_GetNextMap(gameEpisode, gameMap, false); } G_LeaveMap(map, 0, false); return false; // Only do this once! } int C_DECL XLTrav_DisableLine(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { xline_t* xline = P_ToXLine(line); if(xline->xg) { xline_t* origLine = P_ToXLine((linedef_t*) context); xline->xg->disabled = origLine->xg->active; } } return true; // Keep looking... } int C_DECL XLTrav_EnableLine(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { if(line) { xline_t* xline = P_ToXLine(line); if(xline->xg) { xline_t* origLine = P_ToXLine((linedef_t*) context); xline->xg->disabled = !origLine->xg->active; } } return true; // Keep looking... } /** * Checks if the given lines are active or inactive. * * @return @c true if all are in the specified state. */ boolean XL_CheckLineStatus(linedef_t* line, int reftype, int ref, int active, mobj_t* activator) { return XL_TraverseLines(line, reftype, ref, &active, 0, activator, XLTrav_CheckLine); } boolean XL_CheckMobjGone(thinker_t* th, void* context) { int thingtype = *(int*) context; mobj_t* mo = (mobj_t *) th; if(mo->type == thingtype && mo->health > 0) { // Not dead. XG_Dev("XL_CheckMobjGone: Thing type %i: Found mo id=%i, " "health=%i, pos=(%g,%g)", thingtype, mo->thinker.id, mo->health, mo->pos[VX], mo->pos[VY]); return false; // Stop iteration. } return true; // Continue iteration. } void XL_SwapSwitchTextures(linedef_t* line, int snum) { if(line) { sidedef_t* side = P_GetPtrp(line, snum? DMU_SIDEDEF1 : DMU_SIDEDEF0); if(side && P_ToggleSwitch(side, SFX_NONE, true, 0)) XG_Dev("XL_SwapSwitchTextures: Line %i, side %i", P_ToIndex(line), P_ToIndex(side)); } } /** * Changes material of the given line. */ void XL_ChangeMaterial(linedef_t* line, int sidenum, int section, material_t* mat, blendmode_t blendmode, byte rgba[4], int flags) { int i; int currentFlags; sidedef_t* side = P_GetPtrp(line, sidenum? DMU_SIDEDEF1:DMU_SIDEDEF0); if(!side) return; // Clamping is not necessary since the rgba array has already a byte type. XG_Dev("XL_ChangeMaterial: Line %i, side %i, section %i, material %i", P_ToIndex(line), sidenum, section, P_ToIndex(mat)); XG_Dev(" red %i, green %i, blue %i, alpha %i, blendmode %i", rgba[0], rgba[1], rgba[2], rgba[3], blendmode); // Which wall section are we working on? if(section == LWS_MID) { // Are we removing the middle texture? if(mat == (material_t*) -1) P_SetPtrp(side, DMU_MIDDLE_MATERIAL, NULL); else if(mat) P_SetPtrp(side, DMU_MIDDLE_MATERIAL, mat); // Are we changing the blendmode? if(blendmode) P_SetIntp(side, DMU_MIDDLE_BLENDMODE, blendmode); // Are we changing the surface color? for(i = 0; i < 4; ++i) if(rgba[i]) P_SetFloatp(side, TO_DMU_MIDDLE_COLOR(i), rgba[i] / 255.f); } else if(section == LWS_UPPER) { if(mat) P_SetPtrp(side, DMU_TOP_MATERIAL, mat); for(i = 0; i < 3; ++i) if(rgba[i]) P_SetFloatp(side, TO_DMU_TOP_COLOR(i), rgba[i] / 255.f); } else if(section == LWS_LOWER) { if(mat) P_SetPtrp(side, DMU_BOTTOM_MATERIAL, mat); for(i = 0; i < 3; ++i) if(rgba[i]) P_SetFloatp(side, TO_DMU_BOTTOM_COLOR(i), rgba[i] / 255.f); } // Adjust the side's flags currentFlags = P_GetIntp(side, DMU_FLAGS); currentFlags |= flags; P_SetIntp(side, DMU_FLAGS, currentFlags); } void XL_Message(mobj_t* act, char* msg, boolean global) { int i; player_t* pl; if(!msg || !msg[0]) return; if(global) { XG_Dev("XL_Message: GLOBAL '%s'", msg); // Send to all players in the game. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) P_SetMessage(players + i, msg, false); return; } if(act->player) { pl = act->player; } else if((act->flags & MF_MISSILE) && act->target && act->target->player) { // Originator of the missile. pl = act->target->player; } else { // We don't know whom to send the message. XG_Dev("XL_Message: '%s'", msg); XG_Dev(" NO DESTINATION, MESSAGE DISCARDED"); return; } P_SetMessage(pl, msg, false); } /** * XL_ActivateLine */ void XL_ActivateLine(boolean activating, linetype_t* info, linedef_t* line, int sidenum, mobj_t* data, int evtype) { byte rgba[4] = { 0, 0, 0, 0 }; xgline_t* xg; sector_t* frontsector; mobj_t* activator_thing = (mobj_t *) data; ddmobj_base_t* soundOrg = 0; xg = P_ToXLine(line)->xg; XG_Dev("XL_ActivateLine: %s line %i, side %i, type %i", activating ? "Activating" : "Deactivating", P_ToIndex(line), sidenum, P_ToXLine(line)->special); if(xg->disabled) { XG_Dev(" LINE DISABLED, ABORTING"); return; // The line is disabled. } if((activating && xg->active) || (!activating && !xg->active)) { XG_Dev(" Line is ALREADY %s, ABORTING", activating ? "ACTIVE" : "INACTIVE"); return; // Do nothing (can't activate if already active!). } // Activation should happen on the front side. frontsector = P_GetPtrp(line, DMU_FRONT_SECTOR); if(frontsector) soundOrg = P_GetPtrp(frontsector, DMU_SOUND_ORIGIN); // Let the line know who's activating it. xg->activator = data; // Process (de)activation chains. Chains always pass as an activation // method, but the other requirements of the chained type must be met. if(activating && info->actChain) { XG_Dev(" Line has Act Chain (type %i) - It will be processed first...",info->actChain); XL_LineEvent(XLE_CHAIN, info->actChain, line, sidenum, data); } else if(!activating && info->deactChain) { XG_Dev(" Line has Deact Chain (type %i) - It will be processed first...",info->deactChain); XL_LineEvent(XLE_CHAIN, info->deactChain, line, sidenum, data); } // Automatically swap any SW* textures. if(xg->active != activating) XL_SwapSwitchTextures(line, sidenum); // Change the state of the line. xg->active = activating; xg->timer = 0; // Reset timer. // Activate lines with a matching tag with Group Activation. if((activating && (info->flags2 & LTF2_GROUP_ACT)) || (!activating && (info->flags2 & LTF2_GROUP_DEACT))) { XL_TraverseLines(line, LREF_LINE_TAGGED, true, &activating, 0, activator_thing, XLTrav_SmartActivate); } // For lines flagged Multiple, quick-(de)activate other lines that have // the same line tag. if(info->flags2 & LTF2_MULTIPLE) { XL_TraverseLines(line, LREF_LINE_TAGGED, true, &activating, 0, activator_thing, XLTrav_QuickActivate); } // Should we apply the function of the line? Functions are defined by // the class of the line type. if((activating && (info->flags2 & LTF2_WHEN_ACTIVATED)) || (!activating && (info->flags2 & LTF2_WHEN_DEACTIVATED))) { if(!(info->flags2 & LTF2_WHEN_LAST) || info->actCount == 1) XL_DoFunction(info, line, sidenum, activator_thing, evtype); else XG_Dev(" Line %i FUNCTION TEST FAILED", P_ToIndex(line)); } else { if(activating) XG_Dev(" Line %i has no activation function", P_ToIndex(line)); else { XG_Dev(" Line %i has no deactivation function", P_ToIndex(line)); } } // Now do any secondary actions that should happen AFTER // the function of the line (regardless if one was applied or not) if(activating) { XL_Message(activator_thing, info->actMsg, (info->flags2 & LTF2_GLOBAL_A_MSG) != 0); if(info->actSound) S_StartSound(info->actSound, (mobj_t *) soundOrg); // Change the texture of the line if asked to. if(info->wallSection && info->actMaterial) XL_ChangeMaterial(line, sidenum, info->wallSection, P_ToPtr(DMU_MATERIAL, info->actMaterial), BM_NORMAL, rgba, 0); // Change the class of the line if asked to if(info->actLineType) XL_SetLineType(line, info->actLineType); } else { XL_Message(activator_thing, info->deactMsg, (info->flags2 & LTF2_GLOBAL_D_MSG) != 0); if(info->deactSound) S_StartSound(info->deactSound, (mobj_t *) soundOrg); // Change the texture of the line if asked to. if(info->wallSection && info->deactMaterial) XL_ChangeMaterial(line, sidenum, info->wallSection, P_ToPtr(DMU_MATERIAL, info->deactMaterial), BM_NORMAL, rgba, 0); // Change the class of the line if asked to. if(info->deactLineType) XL_SetLineType(line, info->deactLineType); } } /** * XL_CheckKeys */ boolean XL_CheckKeys(mobj_t* mo, int flags2, boolean doMsg, boolean doSfx) { player_t* act = mo->player; #if __JDOOM__ || __JDOOM64__ int num = 6; int* keys = (int *) act->keys; int badsound = SFX_OOF; #elif __JHERETIC__ int num = 3; boolean* keys = act->keys; int badsound = SFX_PLROOF; #elif __JSTRIFE__ //// \fixme FIXME!!! int num = 3; int* keys = (int *) act->keys; int badsound = SFX_NONE; #endif int i; for(i = 0; i < num; ++i) { if((flags2 & LTF2_KEY(i)) && !keys[i]) { // This key is missing! // Show a message? if(doMsg) { sprintf(msgbuf, "YOU NEED A %s.", GET_TXT(TXT_KEY1 + i)); XL_Message(mo, msgbuf, false); } // Play a sound? if(doSfx) S_ConsoleSound(badsound, mo, act - players); return false; } } return true; } /** * Decides if the event leads to (de)activation. * Line must be extended. * Most conditions use AND (act method, game mode and difficult use OR). * * @return @c true, iff the event is processed. */ int XL_LineEvent(int evtype, int linetype, linedef_t* line, int sidenum, void* data) { int i; xline_t* xline; xgline_t* xg; linetype_t* info; boolean active; mobj_t* activator_thing = (mobj_t *) data; player_t* activator = 0; boolean anyTrigger = false; // Clients rely on the server, they don't do XG themselves. if(IS_CLIENT) return false; xline = P_ToXLine(line); xg = xline->xg; info = &xg->info; active = xg->active; if(activator_thing) activator = activator_thing->player; #if __JDOOM__ || __JDOOM64__ // BOOM intergration if((xline->flags & ML_ALLTRIGGER) && !(info->flags2 & LTF2_OVERRIDE_ANY)) anyTrigger = true; #endif XG_Dev("XL_LineEvent: %s line %i, side %i (chained type %i)%s", EVTYPESTR(evtype), P_ToIndex(line), sidenum, linetype, anyTrigger? " ANY Trigger":""); if(xg->disabled) { XG_Dev(" LINE IS DISABLED, ABORTING EVENT"); return false; // The line is disabled. } // This is a chained event. if(linetype) { if(!XL_GetType(linetype)) return false; info = &typebuffer; } // Process chained event first. It takes precedence. if(info->evChain) { if(XL_LineEvent(evtype, info->evChain, line, sidenum, data)) { XG_Dev(" Event %s, line %i, side %i OVERRIDDEN BY EVENT CHAIN %i", EVTYPESTR(evtype), P_ToIndex(line), sidenum, info->evChain); return true; } } // Check restrictions and conditions that will prevent processing // the event. if((active && info->actType == LTACT_COUNTED_OFF) || (!active && info->actType == LTACT_COUNTED_ON)) { // Can't be processed at this time. XG_Dev(" Line %i: Active=%i, type=%i ABORTING EVENT", P_ToIndex(line), active, info->actType); return false; } // Check the type of the event vs. the requirements of the line. if(evtype == XLE_CHAIN || evtype == XLE_FUNC) goto type_passes; if(evtype == XLE_USE && ((((info->flags & LTF_PLAYER_USE_A) && activator && !active) || ((info->flags & LTF_OTHER_USE_A) && !activator && !active) || ((info->flags & LTF_PLAYER_USE_D) && activator && active) || ((info->flags & LTF_OTHER_USE_D) && !activator && active)) || anyTrigger)) goto type_passes; if(evtype == XLE_SHOOT && ((((info->flags & LTF_PLAYER_SHOOT_A) && activator && !active) || ((info->flags & LTF_OTHER_SHOOT_A) && !activator && !active) || ((info->flags & LTF_PLAYER_SHOOT_D) && activator && active) || ((info->flags & LTF_OTHER_SHOOT_D) && !activator && active)) || anyTrigger)) goto type_passes; if(evtype == XLE_CROSS && ((((info->flags & LTF_PLAYER_CROSS_A) && activator && !active) || ((info->flags & LTF_MONSTER_CROSS_A) && (activator_thing->flags & MF_COUNTKILL) && !active) || ((info->flags & LTF_MISSILE_CROSS_A) && (activator_thing->flags & MF_MISSILE) && !active) || ((info->flags & LTF_ANY_CROSS_A) && !active) || ((info->flags & LTF_PLAYER_CROSS_D) && activator && active) || ((info->flags & LTF_MONSTER_CROSS_D) && (activator_thing->flags & MF_COUNTKILL) && active) || ((info->flags & LTF_MISSILE_CROSS_D) && (activator_thing->flags & MF_MISSILE) && active) || ((info->flags & LTF_ANY_CROSS_D) && active)) || anyTrigger)) goto type_passes; if(evtype == XLE_HIT && ((((info->flags & LTF_PLAYER_HIT_A) && activator && !active) || ((info->flags & LTF_OTHER_HIT_A) && !activator && !active) || ((info->flags & LTF_MONSTER_HIT_A) && (activator_thing->flags & MF_COUNTKILL) && !active) || ((info->flags & LTF_MISSILE_HIT_A) && (activator_thing->flags & MF_MISSILE) && !active) || ((info->flags & LTF_ANY_HIT_A) && !active) || ((info->flags & LTF_PLAYER_HIT_D) && activator && active) || ((info->flags & LTF_OTHER_HIT_D) && !activator && active) || ((info->flags & LTF_MONSTER_HIT_D) && (activator_thing->flags & MF_COUNTKILL) && active) || ((info->flags & LTF_MISSILE_HIT_D) && (activator_thing->flags & MF_MISSILE) && active) || ((info->flags & LTF_ANY_HIT_D) && active)) || anyTrigger)) goto type_passes; if(evtype == XLE_TICKER && (((info->flags & LTF_TICKER_A) && !active) || ((info->flags & LTF_TICKER_D) && active))) goto type_passes; // Type doesn't pass, sorry. XG_Dev(" Line %i: ACT REQUIREMENTS NOT FULFILLED, ABORTING EVENT", P_ToIndex(line)); return false; type_passes: if(info->flags & LTF_NO_OTHER_USE_SECRET) { // Non-players can't use this line if line is flagged secret. if(evtype == XLE_USE && !activator && (xline->flags & ML_SECRET)) { XG_Dev(" Line %i: ABORTING EVENT due to no_other_use_secret", P_ToIndex(line)); return false; } } if(info->flags & LTF_MOBJ_GONE) { if(!DD_IterateThinkers(P_MobjThinker, XL_CheckMobjGone, &info->aparm[9])) return false; } if(info->flags & LTF_ACTIVATOR_TYPE) { // Check the activator's type. if(!activator_thing || activator_thing->type != info->aparm[9]) { XG_Dev(" Line %i: ABORTING EVENT due to activator type", P_ToIndex(line)); return false; } } if((evtype == XLE_USE || evtype == XLE_SHOOT || evtype == XLE_CROSS) && !(info->flags2 & LTF2_TWOSIDED)) { // Only allow (de)activation from the front side. if(sidenum != 0) { XG_Dev(" Line %i: ABORTING EVENT due to line side test", P_ToIndex(line)); return false; } } // Check counting. if(!info->actCount) { XG_Dev(" Line %i: ABORTING EVENT due to Count = 0", P_ToIndex(line)); return false; } // More requirements. if((info->flags2 & LTF2_HEALTH_ABOVE) && activator_thing->health <= info->aparm[0]) return false; if((info->flags2 & LTF2_HEALTH_BELOW) && activator_thing->health >= info->aparm[1]) return false; if((info->flags2 & LTF2_POWER_ABOVE) && (!activator || activator->armorPoints <= info->aparm[2])) return false; if((info->flags2 & LTF2_POWER_BELOW) && (!activator || activator->armorPoints >= info->aparm[3])) return false; if(info->flags2 & LTF2_LINE_ACTIVE) if(!XL_CheckLineStatus(line, info->aparm[4], info->aparm[5], true, activator_thing)) { XG_Dev(" Line %i: ABORTING EVENT due to line_active test", P_ToIndex(line)); return false; } if(info->flags2 & LTF2_LINE_INACTIVE) if(!XL_CheckLineStatus(line, info->aparm[6], info->aparm[7], false, activator_thing)) { XG_Dev(" Line %i: ABORTING EVENT due to line_inactive test", P_ToIndex(line)); return false; } // Check game mode. if(IS_NETGAME) { if(!(info->flags2 & (LTF2_COOPERATIVE | LTF2_DEATHMATCH))) { XG_Dev(" Line %i: ABORTING EVENT due to netgame mode", P_ToIndex(line)); return false; } } else { if(!(info->flags2 & LTF2_SINGLEPLAYER)) { XG_Dev(" Line %i: ABORTING EVENT due to game mode (1p)", P_ToIndex(line)); return false; } } // Check skill level. if(gameSkill < 1) i = 1; else if(gameSkill > 3) i = 4; else i = 1 << (gameSkill - 1); i <<= LTF2_SKILL_SHIFT; if(!(info->flags2 & i)) { XG_Dev(" Line %i: ABORTING EVENT due to skill level (%i)", P_ToIndex(line), gameSkill); return false; } // Check activator color. if(info->flags2 & LTF2_COLOR) { if(!activator) return false; if(cfg.playerColor[activator - players] != info->aparm[8]) { XG_Dev(" Line %i: ABORTING EVENT due to activator color (%i)", P_ToIndex(line), cfg.playerColor[activator-players]); return false; } } // Keys require that the activator is a player. if(info-> flags2 & (LTF2_KEY1 | LTF2_KEY2 | LTF2_KEY3 | LTF2_KEY4 | LTF2_KEY5 | LTF2_KEY6)) { // Check keys. if(!activator) { XG_Dev(" Line %i: ABORTING EVENT due to missing key " "(no activator)", P_ToIndex(line)); return false; } // Check that all the flagged keys are present. if(!XL_CheckKeys(activator_thing, info->flags2, true, (evtype == XLE_USE? true : false))) { XG_Dev(" Line %i: ABORTING EVENT due to missing key", P_ToIndex(line)); return false; // Keys missing! } } // All tests passed, use this event. if(info->actCount > 0 && evtype != XLE_CHAIN && evtype != XLE_FUNC) { // Decrement counter. info->actCount--; XG_Dev(" Line %i: Decrementing counter, now %i", P_ToIndex(line), info->actCount); } XL_ActivateLine(!active, info, line, sidenum, activator_thing, evtype); return true; } /** * @return @c true, if the event was processed. */ int XL_CrossLine(linedef_t* line, int sidenum, mobj_t* thing) { if(!line || !P_ToXLine(line)->xg) return false; return XL_LineEvent(XLE_CROSS, 0, line, sidenum, thing); } /** * @return @c true, if the event was processed. */ int XL_UseLine(linedef_t* line, int sidenum, mobj_t* thing) { if(!line || !P_ToXLine(line)->xg) return false; return XL_LineEvent(XLE_USE, 0, line, sidenum, thing); } /** * @return @c true, if the event was processed. */ int XL_ShootLine(linedef_t* line, int sidenum, mobj_t* thing) { if(!line || !P_ToXLine(line)->xg) return false; return XL_LineEvent(XLE_SHOOT, 0, line, sidenum, thing); } int XL_HitLine(linedef_t *line, int sidenum, mobj_t *thing) { if(!line || !P_ToXLine(line)->xg) return false; return XL_LineEvent(XLE_HIT, 0, line, sidenum, thing); } void XL_DoChain(linedef_t* line, int chain, boolean activating, mobj_t* actThing) { linedef_t* dummyLine; xline_t* xdummyLine; // We'll use a dummy line for the chain. dummyLine = P_AllocDummyLine(); xdummyLine = P_ToXLine(dummyLine); xdummyLine->xg = Z_Malloc(sizeof(xgline_t), PU_MAP, 0); XG_Dev("XL_DoChain: Line %i, chained type %i", P_ToIndex(line), chain); XG_Dev(" (dummy line will show up as %i)", P_ToIndex(dummyLine)); // Copy all properties to the dummy P_CopyLine(dummyLine, line); P_SetPtrp(dummyLine, DMU_SIDEDEF0, NULL); P_SetPtrp(dummyLine, DMU_SIDEDEF1, NULL); xdummyLine->xg->active = !activating; // Make the chain event XL_LineEvent(XLE_CHAIN, chain, dummyLine, 0, actThing); // Free the dummy Z_Free(xdummyLine->xg); P_FreeDummyLine(dummyLine); } /** * XG lines get to think. */ void XL_Thinker(xlthinker_t* xl) { float levtime; linedef_t* line = xl->line; xline_t* xline; xgline_t* xg; linetype_t* info; // Clients rely on the server, they don't do XG themselves. if(IS_CLIENT) return; if(!xl->line) return; xline = P_ToXLine(line); if(!xline) return; // Not an xline? Most perculiar... xg = xline->xg; if(!xg) return; // Not an extended line. if(xg->disabled) return; // Disabled, do nothing. info = &xg->info; levtime = TIC2FLT(mapTime); // Increment time. if(xg->timer >= 0) { xg->timer++; xg->tickerTimer++; } // Activation by ticker. if((info->tickerEnd <= 0 || (levtime >= info->tickerStart && levtime <= info->tickerEnd)) && xg->tickerTimer > info->tickerInterval) { if(info->flags & LTF_TICKER) { xg->tickerTimer = 0; XL_LineEvent(XLE_TICKER, 0, line, 0, &dummyThing); } // How about some forced functions? if((((info->flags2 & LTF2_WHEN_ACTIVE) && xg->active) || ((info->flags2 & LTF2_WHEN_INACTIVE) && !xg->active)) && (!(info->flags2 & LTF2_WHEN_LAST) || info->actCount == 1)) { XL_DoFunction(info, line, 0, xg->activator, XLE_FORCED); } } // Only process active chain sequences. if(xg->active && info->lineClass == LTC_CHAIN_SEQUENCE) { xg->chTimer -= TIC2FLT(1); // idata = current pos // fdata = count down seconds // i1..i19: line types // f0: interval randomness (100 means real interval can be 0%..200%). // f1..f19: intervals (seconds) // If the counter goes to zero, it's time to execute the chain. if(xg->chTimer < 0) { XG_Dev("XL_ChainSequenceThink: Line %i, executing...", P_ToIndex(line)); // Are there any more chains? if(xg->chIdx < DDLT_MAX_PARAMS && info->iparm[xg->chIdx]) { // Only send activation events. XL_DoChain(line, info->iparm[xg->chIdx], true, xg->activator); // Advance to the next one. xg->chIdx++; // Are we out of chains? if((xg->chIdx == DDLT_MAX_PARAMS || !info->iparm[xg->chIdx]) && (info->iparm[0] & CHSF_LOOP)) { // Loop back to beginning. xg->chIdx = 1; } // If there are more chains, get the next interval. if(xg->chIdx < DDLT_MAX_PARAMS && info->iparm[xg->chIdx]) { // Start counting it down. xg->chTimer = XG_RandomPercentFloat(info->fparm[xg->chIdx], info->fparm[0]); } } else if(info->iparm[0] & CHSF_DEACTIVATE_WHEN_DONE) { // The sequence has been completed. XL_ActivateLine(false, info, line, 0, xg->activator, XLE_CHAIN); } } } // Check for automatical (de)activation. if(((info->actType == LTACT_COUNTED_OFF || info->actType == LTACT_FLIP_COUNTED_OFF) && xg->active) || ((info->actType == LTACT_COUNTED_ON || info->actType == LTACT_FLIP_COUNTED_ON) && !xg->active)) { if(info->actTime >= 0 && xg->timer > FLT2TIC(info->actTime)) { XG_Dev("XL_Think: Line %i, timed to go %s", P_ToIndex(line), xg->active ? "INACTIVE" : "ACTIVE"); // Swap line state without any checks. XL_ActivateLine(!xg->active, info, line, 0, &dummyThing, XLE_AUTO); } } if(info->materialMoveSpeed) { // The texture should be moved. Calculate the offsets. float current[2]; // The current offset. sidedef_t* side; float spd = info->materialMoveSpeed; float offset[2]; angle_t ang = ((angle_t) (ANGLE_MAX * (info->materialMoveAngle / 360))) >> ANGLETOFINESHIFT; offset[VX] = -(FIX2FLT(finecosine[ang]) * spd); offset[VY] = FIX2FLT(finesine[ang]) * spd; /** * Apply to both sides of the line. * These are group offsets. All surfaces on a given side are moved * using the same texmove speed/angle. * * \todo Implement per-surface texture movement also which would * be added to each independantly. */ // Front side. side = P_GetPtrp(line, DMU_SIDEDEF0); if(side) { P_GetFloatpv(side, DMU_TOP_MATERIAL_OFFSET_XY, current); current[VX] += offset[VX]; current[VY] += offset[VY]; P_SetFloatpv(side, DMU_TOP_MATERIAL_OFFSET_XY, current); P_GetFloatpv(side, DMU_MIDDLE_MATERIAL_OFFSET_XY, current); current[VX] += offset[VX]; current[VY] += offset[VY]; P_SetFloatpv(side, DMU_MIDDLE_MATERIAL_OFFSET_XY, current); P_GetFloatpv(side, DMU_BOTTOM_MATERIAL_OFFSET_XY, current); current[VX] += offset[VX]; current[VY] += offset[VY]; P_SetFloatpv(side, DMU_BOTTOM_MATERIAL_OFFSET_XY, current); } // Back side. side = P_GetPtrp(line, DMU_SIDEDEF1); if(side) { P_GetFloatpv(side, DMU_TOP_MATERIAL_OFFSET_XY, current); current[VX] += offset[VX]; current[VY] += offset[VY]; P_SetFloatpv(side, DMU_TOP_MATERIAL_OFFSET_XY, current); P_GetFloatpv(side, DMU_MIDDLE_MATERIAL_OFFSET_XY, current); current[VX] += offset[VX]; current[VY] += offset[VY]; P_SetFloatpv(side, DMU_MIDDLE_MATERIAL_OFFSET_XY, current); P_GetFloatpv(side, DMU_BOTTOM_MATERIAL_OFFSET_XY, current); current[VX] += offset[VX]; current[VY] += offset[VY]; P_SetFloatpv(side, DMU_BOTTOM_MATERIAL_OFFSET_XY, current); } } } /** * During update, definitions are re-read, so the pointers need to be * updated. However, this is a bit messy operation, prone to errors. * Instead, we just disable XG... */ void XL_Update(void) { uint i; xline_t* xline; // It's all PU_MAP memory, so we can just lose it. for(i = 0; i < numlines; ++i) { xline = P_GetXLine(i); if(xline->xg) { xline->xg = NULL; xline->special = 0; } } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/rend_automap.c0000644000175000017500000013545411357170242023463 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_automap.c : Automap drawing. * * Code herein is considered a friend of automap_t. Consequently this means * that it need not negotiate the automap manager any may access automaps * directly. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "am_map.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_tick.h" #include "r_common.h" #if __JDOOM64__ # include "p_inventory.h" #endif #include "rend_automap.h" // MACROS ------------------------------------------------------------------ #define AM_LINE_WIDTH (1.25f) // TYPES ------------------------------------------------------------------- typedef struct { int scissorState[5]; // DGL Display lists. DGLuint lists[NUM_MAP_OBJECTLISTS]; // Each list contains one or more of given type of automap obj. boolean constructMap; // @c true = force a rebuild of all lists. } rautomap_data_t; typedef struct { player_t* plr; const automap_t* map; const automapcfg_t* cfg; // The type of object we want to draw. If @c -1, draw only line specials. int objType; boolean addToLists; } rendwallseg_params_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean freezeMapRLs = false; // if -1 no background image will be drawn. #if __JDOOM__ || __JDOOM64__ static int autopageLumpNum = -1; #elif __JHERETIC__ static int autopageLumpNum = 1; #else static int autopageLumpNum = 1; #endif dpatch_t markerPatches[10]; // Numbers used for marking by the automap (lump indices). // PRIVATE DATA DEFINITIONS ------------------------------------------------ static rautomap_data_t rautomaps[MAXPLAYERS]; #if __JDOOM__ || __JDOOM64__ static int their_colors[] = { GREENS, GRAYS, BROWNS, REDS }; #elif __JHERETIC__ static int their_colors[] = { KEY3_COLOR, KEY2_COLOR, BLOODRED, KEY1_COLOR }; #else static int their_colors[] = { AM_PLR1_COLOR, AM_PLR2_COLOR, AM_PLR3_COLOR, AM_PLR4_COLOR, AM_PLR5_COLOR, AM_PLR6_COLOR, AM_PLR7_COLOR, AM_PLR8_COLOR }; #endif static int numTexUnits; static boolean envModAdd; // TexEnv: modulate and add is available. static DGLuint amMaskTexture = 0; // Used to mask the map primitives. // CODE -------------------------------------------------------------------- static void deleteMapLists(rautomap_data_t* rmap) { uint i; for(i = 0; i < NUM_MAP_OBJECTLISTS; ++i) { if(rmap->lists[i]) DGL_DeleteLists(rmap->lists[i], 1); rmap->lists[i] = 0; } } void Rend_AutomapInit(void) { // Does the graphics library support multitexturing? numTexUnits = DD_GetInteger(DD_MAX_TEXTURE_UNITS); envModAdd = (DGL_GetInteger(DGL_MODULATE_ADD_COMBINE)? true : false); memset(rautomaps, 0, sizeof(rautomaps)); } /** * Load any resources needed for drawing the automap. * Called during startup (post init) and after a renderer restart. */ void Rend_AutomapLoadData(void) { #if !__JDOOM64__ int i; char namebuf[9]; #endif if(IS_DEDICATED) return; // Nothing to do. #if !__JDOOM64__ // Load the marker patches. for(i = 0; i < 10; ++i) { MARKERPATCHES; // Check the macros eg: "sprintf(namebuf, "AMMNUM%d", i)" for jDoom R_CachePatch(&markerPatches[i], namebuf); } #endif if(autopageLumpNum != -1) autopageLumpNum = W_CheckNumForName("AUTOPAGE"); if(numTexUnits > 1) { // Great, we can replicate the map fade out effect using multitexture, // load the mask texture. if(!amMaskTexture && !Get(DD_NOVIDEO)) { amMaskTexture = GL_NewTextureWithParams3(DGL_LUMINANCE, 256, 256, W_CacheLumpName("mapmask", PU_CACHE), 0x8, DGL_NEAREST, DGL_LINEAR, 0 /*no anisotropy*/, DGL_REPEAT, DGL_REPEAT); } } } /** * Unload any resources needed for drawing the automap. * Called during shutdown and before a renderer restart. */ void Rend_AutomapUnloadData(void) { int i; if(Get(DD_NOVIDEO) || IS_DEDICATED) return; // Nothing to do. // Destroy all display lists. for(i = 0; i < MAXPLAYERS; ++i) { rautomap_data_t* rmap = &rautomaps[i]; deleteMapLists(rmap); rmap->constructMap = true; } for(i = 0; i < NUM_VECTOR_GRAPHS; ++i) { vectorgrap_t* vgraph = AM_GetVectorGraph(i); if(vgraph->dlist) DGL_DeleteLists(vgraph->dlist, 1); vgraph->dlist = 0; } if(amMaskTexture) DGL_DeleteTextures(1, (DGLuint*) &amMaskTexture); amMaskTexture = 0; } /** * Called immediately after map load. */ void Rend_AutomapInitForMap(void) { uint i; if(Get(DD_NOVIDEO) || IS_DEDICATED) return; // Nothing to do. for(i = 0; i < MAXPLAYERS; ++i) { rautomap_data_t* rmap = &rautomaps[i]; deleteMapLists(rmap); rmap->constructMap = true; } } /** * Draws the given line including any optional extras. */ static void rendLine2(const automap_t* map, const automapcfg_t* mcfg, float x1, float y1, float x2, float y2, const float color[4], glowtype_t glowType, float glowAlpha, float glowWidth, boolean glowOnly, boolean scaleGlowWithView, boolean caps, blendmode_t blend, boolean drawNormal, boolean addToLists) { float a[2], b[2]; float length, dx, dy; float normal[2], unit[2]; // Scale into map, screen space units. a[VX] = x1; a[VY] = y1; b[VX] = x2; b[VY] = y2; dx = b[VX] - a[VX]; dy = b[VY] - a[VY]; length = sqrt(dx * dx + dy * dy); if(length <= 0) return; unit[VX] = dx / length; unit[VY] = dy / length; normal[VX] = unit[VY]; normal[VY] = -unit[VX]; // Is this a glowing line? if(glowType != NO_GLOW) { int tex; float thickness; // Scale line thickness relative to zoom level? if(scaleGlowWithView) thickness = mcfg->lineGlowScale * 2.5f + 3; else thickness = glowWidth; tex = Get(DD_DYNLIGHT_TEXTURE); if(caps) { // Draw a "cap" at the start of the line. float v1[2], v2[2], v3[2], v4[2]; v1[VX] = a[VX] - unit[VX] * thickness + normal[VX] * thickness; v1[VY] = a[VY] - unit[VY] * thickness + normal[VY] * thickness; v2[VX] = a[VX] + normal[VX] * thickness; v2[VY] = a[VY] + normal[VY] * thickness; v3[VX] = a[VX] - normal[VX] * thickness; v3[VY] = a[VY] - normal[VY] * thickness; v4[VX] = a[VX] - unit[VX] * thickness - normal[VX] * thickness; v4[VY] = a[VY] - unit[VY] * thickness - normal[VY] * thickness; if(!addToLists) { DGL_Bind(tex); DGL_Color4f(color[0], color[1], color[2], glowAlpha * Automap_GetOpacity(map)); DGL_BlendMode(blend); } DGL_Begin(DGL_QUADS); // V1 DGL_TexCoord2f(0, 0, 0); DGL_TexCoord2f(1, v1[VX], v1[VY]); DGL_Vertex2f(v1[VX], v1[VY]); // V2 DGL_TexCoord2f(0, .5f, 0); DGL_TexCoord2f(1, v2[VX], v2[VY]); DGL_Vertex2f(v2[VX], v2[VY]); // V3 DGL_TexCoord2f(0, .5f, 1); DGL_TexCoord2f(1, v3[VX], v3[VY]); DGL_Vertex2f(v3[VX], v3[VY]); // V4 DGL_TexCoord2f(0, 0, 1); DGL_TexCoord2f(1, v4[VX], v4[VY]); DGL_Vertex2f(v4[VX], v4[VY]); DGL_End(); if(!addToLists) DGL_BlendMode(BM_NORMAL); } // The middle part of the line. switch(glowType) { case TWOSIDED_GLOW: { float v1[2], v2[2], v3[2], v4[2]; v1[VX] = a[VX] + normal[VX] * thickness; v1[VY] = a[VY] + normal[VY] * thickness; v2[VX] = b[VX] + normal[VX] * thickness; v2[VY] = b[VY] + normal[VY] * thickness; v3[VX] = b[VX] - normal[VX] * thickness; v3[VY] = b[VY] - normal[VY] * thickness; v4[VX] = a[VX] - normal[VX] * thickness; v4[VY] = a[VY] - normal[VY] * thickness; if(!addToLists) { DGL_Bind(tex); DGL_Color4f(color[0], color[1], color[2], glowAlpha * Automap_GetOpacity(map)); DGL_BlendMode(blend); } DGL_Begin(DGL_QUADS); // V1 DGL_TexCoord2f(0, .5f, 0); DGL_TexCoord2f(1, v1[VX], v1[VY]); DGL_Vertex2f(v1[VX], v1[VY]); // V2 DGL_TexCoord2f(0, .5f, 0); DGL_TexCoord2f(1, v2[VX], v2[VY]); DGL_Vertex2f(v2[VX], v2[VY]); // V3 DGL_TexCoord2f(0, .5f, 1); DGL_TexCoord2f(1, v3[VX], v3[VY]); DGL_Vertex2f(v3[VX], v3[VY]); // V4 DGL_TexCoord2f(0, .5f, 1); DGL_TexCoord2f(1, v4[VX], v4[VY]); DGL_Vertex2f(v4[VX], v4[VY]); DGL_End(); if(!addToLists) DGL_BlendMode(BM_NORMAL); } break; case BACK_GLOW: { float v1[2], v2[2], v3[2], v4[2]; v1[VX] = a[VX] + normal[VX] * thickness; v1[VY] = a[VY] + normal[VY] * thickness; v2[VX] = b[VX] + normal[VX] * thickness; v2[VY] = b[VY] + normal[VY] * thickness; v3[VX] = b[VX]; v3[VY] = b[VY]; v4[VX] = a[VX]; v4[VY] = a[VY]; if(!addToLists) { DGL_Bind(tex); DGL_Color4f(color[0], color[1], color[2], glowAlpha * Automap_GetOpacity(map)); DGL_BlendMode(blend); } DGL_Begin(DGL_QUADS); // V1 DGL_TexCoord2f(0, 0, .25f); DGL_TexCoord2f(1, v1[VX], v1[VY]); DGL_Vertex2f(v1[VX], v1[VY]); // V2 DGL_TexCoord2f(0, 0, .25f); DGL_TexCoord2f(1, v2[VX], v2[VY]); DGL_Vertex2f(v2[VX], v2[VY]); // V3 DGL_TexCoord2f(0, .5f, .25f); DGL_TexCoord2f(1, v3[VX], v3[VY]); DGL_Vertex2f(v3[VX], v3[VY]); // V4 DGL_TexCoord2f(0, .5f, .25f); DGL_TexCoord2f(1, v4[VX], v4[VY]); DGL_Vertex2f(v4[VX], v4[VY]); DGL_End(); if(!addToLists) DGL_BlendMode(BM_NORMAL); } break; case FRONT_GLOW: { float v1[2], v2[2], v3[2], v4[2]; v1[VX] = a[VX]; v1[VY] = a[VY]; v2[VX] = b[VX]; v2[VY] = b[VY]; v3[VX] = b[VX] - normal[VX] * thickness; v3[VY] = b[VY] - normal[VY] * thickness; v4[VX] = a[VX] - normal[VX] * thickness; v4[VY] = a[VY] - normal[VY] * thickness; if(!addToLists) { DGL_Bind(tex); DGL_Color4f(color[0], color[1], color[2], glowAlpha * Automap_GetOpacity(map)); DGL_BlendMode(blend); } DGL_Begin(DGL_QUADS); // V1 DGL_TexCoord2f(0, .75f, .5f); DGL_TexCoord2f(1, v1[VX], v1[VY]); DGL_Vertex2f(v1[VX], v1[VY]); // V2 DGL_TexCoord2f(0, .75f, .5f); DGL_TexCoord2f(1, v2[VX], v2[VY]); DGL_Vertex2f(v2[VX], v2[VY]); // V3 DGL_TexCoord2f(0, .75f, 1); DGL_TexCoord2f(1, v3[VX], v3[VY]); DGL_Vertex2f(v3[VX], v3[VY]); // V4 DGL_TexCoord2f(0, .75f, 1); DGL_TexCoord2f(1, v4[VX], v4[VY]); DGL_Vertex2f(v4[VX], v4[VY]); DGL_End(); if(!addToLists) DGL_BlendMode(BM_NORMAL); } break; default: break; // Impossible. } if(caps) { float v1[2], v2[2], v3[2], v4[2]; v1[VX] = b[VX] + normal[VX] * thickness; v1[VY] = b[VY] + normal[VY] * thickness; v2[VX] = b[VX] + unit[VX] * thickness + normal[VX] * thickness; v2[VY] = b[VY] + unit[VY] * thickness + normal[VY] * thickness; v3[VX] = b[VX] + unit[VX] * thickness - normal[VX] * thickness; v3[VY] = b[VY] + unit[VY] * thickness - normal[VY] * thickness; v4[VX] = b[VX] - normal[VX] * thickness; v4[VY] = b[VY] - normal[VY] * thickness; if(!addToLists) { DGL_Bind(tex); DGL_Color4f(color[0], color[1], color[2], glowAlpha * Automap_GetOpacity(map)); DGL_BlendMode(blend); } DGL_Begin(DGL_QUADS); // V1 DGL_TexCoord2f(0, .5f, 0); DGL_TexCoord2f(1, v1[VX], v1[VY]); DGL_Vertex2f(v1[VX], v1[VY]); // V2 DGL_TexCoord2f(0, 1, 0); DGL_TexCoord2f(1, v2[VX], v2[VY]); DGL_Vertex2f(v2[VX], v2[VY]); // V3 DGL_TexCoord2f(0, 1, 1); DGL_TexCoord2f(1, v3[VX], v3[VY]); DGL_Vertex2f(v3[VX], v3[VY]); // V4 DGL_TexCoord2f(0, .5, 1); DGL_TexCoord2f(1, v4[VX], v4[VY]); DGL_Vertex2f(v4[VX], v4[VY]); DGL_End(); if(!addToLists) DGL_BlendMode(BM_NORMAL); } } if(!glowOnly) { if(!addToLists) { DGL_Color4f(color[0], color[1], color[2], color[3] * Automap_GetOpacity(map)); DGL_BlendMode(blend); } DGL_Begin(DGL_LINES); DGL_TexCoord2f(0, a[VX], a[VY]); DGL_Vertex2f(a[VX], a[VY]); DGL_TexCoord2f(0, b[VX], b[VY]); DGL_Vertex2f(b[VX], b[VY]); DGL_End(); if(!addToLists) DGL_BlendMode(BM_NORMAL); } if(drawNormal) { #define NORMTAIL_LENGTH 8 float center[2]; center[VX] = a[VX] + (length / 2) * unit[VX]; center[VY] = a[VY] + (length / 2) * unit[VY]; a[VX] = center[VX]; a[VY] = center[VY]; b[VX] = center[VX] + normal[VX] * NORMTAIL_LENGTH; b[VY] = center[VY] + normal[VY] * NORMTAIL_LENGTH; if(!addToLists) { DGL_Color4f(color[0], color[1], color[2], color[3] * Automap_GetOpacity(map)); DGL_BlendMode(blend); } DGL_Begin(DGL_LINES); DGL_TexCoord2f(0, a[VX], a[VY]); DGL_Vertex2f(a[VX], a[VY]); DGL_TexCoord2f(0, b[VX], b[VY]); DGL_Vertex2f(b[VX], b[VY]); DGL_End(); if(!addToLists) DGL_BlendMode(BM_NORMAL); #undef NORMTAIL_LENGTH } } int Rend_AutomapSeg(void* obj, void* data) { seg_t* seg = (seg_t*) obj; rendwallseg_params_t* p = (rendwallseg_params_t*) data; float v1[2], v2[2]; linedef_t* line; xline_t* xLine; sector_t* frontSector, *backSector; const mapobjectinfo_t* info; player_t* plr = p->plr; automapid_t id; line = P_GetPtrp(seg, DMU_LINEDEF); if(!line) return 1; xLine = P_ToXLine(line); if(xLine->validCount == VALIDCOUNT) return 1; // Already drawn once. if((xLine->flags & ML_DONTDRAW) && !(p->map->flags & AMF_REND_ALLLINES)) return 1; frontSector = P_GetPtrp(line, DMU_FRONT_SECTOR); if(frontSector != P_GetPtrp(line, DMU_SIDEDEF0_OF_LINE | DMU_SECTOR)) return 1; // We only want to draw twosided lines once. id = AM_MapForPlayer(plr - players); info = NULL; if((p->map->flags & AMF_REND_ALLLINES) || xLine->mapped[plr - players]) { backSector = P_GetPtrp(line, DMU_BACK_SECTOR); // Perhaps this is a specially colored line? info = AM_GetInfoForSpecialLine(id, xLine->special, frontSector, backSector); if(p->objType != -1 && !info) { // Perhaps a default colored line? if(!(frontSector && backSector) || (xLine->flags & ML_SECRET)) { // solid wall (well probably anyway...) info = AM_GetMapObjectInfo(id, AMO_SINGLESIDEDLINE); } else { if(P_GetFloatp(backSector, DMU_FLOOR_HEIGHT) != P_GetFloatp(frontSector, DMU_FLOOR_HEIGHT)) { // Floor level change. info = AM_GetMapObjectInfo(id, AMO_FLOORCHANGELINE); } else if(P_GetFloatp(backSector, DMU_CEILING_HEIGHT) != P_GetFloatp(frontSector, DMU_CEILING_HEIGHT)) { // Ceiling level change. info = AM_GetMapObjectInfo(id, AMO_CEILINGCHANGELINE); } else if(p->map->flags & AMF_REND_ALLLINES) { info = AM_GetMapObjectInfo(id, AMO_UNSEENLINE); } } } } else if(p->objType != -1 && p->cfg->revealed) { if(!(xLine->flags & ML_DONTDRAW)) { // An as yet, unseen line. info = AM_GetMapObjectInfo(id, AMO_UNSEENLINE); } } if(info && (p->objType == -1 || info == &p->cfg->mapObjectInfo[p->objType])) { P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, v1); P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, v2); rendLine2(p->map, p->cfg, v1[VX], v1[VY], v2[VX], v2[VY], info->rgba, (xLine->special && !p->cfg->glowingLineSpecials ? NO_GLOW : info->glow), info->glowAlpha, info->glowWidth, !p->addToLists, info->scaleWithView, (info->glow && !(xLine->special && !p->cfg->glowingLineSpecials)), (xLine->special && !p->cfg->glowingLineSpecials ? BM_NORMAL : info->blendMode), (p->map->flags & AMF_REND_LINE_NORMALS), p->addToLists); xLine->validCount = VALIDCOUNT; // Mark as drawn this frame. } return 1; // Continue iteration. } static boolean drawSegsOfSubsector(subsector_t* ssec, void* context) { return P_Iteratep(ssec, DMU_SEG, context, Rend_AutomapSeg); } /** * Determines visible lines, draws them. * * @params objType Type of map object being drawn. */ static void renderWalls(const automap_t* map, const automapcfg_t* cfg, int player, int objType, boolean addToLists) { uint i; rendwallseg_params_t params; // VALIDCOUNT is used to track which lines have been drawn this frame. VALIDCOUNT++; // Set the vars used during iteration. params.plr = &players[player]; params.map = map; params.cfg = cfg; params.objType = objType; params.addToLists = addToLists; // Can we use the automap's in-view bounding box to cull out of view // objects? if(!addToLists) { float aabb[4]; Automap_GetInViewAABB(map, &aabb[BOXLEFT], &aabb[BOXRIGHT], &aabb[BOXBOTTOM], &aabb[BOXTOP]); P_SubsectorsBoxIterator(aabb, NULL, drawSegsOfSubsector, ¶ms); } else { // No. As the map lists are considered static we want them to // contain all walls, not just those visible *now*. for(i = 0; i < numsubsectors; ++i) { P_Iteratep(P_ToPtr(DMU_SUBSECTOR, i), DMU_SEG, ¶ms, Rend_AutomapSeg); } } } static void renderLinedef(linedef_t* line, float r, float g, float b, float a, blendmode_t blendMode, boolean drawNormal) { float length = P_GetFloatp(line, DMU_LENGTH); if(length > 0) { float v1[2], v2[2]; P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, v1); P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, v2); DGL_BlendMode(blendMode); DGL_Color4f(r, g, b, a); DGL_Begin(DGL_LINES); DGL_TexCoord2f(0, v1[VX], v1[VY]); DGL_Vertex2f(v1[VX], v1[VY]); DGL_TexCoord2f(0, v2[VX], v2[VY]); DGL_Vertex2f(v2[VX], v2[VY]); DGL_End(); if(drawNormal) { #define NORMTAIL_LENGTH 8 float normal[2], unit[2], d1[2]; P_GetFloatpv(line, DMU_DXY, d1); unit[VX] = d1[0] / length; unit[VY] = d1[1] / length; normal[VX] = unit[VY]; normal[VY] = -unit[VX]; // The center of the linedef. v1[VX] += (length / 2) * unit[VX]; v1[VY] += (length / 2) * unit[VY]; // Outside point. v2[VX] = v1[VX] + normal[VX] * NORMTAIL_LENGTH; v2[VY] = v1[VY] + normal[VY] * NORMTAIL_LENGTH; DGL_Begin(DGL_LINES); DGL_TexCoord2f(0, v1[VX], v1[VY]); DGL_Vertex2f(v1[VX], v1[VY]); DGL_TexCoord2f(0, v2[VX], v2[VY]); DGL_Vertex2f(v2[VX], v2[VY]); DGL_End(); #undef NORMTAIL_LENGTH } DGL_BlendMode(BM_NORMAL); } } /** * Rather than draw the segs instead this will draw the linedef of which * the seg is a part. */ int renderPolyObjSeg(void* obj, void* context) { seg_t* seg = (seg_t*) obj; rendwallseg_params_t* p = (rendwallseg_params_t*) context; linedef_t* line; xline_t* xLine; const mapobjectinfo_t* info; automapobjectname_t amo; if(!(line = P_GetPtrp(seg, DMU_LINEDEF)) || !(xLine = P_ToXLine(line))) return 1; if(xLine->validCount == VALIDCOUNT) return 1; // Already processed this frame. if((xLine->flags & ML_DONTDRAW) && !(p->map->flags & AMF_REND_ALLLINES)) return 1; amo = AMO_NONE; if((p->map->flags & AMF_REND_ALLLINES) || xLine->mapped[p->plr - players]) { amo = AMO_SINGLESIDEDLINE; } else if(p->map->flags && !(xLine->flags & ML_DONTDRAW)) { // An as yet, unseen line. amo = AMO_UNSEENLINE; } if((info = AM_GetMapObjectInfo(AM_MapForPlayer(p->plr - players), amo))) { renderLinedef(line, info->rgba[0], info->rgba[1], info->rgba[2], info->rgba[3] * cfg.automapLineAlpha * Automap_GetOpacity(p->map), info->blendMode, (p->map->flags & AMF_REND_LINE_NORMALS)? true : false); } xLine->validCount = VALIDCOUNT; // Mark as processed this frame. return 1; // Continue iteration. } boolean drawSegsOfPolyobject(polyobj_t* po, void* context) { seg_t** segPtr; int result = 1; segPtr = po->segs; while(*segPtr && (result = renderPolyObjSeg(*segPtr, context)) != 0) *segPtr++; return result; } static void renderPolyObjs(const automap_t* map, const automapcfg_t* cfg, int player) { float aabb[4]; rendwallseg_params_t params; // VALIDCOUNT is used to track which lines have been drawn this frame. VALIDCOUNT++; // Set the vars used during iteration. params.plr = &players[player]; params.map = map; params.cfg = cfg; params.objType = MOL_LINEDEF; // Next, draw any polyobjects in view. Automap_GetInViewAABB(map, &aabb[BOXLEFT], &aabb[BOXRIGHT], &aabb[BOXBOTTOM], &aabb[BOXTOP]); P_PolyobjsBoxIterator(aabb, drawSegsOfPolyobject, ¶ms); } #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ boolean renderXGLinedef(linedef_t* line, void* context) { rendwallseg_params_t* p = (rendwallseg_params_t*) context; xline_t* xLine; xLine = P_ToXLine(line); if(!xLine || xLine->validCount == VALIDCOUNT || ((xLine->flags & ML_DONTDRAW) && !(p->map->flags & AMF_REND_ALLLINES))) return 1; // Show only active XG lines. if(!(xLine->xg && xLine->xg->active && (mapTime & 4))) return 1; renderLinedef(line, .8f, 0, .8f, 1, BM_ADD, (p->map->flags & AMF_REND_LINE_NORMALS)? true : false); xLine->validCount = VALIDCOUNT; // Mark as processed this frame. return 1; // Continue iteration. } #endif static void renderXGLinedefs(const automap_t* map, const automapcfg_t* cfg, int player) { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ float aabb[4]; rendwallseg_params_t params; if(!(map->flags & AMF_REND_XGLINES)) return; // VALIDCOUNT is used to track which lines have been drawn this frame. VALIDCOUNT++; // Set the vars used during iteration. params.plr = &players[player]; params.map = map; params.cfg = cfg; params.addToLists = false; params.objType = -1; Automap_GetInViewAABB(map, &aabb[BOXLEFT], &aabb[BOXRIGHT], &aabb[BOXBOTTOM], &aabb[BOXTOP]); P_LinesBoxIterator(aabb, renderXGLinedef, ¶ms); #endif } static DGLuint constructLineCharacter(DGLuint name, const vectorgrap_t* vg) { if(DGL_NewList(name, DGL_COMPILE)) { uint i; DGL_Begin(DGL_LINES); for(i = 0; i < vg->count; ++i) { vgline_t* vgl = &vg->lines[i]; DGL_TexCoord2f(0, vgl->a.pos[VX], vgl->a.pos[VY]); DGL_Vertex2f(vgl->a.pos[VX], vgl->a.pos[VY]); DGL_TexCoord2f(0, vgl->b.pos[VX], vgl->b.pos[VY]); DGL_Vertex2f(vgl->b.pos[VX], vgl->b.pos[VY]); } DGL_End(); return DGL_EndList(); } return 0; } /** * Draws a line character (eg the player arrow) */ static void renderLineCharacter(vectorgrap_t* vg, float x, float y, float angle, float scale, const float rgb[3], float alpha, blendmode_t blendmode) { if(!vg->dlist) vg->dlist = constructLineCharacter(0, vg); DGL_MatrixMode(DGL_PROJECTION); DGL_PushMatrix(); DGL_Translatef(x, y, 1); DGL_Rotatef(angle, 0, 0, 1); DGL_Scalef(scale, scale, 1); DGL_MatrixMode(DGL_TEXTURE); DGL_PushMatrix(); DGL_Translatef(x, y, 1); DGL_Color4f(rgb[0], rgb[1], rgb[2], alpha); DGL_BlendMode(blendmode); DGL_CallList(vg->dlist); DGL_MatrixMode(DGL_TEXTURE); DGL_PopMatrix(); DGL_MatrixMode(DGL_PROJECTION); DGL_PopMatrix(); } /** * Draws all players on the map using a line character */ static void renderPlayers(const automap_t* map, const automapcfg_t* mcfg, int player) { int i; float size = PLAYERRADIUS; vectorgrap_t* vg; vg = AM_GetVectorGraph(AM_GetVectorGraphic(mcfg, AMO_THINGPLAYER)); for(i = 0; i < MAXPLAYERS; ++i) { player_t* p = &players[i]; float rgb[3], alpha; mobj_t* mo; if(!p->plr->inGame) continue; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ if(deathmatch && p != &players[player]) continue; #endif R_GetColorPaletteRGBf(0, rgb, (!IS_NETGAME? WHITE : their_colors[cfg.playerColor[i]]), false); alpha = cfg.automapLineAlpha; #if !__JHEXEN__ if(p->powers[PT_INVISIBILITY]) alpha *= .125f; #endif alpha = MINMAX_OF(0.f, alpha * Automap_GetOpacity(map), 1.f); mo = p->plr->mo; /* $unifiedangles */ renderLineCharacter(vg, mo->pos[VX], mo->pos[VY], mo->angle / (float) ANGLE_MAX * 360, size, rgb, alpha, BM_NORMAL); } } static int getKeyColorForMobjType(int type) { struct keycolor_s { int moType; int color; } keyColors[] = { #if __JDOOM__ || __JDOOM64__ {MT_MISC4, KEY1_COLOR}, {MT_MISC5, KEY2_COLOR}, {MT_MISC6, KEY3_COLOR}, {MT_MISC7, KEY4_COLOR}, {MT_MISC8, KEY5_COLOR}, {MT_MISC9, KEY6_COLOR}, #elif __JHERETIC__ {MT_CKEY, KEY1_COLOR}, {MT_BKYY, KEY2_COLOR}, {MT_AKYY, KEY3_COLOR}, #endif {-1, -1} // Terminate. }; uint i; for(i = 0; keyColors[i].moType != -1; ++i) if(keyColors[i].moType == type) return keyColors[i].color; return -1; // Not a key. } typedef struct { int flags; // AMF_* flags. vectorgrap_t* vgraph; float rgb[3], alpha; } renderthing_params_t; /** * Draws all things on the map */ static boolean renderThing(mobj_t* mo, void* context) { renderthing_params_t* p = (renderthing_params_t*) context; // Only sector linked mobjs should be visible in the automap. if(!(mo->flags & MF_NOSECTOR)) { if(p->flags & AMF_REND_KEYS) { int keyColor; // Is this a key? if((keyColor = getKeyColorForMobjType(mo->type)) != -1) { // This mobj is indeed a key. float rgb[4]; R_GetColorPaletteRGBf(0, rgb, keyColor, false); /* $unifiedangles */ renderLineCharacter(AM_GetVectorGraph(VG_KEYSQUARE), mo->pos[VX], mo->pos[VY], 0, PLAYERRADIUS, rgb, p->alpha, BM_NORMAL); return true; // Continue iteration. } } if(p->flags & AMF_REND_THINGS) { // Something else. /* $unifiedangles */ renderLineCharacter(p->vgraph, mo->pos[VX], mo->pos[VY], mo->angle / (float) ANGLE_MAX * 360, PLAYERRADIUS, p->rgb, p->alpha, BM_NORMAL); } } return true; // Continue iteration. } /** * Draws all the points marked by the player. */ static void drawMarks(const automap_t* map) { #if !__JDOOM64__ float x, y, w, h; dpatch_t* patch; float scrwidth = Get(DD_WINDOW_WIDTH); float scrheight = Get(DD_WINDOW_HEIGHT); float aabb[4]; unsigned int i, numMarks; Automap_GetInViewAABB(map, &aabb[BOXLEFT], &aabb[BOXRIGHT], &aabb[BOXBOTTOM], &aabb[BOXTOP]); numMarks = Automap_GetNumMarks(map); for(i = 0; i < numMarks; ++i) { if(Automap_GetMark(map, i, &x, &y, NULL) && !(x < aabb[BOXLEFT] || x > aabb[BOXRIGHT] || y < aabb[BOXBOTTOM] || y > aabb[BOXTOP])) { patch = &markerPatches[i]; w = Automap_FrameToMap(map, FIXXTOSCREENX(patch->width)); h = Automap_FrameToMap(map, FIXYTOSCREENY(patch->height)); DGL_SetPatch(patch->lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_Color4f(1, 1, 1, Automap_GetOpacity(map)); DGL_MatrixMode(DGL_PROJECTION); DGL_PushMatrix(); DGL_Translatef(x, y, 0); DGL_Rotatef(Automap_GetViewAngle(map), 0, 0, 1); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(-(w / 2), h / 2); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(w / 2, h / 2); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(w / 2, -(h / 2)); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(-(w / 2), -(h / 2)); DGL_End(); DGL_MatrixMode(DGL_PROJECTION); DGL_PopMatrix(); } } #endif } /** * Sets up the state for automap drawing. */ static void setupGLStateForMap(const automap_t* map, const automapcfg_t* mcfg, int player) { float wx, wy, ww, wh, angle, plx, ply; float scrwidth = Get(DD_WINDOW_WIDTH); float scrheight = Get(DD_WINDOW_HEIGHT); rautomap_data_t* rmap = &rautomaps[AM_MapForPlayer(player)-1]; Automap_GetWindow(map, &wx, &wy, &ww, &wh); Automap_GetViewParallaxPosition(map, &plx, &ply); angle = Automap_GetViewAngle(map); // Check for scissor box (to clip the map lines and stuff). // Store the old scissor state. DGL_GetIntegerv(DGL_SCISSOR_TEST, rmap->scissorState); DGL_GetIntegerv(DGL_SCISSOR_BOX, rmap->scissorState + 1); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_MatrixMode(DGL_PROJECTION); DGL_PushMatrix(); DGL_LoadIdentity(); DGL_Ortho(0, 0, scrwidth, scrheight, -1, 1); // Do we want a background texture? if(autopageLumpNum != -1) { // Apply the background texture onto a parallaxing layer which // follows the map view target (not player). DGL_Enable(DGL_TEXTURING); DGL_MatrixMode(DGL_TEXTURE); DGL_PushMatrix(); DGL_LoadIdentity(); // We only want the left portion. DGL_SetRawImage(autopageLumpNum, false, DGL_REPEAT, DGL_REPEAT); DGL_Color4f(mcfg->backgroundRGBA[0], mcfg->backgroundRGBA[1], mcfg->backgroundRGBA[2], Automap_GetOpacity(map) * mcfg->backgroundRGBA[3]); // Scale from texture to window space DGL_Translatef(wx, wy, 0); // Apply the parallax scrolling, map rotation and counteract the // aspect of the quad (sized to map window dimensions). DGL_Translatef(Automap_MapToFrame(map, plx) + .5f, Automap_MapToFrame(map, ply) + .5f, 0); DGL_Rotatef(angle, 0, 0, 1); DGL_Scalef(1, wh / ww, 1); DGL_Translatef(-(.5f), -(.5f), 0); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(wx, wy); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(wx + ww, wy); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(wx + ww, wy + wh); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(wx, wy + wh); DGL_End(); DGL_MatrixMode(DGL_TEXTURE); DGL_PopMatrix(); DGL_MatrixMode(DGL_PROJECTION); } else { // Nope just a solid color. DGL_SetNoMaterial(); DGL_DrawRect(wx, wy, ww, wh, mcfg->backgroundRGBA[0], mcfg->backgroundRGBA[1], mcfg->backgroundRGBA[2], Automap_GetOpacity(map) * mcfg->backgroundRGBA[3]); } #if __JDOOM64__ // jd64 > Demon keys // If drawn in HUD we don't need them visible in the map too. if(!cfg.hudShown[HUD_INVENTORY]) { int i, num = 0; player_t* plr = &players[player]; inventoryitemtype_t items[3] = { IIT_DEMONKEY1, IIT_DEMONKEY2, IIT_DEMONKEY3 }; for(i = 0; i < 3; ++i) num += P_InventoryCount(player, items[i])? 1 : 0; if(num > 0) { float x, y, w, h, spacing, scale, iconAlpha; spriteinfo_t sprInfo; int invItemSprites[NUM_INVENTORYITEM_TYPES] = { SPR_ART1, SPR_ART2, SPR_ART3 }; iconAlpha = MINMAX_OF(.0f, Automap_GetOpacity(map), .5f); spacing = wh / num; y = 0; for(i = 0; i < 3; ++i) { if(P_InventoryCount(player, items[i])) { R_GetSpriteInfo(invItemSprites[i], 0, &sprInfo); DGL_SetPSprite(sprInfo.material); scale = wh / (sprInfo.height * num); x = ww - sprInfo.width * scale; w = sprInfo.width; h = sprInfo.height; { float s, t; // Let's calculate texture coordinates. // To remove a possible edge artifact, move the corner a bit up/left. s = (w - 0.4f) / M_CeilPow2(w); t = (h - 0.4f) / M_CeilPow2(h); DGL_Color4f(1, 1, 1, iconAlpha); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, s, 0); DGL_Vertex2f(x + w * scale, y); DGL_TexCoord2f(0, s, t); DGL_Vertex2f(x + w * scale, y + h * scale); DGL_TexCoord2f(0, 0, t); DGL_Vertex2f(x, y + h * scale); DGL_End(); } y += spacing; } } } } // < d64tc #endif // Setup the scissor clipper. DGL_Scissor(wx, wy, ww, wh); DGL_Enable(DGL_SCISSOR_TEST); } /** * Restores the previous gl draw state */ static void restoreGLStateFromMap(rautomap_data_t* rmap) { // Return to the normal GL state. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); if(!rmap->scissorState[0]) DGL_Disable(DGL_SCISSOR_TEST); DGL_Scissor(rmap->scissorState[1], rmap->scissorState[2], rmap->scissorState[3], rmap->scissorState[4]); } static void drawMapName(float x, float y, float alpha, dpatch_t* patch, const char* lname) { DGL_MatrixMode(DGL_PROJECTION); DGL_PushMatrix(); DGL_LoadIdentity(); DGL_Ortho(0, 0, SCREENWIDTH, SCREENHEIGHT, -1, 1); Draw_BeginZoom(.4f, x, y); y -= 24; // border WI_DrawPatch(x, y, 1, 1, 1, alpha, patch, lname, false, ALIGN_CENTER); Draw_EndZoom(); DGL_MatrixMode(DGL_PROJECTION); DGL_PopMatrix(); } /** * Draws the map name into the automap window */ static void renderMapName(const automap_t* map) { float x, y, otherY; const char* lname; dpatch_t* patch = NULL; #if __JDOOM__ || __JDOOM64__ int mapNum; #endif lname = P_GetMapNiceName(); if(lname) { float wx, wy, ww, wh; float scrwidth = Get(DD_WINDOW_WIDTH); float scrheight = Get(DD_WINDOW_HEIGHT); // Compose the mapnumber used to check the map name patches array. #if __JDOOM64__ mapNum = gameMap; patch = &mapNamePatches[mapNum]; #elif __JDOOM__ if(gameMode == commercial) mapNum = gameMap; else mapNum = (gameEpisode * 9) + gameMap; patch = &mapNamePatches[mapNum]; #endif Automap_GetWindow(map, &wx, &wy, &ww, &wh); x = SCREENXTOFIXX(wx + (ww * .5f)); y = SCREENYTOFIXY(wy + wh); if(cfg.setBlocks < 13) { #if !__JDOOM64__ if(cfg.setBlocks <= 11 || cfg.automapHudDisplay == 2) { // We may need to adjust for the height of the statusbar otherY = ST_Y; otherY += ST_HEIGHT * (1 - (cfg.statusbarScale / 20.0f)); if(y > otherY) y = otherY; } else if(cfg.setBlocks == 12) #endif { // We may need to adjust for the height of the HUD icons. otherY = y; otherY += -(y * (cfg.hudScale / 10.0f)); if(y > otherY) y = otherY; } } drawMapName(x, y, Automap_GetOpacity(map), patch, lname); } } static void renderVertexes(float alpha) { uint i; float v[2], oldPointSize; DGL_Color4f(.2f, .5f, 1, alpha); DGL_Enable(DGL_POINT_SMOOTH); oldPointSize = DGL_GetFloat(DGL_POINT_SIZE); DGL_SetFloat(DGL_POINT_SIZE, 4); DGL_Begin(DGL_POINTS); for(i = 0; i < numvertexes; ++i) { P_GetFloatv(DMU_VERTEX, i, DMU_XY, v); DGL_TexCoord2f(0, v[VX], v[VY]); DGL_Vertex2f(v[VX], v[VY]); } DGL_End(); DGL_SetFloat(DGL_POINT_SIZE, oldPointSize); DGL_Disable(DGL_POINT_SMOOTH); } /** * Compile OpenGL commands for drawing the map objects into display lists. */ static void compileObjectLists(rautomap_data_t* rmap, const automap_t* map, const automapcfg_t* cfg, int player) { uint i; deleteMapLists(rmap); for(i = 0; i < NUM_MAP_OBJECTLISTS; ++i) { // Build commands and compile to a display list. if(DGL_NewList(0, DGL_COMPILE)) { renderWalls(map, cfg, player, i, true); rmap->lists[i] = DGL_EndList(); } } rmap->constructMap = false; } void Rend_AutomapRebuild(int player) { automapid_t map; if((map = AM_MapForPlayer(player))) { rautomap_data_t* rmap = &rautomaps[map-1]; rmap->constructMap = true; } } /** * Render the automap view window for the specified player. */ void Rend_Automap(int player, const automap_t* map) { static int updateWait = 0; uint i; automapid_t id = AM_MapForPlayer(player); player_t* plr; float wx, wy, ww, wh, vx, vy, angle, oldLineWidth, mtof; const automapcfg_t* mcfg; rautomap_data_t* rmap; plr = &players[player]; if(!(/*(plr->plr->flags & DDPF_LOCAL) && */ plr->plr->inGame)) return; if(!(Automap_GetOpacity(map) > 0)) return; mcfg = AM_GetMapConfig(id); rmap = &rautomaps[id-1]; Automap_GetWindow(map, &wx, &wy, &ww, &wh); Automap_GetLocation(map, &vx, &vy); mtof = Automap_MapToFrameMultiplier(map); angle = Automap_GetViewAngle(map); // Freeze the lists if the map is fading out from being open or if set // to frozen for debug. if((++updateWait % 10) && rmap->constructMap && !freezeMapRLs && Automap_IsActive(map)) { // Its time to rebuild the automap object display lists. compileObjectLists(rmap, map, mcfg, player); } // Setup for frame. setupGLStateForMap(map, mcfg, player); DGL_MatrixMode(DGL_PROJECTION); DGL_Translatef(wx + ww / 2, wy + wh / 2, 0); DGL_Rotatef(angle, 0, 0, 1); DGL_Scalef(1, -1, 1); DGL_Scalef(mtof, mtof, 1); DGL_Translatef(-vx, -vy, 0); oldLineWidth = DGL_GetFloat(DGL_LINE_WIDTH); DGL_SetFloat(DGL_LINE_WIDTH, AM_LINE_WIDTH); if(amMaskTexture) { DGL_Enable(DGL_TEXTURING); DGL_Bind(amMaskTexture); DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); DGL_MatrixMode(DGL_TEXTURE); DGL_LoadIdentity(); DGL_PushMatrix(); DGL_Scalef(1.f / ww, 1.f / wh, 1); DGL_Translatef(ww / 2, wh / 2, 0); DGL_Rotatef(-angle, 0, 0, 1); DGL_Scalef(mtof, mtof, 1); DGL_Translatef(-vx, -vy, 0); } // Draw static map geometry. for(i = 0; i < NUM_MAP_OBJECTLISTS; ++i) { if(rmap->lists[i]) { const mapobjectinfo_t* info = &mcfg->mapObjectInfo[i]; // Setup the global list state. DGL_Color4f(info->rgba[0], info->rgba[1], info->rgba[2], info->rgba[3] * cfg.automapLineAlpha * Automap_GetOpacity(map)); DGL_BlendMode(info->blendMode); // Draw. DGL_CallList(rmap->lists[i]); } } // Draw dynamic map geometry. renderXGLinedefs(map, mcfg, player); renderPolyObjs(map, mcfg, player); // Restore the previous state. DGL_BlendMode(BM_NORMAL); DGL_Color4f(1, 1, 1, 1); if(Automap_GetFlags(map) & AMF_REND_VERTEXES) renderVertexes(Automap_GetOpacity(map)); // Draw the map objects: renderPlayers(map, mcfg, player); if(Automap_GetFlags(map) & (AMF_REND_THINGS|AMF_REND_KEYS)) { float aabb[4]; renderthing_params_t params; params.flags = Automap_GetFlags(map); params.vgraph = AM_GetVectorGraph(AM_GetVectorGraphic(mcfg, AMO_THING)); AM_GetMapColor(params.rgb, cfg.automapMobj, THINGCOLORS, !W_IsFromIWAD(W_GetNumForName("PLAYPAL"))); params.alpha = MINMAX_OF(0.f, cfg.automapLineAlpha * Automap_GetOpacity(map), 1.f); Automap_GetInViewAABB(map, &aabb[BOXLEFT], &aabb[BOXRIGHT], &aabb[BOXBOTTOM], &aabb[BOXTOP]); VALIDCOUNT++; P_MobjsBoxIterator(aabb, renderThing, ¶ms); } DGL_SetFloat(DGL_LINE_WIDTH, oldLineWidth); if(amMaskTexture) { DGL_MatrixMode(DGL_TEXTURE); DGL_PopMatrix(); DGL_Bind(0); } // Draw glows. renderWalls(map, mcfg, player, -1, false); // Draw any marked points. drawMarks(map); DGL_MatrixMode(DGL_PROJECTION); DGL_PopMatrix(); renderMapName(map); restoreGLStateFromMap(rmap); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_xgsec.c0000644000175000017500000026065211357170242022434 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_xgsec.c: Extended Generalized Sector Types. */ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_xgline.h" #include "p_xgsec.h" #include "g_common.h" #include "p_map.h" #include "p_mapspec.h" #include "p_terraintype.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ #define PI 3.141592657 #define MAX_VALS 128 #define SIGN(x) ((x)>0? 1 : (x)<0? -1 : 0) #define ISFUNC(fn) (fn->func && fn->func[fn->pos]) #define UPDFUNC(fn) ((ISFUNC(fn) || fn->link)) #define SPREFTYPESTR(reftype) (reftype == SPREF_NONE? "NONE" \ : reftype == SPREF_MY_FLOOR? "MY FLOOR" \ : reftype == SPREF_MY_CEILING? "MY CEILING" \ : reftype == SPREF_ORIGINAL_FLOOR? "ORIGINAL FLOOR" \ : reftype == SPREF_ORIGINAL_CEILING? "ORIGINAL CEILING" \ : reftype == SPREF_CURRENT_FLOOR? "CURRENT FLOOR" \ : reftype == SPREF_CURRENT_CEILING? "CURRENT CEILING" \ : reftype == SPREF_HIGHEST_FLOOR? "HIGHEST FLOOR" \ : reftype == SPREF_HIGHEST_CEILING? "HIGHEST CEILING" \ : reftype == SPREF_LOWEST_FLOOR? "LOWEST FLOOR" \ : reftype == SPREF_LOWEST_CEILING? "LOWEST CEILING" \ : reftype == SPREF_NEXT_HIGHEST_FLOOR? "NEXT HIGHEST FLOOR" \ : reftype == SPREF_NEXT_HIGHEST_CEILING? "NEXT HIGHEST CEILING" \ : reftype == SPREF_NEXT_LOWEST_FLOOR? "NEXT LOWEST FLOOR" \ : reftype == SPREF_NEXT_LOWEST_CEILING? "NEXT LOWEST CEILING" \ : reftype == SPREF_MIN_BOTTOM_MATERIAL? "MIN BOTTOM MATERIAL" \ : reftype == SPREF_MIN_MID_MATERIAL? "MIN MIDDLE MATERIAL" \ : reftype == SPREF_MIN_TOP_MATERIAL? "MIN TOP MATERIAL" \ : reftype == SPREF_MAX_BOTTOM_MATERIAL? "MAX BOTTOM MATERIAL" \ : reftype == SPREF_MAX_MID_MATERIAL? "MAX MIDDLE MATERIAL" \ : reftype == SPREF_MAX_TOP_MATERIAL? "MAX TOP MATERIAL" \ : reftype == SPREF_SECTOR_TAGGED_FLOOR? "SECTOR TAGGED FLOOR" \ : reftype == SPREF_LINE_TAGGED_FLOOR? "LINE TAGGED FLOOR" \ : reftype == SPREF_TAGGED_FLOOR? "TAGGED FLOOR" \ : reftype == SPREF_ACT_TAGGED_FLOOR? "ACT TAGGED FLOOR" \ : reftype == SPREF_INDEX_FLOOR? "INDEXED FLOOR" \ : reftype == SPREF_SECTOR_TAGGED_CEILING? "SECTOR TAGGED CEILING" \ : reftype == SPREF_LINE_TAGGED_CEILING? "LINE TAGGED CEILING" \ : reftype == SPREF_TAGGED_CEILING? "TAGGED CEILING" \ : reftype == SPREF_ACT_TAGGED_CEILING? "ACT TAGGED CEILING" \ : reftype == SPREF_INDEX_CEILING? "INDEXED CEILING" \ : reftype == SPREF_BACK_FLOOR? "BACK FLOOR" \ : reftype == SPREF_BACK_CEILING? "BACK CEILING" \ : reftype == SPREF_SPECIAL? "SPECIAL" \ : reftype == SPREF_LINE_ACT_TAGGED_FLOOR? "LINE ACT TAGGED FLOOR" \ : reftype == SPREF_LINE_ACT_TAGGED_CEILING? "LINE ACT TAGGED CEILING" : "???") #define TO_DMU_COLOR(x) (x == 0? DMU_COLOR_RED \ : x == 1? DMU_COLOR_GREEN \ : DMU_COLOR_BLUE) #define TO_DMU_CEILING_COLOR(x) (x == 0? DMU_CEILING_COLOR_RED \ : x == 1? DMU_CEILING_COLOR_GREEN \ : DMU_CEILING_COLOR_BLUE) #define TO_DMU_FLOOR_COLOR(x) (x == 0? DMU_FLOOR_COLOR_RED \ : x == 1? DMU_FLOOR_COLOR_GREEN \ : DMU_FLOOR_COLOR_BLUE) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void XS_DoChain(sector_t *sec, int ch, int activating, void *actThing); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static sectortype_t sectypebuffer; // CODE -------------------------------------------------------------------- sectortype_t *XS_GetType(int id) { sectortype_t* ptr; char buff[6]; // Try finding it from the DDXGDATA lump. ptr = XG_GetLumpSector(id); if(ptr) { // Got it! memcpy(§ypebuffer, ptr, sizeof(*ptr)); return §ypebuffer; } dd_snprintf(buff, 6, "%i", id); if(Def_Get(DD_DEF_SECTOR_TYPE, buff, §ypebuffer)) return §ypebuffer; // A definition was found. return NULL; // None found. } void XF_Init(sector_t *sec, function_t *fn, char *func, int min, int max, float scale, float offset) { xsector_t *xsec = P_ToXSector(sec); memset(fn, 0, sizeof(*fn)); if(!func) return; // Check for links. if(func[0] == '=') { switch(tolower(func[1])) { case 'r': fn->link = &xsec->xg->rgb[0]; break; case 'g': fn->link = &xsec->xg->rgb[1]; break; case 'b': fn->link = &xsec->xg->rgb[2]; break; case 'f': fn->link = &xsec->xg->plane[XGSP_FLOOR]; break; case 'c': fn->link = &xsec->xg->plane[XGSP_CEILING]; break; case 'l': fn->link = &xsec->xg->light; break; default: Con_Error("XF_Init: Bad linked func (%s).\n", func); } return; } // Check for offsets to current values. if(func[0] == '+') { /** * \important * The original value ranges must be maintained due to the cross linking * between sector function types i.e: * RGB = 0 > 254 * light = 0 > 254 * planeheight = -32768 > 32768 */ switch(func[1]) { case 'r': offset += 255.f * xsec->origRGB[0]; break; case 'g': offset += 255.f * xsec->origRGB[1]; break; case 'b': offset += 255.f * xsec->origRGB[2]; break; case 'l': offset += 255.0f * xsec->origLight; break; case 'f': offset += xsec->SP_floororigheight * FRACUNIT; break; case 'c': offset += xsec->SP_ceilorigheight * FRACUNIT; break; default: Con_Error("XF_Init: Bad preset offset (%s).\n", func); } fn->func = func + 2; } else { fn->func = func; } fn->timer = -1; // The first step musn't skip the first value. fn->maxTimer = XG_RandomInt(min, max); fn->minInterval = min; fn->maxInterval = max; fn->scale = scale; fn->offset = offset; // Make sure oldvalue is out of range. fn->oldValue = -scale + offset; } int C_DECL XLTrav_LineAngle(linedef_t* line, boolean dummy, void* context, void* context2, mobj_t* activator) { sector_t* sec = (sector_t *) context; float d1[2]; if(P_GetPtrp(line, DMU_FRONT_SECTOR) != sec && P_GetPtrp(line, DMU_BACK_SECTOR) != sec) return true; // Wrong sector, keep looking. P_GetFloatpv(line, DMU_DXY, d1); *(angle_t *) context2 = R_PointToAngle2(0, 0, d1[0], d1[1]); return false; // Stop looking after first hit. } boolean findXSThinker(thinker_t* th, void* context) { xsthinker_t* xs = (xsthinker_t*) th; if(xs->sector == (sector_t*) context) return false; // Stop iteration, we've found it. return true; // Continue iteration. } boolean destroyXSThinker(thinker_t* th, void* context) { xsthinker_t* xs = (xsthinker_t*) th; if(xs->sector == (sector_t*) context) { DD_ThinkerRemove(&xs->thinker); return false; // Stop iteration, we're done. } return true; // Continue iteration. } void XS_SetSectorType(struct sector_s* sec, int special) { int i; xsector_t* xsec = P_ToXSector(sec); xgsector_t* xg; sectortype_t* info; if(XS_GetType(special)) { XG_Dev("XS_SetSectorType: Sector %i, type %i", P_ToIndex(sec), special); xsec->special = special; // All right, do the init. if(!xsec->xg) xsec->xg = Z_Malloc(sizeof(xgsector_t), PU_MAP, 0); memset(xsec->xg, 0, sizeof(*xsec->xg)); // Get the type info. memcpy(&xsec->xg->info, §ypebuffer, sizeof(sectypebuffer)); // Init the state. xg = xsec->xg; info = &xsec->xg->info; // Init timer so ambient doesn't play immediately at map start. xg->timer = XG_RandomInt(FLT2TIC(xg->info.soundInterval[0]), FLT2TIC(xg->info.soundInterval[1])); // Light function. XF_Init(sec, &xg->light, info->lightFunc, info->lightInterval[0], info->lightInterval[1], 255, 0); // Color functions. for(i = 0; i < 3; ++i) { XF_Init(sec, &xg->rgb[i], info->colFunc[i], info->colInterval[i][0], info->colInterval[i][1], 255, 0); } // Plane functions / floor. XF_Init(sec, &xg->plane[XGSP_FLOOR], info->floorFunc, info->floorInterval[0], info->floorInterval[1], info->floorMul, info->floorOff); XF_Init(sec, &xg->plane[XGSP_CEILING], info->ceilFunc, info->ceilInterval[0], info->ceilInterval[1], info->ceilMul, info->ceilOff); // Derive texmove angle from first act-tagged line? if((info->flags & STF_ACT_TAG_MATERIALMOVE) || (info->flags & STF_ACT_TAG_WIND)) { angle_t angle = 0; // -1 to support binary XG data with old flag values. XL_TraverseLines(0, (xgDataLumps? LREF_TAGGED -1: LREF_TAGGED), info->actTag, sec, &angle, NULL, XLTrav_LineAngle); // Convert to degrees. if(info->flags & STF_ACT_TAG_MATERIALMOVE) { info->materialMoveAngle[0] = info->materialMoveAngle[1] = angle / (float) ANGLE_MAX *360; } if(info->flags & STF_ACT_TAG_WIND) { info->windAngle = angle / (float) ANGLE_MAX *360; } } // If there is not already an xsthinker for this sector, create one. if(DD_IterateThinkers(XS_Thinker, findXSThinker, sec)) { // Not created one yet. xsthinker_t* xs = Z_Calloc(sizeof(*xs), PU_MAP, 0); xs->thinker.function = XS_Thinker; DD_ThinkerAdd(&xs->thinker); xs->sector = sec; } } else { XG_Dev("XS_SetSectorType: Sector %i, NORMAL TYPE %i", P_ToIndex(sec), special); // If there is an xsthinker for this, destroy it. DD_IterateThinkers(XS_Thinker, destroyXSThinker, sec); // Free previously allocated XG data. if(xsec->xg) Z_Free(xsec->xg); xsec->xg = NULL; // Just set it, then. Must be a standard sector type... // Mind you, we're not going to spawn any standard flash funcs // or anything. xsec->special = special; } } void XS_Init(void) { if(numsectors > 0) { // Allocate stair builder data. uint i; sector_t *sec; xsector_t *xsec; /* // Clients rely on the server, they don't do XG themselves. if(IS_CLIENT) return; */ for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); P_GetFloatpv(sec, DMU_COLOR, xsec->origRGB); xsec->SP_floororigheight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); xsec->SP_ceilorigheight = P_GetFloatp(sec, DMU_CEILING_HEIGHT); xsec->origLight = P_GetFloatp(sec, DMU_LIGHT_LEVEL); // Initialize the XG data for this sector. XS_SetSectorType(sec, xsec->special); } } } void XS_SectorSound(sector_t *sec, int origin, int snd) { if(!snd) return; XG_Dev("XS_SectorSound: Play Sound ID (%i) in Sector ID (%i)", snd, P_ToIndex(sec)); S_SectorSound(sec, origin, snd); } void XS_MoverStopped(xgplanemover_t *mover, boolean done) { xline_t *origin = P_ToXLine(mover->origin); XG_Dev("XS_MoverStopped: Sector %i (done=%i, origin line=%i)", P_ToIndex(mover->sector), done, mover->origin ? P_ToIndex(mover->origin) : -1); if(done) { if((mover->flags & PMF_ACTIVATE_WHEN_DONE) && mover->origin) { XL_ActivateLine(true, &origin->xg->info, mover->origin, 0, &dummyThing, XLE_AUTO); } if((mover->flags & PMF_DEACTIVATE_WHEN_DONE) && mover->origin) { XL_ActivateLine(false, &origin->xg->info, mover->origin, 0, &dummyThing, XLE_AUTO); } // Remove this thinker. DD_ThinkerRemove((thinker_t *) mover); } else { // Normally we just wait, but if... if((mover->flags & PMF_ACTIVATE_ON_ABORT) && mover->origin) { XL_ActivateLine(true, &origin->xg->info, mover->origin, 0, &dummyThing, XLE_AUTO); } if((mover->flags & PMF_DEACTIVATE_ON_ABORT) && mover->origin) { XL_ActivateLine(false, &origin->xg->info, mover->origin, 0, &dummyThing, XLE_AUTO); } if(mover->flags & (PMF_ACTIVATE_ON_ABORT | PMF_DEACTIVATE_ON_ABORT)) { // Destroy this mover. DD_ThinkerRemove((thinker_t *) mover); } } } /** * A thinker function for plane movers. */ void XS_PlaneMover(xgplanemover_t *mover) { int res, res2; int dir; float ceil = P_GetFloatp(mover->sector, DMU_CEILING_HEIGHT); float floor = P_GetFloatp(mover->sector, DMU_FLOOR_HEIGHT); xsector_t *xsec = P_ToXSector(mover->sector); boolean docrush = (mover->flags & PMF_CRUSH) != 0; boolean follows = (mover->flags & PMF_OTHER_FOLLOWS) != 0; boolean setorig = (mover->flags & PMF_SET_ORIGINAL) != 0; // Play movesound when timer goes to zero. if(mover->timer-- <= 0) { // Clear the wait flag. if(mover->flags & PMF_WAIT) { mover->flags &= ~PMF_WAIT; // Play a sound. XS_SectorSound(mover->sector, SORG_FLOOR + mover->ceiling, mover->startSound); } mover->timer = XG_RandomInt(mover->minInterval, mover->maxInterval); XS_SectorSound(mover->sector, SORG_FLOOR + mover->ceiling, mover->moveSound); } // Are we waiting? if(mover->flags & PMF_WAIT) return; // Determine move direction. if((mover->destination - (mover->ceiling ? ceil : floor)) > 0) dir = 1; // Moving up. else dir = -1; // Moving down. // Do the move. res = T_MovePlane(mover->sector, mover->speed, mover->destination, docrush, mover->ceiling, dir); // Should we update origheight? if(setorig) { xsec->planes[mover->ceiling? PLN_CEILING:PLN_FLOOR].origHeight = P_GetFloatp(mover->sector, mover->ceiling? DMU_CEILING_HEIGHT:DMU_FLOOR_HEIGHT); } if(follows) { float off = (mover->ceiling? floor - ceil : ceil - floor); res2 = T_MovePlane(mover->sector, mover->speed, mover->destination + off, docrush, !mover->ceiling, dir); // Should we update origheight? if(setorig) { xsec->planes[(!mover->ceiling)? PLN_CEILING:PLN_FLOOR].origHeight = P_GetFloatp(mover->sector, (!mover->ceiling)? DMU_CEILING_HEIGHT:DMU_FLOOR_HEIGHT); } if(res2 == crushed) res = crushed; } if(res == pastdest) { // Move has finished. XS_MoverStopped(mover, true); // The move is done. Do end stuff. if(mover->setMaterial) { XS_ChangePlaneMaterial(mover->sector, mover->ceiling, mover->setMaterial, NULL); } if(mover->setSectorType >= 0) { XS_SetSectorType(mover->sector, mover->setSectorType); } // Play sound? XS_SectorSound(mover->sector, SORG_FLOOR + mover->ceiling, mover->endSound); } else if(res == crushed) { if(mover->flags & PMF_CRUSH) { // We're crushing things. mover->speed = mover->crushSpeed; } else { // Make sure both the planes are where we started from. if((!mover->ceiling || follows) && P_GetFloatp(mover->sector, DMU_FLOOR_HEIGHT) != floor) { T_MovePlane(mover->sector, mover->speed, floor, docrush, false, -dir); } if((mover->ceiling || follows) && P_GetFloatp(mover->sector, DMU_CEILING_HEIGHT) != ceil) { T_MovePlane(mover->sector, mover->speed, ceil, docrush, true, -dir); } XS_MoverStopped(mover, false); } } } typedef struct { sector_t* sec; boolean ceiling; } stopplanemoverparams_t; static boolean stopPlaneMover(thinker_t* th, void* context) { stopplanemoverparams_t* params = (stopplanemoverparams_t*) context; xgplanemover_t* mover = (xgplanemover_t *) th; if(mover->sector == params->sec && mover->ceiling == params->ceiling) { XS_MoverStopped(mover, false); DD_ThinkerRemove(th); // Remove it. } return true; // Continue iteration. } /** * Returns a new thinker for handling the specified plane. Removes any * existing thinkers associated with the plane. */ xgplanemover_t *XS_GetPlaneMover(sector_t *sec, boolean ceiling) { xgplanemover_t* mover; stopplanemoverparams_t params; params.sec = sec; params.ceiling = ceiling; DD_IterateThinkers(XS_PlaneMover, stopPlaneMover, ¶ms); // Allocate a new thinker. mover = Z_Calloc(sizeof(*mover), PU_MAP, 0); mover->thinker.function = XS_PlaneMover; DD_ThinkerAdd(&mover->thinker); mover->sector = sec; mover->ceiling = ceiling; return mover; } void XS_ChangePlaneMaterial(sector_t *sector, boolean ceiling, material_t* mat, float *rgb) { XG_Dev("XS_ChangePlaneMaterial: Sector %i, %s, texture %i", P_ToIndex(sector), (ceiling ? "ceiling" : "floor"), P_ToIndex(mat)); if(rgb) XG_Dev("red %g, green %g, blue %g", rgb[0], rgb[1], rgb[2]); if(ceiling) { if(rgb) P_SetFloatpv(sector, DMU_CEILING_COLOR, rgb); if(mat) P_SetPtrp(sector, DMU_CEILING_MATERIAL, mat); } else { if(rgb) P_SetFloatpv(sector, DMU_FLOOR_COLOR, rgb); if(mat) P_SetPtrp(sector, DMU_FLOOR_MATERIAL, mat); } } uint FindMaxOf(int *list, uint num) { uint i, idx = 0; int max = list[0]; for(i = 1; i < num; ++i) { if(list[i] > max) { max = list[i]; idx = i; } } return idx; } uint FindMinOf(int *list, uint num) { uint i, idx = 0; int min = list[0]; for(i = 1; i < num; ++i) { if(list[i] < min) { min = list[i]; idx = i; } } return idx; } int FindNextOf(int *list, int num, int h) { int i, min = 0, idx = -1; for(i = 0; i < num; ++i) { if(list[i] <= h) continue; if(idx < 0 || list[i] < min) { idx = i; min = list[i]; } } return idx; } int FindPrevOf(int *list, int num, int h) { int i, max = 0, idx = -1; for(i = 0; i < num; ++i) { if(list[i] >= h) continue; if(idx < 0 || list[i] > max) { idx = i; max = list[i]; } } return idx; } /** * Really an XL_* function! * * @param part 1=mid, 2=top, 3=bottom. * * @return @c MAXINT if not height n/a. */ int XS_TextureHeight(linedef_t* line, int part) { sidedef_t* side; int snum = 0; int minfloor = 0, maxfloor = 0, maxceil = 0; sector_t* front = P_GetPtrp(line, DMU_FRONT_SECTOR); sector_t* back = P_GetPtrp(line, DMU_BACK_SECTOR); boolean twosided = front && back; material_t* mat; if(part != LWS_MID && !twosided) return DDMAXINT; if(twosided) { int ffloor = P_GetIntp(front, DMU_FLOOR_HEIGHT); int fceil = P_GetIntp(front, DMU_CEILING_HEIGHT); int bfloor = P_GetIntp(back, DMU_FLOOR_HEIGHT); int bceil = P_GetIntp(back, DMU_CEILING_HEIGHT); minfloor = ffloor; maxfloor = bfloor; if(part == LWS_LOWER) snum = 0; if(bfloor < minfloor) { minfloor = bfloor; maxfloor = ffloor; if(part == LWS_LOWER) snum = 1; } maxceil = fceil; if(part == LWS_UPPER) snum = 0; if(bceil > maxceil) { maxceil = bceil; if(part == LWS_UPPER) snum = 1; } } else { if(P_GetPtrp(line, DMU_SIDEDEF0)) snum = 0; else snum = 1; } // Which side are we working with? if(snum == 0) side = P_GetPtrp(line, DMU_SIDEDEF0); else side = P_GetPtrp(line, DMU_SIDEDEF1); // Which section of the wall? switch(part) { case LWS_UPPER: if((mat = P_GetPtrp(side, DMU_TOP_MATERIAL))) return maxceil - P_GetIntp(mat, DMU_HEIGHT); break; case LWS_MID: if((mat = P_GetPtrp(side, DMU_MIDDLE_MATERIAL))) return maxfloor + P_GetIntp(mat, DMU_HEIGHT); break; case LWS_LOWER: if((mat = P_GetPtrp(side, DMU_BOTTOM_MATERIAL))) return minfloor + P_GetIntp(mat, DMU_HEIGHT); break; default: Con_Error("XS_TextureHeight: Invalid wall section %d.", part); } return DDMAXINT; } /** * Returns a pointer to the first sector with the tag. * * NOTE: We cannot use the tagged sector lists here as this can be called * during an iteration at a higher level. Doing so would change the position * of the rover which would affect the other iteration. * * NOTE2: Re-above, obviously that is bad design and should be addressed. */ sector_t *XS_FindTagged(int tag) { uint k; uint foundcount = 0; uint retsectorid = 0; sector_t *sec, *retsector; retsector = NULL; for(k = 0; k < numsectors; ++k) { sec = P_ToPtr(DMU_SECTOR, k); if(P_ToXSector(sec)->tag == tag) { if(xgDev) { if(foundcount == 0) { retsector = sec; retsectorid = k; } } else return sec; foundcount++; } } if(xgDev) { if(foundcount > 1) { XG_Dev("XS_FindTagged: More than one sector exists with this tag (%i)!",tag); XG_Dev(" The sector with the lowest ID (%i) will be used.", retsectorid); } if(retsector) return retsector; } return NULL; } /** * Returns a pointer to the first sector with the specified act tag. */ sector_t *XS_FindActTagged(int tag) { uint k; uint foundcount = 0; uint retsectorid = 0; sector_t *sec, *retsector; xsector_t *xsec; retsector = NULL; for(k = 0; k < numsectors; ++k) { sec = P_ToPtr(DMU_SECTOR, k); xsec = P_ToXSector(sec); if(xsec->xg) { if(xsec->xg->info.actTag == tag) { if(xgDev) { if(foundcount == 0) { retsector = sec; retsectorid = k; } } else { return sec; } foundcount++; } } } if(xgDev) { if(foundcount > 1) { XG_Dev("XS_FindActTagged: More than one sector exists with this ACT tag (%i)!",tag); XG_Dev(" The sector with the lowest ID (%i) will be used.", retsectorid); } if(retsector) return retsector; } return NULL; } #define FSETHF_MIN 0x1 // Get min. If not set, get max. typedef struct findsectorextremaltextureheightparams_s { sector_t *baseSec; byte flags; int part; float val; } findsectorextremalmaterialheightparams_t; int findSectorExtremalMaterialHeight(void *ptr, void *context) { linedef_t *li = (linedef_t*) ptr; findsectorextremalmaterialheightparams_t *params = (findsectorextremalmaterialheightparams_t*) context; float height; // The heights are in real world coordinates. height = XS_TextureHeight(li, params->part); if(params->flags & FSETHF_MIN) { if(height < params->val) params->val = height; } else { if(height > params->val) params->val = height; } return 1; // Continue iteration. } boolean XS_GetPlane(linedef_t* actline, sector_t* sector, int ref, uint* refdata, float* height, material_t** mat, sector_t** planeSector) { material_t* otherMat; float otherHeight; sector_t* otherSec = NULL, *iter; xline_t* xline; char buff[50]; if(refdata) sprintf(buff, " : %i", *refdata); if(xgDev) { XG_Dev("XS_GetPlane: Line %i, sector %i, ref (%s(%i)%s)", actline ? P_ToIndex(actline) : -1, P_ToIndex(sector), SPREFTYPESTR(ref), ref, refdata? buff : "" ); } if(ref == SPREF_NONE || ref == SPREF_SPECIAL) { // No reference to anywhere. return false; } // Init the values to the current sector's floor. if(height) *height = P_GetFloatp(sector, DMU_FLOOR_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(sector, DMU_FLOOR_MATERIAL); if(planeSector) *planeSector = sector; // First try the non-comparative, iterative sprefs. iter = NULL; switch(ref) { case SPREF_SECTOR_TAGGED_FLOOR: case SPREF_SECTOR_TAGGED_CEILING: iter = XS_FindTagged(P_ToXSector(sector)->tag); if(!iter) return false; break; case SPREF_LINE_TAGGED_FLOOR: case SPREF_LINE_TAGGED_CEILING: if(!actline) return false; iter = XS_FindTagged(P_ToXLine(actline)->tag); if(!iter) return false; break; case SPREF_TAGGED_FLOOR: case SPREF_TAGGED_CEILING: if(!refdata) { XG_Dev(" %s IS NOT VALID FOR THIS CLASS PARAMETER!", SPREFTYPESTR(ref)); return false; } iter = XS_FindTagged(*refdata); if(!iter) return false; break; case SPREF_LINE_ACT_TAGGED_FLOOR: case SPREF_LINE_ACT_TAGGED_CEILING: xline = P_ToXLine(actline); if(!xline) return false; if(!xline->xg) { XG_Dev(" ACT LINE IS NOT AN XG LINE!"); return false; } if(!xline->xg->info.actTag) { XG_Dev(" ACT LINE DOES NOT HAVE AN ACT TAG!"); return false; } iter = XS_FindActTagged(xline->xg->info.actTag); if(!iter) return false; break; case SPREF_ACT_TAGGED_FLOOR: case SPREF_ACT_TAGGED_CEILING: if(!refdata) { XG_Dev(" %s IS NOT VALID FOR THIS CLASS PARAMETER!", SPREFTYPESTR(ref)); return false; } iter = XS_FindActTagged(*refdata); if(!iter) return false; break; case SPREF_INDEX_FLOOR: case SPREF_INDEX_CEILING: if(!refdata || *refdata >= numsectors) return false; iter = P_ToPtr(DMU_SECTOR, *refdata); break; default: // No iteration. break; } // Did we find the plane through iteration? if(iter) { if(planeSector) *planeSector = iter; if((ref >= SPREF_SECTOR_TAGGED_FLOOR && ref <= SPREF_INDEX_FLOOR) || ref == SPREF_LINE_ACT_TAGGED_FLOOR) { if(height) *height = P_GetFloatp(iter, DMU_FLOOR_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(iter, DMU_FLOOR_MATERIAL); } else { if(height) *height = P_GetFloatp(iter, DMU_CEILING_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(iter, DMU_CEILING_MATERIAL); } return true; } if(ref == SPREF_MY_FLOOR) { sector_t* frontsector; if(!actline) return false; frontsector = P_GetPtrp(actline, DMU_FRONT_SECTOR); if(!frontsector) return false; // Actline's front floor. if(height) *height = P_GetFloatp(frontsector, DMU_FLOOR_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(frontsector, DMU_FLOOR_MATERIAL); if(planeSector) *planeSector = frontsector; return true; } if(ref == SPREF_BACK_FLOOR) { sector_t* backsector; if(!actline) return false; backsector = P_GetPtrp(actline, DMU_BACK_SECTOR); if(!backsector) return false; // Actline's back floor. if(height) *height = P_GetFloatp(backsector, DMU_FLOOR_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(backsector, DMU_FLOOR_MATERIAL); if(planeSector) *planeSector = backsector; return true; } if(ref == SPREF_MY_CEILING) { sector_t* frontsector; if(!actline) return false; frontsector = P_GetPtrp(actline, DMU_FRONT_SECTOR); if(!frontsector) return false; // Actline's front ceiling. if(height) *height = P_GetFloatp(frontsector, DMU_CEILING_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(frontsector, DMU_CEILING_MATERIAL); if(planeSector) *planeSector = frontsector; return true; } if(ref == SPREF_BACK_CEILING) { sector_t* backsector; if(!actline) return false; backsector = P_GetPtrp(actline, DMU_BACK_SECTOR); if(!backsector) return false; // Actline's back ceiling. if(height) *height = P_GetFloatp(backsector, DMU_CEILING_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(backsector, DMU_CEILING_MATERIAL); if(planeSector) *planeSector = backsector; return true; } if(ref == SPREF_ORIGINAL_FLOOR) { if(height) *height = P_ToXSector(sector)->SP_floororigheight; if(mat) *mat = (material_t*) P_GetPtrp(sector, DMU_FLOOR_MATERIAL); return true; } if(ref == SPREF_ORIGINAL_CEILING) { if(height) *height = P_ToXSector(sector)->SP_ceilorigheight; if(mat) *mat = (material_t*) P_GetPtrp(sector, DMU_CEILING_MATERIAL); return true; } if(ref == SPREF_CURRENT_FLOOR) { if(height) *height = P_GetFloatp(sector, DMU_FLOOR_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(sector, DMU_FLOOR_MATERIAL); return true; } if(ref == SPREF_CURRENT_CEILING) { if(height) *height = P_GetFloatp(sector, DMU_CEILING_HEIGHT); if(mat) *mat = (material_t*) P_GetPtrp(sector, DMU_CEILING_MATERIAL); return true; } // Texture height targets? if(ref >= SPREF_MIN_BOTTOM_MATERIAL && ref <= SPREF_MAX_TOP_MATERIAL) { int part; boolean findMin; findsectorextremalmaterialheightparams_t params; // Which part of the wall are we looking at? if(ref == SPREF_MIN_MID_MATERIAL || ref == SPREF_MAX_MID_MATERIAL) part = LWS_MID; else if(ref == SPREF_MIN_TOP_MATERIAL || ref == SPREF_MAX_TOP_MATERIAL) part = LWS_UPPER; else // Then it's the bottom. part = LWS_LOWER; if(ref >= SPREF_MIN_BOTTOM_MATERIAL && ref <= SPREF_MIN_TOP_MATERIAL) findMin = true; else findMin = false; params.baseSec = sector; params.part = part; params.flags = (findMin? FSETHF_MIN : 0); params.val = (findMin? DDMAXFLOAT : DDMINFLOAT); P_Iteratep(sector, DMU_LINEDEF, ¶ms, findSectorExtremalMaterialHeight); if(height) *height = params.val; return true; } // Get the right height and pic. if(ref == SPREF_HIGHEST_CEILING) { otherSec = P_FindSectorSurroundingHighestCeiling(sector, DDMINFLOAT, &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_CEILING_MATERIAL); } else if(ref == SPREF_HIGHEST_FLOOR) { otherSec = P_FindSectorSurroundingHighestFloor(sector, DDMINFLOAT, &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_CEILING_MATERIAL); } else if(ref == SPREF_LOWEST_CEILING) { otherSec = P_FindSectorSurroundingLowestCeiling(sector, DDMAXFLOAT, &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_CEILING_MATERIAL); } else if(ref == SPREF_LOWEST_FLOOR) { otherSec = P_FindSectorSurroundingLowestFloor(sector, DDMAXFLOAT, &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_FLOOR_MATERIAL); } else if(ref == SPREF_NEXT_HIGHEST_CEILING) { otherSec = P_FindSectorSurroundingNextHighestCeiling(sector, P_GetFloatp(sector, DMU_CEILING_HEIGHT), &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_CEILING_MATERIAL); } else if(ref == SPREF_NEXT_HIGHEST_FLOOR) { otherSec = P_FindSectorSurroundingNextHighestFloor(sector, P_GetFloatp(sector, DMU_FLOOR_HEIGHT), &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_FLOOR_MATERIAL); } else if(ref == SPREF_NEXT_LOWEST_CEILING) { otherSec = P_FindSectorSurroundingNextLowestCeiling(sector, P_GetFloatp(sector, DMU_CEILING_HEIGHT), &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_CEILING_MATERIAL); } else if(ref == SPREF_NEXT_LOWEST_FLOOR) { otherSec = P_FindSectorSurroundingNextLowestFloor(sector, P_GetFloatp(sector, DMU_FLOOR_HEIGHT), &otherHeight); if(otherSec) otherMat = P_GetPtrp(otherSec, DMU_FLOOR_MATERIAL); } // The requested plane was not found. if(!otherSec) return false; // Set the values. if(height) *height = otherHeight; if(mat) *mat = otherMat; if(planeSector) *planeSector = otherSec; return true; } /** * DJS - Why find the highest??? Surely unlogical to mod authors. * IMO if a user references multiple sectors, the one with the lowest ID * should be chosen (the same way it works for FIND(act)TAGGED). If that * happens to be zero - so be it. */ int C_DECL XSTrav_HighestSectorType(sector_t *sec, boolean ceiling, void *context, void *context2, mobj_t *activator) { int *type = context2; xsector_t *xsec = P_ToXSector(sec); if(xsec->special > *type) *type = xsec->special; return true; // Keep looking... } void XS_InitMovePlane(linedef_t *line) { xline_t *xline = P_ToXLine(line); // fdata keeps track of wait time. xline->xg->fdata = xline->xg->info.fparm[5]; xline->xg->idata = true; // Play sound. }; int C_DECL XSTrav_MovePlane(sector_t *sector, boolean ceiling, void *context, void *context2, mobj_t *activator) { linedef_t* line = (linedef_t *) context; linetype_t* info = (linetype_t *) context2; xgplanemover_t* mover; int st; material_t* mat; xline_t* xline = P_ToXLine(line); boolean playsound; playsound = xline->xg->idata; XG_Dev("XSTrav_MovePlane: Sector %i (by line %i of type %i)", P_ToIndex(sector), P_ToIndex(line), info->id); // i2: destination type (zero, relative to current, surrounding // highest/lowest floor/ceiling) // i3: flags (PMF_*) // i4: start sound // i5: end sound // i6: move sound // i7: start material origin (uses same ids as i2) // i8: start material index (used with PMD_ZERO). // i9: end material origin (uses same ids as i2) // i10: end material (used with PMD_ZERO) // i11 + i12: (plane ref) start sector type // i13 + i14: (plane ref) end sector type // f0: move speed (units per tic). // f1: crush speed (units per tic). // f2: destination offset // f3: move sound min interval (seconds) // f4: move sound max interval (seconds) // f5: time to wait before starting the move // f6: wait increment for each plane that gets moved mover = XS_GetPlaneMover(sector, ceiling); mover->origin = line; // Setup the thinker and add it to the list. { float temp = mover->destination; XS_GetPlane(line, sector, info->iparm[2], NULL, &temp, 0, 0); mover->destination = temp + info->fparm[2]; } mover->speed = info->fparm[0]; mover->crushSpeed = info->fparm[1]; mover->minInterval = FLT2TIC(info->fparm[3]); mover->maxInterval = FLT2TIC(info->fparm[4]); mover->flags = info->iparm[3]; mover->endSound = playsound ? info->iparm[5] : 0; mover->moveSound = playsound ? info->iparm[6] : 0; // Change texture at end? if(info->iparm[9] == SPREF_NONE || info->iparm[9] == SPREF_SPECIAL) mover->setMaterial = P_ToPtr(DMU_MATERIAL, info->iparm[10]); else { if(!XS_GetPlane(line, sector, info->iparm[9], NULL, 0, &mover->setMaterial, 0)) XG_Dev(" Couldn't find suitable material to set when move ends!"); } // Init timer. mover->timer = XG_RandomInt(mover->minInterval, mover->maxInterval); // Do we need to wait before starting the move? if(xline->xg->fdata > 0) { mover->timer = FLT2TIC(xline->xg->fdata); mover->flags |= PMF_WAIT; } // Increment wait time. xline->xg->fdata += info->fparm[6]; // Do start stuff. Play sound? if(playsound) XS_SectorSound(sector, SORG_FLOOR + ceiling, info->iparm[4]); // Change texture at start? if(info->iparm[7] == SPREF_NONE || info->iparm[7] == SPREF_SPECIAL) mat = P_ToPtr(DMU_MATERIAL, info->iparm[8]); else { if(!XS_GetPlane(line, sector, info->iparm[7], NULL, 0, &mat, 0)) XG_Dev(" Couldn't find suitable material to set when move starts!"); } if(mat) XS_ChangePlaneMaterial(sector, ceiling, mat, NULL); // Should we play no more sounds? if(info->iparm[3] & PMF_ONE_SOUND_ONLY) { // Sound was played only for the first plane. xline->xg->idata = false; } // Change sector type right now? st = info->iparm[12]; if(info->iparm[11] != LPREF_NONE) { if(XL_TraversePlanes (line, info->iparm[11], info->iparm[12], 0, &st, false, 0, XSTrav_HighestSectorType)) { XS_SetSectorType(sector, st); } else XG_Dev(" SECTOR TYPE NOT SET (nothing referenced)"); } // Change sector type in the end of move? st = info->iparm[14]; if(info->iparm[13] != LPREF_NONE) { if(XL_TraversePlanes (line, info->iparm[13], info->iparm[14], 0, &st, false, 0, XSTrav_HighestSectorType)) { // OK, found one or more. mover->setSectorType = st; } else { XG_Dev(" SECTOR TYPE WON'T BE CHANGED AT END (nothing referenced)"); mover->setSectorType = -1; } } else mover->setSectorType = -1; return true; // Keep looking... } void XS_InitStairBuilder(linedef_t *line) { uint i; for(i = 0; i < numsectors; ++i) P_GetXSector(i)->blFlags = 0; } boolean XS_DoBuild(sector_t *sector, boolean ceiling, linedef_t *origin, linetype_t *info, uint stepcount) { static float firstheight; float waittime; xsector_t *xsec; xgplanemover_t *mover; if(!sector) return false; xsec = P_ToXSector(sector); // Make sure each sector is only processed once. if(xsec->blFlags & BL_BUILT) return false; // Already built this one! xsec->blFlags |= BL_WAS_BUILT; // Create a new mover for the plane. mover = XS_GetPlaneMover(sector, ceiling); mover->origin = origin; // Setup the mover. if(stepcount != 0) firstheight = P_GetFloatp(sector, (ceiling? DMU_CEILING_HEIGHT:DMU_FLOOR_HEIGHT)); mover->destination = firstheight + (stepcount + 1) * info->fparm[1]; mover->speed = (info->fparm[0] + stepcount * info->fparm[6]); if(mover->speed <= 0) mover->speed = 1 / 1000; mover->minInterval = FLT2TIC(info->fparm[4]); mover->maxInterval = FLT2TIC(info->fparm[5]); if(info->iparm[8]) mover->flags = PMF_CRUSH; mover->endSound = info->iparm[6]; mover->moveSound = info->iparm[7]; // Wait before starting? waittime = info->fparm[2] + info->fparm[3] * stepcount; if(waittime > 0) { mover->timer = FLT2TIC(waittime); mover->flags |= PMF_WAIT; // Play start sound when waiting ends. mover->startSound = info->iparm[5]; } else { mover->timer = XG_RandomInt(mover->minInterval, mover->maxInterval); // Play step start sound immediately. XS_SectorSound(sector, SORG_FLOOR + ceiling, info->iparm[5]); } // Do start stuff. Play sound? if(stepcount != 0) { // Start building start sound. XS_SectorSound(sector, SORG_FLOOR + ceiling, info->iparm[4]); } return true; // Building has begun! } #define F_MATERIALSTOP 0x1 #define F_CEILING 0x2 typedef struct spreadbuildparams_s { sector_t* baseSec; material_t* baseMat; byte flags; linedef_t* origin; linetype_t* info; int stepCount; size_t spreaded; } spreadbuildparams_t; int spreadBuild(void *ptr, void *context) { linedef_t *li = (linedef_t*) ptr; spreadbuildparams_t *params = (spreadbuildparams_t*) context; sector_t *frontSec, *backSec; frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR); if(!frontSec || frontSec != params->baseSec) return 1; backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(!backSec) return 1; if(params->flags & F_MATERIALSTOP) { // Planepic must match. if(params->flags & F_CEILING) { if(P_GetPtrp(params->baseSec, DMU_CEILING_MATERIAL) != params->baseMat) return 1; } else { if(P_GetPtrp(params->baseSec, DMU_FLOOR_MATERIAL) != params->baseMat) return 1; } } // Don't spread to sectors which have already spreaded. if(P_ToXSector(backSec)->blFlags & BL_SPREADED) return 1; // Build backsector. XS_DoBuild(backSec, ((params->flags & F_CEILING)? true : false), params->origin, params->info, params->stepCount); params->spreaded++; return 1; // Continue iteration. } static void markBuiltSectors(void) { uint i; // Mark the sectors of the last step as processed. for(i = 0; i < numsectors; ++i) { xsector_t* xsec = P_GetXSector(i); if(xsec->blFlags & BL_WAS_BUILT) { xsec->blFlags &= ~BL_WAS_BUILT; xsec->blFlags |= BL_BUILT; } } } static boolean spreadBuildToNeighborAll(linedef_t* origin, linetype_t* info, boolean picstop, boolean ceiling, material_t* myMat, int stepCount) { uint i; boolean result = false; spreadbuildparams_t params; params.baseMat = myMat; params.info = info; params.origin = origin; params.stepCount = stepCount; params.flags = 0; if(picstop) params.flags |= F_MATERIALSTOP; if(ceiling) params.flags |= F_CEILING; for(i = 0; i < numsectors; ++i) { sector_t* sec; xsector_t* xsec = P_GetXSector(i); // Only spread from built sectors (spread only once!). if(!(xsec->blFlags & BL_BUILT) || xsec->blFlags & BL_SPREADED) continue; xsec->blFlags |= BL_SPREADED; // Any 2-sided lines facing the right way? sec = P_ToPtr(DMU_SECTOR, i); params.baseSec = sec; params.spreaded = 0; P_Iteratep(sec, DMU_LINEDEF, ¶ms, spreadBuild); if(params.spreaded > 0) result = true; } return result; } #define F_MATERIALSTOP 0x1 #define F_CEILING 0x2 typedef struct findbuildneighborparams_s { sector_t* baseSec; material_t* baseMat; byte flags; linedef_t* origin; linetype_t* info; int stepCount; uint foundIDX; sector_t* foundSec; } findbuildneighborparams_t; int findBuildNeighbor(void* ptr, void* context) { linedef_t* li = (linedef_t*) ptr; findbuildneighborparams_t *params = (findbuildneighborparams_t*) context; sector_t* frontSec, *backSec; uint idx; frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR); if(!frontSec || frontSec != params->baseSec) return 1; backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(!backSec) return 1; if(params->flags & F_MATERIALSTOP) { // Planepic must match. if(params->flags & F_CEILING) { if(P_GetPtrp(params->baseSec, DMU_CEILING_MATERIAL) != params->baseMat) return 1; } else { if(P_GetPtrp(params->baseSec, DMU_FLOOR_MATERIAL) != params->baseMat) return 1; } } // Don't spread to sectors which have already spreaded. if(P_ToXSector(backSec)->blFlags & BL_SPREADED) return 1; // We need the lowest line number. idx = P_ToIndex(li); if(idx < params->foundIDX) { params->foundSec = backSec; params->foundIDX = idx; } return 1; // Continue iteration. } boolean spreadBuildToNeighborLowestIDX(linedef_t* origin, linetype_t* info, boolean picstop, boolean ceiling, material_t* myMat, int stepcount, sector_t* foundSec) { uint i; boolean result = false; findbuildneighborparams_t params; params.baseMat = myMat; params.info = info; params.origin = origin; params.stepCount = stepcount; params.flags = 0; if(picstop) params.flags |= F_MATERIALSTOP; if(ceiling) params.flags |= F_CEILING; for(i = 0; i < numsectors; ++i) { sector_t* sec; xsector_t* xsec = P_GetXSector(i); // Only spread from built sectors (spread only once!). if(!(xsec->blFlags & BL_BUILT) || xsec->blFlags & BL_SPREADED) continue; xsec->blFlags |= BL_SPREADED; // Any 2-sided lines facing the right way? sec = P_ToPtr(DMU_SECTOR, i); params.baseSec = sec; params.foundIDX = numlines; params.foundSec = NULL; P_Iteratep(sec, DMU_LINEDEF, ¶ms, findBuildNeighbor); if(params.foundSec) { result = true; foundSec = params.foundSec; } } return result; } int C_DECL XSTrav_BuildStairs(sector_t* sector, boolean ceiling, void* context, void* context2, mobj_t* activator) { uint stepCount = 0; linedef_t* origin = (linedef_t *) context; linetype_t* info = context2; sector_t* foundSec = NULL; boolean picstop = info->iparm[2] != 0; boolean spread = info->iparm[3] != 0; material_t* myMat; XG_Dev("XSTrav_BuildStairs: Sector %i, %s", P_ToIndex(sector), ceiling ? "ceiling" : "floor"); // i2: (true/false) stop when texture changes // i3: (true/false) spread build? myMat = ceiling ? P_GetPtrp(sector, DMU_CEILING_MATERIAL) : P_GetPtrp(sector, DMU_FLOOR_MATERIAL); // Apply to first step. XS_DoBuild(sector, ceiling, origin, info, 0); stepCount++; if(spread) { boolean found; do { markBuiltSectors(); // Scan the sectors for the next ones to spread to. found = spreadBuildToNeighborAll(origin, info, picstop, ceiling, myMat, stepCount); stepCount++; } while(found); } else { boolean found; do { found = false; markBuiltSectors(); // Scan the sectors for the next ones to spread to. if(spreadBuildToNeighborLowestIDX(origin, info, picstop, ceiling, myMat, stepCount, foundSec)) { XS_DoBuild(foundSec, ceiling, origin, info, stepCount); found = true; } stepCount++; } while(found); } return true; // Continue searching for planes... } int C_DECL XSTrav_SectorSound(struct sector_s *sec, boolean ceiling, void *context, void *context2, mobj_t *activator) { int originid; linetype_t *info = context2; if(info->iparm[3]) originid = info->iparm[3]; else originid = SORG_CENTER; XS_SectorSound(sec, originid, info->iparm[2]); return true; } int C_DECL XSTrav_PlaneMaterial(struct sector_s *sec, boolean ceiling, void *context, void *context2, mobj_t *activator) { linedef_t* line = (linedef_t *) context; linetype_t* info = context2; material_t* mat; float rgb[3]; // i2: (spref) material origin // i3: texture number (flat), used with SPREF_NONE // i4: red // i5: green // i6: blue if(info->iparm[2] == SPREF_NONE) { mat = P_ToPtr(DMU_MATERIAL, info->iparm[3]); } else { if(!XS_GetPlane(line, sec, info->iparm[2], NULL, 0, &mat, 0)) XG_Dev("XSTrav_PlaneMaterial: Sector %i, couldn't find suitable material!", P_ToIndex(sec)); } rgb[0] = MINMAX_OF(0.f, info->iparm[4] / 255.f, 1.f); rgb[1] = MINMAX_OF(0.f, info->iparm[5] / 255.f, 1.f); rgb[2] = MINMAX_OF(0.f, info->iparm[6] / 255.f, 1.f); // Set the texture. XS_ChangePlaneMaterial(sec, ceiling, mat, rgb); return true; } int C_DECL XSTrav_SectorType(struct sector_s* sec, boolean ceiling, void* context, void* context2, mobj_t* activator) { linetype_t* info = context2; XS_SetSectorType(sec, info->iparm[2]); return true; } int C_DECL XSTrav_SectorLight(sector_t* sector, boolean ceiling, void* context, void* context2, mobj_t* activator) { linedef_t* line = (linedef_t *) context; linetype_t* info = context2; int num, i = 0; float usergb[3]; float lightLevel; // i2: (true/false) set level // i3: (true/false) set RGB // i4: source of light level (SSREF*) // i5: offset // i6: source of RGB (none, my, original) // i7: red offset // i8: green offset // i9: blue offset if(info->iparm[2]) { switch(info->iparm[4]) { case LIGHTREF_NONE: lightLevel = 0; break; case LIGHTREF_MY: { sector_t *frontSec = P_GetPtrp(line, DMU_FRONT_SECTOR); lightLevel = P_GetFloatp(frontSec, DMU_LIGHT_LEVEL); } break; case LIGHTREF_BACK: { sector_t *backSec = P_GetPtrp(line, DMU_BACK_SECTOR); if(backSec) lightLevel = P_GetFloatp(backSec, DMU_LIGHT_LEVEL); } break; case LIGHTREF_ORIGINAL: lightLevel = P_ToXSector(sector)->origLight; break; case LIGHTREF_HIGHEST: P_FindSectorSurroundingHighestLight(sector, &lightLevel); break; case LIGHTREF_LOWEST: P_FindSectorSurroundingLowestLight(sector, &lightLevel); break; case LIGHTREF_NEXT_HIGHEST: { float currentLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); P_FindSectorSurroundingNextHighestLight(sector, currentLevel, &lightLevel); if(lightLevel < currentLevel) lightLevel = currentLevel; } break; case LIGHTREF_NEXT_LOWEST: { float currentLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); P_FindSectorSurroundingNextLowestLight(sector, currentLevel, &lightLevel); if(lightLevel > currentLevel) lightLevel = currentLevel; } break; default: break; } // Add the offset. lightLevel += (float) info->iparm[5] / 255.f; // Clamp the result. if(lightLevel < 0) lightLevel = 0; if(lightLevel > 1) lightLevel = 1; // Set the value. P_SetFloatp(sector, DMU_LIGHT_LEVEL, lightLevel); } if(info->iparm[3]) { switch(info->iparm[6]) { case LIGHTREF_MY: { sector_t* sector = P_GetPtrp(line, DMU_FRONT_SECTOR); P_GetFloatpv(sector, DMU_COLOR, usergb); break; } case LIGHTREF_BACK: { sector_t* sector = P_GetPtrp(line, DMU_BACK_SECTOR); if(sector) P_GetFloatpv(sector, DMU_COLOR, usergb); break; } case LIGHTREF_ORIGINAL: memcpy(usergb, P_ToXSector(sector)->origRGB, sizeof(float) * 3); break; default: memset(usergb, 0, sizeof(usergb)); break; } for(num = 0; num < 3; ++num) { float f = usergb[num] + (float) info->iparm[7 + num] / 255.f; if(f < 0) f = 0; if(f > 1) f = 1; P_SetFloatp(sector, TO_DMU_COLOR(num), f); } } return true; } int C_DECL XSTrav_MimicSector(sector_t *sector, boolean ceiling, void *context, void *context2, mobj_t *activator) { linedef_t *line = (linedef_t *) context; linetype_t *info = context2; sector_t *from = NULL; uint refdata; // Set the spref data parameter (tag or index). switch(info->iparm[2]) { case SPREF_TAGGED_FLOOR: case SPREF_TAGGED_CEILING: case SPREF_INDEX_FLOOR: case SPREF_INDEX_CEILING: case SPREF_ACT_TAGGED_FLOOR: case SPREF_ACT_TAGGED_CEILING: if(info->iparm[3] >= 0) refdata = info->iparm[3]; break; case SPREF_LINE_ACT_TAGGED_FLOOR: case SPREF_LINE_ACT_TAGGED_CEILING: if(info->actTag >= 0); refdata = info->actTag; break; default: refdata = 0; break; } // If can't apply to a sector, just skip it. if(!XS_GetPlane(line, sector, info->iparm[2], &refdata, 0, 0, &from)) { XG_Dev("XSTrav_MimicSector: No suitable neighbor " "for %i.\n", P_ToIndex(sector)); return true; } // Mimicing itself is pointless. if(from == sector) return true; XG_Dev("XSTrav_MimicSector: Sector %i mimicking sector %i", P_ToIndex(sector), P_ToIndex(from)); // Copy the properties of the target sector. P_CopySector(sector, from); P_ChangeSector(sector, false); // Copy type as well. XS_SetSectorType(sector, P_ToXSector(from)->special); if(P_ToXSector(from)->xg) memcpy(P_ToXSector(sector)->xg, P_ToXSector(from)->xg, sizeof(xgsector_t)); return true; } int C_DECL XSTrav_Teleport(sector_t* sector, boolean ceiling, void* context, void* context2, mobj_t* thing) { mobj_t* mo = NULL; boolean ok = false; linetype_t* info = context2; // Don't teleport things marked noteleport! if(thing->flags2 & MF2_NOTELEPORT) { XG_Dev("XSTrav_Teleport: Activator is unteleportable (THING type %i)", thing->type); return false; } for(mo = P_GetPtrp(sector, DMT_MOBJS); mo; mo = mo->sNext) { thinker_t *th = (thinker_t*) mo; // Not a mobj. if(th->function != P_MobjThinker) continue; // Not a teleportman. if(mo->type != MT_TELEPORTMAN) continue; ok = true; break; } if(ok) { // We can teleport. mobj_t* flash; unsigned an; float oldpos[3]; float thfloorz, thceilz; float aboveFloor, fogDelta = 0; angle_t oldAngle; XG_Dev("XSTrav_Teleport: Sector %i, %s, %s%s", P_ToIndex(sector), info->iparm[2]? "No Flash":"", info->iparm[3]? "Play Sound":"Silent", info->iparm[4]? " Stomp" : ""); if(!P_TeleportMove(thing, mo->pos[VX], mo->pos[VY], (info->iparm[4] > 0? 1 : 0))) { XG_Dev("XSTrav_Teleport: No free space at teleport exit. Aborting teleport..."); return false; } memcpy(oldpos, thing->pos, sizeof(thing->pos)); oldAngle = thing->angle; thfloorz = P_GetFloatp(thing->subsector, DMU_FLOOR_HEIGHT); thceilz = P_GetFloatp(thing->subsector, DMU_CEILING_HEIGHT); aboveFloor = thing->pos[VZ] - thfloorz; // Players get special consideration if(thing->player) { if((thing->player->plr->mo->flags2 & MF2_FLY) && aboveFloor) { thing->pos[VZ] = thfloorz + aboveFloor; if(thing->pos[VZ] + thing->height > thceilz) { thing->pos[VZ] = thceilz - thing->height; } thing->player->viewZ = thing->pos[VZ] + thing->player->viewHeight; } else { thing->pos[VZ] = thfloorz; thing->player->viewZ = thing->pos[VZ] + thing->player->viewHeight; thing->dPlayer->lookDir = 0; /* $unifiedangles */ } #if __JHERETIC__ if(!thing->player->powers[PT_WEAPONLEVEL2]) #endif { // Freeze player for about .5 sec thing->reactionTime = 18; } //thing->dPlayer->clAngle = thing->angle; /* $unifiedangles */ thing->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; } #if __JHERETIC__ else if(thing->flags & MF_MISSILE) { thing->pos[VZ] = thfloorz + aboveFloor; if(thing->pos[VZ] + thing->height > thceilz) { thing->pos[VZ] = thceilz - thing->height; } } #endif else { thing->pos[VZ] = thfloorz; } // Spawn flash at the old position? if(!info->iparm[2]) { // Old position #if __JHERETIC__ fogDelta = ((thing->flags & MF_MISSILE)? 0 : TELEFOGHEIGHT); #endif if((flash = P_SpawnMobj3f(MT_TFOG, oldpos[VX], oldpos[VY], oldpos[VZ] + fogDelta, oldAngle + ANG180, 0))) { // Play a sound? if(info->iparm[3]) S_StartSound(info->iparm[3], flash); } } an = mo->angle >> ANGLETOFINESHIFT; // Spawn flash at the new position? if(!info->iparm[2]) { // New position if((flash = P_SpawnMobj3f(MT_TFOG, mo->pos[VX] + 20 * FIX2FLT(finecosine[an]), mo->pos[VY] + 20 * FIX2FLT(finesine[an]), mo->pos[VZ] + fogDelta, mo->angle, 0))) { // Play a sound? if(info->iparm[3]) S_StartSound(info->iparm[3], flash); } } // Adjust the angle to match that of the teleporter exit thing->angle = mo->angle; // Have we teleported from/to a sector with a non-solid floor? if(thing->flags2 & MF2_FLOORCLIP) { thing->floorClip = 0; if(thing->pos[VZ] == P_GetFloatp(thing->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(thing); if(tt->flags & TTF_FLOORCLIP) { thing->floorClip = 10; } } } if(thing->flags & MF_MISSILE) { an >>= ANGLETOFINESHIFT; thing->mom[MX] = thing->info->speed * FIX2FLT(finecosine[an]); thing->mom[MY] = thing->info->speed * FIX2FLT(finesine[an]); } else { thing->mom[MX] = thing->mom[MY] = thing->mom[MZ] = 0; } } else { // Keep looking, there may be another referenced sector we could // teleport to... XG_Dev("XSTrav_Teleport: No teleport exit in referenced sector (ID %i)." " Continuing search...", P_ToIndex(sector)); return true; } return false; // Only do this once. } int XF_FindRewindMarker(char *func, int pos) { while(pos > 0 && func[pos] != '>') pos--; if(func[pos] == '>') pos++; return pos; } int XF_GetCount(function_t * fn, int *pos) { char *end; int count; count = strtol(fn->func + *pos, &end, 10); *pos = end - fn->func; return count; } float XF_GetValue(function_t * fn, int pos) { int ch; if(fn->func[pos] == '/' || fn->func[pos] == '%') { // Exact value. return strtod(fn->func + pos + 1, 0); } ch = tolower(fn->func[pos]); // A=0, Z=25. return (ch - 'a') / 25.0f; } /** * Returns the position of the next value. * Repeat counting is handled here. * Poke should be true only if fn->pos is really about to move. */ int XF_FindNextPos(function_t *fn, int pos, boolean poke, sector_t *sec) { int startpos = pos; int c; char *ptr; if(fn->repeat > 0) { if(poke) fn->repeat--; return pos; } // Skip current. if(fn->func[pos] == '/' || fn->func[pos] == '%') { strtod(fn->func + pos + 1, &ptr); pos = ptr - fn->func; // Go to the end. } else { // It's just a normal character [a-z,A-Z]. pos++; } while(pos != startpos && fn->func[pos]) { // Check for various special characters. if(isdigit(fn->func[pos])) { // A repeat! // Move pos to the value to be repeated and set repeat counter. c = XF_GetCount(fn, &pos) - 1; if(poke) fn->repeat = c; return pos; } if(fn->func[pos] == '!') { // Chain event. pos++; c = XF_GetCount(fn, &pos); if(poke) { // Sector funcs don't have activators. XS_DoChain(sec, XSCE_FUNCTION, c, NULL); } continue; } if(fn->func[pos] == '#') { // Set timer. pos++; c = XF_GetCount(fn, &pos); if(poke) { fn->timer = 0; fn->maxTimer = c; } continue; } if(fn->func[pos] == '?') { // Random timer. pos++; c = XF_GetCount(fn, &pos); if(poke) { fn->timer = 0; fn->maxTimer = XG_RandomInt(0, c); } continue; } if(fn->func[pos] == '<') { // Rewind. pos = XF_FindRewindMarker(fn->func, pos); continue; } if(poke) { if(islower(fn->func[pos]) || fn->func[pos] == '/') { int next = XF_FindNextPos(fn, pos, false, sec); if(fn->func[next] == '.') { pos++; continue; } break; } } else if(fn->func[pos] == '.') { break; } // Is it a value, then? if(isalpha(fn->func[pos]) || fn->func[pos] == '/' || fn->func[pos] == '%') break; // A bad character, skip it. pos++; } return pos; } /** * Tick the function, update value. */ void XF_Ticker(function_t* fn, sector_t* sec) { int next; float inter; // Store the previous value of the function. fn->oldValue = fn->value; // Is there a function? if(!ISFUNC(fn) || fn->link) return; // Increment time. if(fn->timer++ >= fn->maxTimer) { fn->timer = 0; fn->maxTimer = XG_RandomInt(fn->minInterval, fn->maxInterval); // Advance to next pos. fn->pos = XF_FindNextPos(fn, fn->pos, true, sec); } /** * Syntax: * * abcdefghijlkmnopqrstuvwxyz (26) * * az.< (fade from 0 to 1, break interpolation and repeat) * [note that AZ.AZ is the same as AZAZ] * [also note that a.z is the same as z] * az.>mz< (fade from 0 to 1, break, repeat fade from 0.5 to 1 to 0.5) * 10a10z is the same as aaaaaaaaaazzzzzzzzzz * aB or Ba do not interpolate * zaN (interpolate from 1 to 0, wait at 0, stay at N) * za.N (interpolate from 1 to 0, skip to N) * 1A is the same as A */ // Stop? if(!fn->func[fn->pos]) return; if(isupper(fn->func[fn->pos]) || fn->func[fn->pos] == '%') { // No interpolation. fn->value = XF_GetValue(fn, fn->pos); } else { inter = 0; next = XF_FindNextPos(fn, fn->pos, false, sec); if(islower(fn->func[next]) || fn->func[next] == '/') { if(fn->maxTimer) inter = fn->timer / (float) fn->maxTimer; } fn->value = (1 - inter) * XF_GetValue(fn, fn->pos) + inter * XF_GetValue(fn, next); } // Scale and offset. fn->value = fn->value * fn->scale + fn->offset; } void XS_UpdatePlanes(sector_t* sec) { int i; xgsector_t* xg; function_t* fn; boolean docrush; xg = P_ToXSector(sec)->xg; docrush = (xg->info.flags & STF_CRUSH) != 0; // Update floor. fn = &xg->plane[XGSP_FLOOR]; if(UPDFUNC(fn)) { // Changed. // How different? i = fn->value - P_GetFloatp(sec, DMU_FLOOR_HEIGHT); if(i) { // Move the floor plane accordingly. T_MovePlane(sec, abs(i), fn->value, docrush, 0, SIGN(i)); } } // Update celing. fn = &xg->plane[XGSP_CEILING]; if(UPDFUNC(fn)) { // Changed. // How different? i = fn->value - P_GetFloatp(sec, DMU_CEILING_HEIGHT); if(i) { // Move the ceiling accordingly. T_MovePlane(sec, abs(i), fn->value, docrush, 1, SIGN(i)); } } } void XS_UpdateLight(sector_t* sec) { int i; float c, lightlevel; xgsector_t* xg; function_t* fn; xg = P_ToXSector(sec)->xg; // Light intensity. fn = &xg->light; if(UPDFUNC(fn)) { // Changed. lightlevel = MINMAX_OF(0, fn->value / 255.f, 1); P_SetFloatp(sec, DMU_LIGHT_LEVEL, lightlevel); } // Red, green and blue. for(i = 0; i < 3; ++i) { fn = &xg->rgb[i]; if(!UPDFUNC(fn)) continue; // Changed. c = MINMAX_OF(0, fn->value / 255.f, 1); P_SetFloatp(sec, TO_DMU_COLOR(i), c); } } void XS_DoChain(sector_t *sec, int ch, int activating, void *act_thing) { xgsector_t *xg; sectortype_t *info; float flevtime = TIC2FLT(mapTime); linedef_t *dummyLine; xline_t *xdummyLine; linetype_t *ltype; xg = P_ToXSector(sec)->xg; info = &xg->info; if(ch < XSCE_NUM_CHAINS) { // How's the counter? if(!info->count[ch]) return; // How's the time? if(flevtime < info->start[ch] || (info->end[ch] > 0 && flevtime > info->end[ch])) return; // Not operating at this time. // Time to try the chain. Reset timer. xg->chainTimer[ch] = XG_RandomInt(FLT2TIC(info->interval[ch][0]), FLT2TIC(info->interval[ch][1])); } // Prepare the dummy line to use for the event. dummyLine = P_AllocDummyLine(); xdummyLine = P_ToXLine(dummyLine); xdummyLine->xg = Z_Calloc(sizeof(xgline_t), PU_MAP, 0); P_SetPtrp(dummyLine, DMU_FRONT_SECTOR, sec); xdummyLine->special = (ch == XSCE_FUNCTION ? activating : info->chain[ch]); xdummyLine->tag = P_ToXSector(sec)->tag; ltype = XL_GetType(xdummyLine->special); if(!ltype) { // What is this? There is no such XG line type. XG_Dev("XS_DoChain: Unknown XG line type %i", xdummyLine->special); // We're done, free the dummy. Z_Free(xdummyLine->xg); P_FreeDummyLine(dummyLine); return; } memcpy(&xdummyLine->xg->info, ltype, sizeof(*ltype)); if(act_thing) xdummyLine->xg->activator = act_thing; else xdummyLine->xg->activator = NULL; xdummyLine->xg->active = (ch == XSCE_FUNCTION ? false : !activating); XG_Dev("XS_DoChain: Dummy line will show up as %i", P_ToIndex(dummyLine)); // Send the event. if(XL_LineEvent((ch == XSCE_FUNCTION ? XLE_FUNC : XLE_CHAIN), 0, dummyLine, 0, act_thing)) { // Success! if(ch < XSCE_NUM_CHAINS) { // Decrease counter. if(info->count[ch] > 0) { info->count[ch]--; XG_Dev ("XS_DoChain: %s, sector %i (activating=%i): Counter now at %i", ch == XSCE_FLOOR ? "FLOOR" : ch == XSCE_CEILING ? "CEILING" : ch == XSCE_INSIDE ? "INSIDE" : ch == XSCE_TICKER ? "TICKER" : ch == XSCE_FUNCTION ? "FUNCTION" : "???", P_ToIndex(sec), activating, info->count[ch]); } } } // We're done, free the dummy. Z_Free(xdummyLine->xg); P_FreeDummyLine(dummyLine); } static boolean checkChainRequirements(sector_t* sec, mobj_t* mo, int ch, boolean* activating) { xgsector_t* xg; sectortype_t* info; player_t* player = mo->player; int flags; boolean typePasses = false; xg = P_ToXSector(sec)->xg; info = &xg->info; flags = info->chainFlags[ch]; // Check mobj type. if((flags & (SCEF_ANY_A | SCEF_ANY_D | SCEF_TICKER_A | SCEF_TICKER_D)) || ((flags & (SCEF_PLAYER_A | SCEF_PLAYER_D)) && player) || ((flags & (SCEF_OTHER_A | SCEF_OTHER_D)) && !player) || ((flags & (SCEF_MONSTER_A | SCEF_MONSTER_D)) && (mo->flags & MF_COUNTKILL)) || ((flags & (SCEF_MISSILE_A | SCEF_MISSILE_D)) && (mo->flags & MF_MISSILE))) typePasses = true; if(!typePasses) return false; // Wrong type. // Are we looking for an activation effect? if(player) *activating = !(flags & SCEF_PLAYER_D); else if(mo->flags & MF_COUNTKILL) *activating = !(flags & SCEF_MONSTER_D); else if(mo->flags & MF_MISSILE) *activating = !(flags & SCEF_MISSILE_D); else if(flags & (SCEF_ANY_A | SCEF_ANY_D)) *activating = !(flags & SCEF_ANY_D); else *activating = !(flags & SCEF_OTHER_D); // Check for extra requirements (touching). switch(ch) { case XSCE_FLOOR: // Is it touching the floor? if(mo->pos[VZ] > P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) return false; case XSCE_CEILING: // Is it touching the ceiling? if(mo->pos[VZ] + mo->height < P_GetFloatp(sec, DMU_CEILING_HEIGHT)) return false; default: break; } return true; } typedef struct { sector_t* sec; int data; } xstrav_sectorchainparams_t; boolean XSTrav_SectorChain(thinker_t* th, void* context) { xstrav_sectorchainparams_t* params = (xstrav_sectorchainparams_t*) context; mobj_t* mo = (mobj_t *) th; if(params->sec == P_GetPtrp(mo->subsector, DMU_SECTOR)) { boolean activating; if(checkChainRequirements(params->sec, mo, params->data, &activating)) XS_DoChain(params->sec, params->data, activating, mo); } return true; // Continue iteration. } void P_ApplyWind(mobj_t* mo, sector_t* sec) { sectortype_t* info; float ang; if(mo->player && (mo->player->plr->flags & DDPF_CAMERA)) return; // Wind does not affect cameras. info = &(P_ToXSector(sec)->xg->info); ang = PI * info->windAngle / 180; if(IS_CLIENT) { // Clientside wind only affects the local player. if(!mo->player || mo->player != &players[CONSOLEPLAYER]) return; } // Does wind affect this sort of things? if(((info->flags & STF_PLAYER_WIND) && mo->player) || ((info->flags & STF_OTHER_WIND) && !mo->player) || ((info->flags & STF_MONSTER_WIND) && (mo->flags & MF_COUNTKILL)) || ((info->flags & STF_MISSILE_WIND) && (mo->flags & MF_MISSILE))) { float thfloorz = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); float thceilz = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); if(!(info->flags & (STF_FLOOR_WIND | STF_CEILING_WIND)) || ((info->flags & STF_FLOOR_WIND) && mo->pos[VZ] <= thfloorz) || ((info->flags & STF_CEILING_WIND) && mo->pos[VZ] + mo->height >= thceilz)) { // Apply vertical wind. mo->mom[MZ] += info->verticalWind; // Horizontal wind. mo->mom[MX] += cos(ang) * info->windSpeed; mo->mom[MY] += sin(ang) * info->windSpeed; } } } typedef struct { sector_t* sec; } xstrav_windparams_t; boolean XSTrav_Wind(thinker_t* th, void* context) { xstrav_windparams_t* params = (xstrav_windparams_t*) context; mobj_t* mo = (mobj_t *) th; if(params->sec == P_GetPtrp(mo->subsector, DMU_SECTOR)) { P_ApplyWind(mo, params->sec); } return true; // Continue iteration. } /** * Makes sure the offset is in the range 0..64. */ void XS_ConstrainPlaneOffset(float *offset) { if(*offset > 64) *offset -= 64; if(*offset < 0) *offset += 64; } /** * XG sectors get to think. */ void XS_Thinker(xsthinker_t* xs) { int i; float ang; float floorOffset[2], ceilOffset[2]; sector_t* sector = xs->sector; xsector_t* xsector = P_ToXSector(sector); xgsector_t* xg; sectortype_t* info; if(!xsector) return; // Not an xsector? Most perculiar... xg = xsector->xg; if(!xg) return; // Not an extended sector. if(xg->disabled) return; // This sector is disabled. info = &xg->info; if(!IS_CLIENT) { // Function tickers. for(i = 0; i < 2; ++i) XF_Ticker(&xg->plane[i], sector); XF_Ticker(&xg->light, sector); for(i = 0; i < 3; ++i) XF_Ticker(&xg->rgb[i], sector); // Update linked functions. for(i = 0; i < 3; ++i) { if(i < 2 && xg->plane[i].link) xg->plane[i].value = xg->plane[i].link->value; if(xg->rgb[i].link) xg->rgb[i].value = xg->rgb[i].link->value; } if(xg->light.link) xg->light.value = xg->light.link->value; // Update planes. XS_UpdatePlanes(sector); // Update sector light. XS_UpdateLight(sector); // Decrement chain timers. for(i = 0; i < XSCE_NUM_CHAINS; ++i) xg->chainTimer[i]--; // Floor chain. Check any mobjs that are touching the floor of the // sector. if(info->chain[XSCE_FLOOR] && xg->chainTimer[XSCE_FLOOR] <= 0) { xstrav_sectorchainparams_t params; params.sec = sector; params.data = XSCE_FLOOR; DD_IterateThinkers(P_MobjThinker, XSTrav_SectorChain, ¶ms); } // Ceiling chain. Check any mobjs that are touching the ceiling. if(info->chain[XSCE_CEILING] && xg->chainTimer[XSCE_CEILING] <= 0) { xstrav_sectorchainparams_t params; params.sec = sector; params.data = XSCE_CEILING; DD_IterateThinkers(P_MobjThinker, XSTrav_SectorChain, ¶ms); } // Inside chain. Check any sectorlinked mobjs. if(info->chain[XSCE_INSIDE] && xg->chainTimer[XSCE_INSIDE] <= 0) { xstrav_sectorchainparams_t params; params.sec = sector; params.data = XSCE_INSIDE; DD_IterateThinkers(P_MobjThinker, XSTrav_SectorChain, ¶ms); } // Ticker chain. Send an activate event if TICKER_D flag is not set. if(info->chain[XSCE_TICKER] && xg->chainTimer[XSCE_TICKER] <= 0) { XS_DoChain(sector, XSCE_TICKER, !(info->chainFlags[XSCE_TICKER] & SCEF_TICKER_D), &dummyThing); } // Play ambient sounds. if(xg->info.ambientSound) { if(xg->timer-- < 0) { xg->timer = XG_RandomInt(FLT2TIC(xg->info.soundInterval[0]), FLT2TIC(xg->info.soundInterval[1])); S_SectorSound(sector, SORG_CENTER, xg->info.ambientSound); } } } // Floor Texture movement if(xg->info.materialMoveSpeed[0] != 0) { ang = PI * xg->info.materialMoveAngle[0] / 180; // Get current values P_GetFloatpv(sector, DMU_FLOOR_MATERIAL_OFFSET_XY, floorOffset); // Apply the offsets floorOffset[VX] -= cos(ang) * xg->info.materialMoveSpeed[0]; floorOffset[VY] -= sin(ang) * xg->info.materialMoveSpeed[0]; // Set the results P_SetFloatpv(sector, DMU_FLOOR_MATERIAL_OFFSET_XY, floorOffset); } // Ceiling Texture movement if(xg->info.materialMoveSpeed[1] != 0) { ang = PI * xg->info.materialMoveAngle[1] / 180; // Get current values P_GetFloatpv(sector, DMU_CEILING_MATERIAL_OFFSET_XY, ceilOffset); // Apply the offsets ceilOffset[VX] -= cos(ang) * xg->info.materialMoveSpeed[1]; ceilOffset[VY] -= sin(ang) * xg->info.materialMoveSpeed[1]; // Set the results P_SetFloatpv(sector, DMU_CEILING_MATERIAL_OFFSET_XY, ceilOffset); } // Wind for all sectorlinked mobjs. if(xg->info.windSpeed || xg->info.verticalWind) { xstrav_windparams_t params; params.sec = sector; DD_IterateThinkers(P_MobjThinker, XSTrav_Wind, ¶ms); } } float XS_Gravity(struct sector_s* sec) { xsector_t* xsec; if(!sec) return P_GetGravity(); // World gravity. xsec = P_ToXSector(sec); if(!xsec->xg || !(xsec->xg->info.flags & STF_GRAVITY)) { return P_GetGravity(); // World gravity. } else { // Sector-specific gravity. float gravity = xsec->xg->info.gravity; // Apply gravity modifier. if(IS_NETGAME && cfg.netGravity != -1) gravity *= (float) cfg.netGravity / 100; return gravity; } } float XS_Friction(struct sector_s *sector) { if(!P_ToXSector(sector)->xg || !(P_ToXSector(sector)->xg->info.flags & STF_FRICTION)) return FRICTION_NORMAL; // Normal friction. return P_ToXSector(sector)->xg->info.friction; } /** * @return The thrust multiplier caused by friction. */ float XS_ThrustMul(struct sector_s *sector) { float x = XS_Friction(sector); if(x <= FRICTION_NORMAL) return 1; // Normal friction. if(x > 1) return 0; // There's nothing to thrust from! // {c = -93.31092643, b = 208.0448223, a = -114.7338958} return (-114.7338958 * x * x + 208.0448223 * x - 93.31092643); } /** * During update, definitions are re-read, so the pointers need to be * updated. However, this is a bit messy operation, prone to errors. * Instead, we just disable XG... */ void XS_Update(void) { uint i; xsector_t *xsec; // It's all PU_MAP memory, so we can just lose it. for(i = 0; i < numsectors; ++i) { xsec = P_ToXSector(P_ToPtr(DMU_SECTOR, i)); if(xsec->xg) { xsec->xg = NULL; xsec->special = 0; } } } #if 0 // no longer supported in 1.8.7 /* * Write XG types into a binary file. */ DEFCC(CCmdDumpXG) { FILE *file; if(argc != 2) { Con_Printf("Usage: %s (file)\n", argv[0]); Con_Printf("Writes XG line and sector types to the file.\n"); return true; } file = fopen(argv[1], "wb"); if(!file) { Con_Printf("Can't open \"%s\" for writing.\n", argv[1]); return false; } XG_WriteTypes(file); fclose(file); return true; } #endif /** * $moveplane: Command line interface to the plane mover. */ DEFCC(CCmdMovePlane) { boolean isCeiling = !stricmp(argv[0], "moveceil"); boolean isBoth = !stricmp(argv[0], "movesec"); boolean isOffset = false, isCrusher = false; sector_t *sector = NULL; float units = 0, speed = FRACUNIT; int p = 0; float floorheight, ceilingheight; xgplanemover_t *mover; if(argc < 2) { Con_Printf("Usage: %s (opts)\n", argv[0]); Con_Printf("Opts can be:\n"); Con_Printf(" here [crush] [off] (z/units) [speed]\n"); Con_Printf(" at (x) (y) [crush] [off] (z/units) [speed]\n"); Con_Printf(" tag (sector-tag) [crush] [off] (z/units) [speed]\n"); return true; } if(IS_CLIENT) { Con_Printf("Clients can't move planes.\n"); return false; } // Which mode? if(!stricmp(argv[1], "here")) { p = 2; if(!players[CONSOLEPLAYER].plr->mo) return false; sector = P_GetPtrp(players[CONSOLEPLAYER].plr->mo->subsector, DMU_SECTOR); } else if(!stricmp(argv[1], "at") && argc >= 4) { p = 4; sector = P_GetPtrp(R_PointInSubsector((float) strtol(argv[2], 0, 0), (float) strtol(argv[3], 0, 0)), DMU_SECTOR); } else if(!stricmp(argv[1], "tag") && argc >= 3) { int tag = (short) strtol(argv[2], 0, 0); sector_t *sec = NULL; iterlist_t *list; p = 3; list = P_GetSectorIterListForTag(tag, false); if(list) { // Find the first sector with the tag. P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { sector = sec; break; } } } else { // Unknown mode. Con_Printf("Unknown mode.\n"); return false; } floorheight = P_GetFloatp(sector, DMU_FLOOR_HEIGHT); ceilingheight = P_GetFloatp(sector, DMU_CEILING_HEIGHT); // No more arguments? if(argc == p) { Con_Printf("Ceiling = %g\nFloor = %g\n", ceilingheight, floorheight); return true; } // Check for the optional 'crush' parameter. if(argc >= p + 1 && !stricmp(argv[p], "crush")) { isCrusher = true; ++p; } // Check for the optional 'off' parameter. if(argc >= p + 1 && !stricmp(argv[p], "off")) { isOffset = true; ++p; } // The amount to move. if(argc >= p + 1) { units = strtod(argv[p++], 0); } else { Con_Printf("You must specify Z-units.\n"); return false; // Required parameter missing. } // The optional speed parameter. if(argc >= p + 1) { speed = strtod(argv[p++], 0); // The speed is always positive. if(speed < 0) speed = -speed; } // We must now have found the sector to operate on. if(!sector) return false; mover = XS_GetPlaneMover(sector, isCeiling); // Setup the thinker and add it to the list. mover->destination = units + (isOffset ? (isCeiling ? ceilingheight : floorheight) : 0); // Check that the destination is valid. if(!isBoth) { if(isCeiling && mover->destination < floorheight + 4) mover->destination = floorheight + 4; if(!isCeiling && mover->destination > ceilingheight - 4) mover->destination = ceilingheight - 4; } mover->speed = speed; if(isCrusher) { mover->crushSpeed = speed * .5; // Crush at half speed. mover->flags |= PMF_CRUSH; } if(isBoth) mover->flags |= PMF_OTHER_FOLLOWS; return true; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_saveg.c0000644000175000017500000044466411357170242022437 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_saveg.c: Save Game I/O * * \bug Not 64bit clean: In function 'SV_ReadPlayer': cast from pointer to integer of different size * \bug Not 64bit clean: In function 'SV_WriteMobj': cast from pointer to integer of different size * \bug Not 64bit clean: In function 'RestoreMobj': cast from pointer to integer of different size * \bug Not 64bit clean: In function 'SV_ReadMobj': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'P_UnArchiveThinkers': cast from pointer to integer of different size * \bug Not 64bit clean: In function 'P_UnArchiveBrain': cast to pointer from integer of different size, cast from pointer to integer of different size * \bug Not 64bit clean: In function 'P_UnArchiveSoundTargets': cast to pointer from integer of different size, cast from pointer to integer of different size */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "p_saveg.h" #include "f_infine.h" #include "d_net.h" #include "p_svtexarc.h" #include "dmu_lib.h" #include "p_map.h" #include "p_mapsetup.h" #include "p_player.h" #include "p_inventory.h" #include "am_map.h" #include "p_tick.h" #include "p_actor.h" #include "p_ceiling.h" #include "p_door.h" #include "p_floor.h" #include "p_plat.h" #include "p_switch.h" #include "hu_log.h" #if __JHERETIC__ || __JHEXEN__ #include "hu_inventory.h" #endif // MACROS ------------------------------------------------------------------ #if __JDOOM__ # define MY_SAVE_MAGIC 0x1DEAD666 # define MY_CLIENT_SAVE_MAGIC 0x2DEAD666 # define MY_SAVE_VERSION 7 # define SAVESTRINGSIZE 24 # define CONSISTENCY 0x2c # define SAVEGAMENAME "DoomSav" # define CLIENTSAVEGAMENAME "DoomCl" # define SAVEGAMEEXTENSION "dsg" #elif __JDOOM64__ # define MY_SAVE_MAGIC 0x1D6420F4 # define MY_CLIENT_SAVE_MAGIC 0x2D6420F4 # define MY_SAVE_VERSION 7 # define SAVESTRINGSIZE 24 # define CONSISTENCY 0x2c # define SAVEGAMENAME "D64Sav" # define CLIENTSAVEGAMENAME "D64Cl" # define SAVEGAMEEXTENSION "6sg" #elif __JHERETIC__ # define MY_SAVE_MAGIC 0x7D9A12C5 # define MY_CLIENT_SAVE_MAGIC 0x1062AF43 # define MY_SAVE_VERSION 7 # define SAVESTRINGSIZE 24 # define CONSISTENCY 0x9d # define SAVEGAMENAME "HticSav" # define CLIENTSAVEGAMENAME "HticCl" # define SAVEGAMEEXTENSION "hsg" #elif __JHEXEN__ # define HXS_VERSION_TEXT "HXS Ver " // Do not change me! # define HXS_VERSION_TEXT_LENGTH 16 # define MY_SAVE_VERSION 8 # define SAVESTRINGSIZE 24 # define SAVEGAMENAME "hex" # define CLIENTSAVEGAMENAME "hexencl" # define SAVEGAMEEXTENSION "hxs" # define MOBJ_XX_PLAYER -2 # define MAX_MAPS 99 # define BASE_SLOT 6 # define REBORN_SLOT 7 # define REBORN_DESCRIPTION "TEMP GAME" #endif #if !__JHEXEN__ # define PRE_VER5_END_SPECIALS 7 #endif #define FF_FULLBRIGHT 0x8000 // used to be flag in thing->frame #define FF_FRAMEMASK 0x7fff // TYPES ------------------------------------------------------------------- #if !__JHEXEN__ typedef struct saveheader_s { int magic; int version; int gameMode; char description[SAVESTRINGSIZE]; byte skill; byte episode; byte map; byte deathmatch; byte noMonsters; byte respawnMonsters; int mapTime; byte players[MAXPLAYERS]; unsigned int gameID; } saveheader_t; #endif typedef struct playerheader_s { int numPowers; int numKeys; int numFrags; int numWeapons; int numAmmoTypes; int numPSprites; #if __JDOOM64__ || __JHERETIC__ || __JHEXEN__ int numInvItemTypes; #endif #if __JHEXEN__ int numArmorTypes; #endif } playerheader_t; typedef enum gamearchivesegment_e { ASEG_GAME_HEADER = 101, //jhexen only ASEG_MAP_HEADER, //jhexen only ASEG_WORLD, ASEG_POLYOBJS, //jhexen only ASEG_MOBJS, //jhexen < ver 4 only ASEG_THINKERS, ASEG_SCRIPTS, //jhexen only ASEG_PLAYERS, ASEG_SOUNDS, //jhexen only ASEG_MISC, //jhexen only ASEG_END, ASEG_MATERIAL_ARCHIVE, ASEG_MAP_HEADER2, //jhexen only ASEG_PLAYER_HEADER, ASEG_GLOBALSCRIPTDATA //jhexen only } gamearchivesegment_t; #if __JHEXEN__ static union saveptr_u { byte *b; short *w; int *l; float *f; } saveptr; typedef struct targetplraddress_s { void **address; struct targetplraddress_s *next; } targetplraddress_t; #endif // Thinker Save flags #define TSF_SERVERONLY 0x01 // Only saved by servers. typedef struct thinkerinfo_s { thinkerclass_t thinkclass; think_t function; int flags; void (*Write) (); int (*Read) (); size_t size; } thinkerinfo_t; typedef enum sectorclass_e { sc_normal, sc_ploff, // plane offset #if !__JHEXEN__ sc_xg1 #endif } sectorclass_t; typedef enum lineclass_e { lc_normal, #if !__JHEXEN__ lc_xg1 #endif } lineclass_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void SV_WriteMobj(const mobj_t* mobj); static int SV_ReadMobj(thinker_t* th); static void SV_WriteCeiling(const ceiling_t* ceiling); static int SV_ReadCeiling(ceiling_t* ceiling); static void SV_WriteDoor(const door_t* door); static int SV_ReadDoor(door_t* door); static void SV_WriteFloor(const floor_t* floor); static int SV_ReadFloor(floor_t* floor); static void SV_WritePlat(const plat_t* plat); static int SV_ReadPlat(plat_t* plat); static void SV_WriteMaterialChanger(const materialchanger_t* mchanger); static int SV_ReadMaterialChanger(materialchanger_t* mchanger); #if __JHEXEN__ static void SV_WriteLight(const light_t* light); static int SV_ReadLight(light_t* light); static void SV_WritePhase(const phase_t* phase); static int SV_ReadPhase(phase_t* phase); static void SV_WriteScript(const acs_t* script); static int SV_ReadScript(acs_t* script); static void SV_WriteDoorPoly(const polydoor_t* polydoor); static int SV_ReadDoorPoly(polydoor_t* polydoor); static void SV_WriteMovePoly(const polyevent_t* movepoly); static int SV_ReadMovePoly(polyevent_t* movepoly); static void SV_WriteRotatePoly(const polyevent_t* rotatepoly); static int SV_ReadRotatePoly(polyevent_t* rotatepoly); static void SV_WritePillar(const pillar_t* pillar); static int SV_ReadPillar(pillar_t* pillar); static void SV_WriteFloorWaggle(const waggle_t* floorwaggle); static int SV_ReadFloorWaggle(waggle_t* floorwaggle); #else static void SV_WriteFlash(const lightflash_t* flash); static int SV_ReadFlash(lightflash_t* flash); static void SV_WriteStrobe(const strobe_t* strobe); static int SV_ReadStrobe(strobe_t* strobe); static void SV_WriteGlow(const glow_t* glow); static int SV_ReadGlow(glow_t* glow); # if __JDOOM__ || __JDOOM64__ static void SV_WriteFlicker(const fireflicker_t* flicker); static int SV_ReadFlicker(fireflicker_t* flicker); # endif # if __JDOOM64__ static void SV_WriteBlink(const lightblink_t* flicker); static int SV_ReadBlink(lightblink_t* flicker); # endif #endif #if __JHEXEN__ static void OpenStreamOut(char *fileName); static void CloseStreamOut(void); static void ClearSaveSlot(int slot); static void CopySaveSlot(int sourceSlot, int destSlot); static void CopyFile(char *sourceName, char *destName); static boolean ExistingFile(char *name); #endif static void unarchiveMap(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- LZFILE* savefile; #if __JHEXEN__ filename_t savePath; /* = "hexndata\\"; */ filename_t clientSavePath; /* = "hexndata\\client\\"; */ #else filename_t savePath; /* = "savegame\\"; */ filename_t clientSavePath; /* = "savegame\\client\\"; */ #endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ #if __JHEXEN__ static int saveVersion; #else static saveheader_t hdr; #endif static playerheader_t playerHeader; static boolean playerHeaderOK = false; static mobj_t** thingArchive = NULL; static uint thingArchiveSize = 0; static int saveToRealPlayerNum[MAXPLAYERS]; #if __JHEXEN__ static targetplraddress_t* targetPlayerAddrs = NULL; static byte* saveBuffer; static boolean savingPlayers; #else static int numSoundTargets = 0; #endif static byte* junkbuffer; // Old save data is read into here. static thinkerinfo_t thinkerInfo[] = { { TC_MOBJ, P_MobjThinker, TSF_SERVERONLY, SV_WriteMobj, SV_ReadMobj, sizeof(mobj_t) }, #if !__JHEXEN__ { TC_XGMOVER, XS_PlaneMover, 0, SV_WriteXGPlaneMover, SV_ReadXGPlaneMover, sizeof(xgplanemover_t) }, #endif { TC_CEILING, T_MoveCeiling, 0, SV_WriteCeiling, SV_ReadCeiling, sizeof(ceiling_t) }, { TC_DOOR, T_Door, 0, SV_WriteDoor, SV_ReadDoor, sizeof(door_t) }, { TC_FLOOR, T_MoveFloor, 0, SV_WriteFloor, SV_ReadFloor, sizeof(floor_t) }, { TC_PLAT, T_PlatRaise, 0, SV_WritePlat, SV_ReadPlat, sizeof(plat_t) }, #if __JHEXEN__ { TC_INTERPRET_ACS, T_InterpretACS, 0, SV_WriteScript, SV_ReadScript, sizeof(acs_t) }, { TC_FLOOR_WAGGLE, T_FloorWaggle, 0, SV_WriteFloorWaggle, SV_ReadFloorWaggle, sizeof(waggle_t) }, { TC_LIGHT, T_Light, 0, SV_WriteLight, SV_ReadLight, sizeof(light_t) }, { TC_PHASE, T_Phase, 0, SV_WritePhase, SV_ReadPhase, sizeof(phase_t) }, { TC_BUILD_PILLAR, T_BuildPillar, 0, SV_WritePillar, SV_ReadPillar, sizeof(pillar_t) }, { TC_ROTATE_POLY, T_RotatePoly, 0, SV_WriteRotatePoly, SV_ReadRotatePoly, sizeof(polyevent_t) }, { TC_MOVE_POLY, T_MovePoly, 0, SV_WriteMovePoly, SV_ReadMovePoly, sizeof(polyevent_t) }, { TC_POLY_DOOR, T_PolyDoor, 0, SV_WriteDoorPoly, SV_ReadDoorPoly, sizeof(polydoor_t) }, #else { TC_FLASH, T_LightFlash, 0, SV_WriteFlash, SV_ReadFlash, sizeof(lightflash_t) }, { TC_STROBE, T_StrobeFlash, 0, SV_WriteStrobe, SV_ReadStrobe, sizeof(strobe_t) }, { TC_GLOW, T_Glow, 0, SV_WriteGlow, SV_ReadGlow, sizeof(glow_t) }, # if __JDOOM__ || __JDOOM64__ { TC_FLICKER, T_FireFlicker, 0, SV_WriteFlicker, SV_ReadFlicker, sizeof(fireflicker_t) }, # endif # if __JDOOM64__ { TC_BLINK, T_LightBlink, 0, SV_WriteBlink, SV_ReadBlink, sizeof(lightblink_t) }, # endif #endif { TC_MATERIALCHANGER, T_MaterialChanger, 0, SV_WriteMaterialChanger, SV_ReadMaterialChanger, sizeof(materialchanger_t) }, // Terminator { TC_NULL, NULL, 0, NULL, NULL, 0 } }; // CODE -------------------------------------------------------------------- /** * Exit with a fatal error if the value at the current location in the save * file does not match that associated with the specified segment type. * * @param segType Value by which to check for alignment. */ static void AssertSegment(int segType) { #if __JHEXEN__ if(SV_ReadLong() != segType) { Con_Error("Corrupt save game: Segment [%d] failed alignment check", segType); } #endif } static void SV_BeginSegment(int segType) { #if __JHEXEN__ SV_WriteLong(segType); #endif } /** * @return Ptr to the thinkerinfo for the given thinker. */ static thinkerinfo_t* infoForThinker(thinker_t* th) { thinkerinfo_t* thInfo = thinkerInfo; if(!th) return NULL; while(thInfo->thinkclass != TC_NULL) { if(thInfo->function == th->function) return thInfo; thInfo++; } return NULL; } static boolean removeThinker(thinker_t* th, void* context) { if(th->function == P_MobjThinker) P_MobjRemove((mobj_t *) th, true); else Z_Free(th); return true; // Continue iteration. } typedef struct { uint count; boolean savePlayers; } countmobjsparams_t; static boolean countMobjs(thinker_t* th, void* context) { countmobjsparams_t* params = (countmobjsparams_t*) context; mobj_t* mo = (mobj_t*) th; if(!(mo->player && !params->savePlayers)) params->count++; return true; // Continue iteration. } /** * Must be called before saving or loading any data. */ static uint SV_InitThingArchive(boolean load, boolean savePlayers) { countmobjsparams_t params; params.count = 0; params.savePlayers = savePlayers; if(load) { #if !__JHEXEN__ if(hdr.version < 5) params.count = 1024; // Limit in previous versions. else #endif params.count = SV_ReadLong(); } else { // Count the number of mobjs we'll be writing. DD_IterateThinkers(P_MobjThinker, countMobjs, ¶ms); } thingArchive = calloc(params.count, sizeof(mobj_t*)); return thingArchiveSize = params.count; } /** * Used by the read code when mobjs are read. */ static void SV_SetArchiveThing(mobj_t* mo, int num) { #if __JHEXEN__ if(saveVersion >= 4) #endif num -= 1; if(num < 0) return; if(!thingArchive) Con_Error("SV_SetArchiveThing: Thing archive uninitialized."); thingArchive[num] = mo; } /** * Free the thing archive. Called when load is complete. */ static void SV_FreeThingArchive(void) { if(thingArchive) { free(thingArchive); thingArchive = NULL; thingArchiveSize = 0; } } /** * Called by the write code to get archive numbers. * If the mobj is already archived, the existing number is returned. * Number zero is not used. */ #if __JHEXEN__ int SV_ThingArchiveNum(mobj_t* mo) #else unsigned short SV_ThingArchiveNum(mobj_t* mo) #endif { uint i, firstEmpty = 0; boolean found; // We only archive valid mobj thinkers. if(mo == NULL || ((thinker_t *) mo)->function != P_MobjThinker) return 0; #if __JHEXEN__ if(mo->player && !savingPlayers) return MOBJ_XX_PLAYER; #endif if(!thingArchive) Con_Error("SV_ThingArchiveNum: Thing archive uninitialized."); found = false; for(i = 0; i < thingArchiveSize; ++i) { if(!thingArchive[i] && !found) { firstEmpty = i; found = true; continue; } if(thingArchive[i] == mo) return i + 1; } if(!found) { Con_Error("SV_ThingArchiveNum: Thing archive exhausted!\n"); return 0; // No number available! } // OK, place it in an empty pos. thingArchive[firstEmpty] = mo; return firstEmpty + 1; } #if __JHEXEN__ static void SV_FreeTargetPlayerList(void) { targetplraddress_t* p = targetPlayerAddrs, *np; while(p != NULL) { np = p->next; free(p); p = np; } targetPlayerAddrs = NULL; } #endif /** * Called by the read code to resolve mobj ptrs from archived thing ids * after all thinkers have been read and spawned into the map. */ mobj_t *SV_GetArchiveThing(int thingid, void *address) { #if __JHEXEN__ if(thingid == MOBJ_XX_PLAYER) { targetplraddress_t *tpa = malloc(sizeof(targetplraddress_t)); tpa->address = address; tpa->next = targetPlayerAddrs; targetPlayerAddrs = tpa; return NULL; } #endif if(!thingArchive) Con_Error("SV_GetArchiveThing: Thing archive uninitialized."); // Check that the thing archive id is valid. #if __JHEXEN__ if(saveVersion < 4) { // Old format is base 0. if(thingid == -1) return NULL; // A NULL reference. if(thingid < 0 || (uint) thingid > thingArchiveSize - 1) return NULL; } else #endif { // New format is base 1. if(thingid == 0) return NULL; // A NULL reference. if(thingid < 1 || (uint) thingid > thingArchiveSize) { Con_Message("SV_GetArchiveThing: Invalid NUM %i??\n", thingid); return NULL; } thingid -= 1; } return thingArchive[thingid]; } static playerheader_t* getPlayerHeader(void) { #if _DEBUG if(!playerHeaderOK) Con_Error("getPlayerHeader: Attempted to read before init!"); #endif return &playerHeader; } unsigned int SV_GameID(void) { return Sys_GetRealTime() + (mapTime << 24); } void SV_Write(const void *data, int len) { lzWrite((void*)data, len, savefile); } void SV_WriteByte(byte val) { lzPutC(val, savefile); } #if __JHEXEN__ void SV_WriteShort(unsigned short val) #else void SV_WriteShort(short val) #endif { lzPutW(val, savefile); } #if __JHEXEN__ void SV_WriteLong(unsigned int val) #else void SV_WriteLong(long val) #endif { lzPutL(val, savefile); } void SV_WriteFloat(float val) { long temp = 0; memcpy(&temp, &val, 4); lzPutL(temp, savefile); } void SV_Read(void *data, int len) { #if __JHEXEN__ memcpy(data, saveptr.b, len); saveptr.b += len; #else lzRead(data, len, savefile); #endif } byte SV_ReadByte(void) { #if __JHEXEN__ return (*saveptr.b++); #else return lzGetC(savefile); #endif } short SV_ReadShort(void) { #if __JHEXEN__ return (SHORT(*saveptr.w++)); #else return lzGetW(savefile); #endif } long SV_ReadLong(void) { #if __JHEXEN__ return (LONG(*saveptr.l++)); #else return lzGetL(savefile); #endif } float SV_ReadFloat(void) { #if __JHEXEN__ return (FLOAT(*saveptr.f++)); #else long val = lzGetL(savefile); float returnValue = 0; memcpy(&returnValue, &val, 4); return returnValue; #endif } #if __JHEXEN__ static void OpenStreamOut(char *fileName) { savefile = lzOpen(fileName, "wp"); } static void CloseStreamOut(void) { if(savefile) { lzClose(savefile); } } static boolean ExistingFile(char *name) { FILE *fp; if((fp = fopen(name, "rb")) != NULL) { fclose(fp); return true; } else { return false; } } /** * Deletes all save game files associated with a slot number. */ static void ClearSaveSlot(int slot) { int i; filename_t fileName; for(i = 0; i < MAX_MAPS; ++i) { dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex%d%02d.hxs", savePath, slot, i); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); remove(fileName); } dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex%d.hxs", savePath, slot); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); remove(fileName); } static void CopyFile(char *sourceName, char *destName) { size_t length; byte *buffer; LZFILE *outf; length = M_ReadFile(sourceName, &buffer); outf = lzOpen(destName, "wp"); if(outf) { lzWrite(buffer, length, outf); lzClose(outf); } Z_Free(buffer); } /** * Copies all the save game files from one slot to another. */ static void CopySaveSlot(int sourceSlot, int destSlot) { int i; filename_t sourceName, destName; for(i = 0; i < MAX_MAPS; ++i) { dd_snprintf(sourceName, FILENAME_T_MAXLEN, "%shex%d%02d.hxs", savePath, sourceSlot, i); M_TranslatePath(sourceName, sourceName, FILENAME_T_MAXLEN); if(ExistingFile(sourceName)) { dd_snprintf(destName, FILENAME_T_MAXLEN, "%shex%d%02d.hxs", savePath, destSlot, i); M_TranslatePath(destName, destName, FILENAME_T_MAXLEN); CopyFile(sourceName, destName); } } dd_snprintf(sourceName, FILENAME_T_MAXLEN, "%shex%d.hxs", savePath, sourceSlot); M_TranslatePath(sourceName, sourceName, FILENAME_T_MAXLEN); if(ExistingFile(sourceName)) { dd_snprintf(destName, FILENAME_T_MAXLEN, "%shex%d.hxs", savePath, destSlot); M_TranslatePath(destName, destName, FILENAME_T_MAXLEN); CopyFile(sourceName, destName); } } /** * Copies the base slot to the reborn slot. */ void SV_HxUpdateRebornSlot(void) { ClearSaveSlot(REBORN_SLOT); CopySaveSlot(BASE_SLOT, REBORN_SLOT); } void SV_HxClearRebornSlot(void) { ClearSaveSlot(REBORN_SLOT); } int SV_HxGetRebornSlot(void) { return (REBORN_SLOT); } /** * @return @c true, if the reborn slot is available. */ boolean SV_HxRebornSlotAvailable(void) { filename_t fileName; dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex%d.hxs", savePath, REBORN_SLOT); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); return ExistingFile(fileName); } void SV_HxInitBaseSlot(void) { ClearSaveSlot(BASE_SLOT); } #endif /** * Writes the given player's data (not including the ID number). */ static void SV_WritePlayer(int playernum) { int i, numPSprites = getPlayerHeader()->numPSprites; player_t temp, *p = &temp; ddplayer_t ddtemp, *dp = &ddtemp; // Make a copy of the player. memcpy(p, &players[playernum], sizeof(temp)); memcpy(dp, players[playernum].plr, sizeof(ddtemp)); temp.plr = &ddtemp; // Convert the psprite states. for(i = 0; i < numPSprites; ++i) { pspdef_t *pspDef = &temp.pSprites[i]; if(pspDef->state) { pspDef->state = (state_t *) (pspDef->state - STATES); } } // Version number. Increase when you make changes to the player data // segment format. SV_WriteByte(6); #if __JHEXEN__ // Class. SV_WriteByte(cfg.playerClass[playernum]); #endif SV_WriteLong(p->playerState); #if __JHEXEN__ SV_WriteLong(p->class); // 2nd class...? #endif SV_WriteLong(FLT2FIX(p->viewZ)); SV_WriteLong(FLT2FIX(p->viewHeight)); SV_WriteLong(FLT2FIX(p->viewHeightDelta)); #if !__JHEXEN__ SV_WriteFloat(dp->lookDir); #endif SV_WriteLong(FLT2FIX(p->bob)); #if __JHEXEN__ SV_WriteLong(p->flyHeight); SV_WriteFloat(dp->lookDir); SV_WriteLong(p->centering); #endif SV_WriteLong(p->health); #if __JHEXEN__ for(i = 0; i < getPlayerHeader()->numArmorTypes; ++i) { SV_WriteLong(p->armorPoints[i]); } #else SV_WriteLong(p->armorPoints); SV_WriteLong(p->armorType); #endif #if __JDOOM64__ || __JHEXEN__ for(i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) { inventoryitemtype_t type = IIT_FIRST + i; SV_WriteLong(type); SV_WriteLong(P_InventoryCount(playernum, type)); } SV_WriteLong(P_InventoryReadyItem(playernum)); #endif for(i = 0; i < getPlayerHeader()->numPowers; ++i) { SV_WriteLong(p->powers[i]); } #if __JHEXEN__ SV_WriteLong(p->keys); #else for(i = 0; i < getPlayerHeader()->numKeys; ++i) { SV_WriteLong(p->keys[i]); } #endif #if __JHEXEN__ SV_WriteLong(p->pieces); #else SV_WriteLong(p->backpack); #endif for(i = 0; i < getPlayerHeader()->numFrags; ++i) { SV_WriteLong(p->frags[i]); } SV_WriteLong(p->readyWeapon); SV_WriteLong(p->pendingWeapon); for(i = 0; i < getPlayerHeader()->numWeapons; ++i) { SV_WriteLong(p->weapons[i].owned); } for(i = 0; i < getPlayerHeader()->numAmmoTypes; ++i) { SV_WriteLong(p->ammo[i].owned); #if !__JHEXEN__ SV_WriteLong(p->ammo[i].max); #endif } SV_WriteLong(p->attackDown); SV_WriteLong(p->useDown); SV_WriteLong(p->cheats); SV_WriteLong(p->refire); SV_WriteLong(p->killCount); SV_WriteLong(p->itemCount); SV_WriteLong(p->secretCount); SV_WriteLong(p->damageCount); SV_WriteLong(p->bonusCount); #if __JHEXEN__ SV_WriteLong(p->poisonCount); #endif SV_WriteLong(dp->extraLight); SV_WriteLong(dp->fixedColorMap); SV_WriteLong(p->colorMap); for(i = 0; i < numPSprites; ++i) { pspdef_t *psp = &p->pSprites[i]; SV_WriteLong((int)psp->state); SV_WriteLong(psp->tics); SV_WriteLong(FLT2FIX(psp->pos[VX])); SV_WriteLong(FLT2FIX(psp->pos[VY])); } #if !__JHEXEN__ SV_WriteLong(p->didSecret); // Added in ver 2 with __JDOOM__ SV_WriteLong(p->flyHeight); #endif #if __JHERETIC__ for(i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) { inventoryitemtype_t type = IIT_FIRST + i; SV_WriteLong(type); SV_WriteLong(P_InventoryCount(playernum, type)); } SV_WriteLong(P_InventoryReadyItem(playernum)); SV_WriteLong(p->chickenPeck); #endif #if __JHERETIC__ || __JHEXEN__ SV_WriteLong(p->morphTics); #endif SV_WriteLong(p->airCounter); #if __JHEXEN__ SV_WriteLong(p->jumpTics); SV_WriteLong(p->worldTimer); #elif __JHERETIC__ SV_WriteLong(p->flameCount); // Added in ver 2 SV_WriteByte(p->class); #endif } /** * Reads a player's data (not including the ID number). */ static void SV_ReadPlayer(player_t* p) { int i, plrnum = p - players, numPSprites = getPlayerHeader()->numPSprites; byte ver; ddplayer_t* dp = p->plr; ver = SV_ReadByte(); #if __JHEXEN__ cfg.playerClass[plrnum] = SV_ReadByte(); memset(p, 0, sizeof(*p)); // Force everything NULL, p->plr = dp; // but restore the ddplayer pointer. #endif p->playerState = SV_ReadLong(); #if __JHEXEN__ p->class = SV_ReadLong(); // 2nd class...? #endif p->viewZ = FIX2FLT(SV_ReadLong()); p->viewHeight = FIX2FLT(SV_ReadLong()); p->viewHeightDelta = FIX2FLT(SV_ReadLong()); #if !__JHEXEN__ dp->lookDir = SV_ReadFloat(); #endif p->bob = FIX2FLT(SV_ReadLong()); #if __JHEXEN__ p->flyHeight = SV_ReadLong(); dp->lookDir = SV_ReadFloat(); p->centering = SV_ReadLong(); #endif p->health = SV_ReadLong(); #if __JHEXEN__ for(i = 0; i < getPlayerHeader()->numArmorTypes; ++i) { p->armorPoints[i] = SV_ReadLong(); } #else p->armorPoints = SV_ReadLong(); p->armorType = SV_ReadLong(); #endif #if __JDOOM64__ || __JHEXEN__ P_InventoryEmpty(plrnum); for(i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) { inventoryitemtype_t type = SV_ReadLong(); int j, count = SV_ReadLong(); for(j = 0; j < count; ++j) P_InventoryGive(plrnum, type, true); } P_InventorySetReadyItem(plrnum, (inventoryitemtype_t) SV_ReadLong()); # if __JHEXEN__ Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); if(ver < 5) { SV_ReadLong(); // Current inventory item count? } if(ver < 6) /*p->inventorySlotNum =*/ SV_ReadLong(); # endif #endif for(i = 0; i < getPlayerHeader()->numPowers; ++i) { p->powers[i] = SV_ReadLong(); } if(p->powers[PT_ALLMAP]) AM_RevealMap(AM_MapForPlayer(plrnum), true); #if __JHEXEN__ p->keys = SV_ReadLong(); #else for(i = 0; i < getPlayerHeader()->numKeys; ++i) { p->keys[i] = SV_ReadLong(); } #endif #if __JHEXEN__ p->pieces = SV_ReadLong(); #else p->backpack = SV_ReadLong(); #endif for(i = 0; i < getPlayerHeader()->numFrags; ++i) { p->frags[i] = SV_ReadLong(); } p->readyWeapon = SV_ReadLong(); #if __JHEXEN__ if(ver < 5) p->pendingWeapon = WT_NOCHANGE; else #endif p->pendingWeapon = SV_ReadLong(); for(i = 0; i < getPlayerHeader()->numWeapons; ++i) { p->weapons[i].owned = (SV_ReadLong()? true : false); } for(i = 0; i < getPlayerHeader()->numAmmoTypes; ++i) { p->ammo[i].owned = SV_ReadLong(); #if !__JHEXEN__ p->ammo[i].max = SV_ReadLong(); #endif } p->attackDown = SV_ReadLong(); p->useDown = SV_ReadLong(); p->cheats = SV_ReadLong(); p->refire = SV_ReadLong(); p->killCount = SV_ReadLong(); p->itemCount = SV_ReadLong(); p->secretCount = SV_ReadLong(); #if __JHEXEN__ if(ver <= 1) { /*p->messageTics =*/ SV_ReadLong(); /*p->ultimateMessage =*/ SV_ReadLong(); /*p->yellowMessage =*/ SV_ReadLong(); } #endif p->damageCount = SV_ReadLong(); p->bonusCount = SV_ReadLong(); #if __JHEXEN__ p->poisonCount = SV_ReadLong(); #endif dp->extraLight = SV_ReadLong(); dp->fixedColorMap = SV_ReadLong(); p->colorMap = SV_ReadLong(); for(i = 0; i < numPSprites; ++i) { pspdef_t *psp = &p->pSprites[i]; psp->state = (state_t*) SV_ReadLong(); psp->tics = SV_ReadLong(); psp->pos[VX] = FIX2FLT(SV_ReadLong()); psp->pos[VY] = FIX2FLT(SV_ReadLong()); } #if !__JHEXEN__ p->didSecret = SV_ReadLong(); # if __JDOOM__ || __JDOOM64__ if(ver == 2) // nolonger used in >= ver 3 /*p->messageTics =*/ SV_ReadLong(); if(ver >= 2) p->flyHeight = SV_ReadLong(); # elif __JHERETIC__ if(ver < 3) // nolonger used in >= ver 3 /*p->messageTics =*/ SV_ReadLong(); p->flyHeight = SV_ReadLong(); P_InventoryEmpty(plrnum); for(i = 0; i < getPlayerHeader()->numInvItemTypes; ++i) { inventoryitemtype_t type = SV_ReadLong(); int j, count = SV_ReadLong(); for(j = 0; j < count; ++j) P_InventoryGive(plrnum, type, true); } P_InventorySetReadyItem(plrnum, (inventoryitemtype_t) SV_ReadLong()); Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); if(ver < 5) { SV_ReadLong(); // Current inventory item count? } if(ver < 6) /*p->inventorySlotNum =*/ SV_ReadLong(); p->chickenPeck = SV_ReadLong(); # endif #endif #if __JHERETIC__ || __JHEXEN__ p->morphTics = SV_ReadLong(); #endif if(ver >= 2) p->airCounter = SV_ReadLong(); #if __JHEXEN__ p->jumpTics = SV_ReadLong(); p->worldTimer = SV_ReadLong(); #elif __JHERETIC__ p->flameCount = SV_ReadLong(); if(ver >= 2) p->class = SV_ReadByte(); #endif #if !__JHEXEN__ // Will be set when unarc thinker. p->plr->mo = NULL; p->attacker = NULL; #endif // Demangle it. for(i = 0; i < numPSprites; ++i) if(p->pSprites[i].state) { p->pSprites[i].state = &STATES[(int) p->pSprites[i].state]; } // Mark the player for fixpos and fixangles. dp->flags |= DDPF_FIXPOS | DDPF_FIXANGLES | DDPF_FIXMOM; p->update |= PSF_REBORN; } #if __JHEXEN__ # define MOBJ_SAVEVERSION 8 #elif __JHERETIC__ # define MOBJ_SAVEVERSION 10 #else # define MOBJ_SAVEVERSION 10 #endif static void SV_WriteMobj(const mobj_t* original) { mobj_t temp, *mo = &temp; memcpy(mo, original, sizeof(*mo)); // Mangle it! mo->state = (state_t *) (mo->state - STATES); if(mo->player) mo->player = (player_t *) ((mo->player - players) + 1); // Version. // JHEXEN // 2: Added the 'translucency' byte. // 3: Added byte 'vistarget' // 4: Added long 'tracer' // 4: Added long 'lastenemy' // 5: Added flags3 // 6: Floor material removed. // // JDOOM || JHERETIC || JDOOM64 // 4: Added byte 'translucency' // 5: Added byte 'vistarget' // 5: Added tracer in jDoom // 5: Added dropoff fix in jHeretic // 5: Added long 'floorclip' // 6: Added proper respawn data // 6: Added flags 2 in jDoom // 6: Added damage // 7: Added generator in jHeretic // 7: Added flags3 // // JDOOM // 9: Revised mapspot flag interpretation // // JHERETIC // 8: Added special3 // 9: Revised mapspot flag interpretation // // JHEXEN // 7: Removed superfluous info ptr // 8: Added 'onMobj' SV_WriteByte(MOBJ_SAVEVERSION); #if !__JHEXEN__ // A version 2 features: archive number and target. SV_WriteShort(SV_ThingArchiveNum((mobj_t*) original)); SV_WriteShort(SV_ThingArchiveNum(mo->target)); # if __JDOOM__ || __JDOOM64__ // Ver 5 features: Save tracer (fixes Archvile, Revenant bug) SV_WriteShort(SV_ThingArchiveNum(mo->tracer)); # endif #endif SV_WriteShort(SV_ThingArchiveNum(mo->onMobj)); // Info for drawing: position. SV_WriteLong(FLT2FIX(mo->pos[VX])); SV_WriteLong(FLT2FIX(mo->pos[VY])); SV_WriteLong(FLT2FIX(mo->pos[VZ])); //More drawing info: to determine current sprite. SV_WriteLong(mo->angle); // Orientation. SV_WriteLong(mo->sprite); // Used to find patch_t and flip value. SV_WriteLong(mo->frame); #if !__JHEXEN__ // The closest interval over all contacted Sectors. SV_WriteLong(FLT2FIX(mo->floorZ)); SV_WriteLong(FLT2FIX(mo->ceilingZ)); #endif // For movement checking. SV_WriteLong(FLT2FIX(mo->radius)); SV_WriteLong(FLT2FIX(mo->height)); // Momentums, used to update position. SV_WriteLong(FLT2FIX(mo->mom[MX])); SV_WriteLong(FLT2FIX(mo->mom[MY])); SV_WriteLong(FLT2FIX(mo->mom[MZ])); // If == VALIDCOUNT, already checked. SV_WriteLong(mo->valid); SV_WriteLong(mo->type); SV_WriteLong(mo->tics); // State tic counter. SV_WriteLong((int) mo->state); #if __JHEXEN__ SV_WriteLong(mo->damage); #endif SV_WriteLong(mo->flags); #if __JHEXEN__ SV_WriteLong(mo->flags2); SV_WriteLong(mo->flags3); if(mo->type == MT_KORAX) SV_WriteLong(0); // Searching index. else SV_WriteLong(mo->special1); switch(mo->type) { case MT_LIGHTNING_FLOOR: case MT_LIGHTNING_ZAP: case MT_HOLY_TAIL: case MT_LIGHTNING_CEILING: if(mo->flags & MF_CORPSE) SV_WriteLong(0); else SV_WriteLong(SV_ThingArchiveNum((mobj_t *) mo->special2)); break; default: SV_WriteLong(mo->special2); break; } #endif SV_WriteLong(mo->health); // Movement direction, movement generation (zig-zagging). SV_WriteLong(mo->moveDir); // 0-7 SV_WriteLong(mo->moveCount); // When 0, select a new dir. #if __JHEXEN__ if(mo->flags & MF_CORPSE) SV_WriteLong(0); else SV_WriteLong((int) SV_ThingArchiveNum(mo->target)); #endif // Reaction time: if non 0, don't attack yet. // Used by player to freeze a bit after teleporting. SV_WriteLong(mo->reactionTime); // If >0, the target will be chased no matter what (even if shot). SV_WriteLong(mo->threshold); // Additional info record for player avatars only (only valid if type // == MT_PLAYER). SV_WriteLong((int) mo->player); // Player number last looked for. SV_WriteLong(mo->lastLook); #if !__JHEXEN__ // For nightmare/multiplayer respawn. SV_WriteLong(FLT2FIX(mo->spawnSpot.pos[VX])); SV_WriteLong(FLT2FIX(mo->spawnSpot.pos[VY])); SV_WriteLong(FLT2FIX(mo->spawnSpot.pos[VZ])); SV_WriteLong(mo->spawnSpot.angle); SV_WriteLong(mo->spawnSpot.flags); SV_WriteLong(mo->intFlags); // $dropoff_fix: internal flags. SV_WriteLong(FLT2FIX(mo->dropOffZ)); // $dropoff_fix SV_WriteLong(mo->gear); // Used in torque simulation. SV_WriteLong(mo->damage); SV_WriteLong(mo->flags2); SV_WriteLong(mo->flags3); # ifdef __JHERETIC__ SV_WriteLong(mo->special1); SV_WriteLong(mo->special2); SV_WriteLong(mo->special3); # endif SV_WriteByte(mo->translucency); SV_WriteByte((byte)(mo->visTarget +1)); #endif SV_WriteLong(FLT2FIX(mo->floorClip)); #if __JHEXEN__ SV_WriteLong(SV_ThingArchiveNum((mobj_t*) original)); SV_WriteLong(mo->tid); SV_WriteLong(mo->special); SV_Write(mo->args, sizeof(mo->args)); SV_WriteByte(mo->translucency); SV_WriteByte((byte)(mo->visTarget +1)); switch(mo->type) { case MT_BISH_FX: case MT_HOLY_FX: case MT_DRAGON: case MT_THRUSTFLOOR_UP: case MT_THRUSTFLOOR_DOWN: case MT_MINOTAUR: case MT_SORCFX1: case MT_MSTAFF_FX2: case MT_HOLY_TAIL: case MT_LIGHTNING_CEILING: if(mo->flags & MF_CORPSE) SV_WriteLong(0); else SV_WriteLong(SV_ThingArchiveNum(mo->tracer)); break; default: # if _DEBUG if(mo->tracer != NULL) Con_Error("SV_WriteMobj: Mobj using tracer. Possibly saved incorrectly."); # endif SV_WriteLong((int) mo->tracer); break; } SV_WriteLong((int) mo->lastEnemy); #elif __JHERETIC__ // Ver 7 features: generator SV_WriteShort(SV_ThingArchiveNum(mo->generator)); #endif } /** * Fixes the mobj flags in older save games to the current values. * * Called after loading a save game where the mobj format is older than * the current version. * * @param mo Ptr to the mobj whoose flags are to be updated. * @param ver The MOBJ save version to update from. */ #if !__JDOOM64__ void SV_UpdateReadMobjFlags(mobj_t *mo, int ver) { #if __JDOOM__ || __JHERETIC__ if(ver < 6) { // mobj.flags # if __JDOOM__ // switched values for MF_BRIGHTSHADOW <> MF_BRIGHTEXPLODE if((mo->flags & MF_BRIGHTEXPLODE) != (mo->flags & MF_BRIGHTSHADOW)) { if(mo->flags & MF_BRIGHTEXPLODE) // previously MF_BRIGHTSHADOW { mo->flags |= MF_BRIGHTSHADOW; mo->flags &= ~MF_BRIGHTEXPLODE; } else // previously MF_BRIGHTEXPLODE { mo->flags |= MF_BRIGHTEXPLODE; mo->flags &= ~MF_BRIGHTSHADOW; } } // else they were both on or off so it doesn't matter. # endif // Remove obsoleted flags in earlier save versions. mo->flags &= ~MF_V6OBSOLETE; // mobj.flags2 # if __JDOOM__ // jDoom only gained flags2 in ver 6 so all we can do is to // apply the values as set in the mobjinfo. // Non-persistent flags might screw things up a lot worse otherwise. mo->flags2 = mo->info->flags2; # endif } #endif #if __JDOOM__ || __JHERETIC__ if(ver < 9) { mo->spawnSpot.flags &= ~MASK_UNKNOWN_MSF_FLAGS; // Spawn on the floor by default unless the mobjtype flags override. mo->spawnSpot.flags |= MSF_Z_FLOOR; } #endif #if __JHEXEN__ if(ver < 5) #else if(ver < 7) #endif { // flags3 was introduced in a latter version so all we can do is to // apply the values as set in the mobjinfo. // Non-persistent flags might screw things up a lot worse otherwise. mo->flags3 = mo->info->flags3; } } #endif static void RestoreMobj(mobj_t *mo, int ver) { mo->info = &MOBJINFO[mo->type]; P_MobjSetState(mo, (int) mo->state); #if __JHEXEN__ if(mo->flags2 & MF2_DORMANT) mo->tics = -1; #endif if(mo->player) { // The player number translation table is used to find out the // *current* (actual) player number of the referenced player. int pNum = saveToRealPlayerNum[(int) mo->player - 1]; #if __JHEXEN__ if(pNum < 0) { // This saved player does not exist in the current game! // This'll make the mobj unarchiver destroy this mobj. Z_Free(mo); return; // Don't add this thinker. } #endif mo->player = &players[pNum]; mo->dPlayer = mo->player->plr; mo->dPlayer->mo = mo; //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */ mo->dPlayer->lookDir = 0; /* $unifiedangles */ } mo->visAngle = mo->angle >> 16; #if !__JHEXEN__ if(mo->dPlayer && !mo->dPlayer->inGame) { if(mo->dPlayer) mo->dPlayer->mo = NULL; P_MobjDestroy(mo); return; } #endif #if !__JDOOM64__ // Do we need to update this mobj's flag values? if(ver < MOBJ_SAVEVERSION) SV_UpdateReadMobjFlags(mo, ver); #endif P_MobjSetPosition(mo); mo->floorZ = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); mo->ceilingZ = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); return; } /** * Always returns @c false as a thinker will have already been allocated in * the mobj creation process. */ static int SV_ReadMobj(thinker_t *th) { int ver; mobj_t *mo = (mobj_t*) th; ver = SV_ReadByte(); #if !__JHEXEN__ if(ver >= 2) // Version 2 has mobj archive numbers. SV_SetArchiveThing(mo, SV_ReadShort()); #endif #if !__JHEXEN__ mo->target = NULL; if(ver >= 2) { mo->target = (mobj_t*) (int) SV_ReadShort(); } #endif #if __JDOOM__ || __JDOOM64__ // Tracer for enemy attacks (updated after all mobjs are loaded). mo->tracer = NULL; if(ver >= 5) { mo->tracer = (mobj_t*) (int) SV_ReadShort(); } #endif // mobj this one is on top of (updated after all mobjs are loaded). mo->onMobj = NULL; #if __JHEXEN__ if(ver >= 8) #else if(ver >= 5) #endif { mo->onMobj = (mobj_t*) (int) SV_ReadShort(); } // Info for drawing: position. mo->pos[VX] = FIX2FLT(SV_ReadLong()); mo->pos[VY] = FIX2FLT(SV_ReadLong()); mo->pos[VZ] = FIX2FLT(SV_ReadLong()); //More drawing info: to determine current sprite. mo->angle = SV_ReadLong(); // orientation mo->sprite = SV_ReadLong(); // used to find patch_t and flip value mo->frame = SV_ReadLong(); // might be ORed with FF_FULLBRIGHT if(mo->frame & FF_FULLBRIGHT) mo->frame &= FF_FRAMEMASK; // not used anymore. #if __JHEXEN__ if(ver < 6) SV_ReadLong(); // Used to be floorflat. #else // The closest interval over all contacted Sectors. mo->floorZ = FIX2FLT(SV_ReadLong()); mo->ceilingZ = FIX2FLT(SV_ReadLong()); #endif // For movement checking. mo->radius = FIX2FLT(SV_ReadLong()); mo->height = FIX2FLT(SV_ReadLong()); // Momentums, used to update position. mo->mom[MX] = FIX2FLT(SV_ReadLong()); mo->mom[MY] = FIX2FLT(SV_ReadLong()); mo->mom[MZ] = FIX2FLT(SV_ReadLong()); // If == VALIDCOUNT, already checked. mo->valid = SV_ReadLong(); mo->type = SV_ReadLong(); #if __JHEXEN__ if(ver < 7) /*mo->info = (mobjinfo_t *)*/ SV_ReadLong(); #endif mo->info = &MOBJINFO[mo->type]; if(mo->info->flags2 & MF2_FLOATBOB) mo->mom[MZ] = 0; if(mo->info->flags & MF_SOLID) mo->ddFlags |= DDMF_SOLID; if(mo->info->flags2 & MF2_DONTDRAW) mo->ddFlags |= DDMF_DONTDRAW; mo->tics = SV_ReadLong(); // state tic counter mo->state = (state_t *) SV_ReadLong(); #if __JHEXEN__ mo->damage = SV_ReadLong(); #endif mo->flags = SV_ReadLong(); #if __JHEXEN__ mo->flags2 = SV_ReadLong(); if(ver >= 5) mo->flags3 = SV_ReadLong(); mo->special1 = SV_ReadLong(); mo->special2 = SV_ReadLong(); #endif mo->health = SV_ReadLong(); #if __JHERETIC__ if(ver < 8) { // Fix a bunch of kludges in the original Heretic. switch(mo->type) { case MT_MACEFX1: case MT_MACEFX2: case MT_MACEFX3: case MT_HORNRODFX2: case MT_HEADFX3: case MT_WHIRLWIND: case MT_TELEGLITTER: case MT_TELEGLITTER2: mo->special3 = mo->health; if(mo->type == MT_HORNRODFX2 && mo->special3 > 16) mo->special3 = 16; mo->health = MOBJINFO[mo->type].spawnHealth; break; default: break; } } #endif // Movement direction, movement generation (zig-zagging). mo->moveDir = SV_ReadLong(); // 0-7 mo->moveCount = SV_ReadLong(); // when 0, select a new dir #if __JHEXEN__ mo->target = (mobj_t *) SV_ReadLong(); #endif // Reaction time: if non 0, don't attack yet. // Used by player to freeze a bit after teleporting. mo->reactionTime = SV_ReadLong(); // If >0, the target will be chased // no matter what (even if shot) mo->threshold = SV_ReadLong(); // Additional info record for player avatars only. // Only valid if type == MT_PLAYER mo->player = (player_t *) SV_ReadLong(); // Player number last looked for. mo->lastLook = SV_ReadLong(); #if __JHEXEN__ mo->floorClip = FIX2FLT(SV_ReadLong()); SV_SetArchiveThing(mo, SV_ReadLong()); mo->tid = SV_ReadLong(); #else // For nightmare respawn. if(ver >= 6) { mo->spawnSpot.pos[VX] = FIX2FLT(SV_ReadLong()); mo->spawnSpot.pos[VY] = FIX2FLT(SV_ReadLong()); mo->spawnSpot.pos[VZ] = FIX2FLT(SV_ReadLong()); mo->spawnSpot.angle = SV_ReadLong(); if(ver < 10) /* mo->spawnSpot.type = */ SV_ReadLong(); mo->spawnSpot.flags = SV_ReadLong(); } else { mo->spawnSpot.pos[VX] = (float) SV_ReadShort(); mo->spawnSpot.pos[VY] = (float) SV_ReadShort(); mo->spawnSpot.pos[VZ] = 0; // Initialize with "something". mo->spawnSpot.angle = (angle_t) (ANG45 * (SV_ReadShort() / 45)); /*mo->spawnSpot.type = (int)*/ SV_ReadShort(); mo->spawnSpot.flags = (int) SV_ReadShort(); } # if __JDOOM__ || __JDOOM64__ if(ver >= 3) # elif __JHERETIC__ if(ver >= 5) # endif { mo->intFlags = SV_ReadLong(); // killough $dropoff_fix: internal flags mo->dropOffZ = FIX2FLT(SV_ReadLong()); // killough $dropoff_fix mo->gear = SV_ReadLong(); // killough used in torque simulation } # if __JDOOM__ || __JDOOM64__ if(ver >= 6) { mo->damage = SV_ReadLong(); mo->flags2 = SV_ReadLong(); }// Else flags2 will be applied from the defs. else mo->damage = DDMAXINT; // Use the value set in mo->info->damage # elif __JHERETIC__ mo->damage = SV_ReadLong(); mo->flags2 = SV_ReadLong(); # endif if(ver >= 7) mo->flags3 = SV_ReadLong(); // Else flags3 will be applied from the defs. #endif #if __JHEXEN__ mo->special = SV_ReadLong(); SV_Read(mo->args, 1 * 5); #elif __JHERETIC__ mo->special1 = SV_ReadLong(); mo->special2 = SV_ReadLong(); if(ver >= 8) mo->special3 = SV_ReadLong(); #endif #if __JHEXEN__ if(ver >= 2) #else if(ver >= 4) #endif mo->translucency = SV_ReadByte(); #if __JHEXEN__ if(ver >= 3) #else if(ver >= 5) #endif mo->visTarget = (short) (SV_ReadByte()) -1; #if __JHEXEN__ if(ver >= 4) mo->tracer = (mobj_t *) SV_ReadLong(); if(ver >= 4) mo->lastEnemy = (mobj_t *) SV_ReadLong(); #else if(ver >= 5) mo->floorClip = FIX2FLT(SV_ReadLong()); #endif #if __JHERETIC__ if(ver >= 7) mo->generator = (mobj_t *) (int) SV_ReadShort(); else mo->generator = NULL; #endif // Restore! (unmangle) RestoreMobj(mo, ver); return false; } /** * Prepare and write the player header info. */ static void P_ArchivePlayerHeader(void) { playerheader_t *ph = &playerHeader; SV_BeginSegment(ASEG_PLAYER_HEADER); SV_WriteByte(2); // version byte ph->numPowers = NUM_POWER_TYPES; ph->numKeys = NUM_KEY_TYPES; ph->numFrags = MAXPLAYERS; ph->numWeapons = NUM_WEAPON_TYPES; ph->numAmmoTypes = NUM_AMMO_TYPES; ph->numPSprites = NUMPSPRITES; #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ ph->numInvItemTypes = NUM_INVENTORYITEM_TYPES; #endif #if __JHEXEN__ ph->numArmorTypes = NUMARMOR; #endif SV_WriteLong(ph->numPowers); SV_WriteLong(ph->numKeys); SV_WriteLong(ph->numFrags); SV_WriteLong(ph->numWeapons); SV_WriteLong(ph->numAmmoTypes); SV_WriteLong(ph->numPSprites); #if __JDOOM64__ || __JHERETIC__ || __JHEXEN__ SV_WriteLong(ph->numInvItemTypes); #endif #if __JHEXEN__ SV_WriteLong(ph->numArmorTypes); #endif playerHeaderOK = true; } /** * Read archived player header info. */ static void P_UnArchivePlayerHeader(void) { #if __JHEXEN__ if(saveVersion >= 4) #else if(hdr.version >= 5) #endif { int ver; AssertSegment(ASEG_PLAYER_HEADER); ver = SV_ReadByte(); playerHeader.numPowers = SV_ReadLong(); playerHeader.numKeys = SV_ReadLong(); playerHeader.numFrags = SV_ReadLong(); playerHeader.numWeapons = SV_ReadLong(); playerHeader.numAmmoTypes = SV_ReadLong(); playerHeader.numPSprites = SV_ReadLong(); #if __JHERETIC__ if(ver >= 2) playerHeader.numInvItemTypes = SV_ReadLong(); else playerHeader.numInvItemTypes = NUM_INVENTORYITEM_TYPES; #endif #if __JHEXEN__ || __JDOOM64__ playerHeader.numInvItemTypes = SV_ReadLong(); #endif #if __JHEXEN__ playerHeader.numArmorTypes = SV_ReadLong(); #endif } else // The old format didn't save the counts. { #if __JHEXEN__ playerHeader.numPowers = 9; playerHeader.numKeys = 11; playerHeader.numFrags = 8; playerHeader.numWeapons = 4; playerHeader.numAmmoTypes = 2; playerHeader.numPSprites = 2; playerHeader.numInvItemTypes = 33; playerHeader.numArmorTypes = 4; #elif __JDOOM__ || __JDOOM64__ playerHeader.numPowers = 6; playerHeader.numKeys = 6; playerHeader.numFrags = 4; // Why was this only 4? playerHeader.numWeapons = 9; playerHeader.numAmmoTypes = 4; playerHeader.numPSprites = 2; # if __JDOOM64__ playerHeader.numInvItemTypes = 3; # endif #elif __JHERETIC__ playerHeader.numPowers = 9; playerHeader.numKeys = 3; playerHeader.numFrags = 4; // ? playerHeader.numWeapons = 8; playerHeader.numInvItemTypes = 14; playerHeader.numAmmoTypes = 6; playerHeader.numPSprites = 2; #endif } playerHeaderOK = true; } static void P_ArchivePlayers(void) { int i; SV_BeginSegment(ASEG_PLAYERS); #if __JHEXEN__ for(i = 0; i < MAXPLAYERS; ++i) { SV_WriteByte(players[i].plr->inGame); } #endif for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; SV_WriteLong(Net_GetPlayerID(i)); SV_WritePlayer(i); } } static void P_UnArchivePlayers(boolean *infile, boolean *loaded) { int i, j; unsigned int pid; player_t dummyPlayer; ddplayer_t dummyDDPlayer; player_t *player; // Setup the dummy. dummyPlayer.plr = &dummyDDPlayer; // Load the players. for(i = 0; i < MAXPLAYERS; ++i) { // By default a saved player translates to nothing. saveToRealPlayerNum[i] = -1; if(!infile[i]) continue; // The ID number will determine which player this actually is. pid = SV_ReadLong(); for(player = 0, j = 0; j < MAXPLAYERS; ++j) if((IS_NETGAME && Net_GetPlayerID(j) == pid) || (!IS_NETGAME && j == 0)) { // This is our guy. player = players + j; loaded[j] = true; // Later references to the player number 'i' must be // translated! saveToRealPlayerNum[i] = j; #if _DEBUG Con_Printf("P_UnArchivePlayers: Saved %i is now %i.\n", i, j); #endif break; } if(!player) { // We have a missing player. Use a dummy to load the data. player = &dummyPlayer; } // Read the data. SV_ReadPlayer(player); } } static void SV_WriteSector(sector_t *sec) { int i, type; float flooroffx = P_GetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_X); float flooroffy = P_GetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_Y); float ceiloffx = P_GetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_X); float ceiloffy = P_GetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_Y); byte lightlevel = (byte) (255.f * P_GetFloatp(sec, DMU_LIGHT_LEVEL)); short floorheight = (short) P_GetIntp(sec, DMU_FLOOR_HEIGHT); short ceilingheight = (short) P_GetIntp(sec, DMU_CEILING_HEIGHT); short floorFlags = (short) P_GetIntp(sec, DMU_FLOOR_FLAGS); short ceilingFlags = (short) P_GetIntp(sec, DMU_CEILING_FLAGS); material_t* floorMaterial = P_GetPtrp(sec, DMU_FLOOR_MATERIAL); material_t* ceilingMaterial = P_GetPtrp(sec, DMU_CEILING_MATERIAL); xsector_t* xsec = P_ToXSector(sec); float rgb[3]; #if !__JHEXEN__ // Determine type. if(xsec->xg) type = sc_xg1; else #endif if(flooroffx || flooroffy || ceiloffx || ceiloffy) type = sc_ploff; else type = sc_normal; // Type byte. SV_WriteByte(type); // Version. // 2: Surface colors. // 3: Surface flags. SV_WriteByte(3); // write a version byte. SV_WriteShort(floorheight); SV_WriteShort(ceilingheight); SV_WriteShort(SV_MaterialArchiveNum(floorMaterial)); SV_WriteShort(SV_MaterialArchiveNum(ceilingMaterial)); SV_WriteShort(floorFlags); SV_WriteShort(ceilingFlags); #if __JHEXEN__ SV_WriteShort((short) lightlevel); #else SV_WriteByte(lightlevel); #endif P_GetFloatpv(sec, DMU_COLOR, rgb); for(i = 0; i < 3; ++i) SV_WriteByte((byte)(255.f * rgb[i])); P_GetFloatpv(sec, DMU_FLOOR_COLOR, rgb); for(i = 0; i < 3; ++i) SV_WriteByte((byte)(255.f * rgb[i])); P_GetFloatpv(sec, DMU_CEILING_COLOR, rgb); for(i = 0; i < 3; ++i) SV_WriteByte((byte)(255.f * rgb[i])); SV_WriteShort(xsec->special); SV_WriteShort(xsec->tag); #if __JHEXEN__ SV_WriteShort(xsec->seqType); #endif if(type == sc_ploff #if !__JHEXEN__ || type == sc_xg1 #endif ) { SV_WriteFloat(flooroffx); SV_WriteFloat(flooroffy); SV_WriteFloat(ceiloffx); SV_WriteFloat(ceiloffy); } #if !__JHEXEN__ if(xsec->xg) // Extended General? { SV_WriteXGSector(sec); } // Count the number of sound targets if(xsec->soundTarget) numSoundTargets++; #endif } /** * Reads all versions of archived sectors. * Including the old Ver1. */ static void SV_ReadSector(sector_t *sec) { int i, ver = 1; int type = 0; material_t* floorMaterial, *ceilingMaterial; byte rgb[3], lightlevel; xsector_t* xsec = P_ToXSector(sec); int fh, ch; // A type byte? #if __JHEXEN__ if(saveVersion < 4) type = sc_ploff; else #else if(hdr.version <= 1) type = sc_normal; else #endif type = SV_ReadByte(); // A version byte? #if __JHEXEN__ if(saveVersion > 2) #else if(hdr.version > 4) #endif ver = SV_ReadByte(); fh = SV_ReadShort(); ch = SV_ReadShort(); P_SetIntp(sec, DMU_FLOOR_HEIGHT, fh); P_SetIntp(sec, DMU_CEILING_HEIGHT, ch); #if __JHEXEN__ // Update the "target heights" of the planes. P_SetIntp(sec, DMU_FLOOR_TARGET_HEIGHT, fh); P_SetIntp(sec, DMU_CEILING_TARGET_HEIGHT, ch); // The move speed is not saved; can cause minor problems. P_SetIntp(sec, DMU_FLOOR_SPEED, 0); P_SetIntp(sec, DMU_CEILING_SPEED, 0); #endif #if !__JHEXEN__ if(hdr.version == 1) { // Flat numbers are the original flat lump indices - (lump) "F_START". floorMaterial = P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(SV_ReadShort(), MN_FLATS)); ceilingMaterial = P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(SV_ReadShort(), MN_FLATS)); } else if(hdr.version >= 4) #endif { // The flat numbers are actually archive numbers. floorMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 0); ceilingMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 0); } P_SetPtrp(sec, DMU_FLOOR_MATERIAL, floorMaterial); P_SetPtrp(sec, DMU_CEILING_MATERIAL, ceilingMaterial); if(ver >= 3) { P_SetIntp(sec, DMU_FLOOR_FLAGS, SV_ReadShort()); P_SetIntp(sec, DMU_CEILING_FLAGS, SV_ReadShort()); } #if __JHEXEN__ lightlevel = (byte) SV_ReadShort(); #else // In Ver1 the light level is a short if(hdr.version == 1) lightlevel = (byte) SV_ReadShort(); else lightlevel = SV_ReadByte(); #endif P_SetFloatp(sec, DMU_LIGHT_LEVEL, (float) lightlevel / 255.f); #if !__JHEXEN__ if(hdr.version > 1) #endif { SV_Read(rgb, 3); for(i = 0; i < 3; ++i) P_SetFloatp(sec, DMU_COLOR_RED + i, rgb[i] / 255.f); } // Ver 2 includes surface colours if(ver >= 2) { SV_Read(rgb, 3); for(i = 0; i < 3; ++i) P_SetFloatp(sec, DMU_FLOOR_COLOR_RED + i, rgb[i] / 255.f); SV_Read(rgb, 3); for(i = 0; i < 3; ++i) P_SetFloatp(sec, DMU_CEILING_COLOR_RED + i, rgb[i] / 255.f); } xsec->special = SV_ReadShort(); /*xsec->tag =*/ SV_ReadShort(); #if __JHEXEN__ xsec->seqType = SV_ReadShort(); #endif if(type == sc_ploff #if !__JHEXEN__ || type == sc_xg1 #endif ) { P_SetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_X, SV_ReadFloat()); P_SetFloatp(sec, DMU_FLOOR_MATERIAL_OFFSET_Y, SV_ReadFloat()); P_SetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_X, SV_ReadFloat()); P_SetFloatp(sec, DMU_CEILING_MATERIAL_OFFSET_Y, SV_ReadFloat()); } #if !__JHEXEN__ if(type == sc_xg1) SV_ReadXGSector(sec); #endif #if !__JHEXEN__ if(hdr.version <= 1) #endif { xsec->specialData = 0; } // We'll restore the sound targets latter on xsec->soundTarget = 0; } static void SV_WriteLine(linedef_t* li) { uint i, j; float rgba[4]; lineclass_t type; xline_t* xli = P_ToXLine(li); #if !__JHEXEN__ if(xli->xg) type = lc_xg1; else #endif type = lc_normal; SV_WriteByte(type); // Version. // 2: Per surface texture offsets. // 2: Surface colors. // 3: "Mapped by player" values. // 3: Surface flags. // 4: Engine-side linedef flags. SV_WriteByte(4); // Write a version byte SV_WriteShort(P_GetIntp(li, DMU_FLAGS)); SV_WriteShort(xli->flags); for(i = 0; i < MAXPLAYERS; ++i) SV_WriteByte(xli->mapped[i]); #if __JHEXEN__ SV_WriteByte(xli->special); SV_WriteByte(xli->arg1); SV_WriteByte(xli->arg2); SV_WriteByte(xli->arg3); SV_WriteByte(xli->arg4); SV_WriteByte(xli->arg5); #else SV_WriteShort(xli->special); SV_WriteShort(xli->tag); #endif // For each side for(i = 0; i < 2; ++i) { sidedef_t *si = P_GetPtrp(li, (i? DMU_SIDEDEF1:DMU_SIDEDEF0)); if(!si) continue; SV_WriteShort(P_GetIntp(si, DMU_TOP_MATERIAL_OFFSET_X)); SV_WriteShort(P_GetIntp(si, DMU_TOP_MATERIAL_OFFSET_Y)); SV_WriteShort(P_GetIntp(si, DMU_MIDDLE_MATERIAL_OFFSET_X)); SV_WriteShort(P_GetIntp(si, DMU_MIDDLE_MATERIAL_OFFSET_Y)); SV_WriteShort(P_GetIntp(si, DMU_BOTTOM_MATERIAL_OFFSET_X)); SV_WriteShort(P_GetIntp(si, DMU_BOTTOM_MATERIAL_OFFSET_Y)); SV_WriteShort(P_GetIntp(si, DMU_TOP_FLAGS)); SV_WriteShort(P_GetIntp(si, DMU_MIDDLE_FLAGS)); SV_WriteShort(P_GetIntp(si, DMU_BOTTOM_FLAGS)); SV_WriteShort(SV_MaterialArchiveNum(P_GetPtrp(si, DMU_TOP_MATERIAL))); SV_WriteShort(SV_MaterialArchiveNum(P_GetPtrp(si, DMU_BOTTOM_MATERIAL))); SV_WriteShort(SV_MaterialArchiveNum(P_GetPtrp(si, DMU_MIDDLE_MATERIAL))); P_GetFloatpv(si, DMU_TOP_COLOR, rgba); for(j = 0; j < 3; ++j) SV_WriteByte((byte)(255 * rgba[j])); P_GetFloatpv(si, DMU_BOTTOM_COLOR, rgba); for(j = 0; j < 3; ++j) SV_WriteByte((byte)(255 * rgba[j])); P_GetFloatpv(si, DMU_MIDDLE_COLOR, rgba); for(j = 0; j < 4; ++j) SV_WriteByte((byte)(255 * rgba[j])); SV_WriteLong(P_GetIntp(si, DMU_MIDDLE_BLENDMODE)); SV_WriteShort(P_GetIntp(si, DMU_FLAGS)); } #if !__JHEXEN__ // Extended General? if(xli->xg) { SV_WriteXGLine(li); } #endif } /** * Reads all versions of archived lines. * Including the old Ver1. */ static void SV_ReadLine(linedef_t *li) { int i, j; lineclass_t type; int ver; material_t* topMaterial, *bottomMaterial, *middleMaterial; short flags; xline_t* xli = P_ToXLine(li); // A type byte? #if __JHEXEN__ if(saveVersion < 4) #else if(hdr.version < 2) #endif type = lc_normal; else type = (int) SV_ReadByte(); // A version byte? #if __JHEXEN__ if(saveVersion < 3) #else if(hdr.version < 5) #endif ver = 1; else ver = (int) SV_ReadByte(); if(ver >= 4) P_SetIntp(li, DMU_FLAGS, SV_ReadShort()); flags = SV_ReadShort(); if(ver < 4) { // Translate old linedef flags. int ddLineFlags = 0; if(flags & 0x0001) // old ML_BLOCKING flag { ddLineFlags |= DDLF_BLOCKING; flags &= ~0x0001; } if(flags & 0x0004) // old ML_TWOSIDED flag { flags &= ~0x0004; } if(flags & 0x0008) // old ML_DONTPEGTOP flag { ddLineFlags |= DDLF_DONTPEGTOP; flags &= ~0x0008; } if(flags & 0x0010) // old ML_DONTPEGBOTTOM flag { ddLineFlags |= DDLF_DONTPEGBOTTOM; flags &= ~0x0010; } P_SetIntp(li, DMU_FLAGS, ddLineFlags); } if(ver < 3) { if(flags & 0x0100) // old ML_MAPPED flag { uint lineIDX = P_ToIndex(li); // Set line as having been seen by all players.. memset(xli->mapped, 0, sizeof(xli->mapped)); for(i = 0; i < MAXPLAYERS; ++i) AM_UpdateLinedef(AM_MapForPlayer(i), lineIDX, true); flags &= ~0x0100; // remove the old flag. } } xli->flags = flags; if(ver >= 3) { for(i = 0; i < MAXPLAYERS; ++i) xli->mapped[i] = SV_ReadByte(); } #if __JHEXEN__ xli->special = SV_ReadByte(); xli->arg1 = SV_ReadByte(); xli->arg2 = SV_ReadByte(); xli->arg3 = SV_ReadByte(); xli->arg4 = SV_ReadByte(); xli->arg5 = SV_ReadByte(); #else xli->special = SV_ReadShort(); /*xli->tag =*/ SV_ReadShort(); #endif // For each side for(i = 0; i < 2; ++i) { sidedef_t* si = P_GetPtrp(li, (i? DMU_SIDEDEF1:DMU_SIDEDEF0)); if(!si) continue; // Versions latter than 2 store per surface texture offsets. if(ver >= 2) { float offset[2]; offset[VX] = (float) SV_ReadShort(); offset[VY] = (float) SV_ReadShort(); P_SetFloatpv(si, DMU_TOP_MATERIAL_OFFSET_XY, offset); offset[VX] = (float) SV_ReadShort(); offset[VY] = (float) SV_ReadShort(); P_SetFloatpv(si, DMU_MIDDLE_MATERIAL_OFFSET_XY, offset); offset[VX] = (float) SV_ReadShort(); offset[VY] = (float) SV_ReadShort(); P_SetFloatpv(si, DMU_BOTTOM_MATERIAL_OFFSET_XY, offset); } else { float offset[2]; offset[VX] = (float) SV_ReadShort(); offset[VY] = (float) SV_ReadShort(); P_SetFloatpv(si, DMU_TOP_MATERIAL_OFFSET_XY, offset); P_SetFloatpv(si, DMU_MIDDLE_MATERIAL_OFFSET_XY, offset); P_SetFloatpv(si, DMU_BOTTOM_MATERIAL_OFFSET_XY, offset); } if(ver >= 3) { P_SetIntp(si, DMU_TOP_FLAGS, SV_ReadShort()); P_SetIntp(si, DMU_MIDDLE_FLAGS, SV_ReadShort()); P_SetIntp(si, DMU_BOTTOM_FLAGS, SV_ReadShort()); } #if !__JHEXEN__ if(hdr.version >= 4) #endif { // The texture numbers are archive numbers. topMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 1); bottomMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 1); middleMaterial = SV_GetArchiveMaterial(SV_ReadShort(), 1); } P_SetPtrp(si, DMU_TOP_MATERIAL, topMaterial); P_SetPtrp(si, DMU_BOTTOM_MATERIAL, bottomMaterial); P_SetPtrp(si, DMU_MIDDLE_MATERIAL, middleMaterial); // Ver2 includes surface colours if(ver >= 2) { float rgba[4]; for(j = 0; j < 3; ++j) rgba[j] = (float) SV_ReadByte() / 255.f; rgba[3] = 1; P_SetFloatpv(si, DMU_TOP_COLOR, rgba); for(j = 0; j < 3; ++j) rgba[j] = (float) SV_ReadByte() / 255.f; rgba[3] = 1; P_SetFloatpv(si, DMU_BOTTOM_COLOR, rgba); for(j = 0; j < 4; ++j) rgba[j] = (float) SV_ReadByte() / 255.f; P_SetFloatpv(si, DMU_MIDDLE_COLOR, rgba); P_SetIntp(si, DMU_MIDDLE_BLENDMODE, SV_ReadLong()); P_SetIntp(si, DMU_FLAGS, SV_ReadShort()); } } #if !__JHEXEN__ if(type == lc_xg1) SV_ReadXGLine(li); #endif } #if __JHEXEN__ static void SV_WritePolyObj(polyobj_t* po) { SV_WriteByte(1); // write a version byte. SV_WriteLong(po->tag); SV_WriteLong(po->angle); SV_WriteLong(FLT2FIX(po->pos[VX])); SV_WriteLong(FLT2FIX(po->pos[VY])); } static int SV_ReadPolyObj(void) { int ver; float deltaX; float deltaY; angle_t angle; polyobj_t* po; if(saveVersion >= 3) ver = SV_ReadByte(); po = P_GetPolyobj(SV_ReadLong()); // Get polyobj by tag. if(!po) Con_Error("UnarchivePolyobjs: Invalid polyobj tag"); angle = (angle_t) SV_ReadLong(); P_PolyobjRotate(po, angle); po->destAngle = angle; deltaX = FIX2FLT(SV_ReadLong()) - po->pos[VX]; deltaY = FIX2FLT(SV_ReadLong()) - po->pos[VY]; P_PolyobjMove(po, deltaX, deltaY); //// \fixme What about speed? It isn't saved at all? return true; } #endif /** * Only write world in the latest format. */ static void P_ArchiveWorld(void) { uint i; SV_BeginSegment(ASEG_MATERIAL_ARCHIVE); SV_WriteMaterialArchive(); SV_BeginSegment(ASEG_WORLD); for(i = 0; i < numsectors; ++i) SV_WriteSector(P_ToPtr(DMU_SECTOR, i)); for(i = 0; i < numlines; ++i) SV_WriteLine(P_ToPtr(DMU_LINEDEF, i)); #if __JHEXEN__ SV_BeginSegment(ASEG_POLYOBJS); SV_WriteLong(numpolyobjs); for(i = 0; i < numpolyobjs; ++i) SV_WritePolyObj(P_GetPolyobj(i | 0x80000000)); #endif } static void P_UnArchiveWorld(void) { uint i; int matArchiveVer = -1; AssertSegment(ASEG_MATERIAL_ARCHIVE); #if __JHEXEN__ if(saveVersion < 6) #else if(hdr.version < 6) #endif matArchiveVer = 0; // Load the material archive for this map? #if !__JHEXEN__ if(hdr.version >= 4) #endif SV_ReadMaterialArchive(matArchiveVer); AssertSegment(ASEG_WORLD); // Load sectors. for(i = 0; i < numsectors; ++i) SV_ReadSector(P_ToPtr(DMU_SECTOR, i)); // Load lines. for(i = 0; i < numlines; ++i) SV_ReadLine(P_ToPtr(DMU_LINEDEF, i)); #if __JHEXEN__ // Load polyobjects. AssertSegment(ASEG_POLYOBJS); if(SV_ReadLong() != numpolyobjs) Con_Error("UnarchivePolyobjs: Bad polyobj count"); for(i = 0; i < numpolyobjs; ++i) SV_ReadPolyObj(); #endif } static void SV_WriteCeiling(const ceiling_t* ceiling) { SV_WriteByte(2); // Write a version byte. SV_WriteByte((byte) ceiling->type); SV_WriteLong(P_ToIndex(ceiling->sector)); SV_WriteShort((int)ceiling->bottomHeight); SV_WriteShort((int)ceiling->topHeight); SV_WriteLong(FLT2FIX(ceiling->speed)); SV_WriteByte(ceiling->crush); SV_WriteByte((byte) ceiling->state); SV_WriteLong(ceiling->tag); SV_WriteByte((byte) ceiling->oldState); } static int SV_ReadCeiling(ceiling_t* ceiling) { sector_t* sector; #if __JHEXEN__ if(saveVersion >= 4) #else if(hdr.version >= 5) #endif { // Note: the thinker class byte has already been read. int ver = SV_ReadByte(); // version byte. ceiling->thinker.function = T_MoveCeiling; #if !__JHEXEN__ // Should we put this into stasis? if(hdr.version == 5) { if(!SV_ReadByte()) DD_ThinkerSetStasis(&ceiling->thinker, true); } #endif ceiling->type = (ceilingtype_e) SV_ReadByte(); sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!sector) Con_Error("TC_CEILING: bad sector number\n"); ceiling->sector = sector; ceiling->bottomHeight = (float) SV_ReadShort(); ceiling->topHeight = (float) SV_ReadShort(); ceiling->speed = FIX2FLT((fixed_t) SV_ReadLong()); ceiling->crush = SV_ReadByte(); if(ver == 2) ceiling->state = SV_ReadByte(); else ceiling->state = (SV_ReadLong() == -1? CS_DOWN : CS_UP); ceiling->tag = SV_ReadLong(); if(ver == 2) ceiling->oldState = SV_ReadByte(); else ceiling->state = (SV_ReadLong() == -1? CS_DOWN : CS_UP); } else { // Its in the old format which serialized ceiling_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. #if __JHEXEN__ // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!sector) Con_Error("TC_CEILING: bad sector number\n"); ceiling->sector = sector; ceiling->type = SV_ReadLong(); #else ceiling->type = SV_ReadLong(); // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!sector) Con_Error("TC_CEILING: bad sector number\n"); ceiling->sector = sector; #endif ceiling->bottomHeight = FIX2FLT((fixed_t) SV_ReadLong()); ceiling->topHeight = FIX2FLT((fixed_t) SV_ReadLong()); ceiling->speed = FIX2FLT((fixed_t) SV_ReadLong()); ceiling->crush = SV_ReadLong(); ceiling->state = (SV_ReadLong() == -1? CS_DOWN : CS_UP); ceiling->tag = SV_ReadLong(); ceiling->oldState = (SV_ReadLong() == -1? CS_DOWN : CS_UP); ceiling->thinker.function = T_MoveCeiling; #if !__JHEXEN__ if(!junk.function) DD_ThinkerSetStasis(&ceiling->thinker, true); #endif } P_ToXSector(ceiling->sector)->specialData = ceiling; return true; // Add this thinker. } static void SV_WriteDoor(const door_t *door) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteByte((byte) door->type); SV_WriteLong(P_ToIndex(door->sector)); SV_WriteShort((int)door->topHeight); SV_WriteLong(FLT2FIX(door->speed)); SV_WriteLong(door->state); SV_WriteLong(door->topWait); SV_WriteLong(door->topCountDown); } static int SV_ReadDoor(door_t *door) { sector_t *sector; #if __JHEXEN__ if(saveVersion >= 4) #else if(hdr.version >= 5) #endif { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. door->type = (doortype_e) SV_ReadByte(); sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!sector) Con_Error("TC_DOOR: bad sector number\n"); door->sector = sector; door->topHeight = (float) SV_ReadShort(); door->speed = FIX2FLT((fixed_t) SV_ReadLong()); door->state = SV_ReadLong(); door->topWait = SV_ReadLong(); door->topCountDown = SV_ReadLong(); } else { // Its in the old format which serialized door_t // Padding at the start (an old thinker_t struct) SV_Read(junkbuffer, (size_t) 16); // Start of used data members. #if __JHEXEN__ // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_DOOR: bad sector number\n"); door->sector = sector; door->type = SV_ReadLong(); #else door->type = SV_ReadLong(); // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_DOOR: bad sector number\n"); door->sector = sector; #endif door->topHeight = FIX2FLT((fixed_t) SV_ReadLong()); door->speed = FIX2FLT((fixed_t) SV_ReadLong()); door->state = SV_ReadLong(); door->topWait = SV_ReadLong(); door->topCountDown = SV_ReadLong(); } P_ToXSector(door->sector)->specialData = door; door->thinker.function = T_Door; return true; // Add this thinker. } static void SV_WriteFloor(const floor_t *floor) { SV_WriteByte(3); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteByte((byte) floor->type); SV_WriteLong(P_ToIndex(floor->sector)); SV_WriteByte((byte) floor->crush); SV_WriteLong((int) floor->state); SV_WriteLong(floor->newSpecial); SV_WriteShort(SV_MaterialArchiveNum(floor->material)); SV_WriteShort((int) floor->floorDestHeight); SV_WriteLong(FLT2FIX(floor->speed)); #if __JHEXEN__ SV_WriteLong(floor->delayCount); SV_WriteLong(floor->delayTotal); SV_WriteLong(FLT2FIX(floor->stairsDelayHeight)); SV_WriteLong(FLT2FIX(floor->stairsDelayHeightDelta)); SV_WriteLong(FLT2FIX(floor->resetHeight)); SV_WriteShort(floor->resetDelay); SV_WriteShort(floor->resetDelayCount); #endif } static int SV_ReadFloor(floor_t* floor) { sector_t* sector; #if __JHEXEN__ if(saveVersion >= 4) #else if(hdr.version >= 5) #endif { // Note: the thinker class byte has already been read. byte ver = SV_ReadByte(); // version byte. floor->type = (floortype_e) SV_ReadByte(); sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!sector) Con_Error("TC_FLOOR: bad sector number\n"); floor->sector = sector; floor->crush = (boolean) SV_ReadByte(); floor->state = (int) SV_ReadLong(); floor->newSpecial = SV_ReadLong(); if(ver >= 2) floor->material = SV_GetArchiveMaterial(SV_ReadShort(), 0); else floor->material = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(W_LumpName(SV_ReadShort()), MN_FLATS)); floor->floorDestHeight = (float) SV_ReadShort(); floor->speed = FIX2FLT(SV_ReadLong()); #if __JHEXEN__ floor->delayCount = SV_ReadLong(); floor->delayTotal = SV_ReadLong(); floor->stairsDelayHeight = FIX2FLT(SV_ReadLong()); floor->stairsDelayHeightDelta = FIX2FLT(SV_ReadLong()); floor->resetHeight = FIX2FLT(SV_ReadLong()); floor->resetDelay = SV_ReadShort(); floor->resetDelayCount = SV_ReadShort(); /*floor->textureChange =*/ SV_ReadByte(); #endif } else { // Its in the old format which serialized floor_t // Padding at the start (an old thinker_t struct) SV_Read(junkbuffer, (size_t) 16); // Start of used data members. #if __JHEXEN__ // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_FLOOR: bad sector number\n"); floor->sector = sector; floor->type = SV_ReadLong(); floor->crush = SV_ReadLong(); #else floor->type = SV_ReadLong(); floor->crush = SV_ReadLong(); // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_FLOOR: bad sector number\n"); floor->sector = sector; #endif floor->state = (int) SV_ReadLong(); floor->newSpecial = SV_ReadLong(); floor->material = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(W_LumpName(SV_ReadShort()), MN_FLATS)); floor->floorDestHeight = FIX2FLT((fixed_t) SV_ReadLong()); floor->speed = FIX2FLT((fixed_t) SV_ReadLong()); #if __JHEXEN__ floor->delayCount = SV_ReadLong(); floor->delayTotal = SV_ReadLong(); floor->stairsDelayHeight = FIX2FLT((fixed_t) SV_ReadLong()); floor->stairsDelayHeightDelta = FIX2FLT((fixed_t) SV_ReadLong()); floor->resetHeight = FIX2FLT((fixed_t) SV_ReadLong()); floor->resetDelay = SV_ReadShort(); floor->resetDelayCount = SV_ReadShort(); /*floor->textureChange =*/ SV_ReadByte(); #endif } P_ToXSector(floor->sector)->specialData = floor; floor->thinker.function = T_MoveFloor; return true; // Add this thinker. } static void SV_WritePlat(const plat_t *plat) { SV_WriteByte(1); // Write a version byte. SV_WriteByte((byte) plat->type); SV_WriteLong(P_ToIndex(plat->sector)); SV_WriteLong(FLT2FIX(plat->speed)); SV_WriteShort((int)plat->low); SV_WriteShort((int)plat->high); SV_WriteLong(plat->wait); SV_WriteLong(plat->count); SV_WriteByte((byte) plat->state); SV_WriteByte((byte) plat->oldState); SV_WriteByte((byte) plat->crush); SV_WriteLong(plat->tag); } static int SV_ReadPlat(plat_t *plat) { sector_t *sector; #if __JHEXEN__ if(saveVersion >= 4) #else if(hdr.version >= 5) #endif { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. plat->thinker.function = T_PlatRaise; #if !__JHEXEN__ // Should we put this into stasis? if(hdr.version == 5) { if(!SV_ReadByte()) DD_ThinkerSetStasis(&plat->thinker, true); } #endif plat->type = (plattype_e) SV_ReadByte(); sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!sector) Con_Error("TC_PLAT: bad sector number\n"); plat->sector = sector; plat->speed = FIX2FLT(SV_ReadLong()); plat->low = (float) SV_ReadShort(); plat->high = (float) SV_ReadShort(); plat->wait = SV_ReadLong(); plat->count = SV_ReadLong(); plat->state = (platstate_e) SV_ReadByte(); plat->oldState = (platstate_e) SV_ReadByte(); plat->crush = (boolean) SV_ReadByte(); plat->tag = SV_ReadLong(); } else { // Its in the old format which serialized plat_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_PLAT: bad sector number\n"); plat->sector = sector; plat->speed = FIX2FLT((fixed_t) SV_ReadLong()); plat->low = FIX2FLT((fixed_t) SV_ReadLong()); plat->high = FIX2FLT((fixed_t) SV_ReadLong()); plat->wait = SV_ReadLong(); plat->count = SV_ReadLong(); plat->state = SV_ReadLong(); plat->oldState = SV_ReadLong(); plat->crush = SV_ReadLong(); plat->tag = SV_ReadLong(); plat->type = SV_ReadLong(); plat->thinker.function = T_PlatRaise; #if !__JHEXEN__ if(!junk.function) DD_ThinkerSetStasis(&plat->thinker, true); #endif } P_ToXSector(plat->sector)->specialData = plat; return true; // Add this thinker. } #if __JHEXEN__ static void SV_WriteLight(const light_t* th) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteByte((byte) th->type); SV_WriteLong(P_ToIndex(th->sector)); SV_WriteLong((int) (255.0f * th->value1)); SV_WriteLong((int) (255.0f * th->value2)); SV_WriteLong(th->tics1); SV_WriteLong(th->tics2); SV_WriteLong(th->count); } static int SV_ReadLight(light_t* th) { sector_t* sector; if(saveVersion >= 4) { /*int ver =*/ SV_ReadByte(); // version byte. th->type = (lighttype_t) SV_ReadByte(); sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!sector) Con_Error("TC_LIGHT: bad sector number\n"); th->sector = sector; th->value1 = (float) SV_ReadLong() / 255.0f; th->value2 = (float) SV_ReadLong() / 255.0f; th->tics1 = SV_ReadLong(); th->tics2 = SV_ReadLong(); th->count = SV_ReadLong(); } else { // Its in the old pre V4 format which serialized light_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_LIGHT: bad sector number\n"); th->sector = sector; th->type = (lighttype_t) SV_ReadLong(); th->value1 = (float) SV_ReadLong() / 255.0f; th->value2 = (float) SV_ReadLong() / 255.0f; th->tics1 = SV_ReadLong(); th->tics2 = SV_ReadLong(); th->count = SV_ReadLong(); } th->thinker.function = T_Light; return true; // Add this thinker. } static void SV_WritePhase(const phase_t* th) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(th->sector)); SV_WriteLong(th->index); SV_WriteLong((int) (255.0f * th->baseValue)); } static int SV_ReadPhase(phase_t* th) { sector_t* sector; if(saveVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_PHASE: bad sector number\n"); th->sector = sector; th->index = SV_ReadLong(); th->baseValue = (float) SV_ReadLong() / 255.0f; } else { // Its in the old pre V4 format which serialized phase_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_PHASE: bad sector number\n"); th->sector = sector; th->index = SV_ReadLong(); th->baseValue = (float) SV_ReadLong() / 255.0f; } th->thinker.function = T_Phase; return true; // Add this thinker. } static void SV_WriteScript(const acs_t* th) { uint i; SV_WriteByte(1); // Write a version byte. SV_WriteLong(SV_ThingArchiveNum(th->activator)); SV_WriteLong(th->line ? P_ToIndex(th->line) : -1); SV_WriteLong(th->side); SV_WriteLong(th->number); SV_WriteLong(th->infoIndex); SV_WriteLong(th->delayCount); for(i = 0; i < ACS_STACK_DEPTH; ++i) SV_WriteLong(th->stack[i]); SV_WriteLong(th->stackPtr); for(i = 0; i < MAX_ACS_SCRIPT_VARS; ++i) SV_WriteLong(th->vars[i]); SV_WriteLong((int) (th->ip) - (int) ActionCodeBase); } static int SV_ReadScript(acs_t* th) { int temp; uint i; if(saveVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. th->activator = (mobj_t*) SV_ReadLong(); th->activator = SV_GetArchiveThing((int) th->activator, &th->activator); temp = SV_ReadLong(); if(temp == -1) th->line = NULL; else th->line = P_ToPtr(DMU_LINEDEF, temp); th->side = SV_ReadLong(); th->number = SV_ReadLong(); th->infoIndex = SV_ReadLong(); th->delayCount = SV_ReadLong(); for(i = 0; i < ACS_STACK_DEPTH; ++i) th->stack[i] = SV_ReadLong(); th->stackPtr = SV_ReadLong(); for(i = 0; i < MAX_ACS_SCRIPT_VARS; ++i) th->vars[i] = SV_ReadLong(); th->ip = (int *) (ActionCodeBase + SV_ReadLong()); } else { // Its in the old pre V4 format which serialized acs_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. th->activator = (mobj_t*) SV_ReadLong(); th->activator = SV_GetArchiveThing((int) th->activator, &th->activator); temp = SV_ReadLong(); if(temp == -1) th->line = NULL; else th->line = P_ToPtr(DMU_LINEDEF, temp); th->side = SV_ReadLong(); th->number = SV_ReadLong(); th->infoIndex = SV_ReadLong(); th->delayCount = SV_ReadLong(); for(i = 0; i < ACS_STACK_DEPTH; ++i) th->stack[i] = SV_ReadLong(); th->stackPtr = SV_ReadLong(); for(i = 0; i < MAX_ACS_SCRIPT_VARS; ++i) th->vars[i] = SV_ReadLong(); th->ip = (int *) (ActionCodeBase + SV_ReadLong()); } th->thinker.function = T_InterpretACS; return true; // Add this thinker. } static void SV_WriteDoorPoly(const polydoor_t* th) { SV_WriteByte(1); // Write a version byte. SV_WriteByte(th->type); // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(th->polyobj); SV_WriteLong(th->intSpeed); SV_WriteLong(th->dist); SV_WriteLong(th->totalDist); SV_WriteLong(th->direction); SV_WriteLong(FLT2FIX(th->speed[VX])); SV_WriteLong(FLT2FIX(th->speed[VY])); SV_WriteLong(th->tics); SV_WriteLong(th->waitTics); SV_WriteByte(th->close); } static int SV_ReadDoorPoly(polydoor_t* th) { if(saveVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. // Start of used data members. th->type = SV_ReadByte(); th->polyobj = SV_ReadLong(); th->intSpeed = SV_ReadLong(); th->dist = SV_ReadLong(); th->totalDist = SV_ReadLong(); th->direction = SV_ReadLong(); th->speed[VX] = FIX2FLT(SV_ReadLong()); th->speed[VY] = FIX2FLT(SV_ReadLong()); th->tics = SV_ReadLong(); th->waitTics = SV_ReadLong(); th->close = SV_ReadByte(); } else { // Its in the old pre V4 format which serialized polydoor_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. th->polyobj = SV_ReadLong(); th->intSpeed = SV_ReadLong(); th->dist = SV_ReadLong(); th->totalDist = SV_ReadLong(); th->direction = SV_ReadLong(); th->speed[VX] = FIX2FLT(SV_ReadLong()); th->speed[VY] = FIX2FLT(SV_ReadLong()); th->tics = SV_ReadLong(); th->waitTics = SV_ReadLong(); th->type = SV_ReadByte(); th->close = SV_ReadByte(); } th->thinker.function = T_PolyDoor; return true; // Add this thinker. } static void SV_WriteMovePoly(const polyevent_t* th) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(th->polyobj); SV_WriteLong(th->intSpeed); SV_WriteLong(th->dist); SV_WriteLong(th->fangle); SV_WriteLong(FLT2FIX(th->speed[VX])); SV_WriteLong(FLT2FIX(th->speed[VY])); } static int SV_ReadMovePoly(polyevent_t* th) { if(saveVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. // Start of used data members. th->polyobj = SV_ReadLong(); th->intSpeed = SV_ReadLong(); th->dist = SV_ReadLong(); th->fangle = SV_ReadLong(); th->speed[VX] = FIX2FLT(SV_ReadLong()); th->speed[VY] = FIX2FLT(SV_ReadLong()); } else { // Its in the old pre V4 format which serialized polyevent_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. th->polyobj = SV_ReadLong(); th->intSpeed = SV_ReadLong(); th->dist = SV_ReadLong(); th->fangle = SV_ReadLong(); th->speed[VX] = FIX2FLT(SV_ReadLong()); th->speed[VY] = FIX2FLT(SV_ReadLong()); } th->thinker.function = T_MovePoly; return true; // Add this thinker. } static void SV_WriteRotatePoly(const polyevent_t* th) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(th->polyobj); SV_WriteLong(th->intSpeed); SV_WriteLong(th->dist); SV_WriteLong(th->fangle); SV_WriteLong(FLT2FIX(th->speed[VX])); SV_WriteLong(FLT2FIX(th->speed[VY])); } static int SV_ReadRotatePoly(polyevent_t* th) { if(saveVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. // Start of used data members. th->polyobj = SV_ReadLong(); th->intSpeed = SV_ReadLong(); th->dist = SV_ReadLong(); th->fangle = SV_ReadLong(); th->speed[VX] = FIX2FLT(SV_ReadLong()); th->speed[VY] = FIX2FLT(SV_ReadLong()); } else { // Its in the old pre V4 format which serialized polyevent_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. th->polyobj = SV_ReadLong(); th->intSpeed = SV_ReadLong(); th->dist = SV_ReadLong(); th->fangle = SV_ReadLong(); th->speed[VX] = FIX2FLT(SV_ReadLong()); th->speed[VY] = FIX2FLT(SV_ReadLong()); } th->thinker.function = T_RotatePoly; return true; // Add this thinker. } static void SV_WritePillar(const pillar_t* th) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(th->sector)); SV_WriteLong(FLT2FIX(th->ceilingSpeed)); SV_WriteLong(FLT2FIX(th->floorSpeed)); SV_WriteLong(FLT2FIX(th->floorDest)); SV_WriteLong(FLT2FIX(th->ceilingDest)); SV_WriteLong(th->direction); SV_WriteLong(th->crush); } static int SV_ReadPillar(pillar_t* th) { sector_t* sector; if(saveVersion >= 4) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. // Start of used data members. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_BUILD_PILLAR: bad sector number\n"); th->sector = sector; th->ceilingSpeed = FIX2FLT((fixed_t) SV_ReadLong()); th->floorSpeed = FIX2FLT((fixed_t) SV_ReadLong()); th->floorDest = FIX2FLT((fixed_t) SV_ReadLong()); th->ceilingDest = FIX2FLT((fixed_t) SV_ReadLong()); th->direction = SV_ReadLong(); th->crush = SV_ReadLong(); } else { // Its in the old pre V4 format which serialized pillar_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_BUILD_PILLAR: bad sector number\n"); th->sector = sector; th->ceilingSpeed = FIX2FLT((fixed_t) SV_ReadLong()); th->floorSpeed = FIX2FLT((fixed_t) SV_ReadLong()); th->floorDest = FIX2FLT((fixed_t) SV_ReadLong()); th->ceilingDest = FIX2FLT((fixed_t) SV_ReadLong()); th->direction = SV_ReadLong(); th->crush = SV_ReadLong(); } th->thinker.function = T_BuildPillar; P_ToXSector(th->sector)->specialData = th; return true; // Add this thinker. } static void SV_WriteFloorWaggle(const waggle_t* th) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(th->sector)); SV_WriteLong(FLT2FIX(th->originalHeight)); SV_WriteLong(FLT2FIX(th->accumulator)); SV_WriteLong(FLT2FIX(th->accDelta)); SV_WriteLong(FLT2FIX(th->targetScale)); SV_WriteLong(FLT2FIX(th->scale)); SV_WriteLong(FLT2FIX(th->scaleDelta)); SV_WriteLong(th->ticker); SV_WriteLong(th->state); } static int SV_ReadFloorWaggle(waggle_t* th) { sector_t* sector; if(saveVersion >= 4) { /*int ver =*/ SV_ReadByte(); // version byte. // Start of used data members. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_FLOOR_WAGGLE: bad sector number\n"); th->sector = sector; th->originalHeight = FIX2FLT((fixed_t) SV_ReadLong()); th->accumulator = FIX2FLT((fixed_t) SV_ReadLong()); th->accDelta = FIX2FLT((fixed_t) SV_ReadLong()); th->targetScale = FIX2FLT((fixed_t) SV_ReadLong()); th->scale = FIX2FLT((fixed_t) SV_ReadLong()); th->scaleDelta = FIX2FLT((fixed_t) SV_ReadLong()); th->ticker = SV_ReadLong(); th->state = SV_ReadLong(); } else { // Its in the old pre V4 format which serialized waggle_t // Padding at the start (an old thinker_t struct) thinker_t junk; SV_Read(&junk, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_FLOOR_WAGGLE: bad sector number\n"); th->sector = sector; th->originalHeight = FIX2FLT((fixed_t) SV_ReadLong()); th->accumulator = FIX2FLT((fixed_t) SV_ReadLong()); th->accDelta = FIX2FLT((fixed_t) SV_ReadLong()); th->targetScale = FIX2FLT((fixed_t) SV_ReadLong()); th->scale = FIX2FLT((fixed_t) SV_ReadLong()); th->scaleDelta = FIX2FLT((fixed_t) SV_ReadLong()); th->ticker = SV_ReadLong(); th->state = SV_ReadLong(); } th->thinker.function = T_FloorWaggle; P_ToXSector(th->sector)->specialData = th; return true; // Add this thinker. } #endif // __JHEXEN__ #if !__JHEXEN__ static void SV_WriteFlash(const lightflash_t* flash) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(flash->sector)); SV_WriteLong(flash->count); SV_WriteLong((int) (255.0f * flash->maxLight)); SV_WriteLong((int) (255.0f * flash->minLight)); SV_WriteLong(flash->maxTime); SV_WriteLong(flash->minTime); } static int SV_ReadFlash(lightflash_t* flash) { sector_t* sector; if(hdr.version >= 5) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. // Start of used data members. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_FLASH: bad sector number\n"); flash->sector = sector; flash->count = SV_ReadLong(); flash->maxLight = (float) SV_ReadLong() / 255.0f; flash->minLight = (float) SV_ReadLong() / 255.0f; flash->maxTime = SV_ReadLong(); flash->minTime = SV_ReadLong(); } else { // Its in the old pre V5 format which serialized lightflash_t // Padding at the start (an old thinker_t struct) SV_Read(junkbuffer, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_FLASH: bad sector number\n"); flash->sector = sector; flash->count = SV_ReadLong(); flash->maxLight = (float) SV_ReadLong() / 255.0f; flash->minLight = (float) SV_ReadLong() / 255.0f; flash->maxTime = SV_ReadLong(); flash->minTime = SV_ReadLong(); } flash->thinker.function = T_LightFlash; return true; // Add this thinker. } static void SV_WriteStrobe(const strobe_t* strobe) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(strobe->sector)); SV_WriteLong(strobe->count); SV_WriteLong((int) (255.0f * strobe->maxLight)); SV_WriteLong((int) (255.0f * strobe->minLight)); SV_WriteLong(strobe->darkTime); SV_WriteLong(strobe->brightTime); } static int SV_ReadStrobe(strobe_t* strobe) { sector_t* sector; if(hdr.version >= 5) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_STROBE: bad sector number\n"); strobe->sector = sector; strobe->count = SV_ReadLong(); strobe->maxLight = (float) SV_ReadLong() / 255.0f; strobe->minLight = (float) SV_ReadLong() / 255.0f; strobe->darkTime = SV_ReadLong(); strobe->brightTime = SV_ReadLong(); } else { // Its in the old pre V5 format which serialized strobe_t // Padding at the start (an old thinker_t struct) SV_Read(junkbuffer, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_STROBE: bad sector number\n"); strobe->sector = sector; strobe->count = SV_ReadLong(); strobe->minLight = (float) SV_ReadLong() / 255.0f; strobe->maxLight = (float) SV_ReadLong() / 255.0f; strobe->darkTime = SV_ReadLong(); strobe->brightTime = SV_ReadLong(); } strobe->thinker.function = T_StrobeFlash; return true; // Add this thinker. } static void SV_WriteGlow(const glow_t* glow) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(glow->sector)); SV_WriteLong((int) (255.0f * glow->maxLight)); SV_WriteLong((int) (255.0f * glow->minLight)); SV_WriteLong(glow->direction); } static int SV_ReadGlow(glow_t* glow) { sector_t* sector; if(hdr.version >= 5) { // Note: the thinker class byte has already been read. /*int ver =*/ SV_ReadByte(); // version byte. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_GLOW: bad sector number\n"); glow->sector = sector; glow->maxLight = (float) SV_ReadLong() / 255.0f; glow->minLight = (float) SV_ReadLong() / 255.0f; glow->direction = SV_ReadLong(); } else { // Its in the old pre V5 format which serialized strobe_t // Padding at the start (an old thinker_t struct) SV_Read(junkbuffer, (size_t) 16); // Start of used data members. // A 32bit pointer to sector, serialized. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_GLOW: bad sector number\n"); glow->sector = sector; glow->minLight = (float) SV_ReadLong() / 255.0f; glow->maxLight = (float) SV_ReadLong() / 255.0f; glow->direction = SV_ReadLong(); } glow->thinker.function = T_Glow; return true; // Add this thinker. } # if __JDOOM__ || __JDOOM64__ static void SV_WriteFlicker(const fireflicker_t* flicker) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(flicker->sector)); SV_WriteLong((int) (255.0f * flicker->maxLight)); SV_WriteLong((int) (255.0f * flicker->minLight)); } /** * T_FireFlicker was added to save games in ver5, therefore we don't have * an old format to support. */ static int SV_ReadFlicker(fireflicker_t* flicker) { sector_t* sector; /*int ver =*/ SV_ReadByte(); // version byte. // Note: the thinker class byte has already been read. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("TC_FLICKER: bad sector number\n"); flicker->sector = sector; flicker->maxLight = (float) SV_ReadLong() / 255.0f; flicker->minLight = (float) SV_ReadLong() / 255.0f; flicker->thinker.function = T_FireFlicker; return true; // Add this thinker. } # endif # if __JDOOM64__ static void SV_WriteBlink(const lightblink_t* blink) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. SV_WriteLong(P_ToIndex(blink->sector)); SV_WriteLong(blink->count); SV_WriteLong((int) (255.0f * blink->maxLight)); SV_WriteLong((int) (255.0f * blink->minLight)); SV_WriteLong(blink->maxTime); SV_WriteLong(blink->minTime); } /** * T_LightBlink was added to save games in ver5, therefore we don't have an * old format to support */ static int SV_ReadBlink(lightblink_t* blink) { sector_t* sector; /*int ver =*/ SV_ReadByte(); // version byte. // Note: the thinker class byte has already been read. sector = P_ToPtr(DMU_SECTOR, (int) SV_ReadLong()); if(!sector) Con_Error("tc_lightblink: bad sector number\n"); blink->sector = sector; blink->count = SV_ReadLong(); blink->maxLight = (float) SV_ReadLong() / 255.0f; blink->minLight = (float) SV_ReadLong() / 255.0f; blink->maxTime = SV_ReadLong(); blink->minTime = SV_ReadLong(); blink->thinker.function = T_LightBlink; return true; // Add this thinker. } # endif #endif // !__JHEXEN__ static void SV_WriteMaterialChanger(const materialchanger_t* mchanger) { SV_WriteByte(1); // Write a version byte. // Note we don't bother to save a byte to tell if the function // is present as we ALWAYS add one when loading. // Write a type byte. For future use (e.g., changing plane surface // materials as well as sidedef surface materials). SV_WriteByte(0); SV_WriteLong(mchanger->timer); SV_WriteLong(P_ToIndex(mchanger->side)); SV_WriteByte((byte) mchanger->ssurfaceID); SV_WriteShort(SV_MaterialArchiveNum(mchanger->material)); } static int SV_ReadMaterialChanger(materialchanger_t* mchanger) { sidedef_t* side; /*int ver =*/ SV_ReadByte(); // version byte. SV_ReadByte(); // Type byte. mchanger->timer = SV_ReadLong(); // Note: the thinker class byte has already been read. side = P_ToPtr(DMU_SIDEDEF, (int) SV_ReadLong()); if(!side) Con_Error("t_materialchanger: bad sidedef number\n"); mchanger->side = side; mchanger->ssurfaceID = (sidedefsurfaceid_t) SV_ReadByte(); mchanger->material = SV_GetArchiveMaterial(SV_ReadShort(), 0); mchanger->thinker.function = T_MaterialChanger; return true; // Add this thinker. } /** * Archives the specified thinker. * * @param th The thinker to be archived. */ static boolean archiveThinker(thinker_t* th, void* context) { boolean savePlayers = *(boolean*) context; // Are we archiving players? if(!(th->function == P_MobjThinker && ((mobj_t *) th)->player && !savePlayers)) { thinkerinfo_t* thInfo = infoForThinker(th); if(!thInfo) return true; // This is not a thinker we need to save. // Only the server saves this class of thinker? if(!((thInfo->flags & TSF_SERVERONLY) && IS_CLIENT)) { #if _DEBUG assert(thInfo->Write); #endif // Write the header block for this thinker. SV_WriteByte(thInfo->thinkclass); // Thinker type byte. SV_WriteByte(th->inStasis? 1 : 0); // In stasis? // Write the thinker data. thInfo->Write(th); } } return true; // Continue iteration. } /** * Archives thinkers for both client and server. * Clients do not save all data for all thinkers (the server will send * it to us anyway so saving it would just bloat client save games). * * \note Some thinker classes are NEVER saved by clients. */ static void P_ArchiveThinkers(boolean savePlayers) { boolean localSavePlayers = savePlayers; SV_BeginSegment(ASEG_THINKERS); #if __JHEXEN__ SV_WriteLong(thingArchiveSize); // number of mobjs. #endif // Save off the current thinkers. DD_IterateThinkers(NULL, archiveThinker, &localSavePlayers); // Add a terminating marker. SV_WriteByte(TC_END); } static boolean restoreMobjLinks(thinker_t* th, void* context) { mobj_t* mo = (mobj_t *) th; mo->target = SV_GetArchiveThing((int) mo->target, &mo->target); mo->onMobj = SV_GetArchiveThing((int) mo->onMobj, &mo->onMobj); #if __JHEXEN__ switch(mo->type) { // Just tracer case MT_BISH_FX: case MT_HOLY_FX: case MT_DRAGON: case MT_THRUSTFLOOR_UP: case MT_THRUSTFLOOR_DOWN: case MT_MINOTAUR: case MT_SORCFX1: if(saveVersion >= 3) { mo->tracer = SV_GetArchiveThing((int) mo->tracer, &mo->tracer); } else { mo->tracer = SV_GetArchiveThing(mo->special1, &mo->tracer); mo->special1 = 0; } break; // Just special2 case MT_LIGHTNING_FLOOR: case MT_LIGHTNING_ZAP: mo->special2 = (int) SV_GetArchiveThing(mo->special2, &mo->special2); break; // Both tracer and special2 case MT_HOLY_TAIL: case MT_LIGHTNING_CEILING: if(saveVersion >= 3) { mo->tracer = SV_GetArchiveThing((int) mo->tracer, &mo->tracer); } else { mo->tracer = SV_GetArchiveThing(mo->special1, &mo->tracer); mo->special1 = 0; } mo->special2 = (int) SV_GetArchiveThing(mo->special2, &mo->special2); break; default: break; } #else # if __JDOOM__ || __JDOOM64__ mo->tracer = SV_GetArchiveThing((int) mo->tracer, &mo->tracer); # endif # if __JHERETIC__ mo->generator = SV_GetArchiveThing((int) mo->generator, &mo->generator); # endif #endif return true; // Continue iteration. } /** * Un-Archives thinkers for both client and server. */ static void P_UnArchiveThinkers(void) { uint i; byte tClass; thinker_t *th = 0; thinkerinfo_t *thInfo = 0; boolean found, knownThinker; boolean inStasis; #if __JHEXEN__ boolean doSpecials = (saveVersion >= 4); #else boolean doSpecials = (hdr.version >= 5); #endif #if !__JHEXEN__ if(IS_SERVER) #endif { DD_IterateThinkers(NULL, removeThinker, NULL); DD_InitThinkers(); } #if __JHEXEN__ if(saveVersion < 4) AssertSegment(ASEG_MOBJS); else #endif AssertSegment(ASEG_THINKERS); #if __JHEXEN__ targetPlayerAddrs = NULL; SV_InitThingArchive(true, savingPlayers); #endif // Read in saved thinkers. #if __JHEXEN__ i = 0; #endif for(;;) { #if __JHEXEN__ if(doSpecials) #endif tClass = SV_ReadByte(); #if __JHEXEN__ if(saveVersion < 4) { if(doSpecials) // Have we started on the specials yet? { // Versions prior to 4 used a different value to mark // the end of the specials data and the thinker class ids // are differrent, so we need to manipulate the thinker // class identifier value. if(tClass != TC_END) tClass += 2; } else tClass = TC_MOBJ; if(tClass == TC_MOBJ && i == thingArchiveSize) { AssertSegment(ASEG_THINKERS); // We have reached the begining of the "specials" block. doSpecials = true; continue; } } #else if(hdr.version < 5) { if(doSpecials) // Have we started on the specials yet? { // Versions prior to 5 used a different value to mark // the end of the specials data so we need to manipulate // the thinker class identifier value. if(tClass == PRE_VER5_END_SPECIALS) tClass = TC_END; else tClass += 3; } else if(tClass == TC_END) { // We have reached the begining of the "specials" block. doSpecials = true; continue; } } #endif if(tClass == TC_END) break; // End of the list. found = knownThinker = inStasis = false; thInfo = thinkerInfo; while(thInfo->thinkclass != TC_NULL && !found) { if(thInfo->thinkclass == tClass) { found = true; // Not for us? (it shouldn't be here anyway!). if(!((thInfo->flags & TSF_SERVERONLY) && IS_CLIENT)) { // Mobjs use a special engine-side allocator. if(thInfo->thinkclass == TC_MOBJ) { th = (thinker_t*) P_MobjCreate(P_MobjThinker, 0, 0, 0, 0, 64, 64, 0); } else { th = Z_Calloc(thInfo->size, PU_MAP, 0); } // Is there a thinker header block? #if __JHEXEN__ if(saveVersion >= 6) #else if(hdr.version >= 6) #endif { inStasis = (boolean) SV_ReadByte(); } knownThinker = thInfo->Read(th); } } if(!found) thInfo++; } #if __JHEXEN__ if(tClass == TC_MOBJ) i++; #endif if(!found) Con_Error("P_UnarchiveThinkers: Unknown tClass %i in savegame", tClass); if(knownThinker) DD_ThinkerAdd(th); if(inStasis) DD_ThinkerSetStasis(th, true); } // Update references to things. #if __JHEXEN__ DD_IterateThinkers(P_MobjThinker, restoreMobjLinks, NULL); #else if(IS_SERVER) { DD_IterateThinkers(P_MobjThinker, restoreMobjLinks, NULL); for(i = 0; i < numlines; ++i) { xline_t *xline = P_ToXLine(P_ToPtr(DMU_LINEDEF, i)); if(xline->xg) xline->xg->activator = SV_GetArchiveThing((int) xline->xg->activator, &xline->xg->activator); } } #endif #if __JHEXEN__ P_CreateTIDList(); P_InitCreatureCorpseQueue(true); // true = scan for corpses #endif } #if __JDOOM__ static void P_ArchiveBrain(void) { int i; SV_WriteByte(numBrainTargets); SV_WriteByte(brain.targetOn); // Write the mobj references using the mobj archive. for(i = 0; i < numBrainTargets; ++i) SV_WriteShort(SV_ThingArchiveNum(brainTargets[i])); } static void P_UnArchiveBrain(void) { int i; if(hdr.version < 3) return; // No brain data before version 3. numBrainTargets = SV_ReadByte(); brain.targetOn = SV_ReadByte(); for(i = 0; i < numBrainTargets; ++i) { brainTargets[i] = (mobj_t*) (int) SV_ReadShort(); brainTargets[i] = SV_GetArchiveThing((int) brainTargets[i], NULL); } if(gameMode == commercial) P_SpawnBrainTargets(); } #endif #if !__JHEXEN__ static void P_ArchiveSoundTargets(void) { uint i; xsector_t* xsec; // Write the total number. SV_WriteLong(numSoundTargets); // Write the mobj references using the mobj archive. for(i = 0; i < numsectors; ++i) { xsec = P_ToXSector(P_ToPtr(DMU_SECTOR, i)); if(xsec->soundTarget) { SV_WriteLong(i); SV_WriteShort(SV_ThingArchiveNum(xsec->soundTarget)); } } } static void P_UnArchiveSoundTargets(void) { uint i; uint secid; uint numsoundtargets; xsector_t* xsec; // Sound Target data was introduced in ver 5 if(hdr.version < 5) return; // Read the number of targets numsoundtargets = SV_ReadLong(); // Read in the sound targets. for(i = 0; i < numsoundtargets; ++i) { secid = SV_ReadLong(); if(secid > numsectors) Con_Error("P_UnArchiveSoundTargets: bad sector number\n"); xsec = P_ToXSector(P_ToPtr(DMU_SECTOR, secid)); xsec->soundTarget = (mobj_t*) (int) SV_ReadShort(); xsec->soundTarget = SV_GetArchiveThing((int) xsec->soundTarget, &xsec->soundTarget); } } #endif #if __JHEXEN__ static void P_ArchiveSounds(void) { uint i; int difference; seqnode_t* node; sector_t* sec; // Save the sound sequences. SV_BeginSegment(ASEG_SOUNDS); SV_WriteLong(ActiveSequences); for(node = SequenceListHead; node; node = node->next) { SV_WriteByte(1); // Write a version byte. SV_WriteLong(node->sequence); SV_WriteLong(node->delayTics); SV_WriteLong(node->volume); SV_WriteLong(SN_GetSequenceOffset(node->sequence, node->sequencePtr)); SV_WriteLong(node->currentSoundID); i = 0; if(node->mobj) { for(; i < numpolyobjs; ++i) { if(node->mobj == (mobj_t*) P_GetPolyobj(i | 0x80000000)) { break; } } } if(i == numpolyobjs) { // Sound is attached to a sector, not a polyobj. sec = P_GetPtrp(R_PointInSubsector(node->mobj->pos[VX], node->mobj->pos[VY]), DMU_SECTOR); difference = P_ToIndex(sec); SV_WriteLong(0); // 0 -- sector sound origin. } else { SV_WriteLong(1); // 1 -- polyobj sound origin difference = i; } SV_WriteLong(difference); } } static void P_UnArchiveSounds(void) { int i; int numSequences, sequence, seqOffset; int delayTics, soundID, volume; int polySnd, secNum, ver; mobj_t* sndMobj = NULL; AssertSegment(ASEG_SOUNDS); // Reload and restart all sound sequences numSequences = SV_ReadLong(); i = 0; while(i < numSequences) { if(saveVersion >= 3) ver = SV_ReadByte(); sequence = SV_ReadLong(); delayTics = SV_ReadLong(); volume = SV_ReadLong(); seqOffset = SV_ReadLong(); soundID = SV_ReadLong(); polySnd = SV_ReadLong(); secNum = SV_ReadLong(); if(!polySnd) { sndMobj = P_GetPtr(DMU_SECTOR, secNum, DMU_SOUND_ORIGIN); } else { polyobj_t* po; if((po = P_GetPolyobj(secNum | 0x80000000))) sndMobj = (mobj_t*) po; } SN_StartSequence(sndMobj, sequence); SN_ChangeNodeData(i, seqOffset, delayTics, volume, soundID); i++; } } static void P_ArchiveScripts(void) { int i; SV_BeginSegment(ASEG_SCRIPTS); for(i = 0; i < ACScriptCount; ++i) { SV_WriteShort(ACSInfo[i].state); SV_WriteShort(ACSInfo[i].waitValue); } for(i = 0; i < MAX_ACS_MAP_VARS; ++i) SV_WriteLong(MapVars[i]); } static void P_UnArchiveScripts(void) { int i; AssertSegment(ASEG_SCRIPTS); for(i = 0; i < ACScriptCount; ++i) { ACSInfo[i].state = SV_ReadShort(); ACSInfo[i].waitValue = SV_ReadShort(); } for(i = 0; i < MAX_ACS_MAP_VARS; ++i) MapVars[i] = SV_ReadLong(); } static void P_ArchiveGlobalScriptData(void) { int i; SV_BeginSegment(ASEG_GLOBALSCRIPTDATA); SV_WriteByte(3); // version byte for(i = 0; i < MAX_ACS_WORLD_VARS; ++i) SV_WriteLong(WorldVars[i]); SV_WriteLong(ACSStoreSize); for(i = 0; i < ACSStoreSize; ++i) { const acsstore_t* store = &ACSStore[i]; int j; SV_WriteLong(store->map); SV_WriteLong(store->script); for(j = 0; j < 4; ++j) SV_WriteByte(store->args[j]); } } static void P_UnArchiveGlobalScriptData(void) { int i, ver = 1; if(saveVersion >= 7) { AssertSegment(ASEG_GLOBALSCRIPTDATA); ver = SV_ReadByte(); } for(i = 0; i < MAX_ACS_WORLD_VARS; ++i) WorldVars[i] = SV_ReadLong(); if(ver >= 3) { ACSStoreSize = SV_ReadLong(); if(ACSStoreSize) { if(ACSStore) ACSStore = Z_Realloc(ACSStore, sizeof(acsstore_t) * ACSStoreSize, PU_STATIC); else ACSStore = Z_Malloc(sizeof(acsstore_t) * ACSStoreSize, PU_STATIC, 0); for(i = 0; i < ACSStoreSize; ++i) { acsstore_t* store = &ACSStore[i]; int j; store->map = SV_ReadLong(); store->script = SV_ReadLong(); for(j = 0; j < 4; ++j) store->args[j] = SV_ReadByte(); } } } else { // Old format. acsstore_t tempStore[20]; ACSStoreSize = 0; for(i = 0; i < 20; ++i) { int map = SV_ReadLong(); acsstore_t* store = &tempStore[map < 0? 19 : ACSStoreSize++]; int j; store->map = map < 0? 0 : map-1; store->script = SV_ReadLong(); for(j = 0; j < 4; ++j) store->args[j] = SV_ReadByte(); } if(saveVersion < 7) SV_Read(junkbuffer, 12); // Junk. if(ACSStoreSize) { if(ACSStore) ACSStore = Z_Realloc(ACSStore, sizeof(acsstore_t) * ACSStoreSize, PU_STATIC); else ACSStore = Z_Malloc(sizeof(acsstore_t) * ACSStoreSize, PU_STATIC, 0); memcpy(ACSStore, tempStore, sizeof(acsstore_t) * ACSStoreSize); } } if(!ACSStoreSize && ACSStore) { Z_Free(ACSStore); ACSStore = NULL; } } static void P_ArchiveMisc(void) { int ix; SV_BeginSegment(ASEG_MISC); for(ix = 0; ix < MAXPLAYERS; ++ix) { SV_WriteLong(localQuakeHappening[ix]); } } static void P_UnArchiveMisc(void) { int ix; AssertSegment(ASEG_MISC); for(ix = 0; ix < MAXPLAYERS; ++ix) { localQuakeHappening[ix] = SV_ReadLong(); } } #endif static void P_ArchiveMap(boolean savePlayers) { // Place a header marker SV_BeginSegment(ASEG_MAP_HEADER2); #if __JHEXEN__ savingPlayers = savePlayers; // Write a version byte SV_WriteByte(MY_SAVE_VERSION); // Write the map timer SV_WriteLong(mapTime); #else // Clear the sound target count (determined while saving sectors). numSoundTargets = 0; #endif SV_InitMaterialArchives(); P_ArchiveWorld(); P_ArchiveThinkers(savePlayers); #if __JHEXEN__ P_ArchiveScripts(); P_ArchiveSounds(); P_ArchiveMisc(); #else if(IS_SERVER) { # if __JDOOM__ // Doom saves the brain data, too. (It's a part of the world.) P_ArchiveBrain(); # endif // Save the sound target data (prevents bug where monsters who have // been alerted go back to sleep when loading a save game). P_ArchiveSoundTargets(); } #endif // Place a termination marker SV_BeginSegment(ASEG_END); } static void P_UnArchiveMap(void) { #if __JHEXEN__ int segType = SV_ReadLong(); // Determine the map version. if(segType == ASEG_MAP_HEADER2) { saveVersion = SV_ReadByte(); } else if(segType == ASEG_MAP_HEADER) { saveVersion = 2; } else { Con_Error("Corrupt save game: Segment [%d] failed alignment check", ASEG_MAP_HEADER); } #else AssertSegment(ASEG_MAP_HEADER2); #endif #if __JHEXEN__ // Read the map timer mapTime = SV_ReadLong(); #endif P_UnArchiveWorld(); P_UnArchiveThinkers(); #if __JHEXEN__ P_UnArchiveScripts(); P_UnArchiveSounds(); P_UnArchiveMisc(); #else if(IS_SERVER) { #if __JDOOM__ // Doom saves the brain data, too. (It's a part of the world.) P_UnArchiveBrain(); #endif // Read the sound target data (prevents bug where monsters who have // been alerted go back to sleep when loading a save game). P_UnArchiveSoundTargets(); } #endif AssertSegment(ASEG_END); } int SV_GetSaveDescription(char* str, const char* filename, size_t len) { #if __JHEXEN__ LZFILE* fp; filename_t name; char versionText[HXS_VERSION_TEXT_LENGTH]; boolean found = false; strncpy(name, filename, FILENAME_T_MAXLEN); M_TranslatePath(name, name, FILENAME_T_MAXLEN); fp = lzOpen(name, "rp"); if(fp) { lzRead(str, len, fp); lzRead(versionText, HXS_VERSION_TEXT_LENGTH, fp); lzClose(fp); if(!strncmp(versionText, HXS_VERSION_TEXT, 8)) { saveVersion = atoi(&versionText[8]); if(saveVersion <= MY_SAVE_VERSION) found = true; } } return found; #else savefile = lzOpen((char*)filename, "rp"); if(!savefile) { # if __JDOOM64__ // We don't support the original game's save format (for obvious // reasons). return false; # else // It might still be a v19 savegame. savefile = lzOpen((char*)filename, "r"); if(!savefile) return false; // It just doesn't exist. lzRead(str, len, savefile); str[len - 1] = 0; lzClose(savefile); return true; # endif } // Read the header. lzRead(&hdr, sizeof(hdr), savefile); lzClose(savefile); // Check the magic. if(hdr.magic != MY_SAVE_MAGIC) // This isn't a proper savegame file. return false; strncpy(str, hdr.description, len); return true; #endif } /** * Initialize the savegame directories. * If the directories do not exist, they are created. */ void SV_Init(void) { if(ArgCheckWith("-savedir", 1)) { strcpy(savePath, ArgNext()); // Add a trailing backslash is necessary. if(savePath[strlen(savePath) - 1] != '\\') strcat(savePath, "\\"); } else { // Use the default path. #if __JHEXEN__ sprintf(savePath, "hexndata\\%s\\", (char *) G_GetVariable(DD_GAME_MODE)); #else sprintf(savePath, "savegame\\%s\\", (char *) G_GetVariable(DD_GAME_MODE)); #endif } // Build the client save path. strcpy(clientSavePath, savePath); strcat(clientSavePath, "client\\"); // Check that the save paths exist. M_CheckPath(savePath); M_CheckPath(clientSavePath); #if !__JHEXEN__ M_TranslatePath(savePath, savePath, FILENAME_T_MAXLEN); M_TranslatePath(clientSavePath, clientSavePath, FILENAME_T_MAXLEN); #endif } void SV_GetSaveGameFileName(char* str, int slot, size_t len) { dd_snprintf(str, len, "%s" SAVEGAMENAME "%i." SAVEGAMEEXTENSION, savePath, slot); } void SV_GetClientSaveGameFileName(char* str, unsigned int gameID, size_t len) { dd_snprintf(str, len, "%s" CLIENTSAVEGAMENAME "%08X." SAVEGAMEEXTENSION, clientSavePath, gameID); } static boolean openSaveGameFile(const char* fileName, boolean write) { #if __JHEXEN__ if(!write) return M_ReadFile(fileName, &saveBuffer) > 0; else #endif savefile = lzOpen((char*)fileName, write? "wp" : "rp"); return savefile? true : false; } enum { SV_OK = 0, SV_INVALIDFILENAME, }; typedef struct savegameparam_s { #if __JHEXEN__ int slot; #endif const char* filename; const char* description; } savegameparam_t; int SV_SaveGameWorker(void* ptr) { savegameparam_t* param = ptr; #if __JHEXEN__ char versionText[HXS_VERSION_TEXT_LENGTH]; #else int i; #endif VERBOSE(Con_Message("SV_SaveGame: Attempting save game to " "\"%s\".\n", M_PrettyPath(param->filename))); // Open the output file if(!openSaveGameFile(param->filename, true)) { Con_BusyWorkerEnd(); return SV_INVALIDFILENAME; // No success. } playerHeaderOK = false; // Uninitialized. #if __JHEXEN__ // Write game save description SV_Write(param->description, SAVESTRINGSIZE); // Write version info memset(versionText, 0, HXS_VERSION_TEXT_LENGTH); sprintf(versionText, HXS_VERSION_TEXT"%i", MY_SAVE_VERSION); SV_Write(versionText, HXS_VERSION_TEXT_LENGTH); // Place a header marker SV_BeginSegment(ASEG_GAME_HEADER); // Write current map and difficulty SV_WriteByte(gameMap+1); SV_WriteByte(gameSkill); SV_WriteByte(deathmatch); SV_WriteByte(noMonstersParm); SV_WriteByte(randomClassParm); // Write global script info P_ArchiveGlobalScriptData(); #else // Write the header. hdr.magic = MY_SAVE_MAGIC; hdr.version = MY_SAVE_VERSION; # if __JDOOM__ || __JDOOM64__ hdr.gameMode = gameMode; # elif __JHERETIC__ hdr.gameMode = 0; # endif strncpy(hdr.description, param->description, SAVESTRINGSIZE); hdr.description[SAVESTRINGSIZE - 1] = 0; hdr.skill = gameSkill; if(fastParm) hdr.skill |= 0x80; // Set high byte. hdr.episode = gameEpisode+1; hdr.map = gameMap+1; hdr.deathmatch = deathmatch; hdr.noMonsters = noMonstersParm; hdr.respawnMonsters = respawnMonsters; hdr.mapTime = mapTime; hdr.gameID = SV_GameID(); for(i = 0; i < MAXPLAYERS; i++) hdr.players[i] = players[i].plr->inGame; lzWrite(&hdr, sizeof(hdr), savefile); // In netgames the server tells the clients to save their games. NetSv_SaveGame(hdr.gameID); #endif // Set the mobj archive numbers SV_InitThingArchive(false, true); #if !__JHEXEN__ SV_WriteLong(thingArchiveSize); #endif P_ArchivePlayerHeader(); P_ArchivePlayers(); // Place a termination marker SV_BeginSegment(ASEG_END); #if __JHEXEN__ // Close the output file (maps are saved into a seperate file). CloseStreamOut(); #endif // Save out the current map #if __JHEXEN__ { filename_t fileName; // Open the output file dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex6%02u.hxs", savePath, gameMap+1); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); OpenStreamOut(fileName); P_ArchiveMap(true); // true = save player info // Close the output file CloseStreamOut(); } #else P_ArchiveMap(true); #endif #if!__JHEXEN__ // To be absolutely sure... SV_WriteByte(CONSISTENCY); SV_FreeThingArchive(); lzClose(savefile); #endif #if __JHEXEN__ // Clear all save files at destination slot. ClearSaveSlot(param->slot); // Copy base slot to destination slot CopySaveSlot(BASE_SLOT, param->slot); #endif Con_BusyWorkerEnd(); return SV_OK; // Success! } #if __JHEXEN__ boolean SV_SaveGame(int slot, const char *description) #else boolean SV_SaveGame(const char* filename, const char *description) #endif { int result; #if __JHEXEN__ filename_t filename; #endif savegameparam_t param; #if __JHEXEN__ param.slot = slot; #endif #if __JHEXEN__ dd_snprintf(filename, FILENAME_T_MAXLEN, "%shex6.hxs", savePath); M_TranslatePath(filename, filename, FILENAME_T_MAXLEN); #endif param.filename = filename; param.description = description; // \todo Use progress bar mode and update progress during the setup. result = Con_Busy(BUSYF_ACTIVITY | /*BUSYF_PROGRESS_BAR |*/ (verbose? BUSYF_CONSOLE_OUTPUT : 0), "Saving game...", SV_SaveGameWorker, ¶m); if(result == SV_INVALIDFILENAME) { Con_Message("P_SaveGame: Couldn't open \"%s\" for writing.\n", filename); } return result; } #if __JHEXEN__ static boolean readSaveHeader(void) #else static boolean readSaveHeader(saveheader_t *hdr, LZFILE *savefile) #endif { #if __JHEXEN__ // Set the save pointer and skip the description field saveptr.b = saveBuffer + SAVESTRINGSIZE; if(strncmp((const char*) saveptr.b, HXS_VERSION_TEXT, 8)) { Con_Message("SV_LoadGame: Bad magic.\n"); return false; } saveVersion = atoi((const char*) (saveptr.b + 8)); // Check for unsupported versions. if(saveVersion > MY_SAVE_VERSION) { return false; // A future version } // We are incompatible with ver3 saves. Due to an invalid test // used to determine present sidedefs, the ver3 format's sides // included chunks of junk data. if(saveVersion == 3) return false; saveptr.b += HXS_VERSION_TEXT_LENGTH; AssertSegment(ASEG_GAME_HEADER); gameEpisode = 0; gameMap = SV_ReadByte() - 1; gameSkill = SV_ReadByte(); deathmatch = SV_ReadByte(); noMonstersParm = SV_ReadByte(); randomClassParm = SV_ReadByte(); #else lzRead(hdr, sizeof(*hdr), savefile); if(hdr->magic != MY_SAVE_MAGIC) { Con_Message("SV_LoadGame: Bad magic.\n"); return false; } // Check for unsupported versions. if(hdr->version > MY_SAVE_VERSION) { return false; // A future version. } # if __JDOOM__ || __JDOOM64__ if(hdr->gameMode != gameMode && !ArgExists("-nosavecheck")) { Con_Message("SV_LoadGame: savegame not from gameMode %i.\n", gameMode); return false; } # endif gameSkill = hdr->skill & 0x7f; fastParm = (hdr->skill & 0x80) != 0; gameEpisode = hdr->episode - 1; gameMap = hdr->map - 1; deathmatch = hdr->deathmatch; noMonstersParm = hdr->noMonsters; respawnMonsters = hdr->respawnMonsters; #endif return true; // Read was OK. } static boolean SV_LoadGame2(void) { int i; char buf[80]; boolean loaded[MAXPLAYERS], infile[MAXPLAYERS]; #if __JHEXEN__ int k; #endif // Read the header. #if __JHEXEN__ if(!readSaveHeader()) #else if(!readSaveHeader(&hdr, savefile)) #endif return false; // Something went wrong. // Allocate a small junk buffer. // (Data from old save versions is read into here). junkbuffer = malloc(sizeof(byte) * 64); // Read global save data not part of the game metadata. #if __JHEXEN__ // Read global script info. P_UnArchiveGlobalScriptData(); #endif // We don't want to see a briefing if we're loading a save game. briefDisabled = true; // Load the map and configure some game settings. G_InitNew(gameSkill, gameEpisode, gameMap); #if !__JHEXEN__ // Set the time. mapTime = hdr.mapTime; SV_InitThingArchive(true, true); #endif P_UnArchivePlayerHeader(); // Read the player structures AssertSegment(ASEG_PLAYERS); // We don't have the right to say which players are in the game. The // players that already are will continue to be. If the data for a given // player is not in the savegame file, he will be notified. The data for // players who were saved but are not currently in the game will be // discarded. #if !__JHEXEN__ for(i = 0; i < MAXPLAYERS; ++i) infile[i] = hdr.players[i]; #else for(i = 0; i < MAXPLAYERS; ++i) infile[i] = SV_ReadByte(); #endif memset(loaded, 0, sizeof(loaded)); P_UnArchivePlayers(infile, loaded); AssertSegment(ASEG_END); #if __JHEXEN__ Z_Free(saveBuffer); #endif // Load the current map state. unarchiveMap(); #if !__JHEXEN__ // Check consistency. if(SV_ReadByte() != CONSISTENCY) Con_Error("SV_LoadGame: Bad savegame (consistency test failed!)\n"); // We're done. SV_FreeThingArchive(); lzClose(savefile); #endif #if __JHEXEN__ // Don't need the player mobj relocation info for load game SV_FreeTargetPlayerList(); #endif // Notify the players that weren't in the savegame. for(i = 0; i < MAXPLAYERS; ++i) { boolean notLoaded = false; #if __JHEXEN__ if(players[i].plr->inGame) { // Try to find a saved player that corresponds this one. for(k = 0; k < MAXPLAYERS; ++k) if(saveToRealPlayerNum[k] == i) break; if(k < MAXPLAYERS) continue; // Found; don't bother this player. players[i].playerState = PST_REBORN; if(!i) { // If the CONSOLEPLAYER isn't in the save, it must be some // other player's file? P_SetMessage(players, GET_TXT(TXT_LOADMISSING), false); } else { NetSv_SendMessage(i, GET_TXT(TXT_LOADMISSING)); notLoaded = true; } } #else if(!loaded[i] && players[i].plr->inGame) { if(!i) { P_SetMessage(players, GET_TXT(TXT_LOADMISSING), false); } else { NetSv_SendMessage(i, GET_TXT(TXT_LOADMISSING)); } notLoaded = true; } #endif if(notLoaded) { // Kick this player out, he doesn't belong here. sprintf(buf, "kick %i", i); DD_Execute(false, buf); } } #if !__JHEXEN__ // In netgames, the server tells the clients about this. NetSv_LoadGame(hdr.gameID); #endif return true; // Success! } #if __JHEXEN__ boolean SV_LoadGame(int slot) #else boolean SV_LoadGame(const char* fileName) #endif { boolean result = false; #if __JHEXEN__ filename_t fileName; // Copy all needed save files to the base slot if(slot != BASE_SLOT) { ClearSaveSlot(BASE_SLOT); CopySaveSlot(slot, BASE_SLOT); } // Create the name dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex6.hxs", savePath); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); #endif VERBOSE(Con_Message("SV_LoadGame: Attempting load of save game " "\"%s\".\n", M_PrettyPath(fileName))); if(openSaveGameFile(fileName, false)) { playerHeaderOK = false; // Uninitialized. return SV_LoadGame2(); } // It might be an original game save? #if __JDOOM__ result = SV_v19_LoadGame(fileName); #elif __JHERETIC__ result = SV_v13_LoadGame(fileName); #endif if(!result) Con_Message("SV_LoadGame: Warning, failed loading save game " "\"%s\".\n", M_PrettyPath(fileName)); return result; } /** * Saves a snapshot of the world, a still image. * No data of movement is included (server sends it). */ void SV_SaveClient(unsigned int gameID) { #if !__JHEXEN__ // unsupported in jHexen filename_t name; player_t* pl = &players[CONSOLEPLAYER]; mobj_t* mo = pl->plr->mo; if(!IS_CLIENT || !mo) return; playerHeaderOK = false; // Uninitialized. SV_GetClientSaveGameFileName(name, gameID, FILENAME_T_MAXLEN); // Open the file. savefile = lzOpen(name, "wp"); if(!savefile) { Con_Message("SV_SaveClient: Couldn't open \"%s\" for writing.\n", name); return; } // Prepare the header. memset(&hdr, 0, sizeof(hdr)); hdr.magic = MY_CLIENT_SAVE_MAGIC; hdr.version = MY_SAVE_VERSION; hdr.skill = gameSkill; hdr.episode = gameEpisode+1; hdr.map = gameMap+1; hdr.deathmatch = deathmatch; hdr.noMonsters = noMonstersParm; hdr.respawnMonsters = respawnMonsters; hdr.mapTime = mapTime; hdr.gameID = gameID; SV_Write(&hdr, sizeof(hdr)); // Some important information. // Our position and look angles. SV_WriteLong(FLT2FIX(mo->pos[VX])); SV_WriteLong(FLT2FIX(mo->pos[VY])); SV_WriteLong(FLT2FIX(mo->pos[VZ])); SV_WriteLong(FLT2FIX(mo->floorZ)); SV_WriteLong(FLT2FIX(mo->ceilingZ)); SV_WriteLong(mo->angle); /* $unifiedangles */ SV_WriteFloat(pl->plr->lookDir); /* $unifiedangles */ P_ArchivePlayerHeader(); SV_WritePlayer(CONSOLEPLAYER); P_ArchiveMap(true); lzClose(savefile); free(junkbuffer); #endif } void SV_LoadClient(unsigned int gameid) { #if !__JHEXEN__ // unsupported in jHexen filename_t name; player_t* cpl = players + CONSOLEPLAYER; mobj_t* mo = cpl->plr->mo; if(!IS_CLIENT || !mo) return; playerHeaderOK = false; // Uninitialized. SV_GetClientSaveGameFileName(name, gameid, FILENAME_T_MAXLEN); // Try to open the file. savefile = lzOpen(name, "rp"); if(!savefile) return; SV_Read(&hdr, sizeof(hdr)); if(hdr.magic != MY_CLIENT_SAVE_MAGIC) { lzClose(savefile); Con_Message("SV_LoadClient: Bad magic!\n"); return; } // Allocate a small junk buffer. // (Data from old save versions is read into here) junkbuffer = malloc(sizeof(byte) * 64); gameSkill = hdr.skill; deathmatch = hdr.deathmatch; noMonstersParm = hdr.noMonsters; respawnMonsters = hdr.respawnMonsters; // Do we need to change the map? if(gameMap != hdr.map - 1 || gameEpisode != hdr.episode - 1) { gameMap = hdr.map - 1; gameEpisode = hdr.episode - 1; G_InitNew(gameSkill, gameEpisode, gameMap); } mapTime = hdr.mapTime; P_MobjUnsetPosition(mo); mo->pos[VX] = FIX2FLT(SV_ReadLong()); mo->pos[VY] = FIX2FLT(SV_ReadLong()); mo->pos[VZ] = FIX2FLT(SV_ReadLong()); P_MobjSetPosition(mo); mo->floorZ = FIX2FLT(SV_ReadLong()); mo->ceilingZ = FIX2FLT(SV_ReadLong()); mo->angle = SV_ReadLong(); /* $unifiedangles */ cpl->plr->lookDir = SV_ReadFloat(); /* $unifiedangles */ P_UnArchivePlayerHeader(); SV_ReadPlayer(cpl); P_UnArchiveMap(); lzClose(savefile); free(junkbuffer); #endif } static void unarchiveMap(void) { #if __JHEXEN__ filename_t fileName; // Create the name dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex6%02u.hxs", savePath, gameMap+1); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); #ifdef _DEBUG Con_Printf("unarchiveMap: Reading %s\n", fileName); #endif // Load the file M_ReadFile(fileName, &saveBuffer); saveptr.b = saveBuffer; #endif P_UnArchiveMap(); #if __JHEXEN__ // Free mobj list and save buffer SV_FreeThingArchive(); Z_Free(saveBuffer); #endif // Spawn particle generators, fix HOMS etc, etc... R_SetupMap(DDSMM_AFTER_LOADING, 0); } #if __JHEXEN__ void SV_MapTeleport(uint map, uint position) { int i, oldKeys = 0, oldPieces = 0, bestWeapon; filename_t fileName; player_t playerBackup[MAXPLAYERS]; uint numInventoryItems[MAXPLAYERS][NUM_INVENTORYITEM_TYPES]; inventoryitemtype_t readyItem[MAXPLAYERS]; mobj_t* targetPlayerMobj; boolean rClass, playerWasReborn, revisit; boolean oldWeaponOwned[NUM_WEAPON_TYPES]; playerHeaderOK = false; // Uninitialized. /** * First, determine whether we've been to this map previously and if so, * whether we need to load the archived map state. */ dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex6%02u.hxs", savePath, map+1); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); if(!deathmatch && ExistingFile(fileName)) revisit = true; else revisit = false; if(!deathmatch) { if(P_GetMapCluster(gameMap) == P_GetMapCluster(map)) { // Same cluster - save current map without saving player mobjs. filename_t fileName; // Set the mobj archive numbers SV_InitThingArchive(false, false); // Open the output file dd_snprintf(fileName, FILENAME_T_MAXLEN, "%shex6%02u.hxs", savePath, gameMap+1); M_TranslatePath(fileName, fileName, FILENAME_T_MAXLEN); OpenStreamOut(fileName); P_ArchiveMap(false); // Close the output file CloseStreamOut(); } else { // Entering new cluster - clear base slot ClearSaveSlot(BASE_SLOT); } } // Store player structs for later rClass = randomClassParm; randomClassParm = false; for(i = 0; i < MAXPLAYERS; ++i) { uint j; memcpy(&playerBackup[i], &players[i], sizeof(player_t)); for(j = 0; j < NUM_INVENTORYITEM_TYPES; ++j) numInventoryItems[i][j] = P_InventoryCount(i, j); readyItem[i] = P_InventoryReadyItem(i); } // Only unarchiveMap() uses targetPlayerAddrs, so it's NULLed here // for the following check (player mobj redirection) targetPlayerAddrs = NULL; // We don't want to see a briefing if we're loading a save game. if(revisit) briefDisabled = true; G_InitNew(gameSkill, gameEpisode, map); if(revisit) { // Been here before, load the previous map state. unarchiveMap(); } else { // First visit. // Destroy all freshly spawned players for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { P_MobjRemove(players[i].plr->mo, true); } } } // Restore player structs. targetPlayerMobj = NULL; for(i = 0; i < MAXPLAYERS; ++i) { uint j; if(!players[i].plr->inGame) { continue; } memcpy(&players[i], &playerBackup[i], sizeof(player_t)); for(j = 0; j < NUM_INVENTORYITEM_TYPES; ++j) { uint k; // Don't give back the wings of wrath if reborn. if(j == IIT_FLY && players[i].playerState == PST_REBORN) continue; for(k = 0; k < numInventoryItems[i][j]; ++k) P_InventoryGive(i, j, true); } P_InventorySetReadyItem(i, readyItem[i]); Hu_LogEmpty(i); players[i].attacker = NULL; players[i].poisoner = NULL; if(IS_NETGAME || deathmatch) { if(players[i].playerState == PST_DEAD) { // In a network game, force all players to be alive players[i].playerState = PST_REBORN; } if(!deathmatch) { // Cooperative net-play, retain keys and weapons oldKeys = players[i].keys; oldPieces = players[i].pieces; for(j = 0; j < NUM_WEAPON_TYPES; j++) { oldWeaponOwned[j] = players[i].weapons[j].owned; } } } playerWasReborn = (players[i].playerState == PST_REBORN); if(deathmatch) { memset(players[i].frags, 0, sizeof(players[i].frags)); players[i].plr->mo = NULL; G_DeathMatchSpawnPlayer(i); } else { const playerstart_t* start; if((start = P_GetPlayerStart(position, i, false))) { P_SpawnPlayer(i, cfg.playerClass[i], start->pos[VX], start->pos[VY], start->pos[VZ], start->angle, start->spawnFlags, false, true); } else { P_SpawnPlayer(i, cfg.playerClass[i], 0, 0, 0, 0, MSF_Z_FLOOR, true, true); } } if(playerWasReborn && IS_NETGAME && !deathmatch) { // Restore keys and weapons when reborn in co-op players[i].keys = oldKeys; players[i].pieces = oldPieces; for(bestWeapon = 0, j = 0; j < NUM_WEAPON_TYPES; ++j) { if(oldWeaponOwned[j]) { bestWeapon = j; players[i].weapons[j].owned = true; } } players[i].ammo[AT_BLUEMANA].owned = 25; //// \fixme values.ded players[i].ammo[AT_GREENMANA].owned = 25; //// \fixme values.ded if(bestWeapon) { // Bring up the best weapon players[i].pendingWeapon = bestWeapon; } } if(targetPlayerMobj == NULL) { // The poor sap. targetPlayerMobj = players[i].plr->mo; } } randomClassParm = rClass; //// \fixme Redirect anything targeting a player mobj //// FIXME! This only supports single player games!! if(targetPlayerAddrs) { targetplraddress_t *p; p = targetPlayerAddrs; while(p != NULL) { *(p->address) = targetPlayerMobj; p = p->next; } SV_FreeTargetPlayerList(); /* DJS - When XG is available in jHexen, call this after updating target player references (after a load). // The activator mobjs must be set. XL_UpdateActivators(); */ } // Destroy all things touching players for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { P_TeleportMove(players[i].plr->mo, players[i].plr->mo->pos[VX], players[i].plr->mo->pos[VY], true); } } // Launch waiting scripts if(!deathmatch) { P_CheckACSStore(gameMap); } // For single play, save immediately into the reborn slot if(!IS_NETGAME && !deathmatch) { SV_SaveGame(REBORN_SLOT, REBORN_DESCRIPTION); } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/m_fixed.c0000644000175000017500000000654111357170242022412 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2004 Lukasz Stelmach * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_fixed.c: Fixed-point math. * * Define NO_FIXED_ASM to disable the assembler version. */ // HEADER FILES ------------------------------------------------------------ #include #include "dd_share.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- #ifdef NO_FIXED_ASM fixed_t FixedMul(fixed_t a, fixed_t b) { // Let's do this in an ultra-slow way. return (fixed_t) (((double) a * (double) b) / FRACUNIT); } fixed_t FixedDiv2(fixed_t a, fixed_t b) { if(!b) return 0; // We've got cycles to spare! return (fixed_t) (((double) a / (double) b) * FRACUNIT); } #endif #ifdef GNU_X86_FIXED_ASM // Courtesy of Lukasz Stelmach. fixed_t FixedMul(fixed_t a, fixed_t b) { asm volatile ( "imull %2\n\t" "shrdl $16, %%edx, %%eax" : "=a" (a) : "a" (a), "r" (b) : "edx" ); return a; } fixed_t FixedDiv2(fixed_t a, fixed_t b) { asm volatile ( "cdq\n\t" "shldl $16, %%eax, %%edx\n\t" "sall $16 ,%%eax\n\t" "idivl %2" : "=a" (a) : "a" (a), "r" (b) : "edx" ); return a; } #endif fixed_t FixedDiv(fixed_t a, fixed_t b) { if((abs(a) >> 14) >= abs(b)) { return ((a ^ b) < 0 ? DDMININT : DDMAXINT); } return (FixedDiv2(a, b)); } short ShortSwap(short n) { return ((n & 0xff) << 8) | ((n & 0xff00) >> 8); } long LongSwap(long n) { return (((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); } float FloatSwap(float f) { long temp = 0; float returnValue = 0; memcpy(&temp, &f, 4); // Must be 4. temp = LongSwap(temp); memcpy(&returnValue, &temp, 4); // Must be 4. return returnValue; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_ceiling.c0000644000175000017500000003636311357170242022735 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Martin Eyre *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_ceilings.c : Moving ceilings (lowering, crushing, raising). */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "dmu_lib.h" #include "p_mapspec.h" #include "p_start.h" #include "p_tick.h" #include "p_ceiling.h" // MACROS ------------------------------------------------------------------ // Sounds played by the ceilings when changing state or moving. // jHexen uses sound sequences, so it's are defined as 'SFX_NONE'. #if __JDOOM__ # define SFX_CEILINGMOVE (SFX_STNMOV) # define SFX_CEILINGSTOP (SFX_PSTOP) #elif __JDOOM64__ # define SFX_CEILINGMOVE (SFX_STNMOV) # define SFX_CEILINGSTOP (SFX_PSTOP) #elif __JHERETIC__ # define SFX_CEILINGMOVE (SFX_DORMOV) # define SFX_CEILINGSTOP (SFX_NONE) #elif __JHEXEN__ # define SFX_CEILINGMOVE (SFX_NONE) # define SFX_CEILINGSTOP (SFX_NONE) #endif // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Called when a moving ceiling needs to be removed. * * @param ceiling Ptr to the ceiling to be stopped. */ static void stopCeiling(ceiling_t* ceiling) { P_ToXSector(ceiling->sector)->specialData = NULL; #if __JHEXEN__ P_TagFinished(P_ToXSector(ceiling->sector)->tag); #endif DD_ThinkerRemove(&ceiling->thinker); } void T_MoveCeiling(ceiling_t* ceiling) { result_e res; switch(ceiling->state) { case CS_UP: // Going up. res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->topHeight, false, 1, 1); // Play a "while-moving" sound? #if !__JHEXEN__ if(!(mapTime & 7)) { # if __JHERETIC__ S_SectorSound(ceiling->sector, SORG_CEILING, SFX_CEILINGMOVE); # else switch(ceiling->type) { case CT_SILENTCRUSHANDRAISE: break; default: S_SectorSound(ceiling->sector, SORG_CEILING, SFX_CEILINGMOVE); break; } # endif } #endif if(res == pastdest) { #if __JHEXEN__ SN_StopSequence(P_SectorSoundOrigin(ceiling->sector)); #endif switch(ceiling->type) { #if !__JHEXEN__ case CT_RAISETOHIGHEST: # if __JDOOM64__ case CT_CUSTOM: //jd64 # endif stopCeiling(ceiling); break; # if !__JHERETIC__ case CT_SILENTCRUSHANDRAISE: S_SectorSound(ceiling->sector, SORG_CEILING, SFX_CEILINGSTOP); # endif case CT_CRUSHANDRAISEFAST: #endif case CT_CRUSHANDRAISE: ceiling->state = CS_DOWN; #if __JHEXEN__ ceiling->speed *= 2; #endif break; default: #if __JHEXEN__ stopCeiling(ceiling); #endif break; } } break; case CS_DOWN: // Going down. res = T_MovePlane(ceiling->sector, ceiling->speed, ceiling->bottomHeight, ceiling->crush, 1, -1); // Play a "while-moving" sound? #if !__JHEXEN__ if(!(mapTime & 7)) { # if __JHERETIC__ S_SectorSound(ceiling->sector, SORG_CEILING, SFX_CEILINGMOVE); # else switch(ceiling->type) { case CT_SILENTCRUSHANDRAISE: break; default: S_SectorSound(ceiling->sector, SORG_CEILING, SFX_CEILINGMOVE); } # endif } #endif if(res == pastdest) { #if __JHEXEN__ SN_StopSequence(P_SectorSoundOrigin(ceiling->sector)); #endif switch(ceiling->type) { #if __JDOOM__ || __JDOOM64__ case CT_SILENTCRUSHANDRAISE: S_SectorSound(ceiling->sector, SORG_CEILING, SFX_CEILINGSTOP); ceiling->speed = CEILSPEED; ceiling->state = CS_UP; break; #endif case CT_CRUSHANDRAISE: #if __JHEXEN__ case CT_CRUSHRAISEANDSTAY: #endif #if __JHEXEN__ ceiling->speed = ceiling->speed * .5; #else ceiling->speed = CEILSPEED; #endif ceiling->state = CS_UP; break; #if !__JHEXEN__ case CT_CRUSHANDRAISEFAST: ceiling->state = CS_UP; break; case CT_LOWERANDCRUSH: case CT_LOWERTOFLOOR: # if __JDOOM64__ case CT_CUSTOM: //jd64 # endif stopCeiling(ceiling); break; #endif default: #if __JHEXEN__ stopCeiling(ceiling); #endif break; } } else // ( res != pastdest ) { if(res == crushed) { switch(ceiling->type) { #if __JDOOM__ || __JDOOM64__ case CT_SILENTCRUSHANDRAISE: #endif case CT_CRUSHANDRAISE: case CT_LOWERANDCRUSH: #if __JHEXEN__ case CT_CRUSHRAISEANDSTAY: #endif #if !__JHEXEN__ ceiling->speed = CEILSPEED * .125; #endif break; default: break; } } } break; } } #if __JDOOM64__ static int EV_DoCeiling2(linedef_t* line, int tag, float basespeed, ceilingtype_e type) #elif __JHEXEN__ static int EV_DoCeiling2(byte* arg, int tag, float basespeed, ceilingtype_e type) #else static int EV_DoCeiling2(int tag, float basespeed, ceilingtype_e type) #endif { int rtn = 0; xsector_t* xsec; sector_t* sec = NULL; ceiling_t* ceiling; iterlist_t* list; list = P_GetSectorIterListForTag(tag, false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { xsec = P_ToXSector(sec); if(xsec->specialData) continue; // new door thinker rtn = 1; ceiling = Z_Calloc(sizeof(*ceiling), PU_MAP, 0); ceiling->thinker.function = T_MoveCeiling; DD_ThinkerAdd(&ceiling->thinker); xsec->specialData = ceiling; ceiling->sector = sec; ceiling->crush = false; ceiling->speed = basespeed; switch(type) { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ case CT_CRUSHANDRAISEFAST: ceiling->crush = true; ceiling->topHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT); ceiling->bottomHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + 8; ceiling->state = CS_DOWN; ceiling->speed *= 2; break; #endif #if __JHEXEN__ case CT_CRUSHRAISEANDSTAY: ceiling->crush = (int) arg[2]; // arg[2] = crushing value ceiling->topHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT); ceiling->bottomHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + 8; ceiling->state = CS_DOWN; break; #endif #if __JDOOM__ || __JDOOM64__ case CT_SILENTCRUSHANDRAISE: #endif case CT_CRUSHANDRAISE: #if !__JHEXEN__ ceiling->crush = true; #endif ceiling->topHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT); case CT_LOWERANDCRUSH: #if __JHEXEN__ ceiling->crush = (int) arg[2]; // arg[2] = crushing value #endif case CT_LOWERTOFLOOR: ceiling->bottomHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); if(type != CT_LOWERTOFLOOR) ceiling->bottomHeight += 8; ceiling->state = CS_DOWN; #if __JDOOM64__ ceiling->speed *= 8; // jd64 #endif break; case CT_RAISETOHIGHEST: P_FindSectorSurroundingHighestCeiling(sec, 0, &ceiling->topHeight); #if __JDOOM64__ ceiling->topHeight -= 8; // jd64 #endif ceiling->state = CS_UP; break; #if __JDOOM64__ case CT_CUSTOM: // jd64 { //bitmip? wha? sidedef_t *front = P_GetPtrp(line, DMU_SIDEDEF0); sidedef_t *back = P_GetPtrp(line, DMU_SIDEDEF1); float bitmipL = 0, bitmipR = 0; bitmipL = P_GetFloatp(front, DMU_MIDDLE_MATERIAL_OFFSET_X); if(back) bitmipR = P_GetFloatp(back, DMU_MIDDLE_MATERIAL_OFFSET_X); if(bitmipR > 0) { P_FindSectorSurroundingHighestCeiling(sec, 0, &ceiling->topHeight); ceiling->state = CS_UP; ceiling->speed *= bitmipL; ceiling->topHeight -= bitmipR; } else { ceiling->bottomHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); ceiling->bottomHeight -= bitmipR; ceiling->state = CS_DOWN; ceiling->speed *= bitmipL; } } #endif #if __JHEXEN__ case CT_LOWERBYVALUE: ceiling->bottomHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT) - (float) arg[2]; ceiling->state = CS_DOWN; break; case CT_RAISEBYVALUE: ceiling->topHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT) + (float) arg[2]; ceiling->state = CS_UP; break; case CT_MOVETOVALUEMUL8: { float destHeight = (float) arg[2] * 8; if(arg[3]) // Going down? destHeight = -destHeight; if(P_GetFloatp(sec, DMU_CEILING_HEIGHT) <= destHeight) { ceiling->state = CS_UP; ceiling->topHeight = destHeight; if(P_GetFloatp(sec, DMU_CEILING_HEIGHT) == destHeight) rtn = 0; } else if(P_GetFloatp(sec, DMU_CEILING_HEIGHT) > destHeight) { ceiling->state = CS_DOWN; ceiling->bottomHeight = destHeight; } break; } #endif default: #if __JHEXEN__ rtn = 0; #endif break; } ceiling->tag = xsec->tag; ceiling->type = type; #if __JHEXEN__ if(rtn) { SN_StartSequence(P_SectorSoundOrigin(ceiling->sector), SEQ_PLATFORM + P_ToXSector(ceiling->sector)->seqType); } #endif } return rtn; } /** * Move a ceiling up/down. */ #if __JHEXEN__ int EV_DoCeiling(linedef_t *line, byte *args, ceilingtype_e type) #else int EV_DoCeiling(linedef_t *line, ceilingtype_e type) #endif { #if __JHEXEN__ return EV_DoCeiling2(args, (int) args[0], (float) args[1] * (1.0 / 8), type); #else int rtn = 0; // Reactivate in-stasis ceilings...for certain types. switch(type) { case CT_CRUSHANDRAISEFAST: # if __JDOOM__ || __JDOOM64__ case CT_SILENTCRUSHANDRAISE: # endif case CT_CRUSHANDRAISE: rtn = P_CeilingActivate(P_ToXLine(line)->tag); break; default: break; } # if __JDOOM64__ return EV_DoCeiling2(line, P_ToXLine(line)->tag, CEILSPEED, type) || rtn; # else return EV_DoCeiling2(P_ToXLine(line)->tag, CEILSPEED, type) || rtn; # endif #endif } #if !__JHEXEN__ typedef struct { short tag; int count; } activateceilingparams_t; static boolean activateCeiling(thinker_t* th, void* context) { ceiling_t* ceiling = (ceiling_t*) th; activateceilingparams_t* params = (activateceilingparams_t*) context; if(ceiling->tag == (int) params->tag && ceiling->thinker.inStasis) { ceiling->state = ceiling->oldState; DD_ThinkerSetStasis(&ceiling->thinker, false); params->count++; } return true; // Continue iteration. } /** * Reactivates all stopped crushers with the right tag. * * @param tag Tag of ceilings to activate. * * @return @c true, if a ceiling is activated. */ int P_CeilingActivate(short tag) { activateceilingparams_t params; params.tag = tag; params.count = 0; DD_IterateThinkers(T_MoveCeiling, activateCeiling, ¶ms); return params.count; } #endif typedef struct { short tag; int count; } deactivateceilingparams_t; static boolean deactivateCeiling(thinker_t* th, void* context) { ceiling_t* ceiling = (ceiling_t*) th; deactivateceilingparams_t* params = (deactivateceilingparams_t*) context; #if __JHEXEN__ if(ceiling->tag == (int) params->tag) { // Destroy it. SN_StopSequence(P_SectorSoundOrigin(ceiling->sector)); stopCeiling(ceiling); params->count++; return false; // Stop iteration. } #else if(!ceiling->thinker.inStasis && ceiling->tag == (int) params->tag) { // Put it into stasis. ceiling->oldState = ceiling->state; DD_ThinkerSetStasis(&ceiling->thinker, true); params->count++; } #endif return true; // Continue iteration. } /** * Stops all active ceilings with the right tag. * * @param tag Tag of ceilings to stop. * * @return @c true, if a ceiling put in stasis. */ int P_CeilingDeactivate(short tag) { deactivateceilingparams_t params; params.tag = tag; params.count = 0; DD_IterateThinkers(T_MoveCeiling, deactivateCeiling, ¶ms); return params.count; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/hu_msg.c0000644000175000017500000002113411357170242022254 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_msg.c: Important state change messages. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "hu_msg.h" #include "hu_menu.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdMsgResponse); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- ccmd_t msgCCmds[] = { {"messageyes", "", CCmdMsgResponse}, {"messageno", "", CCmdMsgResponse}, {"messagecancel", "", CCmdMsgResponse}, {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean awaitingResponse; static int messageToPrint; // 1 = message to be printed. static msgresponse_t messageResponse; static msgtype_t msgType; static msgfunc_t msgCallback; static char* msgText; static void* msgContext; static char yesNoMessage[160]; // CODE -------------------------------------------------------------------- /** * Called during the PreInit of each game during start up. * Register Cvars and CCmds for the important messages. */ void Hu_MsgRegister(void) { int i; for(i = 0; msgCCmds[i].name; ++i) Con_AddCommand(msgCCmds + i); } /** * Called during init. */ void Hu_MsgInit(void) { awaitingResponse = false; messageToPrint = 0; // 1 = message to be printed. messageResponse = MSG_CANCEL; msgCallback = NULL; msgText = NULL; msgContext = NULL; } /** * Called during engine shutdown. */ void Hu_MsgShutdown(void) { if(msgText) free(msgText); msgText = NULL; } static void stopMessage(void) { #if __JDOOM__ || __JDOOM64__ # define SFX_ENDMESSAGE SFX_SWTCHX #elif __JHERETIC__ # define SFX_ENDMESSAGE SFX_CHAT #elif __JHEXEN__ # define SFX_ENDMESSAGE SFX_DOOR_LIGHT_CLOSE #endif messageToPrint = 0; awaitingResponse = false; if(msgText) free(msgText); msgText = NULL; S_LocalSound(SFX_ENDMESSAGE, NULL); // Disable the message binding context. DD_Executef(true, "deactivatebcontext message"); #undef SFX_ENDMESSAGE } /** * \todo: Query the bindings to determine the actual controls bound to the * message response commands. */ static void composeYesNoMessage(void) { char* buf = yesNoMessage, *in, tmp[2]; buf[0] = 0; tmp[1] = 0; // Get the message template. in = PRESSYN; for(; *in; in++) { if(in[0] == '%') { if(in[1] == '1') { strcat(buf, "Y"); in++; continue; } if(in[1] == '2') { strcat(buf, "N"); in++; continue; } if(in[1] == '%') in++; } tmp[0] = *in; strcat(buf, tmp); } } static void drawMessage(void) { int x, y; char* p; y = 100 - M_StringHeight(msgText, GF_FONTA) / 2; p = msgText; while(*p) { char* string = p, c; while((c = *p) && *p != '\n') p++; *p = 0; x = 160 - M_StringWidth(string, GF_FONTA) / 2; M_WriteText3(x, y, string, GF_FONTA, cfg.menuColor2[0], cfg.menuColor2[1], cfg.menuColor2[2], 1, true, true, 0); y += M_StringHeight(string, GF_FONTA); if(((*p) = c)) p++; } // An additional blank line between the message and response prompt. y += M_StringHeight("A", GF_FONTA); switch(msgType) { case MSG_ANYKEY: x = 160 - M_StringWidth(PRESSKEY, GF_FONTA) / 2; M_WriteText3(x, y, PRESSKEY, GF_FONTA, cfg.menuColor2[0], cfg.menuColor2[1], cfg.menuColor2[2], 1, true, true, 0); break; case MSG_YESNO: x = 160 - M_StringWidth(yesNoMessage, GF_FONTA) / 2; M_WriteText3(x, y, yesNoMessage, GF_FONTA, cfg.menuColor2[0], cfg.menuColor2[1], cfg.menuColor2[2], 1, true, true, 0); break; default: Con_Error("drawMessage: Internal error, unknown message type %i.\n", (int) msgType); } } /** * Draw any active message. */ void Hu_MsgDrawer(void) { if(!messageToPrint) return; // Scale by the hudScale. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(160, 100, 0); DGL_Scalef(cfg.hudScale, cfg.hudScale, 1); DGL_Translatef(-160, -100, 0); // Draw the message. drawMessage(); // Restore original matrices. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } /** * Updates on Game Tick. */ void Hu_MsgTicker(timespan_t time) { // Check if there has been a response to a message. if(!messageToPrint || awaitingResponse) return; // We can now stop the message. stopMessage(); if(msgType != MSG_ANYKEY && msgCallback) msgCallback(messageResponse, msgContext); } /** * If an "any key" message is active, respond to the event. */ boolean Hu_MsgResponder(event_t* ev) { if(!messageToPrint || msgType != MSG_ANYKEY) return false; // We are only interested in key downs. if(ev->state == EVS_DOWN && (ev->type == EV_KEY || ev->type == EV_MOUSE_BUTTON || ev->type == EV_JOY_BUTTON)) { stopMessage(); return true; } return true; } boolean Hu_IsMessageActive(void) { return messageToPrint; } /** * Begin a new message. */ void Hu_MsgStart(msgtype_t type, const char* msg, msgfunc_t callback, void* context) { assert(msg); awaitingResponse = true; messageResponse = 0; messageToPrint = 1; msgType = type; msgCallback = callback; msgContext = context; // Take a copy of the message string. msgText = calloc(1, strlen(msg)+1); strncpy(msgText, msg, strlen(msg)); if(msgType == MSG_YESNO) composeYesNoMessage(); typeInTime = 0; // If the console is open, close it. This message must be noticed! Con_Open(false); // Enable the message binding context. DD_Execute(true, "activatebcontext message"); } /** * Handles responses to messages requiring input. */ DEFCC(CCmdMsgResponse) { if(messageToPrint) { // Handle "Press any key to continue" messages. if(messageToPrint && msgType == MSG_ANYKEY) { stopMessage(); return true; } if(!stricmp(argv[0], "messageyes")) { awaitingResponse = false; messageResponse = MSG_YES; return true; } else if(!stricmp(argv[0], "messageno")) { awaitingResponse = false; messageResponse = MSG_NO; return true; } else if(!stricmp(argv[0], "messagecancel")) { awaitingResponse = false; messageResponse = MSG_CANCEL; return true; } } return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/st_lib.c0000644000175000017500000001111111357170242022240 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_lib.c: The status bar widget code. */ // HEADER FILES ------------------------------------------------------------ #include #if __JDOOM__ # include "jdoom.h" # include "hu_stuff.h" #elif __JDOOM64__ # include "jdoom64.h" # include "hu_stuff.h" #elif __JHERETIC__ # include "jheretic.h" # include "hu_stuff.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "st_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void STlib_InitNum(st_number_t* n, int x, int y, dpatch_t* pl, int* num, int maxDigits, float alpha) { n->x = x; n->y = y; n->maxDigits = maxDigits; n->alpha = alpha; n->num = num; n->p = pl; } void STlib_DrawNum(st_number_t* n, float alpha) { int numdigits = n->maxDigits; int num = *n->num; int w = n->p[0].width; int x = n->x; int neg; neg = num < 0; if(neg) { if(numdigits == 2 && num < -9) num = -9; else if(numdigits == 3 && num < -99) num = -99; num = -num; } x = n->x - numdigits * w; // If non-number, do not draw it. if(num == 1994) return; x = n->x; // In the special case of 0, you draw 0. if(!num) WI_DrawPatch(x - w, n->y, 1, 1, 1, n->alpha * alpha, &n->p[0], NULL, false, ALIGN_LEFT); // Draw the number. while(num && numdigits--) { x -= w; WI_DrawPatch(x, n->y, 1, 1, 1, n->alpha * alpha, &n->p[num % 10], NULL, false, ALIGN_LEFT); num /= 10; } // Draw a minus sign if necessary. if(neg) WI_DrawPatch(x - 8, n->y, 1, 1, 1, n->alpha * alpha, &huMinus, NULL, false, ALIGN_LEFT); } void STlib_InitPercent(st_percent_t* p, int x, int y, dpatch_t* pl, int* num, dpatch_t* percent, float alpha) { STlib_InitNum(&p->n, x, y, pl, num, 3, alpha); p->p = percent; } void STlib_DrawPercent(st_percent_t* per, float alpha) { WI_DrawPatch(per->n.x, per->n.y, 1, 1, 1, per->n.alpha * alpha, per->p, NULL, false, ALIGN_LEFT); STlib_DrawNum(&per->n, alpha); } void STlib_InitIcon(st_icon_t* b, int x, int y, dpatch_t* i, float alpha) { b->x = x; b->y = y; b->alpha = alpha; b->p = i; } void STlib_DrawIcon(st_icon_t* bi, float alpha) { WI_DrawPatch(bi->x, bi->y, 1, 1, 1, bi->alpha * alpha, bi->p, NULL, false, ALIGN_LEFT); } void STlib_InitMultiIcon(st_multiicon_t* i, int x, int y, dpatch_t* il, float alpha) { i->x = x; i->y = y; i->alpha = alpha; i->p = il; } void STlib_DrawMultiIcon(st_multiicon_t* mi, int iconNum, float alpha) { if(iconNum >= 0) WI_DrawPatch(mi->x, mi->y, 1, 1, 1, mi->alpha * alpha, &mi->p[iconNum], NULL, false, ALIGN_LEFT); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/hu_stuff.c0000644000175000017500000024240111357170242022617 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_stuff.c: Heads-up displays, font handling, text drawing routines */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "hu_menu.h" #include "hu_msg.h" #include "hu_stuff.h" #include "hu_log.h" #include "p_mapsetup.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Counter Cheat flags. #define CCH_KILLS 0x1 #define CCH_ITEMS 0x2 #define CCH_SECRET 0x4 #define CCH_KILLS_PRCNT 0x8 #define CCH_ITEMS_PRCNT 0x10 #define CCH_SECRET_PRCNT 0x20 #endif // TYPES ------------------------------------------------------------------- typedef struct { boolean active; int scoreHideTics; float scoreAlpha; } hudstate_t; // Column flags #define CF_HIDE 0x0001 #define CF_FIXEDWIDTH 0x0002 typedef struct { const char* label; int type; short flags; // CF_* flags. boolean alignRight; } column_t; typedef struct fogeffectlayer_s { float texOffset[2]; float texAngle; float posAngle; } fogeffectlayer_t; typedef struct fogeffectdata_s { DGLuint texture; float alpha, targetAlpha; fogeffectlayer_t layers[2]; float joinY; boolean scrollDir; } fogeffectdata_t; typedef struct fontpatch_s { byte ch; char lumpName[9]; } fontpatch_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static gamefont_t gFonts[NUM_GAME_FONTS]; static gamefontid_t currentGFontIndex; #if __JHERETIC__ || __JHEXEN__ dpatch_t dpSmallNumbers[10]; #endif dpatch_t huMinus; int typeInTime = 0; #if __JDOOM__ || __JDOOM64__ // Name graphics of each map. dpatch_t* mapNamePatches = NULL; // Name graphics of each skill mode. dpatch_t skillModeNames[NUM_SKILL_MODES]; dpatch_t m_pause; // Paused graphic. #endif #if __JDOOM__ // Name graphics of each episode. dpatch_t* episodeNamePatches = NULL; #endif #if __JHERETIC__ || __JHEXEN__ dpatch_t dpInvItemBox; dpatch_t dpInvSelectBox; dpatch_t dpInvPageLeft[2]; dpatch_t dpInvPageRight[2]; #endif const char shiftXForm[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, ' ', '!', '"', '#', '$', '%', '&', '"', // shift-' '(', ')', '*', '+', '<', // shift-, '_', // shift-- '>', // shift-. '?', // shift-/ ')', // shift-0 '!', // shift-1 '@', // shift-2 '#', // shift-3 '$', // shift-4 '%', // shift-5 '^', // shift-6 '&', // shift-7 '*', // shift-8 '(', // shift-9 ':', ':', // shift-; '<', '+', // shift-= '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '[', // shift-[ '!', // shift-backslash ']', // shift-] '"', '_', '\'', // shift-` 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '{', '|', '}', '~', 127 }; cvar_t hudCVars[] = { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ {"map-cheat-counter", 0, CVT_BYTE, &cfg.counterCheat, 0, 63}, {"map-cheat-counter-scale", 0, CVT_FLOAT, &cfg.counterCheatScale, .1f, 1}, #endif {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static hudstate_t hudStates[MAXPLAYERS]; static dpatch_t borderPatches[8]; static fogeffectdata_t fogEffectData; // Code ------------------------------------------------------------------- /** * Called during pre-init to register cvars and ccmds for the hud displays. */ void HU_Register(void) { uint i; for(i = 0; hudCVars[i].name; ++i) Con_AddVariable(&hudCVars[i]); } void R_SetFontCharacter(gamefontid_t fontid, byte ch, const char* lumpname) { gamefont_t* font; if(!(fontid >= GF_FIRST && fontid < NUM_GAME_FONTS)) { Con_Message("R_SetFontCharacter: Warning, unknown font id %i.\n", (int) fontid); return; } font = &gFonts[fontid]; memset(font->chars[ch].lumpname, 0, sizeof(font->chars[ch].lumpname)); strncpy(font->chars[ch].lumpname, lumpname, 8); // Instruct Doomsday to load the patch in monochrome mode. // (2 = weighted average). DD_SetInteger(DD_MONOCHROME_PATCHES, 2); DD_SetInteger(DD_UPSCALE_AND_SHARPEN_PATCHES, true); R_CachePatch(&font->chars[ch].patch, font->chars[ch].lumpname); DD_SetInteger(DD_MONOCHROME_PATCHES, 0); DD_SetInteger(DD_UPSCALE_AND_SHARPEN_PATCHES, false); } void R_InitFont(gamefontid_t fontid, const fontpatch_t* patches, size_t num) { size_t i; gamefont_t* font; if(!(fontid >= GF_FIRST && fontid < NUM_GAME_FONTS)) { Con_Message("R_InitFont: Warning, unknown font id %i.\n", (int) fontid); return; } font = &gFonts[fontid]; memset(font, 0, sizeof(*font)); for(i = 0; i < num; ++i) { const fontpatch_t* p = &patches[i]; R_SetFontCharacter(fontid, p->ch, p->lumpName); } } /** * Change the current font. */ void R_SetFont(gamefontid_t fontid) { if(!(fontid >= GF_FIRST && fontid < NUM_GAME_FONTS)) return; // No such font. currentGFontIndex = fontid; } gamefontid_t R_GetCurrentFont(void) { if(currentGFontIndex == -1) return 0; return currentGFontIndex; } /** * Loads the font patches and inits various strings * JHEXEN Note: Don't bother with the yellow font, we'll colour the white version */ void Hu_LoadData(void) { int i; char name[9]; #if __JDOOM__ || __JDOOM64__ static const char* skillModePatchNames[] = { "M_JKILL", "M_ROUGH", "M_HURT", "M_ULTRA", # if __JDOOM__ "M_NMARE" # endif }; #endif #if __JDOOM__ static const char* episodePatchNames[] = { "M_EPI1", "M_EPI2", "M_EPI3", "M_EPI4" }; #endif /** * \todo Read this information from a definition (ideally with more user * friendly mnemonics). */ #if __JDOOM__ || __JDOOM64__ static const fontpatch_t fontA[] = { { 32, "STCFN032" }, // ' ' { 33, "STCFN033" }, // ! { 34, "STCFN034" }, // " { 35, "STCFN035" }, // # { 36, "STCFN036" }, // $ { 37, "STCFN037" }, // % { 38, "STCFN038" }, // & { 39, "STCFN039" }, // ' { 40, "STCFN040" }, // ( { 41, "STCFN041" }, // ) { 42, "STCFN042" }, // * { 43, "STCFN043" }, // + { 44, "STCFN044" }, // , { 45, "STCFN045" }, // - { 46, "STCFN046" }, // . { 47, "STCFN047" }, // / { 48, "STCFN048" }, // 0 { 49, "STCFN049" }, // 1 { 50, "STCFN050" }, // 2 { 51, "STCFN051" }, // 3 { 52, "STCFN052" }, // 4 { 53, "STCFN053" }, // 5 { 54, "STCFN054" }, // 6 { 55, "STCFN055" }, // 7 { 56, "STCFN056" }, // 8 { 57, "STCFN057" }, // 9 { 58, "STCFN058" }, // : { 59, "STCFN059" }, // ; { 60, "STCFN060" }, // < { 61, "STCFN061" }, // = { 62, "STCFN062" }, // > { 63, "STCFN063" }, // ? { 64, "STCFN064" }, // @ { 65, "STCFN065" }, // A { 66, "STCFN066" }, // B { 67, "STCFN067" }, // C { 68, "STCFN068" }, // D { 69, "STCFN069" }, // E { 70, "STCFN070" }, // F { 71, "STCFN071" }, // G { 72, "STCFN072" }, // H { 73, "STCFN073" }, // I { 74, "STCFN074" }, // J { 75, "STCFN075" }, // K { 76, "STCFN076" }, // L { 77, "STCFN077" }, // M { 78, "STCFN078" }, // N { 79, "STCFN079" }, // O { 80, "STCFN080" }, // P { 81, "STCFN081" }, // Q { 82, "STCFN082" }, // R { 83, "STCFN083" }, // S { 84, "STCFN084" }, // T { 85, "STCFN085" }, // U { 86, "STCFN086" }, // V { 87, "STCFN087" }, // W { 88, "STCFN088" }, // X { 89, "STCFN089" }, // Y { 90, "STCFN090" }, // Z { 91, "STCFN091" }, // [ { 92, "STCFN092" }, // '\' { 93, "STCFN093" }, // ] { 94, "STCFN094" }, // ^ { 95, "STCFN095" }, // _ { 96, "STCFN121" }, // ` { 97, "STCFN065" }, // a { 98, "STCFN066" }, // b { 99, "STCFN067" }, // c { 100, "STCFN068" }, // d { 101, "STCFN069" }, // e { 102, "STCFN070" }, // f { 103, "STCFN071" }, // g { 104, "STCFN072" }, // h { 105, "STCFN073" }, // i { 106, "STCFN074" }, // j { 107, "STCFN075" }, // k { 108, "STCFN076" }, // l { 109, "STCFN077" }, // m { 110, "STCFN078" }, // n { 111, "STCFN079" }, // o { 112, "STCFN080" }, // p { 113, "STCFN081" }, // q { 114, "STCFN082" }, // r { 115, "STCFN083" }, // s { 116, "STCFN084" }, // t { 117, "STCFN085" }, // u { 118, "STCFN086" }, // v { 119, "STCFN087" }, // w { 120, "STCFN088" }, // x { 121, "STCFN089" }, // y { 122, "STCFN090" } // z }; static const fontpatch_t fontB[] = { { 32, "FONTB032" }, // ' ' { 33, "FONTB033" }, // ! { 34, "FONTB034" }, // " { 35, "FONTB035" }, // # { 36, "FONTB036" }, // $ { 37, "FONTB037" }, // % { 38, "FONTB038" }, // & { 39, "FONTB039" }, // ' { 40, "FONTB040" }, // ( { 41, "FONTB041" }, // ) { 42, "FONTB042" }, // * { 43, "FONTB043" }, // + { 44, "FONTB044" }, // , { 45, "FONTB045" }, // - { 46, "FONTB046" }, // . { 47, "FONTB047" }, // / { 48, "FONTB048" }, // 0 { 49, "FONTB049" }, // 1 { 50, "FONTB050" }, // 2 { 51, "FONTB051" }, // 3 { 52, "FONTB052" }, // 4 { 53, "FONTB053" }, // 5 { 54, "FONTB054" }, // 6 { 55, "FONTB055" }, // 7 { 56, "FONTB056" }, // 8 { 57, "FONTB057" }, // 9 { 58, "FONTB058" }, // : { 59, "FONTB059" }, // ; { 60, "FONTB060" }, // < { 61, "FONTB061" }, // = { 62, "FONTB062" }, // > { 63, "FONTB063" }, // ? { 64, "FONTB064" }, // @ { 65, "FONTB065" }, // A { 66, "FONTB066" }, // B { 67, "FONTB067" }, // C { 68, "FONTB068" }, // D { 69, "FONTB069" }, // E { 70, "FONTB070" }, // F { 71, "FONTB071" }, // G { 72, "FONTB072" }, // H { 73, "FONTB073" }, // I { 74, "FONTB074" }, // J { 75, "FONTB075" }, // K { 76, "FONTB076" }, // L { 77, "FONTB077" }, // M { 78, "FONTB078" }, // N { 79, "FONTB079" }, // O { 80, "FONTB080" }, // P { 81, "FONTB081" }, // Q { 82, "FONTB082" }, // R { 83, "FONTB083" }, // S { 84, "FONTB084" }, // T { 85, "FONTB085" }, // U { 86, "FONTB086" }, // V { 87, "FONTB087" }, // W { 88, "FONTB088" }, // X { 89, "FONTB089" }, // Y { 90, "FONTB090" }, // Z { 97, "FONTB065" }, // a { 98, "FONTB066" }, // b { 99, "FONTB067" }, // c { 100, "FONTB068" }, // d { 101, "FONTB069" }, // e { 102, "FONTB070" }, // f { 103, "FONTB071" }, // g { 104, "FONTB072" }, // h { 105, "FONTB073" }, // i { 106, "FONTB074" }, // j { 107, "FONTB075" }, // k { 108, "FONTB076" }, // l { 109, "FONTB077" }, // m { 110, "FONTB078" }, // n { 111, "FONTB079" }, // o { 112, "FONTB080" }, // p { 113, "FONTB081" }, // q { 114, "FONTB082" }, // r { 115, "FONTB083" }, // s { 116, "FONTB084" }, // t { 117, "FONTB085" }, // u { 118, "FONTB086" }, // v { 119, "FONTB087" }, // w { 120, "FONTB088" }, // x { 121, "FONTB089" }, // y { 122, "FONTB090" } // z }; #else // __JHERETIC__ || __JHEXEN__ // Heretic/Hexen don't use ASCII numbered font patches // plus they don't even have a full set eg '!' = 1 '_'= 58 !!! static const fontpatch_t fontA[] = { { 32, "FONTA00" }, // ' ' { 33, "FONTA01" }, // ! { 34, "FONTA02" }, // " { 35, "FONTA03" }, // # { 36, "FONTA04" }, // $ { 37, "FONTA05" }, // % { 38, "FONTA06" }, // & { 39, "FONTA07" }, // ' { 40, "FONTA08" }, // ( { 41, "FONTA09" }, // ) { 42, "FONTA10" }, // * { 43, "FONTA11" }, // + { 44, "FONTA12" }, // , { 45, "FONTA13" }, // - { 46, "FONTA14" }, // . { 47, "FONTA15" }, // / { 48, "FONTA16" }, // 0 { 49, "FONTA17" }, // 1 { 50, "FONTA18" }, // 2 { 51, "FONTA19" }, // 3 { 52, "FONTA20" }, // 4 { 53, "FONTA21" }, // 5 { 54, "FONTA22" }, // 6 { 55, "FONTA23" }, // 7 { 56, "FONTA24" }, // 8 { 57, "FONTA25" }, // 9 { 58, "FONTA26" }, // : { 59, "FONTA27" }, // ; { 60, "FONTA28" }, // < { 61, "FONTA29" }, // = { 62, "FONTA30" }, // > { 63, "FONTA31" }, // ? { 64, "FONTA32" }, // @ { 65, "FONTA33" }, // A { 66, "FONTA34" }, // B { 67, "FONTA35" }, // C { 68, "FONTA36" }, // D { 69, "FONTA37" }, // E { 70, "FONTA38" }, // F { 71, "FONTA39" }, // G { 72, "FONTA40" }, // H { 73, "FONTA41" }, // I { 74, "FONTA42" }, // J { 75, "FONTA43" }, // K { 76, "FONTA44" }, // L { 77, "FONTA45" }, // M { 78, "FONTA46" }, // N { 79, "FONTA47" }, // O { 80, "FONTA48" }, // P { 81, "FONTA49" }, // Q { 82, "FONTA50" }, // R { 83, "FONTA51" }, // S { 84, "FONTA52" }, // T { 85, "FONTA53" }, // U { 86, "FONTA54" }, // V { 87, "FONTA55" }, // W { 88, "FONTA56" }, // X { 89, "FONTA57" }, // Y { 90, "FONTA58" }, // Z { 91, "FONTA61" }, // [ { 92, "FONTA62" }, // '\' { 93, "FONTA63" }, // ] { 94, "FONTA64" }, // ^ { 95, "FONTA59" }, // _ { 97, "FONTA33" }, // a { 98, "FONTA34" }, // b { 99, "FONTA35" }, // c { 100, "FONTA36" }, // d { 101, "FONTA37" }, // e { 102, "FONTA38" }, // f { 103, "FONTA39" }, // g { 104, "FONTA40" }, // h { 105, "FONTA41" }, // i { 106, "FONTA42" }, // j { 107, "FONTA43" }, // k { 108, "FONTA44" }, // l { 109, "FONTA45" }, // m { 110, "FONTA46" }, // n { 111, "FONTA47" }, // o { 112, "FONTA48" }, // p { 113, "FONTA49" }, // q { 114, "FONTA50" }, // r { 115, "FONTA51" }, // s { 116, "FONTA52" }, // t { 117, "FONTA53" }, // u { 118, "FONTA54" }, // v { 119, "FONTA55" }, // w { 120, "FONTA56" }, // x { 121, "FONTA57" }, // y { 122, "FONTA58" } // z }; static const fontpatch_t fontB[] = { { 32, "FONTB00" }, // ' ' { 33, "FONTB01" }, // ! { 34, "FONTB02" }, // " { 35, "FONTB03" }, // # { 36, "FONTB04" }, // $ { 37, "FONTB05" }, // % { 38, "FONTB06" }, // & { 39, "FONTB07" }, // ' { 40, "FONTB08" }, // ( { 41, "FONTB09" }, // ) { 42, "FONTB10" }, // * { 43, "FONTB11" }, // + { 44, "FONTB12" }, // , { 45, "FONTB13" }, // - { 46, "FONTB14" }, // . { 47, "FONTB15" }, // / { 48, "FONTB16" }, // 0 { 49, "FONTB17" }, // 1 { 50, "FONTB18" }, // 2 { 51, "FONTB19" }, // 3 { 52, "FONTB20" }, // 4 { 53, "FONTB21" }, // 5 { 54, "FONTB22" }, // 6 { 55, "FONTB23" }, // 7 { 56, "FONTB24" }, // 8 { 57, "FONTB25" }, // 9 { 58, "FONTB26" }, // : { 59, "FONTB27" }, // ; { 60, "FONTB28" }, // < { 61, "FONTB29" }, // = { 62, "FONTB30" }, // > { 63, "FONTB31" }, // ? { 64, "FONTB32" }, // @ { 65, "FONTB33" }, // A { 66, "FONTB34" }, // B { 67, "FONTB35" }, // C { 68, "FONTB36" }, // D { 69, "FONTB37" }, // E { 70, "FONTB38" }, // F { 71, "FONTB39" }, // G { 72, "FONTB40" }, // H { 73, "FONTB41" }, // I { 74, "FONTB42" }, // J { 75, "FONTB43" }, // K { 76, "FONTB44" }, // L { 77, "FONTB45" }, // M { 78, "FONTB46" }, // N { 79, "FONTB47" }, // O { 80, "FONTB48" }, // P { 81, "FONTB49" }, // Q { 82, "FONTB50" }, // R { 83, "FONTB51" }, // S { 84, "FONTB52" }, // T { 85, "FONTB53" }, // U { 86, "FONTB54" }, // V { 87, "FONTB55" }, // W { 88, "FONTB56" }, // X { 89, "FONTB57" }, // Y { 90, "FONTB58" }, // Z { 91, "FONTB59" }, // [ { 92, "FONTB60" }, // '\' { 93, "FONTB61" }, // ] { 94, "FONTB62" }, // ^ { 95, "FONTB63" }, // _ { 97, "FONTB33" }, // a { 98, "FONTB34" }, // b { 99, "FONTB35" }, // c { 100, "FONTB36" }, // d { 101, "FONTB37" }, // e { 102, "FONTB38" }, // f { 103, "FONTB39" }, // g { 104, "FONTB40" }, // h { 105, "FONTB41" }, // i { 106, "FONTB42" }, // j { 107, "FONTB43" }, // k { 108, "FONTB44" }, // l { 109, "FONTB45" }, // m { 110, "FONTB46" }, // n { 111, "FONTB47" }, // o { 112, "FONTB48" }, // p { 113, "FONTB49" }, // q { 114, "FONTB50" }, // r { 115, "FONTB51" }, // s { 116, "FONTB52" }, // t { 117, "FONTB53" }, // u { 118, "FONTB54" }, // v { 119, "FONTB55" }, // w { 120, "FONTB56" }, // x { 121, "FONTB57" }, // y { 122, "FONTB58" } // z }; #endif // Intialize the background fog effect. fogEffectData.texture = 0; fogEffectData.alpha = fogEffectData.targetAlpha = 0; fogEffectData.joinY = 0.5f; fogEffectData.scrollDir = true; fogEffectData.layers[0].texOffset[VX] = fogEffectData.layers[0].texOffset[VY] = 0; fogEffectData.layers[0].texAngle = 93; fogEffectData.layers[0].posAngle = 35; fogEffectData.layers[1].texOffset[VX] = fogEffectData.layers[1].texOffset[VY] = 0; fogEffectData.layers[1].texAngle = 12; fogEffectData.layers[1].posAngle = 77; // Load the background fog texture. if(!fogEffectData.texture && !Get(DD_NOVIDEO)) { fogEffectData.texture = GL_NewTextureWithParams3(DGL_LUMINANCE, 64, 64, W_CacheLumpName("menufog", PU_CACHE), 0, DGL_NEAREST, DGL_LINEAR, -1 /*best anisotropy*/, DGL_REPEAT, DGL_REPEAT); } // Load the border patches for(i = 1; i < 9; ++i) R_CachePatch(&borderPatches[i-1], borderLumps[i]); // Patch used for '-' (minus) in the status bar. #if __JDOOM__ R_CachePatch(&huMinus, "STTMINUS"); #elif __JDOOM64__ R_CachePatch(&huMinus, "FONTB046"); #else R_CachePatch(&huMinus, "FONTB13"); #endif #if __JDOOM__ || __JDOOM64__ for(i = 0; i < NUM_SKILL_MODES; ++i) { R_CachePatch(&skillModeNames[i], skillModePatchNames[i]); } R_CachePatch(&m_pause, "M_PAUSE"); // Load the map name patches. # if __JDOOM64__ { int NUMCMAPS = 32; mapNamePatches = Z_Malloc(sizeof(dpatch_t) * NUMCMAPS, PU_STATIC, 0); for(i = 0; i < NUMCMAPS; ++i) { sprintf(name, "WILV%2.2d", i); R_CachePatch(&mapNamePatches[i], name); } } # else if(gameMode == commercial) { int NUMCMAPS = 32; mapNamePatches = Z_Malloc(sizeof(dpatch_t) * NUMCMAPS, PU_STATIC, 0); for(i = 0; i < NUMCMAPS; ++i) { sprintf(name, "CWILV%2.2d", i); R_CachePatch(&mapNamePatches[i], name); } } else { int j; // Don't waste space - patches are loaded back to back // ie no space in the array is left for E1M10 mapNamePatches = Z_Malloc(sizeof(dpatch_t) * (9*4), PU_STATIC, 0); for(i = 0; i < 4; ++i) // Number of episodes. { for(j = 0; j < 9; ++j) // Number of maps per episode. { sprintf(name, "WILV%2.2d", (i * 10) + j); R_CachePatch(&mapNamePatches[(i* 9) + j], name); } } episodeNamePatches = Z_Malloc(sizeof(dpatch_t) * 4, PU_STATIC, 0); for(i = 0; i < 4; ++i) R_CachePatch(&episodeNamePatches[i], episodePatchNames[i]); } # endif #endif R_InitFont(GF_FONTA, fontA, sizeof(fontA) / sizeof(fontA[0])); R_InitFont(GF_FONTB, fontB, sizeof(fontB) / sizeof(fontB[0])); #if __JHERETIC__ || __JHEXEN__ for(i = 0; i < 10; ++i) { sprintf(name, "SMALLIN%d", i); R_CachePatch(&dpSmallNumbers[i], name); } #endif #if __JHERETIC__ || __JHEXEN__ R_CachePatch(&dpInvItemBox, "ARTIBOX"); R_CachePatch(&dpInvSelectBox, "SELECTBO"); R_CachePatch(&dpInvPageLeft[0], "INVGEML1"); R_CachePatch(&dpInvPageLeft[1], "INVGEML2"); R_CachePatch(&dpInvPageRight[0], "INVGEMR1"); R_CachePatch(&dpInvPageRight[1], "INVGEMR2"); #endif Chat_Init(); } void Hu_UnloadData(void) { #if __JDOOM__ || __JDOOM64__ if(mapNamePatches) Z_Free(mapNamePatches); #endif if(!Get(DD_NOVIDEO)) { if(fogEffectData.texture) DGL_DeleteTextures(1, (DGLuint*) &fogEffectData.texture); fogEffectData.texture = 0; } } void HU_Stop(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; hud->active = false; } void HU_Start(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; Chat_Start(); Hu_LogStart(player); hud = &hudStates[player]; if(hud->active) HU_Stop(player); hud->active = true; } void HU_Drawer(int player) { // Don't draw the message log while the map title is up. if(!(cfg.mapTitle && actualMapTime < 6 * 35)) { Hu_LogDrawer(player); } Chat_Drawer(player); HU_DrawScoreBoard(player); } static void drawQuad(float x, float y, float w, float h, float s, float t, float r, float g, float b, float a) { DGL_Color4f(r, g, b, a); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0 * s, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1 * s, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1 * s, t); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0 * s, t); DGL_Vertex2f(x, y + h); DGL_End(); } void HU_DrawText(const char* str, gamefontid_t font, float x, float y, float scale, float r, float g, float b, float a, boolean alignRight) { const char* ch; char c; float w, h; dpatch_t* p; if(!str || !str[0]) return; if(alignRight) { ch = str; for(;;) { c = *ch++; if(!c) break; if(!gFonts[font].chars[(byte) c].patch.lump) continue; p = &gFonts[font].chars[(byte) c].patch; x -= p->width * scale; } } DGL_Color4f(r, g, b, a); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(x, y, 0); DGL_Scalef(scale, scale, 1); DGL_Translatef(-x, -y, 0); ch = str; for(;;) { c = *ch++; if(!c) break; if(!gFonts[font].chars[(byte) c].patch.lump) continue; p = &gFonts[font].chars[(byte) c].patch; w = p->width; h = p->height; GL_DrawPatch_CS(x, y, p->lump); x += w; } DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } typedef struct { int player, pClass, team; int kills, suicides; float color[3]; } scoreinfo_t; int scoreInfoCompare(const void* a, const void* b) { const scoreinfo_t* infoA = (scoreinfo_t*) a; const scoreinfo_t* infoB = (scoreinfo_t*) b; if(infoA->kills > infoB->kills) return -1; if(infoB->kills > infoA->kills) return 1; if(deathmatch) { // In deathmatch, suicides affect your place on the scoreboard. if(infoA->suicides < infoB->suicides) return -1; if(infoB->suicides < infoA->suicides) return 1; } return 0; } static void sortScoreInfo(scoreinfo_t* vec, size_t size) { qsort(vec, size, sizeof(scoreinfo_t), scoreInfoCompare); } static int buildScoreBoard(scoreinfo_t* scoreBoard, int maxPlayers, int player) { #if __JHEXEN__ static const int plrColors[] = { AM_PLR1_COLOR, AM_PLR2_COLOR, AM_PLR3_COLOR, AM_PLR4_COLOR, AM_PLR5_COLOR, AM_PLR6_COLOR, AM_PLR7_COLOR, AM_PLR8_COLOR }; #else static const float green[3] = { 0.f, .8f, 0.f }; static const float gray[3] = { .45f, .45f, .45f }; static const float brown[3] = { .7f, .5f, .4f }; static const float red[3] = { 1.f, 0.f, 0.f }; #endif int i, j, n, inCount; memset(scoreBoard, 0, sizeof(*scoreBoard) * maxPlayers); inCount = 0; for(i = 0, n = 0; i < maxPlayers; ++i) { player_t* plr = &players[i]; scoreinfo_t* info; if(!plr->plr->inGame) continue; inCount++; info = &scoreBoard[n++]; info->player = i; #if __JHERETIC__ info->pClass = (plr->morphTics > 0? PCLASS_CHICKEN : PCLASS_PLAYER); #elif __JHEXEN__ if(plr->morphTics > 0) info->pClass = PCLASS_PIG; else info->pClass = plr->class; #else info->pClass = PCLASS_PLAYER; #endif info->team = cfg.playerColor[i]; // Pick team color: #if __JHEXEN__ R_GetColorPaletteRGBf(0, info->color, plrColors[info->team], false); #else switch(info->team) { case 0: memcpy(info->color, green, sizeof(float)*3); break; case 1: memcpy(info->color, gray, sizeof(float)*3); break; case 2: memcpy(info->color, brown, sizeof(float)*3); break; case 3: memcpy(info->color, red, sizeof(float)*3); break; } #endif if(deathmatch) { for(j = 0; j < maxPlayers; ++j) { if(j != i) { info->kills += plr->frags[j]; } else { #if __JHEXEN__ info->suicides += -plr->frags[j]; #else info->suicides += plr->frags[j]; #endif } } } else { info->kills = plr->killCount; info->suicides = 0; // We don't care anyway. } } sortScoreInfo(scoreBoard, n); return inCount; } void HU_ScoreBoardUnHide(int player) { hudstate_t* hud; player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; hud = &hudStates[player]; hud->scoreAlpha = 1; hud->scoreHideTics = 35; } static void drawTable(float x, float ly, float width, float height, column_t* columns, scoreinfo_t* scoreBoard, int inCount, float alpha, int player) { #define CELL_PADDING (1) int i, n, numCols, numStretchCols; float cX, cY, fixedWidth, lineHeight, fontScale, fontHeight, fontOffsetY; float* colX, *colW; if(!columns) return; if(!(alpha > 0)) return; numStretchCols = 0; numCols = 0; for(n = 0; columns[n].label; n++) { numCols++; if(columns[n].flags & CF_HIDE) continue; if(!(columns[n].flags & CF_FIXEDWIDTH)) numStretchCols++; } if(!numCols) return; colX = calloc(1, sizeof(*colX) * numCols); colW = calloc(1, sizeof(*colW) * numCols); lineHeight = height / (MAXPLAYERS + 1); fontHeight = M_StringHeight("AgIq^_", GF_FONTA); fontScale = (lineHeight - CELL_PADDING * 2) / fontHeight; fontOffsetY = 0; if(fontScale > 1) { fontScale = 1; fontOffsetY = (lineHeight - CELL_PADDING * 2 - fontHeight) / 2; } fixedWidth = 0; for(n = 0; n < numCols; ++n) { if(columns[n].flags & CF_HIDE) continue; if(columns[n].flags & CF_FIXEDWIDTH) { colW[n] = M_StringWidth(columns[n].label, GF_FONTA) + CELL_PADDING * 2; fixedWidth += colW[n]; } } for(n = 0; n < numCols; ++n) { if(columns[n].flags & CF_HIDE) continue; if(!(columns[n].flags & CF_FIXEDWIDTH)) colW[n] = (width - fixedWidth) / numStretchCols; } colX[0] = x; for(n = 1; n < numCols; ++n) { if(columns[n].flags & CF_HIDE) colX[n] = colX[n-1]; else colX[n] = colX[n-1] + colW[n-1]; } // Draw the table header: for(n = 0; n < numCols; ++n) { if(columns[n].flags & CF_HIDE) continue; cX = colX[n]; cY = ly + fontOffsetY; cY += CELL_PADDING; if(columns[n].alignRight) cX += colW[n] - CELL_PADDING; else cX += CELL_PADDING; HU_DrawText(columns[n].label, GF_FONTA, cX, cY, fontScale, 1.f, 1.f, 1.f, alpha, columns[n].alignRight); } ly += lineHeight; // Draw the table from left to right, top to bottom: for(i = 0; i < inCount; ++i, ly += lineHeight) { scoreinfo_t* info = &scoreBoard[i]; const char* name = Net_GetPlayerName(info->player); char buf[5]; if(info->player == player) { // Draw a background to make *me* stand out. float val = (info->color[0] + info->color[1] + info->color[2]) / 3; if(val < .5f) val = .2f; else val = .8f; DGL_Disable(DGL_TEXTURING); DGL_DrawRect(x, ly, width, lineHeight, val + .2f, val + .2f, val, .5f * alpha); DGL_Enable(DGL_TEXTURING); } // Now draw the fields: for(n = 0; n < numCols; ++n) { if(columns[n].flags & CF_HIDE) continue; cX = colX[n]; cY = ly; /*#if _DEBUG DGL_Disable(DGL_TEXTURING); GL_DrawRect(cX + CELL_PADDING, cY + CELL_PADDING, colW[n] - CELL_PADDING * 2, lineHeight - CELL_PADDING * 2, 1, 1, 1, .1f * alpha); DGL_Enable(DGL_TEXTURING); #endif*/ cY += CELL_PADDING; if(columns[n].alignRight) cX += colW[n] - CELL_PADDING; else cX += CELL_PADDING; switch(columns[n].type) { case 0: // Class icon. { #if __JHERETIC__ || __JHEXEN__ int spr = 0; # if __JHERETIC__ if(info->pClass == PCLASS_CHICKEN) spr = SPR_CHKN; # else switch(info->pClass) { case PCLASS_FIGHTER: spr = SPR_PLAY; break; case PCLASS_CLERIC: spr = SPR_CLER; break; case PCLASS_MAGE: spr = SPR_MAGE; break; case PCLASS_PIG: spr = SPR_PIGY; break; } # endif if(spr) { spriteinfo_t sprInfo; int w, h, w2, h2; float s, t, scale; R_GetSpriteInfo(spr, 0, &sprInfo); w = sprInfo.width; h = sprInfo.height; w2 = M_CeilPow2(w); h2 = M_CeilPow2(h); // Let's calculate texture coordinates. // To remove a possible edge artifact, move the corner a bit up/left. s = (w - 0.4f) / w2; t = (h - 0.4f) / h2; if(h > w) scale = (lineHeight - CELL_PADDING * 2) / h; else scale = (colW[n] - CELL_PADDING * 2) / w; w *= scale; h *= scale; // Align to center on both X+Y axes. cX += ((colW[n] - CELL_PADDING * 2) - w) / 2; cY += ((lineHeight - CELL_PADDING * 2) - h) / 2; DGL_SetMaterial(sprInfo.material); drawQuad(cX, cY, w, h, s, t, 1, 1, 1, alpha); } #endif break; } case 1: // Name. HU_DrawText(name, GF_FONTA, cX, cY + fontOffsetY, fontScale, info->color[0], info->color[1], info->color[2], alpha, false); break; case 2: // #Suicides. sprintf(buf, "%4i", info->suicides); HU_DrawText(buf, GF_FONTA, cX, cY + fontOffsetY, fontScale, info->color[0], info->color[1], info->color[2], alpha, true); break; case 3: // #Kills. sprintf(buf, "%4i", info->kills); HU_DrawText(buf, GF_FONTA, cX, cY + fontOffsetY, fontScale, info->color[0], info->color[1], info->color[2], alpha, true); break; } } } free(colX); free(colW); #undef CELL_PADDING } const char* P_GetGameModeName(void) { static const char* dm = "deathmatch"; static const char* coop = "cooperative"; static const char* sp = "singleplayer"; if(IS_NETGAME) { if(deathmatch) return dm; return coop; } return sp; } static void drawMapMetaData(float x, float y, gamefontid_t font, float alpha) { static const char* unnamed = "unnamed"; const char* lname = P_GetMapNiceName(); if(!lname) lname = unnamed; // Map name: M_WriteText2(x, y + 16, "map: ", font, 1, 1, 1, alpha); M_WriteText2(x += M_StringWidth("map: ", font), y + 16, lname, font, 1, 1, 1, alpha); x += 8; // Game mode: M_WriteText2(x += M_StringWidth(lname, font), y + 16, "gamemode: ", font, 1, 1, 1, alpha); M_WriteText2(x += M_StringWidth("gamemode: ", font), y + 16, P_GetGameModeName(), font, 1, 1, 1, alpha); } /** * Draws a sorted frags list in the lower right corner of the screen. */ void HU_DrawScoreBoard(int player) { #define LINE_BORDER 4 column_t columns[] = { {"cl", 0, CF_FIXEDWIDTH, false}, {"name", 1, 0, false}, {"suicides", 2, CF_FIXEDWIDTH, true}, {"frags", 3, CF_FIXEDWIDTH, true}, {NULL, 0, 0} }; int x, y, width, height, inCount; hudstate_t* hud; scoreinfo_t scoreBoard[MAXPLAYERS]; if(!IS_NETGAME) return; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(!(hud->scoreAlpha > 0)) return; // Determine the dimensions of the scoreboard: x = 0; y = 0; width = SCREENWIDTH - 32; height = SCREENHEIGHT - 32; // Build and sort the scoreboard according to game rules, type, etc. inCount = buildScoreBoard(scoreBoard, MAXPLAYERS, player); // Only display the player class column if more than one. if(NUM_PLAYER_CLASSES == 1) columns[0].flags |= CF_HIDE; // Scale by HUD scale. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(16, 16, 0); // Draw a background around the whole thing. DGL_Disable(DGL_TEXTURING); DGL_DrawRect(x, y, width, height, 0, 0, 0, .4f * hud->scoreAlpha); DGL_Enable(DGL_TEXTURING); // Title: M_WriteText2(x + width / 2 - M_StringWidth("ranking", GF_FONTB) / 2, y + LINE_BORDER, "ranking", GF_FONTB, 1, 0, 0, hud->scoreAlpha); drawMapMetaData(x, y + 16, GF_FONTA, hud->scoreAlpha); drawTable(x, y + 20, width, height - 20, columns, scoreBoard, inCount, hud->scoreAlpha, player); DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } /** * Draws the world time in the top right corner of the screen */ static void drawWorldTimer(void) { #if __JHEXEN__ int days, hours, minutes, seconds; int worldTimer; char timeBuffer[15]; char dayBuffer[20]; worldTimer = players[DISPLAYPLAYER].worldTimer; worldTimer /= 35; days = worldTimer / 86400; worldTimer -= days * 86400; hours = worldTimer / 3600; worldTimer -= hours * 3600; minutes = worldTimer / 60; worldTimer -= minutes * 60; seconds = worldTimer; sprintf(timeBuffer, "%.2d : %.2d : %.2d", hours, minutes, seconds); M_WriteText2(240, 8, timeBuffer, GF_FONTA, 1, 1, 1, 1); if(days) { if(days == 1) { sprintf(dayBuffer, "%.2d DAY", days); } else { sprintf(dayBuffer, "%.2d DAYS", days); } M_WriteText2(240, 20, dayBuffer, GF_FONTA, 1, 1, 1, 1); if(days >= 5) { M_WriteText2(230, 35, "YOU FREAK!!!", GF_FONTA, 1, 1, 1, 1); } } #endif } /** * Handles what counters to draw eg title, timer, dm stats etc */ void HU_DrawMapCounters(void) { player_t *plr; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ char buf[40], tmp[20]; int x = 5, y = LINEHEIGHT_A * 3; #endif plr = &players[DISPLAYPLAYER]; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ DGL_Color3f(1, 1, 1); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); #endif DGL_Enable(DGL_TEXTURING); drawWorldTimer(); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ Draw_BeginZoom(cfg.counterCheatScale, x, y); if(cfg.counterCheat) { // Kills. if(cfg.counterCheat & (CCH_KILLS | CCH_KILLS_PRCNT)) { strcpy(buf, "Kills: "); if(cfg.counterCheat & CCH_KILLS) { sprintf(tmp, "%i/%i ", plr->killCount, totalKills); strcat(buf, tmp); } if(cfg.counterCheat & CCH_KILLS_PRCNT) { sprintf(tmp, "%s%i%%%s", (cfg.counterCheat & CCH_KILLS ? "(" : ""), totalKills ? plr->killCount * 100 / totalKills : 100, (cfg.counterCheat & CCH_KILLS ? ")" : "")); strcat(buf, tmp); } M_WriteText2(x, y, buf, GF_FONTA, 1, 1, 1, 1); y += LINEHEIGHT_A; } // Items. if(cfg.counterCheat & (CCH_ITEMS | CCH_ITEMS_PRCNT)) { strcpy(buf, "Items: "); if(cfg.counterCheat & CCH_ITEMS) { sprintf(tmp, "%i/%i ", plr->itemCount, totalItems); strcat(buf, tmp); } if(cfg.counterCheat & CCH_ITEMS_PRCNT) { sprintf(tmp, "%s%i%%%s", (cfg.counterCheat & CCH_ITEMS ? "(" : ""), totalItems ? plr->itemCount * 100 / totalItems : 100, (cfg.counterCheat & CCH_ITEMS ? ")" : "")); strcat(buf, tmp); } M_WriteText2(x, y, buf, GF_FONTA, 1, 1, 1, 1); y += LINEHEIGHT_A; } // Secrets. if(cfg.counterCheat & (CCH_SECRET | CCH_SECRET_PRCNT)) { strcpy(buf, "Secret: "); if(cfg.counterCheat & CCH_SECRET) { sprintf(tmp, "%i/%i ", plr->secretCount, totalSecret); strcat(buf, tmp); } if(cfg.counterCheat & CCH_SECRET_PRCNT) { sprintf(tmp, "%s%i%%%s", (cfg.counterCheat & CCH_SECRET ? "(" : ""), totalSecret ? plr->secretCount * 100 / totalSecret : 100, (cfg.counterCheat & CCH_SECRET ? ")" : "")); strcat(buf, tmp); } M_WriteText2(x, y, buf, GF_FONTA, 1, 1, 1, 1); y += LINEHEIGHT_A; } } Draw_EndZoom(); DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); #endif } void Hu_Ticker(void) { int i; Hu_LogTicker(); for(i = 0; i < MAXPLAYERS; ++i) { hudstate_t* hud = &hudStates[i]; player_t* plr = &players[i]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) continue; if(hud->scoreHideTics > 0) { hud->scoreHideTics--; } else { if(hud->scoreAlpha > 0) hud->scoreAlpha -= .05f; } } } /** * Updates on Game Tick. */ void Hu_FogEffectTicker(timespan_t time) { #define fog (&fogEffectData) #define FOGALPHA_FADE_STEP (.07f) int i; static const float MENUFOGSPEED[2] = {.05f, -.085f}; static trigger_t fixed = { 1 / 35.0 }; if(!M_RunTrigger(&fixed, time)) return; if(cfg.hudFog == 0) return; // Move towards the target alpha if(fog->alpha != fog->targetAlpha) { float diff = fog->targetAlpha - fog->alpha; if(fabs(diff) > FOGALPHA_FADE_STEP) { fog->alpha += FOGALPHA_FADE_STEP * (diff > 0? 1 : -1); } else { fog->alpha = fog->targetAlpha; } } if(!(fog->alpha > 0)) return; for(i = 0; i < 2; ++i) { if(cfg.hudFog == 2) { fog->layers[i].texAngle += MENUFOGSPEED[i] / 4; fog->layers[i].posAngle -= MENUFOGSPEED[!i]; fog->layers[i].texOffset[VX] = 160 + 120 * cos(fog->layers[i].posAngle / 180 * PI); fog->layers[i].texOffset[VY] = 100 + 100 * sin(fog->layers[i].posAngle / 180 * PI); } else { fog->layers[i].texAngle += MENUFOGSPEED[i] / 4; fog->layers[i].posAngle -= MENUFOGSPEED[!i] * 1.5f; fog->layers[i].texOffset[VX] = 320 + 320 * cos(fog->layers[i].posAngle / 180 * PI); fog->layers[i].texOffset[VY] = 240 + 240 * sin(fog->layers[i].posAngle / 180 * PI); } } // Calculate the height of the menuFog 3 Y join if(cfg.hudFog == 4) { if(fog->scrollDir && fog->joinY > 0.46f) fog->joinY = fog->joinY / 1.002f; else if(!fog->scrollDir && fog->joinY < 0.54f ) fog->joinY = fog->joinY * 1.002f; if((fog->joinY < 0.46f || fog->joinY > 0.54f)) fog->scrollDir = !fog->scrollDir; } #undef fog #undef FOGALPHA_FADE_STEP } /** * Expected: = */ float WI_ParseFloat(char** str) { float value; char* end; *str = M_SkipWhite(*str); if(**str != '=') return 0; // Now I'm confused! *str = M_SkipWhite(*str + 1); value = strtod(*str, &end); *str = end; return value; } /** * Draw a string of text controlled by parameter blocks. */ void WI_DrawParamText(int x, int y, const char* inString, gamefontid_t defFont, float defRed, float defGreen, float defBlue, float defAlpha, boolean defCase, boolean defTypeIn, int halign) { #define SMALLBUFF_SIZE 80 char smallBuff[SMALLBUFF_SIZE+1], *bigBuff = NULL; char temp[256], *str, *string, *end; gamefontid_t font = defFont; float r = defRed, g = defGreen, b = defBlue, a = defAlpha; float offX = 0, offY = 0, width = 0; float scaleX = 1, scaleY = 1, angle = 0, extraScale; float cx = x, cy = y; int charCount = 0; boolean typeIn = defTypeIn; boolean caseScale = defCase; struct { float scale, offset; } caseMod[2]; // 1=upper, 0=lower int curCase = -1; int alignx = 0; size_t len; if(!inString || !inString[0]) return; len = strlen(inString); if(len < SMALLBUFF_SIZE) { memcpy(smallBuff, inString, len); smallBuff[len] = '\0'; str = smallBuff; } else { bigBuff = malloc(len+1); memcpy(bigBuff, inString, len); bigBuff[len+1] = '\0'; str = bigBuff; } caseMod[0].scale = 1; caseMod[0].offset = 3; caseMod[1].scale = 1.25f; caseMod[1].offset = 0; // With centrally aligned strings we need to calculate the width // of the whole visible string before we can draw any characters. // So we'll need to make two passes on the string. if(halign == ALIGN_CENTER) { string = str; while(*string) { if(*string == '{') // Parameters included? { string++; while(*string && *string != '}') { string = M_SkipWhite(string); // We are only interested in font changes // at this stage. if(!strnicmp(string, "fonta", 5)) { font = GF_FONTA; string += 5; } else if(!strnicmp(string, "fontb", 5)) { font = GF_FONTB; string += 5; } else { // Unknown, skip it. if(*string != '}') string++; } } // Skip over the closing brace. if(*string) string++; } for(end = string; *end && *end != '{';) { // Find the end of the visible part of the string. for(; *end && *end != '{'; end++); strncpy(temp, string, end - string); temp[end - string] = 0; width += M_StringWidth(temp, font); string = end; // Continue from here. } } width /= 2; } string = str; while(*string) { // Parse and draw the replacement string. if(*string == '{') // Parameters included? { string++; while(*string && *string != '}') { string = M_SkipWhite(string); // What do we have here? if(!strnicmp(string, "fonta", 5)) { font = GF_FONTA; string += 5; } else if(!strnicmp(string, "fontb", 5)) { font = GF_FONTB; string += 5; } else if(!strnicmp(string, "flash", 5)) { string += 5; typeIn = true; } else if(!strnicmp(string, "noflash", 7)) { string += 7; typeIn = false; } else if(!strnicmp(string, "case", 4)) { string += 4; caseScale = true; } else if(!strnicmp(string, "nocase", 6)) { string += 6; caseScale = false; } else if(!strnicmp(string, "ups", 3)) { string += 3; caseMod[1].scale = WI_ParseFloat(&string); } else if(!strnicmp(string, "upo", 3)) { string += 3; caseMod[1].offset = WI_ParseFloat(&string); } else if(!strnicmp(string, "los", 3)) { string += 3; caseMod[0].scale = WI_ParseFloat(&string); } else if(!strnicmp(string, "loo", 3)) { string += 3; caseMod[0].offset = WI_ParseFloat(&string); } else if(!strnicmp(string, "break", 5)) { string += 5; cx = x; cy += scaleY * gFonts[font].chars[0].patch.height; } else if(!strnicmp(string, "r", 1)) { string++; r = WI_ParseFloat(&string); } else if(!strnicmp(string, "g", 1)) { string++; g = WI_ParseFloat(&string); } else if(!strnicmp(string, "b", 1)) { string++; b = WI_ParseFloat(&string); } else if(!strnicmp(string, "x", 1)) { string++; offX = WI_ParseFloat(&string); } else if(!strnicmp(string, "y", 1)) { string++; offY = WI_ParseFloat(&string); } else if(!strnicmp(string, "scalex", 6)) { string += 6; scaleX = WI_ParseFloat(&string); } else if(!strnicmp(string, "scaley", 6)) { string += 6; scaleY = WI_ParseFloat(&string); } else if(!strnicmp(string, "scale", 5)) { string += 5; scaleX = scaleY = WI_ParseFloat(&string); } else if(!strnicmp(string, "angle", 5)) { string += 5; angle = WI_ParseFloat(&string); } else { // Unknown, skip it. if(*string != '}') string++; } } // Skip over the closing brace. if(*string) string++; } for(end = string; *end && *end != '{';) { if(caseScale) { curCase = -1; // Select a substring with characters of the same case // (or whitespace). for(; *end && *end != '{'; end++) { // We can skip whitespace. if(isspace(*end)) continue; if(curCase < 0) curCase = (isupper(*end) != 0); else if(curCase != (isupper(*end) != 0)) break; } } else { // Find the end of the visible part of the string. for(; *end && *end != '{'; end++); } strncpy(temp, string, end - string); temp[end - string] = 0; string = end; // Continue from here. if(halign == ALIGN_CENTER){ alignx = width; } else if (halign == ALIGN_RIGHT){ alignx = scaleX * M_StringWidth(temp, font); } else { alignx = 0; } // Setup the scaling. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); // Rotate. if(angle != 0) { // The origin is the specified (x,y) for the patch. // We'll undo the VGA aspect ratio (otherwise the result would // be skewed). DGL_Translatef(x, y, 0); DGL_Scalef(1, 200.0f / 240.0f, 1); DGL_Rotatef(angle, 0, 0, 1); DGL_Scalef(1, 240.0f / 200.0f, 1); DGL_Translatef(-x, -y, 0); } DGL_Translatef(cx + offX - alignx, cy + offY + (caseScale ? caseMod[curCase].offset : 0), 0); extraScale = (caseScale ? caseMod[curCase].scale : 1); DGL_Scalef(scaleX, scaleY * extraScale, 1); // Draw it. M_WriteText3(0, 0, temp, font, r, g, b, a, typeIn, false, typeIn ? charCount : 0); charCount += strlen(temp); // Advance the current position. cx += scaleX * M_StringWidth(temp, font); DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } } // Free temporary storage. if(bigBuff) free(bigBuff); #undef SMALLBUFF_SIZE } /** * Find string width from huFont chars * Skips parameter blocks eg "{param}Text" = 4 chars */ int M_StringWidth(const char* string, gamefontid_t font) { uint i; int w = 0, maxWidth = -1; int c; boolean skip; for(i = 0, skip = false; i < strlen(string); ++i) { c = string[i]; if(string[i] == '{') skip = true; if(skip == false && string[i] != '\n') w += gFonts[font].chars[c].patch.width; if(string[i] == '}') skip = false; if(string[i] == '\n') { if(w > maxWidth) maxWidth = w; w = 0; } else if(i == strlen(string) - 1 && maxWidth == -1) { maxWidth = w; } } return maxWidth; } int M_CharWidth(unsigned char ch, gamefontid_t font) { return gFonts[font].chars[ch].patch.width; } int M_CharHeight(unsigned char ch, gamefontid_t font) { return gFonts[font].chars[ch].patch.height; } /** * Find string height from huFont chars */ int M_StringHeight(const char* string, gamefontid_t font) { uint i; int h, height = gFonts[font].chars['A'].patch.height; h = height; for(i = 0; i < strlen(string); ++i) { if(string[i] == '\n') h += height; } return h; } void M_LetterFlash(int x, int y, int w, int h, int bright, float r, float g, float b, float a) { float fsize = 4 + bright, red, green, blue, alpha; float fw = fsize * w / 2.0f, fh = fsize * h / 2.0f; // Don't draw anything for very small letters. if(h <= 4) return; // Don't bother with hidden letters. if(!(a > 0.f)) return; red = MINMAX_OF(0.f, r, 1.f); green = MINMAX_OF(0.f, g, 1.f); blue = MINMAX_OF(0.f, b, 1.f); alpha = MINMAX_OF(0.f, a, 1.f); DGL_Bind(Get(DD_DYNLIGHT_TEXTURE)); if(bright) DGL_BlendMode(BM_ADD); else DGL_BlendFunc(DGL_ZERO, DGL_ONE_MINUS_SRC_ALPHA); DGL_DrawRect(x + w / 2.0f - fw / 2, y + h / 2.0f - fh / 2, fw, fh, red, green, blue, alpha); DGL_BlendMode(BM_NORMAL); } void M_DrawChar(int x, int y, unsigned char ch, gamefontid_t font) { lumpnum_t lump; lump = gFonts[font].chars[ch].patch.lump; GL_DrawPatch_CS(x, y, lump); } void HUlib_drawTextLine2(int x, int y, const char* string, size_t len, gamefontid_t fontid, boolean drawCursor) { const gamefont_t* font = &gFonts[fontid]; size_t i; DGL_Color3fv(cfg.hudColor); for(i = 0; i < len; ++i) { unsigned char c = string[i]; int w; const dpatch_t* p = &font->chars[c].patch; w = p->width; if(x + w > SCREENWIDTH) break; GL_DrawPatch_CS(x, y, p->lump); x += w; } // Draw the cursor if requested. if(drawCursor && x + font->chars['_'].patch.width <= SCREENWIDTH) GL_DrawPatch_CS(x, y, font->chars['_'].patch.lump); } #if __JHERETIC__ void HU_DrawBNumber(signed int val, int x, int y, float red, float green, float blue, float alpha) { const dpatch_t* patch; int xpos; int oldval; oldval = val; xpos = x; if(val < 0) { val = 0; } if(val > 99) { patch = &gFonts[GF_FONTB].chars['0' + val / 100].patch; GL_DrawPatchLitAlpha(xpos + 8 - patch->width / 2, y +2, 0, alpha * .4f, patch->lump); DGL_Color4f(red, green, blue, alpha); GL_DrawPatch_CS(xpos + 6 - patch->width / 2, y, patch->lump); DGL_Color4f(1, 1, 1, 1); } val = val % 100; xpos += 12; if(val > 9 || oldval > 99) { patch = &gFonts[GF_FONTB].chars['0' + val / 10].patch; GL_DrawPatchLitAlpha(xpos + 8 - patch->width / 2, y +2, 0, alpha * .4f, patch->lump); DGL_Color4f(red, green, blue, alpha); GL_DrawPatch_CS(xpos + 6 - patch->width / 2, y, patch->lump); DGL_Color4f(1, 1, 1, 1); } val = val % 10; xpos += 12; patch = &gFonts[GF_FONTB].chars['0' + val].patch; GL_DrawPatchLitAlpha(xpos + 8 - patch->width / 2, y +2, 0, alpha * .4f, patch->lump); DGL_Color4f(red, green, blue, alpha); GL_DrawPatch_CS(xpos + 6 - patch->width / 2, y, patch->lump); DGL_Color4f(1, 1, 1, 1); } #endif #if __JHERETIC__ void IN_DrawShadowChar(int x, int y, unsigned char ch, gamefontid_t font) { GL_DrawPatchLitAlpha(x+2, y+2, 0, .4f, gFonts[font].chars[ch].patch.lump); DGL_Color4f(defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); M_DrawChar(x, y, ch, font); } #elif __JHEXEN__ void GL_DrawShadowedPatch2(float x, float y, float r, float g, float b, float a, lumpnum_t lump) { GL_DrawPatchLitAlpha(x + 2, y + 2, 0, a * .4f, lump); DGL_Color4f(r, g, b, a); GL_DrawPatch_CS(x, y, lump); DGL_Color4f(1, 1, 1, 1); } #endif #if __JHERETIC__ void IN_DrawNumber(int val, int x, int y, int digits, float r, float g, float b, float a) { int xpos; int oldval; int realdigits; boolean neg; oldval = val; xpos = x; neg = false; realdigits = 1; if(val < 0) { val = -val; neg = true; if(val > 99) { val = 99; } } if(val > 9) { realdigits++; if(digits < realdigits) { realdigits = digits; val = 9; } } if(val > 99) { realdigits++; if(digits < realdigits) { realdigits = digits; val = 99; } } if(val > 999) { realdigits++; if(digits < realdigits) { realdigits = digits; val = 999; } } if(digits == 4) { GL_DrawPatchLitAlpha(xpos + 8 - gFonts[GF_FONTB].chars['0' + val / 1000].patch.width / 2 - 12, y + 2, 0, .4f, gFonts[GF_FONTB].chars['0' + val / 1000].patch.lump); DGL_Color4f(r, g, b, a); GL_DrawPatch_CS(xpos + 6 - gFonts[GF_FONTB].chars['0' + val / 1000].patch.width / 2 - 12, y, gFonts[GF_FONTB].chars['0' + val / 1000].patch.lump); } if(digits > 2) { if(realdigits > 2) { GL_DrawPatchLitAlpha(xpos + 8 - gFonts[GF_FONTB].chars['0' + val / 100].patch.width / 2, y+2, 0, .4f, gFonts[GF_FONTB].chars['0' + val / 100].patch.lump); DGL_Color4f(r, g, b, a); GL_DrawPatch_CS(xpos + 6 - gFonts[GF_FONTB].chars['0' + val / 100].patch.width / 2, y, gFonts[GF_FONTB].chars['0' + val / 100].patch.lump); } xpos += 12; } val = val % 100; if(digits > 1) { if(val > 9) { GL_DrawPatchLitAlpha(xpos + 8 - gFonts[GF_FONTB].chars['0' + val / 10].patch.width / 2, y+2, 0, .4f, gFonts[GF_FONTB].chars['0' + val / 10].patch.lump); DGL_Color4f(r, g, b, a); GL_DrawPatch_CS(xpos + 6 - gFonts[GF_FONTB].chars['0' + val / 10].patch.width / 2, y, gFonts[GF_FONTB].chars['0' + val / 10].patch.lump); } else if(digits == 2 || oldval > 99) { GL_DrawPatchLitAlpha(xpos+2, y+2, 0, .4f, gFonts[GF_FONTB].chars['0'].patch.lump); DGL_Color4f(r, g, b, a); GL_DrawPatch_CS(xpos, y, gFonts[GF_FONTB].chars['0'].patch.lump); } xpos += 12; } val = val % 10; GL_DrawPatchLitAlpha(xpos + 8 - gFonts[GF_FONTB].chars['0' + val].patch.width / 2, y+2, 0, .4f, gFonts[GF_FONTB].chars['0' + val].patch.lump); DGL_Color4f(r, g, b, a); GL_DrawPatch_CS(xpos + 6 - gFonts[GF_FONTB].chars['0' + val].patch.width / 2, y, gFonts[GF_FONTB].chars['0' + val].patch.lump); if(neg) { GL_DrawPatchLitAlpha(xpos + 8 - gFonts[GF_FONTB].chars['-'].patch.width / 2 - 12 * (realdigits), y+2, 0, .4f, gFonts[GF_FONTB].chars['-'].patch.lump); DGL_Color4f(r, g, b, a); GL_DrawPatch_CS(xpos + 6 - gFonts[GF_FONTB].chars['-'].patch.width / 2 - 12 * (realdigits), y, gFonts[GF_FONTB].chars['-'].patch.lump); } } #endif #if __JHEXEN__ /** * Draws a three digit number using FontB */ void DrBNumber(int val, int x, int y, float red, float green, float blue, float alpha) { dpatch_t* patch; int xpos; int oldval; // Limit to three digits. if(val > 999) val = 999; if(val < -999) val = -999; oldval = val; xpos = x; if(val < 0) { val = 0; } if(val > 99) { patch = &gFonts[GF_FONTB].chars['0' + val / 100].patch; GL_DrawShadowedPatch2(xpos + 6 - patch->width / 2, y, red, green, blue, alpha, patch->lump); } val = val % 100; xpos += 12; if(val > 9 || oldval > 99) { patch = &gFonts[GF_FONTB].chars['0' + val / 10].patch; GL_DrawShadowedPatch2(xpos + 6 - patch->width / 2, y, red, green, blue, alpha, patch->lump); } val = val % 10; xpos += 12; patch = &gFonts[GF_FONTB].chars['0' + val].patch; GL_DrawShadowedPatch2(xpos + 6 - patch->width / 2, y, red, green, blue, alpha, patch->lump); } #endif /** * Write a string using the huFont. */ void M_WriteText(int x, int y, const char* string) { M_WriteText2(x, y, string, GF_FONTA, 1, 1, 1, 1); } void M_WriteText2(int x, int y, const char* string, gamefontid_t font, float red, float green, float blue, float alpha) { M_WriteText3(x, y, string, font, red, green, blue, alpha, false, true, 0); } /** * Write a string using a colored, custom font. * Also do a type-in effect. */ void M_WriteText3(int x, int y, const char* string, gamefontid_t font, float red, float green, float blue, float alpha, boolean flagTypeIn, boolean flagShadow, int initialCount) { const char* ch; unsigned char c; int pass, w, h, cx, cy, count, yoff; float flash, flashColor[4]; if(!string || !string[0]) return; flashColor[CR] = (red >= 0? ((1 + 2 * MINMAX_OF(0, red, 1)) / 3) : 1); flashColor[CB] = (blue >= 0? ((1 + 2 * MINMAX_OF(0, blue, 1)) / 3) : 1); flashColor[CG] = (green >= 0? ((1 + 2 * MINMAX_OF(0, green, 1)) / 3) : 1); flashColor[CA] = cfg.menuGlitter * (alpha>=0? MINMAX_OF(0, alpha, 1) : 1); for(pass = (flagShadow? 0 : 1); pass < 2; ++pass) { count = initialCount; if(red >= 0) DGL_Color4f(red, green, blue, alpha); ch = string; cx = x; cy = y; for(;;) { c = *ch++; yoff = 0; flash = 0; // Do the type-in effect? if(flagTypeIn && cfg.menuEffects != 0) { int maxCount = (typeInTime > 0? typeInTime * 2 : 0); if(count == maxCount) { flash = 1; if(red >= 0) DGL_Color4f(1, 1, 1, 1); } else if(count + 1 == maxCount) { flash = 0.5f; if(red >= 0) DGL_Color4f((1 + red) / 2, (1 + green) / 2, (1 + blue) / 2, alpha); } else if(count + 2 == maxCount) { flash = 0.25f; if(red >= 0) DGL_Color4f(red, green, blue, alpha); } else if(count + 3 == maxCount) { flash = 0.12f; if(red >= 0) DGL_Color4f(red, green, blue, alpha); } else if(count > maxCount) { break; } } count++; if(!c) break; if(c == '\n') { cx = x; cy += 12; continue; } w = gFonts[font].chars[c].patch.width; h = gFonts[font].chars[c].patch.height; if(!gFonts[font].chars[c].patch.lump) { // A character we don't have a patch for...?! continue; } if(pass) { // The character itself. GL_DrawPatch_CS(cx, cy + yoff, gFonts[font].chars[c].patch.lump); // Do something flashy! if(flash > 0) { M_LetterFlash(cx, cy + yoff + h/2, w, h, true, flashColor[CR], flashColor[CG], flashColor[CB], flashColor[CA] * flash); } } else if(flagShadow && cfg.menuShadow > 0) { // Shadow. M_LetterFlash(cx, cy + yoff + h/2, w, h, false, 1, 1, 1, (red < 0 ? DGL_GetInteger(DGL_CURRENT_COLOR_A) / 255.0f : alpha) * cfg.menuShadow); } cx += w; } } } #if __JHERETIC__ || __JHEXEN__ void Hu_DrawSmallNum(int val, int numDigits, int x, int y, float alpha) { int w = dpSmallNumbers[0].width; boolean drawMinus = false; if(val < 0) { if(numDigits == 2 && val < -9) val = -9; else if(numDigits == 3 && val < -99) val = -99; val = -val; drawMinus = true; } // In the special case of 0, you draw 0. if(val == 0) WI_DrawPatch(x - w, y, 1, 1, 1, alpha, &dpSmallNumbers[0], NULL, false, ALIGN_LEFT); // Draw the number. while(val && numDigits--) { x -= w; WI_DrawPatch(x, y, 1, 1, 1, alpha, &dpSmallNumbers[val % 10], NULL, false, ALIGN_LEFT); val /= 10; } // Draw a minus sign if necessary. if(drawMinus) WI_DrawPatch(x - 8, y, 1, 1, 1, alpha, &huMinus, NULL, false, ALIGN_LEFT); } #endif /** * This routine tests for a string-replacement for the patch. * If one is found, it's used instead of the original graphic. * * "{fontb; r=0.5; g=1; b=0; x=2; y=-2}This is good!" * * If the patch is not in an IWAD, it won't be replaced! * * @param altstring String to use instead of the patch if appropriate. * @param built-in (True) if the altstring is a built-in replacement * (ie it does not originate from a DED definition). */ void WI_DrawPatch(int x, int y, float r, float g, float b, float a, const dpatch_t* patch, const char* altstring, boolean builtin, int halign) { char def[80], *string; int patchString = 0, posx = x; if(IS_DEDICATED) return; if(!patch) return; if(altstring && altstring[0] && !builtin) { // We have already determined a string to replace this with. if(W_IsFromIWAD(patch->lump)) { WI_DrawParamText(x, y, altstring, GF_FONTB, r, g, b, a, false, true, halign); return; } } else if(cfg.usePatchReplacement) { // We might be able to replace the patch with a string if(!patch) return; strcpy(def, "Patch Replacement|"); strcat(def, W_LumpName(patch->lump)); patchString = Def_Get(DD_DEF_VALUE, def, &string); if(W_IsFromIWAD(patch->lump)) { // A user replacement? if(patchString) { WI_DrawParamText(x, y, string, GF_FONTB, r, g, b, a, false, true, halign); return; } // A built-in replacement? if(cfg.usePatchReplacement == 2 && altstring && altstring[0]) { WI_DrawParamText(x, y, altstring, GF_FONTB, r, g, b, a, false, true, halign); return; } } } if(!patch) return; // No replacement possible/wanted - use the original patch. if(halign == ALIGN_CENTER) posx -= patch->width /2; else if(halign == ALIGN_RIGHT) posx -= patch->width; DGL_Color4f(1, 1, 1, a); GL_DrawPatch_CS(posx, y, patch->lump); } /** * Draws a box using the border patches, a border is drawn outside. */ void M_DrawBackgroundBox(float x, float y, float w, float h, float red, float green, float blue, float alpha, boolean background, int border) { dpatch_t* t = 0, *b = 0, *l = 0, *r = 0, *tl = 0, *tr = 0, *br = 0, *bl = 0; int up = -1; switch(border) { case BORDERUP: t = &borderPatches[2]; b = &borderPatches[0]; l = &borderPatches[1]; r = &borderPatches[3]; tl = &borderPatches[6]; tr = &borderPatches[7]; br = &borderPatches[4]; bl = &borderPatches[5]; up = -1; break; case BORDERDOWN: t = &borderPatches[0]; b = &borderPatches[2]; l = &borderPatches[3]; r = &borderPatches[1]; tl = &borderPatches[4]; tr = &borderPatches[5]; br = &borderPatches[6]; bl = &borderPatches[7]; up = 1; break; default: break; } DGL_Color4f(red, green, blue, alpha); if(background) { DGL_SetMaterial(P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(borderLumps[0], MN_FLATS))); DGL_DrawRectTiled(x, y, w, h, 64, 64); } if(border) { // Top DGL_SetPatch(t->lump, DGL_REPEAT, DGL_REPEAT); DGL_DrawRectTiled(x, y - t->height, w, t->height, up * t->width, up * t->height); // Bottom DGL_SetPatch(b->lump, DGL_REPEAT, DGL_REPEAT); DGL_DrawRectTiled(x, y + h, w, b->height, up * b->width, up * b->height); // Left DGL_SetPatch(l->lump, DGL_REPEAT, DGL_REPEAT); DGL_DrawRectTiled(x - l->width, y, l->width, h, up * l->width, up * l->height); // Right DGL_SetPatch(r->lump, DGL_REPEAT, DGL_REPEAT); DGL_DrawRectTiled(x + w, y, r->width, h, up * r->width, up * r->height); // Top Left DGL_SetPatch(tl->lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(x - tl->width, y - tl->height, tl->width, tl->height, red, green, blue, alpha); // Top Right DGL_SetPatch(tr->lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(x + w, y - tr->height, tr->width, tr->height, red, green, blue, alpha); // Bottom Right DGL_SetPatch(br->lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(x + w, y + h, br->width, br->height, red, green, blue, alpha); // Bottom Left DGL_SetPatch(bl->lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(x - bl->width, y + h, bl->width, bl->height, red, green, blue, alpha); } } /** * Draws a menu slider control */ #if __JHERETIC__ || __JHEXEN__ void M_DrawSlider(int x, int y, int width, int slot, float alpha) #else void M_DrawSlider(int x, int y, int width, int height, int slot, float alpha) #endif { #if __JHERETIC__ || __JHEXEN__ float unit = (width * 8 + 2) / width; DGL_Color4f( 1, 1, 1, alpha); GL_DrawPatch_CS(x - 32, y, W_GetNumForName("M_SLDLT")); GL_DrawPatch_CS(x + width * 8, y, W_GetNumForName("M_SLDRT")); DGL_SetPatch(W_GetNumForName("M_SLDMD1"), DGL_REPEAT, DGL_REPEAT); DGL_DrawRectTiled(x - 1, y + 1, width * 8 + 2, 13, 8, 13); DGL_Color4f( 1, 1, 1, alpha); GL_DrawPatch_CS(x + 4 + slot * unit, y + 7, W_GetNumForName("M_SLDKB")); #else int xx; float scale = height / 13.0f; xx = x; DGL_SetPatch(W_GetNumForName("M_THERML"), DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(xx, y, 6 * scale, height, 1, 1, 1, alpha); xx += 6 * scale; DGL_SetPatch(W_GetNumForName("M_THERM2"), DGL_REPEAT, DGL_CLAMP_TO_EDGE); DGL_DrawRectTiled(xx, y, 8 * width * scale, height, 8 * scale, height); xx += 8 * width * scale; DGL_SetPatch(W_GetNumForName("M_THERMR"), DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(xx, y, 6 * scale, height, 1, 1, 1, alpha); DGL_SetPatch(W_GetNumForName("M_THERMO"), DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_DrawRect(x + (6 + slot * 8) * scale, y, 6 * scale, height, 1, 1, 1, alpha); #endif } void Draw_BeginZoom(float s, float originX, float originY) { DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(originX, originY, 0); DGL_Scalef(s, s, 1); DGL_Translatef(-originX, -originY, 0); } void Draw_EndZoom(void) { DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } /** * Draws a 'fancy' fullscreen fog effect. Used as a background to various * HUD displays. */ void Hu_DrawFogEffect(int effectID, DGLuint tex, float texOffset[2], float texAngle, float alpha, float arg1) { const float xscale = 2.0f; const float yscale = 1.0f; if(!(alpha > 0)) return; if(effectID == 4) { DGL_SetNoMaterial(); DGL_DrawRect(0, 0, 320, 200, 0.0f, 0.0f, 0.0f, MIN_OF(alpha, .5f)); return; } if(effectID == 2) { DGL_Disable(DGL_TEXTURING); DGL_Color4f(alpha, alpha / 2, 0, alpha / 3); DGL_BlendMode(BM_INVERSE_MUL); DGL_DrawRectTiled(0, 0, 320, 200, 1, 1); DGL_Enable(DGL_TEXTURING); } DGL_Bind(tex); DGL_Color3f(alpha, alpha, alpha); DGL_MatrixMode(DGL_TEXTURE); DGL_LoadIdentity(); DGL_PushMatrix(); if(effectID == 1) { DGL_Color3f(alpha / 3, alpha / 2, alpha / 2); DGL_BlendMode(BM_INVERSE_MUL); } else if(effectID == 2) { DGL_Color3f(alpha / 5, alpha / 3, alpha / 2); DGL_BlendFunc(DGL_SRC_ALPHA, DGL_SRC_ALPHA); } else if(effectID == 0) { DGL_Color3f(alpha * 0.15, alpha * 0.2, alpha * 0.3); DGL_BlendFunc(DGL_SRC_ALPHA, DGL_SRC_ALPHA); } if(effectID == 3) { // The fancy one. DGL_BlendFunc(DGL_SRC_ALPHA, DGL_SRC_ALPHA); DGL_Translatef(texOffset[VX] / 320, texOffset[VY] / 200, 0); DGL_Rotatef(texAngle * 1, 0, 0, 1); DGL_Translatef(-texOffset[VX] / 320, -texOffset[VY] / 200, 0); DGL_Begin(DGL_QUADS); // Top Half DGL_Color4f(alpha * 0.25, alpha * 0.3, alpha * 0.4, 1 - (alpha * 0.8) ); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(0, 0); DGL_Color4f(alpha * 0.25, alpha * 0.3, alpha * 0.4, 1 - (alpha * 0.8) ); DGL_TexCoord2f(0, xscale, 0); DGL_Vertex2f(320, 0); DGL_Color4f(alpha * 0.7, alpha * 0.7, alpha * 0.8, 1 - (0-(alpha * 0.9))); DGL_TexCoord2f(0, xscale, yscale * arg1); DGL_Vertex2f(320, 200 * arg1); DGL_Color4f(alpha * 0.7, alpha * 0.7, alpha * 0.8, 1 - (0-(alpha * 0.9))); DGL_TexCoord2f(0, 0, yscale * arg1); DGL_Vertex2f(0, 200 * arg1); // Bottom Half DGL_Color4f(alpha * 0.7, alpha * 0.7, alpha * 0.8, 1 - (0-(alpha * 0.9))); DGL_TexCoord2f(0, 0, yscale * arg1); DGL_Vertex2f(0, 200 * arg1); DGL_Color4f(alpha * 0.7, alpha * 0.7, alpha * 0.8, 1 - (0-(alpha * 0.9))); DGL_TexCoord2f(0, xscale, yscale * arg1); DGL_Vertex2f(320, 200 * arg1); DGL_Color4f(alpha * 0.25, alpha * 0.3, alpha * 0.4, 1 - (alpha * 0.8) ); DGL_TexCoord2f(0, xscale, yscale); DGL_Vertex2f(320, 200); DGL_Color4f(alpha * 0.25, alpha * 0.3, alpha * 0.4, 1 - (alpha * 0.8) ); DGL_TexCoord2f(0, 0, yscale); DGL_Vertex2f(0, 200); DGL_End(); } else { DGL_Translatef(texOffset[VX] / 320, texOffset[VY] / 200, 0); DGL_Rotatef(texAngle * (effectID == 0 ? 0.5 : 1), 0, 0, 1); DGL_Translatef(-texOffset[VX] / 320, -texOffset[VY] / 200, 0); if(effectID == 2) DGL_DrawRectTiled(0, 0, 320, 200, 270 / 8, 4 * 225); else if(effectID == 0) DGL_DrawRectTiled(0, 0, 320, 200, 270 / 4, 8 * 225); else DGL_DrawRectTiled(0, 0, 320, 200, 270, 225); } DGL_MatrixMode(DGL_TEXTURE); DGL_PopMatrix(); DGL_BlendMode(BM_NORMAL); } static void drawFogEffect(void) { #define mfd (&fogEffectData) DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); // Two layers. Hu_DrawFogEffect(cfg.hudFog - 1, mfd->texture, mfd->layers[0].texOffset, mfd->layers[0].texAngle, mfd->alpha, fogEffectData.joinY); Hu_DrawFogEffect(cfg.hudFog - 1, mfd->texture, mfd->layers[1].texOffset, mfd->layers[1].texAngle, mfd->alpha, fogEffectData.joinY); // Restore original matrices. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); #undef mfd } void Hu_Drawer(void) { if((Hu_MenuIsActive() || Hu_MenuAlpha() > 0) || Hu_IsMessageActive()) { // Use a plain 320x200 projection. DGL_MatrixMode(DGL_PROJECTION); DGL_LoadIdentity(); DGL_PushMatrix(); DGL_Ortho(0, 0, 320, 200, -1, 1); // Draw the fog effect? if(fogEffectData.alpha > 0 && cfg.hudFog && !((Hu_MenuIsActive() || Hu_MenuAlpha() > 0) && MN_CurrentMenuHasBackground())) drawFogEffect(); if(Hu_IsMessageActive()) Hu_MsgDrawer(); else Hu_MenuDrawer(); DGL_MatrixMode(DGL_PROJECTION); DGL_PopMatrix(); } } void Hu_FogEffectSetAlphaTarget(float alpha) { fogEffectData.targetAlpha = MINMAX_OF(0, alpha, 1); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_xgsave.c0000644000175000017500000001712111357170242022607 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_xgsave.c: Extended Generalized Line Types. * * Implements: Saving and loading routines for the XG data. * * \bug Not 64bit clean: In function 'SV_ReadXGLine': cast to pointer from integer of different size */ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "p_mapsetup.h" #include "p_saveg.h" #include "p_xg.h" #include "p_svtexarc.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void SV_WriteXGLine(linedef_t *li) { xgline_t *xg; linetype_t *info; xg = P_ToXLine(li)->xg; info = &xg->info; // Version byte. SV_WriteByte(1); /** * Remember, savegames are applied on top of an initialized map. * No strings are saved, because they are all const strings * defined either in the maps's DDXGDATA lump or a DED file. * During loading, XL_SetLineType is called with the id in the savegame. */ SV_WriteLong(info->id); SV_WriteLong(info->actCount); SV_WriteByte(xg->active); SV_WriteByte(xg->disabled); SV_WriteLong(xg->timer); SV_WriteLong(xg->tickerTimer); SV_WriteShort(SV_ThingArchiveNum(xg->activator)); SV_WriteLong(xg->idata); SV_WriteFloat(xg->fdata); SV_WriteLong(xg->chIdx); SV_WriteFloat(xg->chTimer); } void SV_ReadXGLine(linedef_t *li) { xgline_t *xg; xline_t *xline = P_ToXLine(li); // Read version. SV_ReadByte(); // This'll set all the correct string pointers and other data. XL_SetLineType(li, SV_ReadLong()); if(!xline || !xline->xg) Con_Error("SV_ReadXGLine: Bad XG line!\n"); xg = xline->xg; xg->info.actCount = SV_ReadLong(); xg->active = SV_ReadByte(); xg->disabled = SV_ReadByte(); xg->timer = SV_ReadLong(); xg->tickerTimer = SV_ReadLong(); // Will be updated later. xg->activator = (void *) (unsigned int) SV_ReadShort(); xg->idata = SV_ReadLong(); xg->fdata = SV_ReadFloat(); xg->chIdx = SV_ReadLong(); xg->chTimer = SV_ReadFloat(); } /** * The function must belong to the specified xgsector. */ void SV_WriteXGFunction(xgsector_t *xg, function_t *fn) { // Version byte. SV_WriteByte(1); SV_WriteLong(fn->flags); SV_WriteShort(fn->pos); SV_WriteShort(fn->repeat); SV_WriteShort(fn->timer); SV_WriteShort(fn->maxTimer); SV_WriteFloat(fn->value); SV_WriteFloat(fn->oldValue); } void SV_ReadXGFunction(xgsector_t *xg, function_t *fn) { // Version byte. SV_ReadByte(); fn->flags = SV_ReadLong(); fn->pos = SV_ReadShort(); fn->repeat = SV_ReadShort(); fn->timer = SV_ReadShort(); fn->maxTimer = SV_ReadShort(); fn->value = SV_ReadFloat(); fn->oldValue = SV_ReadFloat(); } void SV_WriteXGSector(struct sector_s *sec) { int i; xgsector_t *xg; sectortype_t *info; xsector_t *xsec = P_ToXSector(sec); xg = xsec->xg; info = &xg->info; // Version byte. SV_WriteByte(1); SV_WriteLong(info->id); SV_Write(info->count, sizeof(info->count)); SV_Write(xg->chainTimer, sizeof(xg->chainTimer)); SV_WriteLong(xg->timer); SV_WriteByte(xg->disabled); for(i = 0; i < 3; ++i) SV_WriteXGFunction(xg, &xg->rgb[i]); for(i = 0; i < 2; ++i) SV_WriteXGFunction(xg, &xg->plane[i]); SV_WriteXGFunction(xg, &xg->light); } void SV_ReadXGSector(struct sector_s *sec) { int i; xgsector_t *xg; xsector_t *xsec = P_ToXSector(sec); // Version byte. SV_ReadByte(); // This'll init all the data. XS_SetSectorType(sec, SV_ReadLong()); xg = xsec->xg; SV_Read(xg->info.count, sizeof(xg->info.count)); SV_Read(xg->chainTimer, sizeof(xg->chainTimer)); xg->timer = SV_ReadLong(); xg->disabled = SV_ReadByte(); for(i = 0; i < 3; ++i) SV_ReadXGFunction(xg, &xg->rgb[i]); for(i = 0; i < 2; ++i) SV_ReadXGFunction(xg, &xg->plane[i]); SV_ReadXGFunction(xg, &xg->light); } void SV_WriteXGPlaneMover(thinker_t *th) { uint i; xgplanemover_t *mov = (xgplanemover_t *) th; SV_WriteByte(3); // Version. SV_WriteLong(P_ToIndex(mov->sector)); SV_WriteByte(mov->ceiling); SV_WriteLong(mov->flags); i = P_ToIndex(mov->origin); if(i >= numlines) // Is it a real line? i = 0; // No... else i++; SV_WriteLong(i); // Zero means there is no origin. SV_WriteLong(FLT2FIX(mov->destination)); SV_WriteLong(FLT2FIX(mov->speed)); SV_WriteLong(FLT2FIX(mov->crushSpeed)); SV_WriteLong(SV_MaterialArchiveNum(mov->setMaterial)); SV_WriteLong(mov->setSectorType); SV_WriteLong(mov->startSound); SV_WriteLong(mov->endSound); SV_WriteLong(mov->moveSound); SV_WriteLong(mov->minInterval); SV_WriteLong(mov->maxInterval); SV_WriteLong(mov->timer); } /** * Reads the plane mover thinker. */ int SV_ReadXGPlaneMover(xgplanemover_t* mov) { int i, num; byte ver; ver = SV_ReadByte(); // Version. mov->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); mov->ceiling = SV_ReadByte(); mov->flags = SV_ReadLong(); i = SV_ReadLong(); if(i) mov->origin = P_ToPtr(DMU_LINEDEF, i - 1); mov->destination = FIX2FLT(SV_ReadLong()); mov->speed = FIX2FLT(SV_ReadLong()); mov->crushSpeed = FIX2FLT(SV_ReadLong()); num = SV_ReadLong(); if(ver >= 3) mov->setMaterial = SV_GetArchiveMaterial(num, 0); else mov->setMaterial = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(W_LumpName(num), MN_FLATS)); mov->setSectorType = SV_ReadLong(); mov->startSound = SV_ReadLong(); mov->endSound = SV_ReadLong(); mov->moveSound = SV_ReadLong(); mov->minInterval = SV_ReadLong(); mov->maxInterval = SV_ReadLong(); mov->timer = SV_ReadLong(); mov->thinker.function = XS_PlaneMover; return true; // Add this thinker. } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_automap.c0000644000175000017500000004224011357170242022760 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_automap.c: The automap. */ // HEADER FILES ------------------------------------------------------------ #include #include "doomsday.h" // temporary, to be removed. #include "p_automap.h" // MACROS ------------------------------------------------------------------ #define LERP(start, end, pos) (end * pos + start * (1 - pos)) // Translate between frame and map distances: #define FTOM(map, x) ((x) * (map)->scaleFTOM) #define MTOF(map, x) ((x) * (map)->scaleMTOF) // Map boundry plane idents: #define BOXTOP (0) #define BOXBOTTOM (1) #define BOXLEFT (2) #define BOXRIGHT (3) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static void rotate2D(float* x, float* y, float angle) { #define PI 3.141592657 float tmpx; tmpx = (float) ((*x * cos(angle/180 * PI)) - (*y * sin(angle/180 * PI))); *y = (float) ((*x * sin(angle/180 * PI)) + (*y * cos(angle/180 * PI))); *x = tmpx; #undef PI } /** * Calculate the min/max scaling factors. * * Take the distance from the bottom left to the top right corners and * choose a max scaling factor such that this distance is short than both * the automap window width and height. */ static void calcViewScaleFactors(automap_t* map) { float dx, dy, dist, a, b; if(!map) return; // hmm... dx = map->bounds[BOXRIGHT] - map->bounds[BOXLEFT]; dy = map->bounds[BOXTOP] - map->bounds[BOXBOTTOM]; dist = (float) sqrt(dx * dx + dy * dy); if(dist < 0) dist = -dist; a = map->window.width / dist; b = map->window.height / dist; map->minScaleMTOF = (a < b ? a : b); map->maxScaleMTOF = map->window.height / map->minScale; map->updateViewScale = false; } void Automap_SetWorldBounds(automap_t* map, float lowX, float hiX, float lowY, float hiY) { if(!map) return; map->bounds[BOXLEFT] = lowX; map->bounds[BOXTOP] = hiY; map->bounds[BOXRIGHT] = hiX; map->bounds[BOXBOTTOM] = lowY; map->updateViewScale = true; } void Automap_SetMinScale(automap_t* map, const float scale) { if(!map) return; map->minScale = MAX_OF(1, scale); map->updateViewScale = true; } /** * @param max Maximum view position delta, in world units. */ void Automap_SetMaxLocationTargetDelta(automap_t* map, float max) { if(!map) return; map->maxViewPositionDelta = MINMAX_OF(0, max, 32768*2); } void Automap_Open(automap_t* map, int yes, int fast) { if(!map) return; if(yes == map->active) return; // No change. map->targetAlpha = (yes? 1.f : 0.f); if(fast) { map->alpha = map->oldAlpha = map->targetAlpha; } else { // Reset the timer. map->oldAlpha = map->alpha; map->alphaTimer = 0.f; } map->active = (yes? true : false); } void Automap_RunTic(automap_t* map) { float width, height, scale; if(!map) return; if(map->updateViewScale) calcViewScaleFactors(map); // Window position and dimensions. if(!map->fullScreenMode) { automapwindow_t* win = &map->window; win->posTimer += .4f; if(win->posTimer >= 1) { win->x = win->targetX; win->y = win->targetY; win->width = win->targetWidth; win->height = win->targetHeight; } else { win->x = LERP(win->oldX, win->targetX, win->posTimer); win->y = LERP(win->oldY, win->targetY, win->posTimer); win->width = LERP(win->oldWidth, win->targetWidth, win->posTimer); win->height = LERP(win->oldHeight, win->targetHeight, win->posTimer); } } // Map viewer location. map->viewTimer += .4f; if(map->viewTimer >= 1) { map->viewX = map->targetViewX; map->viewY = map->targetViewY; } else { map->viewX = LERP(map->oldViewX, map->targetViewX, map->viewTimer); map->viewY = LERP(map->oldViewY, map->targetViewY, map->viewTimer); } // Move the parallax layer. map->viewPLX = map->viewX / 4000; map->viewPLY = map->viewY / 4000; // Map view scale (zoom). map->viewScaleTimer += .4f; if(map->viewScaleTimer >= 1) { map->viewScale = map->targetViewScale; } else { map->viewScale = LERP(map->oldViewScale, map->targetViewScale, map->viewScaleTimer); } // Map view rotation. map->angleTimer += .4f; if(map->angleTimer >= 1) { map->angle = map->targetAngle; } else { float diff, startAngle = map->oldAngle, endAngle = map->targetAngle; if(endAngle > startAngle) { diff = endAngle - startAngle; if(diff > 180) endAngle = startAngle - (360 - diff); } else { diff = startAngle - endAngle; if(diff > 180) endAngle = startAngle + (360 - diff); } map->angle = LERP(startAngle, endAngle, map->angleTimer); if(map->angle < 0) map->angle += 360; else if(map->angle > 360) map->angle -= 360; } // // Activate the new scale, position etc. // scale = map->viewScale; // Scaling multipliers. map->scaleMTOF = scale; map->scaleFTOM = 1.0f / map->scaleMTOF; width = Automap_FrameToMap(map, map->window.width); height = Automap_FrameToMap(map, map->window.height); // Calculate the in-view, AABB. { // Rotation-aware. #define ADDTOBOX(b, x, y) if((x) < (b)[BOXLEFT]) \ (b)[BOXLEFT] = (x); \ else if((x) > (b)[BOXRIGHT]) \ (b)[BOXRIGHT] = (x); \ if((y) < (b)[BOXBOTTOM]) \ (b)[BOXBOTTOM] = (y); \ else if((y) > (b)[BOXTOP]) \ (b)[BOXTOP] = (y); float angle; float v[2]; angle = map->angle; v[0] = -width / 2; v[1] = -height / 2; rotate2D(&v[0], &v[1], angle); v[0] += map->viewX; v[1] += map->viewY; map->viewAABB[BOXLEFT] = map->viewAABB[BOXRIGHT] = v[0]; map->viewAABB[BOXTOP] = map->viewAABB[BOXBOTTOM] = v[1]; v[0] = width / 2; v[1] = -height / 2; rotate2D(&v[0], &v[1], angle); v[0] += map->viewX; v[1] += map->viewY; ADDTOBOX(map->viewAABB, v[0], v[1]); v[0] = -width / 2; v[1] = height / 2; rotate2D(&v[0], &v[1], angle); v[0] += map->viewX; v[1] += map->viewY; ADDTOBOX(map->viewAABB, v[0], v[1]); v[0] = width / 2; v[1] = height / 2; rotate2D(&v[0], &v[1], angle); v[0] += map->viewX; v[1] += map->viewY; ADDTOBOX(map->viewAABB, v[0], v[1]); #undef ADDTOBOX } } /** * Translates from map to automap window coordinates. */ float Automap_MapToFrame(const automap_t* map, float val) { if(!map) return 1; return MTOF(map, val); } /** * Translates from automap window to map coordinates. */ float Automap_FrameToMap(const automap_t* map, float val) { if(!map) return 1; return FTOM(map, val); } void Automap_SetWindowTarget(automap_t* map, int x, int y, int w, int h) { automapwindow_t* win; if(!map) return; // Are we in fullscreen mode? // If so, setting the window size is not allowed. if(map->fullScreenMode) return; win = &map->window; // Already at this target? if(x == win->targetX && y == win->targetY && w == win->targetWidth && h == win->targetHeight) return; win->oldX = win->x; win->oldY = win->y; win->oldWidth = win->width; win->oldHeight = win->height; // Restart the timer. win->posTimer = 0; win->targetX = (float) x; win->targetY = (float) y; win->targetWidth = (float) w; win->targetHeight = (float) h; } void Automap_GetWindow(const automap_t* map, float* x, float* y, float* w, float* h) { if(!map) return; if(x) *x = map->window.x; if(y) *y = map->window.y; if(w) *w = map->window.width; if(h) *h = map->window.height; } void Automap_SetLocationTarget(automap_t* map, float x, float y) { boolean instantChange = false; if(!map) return; x = MINMAX_OF(-32768, x, 32768); y = MINMAX_OF(-32768, y, 32768); // Already at this target? if(x == map->targetViewX && y == map->targetViewY) return; if(map->maxViewPositionDelta > 0) { float dx, dy, dist; dx = map->viewX - x; dy = map->viewY - y; dist = (float) sqrt(dx * dx + dy * dy); if(dist < 0) dist = -dist; if(dist > map->maxViewPositionDelta) instantChange = true; } if(instantChange) { map->viewX = map->oldViewX = map->targetViewX = x; map->viewY = map->oldViewY = map->targetViewY = y; } else { map->oldViewX = map->viewX; map->oldViewY = map->viewY; map->targetViewX = x; map->targetViewY = y; // Restart the timer. map->viewTimer = 0; } } void Automap_GetLocation(const automap_t* map, float* x, float* y) { if(!map) return; if(x) *x = map->viewX; if(y) *y = map->viewY; } void Automap_GetViewParallaxPosition(const automap_t* map, float* x, float* y) { if(!map) return; if(x) *x = map->viewPLX; if(y) *y = map->viewPLY; } /** * @return Current alpha level of the automap. */ float Automap_GetViewAngle(const automap_t* map) { if(!map) return 0; return map->angle; } void Automap_SetViewScaleTarget(automap_t* map, float scale) { if(!map) return; if(map->updateViewScale) calcViewScaleFactors(map); scale = MINMAX_OF(map->minScaleMTOF, scale, map->maxScaleMTOF); // Already at this target? if(scale == map->targetViewScale) return; map->oldViewScale = map->viewScale; // Restart the timer. map->viewScaleTimer = 0; map->targetViewScale = scale; } void Automap_SetViewAngleTarget(automap_t* map, float angle) { if(!map) return; // Already at this target? if(angle == map->targetAngle) return; map->oldAngle = map->angle; map->targetAngle = MINMAX_OF(0, angle, 359.9999f); // Restart the timer. map->angleTimer = 0; } float Automap_MapToFrameMultiplier(const automap_t* map) { if(!map) return 1; return map->scaleMTOF; } /** * @return True if the specified map is currently active. */ int Automap_IsActive(const automap_t* map) { if(!map) return false; return map->active; } void Automap_GetInViewAABB(const automap_t* map, float* lowX, float* hiX, float* lowY, float* hiY) { if(!map) return; if(lowX) *lowX = map->viewAABB[BOXLEFT]; if(hiX) *hiX = map->viewAABB[BOXRIGHT]; if(lowY) *lowY = map->viewAABB[BOXBOTTOM]; if(hiY) *hiY = map->viewAABB[BOXTOP]; } void Automap_ClearMarks(automap_t* map) { uint i; if(!map) return; for(i = 0; i < MAX_MAP_POINTS; ++i) map->markpointsUsed[i] = false; map->markpointnum = 0; } unsigned int Automap_GetNumMarks(const automap_t* map) { unsigned int i, numUsed = 0; if(!map) return numUsed; for(i = 0; i < MAX_MAP_POINTS; ++i) if(map->markpointsUsed[i]) numUsed++; return numUsed; } /** * Adds a marker at the current location. */ int Automap_AddMark(automap_t* map, float x, float y, float z) { unsigned int num; automappoint_t* point; if(!map) return -1; num = map->markpointnum; point = &map->markpoints[num]; point->pos[0] = x; point->pos[1] = y; point->pos[2] = z; map->markpointsUsed[num] = true; map->markpointnum = (map->markpointnum + 1) % MAX_MAP_POINTS; return num; } int Automap_GetMark(const automap_t* map, unsigned int mark, float* x, float* y, float* z) { if(!map) return false; if(!x && !y && !z) return false; if(mark < MAX_MAP_POINTS && map->markpointsUsed[mark]) { const automappoint_t* point = &map->markpoints[mark]; if(x) *x = point->pos[0]; if(y) *y = point->pos[1]; if(z) *z = point->pos[2]; return true; } return false; } /** * Toggles between active and max zoom. */ void Automap_ToggleZoomMax(automap_t* map) { if(!map) return; if(map->updateViewScale) calcViewScaleFactors(map); // When switching to max scale mode, store the old scale. if(!map->forceMaxScale) map->priorToMaxScale = map->viewScale; map->forceMaxScale = !map->forceMaxScale; Automap_SetViewScaleTarget(map, (map->forceMaxScale? 0 : map->priorToMaxScale)); } /** * Toggles follow mode. */ void Automap_ToggleFollow(automap_t* map) { if(!map) return; map->panMode = !map->panMode; } void Automap_SetViewRotate(automap_t* map, int on) { if(!map) return; map->rotate = on; } void Automap_SetWindowFullScreenMode(automap_t* map, int value) { if(!map) return; if(value < 0 || value > 2) { #if _DEBUG Con_Error("Automap::SetWindowFullScreenMode: Unknown value %i.", value); #endif return; } if(value == 2) // toggle map->fullScreenMode = !map->fullScreenMode; else map->fullScreenMode = value; } int Automap_IsMapWindowInFullScreenMode(const automap_t* map) { if(!map) return false; return map->fullScreenMode; } /** * Set the alpha level of the automap. Alpha levels below one automatically * show the game view in addition to the automap. * * @param alpha Alpha level to set the automap too (0...1) */ void Automap_SetOpacityTarget(automap_t* map, float alpha) { if(!map) return; alpha = MINMAX_OF(0, alpha, 1); // Already at this target? if(alpha == map->targetAlpha) return; map->oldAlpha = map->alpha; // Restart the timer. map->alphaTimer = 0; map->targetAlpha = alpha; } /** * @return Current alpha level of the automap. */ float Automap_GetOpacity(const automap_t* map) { if(!map) return 0; return map->alpha; } int Automap_GetFlags(const automap_t* map) { if(!map) return 0; return map->flags; } /** * @param flags AMF_* flags. */ void Automap_SetFlags(automap_t* map, int flags) { if(!map) return; map->flags = flags; } void Automap_UpdateWindow(automap_t* map, float newX, float newY, float newWidth, float newHeight) { automapwindow_t* win; if(!map) return; win = &map->window; if(newX != win->x || newY != win->y || newWidth != win->width || newHeight != win->height) { if(map->fullScreenMode) { // In fullscreen mode we always snap straight to the // new dimensions. win->x = win->oldX = win->targetX = newX; win->y = win->oldY = win->targetY = newY; win->width = win->oldWidth = win->targetWidth = newWidth; win->height = win->oldHeight = win->targetHeight = newHeight; } else { // Snap dimensions if new scale is smaller. if(newX > win->x) win->x = win->oldX = win->targetX = newX; if(newY > win->y) win->y = win->oldY = win->targetY = newY; if(newWidth < win->width) win->width = win->oldWidth = win->targetWidth = newWidth; if(newHeight < win->height) win->height = win->oldHeight = win->targetHeight = newHeight; } // Now the screen dimensions have changed we have to update scaling // factors accordingly. map->updateViewScale = true; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_iterlist.c0000644000175000017500000001171511357170242023154 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_iterlist.c : Object lists. * The lists can be traversed through iteration but otherwise act like a * LIFO stack. Used for things like spechits, linespecials etc. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "p_iterlist.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Allocate and initialize a new iterlist. * * @return Ptr to the new list. */ iterlist_t *P_CreateIterList(void) { iterlist_t *list = malloc(sizeof(iterlist_t)); list->list = NULL; list->count = list->max = list->rover = 0; list->forward = false; return list; } /** * Free any memory used by the iterlist. * * @param list Ptr to the list to be destroyed. */ void P_DestroyIterList(iterlist_t *list) { if(!list) return; if(list->count > 0) { free(list->list); list->list = NULL; } free(list); list = NULL; } /** * Add the given object to iterlist. * * @param list Ptr to the list to add 'obj' too. * @param obj Ptr to the object to be added to the list. * @return The index of the object within 'list' once added, * ELSE @c -1. */ int P_AddObjectToIterList(iterlist_t *list, void *obj) { if(!list || !obj) return -1; if(++list->count > list->max) { list->max = (list->max? list->max * 2 : 8); list->list = realloc(list->list, sizeof(void*) * list->max); } list->list[list->count - 1] = obj; return list->count - 1; } /** * Pop the top of the iterlist and return the next element. * * @param list Ptr to the list to be pop. * @return Ptr to the next object in 'list'. */ void* P_PopIterList(iterlist_t *list) { if(!list) return NULL; if(list->count > 0) return list->list[--list->count]; else return NULL; } /** * Returns the next element in the iterlist. * * @param list Ptr to the list to iterate. * @return The next object in the iterlist. */ void* P_IterListIterator(iterlist_t *list) { if(!list || !list->count) return NULL; if(list->forward) { if(list->rover < list->count - 1) return list->list[++list->rover]; else return NULL; } else { if(list->rover > 0) return list->list[--list->rover]; else return NULL; } } /** * Returns the iterlist iterator to the beginning (the end). * * @param list Ptr to the list whoose iterator to reset. * @param forward @c true = iteration will move forwards. */ void P_IterListResetIterator(iterlist_t *list, boolean forward) { if(!list) return; list->forward = forward; if(list->forward) list->rover = -1; else list->rover = list->count; } /** * Empty the iterlist. * * @param list Ptr to the list to empty. */ void P_EmptyIterList(iterlist_t *list) { if(!list) return; list->count = list->max = list->rover = 0; } /** * Return the size of the iterlist. * * @param list Ptr to the list to return the size of. * @return The size of the iterlist. */ int P_IterListSize(iterlist_t *list) { if(!list) return 0; return list->count; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_door.c0000644000175000017500000005546011357170242022265 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Martin Eyre *\author Copyright © 2003-2005 Samuel Villarreal *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_doors.c : Vertical doors (opening/closing). */ // HEADER FILES ------------------------------------------------------------ #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "dmu_lib.h" #include "p_player.h" #include "p_mapspec.h" #include "p_door.h" #if __JDOOM64__ # include "p_ceiling.h" # include "p_floor.h" # include "p_inventory.h" #endif // MACROS ------------------------------------------------------------------ // Sounds played by the doors when changing state. // jHexen uses sound sequences, so it's are defined as 'SFX_NONE'. #if __JDOOM64__ # define SFX_DOORCLOSE (SFX_DORCLS) # define SFX_DOORBLAZECLOSE (SFX_BDCLS) # define SFX_DOOROPEN (SFX_DOROPN) # define SFX_DOORBLAZEOPEN (SFX_BDOPN) # define SFX_DOORLOCKED (SFX_OOF) #elif __JDOOM__ # define SFX_DOORCLOSE (SFX_DORCLS) # define SFX_DOORBLAZECLOSE (SFX_BDCLS) # define SFX_DOOROPEN (SFX_DOROPN) # define SFX_DOORBLAZEOPEN (SFX_BDOPN) # define SFX_DOORLOCKED (SFX_OOF) #elif __JHERETIC__ # define SFX_DOORCLOSE (SFX_DORCLS) # define SFX_DOORBLAZECLOSE (SFX_NONE) # define SFX_DOOROPEN (SFX_DOROPN) # define SFX_DOORBLAZEOPEN (SFX_DOROPN) # define SFX_DOORLOCKED (SFX_PLROOF) #elif __JHEXEN__ # define SFX_DOORCLOSE (SFX_NONE) # define SFX_DOORBLAZECLOSE (SFX_NONE) # define SFX_DOOROPEN (SFX_NONE) # define SFX_DOORBLAZEOPEN (SFX_NONE) # define SFX_DOORLOCKED (SFX_NONE) #endif // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void T_Door(door_t* door) { xsector_t* xsec; result_e res; xsec = P_ToXSector(door->sector); switch(door->state) { case DS_WAIT: if(!--door->topCountDown) { switch(door->type) { #if __JDOOM64__ case DT_INSTANTRAISE: //jd64 door->state = DS_DOWN; break; #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ # if __JHERETIC__ case DT_BLAZEOPEN: # else case DT_BLAZERAISE: # endif door->state = DS_DOWN; // Time to go back down. S_SectorSound(door->sector, SORG_CEILING, SFX_DOORBLAZECLOSE); break; #endif case DT_NORMAL: door->state = DS_DOWN; // Time to go back down. #if __JHEXEN__ SN_StartSequence(P_SectorSoundOrigin(door->sector), SEQ_DOOR_STONE + xsec->seqType); #else S_SectorSound(door->sector, SORG_CEILING, SFX_DOORCLOSE); #endif break; case DT_CLOSE30THENOPEN: door->state = DS_UP; #if !__JHEXEN__ S_SectorSound(door->sector, SORG_CEILING, SFX_DOOROPEN); #endif break; default: break; } } break; case DS_INITIALWAIT: if(!--door->topCountDown) { switch(door->type) { case DT_RAISEIN5MINS: door->state = DS_UP; door->type = DT_NORMAL; #if !__JHEXEN__ S_SectorSound(door->sector, SORG_CEILING, SFX_DOOROPEN); #endif break; default: break; } } break; case DS_DOWN: res = T_MovePlane(door->sector, door->speed, P_GetFloatp(door->sector, DMU_FLOOR_HEIGHT), false, 1, -1); if(res == pastdest) { #if __JHEXEN__ SN_StopSequence(P_SectorSoundOrigin(door->sector)); #endif switch(door->type) { #if __JDOOM64__ case DT_INSTANTRAISE: //jd64 case DT_INSTANTCLOSE: //jd64 P_ToXSector(door->sector)->specialData = NULL; DD_ThinkerRemove(&door->thinker); // Unlink and free. break; #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ # if __JHERETIC__ case DT_BLAZEOPEN: # else case DT_BLAZERAISE: case DT_BLAZECLOSE: # endif xsec->specialData = NULL; DD_ThinkerRemove(&door->thinker); // Unlink and free. // DOOMII BUG: // This is what causes blazing doors to produce two closing // sounds as one has already been played when the door starts // to close (above) S_SectorSound(door->sector, SORG_CEILING, SFX_DOORBLAZECLOSE); break; #endif case DT_NORMAL: case DT_CLOSE: xsec->specialData = NULL; #if __JHEXEN__ P_TagFinished(P_ToXSector(door->sector)->tag); #endif DD_ThinkerRemove(&door->thinker); // Unlink and free. #if __JHERETIC__ S_SectorSound(door->sector, SORG_CEILING, SFX_DOORCLOSE); #endif break; case DT_CLOSE30THENOPEN: door->state = DS_WAIT; door->topCountDown = 30 * TICSPERSEC; break; default: break; } } else if(res == crushed) { // DOOMII BUG: // The switch bellow SHOULD(?) play the blazing open sound if // the door type is blazing and not SFX_DOROPN. switch(door->type) { #if __JDOOM__ || __JDOOM64__ case DT_BLAZECLOSE: #endif case DT_CLOSE: // Do not go back up! break; default: door->state = DS_UP; #if !__JHEXEN__ S_SectorSound(door->sector, SORG_CEILING, SFX_DOOROPEN); #endif break; } } break; case DS_UP: res = T_MovePlane(door->sector, door->speed, door->topHeight, false, 1, 1); if(res == pastdest) { #if __JHEXEN__ SN_StopSequence(P_SectorSoundOrigin(door->sector)); #endif switch(door->type) { #if __JDOOM64__ case DT_INSTANTRAISE: //jd64 door->state = DS_WAIT; /* * skip topwait and began the countdown * that way there won't be a big delay when the * animation starts -kaiser */ door->topCountDown = 160; break; #endif #if __JDOOM__ || __JDOOM64__ case DT_BLAZERAISE: #endif #if __JHERETIC__ case DT_BLAZEOPEN: #endif case DT_NORMAL: door->state = DS_WAIT; // Wait at top. door->topCountDown = door->topWait; break; #if __JDOOM__ || __JDOOM64__ case DT_BLAZEOPEN: #endif case DT_CLOSE30THENOPEN: case DT_OPEN: xsec->specialData = NULL; #if __JHEXEN__ P_TagFinished(P_ToXSector(door->sector)->tag); #endif DD_ThinkerRemove(&door->thinker); // Unlink and free. #if __JHERETIC__ S_StopSound(0, (mobj_t *) P_GetPtrp(door->sector, DMU_CEILING_SOUND_ORIGIN)); #endif break; default: break; } } break; default: break; } } static int EV_DoDoor2(int tag, float speed, int topwait, doortype_e type) { int rtn = 0, sound; xsector_t *xsec; sector_t *sec = NULL; door_t *door; iterlist_t *list; list = P_GetSectorIterListForTag(tag, false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { xsec = P_ToXSector(sec); if(xsec->specialData) continue; // new door thinker rtn = 1; door = Z_Calloc(sizeof(*door), PU_MAP, 0); door->thinker.function = T_Door; DD_ThinkerAdd(&door->thinker); xsec->specialData = door; door->sector = sec; door->type = type; door->topWait = topwait; door->speed = speed; #if __JHEXEN__ sound = SEQ_DOOR_STONE + P_ToXSector(door->sector)->seqType; #else sound = 0; #endif switch(type) { #if __JDOOM__ || __JDOOM64__ case DT_BLAZECLOSE: P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &door->topHeight); door->topHeight -= 4; door->state = DS_DOWN; door->speed *= 4; sound = SFX_DOORBLAZECLOSE; break; #endif case DT_CLOSE: P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &door->topHeight); door->topHeight -= 4; door->state = DS_DOWN; #if !__JHEXEN__ sound = SFX_DOORCLOSE; #endif break; case DT_CLOSE30THENOPEN: door->topHeight = P_GetFloatp(sec, DMU_CEILING_HEIGHT); door->state = DS_DOWN; #if !__JHEXEN__ sound = SFX_DOORCLOSE; #endif break; #if __JDOOM__ || __JDOOM64__ case DT_BLAZERAISE: #endif #if !__JHEXEN__ case DT_BLAZEOPEN: door->state = DS_UP; P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &door->topHeight); door->topHeight -= 4; # if __JHERETIC__ door->speed *= 3; # else door->speed *= 4; # endif if(door->topHeight != P_GetFloatp(sec, DMU_CEILING_HEIGHT)) sound = SFX_DOORBLAZEOPEN; break; #endif case DT_NORMAL: case DT_OPEN: door->state = DS_UP; P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &door->topHeight); door->topHeight -= 4; #if !__JHEXEN__ if(door->topHeight != P_GetFloatp(sec, DMU_CEILING_HEIGHT)) sound = SFX_DOOROPEN; #endif break; default: break; } // Play a sound? #if __JHEXEN__ SN_StartSequence(P_SectorSoundOrigin(door->sector), sound); #else if(sound) S_SectorSound(door->sector, SORG_CEILING, sound); #endif } return rtn; } #if __JHEXEN__ int EV_DoDoor(linedef_t *line, byte *args, doortype_e type) { return EV_DoDoor2((int) args[0], (float) args[1] * (1.0 / 8), (int) args[2], type); } #else int EV_DoDoor(linedef_t *line, doortype_e type) { return EV_DoDoor2(P_ToXLine(line)->tag, DOORSPEED, DOORWAIT, type); } #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ static void sendNeedKeyMessage(player_t* p, textenum_t msgTxt, int keyNum) { char buf[160], *in, tmp[2]; buf[0] = 0; tmp[1] = 0; // Get the message template. in = GET_TXT(msgTxt); for(; *in; in++) { if(in[0] == '%') { if(in[1] == '1') { strcat(buf, GET_TXT(TXT_KEY1 + keyNum)); in++; continue; } if(in[1] == '%') in++; } tmp[0] = *in; strcat(buf, tmp); } P_SetMessage(p, buf, false); } #endif #if __JDOOM__ || __JDOOM64__ /** * Checks whether the given linedef is a locked door. * If locked and the player IS ABLE to open it, return @c true. * If locked and the player IS NOT ABLE to open it, send an appropriate * message and play a sound before returning @c false. * Else, NOT a locked door and can be opened, return @c true. */ static boolean tryLockedDoor(linedef_t *line, player_t *p) { xline_t *xline = P_ToXLine(line); if(!p || !xline) return false; switch(xline->special) { case 99: // Blue Lock case 133: if(!p->keys[KT_BLUECARD] && !p->keys[KT_BLUESKULL]) { sendNeedKeyMessage(p, TXT_PD_BLUEO, 0); S_StartSound(SFX_DOORLOCKED, p->plr->mo); return false; } break; case 134: // Red Lock case 135: if(!p->keys[KT_REDCARD] && !p->keys[KT_REDSKULL]) { sendNeedKeyMessage(p, TXT_PD_REDO, 2); S_StartSound(SFX_DOORLOCKED, p->plr->mo); return false; } break; case 136: // Yellow Lock case 137: if(!p->keys[KT_YELLOWCARD] && !p->keys[KT_YELLOWSKULL]) { sendNeedKeyMessage(p, TXT_PD_YELLOWO, 1); S_StartSound(SFX_DOORLOCKED, p->plr->mo); return false; } break; # if __JDOOM64__ case 343: if(!P_InventoryCount(p - players, IIT_DEMONKEY1)) { P_SetMessage(p, PD_OPNPOWERUP, false); S_StartSound(SFX_DOORLOCKED, p->plr->mo); return false; } break; case 344: if(!P_InventoryCount(p - players, IIT_DEMONKEY2)) { P_SetMessage(p, PD_OPNPOWERUP, false); S_StartSound(SFX_DOORLOCKED, p->plr->mo); return false; } break; case 345: if(!P_InventoryCount(p - players, IIT_DEMONKEY3)) { P_SetMessage(p, PD_OPNPOWERUP, false); S_StartSound(SFX_DOORLOCKED, p->plr->mo); return false; } break; # endif default: break; } return true; } #endif /** * Checks whether the given linedef is a locked manual door. * If locked and the player IS ABLE to open it, return @c true. * If locked and the player IS NOT ABLE to open it, send an appropriate * message and play a sound before returning @c false. * Else, NOT a locked door and can be opened, return @c true. */ static boolean tryLockedManualDoor(linedef_t* line, mobj_t* mo) { xline_t* xline = P_ToXLine(line); player_t* p; #if !__JHEXEN__ int keyNum = -1; textenum_t msgTxt = 0; sfxenum_t sfxNum = 0; #endif if(!mo || !xline) return false; p = mo->player; #if !__JHEXEN__ switch(xline->special) { case 26: case 32: # if __JDOOM64__ case 525: // jd64 # endif if(!p) return false; // Blue Lock # if __JHERETIC__ if(!p->keys[KT_BLUE]) { msgTxt = TXT_TXT_NEEDBLUEKEY; keyNum = 2; sfxNum = SFX_DOORLOCKED; } # else if(!p->keys[KT_BLUECARD] && !p->keys[KT_BLUESKULL]) { msgTxt = TXT_PD_BLUEK; keyNum = 0; sfxNum = SFX_DOORLOCKED; } # endif break; case 27: case 34: # if __JDOOM64__ case 526: // jd64 # endif if(!p) return false; // Yellow Lock # if __JHERETIC__ if(!p->keys[KT_YELLOW]) { msgTxt = TXT_TXT_NEEDYELLOWKEY; keyNum = 0; sfxNum = SFX_DOORLOCKED; } # else if(!p->keys[KT_YELLOWCARD] && !p->keys[KT_YELLOWSKULL]) { msgTxt = TXT_PD_YELLOWK; keyNum = 1; sfxNum = SFX_DOORLOCKED; } # endif break; case 28: case 33: # if __JDOOM64__ case 527: // jd64 # endif if(!p) return false; # if __JHERETIC__ // Green lock if(!p->keys[KT_GREEN]) { msgTxt = TXT_TXT_NEEDGREENKEY; keyNum = 1; sfxNum = SFX_DOORLOCKED; } # else // Red lock if(!p->keys[KT_REDCARD] && !p->keys[KT_REDSKULL]) { msgTxt = TXT_PD_REDK; keyNum = 2; sfxNum = SFX_DOORLOCKED; } # endif break; default: break; } if(keyNum != -1) { // A key is required. sendNeedKeyMessage(p, msgTxt, keyNum); S_StartSound(sfxNum, p->plr->mo); return false; } #endif return true; } /** * Move a locked door up/down. */ #if __JDOOM__ || __JDOOM64__ int EV_DoLockedDoor(linedef_t *line, doortype_e type, mobj_t *thing) { if(!tryLockedDoor(line, thing->player)) return 0; return EV_DoDoor(line, type); } #endif /** * Open a door manually, no tag value. */ boolean EV_VerticalDoor(linedef_t* line, mobj_t* mo) { xline_t* xline; xsector_t* xsec; sector_t* sec; door_t* door; sec = P_GetPtrp(line, DMU_BACK_SECTOR); if(!sec) return false; if(!tryLockedManualDoor(line, mo)) return false; // Mobj cannot open this door. xsec = P_ToXSector(sec); xline = P_ToXLine(line); // If the sector has an active thinker, use it. if(xsec->specialData) { #if __JHEXEN__ return false; #else door = xsec->specialData; switch(xline->special) { case 1: case 26: case 27: case 28: # if __JDOOM__ || __JDOOM64__ case 117: # endif # if __JDOOM64__ case 525: // jd64 case 526: // jd64 case 527: // jd64 # endif // Only for "raise" doors, not "open"s. if(door->state == DS_DOWN) door->state = DS_UP; // Go back up. else { if(!mo->player) return false; // Bad guys never close doors. door->state = DS_DOWN; // Start going down immediately. } return false; default: break; } #endif } // New door thinker. door = Z_Calloc(sizeof(*door), PU_MAP, 0); door->thinker.function = T_Door; DD_ThinkerAdd(&door->thinker); xsec->specialData = door; door->sector = sec; door->state = DS_UP; // Play a sound? #if __JHEXEN__ SN_StartSequence(P_SectorSoundOrigin(door->sector), SEQ_DOOR_STONE + P_ToXSector(door->sector)->seqType); #else switch(xline->special) { # if __JDOOM__ || __JDOOM64__ case 117: case 118: # if __JDOOM64__ case 525: // jd64 case 526: // jd64 case 527: // jd64 # endif // BLAZING DOOR RAISE/OPEN S_SectorSound(door->sector, SORG_CEILING, SFX_DOORBLAZEOPEN); break; # endif case 1: case 31: // NORMAL DOOR SOUND S_SectorSound(door->sector, SORG_CEILING, SFX_DOOROPEN); break; default: // LOCKED DOOR SOUND S_SectorSound(door->sector, SORG_CEILING, SFX_DOOROPEN); break; } #endif switch(xline->special) { #if __JHEXEN__ case 11: door->type = DT_OPEN; door->speed = (float) xline->arg2 * (1.0 / 8); door->topWait = (int) xline->arg3; xline->special = 0; break; #else case 31: case 32: case 33: case 34: door->type = DT_OPEN; door->speed = DOORSPEED; door->topWait = DOORWAIT; xline->special = 0; break; #endif #if __JHEXEN__ case 12: case 13: door->type = DT_NORMAL; door->speed = (float) xline->arg2 * (1.0 / 8); door->topWait = (int) xline->arg3; break; #else case 1: case 26: case 27: case 28: door->type = DT_NORMAL; door->speed = DOORSPEED; door->topWait = DOORWAIT; break; #endif #if __JDOOM__ || __JDOOM64__ case 117: // blazing door raise # if __JDOOM64__ case 525: // jd64 case 526: // jd64 case 527: // jd64 # endif door->type = DT_BLAZERAISE; door->speed = DOORSPEED * 4; door->topWait = DOORWAIT; break; case 118: // blazing door open door->type = DT_BLAZEOPEN; door->speed = DOORSPEED * 4; door->topWait = DOORWAIT; xline->special = 0; break; #endif default: #if __JHEXEN__ door->type = DT_NORMAL; door->speed = (float) xline->arg2 * (1.0 / 8); door->topWait = (int) xline->arg3; #else door->speed = DOORSPEED; door->topWait = DOORWAIT; #endif break; } // find the top and bottom of the movement range P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &door->topHeight); door->topHeight -= 4; return true; } #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ void P_SpawnDoorCloseIn30(sector_t *sec) { door_t *door; door = Z_Calloc(sizeof(*door), PU_MAP, 0); door->thinker.function = T_Door; DD_ThinkerAdd(&door->thinker); P_ToXSector(sec)->specialData = door; P_ToXSector(sec)->special = 0; door->sector = sec; door->state = DS_WAIT; door->type = DT_NORMAL; door->speed = DOORSPEED; door->topCountDown = 30 * TICSPERSEC; } void P_SpawnDoorRaiseIn5Mins(sector_t *sec) { door_t *door; door = Z_Calloc(sizeof(*door), PU_MAP, 0); door->thinker.function = T_Door; DD_ThinkerAdd(&door->thinker); P_ToXSector(sec)->specialData = door; P_ToXSector(sec)->special = 0; door->sector = sec; door->state = DS_INITIALWAIT; door->type = DT_RAISEIN5MINS; door->speed = DOORSPEED; P_FindSectorSurroundingLowestCeiling(sec, (float) MAXINT, &door->topHeight); door->topHeight -= 4; door->topWait = DOORWAIT; door->topCountDown = 5 * 60 * TICSPERSEC; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/r_common.c0000644000175000017500000001716711357170242022616 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_common.c : Common routines for refresh. */ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "am_map.h" #include "p_player.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // View window current position. static float windowX = 0, oldWindowX = 0; static float windowY = 0, oldWindowY = 0; static float windowWidth = SCREENWIDTH, oldWindowWidth = SCREENWIDTH; static float windowHeight = SCREENHEIGHT, oldWindowHeight = SCREENHEIGHT; static int targetX = -1, targetY = -1, targetWidth = -1, targetHeight = -1; static float windowPos = 0; static int gammaLevel; #ifndef __JHEXEN__ char gammamsg[5][81]; #endif // CODE -------------------------------------------------------------------- void R_PrecachePSprites(void) { int i, k; int pclass = players[CONSOLEPLAYER].class; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { for(k = 0; k < NUMWEAPLEVELS; ++k) { pclass = players[CONSOLEPLAYER].class; R_PrecacheSkinsForState(weaponInfo[i][pclass].mode[k].states[WSN_UP]); R_PrecacheSkinsForState(weaponInfo[i][pclass].mode[k].states[WSN_DOWN]); R_PrecacheSkinsForState(weaponInfo[i][pclass].mode[k].states[WSN_READY]); R_PrecacheSkinsForState(weaponInfo[i][pclass].mode[k].states[WSN_ATTACK]); R_PrecacheSkinsForState(weaponInfo[i][pclass].mode[k].states[WSN_FLASH]); #if __JHERETIC__ || __JHEXEN__ R_PrecacheSkinsForState(weaponInfo[i][pclass].mode[k].states[WSN_ATTACK_HOLD]); #endif } } } void R_SetViewWindowTarget(int x, int y, int w, int h) { if(targetX == -1) { // First call. windowX = oldWindowX = targetX = x; windowY = oldWindowY = targetY = y; windowWidth = oldWindowWidth = targetWidth = w; windowHeight = oldWindowHeight = targetHeight = h; return; } if(x == targetX && y == targetY && w == targetWidth && h == targetHeight) { return; } oldWindowX = windowX; oldWindowY = windowY; oldWindowWidth = windowWidth; oldWindowHeight = windowHeight; // Restart the timer. windowPos = 0; targetX = x; targetY = y; targetWidth = w; targetHeight = h; } /** * Animates the game view window towards the target values. */ void R_ViewWindowTicker(void) { if(targetX == -1) return; // Nothing to do. windowPos += .4f; if(windowPos >= 1) { windowX = targetX; windowY = targetY; windowWidth = targetWidth; windowHeight = targetHeight; } else { #define LERP(start, end, pos) (end * pos + start * (1 - pos)) windowX = LERP(oldWindowX, targetX, windowPos); windowY = LERP(oldWindowY, targetY, windowPos); windowWidth = LERP(oldWindowWidth, targetWidth, windowPos); windowHeight = LERP(oldWindowHeight, targetHeight, windowPos); #undef LERP } } void R_GetViewWindow(float* x, float* y, float* w, float* h) { if(x) *x = windowX; if(y) *y = windowY; if(w) *w = windowWidth; if(h) *h = windowHeight; } boolean R_IsFullScreenViewWindow(void) { return (windowWidth >= 320 && windowHeight >= 200 && windowX <= 0 && windowY <= 0); } /** * Does the given display player's automap obscure the window completely? * \note: Window dimensions are in fixed scale {x} 0 - 320, {y} 0 - 200. * * @param playerid Index of the player whose map to check. * @param x Top left X coordinate. * @param y Top left Y coordinate. * @param w Width. * @param h Height. * * @return @true if there is no point within the given window * which is even partially visible. */ boolean R_MapObscures(int playerid, int x, int y, int w, int h) { boolean retVal = false; automapid_t map = AM_MapForPlayer(DISPLAYPLAYER); if(AM_IsActive(map)) { float alpha; AM_GetColorAndAlpha(map, AMO_BACKGROUND, NULL, NULL, NULL, &alpha); if(!(alpha < 1) && !(AM_GlobalAlpha(map) < 1)) { if(AM_IsMapWindowInFullScreenMode(map)) { retVal = true; } else { // We'll have to compare the dimensions. float scrwidth = Get(DD_WINDOW_WIDTH); float scrheight = Get(DD_WINDOW_HEIGHT); float fx = FIXXTOSCREENX(x); float fy = FIXYTOSCREENY(x); float fw = FIXXTOSCREENX(w); float fh = FIXYTOSCREENY(h); float mx, my, mw, mh; AM_GetWindow(map, &mx, &my, &mw, &mh); if(mx >= fx && my >= fy && mw >= fw && mh >= fh) retVal = true; } } } return retVal; } void R_CachePatch(dpatch_t* dp, const char* name) { lumppatch_t* patch; if(IS_DEDICATED) return; dp->lump = W_CheckNumForName(name); if(dp->lump == -1) return; patch = (lumppatch_t *) W_CacheLumpNum(dp->lump, PU_CACHE); dp->width = SHORT(patch->width); dp->height = SHORT(patch->height); dp->leftOffset = SHORT(patch->leftOffset); dp->topOffset = SHORT(patch->topOffset); // Precache the patch while we're at it. R_PrecachePatch(dp->lump); } #ifndef __JHEXEN__ void R_GetGammaMessageStrings(void) { int i; // Init some strings. for(i = 0; i < 5; ++i) strcpy(gammamsg[i], GET_TXT(TXT_GAMMALVL0 + i)); } #endif void R_CycleGammaLevel(void) { char buf[50]; gammaLevel++; if(gammaLevel > 4) gammaLevel = 0; #if __JDOOM__ || __JDOOM64__ P_SetMessage(players + CONSOLEPLAYER, gammamsg[gammaLevel], true); #endif sprintf(buf, "rend-tex-gamma %f", ((float) gammaLevel / 8.0f) * 1.5f); DD_Execute(false, buf); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_svtexarc.c0000644000175000017500000001654311357170242023160 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_svtexarc.c: Archived texture names (save games). */ // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_svtexarc.h" #include "p_saveg.h" // MACROS ------------------------------------------------------------------ #define MAX_ARCHIVED_MATERIALS 1024 #define BADTEXNAME "DD_BADTX" // string that will be written in the texture // archives to denote a missing texture. // TYPES ------------------------------------------------------------------- typedef struct { char name[9]; material_namespace_t mnamespace; } materialentry_t; typedef struct { //// \todo Remove fixed limit. materialentry_t table[MAX_ARCHIVED_MATERIALS]; int count, version; } materialarchive_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- materialarchive_t matArchive; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int numFlats; // Used with older versions. // CODE -------------------------------------------------------------------- static void initMaterialNameLUT(void) { matArchive.count = 0; memset(matArchive.table, 0, sizeof(matArchive.table)); } /** * Called for every material in the map before saving by * Sv_InitTextureArchives. */ void SV_PrepareMaterial(material_t* mat, materialarchive_t* arc) { int c; char name[9]; const char* matName; material_namespace_t mnamespace; if(!mat) return; matName = P_GetMaterialName(mat); mnamespace = P_GetIntp(mat, DMU_NAMESPACE); // Get the name of the material. if(matName) strncpy(name, matName, 8); else strncpy(name, BADTEXNAME, 8); name[8] = 0; // Has this already been registered? for(c = 0; c < arc->count; c++) { if(arc->table[c].mnamespace == mnamespace && !stricmp(arc->table[c].name, name)) { break;// Yes, skip it... } } if(c == arc->count) { strcpy(arc->table[arc->count++].name, name); arc->table[arc->count - 1].mnamespace = mnamespace; } } /** * Initializes the material archives (translation tables). * Must be called before saving. The table is written before any world data * is saved. * * \fixme: Poor design. What about the case where we wish to save a * reference to a material which is not currently used on any world surface * (for example, thinkers that will change a material at some later time)? */ void SV_InitMaterialArchives(void) { uint i; matArchive.version = MATERIAL_ARCHIVE_VERSION; initMaterialNameLUT(); for(i = 0; i < numsectors; ++i) { SV_PrepareMaterial(P_GetPtr(DMU_SECTOR, i, DMU_FLOOR_MATERIAL), &matArchive); SV_PrepareMaterial(P_GetPtr(DMU_SECTOR, i, DMU_CEILING_MATERIAL), &matArchive); } for(i = 0; i < numsides; ++i) { SV_PrepareMaterial(P_GetPtr(DMU_SIDEDEF, i, DMU_MIDDLE_MATERIAL), &matArchive); SV_PrepareMaterial(P_GetPtr(DMU_SIDEDEF, i, DMU_TOP_MATERIAL), &matArchive); SV_PrepareMaterial(P_GetPtr(DMU_SIDEDEF, i, DMU_BOTTOM_MATERIAL), &matArchive); } } unsigned short SV_SearchArchive(materialarchive_t* arc, const char* name) { int i; for(i = 0; i < arc->count; ++i) { if(!stricmp(arc->table[i].name, name)) return i + 1; } // Not found?!!! return 0; } /** * @return The archive number of the given material. */ unsigned short SV_MaterialArchiveNum(material_t* mat) { char name[9]; if(!mat) return 0; if(P_GetMaterialName(mat)) strncpy(name, P_GetMaterialName(mat), 8); else strncpy(name, BADTEXNAME, 8); name[8] = 0; return SV_SearchArchive(&matArchive, name); } material_t* SV_GetArchiveMaterial(int archivenum, int group) { if(archivenum == 0) return NULL; archivenum--; if(matArchive.version < 1 && group == 1) { archivenum += numFlats; } if(!(archivenum < matArchive.count)) { #if _DEBUG Con_Error("SV_GetArchiveMaterial: Bad archivenum %i.", archivenum); #endif return NULL; } if(!strncmp(matArchive.table[archivenum].name, BADTEXNAME, 8)) return NULL; else return P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(matArchive.table[archivenum].name, matArchive.table[archivenum].mnamespace)); } void SV_WriteMaterialArchive(void) { int i; SV_WriteByte(matArchive.version); SV_WriteShort(matArchive.count); for(i = 0; i < matArchive.count; ++i) { SV_Write(matArchive.table[i].name, 8); SV_WriteByte(matArchive.table[i].mnamespace); } } static void readMatArchive(materialarchive_t* arc, material_namespace_t defaultGroup) { int i, num; num = SV_ReadShort(); for(i = arc->count; i < arc->count + num; ++i) { SV_Read(arc->table[i].name, 8); arc->table[i].name[8] = 0; if(arc->version >= 1) arc->table[i].mnamespace = SV_ReadByte(); else arc->table[i].mnamespace = defaultGroup; } arc->count += num; } /** * @param version Override support for/of a particular version. */ void SV_ReadMaterialArchive(int version) { if(version >= 0) { matArchive.version = version; if(version != 0) SV_ReadByte(); } else { matArchive.version = SV_ReadByte(); } initMaterialNameLUT(); readMatArchive(&matArchive, MN_FLATS); if(matArchive.version == 0) { // The old format saved textures and flats in seperate blocks. numFlats = matArchive.count; readMatArchive(&matArchive, MN_FLATS); } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/g_game.c0000644000175000017500000021101211357170242022205 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 1999-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_game.c: Top-level (common) game routines. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if __JDOOM__ # include # include "jdoom.h" #elif __JDOOM64__ # include # include "jdoom64.h" #elif __JHERETIC__ # include # include "jheretic.h" # include "p_inventory.h" #elif __JHEXEN__ # include "jhexen.h" # include "p_inventory.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "p_saveg.h" #include "g_controls.h" #include "g_eventsequence.h" #include "p_mapsetup.h" #include "p_user.h" #include "p_actor.h" #include "p_tick.h" #include "am_map.h" #include "hu_stuff.h" #include "hu_menu.h" #include "hu_log.h" #include "hu_msg.h" #include "hu_pspr.h" #include "g_common.h" #include "g_update.h" #include "d_net.h" #include "x_hair.h" #include "p_player.h" #include "r_common.h" #include "p_mapspec.h" #include "f_infine.h" #include "p_start.h" #include "p_inventory.h" #if __JHERETIC__ || __JHEXEN__ # include "hu_inventory.h" #endif // MACROS ------------------------------------------------------------------ #define BODYQUEUESIZE (32) #define UNNAMEDMAP "Unnamed" #define NOTAMAPNAME "N/A" #define READONLYCVAR CVF_READ_ONLY|CVF_NO_MAX|CVF_NO_MIN|CVF_NO_ARCHIVE // TYPES ------------------------------------------------------------------- #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ struct missileinfo_s { mobjtype_t type; float speed[2]; } MonsterMissileInfo[] = { #if __JDOOM__ || __JDOOM64__ {MT_BRUISERSHOT, {15, 20}}, {MT_HEADSHOT, {10, 20}}, {MT_TROOPSHOT, {10, 20}}, # if __JDOOM64__ {MT_BRUISERSHOTRED, {15, 20}}, {MT_NTROSHOT, {20, 40}}, # endif #elif __JHERETIC__ {MT_IMPBALL, {10, 20}}, {MT_MUMMYFX1, {9, 18}}, {MT_KNIGHTAXE, {9, 18}}, {MT_REDAXE, {9, 18}}, {MT_BEASTBALL, {12, 20}}, {MT_WIZFX1, {18, 24}}, {MT_SNAKEPRO_A, {14, 20}}, {MT_SNAKEPRO_B, {14, 20}}, {MT_HEADFX1, {13, 20}}, {MT_HEADFX3, {10, 18}}, {MT_MNTRFX1, {20, 26}}, {MT_MNTRFX2, {14, 20}}, {MT_SRCRFX1, {20, 28}}, {MT_SOR2FX1, {20, 28}}, #endif {-1, {-1, -1}} // Terminator }; #endif // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdListMaps); void G_PlayerReborn(int player); void G_InitNew(skillmode_t skill, uint episode, uint map); void G_DoInitNew(void); void G_DoReborn(int playernum); void G_DoLoadMap(void); void G_DoNewGame(void); void G_DoLoadGame(void); void G_DoPlayDemo(void); void G_DoMapCompleted(void); void G_DoVictory(void); void G_DoWorldDone(void); void G_DoSaveGame(void); void G_DoScreenShot(void); boolean G_ValidateMap(uint *episode, uint *map); #if __JHEXEN__ || __JSTRIFE__ void G_DoSingleReborn(void); void H2_PageTicker(void); void H2_AdvanceDemo(void); #endif void G_StopDemo(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- game_config_t cfg; // The global cfg. int debugSound; // Debug flag for displaying sound info. skillmode_t dSkill; skillmode_t gameSkill; uint gameEpisode; uint gameMap; uint nextMap; #if __JHEXEN__ || __JSTRIFE__ uint nextMapEntryPoint; #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ boolean secretExit; #endif #if __JHEXEN__ || __JSTRIFE__ // Position indicator for cooperative net-play reborn uint rebornPosition; #endif #if __JHEXEN__ || __JSTRIFE__ uint mapHub = 0; #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ || __JSTRIFE__ boolean respawnMonsters; #endif boolean paused; boolean sendPause; // Send a pause event next tic. boolean userGame = false; // Ok to save / end game. boolean deathmatch; // Only if started as net death. player_t players[MAXPLAYERS]; int mapStartTic; // Game tic at map start. int totalKills, totalItems, totalSecret; // For intermission. boolean singledemo; // Quit after playing a demo from cmdline. boolean precache = true; // If @c true, load all graphics at start. #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ wbstartstruct_t wmInfo; // Params for world map / intermission. #endif int saveGameSlot; char saveDescription[HU_SAVESTRINGSIZE]; #if __JDOOM__ || __JDOOM64__ mobj_t *bodyQueue[BODYQUEUESIZE]; int bodyQueueSlot; #endif filename_t saveName; // vars used with game status cvars int gsvInMap = 0; int gsvCurrentMusic = 0; int gsvMapMusic = -1; int gsvArmor = 0; int gsvHealth = 0; #if !__JHEXEN__ int gsvKills = 0; int gsvItems = 0; int gsvSecrets = 0; #endif int gsvCurrentWeapon; int gsvWeapons[NUM_WEAPON_TYPES]; int gsvKeys[NUM_KEY_TYPES]; int gsvAmmo[NUM_AMMO_TYPES]; char *gsvMapName = NOTAMAPNAME; #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ int gsvInvItems[NUM_INVENTORYITEM_TYPES]; #endif #if __JHEXEN__ int gsvWPieces[4]; #endif static gamestate_t gameState = GS_STARTUP; cvar_t gamestatusCVars[] = { {"game-state", READONLYCVAR, CVT_INT, &gameState, 0, 0}, {"game-state-map", READONLYCVAR, CVT_INT, &gsvInMap, 0, 0}, {"game-paused", READONLYCVAR, CVT_INT, &paused, 0, 0}, {"game-skill", READONLYCVAR, CVT_INT, &gameSkill, 0, 0}, {"map-id", READONLYCVAR, CVT_INT, &gameMap, 0, 0}, {"map-name", READONLYCVAR, CVT_CHARPTR, &gsvMapName, 0, 0}, {"map-episode", READONLYCVAR, CVT_INT, &gameEpisode, 0, 0}, #if __JDOOM__ {"map-mission", READONLYCVAR, CVT_INT, &gameMission, 0, 0}, #endif #if __JHEXEN__ || __JSTRIFE__ {"map-hub", READONLYCVAR, CVT_INT, &mapHub, 0, 0}, #endif {"game-music", READONLYCVAR, CVT_INT, &gsvCurrentMusic, 0, 0}, {"map-music", READONLYCVAR, CVT_INT, &gsvMapMusic, 0, 0}, #if !__JHEXEN__ {"game-stats-kills", READONLYCVAR, CVT_INT, &gsvKills, 0, 0}, {"game-stats-items", READONLYCVAR, CVT_INT, &gsvItems, 0, 0}, {"game-stats-secrets", READONLYCVAR, CVT_INT, &gsvSecrets, 0, 0}, #endif {"player-health", READONLYCVAR, CVT_INT, &gsvHealth, 0, 0}, {"player-armor", READONLYCVAR, CVT_INT, &gsvArmor, 0, 0}, {"player-weapon-current", READONLYCVAR, CVT_INT, &gsvCurrentWeapon, 0, 0}, #if __JDOOM__ || __JDOOM64__ // Ammo {"player-ammo-bullets", READONLYCVAR, CVT_INT, &gsvAmmo[AT_CLIP], 0, 0}, {"player-ammo-shells", READONLYCVAR, CVT_INT, &gsvAmmo[AT_SHELL], 0, 0}, {"player-ammo-cells", READONLYCVAR, CVT_INT, &gsvAmmo[AT_CELL], 0, 0}, {"player-ammo-missiles", READONLYCVAR, CVT_INT, &gsvAmmo[AT_MISSILE], 0, 0}, // Weapons {"player-weapon-fist", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FIRST], 0, 0}, {"player-weapon-pistol", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SECOND], 0, 0}, {"player-weapon-shotgun", READONLYCVAR, CVT_INT, &gsvWeapons[WT_THIRD], 0, 0}, {"player-weapon-chaingun", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FOURTH], 0, 0}, {"player-weapon-mlauncher", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FIFTH], 0, 0}, {"player-weapon-plasmarifle", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SIXTH], 0, 0}, {"player-weapon-bfg", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SEVENTH], 0, 0}, {"player-weapon-chainsaw", READONLYCVAR, CVT_INT, &gsvWeapons[WT_EIGHTH], 0, 0}, {"player-weapon-sshotgun", READONLYCVAR, CVT_INT, &gsvWeapons[WT_NINETH], 0, 0}, // Keys {"player-key-blue", READONLYCVAR, CVT_INT, &gsvKeys[KT_BLUECARD], 0, 0}, {"player-key-yellow", READONLYCVAR, CVT_INT, &gsvKeys[KT_YELLOWCARD], 0, 0}, {"player-key-red", READONLYCVAR, CVT_INT, &gsvKeys[KT_REDCARD], 0, 0}, {"player-key-blueskull", READONLYCVAR, CVT_INT, &gsvKeys[KT_BLUESKULL], 0, 0}, {"player-key-yellowskull", READONLYCVAR, CVT_INT, &gsvKeys[KT_YELLOWSKULL], 0, 0}, {"player-key-redskull", READONLYCVAR, CVT_INT, &gsvKeys[KT_REDSKULL], 0, 0}, #elif __JHERETIC__ // Ammo {"player-ammo-goldwand", READONLYCVAR, CVT_INT, &gsvAmmo[AT_CRYSTAL], 0, 0}, {"player-ammo-crossbow", READONLYCVAR, CVT_INT, &gsvAmmo[AT_ARROW], 0, 0}, {"player-ammo-dragonclaw", READONLYCVAR, CVT_INT, &gsvAmmo[AT_ORB], 0, 0}, {"player-ammo-hellstaff", READONLYCVAR, CVT_INT, &gsvAmmo[AT_RUNE], 0, 0}, {"player-ammo-phoenixrod", READONLYCVAR, CVT_INT, &gsvAmmo[AT_FIREORB], 0, 0}, {"player-ammo-mace", READONLYCVAR, CVT_INT, &gsvAmmo[AT_MSPHERE], 0, 0}, // Weapons {"player-weapon-staff", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FIRST], 0, 0}, {"player-weapon-goldwand", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SECOND], 0, 0}, {"player-weapon-crossbow", READONLYCVAR, CVT_INT, &gsvWeapons[WT_THIRD], 0, 0}, {"player-weapon-dragonclaw", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FOURTH], 0, 0}, {"player-weapon-hellstaff", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FIFTH], 0, 0}, {"player-weapon-phoenixrod", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SIXTH], 0, 0}, {"player-weapon-mace", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SEVENTH], 0, 0}, {"player-weapon-gauntlets", READONLYCVAR, CVT_INT, &gsvWeapons[WT_EIGHTH], 0, 0}, // Keys {"player-key-yellow", READONLYCVAR, CVT_INT, &gsvKeys[KT_YELLOW], 0, 0}, {"player-key-green", READONLYCVAR, CVT_INT, &gsvKeys[KT_GREEN], 0, 0}, {"player-key-blue", READONLYCVAR, CVT_INT, &gsvKeys[KT_BLUE], 0, 0}, // Inventory items {"player-artifact-ring", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_INVULNERABILITY], 0, 0}, {"player-artifact-shadowsphere", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_INVISIBILITY], 0, 0}, {"player-artifact-crystalvial", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_HEALTH], 0, 0}, {"player-artifact-mysticurn", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_SUPERHEALTH], 0, 0}, {"player-artifact-tomeofpower", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_TOMBOFPOWER], 0, 0}, {"player-artifact-torch", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_TORCH], 0, 0}, {"player-artifact-firebomb", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_FIREBOMB], 0, 0}, {"player-artifact-egg", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_EGG], 0, 0}, {"player-artifact-wings", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_FLY], 0, 0}, {"player-artifact-chaosdevice", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_TELEPORT], 0, 0}, #elif __JHEXEN__ // Mana {"player-mana-blue", READONLYCVAR, CVT_INT, &gsvAmmo[AT_BLUEMANA], 0, 0}, {"player-mana-green", READONLYCVAR, CVT_INT, &gsvAmmo[AT_GREENMANA], 0, 0}, // Keys {"player-key-steel", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY1], 0, 0}, {"player-key-cave", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY2], 0, 0}, {"player-key-axe", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY3], 0, 0}, {"player-key-fire", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY4], 0, 0}, {"player-key-emerald", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY5], 0, 0}, {"player-key-dungeon", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY6], 0, 0}, {"player-key-silver", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY7], 0, 0}, {"player-key-rusted", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY8], 0, 0}, {"player-key-horn", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEY9], 0, 0}, {"player-key-swamp", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEYA], 0, 0}, {"player-key-castle", READONLYCVAR, CVT_INT, &gsvKeys[KT_KEYB], 0, 0}, // Weapons {"player-weapon-first", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FIRST], 0, 0}, {"player-weapon-second", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SECOND], 0, 0}, {"player-weapon-third", READONLYCVAR, CVT_INT, &gsvWeapons[WT_THIRD], 0, 0}, {"player-weapon-fourth", READONLYCVAR, CVT_INT, &gsvWeapons[WT_FOURTH], 0, 0}, // Weapon Pieces {"player-weapon-piece1", READONLYCVAR, CVT_INT, &gsvWPieces[0], 0, 0}, {"player-weapon-piece2", READONLYCVAR, CVT_INT, &gsvWPieces[1], 0, 0}, {"player-weapon-piece3", READONLYCVAR, CVT_INT, &gsvWPieces[2], 0, 0}, {"player-weapon-allpieces", READONLYCVAR, CVT_INT, &gsvWPieces[3], 0, 0}, // Inventory items {"player-artifact-defender", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_INVULNERABILITY], 0, 0}, {"player-artifact-quartzflask", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_HEALTH], 0, 0}, {"player-artifact-mysticurn", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_SUPERHEALTH], 0, 0}, {"player-artifact-mysticambit", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_HEALINGRADIUS], 0, 0}, {"player-artifact-darkservant", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_SUMMON], 0, 0}, {"player-artifact-torch", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_TORCH], 0, 0}, {"player-artifact-porkalator", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_EGG], 0, 0}, {"player-artifact-wings", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_FLY], 0, 0}, {"player-artifact-repulsion", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_BLASTRADIUS], 0, 0}, {"player-artifact-flechette", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_POISONBAG], 0, 0}, {"player-artifact-banishment", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_TELEPORTOTHER], 0, 0}, {"player-artifact-speed", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_SPEED], 0, 0}, {"player-artifact-might", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_BOOSTMANA], 0, 0}, {"player-artifact-bracers", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_BOOSTARMOR], 0, 0}, {"player-artifact-chaosdevice", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_TELEPORT], 0, 0}, {"player-artifact-skull", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZSKULL], 0, 0}, {"player-artifact-heart", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEMBIG], 0, 0}, {"player-artifact-ruby", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEMRED], 0, 0}, {"player-artifact-emerald1", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEMGREEN1], 0, 0}, {"player-artifact-emerald2", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEMGREEN2], 0, 0}, {"player-artifact-sapphire1", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEMBLUE1], 0, 0}, {"player-artifact-sapphire2", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEMBLUE2], 0, 0}, {"player-artifact-daemoncodex", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZBOOK1], 0, 0}, {"player-artifact-liberoscura", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZBOOK2], 0, 0}, {"player-artifact-flamemask", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZSKULL2], 0, 0}, {"player-artifact-glaiveseal", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZFWEAPON], 0, 0}, {"player-artifact-holyrelic", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZCWEAPON], 0, 0}, {"player-artifact-sigilmagus", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZMWEAPON], 0, 0}, {"player-artifact-gear1", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEAR1], 0, 0}, {"player-artifact-gear2", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEAR2], 0, 0}, {"player-artifact-gear3", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEAR3], 0, 0}, {"player-artifact-gear4", READONLYCVAR, CVT_INT, &gsvInvItems[IIT_PUZZGEAR4], 0, 0}, #endif {NULL} }; ccmd_t gameCmds[] = { { "listmaps", "", CCmdListMaps }, { NULL } }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static uint dEpisode; static uint dMap; #if __JHEXEN__ || __JSTRIFE__ static int gameLoadSlot; #endif static gameaction_t gameAction; // CODE -------------------------------------------------------------------- void G_Register(void) { int i; for(i = 0; gamestatusCVars[i].name; ++i) Con_AddVariable(gamestatusCVars + i); for(i = 0; gameCmds[i].name; ++i) Con_AddCommand(gameCmds + i); } void G_SetGameAction(gameaction_t action) { if(gameAction == GA_QUIT) return; if(gameAction != action) gameAction = action; } gameaction_t G_GetGameAction(void) { return gameAction; } /** * Common Pre Engine Initialization routine. * Game-specfic pre init actions should be placed in eg D_PreInit() (for jDoom) */ void G_CommonPreInit(void) { int i; filename_t file; // Make sure game.dll isn't newer than Doomsday... if(gi.version < DOOMSDAY_VERSION) Con_Error(GAME_NICENAME " requires at least Doomsday " DOOMSDAY_VERSION_TEXT "!\n"); #ifdef TIC_DEBUG rndDebugfile = fopen("rndtrace.txt", "wt"); #endif verbose = ArgExists("-verbose"); // Setup the players. for(i = 0; i < MAXPLAYERS; ++i) { players[i].plr = DD_GetPlayer(i); players[i].plr->extraData = (void *) &players[i]; } dd_snprintf(file, FILENAME_T_MAXLEN, CONFIGFILE); DD_SetConfigFile(file); dd_snprintf(file, FILENAME_T_MAXLEN, DEFSFILE); DD_SetDefsFile(file); R_SetDataPath( DATAPATH ); Con_SetString("map-name", NOTAMAPNAME, 1); G_RegisterBindClasses(); G_RegisterPlayerControls(); P_RegisterMapObjs(); // Add the cvars and ccmds to the console databases. G_ConsoleRegistration(); // Main command list. D_NetConsoleRegistration(); // For network. G_Register(); // Read-only game status cvars (for playsim). G_ControlRegister(); // For controls/input. AM_Register(); // For the automap. Hu_MenuRegister(); // For the menu. HU_Register(); // For the HUD displays. Hu_LogRegister(); // For the player message logs. Chat_Register(); Hu_MsgRegister(); // For the game messages. ST_Register(); // For the hud/statusbar. X_Register(); // For the crosshair. DD_AddStartupWAD( STARTUPPK3 ); G_DetectIWADs(); } #if __JHEXEN__ /** * \todo all this swapping colors around is rather silly, why not simply * reorder the translation tables at load time? */ void R_GetTranslation(int plrClass, int plrColor, int* tclass, int* tmap) { *tclass = 1; if(plrColor == 0) *tmap = 1; else if(plrColor == 1) *tmap = 0; else *tmap = plrColor; // Fighter's colors are a bit different. if(plrClass == PCLASS_FIGHTER && *tmap > 1) *tclass = 0; } void R_SetTranslation(mobj_t* mo) { if(!(mo->flags & MF_TRANSLATION)) { // No translation. mo->tmap = mo->tclass = 0; } else { int tclass, tmap; tmap = (mo->flags & MF_TRANSLATION) >> MF_TRANSSHIFT; if(mo->player) { tclass = 1; if(mo->player->class == PCLASS_FIGHTER) { // Fighter's colors are a bit different. if(tmap == 0) tmap = 2; else if(tmap == 2) tmap = 0; else tclass = 0; } mo->tclass = tclass; } else tclass = mo->special1; mo->tmap = tmap; mo->tclass = tclass; } } #endif void R_LoadColorPalettes(void) { #define PALLUMPNAME "PLAYPAL" #define PALENTRIES (256) #define PALID (0) lumpnum_t lump = W_GetNumForName(PALLUMPNAME); byte data[PALENTRIES*3]; W_ReadLumpSection(lump, data, 0 + PALID * (PALENTRIES * 3), PALENTRIES * 3); R_CreateColorPalette("R8G8B8", PALLUMPNAME, data, PALENTRIES); /** * Create the translation tables to map the green color ramp to gray, * brown, red. * * \note Assumes a given structure of the PLAYPAL. Could be read from a * lump instead? */ #if __JDOOM__ || __JDOOM64__ { byte *translationtables = (byte *) DD_GetVariable(DD_TRANSLATIONTABLES_ADDRESS); int i; // Translate just the 16 green colors. for(i = 0; i < 256; ++i) { if(i >= 0x70 && i <= 0x7f) { // Map green ramp to gray, brown, red. translationtables[i] = 0x60 + (i & 0xf); translationtables[i + 256] = 0x40 + (i & 0xf); translationtables[i + 512] = 0x20 + (i & 0xf); } else { // Keep all other colors as is. translationtables[i] = translationtables[i + 256] = translationtables[i + 512] = i; } } } #elif __JHERETIC__ { int i; byte* translationtables = (byte*) DD_GetVariable(DD_TRANSLATIONTABLES_ADDRESS); // Fill out the translation tables. for(i = 0; i < 256; ++i) { if(i >= 225 && i <= 240) { translationtables[i] = 114 + (i - 225); // yellow translationtables[i + 256] = 145 + (i - 225); // red translationtables[i + 512] = 190 + (i - 225); // blue } else { translationtables[i] = translationtables[i + 256] = translationtables[i + 512] = i; } } } #else // __JHEXEN__ { int i; byte* translationtables = (byte*) DD_GetVariable(DD_TRANSLATIONTABLES_ADDRESS); for(i = 0; i < 3 * 7; ++i) { char name[9]; lumpnum_t lump; dd_snprintf(name, 9, "TRANTBL%X", i); if((lump = W_CheckNumForName(name)) != -1) { W_ReadLumpSection(lump, &translationtables[i * 256], 0, 256); } } } #endif #undef PALID #undef PALENTRIES #undef PALLUMPNAME } void R_InitRefresh(void) { VERBOSE(Con_Message("R_InitRefresh: Loading data for referesh.\n")) R_LoadColorPalettes(); { float mul = 1.4f; DD_SetVariable(DD_PSPRITE_LIGHTLEVEL_MULTIPLIER, &mul); } } /** * Common Post Engine Initialization routine. * Game-specific post init actions should be placed in eg D_PostInit() * (for jDoom) and NOT here. */ void G_CommonPostInit(void) { VERBOSE(G_PrintMapList()); R_InitRefresh(); // Init the save system and create the game save directory SV_Init(); #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ XG_ReadTypes(); XG_Register(); // Register XG classnames. #endif R_SetViewSize(cfg.screenBlocks); R_SetBorderGfx(borderLumps); Con_Message("P_Init: Init Playloop state.\n"); P_Init(); Con_Message("Hu_LoadData: Setting up heads up display.\n"); Hu_LoadData(); #if __JHERETIC__ || __JHEXEN__ Hu_InventoryInit(); #endif Con_Message("ST_Init: Init status bar.\n"); ST_Init(); #if __JDOOM__ || __JHERETIC__ || __JHEXEN__ Cht_Init(); #endif Con_Message("Hu_MenuInit: Init miscellaneous info.\n"); Hu_MenuInit(); Hu_MsgInit(); // From this point on, the shortcuts are always active. DD_Execute(true, "activatebcontext shortcut"); Con_Message("AM_Init: Init automap.\n"); AM_Init(); // Create the various line lists (spechits, anims, buttons etc). spechit = P_CreateIterList(); linespecials = P_CreateIterList(); } /** * Retrieve the current game state. * * @return The current game state. */ gamestate_t G_GetGameState(void) { return gameState; } #if _DEBUG static const char* getGameStateStr(gamestate_t state) { struct statename_s { gamestate_t state; const char* name; } stateNames[] = { {GS_MAP, "GS_MAP"}, {GS_INTERMISSION, "GS_INTERMISSION"}, {GS_FINALE, "GS_FINALE"}, {GS_STARTUP, "GS_STARTUP"}, {GS_WAITING, "GS_WAITING"}, {GS_INFINE, "GS_INFINE"}, {-1, NULL} }; uint i; for(i = 0; stateNames[i].name; ++i) if(stateNames[i].state == state) return stateNames[i].name; return NULL; } #endif /** * Called when the gameui binding context is active. Triggers the menu. */ int G_UIResponder(event_t* ev) { // Handle "Press any key to continue" messages. if(Hu_MsgResponder(ev)) return true; if(!Hu_MenuIsActive()) { // Any key/button down pops up menu if in demos. if(G_GetGameAction() == GA_NONE && !singledemo && (Get(DD_PLAYBACK) || FI_IsMenuTrigger(ev))) { if(ev->state == EVS_DOWN && (ev->type == EV_KEY || ev->type == EV_MOUSE_BUTTON || ev->type == EV_JOY_BUTTON)) { Hu_MenuCommand(MCMD_OPEN); return true; } } } return false; } /** * Change the game's state. * * @param state The state to change to. */ void G_ChangeGameState(gamestate_t state) { boolean gameUIActive = false; boolean gameActive = true; if(G_GetGameAction() == GA_QUIT) return; if(state < 0 || state >= NUM_GAME_STATES) Con_Error("G_ChangeGameState: Invalid state %i.\n", (int) state); if(gameState != state) { #if _DEBUG // Log gamestate changes in debug builds, with verbose. VERBOSE(Con_Message("G_ChangeGameState: New state %s.\n", getGameStateStr(state))); #endif gameState = state; } // Update the state of the gameui binding context. switch(gameState) { case GS_FINALE: case GS_STARTUP: case GS_WAITING: case GS_INFINE: gameActive = false; case GS_INTERMISSION: gameUIActive = true; break; default: break; } if(gameUIActive) { DD_Execute(true, "activatebcontext gameui"); B_SetContextFallback("gameui", G_UIResponder); } DD_Executef(true, "%sactivatebcontext game", gameActive? "" : "de"); } /** * Begin the titlescreen animation sequence. */ void G_StartTitle(void) { char *name = "title"; void *script; G_StopDemo(); userGame = false; // The title script must always be defined. if(!Def_Get(DD_DEF_FINALE, name, &script)) { Con_Error("G_StartTitle: Script \"%s\" not defined.\n", name); } FI_Start(script, FIMODE_LOCAL); } void G_DoLoadMap(void) { int i; char* lname, *ptr; ddfinale_t fin; boolean hasBrief; #if __JHEXEN__ || __JSTRIFE__ static int firstFragReset = 1; #endif mapStartTic = (int) GAMETIC; // Fr time calculation. // If we're the server, let clients know the map will change. NetSv_SendGameState(GSF_CHANGE_MAP, DDSP_ALL_PLAYERS); for(i = 0; i < MAXPLAYERS; ++i) { player_t *plr = &players[i]; if(plr->plr->inGame && plr->playerState == PST_DEAD) plr->playerState = PST_REBORN; #if __JHEXEN__ || __JSTRIFE__ if(!IS_NETGAME || (IS_NETGAME != 0 && deathmatch != 0) || firstFragReset == 1) { memset(plr->frags, 0, sizeof(plr->frags)); firstFragReset = 0; } #else memset(plr->frags, 0, sizeof(plr->frags)); #endif } #if __JHEXEN__ || __JSTRIFE__ SN_StopAllSequences(); #endif // Set all player mobjs to NULL, clear control state toggles etc. for(i = 0; i < MAXPLAYERS; ++i) { players[i].plr->mo = NULL; G_ResetLookOffset(i); } // Determine whether there is a briefing to run before the map starts // (played after the map has been loaded). hasBrief = FI_Briefing(gameEpisode, gameMap, &fin); if(!hasBrief) { #if __JHEXEN__ /** * \kludge Due to the way music is managed with Hexen, unless we * explicitly stop the current playing track the engine will not * change tracks. This is due to the use of the runtime-updated * "currentmap" definition (the engine thinks music has not changed * because the current Music definition is the same). * * The only reason it worked previously was because the * waiting-for-map-load song was started prior to load. * * \todo Rethink the Music definition stuff with regard to Hexen. * Why not create definitions during startup by parsing MAPINFO? */ S_StopMusic(); //S_StartMusic("chess", true); // Waiting-for-map-load song #endif S_MapMusic(gameEpisode, gameMap); S_PauseMusic(true); } P_SetupMap(gameEpisode, gameMap, 0, gameSkill); Set(DD_DISPLAYPLAYER, CONSOLEPLAYER); // View the guy you are playing. G_SetGameAction(GA_NONE); nextMap = 0; Z_CheckHeap(); // Clear cmd building stuff. G_ResetMousePos(); sendPause = paused = false; G_ControlReset(-1); // Clear all controls for all local players. // Set the game status cvar for map name. lname = (char *) DD_GetVariable(DD_MAP_NAME); if(lname) { ptr = strchr(lname, ':'); // Skip the E#M# or Map #. if(ptr) { lname = ptr + 1; while(*lname && isspace(*lname)) lname++; } } #if __JHEXEN__ // In jHexen we can look in the MAPINFO for the map name if(!lname) lname = P_GetMapName(gameMap); #endif // Set the map name // If still no name, call it unnamed. if(!lname) { Con_SetString("map-name", UNNAMEDMAP, 1); } else { Con_SetString("map-name", lname, 1); } // Start a briefing, if there is one. if(hasBrief) { FI_Start(fin.script, FIMODE_BEFORE); } else // No briefing, start the map. { G_ChangeGameState(GS_MAP); S_PauseMusic(false); } } /** * Get info needed to make ticcmd_ts for the players. * Return false if the event should be checked for bindings. */ boolean G_Responder(event_t *ev) { if(G_GetGameAction() == GA_QUIT) return false; // Eat all events once shutdown has begun. // With the menu active, none of these should respond to input events. if(!Hu_MenuIsActive() && !Hu_IsMessageActive()) { // Try Infine. if(FI_Responder(ev)) return true; // Try the chatmode responder. if(Chat_Responder(ev)) return true; #if __JDOOM__ || __JHERETIC__ || __JHEXEN__ // Check for cheats? if(G_GetGameState() == GS_MAP) { if(G_EventSequenceResponder(ev)) return true; } #endif } // Try the edit responder. if(M_EditResponder(ev)) return true; // We may wish to eat the event depending on type... if(G_AdjustControlState(ev)) return true; // The event wasn't used. return false; } /** * Updates the game status cvars based on game and player data. * Called each tick by G_Ticker(). */ void G_UpdateGSVarsForPlayer(player_t* pl) { int i, plrnum; gamestate_t gameState; if(!pl) return; plrnum = pl - players; gameState = G_GetGameState(); gsvHealth = pl->health; #if !__JHEXEN__ // Map stats gsvKills = pl->killCount; gsvItems = pl->itemCount; gsvSecrets = pl->secretCount; #endif // armor #if __JHEXEN__ gsvArmor = FixedDiv(PCLASS_INFO(pl->class)->autoArmorSave + pl->armorPoints[ARMOR_ARMOR] + pl->armorPoints[ARMOR_SHIELD] + pl->armorPoints[ARMOR_HELMET] + pl->armorPoints[ARMOR_AMULET], 5 * FRACUNIT) >> FRACBITS; #else gsvArmor = pl->armorPoints; #endif // Owned keys for(i = 0; i < NUM_KEY_TYPES; ++i) #if __JHEXEN__ gsvKeys[i] = (pl->keys & (1 << i))? 1 : 0; #else gsvKeys[i] = pl->keys[i]; #endif // current weapon gsvCurrentWeapon = pl->readyWeapon; // owned weapons for(i = 0; i < NUM_WEAPON_TYPES; ++i) gsvWeapons[i] = pl->weapons[i].owned; #if __JHEXEN__ // weapon pieces gsvWPieces[0] = (pl->pieces & WPIECE1)? 1 : 0; gsvWPieces[1] = (pl->pieces & WPIECE2)? 1 : 0; gsvWPieces[2] = (pl->pieces & WPIECE3)? 1 : 0; gsvWPieces[3] = (pl->pieces == 7)? 1 : 0; #endif // Current ammo amounts. for(i = 0; i < NUM_AMMO_TYPES; ++i) gsvAmmo[i] = pl->ammo[i].owned; #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ // Inventory items. for(i = 0; i < NUM_INVENTORYITEM_TYPES; ++i) { if(pl->plr->inGame && gameState == GS_MAP) gsvInvItems[i] = P_InventoryCount(plrnum, IIT_FIRST + i); else gsvInvItems[i] = 0; } #endif } static void runGameAction(void) { if(G_GetGameAction() == GA_QUIT) { #define QUITWAIT_MILLISECONDS 1500 static uint quitTime = 0; if(quitTime == 0) { quitTime = Sys_GetRealTime(); Hu_MenuCommand(MCMD_CLOSEFAST); if(!IS_NETGAME) { #if __JDOOM__ || __JDOOM64__ // Play an exit sound if it is enabled. if(cfg.menuQuitSound) { static int quitsounds[8] = { SFX_PLDETH, SFX_DMPAIN, SFX_POPAIN, SFX_SLOP, SFX_TELEPT, SFX_POSIT1, SFX_POSIT3, SFX_SGTATK }; static int quitsounds2[8] = { SFX_VILACT, SFX_GETPOW, # if __JDOOM64__ SFX_PEPAIN, # else SFX_BOSCUB, # endif SFX_SLOP, SFX_SKESWG, SFX_KNTDTH, SFX_BSPACT, SFX_SGTATK }; if(gameMode == commercial) S_LocalSound(quitsounds2[P_Random() & 7], NULL); else S_LocalSound(quitsounds[P_Random() & 7], NULL); } #endif DD_Executef(true, "activatebcontext deui"); } } if(Sys_GetRealTime() > quitTime + QUITWAIT_MILLISECONDS) { Sys_Quit(); } else { float t = (Sys_GetRealTime() - quitTime) / (float) QUITWAIT_MILLISECONDS; quitDarkenOpacity = t*t*t; } // No game state changes occur once we have begun to quit. return; #undef QUITWAIT_MILLISECONDS } // Do things to change the game state. {gameaction_t currentAction; while((currentAction = G_GetGameAction()) != GA_NONE) { switch(currentAction) { #if __JHEXEN__ || __JSTRIFE__ case GA_INITNEW: G_DoInitNew(); break; case GA_SINGLEREBORN: G_DoSingleReborn(); break; #endif case GA_LEAVEMAP: G_DoWorldDone(); break; case GA_LOADMAP: G_DoLoadMap(); break; case GA_NEWGAME: G_DoNewGame(); break; case GA_LOADGAME: G_DoLoadGame(); break; case GA_SAVEGAME: G_DoSaveGame(); break; case GA_MAPCOMPLETED: G_DoMapCompleted(); break; case GA_VICTORY: G_SetGameAction(GA_NONE); break; case GA_SCREENSHOT: G_DoScreenShot(); G_SetGameAction(GA_NONE); break; case GA_NONE: default: break; } }} } /** * The core of the timing loop. Game state, game actions etc occur here. * * @param ticLength How long this tick is, in seconds. */ void G_Ticker(timespan_t ticLength) { static gamestate_t oldGameState = -1; static trigger_t fixed = {1.0 / TICSPERSEC}; int i; // Always tic: Hu_FogEffectTicker(ticLength); Hu_MenuTicker(ticLength); Hu_MsgTicker(ticLength); if(IS_CLIENT && !Get(DD_GAME_READY)) return; // Do player reborns if needed. for(i = 0; i < MAXPLAYERS; ++i) { player_t *plr = &players[i]; if(plr->plr->inGame && plr->playerState == PST_REBORN && !P_MobjIsCamera(plr->plr->mo)) G_DoReborn(i); // Player has left? if(plr->playerState == PST_GONE) { plr->playerState = PST_REBORN; if(plr->plr->mo) { if(!IS_CLIENT) { P_SpawnTeleFog(plr->plr->mo->pos[VX], plr->plr->mo->pos[VY], plr->plr->mo->angle + ANG180); } // Let's get rid of the mobj. #ifdef _DEBUG Con_Message("G_Ticker: Removing player %i's mobj.\n", i); #endif P_MobjRemove(plr->plr->mo, true); plr->plr->mo = NULL; } } } runGameAction(); if(G_GetGameAction() != GA_QUIT) { // Update the viewer's look angle //G_LookAround(CONSOLEPLAYER); if(!IS_CLIENT) { // Enable/disable sending of frames (delta sets) to clients. Set(DD_ALLOW_FRAMES, G_GetGameState() == GS_MAP); // Tell Doomsday when the game is paused (clients can't pause // the game.) Set(DD_CLIENT_PAUSED, P_IsPaused()); } // Must be called on every tick. P_RunPlayers(ticLength); } else { if(!IS_CLIENT) { // Disable sending of frames (delta sets) to clients. Set(DD_ALLOW_FRAMES, false); } } // The following is restricted to fixed 35 Hz ticks. if(M_RunTrigger(&fixed, ticLength)) { // Do main actions. switch(G_GetGameState()) { case GS_MAP: // Update in-map game status cvar. if(oldGameState != GS_MAP) gsvInMap = 1; P_DoTick(); HU_UpdatePsprites(); // Active briefings once again (they were disabled when loading // a saved game). briefDisabled = false; if(IS_DEDICATED) break; ST_Ticker(); AM_Ticker(); Hu_Ticker(); break; case GS_INTERMISSION: #if __JDOOM__ || __JDOOM64__ WI_Ticker(); #else IN_Ticker(); #endif break; default: if(oldGameState != G_GetGameState()) { // Update game status cvars. gsvInMap = 0; Con_SetString("map-name", NOTAMAPNAME, 1); gsvMapMusic = -1; } break; } // Update the game status cvars for player data. G_UpdateGSVarsForPlayer(&players[CONSOLEPLAYER]); // Update view window size. R_ViewWindowTicker(); // InFine ticks whenever it's active. FI_Ticker(); // Servers will have to update player information and do such stuff. if(!IS_CLIENT) NetSv_Ticker(); } oldGameState = gameState; } /** * Called when a player leaves a map. * * Jobs include; striping keys, inventory and powers from the player * and configuring other player-specific properties ready for the next * map. * * @param player Id of the player to configure. */ void G_PlayerLeaveMap(int player) { #if __JHERETIC__ || __JHEXEN__ uint i; int flightPower; #endif player_t* p = &players[player]; boolean newCluster; #if __JHEXEN__ || __JSTRIFE__ newCluster = (P_GetMapCluster(gameMap) != P_GetMapCluster(nextMap)); #else newCluster = true; #endif #if __JHERETIC__ || __JHEXEN__ // Remember if flying. flightPower = p->powers[PT_FLIGHT]; #endif #if __JHERETIC__ // Empty the inventory of excess items for(i = 0; i < NUM_INVENTORYITEM_TYPES; ++i) { inventoryitemtype_t type = IIT_FIRST + i; uint count = P_InventoryCount(player, type); if(count) { uint j; if(type != IIT_FLY) count--; for(j = 0; j < count; ++j) P_InventoryTake(player, type, true); } } #endif #if __JHEXEN__ if(newCluster) { uint count = P_InventoryCount(player, IIT_FLY); for(i = 0; i < count; ++i) P_InventoryTake(player, IIT_FLY, true); } #endif // Remove their powers. p->update |= PSF_POWERS; memset(p->powers, 0, sizeof(p->powers)); #if __JHEXEN__ if(!newCluster && !deathmatch) p->powers[PT_FLIGHT] = flightPower; // Restore flight. #endif // Remove their keys. #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ p->update |= PSF_KEYS; memset(p->keys, 0, sizeof(p->keys)); #else if(!deathmatch && newCluster) p->keys = 0; #endif // Misc #if __JHERETIC__ p->rain1 = NULL; p->rain2 = NULL; #endif // Un-morph? #if __JHERETIC__ || __JHEXEN__ p->update |= PSF_MORPH_TIME; if(p->morphTics) { p->readyWeapon = p->plr->mo->special1; // Restore weapon. p->morphTics = 0; } #endif p->plr->lookDir = 0; p->plr->mo->flags &= ~MF_SHADOW; // Cancel invisibility. p->plr->extraLight = 0; // Cancel gun flashes. p->plr->fixedColorMap = 0; // Cancel IR goggles. // Clear filter. p->plr->flags &= ~DDPF_VIEW_FILTER; p->plr->flags |= DDPF_FILTER; // Server: Send the change to the client. p->damageCount = 0; // No palette changes. p->bonusCount = 0; #if __JHEXEN__ p->poisonCount = 0; #endif Hu_LogEmpty(p - players); } /** * Safely clears the player data structures. */ void ClearPlayer(player_t *p) { ddplayer_t *ddplayer = p->plr; int playeringame = ddplayer->inGame; int flags = ddplayer->flags; int start = p->startSpot; fixcounters_t counter, acked; // Restore counters. counter = ddplayer->fixCounter; acked = ddplayer->fixAcked; memset(p, 0, sizeof(*p)); // Restore the pointer to ddplayer. p->plr = ddplayer; #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ P_InventoryEmpty(p - players); P_InventorySetReadyItem(p - players, IIT_NONE); #endif // Also clear ddplayer. memset(ddplayer, 0, sizeof(*ddplayer)); // Restore the pointer to this player. ddplayer->extraData = p; // Restore the playeringame data. ddplayer->inGame = playeringame; ddplayer->flags = flags & ~(DDPF_INTERYAW | DDPF_INTERPITCH); // Don't clear the start spot. p->startSpot = start; // Restore counters. ddplayer->fixCounter = counter; ddplayer->fixAcked = acked; ddplayer->fixCounter.angles++; ddplayer->fixCounter.pos++; ddplayer->fixCounter.mom++; /* ddplayer->fixAcked.angles = ddplayer->fixAcked.pos = ddplayer->fixAcked.mom = -1; #ifdef _DEBUG Con_Message("ClearPlayer: fixacked set to -1 (counts:%i, %i, %i)\n", ddplayer->fixCounter.angles, ddplayer->fixCounter.pos, ddplayer->fixCounter.mom); #endif*/ } /** * Called after a player dies (almost everything is cleared and then * re-initialized). */ void G_PlayerReborn(int player) { player_t *p; int frags[MAXPLAYERS]; int killcount, itemcount, secretcount; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ int i; #endif #if __JHERETIC__ boolean secret = false; int spot; #elif __JHEXEN__ || __JSTRIFE__ uint worldTimer; #endif if(player < 0 || player >= MAXPLAYERS) return; // Wha? p = &players[player]; memcpy(frags, p->frags, sizeof(frags)); killcount = p->killCount; itemcount = p->itemCount; secretcount = p->secretCount; #if __JHEXEN__ || __JSTRIFE__ worldTimer = p->worldTimer; #endif #if __JHERETIC__ if(p->didSecret) secret = true; spot = p->startSpot; #endif // Clears (almost) everything. ClearPlayer(p); #if __JHERETIC__ p->startSpot = spot; #endif memcpy(p->frags, frags, sizeof(p->frags)); p->killCount = killcount; p->itemCount = itemcount; p->secretCount = secretcount; #if __JHEXEN__ || __JSTRIFE__ p->worldTimer = worldTimer; p->colorMap = cfg.playerColor[player]; #endif #if __JHEXEN__ p->class = cfg.playerClass[player]; #endif p->useDown = p->attackDown = true; // Don't do anything immediately. p->playerState = PST_LIVE; p->health = maxHealth; #if __JDOOM__ || __JDOOM64__ p->readyWeapon = p->pendingWeapon = WT_SECOND; p->weapons[WT_FIRST].owned = true; p->weapons[WT_SECOND].owned = true; // Initalize the player's ammo counts. memset(p->ammo, 0, sizeof(p->ammo)); p->ammo[AT_CLIP].owned = 50; // See if the Values specify anything. P_InitPlayerValues(p); #elif __JHERETIC__ p->readyWeapon = p->pendingWeapon = WT_SECOND; p->weapons[WT_FIRST].owned = true; p->weapons[WT_SECOND].owned = true; p->ammo[AT_CRYSTAL].owned = 50; if(gameMap == 8 || secret) { p->didSecret = true; } #else p->readyWeapon = p->pendingWeapon = WT_FIRST; p->weapons[WT_FIRST].owned = true; localQuakeHappening[player] = false; #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Reset maxammo. for(i = 0; i < NUM_AMMO_TYPES; ++i) p->ammo[i].max = maxAmmo[i]; #endif // We'll need to update almost everything. #if __JHERETIC__ p->update |= PSF_STATE | PSF_HEALTH | PSF_ARMOR_TYPE | PSF_ARMOR_POINTS | PSF_INVENTORY | PSF_POWERS | PSF_KEYS | PSF_OWNED_WEAPONS | PSF_AMMO | PSF_MAX_AMMO | PSF_PENDING_WEAPON | PSF_READY_WEAPON; #else p->update |= PSF_REBORN; #endif p->plr->flags &= ~DDPF_DEAD; } #if __JDOOM__ || __JDOOM64__ void G_QueueBody(mobj_t* mo) { if(!mo) return; // Flush an old corpse if needed. if(bodyQueueSlot >= BODYQUEUESIZE) P_MobjRemove(bodyQueue[bodyQueueSlot % BODYQUEUESIZE], false); bodyQueue[bodyQueueSlot % BODYQUEUESIZE] = mo; bodyQueueSlot++; } #endif void G_DoReborn(int plrNum) { if(plrNum < 0 || plrNum >= MAXPLAYERS) return; // Wha? // Clear the currently playing script, if any. FI_Reset(); if(!IS_NETGAME) { // We've just died, don't do a briefing now. briefDisabled = true; #if __JHEXEN__ if(SV_HxRebornSlotAvailable()) { // Use the reborn code if the slot is available G_SetGameAction(GA_SINGLEREBORN); } else { // Start a new game if there's no reborn info G_SetGameAction(GA_NEWGAME); } #else // Reload the map from scratch. G_SetGameAction(GA_LOADMAP); #endif } else { // In a net game. P_RebornPlayer(plrNum); } } #if __JHEXEN__ void G_StartNewInit(void) { SV_HxInitBaseSlot(); SV_HxClearRebornSlot(); P_ACSInitNewGame(); // Default the player start spot group to 0 rebornPosition = 0; } void G_StartNewGame(skillmode_t skill) { G_StartNewInit(); G_InitNew(skill, 0, P_TranslateMap(0)); } #endif /** * Leave the current map and start intermission routine. * (if __JHEXEN__ the intermission will only be displayed when exiting a * hub and in DeathMatch games) * * @param newMap ID of the map we are entering. * @param _entryPoint Entry point on the new map. * @param secretExit */ void G_LeaveMap(uint newMap, uint _entryPoint, boolean _secretExit) { if(cyclingMaps && mapCycleNoExit) return; #if __JHEXEN__ if(shareware && newMap != DDMAXINT && newMap > 3) { // Not possible in the 4-map demo. P_SetMessage(&players[CONSOLEPLAYER], "PORTAL INACTIVE -- DEMO", false); return; } #endif #if __JHEXEN__ nextMap = newMap; nextMapEntryPoint = _entryPoint; #else secretExit = _secretExit; #if __JDOOM__ // If no Wolf3D maps, no secret exit! if(secretExit && (gameMode == commercial) && W_CheckNumForName("map31") < 0) secretExit = false; #endif #endif G_SetGameAction(GA_MAPCOMPLETED); } /** * @return @c true, if the game has been completed. */ boolean G_IfVictory(void) { #if __JDOOM64__ if(gameMap == 27) { return true; } #elif __JDOOM__ if((gameMap == 7) && (gameMode != commercial)) { return true; } #elif __JHERETIC__ if(gameMap == 7) { return true; } #elif __JHEXEN__ || __JSTRIFE__ if(nextMap == DDMAXINT && nextMapEntryPoint == DDMAXINT) { return true; } #endif return false; } static int prepareIntermission(void* paramaters) { #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ wmInfo.episode = gameEpisode; wmInfo.currentMap = gameMap; wmInfo.nextMap = nextMap; wmInfo.didSecret = players[CONSOLEPLAYER].didSecret; # if __JDOOM__ || __JDOOM64__ wmInfo.maxKills = totalKills; wmInfo.maxItems = totalItems; wmInfo.maxSecret = totalSecret; G_PrepareWIData(); # endif #endif #if __JDOOM__ || __JDOOM64__ WI_Init(&wmInfo); #elif __JHERETIC__ IN_Init(&wmInfo); #else /* __JHEXEN__ */ IN_Init(); #endif G_ChangeGameState(GS_INTERMISSION); Con_BusyWorkerEnd(); return 0; } void G_DoMapCompleted(void) { int i; G_SetGameAction(GA_NONE); for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { AM_Open(AM_MapForPlayer(i), false, true); G_PlayerLeaveMap(i); // take away cards and stuff // Update this client's stats. NetSv_SendPlayerState(i, DDSP_ALL_PLAYERS, PSF_FRAGS | PSF_COUNTERS, true); } } GL_SetFilter(false); #if __JHEXEN__ SN_StopAllSequences(); #endif // Go to an intermission? #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ { ddmapinfo_t minfo; char levid[8]; P_GetMapLumpName(gameEpisode, gameMap, levid); if(Def_Get(DD_DEF_MAP_INFO, levid, &minfo) && (minfo.flags & MIF_NO_INTERMISSION)) { G_WorldDone(); return; } } #elif __JHEXEN__ if(!deathmatch) { G_WorldDone(); return; } #endif // Has the player completed the game? if(G_IfVictory()) { // Victorious! G_SetGameAction(GA_VICTORY); return; } #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ # if __JDOOM__ if(gameMode != commercial && gameMap == 8) { int i; for(i = 0; i < MAXPLAYERS; ++i) players[i].didSecret = true; } # endif // Determine the next map. nextMap = G_GetNextMap(gameEpisode, gameMap, secretExit); #endif // Time for an intermission. #if __JDOOM64__ S_StartMusic("dm2int", true); #elif __JDOOM__ S_StartMusic(gameMode == commercial? "dm2int" : "inter", true); #elif __JHERETIC__ S_StartMusic("intr", true); #elif __JHEXEN__ S_StartMusic("hub", true); #endif S_PauseMusic(true); Con_Busy(BUSYF_TRANSITION, NULL, prepareIntermission, NULL); #if __JHERETIC__ // @fixme is this necessary at this time? NetSv_SendGameState(0, DDSP_ALL_PLAYERS); #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ NetSv_Intermission(IMF_BEGIN, 0, 0); #else /* __JHEXEN__ */ NetSv_Intermission(IMF_BEGIN, (int) nextMap, (int) nextMapEntryPoint); #endif S_PauseMusic(false); } #if __JDOOM__ || __JDOOM64__ void G_PrepareWIData(void) { int i; ddmapinfo_t minfo; char levid[8]; wbstartstruct_t *info = &wmInfo; info->maxFrags = 0; P_GetMapLumpName(gameEpisode, gameMap, levid); // See if there is a par time definition. if(Def_Get(DD_DEF_MAP_INFO, levid, &minfo) && minfo.parTime > 0) info->parTime = TICRATE * (int) minfo.parTime; else info->parTime = -1; // Unknown. info->pNum = CONSOLEPLAYER; for(i = 0; i < MAXPLAYERS; ++i) { player_t *p = &players[i]; wbplayerstruct_t *pStats = &info->plyr[i]; pStats->inGame = p->plr->inGame; pStats->kills = p->killCount; pStats->items = p->itemCount; pStats->secret = p->secretCount; pStats->time = mapTime; memcpy(pStats->frags, p->frags, sizeof(pStats->frags)); } } #endif void G_WorldDone(void) { #if __JDOOM__ || __JDOOM64__ if(secretExit) players[CONSOLEPLAYER].didSecret = true; #endif // Clear the currently playing script, if any. // @note FI_Reset() changes the game state so we must determine // whether the debrief is enabled first. { ddfinale_t fin; boolean doDebrief = FI_Debriefing(gameEpisode, gameMap, &fin); FI_Reset(); if(doDebrief) { FI_Start(fin.script, FIMODE_AFTER); return; } // We have either just returned from a debriefing or there wasn't one. briefDisabled = false; } G_SetGameAction(GA_LEAVEMAP); } void G_DoWorldDone(void) { #if __JHEXEN__ SV_MapTeleport(nextMap, nextMapEntryPoint); rebornPosition = nextMapEntryPoint; #else # if __JDOOM__ || __JDOOM64__ || __JHERETIC__ gameMap = nextMap; # endif G_DoLoadMap(); #endif G_SetGameAction(GA_NONE); } #if __JHEXEN__ /** * Called by G_Ticker based on gameaction. Loads a game from the reborn * save slot. */ void G_DoSingleReborn(void) { G_SetGameAction(GA_NONE); SV_LoadGame(SV_HxGetRebornSlot()); } #endif /** * Can be called by the startup code or the menu task. */ #if __JHEXEN__ || __JSTRIFE__ void G_LoadGame(int slot) { gameLoadSlot = slot; G_SetGameAction(GA_LOADGAME); } #else void G_LoadGame(const char* name) { M_TranslatePath(saveName, name, FILENAME_T_MAXLEN); G_SetGameAction(GA_LOADGAME); } #endif /** * Called by G_Ticker based on gameaction. */ void G_DoLoadGame(void) { G_StopDemo(); FI_Reset(); G_SetGameAction(GA_NONE); #if __JHEXEN__ || __JSTRIFE__ GL_DrawPatch(100, 68, W_GetNumForName("loadicon")); SV_LoadGame(gameLoadSlot); if(!IS_NETGAME) { // Copy the base slot to the reborn slot SV_HxUpdateRebornSlot(); } #else SV_LoadGame(saveName); #endif } /** * Called by the menu task. * * @param description A 24 byte text string. */ void G_SaveGame(int slot, const char* description) { saveGameSlot = slot; strncpy(saveDescription, description, HU_SAVESTRINGSIZE); G_SetGameAction(GA_SAVEGAME); } /** * Called by G_Ticker based on gameaction. */ void G_DoSaveGame(void) { #if __JHEXEN__ || __JSTRIFE__ GL_DrawPatch(100, 68, W_GetNumForName("SAVEICON")); SV_SaveGame(saveGameSlot, saveDescription); #else filename_t name; SV_GetSaveGameFileName(name, saveGameSlot, FILENAME_T_MAXLEN); SV_SaveGame(name, saveDescription); #endif G_SetGameAction(GA_NONE); saveDescription[0] = 0; P_SetMessage(&players[CONSOLEPLAYER], TXT_GAMESAVED, false); } #if __JHEXEN__ || __JSTRIFE__ void G_DeferredNewGame(skillmode_t skill) { dSkill = skill; G_SetGameAction(GA_NEWGAME); } void G_DoInitNew(void) { SV_HxInitBaseSlot(); G_InitNew(dSkill, dEpisode, dMap); G_SetGameAction(GA_NONE); } #endif /** * Can be called by the startup code or the menu task, CONSOLEPLAYER, * DISPLAYPLAYER, playeringame[] should be set. */ void G_DeferedInitNew(skillmode_t skill, uint episode, uint map) { dSkill = skill; dEpisode = episode; dMap = map; #if __JHEXEN__ || __JSTRIFE__ G_SetGameAction(GA_INITNEW); #else G_SetGameAction(GA_NEWGAME); #endif } void G_DoNewGame(void) { G_StopDemo(); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ if(!IS_NETGAME) { deathmatch = false; respawnMonsters = false; noMonstersParm = ArgExists("-nomonsters")? true : false; } G_InitNew(dSkill, dEpisode, dMap); #else G_StartNewGame(dSkill); #endif G_SetGameAction(GA_NONE); } /** * Start a new game. */ void G_InitNew(skillmode_t skill, uint episode, uint map) { int i; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ int speed; #endif // Close any open automaps. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) AM_Open(AM_MapForPlayer(i), false, true); // If there are any InFine scripts running, they must be stopped. FI_Reset(); if(paused) { paused = false; } if(skill < SM_BABY) skill = SM_BABY; if(skill > NUM_SKILL_MODES - 1) skill = NUM_SKILL_MODES - 1; // Make sure that the episode and map numbers are good. G_ValidateMap(&episode, &map); M_ResetRandom(); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ || __JSTRIFE__ respawnMonsters = respawnParm; #endif #if __JDOOM__ || __JHERETIC__ // Is respawning enabled at all in nightmare skill? if(skill == SM_NIGHTMARE) respawnMonsters = cfg.respawnMonstersNightmare; #endif //// \kludge Doom/Heretic Fast Monters/Missiles #if __JDOOM__ || __JDOOM64__ // Fast monsters? if(fastParm # if __JDOOM__ || (skill == SM_NIGHTMARE && gameSkill != SM_NIGHTMARE) # endif ) { for(i = S_SARG_RUN1; i <= S_SARG_RUN8; ++i) STATES[i].tics = 1; for(i = S_SARG_ATK1; i <= S_SARG_ATK3; ++i) STATES[i].tics = 4; for(i = S_SARG_PAIN; i <= S_SARG_PAIN2; ++i) STATES[i].tics = 1; } else { for(i = S_SARG_RUN1; i <= S_SARG_RUN8; ++i) STATES[i].tics = 2; for(i = S_SARG_ATK1; i <= S_SARG_ATK3; ++i) STATES[i].tics = 8; for(i = S_SARG_PAIN; i <= S_SARG_PAIN2; ++i) STATES[i].tics = 2; } #endif // Fast missiles? #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ # if __JDOOM64__ speed = fastParm; # elif __JDOOM__ speed = (fastParm || (skill == SM_NIGHTMARE && gameSkill != SM_NIGHTMARE)); # else speed = skill == SM_NIGHTMARE; # endif for(i = 0; MonsterMissileInfo[i].type != -1; ++i) { MOBJINFO[MonsterMissileInfo[i].type].speed = MonsterMissileInfo[i].speed[speed]; } #endif // <-- KLUDGE if(!IS_CLIENT) { // Force players to be initialized upon first map load. for(i = 0; i < MAXPLAYERS; ++i) { player_t *plr = &players[i]; plr->playerState = PST_REBORN; #if __JHEXEN__ || __JSTRIFE__ plr->worldTimer = 0; #else plr->didSecret = false; #endif } } userGame = true; // Will be set false if a demo. paused = false; gameEpisode = episode; gameMap = map; gameSkill = skill; NetSv_UpdateGameConfig(); G_DoLoadMap(); #if __JHEXEN__ // Initialize the sky. P_InitSky(map); #endif } /** * Return the index of this map. */ uint G_GetMapNumber(uint episode, uint map) { #if __JHEXEN__ || __JSTRIFE__ return P_TranslateMap(map); #elif __JDOOM64__ return map; #else #if __JDOOM__ if(gameMode == commercial) return map; else #endif { return map + episode * 9; // maps per episode. } #endif } /** * Compose the name of the map lump identifier. */ void P_GetMapLumpName(uint episode, uint map, char* lumpName) { #if __JDOOM64__ sprintf(lumpName, "MAP%02u", map+1); #elif __JDOOM__ if(gameMode == commercial) sprintf(lumpName, "MAP%02u", map+1); else sprintf(lumpName, "E%uM%u", episode+1, map+1); #elif __JHERETIC__ sprintf(lumpName, "E%uM%u", episode+1, map+1); #else sprintf(lumpName, "MAP%02u", map+1); #endif } /** * Returns true if the specified ep/map exists in a WAD. */ boolean P_MapExists(uint episode, uint map) { char buf[20]; P_GetMapLumpName(episode, map, buf); return W_CheckNumForName(buf) >= 0; } /** * Returns true if the specified (episode, map) pair can be used. * Otherwise the values are adjusted so they are valid. */ boolean G_ValidateMap(uint* episode, uint* map) { boolean ok = true; #if __JDOOM64__ if(*map > 98) { *map = 98; ok = false; } #elif __JDOOM__ if(gameMode == shareware) { // only start episode 0 on shareware if(*episode != 0) { *episode = 0; ok = false; } } else { // Allow episodes 0-8. if(*episode > 8) { *episode = 8; ok = false; } } if(gameMode == commercial) { if(*map > 98) { *map = 98; ok = false; } } else { if(*map > 8) { *map = 8; ok = false; } } #elif __JHERETIC__ // Allow episodes 0-8. if(*episode > 8) { *episode = 8; ok = false; } if(*map > 8) { *map = 8; ok = false; } if(gameMode == shareware) // Shareware version checks { if(*episode != 0) { *episode = 0; ok = false; } } else if(gameMode == extended) // Extended version checks { if(*episode == 5) { if(*map > 2) { *map = 2; ok = false; } } else if(*episode > 4) { *episode = 4; ok = false; } } else // Registered version checks { if(*episode == 3) { if(*map != 0) { *map = 0; ok = false; } } else if(*episode > 2) { *episode = 2; ok = false; } } #elif __JHEXEN__ || __JSTRIFE__ if(*map > 98) { *map = 98; ok = false; } #endif // Check that the map truly exists. if(!P_MapExists(*episode, *map)) { // (0,0) should exist always? *episode = 0; *map = 0; ok = false; } return ok; } /** * Return the next map according to the default map progression. * * @param episode Current episode. * @param map Current map. * @param secretExit * @return The next map. */ uint G_GetNextMap(uint episode, uint map, boolean secretExit) { #if __JHEXEN__ return G_GetMapNumber(episode, P_GetMapNextMap(map)); #elif __JDOOM64__ if(secretExit) { switch(map) { case 0: return 31; case 3: return 28; case 11: return 29; case 17: return 30; case 31: return 0; default: Con_Message("G_NextMap: Warning - No secret exit on map %u!", map+1); break; } } switch(map) { case 23: return 27; case 31: return 0; case 28: return 4; case 29: return 12; case 30: return 18; case 24: return 0; case 25: return 0; case 26: return 0; default: return map + 1; } #elif __JDOOM__ if(gameMode == commercial) { if(secretExit) { switch(map) { case 14: return 30; case 30: return 31; default: Con_Message("G_NextMap: Warning - No secret exit on map %u!", map+1); break; } } switch(map) { case 30: case 31: return 15; default: return map + 1; } } else { if(secretExit && map != 8) return 8; // Go to secret map. switch(map) { case 8: // Returning from secret map. switch(episode) { case 0: return 3; case 1: return 5; case 2: return 6; case 3: return 2; default: Con_Error("G_NextMap: Invalid episode num #%u!", episode); } return 0; // Unreachable default: return map + 1; // Go to next map. } } #elif __JHERETIC__ if(secretExit && map != 8) return 8; // Go to secret map. switch(map) { case 8: // Returning from secret map. switch(episode) { case 0: return 6; case 1: return 4; case 2: return 4; case 3: return 4; case 4: return 3; default: Con_Error("G_NextMap: Invalid episode num #%u!", episode); } return 0; // Unreachable default: return map + 1; // Go to next map. } #endif } #if __JHERETIC__ const char* P_GetShortMapName(uint episode, uint map) { const char* name = P_GetMapName(episode, map); const char* ptr; // Skip over the "ExMx:" from the beginning. ptr = strchr(name, ':'); if(!ptr) return name; name = ptr + 1; while(*name && isspace(*name)) name++; // Skip any number of spaces. return name; } const char* P_GetMapName(uint episode, uint map) { char id[10], *ptr; ddmapinfo_t info; // Compose the map identifier. P_GetMapLumpName(episode, map, id); // Get the map info definition. if(!Def_Get(DD_DEF_MAP_INFO, id, &info)) { // There is no map information for this map... return ""; } if(Def_Get(DD_DEF_TEXT, info.name, &ptr) != -1) return ptr; return info.name; } #endif /** * Print a list of maps and the WAD files where they are from. */ void G_PrintFormattedMapList(uint episode, const char** files, uint count) { const char* current = NULL; char lump[20]; uint i, k; uint rangeStart = 0, len; for(i = 0; i < count; ++i) { if(!current && files[i]) { current = files[i]; rangeStart = i; } else if(current && (!files[i] || stricmp(current, files[i]))) { // Print a range. len = i - rangeStart; Con_Printf(" "); // Indentation. if(len <= 2) { for(k = rangeStart; k < i; ++k) { P_GetMapLumpName(episode, k, lump); Con_Printf("%s%s", lump, k != i ? "," : ""); } } else { P_GetMapLumpName(episode, rangeStart, lump); Con_Printf("%s-", lump); P_GetMapLumpName(episode, i, lump); Con_Printf("%s", lump); } Con_Printf(": %s\n", M_PrettyPath(current)); // Moving on to a different file. current = files[i]; rangeStart = i; } } } /** * Print a list of loaded maps and which WAD files are they located in. * The maps are identified using the "ExMy" and "MAPnn" markers. */ void G_PrintMapList(void) { const char* sourceList[100]; lumpnum_t lump; uint episode, map, numEpisodes, maxMapsPerEpisode; char mapLump[20]; #if __JDOOM__ if(gameMode == registered) { numEpisodes = 3; maxMapsPerEpisode = 9; } else if(gameMode == retail) { numEpisodes = 4; maxMapsPerEpisode = 9; } else { numEpisodes = 1; maxMapsPerEpisode = 99; } #elif __JHERETIC__ if(gameMode == extended) numEpisodes = 6; else if(gameMode == registered) numEpisodes = 3; else numEpisodes = 1; maxMapsPerEpisode = 9; #else numEpisodes = 1; maxMapsPerEpisode = 99; #endif for(episode = 0; episode < numEpisodes; ++episode) { memset((void *) sourceList, 0, sizeof(sourceList)); // Find the name of each map (not all may exist). for(map = 0; map < maxMapsPerEpisode-1; ++map) { P_GetMapLumpName(episode, map, mapLump); // Does the lump exist? if((lump = W_CheckNumForName(mapLump)) >= 0) { // Get the name of the WAD. sourceList[map] = W_LumpSourceFile(lump); } } G_PrintFormattedMapList(episode, sourceList, 99); } } /** * Stops both playback and a recording. Called at critical points like * starting a new game, or ending the game in the menu. */ void G_StopDemo(void) { DD_Execute(true, "stopdemo"); } void G_DemoEnds(void) { G_ChangeGameState(GS_WAITING); if(singledemo) { G_SetGameAction(GA_QUIT); return; } FI_DemoEnds(); } void G_DemoAborted(void) { G_ChangeGameState(GS_WAITING); FI_DemoEnds(); } void G_ScreenShot(void) { G_SetGameAction(GA_SCREENSHOT); } void G_DoScreenShot(void) { int i; filename_t name; char* numPos; // Use game mode as the file name base. sprintf(name, "%s-", (char *) G_GetVariable(DD_GAME_MODE)); numPos = name + strlen(name); // Find an unused file name. for(i = 0; i < 1e6; ++i) // Stop eventually... { sprintf(numPos, "%03i.tga", i); if(!M_FileExists(name)) break; } M_ScreenShot(name, 24); Con_Message("Wrote %s.\n", name); } DEFCC(CCmdListMaps) { Con_Message("Loaded maps:\n"); G_PrintMapList(); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/g_defs.c0000644000175000017500000000527011357170242022224 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 1999-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_defs.c: Game object/value definitions. */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" # include "p_inventory.h" #elif __JHEXEN__ # include "jhexen.h" # include "p_inventory.h" #elif __JSTRIFE__ # include "jstrife.h" #endif // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * @return The default for a value (retrieved from Doomsday). */ int GetDefInt(char* def, int* returnVal) { char* data; int val; // Get the value. if(!Def_Get(DD_DEF_VALUE, def, &data)) return 0; // No such value... // Convert to integer. val = strtol(data, 0, 0); if(returnVal) *returnVal = val; return val; } void GetDefState(char* def, int* val) { char* data; // Get the value. if(!Def_Get(DD_DEF_VALUE, def, &data)) return; // Get the state number. *val = Def_Get(DD_DEF_STATE, data, 0); if(*val < 0) *val = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_view.c0000644000175000017500000001354011357170242022265 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_view.c: */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" # include "g_common.h" #elif __JDOOM64__ # include "jdoom64.h" # include "g_common.h" #elif __JHERETIC__ # include "jheretic.h" # include "g_common.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "p_player.h" #include "p_tick.h" #include "p_actor.h" // MACROS ------------------------------------------------------------------ #define VIEW_HEIGHT (cfg.plrViewHeight) #define MAXBOB (16) // pixels. // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Calculate the walking / running height adjustment. */ void P_CalcHeight(player_t* plr) { boolean airborne; boolean morphed = false; ddplayer_t* ddplr = plr->plr; mobj_t* pmo = ddplr->mo; float target, step; // Regular movement bobbing (needs to be calculated for gun swing even // if not on ground). plr->bob = (pmo->mom[MX] * pmo->mom[MX]) + (pmo->mom[MY] * pmo->mom[MY]); plr->bob /= 4; if(plr->bob > MAXBOB) plr->bob = MAXBOB; // When flying, don't bob the view. if((pmo->flags2 & MF2_FLY) && pmo->pos[VZ] > pmo->floorZ) { plr->bob = 1.0f / 2; } #if __JHERETIC__ || __JHEXEN__ if(plr->morphTics) morphed = true; #endif // During demo playback the view is thought to be airborne if viewheight // is zero (Cl_MoveLocalPlayer). if(Get(DD_PLAYBACK)) airborne = !plr->viewHeight; else airborne = pmo->pos[VZ] > pmo->floorZ; // Truly in the air? // Morphed players don't bob their view. if(P_MobjIsCamera(ddplr->mo) /*$democam*/ || (ddplr->flags & DDPF_CHASECAM) || airborne || morphed || (P_GetPlayerCheats(plr) & CF_NOMOMENTUM)) { // Reduce the bob offset to zero. target = 0; } else { angle_t angle = (FINEANGLES / 20 * mapTime) & FINEMASK; target = cfg.bobView * ((plr->bob / 2) * FIX2FLT(finesine[angle])); } // Do the change gradually. if(airborne || plr->airCounter > 0) step = 4.0f - (plr->airCounter > 0 ? plr->airCounter * 0.2f : 3.5f); else step = 4.0f; if(plr->viewOffset[VZ] > target) { if(plr->viewOffset[VZ] - target > step) plr->viewOffset[VZ] -= step; else plr->viewOffset[VZ] = target; } else if(plr->viewOffset[VZ] < target) { if(target - plr->viewOffset[VZ] > step) plr->viewOffset[VZ] += step; else plr->viewOffset[VZ] = target; } // The aircounter will soften the touchdown after a fall. plr->airCounter--; if(airborne) plr->airCounter = TICSPERSEC / 2; // Should viewheight be moved? Not if camera or we're in demo. if(!((P_GetPlayerCheats(plr) & CF_NOMOMENTUM) || P_MobjIsCamera(pmo) /*$democam*/ || Get(DD_PLAYBACK))) { // Move viewheight. if(plr->playerState == PST_LIVE) { plr->viewHeight += plr->viewHeightDelta; if(plr->viewHeight > VIEW_HEIGHT) { plr->viewHeight = VIEW_HEIGHT; plr->viewHeightDelta = 0; } else if(plr->viewHeight < VIEW_HEIGHT / 2.0f) { plr->viewHeight = VIEW_HEIGHT / 2.0f; if(plr->viewHeightDelta <= 0) plr->viewHeightDelta = 1; } if(plr->viewHeightDelta) { plr->viewHeightDelta += 0.25f; if(!plr->viewHeightDelta) plr->viewHeightDelta = 1; } } } // Set the plr's eye-level Z coordinate. plr->viewZ = pmo->pos[VZ] + (P_MobjIsCamera(pmo)? 0 : plr->viewHeight); // During demo playback (or camera mode) the viewz will not be modified // any further. if(!(Get(DD_PLAYBACK) || P_MobjIsCamera(pmo) || (ddplr->flags & DDPF_CHASECAM))) { if(morphed) { // Chicken or pig. plr->viewZ -= 20; } // Foot clipping is done for living players. if(plr->playerState != PST_DEAD) { if(pmo->floorClip && pmo->pos[VZ] <= pmo->floorZ) { plr->viewZ -= pmo->floorClip; } } } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_map.c0000644000175000017500000026333411357170242022100 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_map.c: Common map routines. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "d_net.h" #include "g_common.h" #include "dmu_lib.h" #include "p_mapspec.h" #include "p_terraintype.h" #include "p_tick.h" #include "p_actor.h" #include "p_player.h" #include "p_mapsetup.h" // MACROS ------------------------------------------------------------------ #if __JHEXEN__ #define USE_PUZZLE_ITEM_SPECIAL 129 #endif // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- #if __JDOOM64__ static void CheckMissileImpact(mobj_t* mobj); #endif #if __JHERETIC__ static void CheckMissileImpact(mobj_t* mobj); #elif __JHEXEN__ static void P_FakeZMovement(mobj_t* mo); static void checkForPushSpecial(linedef_t* line, int side, mobj_t* mobj); #endif // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float tmBBox[4]; mobj_t* tmThing; // If "floatOk" true, move would be ok if within "tmFloorZ - tmCeilingZ". boolean floatOk; float tmFloorZ; float tmCeilingZ; #if __JHEXEN__ material_t* tmFloorMaterial; #endif boolean fellDown; // $dropoff_fix // The following is used to keep track of the linedefs that clip the open // height range e.g. PIT_CheckLine. They in turn are used with the &unstuck // logic and to prevent missiles from exploding against sky hack walls. linedef_t* ceilingLine; linedef_t* floorLine; mobj_t* lineTarget; // Who got hit (or NULL). linedef_t* blockLine; // $unstuck: blocking linedef float attackRange; #if __JHEXEN__ mobj_t* puffSpawned; mobj_t* blockingMobj; #endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ static float tm[3]; #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ static float tmHeight; static linedef_t* tmHitLine; #endif static float tmDropoffZ; static float bestSlideFrac, secondSlideFrac; static linedef_t* bestSlideLine, *secondSlideLine; static mobj_t* slideMo; static float tmMove[3]; static mobj_t* shootThing; // Height if not aiming up or down. static float shootZ; static int lineAttackDamage; static float aimSlope; // slopes to top and bottom of target static float topSlope, bottomSlope; static mobj_t* useThing; static mobj_t* bombSource, *bombSpot; static int bombDamage; static int bombDistance; static boolean crushChange; static boolean noFit; static float startPos[3]; // start position for trajectory line checks static float endPos[3]; // end position for trajectory checks #if __JHEXEN__ static mobj_t* tsThing; static boolean damageSource; static mobj_t* onMobj; // generic global onMobj...used for landing on pods/players static mobj_t* puzzleItemUser; static int puzzleItemType; static boolean puzzleActivated; #endif #if !__JHEXEN__ static int tmUnstuck; // $unstuck: used to check unsticking #endif static byte* rejectMatrix = NULL; // For fast sight rejection. // CODE -------------------------------------------------------------------- float P_GetGravity(void) { if(IS_NETGAME && cfg.netGravity != -1) return (float) cfg.netGravity / 100; return *((float*) DD_GetVariable(DD_GRAVITY)); } /** * Checks the reject matrix to find out if the two sectors are visible * from each other. */ static boolean checkReject(subsector_t* a, subsector_t* b) { if(rejectMatrix != NULL) { uint s1, s2, pnum, bytenum, bitnum; sector_t* sec1 = P_GetPtrp(a, DMU_SECTOR); sector_t* sec2 = P_GetPtrp(b, DMU_SECTOR); // Determine subsector entries in REJECT table. s1 = P_ToIndex(sec1); s2 = P_ToIndex(sec2); pnum = s1 * numsectors + s2; bytenum = pnum >> 3; bitnum = 1 << (pnum & 7); // Check in REJECT table. if(rejectMatrix[bytenum] & bitnum) { // Can't possibly be connected. return false; } } return true; } /** * Look from eyes of t1 to any part of t2 (start from middle of t1). * * @param from The mobj doing the looking. * @param to The mobj being looked at. * * @return @c true if a straight line between t1 and t2 is * unobstructed. */ boolean P_CheckSight(const mobj_t* from, const mobj_t* to) { float fPos[3]; // If either is unlinked, they can't see each other. if(!from->subsector || !to->subsector) return false; if(to->dPlayer && (to->dPlayer->flags & DDPF_CAMERA)) return false; // Cameramen don't exist! // Check for trivial rejection. if(!checkReject(from->subsector, to->subsector)) return false; fPos[VX] = from->pos[VX]; fPos[VY] = from->pos[VY]; fPos[VZ] = from->pos[VZ]; if(!P_MobjIsCamera(from)) fPos[VZ] += from->height + -(from->height / 4); return P_CheckLineSight(fPos, to->pos, 0, to->height, 0); } boolean PIT_StompThing(mobj_t* mo, void* data) { int stompAnyway; float blockdist; if(!(mo->flags & MF_SHOOTABLE)) return true; blockdist = mo->radius + tmThing->radius; if(fabs(mo->pos[VX] - tm[VX]) >= blockdist || fabs(mo->pos[VY] - tm[VY]) >= blockdist) return true; // Didn't hit it. if(mo == tmThing) return true; // Don't clip against self. stompAnyway = *(int*) data; // Should we stomp anyway? unless self. if(mo != tmThing && stompAnyway) { P_DamageMobj(mo, tmThing, tmThing, 10000, true); return true; } #if __JDOOM64__ // monsters don't stomp things if(!tmThing->player) return false; #elif __JDOOM__ // Monsters don't stomp things except on a boss map. if(!tmThing->player && gameMap != 29) return false; #endif if(!(tmThing->flags2 & MF2_TELESTOMP)) return false; // Not allowed to stomp things. // Do stomp damage (unless self). if(mo != tmThing) P_DamageMobj(mo, tmThing, tmThing, 10000, true); return true; } boolean P_TeleportMove(mobj_t* thing, float x, float y, boolean alwaysStomp) { int stomping; subsector_t* newSSec; float box[4]; // Kill anything occupying the position. tmThing = thing; stomping = alwaysStomp; tm[VX] = x; tm[VY] = y; tmBBox[BOXTOP] = tm[VY] + tmThing->radius; tmBBox[BOXBOTTOM] = tm[VY] - tmThing->radius; tmBBox[BOXRIGHT] = tm[VX] + tmThing->radius; tmBBox[BOXLEFT] = tm[VX] - tmThing->radius; newSSec = R_PointInSubsector(tm[VX], tm[VY]); ceilingLine = floorLine = NULL; #if !__JHEXEN__ blockLine = NULL; tmUnstuck = thing->dPlayer && thing->dPlayer->mo == thing; #endif // The base floor / ceiling is from the subsector that contains the // point. Any contacted lines the step closer together will adjust them. tmFloorZ = tmDropoffZ = P_GetFloatp(newSSec, DMU_FLOOR_HEIGHT); tmCeilingZ = P_GetFloatp(newSSec, DMU_CEILING_HEIGHT); #if __JHEXEN__ tmFloorMaterial = P_GetPtrp(newSSec, DMU_FLOOR_MATERIAL); #endif P_EmptyIterList(spechit); box[BOXLEFT] = tmBBox[BOXLEFT] - MAXRADIUS; box[BOXRIGHT] = tmBBox[BOXRIGHT] + MAXRADIUS; box[BOXBOTTOM] = tmBBox[BOXBOTTOM] - MAXRADIUS; box[BOXTOP] = tmBBox[BOXTOP] + MAXRADIUS; // Stomp on any things contacted. VALIDCOUNT++; if(!P_MobjsBoxIterator(box, PIT_StompThing, &stomping)) return false; // The move is ok, so link the thing into its new position. P_MobjUnsetPosition(thing); thing->floorZ = tmFloorZ; thing->ceilingZ = tmCeilingZ; #if !__JHEXEN__ thing->dropOffZ = tmDropoffZ; #endif thing->pos[VX] = x; thing->pos[VY] = y; P_MobjSetPosition(thing); P_MobjClearSRVO(thing); return true; } /** * Checks to see if a start->end trajectory line crosses a blocking line. * Returns false if it does. * * tmBBox holds the bounding box of the trajectory. If that box does not * touch the bounding box of the line in question, then the trajectory is * not blocked. If the start is on one side of the line and the end is on * the other side, then the trajectory is blocked. * * Currently this assumes an infinite line, which is not quite correct. * A more correct solution would be to check for an intersection of the * trajectory and the line, but that takes longer and probably really isn't * worth the effort. * * @param data Unused. */ boolean PIT_CrossLine(linedef_t* ld, void* data) { int flags = P_GetIntp(ld, DMU_FLAGS); if((flags & DDLF_BLOCKING) || (P_ToXLine(ld)->flags & ML_BLOCKMONSTERS) || (!P_GetPtrp(ld, DMU_FRONT_SECTOR) || !P_GetPtrp(ld, DMU_BACK_SECTOR))) { float bbox[4]; P_GetFloatpv(ld, DMU_BOUNDING_BOX, bbox); if(!(tmBBox[BOXLEFT] > bbox[BOXRIGHT] || tmBBox[BOXRIGHT] < bbox[BOXLEFT] || tmBBox[BOXTOP] < bbox[BOXBOTTOM] || tmBBox[BOXBOTTOM] > bbox[BOXTOP])) { if(P_PointOnLinedefSide(startPos[VX], startPos[VY], ld) != P_PointOnLinedefSide(endPos[VX], endPos[VY], ld)) // Line blocks trajectory. return false; } } // Line doesn't block trajectory. return true; } /** * This routine checks for Lost Souls trying to be spawned across 1-sided * lines, impassible lines, or "monsters can't cross" lines. * * Draw an imaginary line between the PE and the new Lost Soul spawn spot. * If that line crosses a 'blocking' line, then disallow the spawn. Only * search lines in the blocks of the blockmap where the bounding box of the * trajectory line resides. Then check bounding box of the trajectory vs * the bounding box of each blocking line to see if the trajectory and the * blocking line cross. Then check the PE and LS to see if they are on * different sides of the blocking line. If so, return true otherwise * false. */ boolean P_CheckSides(mobj_t* actor, float x, float y) { startPos[VX] = actor->pos[VX]; startPos[VY] = actor->pos[VY]; startPos[VZ] = actor->pos[VZ]; endPos[VX] = x; endPos[VY] = y; endPos[VZ] = DDMINFLOAT; // Initialize with *something*. // The bounding box of the trajectory tmBBox[BOXLEFT] = (startPos[VX] < endPos[VX]? startPos[VX] : endPos[VX]); tmBBox[BOXRIGHT] = (startPos[VX] > endPos[VX]? startPos[VX] : endPos[VX]); tmBBox[BOXTOP] = (startPos[VY] > endPos[VY]? startPos[VY] : endPos[VY]); tmBBox[BOXBOTTOM] = (startPos[VY] < endPos[VY]? startPos[VY] : endPos[VY]); VALIDCOUNT++; return !P_AllLinesBoxIterator(tmBBox, PIT_CrossLine, 0); } #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ /** * $unstuck: used to test intersection between thing and line assuming NO * movement occurs -- used to avoid sticky situations. */ static int untouched(linedef_t* ld) { float x, y, box[4]; float bbox[4]; float radius; P_GetFloatpv(ld, DMU_BOUNDING_BOX, bbox); x = tmThing->pos[VX]; y = tmThing->pos[VY]; radius = tmThing->radius; if(((box[BOXRIGHT] = x + radius) <= bbox[BOXLEFT]) || ((box[BOXLEFT] = x - radius) >= bbox[BOXRIGHT]) || ((box[BOXTOP] = y + radius) <= bbox[BOXBOTTOM]) || ((box[BOXBOTTOM] = y - radius) >= bbox[BOXTOP]) || P_BoxOnLineSide(box, ld) != -1) return true; return false; } #endif boolean PIT_CheckThing(mobj_t* thing, void* data) { int damage; float blockdist; boolean solid; #if !__JHEXEN__ boolean overlap = false; #endif // Don't clip against self. if(thing == tmThing) return true; #if __JHEXEN__ // Don't clip on something we are stood on. if(thing == tmThing->onMobj) return true; #endif if(!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE)) || P_MobjIsCamera(thing) || P_MobjIsCamera(tmThing)) return true; #if !__JHEXEN__ // Player only. if(tmThing->player && tm[VZ] != DDMAXFLOAT && (cfg.moveCheckZ || (tmThing->flags2 & MF2_PASSMOBJ))) { if((thing->pos[VZ] > tm[VZ] + tmHeight) || (thing->pos[VZ] + thing->height < tm[VZ])) return true; // Under or over it. overlap = true; } #endif blockdist = thing->radius + tmThing->radius; if(fabs(thing->pos[VX] - tm[VX]) >= blockdist || fabs(thing->pos[VY] - tm[VY]) >= blockdist) return true; // Didn't hit thing. #if __JHEXEN__ // Stop here if we are a client. if(IS_CLIENT) return false; #endif #if !__JHEXEN__ if(!tmThing->player && (tmThing->flags2 & MF2_PASSMOBJ)) #else blockingMobj = thing; if(tmThing->flags2 & MF2_PASSMOBJ) #endif { // Check if a mobj passed over/under another object. #if __JHERETIC__ if((tmThing->type == MT_IMP || tmThing->type == MT_WIZARD) && (thing->type == MT_IMP || thing->type == MT_WIZARD)) { return false; // Don't let imps/wizards fly over other imps/wizards. } #elif __JHEXEN__ if(tmThing->type == MT_BISHOP && thing->type == MT_BISHOP) return false; // Don't let bishops fly over other bishops. #endif if(!(thing->flags & MF_SPECIAL)) { if(tmThing->pos[VZ] > thing->pos[VZ] + thing->height || tmThing->pos[VZ] + tmThing->height < thing->pos[VZ]) return true; // Over/under thing. } } // Check for skulls slamming into things. if((tmThing->flags & MF_SKULLFLY) && (thing->flags & MF_SOLID)) { #if __JHEXEN__ blockingMobj = NULL; if(tmThing->type == MT_MINOTAUR) { // Slamming minotaurs shouldn't move non-creatures. if(!(thing->flags & MF_COUNTKILL)) { return false; } } else if(tmThing->type == MT_HOLY_FX) { if((thing->flags & MF_SHOOTABLE) && thing != tmThing->target) { if(IS_NETGAME && !deathmatch && thing->player) return true; // don't attack other co-op players if((thing->flags2 & MF2_REFLECTIVE) && (thing->player || (thing->flags2 & MF2_BOSS))) { tmThing->tracer = tmThing->target; tmThing->target = thing; return true; } if(thing->flags & MF_COUNTKILL || thing->player) { tmThing->tracer = thing; } if(P_Random() < 96) { damage = 12; if(thing->player || (thing->flags2 & MF2_BOSS)) { damage = 3; // Ghost burns out faster when attacking players/bosses. tmThing->health -= 6; } P_DamageMobj(thing, tmThing, tmThing->target, damage, false); if(P_Random() < 128) { P_SpawnMobj3fv(MT_HOLY_PUFF, tmThing->pos, P_Random() << 24, 0); S_StartSound(SFX_SPIRIT_ATTACK, tmThing); if((thing->flags & MF_COUNTKILL) && P_Random() < 128 && !S_IsPlaying(SFX_PUPPYBEAT, thing)) { if((thing->type == MT_CENTAUR) || (thing->type == MT_CENTAURLEADER) || (thing->type == MT_ETTIN)) { S_StartSound(SFX_PUPPYBEAT, thing); } } } } if(thing->health <= 0) tmThing->tracer = NULL; } return true; } #endif #if __JDOOM__ if(tmThing->damage == DDMAXINT) //// \kludge to support old save games. damage = tmThing->info->damage; else #endif damage = tmThing->damage; damage *= (P_Random() % 8) + 1; P_DamageMobj(thing, tmThing, tmThing, damage, false); tmThing->flags &= ~MF_SKULLFLY; tmThing->mom[MX] = tmThing->mom[MY] = tmThing->mom[MZ] = 0; #if __JHERETIC__ || __JHEXEN__ P_MobjChangeState(tmThing, P_GetState(tmThing->type, SN_SEE)); #else P_MobjChangeState(tmThing, P_GetState(tmThing->type, SN_SPAWN)); #endif return false; // Stop moving. } #if __JHEXEN__ // Check for blasted thing running into another if((tmThing->flags2 & MF2_BLASTED) && (thing->flags & MF_SHOOTABLE)) { if(!(thing->flags2 & MF2_BOSS) && (thing->flags & MF_COUNTKILL)) { thing->mom[MX] += tmThing->mom[MX]; thing->mom[MY] += tmThing->mom[MY]; if(thing->dPlayer) thing->dPlayer->flags |= DDPF_FIXMOM; if((thing->mom[MX] + thing->mom[MY]) > 3) { damage = (tmThing->info->mass / 100) + 1; P_DamageMobj(thing, tmThing, tmThing, damage, false); damage = (thing->info->mass / 100) + 1; P_DamageMobj(tmThing, thing, thing, damage >> 2, false); } return false; } } #endif // Missiles can hit other things. if(tmThing->flags & MF_MISSILE) { #if __JHEXEN__ // Check for a non-shootable mobj. if(thing->flags2 & MF2_NONSHOOTABLE) return true; #else // Check for passing through a ghost. if((thing->flags & MF_SHADOW) && (tmThing->flags2 & MF2_THRUGHOST)) return true; #endif // See if it went over / under. if(tmThing->pos[VZ] > thing->pos[VZ] + thing->height) return true; // Overhead. if(tmThing->pos[VZ] + tmThing->height < thing->pos[VZ]) return true; // Underneath. #if __JHEXEN__ if(tmThing->flags2 & MF2_FLOORBOUNCE) { if(tmThing->target == thing || !(thing->flags & MF_SOLID)) return true; else return false; } if(tmThing->type == MT_LIGHTNING_FLOOR || tmThing->type == MT_LIGHTNING_CEILING) { if((thing->flags & MF_SHOOTABLE) && thing != tmThing->target) { if(thing->info->mass != DDMAXINT) { thing->mom[MX] += tmThing->mom[MX] / 16; thing->mom[MY] += tmThing->mom[MY] / 16; if(thing->dPlayer) thing->dPlayer->flags |= DDPF_FIXMOM; } if((!thing->player && !(thing->flags2 & MF2_BOSS)) || !(mapTime & 1)) { if(thing->type == MT_CENTAUR || thing->type == MT_CENTAURLEADER) { // Lightning does more damage to centaurs. P_DamageMobj(thing, tmThing, tmThing->target, 9, false); } else { P_DamageMobj(thing, tmThing, tmThing->target, 3, false); } if(!(S_IsPlaying(SFX_MAGE_LIGHTNING_ZAP, tmThing))) { S_StartSound(SFX_MAGE_LIGHTNING_ZAP, tmThing); } if((thing->flags & MF_COUNTKILL) && P_Random() < 64 && !S_IsPlaying(SFX_PUPPYBEAT, thing)) { if((thing->type == MT_CENTAUR) || (thing->type == MT_CENTAURLEADER) || (thing->type == MT_ETTIN)) { S_StartSound(SFX_PUPPYBEAT, thing); } } } tmThing->health--; if(tmThing->health <= 0 || thing->health <= 0) { return false; } if(tmThing->type == MT_LIGHTNING_FLOOR) { if(tmThing->lastEnemy && !tmThing->lastEnemy->tracer) { tmThing->lastEnemy->tracer = thing; } } else if(!tmThing->tracer) { tmThing->tracer = thing; } } return true; // Lightning zaps through all sprites. } else if(tmThing->type == MT_LIGHTNING_ZAP) { mobj_t *lmo; if((thing->flags & MF_SHOOTABLE) && thing != tmThing->target) { lmo = tmThing->lastEnemy; if(lmo) { if(lmo->type == MT_LIGHTNING_FLOOR) { if(lmo->lastEnemy && !lmo->lastEnemy->tracer) { lmo->lastEnemy->tracer = thing; } } else if(!lmo->tracer) { lmo->tracer = thing; } if(!(mapTime & 3)) { lmo->health--; } } } } else if(tmThing->type == MT_MSTAFF_FX2 && thing != tmThing->target) { if(!thing->player && !(thing->flags2 & MF2_BOSS)) { switch(thing->type) { case MT_FIGHTER_BOSS: // these not flagged boss case MT_CLERIC_BOSS: // so they can be blasted case MT_MAGE_BOSS: break; default: P_DamageMobj(thing, tmThing, tmThing->target, 10, false); return true; break; } } } #endif // Don't hit same species as originator. #if __JDOOM__ || __JDOOM64__ if(tmThing->target && (tmThing->target->type == thing->type || (tmThing->target->type == MT_KNIGHT && thing->type == MT_BRUISER) || (tmThing->target->type == MT_BRUISER && thing->type == MT_KNIGHT))) #else if(tmThing->target && tmThing->target->type == thing->type) #endif { if(thing == tmThing->target) return true; #if __JHEXEN__ if(!thing->player) return false; // Hit same species as originator, explode, no damage #else if(!monsterInfight && thing->type != MT_PLAYER) { // Explode, but do no damage. // Let players missile other players. return false; } #endif } if(!(thing->flags & MF_SHOOTABLE)) { return !(thing->flags & MF_SOLID); // Didn't do any damage. } if(tmThing->flags2 & MF2_RIP) { #if __JHEXEN__ if(!(thing->flags & MF_NOBLOOD) && !(thing->flags2 & MF2_REFLECTIVE) && !(thing->flags2 & MF2_INVULNERABLE)) #else if(!(thing->flags & MF_NOBLOOD)) #endif { // Ok to spawn some blood. P_RipperBlood(tmThing); } #if __JHERETIC__ S_StartSound(SFX_RIPSLOP, tmThing); #endif #if __JDOOM__ if(tmThing->damage == DDMAXINT) //// \kludge to support old save games. damage = tmThing->info->damage; else #endif damage = tmThing->damage; damage *= (P_Random() & 3) + 2; P_DamageMobj(thing, tmThing, tmThing->target, damage, false); if((thing->flags2 & MF2_PUSHABLE) && !(tmThing->flags2 & MF2_CANNOTPUSH)) { // Push thing thing->mom[MX] += tmThing->mom[MX] / 4; thing->mom[MY] += tmThing->mom[MY] / 4; if(thing->dPlayer) thing->dPlayer->flags |= DDPF_FIXMOM; } P_EmptyIterList(spechit); return true; } // Do damage #if __JDOOM__ if(tmThing->damage == DDMAXINT) //// \kludge to support old save games. damage = tmThing->info->damage; else #endif damage = tmThing->damage; damage *= (P_Random() % 8) + 1; #if __JDOOM__ || __JDOOM64__ P_DamageMobj(thing, tmThing, tmThing->target, damage, false); #else if(damage) { # if __JHERETIC__ if(!(thing->flags & MF_NOBLOOD) && P_Random() < 192) # else //__JHEXEN__ if(!(thing->flags & MF_NOBLOOD) && !(thing->flags2 & MF2_REFLECTIVE) && !(thing->flags2 & MF2_INVULNERABLE) && !(tmThing->type == MT_TELOTHER_FX1) && !(tmThing->type == MT_TELOTHER_FX2) && !(tmThing->type == MT_TELOTHER_FX3) && !(tmThing->type == MT_TELOTHER_FX4) && !(tmThing->type == MT_TELOTHER_FX5) && (P_Random() < 192)) # endif P_SpawnBloodSplatter(tmThing->pos[VX], tmThing->pos[VY], tmThing->pos[VZ], thing); P_DamageMobj(thing, tmThing, tmThing->target, damage, false); } #endif // Don't traverse anymore. return false; } if((thing->flags2 & MF2_PUSHABLE) && !(tmThing->flags2 & MF2_CANNOTPUSH)) { // Push thing thing->mom[MX] += tmThing->mom[MX] / 4; thing->mom[MY] += tmThing->mom[MY] / 4; if(thing->dPlayer) thing->dPlayer->flags |= DDPF_FIXMOM; } // \kludge: Always treat blood as a solid. if(tmThing->type == MT_BLOOD) solid = true; else solid = (thing->flags & MF_SOLID) && !(thing->flags & MF_NOCLIP) && (tmThing->flags & MF_SOLID); // \kludge: end. // Check for special pickup. if((thing->flags & MF_SPECIAL) && (tmThing->flags & MF_PICKUP)) { P_TouchSpecialMobj(thing, tmThing); // Can remove thing. } #if !__JHEXEN__ else if(overlap && solid) { // How are we positioned, allow step up? if(!(thing->flags & MF_CORPSE) && tm[VZ] > thing->pos[VZ] + thing->height - 24) { tmThing->onMobj = thing; if(thing->pos[VZ] + thing->height > tmFloorZ) tmFloorZ = thing->pos[VZ] + thing->height; return true; } } #endif return !solid; } /** * Adjusts tmFloorZ and tmCeilingZ as lines are contacted. */ boolean PIT_CheckLine(linedef_t* ld, void* data) { float bbox[4]; xline_t* xline; P_GetFloatpv(ld, DMU_BOUNDING_BOX, bbox); if(tmBBox[BOXRIGHT] <= bbox[BOXLEFT] || tmBBox[BOXLEFT] >= bbox[BOXRIGHT] || tmBBox[BOXTOP] <= bbox[BOXBOTTOM] || tmBBox[BOXBOTTOM] >= bbox[BOXTOP]) return true; if(P_BoxOnLineSide(tmBBox, ld) != -1) return true; // A line has been hit xline = P_ToXLine(ld); #if !__JHEXEN__ tmThing->wallHit = true; // A Hit event will be sent to special lines. if(xline->special) tmHitLine = ld; #endif if(!P_GetPtrp(ld, DMU_BACK_SECTOR)) // One sided line. { #if __JHEXEN__ if(tmThing->flags2 & MF2_BLASTED) P_DamageMobj(tmThing, NULL, NULL, tmThing->info->mass >> 5, false); checkForPushSpecial(ld, 0, tmThing); return false; #else float d1[2]; P_GetFloatpv(ld, DMU_DXY, d1); /** * $unstuck: allow player to move out of 1s wall, to prevent * sticking. The moving thing's destination position will cross the * given line. * If this should not be allowed, return false. * If the line is special, keep track of it to process later if the * move is proven ok. * * \note Specials are NOT sorted by order, so two special lines that * are only 8 units apart could be crossed in either order. */ blockLine = ld; return tmUnstuck && !untouched(ld) && ((tm[VX] - tmThing->pos[VX]) * d1[1]) > ((tm[VY] - tmThing->pos[VY]) * d1[0]); #endif } // \fixme Will never pass this test due to above. Is the previous check // supposed to qualify player mobjs only? #if __JHERETIC__ if(!P_GetPtrp(ld, DMU_BACK_SECTOR)) // one sided line { // One sided line if(tmThing->flags & MF_MISSILE) { // Missiles can trigger impact specials if(xline->special) P_AddObjectToIterList(spechit, ld); } return false; } #endif if(!(tmThing->flags & MF_MISSILE)) { // Explicitly blocking everything? if(P_GetIntp(ld, DMU_FLAGS) & DDLF_BLOCKING) { #if __JHEXEN__ if(tmThing->flags2 & MF2_BLASTED) P_DamageMobj(tmThing, NULL, NULL, tmThing->info->mass >> 5, false); checkForPushSpecial(ld, 0, tmThing); return false; #else // $unstuck: allow escape. return tmUnstuck && !untouched(ld); #endif } // Block monsters only? #if __JHEXEN__ if(!tmThing->player && tmThing->type != MT_CAMERA && (xline->flags & ML_BLOCKMONSTERS)) #elif __JHERETIC__ if(!tmThing->player && tmThing->type != MT_POD && (xline->flags & ML_BLOCKMONSTERS)) #else if(!tmThing->player && (xline->flags & ML_BLOCKMONSTERS)) #endif { #if __JHEXEN__ if(tmThing->flags2 & MF2_BLASTED) P_DamageMobj(tmThing, NULL, NULL, tmThing->info->mass >> 5, false); #endif return false; } } #if __JDOOM64__ if((tmThing->flags & MF_MISSILE)) { if(xline->flags & ML_BLOCKALL) // Explicitly blocking everything. return tmUnstuck && !untouched(ld); // $unstuck: allow escape. } #endif // Set OPENRANGE, OPENTOP, OPENBOTTOM. P_LineOpening(ld); // Adjust floor / ceiling heights. if(OPENTOP < tmCeilingZ) { tmCeilingZ = OPENTOP; ceilingLine = ld; #if !__JHEXEN__ blockLine = ld; #endif } if(OPENBOTTOM > tmFloorZ) { tmFloorZ = OPENBOTTOM; floorLine = ld; #if !__JHEXEN__ blockLine = ld; #endif } if(LOWFLOOR < tmDropoffZ) tmDropoffZ = LOWFLOOR; // If contacted a special line, add it to the list. if(P_ToXLine(ld)->special) P_AddObjectToIterList(spechit, ld); #if !__JHEXEN__ tmThing->wallHit = false; #endif return true; // Continue iteration. } /** * This is purely informative, nothing is modified (except things picked up). * * in: * a mobj_t (can be valid or invalid) * a position to be checked * (doesn't need to be related to the mobj_t->x,y) * * during: * special things are touched if MF_PICKUP early out on solid lines? * * out: * newsubsec * floorz * ceilingz * tmDropoffZ * the lowest point contacted * (monsters won't move to a drop off) * speciallines[] * numspeciallines */ boolean P_CheckPosition3f(mobj_t* thing, float x, float y, float z) { sector_t* newSec; float box[4]; tmThing = thing; #if !__JHEXEN__ thing->onMobj = NULL; thing->wallHit = false; tmHitLine = NULL; tmHeight = thing->height; #endif tm[VX] = x; tm[VY] = y; tm[VZ] = z; tmBBox[BOXTOP] = tm[VY] + tmThing->radius; tmBBox[BOXBOTTOM] = tm[VY] - tmThing->radius; tmBBox[BOXRIGHT] = tm[VX] + tmThing->radius; tmBBox[BOXLEFT] = tm[VX] - tmThing->radius; newSec = P_GetPtrp(R_PointInSubsector(tm[VX], tm[VY]), DMU_SECTOR); ceilingLine = floorLine = NULL; #if !__JHEXEN__ blockLine = NULL; tmUnstuck = ((thing->dPlayer && thing->dPlayer->mo == thing)? true : false); #endif // The base floor/ceiling is from the subsector that contains the point. // Any contacted lines the step closer together will adjust them. tmFloorZ = tmDropoffZ = P_GetFloatp(newSec, DMU_FLOOR_HEIGHT); tmCeilingZ = P_GetFloatp(newSec, DMU_CEILING_HEIGHT); #if __JHEXEN__ tmFloorMaterial = P_GetPtrp(newSec, DMU_FLOOR_MATERIAL); #endif P_EmptyIterList(spechit); #if __JHEXEN__ if((tmThing->flags & MF_NOCLIP) && !(tmThing->flags & MF_SKULLFLY)) return true; #else if((tmThing->flags & MF_NOCLIP)) return true; #endif // Check things first, possibly picking things up the bounding box is // extended by MAXRADIUS because mobj_ts are grouped into mapblocks // based on their origin point, and can overlap into adjacent blocks by // up to MAXRADIUS units. box[BOXLEFT] = tmBBox[BOXLEFT] - MAXRADIUS; box[BOXRIGHT] = tmBBox[BOXRIGHT] + MAXRADIUS; box[BOXBOTTOM] = tmBBox[BOXBOTTOM] - MAXRADIUS; box[BOXTOP] = tmBBox[BOXTOP] + MAXRADIUS; VALIDCOUNT++; // The camera goes through all objects. if(!P_MobjIsCamera(thing)) { #if __JHEXEN__ blockingMobj = NULL; #endif if(!P_MobjsBoxIterator(box, PIT_CheckThing, 0)) return false; #if _DEBUG if(thing->onMobj) Con_Message("thing->onMobj = %p (solid:%i)\n", thing->onMobj, (thing->onMobj->flags & MF_SOLID)!=0); #endif } // Check lines. #if __JHEXEN__ if(tmThing->flags & MF_NOCLIP) return true; blockingMobj = NULL; #endif box[BOXLEFT] = tmBBox[BOXLEFT]; box[BOXRIGHT] = tmBBox[BOXRIGHT]; box[BOXBOTTOM] = tmBBox[BOXBOTTOM]; box[BOXTOP] = tmBBox[BOXTOP]; return P_AllLinesBoxIterator(box, PIT_CheckLine, 0); } boolean P_CheckPosition3fv(mobj_t* thing, const float pos[3]) { return P_CheckPosition3f(thing, pos[VX], pos[VY], pos[VZ]); } boolean P_CheckPosition2f(mobj_t* thing, float x, float y) { return P_CheckPosition3f(thing, x, y, DDMAXFLOAT); } /** * Attempt to move to a new position, crossing special lines unless * MF_TELEPORT is set. $dropoff_fix */ #if __JHEXEN__ static boolean P_TryMove2(mobj_t* thing, float x, float y) #else static boolean P_TryMove2(mobj_t* thing, float x, float y, boolean dropoff) #endif { float oldpos[3]; int side, oldSide; linedef_t* ld; // $dropoff_fix: fellDown. floatOk = false; #if !__JHEXEN__ fellDown = false; #endif #if __JHEXEN__ if(!P_CheckPosition2f(thing, x, y)) #else if(!P_CheckPosition3f(thing, x, y, thing->pos[VZ])) #endif { #if __JHEXEN__ if(!blockingMobj || blockingMobj->player || !thing->player) { goto pushline; } else if(blockingMobj->pos[VZ] + blockingMobj->height - thing->pos[VZ] > 24 || (P_GetFloatp(blockingMobj->subsector, DMU_CEILING_HEIGHT) - (blockingMobj->pos[VZ] + blockingMobj->height) < thing->height) || (tmCeilingZ - (blockingMobj->pos[VZ] + blockingMobj->height) < thing->height)) { goto pushline; } #else # if __JHERETIC__ CheckMissileImpact(thing); # endif // Would we hit another thing or a solid wall? if(!thing->onMobj || thing->wallHit) return false; #endif } if(!(thing->flags & MF_NOCLIP)) { #if __JHEXEN__ if(tmCeilingZ - tmFloorZ < thing->height) { // Doesn't fit. goto pushline; } floatOk = true; if(!(thing->flags & MF_TELEPORT) && tmCeilingZ - thing->pos[VZ] < thing->height && thing->type != MT_LIGHTNING_CEILING && !(thing->flags2 & MF2_FLY)) { // Mobj must lower itself to fit. goto pushline; } #else // Possibly allow escape if otherwise stuck. boolean ret = (tmUnstuck && !(ceilingLine && untouched(ceilingLine)) && !(floorLine && untouched(floorLine))); if(tmCeilingZ - tmFloorZ < thing->height) return ret; // Doesn't fit. // Mobj must lower to fit. floatOk = true; if(!(thing->flags & MF_TELEPORT) && !(thing->flags2 & MF2_FLY) && tmCeilingZ - thing->pos[VZ] < thing->height) return ret; // Too big a step up. if(!(thing->flags & MF_TELEPORT) && !(thing->flags2 & MF2_FLY) # if __JHERETIC__ && thing->type != MT_MNTRFX2 // The Minotaur floor fire (MT_MNTRFX2) can step up any amount # endif ) { if(tmFloorZ - thing->pos[VZ] > 24) { # if __JHERETIC__ CheckMissileImpact(thing); # endif return ret; } } # if __JHERETIC__ if((thing->flags & MF_MISSILE) && tmFloorZ > thing->pos[VZ]) { CheckMissileImpact(thing); } # endif #endif if(thing->flags2 & MF2_FLY) { if(thing->pos[VZ] + thing->height > tmCeilingZ) { thing->mom[MZ] = -8; #if __JHEXEN__ goto pushline; #else return false; #endif } else if(thing->pos[VZ] < tmFloorZ && tmFloorZ - tmDropoffZ > 24) { thing->mom[MZ] = 8; #if __JHEXEN__ goto pushline; #else return false; #endif } } #if __JHEXEN__ if(!(thing->flags & MF_TELEPORT) // The Minotaur floor fire (MT_MNTRFX2) can step up any amount && thing->type != MT_MNTRFX2 && thing->type != MT_LIGHTNING_FLOOR && tmFloorZ - thing->pos[VZ] > 24) { goto pushline; } #endif #if __JHEXEN__ if(!(thing->flags & (MF_DROPOFF | MF_FLOAT)) && (tmFloorZ - tmDropoffZ > 24) && !(thing->flags2 & MF2_BLASTED)) { // Can't move over a dropoff unless it's been blasted. return false; } #else /** * Allow certain objects to drop off. * Prevent monsters from getting stuck hanging off ledges. * Allow dropoffs in controlled circumstances. * Improve symmetry of clipping on stairs. */ if(!(thing->flags & (MF_DROPOFF | MF_FLOAT))) { // Dropoff height limit. if(cfg.avoidDropoffs) { if(tmFloorZ - tmDropoffZ > 24) return false; // Don't stand over dropoff. } else { float floorZ = tmFloorZ; if(thing->onMobj) { // Thing is stood on something so use our z position // as the floor. floorZ = (thing->pos[VZ] > tmFloorZ ? thing->pos[VZ] : tmFloorZ); } if(!dropoff) { if(thing->floorZ - floorZ > 24 || thing->dropOffZ - tmDropoffZ > 24) return false; } else { // Set fellDown if drop > 24. fellDown = !(thing->flags & MF_NOGRAVITY) && thing->pos[VZ] - floorZ > 24; } } } #endif #if __JDOOM64__ //// \fixme DJS - FIXME! Mother demon fire attack. if(!(thing->flags & MF_TELEPORT) /*&& thing->type != MT_SPAWNFIRE*/ && tmFloorZ - thing->pos[VZ] > 24) { // Too big a step up CheckMissileImpact(thing); return false; } #endif #if __JHEXEN__ // Must stay within a sector of a certain floor type? if((thing->flags2 & MF2_CANTLEAVEFLOORPIC) && (tmFloorMaterial != P_GetPtrp(thing->subsector, DMU_FLOOR_MATERIAL) || tmFloorZ - thing->pos[VZ] != 0)) { return false; } #endif #if !__JHEXEN__ // $dropoff: prevent falling objects from going up too many steps. if(!thing->player && (thing->intFlags & MIF_FALLING) && tmFloorZ - thing->pos[VZ] > (thing->mom[MX] * thing->mom[MX]) + (thing->mom[MY] * thing->mom[MY])) { return false; } #endif } // The move is ok, so link the thing into its new position. P_MobjUnsetPosition(thing); oldpos[VX] = thing->pos[VX]; oldpos[VY] = thing->pos[VY]; oldpos[VZ] = thing->pos[VZ]; thing->floorZ = tmFloorZ; thing->ceilingZ = tmCeilingZ; #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ thing->dropOffZ = tmDropoffZ; // $dropoff_fix: keep track of dropoffs. #endif thing->pos[VX] = x; thing->pos[VY] = y; P_MobjSetPosition(thing); if(thing->flags2 & MF2_FLOORCLIP) { thing->floorClip = 0; if(thing->pos[VZ] == P_GetFloatp(thing->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(thing); if(tt->flags & TTF_FLOORCLIP) { thing->floorClip = 10; } } } // If any special lines were hit, do the effect. if(!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) { while((ld = P_PopIterList(spechit)) != NULL) { // See if the line was crossed. if(P_ToXLine(ld)->special) { side = P_PointOnLinedefSide(thing->pos[VX], thing->pos[VY], ld); oldSide = P_PointOnLinedefSide(oldpos[VX], oldpos[VY], ld); if(side != oldSide) { #if __JHEXEN__ if(thing->player) { P_ActivateLine(ld, thing, oldSide, SPAC_CROSS); } else if(thing->flags2 & MF2_MCROSS) { P_ActivateLine(ld, thing, oldSide, SPAC_MCROSS); } else if(thing->flags2 & MF2_PCROSS) { P_ActivateLine(ld, thing, oldSide, SPAC_PCROSS); } #else P_ActivateLine(ld, thing, oldSide, SPAC_CROSS); #endif } } } } return true; #if __JHEXEN__ pushline: if(!(thing->flags & (MF_TELEPORT | MF_NOCLIP))) { if(tmThing->flags2 & MF2_BLASTED) { P_DamageMobj(tmThing, NULL, NULL, tmThing->info->mass >> 5, false); } P_IterListResetIterator(spechit, false); while((ld = P_IterListIterator(spechit)) != NULL) { // See if the line was crossed. side = P_PointOnLinedefSide(thing->pos[VX], thing->pos[VY], ld); checkForPushSpecial(ld, side, thing); } } return false; #endif } #if __JHEXEN__ boolean P_TryMove(mobj_t* thing, float x, float y) #else boolean P_TryMove(mobj_t* thing, float x, float y, boolean dropoff, boolean slide) #endif { #if __JHEXEN__ return P_TryMove2(thing, x, y); #else // $dropoff_fix boolean res = P_TryMove2(thing, x, y, dropoff); if(!res && tmHitLine) { // Move not possible, see if the thing hit a line and send a Hit // event to it. XL_HitLine(tmHitLine, P_PointOnLinedefSide(thing->pos[VX], thing->pos[VY], tmHitLine), thing); } if(res && slide) thing->wallRun = true; return res; #endif } /** * \fixme DJS - This routine has gotten way too big, split if(in->isaline) * to a seperate routine? */ boolean PTR_ShootTraverse(intercept_t* in) { #if __JHEXEN__ extern mobj_t lavaInflictor; #endif int divisor; float pos[3], frac, slope, dist, thingTopSlope, thingBottomSlope, cTop, cBottom, d[3], step, stepv[3], tracePos[3], cFloor, cCeil; linedef_t* li; mobj_t* th; divline_t* trace = (divline_t *) DD_GetVariable(DD_TRACE_ADDRESS); sector_t* frontSec = NULL, *backSec = NULL; subsector_t* contact, *originSub; xline_t* xline; boolean lineWasHit; tracePos[VX] = FIX2FLT(trace->pos[VX]); tracePos[VY] = FIX2FLT(trace->pos[VY]); tracePos[VZ] = shootZ; if(in->type == ICPT_LINE) { li = in->d.lineDef; xline = P_ToXLine(li); frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR); backSec = P_GetPtrp(li, DMU_BACK_SECTOR); if(!backSec && P_PointOnLinedefSide(tracePos[VX], tracePos[VY], li)) return true; // Continue traversal. if(xline->special) P_ActivateLine(li, shootThing, 0, SPAC_IMPACT); if(!backSec) goto hitline; #if __JDOOM64__ if(xline->flags & ML_BLOCKALL) // jd64 goto hitline; #endif // Crosses a two sided line. P_LineOpening(li); dist = attackRange * in->frac; if(P_GetFloatp(frontSec, DMU_FLOOR_HEIGHT) != P_GetFloatp(backSec, DMU_FLOOR_HEIGHT)) { slope = (OPENBOTTOM - tracePos[VZ]) / dist; if(slope > aimSlope) goto hitline; } if(P_GetFloatp(frontSec, DMU_CEILING_HEIGHT) != P_GetFloatp(backSec, DMU_CEILING_HEIGHT)) { slope = (OPENTOP - tracePos[VZ]) / dist; if(slope < aimSlope) goto hitline; } // Shot continues... return true; // Hit a line. hitline: // Position a bit closer. frac = in->frac - (4 / attackRange); pos[VX] = tracePos[VX] + (FIX2FLT(trace->dX) * frac); pos[VY] = tracePos[VY] + (FIX2FLT(trace->dY) * frac); pos[VZ] = tracePos[VZ] + (aimSlope * (frac * attackRange)); if(backSec) { // Is it a sky hack wall? If the hitpoint is beyond the visible // surface, no puff must be shown. if((P_GetIntp(P_GetPtrp(frontSec, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) && (pos[VZ] > P_GetFloatp(frontSec, DMU_CEILING_HEIGHT) || pos[VZ] > P_GetFloatp(backSec, DMU_CEILING_HEIGHT))) return false; if((P_GetIntp(P_GetPtrp(backSec, DMU_FLOOR_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) && (pos[VZ] < P_GetFloatp(frontSec, DMU_FLOOR_HEIGHT) || pos[VZ] < P_GetFloatp(backSec, DMU_FLOOR_HEIGHT))) return false; } lineWasHit = true; // This is the subsector where the trace originates. originSub = R_PointInSubsector(tracePos[VX], tracePos[VY]); d[VX] = pos[VX] - tracePos[VX]; d[VY] = pos[VY] - tracePos[VY]; d[VZ] = pos[VZ] - tracePos[VZ]; if(!INRANGE_OF(d[VZ], 0, .0001f)) // Epsilon { contact = R_PointInSubsector(pos[VX], pos[VY]); step = P_ApproxDistance3(d[VX], d[VY], d[VZ]); stepv[VX] = d[VX] / step; stepv[VY] = d[VY] / step; stepv[VZ] = d[VZ] / step; cFloor = P_GetFloatp(contact, DMU_FLOOR_HEIGHT); cCeil = P_GetFloatp(contact, DMU_CEILING_HEIGHT); // Backtrack until we find a non-empty sector. while(cCeil <= cFloor && contact != originSub) { d[VX] -= 8 * stepv[VX]; d[VY] -= 8 * stepv[VY]; d[VZ] -= 8 * stepv[VZ]; pos[VX] = tracePos[VX] + d[VX]; pos[VY] = tracePos[VY] + d[VY]; pos[VZ] = tracePos[VZ] + d[VZ]; contact = R_PointInSubsector(pos[VX], pos[VY]); } // Should we backtrack to hit a plane instead? cTop = cCeil - 4; cBottom = cFloor + 4; divisor = 2; // We must not hit a sky plane. if(pos[VZ] > cTop && (P_GetIntp(P_GetPtrp(contact, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK)) return false; if(pos[VZ] < cBottom && (P_GetIntp(P_GetPtrp(contact, DMU_FLOOR_MATERIAL), DMU_FLAGS) & MATF_SKYMASK)) return false; // Find the approximate hitpoint by stepping back and // forth using smaller and smaller steps. while((pos[VZ] > cTop || pos[VZ] < cBottom) && divisor <= 128) { // We aren't going to hit a line any more. lineWasHit = false; // Take a step backwards. pos[VX] -= d[VX] / divisor; pos[VY] -= d[VY] / divisor; pos[VZ] -= d[VZ] / divisor; // Divisor grows. divisor *= 2; // Move forward until limits breached. while((d[VZ] > 0 && pos[VZ] <= cTop) || (d[VZ] < 0 && pos[VZ] >= cBottom)) { pos[VX] += d[VX] / divisor; pos[VY] += d[VY] / divisor; pos[VZ] += d[VZ] / divisor; } } } // Spawn bullet puffs. P_SpawnPuff(pos[VX], pos[VY], pos[VZ], P_Random() << 24); #if !__JHEXEN__ if(lineWasHit && xline->special) { // Extended shoot events only happen when the bullet actually // hits the line. XL_ShootLine(li, 0, shootThing); } /* if(lineWasHit) Con_Message("Hit line [%i,%i]\n", P_GetIntp(li, DMU_SIDEDEF0), P_GetIntp(li, DMU_SIDEDEF1)); */ #endif // Don't go any farther. return false; } // Shot a mobj. th = in->d.mo; if(th == shootThing) return true; // Can't shoot self. if(!(th->flags & MF_SHOOTABLE)) return true; // Corpse or something. #if __JHERETIC__ // Check for physical attacks on a ghost. if((th->flags & MF_SHADOW) && shootThing->player->readyWeapon == WT_FIRST) return true; #endif // Check angles to see if the thing can be aimed at dist = attackRange * in->frac; { float dz = th->pos[VZ]; if(!(th->player && (th->player->plr->flags & DDPF_CAMERA))) dz += th->height; dz -= tracePos[VZ]; thingTopSlope = dz / dist; } if(thingTopSlope < aimSlope) return true; // Shot over the thing. thingBottomSlope = (th->pos[VZ] - tracePos[VZ]) / dist; if(thingBottomSlope > aimSlope) return true; // Shot under the thing. // Hit thing. // Position a bit closer. frac = in->frac - (10 / attackRange); pos[VX] = tracePos[VX] + (FIX2FLT(trace->dX) * frac); pos[VY] = tracePos[VY] + (FIX2FLT(trace->dY) * frac); pos[VZ] = tracePos[VZ] + (aimSlope * (frac * attackRange)); // Spawn bullet puffs or blood spots, depending on target type. #if __JHERETIC__ if(puffType == MT_BLASTERPUFF1) { // Make blaster big puff. mobj_t* mo; if((mo = P_SpawnMobj3fv(MT_BLASTERPUFF2, pos, P_Random() << 24, 0))) S_StartSound(SFX_BLSHIT, mo); } else P_SpawnPuff(pos[VX], pos[VY], pos[VZ], P_Random() << 24); #elif __JHEXEN__ P_SpawnPuff(pos[VX], pos[VY], pos[VZ], P_Random() << 24); #endif if(lineAttackDamage) { int damageDone; #if __JDOOM__ || __JDOOM64__ angle_t attackAngle = R_PointToAngle2(shootThing->pos[VX], shootThing->pos[VY], pos[VX], pos[VY]); #endif #if __JHEXEN__ if(PuffType == MT_FLAMEPUFF2) { // Cleric FlameStrike does fire damage. damageDone = P_DamageMobj(th, &lavaInflictor, shootThing, lineAttackDamage, false); } else #endif { damageDone = P_DamageMobj(th, shootThing, shootThing, lineAttackDamage, false); } #if __JHEXEN__ if(!(in->d.mo->flags2 & MF2_INVULNERABLE)) #endif { if(!(in->d.mo->flags & MF_NOBLOOD)) { if(damageDone > 0) { // Damage was inflicted, so shed some blood. #if __JDOOM__ || __JDOOM64__ P_SpawnBlood(pos[VX], pos[VY], pos[VZ], lineAttackDamage, attackAngle + ANG180); #else # if __JHEXEN__ if(PuffType == MT_AXEPUFF || PuffType == MT_AXEPUFF_GLOW) { P_SpawnBloodSplatter2(pos[VX], pos[VY], pos[VZ], in->d.mo); } else # endif if(P_Random() < 192) P_SpawnBloodSplatter(pos[VX], pos[VY], pos[VZ], in->d.mo); #endif } } #if __JDOOM__ || __JDOOM64__ else P_SpawnPuff(pos[VX], pos[VY], pos[VZ], P_Random() << 24); #endif } } // Don't go any farther. return false; } /** * Sets linetarget and aimSlope when a target is aimed at. */ boolean PTR_AimTraverse(intercept_t* in) { float slope, thingTopSlope, thingBottomSlope, dist; mobj_t* th; linedef_t* li; sector_t* backSec, *frontSec; if(in->type == ICPT_LINE) { float fFloor, bFloor; float fCeil, bCeil; li = in->d.lineDef; if(!(frontSec = P_GetPtrp(li, DMU_FRONT_SECTOR)) || !(backSec = P_GetPtrp(li, DMU_BACK_SECTOR))) { float tracePos[3]; divline_t* trace = (divline_t *) DD_GetVariable(DD_TRACE_ADDRESS); tracePos[VX] = FIX2FLT(trace->pos[VX]); tracePos[VY] = FIX2FLT(trace->pos[VY]); tracePos[VZ] = shootZ; if(P_PointOnLinedefSide(tracePos[VX], tracePos[VY], li)) return true; // Continue traversal. return false; // Stop. } // Crosses a two sided line. // A two sided line will restrict the possible target ranges. P_LineOpening(li); if(OPENBOTTOM >= OPENTOP) return false; // Stop. dist = attackRange * in->frac; fFloor = P_GetFloatp(frontSec, DMU_FLOOR_HEIGHT); fCeil = P_GetFloatp(frontSec, DMU_CEILING_HEIGHT); bFloor = P_GetFloatp(backSec, DMU_FLOOR_HEIGHT); bCeil = P_GetFloatp(backSec, DMU_CEILING_HEIGHT); if(fFloor != bFloor) { slope = (OPENBOTTOM - shootZ) / dist; if(slope > bottomSlope) bottomSlope = slope; } if(fCeil != bCeil) { slope = (OPENTOP - shootZ) / dist; if(slope < topSlope) topSlope = slope; } if(topSlope <= bottomSlope) return false; // Stop. return true; // Shot continues... } // Shot a mobj. th = in->d.mo; if(th == shootThing) return true; // Can't shoot self. if(!(th->flags & MF_SHOOTABLE)) return true; // Corpse or something? #if __JHERETIC__ if(th->type == MT_POD) return true; // Can't auto-aim at pods. #endif #if __JDOOM__ || __JHEXEN__ || __JDOOM64__ if(th->player && IS_NETGAME && !deathmatch) return true; // Don't aim at fellow co-op players. #endif // Check angles to see if the thing can be aimed at. dist = attackRange * in->frac; { float posZ = th->pos[VZ]; if(!(th->player && (th->player->plr->flags & DDPF_CAMERA))) posZ += th->height; thingTopSlope = (posZ - shootZ) / dist; if(thingTopSlope < bottomSlope) return true; // Shot over the thing. // Too far below? // $addtocfg $limitautoaimZ: #if __JHEXEN__ if(posZ < shootZ - attackRange / 1.2f) return true; #endif } thingBottomSlope = (th->pos[VZ] - shootZ) / dist; if(thingBottomSlope > topSlope) return true; // Shot under the thing. // Too far above? // $addtocfg $limitautoaimZ: #if __JHEXEN__ if(th->pos[VZ] > shootZ + attackRange / 1.2f) return true; #endif // This thing can be hit! if(thingTopSlope > topSlope) thingTopSlope = topSlope; if(thingBottomSlope < bottomSlope) thingBottomSlope = bottomSlope; aimSlope = (thingTopSlope + thingBottomSlope) / 2; lineTarget = th; return false; // Don't go any farther. } float P_AimLineAttack(mobj_t *t1, angle_t angle, float distance) { uint an; float pos[2]; an = angle >> ANGLETOFINESHIFT; shootThing = t1; pos[VX] = t1->pos[VX] + distance * FIX2FLT(finecosine[an]); pos[VY] = t1->pos[VY] + distance * FIX2FLT(finesine[an]); // Determine the z trace origin. shootZ = t1->pos[VZ]; #if __JHEXEN__ if(t1->player && (t1->player->class == PCLASS_FIGHTER || t1->player->class == PCLASS_CLERIC || t1->player->class == PCLASS_MAGE)) #else if(t1->player && t1->type == MT_PLAYER) #endif { if(!(t1->player->plr->flags & DDPF_CAMERA)) shootZ += (cfg.plrViewHeight - 5); } else shootZ += (t1->height / 2) + 8; #if __JDOOM__ || __JDOOM64__ topSlope = 60; bottomSlope = -topSlope; #else topSlope = 100; bottomSlope = -100; #endif attackRange = distance; lineTarget = NULL; P_PathTraverse(t1->pos[VX], t1->pos[VY], pos[VX], pos[VY], PT_ADDLINES | PT_ADDMOBJS, PTR_AimTraverse); if(lineTarget) { // While autoaiming, we accept this slope. if(!t1->player || !cfg.noAutoAim) return aimSlope; } if(t1->player && cfg.noAutoAim) { // The slope is determined by lookdir. return tan(LOOKDIR2RAD(t1->dPlayer->lookDir)) / 1.2; } return 0; } /** * If damage == 0, it is just a test trace that will leave lineTarget set. */ void P_LineAttack(mobj_t* t1, angle_t angle, float distance, float slope, int damage) { uint an; float targetPos[2]; an = angle >> ANGLETOFINESHIFT; shootThing = t1; lineAttackDamage = damage; targetPos[VX] = t1->pos[VX] + distance * FIX2FLT(finecosine[an]); targetPos[VY] = t1->pos[VY] + distance * FIX2FLT(finesine[an]); // Determine the z trace origin. shootZ = t1->pos[VZ]; #if __JHEXEN__ if(t1->player && (t1->player->class == PCLASS_FIGHTER || t1->player->class == PCLASS_CLERIC || t1->player->class == PCLASS_MAGE)) #else if(t1->player && t1->type == MT_PLAYER) #endif { if(!(t1->player->plr->flags & DDPF_CAMERA)) shootZ += cfg.plrViewHeight - 5; } else shootZ += (t1->height / 2) + 8; shootZ -= t1->floorClip; attackRange = distance; aimSlope = slope; if(P_PathTraverse(t1->pos[VX], t1->pos[VY], targetPos[VX], targetPos[VY], PT_ADDLINES | PT_ADDMOBJS, PTR_ShootTraverse)) { #if __JHEXEN__ switch(PuffType) { case MT_PUNCHPUFF: S_StartSound(SFX_FIGHTER_PUNCH_MISS, t1); break; case MT_HAMMERPUFF: case MT_AXEPUFF: case MT_AXEPUFF_GLOW: S_StartSound(SFX_FIGHTER_HAMMER_MISS, t1); break; case MT_FLAMEPUFF: P_SpawnPuff(targetPos[VX], targetPos[VY], shootZ + (slope * distance), P_Random() << 24); break; default: break; } #endif } } /** * "bombSource" is the creature that caused the explosion at "bombSpot". */ boolean PIT_RadiusAttack(mobj_t* thing, void* data) { float dx, dy, dz, dist; if(!(thing->flags & MF_SHOOTABLE)) return true; // Boss spider and cyborg take no damage from concussion. #if __JHERETIC__ if(thing->type == MT_MINOTAUR || thing->type == MT_SORCERER1 || thing->type == MT_SORCERER2) return true; #elif __JDOOM__ || __JDOOM64__ if(thing->type == MT_CYBORG) return true; # if __JDOOM__ if(thing->type == MT_SPIDER) return true; # endif #endif #if __JHEXEN__ if(!damageSource && thing == bombSource) // Don't damage the source of the explosion. return true; #endif dx = fabs(thing->pos[VX] - bombSpot->pos[VX]); dy = fabs(thing->pos[VY] - bombSpot->pos[VY]); dz = fabs((thing->pos[VZ] + thing->height / 2) - bombSpot->pos[VZ]); dist = (dx > dy? dx : dy); #if __JHEXEN__ if(!cfg.netNoMaxZRadiusAttack) dist = (dz > dist? dz : dist); #else if(!(cfg.netNoMaxZRadiusAttack || (thing->info->flags2 & MF2_INFZBOMBDAMAGE))) dist = (dz > dist? dz : dist); #endif dist = (dist - thing->radius); if(dist < 0) dist = 0; if(dist >= bombDistance) return true; // Out of range. // Must be in direct path. if(P_CheckSight(thing, bombSpot)) { int damage; damage = (bombDamage * (bombDistance - dist) / bombDistance) + 1; #if __JHEXEN__ if(thing->player) damage /= 4; #endif P_DamageMobj(thing, bombSpot, bombSource, damage, false); } return true; } /** * Source is the creature that caused the explosion at spot. */ #if __JHEXEN__ void P_RadiusAttack(mobj_t* spot, mobj_t* source, int damage, int distance, boolean canDamageSource) #else void P_RadiusAttack(mobj_t* spot, mobj_t* source, int damage, int distance) #endif { float dist; float box[4]; dist = distance + MAXRADIUS; box[BOXLEFT] = spot->pos[VX] - dist; box[BOXRIGHT] = spot->pos[VX] + dist; box[BOXBOTTOM] = spot->pos[VY] - dist; box[BOXTOP] = spot->pos[VY] + dist; bombSpot = spot; bombDamage = damage; bombDistance = distance; #if __JHERETIC__ if(spot->type == MT_POD && spot->target) bombSource = spot->target; else #endif bombSource = source; #if __JHEXEN__ damageSource = canDamageSource; #endif VALIDCOUNT++; P_MobjsBoxIterator(box, PIT_RadiusAttack, 0); } boolean PTR_UseTraverse(intercept_t* in) { int side; xline_t* xline; if(in->type != ICPT_LINE) return true; // Continue iteration. xline = P_ToXLine(in->d.lineDef); if(!xline->special) { P_LineOpening(in->d.lineDef); if(OPENRANGE <= 0) { if(useThing->player) S_StartSound(PCLASS_INFO(useThing->player->class)->failUseSound, useThing); return false; // Can't use through a wall. } #if __JHEXEN__ if(useThing->player) { float pheight = useThing->pos[VZ] + useThing->height/2; if((OPENTOP < pheight) || (OPENBOTTOM > pheight)) S_StartSound(PCLASS_INFO(useThing->player->class)->failUseSound, useThing); } #endif // Not a special line, but keep checking. return true; } side = 0; if(1 == P_PointOnLinedefSide(useThing->pos[VX], useThing->pos[VY], in->d.lineDef)) side = 1; #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ if(side == 1) return false; // don't use back side #endif P_ActivateLine(in->d.lineDef, useThing, side, SPAC_USE); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Can use multiple line specials in a row with the PassThru flag. if(xline->flags & ML_PASSUSE) return true; #endif // Can't use more than one special line in a row. return false; } /** * Looks for special lines in front of the player to activate. * * @param player The player to test. */ void P_UseLines(player_t* player) { uint an; float pos[3]; mobj_t* mo; if(IS_CLIENT) { #ifdef _DEBUG Con_Message("P_UseLines: Sending a use request for player %i.\n", player - players); #endif NetCl_PlayerActionRequest(player, GPA_USE); return; } useThing = mo = player->plr->mo; an = mo->angle >> ANGLETOFINESHIFT; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += USERANGE * FIX2FLT(finecosine[an]); pos[VY] += USERANGE * FIX2FLT(finesine[an]); P_PathTraverse(mo->pos[VX], mo->pos[VY], pos[VX], pos[VY], PT_ADDLINES, PTR_UseTraverse); } /** * Takes a valid thing and adjusts the thing->floorZ, thing->ceilingZ, * and possibly thing->pos[VZ]. * * This is called for all nearby monsters whenever a sector changes height * If the thing doesn't fit, the z will be set to the lowest value and * false will be returned * * @param thing The mobj whoose position to adjust. * @return @c true, if the thing did fit. */ static boolean P_ThingHeightClip(mobj_t* thing) { boolean onfloor; if(P_MobjIsCamera(thing)) return false; // Don't height clip cameras. onfloor = (thing->pos[VZ] == thing->floorZ)? true : false; P_CheckPosition3fv(thing, thing->pos); thing->floorZ = tmFloorZ; thing->ceilingZ = tmCeilingZ; #if !__JHEXEN__ thing->dropOffZ = tmDropoffZ; // $dropoff_fix: remember dropoffs. #endif if(onfloor) { #if __JHEXEN__ if((thing->pos[VZ] - thing->floorZ < 9) || (thing->flags & MF_NOGRAVITY)) { thing->pos[VZ] = thing->floorZ; } #else // Update view offset of real players $voodoodolls. if(thing->player && thing->player->plr->mo == thing) thing->player->viewZ += thing->floorZ - thing->pos[VZ]; // Walking monsters rise and fall with the floor. thing->pos[VZ] = thing->floorZ; // $dropoff_fix: Possibly upset balance of objects hanging off ledges. if((thing->intFlags & MIF_FALLING) && thing->gear >= MAXGEAR) thing->gear = 0; #endif } else { // Don't adjust a floating monster unless forced to. if(thing->pos[VZ] + thing->height > thing->ceilingZ) thing->pos[VZ] = thing->ceilingZ - thing->height; } if(thing->ceilingZ - thing->floorZ >= thing->height) return true; return false; } /** * Allows the player to slide along any angled walls by adjusting the * xmove / ymove so that the NEXT move will slide along the wall. * * @param ld The line being slid along. */ static void P_HitSlideLine(linedef_t* ld) { int side; unsigned int an; angle_t lineAngle, moveAngle, deltaAngle; float moveLen, newLen, d1[2]; slopetype_t slopeType = P_GetIntp(ld, DMU_SLOPE_TYPE); if(slopeType == ST_HORIZONTAL) { tmMove[MY] = 0; return; } else if(slopeType == ST_VERTICAL) { tmMove[MX] = 0; return; } side = P_PointOnLinedefSide(slideMo->pos[VX], slideMo->pos[VY], ld); P_GetFloatpv(ld, DMU_DXY, d1); lineAngle = R_PointToAngle2(0, 0, d1[0], d1[1]); moveAngle = R_PointToAngle2(0, 0, tmMove[MX], tmMove[MY]); if(side == 1) lineAngle += ANG180; deltaAngle = moveAngle - lineAngle; if(deltaAngle > ANG180) deltaAngle += ANG180; moveLen = P_ApproxDistance(tmMove[MX], tmMove[MY]); an = deltaAngle >> ANGLETOFINESHIFT; newLen = moveLen * FIX2FLT(finecosine[an]); an = lineAngle >> ANGLETOFINESHIFT; tmMove[MX] = newLen * FIX2FLT(finecosine[an]); tmMove[MY] = newLen * FIX2FLT(finesine[an]); } boolean PTR_SlideTraverse(intercept_t* in) { linedef_t* li; if(in->type != ICPT_LINE) Con_Error("PTR_SlideTraverse: Not a line?"); li = in->d.lineDef; if(!P_GetPtrp(li, DMU_FRONT_SECTOR) || !P_GetPtrp(li, DMU_BACK_SECTOR)) { if(P_PointOnLinedefSide(slideMo->pos[VX], slideMo->pos[VY], li)) return true; // Don't hit the back side. goto isblocking; } #if __JDOOM64__ if(P_ToXLine(li)->flags & ML_BLOCKALL) // jd64 goto isblocking; #endif P_LineOpening(li); // Set OPENRANGE, OPENTOP, OPENBOTTOM... if(OPENRANGE < slideMo->height) goto isblocking; // Doesn't fit. if(OPENTOP - slideMo->pos[VZ] < slideMo->height) goto isblocking; // mobj is too high. if(OPENBOTTOM - slideMo->pos[VZ] > 24) goto isblocking; // Too big a step up. // This line doesn't block movement. return true; // The line does block movement, see if it is closer than best so far. isblocking: if(in->frac < bestSlideFrac) { secondSlideFrac = bestSlideFrac; secondSlideLine = bestSlideLine; bestSlideFrac = in->frac; bestSlideLine = li; } return false; // Stop. } /** * \fixme The momx / momy move is bad, so try to slide along a wall. * Find the first line hit, move flush to it, and slide along it * * This is a kludgy mess. * * @param mo The mobj to attempt the slide move. */ void P_SlideMove(mobj_t* mo) { int hitcount = 3; slideMo = mo; do { float leadpos[3], trailpos[3], newPos[3]; if(--hitcount == 0) goto stairstep; // Don't loop forever. // Trace along the three leading corners. leadpos[VX] = trailpos[VX] = mo->pos[VX]; leadpos[VY] = trailpos[VY] = mo->pos[VY]; leadpos[VZ] = trailpos[VZ] = mo->pos[VZ]; if(mo->mom[MX] > 0) { leadpos[VX] += mo->radius; trailpos[VX] -= mo->radius; } else { leadpos[VX] -= mo->radius; trailpos[VX] += mo->radius; } if(mo->mom[MY] > 0) { leadpos[VY] += mo->radius; trailpos[VY] -= mo->radius; } else { leadpos[VY] -= mo->radius; trailpos[VY] += mo->radius; } bestSlideFrac = 1; P_PathTraverse(leadpos[VX], leadpos[VY], leadpos[VX] + mo->mom[MX], leadpos[VY] + mo->mom[MY], PT_ADDLINES, PTR_SlideTraverse); P_PathTraverse(trailpos[VX], leadpos[VY], trailpos[VX] + mo->mom[MX], leadpos[VY] + mo->mom[MY], PT_ADDLINES, PTR_SlideTraverse); P_PathTraverse(leadpos[VX], trailpos[VY], leadpos[VX] + mo->mom[MX], trailpos[VY] + mo->mom[MY], PT_ADDLINES, PTR_SlideTraverse); // Move up to the wall. if(bestSlideFrac == 1) { // The move must have hit the middle, so stairstep. $dropoff_fix stairstep: /** * Ideally we would set the directional momentum of the mobj to zero * here should a move fail (to prevent noticeable stuttering against * the blocking surface/thing). However due to the mechanics of the * wall side algorithm this is not possible as it results in highly * unpredictable behaviour and resulting in the player sling-shoting * away from the wall. */ #if __JHEXEN__ if(!P_TryMove(mo, mo->pos[VX], mo->pos[VY] + mo->mom[MY])) P_TryMove(mo, mo->pos[VX] + mo->mom[MX], mo->pos[VY]); #else if(!P_TryMove(mo, mo->pos[VX], mo->pos[VY] + mo->mom[MY], true, true)) P_TryMove(mo, mo->pos[VX] + mo->mom[MX], mo->pos[VY], true, true); #endif break; } // Fudge a bit to make sure it doesn't hit. bestSlideFrac -= (1.0f / 32); if(bestSlideFrac > 0) { newPos[VX] = mo->mom[MX] * bestSlideFrac; newPos[VY] = mo->mom[MY] * bestSlideFrac; newPos[VZ] = DDMAXFLOAT; // Just initialize with *something*. // $dropoff_fix: Allow objects to drop off ledges #if __JHEXEN__ if(!P_TryMove(mo, mo->pos[VX] + newPos[VX], mo->pos[VY] + newPos[VY])) goto stairstep; #else if(!P_TryMove(mo, mo->pos[VX] + newPos[VX], mo->pos[VY] + newPos[VY], true, true)) goto stairstep; #endif } // Now continue along the wall. // First calculate remainder. bestSlideFrac = 1 - (bestSlideFrac + (1.0f / 32)); if(bestSlideFrac > 1) bestSlideFrac = 1; if(bestSlideFrac <= 0) break; tmMove[MX] = mo->mom[MX] * bestSlideFrac; tmMove[MY] = mo->mom[MY] * bestSlideFrac; P_HitSlideLine(bestSlideLine); // Clip the move. mo->mom[MX] = tmMove[MX]; mo->mom[MY] = tmMove[MY]; // $dropoff_fix: Allow objects to drop off ledges: #if __JHEXEN__ } while(!P_TryMove(mo, mo->pos[VX] + tmMove[MX], mo->pos[VY] + tmMove[MY])); #else } while(!P_TryMove(mo, mo->pos[VX] + tmMove[MX], mo->pos[VY] + tmMove[MY], true, true)); #endif } /** * SECTOR HEIGHT CHANGING * After modifying a sectors floor or ceiling height, call this routine * to adjust the positions of all things that touch the sector. * * If anything doesn't fit anymore, true will be returned. * If crunch is true, they will take damage as they are being crushed. * If Crunch is false, you should set the sector height back the way it * was and call P_ChangeSector again to undo the changes. */ /** * @param thing The thing to check against height changes. * @param data Unused. */ boolean PIT_ChangeSector(mobj_t* thing, void* data) { mobj_t* mo; // Don't check things that aren't blocklinked (supposedly immaterial). if(thing->info->flags & MF_NOBLOCKMAP) return true; if(P_ThingHeightClip(thing)) return true; // Keep checking... // Crunch bodies to giblets. #if __JDOOM__ || __JDOOM64__ if(thing->health <= 0 && !(thing->flags & MF_NOBLOOD)) #elif __JHEXEN__ if(thing->health <= 0 && (thing->flags & MF_CORPSE)) #else if(thing->health <= 0) #endif { #if __JHEXEN__ if(thing->flags & MF_NOBLOOD) { P_MobjRemove(thing, false); } else { if(thing->state != &STATES[S_GIBS1]) { P_MobjChangeState(thing, S_GIBS1); thing->height = 0; thing->radius = 0; S_StartSound(SFX_PLAYER_FALLING_SPLAT, thing); } } #else # if __JDOOM64__ S_StartSound(SFX_SLOP, thing); # endif # if __JDOOM__ || __JDOOM64__ P_MobjChangeState(thing, S_GIBS); # endif thing->flags &= ~MF_SOLID; thing->height = 0; thing->radius = 0; #endif return true; // Keep checking... } // Crunch dropped items. #if __JHEXEN__ if(thing->flags2 & MF2_DROPPED) #else if(thing->flags & MF_DROPPED) #endif { P_MobjRemove(thing, false); return true; // Keep checking... } if(!(thing->flags & MF_SHOOTABLE)) return true; // Keep checking... noFit = true; if(crushChange > 0 && !(mapTime & 3)) { #if __JHEXEN__ P_DamageMobj(thing, NULL, NULL, crushChange, false); #else P_DamageMobj(thing, NULL, NULL, 10, false); #endif #if __JDOOM__ || __JDOOM64__ if(!(thing->flags & MF_NOBLOOD)) #elif __JHEXEN__ if(!(thing->flags & MF_NOBLOOD) && !(thing->flags2 & MF2_INVULNERABLE)) #endif { // Spray blood in a random direction. if((mo = P_SpawnMobj3f(MT_BLOOD, thing->pos[VX], thing->pos[VY], thing->pos[VZ] + (thing->height /2), P_Random() << 24, 0))) { mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 12); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 12); } } } return true; // Keep checking (crush other things)... } /** * @param sector The sector to check. * @param crunch @c true = crush any things in the sector. */ boolean P_ChangeSector(sector_t* sector, boolean crunch) { noFit = false; crushChange = crunch; VALIDCOUNT++; P_SectorTouchingMobjsIterator(sector, PIT_ChangeSector, 0); return noFit; } /** * The following routines originate from the Heretic src! */ #if __JHERETIC__ || __JHEXEN__ /** * @param mobj The mobj whoose position to test. * @return boolean @c true, if the mobj is not blocked by anything. */ boolean P_TestMobjLocation(mobj_t* mobj) { int flags; flags = mobj->flags; mobj->flags &= ~MF_PICKUP; if(P_CheckPosition2f(mobj, mobj->pos[VX], mobj->pos[VY])) { // XY is ok, now check Z mobj->flags = flags; if((mobj->pos[VZ] < mobj->floorZ) || (mobj->pos[VZ] + mobj->height > mobj->ceilingZ)) { return false; // Bad Z } return true; } mobj->flags = flags; return false; } #endif #if __JDOOM64__ || __JHERETIC__ static void CheckMissileImpact(mobj_t* mobj) { int size; linedef_t* ld; if(!mobj->target || !mobj->target->player || !(mobj->flags & MF_MISSILE)) return; if(!(size = P_IterListSize(spechit))) return; P_IterListResetIterator(spechit, false); while((ld = P_IterListIterator(spechit)) != NULL) P_ActivateLine(ld, mobj->target, 0, SPAC_IMPACT); } #endif #if __JHEXEN__ boolean PIT_ThrustStompThing(mobj_t* thing, void* data) { float blockdist; if(!(thing->flags & MF_SHOOTABLE)) return true; blockdist = thing->radius + tsThing->radius; if(fabs(thing->pos[VX] - tsThing->pos[VX]) >= blockdist || fabs(thing->pos[VY] - tsThing->pos[VY]) >= blockdist || (thing->pos[VZ] > tsThing->pos[VZ] + tsThing->height)) return true; // Didn't hit it. if(thing == tsThing) return true; // Don't clip against self. P_DamageMobj(thing, tsThing, tsThing, 10001, false); tsThing->args[1] = 1; // Mark thrust thing as bloody. return true; } void PIT_ThrustSpike(mobj_t* actor) { float bbox[4]; float radius; tsThing = actor; radius = actor->info->radius + MAXRADIUS; bbox[BOXLEFT] = bbox[BOXRIGHT] = actor->pos[VX]; bbox[BOXBOTTOM] = bbox[BOXTOP] = actor->pos[VY]; bbox[BOXLEFT] -= radius; bbox[BOXRIGHT] += radius; bbox[BOXBOTTOM] -= radius; bbox[BOXTOP] += radius; // Stomp on any things contacted. VALIDCOUNT++; P_MobjsBoxIterator(bbox, PIT_ThrustStompThing, 0); } boolean PIT_CheckOnmobjZ(mobj_t* thing, void* data) { float blockdist; if(!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) return true; // Can't hit thing. blockdist = thing->radius + tmThing->radius; if(fabs(thing->pos[VX] - tm[VX]) >= blockdist || fabs(thing->pos[VY] - tm[VY]) >= blockdist) return true; // Didn't hit thing. if(thing == tmThing) return true; // Don't clip against self. if(tmThing->pos[VZ] > thing->pos[VZ] + thing->height) return true; else if(tmThing->pos[VZ] + tmThing->height < thing->pos[VZ]) return true; // Under thing. if(thing->flags & MF_SOLID) onMobj = thing; return !(thing->flags & MF_SOLID); } mobj_t* P_CheckOnMobj(mobj_t* thing) { subsector_t* newSSec; float pos[3], box[4]; mobj_t oldMo; pos[VX] = thing->pos[VX]; pos[VY] = thing->pos[VY]; pos[VZ] = thing->pos[VZ]; tmThing = thing; //// \fixme Do this properly! oldMo = *thing; // Save the old mobj before the fake z movement. P_FakeZMovement(tmThing); tm[VX] = pos[VX]; tm[VY] = pos[VY]; tm[VZ] = pos[VZ]; tmBBox[BOXTOP] = pos[VY] + tmThing->radius; tmBBox[BOXBOTTOM] = pos[VY] - tmThing->radius; tmBBox[BOXRIGHT] = pos[VX] + tmThing->radius; tmBBox[BOXLEFT] = pos[VX] - tmThing->radius; newSSec = R_PointInSubsector(pos[VX], pos[VY]); ceilingLine = floorLine = NULL; // The base floor/ceiling is from the subsector that contains the // point. Any contacted lines the step closer together will adjust them. tmFloorZ = tmDropoffZ = P_GetFloatp(newSSec, DMU_FLOOR_HEIGHT); tmCeilingZ = P_GetFloatp(newSSec, DMU_CEILING_HEIGHT); tmFloorMaterial = P_GetPtrp(newSSec, DMU_FLOOR_MATERIAL); P_EmptyIterList(spechit); if(tmThing->flags & MF_NOCLIP) return NULL; // Check things first, possibly picking things up the bounding box is // extended by MAXRADIUS because mobj_ts are grouped into mapblocks // based on their origin point, and can overlap into adjacent blocks by // up to MAXRADIUS. box[BOXLEFT] = tmBBox[BOXLEFT] - MAXRADIUS; box[BOXRIGHT] = tmBBox[BOXRIGHT] + MAXRADIUS; box[BOXBOTTOM] = tmBBox[BOXBOTTOM] - MAXRADIUS; box[BOXTOP] = tmBBox[BOXTOP] + MAXRADIUS; VALIDCOUNT++; if(!P_MobjsBoxIterator(box, PIT_CheckOnmobjZ, 0)) { *tmThing = oldMo; return onMobj; } *tmThing = oldMo; return NULL; } /** * Fake the zmovement so that we can check if a move is legal. */ static void P_FakeZMovement(mobj_t* mo) { float dist; float delta; if(P_MobjIsCamera(mo)) return; // Adjust height. mo->pos[VZ] += mo->mom[MZ]; if((mo->flags & MF_FLOAT) && mo->target) { // Float down towards target if too close. if(!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) { dist = P_ApproxDistance(mo->pos[VX] - mo->target->pos[VX], mo->pos[VY] - mo->target->pos[VY]); delta = mo->target->pos[VZ] + (mo->height / 2) - mo->pos[VZ]; if(delta < 0 && dist < -(delta * 3)) mo->pos[VZ] -= FLOATSPEED; else if(delta > 0 && dist < (delta * 3)) mo->pos[VZ] += FLOATSPEED; } } if(mo->player && (mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && (mapTime & 2)) { mo->pos[VZ] += FIX2FLT(finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]); } // Clip movement. if(mo->pos[VZ] <= mo->floorZ) // Hit the floor. { mo->pos[VZ] = mo->floorZ; if(mo->mom[MZ] < 0) mo->mom[MZ] = 0; if(mo->flags & MF_SKULLFLY) mo->mom[MZ] = -mo->mom[MZ]; // The skull slammed into something if(P_GetState(mo->type, SN_CRASH) && (mo->flags & MF_CORPSE)) return; } else if(mo->flags2 & MF2_LOGRAV) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -(P_GetGravity() / 32) * 2; else mo->mom[MZ] -= P_GetGravity() / 32; } else if(!(mo->flags & MF_NOGRAVITY)) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -P_GetGravity() * 2; else mo->mom[MZ] -= P_GetGravity(); } if(mo->pos[VZ] + mo->height > mo->ceilingZ) // Hit the ceiling. { mo->pos[VZ] = mo->ceilingZ - mo->height; if(mo->mom[MZ] > 0) mo->mom[MZ] = 0; if(mo->flags & MF_SKULLFLY) mo->mom[MZ] = -mo->mom[MZ]; // The skull slammed into something. } } static void checkForPushSpecial(linedef_t* line, int side, mobj_t* mobj) { if(P_ToXLine(line)->special) { if(mobj->flags2 & MF2_PUSHWALL) { P_ActivateLine(line, mobj, side, SPAC_PUSH); } else if(mobj->flags2 & MF2_IMPACT) { P_ActivateLine(line, mobj, side, SPAC_IMPACT); } } } boolean PTR_BounceTraverse(intercept_t* in) { linedef_t* li; if(in->type != ICPT_LINE) Con_Error("PTR_BounceTraverse: Not a line?"); li = in->d.lineDef; if(!P_GetPtrp(li, DMU_FRONT_SECTOR) || !P_GetPtrp(li, DMU_BACK_SECTOR)) { if(P_PointOnLinedefSide(slideMo->pos[VX], slideMo->pos[VY], li)) return true; // Don't hit the back side. goto bounceblocking; } P_LineOpening(li); // Set OPENRANGE, OPENTOP, OPENBOTTOM... if(OPENRANGE < slideMo->height) goto bounceblocking; // Doesn't fit. if(OPENTOP - slideMo->pos[VZ] < slideMo->height) goto bounceblocking; // Mobj is too high... return true; // This line doesn't block movement... // the line does block movement, see if it is closer than best so far. bounceblocking: if(in->frac < bestSlideFrac) { secondSlideFrac = bestSlideFrac; secondSlideLine = bestSlideLine; bestSlideFrac = in->frac; bestSlideLine = li; } return false; // Stop. } void P_BounceWall(mobj_t* mo) { int side; unsigned int an; float moveLen, leadPos[3], d1[2]; angle_t lineAngle, moveAngle, deltaAngle; slideMo = mo; // Trace along the three leading corners. leadPos[VX] = mo->pos[VX]; leadPos[VY] = mo->pos[VY]; leadPos[VZ] = mo->pos[VZ]; if(mo->mom[MX] > 0) leadPos[VX] += mo->radius; else leadPos[VX] -= mo->radius; if(mo->mom[MY] > 0) leadPos[VY] += mo->radius; else leadPos[VY] -= mo->radius; bestSlideFrac = 1; P_PathTraverse(leadPos[VX], leadPos[VY], leadPos[VX] + mo->mom[MX], leadPos[VY] + mo->mom[MY], PT_ADDLINES, PTR_BounceTraverse); if(!bestSlideLine) return; // We don't want to crash. side = P_PointOnLinedefSide(mo->pos[VX], mo->pos[VY], bestSlideLine); P_GetFloatpv(bestSlideLine, DMU_DXY, d1); lineAngle = R_PointToAngle2(0, 0, d1[0], d1[1]); if(side == 1) lineAngle += ANG180; moveAngle = R_PointToAngle2(0, 0, mo->mom[MX], mo->mom[MY]); deltaAngle = (2 * lineAngle) - moveAngle; moveLen = P_ApproxDistance(mo->mom[MX], mo->mom[MY]); moveLen *= 0.75f; // Friction. if(moveLen < 1) moveLen = 2; an = deltaAngle >> ANGLETOFINESHIFT; mo->mom[MX] = moveLen * FIX2FLT(finecosine[an]); mo->mom[MY] = moveLen * FIX2FLT(finesine[an]); } boolean PTR_PuzzleItemTraverse(intercept_t* in) { switch(in->type) { case ICPT_LINE: // Linedef. { linedef_t* line = in->d.lineDef; xline_t* xline = P_ToXLine(line); if(xline->special != USE_PUZZLE_ITEM_SPECIAL) { P_LineOpening(line); if(OPENRANGE <= 0) { sfxenum_t sound = SFX_NONE; if(puzzleItemUser->player) { switch(puzzleItemUser->player->class) { case PCLASS_FIGHTER: sound = SFX_PUZZLE_FAIL_FIGHTER; break; case PCLASS_CLERIC: sound = SFX_PUZZLE_FAIL_CLERIC; break; case PCLASS_MAGE: sound = SFX_PUZZLE_FAIL_MAGE; break; default: sound = SFX_NONE; break; } } S_StartSound(sound, puzzleItemUser); return false; // Can't use through a wall. } return true; // Continue searching... } if(P_PointOnLinedefSide(puzzleItemUser->pos[VX], puzzleItemUser->pos[VY], line) == 1) return false; // Don't use back sides. if(puzzleItemType != xline->arg1) return false; // Item type doesn't match. P_StartACS(xline->arg2, 0, &xline->arg3, puzzleItemUser, line, 0); xline->special = 0; puzzleActivated = true; return false; // Stop searching. } case ICPT_MOBJ: // Mobj. { mobj_t* mo = in->d.mo; if(mo->special != USE_PUZZLE_ITEM_SPECIAL) return true; // Wrong special... if(puzzleItemType != mo->args[0]) return true; // Item type doesn't match... P_StartACS(mo->args[1], 0, &mo->args[2], puzzleItemUser, NULL, 0); mo->special = 0; puzzleActivated = true; return false; // Stop searching. } default: Con_Error("PTR_PuzzleItemTraverse: Unknown intercept type %i.", in->type); } // Unreachable. return false; } /** * See if the specified player can use the specified puzzle item on a * thing or line(s) at their current world location. * * @param player The player using the puzzle item. * @param itemType The type of item to try to use. * @return boolean true if the puzzle item was used. */ boolean P_UsePuzzleItem(player_t* player, int itemType) { int angle; float pos1[3], pos2[3]; puzzleItemType = itemType; puzzleItemUser = player->plr->mo; puzzleActivated = false; angle = player->plr->mo->angle >> ANGLETOFINESHIFT; memcpy(pos1, player->plr->mo->pos, sizeof(pos1)); memcpy(pos2, player->plr->mo->pos, sizeof(pos2)); pos2[VX] += FIX2FLT(USERANGE * finecosine[angle]); pos2[VY] += FIX2FLT(USERANGE * finesine[angle]); P_PathTraverse(pos1[VX], pos1[VY], pos2[VX], pos2[VY], PT_ADDLINES | PT_ADDMOBJS, PTR_PuzzleItemTraverse); if(!puzzleActivated) { P_SetYellowMessage(player, TXT_USEPUZZLEFAILED, false); } return puzzleActivated; } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/hu_inventory.c0000644000175000017500000005221511357170242023527 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_inventory.c: Heads-up display(s) for the player inventory. */ #if defined(__JHERETIC__) || defined(__JHEXEN__) // HEADER FILES ------------------------------------------------------------ #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "p_tick.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // How many inventory slots are visible in the fixed-size inventory. #define NUMVISINVSLOTS (7) #define ST_INVENTORYHEIGHT (30) #define ST_INVSLOTWIDTH (31) // Inventory item counts (relative to each slot). #define ST_INVCOUNTDIGITS (2) #if __JHERETIC__ #define ST_INVICONOFFY (0) #define ST_INVCOUNTOFFX (27) #define ST_INVCOUNTOFFY (22) #define ST_INVSLOTOFFX (1) #define ST_INVSELECTOFFY (ST_INVENTORYHEIGHT) #else #define ST_INVICONOFFY (-1) #define ST_INVCOUNTOFFX (28) #define ST_INVCOUNTOFFY (22) #define ST_INVSLOTOFFX (1) #define ST_INVSELECTOFFY (1) #endif // HUD Inventory Flags: #define HIF_VISIBLE 0x1 #define HIF_IS_DIRTY 0x8 // TYPES ------------------------------------------------------------------- typedef struct { byte flags; // HIF_* flags int hideTics; uint numOwnedItemTypes; uint slots[NUM_INVENTORYITEM_TYPES - 1]; uint numUsedSlots; uint selected; uint varCursorPos; // Variable-range, fullscreen inv cursor. uint fixedCursorPos; // Fixed-range, statusbar inv cursor. } hud_inventory_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void ST_ResizeInventory(struct cvar_s* cvar); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void inventoryIndexes(const player_t* plr, const hud_inventory_t* hud, uint maxVisSlots, int origCursor, uint* firstVisible, uint* cursorPos, uint* startSlot, uint* endSlot); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static hud_inventory_t hudInventories[MAXPLAYERS]; cvar_t hudInvCVars[] = { {"hud-inventory-timer", 0, CVT_FLOAT, &cfg.inventoryTimer, 0, 30}, {"hud-inventory-slot-showempty", 0, CVT_BYTE, &cfg.inventorySlotShowEmpty, 0, 1}, {"hud-inventory-slot-max", CVF_NO_MAX, CVT_INT, &cfg.inventorySlotMaxVis, 0, 0, ST_ResizeInventory}, {NULL} }; // CODE ------------------------------------------------------------------- /** * Register CVARs and CCmds for the HUD inventory. */ void Hu_InventoryRegister(void) { int i; for(i = 0; hudInvCVars[i].name; ++i) Con_AddVariable(hudInvCVars + i); } /** * Rebuild the inventory item type table. * These indices can be used to associate slots in an inventory browser * to the items held within. */ static void rebuildInventory(hud_inventory_t* inv) { int i, plrNum = inv - hudInventories; uint numOwnedItemTypes; inventoryitemtype_t selectedType = P_GetInvItem( inv->slots[inv->selected])->type; inv->selected = 0; numOwnedItemTypes = 0; for(i = 0; i < NUM_INVENTORYITEM_TYPES - 1; ++i) if(P_InventoryCount(plrNum, IIT_FIRST + i) > 0) numOwnedItemTypes++; // Always 1:1 inv->numOwnedItemTypes = inv->numUsedSlots = numOwnedItemTypes; memset(inv->slots, 0, sizeof(inv->slots[0]) * (NUM_INVENTORYITEM_TYPES - 1)); if(inv->numUsedSlots) { uint idx = 0; for(i = 0; i < NUM_INVENTORYITEM_TYPES - 1; ++i) { if(P_InventoryCount(plrNum, IIT_FIRST + i)) { inv->slots[idx] = i; if(P_GetInvItem(i)->type == selectedType) inv->selected = idx; if(++idx >= inv->numUsedSlots) break; } } } if(inv->flags & HIF_IS_DIRTY) inv->flags &= ~HIF_IS_DIRTY; } static void inventoryIndexes(const player_t* plr, const hud_inventory_t* inv, uint maxVisSlots, int origCursor, uint* firstVisible, uint* cursorPos, uint* fromSlot, uint* toSlot) { int cursor, first, from, to; if(!firstVisible && !cursorPos && !fromSlot && !toSlot) return; if(cfg.inventorySelectMode) { // Scroll. int last; cursor = maxVisSlots / 2; if(cfg.inventoryWrap) { first = inv->selected - cursor; if(first < 0) first += inv->numUsedSlots; from = 0; to = maxVisSlots; } else { first = inv->selected - cursor; if(first < 0) first = 0; from = cursor - inv->selected; if(from < 0) from = 0; last = inv->selected + cursor + (maxVisSlots % 2? 1 : 0); if(last - 1 < (signed) inv->numUsedSlots) to = maxVisSlots; else to = maxVisSlots - (last - inv->numUsedSlots); } } else { // Cursor. cursor = origCursor; if(inv->numUsedSlots < maxVisSlots) { from = (maxVisSlots - inv->numUsedSlots) / 2; to = from + inv->numUsedSlots; cursor += from; } else { if(cfg.inventoryWrap) { from = 0; to = maxVisSlots; } else { int last; from = cursor - inv->selected; if(from < 0) from = 0; last = inv->numUsedSlots - 1 - (inv->selected + cursor); to = maxVisSlots; } } first = inv->selected - origCursor; if(cfg.inventoryWrap) { if(first < 0) first += inv->numUsedSlots; } else { if(inv->numUsedSlots < maxVisSlots || first + maxVisSlots > inv->numUsedSlots) { int shift = inv->numUsedSlots - (first + maxVisSlots); first += shift; if(first < 0) { first = 0; cursor = from + inv->selected; } else cursor -= shift; } } if(first < 0) first = 0; } if(firstVisible) *firstVisible = (unsigned) first; if(cursorPos) *cursorPos = (unsigned) cursor; if(fromSlot) *fromSlot = (unsigned) from; if(toSlot) *toSlot = (unsigned) to; } void Hu_InventoryDraw(int player, int x, int y, float alpha, float textAlpha, float iconAlpha) { #define BORDER 1 const hud_inventory_t* inv; player_t* plr; uint i, from, to, idx, slot, first, selected, numVisSlots, maxVisSlots, startSlot, endSlot; float invScale, lightDelta; if(alpha <= 0) return; if(player < 0 || player >= MAXPLAYERS) return; inv = &hudInventories[player]; plr = &players[player]; if(cfg.inventorySlotMaxVis) maxVisSlots = cfg.inventorySlotMaxVis; else maxVisSlots = NUM_INVENTORYITEM_TYPES - 1; inventoryIndexes(plr, inv, maxVisSlots, inv->varCursorPos, &first, &selected, &startSlot, &endSlot); numVisSlots = maxVisSlots; { #define EXTRA_SCALE .75f float availWidth = SCREENWIDTH - 50 * 2, width = (numVisSlots * ST_INVSLOTWIDTH) * EXTRA_SCALE; if(width > availWidth) invScale = availWidth / width; else invScale = 1; invScale *= cfg.hudScale * EXTRA_SCALE; #undef EXTRA_SCALE } if(maxVisSlots % 2) lightDelta = 1.f / maxVisSlots; else lightDelta = 1.f / (maxVisSlots - 1); lightDelta *= 2; idx = first; slot = (cfg.inventorySlotShowEmpty? 0 : startSlot); from = (cfg.inventorySlotShowEmpty? 0 : startSlot); if(cfg.inventorySlotShowEmpty) { to = maxVisSlots; } else { if(startSlot > 0) to = maxVisSlots; else to = endSlot - startSlot; if(inv->numUsedSlots - 1 < endSlot - startSlot) to = from + inv->numUsedSlots; } Draw_BeginZoom(invScale, x, y + ST_INVENTORYHEIGHT); x -= (numVisSlots * ST_INVSLOTWIDTH) / 2.f; for(i = from; i < to; ++i) { float light, a; if(i < maxVisSlots / 2) light = (i + 1) * lightDelta; else light = (maxVisSlots - i) * lightDelta; a = i == selected? .5f : light / 2; GL_DrawPatchLitAlpha(x + slot * ST_INVSLOTWIDTH + ST_INVSLOTOFFX, y, light, a * alpha, dpInvItemBox.lump); if(i >= startSlot && i < endSlot) { uint count; const invitem_t* item = P_GetInvItem(inv->slots[idx]); if((count = P_InventoryCount(player, item->type))) { GL_DrawPatchLitAlpha(x + slot * ST_INVSLOTWIDTH, y + ST_INVICONOFFY, 1, slot == selected? alpha : iconAlpha / 3, item->patchLump); if(count > 1) Hu_DrawSmallNum(P_InventoryCount(player, item->type), ST_INVCOUNTDIGITS, x + slot * ST_INVSLOTWIDTH + ST_INVCOUNTOFFX, y + ST_INVCOUNTOFFY, slot == selected? alpha : textAlpha / 2); } if(++idx > inv->numOwnedItemTypes - 1) idx = 0; } slot++; } GL_DrawPatchLitAlpha(x + selected * ST_INVSLOTWIDTH, y + ST_INVSELECTOFFY - BORDER, 1, alpha, dpInvSelectBox.lump); if(inv->numUsedSlots > maxVisSlots) { #define ARROW_RELXOFF 2 #define ARROW_YOFFSET 9 if(cfg.inventoryWrap || first != 0) { GL_DrawPatchLitAlpha( #if __JHEXEN__ 40, 167, #else x - dpInvPageLeft[0].width - ARROW_RELXOFF, y + ARROW_YOFFSET, #endif 1, iconAlpha, dpInvPageLeft[!(mapTime & 4)? 1 : 0].lump); } if(cfg.inventoryWrap || inv->numUsedSlots - first > numVisSlots) { GL_DrawPatchLitAlpha( #if __JHEXEN__ 270, 167, #else x + numVisSlots * ST_INVSLOTWIDTH + ARROW_RELXOFF, y + ARROW_YOFFSET, #endif 1, iconAlpha, dpInvPageRight[!(mapTime & 4)? 1 : 0].lump); } #undef ARROW_XOFFSET #undef ARROW_YOFFSET } Draw_EndZoom(); #undef BORDER } void Hu_InventoryDraw2(int player, int x, int y, float alpha) { #define BORDER 1 const hud_inventory_t* inv; player_t* plr; uint i, idx, slot, from, to, first, cursor, startSlot, endSlot; if(alpha <= 0) return; if(player < 0 || player >= MAXPLAYERS) return; inv = &hudInventories[player]; plr = &players[player]; inventoryIndexes(plr, inv, NUMVISINVSLOTS, inv->fixedCursorPos, &first, &cursor, &startSlot, &endSlot); idx = first; from = startSlot; slot = startSlot; if(startSlot > 0) to = NUMVISINVSLOTS; else to = endSlot - startSlot; if(inv->numUsedSlots - 1 < endSlot - startSlot) to = from + inv->numUsedSlots; for(i = from; i < to; ++i) { if(i >= startSlot && i < endSlot) { uint count; const invitem_t* item = P_GetInvItem(inv->slots[idx]); if((count = P_InventoryCount(player, item->type))) { GL_DrawPatchLitAlpha(x + slot * ST_INVSLOTWIDTH, y + ST_INVICONOFFY, 1, alpha, item->patchLump); if(count > 1) Hu_DrawSmallNum(P_InventoryCount(player, item->type), ST_INVCOUNTDIGITS, x + slot * ST_INVSLOTWIDTH + ST_INVCOUNTOFFX, y + ST_INVCOUNTOFFY, alpha); } if(++idx > inv->numOwnedItemTypes - 1) idx = 0; } slot++; } GL_DrawPatchLitAlpha(x + cursor * ST_INVSLOTWIDTH, y + ST_INVSELECTOFFY - BORDER, 1, alpha, dpInvSelectBox.lump); if(inv->numUsedSlots > NUMVISINVSLOTS) { // Draw more left indicator. if(cfg.inventoryWrap || first != 0) GL_DrawPatchLitAlpha( #if __JHEXEN__ 42, 163, #else x - 12, y - 1, #endif 1, alpha, dpInvPageLeft[!(mapTime & 4)? 1 : 0].lump); // Draw more right indicator. if(cfg.inventoryWrap || inv->numUsedSlots - first > NUMVISINVSLOTS) GL_DrawPatchLitAlpha(269, #if __JHEXEN__ 163, #else y - 1, #endif 1, alpha, dpInvPageRight[!(mapTime & 4)? 1 : 0].lump); } #undef BORDER } static void inventoryMove(hud_inventory_t* inv, int dir, boolean canWrap) { if(dir == 1) { // Move right. uint maxVisSlots; if(inv->selected == inv->numUsedSlots - 1) { if(canWrap) inv->selected = 0; } else inv->selected++; // First the fixed range statusbar cursor. if(inv->fixedCursorPos < NUMVISINVSLOTS - 1 && !(inv->fixedCursorPos + 1 > inv->numUsedSlots - 1)) inv->fixedCursorPos++; // Now the variable range full-screen cursor. if(cfg.inventorySlotMaxVis) maxVisSlots = cfg.inventorySlotMaxVis; else maxVisSlots = NUM_INVENTORYITEM_TYPES - 1; if(inv->varCursorPos < maxVisSlots - 1 && !(inv->varCursorPos + 1 > inv->numUsedSlots - 1)) inv->varCursorPos++; return; } // Else, a move left. if(inv->selected == 0) { if(canWrap) inv->selected = inv->numUsedSlots - 1; } else inv->selected--; // First the fixed range statusbar cursor. if(inv->fixedCursorPos > 0) inv->fixedCursorPos--; // Now the variable range full-screen cursor. if(inv->varCursorPos > 0) inv->varCursorPos--; } void Hu_InventoryOpen(int player, boolean show) { player_t* plr; hud_inventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; inv = &hudInventories[player]; if(show) { inv->flags |= HIF_VISIBLE; inv->hideTics = (int) (cfg.inventoryTimer * TICSPERSEC); ST_HUDUnHide(player, HUE_FORCE); } else { inv->flags &= ~HIF_VISIBLE; P_InventorySetReadyItem(player, P_GetInvItem(inv->slots[inv->selected])->type); } } boolean Hu_InventoryIsOpen(int player) { hud_inventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return false; inv = &hudInventories[player]; return ((inv->flags & HIF_VISIBLE)? true : false); } /** * Mark the HUD inventory as dirty (i.e., the player inventory state has * changed in such a way that would require the HUD inventory display(s) * to be updated e.g., the player gains a new item). * * @param player Player whoose in HUD inventory is dirty. */ void Hu_InventoryMarkDirty(int player) { if(player < 0 || player >= MAXPLAYERS) return; hudInventories[player].flags |= HIF_IS_DIRTY; } boolean Hu_InventorySelect(int player, inventoryitemtype_t type) { assert(type == IIT_NONE || (type >= IIT_FIRST && type < NUM_INVENTORYITEM_TYPES)); if(player >= 0 && player < MAXPLAYERS) { hud_inventory_t* inv = &hudInventories[player]; if(P_InventoryCount(player, type)) { uint i; for(i = 0; i < inv->numUsedSlots; ++i) if(P_GetInvItem(inv->slots[i])->type == type) { inv->selected = i; inv->varCursorPos = inv->fixedCursorPos = 0; return true; } } } return false; } boolean Hu_InventoryMove(int player, int dir, boolean canWrap, boolean silent) { player_t* plr; hud_inventory_t* inv; if(player < 0 || player >= MAXPLAYERS) return false; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return false; inv = &hudInventories[player]; // Do the move first, before updating a possibly out of date inventory. if(inv->numOwnedItemTypes > 1) { inventoryMove(inv, dir, canWrap); } if(inv->flags & HIF_IS_DIRTY) { rebuildInventory(inv); } if(inv->numOwnedItemTypes > 1) { P_InventorySetReadyItem(player, P_GetInvItem(inv->selected)->type); } if(!silent) { inv->hideTics = (int) (cfg.inventoryTimer * TICSPERSEC); } return true; } void Hu_InventoryInit(void) { int i; memset(hudInventories, 0, sizeof(hudInventories)); for(i = 0; i < MAXPLAYERS; ++i) { hud_inventory_t* inv = &hudInventories[i]; inv->flags = HIF_IS_DIRTY; } } void Hu_InventoryTicker(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; hud_inventory_t* inv = &hudInventories[i]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) continue; if(inv->flags & HIF_IS_DIRTY) rebuildInventory(inv); if(!P_IsPaused()) { if(Hu_InventoryIsOpen(i)) { // Turn inventory off after a certain amount of time? if(cfg.inventoryTimer == 0) { inv->hideTics = 0; } else { if(inv->hideTics > 0) inv->hideTics--; if(inv->hideTics == 0 && cfg.inventoryTimer > 0) Hu_InventoryOpen(i, false); // Close the inventory. } } } } } void ST_ResizeInventory(cvar_t* unused) { int i; uint maxVisSlots; if(cfg.inventorySlotMaxVis) maxVisSlots = cfg.inventorySlotMaxVis; else maxVisSlots = NUM_INVENTORYITEM_TYPES - 1; for(i = 0; i < MAXPLAYERS; ++i) { hud_inventory_t* inv = &hudInventories[i]; if(inv->varCursorPos >= maxVisSlots - 1) { inv->varCursorPos = maxVisSlots - 1; } inv->flags |= HIF_IS_DIRTY; } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/g_eventsequence.c0000644000175000017500000001030111357170242024144 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ // HEADER FILES ------------------------------------------------------------ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "g_eventsequence.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct eventsequence_s { unsigned char* sequence; int (*callback) (const int* args, int); size_t length, pos; int args[2]; int currentArg; } eventsequence_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static eventsequence_t* eventSequences = NULL; static int numEventSequences = 0; // CODE -------------------------------------------------------------------- /** * @return Non-zero iff the sequence was completed. */ static int checkSequence(eventsequence_t* es, char key, boolean* eat) { if(es->sequence[es->pos] == 0) { es->args[es->currentArg++] = key; es->pos++; *eat = true; } else if(key == es->sequence[es->pos]) { es->pos++; // Not eating partial matches. *eat = false; } else { es->pos = 0; es->currentArg = 0; } if(es->sequence[es->pos] == 1) { es->pos++; } if(es->pos >= es->length) { es->pos = 0; es->currentArg = 0; return true; } return false; } /** * Responds to an input event if determined to be part of a known event * sequence. * * @param ev Ptr to the event to be checked. * * @return @c true, if the event was 'eaten'. */ boolean G_EventSequenceResponder(event_t* ev) { boolean eat = false; int i; if(ev->type != EV_KEY || ev->state != EVS_DOWN) return false; for(i = 0; i < numEventSequences; ++i) { eventsequence_t* es = &eventSequences[i]; if(checkSequence(es, ev->data1, &eat)) { es->callback(es->args, CONSOLEPLAYER); return true; } } return eat; } void G_AddEventSequence(const unsigned char* sequence, size_t sequenceLength, int (*callback) (const int*, int)) { eventsequence_t* es; eventSequences = Z_Realloc(eventSequences, sizeof(eventsequence_t) * ++numEventSequences, PU_STATIC); es = &eventSequences[numEventSequences-1]; es->sequence = Z_Malloc(sizeof(unsigned char) * sequenceLength, PU_STATIC, 0); memcpy(es->sequence, sequence, sequenceLength); es->length = sequenceLength; es->callback = callback; es->pos = 0; es->currentArg = 0; memset(es->args, 0, sizeof(es->args)); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_terraintype.c0000644000175000017500000001470711357170242023667 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_terraintype.c: */ // HEADER FILES ------------------------------------------------------------ #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #include "dmu_lib.h" #include "p_terraintype.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct { material_t* material; uint terrainNum; } materialterraintype_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static terraintype_t terrainTypes[] = { {"Default", 0}, // Default type (no special attributes). #if __JDOOM__ || __JDOOM64__ {"Water", TTF_NONSOLID|TTF_FLOORCLIP}, {"Lava", TTF_NONSOLID|TTF_FLOORCLIP}, {"Blood", TTF_NONSOLID|TTF_FLOORCLIP}, {"Nukage", TTF_NONSOLID|TTF_FLOORCLIP}, {"Slime", TTF_NONSOLID|TTF_FLOORCLIP}, #endif #if __JHERETIC__ {"Water", TTF_NONSOLID|TTF_FLOORCLIP|TTF_SPAWN_SPLASHES}, {"Lava", TTF_NONSOLID|TTF_FLOORCLIP|TTF_SPAWN_SMOKE}, {"Sludge", TTF_NONSOLID|TTF_FLOORCLIP|TTF_SPAWN_SLUDGE}, #endif #if __JHEXEN__ {"Water", TTF_NONSOLID|TTF_FLOORCLIP|TTF_SPAWN_SPLASHES}, {"Lava", TTF_NONSOLID|TTF_FLOORCLIP|TTF_FRICTION_HIGH|TTF_DAMAGING|TTF_SPAWN_SMOKE}, {"Sludge", TTF_NONSOLID|TTF_FLOORCLIP|TTF_SPAWN_SLUDGE}, {"Ice", TTF_FRICTION_LOW}, #endif {NULL, 0} }; static materialterraintype_t* materialTTypes = NULL; static uint numMaterialTTypes = 0; // CODE -------------------------------------------------------------------- static void createMaterialTerrainType(material_t* mat, uint idx) { uint i; materialterraintype_t* mtt; // If we've already assigned this material to a terrain type, override // the previous assignation. for(i = 0; i < numMaterialTTypes; ++i) if(materialTTypes[i].material == mat) { materialTTypes[i].terrainNum = idx; return; } // Its a new material. materialTTypes = Z_Realloc(materialTTypes, sizeof(*materialTTypes) * ++numMaterialTTypes, PU_STATIC); mtt = &materialTTypes[numMaterialTTypes-1]; mtt->material = mat; mtt->terrainNum = idx - 1; } /** * @param name The symbolic terrain type name. */ static uint getTerrainTypeNumForName(const char* name) { uint i; if(name && name[0]) { for(i = 0; terrainTypes[i].name; ++i) { terraintype_t* tt = &terrainTypes[i]; if(!stricmp(tt->name, name)) return i + 1; // 1-based index. } } return 0; } static terraintype_t* getTerrainTypeForMaterial(material_t* mat) { uint i; if(mat) { for(i = 0; i < numMaterialTTypes; ++i) { materialterraintype_t* mtt = &materialTTypes[i]; if(mtt->material == mat) return &terrainTypes[mtt->terrainNum]; } } return NULL; } /** * Called during (re)init. */ void P_InitTerrainTypes(void) { struct matttypedef_s { const char* matName; material_namespace_t matGroup; const char* ttName; } matTTypeDefs[] = { #if __JDOOM__ || __JDOOM64__ {"FWATER1", MN_FLATS, "Water"}, {"LAVA1", MN_FLATS, "Lava"}, {"BLOOD1", MN_FLATS, "Blood"}, {"NUKAGE1", MN_FLATS, "Nukage"}, {"SLIME01", MN_FLATS, "Slime"}, #endif #if __JHERETIC__ {"FLTWAWA1", MN_FLATS, "Water"}, {"FLTFLWW1", MN_FLATS, "Water"}, {"FLTLAVA1", MN_FLATS, "Lava"}, {"FLATHUH1", MN_FLATS, "Lava"}, {"FLTSLUD1", MN_FLATS, "Sludge"}, #endif #if __JHEXEN__ {"X_005", MN_FLATS, "Water"}, {"X_001", MN_FLATS, "Lava"}, {"X_009", MN_FLATS, "Sludge"}, {"F_033", MN_FLATS, "Ice"}, #endif {NULL, 0, NULL} }; uint i; if(materialTTypes) Z_Free(materialTTypes); materialTTypes = NULL; numMaterialTTypes = 0; for(i = 0; matTTypeDefs[i].matName; ++i) { uint idx = getTerrainTypeNumForName(matTTypeDefs[i].ttName); if(idx) { material_t* mat = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(matTTypeDefs[i].matName, matTTypeDefs[i].matGroup)); if(mat) { Con_Message("P_InitTerrainTypes: Material '%s' linked to terrain type '%s'.\n", matTTypeDefs[i].matName, matTTypeDefs[i].ttName); createMaterialTerrainType(mat, idx); } } } } /** * Return the terrain type of the specified material. * * @param num The material to check. */ const terraintype_t* P_TerrainTypeForMaterial(material_t* mat) { const terraintype_t* tt = getTerrainTypeForMaterial(mat); if(tt) return tt; // Known, return it. // Return the default type. return &terrainTypes[0]; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/d_netsv.c0000644000175000017500000012210011357170242022427 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2007 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_netsv.c : Common code related to net games (server-side). */ // HEADER FILES ------------------------------------------------------------ #include #include #include #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "d_net.h" #include "p_svtexarc.h" #include "p_player.h" #include "p_user.h" #include "p_map.h" #include "g_common.h" #include "p_tick.h" #include "p_start.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ #if __JHEXEN__ || __JSTRIFE__ # define SOUND_COUNTDOWN SFX_PICKUP_KEY #elif __JDOOM__ || __JDOOM64__ # define SOUND_COUNTDOWN SFX_GETPOW #elif __JHERETIC__ # define SOUND_COUNTDOWN SFX_KEYUP #endif #define SOUND_VICTORY SOUND_COUNTDOWN #define UPD_BUFFER_LEN 500 // How long is the largest possible sector update? #define MAX_SECTORUPD 20 #define MAX_SIDEUPD 9 #define WRITE_SHORT(byteptr, val) {(*(short*)(byteptr) = SHORT(val)); byteptr += 2;} #define WRITE_LONG(byteptr, val) {(*(int*)(byteptr) = LONG(val)); byteptr += 4;} // TYPES ------------------------------------------------------------------- typedef struct maprule_s { boolean usetime, usefrags; int time; // Minutes. int frags; // Maximum frags for one player. } maprule_t; typedef enum cyclemode_s { CYCLE_IDLE, CYCLE_TELL_RULES, CYCLE_COUNTDOWN } cyclemode_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void R_SetAllDoomsdayFlags(); void P_FireWeapon(player_t *player); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- int NetSv_GetFrags(int pl); void NetSv_CheckCycling(void); void NetSv_SendPlayerClass(int pnum, char cls); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- char cyclingMaps = false; char *mapCycle = ""; char mapCycleNoExit = true; int netSvAllowSendMsg = true; int netSvAllowCheats = false; // This is returned in *_Get(DD_GAME_CONFIG). It contains a combination // of space-separated keywords. char gameConfigString[128]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int cycleIndex; static int cycleCounter = -1, cycleMode = CYCLE_IDLE; static int oldPals[MAXPLAYERS]; #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ static int oldClasses[MAXPLAYERS]; #endif // CODE -------------------------------------------------------------------- /** * Update the game config string with keywords that describe the game. * The string is sent out in netgames (also to the master). * Keywords: dm, coop, jump, nomonst, respawn, skillN */ void NetSv_UpdateGameConfig(void) { if(IS_CLIENT) return; memset(gameConfigString, 0, sizeof(gameConfigString)); sprintf(gameConfigString, "skill%i", gameSkill + 1); if(deathmatch > 1) sprintf(gameConfigString, " dm%i", deathmatch); else if(deathmatch) strcat(gameConfigString, " dm"); else strcat(gameConfigString, " coop"); if(noMonstersParm) strcat(gameConfigString, " nomonst"); #if !__JHEXEN__ if(respawnMonsters) strcat(gameConfigString, " respawn"); #endif if(cfg.jumpEnabled) strcat(gameConfigString, " jump"); } /** * \kludge Unravel a DDPT_COMMANDS (32) packet. Returns a pointer to a static * buffer that contains the ticcmds (kludge to work around the parameter * passing from the engine). */ void *NetSv_ReadCommands(byte *msg, uint size) { #define MAX_COMMANDS 30 static byte data[2 + sizeof(ticcmd_t) * MAX_COMMANDS]; ticcmd_t *cmd; byte *end = msg + size, flags; ushort *count = (ushort *) data; memset(data, 0, sizeof(data)); // The first two bytes of the data contain the number of commands. *count = 0; // The first command. cmd = (void *) (data + 2); while(msg < end) { // One more command. *count += 1; // Only act on up to MAX_COMMANDS, and discard the rest to prevent // buffer overflows its a fugly hack - we really need to replace // the netcode - Yagisan if(*msg <= MAX_COMMANDS) { // First the flags. flags = *msg++; if(flags & CMDF_FORWARDMOVE) cmd->forwardMove = *msg++; if(flags & CMDF_SIDEMOVE) cmd->sideMove = *msg++; if(flags & CMDF_ANGLE) { cmd->angle = SHORT( *(short *) msg ); msg += 2; } if(flags & CMDF_LOOKDIR) { cmd->pitch = SHORT( *(short *) msg ); msg += 2; } if(flags & CMDF_BUTTONS) cmd->actions = *msg++; /* if(flags & CMDF_BUTTONS) { byte buttons = *msg++; cmd->attack = ((buttons & CMDF_BTN_ATTACK) != 0); cmd->use = ((buttons & CMDF_BTN_USE) != 0); cmd->jump = ((buttons & CMDF_BTN_JUMP) != 0); cmd->pause = ((buttons & CMDF_BTN_PAUSE) != 0); } else { cmd->attack = cmd->use = cmd->jump = cmd->pause = false; } if(flags & CMDF_LOOKFLY) cmd->fly = *msg++; if(flags & CMDF_ARTI) cmd->arti = *msg++; if(flags & CMDF_CHANGE_WEAPON) { cmd->changeWeapon = SHORT( *(short *) msg ); msg += 2; } */ // Copy to next command (only differences have been written). memcpy(cmd + 1, cmd, sizeof(ticcmd_t)); } /** * We reached MAX_COMMANDS, start discarding now to prevent buffer * overflows. * Its a fugly hack - we really need to replace the netcode - Yagisan */ else { msg++; } // Move to next command. cmd++; } return data; } void NetSv_Ticker(void) { int i; float power; // Map rotation checker. NetSv_CheckCycling(); // This is done here for servers. R_SetAllDoomsdayFlags(); // Set the camera filters for players. for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr; int red, palette = 0; if(!players[i].plr->inGame) continue; plr = &players[i]; red = plr->damageCount; #if __JDOOM__ || __JDOOM64__ if(plr->powers[PT_STRENGTH]) { int bz; // Slowly fade the berzerk out. bz = 12 - (plr->powers[PT_STRENGTH] >> 6); if(bz > red) red = bz; } #endif if(red) { palette = (red + 7) >> 3; if(palette >= NUMREDPALS) { palette = NUMREDPALS - 1; } palette += STARTREDPALS; } else if(plr->bonusCount) { palette = (plr->bonusCount + 7) >> 3; if(palette >= NUMBONUSPALS) { palette = NUMBONUSPALS - 1; } palette += STARTBONUSPALS; } #if __JDOOM__ || __JDOOM64__ else if(plr->powers[PT_IRONFEET] > 4 * 32 || plr->powers[PT_IRONFEET] & 8) { palette = 13; //RADIATIONPAL; } #elif __JHEXEN__ else if(plr->poisonCount) { palette = (plr->poisonCount + 7) >> 3; if(palette >= NUMPOISONPALS) { palette = NUMPOISONPALS - 1; } palette += STARTPOISONPALS; } else if(plr->plr->mo && plr->plr->mo->flags2 & MF2_ICEDAMAGE) { palette = STARTICEPAL; } #endif if(palette > 0) plr->plr->flags |= DDPF_VIEW_FILTER; else plr->plr->flags &= ~DDPF_VIEW_FILTER; // $democam if(oldPals[i] != palette) { // The filter changes. R_GetFilterColor(plr->plr->filterColor, palette); // If we are the server, we'll need inform the client. plr->plr->flags |= DDPF_FILTER; oldPals[i] = palette; } } #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ // Keep track of player class changes (fighter, cleric, mage, pig). // Notify clients accordingly. This is mostly just FYI (it'll update // pl->class on the clientside). for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; if(oldClasses[i] != players[i].class) { oldClasses[i] = players[i].class; NetSv_SendPlayerClass(i, players[i].class); } } #endif // Inform clients about jumping? power = (cfg.jumpEnabled ? cfg.jumpPower : 0); if(power != netJumpPower) { netJumpPower = power; for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) NetSv_SendJumpPower(i, power); } } // Send the player state updates. for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; // Don't send on every tic. Also, don't send to all // players at the same time. if(((int) GAMETIC + i) % 10) continue; if(!plr->plr->inGame || !plr->update) continue; // Owned weapons and player state will be sent in a new kind of // packet. if(plr->update & (PSF_OWNED_WEAPONS | PSF_STATE)) { int flags = (plr->update & PSF_OWNED_WEAPONS ? PSF2_OWNED_WEAPONS : 0) | (plr->update & PSF_STATE ? PSF2_STATE : 0); NetSv_SendPlayerState2(i, i, flags, true); plr->update &= ~(PSF_OWNED_WEAPONS | PSF_STATE); // That was all? if(!plr->update) continue; } // The delivery of the state packet will be confirmed. NetSv_SendPlayerState(i, i, plr->update, true); plr->update = 0; } } void NetSv_CycleToMapNum(uint map) { char tmp[3], cmd[80]; sprintf(tmp, "%02u", map); #if __JDOOM64__ sprintf(cmd, "setmap 1 %u", map); #elif __JDOOM__ if(gameMode == commercial) sprintf(cmd, "setmap 1 %u", map); else sprintf(cmd, "setmap %c %c", tmp[0], tmp[1]); #elif __JHERETIC__ sprintf(cmd, "setmap %c %c", tmp[0], tmp[1]); #elif __JHEXEN__ || __JSTRIFE__ sprintf(cmd, "setmap %u", map); #endif DD_Execute(false, cmd); // In a couple of seconds, send everyone the rules of this map. cycleMode = CYCLE_TELL_RULES; cycleCounter = 3 * TICSPERSEC; } /** * Reads through the MapCycle cvar and finds the map with the given index. * Rules that apply to the map are returned in 'rules'. */ int NetSv_ScanCycle(int index, maprule_t* rules) { char *ptr = mapCycle, *end; int i, pos = -1; uint episode, map; #if __JHEXEN__ || __JSTRIFE__ int m; #endif char tmp[3], lump[10]; boolean clear = false, has_random = false; maprule_t dummy; if(!rules) rules = &dummy; // By default no rules apply. rules->usetime = rules->usefrags = false; for(; *ptr; ptr++) { if(isspace(*ptr)) continue; if(*ptr == ',' || *ptr == '+' || *ptr == ';' || *ptr == '/' || *ptr == '\\') { // These symbols are allowed to combine "time" and "frags". // E.g. "Time:10/Frags:5" or "t:30, f:10" clear = false; } else if(!strnicmp("time", ptr, 1)) { // Find the colon. while(*ptr && *ptr != ':') ptr++; if(!*ptr) return -1; if(clear) rules->usefrags = false; clear = true; rules->usetime = true; rules->time = strtol(ptr + 1, &end, 0); ptr = end - 1; } else if(!strnicmp("frags", ptr, 1)) { // Find the colon. while(*ptr && *ptr != ':') ptr++; if(!*ptr) return -1; if(clear) rules->usetime = false; clear = true; rules->usefrags = true; rules->frags = strtol(ptr + 1, &end, 0); ptr = end - 1; } else if(*ptr == '*' || (*ptr >= '0' && *ptr <= '9')) { // A map identifier is here. pos++; // Read it. tmp[0] = *ptr++; tmp[1] = *ptr; tmp[2] = 0; if(strlen(tmp) < 2) { // Assume a zero is missing. tmp[1] = tmp[0]; tmp[0] = '0'; } if(index == pos) { if(tmp[0] == '*' || tmp[1] == '*') has_random = true; // This is the map we're looking for. Return it. // But first randomize the asterisks. for(i = 0; i < 100; i++) // Try many times to find a good map. { // The differences in map numbering make this harder // than it should be. #if __JDOOM64__ sprintf(lump, "MAP%u%u", episode = tmp[0] == '*' ? M_Random() % 4 : tmp[0] - '0', map = tmp[1] == '*' ? M_Random() % 10 : tmp[1] - '0'); #elif __JDOOM__ if(gameMode == commercial) { sprintf(lump, "MAP%u%u", episode = tmp[0] == '*' ? M_Random() % 4 : tmp[0] - '0', map = tmp[1] == '*' ? M_Random() % 10 : tmp[1] - '0'); } else { sprintf(lump, "E%uM%u", episode = tmp[0] == '*' ? 1 + M_Random() % 4 : tmp[0] - '0', map = tmp[1] == '*' ? 1 + M_Random() % 9 : tmp[1] - '0'); } #elif __JSTRIFE__ sprintf(lump, "MAP%u%u", episode = tmp[0] == '*' ? M_Random() % 4 : tmp[0] - '0', map = tmp[1] == '*' ? M_Random() % 10 : tmp[1] - '0'); #elif __JHERETIC__ sprintf(lump, "E%uM%u", episode = tmp[0] == '*' ? 1 + M_Random() % 6 : tmp[0] - '0', map = tmp[1] == '*' ? 1 + M_Random() % 9 : tmp[1] - '0'); #elif __JHEXEN__ sprintf(lump, "%u%u", episode = tmp[0] == '*' ? M_Random() % 4 : tmp[0] - '0', map = tmp[1] == '*' ? M_Random() % 10 : tmp[1] - '0'); m = P_TranslateMap(atoi(lump)); if(m < 0) continue; sprintf(lump, "MAP%02u", m); #endif if(W_CheckNumForName(lump) >= 0) { tmp[0] = episode + '0'; tmp[1] = map + '0'; break; } else if(!has_random) { return -1; } } // Convert to a number. return atoi(tmp); } } } // Didn't find it. return -1; } void NetSv_CheckCycling(void) { int map, i, f; maprule_t rules; char msg[100], tmp[50]; if(!cyclingMaps) return; cycleCounter--; switch(cycleMode) { case CYCLE_IDLE: // Check if the current map should end. if(cycleCounter <= 0) { // Test every ten seconds. cycleCounter = 10 * TICSPERSEC; map = NetSv_ScanCycle(cycleIndex, &rules); if(map < 0) { map = NetSv_ScanCycle(cycleIndex = 0, &rules); if(map < 0) { // Hmm?! Abort cycling. Con_Message ("NetSv_CheckCycling: All of a sudden MapCycle is invalid!\n"); DD_Execute(false, "endcycle"); return; } } if(rules.usetime && mapTime > (rules.time * 60 - 29) * TICSPERSEC) { // Time runs out! cycleMode = CYCLE_COUNTDOWN; cycleCounter = 31 * TICSPERSEC; } if(rules.usefrags) { for(i = 0; i < MAXPLAYERS; i++) { if(!players[i].plr->inGame) continue; if((f = NetSv_GetFrags(i)) >= rules.frags) { sprintf(msg, "--- %s REACHES %i FRAGS ---", Net_GetPlayerName(i), f); NetSv_SendMessage(DDSP_ALL_PLAYERS, msg); S_StartSound(SOUND_VICTORY, NULL); cycleMode = CYCLE_COUNTDOWN; cycleCounter = 15 * TICSPERSEC; // No msg for 15 secs. break; } } } } break; case CYCLE_TELL_RULES: if(cycleCounter <= 0) { // Get the rules of the current map. NetSv_ScanCycle(cycleIndex, &rules); strcpy(msg, "MAP RULES: "); if(!rules.usetime && !rules.usefrags) strcat(msg, "NONE"); else { if(rules.usetime) { sprintf(tmp, "%i MINUTES", rules.time); strcat(msg, tmp); } if(rules.usefrags) { sprintf(tmp, "%s%i FRAGS", rules.usetime ? " OR " : "", rules.frags); strcat(msg, tmp); } } // Send it to all players. NetSv_SendMessage(DDSP_ALL_PLAYERS, msg); // Start checking. cycleMode = CYCLE_IDLE; } break; case CYCLE_COUNTDOWN: if(cycleCounter == 30 * TICSPERSEC || cycleCounter == 15 * TICSPERSEC || cycleCounter == 10 * TICSPERSEC || cycleCounter == 5 * TICSPERSEC) { sprintf(msg, "--- WARPING IN %i SECONDS ---", cycleCounter / TICSPERSEC); NetSv_SendMessage(DDSP_ALL_PLAYERS, msg); // Also, a warning sound. S_StartSound(SOUND_COUNTDOWN, NULL); } else if(cycleCounter <= 0) { // Next map, please! map = NetSv_ScanCycle(++cycleIndex, NULL); if(map < 0) { // Must be past the end? map = NetSv_ScanCycle(cycleIndex = 0, NULL); if(map < 0) { // Hmm?! Abort cycling. Con_Message ("NetSv_CheckCycling: All of a sudden MapCycle is invalid!\n"); DD_Execute(false, "endcycle"); return; } } // Warp to the next map. Don't bother with the intermission. NetSv_CycleToMapNum(map); } break; } } /** * Server calls this when new players enter the game. */ void NetSv_NewPlayerEnters(int plrNum) { player_t* plr = &players[plrNum]; Con_Message("NetSv_NewPlayerEnters: spawning player %i.\n", plrNum); plr->playerState = PST_REBORN; // Force an init. // Re-deal player starts. P_DealPlayerStarts(0); // Spawn the player into the world. if(deathmatch) { G_DeathMatchSpawnPlayer(plrNum); } else { #if __JHEXEN__ uint nextMapEntryPoint = rebornPosition; playerclass_t pClass = cfg.playerClass[plrNum]; #else uint nextMapEntryPoint = 0; playerclass_t pClass = PCLASS_PLAYER; #endif const playerstart_t* start; if((start = P_GetPlayerStart(nextMapEntryPoint, plrNum, false))) { P_SpawnPlayer(plrNum, pClass, start->pos[VX], start->pos[VY], start->pos[VZ], start->angle, start->spawnFlags, false, true); } else { P_SpawnPlayer(plrNum, pClass, 0, 0, 0, 0, MSF_Z_FLOOR, true, true); } //// \fixme Spawn a telefog in front of the player. } // Get rid of anybody at the starting spot. P_Telefrag(plr->plr->mo); } void NetSv_Intermission(int flags, int state, int time) { byte buffer[32], *ptr = buffer; if(IS_CLIENT) return; *ptr++ = flags; #if __JDOOM__ || __JDOOM64__ if(flags & IMF_BEGIN) { // Only include the necessary information. WRITE_SHORT(ptr, wmInfo.maxKills); WRITE_SHORT(ptr, wmInfo.maxItems); WRITE_SHORT(ptr, wmInfo.maxSecret); *ptr++ = wmInfo.nextMap; *ptr++ = wmInfo.currentMap; *ptr++ = wmInfo.didSecret; } #endif #if __JHEXEN__ || __JSTRIFE__ if(flags & IMF_BEGIN) { *ptr++ = state; // LeaveMap *ptr++ = time; // LeavePosition } #endif if(flags & IMF_STATE) *ptr++ = state; if(flags & IMF_TIME) WRITE_SHORT(ptr, time); Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_ORDERED, GPT_INTERMISSION, buffer, ptr - buffer); } /** * The actual script is sent to the clients. 'script' can be NULL. */ void NetSv_Finale(int flags, const char* script, const boolean* conds, byte numConds) { size_t len, scriptLen = 0; byte* buffer, *ptr; if(IS_CLIENT) return; // How much memory do we need? if(script) { flags |= FINF_SCRIPT; scriptLen = strlen(script) + 1; len = scriptLen + 2; // The end null and flags byte. // The number of conditions and their values. len += 1 + numConds; } else { // Just enough memory for the flags byte. len = 1; } ptr = buffer = Z_Malloc(len, PU_STATIC, 0); // First the flags. *ptr++ = flags; if(script) { int i; // The conditions. *ptr++ = numConds; for(i = 0; i < numConds; ++i) *ptr++ = conds[i]; // Then the script itself. memcpy(ptr, script, scriptLen + 1); ptr[scriptLen] = '\0'; } Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_ORDERED, GPT_FINALE2, buffer, len); Z_Free(buffer); } void NetSv_SendGameState(int flags, int to) { byte buffer[256], *ptr; int i; fixed_t gravity; if(IS_CLIENT) return; if(G_GetGameState() != GS_MAP) return; gravity = FLT2FIX(P_GetGravity()); // Print a short message that describes the game state. if(verbose || IS_DEDICATED) { Con_Printf("Game setup: ep%u map%u %s\n", gameEpisode+1, gameMap+1, gameConfigString); } // Send an update to all the players in the game. for(i = 0; i < MAXPLAYERS; ++i) { #if __JHEXEN__ || __JSTRIFE__ int gameStateSize = 16; #else int gameStateSize = 8; #endif //int k; if(!players[i].plr->inGame || (to != DDSP_ALL_PLAYERS && to != i)) continue; ptr = buffer; // The contents of the game state package are a bit messy // due to compatibility with older versions. #if __JDOOM__ || __JDOOM64__ ptr[0] = gameMode; #else ptr[0] = 0; #endif ptr[1] = flags; ptr[2] = gameEpisode+1; ptr[3] = gameMap+1; ptr[4] = (deathmatch & 0x3) | (!noMonstersParm? 0x4 : 0) #if !__JHEXEN__ | (respawnMonsters? 0x8 : 0) #else | 0 #endif | (cfg.jumpEnabled? 0x10 : 0) #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ | (gameSkill << 5); #else ; #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ ptr[5] = 0; #else ptr[5] = gameSkill & 0x7; #endif ptr[6] = (gravity >> 8) & 0xff; // low byte ptr[7] = (gravity >> 16) & 0xff; // high byte memset(ptr + 8, 0, 8); ptr += gameStateSize; if(flags & GSF_CAMERA_INIT) { mobj_t *mo = players[i].plr->mo; WRITE_SHORT(ptr, (int) mo->pos[VX]); WRITE_SHORT(ptr, (int) mo->pos[VY]); WRITE_SHORT(ptr, (int) mo->pos[VZ]); WRITE_SHORT(ptr, mo->angle >> 16); } // Send the packet. Net_SendPacket(i | DDSP_ORDERED, GPT_GAME_STATE, buffer, ptr - buffer); } } /** * More player state information. Had to be separate because of backwards * compatibility. */ void NetSv_SendPlayerState2(int srcPlrNum, int destPlrNum, int flags, boolean reliable) { int pType = (srcPlrNum == destPlrNum ? GPT_CONSOLEPLAYER_STATE2 : GPT_PLAYER_STATE2); player_t *pl = &players[srcPlrNum]; byte buffer[UPD_BUFFER_LEN], *ptr = buffer; int i, fl; // Check that this is a valid call. if(IS_CLIENT || !pl->plr->inGame || (destPlrNum >= 0 && destPlrNum < MAXPLAYERS && !players[destPlrNum].plr->inGame)) return; // Include the player number if necessary. if(pType == GPT_PLAYER_STATE2) *ptr++ = srcPlrNum; WRITE_LONG(ptr, flags); if(flags & PSF2_OWNED_WEAPONS) { // This supports up to 16 weapons. for(fl = 0, i = 0; i < NUM_WEAPON_TYPES; ++i) if(pl->weapons[i].owned) fl |= 1 << i; WRITE_SHORT(ptr, fl); } if(flags & PSF2_STATE) { *ptr++ = pl->playerState | #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Hexen doesn't have armortype. (pl->armorType << 4); #else 0; #endif *ptr++ = pl->cheats; } // Finally, send the packet. Net_SendPacket(destPlrNum | (reliable ? DDSP_ORDERED : 0), pType, buffer, ptr - buffer); } void NetSv_SendPlayerState(int srcPlrNum, int destPlrNum, int flags, boolean reliable) { int pType = srcPlrNum == destPlrNum ? GPT_CONSOLEPLAYER_STATE : GPT_PLAYER_STATE; player_t *pl = &players[srcPlrNum]; byte buffer[UPD_BUFFER_LEN], *ptr = buffer, fl; int i, k; if(IS_CLIENT || !pl->plr->inGame || (destPlrNum >= 0 && destPlrNum < MAXPLAYERS && !players[destPlrNum].plr->inGame)) return; // Include the player number if necessary. if(pType == GPT_PLAYER_STATE) *ptr++ = srcPlrNum; // The first bytes contain the flags. WRITE_SHORT(ptr, flags); if(flags & PSF_STATE) { *ptr++ = pl->playerState | #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Hexen doesn't have armortype. (pl->armorType << 4); #else 0; #endif } if(flags & PSF_HEALTH) *ptr++ = pl->health; if(flags & PSF_ARMOR_POINTS) { #if __JHEXEN__ // Hexen has many types of armor points, send them all. for(i = 0; i < NUMARMOR; ++i) *ptr++ = pl->armorPoints[i]; #else *ptr++ = pl->armorPoints; #endif } #if __JHERETIC__ || __JHEXEN__ if(flags & PSF_INVENTORY) { uint i, count = 0; for(i = 0; i < NUM_INVENTORYITEM_TYPES; ++i) count += (P_InventoryCount(srcPlrNum, IIT_FIRST + i)? 1 : 0); *ptr++ = count; if(count) { for(i = 0; i < NUM_INVENTORYITEM_TYPES; ++i) { inventoryitemtype_t type = IIT_FIRST + i; uint num = P_InventoryCount(srcPlrNum, type); if(num) { WRITE_SHORT(ptr, (type & 0xff) | ((num & 0xff) << 8)); } } } } #endif if(flags & PSF_POWERS) { // First see which powers should be sent. #if __JHEXEN__ || __JSTRIFE__ for(i = 1, *ptr = 0; i < NUM_POWER_TYPES; ++i) if(pl->powers[i]) *ptr |= 1 << (i - 1); #else for(i = 0, *ptr = 0; i < NUM_POWER_TYPES; ++i) { # if __JDOOM__ || __JDOOM64__ if(i == PT_IRONFEET || i == PT_STRENGTH) continue; # endif if(pl->powers[i]) *ptr |= 1 << i; } #endif ptr++; // Send the non-zero powers. #if __JHEXEN__ || __JSTRIFE__ for(i = 1; i < NUM_POWER_TYPES; ++i) if(pl->powers[i]) *ptr++ = (pl->powers[i] + 34) / 35; #else for(i = 0; i < NUM_POWER_TYPES; ++i) { # if __JDOOM__ || __JDOOM64__ if(i == PT_IRONFEET || i == PT_STRENGTH) continue; # endif if(pl->powers[i]) *ptr++ = (pl->powers[i] + 34) / 35; // Send as seconds. } #endif } if(flags & PSF_KEYS) { *ptr = 0; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ for(i = 0; i < NUM_KEY_TYPES; ++i) if(pl->keys[i]) *ptr |= 1 << i; #endif ptr++; } if(flags & PSF_FRAGS) { byte *count = ptr++; // We'll send all non-zero frags. The topmost four bits of // the word define the player number. for(i = 0, *count = 0; i < MAXPLAYERS; ++i) if(pl->frags[i]) { WRITE_SHORT(ptr, (i << 12) | pl->frags[i]); (*count)++; } } if(flags & PSF_OWNED_WEAPONS) { for(k = 0, i = 0; i < NUM_WEAPON_TYPES; ++i) if(pl->weapons[i].owned) k |= 1 << i; *ptr++ = k; } if(flags & PSF_AMMO) { for(i = 0; i < NUM_AMMO_TYPES; ++i) #if __JHEXEN__ || __JSTRIFE__ *ptr++ = pl->ammo[i].owned; #else WRITE_SHORT(ptr, pl->ammo[i].owned); #endif } if(flags & PSF_MAX_AMMO) { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Hexen has no use for max ammo. for(i = 0; i < NUM_AMMO_TYPES; ++i) WRITE_SHORT(ptr, pl->ammo[i].max); #endif } if(flags & PSF_COUNTERS) { WRITE_SHORT(ptr, pl->killCount); *ptr++ = pl->itemCount; *ptr++ = pl->secretCount; } if((flags & PSF_PENDING_WEAPON) || (flags & PSF_READY_WEAPON)) { // These two will be in the same byte. fl = 0; if(flags & PSF_PENDING_WEAPON) fl |= pl->pendingWeapon & 0xf; if(flags & PSF_READY_WEAPON) fl |= (pl->readyWeapon & 0xf) << 4; *ptr++ = fl; } if(flags & PSF_VIEW_HEIGHT) { // @todo Do clients really need to know this? *ptr++ = (byte) pl->viewHeight; } #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ if(flags & PSF_MORPH_TIME) { // Send as seconds. *ptr++ = (pl->morphTics + 34) / 35; } #endif #if __JHEXEN__ || __JSTRIFE__ if(flags & PSF_LOCAL_QUAKE) { // Send the "quaking" state. *ptr++ = localQuakeHappening[srcPlrNum]; } #endif // Finally, send the packet. Net_SendPacket(destPlrNum | (reliable ? DDSP_ORDERED : 0), pType, buffer, ptr - buffer); } void NetSv_PSpriteChange(int plrNum, int state) { /* byte buffer[20], *ptr = buffer; if(IS_CLIENT) return; WRITE_SHORT(ptr, state); Net_SendPacket(plrNum, GPT_PSPRITE_STATE, buffer, ptr-buffer); */ } void NetSv_SendPlayerInfo(int whose, int to_whom) { byte buffer[10], *ptr = buffer; if(IS_CLIENT) return; *ptr++ = whose; *ptr++ = cfg.playerColor[whose]; #if __JHERETIC__ || __JHEXEN__ *ptr++ = cfg.playerClass[whose]; #endif Net_SendPacket(to_whom | DDSP_ORDERED, GPT_PLAYER_INFO, buffer, ptr - buffer); } void NetSv_ChangePlayerInfo(int from, byte* data) { int col; player_t* pl = &players[from]; // Color is first. col = *data++; cfg.playerColor[from] = PLR_COLOR(from, col); #if __JHERETIC__ || __JHEXEN__ cfg.playerClass[from] = *data++; Con_Printf("NetSv_ChangePlayerInfo: pl%i, col=%i, class=%i\n", from, cfg.playerColor[from], cfg.playerClass[from]); #else Con_Printf("NetSv_ChangePlayerInfo: pl%i, col=%i\n", from, cfg.playerColor[from]); #endif #if __JHEXEN__ // The 'colormap' variable controls the setting of the color // translation flags when the player is (re)spawned (which will // be done in P_PlayerChangeClass). pl->colorMap = cfg.playerColor[from]; #else if(pl->plr->mo) { // Change the player's mobj's color translation flags. pl->plr->mo->flags &= ~MF_TRANSLATION; pl->plr->mo->flags |= col << MF_TRANSSHIFT; } #endif #if __JHEXEN__ P_PlayerChangeClass(pl, cfg.playerClass[from]); #endif // Re-deal start spots. P_DealPlayerStarts(0); // Tell the other clients about the change. NetSv_SendPlayerInfo(from, DDSP_ALL_PLAYERS); } /** * Sends the frags of player 'whose' to all other players. */ void NetSv_FragsForAll(player_t *player) { NetSv_SendPlayerState(player - players, DDSP_ALL_PLAYERS, PSF_FRAGS, true); } /** * Calculates the frags of player 'pl'. */ int NetSv_GetFrags(int pl) { int i, frags = 0; for(i = 0; i < MAXPLAYERS; ++i) { #if __JDOOM__ || __JDOOM64__ frags += players[pl].frags[i] * (i == pl ? -1 : 1); #else frags += players[pl].frags[i]; #endif } return frags; } /** * Send one of the kill messages, depending on the weapon of the killer. */ void NetSv_KillMessage(player_t *killer, player_t *fragged, boolean stomping) { #if __JDOOM__ || __JDOOM64__ char buf[160], *in, tmp[2]; if(!cfg.killMessages || !deathmatch) return; buf[0] = 0; tmp[1] = 0; // Choose the right kill message template. in = GET_TXT(stomping ? TXT_KILLMSG_STOMP : killer == fragged ? TXT_KILLMSG_SUICIDE : TXT_KILLMSG_WEAPON0 + killer->readyWeapon); for(; *in; in++) { if(in[0] == '%') { if(in[1] == '1') { strcat(buf, Net_GetPlayerName(killer - players)); in++; continue; } if(in[1] == '2') { strcat(buf, Net_GetPlayerName(fragged - players)); in++; continue; } if(in[1] == '%') in++; } tmp[0] = *in; strcat(buf, tmp); } // Send the message to everybody. NetSv_SendMessage(DDSP_ALL_PLAYERS, buf); #endif } void NetSv_SendPlayerClass(int pnum, char cls) { Net_SendPacket(pnum | DDSP_CONFIRM, GPT_CLASS, &cls, 1); } /** * The default jump power is 9. */ void NetSv_SendJumpPower(int target, float power) { char msg[50]; if(!IS_SERVER) return; power = FLOAT(power); memcpy((void *) msg, &power, 4); Net_SendPacket(target | DDSP_CONFIRM, GPT_JUMP_POWER, msg, 4); } /** * Process the requested cheat command, if possible. */ void NetSv_DoCheat(int player, const char* data) { char command[40]; memset(command, 0, sizeof(command)); strncpy(command, data, sizeof(command) - 1); // If cheating is not allowed, we ain't doing nuthin'. if(!netSvAllowCheats) return; if(!strnicmp(command, "god", 3) || !strnicmp(command, "noclip", 6) || !strnicmp(command, "suicide", 7) || !strnicmp(command, "give", 4)) { DD_Executef(false, "%s %i", command, player); } } /** * Process the requested player action, if possible. */ void NetSv_DoAction(int player, const char *data) { const int *ptr = (const int*) data; int type = 0; float pos[3]; angle_t angle = 0; float lookDir = 0; int readyWeapon = 0; player_t *pl = &players[player]; type = LONG(*ptr++); pos[VX] = FIX2FLT(LONG(*ptr++)); pos[VY] = FIX2FLT(LONG(*ptr++)); pos[VZ] = FIX2FLT(LONG(*ptr++)); angle = LONG(*ptr++); lookDir = FIX2FLT( LONG(*ptr++) ); readyWeapon = LONG(*ptr++); #ifdef _DEBUG Con_Message("NetSv_DoAction: player=%i, type=%i, xyz=(%.1f,%.1f,%.1f)\n " "angle=%x lookDir=%g\n", player, type, pos[VX], pos[VY], pos[VZ], angle, lookDir); #endif if(pl->playerState == PST_DEAD) { // This player is dead. Rise, my friend! P_PlayerReborn(pl); return; } switch(type) { case GPA_USE: case GPA_FIRE: if(pl->plr->mo) { if(P_CheckPosition3fv(pl->plr->mo, pos)) { P_MobjUnlink(pl->plr->mo); pl->plr->mo->pos[VX] = pos[VX]; pl->plr->mo->pos[VY] = pos[VY]; pl->plr->mo->pos[VZ] = pos[VZ]; P_MobjLink(pl->plr->mo, DDLINK_SECTOR | DDLINK_BLOCKMAP); pl->plr->mo->floorZ = tmFloorZ; pl->plr->mo->ceilingZ = tmCeilingZ; } pl->plr->mo->angle = angle; pl->plr->lookDir = lookDir; if(type == GPA_USE) P_UseLines(pl); else P_FireWeapon(pl); } break; } } void NetSv_SaveGame(unsigned int game_id) { if(!IS_SERVER || !IS_NETGAME) return; // This will make the clients save their games. Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_CONFIRM, GPT_SAVE, &game_id, 4); } void NetSv_LoadGame(unsigned int game_id) { if(!IS_SERVER || !IS_NETGAME) return; // The clients must tell their old console numbers. Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_CONFIRM, GPT_LOAD, &game_id, 4); } /** * Inform all clients about a change in the 'pausedness' of a game. */ void NetSv_Paused(boolean isPaused) { char setPause = (isPaused != false); if(!IS_SERVER || !IS_NETGAME) return; Net_SendPacket(DDSP_ALL_PLAYERS | DDSP_CONFIRM, GPT_PAUSE, &setPause, 1); } void NetSv_SendMessageEx(int plrNum, char *msg, boolean yellow) { if(IS_CLIENT || !netSvAllowSendMsg) return; if(plrNum >= 0 && plrNum < MAXPLAYERS) if(!players[plrNum].plr->inGame) return; if(plrNum == DDSP_ALL_PLAYERS) { // Also show locally. No sound is played! D_NetMessageNoSound(CONSOLEPLAYER, msg); } Net_SendPacket(plrNum | DDSP_ORDERED, yellow ? GPT_YELLOW_MESSAGE : GPT_MESSAGE, msg, strlen(msg) + 1); } void NetSv_SendMessage(int plrNum, char *msg) { NetSv_SendMessageEx(plrNum, msg, false); } void NetSv_SendYellowMessage(int plrNum, char *msg) { NetSv_SendMessageEx(plrNum, msg, true); } void P_Telefrag(mobj_t *thing) { P_TeleportMove(thing, thing->pos[VX], thing->pos[VY], false); } /** * Handles the console commands "startcycle" and "endcycle". */ DEFCC(CCmdMapCycle) { int map; if(!IS_SERVER) { Con_Printf("Only allowed for a server.\n"); return false; } if(!stricmp(argv[0], "startcycle")) // (Re)start rotation? { // Find the first map in the sequence. map = NetSv_ScanCycle(cycleIndex = 0, 0); if(map < 0) { Con_Printf("MapCycle \"%s\" is invalid.\n", mapCycle); return false; } // Warp there. NetSv_CycleToMapNum(map); cyclingMaps = true; } else { // OK, then we need to end it. if(cyclingMaps) { cyclingMaps = false; NetSv_SendMessage(DDSP_ALL_PLAYERS, "MAP ROTATION ENDS"); } } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_start.c0000644000175000017500000010070011357170242022443 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_start.c */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #if __JDOOM__ # include "jdoom.h" # include "r_common.h" # include "hu_stuff.h" #elif __JDOOM64__ # include "jdoom64.h" # include "r_common.h" # include "hu_stuff.h" #elif __JHERETIC__ # include "jheretic.h" # include "r_common.h" # include "hu_stuff.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "p_tick.h" #include "p_mapsetup.h" #include "p_user.h" #include "d_net.h" #include "p_map.h" #include "p_terraintype.h" #include "g_common.h" #include "p_start.h" #include "p_actor.h" #include "p_switch.h" #include "g_defs.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ # define TELEPORTSOUND SFX_TELEPT # define MAX_START_SPOTS 4 // Maximum number of different player starts. #else # define TELEPORTSOUND SFX_TELEPORT # define MAX_START_SPOTS 8 #endif // Time interval for item respawning. #define SPAWNQUEUE_MAX 128 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- uint numMapSpots; mapspot_t* mapSpots; #if __JHERETIC__ int maceSpotCount; mapspot_t* maceSpots; int bossSpotCount; mapspot_t* bossSpots; #endif // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int numPlayerStarts = 0; static playerstart_t* playerStarts; static int numPlayerDMStarts = 0; static playerstart_t* deathmatchStarts; // CODE -------------------------------------------------------------------- static boolean fuzzySpawnPosition(float* x, float* y, float* z, angle_t* angle, int* spawnFlags) { #define XOFFSET (33) // Player radius = 16 #define YOFFSET (33) // Player radius = 16 int i; assert(x); assert(y); // Try some spots in the vicinity. for(i = 0; i < 9; ++i) { float pos[2]; pos[VX] = *x; pos[VY] = *y; if(i != 0) { int k = (i == 4 ? 0 : i); // Move a bit. pos[VX] += (k % 3 - 1) * XOFFSET; pos[VY] += (k / 3 - 1) * YOFFSET; } if(P_CheckSpot(pos[VX], pos[VY])) { *x = pos[VX]; *y = pos[VY]; return true; } } #undef XOFFSET #undef YOFFSET return false; } /** * Given a doomednum, look up the associated mobj type. * * @param doomEdNum Doom Editor (Thing) Number to look up. * @return The associated mobj type if found else @c MT_NONE. */ mobjtype_t P_DoomEdNumToMobjType(int doomEdNum) { int i; for(i = 0; i < Get(DD_NUMMOBJTYPES); ++i) { if(doomEdNum == MOBJINFO[i].doomEdNum) return i; } return MT_NONE; } /** * Initializes various playsim related data */ void P_Init(void) { #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ P_InitInventory(); #endif #if __JHEXEN__ P_InitMapInfo(); #endif P_InitSwitchList(); P_InitPicAnims(); P_InitTerrainTypes(); #if __JHERETIC__ || __JHEXEN__ || __JSTRIFE__ P_InitLava(); #endif maxHealth = 100; GetDefInt("Player|Max Health", &maxHealth); #if __JDOOM__ || __JDOOM64__ healthLimit = 200; godModeHealth = 100; megaSphereHealth = 200; soulSphereHealth = 100; soulSphereLimit = 200; armorPoints[0] = 100; armorPoints[1] = armorPoints[2] = armorPoints[3] = 200; armorClass[0] = 1; armorClass[1] = armorClass[2] = armorClass[3] = 2; GetDefInt("Player|Health Limit", &healthLimit); GetDefInt("Player|God Health", &godModeHealth); GetDefInt("Player|Green Armor", &armorPoints[0]); GetDefInt("Player|Blue Armor", &armorPoints[1]); GetDefInt("Player|IDFA Armor", &armorPoints[2]); GetDefInt("Player|IDKFA Armor", &armorPoints[3]); GetDefInt("Player|Green Armor Class", &armorClass[0]); GetDefInt("Player|Blue Armor Class", &armorClass[1]); GetDefInt("Player|IDFA Armor Class", &armorClass[2]); GetDefInt("Player|IDKFA Armor Class", &armorClass[3]); GetDefInt("MegaSphere|Give|Health", &megaSphereHealth); GetDefInt("SoulSphere|Give|Health", &soulSphereHealth); GetDefInt("SoulSphere|Give|Health Limit", &soulSphereLimit); #endif } void P_CreatePlayerStart(int defaultPlrNum, uint entryPoint, boolean deathmatch, float x, float y, float z, angle_t angle, int spawnFlags) { playerstart_t* start; if(deathmatch) { deathmatchStarts = Z_Realloc(deathmatchStarts, sizeof(playerstart_t) * ++numPlayerDMStarts, PU_MAP); start = &deathmatchStarts[numPlayerDMStarts - 1]; } else { playerStarts = Z_Realloc(playerStarts, sizeof(playerstart_t) * ++numPlayerStarts, PU_MAP); start = &playerStarts[numPlayerStarts - 1]; } start->plrNum = defaultPlrNum; start->entryPoint = entryPoint; start->pos[VX] = x; start->pos[VY] = y; start->pos[VZ] = z; start->angle = angle; start->spawnFlags = spawnFlags; } void P_DestroyPlayerStarts(void) { if(playerStarts) Z_Free(playerStarts); playerStarts = NULL; numPlayerStarts = 0; if(deathmatchStarts) Z_Free(deathmatchStarts); deathmatchStarts = NULL; numPlayerDMStarts = 0; } /** * @return The correct start for the player. The start is in * the given group for specified entry point. */ const playerstart_t* P_GetPlayerStart(uint entryPoint, int pnum, boolean deathmatch) { #if __JHEXEN__ int i; const playerstart_t* def = NULL; #endif if((deathmatch && !numPlayerDMStarts) || !numPlayerStarts) return NULL; if(pnum < 0) pnum = P_Random() % (deathmatch? numPlayerDMStarts:numPlayerStarts); else pnum = MINMAX_OF(0, pnum, MAXPLAYERS-1); if(deathmatch) { // In deathmatch, entry point is ignored. return &deathmatchStarts[pnum]; } #if __JHEXEN__ for(i = 0; i < numPlayerStarts; ++i) { const playerstart_t* start = &playerStarts[i]; if(start->entryPoint == nextMapEntryPoint && start->plrNum - 1 == pnum) return start; if(!start->entryPoint && start->plrNum - 1 == pnum) def = start; } // Return the default choice. return def; #else return &playerStarts[players[pnum].startSpot]; #endif } uint P_GetNumPlayerStarts(boolean deathmatch) { if(deathmatch) return numPlayerDMStarts; return numPlayerStarts; } /** * Gives all the players in the game a playerstart. * Only needed in co-op games (start spots are random in deathmatch). */ void P_DealPlayerStarts(uint entryPoint) { int i; if(!numPlayerStarts) { Con_Message("P_DealPlayerStarts: Warning, no player starts!\n"); return; } // First assign one start per player, only accepting perfect matches. for(i = 0; i < MAXPLAYERS; ++i) { int k, spotNumber; player_t* pl = &players[i]; if(!pl->plr->inGame) continue; // The number of the start spot this player will use. spotNumber = i % MAX_START_SPOTS; pl->startSpot = -1; for(k = 0; k < numPlayerStarts; ++k) { const playerstart_t* start = &playerStarts[k]; if(spotNumber == start->plrNum - 1 && start->entryPoint == entryPoint) { // A match! pl->startSpot = k; // Keep looking. } } // If still without a start spot, assign one randomly. if(pl->startSpot == -1) { // It's likely that some players will get the same start spots. pl->startSpot = M_Random() % numPlayerStarts; } } if(IS_NETGAME) { Con_Printf("Player starting spots:\n"); for(i = 0; i < MAXPLAYERS; ++i) { player_t* pl = &players[i]; if(!pl->plr->inGame) continue; Con_Printf("- pl%i: color %i, spot %i\n", i, cfg.playerColor[i], pl->startSpot); } } } /** * Called when a player is spawned into the map. Most of the player * structure stays unchanged between maps. */ void P_SpawnPlayer(int plrNum, playerclass_t pClass, float x, float y, float z, angle_t angle, int spawnFlags, boolean makeCamera, boolean pickupItems) { player_t* p; mobj_t* mo; plrNum = MINMAX_OF(0, plrNum, MAXPLAYERS - 1); // Not playing? if(!players[plrNum].plr->inGame) return; pClass = MINMAX_OF(0, pClass, NUM_PLAYER_CLASSES - 1); /* $unifiedangles */ if(!(mo = P_SpawnMobj3f(PCLASS_INFO(pClass)->mobjType, x, y, z, angle, spawnFlags))) Con_Error("P_SpawnPlayer: Failed spawning mobj for player %i " "(class:%i) pos:[%g, %g, %g] angle:%i.", plrNum, pClass, x, y, z, angle); p = &players[plrNum]; if(p->playerState == PST_REBORN) G_PlayerReborn(plrNum); // \fixme Should this not occur before the reborn? p->class = pClass; // With clients all player mobjs are remote, even the CONSOLEPLAYER. if(IS_CLIENT) { mo->flags &= ~MF_SOLID; mo->ddFlags = DDMF_REMOTE | DDMF_DONTDRAW; // The real flags are received from the server later on. } // Set color translations for player sprites. #if __JHEXEN__ if(p->class == PCLASS_FIGHTER && (p->colorMap == 0 || p->colorMap == 2)) { // The first type should be blue, and the third should be the // Fighter's original gold color //if(spot->type == 1) if(p->colorMap == 0) { mo->flags |= 2 << MF_TRANSSHIFT; } } else if(p->colorMap > 0 && p->colorMap < 8) { // Set color translation bits for player sprites //mo->flags |= (spot->type-1)<flags |= p->colorMap << MF_TRANSSHIFT; } #else if(cfg.playerColor[plrNum] > 0) mo->flags |= cfg.playerColor[plrNum] << MF_TRANSSHIFT; #endif p->plr->lookDir = 0; /* $unifiedangles */ p->plr->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; p->jumpTics = 0; p->airCounter = 0; mo->player = p; mo->dPlayer = p->plr; mo->health = p->health; p->plr->mo = mo; p->playerState = PST_LIVE; p->refire = 0; p->damageCount = 0; p->bonusCount = 0; #if __JHEXEN__ p->poisonCount = 0; #endif #if __JHERETIC__ || __JHEXEN__ p->morphTics = 0; #endif #if __JHERETIC__ p->rain1 = NULL; p->rain2 = NULL; #endif p->plr->extraLight = 0; p->plr->fixedColorMap = 0; if(makeCamera) p->plr->flags |= DDPF_CAMERA; if(p->plr->flags & DDPF_CAMERA) { p->plr->mo->pos[VZ] += (float) cfg.plrViewHeight; p->viewHeight = 0; } else p->viewHeight = (float) cfg.plrViewHeight; p->viewZ = p->plr->mo->pos[VZ] + p->viewHeight; // Give all cards in death match mode. if(deathmatch) { #if __JHEXEN__ p->keys = 2047; #else int i; for(i = 0; i < NUM_KEY_TYPES; ++i) p->keys[i] = true; #endif } p->pendingWeapon = WT_NOCHANGE; if(pickupItems) { // Check the current position so that any interactions which would // occur as a result of collision happen immediately // (e.g., weapon pickups at the current position will be collected). P_CheckPosition3fv(mo, mo->pos); } if(p->pendingWeapon != WT_NOCHANGE) p->readyWeapon = p->pendingWeapon; else p->pendingWeapon = p->readyWeapon; // Setup gun psprite. P_SetupPsprites(p); // Wake up the status bar. ST_Start(p - players); // Wake up the heads up text. HU_Start(p - players); #if __JHEXEN__ cfg.playerClass[plrNum] = pClass; NetSv_SendPlayerInfo(plrNum, DDSP_ALL_PLAYERS); #endif } static void spawnPlayer(int plrNum, playerclass_t pClass, float x, float y, float z, angle_t angle, int spawnFlags, boolean makeCamera, boolean doTeleSpark, boolean doTeleFrag) { player_t* plr; #if __JDOOM__ || __JDOOM64__ boolean queueBody = (plrNum >= 0? true : false); #endif boolean pickupItems = true; /* $voodoodolls */ if(plrNum < 0) { plrNum = -plrNum - 1; pickupItems = false; } plrNum = MINMAX_OF(0, plrNum, MAXPLAYERS-1); plr = &players[plrNum]; #if __JDOOM__ || __JDOOM64__ if(queueBody) G_QueueBody(plr->plr->mo); #endif P_SpawnPlayer(plrNum, pClass, x, y, z, angle, spawnFlags, makeCamera, pickupItems); // Spawn a teleport fog? if(doTeleSpark && !makeCamera) { mobj_t* mo; uint an = angle >> ANGLETOFINESHIFT; x += 20 * FIX2FLT(finecosine[an]); y += 20 * FIX2FLT(finesine[an]); if((mo = P_SpawnTeleFog(x, y, angle + ANG180))) { // Don't start sound on first frame. if(mapTime > 1) S_StartSound(TELEPORTSOUND, mo); } } // Camera players do not telefrag. if(!makeCamera && doTeleFrag) P_Telefrag(plr->plr->mo); } /** * Called by G_DoReborn if playing a net game. */ void P_RebornPlayer(int plrNum) { #if __JHEXEN__ int oldKeys = 0, oldPieces = 0, bestWeapon; boolean oldWeaponOwned[NUM_WEAPON_TYPES]; #endif player_t* p; #if __JHEXEN__ playerclass_t pClass = cfg.playerClass[plrNum]; #else playerclass_t pClass = PCLASS_PLAYER; #endif float pos[3]; angle_t angle; int spawnFlags; boolean makeCamera; if(plrNum < 0 || plrNum >= MAXPLAYERS) return; // Wha? p = &players[plrNum]; Con_Printf("P_RebornPlayer: %i.\n", plrNum); if(p->plr->mo) { // First dissasociate the corpse. p->plr->mo->player = NULL; p->plr->mo->dPlayer = NULL; } if(G_GetGameState() != GS_MAP) return; // Nothing else to do. // Spawn at random spot if in death match. if(deathmatch) { G_DeathMatchSpawnPlayer(plrNum); return; } // Save player state? if(!IS_CLIENT) { #if __JHEXEN__ int i; // Cooperative net-play, retain keys and weapons oldKeys = p->keys; oldPieces = p->pieces; for(i = 0; i < NUM_WEAPON_TYPES; ++i) oldWeaponOwned[i] = p->weapons[i].owned; #endif } // Determine the spawn position. if(IS_CLIENT) { // Anywhere will do for now. pos[VX] = pos[VY] = pos[VZ] = 0; angle = 0; spawnFlags = MSF_Z_FLOOR; makeCamera = true; // Clients spawn as spectators. } else { #if __JHEXEN__ uint entryPoint = rebornPosition; #else uint entryPoint = 0; #endif boolean foundSpot = false; const playerstart_t* assigned = P_GetPlayerStart(entryPoint, plrNum, false); if(assigned && P_CheckSpot(assigned->pos[VX], assigned->pos[VY])) { // Appropriate player start spot is open. Con_Printf("- spawning at assigned spot\n"); pos[VX] = assigned->pos[VX]; pos[VY] = assigned->pos[VY]; pos[VZ] = assigned->pos[VZ]; angle = assigned->angle; spawnFlags = assigned->spawnFlags; foundSpot = true; } #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ else { Con_Printf("- force spawning at %i.\n", p->startSpot); if(assigned) { pos[VX] = assigned->pos[VX]; pos[VY] = assigned->pos[VY]; pos[VZ] = assigned->pos[VZ]; angle = assigned->angle; spawnFlags = assigned->spawnFlags; // "Fuzz" the spawn position looking for room nearby. makeCamera = !fuzzySpawnPosition(&pos[VX], &pos[VY], &pos[VZ], &angle, &spawnFlags); } else { pos[VX] = pos[VY] = pos[VZ] = 0; angle = 0; spawnFlags = MSF_Z_FLOOR; makeCamera = true; } } #else else { int i; // Try to spawn at one of the other player start spots. for(i = 0; i < MAXPLAYERS; ++i) { const playerstart_t* start; if((start = P_GetPlayerStart(rebornPosition, i, false))) { if(P_CheckSpot(start->pos[VX], start->pos[VY])) { // Found an open start spot. pos[VX] = start->pos[VX]; pos[VY] = start->pos[VY]; pos[VZ] = start->pos[VZ]; angle = start->angle; spawnFlags = start->spawnFlags; foundSpot = true; break; } } } } if(!foundSpot) { // Player's going to be inside something. const playerstart_t* start; if((start = P_GetPlayerStart(rebornPosition, plrNum, false))) { pos[VX] = start->pos[VX]; pos[VY] = start->pos[VY]; pos[VZ] = start->pos[VZ]; angle = start->angle; spawnFlags = start->spawnFlags; } else { pos[VX] = pos[VY] = pos[VZ] = 0; angle = 0; spawnFlags = MSF_Z_FLOOR; makeCamera = true; } } #endif } spawnPlayer(plrNum, pClass, pos[VX], pos[VY], pos[VZ], angle, spawnFlags, makeCamera, true, true); // Restore player state? if(!IS_CLIENT) { #if __JHEXEN__ int i; // Restore keys and weapons p->keys = oldKeys; p->pieces = oldPieces; for(bestWeapon = 0, i = 0; i < NUM_WEAPON_TYPES; ++i) { if(oldWeaponOwned[i]) { bestWeapon = i; p->weapons[i].owned = true; } } p->ammo[AT_BLUEMANA].owned = 25; //// \fixme values.ded p->ammo[AT_GREENMANA].owned = 25; //// \fixme values.ded if(bestWeapon) { // Bring up the best weapon. p->pendingWeapon = bestWeapon; } #endif } } /** * @return @c false if the player cannot be respawned at the * given location because something is occupying it. */ boolean P_CheckSpot(float x, float y) { #if __JHEXEN__ #define DUMMY_TYPE MT_PLAYER_FIGHTER #else #define DUMMY_TYPE MT_PLAYER #endif float pos[3]; mobj_t* dummy; boolean result; pos[VX] = x; pos[VY] = y; pos[VZ] = 0; // Create a dummy to test with. if(!(dummy = P_SpawnMobj3fv(DUMMY_TYPE, pos, 0, MSF_Z_FLOOR))) Con_Error("P_CheckSpot: Failed creating dummy mobj."); dummy->flags &= ~MF_PICKUP; dummy->flags2 &= ~MF2_PASSMOBJ; result = P_CheckPosition3fv(dummy, pos); P_MobjRemove(dummy, true); return result; #undef DUMMY_TYPE } #if __JHERETIC__ void P_AddMaceSpot(float x, float y, angle_t angle) { mapspot_t* spot; maceSpots = Z_Realloc(maceSpots, sizeof(mapspot_t) * ++maceSpotCount, PU_MAP); spot = &maceSpots[maceSpotCount-1]; spot->pos[VX] = x; spot->pos[VY] = y; spot->angle = angle; } void P_AddBossSpot(float x, float y, angle_t angle) { mapspot_t* spot; bossSpots = Z_Realloc(bossSpots, sizeof(mapspot_t) * ++bossSpotCount, PU_MAP); spot = &bossSpots[bossSpotCount-1]; spot->pos[VX] = x; spot->pos[VY] = y; spot->angle = angle; } #endif /** * Spawns all players, using the method appropriate for current game mode. * Called during map setup. */ void P_SpawnPlayers(void) { int i; // If deathmatch, randomly spawn the active players. if(deathmatch) { for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) { players[i].plr->mo = NULL; G_DeathMatchSpawnPlayer(i); } } else { #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ if(!IS_NETGAME) { /* $voodoodolls */ for(i = 0; i < numPlayerStarts; ++i) { if(players[0].startSpot != i && playerStarts[i].plrNum == 1) { const playerstart_t* start = &playerStarts[i]; spawnPlayer(-1, PCLASS_PLAYER, start->pos[VX], start->pos[VY], start->pos[VZ], start->angle, start->spawnFlags, false, false, false); } } } #endif // Spawn everybody at their assigned places. // Might get messy if there aren't enough starts. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) { const playerstart_t* start = NULL; float pos[3]; angle_t angle; int spawnFlags; boolean makeCamera; #if __JHEXEN__ playerclass_t pClass = cfg.playerClass[i]; #else playerclass_t pClass = PCLASS_PLAYER; #endif if(players[i].startSpot < numPlayerStarts) start = &playerStarts[players[i].startSpot]; if(start) { pos[VX] = start->pos[VX]; pos[VY] = start->pos[VY]; pos[VZ] = start->pos[VZ]; angle = start->angle; spawnFlags = start->spawnFlags; // "Fuzz" the spawn position looking for room nearby. makeCamera = !fuzzySpawnPosition(&pos[VX], &pos[VY], &pos[VZ], &angle, &spawnFlags); } else { pos[VX] = pos[VY] = pos[VZ] = 0; angle = 0; spawnFlags = MSF_Z_FLOOR; makeCamera = true; } spawnPlayer(i, pClass, pos[VX], pos[VY], pos[VZ], angle, spawnFlags, makeCamera, false, true); } } } /** * Spawns a player at one of the random death match spots. */ void G_DeathMatchSpawnPlayer(int playerNum) { int i; playerclass_t pClass; playerNum = MINMAX_OF(0, playerNum, MAXPLAYERS-1); #if __JHEXEN__ if(randomClassParm) { pClass = P_Random() % 3; if(pClass == cfg.playerClass[playerNum]) pClass = (pClass + 1) % 3; } else { pClass = cfg.playerClass[playerNum]; } #else pClass = PCLASS_PLAYER; #endif if(IS_CLIENT) { if(G_GetGameState() == GS_MAP) { // Anywhere will do, for now. spawnPlayer(playerNum, pClass, 0, 0, 0, 0, MSF_Z_FLOOR, false, false, false); } return; } // Now let's find an available deathmatch start. if(numPlayerDMStarts < 2) Con_Error("G_DeathMatchSpawnPlayer: Error, minimum of two " "(deathmatch) mapspots required for deathmatch."); for(i = 0; i < 20; ++i) { const playerstart_t* start = &deathmatchStarts[P_Random() % numPlayerDMStarts]; if(P_CheckSpot(start->pos[VX], start->pos[VY])) { spawnPlayer(playerNum, pClass, start->pos[VX], start->pos[VY], start->pos[VZ], start->angle, start->spawnFlags, false, true, true); return; } } Con_Error("G_DeathMatchSpawnPlayer: Failed to spawn player %i.", playerNum); } typedef struct { float pos[2], minDist; } unstuckmobjinlinedefparams_t; boolean unstuckMobjInLinedef(linedef_t* li, void* context) { unstuckmobjinlinedefparams_t *params = (unstuckmobjinlinedefparams_t*) context; if(!P_GetPtrp(li, DMU_BACK_SECTOR)) { float pos, linePoint[2], lineDelta[2], result[2]; /** * Project the point (mo position) onto this linedef. If the * resultant point lies on the linedef and the current position is * in range of that point, adjust the position moving it away from * the projected point. */ P_GetFloatpv(P_GetPtrp(li, DMU_VERTEX0), DMU_XY, linePoint); P_GetFloatpv(li, DMU_DXY, lineDelta); pos = M_ProjectPointOnLine(params->pos, linePoint, lineDelta, 0, result); if(pos > 0 && pos < 1) { float dist = P_ApproxDistance(params->pos[VX] - result[VX], params->pos[VY] - result[VY]); if(dist >= 0 && dist < params->minDist) { float len, unit[2], normal[2]; // Derive the line normal. len = P_ApproxDistance(lineDelta[0], lineDelta[1]); if(len) { unit[VX] = lineDelta[0] / len; unit[VY] = lineDelta[1] / len; } else { unit[VX] = unit[VY] = 0; } normal[VX] = unit[VY]; normal[VY] = -unit[VX]; // Adjust the position. params->pos[VX] += normal[VX] * params->minDist; params->pos[VY] += normal[VY] * params->minDist; } } } return true; // Continue iteration. } boolean iterateLinedefsNearMobj(thinker_t* th, void* context) { mobj_t* mo = (mobj_t*) th; mobjtype_t type = *((mobjtype_t*) context); float aabb[4]; unstuckmobjinlinedefparams_t params; // \todo Why not type-prune at an earlier point? We could specify a // custom comparison func for DD_IterateThinkers... if(mo->type != type) return true; // Continue iteration. aabb[BOXLEFT] = mo->pos[VX] - mo->radius; aabb[BOXRIGHT] = mo->pos[VX] + mo->radius; aabb[BOXBOTTOM] = mo->pos[VY] - mo->radius; aabb[BOXTOP] = mo->pos[VY] + mo->radius; params.pos[VX] = mo->pos[VX]; params.pos[VY] = mo->pos[VY]; params.minDist = mo->radius / 2; VALIDCOUNT++; P_LinesBoxIterator(aabb, unstuckMobjInLinedef, ¶ms); if(mo->pos[VX] != params.pos[VX] || mo->pos[VY] != params.pos[VY]) { mo->angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY], params.pos[VX], params.pos[VY]); P_MobjUnsetPosition(mo); mo->pos[VX] = params.pos[VX]; mo->pos[VY] = params.pos[VY]; P_MobjSetPosition(mo); } return true; // Continue iteration. } /** * Only affects torches, which are often placed inside walls in the * original maps. The DOOM engine allowed these kinds of things but a * Z-buffer doesn't. */ void P_MoveThingsOutOfWalls(void) { static const mobjtype_t types[] = { #if __JHERETIC__ MT_MISC10, #elif __JHEXEN__ MT_ZWALLTORCH, MT_ZWALLTORCH_UNLIT, #endif NUMMOBJTYPES // terminate. }; uint i; for(i = 0; types[i] != NUMMOBJTYPES; ++i) { mobjtype_t type = types[i]; DD_IterateThinkers(P_MobjThinker, iterateLinedefsNearMobj, &type); } } #if __JHERETIC__ float P_PointLineDistance(linedef_t *line, float x, float y, float *offset) { float a[2], b[2], c[2], d[2], len; P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, a); P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, b); c[VX] = x; c[VY] = y; d[VX] = b[VX] - a[VX]; d[VY] = b[VY] - a[VY]; len = sqrt(d[VX] * d[VX] + d[VY] * d[VY]); // Accurate. if(offset) *offset = ((a[VY] - c[VY]) * (a[VY] - b[VY]) - (a[VX] - c[VX]) * (b[VX] - a[VX])) / len; return ((a[VY] - c[VY]) * (b[VX] - a[VX]) - (a[VX] - c[VX]) * (b[VY] - a[VY])) / len; } /** * Fails in some places, but works most of the time. */ void P_TurnGizmosAwayFromDoors(void) { #define MAXLIST 200 sector_t *sec; mobj_t *iter; uint i, l; int k, t; linedef_t *closestline = NULL, *li; xline_t *xli; float closestdist = 0, dist, off, linelen; //, minrad; mobj_t *tlist[MAXLIST]; for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); memset(tlist, 0, sizeof(tlist)); // First all the things to process. for(k = 0, iter = P_GetPtrp(sec, DMT_MOBJS); k < MAXLIST - 1 && iter; iter = iter->sNext) { if(iter->type == MT_KEYGIZMOBLUE || iter->type == MT_KEYGIZMOGREEN || iter->type == MT_KEYGIZMOYELLOW) tlist[k++] = iter; } // Turn to face away from the nearest door. for(t = 0; (iter = tlist[t]) != NULL; ++t) { closestline = NULL; for(l = 0; l < numlines; ++l) { float d1[2]; li = P_ToPtr(DMU_LINEDEF, l); if(P_GetPtrp(li, DMU_BACK_SECTOR)) continue; xli = P_ToXLine(li); // It must be a special line with a back sector. if((xli->special != 32 && xli->special != 33 && xli->special != 34 && xli->special != 26 && xli->special != 27 && xli->special != 28)) continue; P_GetFloatpv(li, DMU_DXY, d1); linelen = P_ApproxDistance(d1[0], d1[1]); dist = fabs(P_PointLineDistance(li, iter->pos[VX], iter->pos[VY], &off)); if(!closestline || dist < closestdist) { closestdist = dist; closestline = li; } } if(closestline) { vertex_t* v0, *v1; float v0p[2], v1p[2]; v0 = P_GetPtrp(closestline, DMU_VERTEX0); v1 = P_GetPtrp(closestline, DMU_VERTEX1); P_GetFloatpv(v0, DMU_XY, v0p); P_GetFloatpv(v1, DMU_XY, v1p); iter->angle = R_PointToAngle2(v0p[VX], v0p[VY], v1p[VX], v1p[VY]) - ANG90; } } } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/src/p_player.c0000644000175000017500000010171311357170242022607 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_player.c: Common playsim routines relating to players. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "dd_share.h" #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #include "dmu_lib.h" #include "d_netsv.h" #include "d_net.h" #include "hu_log.h" #include "p_map.h" #include "g_common.h" #include "p_actor.h" #include "p_start.h" #include "p_player.h" // MACROS ------------------------------------------------------------------ #define MESSAGETICS (4 * TICSPERSEC) #define CAMERA_FRICTION_THRESHOLD (.4f) // TYPES ------------------------------------------------------------------- typedef struct weaponslotinfo_s { uint num; weapontype_t* types; } weaponslotinfo_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static weaponslotinfo_t weaponSlots[NUM_WEAPON_SLOTS]; // CODE -------------------------------------------------------------------- static byte slotForWeaponType(weapontype_t type, uint* position) { byte i = 0, found = 0; do { weaponslotinfo_t* slot = &weaponSlots[i]; uint j = 0; while(!found && j < slot->num) { if(slot->types[j] == type) { found = i + 1; if(position) *position = j; } else j++; } } while(!found && ++i < NUM_WEAPON_SLOTS); return found; } static void unlinkWeaponInSlot(byte slotidx, weapontype_t type) { uint i; weaponslotinfo_t* slot = &weaponSlots[slotidx-1]; for(i = 0; i < slot->num; ++i) if(slot->types[i] == type) break; if(i == slot->num) return; // Not linked to this slot. memmove(&slot->types[i], &slot->types[i+1], sizeof(weapontype_t) * (slot->num - 1 - i)); slot->types = realloc(slot->types, sizeof(weapontype_t) * --slot->num); } static void linkWeaponInSlot(byte slotidx, weapontype_t type) { weaponslotinfo_t* slot = &weaponSlots[slotidx-1]; slot->types = realloc(slot->types, sizeof(weapontype_t) * ++slot->num); if(slot->num > 1) memmove(&slot->types[1], &slot->types[0], sizeof(weapontype_t) * (slot->num - 1)); slot->types[0] = type; } void P_InitWeaponSlots(void) { memset(weaponSlots, 0, sizeof(weaponSlots)); } void P_FreeWeaponSlots(void) { byte i; for(i = 0; i < NUM_WEAPON_SLOTS; ++i) { weaponslotinfo_t* slot = &weaponSlots[i]; if(slot->types) free(slot->types); slot->types = NULL; slot->num = 0; } } boolean P_SetWeaponSlot(weapontype_t type, byte slot) { byte currentSlot; if(slot > NUM_WEAPON_SLOTS) return false; currentSlot = slotForWeaponType(type, NULL); // First, remove the weapon (if found). if(currentSlot) unlinkWeaponInSlot(currentSlot, type); if(slot != 0) { // Add this weapon to the specified slot (head). linkWeaponInSlot(slot, type); } return true; } byte P_GetWeaponSlot(weapontype_t type) { if(type >= WT_FIRST && type < NUM_WEAPON_TYPES) return slotForWeaponType(type, NULL); return 0; } weapontype_t P_WeaponSlotCycle(weapontype_t type, boolean prev) { if(type >= WT_FIRST && type < NUM_WEAPON_TYPES) { byte slotidx; uint position; if((slotidx = slotForWeaponType(type, &position))) { weaponslotinfo_t* slot = &weaponSlots[slotidx-1]; if(slot->num > 1) { if(prev) { if(position == 0) position = slot->num - 1; else position--; } else { if(position == slot->num - 1) position = 0; else position++; } return slot->types[position]; } } } return type; } /** * Iterate the weapons of a given weapon slot. * * @param slot Weapon slot number. * @param reverse Iff @c = true, the traversal is done in reverse. * @param callback Ptr to the callback to make for each element. * If the callback returns @c 0, iteration ends. * @param context Passed as an argument to @a callback. * * @return Non-zero if no weapon is bound to the slot @a slot, * or callback @a callback signals an end to iteration. */ int P_IterateWeaponsInSlot(byte slot, boolean reverse, int (*callback) (weapontype_t, void* context), void* context) { int result = 1; if(slot <= NUM_WEAPON_SLOTS) { uint i = 0; const weaponslotinfo_t* sl = &weaponSlots[slot]; while(i < sl->num && (result = callback(sl->types[reverse ? sl->num - 1 - i : i], context)) != 0) i++; } return result; } /** * Initialize player class info. */ #if __JHEXEN__ void P_InitPlayerClassInfo(void) { PCLASS_INFO(PCLASS_FIGHTER)->niceName = GET_TXT(TXT_PLAYERCLASS1); PCLASS_INFO(PCLASS_CLERIC)->niceName = GET_TXT(TXT_PLAYERCLASS2); PCLASS_INFO(PCLASS_MAGE)->niceName = GET_TXT(TXT_PLAYERCLASS3); PCLASS_INFO(PCLASS_PIG)->niceName = GET_TXT(TXT_PLAYERCLASS4); } #endif /** * @param player The player to work with. * * @return Number of the given player. */ int P_GetPlayerNum(player_t *player) { int i; for(i = 0; i < MAXPLAYERS; ++i) { if(player == &players[i]) { return i; } } return 0; } /** * Return a bit field for the current player's cheats. * * @param The player to work with. * * @return Cheats active for the given player in a bitfield. */ int P_GetPlayerCheats(player_t *player) { if(!player) { return 0; } else { if(player->plr->flags & DDPF_CAMERA) return (player->cheats | (CF_GODMODE | cfg.cameraNoClip? CF_NOCLIP : 0)); else return player->cheats; } } /** * Subtract the appropriate amount of ammo from the player for firing * the current ready weapon. * * @param player The player doing the firing. */ void P_ShotAmmo(player_t *player) { ammotype_t i; int fireMode; weaponinfo_t* wInfo = &weaponInfo[player->readyWeapon][player->class]; #if __JHERETIC__ if(deathmatch) fireMode = 0; // In deathmatch always use mode zero. else fireMode = (player->powers[PT_WEAPONLEVEL2]? 1 : 0); #else fireMode = 0; #endif for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!wInfo->mode[fireMode].ammoType[i]) continue; // Weapon does not take this ammo. // Don't let it fall below zero. player->ammo[i].owned = MAX_OF(0, player->ammo[i].owned - wInfo->mode[fireMode].perShot[i]); } } /** * Decides if an automatic weapon change should occur and does it. * * Called when: * A) the player has ran out of ammo for the readied weapon. * B) the player has been given a NEW weapon. * C) the player is ABOUT TO be given some ammo. * * If "weapon" is non-zero then we'll always try to change weapon. * If "ammo" is non-zero then we'll consider the ammo level of weapons that * use this ammo type. * If both non-zero - no more ammo for the current weapon. * * \todo Should be called AFTER ammo is given but we need to * remember the old count before the change. * * @param player The player given the weapon. * @param weapon The weapon given to the player (if any). * @param ammo The ammo given to the player (if any). * @param force @c true = Force a weapon change. * * @return The weapon we changed to OR WT_NOCHANGE. */ weapontype_t P_MaybeChangeWeapon(player_t *player, weapontype_t weapon, ammotype_t ammo, boolean force) { int i, lvl, pclass; ammotype_t ammotype; weapontype_t candidate; weapontype_t returnval = WT_NOCHANGE; weaponinfo_t *winf; boolean found; // Assume weapon power level zero. lvl = 0; pclass = player->class; #if __JHERETIC__ if(player->powers[PT_WEAPONLEVEL2]) lvl = 1; #endif if(weapon == WT_NOCHANGE && ammo == AT_NOAMMO) // Out of ammo. { boolean good; // Note we have no auto-logical choice for a forced change. // Preferences are set by the user. found = false; for(i = 0; i < NUM_WEAPON_TYPES && !found; ++i) { candidate = cfg.weaponOrder[i]; winf = &weaponInfo[candidate][pclass]; // Is candidate available in this game mode? if(!(winf->mode[lvl].gameModeBits & gameModeBits)) continue; // Does the player actually own this candidate? if(!player->weapons[candidate].owned) continue; // Is there sufficent ammo for the candidate weapon? // Check amount for each used ammo type. good = true; for(ammotype = 0; ammotype < NUM_AMMO_TYPES && good; ++ammotype) { if(!winf->mode[lvl].ammoType[ammotype]) continue; // Weapon does not take this type of ammo. #if __JHERETIC__ // Heretic always uses lvl 0 ammo requirements in deathmatch if(deathmatch && player->ammo[ammotype].owned < winf->mode[0].perShot[ammotype]) { // Not enough ammo of this type. Candidate is NOT good. good = false; } else #endif if(player->ammo[ammotype].owned < winf->mode[lvl].perShot[ammotype]) { // Not enough ammo of this type. Candidate is NOT good. good = false; } } if(good) { // Candidate weapon meets the criteria. returnval = candidate; found = true; } } } else if(weapon != WT_NOCHANGE) // Player was given a NEW weapon. { // A forced weapon change? if(force) { returnval = weapon; } // Is the player currently firing? else if(!((player->brain.attack) && cfg.noWeaponAutoSwitchIfFiring)) { // Should we change weapon automatically? if(cfg.weaponAutoSwitch == 2) { // Always change weapon mode returnval = weapon; } else if(cfg.weaponAutoSwitch == 1) { // Change if better mode // Iterate the weapon order array and see if a weapon change // should be made. Preferences are user selectable. for(i = 0; i < NUM_WEAPON_TYPES; ++i) { candidate = cfg.weaponOrder[i]; winf = &weaponInfo[candidate][pclass]; // Is candidate available in this game mode? if(!(winf->mode[lvl].gameModeBits & gameModeBits)) continue; if(weapon == candidate) { // weapon has a higher priority than the readyweapon. returnval = weapon; } else if(player->readyWeapon == candidate) { // readyweapon has a higher priority so don't change. break; } } } } } else if(ammo != AT_NOAMMO) // Player is about to be given some ammo. { if((!(player->ammo[ammo].owned > 0) && cfg.ammoAutoSwitch != 0) || force) { // We were down to zero, so select a new weapon. // Iterate the weapon order array and see if the player owns a // weapon that can be used now they have this ammo. // Preferences are user selectable. for(i = 0; i < NUM_WEAPON_TYPES; ++i) { candidate = cfg.weaponOrder[i]; winf = &weaponInfo[candidate][pclass]; // Is candidate available in this game mode? if(!(winf->mode[lvl].gameModeBits & gameModeBits)) continue; // Does the player actually own this candidate? if(!player->weapons[candidate].owned) continue; // Does the weapon use this type of ammo? if(!(winf->mode[lvl].ammoType[ammo])) continue; /** * \fixme Have we got enough of ALL used ammo types? * Problem, since the ammo has not been given yet (could * be an object that gives several ammo types eg backpack) * we can't test for this with what we know! * * This routine should be called AFTER the new ammo has * been given. Somewhat complex logic to decipher first... */ if(cfg.ammoAutoSwitch == 2) { // Always change weapon mode. returnval = candidate; break; } else if(cfg.ammoAutoSwitch == 1 && player->readyWeapon == candidate) { // readyweapon has a higher priority so don't change. break; } } } } // Don't change to the exisitng weapon. if(returnval == player->readyWeapon) returnval = WT_NOCHANGE; // Choosen a weapon to change to? if(returnval != WT_NOCHANGE) { player->pendingWeapon = returnval; player->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; } return returnval; } /** * Checks if the player has enough ammo to fire their readied weapon. * If not, a weapon change is instigated. * * @return @c true, if there is enough ammo to fire. */ boolean P_CheckAmmo(player_t* plr) { int fireMode; boolean good; ammotype_t i; weaponinfo_t* wInfo; wInfo = &weaponInfo[plr->readyWeapon][plr->class]; #if __JDOOM__ || __JDOOM64__ || __JHEXEN__ fireMode = 0; #endif #if __JHERETIC__ // If deathmatch always use firemode two ammo requirements. if(plr->powers[PT_WEAPONLEVEL2] && !deathmatch) fireMode = 1; else fireMode = 0; #endif #if __JHEXEN__ //// \kludge Work around the multiple firing modes problems. //// We need to split the weapon firing routines and implement them as //// new fire modes. if(plr->class == PCLASS_FIGHTER && plr->readyWeapon != WT_FOURTH) return true; // < KLUDGE #endif // Check we have enough of ALL ammo types used by this weapon. good = true; for(i = 0; i < NUM_AMMO_TYPES && good; ++i) { if(!wInfo->mode[fireMode].ammoType[i]) continue; // Weapon does not take this type of ammo. // Minimal amount for one shot varies. if(plr->ammo[i].owned < wInfo->mode[fireMode].perShot[i]) { // Insufficent ammo to fire this weapon. good = false; } } if(good) return true; // Out of ammo, pick a weapon to change to. P_MaybeChangeWeapon(plr, WT_NOCHANGE, AT_NOAMMO, false); // Now set appropriate weapon overlay. if(plr->pendingWeapon != WT_NOCHANGE) P_SetPsprite(plr, ps_weapon, wInfo->mode[fireMode].states[WSN_DOWN]); return false; } /** * Return the next weapon for the given player. Can return the existing * weapon if no other valid choices. Preferences are NOT user selectable. * * @param player The player to work with. * @param prev Search direction @c true = previous, @c false = next. */ weapontype_t P_PlayerFindWeapon(player_t* player, boolean prev) { weapontype_t* list, w = 0; int lvl, i; #if __JDOOM__ static weapontype_t wp_list[] = { WT_FIRST, WT_SECOND, WT_THIRD, WT_NINETH, WT_FOURTH, WT_FIFTH, WT_SIXTH, WT_SEVENTH, WT_EIGHTH }; #elif __JDOOM64__ static weapontype_t wp_list[] = { WT_FIRST, WT_SECOND, WT_THIRD, WT_NINETH, WT_FOURTH, WT_FIFTH, WT_SIXTH, WT_SEVENTH, WT_EIGHTH, WT_TENTH }; #elif __JHERETIC__ static weapontype_t wp_list[] = { WT_FIRST, WT_SECOND, WT_THIRD, WT_FOURTH, WT_FIFTH, WT_SIXTH, WT_SEVENTH, WT_EIGHTH }; #elif __JHEXEN__ || __JSTRIFE__ static weapontype_t wp_list[] = { WT_FIRST, WT_SECOND, WT_THIRD, WT_FOURTH }; #endif #if __JHERETIC__ lvl = (player->powers[PT_WEAPONLEVEL2]? 1 : 0); #else lvl = 0; #endif // Are we using weapon order preferences for next/previous? if(cfg.weaponNextMode) { list = (weapontype_t*) cfg.weaponOrder; prev = !prev; // Invert order. } else list = wp_list; // Find the current position in the weapon list. for(i = 0; i < NUM_WEAPON_TYPES; ++i) { w = list[i]; if(w == player->readyWeapon) break; } // Locate the next or previous weapon owned by the player. for(;;) { // Move the iterator. if(prev) i--; else i++; if(i < 0) i = NUM_WEAPON_TYPES - 1; else if(i > NUM_WEAPON_TYPES - 1) i = 0; w = list[i]; // Have we circled around? if(w == player->readyWeapon) break; // Available in this game mode? And a valid weapon? if((weaponInfo[w][player->class].mode[lvl]. gameModeBits & gameModeBits) && player->weapons[w].owned) break; } return w; } #if __JHEXEN__ /** * Changes the class of the given player. Will not work if the player * is currently morphed. */ void P_PlayerChangeClass(player_t* player, playerclass_t newClass) { int i; // Don't change if morphed. if(player->morphTics) return; if(!PCLASS_INFO(newClass)->userSelectable) return; player->class = newClass; cfg.playerClass[player - players] = newClass; // Take away armor. for(i = 0; i < NUMARMOR; ++i) player->armorPoints[i] = 0; player->update |= PSF_ARMOR_POINTS; P_PostMorphWeapon(player, WT_FIRST); if(player->plr->mo) { // Respawn the player and destroy the old mobj. mobj_t* oldMo = player->plr->mo; P_SpawnPlayer(player - players, newClass, oldMo->pos[VX], oldMo->pos[VY], oldMo->pos[VZ], oldMo->angle, 0, P_MobjIsCamera(oldMo), true); P_MobjRemove(oldMo, true); } } #endif /** * Send a message to the given player and maybe echos it to the console. * * @param player The player to send the message to. * @param msg The message to be sent. * @param noHide @c true = show message even if messages have been * disabled by the player. */ void P_SetMessage(player_t* pl, char *msg, boolean noHide) { byte flags = (noHide? LMF_NOHIDE : 0); Hu_LogPost(pl - players, flags, msg); if(pl == &players[CONSOLEPLAYER] && cfg.echoMsg) Con_FPrintf(CBLF_CYAN, "%s\n", msg); // Servers are responsible for sending these messages to the clients. NetSv_SendMessage(pl - players, msg); } #if __JHEXEN__ /** * Send a yellow message to the given player and maybe echos it to the console. * * @param player The player to send the message to. * @param msg The message to be sent. * @param noHide @c true = show message even if messages have been * disabled by the player. */ void P_SetYellowMessage(player_t* pl, char *msg, boolean noHide) { byte flags = LMF_YELLOW | (noHide? LMF_NOHIDE : 0); Hu_LogPost(pl - players, flags, msg); if(pl == &players[CONSOLEPLAYER] && cfg.echoMsg) Con_FPrintf(CBLF_CYAN, "%s\n", msg); // Servers are responsible for sending these messages to the clients. NetSv_SendMessage(pl - players, msg); } #endif void P_Thrust3D(player_t *player, angle_t angle, float lookdir, int forwardmovex, int sidemovex) { angle_t pitch = LOOKDIR2DEG(lookdir) / 360 * ANGLE_MAX; angle_t sideangle = angle - ANG90; mobj_t *mo = player->plr->mo; float zmul; float mom[3]; float forwardmove = FIX2FLT(forwardmovex); float sidemove = FIX2FLT(sidemovex); angle >>= ANGLETOFINESHIFT; pitch >>= ANGLETOFINESHIFT; mom[MX] = forwardmove * FIX2FLT(finecosine[angle]); mom[MY] = forwardmove * FIX2FLT(finesine[angle]); mom[MZ] = forwardmove * FIX2FLT(finesine[pitch]); zmul = FIX2FLT(finecosine[pitch]); mom[MX] *= zmul; mom[MY] *= zmul; sideangle >>= ANGLETOFINESHIFT; mom[MX] += sidemove * FIX2FLT(finecosine[sideangle]); mom[MY] += sidemove * FIX2FLT(finesine[sideangle]); mo->mom[MX] += mom[MX]; mo->mom[MY] += mom[MY]; mo->mom[MZ] += mom[MZ]; } int P_CameraXYMovement(mobj_t *mo) { if(!P_MobjIsCamera(mo)) return false; #if __JDOOM__ || __JDOOM64__ if(mo->flags & MF_NOCLIP || // This is a very rough check! Sometimes you get stuck in things. P_CheckPosition3f(mo, mo->pos[VX] + mo->mom[MX], mo->pos[VY] + mo->mom[MY], mo->pos[VZ])) { #endif P_MobjUnsetPosition(mo); mo->pos[VX] += mo->mom[MX]; mo->pos[VY] += mo->mom[MY]; P_MobjSetPosition(mo); P_CheckPosition2f(mo, mo->pos[VX], mo->pos[VY]); mo->floorZ = tmFloorZ; mo->ceilingZ = tmCeilingZ; #if __JDOOM__ || __JDOOM64__ } #endif // Friction. if(!INRANGE_OF(mo->player->brain.forwardMove, 0, CAMERA_FRICTION_THRESHOLD) || !INRANGE_OF(mo->player->brain.sideMove, 0, CAMERA_FRICTION_THRESHOLD) || !INRANGE_OF(mo->player->brain.upMove, 0, CAMERA_FRICTION_THRESHOLD)) { // While moving; normal friction applies. mo->mom[MX] *= FRICTION_NORMAL; mo->mom[MY] *= FRICTION_NORMAL; } else { // Else lose momentum, quickly!. mo->mom[MX] *= FRICTION_HIGH; mo->mom[MY] *= FRICTION_HIGH; } return true; } int P_CameraZMovement(mobj_t *mo) { if(!P_MobjIsCamera(mo)) return false; mo->pos[VZ] += mo->mom[MZ]; // Friction. if(!INRANGE_OF(mo->player->brain.forwardMove, 0, CAMERA_FRICTION_THRESHOLD) || !INRANGE_OF(mo->player->brain.sideMove, 0, CAMERA_FRICTION_THRESHOLD) || !INRANGE_OF(mo->player->brain.upMove, 0, CAMERA_FRICTION_THRESHOLD)) { // While moving; normal friction applies. mo->mom[MZ] *= FRICTION_NORMAL; } else { // Else, lose momentum quickly!. mo->mom[MZ] *= FRICTION_HIGH; } return true; } /** * Set appropriate parameters for a camera. */ void P_PlayerThinkCamera(player_t *player) { mobj_t *mo; // If this player is not a camera, get out of here. if(!(player->plr->flags & DDPF_CAMERA)) { if(player->playerState == PST_LIVE) player->plr->mo->flags |= (MF_SOLID | MF_SHOOTABLE | MF_PICKUP); return; } mo = player->plr->mo; mo->flags &= ~(MF_SOLID | MF_SHOOTABLE | MF_PICKUP); // How about viewlock? if(player->viewLock) { angle_t angle; int full; float dist; mobj_t *target = players->viewLock; if(!target->player || !target->player->plr->inGame) { player->viewLock = NULL; return; } full = player->lockFull; angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY], target->pos[VX], target->pos[VY]); //player->plr->flags |= DDPF_FIXANGLES; /* $unifiedangles */ mo->angle = angle; //player->plr->clAngle = angle; player->plr->flags |= DDPF_INTERYAW; if(full) { dist = P_ApproxDistance(mo->pos[VX] - target->pos[VX], mo->pos[VY] - target->pos[VY]); angle = R_PointToAngle2(0, 0, target->pos[VZ] + (target->height / 2) - mo->pos[VZ], dist); //player->plr->clLookDir = player->plr->lookDir = -(angle / (float) ANGLE_MAX * 360.0f - 90); if(player->plr->lookDir > 180) player->plr->lookDir -= 360; player->plr->lookDir *= 110.0f / 85.0f; if(player->plr->lookDir > 110) player->plr->lookDir = 110; if(player->plr->lookDir < -110) player->plr->lookDir = -110; player->plr->flags |= DDPF_INTERPITCH; } } } DEFCC(CCmdSetCamera) { int p; player_t *player; p = atoi(argv[1]); if(p < 0 || p >= MAXPLAYERS) { Con_Printf("Invalid console number %i.\n", p); return false; } player = &players[p]; player->plr->flags ^= DDPF_CAMERA; if(player->plr->inGame) { if(player->plr->flags & DDPF_CAMERA) { // Is now a camera. if(player->plr->mo) player->plr->mo->pos[VZ] += player->viewHeight; } else { // Is now a "real" player. if(player->plr->mo) player->plr->mo->pos[VZ] -= player->viewHeight; } } return true; } /** * Give the player an armor bonus (points delta). * * @param plr This. * @param points Points delta. * * @return Number of points applied. */ #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ int P_PlayerGiveArmorBonus(player_t* plr, int points) #else // __JHEXEN__ int P_PlayerGiveArmorBonus(player_t* plr, armortype_t type, int points) #endif { int delta, oldPoints; int* current; if(!points) return 0; #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ current = &plr->armorPoints; #else // __JHEXEN__ current = &plr->armorPoints[type]; #endif oldPoints = *current; if(points > 0) { delta = points; /// \fixme No upper limit? } else { if(*current + points < 0) delta = -(*current); else delta = points; } *current += delta; if(*current != oldPoints) plr->update |= PSF_ARMOR_POINTS; return delta; } #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ void P_PlayerSetArmorType(player_t* plr, int type) { int oldType = plr->armorType; plr->armorType = type; if(plr->armorType != oldType) plr->update |= PSF_ARMOR_TYPE; } #endif DEFCC(CCmdSetViewMode) { int pl = CONSOLEPLAYER; if(argc > 2) return false; if(argc == 2) pl = atoi(argv[1]); if(pl < 0 || pl >= MAXPLAYERS) return false; if(!(players[pl].plr->flags & DDPF_CHASECAM)) players[pl].plr->flags |= DDPF_CHASECAM; else players[pl].plr->flags &= ~DDPF_CHASECAM; return true; } DEFCC(CCmdSetViewLock) { int pl = CONSOLEPLAYER, lock; if(!stricmp(argv[0], "lockmode")) { lock = atoi(argv[1]); if(lock) players[pl].lockFull = true; else players[pl].lockFull = false; return true; } if(argc < 2) return false; if(argc >= 3) pl = atoi(argv[2]); // Console number. lock = atoi(argv[1]); if(!(lock == pl || lock < 0 || lock >= MAXPLAYERS)) { if(players[lock].plr->inGame && players[lock].plr->mo) { players[pl].viewLock = players[lock].plr->mo; return true; } } players[pl].viewLock = NULL; return false; } DEFCC(CCmdMakeLocal) { int p; char buf[20]; player_t *plr; if(G_GetGameState() != GS_MAP) { Con_Printf("You must be in a game to create a local player.\n"); return false; } p = atoi(argv[1]); if(p < 0 || p >= MAXPLAYERS) { Con_Printf("Invalid console number %i.\n", p); return false; } plr = &players[p]; if(plr->plr->inGame) { Con_Printf("Player %i is already in the game.\n", p); return false; } plr->playerState = PST_REBORN; plr->plr->inGame = true; sprintf(buf, "conlocp %i", p); DD_Execute(false, buf); P_DealPlayerStarts(0); return true; } /** * Print the console player's coordinates. */ DEFCC(CCmdPrintPlayerCoords) { mobj_t *mo = players[CONSOLEPLAYER].plr->mo; if(!mo || G_GetGameState() != GS_MAP) return false; Con_Printf("Console %i: X=%g Y=%g Z=%g\n", CONSOLEPLAYER, mo->pos[VX], mo->pos[VY], mo->pos[VZ]); return true; } DEFCC(CCmdCycleSpy) { //// \fixme The engine should do this. Con_Printf("Spying not allowed.\n"); #if 0 if(G_GetGameState() == GS_MAP && !deathmatch) { // Cycle the display player. do { Set(DD_DISPLAYPLAYER, DISPLAYPLAYER + 1); if(DISPLAYPLAYER == MAXPLAYERS) { Set(DD_DISPLAYPLAYER, 0); } } while(!players[DISPLAYPLAYER].plr->inGame && DISPLAYPLAYER != CONSOLEPLAYER); } #endif return true; } DEFCC(CCmdSpawnMobj) { mobjtype_t type; float pos[3]; mobj_t* mo; angle_t angle; int spawnFlags = 0; if(argc != 5 && argc != 6) { Con_Printf("Usage: %s (type) (x) (y) (z) (angle)\n", argv[0]); Con_Printf("Type must be a defined Thing ID or Name.\n"); Con_Printf("Z is an offset from the floor, 'floor', 'ceil' or 'random'.\n"); Con_Printf("Angle (0..360) is optional.\n"); return true; } if(IS_CLIENT) { Con_Printf("%s can't be used by clients.\n", argv[0]); return false; } // First try to find the thing by ID. if((type = Def_Get(DD_DEF_MOBJ, argv[1], 0)) < 0) { // Try to find it by name instead. if((type = Def_Get(DD_DEF_MOBJ_BY_NAME, argv[1], 0)) < 0) { Con_Printf("Undefined thing type %s.\n", argv[1]); return false; } } // The coordinates. pos[VX] = strtod(argv[2], 0); pos[VY] = strtod(argv[3], 0); pos[VZ] = 0; if(!stricmp(argv[4], "ceil")) spawnFlags |= MSF_Z_CEIL; else if(!stricmp(argv[4], "random")) spawnFlags |= MSF_Z_RANDOM; else { spawnFlags |= MSF_Z_FLOOR; if(stricmp(argv[4], "floor")) pos[VZ] = strtod(argv[4], 0); } if(argc == 6) angle = ((int) (strtod(argv[5], 0) / 360 * FRACUNIT)) << 16; else angle = 0; if((mo = P_SpawnMobj3fv(type, pos, angle, spawnFlags))) { #if __JDOOM64__ // jd64 > kaiser - another cheesy hack!!! if(mo->type == MT_DART) { S_StartSound(SFX_SKESWG, mo); // We got darts! spawn skeswg sound! } else { S_StartSound(SFX_ITMBK, mo); // If not dart, then spawn itmbk sound mo->translucency = 255; mo->spawnFadeTics = 0; mo->intFlags |= MIF_FADE; } // << d64tc #endif } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/0000755000175000017500000000000011523516204021456 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_mapsetup.h0000644000175000017500000000371111357170242024011 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.c: Common map setup routines. */ #ifndef __COMMON_PLAYSETUP_H__ #define __COMMON_PLAYSETUP_H__ #define numvertexes (*(uint*) DD_GetVariable(DD_VERTEX_COUNT)) #define numsegs (*(uint*) DD_GetVariable(DD_SEG_COUNT)) #define numsectors (*(uint*) DD_GetVariable(DD_SECTOR_COUNT)) #define numsubsectors (*(uint*) DD_GetVariable(DD_SUBSECTOR_COUNT)) #define numnodes (*(uint*) DD_GetVariable(DD_NODE_COUNT)) #define numlines (*(uint*) DD_GetVariable(DD_LINE_COUNT)) #define numsides (*(uint*) DD_GetVariable(DD_SIDE_COUNT)) #define nummaterials (*(uint*) DD_GetVariable(DD_MATERIAL_COUNT)) #if __JHEXEN__ #define numpolyobjs (*(uint*) DD_GetVariable(DD_POLYOBJ_COUNT)) #endif // If true we are in the process of setting up a map. extern boolean mapSetup; void P_SetupForMapData(int type, uint num); void P_SetupMap(uint episode, uint map, int playermask, skillmode_t skill); const char* P_GetMapNiceName(void); const char* P_GetMapAuthor(boolean surpressIWADAuthors); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/dmu_lib.h0000644000175000017500000001401511357170242023246 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * DMU_lib.h: Helper routines for accessing the DMU API */ #ifndef __DMU_LIB_H__ #define __DMU_LIB_H__ #include "doomsday.h" // DMU property aliases. For short-hand purposes: #define DMU_TOP_MATERIAL (DMU_TOP_OF_SIDEDEF | DMU_MATERIAL) #define DMU_TOP_MATERIAL_OFFSET_X (DMU_TOP_OF_SIDEDEF | DMU_OFFSET_X) #define DMU_TOP_MATERIAL_OFFSET_Y (DMU_TOP_OF_SIDEDEF | DMU_OFFSET_Y) #define DMU_TOP_MATERIAL_OFFSET_XY (DMU_TOP_OF_SIDEDEF | DMU_OFFSET_XY) #define DMU_TOP_FLAGS (DMU_TOP_OF_SIDEDEF | DMU_FLAGS) #define DMU_TOP_COLOR (DMU_TOP_OF_SIDEDEF | DMU_COLOR) #define DMU_TOP_COLOR_RED (DMU_TOP_OF_SIDEDEF | DMU_COLOR_RED) #define DMU_TOP_COLOR_GREEN (DMU_TOP_OF_SIDEDEF | DMU_COLOR_GREEN) #define DMU_TOP_COLOR_BLUE (DMU_TOP_OF_SIDEDEF | DMU_COLOR_BLUE) #define DMU_MIDDLE_MATERIAL (DMU_MIDDLE_OF_SIDEDEF | DMU_MATERIAL) #define DMU_MIDDLE_MATERIAL_OFFSET_X (DMU_MIDDLE_OF_SIDEDEF | DMU_OFFSET_X) #define DMU_MIDDLE_MATERIAL_OFFSET_Y (DMU_MIDDLE_OF_SIDEDEF | DMU_OFFSET_Y) #define DMU_MIDDLE_MATERIAL_OFFSET_XY (DMU_MIDDLE_OF_SIDEDEF | DMU_OFFSET_XY) #define DMU_MIDDLE_FLAGS (DMU_MIDDLE_OF_SIDEDEF | DMU_FLAGS) #define DMU_MIDDLE_COLOR (DMU_MIDDLE_OF_SIDEDEF | DMU_COLOR) #define DMU_MIDDLE_COLOR_RED (DMU_MIDDLE_OF_SIDEDEF | DMU_COLOR_RED) #define DMU_MIDDLE_COLOR_GREEN (DMU_MIDDLE_OF_SIDEDEF | DMU_COLOR_GREEN) #define DMU_MIDDLE_COLOR_BLUE (DMU_MIDDLE_OF_SIDEDEF | DMU_COLOR_BLUE) #define DMU_MIDDLE_ALPHA (DMU_MIDDLE_OF_SIDEDEF | DMU_ALPHA) #define DMU_MIDDLE_BLENDMODE (DMU_MIDDLE_OF_SIDEDEF | DMU_BLENDMODE) #define DMU_BOTTOM_MATERIAL (DMU_BOTTOM_OF_SIDEDEF | DMU_MATERIAL) #define DMU_BOTTOM_MATERIAL_OFFSET_X (DMU_BOTTOM_OF_SIDEDEF | DMU_OFFSET_X) #define DMU_BOTTOM_MATERIAL_OFFSET_Y (DMU_BOTTOM_OF_SIDEDEF | DMU_OFFSET_Y) #define DMU_BOTTOM_MATERIAL_OFFSET_XY (DMU_BOTTOM_OF_SIDEDEF | DMU_OFFSET_XY) #define DMU_BOTTOM_FLAGS (DMU_BOTTOM_OF_SIDEDEF | DMU_FLAGS) #define DMU_BOTTOM_COLOR (DMU_BOTTOM_OF_SIDEDEF | DMU_COLOR) #define DMU_BOTTOM_COLOR_RED (DMU_BOTTOM_OF_SIDEDEF | DMU_COLOR_RED) #define DMU_BOTTOM_COLOR_GREEN (DMU_BOTTOM_OF_SIDEDEF | DMU_COLOR_GREEN) #define DMU_BOTTOM_COLOR_BLUE (DMU_BOTTOM_OF_SIDEDEF | DMU_COLOR_BLUE) #define DMU_FLOOR_HEIGHT (DMU_FLOOR_OF_SECTOR | DMU_HEIGHT) #define DMU_FLOOR_TARGET_HEIGHT (DMU_FLOOR_OF_SECTOR | DMU_TARGET_HEIGHT) #define DMU_FLOOR_SPEED (DMU_FLOOR_OF_SECTOR | DMU_SPEED) #define DMU_FLOOR_MATERIAL (DMU_FLOOR_OF_SECTOR | DMU_MATERIAL) #define DMU_FLOOR_SOUND_ORIGIN (DMU_FLOOR_OF_SECTOR | DMU_SOUND_ORIGIN) #define DMU_FLOOR_FLAGS (DMU_FLOOR_OF_SECTOR | DMU_FLAGS) #define DMU_FLOOR_COLOR (DMU_FLOOR_OF_SECTOR | DMU_COLOR) #define DMU_FLOOR_COLOR_RED (DMU_FLOOR_OF_SECTOR | DMU_COLOR_RED) #define DMU_FLOOR_COLOR_GREEN (DMU_FLOOR_OF_SECTOR | DMU_COLOR_GREEN) #define DMU_FLOOR_COLOR_BLUE (DMU_FLOOR_OF_SECTOR | DMU_COLOR_BLUE) #define DMU_FLOOR_MATERIAL_OFFSET_X (DMU_FLOOR_OF_SECTOR | DMU_OFFSET_X) #define DMU_FLOOR_MATERIAL_OFFSET_Y (DMU_FLOOR_OF_SECTOR | DMU_OFFSET_Y) #define DMU_FLOOR_MATERIAL_OFFSET_XY (DMU_FLOOR_OF_SECTOR | DMU_OFFSET_XY) #define DMU_FLOOR_NORMAL_X (DMU_FLOOR_OF_SECTOR | DMU_NORMAL_X) #define DMU_FLOOR_NORMAL_Y (DMU_FLOOR_OF_SECTOR | DMU_NORMAL_Y) #define DMU_FLOOR_NORMAL_Z (DMU_FLOOR_OF_SECTOR | DMU_NORMAL_Z) #define DMU_FLOOR_NORMAL_XYZ (DMU_FLOOR_OF_SECTOR | DMU_NORMAL_XYZ) #define DMU_CEILING_HEIGHT (DMU_CEILING_OF_SECTOR | DMU_HEIGHT) #define DMU_CEILING_TARGET_HEIGHT (DMU_CEILING_OF_SECTOR | DMU_TARGET_HEIGHT) #define DMU_CEILING_SPEED (DMU_CEILING_OF_SECTOR | DMU_SPEED) #define DMU_CEILING_MATERIAL (DMU_CEILING_OF_SECTOR | DMU_MATERIAL) #define DMU_CEILING_SOUND_ORIGIN (DMU_CEILING_OF_SECTOR | DMU_SOUND_ORIGIN) #define DMU_CEILING_FLAGS (DMU_CEILING_OF_SECTOR | DMU_FLAGS) #define DMU_CEILING_COLOR (DMU_CEILING_OF_SECTOR | DMU_COLOR) #define DMU_CEILING_COLOR_RED (DMU_CEILING_OF_SECTOR | DMU_COLOR_RED) #define DMU_CEILING_COLOR_GREEN (DMU_CEILING_OF_SECTOR | DMU_COLOR_GREEN) #define DMU_CEILING_COLOR_BLUE (DMU_CEILING_OF_SECTOR | DMU_COLOR_BLUE) #define DMU_CEILING_MATERIAL_OFFSET_X (DMU_CEILING_OF_SECTOR | DMU_OFFSET_X) #define DMU_CEILING_MATERIAL_OFFSET_Y (DMU_CEILING_OF_SECTOR | DMU_OFFSET_Y) #define DMU_CEILING_MATERIAL_OFFSET_XY (DMU_CEILING_OF_SECTOR | DMU_OFFSET_XY) #define DMU_CEILING_NORMAL_X (DMU_CEILING_OF_SECTOR | DMU_NORMAL_X) #define DMU_CEILING_NORMAL_Y (DMU_CEILING_OF_SECTOR | DMU_NORMAL_Y) #define DMU_CEILING_NORMAL_Z (DMU_CEILING_OF_SECTOR | DMU_NORMAL_Z) #define DMU_CEILING_NORMAL_XYZ (DMU_CEILING_OF_SECTOR | DMU_NORMAL_XYZ) linedef_t* P_AllocDummyLine(void); void P_FreeDummyLine(linedef_t* line); void P_CopyLine(linedef_t* dest, linedef_t* src); void P_CopySector(sector_t* dest, sector_t* src); float P_SectorLight(sector_t* sector); void P_SectorSetLight(sector_t* sector, float level); void P_SectorModifyLight(sector_t* sector, float value); void P_SectorModifyLightx(sector_t* sector, fixed_t value); void* P_SectorSoundOrigin(sector_t* sector); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/hu_pspr.h0000644000175000017500000000217511357170242023317 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_pspr.h: */ #ifndef __COMMON_PSPRITE_H__ #define __COMMON_PSPRITE_H__ void HU_UpdatePsprites(void); float HU_PSpriteYOffset(player_t* pl); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_terraintype.h0000644000175000017500000000363011357170242024521 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_terraintype.h: */ #ifndef __COMMON_TERRAINTYPE_H__ #define __COMMON_TERRAINTYPE_H__ #define TTF_NONSOLID 0x1 /* Various implications: 1) Bouncing mobjs destroyed on contact. 2) Able mobjs can dive/surface. */ #define TTF_FLOORCLIP 0x2 // Mobjs contacting this terrain will sink into it. #define TTF_FRICTION_LOW 0x4 #define TTF_FRICTION_HIGH 0x8 // Mobjs contacting this cause various fx to be spawned: #if __JHERETIC__ || __JHEXEN__ #define TTF_SPAWN_SPLASHES 0x10 #define TTF_SPAWN_SMOKE 0x20 #define TTF_SPAWN_SLUDGE 0x40 #endif #if __JHEXEN__ #define TTF_DAMAGING 0x80 #endif typedef struct terraindef_s { char* name; // Symbolic name for this terrain. short flags; // TTF_* terrain type flags. } terraintype_t; void P_InitTerrainTypes(void); const terraintype_t* P_TerrainTypeForMaterial(material_t* mat); const terraintype_t* P_GetPlaneMaterialType(sector_t* sec, int plane); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/xgclass.h0000644000175000017500000000643511357170242023306 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * xgclass.h: */ #ifndef __XG_LINE_CLASSES_H__ #define __XG_LINE_CLASSES_H__ // When the common playsim is in place - Doomsday will call the // the XG Class Funcs which are owned by the game. // iparm string mapping identifiers #define MAP_SND 0x01000000 #define MAP_MUS 0x02000000 #define MAP_MATERIAL 0x04000000 #define MAP_MASK 0x00ffffff enum { XGPF_INT, XGPF_FLOAT, XGPF_STRING }; typedef struct { int flags; char name[128]; char flagPrefix[20]; int map; } xgclassparm_t; typedef enum { TRAV_NONE, // The class func is executed once only, WITHOUT any traversal TRAV_LINES, TRAV_PLANES, TRAV_SECTORS /* Actually traverses planes but pretends to the user that its traversing sectors via XG_Dev messages (easier to comprehend) */ } xgtravtype; #ifndef C_DECL # if defined(WIN32) # define C_DECL __cdecl # elif defined(UNIX) # define C_DECL # endif #endif typedef struct xgclass_s{ // Do function (called during ref iteration) int (C_DECL *doFunc)(); // Init function (called once, before ref iteration) void (*initFunc)(struct linedef_s *line); // what the class wants to traverse xgtravtype traverse; // the iparm numbers to use for ref traversal int travRef; int travData; int evTypeFlags; /* if > 0 the class only supports certain event types (which are flags on this var) */ const char* className; // txt string id xgclassparm_t iparm[20]; // iparms } xgclass_t; // Line type classes. Add new classes to the end! enum { LTC_NONE, // No action. LTC_CHAIN_SEQUENCE, LTC_PLANE_MOVE, LTC_BUILD_STAIRS, LTC_DAMAGE, LTC_POWER, LTC_LINE_TYPE, LTC_SECTOR_TYPE, LTC_SECTOR_LIGHT, LTC_ACTIVATE, LTC_KEY, LTC_MUSIC, // Change the music to play. LTC_LINE_COUNT, // Line activation count delta. LTC_LEAVE_MAP, LTC_DISABLE_IF_ACTIVE, LTC_ENABLE_IF_ACTIVE, LTC_EXPLODE, // Explodes the activator. LTC_PLANE_MATERIAL, LTC_WALL_MATERIAL, LTC_COMMAND, LTC_SOUND, // Play a sector sound. LTC_MIMIC_SECTOR, LTC_TELEPORT, LTC_LINE_TELEPORT, NUMXGCLASSES }; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_xgline.h0000644000175000017500000003207511357170242023446 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_xgline.h: */ // Extended Generalized Line Types #ifndef __XG_LINETYPE_H__ #define __XG_LINETYPE_H__ #include "xgclass.h" // Line events. #define XLE_CHAIN 0x001 #define XLE_CROSS 0x002 #define XLE_USE 0x004 #define XLE_SHOOT 0x008 #define XLE_HIT 0x010 #define XLE_TICKER 0x020 // These two arn't real line events #define XLE_AUTO 0x040 #define XLE_FORCED 0x080 // Treated as XLE_CHAIN (class "do" funcs use it to determine when a "real" // activator isn't present. #define XLE_FUNC 0x100 // Time conversion. #define FLT2TIC(x) ( (int) ((x)*35) ) #define TIC2FLT(x) ( (x)/35.0f ) // Line type definition flags. #define LTF_ACTIVE 0x00000001 // Active in the beginning of a map. // Activation method. Line is activated if any of the following // situations take place. #define LTF_PLAYER_USE_A 0x00000002 // Player uses. #define LTF_OTHER_USE_A 0x00000004 // Nonplayers can activate with use. #define LTF_PLAYER_SHOOT_A 0x00000008 // Player shoots it. #define LTF_OTHER_SHOOT_A 0x00000010 // Non-player thing shoots it. #define LTF_ANY_CROSS_A 0x00000020 // Any mobj. #define LTF_MONSTER_CROSS_A 0x00000040 // Flagged Countkill. #define LTF_PLAYER_CROSS_A 0x00000080 // Player crosses the line. #define LTF_MISSILE_CROSS_A 0x00000100 // Missile crosses the line. #define LTF_PLAYER_HIT_A 0x00000200 // Player hits the line (walks into). #define LTF_OTHER_HIT_A 0x00000400 // Nonplayer hits the line. #define LTF_MONSTER_HIT_A 0x00000800 // Monster hits the line. #define LTF_MISSILE_HIT_A 0x00001000 // Missile collides with the line. #define LTF_ANY_HIT_A 0x00002000 // Any mobj collides with the line. // Deactivating by colliding with the line. #define LTF_PLAYER_USE_D 0x00004000 // Player uses. #define LTF_OTHER_USE_D 0x00008000 // Nonplayers can activate with use. #define LTF_PLAYER_SHOOT_D 0x00010000 // Player shoots it. #define LTF_OTHER_SHOOT_D 0x00020000 // Non-player thing shoots it. #define LTF_ANY_CROSS_D 0x00040000 // Any mobj. #define LTF_MONSTER_CROSS_D 0x00080000 // Flagged Countkill. #define LTF_PLAYER_CROSS_D 0x00100000 // Player crosses the line. #define LTF_MISSILE_CROSS_D 0x00200000 // Missile crosses the line. #define LTF_PLAYER_HIT_D 0x00400000 // Player hits the line (walks into). #define LTF_OTHER_HIT_D 0x00800000 // Nonplayer hits the line. #define LTF_MONSTER_HIT_D 0x01000000 // Monster hits the line. #define LTF_MISSILE_HIT_D 0x02000000 // Missile collides with the line. #define LTF_ANY_HIT_D 0x04000000 // Any mobj collides with the line. // A+D activation methods. (A and D flags combined.) #define LTF_PLAYER_USE 0x00004002 // Player uses. #define LTF_OTHER_USE 0x00008004 // Non-player uses. #define LTF_PLAYER_SHOOT 0x00010008 // Player shoots it. #define LTF_OTHER_SHOOT 0x00020010 // Non-player thing shoots it. #define LTF_ANY_CROSS 0x00040020 // Any mobj. #define LTF_MONSTER_CROSS 0x00080040 // Flagged Countkill. #define LTF_PLAYER_CROSS 0x00100080 // Player crosses the line. #define LTF_MISSILE_CROSS 0x00200100 // Missile crosses the line. #define LTF_PLAYER_HIT 0x00400200 // Player hits the line (walks into). #define LTF_OTHER_HIT 0x00800400 // Nonplayer hits the line. #define LTF_MONSTER_HIT 0x01000800 // Monster hits the line. #define LTF_MISSILE_HIT 0x02001000 // Missile collides with the line. #define LTF_ANY_HIT 0x04002000 // Any mobj collides with the line. // Special activation methods/requirements. #define LTF_TICKER_A 0x08000000 // Activate on ticker. #define LTF_TICKER_D 0x10000000 // Deactivate on ticker. #define LTF_TICKER 0x18000000 // A+D on ticker. #define LTF_MOBJ_GONE 0x20000000 // a9 specifies mobj type #define LTF_NO_OTHER_USE_SECRET 0x40000000 // Nonplr can't use line if secret #define LTF_ACTIVATOR_TYPE 0x80000000 // a9 specifies mobj type // When to do effect? #define LTF2_WHEN_ACTIVATED 0x00000001 #define LTF2_WHEN_DEACTIVATED 0x00000002 #define LTF2_WHEN_ACTIVE 0x00000004 #define LTF2_WHEN_INACTIVE 0x00000008 #define LTF2_WHEN_LAST 0x00000010 // Only do effects when count=1. // Activation requirements. #define LTF2_KEY(n) (1<<(5+n)) #define LTF2_KEY1 0x00000020 #define LTF2_KEY2 0x00000040 #define LTF2_KEY3 0x00000080 #define LTF2_KEY4 0x00000100 #define LTF2_KEY5 0x00000200 #define LTF2_KEY6 0x00000400 #define LTF2_LINE_ACTIVE 0x00000800 // line ref: a4 + a5 #define LTF2_LINE_INACTIVE 0x00001000 // line ref: a6 + a7 #define LTF2_COLOR 0x00002000 // a8: activator's color. // Continued in flags2. #define LTF2_HEALTH_ABOVE 0x00004000 // a0 (activator health) #define LTF2_HEALTH_BELOW 0x00008000 // a1 #define LTF2_POWER_ABOVE 0x00010000 // a2 (activator power) #define LTF2_POWER_BELOW 0x00020000 // a3 #define LTF2_SINGLEPLAYER 0x00040000 #define LTF2_COOPERATIVE 0x00080000 #define LTF2_DEATHMATCH 0x00100000 #define LTF2_ANY_MODE 0x001c0000 // Singleplayer, coop and DM combined. #define LTF2_EASY 0x00200000 #define LTF2_MED 0x00400000 #define LTF2_HARD 0x00800000 #define LTF2_ANY_SKILL 0x00e00000 // Easy/med/hard combined. #define LTF2_SKILL_SHIFT 21 // 1< Plane reference type. { LPREF_NONE, LPREF_MY_FLOOR, LPREF_TAGGED_FLOORS, LPREF_LINE_TAGGED_FLOORS, LPREF_ACT_TAGGED_FLOORS, LPREF_INDEX_FLOOR, LPREF_ALL_FLOORS, LPREF_MY_CEILING, LPREF_TAGGED_CEILINGS, LPREF_LINE_TAGGED_CEILINGS, LPREF_ACT_TAGGED_CEILINGS, LPREF_INDEX_CEILING, LPREF_ALL_CEILINGS, LPREF_SPECIAL, // 2nd param of reference treated in a special way. LPREF_BACK_FLOOR, LPREF_BACK_CEILING, LPREF_THING_EXIST_FLOORS, LPREF_THING_EXIST_CEILINGS, LPREF_THING_NOEXIST_FLOORS, LPREF_THING_NOEXIST_CEILINGS, // Line -> Sector references (same as ->Plane, really). LSREF_NONE = LPREF_NONE, LSREF_MY, LSREF_TAGGED, LSREF_LINE_TAGGED, LSREF_ACT_TAGGED, LSREF_INDEX, LSREF_ALL, LSREF_BACK = LPREF_BACK_FLOOR, LSREF_THING_EXIST = LPREF_THING_EXIST_FLOORS, LSREF_THING_NOEXIST = LPREF_THING_NOEXIST_FLOORS }; enum // Sector -> Plane reference type. { SPREF_NONE, SPREF_MY_FLOOR, SPREF_MY_CEILING, SPREF_ORIGINAL_FLOOR, SPREF_ORIGINAL_CEILING, SPREF_CURRENT_FLOOR, SPREF_CURRENT_CEILING, SPREF_HIGHEST_FLOOR, SPREF_HIGHEST_CEILING, SPREF_LOWEST_FLOOR, SPREF_LOWEST_CEILING, SPREF_NEXT_HIGHEST_FLOOR, SPREF_NEXT_HIGHEST_CEILING, SPREF_NEXT_LOWEST_FLOOR, SPREF_NEXT_LOWEST_CEILING, SPREF_MIN_BOTTOM_MATERIAL, SPREF_MIN_MID_MATERIAL, SPREF_MIN_TOP_MATERIAL, SPREF_MAX_BOTTOM_MATERIAL, SPREF_MAX_MID_MATERIAL, SPREF_MAX_TOP_MATERIAL, SPREF_SECTOR_TAGGED_FLOOR, SPREF_LINE_TAGGED_FLOOR, SPREF_TAGGED_FLOOR, SPREF_ACT_TAGGED_FLOOR, SPREF_INDEX_FLOOR, SPREF_SECTOR_TAGGED_CEILING, SPREF_LINE_TAGGED_CEILING, SPREF_TAGGED_CEILING, SPREF_ACT_TAGGED_CEILING, SPREF_INDEX_CEILING, SPREF_BACK_FLOOR, SPREF_BACK_CEILING, SPREF_SPECIAL, SPREF_LINE_ACT_TAGGED_FLOOR, SPREF_LINE_ACT_TAGGED_CEILING }; enum // Special lightlevel sources. { LIGHTREF_NONE, LIGHTREF_MY, // Actline's front sector. LIGHTREF_ORIGINAL, // Original light level of the sector. LIGHTREF_CURRENT, // Current light level of the sector. LIGHTREF_HIGHEST, // Highest surrounding. LIGHTREF_LOWEST, // Lowest surrounding. LIGHTREF_NEXT_HIGHEST, // Next highest surrounding. LIGHTREF_NEXT_LOWEST, // Next lowest surrounding. LIGHTREF_BACK // Actline's back sector. }; enum // Line.data references { LDREF_NONE, // Not actually used atm LDREF_ID, LDREF_SPECIAL, LDREF_TAG, LDREF_ACTTAG, LDREF_COUNT, LDREF_ANGLE, LDREF_LENGTH, LDREF_TOP_OFFSETX, LDREF_TOP_OFFSETY, LDREF_MIDDLE_OFFSETX, LDREF_MIDDLE_OFFSETY, LDREF_BOTTOM_OFFSETX, LDREF_BOTTOM_OFFSETY }; // Chain sequence flags. #define CHSF_DEACTIVATE_WHEN_DONE 0x1 #define CHSF_LOOP 0x2 typedef struct { thinker_t thinker; linedef_t* line; } xlthinker_t; // State data for each line. typedef struct { linetype_t info; // Type definition. boolean active; boolean disabled; // If true, skip all processing. int timer; int tickerTimer; void* activator; int idata; float fdata; int chIdx; // Chain sequence index. float chTimer; // Chain sequence timer. } xgline_t; // The XG line Classes extern struct xgclass_s xgClasses[]; // Used as the activator if there is no real activator. extern struct mobj_s dummyThing; // Register the XG classnames for XGdev void XG_Register(void); // Initialize extended lines for the map. void XL_Init(void); // Called when reseting engine state. void XL_Update(void); void XL_Thinker(xlthinker_t* xl); void XL_SetLineType(struct linedef_s* line, int id); linetype_t* XL_GetType(int id); int XL_LineEvent(int evType, int lineType, struct linedef_s* line, int sideNum, void* data); void XL_ActivateLine(boolean activating, linetype_t* info, struct linedef_s* line, int sideNum, struct mobj_s* data, int evType); int XL_TraverseLines(struct linedef_s* line, int reftype, int ref, void* context, void* context2, struct mobj_s* activator, int (C_DECL *func)()); int XL_TraversePlanes(struct linedef_s* line, int reftype, int ref, void* context, void* context2, boolean travSectors, struct mobj_s* activator, int (C_DECL *func)()); // Return false if the event was processed. int XL_CrossLine(struct linedef_s* line, int sideNum, struct mobj_s* thing); int XL_UseLine(struct linedef_s* line, int sideNum, struct mobj_s* thing); int XL_ShootLine(struct linedef_s* line, int sideNum, struct mobj_s* thing); int XL_HitLine(struct linedef_s* line, int sideNum, struct mobj_s* thing); int XG_RandomInt(int min, int max); void SV_WriteXGLine(struct linedef_s* li); void SV_ReadXGLine(struct linedef_s* li); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_actor.h0000644000175000017500000000451311357170242023264 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_actor.h: Common actor (mobj) routines. */ #ifndef __DD_COMMON_ACTOR_H__ #define __DD_COMMON_ACTOR_H__ void P_MobjRemove(mobj_t* mo, boolean noRespawn); void P_MobjUnsetPosition(mobj_t* mo); void P_MobjSetPosition(mobj_t* mo); void P_MobjSetSRVO(mobj_t* mo, float stepx, float stepy); void P_MobjSetSRVOZ(mobj_t* mo, float stepz); void P_MobjClearSRVO(mobj_t* mo); void P_MobjAngleSRVOTicker(mobj_t* mo); boolean P_MobjIsCamera(const mobj_t* mo); void P_UpdateHealthBits(mobj_t* mo); statenum_t P_GetState(mobjtype_t mobjType, statename_t name); void P_DoDeferredSpawns(void); void P_PurgeDeferredSpawns(void); void P_DeferSpawnMobj3f(int minTics, mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags, void (*callback) (mobj_t* mo, void* context), void* context); void P_DeferSpawnMobj3fv(int minTics, mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags, void (*callback) (mobj_t* mo, void* context), void* context); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_xgsec.h0000644000175000017500000001637311357170242023274 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_xgsec.c: Extended Generalized Sector Types. */ #ifndef __XG_SECTORTYPE_H__ #define __XG_SECTORTYPE_H__ #include "g_common.h" // Sector chain event types. enum { XSCE_FLOOR, XSCE_CEILING, XSCE_INSIDE, XSCE_TICKER, XSCE_NUM_CHAINS, XSCE_FUNCTION }; // Sector Type flags. #define STF_GRAVITY 0x00000001 // Use custom gravity gravity. #define STF_FRICTION 0x00000002 // Use custom friction. #define STF_CRUSH 0x00000004 #define STF_PLAYER_WIND 0x00000008 // Wind affects players. #define STF_OTHER_WIND 0x00000010 #define STF_MONSTER_WIND 0x00000020 #define STF_MISSILE_WIND 0x00000040 #define STF_ANY_WIND 0x00000018 // Player + nonplayer. #define STF_ACT_TAG_MATERIALMOVE 0x00000080 // Materialmove from act tagged line. #define STF_ACT_TAG_WIND 0x00000100 #define STF_FLOOR_WIND 0x00000200 // Wind only when touching the floor. #define STF_CEILING_WIND 0x00000400 // Sector Chain Event flags. #define SCEF_PLAYER_A 0x00000001 // Activate for players. #define SCEF_OTHER_A 0x00000002 // Act. for non-players. #define SCEF_MONSTER_A 0x00000004 // Countkills. #define SCEF_MISSILE_A 0x00000008 // Missiles. #define SCEF_ANY_A 0x00000010 // All mobjs. #define SCEF_TICKER_A 0x00000020 // Activate by ticker. #define SCEF_PLAYER_D 0x00000040 // Deactivate for players. #define SCEF_OTHER_D 0x00000080 // Deact. for non-players. #define SCEF_MONSTER_D 0x00000100 // Countkills. #define SCEF_MISSILE_D 0x00000200 // Missiles. #define SCEF_ANY_D 0x00000400 // All mobjs. #define SCEF_TICKER_D 0x00000800 // Deactivate by ticker. // Plane mover flags. #define PMF_CRUSH 0x1 // Crush things inside. // (De)activate origin if move is blocked (when not crushing) and // destroy mover. Normally the mover waits until it can move again. #define PMF_ACTIVATE_ON_ABORT 0x2 #define PMF_DEACTIVATE_ON_ABORT 0x4 // (De)activate origin when move is done. #define PMF_ACTIVATE_WHEN_DONE 0x8 #define PMF_DEACTIVATE_WHEN_DONE 0x10 #define PMF_OTHER_FOLLOWS 0x20 // Other plane follows. #define PMF_WAIT 0x40 // Wait until timer counts to 0. #define PMF_SET_ORIGINAL 0x80 // Set origfloor/ceil. // Only play sound for one sector. #define PMF_ONE_SOUND_ONLY 0x100 typedef struct function_s { struct function_s* link; // Linked to another func? char* func; int flags; int pos; int repeat; int timer, maxTimer; int minInterval, maxInterval; float scale, offset; float value, oldValue; } function_t; enum { XGSP_FLOOR, XGSP_CEILING, XGSP_RED = 0, XGSP_GREEN, XGSP_BLUE }; typedef struct { thinker_t thinker; sector_t* sector; } xsthinker_t; typedef struct { boolean disabled; function_t rgb[3]; // Don't move the functions around in the struct. function_t plane[2]; function_t light; sectortype_t info; int timer; int chainTimer[DDLT_MAX_CHAINS]; } xgsector_t; typedef struct { thinker_t thinker; struct sector_s* sector; boolean ceiling; // True if operates on the ceiling. int flags; struct linedef_s* origin; float destination; float speed; // Signed. float crushSpeed; // Signed (speed to use when crushing). material_t* setMaterial; // Set material when move done. int setSectorType; // Sector type to set when move done // (-1 if no change). int startSound; // Played after waiting. int endSound; // Play when move done. int moveSound; // Sound to play while moving. int minInterval, maxInterval; // Sound playing intervals. int timer; // Counts down to zero. } xgplanemover_t; void XS_Init(void); void XS_Update(void); void XS_Thinker(xsthinker_t* xs); float XS_Gravity(struct sector_s *sector); float XS_Friction(struct sector_s *sector); float XS_ThrustMul(struct sector_s *sector); void XS_InitMovePlane(struct linedef_s *line); int C_DECL XSTrav_MovePlane(struct sector_s *sector, boolean ceiling, void *context, void *context2, struct mobj_s *activator); int C_DECL XSTrav_SectorType(struct sector_s *sec, boolean ceiling, void *context, void *context2, struct mobj_s *activator); int C_DECL XSTrav_SectorLight(struct sector_s *sector, boolean ceiling, void *context, void *context2, struct mobj_s *activator); int C_DECL XSTrav_PlaneMaterial(struct sector_s *sec, boolean ceiling, void *context, void *context2, struct mobj_s *activator); void XS_InitStairBuilder(struct linedef_s *line); int C_DECL XSTrav_BuildStairs(struct sector_s *sector, boolean ceiling, void *context, void *context2, struct mobj_s *activator); int C_DECL XSTrav_SectorSound(struct sector_s *sec, boolean ceiling, void *context, void *context2, struct mobj_s *activator); int C_DECL XSTrav_MimicSector(struct sector_s *sector, boolean ceiling, void *context, void *context2, struct mobj_s *activator); int C_DECL XSTrav_Teleport(struct sector_s *sector, boolean ceiling, void *context, void *context2, struct mobj_s *activator); void XS_SetSectorType(struct sector_s *sec, int special); void XS_ChangePlaneMaterial(struct sector_s *sector, boolean ceiling, material_t* mat, float *rgb); xgplanemover_t *XS_GetPlaneMover(struct sector_s *sector, boolean ceiling); void XS_PlaneMover(xgplanemover_t *mover); // A thinker for plane movers. void SV_WriteXGSector(struct sector_s *sec); void SV_ReadXGSector(struct sector_s *sec); void SV_WriteXGPlaneMover(thinker_t *th); int SV_ReadXGPlaneMover(xgplanemover_t* mov); DEFCC(CCmdMovePlane); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_plat.h0000644000175000017500000000500011357170242023104 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_plat.h: Common playsim routines relating to moving platforms. */ #ifndef __COMMON_THINKER_PLAT_H__ #define __COMMON_THINKER_PLAT_H__ typedef enum { PS_UP, // Moving up. PS_DOWN, // Moving down. PS_WAIT } platstate_e; typedef enum { PT_PERPETUALRAISE, PT_DOWNWAITUPSTAY, #if __JHEXEN__ PT_DOWNBYVALUEWAITUPSTAY, PT_UPWAITDOWNSTAY, PT_UPBYVALUEWAITDOWNSTAY, #else # if __JDOOM64__ PT_UPWAITDOWNSTAY, //jd64 kaiser - outcast PT_DOWNWAITUPDOOR, //jd64 kaiser - outcast # endif PT_RAISEANDCHANGE, PT_RAISETONEARESTANDCHANGE, # if __JDOOM__ || __JDOOM64__ PT_DOWNWAITUPSTAYBLAZE, # if __JDOOM64__ PT_DOWNWAITUPPLUS16STAYBLAZE, //jd64 # endif # endif #endif NUMPLATTYPES } plattype_e; typedef struct plat_s { thinker_t thinker; sector_t* sector; float speed; float low; float high; int wait; int count; platstate_e state; platstate_e oldState; boolean crush; int tag; plattype_e type; } plat_t; #define PLATWAIT (3) #define PLATSPEED (1) void T_PlatRaise(plat_t* pl); #if __JHEXEN__ int EV_DoPlat(linedef_t* li, byte* args, plattype_e type, int amount); int P_PlatDeactivate(short tag); #else int EV_DoPlat(linedef_t* li, plattype_e type, int amount); int P_PlatActivate(short tag); int P_PlatDeactivate(short tag); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_saveg.h0000644000175000017500000000677611357170242023276 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_saveg.h: Common save game handling. */ #ifndef __P_SAVEG_H__ #define __P_SAVEG_H__ /** * Original indices must remain unchanged! * Added new think classes to the end. */ typedef enum thinkclass_e { TC_NULL = -1, TC_END, TC_MOBJ, TC_XGMOVER, TC_CEILING, TC_DOOR, TC_FLOOR, TC_PLAT, #if __JHEXEN__ TC_INTERPRET_ACS, TC_FLOOR_WAGGLE, TC_LIGHT, TC_PHASE, TC_BUILD_PILLAR, TC_ROTATE_POLY, TC_MOVE_POLY, TC_POLY_DOOR, #else TC_FLASH, TC_STROBE, # if __JDOOM__ || __JDOOM64__ TC_GLOW, TC_FLICKER, # if __JDOOM64__ TC_BLINK, # endif # else TC_GLOW, # endif #endif TC_MATERIALCHANGER, NUMTHINKERCLASSES } thinkerclass_t; void SV_Init(void); void SV_GetSaveGameFileName(char* str, int slot, size_t len); int SV_GetSaveDescription(char* str, const char* filename, size_t len); #if __JHEXEN__ boolean SV_SaveGame(int slot, const char* description); boolean SV_LoadGame(int slot); void SV_MapTeleport(uint map, uint position); void SV_HxInitBaseSlot(void); void SV_HxUpdateRebornSlot(void); void SV_HxClearRebornSlot(void); boolean SV_HxRebornSlotAvailable(void); int SV_HxGetRebornSlot(void); #else boolean SV_SaveGame(const char* filename, const char* description); boolean SV_LoadGame(const char* filename); #endif // Write a client savegame file. void SV_SaveClient(unsigned int gameid); void SV_GetClientSaveGameFileName(char* str, unsigned int gameID, size_t len); void SV_LoadClient(unsigned int gameid); #if __JHEXEN__ int SV_ThingArchiveNum(mobj_t* mo); #else unsigned short SV_ThingArchiveNum(mobj_t* mo); #endif mobj_t* SV_GetArchiveThing(int thingid, void* address); void SV_Write(const void* data, int len); void SV_WriteByte(byte val); #if __JHEXEN__ void SV_WriteShort(unsigned short val); #else void SV_WriteShort(short val); #endif #if __JHEXEN__ void SV_WriteLong(unsigned int val); #else void SV_WriteLong(long val); #endif void SV_WriteFloat(float val); void SV_Read(void* data, int len); byte SV_ReadByte(void); short SV_ReadShort(void); long SV_ReadLong(void); float SV_ReadFloat(void); // Misc save/load routines. void SV_UpdateReadMobjFlags(mobj_t* mo, int ver); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_switch.h0000644000175000017500000000457011357170242023460 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_switch.h: Common playsim routines relating to switches. */ #ifndef __COMMON_SWITCH_H__ #define __COMMON_SWITCH_H__ typedef enum { SID_MIDDLE, SID_BOTTOM, SID_TOP } sidedefsurfaceid_t; #define BUTTONTIME (TICSPERSEC) // 1 second, in ticks. typedef struct { thinker_t thinker; int timer; sidedef_t* side; sidedefsurfaceid_t ssurfaceID; material_t* material; } materialchanger_t; /** * This struct is used to provide byte offsets when reading a custom * SWITCHES lump thus it must be packed and cannot be altered. */ #pragma pack(1) typedef struct { /* Do NOT change these members in any way! */ char name1[9]; char name2[9]; #if __JHEXEN__ int soundID; #else short episode; #endif } switchlist_t; #pragma pack() void P_InitSwitchList(void); material_t* P_GetSwitch(material_t* mat, const switchlist_t** info); boolean P_ToggleSwitch(sidedef_t* side, int sound, boolean silent, int tics); boolean P_UseSpecialLine(mobj_t* mo, linedef_t* line, int side); void T_MaterialChanger(materialchanger_t* mchanger); void P_SpawnMaterialChanger(sidedef_t* side, sidedefsurfaceid_t ssurfaceID, material_t* mat, int tics); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/g_controls.h0000644000175000017500000001012411357170242024001 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_controls.h: Common code for game controls */ #ifndef __COMMON_CONTROLS_H__ #define __COMMON_CONTROLS_H__ /* // Game registered bindContexts enum { GBC_CLASS1 = NUM_DDBINDCLASSES, GBC_CLASS2, GBC_CLASS3, GBC_MENUHOTKEY, GBC_CHAT, GBC_MESSAGE }; */ // Control identifiers. enum { CTL_SPEED = CTL_FIRST_GAME_CONTROL, //CTL_STRAFE, CTL_LOOK_CENTER, CTL_FALL_DOWN, CTL_USE, CTL_ATTACK, CTL_JUMP, CTL_WEAPON1, CTL_WEAPON2, CTL_WEAPON3, CTL_WEAPON4, CTL_WEAPON5, CTL_WEAPON6, CTL_WEAPON7, CTL_WEAPON8, CTL_WEAPON9, #if __JDOOM64__ CTL_WEAPON10, #endif CTL_WEAPON0, CTL_NEXT_WEAPON, CTL_PREV_WEAPON, #if __JHERETIC__ || __JHEXEN__ CTL_USE_ITEM, CTL_NEXT_ITEM, CTL_PREV_ITEM, CTL_PANIC, #endif #if __JHERETIC__ CTL_TOME_OF_POWER, CTL_INVISIBILITY, CTL_FLY, CTL_TORCH, CTL_HEALTH, CTL_SUPER_HEALTH, CTL_TELEPORT, CTL_FIREBOMB, CTL_INVULNERABILITY, CTL_EGG, #endif #if __JHEXEN__ CTL_FLY, CTL_TORCH, CTL_HEALTH, CTL_MYSTIC_URN, CTL_KRATER, CTL_SPEED_BOOTS, CTL_BLAST_RADIUS, CTL_TELEPORT, CTL_TELEPORT_OTHER, CTL_FIREBOMB, CTL_POISONBAG, CTL_INVULNERABILITY, CTL_DARK_SERVANT, CTL_EGG, #endif CTL_MAP, CTL_MAP_PAN_X, CTL_MAP_PAN_Y, CTL_MAP_ZOOM, CTL_MAP_ZOOM_MAX, CTL_MAP_FOLLOW, CTL_MAP_ROTATE, CTL_MAP_MARK_ADD, CTL_MAP_MARK_CLEAR_ALL, CTL_HUD_SHOW, CTL_SCORE_SHOW, CTL_LOG_REFRESH }; // This structure replaced ticcmd as the place where players store the intentions // of their human operators. typedef struct playerbrain_s { float forwardMove; // 1.0 for maximum movement float sideMove; // 1.0 for maximum movement float upMove; // 1.0 for maximum movement int changeWeapon; // WT_NOCHANGE, or the weapon to change to int cycleWeapon; // +1 or -1 #if __JHERETIC__ || __JHEXEN__ int cycleInvItem; // +1 or -1 #endif // Bits: uint speed : 1; uint use : 1; uint lunge : 1; uint attack : 1; uint lookCenter : 1; uint fallDown : 1; uint jump : 1; uint mapToggle : 1; uint mapZoomMax : 1; uint mapFollow : 1; uint mapRotate : 1; uint mapMarkAdd : 1; uint mapMarkClearAll : 1; uint hudShow : 1; uint scoreShow : 1; uint doReborn: 1; // Set when the player wishes to be reborn. #if __JHERETIC__ || __JHEXEN__ uint useInvItem: 1; #endif uint logRefresh: 1; } playerbrain_t; void G_ControlRegister(void); void G_DefaultBindings(void); void G_RegisterBindClasses(void); int G_PrivilegedResponder(event_t *event); boolean G_AdjustControlState(event_t *ev); void G_LookAround(int pnum); void G_SetPause(boolean yes); void G_ResetMousePos(void); void G_ControlReset(int pnum); float G_GetLookOffset(int pnum); void G_ResetLookOffset(int pnum); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/d_netcl.h0000644000175000017500000000354411357170242023250 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_netcl.h: */ #ifndef __D_NETCL_H__ #define __D_NETCL_H__ #include "d_net.h" void* NetCl_WriteCommands(ticcmd_t* cmd, int count); void NetCl_UpdateGameState(byte* data); void NetCl_CheatRequest(const char* command); void NetCl_UpdatePlayerState(byte* data, int plrNum); void NetCl_UpdatePlayerState2(byte* data, int plrNum); void NetCl_UpdatePSpriteState(byte* data); void NetCl_UpdateJumpPower(void* data); void NetCl_Intermission(byte* data); void NetCl_Finale(int packetType, byte* data); void NetCl_UpdatePlayerInfo(byte* data); void NetCl_SendPlayerInfo(void); void NetCl_SaveGame(void* data); void NetCl_LoadGame(void* data); void NetCl_Paused(boolean setPause); void NetCl_PlayerActionRequest(player_t* player, int actionType); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/g_eventsequence.h0000644000175000017500000000254711357170242025022 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef COMMON_EVENTSEQUENCE_H #define COMMON_EVENTSEQUENCE_H boolean G_EventSequenceResponder(event_t* ev); void G_AddEventSequence(const unsigned char* sequence, size_t sequenceLength, int (*callback) (const int*, int)); #endif /* COMMON_EVENTSEQUENCE_H */ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_tick.h0000644000175000017500000000233111357170242023102 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_tick.h: (Common) Top-level tick stuff. */ #ifndef __P_TICK_H__ #define __P_TICK_H__ extern int mapTime; extern int actualMapTime; extern int timerGame; void P_RunPlayers(timespan_t ticLength); boolean P_IsPaused(void); void P_DoTick(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_player.h0000644000175000017500000000575611357170242023462 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_player.h: Common playsim routines relating to players. */ #ifndef __COMMON_PLAYER_H__ #define __COMMON_PLAYER_H__ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif #if __JDOOM64__ #define NUM_WEAPON_SLOTS (8) #elif __JDOOM__ || __JHERETIC__ #define NUM_WEAPON_SLOTS (7) #elif __JHEXEN__ #define NUM_WEAPON_SLOTS (4) #endif #if __JHEXEN__ void P_InitPlayerClassInfo(void); #endif void P_InitWeaponSlots(void); void P_FreeWeaponSlots(void); boolean P_SetWeaponSlot(weapontype_t type, byte slot); byte P_GetWeaponSlot(weapontype_t type); int P_IterateWeaponsInSlot(byte slot, boolean reverse, int (*callback) (weapontype_t, void* context), void* context); // A specialized iterator for weapon slot cycling. weapontype_t P_WeaponSlotCycle(weapontype_t type, boolean prev); int P_GetPlayerNum(player_t* plr); int P_GetPlayerCheats(player_t* plr); weapontype_t P_PlayerFindWeapon(player_t* plr, boolean prev); weapontype_t P_MaybeChangeWeapon(player_t* plr, weapontype_t weapon, ammotype_t ammo, boolean force); boolean P_CheckAmmo(player_t* plr); void P_ShotAmmo(player_t* plr); #if __JHEXEN__ void P_PlayerChangeClass(player_t* plr, playerclass_t newClass); #endif void P_SetMessage(player_t* plr, char* msg, boolean noHide); #if __JHEXEN__ void P_SetYellowMessage(player_t* plr, char* msg, boolean noHide); #endif void P_PlayerThinkCamera(player_t* plr); #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ void P_PlayerSetArmorType(player_t* plr, int type); int P_PlayerGiveArmorBonus(player_t* plr, int points); #else // __JHEXEN__ int P_PlayerGiveArmorBonus(player_t* plr, armortype_t type, int points); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_inventory.h0000644000175000017500000000465011357170242024213 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inventory.h: Common code for player inventory. */ #if __JHERETIC__ || __JHEXEN__ || __JDOOM64__ #ifndef __COMMON_INVENTORY_H__ #define __COMMON_INVENTORY_H__ // Inventory Item Flags: #define IIF_USE_PANIC 0x1 // Item is usable when panicked. #define IIF_READY_ALWAYS 0x8 // Item is always "ready" (i.e., usable). typedef struct { byte flags; char niceName[32]; char action[32]; char useSnd[32]; char patch[9]; int hotKeyCtrlIdent; } def_invitem_t; typedef struct { inventoryitemtype_t type; textenum_t niceName; acfnptr_t action; sfxenum_t useSnd; lumpnum_t patchLump; } invitem_t; extern int didUseItem; void P_InitInventory(void); void P_ShutdownInventory(void); const invitem_t* P_GetInvItem(int id); const def_invitem_t* P_GetInvItemDef(inventoryitemtype_t type); void P_InventoryEmpty(int player); int P_InventoryGive(int player, inventoryitemtype_t type, int silent); int P_InventoryTake(int player, inventoryitemtype_t type, int silent); int P_InventoryUse(int player, inventoryitemtype_t type, int silent); int P_InventorySetReadyItem(int player, inventoryitemtype_t type); inventoryitemtype_t P_InventoryReadyItem(int player); unsigned int P_InventoryCount(int player, inventoryitemtype_t type); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_xg.h0000644000175000017500000000323311357170242022570 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef __EXTENDED_GENERAL_H__ #define __EXTENDED_GENERAL_H__ #include "p_xgline.h" #include "p_xgsec.h" extern int xgDev; extern boolean xgDataLumps; // Debug message printer. void XG_Dev(const char *format, ...) PRINTF_F(1,2); // Called once, at post init. void XG_ReadTypes(void); // Init both XG lines and sectors. Called for each map. void XG_Init(void); // Thinks for XG lines and sectors. void XG_Ticker(void); // Updates XG state during engine reset. void XG_Update(void); //void XG_WriteTypes(FILE * file); void XG_ReadTypes(void); linetype_t *XG_GetLumpLine(int id); sectortype_t *XG_GetLumpSector(int id); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/hu_log.h0000644000175000017500000000631611357170242023115 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_log.h: */ #ifndef __HUD_LOG_H__ #define __HUD_LOG_H__ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif // Log Message Flags (LMF_*), used with Hu_LogPost. #define LMF_NOHIDE (0x1) #define LMF_YELLOW (0x2) void Hu_LogRegister(void); void Hu_LogStart(int player); void Hu_LogShutdown(void); void Hu_LogPost(int player, byte flags, const char* msg); void Hu_LogRefresh(int player); void Hu_LogEmpty(int player); void Hu_LogDrawer(int player); void Hu_LogTicker(void); #endif /**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_chat.h: */ #ifndef __HUD_CHAT_H__ #define __HUD_CHAT_H__ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #endif extern boolean chatOn; void Chat_Register(void); void Chat_Init(void); void Chat_Start(void); void Chat_Open(int player, boolean open); boolean Chat_Responder(event_t* ev); void Chat_Drawer(int player); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_map.h0000644000175000017500000000574511357170242022741 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_map.h : Common play/maputil functions. */ #ifndef __COMMON_P_LOCAL__ #define __COMMON_P_LOCAL__ extern float attackRange; // If "floatOk" true, move would be ok if within "tmFloorZ - tmCeilingZ". extern boolean floatOk; extern float tmFloorZ; extern float tmCeilingZ; extern material_t* tmFloorMaterial; extern linedef_t* ceilingLine, *floorLine; extern linedef_t* blockLine; extern mobj_t* lineTarget; // Who got hit (or NULL). extern mobj_t* tmThing; #if __JHEXEN__ extern mobj_t* puffSpawned; extern mobj_t* blockingMobj; #endif extern float tmBBox[]; extern boolean fellDown; boolean P_CheckSight(const mobj_t* from, const mobj_t* to); boolean P_CheckPosition2f(mobj_t* thing, float x, float y); boolean P_CheckPosition3f(mobj_t* thing, float x, float y, float z); boolean P_CheckPosition3fv(mobj_t* thing, const float pos[3]); #if __JHEXEN__ void P_RadiusAttack(mobj_t* spot, mobj_t* source, int damage, int distance, boolean canDamageSource); #else void P_RadiusAttack(mobj_t* spot, mobj_t* source, int damage, int distance); #endif #if !__JHEXEN__ boolean P_TryMove(mobj_t* thing, float x, float y, boolean dropoff, boolean slide); #else boolean P_TryMove(mobj_t* thing, float x, float y); #endif boolean P_TeleportMove(mobj_t* thing, float x, float y, boolean alwaysStomp); void P_SlideMove(mobj_t* mo); void P_UseLines(player_t* player); boolean P_ChangeSector(sector_t* sector, boolean crunch); float P_AimLineAttack(mobj_t* t1, angle_t angle, float distance); void P_LineAttack(mobj_t* t1, angle_t angle, float distance, float slope, int damage); float P_GetGravity(void); boolean P_CheckSides(mobj_t* actor, float x, float y); #if __JHEXEN__ boolean P_TestMobjLocation(mobj_t* mobj); void PIT_ThrustSpike(mobj_t* actor); boolean P_UsePuzzleItem(player_t* player, int itemType); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/g_update.h0000644000175000017500000000216011357170242023421 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_update.h: */ #ifndef __GAME_UPDATE_H__ #define __GAME_UPDATE_H__ void G_SetGlowing(void); void G_UpdateState(int step); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/f_infine.h0000644000175000017500000000376211357170242023417 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * f_infine.h: */ #ifndef __F_INFINE_H__ #define __F_INFINE_H__ // Condition truth values (that clients can't deduce on their own). enum { FICOND_SECRET, FICOND_LEAVEHUB, NUM_FICONDS }; typedef enum infinemode_e { FIMODE_LOCAL, FIMODE_OVERLAY, FIMODE_BEFORE, FIMODE_AFTER } infinemode_t; extern boolean fiActive; extern boolean fiCmdExecuted; // Set to true after first command. extern boolean briefDisabled; void FI_Reset(void); void FI_Start(char* finalescript, infinemode_t mode); void FI_End(void); void FI_SetCondition(int index, boolean value); int FI_Briefing(uint episode, uint map, ddfinale_t* fin); int FI_Debriefing(uint episode, uint map, ddfinale_t* fin); void FI_DemoEnds(void); int FI_SkipRequest(void); void FI_Ticker(void); int FI_Responder(event_t* ev); void FI_Drawer(void); boolean FI_IsMenuTrigger(event_t* ev); DEFCC(CCmdStartInFine); DEFCC(CCmdStopInFine); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/x_hair.h0000644000175000017500000000220311357170242023101 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_hair.c: HUD crosshairs. */ #ifndef __X_HAIR_H__ #define __X_HAIR_H__ #define NUM_XHAIRS (6) void X_Drawer(int player); void X_Register(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_automap.h0000644000175000017500000001442211357170242023622 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_automap.h : The automap. */ #ifndef __AUTOMAP_H__ #define __AUTOMAP_H__ #define MAX_MAP_POINTS (10) // Automap flags: #define AMF_REND_THINGS 0x01 #define AMF_REND_KEYS 0x02 #define AMF_REND_ALLLINES 0x04 #define AMF_REND_XGLINES 0x08 #define AMF_REND_VERTEXES 0x10 #define AMF_REND_LINE_NORMALS 0x20 typedef struct automapwindow_s { // Where the window currently is on screen, and the dimensions. float x, y, width, height; // Where the window should be on screen, and the dimensions. float targetX, targetY, targetWidth, targetHeight; float oldX, oldY, oldWidth, oldHeight; float posTimer; } automapwindow_t; typedef struct { float pos[3]; } automappoint_t; typedef struct automap_s { // State int flags; boolean active; boolean fullScreenMode; // If the map is currently in fullscreen mode. boolean panMode; // If the map viewer location is currently in free pan mode. boolean rotate; boolean forceMaxScale; // If the map is currently in forced max zoom mode. float priorToMaxScale; // Viewer scale before entering maxScale mode. // Used by MTOF to scale from map-to-frame-buffer coords. float scaleMTOF; // Used by FTOM to scale from frame-buffer-to-map coords (=1/scaleMTOF). float scaleFTOM; // Map bounds. float minScale; float bounds[4]; // Paramaters for render. float alpha, targetAlpha, oldAlpha; float alphaTimer; // Automap window (screen space). automapwindow_t window; // Viewer location on the map. float viewTimer; float viewX, viewY; // Current. float targetViewX, targetViewY; // Should be at. float oldViewX, oldViewY; // Previous. // For the parallax layer. float viewPLX, viewPLY; // Current. // View frame scale. float viewScaleTimer; float viewScale; // Current. float targetViewScale; // Should be at. float oldViewScale; // Previous. float minScaleMTOF; // Viewer frame scale limits. float maxScaleMTOF; // // View frame rotation. float angleTimer; float angle; // Current. float targetAngle; // Should be at. float oldAngle; // Previous. // View frame coordinates on map. float viewAABB[4]; // Clip bbox coordinates on map. // Misc float maxViewPositionDelta; boolean updateViewScale; // Marked map points. automappoint_t markpoints[MAX_MAP_POINTS]; boolean markpointsUsed[MAX_MAP_POINTS]; unsigned int markpointnum; // next point to be assigned. } automap_t; #ifdef __cplusplus extern "C" { #endif void Automap_Open(automap_t* map, int yes, int fast); void Automap_RunTic(automap_t* map); void Automap_UpdateWindow(automap_t* map, float newX, float newY, float newWidth, float newHeight); int Automap_IsActive(const automap_t* map); int Automap_AddMark(automap_t* map, float x, float y, float z); int Automap_GetMark(const automap_t* map, unsigned int mark, float* x, float* y, float* z); void Automap_ClearMarks(automap_t* map); unsigned int Automap_GetNumMarks(const automap_t* map); void Automap_SetFlags(automap_t* map, int flags); int Automap_GetFlags(const automap_t* map); void Automap_SetWorldBounds(automap_t* map, float lowX, float hiX, float lowY, float hiY); void Automap_SetMinScale(automap_t* map, const float scale); void Automap_SetWindowTarget(automap_t* map, int x, int y, int w, int h); void Automap_GetWindow(const automap_t* map, float* x, float* y, float* w, float* h); void Automap_SetMaxLocationTargetDelta(automap_t* map, float max); void Automap_SetLocationTarget(automap_t* map, float x, float y); void Automap_GetLocation(const automap_t* map, float* x, float* y); void Automap_SetViewScaleTarget(automap_t* map, float scale); void Automap_SetViewAngleTarget(automap_t* map, float angle); float Automap_GetViewAngle(const automap_t* map); void Automap_SetOpacityTarget(automap_t* map, float alpha); float Automap_GetOpacity(const automap_t* map); // Conversion helpers: float Automap_FrameToMap(const automap_t* map, float val); float Automap_MapToFrame(const automap_t* map, float val); float Automap_MapToFrameMultiplier(const automap_t* map); /// \todo void Automap_SetWindowFullScreenMode(automap_t* map, int value); int Automap_IsMapWindowInFullScreenMode(const automap_t* map); void Automap_SetViewRotate(automap_t* map, int offOnToggle); void Automap_ToggleFollow(automap_t* map); void Automap_ToggleZoomMax(automap_t* map); void Automap_GetInViewAABB(const automap_t* map, float* lowX, float* hiX, float* lowY, float* hiY); void Automap_GetViewParallaxPosition(const automap_t* map, float* x, float* y); #ifdef __cplusplus } #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/hu_lib.h0000644000175000017500000000513211357170242023075 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef __HU_LIB_H__ #define __HU_LIB_H__ #include "hu_stuff.h" #define HU_MAXLINELENGTH (160) // Text Line widget, (parent of Scrolling Text and Input Text widgets). typedef struct { int x, y; // Left-justified position of scrolling text window. char l[HU_MAXLINELENGTH + 1]; // Line of text. int len; // Current line length. int needsupdate; // Whether this line needs to be udpated. } hu_textline_t; // Input Text Line widget (child of Text Line widget). typedef struct { hu_textline_t l; // Text line to input on. int lm; // Left margin past which I am not to delete characters. boolean* on; // Whether to update window. boolean laston; // Last value of *->on. } hu_text_t; void HUlib_init(void); void HUlib_clearTextLine(hu_textline_t* t); void HUlib_initTextLine(hu_textline_t* t, int x, int y); boolean HUlib_addCharToTextLine(hu_textline_t* t, char ch); boolean HUlib_delCharFromTextLine(hu_textline_t* t); void HUlib_eraseTextLine(hu_textline_t* l); void HUlib_initText(hu_text_t* it, int x, int y, boolean* on); void HUlib_delCharFromText(hu_text_t* it); void HUlib_eraseLineFromText(hu_text_t* it); void HUlib_resetText(hu_text_t* it); void HUlib_addPrefixToText(hu_text_t* it, char* str); boolean HUlib_keyInText(hu_text_t* it, unsigned char ch); void HUlib_drawText(hu_text_t* it, gamefontid_t font); void HUlib_eraseText(hu_text_t* it); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_start.h0000644000175000017500000001476511357170242023323 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_start.h: Common playsim code relating to the (re)spawn of map objects. */ #ifndef __COMMON_PLAYSTART_H__ #define __COMMON_PLAYSTART_H__ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ # include "r_defs.h" #else # include "xddefs.h" #endif /** * Map Spot Flags (MSF): * \todo Commonize these flags and introduce translations where needed. */ #define MSF_EASY 0x00000001 // Appears in easy skill modes. #define MSF_MEDIUM 0x00000002 // Appears in medium skill modes. #define MSF_HARD 0x00000004 // Appears in hard skill modes. #if __JDOOM__ || __JDOOM64__ # define MSF_DEAF 0x00000008 // Thing is deaf. #elif __JHERETIC__ || __JHEXEN__ # define MSF_AMBUSH 0x00000008 // Mobj will be deaf spawned deaf. #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ # define MSF_NOTSINGLE 0x00000010 // Appears in multiplayer game modes only. #elif __JHEXEN__ # define MTF_DORMANT 0x00000010 #endif #if __JDOOM__ || __JHERETIC__ # define MSF_NOTDM 0x00000020 // (BOOM) Can not be spawned in the Deathmatch gameMode. # define MSF_NOTCOOP 0x00000040 // (BOOM) Can not be spawned in the Co-op gameMode. # define MSF_FRIENDLY 0x00000080 // (BOOM) friendly monster. #elif __JDOOM64__ # define MSF_DONTSPAWNATSTART 0x00000020 // Do not spawn this thing at map start. # define MSF_SCRIPT_TOUCH 0x00000040 // Mobjs spawned from this spot will envoke a script when touched. # define MSF_SCRIPT_DEATH 0x00000080 // Mobjs spawned from this spot will envoke a script on death. # define MSF_SECRET 0x00000100 // A secret (bonus) item. # define MSF_NOTARGET 0x00000200 // Mobjs spawned from this spot will not target their attacker when hurt. # define MSF_NOTDM 0x00000400 // Can not be spawned in the Deathmatch gameMode. # define MSF_NOTCOOP 0x00000800 // Can not be spawned in the Co-op gameMode. #elif __JHEXEN__ # define MSF_FIGHTER 0x00000020 # define MSF_CLERIC 0x00000040 # define MSF_MAGE 0x00000080 # define MSF_NOTSINGLE 0x00000100 # define MSF_NOTCOOP 0x00000200 # define MSF_NOTDM 0x00000400 // The following are not currently implemented. # define MSF_SHADOW 0x00000800 // (ZDOOM) Thing is 25% translucent. # define MSF_INVISIBLE 0x00001000 // (ZDOOM) Makes the thing invisible. # define MSF_FRIENDLY 0x00002000 // (ZDOOM) Friendly monster. # define MSF_STILL 0x00004000 // (ZDOOM) Thing stands still (only useful for specific Strife monsters or friendlies). #endif // New flags: #define MSF_Z_FLOOR 0x20000000 // Spawn relative to floor height. #define MSF_Z_CEIL 0x40000000 // Spawn relative to ceiling height (minus thing height). #define MSF_Z_RANDOM 0x80000000 // Random point between floor and ceiling. // Unknown flag mask: #if __JDOOM__ #define MASK_UNKNOWN_MSF_FLAGS (0xffffffff \ ^ (MSF_EASY|MSF_MEDIUM|MSF_HARD|MSF_DEAF|MSF_NOTSINGLE|MSF_NOTDM|MSF_NOTCOOP|MSF_FRIENDLY)) #elif __JDOOM64__ #define MASK_UNKNOWN_MSF_FLAGS (0xffffffff \ ^ (MSF_EASY|MSF_MEDIUM|MSF_HARD|MSF_DEAF|MSF_NOTSINGLE|MSF_DONTSPAWNATSTART|MSF_SCRIPT_TOUCH|MSF_SCRIPT_DEATH|MSF_SECRET|MSF_NOTARGET|MSF_NOTDM|MSF_NOTCOOP)) #elif __JHERETIC__ #define MASK_UNKNOWN_MSF_FLAGS (0xffffffff \ ^ (MSF_EASY|MSF_MEDIUM|MSF_HARD|MSF_AMBUSH|MSF_NOTSINGLE|MSF_NOTDM|MSF_NOTCOOP|MSF_FRIENDLY)) #elif __JHEXEN__ #define MASK_UNKNOWN_MSF_FLAGS (0xffffffff \ ^ (MSF_EASY|MTF_NORMAL|MSF_HARD|MSF_AMBUSH|MTF_DORMANT|MSF_FIGHTER|MSF_CLERIC|MSF_MAGE|MSF_GSINGLE|MSF_GCOOP|MSF_GDEATHMATCH|MSF_SHADOW|MSF_INVISIBLE|MSF_FRIENDLY|MSF_STILL)) #endif typedef struct { #if __JHEXEN__ short tid; #endif float pos[3]; angle_t angle; int doomEdNum; int flags; #if __JHEXEN__ byte special; byte arg1; byte arg2; byte arg3; byte arg4; byte arg5; #endif } mapspot_t; typedef struct { int plrNum; uint entryPoint; float pos[3]; angle_t angle; int spawnFlags; // MSF_* flags. } playerstart_t; extern uint numMapSpots; extern mapspot_t* mapSpots; #if __JHERETIC__ extern mapspot_t* maceSpots; extern int maceSpotCount; extern mapspot_t* bossSpots; extern int bossSpotCount; #endif void P_Init(void); mobjtype_t P_DoomEdNumToMobjType(int doomEdNum); void P_SpawnPlayers(void); void P_MoveThingsOutOfWalls(); #if __JHERETIC__ void P_TurnGizmosAwayFromDoors(); #endif #if __JHERETIC__ void P_AddMaceSpot(float x, float y, angle_t angle); void P_AddBossSpot(float x, float y, angle_t angle); #endif void P_CreatePlayerStart(int defaultPlrNum, uint entryPoint, boolean deathmatch, float x, float y, float z, angle_t angle, int spawnFlags); void P_DestroyPlayerStarts(void); uint P_GetNumPlayerStarts(boolean deathmatch); const playerstart_t* P_GetPlayerStart(uint entryPoint, int pnum, boolean deathmatch); void P_DealPlayerStarts(uint entryPoint); void P_SpawnPlayer(int plrNum, playerclass_t pClass, float x, float y, float z, angle_t angle, int spawnFlags, boolean makeCamera, boolean pickupItems); void G_DeathMatchSpawnPlayer(int playernum); void P_RebornPlayer(int plrNum); boolean P_CheckSpot(float x, float y); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/hu_menu.h0000644000175000017500000000723611357170242023302 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_menu.h: Menu widget stuff, episode selection and such. */ #ifndef __COMMON_HUD_MENU__ #define __COMMON_HUD_MENU__ #include "dd_types.h" typedef enum menucommand_e { MCMD_OPEN, // Open the menu. MCMD_CLOSE, // Close the menu. MCMD_CLOSEFAST, // Instantly close the menu. MCMD_NAV_OUT, // Navigate "out" of the current menu (up a level). MCMD_NAV_LEFT, MCMD_NAV_RIGHT, MCMD_NAV_DOWN, MCMD_NAV_UP, MCMD_NAV_PAGEDOWN, MCMD_NAV_PAGEUP, MCMD_SELECT, // Execute whatever action is attaced to the current item. MCMD_DELETE } menucommand_e; // Not to be confused with the size of the description in the save file. #define HU_SAVESTRINGSIZE (24) // Sounds played in the menu. #if __JDOOM__ || __JDOOM64__ #define SFX_MENU_CLOSE (SFX_SWTCHX) #define SFX_MENU_OPEN (SFX_SWTCHN) #define SFX_MENU_CANCEL (SFX_SWTCHN) #define SFX_MENU_NAV_UP (SFX_PSTOP) #define SFX_MENU_NAV_RIGHT (SFX_PSTOP) #define SFX_MENU_ACCEPT (SFX_PISTOL) #define SFX_MENU_CYCLE (SFX_PISTOL) // Cycle available options. #define SFX_MENU_SLIDER_MOVE (SFX_STNMOV) #define SFX_QUICKSAVE_PROMPT (SFX_SWTCHN) #define SFX_QUICKLOAD_PROMPT (SFX_SWTCHN) #elif __JHERETIC__ #define SFX_MENU_CLOSE (SFX_DORCLS) #define SFX_MENU_OPEN (SFX_SWITCH) #define SFX_MENU_CANCEL (SFX_SWITCH) #define SFX_MENU_NAV_UP (SFX_SWITCH) #define SFX_MENU_NAV_RIGHT (SFX_SWITCH) #define SFX_MENU_ACCEPT (SFX_DORCLS) #define SFX_MENU_CYCLE (SFX_DORCLS) // Cycle available options. #define SFX_MENU_SLIDER_MOVE (SFX_STNMOV) #define SFX_QUICKSAVE_PROMPT (SFX_CHAT) #define SFX_QUICKLOAD_PROMPT (SFX_CHAT) #elif __JHEXEN__ #define SFX_MENU_CLOSE (SFX_DOOR_LIGHT_CLOSE) #define SFX_MENU_OPEN (SFX_DOOR_LIGHT_CLOSE) #define SFX_MENU_CANCEL (SFX_PICKUP_KEY) #define SFX_MENU_NAV_UP (SFX_FIGHTER_HAMMER_HITWALL) #define SFX_MENU_NAV_RIGHT (SFX_FIGHTER_HAMMER_HITWALL) #define SFX_MENU_ACCEPT (SFX_PLATFORM_STOP) #define SFX_MENU_CYCLE (SFX_CHAT) // Cycle available options. #define SFX_MENU_SLIDER_MOVE (SFX_PICKUP_KEY) #define SFX_QUICKSAVE_PROMPT (SFX_CHAT) #define SFX_QUICKLOAD_PROMPT (SFX_CHAT) #endif void Hu_MenuRegister(void); void Hu_MenuInit(void); void Hu_MenuTicker(timespan_t time); int Hu_MenuResponder(event_t* ev); void Hu_MenuDrawer(void); void Hu_MenuCommand(menucommand_e cmd); boolean Hu_MenuIsActive(void); void Hu_MenuSetAlpha(float alpha); float Hu_MenuAlpha(void); void Hu_MenuPageString(char* page, const menu_t* menu); boolean M_EditResponder(event_t* ev); DEFCC(CCmdMenuAction); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_iterlist.h0000644000175000017500000000341611357170242024014 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_iterlist.c : Object lists. * The lists can be traversed through iteration but otherwise act like a * LIFO stack. Used for things like spechits, linespecials etc. */ #ifndef __COMMON_ITERLIST_H__ #define __COMMON_ITERLIST_H__ #include "dd_api.h" typedef struct iterlist_s { void **list; int max; int count; int rover; // used during iteration boolean forward; // if true iteration moves forward instead. } iterlist_t; iterlist_t *P_CreateIterList(void); void P_DestroyIterList(iterlist_t *list); int P_AddObjectToIterList(iterlist_t *list, void *obj); void *P_PopIterList(iterlist_t *list); void *P_IterListIterator(iterlist_t *list); void P_IterListResetIterator(iterlist_t *list, boolean forward); void P_EmptyIterList(iterlist_t *list); int P_IterListSize(iterlist_t *list); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/g_defs.h0000644000175000017500000000221311357170242023057 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 1999-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_defs.h: */ #ifndef __GAME_DEFINITIONS_H__ #define __GAME_DEFINITIONS_H__ int GetDefInt(char* def, int* returnVal); void GetDefState(char* def, int* val); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_door.h0000644000175000017500000000511411357170242023115 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_door.h: Common playsim routines relating to doors. */ #ifndef __COMMON_THINKER_DOOR_H__ #define __COMMON_THINKER_DOOR_H__ typedef enum { DS_DOWN = -1, DS_WAIT, DS_UP, DS_INITIALWAIT } doorstate_e; typedef enum { DT_NORMAL, DT_CLOSE30THENOPEN, DT_CLOSE, DT_OPEN, DT_RAISEIN5MINS, #if __JDOOM__ || __JDOOM64__ DT_BLAZERAISE, #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ DT_BLAZEOPEN, #endif #if __JDOOM64__ DT_INSTANTOPEN, //jd64 kaiser DT_INSTANTCLOSE, //jd64 kaiser DT_INSTANTRAISE, //jd64 kaiser #endif #if __JDOOM__ || __JDOOM64__ DT_BLAZECLOSE, #endif NUMDOORTYPES } doortype_e; typedef struct { thinker_t thinker; doortype_e type; sector_t* sector; float topHeight; float speed; doorstate_e state; int topWait; // Tics to wait at the top. int topCountDown; } door_t; #define DOORSPEED (2) #define DOORWAIT (150) void T_Door(door_t* door); boolean EV_VerticalDoor(linedef_t* li, mobj_t* mo); #if __JHEXEN__ int EV_DoDoor(linedef_t* li, byte* args, doortype_e type); #else int EV_DoDoor(linedef_t* li, doortype_e type); #endif #if __JDOOM__ || __JDOOM64__ int EV_DoLockedDoor(linedef_t* li, doortype_e type, mobj_t* mo); #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ void P_SpawnDoorCloseIn30(sector_t* sec); void P_SpawnDoorRaiseIn5Mins(sector_t* sec); #endif #if __JDOOM64__ int EV_AnimateDoor(linedef_t* li, mobj_t* mo); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/d_netsv.h0000644000175000017500000000630111357170242023274 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef __D_NETSV_H__ #define __D_NETSV_H__ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif extern char cyclingMaps, mapCycleNoExit; extern int netSvAllowCheats; extern char *mapCycle; extern char gameConfigString[]; void P_Telefrag(mobj_t *thing); void NetSv_NewPlayerEnters(int plrnumber); void *NetSv_ReadCommands(byte *msg, uint size); void NetSv_SendGameState(int flags, int to); void NetSv_SendMessage(int plrNum, char *msg); void NetSv_SendYellowMessage(int plrNum, char *msg); void NetSv_SendPlayerState(int srcPlrNum, int destPlrNum, int flags, boolean reliable); void NetSv_SendPlayerState2(int srcPlrNum, int destPlrNum, int flags, boolean reliable); void NetSv_PSpriteChange(int plrNum, int state); void NetSv_Sound(mobj_t *origin, int sound_id, int toPlr); // toPlr=0: broadcast. void NetSv_SoundAtVolume(mobj_t *origin, int sound_id, int volume, int toPlr); void NetSv_Intermission(int flags, int state, int time); void NetSv_Finale(int flags, const char* script, const boolean* conds, byte numConds); void NetSv_SendPlayerInfo(int whose, int to_whom); void NetSv_ChangePlayerInfo(int from, byte *data); void NetSv_Ticker(void); void NetSv_SaveGame(unsigned int game_id); void NetSv_LoadGame(unsigned int game_id); void NetSv_LoadReply(int plnum, int console); void NetSv_FragsForAll(player_t *player); void NetSv_KillMessage(player_t *killer, player_t *fragged, boolean stomping); void NetSv_UpdateGameConfig(void); void NetSv_Paused(boolean isPaused); void NetSv_DoCheat(int player, const char *data); void NetSv_DoAction(int player, const char *data); void NetSv_SendJumpPower(int target, float power); DEFCC(CCmdMapCycle); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/d_net.h0000644000175000017500000001504511357170242022730 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_net.h: */ #ifndef __GAME_NETWORK_DEF_H__ #define __GAME_NETWORK_DEF_H__ #include "dd_share.h" #define NETBUFFER_MAXMESSAGE 255 #ifdef __JHEXEN__ #define PLR_COLOR(pl, x) (((unsigned)(x)) > 7? (pl) % 8 : (x)) #elif __JSTRIFE__ #define PLR_COLOR(pl, x) (((unsigned)(x)) > 7? (pl) % 8 : (x)) #else #define PLR_COLOR(pl, x) (((unsigned)(x)) > 3? (pl) % 4 : (x)) #endif // This playerstate is used to signal that a player should be removed // from the world (he has quit netgame). #define PST_GONE 0x1000 // Game packet types. (DON'T CHANGE THESE) enum { GPT_GAME_STATE = DDPT_FIRST_GAME_EVENT, GPT_WEAPON_FIRE, GPT_PLANE_MOVE, GPT_MESSAGE, // Non-chat messages. GPT_CONSOLEPLAYER_STATE, GPT_PLAYER_STATE, GPT_PSPRITE_STATE, GPT_SOUND, GPT_SECTOR_SOUND, GPT_FLOOR_MOVE_SOUND, GPT_CEILING_MOVE_SOUND, GPT_INTERMISSION, GPT_FINALE, GPT_PLAYER_INFO, GPT_SAVE, GPT_LOAD, GPT_CLASS, // jHexen: player class notification. GPT_CONSOLEPLAYER_STATE2, GPT_PLAYER_STATE2, GPT_YELLOW_MESSAGE, // jHexen: yellow message. GPT_PAUSE, GPT_FINALE2, GPT_CHEAT_REQUEST, GPT_JUMP_POWER, // Jump power (0 = no jumping) GPT_ACTION_REQUEST, }; #if 0 // This packet is sent by servers to clients when the game state // changes. typedef struct { byte gameMode; byte flags; byte episode, map; byte deathmatch:2; byte monsters:1; byte respawn:1; byte jumping:1; #if __JHEXEN__ byte randomclass:1; #endif byte skill:3; short gravity; // signed fixed-8.8 #if __JHEXEN__ float damagemod; // netMobDamageModifier (UNUSED) float healthmod; // netMobHealthModifier (UNUSED) #elif __JSTRIFE__ float damagemod; // netMobDamageModifier (UNUSED) float healthmod; // netMobHealthModifier (UNUSED) #endif } packet_gamestate_t; #endif // Player action requests. enum { GPA_FIRE = 1, GPA_USE = 2 }; // Game state flags. #define GSF_CHANGE_MAP 0x01 // Map has changed. #define GSF_CAMERA_INIT 0x02 // After gamestate follows camera init. #define GSF_DEMO 0x04 // Only valid during demo playback. // Player state update flags. #define PSF_STATE 0x0001 // Dead or alive / armor type. #define PSF_ARMOR_TYPE 0x0001 // Upper four bits of the 1st byte. #define PSF_HEALTH 0x0002 #define PSF_ARMOR_POINTS 0x0004 #define PSF_POWERS 0x0010 #define PSF_KEYS 0x0020 #define PSF_FRAGS 0x0040 #define PSF_VIEW_HEIGHT 0x0080 #define PSF_OWNED_WEAPONS 0x0100 #define PSF_AMMO 0x0200 #define PSF_MAX_AMMO 0x0400 #define PSF_COUNTERS 0x0800 // Kill, item and secret counts. #define PSF_PENDING_WEAPON 0x1000 #define PSF_READY_WEAPON 0x2000 // Player state update II flags. #define PSF2_OWNED_WEAPONS 0x00000001 #define PSF2_STATE 0x00000002 // Includes cheatflags. #if __JDOOM__ || __JDOOM64__ #define PSF_REBORN 0x37f7 #endif #ifdef __JHERETIC__ #define PSF_INVENTORY 0x0008 #define PSF_MORPH_TIME 0x4000 #define PSF_REBORN 0x77ff #endif #ifdef __JHEXEN__ #define PSF_ARMOR PSF_ARMOR_POINTS // For convenience. #define PSF_WEAPONS (PSF_PENDING_WEAPON | PSF_READY_WEAPON) #define PSF_INVENTORY 0x0008 #define PSF_MORPH_TIME 0x4000 #define PSF_LOCAL_QUAKE 0x8000 #define PSF_REBORN 0xf7ff #endif #ifdef __JDOOM64__ #define PSF_INVENTORY 0x0008 #endif // Intermission flags. #define IMF_BEGIN 0x01 #define IMF_END 0x02 #define IMF_STATE 0x04 #define IMF_TIME 0x08 // Finale flags. #define FINF_BEGIN 0x01 #define FINF_END 0x02 #define FINF_SCRIPT 0x04 // Script included. #define FINF_AFTER 0x08 // Otherwise before. #define FINF_SKIP 0x10 #define FINF_OVERLAY 0x20 // Otherwise before (or after). // Ticcmd flags. #define CMDF_FORWARDMOVE 0x01 #define CMDF_SIDEMOVE 0x02 #define CMDF_ANGLE 0x04 #define CMDF_LOOKDIR 0x08 #define CMDF_BUTTONS 0x10 #define CMDF_LOOKFLY 0x20 #define CMDF_ARTI 0x40 #define CMDF_CHANGE_WEAPON 0x80 #define CMDF_BTN_ATTACK 0x01 #define CMDF_BTN_USE 0x02 #define CMDF_BTN_JUMP 0x04 #define CMDF_BTN_PAUSE 0x08 #define CMDF_BTN_SUICIDE 0x10 // Now ignored in ticcmds // Networking. int D_NetServerOpen(int before); int D_NetServerClose(int before); int D_NetServerStarted(int before); int D_NetConnect(int before); int D_NetDisconnect(int before); long int D_NetPlayerEvent(int plrNumber, int peType, void *data); boolean D_NetDamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage); int D_NetWorldEvent(int type, int tic, void *data); void D_HandlePacket(int fromplayer, int type, void *data, size_t length); void* D_NetWriteCommands(int numCommands, void* data); void* D_NetReadCommands(size_t pktLength, void* data); void D_NetConsoleRegistration(void); void D_NetMessage(int player, const char *msg); void D_NetMessageNoSound(int player, const char *msg); // Console commands. extern ccmd_t netCCmds[]; extern float netJumpPower; #include "d_netsv.h" #include "d_netcl.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/hu_stuff.h0000644000175000017500000001332611357170242023462 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_stuff.h: */ #ifndef __COMMON_HU_STUFF_H__ #define __COMMON_HU_STUFF_H__ #include "doomsday.h" #include "r_common.h" typedef enum border_e { BORDERUP = 1, BORDERDOWN } border_t; enum { ALIGN_LEFT = 0, ALIGN_CENTER, ALIGN_RIGHT }; // The fonts. typedef enum { GF_FIRST = 0, GF_FONTA = GF_FIRST, GF_FONTB, NUM_GAME_FONTS } gamefontid_t; typedef struct gamefont_s { struct gamefont_char_s { char lumpname[9]; dpatch_t patch; } chars[256]; } gamefont_t; extern dpatch_t huMinus; #if __JHERETIC__ || __JHEXEN__ extern dpatch_t dpSmallNumbers[10]; #endif // Name graphics of each map. extern dpatch_t* mapNamePatches; // Name graphics of each skill mode. #if __JDOOM__ || __JDOOM64__ extern dpatch_t skillModeNames[NUM_SKILL_MODES]; extern dpatch_t m_pause; // Paused graphic. #endif // Name graphics of each episode. #if __JDOOM__ extern dpatch_t* episodeNamePatches; #endif extern const char shiftXForm[]; extern int typeInTime; #if __JDOOM__ // Plutonia and TNT map names. extern char *mapNamesPlut[32], *mapNamesTNT[32]; #endif #if __JHERETIC__ || __JHEXEN__ extern dpatch_t dpInvItemBox; extern dpatch_t dpInvSelectBox; extern dpatch_t dpInvPageLeft[2]; extern dpatch_t dpInvPageRight[2]; #endif void Hu_LoadData(void); void Hu_Drawer(void); void Hu_Ticker(void); void Hu_FogEffectTicker(timespan_t time); void Hu_FogEffectSetAlphaTarget(float alpha); // Implements patch replacement. void WI_DrawPatch(int x, int y, float r, float g, float b, float a, const dpatch_t* patch, const char* altstring, boolean builtin, int halign); void WI_DrawParamText(int x, int y, const char* string, gamefontid_t font, float defRed, float defGreen, float defBlue, float defAlpha, boolean defCase, boolean defTypeIn, int halign); void M_WriteText(int x, int y, const char *string); void M_WriteText2(int x, int y, const char *string, gamefontid_t font, float red, float green, float blue, float alpha); void M_WriteText3(int x, int y, const char *string, gamefontid_t font, float red, float green, float blue, float alpha, boolean flagTypeIn, boolean flagShadow, int initialCount); void HUlib_drawTextLine2(int x, int y, const char* string, size_t len, gamefontid_t font, boolean drawcursor); void M_DrawChar(int x, int y, unsigned char ch, gamefontid_t font); #if __JHERETIC__ || __JHEXEN__ void Hu_DrawSmallNum(int val, int numDigits, int x, int y, float alpha); #endif #if __JHERETIC__ void HU_DrawBNumber(signed int val, int x, int y, float red, float green, float blue, float alpha); void IN_DrawNumber(int val, int x, int y, int digits, float r, float g, float b, float a); void IN_DrawShadowChar(int x, int y, unsigned char ch, gamefontid_t font); #endif #if __JHEXEN__ void DrBNumber(int val, int x, int y, float red, float green, float blue, float alpha); #endif int M_DrawText(int x, int y, boolean direct, char *string); void M_DrawTitle(char *text, int y); int M_StringWidth(const char* string, gamefontid_t font); int M_CharWidth(unsigned char ch, gamefontid_t font); int M_CharHeight(unsigned char ch, gamefontid_t font); int M_StringHeight(const char* string, gamefontid_t font); void M_DrawBackgroundBox(float x, float y, float w, float h, float red, float green, float blue, float alpha, boolean background, int border); #if __JHERETIC__ || __JHEXEN__ void M_DrawSlider(int x, int y, int width, int slot, float alpha); #else void M_DrawSlider(int x, int y, int width, int height, int slot, float alpha); #endif void Draw_BeginZoom(float s, float originX, float originY); void Draw_EndZoom(void); void HU_Register(void); void HU_Start(int player); void Hu_UnloadData(void); void HU_Drawer(int player); char HU_dequeueChatChar(void); void HU_Erase(void); void HU_DrawMapCounters(void); void Hu_DrawFogEffect(int effectID, DGLuint tex, float texOffset[2], float texAngle, float alpha, float arg1); void HU_ScoreBoardUnHide(int player); void HU_DrawScoreBoard(int player); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/m_defs.h0000644000175000017500000000506511357170242023075 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_defs.h: Common menu defines and types. */ #ifndef __MENU_COMMON_DEFS_H_ #define __MENU_COMMON_DEFS_H_ #include "r_common.h" typedef enum { ITT_EMPTY, ITT_EFUNC, ITT_LRFUNC, ITT_SETMENU } menuitemtype_t; // Menu item flags #define MIF_NOTALTTXT 0x01 // Don't use alt text instead of lump (M_NMARE) typedef struct { menuitemtype_t type; int flags; const char* text; void (*func) (int option, void *data); int option; dpatch_t* patch; void* data; } menuitem_t; // Menu flags #define MNF_NOHOTKEYS 0x00000001 // Hotkeys are disabled. #define MNF_NOSCALE 0x00000002 // Menu wont be scaled (e.g. readthis). #define MNF_DELETEFUNC 0x00000004 // MCMD_DELETE causes a call to item's func typedef struct unscaledmenustate_s { int numVisItems; int y; } unscaledmenustate_t; typedef struct { int flags; int x; int y; void (*drawFunc) (void); int itemCount; const menuitem_t* items; int lastOn; int prevMenu; // menutype_t gamefontid_t font; // Font for menu items. float* color; char* background; // Background lump name for this menu (if any). boolean backgroundIsRaw; int itemHeight; // For multipage menus. int firstItem, numVisItems; // Scalable menus. unscaledmenustate_t unscaled; } menu_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/hu_inventory.h0000644000175000017500000000354111357170242024366 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_inventory.h: Heads-up display(s) for the player inventory. */ #ifndef __COMMON_HUD_INVENTORY__ #define __COMMON_HUD_INVENTORY__ #if __JHERETIC__ || __JHEXEN__ void Hu_InventoryRegister(void); void Hu_InventoryInit(void); void Hu_InventoryTicker(void); void Hu_InventoryOpen(int player, boolean show); boolean Hu_InventoryIsOpen(int player); boolean Hu_InventorySelect(int player, inventoryitemtype_t type); boolean Hu_InventoryMove(int player, int dir, boolean canWrap, boolean silent); void Hu_InventoryDraw(int player, int x, int y, float alpha, float textAlpha, float iconAlpha); void Hu_InventoryDraw2(int player, int x, int y, float alpha); /// \todo refactor this away. void Hu_InventoryMarkDirty(int player); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_ceiling.h0000644000175000017500000000454611357170242023574 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_ceiling.h: Common playsim routines relating to ceilings. */ #ifndef __COMMON_THINKER_CEILING_H__ #define __COMMON_THINKER_CEILING_H__ typedef enum { CS_DOWN, CS_UP } ceilingstate_e; typedef enum { CT_LOWERTOFLOOR, CT_RAISETOHIGHEST, CT_LOWERANDCRUSH, CT_CRUSHANDRAISE, #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ CT_CRUSHANDRAISEFAST, #endif #if __JDOOM__ || __JDOOM64__ CT_SILENTCRUSHANDRAISE, #endif #if __JDOOM64__ CT_CUSTOM, #endif #if __JHEXEN__ CT_LOWERBYVALUE, CT_RAISEBYVALUE, CT_CRUSHRAISEANDSTAY, CT_MOVETOVALUEMUL8, #endif NUMCEILINGTYPES } ceilingtype_e; typedef struct { thinker_t thinker; ceilingtype_e type; sector_t* sector; float bottomHeight; float topHeight; float speed; boolean crush; ceilingstate_e state; ceilingstate_e oldState; int tag; // id. } ceiling_t; #define CEILSPEED (1) #define CEILWAIT (150) void T_MoveCeiling(ceiling_t* c); #if __JHEXEN__ int EV_DoCeiling(linedef_t* line, byte* args, ceilingtype_e type); #else int EV_DoCeiling(linedef_t* li, ceilingtype_e type); #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ int P_CeilingActivate(short tag); #endif int P_CeilingDeactivate(short tag); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/r_common.h0000644000175000017500000000422311357170242023444 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_common.h : Common routines for refresh. */ #ifndef __GAME_COMMON_REFRESH_H__ #define __GAME_COMMON_REFRESH_H__ // A combination of patch data and its lump number. typedef struct dpatch_s { int width, height; int leftOffset, topOffset; lumpnum_t lump; } dpatch_t; // Translate between fixed screen dimensions to actual, current. #define FIXXTOSCREENX(x) (scrwidth * ((x) / (float) SCREENWIDTH)) #define FIXYTOSCREENY(y) (scrheight * ((y) / (float) SCREENHEIGHT)) #define SCREENXTOFIXX(x) ((float) SCREENWIDTH * ((x) / scrwidth)) #define SCREENYTOFIXY(y) ((float) SCREENHEIGHT * ((y) / scrheight)) #define LERP(start, end, pos) (end * pos + start * (1 - pos)) void R_SetViewWindowTarget(int x, int y, int w, int h); void R_ViewWindowTicker(void); void R_GetViewWindow(float* x, float* y, float* w, float* h); boolean R_IsFullScreenViewWindow(void); boolean R_MapObscures(int playerid, int x, int y, int w, int h); void R_PrecachePSprites(void); void R_CachePatch(dpatch_t* dp, const char* name); void R_GetGammaMessageStrings(void); void R_CycleGammaLevel(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/hu_msg.h0000644000175000017500000000375011357170242023121 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hu_msg.h: Important state change messages. */ #ifndef __HUD_MESSAGE_H__ #define __HUD_MESSAGE_H__ #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif typedef enum { MSG_CANCEL = -1, MSG_NO, MSG_YES, NUM_MESSAGE_RESPONSES } msgresponse_t; typedef int (C_DECL *msgfunc_t) (msgresponse_t response, void* context); typedef enum { MSG_ANYKEY, MSG_YESNO, NUM_MESSAGE_TYPES } msgtype_t; void Hu_MsgRegister(void); void Hu_MsgInit(void); void Hu_MsgShutdown(void); void Hu_MsgTicker(timespan_t time); boolean Hu_MsgResponder(event_t* ev); void Hu_MsgDrawer(void); boolean Hu_IsMessageActive(void); void Hu_MsgStart(msgtype_t type, const char* msg, msgfunc_t callback, void* context); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_mapspec.h0000644000175000017500000000551711357170242023611 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mapspec.c: Line Tag handling. Line and Sector groups. * * Specialized iteration routines, respective utility functions... */ #ifndef __COMMON_MAP_SPEC_H__ #define __COMMON_MAP_SPEC_H__ #include "p_iterlist.h" extern iterlist_t *spechit; // for crossed line specials. extern iterlist_t *linespecials; // for surfaces that tick eg wall scrollers. void P_DestroyLineTagLists(void); iterlist_t *P_GetLineIterListForTag(int tag, boolean createNewList); void P_DestroySectorTagLists(void); iterlist_t *P_GetSectorIterListForTag(int tag, boolean createNewList); sector_t* P_GetNextSector(linedef_t *line, sector_t *sec); sector_t* P_FindSectorSurroundingLowestFloor(sector_t *sec, float max, float *val); sector_t* P_FindSectorSurroundingHighestFloor(sector_t *sec, float min, float *val); sector_t* P_FindSectorSurroundingLowestCeiling(sector_t *sec, float max, float *val); sector_t* P_FindSectorSurroundingHighestCeiling(sector_t *sec, float min, float *val); sector_t* P_FindSectorSurroundingLowestLight(sector_t *sector, float *val); sector_t* P_FindSectorSurroundingHighestLight(sector_t *sector, float *val); sector_t* P_FindSectorSurroundingNextHighestFloor(sector_t *sec, float baseHeight, float *val); sector_t* P_FindSectorSurroundingNextLowestFloor(sector_t *sec, float baseHeight, float *val); sector_t* P_FindSectorSurroundingNextHighestCeiling(sector_t *sec, float baseHeight, float *val); sector_t* P_FindSectorSurroundingNextLowestCeiling(sector_t *sec, float baseHeight, float *val); sector_t* P_FindSectorSurroundingNextLowestLight(sector_t *sector, float baseLight, float *val); sector_t* P_FindSectorSurroundingNextHighestLight(sector_t *sector, float baseLight, float *val); void P_RecursiveSound(struct mobj_s *soundTarget, sector_t *sec, int soundBlocks); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/rend_automap.h0000644000175000017500000000262311357170242024313 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * rend_automap.h: */ #ifndef __COMMON_RENDER_AUTOMAP_H__ #define __COMMON_RENDER_AUTOMAP_H__ #include "p_automap.h" extern boolean freezeMapRLs; void Rend_AutomapInit(void); void Rend_AutomapLoadData(void); void Rend_AutomapUnloadData(void); void Rend_AutomapInitForMap(void); void Rend_Automap(int player, const automap_t* map); void Rend_AutomapRebuild(int player); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/st_lib.h0000644000175000017500000000550511357170242023113 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_lib.h: HUD, Status Widgets. */ #ifndef __COMMON_STLIB__ #define __COMMON_STLIB__ #include "hu_stuff.h" /** * Number widget. */ typedef struct { int x, y; // Upper right-hand corner of the number (right-justified). int maxDigits; // Max # of digits in number. float alpha; int* num; // Pointer to current value. dpatch_t* p; // List of patches for 0-9. } st_number_t; void STlib_InitNum(st_number_t* n, int x, int y, dpatch_t* pl, int* num, int maxDigits, float alpha); void STlib_DrawNum(st_number_t* n, float alpha); /** * Percent widget * "child" of number widget, or, more precisely, contains a number widget. */ typedef struct { st_number_t n; // Number. dpatch_t* p; // Percent sign graphic. } st_percent_t; void STlib_InitPercent(st_percent_t* p, int x, int y, dpatch_t* pl, int* num, dpatch_t* percent, float alpha); void STlib_DrawPercent(st_percent_t* per, float alpha); /** * Icon widget. */ typedef struct { int x, y; // Center-justified location of icon. float alpha; dpatch_t* p; // Icon. } st_icon_t; void STlib_InitIcon(st_icon_t* b, int x, int y, dpatch_t* i, float alpha); void STlib_DrawIcon(st_icon_t* bi, float alpha); /** * Multi Icon widget. */ typedef struct { int x, y; // Center-justified location of icons. float alpha; dpatch_t* p; // List of icons. } st_multiicon_t; void STlib_InitMultiIcon(st_multiicon_t* mi, int x, int y, dpatch_t* il, float alpha); void STlib_DrawMultiIcon(st_multiicon_t* mi, int icon, float alpha); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_user.h0000644000175000017500000000624511357170242023136 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_user.c : Player related stuff. * * Bobbing POV/weapon, movement, pending weapon... * Compiles for jDoom, jHeretic and jHexen. */ #ifndef __P_USER_H__ #define __P_USER_H__ #include "dd_types.h" #define PLAYER_REBORN_TICS (1*TICSPERSEC) extern boolean onground; extern int maxHealth; #if __JDOOM__ || __JDOOM64__ extern int healthLimit; extern int godModeHealth; extern int soulSphereLimit; extern int megaSphereHealth; extern int soulSphereHealth; extern int armorPoints[4]; extern int armorClass[4]; #endif extern classinfo_t classInfo[]; void P_Thrust(player_t *player, angle_t angle, float move); boolean P_IsPlayerOnGround(player_t *player); void P_CheckPlayerJump(player_t *player); void P_MovePlayer(player_t *player); void P_PlayerReborn(player_t *player); void P_ClientSideThink(void); void P_DeathThink(player_t *player); void P_PlayerThink(player_t *player, timespan_t ticLength); void P_PlayerThinkState(player_t *player); void P_PlayerThinkCheat(player_t *player); void P_PlayerThinkAttackLunge(player_t *player); boolean P_PlayerThinkDeath(player_t *player); void P_PlayerThinkMorph(player_t *player); void P_PlayerThinkMove(player_t *player); void P_PlayerThinkFly(player_t *player); void P_PlayerThinkJump(player_t *player); void P_PlayerThinkView(player_t *player); void P_PlayerThinkSpecial(player_t *player); void P_PlayerThinkSounds(player_t *player); #if __JHERETIC__ || __JHEXEN__ void P_PlayerThinkInventory(player_t* player); #endif void P_PlayerThinkItems(player_t *player); void P_PlayerThinkWeapons(player_t *player); void P_PlayerThinkUse(player_t *player); void P_PlayerThinkPsprites(player_t *player); void P_PlayerThinkPowers(player_t *player); void P_PlayerThinkLookAround(player_t *player, timespan_t ticLength); void P_PlayerThinkUpdateControls(player_t* player); #if __JHERETIC__ || __JHEXEN__ void P_MorphThink(player_t *player); boolean P_UndoPlayerMorph(player_t *player); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/g_common.h0000644000175000017500000000417511357170242023437 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_common.h: */ #ifndef __COMMON_GAME_H__ #define __COMMON_GAME_H__ #include "dd_share.h" #include "g_controls.h" #if __JDOOM__ # include "jdoom.h" #elif __JDOOM64__ # include "jdoom64.h" #elif __JHERETIC__ # include "jheretic.h" #elif __JHEXEN__ # include "jhexen.h" #elif __JSTRIFE__ # include "jstrife.h" #endif #define OBSOLETE CVF_HIDE|CVF_NO_ARCHIVE enum { JOYAXIS_NONE, JOYAXIS_MOVE, JOYAXIS_TURN, JOYAXIS_STRAFE, JOYAXIS_LOOK }; extern boolean singledemo; void G_Register(void); void G_PreInit(void); void G_PostInit(void); void G_StartTitle(void); gamestate_t G_GetGameState(void); void G_ChangeGameState(gamestate_t state); gameaction_t G_GetGameAction(void); void G_SetGameAction(gameaction_t action); int P_CameraXYMovement(mobj_t* mo); int P_CameraZMovement(mobj_t* mo); void P_Thrust3D(struct player_s* player, angle_t angle, float lookdir, int forwardmove, int sidemove); DEFCC( CCmdMakeLocal ); DEFCC( CCmdSetCamera ); DEFCC( CCmdSetViewLock ); DEFCC( CCmdLocalMessage ); DEFCC( CCmdExitLevel ); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_floor.h0000644000175000017500000000723711357170242023303 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_floor.h: Common playsim routines relating to moving floors. */ #ifndef __COMMON_THINKER_FLOOR_H__ #define __COMMON_THINKER_FLOOR_H__ typedef enum { FS_DOWN = -1, // Moving down. FS_WAIT, // Currently unused. FS_UP // Moving up. } floorstate_e; typedef enum { FT_LOWER, // Lower floor to highest surrounding floor. FT_LOWERTOLOWEST, // Lower floor to lowest surrounding floor. #if __JHEXEN__ FT_LOWERBYVALUE, #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ FT_LOWERTURBO, // Lower floor to highest surrounding floor VERY FAST. #endif #if __JDOOM64__ FT_TOHIGHESTPLUS8, // jd64 FT_TOHIGHESTPLUSBITMIP, // jd64 FT_CUSTOMCHANGESEC, // jd64 #endif FT_RAISEFLOOR, // Raise floor to lowest surrounding CEILING. FT_RAISEFLOORTONEAREST, // Raise floor to next highest surrounding floor. #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ FT_RAISETOTEXTURE, // Raise floor to shortest height texture around it. FT_LOWERANDCHANGE, // Lower floor to lowest surrounding floor and change floorpic. FT_RAISE24, FT_RAISE24ANDCHANGE, #endif #if __JHEXEN__ FT_RAISEFLOORBYVALUE, #endif FT_RAISEFLOORCRUSH, #if __JDOOM__ || __JDOOM64__ FT_RAISEFLOORTURBO, // Raise to next highest floor, turbo-speed. #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ FT_RAISEDONUT, #endif #if __JDOOM__ || __JDOOM64__ FT_RAISE512, #endif #if __JDOOM64__ FT_RAISE32, // jd64 #endif #if __JHERETIC__ || __JHEXEN__ FT_RAISEBUILDSTEP, #endif #if __JHEXEN__ FT_RAISEBYVALUEMUL8, FT_LOWERBYVALUEMUL8, FT_LOWERMUL8INSTANT, FT_RAISEMUL8INSTANT, FT_TOVALUEMUL8, #endif NUMFLOORTYPES } floortype_e; typedef struct { thinker_t thinker; floortype_e type; boolean crush; sector_t* sector; floorstate_e state; int newSpecial; material_t* material; float floorDestHeight; float speed; #if __JHEXEN__ int delayCount; int delayTotal; float stairsDelayHeight; float stairsDelayHeightDelta; float resetHeight; short resetDelay; short resetDelayCount; // byte textureChange; #endif } floor_t; #define FLOORSPEED (1) void T_MoveFloor(floor_t* floor); #if __JHEXEN__ int EV_DoFloor(linedef_t* li, byte* args, floortype_e type); #else int EV_DoFloor(linedef_t* li, floortype_e type); #endif #if __JHEXEN__ int EV_DoFloorAndCeiling(linedef_t* li, byte* args, int ftype, int ctype); #elif __JDOOM64__ int EV_DoFloorAndCeiling(linedef_t* li, int ftype, int ctype); #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/m_argv.h0000644000175000017500000000201311357170242023101 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_argv.h: */ #ifndef __M_ARGV__ #define __M_ARGV__ #define myargc Argc() #define M_CheckParm gi.CheckParm #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/am_map.h0000644000175000017500000003016111357170242023065 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * am_map.h : Automap, automap menu and related code. */ #ifndef __COMMON_AUTOMAP_MANAGER__ #define __COMMON_AUTOMAP_MANAGER__ #define AUTOMAP_OPEN_SECONDS (.3f) // Num of seconds to open/close the map. #if __JDOOM__ || __JDOOM64__ // For use if I do walls with outsides/insides #define BLUES (256-4*16+8) #define YELLOWRANGE 1 #define BLACK 0 #define REDS (256-5*16) #define REDRANGE 16 #define BLUERANGE 8 #define GREENS (7*16) #define GREENRANGE 16 #define GRAYS (6*16) #define GRAYSRANGE 16 #define BROWNS (4*16) #define BROWNRANGE 16 #define YELLOWS (256-32+7) #define WHITE (256-47) #define YOURCOLORS WHITE #define YOURRANGE 0 #define WALLCOLORS REDS #define WALLRANGE REDRANGE #define TSWALLCOLORS GRAYS #define TSWALLRANGE GRAYSRANGE #define CDWALLCOLORS YELLOWS #define CDWALLRANGE YELLOWRANGE #define THINGCOLORS GREENS #define THINGRANGE GREENRANGE #define SECRETWALLCOLORS WALLCOLORS #define SECRETWALLRANGE WALLRANGE #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) #define GRIDRANGE 0 #define XHAIRCOLORS GRAYS #define FDWALLCOLORS BROWNS #define FDWALLRANGE BROWNRANGE #define BORDEROFFSET 3 // Automap colors #define BACKGROUND BLACK // Keys for Baby Mode #define KEY1_COLOR 197 // Blue Key #define KEY2_COLOR (256-5*16) // Red Key #define KEY3_COLOR (256-32+7) // Yellow Key #define KEY4_COLOR (256-32+7) // Yellow Skull #define KEY5_COLOR (256-5*16) // Red Skull #define KEY6_COLOR 197 // Blue Skull #define BORDERGRAPHIC "brdr_b" #define MARKERPATCHES (sprintf(namebuf, "AMMNUM%d", i)) // DJS - Patches used for marking the automap, a bit of a hack I suppose #endif #ifdef __JHERETIC__ // For use if I do walls with outsides/insides #define REDS 12*8 #define REDRANGE 1 //16 #define BLUES (256-4*16+8) #define BLUERANGE 1 //8 #define GREENS (33*8) #define GREENRANGE 1 //16 #define GRAYS (5*8) #define GRAYSRANGE 1 //16 #define BROWNS (14*8) #define BROWNRANGE 1 //16 #define YELLOWS 10*8 #define YELLOWRANGE 1 #define BLACK 0 #define WHITE 4*8 #define PARCH 13*8-1 #define WALLCOLORS REDS #define FDWALLCOLORS BROWNS #define CDWALLCOLORS YELLOWS #define YOURCOLORS WHITE #define YOURRANGE 0 #define WALLRANGE REDRANGE #define TSWALLCOLORS GRAYS #define TSWALLRANGE GRAYSRANGE #define FDWALLRANGE BROWNRANGE #define CDWALLRANGE YELLOWRANGE #define THINGCOLORS GREENS #define THINGRANGE GREENRANGE #define SECRETWALLCOLORS WALLCOLORS #define SECRETWALLRANGE WALLRANGE #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) #define GRIDRANGE 0 #define XHAIRCOLORS GRAYS #define BLOODRED 150 // Automap colors #define BACKGROUND PARCH #define YOURCOLORS WHITE #define YOURRANGE 0 #define WALLRANGE REDRANGE #define TSWALLCOLORS GRAYS #define TSWALLRANGE GRAYSRANGE #define FDWALLRANGE BROWNRANGE #define CDWALLRANGE YELLOWRANGE #define THINGCOLORS GREENS #define THINGRANGE GREENRANGE #define SECRETWALLCOLORS WALLCOLORS #define SECRETWALLRANGE WALLRANGE #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) #define GRIDRANGE 0 #define XHAIRCOLORS GRAYS #define BORDEROFFSET 4 // Keys for Baby Mode #define KEY1_COLOR 144 // HERETIC - Green Key #define KEY2_COLOR 197 // HERETIC - Yellow Key #define KEY3_COLOR 220 // HERETIC - Blue Key #define BORDERGRAPHIC "bordb" #define MARKERPATCHES (sprintf(namebuf, "FONTA%d", (16 +i) )) // DJS - Patches used for marking the automap, a bit of a hack I suppose #endif #ifdef __JHEXEN__ // For use if I do walls with outsides/insides #define REDS 12*8 #define REDRANGE 1 //16 #define BLUES (256-4*16+8) #define BLUERANGE 1 //8 #define GREENS (33*8) #define GREENRANGE 1 //16 #define GRAYS (5*8) #define GRAYSRANGE 1 //16 #define BROWNS (14*8) #define BROWNRANGE 1 //16 #define YELLOWS 10*8 #define YELLOWRANGE 1 #define BLACK 0 #define WHITE 4*8 #define PARCH 13*8-1 #define BLOODRED 177 // Automap colors #define BACKGROUND PARCH #define YOURCOLORS WHITE #define YOURRANGE 0 #define WALLCOLORS 83 // REDS #define WALLRANGE REDRANGE #define TSWALLCOLORS GRAYS #define TSWALLRANGE GRAYSRANGE #define FDWALLCOLORS 96 // BROWNS #define FDWALLRANGE BROWNRANGE #define CDWALLCOLORS 107 // YELLOWS #define CDWALLRANGE YELLOWRANGE #define THINGCOLORS GREENS #define THINGRANGE GREENRANGE #define SECRETWALLCOLORS WALLCOLORS #define SECRETWALLRANGE WALLRANGE #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) #define GRIDRANGE 0 #define XHAIRCOLORS GRAYS #define BORDEROFFSET 4 // Automap colors #define AM_PLR1_COLOR 157 // Blue #define AM_PLR2_COLOR 177 // Red #define AM_PLR3_COLOR 137 // Yellow #define AM_PLR4_COLOR 198 // Green #define AM_PLR5_COLOR 215 // Jade #define AM_PLR6_COLOR 32 // White #define AM_PLR7_COLOR 106 // Hazel #define AM_PLR8_COLOR 234 // Purple #define KEY1 197 // HEXEN - #define KEY2 144 // HEXEN - #define KEY3 220 // HEXEN - #define BORDERGRAPHIC "bordb" #define MARKERPATCHES (sprintf(namebuf, "FONTA%d", (16 +i) )) // DJS - Patches used for marking the automap, a bit of a hack I suppose #endif #ifdef __JSTRIFE__ // For use if I do walls with outsides/insides #define REDS 12*8 #define REDRANGE 1 //16 #define BLUES (256-4*16+8) #define BLUERANGE 1 //8 #define GREENS (33*8) #define GREENRANGE 1 //16 #define GRAYS (5*8) #define GRAYSRANGE 1 //16 #define BROWNS (14*8) #define BROWNRANGE 1 //16 #define YELLOWS 10*8 #define YELLOWRANGE 1 #define BLACK 0 #define WHITE 4*8 #define PARCH 13*8-1 #define BLOODRED 177 // Automap colors #define BACKGROUND PARCH #define YOURCOLORS WHITE #define YOURRANGE 0 #define WALLCOLORS 83 // REDS #define WALLRANGE REDRANGE #define TSWALLCOLORS GRAYS #define TSWALLRANGE GRAYSRANGE #define FDWALLCOLORS 96 // BROWNS #define FDWALLRANGE BROWNRANGE #define CDWALLCOLORS 107 // YELLOWS #define CDWALLRANGE YELLOWRANGE #define THINGCOLORS GREENS #define THINGRANGE GREENRANGE #define SECRETWALLCOLORS WALLCOLORS #define SECRETWALLRANGE WALLRANGE #define GRIDCOLORS (GRAYS + GRAYSRANGE/2) #define GRIDRANGE 0 #define XHAIRCOLORS GRAYS #define BORDEROFFSET 4 // Automap colors #define KEY1 197 // HEXEN - #define KEY2 144 // HEXEN - #define KEY3 220 // HEXEN - #define BORDERGRAPHIC "bordb" #define MARKERPATCHES (sprintf(namebuf, "FONTA%d", (16 +i) )) // DJS - Patches used for marking the automap, a bit of a hack I suppose #endif typedef unsigned int automapid_t; typedef enum { AMO_NONE = -1, AMO_THING = 0, AMO_THINGPLAYER, AMO_BACKGROUND, AMO_UNSEENLINE, AMO_SINGLESIDEDLINE, AMO_TWOSIDEDLINE, AMO_FLOORCHANGELINE, AMO_CEILINGCHANGELINE, AMO_NUMOBJECTS } automapobjectname_t; typedef struct mapobjectinfo_s { float rgba[4]; int blendMode; float glowAlpha, glowWidth; boolean glow; boolean scaleWithView; } mapobjectinfo_t; enum { MOL_LINEDEF = 0, MOL_LINEDEF_TWOSIDED, MOL_LINEDEF_FLOOR, MOL_LINEDEF_CEILING, MOL_LINEDEF_UNSEEN, NUM_MAP_OBJECTLISTS }; typedef enum vectorgraphname_e { VG_NONE = -1, VG_KEYSQUARE, VG_TRIANGLE, VG_ARROW, #if !__JHEXEN__ VG_CHEATARROW, #endif NUM_VECTOR_GRAPHS } vectorgrapname_t; typedef struct mpoint_s { float pos[3]; } mpoint_t; typedef struct mline_s { mpoint_t a, b; } vgline_t; typedef struct vectorgrap_s { DGLuint dlist; uint count; vgline_t* lines; } vectorgrap_t; vectorgrap_t* AM_GetVectorGraph(vectorgrapname_t id); #define AM_MAXSPECIALLINES 32 typedef struct automapspecialline_s { int special; int sided; int cheatLevel; // minimum cheat level for this special. mapobjectinfo_t info; } automapspecialline_t; typedef struct automapcfg_s { float lineGlowScale; boolean glowingLineSpecials; float backgroundRGBA[4]; float panSpeed; boolean panResetOnOpen; float zoomSpeed; float openSeconds; // Num seconds it takes for the map to open/close. automapspecialline_t specialLines[AM_MAXSPECIALLINES]; uint numSpecialLines; vectorgrapname_t vectorGraphicForPlayer; vectorgrapname_t vectorGraphicForThing; int cheating; boolean revealed; uint followPlayer; // Player id of that to follow. mapobjectinfo_t mapObjectInfo[NUM_MAP_OBJECTLISTS]; } automapcfg_t; typedef enum glowtype_e { NO_GLOW, TWOSIDED_GLOW, BACK_GLOW, FRONT_GLOW } glowtype_t; void AM_Register(void); void AM_Init(void); void AM_Shutdown(void); void AM_InitForMap(void); void AM_Ticker(void); void AM_Drawer(int player); automapid_t AM_MapForPlayer(int plrnum); void AM_Open(automapid_t id, boolean yes, boolean fast); boolean AM_IsActive(automapid_t id); void AM_UpdateLinedef(automapid_t id, uint lineIdx, boolean visible); int AM_AddMark(automapid_t id, float x, float y, float z); void AM_ClearMarks(automapid_t id); void AM_IncMapCheatLevel(automapid_t id); void AM_SetCheatLevel(automapid_t id, int level); void AM_SetViewRotate(automapid_t id, int offOnToggle); void AM_RevealMap(automapid_t id, boolean on); void AM_ToggleZoomMax(automapid_t id); void AM_ToggleFollow(automapid_t id); float AM_GlobalAlpha(automapid_t id); void AM_GetWindow(automapid_t id, float* x, float* y, float* w, float* h); boolean AM_IsMapWindowInFullScreenMode(automapid_t id); int AM_GetFlags(automapid_t id); boolean AM_IsRevealed(automapid_t id); float AM_MapToFrame(automapid_t id, float val); void AM_GetViewPosition(automapid_t id, float* x, float* y); void M_DrawMAP(void); const automapcfg_t* AM_GetMapConfig(automapid_t id); const mapobjectinfo_t* AM_GetMapObjectInfo(automapid_t id, int objectname); const mapobjectinfo_t* AM_GetInfoForSpecialLine(automapid_t id, int special, const sector_t* frontsector, const sector_t* backsector); void AM_GetColorAndAlpha(automapid_t id, int objectname, float* r, float* g, float* b, float* a); void AM_SetColorAndAlpha(automapid_t id, int objectname, float r, float g, float b, float a); void AM_GetMapColor(float* rgb, const float* uColor, int palidx, boolean customPal); vectorgrapname_t AM_GetVectorGraphic(const automapcfg_t* cfg, int objectname); void AM_SetVectorGraphic(automapcfg_t* cfg, int objectname, int vgname); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_view.h0000644000175000017500000000200611357170242023121 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef __COMMON_PLAYER_VIEW_H__ #define __COMMON_PLAYER_VIEW_H__ void P_CalcHeight(player_t *player); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/common/include/p_svtexarc.h0000644000175000017500000000264111357170242024013 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_svtexarc.c: Archived material names (save games). */ #ifndef __DD_SAVEGAME_MATERIAL_ARCHIVE_H__ #define __DD_SAVEGAME_MATERIAL_ARCHIVE_H__ #define MATERIAL_ARCHIVE_VERSION (1) void SV_InitMaterialArchives(void); unsigned short SV_MaterialArchiveNum(material_t* mat); material_t* SV_GetArchiveMaterial(int archiveID, int group); void SV_WriteMaterialArchive(void); void SV_ReadMaterialArchive(int version); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/0000755000175000017500000000000011357170242017675 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/api/0000755000175000017500000000000011523516204020443 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/api/dswinmm.def0000644000175000017500000000054211357170242022605 0ustar keeskeesLIBRARY DSWINMM ; All exports should be prefixed DS_. EXPORTS DS_Init DS_Shutdown DS_Event DM_Music_Init DM_Music_Update DM_Music_Set DM_Music_Get DM_Music_Pause DM_Music_Stop DM_Music_Play DM_Music_SongBuffer DM_CDAudio_Init DM_CDAudio_Update DM_CDAudio_Set DM_CDAudio_Get DM_CDAudio_Pause DM_CDAudio_Stop DM_CDAudio_Playdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/res/0000755000175000017500000000000011523516204020463 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/res/dswinmm.dll.manifest0000644000175000017500000000062311357170242024447 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/res/winmm.rc0000644000175000017500000001003211357170242022137 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * winmm.rc: dsWinMM.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""dswinmm.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION PLUGIN_VERSION_NUMBER\r\n" "PRODUCTVERSION PLUGIN_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dsWinMM.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION PLUGIN_VERSION_NUMBER PRODUCTVERSION PLUGIN_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "dsWinMM.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/res/resource.h0000644000175000017500000000061111357170242022464 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by winmm.rc // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/doc/0000755000175000017500000000000011523516204020437 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/doc/LICENSE0000644000175000017500000003545111357170242021457 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/src/0000755000175000017500000000000011357170242020464 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/src/dswinmm.cpp0000644000175000017500000002626311357170242022657 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dswinmm.cpp: Music Driver for Win32 Multimedia (winmm). */ // HEADER FILES ------------------------------------------------------------ #include #include "dswinmm.h" #include "midistream.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct mixerdata_s { boolean available; MIXERLINE line; MIXERLINECONTROLS controls; MIXERCONTROL volume; } mixerdata_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean initedOk = false; static int verbose = 0; static int midiAvail = false; static WinMIDIStreamer* MIDIStreamer = NULL; static int initMixerOk = 0; static MMRESULT res; static HMIXER mixer = NULL; static mixerdata_t mixCD, mixMidi; static int origVol; // The original MIDI volume. static int origCDVol; // The original CD-DA volume. // CODE -------------------------------------------------------------------- int mixer4i(int device, int action, int control, int parm) { MIXERCONTROLDETAILS ctrlDetails; MIXERCONTROLDETAILS_UNSIGNED mcdUnsigned[2]; MIXERCONTROL *mctrl; MIXERLINE *mline; mixerdata_t *mix; int i; if(!initMixerOk) return MIX_ERROR; // This is quite specific at the moment. // Only allow setting the CD volume. if(device != MIX_CDAUDIO && device != MIX_MIDI) return MIX_ERROR; if(control != MIX_VOLUME) return MIX_ERROR; // Choose the mixer line. mix = (device == MIX_CDAUDIO ? &mixCD : &mixMidi); // Is the mixer line for the requested device available? if(!mix->available) return MIX_ERROR; mline = &mix->line; mctrl = &mix->volume; // Init the data structure. memset(&ctrlDetails, 0, sizeof(ctrlDetails)); ctrlDetails.cbStruct = sizeof(ctrlDetails); ctrlDetails.dwControlID = mctrl->dwControlID; ctrlDetails.cChannels = 1; //mline->cChannels; ctrlDetails.cbDetails = sizeof(mcdUnsigned); ctrlDetails.paDetails = &mcdUnsigned; switch(action) { case MIX_GET: res = mixerGetControlDetails((HMIXEROBJ) mixer, &ctrlDetails, MIXER_GETCONTROLDETAILSF_VALUE); if(res != MMSYSERR_NOERROR) return MIX_ERROR; // The bigger one is the real volume. i = mcdUnsigned[mcdUnsigned[0].dwValue > mcdUnsigned[1].dwValue ? 0 : 1].dwValue; // Return the value in range 0-255. return (255 * (i - mctrl->Bounds.dwMinimum)) / (mctrl->Bounds.dwMaximum - mctrl->Bounds.dwMinimum); case MIX_SET: // Clamp it. if(parm < 0) parm = 0; if(parm > 255) parm = 255; // Set both channels to the same volume (center balance). mcdUnsigned[0].dwValue = mcdUnsigned[1].dwValue = (parm * (mctrl->Bounds.dwMaximum - mctrl->Bounds.dwMinimum)) / 255 + mctrl->Bounds.dwMinimum; res = mixerSetControlDetails((HMIXEROBJ) mixer, &ctrlDetails, MIXER_SETCONTROLDETAILSF_VALUE); if(res != MMSYSERR_NOERROR) return MIX_ERROR; break; default: return MIX_ERROR; } return MIX_OK; } static int mixer3i(int device, int action, int control) { return mixer4i(device, action, control, 0); } static void initMixerLine(mixerdata_t* mix, DWORD type) { memset(mix, 0, sizeof(*mix)); mix->line.cbStruct = sizeof(mix->line); mix->line.dwComponentType = type; if((res = mixerGetLineInfo((HMIXEROBJ) mixer, &mix->line, MIXER_GETLINEINFOF_COMPONENTTYPE)) != MMSYSERR_NOERROR) { if(verbose) Con_Message(" Error getting line info: " "Error %i\n", res); return; } if(verbose) { Con_Message(" Destination line idx: %i\n", mix->line.dwDestination); Con_Message(" Line ID: 0x%x\n", mix->line.dwLineID); Con_Message(" Channels: %i\n", mix->line.cChannels); Con_Message(" Controls: %i\n", mix->line.cControls); Con_Message(" Name: %s (%s)\n", mix->line.szName, mix->line.szShortName); } mix->controls.cbStruct = sizeof(mix->controls); mix->controls.dwLineID = mix->line.dwLineID; mix->controls.dwControlType = MIXERCONTROL_CONTROLTYPE_VOLUME; mix->controls.cControls = 1; mix->controls.cbmxctrl = sizeof(mix->volume); mix->controls.pamxctrl = &mix->volume; if((res = mixerGetLineControls((HMIXEROBJ) mixer, &mix->controls, MIXER_GETLINECONTROLSF_ONEBYTYPE)) != MMSYSERR_NOERROR) { if(verbose) Con_Message(" Error getting line controls " "(vol): error %i\n", res); return; } if(verbose) { Con_Message(" Volume control ID: 0x%x\n", mix->volume.dwControlID); Con_Message(" Name: %s (%s)\n", mix->volume.szName, mix->volume.szShortName); Con_Message(" Min/Max: %i/%i\n", mix->volume.Bounds.dwMinimum, mix->volume.Bounds.dwMaximum); } // This mixer line is now available. mix->available = true; } /** * A ridiculous amount of code to do something this simple. * But mixers are pretty abstract a subject, I guess... * (No, the API just sucks.) */ static int initMixer(void) { MIXERCAPS mixerCaps; int num = mixerGetNumDevs(); // Number of mixer devices. if(initMixerOk || ArgCheck("-nomixer")) return true; if(verbose) { // In verbose mode, print a lot of extra information. Con_Message("dsWinMM::initMixer: Number of mixer devices: %i\n", num); } // Open the mixer device. res = mixerOpen(&mixer, 0, 0, 0, MIXER_OBJECTF_MIXER); if(res != MMSYSERR_NOERROR) { if(verbose) Con_Message(" Error opening mixer: Error %i\n", res); return 0; } // Get the device caps. mixerGetDevCaps((UINT_PTR) mixer, &mixerCaps, sizeof(mixerCaps)); Con_Message("dsWinMM::initMixer: %s\n", mixerCaps.szPname); if(verbose) Con_Message(" Audio line destinations: %i\n", mixerCaps.cDestinations); // Init CD mixer. if(verbose) Con_Message("Init CD audio line:\n"); initMixerLine(&mixCD, MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC); if(verbose) Con_Message("Init synthesizer line:\n"); initMixerLine(&mixMidi, MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER); // We're successful. initMixerOk = true; // Get the original mixer volume settings (restored at shutdown). origVol = mixer3i(MIX_MIDI, MIX_GET, MIX_VOLUME); origCDVol = mixer3i(MIX_CDAUDIO, MIX_GET, MIX_VOLUME); return true; } static void shutdownMixer(void) { if(!initMixerOk) return; // Can't uninitialize if not inited. // Restore the original mixer volumes, if possible. mixer4i(MIX_MIDI, MIX_SET, MIX_VOLUME, origVol); if(origCDVol != MIX_ERROR) mixer4i(MIX_CDAUDIO, MIX_SET, MIX_VOLUME, origCDVol); mixerClose(mixer); mixer = NULL; initMixerOk = false; } int DS_Init(void) { // Are we in verbose mode? verbose = ArgExists("-verbose"); initMixer(); initedOk = true; return true; } void DS_Shutdown(void) { if(!initedOk) return; // Wha? // In case the engine hasn't already done so, close open interfaces. DM_CDAudio_Shutdown(); DM_Music_Shutdown(); shutdownMixer(); initedOk = false; } /** * The Event function is called to tell the driver about certain critical * events like the beginning and end of an update cycle. */ void DS_Event(int type) { // Do nothing... } /** * @return @c true, if successful. */ int DM_Music_Init(void) { if(midiAvail) return true; // Already initialized. Con_Message("DM_WinMusInit: %i MIDI-Out devices present.\n", midiOutGetNumDevs()); MIDIStreamer = new WinMIDIStreamer; // Open the midi stream. if(!MIDIStreamer || !MIDIStreamer->OpenStream()) return false; // Double output volume? MIDIStreamer->volumeShift = ArgExists("-mdvol") ? 1 : 0; // Now the MIDI is available. Con_Message("DM_WinMusInit: MIDI initialized.\n"); return midiAvail = true; } void DM_Music_Shutdown(void) { if(midiAvail) { delete MIDIStreamer; MIDIStreamer = NULL; midiAvail = false; } } void DM_Music_Set(int prop, float value) { if(!midiAvail) return; switch(prop) { case MUSIP_VOLUME: { int val = MINMAX_OF(0, (byte) (value * 255 + .5f), 255); // Straighten the volume curve. val <<= 8; // Make it a word. val = (int) (255.9980469 * sqrt(value)); mixer4i(MIX_MIDI, MIX_SET, MIX_VOLUME, val); break; } default: break; } } int DM_Music_Get(int prop, void* ptr) { switch(prop) { case MUSIP_ID: if(ptr) { strcpy((char*) ptr, "Win/Mus"); return true; } break; case MUSIP_PLAYING: if(midiAvail && MIDIStreamer) return (MIDIStreamer->IsPlaying()? true : false); return false; default: break; } return false; } void DM_Music_Update(void) { // No need to do anything. The callback handles restarting. } void DM_Music_Stop(void) { if(midiAvail) { MIDIStreamer->Stop(); } } int DM_Music_Play(int looped) { if(midiAvail) { MIDIStreamer->Play(looped); return true; } return false; } void DM_Music_Pause(int setPause) { if(midiAvail) { MIDIStreamer->Pause(setPause); } } void* DM_Music_SongBuffer(size_t length) { if(midiAvail) { return MIDIStreamer->SongBuffer(length); } return NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/src/midistream.cpp0000644000175000017500000003266611357170242023343 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2006-2008 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * midistream.cpp: Plays MIDI streams via the winmm API. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "midistream.h" // MACROS ------------------------------------------------------------------ #define MAX_BUFFER_LEN (65535) #define MAX_BUFFERS (8) #define BUFFER_ALLOC (4096) // Allocate in 4K chunks. // TYPES ------------------------------------------------------------------- typedef struct { char id[4]; // Identifier ("MUS" 0x1A). WORD scoreLen; WORD scoreStart; WORD channels; // Number of primary channels. WORD secondaryChannels; // Number of secondary channels. WORD instrCnt; WORD dummy; // The instrument list begins here. } musheader_t; typedef struct { unsigned char channel:4; unsigned char event:3; unsigned char last:1; } museventdesc_t; enum // MUS event types. { MUS_EV_RELEASE_NOTE, MUS_EV_PLAY_NOTE, MUS_EV_PITCH_WHEEL, MUS_EV_SYSTEM, // Valueless controller. MUS_EV_CONTROLLER, MUS_EV_FIVE, // ? MUS_EV_SCORE_END, MUS_EV_SEVEN // ? }; enum // MUS controllers. { MUS_CTRL_INSTRUMENT, MUS_CTRL_BANK, MUS_CTRL_MODULATION, MUS_CTRL_VOLUME, MUS_CTRL_PAN, MUS_CTRL_EXPRESSION, MUS_CTRL_REVERB, MUS_CTRL_CHORUS, MUS_CTRL_SUSTAIN_PEDAL, MUS_CTRL_SOFT_PEDAL, // The valueless controllers. MUS_CTRL_SOUNDS_OFF, MUS_CTRL_NOTES_OFF, MUS_CTRL_MONO, MUS_CTRL_POLY, MUS_CTRL_RESET_ALL, NUM_MUS_CTRLS }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static const char ctrlMus2Midi[NUM_MUS_CTRLS] = { 0, // Not used. 0, // Bank select. 1, // Modulation. 7, // Volume. 10, // Pan. 11, // Expression. 91, // Reverb. 93, // Chorus. 64, // Sustain pedal. 67, // Soft pedal. // The valueless controllers: 120, // All sounds off. 123, // All notes off. 126, // Mono. 127, // Poly. 121 // Reset all controllers. }; // CODE -------------------------------------------------------------------- /** * WinMIDIStreamer - Constructor. */ WinMIDIStreamer::WinMIDIStreamer(void) { UINT i; midiStr = NULL; playing = 0; registered = FALSE; song = NULL; // Clear the MIDI buffers. memset(midiBuffers, 0, sizeof(midiBuffers)); // Init channel volumes. for(i = 0; i < 16; ++i) chanVols[i] = 64; } /** * WinMIDIStreamer - Destructor. */ WinMIDIStreamer::~WinMIDIStreamer(void) { CloseStream(); } int WinMIDIStreamer::OpenStream(void) { MMRESULT mmres; MIDIPROPTIMEDIV tdiv; devId = MIDI_MAPPER; if(MMSYSERR_NOERROR != (mmres = midiStreamOpen(&midiStr, &devId, 1, (DWORD_PTR) Callback, (DWORD_PTR) this, CALLBACK_FUNCTION))) { printf("WinMIDIStreamer::OpenStream: midiStreamOpen error %i.\n", mmres); return FALSE; } // Set stream time format, 140 ticks per quarter note. tdiv.cbStruct = sizeof(tdiv); tdiv.dwTimeDiv = 140; if(MMSYSERR_NOERROR != (mmres = midiStreamProperty(midiStr, (BYTE *) & tdiv, MIDIPROP_SET | MIDIPROP_TIMEDIV))) { printf("WinMIDIStreamer::OpenStream: time format! %i\n", mmres); return FALSE; } return TRUE; } void WinMIDIStreamer::CloseStream(void) { FreeSongBuffer(); if(midiStr) { Reset(); midiStreamClose(midiStr); } } /** * Reads the MUS data and produces the next corresponding MIDI event. * * @return @c false, when the score ends. */ int WinMIDIStreamer::GetNextEvent(MIDIEVENT* mev) { int i; museventdesc_t* evDesc; byte midiStatus, midiChan, midiParm1, midiParm2; mev->dwDeltaTime = readTime; readTime = 0; evDesc = (museventdesc_t *) readPos++; midiStatus = midiChan = midiParm1 = midiParm2 = 0; // Construct the MIDI event. switch(evDesc->event) { case MUS_EV_RELEASE_NOTE: midiStatus = 0x80; // Which note? midiParm1 = *readPos++; break; case MUS_EV_PLAY_NOTE: midiStatus = 0x90; // Which note? midiParm1 = *readPos++; // Is the volume there, too? if(midiParm1 & 0x80) chanVols[evDesc->channel] = *readPos++; midiParm1 &= 0x7f; if((i = chanVols[evDesc->channel] << volumeShift) > 127) i = 127; midiParm2 = i; /*#if _DEBUG Con_Message("time: %i note: p1:%i p2:%i\n", mev->dwDeltaTime, midiParm1, midiParm2); #endif*/ break; case MUS_EV_CONTROLLER: midiStatus = 0xb0; midiParm1 = *readPos++; midiParm2 = *readPos++; // The instrument control is mapped to another kind of MIDI event. if(midiParm1 == MUS_CTRL_INSTRUMENT) { midiStatus = 0xc0; midiParm1 = midiParm2; midiParm2 = 0; } else { // Use the conversion table. midiParm1 = ctrlMus2Midi[midiParm1]; } break; case MUS_EV_PITCH_WHEEL: /** * 2 bytes, 14 bit value. 0x2000 is the center. * First seven bits go to parm1, the rest to parm2. */ midiStatus = 0xe0; i = *readPos++ << 6; midiParm1 = i & 0x7f; midiParm2 = i >> 7; /*#if _DEBUG Con_Message("pitch wheel: ch %d (%x %x = %x)\n", evDesc->channel, midiParm1, midiParm2, midiParm1 | (midiParm2 << 7)); #endif*/ break; case MUS_EV_SYSTEM: midiStatus = 0xb0; midiParm1 = ctrlMus2Midi[*readPos++]; break; default: case MUS_EV_SCORE_END: // We're done. return FALSE; } // Choose the channel. midiChan = evDesc->channel; // Redirect MUS channel 16 to MIDI channel 10 (percussion). if(midiChan == 15) midiChan = 9; else if(midiChan == 9) midiChan = 15; /*#if _DEBUG Con_Message("MIDI event/%d: %x %d %d\n",evDesc->channel,midiStatus, midiParm1,midiParm2); #endif*/ mev->dwEvent = (MEVT_SHORTMSG << 24) | midiChan | midiStatus | (midiParm1 << 8) | (midiParm2 << 16); // Check if this was the last event in a group. if(!evDesc->last) return TRUE; // Read the time delta. readTime = 0; do { midiParm1 = *readPos++; readTime = readTime * 128 + (midiParm1 & 0x7f); } while(midiParm1 & 0x80); return TRUE; } /** * Note that lpData changes during reallocation! * * @return @c false, if the allocation can't be done. */ int WinMIDIStreamer::ResizeWorkBuffer(LPMIDIHDR mh) { // Don't allocate too large buffers. if(mh->dwBufferLength + BUFFER_ALLOC > MAX_BUFFER_LEN) return FALSE; mh->dwBufferLength += BUFFER_ALLOC; mh->lpData = (LPSTR) realloc(mh->lpData, mh->dwBufferLength); // Allocation was successful. return TRUE; } void* WinMIDIStreamer::SongBuffer(size_t length) { FreeSongBuffer(); songSize = length; return song = malloc(length); } void WinMIDIStreamer::FreeSongBuffer(void) { DeregisterSong(); if(song) free(song); song = NULL; songSize = 0; } LPMIDIHDR WinMIDIStreamer::GetFreeBuffer(void) { int i; for(i = 0; i < MAX_BUFFERS; ++i) { LPMIDIHDR mh = &midiBuffers[i]; if(mh->dwUser == FALSE) { // Mark the header used. mh->dwUser = TRUE; // Allocate some memory for buffer. mh->dwBufferLength = BUFFER_ALLOC; mh->lpData = (LPSTR) malloc(mh->dwBufferLength); mh->dwBytesRecorded = 0; mh->dwFlags = 0; return mh; } } return NULL; } void WinMIDIStreamer::Play(int looped) { UINT i; // Do we need to prepare the MIDI data? if(!registered) { // The song is already loaded in the song buffer. DeregisterSong(); // Prepare the buffers. if(song) { LPMIDIHDR mh = GetFreeBuffer(); MIDIEVENT mev; DWORD* ptr; // First add the tempo. ptr = (DWORD *) mh->lpData; *ptr++ = 0; *ptr++ = 0; *ptr++ = (MEVT_TEMPO << 24) | 1000000; // One second. mh->dwBytesRecorded = 3 * sizeof(DWORD); // Start reading the events. readPos = (byte *) song + ((musheader_t*)song)->scoreStart; readTime = 0; while(GetNextEvent(&mev)) { // Is the buffer getting full? if(mh->dwBufferLength - mh->dwBytesRecorded < 3 * sizeof(DWORD)) { // Try to get more buffer. if(!ResizeWorkBuffer(mh)) { // Not possible, buffer size has reached the limit. // We need to start working on another one. midiOutPrepareHeader((HMIDIOUT) midiStr, mh, sizeof(*mh)); mh = GetFreeBuffer(); if(!mh) return; // Oops. } } // Add the event. ptr = (DWORD *) (mh->lpData + mh->dwBytesRecorded); *ptr++ = mev.dwDeltaTime; *ptr++ = 0; *ptr++ = mev.dwEvent; mh->dwBytesRecorded += 3 * sizeof(DWORD); } // Prepare the last buffer, too. midiOutPrepareHeader((HMIDIOUT) midiStr, mh, sizeof(*mh)); } // Now there is a registered song. registered = TRUE; } playing = true; Reset(); // Stream out all buffers. for(i = 0; i < MAX_BUFFERS; ++i) { if(midiBuffers[i].dwUser) { loopBuffer = &midiBuffers[i]; midiStreamOut(midiStr, &midiBuffers[i], sizeof(midiBuffers[i])); } } // If we aren't looping, don't bother. if(!looped) loopBuffer = NULL; // Start playing. midiStreamRestart(midiStr); } void WinMIDIStreamer::Pause(int setPause) { playing = !setPause; if(setPause) midiStreamPause(midiStr); else midiStreamRestart(midiStr); } void WinMIDIStreamer::Reset(void) { int i; midiStreamStop(midiStr); // Reset channel settings. for(i = 0; i <= 0xf; ++i) // All channels. { midiOutShortMsg((HMIDIOUT) midiStr, 0xe0 | i | 64 << 16); // Pitch bend. } midiOutReset((HMIDIOUT) midiStr); } void WinMIDIStreamer::Stop(void) { if(!playing) return; playing = false; loopBuffer = NULL; Reset(); } void WinMIDIStreamer::DeregisterSong(void) { int i; if(!registered) return; // First stop the song. Stop(); // This is the actual unregistration. for(i = 0; i < MAX_BUFFERS; ++i) { if(midiBuffers[i].dwUser) { LPMIDIHDR mh = &midiBuffers[i]; midiOutUnprepareHeader((HMIDIOUT) midiStr, mh, sizeof(*mh)); free(mh->lpData); // Clear for re-use. memset(mh, 0, sizeof(*mh)); } } registered = FALSE; } int WinMIDIStreamer::IsPlaying(void) { return playing; } void CALLBACK WinMIDIStreamer::Callback(HMIDIOUT hmo, UINT uMsg, DWORD_PTR dwInstance, DWORD dwParam1, DWORD dwParam2) { WinMIDIStreamer* me = (WinMIDIStreamer*) dwInstance; LPMIDIHDR mh; switch(uMsg) { case MOM_DONE: if(!me->playing) return; mh = (LPMIDIHDR) dwParam1; // This buffer has stopped. Is this the last buffer? // If so, check for looping. if(mh == me->loopBuffer) { // Play all buffers again. me->Play(true); } else { me->playing = false; } break; default: break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/src/cdaudio.cpp0000644000175000017500000001453011357170242022603 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cdaudio.cpp: Compact Disc-Digital Audio (CD-DA) / "Redbook". * * WIN32-specific, uses the MCI interface. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "dswinmm.h" // MACROS ------------------------------------------------------------------ #define DEVICEID "mycd" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int cdInited = false; // Currently playing track info: static int cdCurrentTrack = 0; static boolean cdLooping; static double cdStartTime, cdPauseTime, cdTrackLength; // CODE -------------------------------------------------------------------- /** * Execute an MCI command string. * * @return @c true, if successful. */ static int sendMCICmd(char* returnInfo, int returnLength, const char *format, ...) { char buf[300]; va_list args; MCIERROR error; va_start(args, format); dd_vsnprintf(buf, sizeof(buf), format, args); va_end(args); if((error = mciSendString(buf, returnInfo, returnLength, NULL))) { mciGetErrorString(error, buf, 300); Con_Message("DM_WinCD: %s\n", buf); return false; } return true; } /** * @return Length of the track in seconds. */ static int getTrackLength(int track) { char lenString[80]; int min, sec; if(!sendMCICmd(lenString, 80, "status " DEVICEID " length track %i", track)) return 0; sscanf(lenString, "%i:%i", &min, &sec); return min * 60 + sec; } static int isPlaying(void) { char lenString[80]; if(!sendMCICmd(lenString, 80, "status " DEVICEID " mode wait")) return false; if(strcmp(lenString, "playing") == 0) return true; return false; } /** * Assign the value of a CDAudio-interface property. */ void DM_CDAudio_Set(int prop, float value) { if(!cdInited) return; switch(prop) { case MUSIP_VOLUME: { int val = MINMAX_OF(0, (byte) (value * 255 + .5f), 255); // Straighten the volume curve. val <<= 8; // Make it a word. val = (int) (255.9980469 * sqrt(value)); mixer4i(MIX_CDAUDIO, MIX_SET, MIX_VOLUME, val); break; } default: break; } } /** * Retrieve the value of a CDAudio-interface property. */ int DM_CDAudio_Get(int prop, void* ptr) { if(!cdInited) return false; switch(prop) { case MUSIP_ID: if(ptr) { strcpy((char*) ptr, "Win/CD"); return true; } break; case MUSIP_PLAYING: return (cdInited && isPlaying()? true : false); default: break; } return false; } /** * Initialize the CDAudio-interface. */ int DM_CDAudio_Init(void) { if(cdInited) return true; if(!sendMCICmd(0, 0, "open cdaudio alias " DEVICEID)) return false; if(!sendMCICmd(0, 0, "set " DEVICEID " time format tmsf")) return false; cdCurrentTrack = 0; cdLooping = false; cdStartTime = cdPauseTime = cdTrackLength = 0; // Successful initialization. return cdInited = true; } /** * Shutdown the CDAudio-interface, we do nothing whilst offline. */ void DM_CDAudio_Shutdown(void) { if(!cdInited) return; DM_CDAudio_Stop(); sendMCICmd(0, 0, "close " DEVICEID); cdInited = false; } /** * Do any necessary update tasks. Called every frame by the engine. */ void DM_CDAudio_Update(void) { if(!cdInited) return; // Check for looping. if(cdCurrentTrack && cdLooping && Sys_GetSeconds() - cdStartTime > cdTrackLength) { // Restart the track. DM_CDAudio_Play(cdCurrentTrack, true); } } /** * Begin playback of a specifc audio track, possibly looped. */ int DM_CDAudio_Play(int track, int looped) { int len; if(!cdInited) return false; // Get the length of the track. cdTrackLength = len = getTrackLength(track); if(!len) return false; // Hmm?! // Play it! if(!sendMCICmd(0, 0, "play " DEVICEID " from %i to %i", track, MCI_MAKE_TMSF(track, 0, len, 0))) return false; // Success! cdLooping = looped; cdStartTime = Sys_GetSeconds(); return cdCurrentTrack = track; } /** * Pauses playback of the currently playing audio track. */ void DM_CDAudio_Pause(int pause) { if(!cdInited) return; sendMCICmd(0, 0, "%s " DEVICEID, pause ? "pause" : "play"); if(pause) cdPauseTime = Sys_GetSeconds(); else cdStartTime += Sys_GetSeconds() - cdPauseTime; } /** * Stops playback of the currently playing audio track. */ void DM_CDAudio_Stop(void) { if(!cdInited || !cdCurrentTrack) return; cdCurrentTrack = 0; sendMCICmd(0, 0, "stop " DEVICEID); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/include/0000755000175000017500000000000011523516204021315 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/include/dswinmm.h0000644000175000017500000000451011357170242023147 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dswinmm.h: Windows Multimedia, Win32 audio driver. */ #ifndef __DSWINMM_H__ #define __DSWINMM_H__ #define WIN32_LEAN_AND_MEAN #include #include #include "doomsday.h" #include "sys_audiod_mus.h" // Mixer return values. enum { MIX_ERROR = -1, MIX_OK }; // Mixer devices. enum { MIX_CDAUDIO, MIX_MIDI }; // Mixer actions. enum { MIX_GET, MIX_SET }; // Mixer controls. enum { MIX_VOLUME // 0-255 }; int mixer4i(int device, int action, int control, int parm); // Public music interface. int DM_Music_Init(void); void DM_Music_Shutdown(void); void DM_Music_Reset(void); void DM_Music_Update(void); void DM_Music_Set(int prop, float value); int DM_Music_Get(int prop, void* ptr); void DM_Music_Pause(int pause); void DM_Music_Stop(void); void* DM_Music_SongBuffer(size_t length); int DM_Music_Play(int looped); // CD Audio interface: int DM_CDAudio_Init(void); void DM_CDAudio_Shutdown(void); void DM_CDAudio_Update(void); void DM_CDAudio_Set(int prop, float value); int DM_CDAudio_Get(int prop, void* ptr); void DM_CDAudio_Pause(int pause); void DM_CDAudio_Stop(void); int DM_CDAudio_Play(int track, int looped); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/include/version.h0000644000175000017500000000336511357170242023165 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __DSWINMM_VERSION_H__ #define __DSWINMM_VERSION_H__ #ifndef DSWINMM_VER_ID # ifdef _DEBUG # define DSWINMM_VER_ID "+D Doomsday" # else # define DSWINMM_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define PLUGIN_NAME "dswinmm" // Presented to the user in dialogs, messages etc. #define PLUGIN_NICENAME "Windows Multimedia Audio Driver" #define PLUGIN_DETAILS "Doomsday plugin for audio playback via Windows Multimedia." #define PLUGIN_VERSION_TEXT "1.0.5" #define PLUGIN_VERSION_TEXTLONG "Version" PLUGIN_VERSION_TEXT " " __DATE__ " (" DSWINMM_VER_ID ")" #define PLUGIN_VERSION_NUMBER 1,0,5,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/include/cdaudio.h0000644000175000017500000000332211357170242023101 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * cdaudio.h: Plays CDAudio tracks via winmm API. */ #ifndef __WIN_CDAUDIO_H__ #define __WIN_CDAUDIO_H__ #define WIN32_LEAN_AND_MEAN #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0400 # undef _WIN32_WINNT #endif #ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0400 #endif #include #include typedef unsigned char byte; class WinCDAudio { public: WinCDAudio(); ~WinCDAudio(void); void Update(void); int Play(int track, int looped); void Pause(int pause); void Stop(void); private: int IsMediaPresent(void); int GetTrackLength(int track); protected: int isInited; // Currently playing track info: int currentTrack; int isLooping; double startTime, pauseTime, trackLength; }; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/winmm/include/midistream.h0000644000175000017500000000455011357170242023633 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2007-2008 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * midistream.h: Plays MIDI streams via the winmm API. */ #ifndef __WIN_MIDISTREAMER_H__ #define __WIN_MIDISTREAMER_H__ #define WIN32_LEAN_AND_MEAN #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0400 # undef _WIN32_WINNT #endif #ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0400 #endif #include #include typedef unsigned char byte; class WinMIDIStreamer { public: WinMIDIStreamer(void); ~WinMIDIStreamer(void); int OpenStream(void); void* SongBuffer(size_t length); void FreeSongBuffer(void); void CloseStream(void); void Play(int looped); void Pause(int setPause); void Reset(void); void Stop(void); int IsPlaying(void); int volumeShift; protected: static void CALLBACK Callback(HMIDIOUT, UINT, DWORD_PTR, DWORD, DWORD); LPMIDIHDR GetFreeBuffer(void); int ResizeWorkBuffer(LPMIDIHDR mh); int GetNextEvent(MIDIEVENT* mev); void DeregisterSong(void); HMIDISTRM midiStr; UINT devId; int playing; // The song is playing/looping. byte chanVols[16]; // Last volume for each channel. void* song; size_t songSize; MIDIHDR midiBuffers[8]; LPMIDIHDR loopBuffer; int registered; byte* readPos; int readTime; // In ticks. }; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/0000755000175000017500000000000011523516204020340 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/api/0000755000175000017500000000000011523516204021111 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/api/jheretic.def0000644000175000017500000000005311357170242023367 0ustar keeskeesLIBRARY JHERETIC EXPORTS GetGameAPI @1deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/res/0000755000175000017500000000000011523516204021131 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/res/jheretic.dll.manifest0000644000175000017500000000062311357170242025234 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/res/jheretic.rc0000644000175000017500000001030311357170242023254 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jheretic.rc: jHeretic.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""jheretic.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION GAME_VERSION_NUMBER\r\n" "PRODUCTVERSION GAME_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", GAME_NICENAME "" (Doomsday Engine game plugin)\0""\r\n" " VALUE ""FileVersion"", GAME_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", GAME_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""jHeretic.dll\0""\r\n" " VALUE ""ProductName"", GAME_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", GAME_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif /** * Icons: * Icon with lowest ID value placed first to ensure application icon * remains consistent on all systems. */ IDI_GAME_ICON ICON DISCARDABLE "jheretic.ico" #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION GAME_VERSION_NUMBER PRODUCTVERSION GAME_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", GAME_NICENAME " (Doomsday Engine game plugin)\0" VALUE "FileVersion", GAME_VERSION_TEXT "\0" VALUE "InternalName", GAME_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "jHeretic.dll\0" VALUE "ProductName", GAME_NICENAME "\0" VALUE "ProductVersion", GAME_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/res/jheretic.ico0000644000175000017500000001114611357170242023430 0ustar keeskees(Fhn   (  000 " "0" "#:3""3# * ( @'7*gvuɀ bIX8|F/>I-x:1{@_m@Iep?N4 Yd,&b/ +/d;*d6Sa\TFTEU)6.<.= <;pJCyO JVd?ME Wg>=8mG    &q46BO]6DAQDS2B:G)e+c,P_;IN\E~RIYDPP^P]IX#l1!%( "r0{,"o1JZ:iH1A3B|-SbTa=jH  0"$:I- )p6)r7,#;J 1,   u- o.t.p.+ *;+;%+ + #%# &i%V0p2x_iW3wXEzyD:jIF4k_,Y|Z{0&5;l\6}-'[0 ]HGm~K=0J)MLbPa "O qR@7.?Qr9S8Asu* /Bt veC#dUTcvhg$+f10( @ "****:*3**2**2""""""" """"""""**":*":0""# "#:""3"2":":# #"" ***#  # 0" ( @BTEUsZ%K64C6r|(x̄4E!0" L\LYam^hBsQhv+%ms@/7fK0c?6lE (Q]ߋ X&*@-*6+o|CT+M[VbA% ȊK'59|F=LN =KXf,b5Tb[jP^;I"20*O^ />}O+;.2A4DvWb P`.u=!h/'7W$ftFVKWoy2A-_)Vd,l@"/C"/s|:-q9?jwYjj$^m6E _*2A9FIWTa >HX[*C.;Xhl#AQfsixFW8'kt8) @20?GVYe ?|brGXQ^kvE~Pd'A(eqFT:jz5C%_/ 3kzT(#^-)y7=L#g11 p' e0s(+;0}>AO->- 96W*+=B*4xD2A.m;G|OHU:,:y3D3@0n=yJ N {)w4'f5*  ]jTa3z@Taixdr'g2L\eum| @AQUcA.>$n0%l4'j4 h,0? x..=$r0+u8@ML\M\T#;"*v6drS%+ j,?MQ.ajUcuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu8uuuuuuuuuruuuuuuuuuuuuuuuu(uuuuuuluuuuuuuuuuuuuuuuGuuuuuاOuuuuuuuuuuuuuuuuu2uuuuu9uuuuuuuuuuuuuuuu2uuuuu^Suuuuuuuuuuuuuuuu؍)uuuuuSuuuuuuuuuuuuuuuuluuuuuuuuuuuuuuuuuuuuSuuuu uuuuuuuuuuuuuuuu؈^uuuur*uuuuuuuuuuuuuuuuؤsuuuu؋*2uuuuuuuuuuuuuuuu2uuuufNuuuuuuuuuuuuuuuu*2uuuuԈ2NuuuuuuuuuuuuuuuuuuuuufuuuuuuuuuuuuuuuuؤKuuuub*fuuuuuuuuuuuuuuuuؤ󌪼uuuube2fuuuuuuuuuuuuuuuueuuuud2uuuuuuuuuuuuuuuu_Ohe>uuuN*fuuuuuuuuuuuuuuuؤPÒfuuuuuuuuuuuuuuu*T2!uuuuuuuuuuuuuuuiNNB4uuuuuuuuuuuuuuumDlh^<*uuuuuuuuuuuuuu" F؆eluuuuuuuuuuuuuT2+or2uuuuuuuuuuuuuuNq$^.rduuuuuuuuuuuuuutsGuuԮruuuuuuuuuuuuuuؼGGGuu%2uuuuuuuuuuuuuu9// /uuuuuuuuuuuuuuuxuuxxxxuux&uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu???0 deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/res/resource.h0000644000175000017500000000067011357170242023137 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by jheretic.rc // #define IDI_GAME_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/doc/0000755000175000017500000000000011523516204021105 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/doc/LICENSE0000644000175000017500000003545111357170242022125 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/0000755000175000017500000000000011523516204021251 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/conhelp.txt0000644000175000017500000004754311357170242023462 0ustar keeskees# # CONSOLE COMMANDS - JHERETIC SPECFIC # [conbg] desc = Console background setup. inf = Params: conbg (materialname) [setcolor] desc = Set player color. inf = Params: setcolor (playernum)\nFor example, 'setcolor 4'. [setmap] desc = Set map. inf = Params: setmap (episode) (map)\nFor example, 'setmap 1 7'. [setclass] desc = Set player class. [startcycle] desc = Begin map rotation. [endcycle] desc = End map rotation. [menu] desc = Open/Close the menu. [menuup] desc = Move the menu cursor up. [menudown] desc = Move the menu cursor down. [menuleft] desc = Move the menu cursor left. [menuright] desc = Move the menu cursor right. [menuselect] desc = Select/Accept the current menu item. [menuback] desc = Return to the previous menu page. [helpscreen] desc = Show the Help screens. [savegame] desc = Open the save game menu. [loadgame] desc = Open the load game menu. [listmaps] desc = List all loaded maps. [soundmenu] desc = Open the sound settings menu. [quicksave] desc = Quicksave the game. [endgame] desc = End the game. [togglemsgs] desc = Messages on/off. [quickload] desc = Load the quicksaved game. [quit] desc = Quit the game and return to the OS. [togglegamma] desc = Cycle gamma correction levels. [messageyes] desc = Respond - YES to the message promt. [messageno] desc = Respond - NO to the message promt. [messagecancel] desc = Respond - CANCEL to the message promte. [spy] desc = Change the viewplayer when not in deathmatch. [screenshot] desc = Take a screenshot. [viewsize] desc = Set the view size. inf = Params: viewsize (size)\nFor example, 'viewsize 10'.\nSize can be: +, -, (num). [pause] desc = Pause the game (same as pressing the pause key). [cheat] desc = Issue a cheat code using the original Heretic cheats. inf = Params: cheat (cheat)\nFor example, 'cheat rambo'. [god] desc = I don't think He needs any help... [notarget] desc = Enemies will not target the player (cheat). [noclip] desc = Movement clipping on/off. [warp] desc = Warp to a map. [reveal] desc = Map cheat. inf = Params: reveal (0-4)\nModes:\n 0=nothing\n 1=show unseen\n 2=full map\n 3=map+things\n 4=show subsectors [give] desc = Cheat command to give you various kinds of things. [kill] desc = Kill all the monsters on the map. [exitmap] desc = Exit the current map. [suicide] desc = Kill yourself. What did you think? [hereticfont] desc = Use the Heretic font. [startinf] desc = Start an InFine script. inf = Params: startinf (script-id)\nFor example, 'startinf coolscript'. [stopinf] desc = Stop the currently playing interlude/finale. [stopfinale] desc = Stop the currently playing interlude/finale. [spawnmobj] desc = Spawn a new mobj. [coord] desc = Print the coordinates of the consoleplayer. [makelocp] desc = Make local player. inf = Params: makelocp (playernum)\nFor example, 'makelocp 1'. [makecam] desc = Toggle camera mode. inf = Params: makecam (playernum)\nFor example, 'makecam 1'. [setlock] desc = Set camera viewlock. [lockmode] desc = Set camera viewlock mode. inf = Params: lockmode (0-1). [chicken] desc = Turn yourself into a chicken. Go ahead. [where] desc = Prints your map number and exact location. [sbsize] desc = Status bar size adjustment. inf = Params: sbsize (size)\nFor example, 'sbsize +'.\nSize can be: +, -, (num). [movefloor] desc = Move a sector's floor plane. [moveceil] desc = Move a sector's ceiling plane. [movesec] desc = Move a sector's both planes. [chatcomplete] desc = Send the chat message and exit chat mode. [chatdelete] desc = Delete a character from the chat buffer. [chatcancel] desc = Exit chat mode without sending the message. [chatsendmacro] desc = Send a chat macro. [beginchat] desc = Begin chat mode. [message] desc = Show a local game message. inf = Params: message (msg)\nFor example, 'message "this is a message"'. # # CONSOLE VARIABLES - JHERETIC SPECIFIC # [server-game-mapcycle] desc = Map rotation sequence. [server-game-mapcycle-noexit] desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). [menu-scale] desc = Scaling for menus. [menu-flash-r] desc = Menu selection flash color, red component. [menu-flash-g] desc = Menu selection flash color, green component. [menu-flash-b] desc = Menu selection flash color, blue component. [menu-flash-speed] desc = Menu selection flash speed. [menu-turningskull] desc = 1=Menu skull turns at slider items. [menu-effect] desc = 0=Disable menu effects. 1=type-in. [menu-color-r] desc = Menu color red component. [menu-color-g] desc = Menu color green component. [menu-color-b] desc = Menu color blue component. [menu-colorb-r] desc = Menu color B red component. [menu-colorb-g] desc = Menu color B green component. [menu-colorb-b] desc = Menu color B blue component. [menu-glitter] desc = Strength of type-in glitter. [menu-fog] desc = Menu fog mode: 0=off, 1=shimmer, 2=black smoke, 3=blue vertical, 4=grey smoke, 5=dimmed. [menu-hotkeys] desc = 1=Enable hotkey navigation in the menu. [menu-shadow] desc = Menu text shadow darkness. [menu-patch-replacement] desc = Patch Replacement strings. 1=Enable external, 2=Enable built-in. [menu-slam] desc = 1=Slam the menu when opening. [menu-quick-ask] desc = 1=Ask me to confirm when quick saving/loading. [xg-dev] desc = 1=Print XG debug messages. [view-cross-type] desc = The current crosshair. [view-cross-size] desc = Crosshair size: 1=Normal. [view-cross-vitality] desc = Color the crosshair according to how near you are to death. [view-cross-r] desc = Crosshair color red component. [view-cross-g] desc = Crosshair color green component. [view-cross-b] desc = Crosshair color blue component. [view-cross-a] desc = Crosshair color alpha component. [view-filter-strength] desc = Strength of view filter. [msg-show] desc = 1=Show messages. [msg-echo] desc = 1=Echo all messages to the console. [msg-count] desc = Number of HUD messages displayed at the same time. [msg-uptime] desc = Number of seconds to keep HUD messages on screen. [msg-scale] desc = Scaling factor for HUD messages. [msg-align] desc = Alignment of HUD messages. 0 = left, 1 = center, 2 = right. [msg-color-r] desc = Color of HUD messages red component. [msg-color-g] desc = Color of HUD messages green component. [msg-color-b] desc = Color of HUD messages blue component. [msg-blink] desc = HUD messages blink for this number of tics when printed. [game-state] desc = Current game state. [game-state-map] desc = 1=Currently playing a map. [game-paused] desc = 1=Game paused. [game-skill] desc = Current skill level. [map-id] desc = Current map id. [map-name] desc = Current map name. [map-episode] desc = Current episode. [game-music] desc = Currently playing music (id). [map-music] desc = Music (id) for current map. [game-stats-kills] desc = Current number of kills. [game-stats-items] desc = Current number of items. [game-stats-secrets] desc = Current number of discovered secrets. [player-health] desc = Current health ammount. [player-armor] desc = Current armor ammount. [player-weapon-current] desc = Current weapon (id) [player-ammo-goldwand] desc = Current amount of ammo for the goldwand. [player-ammo-crossbow] desc = Current amount of ammo for the crossbow. [player-ammo-dragonclaw] desc = Current amount of ammo for the Dragon Claw. [player-ammo-hellstaff] desc = Current amount of ammo for the Hell Staff. [player-ammo-phoenixrod] desc = Current amount of ammo for the Phoenix Rod. [player-ammo-mace] desc = Current amount of ammo for the mace. [player-weapon-staff] desc = 1= Player has staff. [player-weapon-goldwand] desc = 1= Player has goldwand. [player-weapon-crossbow] desc = 1= Player has crossbow. [player-weapon-dragonclaw] desc = 1= Player has the Dragon Claw. [player-weapon-hellstaff] desc = 1= Player has the Hell Staff. [player-weapon-phoenixrod] desc = 1= Player has the Phoenix Rod. [player-weapon-mace] desc = 1= Player has mace. [player-weapon-gauntlets] desc = 1= Player has gauntlets. [player-key-yellow] desc = 1= Player has yellow key. [player-key-green] desc = 1= Player has green key. [player-key-blue] desc = 1= Player has blue key. [player-artifact-ring] desc = Current number of Rings of Invincibility. [player-artifact-shadowsphere] desc = Current number of Shadowsphere artifacts. [player-artifact-crystalvial] desc = Current number of Crystal Vials. [player-artifact-mysticurn] desc = Current number of Mystic Urn artifacts. [player-artifact-tomeofpower] desc = Current number of Tome of Power artifacts. [player-artifact-torch] desc = Current number of torches. [player-artifact-firebomb] desc = Current number of Time Bombs Of The Ancients. [player-artifact-egg] desc = Current number of Morph Ovum artifacts. [player-artifact-wings] desc = Current number of Wings of Wrath artifacts. [player-artifact-chaosdevice] desc = Current number of Chaos Devices. [chat-beep] desc = 1= Play a beep sound when a new chat message arrives. [chat-macro0] desc = Chat macro 1. [chat-macro1] desc = Chat macro 2. [chat-macro2] desc = Chat macro 3. [chat-macro3] desc = Chat macro 4. [chat-macro4] desc = Chat macro 5. [chat-macro5] desc = Chat macro 6. [chat-macro6] desc = Chat macro 7. [chat-macro7] desc = Chat macro 8. [chat-macro8] desc = Chat macro 9. [chat-macro9] desc = Chat macro 10. [map-alpha-lines] desc = Alpha level of automap lines. [map-babykeys] desc = 1=Show keys in automap (easy skill mode only). [map-background-r] desc = Automap background color, red component. [map-background-g] desc = Automap background color, green component. [map-background-b] desc = Automap background color, blue component. [map-cheat-counter] desc = 6-bit bitfield. Show kills, items and secret counters in automap. [map-cheat-counter-scale] desc = Size factor for the counters in the automap. [map-customcolors] desc = Custom automap coloring 0=Never, 1=Auto (enabled if unchanged), 2=Always. [map-door-colors] desc = 1=Show door colors in automap. [map-door-glow] desc = Door glow thickness in the automap (with map-door-colors). [map-huddisplay] desc = 0=No HUD when in the automap 1=Current HUD display shown when in the automap 2=Always show Status Bar when in the automap [map-mobj-r] desc = Automap mobjs, red component. [map-mobj-g] desc = Automap mobjs, green component. [map-mobj-b] desc = Automap mobjs, blue component. [map-opacity] desc = Opacity of the automap. [map-open-timer] desc = Time taken to open/close the automap, in seconds. [map-pan-speed] desc = Pan speed multiplier in the automap. [map-pan-resetonopen] desc = 1= Reset automap pan location when opening the automap. [map-rotate] desc = 1=Automap turns with player, up=forward. [map-wall-r] desc = Automap walls, red component. [map-wall-g] desc = Automap walls, green component. [map-wall-b] desc = Automap walls, blue component. [map-wall-ceilingchange-r] desc = Automap ceiling height difference lines, red component. [map-wall-ceilingchange-g] desc = Automap ceiling height difference lines, green component. [map-wall-ceilingchange-b] desc = Automap ceiling height difference lines, blue component. [map-wall-floorchange-r] desc = Automap floor height difference lines, red component. [map-wall-floorchange-g] desc = Automap floor height difference lines, green component. [map-wall-floorchange-b] desc = Automap floor height difference lines, blue component. [map-wall-unseen-r] desc = Automap unseen areas, red component. [map-wall-unseen-g] desc = Automap unseen areas, green component. [map-wall-unseen-b] desc = Automap unseen areas, blue component. [map-zoom-speed] desc = Zoom in/out speed multiplier in the automap. [input-mouse-x-sensi] desc = Mouse X axis sensitivity. [input-mouse-y-sensi] desc = Mouse Y axis sensitivity. [input-joy-x] desc = X axis control: 0=None, 1=Move, 2=Turn, 3=Strafe, 4=Look. [input-joy-y] desc = Y axis control. [input-joy-z] desc = Z axis control. [input-joy-rx] desc = X rotational axis control. [input-joy-ry] desc = Y rotational axis control. [input-joy-rz] desc = Z rotational axis control. [input-joy-slider1] desc = First slider control. [input-joy-slider2] desc = Second slider control. [ctl-aim-noauto] desc = 1=Autoaiming disabled. [ctl-turn-speed] desc = The speed of turning left/right. [ctl-run] desc = 1=Always run. [ctl-use-dclick] desc = 1=Doubleclick forward/strafe equals use key. [ctl-inventory-mode] desc = Inventory selection mode 0=cursor, 1=scroll. [ctl-inventory-wrap] desc = 1=Inventory selection wraps around. [ctl-inventory-use-immediate] desc = 1=Use items immediately from the inventory. [ctl-inventory-use-next] desc = 1=Automatically select the next inventory item when unusable. [ctl-look-speed] desc = The speed of looking up/down. [ctl-look-spring] desc = 1=Lookspring active. [ctl-look-mouse] desc = 1=Mouse look active. [ctl-look-mouse-inverse] desc = 1=Inverse mouse look Y axis. [ctl-look-pov] desc = 1=Look around using the POV hat. [ctl-look-joy] desc = 1=Joystick look active. [ctl-look-joy-inverse] desc = 1=Inverse joystick look Y axis. [ctl-look-joy-delta] desc = 1=Joystick values => look angle delta. [con-zoom] desc = Zoom factor for the console background. [view-size] desc = View window size (3-13). [hud-title] desc = 1=Show map title and author in the beginning. [hud-title-author-noiwad] desc = 1=Do not show map author if it is a map from an IWAD. [view-bob-height] desc = Scale for viewheight bobbing. [view-bob-weapon] desc = Scale for player weapon bobbing. [view-bob-weapon-switch-lower] desc = HUD weapon lowered during weapon switching. [view-ringfilter] desc = Ring effect filter. 1=Brownish, 2=Blue. [server-game-announce-secret] desc = 1=Announce the discovery of secret areas. [server-game-skill] desc = Skill level in multiplayer games. [server-game-map] desc = Map to use in multiplayer games. [server-game-episode] desc = Episode to use in multiplayer games. [server-game-deathmatch] desc = Start multiplayers games as deathmatch. [server-game-mod-damage] desc = Enemy (mob) damage modifier, multiplayer (1..100). [server-game-mod-health] desc = Enemy (mob) health modifier, multiplayer (1..20). [server-game-mod-gravity] desc = gravity modifier, multiplayer (-1..100). -1 = Map default. [server-game-jump] desc = 1=Allow jumping in multiplayer games. [server-game-maulotaur-fixfloorfire] desc = 1=Fix bug in original Heretic which would explode the Maulotaur floor fire if spawned while it's feet are clipped. [server-game-plane-fixmaterialscroll] desc = 1=Fix bug in original Heretic which would only allow scrolling materials on planes to move east. [server-game-nomonsters] desc = 1=No monsters. [server-game-respawn] desc = 1= -respawn was used. [server-game-respawn-monsters-nightmare] desc = 1=Monster respawning in Nightmare difficulty enabled. [server-game-radiusattack-nomaxz] desc = 1=ALL radius attacks are infinitely tall. [server-game-monster-meleeattack-nomaxz] desc = 1=Monster melee attacks are infinitely tall. [player-color] desc = Player color: 0=green, 1=yellow, 2=red, 3=blue, 4=default. [player-eyeheight] desc = Player eye height. The original is 41. [player-move-speed] desc = Player movement speed modifier. [player-jump] desc = 1=Allow jumping. [player-jump-power] desc = Jump power (for all clients if this is the server). [player-air-movement] desc = Player movement speed while airborne. [player-autoswitch] desc = Change weapon automatically when picking one up. 1=If better 2=Always [player-autoswitch-notfiring] desc = 1=Disable automatic weapon switch if firing when picking one up. [player-autoswitch-ammo] desc = Change weapon automatically when picking up ammo. 1=If better 2=Always [player-weapon-order0] desc = Weapon change order, slot 0. [player-weapon-order1] desc = Weapon change order, slot 1. [player-weapon-order2] desc = Weapon change order, slot 2. [player-weapon-order3] desc = Weapon change order, slot 3. [player-weapon-order4] desc = Weapon change order, slot 4. [player-weapon-order5] desc = Weapon change order, slot 5. [player-weapon-order6] desc = Weapon change order, slot 6. [player-weapon-order7] desc = Weapon change order, slot 7. [player-weapon-order8] desc = Weapon change order, slot 8. [player-weapon-nextmode] desc = 1= Use custom weapon order with Next/Previous weapon. [player-camera-noclip] desc = 1=Camera players have no movement clipping. [game-monsters-stuckindoors] desc = 1=Monsters can get stuck in doortracks (disables DOOM bug fix). [game-objects-hangoverledges] desc = 1=Only some objects can hang over tall ledges (enables DOOM bug fix). [game-objects-clipping] desc = 1=Use EXACTLY DOOM's clipping code (disables DOOM bug fix). [game-player-wallrun-northonly] desc = 1=Players can only wallrun North (disables DOOM bug fix). [game-objects-falloff] desc = 1=Objects fall under their own weight (enables DOOM bug fix). [game-zclip] desc = 1=Allow mobjs to move under/over each other (enables DOOM bug fix). [game-corpse-sliding] desc = 1=Corpses slide down stairs and ledges (enables enhanced BOOM behaviour). [game-fastmonsters] desc = 1=Fast monsters in non-demo single player. [game-corpse-time] desc = Corpse vanish time in seconds, 0=disabled. [hud-scale] desc = Scaling for HUD info. [hud-status-size] desc = Status bar size (1-20). [hud-color-r] desc = HUD info color red component. [hud-color-g] desc = HUD info color green component. [hud-color-b] desc = HUD info color alpha component. [hud-color-a] desc = HUD info alpha value. [hud-icon-alpha] desc = HUD icon alpha value. [hud-status-alpha] desc = Status bar Alpha level. [hud-status-icon-a] desc = Status bar icons & counters Alpha level. [hud-ammo] desc = 1=Show ammo when the status bar is hidden. [hud-armor] desc = 1=Show armor when the status bar is hidden. [hud-keys] desc = 1=Show keys when the status bar is hidden. [hud-health] desc = 1=Show health when the status bar is hidden. [hud-currentitem] desc = 1=Show current item in full-screen mode. [hud-tome-timer] desc = Countdown seconds for the Tome of Power. [hud-tome-sound] desc = Seconds for countdown sound of Tome of Power. [hud-inventory-slot-max] desc = Maximum number of inventory slots to display in full-screen mode. [hud-inventory-slot-showempty] desc = 1=Show empty inventory slots in full-screen mode. [hud-inventory-timer] desc = Seconds before the inventory auto-hides. [hud-frags-all] desc = Debug: HUD shows all frags of all players. [hud-timer] desc = Number of seconds before the hud auto-hides. [hud-unhide-damage] desc = 1=Unhide the HUD when player receives damaged. [hud-unhide-pickup-health] desc = 1=Unhide the HUD when player collects a health item. [hud-unhide-pickup-armor] desc = 1=Unhide the HUD when player collects an armor item. [hud-unhide-pickup-powerup] desc = 1=Unhide the HUD when player collects a powerup or item of equipment. [hud-unhide-pickup-weapon] desc = 1=Unhide the HUD when player collects a weapon. [hud-unhide-pickup-ammo] desc = 1=Unhide the HUD when player collects an ammo item. [hud-unhide-pickup-key] desc = 1=Unhide the HUD when player collects a key. [hud-unhide-pickup-invitem] desc = 1=Unhide the HUD when player collects an inventory item. [rend-dev-freeze-map] desc = 1=Stop updating the automap rendering lists. deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/0000755000175000017500000000000011357170242022414 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fontb00.lmp0000644000175000017500000000004111357170242024371 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fontb60.lmp0000644000175000017500000000031411357170242024402 0ustar keeskees @GPZep{  deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fonta60.lmp0000644000175000017500000000011311357170242024376 0ustar keeskees$0<!###!deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fonta61.lmp0000644000175000017500000000016711357170242024410 0ustar keeskees$+3;CKS '' deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fonta62.lmp0000644000175000017500000000011311357170242024400 0ustar keeskees'3?!!###deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fonta63.lmp0000644000175000017500000000010211357170242024377 0ustar keeskees#+3;#deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fontb62.lmp0000644000175000017500000000020011357170242024376 0ustar keeskees ,3<FQ[fpydeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fonta00.lmp0000644000175000017500000000003411357170242024372 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/fontb61.lmp0000644000175000017500000000026311357170242024406 0ustar keeskees (9J[m     deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/mapmask.lmp0000644000175000017500000020000011357170242024547 0ustar keeskees             !  !!! ! !"! ! !!!!!"""#!!"""!! ""!!! !!!"" !!!!! !! "" !"! !  ! ! !!!"! !! """ ! !""!!!"!" !!!!!!!"  "#""!!! ! !! !! !!! ! ! !! !  "!! "!"" !! ! !"!!" """ !  "$&'&&%&'&'&'&&&'&&%&&&'''&((('''''&&'&&&%&(('&%&''&'(&%&'''&%%%&&&&'(%&'&&&%&%&&%%&&&('&''&(((&&'&&&&&(&&'((&&&&'''&'''(&&&%%&'(&&'&'&&&&&&&&&&'&&&'&&&''&&'&''('&&'&%&(''&('&&&&''&&&&'''&&''((&'$"    #%()+,,-,,,+,+,++++++++,*++,+,,-+,,,+++,,,+*,,-,+*+,,,,-+*+-..-+*,++*++,*+,+++,-*,+**+++--,-,+-,,-+,,,+,*,**,-,+++-++,--,+,*,+**++,++,++,,++++++,+,++,,-,+,,+,,-,,,++,-+++-,,+,,++,,+,++,++,,++-+,-,+)(&$#    "%'),./1121110101010//0001//010000/0110//1110/1120/.0/0111//012211000.////./000021/10.000011120000010/1101000/11100020/1110///0/////10010011/000/0110001111101001100///01000200/010011//00101101010001/.,*('$#!    #&&(*-/245777677666755655667755567766567665556765675654655688555666676564445545766676576466667767666665657767766577556676555655556555556775667756665666656566666766754455567665566566566745676667666655665420-+*&&&"  "%&(++-/3579:<<;;<<<;;<::;:;==<=;;;;<<<=<<<;;;;:;<<;;<:;:9;;:;==<<:;;:;<<:;::9<;9:<;;;<<<==;<===<<;;;==<<:;<<<<<<<<<<<:;<<<<;::;;;<;<<:<;;;<<:;;=<:;;<;;;;;:<:;;;;;=<;<::9::;<<;<;:;<<;;;<;<9;<<;<;<;;;;;;<;;:7530/,++($! "&)+-00259;<=?AA@@AAA@@A@???ABBABAAA@AAABAAAA@@@?AAA@@A@@A?BA@@ABBA?@@?@AAA@AA@A@@A@@@@ABBBBAABBBAA@@@BBAAA@AAAAAAAAAACAAAAAAAA@@@@A@AAAAAAAAA?@BBAA@@A@@@BB@A?@@@@@BA@A@@@?AAAA@BA@@AA@AAA@A?@AAAA@A@@BABAA@@?<:866300-)(#   %*.03568;<>ACEFFFGGGGGFFGEEEGHGFGGGFFFEFGFGFGFFFFGGFFFGFGGFHGFFFHHFEFFEGFGGGGGGFFGGFEEFFHHGGDFGHGFFEFFGGFFGFFFEFFFGFGGIHGFFFGGGGEEFFFFFHGGFGFFFGHGGGFFGFFGHHFGFEGGGFGFFFFFFFGFFGFGGEFEEFGFFFFEEFFGGFGFGHGHGFFFEC@=<<86420.)$ $*/3589;>@ACFHJJKLMLKLMKKLJKJLMKKKKJJLKIKLJLKKJJKLKKKLKLKLLKLKKKKMLJJKKJLKLKLLKLKLLKKIIKKLKKKIKLKKKKJKKKLJKLKJJJKKKKJKLMLKKKJLLLMJJJKKLKLMKKLKKKKLLLLKKKJKLLLJKKKKLLKLJKKJKKKLJJKKKJIKIJLMKJKJJJKKKKKKKLLLLLKKJJGDAA@=:9642-("  $).38;>>@CEFHKMOOPQQQQQRQPQPOOQRRRRQPOPPPPQPQPPOPPQPPRRQQQQQQQPPPPRPOPQQOQPQPQQOQPQPOQPPQRQPQQOPQPPPPPQQOQOPQPPONQPPPPOPPPPPPQPPQRQOOPOQQQQPPQPPPPPQQQQPPOPOPPOPQOOQQPQPQPOPPPQPPPPPOPQPOQRPQQQPPQOOPPOQQPQQQPONNLIGFEC@=:872,&! #)/27;60*&!   #'-37;@FIKLNPRUVXZ[]\[\\[[\Z[[\ZY\\[[]]ZZ\[Z[\\\\\\[[[[Z[]\]\\\\[[\[\[[Z]]\[[^]\[[[\[ZZ\\[[\]\\]\\[\[\[[\Z[[[\[\[[[\]\\[\[[[[[\]]]\Z[\[[\\][\]]][[Z[[[[]\\\[YZ\\\]][ZZ[\\\[[[\\[\]\\]\\\][[[[\\\\[[]\[Z[\[[\[]\]\ZXWURPPNMJGD>:5/*%   $(-28<@DJMPRSUXZZ\_`a``aa``a__`a`_aaa`ba``a`_`ba`aaa`````_aabaaaaaa``a``_aaa``cba```a`___```abaaaaa````aaa```aa``aaaabbaabbba``ababa`````baa`abaa``_````baab`_abaaaa___`a`a```aaaaa``aa`ab``````````aa`_`````aaaaa`]\ZWVUSQNKHB?:4.*$   !',16:@DHMPTWXZ\^_`deeddfdeeeddeeedfgfegffeffdefedfeeeddedeeffffffeedefefeeeeefffgedefeeedfffffffefeedecffgeeefffdffefefffegfeffeffffedeeegfeeffeeefefeeefffeeeggffeedeeeedeeeddfffeddeffefeddedddeefdeeeeefedfeedefcb`]\ZXUSPKGC>93-($  %+05:=CIMRVZ\^`bdefjkkiiljjjkljkkkjlmlklkkjkljkkjjlkkkiijjkkkkkkklkkjkkklljjkkllllkjkkklkkllkkkklkljjjihkllkkkllljkjjkjjkljlkkkkjkkllkikkkllkjkljkjlmlkkklkljklmlkkkkjkkkkikkkjikkkkjjjkkjkkijkiijjkljklkkjkkjkjkjkkjheca`^[YUOLHB>83.)"  ")/49>CGMQW[_adfgjlmorpopqqooprqppqqrrspqppopqoqqqoqrppppoorqpppppqpqqppqqqooppqqqqpqrpqqqqrqppppqqrppoooqqppqqqqqoppopoopqppppqpoppqrrpqrpqqqoprqqoqrqqrqqpqqqrrqpoppppppppqpqopqpopoppqpopqooqpppnprqrsrpoppqpopqppomjhfeda^ZTPLFA<83,& $,28=CIMRV\`dfhkmoqsuwvuvvvutuwvvvvvwwxvuvuuuvuwwwuuwuuvwuuwvuvvvvvuvwvuvvvuuuuuuvuuvwuvvvvwvuuvvvvwvvuuvwvuuwwvvuuvvuuutuvvvvvwuuvuvwwvvwvuuvttwwvtuuuvwvuvwvvwvvuuvvvvvvvvvuvuvwvuvuuwwutvvuuvvvutvwvwxwutuuvutvwvvtromljieb^XTPKE@<6/)" !&.4;AHLPVZ`dhkmprsuwz|{yzzz{zzz{{{z{{||{zzz{{{z{{{zy|{z{{||{zz{z{zzzz{|zzzz{zzz{z{z{z{{{{{|{{zz|zz{{|{{z{{{{{{{z{{{{{{{{yyz{{z{{zzzzz{|{z{{zzzzy{|zyzyzz|zz{|zz{z{{{{||{{{{{{zzz{{zz{zz{zyz{zzzz{{yy{{z{{{{z{z{{z{||{ywtqpomigc]WSOID?92+$#*18?FLQU[^cimpruwxz|~~|{wutrnmhb\WRNHB<6.'   &.5ELSZ`glpuz~xsmke^WNHB<3,$%,3:AHOV]cjpuy}xrnhaYRLE?6.&   "*074.% "*3FNW^fow}zskd[RJC81)  %.7@HOXaiqz}umf]TKC:3+" '/7@HOZcks|vog_ULD<3+" '/7@IP[ckt|wpi`XNF<2*" (19AKS]emu~ļypjaYPH=4-$  *2:BLT^fovȿzqjbZQH?6/%  "+3=DNV`gpxü|rjc[RH@8/' #,5?FNWahpzƿ}tlc\TJ?8/' $.8@GOXbiq{~vmd]UKA90' &0:AIQYcls|¹xoe^UMD;2(   (1;BJRZdmu|ûyof^VME=4+# "*3;BKS\dmw~Žyph_XOF?6-%  #+5GOV^goyɿ|skd[TKB90(  %.6>GOX_gozɿ|umd[SJB90(  %.5>FOW_hpz|umd[QIB90(  $.6=ENV_ipy}uldZQIB81) %.5FMU^hpx}umd[RKB90(  %-5>FNV^iqy~umd[SKA91)! $,4=FNU^ipz~tle[SKA92)! $,4HOW`iry}ukcZSJA91) %.6>GNWajry~wlbZRJB90( $-6>FNWaiqz}vlbZRJB90'  $-5>ENW_gqz}vmd[RKB91(  $-5>ENV^gqy¹}tme[SKA92*  $-6=FMV_gpx¹|skd[TKA82*  %.7>FNV_hpx|tke\SKB81*   %.6>GOW^gqy¸}ule\SLA70)  %.6>GOW^gqy¸~wme\ULA70(  $/7>GOW^gqy¸~wmd\ULB81( $.7>GOW^gpx~wmd[TLC:1(  #-7>GOW^hpxvlcZSLB:1)  #-7>FOW^ipyukcZSKA90)  $,6=FOW_ipz~ukc[SKA90(  $+5GPW_how}tlcZRKC91(  $-6>GPW_hpx}ukc[SKB90(  $,4=GOW`iqy}vlc\SKC:0)! $+4=FNV`ipz}uld\TJC:1)! $+4>FMW`hpz}tkd\TJC91)! #-5?FNX_hqz}ukc\SKB91(! #.6?GOX_hrz~uld[TKB:1)" $-7>GNX_gry}ume\SKC92)!  $-7=GMW_gpy}ume\SJB92)   $.6=FMW`goz~umd[TJA92)  %.6>FNX`foz~tlc[TKA81)  $,4>GOW_gqz~tlcZTLA80(  %,4?HOV_gpz~umdZTLA80) %-4?HOV_gpz¹~ume\TLA80) $-4?GOW`hqy~ume]TKB81)  $,5?GOWajrz}umd\SJC91)  #+5?GOW`irz}ume\UKB81*  #,5?GOW`hrz}ule\UKB81) $-5>GNWahpz|tkd\SJB80' %,6>FNXbhoy{tld\RIB90'  $-5>FMWahnx{umd\RJB80(! #-6>GMXahny|vme\RJC91)! $-6>GOXahpy}uke\RJC91)! %-5>GPXaiqx}tkd\SIB91)  &.6?FOX`hqx¸|tlc[SIB:0'  &-7?ENY`hqx¹|skdZRJC90'  %-7>FNY_hqxº|skdZRKC90'  $-7>GNW_hpxº|tlcZSKC91(  $-6>GNV`hoy|tlc[SJC92)  $,5>HOW_gpy~tkd[RJB92)  %,4>HOW`hqy~tld[RJC91(  &-5>HOWahqy~umd[RJC91(  &.6=GOWahpy}ume[RJB81)  %.6=FOY`hpz}tme[SJA81)  $-6=GPX`hq{}sld[TJA91)  $-6=GPW_hqz~slc[TJA90(  %-6>GOW_hqy~tlc[TJA90'  %-6?GOW_hqy~umc[TKB80(  $-5?HPX`ipx¸}vlcZSIB90( $+4=GOW_ipx¹}vmd[SI@80( $,4=FNV_ipx¹}vmd[RI@80' $-5>FNV`hpx}vmd[RJA81' $-5?GOW`hoy}ukd[TKB92( $+4=FOWahpz|ulc\RIB:2(  $+4=FOW`ipz|ukc\RIC:2) $,4=FOW`ipz|ukc[RJC80) $,4=GPW`hpz¸{tlcZSKC8/(  %-5=HPW`ipx¹|umd[SKC:0' &.6>GOW`hox~tld\RJB91( &.6>GOW`ipy~tld\RJB91)  %-5=GOW`iqy~tld\SKB91)  %-5>GNXahoy}uld[SKC91)  %-5?GNXahoz|ulc\TLC90)! %-6?GOXaipy|umd[TLB90)! %-6=GOXaipy|uld[TJA91)! %-5=GNWaipy|ukd\SIA92*! &-4>HPW`irz}vld\SIB:3*! %,5?HQY`ir{}uld\RJC:2)  $,6?GQY`irz}tkd\RKB:2(  #,7>GPX`iry}skd[SKB:1(  $-5>HOY`hqy|tlcZTLC:0( %-5?GOY`hq{}tlc[TLC91( $.5>FOX_hq|~tlcZSKB91( #.6=FNW_hq{~tlcZSKB91) #-6=FMW`hpz~tlcZSKB92)  $,5>GOW_goy~umd\SKB92(! $,5>GPX`gpz}uld\SKB81)! $-5=GPW`hpz|ukd[RJB80(! $-6=GPW`hpy|ukd[QIB90'  #-7>FPX_gqy}tkd\RJA91' $.7>FPX_gqz~umd\RJB91)  $-6=GOW_hqz}tldZSKB91)  %-5=GOW_iqz}uldZSKB91) %-5=GPW_ipz}vmd[SJB91) $-5GNV^ipx~tkcZSKA:2) $-4>GNV`ipx}tkcZSJA90(! %.4=FOW`ipx|ukdZSIA80(! &/5=FOW_hqy|tld[QIA80(  %/5=GPX_hqy}umd[QJB91) %-5=GQY_iry~ume\RKD91) %,4=GQY`iry~ule\TKD90( %,4>GPZaiqy}ume\TLD:0' $,6>GOWajqy|tmdZRJD:0( %,5>GNWajqy}tldZRJC90' %,4>GNWaiqy}tkdZRJC90' %-4>HOV`hqy}ukc[RIB:1' $,4>GOW`hrz}vld[SIA:1' $-5>FOX_iqy}uld\TKB;1' $-5?FOY_iry|ukd\TKB;0( $-5?GOY_hrz|ukd[SJB:0(   $-5?HPX_hqz}vmdZSIB90(! $-5?HPX_gqz}vmcZRJC90(  $,6?GOW_hqyº|uld[RJC90( $,6>GOW`hqx»|tke\RJC90(  %,6=FOWaipx»|tke\RJB91)! &-5FNV`irzȿ}tkd\SHA9/& %/7?GOW`iqy~ukd\SH@80( %.7?FNX`ipx~vld\RHA91) %.6>FNX_how~vle\SIA90) %.5>FOX_gnw~tle\TKA90)  %.6>GPX_how}tld\SKA91)! $-7?HPX_hqzɿ~umd\RIB:0(! %.6>HOW^gqzɿ~umd\RIB90(  %.6>GOV_gqzȿ}umd[RIB80( %,46/&  )0:CIPX`fmuz~wqibZTNF=5-$ '09AFMU\ckqw~{tof_WQLD;3,$  %.6>DJRY`ims{~xpkd\UOIA91+" $,4:@GOV]ejqw~ztmf`XQKE>6.(  "*28>EMT[biouz|wqkc]VOHA<4+&  (.5;AIPW]dlrv{|xsmha[TME>82)" $*18?EMTY_gmqv|~xsojd^XPIB;3.&    '.5GNTZ`ehmtx{~~|yvpje`[WQIB;5.(  !(.5;CKQUZ`ciotvy{~}{ywuqlea[VRLF?83+% $+28@GMPTZ_eknpsuxy{~~zxwusokfa]VQNHB<50(!  !'/582,$ $,28>DHLQV[acehjknpsuvvvvttvwutuuvwvvvvuvwvwwvuwvvvwvvuwvuvvvvvvvvuuvwvvvvwvvwwuvuuvvvvvuwxvwvwvvvwvwvwwwutvwwvvuuvvvvvwvvwuuvvxvvvuvvvvuvuuxwvvvvvuvwvwvwvvwwwxvvvwuuuvwwwvuuuvvvvwxuuwvwwvutuvwwvuuuvtwwwvuvuuuuwvutsqnligeb]YSNJD@;5.(!  "*05:?DHLQW\_acegilnopqrrpprsqpqqrrqqqrqrrqrqqqrrqrsrqrqqqrrssrqqqpqqqqqqqrqqqrqqqsrrrqrqrrrrrrqrrrrrqqrrpprsrrqpqrrrqqrqqqppqqsqqqqqqrqqqqqsrpqqqppqrrsqrqrssssrrqrrpprrqrqqqqrsqqrrpprrrrqpqpqrrrqqqqprqqqpqqqqprrponligec`]ZVOJFB<82+$  ',0684.'   "',17:4.*% $)-05<@DGKMNPRRUXZ\]\[[Z\[Z[[\\ZZ\[[[[\]\[Z[[[[[[[[\Z[Z[Z[[[ZZ[Z[\[[Y[]][[[\\\[Z[\\[Z[[[[\\[Z[[\ZZYZ[\[[[[\[Z[\Z[[[\]Z[\[ZZ[\\\[[[ZZ\\[[\\[\\[\[[\\\\\\\ZZZZZ[\[ZZ[[[ZZZ[[\\[[ZZ\\Z[][Z\]\\[[\[[\\[[[[[ZZZ[\Z[\[[\ZWUSQNMKHEA=84/*%   $)-28<@BFHIKMNPSUVXXWVVWVUVWWWUVWWVVVVWWWVVWUVVVUWWVVVUTVVVVVVVVWVVUWYXVVUVWVUVWVWVUWVVVWWVVVWVVUUVVVVVWWXWUWWVWVVWXVVWXVUVWWXVUWUTVVVWWWWWWWWVVVWXXWWVWWWVUVWVVUVVVVUVWVWVUUUUWWUVXVVWXVVXWXWWWWVVVWWUVVVWUUWXVWVSQNLIHFD@=840+'! $)-37;=BBCEHIKNPQRQQQQRQPQQQQPRRRQQQOPRSRQQPQQPPRRQQRPOQQRRQQQQQQQPRRRQQPPQQPQRQQPPPQQQRRQQQRQPOPRQRRRRQQRPPQRRQQRSQQRRQPQQRRQQSPPQQQPRRQQRPQQQQQRRQPPRRRRPQQQQPQRPQPQSQQQQPPPQQPQSQQQRQQSRRRRRRQQRRRQPQQRPPRSQQOMLIGECB@=:4/+'#   %)/369<<=>BDEHKLLKKKKLKLKKKKLLLLKLKKLLMMLKLLLJKLLKKLLJKLLMKKMKKKKLLLLLMKJKMKLLMKJLJKKKLLMKMNMKIJLLLLLKKKLKJKMLLLLMKKLKKLKKLKKMMJLMLKJLLKKLJJMKLKLLKJKLLLLLKKKMLLLJKKKMKKLMLJLKKLMMKKKLMMMLKLLNMLLLLLLJKMLKKLLLKIGFDA@><;860+'#  !%+/235789<@@AEFGGFFFGFFEFFFFGFFEFGGHEGGFFFFFFFEEFFGFFFFEFEEGEFEEFGGFFGEEFGGHGGFFFFGGFGGGFGHIGEDFFEEEDGFFFFGHGHHFFEFGEEFFGFEFGGEFGFFFEGFEEEDGGGGGFFFFGFEFFFEFGFFEFFGEFFEFHHFFFFFGGFFEEGGFEEEFHGFFEEGFFGGFGGGEFDEB@>;985420-(#  "'*,.01357:;=@AABA@ABA@@BBAAB@@@ABBBABAAAAAAAAA@ABBABAA@A@AA@BA@ABBAAB@AABBBBAAAAABBBBABAABCBA@@@A@@?BA@ABBCBCBABAAB@@ABB@@AAA@@AAAAABAAA@?ABBBBAAABBA@@AA@AA@AAABBAAA@ABBA@AAA@AAAAABABAAA@BBAA@ABAABAABBB???@=;96420.,*)%   "$')+-022467:<<=<<=<<<<<=<=<;<<<<<=;<;<=====<=<===<=<<=<<=;<==<==<=<===<;==<;<===>>=<=>=;<>==<=<<<<=>=<<<>><===>==<<<<=<<<<<<;=<<<<=<==<;;;<====<<=<===<;;<<;<==>>=<===<=<=<;;;;;<==>=<===<==<<<==<==<<=<<;:;;8632.,**)'$   ##%(+-,.014667667666667687677766756667788767777877668777667878868688866776567778976787668788866667887668878778776676766766677866776787666677887777888656766687887788867786566667788867876777667767777766656530.-)'$$#"   "$''(*+.01100100000002312221110/11121100120232101222110012111102331122000112121011010112311011011201112222222112011120/01220/201011111011123212222001212112112222312211011112221110121112110212022011201/.+(($"  !"$&&)+,,++,+++++++,,+,,,+++**+-,,++*+,-+-.-+++,,,,,+++,+*+++,--,,-,+++,--,,++,,*+**+,,+,++++*+,+++,,,,---,,,,*++,-+*++-,**,+,++++,,+,+*,--,-,,,*+,,+,++,+,,-+,-,-,+,,--,,,,,++,++,+++,,++,--+,,+,,,++*(%""   !""&'(('((('''&'('&&'('&&&%%&'('&%&'''''((''&''&'''''&&%&'''(''&''((''((&&'(('&&&&'&&&'&&&'%&'&&&('''('('&'(&'&&&'''&((%%'&&&'&''&'('&('''((''&'((&&&&''&''&'((((&''(('('&'%%'&&&&&'((&''(('('''&&''&#   !"##"##$"""!"""!!"#"!! !! !""" !"!""""#""!!!!""""" ! !"""#! !"##""""!!"#""!!!!"!!!"!! " "" !#"!!#!""!!#!" "!"#"!#" "!!!"!"" """"#!!!##""!""#!!!!"" "!!!"###!!"##""" ! !!!!!!"#"!"!"""#""" !"!                                      deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/menufog.lmp0000644000175000017500000001000011357170242024555 0ustar keeskees99!,,EE999JRjjJ9EE^^JE9,!,!+)ajrrrjJRE9,!!!!,,!!,E,!!!!!99J^j^JJ9Jj^JE,,,,!%Jcsrr^^J9,!!,!!!,99EJRE!!9EJjjjRR^rRJD)()!%8Mi~rRJE!,E!!9Jj^9!9J^r^I3!!!%-;`r^RE!!9JJ!JrJ!!!,JjrrjD4! 1>]j^J9!E^^99jrjE9,9,,9ERrjP4#!'#=Jqrjrj^J9!JrE,JJj^^RJRJJEJ^rZ= 3LLk}rjrr^^E!,JJ!!,,JRj^jjRREJj`8%%DuȯŨrrjJ9!,!9JJ999!!!9J^jjrjRR^jiP0 +Yĵj^E99E^rRJRJ9!!EJRrjj^^^j͹~`P3/^}j^RR^rjRJ^RJ,!,,,EJ^^^^j^rvT,>enifeif]T^rj^omo^JRR^RE,REEEJRR^jrr{PayeRIENQE;Dir^Re{qQEER^r^Rj^RJJRJjraE=>HJE9>Nw}rJJEZuZE9E^jRRR^jXD@P``UB>PZ\j^^J,!,YrmN999J^rj^RRRjurJ>HgwYIDIDEE9!!>n~`>,,9EJ^RjRRRJJRrȫrrrr^NZP54Hw˗iFA>8!!)NnN3!!,99EE9EE9999ER{˵^R^^^L484%'RkLE8,!)bfb@,!,!,,,,!!!!!,,9Jmȳj^JRRc3,9EE,9^wr{fcirU/@N`VU]mZ%$@gq]5,9EE99!!Rrwwecoz>)!EaRVYms;09emN3/49E9JJE,!!9j}~aD!9QicVkwgcfifH7;f{{reQ>)9ALU^ZYRJE9J{şuRJJ^gn`{^LEEA@P^^YTPUr~j^^jyqmR@58/7AFZw̷{VMacr7 $'0=EFELV`nriky˼jjjrrjj^RQA4,1=879LnϣjPIby<$(,3'/Qc]MBJuR7Fc}k\QJII>;qw^F@7DFHUgLABHfrr^RE;/!(Mm{wmTNi`>';joTB;DEFcsZNL\\wzwj^^jrrrj^Q>0 )MfgU7(=`fa@0-BnnjVF43Jsk]^X\JQbjJ9,,,J^rrrj^L5'#580)'4DJ@408ArjE($1^yzfXaJ99EJrrrjE,!Jjrj]P,#>HMLH98<>7Pnz{}{rM(-F^QQJE,,9E^r^J9!!EjU' 7YwniQB589)-DY`jooT((99JE9,,9^rRE!!,Js>#!4IjjJ9!99'!>I\afQ+3EJRJ,,,Jr^E,9,,,9JrjjoE-(+YsjRE99Rrj^RRJRR99EjjJD4@@L]^^J99JV5(4HJPUfzjRE9E^rjRRR^JRr^jRE!!,Rr^JJEEJJRrrjRJ^gN0P\i}jJ99Jj^RRJR^RJRrrRR9EE!!!,Jj^^JJJJJjrrg, 5Ii{mYJE^rjRJJRRJ9JR^^^R9,!!,!!!,JrrjRREJ^F-IzoaX^jjREJJRE!,9EE,!!,,!!!E^rj^rjRJJ^rͼs3Iٱkjnuor^RR^jR!!!,9,!!,9E,,J^r^JJ^^̪`;#YjY^kj^jjE,EE,,!!!EjjJJJRj͹g<Zͧz`R^wrrr^,EEE,,!,,!!RrRJEE^rU#PÜs\Ve~^^jjE!,EEE,9999!!ErJJEEERrU)Akk}rJJRj^E!!,JJE99EJ9,!^jJJEE9J^jrjoveM- AjE,9Rjj^J,!!^^^RJRRE!9JJRJJJJ^jj^c^IA7+9R^J!!,9E999!,jrjjrR,!!9JRJRR^rjrjLHADNLUbjJ,9RJ,!E^jrR!,ERRRRRjrjM5H`eVNXanrzsrqyjJ,9JJ9!,JJRj^,,J^^JEJ^jjjI7TiaMIJNIJUPM>>\<<<<<<<<===========>>>\<<<<<<===========>>>>\\<<<<<==========>>>>>>\\]]<<<==========>>>>>>>]]]]]<==========>>>>>>>>]]]]]==========>>>>>>>333]]]]]]]=======>>>>>>>>33333]]]]]]]======>>>>>>>>3333333]]]]]]]=====>>>>>>>33333333]]]]^^^^==1>>>>>>2333333333]]^^^^^^^111>222223333333333^^^^^^^^^12222222333333333^^^^^^^^^22222223333333333^^^^^^^^^222233333333333^^^^^^^^^233333333333^^^^^^^^^3333333333^^^^^^^^^33333333^^^^^^^^^333333^^^^^^^^^^^^^^^^^^^^^^^^^^ŲŲŲųųųųƳƳƳƳƳƳƳƳƳƳƳƳƴƴƴƴƴƴƴƴƴƴƴƴɴ=ɴ====ɴ======ɵ=========ɵ==========ɵ<===========ɵ<<<<<============ʵ<<<<<<<============>ʵ<<<<<<<============>>ʵ<<<<<<<<============>>>ʵ<<<<<<<<============>>>><<<<<<<<===========>>>>>><<<<<<<===========>>>>>>><<<<<<===========>>>>>>>\<<<<===========>>>>>>>\]<<<==========>>>>>>>>>]]]]<==========>>>>>>>>>]]]]=========>>>>>>>>>]]]]========>>>>>>>>>>]]]]]======>>>>>>>>>>>3]]]]]====>>>>>>>>>>3333]]^^^^===>>>>>>>>>>33333^^^^^^^=>>>>>>>>>>333333^^^^^^^^>>>>>>>>>3333333^^^^^^^^>>>>>>>>33333333^^^^^^^^>>>>>333333333^^^^^^^^>3333333333^^^^^^^^333333333^^^^^^^^3333333^^^^^^^^33333^^^^^^^^^^^^^^^^^^^^^^^AA^^^^^^ŭŭųųƳƳƳƳƳƳƳƳƳƳƳƳƴƴƴƴƴƴƴƴƴƴƴƴƴȴȴɴɴɵ==ɵ=====ɵ=======ɵ========>>ɵ=========>>>>ʵ=========>>>>>>ʵ=========>>>>>>ʵ==========>>>>>>ʵ<==========>>>>>>><<<<==========>>>>>>>><<<<<===========>>>>>>>><<<===========>>>>>>>>><<===========>>>>>>>>>]]==========>>>>>>>>>>]]=========>>>>>>>>>>>]]========>>>>>>>>>>>]]======>>>>>>>>>>>???]]]====>>>>>>>>>>>>???^^^^==>>>>>>>>>>>>????^^^^=>>>>>>>>>>>>????^^^^^>>>>>>>>>>>>?????^^^^^^^>>>>>>>>>>>?????^^^^^^^^>>>>>>>>>3?????^^^^^^^^>>>>333????^^^^^^^^>3333????^^^^^^^333???^^^^^^^33???^^^^^^^^^^^^^A^^^^^^AA ^^^^AA ^^^ŭƭƭƭƳƳƳƳƳƳƳƳƳƳƴƴƴƴƴƴƴƴƴƴƴƴƴƴȴȴȴɴɵɵɵ=ɵ====ɵ=====>>ɵ=====>>>>ʵ=====>>>>>>>ʵ=====>>>>>>>>ʵ======>>>>>>>>ʶ=======>>>>>>>>ʶ======>>>>>>>>>>ʶ=======>>>>>>>>>>ʶ========>>>>>>>>>>ʶ========>>>>>>>>>>>??]˶========>>>>>>>>>>>>??]=======>>>>>>>>>>>>???]======>>>>>>>>>>>>???====>>>>>>>>>>>>????^^==>>>>>>>>>>>>>????^^^=>>>>>>>>>>>>>?????^^^^>>>>>>>>>>>>?????^^^^^>>>>>>>>>>>??????^^^^^^>>>>>>>>>>??????^^^^^^>>>>>>>???????^^^^^^>>>>???????^^^^^^???????^^^^??????^^^^???A^^^AA^^^AA ^AA AA !!ƭƭƭƭƭƭƳƳƳƳƳƴƴƴƴƴƴƴƴƴƴƴƴƴƴƴȴȴȴȴȵɵɵɵɵɵɵ=>>ɵ==>>>>ʵ=>>>>>>>>ʵ==>>>>>>>>>ʶ==>>>>>>>>>>ʶ===>>>>>>>>>>??ʶ===>>>>>>>>>>>??ʶ===>>>>>>>>>>>???ʶ====>>>>>>>>>>>???ʶ====>>>>>>>>>>>????˶====>>>>>>>>>>>>????=====>>>>>>>>>>>>?????====>>>>>>>>>>>>?????===>>>>>>>>>>>>??????^>>>>>>>>>>>>>??????^^>>>>>>>>>>>>???????^^^>>>>>>>>>>>???????^^^>>>>>>>>>>???????^^^>>>>>>>>????????^^^>>>>????????^^^>????????^^???????^^?????AA^AA AA AA AA !!AA !!!!ƭƭƭƭƭƭƭƭƭƴƴƴƴƴƴƴƴƴƴƴƴƴƴƴƴȴȴȴȵȵȵɵɵɵɵɵɵɵ>ʵ>>>>>ʶ>>>>>>>>ʶ>>>>>>>>>???ʶ>>>>>>>>>>????ʶ>>>>>>>>>>????ʶ>>>>>>>>>>>?????ʶ>>>>>>>>>>>?????ʶ=>>>>>>>>>>>??????˶>>>>>>>>>>>>??????@˶=>>>>>>>>>>>>???????@==>>>>>>>>>>>>???????@=>>>>>>>>>>>>???????@>>>>>>>>>>>>????????@>>>>>>>>>>????????@^>>>>>>>>>????????@^>>>>>>>>?????????@^>>>>>?????????@^>?????????@???????@A??????@AA ?@AA AA AA AA !!AA !!!!AA !!!!!ƭƭƭƭƭƭƭƭƭƴƴƴƴƴƴƴƴƴƴƴǴƴǴǴȴȴȵȵȵȵȵɵɵɵɵɵɵɵʵʶ>>ʶ>>>>???ʶ>>>>?????ʶ>>>>>?????@ʶ>>>>>>??????@@ʶ>>>>>>>??????@@@ʶ>>>>>>>>??????@@@@˶>>>>>>>>>??????@@@@@˶>>>>>>>>>>???????@@@@@˶>>>>>>>>>>???????@@@@@@˷>>>>>>>>>>>???????@@@@@@>>>>>>>>>>>???????@@@@@@>>>>>>>>>>????????@@@@@>>>>>>>>>????????@@@@@>>>>>>????????@@@@@>>>????????@@@@@?????????@@@@A??????@@@@AA ????@@@@AA @@AA AA AA !!AA !!!!AA !!!!!A !!!!!!ƭƭƭƭƭƭƭƭƭƭƴƴƴǴǴǴǴǴǴǴǴǴǴǴȴȵȵȵȵȵȵɵɵɵɵɵɵɵʶʶʶ??ʶ?????@ʶ??????@@ʶ??????@@@ʶ>??????@@@@ʶ>>???????@@@@˶>>???????@@@@@@˶>>>???????@@@@@@@˷>>>>???????@@@@@@@˷>>>>>????????@@@@@@˷>>>>>>????????@@@@@@˷>>>>>>>????????@@@@@@>>>>>>>????????@@@@@@>>>?????????@@@@@?????????@@@@@A???????@@@@@AA ????@@@@@AA @@@@AA AA AA !!AA !!!!AA !!!!!A !!!!!! !!!!!!"ƭƭƭƭƭƭƭƭƭǭǴǴǴǴǴǴǴǴǴǴǴǴǵǵȵȵȵȵȵȵȵɵɵɵɵɵɶɶʶʶʶʶ???ʶ???@@@ʶ?????@@@ʶ?????@@@@@ʶ?????@@@@@@˶?????@@@@@@@˶???????@@@@@@@˷???????@@@@@@@@˷???????@@@@@@@@˷????????@@@@@@@@˷?????????@@@@@@@Ϸ>?????????@@@@@@@>?????????@@@@@@@A???????@@@@@@@AA ??????@@@@@@AA ??@@@@@@AA @@@AA AA !!AA !!!!AA !!!!!A !!!!!! !!!!!!" !!!!!!""ƭƭƭƭƭƭƭǭǭǮǮǮǴǴǴǴǴǴǵǵǵǵǵǵȵȵȵȵȵȵȵɵɵɵɵɵɶɶʶʶʶʶʶ??@@@@ʶ??@@@@@ʶ??@@@@@@ʶ????@@@@@@˶????@@@@@@@˷????@@@@@@@@˷?????@@@@@@@@@˷??????@@@@@@@@˷??????@@@@@@@@˷???????@@@@@@@@Ϸ???????@@@@@@@@A????????@@@@@@@AA ??????@@@@@@@AA ???@@@@@@@AA @@@@@AA @@AA !!AA !!!!AA !!!!!A !!!!!! !!!!!!" !!!!!!"" !!!!!!"""ƭƭƭƭƭƭǭǮǮǮǮǮǮǮǮǵǵǵǵǵǵǵǵǵȵȵȵȵȵȵȵɵɵɵɶɶɶɶʶʶʶʶʶ@@@@ʶ@@@@ʶ@@@@@ʶ@@@@@@˷@@@@@@@˷?@@@@@@@@˷?@@@@@@@@@˷??@@@@@@@@˷???@@@@@@@@˷????@@@@@@@@AϷ????@@@@@@@@AA Ϸ??????@@@@@@@@AA ????@@@@@@@@AA @@@@@@@AA @@@@AA !!AA !!!!AA !!!!!AA !!!!!! !!!!!!" !!!!!!"" !!!!!!"""!!!!!!""""ƭƭƭƭƮǮǮǮǮǮǮǮǮǮǮǵǵǵǵǵǵǵǵǵȵȵȵȵȵȵȵɵɵɶɶɶɶɶʶʶʶʶʶʶ@ʶ@@@ʶ@@@@˷@@@@@˷@@@@˷@@@@˷@@@@˷@@@@A˷@@@@AA Ϸ@@@@AA Ϸ@@@AA ϸ@@@AA и@@@AA !!@AA !!!!AA !!!!!AA !!!!!! !!!!!!" !!!!!!"" !!!!!!"""!!!!!!""""!!!!!"""""ƭƭƮƮǮǮǮǮǮǮǮǮǮǮǮǯǵǵǵǵǵǵǵǵȵȵȵȵȵȵȵɵɶɶɶɶɶɶʶʶʶʶʶʶʶʷ@˷@˷@˷@˷@A˷@AA ˷@AA ϷAA ϸAA ϸAA !!ϸAA !!!!AA !!!!!AA !!!!!! !!!!!!" !!!!!!"" !!!!!!""" !!!!!!""""!!!!!"""""!!!!""""""ƮƮƮǮǮǮǮǮǮǮǮǮǮǮǮǯǵǵǵǵǵǵǵǵȵȵȵȵȵȵȵɶɶɶɶɶɶɶʶʶʶʶʶʶʷʷ˷˷˷A˷AA ˷AA ϷAA ϷAA ϸAA !!ϸAA !!!!ϸAA !!!!!иAA !!!!!!A !!!!!!" !!!!!!"" !!!!!!""" !!!!!!""""!!!!!"""""!!!!""""""!!!"""""""ƮƮǮǮǮǮǮǮǮǮǮǮǮǮǯǯǯǯǵǵǵǵǵǵȵȵȵȵȵȶȶɶɶɶɶɶɶɶʶʶʶʶʶʷʷʷ˷˷˷ ˷ ˷ Ϸ Ϸ !!ϸ !!!!ϸ !!!!!ϸ !!!!!!и !!!!!!" !!!!!!"" !!!!!!""" !!!!!!""""!!!!!!"""""!!!!""""""!!!"""""""!!"""""""#ƮǮǮǮǮǮǮǮǮǮǮǮǮǯǯǯǯǯǯǵǵǵǵǵȵȵȵȶȶȶȶɶɶɶɶɶɶɶʶʶʶʶʶʷʷʷ˷˷˷˷ ˷ Ϸ !!ϸ !!!!ϸ !!!!!ϸ !!!!!!ϸ !!!!!!"и !!!!!!"" !!!!!!""" !!!!!!""""!!!!!!"""""!!!!""""""!!!"""""""!!"""""""#"""""""##deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/data/lumps/e2endpcx.lmp0000644000175000017500000017323211357170242024646 0ustar keeskees ? (Td (Xh$P\Phlx(t$Dl$8X \|(,p@堾Y ݲ݈Ĉ݉Yɠò݈SɠݲĈ¾YɉeيҒ‰ŲS¾ɠْ݈݉’݉ŲSľ݉¾Y™ٯeييي‰DzSľ YԊŠԊDzSþYˆ݉Y²يҊYƲS¾eǾYݲYYYŠْ‰ŲSÒľˆɠþ YeԊYYŲSԒ’ľY ɠþYYY™҉ъԴҠƲSSe’ľY þľY YYڲ뒊YҠŲS²벉’ƾɉ¾ľ‰ҠYYYŲSòŒǾþ¾YĉɠY¾¶ԒԒԒYYҙƲSòԉÒľY ݈þ¾‰݉ Y¾Yҙկ|’Ғ堙YŲSòԊÒ¾YYɉþYĉYQdY´̱||ҒԒڥڲԊҙYYYݲ²S²’¾YþľþY‰ɠɉvնԊð’YYYY²Sݲ’ƾľ¾Y‰ɠɉ¾荶Չ̯’ àYYҙ²òS̰əɉǾɾþYĠ¾Ɋٴي㊲ڲ㲉ҒYĠYYҙò݈ҒݲƾYݲ°GþYҠTGɠTv°¾Ѯ|ҊڲS ҙYYÙYҲòƾ ˆݰGGQTQ ɉvvTv|ԊSْàY™Y²ݲڲ㉲žYĈ݈ݲQ¾TvvT㙾¾󙠙Š’Y™ҙݲݲQdǾĈǾYҠL™LvÙѯ㲰D²ҒɈY¾Y™ҾY²ɲQTvTvdǾĈݲɾY ɉYҥٮݼڲ҉Y™YݲԴڲ²ǾĈTv¾ھ¾YY ɠɠYàYQ|ݲSTYYҠ݉™¾™Ҋ¯žQTvTݲT݈ɠGv¾YY ĠYYڰڍ㈲݉DҒYY™Y™ҒB¼̰݉’YþYTv ˆˆ¾ҥYҠ Y̯QsTҾYþYQYɉڮ¨ð²Q^TžTˆ݈ǾYvTҠɉY¾QъD²̲YYQBQ‰YÙQμ̰²dTQdQ GLvTTȾYTvT Éɾ񍰮²²ݲ²¾QÉYԊQ̯ڲ²ɉݲd^QTGTvɲsssvvȾYààYï҉SsDYY¾ѯQɉþ¯v²㲠dQ뉥QĈ¾ĈȾYǠY D|ݲòDDYYYBDYɉYþ‰d’?BïT²S²Y뒠YQƾYˆ ĈƾYĠYY |v||ХډSòD?s²Y¾QYɉ¾É@e¶ŠTüڲݲSݠY|^TvTv˾YňƾY™YYկݲݲYSTs²YҥY‰¾™É㉊¶௮v²ݲݲ’YQddY˾ÙǾYYYYЮQ҉ݲS²SD²D¾Y̯QYݠɾ݉|Íö°¯ѯ’;șƾ¾|›ɉݲ݉SSSɉD¾YүگQdYY|Ͷ벰Dڰگ²’;YǙþٰ| ²SsSdYY™Y|™YY‰‰|dĶ̯ÖҠ’ξYǙƙڲ݈SYÙYY Y?Y ¾ɉ݉‰|dŶÒ˾̙¾ѥɉY㈉²?ԙY™Y YDڶɠ‰||эd͉‰Tگ̲Òƙ¾þęșƾÙS?sQSԒYYYYѥɠY‰ĉ||эdŶ‰݉Tv݉噾șΙęڰ҉Sݠ݉s?DsYYY¾YDYƉ||dĶ݉݉B–?ð҉ݲ݉’™ęǙҠڲ벥ѮSYÙYY¾ə݉||d͉ìİïò݉ݲÙ㉲ᶍ|^~]K]|݉Y Y™™Q¾҉‰É||ѥQd¶‰‰TɠҒęկü?LK^w^KM3b7b]TYà™əҙ|Qd¶‰‰݉گگ²řɉ?Tw^]M%E3787M%Yү̯Ù|ѥQd¶݉‰҉SYIJ݉ƙƙ (JbGYD̥ðT~]Mb²T^%3bMw|YÙeҙ噥|ѥQdQ¶̼گðSݲڲęǙQTvG 2.2.2A4;pҠDssïİT^wb]Ss¤%E9K]wҠYگٯÙe||ѥQdöయ@‰™ٶѮKbOJO(;2. A2CfpHBssư^|^]^s^¤v%EL~^|ٙe™||ѥddQ¶يךŮӳŮ|²ԒҙGz E&8O-J(4 A2.2.(-cn}a̯¯s°^]Ts^vGLvҒeęeÙeÙ|||¥dö׳Tv^’ԊǒĒŒ™̏85n5n]395g})xf`CJ22.A iIfIxn}n}xwGvss̯sЍ~TsîvTv?@‰ ɠ¯eҴÙ|э||¥ddQ¶@v^ĤvŠْ’TK8 E93K}©p)fCRO( (2A cIcZiRZ}m}w%Gv̯s̍~ssSs|ЮT°T@™´Ùѥ¥dQ¶يگڲѰ^¤~vQÒѤKMb3 5gmӇćf A;AC2`(;4iRZRZRiRf}]%wL%LGvss²Ssð¥|Ű?ҙҙɠْeэådQ¶ҴگگsѮ^¤~GQQQ|am}}388bM]}ap- J(>A`(5J;(-f}uci\XNUXOM]%w%wGvT̯s²sگṴ̋De||ådöԊ¯¯B̯گš^¤w~QQگQQ|†aa}KM]گ®-4C; >A(f!ީxZiXO/niXU0> 8b]wGTDs²sگðD°̯sٴ‰Դïэ|ådQ¶¯^|^~Gw~ŠQ˯Qᶳ-f4Aqއ‡pZ\NiIni;0>A> ;b]wG~^|ssSگD°̯̯s´يe¯¯|¥d@گs³䮬Į~Gw|QįB¯Q¶^¯T¼›v›Ť!-JpCR(; -)(>;쇋ZN4Ofxb;A> 8]w}~^sڲ¯sDsů̯D¯گeээ¥dQگ̯淋ћ¤~GwG^گ¥¶資Ç<^°TȼTĮ^ÛxCpfCJ(--;4|쇘Z(4(`! >0 8f}w~vTss̯¯D̯e@گčÍd̯¯v~Gw~|ٴeĥᶳ›ЮTļT°î^›)Hp!f-C)-()Ѯ|ڰީC(4;CgA0>0OK]w}~sگ±DگԴ|ōэd¥¯ů¯וּvGw^›T¼T|ƮHH)xfHf-)®Ѷo|հа³`(JgA0UNK}w~گ¯կDD??DBįe@̯Q|ээ|эե°گ̯į¯ΪTvGwŶô퇆¼v|î|Ů½޽px)ѮХQaаg( Jg >0UNK}w~گ@?DDD??DįմeöQï¥|||¥ï̯گ¯ﵧмv¤~wGٴe퇆±ЮĮîކ‡ކpѥQa'ήðmJ J}*4>0UNKw~@Ֆ?¯DBB̯B¯̯ٴ̯¯Qï¯ïį|dÍэĥį̯וּTvä~Ge޽¯¯TîЮгކ퇽Hѥo|мpJ4O}C4UX7]w~¤@?BՊBǯ¯̯Båǯ±ïگ¥dč|ĥ̥¯̯̯կtüv¤~Geï̯̰®Tr<м®ai4O}cXUXcm~@?կDḆٯBگ̯گůձB¯گ¯ڴdč|б襰̰LTvä~Ԋ¯̯|sTЮ|އگն—rRX\uI\Nc‹m~¯ٴگǯBïįįگڶeÍİDZwڰv^¤~׮ۚïįsð||їrrбÖHZNi½Ha~¤诱eį̱گ̯¯ȯگ¥e"ð̯ڰvä̯±ñS°į|orŗ|μjumņ~կeeïBӳ¯¯¯į¥de´б襰±'±D̯^ڰ¤0UXN\RF/IuHu…ÿî`5Vš¬ŨĨ•Ӻq)p-Ob۽‡‡øø Ƴ³mÚ<šHL½۷ۘ6½˜‹fZi0>A ;NO\RF/Inunu6¿ÿۚ95Vl­εµĹ۩n\3¸Ÿó³ӳaĚý­۽͕ۺH˜ucRiRi\UX(J-\ON\RF/nH̑Ñ5VlĵĨǘZǺӇǸ£ 򭘽HiIN/q͵Īϕ,؇©ޅŷu*ގH#-Vۘl_¸ܳÅ+ؓŹەynXI޿WªŧĪۧ©޷¿÷=qV޿6x3LJ•ީ»ܳ++̀R͹§ê­‡ÿ·WºV¿)VƇܳܳ+ŹߓꕬIuۺĕ͵êª,ؽÿ==W§¿,‡Ӹ¿Ͽ¬µêϪ,퇺=ǺW§lꦷl=_l͕죓û۬½‹˜…lWêWª,,‡؇쭃=lºǺ=ۦ۽Ş©¸+ߓqEx}uqۺϬWŵêŵ,؇!6·Ǻ=º¿p)f!ޞ5,++潚ºqgxf`xuǑޑđ:¡Ϭ͹µªǹž,➭*n·WǷŽÌZR`ޞbF6¿_¸­g}x}xfx}gH½đͬϹõެW,ž,žȭgxJR#•l¿6/9`8Fn‹‡_¸¸ۺğ}ggqºǑѕǹ§ެ,žȞ,5)6COJfugl¿Ǻ޽©q!`5}؇‡ؓ_øƸĸϺqő‘:q:•Ϲ۬,,ОȞ`pnq޿•pfZ-JON&&9ĸɸ_++ޑÑq:ŬW•¬Ǖ➻ǞȞ‘3nŒ:‘=ۿ6)u#unF\X0>9Çĸ_ ¦++‘qϹ•¬͕؞žĞ꿑۔JFu=WŽŽuF\N4&9ž_¸ ߓ ߦⓦŹ++lq:ϕ•¬•ǞȞžW38\F#¿lŽ‘¿·Œ/FO&ߓ “ ߓ Ź+Ƹ̓V‘޸ǸǺq•ǹ•ŕ,žȞ,➻ȞVu*&;i/#6pf#ێ¦÷¿Ž#I-3,ó ߻ ¸!V‘ǸWǹÕW¹޿ÞȻȿ5Z`C`x)9i#·¦ 6u/39x*`ž,޳ ߓ ¸+ŨglŹĹŹ޿“ȞqHûȻ!bi#÷· 귿#5q6f-V,޳ߓ ߻ +++żWlŹ¹Ź‘Óž,ûȞȞgf)ꦷ æ =··Žpu,, ͸WW޸ޑ޿ÿûߓ“Þ,»,ȻÑ· WBǷ÷:VW,, __++WW»»⻓û,ĻȻѦæǺW§W=Ƿ÷VǦ=, _ Ǹ³‘‘û⓻žûȻȻž‘Ħ͹•BŷWl ·ׇ»_ _¸ӳļÑ޿¿đĻȻƞ‘‘ꦷ=W=Ǻķ=¦ ߻ _ ¦¦­ŝő‘Ñ‘»ž➻ۑ‘ꦷ=Ƿ=Wꦷ,߻ž¸¦ Ǹ޿ő‘őû“Ş⻞Ȟ꺿đ¦=W q·¦ߞ߻ߞߞއ‘‘đ‘Ñ»ēƻĞȻ:‘¦=WǷ¦`u·Ħ߻ ⻞¿đÑőđ»“Ȼ꡺=W•Ƿ¦:9-u ߞ,û ޿Ñđ‘ÑȻûߓœ:‘·Wͺ۷ꦷ q`x!p ߦ؇ߞȻ »‡؞޿ǑÑÿ꩑û“ÓœÓ۔qǷĦ· æ ؇ߞ,Ȼ޿ȑ‘޷·iJ`Ļ ߓē ,lVq۷æqq ߻޿Ñő‘·FO3ûÓ ➻Ş`u¿#u/O&9 ߦߓ ž¦ ޿Ñő‘¿6`g»Ȼ““ߓ ēߓ؞*/n¿·#F3 ߦߓ ‡žŦ߻‘őÑȻߦ ߓV b-/uŽ¿Î6pߓ ؇Ȟߦ ¦ ¦ ¦ÑߦȻ⑃3JRFI6ŽŽqVW¦“_ _ŦȞ¦Ʀ ¦ ‘¿‘ꑿ ⻓ē»g8&OiFn#6q=·ߓĦøɦž ¦¦ ¦  TD4@\hhh $Dl`hp,\4@`$0Ll,X(L *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.c: Random number LUT. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static int rndIndex = 0; static int prndIndex = 0; // Returns a 0-255 number static unsigned char rndTable[256] = { 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36, 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242, 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0, 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235, 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113, 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75, 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196, 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113, 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241, 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224, 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226, 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136, 120, 163, 236, 249 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * \note The returned value is calculated deterministically. * * @return A pseudo-random number from the table. */ byte P_Random(void) { prndIndex = (prndIndex + 1) & 0xff; return rndTable[prndIndex]; } /** * \note The returned value is NOT calculated deterministically. * * @return A pseudo-random number from the table. */ byte M_Random(void) { rndIndex = (rndIndex + 1) & 0xff; return rndTable[rndIndex]; } /** * Resets the seed for the random number generator. */ void M_ResetRandom(void) { rndIndex = prndIndex = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/tables.c0000644000175000017500000042273411357170242022564 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * tables.c: Lookup tables. * * In the order of appearance: * * int finetangent[4096] - Tangens LUT. * Should work with BAM fairly well (12 of 16bit, effectively, by shifting). * * int finesine[10240] - Sine lookup. * Guess what, serves as cosine, too. * Remarkable thing is, how to use BAMs with this? * * int tantoangle[2049] - ArcTan LUT, * maps tan(angle) to angle fast. Gotta search. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // finecosine and finesine use the same array of values. fixed_t *finecosine = &finesine[FINEANGLES / 4]; int finetangent[4096] = { -170910304, -56965752, -34178904, -24413316, -18988036, -15535599, -13145455, -11392683, -10052327, -8994149, -8137527, -7429880, -6835455, -6329090, -5892567, -5512368, -5178251, -4882318, -4618375, -4381502, -4167737, -3973855, -3797206, -3635590, -3487165, -3350381, -3223918, -3106651, -2997613, -2895966, -2800983, -2712030, -2628549, -2550052, -2476104, -2406322, -2340362, -2277919, -2218719, -2162516, -2109087, -2058233, -2009771, -1963536, -1919378, -1877161, -1836758, -1798063, -1760956, -1725348, -1691149, -1658278, -1626658, -1596220, -1566898, -1538632, -1511367, -1485049, -1459630, -1435065, -1411312, -1388330, -1366084, -1344537, -1323658, -1303416, -1283783, -1264730, -1246234, -1228269, -1210813, -1193846, -1177345, -1161294, -1145673, -1130465, -1115654, -1101225, -1087164, -1073455, -1060087, -1047046, -1034322, -1021901, -1009774, -997931, -986361, -975054, -964003, -953199, -942633, -932298, -922186, -912289, -902602, -893117, -883829, -874730, -865817, -857081, -848520, -840127, -831898, -823827, -815910, -808143, -800521, -793041, -785699, -778490, -771411, -764460, -757631, -750922, -744331, -737853, -731486, -725227, -719074, -713023, -707072, -701219, -695462, -689797, -684223, -678737, -673338, -668024, -662792, -657640, -652568, -647572, -642651, -637803, -633028, -628323, -623686, -619117, -614613, -610174, -605798, -601483, -597229, -593033, -588896, -584815, -580789, -576818, -572901, -569035, -565221, -561456, -557741, -554074, -550455, -546881, -543354, -539870, -536431, -533034, -529680, -526366, -523094, -519861, -516667, -513512, -510394, -507313, -504269, -501261, -498287, -495348, -492443, -489571, -486732, -483925, -481150, -478406, -475692, -473009, -470355, -467730, -465133, -462565, -460024, -457511, -455024, -452564, -450129, -447720, -445337, -442978, -440643, -438332, -436045, -433781, -431540, -429321, -427125, -424951, -422798, -420666, -418555, -416465, -414395, -412344, -410314, -408303, -406311, -404338, -402384, -400448, -398530, -396630, -394747, -392882, -391034, -389202, -387387, -385589, -383807, -382040, -380290, -378555, -376835, -375130, -373440, -371765, -370105, -368459, -366826, -365208, -363604, -362013, -360436, -358872, -357321, -355783, -354257, -352744, -351244, -349756, -348280, -346816, -345364, -343924, -342495, -341078, -339671, -338276, -336892, -335519, -334157, -332805, -331464, -330133, -328812, -327502, -326201, -324910, -323629, -322358, -321097, -319844, -318601, -317368, -316143, -314928, -313721, -312524, -311335, -310154, -308983, -307819, -306664, -305517, -304379, -303248, -302126, -301011, -299904, -298805, -297714, -296630, -295554, -294485, -293423, -292369, -291322, -290282, -289249, -288223, -287204, -286192, -285186, -284188, -283195, -282210, -281231, -280258, -279292, -278332, -277378, -276430, -275489, -274553, -273624, -272700, -271782, -270871, -269965, -269064, -268169, -267280, -266397, -265519, -264646, -263779, -262917, -262060, -261209, -260363, -259522, -258686, -257855, -257029, -256208, -255392, -254581, -253774, -252973, -252176, -251384, -250596, -249813, -249035, -248261, -247492, -246727, -245966, -245210, -244458, -243711, -242967, -242228, -241493, -240763, -240036, -239314, -238595, -237881, -237170, -236463, -235761, -235062, -234367, -233676, -232988, -232304, -231624, -230948, -230275, -229606, -228941, -228279, -227621, -226966, -226314, -225666, -225022, -224381, -223743, -223108, -222477, -221849, -221225, -220603, -219985, -219370, -218758, -218149, -217544, -216941, -216341, -215745, -215151, -214561, -213973, -213389, -212807, -212228, -211652, -211079, -210509, -209941, -209376, -208815, -208255, -207699, -207145, -206594, -206045, -205500, -204956, -204416, -203878, -203342, -202809, -202279, -201751, -201226, -200703, -200182, -199664, -199149, -198636, -198125, -197616, -197110, -196606, -196105, -195606, -195109, -194614, -194122, -193631, -193143, -192658, -192174, -191693, -191213, -190736, -190261, -189789, -189318, -188849, -188382, -187918, -187455, -186995, -186536, -186080, -185625, -185173, -184722, -184274, -183827, -183382, -182939, -182498, -182059, -181622, -181186, -180753, -180321, -179891, -179463, -179037, -178612, -178190, -177769, -177349, -176932, -176516, -176102, -175690, -175279, -174870, -174463, -174057, -173653, -173251, -172850, -172451, -172053, -171657, -171263, -170870, -170479, -170089, -169701, -169315, -168930, -168546, -168164, -167784, -167405, -167027, -166651, -166277, -165904, -165532, -165162, -164793, -164426, -164060, -163695, -163332, -162970, -162610, -162251, -161893, -161537, -161182, -160828, -160476, -160125, -159775, -159427, -159079, -158734, -158389, -158046, -157704, -157363, -157024, -156686, -156349, -156013, -155678, -155345, -155013, -154682, -154352, -154024, -153697, -153370, -153045, -152722, -152399, -152077, -151757, -151438, -151120, -150803, -150487, -150172, -149859, -149546, -149235, -148924, -148615, -148307, -148000, -147693, -147388, -147084, -146782, -146480, -146179, -145879, -145580, -145282, -144986, -144690, -144395, -144101, -143808, -143517, -143226, -142936, -142647, -142359, -142072, -141786, -141501, -141217, -140934, -140651, -140370, -140090, -139810, -139532, -139254, -138977, -138701, -138426, -138152, -137879, -137607, -137335, -137065, -136795, -136526, -136258, -135991, -135725, -135459, -135195, -134931, -134668, -134406, -134145, -133884, -133625, -133366, -133108, -132851, -132594, -132339, -132084, -131830, -131576, -131324, -131072, -130821, -130571, -130322, -130073, -129825, -129578, -129332, -129086, -128841, -128597, -128353, -128111, -127869, -127627, -127387, -127147, -126908, -126669, -126432, -126195, -125959, -125723, -125488, -125254, -125020, -124787, -124555, -124324, -124093, -123863, -123633, -123404, -123176, -122949, -122722, -122496, -122270, -122045, -121821, -121597, -121374, -121152, -120930, -120709, -120489, -120269, -120050, -119831, -119613, -119396, -119179, -118963, -118747, -118532, -118318, -118104, -117891, -117678, -117466, -117254, -117044, -116833, -116623, -116414, -116206, -115998, -115790, -115583, -115377, -115171, -114966, -114761, -114557, -114354, -114151, -113948, -113746, -113545, -113344, -113143, -112944, -112744, -112546, -112347, -112150, -111952, -111756, -111560, -111364, -111169, -110974, -110780, -110586, -110393, -110200, -110008, -109817, -109626, -109435, -109245, -109055, -108866, -108677, -108489, -108301, -108114, -107927, -107741, -107555, -107369, -107184, -107000, -106816, -106632, -106449, -106266, -106084, -105902, -105721, -105540, -105360, -105180, -105000, -104821, -104643, -104465, -104287, -104109, -103933, -103756, -103580, -103404, -103229, -103054, -102880, -102706, -102533, -102360, -102187, -102015, -101843, -101671, -101500, -101330, -101159, -100990, -100820, -100651, -100482, -100314, -100146, -99979, -99812, -99645, -99479, -99313, -99148, -98982, -98818, -98653, -98489, -98326, -98163, -98000, -97837, -97675, -97513, -97352, -97191, -97030, -96870, -96710, -96551, -96391, -96233, -96074, -95916, -95758, -95601, -95444, -95287, -95131, -94975, -94819, -94664, -94509, -94354, -94200, -94046, -93892, -93739, -93586, -93434, -93281, -93129, -92978, -92826, -92675, -92525, -92375, -92225, -92075, -91926, -91777, -91628, -91480, -91332, -91184, -91036, -90889, -90742, -90596, -90450, -90304, -90158, -90013, -89868, -89724, -89579, -89435, -89292, -89148, -89005, -88862, -88720, -88577, -88435, -88294, -88152, -88011, -87871, -87730, -87590, -87450, -87310, -87171, -87032, -86893, -86755, -86616, -86479, -86341, -86204, -86066, -85930, -85793, -85657, -85521, -85385, -85250, -85114, -84980, -84845, -84710, -84576, -84443, -84309, -84176, -84043, -83910, -83777, -83645, -83513, -83381, -83250, -83118, -82987, -82857, -82726, -82596, -82466, -82336, -82207, -82078, -81949, -81820, -81691, -81563, -81435, -81307, -81180, -81053, -80925, -80799, -80672, -80546, -80420, -80294, -80168, -80043, -79918, -79793, -79668, -79544, -79420, -79296, -79172, -79048, -78925, -78802, -78679, -78557, -78434, -78312, -78190, -78068, -77947, -77826, -77705, -77584, -77463, -77343, -77223, -77103, -76983, -76864, -76744, -76625, -76506, -76388, -76269, -76151, -76033, -75915, -75797, -75680, -75563, -75446, -75329, -75213, -75096, -74980, -74864, -74748, -74633, -74517, -74402, -74287, -74172, -74058, -73944, -73829, -73715, -73602, -73488, -73375, -73262, -73149, -73036, -72923, -72811, -72699, -72587, -72475, -72363, -72252, -72140, -72029, -71918, -71808, -71697, -71587, -71477, -71367, -71257, -71147, -71038, -70929, -70820, -70711, -70602, -70494, -70385, -70277, -70169, -70061, -69954, -69846, -69739, -69632, -69525, -69418, -69312, -69205, -69099, -68993, -68887, -68781, -68676, -68570, -68465, -68360, -68255, -68151, -68046, -67942, -67837, -67733, -67629, -67526, -67422, -67319, -67216, -67113, -67010, -66907, -66804, -66702, -66600, -66498, -66396, -66294, -66192, -66091, -65989, -65888, -65787, -65686, -65586, -65485, -65385, -65285, -65185, -65085, -64985, -64885, -64786, -64687, -64587, -64488, -64389, -64291, -64192, -64094, -63996, -63897, -63799, -63702, -63604, -63506, -63409, -63312, -63215, -63118, -63021, -62924, -62828, -62731, -62635, -62539, -62443, -62347, -62251, -62156, -62060, -61965, -61870, -61775, -61680, -61585, -61491, -61396, -61302, -61208, -61114, -61020, -60926, -60833, -60739, -60646, -60552, -60459, -60366, -60273, -60181, -60088, -59996, -59903, -59811, -59719, -59627, -59535, -59444, -59352, -59261, -59169, -59078, -58987, -58896, -58805, -58715, -58624, -58534, -58443, -58353, -58263, -58173, -58083, -57994, -57904, -57815, -57725, -57636, -57547, -57458, -57369, -57281, -57192, -57104, -57015, -56927, -56839, -56751, -56663, -56575, -56487, -56400, -56312, -56225, -56138, -56051, -55964, -55877, -55790, -55704, -55617, -55531, -55444, -55358, -55272, -55186, -55100, -55015, -54929, -54843, -54758, -54673, -54587, -54502, -54417, -54333, -54248, -54163, -54079, -53994, -53910, -53826, -53741, -53657, -53574, -53490, -53406, -53322, -53239, -53156, -53072, -52989, -52906, -52823, -52740, -52657, -52575, -52492, -52410, -52327, -52245, -52163, -52081, -51999, -51917, -51835, -51754, -51672, -51591, -51509, -51428, -51347, -51266, -51185, -51104, -51023, -50942, -50862, -50781, -50701, -50621, -50540, -50460, -50380, -50300, -50221, -50141, -50061, -49982, -49902, -49823, -49744, -49664, -49585, -49506, -49427, -49349, -49270, -49191, -49113, -49034, -48956, -48878, -48799, -48721, -48643, -48565, -48488, -48410, -48332, -48255, -48177, -48100, -48022, -47945, -47868, -47791, -47714, -47637, -47560, -47484, -47407, -47331, -47254, -47178, -47102, -47025, -46949, -46873, -46797, -46721, -46646, -46570, -46494, -46419, -46343, -46268, -46193, -46118, -46042, -45967, -45892, -45818, -45743, -45668, -45593, -45519, -45444, -45370, -45296, -45221, -45147, -45073, -44999, -44925, -44851, -44778, -44704, -44630, -44557, -44483, -44410, -44337, -44263, -44190, -44117, -44044, -43971, -43898, -43826, -43753, -43680, -43608, -43535, -43463, -43390, -43318, -43246, -43174, -43102, -43030, -42958, -42886, -42814, -42743, -42671, -42600, -42528, -42457, -42385, -42314, -42243, -42172, -42101, -42030, -41959, -41888, -41817, -41747, -41676, -41605, -41535, -41465, -41394, -41324, -41254, -41184, -41113, -41043, -40973, -40904, -40834, -40764, -40694, -40625, -40555, -40486, -40416, -40347, -40278, -40208, -40139, -40070, -40001, -39932, -39863, -39794, -39726, -39657, -39588, -39520, -39451, -39383, -39314, -39246, -39178, -39110, -39042, -38973, -38905, -38837, -38770, -38702, -38634, -38566, -38499, -38431, -38364, -38296, -38229, -38161, -38094, -38027, -37960, -37893, -37826, -37759, -37692, -37625, -37558, -37491, -37425, -37358, -37291, -37225, -37158, -37092, -37026, -36959, -36893, -36827, -36761, -36695, -36629, -36563, -36497, -36431, -36365, -36300, -36234, -36168, -36103, -36037, -35972, -35907, -35841, -35776, -35711, -35646, -35580, -35515, -35450, -35385, -35321, -35256, -35191, -35126, -35062, -34997, -34932, -34868, -34803, -34739, -34675, -34610, -34546, -34482, -34418, -34354, -34289, -34225, -34162, -34098, -34034, -33970, -33906, -33843, -33779, -33715, -33652, -33588, -33525, -33461, -33398, -33335, -33272, -33208, -33145, -33082, -33019, -32956, -32893, -32830, -32767, -32705, -32642, -32579, -32516, -32454, -32391, -32329, -32266, -32204, -32141, -32079, -32017, -31955, -31892, -31830, -31768, -31706, -31644, -31582, -31520, -31458, -31396, -31335, -31273, -31211, -31150, -31088, -31026, -30965, -30904, -30842, -30781, -30719, -30658, -30597, -30536, -30474, -30413, -30352, -30291, -30230, -30169, -30108, -30048, -29987, -29926, -29865, -29805, -29744, -29683, -29623, -29562, -29502, -29441, -29381, -29321, -29260, -29200, -29140, -29080, -29020, -28959, -28899, -28839, -28779, -28719, -28660, -28600, -28540, -28480, -28420, -28361, -28301, -28241, -28182, -28122, -28063, -28003, -27944, -27884, -27825, -27766, -27707, -27647, -27588, -27529, -27470, -27411, -27352, -27293, -27234, -27175, -27116, -27057, -26998, -26940, -26881, -26822, -26763, -26705, -26646, -26588, -26529, -26471, -26412, -26354, -26295, -26237, -26179, -26120, -26062, -26004, -25946, -25888, -25830, -25772, -25714, -25656, -25598, -25540, -25482, -25424, -25366, -25308, -25251, -25193, -25135, -25078, -25020, -24962, -24905, -24847, -24790, -24732, -24675, -24618, -24560, -24503, -24446, -24389, -24331, -24274, -24217, -24160, -24103, -24046, -23989, -23932, -23875, -23818, -23761, -23704, -23647, -23591, -23534, -23477, -23420, -23364, -23307, -23250, -23194, -23137, -23081, -23024, -22968, -22911, -22855, -22799, -22742, -22686, -22630, -22573, -22517, -22461, -22405, -22349, -22293, -22237, -22181, -22125, -22069, -22013, -21957, -21901, -21845, -21789, -21733, -21678, -21622, -21566, -21510, -21455, -21399, -21343, -21288, -21232, -21177, -21121, -21066, -21010, -20955, -20900, -20844, -20789, -20734, -20678, -20623, -20568, -20513, -20457, -20402, -20347, -20292, -20237, -20182, -20127, -20072, -20017, -19962, -19907, -19852, -19797, -19742, -19688, -19633, -19578, -19523, -19469, -19414, -19359, -19305, -19250, -19195, -19141, -19086, -19032, -18977, -18923, -18868, -18814, -18760, -18705, -18651, -18597, -18542, -18488, -18434, -18380, -18325, -18271, -18217, -18163, -18109, -18055, -18001, -17946, -17892, -17838, -17784, -17731, -17677, -17623, -17569, -17515, -17461, -17407, -17353, -17300, -17246, -17192, -17138, -17085, -17031, -16977, -16924, -16870, -16817, -16763, -16710, -16656, -16603, -16549, -16496, -16442, -16389, -16335, -16282, -16229, -16175, -16122, -16069, -16015, -15962, -15909, -15856, -15802, -15749, -15696, -15643, -15590, -15537, -15484, -15431, -15378, -15325, -15272, -15219, -15166, -15113, -15060, -15007, -14954, -14901, -14848, -14795, -14743, -14690, -14637, -14584, -14531, -14479, -14426, -14373, -14321, -14268, -14215, -14163, -14110, -14057, -14005, -13952, -13900, -13847, -13795, -13742, -13690, -13637, -13585, -13533, -13480, -13428, -13375, -13323, -13271, -13218, -13166, -13114, -13062, -13009, -12957, -12905, -12853, -12800, -12748, -12696, -12644, -12592, -12540, -12488, -12436, -12383, -12331, -12279, -12227, -12175, -12123, -12071, -12019, -11967, -11916, -11864, -11812, -11760, -11708, -11656, -11604, -11552, -11501, -11449, -11397, -11345, -11293, -11242, -11190, -11138, -11086, -11035, -10983, -10931, -10880, -10828, -10777, -10725, -10673, -10622, -10570, -10519, -10467, -10415, -10364, -10312, -10261, -10209, -10158, -10106, -10055, -10004, -9952, -9901, -9849, -9798, -9747, -9695, -9644, -9592, -9541, -9490, -9438, -9387, -9336, -9285, -9233, -9182, -9131, -9080, -9028, -8977, -8926, -8875, -8824, -8772, -8721, -8670, -8619, -8568, -8517, -8466, -8414, -8363, -8312, -8261, -8210, -8159, -8108, -8057, -8006, -7955, -7904, -7853, -7802, -7751, -7700, -7649, -7598, -7547, -7496, -7445, -7395, -7344, -7293, -7242, -7191, -7140, -7089, -7038, -6988, -6937, -6886, -6835, -6784, -6733, -6683, -6632, -6581, -6530, -6480, -6429, -6378, -6327, -6277, -6226, -6175, -6124, -6074, -6023, -5972, -5922, -5871, -5820, -5770, -5719, -5668, -5618, -5567, -5517, -5466, -5415, -5365, -5314, -5264, -5213, -5162, -5112, -5061, -5011, -4960, -4910, -4859, -4808, -4758, -4707, -4657, -4606, -4556, -4505, -4455, -4404, -4354, -4303, -4253, -4202, -4152, -4101, -4051, -4001, -3950, -3900, -3849, -3799, -3748, -3698, -3648, -3597, -3547, -3496, -3446, -3395, -3345, -3295, -3244, -3194, -3144, -3093, -3043, -2992, -2942, -2892, -2841, -2791, -2741, -2690, -2640, -2590, -2539, -2489, -2439, -2388, -2338, -2288, -2237, -2187, -2137, -2086, -2036, -1986, -1935, -1885, -1835, -1784, -1734, -1684, -1633, -1583, -1533, -1483, -1432, -1382, -1332, -1281, -1231, -1181, -1131, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1131, 1181, 1231, 1281, 1332, 1382, 1432, 1483, 1533, 1583, 1633, 1684, 1734, 1784, 1835, 1885, 1935, 1986, 2036, 2086, 2137, 2187, 2237, 2288, 2338, 2388, 2439, 2489, 2539, 2590, 2640, 2690, 2741, 2791, 2841, 2892, 2942, 2992, 3043, 3093, 3144, 3194, 3244, 3295, 3345, 3395, 3446, 3496, 3547, 3597, 3648, 3698, 3748, 3799, 3849, 3900, 3950, 4001, 4051, 4101, 4152, 4202, 4253, 4303, 4354, 4404, 4455, 4505, 4556, 4606, 4657, 4707, 4758, 4808, 4859, 4910, 4960, 5011, 5061, 5112, 5162, 5213, 5264, 5314, 5365, 5415, 5466, 5517, 5567, 5618, 5668, 5719, 5770, 5820, 5871, 5922, 5972, 6023, 6074, 6124, 6175, 6226, 6277, 6327, 6378, 6429, 6480, 6530, 6581, 6632, 6683, 6733, 6784, 6835, 6886, 6937, 6988, 7038, 7089, 7140, 7191, 7242, 7293, 7344, 7395, 7445, 7496, 7547, 7598, 7649, 7700, 7751, 7802, 7853, 7904, 7955, 8006, 8057, 8108, 8159, 8210, 8261, 8312, 8363, 8414, 8466, 8517, 8568, 8619, 8670, 8721, 8772, 8824, 8875, 8926, 8977, 9028, 9080, 9131, 9182, 9233, 9285, 9336, 9387, 9438, 9490, 9541, 9592, 9644, 9695, 9747, 9798, 9849, 9901, 9952, 10004, 10055, 10106, 10158, 10209, 10261, 10312, 10364, 10415, 10467, 10519, 10570, 10622, 10673, 10725, 10777, 10828, 10880, 10931, 10983, 11035, 11086, 11138, 11190, 11242, 11293, 11345, 11397, 11449, 11501, 11552, 11604, 11656, 11708, 11760, 11812, 11864, 11916, 11967, 12019, 12071, 12123, 12175, 12227, 12279, 12331, 12383, 12436, 12488, 12540, 12592, 12644, 12696, 12748, 12800, 12853, 12905, 12957, 13009, 13062, 13114, 13166, 13218, 13271, 13323, 13375, 13428, 13480, 13533, 13585, 13637, 13690, 13742, 13795, 13847, 13900, 13952, 14005, 14057, 14110, 14163, 14215, 14268, 14321, 14373, 14426, 14479, 14531, 14584, 14637, 14690, 14743, 14795, 14848, 14901, 14954, 15007, 15060, 15113, 15166, 15219, 15272, 15325, 15378, 15431, 15484, 15537, 15590, 15643, 15696, 15749, 15802, 15856, 15909, 15962, 16015, 16069, 16122, 16175, 16229, 16282, 16335, 16389, 16442, 16496, 16549, 16603, 16656, 16710, 16763, 16817, 16870, 16924, 16977, 17031, 17085, 17138, 17192, 17246, 17300, 17353, 17407, 17461, 17515, 17569, 17623, 17677, 17731, 17784, 17838, 17892, 17946, 18001, 18055, 18109, 18163, 18217, 18271, 18325, 18380, 18434, 18488, 18542, 18597, 18651, 18705, 18760, 18814, 18868, 18923, 18977, 19032, 19086, 19141, 19195, 19250, 19305, 19359, 19414, 19469, 19523, 19578, 19633, 19688, 19742, 19797, 19852, 19907, 19962, 20017, 20072, 20127, 20182, 20237, 20292, 20347, 20402, 20457, 20513, 20568, 20623, 20678, 20734, 20789, 20844, 20900, 20955, 21010, 21066, 21121, 21177, 21232, 21288, 21343, 21399, 21455, 21510, 21566, 21622, 21678, 21733, 21789, 21845, 21901, 21957, 22013, 22069, 22125, 22181, 22237, 22293, 22349, 22405, 22461, 22517, 22573, 22630, 22686, 22742, 22799, 22855, 22911, 22968, 23024, 23081, 23137, 23194, 23250, 23307, 23364, 23420, 23477, 23534, 23591, 23647, 23704, 23761, 23818, 23875, 23932, 23989, 24046, 24103, 24160, 24217, 24274, 24331, 24389, 24446, 24503, 24560, 24618, 24675, 24732, 24790, 24847, 24905, 24962, 25020, 25078, 25135, 25193, 25251, 25308, 25366, 25424, 25482, 25540, 25598, 25656, 25714, 25772, 25830, 25888, 25946, 26004, 26062, 26120, 26179, 26237, 26295, 26354, 26412, 26471, 26529, 26588, 26646, 26705, 26763, 26822, 26881, 26940, 26998, 27057, 27116, 27175, 27234, 27293, 27352, 27411, 27470, 27529, 27588, 27647, 27707, 27766, 27825, 27884, 27944, 28003, 28063, 28122, 28182, 28241, 28301, 28361, 28420, 28480, 28540, 28600, 28660, 28719, 28779, 28839, 28899, 28959, 29020, 29080, 29140, 29200, 29260, 29321, 29381, 29441, 29502, 29562, 29623, 29683, 29744, 29805, 29865, 29926, 29987, 30048, 30108, 30169, 30230, 30291, 30352, 30413, 30474, 30536, 30597, 30658, 30719, 30781, 30842, 30904, 30965, 31026, 31088, 31150, 31211, 31273, 31335, 31396, 31458, 31520, 31582, 31644, 31706, 31768, 31830, 31892, 31955, 32017, 32079, 32141, 32204, 32266, 32329, 32391, 32454, 32516, 32579, 32642, 32705, 32767, 32830, 32893, 32956, 33019, 33082, 33145, 33208, 33272, 33335, 33398, 33461, 33525, 33588, 33652, 33715, 33779, 33843, 33906, 33970, 34034, 34098, 34162, 34225, 34289, 34354, 34418, 34482, 34546, 34610, 34675, 34739, 34803, 34868, 34932, 34997, 35062, 35126, 35191, 35256, 35321, 35385, 35450, 35515, 35580, 35646, 35711, 35776, 35841, 35907, 35972, 36037, 36103, 36168, 36234, 36300, 36365, 36431, 36497, 36563, 36629, 36695, 36761, 36827, 36893, 36959, 37026, 37092, 37158, 37225, 37291, 37358, 37425, 37491, 37558, 37625, 37692, 37759, 37826, 37893, 37960, 38027, 38094, 38161, 38229, 38296, 38364, 38431, 38499, 38566, 38634, 38702, 38770, 38837, 38905, 38973, 39042, 39110, 39178, 39246, 39314, 39383, 39451, 39520, 39588, 39657, 39726, 39794, 39863, 39932, 40001, 40070, 40139, 40208, 40278, 40347, 40416, 40486, 40555, 40625, 40694, 40764, 40834, 40904, 40973, 41043, 41113, 41184, 41254, 41324, 41394, 41465, 41535, 41605, 41676, 41747, 41817, 41888, 41959, 42030, 42101, 42172, 42243, 42314, 42385, 42457, 42528, 42600, 42671, 42743, 42814, 42886, 42958, 43030, 43102, 43174, 43246, 43318, 43390, 43463, 43535, 43608, 43680, 43753, 43826, 43898, 43971, 44044, 44117, 44190, 44263, 44337, 44410, 44483, 44557, 44630, 44704, 44778, 44851, 44925, 44999, 45073, 45147, 45221, 45296, 45370, 45444, 45519, 45593, 45668, 45743, 45818, 45892, 45967, 46042, 46118, 46193, 46268, 46343, 46419, 46494, 46570, 46646, 46721, 46797, 46873, 46949, 47025, 47102, 47178, 47254, 47331, 47407, 47484, 47560, 47637, 47714, 47791, 47868, 47945, 48022, 48100, 48177, 48255, 48332, 48410, 48488, 48565, 48643, 48721, 48799, 48878, 48956, 49034, 49113, 49191, 49270, 49349, 49427, 49506, 49585, 49664, 49744, 49823, 49902, 49982, 50061, 50141, 50221, 50300, 50380, 50460, 50540, 50621, 50701, 50781, 50862, 50942, 51023, 51104, 51185, 51266, 51347, 51428, 51509, 51591, 51672, 51754, 51835, 51917, 51999, 52081, 52163, 52245, 52327, 52410, 52492, 52575, 52657, 52740, 52823, 52906, 52989, 53072, 53156, 53239, 53322, 53406, 53490, 53574, 53657, 53741, 53826, 53910, 53994, 54079, 54163, 54248, 54333, 54417, 54502, 54587, 54673, 54758, 54843, 54929, 55015, 55100, 55186, 55272, 55358, 55444, 55531, 55617, 55704, 55790, 55877, 55964, 56051, 56138, 56225, 56312, 56400, 56487, 56575, 56663, 56751, 56839, 56927, 57015, 57104, 57192, 57281, 57369, 57458, 57547, 57636, 57725, 57815, 57904, 57994, 58083, 58173, 58263, 58353, 58443, 58534, 58624, 58715, 58805, 58896, 58987, 59078, 59169, 59261, 59352, 59444, 59535, 59627, 59719, 59811, 59903, 59996, 60088, 60181, 60273, 60366, 60459, 60552, 60646, 60739, 60833, 60926, 61020, 61114, 61208, 61302, 61396, 61491, 61585, 61680, 61775, 61870, 61965, 62060, 62156, 62251, 62347, 62443, 62539, 62635, 62731, 62828, 62924, 63021, 63118, 63215, 63312, 63409, 63506, 63604, 63702, 63799, 63897, 63996, 64094, 64192, 64291, 64389, 64488, 64587, 64687, 64786, 64885, 64985, 65085, 65185, 65285, 65385, 65485, 65586, 65686, 65787, 65888, 65989, 66091, 66192, 66294, 66396, 66498, 66600, 66702, 66804, 66907, 67010, 67113, 67216, 67319, 67422, 67526, 67629, 67733, 67837, 67942, 68046, 68151, 68255, 68360, 68465, 68570, 68676, 68781, 68887, 68993, 69099, 69205, 69312, 69418, 69525, 69632, 69739, 69846, 69954, 70061, 70169, 70277, 70385, 70494, 70602, 70711, 70820, 70929, 71038, 71147, 71257, 71367, 71477, 71587, 71697, 71808, 71918, 72029, 72140, 72252, 72363, 72475, 72587, 72699, 72811, 72923, 73036, 73149, 73262, 73375, 73488, 73602, 73715, 73829, 73944, 74058, 74172, 74287, 74402, 74517, 74633, 74748, 74864, 74980, 75096, 75213, 75329, 75446, 75563, 75680, 75797, 75915, 76033, 76151, 76269, 76388, 76506, 76625, 76744, 76864, 76983, 77103, 77223, 77343, 77463, 77584, 77705, 77826, 77947, 78068, 78190, 78312, 78434, 78557, 78679, 78802, 78925, 79048, 79172, 79296, 79420, 79544, 79668, 79793, 79918, 80043, 80168, 80294, 80420, 80546, 80672, 80799, 80925, 81053, 81180, 81307, 81435, 81563, 81691, 81820, 81949, 82078, 82207, 82336, 82466, 82596, 82726, 82857, 82987, 83118, 83250, 83381, 83513, 83645, 83777, 83910, 84043, 84176, 84309, 84443, 84576, 84710, 84845, 84980, 85114, 85250, 85385, 85521, 85657, 85793, 85930, 86066, 86204, 86341, 86479, 86616, 86755, 86893, 87032, 87171, 87310, 87450, 87590, 87730, 87871, 88011, 88152, 88294, 88435, 88577, 88720, 88862, 89005, 89148, 89292, 89435, 89579, 89724, 89868, 90013, 90158, 90304, 90450, 90596, 90742, 90889, 91036, 91184, 91332, 91480, 91628, 91777, 91926, 92075, 92225, 92375, 92525, 92675, 92826, 92978, 93129, 93281, 93434, 93586, 93739, 93892, 94046, 94200, 94354, 94509, 94664, 94819, 94975, 95131, 95287, 95444, 95601, 95758, 95916, 96074, 96233, 96391, 96551, 96710, 96870, 97030, 97191, 97352, 97513, 97675, 97837, 98000, 98163, 98326, 98489, 98653, 98818, 98982, 99148, 99313, 99479, 99645, 99812, 99979, 100146, 100314, 100482, 100651, 100820, 100990, 101159, 101330, 101500, 101671, 101843, 102015, 102187, 102360, 102533, 102706, 102880, 103054, 103229, 103404, 103580, 103756, 103933, 104109, 104287, 104465, 104643, 104821, 105000, 105180, 105360, 105540, 105721, 105902, 106084, 106266, 106449, 106632, 106816, 107000, 107184, 107369, 107555, 107741, 107927, 108114, 108301, 108489, 108677, 108866, 109055, 109245, 109435, 109626, 109817, 110008, 110200, 110393, 110586, 110780, 110974, 111169, 111364, 111560, 111756, 111952, 112150, 112347, 112546, 112744, 112944, 113143, 113344, 113545, 113746, 113948, 114151, 114354, 114557, 114761, 114966, 115171, 115377, 115583, 115790, 115998, 116206, 116414, 116623, 116833, 117044, 117254, 117466, 117678, 117891, 118104, 118318, 118532, 118747, 118963, 119179, 119396, 119613, 119831, 120050, 120269, 120489, 120709, 120930, 121152, 121374, 121597, 121821, 122045, 122270, 122496, 122722, 122949, 123176, 123404, 123633, 123863, 124093, 124324, 124555, 124787, 125020, 125254, 125488, 125723, 125959, 126195, 126432, 126669, 126908, 127147, 127387, 127627, 127869, 128111, 128353, 128597, 128841, 129086, 129332, 129578, 129825, 130073, 130322, 130571, 130821, 131072, 131324, 131576, 131830, 132084, 132339, 132594, 132851, 133108, 133366, 133625, 133884, 134145, 134406, 134668, 134931, 135195, 135459, 135725, 135991, 136258, 136526, 136795, 137065, 137335, 137607, 137879, 138152, 138426, 138701, 138977, 139254, 139532, 139810, 140090, 140370, 140651, 140934, 141217, 141501, 141786, 142072, 142359, 142647, 142936, 143226, 143517, 143808, 144101, 144395, 144690, 144986, 145282, 145580, 145879, 146179, 146480, 146782, 147084, 147388, 147693, 148000, 148307, 148615, 148924, 149235, 149546, 149859, 150172, 150487, 150803, 151120, 151438, 151757, 152077, 152399, 152722, 153045, 153370, 153697, 154024, 154352, 154682, 155013, 155345, 155678, 156013, 156349, 156686, 157024, 157363, 157704, 158046, 158389, 158734, 159079, 159427, 159775, 160125, 160476, 160828, 161182, 161537, 161893, 162251, 162610, 162970, 163332, 163695, 164060, 164426, 164793, 165162, 165532, 165904, 166277, 166651, 167027, 167405, 167784, 168164, 168546, 168930, 169315, 169701, 170089, 170479, 170870, 171263, 171657, 172053, 172451, 172850, 173251, 173653, 174057, 174463, 174870, 175279, 175690, 176102, 176516, 176932, 177349, 177769, 178190, 178612, 179037, 179463, 179891, 180321, 180753, 181186, 181622, 182059, 182498, 182939, 183382, 183827, 184274, 184722, 185173, 185625, 186080, 186536, 186995, 187455, 187918, 188382, 188849, 189318, 189789, 190261, 190736, 191213, 191693, 192174, 192658, 193143, 193631, 194122, 194614, 195109, 195606, 196105, 196606, 197110, 197616, 198125, 198636, 199149, 199664, 200182, 200703, 201226, 201751, 202279, 202809, 203342, 203878, 204416, 204956, 205500, 206045, 206594, 207145, 207699, 208255, 208815, 209376, 209941, 210509, 211079, 211652, 212228, 212807, 213389, 213973, 214561, 215151, 215745, 216341, 216941, 217544, 218149, 218758, 219370, 219985, 220603, 221225, 221849, 222477, 223108, 223743, 224381, 225022, 225666, 226314, 226966, 227621, 228279, 228941, 229606, 230275, 230948, 231624, 232304, 232988, 233676, 234367, 235062, 235761, 236463, 237170, 237881, 238595, 239314, 240036, 240763, 241493, 242228, 242967, 243711, 244458, 245210, 245966, 246727, 247492, 248261, 249035, 249813, 250596, 251384, 252176, 252973, 253774, 254581, 255392, 256208, 257029, 257855, 258686, 259522, 260363, 261209, 262060, 262917, 263779, 264646, 265519, 266397, 267280, 268169, 269064, 269965, 270871, 271782, 272700, 273624, 274553, 275489, 276430, 277378, 278332, 279292, 280258, 281231, 282210, 283195, 284188, 285186, 286192, 287204, 288223, 289249, 290282, 291322, 292369, 293423, 294485, 295554, 296630, 297714, 298805, 299904, 301011, 302126, 303248, 304379, 305517, 306664, 307819, 308983, 310154, 311335, 312524, 313721, 314928, 316143, 317368, 318601, 319844, 321097, 322358, 323629, 324910, 326201, 327502, 328812, 330133, 331464, 332805, 334157, 335519, 336892, 338276, 339671, 341078, 342495, 343924, 345364, 346816, 348280, 349756, 351244, 352744, 354257, 355783, 357321, 358872, 360436, 362013, 363604, 365208, 366826, 368459, 370105, 371765, 373440, 375130, 376835, 378555, 380290, 382040, 383807, 385589, 387387, 389202, 391034, 392882, 394747, 396630, 398530, 400448, 402384, 404338, 406311, 408303, 410314, 412344, 414395, 416465, 418555, 420666, 422798, 424951, 427125, 429321, 431540, 433781, 436045, 438332, 440643, 442978, 445337, 447720, 450129, 452564, 455024, 457511, 460024, 462565, 465133, 467730, 470355, 473009, 475692, 478406, 481150, 483925, 486732, 489571, 492443, 495348, 498287, 501261, 504269, 507313, 510394, 513512, 516667, 519861, 523094, 526366, 529680, 533034, 536431, 539870, 543354, 546881, 550455, 554074, 557741, 561456, 565221, 569035, 572901, 576818, 580789, 584815, 588896, 593033, 597229, 601483, 605798, 610174, 614613, 619117, 623686, 628323, 633028, 637803, 642651, 647572, 652568, 657640, 662792, 668024, 673338, 678737, 684223, 689797, 695462, 701219, 707072, 713023, 719074, 725227, 731486, 737853, 744331, 750922, 757631, 764460, 771411, 778490, 785699, 793041, 800521, 808143, 815910, 823827, 831898, 840127, 848520, 857081, 865817, 874730, 883829, 893117, 902602, 912289, 922186, 932298, 942633, 953199, 964003, 975054, 986361, 997931, 1009774, 1021901, 1034322, 1047046, 1060087, 1073455, 1087164, 1101225, 1115654, 1130465, 1145673, 1161294, 1177345, 1193846, 1210813, 1228269, 1246234, 1264730, 1283783, 1303416, 1323658, 1344537, 1366084, 1388330, 1411312, 1435065, 1459630, 1485049, 1511367, 1538632, 1566898, 1596220, 1626658, 1658278, 1691149, 1725348, 1760956, 1798063, 1836758, 1877161, 1919378, 1963536, 2009771, 2058233, 2109087, 2162516, 2218719, 2277919, 2340362, 2406322, 2476104, 2550052, 2628549, 2712030, 2800983, 2895966, 2997613, 3106651, 3223918, 3350381, 3487165, 3635590, 3797206, 3973855, 4167737, 4381502, 4618375, 4882318, 5178251, 5512368, 5892567, 6329090, 6835455, 7429880, 8137527, 8994149, 10052327, 11392683, 13145455, 15535599, 18988036, 24413316, 34178904, 56965752, 170910304 }; int finesine[10240] = { 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3541, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5748, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22433, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30426, 30471, 30515, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36555, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40300, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47860, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50065, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53911, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54308, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64601, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65534, 65534, 65534, 65533, 65533, 65532, 65532, 65531, 65531, 65530, 65530, 65529, 65528, 65527, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65516, 65515, 65514, 65513, 65511, 65510, 65508, 65507, 65505, 65504, 65502, 65501, 65499, 65497, 65496, 65494, 65492, 65490, 65488, 65486, 65484, 65482, 65480, 65478, 65476, 65474, 65472, 65470, 65467, 65465, 65463, 65460, 65458, 65455, 65453, 65450, 65448, 65445, 65442, 65440, 65437, 65434, 65431, 65429, 65426, 65423, 65420, 65417, 65414, 65411, 65408, 65404, 65401, 65398, 65395, 65391, 65388, 65385, 65381, 65378, 65374, 65371, 65367, 65363, 65360, 65356, 65352, 65349, 65345, 65341, 65337, 65333, 65329, 65325, 65321, 65317, 65313, 65309, 65305, 65300, 65296, 65292, 65287, 65283, 65279, 65274, 65270, 65265, 65260, 65256, 65251, 65246, 65242, 65237, 65232, 65227, 65222, 65217, 65212, 65207, 65202, 65197, 65192, 65187, 65182, 65177, 65171, 65166, 65161, 65155, 65150, 65144, 65139, 65133, 65128, 65122, 65117, 65111, 65105, 65099, 65094, 65088, 65082, 65076, 65070, 65064, 65058, 65052, 65046, 65040, 65033, 65027, 65021, 65015, 65008, 65002, 64995, 64989, 64982, 64976, 64969, 64963, 64956, 64949, 64943, 64936, 64929, 64922, 64915, 64908, 64902, 64895, 64887, 64880, 64873, 64866, 64859, 64852, 64844, 64837, 64830, 64822, 64815, 64808, 64800, 64793, 64785, 64777, 64770, 64762, 64754, 64747, 64739, 64731, 64723, 64715, 64707, 64699, 64691, 64683, 64675, 64667, 64659, 64651, 64642, 64634, 64626, 64617, 64609, 64600, 64592, 64584, 64575, 64566, 64558, 64549, 64540, 64532, 64523, 64514, 64505, 64496, 64487, 64478, 64469, 64460, 64451, 64442, 64433, 64424, 64414, 64405, 64396, 64387, 64377, 64368, 64358, 64349, 64339, 64330, 64320, 64310, 64301, 64291, 64281, 64271, 64261, 64252, 64242, 64232, 64222, 64212, 64202, 64192, 64181, 64171, 64161, 64151, 64140, 64130, 64120, 64109, 64099, 64088, 64078, 64067, 64057, 64046, 64035, 64025, 64014, 64003, 63992, 63981, 63971, 63960, 63949, 63938, 63927, 63915, 63904, 63893, 63882, 63871, 63859, 63848, 63837, 63825, 63814, 63803, 63791, 63779, 63768, 63756, 63745, 63733, 63721, 63709, 63698, 63686, 63674, 63662, 63650, 63638, 63626, 63614, 63602, 63590, 63578, 63565, 63553, 63541, 63528, 63516, 63504, 63491, 63479, 63466, 63454, 63441, 63429, 63416, 63403, 63390, 63378, 63365, 63352, 63339, 63326, 63313, 63300, 63287, 63274, 63261, 63248, 63235, 63221, 63208, 63195, 63182, 63168, 63155, 63141, 63128, 63114, 63101, 63087, 63074, 63060, 63046, 63032, 63019, 63005, 62991, 62977, 62963, 62949, 62935, 62921, 62907, 62893, 62879, 62865, 62850, 62836, 62822, 62808, 62793, 62779, 62764, 62750, 62735, 62721, 62706, 62692, 62677, 62662, 62648, 62633, 62618, 62603, 62588, 62573, 62558, 62543, 62528, 62513, 62498, 62483, 62468, 62453, 62437, 62422, 62407, 62391, 62376, 62360, 62345, 62329, 62314, 62298, 62283, 62267, 62251, 62236, 62220, 62204, 62188, 62172, 62156, 62141, 62125, 62108, 62092, 62076, 62060, 62044, 62028, 62012, 61995, 61979, 61963, 61946, 61930, 61913, 61897, 61880, 61864, 61847, 61831, 61814, 61797, 61780, 61764, 61747, 61730, 61713, 61696, 61679, 61662, 61645, 61628, 61611, 61594, 61577, 61559, 61542, 61525, 61507, 61490, 61473, 61455, 61438, 61420, 61403, 61385, 61367, 61350, 61332, 61314, 61297, 61279, 61261, 61243, 61225, 61207, 61189, 61171, 61153, 61135, 61117, 61099, 61081, 61062, 61044, 61026, 61007, 60989, 60971, 60952, 60934, 60915, 60897, 60878, 60859, 60841, 60822, 60803, 60785, 60766, 60747, 60728, 60709, 60690, 60671, 60652, 60633, 60614, 60595, 60576, 60556, 60537, 60518, 60499, 60479, 60460, 60441, 60421, 60402, 60382, 60363, 60343, 60323, 60304, 60284, 60264, 60244, 60225, 60205, 60185, 60165, 60145, 60125, 60105, 60085, 60065, 60045, 60025, 60004, 59984, 59964, 59944, 59923, 59903, 59883, 59862, 59842, 59821, 59801, 59780, 59759, 59739, 59718, 59697, 59677, 59656, 59635, 59614, 59593, 59572, 59551, 59530, 59509, 59488, 59467, 59446, 59425, 59404, 59382, 59361, 59340, 59318, 59297, 59276, 59254, 59233, 59211, 59190, 59168, 59146, 59125, 59103, 59081, 59059, 59038, 59016, 58994, 58972, 58950, 58928, 58906, 58884, 58862, 58840, 58818, 58795, 58773, 58751, 58729, 58706, 58684, 58662, 58639, 58617, 58594, 58572, 58549, 58527, 58504, 58481, 58459, 58436, 58413, 58390, 58367, 58345, 58322, 58299, 58276, 58253, 58230, 58207, 58183, 58160, 58137, 58114, 58091, 58067, 58044, 58021, 57997, 57974, 57950, 57927, 57903, 57880, 57856, 57833, 57809, 57785, 57762, 57738, 57714, 57690, 57666, 57642, 57618, 57594, 57570, 57546, 57522, 57498, 57474, 57450, 57426, 57402, 57377, 57353, 57329, 57304, 57280, 57255, 57231, 57206, 57182, 57157, 57133, 57108, 57083, 57059, 57034, 57009, 56984, 56959, 56935, 56910, 56885, 56860, 56835, 56810, 56785, 56760, 56734, 56709, 56684, 56659, 56633, 56608, 56583, 56557, 56532, 56507, 56481, 56456, 56430, 56404, 56379, 56353, 56328, 56302, 56276, 56250, 56225, 56199, 56173, 56147, 56121, 56095, 56069, 56043, 56017, 55991, 55965, 55938, 55912, 55886, 55860, 55833, 55807, 55781, 55754, 55728, 55701, 55675, 55648, 55622, 55595, 55569, 55542, 55515, 55489, 55462, 55435, 55408, 55381, 55354, 55327, 55300, 55274, 55246, 55219, 55192, 55165, 55138, 55111, 55084, 55056, 55029, 55002, 54974, 54947, 54920, 54892, 54865, 54837, 54810, 54782, 54755, 54727, 54699, 54672, 54644, 54616, 54588, 54560, 54533, 54505, 54477, 54449, 54421, 54393, 54365, 54337, 54308, 54280, 54252, 54224, 54196, 54167, 54139, 54111, 54082, 54054, 54026, 53997, 53969, 53940, 53911, 53883, 53854, 53826, 53797, 53768, 53739, 53711, 53682, 53653, 53624, 53595, 53566, 53537, 53508, 53479, 53450, 53421, 53392, 53363, 53334, 53304, 53275, 53246, 53216, 53187, 53158, 53128, 53099, 53069, 53040, 53010, 52981, 52951, 52922, 52892, 52862, 52832, 52803, 52773, 52743, 52713, 52683, 52653, 52624, 52594, 52564, 52534, 52503, 52473, 52443, 52413, 52383, 52353, 52322, 52292, 52262, 52231, 52201, 52171, 52140, 52110, 52079, 52049, 52018, 51988, 51957, 51926, 51896, 51865, 51834, 51803, 51773, 51742, 51711, 51680, 51649, 51618, 51587, 51556, 51525, 51494, 51463, 51432, 51401, 51369, 51338, 51307, 51276, 51244, 51213, 51182, 51150, 51119, 51087, 51056, 51024, 50993, 50961, 50929, 50898, 50866, 50834, 50803, 50771, 50739, 50707, 50675, 50644, 50612, 50580, 50548, 50516, 50484, 50452, 50420, 50387, 50355, 50323, 50291, 50259, 50226, 50194, 50162, 50129, 50097, 50065, 50032, 50000, 49967, 49935, 49902, 49869, 49837, 49804, 49771, 49739, 49706, 49673, 49640, 49608, 49575, 49542, 49509, 49476, 49443, 49410, 49377, 49344, 49311, 49278, 49244, 49211, 49178, 49145, 49112, 49078, 49045, 49012, 48978, 48945, 48911, 48878, 48844, 48811, 48777, 48744, 48710, 48676, 48643, 48609, 48575, 48542, 48508, 48474, 48440, 48406, 48372, 48338, 48304, 48271, 48237, 48202, 48168, 48134, 48100, 48066, 48032, 47998, 47963, 47929, 47895, 47860, 47826, 47792, 47757, 47723, 47688, 47654, 47619, 47585, 47550, 47516, 47481, 47446, 47412, 47377, 47342, 47308, 47273, 47238, 47203, 47168, 47133, 47098, 47063, 47028, 46993, 46958, 46923, 46888, 46853, 46818, 46783, 46747, 46712, 46677, 46642, 46606, 46571, 46536, 46500, 46465, 46429, 46394, 46358, 46323, 46287, 46252, 46216, 46180, 46145, 46109, 46073, 46037, 46002, 45966, 45930, 45894, 45858, 45822, 45786, 45750, 45714, 45678, 45642, 45606, 45570, 45534, 45498, 45462, 45425, 45389, 45353, 45316, 45280, 45244, 45207, 45171, 45135, 45098, 45062, 45025, 44989, 44952, 44915, 44879, 44842, 44806, 44769, 44732, 44695, 44659, 44622, 44585, 44548, 44511, 44474, 44437, 44400, 44363, 44326, 44289, 44252, 44215, 44178, 44141, 44104, 44067, 44029, 43992, 43955, 43918, 43880, 43843, 43806, 43768, 43731, 43693, 43656, 43618, 43581, 43543, 43506, 43468, 43430, 43393, 43355, 43317, 43280, 43242, 43204, 43166, 43128, 43091, 43053, 43015, 42977, 42939, 42901, 42863, 42825, 42787, 42749, 42711, 42672, 42634, 42596, 42558, 42520, 42481, 42443, 42405, 42366, 42328, 42290, 42251, 42213, 42174, 42136, 42097, 42059, 42020, 41982, 41943, 41904, 41866, 41827, 41788, 41750, 41711, 41672, 41633, 41595, 41556, 41517, 41478, 41439, 41400, 41361, 41322, 41283, 41244, 41205, 41166, 41127, 41088, 41048, 41009, 40970, 40931, 40891, 40852, 40813, 40773, 40734, 40695, 40655, 40616, 40576, 40537, 40497, 40458, 40418, 40379, 40339, 40300, 40260, 40220, 40180, 40141, 40101, 40061, 40021, 39982, 39942, 39902, 39862, 39822, 39782, 39742, 39702, 39662, 39622, 39582, 39542, 39502, 39462, 39422, 39382, 39341, 39301, 39261, 39221, 39180, 39140, 39100, 39059, 39019, 38979, 38938, 38898, 38857, 38817, 38776, 38736, 38695, 38655, 38614, 38573, 38533, 38492, 38451, 38411, 38370, 38329, 38288, 38248, 38207, 38166, 38125, 38084, 38043, 38002, 37961, 37920, 37879, 37838, 37797, 37756, 37715, 37674, 37633, 37592, 37551, 37509, 37468, 37427, 37386, 37344, 37303, 37262, 37220, 37179, 37137, 37096, 37055, 37013, 36972, 36930, 36889, 36847, 36805, 36764, 36722, 36681, 36639, 36597, 36556, 36514, 36472, 36430, 36388, 36347, 36305, 36263, 36221, 36179, 36137, 36095, 36053, 36011, 35969, 35927, 35885, 35843, 35801, 35759, 35717, 35675, 35633, 35590, 35548, 35506, 35464, 35421, 35379, 35337, 35294, 35252, 35210, 35167, 35125, 35082, 35040, 34997, 34955, 34912, 34870, 34827, 34785, 34742, 34699, 34657, 34614, 34571, 34529, 34486, 34443, 34400, 34358, 34315, 34272, 34229, 34186, 34143, 34100, 34057, 34015, 33972, 33929, 33886, 33843, 33799, 33756, 33713, 33670, 33627, 33584, 33541, 33498, 33454, 33411, 33368, 33325, 33281, 33238, 33195, 33151, 33108, 33065, 33021, 32978, 32934, 32891, 32847, 32804, 32760, 32717, 32673, 32630, 32586, 32542, 32499, 32455, 32411, 32368, 32324, 32280, 32236, 32193, 32149, 32105, 32061, 32017, 31974, 31930, 31886, 31842, 31798, 31754, 31710, 31666, 31622, 31578, 31534, 31490, 31446, 31402, 31357, 31313, 31269, 31225, 31181, 31136, 31092, 31048, 31004, 30959, 30915, 30871, 30826, 30782, 30738, 30693, 30649, 30604, 30560, 30515, 30471, 30426, 30382, 30337, 30293, 30248, 30204, 30159, 30114, 30070, 30025, 29980, 29936, 29891, 29846, 29801, 29757, 29712, 29667, 29622, 29577, 29533, 29488, 29443, 29398, 29353, 29308, 29263, 29218, 29173, 29128, 29083, 29038, 28993, 28948, 28903, 28858, 28812, 28767, 28722, 28677, 28632, 28586, 28541, 28496, 28451, 28405, 28360, 28315, 28269, 28224, 28179, 28133, 28088, 28042, 27997, 27952, 27906, 27861, 27815, 27770, 27724, 27678, 27633, 27587, 27542, 27496, 27450, 27405, 27359, 27313, 27268, 27222, 27176, 27131, 27085, 27039, 26993, 26947, 26902, 26856, 26810, 26764, 26718, 26672, 26626, 26580, 26534, 26488, 26442, 26396, 26350, 26304, 26258, 26212, 26166, 26120, 26074, 26028, 25982, 25936, 25889, 25843, 25797, 25751, 25705, 25658, 25612, 25566, 25520, 25473, 25427, 25381, 25334, 25288, 25241, 25195, 25149, 25102, 25056, 25009, 24963, 24916, 24870, 24823, 24777, 24730, 24684, 24637, 24591, 24544, 24497, 24451, 24404, 24357, 24311, 24264, 24217, 24171, 24124, 24077, 24030, 23984, 23937, 23890, 23843, 23796, 23750, 23703, 23656, 23609, 23562, 23515, 23468, 23421, 23374, 23327, 23280, 23233, 23186, 23139, 23092, 23045, 22998, 22951, 22904, 22857, 22810, 22763, 22716, 22668, 22621, 22574, 22527, 22480, 22433, 22385, 22338, 22291, 22243, 22196, 22149, 22102, 22054, 22007, 21960, 21912, 21865, 21817, 21770, 21723, 21675, 21628, 21580, 21533, 21485, 21438, 21390, 21343, 21295, 21248, 21200, 21153, 21105, 21057, 21010, 20962, 20915, 20867, 20819, 20772, 20724, 20676, 20629, 20581, 20533, 20485, 20438, 20390, 20342, 20294, 20246, 20199, 20151, 20103, 20055, 20007, 19959, 19912, 19864, 19816, 19768, 19720, 19672, 19624, 19576, 19528, 19480, 19432, 19384, 19336, 19288, 19240, 19192, 19144, 19096, 19048, 19000, 18951, 18903, 18855, 18807, 18759, 18711, 18663, 18614, 18566, 18518, 18470, 18421, 18373, 18325, 18277, 18228, 18180, 18132, 18084, 18035, 17987, 17939, 17890, 17842, 17793, 17745, 17697, 17648, 17600, 17551, 17503, 17455, 17406, 17358, 17309, 17261, 17212, 17164, 17115, 17067, 17018, 16970, 16921, 16872, 16824, 16775, 16727, 16678, 16629, 16581, 16532, 16484, 16435, 16386, 16338, 16289, 16240, 16191, 16143, 16094, 16045, 15997, 15948, 15899, 15850, 15802, 15753, 15704, 15655, 15606, 15557, 15509, 15460, 15411, 15362, 15313, 15264, 15215, 15167, 15118, 15069, 15020, 14971, 14922, 14873, 14824, 14775, 14726, 14677, 14628, 14579, 14530, 14481, 14432, 14383, 14334, 14285, 14236, 14187, 14138, 14089, 14040, 13990, 13941, 13892, 13843, 13794, 13745, 13696, 13646, 13597, 13548, 13499, 13450, 13401, 13351, 13302, 13253, 13204, 13154, 13105, 13056, 13007, 12957, 12908, 12859, 12810, 12760, 12711, 12662, 12612, 12563, 12514, 12464, 12415, 12366, 12316, 12267, 12218, 12168, 12119, 12069, 12020, 11970, 11921, 11872, 11822, 11773, 11723, 11674, 11624, 11575, 11525, 11476, 11426, 11377, 11327, 11278, 11228, 11179, 11129, 11080, 11030, 10981, 10931, 10882, 10832, 10782, 10733, 10683, 10634, 10584, 10534, 10485, 10435, 10386, 10336, 10286, 10237, 10187, 10137, 10088, 10038, 9988, 9939, 9889, 9839, 9790, 9740, 9690, 9640, 9591, 9541, 9491, 9442, 9392, 9342, 9292, 9243, 9193, 9143, 9093, 9043, 8994, 8944, 8894, 8844, 8794, 8745, 8695, 8645, 8595, 8545, 8496, 8446, 8396, 8346, 8296, 8246, 8196, 8147, 8097, 8047, 7997, 7947, 7897, 7847, 7797, 7747, 7697, 7648, 7598, 7548, 7498, 7448, 7398, 7348, 7298, 7248, 7198, 7148, 7098, 7048, 6998, 6948, 6898, 6848, 6798, 6748, 6698, 6648, 6598, 6548, 6498, 6448, 6398, 6348, 6298, 6248, 6198, 6148, 6098, 6048, 5998, 5948, 5898, 5848, 5798, 5748, 5697, 5647, 5597, 5547, 5497, 5447, 5397, 5347, 5297, 5247, 5197, 5146, 5096, 5046, 4996, 4946, 4896, 4846, 4796, 4745, 4695, 4645, 4595, 4545, 4495, 4445, 4394, 4344, 4294, 4244, 4194, 4144, 4093, 4043, 3993, 3943, 3893, 3843, 3792, 3742, 3692, 3642, 3592, 3541, 3491, 3441, 3391, 3341, 3291, 3240, 3190, 3140, 3090, 3039, 2989, 2939, 2889, 2839, 2788, 2738, 2688, 2638, 2587, 2537, 2487, 2437, 2387, 2336, 2286, 2236, 2186, 2135, 2085, 2035, 1985, 1934, 1884, 1834, 1784, 1733, 1683, 1633, 1583, 1532, 1482, 1432, 1382, 1331, 1281, 1231, 1181, 1130, 1080, 1030, 980, 929, 879, 829, 779, 728, 678, 628, 578, 527, 477, 427, 376, 326, 276, 226, 175, 125, 75, 25, -25, -75, -125, -175, -226, -276, -326, -376, -427, -477, -527, -578, -628, -678, -728, -779, -829, -879, -929, -980, -1030, -1080, -1130, -1181, -1231, -1281, -1331, -1382, -1432, -1482, -1532, -1583, -1633, -1683, -1733, -1784, -1834, -1884, -1934, -1985, -2035, -2085, -2135, -2186, -2236, -2286, -2336, -2387, -2437, -2487, -2537, -2588, -2638, -2688, -2738, -2788, -2839, -2889, -2939, -2989, -3039, -3090, -3140, -3190, -3240, -3291, -3341, -3391, -3441, -3491, -3541, -3592, -3642, -3692, -3742, -3792, -3843, -3893, -3943, -3993, -4043, -4093, -4144, -4194, -4244, -4294, -4344, -4394, -4445, -4495, -4545, -4595, -4645, -4695, -4745, -4796, -4846, -4896, -4946, -4996, -5046, -5096, -5146, -5197, -5247, -5297, -5347, -5397, -5447, -5497, -5547, -5597, -5647, -5697, -5748, -5798, -5848, -5898, -5948, -5998, -6048, -6098, -6148, -6198, -6248, -6298, -6348, -6398, -6448, -6498, -6548, -6598, -6648, -6698, -6748, -6798, -6848, -6898, -6948, -6998, -7048, -7098, -7148, -7198, -7248, -7298, -7348, -7398, -7448, -7498, -7548, -7598, -7648, -7697, -7747, -7797, -7847, -7897, -7947, -7997, -8047, -8097, -8147, -8196, -8246, -8296, -8346, -8396, -8446, -8496, -8545, -8595, -8645, -8695, -8745, -8794, -8844, -8894, -8944, -8994, -9043, -9093, -9143, -9193, -9243, -9292, -9342, -9392, -9442, -9491, -9541, -9591, -9640, -9690, -9740, -9790, -9839, -9889, -9939, -9988, -10038, -10088, -10137, -10187, -10237, -10286, -10336, -10386, -10435, -10485, -10534, -10584, -10634, -10683, -10733, -10782, -10832, -10882, -10931, -10981, -11030, -11080, -11129, -11179, -11228, -11278, -11327, -11377, -11426, -11476, -11525, -11575, -11624, -11674, -11723, -11773, -11822, -11872, -11921, -11970, -12020, -12069, -12119, -12168, -12218, -12267, -12316, -12366, -12415, -12464, -12514, -12563, -12612, -12662, -12711, -12760, -12810, -12859, -12908, -12957, -13007, -13056, -13105, -13154, -13204, -13253, -13302, -13351, -13401, -13450, -13499, -13548, -13597, -13647, -13696, -13745, -13794, -13843, -13892, -13941, -13990, -14040, -14089, -14138, -14187, -14236, -14285, -14334, -14383, -14432, -14481, -14530, -14579, -14628, -14677, -14726, -14775, -14824, -14873, -14922, -14971, -15020, -15069, -15118, -15167, -15215, -15264, -15313, -15362, -15411, -15460, -15509, -15557, -15606, -15655, -15704, -15753, -15802, -15850, -15899, -15948, -15997, -16045, -16094, -16143, -16191, -16240, -16289, -16338, -16386, -16435, -16484, -16532, -16581, -16629, -16678, -16727, -16775, -16824, -16872, -16921, -16970, -17018, -17067, -17115, -17164, -17212, -17261, -17309, -17358, -17406, -17455, -17503, -17551, -17600, -17648, -17697, -17745, -17793, -17842, -17890, -17939, -17987, -18035, -18084, -18132, -18180, -18228, -18277, -18325, -18373, -18421, -18470, -18518, -18566, -18614, -18663, -18711, -18759, -18807, -18855, -18903, -18951, -19000, -19048, -19096, -19144, -19192, -19240, -19288, -19336, -19384, -19432, -19480, -19528, -19576, -19624, -19672, -19720, -19768, -19816, -19864, -19912, -19959, -20007, -20055, -20103, -20151, -20199, -20246, -20294, -20342, -20390, -20438, -20485, -20533, -20581, -20629, -20676, -20724, -20772, -20819, -20867, -20915, -20962, -21010, -21057, -21105, -21153, -21200, -21248, -21295, -21343, -21390, -21438, -21485, -21533, -21580, -21628, -21675, -21723, -21770, -21817, -21865, -21912, -21960, -22007, -22054, -22102, -22149, -22196, -22243, -22291, -22338, -22385, -22433, -22480, -22527, -22574, -22621, -22668, -22716, -22763, -22810, -22857, -22904, -22951, -22998, -23045, -23092, -23139, -23186, -23233, -23280, -23327, -23374, -23421, -23468, -23515, -23562, -23609, -23656, -23703, -23750, -23796, -23843, -23890, -23937, -23984, -24030, -24077, -24124, -24171, -24217, -24264, -24311, -24357, -24404, -24451, -24497, -24544, -24591, -24637, -24684, -24730, -24777, -24823, -24870, -24916, -24963, -25009, -25056, -25102, -25149, -25195, -25241, -25288, -25334, -25381, -25427, -25473, -25520, -25566, -25612, -25658, -25705, -25751, -25797, -25843, -25889, -25936, -25982, -26028, -26074, -26120, -26166, -26212, -26258, -26304, -26350, -26396, -26442, -26488, -26534, -26580, -26626, -26672, -26718, -26764, -26810, -26856, -26902, -26947, -26993, -27039, -27085, -27131, -27176, -27222, -27268, -27313, -27359, -27405, -27450, -27496, -27542, -27587, -27633, -27678, -27724, -27770, -27815, -27861, -27906, -27952, -27997, -28042, -28088, -28133, -28179, -28224, -28269, -28315, -28360, -28405, -28451, -28496, -28541, -28586, -28632, -28677, -28722, -28767, -28812, -28858, -28903, -28948, -28993, -29038, -29083, -29128, -29173, -29218, -29263, -29308, -29353, -29398, -29443, -29488, -29533, -29577, -29622, -29667, -29712, -29757, -29801, -29846, -29891, -29936, -29980, -30025, -30070, -30114, -30159, -30204, -30248, -30293, -30337, -30382, -30426, -30471, -30515, -30560, -30604, -30649, -30693, -30738, -30782, -30826, -30871, -30915, -30959, -31004, -31048, -31092, -31136, -31181, -31225, -31269, -31313, -31357, -31402, -31446, -31490, -31534, -31578, -31622, -31666, -31710, -31754, -31798, -31842, -31886, -31930, -31974, -32017, -32061, -32105, -32149, -32193, -32236, -32280, -32324, -32368, -32411, -32455, -32499, -32542, -32586, -32630, -32673, -32717, -32760, -32804, -32847, -32891, -32934, -32978, -33021, -33065, -33108, -33151, -33195, -33238, -33281, -33325, -33368, -33411, -33454, -33498, -33541, -33584, -33627, -33670, -33713, -33756, -33799, -33843, -33886, -33929, -33972, -34015, -34057, -34100, -34143, -34186, -34229, -34272, -34315, -34358, -34400, -34443, -34486, -34529, -34571, -34614, -34657, -34699, -34742, -34785, -34827, -34870, -34912, -34955, -34997, -35040, -35082, -35125, -35167, -35210, -35252, -35294, -35337, -35379, -35421, -35464, -35506, -35548, -35590, -35633, -35675, -35717, -35759, -35801, -35843, -35885, -35927, -35969, -36011, -36053, -36095, -36137, -36179, -36221, -36263, -36305, -36347, -36388, -36430, -36472, -36514, -36555, -36597, -36639, -36681, -36722, -36764, -36805, -36847, -36889, -36930, -36972, -37013, -37055, -37096, -37137, -37179, -37220, -37262, -37303, -37344, -37386, -37427, -37468, -37509, -37551, -37592, -37633, -37674, -37715, -37756, -37797, -37838, -37879, -37920, -37961, -38002, -38043, -38084, -38125, -38166, -38207, -38248, -38288, -38329, -38370, -38411, -38451, -38492, -38533, -38573, -38614, -38655, -38695, -38736, -38776, -38817, -38857, -38898, -38938, -38979, -39019, -39059, -39100, -39140, -39180, -39221, -39261, -39301, -39341, -39382, -39422, -39462, -39502, -39542, -39582, -39622, -39662, -39702, -39742, -39782, -39822, -39862, -39902, -39942, -39982, -40021, -40061, -40101, -40141, -40180, -40220, -40260, -40299, -40339, -40379, -40418, -40458, -40497, -40537, -40576, -40616, -40655, -40695, -40734, -40773, -40813, -40852, -40891, -40931, -40970, -41009, -41048, -41087, -41127, -41166, -41205, -41244, -41283, -41322, -41361, -41400, -41439, -41478, -41517, -41556, -41595, -41633, -41672, -41711, -41750, -41788, -41827, -41866, -41904, -41943, -41982, -42020, -42059, -42097, -42136, -42174, -42213, -42251, -42290, -42328, -42366, -42405, -42443, -42481, -42520, -42558, -42596, -42634, -42672, -42711, -42749, -42787, -42825, -42863, -42901, -42939, -42977, -43015, -43053, -43091, -43128, -43166, -43204, -43242, -43280, -43317, -43355, -43393, -43430, -43468, -43506, -43543, -43581, -43618, -43656, -43693, -43731, -43768, -43806, -43843, -43880, -43918, -43955, -43992, -44029, -44067, -44104, -44141, -44178, -44215, -44252, -44289, -44326, -44363, -44400, -44437, -44474, -44511, -44548, -44585, -44622, -44659, -44695, -44732, -44769, -44806, -44842, -44879, -44915, -44952, -44989, -45025, -45062, -45098, -45135, -45171, -45207, -45244, -45280, -45316, -45353, -45389, -45425, -45462, -45498, -45534, -45570, -45606, -45642, -45678, -45714, -45750, -45786, -45822, -45858, -45894, -45930, -45966, -46002, -46037, -46073, -46109, -46145, -46180, -46216, -46252, -46287, -46323, -46358, -46394, -46429, -46465, -46500, -46536, -46571, -46606, -46642, -46677, -46712, -46747, -46783, -46818, -46853, -46888, -46923, -46958, -46993, -47028, -47063, -47098, -47133, -47168, -47203, -47238, -47273, -47308, -47342, -47377, -47412, -47446, -47481, -47516, -47550, -47585, -47619, -47654, -47688, -47723, -47757, -47792, -47826, -47860, -47895, -47929, -47963, -47998, -48032, -48066, -48100, -48134, -48168, -48202, -48236, -48271, -48304, -48338, -48372, -48406, -48440, -48474, -48508, -48542, -48575, -48609, -48643, -48676, -48710, -48744, -48777, -48811, -48844, -48878, -48911, -48945, -48978, -49012, -49045, -49078, -49112, -49145, -49178, -49211, -49244, -49278, -49311, -49344, -49377, -49410, -49443, -49476, -49509, -49542, -49575, -49608, -49640, -49673, -49706, -49739, -49771, -49804, -49837, -49869, -49902, -49935, -49967, -50000, -50032, -50065, -50097, -50129, -50162, -50194, -50226, -50259, -50291, -50323, -50355, -50387, -50420, -50452, -50484, -50516, -50548, -50580, -50612, -50644, -50675, -50707, -50739, -50771, -50803, -50834, -50866, -50898, -50929, -50961, -50993, -51024, -51056, -51087, -51119, -51150, -51182, -51213, -51244, -51276, -51307, -51338, -51369, -51401, -51432, -51463, -51494, -51525, -51556, -51587, -51618, -51649, -51680, -51711, -51742, -51773, -51803, -51834, -51865, -51896, -51926, -51957, -51988, -52018, -52049, -52079, -52110, -52140, -52171, -52201, -52231, -52262, -52292, -52322, -52353, -52383, -52413, -52443, -52473, -52503, -52534, -52564, -52594, -52624, -52653, -52683, -52713, -52743, -52773, -52803, -52832, -52862, -52892, -52922, -52951, -52981, -53010, -53040, -53069, -53099, -53128, -53158, -53187, -53216, -53246, -53275, -53304, -53334, -53363, -53392, -53421, -53450, -53479, -53508, -53537, -53566, -53595, -53624, -53653, -53682, -53711, -53739, -53768, -53797, -53826, -53854, -53883, -53911, -53940, -53969, -53997, -54026, -54054, -54082, -54111, -54139, -54167, -54196, -54224, -54252, -54280, -54308, -54337, -54365, -54393, -54421, -54449, -54477, -54505, -54533, -54560, -54588, -54616, -54644, -54672, -54699, -54727, -54755, -54782, -54810, -54837, -54865, -54892, -54920, -54947, -54974, -55002, -55029, -55056, -55084, -55111, -55138, -55165, -55192, -55219, -55246, -55274, -55300, -55327, -55354, -55381, -55408, -55435, -55462, -55489, -55515, -55542, -55569, -55595, -55622, -55648, -55675, -55701, -55728, -55754, -55781, -55807, -55833, -55860, -55886, -55912, -55938, -55965, -55991, -56017, -56043, -56069, -56095, -56121, -56147, -56173, -56199, -56225, -56250, -56276, -56302, -56328, -56353, -56379, -56404, -56430, -56456, -56481, -56507, -56532, -56557, -56583, -56608, -56633, -56659, -56684, -56709, -56734, -56760, -56785, -56810, -56835, -56860, -56885, -56910, -56935, -56959, -56984, -57009, -57034, -57059, -57083, -57108, -57133, -57157, -57182, -57206, -57231, -57255, -57280, -57304, -57329, -57353, -57377, -57402, -57426, -57450, -57474, -57498, -57522, -57546, -57570, -57594, -57618, -57642, -57666, -57690, -57714, -57738, -57762, -57785, -57809, -57833, -57856, -57880, -57903, -57927, -57950, -57974, -57997, -58021, -58044, -58067, -58091, -58114, -58137, -58160, -58183, -58207, -58230, -58253, -58276, -58299, -58322, -58345, -58367, -58390, -58413, -58436, -58459, -58481, -58504, -58527, -58549, -58572, -58594, -58617, -58639, -58662, -58684, -58706, -58729, -58751, -58773, -58795, -58818, -58840, -58862, -58884, -58906, -58928, -58950, -58972, -58994, -59016, -59038, -59059, -59081, -59103, -59125, -59146, -59168, -59190, -59211, -59233, -59254, -59276, -59297, -59318, -59340, -59361, -59382, -59404, -59425, -59446, -59467, -59488, -59509, -59530, -59551, -59572, -59593, -59614, -59635, -59656, -59677, -59697, -59718, -59739, -59759, -59780, -59801, -59821, -59842, -59862, -59883, -59903, -59923, -59944, -59964, -59984, -60004, -60025, -60045, -60065, -60085, -60105, -60125, -60145, -60165, -60185, -60205, -60225, -60244, -60264, -60284, -60304, -60323, -60343, -60363, -60382, -60402, -60421, -60441, -60460, -60479, -60499, -60518, -60537, -60556, -60576, -60595, -60614, -60633, -60652, -60671, -60690, -60709, -60728, -60747, -60766, -60785, -60803, -60822, -60841, -60859, -60878, -60897, -60915, -60934, -60952, -60971, -60989, -61007, -61026, -61044, -61062, -61081, -61099, -61117, -61135, -61153, -61171, -61189, -61207, -61225, -61243, -61261, -61279, -61297, -61314, -61332, -61350, -61367, -61385, -61403, -61420, -61438, -61455, -61473, -61490, -61507, -61525, -61542, -61559, -61577, -61594, -61611, -61628, -61645, -61662, -61679, -61696, -61713, -61730, -61747, -61764, -61780, -61797, -61814, -61831, -61847, -61864, -61880, -61897, -61913, -61930, -61946, -61963, -61979, -61995, -62012, -62028, -62044, -62060, -62076, -62092, -62108, -62125, -62141, -62156, -62172, -62188, -62204, -62220, -62236, -62251, -62267, -62283, -62298, -62314, -62329, -62345, -62360, -62376, -62391, -62407, -62422, -62437, -62453, -62468, -62483, -62498, -62513, -62528, -62543, -62558, -62573, -62588, -62603, -62618, -62633, -62648, -62662, -62677, -62692, -62706, -62721, -62735, -62750, -62764, -62779, -62793, -62808, -62822, -62836, -62850, -62865, -62879, -62893, -62907, -62921, -62935, -62949, -62963, -62977, -62991, -63005, -63019, -63032, -63046, -63060, -63074, -63087, -63101, -63114, -63128, -63141, -63155, -63168, -63182, -63195, -63208, -63221, -63235, -63248, -63261, -63274, -63287, -63300, -63313, -63326, -63339, -63352, -63365, -63378, -63390, -63403, -63416, -63429, -63441, -63454, -63466, -63479, -63491, -63504, -63516, -63528, -63541, -63553, -63565, -63578, -63590, -63602, -63614, -63626, -63638, -63650, -63662, -63674, -63686, -63698, -63709, -63721, -63733, -63745, -63756, -63768, -63779, -63791, -63803, -63814, -63825, -63837, -63848, -63859, -63871, -63882, -63893, -63904, -63915, -63927, -63938, -63949, -63960, -63971, -63981, -63992, -64003, -64014, -64025, -64035, -64046, -64057, -64067, -64078, -64088, -64099, -64109, -64120, -64130, -64140, -64151, -64161, -64171, -64181, -64192, -64202, -64212, -64222, -64232, -64242, -64252, -64261, -64271, -64281, -64291, -64301, -64310, -64320, -64330, -64339, -64349, -64358, -64368, -64377, -64387, -64396, -64405, -64414, -64424, -64433, -64442, -64451, -64460, -64469, -64478, -64487, -64496, -64505, -64514, -64523, -64532, -64540, -64549, -64558, -64566, -64575, -64584, -64592, -64601, -64609, -64617, -64626, -64634, -64642, -64651, -64659, -64667, -64675, -64683, -64691, -64699, -64707, -64715, -64723, -64731, -64739, -64747, -64754, -64762, -64770, -64777, -64785, -64793, -64800, -64808, -64815, -64822, -64830, -64837, -64844, -64852, -64859, -64866, -64873, -64880, -64887, -64895, -64902, -64908, -64915, -64922, -64929, -64936, -64943, -64949, -64956, -64963, -64969, -64976, -64982, -64989, -64995, -65002, -65008, -65015, -65021, -65027, -65033, -65040, -65046, -65052, -65058, -65064, -65070, -65076, -65082, -65088, -65094, -65099, -65105, -65111, -65117, -65122, -65128, -65133, -65139, -65144, -65150, -65155, -65161, -65166, -65171, -65177, -65182, -65187, -65192, -65197, -65202, -65207, -65212, -65217, -65222, -65227, -65232, -65237, -65242, -65246, -65251, -65256, -65260, -65265, -65270, -65274, -65279, -65283, -65287, -65292, -65296, -65300, -65305, -65309, -65313, -65317, -65321, -65325, -65329, -65333, -65337, -65341, -65345, -65349, -65352, -65356, -65360, -65363, -65367, -65371, -65374, -65378, -65381, -65385, -65388, -65391, -65395, -65398, -65401, -65404, -65408, -65411, -65414, -65417, -65420, -65423, -65426, -65429, -65431, -65434, -65437, -65440, -65442, -65445, -65448, -65450, -65453, -65455, -65458, -65460, -65463, -65465, -65467, -65470, -65472, -65474, -65476, -65478, -65480, -65482, -65484, -65486, -65488, -65490, -65492, -65494, -65496, -65497, -65499, -65501, -65502, -65504, -65505, -65507, -65508, -65510, -65511, -65513, -65514, -65515, -65516, -65518, -65519, -65520, -65521, -65522, -65523, -65524, -65525, -65526, -65527, -65527, -65528, -65529, -65530, -65530, -65531, -65531, -65532, -65532, -65533, -65533, -65534, -65534, -65534, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65534, -65534, -65534, -65533, -65533, -65532, -65532, -65531, -65531, -65530, -65530, -65529, -65528, -65527, -65527, -65526, -65525, -65524, -65523, -65522, -65521, -65520, -65519, -65518, -65516, -65515, -65514, -65513, -65511, -65510, -65508, -65507, -65505, -65504, -65502, -65501, -65499, -65497, -65496, -65494, -65492, -65490, -65488, -65486, -65484, -65482, -65480, -65478, -65476, -65474, -65472, -65470, -65467, -65465, -65463, -65460, -65458, -65455, -65453, -65450, -65448, -65445, -65442, -65440, -65437, -65434, -65431, -65429, -65426, -65423, -65420, -65417, -65414, -65411, -65408, -65404, -65401, -65398, -65395, -65391, -65388, -65385, -65381, -65378, -65374, -65371, -65367, -65363, -65360, -65356, -65352, -65349, -65345, -65341, -65337, -65333, -65329, -65325, -65321, -65317, -65313, -65309, -65305, -65300, -65296, -65292, -65287, -65283, -65279, -65274, -65270, -65265, -65260, -65256, -65251, -65246, -65242, -65237, -65232, -65227, -65222, -65217, -65212, -65207, -65202, -65197, -65192, -65187, -65182, -65177, -65171, -65166, -65161, -65155, -65150, -65144, -65139, -65133, -65128, -65122, -65117, -65111, -65105, -65099, -65094, -65088, -65082, -65076, -65070, -65064, -65058, -65052, -65046, -65040, -65033, -65027, -65021, -65015, -65008, -65002, -64995, -64989, -64982, -64976, -64969, -64963, -64956, -64949, -64943, -64936, -64929, -64922, -64915, -64908, -64902, -64895, -64887, -64880, -64873, -64866, -64859, -64852, -64844, -64837, -64830, -64822, -64815, -64808, -64800, -64793, -64785, -64777, -64770, -64762, -64754, -64747, -64739, -64731, -64723, -64715, -64707, -64699, -64691, -64683, -64675, -64667, -64659, -64651, -64642, -64634, -64626, -64617, -64609, -64601, -64592, -64584, -64575, -64566, -64558, -64549, -64540, -64532, -64523, -64514, -64505, -64496, -64487, -64478, -64469, -64460, -64451, -64442, -64433, -64424, -64414, -64405, -64396, -64387, -64377, -64368, -64358, -64349, -64339, -64330, -64320, -64310, -64301, -64291, -64281, -64271, -64261, -64252, -64242, -64232, -64222, -64212, -64202, -64192, -64181, -64171, -64161, -64151, -64140, -64130, -64120, -64109, -64099, -64088, -64078, -64067, -64057, -64046, -64035, -64025, -64014, -64003, -63992, -63981, -63971, -63960, -63949, -63938, -63927, -63915, -63904, -63893, -63882, -63871, -63859, -63848, -63837, -63825, -63814, -63803, -63791, -63779, -63768, -63756, -63745, -63733, -63721, -63709, -63698, -63686, -63674, -63662, -63650, -63638, -63626, -63614, -63602, -63590, -63578, -63565, -63553, -63541, -63528, -63516, -63504, -63491, -63479, -63466, -63454, -63441, -63429, -63416, -63403, -63390, -63378, -63365, -63352, -63339, -63326, -63313, -63300, -63287, -63274, -63261, -63248, -63235, -63221, -63208, -63195, -63182, -63168, -63155, -63141, -63128, -63114, -63101, -63087, -63074, -63060, -63046, -63032, -63019, -63005, -62991, -62977, -62963, -62949, -62935, -62921, -62907, -62893, -62879, -62865, -62850, -62836, -62822, -62808, -62793, -62779, -62764, -62750, -62735, -62721, -62706, -62692, -62677, -62662, -62648, -62633, -62618, -62603, -62588, -62573, -62558, -62543, -62528, -62513, -62498, -62483, -62468, -62453, -62437, -62422, -62407, -62391, -62376, -62360, -62345, -62329, -62314, -62298, -62283, -62267, -62251, -62236, -62220, -62204, -62188, -62172, -62156, -62141, -62125, -62108, -62092, -62076, -62060, -62044, -62028, -62012, -61995, -61979, -61963, -61946, -61930, -61913, -61897, -61880, -61864, -61847, -61831, -61814, -61797, -61780, -61764, -61747, -61730, -61713, -61696, -61679, -61662, -61645, -61628, -61611, -61594, -61577, -61559, -61542, -61525, -61507, -61490, -61473, -61455, -61438, -61420, -61403, -61385, -61367, -61350, -61332, -61314, -61297, -61279, -61261, -61243, -61225, -61207, -61189, -61171, -61153, -61135, -61117, -61099, -61081, -61062, -61044, -61026, -61007, -60989, -60971, -60952, -60934, -60915, -60897, -60878, -60859, -60841, -60822, -60803, -60785, -60766, -60747, -60728, -60709, -60690, -60671, -60652, -60633, -60614, -60595, -60576, -60556, -60537, -60518, -60499, -60479, -60460, -60441, -60421, -60402, -60382, -60363, -60343, -60323, -60304, -60284, -60264, -60244, -60225, -60205, -60185, -60165, -60145, -60125, -60105, -60085, -60065, -60045, -60025, -60004, -59984, -59964, -59944, -59923, -59903, -59883, -59862, -59842, -59821, -59801, -59780, -59759, -59739, -59718, -59697, -59677, -59656, -59635, -59614, -59593, -59572, -59551, -59530, -59509, -59488, -59467, -59446, -59425, -59404, -59382, -59361, -59340, -59318, -59297, -59276, -59254, -59233, -59211, -59189, -59168, -59146, -59125, -59103, -59081, -59059, -59038, -59016, -58994, -58972, -58950, -58928, -58906, -58884, -58862, -58840, -58818, -58795, -58773, -58751, -58729, -58706, -58684, -58662, -58639, -58617, -58594, -58572, -58549, -58527, -58504, -58481, -58459, -58436, -58413, -58390, -58367, -58345, -58322, -58299, -58276, -58253, -58230, -58207, -58183, -58160, -58137, -58114, -58091, -58067, -58044, -58021, -57997, -57974, -57950, -57927, -57903, -57880, -57856, -57833, -57809, -57785, -57762, -57738, -57714, -57690, -57666, -57642, -57618, -57594, -57570, -57546, -57522, -57498, -57474, -57450, -57426, -57402, -57377, -57353, -57329, -57304, -57280, -57255, -57231, -57206, -57182, -57157, -57133, -57108, -57083, -57059, -57034, -57009, -56984, -56959, -56935, -56910, -56885, -56860, -56835, -56810, -56785, -56760, -56734, -56709, -56684, -56659, -56633, -56608, -56583, -56557, -56532, -56507, -56481, -56456, -56430, -56404, -56379, -56353, -56328, -56302, -56276, -56250, -56225, -56199, -56173, -56147, -56121, -56095, -56069, -56043, -56017, -55991, -55965, -55938, -55912, -55886, -55860, -55833, -55807, -55781, -55754, -55728, -55701, -55675, -55648, -55622, -55595, -55569, -55542, -55515, -55489, -55462, -55435, -55408, -55381, -55354, -55327, -55300, -55274, -55246, -55219, -55192, -55165, -55138, -55111, -55084, -55056, -55029, -55002, -54974, -54947, -54920, -54892, -54865, -54837, -54810, -54782, -54755, -54727, -54699, -54672, -54644, -54616, -54588, -54560, -54533, -54505, -54477, -54449, -54421, -54393, -54365, -54337, -54308, -54280, -54252, -54224, -54196, -54167, -54139, -54111, -54082, -54054, -54026, -53997, -53969, -53940, -53911, -53883, -53854, -53826, -53797, -53768, -53739, -53711, -53682, -53653, -53624, -53595, -53566, -53537, -53508, -53479, -53450, -53421, -53392, -53363, -53334, -53304, -53275, -53246, -53216, -53187, -53158, -53128, -53099, -53069, -53040, -53010, -52981, -52951, -52922, -52892, -52862, -52832, -52803, -52773, -52743, -52713, -52683, -52653, -52624, -52594, -52564, -52534, -52503, -52473, -52443, -52413, -52383, -52353, -52322, -52292, -52262, -52231, -52201, -52171, -52140, -52110, -52079, -52049, -52018, -51988, -51957, -51926, -51896, -51865, -51834, -51803, -51773, -51742, -51711, -51680, -51649, -51618, -51587, -51556, -51525, -51494, -51463, -51432, -51401, -51369, -51338, -51307, -51276, -51244, -51213, -51182, -51150, -51119, -51087, -51056, -51024, -50993, -50961, -50929, -50898, -50866, -50834, -50803, -50771, -50739, -50707, -50675, -50644, -50612, -50580, -50548, -50516, -50484, -50452, -50420, -50387, -50355, -50323, -50291, -50259, -50226, -50194, -50162, -50129, -50097, -50065, -50032, -50000, -49967, -49935, -49902, -49869, -49837, -49804, -49771, -49739, -49706, -49673, -49640, -49608, -49575, -49542, -49509, -49476, -49443, -49410, -49377, -49344, -49311, -49278, -49244, -49211, -49178, -49145, -49112, -49078, -49045, -49012, -48978, -48945, -48911, -48878, -48844, -48811, -48777, -48744, -48710, -48676, -48643, -48609, -48575, -48542, -48508, -48474, -48440, -48406, -48372, -48338, -48305, -48271, -48237, -48202, -48168, -48134, -48100, -48066, -48032, -47998, -47963, -47929, -47895, -47860, -47826, -47792, -47757, -47723, -47688, -47654, -47619, -47585, -47550, -47516, -47481, -47446, -47412, -47377, -47342, -47307, -47273, -47238, -47203, -47168, -47133, -47098, -47063, -47028, -46993, -46958, -46923, -46888, -46853, -46818, -46783, -46747, -46712, -46677, -46642, -46606, -46571, -46536, -46500, -46465, -46429, -46394, -46358, -46323, -46287, -46251, -46216, -46180, -46145, -46109, -46073, -46037, -46002, -45966, -45930, -45894, -45858, -45822, -45786, -45750, -45714, -45678, -45642, -45606, -45570, -45534, -45498, -45462, -45425, -45389, -45353, -45316, -45280, -45244, -45207, -45171, -45135, -45098, -45062, -45025, -44989, -44952, -44915, -44879, -44842, -44806, -44769, -44732, -44695, -44659, -44622, -44585, -44548, -44511, -44474, -44437, -44400, -44363, -44326, -44289, -44252, -44215, -44178, -44141, -44104, -44067, -44029, -43992, -43955, -43918, -43880, -43843, -43806, -43768, -43731, -43693, -43656, -43618, -43581, -43543, -43506, -43468, -43430, -43393, -43355, -43317, -43280, -43242, -43204, -43166, -43128, -43091, -43053, -43015, -42977, -42939, -42901, -42863, -42825, -42787, -42749, -42711, -42672, -42634, -42596, -42558, -42520, -42481, -42443, -42405, -42366, -42328, -42290, -42251, -42213, -42174, -42136, -42097, -42059, -42020, -41982, -41943, -41904, -41866, -41827, -41788, -41750, -41711, -41672, -41633, -41595, -41556, -41517, -41478, -41439, -41400, -41361, -41322, -41283, -41244, -41205, -41166, -41127, -41087, -41048, -41009, -40970, -40931, -40891, -40852, -40813, -40773, -40734, -40695, -40655, -40616, -40576, -40537, -40497, -40458, -40418, -40379, -40339, -40299, -40260, -40220, -40180, -40141, -40101, -40061, -40021, -39982, -39942, -39902, -39862, -39822, -39782, -39742, -39702, -39662, -39622, -39582, -39542, -39502, -39462, -39422, -39382, -39341, -39301, -39261, -39221, -39180, -39140, -39100, -39059, -39019, -38979, -38938, -38898, -38857, -38817, -38776, -38736, -38695, -38655, -38614, -38573, -38533, -38492, -38451, -38411, -38370, -38329, -38288, -38248, -38207, -38166, -38125, -38084, -38043, -38002, -37961, -37920, -37879, -37838, -37797, -37756, -37715, -37674, -37633, -37592, -37550, -37509, -37468, -37427, -37386, -37344, -37303, -37262, -37220, -37179, -37137, -37096, -37055, -37013, -36972, -36930, -36889, -36847, -36805, -36764, -36722, -36681, -36639, -36597, -36556, -36514, -36472, -36430, -36388, -36347, -36305, -36263, -36221, -36179, -36137, -36095, -36053, -36011, -35969, -35927, -35885, -35843, -35801, -35759, -35717, -35675, -35633, -35590, -35548, -35506, -35464, -35421, -35379, -35337, -35294, -35252, -35210, -35167, -35125, -35082, -35040, -34997, -34955, -34912, -34870, -34827, -34785, -34742, -34699, -34657, -34614, -34571, -34529, -34486, -34443, -34400, -34358, -34315, -34272, -34229, -34186, -34143, -34100, -34057, -34015, -33972, -33929, -33886, -33843, -33799, -33756, -33713, -33670, -33627, -33584, -33541, -33498, -33454, -33411, -33368, -33325, -33281, -33238, -33195, -33151, -33108, -33065, -33021, -32978, -32934, -32891, -32847, -32804, -32760, -32717, -32673, -32630, -32586, -32542, -32499, -32455, -32411, -32368, -32324, -32280, -32236, -32193, -32149, -32105, -32061, -32017, -31974, -31930, -31886, -31842, -31798, -31754, -31710, -31666, -31622, -31578, -31534, -31490, -31446, -31402, -31357, -31313, -31269, -31225, -31181, -31136, -31092, -31048, -31004, -30959, -30915, -30871, -30826, -30782, -30738, -30693, -30649, -30604, -30560, -30515, -30471, -30426, -30382, -30337, -30293, -30248, -30204, -30159, -30114, -30070, -30025, -29980, -29936, -29891, -29846, -29801, -29757, -29712, -29667, -29622, -29577, -29533, -29488, -29443, -29398, -29353, -29308, -29263, -29218, -29173, -29128, -29083, -29038, -28993, -28948, -28903, -28858, -28812, -28767, -28722, -28677, -28632, -28586, -28541, -28496, -28451, -28405, -28360, -28315, -28269, -28224, -28179, -28133, -28088, -28042, -27997, -27952, -27906, -27861, -27815, -27770, -27724, -27678, -27633, -27587, -27542, -27496, -27450, -27405, -27359, -27313, -27268, -27222, -27176, -27131, -27085, -27039, -26993, -26947, -26902, -26856, -26810, -26764, -26718, -26672, -26626, -26580, -26534, -26488, -26442, -26396, -26350, -26304, -26258, -26212, -26166, -26120, -26074, -26028, -25982, -25936, -25889, -25843, -25797, -25751, -25705, -25658, -25612, -25566, -25520, -25473, -25427, -25381, -25334, -25288, -25241, -25195, -25149, -25102, -25056, -25009, -24963, -24916, -24870, -24823, -24777, -24730, -24684, -24637, -24591, -24544, -24497, -24451, -24404, -24357, -24311, -24264, -24217, -24171, -24124, -24077, -24030, -23984, -23937, -23890, -23843, -23796, -23750, -23703, -23656, -23609, -23562, -23515, -23468, -23421, -23374, -23327, -23280, -23233, -23186, -23139, -23092, -23045, -22998, -22951, -22904, -22857, -22810, -22763, -22716, -22668, -22621, -22574, -22527, -22480, -22432, -22385, -22338, -22291, -22243, -22196, -22149, -22102, -22054, -22007, -21960, -21912, -21865, -21817, -21770, -21723, -21675, -21628, -21580, -21533, -21485, -21438, -21390, -21343, -21295, -21248, -21200, -21153, -21105, -21057, -21010, -20962, -20915, -20867, -20819, -20772, -20724, -20676, -20629, -20581, -20533, -20485, -20438, -20390, -20342, -20294, -20246, -20199, -20151, -20103, -20055, -20007, -19959, -19912, -19864, -19816, -19768, -19720, -19672, -19624, -19576, -19528, -19480, -19432, -19384, -19336, -19288, -19240, -19192, -19144, -19096, -19048, -19000, -18951, -18903, -18855, -18807, -18759, -18711, -18663, -18614, -18566, -18518, -18470, -18421, -18373, -18325, -18277, -18228, -18180, -18132, -18084, -18035, -17987, -17939, -17890, -17842, -17793, -17745, -17697, -17648, -17600, -17551, -17503, -17455, -17406, -17358, -17309, -17261, -17212, -17164, -17115, -17067, -17018, -16970, -16921, -16872, -16824, -16775, -16727, -16678, -16629, -16581, -16532, -16484, -16435, -16386, -16338, -16289, -16240, -16191, -16143, -16094, -16045, -15997, -15948, -15899, -15850, -15802, -15753, -15704, -15655, -15606, -15557, -15509, -15460, -15411, -15362, -15313, -15264, -15215, -15167, -15118, -15069, -15020, -14971, -14922, -14873, -14824, -14775, -14726, -14677, -14628, -14579, -14530, -14481, -14432, -14383, -14334, -14285, -14236, -14187, -14138, -14089, -14040, -13990, -13941, -13892, -13843, -13794, -13745, -13696, -13647, -13597, -13548, -13499, -13450, -13401, -13351, -13302, -13253, -13204, -13154, -13105, -13056, -13007, -12957, -12908, -12859, -12810, -12760, -12711, -12662, -12612, -12563, -12514, -12464, -12415, -12366, -12316, -12267, -12217, -12168, -12119, -12069, -12020, -11970, -11921, -11872, -11822, -11773, -11723, -11674, -11624, -11575, -11525, -11476, -11426, -11377, -11327, -11278, -11228, -11179, -11129, -11080, -11030, -10981, -10931, -10882, -10832, -10782, -10733, -10683, -10634, -10584, -10534, -10485, -10435, -10386, -10336, -10286, -10237, -10187, -10137, -10088, -10038, -9988, -9939, -9889, -9839, -9790, -9740, -9690, -9640, -9591, -9541, -9491, -9442, -9392, -9342, -9292, -9243, -9193, -9143, -9093, -9043, -8994, -8944, -8894, -8844, -8794, -8745, -8695, -8645, -8595, -8545, -8496, -8446, -8396, -8346, -8296, -8246, -8196, -8147, -8097, -8047, -7997, -7947, -7897, -7847, -7797, -7747, -7697, -7648, -7598, -7548, -7498, -7448, -7398, -7348, -7298, -7248, -7198, -7148, -7098, -7048, -6998, -6948, -6898, -6848, -6798, -6748, -6698, -6648, -6598, -6548, -6498, -6448, -6398, -6348, -6298, -6248, -6198, -6148, -6098, -6048, -5998, -5948, -5898, -5848, -5798, -5747, -5697, -5647, -5597, -5547, -5497, -5447, -5397, -5347, -5297, -5247, -5197, -5146, -5096, -5046, -4996, -4946, -4896, -4846, -4796, -4745, -4695, -4645, -4595, -4545, -4495, -4445, -4394, -4344, -4294, -4244, -4194, -4144, -4093, -4043, -3993, -3943, -3893, -3843, -3792, -3742, -3692, -3642, -3592, -3541, -3491, -3441, -3391, -3341, -3291, -3240, -3190, -3140, -3090, -3039, -2989, -2939, -2889, -2839, -2788, -2738, -2688, -2638, -2588, -2537, -2487, -2437, -2387, -2336, -2286, -2236, -2186, -2135, -2085, -2035, -1985, -1934, -1884, -1834, -1784, -1733, -1683, -1633, -1583, -1532, -1482, -1432, -1382, -1331, -1281, -1231, -1181, -1130, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3542, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5747, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22432, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30427, 30471, 30516, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36556, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40299, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47861, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50064, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53912, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54309, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64600, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535 }; angle_t tantoangle[SLOPERANGE + 1] = { 0, 333772, 667544, 1001315, 1335086, 1668857, 2002626, 2336395, 2670163, 3003929, 3337694, 3671457, 4005219, 4338979, 4672736, 5006492, 5340245, 5673995, 6007743, 6341488, 6675230, 7008968, 7342704, 7676435, 8010164, 8343888, 8677609, 9011325, 9345037, 9678744, 10012447, 10346145, 10679838, 11013526, 11347209, 11680887, 12014558, 12348225, 12681885, 13015539, 13349187, 13682829, 14016464, 14350092, 14683714, 15017328, 15350936, 15684536, 16018129, 16351714, 16685291, 17018860, 17352422, 17685974, 18019518, 18353054, 18686582, 19020100, 19353610, 19687110, 20020600, 20354080, 20687552, 21021014, 21354466, 21687906, 22021338, 22354758, 22688168, 23021568, 23354956, 23688332, 24021698, 24355052, 24688396, 25021726, 25355046, 25688352, 26021648, 26354930, 26688200, 27021456, 27354702, 27687932, 28021150, 28354356, 28687548, 29020724, 29353888, 29687038, 30020174, 30353296, 30686404, 31019496, 31352574, 31685636, 32018684, 32351718, 32684734, 33017736, 33350722, 33683692, 34016648, 34349584, 34682508, 35015412, 35348300, 35681172, 36014028, 36346868, 36679688, 37012492, 37345276, 37678044, 38010792, 38343524, 38676240, 39008936, 39341612, 39674272, 40006912, 40339532, 40672132, 41004716, 41337276, 41669820, 42002344, 42334848, 42667332, 42999796, 43332236, 43664660, 43997060, 44329444, 44661800, 44994140, 45326456, 45658752, 45991028, 46323280, 46655512, 46987720, 47319908, 47652072, 47984212, 48316332, 48648428, 48980500, 49312548, 49644576, 49976580, 50308556, 50640512, 50972444, 51304352, 51636236, 51968096, 52299928, 52631740, 52963524, 53295284, 53627020, 53958728, 54290412, 54622068, 54953704, 55285308, 55616888, 55948444, 56279972, 56611472, 56942948, 57274396, 57605816, 57937212, 58268576, 58599916, 58931228, 59262512, 59593768, 59924992, 60256192, 60587364, 60918508, 61249620, 61580704, 61911760, 62242788, 62573788, 62904756, 63235692, 63566604, 63897480, 64228332, 64559148, 64889940, 65220696, 65551424, 65882120, 66212788, 66543420, 66874024, 67204600, 67535136, 67865648, 68196120, 68526568, 68856984, 69187360, 69517712, 69848024, 70178304, 70508560, 70838776, 71168960, 71499112, 71829224, 72159312, 72489360, 72819376, 73149360, 73479304, 73809216, 74139096, 74468936, 74798744, 75128520, 75458264, 75787968, 76117632, 76447264, 76776864, 77106424, 77435952, 77765440, 78094888, 78424304, 78753688, 79083032, 79412336, 79741608, 80070840, 80400032, 80729192, 81058312, 81387392, 81716432, 82045440, 82374408, 82703336, 83032224, 83361080, 83689896, 84018664, 84347400, 84676096, 85004760, 85333376, 85661952, 85990488, 86318984, 86647448, 86975864, 87304240, 87632576, 87960872, 88289128, 88617344, 88945520, 89273648, 89601736, 89929792, 90257792, 90585760, 90913688, 91241568, 91569408, 91897200, 92224960, 92552672, 92880336, 93207968, 93535552, 93863088, 94190584, 94518040, 94845448, 95172816, 95500136, 95827416, 96154648, 96481832, 96808976, 97136080, 97463136, 97790144, 98117112, 98444032, 98770904, 99097736, 99424520, 99751256, 100077944, 100404592, 100731192, 101057744, 101384248, 101710712, 102037128, 102363488, 102689808, 103016080, 103342312, 103668488, 103994616, 104320696, 104646736, 104972720, 105298656, 105624552, 105950392, 106276184, 106601928, 106927624, 107253272, 107578872, 107904416, 108229920, 108555368, 108880768, 109206120, 109531416, 109856664, 110181872, 110507016, 110832120, 111157168, 111482168, 111807112, 112132008, 112456856, 112781648, 113106392, 113431080, 113755720, 114080312, 114404848, 114729328, 115053760, 115378136, 115702464, 116026744, 116350960, 116675128, 116999248, 117323312, 117647320, 117971272, 118295176, 118619024, 118942816, 119266560, 119590248, 119913880, 120237456, 120560984, 120884456, 121207864, 121531224, 121854528, 122177784, 122500976, 122824112, 123147200, 123470224, 123793200, 124116120, 124438976, 124761784, 125084528, 125407224, 125729856, 126052432, 126374960, 126697424, 127019832, 127342184, 127664472, 127986712, 128308888, 128631008, 128953072, 129275080, 129597024, 129918912, 130240744, 130562520, 130884232, 131205888, 131527480, 131849016, 132170496, 132491912, 132813272, 133134576, 133455816, 133776992, 134098120, 134419184, 134740176, 135061120, 135382000, 135702816, 136023584, 136344272, 136664912, 136985488, 137306016, 137626464, 137946864, 138267184, 138587456, 138907664, 139227808, 139547904, 139867920, 140187888, 140507776, 140827616, 141147392, 141467104, 141786752, 142106336, 142425856, 142745312, 143064720, 143384048, 143703312, 144022512, 144341664, 144660736, 144979744, 145298704, 145617584, 145936400, 146255168, 146573856, 146892480, 147211040, 147529536, 147847968, 148166336, 148484640, 148802880, 149121056, 149439152, 149757200, 150075168, 150393072, 150710912, 151028688, 151346400, 151664048, 151981616, 152299136, 152616576, 152933952, 153251264, 153568496, 153885680, 154202784, 154519824, 154836784, 155153696, 155470528, 155787296, 156104000, 156420624, 156737200, 157053696, 157370112, 157686480, 158002768, 158318976, 158635136, 158951216, 159267232, 159583168, 159899040, 160214848, 160530592, 160846256, 161161840, 161477376, 161792832, 162108208, 162423520, 162738768, 163053952, 163369040, 163684080, 163999040, 164313936, 164628752, 164943504, 165258176, 165572784, 165887312, 166201776, 166516160, 166830480, 167144736, 167458912, 167773008, 168087040, 168400992, 168714880, 169028688, 169342432, 169656096, 169969696, 170283216, 170596672, 170910032, 171223344, 171536576, 171849728, 172162800, 172475808, 172788736, 173101600, 173414384, 173727104, 174039728, 174352288, 174664784, 174977200, 175289536, 175601792, 175913984, 176226096, 176538144, 176850096, 177161984, 177473792, 177785536, 178097200, 178408784, 178720288, 179031728, 179343088, 179654368, 179965568, 180276704, 180587744, 180898720, 181209616, 181520448, 181831184, 182141856, 182452448, 182762960, 183073408, 183383760, 183694048, 184004240, 184314368, 184624416, 184934400, 185244288, 185554096, 185863840, 186173504, 186483072, 186792576, 187102000, 187411344, 187720608, 188029808, 188338912, 188647936, 188956896, 189265760, 189574560, 189883264, 190191904, 190500448, 190808928, 191117312, 191425632, 191733872, 192042016, 192350096, 192658096, 192966000, 193273840, 193581584, 193889264, 194196848, 194504352, 194811792, 195119136, 195426400, 195733584, 196040688, 196347712, 196654656, 196961520, 197268304, 197574992, 197881616, 198188144, 198494592, 198800960, 199107248, 199413456, 199719584, 200025616, 200331584, 200637456, 200943248, 201248960, 201554576, 201860128, 202165584, 202470960, 202776256, 203081456, 203386592, 203691632, 203996592, 204301472, 204606256, 204910976, 205215600, 205520144, 205824592, 206128960, 206433248, 206737456, 207041584, 207345616, 207649568, 207953424, 208257216, 208560912, 208864512, 209168048, 209471488, 209774832, 210078112, 210381296, 210684384, 210987408, 211290336, 211593184, 211895936, 212198608, 212501184, 212803680, 213106096, 213408432, 213710672, 214012816, 214314880, 214616864, 214918768, 215220576, 215522288, 215823920, 216125472, 216426928, 216728304, 217029584, 217330784, 217631904, 217932928, 218233856, 218534704, 218835472, 219136144, 219436720, 219737216, 220037632, 220337952, 220638192, 220938336, 221238384, 221538352, 221838240, 222138032, 222437728, 222737344, 223036880, 223336304, 223635664, 223934912, 224234096, 224533168, 224832160, 225131072, 225429872, 225728608, 226027232, 226325776, 226624240, 226922608, 227220880, 227519056, 227817152, 228115168, 228413088, 228710912, 229008640, 229306288, 229603840, 229901312, 230198688, 230495968, 230793152, 231090256, 231387280, 231684192, 231981024, 232277760, 232574416, 232870960, 233167440, 233463808, 233760096, 234056288, 234352384, 234648384, 234944304, 235240128, 235535872, 235831504, 236127056, 236422512, 236717888, 237013152, 237308336, 237603424, 237898416, 238193328, 238488144, 238782864, 239077488, 239372016, 239666464, 239960816, 240255072, 240549232, 240843312, 241137280, 241431168, 241724960, 242018656, 242312256, 242605776, 242899200, 243192512, 243485744, 243778896, 244071936, 244364880, 244657744, 244950496, 245243168, 245535744, 245828224, 246120608, 246412912, 246705104, 246997216, 247289216, 247581136, 247872960, 248164688, 248456320, 248747856, 249039296, 249330640, 249621904, 249913056, 250204128, 250495088, 250785968, 251076736, 251367424, 251658016, 251948512, 252238912, 252529200, 252819408, 253109520, 253399536, 253689456, 253979280, 254269008, 254558640, 254848176, 255137632, 255426976, 255716224, 256005376, 256294432, 256583392, 256872256, 257161024, 257449696, 257738272, 258026752, 258315136, 258603424, 258891600, 259179696, 259467696, 259755600, 260043392, 260331104, 260618704, 260906224, 261193632, 261480960, 261768176, 262055296, 262342320, 262629248, 262916080, 263202816, 263489456, 263776000, 264062432, 264348784, 264635024, 264921168, 265207216, 265493168, 265779024, 266064784, 266350448, 266636000, 266921472, 267206832, 267492096, 267777264, 268062336, 268347312, 268632192, 268916960, 269201632, 269486208, 269770688, 270055072, 270339360, 270623552, 270907616, 271191616, 271475488, 271759296, 272042976, 272326560, 272610048, 272893440, 273176736, 273459936, 273743040, 274026048, 274308928, 274591744, 274874432, 275157024, 275439520, 275721920, 276004224, 276286432, 276568512, 276850528, 277132416, 277414240, 277695936, 277977536, 278259040, 278540448, 278821728, 279102944, 279384032, 279665056, 279945952, 280226752, 280507456, 280788064, 281068544, 281348960, 281629248, 281909472, 282189568, 282469568, 282749440, 283029248, 283308960, 283588544, 283868032, 284147424, 284426720, 284705920, 284985024, 285264000, 285542912, 285821696, 286100384, 286378976, 286657440, 286935840, 287214112, 287492320, 287770400, 288048384, 288326240, 288604032, 288881696, 289159264, 289436768, 289714112, 289991392, 290268576, 290545632, 290822592, 291099456, 291376224, 291652896, 291929440, 292205888, 292482272, 292758528, 293034656, 293310720, 293586656, 293862496, 294138240, 294413888, 294689440, 294964864, 295240192, 295515424, 295790560, 296065600, 296340512, 296615360, 296890080, 297164704, 297439200, 297713632, 297987936, 298262144, 298536256, 298810240, 299084160, 299357952, 299631648, 299905248, 300178720, 300452128, 300725408, 300998592, 301271680, 301544640, 301817536, 302090304, 302362976, 302635520, 302908000, 303180352, 303452608, 303724768, 303996800, 304268768, 304540608, 304812320, 305083968, 305355520, 305626944, 305898272, 306169472, 306440608, 306711616, 306982528, 307253344, 307524064, 307794656, 308065152, 308335552, 308605856, 308876032, 309146112, 309416096, 309685984, 309955744, 310225408, 310494976, 310764448, 311033824, 311303072, 311572224, 311841280, 312110208, 312379040, 312647776, 312916416, 313184960, 313453376, 313721696, 313989920, 314258016, 314526016, 314793920, 315061728, 315329408, 315597024, 315864512, 316131872, 316399168, 316666336, 316933408, 317200384, 317467232, 317733984, 318000640, 318267200, 318533632, 318799968, 319066208, 319332352, 319598368, 319864288, 320130112, 320395808, 320661408, 320926912, 321192320, 321457632, 321722816, 321987904, 322252864, 322517760, 322782528, 323047200, 323311744, 323576192, 323840544, 324104800, 324368928, 324632992, 324896928, 325160736, 325424448, 325688096, 325951584, 326215008, 326478304, 326741504, 327004608, 327267584, 327530464, 327793248, 328055904, 328318496, 328580960, 328843296, 329105568, 329367712, 329629760, 329891680, 330153536, 330415264, 330676864, 330938400, 331199808, 331461120, 331722304, 331983392, 332244384, 332505280, 332766048, 333026752, 333287296, 333547776, 333808128, 334068384, 334328544, 334588576, 334848512, 335108352, 335368064, 335627712, 335887200, 336146624, 336405920, 336665120, 336924224, 337183200, 337442112, 337700864, 337959552, 338218112, 338476576, 338734944, 338993184, 339251328, 339509376, 339767296, 340025120, 340282848, 340540480, 340797984, 341055392, 341312704, 341569888, 341826976, 342083968, 342340832, 342597600, 342854272, 343110848, 343367296, 343623648, 343879904, 344136032, 344392064, 344648000, 344903808, 345159520, 345415136, 345670656, 345926048, 346181344, 346436512, 346691616, 346946592, 347201440, 347456224, 347710880, 347965440, 348219872, 348474208, 348728448, 348982592, 349236608, 349490528, 349744320, 349998048, 350251648, 350505152, 350758528, 351011808, 351264992, 351518048, 351771040, 352023872, 352276640, 352529280, 352781824, 353034272, 353286592, 353538816, 353790944, 354042944, 354294880, 354546656, 354798368, 355049952, 355301440, 355552800, 355804096, 356055264, 356306304, 356557280, 356808128, 357058848, 357309504, 357560032, 357810464, 358060768, 358311008, 358561088, 358811104, 359060992, 359310784, 359560480, 359810048, 360059520, 360308896, 360558144, 360807296, 361056352, 361305312, 361554144, 361802880, 362051488, 362300032, 362548448, 362796736, 363044960, 363293056, 363541024, 363788928, 364036704, 364284384, 364531936, 364779392, 365026752, 365274016, 365521152, 365768192, 366015136, 366261952, 366508672, 366755296, 367001792, 367248192, 367494496, 367740704, 367986784, 368232768, 368478656, 368724416, 368970080, 369215648, 369461088, 369706432, 369951680, 370196800, 370441824, 370686752, 370931584, 371176288, 371420896, 371665408, 371909792, 372154080, 372398272, 372642336, 372886304, 373130176, 373373952, 373617600, 373861152, 374104608, 374347936, 374591168, 374834304, 375077312, 375320224, 375563040, 375805760, 376048352, 376290848, 376533248, 376775520, 377017696, 377259776, 377501728, 377743584, 377985344, 378227008, 378468544, 378709984, 378951328, 379192544, 379433664, 379674688, 379915584, 380156416, 380397088, 380637696, 380878176, 381118560, 381358848, 381599040, 381839104, 382079072, 382318912, 382558656, 382798304, 383037856, 383277280, 383516640, 383755840, 383994976, 384233984, 384472896, 384711712, 384950400, 385188992, 385427488, 385665888, 385904160, 386142336, 386380384, 386618368, 386856224, 387093984, 387331616, 387569152, 387806592, 388043936, 388281152, 388518272, 388755296, 388992224, 389229024, 389465728, 389702336, 389938816, 390175200, 390411488, 390647680, 390883744, 391119712, 391355584, 391591328, 391826976, 392062528, 392297984, 392533312, 392768544, 393003680, 393238720, 393473632, 393708448, 393943168, 394177760, 394412256, 394646656, 394880960, 395115136, 395349216, 395583200, 395817088, 396050848, 396284512, 396518080, 396751520, 396984864, 397218112, 397451264, 397684288, 397917248, 398150080, 398382784, 398615424, 398847936, 399080320, 399312640, 399544832, 399776928, 400008928, 400240832, 400472608, 400704288, 400935872, 401167328, 401398720, 401629984, 401861120, 402092192, 402323136, 402553984, 402784736, 403015360, 403245888, 403476320, 403706656, 403936896, 404167008, 404397024, 404626944, 404856736, 405086432, 405316032, 405545536, 405774912, 406004224, 406233408, 406462464, 406691456, 406920320, 407149088, 407377760, 407606336, 407834784, 408063136, 408291392, 408519520, 408747584, 408975520, 409203360, 409431072, 409658720, 409886240, 410113664, 410340992, 410568192, 410795296, 411022304, 411249216, 411476032, 411702720, 411929312, 412155808, 412382176, 412608480, 412834656, 413060736, 413286720, 413512576, 413738336, 413964000, 414189568, 414415040, 414640384, 414865632, 415090784, 415315840, 415540800, 415765632, 415990368, 416215008, 416439552, 416663968, 416888288, 417112512, 417336640, 417560672, 417784576, 418008384, 418232096, 418455712, 418679200, 418902624, 419125920, 419349120, 419572192, 419795200, 420018080, 420240864, 420463552, 420686144, 420908608, 421130976, 421353280, 421575424, 421797504, 422019488, 422241344, 422463104, 422684768, 422906336, 423127776, 423349120, 423570400, 423791520, 424012576, 424233536, 424454368, 424675104, 424895744, 425116288, 425336736, 425557056, 425777280, 425997408, 426217440, 426437376, 426657184, 426876928, 427096544, 427316064, 427535488, 427754784, 427974016, 428193120, 428412128, 428631040, 428849856, 429068544, 429287168, 429505664, 429724064, 429942368, 430160576, 430378656, 430596672, 430814560, 431032352, 431250048, 431467616, 431685120, 431902496, 432119808, 432336992, 432554080, 432771040, 432987936, 433204736, 433421408, 433637984, 433854464, 434070848, 434287104, 434503296, 434719360, 434935360, 435151232, 435367008, 435582656, 435798240, 436013696, 436229088, 436444352, 436659520, 436874592, 437089568, 437304416, 437519200, 437733856, 437948416, 438162880, 438377248, 438591520, 438805696, 439019744, 439233728, 439447584, 439661344, 439875008, 440088576, 440302048, 440515392, 440728672, 440941824, 441154880, 441367872, 441580736, 441793472, 442006144, 442218720, 442431168, 442643552, 442855808, 443067968, 443280032, 443492000, 443703872, 443915648, 444127296, 444338880, 444550336, 444761696, 444972992, 445184160, 445395232, 445606176, 445817056, 446027840, 446238496, 446449088, 446659552, 446869920, 447080192, 447290400, 447500448, 447710432, 447920320, 448130112, 448339776, 448549376, 448758848, 448968224, 449177536, 449386720, 449595808, 449804800, 450013664, 450222464, 450431168, 450639776, 450848256, 451056640, 451264960, 451473152, 451681248, 451889248, 452097152, 452304960, 452512672, 452720288, 452927808, 453135232, 453342528, 453549760, 453756864, 453963904, 454170816, 454377632, 454584384, 454791008, 454997536, 455203968, 455410304, 455616544, 455822688, 456028704, 456234656, 456440512, 456646240, 456851904, 457057472, 457262912, 457468256, 457673536, 457878688, 458083744, 458288736, 458493600, 458698368, 458903040, 459107616, 459312096, 459516480, 459720768, 459924960, 460129056, 460333056, 460536960, 460740736, 460944448, 461148064, 461351584, 461554976, 461758304, 461961536, 462164640, 462367680, 462570592, 462773440, 462976160, 463178816, 463381344, 463583776, 463786144, 463988384, 464190560, 464392608, 464594560, 464796448, 464998208, 465199872, 465401472, 465602944, 465804320, 466005600, 466206816, 466407904, 466608896, 466809824, 467010624, 467211328, 467411936, 467612480, 467812896, 468013216, 468213440, 468413600, 468613632, 468813568, 469013440, 469213184, 469412832, 469612416, 469811872, 470011232, 470210528, 470409696, 470608800, 470807776, 471006688, 471205472, 471404192, 471602784, 471801312, 471999712, 472198048, 472396288, 472594400, 472792448, 472990400, 473188256, 473385984, 473583648, 473781216, 473978688, 474176064, 474373344, 474570528, 474767616, 474964608, 475161504, 475358336, 475555040, 475751648, 475948192, 476144608, 476340928, 476537184, 476733312, 476929376, 477125344, 477321184, 477516960, 477712640, 477908224, 478103712, 478299104, 478494400, 478689600, 478884704, 479079744, 479274656, 479469504, 479664224, 479858880, 480053408, 480247872, 480442240, 480636512, 480830656, 481024736, 481218752, 481412640, 481606432, 481800128, 481993760, 482187264, 482380704, 482574016, 482767264, 482960416, 483153472, 483346432, 483539296, 483732064, 483924768, 484117344, 484309856, 484502240, 484694560, 484886784, 485078912, 485270944, 485462880, 485654720, 485846464, 486038144, 486229696, 486421184, 486612576, 486803840, 486995040, 487186176, 487377184, 487568096, 487758912, 487949664, 488140320, 488330880, 488521312, 488711712, 488901984, 489092160, 489282240, 489472256, 489662176, 489851968, 490041696, 490231328, 490420896, 490610336, 490799712, 490988960, 491178144, 491367232, 491556224, 491745120, 491933920, 492122656, 492311264, 492499808, 492688256, 492876608, 493064864, 493253056, 493441120, 493629120, 493817024, 494004832, 494192544, 494380160, 494567712, 494755136, 494942496, 495129760, 495316928, 495504000, 495691008, 495877888, 496064704, 496251424, 496438048, 496624608, 496811040, 496997408, 497183680, 497369856, 497555936, 497741920, 497927840, 498113632, 498299360, 498484992, 498670560, 498856000, 499041376, 499226656, 499411840, 499596928, 499781920, 499966848, 500151680, 500336416, 500521056, 500705600, 500890080, 501074464, 501258752, 501442944, 501627040, 501811072, 501995008, 502178848, 502362592, 502546240, 502729824, 502913312, 503096704, 503280000, 503463232, 503646368, 503829408, 504012352, 504195200, 504377984, 504560672, 504743264, 504925760, 505108192, 505290496, 505472736, 505654912, 505836960, 506018944, 506200832, 506382624, 506564320, 506745952, 506927488, 507108928, 507290272, 507471552, 507652736, 507833824, 508014816, 508195744, 508376576, 508557312, 508737952, 508918528, 509099008, 509279392, 509459680, 509639904, 509820032, 510000064, 510180000, 510359872, 510539648, 510719328, 510898944, 511078432, 511257856, 511437216, 511616448, 511795616, 511974688, 512153664, 512332576, 512511392, 512690112, 512868768, 513047296, 513225792, 513404160, 513582432, 513760640, 513938784, 514116800, 514294752, 514472608, 514650368, 514828064, 515005664, 515183168, 515360608, 515537952, 515715200, 515892352, 516069440, 516246432, 516423328, 516600160, 516776896, 516953536, 517130112, 517306592, 517482976, 517659264, 517835488, 518011616, 518187680, 518363648, 518539520, 518715296, 518891008, 519066624, 519242144, 519417600, 519592960, 519768256, 519943424, 520118528, 520293568, 520468480, 520643328, 520818112, 520992800, 521167392, 521341888, 521516320, 521690656, 521864896, 522039072, 522213152, 522387168, 522561056, 522734912, 522908640, 523082304, 523255872, 523429376, 523602784, 523776096, 523949312, 524122464, 524295552, 524468512, 524641440, 524814240, 524986976, 525159616, 525332192, 525504640, 525677056, 525849344, 526021568, 526193728, 526365792, 526537760, 526709632, 526881440, 527053152, 527224800, 527396352, 527567840, 527739200, 527910528, 528081728, 528252864, 528423936, 528594880, 528765760, 528936576, 529107296, 529277920, 529448480, 529618944, 529789344, 529959648, 530129856, 530300000, 530470048, 530640000, 530809888, 530979712, 531149440, 531319072, 531488608, 531658080, 531827488, 531996800, 532166016, 532335168, 532504224, 532673184, 532842080, 533010912, 533179616, 533348288, 533516832, 533685312, 533853728, 534022048, 534190272, 534358432, 534526496, 534694496, 534862400, 535030240, 535197984, 535365632, 535533216, 535700704, 535868128, 536035456, 536202720, 536369888, 536536992, 536704000, 536870912 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- int SlopeDiv(unsigned num, unsigned den) { unsigned ans; if(den < 512) return SLOPERANGE; ans = (num << 3) / (den >> 8); return ans <= SLOPERANGE ? ans : SLOPERANGE; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/h_refresh.c0000644000175000017500000003260611357170242023252 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_refresh.c: - jHeretic specific. */ // HEADER FILES ------------------------------------------------------------ #include #include "jheretic.h" #include "hu_stuff.h" #include "hu_menu.h" #include "hu_msg.h" #include "hu_pspr.h" #include "am_map.h" #include "g_common.h" #include "r_common.h" #include "d_net.h" #include "f_infine.h" #include "x_hair.h" #include "g_controls.h" #include "p_mapsetup.h" #include "p_tick.h" #include "rend_automap.h" // MACROS ------------------------------------------------------------------ #define WINDOWHEIGHT Get(DD_VIEWWINDOW_HEIGHT) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void R_SetAllDoomsdayFlags(void); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern const float defFontRGB[]; extern const float defFontRGB2[]; // PUBLIC DATA DEFINITIONS ------------------------------------------------- float quitDarkenOpacity = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Draws a special filter over the screen. */ void R_DrawSpecialFilter(int pnum) { float x, y, w, h; player_t* player = &players[pnum]; if(player->powers[PT_INVULNERABILITY] <= BLINKTHRESHOLD && !(player->powers[PT_INVULNERABILITY] & 8)) return; R_GetViewWindow(&x, &y, &w, &h); DGL_Disable(DGL_TEXTURING); if(cfg.ringFilter == 1) { DGL_BlendFunc(DGL_SRC_COLOR, DGL_SRC_COLOR); DGL_DrawRect(x, y, w, h, .5f, .35f, .1f, cfg.filterStrength); } else { DGL_BlendFunc(DGL_DST_COLOR, DGL_SRC_COLOR); DGL_DrawRect(x, y, w, h, 0, 0, .6f, cfg.filterStrength); } // Restore the normal rendering state. DGL_BlendMode(BM_NORMAL); DGL_Enable(DGL_TEXTURING); } boolean R_GetFilterColor(float rgba[4], int filter) { if(!rgba) return false; // We have to choose the right color and alpha. if(filter >= STARTREDPALS && filter < STARTREDPALS + NUMREDPALS) { // Red. rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; rgba[CA] = (deathmatch? 1.0f : cfg.filterStrength) * filter / 8.f; // Full red with filter 8. return true; } else if(filter >= STARTBONUSPALS && filter < STARTBONUSPALS + NUMBONUSPALS) { // Light Yellow. rgba[CR] = 1; rgba[CG] = 1; rgba[CB] = .5f; rgba[CA] = cfg.filterStrength * (filter - STARTBONUSPALS + 1) / 16.f; return true; } if(filter) Con_Message("R_GetFilterColor: Real strange filter number: %d.\n", filter); return false; } void R_DrawMapTitle(int x, int y, float alpha, gamefontid_t font, boolean center) { const char* lname, *lauthor; lname = P_GetMapNiceName(); if(lname) { M_WriteText3(x - M_StringWidth(lname, font) / 2, y, lname, font, defFontRGB[0], defFontRGB[1], defFontRGB[2], alpha, false, true, 0); y += 20; } lauthor = P_GetMapAuthor(cfg.hideIWADAuthor); if(lauthor) { M_WriteText3(x - M_StringWidth(lauthor, GF_FONTA) / 2, y, lauthor, GF_FONTA, .5f, .5f, .5f, alpha, false, true, 0); } } /** * Do not really change anything here, because Doomsday might be in the * middle of a refresh. The change will take effect next refresh. */ void R_SetViewSize(int blocks) { cfg.setSizeNeeded = true; if(cfg.setBlocks != blocks && blocks > 10 && blocks < 13) { // Going to/from fullscreen. int i; // Force a hud show event (to reset the timer). for(i = 0; i < MAXPLAYERS; ++i) ST_HUDUnHide(i, HUE_FORCE); } cfg.setBlocks = blocks; } static void rendPlayerView(int player) { player_t* plr = &players[player]; float viewPos[3], viewPitch, pspriteOffsetY; angle_t viewAngle; boolean isFullBright = (plr->powers[PT_INVULNERABILITY] > BLINKTHRESHOLD) || (plr->powers[PT_INVULNERABILITY] & 8); if(IS_CLIENT) { // Server updates mobj flags in NetSv_Ticker. R_SetAllDoomsdayFlags(); } viewPos[VX] = plr->plr->mo->pos[VX] + plr->viewOffset[VX]; viewPos[VY] = plr->plr->mo->pos[VY] + plr->viewOffset[VY]; viewPos[VZ] = plr->viewZ + plr->viewOffset[VZ]; viewAngle = plr->plr->mo->angle + (int) (ANGLE_MAX * -G_GetLookOffset(player)); viewPitch = plr->plr->lookDir; DD_SetVariable(DD_VIEW_X, &viewPos[VX]); DD_SetVariable(DD_VIEW_Y, &viewPos[VY]); DD_SetVariable(DD_VIEW_Z, &viewPos[VZ]); DD_SetVariable(DD_VIEW_ANGLE, &viewAngle); DD_SetVariable(DD_VIEW_PITCH, &viewPitch); pspriteOffsetY = HU_PSpriteYOffset(plr); DD_SetVariable(DD_PSPRITE_OFFSET_Y, &pspriteOffsetY); // $democam GL_SetFilter((plr->plr->flags & DDPF_VIEW_FILTER)? true : false); if(plr->plr->flags & DDPF_VIEW_FILTER) { const float* color = plr->plr->filterColor; GL_SetFilterColor(color[CR], color[CG], color[CB], color[CA]); } // How about fullbright? DD_SetInteger(DD_FULLBRIGHT, isFullBright); // Render the view with possible custom filters. R_RenderPlayerView(player); } static void rendHUD(int player) { player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; if(G_GetGameState() != GS_MAP) return; if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; plr = &players[player]; // These various HUD's will be drawn unless Doomsday advises not to if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { automapid_t map = AM_MapForPlayer(player); boolean redrawsbar = false; if((WINDOWHEIGHT != 200)) redrawsbar = true; // Draw HUD displays only visible when the automap is open. if(AM_IsActive(map)) HU_DrawMapCounters(); // Do we need to render a full status bar at this point? if(!(AM_IsActive(map) && cfg.automapHudDisplay == 0) && !(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { int viewmode = ((WINDOWHEIGHT == 200)? (cfg.setBlocks - 10) : 0); ST_Drawer(player, viewmode, redrawsbar); // $democam } HU_Drawer(player); } } /** * Draws the in-viewport display. * * @param layer @c 0 = bottom layer (before the viewport border). * @c 1 = top layer (after the viewport border). */ void H_Display(int layer) { int player = DISPLAYPLAYER; player_t* plr = &players[player]; float x, y, w, h; if(layer != 0) { rendHUD(player); return; } if(G_GetGameState() == GS_MAP) { // $democam: can be set on every frame. if(cfg.setBlocks > 10 || (P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { // Full screen. R_SetViewWindowTarget(0, 0, SCREENWIDTH, SCREENHEIGHT); } else { int w = cfg.setBlocks * 32; int h = cfg.setBlocks * (SCREENHEIGHT - SBARHEIGHT * cfg.statusbarScale / 20) / 10; R_SetViewWindowTarget(SCREENWIDTH/2 - w/2, (SCREENHEIGHT - SBARHEIGHT * cfg.statusbarScale / 20 - h) / 2, w, h); } R_GetViewWindow(&x, &y, &w, &h); } else { x = 0; y = 0; w = SCREENWIDTH; h = SCREENHEIGHT; } R_SetViewWindow((int) x, (int) y, (int) w, (int) h); switch(G_GetGameState()) { case GS_MAP: if(!(MN_CurrentMenuHasBackground() && Hu_MenuAlpha() >= 1) && !R_MapObscures(player, (int) x, (int) y, (int) w, (int) h)) { if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; rendPlayerView(player); R_DrawSpecialFilter(player); // Crosshair. if(!(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) // $democam X_Drawer(player); } // Draw the automap? AM_Drawer(player); break; case GS_STARTUP: DGL_Disable(DGL_TEXTURING); DGL_DrawRect(x, y, w, h, 0, 0, 0, 1); DGL_Enable(DGL_TEXTURING); break; default: break; } } void H_Display2(void) { switch(G_GetGameState()) { case GS_MAP: if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) break; if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { // Level information is shown for a few seconds in the // beginning of a level. if(cfg.mapTitle || actualMapTime <= 6 * TICSPERSEC) { int x, y; float alpha = 1; if(actualMapTime < 35) alpha = actualMapTime / 35.0f; if(actualMapTime > 5 * 35) alpha = 1 - (actualMapTime - 5 * 35) / 35.0f; x = SCREENWIDTH / 2; y = 13; Draw_BeginZoom((1 + cfg.hudScale)/2, x, y); R_DrawMapTitle(x, y, alpha, GF_FONTB, true); Draw_EndZoom(); } } break; case GS_INTERMISSION: IN_Drawer(); break; case GS_WAITING: // Clear the screen while waiting, doesn't mess up the menu. //gl.Clear(DGL_COLOR_BUFFER_BIT); break; default: break; } // Draw pause pic (but not if InFine active). if(paused && !fiActive) { GL_DrawPatch(SCREENWIDTH/2, 4, W_GetNumForName("PAUSED")); } // InFine is drawn whenever active. FI_Drawer(); // Draw HUD displays; menu, messages. Hu_Drawer(); if(G_GetGameAction() == GA_QUIT) { DGL_Disable(DGL_TEXTURING); DGL_DrawRect(0, 0, 320, 200, 0, 0, 0, quitDarkenOpacity); DGL_Enable(DGL_TEXTURING); } } /** * Updates the mobj flags used by Doomsday with the state of our local flags * for the given mobj. */ void R_SetDoomsdayFlags(mobj_t* mo) { // Client mobjs can't be set here. if(IS_CLIENT && mo->ddFlags & DDMF_REMOTE) return; // Reset the flags for a new frame. mo->ddFlags &= DDMF_CLEAR_MASK; // Local objects aren't sent to clients. if(mo->flags & MF_LOCAL) mo->ddFlags |= DDMF_LOCAL; if(mo->flags & MF_SOLID) mo->ddFlags |= DDMF_SOLID; if(mo->flags & MF_NOGRAVITY) mo->ddFlags |= DDMF_NOGRAVITY; if(mo->flags2 & MF2_FLOATBOB) mo->ddFlags |= DDMF_NOGRAVITY | DDMF_BOB; if(mo->flags & MF_MISSILE) { // Mace death balls are controlled by the server. //if(mo->type != MT_MACEFX4) mo->ddFlags |= DDMF_MISSILE; } if(mo->info && (mo->info->flags2 & MF2_ALWAYSLIT)) mo->ddFlags |= DDMF_ALWAYSLIT; if(mo->flags2 & MF2_FLY) mo->ddFlags |= DDMF_FLY | DDMF_NOGRAVITY; // $democam: cameramen are invisible. if(P_MobjIsCamera(mo)) mo->ddFlags |= DDMF_DONTDRAW; if((mo->flags & MF_CORPSE) && cfg.corpseTime && mo->corpseTics == -1) mo->ddFlags |= DDMF_DONTDRAW; // Choose which ddflags to set. if(mo->flags2 & MF2_DONTDRAW) { mo->ddFlags |= DDMF_DONTDRAW; return; // No point in checking the other flags. } if(mo->flags2 & MF2_LOGRAV) mo->ddFlags |= DDMF_LOWGRAVITY; if(mo->flags & MF_BRIGHTSHADOW) mo->ddFlags |= DDMF_BRIGHTSHADOW; else if(mo->flags & MF_SHADOW) mo->ddFlags |= DDMF_ALTSHADOW; if(((mo->flags & MF_VIEWALIGN) && !(mo->flags & MF_MISSILE)) || (mo->flags & MF_FLOAT) || ((mo->flags & MF_MISSILE) && !(mo->flags & MF_VIEWALIGN))) mo->ddFlags |= DDMF_VIEWALIGN; if(mo->flags & MF_TRANSLATION) mo->tmap = (mo->flags & MF_TRANSLATION) >> MF_TRANSSHIFT; } /** * Updates the status flags for all visible things. */ void R_SetAllDoomsdayFlags(void) { uint i; mobj_t* iter; // Only visible things are in the sector thinglists, so this is good. for(i = 0; i < numsectors; ++i) { iter = P_GetPtr(DMU_SECTOR, i, DMT_MOBJS); while(iter) { R_SetDoomsdayFlags(iter); iter = iter->sNext; } } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_enemy.c0000644000175000017500000017025111357170242022740 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.c: Enemy thinking, AI. * * Action Pointer Functions that are associated with states/frames. */ // HEADER FILES ------------------------------------------------------------ #include #ifdef MSVC # pragma optimize("g", off) #endif #include "jheretic.h" #include "dmu_lib.h" #include "p_mapspec.h" #include "p_map.h" #include "p_floor.h" // MACROS ------------------------------------------------------------------ #define MONS_LOOK_RANGE (20*64) #define MONS_LOOK_LIMIT 64 #define MNTR_CHARGE_SPEED (13) #define MAX_GEN_PODS 16 #define BODYQUESIZE 32 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- boolean P_TestMobjLocation(mobj_t *mobj); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern boolean fellDown; //$dropoff_fix: used to flag pushed off ledge extern linedef_t *blockLine; // $unstuck: blocking linedef extern float tmBBox[4]; // for line intersection checks // PUBLIC DATA DEFINITIONS ------------------------------------------------- // Eight directional movement speeds. #define MOVESPEED_DIAGONAL (0.71716309f) static const float dirSpeed[8][2] = { {1, 0}, {MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {0, 1}, {-MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {-1, 0}, {-MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL}, {0, -1}, {MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL} }; #undef MOVESPEED_DIAGONAL mobj_t *bodyque[BODYQUESIZE]; int bodyqueslot; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static float dropoffDelta[2], floorZ; // CODE -------------------------------------------------------------------- /** * If a monster yells at a player, it will alert other monsters to the * player's whereabouts. */ void P_NoiseAlert(mobj_t *target, mobj_t *emitter) { VALIDCOUNT++; P_RecursiveSound(target, P_GetPtrp(emitter->subsector, DMU_SECTOR), 0); } boolean P_CheckMeleeRange(mobj_t *actor) { mobj_t *pl; float dist, range; if(!actor->target) return false; pl = actor->target; dist = P_ApproxDistance(pl->pos[VX] - actor->pos[VX], pl->pos[VY] - actor->pos[VY]); if(!cfg.netNoMaxZMonsterMeleeAttack) { // Account for Z height difference. if(pl->pos[VZ] > actor->pos[VZ] + actor->height || pl->pos[VZ] + pl->height < actor->pos[VZ]) return false; } range = MELEERANGE - 20 + pl->info->radius; if(dist >= range) return false; if(!P_CheckSight(actor, actor->target)) return false; return true; } boolean P_CheckMissileRange(mobj_t *actor) { float dist; if(!P_CheckSight(actor, actor->target)) return false; if(actor->flags & MF_JUSTHIT) { // The target just hit the enemy, so fight back! actor->flags &= ~MF_JUSTHIT; return true; } if(actor->reactionTime) return false; // Don't attack yet dist = (P_ApproxDistance (actor->pos[VX] - actor->target->pos[VX], actor->pos[VY] - actor->target->pos[VY])) - 64; if(P_GetState(actor->type, SN_MELEE) == S_NULL) dist -= 128; // No melee attack, so fire more frequently. // Imp's fly attack from far away if(actor->type == MT_IMP) dist /= 2; if(dist > 200) dist = 200; if(P_Random() < dist) return false; return true; } /** * Move in the current direction. * * @return @c false, if the move is blocked. */ boolean P_Move(mobj_t *actor, boolean dropoff) { float pos[2], step[2]; linedef_t *ld; boolean good; if(actor->moveDir == DI_NODIR) return false; if((unsigned) actor->moveDir >= DI_NODIR) Con_Error("Weird actor->moveDir!"); step[VX] = actor->info->speed * dirSpeed[actor->moveDir][VX]; step[VY] = actor->info->speed * dirSpeed[actor->moveDir][VY]; pos[VX] = actor->pos[VX] + step[VX]; pos[VY] = actor->pos[VY] + step[VY]; // killough $dropoff_fix. if(!P_TryMove(actor, pos[VX], pos[VY], dropoff, false)) { // Open any specials. if((actor->flags & MF_FLOAT) && floatOk) { // Must adjust height. if(actor->pos[VZ] < tmFloorZ) actor->pos[VZ] += FLOATSPEED; else actor->pos[VZ] -= FLOATSPEED; actor->flags |= MF_INFLOAT; return true; } if(!P_IterListSize(spechit)) return false; actor->moveDir = DI_NODIR; good = false; while((ld = P_PopIterList(spechit)) != NULL) { /** * If the special is not a door that can be opened, return false. * * $unstuck: This is what caused monsters to get stuck in * doortracks, because it thought that the monster freed itself * by opening a door, even if it was moving towards the * doortrack, and not the door itself. * * If a line blocking the monster is activated, return true 90% * of the time. If a line blocking the monster is not activated, * but some other line is, return false 90% of the time. * A bit of randomness is needed to ensure it's free from * lockups, but for most cases, it returns the correct result. * * Do NOT simply return false 1/4th of the time (causes monsters * to back out when they shouldn't, and creates secondary * stickiness). */ if(P_ActivateLine(ld, actor, 0, SPAC_USE)) good |= ld == blockLine ? 1 : 2; } if(!good || cfg.monstersStuckInDoors) return good; else return (P_Random() >= 230) || (good & 1); } else { // "servo": movement smoothing P_MobjSetSRVO(actor, step[VX], step[VY]); actor->flags &= ~MF_INFLOAT; } // $dropoff_fix: fall more slowly, under gravity, if fellDown==true if(!(actor->flags & MF_FLOAT) && !fellDown) { if(actor->pos[VZ] > actor->floorZ) P_HitFloor(actor); actor->pos[VZ] = actor->floorZ; } return true; } /** * Attempts to move actor in its current (ob->moveangle) direction. * If blocked by either a wall or an actor returns FALSE. * If move is either clear of block only by a door, returns TRUE and sets. * If a door is in the way, an OpenDoor call is made to start it opening. */ boolean P_TryWalk(mobj_t *actor) { // $dropoff_fix if(!P_Move(actor, false)) return false; actor->moveCount = P_Random() & 15; return true; } static void newChaseDir(mobj_t *actor, float deltaX, float deltaY) { dirtype_t xdir, ydir, tdir; dirtype_t olddir = actor->moveDir; dirtype_t turnaround = olddir; if(turnaround != DI_NODIR) // find reverse direction turnaround ^= 4; xdir = (deltaX > 10 ? DI_EAST : deltaX < -10 ? DI_WEST : DI_NODIR); ydir = (deltaY < -10 ? DI_SOUTH : deltaY > 10 ? DI_NORTH : DI_NODIR); // Try direct route. if(xdir != DI_NODIR && ydir != DI_NODIR && turnaround != (actor->moveDir = deltaY < 0 ? deltaX > 0 ? DI_SOUTHEAST : DI_SOUTHWEST : deltaX > 0 ? DI_NORTHEAST : DI_NORTHWEST) && P_TryWalk(actor)) return; // Try other directions. if(P_Random() > 200 || fabs(deltaY) > fabs(deltaX)) { dirtype_t temp = xdir; xdir = ydir; ydir = temp; } if((xdir == turnaround ? xdir = DI_NODIR : xdir) != DI_NODIR && (actor->moveDir = xdir, P_TryWalk(actor))) return; // Either moved forward or attacked. if((ydir == turnaround ? ydir = DI_NODIR : ydir) != DI_NODIR && (actor->moveDir = ydir, P_TryWalk(actor))) return; // There is no direct path to the player, so pick another direction. if(olddir != DI_NODIR && (actor->moveDir = olddir, P_TryWalk(actor))) return; // Randomly determine direction of search. if(P_Random() & 1) { for(tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) if(tdir != turnaround && (actor->moveDir = tdir, P_TryWalk(actor))) return; } else { for(tdir = DI_SOUTHEAST; tdir != DI_EAST - 1; tdir--) if(tdir != turnaround && (actor->moveDir = tdir, P_TryWalk(actor))) return; } if((actor->moveDir = turnaround) != DI_NODIR && !P_TryWalk(actor)) actor->moveDir = DI_NODIR; } /** * Monsters try to move away from tall dropoffs. * * In Doom, they were never allowed to hang over dropoffs, and would remain * stuck if involuntarily forced over one. This logic, combined with * p_map.c::P_TryMove(), allows monsters to free themselves without making * them tend to hang over dropoffs. */ static boolean PIT_AvoidDropoff(linedef_t* line, void* data) { sector_t* backsector = P_GetPtrp(line, DMU_BACK_SECTOR); float* bbox = P_GetPtrp(line, DMU_BOUNDING_BOX); if(backsector && tmBBox[BOXRIGHT] > bbox[BOXLEFT] && tmBBox[BOXLEFT] < bbox[BOXRIGHT] && tmBBox[BOXTOP] > bbox[BOXBOTTOM] && // Linedef must be contacted tmBBox[BOXBOTTOM] < bbox[BOXTOP] && P_BoxOnLineSide(tmBBox, line) == -1) { sector_t* frontsector = P_GetPtrp(line, DMU_FRONT_SECTOR); float front = P_GetFloatp(frontsector, DMU_FLOOR_HEIGHT); float back = P_GetFloatp(backsector, DMU_FLOOR_HEIGHT); float d1[2]; angle_t angle; P_GetFloatpv(line, DMU_DXY, d1); // The monster must contact one of the two floors, and the other // must be a tall drop off (more than 24). if(back == floorZ && front < floorZ - 24) { angle = R_PointToAngle2(0, 0, d1[0], d1[1]); // front side drop off } else { if(front == floorZ && back < floorZ - 24) angle = R_PointToAngle2(d1[0], d1[1], 0, 0); // back side drop off else return true; } // Move away from drop off at a standard speed. // Multiple contacted linedefs are cumulative (e.g. hanging over corner) dropoffDelta[VX] -= FIX2FLT(finesine[angle >> ANGLETOFINESHIFT]) * 32; dropoffDelta[VY] += FIX2FLT(finecosine[angle >> ANGLETOFINESHIFT]) * 32; } return true; } /** * Driver for above */ static float P_AvoidDropoff(mobj_t *actor) { floorZ = actor->pos[VZ]; // Remember floor height. dropoffDelta[VX] = dropoffDelta[VY] = 0; VALIDCOUNT++; // Check lines P_MobjLinesIterator(actor, PIT_AvoidDropoff, 0); // Non-zero if movement prescribed. return !(dropoffDelta[VX] == 0 || dropoffDelta[VY] == 0); } void P_NewChaseDir(mobj_t *actor) { float delta[2]; if(!actor->target) Con_Error("P_NewChaseDir: called with no target"); delta[VX] = actor->target->pos[VX] - actor->pos[VX]; delta[VY] = actor->target->pos[VY] - actor->pos[VY]; if(actor->floorZ - actor->dropOffZ > 24 && actor->pos[VZ] <= actor->floorZ && !(actor->flags & (MF_DROPOFF | MF_FLOAT)) && !cfg.avoidDropoffs && P_AvoidDropoff(actor)) { // Move away from dropoff. newChaseDir(actor, dropoffDelta[VX], dropoffDelta[VY]); // $dropoff_fix // If moving away from drop off, set movecount to 1 so that // small steps are taken to get monster away from drop off. actor->moveCount = 1; return; } newChaseDir(actor, delta[VX], delta[VY]); } typedef struct { size_t count; size_t maxTries; mobj_t* notThis; mobj_t* foundMobj; float origin[2]; float maxDistance; int minHealth; int compFlags; boolean checkLOS; byte randomSkip; } findmobjparams_t; static boolean findMobj(thinker_t* th, void* context) { findmobjparams_t* params = (findmobjparams_t*) context; mobj_t* mo = (mobj_t *) th; // Flags requirement? if(params->compFlags > 0 && !(mo->flags & params->compFlags)) return true; // Continue iteration. // Minimum health requirement? if(params->minHealth > 0 && mo->health < params->minHealth) return true; // Continue iteration. // Exclude this mobj? if(params->notThis && mo == params->notThis) return true; // Continue iteration. // Out of range? if(params->maxDistance > 0 && P_ApproxDistance(params->origin[VX] - mo->pos[VX], params->origin[VY] - mo->pos[VY]) > params->maxDistance) return true; // Continue iteration. // Randomly skip this? if(params->randomSkip && P_Random() < params->randomSkip) return true; // Continue iteration. if(params->maxTries > 0 && params->count++ > params->maxTries) return false; // Stop iteration. // Out of sight? if(params->checkLOS && params->notThis && !P_CheckSight(params->notThis, mo)) return true; // Continue iteration. // Found one! params->foundMobj = mo; return false; // Stop iteration. } boolean P_LookForMonsters(mobj_t* mo) { findmobjparams_t params; if(!P_CheckSight(players[0].plr->mo, mo)) return false; // Player can't see the monster. params.count = 0; params.notThis = mo; params.origin[VX] = mo->pos[VX]; params.origin[VY] = mo->pos[VY]; params.foundMobj = NULL; params.maxDistance = MONS_LOOK_RANGE; params.maxTries = MONS_LOOK_LIMIT; params.minHealth = 1; params.compFlags = MF_COUNTKILL; params.checkLOS = true; params.randomSkip = 16; DD_IterateThinkers(P_MobjThinker, findMobj, ¶ms); if(params.foundMobj) { mo->target = params.foundMobj; return true; } return false; } /** * If allaround is false, only look 180 degrees in front * returns true if a player is targeted */ boolean P_LookForPlayers(mobj_t *actor, boolean allaround) { int c, stop; player_t *player; sector_t *sector; angle_t an; float dist; mobj_t *plrmo; int playerCount; // If in single player and player is dead, look for monsters. if(!IS_NETGAME && players[0].health <= 0) return P_LookForMonsters(actor); for(c = playerCount = 0; c < MAXPLAYERS; c++) if(players[c].plr->inGame) playerCount++; // Are there any players? if(!playerCount) return false; sector = P_GetPtrp(actor->subsector, DMU_SECTOR); c = 0; stop = (actor->lastLook - 1) & 3; for(;; actor->lastLook = (actor->lastLook + 1) & 3) { if(!players[actor->lastLook].plr->inGame) continue; if(c++ == 2 || actor->lastLook == stop) return false; // Done looking player = &players[actor->lastLook]; plrmo = player->plr->mo; // Dead? if(player->health <= 0) continue; // Out of sight? if(!P_CheckSight(actor, plrmo)) continue; if(!allaround) { an = R_PointToAngle2(actor->pos[VX], actor->pos[VY], plrmo->pos[VX], plrmo->pos[VY]) - actor->angle; if(an > ANG90 && an < ANG270) { dist = P_ApproxDistance(plrmo->pos[VX] - actor->pos[VX], plrmo->pos[VY] - actor->pos[VY]); // if real close, react anyway if(dist > MELEERANGE) continue; // behind back } } // Is player invisible? if(plrmo->flags & MF_SHADOW) { if((P_ApproxDistance(plrmo->pos[VX] - actor->pos[VX], plrmo->pos[VY] - actor->pos[VY]) > 2 * MELEERANGE) && P_ApproxDistance(plrmo->mom[MX], plrmo->mom[MY]) < 5) { // Player is sneaking - can't detect. return false; } if(P_Random() < 225) { // Player isn't sneaking, but still didn't detect. return false; } } actor->target = plrmo; return true; } } /** * Stay in state until a player is sighted. */ void C_DECL A_Look(mobj_t *actor) { mobj_t *targ; sector_t *sec; // Any shot will wake up actor->threshold = 0; sec = P_GetPtrp(actor->subsector, DMU_SECTOR); targ = P_ToXSector(sec)->soundTarget; if(targ && (targ->flags & MF_SHOOTABLE)) { actor->target = targ; if(actor->flags & MF_AMBUSH) { if(P_CheckSight(actor, actor->target)) goto seeyou; } else goto seeyou; } if(!P_LookForPlayers(actor, false)) return; // go into chase state seeyou: if(actor->info->seeSound) { int sound; sound = actor->info->seeSound; if(actor->flags2 & MF2_BOSS) S_StartSound(sound, NULL); // Full volume else S_StartSound(sound, actor); } P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } /** * Actor has a melee attack, so it tries to close as fast as possible. */ void C_DECL A_Chase(mobj_t* actor) { int delta; statenum_t state; if(actor->reactionTime) actor->reactionTime--; // Modify target threshold. if(actor->threshold) actor->threshold--; if(gameSkill == SM_NIGHTMARE || cfg.fastMonsters) { // Monsters move faster in nightmare mode. actor->tics -= actor->tics / 2; if(actor->tics < 3) actor->tics = 3; } // Turn towards movement direction if not there yet. if(actor->moveDir < DI_NODIR) { actor->angle &= (7 << 29); delta = actor->angle - (actor->moveDir << 29); if(delta > 0) actor->angle -= ANG90 / 2; else if(delta < 0) actor->angle += ANG90 / 2; } if(!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { // Look for a new target. if(P_LookForPlayers(actor, true)) return; // Got a new target. P_MobjChangeState(actor, P_GetState(actor->type, SN_SPAWN)); return; } // Don't attack twice in a row. if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if(gameSkill != SM_NIGHTMARE) P_NewChaseDir(actor); return; } // Check for melee attack. if((state = P_GetState(actor->type, SN_MELEE)) != S_NULL && P_CheckMeleeRange(actor)) { if(actor->info->attackSound) S_StartSound(actor->info->attackSound, actor); P_MobjChangeState(actor, state); return; } // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { if(!(gameSkill < SM_NIGHTMARE && actor->moveCount)) { if(P_CheckMissileRange(actor)) { P_MobjChangeState(actor, state); actor->flags |= MF_JUSTATTACKED; return; } } } // Possibly choose another target. if(IS_NETGAME && !actor->threshold && !P_CheckSight(actor, actor->target)) { if(P_LookForPlayers(actor, true)) return; // Got a new target. } // Chase towards player. if(--actor->moveCount < 0 || !P_Move(actor, false)) { P_NewChaseDir(actor); } // Make active sound. if(actor->info->activeSound && P_Random() < 3) { if(actor->type == MT_WIZARD && P_Random() < 128) { S_StartSound(actor->info->seeSound, actor); } else if(actor->type == MT_SORCERER2) { S_StartSound(actor->info->activeSound, NULL); } else { S_StartSound(actor->info->activeSound, actor); } } } void C_DECL A_FaceTarget(mobj_t *actor) { if(!actor->target) return; actor->turnTime = true; // $visangle-facetarget actor->flags &= ~MF_AMBUSH; actor->angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], actor->target->pos[VX], actor->target->pos[VY]); // Is target a ghost? if(actor->target->flags & MF_SHADOW) { actor->angle += (P_Random() - P_Random()) << 21; } } void C_DECL A_Pain(mobj_t *actor) { if(actor->info->painSound) S_StartSound(actor->info->painSound, actor); } void C_DECL A_DripBlood(mobj_t *actor) { mobj_t* mo; if((mo = P_SpawnMobj3f(MT_BLOOD, actor->pos[VX] + FIX2FLT((P_Random() - P_Random()) << 11), actor->pos[VY] + FIX2FLT((P_Random() - P_Random()) << 11), actor->pos[VZ], P_Random() << 24, 0))) { mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); mo->flags2 |= MF2_LOGRAV; } } void C_DECL A_KnightAttack(mobj_t *actor) { if(!actor->target) return; if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(3), false); S_StartSound(SFX_KGTAT2, actor); return; } // Throw axe. S_StartSound(actor->info->attackSound, actor); if(actor->type == MT_KNIGHTGHOST || P_Random() < 40) { // Red axe. P_SpawnMissile(MT_REDAXE, actor, actor->target, true); return; } // Green axe. P_SpawnMissile(MT_KNIGHTAXE, actor, actor->target, true); } void C_DECL A_ImpExplode(mobj_t* actor) { mobj_t* mo; if((mo = P_SpawnMobj3fv(MT_IMPCHUNK1, actor->pos, P_Random() << 24, 0))) { mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MZ] = 9; } if((mo = P_SpawnMobj3fv(MT_IMPCHUNK2, actor->pos, P_Random() << 24, 0))) { mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MZ] = 9; } if(actor->special1 == 666) P_MobjChangeState(actor, S_IMP_XCRASH1); // Extreme death crash. } void C_DECL A_BeastPuff(mobj_t* actor) { if(P_Random() > 64) { P_SpawnMobj3f(MT_PUFFY, actor->pos[VX] + FIX2FLT((P_Random() - P_Random()) << 10), actor->pos[VY] + FIX2FLT((P_Random() - P_Random()) << 10), actor->pos[VZ] + FIX2FLT((P_Random() - P_Random()) << 10), P_Random() << 24, 0); } } void C_DECL A_ImpMeAttack(mobj_t* actor) { if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, 5 + (P_Random() & 7), false); } } void C_DECL A_ImpMsAttack(mobj_t* actor) { mobj_t* dest; uint an; int dist; if(!actor->target || P_Random() > 64) { P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); return; } dest = actor->target; actor->flags |= MF_SKULLFLY; S_StartSound(actor->info->attackSound, actor); A_FaceTarget(actor); an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = 12 * FIX2FLT(finecosine[an]); actor->mom[MY] = 12 * FIX2FLT(finesine[an]); dist = P_ApproxDistance(dest->pos[VX] - actor->pos[VX], dest->pos[VY] - actor->pos[VY]); dist /= 12; if(dist < 1) dist = 1; actor->mom[MZ] = (dest->pos[VZ] + (dest->height /2) - actor->pos[VZ]) / dist; } /** * Fireball attack of the imp leader. */ void C_DECL A_ImpMsAttack2(mobj_t *actor) { if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, 5 + (P_Random() & 7), false); return; } P_SpawnMissile(MT_IMPBALL, actor, actor->target, true); } void C_DECL A_ImpDeath(mobj_t *actor) { actor->flags &= ~MF_SOLID; actor->flags2 |= MF2_FLOORCLIP; if(actor->pos[VZ] <= actor->floorZ) P_MobjChangeState(actor, S_IMP_CRASH1); } void C_DECL A_ImpXDeath1(mobj_t *actor) { actor->flags &= ~MF_SOLID; actor->flags |= MF_NOGRAVITY; actor->flags2 |= MF2_FLOORCLIP; actor->special1 = 666; // Flag the crash routine. } void C_DECL A_ImpXDeath2(mobj_t *actor) { actor->flags &= ~MF_NOGRAVITY; if(actor->pos[VZ] <= actor->floorZ) P_MobjChangeState(actor, S_IMP_CRASH1); } /** * @return @c true, if the chicken morphs. */ boolean P_UpdateChicken(mobj_t *actor, int tics) { mobj_t *fog; float pos[3]; mobjtype_t moType; mobj_t *mo; mobj_t oldChicken; actor->special1 -= tics; if(actor->special1 > 0) return false; moType = actor->special2; memcpy(pos, actor->pos, sizeof(pos)); //// \fixme Do this properly! memcpy(&oldChicken, actor, sizeof(oldChicken)); if(!(mo = P_SpawnMobj3fv(moType, pos, oldChicken.angle, 0))) return false; P_MobjChangeState(actor, S_FREETARGMOBJ); if(P_TestMobjLocation(mo) == false) { // Didn't fit. P_MobjRemove(mo, true); if((mo = P_SpawnMobj3fv(MT_CHICKEN, pos, oldChicken.angle, 0))) { mo->flags = oldChicken.flags; mo->health = oldChicken.health; mo->target = oldChicken.target; mo->special1 = 5 * TICSPERSEC; // Next try in 5 seconds. mo->special2 = moType; } return false; } mo->target = oldChicken.target; if((fog = P_SpawnMobj3f(MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, mo->angle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); return true; } void C_DECL A_ChicAttack(mobj_t *actor) { if(P_UpdateChicken(actor, 18)) return; if(!actor->target) return; if(P_CheckMeleeRange(actor)) P_DamageMobj(actor->target, actor, actor, 1 + (P_Random() & 1), false); } void C_DECL A_ChicLook(mobj_t *actor) { if(P_UpdateChicken(actor, 10)) return; A_Look(actor); } void C_DECL A_ChicChase(mobj_t *actor) { if(P_UpdateChicken(actor, 3)) return; A_Chase(actor); } void C_DECL A_ChicPain(mobj_t *actor) { if(P_UpdateChicken(actor, 10)) return; S_StartSound(actor->info->painSound, actor); } void C_DECL A_Feathers(mobj_t *actor) { int i, count; mobj_t *mo; // In Pain? if(actor->health > 0) count = P_Random() < 32 ? 2 : 1; else // Death. count = 5 + (P_Random() & 3); for(i = 0; i < count; ++i) { if((mo = P_SpawnMobj3f(MT_FEATHER, actor->pos[VX], actor->pos[VY], actor->pos[VZ] + 20, P_Random() << 24, 0))) { mo->target = actor; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MZ] = 1 + FIX2FLT(P_Random() << 9); P_MobjChangeState(mo, S_FEATHER1 + (P_Random() & 7)); } } } void C_DECL A_MummyAttack(mobj_t *actor) { if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(2), false); S_StartSound(SFX_MUMAT2, actor); return; } S_StartSound(SFX_MUMAT1, actor); } /** * Mummy leader missile attack. */ void C_DECL A_MummyAttack2(mobj_t *actor) { mobj_t *mo; if(!actor->target) return; if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(2), false); return; } mo = P_SpawnMissile(MT_MUMMYFX1, actor, actor->target, true); if(mo != NULL) mo->tracer = actor->target; } void C_DECL A_MummyFX1Seek(mobj_t* actor) { P_SeekerMissile(actor, ANGLE_1 * 10, ANGLE_1 * 20); } void C_DECL A_MummySoul(mobj_t* mummy) { mobj_t* mo; if((mo = P_SpawnMobj3f(MT_MUMMYSOUL, mummy->pos[VX], mummy->pos[VY], mummy->pos[VZ] + 10, mummy->angle, 0))) { mo->mom[MZ] = 1; } } void C_DECL A_Sor1Pain(mobj_t* actor) { actor->special1 = 20; // Number of steps to walk fast. A_Pain(actor); } void C_DECL A_Sor1Chase(mobj_t *actor) { if(actor->special1) { actor->special1--; actor->tics -= 3; } A_Chase(actor); } /** * Sorcerer demon attack. */ void C_DECL A_Srcr1Attack(mobj_t *actor) { mobj_t *mo; angle_t angle; if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(8), false); return; } if(actor->health > (actor->info->spawnHealth / 3) * 2) { // Spit one fireball. P_SpawnMissile(MT_SRCRFX1, actor, actor->target, true); } else { // Spit three fireballs. mo = P_SpawnMissile(MT_SRCRFX1, actor, actor->target, true); if(mo) { angle = mo->angle; P_SpawnMissileAngle(MT_SRCRFX1, actor, angle - ANGLE_1 * 3, mo->mom[MZ]); P_SpawnMissileAngle(MT_SRCRFX1, actor, angle + ANGLE_1 * 3, mo->mom[MZ]); } if(actor->health < actor->info->spawnHealth / 3) { // Maybe attack again? if(actor->special1) { // Just attacked, so don't attack again/ actor->special1 = 0; } else { // Set state to attack again/ actor->special1 = 1; P_MobjChangeState(actor, S_SRCR1_ATK4); } } } } void C_DECL A_SorcererRise(mobj_t* actor) { mobj_t* mo; actor->flags &= ~MF_SOLID; if((mo = P_SpawnMobj3fv(MT_SORCERER2, actor->pos, actor->angle, 0))) { P_MobjChangeState(mo, S_SOR2_RISE1); mo->target = actor->target; } } void P_DSparilTeleport(mobj_t* actor) { // No spots? if(bossSpotCount > 0) { int i, tries; const mapspot_t* dest; i = P_Random(); tries = bossSpotCount; do { dest = &bossSpots[++i % bossSpotCount]; if(P_ApproxDistance(actor->pos[VX] - dest->pos[VX], actor->pos[VY] - dest->pos[VY]) >= 128) { // A suitable teleport destination is available. float prevpos[3]; angle_t oldAngle; memcpy(prevpos, actor->pos, sizeof(prevpos)); oldAngle = actor->angle; if(P_TeleportMove(actor, dest->pos[VX], dest->pos[VY], false)) { mobj_t* mo; if((mo = P_SpawnMobj3fv(MT_SOR2TELEFADE, prevpos, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPT, mo); P_MobjChangeState(actor, S_SOR2_TELE1); actor->pos[VZ] = actor->floorZ; actor->angle = dest->angle; actor->mom[MX] = actor->mom[MY] = actor->mom[MZ] = 0; S_StartSound(SFX_TELEPT, actor); } return; } } while(tries-- > 0); // Don't stay here forever. } } void C_DECL A_Srcr2Decide(mobj_t *actor) { static int chance[] = { 192, 120, 120, 120, 64, 64, 32, 16, 0 }; // No spots? if(!bossSpotCount) return; if(P_Random() < chance[actor->health / (actor->info->spawnHealth / 8)]) { P_DSparilTeleport(actor); } } void C_DECL A_Srcr2Attack(mobj_t *actor) { int chance; if(!actor->target) return; S_StartSound(actor->info->attackSound, NULL); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(20), false); return; } chance = actor->health < actor->info->spawnHealth / 2 ? 96 : 48; if(P_Random() < chance) { // Wizard spawners. P_SpawnMissileAngle(MT_SOR2FX2, actor, actor->angle - ANG45, 1.0f/2); P_SpawnMissileAngle(MT_SOR2FX2, actor, actor->angle + ANG45, 1.0f/2); } else { // Blue bolt. P_SpawnMissile(MT_SOR2FX1, actor, actor->target, true); } } void C_DECL A_BlueSpark(mobj_t* actor) { int i; for(i = 0; i < 2; ++i) { mobj_t* mo; if((mo = P_SpawnMobj3fv(MT_SOR2FXSPARK, actor->pos, P_Random() << 24, 0))) { mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MZ] = 1 + FIX2FLT(P_Random() << 8); } } } void C_DECL A_GenWizard(mobj_t* actor) { mobj_t* mo, *fog; if(!(mo = P_SpawnMobj3f(MT_WIZARD, actor->pos[VX], actor->pos[VY], actor->pos[VZ] - (MOBJINFO[MT_WIZARD].height / 2), actor->angle, 0))) return; if(P_TestMobjLocation(mo) == false) { // Didn't fit. P_MobjRemove(mo, true); return; } actor->mom[MX] = actor->mom[MY] = actor->mom[MZ] = 0; P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH)); actor->flags &= ~MF_MISSILE; if((fog = P_SpawnMobj3fv(MT_TFOG, actor->pos, actor->angle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); } void C_DECL A_Sor2DthInit(mobj_t *actor) { // Set the animation loop counter. actor->special1 = 7; // Kill monsters early. P_Massacre(); } void C_DECL A_Sor2DthLoop(mobj_t *actor) { if(--actor->special1) { // Need to loop. P_MobjChangeState(actor, S_SOR2_DIE4); } } /** * D'Sparil Sound Routines. */ void C_DECL A_SorZap(mobj_t *actor) { S_StartSound(SFX_SORZAP, NULL); } void C_DECL A_SorRise(mobj_t *actor) { S_StartSound(SFX_SORRISE, NULL); } void C_DECL A_SorDSph(mobj_t *actor) { S_StartSound(SFX_SORDSPH, NULL); } void C_DECL A_SorDExp(mobj_t *actor) { S_StartSound(SFX_SORDEXP, NULL); } void C_DECL A_SorDBon(mobj_t *actor) { S_StartSound(SFX_SORDBON, NULL); } void C_DECL A_SorSightSnd(mobj_t* actor) { S_StartSound(SFX_SORSIT, NULL); } /** * Minotaur Melee attack. */ void C_DECL A_MinotaurAtk1(mobj_t* actor) { player_t* player; if(!actor->target) return; S_StartSound(SFX_STFPOW, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(4), false); if((player = actor->target->player) != NULL) { // Squish the player. player->viewHeightDelta = -16; } } } /** * Minotaur : Choose a missile attack. */ void C_DECL A_MinotaurDecide(mobj_t* actor) { uint an; mobj_t* target; float dist; target = actor->target; if(!target) return; S_StartSound(SFX_MINSIT, actor); dist = P_ApproxDistance(actor->pos[VX] - target->pos[VX], actor->pos[VY] - target->pos[VY]); if(target->pos[VZ] + target->height > actor->pos[VZ] && target->pos[VZ] + target->height < actor->pos[VZ] + actor->height && dist < 8 * 64 && dist > 1 * 64 && P_Random() < 150) { // Charge attack. // Don't call the state function right away. P_SetMobjStateNF(actor, S_MNTR_ATK4_1); actor->flags |= MF_SKULLFLY; A_FaceTarget(actor); an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = MNTR_CHARGE_SPEED * FIX2FLT(finecosine[an]); actor->mom[MY] = MNTR_CHARGE_SPEED * FIX2FLT(finesine[an]); // Charge duration. actor->special1 = 35 / 2; } else if(target->pos[VZ] == target->floorZ && dist < 9 * 64 && P_Random() < 220) { // Floor fire attack. P_MobjChangeState(actor, S_MNTR_ATK3_1); actor->special2 = 0; } else { // Swing attack. A_FaceTarget(actor); // NOTE: Don't need to call P_MobjChangeState because the current // state falls through to the swing attack } } void C_DECL A_MinotaurCharge(mobj_t* actor) { mobj_t* puff; if(actor->special1) { if((puff = P_SpawnMobj3fv(MT_PHOENIXPUFF, actor->pos, P_Random() << 24, 0))) puff->mom[MZ] = 2; actor->special1--; } else { actor->flags &= ~MF_SKULLFLY; P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } } /** * Minotaur : Swing attack. */ void C_DECL A_MinotaurAtk2(mobj_t* actor) { mobj_t* mo; if(!actor->target) return; S_StartSound(SFX_MINAT2, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(5), false); return; } mo = P_SpawnMissile(MT_MNTRFX1, actor, actor->target, true); if(mo) { angle_t angle = mo->angle; float momZ = mo->mom[MZ]; S_StartSound(SFX_MINAT2, mo); P_SpawnMissileAngle(MT_MNTRFX1, actor, angle - (ANG45 / 8), momZ); P_SpawnMissileAngle(MT_MNTRFX1, actor, angle + (ANG45 / 8), momZ); P_SpawnMissileAngle(MT_MNTRFX1, actor, angle - (ANG45 / 16), momZ); P_SpawnMissileAngle(MT_MNTRFX1, actor, angle + (ANG45 / 16), momZ); } } /** * Minotaur : Floor fire attack. */ void C_DECL A_MinotaurAtk3(mobj_t* actor) { player_t* player; if(!actor->target) return; if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(5), false); if((player = actor->target->player) != NULL) { // Squish the player. player->viewHeightDelta = -16; } } else { mobj_t* mo; boolean fixFloorFire = (!cfg.fixFloorFire && actor->floorClip > 0); /** * Original Heretic bug: * When an attempt is made to spawn MT_MNTRFX2 (the Maulotaur's * ground flame) the z coordinate is set to ONFLOORZ but if the * Maulotaur's feet are currently clipped (i.e., it is in a sector * whose terrain info is set to clip) then FOOTCLIPSIZE is * subtracted from the z coordinate. So when P_SpawnMobj is called, * z != ONFLOORZ, so rather than being set to the height of the * floor it is left at 2146838915 (float: 32758.162). * * This in turn means that when P_TryMove is called (via * P_CheckMissileSpawn), the test which is there to check whether a * missile hits an upper sidedef section will return true * (ceilingheight - thingz > thingheight). * * This results in P_ExplodeMissile being called instantly. * * jHeretic fixes this bug, however we maintain original behaviour * using the following method: * * 1) Do not call P_CheckMissileSpawn from P_SpawnMissile. * 2) Use special-case logic here which behaves similarly. */ if((mo = P_SpawnMissile(MT_MNTRFX2, actor, actor->target, (fixFloorFire? false : true)))) { if(fixFloorFire) { mo->pos[VX] += mo->mom[MX] / 2; mo->pos[VY] += mo->mom[MY] / 2; mo->pos[VZ] += mo->mom[MZ] / 2; P_ExplodeMissile(mo); } else { S_StartSound(SFX_MINAT1, mo); } } } if(P_Random() < 192 && actor->special2 == 0) { P_MobjChangeState(actor, S_MNTR_ATK3_4); actor->special2 = 1; } } void C_DECL A_MntrFloorFire(mobj_t* actor) { mobj_t* mo; float pos[3]; angle_t angle; // Make sure we are on the floor. actor->pos[VZ] = actor->floorZ; pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = 0; pos[VX] += FIX2FLT((P_Random() - P_Random()) << 10); pos[VY] += FIX2FLT((P_Random() - P_Random()) << 10); angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], pos[VX], pos[VY]); if((mo = P_SpawnMobj3fv(MT_MNTRFX3, pos, angle, MSF_Z_FLOOR))) { mo->target = actor->target; mo->mom[MX] = FIX2FLT(1); // Force block checking. P_CheckMissileSpawn(mo); } } void C_DECL A_BeastAttack(mobj_t* actor) { if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(3), false); return; } P_SpawnMissile(MT_BEASTBALL, actor, actor->target, true); } void C_DECL A_HeadAttack(mobj_t *actor) { int i; mobj_t *fire, *baseFire, *mo, *target; int randAttack; static int atkResolve1[] = { 50, 150 }; static int atkResolve2[] = { 150, 200 }; float dist; // Ice ball (close 20% : far 60%) // Fire column (close 40% : far 20%) // Whirlwind (close 40% : far 20%) // Distance threshold = 8 cells target = actor->target; if(target == NULL) return; A_FaceTarget(actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(target, actor, actor, HITDICE(6), false); return; } dist = P_ApproxDistance(actor->pos[VX] - target->pos[VX], actor->pos[VY] - target->pos[VY]) > 8 * 64; randAttack = P_Random(); if(randAttack < atkResolve1[(FLT2FIX(dist) != 0)? 1 : 0]) { // Ice ball P_SpawnMissile(MT_HEADFX1, actor, target, true); S_StartSound(SFX_HEDAT2, actor); } else if(randAttack < atkResolve2[(FLT2FIX(dist) != 0)? 1 : 0]) { // Fire column baseFire = P_SpawnMissile(MT_HEADFX3, actor, target, true); if(baseFire != NULL) { P_MobjChangeState(baseFire, S_HEADFX3_4); // Don't grow for(i = 0; i < 5; ++i) { if((fire = P_SpawnMobj3fv(MT_HEADFX3, baseFire->pos, baseFire->angle, 0))) { if(i == 0) S_StartSound(SFX_HEDAT1, actor); fire->target = baseFire->target; fire->mom[MX] = baseFire->mom[MX]; fire->mom[MY] = baseFire->mom[MY]; fire->mom[MZ] = baseFire->mom[MZ]; fire->damage = 0; fire->special3 = (i + 1) * 2; P_CheckMissileSpawn(fire); } } } } else { // Whirlwind. if((mo = P_SpawnMissile(MT_WHIRLWIND, actor, target, true))) { mo->pos[VZ] -= 32; mo->tracer = target; mo->special1 = 60; mo->special2 = 50; // Timer for active sound. mo->special3 = 20 * TICSPERSEC; // Duration. S_StartSound(SFX_HEDAT3, actor); } } } void C_DECL A_WhirlwindSeek(mobj_t *actor) { actor->special3 -= 3; if(actor->special3 < 0) { actor->mom[MX] = actor->mom[MY] = actor->mom[MZ] = 0; P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH)); actor->flags &= ~MF_MISSILE; return; } if((actor->special2 -= 3) < 0) { actor->special2 = 58 + (P_Random() & 31); S_StartSound(SFX_HEDAT3, actor); } if(actor->tracer && actor->tracer->flags & MF_SHADOW) return; P_SeekerMissile(actor, ANGLE_1 * 10, ANGLE_1 * 30); } void C_DECL A_HeadIceImpact(mobj_t *ice) { int i; for(i = 0; i < 8; ++i) { mobj_t* shard; angle_t angle = i * ANG45; if((shard = P_SpawnMobj3fv(MT_HEADFX2, ice->pos, angle, 0))) { unsigned int an = angle >> ANGLETOFINESHIFT; shard->target = ice->target; shard->mom[MX] = shard->info->speed * FIX2FLT(finecosine[an]); shard->mom[MY] = shard->info->speed * FIX2FLT(finesine[an]); shard->mom[MZ] = -.6f; P_CheckMissileSpawn(shard); } } } void C_DECL A_HeadFireGrow(mobj_t *fire) { fire->special3--; fire->pos[VZ] += 9; if(fire->special3 == 0) { fire->damage = fire->info->damage; P_MobjChangeState(fire, S_HEADFX3_4); } } void C_DECL A_SnakeAttack(mobj_t *actor) { if(!actor->target) { P_MobjChangeState(actor, S_SNAKE_WALK1); return; } S_StartSound(actor->info->attackSound, actor); A_FaceTarget(actor); P_SpawnMissile(MT_SNAKEPRO_A, actor, actor->target, true); } void C_DECL A_SnakeAttack2(mobj_t *actor) { if(!actor->target) { P_MobjChangeState(actor, S_SNAKE_WALK1); return; } S_StartSound(actor->info->attackSound, actor); A_FaceTarget(actor); P_SpawnMissile(MT_SNAKEPRO_B, actor, actor->target, true); } void C_DECL A_ClinkAttack(mobj_t *actor) { int damage; if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor)) { damage = ((P_Random() % 7) + 3); P_DamageMobj(actor->target, actor, actor, damage, false); } } void C_DECL A_GhostOff(mobj_t *actor) { actor->flags &= ~MF_SHADOW; } void C_DECL A_WizAtk1(mobj_t *actor) { A_FaceTarget(actor); actor->flags &= ~MF_SHADOW; } void C_DECL A_WizAtk2(mobj_t *actor) { A_FaceTarget(actor); actor->flags |= MF_SHADOW; } void C_DECL A_WizAtk3(mobj_t *actor) { mobj_t *mo; angle_t angle; float momZ; actor->flags &= ~MF_SHADOW; if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor)) { P_DamageMobj(actor->target, actor, actor, HITDICE(4), false); return; } mo = P_SpawnMissile(MT_WIZFX1, actor, actor->target, true); if(mo) { momZ = mo->mom[MZ]; angle = mo->angle; P_SpawnMissileAngle(MT_WIZFX1, actor, angle - (ANG45 / 8), momZ); P_SpawnMissileAngle(MT_WIZFX1, actor, angle + (ANG45 / 8), momZ); } } void C_DECL A_Scream(mobj_t *actor) { switch(actor->type) { case MT_CHICPLAYER: case MT_SORCERER1: case MT_MINOTAUR: // Make boss death sounds full volume S_StartSound(actor->info->deathSound, NULL); break; case MT_PLAYER: // Handle the different player death screams if(actor->special1 < 10) { // Wimpy death sound. S_StartSound(SFX_PLRWDTH, actor); } else if(actor->health > -50) { // Normal death sound. S_StartSound(actor->info->deathSound, actor); } else if(actor->health > -100) { // Crazy death sound. S_StartSound(SFX_PLRCDTH, actor); } else { // Extreme death sound. S_StartSound(SFX_GIBDTH, actor); } break; default: S_StartSound(actor->info->deathSound, actor); break; } } mobj_t* P_DropItem(mobjtype_t type, mobj_t* source, int special, int chance) { mobj_t* mo; if(P_Random() > chance) return NULL; if((mo = P_SpawnMobj3f(type, source->pos[VX], source->pos[VY], source->pos[VZ] + source->height / 2, source->angle, 0))) { mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 8); if(!(mo->info->flags2 & MF2_FLOATBOB)) mo->mom[MZ] = 5 + FIX2FLT(P_Random() << 10); mo->flags |= MF_DROPPED; mo->health = special; } return mo; } void C_DECL A_NoBlocking(mobj_t *actor) { actor->flags &= ~MF_SOLID; // Check for monsters dropping things. switch(actor->type) { case MT_MUMMY: case MT_MUMMYLEADER: case MT_MUMMYGHOST: case MT_MUMMYLEADERGHOST: P_DropItem(MT_AMGWNDWIMPY, actor, 3, 84); break; case MT_KNIGHT: case MT_KNIGHTGHOST: P_DropItem(MT_AMCBOWWIMPY, actor, 5, 84); break; case MT_WIZARD: P_DropItem(MT_AMBLSRWIMPY, actor, 10, 84); P_DropItem(MT_ARTITOMEOFPOWER, actor, 0, 4); break; case MT_HEAD: P_DropItem(MT_AMBLSRWIMPY, actor, 10, 84); P_DropItem(MT_ARTIEGG, actor, 0, 51); break; case MT_BEAST: P_DropItem(MT_AMCBOWWIMPY, actor, 10, 84); break; case MT_CLINK: P_DropItem(MT_AMSKRDWIMPY, actor, 20, 84); break; case MT_SNAKE: P_DropItem(MT_AMPHRDWIMPY, actor, 5, 84); break; case MT_MINOTAUR: P_DropItem(MT_ARTISUPERHEAL, actor, 0, 51); P_DropItem(MT_AMPHRDWIMPY, actor, 10, 84); break; default: break; } } void C_DECL A_Explode(mobj_t* actor) { int damage; damage = 128; switch(actor->type) { case MT_FIREBOMB: // Time Bombs. actor->pos[VZ] += 32; actor->flags &= ~MF_SHADOW; actor->flags |= MF_BRIGHTSHADOW | MF_VIEWALIGN; break; case MT_MNTRFX2: // Minotaur floor fire damage = 24; break; case MT_SOR2FX1: // D'Sparil missile damage = 80 + (P_Random() & 31); break; default: break; } P_RadiusAttack(actor, actor->target, damage, damage - 1); P_HitFloor(actor); } void C_DECL A_PodPain(mobj_t *actor) { int i, count, chance; chance = P_Random(); if(chance < 128) return; if(chance > 240) count = 2; else count = 1; for(i = 0; i < count; ++i) { mobj_t* goo; if((goo = P_SpawnMobj3f(MT_PODGOO, actor->pos[VX], actor->pos[VY], actor->pos[VZ] + 48, actor->angle, 0))) { goo->target = actor; goo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); goo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); goo->mom[MZ] = 1.0f / 2 + FIX2FLT((P_Random() << 9)); } } } void C_DECL A_RemovePod(mobj_t* actor) { mobj_t* mo; if((mo = actor->generator)) { if(mo->special1 > 0) mo->special1--; } } void C_DECL A_MakePod(mobj_t* actor) { mobj_t* mo; // Too many generated pods? if(actor->special1 == MAX_GEN_PODS) return; if(!(mo = P_SpawnMobj3f(MT_POD, actor->pos[VX], actor->pos[VY], 0, actor->angle, MSF_Z_FLOOR))) return; if(P_CheckPosition2f(mo, mo->pos[VX], mo->pos[VY]) == false) { // Didn't fit. P_MobjRemove(mo, true); return; } P_MobjChangeState(mo, S_POD_GROW1); P_ThrustMobj(mo, P_Random() << 24, 4.5f); S_StartSound(SFX_NEWPOD, mo); // Increment generated pod count. actor->special1++; // Link the generator to the pod. mo->generator = actor; return; } static boolean massacreMobj(thinker_t* th, void* context) { int* count = (int*) context; mobj_t* mo = (mobj_t *) th; if(!mo->player && sentient(mo) && (mo->flags & MF_SHOOTABLE)) { P_DamageMobj(mo, NULL, NULL, 10000, false); (*count)++; } return true; // Continue iteration. } /** * Kills all monsters. */ int P_Massacre(void) { int count = 0; // Only massacre when actually in a level. if(G_GetGameState() == GS_MAP) { DD_IterateThinkers(P_MobjThinker, massacreMobj, &count); } return count; } typedef struct { mobjtype_t type; size_t count; } countmobjoftypeparams_t; static boolean countMobjOfType(thinker_t* th, void* context) { countmobjoftypeparams_t *params = (countmobjoftypeparams_t*) context; mobj_t* mo = (mobj_t *) th; if(params->type == mo->type && mo->health > 0) params->count++; return true; // Continue iteration. } /** * Trigger special effects if all bosses are dead. */ void C_DECL A_BossDeath(mobj_t* actor) { static mobjtype_t bossType[6] = { MT_HEAD, MT_MINOTAUR, MT_SORCERER2, MT_HEAD, MT_MINOTAUR, -1 }; linedef_t* dummyLine; countmobjoftypeparams_t params; // Not a boss level? if(gameMap != 7) return; // Not considered a boss in this episode? if(actor->type != bossType[gameEpisode]) return; // Scan the remaining thinkers to see if all bosses are dead. params.type = actor->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(params.count) { // Other boss not dead. return; } // Kill any remaining monsters. if(gameEpisode != 0) P_Massacre(); dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoFloor(dummyLine, FT_LOWER); P_FreeDummyLine(dummyLine); } void C_DECL A_ESound(mobj_t *mo) { int sound; switch(mo->type) { case MT_SOUNDWATERFALL: sound = SFX_WATERFL; break; case MT_SOUNDWIND: sound = SFX_WIND; break; default: return; } S_StartSound(sound, mo); } void C_DECL A_SpawnTeleGlitter(mobj_t* actor) { mobj_t* mo; if(!actor) return; if((mo = P_SpawnMobj3f(MT_TELEGLITTER, actor->pos[VX] + ((P_Random() & 31) - 16), actor->pos[VY] + ((P_Random() & 31) - 16), P_GetFloatp(actor->subsector, DMU_FLOOR_HEIGHT), P_Random() << 24, 0))) { mo->mom[MZ] = 1.0f / 4; mo->special3 = 1000; } } void C_DECL A_SpawnTeleGlitter2(mobj_t* actor) { mobj_t* mo; if(!actor) return; if((mo = P_SpawnMobj3f(MT_TELEGLITTER2, actor->pos[VX] + ((P_Random() & 31) - 16), actor->pos[VY] + ((P_Random() & 31) - 16), P_GetFloatp(actor->subsector, DMU_FLOOR_HEIGHT), P_Random() << 24, 0))) { mo->mom[MZ] = 1.0f / 4; mo->special3 = 1000; } } void C_DECL A_AccTeleGlitter(mobj_t *actor) { if(++actor->special3 > 35) actor->mom[MZ] += actor->mom[MZ] / 2; } void C_DECL A_InitKeyGizmo(mobj_t *gizmo) { mobj_t* mo; statenum_t state; switch(gizmo->type) { case MT_KEYGIZMOBLUE: state = S_KGZ_BLUEFLOAT1; break; case MT_KEYGIZMOGREEN: state = S_KGZ_GREENFLOAT1; break; case MT_KEYGIZMOYELLOW: state = S_KGZ_YELLOWFLOAT1; break; default: return; } if((mo = P_SpawnMobj3f(MT_KEYGIZMOFLOAT, gizmo->pos[VX], gizmo->pos[VY], gizmo->pos[VZ] + 60, gizmo->angle, 0))) { P_MobjChangeState(mo, state); } } void C_DECL A_VolcanoSet(mobj_t* volcano) { volcano->tics = 105 + (P_Random() & 127); } void C_DECL A_VolcanoBlast(mobj_t* volcano) { int i, count; count = 1 + (P_Random() % 3); for(i = 0; i < count; i++) { mobj_t* blast; unsigned int an; if((blast = P_SpawnMobj3f(MT_VOLCANOBLAST, volcano->pos[VX], volcano->pos[VY], volcano->pos[VZ] + 44, P_Random() << 24, 0))) { blast->target = volcano; an = blast->angle >> ANGLETOFINESHIFT; blast->mom[MX] = 1 * FIX2FLT(finecosine[an]); blast->mom[MY] = 1 * FIX2FLT(finesine[an]); blast->mom[MZ] = 2.5f + FIX2FLT(P_Random() << 10); S_StartSound(SFX_VOLSHT, blast); P_CheckMissileSpawn(blast); } } } void C_DECL A_VolcBallImpact(mobj_t* ball) { int i; if(ball->pos[VZ] <= ball->floorZ) { ball->flags |= MF_NOGRAVITY; ball->flags2 &= ~MF2_LOGRAV; ball->pos[VZ] += 28; } P_RadiusAttack(ball, ball->target, 25, 24); for(i = 0; i < 4; ++i) { mobj_t* tiny; if((tiny = P_SpawnMobj3fv(MT_VOLCANOTBLAST, ball->pos, i * ANG90, 0))) { unsigned int an = tiny->angle >> ANGLETOFINESHIFT; tiny->target = ball; tiny->mom[MX] = .7f * FIX2FLT(finecosine[an]); tiny->mom[MY] = .7f * FIX2FLT(finesine[an]); tiny->mom[MZ] = 1 + FIX2FLT(P_Random() << 9); P_CheckMissileSpawn(tiny); } } } void C_DECL A_SkullPop(mobj_t* actor) { mobj_t* mo; if((mo = P_SpawnMobj3f(MT_BLOODYSKULL, actor->pos[VX], actor->pos[VY], actor->pos[VZ] + 48, actor->angle, 0))) { player_t* player; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MZ] = 2 + FIX2FLT(P_Random() << 6); // Attach player mobj to bloody skull. player = actor->player; actor->player = NULL; actor->dPlayer = NULL; actor->flags &= ~MF_SOLID; mo->player = player; mo->dPlayer = player->plr; mo->health = actor->health; player->plr->mo = mo; player->plr->lookDir = 0; player->damageCount = 32; } } void C_DECL A_CheckSkullFloor(mobj_t *actor) { if(actor->pos[VZ] <= actor->floorZ) P_MobjChangeState(actor, S_BLOODYSKULLX1); } void C_DECL A_CheckSkullDone(mobj_t *actor) { if(actor->special2 == 666) P_MobjChangeState(actor, S_BLOODYSKULLX2); } void C_DECL A_CheckBurnGone(mobj_t *actor) { if(actor->special2 == 666) P_MobjChangeState(actor, S_PLAY_FDTH20); } void C_DECL A_FreeTargMobj(mobj_t *mo) { mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; mo->pos[VZ] = mo->ceilingZ + 4; mo->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_SOLID); mo->flags |= MF_CORPSE | MF_DROPOFF | MF_NOGRAVITY; mo->flags2 &= ~(MF2_PASSMOBJ | MF2_LOGRAV); mo->player = NULL; mo->dPlayer = NULL; } void C_DECL A_AddPlayerCorpse(mobj_t *actor) { // Too many player corpses? if(bodyqueslot >= BODYQUESIZE) { // Remove an old one. P_MobjRemove(bodyque[bodyqueslot % BODYQUESIZE], true); } bodyque[bodyqueslot % BODYQUESIZE] = actor; bodyqueslot++; } void C_DECL A_FlameSnd(mobj_t *actor) { S_StartSound(SFX_HEDAT1, actor); // Burn sound. } void C_DECL A_HideThing(mobj_t *actor) { //P_MobjUnsetPosition(actor); actor->flags2 |= MF2_DONTDRAW; } void C_DECL A_UnHideThing(mobj_t *actor) { //P_MobjSetPosition(actor); actor->flags2 &= ~MF2_DONTDRAW; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_spec.c0000644000175000017500000013534511357170242022562 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.c: Implements special effects. * * Texture animation, height or lighting changes according to adjacent * sectors, respective utility functions, etc. * * Line Tag handling. Line and Sector triggers. * * Events are operations triggered by using, crossing, or shooting special * lines, or by timed thinkers. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "m_argv.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_mapspec.h" #include "p_player.h" #include "p_tick.h" #include "p_ceiling.h" #include "p_door.h" #include "p_floor.h" #include "p_plat.h" #include "p_switch.h" #include "d_netsv.h" // MACROS ------------------------------------------------------------------ #define MAX_AMBIENT_SFX 8 // Per level // TYPES ------------------------------------------------------------------- typedef enum afxcmd_e { afxcmd_play, // (sound) afxcmd_playabsvol, // (sound, volume) afxcmd_playrelvol, // (sound, volume) afxcmd_delay, // (ticks) afxcmd_delayrand, // (andbits) afxcmd_end // () } afxcmd_t; // Animating textures and planes // In Doomsday these are handled via DED definitions. // In BOOM they invented the ANIMATED lump for the same purpose. // This struct is directly read from the lump. // So its important we keep it aligned. #pragma pack(1) typedef struct animdef_s { /* Do NOT change these members in any way */ signed char istexture; // if false, it is a flat (instead of bool) char endname[9]; char startname[9]; int speed; } animdef_t; #pragma pack() // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void P_CrossSpecialLine(linedef_t* line, int side, mobj_t* thing); static void P_ShootSpecialLine(mobj_t* thing, linedef_t* line); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- mobj_t LavaInflictor; int* LevelAmbientSfx[MAX_AMBIENT_SFX]; int* AmbSfxPtr; int AmbSfxCount; int AmbSfxTics; int AmbSfxVolume; int AmbSndSeqInit[] = { // Startup afxcmd_end }; int AmbSndSeq1[] = { // Scream afxcmd_play, SFX_AMB1, afxcmd_end }; int AmbSndSeq2[] = { // Squish afxcmd_play, SFX_AMB2, afxcmd_end }; int AmbSndSeq3[] = { // Drops afxcmd_play, SFX_AMB3, afxcmd_delay, 16, afxcmd_delayrand, 31, afxcmd_play, SFX_AMB7, afxcmd_delay, 16, afxcmd_delayrand, 31, afxcmd_play, SFX_AMB3, afxcmd_delay, 16, afxcmd_delayrand, 31, afxcmd_play, SFX_AMB7, afxcmd_delay, 16, afxcmd_delayrand, 31, afxcmd_play, SFX_AMB3, afxcmd_delay, 16, afxcmd_delayrand, 31, afxcmd_play, SFX_AMB7, afxcmd_delay, 16, afxcmd_delayrand, 31, afxcmd_end }; int AmbSndSeq4[] = { // SlowFootSteps afxcmd_play, SFX_AMB4, afxcmd_delay, 15, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_delay, 15, afxcmd_playrelvol, SFX_AMB4, -3, afxcmd_delay, 15, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_delay, 15, afxcmd_playrelvol, SFX_AMB4, -3, afxcmd_delay, 15, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_delay, 15, afxcmd_playrelvol, SFX_AMB4, -3, afxcmd_delay, 15, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_end }; int AmbSndSeq5[] = { // Heartbeat afxcmd_play, SFX_AMB5, afxcmd_delay, 35, afxcmd_play, SFX_AMB5, afxcmd_delay, 35, afxcmd_play, SFX_AMB5, afxcmd_delay, 35, afxcmd_play, SFX_AMB5, afxcmd_end }; int AmbSndSeq6[] = { // Bells afxcmd_play, SFX_AMB6, afxcmd_delay, 17, afxcmd_playrelvol, SFX_AMB6, -8, afxcmd_delay, 17, afxcmd_playrelvol, SFX_AMB6, -8, afxcmd_delay, 17, afxcmd_playrelvol, SFX_AMB6, -8, afxcmd_end }; int AmbSndSeq7[] = { // Growl afxcmd_play, SFX_BSTSIT, afxcmd_end }; int AmbSndSeq8[] = { // Magic afxcmd_play, SFX_AMB8, afxcmd_end }; int AmbSndSeq9[] = { // Laughter afxcmd_play, SFX_AMB9, afxcmd_delay, 16, afxcmd_playrelvol, SFX_AMB9, -4, afxcmd_delay, 16, afxcmd_playrelvol, SFX_AMB9, -4, afxcmd_delay, 16, afxcmd_playrelvol, SFX_AMB10, -4, afxcmd_delay, 16, afxcmd_playrelvol, SFX_AMB10, -4, afxcmd_delay, 16, afxcmd_playrelvol, SFX_AMB10, -4, afxcmd_end }; int AmbSndSeq10[] = { // FastFootsteps afxcmd_play, SFX_AMB4, afxcmd_delay, 8, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_delay, 8, afxcmd_playrelvol, SFX_AMB4, -3, afxcmd_delay, 8, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_delay, 8, afxcmd_playrelvol, SFX_AMB4, -3, afxcmd_delay, 8, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_delay, 8, afxcmd_playrelvol, SFX_AMB4, -3, afxcmd_delay, 8, afxcmd_playrelvol, SFX_AMB11, -3, afxcmd_end }; int* AmbientSfx[] = { AmbSndSeq1, // Scream AmbSndSeq2, // Squish AmbSndSeq3, // Drops AmbSndSeq4, // SlowFootsteps AmbSndSeq5, // Heartbeat AmbSndSeq6, // Bells AmbSndSeq7, // Growl AmbSndSeq8, // Magic AmbSndSeq9, // Laughter AmbSndSeq10 // FastFootsteps }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static animdef_t anims[] = { {0, "FLTWAWA3", "FLTWAWA1", MACRO_LONG(8)}, {0, "FLTSLUD3", "FLTSLUD1", MACRO_LONG(8)}, {0, "FLTTELE4", "FLTTELE1", MACRO_LONG(6)}, {0, "FLTFLWW3", "FLTFLWW1", MACRO_LONG(9)}, {0, "FLTLAVA4", "FLTLAVA1", MACRO_LONG(8)}, {0, "FLATHUH4", "FLATHUH1", MACRO_LONG(8)}, {1, "LAVAFL3", "LAVAFL1", MACRO_LONG(6)}, {1, "WATRWAL3", "WATRWAL1", MACRO_LONG(4)}, {-1, "\0", "\0"} }; // CODE -------------------------------------------------------------------- /** * From PrBoom: * Load the table of animation definitions, checking for existence of * the start and end of each frame. If the start doesn't exist the sequence * is skipped, if the last doesn't exist, BOOM exits. * * Wall/Flat animation sequences, defined by name of first and last frame, * The full animation sequence is given using all lumps between the start * and end entry, in the order found in the WAD file. * * This routine modified to read its data from a predefined lump or * PWAD lump called ANIMATED rather than a static table in this module to * allow wad designers to insert or modify animation sequences. * * Lump format is an array of byte packed animdef_t structures, terminated * by a structure with istexture == -1. The lump can be generated from a * text source file using SWANTBLS.EXE, distributed with the BOOM utils. * The standard list of switches and animations is contained in the example * source text file DEFSWANI.DAT also in the BOOM util distribution. */ static void loadAnimDefs(animdef_t* animDefs) { int i; // Read structures until -1 is found for(i = 0; animDefs[i].istexture != -1 ; ++i) { int groupNum, ticsPerFrame, numFrames; material_namespace_t mnamespace = (animDefs[i].istexture? MN_TEXTURES : MN_FLATS); switch(mnamespace) { case MN_FLATS: { lumpnum_t startFrame, endFrame, n; if((startFrame = W_CheckNumForName(animDefs[i].startname)) == -1 || (endFrame = W_CheckNumForName(animDefs[i].endname)) == -1) continue; numFrames = endFrame - startFrame + 1; ticsPerFrame = LONG(animDefs[i].speed); if(numFrames < 2) Con_Error("P_InitPicAnims: bad cycle from %s to %s", animDefs[i].startname, animDefs[i].endname); if(startFrame && endFrame) { // We have a valid animation. // Create a new animation group for it. groupNum = R_CreateAnimGroup(AGF_SMOOTH); /** * Doomsday's group animation needs to know the texture/flat * numbers of ALL frames in the animation group so we'll * have to step through the directory adding frames as we * go. (DOOM only required the start/end texture/flat * numbers and would animate all textures/flats inbetween). */ VERBOSE(Con_Message("P_InitPicAnims: ADD (\"%s\" > \"%s\" %d)\n", animDefs[i].startname, animDefs[i].endname, ticsPerFrame)); // Add all frames from start to end to the group. if(endFrame > startFrame) { for(n = startFrame; n <= endFrame; n++) { materialnum_t frame = P_MaterialCheckNumForName(W_LumpName(n), MN_FLATS); if(frame != 0) R_AddToAnimGroup(groupNum, frame, ticsPerFrame, 0); } } else { for(n = endFrame; n >= startFrame; n--) { materialnum_t frame = P_MaterialCheckNumForName(W_LumpName(n), MN_FLATS); if(frame != 0) R_AddToAnimGroup(groupNum, frame, ticsPerFrame, 0); } } } break; } case MN_TEXTURES: { // Same as above but for texture groups. materialnum_t startFrame, endFrame, n; if((startFrame = P_MaterialCheckNumForName(animDefs[i].startname, MN_TEXTURES)) == 0 || (endFrame = P_MaterialCheckNumForName(animDefs[i].endname, MN_TEXTURES)) == 0) continue; numFrames = endFrame - startFrame + 1; ticsPerFrame = LONG(animDefs[i].speed); if(numFrames < 2) Con_Error("P_InitPicAnims: bad cycle from %s to %s", animDefs[i].startname, animDefs[i].endname); if(startFrame && endFrame) { groupNum = R_CreateAnimGroup(AGF_SMOOTH); VERBOSE(Con_Message("P_InitPicAnims: ADD (\"%s\" > \"%s\" %d)\n", animDefs[i].startname, animDefs[i].endname, ticsPerFrame)); /** * \fixme Here an assumption is made that MN_TEXTURES type * materials are registered in the same order as they are * defined in the TEXTURE(1...) lump(s). */ if(endFrame > startFrame) { for(n = startFrame; n <= endFrame; n++) R_AddToAnimGroup(groupNum, n, ticsPerFrame, 0); } else { for(n = endFrame; n >= startFrame; n--) R_AddToAnimGroup(groupNum, n, ticsPerFrame, 0); } } break; } default: Con_Error("loadAnimDefs: Internal Error, invalid namespace %i.", (int) mnamespace); } } } void P_InitPicAnims(void) { int lump; // Is there an ANIMATED lump? if((lump = W_CheckNumForName("ANIMATED")) > 0) { animdef_t* animDefs; /** * We'll support this BOOM extension by reading the data and then * registering the new animations into Doomsday using the animation * groups feature. * * Support for this extension should be considered depreciated. * All new features should be added, accessed via DED. */ Con_Message("P_InitPicAnims: \"ANIMATED\" lump found. " "Reading animations...\n"); animDefs = (animdef_t *)W_CacheLumpNum(lump, PU_STATIC); loadAnimDefs(animDefs); Z_Free(animDefs); } else { Con_Message("P_InitPicAnims: Registering default animations...\n"); loadAnimDefs(anims); } VERBOSE(Con_Message("P_InitPicAnims: Done.\n")); } boolean P_ActivateLine(linedef_t *ld, mobj_t *mo, int side, int actType) { switch(actType) { case SPAC_CROSS: P_CrossSpecialLine(ld, side, mo); return true; case SPAC_USE: return P_UseSpecialLine(mo, ld, side); case SPAC_IMPACT: P_ShootSpecialLine(mo, ld); return true; default: Con_Error("P_ActivateLine: Unknown Activation Type %i", actType); break; } return false; } /** * Called every time a thing origin is about to cross a line with * a non 0 special. */ static void P_CrossSpecialLine(linedef_t *line, int side, mobj_t *thing) { int ok; xline_t* xline; // Extended functionality overrides old. if(XL_CrossLine(line, side, thing)) return; xline = P_ToXLine(line); // Triggers that other things can activate. if(!thing->player) { /* // DJS - All things can trigger specials in Heretic // Things that should NOT trigger specials... switch (thing->type) { case MT_ROCKET: case MT_PLASMA: case MT_BFG: case MT_TROOPSHOT: case MT_HEADSHOT: case MT_BRUISERSHOT: return; break; default: break; } */ ok = 0; switch(xline->special) { case 39: // TELEPORT TRIGGER case 97: // TELEPORT RETRIGGER //case 125: // TELEPORT MONSTERONLY TRIGGER //case 126: // TELEPORT MONSTERONLY RETRIGGER case 4: // RAISE DOOR //case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER //case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER ok = 1; break; } /* // DJS - Not implemented in jHeretic // Anything can trigger this line! if(P_GetInt(DMU_LINEDEF, linenum, DMU_FLAGS) & ML_ALLTRIGGER) ok = 1; */ if(!ok) return; } // Note: could use some const's here. switch(xline->special) { // TRIGGERS. // All from here to RETRIGGERS. case 2: // Open Door EV_DoDoor(line, DT_OPEN); xline->special = 0; break; case 3: // Close Door EV_DoDoor(line, DT_CLOSE); xline->special = 0; break; case 4: // Raise Door EV_DoDoor(line, DT_NORMAL); xline->special = 0; break; case 5: // Raise Floor EV_DoFloor(line, FT_RAISEFLOOR); xline->special = 0; break; case 6: // Fast Ceiling Crush & Raise EV_DoCeiling(line, CT_CRUSHANDRAISEFAST); xline->special = 0; break; case 8: // Build Stairs EV_BuildStairs(line, build8); xline->special = 0; break; case 10: // PlatDownWaitUp EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0); xline->special = 0; break; case 12: // Light Turn On - brightest near EV_LightTurnOn(line, 0); xline->special = 0; break; case 13: // Light Turn On 255 EV_LightTurnOn(line, 1); xline->special = 0; break; case 16: // Close Door 30 EV_DoDoor(line, DT_CLOSE30THENOPEN); xline->special = 0; break; case 17: // Start Light Strobing EV_StartLightStrobing(line); xline->special = 0; break; case 19: // Lower Floor EV_DoFloor(line, FT_LOWER); xline->special = 0; break; case 22: // Raise floor to nearest height and change texture EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); xline->special = 0; break; case 25: // Ceiling Crush and Raise EV_DoCeiling(line, CT_CRUSHANDRAISE); xline->special = 0; break; case 30: // Raise floor to shortest texture height // on either side of lines. EV_DoFloor(line, FT_RAISETOTEXTURE); xline->special = 0; break; case 35: // Lights Very Dark EV_LightTurnOn(line, 35.0f/255.0f); xline->special = 0; break; case 36: // Lower Floor (TURBO) EV_DoFloor(line, FT_LOWERTURBO); xline->special = 0; break; case 37: // LowerAndChange EV_DoFloor(line, FT_LOWERANDCHANGE); xline->special = 0; break; case 38: // Lower Floor To Lowest EV_DoFloor(line, FT_LOWERTOLOWEST); xline->special = 0; break; case 39: // TELEPORT! EV_Teleport(line, side, thing, true); xline->special = 0; break; case 40: // RaiseCeilingLowerFloor EV_DoCeiling(line, CT_RAISETOHIGHEST); EV_DoFloor(line, FT_LOWERTOLOWEST); xline->special = 0; break; case 44: // Ceiling Crush EV_DoCeiling(line, CT_LOWERANDCRUSH); xline->special = 0; break; case 52: // EXIT! G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); break; case 53: // Perpetual Platform Raise EV_DoPlat(line, PT_PERPETUALRAISE, 0); xline->special = 0; break; case 54: // Platform Stop P_PlatDeactivate(xline->tag); xline->special = 0; break; case 56: // Raise Floor Crush EV_DoFloor(line, FT_RAISEFLOORCRUSH); xline->special = 0; break; case 57: // Ceiling Crush Stop P_CeilingDeactivate(xline->tag); xline->special = 0; break; case 58: // Raise Floor 24 EV_DoFloor(line, FT_RAISE24); xline->special = 0; break; case 59: // Raise Floor 24 And Change EV_DoFloor(line, FT_RAISE24ANDCHANGE); xline->special = 0; break; case 104: // Turn lights off in sector(tag) EV_TurnTagLightsOff(line); xline->special = 0; break; /* // DJS - This stuff isn't in Heretic case 108: // Blazing Door Raise (faster than TURBO!) EV_DoDoor(line, DT_BLAZERAISE); xline->special = 0; break; case 109: // Blazing Door Open (faster than TURBO!) EV_DoDoor(line, DT_BLAZEOPEN); xline->special = 0; break; case 100: // Build Stairs Turbo 16 EV_BuildStairs(line, turbo16); xline->special = 0; break; case 110: // Blazing Door Close (faster than TURBO!) EV_DoDoor(line, DT_BLAZECLOSE); xline->special = 0; break; case 119: // Raise floor to nearest surr. floor EV_DoFloor(line, FT_RAISEFLOORTONEAREST); xline->special = 0; break; case 121: // Blazing PlatDownWaitUpStay EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0); xline->special = 0; break; */ //case 124: // DJS - In Heretic, the secret exit is 105 case 105: // Secret EXIT G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, true), 0, true); break; // DJS - Heretic has an additional stair build special // that moves in steps of 16. case 106: // Build Stairs EV_BuildStairs(line, build16); xline->special = 0; break; /* // DJS - more specials that arn't in Heretic case 125: // TELEPORT MonsterONLY if(!thing->player) { EV_Teleport(line, side, thing); xline->special = 0; } break; case 130: // Raise Floor Turbo EV_DoFloor(line, FT_RAISEFLOORTURBO); xline->special = 0; break; case 141: // Silent Ceiling Crush & Raise EV_DoCeiling(line, CT_SILENTCRUSHANDRAISE); xline->special = 0; break; */ // RETRIGGERS. All from here till end. case 72: // Ceiling Crush EV_DoCeiling(line, CT_LOWERANDCRUSH); break; case 73: // Ceiling Crush and Raise EV_DoCeiling(line, CT_CRUSHANDRAISE); break; case 74: // Ceiling Crush Stop P_CeilingDeactivate(xline->tag); break; case 75: // Close Door EV_DoDoor(line, DT_CLOSE); break; case 76: // Close Door 30 EV_DoDoor(line, DT_CLOSE30THENOPEN); break; case 77: // Fast Ceiling Crush & Raise EV_DoCeiling(line, CT_CRUSHANDRAISEFAST); break; case 79: // Lights Very Dark EV_LightTurnOn(line, 35.0f/255.0f); break; case 80: // Light Turn On - brightest near EV_LightTurnOn(line, 0); break; case 81: // Light Turn On 255 EV_LightTurnOn(line, 1); break; case 82: // Lower Floor To Lowest EV_DoFloor(line, FT_LOWERTOLOWEST); break; case 83: // Lower Floor EV_DoFloor(line, FT_LOWER); break; case 84: // LowerAndChange EV_DoFloor(line, FT_LOWERANDCHANGE); break; case 86: // Open Door EV_DoDoor(line, DT_OPEN); break; case 87: // Perpetual Platform Raise EV_DoPlat(line, PT_PERPETUALRAISE, 0); break; case 88: // PlatDownWaitUp EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0); break; case 89: // Platform Stop P_PlatDeactivate(xline->tag); break; case 90: // Raise Door EV_DoDoor(line, DT_NORMAL); break; case 91: // Raise Floor EV_DoFloor(line, FT_RAISEFLOOR); break; case 92: // Raise Floor 24 EV_DoFloor(line, FT_RAISE24); break; case 93: // Raise Floor 24 And Change EV_DoFloor(line, FT_RAISE24ANDCHANGE); break; case 94: // Raise Floor Crush EV_DoFloor(line, FT_RAISEFLOORCRUSH); break; case 95: // Raise floor to nearest height // and change texture. EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); break; case 96: // Raise floor to shortest texture height // on either side of lines. EV_DoFloor(line, FT_RAISETOTEXTURE); break; case 97: // TELEPORT! EV_Teleport(line, side, thing, true); break; case 100: // DJS - Heretic has one turbo door raise EV_DoDoor(line, DT_BLAZEOPEN); break; /* // DJS - Yet more specials not in Heretic case 98: // Lower Floor (TURBO) EV_DoFloor(line, FT_LOWERTURBO); break; case 105: // Blazing Door Raise (faster than TURBO!) EV_DoDoor(line, DT_BLAZERAISE); break; case 106: // Blazing Door Open (faster than TURBO!) EV_DoDoor(line, DT_BLAZEOPEN); break; case 107: // Blazing Door Close (faster than TURBO!) EV_DoDoor(line, DT_BLAZECLOSE); break; case 120: // Blazing PlatDownWaitUpStay. EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0); break; case 126: // TELEPORT MonsterONLY. if(!thing->player) EV_Teleport(line, side, thing); break; case 128: // Raise To Nearest Floor EV_DoFloor(line, FT_RAISEFLOORTONEAREST); break; case 129: // Raise Floor Turbo EV_DoFloor(line, FT_RAISEFLOORTURBO); break; */ } } /** * Called when a thing shoots a special line. */ static void P_ShootSpecialLine(mobj_t* thing, linedef_t* line) { xline_t* xline = P_ToXLine(line); // Impacts that other things can activate. if(!thing->player) { switch(xline->special) { case 46: // OPEN DOOR IMPACT break; default: return; } } switch(xline->special) { case 24: // RAISE FLOOR EV_DoFloor(line, FT_RAISEFLOOR); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; break; case 46: // OPEN DOOR EV_DoDoor(line, DT_OPEN); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 47: // RAISE FLOOR NEAR AND CHANGE EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; break; default: break; } } /** * Called every tic frame that the player origin is in a special sector. */ void P_PlayerInSpecialSector(player_t *player) { sector_t *sector = P_GetPtrp(player->plr->mo->subsector, DMU_SECTOR); // Falling, not all the way down yet? if(player->plr->mo->pos[VZ] != P_GetFloatp(sector, DMU_FLOOR_HEIGHT)) return; // Has hitten ground. switch(P_ToXSector(sector)->special) { case 5: // LAVA DAMAGE WEAK if(!(mapTime & 15)) { P_DamageMobj(player->plr->mo, &LavaInflictor, NULL, 5, false); P_HitFloor(player->plr->mo); } break; case 7: // SLUDGE DAMAGE if(!(mapTime & 31)) P_DamageMobj(player->plr->mo, NULL, NULL, 4, false); break; case 16: // LAVA DAMAGE HEAVY if(!(mapTime & 15)) { P_DamageMobj(player->plr->mo, &LavaInflictor, NULL, 8, false); P_HitFloor(player->plr->mo); } break; case 4: // LAVA DAMAGE WEAK PLUS SCROLL EAST P_Thrust(player, 0, FIX2FLT(2048 * 28)); if(!(mapTime & 15)) { P_DamageMobj(player->plr->mo, &LavaInflictor, NULL, 5, false); P_HitFloor(player->plr->mo); } break; case 9: // SECRET SECTOR player->secretCount++; P_ToXSector(sector)->special = 0; if(cfg.secretMsg) { P_SetMessage(player, "You've found a secret area!", false); S_ConsoleSound(SFX_SECRET, 0, player - players); } break; case 11: // EXIT SUPER DAMAGE! (for E1M8 finale) /* // DJS - Not used in Heretic player->cheats &= ~CF_GODMODE; if(!(leveltime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 20); if(player->health <= 10) G_ExitLevel(); */ break; // DJS - These specials are handled elsewhere in jHeretic. case 15: // LOW FRICTION case 40: // WIND SPECIALS case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: break; default: P_PlayerInWindSector(player); break; } } /** * Animate planes, scroll walls, etc. */ void P_UpdateSpecials(void) { #define PLANE_MATERIAL_SCROLLUNIT (8.f/35*2) uint i; float x; linedef_t* line; sidedef_t* side; // Extended lines and sectors. XG_Ticker(); // Update scrolling plane materials. for(i = 0; i < numsectors; ++i) { xsector_t* sect = P_ToXSector(P_ToPtr(DMU_SECTOR, i)); float texOff[2]; switch(sect->special) { case 25: // Scroll north. case 26: case 27: case 28: case 29: if(!cfg.fixPlaneScrollMaterialsEastOnly) break; texOff[VY] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y); texOff[VY] -= PLANE_MATERIAL_SCROLLUNIT * (1 + (sect->special - 25)*2); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y, texOff[VY]); break; case 20: // Scroll east. case 21: case 22: case 23: case 24: texOff[VX] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X); texOff[VX] -= PLANE_MATERIAL_SCROLLUNIT * (1 + (sect->special - 20)*2); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X, texOff[VX]); break; case 4: // Scroll east (lava damage). texOff[VX] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X); texOff[VX] -= PLANE_MATERIAL_SCROLLUNIT * 8 * (1 + sect->special - 4); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X, texOff[VX]); break; case 30: // Scroll south. case 31: case 32: case 33: case 34: if(!cfg.fixPlaneScrollMaterialsEastOnly) break; texOff[VY] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y); texOff[VY] += PLANE_MATERIAL_SCROLLUNIT * (1 + (sect->special - 30)*2); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y, texOff[VY]); break; case 35: // Scroll west. case 36: case 37: case 38: case 39: if(!cfg.fixPlaneScrollMaterialsEastOnly) break; texOff[VX] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X); texOff[VX] += PLANE_MATERIAL_SCROLLUNIT * (1 + (sect->special - 35)*2); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X, texOff[VX]); break; default: break; } } // ANIMATE LINE SPECIALS if(P_IterListSize(linespecials)) { P_IterListResetIterator(linespecials, false); while((line = P_IterListIterator(linespecials)) != NULL) { switch(P_ToXLine(line)->special) { case 48: side = P_GetPtrp(line, DMU_SIDEDEF0); // EFFECT FIRSTCOL SCROLL + x = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X, x + 1); x = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X, x + 1); x = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X, x + 1); break; // DJS - Heretic also has a backwards wall scroller. case 99: side = P_GetPtrp(line, DMU_SIDEDEF0); // EFFECT FIRSTCOL SCROLL + x = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X, x - 1); x = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X, x - 1); x = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X, x - 1); break; default: break; } } } #undef PLANE_MATERIAL_SCROLLUNIT } /** * After the map has been loaded, scan for specials that spawn thinkers. */ void P_SpawnSpecials(void) { uint i; linedef_t *line; xline_t *xline; iterlist_t *list; sector_t *sec; xsector_t *xsec; // Init special SECTORs. P_DestroySectorTagLists(); for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); if(xsec->tag) { list = P_GetSectorIterListForTag(xsec->tag, true); P_AddObjectToIterList(list, sec); } if(!xsec->special) continue; if(IS_CLIENT) { switch(xsec->special) { case 9: // SECRET SECTOR totalSecret++; break; default: break; } continue; } switch(xsec->special) { case 1: // FLICKERING LIGHTS P_SpawnLightFlash(sec); break; case 2: // STROBE FAST P_SpawnStrobeFlash(sec, FASTDARK, 0); break; case 3: // STROBE SLOW P_SpawnStrobeFlash(sec, SLOWDARK, 0); break; case 4: // STROBE FAST/DEATH SLIME P_SpawnStrobeFlash(sec, FASTDARK, 0); xsec->special = 4; break; case 8: // GLOWING LIGHT P_SpawnGlowingLight(sec); break; case 9: // SECRET SECTOR totalSecret++; break; case 10: // DOOR CLOSE IN 30 SECONDS P_SpawnDoorCloseIn30(sec); break; case 12: // SYNC STROBE SLOW P_SpawnStrobeFlash(sec, SLOWDARK, 1); break; case 13: // SYNC STROBE FAST P_SpawnStrobeFlash(sec, FASTDARK, 1); break; case 14: // DOOR RAISE IN 5 MINUTES P_SpawnDoorRaiseIn5Mins(sec); break; /* // DJS - Heretic doesn't use these. case 17: P_SpawnFireFlicker(sec); break; */ default: break; } } // Init animating line specials. P_EmptyIterList(linespecials); P_DestroyLineTagLists(); for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); xline = P_ToXLine(line); switch(xline->special) { case 48: // EFFECT FIRSTCOL SCROLL+ case 99: // EFFECT FIRSTCOL SCROLL- // DJS - Heretic also has a backwards wall scroller. P_AddObjectToIterList(linespecials, line); break; default: break; } if(xline->tag) { list = P_GetLineIterListForTag(xline->tag, true); P_AddObjectToIterList(list, line); } } // Init extended generalized lines and sectors. XG_Init(); } void P_InitLava(void) { memset(&LavaInflictor, 0, sizeof(mobj_t)); LavaInflictor.type = MT_PHOENIXFX2; LavaInflictor.flags2 = MF2_FIREDAMAGE | MF2_NODMGTHRUST; } /** * Handles sector specials 25 - 39. */ void P_PlayerInWindSector(player_t *player) { sector_t *sector = P_GetPtrp(player->plr->mo->subsector, DMU_SECTOR); static int pushTab[5] = { 2048 * 5, 2048 * 10, 2048 * 25, 2048 * 30, 2048 * 35 }; switch(P_ToXSector(sector)->special) { case 25: case 26: case 27: case 28: case 29: // Scroll_North P_Thrust(player, ANG90, FIX2FLT(pushTab[P_ToXSector(sector)->special - 25])); break; case 20: case 21: case 22: case 23: case 24: // Scroll_East P_Thrust(player, 0, FIX2FLT(pushTab[P_ToXSector(sector)->special - 20])); break; case 30: case 31: case 32: case 33: case 34: // Scroll_South P_Thrust(player, ANG270, FIX2FLT(pushTab[P_ToXSector(sector)->special - 30])); break; case 35: case 36: case 37: case 38: case 39: // Scroll_West P_Thrust(player, ANG180, FIX2FLT(pushTab[P_ToXSector(sector)->special - 35])); break; } // The other wind types (40..51). P_WindThrust(player->plr->mo); } void P_InitAmbientSound(void) { AmbSfxCount = 0; AmbSfxVolume = 0; AmbSfxTics = 10 * TICSPERSEC; AmbSfxPtr = AmbSndSeqInit; } /** * Called by spawnMapThing during (P_setup):P_SetupMap. */ void P_AddAmbientSfx(int sequence) { if(AmbSfxCount == MAX_AMBIENT_SFX) { Con_Error("Too many ambient sound sequences"); } LevelAmbientSfx[AmbSfxCount++] = AmbientSfx[sequence]; } /** * Called every tic by (P_tick):P_Ticker. */ void P_AmbientSound(void) { afxcmd_t cmd; int sound; boolean done; // No ambient sound sequences on current level if(!AmbSfxCount) return; if(--AmbSfxTics) return; done = false; do { cmd = *AmbSfxPtr++; switch(cmd) { case afxcmd_play: AmbSfxVolume = P_Random() >> 2; S_StartSoundAtVolume(*AmbSfxPtr++, NULL, AmbSfxVolume / 127.0f); break; case afxcmd_playabsvol: sound = *AmbSfxPtr++; AmbSfxVolume = *AmbSfxPtr++; S_StartSoundAtVolume(sound, NULL, AmbSfxVolume / 127.0f); break; case afxcmd_playrelvol: sound = *AmbSfxPtr++; AmbSfxVolume += *AmbSfxPtr++; if(AmbSfxVolume < 0) AmbSfxVolume = 0; else if(AmbSfxVolume > 127) AmbSfxVolume = 127; S_StartSoundAtVolume(sound, NULL, AmbSfxVolume / 127.0f); break; case afxcmd_delay: AmbSfxTics = *AmbSfxPtr++; done = true; break; case afxcmd_delayrand: AmbSfxTics = P_Random() & (*AmbSfxPtr++); done = true; break; case afxcmd_end: AmbSfxTics = 6 * TICSPERSEC + P_Random(); AmbSfxPtr = LevelAmbientSfx[P_Random() % AmbSfxCount]; done = true; break; default: Con_Error("P_AmbientSound: Unknown afxcmd %d", cmd); break; } } while(done == false); } boolean P_UseSpecialLine2(mobj_t* mo, linedef_t* line, int side) { xline_t *xline = P_ToXLine(line); // Switches that other things can activate. if(!mo->player) { // never DT_OPEN secret doors if(xline->flags & ML_SECRET) return false; } if(!mo->player) { switch(xline->special) { case 1: // MANUAL DOOR RAISE case 32: // MANUAL BLUE case 33: // MANUAL RED case 34: // MANUAL YELLOW break; default: return false; } } // Do something. switch(xline->special) { // MANUALS case 1: // Vertical Door case 26: // Blue Door/Locked case 27: // Yellow Door /Locked case 28: // Red Door /Locked case 31: // Manual door DT_OPEN case 32: // Blue locked door DT_OPEN case 33: // Red locked door DT_OPEN case 34: // Yellow locked door DT_OPEN EV_VerticalDoor(line, mo); break; // SWITCHES case 7: // Switch_Build_Stairs (8 pixel steps) if(EV_BuildStairs(line, build8)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 107: // Switch_Build_Stairs_16 (16 pixel steps) if(EV_BuildStairs(line, build16)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 9: // Change Donut. if(EV_DoDonut(line)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 11: // Exit level. if(cyclingMaps && mapCycleNoExit) break; G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; break; case 14: // Raise Floor 32 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 15: // Raise Floor 24 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 18: // Raise Floor to next highest floor. if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 20: // Raise Plat next highest floor and change texture. if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 21: // PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 23: // Lower Floor to Lowest. if(EV_DoFloor(line, FT_LOWERTOLOWEST)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 29: // Raise Door. if(EV_DoDoor(line, DT_NORMAL)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 41: // Lower Ceiling to Floor. if(EV_DoCeiling(line, CT_LOWERTOFLOOR)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 71: // Turbo Lower Floor. if(EV_DoFloor(line, FT_LOWERTURBO)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 49: // Lower Ceiling And Crush. if(EV_DoCeiling(line, CT_LOWERANDCRUSH)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 50: // Close Door. if(EV_DoDoor(line, DT_CLOSE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 51: // Secret EXIT. if(cyclingMaps && mapCycleNoExit) break; G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, true), 0, true); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; break; case 55: // Raise Floor Crush. if(EV_DoFloor(line, FT_RAISEFLOORCRUSH)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 101: // Raise Floor. if(EV_DoFloor(line, FT_RAISEFLOOR)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 102: // Lower Floor to Surrounding floor height. if(EV_DoFloor(line, FT_LOWER)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 103: // Open Door. if(EV_DoDoor(line, DT_OPEN)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; // BUTTONS case 42: // Close Door. if(EV_DoDoor(line, DT_CLOSE)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 43: // Lower Ceiling to Floor. if(EV_DoCeiling(line, CT_LOWERTOFLOOR)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 45: // Lower Floor to Surrounding floor height. if(EV_DoFloor(line, FT_LOWER)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 60: // Lower Floor to Lowest. if(EV_DoFloor(line, FT_LOWERTOLOWEST)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 61: // Open Door. if(EV_DoDoor(line, DT_OPEN)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 62: // PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 1)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 63: // Raise Door. if(EV_DoDoor(line, DT_NORMAL)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 64: // Raise Floor to ceiling. if(EV_DoFloor(line, FT_RAISEFLOOR)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 66: // Raise Floor 24 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 67: // Raise Floor 32 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 65: // Raise Floor Crush. if(EV_DoFloor(line, FT_RAISEFLOORCRUSH)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 68: // Raise Plat to next highest floor and change texture. if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 69: // Raise Floor to next highest floor. if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 70: // Turbo Lower Floor. if(EV_DoFloor(line, FT_LOWERTURBO)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; default: break; } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/in_lude.c0000644000175000017500000006036411357170242022726 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * in_lude.c: Intermission/stat screens. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "hu_stuff.h" #include "d_net.h" #include "am_map.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ #define NUMTEAMS (4) // Four colors, four teams. // TYPES ------------------------------------------------------------------- typedef enum gametype_e { SINGLE, COOPERATIVE, DEATHMATCH } gametype_t; typedef struct teaminfo_s { int members; int frags[NUMTEAMS]; int totalFrags; } teaminfo_t; typedef struct yahpt_s { int x, y; } yahpt_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- void IN_DrawOldLevel(void); void IN_DrawYAH(void); void IN_DrawStatBack(void); void IN_DrawSingleStats(void); void IN_DrawCoopStats(void); void IN_DrawDMStats(void); void IN_DrawNumber(int val, int x, int y, int digits, float r, float g, float b, float a); void IN_DrawTime(int x, int y, int h, int m, int s, float r, float g, float b, float a); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean intermission; int interState = 0; int interTime = -1; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Used for timing of background animation. static int bcnt; // Contains information passed into intermission. static wbstartstruct_t *wbs; static boolean skipIntermission; static int oldInterTime = 0; static gametype_t gameType; static int cnt; static int time; static int hours; static int minutes; static int seconds; static int slaughterBoy; // In DM, the player with the most kills. static int killPercent[NUMTEAMS]; static int bonusPercent[NUMTEAMS]; static int secretPercent[NUMTEAMS]; static int playerTeam[MAXPLAYERS]; static teaminfo_t teamInfo[NUMTEAMS]; static int interPic, beenThere, goingThere; static int patchFaceOkayBase; static int patchFaceDeadBase; static fixed_t dSlideX[NUMTEAMS]; static fixed_t dSlideY[NUMTEAMS]; static char *killersText[] = { "K", "I", "L", "L", "E", "R", "S" }; static yahpt_t YAHspot[3][9] = { { {172, 78}, {86, 90}, {73, 66}, {159, 95}, {148, 126}, {132, 54}, {131, 74}, {208, 138}, {52, 101} }, { {218, 57}, {137, 81}, {155, 124}, {171, 68}, {250, 86}, {136, 98}, {203, 90}, {220, 140}, {279, 106} }, { {86, 99}, {124, 103}, {154, 79}, {202, 83}, {178, 59}, {142, 58}, {219, 66}, {247, 57}, {107, 80} } }; // CODE -------------------------------------------------------------------- void WI_initVariables(wbstartstruct_t * wbstartstruct) { wbs = wbstartstruct; /*#ifdef RANGECHECK if(gameMode != commercial) { if(gameMode == retail) RNGCHECK(wbs->epsd, 0, 3); else RNGCHECK(wbs->epsd, 0, 2); } else { RNGCHECK(wbs->last, 0, 8); RNGCHECK(wbs->next, 0, 8); } RNGCHECK(wbs->pnum, 0, MAXPLAYERS); RNGCHECK(wbs->pnum, 0, MAXPLAYERS); #endif accelerateStage = 0; cnt =*/ bcnt = 0; /* firstRefresh = 1; me = wbs->pNum; myTeam = cfg.playerColor[wbs->pNum]; plrs = wbs->plyr; if(!wbs->maxKills) wbs->maxKills = 1; if(!wbs->maxItems) wbs->maxItems = 1; if(!wbs->maxSecret) wbs->maxSecret = 1; if(gameMode != retail) if(wbs->epsd > 2) wbs->epsd -= 3;*/ intermission = true; interState = -1; skipIntermission = false; interTime = 0; oldInterTime = 0; } void IN_Init(wbstartstruct_t * wbstartstruct) { WI_initVariables(wbstartstruct); IN_LoadPics(); IN_InitStats(); } void IN_WaitStop(void) { if(!--cnt) { IN_Stop(); G_WorldDone(); } } void IN_Stop(void) { NetSv_Intermission(IMF_END, 0, 0); intermission = false; IN_UnloadPics(); } /** * Initializes the stats for single player mode */ void IN_InitStats(void) { signed int slaughterfrags; int i, j; int posNum; int slaughterCount; int teamCount, team; // Init team info. if(IS_NETGAME) { memset(teamInfo, 0, sizeof(teamInfo)); memset(playerTeam, 0, sizeof(playerTeam)); for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; playerTeam[i] = cfg.playerColor[i]; teamInfo[playerTeam[i]].members++; } } time = mapTime / 35; hours = time / 3600; time -= hours * 3600; minutes = time / 60; time -= minutes * 60; seconds = time; if(!IS_NETGAME) { gameType = SINGLE; } else if( /*IS_NETGAME && */ !deathmatch) { gameType = COOPERATIVE; memset(killPercent, 0, sizeof(killPercent)); memset(bonusPercent, 0, sizeof(bonusPercent)); memset(secretPercent, 0, sizeof(secretPercent)); for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { if(totalKills) { j = players[i].killCount * 100 / totalKills; if(j > killPercent[playerTeam[i]]) killPercent[playerTeam[i]] = j; } if(totalItems) { j = players[i].itemCount * 100 / totalItems; if(j > bonusPercent[playerTeam[i]]) bonusPercent[playerTeam[i]] = j; } if(totalSecret) { j = players[i].secretCount * 100 / totalSecret; if(j > secretPercent[playerTeam[i]]) secretPercent[playerTeam[i]] = j; } } } } else { gameType = DEATHMATCH; slaughterBoy = 0; slaughterfrags = -9999; posNum = 0; teamCount = 0; slaughterCount = 0; for(i = 0; i < MAXPLAYERS; ++i) { team = playerTeam[i]; if(players[i].plr->inGame) { for(j = 0; j < MAXPLAYERS; ++j) { if(players[j].plr->inGame) { teamInfo[team].frags[playerTeam[j]] += players[i].frags[j]; teamInfo[team].totalFrags += players[i].frags[j]; } } // Find out the largest number of frags. if(teamInfo[team].totalFrags > slaughterfrags) slaughterfrags = teamInfo[team].totalFrags; } } for(i = 0; i < NUMTEAMS; ++i) { //posNum++; /*if(teamInfo[i].totalFrags > slaughterfrags) { slaughterBoy = 1<episode) { case 0: interPic = W_GetNumForName("MAPE1"); break; case 1: interPic = W_GetNumForName("MAPE2"); break; case 2: interPic = W_GetNumForName("MAPE3"); break; default: break; } beenThere = W_GetNumForName("IN_X"); goingThere = W_GetNumForName("IN_YAH"); patchFaceOkayBase = W_GetNumForName("FACEA0"); patchFaceDeadBase = W_GetNumForName("FACEB0"); } void IN_UnloadPics(void) { /* Nothing to do...*/ } void IN_Ticker(void) { if(!intermission) { return; } if(!IS_CLIENT) { if(interState == 3) { IN_WaitStop(); return; } IN_CheckForSkip(); } // Counter for general background animation. bcnt++; interTime++; if(oldInterTime < interTime) { interState++; if(wbs->episode > 2 && interState >= 1) { // Extended Wad levels: skip directly to the next level interState = 3; } switch(interState) { case 0: oldInterTime = interTime + 300; if(wbs->episode > 2) { oldInterTime = interTime + 1200; } break; case 1: oldInterTime = interTime + 200; break; case 2: oldInterTime = MAXINT; break; case 3: cnt = 10; break; default: break; } } if(skipIntermission) { if(interState == 0 && interTime < 150) { interTime = 150; skipIntermission = false; NetSv_Intermission(IMF_TIME, 0, interTime); return; } else if(interState < 2 && wbs->episode < 3) { interState = 2; skipIntermission = false; S_StartSound(SFX_DORCLS, NULL); NetSv_Intermission(IMF_STATE, interState, 0); return; } interState = 3; cnt = 10; skipIntermission = false; S_StartSound(SFX_DORCLS, NULL); NetSv_Intermission(IMF_STATE, interState, 0); } } /** * Check to see if any player hit a key. */ void IN_CheckForSkip(void) { int i; player_t *player; if(IS_CLIENT) return; for(i = 0, player = players; i < MAXPLAYERS; ++i, player++) { if(players->plr->inGame) { if(player->brain.attack) { if(!player->attackDown) { skipIntermission = 1; } player->attackDown = true; } else { player->attackDown = false; } if(player->brain.use) { if(!player->useDown) { skipIntermission = 1; } player->useDown = true; } else { player->useDown = false; } } } } void IN_Drawer(void) { static int oldInterState; if(!intermission || interState > 3) { return; } if(interState == 3) { return; } if(oldInterState != 2 && interState == 2) { S_LocalSound(SFX_PSTOP, NULL); } if(interState != -1) oldInterState = interState; switch(interState) { case -1: case 0: // Draw stats. IN_DrawStatBack(); switch(gameType) { case SINGLE: IN_DrawSingleStats(); break; case COOPERATIVE: IN_DrawCoopStats(); break; case DEATHMATCH: IN_DrawDMStats(); break; } break; case 1: // Leaving old level. if(wbs->episode < 3) { GL_DrawPatch(0, 0, interPic); IN_DrawOldLevel(); } break; case 2: // Going to the next level. if(wbs->episode < 3) { GL_DrawPatch(0, 0, interPic); IN_DrawYAH(); } break; case 3: // Waiting before going to the next level. if(wbs->episode < 3) { GL_DrawPatch(0, 0, interPic); } break; default: Con_Error("IN_lude: Intermission state out of range.\n"); break; } } void IN_DrawStatBack(void) { DGL_Color4f(1, 1, 1, 1); DGL_SetMaterial(P_ToPtr(DMU_MATERIAL, P_MaterialNumForName("FLOOR16", MN_FLATS))); DGL_DrawRectTiled(0, 0, SCREENWIDTH, SCREENHEIGHT, 64, 64); } void IN_DrawOldLevel(void) { int x; const char* levelname; levelname = P_GetShortMapName(wbs->episode, wbs->currentMap); x = 160 - M_StringWidth(levelname, GF_FONTB) / 2; M_WriteText2(x, 3, levelname, GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); x = 160 - M_StringWidth("FINISHED", GF_FONTA) / 2; M_WriteText2(x, 25, "FINISHED", GF_FONTA, defFontRGB2[0], defFontRGB2[1],defFontRGB2[2], 1); if(wbs->currentMap == 8) { uint i; for(i = 0; i < wbs->nextMap; ++i) { GL_DrawPatch(YAHspot[wbs->episode][i].x, YAHspot[wbs->episode][i].y, beenThere); } if(!(interTime & 16)) { GL_DrawPatch(YAHspot[wbs->episode][8].x, YAHspot[wbs->episode][8].y, beenThere); } } else { uint i; for(i = 0; i < wbs->currentMap; ++i) { GL_DrawPatch(YAHspot[wbs->episode][i].x, YAHspot[wbs->episode][i].y, beenThere); } if(players[CONSOLEPLAYER].didSecret) { GL_DrawPatch(YAHspot[wbs->episode][8].x, YAHspot[wbs->episode][8].y, beenThere); } if(!(interTime & 16)) { GL_DrawPatch(YAHspot[wbs->episode][wbs->currentMap].x, YAHspot[wbs->episode][wbs->currentMap].y, beenThere); } } } void IN_DrawYAH(void) { uint i; int x; const char* levelname; levelname = P_GetShortMapName(wbs->episode, wbs->nextMap); x = 160 - M_StringWidth("NOW ENTERING:", GF_FONTA) / 2; M_WriteText2(x, 10, "NOW ENTERING:", GF_FONTA, defFontRGB2[0], defFontRGB2[1], defFontRGB2[2], 1); x = 160 - M_StringWidth(levelname, GF_FONTB) / 2; M_WriteText2(x, 20, levelname, GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); for(i = 0; i < wbs->nextMap; ++i) { GL_DrawPatch(YAHspot[wbs->episode][i].x, YAHspot[wbs->episode][i].y, beenThere); } if(players[CONSOLEPLAYER].didSecret) { GL_DrawPatch(YAHspot[wbs->episode][8].x, YAHspot[wbs->episode][8].y, beenThere); } if(!(interTime & 16) || interState == 3) { // Draw the destination 'X' GL_DrawPatch(YAHspot[wbs->episode][wbs->nextMap].x, YAHspot[wbs->episode][wbs->nextMap].y, goingThere); } } void IN_DrawSingleStats(void) { static int sounds; int x; const char* levelname; levelname = P_GetShortMapName(wbs->episode, wbs->currentMap); M_WriteText2(50, 65, "KILLS", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); M_WriteText2(50, 90, "ITEMS", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); M_WriteText2(50, 115, "SECRETS", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); x = 160 - M_StringWidth(levelname, GF_FONTB) / 2; M_WriteText2(x, 3, levelname, GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); x = 160 - M_StringWidth("FINISHED", GF_FONTA) / 2; M_WriteText2(x, 25, "FINISHED", GF_FONTA, defFontRGB2[0], defFontRGB2[1], defFontRGB2[2], 1); if(interTime < 30) { sounds = 0; return; } if(sounds < 1 && interTime >= 30) { S_LocalSound(SFX_DORCLS, NULL); sounds++; } IN_DrawNumber(players[CONSOLEPLAYER].killCount, 200, 65, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); IN_DrawShadowChar(236, 65, '/', GF_FONTB); IN_DrawNumber(totalKills, 248, 65, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); if(interTime < 60) return; if(sounds < 2 && interTime >= 60) { S_LocalSound(SFX_DORCLS, NULL); sounds++; } IN_DrawNumber(players[CONSOLEPLAYER].itemCount, 200, 90, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); IN_DrawShadowChar(236, 90, '/', GF_FONTB); IN_DrawNumber(totalItems, 248, 90, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); if(interTime < 90) return; if(sounds < 3 && interTime >= 90) { S_LocalSound(SFX_DORCLS, NULL); sounds++; } IN_DrawNumber(players[CONSOLEPLAYER].secretCount, 200, 115, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); IN_DrawShadowChar(236, 115, '/', GF_FONTB); IN_DrawNumber(totalSecret, 248, 115, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); if(interTime < 150) { return; } if(sounds < 4 && interTime >= 150) { S_LocalSound(SFX_DORCLS, NULL); sounds++; } if(gameMode != extended || wbs->episode < 3) { M_WriteText2(85, 160, "TIME", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); IN_DrawTime(155, 160, hours, minutes, seconds, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); } else { x = 160 - M_StringWidth("NOW ENTERING:", GF_FONTA) / 2; M_WriteText2(x, 160, "NOW ENTERING:", GF_FONTA, defFontRGB2[0], defFontRGB2[1], defFontRGB2[2], 1); levelname = P_GetShortMapName(wbs->episode, wbs->nextMap); x = 160 - M_StringWidth(levelname, GF_FONTB) / 2; M_WriteText2(x, 170, levelname, GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); skipIntermission = false; } } void IN_DrawCoopStats(void) { static int sounds; int i, x, ypos; const char* levelname; levelname = P_GetShortMapName(wbs->episode, wbs->currentMap); M_WriteText2(95, 35, "KILLS", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); M_WriteText2(155, 35, "BONUS", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); M_WriteText2(232, 35, "SECRET", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); x = 160 - M_StringWidth(levelname, GF_FONTB) / 2; M_WriteText2(x, 3, levelname, GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); x = 160 - M_StringWidth("FINISHED", GF_FONTA) / 2; M_WriteText2(x, 25, "FINISHED", GF_FONTA, defFontRGB2[0], defFontRGB2[1], defFontRGB2[2], 1); ypos = 50; for(i = 0; i < NUMTEAMS; ++i) { if(teamInfo[i].members) { GL_DrawPatchLitAlpha(27, ypos+2, 0, .4f, patchFaceOkayBase + i); DGL_Color4f(defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); GL_DrawPatch_CS(25, ypos, patchFaceOkayBase + i); if(interTime < 40) { sounds = 0; ypos += 37; continue; } else if(interTime >= 40 && sounds < 1) { S_LocalSound(SFX_DORCLS, NULL); sounds++; } IN_DrawNumber(killPercent[i], 85, ypos + 10, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); IN_DrawShadowChar(121, ypos + 10, '%', GF_FONTB); IN_DrawNumber(bonusPercent[i], 160, ypos + 10, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); IN_DrawShadowChar(196, ypos + 10, '%', GF_FONTB); IN_DrawNumber(secretPercent[i], 237, ypos + 10, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); IN_DrawShadowChar(273, ypos + 10, '%', GF_FONTB); ypos += 37; } } } void IN_DrawDMStats(void) { static int sounds; int i, j; int ypos, xpos, kpos; xpos = 90; ypos = 55; M_WriteText2(265, 30, "TOTAL", GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); M_WriteText2(140, 8, "VICTIMS", GF_FONTA, defFontRGB2[0], defFontRGB2[1], defFontRGB2[2], 1); for(i = 0; i < 7; ++i) { M_WriteText2(10, 80 + 9 * i, killersText[i], GF_FONTA, defFontRGB2[0], defFontRGB2[1], defFontRGB2[2], 1); } if(interTime < 20) { for(i = 0; i < NUMTEAMS; ++i) { if(teamInfo[i].members) { GL_DrawShadowedPatch(40, ((ypos << FRACBITS) + dSlideY[i] * interTime) >> FRACBITS, patchFaceOkayBase + i); GL_DrawShadowedPatch(((xpos << FRACBITS) + dSlideX[i] * interTime) >> FRACBITS, 18, patchFaceDeadBase + i); } } sounds = 0; return; } if(interTime >= 20 && sounds < 1) { S_LocalSound(SFX_DORCLS, NULL); sounds++; } if(interTime >= 100 && slaughterBoy && sounds < 2) { S_LocalSound(SFX_WPNUP, NULL); sounds++; } for(i = 0; i < NUMTEAMS; ++i) { if(teamInfo[i].members) { if(interTime < 100 || i == playerTeam[CONSOLEPLAYER]) { GL_DrawShadowedPatch(40, ypos, patchFaceOkayBase + i); GL_DrawShadowedPatch(xpos, 18, patchFaceDeadBase + i); } else { GL_DrawFuzzPatch(40, ypos, patchFaceOkayBase + i); GL_DrawFuzzPatch(xpos, 18, patchFaceDeadBase + i); } kpos = 86; for(j = 0; j < NUMTEAMS; ++j) { if(teamInfo[j].members) { IN_DrawNumber(teamInfo[i].frags[j], kpos, ypos + 10, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); kpos += 43; } } if(slaughterBoy & (1 << i)) { if(!(interTime & 16)) { IN_DrawNumber(teamInfo[i].totalFrags, 263, ypos + 10, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); } } else { IN_DrawNumber(teamInfo[i].totalFrags, 263, ypos + 10, 3, defFontRGB[0], defFontRGB[1], defFontRGB[2], 1); } ypos += 36; xpos += 43; } } } void IN_DrawTime(int x, int y, int h, int m, int s, float r, float g, float b, float a) { if(h) { IN_DrawNumber(h, x, y, 2, r, g, b, a); M_WriteText2(x + 26, y, ":", GF_FONTB, r, g, b, a); } x += 34; if(m || h) { IN_DrawNumber(m, x, y, 2, r, g, b, a); } x += 34; M_WriteText2(x-8, y, ":", GF_FONTB, r, g, b, a); IN_DrawNumber(s, x, y, 2, r, g, b, a); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_telept.c0000644000175000017500000001746011357170242023122 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.c: */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_map.h" #include "p_mapspec.h" #include "p_terraintype.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle) { return P_SpawnMobj3f(MT_TFOG, x, y, TELEFOGHEIGHT, angle, MSF_Z_FLOOR); } boolean P_Teleport(mobj_t* thing, float x, float y, angle_t angle, boolean spawnFog) { float oldpos[3]; float aboveFloor; float fogDelta; player_t* player; uint an; angle_t oldAngle; mobj_t* fog; memcpy(oldpos, thing->pos, sizeof(oldpos)); aboveFloor = thing->pos[VZ] - thing->floorZ; oldAngle = thing->angle; if(!P_TeleportMove(thing, x, y, false)) { return false; } if(thing->player) { player = thing->player; if(player->powers[PT_FLIGHT] && aboveFloor > 0) { thing->pos[VZ] = thing->floorZ + aboveFloor; if(thing->pos[VZ] + thing->height > thing->ceilingZ) { thing->pos[VZ] = thing->ceilingZ - thing->height; } player->viewZ = thing->pos[VZ] + player->viewHeight; } else { thing->pos[VZ] = thing->floorZ; player->viewHeight = (float) cfg.plrViewHeight; player->viewHeightDelta = 0; player->viewZ = thing->pos[VZ] + player->viewHeight; //player->plr->clLookDir = 0; /* $unifiedangles */ player->plr->lookDir = 0; } //player->plr->clAngle = angle; /* $unifiedangles */ player->plr->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; } else if(thing->flags & MF_MISSILE) { thing->pos[VZ] = thing->floorZ + aboveFloor; if(thing->pos[VZ] + thing->height > thing->ceilingZ) { thing->pos[VZ] = thing->ceilingZ - thing->height; } } else { thing->pos[VZ] = thing->floorZ; } if(spawnFog) { // Spawn teleport fog at source and destination fogDelta = ((thing->flags & MF_MISSILE)? 0 : TELEFOGHEIGHT); if((fog = P_SpawnMobj3f(MT_TFOG, oldpos[VX], oldpos[VY], oldpos[VZ] + fogDelta, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); an = angle >> ANGLETOFINESHIFT; if((fog = P_SpawnMobj3f(MT_TFOG, x + 20 * FIX2FLT(finecosine[an]), y + 20 * FIX2FLT(finesine[an]), thing->pos[VZ] + fogDelta, angle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); } if(thing->player && !thing->player->powers[PT_WEAPONLEVEL2]) { // Freeze player for about .5 sec. thing->reactionTime = 18; } thing->angle = angle; if(thing->flags2 & MF2_FLOORCLIP) { thing->floorClip = 0; if(thing->pos[VZ] == P_GetFloatp(thing->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(thing); if(tt->flags & TTF_FLOORCLIP) { thing->floorClip = 10; } } } if(thing->flags & MF_MISSILE) { an = angle >> ANGLETOFINESHIFT; thing->mom[MX] = thing->info->speed * FIX2FLT(finecosine[angle]); thing->mom[MY] = thing->info->speed * FIX2FLT(finesine[angle]); } else { thing->mom[MX] = thing->mom[MY] = thing->mom[MZ] = 0; } P_MobjClearSRVO(thing); return true; } typedef struct { sector_t* sec; mobjtype_t type; mobj_t* foundMobj; } findmobjparams_t; static boolean findMobj(thinker_t* th, void* context) { findmobjparams_t* params = (findmobjparams_t*) context; mobj_t* mo = (mobj_t *) th; // Must be of the correct type? if(params->type >= 0 && params->type != mo->type) return true; // Continue iteration. // Must be in the specified sector? if(params->sec && params->sec != P_GetPtrp(mo->subsector, DMU_SECTOR)) return true; // Continue iteration. // Found it! params->foundMobj = mo; return false; // Stop iteration. } static mobj_t* getTeleportDestination(short tag) { iterlist_t* list; list = P_GetSectorIterListForTag(tag, false); if(list) { sector_t* sec = NULL; findmobjparams_t params; params.type = MT_TELEPORTMAN; params.foundMobj = NULL; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { params.sec = sec; if(!DD_IterateThinkers(P_MobjThinker, findMobj, ¶ms)) { // Found one! return params.foundMobj; } } } return NULL; } boolean EV_Teleport(linedef_t* line, int side, mobj_t* mo, boolean spawnFog) { mobj_t* dest; if(mo->flags2 & MF2_NOTELEPORT) return false; // Don't teleport if hit back of line, so you can get out of teleporter. if(side == 1) return false; if((dest = getTeleportDestination(P_ToXLine(line)->tag)) != NULL) { return P_Teleport(mo, dest->pos[VX], dest->pos[VY], dest->angle, spawnFog); } return false; } #if __JHERETIC__ || __JHEXEN__ void P_ArtiTele(player_t* player) { const playerstart_t* start; // Get a random deathmatch start. if((start = P_GetPlayerStart(0, deathmatch? -1 : 0, deathmatch))) { P_Teleport(player->plr->mo, start->pos[VX], start->pos[VY], start->angle, true); #if __JHEXEN__ if(player->morphTics) { // Teleporting away will undo any morph effects (pig) P_UndoPlayerMorph(player); } //S_StartSound(NULL, SFX_WPNUP); // Full volume laugh #else /*S_StartSound(SFX_WPNUP, NULL); // Full volume laugh NetSv_Sound(NULL, SFX_WPNUP, player-players); */ S_StartSound(SFX_WPNUP, NULL); #endif } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_lights.c0000644000175000017500000002025511357170242023113 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.c: Per-sector lighting effects - jHeretic specific. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_mapspec.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Broken light flashing. */ void T_LightFlash(lightflash_t *flash) { float lightlevel = P_GetFloatp(flash->sector, DMU_LIGHT_LEVEL); if(--flash->count) return; if(lightlevel == flash->maxLight) { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->minLight); flash->count = (P_Random() & flash->minTime) + 1; } else { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->maxLight); flash->count = (P_Random() & flash->maxTime) + 1; } } /** * After the map has been loaded, scan each sector for specials that spawn * thinkers. */ void P_SpawnLightFlash(sector_t *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; lightflash_t *flash; // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; flash = Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = T_LightFlash; DD_ThinkerAdd(&flash->thinker); flash->sector = sector; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; flash->maxTime = 64; flash->minTime = 7; flash->count = (P_Random() & flash->maxTime) + 1; } /** * Strobe light flashing. */ void T_StrobeFlash(strobe_t *flash) { float lightLevel; if(--flash->count) return; lightLevel = P_GetFloatp(flash->sector, DMU_LIGHT_LEVEL); if(lightLevel == flash->minLight) { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->maxLight); flash->count = flash->brightTime; } else { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->minLight); flash->count = flash->darkTime; } } /** * After the map has been loaded, scan each sector for specials that spawn * thinkers. */ void P_SpawnStrobeFlash(sector_t *sector, int fastOrSlow, int inSync) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; strobe_t *flash; flash = Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = T_StrobeFlash; DD_ThinkerAdd(&flash->thinker); flash->sector = sector; flash->darkTime = fastOrSlow; flash->brightTime = STROBEBRIGHT; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; if(flash->minLight == flash->maxLight) flash->minLight = 0; // nothing special about it during gameplay P_ToXSector(sector)->special = 0; if(!inSync) flash->count = (P_Random() & 7) + 1; else flash->count = 1; } /** * Start strobing lights (usually from a trigger). */ void EV_StartLightStrobing(linedef_t *line) { sector_t *sec = NULL; iterlist_t *list; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(P_ToXSector(sec)->specialData) continue; P_SpawnStrobeFlash(sec, SLOWDARK, 0); } } void EV_TurnTagLightsOff(linedef_t *line) { sector_t *sec = NULL; iterlist_t *list; float lightLevel; float otherLevel; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { lightLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); otherLevel = DDMAXFLOAT; P_FindSectorSurroundingLowestLight(sec, &otherLevel); if(otherLevel < lightLevel) lightLevel = otherLevel; P_SetFloatp(sec, DMU_LIGHT_LEVEL, lightLevel); } } void EV_LightTurnOn(linedef_t *line, float max) { sector_t *sec = NULL; iterlist_t *list; float lightLevel, otherLevel; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; if(max != 0) lightLevel = max; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { // If Max = 0 means to search for the highest light level in the // surrounding sector. if(max == 0) { lightLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); otherLevel = DDMINFLOAT; P_FindSectorSurroundingHighestLight(sec, &otherLevel); if(otherLevel > lightLevel) lightLevel = otherLevel; } P_SetFloatp(sec, DMU_LIGHT_LEVEL, lightLevel); } } void T_Glow(glow_t * g) { float lightlevel = P_GetFloatp(g->sector, DMU_LIGHT_LEVEL); float glowdelta = (1.0f / 255.0f) * (float) GLOWSPEED; switch(g->direction) { case -1: // Down. lightlevel -= glowdelta; if(lightlevel <= g->minLight) { lightlevel += glowdelta; g->direction = 1; } break; case 1: // Up. lightlevel += glowdelta; if(lightlevel >= g->maxLight) { lightlevel -= glowdelta; g->direction = -1; } break; } P_SetFloatp(g->sector, DMU_LIGHT_LEVEL, lightlevel); } void P_SpawnGlowingLight(sector_t *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; glow_t *g; g = Z_Calloc(sizeof(*g), PU_MAP, 0); g->thinker.function = T_Glow; DD_ThinkerAdd(&g->thinker); g->sector = sector; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) g->minLight = otherLevel; else g->minLight = lightLevel; g->maxLight = lightLevel; g->direction = -1; P_ToXSector(sector)->special = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_oldsvg.c0000644000175000017500000006506311357170242023125 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_oldsvg.c: * * \bug Not 64bit clean: In function 'P_v13_UnArchivePlayers': cast from pointer to integer of different size * \bug Not 64bit clean: In function 'P_v13_UnArchiveThinkers': cast from pointer to integer of different size */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "dmu_lib.h" #include "p_saveg.h" #include "p_map.h" #include "p_mapsetup.h" #include "p_tick.h" #include "p_ceiling.h" #include "p_door.h" #include "p_plat.h" #include "p_floor.h" #include "am_map.h" #include "p_inventory.h" #include "hu_inventory.h" // MACROS ------------------------------------------------------------------ // Do NOT change this: #define SAVE_VERSION 130 #define VERSIONSIZE 16 #define SAVE_GAME_TERMINATOR 0x1d #define V13_SAVESTRINGSIZE 24 #define FF_FRAMEMASK 0x7fff #define SIZEOF_V13_THINKER_T 12 #define V13_THINKER_T_FUNC_OFFSET 8 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern void SV_UpdateReadMobjFlags(mobj_t *mo, int ver); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- byte *savebuffer; byte *save_p; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static long SV_v13_ReadLong(void) { save_p += 4; return *(int *) (save_p - 4); } static short SV_v13_ReadShort(void) { save_p += 2; return *(short *) (save_p - 2); } static void SV_v13_Read(void* data, int len) { if(data) memcpy(data, save_p, len); save_p += len; } static void SV_v13_ReadPlayer(player_t* pl) { int i, plrnum = pl - players; byte temp[12]; ddplayer_t* ddpl = pl->plr; SV_v13_ReadLong(); // mo pl->playerState = SV_v13_ReadLong(); SV_v13_Read(temp, 10); // ticcmd_t pl->viewZ = FIX2FLT(SV_v13_ReadLong()); pl->viewHeight = FIX2FLT(SV_v13_ReadLong()); pl->viewHeightDelta = FIX2FLT(SV_v13_ReadLong()); pl->bob = FIX2FLT(SV_v13_ReadLong()); pl->flyHeight = SV_v13_ReadLong(); ddpl->lookDir = SV_v13_ReadLong(); pl->centering = SV_v13_ReadLong(); pl->health = SV_v13_ReadLong(); pl->armorPoints = SV_v13_ReadLong(); pl->armorType = SV_v13_ReadLong(); P_InventoryEmpty(plrnum); for(i = 0; i < 14; ++i) { inventoryitemtype_t type = SV_v13_ReadLong(); int j, count = SV_v13_ReadLong(); for(j = 0; j < count; ++j) P_InventoryGive(plrnum, type, true); } P_InventorySetReadyItem(plrnum, (inventoryitemtype_t) SV_v13_ReadLong()); Hu_InventorySelect(plrnum, P_InventoryReadyItem(plrnum)); SV_v13_ReadLong(); // current inventory item count? /*pl->inventorySlotNum =*/ SV_v13_ReadLong(); memset(pl->powers, 0, sizeof(pl->powers)); pl->powers[PT_INVULNERABILITY] = (SV_v13_ReadLong()? true : false); pl->powers[PT_INVISIBILITY] = (SV_v13_ReadLong()? true : false); pl->powers[PT_ALLMAP] = (SV_v13_ReadLong()? true : false); if(pl->powers[PT_ALLMAP]) AM_RevealMap(AM_MapForPlayer(pl - players), true); pl->powers[PT_INFRARED] = (SV_v13_ReadLong()? true : false); pl->powers[PT_WEAPONLEVEL2] = (SV_v13_ReadLong()? true : false); pl->powers[PT_FLIGHT] = (SV_v13_ReadLong()? true : false); pl->powers[PT_SHIELD] = (SV_v13_ReadLong()? true : false); pl->powers[PT_HEALTH2] = (SV_v13_ReadLong()? true : false); memset(pl->keys, 0, sizeof(pl->keys)); pl->keys[KT_YELLOW] = (SV_v13_ReadLong()? true : false); pl->keys[KT_GREEN] = (SV_v13_ReadLong()? true : false); pl->keys[KT_BLUE] = (SV_v13_ReadLong()? true : false); pl->backpack = SV_v13_ReadLong(); memset(pl->frags, 0, sizeof(pl->frags)); pl->frags[0] = SV_v13_ReadLong(); pl->frags[1] = SV_v13_ReadLong(); pl->frags[2] = SV_v13_ReadLong(); pl->frags[3] = SV_v13_ReadLong(); pl->readyWeapon = SV_v13_ReadLong(); pl->pendingWeapon = SV_v13_ReadLong(); // Owned weapons. memset(pl->weapons, 0, sizeof(pl->weapons)); pl->weapons[WT_FIRST].owned = (SV_v13_ReadLong()? true : false); pl->weapons[WT_SECOND].owned = (SV_v13_ReadLong()? true : false); pl->weapons[WT_THIRD].owned = (SV_v13_ReadLong()? true : false); pl->weapons[WT_FOURTH].owned = (SV_v13_ReadLong()? true : false); pl->weapons[WT_FIFTH].owned = (SV_v13_ReadLong()? true : false); pl->weapons[WT_SIXTH].owned = (SV_v13_ReadLong()? true : false); pl->weapons[WT_SEVENTH].owned = (SV_v13_ReadLong()? true : false); pl->weapons[WT_EIGHTH].owned = (SV_v13_ReadLong()? true : false); memset(pl->ammo, 0, sizeof(pl->ammo)); pl->ammo[AT_CRYSTAL].owned = SV_v13_ReadLong(); pl->ammo[AT_ARROW].owned = SV_v13_ReadLong(); pl->ammo[AT_ORB].owned = SV_v13_ReadLong(); pl->ammo[AT_RUNE].owned = SV_v13_ReadLong(); pl->ammo[AT_FIREORB].owned = SV_v13_ReadLong(); pl->ammo[AT_MSPHERE].owned = SV_v13_ReadLong(); pl->ammo[AT_CRYSTAL].max = SV_v13_ReadLong(); pl->ammo[AT_ARROW].max = SV_v13_ReadLong(); pl->ammo[AT_ORB].max = SV_v13_ReadLong(); pl->ammo[AT_RUNE].max = SV_v13_ReadLong(); pl->ammo[AT_FIREORB].max = SV_v13_ReadLong(); pl->ammo[AT_MSPHERE].max = SV_v13_ReadLong(); pl->attackDown = SV_v13_ReadLong(); pl->useDown = SV_v13_ReadLong(); pl->cheats = SV_v13_ReadLong(); pl->refire = SV_v13_ReadLong(); pl->killCount = SV_v13_ReadLong(); pl->itemCount = SV_v13_ReadLong(); pl->secretCount = SV_v13_ReadLong(); SV_v13_ReadLong(); // message, char* pl->damageCount = SV_v13_ReadLong(); pl->bonusCount = SV_v13_ReadLong(); pl->flameCount = SV_v13_ReadLong(); SV_v13_ReadLong(); // attacker ddpl->extraLight = SV_v13_ReadLong(); ddpl->fixedColorMap = SV_v13_ReadLong(); pl->colorMap = SV_v13_ReadLong(); for(i = 0; i < 2; ++i) { pspdef_t *psp = &pl->pSprites[i]; psp->state = (state_t*) SV_v13_ReadLong(); psp->pos[VX] = SV_v13_ReadLong(); psp->pos[VY] = SV_v13_ReadLong(); psp->tics = SV_v13_ReadLong(); } pl->didSecret = SV_v13_ReadLong(); pl->morphTics = SV_v13_ReadLong(); pl->chickenPeck = SV_v13_ReadLong(); SV_v13_ReadLong(); // rain1 SV_v13_ReadLong(); // rain2 } static void SV_v13_ReadMobj(void) { angle_t angle; spritenum_t sprite; int frame, valid, type, ddflags = 0; float pos[3], mom[3], floorz, ceilingz, radius, height; mobj_t *mo; mobjinfo_t* info; // The thinker was 3 ints long. SV_v13_ReadLong(); SV_v13_ReadLong(); SV_v13_ReadLong(); pos[VX] = FIX2FLT(SV_v13_ReadLong()); pos[VY] = FIX2FLT(SV_v13_ReadLong()); pos[VZ] = FIX2FLT(SV_v13_ReadLong()); // Sector links. SV_v13_ReadLong(); SV_v13_ReadLong(); angle = (angle_t) (ANG45 * (SV_v13_ReadLong() / 45)); sprite = SV_v13_ReadLong(); frame = SV_v13_ReadLong(); frame &= ~FF_FRAMEMASK; // not used anymore. // Block links. SV_v13_ReadLong(); SV_v13_ReadLong(); // Subsector. SV_v13_ReadLong(); floorz = FIX2FLT(SV_v13_ReadLong()); ceilingz = FIX2FLT(SV_v13_ReadLong()); radius = FIX2FLT(SV_v13_ReadLong()); height = FIX2FLT(SV_v13_ReadLong()); mom[MX] = FIX2FLT(SV_v13_ReadLong()); mom[MY] = FIX2FLT(SV_v13_ReadLong()); mom[MZ] = FIX2FLT(SV_v13_ReadLong()); valid = SV_v13_ReadLong(); type = SV_v13_ReadLong(); info = &MOBJINFO[type]; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; /** * We now have all the information we need to create the mobj. */ mo = P_MobjCreate(P_MobjThinker, pos[VX], pos[VY], pos[VZ], angle, radius, height, ddflags); mo->sprite = sprite; mo->frame = frame; mo->floorZ = floorz; mo->ceilingZ = ceilingz; mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; mo->mom[MZ] = mom[MZ]; mo->valid = valid; mo->type = type; mo->moveDir = DI_NODIR; /** * Continue reading the mobj data. */ SV_v13_ReadLong(); // info mo->tics = SV_v13_ReadLong(); mo->state = (state_t *) SV_v13_ReadLong(); mo->damage = SV_v13_ReadLong(); mo->flags = SV_v13_ReadLong(); mo->flags2 = SV_v13_ReadLong(); mo->special1 = SV_v13_ReadLong(); mo->special2 = SV_v13_ReadLong(); mo->health = SV_v13_ReadLong(); // Fix a bunch of kludges in the original Heretic. switch(mo->type) { case MT_MACEFX1: case MT_MACEFX2: case MT_MACEFX3: case MT_HORNRODFX2: case MT_HEADFX3: case MT_WHIRLWIND: case MT_TELEGLITTER: case MT_TELEGLITTER2: mo->special3 = mo->health; mo->health = info->spawnHealth; break; default: break; } mo->moveDir = SV_v13_ReadLong(); mo->moveCount = SV_v13_ReadLong(); SV_v13_ReadLong(); // target mo->reactionTime = SV_v13_ReadLong(); mo->threshold = SV_v13_ReadLong(); mo->player = (player_t *) SV_v13_ReadLong(); mo->lastLook = SV_v13_ReadLong(); mo->spawnSpot.pos[VX] = (float) SV_v13_ReadLong(); mo->spawnSpot.pos[VY] = (float) SV_v13_ReadLong(); mo->spawnSpot.pos[VZ] = 0; // Initialize with "something". mo->spawnSpot.angle = (angle_t) (ANG45 * (SV_v13_ReadLong() / 45)); /*mo->spawnSpot.type = (int)*/ SV_v13_ReadLong(); mo->spawnSpot.flags = (int) SV_v13_ReadLong(); mo->spawnSpot.flags &= ~MASK_UNKNOWN_MSF_FLAGS; // Spawn on the floor by default unless the mobjtype flags override. mo->spawnSpot.flags |= MSF_Z_FLOOR; SV_UpdateReadMobjFlags(mo, 0); mo->state = &STATES[(int) mo->state]; mo->target = NULL; if(mo->player) { mo->player = &players[(int) mo->player - 1]; mo->player->plr->mo = mo; mo->player->plr->mo->dPlayer = mo->player->plr; } P_MobjSetPosition(mo); mo->info = info; mo->floorZ = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); mo->ceilingZ = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); } void P_v13_UnArchivePlayers(void) { int i, j; for(i = 0; i < 4; ++i) { if(!players[i].plr->inGame) continue; SV_v13_ReadPlayer(players + i); players[i].plr->mo = NULL; // Will be set when unarc thinker. players[i].attacker = NULL; for(j = 0; j < NUMPSPRITES; ++j) { player_t *plr = &players[i]; if(plr->pSprites[j].state) { plr->pSprites[j].state = &STATES[(int) plr->pSprites[j].state]; } } } } void P_v13_UnArchiveWorld(void) { uint i, j; fixed_t offx, offy; short* get; sector_t* sec; xsector_t* xsec; linedef_t* line; xline_t* xline; get = (short *) save_p; // Do sectors. for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); P_SetFixedp(sec, DMU_FLOOR_HEIGHT, *get++ << FRACBITS); P_SetFixedp(sec, DMU_CEILING_HEIGHT, *get++ << FRACBITS); P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_FLATS))); P_SetPtrp(sec, DMU_CEILING_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_FLATS))); P_SetFloatp(sec, DMU_LIGHT_LEVEL, (float) (*get++) / 255.0f); xsec->special = *get++; // needed? /*xsec->tag =*/ *get++; // needed? xsec->specialData = 0; xsec->soundTarget = 0; } // Do lines. for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); xline = P_ToXLine(line); xline->flags = *get++; xline->special = *get++; /*xline->tag =*/ *get++; for(j = 0; j < 2; j++) { sidedef_t* sdef; if(j == 0) sdef = P_GetPtrp(line, DMU_SIDEDEF0); else sdef = P_GetPtrp(line, DMU_SIDEDEF1); if(!sdef) continue; offx = *get++ << FRACBITS; offy = *get++ << FRACBITS; P_SetFixedp(sdef, DMU_TOP_MATERIAL_OFFSET_X, offx); P_SetFixedp(sdef, DMU_TOP_MATERIAL_OFFSET_Y, offy); P_SetFixedp(sdef, DMU_MIDDLE_MATERIAL_OFFSET_X, offx); P_SetFixedp(sdef, DMU_MIDDLE_MATERIAL_OFFSET_Y, offy); P_SetFixedp(sdef, DMU_BOTTOM_MATERIAL_OFFSET_X, offx); P_SetFixedp(sdef, DMU_BOTTOM_MATERIAL_OFFSET_Y, offy); P_SetPtrp(sdef, DMU_TOP_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_TEXTURES))); P_SetPtrp(sdef, DMU_BOTTOM_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_TEXTURES))); P_SetPtrp(sdef, DMU_MIDDLE_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_TEXTURES))); } } save_p = (byte *) get; } static boolean removeThinker(thinker_t* th, void* context) { if(th->function == P_MobjThinker) P_MobjRemove((mobj_t *) th, true); else Z_Free(th); return true; // Continue iteration. } void P_v13_UnArchiveThinkers(void) { typedef enum { TC_END, TC_MOBJ } thinkerclass_t; byte tclass; // Remove all the current thinkers. DD_IterateThinkers(NULL, removeThinker, NULL); DD_InitThinkers(); // read in saved thinkers for(;;) { tclass = *save_p++; switch(tclass) { case TC_END: return; // End of list. case TC_MOBJ: SV_v13_ReadMobj(); break; default: Con_Error("Unknown tclass %i in savegame", tclass); } } } static int SV_ReadCeiling(ceiling_t *ceiling) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes ceilingtype_e type; // was 32bit int sector_t *sector; fixed_t bottomheight, topheight; fixed_t speed; boolean crush; int direction; // 1 = up, 0 = waiting, -1 = down int tag; // ID int olddirection; } v13_ceiling_t; */ byte temp[SIZEOF_V13_THINKER_T]; // Padding at the start (an old thinker_t struct) SV_v13_Read(&temp, SIZEOF_V13_THINKER_T); // Start of used data members. ceiling->type = SV_v13_ReadLong(); // A 32bit pointer to sector, serialized. ceiling->sector = P_ToPtr(DMU_SECTOR, SV_v13_ReadLong()); if(!ceiling->sector) Con_Error("tc_ceiling: bad sector number\n"); ceiling->bottomHeight = FIX2FLT(SV_v13_ReadLong()); ceiling->topHeight = FIX2FLT(SV_v13_ReadLong()); ceiling->speed = FIX2FLT(SV_v13_ReadLong()); ceiling->crush = SV_v13_ReadLong(); ceiling->state = (SV_v13_ReadLong() == -1? CS_DOWN : CS_UP); ceiling->tag = SV_v13_ReadLong(); ceiling->oldState = (SV_v13_ReadLong() == -1? CS_DOWN : CS_UP); ceiling->thinker.function = T_MoveCeiling; if(!(temp + V13_THINKER_T_FUNC_OFFSET)) DD_ThinkerSetStasis(&ceiling->thinker, true); P_ToXSector(ceiling->sector)->specialData = T_MoveCeiling; return true; // Add this thinker. } static int SV_ReadDoor(door_t *door) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes doortype_e type; // was 32bit int sector_t *sector; fixed_t topheight; fixed_t speed; int direction; // 1 = up, 0 = waiting at top, -1 = down int topwait; // tics to wait at the top // (keep in case a door going down is reset) int topcountdown; // when it reaches 0, start going down } v13_vldoor_t; */ // Padding at the start (an old thinker_t struct) SV_v13_Read(NULL, SIZEOF_V13_THINKER_T); // Start of used data members. door->type = SV_v13_ReadLong(); // A 32bit pointer to sector, serialized. door->sector = P_ToPtr(DMU_SECTOR, SV_v13_ReadLong()); if(!door->sector) Con_Error("tc_door: bad sector number\n"); door->topHeight = FIX2FLT(SV_v13_ReadLong()); door->speed = FIX2FLT(SV_v13_ReadLong()); door->state = SV_v13_ReadLong(); door->topWait = SV_v13_ReadLong(); door->topCountDown = SV_v13_ReadLong(); door->thinker.function = T_Door; P_ToXSector(door->sector)->specialData = T_Door; return true; // Add this thinker. } static int SV_ReadFloor(floor_t *floor) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes floortype_e type; // was 32bit int boolean crush; sector_t *sector; int direction; int newspecial; short texture; fixed_t floordestheight; fixed_t speed; } v13_floormove_t; */ // Padding at the start (an old thinker_t struct) SV_v13_Read(NULL, SIZEOF_V13_THINKER_T); // Start of used data members. floor->type = SV_v13_ReadLong(); floor->crush = SV_v13_ReadLong(); // A 32bit pointer to sector, serialized. floor->sector = P_ToPtr(DMU_SECTOR, SV_v13_ReadLong()); if(!floor->sector) Con_Error("tc_floor: bad sector number\n"); floor->state = (int) SV_v13_ReadLong(); floor->newSpecial = SV_v13_ReadLong(); floor->material = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(W_LumpName(SV_v13_ReadShort()), MN_FLATS)); floor->floorDestHeight = FIX2FLT(SV_v13_ReadLong()); floor->speed = FIX2FLT(SV_v13_ReadLong()); floor->thinker.function = T_MoveFloor; P_ToXSector(floor->sector)->specialData = T_MoveFloor; return true; // Add this thinker. } static int SV_ReadPlat(plat_t *plat) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; fixed_t speed; fixed_t low; fixed_t high; int wait; int count; platstate_e status; // was 32bit int platstate_e oldStatus; // was 32bit int boolean crush; int tag; plattype_e type; // was 32bit int } v13_plat_t; */ byte temp[SIZEOF_V13_THINKER_T]; // Padding at the start (an old thinker_t struct) SV_v13_Read(&temp, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. plat->sector = P_ToPtr(DMU_SECTOR, SV_v13_ReadLong()); if(!plat->sector) Con_Error("tc_plat: bad sector number\n"); plat->speed = FIX2FLT(SV_v13_ReadLong()); plat->low = FIX2FLT(SV_v13_ReadLong()); plat->high = FIX2FLT(SV_v13_ReadLong()); plat->wait = SV_v13_ReadLong(); plat->count = SV_v13_ReadLong(); plat->state = SV_v13_ReadLong(); plat->oldState = SV_v13_ReadLong(); plat->crush = SV_v13_ReadLong(); plat->tag = SV_v13_ReadLong(); plat->type = SV_v13_ReadLong(); plat->thinker.function = T_PlatRaise; if(!(temp + V13_THINKER_T_FUNC_OFFSET)) DD_ThinkerSetStasis(&plat->thinker, true); P_ToXSector(plat->sector)->specialData = T_PlatRaise; return true; // Add this thinker. } static int SV_ReadFlash(lightflash_t *flash) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; int count; int maxLight; int minLight; int maxTime; int minTime; } v13_lightflash_t; */ // Padding at the start (an old thinker_t struct) SV_v13_Read(NULL, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. flash->sector = P_ToPtr(DMU_SECTOR, SV_v13_ReadLong()); if(!flash->sector) Con_Error("tc_flash: bad sector number\n"); flash->count = SV_v13_ReadLong(); flash->maxLight = (float) SV_v13_ReadLong() / 255.0f; flash->minLight = (float) SV_v13_ReadLong() / 255.0f; flash->maxTime = SV_v13_ReadLong(); flash->minTime = SV_v13_ReadLong(); flash->thinker.function = T_LightFlash; return true; // Add this thinker. } static int SV_ReadStrobe(strobe_t *strobe) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; int count; int minLight; int maxLight; int darkTime; int brightTime; } v13_strobe_t; */ // Padding at the start (an old thinker_t struct) SV_v13_Read(NULL, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. strobe->sector = P_ToPtr(DMU_SECTOR, SV_v13_ReadLong()); if(!strobe->sector) Con_Error("tc_strobe: bad sector number\n"); strobe->count = SV_v13_ReadLong(); strobe->minLight = (float) SV_v13_ReadLong() / 255.0f; strobe->maxLight = (float) SV_v13_ReadLong() / 255.0f; strobe->darkTime = SV_v13_ReadLong(); strobe->brightTime = SV_v13_ReadLong(); strobe->thinker.function = T_StrobeFlash; return true; // Add this thinker. } static int SV_ReadGlow(glow_t *glow) { /* Original Heretic format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; int minLight; int maxLight; int direction; } v13_glow_t; */ // Padding at the start (an old thinker_t struct) SV_v13_Read(NULL, SIZEOF_V13_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. glow->sector = P_ToPtr(DMU_SECTOR, SV_v13_ReadLong()); if(!glow->sector) Con_Error("tc_glow: bad sector number\n"); glow->minLight = (float) SV_v13_ReadLong() / 255.0f; glow->maxLight = (float) SV_v13_ReadLong() / 255.0f; glow->direction = SV_v13_ReadLong(); glow->thinker.function = T_Glow; return true; // Add this thinker. } /** * Things to handle: * * T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list * T_Door, (door_t: sector_t * swizzle), * T_MoveFloor, (floor_t: sector_t * swizzle), * T_LightFlash, (lightflash_t: sector_t * swizzle), * T_StrobeFlash, (strobe_t: sector_t *), * T_Glow, (glow_t: sector_t *), * T_PlatRaise, (plat_t: sector_t *), - active list */ void P_v13_UnArchiveSpecials(void) { enum { tc_ceiling, tc_door, tc_floor, tc_plat, tc_flash, tc_strobe, tc_glow, tc_endspecials }; byte tclass; ceiling_t *ceiling; door_t *door; floor_t *floor; plat_t *plat; lightflash_t *flash; strobe_t *strobe; glow_t *glow; // read in saved thinkers for(;;) { tclass = *save_p++; switch(tclass) { case tc_endspecials: return; // end of list case tc_ceiling: ceiling = Z_Calloc(sizeof(*ceiling), PU_MAP, NULL); SV_ReadCeiling(ceiling); DD_ThinkerAdd(&ceiling->thinker); break; case tc_door: door = Z_Calloc(sizeof(*door), PU_MAP, NULL); SV_ReadDoor(door); DD_ThinkerAdd(&door->thinker); break; case tc_floor: floor = Z_Calloc(sizeof(*floor), PU_MAP, NULL); SV_ReadFloor(floor); DD_ThinkerAdd(&floor->thinker); break; case tc_plat: plat = Z_Calloc(sizeof(*plat), PU_MAP, NULL); SV_ReadPlat(plat); DD_ThinkerAdd(&plat->thinker); break; case tc_flash: flash = Z_Calloc(sizeof(*flash), PU_MAP, NULL); SV_ReadFlash(flash); DD_ThinkerAdd(&flash->thinker); break; case tc_strobe: strobe = Z_Calloc(sizeof(*strobe), PU_MAP, NULL); SV_ReadStrobe(strobe); DD_ThinkerAdd(&strobe->thinker); break; case tc_glow: glow = Z_Calloc(sizeof(*glow), PU_MAP, NULL); SV_ReadGlow(glow); DD_ThinkerAdd(&glow->thinker); break; default: Con_Error("P_UnarchiveSpecials:Unknown tclass %i " "in savegame", tclass); } } } boolean SV_v13_LoadGame(const char* savename) { size_t length; int i, a, b, c; char vcheck[VERSIONSIZE]; if(!(length = M_ReadFile(savename, &savebuffer))) return false; save_p = savebuffer + V13_SAVESTRINGSIZE; // Skip the description field memset(vcheck, 0, sizeof(vcheck)); sprintf(vcheck, "version %i", SAVE_VERSION); if(strcmp(save_p, vcheck)) { // Bad version Con_Message("Savegame ID '%s': incompatible?\n", save_p); } save_p += VERSIONSIZE; gameSkill = *save_p++; gameEpisode = (*save_p++) - 1; gameMap = (*save_p++) - 1; for(i = 0; i < 4; ++i) { players[i].plr->inGame = *save_p++; } // Load a base map. G_InitNew(gameSkill, gameEpisode, gameMap); // Create map time. a = *save_p++; b = *save_p++; c = *save_p++; mapTime = (a << 16) + (b << 8) + c; // De-archive all the modifications. P_v13_UnArchivePlayers(); P_v13_UnArchiveWorld(); P_v13_UnArchiveThinkers(); P_v13_UnArchiveSpecials(); if(*save_p != SAVE_GAME_TERMINATOR) Con_Error("Bad savegame"); // Missing savegame termination marker. Z_Free(savebuffer); // Spawn particle generators. R_SetupMap(DDSMM_AFTER_LOADING, 0); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/acfnlink.c0000644000175000017500000001715111357170242023070 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * acfnlink.c: */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- actionlink_t actionlinks[] = { {"A_AccTeleGlitter", A_AccTeleGlitter}, {"A_AddPlayerCorpse", A_AddPlayerCorpse}, {"A_AddPlayerRain", A_AddPlayerRain}, {"A_BeakAttackPL1", A_BeakAttackPL1}, {"A_BeakAttackPL2", A_BeakAttackPL2}, {"A_BeakRaise", A_BeakRaise}, {"A_BeakReady", A_BeakReady}, {"A_BeastAttack", A_BeastAttack}, {"A_BeastPuff", A_BeastPuff}, {"A_BlueSpark", A_BlueSpark}, {"A_BoltSpark", A_BoltSpark}, {"A_BossDeath", A_BossDeath}, {"A_Chase", A_Chase}, {"A_CheckBurnGone", A_CheckBurnGone}, {"A_CheckSkullDone", A_CheckSkullDone}, {"A_CheckSkullFloor", A_CheckSkullFloor}, {"A_ChicAttack", A_ChicAttack}, {"A_ChicChase", A_ChicChase}, {"A_ChicLook", A_ChicLook}, {"A_ChicPain", A_ChicPain}, {"A_ClinkAttack", A_ClinkAttack}, {"A_ContMobjSound", A_ContMobjSound}, {"A_DeathBallImpact", A_DeathBallImpact}, {"A_DripBlood", A_DripBlood}, {"A_ESound", A_ESound}, {"A_Explode", A_Explode}, {"A_FaceTarget", A_FaceTarget}, {"A_Feathers", A_Feathers}, {"A_FireBlasterPL1", A_FireBlasterPL1}, {"A_FireBlasterPL2", A_FireBlasterPL2}, {"A_FireCrossbowPL1", A_FireCrossbowPL1}, {"A_FireCrossbowPL2", A_FireCrossbowPL2}, {"A_FireGoldWandPL1", A_FireGoldWandPL1}, {"A_FireGoldWandPL2", A_FireGoldWandPL2}, {"A_FireMacePL1", A_FireMacePL1}, {"A_FireMacePL2", A_FireMacePL2}, {"A_FirePhoenixPL1", A_FirePhoenixPL1}, {"A_FirePhoenixPL2", A_FirePhoenixPL2}, {"A_FireSkullRodPL1", A_FireSkullRodPL1}, {"A_FireSkullRodPL2", A_FireSkullRodPL2}, {"A_FlameEnd", A_FlameEnd}, {"A_FlameSnd", A_FlameSnd}, {"A_FloatPuff", A_FloatPuff}, {"A_FreeTargMobj", A_FreeTargMobj}, {"A_GauntletAttack", A_GauntletAttack}, {"A_GenWizard", A_GenWizard}, {"A_GhostOff", A_GhostOff}, {"A_HeadAttack", A_HeadAttack}, {"A_HeadFireGrow", A_HeadFireGrow}, {"A_HeadIceImpact", A_HeadIceImpact}, {"A_HideInCeiling", A_HideInCeiling}, {"A_HideThing", A_HideThing}, {"A_ImpDeath", A_ImpDeath}, {"A_ImpExplode", A_ImpExplode}, {"A_ImpMeAttack", A_ImpMeAttack}, {"A_ImpMsAttack", A_ImpMsAttack}, {"A_ImpMsAttack2", A_ImpMsAttack2}, {"A_ImpXDeath1", A_ImpXDeath1}, {"A_ImpXDeath2", A_ImpXDeath2}, {"A_InitKeyGizmo", A_InitKeyGizmo}, {"A_InitPhoenixPL2", A_InitPhoenixPL2}, {"A_KnightAttack", A_KnightAttack}, {"A_Light0", A_Light0}, {"A_Look", A_Look}, {"A_Lower", A_Lower}, {"A_MaceBallImpact", A_MaceBallImpact}, {"A_MaceBallImpact2", A_MaceBallImpact2}, {"A_MacePL1Check", A_MacePL1Check}, {"A_MakePod", A_MakePod}, {"A_MinotaurAtk1", A_MinotaurAtk1}, {"A_MinotaurAtk2", A_MinotaurAtk2}, {"A_MinotaurAtk3", A_MinotaurAtk3}, {"A_MinotaurCharge", A_MinotaurCharge}, {"A_MinotaurDecide", A_MinotaurDecide}, {"A_MntrFloorFire", A_MntrFloorFire}, {"A_MummyAttack", A_MummyAttack}, {"A_MummyAttack2", A_MummyAttack2}, {"A_MummyFX1Seek", A_MummyFX1Seek}, {"A_MummySoul", A_MummySoul}, {"A_NoBlocking", A_NoBlocking}, {"A_Pain", A_Pain}, {"A_PhoenixPuff", A_PhoenixPuff}, {"A_PodPain", A_PodPain}, {"A_RainImpact", A_RainImpact}, {"A_Raise", A_Raise}, {"A_ReFire", A_ReFire}, {"A_RemovePod", A_RemovePod}, {"A_RestoreArtifact", A_RestoreArtifact}, {"A_RestoreSpecialThing1", A_RestoreSpecialThing1}, {"A_RestoreSpecialThing2", A_RestoreSpecialThing2}, {"A_Scream", A_Scream}, {"A_ShutdownPhoenixPL2", A_ShutdownPhoenixPL2}, {"A_SkullPop", A_SkullPop}, {"A_SkullRodPL2Seek", A_SkullRodPL2Seek}, {"A_SkullRodStorm", A_SkullRodStorm}, {"A_SnakeAttack", A_SnakeAttack}, {"A_SnakeAttack2", A_SnakeAttack2}, {"A_Sor1Chase", A_Sor1Chase}, {"A_Sor1Pain", A_Sor1Pain}, {"A_Sor2DthInit", A_Sor2DthInit}, {"A_Sor2DthLoop", A_Sor2DthLoop}, {"A_SorcererRise", A_SorcererRise}, {"A_SorDBon", A_SorDBon}, {"A_SorDExp", A_SorDExp}, {"A_SorDSph", A_SorDSph}, {"A_SorRise", A_SorRise}, {"A_SorSightSnd", A_SorSightSnd}, {"A_SorZap", A_SorZap}, {"A_SpawnRippers", A_SpawnRippers}, {"A_SpawnTeleGlitter", A_SpawnTeleGlitter}, {"A_SpawnTeleGlitter2", A_SpawnTeleGlitter2}, {"A_Srcr1Attack", A_Srcr1Attack}, {"A_Srcr2Attack", A_Srcr2Attack}, {"A_Srcr2Decide", A_Srcr2Decide}, {"A_StaffAttackPL1", A_StaffAttackPL1}, {"A_StaffAttackPL2", A_StaffAttackPL2}, {"A_UnHideThing", A_UnHideThing}, {"A_VolcanoBlast", A_VolcanoBlast}, {"A_VolcanoSet", A_VolcanoSet}, {"A_VolcBallImpact", A_VolcBallImpact}, {"A_WeaponReady", A_WeaponReady}, {"A_WhirlwindSeek", A_WhirlwindSeek}, {"A_WizAtk1", A_WizAtk1}, {"A_WizAtk2", A_WizAtk2}, {"A_WizAtk3", A_WizAtk3}, // Inventory: {"A_FireBomb", A_FireBomb}, {"A_TombOfPower", A_TombOfPower}, {"A_Egg", A_Egg}, {"A_Wings", A_Wings}, {"A_Teleport", A_Teleport}, {"A_Torch", A_Torch}, {"A_Health", A_Health}, {"A_SuperHealth", A_SuperHealth}, {"A_Invisibility", A_Invisibility}, {"A_Invulnerability", A_Invulnerability}, {0, 0} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_setup.c0000644000175000017500000001267711357170242022772 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2002-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.c: Handle jHeretic specific map data properties. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "am_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Called during pre-init. * Register the map object data types we want to Doomsday to make public via * it's MPE interface. */ void P_RegisterMapObjs(void) { P_RegisterMapObj(MO_THING, "Thing"); P_RegisterMapObjProperty(MO_THING, MO_X, "X", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Y, "Y", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Z, "Z", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_ANGLE, "Angle", DDVT_ANGLE); P_RegisterMapObjProperty(MO_THING, MO_DOOMEDNUM, "DoomEdNum", DDVT_INT); P_RegisterMapObjProperty(MO_THING, MO_FLAGS, "Flags", DDVT_INT); P_RegisterMapObj(MO_XLINEDEF, "XLinedef"); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TAG, "Tag", DDVT_SHORT); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TYPE, "Type", DDVT_SHORT); P_RegisterMapObjProperty(MO_XLINEDEF, MO_FLAGS, "Flags", DDVT_SHORT); P_RegisterMapObj(MO_XSECTOR, "XSector"); P_RegisterMapObjProperty(MO_XSECTOR, MO_TAG, "Tag", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_TYPE, "Type", DDVT_SHORT); } /** * \todo This is actually unnecessary. If we say that in the case of BOOM * overloaded texture names, rather than setting the surface material as * normal, the map converter should instead write to a property in XLinedef * which the game can then look up later. * * Doomsday will call this when loading the map data if it encounters a * value that it doesn't understand for a property IT handles. * * Doomsday thinks we might know what to do with it... * If we don't know what to do we'll return -1. * * @param id Index of the current element being read. * @param dtype DMU type identifier. * @param prop DMU property identifier. * @param type Data type id of the value pointed to by *data. * @param *data Ptr to the data value (has already been expanded, * size converted and endian converted where necessary). */ int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void *data) { switch(dtype) { case DMU_SURFACE: switch(prop) { case DMU_MATERIAL: /** * It could be a BOOM overloaded texture name? * In this context Doomsday expects either -1 (a bad texture name) * Or the id of a wall texture it should set to this section. * \todo Add code to determine what to do. */ break; default: break; } break; default: break; } return -1; // We ain't got a clue what to do with it... } /** * These status reports inform us of what Doomsday is doing to a particular * map data object (at any time) that we might want to react to. * * If we arn't interested in the report - we should simply return true and * take no further action. * * @param code ID code of the status report (enum in dd_share.h) * @param id Map data object id. * @param type Map data object type eg DMU_SECTOR. * @param data Any relevant data for this report (currently unused). */ int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void *data) { switch(code) { case DMUSC_LINE_FIRSTRENDERED: /** * Called the first time the given line is rendered. * *data is a pointer to int, giving the player id which has seen it. * We'll utilize this to mark it as being visible in the automap. */ AM_UpdateLinedef(AM_MapForPlayer(*(int *) data), id, true); break; default: break; } return 1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/h_console.c0000644000175000017500000002612411357170242023254 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_console.c: Console stuff - jHeretic specific. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "hu_stuff.h" #include "f_infine.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdCheat); DEFCC(CCmdCheatGod); DEFCC(CCmdCheatNoClip); DEFCC(CCmdCheatWarp); DEFCC(CCmdCheatReveal); DEFCC(CCmdCheatGive); DEFCC(CCmdCheatMassacre); DEFCC(CCmdCheatWhere); DEFCC(CCmdCheatPig); DEFCC(CCmdCheatLeaveMap); DEFCC(CCmdCheatSuicide); DEFCC(CCmdMakeLocal); DEFCC(CCmdSetCamera); DEFCC(CCmdSetViewLock); DEFCC(CCmdSetViewMode); DEFCC(CCmdCycleSpy); DEFCC(CCmdPlayDemo); DEFCC(CCmdRecordDemo); DEFCC(CCmdStopDemo); DEFCC(CCmdSpawnMobj); DEFCC(CCmdPrintPlayerCoords); void G_UpdateEyeHeight(cvar_t* unused); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- DEFCC(CCmdScreenShot); DEFCC(CCmdViewSize); DEFCC(CCmdHereticFont); DEFCC(CCmdConBackground); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- material_t* consoleBG = NULL; float consoleZoom = 1; // Console variables. cvar_t gameCVars[] = { // Console {"con-zoom", 0, CVT_FLOAT, &consoleZoom, 0.1f, 100.0f}, // View/Refresh {"view-size", CVF_PROTECTED, CVT_INT, &cfg.screenBlocks, 3, 13}, {"hud-title", 0, CVT_BYTE, &cfg.mapTitle, 0, 1}, {"hud-title-author-noiwad", 0, CVT_BYTE, &cfg.hideIWADAuthor, 0, 1}, {"view-bob-height", 0, CVT_FLOAT, &cfg.bobView, 0, 1}, {"view-bob-weapon", 0, CVT_FLOAT, &cfg.bobWeapon, 0, 1}, {"view-bob-weapon-switch-lower", 0, CVT_BYTE, &cfg.bobWeaponLower, 0, 1}, {"view-filter-strength", 0, CVT_FLOAT, &cfg.filterStrength, 0, 1}, {"view-ringfilter", 0, CVT_INT, &cfg.ringFilter, 1, 2}, // Server-side options // Game state {"server-game-skill", 0, CVT_BYTE, &cfg.netSkill, 0, 4}, {"server-game-map", CVF_NO_MAX, CVT_BYTE, &cfg.netMap, 0, 0}, {"server-game-episode", CVF_NO_MAX, CVT_BYTE, &cfg.netEpisode, 0, 0}, {"server-game-deathmatch", 0, CVT_BYTE, &cfg.netDeathmatch, 0, 1}, /* jHeretic only has one deathmatch mode */ // Modifiers {"server-game-mod-damage", 0, CVT_BYTE, &cfg.netMobDamageModifier, 1, 100}, {"server-game-mod-health", 0, CVT_BYTE, &cfg.netMobHealthModifier, 1, 20}, {"server-game-mod-gravity", 0, CVT_INT, &cfg.netGravity, -1, 100}, // Gameplay options {"server-game-jump", 0, CVT_BYTE, &cfg.netJumping, 0, 1}, {"server-game-nomonsters", 0, CVT_BYTE, &cfg.netNoMonsters, 0, 1}, {"server-game-respawn", 0, CVT_BYTE, &cfg.netRespawn, 0, 1}, {"server-game-respawn-monsters-nightmare", 0, CVT_BYTE, &cfg.respawnMonstersNightmare, 0, 1}, {"server-game-radiusattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZRadiusAttack, 0, 1}, {"server-game-monster-meleeattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZMonsterMeleeAttack, 0, 1}, {"server-game-coop-nodamage", 0, CVT_BYTE, &cfg.noCoopDamage, 0, 1}, {"server-game-noteamdamage", 0, CVT_BYTE, &cfg.noTeamDamage, 0, 1}, // Misc {"server-game-announce-secret", 0, CVT_BYTE, &cfg.secretMsg, 0, 1}, // Player // Player data {"player-color", 0, CVT_BYTE, &cfg.netColor, 0, 4}, {"player-eyeheight", 0, CVT_INT, &cfg.plrViewHeight, 41, 54, G_UpdateEyeHeight}, // Movment {"player-move-speed", 0, CVT_FLOAT, &cfg.playerMoveSpeed, 0, 1}, {"player-jump", 0, CVT_INT, &cfg.jumpEnabled, 0, 1}, {"player-jump-power", 0, CVT_FLOAT, &cfg.jumpPower, 0, 100}, {"player-air-movement", 0, CVT_BYTE, &cfg.airborneMovement, 0, 32}, // Weapon switch preferences {"player-autoswitch", 0, CVT_BYTE, &cfg.weaponAutoSwitch, 0, 2}, {"player-autoswitch-ammo", 0, CVT_BYTE, &cfg.ammoAutoSwitch, 0, 2}, {"player-autoswitch-notfiring", 0, CVT_BYTE, &cfg.noWeaponAutoSwitchIfFiring, 0, 1}, // Weapon Order preferences {"player-weapon-order0", 0, CVT_INT, &cfg.weaponOrder[0], 0, NUM_WEAPON_TYPES}, {"player-weapon-order1", 0, CVT_INT, &cfg.weaponOrder[1], 0, NUM_WEAPON_TYPES}, {"player-weapon-order2", 0, CVT_INT, &cfg.weaponOrder[2], 0, NUM_WEAPON_TYPES}, {"player-weapon-order3", 0, CVT_INT, &cfg.weaponOrder[3], 0, NUM_WEAPON_TYPES}, {"player-weapon-order4", 0, CVT_INT, &cfg.weaponOrder[4], 0, NUM_WEAPON_TYPES}, {"player-weapon-order5", 0, CVT_INT, &cfg.weaponOrder[5], 0, NUM_WEAPON_TYPES}, {"player-weapon-order6", 0, CVT_INT, &cfg.weaponOrder[6], 0, NUM_WEAPON_TYPES}, {"player-weapon-order7", 0, CVT_INT, &cfg.weaponOrder[7], 0, NUM_WEAPON_TYPES}, {"player-weapon-order8", 0, CVT_INT, &cfg.weaponOrder[8], 0, NUM_WEAPON_TYPES}, {"player-weapon-nextmode", 0, CVT_BYTE, &cfg.weaponNextMode, 0, 1}, // Misc {"player-camera-noclip", 0, CVT_INT, &cfg.cameraNoClip, 0, 1}, // Compatibility options {"game-monsters-stuckindoors", 0, CVT_BYTE, &cfg.monstersStuckInDoors, 0, 1}, {"game-objects-neverhangoverledges", 0, CVT_BYTE, &cfg.avoidDropoffs, 0, 1}, {"game-objects-clipping", 0, CVT_BYTE, &cfg.moveBlock, 0, 1}, {"game-player-wallrun-northonly", 0, CVT_BYTE, &cfg.wallRunNorthOnly, 0, 1}, {"game-objects-falloff", 0, CVT_BYTE, &cfg.fallOff, 0, 1}, {"game-zclip", 0, CVT_BYTE, &cfg.moveCheckZ, 0, 1}, {"game-corpse-sliding", 0, CVT_BYTE, &cfg.slidingCorpses, 0, 1}, {"server-game-maulotaur-fixfloorfire", 0, CVT_BYTE, &cfg.fixFloorFire, 0, 1}, {"server-game-plane-fixmaterialscroll", 0, CVT_BYTE, &cfg.fixPlaneScrollMaterialsEastOnly, 0, 1}, // Game state {"game-fastmonsters", 0, CVT_BYTE, &cfg.fastMonsters, 0, 1}, // Gameplay {"game-corpse-time", CVF_NO_MAX, CVT_INT, &cfg.corpseTime, 0, 0}, // Misc {"msg-echo", 0, CVT_BYTE, &cfg.echoMsg, 0, 1}, {NULL} }; // Console commands ccmd_t gameCCmds[] = { {"spy", "", CCmdCycleSpy}, {"screenshot", "", CCmdScreenShot}, {"viewsize", "s", CCmdViewSize}, // $cheats {"cheat", "s", CCmdCheat}, {"god", NULL, CCmdCheatGod}, {"noclip", NULL, CCmdCheatNoClip}, {"warp", NULL, CCmdCheatWarp}, {"reveal", "i", CCmdCheatReveal}, {"give", NULL, CCmdCheatGive}, {"kill", "", CCmdCheatMassacre}, {"leavemap", "", CCmdCheatLeaveMap}, {"suicide", NULL, CCmdCheatSuicide}, {"where", "", CCmdCheatWhere}, {"hereticfont", "", CCmdHereticFont}, {"conbg", "s", CCmdConBackground}, // $infine {"startinf", "s", CCmdStartInFine}, {"stopinf", "", CCmdStopInFine}, {"stopfinale", "", CCmdStopInFine}, {"spawnmobj", NULL, CCmdSpawnMobj}, {"coord", "", CCmdPrintPlayerCoords}, // $democam {"makelocp", "i", CCmdMakeLocal}, {"makecam", "i", CCmdSetCamera}, {"setlock", NULL, CCmdSetViewLock}, {"lockmode", "i", CCmdSetViewLock}, {"viewmode", NULL, CCmdSetViewMode}, // Heretic specific {"chicken", "", CCmdCheatPig}, {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Add the console variables and commands. */ void G_ConsoleRegistration(void) { int i; for(i = 0; gameCVars[i].name; ++i) Con_AddVariable(gameCVars + i); for(i = 0; gameCCmds[i].name; ++i) Con_AddCommand(gameCCmds + i); } /** * Settings for console background drawing. * Called EVERY FRAME by the console drawer. */ void H_ConsoleBg(int* width, int* height) { if(consoleBG) { DGL_SetMaterial(consoleBG); *width = (int) (64 * consoleZoom); *height = (int) (64 * consoleZoom); } else { DGL_SetNoMaterial(); *width = *height = 0; } } /** * Called when the player-eyeheight cvar is changed. */ void G_UpdateEyeHeight(cvar_t* unused) { player_t* plr = &players[CONSOLEPLAYER]; if(!(plr->plr->flags & DDPF_CAMERA)) plr->viewHeight = (float) cfg.plrViewHeight; } /** * Draw (char *) text in the game's font. * Called by the console drawer. */ int ConTextOut(const char* text, int x, int y) { M_WriteText3(x, y, text, GF_FONTA, -1, -1, -1, -1, false, false, 0); return 0; } /** * Get the visual width of (char*) text in the game's font. */ int ConTextWidth(const char* text) { return M_StringWidth(text, GF_FONTA); } /** * Console command to take a screenshot (duh). */ DEFCC(CCmdScreenShot) { G_ScreenShot(); return true; } /** * Console command to change the size of the view window. */ DEFCC(CCmdViewSize) { int min = 3, max = 13, *val = &cfg.screenBlocks; if(argc != 2) { Con_Printf("Usage: %s (size)\n", argv[0]); Con_Printf("Size can be: +, -, (num).\n"); return true; } // Adjust/set the value if(!stricmp(argv[1], "+")) (*val)++; else if(!stricmp(argv[1], "-")) (*val)--; else *val = strtol(argv[1], NULL, 0); // Clamp it if(*val < min) *val = min; if(*val > max) *val = max; // Update the view size if necessary. R_SetViewSize(cfg.screenBlocks); return true; } /** * Configure the console to use the game's font. */ DEFCC(CCmdHereticFont) { ddfont_t cfont; cfont.flags = DDFONT_WHITE; cfont.height = 9; cfont.sizeX = 1.2f; cfont.sizeY = 2; cfont.drawText = ConTextOut; cfont.getWidth = ConTextWidth; cfont.filterText = NULL; Con_SetFont(&cfont); return true; } /** * Configure the console background. */ DEFCC(CCmdConBackground) { material_t* mat; if(!stricmp(argv[1], "off") || !stricmp(argv[1], "none")) { consoleBG = NULL; return true; } if((mat = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(argv[1], MN_ANY)))) consoleBG = mat; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/h_api.c0000644000175000017500000001221611357170242022360 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_api.c: Doomsday API setup and interaction - jHeretic specific */ // HEADER FILES ------------------------------------------------------------ #include #include "jheretic.h" #include "d_netsv.h" #include "d_net.h" #include "hu_menu.h" #include "xgclass.h" #include "g_update.h" #include "p_mapsetup.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The interface to the Doomsday engine. game_import_t gi; game_export_t gx; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Get a 32-bit integer value. */ int G_GetInteger(int id) { switch(id) { case DD_GAME_DMUAPI_VER: return DMUAPI_VER; default: break; } // ID not recognized, return NULL. return 0; } /** * Get a pointer to the value of a variable. Added for 64-bit support. */ void* G_GetVariable(int id) { static float bob[2]; switch(id) { case DD_GAME_NAME: return GAMENAMETEXT; case DD_GAME_NICENAME: return GAME_NICENAME; case DD_GAME_ID: return GAMENAMETEXT " " GAME_VERSION_TEXT; case DD_GAME_MODE: return gameModeString; case DD_GAME_CONFIG: return gameConfigString; case DD_VERSION_SHORT: return GAME_VERSION_TEXT; case DD_VERSION_LONG: return GAME_VERSION_TEXTLONG "\n" GAME_DETAILS; case DD_ACTION_LINK: return actionlinks; case DD_XGFUNC_LINK: return xgClasses; case DD_PSPRITE_BOB_X: R_GetWeaponBob(DISPLAYPLAYER, &bob[0], NULL); return &bob[0]; case DD_PSPRITE_BOB_Y: R_GetWeaponBob(DISPLAYPLAYER, NULL, &bob[1]); return &bob[1]; default: break; } // ID not recognized, return NULL. return 0; } /** * Takes a copy of the engine's entry points and exported data. Returns * a pointer to the structure that contains our entry points and exports. */ game_export_t* GetGameAPI(game_import_t* imports) { // Take a copy of the imports, but only copy as much data as is // allowed and legal. memset(&gi, 0, sizeof(gi)); memcpy(&gi, imports, MIN_OF(sizeof(game_import_t), imports->apiSize)); // Clear all of our exports. memset(&gx, 0, sizeof(gx)); // Fill in the data for the exports. gx.apiSize = sizeof(gx); gx.PreInit = G_PreInit; gx.PostInit = G_PostInit; gx.Shutdown = G_Shutdown; gx.Ticker = G_Ticker; gx.G_Drawer = H_Display; gx.G_Drawer2 = H_Display2; gx.PrivilegedResponder = (boolean (*)(event_t *)) G_PrivilegedResponder; gx.FallbackResponder = NULL; //Hu_MenuResponder; gx.G_Responder = G_Responder; gx.MobjThinker = P_MobjThinker; gx.MobjFriction = (float (*)(void *)) P_MobjGetFriction; gx.EndFrame = G_EndFrame; gx.ConsoleBackground = H_ConsoleBg; gx.UpdateState = G_UpdateState; gx.GetInteger = G_GetInteger; gx.GetVariable = G_GetVariable; gx.NetServerStart = D_NetServerStarted; gx.NetServerStop = D_NetServerClose; gx.NetConnect = D_NetConnect; gx.NetDisconnect = D_NetDisconnect; gx.NetPlayerEvent = D_NetPlayerEvent; gx.NetWorldEvent = D_NetWorldEvent; gx.HandlePacket = D_HandlePacket; gx.NetWriteCommands = D_NetWriteCommands; gx.NetReadCommands = D_NetReadCommands; // Data structure sizes. gx.ticcmdSize = sizeof(ticcmd_t); gx.mobjSize = sizeof(mobj_t); gx.polyobjSize = sizeof(polyobj_t); gx.SetupForMapData = P_SetupForMapData; // These really need better names. Ideas? gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; return &gx; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/h_main.c0000644000175000017500000003756711357170242022553 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_main.c: Game initialization - jHeretic specific. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "jheretic.h" #include "m_argv.h" #include "hu_stuff.h" #include "hu_menu.h" #include "hu_msg.h" #include "hu_log.h" #include "p_saveg.h" #include "d_net.h" #include "p_mapspec.h" #include "p_switch.h" #include "am_map.h" #include "p_inventory.h" #include "p_player.h" // MACROS ------------------------------------------------------------------ #define MAXWADFILES 20 // MAPDIR should be defined as the directory that holds development maps // for the -wart # # command #define MAPDIR "\\data\\" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int verbose; boolean devParm; // checkparm of -devparm boolean noMonstersParm; // checkparm of -nomonsters boolean respawnParm; // checkparm of -respawn boolean turboParm; // checkparm of -turbo boolean fastParm; // checkparm of -fast float turboMul; // multiplier for turbo skillmode_t startSkill; int startEpisode; int startMap; boolean autoStart; gamemode_t gameMode; int gameModeBits; // This is returned in D_Get(DD_GAME_MODE), max 16 chars. char gameModeString[17]; boolean monsterInfight; // Default font colours. const float defFontRGB[] = { .425f, 0.986f, 0.378f}; const float defFontRGB2[] = { 1.0f, 1.0f, 1.0f}; char *borderLumps[] = { "FLAT513", // background "bordt", // top "bordr", // right "bordb", // bottom "bordl", // left "bordtl", // top left "bordtr", // top right "bordbr", // bottom right "bordbl" // bottom left }; char *wadFiles[MAXWADFILES] = { "heretic.wad", "texture1.lmp", "texture2.lmp", "pnames.lmp" }; char *baseDefault = "heretic.cfg"; char exrnWADs[80]; char exrnWADs2[80]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean devMap; // CODE -------------------------------------------------------------------- /** * Attempt to change the current game mode. Can only be done when not * actually in a level. * * \todo Doesn't actually do anything yet other than set the game mode * global vars. * * @param mode The game mode to change to. * * @return @c true, if we changed game modes successfully. */ boolean G_SetGameMode(gamemode_t mode) { gameMode = mode; if(G_GetGameState() == GS_MAP) return false; switch(mode) { case shareware: // shareware, E1, M9 gameModeBits = GM_SHAREWARE; break; case registered: // registered episodes gameModeBits = GM_REGISTERED; break; case extended: // episodes 4 and 5 present gameModeBits = GM_EXTENDED; break; case indetermined: // Well, no IWAD found. gameModeBits = GM_INDETERMINED; break; default: Con_Error("G_SetGameMode: Unknown gamemode %i", mode); } return true; } static void addFile(char *file) { int numWADFiles; char *new; for(numWADFiles = 0; wadFiles[numWADFiles]; numWADFiles++); new = malloc(strlen(file) + 1); strcpy(new, file); if(strlen(exrnWADs) + strlen(file) < 78) { if(strlen(exrnWADs)) { strcat(exrnWADs, ", "); } else { strcpy(exrnWADs, "External Wadfiles: "); } strcat(exrnWADs, file); } else if(strlen(exrnWADs2) + strlen(file) < 79) { if(strlen(exrnWADs2)) { strcat(exrnWADs2, ", "); } else { strcpy(exrnWADs2, " "); strcat(exrnWADs, ","); } strcat(exrnWADs2, file); } wadFiles[numWADFiles] = new; } /** * Check which known IWADs are found. The purpose of this routine is to * find out which IWADs the user lets us to know about, but we don't * decide which one gets loaded or even see if the WADs are actually * there. The default location for IWADs is Data\GAMENAMETEXT\. */ void G_DetectIWADs(void) { // Add a couple of probable locations for Heretic.wad. DD_AddIWAD("}data\\"GAMENAMETEXT"\\heretic.wad"); DD_AddIWAD("}data\\heretic.wad"); DD_AddIWAD("}heretic.wad"); DD_AddIWAD("heretic.wad"); } /** * gamemode, gamemission and the gameModeString are set. */ void G_IdentifyVersion(void) { // The game mode string is used in netgames. strcpy(gameModeString, "heretic"); if(W_CheckNumForName("E2M1") == -1) { // Can't find episode 2 maps, must be the shareware WAD strcpy(gameModeString, "heretic-share"); } else if(W_CheckNumForName("EXTENDED") != -1) { // Found extended lump, must be the extended WAD strcpy(gameModeString, "heretic-ext"); } } /** * Pre Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PreInit(void) { int i; G_SetGameMode(indetermined); // Config defaults. The real settings are read from the .cfg files // but these will be used no such files are found. memset(&cfg, 0, sizeof(cfg)); cfg.playerMoveSpeed = 1; cfg.dclickUse = false; cfg.povLookAround = true; cfg.statusbarScale = 20; // Full size. cfg.screenBlocks = cfg.setBlocks = 10; cfg.echoMsg = true; cfg.lookSpeed = 3; cfg.turnSpeed = 1; cfg.usePatchReplacement = 2; // Use built-in replacements if available. cfg.menuScale = .9f; cfg.menuGlitter = 0; cfg.menuShadow = 0; //cfg.menuQuitSound = true; cfg.flashColor[0] = .7f; cfg.flashColor[1] = .9f; cfg.flashColor[2] = 1; cfg.flashSpeed = 4; cfg.turningSkull = false; cfg.hudShown[HUD_AMMO] = true; cfg.hudShown[HUD_ARMOR] = true; cfg.hudShown[HUD_KEYS] = true; cfg.hudShown[HUD_HEALTH] = true; cfg.hudShown[HUD_CURRENTITEM] = true; for(i = 0; i < NUMHUDUNHIDEEVENTS; ++i) // when the hud/statusbar unhides. cfg.hudUnHide[i] = 1; cfg.hudScale = .7f; cfg.hudColor[0] = .325f; cfg.hudColor[1] = .686f; cfg.hudColor[2] = .278f; cfg.hudColor[3] = 1; cfg.hudIconAlpha = 1; cfg.xhairSize = .5f; cfg.xhairVitality = false; cfg.xhairColor[0] = 1; cfg.xhairColor[1] = 1; cfg.xhairColor[2] = 1; cfg.xhairColor[3] = 1; cfg.filterStrength = .8f; //cfg.snd_3D = false; //cfg.snd_ReverbFactor = 100; cfg.moveCheckZ = true; cfg.jumpPower = 9; cfg.airborneMovement = 1; cfg.weaponAutoSwitch = 1; // IF BETTER cfg.noWeaponAutoSwitchIfFiring = false; cfg.ammoAutoSwitch = 0; // never cfg.slidingCorpses = false; cfg.fastMonsters = false; cfg.secretMsg = true; cfg.netJumping = true; cfg.netEpisode = 0; cfg.netMap = 1; cfg.netSkill = SM_MEDIUM; cfg.netColor = 4; // Use the default color by default. cfg.netMobDamageModifier = 1; cfg.netMobHealthModifier = 1; cfg.netGravity = -1; // use map default cfg.plrViewHeight = DEFAULT_PLAYER_VIEWHEIGHT; cfg.mapTitle = true; cfg.hideIWADAuthor = true; cfg.menuColor[0] = defFontRGB[0]; // use the default colour by default. cfg.menuColor[1] = defFontRGB[1]; cfg.menuColor[2] = defFontRGB[2]; cfg.menuColor2[0] = defFontRGB2[0]; // use the default colour by default. cfg.menuColor2[1] = defFontRGB2[1]; cfg.menuColor2[2] = defFontRGB2[2]; cfg.menuSlam = true; cfg.menuHotkeys = true; cfg.askQuickSaveLoad = true; cfg.monstersStuckInDoors = false; cfg.avoidDropoffs = true; cfg.moveBlock = false; cfg.fallOff = true; cfg.fixFloorFire = false; cfg.fixPlaneScrollMaterialsEastOnly = true; cfg.statusbarOpacity = 1; cfg.statusbarCounterAlpha = 1; cfg.automapCustomColors = 0; // Never. cfg.automapL0[0] = .455f; // Unseen areas cfg.automapL0[1] = .482f; cfg.automapL0[2] = .439f; cfg.automapL1[0] = .294f; // onesided lines cfg.automapL1[1] = .196f; cfg.automapL1[2] = .063f; cfg.automapL2[0] = .184f; // floor height change lines cfg.automapL2[1] = .094f; cfg.automapL2[2] = .002f; cfg.automapL3[0] = .592f; // ceiling change lines cfg.automapL3[1] = .388f; cfg.automapL3[2] = .231f; cfg.automapMobj[0] = 1.f; cfg.automapMobj[1] = 1.f; cfg.automapMobj[2] = 1.f; cfg.automapBack[0] = 1.0f; cfg.automapBack[1] = 1.0f; cfg.automapBack[2] = 1.0f; cfg.automapOpacity = 1.0f; cfg.automapLineAlpha = 1.0f; cfg.automapShowDoors = true; cfg.automapDoorGlow = 8; cfg.automapHudDisplay = 2; cfg.automapRotate = true; cfg.automapBabyKeys = true; cfg.automapZoomSpeed = .1f; cfg.automapPanSpeed = .5f; cfg.automapPanResetOnOpen = true; cfg.automapOpenSeconds = AUTOMAP_OPEN_SECONDS; cfg.counterCheatScale = .7f; cfg.msgShow = true; cfg.msgCount = 4; cfg.msgScale = .8f; cfg.msgUptime = 5; cfg.msgAlign = ALIGN_CENTER; cfg.msgBlink = 5; cfg.msgColor[0] = defFontRGB2[0]; cfg.msgColor[1] = defFontRGB2[1]; cfg.msgColor[2] = defFontRGB2[2]; cfg.inventoryTimer = 5; cfg.inventoryWrap = false; cfg.inventoryUseNext = false; cfg.inventoryUseImmediate = false; cfg.inventorySlotMaxVis = 7; cfg.inventorySlotShowEmpty = true; cfg.inventorySelectMode = 0; // Cursor select. cfg.chatBeep = 1; //cfg.killMessages = true; cfg.bobView = 1; cfg.bobWeapon = 1; cfg.bobWeaponLower = true; cfg.cameraNoClip = true; cfg.respawnMonstersNightmare = false; cfg.weaponOrder[0] = WT_SEVENTH; // mace \ beak cfg.weaponOrder[1] = WT_SIXTH; // phoenixrod \ beak cfg.weaponOrder[2] = WT_FIFTH; // skullrod \ beak cfg.weaponOrder[3] = WT_FOURTH; // blaster \ beak cfg.weaponOrder[4] = WT_THIRD; // crossbow \ beak cfg.weaponOrder[5] = WT_SECOND; // goldwand \ beak cfg.weaponOrder[6] = WT_EIGHTH; // gauntlets \ beak cfg.weaponOrder[7] = WT_FIRST; // staff \ beak cfg.menuEffects = 0; cfg.hudFog = 5; cfg.ringFilter = 1; cfg.tomeCounter = 10; cfg.tomeSound = 3; // Shareware WAD has different border background if(W_CheckNumForName("E2M1") == -1) borderLumps[0] = "FLOOR04"; // Do the common pre init routine; G_CommonPreInit(); } /** * Post Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PostInit(void) { int e, m, p; filename_t file; char mapStr[6]; if(W_CheckNumForName("E2M1") == -1) // Can't find episode 2 maps, must be the shareware WAD. G_SetGameMode(shareware); else if(W_CheckNumForName("EXTENDED") != -1) // Found extended lump, must be the extended WAD. G_SetGameMode(extended); else G_SetGameMode(registered); // Common post init routine. G_CommonPostInit(); // Initialize weapon info using definitions. P_InitWeaponInfo(); // Print a game mode banner with rulers. Con_FPrintf(CBLF_RULER | CBLF_WHITE | CBLF_CENTER, gameMode == shareware? "Heretic Shareware Startup\n" : gameMode == registered? "Heretic Registered Startup\n" : gameMode == extended? "Heretic: Shadow of the Serpent Riders Startup\n" : "Public Heretic\n"); Con_FPrintf(CBLF_RULER, ""); // Game parameters. monsterInfight = GetDefInt("AI|Infight", 0); // Defaults for skill, episode and map. startSkill = SM_MEDIUM; startEpisode = 0; startMap = 0; autoStart = false; // Game mode specific settings. /* None */ // Command line options. noMonstersParm = ArgCheck("-nomonsters"); respawnParm = ArgCheck("-respawn"); devParm = ArgCheck("-devparm"); if(ArgCheck("-deathmatch")) { cfg.netDeathmatch = true; } p = ArgCheck("-skill"); if(p && p < myargc - 1) { startSkill = Argv(p + 1)[0] - '1'; autoStart = true; } p = ArgCheck("-episode"); if(p && p < myargc - 1) { startEpisode = Argv(p + 1)[0] - '1'; startMap = 0; autoStart = true; } p = ArgCheck("-warp"); if(p && p < myargc - 2) { startEpisode = Argv(p + 1)[0] - '1'; startMap = Argv(p + 2)[0] - '1'; autoStart = true; } // turbo option. p = ArgCheck("-turbo"); turboMul = 1.0f; if(p) { int scale = 200; turboParm = true; if(p < myargc - 1) scale = atoi(Argv(p + 1)); if(scale < 10) scale = 10; if(scale > 400) scale = 400; Con_Message("turbo scale: %i%%\n", scale); turboMul = scale / 100.f; } // -DEVMAP // Adds a map wad from the development directory to the wad list, // and sets the start episode and the start map. devMap = false; p = ArgCheck("-devmap"); if(p && p < myargc - 2) { e = Argv(p + 1)[0] - 1; m = Argv(p + 2)[0] - 1; sprintf(file, MAPDIR "E%cM%c.wad", e+1, m+1); addFile(file); printf("DEVMAP: Episode %c, Map %c.\n", e+1, m+1); startEpisode = e; startMap = m; autoStart = true; devMap = true; } // Are we autostarting? if(autoStart) { Con_Message("Warp to Episode %d, Map %d, Skill %d\n", startEpisode+1, startMap+1, startSkill + 1); } // Load a saved game? p = ArgCheck("-loadgame"); if(p && p < myargc - 1) { SV_GetSaveGameFileName(file, Argv(p + 1)[0] - '0', FILENAME_T_MAXLEN); G_LoadGame(file); } // Check valid episode and map if(autoStart || IS_NETGAME && !devMap) { sprintf(mapStr, "E%d%d", startEpisode+1, startMap+1); if(!W_CheckNumForName(mapStr)) { startEpisode = 0; startMap = 0; } } if(G_GetGameAction() != GA_LOADGAME) { if(autoStart || IS_NETGAME) { G_DeferedInitNew(startSkill, startEpisode, startMap); } else { G_StartTitle(); // Start up intro loop. } } } void G_Shutdown(void) { Hu_MsgShutdown(); Hu_UnloadData(); Hu_LogShutdown(); P_DestroyIterList(spechit); P_DestroyIterList(linespecials); P_DestroyLineTagLists(); P_DestroySectorTagLists(); P_ShutdownInventory(); AM_Shutdown(); P_FreeWeaponSlots(); } void G_EndFrame(void) { // Nothing to do. } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_sound.c0000644000175000017500000000626611357170242022757 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sound.c: */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "dmu_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Start the song for the specified map. */ void S_MapMusic(uint episode, uint map) { ddmapinfo_t mapInfo; char mapId[8]; P_GetMapLumpName(episode, map, mapId); if(Def_Get(DD_DEF_MAP_INFO, mapId, &mapInfo)) { if(S_StartMusicNum(mapInfo.music, true)) { // Set the game status cvar for the map music. gsvMapMusic = mapInfo.music; } } } /** * Doom-like sector sounds: when a new sound starts, stop any old ones * from the same origin. * * @param sec Sector in which the sound should be played. * @param origin Origin of the sound (center/floor/ceiling). * @param id ID number of the sound to be played. */ void S_SectorSound(sector_t *sec, int origin, int id) { mobj_t *centerorigin, *floororigin, *ceilingorigin; centerorigin = (mobj_t *) P_GetPtrp(sec, DMU_SOUND_ORIGIN); floororigin = (mobj_t *) P_GetPtrp(sec, DMU_FLOOR_SOUND_ORIGIN); ceilingorigin = (mobj_t *) P_GetPtrp(sec, DMU_CEILING_SOUND_ORIGIN); S_StopSound(0, centerorigin); S_StopSound(0, floororigin); S_StopSound(0, ceilingorigin); switch(origin) { case SORG_FLOOR: S_StartSound(id, floororigin); break; case SORG_CEILING: S_StartSound(id, ceilingorigin); break; case SORG_CENTER: default: S_StartSound(id, centerorigin); break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_mobj.c0000644000175000017500000013435611357170242022560 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.c: Moving object handling. Spawn functions. */ // HEADER FILES ------------------------------------------------------------ #include #include "jheretic.h" #include "dmu_lib.h" #include "hu_stuff.h" #include "g_common.h" #include "p_map.h" #include "p_terraintype.h" #include "p_player.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ #define VANISHTICS (2*TICSPERSEC) #define MAX_BOB_OFFSET (8) #define NOMOMENTUM_THRESHOLD (0.000001f) #define WALKSTOP_THRESHOLD (0.062484741f) // FIX2FLT(0x1000-1) #define STANDSPEED (1.0f/2) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- mobjtype_t puffType; mobj_t *missileMobj; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- const terraintype_t* P_MobjGetFloorTerrainType(mobj_t* mo) { sector_t* sec = P_GetPtrp(mo->subsector, DMU_SECTOR); return P_GetPlaneMaterialType(sec, PLN_FLOOR); } /** * @return @c true, if the mobj is still present. */ boolean P_MobjChangeState(mobj_t* mobj, statenum_t state) { state_t* st; if(state == S_NULL) { // Remove mobj. mobj->state = (state_t *) S_NULL; P_MobjRemove(mobj, false); return false; } if(mobj->ddFlags & DDMF_REMOTE) { Con_Error("P_MobjChangeState: Can't set Remote state!\n"); } st = &STATES[state]; P_MobjSetState(mobj, state); mobj->turnTime = false; // $visangle-facetarget. if(st->action) { // Call action function. st->action(mobj); } return true; } /** * Same as P_MobjChangeState, but does not call the state function. */ boolean P_SetMobjStateNF(mobj_t *mobj, statenum_t state) { if(state == S_NULL) { // Remove mobj. mobj->state = (state_t *) S_NULL; P_MobjRemove(mobj, false); return false; } mobj->turnTime = false; // $visangle-facetarget P_MobjSetState(mobj, state); return true; } void P_ExplodeMissile(mobj_t *mo) { if(IS_CLIENT) { // Clients won't explode missiles. P_MobjChangeState(mo, S_NULL); return; } if(mo->type == MT_WHIRLWIND) { if(++mo->special2 < 60) { return; } } mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); if(mo->flags & MF_MISSILE) { mo->flags &= ~MF_MISSILE; mo->flags |= MF_VIEWALIGN; if(mo->flags & MF_BRIGHTEXPLODE) mo->flags |= MF_BRIGHTSHADOW; } if(mo->info->deathSound) { S_StartSound(mo->info->deathSound, mo); } } void P_FloorBounceMissile(mobj_t* mo) { mo->mom[MZ] = -mo->mom[MZ]; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); } void P_ThrustMobj(mobj_t* mo, angle_t angle, float move) { uint an = angle >> ANGLETOFINESHIFT; mo->mom[MX] += move * FIX2FLT(finecosine[an]); mo->mom[MY] += move * FIX2FLT(finesine[an]); } /** * @param delta The amount 'source' needs to turn. * * @return @c 1, = 'source' needs to turn clockwise, or * @c 0, = 'source' needs to turn counter clockwise. */ int P_FaceMobj(mobj_t* source, mobj_t* target, angle_t* delta) { angle_t diff, angle1, angle2; angle1 = source->angle; angle2 = R_PointToAngle2(source->pos[VX], source->pos[VY], target->pos[VX], target->pos[VY]); if(angle2 > angle1) { diff = angle2 - angle1; if(diff > ANGLE_180) { *delta = ANGLE_MAX - diff; return 0; } else { *delta = diff; return 1; } } else { diff = angle1 - angle2; if(diff > ANGLE_180) { *delta = ANGLE_MAX - diff; return 1; } else { *delta = diff; return 0; } } } /** * The missile tracer field must be the target. * * @return @c true, if target was tracked else @c false. */ boolean P_SeekerMissile(mobj_t* actor, angle_t thresh, angle_t turnMax) { int dir; uint an; float dist; angle_t delta; mobj_t* target; target = actor->tracer; if(target == NULL) return false; if(!(target->flags & MF_SHOOTABLE)) { // Target died. actor->tracer = NULL; return false; } dir = P_FaceMobj(actor, target, &delta); if(delta > thresh) { delta >>= 1; if(delta > turnMax) { delta = turnMax; } } if(dir) { // Turn clockwise. actor->angle += delta; } else { // Turn counter clockwise. actor->angle -= delta; } an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = actor->info->speed * FIX2FLT(finecosine[an]); actor->mom[MY] = actor->info->speed * FIX2FLT(finesine[an]); if(actor->pos[VZ] + actor->height < target->pos[VZ] || target->pos[VZ] + target->height < actor->pos[VZ]) { // Need to seek vertically. dist = P_ApproxDistance(target->pos[VX] - actor->pos[VX], target->pos[VY] - actor->pos[VY]); dist /= actor->info->speed; if(dist < 1) dist = 1; actor->mom[MZ] = (target->pos[VZ] - actor->pos[VZ]) / dist; } return true; } /** * Wind pushes the mobj, if its sector special is a wind type. */ void P_WindThrust(mobj_t *mo) { static int windTab[3] = { 2048 * 5, 2048 * 10, 2048 * 25 }; sector_t *sec = P_GetPtrp(mo->subsector, DMU_SECTOR); int special = P_ToXSector(sec)->special; switch(special) { case 40: // Wind_East case 41: case 42: P_ThrustMobj(mo, 0, FIX2FLT(windTab[special - 40])); break; case 43: // Wind_North case 44: case 45: P_ThrustMobj(mo, ANG90, FIX2FLT(windTab[special - 43])); break; case 46: // Wind_South case 47: case 48: P_ThrustMobj(mo, ANG270, FIX2FLT(windTab[special - 46])); break; case 49: // Wind_West case 50: case 51: P_ThrustMobj(mo, ANG180, FIX2FLT(windTab[special - 49])); break; default: break; } } float P_MobjGetFriction(mobj_t *mo) { if((mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && !mo->onMobj) { return FRICTION_FLY; } else { sector_t *sec = P_GetPtrp(mo->subsector, DMU_SECTOR); if(P_ToXSector(sec)->special == 15) { return FRICTION_LOW; } return XS_Friction(sec); } } static boolean isInWalkState(player_t* pl) { return pl->plr->mo->state - STATES - PCLASS_INFO(pl->class)->runState < 4; } static float getFriction(mobj_t* mo) { if((mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && !mo->onMobj) { // Airborne friction. return FRICTION_FLY; } #if __JHERETIC__ if(P_ToXSector(P_GetPtrp(mo->subsector, DMU_SECTOR))->special == 15) { // Friction_Low return FRICTION_LOW; } #endif return P_MobjGetFriction(mo); } void P_MobjMoveXY(mobj_t* mo) { float pos[2], mom[2]; player_t* player; boolean largeNegative; // $democam: cameramen have their own movement code if(P_CameraXYMovement(mo)) return; mom[MX] = MINMAX_OF(-MAXMOVE, mo->mom[MX], MAXMOVE); mom[MY] = MINMAX_OF(-MAXMOVE, mo->mom[MY], MAXMOVE); mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; if(mom[MX] == 0 && mom[MY] == 0) { if(mo->flags & MF_SKULLFLY) { // A flying mobj slammed into something. mo->flags &= ~MF_SKULLFLY; mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_SEE)); } return; } if(mo->flags2 & MF2_WINDTHRUST) P_WindThrust(mo); player = mo->player; do { /** * DOOM.exe bug fix: * Large negative displacements were never considered. This explains * the tendency for Mancubus fireballs to pass through walls. */ largeNegative = false; if(!cfg.moveBlock && (mom[MX] < -MAXMOVE / 2 || mom[MY] < -MAXMOVE / 2)) { // Make an exception for "north-only wallrunning". if(!(cfg.wallRunNorthOnly && mo->wallRun)) largeNegative = true; } if(largeNegative || mom[MX] > MAXMOVE / 2 || mom[MY] > MAXMOVE / 2) { pos[VX] = mo->pos[VX] + (mom[MX] /= 2); pos[VY] = mo->pos[VY] + (mom[MY] /= 2); } else { pos[VX] = mo->pos[VX] + mom[MX]; pos[VY] = mo->pos[VY] + mom[MY]; mom[MX] = mom[MY] = 0; } // If mobj was wallrunning - stop. if(mo->wallRun) mo->wallRun = false; // $dropoff_fix if(!P_TryMove(mo, pos[VX], pos[VY], true, false)) { // Blocked mom. if(mo->flags2 & MF2_SLIDE) { // Try to slide along it. P_SlideMove(mo); } else if(mo->flags & MF_MISSILE) { // Explode a missile sector_t* backSec; //// kludge: Prevent missiles exploding against the sky. if(ceilingLine && (backSec = P_GetPtrp(ceilingLine, DMU_BACK_SECTOR))) { if((P_GetIntp(P_GetPtrp(backSec, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] > P_GetFloatp(backSec, DMU_CEILING_HEIGHT)) { if(mo->type == MT_BLOODYSKULL) { mo->mom[MX] = mo->mom[MY] = 0; mo->mom[MZ] = -1; } else { P_MobjRemove(mo, false); } return; } } if(floorLine && (backSec = P_GetPtrp(floorLine, DMU_BACK_SECTOR))) { if((P_GetIntp(P_GetPtrp(backSec, DMU_FLOOR_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] < P_GetFloatp(backSec, DMU_FLOOR_HEIGHT)) { if(mo->type == MT_BLOODYSKULL) { mo->mom[MX] = mo->mom[MY] = 0; mo->mom[MZ] = -1; } else { P_MobjRemove(mo, false); } return; } } //// kludge end. P_ExplodeMissile(mo); } else { mo->mom[MX] = mo->mom[MY] = 0; } } } while(!INRANGE_OF(mom[MX], 0, NOMOMENTUM_THRESHOLD) || !INRANGE_OF(mom[MY], 0, NOMOMENTUM_THRESHOLD)); // Slow down. if(player && (P_GetPlayerCheats(player) & CF_NOMOMENTUM)) { // Debug option for no sliding at all mo->mom[MX] = mo->mom[MY] = 0; return; } if(mo->flags & (MF_MISSILE | MF_SKULLFLY)) { // No friction for missiles. return; } if(mo->pos[VZ] > mo->floorZ && !mo->onMobj && !(mo->flags2 & MF2_FLY)) { // No friction when falling. return; } if(cfg.slidingCorpses) { /** * $dropoff_fix: * Add objects falling off ledges. Does not apply to players! */ if(((mo->flags & MF_CORPSE) || (mo->intFlags & MIF_FALLING)) && !mo->player) { // Do not stop sliding. // If halfway off a step with some momentum. if(mo->mom[MX] > 1.0f / 4 || mo->mom[MX] < -1.0f / 4 || mo->mom[MY] > 1.0f / 4 || mo->mom[MY] < -1.0f / 4) { if(mo->floorZ != P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) return; } } } // Stop player walking animation. if((!player || (!(player->plr->cmd.forwardMove | player->plr->cmd.sideMove) && player->plr->mo != mo /* $voodoodolls: Stop animating. */)) && INRANGE_OF(mo->mom[MX], 0, WALKSTOP_THRESHOLD) && INRANGE_OF(mo->mom[MY], 0, WALKSTOP_THRESHOLD)) { // If in a walking frame, stop moving. if(player && isInWalkState(player) && player->plr->mo == mo) P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->normalState); // $voodoodolls: Do not zero mom! if(!(player && player->plr->mo != mo)) mo->mom[MX] = mo->mom[MY] = 0; // $voodoodolls: Stop view bobbing if this isn't a voodoo doll. if(player && player->plr->mo == mo) player->bob = 0; } else { float friction = getFriction(mo); mo->mom[MX] *= friction; mo->mom[MY] *= friction; } } void P_MobjMoveZ(mobj_t *mo) { float gravity; float dist; float delta; // $democam: cameramen get special z movement if(P_CameraZMovement(mo)) return; gravity = XS_Gravity(P_GetPtrp(mo->subsector, DMU_SECTOR)); // $voodoodolls: Check for smooth step up unless a voodoo doll. if(mo->player && mo->player->plr->mo == mo && mo->pos[VZ] < mo->floorZ) { mo->player->viewHeight -= mo->floorZ - mo->pos[VZ]; mo->player->viewHeightDelta = (cfg.plrViewHeight - mo->player->viewHeight) / 8; } // Adjust height. mo->pos[VZ] += mo->mom[MZ]; if((mo->flags2 & MF2_FLY) && mo->onMobj && mo->pos[VZ] > mo->onMobj->pos[VZ] + mo->onMobj->height) mo->onMobj = NULL; // We were on a mobj, we are NOT now. if((mo->flags & MF_FLOAT) && mo->target && !P_MobjIsCamera(mo->target)) { // Float down towards target if too close. if(!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) { dist = P_ApproxDistance(mo->pos[VX] - mo->target->pos[VX], mo->pos[VY] - mo->target->pos[VY]); delta = (mo->target->pos[VZ] + mo->target->height /2) - (mo->pos[VZ] + mo->height /2); if(dist < mo->radius + mo->target->radius && fabs(delta) < mo->height + mo->target->height) { // Don't go INTO the target. delta = 0; } if(delta < 0 && dist < -(delta * 3)) { mo->pos[VZ] -= FLOATSPEED; P_MobjSetSRVOZ(mo, -FLOATSPEED); } else if(delta > 0 && dist < (delta * 3)) { mo->pos[VZ] += FLOATSPEED; P_MobjSetSRVOZ(mo, FLOATSPEED); } } } // Do some fly-bobbing. if(mo->player && mo->player->plr->mo == mo && (mo->flags2 & MF2_FLY) && mo->pos[VZ] > mo->floorZ && !mo->onMobj && (mapTime & 2)) { mo->pos[VZ] += FIX2FLT(finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]); } // Clip movement. Another thing? if(mo->onMobj && mo->pos[VZ] <= mo->onMobj->pos[VZ] + mo->onMobj->height) { if(mo->mom[MZ] < 0) { if(mo->player && mo->mom[MZ] < -gravity * 8 && !(mo->flags2 & MF2_FLY)) { // Squat down. Decrease viewheight for a moment after // hitting the ground (hard), and utter appropriate sound. mo->player->viewHeightDelta = mo->mom[MZ] / 8; if(mo->player->health > 0) S_StartSound(SFX_PLROOF, mo); } mo->mom[MZ] = 0; } if(mo->mom[MZ] == 0) mo->pos[VZ] = mo->onMobj->pos[VZ] + mo->onMobj->height; if((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) { P_ExplodeMissile(mo); return; } } // The floor. if(mo->pos[VZ] <= mo->floorZ) { // Hit the floor. boolean movingDown; // Note (id): // somebody left this after the setting mom[MZ] to 0, // kinda useless there. // // cph - This was the a bug in the linuxdoom-1.10 source which // caused it not to sync Doom 2 v1.9 demos. Someone // added the above comment and moved up the following code. So // demos would desync in close lost soul fights. // Note that this only applies to original Doom 1 or Doom2 demos - not // Final Doom and Ultimate Doom. So we test demo_compatibility *and* // gamemission. (Note we assume that Doom1 is always Ult Doom, which // seems to hold for most published demos.) // // fraggle - cph got the logic here slightly wrong. There are three // versions of Doom 1.9: // // * The version used in registered doom 1.9 + doom2 - no bounce // * The version used in ultimate doom - has bounce // * The version used in final doom - has bounce // // So we need to check that this is either retail or commercial // (but not doom2) int correct_lost_soul_bounce = false; if(correct_lost_soul_bounce && (mo->flags & MF_SKULLFLY)) { // the skull slammed into something mo->mom[MZ] = -mo->mom[MZ]; } if(movingDown = (mo->mom[MZ] < 0)) { if(mo->player && mo->mom[MZ] < -gravity * 8 && !(mo->flags2 & MF2_FLY)) { // Squat down. Decrease viewheight for a moment after // hitting the ground hard and utter appropriate sound. mo->player->viewHeightDelta = mo->mom[MZ] / 8; #if __JHERETIC__ mo->player->jumpTics = 12; // Can't jump in a while. #endif // Fix DOOM bug - dead players grunting when hitting the ground // (e.g., after an archvile attack) if(mo->player->health > 0) S_StartSound(SFX_PLROOF, mo); } } mo->pos[VZ] = mo->floorZ; if(movingDown) P_HitFloor(mo); // cph 2001/05/26 - // See lost soul bouncing comment above. We need this here for bug // compatibility with original Doom2 v1.9 - if a soul is charging and // hit by a raising floor this incorrectly reverses its Y momentum. if(!correct_lost_soul_bounce && (mo->flags & MF_SKULLFLY)) mo->mom[MZ] = -mo->mom[MZ]; if((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) { if(mo->flags2 & MF2_FLOORBOUNCE) { P_FloorBounceMissile(mo); return; } #if __JHERETIC__ else if(mo->type == MT_MNTRFX2) { // Minotaur floor fire can go up steps return; } else #endif { P_ExplodeMissile(mo); return; } } if(movingDown && mo->mom[MZ] < 0) mo->mom[MZ] = 0; #if __JHERETIC__ { statenum_t state; if((state = P_GetState(mo->type, SN_CRASH)) != S_NULL && (mo->flags & MF_CORPSE)) { P_MobjChangeState(mo, state); return; } } #endif } else if(mo->flags2 & MF2_LOGRAV) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= gravity / 8; } else if(!(mo->flags & MF_NOGRAVITY)) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; } if(mo->pos[VZ] + mo->height > mo->ceilingZ) { // hit the ceiling if(mo->mom[MZ] > 0) mo->mom[MZ] = 0; mo->pos[VZ] = mo->ceilingZ - mo->height; if(mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->mom[MZ] = -mo->mom[MZ]; } if((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) { if(P_GetIntp(P_GetPtrp(mo->subsector, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) { #if __JHERETIC__ if(mo->type == MT_BLOODYSKULL) { mo->mom[MX] = mo->mom[MY] = 0; mo->mom[MZ] = -1; } else #endif // Don't explode against sky. { P_MobjRemove(mo, false); } return; } P_ExplodeMissile(mo); return; } } } void P_NightmareRespawn(mobj_t* mobj) { mobj_t* mo; // Something is occupying it's position? if(!P_CheckPosition2f(mobj, mobj->spawnSpot.pos[VX], mobj->spawnSpot.pos[VY])) return; // No respwan. if((mo = P_SpawnMobj3fv(mobj->type, mobj->spawnSpot.pos, mobj->spawnSpot.angle, mobj->spawnSpot.flags))) { mo->reactionTime = 18; // Spawn a teleport fog at old spot because of removal of the body? if((mo = P_SpawnMobj3f(MT_TFOG, mobj->pos[VX], mobj->pos[VY], TELEFOGHEIGHT, mobj->angle, MSF_Z_FLOOR))) S_StartSound(SFX_TELEPT, mo); // Spawn a teleport fog at the new spot. if((mo = P_SpawnMobj3f(MT_TFOG, mobj->spawnSpot.pos[VX], mobj->spawnSpot.pos[VY], TELEFOGHEIGHT, mobj->spawnSpot.angle, MSF_Z_FLOOR))) S_StartSound(SFX_TELEPT, mo); } // Remove the old monster. P_MobjRemove(mobj, true); } void P_MobjThinker(mobj_t *mobj) { if(mobj->ddFlags & DDMF_REMOTE) return; // Remote mobjs are handled separately. if(mobj->type == MT_BLASTERFX1) { int i; float frac[3]; float z; boolean changexy; // Handle movement if(mobj->mom[MX] != 0 || mobj->mom[MY] != 0 || mobj->mom[MZ] != 0 || (mobj->pos[VZ] != mobj->floorZ)) { frac[MX] = mobj->mom[MX] / 8; frac[MY] = mobj->mom[MY] / 8; frac[MZ] = mobj->mom[MZ] / 8; changexy = (frac[MX] != 0 || frac[MY] != 0); for(i = 0; i < 8; ++i) { if(changexy) { if(!P_TryMove(mobj, mobj->pos[VX] + frac[MX], mobj->pos[VY] + frac[MY], false, false)) { // Blocked move. P_ExplodeMissile(mobj); return; } } mobj->pos[VZ] += frac[MZ]; if(mobj->pos[VZ] <= mobj->floorZ) { // Hit the floor. mobj->pos[VZ] = mobj->floorZ; P_HitFloor(mobj); P_ExplodeMissile(mobj); return; } if(mobj->pos[VZ] + mobj->height > mobj->ceilingZ) { // Hit the ceiling. mobj->pos[VZ] = mobj->ceilingZ - mobj->height; P_ExplodeMissile(mobj); return; } if(changexy && (P_Random() < 64)) { z = mobj->pos[VZ] - 8; if(z < mobj->floorZ) { z = mobj->floorZ; } P_SpawnMobj3f(MT_BLASTERSMOKE, mobj->pos[VX], mobj->pos[VY], z, P_Random() << 24, 0); } } } // Advance the state. if(mobj->tics != -1) { mobj->tics--; while(!mobj->tics) { if(!P_MobjChangeState(mobj, mobj->state->nextState)) { // Mobj was removed. return; } } } return; } #if __JDOOM__ // Spectres get selector = 1. if(mobj->type == MT_SHADOWS) mobj->selector = (mobj->selector & ~DDMOBJ_SELECTOR_MASK) | 1; #endif // The first three bits of the selector special byte contain a relative // health level. P_UpdateHealthBits(mobj); // Handle X and Y momentums. if(mobj->mom[MX] != 0 || mobj->mom[MY] != 0 || (mobj->flags & MF_SKULLFLY)) { P_MobjMoveXY(mobj); //// \fixme decent NOP/NULL/Nil function pointer please. if(mobj->thinker.function == NOPFUNC) return; // Mobj was removed. } if(mobj->flags2 & MF2_FLOATBOB) { // Floating item bobbing motion. // Keep it on the floor. mobj->pos[VZ] = mobj->floorZ; // Negative floorclip raises the mobj off the floor. mobj->floorClip = -mobj->special1; if(mobj->floorClip < -MAX_BOB_OFFSET) { // We don't want it going through the floor. mobj->floorClip = -MAX_BOB_OFFSET; } } else if(mobj->pos[VZ] != mobj->floorZ || mobj->mom[MZ] != 0) { P_MobjMoveZ(mobj); if(mobj->thinker.function != P_MobjThinker) return; // mobj was removed } // Non-sentient objects at rest. else if(!(mobj->mom[MX] != 0 || mobj->mom[MY] != 0) && !sentient(mobj) && !(mobj->player) && !((mobj->flags & MF_CORPSE) && cfg.slidingCorpses)) { /** * Objects fall off ledges if they are hanging off slightly push off * of ledge if hanging more than halfway off. */ if(mobj->pos[VZ] > mobj->dropOffZ && // Only objects contacting dropoff !(mobj->flags & MF_NOGRAVITY) && cfg.fallOff) { P_ApplyTorque(mobj); } else { mobj->intFlags &= ~MIF_FALLING; mobj->gear = 0; // Reset torque. } } if(cfg.slidingCorpses) { if(((mobj->flags & MF_CORPSE) ? mobj->pos[VZ] > mobj->dropOffZ : mobj->pos[VZ] - mobj->dropOffZ > 24) && // Only objects contacting drop off. !(mobj->flags & MF_NOGRAVITY)) // Only objects which fall. { P_ApplyTorque(mobj); // Apply torque. } else { mobj->intFlags &= ~MIF_FALLING; mobj->gear = 0; // Reset torque. } } // $vanish: dead monsters disappear after some time. if(cfg.corpseTime && (mobj->flags & MF_CORPSE) && mobj->corpseTics != -1) { if(++mobj->corpseTics < cfg.corpseTime * TICSPERSEC) { mobj->translucency = 0; // Opaque. } else if(mobj->corpseTics < cfg.corpseTime * TICSPERSEC + VANISHTICS) { // Translucent during vanishing. mobj->translucency = ((mobj->corpseTics - cfg.corpseTime * TICSPERSEC) * 255) / VANISHTICS; } else { // Too long; get rid of the corpse. mobj->corpseTics = -1; return; } } // Cycle through states, calling action functions at transitions. if(mobj->tics != -1) { mobj->tics--; P_MobjAngleSRVOTicker(mobj); // "angle-servo"; smooth actor turning. // You can cycle through multiple states in a tic. if(!mobj->tics) { P_MobjClearSRVO(mobj); if(!P_MobjChangeState(mobj, mobj->state->nextState)) return; // Freed itself. } } else if(!IS_CLIENT) { // Check for nightmare respawn. if(!(mobj->flags & MF_COUNTKILL)) return; if(!respawnMonsters) return; mobj->moveCount++; if(mobj->moveCount < 12 * 35) return; if(mapTime & 31) return; if(P_Random() > 4) return; P_NightmareRespawn(mobj); } } /** * Spawns a mobj of "type" at the specified position. */ mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags) { mobj_t* mo; mobjinfo_t* info; float space; int ddflags = 0; if(type < MT_FIRST || type >= Get(DD_NUMMOBJTYPES)) { #ifdef _DEBUG Con_Error("P_SpawnMobj: Illegal mo type %i.\n", type); #endif return NULL; } info = &MOBJINFO[type]; // Clients only spawn local objects. if(!(info->flags & MF_LOCAL) && IS_CLIENT) return NULL; // Not for deathmatch? if(deathmatch && (info->flags & MF_NOTDMATCH)) return NULL; // Check for specific disabled objects. switch(type) { case MT_WSKULLROD: case MT_WPHOENIXROD: case MT_AMSKRDWIMPY: case MT_AMSKRDHEFTY: case MT_AMPHRDWIMPY: case MT_AMPHRDHEFTY: case MT_AMMACEWIMPY: case MT_AMMACEHEFTY: case MT_ARTISUPERHEAL: case MT_ARTITELEPORT: case MT_ITEMSHIELD2: if(gameMode == shareware) { // Don't place on map in shareware version. return NULL; } break; default: break; } // Don't spawn any monsters if -noMonstersParm. if(noMonstersParm && (info->flags & MF_COUNTKILL)) return NULL; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; mo = P_MobjCreate(P_MobjThinker, x, y, z, angle, info->radius, info->height, ddflags); mo->type = type; mo->info = info; mo->flags = info->flags; mo->flags2 = info->flags2; mo->flags3 = info->flags3; mo->damage = info->damage; mo->health = info->spawnHealth * (IS_NETGAME ? cfg.netMobHealthModifier : 1); mo->moveDir = DI_NODIR; if(gameSkill != SM_NIGHTMARE) mo->reactionTime = info->reactionTime; mo->lastLook = P_Random() % MAXPLAYERS; // Must link before setting state (ID assigned for the mo). P_MobjSetState(mo, P_GetState(mo->type, SN_SPAWN)); if(mo->type == MT_MACEFX1 || mo->type == MT_MACEFX2 || mo->type == MT_MACEFX3) mo->special3 = 1000; // Set subsector and/or block links. P_MobjSetPosition(mo); mo->floorZ = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); mo->dropOffZ = mo->floorZ; mo->ceilingZ = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); if((spawnFlags & MSF_Z_CEIL) || (info->flags & MF_SPAWNCEILING)) { mo->pos[VZ] = mo->ceilingZ - mo->info->height - z; } else if((spawnFlags & MSF_Z_RANDOM) || (info->flags2 & MF2_SPAWNFLOAT)) { space = mo->ceilingZ - mo->info->height - mo->floorZ; if(space > 48) { space -= 40; mo->pos[VZ] = ((space * P_Random()) / 256) + mo->floorZ + 40; } else { mo->pos[VZ] = mo->floorZ; } } else if(spawnFlags & MSF_Z_FLOOR) { mo->pos[VZ] = mo->floorZ + z; } if(spawnFlags & MSF_AMBUSH) mo->flags |= MF_AMBUSH; mo->floorClip = 0; if((mo->flags2 & MF2_FLOORCLIP) && mo->pos[VZ] == P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } // Copy spawn attributes to the new mobj. mo->spawnSpot.pos[VX] = x; mo->spawnSpot.pos[VY] = y; mo->spawnSpot.pos[VZ] = z; mo->spawnSpot.angle = angle; mo->spawnSpot.flags = spawnFlags; return mo; } mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags) { return P_SpawnMobj3f(type, pos[VX], pos[VY], pos[VZ], angle, spawnFlags); } /** * Chooses the next spot to place the mace. */ void P_RepositionMace(mobj_t* mo) { int spot; subsector_t* ss; P_MobjUnsetPosition(mo); spot = P_Random() % maceSpotCount; mo->pos[VX] = maceSpots[spot].pos[VX]; mo->pos[VY] = maceSpots[spot].pos[VY]; ss = R_PointInSubsector(mo->pos[VX], mo->pos[VY]); mo->floorZ = P_GetFloatp(ss, DMU_CEILING_HEIGHT); mo->pos[VZ] = mo->floorZ; mo->ceilingZ = P_GetFloatp(ss, DMU_CEILING_HEIGHT); P_MobjSetPosition(mo); } void P_SpawnPuff(float x, float y, float z, angle_t angle) { mobj_t* puff; // Clients do not spawn puffs. if(IS_CLIENT) return; z += FIX2FLT((P_Random() - P_Random()) << 10); if((puff = P_SpawnMobj3f(puffType, x, y, z, angle, 0))) { if(puff->info->attackSound) { S_StartSound(puff->info->attackSound, puff); } switch(puffType) { case MT_BEAKPUFF: case MT_STAFFPUFF: puff->mom[MZ] = 1; break; case MT_GAUNTLETPUFF1: case MT_GAUNTLETPUFF2: puff->mom[MZ] = .8f; default: break; } } } void P_SpawnBloodSplatter(float x, float y, float z, mobj_t* originator) { mobj_t* mo; if((mo = P_SpawnMobj3f(MT_BLOODSPLATTER, x, y, z, P_Random() << 24, 0))) { mo->target = originator; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MZ] = 2; } } #define SMALLSPLASHCLIP 12; /** * @return @c true, if mobj contacted a non-solid floor. */ boolean P_HitFloor(mobj_t* thing) { mobj_t* mo; const terraintype_t* tt; if(thing->floorZ != P_GetFloatp(thing->subsector, DMU_FLOOR_HEIGHT)) { // Don't splash if landing on the edge above water/lava/etc.... return false; } // Things that don't splash go here. switch(thing->type) { case MT_LAVASMOKE: case MT_SPLASH: case MT_SLUDGECHUNK: return false; default: if(P_MobjIsCamera(thing)) return false; break; } tt = P_MobjGetFloorTerrainType(thing); if(tt->flags & TTF_SPAWN_SPLASHES) { if((mo = P_SpawnMobj3f(MT_SPLASHBASE, thing->pos[VX], thing->pos[VY], 0, thing->angle + ANG180, MSF_Z_FLOOR))) mo->floorClip += SMALLSPLASHCLIP; if((mo = P_SpawnMobj3f(MT_SPLASH, thing->pos[VX], thing->pos[VY], 0, thing->angle, MSF_Z_FLOOR))) { mo->target = thing; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MZ] = 2 + FIX2FLT(P_Random() << 8); S_StartSound(SFX_GLOOP, mo); } return true; } else if(tt->flags & TTF_SPAWN_SMOKE) { if((mo = P_SpawnMobj3f(MT_LAVASPLASH, thing->pos[VX], thing->pos[VY], 0, thing->angle + ANG180, MSF_Z_FLOOR))) mo->floorClip += SMALLSPLASHCLIP; if((mo = P_SpawnMobj3f(MT_LAVASMOKE, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR))) { mo->mom[MZ] = 1 + FIX2FLT((P_Random() << 7)); S_StartSound(SFX_BURN, mo); } return true; } else if(tt->flags & TTF_SPAWN_SLUDGE) { if((mo = P_SpawnMobj3f(MT_SLUDGESPLASH, thing->pos[VX], thing->pos[VY], 0, thing->angle + ANG180, MSF_Z_FLOOR))) mo->floorClip += SMALLSPLASHCLIP; if((mo = P_SpawnMobj3f(MT_SLUDGECHUNK, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR))) { mo->target = thing; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MZ] = 1 + FIX2FLT(P_Random() << 8); } return true; } return false; } /** * @return @c true, if the missile is at a valid spawn point, * otherwise; explode it and return @false. */ boolean P_CheckMissileSpawn(mobj_t *missile) { // Move a little forward so an angle can be computed if it immediately // explodes if(missile->type == MT_BLASTERFX1) { // Ultra-fast ripper spawning missile. missile->pos[VX] += missile->mom[MX] / 8; missile->pos[VY] += missile->mom[MY] / 8; missile->pos[VZ] += missile->mom[MZ] / 8; } else { missile->pos[VX] += missile->mom[MX] / 2; missile->pos[VY] += missile->mom[MY] / 2; missile->pos[VZ] += missile->mom[MZ] / 2; } if(!P_TryMove(missile, missile->pos[VX], missile->pos[VY], false, false)) { P_ExplodeMissile(missile); return false; } return true; } /** * Tries to aim at a nearby monster if source is a player. Else aim is * taken at dest. * * @param source The mobj doing the shooting. * @param dest The mobj being shot at. Can be @c NULL if source * is a player. * @param type The type of mobj to be shot. * @param checkSpawn @c true call P_CheckMissileSpawn. * * @return Pointer to the newly spawned missile. */ mobj_t* P_SpawnMissile(mobjtype_t type, mobj_t* source, mobj_t* dest, boolean checkSpawn) { float pos[3]; mobj_t* th = 0; unsigned int an = 0; angle_t angle = 0; float dist = 0; float slope = 0; float spawnZOff = 0; int spawnFlags = 0; memcpy(pos, source->pos, sizeof(pos)); if(source->player) { // see which target is to be aimed at angle = source->angle; slope = P_AimLineAttack(source, angle, 16 * 64); if(!cfg.noAutoAim) if(!lineTarget) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget) { angle = source->angle; slope = tan(LOOKDIR2RAD(source->dPlayer->lookDir)) / 1.2f; } } if(!P_MobjIsCamera(source->player->plr->mo)) spawnZOff = cfg.plrViewHeight - 9 + source->player->plr->lookDir / 173; } else { // Type specific offset to spawn height z. switch(type) { case MT_MNTRFX1: // Minotaur swing attack missile. spawnZOff = 40; break; case MT_SRCRFX1: // Sorcerer Demon fireball. spawnZOff = 48; break; case MT_KNIGHTAXE: // Knight normal axe. case MT_REDAXE: // Knight red power axe. spawnZOff = 36; break; case MT_MNTRFX2: spawnZOff = 0; break; default: spawnZOff = 32; break; } } if(type == MT_MNTRFX2) // always exactly on the floor. { pos[VZ] = 0; spawnFlags |= MSF_Z_FLOOR; } else { pos[VZ] += spawnZOff; pos[VZ] -= source->floorClip; } if(!source->player) { angle = R_PointToAngle2(pos[VX], pos[VY], dest->pos[VX], dest->pos[VY]); // Fuzzy player. if(dest->flags & MF_SHADOW) angle += (P_Random() - P_Random()) << 21; // note << 20 in jDoom } if(!(th = P_SpawnMobj3fv(type, pos, angle, spawnFlags))) return NULL; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Where it came from. an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); if(source->player) { th->mom[MZ] = th->info->speed * slope; } else { dist = P_ApproxDistance(dest->pos[VX] - pos[VX], dest->pos[VY] - pos[VY]); dist /= th->info->speed; if(dist < 1) dist = 1; th->mom[MZ] = (dest->pos[VZ] - source->pos[VZ]) / dist; } // Make sure the speed is right (in 3D). dist = P_ApproxDistance(P_ApproxDistance(th->mom[MX], th->mom[MY]), th->mom[MZ]); if(!dist) dist = 1; dist = th->info->speed / dist; th->mom[MX] *= dist; th->mom[MY] *= dist; th->mom[MZ] *= dist; #if __JHERETIC__ //// \kludge Set this global ptr as we need access to the mobj even if it //// explodes instantly in order to assign values to it. //// This is a bit of a kludge really... missileMobj = th; #endif if(checkSpawn) return (P_CheckMissileSpawn(th)? th : NULL); return th; } /** * Tries to aim at a nearby monster if 'source' is a player. Else aim is * the angle of the source mobj. Z angle is specified with momZ. * * @param type The type of mobj to be shot. * @param source The mobj doing the shooting. * @param angle The X/Y angle to shoot the missile in. * @param momZ The Z momentum of the missile to be spawned. * * @return Pointer to the newly spawned missile. */ mobj_t *P_SpawnMissileAngle(mobjtype_t type, mobj_t *source, angle_t mangle, float momZ) { float pos[3]; mobj_t *th = 0; unsigned int an = 0; angle_t angle = 0; float dist = 0; float slope = 0; float spawnZOff = 0; int spawnFlags = 0; memcpy(pos, source->pos, sizeof(pos)); angle = mangle; if(source->player) { // Try to find a target. slope = P_AimLineAttack(source, angle, 16 * 64); if(!cfg.noAutoAim) if(!lineTarget) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget) { angle = mangle; slope = tan(LOOKDIR2RAD(source->dPlayer->lookDir)) / 1.2f; } } if(!(source->player->plr->flags & DDPF_CAMERA)) spawnZOff = cfg.plrViewHeight - 9 + (source->player->plr->lookDir) / 173; } else { // Type specific offset to spawn height z. switch(type) { case MT_MNTRFX1: // Minotaur swing attack missile. spawnZOff = 40; break; case MT_SRCRFX1: // Sorcerer Demon fireball. spawnZOff = 48; break; case MT_KNIGHTAXE: // Knight normal axe. case MT_REDAXE: // Knight red power axe. spawnZOff = 36; break; default: spawnZOff = 32; break; } } if(type == MT_MNTRFX2) // Always exactly on the floor. { spawnFlags |= MSF_Z_FLOOR; } else { pos[VZ] += spawnZOff; pos[VZ] -= source->floorClip; } if(!(th = P_SpawnMobj3fv(type, pos, angle, spawnFlags))) return NULL; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Where it came from. an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); if(source->player && momZ == -12345) { th->mom[MZ] = th->info->speed * slope; // Make sure the speed is right (in 3D). dist = P_ApproxDistance(P_ApproxDistance(th->mom[MX], th->mom[MY]), th->mom[MZ]); if(dist < 1) dist = 1; dist = th->info->speed / dist; th->mom[MX] *= dist; th->mom[MY] *= dist; th->mom[MZ] *= dist; } else { th->mom[MZ] = momZ; } #if __JHERETIC__ //// \kludge Set this global ptr as we need access to the mobj even if it //// explodes instantly in order to assign values to it. //// This is a bit of a kludge really... missileMobj = th; #endif if(P_CheckMissileSpawn(th)) return th; return NULL; } void C_DECL A_ContMobjSound(mobj_t *actor) { switch(actor->type) { case MT_KNIGHTAXE: S_StartSound(SFX_KGTATK, actor); break; case MT_MUMMYFX1: S_StartSound(SFX_MUMHED, actor); break; default: break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/st_stuff.c0000644000175000017500000011441311357170242023137 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.c: Statusbar code. */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "d_net.h" #include "st_lib.h" #include "hu_stuff.h" #include "p_tick.h" // for P_IsPaused #include "p_player.h" #include "am_map.h" #include "hu_inventory.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // Current ammo icon(sbbar). #define ST_AMMOIMGWIDTH (24) #define ST_AMMOICONX (111) #define ST_AMMOICONY (172) // Inventory. #define ST_INVENTORYX (50) #define ST_INVENTORYY (160) // Current inventory item. #define ST_INVITEMX (179) #define ST_INVITEMY (160) // Current inventory item count. #define ST_INVITEMCWIDTH (2) // Num digits #define ST_INVITEMCX (208) #define ST_INVITEMCY (182) // AMMO number pos. #define ST_AMMOWIDTH (3) #define ST_AMMOX (135) #define ST_AMMOY (162) // ARMOR number pos. #define ST_ARMORWIDTH (3) #define ST_ARMORX (254) #define ST_ARMORY (170) // HEALTH number pos. #define ST_HEALTHWIDTH (3) #define ST_HEALTHX (85) #define ST_HEALTHY (170) // Key icon positions. #define ST_KEY0WIDTH (10) #define ST_KEY0HEIGHT (6) #define ST_KEY0X (153) #define ST_KEY0Y (164) #define ST_KEY1WIDTH (ST_KEY0WIDTH) #define ST_KEY1X (153) #define ST_KEY1Y (172) #define ST_KEY2WIDTH (ST_KEY0WIDTH) #define ST_KEY2X (153) #define ST_KEY2Y (180) // Frags pos. #define ST_FRAGSX (85) #define ST_FRAGSY (171) #define ST_FRAGSWIDTH (2) // TYPES ------------------------------------------------------------------- typedef struct { boolean stopped; int hideTics; float hideAmount; float showBar; // Slide statusbar amount 1.0 is fully open. float alpha; // Fullscreen hud alpha value. float statusbarCounterAlpha; boolean firstTime; // ST_Start() has just been called. boolean statusbarActive; // Whether left-side main status bar is active. boolean hitCenterFrame; int currentInvItemFlash; int currentAmmoIconIdx; // Current ammo icon index. boolean keyBoxes[3]; // Holds key-type for each key box on bar. int fragsCount; // Number of frags so far in deathmatch. boolean blended; // Whether to use alpha blending. int tomePlay; int healthMarker; int chainWiggle; int oldAmmoIconIdx; int oldReadyWeapon; int oldHealth; // Widgets: st_multiicon_t wCurrentAmmoIcon; // Current ammo icon. st_number_t wReadyWeapon; // Ready-weapon. st_number_t wFrags; // In deathmatch only, summary of frags stats. st_number_t wHealth; // Health. st_number_t wArmor; // Armor. st_icon_t wKeyBoxes[3]; // Owned keys. } hudstate_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // Console commands for the HUD/Statusbar. DEFCC(CCmdStatusBarSize); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void drawINumber(signed int val, int x, int y, float r, float g, float b, float a); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static hudstate_t hudStates[MAXPLAYERS]; static dpatch_t statusbar; static dpatch_t statusbarTopLeft; static dpatch_t statusbarTopRight; static dpatch_t chain; static dpatch_t statBar; static dpatch_t lifeBar; static dpatch_t invBar; static dpatch_t lifeGems[4]; static dpatch_t iNumbers[10]; static dpatch_t negative; static dpatch_t ammoIcons[11]; static dpatch_t dpInvItemFlash[5]; static dpatch_t spinBook[16]; static dpatch_t spinFly[16]; static dpatch_t keys[NUM_KEY_TYPES]; static dpatch_t godLeft; static dpatch_t godRight; static dpatch_t lame; // CVARs for the HUD/Statusbar cvar_t sthudCVars[] = { // HUD scale {"hud-scale", 0, CVT_FLOAT, &cfg.hudScale, 0.1f, 10}, {"hud-status-size", CVF_PROTECTED, CVT_INT, &cfg.statusbarScale, 1, 20}, // HUD colour + alpha {"hud-color-r", 0, CVT_FLOAT, &cfg.hudColor[0], 0, 1}, {"hud-color-g", 0, CVT_FLOAT, &cfg.hudColor[1], 0, 1}, {"hud-color-b", 0, CVT_FLOAT, &cfg.hudColor[2], 0, 1}, {"hud-color-a", 0, CVT_FLOAT, &cfg.hudColor[3], 0, 1}, {"hud-icon-alpha", 0, CVT_FLOAT, &cfg.hudIconAlpha, 0, 1}, {"hud-status-alpha", 0, CVT_FLOAT, &cfg.statusbarOpacity, 0, 1}, {"hud-status-icon-a", 0, CVT_FLOAT, &cfg.statusbarCounterAlpha, 0, 1}, // HUD icons {"hud-ammo", 0, CVT_BYTE, &cfg.hudShown[HUD_AMMO], 0, 1}, {"hud-armor", 0, CVT_BYTE, &cfg.hudShown[HUD_ARMOR], 0, 1}, {"hud-keys", 0, CVT_BYTE, &cfg.hudShown[HUD_KEYS], 0, 1}, {"hud-health", 0, CVT_BYTE, &cfg.hudShown[HUD_HEALTH], 0, 1}, {"hud-currentitem", 0, CVT_BYTE, &cfg.hudShown[HUD_CURRENTITEM], 0, 1}, // HUD displays {"hud-tome-timer", CVF_NO_MAX, CVT_INT, &cfg.tomeCounter, 0, 0}, {"hud-tome-sound", CVF_NO_MAX, CVT_INT, &cfg.tomeSound, 0, 0}, {"hud-timer", 0, CVT_FLOAT, &cfg.hudTimer, 0, 60}, {"hud-unhide-damage", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_DAMAGE], 0, 1}, {"hud-unhide-pickup-health", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_HEALTH], 0, 1}, {"hud-unhide-pickup-armor", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_ARMOR], 0, 1}, {"hud-unhide-pickup-powerup", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_POWER], 0, 1}, {"hud-unhide-pickup-weapon", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_WEAPON], 0, 1}, {"hud-unhide-pickup-ammo", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_AMMO], 0, 1}, {"hud-unhide-pickup-key", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_KEY], 0, 1}, {"hud-unhide-pickup-invitem", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_INVITEM], 0, 1}, {NULL} }; // Console commands for the HUD/Status bar ccmd_t sthudCCmds[] = { {"sbsize", "s", CCmdStatusBarSize}, {NULL} }; // CODE -------------------------------------------------------------------- /** * Register CVARs and CCmds for the HUD/Status bar */ void ST_Register(void) { int i; for(i = 0; sthudCVars[i].name; ++i) Con_AddVariable(sthudCVars + i); for(i = 0; sthudCCmds[i].name; ++i) Con_AddCommand(sthudCCmds + i); Hu_InventoryRegister(); } static void shadeChain(float alpha) { DGL_Disable(DGL_TEXTURING); DGL_Begin(DGL_QUADS); // Left shadow. DGL_Color4f(0, 0, 0, alpha); DGL_Vertex2f(20, 200); DGL_Vertex2f(20, 190); DGL_Color4f(0, 0, 0, 0); DGL_Vertex2f(35, 190); DGL_Vertex2f(35, 200); // Right shadow. DGL_Vertex2f(277, 200); DGL_Vertex2f(277, 190); DGL_Color4f(0, 0, 0, alpha); DGL_Vertex2f(293, 190); DGL_Vertex2f(293, 200); DGL_End(); DGL_Enable(DGL_TEXTURING); } static void drawChain(hudstate_t* hud) { static int theirColors[] = { 144, // Green. 197, // Yellow. 150, // Red. 220 // Blue. }; int chainY; float healthPos, gemXOffset, gemglow; int x, y, w, h, gemNum; float cw, rgb[3]; int player = hud - hudStates; player_t* plr = &players[player]; hud->oldHealth = hud->healthMarker; chainY = 191; if(hud->healthMarker != plr->plr->mo->health) chainY += hud->chainWiggle; healthPos = MINMAX_OF(0, hud->healthMarker / 100.f, 1); if(!IS_NETGAME) gemNum = 2; // Always use the red gem in single player. else gemNum = cfg.playerColor[player]; gemglow = healthPos; // Draw the chain. x = 21; y = chainY; w = ST_WIDTH - 21 - 28; h = 8; cw = (float) w / chain.width; DGL_SetPatch(chain.lump, DGL_REPEAT, DGL_CLAMP); DGL_Color4f(1, 1, 1, hud->statusbarCounterAlpha); gemXOffset = (w - lifeGems[gemNum].width) * healthPos; if(gemXOffset > 0) { // Left chain section. float cw = gemXOffset / chain.width; DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 1 - cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(x + gemXOffset, y); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(x + gemXOffset, y + h); DGL_TexCoord2f(0, 1 - cw, 1); DGL_Vertex2f(x, y + h); DGL_End(); } if(gemXOffset + lifeGems[gemNum].width < w) { // Right chain section. float cw = (w - gemXOffset - lifeGems[gemNum].width) / chain.width; DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(x + gemXOffset + lifeGems[gemNum].width, y); DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(x + gemXOffset + lifeGems[gemNum].width, y + h); DGL_End(); } // Draw the life gem. GL_DrawPatchLitAlpha(x + gemXOffset, chainY, 1, hud->statusbarCounterAlpha, lifeGems[gemNum].lump); shadeChain((hud->statusbarCounterAlpha + cfg.statusbarOpacity) /3); // How about a glowing gem? DGL_BlendMode(BM_ADD); DGL_Bind(Get(DD_DYNLIGHT_TEXTURE)); R_GetColorPaletteRGBf(0, rgb, theirColors[gemNum], false); DGL_DrawRect(x + gemXOffset - 11, chainY - 6, 41, 24, rgb[0], rgb[1], rgb[2], gemglow - (1 - hud->statusbarCounterAlpha)); DGL_BlendMode(BM_NORMAL); DGL_Color4f(1, 1, 1, 1); } /** * Draws the whole statusbar backgound. * \todo There is a whole lot of constants in here. What if someone wants to * replace the statusbar with new patches? */ static void drawStatusBarBackground(int player) { hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; float alpha; if(hud->blended) { alpha = cfg.statusbarOpacity - hud->hideAmount; if(!(alpha > 0)) return; alpha = MINMAX_OF(0.f, alpha, 1.f); } else alpha = 1.0f; if(!(alpha < 1)) { // We can just render the full thing as normal. // Top bits. GL_DrawPatch(0, 148, statusbarTopLeft.lump); GL_DrawPatch(290, 148, statusbarTopRight.lump); // Faces. GL_DrawPatch(0, 158, statusbar.lump); if(P_GetPlayerCheats(plr) & CF_GODMODE) { GL_DrawPatch(16, 167, godLeft.lump); GL_DrawPatch(287, 167, godRight.lump); } if(!Hu_InventoryIsOpen(player)) { if(deathmatch) GL_DrawPatch(34, 160, statBar.lump); else GL_DrawPatch(34, 160, lifeBar.lump); } else { GL_DrawPatch(34, 160, invBar.lump); } } else { DGL_Color4f(1, 1, 1, alpha); // Top bits. GL_DrawPatch_CS(0, 148, statusbarTopLeft.lump); GL_DrawPatch_CS(290, 148, statusbarTopRight.lump); DGL_SetPatch(statusbar.lump, DGL_REPEAT, DGL_REPEAT); // Top border. DGL_DrawCutRectTiled(34, 158, 248, 2, 320, 42, 34, 0, 0, 158, 0, 0); // Chain background. DGL_DrawCutRectTiled(34, 191, 248, 9, 320, 42, 34, 33, 0, 191, 16, 8); // Faces. if(P_GetPlayerCheats(plr) & CF_GODMODE) { // If GOD mode we need to cut windows DGL_DrawCutRectTiled(0, 158, 34, 42, 320, 42, 0, 0, 16, 167, 16, 8); DGL_DrawCutRectTiled(282, 158, 38, 42, 320, 42, 282, 0, 287, 167, 16, 8); GL_DrawPatch_CS(16, 167, godLeft.lump); GL_DrawPatch_CS(287, 167, godRight.lump); } else { DGL_DrawCutRectTiled(0, 158, 34, 42, 320, 42, 0, 0, 0, 158, 0, 0); DGL_DrawCutRectTiled(282, 158, 38, 42, 320, 42, 282, 0, 0, 158, 0, 0); } if(!Hu_InventoryIsOpen(player)) { if(deathmatch) GL_DrawPatch_CS(34, 160, statBar.lump); else GL_DrawPatch_CS(34, 160, lifeBar.lump); } else { GL_DrawPatch_CS(34, 160, invBar.lump); } } } void ST_updateWidgets(int player) { static int largeammo = 1994; // Means "n/a". int i; ammotype_t ammoType; boolean found; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; int lvl = (plr->powers[PT_WEAPONLEVEL2]? 1 : 0); if(hud->blended) { hud->statusbarCounterAlpha = MINMAX_OF(0.f, cfg.statusbarCounterAlpha - hud->hideAmount, 1.f); } else hud->statusbarCounterAlpha = 1.0f; // Must redirect the pointer if the ready weapon has changed. found = false; for(ammoType = 0; ammoType < NUM_AMMO_TYPES && !found; ++ammoType) { if(!weaponInfo[plr->readyWeapon][plr->class].mode[lvl].ammoType[ammoType]) continue; // Weapon does not use this type of ammo. //// \todo Only supports one type of ammo per weapon. hud->wReadyWeapon.num = &plr->ammo[ammoType].owned; if(hud->oldReadyWeapon != plr->readyWeapon) hud->currentAmmoIconIdx = (int) ammoType; found = true; } if(!found) // Weapon takes no ammo at all. { hud->wReadyWeapon.num = &largeammo; hud->currentAmmoIconIdx = -1; } // Update keycard multiple widgets. for(i = 0; i < 3; ++i) { hud->keyBoxes[i] = plr->keys[i] ? true : false; } // Used by wFrags widget. hud->fragsCount = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; hud->fragsCount += plr->frags[i] * (i != player ? 1 : -1); } } void ST_Ticker(void) { int i; Hu_InventoryTicker(); for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; hudstate_t* hud = &hudStates[i]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) continue; ST_updateWidgets(i); if(!P_IsPaused()) { int delta, curHealth; if(cfg.hudTimer == 0) { hud->hideTics = hud->hideAmount = 0; } else { if(hud->hideTics > 0) hud->hideTics--; if(hud->hideTics == 0 && cfg.hudTimer > 0 && hud->hideAmount < 1) hud->hideAmount += 0.1f; } if(hud->currentInvItemFlash > 0) hud->currentInvItemFlash--; if(mapTime & 1) { hud->chainWiggle = P_Random() & 1; } curHealth = MAX_OF(plr->plr->mo->health, 0); if(curHealth < hud->healthMarker) { delta = MINMAX_OF(1, (hud->healthMarker - curHealth) >> 2, 4); hud->healthMarker -= delta; } else if(curHealth > hud->healthMarker) { delta = MINMAX_OF(1, (curHealth - hud->healthMarker) >> 2, 4); hud->healthMarker += delta; } // Tome of Power countdown sound. if(plr->powers[PT_WEAPONLEVEL2] && plr->powers[PT_WEAPONLEVEL2] < cfg.tomeSound * 35) { int timeleft = plr->powers[PT_WEAPONLEVEL2] / 35; if(hud->tomePlay != timeleft) { hud->tomePlay = timeleft; S_LocalSound(SFX_KEYUP, NULL); } } } } } /** * Sets the new palette based upon current values of player->damageCount * and player->bonusCount */ void ST_doPaletteStuff(int player) { int palette = 0; player_t* plr = &players[player]; if(plr->damageCount) { palette = (plr->damageCount + 7) >> 3; if(palette >= NUMREDPALS) { palette = NUMREDPALS - 1; } palette += STARTREDPALS; } else if(plr->bonusCount) { palette = (plr->bonusCount + 7) >> 3; if(palette >= NUMBONUSPALS) { palette = NUMBONUSPALS - 1; } palette += STARTBONUSPALS; } // $democam if(palette) { plr->plr->flags |= DDPF_VIEW_FILTER; R_GetFilterColor(plr->plr->filterColor, palette); } else plr->plr->flags &= ~DDPF_VIEW_FILTER; } static void drawWidgets(hudstate_t* hud) { int i, player = hud - hudStates; player_t* plr = &players[player]; float alpha = hud->statusbarCounterAlpha; hud->oldHealth = -1; if(!Hu_InventoryIsOpen(player)) { inventoryitemtype_t readyItem; // Draw all the counters. // Frags. if(deathmatch) STlib_DrawNum(&hud->wFrags, alpha); else STlib_DrawNum(&hud->wHealth, alpha); // Draw armor. STlib_DrawNum(&hud->wArmor, alpha); // Draw keys. for(i = 0; i < 3; ++i) { if(hud->keyBoxes[i]) STlib_DrawIcon(&hud->wKeyBoxes[i], alpha); } STlib_DrawNum(&hud->wReadyWeapon, alpha); STlib_DrawMultiIcon(&hud->wCurrentAmmoIcon, hud->currentAmmoIconIdx, alpha); // Current inventory item. if((readyItem = P_InventoryReadyItem(player)) != IIT_NONE) { int x, y; lumpnum_t patch; if(hud->currentInvItemFlash > 0) { patch = dpInvItemFlash[hud->currentInvItemFlash % 5].lump; x = ST_INVITEMX + 2; y = ST_INVITEMY + 1; } else { patch = P_GetInvItem(readyItem-1)->patchLump; x = ST_INVITEMX; y = ST_INVITEMY; } DGL_Color4f(1, 1, 1, alpha); GL_DrawPatch_CS(x, y, patch); if(!(hud->currentInvItemFlash > 0)) { uint count = P_InventoryCount(player, readyItem); if(count > 1) Hu_DrawSmallNum(count, ST_INVITEMCWIDTH, ST_INVITEMCX, ST_INVITEMCY, alpha); } } } else { // Draw Inventory. Hu_InventoryDraw2(player, ST_INVENTORYX, ST_INVENTORYY, alpha); } } void ST_FlashCurrentItem(int player) { player_t* plr; hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; hud = &hudStates[player]; hud->currentInvItemFlash = 4; } static void drawINumber(signed int val, int x, int y, float r, float g, float b, float a) { int oldval; DGL_Color4f(r, g, b, a); // Limit to 999. if(val > 999) val = 999; oldval = val; if(val < 0) { if(val < -9) { GL_DrawPatch_CS(x + 1, y + 1, lame.lump); } else { val = -val; GL_DrawPatch_CS(x + 18, y, iNumbers[val].lump); GL_DrawPatch_CS(x + 9, y, negative.lump); } return; } if(val > 99) { GL_DrawPatch_CS(x, y, iNumbers[val / 100].lump); } val = val % 100; if(val > 9 || oldval > 99) { GL_DrawPatch_CS(x + 9, y, iNumbers[val / 10].lump); } val = val % 10; GL_DrawPatch_CS(x + 18, y, iNumbers[val].lump); } /** * Unhides the current HUD display if hidden. * * @param player The player whoose HUD to (maybe) unhide. * @param event The HUD Update Event type to check for triggering. */ void ST_HUDUnHide(int player, hueevent_t ev) { player_t* plr; if(ev < HUE_FORCE || ev > NUMHUDUNHIDEEVENTS) return; plr = &players[player]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) return; if(ev == HUE_FORCE || cfg.hudUnHide[ev]) { hudStates[player].hideTics = (cfg.hudTimer * TICSPERSEC); hudStates[player].hideAmount = 0; } } static void drawIcons(int player) { int frame; float iconAlpha = cfg.hudIconAlpha; float textAlpha = cfg.hudColor[3]; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; Draw_BeginZoom(cfg.hudScale, 2, 2); // Flight icons if(plr->powers[PT_FLIGHT]) { int offset = (cfg.hudShown[HUD_AMMO] && cfg.screenBlocks > 10 && plr->readyWeapon > 0 && plr->readyWeapon < 7) ? 43 : 0; if(plr->powers[PT_FLIGHT] > BLINKTHRESHOLD || !(plr->powers[PT_FLIGHT] & 16)) { frame = (mapTime / 3) & 15; if(plr->plr->mo->flags2 & MF2_FLY) { if(hud->hitCenterFrame && (frame != 15 && frame != 0)) { GL_DrawPatchLitAlpha(20 + offset, 17, 1, iconAlpha, spinFly[15].lump); } else { GL_DrawPatchLitAlpha(20 + offset, 17, 1, iconAlpha, spinFly[frame].lump); hud->hitCenterFrame = false; } } else { if(!hud->hitCenterFrame && (frame != 15 && frame != 0)) { GL_DrawPatchLitAlpha(20 + offset, 17, 1, iconAlpha, spinFly[frame].lump); hud->hitCenterFrame = false; } else { GL_DrawPatchLitAlpha(20 + offset, 17, 1, iconAlpha, spinFly[15].lump); hud->hitCenterFrame = true; } } } } Draw_EndZoom(); Draw_BeginZoom(cfg.hudScale, 318, 2); if(plr->powers[PT_WEAPONLEVEL2] && !plr->morphTics) { if(cfg.tomeCounter || plr->powers[PT_WEAPONLEVEL2] > BLINKTHRESHOLD || !(plr->powers[PT_WEAPONLEVEL2] & 16)) { frame = (mapTime / 3) & 15; if(cfg.tomeCounter && plr->powers[PT_WEAPONLEVEL2] < 35) { DGL_Color4f(1, 1, 1, plr->powers[PT_WEAPONLEVEL2] / 35.0f); } GL_DrawPatchLitAlpha(300, 17, 1, iconAlpha, spinBook[frame].lump); } if(plr->powers[PT_WEAPONLEVEL2] < cfg.tomeCounter * 35) { #define COUNT_X (303) #define COUNT_Y (30) int val = 1 + plr->powers[PT_WEAPONLEVEL2] / 35; DGL_Color4f(1, 1, 1, textAlpha); if(val > 9) { GL_DrawPatch_CS(COUNT_X, COUNT_Y, dpSmallNumbers[(val / 10) % 10].lump); } val = val % 10; GL_DrawPatch_CS(COUNT_X + 4, COUNT_Y, dpSmallNumbers[val].lump); #undef COUNT_X #undef COUNT_Y } } Draw_EndZoom(); } /** * All drawing for the statusbar starts and ends here. */ void ST_doRefresh(int player) { hudstate_t* hud; boolean statusbarVisible; if(player < 0 || player > MAXPLAYERS) return; hud = &hudStates[player]; statusbarVisible = (cfg.statusbarScale < 20 || (cfg.statusbarScale == 20 && hud->showBar < 1.0f)); hud->firstTime = false; if(statusbarVisible) { float fscale = cfg.statusbarScale / 20.0f; float h = 200 * (1 - fscale); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(160 - 320 * fscale / 2, h / hud->showBar, 0); DGL_Scalef(fscale, fscale, 1); } drawStatusBarBackground(player); drawChain(hud); drawWidgets(hud); if(statusbarVisible) { // Restore the normal modelview matrix. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } } void ST_doFullscreenStuff(int player) { int i, x, temp = 0; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; float textAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudColor[3]), 1.f); float iconAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudIconAlpha), 1.f); if(cfg.hudShown[HUD_AMMO]) { if(plr->readyWeapon > 0 && plr->readyWeapon < 7) { ammotype_t ammoType; int lvl = (plr->powers[PT_WEAPONLEVEL2]? 1 : 0); //// \todo Only supports one type of ammo per weapon. // For each type of ammo this weapon takes. for(ammoType = 0; ammoType < NUM_AMMO_TYPES; ++ammoType) { if(!weaponInfo[plr->readyWeapon][plr->class].mode[lvl].ammoType[ammoType]) continue; Draw_BeginZoom(cfg.hudScale, 2, 2); GL_DrawPatchLitAlpha(-1, 0, 1, iconAlpha, ammoIcons[plr->readyWeapon - 1].lump); drawINumber(plr->ammo[ammoType].owned, 18, 2, 1, 1, 1, textAlpha); Draw_EndZoom(); break; } } } Draw_BeginZoom(cfg.hudScale, 2, 198); if(cfg.hudShown[HUD_HEALTH]) { if(plr->plr->mo->health > 0) { HU_DrawBNumber(plr->plr->mo->health, 2, 180, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); } else { HU_DrawBNumber(0, 2, 180, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); } } if(cfg.hudShown[HUD_ARMOR]) { if(cfg.hudShown[HUD_HEALTH] && cfg.hudShown[HUD_KEYS]) temp = 158; else if(!cfg.hudShown[HUD_HEALTH] && cfg.hudShown[HUD_KEYS]) temp = 176; else if(cfg.hudShown[HUD_HEALTH] && !cfg.hudShown[HUD_KEYS]) temp = 168; else if(!cfg.hudShown[HUD_HEALTH] && !cfg.hudShown[HUD_KEYS]) temp = 186; drawINumber(plr->armorPoints, 6, temp, 1, 1, 1, textAlpha); } if(cfg.hudShown[HUD_KEYS]) { x = 6; // Draw keys above health? if(plr->keys[KT_YELLOW]) { GL_DrawPatchLitAlpha(x, cfg.hudShown[HUD_HEALTH]? 172 : 190, 1, iconAlpha, keys[0].lump); x += 11; } if(plr->keys[KT_GREEN]) { GL_DrawPatchLitAlpha(x, cfg.hudShown[HUD_HEALTH]? 172 : 190, 1, iconAlpha, keys[1].lump); x += 11; } if(plr->keys[KT_BLUE]) { GL_DrawPatchLitAlpha(x, cfg.hudShown[HUD_HEALTH]? 172 : 190, 1, iconAlpha, keys[2].lump); } } Draw_EndZoom(); if(deathmatch) { temp = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { temp += plr->frags[i]; } } Draw_BeginZoom(cfg.hudScale, 2, 198); drawINumber(temp, 45, 185, 1, 1, 1, textAlpha); Draw_EndZoom(); } if(!Hu_InventoryIsOpen(player)) { if(cfg.hudShown[HUD_CURRENTITEM]) { if(hud->currentInvItemFlash > 0) { Draw_BeginZoom(cfg.hudScale, 318, 198); GL_DrawPatchLitAlpha(289, 169, 1, iconAlpha / 2, dpInvItemBox.lump); GL_DrawPatchLitAlpha(292, 170, 1, iconAlpha, dpInvItemFlash[hud->currentInvItemFlash % 5].lump); Draw_EndZoom(); } else { inventoryitemtype_t readyItem = P_InventoryReadyItem(player); if(readyItem != IIT_NONE) { uint count; lumpnum_t patch = P_GetInvItem(readyItem-1)->patchLump; Draw_BeginZoom(cfg.hudScale, 318, 198); GL_DrawPatchLitAlpha(289, 169, 1, iconAlpha / 2, dpInvItemBox.lump); GL_DrawPatchLitAlpha(289, 169, 1, iconAlpha, patch); if((count = P_InventoryCount(player, readyItem)) > 1) Hu_DrawSmallNum(count, ST_INVITEMCWIDTH, 317, 191, textAlpha); Draw_EndZoom(); } } } } else { #define BORDER 2 #define INVENTORY_HEIGHT 30 #define INVENTORY_X SCREENWIDTH / 2 #define INVENTORY_Y SCREENHEIGHT - INVENTORY_HEIGHT - BORDER float textAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudColor[3]), 1.f); float iconAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudIconAlpha), 1.f); Hu_InventoryDraw(player, INVENTORY_X, INVENTORY_Y, hud->alpha, textAlpha, iconAlpha); #undef BORDER #undef INVENTORY_HEIGHT #undef INVENTORY_X #undef INVENTORY_Y } } void ST_Drawer(int player, int fullscreenmode, boolean refresh) { hudstate_t* hud; player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; hud = &hudStates[player]; hud->firstTime = hud->firstTime || refresh; hud->statusbarActive = (fullscreenmode < 2) || (AM_IsActive(AM_MapForPlayer(player)) && (cfg.automapHudDisplay == 0 || cfg.automapHudDisplay == 2) ); // Do palette shifts ST_doPaletteStuff(player); // Either slide the status bar in or fade out the fullscreen hud if(hud->statusbarActive) { if(hud->alpha > 0.0f) { hud->statusbarActive = 0; hud->alpha -= 0.1f; } else if(hud->showBar < 1.0f) { hud->showBar += 0.1f; } } else { if(fullscreenmode == 3) { if(hud->alpha > 0.0f) { hud->alpha -= 0.1f; fullscreenmode = 2; } } else { if(hud->showBar > 0.0f) { hud->showBar -= 0.1f; hud->statusbarActive = 1; } else if(hud->alpha < 1.0f) { hud->alpha += 0.1f; } } } // Always try to render statusbar with alpha in fullscreen modes if(fullscreenmode) hud->blended = 1; else hud->blended = 0; if(hud->statusbarActive) { ST_doRefresh(player); } else if(fullscreenmode != 3) { ST_doFullscreenStuff(player); } DGL_Color4f(1, 1, 1, 1); drawIcons(player); } void ST_loadGraphics(void) { int i; char nameBuf[9]; R_CachePatch(&statusbar, "BARBACK"); R_CachePatch(&invBar, "INVBAR"); R_CachePatch(&chain, "CHAIN"); R_CachePatch(&statBar, "STATBAR"); R_CachePatch(&lifeBar, "LIFEBAR"); // Order of lifeGems changed to match player color index. R_CachePatch(&lifeGems[0], "LIFEGEM1"); R_CachePatch(&lifeGems[1], "LIFEGEM3"); R_CachePatch(&lifeGems[2], "LIFEGEM2"); R_CachePatch(&lifeGems[3], "LIFEGEM0"); R_CachePatch(&godLeft, "GOD1"); R_CachePatch(&godRight, "GOD2"); R_CachePatch(&statusbarTopLeft, "LTFCTOP"); R_CachePatch(&statusbarTopRight, "RTFCTOP"); R_CachePatch(&negative, "NEGNUM"); for(i = 0; i < 16; ++i) { sprintf(nameBuf, "SPINBK%d", i); R_CachePatch(&spinBook[i], nameBuf); sprintf(nameBuf, "SPFLY%d", i); R_CachePatch(&spinFly[i], nameBuf); } R_CachePatch(&lame, "LAME"); for(i = 0; i < 10; ++i) { sprintf(nameBuf, "IN%d", i); R_CachePatch(&iNumbers[i], nameBuf); } // Inventory item flash anim. { const char invItemFlashAnim[5][9] = { {"USEARTIA"}, {"USEARTIB"}, {"USEARTIC"}, {"USEARTID"}, {"USEARTIE"} }; for(i = 0; i < 5; ++i) { R_CachePatch(&dpInvItemFlash[i], invItemFlashAnim[i]); } } // Ammo icons. { const char ammoPic[NUM_AMMO_TYPES][9] = { {"INAMGLD"}, {"INAMBOW"}, {"INAMBST"}, {"INAMRAM"}, {"INAMPNX"}, {"INAMLOB"} }; for(i = 0; i < NUM_AMMO_TYPES; ++i) { R_CachePatch(&ammoIcons[i], ammoPic[i]); } } // Key cards. R_CachePatch(&keys[0], "ykeyicon"); R_CachePatch(&keys[1], "gkeyicon"); R_CachePatch(&keys[2], "bkeyicon"); } void ST_loadData(void) { ST_loadGraphics(); } static void initData(hudstate_t* hud) { int i; int player = hud - hudStates; player_t* plr = &players[player]; hud->firstTime = true; hud->statusbarActive = true; hud->stopped = true; hud->oldHealth = -1; // Health marker chain animates up to the actual health value. hud->healthMarker = 0; hud->blended = false; hud->showBar = 0.0f; hud->statusbarCounterAlpha = 1.f; for(i = 0; i < 3; ++i) { hud->keyBoxes[i] = false; } hud->tomePlay = 0; hud->oldAmmoIconIdx = -1; hud->oldReadyWeapon = -1; hud->currentAmmoIconIdx = 0; ST_HUDUnHide(player, HUE_FORCE); } void ST_createWidgets(int player) { static int largeammo = 1994; // Means "n/a". ammotype_t ammoType; boolean found; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; int lvl = (plr->powers[PT_WEAPONLEVEL2]? 1 : 0); // Ready weapon ammo. //// \todo Only supports one type of ammo per weapon. found = false; for(ammoType = 0; ammoType < NUM_AMMO_TYPES && !found; ++ammoType) { if(!weaponInfo[plr->readyWeapon][plr->class].mode[lvl].ammoType[ammoType]) continue; // Weapon does not take this ammo. STlib_InitNum(&hud->wReadyWeapon, ST_AMMOX, ST_AMMOY, iNumbers, &plr->ammo[ammoType].owned, ST_AMMOWIDTH, 1); found = true; } if(!found) // Weapon requires no ammo at all. { // HERETIC.EXE returns an address beyond plr->ammo[NUM_AMMO_TYPES] // if weaponInfo[plr->readyWeapon].ammo == am_noammo // ...obviously a bug. //STlib_InitNum(&wReadyWeapon, ST_AMMOX, ST_AMMOY, iNumbers, // &plr->ammo[weaponinfo[plr->readyWeapon].ammo], // &statusbarActive, ST_AMMOWIDTH, &statusbarCounterAlpha); // Ready weapon ammo. STlib_InitNum(&hud->wReadyWeapon, ST_AMMOX, ST_AMMOY, iNumbers, &largeammo, ST_AMMOWIDTH, 1); } // Ready weapon icon STlib_InitMultiIcon(&hud->wCurrentAmmoIcon, ST_AMMOICONX, ST_AMMOICONY, ammoIcons, 1); // Health num. STlib_InitNum(&hud->wHealth, ST_HEALTHX, ST_HEALTHY, iNumbers, &plr->health, ST_HEALTHWIDTH, 1); // Armor percentage - should be colored later. STlib_InitNum(&hud->wArmor, ST_ARMORX, ST_ARMORY, iNumbers, &plr->armorPoints, ST_ARMORWIDTH, 1); // Frags sum. STlib_InitNum(&hud->wFrags, ST_FRAGSX, ST_FRAGSY, iNumbers, &hud->fragsCount, ST_FRAGSWIDTH, 1); // KeyBoxes 0-2. STlib_InitIcon(&hud->wKeyBoxes[0], ST_KEY0X, ST_KEY0Y, &keys[0], 1); STlib_InitIcon(&hud->wKeyBoxes[1], ST_KEY1X, ST_KEY1Y, &keys[1], 1); STlib_InitIcon(&hud->wKeyBoxes[2], ST_KEY2X, ST_KEY2Y, &keys[2], 1); } void ST_Start(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(!hud->stopped) ST_Stop(player); initData(hud); ST_createWidgets(player); hud->stopped = false; } void ST_Stop(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(hud->stopped) return; hud->stopped = true; } void ST_Init(void) { ST_loadData(); } /** * Console command to change the size of the status bar. */ DEFCC(CCmdStatusBarSize) { int min = 1, max = 20, *val = &cfg.statusbarScale; if(!stricmp(argv[1], "+")) (*val)++; else if(!stricmp(argv[1], "-")) (*val)--; else *val = strtol(argv[1], NULL, 0); *val = MINMAX_OF(min, *val, max); // Update the view size if necessary. R_SetViewSize(cfg.screenBlocks); ST_HUDUnHide(CONSOLEPLAYER, HUE_FORCE); // so the user can see the change. return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_inter.c0000644000175000017500000012520211357170242022740 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.c: Handling interactions (i.e., collisions). */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "am_map.h" #include "d_net.h" #include "dmu_lib.h" #include "p_player.h" #include "p_inventory.h" #include "p_tick.h" #include "p_user.h" #include "p_mapsetup.h" // MACROS ------------------------------------------------------------------ #define BONUSADD (6) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int maxAmmo[NUM_AMMO_TYPES] = { 100, // gold wand 50, // crossbow 200, // blaster 200, // skull rod 20, // phoenix rod 150 // mace }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int getWeaponAmmo[NUM_WEAPON_TYPES] = { 0, // staff 25, // gold wand 10, // crossbow 30, // blaster 50, // skull rod 2, // phoenix rod 50, // mace 0 // gauntlets }; // CODE -------------------------------------------------------------------- /** * Returns true if the player accepted the ammo, false if it was * refused (player has maxammo[ammo]). */ boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int num) { if(ammo == AT_NOAMMO) return false; if(ammo < 0 || ammo > NUM_AMMO_TYPES) Con_Error("P_GiveAmmo: bad type %i", ammo); if(!(player->ammo[ammo].owned < player->ammo[ammo].max)) return false; if(gameSkill == SM_BABY || gameSkill == SM_NIGHTMARE) { // Extra ammo in baby mode and nightmare mode. num += num / 1; } // We are about to receive some more ammo. Does the player want to // change weapon automatically? P_MaybeChangeWeapon(player, WT_NOCHANGE, ammo, false); if(player->ammo[ammo].owned + num > player->ammo[ammo].max) player->ammo[ammo].owned = player->ammo[ammo].max; else player->ammo[ammo].owned += num; player->update |= PSF_AMMO; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_AMMO); return true; } /** * @return @c true, if the weapon or its ammo was accepted. */ boolean P_GiveWeapon(player_t *player, weapontype_t weapon) { int i; int lvl = (player->powers[PT_WEAPONLEVEL2]? 1 : 0); boolean gaveAmmo = false; boolean gaveWeapon = false; if(IS_NETGAME && !deathmatch) { // Leave placed weapons forever on net games. if(player->weapons[weapon].owned) return false; player->bonusCount += BONUSADD; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class].mode[lvl].ammoType[i]) continue; // Weapon does not take this type of ammo. if(P_GiveAmmo(player, i, getWeaponAmmo[weapon])) gaveAmmo = true; // At least ONE type of ammo was given. } // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); S_ConsoleSound(SFX_WPNUP, NULL, player - players); return false; } else { // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class].mode[lvl].ammoType[i]) continue; // Weapon does not take this type of ammo. if(P_GiveAmmo(player, i, getWeaponAmmo[weapon])) gaveAmmo = true; // At least ONE type of ammo was given. } if(player->weapons[weapon].owned) gaveWeapon = false; else { gaveWeapon = true; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false); } // Maybe unhide the HUD? if(gaveWeapon) ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); return (gaveWeapon || gaveAmmo); } } /** * @return @c false, if the body isn't needed at all. */ boolean P_GiveBody(player_t *player, int num) { int max; if(player->morphTics) max = MAXCHICKENHEALTH; else max = maxHealth; if(player->health >= max) { return false; } player->health += num; if(player->health > max) { player->health = max; } player->update |= PSF_HEALTH; player->plr->mo->health = player->health; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_HEALTH); return true; } /** * @return @c true, iff the armor was given. */ boolean P_GiveArmor(player_t* plr, int type, int points) { if(plr->armorPoints >= points) return false; P_PlayerSetArmorType(plr, type); P_PlayerGiveArmorBonus(plr, points - plr->armorPoints); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); return true; } void P_GiveKey(player_t* player, keytype_t key) { if(player->keys[key]) return; player->bonusCount = BONUSADD; player->keys[key] = true; player->update |= PSF_KEYS; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_KEY); } /** * @return @c true, if power accepted. */ boolean P_GivePower(player_t* player, powertype_t power) { mobj_t* plrmo = player->plr->mo; boolean retval = false; player->update |= PSF_POWERS; switch(power) { case PT_INVULNERABILITY: if(!(player->powers[power] > BLINKTHRESHOLD)) { player->powers[power] = INVULNTICS; retval = true; } break; case PT_WEAPONLEVEL2: if(!(player->powers[power] > BLINKTHRESHOLD)) { player->powers[power] = WPNLEV2TICS; retval = true; } break; case PT_INVISIBILITY: if(!(player->powers[power] > BLINKTHRESHOLD)) { player->powers[power] = INVISTICS; plrmo->flags |= MF_SHADOW; retval = true; } break; case PT_FLIGHT: if(!(player->powers[power] > BLINKTHRESHOLD)) { player->powers[power] = FLIGHTTICS; plrmo->flags2 |= MF2_FLY; plrmo->flags |= MF_NOGRAVITY; if(plrmo->pos[VZ] <= plrmo->floorZ) { player->flyHeight = 10; // Thrust the player in the air a bit. player->plr->flags |= DDPF_FIXMOM; } retval = true; } break; case PT_INFRARED: if(!(player->powers[power] > BLINKTHRESHOLD)) { player->powers[power] = INFRATICS; retval = true; } break; default: if(!player->powers[power]) { player->powers[power] = 1; retval = true; } break; } if(retval) { if(power == PT_ALLMAP) AM_RevealMap(AM_MapForPlayer(player - players), true); } return retval; } /** * Removes the MF_SPECIAL flag, and initiates the item pickup animation. */ void P_SetDormantItem(mobj_t* mo) { mo->flags &= ~MF_SPECIAL; if(deathmatch && (mo->type != MT_ARTIINVULNERABILITY) && (mo->type != MT_ARTIINVISIBILITY)) { P_MobjChangeState(mo, S_DORMANTARTI1); } else { // Don't respawn. P_MobjChangeState(mo, S_DEADARTI1); } S_StartSound(SFX_ARTIUP, mo); } void C_DECL A_RestoreArtifact(mobj_t* mo) { mo->flags |= MF_SPECIAL; P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN)); S_StartSound(SFX_RESPAWN, mo); } void P_HideSpecialThing(mobj_t* thing) { thing->flags &= ~MF_SPECIAL; thing->flags2 |= MF2_DONTDRAW; P_MobjChangeState(thing, S_HIDESPECIAL1); } /** * Make a special thing visible again. */ void C_DECL A_RestoreSpecialThing1(mobj_t* thing) { if(thing->type == MT_WMACE) { // Do random mace placement. P_RepositionMace(thing); } thing->flags2 &= ~MF2_DONTDRAW; S_StartSound(SFX_RESPAWN, thing); } void C_DECL A_RestoreSpecialThing2(mobj_t* thing) { thing->flags |= MF_SPECIAL; P_MobjChangeState(thing, P_GetState(thing->type, SN_SPAWN)); } typedef enum { IT_NONE = 0, IT_HEALTH_POTION, IT_SHIELD1, IT_SHIELD2, IT_BAGOFHOLDING, IT_ALLMAP, IT_KEY_BLUE, IT_KEY_YELLOW, IT_KEY_GREEN, IT_ITEM_HEALTHPOTION, IT_ITEM_WINGS, IT_ITEM_INVUL, IT_ITEM_TOMB, IT_ITEM_INVIS, IT_ITEM_EGG, IT_ITEM_HEALTHSUPER, IT_ITEM_TORCH, IT_ITEM_FIREBOMB, IT_ITEM_TELEPORT, IT_AMMO_WAND, IT_AMMO_WAND_LARGE, IT_AMMO_MACE, IT_AMMO_MACE_LARGE, IT_AMMO_CROSSBOW, IT_AMMO_CROSSBOW_LARGE, IT_AMMO_BLASTER, IT_AMMO_BLASTER_LARGE, IT_AMMO_SKULL, IT_AMMO_SKULL_LARGE, IT_AMMO_PHOENIX, IT_AMMO_PHOENIX_LARGE, IT_WEAPON_MACE, IT_WEAPON_CROSSBOW, IT_WEAPON_BLASTER, IT_WEAPON_SKULLROD, IT_WEAPON_PHOENIXROD, IT_WEAPON_GAUNTLETS } itemtype_t; static itemtype_t getItemTypeBySprite(spritetype_e sprite) { static const struct item_s { itemtype_t type; spritetype_e sprite; } items[] = { { IT_HEALTH_POTION, SPR_PTN1 }, { IT_SHIELD1, SPR_SHLD }, { IT_SHIELD2, SPR_SHD2 }, { IT_BAGOFHOLDING, SPR_BAGH }, { IT_ALLMAP, SPR_SPMP }, { IT_KEY_BLUE, SPR_BKYY }, { IT_KEY_YELLOW, SPR_CKYY }, { IT_KEY_GREEN, SPR_AKYY }, { IT_ITEM_HEALTHPOTION, SPR_PTN2 }, { IT_ITEM_WINGS, SPR_SOAR }, { IT_ITEM_INVUL, SPR_INVU }, { IT_ITEM_TOMB, SPR_PWBK }, { IT_ITEM_INVIS, SPR_INVS }, { IT_ITEM_EGG, SPR_EGGC }, { IT_ITEM_HEALTHSUPER, SPR_SPHL }, { IT_ITEM_TORCH, SPR_TRCH }, { IT_ITEM_FIREBOMB, SPR_FBMB }, { IT_ITEM_TELEPORT, SPR_ATLP }, { IT_AMMO_WAND, SPR_AMG1 }, { IT_AMMO_WAND_LARGE, SPR_AMG2 }, { IT_AMMO_MACE, SPR_AMM1 }, { IT_AMMO_MACE_LARGE, SPR_AMM2 }, { IT_AMMO_CROSSBOW, SPR_AMC1 }, { IT_AMMO_CROSSBOW_LARGE, SPR_AMC2 }, { IT_AMMO_BLASTER, SPR_AMB1 }, { IT_AMMO_BLASTER_LARGE, SPR_AMB2 }, { IT_AMMO_SKULL, SPR_AMS1 }, { IT_AMMO_SKULL_LARGE, SPR_AMS2 }, { IT_AMMO_PHOENIX, SPR_AMP1 }, { IT_AMMO_PHOENIX_LARGE, SPR_AMP2 }, { IT_WEAPON_MACE, SPR_WMCE }, { IT_WEAPON_CROSSBOW, SPR_WBOW }, { IT_WEAPON_BLASTER, SPR_WBLS }, { IT_WEAPON_SKULLROD, SPR_WSKL }, { IT_WEAPON_PHOENIXROD, SPR_WPHX }, { IT_WEAPON_GAUNTLETS, SPR_WGNT }, { IT_NONE, 0 }, }; uint i; for(i = 0; items[i].type != IT_NONE; ++i) if(items[i].sprite == sprite) return items[i].type; return IT_NONE; } static boolean giveItem(player_t* plr, itemtype_t item, int quantity) { if(!plr) return false; switch(item) { case IT_HEALTH_POTION: if(!P_GiveBody(plr, 10)) return false; P_SetMessage(plr, TXT_ITEMHEALTH, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_SHIELD1: if(!P_GiveArmor(plr, 1, 1 * 100)) return false; P_SetMessage(plr, TXT_ITEMSHIELD1, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_SHIELD2: if(!P_GiveArmor(plr, 2, 2 * 100)) return false; P_SetMessage(plr, TXT_ITEMSHIELD2, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_BAGOFHOLDING: if(!plr->backpack) { int i; for(i = 0; i < NUM_AMMO_TYPES; ++i) { plr->ammo[i].max *= 2; } plr->backpack = true; } P_GiveAmmo(plr, AT_CRYSTAL, AMMO_GWND_WIMPY); P_GiveAmmo(plr, AT_ORB, AMMO_BLSR_WIMPY); P_GiveAmmo(plr, AT_ARROW, AMMO_CBOW_WIMPY); P_GiveAmmo(plr, AT_RUNE, AMMO_SKRD_WIMPY); P_GiveAmmo(plr, AT_FIREORB, AMMO_PHRD_WIMPY); P_SetMessage(plr, TXT_ITEMBAGOFHOLDING, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ALLMAP: if(!P_GivePower(plr, PT_ALLMAP)) return false; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_POWER); P_SetMessage(plr, TXT_ITEMSUPERMAP, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_KEY_BLUE: if(!plr->keys[KT_BLUE]) { P_SetMessage(plr, TXT_GOTBLUEKEY, false); } P_GiveKey(plr, KT_BLUE); if(!mapSetup) S_ConsoleSound(SFX_KEYUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_YELLOW: if(!plr->keys[KT_YELLOW]) { P_SetMessage(plr, TXT_GOTYELLOWKEY, false); } P_GiveKey(plr, KT_YELLOW); if(!mapSetup) S_ConsoleSound(SFX_KEYUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_GREEN: if(!plr->keys[KT_GREEN]) { P_SetMessage(plr, TXT_GOTGREENKEY, false); } P_GiveKey(plr, KT_GREEN); if(!mapSetup) S_ConsoleSound(SFX_KEYUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_ITEM_HEALTHPOTION: if(!P_InventoryGive(plr - players, IIT_HEALTH, false)) return false; P_SetMessage(plr, TXT_INV_HEALTH, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_WINGS: if(!P_InventoryGive(plr - players, IIT_FLY, false)) return false; P_SetMessage(plr, TXT_INV_FLY, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_INVUL: if(!P_InventoryGive(plr - players, IIT_INVULNERABILITY, false)) return false; P_SetMessage(plr, TXT_INV_INVULNERABILITY, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_TOMB: if(!P_InventoryGive(plr - players, IIT_TOMBOFPOWER, false)) return false; P_SetMessage(plr, TXT_INV_TOMEOFPOWER, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_INVIS: if(!P_InventoryGive(plr - players, IIT_INVISIBILITY, false)) return false; P_SetMessage(plr, TXT_INV_INVISIBILITY, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_EGG: if(!P_InventoryGive(plr - players, IIT_EGG, false)) return false; P_SetMessage(plr, TXT_INV_EGG, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_HEALTHSUPER: if(!P_InventoryGive(plr - players, IIT_SUPERHEALTH, false)) return false; P_SetMessage(plr, TXT_INV_SUPERHEALTH, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_TORCH: if(!P_InventoryGive(plr - players, IIT_TORCH, false)) return false; P_SetMessage(plr, TXT_INV_TORCH, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_FIREBOMB: if(!P_InventoryGive(plr - players, IIT_FIREBOMB, false)) return false; P_SetMessage(plr, TXT_INV_FIREBOMB, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ITEM_TELEPORT: if(!P_InventoryGive(plr - players, IIT_TELEPORT, false)) return false; P_SetMessage(plr, TXT_INV_TELEPORT, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_WAND: if(!P_GiveAmmo(plr, AT_CRYSTAL, quantity)) return false; P_SetMessage(plr, TXT_AMMOGOLDWAND1, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_WAND_LARGE: if(!P_GiveAmmo(plr, AT_CRYSTAL, quantity)) return false; P_SetMessage(plr, TXT_AMMOGOLDWAND2, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_MACE: if(!P_GiveAmmo(plr, AT_MSPHERE, quantity)) return false; P_SetMessage(plr, TXT_AMMOMACE1, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_MACE_LARGE: if(!P_GiveAmmo(plr, AT_MSPHERE, quantity)) return false; P_SetMessage(plr, TXT_AMMOMACE2, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CROSSBOW: if(!P_GiveAmmo(plr, AT_ARROW, quantity)) return false; P_SetMessage(plr, TXT_AMMOCROSSBOW1, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CROSSBOW_LARGE: if(!P_GiveAmmo(plr, AT_ARROW, quantity)) return false; P_SetMessage(plr, TXT_AMMOCROSSBOW2, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_BLASTER: if(!P_GiveAmmo(plr, AT_ORB, quantity)) return false; P_SetMessage(plr, TXT_AMMOBLASTER1, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_BLASTER_LARGE: if(!P_GiveAmmo(plr, AT_ORB, quantity)) return false; P_SetMessage(plr, TXT_AMMOBLASTER2, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SKULL: if(!P_GiveAmmo(plr, AT_RUNE, quantity)) return false; P_SetMessage(plr, TXT_AMMOSKULLROD1, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SKULL_LARGE: if(!P_GiveAmmo(plr, AT_RUNE, quantity)) return false; P_SetMessage(plr, TXT_AMMOSKULLROD2, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_PHOENIX: if(!P_GiveAmmo(plr, AT_FIREORB, quantity)) return false; P_SetMessage(plr, TXT_AMMOPHOENIXROD1, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_PHOENIX_LARGE: if(!P_GiveAmmo(plr, AT_FIREORB, quantity)) return false; P_SetMessage(plr, TXT_AMMOPHOENIXROD2, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_WEAPON_MACE: if(!P_GiveWeapon(plr, WT_SEVENTH)) return false; P_SetMessage(plr, TXT_WPNMACE, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_CROSSBOW: if(!P_GiveWeapon(plr, WT_THIRD)) return false; P_SetMessage(plr, TXT_WPNCROSSBOW, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_BLASTER: if(!P_GiveWeapon(plr, WT_FOURTH)) return false; P_SetMessage(plr, TXT_WPNBLASTER, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_SKULLROD: if(!P_GiveWeapon(plr, WT_FIFTH)) return false; P_SetMessage(plr, TXT_WPNSKULLROD, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_PHOENIXROD: if(!P_GiveWeapon(plr, WT_SIXTH)) return false; P_SetMessage(plr, TXT_WPNPHOENIXROD, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_GAUNTLETS: if(!P_GiveWeapon(plr, WT_EIGHTH)) return false; P_SetMessage(plr, TXT_WPNGAUNTLETS, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; default: Con_Error("giveItem: Unknown item %i.", (int) item); } return true; } void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) { player_t* player; float delta; itemtype_t item; delta = special->pos[VZ] - toucher->pos[VZ]; if(delta > toucher->height || delta < -32) { // Out of reach. return; } // Dead thing touching (can happen with a sliding player corpse). if(toucher->health <= 0) return; player = toucher->player; // Identify by sprite. if((item = getItemTypeBySprite(special->sprite)) != IT_NONE) { if(!giveItem(player, item, special->health)) return; // Don't destroy the item. } else { Con_Message("P_TouchSpecialMobj: Unknown gettable thing %i.\n", (int) special->type); } if(special->flags & MF_COUNTITEM) player->itemCount++; switch(item) { case IT_ITEM_HEALTHPOTION: case IT_ITEM_WINGS: case IT_ITEM_INVUL: case IT_ITEM_TOMB: case IT_ITEM_INVIS: case IT_ITEM_EGG: case IT_ITEM_HEALTHSUPER: case IT_ITEM_TORCH: case IT_ITEM_FIREBOMB: case IT_ITEM_TELEPORT: P_SetDormantItem(special); break; default: if(deathmatch && !(special->flags & MF_DROPPED)) P_HideSpecialThing(special); else P_MobjRemove(special, false); if(!mapSetup) player->bonusCount += BONUSADD; break; } } void P_KillMobj(mobj_t* source, mobj_t* target) { statenum_t state; if(!target) // Nothing to kill. return; target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_NOGRAVITY); target->flags |= MF_CORPSE | MF_DROPOFF; target->flags2 &= ~MF2_PASSMOBJ; target->corpseTics = 0; target->height /= 2*2; if(source && source->player) { if(target->flags & MF_COUNTKILL) { // Count for intermission. source->player->killCount++; } if(target->player) { // Frag stuff. source->player->update |= PSF_FRAGS; if(target == source) { // Self-frag. target->player->frags[target->player - players]--; NetSv_FragsForAll(target->player); } else { source->player->frags[target->player - players]++; NetSv_FragsForAll(source->player); if(source->player->morphTics) { // Make a super chicken. P_GivePower(source->player, PT_WEAPONLEVEL2); } } } } else if(!IS_NETGAME && (target->flags & MF_COUNTKILL)) { // Count all monster deaths. players[0].killCount++; } if(target->player) { if(!source) { // Self-frag. target->player->frags[target->player - players]--; NetSv_FragsForAll(target->player); } target->flags &= ~MF_SOLID; target->flags2 &= ~MF2_FLY; target->player->powers[PT_FLIGHT] = 0; target->player->powers[PT_WEAPONLEVEL2] = 0; target->player->playerState = PST_DEAD; target->player->rebornWait = PLAYER_REBORN_TICS; target->player->plr->flags |= DDPF_DEAD; target->player->update |= PSF_STATE; P_DropWeapon(target->player); if(target->flags2 & MF2_FIREDAMAGE) { // Player flame death. P_MobjChangeState(target, S_PLAY_FDTH1); return; } // Don't die with the automap open. AM_Open(AM_MapForPlayer(target->player - players), false, false); } if((state = P_GetState(target->type, SN_XDEATH)) != S_NULL && target->health < -(target->info->spawnHealth / 2)) { // Extreme death. P_MobjChangeState(target, state); } else { // Normal death. P_MobjChangeState(target, P_GetState(target->type, SN_DEATH)); } target->tics -= P_Random() & 3; } /** * @return @c true, if the player is morphed. */ boolean P_MorphPlayer(player_t* player) { mobj_t* pmo, *fog, *chicken; float pos[3]; angle_t angle; int oldFlags2; if(player->morphTics) { if((player->morphTics < CHICKENTICS - TICSPERSEC) && !player->powers[PT_WEAPONLEVEL2]) { // Make a super chicken. P_GivePower(player, PT_WEAPONLEVEL2); } return false; } if(player->powers[PT_INVULNERABILITY]) { // Immune when invulnerable. return false; } pmo = player->plr->mo; memcpy(pos, pmo->pos, sizeof(pos)); angle = pmo->angle; oldFlags2 = pmo->flags2; if(!(chicken = P_SpawnMobj3fv(MT_CHICPLAYER, pos, angle, 0))) return false; P_MobjChangeState(pmo, S_FREETARGMOBJ); if((fog = P_SpawnMobj3f(MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, angle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); chicken->special1 = player->readyWeapon; chicken->player = player; chicken->dPlayer = player->plr; player->health = chicken->health = MAXCHICKENHEALTH; player->plr->mo = chicken; player->armorPoints = player->armorType = 0; player->powers[PT_INVISIBILITY] = 0; player->powers[PT_WEAPONLEVEL2] = 0; if(oldFlags2 & MF2_FLY) chicken->flags2 |= MF2_FLY; player->morphTics = CHICKENTICS; player->plr->flags |= DDPF_FIXPOS | DDPF_FIXMOM; player->update |= PSF_MORPH_TIME | PSF_HEALTH | PSF_POWERS | PSF_ARMOR_POINTS; P_ActivateMorphWeapon(player); return true; } boolean P_MorphMonster(mobj_t *actor) { mobj_t *fog, *chicken, *target; mobjtype_t moType; float pos[3]; angle_t angle; int ghost; if(actor->player) return false; moType = actor->type; switch(moType) { case MT_POD: case MT_CHICKEN: case MT_HEAD: case MT_MINOTAUR: case MT_SORCERER1: case MT_SORCERER2: return false; default: break; } memcpy(pos, actor->pos, sizeof(pos)); angle = actor->angle; ghost = actor->flags & MF_SHADOW; target = actor->target; if((chicken = P_SpawnMobj3fv(MT_CHICKEN, pos, angle, 0))) { P_MobjChangeState(actor, S_FREETARGMOBJ); if((fog = P_SpawnMobj3f(MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, angle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); chicken->special2 = moType; chicken->special1 = CHICKENTICS + P_Random(); chicken->flags |= ghost; chicken->target = target; } return true; } boolean P_AutoUseChaosDevice(player_t* player) { int plrnum = player - players; //// \todo Do this in the inventory code? if(P_InventoryCount(plrnum, IIT_TELEPORT)) { P_InventoryUse(plrnum, IIT_TELEPORT, false); P_DamageMobj(player->plr->mo, NULL, NULL, player->health - (player->health + 1) / 2, false); return true; } return false; } void P_AutoUseHealth(player_t* player, int saveHealth) { uint i, count; int plrnum = player - players; int normalCount = P_InventoryCount(plrnum, IIT_HEALTH); int superCount = P_InventoryCount(plrnum, IIT_SUPERHEALTH); //// \todo Do this in the inventory code? if(gameSkill == SM_BABY && normalCount * 25 >= saveHealth) { // Use quartz flasks. count = (saveHealth + 24) / 25; for(i = 0; i < count; ++i) { player->health += 25; P_InventoryTake(plrnum, IIT_HEALTH, false); } } else if(superCount * 100 >= saveHealth) { // Use mystic urns. count = (saveHealth + 99) / 100; for(i = 0; i < count; ++i) { player->health += 100; P_InventoryTake(plrnum, IIT_SUPERHEALTH, false); } } else if(gameSkill == SM_BABY && superCount * 100 + normalCount * 25 >= saveHealth) { // Use mystic urns and quartz flasks. count = (saveHealth + 24) / 25; saveHealth -= count * 25; for(i = 0; i < count; ++i) { player->health += 25; P_InventoryTake(plrnum, IIT_HEALTH, false); } count = (saveHealth + 99) / 100; for(i = 0; i < count; ++i) { player->health += 100; P_InventoryTake(plrnum, IIT_SUPERHEALTH, false); } } player->plr->mo->health = player->health; } /** * Damages both enemies and players. * * @param inflictor Mobj that caused the damage creature or missile, * can be NULL (slime, etc) * @param source Mobj to target after taking damage. Can be @c NULL * for barrel explosions and other environmental stuff. * Source and inflictor are the same for melee attacks. * @return Actual amount of damage done. */ int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damageP, boolean stomping) { angle_t angle; int saved, originalHealth; player_t* player; int temp, damage; if(!target) return 0; // Wha? originalHealth = target->health; // The actual damage (== damageP * netMobDamageModifier for any // non-player mobj). damage = damageP; if(IS_NETGAME && !stomping && D_NetDamageMobj(target, inflictor, source, damage)) { // We're done here. return 0; } // Clients can't harm anybody. if(IS_CLIENT) return 0; if(!(target->flags & MF_SHOOTABLE)) return 0; // Shouldn't happen... if(target->health <= 0) return 0; if(target->player) { // Player specific. // Check if player-player damage is disabled. if(source && source->player && source->player != target->player) { // Co-op damage disabled? if(IS_NETGAME && !deathmatch && cfg.noCoopDamage) return 0; // Same color, no damage? if(cfg.noTeamDamage && cfg.playerColor[target->player - players] == cfg.playerColor[source->player - players]) return 0; } } if(target->flags & MF_SKULLFLY) { if(target->type == MT_MINOTAUR) { // Minotaur is invulnerable during charge attack. return 0; } target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0; } player = target->player; if(player && gameSkill == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the // inflictor is not a player. if(inflictor && !inflictor->player && (!source || (source && !source->player))) { // damage = (int) ((float) damage * netMobDamageModifier); if(IS_NETGAME) damage *= cfg.netMobDamageModifier; } // Special damage types. if(inflictor) { switch(inflictor->type) { case MT_EGGFX: if(player) { P_MorphPlayer(player); } else { P_MorphMonster(target); } return 0; // Does no actual "damage" but health IS modified. case MT_WHIRLWIND: { int randVal; target->angle += (P_Random() - P_Random()) << 20; target->mom[MX] += FIX2FLT((P_Random() - P_Random()) << 10); target->mom[MY] += FIX2FLT((P_Random() - P_Random()) << 10); if((mapTime & 16) && !(target->flags2 & MF2_BOSS)) { randVal = P_Random(); if(randVal > 160) { randVal = 160; } target->mom[MZ] += FIX2FLT(randVal << 10); if(target->mom[MZ] > 12) { target->mom[MZ] = 12; } } if(!(mapTime & 7)) { return P_DamageMobj(target, NULL, NULL, 3, false); } return 0; } case MT_MINOTAUR: if(inflictor->flags & MF_SKULLFLY) { // Slam only when in charge mode. angle_t angle; uint an; float thrust; int damageDone; angle = R_PointToAngle2(inflictor->pos[VX], inflictor->pos[VY], target->pos[VX], target->pos[VY]); an = angle >> ANGLETOFINESHIFT; thrust = 16 + FIX2FLT(P_Random() << 10); target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); damageDone = P_DamageMobj(target, NULL, NULL, HITDICE(6), false); if(target->player) { target->reactionTime = 14 + (P_Random() & 7); } return damageDone; } break; case MT_MACEFX4: // Death ball. if((target->flags2 & MF2_BOSS) || target->type == MT_HEAD) { // Don't allow cheap boss kills. break; } else if(target->player) { // Player specific checks. // Is player invulnerable? if(target->player->powers[PT_INVULNERABILITY]) break; // Does the player have a Chaos Device he can use to get // him out of trouble? if(P_AutoUseChaosDevice(target->player)) return originalHealth - target->health; // He's lucky... this time. } // Something's gonna die. damage = 10000; break; case MT_PHOENIXFX2: // Flame thrower. if(target->player && P_Random() < 128) { // Freeze player for a bit. target->reactionTime += 4; } break; case MT_RAINPLR1: case MT_RAINPLR2: case MT_RAINPLR3: case MT_RAINPLR4: // Rain missiles. if(target->flags2 & MF2_BOSS) { // Decrease damage for bosses. damage = (P_Random() & 7) + 1; } break; case MT_HORNRODFX2: case MT_PHOENIXFX1: if(target->type == MT_SORCERER2 && P_Random() < 96) { // D'Sparil teleports away, without taking damage. P_DSparilTeleport(target); return 0; } break; case MT_BLASTERFX1: case MT_RIPPER: if(target->type == MT_HEAD) { // Less damage to Ironlich bosses. damage = P_Random() & 1; if(!damage) return 0; } break; default: break; } } // Some close combat weapons should not inflict thrust and push the // victim out of reach, thus kick away unless using a melee weapon. if(inflictor && !(target->flags & MF_NOCLIP) && (!source || !source->player || source->player->readyWeapon != WT_EIGHTH) && !(inflictor->flags2 & MF2_NODMGTHRUST)) { uint an; float thrust; angle = R_PointToAngle2(inflictor->pos[VX], inflictor->pos[VY], target->pos[VX], target->pos[VY]); thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass); // Make fall forwards sometimes. if(damage < 40 && damage > target->health && target->pos[VZ] - inflictor->pos[VZ] > 64 && (P_Random() & 1)) { angle += ANG180; thrust *= 4; } if(source && source->player && (source == inflictor) && source->player->powers[PT_WEAPONLEVEL2] && source->player->readyWeapon == WT_FIRST) { // Staff power level 2. thrust = 10; if(!(target->flags & MF_NOGRAVITY)) target->mom[MZ] += 5; } an = angle >> ANGLETOFINESHIFT; target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); if(target->dPlayer) { // Only fix momentum. Otherwise clients will find it difficult // to escape from the damage inflictor. target->dPlayer->flags |= DDPF_FIXMOM; } // $dropoff_fix: thrust objects hanging off ledges. if((target->intFlags & MIF_FALLING) && target->gear >= MAXGEAR) target->gear = 0; } // Player specific. if(player) { // Below certain threshold, ignore damage in GOD mode, or with // INVUL power. if(damage < 1000 && ((P_GetPlayerCheats(player) & CF_GODMODE) || player->powers[PT_INVULNERABILITY])) { return 0; } if(player->armorType) { if(player->armorType == 1) saved = damage / 2; else saved = damage / 2 + damage / 4; if(player->armorPoints <= saved) { // Armor is used up. saved = player->armorPoints; player->armorType = 0; } player->armorPoints -= saved; player->update |= PSF_ARMOR_POINTS; damage -= saved; } if(damage >= player->health && ((gameSkill == SM_BABY) || deathmatch) && !player->morphTics) { // Try to use some inventory health. P_AutoUseHealth(player, damage - player->health + 1); } player->health -= damage; if(player->health < 0) player->health = 0; player->update |= PSF_HEALTH; player->attacker = source; player->damageCount += damage; // Add damage after armor / invuln. if(player->damageCount > 100) player->damageCount = 100; // Teleport stomp does 10k points... temp = damage < 100 ? damage : 100; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_DAMAGE); } // How about some particles, yes? // Only works when both target and inflictor are real mobjs. P_SpawnDamageParticleGen(target, inflictor, damage); // Do the damage. target->health -= damage; if(target->health > 0) { // Still alive, phew! if((P_Random() < target->info->painChance) && !(target->flags & MF_SKULLFLY)) { statenum_t state; target->flags |= MF_JUSTHIT; // Fight back! if((state = P_GetState(target->type, SN_PAIN)) != S_NULL) P_MobjChangeState(target, state); } target->reactionTime = 0; // We're awake now... if(source && !target->threshold && !(source->flags3 & MF3_NOINFIGHT) && !(target->type == MT_SORCERER2 && source->type == MT_WIZARD)) { statenum_t state; // Target mobj is not intent on another mobj, so make it chase // after the source of the damage. target->target = source; target->threshold = BASETHRESHOLD; if((state = P_GetState(target->type, SN_SEE)) != S_NULL && target->state == &STATES[P_GetState(target->type, SN_SPAWN)]) { P_MobjChangeState(target, state); } } } else { // Death. target->special1 = damage; if(target->type == MT_POD && source && source->type != MT_POD) { // Make sure players get frags for chain-reaction kills. target->target = source; } if(player && inflictor && !player->morphTics) { // Check for flame death. if((inflictor->flags2 & MF2_FIREDAMAGE) || ((inflictor->type == MT_PHOENIXFX1) && (target->health > -50) && (damage > 25))) { target->flags2 |= MF2_FIREDAMAGE; } } P_KillMobj(source, target); } return originalHealth - target->health; #undef BASETHRESHOLD } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_pspr.c0000644000175000017500000015742211357170242022614 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.c: Weapon sprite animation, weapon objects. * * Action functions for weapons. */ #ifdef MSVC // Sumtin' 'ere messes with poor ol' MSVC's head... # pragma optimize("g", off) #endif // HEADER FILES ------------------------------------------------------------ #include #include "jheretic.h" #include "d_net.h" #include "p_player.h" #include "p_map.h" #include "p_tick.h" #include "p_terraintype.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ #define LOWERSPEED (6) #define RAISESPEED (6) #define WEAPONBOTTOM (128) #define WEAPONTOP (32) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- /* AT_CRYSTAL, AT_ARROW, AT_ORB, AT_RUNE, AT_FIREORB, AT_MSPHERE, */ weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES] = { { { { { // Staff GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_STAFFUP, S_STAFFDOWN, S_STAFFREADY, S_STAFFATK1_1, S_STAFFATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // Staff lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_STAFFUP2, S_STAFFDOWN2, S_STAFFREADY2_1, S_STAFFATK2_1, S_STAFFATK2_1, S_NULL }, 0, // raise sound id SFX_STFCRK // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } } }, { { { { // Gold wand GM_ANY, // gamemodebits {1, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {USE_GWND_AMMO_1, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_GOLDWANDUP, S_GOLDWANDDOWN, S_GOLDWANDREADY, S_GOLDWANDATK1_1, S_GOLDWANDATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {1, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {USE_GWND_AMMO_2, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_GOLDWANDUP, S_GOLDWANDDOWN, S_GOLDWANDREADY, S_GOLDWANDATK2_1, S_GOLDWANDATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } } }, { { { { // Crossbow GM_ANY, // gamemodebits {0, 1, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, USE_CBOW_AMMO_1, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_CRBOWUP, S_CRBOWDOWN, S_CRBOW1, S_CRBOWATK1_1, S_CRBOWATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 1, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, USE_CBOW_AMMO_2, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_CRBOWUP, S_CRBOWDOWN, S_CRBOW1, S_CRBOWATK2_1, S_CRBOWATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } } }, { { { { // Blaster GM_ANY, // gamemodebits {0, 0, 1, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, USE_BLSR_AMMO_1, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BLASTERUP, S_BLASTERDOWN, S_BLASTERREADY, S_BLASTERATK1_1, S_BLASTERATK1_3, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 1, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, USE_BLSR_AMMO_2, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BLASTERUP, S_BLASTERDOWN, S_BLASTERREADY, S_BLASTERATK2_1, S_BLASTERATK2_3, S_NULL }, 0, // raise sound id 0 // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } } }, { { { { // Skull rod GM_NOTSHAREWARE, // gamemodebits {0, 0, 0, 1, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, USE_SKRD_AMMO_1, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_HORNRODUP, S_HORNRODDOWN, S_HORNRODREADY, S_HORNRODATK1_1, S_HORNRODATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_NOTSHAREWARE, // gamemodebits {0, 0, 0, 1, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, USE_SKRD_AMMO_2, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_HORNRODUP, S_HORNRODDOWN, S_HORNRODREADY, S_HORNRODATK2_1, S_HORNRODATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } } }, { { { { // Phoenix rod GM_NOTSHAREWARE, // gamemodebits {0, 0, 0, 0, 1, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, USE_PHRD_AMMO_1, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... false, // autofire when raised if fire held { S_PHOENIXUP, S_PHOENIXDOWN, S_PHOENIXREADY, S_PHOENIXATK1_1, S_PHOENIXATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_NOTSHAREWARE, // gamemodebits {0, 0, 0, 0, 1, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, USE_PHRD_AMMO_2, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... false, // autofire when raised if fire held { S_PHOENIXUP, S_PHOENIXDOWN, S_PHOENIXREADY, S_PHOENIXATK2_1, S_PHOENIXATK2_2, S_NULL }, 0, // raise sound id 0 // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } } }, { { { { // Mace GM_NOTSHAREWARE, // gamemodebits {0, 0, 0, 0, 0, 1}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, USE_MACE_AMMO_1}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_MACEUP, S_MACEDOWN, S_MACEREADY, S_MACEATK1_1, S_MACEATK1_2, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_NOTSHAREWARE, // gamemodebits {0, 0, 0, 0, 0, 1}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, USE_MACE_AMMO_2}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_MACEUP, S_MACEDOWN, S_MACEREADY, S_MACEATK2_1, S_MACEATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0, // readysound } } } }, { { { { // Gauntlets GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_GAUNTLETUP, S_GAUNTLETDOWN, S_GAUNTLETREADY, S_GAUNTLETATK1_1, S_GAUNTLETATK1_3, S_NULL }, SFX_GNTACT, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_GAUNTLETUP2, S_GAUNTLETDOWN2, S_GAUNTLETREADY2_1, S_GAUNTLETATK2_1, S_GAUNTLETATK2_3, S_NULL }, SFX_GNTACT, // raise sound id 0 // readysound } } }, { { { // Beak GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK1_1, S_BEAKATK1_1, S_NULL }, 0, // raise sound id 0 // readysound }, // lvl2 { GM_ANY, // gamemodebits {0, 0, 0, 0, 0, 0}, // type: AT_CRYSTAL | AT_ARROW | etc... {0, 0, 0, 0, 0, 0}, // pershot: AT_CRYSTAL | AT_ARROW | etc... true, // autofire when raised if fire held { S_BEAKUP, S_BEAKDOWN, S_BEAKREADY, S_BEAKATK2_1, S_BEAKATK2_1, S_NULL }, 0, // raise sound id 0 // readysound } } } } }; float bulletSlope; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void R_GetWeaponBob(int player, float* x, float* y) { if(x) { *x = 1 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finecosine[(128 * mapTime) & FINEMASK]); } if(y) { *y = 32 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finesine[(128 * mapTime) & FINEMASK & (FINEANGLES / 2 - 1)]); } } /** *Initialize weapon info, maxammo and clipammo. */ void P_InitWeaponInfo(void) { #define WPINF "Weapon Info|" int pclass = PCLASS_PLAYER; int i; char buf[80]; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { // Level 1 (don't use a sublevel for level 1) sprintf(buf, WPINF "%i|Static", i); weaponInfo[i][pclass].mode[0].staticSwitch = GetDefInt(buf, 0); // Level 2 sprintf(buf, WPINF "%i|2|Static", i); weaponInfo[i][pclass].mode[1].staticSwitch = GetDefInt(buf, 0); } /// \todo Get this info from values. P_InitWeaponSlots(); P_SetWeaponSlot(WT_FIRST, 1); P_SetWeaponSlot(WT_EIGHTH, 1); P_SetWeaponSlot(WT_SECOND, 2); P_SetWeaponSlot(WT_THIRD, 3); P_SetWeaponSlot(WT_FOURTH, 4); P_SetWeaponSlot(WT_FIFTH, 5); P_SetWeaponSlot(WT_SIXTH, 6); P_SetWeaponSlot(WT_SEVENTH, 7); #undef WPINF } void P_SetPsprite(player_t *player, int position, statenum_t stnum) { pspdef_t *psp; state_t *state; psp = &player->pSprites[position]; do { if(!stnum) { // Object removed itself. psp->state = NULL; break; } state = &STATES[stnum]; psp->state = state; psp->tics = state->tics; // Could be 0. if(state->misc[0]) { // Set coordinates. psp->pos[VX] = (float) state->misc[0]; psp->pos[VY] = (float) state->misc[1]; } if(state->action) { // Call action routine. state->action(player, psp); if(!psp->state) { break; } } stnum = psp->state->nextState; } while(!psp->tics); // An initial state of 0 could cycle through. } void P_ActivateMorphWeapon(player_t *player) { player->pendingWeapon = WT_NOCHANGE; player->readyWeapon = WT_FIRST; player->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; player->pSprites[ps_weapon].pos[VY] = WEAPONTOP; P_SetPsprite(player, ps_weapon, S_BEAKREADY); NetSv_PSpriteChange(player - players, S_BEAKREADY); } void P_PostMorphWeapon(player_t *player, weapontype_t weapon) { player->pendingWeapon = WT_NOCHANGE; player->readyWeapon = weapon; player->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; player->pSprites[ps_weapon].pos[VY] = WEAPONBOTTOM; P_SetPsprite(player, ps_weapon, weaponInfo[weapon][player->class].mode[0].states[WSN_UP]); } /** * Starts bringing the pending weapon up from the bottom of the screen. */ void P_BringUpWeapon(player_t *player) { weaponmodeinfo_t *wminfo; wminfo = WEAPON_INFO(player->pendingWeapon, player->class, (player->powers[PT_WEAPONLEVEL2]? 1:0)); if(player->pendingWeapon == WT_NOCHANGE) player->pendingWeapon = player->readyWeapon; if(wminfo->raiseSound) S_StartSoundEx(wminfo->raiseSound, player->plr->mo); player->pendingWeapon = WT_NOCHANGE; player->pSprites[ps_weapon].pos[VY] = WEAPONBOTTOM; P_SetPsprite(player, ps_weapon, wminfo->states[WSN_UP]); } void P_FireWeapon(player_t *player) { statenum_t attackState; int lvl = (player->powers[PT_WEAPONLEVEL2]? 1 : 0); if(!P_CheckAmmo(player)) return; P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackState); if(player->refire) attackState = weaponInfo[player->readyWeapon][player->class].mode[lvl].states[WSN_ATTACK_HOLD]; else attackState = weaponInfo[player->readyWeapon][player->class].mode[lvl].states[WSN_ATTACK]; NetSv_PSpriteChange(player - players, attackState); P_SetPsprite(player, ps_weapon, attackState); P_NoiseAlert(player->plr->mo, player->plr->mo); if(player->readyWeapon == WT_EIGHTH && !player->refire) { // Play the sound for the initial gauntlet attack S_StartSoundEx(SFX_GNTUSE, player->plr->mo); } player->update |= PSF_AMMO; // Psprite state. player->plr->pSprites[0].state = DDPSP_FIRE; } /** * The player died, so put the weapon away. */ void P_DropWeapon(player_t *player) { int level; if(player->powers[PT_WEAPONLEVEL2]) level = 1; else level = 0; P_SetPsprite(player, ps_weapon, weaponInfo[player->readyWeapon][player->class].mode[level].states[WSN_DOWN]); } /** * The player can fire the weapon or change to another weapon at this time. */ void C_DECL A_WeaponReady(player_t *player, pspdef_t *psp) { weaponmodeinfo_t *wminfo; ddpsprite_t *ddpsp; // Change player from attack state if(player->plr->mo->state == &STATES[S_PLAY_ATK1] || player->plr->mo->state == &STATES[S_PLAY_ATK2]) { P_MobjChangeState(player->plr->mo, S_PLAY); } if(player->readyWeapon != WT_NOCHANGE) { wminfo = WEAPON_INFO(player->readyWeapon, player->class, (player->powers[PT_WEAPONLEVEL2]?1:0)); // A weaponready sound? if(psp->state == &STATES[wminfo->states[WSN_READY]] && wminfo->readySound) #if __JHERETIC__ if(P_Random() < 128) #endif S_StartSoundEx(wminfo->readySound, player->plr->mo); // Check for change if player is dead, put the weapon away. if(player->pendingWeapon != WT_NOCHANGE || !player->health) { // (pending weapon should allready be validated) P_SetPsprite(player, ps_weapon, wminfo->states[WSN_DOWN]); return; } } // Check for autofire. if(player->brain.attack) { wminfo = WEAPON_INFO(player->readyWeapon, player->class, 0); if(!player->attackDown || wminfo->autoFire) { player->attackDown = true; P_FireWeapon(player); return; } } else player->attackDown = false; ddpsp = player->plr->pSprites; if(!player->morphTics) { // Bob the weapon based on movement speed. R_GetWeaponBob(player - players, &psp->pos[0], &psp->pos[1]); ddpsp->offset[0] = ddpsp->offset[1] = 0; } // Psprite state. ddpsp->state = DDPSP_BOBBING; } void P_UpdateBeak(player_t *player, pspdef_t *psp) { psp->pos[VY] = WEAPONTOP + FIX2FLT(player->chickenPeck << (FRACBITS - 1)); } void C_DECL A_BeakReady(player_t *player, pspdef_t *psp) { if(player->brain.attack) { // Chicken beak attack. player->attackDown = true; P_MobjChangeState(player->plr->mo, S_CHICPLAY_ATK1); if(player->powers[PT_WEAPONLEVEL2]) { P_SetPsprite(player, ps_weapon, S_BEAKATK2_1); NetSv_PSpriteChange(player - players, S_BEAKATK2_1); } else { P_SetPsprite(player, ps_weapon, S_BEAKATK1_1); NetSv_PSpriteChange(player - players, S_BEAKATK1_1); } P_NoiseAlert(player->plr->mo, player->plr->mo); } else { if(player->plr->mo->state == &STATES[S_CHICPLAY_ATK1]) { // Take out of attack state. P_MobjChangeState(player->plr->mo, S_CHICPLAY); } player->attackDown = false; } } /** * The player can re fire the weapon without lowering it entirely. */ void C_DECL A_ReFire(player_t *player, pspdef_t *psp) { if((player->brain.attack) && player->pendingWeapon == WT_NOCHANGE && player->health) { player->refire++; P_FireWeapon(player); } else { player->refire = 0; P_CheckAmmo(player); } } /** * Lowers current weapon, and changes weapon at bottom. */ void C_DECL A_Lower(player_t *player, pspdef_t *psp) { if(player->morphTics) psp->pos[VY] = WEAPONBOTTOM; else psp->pos[VY] += LOWERSPEED; // Psprite state. player->plr->pSprites[0].state = DDPSP_DOWN; // Should we disable the lowering? if(!cfg.bobWeaponLower || ((player->powers[PT_WEAPONLEVEL2] && weaponInfo[player->readyWeapon][player->class].mode[1].staticSwitch) || weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch)) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 0); } // Is already down. if(psp->pos[VY] < WEAPONBOTTOM) return; // Player is dead. if(player->playerState == PST_DEAD) { psp->pos[VY] = WEAPONBOTTOM; // Don't bring weapon back up. return; } // The old weapon has been lowered off the screen, so change the weapon // and start raising it. if(!player->health) { // Player is dead, so keep the weapon off screen. P_SetPsprite(player, ps_weapon, S_NULL); return; } player->readyWeapon = player->pendingWeapon; // Should we suddenly lower the weapon? if(cfg.bobWeaponLower && ((player->powers[PT_WEAPONLEVEL2] && !weaponInfo[player->readyWeapon][player->class].mode[1].staticSwitch) || !weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch)) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); } P_BringUpWeapon(player); } void C_DECL A_BeakRaise(player_t *player, pspdef_t *psp) { psp->pos[VY] = WEAPONTOP; P_SetPsprite(player, ps_weapon, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_READY]); } void C_DECL A_Raise(player_t *player, pspdef_t *psp) { statenum_t newstate; // Psprite state. player->plr->pSprites[0].state = DDPSP_UP; // Should we disable the lowering? if(!cfg.bobWeaponLower || ((player->powers[PT_WEAPONLEVEL2] && weaponInfo[player->readyWeapon][player->class].mode[1].staticSwitch) || weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch)) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 0); } psp->pos[VY] -= RAISESPEED; if(psp->pos[VY] > WEAPONTOP) return; // Enable the pspr Y offset once again. DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); psp->pos[VY] = WEAPONTOP; // The weapon has been raised all the way, // so change to the ready state. if(player->powers[PT_WEAPONLEVEL2]) newstate = weaponInfo[player->readyWeapon][player->class].mode[1].states[WSN_READY]; else newstate = weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_READY]; P_SetPsprite(player, ps_weapon, newstate); } /** * Sets a slope so a near miss is at aproximately the height of the * intended target. */ void P_BulletSlope(mobj_t *mo) { angle_t an = mo->angle; if(!cfg.noAutoAim) // Autoaiming enabled. { // See which target is to be aimed at. bulletSlope = P_AimLineAttack(mo, an, 16 * 64); if(!lineTarget) { // No target yet, look closer. an += 1 << 26; bulletSlope = P_AimLineAttack(mo, an, 16 * 64); if(!lineTarget) { an -= 2 << 26; bulletSlope = P_AimLineAttack(mo, an, 16 * 64); } } if(lineTarget) { // Found a target, we're done. return; } } // Fall back to manual aiming by lookdir. bulletSlope = tan(LOOKDIR2RAD(mo->dPlayer->lookDir)) / 1.2; } void C_DECL A_BeakAttackPL1(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); damage = 1 + (P_Random() & 3); angle = player->plr->mo->angle; slope = P_AimLineAttack(player->plr->mo, angle, MELEERANGE); puffType = MT_BEAKPUFF; P_LineAttack(player->plr->mo, angle, MELEERANGE, slope, damage); if(lineTarget) { player->plr->mo->angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); } S_StartSoundEx(SFX_CHICPK1 + (P_Random() % 3), player->plr->mo); player->chickenPeck = 12; psp->tics -= P_Random() & 7; } void C_DECL A_BeakAttackPL2(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); damage = HITDICE(4); angle = player->plr->mo->angle; slope = P_AimLineAttack(player->plr->mo, angle, MELEERANGE); puffType = MT_BEAKPUFF; P_LineAttack(player->plr->mo, angle, MELEERANGE, slope, damage); if(lineTarget) { player->plr->mo->angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); } S_StartSoundEx(SFX_CHICPK1 + (P_Random() % 3), player->plr->mo); player->chickenPeck = 12; psp->tics -= P_Random() & 3; } void C_DECL A_StaffAttackPL1(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); damage = 5 + (P_Random() & 15); angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; slope = P_AimLineAttack(player->plr->mo, angle, MELEERANGE); puffType = MT_STAFFPUFF; P_LineAttack(player->plr->mo, angle, MELEERANGE, slope, damage); if(lineTarget) { // Turn to face target. player->plr->mo->angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); } } void C_DECL A_StaffAttackPL2(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); damage = 18 + (P_Random() & 63); angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; slope = P_AimLineAttack(player->plr->mo, angle, MELEERANGE); puffType = MT_STAFFPUFF2; P_LineAttack(player->plr->mo, angle, MELEERANGE, slope, damage); if(lineTarget) { // Turn to face target. player->plr->mo->angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); } } void C_DECL A_FireBlasterPL1(player_t *player, pspdef_t *psp) { mobj_t *mo; angle_t angle; int damage; mo = player->plr->mo; S_StartSoundEx(SFX_GLDHIT, mo); P_ShotAmmo(player); P_BulletSlope(mo); damage = HITDICE(4); angle = mo->angle; if(player->refire) { angle += (P_Random() - P_Random()) << 18; } puffType = MT_BLASTERPUFF1; P_LineAttack(mo, angle, MISSILERANGE, bulletSlope, damage); S_StartSoundEx(SFX_BLSSHT, mo); } void C_DECL A_FireBlasterPL2(player_t* player, pspdef_t* psp) { P_ShotAmmo(player); S_StartSoundEx(SFX_BLSSHT, player->plr->mo); if(IS_CLIENT) return; P_SpawnMissile(MT_BLASTERFX1, player->plr->mo, NULL, true); } void C_DECL A_FireGoldWandPL1(player_t *player, pspdef_t *psp) { mobj_t *mo; angle_t angle; int damage; mo = player->plr->mo; P_ShotAmmo(player); S_StartSoundEx(SFX_GLDHIT, player->plr->mo); if(IS_CLIENT) return; P_BulletSlope(mo); damage = 7 + (P_Random() & 7); angle = mo->angle; if(player->refire) { angle += (P_Random() - P_Random()) << 18; } puffType = MT_GOLDWANDPUFF1; P_LineAttack(mo, angle, MISSILERANGE, bulletSlope, damage); } void C_DECL A_FireGoldWandPL2(player_t *player, pspdef_t *psp) { int i; mobj_t *mo; angle_t angle; int damage; float momZ; mo = player->plr->mo; P_ShotAmmo(player); S_StartSoundEx(SFX_GLDHIT, player->plr->mo); if(IS_CLIENT) return; puffType = MT_GOLDWANDPUFF2; P_BulletSlope(mo); momZ = MOBJINFO[MT_GOLDWANDFX2].speed * bulletSlope; P_SpawnMissileAngle(MT_GOLDWANDFX2, mo, mo->angle - (ANG45 / 8), momZ); P_SpawnMissileAngle(MT_GOLDWANDFX2, mo, mo->angle + (ANG45 / 8), momZ); angle = mo->angle - (ANG45 / 8); for(i = 0; i < 5; ++i) { damage = 1 + (P_Random() & 7); P_LineAttack(mo, angle, MISSILERANGE, bulletSlope, damage); angle += ((ANG45 / 8) * 2) / 4; } } void C_DECL A_FireMacePL1B(player_t *player, pspdef_t *psp) { mobj_t *pmo, *ball; uint an; if(!P_CheckAmmo(player)) return; P_ShotAmmo(player); if(IS_CLIENT) return; pmo = player->plr->mo; if((ball = P_SpawnMobj3f(MT_MACEFX2, pmo->pos[VX], pmo->pos[VY], pmo->pos[VZ] - pmo->floorClip + 28, pmo->angle, 0))) { ball->mom[MZ] = 2 + FIX2FLT(((int) player->plr->lookDir) << (FRACBITS - 5)); ball->target = pmo; ball->pos[VZ] += FIX2FLT(((int) player->plr->lookDir) << (FRACBITS - 4)); an = ball->angle >> ANGLETOFINESHIFT; ball->mom[MX] = (pmo->mom[MX] / 2) + ball->info->speed * FIX2FLT(finecosine[an]); ball->mom[MY] = (pmo->mom[MY] / 2) + ball->info->speed * FIX2FLT(finesine[an]); P_CheckMissileSpawn(ball); S_StartSound(SFX_LOBSHT, ball); } } void C_DECL A_FireMacePL1(player_t *player, pspdef_t *psp) { mobj_t *ball; if(P_Random() < 28) { A_FireMacePL1B(player, psp); return; } if(!P_CheckAmmo(player)) return; P_ShotAmmo(player); psp->pos[VX] = ((P_Random() & 3) - 2); psp->pos[VY] = WEAPONTOP + (P_Random() & 3); if(IS_CLIENT) return; ball = P_SpawnMissileAngle(MT_MACEFX1, player->plr->mo, player->plr->mo->angle + (((P_Random() & 7) - 4) << 24), -12345); if(ball) { ball->special1 = 16; // Tics till dropoff. } } void C_DECL A_MacePL1Check(mobj_t *ball) { uint an; if(ball->special1 == 0) { return; } ball->special1 -= 4; if(ball->special1 > 0) { return; } ball->special1 = 0; ball->flags2 |= MF2_LOGRAV; an = ball->angle >> ANGLETOFINESHIFT; ball->mom[MX] = 7 * FIX2FLT(finecosine[an]); ball->mom[MY] = 7 * FIX2FLT(finesine[an]); ball->mom[MZ] /= 2; } void C_DECL A_MaceBallImpact(mobj_t *ball) { if(ball->pos[VZ] <= ball->floorZ && P_HitFloor(ball)) { // Landed in some sort of liquid. P_MobjRemove(ball, true); return; } if(ball->special3 != MAGIC_JUNK && ball->pos[VZ] <= ball->floorZ && ball->mom[MZ] != 0) { // Bounce. ball->special3 = MAGIC_JUNK; ball->mom[MZ] = FIX2FLT(FLT2FIX(ball->mom[MZ] * 192) >> 8); ball->flags2 &= ~MF2_FLOORBOUNCE; P_MobjChangeState(ball, P_GetState(ball->type, SN_SPAWN)); S_StartSound(SFX_BOUNCE, ball); } else { // Explode. ball->flags |= MF_NOGRAVITY; ball->flags2 &= ~MF2_LOGRAV; S_StartSound(SFX_LOBHIT, ball); } } void C_DECL A_MaceBallImpact2(mobj_t *ball) { if(ball->pos[VZ] <= ball->floorZ && P_HitFloor(ball)) { // Landed in some sort of liquid. P_MobjRemove(ball, true); return; } if(ball->pos[VZ] != ball->floorZ || ball->mom[MZ] < 2) { // Explode ball->mom[MX] = ball->mom[MY] = ball->mom[MZ] = 0; ball->flags |= MF_NOGRAVITY; ball->flags2 &= ~(MF2_LOGRAV | MF2_FLOORBOUNCE); } else { // Bounce mobj_t* tiny; unsigned int an; ball->mom[MZ] = FIX2FLT(FLT2FIX(ball->mom[MZ] * 192) >> 8); P_MobjChangeState(ball, P_GetState(ball->type, SN_SPAWN)); if((tiny = P_SpawnMobj3fv(MT_MACEFX3, ball->pos, ball->angle + ANG90, 0))) { tiny->target = ball->target; an = tiny->angle >> ANGLETOFINESHIFT; tiny->mom[MX] = (ball->mom[MX] / 2) + ((ball->mom[MZ] - 1) * FIX2FLT(finecosine[an])); tiny->mom[MY] = (ball->mom[MY] / 2) + ((ball->mom[MZ] - 1) * FIX2FLT(finesine[an])); tiny->mom[MZ] = ball->mom[MZ]; P_CheckMissileSpawn(tiny); } if((tiny = P_SpawnMobj3fv(MT_MACEFX3, ball->pos, ball->angle - ANG90, 0))) { tiny->target = ball->target; an = tiny->angle >> ANGLETOFINESHIFT; tiny->mom[MX] = (ball->mom[MX] / 2) + ((ball->mom[MZ] - 1) * FIX2FLT(finecosine[an])); tiny->mom[MY] = (ball->mom[MY] / 2) + ((ball->mom[MZ] - 1) * FIX2FLT(finesine[an])); tiny->mom[MZ] = ball->mom[MZ]; P_CheckMissileSpawn(tiny); } } } void C_DECL A_FireMacePL2(player_t *player, pspdef_t *psp) { mobj_t *mo; P_ShotAmmo(player); S_StartSoundEx(SFX_LOBSHT, player->plr->mo); if(IS_CLIENT) return; mo = P_SpawnMissile(MT_MACEFX4, player->plr->mo, NULL, true); if(mo) { mo->mom[MX] += player->plr->mo->mom[MX]; mo->mom[MY] += player->plr->mo->mom[MY]; mo->mom[MZ] = 2 + FIX2FLT(((int) player->plr->lookDir) << (FRACBITS - 5)); if(lineTarget) mo->tracer = lineTarget; } } void C_DECL A_DeathBallImpact(mobj_t *ball) { int i; mobj_t *target; angle_t angle; boolean newAngle; if(ball->pos[VZ] <= ball->floorZ && P_HitFloor(ball)) { // Landed in some sort of liquid. P_MobjRemove(ball, true); return; } if(ball->pos[VZ] <= ball->floorZ && ball->mom[MZ] != 0) { // Bounce. newAngle = false; target = ball->tracer; angle = 0; if(target) { if(!(target->flags & MF_SHOOTABLE)) { // Target died. ball->tracer = NULL; } else { // Seek. angle = R_PointToAngle2(ball->pos[VX], ball->pos[VY], target->pos[VX], target->pos[VY]); newAngle = true; } } else { // Find new target. for(i = 0; i < 16; ++i) { P_AimLineAttack(ball, angle, 10 * 64); if(lineTarget && ball->target != lineTarget) { ball->tracer = lineTarget; angle = R_PointToAngle2(ball->pos[VX], ball->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); newAngle = true; break; } angle += ANGLE_45 / 2; } } if(newAngle) { uint an = angle >> ANGLETOFINESHIFT; ball->angle = angle; ball->mom[MX] = ball->info->speed * FIX2FLT(finecosine[an]); ball->mom[MY] = ball->info->speed * FIX2FLT(finesine[an]); } P_MobjChangeState(ball, P_GetState(ball->type, SN_SPAWN)); S_StartSound(SFX_PSTOP, ball); } else { // Explode. ball->flags |= MF_NOGRAVITY; ball->flags2 &= ~MF2_LOGRAV; S_StartSound(SFX_PHOHIT, ball); } } void C_DECL A_SpawnRippers(mobj_t* actor) { int i; for(i = 0; i < 8; ++i) { angle_t angle = i * ANG45; uint an; mobj_t* ripper; if((ripper = P_SpawnMobj3fv(MT_RIPPER, actor->pos, angle, 0))) { ripper->target = actor->target; an = angle >> ANGLETOFINESHIFT; ripper->mom[MX] = ripper->info->speed * FIX2FLT(finecosine[an]); ripper->mom[MY] = ripper->info->speed * FIX2FLT(finesine[an]); P_CheckMissileSpawn(ripper); } } } void C_DECL A_FireCrossbowPL1(player_t* player, pspdef_t* psp) { mobj_t* pmo; pmo = player->plr->mo; P_ShotAmmo(player); if(IS_CLIENT) return; P_SpawnMissile(MT_CRBOWFX1, pmo, NULL, true); P_SpawnMissileAngle(MT_CRBOWFX3, pmo, pmo->angle - (ANG45 / 10), -12345); P_SpawnMissileAngle(MT_CRBOWFX3, pmo, pmo->angle + (ANG45 / 10), -12345); } void C_DECL A_FireCrossbowPL2(player_t* player, pspdef_t* psp) { mobj_t* pmo; pmo = player->plr->mo; P_ShotAmmo(player); if(IS_CLIENT) return; P_SpawnMissile(MT_CRBOWFX2, pmo, NULL, true); P_SpawnMissileAngle(MT_CRBOWFX2, pmo, pmo->angle - (ANG45 / 10), -12345); P_SpawnMissileAngle(MT_CRBOWFX2, pmo, pmo->angle + (ANG45 / 10), -12345); P_SpawnMissileAngle(MT_CRBOWFX3, pmo, pmo->angle - (ANG45 / 5), -12345); P_SpawnMissileAngle(MT_CRBOWFX3, pmo, pmo->angle + (ANG45 / 5), -12345); } void C_DECL A_BoltSpark(mobj_t* bolt) { mobj_t* spark; if(P_Random() > 50) { if((spark = P_SpawnMobj3fv(MT_CRBOWFX4, bolt->pos, P_Random() << 24, 0))) { spark->pos[VX] += FIX2FLT((P_Random() - P_Random()) << 10); spark->pos[VY] += FIX2FLT((P_Random() - P_Random()) << 10); } } } void C_DECL A_FireSkullRodPL1(player_t* player, pspdef_t* psp) { mobj_t* mo; if(!P_CheckAmmo(player)) return; P_ShotAmmo(player); if(IS_CLIENT) return; if((mo = P_SpawnMissile(MT_HORNRODFX1, player->plr->mo, NULL, true))) { // Randomize the first frame if(mo && P_Random() > 128) { P_MobjChangeState(mo, S_HRODFX1_2); } } } /** * The special2 field holds the player number that shot the rain missile. * The special1 field is used as a counter for the sound looping. */ void C_DECL A_FireSkullRodPL2(player_t* player, pspdef_t* psp) { mobj_t* mo; P_ShotAmmo(player); if(IS_CLIENT) return; if((mo = P_SpawnMissile(MT_HORNRODFX2, player->plr->mo, NULL, true))) mo->special3 = 140; // Use MissileMobj instead of the return value from // P_SpawnMissile because we need to give info to the mobj // even if it exploded immediately. if(IS_NETGAME) { // Multi-player game. missileMobj->special2 = P_GetPlayerNum(player); } else { // Always use red missiles in single player games. missileMobj->special2 = 2; } if(lineTarget) missileMobj->tracer = lineTarget; S_StartSound(SFX_HRNPOW, missileMobj); } void C_DECL A_SkullRodPL2Seek(mobj_t *actor) { P_SeekerMissile(actor, ANGLE_1 * 10, ANGLE_1 * 30); } void C_DECL A_AddPlayerRain(mobj_t *actor) { int playerNum; player_t *player; playerNum = IS_NETGAME ? actor->special2 : 0; if(!players[playerNum].plr->inGame) { // Player not left the game. return; } player = &players[playerNum]; if(player->health <= 0) { // Player is dead. return; } if(player->rain1 && player->rain2) { // Terminate an active rain. if(player->rain1->special3 < player->rain2->special3) { if(player->rain1->special3 > 16) { player->rain1->special3 = 16; } player->rain1 = NULL; } else { if(player->rain2->special3 > 16) { player->rain2->special3 = 16; } player->rain2 = NULL; } } // Add rain mobj to list. if(player->rain1) { player->rain2 = actor; } else { player->rain1 = actor; } } void C_DECL A_SkullRodStorm(mobj_t *actor) { float pos[3]; mobj_t *mo; int playerNum; player_t *player; if(actor->special3-- == 0) { P_MobjChangeState(actor, S_NULL); playerNum = (IS_NETGAME ? actor->special2 : 0); if(!players[playerNum].plr->inGame) { // Player not left the game. return; } player = &players[playerNum]; if(player->health <= 0) { // Player is dead. return; } if(player->rain1 == actor) { player->rain1 = NULL; } else if(player->rain2 == actor) { player->rain2 = NULL; } return; } if(P_Random() < 25) { // Fudge rain frequency. return; } pos[VX] = actor->pos[VX] + ((P_Random() & 127) - 64); pos[VY] = actor->pos[VY] + ((P_Random() & 127) - 64); if((mo = P_SpawnMobj3f(MT_RAINPLR1 + actor->special2, pos[VX], pos[VY], 0, P_Random() << 24, MSF_Z_CEIL))) { mo->flags |= MF_BRIGHTSHADOW; mo->target = actor->target; mo->mom[MX] = 1; // Force collision detection. mo->mom[MZ] = -mo->info->speed; mo->special2 = actor->special2; // Transfer player number. P_CheckMissileSpawn(mo); } if(!(actor->special1 & 31)) S_StartSound(SFX_RAMRAIN, actor); actor->special1++; } void C_DECL A_RainImpact(mobj_t *actor) { if(actor->pos[VZ] > actor->floorZ) { P_MobjChangeState(actor, S_RAINAIRXPLR1_1 + actor->special2); } else if(P_Random() < 40) { P_HitFloor(actor); } } void C_DECL A_HideInCeiling(mobj_t* actor) { actor->pos[VZ] = actor->ceilingZ + 4; } void C_DECL A_FirePhoenixPL1(player_t* player, pspdef_t* psp) { uint an; angle_t angle; P_ShotAmmo(player); if(IS_CLIENT) return; P_SpawnMissile(MT_PHOENIXFX1, player->plr->mo, NULL, true); angle = player->plr->mo->angle + ANG180; an = angle >> ANGLETOFINESHIFT; player->plr->mo->mom[MX] += 4 * FIX2FLT(finecosine[an]); player->plr->mo->mom[MY] += 4 * FIX2FLT(finesine[an]); } void C_DECL A_PhoenixPuff(mobj_t* actor) { mobj_t* puff; uint an; P_SeekerMissile(actor, ANGLE_1 * 5, ANGLE_1 * 10); if((puff = P_SpawnMobj3fv(MT_PHOENIXPUFF, actor->pos, actor->angle + ANG90, 0))) { an = puff->angle >> ANGLETOFINESHIFT; puff->mom[MX] = 1.3 * FIX2FLT(finecosine[an]); puff->mom[MY] = 1.3 * FIX2FLT(finesine[an]); puff->mom[MZ] = 0; } if((puff = P_SpawnMobj3fv(MT_PHOENIXPUFF, actor->pos, actor->angle - ANG90, 0))) { an = puff->angle >> ANGLETOFINESHIFT; puff->mom[MX] = 1.3 * FIX2FLT(finecosine[an]); puff->mom[MY] = 1.3 * FIX2FLT(finesine[an]); puff->mom[MZ] = 0; } } void C_DECL A_InitPhoenixPL2(player_t *player, pspdef_t *psp) { player->flameCount = FLAME_THROWER_TICS; } /** * Flame thrower effect. */ void C_DECL A_FirePhoenixPL2(player_t *player, pspdef_t *psp) { mobj_t *mo, *pmo; angle_t angle; uint an; float pos[3], slope; if(IS_CLIENT) return; if(--player->flameCount == 0) { // Out of flame P_SetPsprite(player, ps_weapon, S_PHOENIXATK2_4); NetSv_PSpriteChange(player - players, S_PHOENIXATK2_4); player->refire = 0; return; } pmo = player->plr->mo; angle = pmo->angle; memcpy(pos, pmo->pos, sizeof(pos)); pos[VX] += FIX2FLT((P_Random() - P_Random()) << 9); pos[VY] += FIX2FLT((P_Random() - P_Random()) << 9); pos[VZ] += 26 + player->plr->lookDir / 173; pos[VZ] -= pmo->floorClip; slope = sin(LOOKDIR2RAD(player->plr->lookDir)) / 1.2; if((mo = P_SpawnMobj3fv(MT_PHOENIXFX2, pos, angle, 0))) { mo->target = pmo; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = pmo->mom[MX] + mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = pmo->mom[MY] + mo->info->speed * FIX2FLT(finesine[an]); mo->mom[MZ] = mo->info->speed * slope; if(!player->refire || !(mapTime % 38)) { S_StartSoundEx(SFX_PHOPOW, player->plr->mo); } P_CheckMissileSpawn(mo); } } void C_DECL A_ShutdownPhoenixPL2(player_t *player, pspdef_t *psp) { P_ShotAmmo(player); } void C_DECL A_FlameEnd(mobj_t *actor) { actor->mom[MZ] += 1.5f; } void C_DECL A_FloatPuff(mobj_t *puff) { puff->mom[MZ] += 1.8f; } void C_DECL A_GauntletAttack(player_t *player, pspdef_t *psp) { angle_t angle; int damage, randVal; float slope, dist; P_ShotAmmo(player); psp->pos[VX] = ((P_Random() & 3) - 2); psp->pos[VY] = WEAPONTOP + (P_Random() & 3); angle = player->plr->mo->angle; if(player->powers[PT_WEAPONLEVEL2]) { damage = HITDICE(2); dist = 4 * MELEERANGE; angle += (P_Random() - P_Random()) << 17; puffType = MT_GAUNTLETPUFF2; } else { damage = HITDICE(2); dist = MELEERANGE + 1; angle += (P_Random() - P_Random()) << 18; puffType = MT_GAUNTLETPUFF1; } slope = P_AimLineAttack(player->plr->mo, angle, dist); P_LineAttack(player->plr->mo, angle, dist, slope, damage); if(!lineTarget) { if(P_Random() > 64) { player->plr->extraLight = !player->plr->extraLight; } S_StartSoundEx(SFX_GNTFUL, player->plr->mo); return; } randVal = P_Random(); if(randVal < 64) { player->plr->extraLight = 0; } else if(randVal < 160) { player->plr->extraLight = 1; } else { player->plr->extraLight = 2; } if(player->powers[PT_WEAPONLEVEL2]) { P_GiveBody(player, damage / 2); S_StartSoundEx(SFX_GNTPOW, player->plr->mo); } else { S_StartSoundEx(SFX_GNTHIT, player->plr->mo); } // Turn to face target. angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); if(angle - player->plr->mo->angle > ANG180) { if(angle - player->plr->mo->angle < -ANG90 / 20) player->plr->mo->angle = angle + ANG90 / 21; else player->plr->mo->angle -= ANG90 / 20; } else { if(angle - player->plr->mo->angle > ANG90 / 20) player->plr->mo->angle = angle - ANG90 / 21; else player->plr->mo->angle += ANG90 / 20; } player->plr->mo->flags |= MF_JUSTATTACKED; } void C_DECL A_Light0(player_t *player, pspdef_t *psp) { player->plr->extraLight = 0; } void C_DECL A_Light1(player_t *player, pspdef_t *psp) { player->plr->extraLight = 1; } void C_DECL A_Light2(player_t *player, pspdef_t *psp) { player->plr->extraLight = 2; } /** * Called at start of level for each player. */ void P_SetupPsprites(player_t* player) { int i; // Remove all psprites. for(i = 0; i < NUMPSPRITES; ++i) { player->pSprites[i].state = NULL; } // Spawn the ready weapon. if(player->pendingWeapon == WT_NOCHANGE) player->pendingWeapon = player->readyWeapon; P_BringUpWeapon(player); } /** * Called every tic by player thinking routine. */ void P_MovePsprites(player_t *player) { int i; pspdef_t *psp; state_t *state; psp = &player->pSprites[0]; for(i = 0; i < NUMPSPRITES; ++i, psp++) { // A null state means not active. state = psp->state; if(state) { // Drop tic count and possibly change state. // A -1 tic count never changes. if(psp->tics != -1) { psp->tics--; if(!psp->tics) { P_SetPsprite(player, i, psp->state->nextState); } } } } player->pSprites[ps_flash].pos[VX] = player->pSprites[ps_weapon].pos[VX]; player->pSprites[ps_flash].pos[VY] = player->pSprites[ps_weapon].pos[VY]; } void C_DECL A_FireBomb(mobj_t* mo) { uint an; mobj_t* bomb; if(!mo->player) return; an = mo->angle >> ANGLETOFINESHIFT; if((bomb = P_SpawnMobj3f(MT_FIREBOMB, mo->pos[VX] + 24 * FIX2FLT(finecosine[an]), mo->pos[VY] + 24 * FIX2FLT(finesine[an]), mo->pos[VZ] - mo->floorClip + 15, mo->angle, 0))) { bomb->target = mo; } didUseItem = true; } void C_DECL A_TombOfPower(mobj_t* mo) { player_t* player; if(!mo->player) return; player = mo->player; if(player->morphTics) { // Attempt to undo chicken. if(P_UndoPlayerMorph(player) == false) { // Failed. P_DamageMobj(player->plr->mo, NULL, NULL, 10000, false); } else { // Succeeded. player->morphTics = 0; S_StartSound(SFX_WPNUP, player->plr->mo); } } else { if(!P_GivePower(player, PT_WEAPONLEVEL2)) return; if(player->readyWeapon == WT_FIRST) { P_SetPsprite(player, ps_weapon, S_STAFFREADY2_1); } else if(player->readyWeapon == WT_EIGHTH) { P_SetPsprite(player, ps_weapon, S_GAUNTLETREADY2_1); } } didUseItem = true; } void C_DECL A_Egg(mobj_t* mo) { if(!mo->player) return; #if __JHEXEN__ P_SpawnPlayerMissile(MT_EGGFX, mo); P_SPMAngle(MT_EGGFX, mo, mo->angle - (ANG45 / 6)); P_SPMAngle(MT_EGGFX, mo, mo->angle + (ANG45 / 6)); P_SPMAngle(MT_EGGFX, mo, mo->angle - (ANG45 / 3)); P_SPMAngle(MT_EGGFX, mo, mo->angle + (ANG45 / 3)); #else P_SpawnMissile(MT_EGGFX, mo, NULL, true); P_SpawnMissileAngle(MT_EGGFX, mo, mo->angle - (ANG45 / 6), -12345); P_SpawnMissileAngle(MT_EGGFX, mo, mo->angle + (ANG45 / 6), -12345); P_SpawnMissileAngle(MT_EGGFX, mo, mo->angle - (ANG45 / 3), -12345); P_SpawnMissileAngle(MT_EGGFX, mo, mo->angle + (ANG45 / 3), -12345); #endif didUseItem = true; } void C_DECL A_Wings(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GivePower(mo->player, PT_FLIGHT); } void C_DECL A_Teleport(mobj_t* mo) { if(!mo->player) return; P_ArtiTele(mo->player); didUseItem = true; } void C_DECL A_Torch(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GivePower(mo->player, PT_INFRARED); } void C_DECL A_Health(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GiveBody(mo->player, 25); } void C_DECL A_SuperHealth(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GiveBody(mo->player, 100); } void C_DECL A_Invisibility(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GivePower(mo->player, PT_INVISIBILITY); } void C_DECL A_Invulnerability(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GivePower(mo->player, PT_INVULNERABILITY); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/m_cheat.c0000644000175000017500000006571011357170242022707 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_cheat.c: Cheat sequence checking. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jheretic.h" #include "f_infine.h" #include "d_net.h" #include "g_common.h" #include "p_player.h" #include "am_map.h" #include "hu_menu.h" #include "hu_msg.h" #include "dmu_lib.h" #include "p_user.h" #include "p_start.h" #include "p_inventory.h" #include "g_eventsequence.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- int Cht_GodFunc(const int* args, int player); int Cht_NoClipFunc(const int* args, int player); int Cht_WeaponsFunc(const int* args, int player); int Cht_PowerupFunc(const int* args, int player); int Cht_HealthFunc(const int* args, int player); int Cht_GiveKeysFunc(const int* args, int player); int Cht_InvItem1Func(const int* args, int player); int Cht_InvItem2Func(const int* args, int player); int Cht_InvItem3Func(const int* args, int player); int Cht_WarpFunc(const int* args, int player); int Cht_ChickenFunc(const int* args, int player); int Cht_MassacreFunc(const int* args, int player); int Cht_IDKFAFunc(const int* args, int player); int Cht_IDDQDFunc(const int* args, int player); int Cht_SoundFunc(const int* args, int player); int Cht_TickerFunc(const int* args, int player); int Cht_RevealFunc(const int* args, int player); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Toggle god mode. static unsigned char cheatGodSeq[] = { 'q', 'u', 'i', 'c', 'k', 'e', 'n' }; // Toggle no clipping mode. static unsigned char cheatNoClipSeq[] = { 'k', 'i', 't', 't', 'y' }; // Get all weapons and ammo. static unsigned char cheatWeaponsSeq[] = { 'r', 'a', 'm', 'b', 'o' }; // Toggle tome of power. static unsigned char cheatPowerSeq[] = { 's', 'h', 'a', 'z', 'a', 'm' }; // Get full health. static unsigned char cheatHealthSeq[] = { 'p', 'o', 'n', 'c', 'e' }; // Get all keys. static unsigned char cheatKeysSeq[] = { 's', 'k', 'e', 'l' }; // Toggle sound debug info. static unsigned char cheatSoundSeq[] = { 'n', 'o', 'i', 's', 'e' }; // Toggle ticker. static unsigned char cheatTickerSeq[] = { 't', 'i', 'c', 'k', 'e', 'r' }; // Get an inventory item 1st stage (ask for type). static unsigned char cheatInvItem1Seq[] = { 'g', 'i', 'm', 'm', 'e' }; // Get an inventory item 2nd stage (ask for count). static unsigned char cheatInvItem2Seq[] = { 'g', 'i', 'm', 'm', 'e', 1, 0 }; // Get an inventory item final stage. static unsigned char cheatInvItem3Seq[] = { 'g', 'i', 'm', 'm', 'e', 1, 0, 0 }; // Warp to new level. static unsigned char cheatWarpSeq[] = { 'e', 'n', 'g', 'a', 'g', 'e', 1, 0, 0 }; // Save a screenshot. static unsigned char cheatChickenSeq[] = { 'c', 'o', 'c', 'k', 'a', 'd', 'o', 'o', 'd', 'l', 'e', 'd', 'o', 'o' }; // Kill all monsters. static unsigned char cheatMassacreSeq[] = { 'm', 'a', 's', 's', 'a', 'c', 'r', 'e' }; static unsigned char cheatIDKFASeq[] = { 'i', 'd', 'k', 'f', 'a' }; static unsigned char cheatIDDQDSeq[] = { 'i', 'd', 'd', 'q', 'd' }; static unsigned char cheatAutomapSeq[] = { 'r', 'a', 'v', 'm', 'a', 'p' }; // CODE -------------------------------------------------------------------- static boolean cheatsEnabled(void) { return !IS_NETGAME; } void Cht_Init(void) { G_AddEventSequence(cheatAutomapSeq, sizeof(cheatAutomapSeq), Cht_RevealFunc); G_AddEventSequence(cheatGodSeq, sizeof(cheatGodSeq), Cht_GodFunc); G_AddEventSequence(cheatNoClipSeq, sizeof(cheatNoClipSeq), Cht_NoClipFunc); G_AddEventSequence(cheatWeaponsSeq, sizeof(cheatWeaponsSeq), Cht_WeaponsFunc); G_AddEventSequence(cheatPowerSeq, sizeof(cheatPowerSeq), Cht_PowerupFunc); G_AddEventSequence(cheatHealthSeq, sizeof(cheatHealthSeq), Cht_HealthFunc); G_AddEventSequence(cheatKeysSeq, sizeof(cheatKeysSeq), Cht_GiveKeysFunc); G_AddEventSequence(cheatSoundSeq, sizeof(cheatSoundSeq), Cht_SoundFunc); G_AddEventSequence(cheatTickerSeq, sizeof(cheatTickerSeq), Cht_TickerFunc); G_AddEventSequence(cheatInvItem3Seq, sizeof(cheatInvItem3Seq), Cht_InvItem3Func); G_AddEventSequence(cheatInvItem2Seq, sizeof(cheatInvItem2Seq), Cht_InvItem2Func); G_AddEventSequence(cheatInvItem1Seq, sizeof(cheatInvItem1Seq), Cht_InvItem1Func); G_AddEventSequence(cheatWarpSeq, sizeof(cheatWarpSeq), Cht_WarpFunc); G_AddEventSequence(cheatChickenSeq, sizeof(cheatChickenSeq), Cht_ChickenFunc); G_AddEventSequence(cheatMassacreSeq, sizeof(cheatMassacreSeq), Cht_MassacreFunc); G_AddEventSequence(cheatIDKFASeq, sizeof(cheatIDKFASeq), Cht_IDKFAFunc); G_AddEventSequence(cheatIDDQDSeq, sizeof(cheatIDDQDSeq), Cht_IDDQDFunc); } int Cht_GodFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->cheats ^= CF_GODMODE; plr->update |= PSF_STATE; P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_GODMODE) ? TXT_CHEATGODON : TXT_CHEATGODOFF), false); S_LocalSound(SFX_DORCLS, NULL); return true; } static void giveArmor(player_t* plr) { plr->update |= PSF_ARMOR_POINTS | PSF_STATE; plr->armorPoints = 200; plr->armorType = 2; } static void giveWeapons(player_t* plr) { int i; plr->update |= PSF_OWNED_WEAPONS; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { if(weaponInfo[i][0].mode[0].gameModeBits & gameModeBits) plr->weapons[i].owned = true; } } static void giveAmmo(player_t* plr) { int i; plr->update |= PSF_MAX_AMMO | PSF_AMMO; if(!plr->backpack) { for(i = 0; i < NUM_AMMO_TYPES; ++i) { plr->ammo[i].max *= 2; } plr->backpack = true; } for(i = 0; i < NUM_AMMO_TYPES; ++i) { plr->ammo[i].owned = plr->ammo[i].max; } } int Cht_WeaponsFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. giveWeapons(plr); giveAmmo(plr); giveArmor(plr); P_SetMessage(plr, TXT_CHEATWEAPONS, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_GiveKeysFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->update |= PSF_KEYS; plr->keys[KT_YELLOW] = true; plr->keys[KT_GREEN] = true; plr->keys[KT_BLUE] = true; P_SetMessage(plr, TXT_CHEATKEYS, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_NoClipFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->cheats ^= CF_NOCLIP; plr->update |= PSF_STATE; P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_NOCLIP) ? TXT_CHEATNOCLIPON : TXT_CHEATNOCLIPOFF), false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_WarpFunc(const int* args, int player) { player_t* plr = &players[player]; uint epsd, map; if(IS_NETGAME) return false; epsd = (args[0] > '0')? args[0] - '1' : 0; map = (args[1] > '0')? args[1] - '1' : 0; // Catch invalid maps. if(!G_ValidateMap(&epsd, &map)) return false; P_SetMessage(plr, TXT_CHEATWARP, false); S_LocalSound(SFX_DORCLS, NULL); // Clear the menu if open. Hu_MenuCommand(MCMD_CLOSE); // So be it. briefDisabled = true; G_DeferedInitNew(gameSkill, epsd, map); return true; } int Cht_PowerupFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->update |= PSF_POWERS; if(plr->powers[PT_WEAPONLEVEL2]) { plr->powers[PT_WEAPONLEVEL2] = 0; P_SetMessage(plr, TXT_CHEATPOWEROFF, false); } else { int plrnum = plr - players; P_InventoryGive(plrnum, IIT_TOMBOFPOWER, true); P_InventoryUse(plrnum, IIT_TOMBOFPOWER, true); P_SetMessage(plr, TXT_CHEATPOWERON, false); } S_LocalSound(SFX_DORCLS, NULL); return true; } static void printDebugInfo(int player) { player_t* plr = &players[player]; char lumpName[9], textBuffer[256]; subsector_t* sub; if(!plr->plr->mo || !userGame) return; P_GetMapLumpName(gameEpisode, gameMap, lumpName); sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", lumpName, plr->plr->mo->pos[VX], plr->plr->mo->pos[VY], plr->plr->mo->pos[VZ]); P_SetMessage(plr, textBuffer, false); // Also print some information to the console. Con_Message(textBuffer); sub = plr->plr->mo->subsector; Con_Message("\nSubsector %i:\n", P_ToIndex(sub)); Con_Message(" FloorZ:%g Material:%s\n", P_GetFloatp(sub, DMU_FLOOR_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_FLOOR_MATERIAL))); Con_Message(" CeilingZ:%g Material:%s\n", P_GetFloatp(sub, DMU_CEILING_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_CEILING_MATERIAL))); Con_Message("Player height:%g Player radius:%g\n", plr->plr->mo->height, plr->plr->mo->radius); } int Cht_HealthFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->update |= PSF_HEALTH; if(plr->morphTics) { plr->health = plr->plr->mo->health = MAXCHICKENHEALTH; } else { plr->health = plr->plr->mo->health = maxHealth; } P_SetMessage(plr, TXT_CHEATHEALTH, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_InvItem1Func(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, TXT_CHEATINVITEMS1, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_InvItem2Func(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, TXT_CHEATINVITEMS2, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_InvItem3Func(const int* args, int player) { player_t* plr = &players[player]; int i, count; inventoryitemtype_t type; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. type = args[0] - 'a' + 1; count = args[1] - '0'; if(type > IIT_NONE && type < NUM_INVENTORYITEM_TYPES && count > 0 && count < 10) { if(gameMode == shareware && (type == IIT_SUPERHEALTH || type == IIT_TELEPORT)) { P_SetMessage(plr, TXT_CHEATITEMSFAIL, false); return false; } for(i = 0; i < count; ++i) { P_InventoryGive(player, type, false); } P_SetMessage(plr, TXT_CHEATINVITEMS3, false); } else { // Bad input P_SetMessage(plr, TXT_CHEATITEMSFAIL, false); } S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_ChickenFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. if(plr->morphTics) { if(P_UndoPlayerMorph(plr)) { P_SetMessage(plr, TXT_CHEATCHICKENOFF, false); } } else if(P_MorphPlayer(plr)) { P_SetMessage(plr, TXT_CHEATCHICKENON, false); } S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_MassacreFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_Massacre(); P_SetMessage(plr, TXT_CHEATMASSACRE, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_IDKFAFunc(const int* args, int player) { player_t* plr = &players[player]; int i; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. if(plr->morphTics) { return false; } for(i = 0; i < NUM_WEAPON_TYPES; ++i) { plr->weapons[i].owned = false; } plr->pendingWeapon = WT_FIRST; P_SetMessage(plr, TXT_CHEATIDKFA, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_IDDQDFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_DamageMobj(plr->plr->mo, NULL, plr->plr->mo, 10000, false); P_SetMessage(plr, TXT_CHEATIDDQD, false); S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_SoundFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. // Otherwise ignored. S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_TickerFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. // Otherwise ignored. S_LocalSound(SFX_DORCLS, NULL); return true; } int Cht_RevealFunc(const int* args, int player) { player_t* plr = &players[player]; automapid_t map; if(IS_NETGAME && deathmatch) return false; if(plr->health <= 0) return false; // Dead players can't cheat. map = AM_MapForPlayer(player); if(!AM_IsActive(map)) return false; AM_IncMapCheatLevel(map); return true; } // This is the multipurpose cheat ccmd. DEFCC(CCmdCheat) { size_t i; // Give each of the characters in argument two to the SB event handler. for(i = 0; i < strlen(argv[1]); ++i) { event_t ev; ev.type = EV_KEY; ev.state = EVS_DOWN; ev.data1 = argv[1][i]; ev.data2 = ev.data3 = 0; G_EventSequenceResponder(&ev); } return true; } DEFCC(CCmdCheatGod) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("god"); } else { int player = CONSOLEPLAYER; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { player = atoi(argv[1]); if(player < 0 || player >= MAXPLAYERS) return false; } if(!players[player].plr->inGame) return false; Cht_GodFunc(NULL, player); } } return true; } DEFCC(CCmdCheatNoClip) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("noclip"); } else { int player = CONSOLEPLAYER; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { player = atoi(argv[1]); if(player < 0 || player >= MAXPLAYERS) return false; } if(!players[player].plr->inGame) return false; Cht_NoClipFunc(NULL, player); } } return true; } static int suicideResponse(msgresponse_t response, void* context) { if(response == MSG_YES) { if(IS_NETGAME && IS_CLIENT) { NetCl_CheatRequest("suicide"); } else { player_t* plr = &players[CONSOLEPLAYER]; P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); } } return true; } DEFCC(CCmdCheatSuicide) { if(G_GetGameState() == GS_MAP) { player_t* plr; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { int i = atoi(argv[1]); if(i < 0 || i >= MAXPLAYERS) return false; plr = &players[i]; } else plr = &players[CONSOLEPLAYER]; if(!plr->plr->inGame) return false; if(plr->playerState == PST_DEAD) return false; if(!IS_NETGAME || IS_CLIENT) { Hu_MsgStart(MSG_YESNO, SUICIDEASK, suicideResponse, NULL); return true; } P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); return true; } else { Hu_MsgStart(MSG_ANYKEY, SUICIDEOUTMAP, NULL, NULL); } return true; } DEFCC(CCmdCheatWarp) { int num, args[2]; if(!cheatsEnabled()) return false; if(argc == 2) { num = atoi(argv[1]); args[0] = num / 10 + '0'; args[1] = num % 10 + '0'; } else if(argc == 3) { args[0] = atoi(argv[1]) % 10 + '0'; args[1] = atoi(argv[2]) % 10 + '0'; } else { Con_Printf("Usage: warp (num)\n"); return true; } Cht_WarpFunc(args, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatReveal) { int option; automapid_t map; if(!cheatsEnabled()) return false; map = AM_MapForPlayer(CONSOLEPLAYER); AM_SetCheatLevel(map, 0); AM_RevealMap(map, false); option = atoi(argv[1]); if(option < 0 || option > 3) return false; if(option == 1) AM_RevealMap(map, true); else if(option != 0) AM_SetCheatLevel(map, option -1); return true; } DEFCC(CCmdCheatGive) { char buf[100]; int player = CONSOLEPLAYER; size_t i, stuffLen; if(IS_CLIENT) { if(argc != 2) return false; sprintf(buf, "give %s", argv[1]); NetCl_CheatRequest(buf); return true; } if(IS_NETGAME && !netSvAllowCheats) return false; if(argc != 2 && argc != 3) { Con_Printf("Usage:\n give (stuff)\n"); Con_Printf(" give (stuff) (plr)\n"); Con_Printf("Stuff consists of one or more of (type:id). " "If no id; give all of type:\n"); Con_Printf(" a - ammo\n"); Con_Printf(" i - items\n"); Con_Printf(" h - health\n"); Con_Printf(" k - keys\n"); Con_Printf(" p - backpack full of ammo\n"); Con_Printf(" r - armor\n"); Con_Printf(" t - tomb of power\n"); Con_Printf(" w - weapons\n"); Con_Printf("Example: 'give ikw' gives items, keys and weapons.\n"); Con_Printf("Example: 'give w2k1' gives weapon two and key one.\n"); return true; } if(argc == 3) { player = atoi(argv[2]); if(player < 0 || player >= MAXPLAYERS) return false; } if(G_GetGameState() != GS_MAP) { Con_Printf("Can only \"give\" when in a game!\n"); return true; } if(!players[player].plr->inGame) return true; // Can't give to a plr who's not playing. strcpy(buf, argv[1]); // Stuff is the 2nd arg. strlwr(buf); stuffLen = strlen(buf); for(i = 0; buf[i]; ++i) { switch(buf[i]) { case 'a': { player_t* plr = &players[player]; boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_AMMO_TYPES) { // Give one specific ammo type. plr->update |= PSF_AMMO; plr->ammo[idx].owned = plr->ammo[idx].max; giveAll = false; i++; } } if(giveAll) { int j; plr->update |= PSF_AMMO; for(j = 0; j < NUM_AMMO_TYPES; ++j) plr->ammo[j].owned = plr->ammo[j].max; } break; } case 'i': // Inventory items { boolean giveAll = true; if(i < stuffLen) { inventoryitemtype_t type = (inventoryitemtype_t) (((int) buf[i+1]) - 48); if(type >= IIT_FIRST && type < NUM_INVENTORYITEM_TYPES) { // Give one specific item. if(!(gameMode = shareware && (type == IIT_SUPERHEALTH || type == IIT_TELEPORT))) { int j; for(j = 0; j < MAXINVITEMCOUNT; ++j) { P_InventoryGive(player, type, false); } } giveAll = false; i++; } } if(giveAll) { inventoryitemtype_t type; for(type = IIT_FIRST; type < NUM_INVENTORYITEM_TYPES; ++type) { int i; if(gameMode == shareware && (type == IIT_SUPERHEALTH || type == IIT_TELEPORT)) { continue; } for(i = 0; i < MAXINVITEMCOUNT; ++i) { P_InventoryGive(player, type, false); } } } break; } case 'h': Cht_HealthFunc(NULL, player); break; case 'k': { player_t* plr = &players[player]; boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_KEY_TYPES) { // Give one specific key. plr->update |= PSF_KEYS; plr->keys[idx] = true; giveAll = false; i++; } } if(giveAll) { Cht_GiveKeysFunc(NULL, player); } break; } case 'p': { player_t* plr = &players[player]; int j; if(!plr->backpack) { plr->update |= PSF_MAX_AMMO; for(j = 0; j < NUM_AMMO_TYPES; ++j) { plr->ammo[j].max *= 2; } plr->backpack = true; } plr->update |= PSF_AMMO; for(j = 0; j < NUM_AMMO_TYPES; ++j) plr->ammo[j].owned = plr->ammo[j].max; break; } case 'r': { player_t* plr = &players[player]; plr->update |= PSF_ARMOR_POINTS; plr->armorPoints = 200; plr->armorType = 2; break; } case 't': Cht_PowerupFunc(NULL, player); break; case 'w': { player_t* plr = &players[player]; boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_WEAPON_TYPES) { // Give one specific weapon. if(weaponInfo[idx][0].mode[0].gameModeBits & gameModeBits) { plr->update |= PSF_OWNED_WEAPONS; plr->weapons[idx].owned = true; giveAll = false; } i++; } } if(giveAll) { giveWeapons(plr); } break; } default: // Unrecognized Con_Printf("What do you mean, '%c'?\n", buf[i]); break; } } return true; } DEFCC(CCmdCheatMassacre) { Cht_MassacreFunc(NULL, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatWhere) { printDebugInfo(CONSOLEPLAYER); return true; } /** * Exit the current map and go to the intermission. */ DEFCC(CCmdCheatLeaveMap) { if(!cheatsEnabled()) return false; if(G_GetGameState() != GS_MAP) { S_LocalSound(SFX_CHAT, NULL); Con_Printf("Can only exit a map when in a game!\n"); return true; } G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); return true; } DEFCC(CCmdCheatPig) { if(IS_NETGAME) return false; if(!userGame || gameSkill == SM_NIGHTMARE || players[CONSOLEPLAYER].health <= 0) return false; Cht_ChickenFunc(NULL, CONSOLEPLAYER); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/g_ctrl.c0000644000175000017500000000702711357170242022556 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.c: Control bindings - jHeretic specifc */ // HEADER FILES ------------------------------------------------------------ #include "jheretic.h" #include "g_controls.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Register all the various player controls with Doomsday. */ void G_RegisterPlayerControls(void) { /* typedef struct { char *command; // The command to execute. } control_t; control_t axisCts[] = { {"WALK"}, {"SIDESTEP"}, {"turn"}, {"ZFLY"}, {"look"}, {"MAPPANX"}, {"MAPPANY"}, {""} // terminate }; control_t toggleCts[] = { {"ATTACK"}, {"USE"}, {"strafe"}, {"SPEED"}, {"JUMP"}, {"mlook"}, {"jlook"}, {"mzoomin"}, {"mzoomout"}, {""} // terminate }; control_t impulseCts[] = { {"falldown"}, {"lookcntr"}, {"usearti"}, {"cantdie"}, {"invisib"}, {"health"}, {"sphealth"}, {"tomepwr"}, {"torch"}, {"firebomb"}, {"egg"}, {"flyarti"}, {"teleport"}, {"panic"}, {"weap1"}, {"weapon1"}, {"weapon2"}, {"weapon3"}, {"weapon4"}, {"weapon5"}, {"weapon6"}, {"weapon7"}, {"weapon8"}, {"weapon9"}, {"nextwpn"}, {"prevwpn"}, {"demostop"}, {""} // terminate }; uint i; // Axis controls. for(i = 0; axisCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_AXIS, axisCts[i].command); } // Toggle controls. for(i = 0; toggleCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_TOGGLE, toggleCts[i].command); } // Impulse controls. for(i = 0; impulseCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_IMPULSE, impulseCts[i].command); }*/ } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/src/p_maputl.c0000644000175000017500000001441711357170242023126 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputil.c: Movement/collision utility functions. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jheretic.h" #include "dmu_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ extern mobj_t *tmThing; // CODE -------------------------------------------------------------------- /** * Apply "torque" to objects hanging off of ledges, so that they fall off. * It's not really torque, since Doom has no concept of rotation, but it's * a convincing effect which avoids anomalies such as lifeless objects * hanging more than halfway off of ledges, and allows objects to roll off * of the edges of moving lifts, or to slide up and then back down stairs, * or to fall into a ditch. * * If more than one linedef is contacted, the effects are cumulative, so * balancing is possible. */ static boolean PIT_ApplyTorque(linedef_t* ld, void* data) { mobj_t* mo = tmThing; float dist; sector_t* frontsec, *backsec; float ffloor, bfloor; float d1[2], vtx[2]; if(tmThing->player) return true; // Skip players! if(!(frontsec = P_GetPtrp(ld, DMU_FRONT_SECTOR)) || !(backsec = P_GetPtrp(ld, DMU_BACK_SECTOR))) return true; // Shouldn't ever happen. ffloor = P_GetFloatp(frontsec, DMU_FLOOR_HEIGHT); bfloor = P_GetFloatp(backsec, DMU_FLOOR_HEIGHT); P_GetFloatpv(ld, DMU_DXY, d1); P_GetFloatpv(P_GetPtrp(ld, DMU_VERTEX0), DMU_XY, vtx); // Lever-arm: dist = +d1[0] * mo->pos[VY] - d1[1] * mo->pos[VX] - d1[0] * vtx[VY] + d1[1] * vtx[VX]; if((dist < 0 && ffloor < mo->pos[VZ] && bfloor >= mo->pos[VZ]) || (dist >= 0 && bfloor < mo->pos[VZ] && ffloor >= mo->pos[VZ])) { // At this point, we know that the object straddles a two-sided // linedef, and that the object's center of mass is above-ground. float x = fabs(d1[0]), y = fabs(d1[1]); if(y > x) { float tmp = x; x = y; y = tmp; } y = FIX2FLT(finesine[(tantoangle[FLT2FIX(y / x) >> DBITS] + ANG90) >> ANGLETOFINESHIFT]); /** * Momentum is proportional to distance between the object's center * of mass and the pivot linedef. * * It is scaled by 2^(OVERDRIVE - gear). When gear is increased, the * momentum gradually decreases to 0 for the same amount of * pseudotorque, so that oscillations are prevented, yet it has a * chance to reach equilibrium. */ if(mo->gear < OVERDRIVE) dist = (dist * FIX2FLT(FLT2FIX(y) << -(mo->gear - OVERDRIVE))) / x; else dist = (dist * FIX2FLT(FLT2FIX(y) >> +(mo->gear - OVERDRIVE))) / x; // Apply momentum away from the pivot linedef. x = d1[1] * dist; y = d1[0] * dist; // Avoid moving too fast all of a sudden (step into "overdrive"). dist = (x * x) + (y * y); while(dist > 4 && mo->gear < MAXGEAR) { ++mo->gear; x /= 2; y /= 2; dist /= 2; } mo->mom[MX] -= x; mo->mom[MY] += y; } return true; } /** * Applies "torque" to objects, based on all contacted linedefs. * \note $dropoff_fix */ void P_ApplyTorque(mobj_t *mo) { // Remember the current state, for gear-change. int flags = mo->intFlags; // Corpse sliding anomalies, made configurable. if(!cfg.slidingCorpses) return; tmThing = mo; // Use VALIDCOUNT to prevent checking the same line twice. VALIDCOUNT++; P_MobjLinesIterator(mo, PIT_ApplyTorque, 0); // If any momentum, mark object as 'falling' using engine-internal flags if(mo->mom[MX] != 0 || mo->mom[MY] != 0) mo->intFlags |= MIF_FALLING; else // Clear the engine-internal flag indicating falling object. mo->intFlags &= ~MIF_FALLING; /** * If the object has been moving, step up the gear. This helps reach * equilibrium and avoid oscillations. * * DOOM has no concept of potential energy, much less of rotation, so we * have to creatively simulate these systems somehow :) */ // If not falling for a while, reset it to full strength. if(!((mo->intFlags | flags) & MIF_FALLING)) mo->gear = 0; else if(mo->gear < MAXGEAR) // Else if not at max gear, move up a gear. mo->gear++; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/config/0000755000175000017500000000000011523516204021605 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/config/startup.cfg0000644000175000017500000000120711357170242023773 0ustar keeskees# # -=- jHeretic Startup -=- # # This file is included with all versions, which means that it gets # overwritten on each upgrade. Give all custom permanent commands in # autoexec.cfg or user.cfg. # Comment these if you want to use the default colors. uicolor text 1 1 1 uicolor shadow 0 0 0 uicolor bglight .18 .22 .18 uicolor bgmed .4 .52 .44 uicolor bgdark .28 .33 .28 uicolor borhigh 1 1 1 uicolor bormed 0 0 0 uicolor borlow .25 .55 .25 uicolor help .4 .52 .4 # The font. #font name fixed12 # Keymap. #keymap default.dkm # The user config file can contain anything the user wants to execute # before the main startup begins. exec user.cfg deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/0000755000175000017500000000000011523516204021763 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/m_random.h0000644000175000017500000000221411357170242023732 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.h: Random numbers. */ #ifndef __M_RANDOM_H__ #define __M_RANDOM_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif byte P_Random(void); byte M_Random(void); void M_ResetRandom(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/r_defs.h0000644000175000017500000000527311357170242023410 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_defs.h: shared data struct definitions. */ #ifndef __R_DEFS_H__ #define __R_DEFS_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif // Screenwidth. #include "doomdef.h" #include "p_xg.h" #ifdef __GNUG__ #pragma interface #endif #define SP_floororigheight planes[PLN_FLOOR].origHeight #define SP_ceilorigheight planes[PLN_CEILING].origHeight // Stair build flags. #define BL_BUILT 0x1 #define BL_WAS_BUILT 0x2 #define BL_SPREADED 0x4 typedef struct xsector_s { short special; short tag; // 0 = untraversed, 1,2 = sndlines -1 int soundTraversed; // thing that made a sound (or null) struct mobj_s *soundTarget; // thinker_t for reversable actions void *specialData; byte blFlags; // Used during stair building. // stone, metal, heavy, etc... byte seqType; // NOT USED ATM struct { float origHeight; } planes[2]; // {floor, ceiling} float origLight; float origRGB[3]; xgsector_t *xg; } xsector_t; typedef struct xline_s { short special; short tag; short flags; // Has been rendered at least once and needs to appear in the map, // for each player. boolean mapped[MAXPLAYERS]; int validCount; // Extended generalized lines. xgline_t *xg; } xline_t; extern xline_t *xlines; extern xsector_t *xsectors; xline_t* P_ToXLine(linedef_t* line); xline_t* P_GetXLine(uint index); xsector_t* P_ToXSector(sector_t* sector); xsector_t* P_GetXSector(uint index); xsector_t* P_ToXSectorOfSubsector(subsector_t* sub); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_event.h0000644000175000017500000000452211357170242023572 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_event.h: */ #ifndef __JHERETIC_EVENT_H__ #define __JHERETIC_EVENT_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "h_type.h" typedef enum { GA_NONE, GA_LOADMAP, GA_NEWGAME, GA_LOADGAME, GA_SAVEGAME, GA_MAPCOMPLETED, GA_VICTORY, GA_LEAVEMAP, GA_SCREENSHOT, GA_QUIT } gameaction_t; /* // // Button/action code definitions. // typedef enum { // Press "Fire". //BT_ATTACK = 1, // Use button, to open doors, activate switches. //BT_USE = 2, // Flag: game events, not really buttons. //BT_SPECIAL = 128, //BT_SPECIALMASK = 3, // Center player look angle (pitch back to zero). //BT_LOOKCENTER = 64, // Flag, weapon change pending. // If true, the next 3 bits hold weapon num. //BT_CHANGE = 4, // The 3bit weapon mask and shift, convenience. //BT_WEAPONMASK = (8+16+32+64), //BT_WEAPONSHIFT = 3, //BT_JUMP = 8, //BT_SPEED = 16, // Pause the game. //BTS_PAUSE = 1, // Save the game at each console. //BTS_SAVEGAME = 2, // Savegame slot numbers // occupy the second byte of buttons. //BTS_SAVEMASK = (4+8+16), //BTS_SAVESHIFT = 2, // Special weapon change flags. //BTS_NEXTWEAPON = 4, //BTS_PREVWEAPON = 8, } buttoncode_t;*/ #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_refresh.h0000644000175000017500000000312011357170242024100 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_refresh.h: */ #ifndef __JHERETIC_REFRESH_H__ #define __JHERETIC_REFRESH_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "hu_stuff.h" // For gamefontid_t #include "p_mobj.h" extern float quitDarkenOpacity; void H_Display(int layer); void H_Display2(void); void R_SetViewSize(int blocks); void R_DrawSpecialFilter(int pnum); void R_DrawMapTitle(int x, int y, float alpha, gamefontid_t font, boolean center); void P_SetDoomsdayFlags(mobj_t* mo); void R_SetAllDoomsdayFlags(void); boolean R_GetFilterColor(float rgba[4], int filter); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_telept.h0000644000175000017500000000231411357170242023753 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.h: */ #ifndef __P_TELEPT_H__ #define __P_TELEPT_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #define TELEFOGHEIGHTF (32) boolean EV_Teleport(linedef_t* line, int side, mobj_t* thing, boolean spawnFog); void P_ArtiTele(player_t* player); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_think.h0000644000175000017500000000303111357170242023560 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_think.h: * * MapObj data. Map Objects or mobjs are actors, entities, * thinker, take-your-pick... anything that moves, acts, or * suffers state changes of more or less violent nature. */ #ifndef __JHERETIC_THINK_H__ #define __JHERETIC_THINK_H__ typedef void (*actionf_v) (); typedef void (*actionf_p1) (void *); typedef void (*actionf_p2) (void *, void *); #define NOPFUNC ((actionf_v) (-1)) typedef union { actionf_p1 acp1; actionf_v acv; actionf_p2 acp2; } actionf_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_oldsvg.h0000644000175000017500000000254111357170242023756 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_oldsvg.h: */ #ifndef __P_OLDSVG_H__ #define __P_OLDSVG_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif boolean SV_v13_LoadGame(const char* filename); void P_v13_UnArchivePlayers(void); void P_v13_UnArchiveWorld(void); void P_v13_UnArchiveThinkers(void); void P_v13_UnArchiveSpecials(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_enemy.h0000644000175000017500000000227311357170242023577 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.h: Enemy thinking, AI. */ #ifndef __P_ENEMY_H__ #define __P_ENEMY_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif int P_Massacre(void); void P_NoiseAlert(mobj_t* target, mobj_t* emmiter); void P_DSparilTeleport(mobj_t* actor); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/info.h0000644000175000017500000010645111357170242023101 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * info.h: Sprite, state, mobjtype, text, sfx and music identifiers */ #ifndef __JHERETIC_INFO_H__ #define __JHERETIC_INFO_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif // Sprites. typedef enum { SPR_IMPX, SPR_ACLO, SPR_PTN1, SPR_SHLD, SPR_SHD2, SPR_BAGH, SPR_SPMP, SPR_INVS, SPR_PTN2, SPR_SOAR, SPR_INVU, SPR_PWBK, SPR_EGGC, SPR_EGGM, SPR_FX01, SPR_SPHL, SPR_TRCH, SPR_FBMB, SPR_XPL1, SPR_ATLP, SPR_PPOD, SPR_AMG1, SPR_SPSH, SPR_LVAS, SPR_SLDG, SPR_SKH1, SPR_SKH2, SPR_SKH3, SPR_SKH4, SPR_CHDL, SPR_SRTC, SPR_SMPL, SPR_STGS, SPR_STGL, SPR_STCS, SPR_STCL, SPR_KFR1, SPR_BARL, SPR_BRPL, SPR_MOS1, SPR_MOS2, SPR_WTRH, SPR_HCOR, SPR_KGZ1, SPR_KGZB, SPR_KGZG, SPR_KGZY, SPR_VLCO, SPR_VFBL, SPR_VTFB, SPR_SFFI, SPR_TGLT, SPR_TELE, SPR_STFF, SPR_PUF3, SPR_PUF4, SPR_BEAK, SPR_WGNT, SPR_GAUN, SPR_PUF1, SPR_WBLS, SPR_BLSR, SPR_FX18, SPR_FX17, SPR_WMCE, SPR_MACE, SPR_FX02, SPR_WSKL, SPR_HROD, SPR_FX00, SPR_FX20, SPR_FX21, SPR_FX22, SPR_FX23, SPR_GWND, SPR_PUF2, SPR_WPHX, SPR_PHNX, SPR_FX04, SPR_FX08, SPR_FX09, SPR_WBOW, SPR_CRBW, SPR_FX03, SPR_BLOD, SPR_PLAY, SPR_FDTH, SPR_BSKL, SPR_CHKN, SPR_MUMM, SPR_FX15, SPR_BEAS, SPR_FRB1, SPR_SNKE, SPR_SNFX, SPR_HEAD, SPR_FX05, SPR_FX06, SPR_FX07, SPR_CLNK, SPR_WZRD, SPR_FX11, SPR_FX10, SPR_KNIG, SPR_SPAX, SPR_RAXE, SPR_SRCR, SPR_FX14, SPR_SOR2, SPR_SDTH, SPR_FX16, SPR_MNTR, SPR_FX12, SPR_FX13, SPR_AKYY, SPR_BKYY, SPR_CKYY, SPR_AMG2, SPR_AMM1, SPR_AMM2, SPR_AMC1, SPR_AMC2, SPR_AMS1, SPR_AMS2, SPR_AMP1, SPR_AMP2, SPR_AMB1, SPR_AMB2, NUMSPRITES } spritetype_e; // States. typedef enum { S_NULL, S_FREETARGMOBJ, S_ITEM_PTN1_1, S_ITEM_PTN1_2, S_ITEM_PTN1_3, S_ITEM_SHLD1, S_ITEM_SHD2_1, S_ITEM_BAGH1, S_ITEM_SPMP1, S_HIDESPECIAL1, S_HIDESPECIAL2, S_HIDESPECIAL3, S_HIDESPECIAL4, S_HIDESPECIAL5, S_HIDESPECIAL6, S_HIDESPECIAL7, S_HIDESPECIAL8, S_HIDESPECIAL9, S_HIDESPECIAL10, S_HIDESPECIAL11, S_DORMANTARTI1, S_DORMANTARTI2, S_DORMANTARTI3, S_DORMANTARTI4, S_DORMANTARTI5, S_DORMANTARTI6, S_DORMANTARTI7, S_DORMANTARTI8, S_DORMANTARTI9, S_DORMANTARTI10, S_DORMANTARTI11, S_DORMANTARTI12, S_DORMANTARTI13, S_DORMANTARTI14, S_DORMANTARTI15, S_DORMANTARTI16, S_DORMANTARTI17, S_DORMANTARTI18, S_DORMANTARTI19, S_DORMANTARTI20, S_DORMANTARTI21, S_DEADARTI1, S_DEADARTI2, S_DEADARTI3, S_DEADARTI4, S_DEADARTI5, S_DEADARTI6, S_DEADARTI7, S_DEADARTI8, S_DEADARTI9, S_DEADARTI10, S_ARTI_INVS1, S_ARTI_PTN2_1, S_ARTI_PTN2_2, S_ARTI_PTN2_3, S_ARTI_SOAR1, S_ARTI_SOAR2, S_ARTI_SOAR3, S_ARTI_SOAR4, S_ARTI_INVU1, S_ARTI_INVU2, S_ARTI_INVU3, S_ARTI_INVU4, S_ARTI_PWBK1, S_ARTI_EGGC1, S_ARTI_EGGC2, S_ARTI_EGGC3, S_ARTI_EGGC4, S_EGGFX1, S_EGGFX2, S_EGGFX3, S_EGGFX4, S_EGGFX5, S_EGGFXI1_1, S_EGGFXI1_2, S_EGGFXI1_3, S_EGGFXI1_4, S_ARTI_SPHL1, S_ARTI_TRCH1, S_ARTI_TRCH2, S_ARTI_TRCH3, S_ARTI_FBMB1, S_FIREBOMB1, S_FIREBOMB2, S_FIREBOMB3, S_FIREBOMB4, S_FIREBOMB5, S_FIREBOMB6, S_FIREBOMB7, S_FIREBOMB8, S_FIREBOMB9, S_FIREBOMB10, S_FIREBOMB11, S_ARTI_ATLP1, S_ARTI_ATLP2, S_ARTI_ATLP3, S_ARTI_ATLP4, S_POD_WAIT1, S_POD_PAIN1, S_POD_DIE1, S_POD_DIE2, S_POD_DIE3, S_POD_DIE4, S_POD_GROW1, S_POD_GROW2, S_POD_GROW3, S_POD_GROW4, S_POD_GROW5, S_POD_GROW6, S_POD_GROW7, S_POD_GROW8, S_PODGOO1, S_PODGOO2, S_PODGOOX, S_PODGENERATOR, S_SPLASH1, S_SPLASH2, S_SPLASH3, S_SPLASH4, S_SPLASHX, S_SPLASHBASE1, S_SPLASHBASE2, S_SPLASHBASE3, S_SPLASHBASE4, S_SPLASHBASE5, S_SPLASHBASE6, S_SPLASHBASE7, S_LAVASPLASH1, S_LAVASPLASH2, S_LAVASPLASH3, S_LAVASPLASH4, S_LAVASPLASH5, S_LAVASPLASH6, S_LAVASMOKE1, S_LAVASMOKE2, S_LAVASMOKE3, S_LAVASMOKE4, S_LAVASMOKE5, S_SLUDGECHUNK1, S_SLUDGECHUNK2, S_SLUDGECHUNK3, S_SLUDGECHUNK4, S_SLUDGECHUNKX, S_SLUDGESPLASH1, S_SLUDGESPLASH2, S_SLUDGESPLASH3, S_SLUDGESPLASH4, S_SKULLHANG70_1, S_SKULLHANG60_1, S_SKULLHANG45_1, S_SKULLHANG35_1, S_CHANDELIER1, S_CHANDELIER2, S_CHANDELIER3, S_SERPTORCH1, S_SERPTORCH2, S_SERPTORCH3, S_SMALLPILLAR, S_STALAGMITESMALL, S_STALAGMITELARGE, S_STALACTITESMALL, S_STALACTITELARGE, S_FIREBRAZIER1, S_FIREBRAZIER2, S_FIREBRAZIER3, S_FIREBRAZIER4, S_FIREBRAZIER5, S_FIREBRAZIER6, S_FIREBRAZIER7, S_FIREBRAZIER8, S_BARREL, S_BRPILLAR, S_MOSS1, S_MOSS2, S_WALLTORCH1, S_WALLTORCH2, S_WALLTORCH3, S_HANGINGCORPSE, S_KEYGIZMO1, S_KEYGIZMO2, S_KEYGIZMO3, S_KGZ_START, S_KGZ_BLUEFLOAT1, S_KGZ_GREENFLOAT1, S_KGZ_YELLOWFLOAT1, S_VOLCANO1, S_VOLCANO2, S_VOLCANO3, S_VOLCANO4, S_VOLCANO5, S_VOLCANO6, S_VOLCANO7, S_VOLCANO8, S_VOLCANO9, S_VOLCANOBALL1, S_VOLCANOBALL2, S_VOLCANOBALLX1, S_VOLCANOBALLX2, S_VOLCANOBALLX3, S_VOLCANOBALLX4, S_VOLCANOBALLX5, S_VOLCANOBALLX6, S_VOLCANOTBALL1, S_VOLCANOTBALL2, S_VOLCANOTBALLX1, S_VOLCANOTBALLX2, S_VOLCANOTBALLX3, S_VOLCANOTBALLX4, S_VOLCANOTBALLX5, S_VOLCANOTBALLX6, S_VOLCANOTBALLX7, S_TELEGLITGEN1, S_TELEGLITGEN2, S_TELEGLITTER1_1, S_TELEGLITTER1_2, S_TELEGLITTER1_3, S_TELEGLITTER1_4, S_TELEGLITTER1_5, S_TELEGLITTER2_1, S_TELEGLITTER2_2, S_TELEGLITTER2_3, S_TELEGLITTER2_4, S_TELEGLITTER2_5, S_TFOG1, S_TFOG2, S_TFOG3, S_TFOG4, S_TFOG5, S_TFOG6, S_TFOG7, S_TFOG8, S_TFOG9, S_TFOG10, S_TFOG11, S_TFOG12, S_TFOG13, S_LIGHTDONE, S_STAFFREADY, S_STAFFDOWN, S_STAFFUP, S_STAFFREADY2_1, S_STAFFREADY2_2, S_STAFFREADY2_3, S_STAFFDOWN2, S_STAFFUP2, S_STAFFATK1_1, S_STAFFATK1_2, S_STAFFATK1_3, S_STAFFATK2_1, S_STAFFATK2_2, S_STAFFATK2_3, S_STAFFPUFF1, S_STAFFPUFF2, S_STAFFPUFF3, S_STAFFPUFF4, S_STAFFPUFF2_1, S_STAFFPUFF2_2, S_STAFFPUFF2_3, S_STAFFPUFF2_4, S_STAFFPUFF2_5, S_STAFFPUFF2_6, S_BEAKREADY, S_BEAKDOWN, S_BEAKUP, S_BEAKATK1_1, S_BEAKATK2_1, S_WGNT, S_GAUNTLETREADY, S_GAUNTLETDOWN, S_GAUNTLETUP, S_GAUNTLETREADY2_1, S_GAUNTLETREADY2_2, S_GAUNTLETREADY2_3, S_GAUNTLETDOWN2, S_GAUNTLETUP2, S_GAUNTLETATK1_1, S_GAUNTLETATK1_2, S_GAUNTLETATK1_3, S_GAUNTLETATK1_4, S_GAUNTLETATK1_5, S_GAUNTLETATK1_6, S_GAUNTLETATK1_7, S_GAUNTLETATK2_1, S_GAUNTLETATK2_2, S_GAUNTLETATK2_3, S_GAUNTLETATK2_4, S_GAUNTLETATK2_5, S_GAUNTLETATK2_6, S_GAUNTLETATK2_7, S_GAUNTLETPUFF1_1, S_GAUNTLETPUFF1_2, S_GAUNTLETPUFF1_3, S_GAUNTLETPUFF1_4, S_GAUNTLETPUFF2_1, S_GAUNTLETPUFF2_2, S_GAUNTLETPUFF2_3, S_GAUNTLETPUFF2_4, S_BLSR, S_BLASTERREADY, S_BLASTERDOWN, S_BLASTERUP, S_BLASTERATK1_1, S_BLASTERATK1_2, S_BLASTERATK1_3, S_BLASTERATK1_4, S_BLASTERATK1_5, S_BLASTERATK1_6, S_BLASTERATK2_1, S_BLASTERATK2_2, S_BLASTERATK2_3, S_BLASTERATK2_4, S_BLASTERATK2_5, S_BLASTERATK2_6, S_BLASTERFX1_1, S_BLASTERFXI1_1, S_BLASTERFXI1_2, S_BLASTERFXI1_3, S_BLASTERFXI1_4, S_BLASTERFXI1_5, S_BLASTERFXI1_6, S_BLASTERFXI1_7, S_BLASTERSMOKE1, S_BLASTERSMOKE2, S_BLASTERSMOKE3, S_BLASTERSMOKE4, S_BLASTERSMOKE5, S_RIPPER1, S_RIPPER2, S_RIPPERX1, S_RIPPERX2, S_RIPPERX3, S_RIPPERX4, S_RIPPERX5, S_BLASTERPUFF1_1, S_BLASTERPUFF1_2, S_BLASTERPUFF1_3, S_BLASTERPUFF1_4, S_BLASTERPUFF1_5, S_BLASTERPUFF2_1, S_BLASTERPUFF2_2, S_BLASTERPUFF2_3, S_BLASTERPUFF2_4, S_BLASTERPUFF2_5, S_BLASTERPUFF2_6, S_BLASTERPUFF2_7, S_WMCE, S_MACEREADY, S_MACEDOWN, S_MACEUP, S_MACEATK1_1, S_MACEATK1_2, S_MACEATK1_3, S_MACEATK1_4, S_MACEATK1_5, S_MACEATK1_6, S_MACEATK1_7, S_MACEATK1_8, S_MACEATK1_9, S_MACEATK1_10, S_MACEATK2_1, S_MACEATK2_2, S_MACEATK2_3, S_MACEATK2_4, S_MACEFX1_1, S_MACEFX1_2, S_MACEFXI1_1, S_MACEFXI1_2, S_MACEFXI1_3, S_MACEFXI1_4, S_MACEFXI1_5, S_MACEFX2_1, S_MACEFX2_2, S_MACEFXI2_1, S_MACEFX3_1, S_MACEFX3_2, S_MACEFX4_1, S_MACEFXI4_1, S_WSKL, S_HORNRODREADY, S_HORNRODDOWN, S_HORNRODUP, S_HORNRODATK1_1, S_HORNRODATK1_2, S_HORNRODATK1_3, S_HORNRODATK2_1, S_HORNRODATK2_2, S_HORNRODATK2_3, S_HORNRODATK2_4, S_HORNRODATK2_5, S_HORNRODATK2_6, S_HORNRODATK2_7, S_HORNRODATK2_8, S_HORNRODATK2_9, S_HRODFX1_1, S_HRODFX1_2, S_HRODFXI1_1, S_HRODFXI1_2, S_HRODFXI1_3, S_HRODFXI1_4, S_HRODFXI1_5, S_HRODFXI1_6, S_HRODFX2_1, S_HRODFX2_2, S_HRODFX2_3, S_HRODFX2_4, S_HRODFXI2_1, S_HRODFXI2_2, S_HRODFXI2_3, S_HRODFXI2_4, S_HRODFXI2_5, S_HRODFXI2_6, S_HRODFXI2_7, S_HRODFXI2_8, S_RAINPLR1_1, S_RAINPLR2_1, S_RAINPLR3_1, S_RAINPLR4_1, S_RAINPLR1X_1, S_RAINPLR1X_2, S_RAINPLR1X_3, S_RAINPLR1X_4, S_RAINPLR1X_5, S_RAINPLR2X_1, S_RAINPLR2X_2, S_RAINPLR2X_3, S_RAINPLR2X_4, S_RAINPLR2X_5, S_RAINPLR3X_1, S_RAINPLR3X_2, S_RAINPLR3X_3, S_RAINPLR3X_4, S_RAINPLR3X_5, S_RAINPLR4X_1, S_RAINPLR4X_2, S_RAINPLR4X_3, S_RAINPLR4X_4, S_RAINPLR4X_5, S_RAINAIRXPLR1_1, S_RAINAIRXPLR2_1, S_RAINAIRXPLR3_1, S_RAINAIRXPLR4_1, S_RAINAIRXPLR1_2, S_RAINAIRXPLR2_2, S_RAINAIRXPLR3_2, S_RAINAIRXPLR4_2, S_RAINAIRXPLR1_3, S_RAINAIRXPLR2_3, S_RAINAIRXPLR3_3, S_RAINAIRXPLR4_3, S_GOLDWANDREADY, S_GOLDWANDDOWN, S_GOLDWANDUP, S_GOLDWANDATK1_1, S_GOLDWANDATK1_2, S_GOLDWANDATK1_3, S_GOLDWANDATK1_4, S_GOLDWANDATK2_1, S_GOLDWANDATK2_2, S_GOLDWANDATK2_3, S_GOLDWANDATK2_4, S_GWANDFX1_1, S_GWANDFX1_2, S_GWANDFXI1_1, S_GWANDFXI1_2, S_GWANDFXI1_3, S_GWANDFXI1_4, S_GWANDFX2_1, S_GWANDFX2_2, S_GWANDPUFF1_1, S_GWANDPUFF1_2, S_GWANDPUFF1_3, S_GWANDPUFF1_4, S_GWANDPUFF1_5, S_WPHX, S_PHOENIXREADY, S_PHOENIXDOWN, S_PHOENIXUP, S_PHOENIXATK1_1, S_PHOENIXATK1_2, S_PHOENIXATK1_3, S_PHOENIXATK1_4, S_PHOENIXATK1_5, S_PHOENIXATK2_1, S_PHOENIXATK2_2, S_PHOENIXATK2_3, S_PHOENIXATK2_4, S_PHOENIXFX1_1, S_PHOENIXFXI1_1, S_PHOENIXFXI1_2, S_PHOENIXFXI1_3, S_PHOENIXFXI1_4, S_PHOENIXFXI1_5, S_PHOENIXFXI1_6, S_PHOENIXFXI1_7, S_PHOENIXFXI1_8, S_PHOENIXPUFF1, S_PHOENIXPUFF2, S_PHOENIXPUFF3, S_PHOENIXPUFF4, S_PHOENIXPUFF5, S_PHOENIXFX2_1, S_PHOENIXFX2_2, S_PHOENIXFX2_3, S_PHOENIXFX2_4, S_PHOENIXFX2_5, S_PHOENIXFX2_6, S_PHOENIXFX2_7, S_PHOENIXFX2_8, S_PHOENIXFX2_9, S_PHOENIXFX2_10, S_PHOENIXFXI2_1, S_PHOENIXFXI2_2, S_PHOENIXFXI2_3, S_PHOENIXFXI2_4, S_PHOENIXFXI2_5, S_WBOW, S_CRBOW1, S_CRBOW2, S_CRBOW3, S_CRBOW4, S_CRBOW5, S_CRBOW6, S_CRBOW7, S_CRBOW8, S_CRBOW9, S_CRBOW10, S_CRBOW11, S_CRBOW12, S_CRBOW13, S_CRBOW14, S_CRBOW15, S_CRBOW16, S_CRBOW17, S_CRBOW18, S_CRBOWDOWN, S_CRBOWUP, S_CRBOWATK1_1, S_CRBOWATK1_2, S_CRBOWATK1_3, S_CRBOWATK1_4, S_CRBOWATK1_5, S_CRBOWATK1_6, S_CRBOWATK1_7, S_CRBOWATK1_8, S_CRBOWATK2_1, S_CRBOWATK2_2, S_CRBOWATK2_3, S_CRBOWATK2_4, S_CRBOWATK2_5, S_CRBOWATK2_6, S_CRBOWATK2_7, S_CRBOWATK2_8, S_CRBOWFX1, S_CRBOWFXI1_1, S_CRBOWFXI1_2, S_CRBOWFXI1_3, S_CRBOWFX2, S_CRBOWFX3, S_CRBOWFXI3_1, S_CRBOWFXI3_2, S_CRBOWFXI3_3, S_CRBOWFX4_1, S_CRBOWFX4_2, S_BLOOD1, S_BLOOD2, S_BLOOD3, S_BLOODSPLATTER1, S_BLOODSPLATTER2, S_BLOODSPLATTER3, S_BLOODSPLATTERX, S_PLAY, S_PLAY_RUN1, S_PLAY_RUN2, S_PLAY_RUN3, S_PLAY_RUN4, S_PLAY_ATK1, S_PLAY_ATK2, S_PLAY_PAIN, S_PLAY_PAIN2, S_PLAY_DIE1, S_PLAY_DIE2, S_PLAY_DIE3, S_PLAY_DIE4, S_PLAY_DIE5, S_PLAY_DIE6, S_PLAY_DIE7, S_PLAY_DIE8, S_PLAY_DIE9, S_PLAY_XDIE1, S_PLAY_XDIE2, S_PLAY_XDIE3, S_PLAY_XDIE4, S_PLAY_XDIE5, S_PLAY_XDIE6, S_PLAY_XDIE7, S_PLAY_XDIE8, S_PLAY_XDIE9, S_PLAY_FDTH1, S_PLAY_FDTH2, S_PLAY_FDTH3, S_PLAY_FDTH4, S_PLAY_FDTH5, S_PLAY_FDTH6, S_PLAY_FDTH7, S_PLAY_FDTH8, S_PLAY_FDTH9, S_PLAY_FDTH10, S_PLAY_FDTH11, S_PLAY_FDTH12, S_PLAY_FDTH13, S_PLAY_FDTH14, S_PLAY_FDTH15, S_PLAY_FDTH16, S_PLAY_FDTH17, S_PLAY_FDTH18, S_PLAY_FDTH19, S_PLAY_FDTH20, S_BLOODYSKULL1, S_BLOODYSKULL2, S_BLOODYSKULL3, S_BLOODYSKULL4, S_BLOODYSKULL5, S_BLOODYSKULLX1, S_BLOODYSKULLX2, S_CHICPLAY, S_CHICPLAY_RUN1, S_CHICPLAY_RUN2, S_CHICPLAY_RUN3, S_CHICPLAY_RUN4, S_CHICPLAY_ATK1, S_CHICPLAY_PAIN, S_CHICPLAY_PAIN2, S_CHICKEN_LOOK1, S_CHICKEN_LOOK2, S_CHICKEN_WALK1, S_CHICKEN_WALK2, S_CHICKEN_PAIN1, S_CHICKEN_PAIN2, S_CHICKEN_ATK1, S_CHICKEN_ATK2, S_CHICKEN_DIE1, S_CHICKEN_DIE2, S_CHICKEN_DIE3, S_CHICKEN_DIE4, S_CHICKEN_DIE5, S_CHICKEN_DIE6, S_CHICKEN_DIE7, S_CHICKEN_DIE8, S_FEATHER1, S_FEATHER2, S_FEATHER3, S_FEATHER4, S_FEATHER5, S_FEATHER6, S_FEATHER7, S_FEATHER8, S_FEATHERX, S_MUMMY_LOOK1, S_MUMMY_LOOK2, S_MUMMY_WALK1, S_MUMMY_WALK2, S_MUMMY_WALK3, S_MUMMY_WALK4, S_MUMMY_ATK1, S_MUMMY_ATK2, S_MUMMY_ATK3, S_MUMMYL_ATK1, S_MUMMYL_ATK2, S_MUMMYL_ATK3, S_MUMMYL_ATK4, S_MUMMYL_ATK5, S_MUMMYL_ATK6, S_MUMMY_PAIN1, S_MUMMY_PAIN2, S_MUMMY_DIE1, S_MUMMY_DIE2, S_MUMMY_DIE3, S_MUMMY_DIE4, S_MUMMY_DIE5, S_MUMMY_DIE6, S_MUMMY_DIE7, S_MUMMY_DIE8, S_MUMMY_SOUL1, S_MUMMY_SOUL2, S_MUMMY_SOUL3, S_MUMMY_SOUL4, S_MUMMY_SOUL5, S_MUMMY_SOUL6, S_MUMMY_SOUL7, S_MUMMYFX1_1, S_MUMMYFX1_2, S_MUMMYFX1_3, S_MUMMYFX1_4, S_MUMMYFXI1_1, S_MUMMYFXI1_2, S_MUMMYFXI1_3, S_MUMMYFXI1_4, S_BEAST_LOOK1, S_BEAST_LOOK2, S_BEAST_WALK1, S_BEAST_WALK2, S_BEAST_WALK3, S_BEAST_WALK4, S_BEAST_WALK5, S_BEAST_WALK6, S_BEAST_ATK1, S_BEAST_ATK2, S_BEAST_PAIN1, S_BEAST_PAIN2, S_BEAST_DIE1, S_BEAST_DIE2, S_BEAST_DIE3, S_BEAST_DIE4, S_BEAST_DIE5, S_BEAST_DIE6, S_BEAST_DIE7, S_BEAST_DIE8, S_BEAST_DIE9, S_BEAST_XDIE1, S_BEAST_XDIE2, S_BEAST_XDIE3, S_BEAST_XDIE4, S_BEAST_XDIE5, S_BEAST_XDIE6, S_BEAST_XDIE7, S_BEAST_XDIE8, S_BEASTBALL1, S_BEASTBALL2, S_BEASTBALL3, S_BEASTBALL4, S_BEASTBALL5, S_BEASTBALL6, S_BEASTBALLX1, S_BEASTBALLX2, S_BEASTBALLX3, S_BEASTBALLX4, S_BEASTBALLX5, S_BURNBALL1, S_BURNBALL2, S_BURNBALL3, S_BURNBALL4, S_BURNBALL5, S_BURNBALL6, S_BURNBALL7, S_BURNBALL8, S_BURNBALLFB1, S_BURNBALLFB2, S_BURNBALLFB3, S_BURNBALLFB4, S_BURNBALLFB5, S_BURNBALLFB6, S_BURNBALLFB7, S_BURNBALLFB8, S_PUFFY1, S_PUFFY2, S_PUFFY3, S_PUFFY4, S_PUFFY5, S_SNAKE_LOOK1, S_SNAKE_LOOK2, S_SNAKE_WALK1, S_SNAKE_WALK2, S_SNAKE_WALK3, S_SNAKE_WALK4, S_SNAKE_ATK1, S_SNAKE_ATK2, S_SNAKE_ATK3, S_SNAKE_ATK4, S_SNAKE_ATK5, S_SNAKE_ATK6, S_SNAKE_ATK7, S_SNAKE_ATK8, S_SNAKE_ATK9, S_SNAKE_PAIN1, S_SNAKE_PAIN2, S_SNAKE_DIE1, S_SNAKE_DIE2, S_SNAKE_DIE3, S_SNAKE_DIE4, S_SNAKE_DIE5, S_SNAKE_DIE6, S_SNAKE_DIE7, S_SNAKE_DIE8, S_SNAKE_DIE9, S_SNAKE_DIE10, S_SNAKEPRO_A1, S_SNAKEPRO_A2, S_SNAKEPRO_A3, S_SNAKEPRO_A4, S_SNAKEPRO_AX1, S_SNAKEPRO_AX2, S_SNAKEPRO_AX3, S_SNAKEPRO_AX4, S_SNAKEPRO_AX5, S_SNAKEPRO_B1, S_SNAKEPRO_B2, S_SNAKEPRO_BX1, S_SNAKEPRO_BX2, S_SNAKEPRO_BX3, S_SNAKEPRO_BX4, S_HEAD_LOOK, S_HEAD_FLOAT, S_HEAD_ATK1, S_HEAD_ATK2, S_HEAD_PAIN1, S_HEAD_PAIN2, S_HEAD_DIE1, S_HEAD_DIE2, S_HEAD_DIE3, S_HEAD_DIE4, S_HEAD_DIE5, S_HEAD_DIE6, S_HEAD_DIE7, S_HEADFX1_1, S_HEADFX1_2, S_HEADFX1_3, S_HEADFXI1_1, S_HEADFXI1_2, S_HEADFXI1_3, S_HEADFXI1_4, S_HEADFX2_1, S_HEADFX2_2, S_HEADFX2_3, S_HEADFXI2_1, S_HEADFXI2_2, S_HEADFXI2_3, S_HEADFXI2_4, S_HEADFX3_1, S_HEADFX3_2, S_HEADFX3_3, S_HEADFX3_4, S_HEADFX3_5, S_HEADFX3_6, S_HEADFXI3_1, S_HEADFXI3_2, S_HEADFXI3_3, S_HEADFXI3_4, S_HEADFX4_1, S_HEADFX4_2, S_HEADFX4_3, S_HEADFX4_4, S_HEADFX4_5, S_HEADFX4_6, S_HEADFX4_7, S_HEADFXI4_1, S_HEADFXI4_2, S_HEADFXI4_3, S_HEADFXI4_4, S_CLINK_LOOK1, S_CLINK_LOOK2, S_CLINK_WALK1, S_CLINK_WALK2, S_CLINK_WALK3, S_CLINK_WALK4, S_CLINK_ATK1, S_CLINK_ATK2, S_CLINK_ATK3, S_CLINK_PAIN1, S_CLINK_PAIN2, S_CLINK_DIE1, S_CLINK_DIE2, S_CLINK_DIE3, S_CLINK_DIE4, S_CLINK_DIE5, S_CLINK_DIE6, S_CLINK_DIE7, S_WIZARD_LOOK1, S_WIZARD_LOOK2, S_WIZARD_WALK1, S_WIZARD_WALK2, S_WIZARD_WALK3, S_WIZARD_WALK4, S_WIZARD_WALK5, S_WIZARD_WALK6, S_WIZARD_WALK7, S_WIZARD_WALK8, S_WIZARD_ATK1, S_WIZARD_ATK2, S_WIZARD_ATK3, S_WIZARD_ATK4, S_WIZARD_ATK5, S_WIZARD_ATK6, S_WIZARD_ATK7, S_WIZARD_ATK8, S_WIZARD_ATK9, S_WIZARD_PAIN1, S_WIZARD_PAIN2, S_WIZARD_DIE1, S_WIZARD_DIE2, S_WIZARD_DIE3, S_WIZARD_DIE4, S_WIZARD_DIE5, S_WIZARD_DIE6, S_WIZARD_DIE7, S_WIZARD_DIE8, S_WIZFX1_1, S_WIZFX1_2, S_WIZFXI1_1, S_WIZFXI1_2, S_WIZFXI1_3, S_WIZFXI1_4, S_WIZFXI1_5, S_IMP_LOOK1, S_IMP_LOOK2, S_IMP_LOOK3, S_IMP_LOOK4, S_IMP_FLY1, S_IMP_FLY2, S_IMP_FLY3, S_IMP_FLY4, S_IMP_FLY5, S_IMP_FLY6, S_IMP_FLY7, S_IMP_FLY8, S_IMP_MEATK1, S_IMP_MEATK2, S_IMP_MEATK3, S_IMP_MSATK1_1, S_IMP_MSATK1_2, S_IMP_MSATK1_3, S_IMP_MSATK1_4, S_IMP_MSATK1_5, S_IMP_MSATK1_6, S_IMP_MSATK2_1, S_IMP_MSATK2_2, S_IMP_MSATK2_3, S_IMP_PAIN1, S_IMP_PAIN2, S_IMP_DIE1, S_IMP_DIE2, S_IMP_XDIE1, S_IMP_XDIE2, S_IMP_XDIE3, S_IMP_XDIE4, S_IMP_XDIE5, S_IMP_CRASH1, S_IMP_CRASH2, S_IMP_CRASH3, S_IMP_CRASH4, S_IMP_XCRASH1, S_IMP_XCRASH2, S_IMP_XCRASH3, S_IMP_CHUNKA1, S_IMP_CHUNKA2, S_IMP_CHUNKA3, S_IMP_CHUNKB1, S_IMP_CHUNKB2, S_IMP_CHUNKB3, S_IMPFX1, S_IMPFX2, S_IMPFX3, S_IMPFXI1, S_IMPFXI2, S_IMPFXI3, S_IMPFXI4, S_KNIGHT_STND1, S_KNIGHT_STND2, S_KNIGHT_WALK1, S_KNIGHT_WALK2, S_KNIGHT_WALK3, S_KNIGHT_WALK4, S_KNIGHT_ATK1, S_KNIGHT_ATK2, S_KNIGHT_ATK3, S_KNIGHT_ATK4, S_KNIGHT_ATK5, S_KNIGHT_ATK6, S_KNIGHT_PAIN1, S_KNIGHT_PAIN2, S_KNIGHT_DIE1, S_KNIGHT_DIE2, S_KNIGHT_DIE3, S_KNIGHT_DIE4, S_KNIGHT_DIE5, S_KNIGHT_DIE6, S_KNIGHT_DIE7, S_SPINAXE1, S_SPINAXE2, S_SPINAXE3, S_SPINAXEX1, S_SPINAXEX2, S_SPINAXEX3, S_REDAXE1, S_REDAXE2, S_REDAXEX1, S_REDAXEX2, S_REDAXEX3, S_SRCR1_LOOK1, S_SRCR1_LOOK2, S_SRCR1_WALK1, S_SRCR1_WALK2, S_SRCR1_WALK3, S_SRCR1_WALK4, S_SRCR1_PAIN1, S_SRCR1_ATK1, S_SRCR1_ATK2, S_SRCR1_ATK3, S_SRCR1_ATK4, S_SRCR1_ATK5, S_SRCR1_ATK6, S_SRCR1_ATK7, S_SRCR1_DIE1, S_SRCR1_DIE2, S_SRCR1_DIE3, S_SRCR1_DIE4, S_SRCR1_DIE5, S_SRCR1_DIE6, S_SRCR1_DIE7, S_SRCR1_DIE8, S_SRCR1_DIE9, S_SRCR1_DIE10, S_SRCR1_DIE11, S_SRCR1_DIE12, S_SRCR1_DIE13, S_SRCR1_DIE14, S_SRCR1_DIE15, S_SRCR1_DIE16, S_SRCR1_DIE17, S_SRCRFX1_1, S_SRCRFX1_2, S_SRCRFX1_3, S_SRCRFXI1_1, S_SRCRFXI1_2, S_SRCRFXI1_3, S_SRCRFXI1_4, S_SRCRFXI1_5, S_SOR2_RISE1, S_SOR2_RISE2, S_SOR2_RISE3, S_SOR2_RISE4, S_SOR2_RISE5, S_SOR2_RISE6, S_SOR2_RISE7, S_SOR2_LOOK1, S_SOR2_LOOK2, S_SOR2_WALK1, S_SOR2_WALK2, S_SOR2_WALK3, S_SOR2_WALK4, S_SOR2_PAIN1, S_SOR2_PAIN2, S_SOR2_ATK1, S_SOR2_ATK2, S_SOR2_ATK3, S_SOR2_TELE1, S_SOR2_TELE2, S_SOR2_TELE3, S_SOR2_TELE4, S_SOR2_TELE5, S_SOR2_TELE6, S_SOR2_DIE1, S_SOR2_DIE2, S_SOR2_DIE3, S_SOR2_DIE4, S_SOR2_DIE5, S_SOR2_DIE6, S_SOR2_DIE7, S_SOR2_DIE8, S_SOR2_DIE9, S_SOR2_DIE10, S_SOR2_DIE11, S_SOR2_DIE12, S_SOR2_DIE13, S_SOR2_DIE14, S_SOR2_DIE15, S_SOR2FX1_1, S_SOR2FX1_2, S_SOR2FX1_3, S_SOR2FXI1_1, S_SOR2FXI1_2, S_SOR2FXI1_3, S_SOR2FXI1_4, S_SOR2FXI1_5, S_SOR2FXI1_6, S_SOR2FXSPARK1, S_SOR2FXSPARK2, S_SOR2FXSPARK3, S_SOR2FX2_1, S_SOR2FX2_2, S_SOR2FX2_3, S_SOR2FXI2_1, S_SOR2FXI2_2, S_SOR2FXI2_3, S_SOR2FXI2_4, S_SOR2FXI2_5, S_SOR2TELEFADE1, S_SOR2TELEFADE2, S_SOR2TELEFADE3, S_SOR2TELEFADE4, S_SOR2TELEFADE5, S_SOR2TELEFADE6, S_MNTR_LOOK1, S_MNTR_LOOK2, S_MNTR_WALK1, S_MNTR_WALK2, S_MNTR_WALK3, S_MNTR_WALK4, S_MNTR_ATK1_1, S_MNTR_ATK1_2, S_MNTR_ATK1_3, S_MNTR_ATK2_1, S_MNTR_ATK2_2, S_MNTR_ATK2_3, S_MNTR_ATK3_1, S_MNTR_ATK3_2, S_MNTR_ATK3_3, S_MNTR_ATK3_4, S_MNTR_ATK4_1, S_MNTR_PAIN1, S_MNTR_PAIN2, S_MNTR_DIE1, S_MNTR_DIE2, S_MNTR_DIE3, S_MNTR_DIE4, S_MNTR_DIE5, S_MNTR_DIE6, S_MNTR_DIE7, S_MNTR_DIE8, S_MNTR_DIE9, S_MNTR_DIE10, S_MNTR_DIE11, S_MNTR_DIE12, S_MNTR_DIE13, S_MNTR_DIE14, S_MNTR_DIE15, S_MNTRFX1_1, S_MNTRFX1_2, S_MNTRFXI1_1, S_MNTRFXI1_2, S_MNTRFXI1_3, S_MNTRFXI1_4, S_MNTRFXI1_5, S_MNTRFXI1_6, S_MNTRFX2_1, S_MNTRFXI2_1, S_MNTRFXI2_2, S_MNTRFXI2_3, S_MNTRFXI2_4, S_MNTRFXI2_5, S_MNTRFX3_1, S_MNTRFX3_2, S_MNTRFX3_3, S_MNTRFX3_4, S_MNTRFX3_5, S_MNTRFX3_6, S_MNTRFX3_7, S_MNTRFX3_8, S_MNTRFX3_9, S_AKYY1, S_AKYY2, S_AKYY3, S_AKYY4, S_AKYY5, S_AKYY6, S_AKYY7, S_AKYY8, S_AKYY9, S_AKYY10, S_BKYY1, S_BKYY2, S_BKYY3, S_BKYY4, S_BKYY5, S_BKYY6, S_BKYY7, S_BKYY8, S_BKYY9, S_BKYY10, S_CKYY1, S_CKYY2, S_CKYY3, S_CKYY4, S_CKYY5, S_CKYY6, S_CKYY7, S_CKYY8, S_CKYY9, S_AMG1, S_AMG2_1, S_AMG2_2, S_AMG2_3, S_AMM1, S_AMM2, S_AMC1, S_AMC2_1, S_AMC2_2, S_AMC2_3, S_AMS1_1, S_AMS1_2, S_AMS2_1, S_AMS2_2, S_AMP1_1, S_AMP1_2, S_AMP1_3, S_AMP2_1, S_AMP2_2, S_AMP2_3, S_AMB1_1, S_AMB1_2, S_AMB1_3, S_AMB2_1, S_AMB2_2, S_AMB2_3, S_SND_WIND, S_SND_WATERFALL, S_TEMPSOUNDORIGIN1, NUMSTATES } statenum_t; // Map objects. typedef enum { MT_NONE = -1, MT_FIRST = 0, MT_MISC0 = MT_FIRST, // 000 MT_ITEMSHIELD1, MT_ITEMSHIELD2, MT_MISC1, MT_MISC2, MT_ARTIINVISIBILITY, MT_MISC3, MT_ARTIFLY, MT_ARTIINVULNERABILITY, MT_ARTITOMEOFPOWER, MT_ARTIEGG, MT_EGGFX, MT_ARTISUPERHEAL, MT_MISC4, MT_MISC5, MT_FIREBOMB, MT_ARTITELEPORT, MT_POD, MT_PODGOO, MT_PODGENERATOR, MT_SPLASH, MT_SPLASHBASE, MT_LAVASPLASH, MT_LAVASMOKE, MT_SLUDGECHUNK, MT_SLUDGESPLASH, MT_SKULLHANG70, MT_SKULLHANG60, MT_SKULLHANG45, MT_SKULLHANG35, MT_CHANDELIER, MT_SERPTORCH, MT_SMALLPILLAR, MT_STALAGMITESMALL, MT_STALAGMITELARGE, MT_STALACTITESMALL, MT_STALACTITELARGE, MT_MISC6, MT_BARREL, MT_MISC7, MT_MISC8, MT_MISC9, MT_MISC10, MT_MISC11, MT_KEYGIZMOBLUE, MT_KEYGIZMOGREEN, MT_KEYGIZMOYELLOW, MT_KEYGIZMOFLOAT, MT_MISC12, MT_VOLCANOBLAST, MT_VOLCANOTBLAST, MT_TELEGLITGEN, MT_TELEGLITGEN2, MT_TELEGLITTER, MT_TELEGLITTER2, MT_TFOG, MT_TELEPORTMAN, MT_STAFFPUFF, MT_STAFFPUFF2, MT_BEAKPUFF, MT_MISC13, MT_GAUNTLETPUFF1, MT_GAUNTLETPUFF2, MT_MISC14, MT_BLASTERFX1, MT_BLASTERSMOKE, MT_RIPPER, MT_BLASTERPUFF1, MT_BLASTERPUFF2, MT_WMACE, MT_MACEFX1, MT_MACEFX2, MT_MACEFX3, MT_MACEFX4, MT_WSKULLROD, MT_HORNRODFX1, MT_HORNRODFX2, MT_RAINPLR1, MT_RAINPLR2, MT_RAINPLR3, MT_RAINPLR4, MT_GOLDWANDFX1, MT_GOLDWANDFX2, MT_GOLDWANDPUFF1, MT_GOLDWANDPUFF2, MT_WPHOENIXROD, MT_PHOENIXFX1, MT_PHOENIXPUFF, MT_PHOENIXFX2, MT_MISC15, MT_CRBOWFX1, MT_CRBOWFX2, MT_CRBOWFX3, MT_CRBOWFX4, MT_BLOOD, MT_BLOODSPLATTER, MT_PLAYER, MT_BLOODYSKULL, MT_CHICPLAYER, MT_CHICKEN, MT_FEATHER, MT_MUMMY, MT_MUMMYLEADER, MT_MUMMYGHOST, MT_MUMMYLEADERGHOST, MT_MUMMYSOUL, MT_MUMMYFX1, MT_BEAST, MT_BEASTBALL, MT_BURNBALL, MT_BURNBALLFB, MT_PUFFY, MT_SNAKE, MT_SNAKEPRO_A, MT_SNAKEPRO_B, MT_HEAD, MT_HEADFX1, MT_HEADFX2, MT_HEADFX3, MT_WHIRLWIND, MT_CLINK, MT_WIZARD, MT_WIZFX1, MT_IMP, MT_IMPLEADER, MT_IMPCHUNK1, MT_IMPCHUNK2, MT_IMPBALL, MT_KNIGHT, MT_KNIGHTGHOST, MT_KNIGHTAXE, MT_REDAXE, MT_SORCERER1, MT_SRCRFX1, MT_SORCERER2, MT_SOR2FX1, MT_SOR2FXSPARK, MT_SOR2FX2, MT_SOR2TELEFADE, MT_MINOTAUR, MT_MNTRFX1, MT_MNTRFX2, MT_MNTRFX3, MT_AKYY, MT_BKYY, MT_CKEY, MT_AMGWNDWIMPY, MT_AMGWNDHEFTY, MT_AMMACEWIMPY, MT_AMMACEHEFTY, MT_AMCBOWWIMPY, MT_AMCBOWHEFTY, MT_AMSKRDWIMPY, MT_AMSKRDHEFTY, MT_AMPHRDWIMPY, MT_AMPHRDHEFTY, MT_AMBLSRWIMPY, MT_AMBLSRHEFTY, MT_SOUNDWIND, MT_SOUNDWATERFALL, MT_TEMPSOUNDORIGIN, NUMMOBJTYPES } mobjtype_t; // Text. typedef enum { TXT_PRESSKEY, TXT_PRESSYN, TXT_TXT_PAUSED, TXT_QUITMSG, TXT_LOADNET, TXT_QLOADNET, TXT_QSAVESPOT, TXT_SAVEDEAD, TXT_QSPROMPT, TXT_QLPROMPT, TXT_NEWGAME, TXT_NIGHTMARE, TXT_SWSTRING, TXT_MSGOFF, TXT_MSGON, TXT_NETEND, TXT_ENDGAME, TXT_DOSY, TXT_DETAILHI, TXT_DETAILLO, TXT_GAMMALVL0, TXT_GAMMALVL1, TXT_GAMMALVL2, TXT_GAMMALVL3, TXT_GAMMALVL4, TXT_EMPTYSTRING, TXT_TXT_GOTBLUEKEY, TXT_TXT_GOTYELLOWKEY, TXT_TXT_GOTGREENKEY, TXT_TXT_INV_HEALTH, TXT_TXT_INV_FLY, TXT_TXT_INV_INVULNERABILITY, TXT_TXT_INV_TOMEOFPOWER, TXT_TXT_INV_INVISIBILITY, TXT_TXT_INV_EGG, TXT_TXT_INV_SUPERHEALTH, TXT_TXT_INV_TORCH, TXT_TXT_INV_FIREBOMB, TXT_TXT_INV_TELEPORT, TXT_TXT_ITEMHEALTH, TXT_TXT_ITEMBAGOFHOLDING, TXT_TXT_ITEMSHIELD1, TXT_TXT_ITEMSHIELD2, TXT_TXT_ITEMSUPERMAP, TXT_TXT_AMMOGOLDWAND1, TXT_TXT_AMMOGOLDWAND2, TXT_TXT_AMMOMACE1, TXT_TXT_AMMOMACE2, TXT_TXT_AMMOCROSSBOW1, TXT_TXT_AMMOCROSSBOW2, TXT_TXT_AMMOBLASTER1, TXT_TXT_AMMOBLASTER2, TXT_TXT_AMMOSKULLROD1, TXT_TXT_AMMOSKULLROD2, TXT_TXT_AMMOPHOENIXROD1, TXT_TXT_AMMOPHOENIXROD2, TXT_TXT_WPNSTAFF, TXT_TXT_WPNWAND, TXT_TXT_WPNCROSSBOW, TXT_TXT_WPNBLASTER, TXT_TXT_WPNSKULLROD, TXT_TXT_WPNPHOENIXROD, TXT_TXT_WPNMACE, TXT_TXT_WPNGAUNTLETS, TXT_TXT_WPNBEAK, TXT_TXT_CHEATGODON, TXT_TXT_CHEATGODOFF, TXT_TXT_CHEATNOCLIPON, TXT_TXT_CHEATNOCLIPOFF, TXT_TXT_CHEATWEAPONS, TXT_TXT_CHEATFLIGHTON, TXT_TXT_CHEATFLIGHTOFF, TXT_TXT_CHEATPOWERON, TXT_TXT_CHEATPOWEROFF, TXT_TXT_CHEATHEALTH, TXT_TXT_CHEATKEYS, TXT_TXT_CHEATSOUNDON, TXT_TXT_CHEATSOUNDOFF, TXT_TXT_CHEATTICKERON, TXT_TXT_CHEATTICKEROFF, TXT_TXT_CHEATINVITEMS1, TXT_TXT_CHEATINVITEMS2, TXT_TXT_CHEATINVITEMS3, TXT_TXT_CHEATITEMSFAIL, TXT_TXT_CHEATWARP, TXT_TXT_CHEATSCREENSHOT, TXT_TXT_CHEATCHICKENON, TXT_TXT_CHEATCHICKENOFF, TXT_TXT_CHEATMASSACRE, TXT_TXT_CHEATIDDQD, TXT_TXT_CHEATIDKFA, TXT_TXT_NEEDBLUEKEY, TXT_TXT_NEEDGREENKEY, TXT_TXT_NEEDYELLOWKEY, TXT_TXT_GAMESAVED, TXT_HUSTR_CHATMACRO0, TXT_HUSTR_CHATMACRO1, TXT_HUSTR_CHATMACRO2, TXT_HUSTR_CHATMACRO3, TXT_HUSTR_CHATMACRO4, TXT_HUSTR_CHATMACRO5, TXT_HUSTR_CHATMACRO6, TXT_HUSTR_CHATMACRO7, TXT_HUSTR_CHATMACRO8, TXT_HUSTR_CHATMACRO9, TXT_HUSTR_TALKTOSELF1, TXT_HUSTR_TALKTOSELF2, TXT_HUSTR_TALKTOSELF3, TXT_HUSTR_TALKTOSELF4, TXT_HUSTR_TALKTOSELF5, TXT_HUSTR_MESSAGESENT, TXT_HUSTR_PLRGREEN, TXT_HUSTR_PLRINDIGO, TXT_HUSTR_PLRBROWN, TXT_HUSTR_PLRRED, TXT_AMSTR_FOLLOWON, TXT_AMSTR_FOLLOWOFF, TXT_AMSTR_GRIDON, TXT_AMSTR_GRIDOFF, TXT_AMSTR_MARKEDSPOT, TXT_AMSTR_MARKSCLEARED, TXT_STSTR_DQDON, TXT_STSTR_DQDOFF, TXT_STSTR_KFAADDED, TXT_STSTR_NCON, TXT_STSTR_NCOFF, TXT_STSTR_BEHOLD, TXT_STSTR_BEHOLDX, TXT_STSTR_CHOPPERS, TXT_STSTR_CLEV, TXT_E1TEXT, TXT_E2TEXT, TXT_E3TEXT, TXT_E4TEXT, TXT_E5TEXT, TXT_LOADMISSING, TXT_EPISODE1, TXT_EPISODE2, TXT_EPISODE3, TXT_EPISODE4, TXT_EPISODE5, TXT_EPISODE6, TXT_AMSTR_ROTATEON, TXT_AMSTR_ROTATEOFF, TXT_SKILL1, TXT_SKILL2, TXT_SKILL3, TXT_SKILL4, TXT_SKILL5, TXT_KEY1, TXT_KEY2, TXT_KEY3, TXT_SAVEOUTMAP, TXT_ENDNOGAME, TXT_SUICIDEOUTMAP, TXT_SUICIDEASK, TXT_PICKGAMETYPE, TXT_SINGLEPLAYER, TXT_MULTIPLAYER, TXT_NOTDESIGNEDFOR, TXT_GAMESETUP, TXT_PLAYERSETUP, TXT_HUSTR_E1M1, TXT_HUSTR_E1M2, TXT_HUSTR_E1M3, TXT_HUSTR_E1M4, TXT_HUSTR_E1M5, TXT_HUSTR_E1M6, TXT_HUSTR_E1M7, TXT_HUSTR_E1M8, TXT_HUSTR_E1M9, TXT_HUSTR_E2M1, TXT_HUSTR_E2M2, TXT_HUSTR_E2M3, TXT_HUSTR_E2M4, TXT_HUSTR_E2M5, TXT_HUSTR_E2M6, TXT_HUSTR_E2M7, TXT_HUSTR_E2M8, TXT_HUSTR_E2M9, TXT_HUSTR_E3M1, TXT_HUSTR_E3M2, TXT_HUSTR_E3M3, TXT_HUSTR_E3M4, TXT_HUSTR_E3M5, TXT_HUSTR_E3M6, TXT_HUSTR_E3M7, TXT_HUSTR_E3M8, TXT_HUSTR_E3M9, TXT_HUSTR_E4M1, TXT_HUSTR_E4M2, TXT_HUSTR_E4M3, TXT_HUSTR_E4M4, TXT_HUSTR_E4M5, TXT_HUSTR_E4M6, TXT_HUSTR_E4M7, TXT_HUSTR_E4M8, TXT_HUSTR_E4M9, TXT_HUSTR_E5M1, TXT_HUSTR_E5M2, TXT_HUSTR_E5M3, TXT_HUSTR_E5M4, TXT_HUSTR_E5M5, TXT_HUSTR_E5M6, TXT_HUSTR_E5M7, TXT_HUSTR_E5M8, TXT_HUSTR_E5M9, TXT_HUSTR_E6M1, TXT_HUSTR_E6M2, TXT_HUSTR_E6M3, NUMTEXT } textenum_t; // Sounds. typedef enum { SFX_NONE, SFX_GLDHIT, SFX_GNTFUL, SFX_GNTHIT, SFX_GNTPOW, SFX_GNTACT, SFX_GNTUSE, SFX_PHOSHT, SFX_PHOHIT, SFX_PHOPOW, SFX_LOBSHT, SFX_LOBHIT, SFX_LOBPOW, SFX_HRNSHT, SFX_HRNHIT, SFX_HRNPOW, SFX_RAMPHIT, SFX_RAMRAIN, SFX_BOWSHT, SFX_STFHIT, SFX_STFPOW, SFX_STFCRK, SFX_IMPSIT, SFX_IMPAT1, SFX_IMPAT2, SFX_IMPDTH, SFX_IMPACT, SFX_IMPPAI, SFX_MUMSIT, SFX_MUMAT1, SFX_MUMAT2, SFX_MUMDTH, SFX_MUMACT, SFX_MUMPAI, SFX_MUMHED, SFX_BSTSIT, SFX_BSTATK, SFX_BSTDTH, SFX_BSTACT, SFX_BSTPAI, SFX_CLKSIT, SFX_CLKATK, SFX_CLKDTH, SFX_CLKACT, SFX_CLKPAI, SFX_SNKSIT, SFX_SNKATK, SFX_SNKDTH, SFX_SNKACT, SFX_SNKPAI, SFX_KGTSIT, SFX_KGTATK, SFX_KGTAT2, SFX_KGTDTH, SFX_KGTACT, SFX_KGTPAI, SFX_WIZSIT, SFX_WIZATK, SFX_WIZDTH, SFX_WIZACT, SFX_WIZPAI, SFX_MINSIT, SFX_MINAT1, SFX_MINAT2, SFX_MINAT3, SFX_MINDTH, SFX_MINACT, SFX_MINPAI, SFX_HEDSIT, SFX_HEDAT1, SFX_HEDAT2, SFX_HEDAT3, SFX_HEDDTH, SFX_HEDACT, SFX_HEDPAI, SFX_SORZAP, SFX_SORRISE, SFX_SORSIT, SFX_SORATK, SFX_SORACT, SFX_SORPAI, SFX_SORDSPH, SFX_SORDEXP, SFX_SORDBON, SFX_SBTSIT, SFX_SBTATK, SFX_SBTDTH, SFX_SBTACT, SFX_SBTPAI, SFX_PLROOF, SFX_PLRPAI, SFX_PLRDTH, SFX_GIBDTH, SFX_PLRWDTH, SFX_PLRCDTH, SFX_ITEMUP, SFX_WPNUP, SFX_TELEPT, SFX_DOROPN, SFX_DORCLS, SFX_DORMOV, SFX_ARTIUP, SFX_SWITCH, SFX_PSTART, SFX_PSTOP, SFX_STNMOV, SFX_CHICPAI, SFX_CHICATK, SFX_CHICDTH, SFX_CHICACT, SFX_CHICPK1, SFX_CHICPK2, SFX_CHICPK3, SFX_KEYUP, SFX_RIPSLOP, SFX_NEWPOD, SFX_PODEXP, SFX_BOUNCE, SFX_VOLSHT, SFX_VOLHIT, SFX_BURN, SFX_SPLASH, SFX_GLOOP, SFX_RESPAWN, SFX_BLSSHT, SFX_BLSHIT, SFX_CHAT, SFX_INVENTORY_USE, SFX_GFRAG, SFX_WATERFL, SFX_WIND, SFX_AMB1, SFX_AMB2, SFX_AMB3, SFX_AMB4, SFX_AMB5, SFX_AMB6, SFX_AMB7, SFX_AMB8, SFX_AMB9, SFX_AMB10, SFX_AMB11, SFX_SECRET, NUMSFX } sfxenum_t; /** * Music. * These ids are no longer used. All tracks are played by ident. typedef enum { MUS_E1M1, MUS_E1M2, MUS_E1M3, MUS_E1M4, MUS_E1M5, MUS_E1M6, MUS_E1M7, MUS_E1M8, MUS_E1M9, MUS_E2M1, MUS_E2M2, MUS_E2M3, MUS_E2M4, MUS_E2M5, MUS_E2M6, MUS_E2M7, MUS_E2M8, MUS_E2M9, MUS_E3M1, MUS_E3M2, MUS_E3M3, MUS_E3M4, MUS_E3M5, MUS_E3M6, MUS_E3M7, MUS_E3M8, MUS_E3M9, MUS_E4M1, MUS_E4M2, MUS_E4M3, MUS_E4M4, MUS_E4M5, MUS_E4M6, MUS_E4M7, MUS_E4M8, MUS_E4M9, MUS_E5M1, MUS_E5M2, MUS_E5M3, MUS_E5M4, MUS_E5M5, MUS_E5M6, MUS_E5M7, MUS_E5M8, MUS_E5M9, MUS_E6M1, MUS_E6M2, MUS_E6M3, MUS_TITL, MUS_INTR, MUS_CPTD, NUMMUSIC } musicenum_t; */ #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/st_stuff.h0000644000175000017500000000403011357170242023771 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.h: Statusbar code jHeretic - specific. * * Does the face/direction indicator animatin. * Does palette indicators as well (red pain/berserk, bright pickup) */ #ifndef __ST_STUFF_H__ #define __ST_STUFF_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif // Size of statusbar, now sensitive for scaling. #define ST_HEIGHT (42 * SCREEN_MUL) #define ST_WIDTH (SCREENWIDTH) #define ST_Y (SCREENHEIGHT - ST_HEIGHT) // Called by main loop. void ST_Ticker(void); // Called by main loop. void ST_Drawer(int player, int fullscreenMode, boolean refresh); void ST_Start(int player); void ST_Stop(int player); // Called by startup code. void ST_Register(void); void ST_Init(void); void ST_doPaletteStuff(int player); void ST_updateGraphics(void); // Called when it might be neccessary for the hud to unhide. void ST_HUDUnHide(int player, hueevent_t ev); void ST_FlashCurrentItem(int player); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_lights.h0000644000175000017500000000461211357170242023753 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.h: Per-sector lighting effects - jHeretic specific. */ #ifndef __P_LIGHTS_H__ #define __P_LIGHTS_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #define GLOWSPEED (8) #define STROBEBRIGHT (5) #define FASTDARK (15) #define SLOWDARK (35) typedef struct { thinker_t thinker; sector_t* sector; int count; float maxLight; float minLight; int maxTime; int minTime; } lightflash_t; typedef struct { thinker_t thinker; sector_t* sector; int count; float minLight; float maxLight; int darkTime; int brightTime; } strobe_t; typedef struct { thinker_t thinker; sector_t* sector; float minLight; float maxLight; int direction; } glow_t; void T_LightFlash(lightflash_t* flash); void P_SpawnLightFlash(sector_t* sector); void T_StrobeFlash(strobe_t* flash); void P_SpawnStrobeFlash(sector_t* sector, int fastOrSlow, int inSync); void T_Glow(glow_t* g); void P_SpawnGlowingLight(sector_t* sector); void EV_StartLightStrobing(linedef_t* line); void EV_TurnTagLightsOff(linedef_t* line); void EV_LightTurnOn(linedef_t* line, float bright); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_player.h0000644000175000017500000001327111357170242023746 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_player.h: */ #ifndef __JHERETIC_PLAYER_H__ #define __JHERETIC_PLAYER_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif // The player data structure depends on a number // of other structs: items (internal inventory), // animation states (closely tied to the sprites // used to represent them, unfortunately). #include "h_items.h" #include "p_pspr.h" // In addition, the player is just a special // case of the generic moving object/actor. #include "p_mobj.h" #include "g_controls.h" #ifdef __GNUG__ #pragma interface #endif // // Player states. // typedef enum { // Playing or camping. PST_LIVE, // Dead on the ground, view follows killer. PST_DEAD, // Ready to restart/respawn??? PST_REBORN } playerstate_t; // // Player internal flags, for cheats and debug. // typedef enum { // No clipping, walk through barriers. CF_NOCLIP = 1, // No damage, no health loss. CF_GODMODE = 2, // Not really a cheat, just a debug aid. CF_NOMOMENTUM = 4 } cheat_t; typedef struct player_s { ddplayer_t* plr; // Pointer to the engine's player data. playerstate_t playerState; playerclass_t class; // Player class. playerbrain_t brain; // This is only used between levels, // mo->health is used during levels. int health; int armorPoints; // Armor type is 0-2. int armorType; // Power ups. invinc and invis are tic counters. int powers[NUM_POWER_TYPES]; boolean keys[NUM_KEY_TYPES]; boolean backpack; signed int frags[MAXPLAYERS]; weapontype_t readyWeapon; weapontype_t pendingWeapon; // Is wp_nochange if not changing. struct playerweapon_s { boolean owned; } weapons[NUM_WEAPON_TYPES]; struct playerammo_s { int owned; int max; } ammo[NUM_AMMO_TYPES]; // true if button down last tic int attackDown; int useDown; // Bit flags, for cheats and debug, see cheat_t, above. int cheats; // Refired shots are less accurate. int refire; // For intermission stats. int killCount; int itemCount; int secretCount; // For screen flashing (red or bright). int damageCount; int bonusCount; // Who did damage (NULL for floors/ceilings). mobj_t* attacker; // Player skin colorshift, 0-3 for which color to draw player. int colorMap; // Overlay view sprites (gun, etc). pspdef_t pSprites[NUMPSPRITES]; // True if secret level has been done. boolean didSecret; int jumpTics; // The player can jump if this counter is zero. int airCounter; int rebornWait; // The player can be reborn if this counter is zero. boolean centering; // The player's view pitch is centering back to zero. int update, startSpot; float viewOffset[3]; // Relative to position of the player mobj. float viewZ; // Focal origin above r.z. float viewHeight; // Base height above floor for viewZ. float viewHeightDelta; float bob; // Bounded/scaled total momentum. // Target view to a mobj (NULL=disabled). mobj_t* viewLock; // $democam int lockFull; int flyHeight; // // DJS - Here follows Heretic specific player_t properties // int flameCount; // For flame thrower duration. int morphTics; // player is a chicken if > 0. int chickenPeck; // chicken peck countdown. mobj_t* rain1; // Active rain maker 1. mobj_t* rain2; // Active rain maker 2. } player_t; // // INTERMISSION // Structure passed e.g. to IN_Init(wb) // /*typedef struct { boolean inGame; // Whether the player is in game. // Player stats, kills, collected items etc. int kills; int items; int secret; int time; int frags[MAXPLAYERS]; int score; // Current score on entry, modified on return. } wbplayerstruct_t;*/ typedef struct { uint episode; boolean didSecret; // If true, splash the secret level. uint currentMap, nextMap; // This and next maps. /* int maxKills; int maxItems; int maxSecret; int maxFrags; int parTime; int pNum; // Index of this player in game. wbplayerstruct_t plyr[MAXPLAYERS];*/ } wbstartstruct_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_sound.h0000644000175000017500000000235211357170242023610 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sound.h: */ #ifndef __P_SOUND_H__ #define __P_SOUND_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomsday.h" enum { SORG_CENTER, SORG_FLOOR, SORG_CEILING }; void S_MapMusic(uint episode, uint map); void S_SectorSound(sector_t* sec, int origin, int id); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_type.h0000644000175000017500000000365211357170242023435 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_type.h: Simple basic typedefs. * * Isolated here to make it easier separating modules. */ #ifndef __JHERETIC_TYPE_H__ #define __JHERETIC_TYPE_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif // Predefined with some OS. #ifdef UNIX #include #define MAXCHAR SCHAR_MAX #define MAXSHORT SHRT_MAX #define MAXINT INT_MAX #define MAXLONG LONG_MAX #define MINCHAR SCHAR_MIN #define MINSHORT SHRT_MIN #define MININT INT_MIN #define MINLONG LONG_MIN #else /* not UNIX */ #define MAXCHAR ((char)0x7f) #define MAXSHORT ((short)0x7fff) // Max pos 32-bit int. #define MAXINT ((int)0x7fffffff) #define MAXLONG ((long)0x7fffffff) #define MINCHAR ((char)0x80) #define MINSHORT ((short)0x8000) // Max negative 32-bit integer. #define MININT ((int)0x80000000) #define MINLONG ((long)0x80000000) #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/mn_def.h0000644000175000017500000000674111357170242023377 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * mn_def.h: Menu defines and types. */ #ifndef __MENU_DEFS_H__ #define __MENU_DEFS_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHeretic__" #endif #include "hu_stuff.h" #include "m_defs.h" // Macros #define LEFT_DIR 0 #define RIGHT_DIR 1 #define DIR_MASK 0x1 #define ITEM_HEIGHT 20 #define SLOTTEXTLEN 16 #define ASCII_CURSOR '_' #define LINEHEIGHT 20 #define LINEHEIGHT_A 10 #define LINEHEIGHT_B 20 #define MENUCURSOR_OFFSET_X -2 #define MENUCURSOR_OFFSET_Y -1 #define MENUCURSOR_TICSPERFRAME 8 #define CURSORPREF "M_SLCTR%d" #define SKULLBASELMP "M_SKL00" #define NUMCURSORS 2 #define NUMSAVESLOTS 8 #define MAX_EDIT_LEN 256 // Types typedef struct { char text[MAX_EDIT_LEN]; char oldtext[MAX_EDIT_LEN]; // If the current edit is canceled... int firstVisible; } editfield_t; typedef enum { MENU_MAIN, MENU_NEWGAME, MENU_EPISODE, MENU_SKILL, MENU_OPTIONS, MENU_OPTIONS2, MENU_GAMEPLAY, MENU_HUD, MENU_MAP, MENU_FILES, MENU_LOAD, MENU_SAVE, MENU_MULTIPLAYER, MENU_GAMESETUP, MENU_PLAYERSETUP, MENU_INVENTORY, MENU_WEAPONS, MENU_CONTROLS, MENU_NONE } menutype_t; extern int menuTime; extern boolean shiftdown; extern menu_t *currentMenu; extern short itemOn; extern menu_t MapDef; // Multiplayer menus. extern menu_t MultiplayerMenu; extern menu_t GameSetupMenu; extern menu_t PlayerSetupMenu; void M_DrawTitle(char *text, int y); void M_WriteMenuText(const menu_t * menu, int index, const char *text); // Color widget. void DrawColorWidget(); void SCColorWidget(int index, void *data); void M_WGCurrentColor(int option, void *data); void M_DrawSaveLoadBorder(int x, int y, int width); void M_SetupNextMenu(menu_t* menudef); void M_DrawThermo(int x, int y, int thermWidth, int thermDot); void MN_DrawSlider(const menu_t * menu, int item, int width, int slot); void MN_DrawColorBox(const menu_t * menu, int index, float r, float g, float b, float a); void M_StartControlPanel(void); void M_FloatMod10(float *variable, int option); void SCEnterMultiplayerMenu(int option, void *data); void MN_TickerEx(void); // The extended ticker. void M_ToggleVar(int option, void* context); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/m_cheat.h0000644000175000017500000000217211357170242023541 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef M_CHEAT_H #define M_CHEAT_H #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif void Cht_Init(void); #endif /* M_CHEAT_H */ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/g_ctrl.h0000644000175000017500000000224511357170242023414 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.h: */ #ifndef __JHERETIC_CTRL_H__ #define __JHERETIC_CTRL_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif void G_RegisterPlayerControls(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_pspr.h0000644000175000017500000000272611357170242023451 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.h: Sprite animation. */ #ifndef __P_PSPR_H__ #define __P_PSPR_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif typedef enum { ps_weapon, ps_flash, NUMPSPRITES } psprnum_t; typedef struct pspdef_s { state_t* state; // a NULL state means not active. int tics; float pos[2]; } pspdef_t; void R_GetWeaponBob(int player, float* x, float* y); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/dstrings.h0000644000175000017500000002223111357170242023774 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2007 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dstrings.h: */ #ifndef __HERETICSTRINGS__ #define __HERETICSTRINGS__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #define GET_TXT(x) ((*gi.text)[x].text) #define NUM_QUITMESSAGES 0 #define PRESSKEY GET_TXT(TXT_PRESSKEY) #define PRESSYN GET_TXT(TXT_PRESSYN) #define TXT_PAUSED GET_TXT(TXT_TXT_PAUSED) #define QUITMSG GET_TXT(TXT_QUITMSG) #define LOADNET GET_TXT(TXT_LOADNET) #define QLOADNET GET_TXT(TXT_QLOADNET) #define QSAVESPOT GET_TXT(TXT_QSAVESPOT) #define SAVEDEAD GET_TXT(TXT_SAVEDEAD) #define SAVEOUTMAP GET_TXT(TXT_SAVEOUTMAP) #define QSPROMPT GET_TXT(TXT_QSPROMPT) #define QLPROMPT GET_TXT(TXT_QLPROMPT) #define NEWGAME GET_TXT(TXT_NEWGAME) #define NIGHTMARE GET_TXT(TXT_NIGHTMARE) #define SWSTRING GET_TXT(TXT_SWSTRING) #define MSGOFF GET_TXT(TXT_MSGOFF) #define MSGON GET_TXT(TXT_MSGON) #define NETEND GET_TXT(TXT_NETEND) #define ENDGAME GET_TXT(TXT_ENDGAME) #define ENDNOGAME GET_TXT(TXT_ENDNOGAME) #define SUICIDEOUTMAP GET_TXT(TXT_SUICIDEOUTMAP) #define SUICIDEASK GET_TXT(TXT_SUICIDEASK) #define DOSY GET_TXT(TXT_DOSY) #define DETAILHI GET_TXT(TXT_DETAILHI) #define DETAILLO GET_TXT(TXT_DETAILLO) #define GAMMALVL0 GET_TXT(TXT_GAMMALVL0) #define GAMMALVL1 GET_TXT(TXT_GAMMALVL1) #define GAMMALVL2 GET_TXT(TXT_GAMMALVL2) #define GAMMALVL3 GET_TXT(TXT_GAMMALVL3) #define GAMMALVL4 GET_TXT(TXT_GAMMALVL4) #define EMPTYSTRING GET_TXT(TXT_EMPTYSTRING) // Pickup Key messages: #define TXT_GOTBLUEKEY GET_TXT(TXT_TXT_GOTBLUEKEY) #define TXT_GOTYELLOWKEY GET_TXT(TXT_TXT_GOTYELLOWKEY) #define TXT_GOTGREENKEY GET_TXT(TXT_TXT_GOTGREENKEY) // Inventory items: #define TXT_INV_HEALTH GET_TXT(TXT_TXT_INV_HEALTH) #define TXT_INV_FLY GET_TXT(TXT_TXT_INV_FLY) #define TXT_INV_INVULNERABILITY GET_TXT(TXT_TXT_INV_INVULNERABILITY) #define TXT_INV_TOMEOFPOWER GET_TXT(TXT_TXT_INV_TOMEOFPOWER) #define TXT_INV_INVISIBILITY GET_TXT(TXT_TXT_INV_INVISIBILITY) #define TXT_INV_EGG GET_TXT(TXT_TXT_INV_EGG) #define TXT_INV_SUPERHEALTH GET_TXT(TXT_TXT_INV_SUPERHEALTH) #define TXT_INV_TORCH GET_TXT(TXT_TXT_INV_TORCH) #define TXT_INV_FIREBOMB GET_TXT(TXT_TXT_INV_FIREBOMB) #define TXT_INV_TELEPORT GET_TXT(TXT_TXT_INV_TELEPORT) // Items #define TXT_ITEMHEALTH GET_TXT(TXT_TXT_ITEMHEALTH) #define TXT_ITEMBAGOFHOLDING GET_TXT(TXT_TXT_ITEMBAGOFHOLDING) #define TXT_ITEMSHIELD1 GET_TXT(TXT_TXT_ITEMSHIELD1) #define TXT_ITEMSHIELD2 GET_TXT(TXT_TXT_ITEMSHIELD2) #define TXT_ITEMSUPERMAP GET_TXT(TXT_TXT_ITEMSUPERMAP) // Ammo #define TXT_AMMOGOLDWAND1 GET_TXT(TXT_TXT_AMMOGOLDWAND1) #define TXT_AMMOGOLDWAND2 GET_TXT(TXT_TXT_AMMOGOLDWAND2) #define TXT_AMMOMACE1 GET_TXT(TXT_TXT_AMMOMACE1) #define TXT_AMMOMACE2 GET_TXT(TXT_TXT_AMMOMACE2) #define TXT_AMMOCROSSBOW1 GET_TXT(TXT_TXT_AMMOCROSSBOW1) #define TXT_AMMOCROSSBOW2 GET_TXT(TXT_TXT_AMMOCROSSBOW2) #define TXT_AMMOBLASTER1 GET_TXT(TXT_TXT_AMMOBLASTER1) #define TXT_AMMOBLASTER2 GET_TXT(TXT_TXT_AMMOBLASTER2) #define TXT_AMMOSKULLROD1 GET_TXT(TXT_TXT_AMMOSKULLROD1) #define TXT_AMMOSKULLROD2 GET_TXT(TXT_TXT_AMMOSKULLROD2) #define TXT_AMMOPHOENIXROD1 GET_TXT(TXT_TXT_AMMOPHOENIXROD1) #define TXT_AMMOPHOENIXROD2 GET_TXT(TXT_TXT_AMMOPHOENIXROD2) // Key names: #define KEY1 GET_TXT(TXT_KEY1) #define KEY2 GET_TXT(TXT_KEY2) #define KEY3 GET_TXT(TXT_KEY3) // Weapon names: #define TXT_WPNMACE GET_TXT(TXT_TXT_WPNMACE) #define TXT_WPNCROSSBOW GET_TXT(TXT_TXT_WPNCROSSBOW) #define TXT_WPNBLASTER GET_TXT(TXT_TXT_WPNBLASTER) #define TXT_WPNSKULLROD GET_TXT(TXT_TXT_WPNSKULLROD) #define TXT_WPNPHOENIXROD GET_TXT(TXT_TXT_WPNPHOENIXROD) #define TXT_WPNGAUNTLETS GET_TXT(TXT_TXT_WPNGAUNTLETS) #define TXT_CHEATGODON GET_TXT(TXT_TXT_CHEATGODON) #define TXT_CHEATGODOFF GET_TXT(TXT_TXT_CHEATGODOFF) #define TXT_CHEATNOCLIPON GET_TXT(TXT_TXT_CHEATNOCLIPON) #define TXT_CHEATNOCLIPOFF GET_TXT(TXT_TXT_CHEATNOCLIPOFF) #define TXT_CHEATWEAPONS GET_TXT(TXT_TXT_CHEATWEAPONS) #define TXT_CHEATFLIGHTON GET_TXT(TXT_TXT_CHEATFLIGHTON) #define TXT_CHEATFLIGHTOFF GET_TXT(TXT_TXT_CHEATFLIGHTOFF) #define TXT_CHEATPOWERON GET_TXT(TXT_TXT_CHEATPOWERON) #define TXT_CHEATPOWEROFF GET_TXT(TXT_TXT_CHEATPOWEROFF) #define TXT_CHEATHEALTH GET_TXT(TXT_TXT_CHEATHEALTH) #define TXT_CHEATKEYS GET_TXT(TXT_TXT_CHEATKEYS) #define TXT_CHEATSOUNDON GET_TXT(TXT_TXT_CHEATSOUNDON) #define TXT_CHEATSOUNDOFF GET_TXT(TXT_TXT_CHEATSOUNDOFF) #define TXT_CHEATTICKERON GET_TXT(TXT_TXT_CHEATTICKERON) #define TXT_CHEATTICKEROFF GET_TXT(TXT_TXT_CHEATTICKEROFF) #define TXT_CHEATINVITEMS1 GET_TXT(TXT_TXT_CHEATINVITEMS1) #define TXT_CHEATINVITEMS2 GET_TXT(TXT_TXT_CHEATINVITEMS2) #define TXT_CHEATINVITEMS3 GET_TXT(TXT_TXT_CHEATINVITEMS3) #define TXT_CHEATITEMSFAIL GET_TXT(TXT_TXT_CHEATITEMSFAIL) #define TXT_CHEATWARP GET_TXT(TXT_TXT_CHEATWARP) #define TXT_CHEATSCREENSHOT GET_TXT(TXT_TXT_CHEATSCREENSHOT) #define TXT_CHEATCHICKENON GET_TXT(TXT_TXT_CHEATCHICKENON) #define TXT_CHEATCHICKENOFF GET_TXT(TXT_TXT_CHEATCHICKENOFF) #define TXT_CHEATMASSACRE GET_TXT(TXT_TXT_CHEATMASSACRE) #define TXT_CHEATIDDQD GET_TXT(TXT_TXT_CHEATIDDQD) #define TXT_CHEATIDKFA GET_TXT(TXT_TXT_CHEATIDKFA) #define TXT_NEEDBLUEKEY GET_TXT(TXT_TXT_NEEDBLUEKEY) #define TXT_NEEDGREENKEY GET_TXT(TXT_TXT_NEEDGREENKEY) #define TXT_NEEDYELLOWKEY GET_TXT(TXT_TXT_NEEDYELLOWKEY) #define TXT_GAMESAVED GET_TXT(TXT_TXT_GAMESAVED) #define HUSTR_CHATMACRO1 GET_TXT(TXT_HUSTR_CHATMACRO1) #define HUSTR_CHATMACRO2 GET_TXT(TXT_HUSTR_CHATMACRO2) #define HUSTR_CHATMACRO3 GET_TXT(TXT_HUSTR_CHATMACRO3) #define HUSTR_CHATMACRO4 GET_TXT(TXT_HUSTR_CHATMACRO4) #define HUSTR_CHATMACRO5 GET_TXT(TXT_HUSTR_CHATMACRO5) #define HUSTR_CHATMACRO6 GET_TXT(TXT_HUSTR_CHATMACRO6) #define HUSTR_CHATMACRO7 GET_TXT(TXT_HUSTR_CHATMACRO7) #define HUSTR_CHATMACRO8 GET_TXT(TXT_HUSTR_CHATMACRO8) #define HUSTR_CHATMACRO9 GET_TXT(TXT_HUSTR_CHATMACRO9) #define HUSTR_CHATMACRO0 GET_TXT(TXT_HUSTR_CHATMACRO0) #define HUSTR_TALKTOSELF1 GET_TXT(TXT_HUSTR_TALKTOSELF1) #define HUSTR_TALKTOSELF2 GET_TXT(TXT_HUSTR_TALKTOSELF2) #define HUSTR_TALKTOSELF3 GET_TXT(TXT_HUSTR_TALKTOSELF3) #define HUSTR_TALKTOSELF4 GET_TXT(TXT_HUSTR_TALKTOSELF4) #define HUSTR_TALKTOSELF5 GET_TXT(TXT_HUSTR_TALKTOSELF5) #define HUSTR_MESSAGESENT GET_TXT(TXT_HUSTR_MESSAGESENT) // The following should NOT be changed unless it seems // just AWFULLY necessary #define HUSTR_PLRGREEN GET_TXT(TXT_HUSTR_PLRGREEN) #define HUSTR_PLRINDIGO GET_TXT(TXT_HUSTR_PLRINDIGO) #define HUSTR_PLRBROWN GET_TXT(TXT_HUSTR_PLRBROWN) #define HUSTR_PLRRED GET_TXT(TXT_HUSTR_PLRRED) #define HUSTR_KEYGREEN 'g' #define HUSTR_KEYINDIGO 'i' #define HUSTR_KEYBROWN 'b' #define HUSTR_KEYRED 'r' #define AMSTR_FOLLOWON GET_TXT(TXT_AMSTR_FOLLOWON) #define AMSTR_FOLLOWOFF GET_TXT(TXT_AMSTR_FOLLOWOFF) #define AMSTR_ROTATEON GET_TXT(TXT_AMSTR_ROTATEON) #define AMSTR_ROTATEOFF GET_TXT(TXT_AMSTR_ROTATEOFF) #define AMSTR_GRIDON GET_TXT(TXT_AMSTR_GRIDON) #define AMSTR_GRIDOFF GET_TXT(TXT_AMSTR_GRIDOFF) #define AMSTR_MARKEDSPOT GET_TXT(TXT_AMSTR_MARKEDSPOT) #define AMSTR_MARKSCLEARED GET_TXT(TXT_AMSTR_MARKSCLEARED) #define STSTR_DQDON GET_TXT(TXT_STSTR_DQDON) #define STSTR_DQDOFF GET_TXT(TXT_STSTR_DQDOFF) #define STSTR_KFAADDED GET_TXT(TXT_STSTR_KFAADDED) #define STSTR_NCON GET_TXT(TXT_STSTR_NCON) #define STSTR_NCOFF GET_TXT(TXT_STSTR_NCOFF) #define STSTR_BEHOLD GET_TXT(TXT_STSTR_BEHOLD) #define STSTR_BEHOLDX GET_TXT(TXT_STSTR_BEHOLDX) #define STSTR_CHOPPERS GET_TXT(TXT_STSTR_CHOPPERS) #define STSTR_CLEV GET_TXT(TXT_STSTR_CLEV) #define E1TEXT GET_TXT(TXT_E1TEXT) #define E2TEXT GET_TXT(TXT_E2TEXT) #define E3TEXT GET_TXT(TXT_E3TEXT) #define E4TEXT GET_TXT(TXT_E4TEXT) #define E5TEXT GET_TXT(TXT_E5TEXT) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/version.h0000644000175000017500000000345511357170242023633 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __JHERETIC_VERSION_H__ #define __JHERETIC_VERSION_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #ifndef JHERETIC_VER_ID # ifdef _DEBUG # define JHERETIC_VER_ID "+D Doomsday" # else # define JHERETIC_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define GAMENAMETEXT "jheretic" // Presented to the user in dialogs, messages etc. #define GAME_NICENAME "jHeretic" #define GAME_DETAILS "jHeretic is based on Heretic v1.3 by Raven Software." #define GAME_VERSION_TEXT "1.4.8" #define GAME_VERSION_TEXTLONG "Version" GAME_VERSION_TEXT " " __DATE__ " (" JHERETIC_VER_ID ")" #define GAME_VERSION_NUMBER 1,4,8,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_mobj.h0000644000175000017500000002317011357170242023410 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.h: Map Objects, MObj, definition and handling. */ #ifndef __P_MOBJ_H__ #define __P_MOBJ_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "p_terraintype.h" #include "h_think.h" #include "info.h" /** * Mobj flags * * \attention IMPORTANT - Keep this current!!! * LEGEND: * p = Flag is persistent (never changes in-game). * i = Internal use (not to be used in defintions). * * \todo Persistent flags (p) don't need to be included in save games or sent to * clients in netgames. We should collect those in to a const flags setting which * is set only once when the mobj is spawned. * * \todo All flags for internal use only (i) should be put in another var and the * flags removed from those defined in GAME/objects.DED */ // --- mobj.flags --- #define MF_SPECIAL 0x00000001 // Call P_SpecialThing when touched. #define MF_SOLID 0x00000002 // Blocks. #define MF_SHOOTABLE 0x00000004 // Can be hit. #define MF_NOSECTOR 0x00000008 // (p) Don't use the sector links (invisible but touchable). #define MF_NOBLOCKMAP 0x00000010 // (p) Don't use the blocklinks (inert but displayable) #define MF_AMBUSH 0x00000020 // Not to be activated by sound, deaf monster. #define MF_JUSTHIT 0x00000040 // Will try to attack right back. #define MF_JUSTATTACKED 0x00000080 // Will take at least one step before attacking. #define MF_SPAWNCEILING 0x00000100 // (p) Hang from ceiling instead of stand on floor. #define MF_NOGRAVITY 0x00000200 // Don't apply gravity (every tic). // Movement flags. #define MF_DROPOFF 0x00000400 // This allows jumps from high places. #define MF_PICKUP 0x00000800 // For players, will pick up items. #define MF_NOCLIP 0x00001000 // (i) Player cheat. //#define MF_SLIDE 0x00002000 // unused #define MF_FLOAT 0x00004000 // Allow moves to any height, no gravity. #define MF_TELEPORT 0x00008000 // (p) Don't cross lines or look at heights on teleport. #define MF_MISSILE 0x00010000 // Don't hit same species, explode on block. #define MF_DROPPED 0x00020000 // (i) Dropped by a demon, not level spawned. #define MF_SHADOW 0x00040000 // Use fuzzy draw (shadow demons or spectres). #define MF_NOBLOOD 0x00080000 // Don't bleed when shot (use puff). #define MF_CORPSE 0x00100000 // (i) Don't stop moving halfway off a step. #define MF_INFLOAT 0x00200000 // Floating to a height for a move, // don't auto float to target's height. #define MF_COUNTKILL 0x00400000 // count towards intermission kill total #define MF_COUNTITEM 0x00800000 // count towards intermission item total #define MF_SKULLFLY 0x01000000 // (i) skull in flight. #define MF_NOTDMATCH 0x02000000 // (p) not spawned in deathmatch mode (e.g. key cards). #define MF_TRANSLATION 0x0c000000 // (i) if 0x4 0x8 or 0xc, use a translation #define MF_TRANSSHIFT 26 // (N/A) table for player colormaps #define MF_LOCAL 0x10000000 // (p) Won't be sent to clients. #define MF_BRIGHTSHADOW 0x20000000 #define MF_BRIGHTEXPLODE 0x40000000 // Make this brightshadow when exploding. #define MF_VIEWALIGN 0x80000000 /* * The following flags are obsolete in a particular mobj version. * They will automatically be cleared when loading an old save game. */ #define MF_V6OBSOLETE (0x00002000) // (MF_SLIDE) // --- mobj.flags2 --- #define MF2_LOGRAV 0x00000001 // alternate gravity setting #define MF2_WINDTHRUST 0x00000002 // (p) gets pushed around by the wind specials // #define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor #define MF2_THRUGHOST 0x00000008 // (p) missile will pass through ghosts #define MF2_FLY 0x00000010 // (i) fly mode is active #define MF2_FLOORCLIP 0x00000020 // if feet are allowed to be clipped #define MF2_SPAWNFLOAT 0x00000040 // (p) spawn random float z #define MF2_NOTELEPORT 0x00000080 // does not teleport #define MF2_RIP 0x00000100 // (p) missile rips through solid targets #define MF2_PUSHABLE 0x00000200 // can be pushed by other moving mobjs #define MF2_SLIDE 0x00000400 // slides against walls #define MF2_ALWAYSLIT 0x00000800 #define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, // this flag will allow the mobj to // pass over/under other mobjs. #define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs #define MF2_INFZBOMBDAMAGE 0x00004000 // (p) Don't check z height with radius attacks #define MF2_BOSS 0x00008000 // (p) mobj is a major boss #define MF2_FIREDAMAGE 0x00010000 // does fire damage #define MF2_NODMGTHRUST 0x00020000 // does not thrust target when // damaging #define MF2_TELESTOMP 0x00040000 // mobj can stomp another #define MF2_FLOATBOB 0x00080000 // (p) use float bobbing z movement #define MF2_DONTDRAW 0X00100000 // don't generate a vissprite // --- mobj.flags3 --- #define MF3_NOINFIGHT 0x00000001 // Mobj will never be targeted for in-fighting // --- mobj.intflags --- (added in MOBJ_SAVEVERSION 6) // Internal mobj flags cannot be set using an external definition. #define MIF_FALLING 0x00000001 // $dropoff_fix: Object is falling from a ledge. /* * end mobj flags */ // For torque simulation: #define OVERDRIVE 6 #define MAXGEAR (OVERDRIVE+16) typedef enum dirtype_s { DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_NODIR, NUMDIRS } dirtype_t; // Map Object definition. typedef struct mobj_s { // Defined in dd_share.h; required mobj elements. DD_BASE_MOBJ_ELEMENTS() // Heretic-specific data: mobjinfo_t *info; // &mobjinfo[mobj->type] int damage; // For missiles int flags; int flags2; // Heretic flags int flags3; int special1; // Special info int special2; // Special info int special3; // Special info int health; int moveDir; // 0-7 int moveCount; // when 0, select a new dir struct mobj_s *target; // thing being chased/attacked (or NULL) // also the originator for missiles // used by player to freeze a bit after // teleporting int threshold; // if >0, the target will be chased int intFlags; // $dropoff_fix: internal flags float dropOffZ; // $dropoff_fix short gear; // used in torque simulation boolean wallRun; // true = last move was the result of a wallrun // no matter what (even if shot) struct player_s *player; // only valid if type == MT_PLAYER int lastLook; // player number last looked for // For nightmare/multiplayer respawn. struct { float pos[3]; angle_t angle; int flags; // MSF_* flags. } spawnSpot; // Thing being chased/attacked for tracers. struct mobj_s *tracer; // Used for pod generating. struct mobj_s *generator; int turnTime; // $visangle-facetarget int corpseTics; // $vanish: how long has this been dead? } mobj_t; typedef struct polyobj_s { // Defined in dd_share.h; required polyobj elements. DD_BASE_POLYOBJ_ELEMENTS() // Heretic-specific data: } polyobj_t; mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags); mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags); void P_SpawnPuff(float x, float y, float z, angle_t angle); void P_SpawnBlood(float x, float y, float z, int damage, angle_t angle); mobj_t* P_SpawnMissile(mobjtype_t type, mobj_t* source, mobj_t* dest, boolean checkSpawn); mobj_t* P_SpawnMissileAngle(mobjtype_t type, mobj_t *source, angle_t angle, float momz); mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle); const terraintype_t* P_MobjGetFloorTerrainType(mobj_t *thing); float P_MobjGetFriction(mobj_t *mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_api.h0000644000175000017500000000241611357170242023222 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_api.h: */ #ifndef __JHERETIC_API_H__ #define __JHERETIC_API_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomsday.h" int G_GetInteger(int id); void *G_GetVariable(int id); game_export_t *GetGameAPI(game_import_t *imports); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/resource.h0000644000175000017500000000272711357170242023776 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * resource.h: */ #ifndef __JHERETIC_RESOURCE_H__ #define __JHERETIC_RESOURCE_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #define IDI_HERETIC 101 #define IDI_HERETIC_2 102 #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 103 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_spec.h0000644000175000017500000000510311357170242023407 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.h: Implements special effects: * * Texture animation, height or lighting changes according to adjacent * sectors, respective utility functions, etc. * * Line Tag handling. Line and Sector triggers. * * Events are operations triggered by using, crossing, or shooting * special lines, or by timed thinkers. */ #ifndef __P_SPEC_H__ #define __P_SPEC_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "h_player.h" #include "r_data.h" #define MO_TELEPORTMAN 14 // at game start void P_InitPicAnims(void); void P_InitLava(void); // at map load void P_SpawnSpecials(void); void P_InitAmbientSound(void); void P_AddAmbientSfx(int sequence); // every tic void P_UpdateSpecials(void); void P_AmbientSound(void); boolean P_ActivateLine(linedef_t* ld, mobj_t* mo, int side, int activationType); void P_PlayerInSpecialSector(player_t* player); void P_PlayerInWindSector(player_t* player); int EV_DoDonut(linedef_t* line); typedef enum { ok, crushed, pastdest } result_e; typedef enum { build8, // Slowly build by 8. build16 // Slowly build by 16. } stair_e; result_e T_MovePlane(sector_t* sector, float speed, float dest, int crush, int floorOrCeiling, int direction); int EV_BuildStairs(linedef_t* line, stair_e type); boolean P_UseSpecialLine2(mobj_t* mo, linedef_t* line, int side); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/jheretic.h0000644000175000017500000000504711357170242023742 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jheretic.h: All jHeretic Headers * * A convenience header for including all jHeretic headers. */ #ifndef __JHERETIC_CONVENIENCE_H__ #define __JHERETIC_CONVENIENCE_H__ #include "../../jheretic/include/acfnlink.h" #include "../../jheretic/include/doomdef.h" #include "../../jheretic/include/dstrings.h" #include "../../jheretic/include/g_game.h" #include "../../jheretic/include/g_ctrl.h" #include "../../jheretic/include/h_api.h" #include "../../jheretic/include/h_config.h" #include "../../jheretic/include/h_console.h" #include "../../jheretic/include/h_event.h" #include "../../jheretic/include/h_main.h" #include "../../jheretic/include/h_refresh.h" #include "../../jheretic/include/h_stat.h" #include "../../jheretic/include/h_type.h" #include "../../jheretic/include/in_lude.h" #include "../../jheretic/include/m_cheat.h" #include "../../jheretic/include/m_random.h" #include "../../jheretic/include/m_menu.h" #include "../../jheretic/include/mn_def.h" #include "../../jheretic/include/p_enemy.h" #include "../../jheretic/include/p_inter.h" #include "../../jheretic/include/p_lights.h" #include "../../jheretic/include/p_local.h" #include "../../jheretic/include/p_maputl.h" #include "../../jheretic/include/p_oldsvg.h" #include "../../jheretic/include/p_pspr.h" #include "../../jheretic/include/p_setup.h" #include "../../jheretic/include/p_sound.h" #include "../../jheretic/include/p_spec.h" #include "../../jheretic/include/p_telept.h" #include "../../jheretic/include/r_defs.h" #include "../../jheretic/include/st_stuff.h" #include "../../jheretic/include/tables.h" #endif // __JHERETIC_CONVENIENCE_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_local.h0000644000175000017500000001246211357170242023555 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_local.h: */ #ifndef __P_LOCAL_H__ #define __P_LOCAL_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #ifndef __R_LOCAL__ #include "r_local.h" #endif #include "p_spec.h" #include "p_start.h" #include "p_actor.h" #include "p_xg.h" #include "info.h" // Palette indices, for damage/bonus red-/gold-shifts. #define STARTREDPALS 1 #define STARTBONUSPALS 9 #define NUMREDPALS 8 #define NUMBONUSPALS 4 #define FLOATSPEED 4 #define MAXHEALTH (maxHealth) //100 #define MAXCHICKENHEALTH 30 #define VIEWHEIGHT 41 // player radius for movement checking #define PLAYERRADIUS 16 // MAXRADIUS is for precalculated sector block boxes // the spider demon is larger, // but we do not have any moving sectors nearby #define MAXRADIUS 32 #define MAXMOVE 30 #define USERANGE 64 #define MELEERANGE 64 #define MISSILERANGE (32*64) // Follow a player exlusively for 3 seconds. #define BASETHRESHOLD 100 #define sentient(mobj) ((mobj)->health > 0 && P_GetState((mobj)->type, SN_SEE)) #define FOOTCLIPSIZEF (10) #define thinkerCap (*gi.thinkerCap) #define FLAME_THROWER_TICS 10*35 #define MAGIC_JUNK 1234 #define USE_GWND_AMMO_1 1 #define USE_GWND_AMMO_2 1 #define USE_CBOW_AMMO_1 1 #define USE_CBOW_AMMO_2 1 #define USE_BLSR_AMMO_1 1 #define USE_BLSR_AMMO_2 5 #define USE_SKRD_AMMO_1 1 #define USE_SKRD_AMMO_2 5 #define USE_PHRD_AMMO_1 1 #define USE_PHRD_AMMO_2 1 #define USE_MACE_AMMO_1 1 #define USE_MACE_AMMO_2 5 void P_RepositionMace(mobj_t* mo); void P_SetPsprite(player_t* player, int position, statenum_t stnum); void P_SetupPsprites(player_t* curplayer); void P_MovePsprites(player_t* curplayer); void P_DropWeapon(player_t* player); void P_ActivateMorphWeapon(player_t* player); void P_PostMorphWeapon(player_t* player, weapontype_t weapon); void P_UpdateBeak(player_t* player, pspdef_t* psp); void P_FireWeapon(player_t* player); void P_ClientSideThink(void); void P_Thrust(player_t* player, angle_t angle, float move); boolean P_UndoPlayerMorph(player_t* player); #define FRICTION_NORMAL (0.90625f) #define FRICTION_FLY (0.91796875f) #define FRICTION_HIGH (0.5f) #define FRICTION_LOW (0.97265625f) extern mobjtype_t puffType; extern mobj_t* missileMobj; boolean P_MobjChangeState(mobj_t* mo, statenum_t state); boolean P_SetMobjStateNF(mobj_t* mo, statenum_t state); void P_ThrustMobj(mobj_t* mo, angle_t angle, float move); void P_WindThrust(mobj_t* mo); int P_FaceMobj(mobj_t* source, mobj_t* target, angle_t* delta); boolean P_SeekerMissile(mobj_t* actor, angle_t thresh, angle_t turnMax); void P_MobjThinker(mobj_t* mo); void P_SpawnBloodSplatter(float x, float y, float z, mobj_t* originator); void P_RipperBlood(mobj_t* mo); boolean P_HitFloor(mobj_t* thing); boolean P_CheckMissileSpawn(mobj_t* missile); void P_MobjMoveZ(mobj_t* mo); void P_ExplodeMissile(mobj_t* mo); #define OPENRANGE (*(float*) DD_GetVariable(DD_OPENRANGE)) #define OPENTOP (*(float*) DD_GetVariable(DD_OPENTOP)) #define OPENBOTTOM (*(float*) DD_GetVariable(DD_OPENBOTTOM)) #define LOWFLOOR (*(float*) DD_GetVariable(DD_LOWFLOOR)) const char* P_GetMapName(uint episode, uint map); const char* P_GetShortMapName(uint episode, uint map); extern float turboMul; extern int maxAmmo[NUM_AMMO_TYPES]; extern int clipAmmo[NUM_AMMO_TYPES]; extern int maxAmmo[NUM_AMMO_TYPES]; void P_GiveKey(player_t* player, keytype_t key); void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher); int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage, boolean stomping); boolean P_GiveAmmo(player_t* player, ammotype_t ammo, int count); boolean P_GiveBody(player_t* player, int num); boolean P_GivePower(player_t* player, powertype_t power); boolean P_MorphPlayer(player_t* player); void Draw_BeginZoom(float s, float originX, float originY); void Draw_EndZoom(void); #define LOOKDIR2DEG(x) ((x) * 85.0/110.0) #define LOOKDIR2RAD(x) (LOOKDIR2DEG(x)/180*PI) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_setup.h0000644000175000017500000000327211357170242023622 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.h: Map setup routines */ #ifndef __P_SETUP_H__ #define __P_SETUP_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif // Map objects and their properties: enum { MO_NONE = 0, MO_THING, MO_XLINEDEF, MO_XSECTOR, MO_X, MO_Y, MO_Z, MO_ANGLE, MO_TYPE, MO_DOOMEDNUM, MO_FLAGS, MO_TAG }; void P_Init(void); void P_RegisterMapObjs(void); int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void* data); int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void* data); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_stat.h0000644000175000017500000000423311357170242023423 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_stat.h: All the global variables that store the internal state. * * Theoretically speaking, the internal state of the game can be found by * looking at the variables collected here, and every relevant module will * have to include this header file. In practice, things are a bit messy. */ #ifndef __JHERETIC_STATE_H__ #define __JHERETIC_STATE_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomdata.h" #include "h_player.h" #define viewwindowx Get(DD_VIEWWINDOW_X) #define viewwindowy Get(DD_VIEWWINDOW_Y) // Player taking events, and displaying. #define CONSOLEPLAYER Get(DD_CONSOLEPLAYER) #define DISPLAYPLAYER Get(DD_DISPLAYPLAYER) #define GAMETIC Get(DD_GAMETIC) #define maketic Get(DD_MAKETIC) #define ticdup 1 // Status flags for refresh. extern boolean paused; // If true, load all graphics at level load. extern boolean precache; // wipegamestate can be set to -1 to force a wipe on the next draw extern gamestate_t wipeGameState; extern int bodyQueueSlot; // This one is related to the 3-screen display mode. // ANG90 = left side, ANG270 = right extern int viewAngleOffset; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/acfnlink.h0000644000175000017500000001330311357170242023724 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * acfnlink.h: */ #ifndef __ACTION_LINK_H__ #define __ACTION_LINK_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "dd_share.h" typedef struct { char* name; // Name of the routine. void (C_DECL *func) (); // Pointer to the function. } actionlink_t; extern actionlink_t actionlinks[]; void C_DECL A_AccTeleGlitter(); void C_DECL A_AddPlayerCorpse(); void C_DECL A_AddPlayerRain(); void C_DECL A_BeakAttackPL1(); void C_DECL A_BeakAttackPL2(); void C_DECL A_BeakRaise(); void C_DECL A_BeakReady(); void C_DECL A_BeastAttack(); void C_DECL A_BeastPuff(); void C_DECL A_BlueSpark(); void C_DECL A_BoltSpark(); void C_DECL A_BossDeath(); void C_DECL A_Chase(); void C_DECL A_CheckBurnGone(); void C_DECL A_CheckSkullDone(); void C_DECL A_CheckSkullFloor(); void C_DECL A_ChicAttack(); void C_DECL A_ChicChase(); void C_DECL A_ChicLook(); void C_DECL A_ChicPain(); void C_DECL A_ClinkAttack(); void C_DECL A_ContMobjSound(); void C_DECL A_DeathBallImpact(); void C_DECL A_DripBlood(); void C_DECL A_ESound(); void C_DECL A_Explode(); void C_DECL A_FaceTarget(); void C_DECL A_Feathers(); void C_DECL A_FireBlasterPL1(); void C_DECL A_FireBlasterPL2(); void C_DECL A_FireCrossbowPL1(); void C_DECL A_FireCrossbowPL2(); void C_DECL A_FireGoldWandPL1(); void C_DECL A_FireGoldWandPL2(); void C_DECL A_FireMacePL1(); void C_DECL A_FireMacePL2(); void C_DECL A_FirePhoenixPL1(); void C_DECL A_FirePhoenixPL2(); void C_DECL A_FireSkullRodPL1(); void C_DECL A_FireSkullRodPL2(); void C_DECL A_FlameEnd(); void C_DECL A_FlameSnd(); void C_DECL A_FloatPuff(); void C_DECL A_FreeTargMobj(); void C_DECL A_GauntletAttack(); void C_DECL A_GenWizard(); void C_DECL A_GhostOff(); void C_DECL A_HeadAttack(); void C_DECL A_HeadFireGrow(); void C_DECL A_HeadIceImpact(); void C_DECL A_HideInCeiling(); void C_DECL A_HideThing(); void C_DECL A_ImpDeath(); void C_DECL A_ImpExplode(); void C_DECL A_ImpMeAttack(); void C_DECL A_ImpMsAttack(); void C_DECL A_ImpMsAttack2(); void C_DECL A_ImpXDeath1(); void C_DECL A_ImpXDeath2(); void C_DECL A_InitKeyGizmo(); void C_DECL A_InitPhoenixPL2(); void C_DECL A_KnightAttack(); void C_DECL A_Light0(); void C_DECL A_Look(); void C_DECL A_Lower(); void C_DECL A_MaceBallImpact(); void C_DECL A_MaceBallImpact2(); void C_DECL A_MacePL1Check(); void C_DECL A_MakePod(); void C_DECL A_MinotaurAtk1(); void C_DECL A_MinotaurAtk2(); void C_DECL A_MinotaurAtk3(); void C_DECL A_MinotaurCharge(); void C_DECL A_MinotaurDecide(); void C_DECL A_MntrFloorFire(); void C_DECL A_MummyAttack(); void C_DECL A_MummyAttack2(); void C_DECL A_MummyFX1Seek(); void C_DECL A_MummySoul(); void C_DECL A_NoBlocking(); void C_DECL A_Pain(); void C_DECL A_PhoenixPuff(); void C_DECL A_PodPain(); void C_DECL A_RainImpact(); void C_DECL A_Raise(); void C_DECL A_ReFire(); void C_DECL A_RemovePod(); void C_DECL A_RestoreArtifact(); void C_DECL A_RestoreSpecialThing1(); void C_DECL A_RestoreSpecialThing2(); void C_DECL A_Scream(); void C_DECL A_ShutdownPhoenixPL2(); void C_DECL A_SkullPop(); void C_DECL A_SkullRodPL2Seek(); void C_DECL A_SkullRodStorm(); void C_DECL A_SnakeAttack(); void C_DECL A_SnakeAttack2(); void C_DECL A_Sor1Chase(); void C_DECL A_Sor1Pain(); void C_DECL A_Sor2DthInit(); void C_DECL A_Sor2DthLoop(); void C_DECL A_SorcererRise(); void C_DECL A_SorDBon(); void C_DECL A_SorDExp(); void C_DECL A_SorDSph(); void C_DECL A_SorRise(); void C_DECL A_SorSightSnd(); void C_DECL A_SorZap(); void C_DECL A_SpawnRippers(); void C_DECL A_SpawnTeleGlitter(); void C_DECL A_SpawnTeleGlitter2(); void C_DECL A_Srcr1Attack(); void C_DECL A_Srcr2Attack(); void C_DECL A_Srcr2Decide(); void C_DECL A_StaffAttackPL1(); void C_DECL A_StaffAttackPL2(); void C_DECL A_UnHideThing(); void C_DECL A_VolcanoBlast(); void C_DECL A_VolcanoSet(); void C_DECL A_VolcBallImpact(); void C_DECL A_WeaponReady(); void C_DECL A_WhirlwindSeek(); void C_DECL A_WizAtk1(); void C_DECL A_WizAtk2(); void C_DECL A_WizAtk3(); // Inventory: void C_DECL A_FireBomb(); void C_DECL A_TombOfPower(); void C_DECL A_Egg(); void C_DECL A_Wings(); void C_DECL A_Teleport(); void C_DECL A_Torch(); void C_DECL A_Health(); void C_DECL A_SuperHealth(); void C_DECL A_Invisibility(); void C_DECL A_Invulnerability(); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/doomdef.h0000644000175000017500000002150311357170242023555 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomdef.h: * * Internally used data structures for virtually everything, * key definitions, lots of other stuff. */ #ifndef __DOOMDEF_H__ #define __DOOMDEF_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #ifdef WIN32 #pragma warning(disable:4244) #endif #include #include #include "doomsday.h" #include "dd_api.h" #include "version.h" #include "info.h" #define Set DD_SetInteger #define Get DD_GetInteger #define CONFIGFILE GAMENAMETEXT".cfg" #define DEFSFILE GAMENAMETEXT"\\"GAMENAMETEXT".ded" #define DATAPATH "}data\\"GAMENAMETEXT"\\" #define STARTUPWAD "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".wad" #define STARTUPPK3 "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".pk3" // Verbose messages. #define VERBOSE(code) { if(verbose >= 1) { code; } } #define VERBOSE2(code) { if(verbose >= 2) { code; } } extern game_import_t gi; extern game_export_t gx; // // Global parameters/defines. // #define MOBJINFO (*gi.mobjInfo) #define STATES (*gi.states) #define VALIDCOUNT (*gi.validCount) // Game mode handling - identify IWAD version to handle IWAD dependend // animations etc. typedef enum { shareware, // shareware, E1, M9 registered, // DOOM 1 registered, E3, M27 extended, // episodes 4 and 5 present indetermined, // Well, no IWAD found. NUM_GAME_MODES } gamemode_t; // Game mode bits for the above. #define GM_SHAREWARE 0x1 // shareware, E1, M9 #define GM_REGISTERED 0x2 // registered episodes #define GM_EXTENDED 0x4 // episodes 4 and 5 present #define GM_INDETERMINED 0x8 // Well, no IWAD found. #define GM_ANY (GM_SHAREWARE|GM_REGISTERED|GM_EXTENDED) #define GM_NOTSHAREWARE (GM_REGISTERED|GM_EXTENDED) #define SCREENWIDTH 320 #define SCREENHEIGHT 200 #define SCREEN_MUL 1 // The maximum number of players, multiplayer/networking. #define MAXPLAYERS 16 // Playsim, core timing rate in cycles per second. #define TICRATE 35 #define TICSPERSEC 35 /** * Player Classes */ typedef enum { PCLASS_PLAYER, PCLASS_CHICKEN, NUM_PLAYER_CLASSES } playerclass_t; #define PCLASS_INFO(class) (&classInfo[class]) typedef struct classinfo_s{ char* niceName; boolean userSelectable; mobjtype_t mobjType; int normalState; int runState; int attackState; int attackEndState; int maxArmor; fixed_t maxMove; fixed_t forwardMove[2]; // walk, run fixed_t sideMove[2]; // walk, run int moveMul; // multiplier for above int turnSpeed[3]; // [normal, speed, initial] int jumpTics; // wait inbetween jumps int failUseSound; // sound played when a use fails. } classinfo_t; extern classinfo_t classInfo[NUM_PLAYER_CLASSES]; /** * Game state (hi-level). * * The current state of the game: whether we are playing, gazing at the * intermission screen, the game final animation, or a demo. */ typedef enum { GS_STARTUP, GS_MAP, GS_INTERMISSION, GS_FINALE, GS_WAITING, GS_INFINE, NUM_GAME_STATES } gamestate_t; /** * Difficulty/skill settings/filters. */ typedef enum { SM_BABY, SM_EASY, SM_MEDIUM, SM_HARD, SM_NIGHTMARE, NUM_SKILL_MODES } skillmode_t; /** * Keys (as in, keys to lockables). */ typedef enum { KT_YELLOW, KT_GREEN, KT_BLUE, NUM_KEY_TYPES } keytype_t; /** * Weapon ids. * * The defined weapons, including a marker indicating user has not changed * weapon. */ typedef enum { WT_FIRST, // staff / beak WT_SECOND, // goldwand / beak WT_THIRD, // crossbow / beak WT_FOURTH, // blaster / beak WT_FIFTH, // skullrod / beak WT_SIXTH, // phoenixrod / beak WT_SEVENTH, // mace / beak WT_EIGHTH, // gauntlets / beak NUM_WEAPON_TYPES, WT_NOCHANGE // No pending weapon change. } weapontype_t; #define NUMWEAPLEVELS 2 // Number of weapon power levels. /** * Ammunition types. */ typedef enum { AT_CRYSTAL, AT_ARROW, AT_ORB, AT_RUNE, AT_FIREORB, AT_MSPHERE, NUM_AMMO_TYPES, AT_NOAMMO // Takes no ammo, used for staff, gauntlets. } ammotype_t; #define AMMO_GWND_WIMPY 10 #define AMMO_GWND_HEFTY 50 #define AMMO_CBOW_WIMPY 5 #define AMMO_CBOW_HEFTY 20 #define AMMO_BLSR_WIMPY 10 #define AMMO_BLSR_HEFTY 25 #define AMMO_SKRD_WIMPY 20 #define AMMO_SKRD_HEFTY 100 #define AMMO_PHRD_WIMPY 1 #define AMMO_PHRD_HEFTY 10 #define AMMO_MACE_WIMPY 20 #define AMMO_MACE_HEFTY 100 /** * Powers, bestowable upon players only. */ typedef enum { PT_NONE, PT_INVULNERABILITY, PT_INVISIBILITY, PT_ALLMAP, PT_INFRARED, PT_WEAPONLEVEL2, // Temporarily boost all owned weapons to level 2. PT_FLIGHT, PT_SHIELD, PT_HEALTH2, NUM_POWER_TYPES } powertype_t; #define INVULNTICS (30*TICRATE) #define INVISTICS (60*TICRATE) #define INFRATICS (120*TICRATE) #define IRONTICS (60*TICRATE) #define WPNLEV2TICS (40*TICRATE) #define FLIGHTTICS (60*TICRATE) #define CHICKENTICS (40*TICRATE) /** * Inventory Item Types: */ typedef enum { IIT_NONE = 0, IIT_FIRST = 1, IIT_INVULNERABILITY = IIT_FIRST, IIT_INVISIBILITY, IIT_HEALTH, IIT_SUPERHEALTH, IIT_TOMBOFPOWER, IIT_TORCH, IIT_FIREBOMB, IIT_EGG, IIT_FLY, IIT_TELEPORT, NUM_INVENTORYITEM_TYPES } inventoryitemtype_t; #define MAXINVITEMCOUNT 16 #define BLINKTHRESHOLD (4*TICRATE) enum { VX, VY, VZ }; // Vertex indices. enum { CR, CG, CB, CA }; // Color indices. #define IS_SERVER Get(DD_SERVER) #define IS_CLIENT Get(DD_CLIENT) #define IS_NETGAME Get(DD_NETGAME) #define IS_DEDICATED Get(DD_DEDICATED) #define CVAR(typ, x) (*(typ*)Con_GetVariable(x)->ptr) #define SFXVOLUME (Get(DD_SFX_VOLUME)/17) #define MUSICVOLUME (Get(DD_MUSIC_VOLUME)/17) void G_IdentifyVersion(void); int G_GetInteger(int id); void *G_GetVariable(int id); // Most damage defined using HITDICE #define HITDICE(a) ((1+(P_Random()&7))*a) #define SBARHEIGHT (42) // status bar height at bottom of screen #define TELEFOGHEIGHT (32) #define MAXEVENTS (64) #define DEFAULT_PLAYER_VIEWHEIGHT (41) extern fixed_t finesine[5 * FINEANGLES / 4]; extern fixed_t *finecosine; //---------- //BASE LEVEL //---------- void D_DoomMain(void); void IncThermo(void); void InitThermo(int max); void tprintf(char *string, int initflag); // called by IO functions when input is detected void NetUpdate(void); // create any new ticcmds and broadcast to other players void D_QuitNetGame(void); //----- //PLAY //----- // called by C_Ticker // can call G_PlayerExited // carries out all thinking of monsters and players void P_SetupMap(uint episode, uint map, int playermask, skillmode_t skill); // called by W_Ticker void P_Init(void); // called by startup code void R_InitTranslationTables(void); //---- //MISC //---- void strcatQuoted(char *dest, char *src); // returns true if the episode/map combo is valid for the current // game configuration void M_ForceUppercase(char *text); int M_DrawText(int x, int y, boolean direct, char *string); //----------------- // MENU (MN_menu.c) //----------------- void MN_ActivateMenu(void); void MN_DeactivateMenu(void); // Drawing text in the Current State. void MN_DrTextA_CS(char *text, int x, int y); void MN_DrTextAGreen_CS(char *text, int x, int y); void MN_DrTextB_CS(char *text, int x, int y); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/r_local.h0000644000175000017500000000251411357170242023554 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_local.h: */ #ifndef __R_LOCAL_H__ #define __R_LOCAL_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #define PI 3.141592657 // // lighting constants // #define NUMCOLORMAPS 32 // number of diminishing #define INVERSECOLORMAP 32 extern int centerx, centery; extern int flyheight; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_maputl.h0000644000175000017500000000223511357170242023762 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputl.h: Movement/collision utility functions jHeretic - specific. */ #ifndef __P_MAPUTL_H__ #define __P_MAPUTL_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "p_mobj.h" void P_ApplyTorque(mobj_t* mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/doomdata.h0000644000175000017500000000432411357170242023732 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomdata.h: Thing and linedef attributes */ #ifndef __DOOMDATA_H__ #define __DOOMDATA_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif // Base plane ids. enum { PLN_FLOOR, PLN_CEILING }; // // LineDef attributes. // // Blocks monsters only. #define ML_BLOCKMONSTERS 2 // In AutoMap: don't map as two sided: IT'S A SECRET! #define ML_SECRET 32 // Sound rendering: don't let sound cross two of these. #define ML_SOUNDBLOCK 64 // Don't draw on the automap at all. #define ML_DONTDRAW 128 // Set if already seen, thus drawn in automap. #define ML_MAPPED 256 // Allows a USE action to pass through a line with a special #define ML_PASSUSE 512 //If set allows any mobj to trigger the line's special #define ML_ALLTRIGGER 1024 // If set ALL flags NOT in DOOM v1.9 will be zeroed upon map load. // ML_BLOCKING -> ML_MAPPED inc will persist. #define ML_INVALID 2048 #define VALIDMASK 0x000001ff // Special activation types #define SPAC_CROSS 0 // when player crosses line #define SPAC_USE 1 // when player uses line #define SPAC_IMPACT 3 // when projectile hits line #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/p_inter.h0000644000175000017500000000221411357170242023576 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.h: Handling interactions (i.e., collisions). */ #ifndef __P_INTER_H__ #define __P_INTER_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif boolean P_GiveArmor(player_t* plr, int type, int points); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_config.h0000644000175000017500000001703011357170242023714 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_config.h: jHeretic configuration. * * Global settings. Most of these are console variables. */ #ifndef __JHERETIC_CONFIG_H__ #define __JHERETIC_CONFIG_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomdef.h" enum { HUD_AMMO, HUD_ARMOR, HUD_KEYS, HUD_HEALTH, HUD_CURRENTITEM }; // Hud Unhide Events (the hud will unhide on these events if enabled). typedef enum { HUE_FORCE = -1, HUE_ON_DAMAGE, HUE_ON_PICKUP_HEALTH, HUE_ON_PICKUP_ARMOR, HUE_ON_PICKUP_POWER, HUE_ON_PICKUP_WEAPON, HUE_ON_PICKUP_AMMO, HUE_ON_PICKUP_KEY, HUE_ON_PICKUP_INVITEM, NUMHUDUNHIDEEVENTS } hueevent_t; // WARNING: Do not use the boolean type. Its size can be either 1 or 4 bytes // depending on build settings. typedef struct jheretic_config_s { float playerMoveSpeed; int dclickUse; int useMLook; // Mouse look (mouse Y => viewpitch) int useJLook; // Joy look (joy Y => viewpitch) int alwaysRun; // Always run. int noAutoAim; // No auto-aiming? int jLookDeltaMode; int lookSpring; float lookSpeed; float turnSpeed; byte povLookAround; int jumpEnabled; float jumpPower; int airborneMovement; byte setSizeNeeded; int setBlocks; int screenBlocks; byte slidingCorpses; int echoMsg; float menuScale; int menuEffects; int hudFog; float menuGlitter; float menuShadow; byte menuSlam; byte menuHotkeys; byte askQuickSaveLoad; float flashColor[3]; int flashSpeed; byte turningSkull; byte hudShown[6]; // HUD data visibility. float hudScale; // How to scale HUD data? float hudColor[4]; float hudIconAlpha; float hudTimer; // Number of seconds until the hud/statusbar auto-hides. byte hudUnHide[NUMHUDUNHIDEEVENTS]; // when the hud/statusbar unhides. byte usePatchReplacement; byte moveCheckZ; // if true, mobjs can move over/under each other. byte weaponAutoSwitch; byte noWeaponAutoSwitchIfFiring; byte ammoAutoSwitch; int weaponOrder[NUM_WEAPON_TYPES]; byte weaponNextMode; // if true use the weaponOrder for next/previous. byte secretMsg; float filterStrength; int plrViewHeight; byte mapTitle, hideIWADAuthor; float menuColor[3]; float menuColor2[3]; byte noCoopDamage; byte noTeamDamage; byte respawnMonstersNightmare; int statusbarScale; float statusbarOpacity; float statusbarCounterAlpha; /** * Compatibility options. * \todo Put these into an array so we can use a bit array to change * multiple options based on a compatibility mode (ala PrBoom). */ byte monstersStuckInDoors; byte avoidDropoffs; byte moveBlock; // Dont handle large negative movement in P_TryMove. byte wallRunNorthOnly; // If handle large make exception for wallrunning byte fallOff; // Objects fall under their own weight. byte fixFloorFire; // Fix Heretic bug; explode Maulotaur floor fire when feetclipped. byte fixPlaneScrollMaterialsEastOnly; // Fix Heretic bug; plane materials would only scroll east. byte counterCheat; float counterCheatScale; // Automap stuff. /* int automapPos; float automapWidth; float automapHeight;*/ float automapMobj[3]; float automapL0[3]; float automapL1[3]; float automapL2[3]; float automapL3[3]; float automapBack[3]; float automapOpacity; float automapLineAlpha; byte automapRotate; int automapHudDisplay; int automapCustomColors; byte automapShowDoors; float automapDoorGlow; byte automapBabyKeys; float automapZoomSpeed; float automapPanSpeed; byte automapPanResetOnOpen; float automapOpenSeconds; int msgCount; float msgScale; float msgUptime; int msgBlink; int msgAlign; byte msgShow; float msgColor[3]; char* chatMacros[10]; byte chatBeep; int corpseTime; float bobWeapon, bobView; byte bobWeaponLower; int cameraNoClip; // Crosshair. int xhair; float xhairSize; byte xhairVitality; float xhairColor[4]; // Network. byte netDeathmatch; byte netMobDamageModifier; // multiplier for non-player mobj damage byte netMobHealthModifier; // health modifier for non-player mobjs int netGravity; // multiplayer custom gravity byte netNoMaxZRadiusAttack; // radius attacks are infinitely tall byte netNoMaxZMonsterMeleeAttack; // melee attacks are infinitely tall byte netNoMonsters; byte netRespawn; byte netJumping; byte netEpisode; byte netMap; byte netSkill; byte netSlot; byte netColor; playerclass_t playerClass[MAXPLAYERS]; int playerColor[MAXPLAYERS]; // jHeretic specific int ringFilter; float inventoryTimer; // Number of seconds until the invetory auto-hides. byte inventoryWrap; byte inventoryUseNext; byte inventoryUseImmediate; int inventorySlotMaxVis; byte inventorySlotShowEmpty; byte inventorySelectMode; int tomeCounter, tomeSound; byte fastMonsters; } game_config_t; extern game_config_t cfg; // in g_game.c int GetDefInt(char *def, int *returned_value); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_console.h0000644000175000017500000000240411357170242024110 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_console.h: Console stuff - jHeretic specific. */ #ifndef __JHERETIC_CONSOLE_H__ #define __JHERETIC_CONSOLE_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif void G_ConsoleRegistration(); void H_ConsoleBg(int *width, int *height); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_items.h0000644000175000017500000000441111357170242023567 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_items.h: Items, key cards/weapons/ammunition... */ #ifndef __JHERETIC_ITEMS_H__ #define __JHERETIC_ITEMS_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomdef.h" #define WEAPON_INFO(weaponnum, pclass, fmode) ( \ &weaponInfo[(weaponnum)][(pclass)].mode[(fmode)]) typedef enum { WSN_UP, WSN_DOWN, WSN_READY, WSN_ATTACK, WSN_ATTACK_HOLD, WSN_FLASH, NUM_WEAPON_STATE_NAMES } weaponstatename_t; typedef struct { int gameModeBits; // Game modes, weapon is available in. int ammoType[NUM_AMMO_TYPES]; // required ammo types. int perShot[NUM_AMMO_TYPES]; // Ammo used per shot of each type. boolean autoFire; // @c true = fire when raised if fire held. int states[NUM_WEAPON_STATE_NAMES]; int raiseSound; // Sound played when weapon is raised. int readySound; // Sound played WHILE weapon is readyied. int staticSwitch; // Weapon is not lowered during switch. } weaponmodeinfo_t; // Weapon info: sprite frames, ammunition use. typedef struct { weaponmodeinfo_t mode[NUMWEAPLEVELS]; } weaponinfo_t; extern weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES]; void P_InitWeaponInfo(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/h_main.h0000644000175000017500000000357011357170242023377 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h_main.h: */ #ifndef __JHERETIC_MAIN_H__ #define __JHERETIC_MAIN_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomdef.h" extern int verbose; extern boolean devParm; extern boolean noMonstersParm; extern boolean respawnParm; extern boolean turboParm; extern boolean fastParm; extern float turboMul; extern skillmode_t startSkill; extern int startEpisode; extern int startMap; extern boolean autoStart; extern gamemode_t gameMode; extern int gameModeBits; extern char gameModeString[]; extern boolean monsterInfight; extern const float defFontRGB[]; extern const float defFontRGB2[]; extern char *borderLumps[]; extern char *wadFiles[]; extern char *baseDefault; extern char exrnWADs[]; extern char exrnWADs2[]; void G_Shutdown(void); void G_EndFrame(void); boolean G_SetGameMode(gamemode_t mode); void G_DetectIWADs(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/in_lude.h0000644000175000017500000000311011357170242023551 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * in_lude.h: Intermission/stat screens */ #ifndef __IN_LUDE_H__ #define __IN_LUDE_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "h_player.h" extern boolean intermission; extern int interState; extern int interTime; void IN_Init(wbstartstruct_t* wbstartstruct); void IN_Stop(void); void IN_Ticker(void); void IN_Drawer(void); void IN_WaitStop(void); void IN_LoadPics(void); void IN_UnloadPics(void); void IN_CheckForSkip(void); void IN_InitStats(void); void IN_InitDeathmatchStats(void); void IN_InitNetgameStats(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/r_data.h0000644000175000017500000000217711357170242023400 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_data.h: */ #ifndef __R_DATA_H__ #define __R_DATA_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "r_defs.h" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/tables.h0000644000175000017500000000420711357170242023414 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * tables.h: Lookup tables. */ #ifndef __TABLES_H__ #define __TABLES_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomsday.h" #define PI 3.141592657 //#include "m_fixed.h" #define FINEANGLES 8192 #define FINEMASK (FINEANGLES-1) // 0x100000000 to 0x2000 #define ANGLETOFINESHIFT 19 // Effective size is 10240. extern fixed_t finesine[5 * FINEANGLES / 4]; // Re-use data, is just PI/2 pahse shift. extern fixed_t *finecosine; // Effective size is 4096. extern fixed_t finetangent[FINEANGLES / 2]; // Binary Angle Measument, BAM. #define ANG45 0x20000000 #define ANG90 0x40000000 #define ANG180 0x80000000 #define ANG270 0xc0000000 #define SLOPERANGE 2048 #define SLOPEBITS 11 #define DBITS (FRACBITS-SLOPEBITS) // Effective size is 2049; // The +1 size is to handle the case when x==y without additional checking. extern angle_t tantoangle[SLOPERANGE + 1]; // Utility function, called by R_PointToAngle. int SlopeDiv(unsigned num, unsigned den); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/g_game.h0000644000175000017500000000631411357170242023362 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_game.h: Top-level (common) game routines jHeretic - specific. */ #ifndef __G_GAME_H__ #define __G_GAME_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "doomdef.h" #include "h_event.h" #include "h_player.h" extern boolean deathmatch; extern boolean respawnMonsters; extern boolean userGame; extern player_t players[MAXPLAYERS]; extern skillmode_t gameSkill; extern uint gameEpisode; extern uint gameMap; extern uint nextMap; extern boolean secretExit; extern int mapStartTic; extern int totalKills, totalItems, totalSecret; extern wbstartstruct_t wmInfo; extern int gsvMapMusic; void G_Register(void); void G_CommonPreInit(void); void G_CommonPostInit(void); void R_InitRefresh(void); void G_DeathMatchSpawnPlayer(int playernum); void G_PrintMapList(void); boolean G_ValidateMap(uint* episode, uint* map); uint G_GetMapNumber(uint episode, uint map); void G_InitNew(skillmode_t skill, uint episode, uint map); // Can be called by the startup code or Hu_MenuResponder. // A normal game starts at map 1, but a warp test can start elsewhere. void G_DeferedInitNew(skillmode_t skill, uint episode, uint map); void G_DeferedPlayDemo(char* demo); // Can be called by the startup code or Hu_MenuResponder. // Calls P_SetupMap or W_EnterWorld. void G_LoadGame(const char* name); void G_DoLoadGame(void); // Called by Hu_MenuResponder. void G_SaveGame(int slot, const char* description); void G_StopDemo(void); void G_DemoEnds(void); void G_DemoAborted(void); void G_DoReborn(int playernum); void G_PlayerReborn(int player); void G_LeaveMap(uint newMap, uint entryPoint, boolean secretExit); uint G_GetNextMap(uint episode, uint map, boolean secretExit); boolean P_MapExists(uint episode, uint map); void G_WorldDone(void); void G_Ticker(timespan_t ticLength); boolean G_Responder(event_t* ev); void G_ScreenShot(void); void P_GetMapLumpName(uint episode, uint map, char* lumpName); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/include/m_menu.h0000644000175000017500000000252111357170242023417 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_menu.h: Menu widget stuff, episode selection and such. */ #ifndef __M_MENU_H__ #define __M_MENU_H__ #ifndef __JHERETIC__ # error "Using jHeretic headers without __JHERETIC__" #endif #include "hu_stuff.h" #include "h_event.h" void M_LoadData(void); boolean MN_CurrentMenuHasBackground(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/0000755000175000017500000000000011523516204021261 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/special.ded0000644000175000017500000000240211357170242023360 0ustar keeskees# jHeretic: Special Effects (for both sprites and models) Header { Version = 5; } # Sparks from Gold Wand hits. Generator { State = "GWANDPUFF1_1"; Flags = "gnf_blend"; Particles = 10; Speed = 5; Speed rnd = .7; Spawn age = 2; Max age = 45; Spawn rate = 5; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Radius = 8; Tics = 4; Rnd = .1; Color { 1 1 1 1 }; Gravity = 0.1; Resistance = 0.02; Bounce = 0.5; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Radius = 1.5; Tics = 41; Rnd = .4; Color { 1 .7 0 .8 }; Gravity = 0.1; Resistance = 0.02; Bounce = 0.5; }; Stage { Type = "pt_point"; Color { 1 0 0 0 }; }; } #> Generator { Mobj = "BARREL"; Flags = "gnf_static gnf_blend"; # Room for 10 sources. Particles = 200; Center { 0 0 50 }; Speed = 5; Speed rnd = 1; Spawn radius = 10; Spawn age = -1; Max age = -1; Spawn rate = 1; Vector { 0 0 1 }; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Radius = 30; Tics = 19; Rnd = 0.3; Color { 1 .9 .4 .5 }; Gravity = -0.3; Resistance = 0.1; }; Stage { Type = "pt_point"; Radius = 10; Color { 1 .1 .1 .1 }; }; } <#deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/skies.ded0000644000175000017500000000061111357170242023056 0ustar keeskees# # jHeretic: Skies # Sky { ID = "sky1"; Height = 0.6; Horizon offset = -0.105; Layer 1 { Flags = enable; Texture = "SKY1"; }; } # The rest of the file is skipped if Heretic Shareware. SkipIf heretic-share; Copy Sky { ID = "sky2"; Layer 1 { Texture = "SKY2"; }; } Copy Sky { ID = "sky3"; Layer 1 { Texture = "SKY3"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/flags.ded0000644000175000017500000000475111357170242023045 0ustar keeskees# jHeretic: Flags # Mobj flags: Flag { ID = "mf_special"; Value = 0x1; } Flag { ID = "mf_solid"; Value = 0x2; } Flag { ID = "mf_shootable"; Value = 0x4; } Flag { ID = "mf_nosector"; Value = 0x8; } Flag { ID = "mf_noblockmap"; Value = 0x10; } Flag { ID = "mf_ambush"; Value = 0x20; } Flag { ID = "mf_justhit"; Value = 0x40; } Flag { ID = "mf_justattacked"; Value = 0x80; } Flag { ID = "mf_spawnceiling"; Value = 0x100; } Flag { ID = "mf_nogravity"; Value = 0x200; } Flag { ID = "mf_dropoff"; Value = 0x400; } Flag { ID = "mf_pickup"; Value = 0x800; } Flag { ID = "mf_noclip"; Value = 0x1000; } Flag { ID = "mf_float"; Value = 0x4000; } Flag { ID = "mf_teleport"; Value = 0x8000; } Flag { ID = "mf_missile"; Value = 0x10000; } Flag { ID = "mf_dropped"; Value = 0x20000; } Flag { ID = "mf_shadow"; Value = 0x40000; } Flag { ID = "mf_noblood"; Value = 0x80000; } Flag { ID = "mf_corpse"; Value = 0x100000; } Flag { ID = "mf_infloat"; Value = 0x200000; } Flag { ID = "mf_countkill"; Value = 0x400000; } Flag { ID = "mf_countitem"; Value = 0x800000; } Flag { ID = "mf_skullfly"; Value = 0x1000000; } Flag { ID = "mf_notdmatch"; Value = 0x2000000; } Flag { ID = "mf_translation"; Value = 0xC000000; } Flag { ID = "mf_transshift"; Value = 0x1A; } Flag { ID = "mf_local"; Value = 0x10000000; } Flag { ID = "mf_brightshadow"; Value = 0x20000000; } Flag { ID = "mf_brightexplode"; Value = 0x40000000; } Flag { ID = "mf_viewalign"; Value = 0x80000000; } # Mobj flags2: Flag { ID = "mf2_lograv"; Value = 0x1; } Flag { ID = "mf2_windthrust"; Value = 0x2; } Flag { ID = "mf2_floorbounce"; Value = 0x4; } Flag { ID = "mf2_thrughost"; Value = 0x8; } Flag { ID = "mf2_fly"; Value = 0x10; } Flag { ID = "mf2_footclip"; Value = 0x20; } Flag { ID = "mf2_spawnfloat"; Value = 0x40; } Flag { ID = "mf2_noteleport"; Value = 0x80; } Flag { ID = "mf2_rip"; Value = 0x100; } Flag { ID = "mf2_pushable"; Value = 0x200; } Flag { ID = "mf2_slide"; Value = 0x400; } Flag { ID = "mf2_alwayslit"; Value = 0x800; } Flag { ID = "mf2_passmobj"; Value = 0x1000; } Flag { ID = "mf2_cannotpush"; Value = 0x2000; } Flag { ID = "mf2_radiusattacknomaxz"; Value = 0x4000; } Flag { ID = "mf2_boss"; Value = 0x8000; } Flag { ID = "mf2_firedamage"; Value = 0x10000; } Flag { ID = "mf2_nodmgthrust"; Value = 0x20000; } Flag { ID = "mf2_telestomp"; Value = 0x40000; } Flag { ID = "mf2_floatbob"; Value = 0x80000; } Flag { ID = "mf2_dontdraw"; Value = 0x100000; } # Mobj flags3: Flag { ID = "mf3_noinfight"; Value = 0x1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/maps.ded0000644000175000017500000001124411357170242022704 0ustar keeskees# # jHeretic: Maps # Header { Version = 5; } # The default definition, used for any maps without a map info definition. Map Info { ID = "*"; Author = "Unknown"; Music = "e1m1"; Gravity = 1; Sky = "sky1"; } Map Info { ID = "E1M1"; Name = "HUSTR_E1M1"; Author = "Raven Software"; Music = "e1m1"; Gravity = 1; Sky = "sky1"; } Copy Map Info { ID = "E1M2"; Name = "HUSTR_E1M2"; Music = "e1m2"; } Copy Map Info { ID = "E1M3"; Name = "HUSTR_E1M3"; Music = "e1m3"; } Copy Map Info { ID = "E1M4"; Name = "HUSTR_E1M4"; Music = "e1m4"; } Copy Map Info { ID = "E1M5"; Name = "HUSTR_E1M5"; Music = "e1m5"; } Copy Map Info { ID = "E1M6"; Name = "HUSTR_E1M6"; Music = "e1m6"; } Copy Map Info { ID = "E1M7"; Name = "HUSTR_E1M7"; Music = "e1m7"; } Copy Map Info { ID = "E1M9"; Name = "HUSTR_E1M9"; Music = "e1m9"; } Copy Map Info { ID = "E1M8"; Name = "HUSTR_E1M8"; Music = "e1m8"; Flags = nointermission; } # The rest of the file is skipped if Heretic Shareware. SkipIf heretic-share; Map Info { ID = "E2M1"; Name = "HUSTR_E2M1"; Author = "Raven Software"; Music = "e2m1"; Gravity = 1; Sky = "sky2"; } Copy Map Info { ID = "E2M2"; Name = "HUSTR_E2M2"; Music = "e2m2"; } Copy Map Info { ID = "E2M3"; Name = "HUSTR_E2M3"; Music = "e2m3"; } Copy Map Info { ID = "E2M4"; Name = "HUSTR_E2M4"; Music = "e2m4"; } Copy Map Info { ID = "E2M5"; Name = "HUSTR_E2M5"; Music = "e1m4"; } Copy Map Info { ID = "E2M6"; Name = "HUSTR_E2M6"; Music = "e2m6"; } Copy Map Info { ID = "E2M7"; Name = "HUSTR_E2M7"; Music = "e2m7"; } Copy Map Info { ID = "E2M9"; Name = "HUSTR_E2M9"; Music = "e2m9"; } Copy Map Info { ID = "E2M8"; Name = "HUSTR_E2M8"; Music = "e2m8"; Flags = nointermission; } Map Info { ID = "E3M1"; Name = "HUSTR_E3M1"; Author = "Raven Software"; Music = "e1m1"; Gravity = 1; Sky = "sky3"; } Copy Map Info { ID = "E3M2"; Name = "HUSTR_E3M2"; Music = "e3m2"; } Copy Map Info { ID = "E3M3"; Name = "HUSTR_E3M3"; Music = "e3m3"; } Copy Map Info { ID = "E3M4"; Name = "HUSTR_E3M4"; Music = "e1m6"; } Copy Map Info { ID = "E3M5"; Name = "HUSTR_E3M5"; Music = "e1m3"; } Copy Map Info { ID = "E3M6"; Name = "HUSTR_E3M6"; Music = "e1m2"; } Copy Map Info { ID = "E3M7"; Name = "HUSTR_E3M7"; Music = "e1m5"; } Copy Map Info { ID = "E3M9"; Name = "HUSTR_E3M9"; Music = "e2m6"; } Copy Map Info { ID = "E3M8"; Name = "HUSTR_E3M8"; Music = "e1m9"; Flags = nointermission; } # The rest of the file is skipped if not Heretic Extended. SkipIf Not heretic-ext; Map Info { ID = "E4M1"; Name = "HUSTR_E4M1"; Author = "Raven Software"; Music = "e1m6"; Gravity = 1; Sky = "sky1"; } Copy Map Info { ID = "E4M2"; Name = "HUSTR_E4M2"; Music = "e1m2"; } Copy Map Info { ID = "E4M3"; Name = "HUSTR_E4M3"; Music = "e1m3"; } Copy Map Info { ID = "E4M4"; Name = "HUSTR_E4M4"; Music = "e1m4"; } Copy Map Info { ID = "E4M5"; Name = "HUSTR_E4M5"; Music = "e1m5"; } Copy Map Info { ID = "E4M6"; Name = "HUSTR_E4M6"; Music = "e1m1"; } Copy Map Info { ID = "E4M7"; Name = "HUSTR_E4M7"; Music = "e1m7"; } Copy Map Info { ID = "E4M9"; Name = "HUSTR_E4M9"; Music = "e1m9"; } Copy Map Info { ID = "E4M8"; Name = "HUSTR_E4M8"; Music = "e1m8"; Flags = nointermission; } Map Info { ID = "E5M1"; Name = "HUSTR_E5M1"; Author = "Raven Software"; Music = "e2m1"; Gravity = 1; Sky = "sky3"; } Copy Map Info { ID = "E5M2"; Name = "HUSTR_E5M2"; Music = "e2m2"; } Copy Map Info { ID = "E5M3"; Name = "HUSTR_E5M3"; Music = "e2m3"; } Copy Map Info { ID = "E5M4"; Name = "HUSTR_E5M4"; Music = "e2m4"; } Copy Map Info { ID = "E5M5"; Name = "HUSTR_E5M5"; Music = "e1m4"; } Copy Map Info { ID = "E5M6"; Name = "HUSTR_E5M6"; Music = "e2m6"; } Copy Map Info { ID = "E5M7"; Name = "HUSTR_E5M7"; Music = "e2m7"; } Copy Map Info { ID = "E5M9"; Name = "HUSTR_E5M9"; Music = "e2m9"; } Copy Map Info { ID = "E5M8"; Name = "HUSTR_E5M8"; Music = "e2m8"; Flags = nointermission; } Map Info { ID = "E6M1"; Name = "HUSTR_E6M1"; Author = "Raven Software"; Music = "e3m2"; Gravity = 1; Sky = "sky1"; } Copy Map Info { ID = "E6M2"; Name = "HUSTR_E6M2"; Music = "e3m3"; } Copy Map Info { ID = "E6M3"; Name = "HUSTR_E6M3"; Music = "e1m6"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/anim.ded0000644000175000017500000000123111357170242022663 0ustar keeskees# jHeretic: Additional Animation Sequences # # Heretic has predefined texture animation sequences. # In order to remain compatible with existing WADs, jHeretic builds # animations from these predefined sequences and creates texture # animation groups for them. The flags "tgf_smooth" and # "tgf_first_only" are set for each group. # # Additional sequences can be defined using Group definitions. Header { Version = 6; } # # Precache groups. # Group { Flags = precache; Texture { ID = "SW1OFF"; Tics = 0; }; Texture { ID = "SW1ON"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW2OFF"; Tics = 0; }; Texture { ID = "SW2ON"; Tics = 0; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/materials.ded0000644000175000017500000000121011357170242023715 0ustar keeskees# jHeretic: Material Enhancements # # Patch the Material definitions created automatically # by the engine, adding new effects to them. Header { Version = 6; } # # Skymasked flats: # Material { ID = "F_SKY1"; Namespace = flats; Flags = skymask; } # # Glowing flats: # Material { ID = "FLATHUH1"; Namespace = flats; Flags = glow; } * Material { ID = "FLATHUH2"; } * Material { ID = "FLATHUH3"; } * Material { ID = "FLATHUH4"; } # # Glowing textures: # Material { ID = "LAVAFL1"; Namespace = textures; Flags = glow; } * Material { ID = "LAVAFL2"; } * Material { ID = "LAVAFL3"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/audio.ded0000644000175000017500000003752111357170242023053 0ustar keeskees# jHeretic: Audio Header { Version = 5; } #####====--- MUSIC ---====##### Music { ID = "e1m1"; Lump = "MUS_E1M1"; } Music { ID = "e1m2"; Lump = "MUS_E1M2"; } Music { ID = "e1m3"; Lump = "MUS_E1M3"; } Music { ID = "e1m4"; Lump = "MUS_E1M4"; } Music { ID = "e1m5"; Lump = "MUS_E1M5"; } Music { ID = "e1m6"; Lump = "MUS_E1M6"; } Music { ID = "e1m7"; Lump = "MUS_E1M7"; } Music { ID = "e1m8"; Lump = "MUS_E1M8"; } Music { ID = "e1m9"; Lump = "MUS_E1M9"; } Music { ID = "e2m1"; Lump = "MUS_E2M1"; } Music { ID = "e2m2"; Lump = "MUS_E2M2"; } Music { ID = "e2m3"; Lump = "MUS_E2M3"; } Music { ID = "e2m4"; Lump = "MUS_E2M4"; } Music { ID = "e2m6"; Lump = "MUS_E2M6"; } Music { ID = "e2m7"; Lump = "MUS_E2M7"; } Music { ID = "e2m8"; Lump = "MUS_E2M8"; } Music { ID = "e2m9"; Lump = "MUS_E2M9"; } Music { ID = "e3m2"; Lump = "MUS_E3M2"; } Music { ID = "e3m3"; Lump = "MUS_E3M3"; } Music { ID = "titl"; Lump = "MUS_TITL"; } Music { ID = "intr"; Lump = "MUS_INTR"; } Music { ID = "cptd"; Lump = "MUS_CPTD"; } #####====--- SOUND EFFECTS ---====##### Sound { ID = "None"; } Sound { ID = "gldhit"; Lump = "GLDHIT"; Priority = 32; Max channels = 2; } Sound { ID = "gntful"; Lump = "GNTFUL"; Priority = 32; Max channels = -1; } Sound { ID = "gnthit"; Lump = "GNTHIT"; Priority = 32; Max channels = -1; } Sound { ID = "gntpow"; Lump = "GNTPOW"; Priority = 32; Max channels = -1; } Sound { ID = "gntact"; Lump = "GNTACT"; Priority = 32; Max channels = -1; } Sound { ID = "gntuse"; Lump = "GNTUSE"; Priority = 32; Max channels = -1; } Sound { ID = "phosht"; Lump = "PHOSHT"; Priority = 32; Max channels = 2; } Sound { ID = "phohit"; Lump = "PHOHIT"; Priority = 32; Max channels = -1; } Sound { ID = "phopow"; Lump = "PHOPOW"; Link = "hedat1"; Priority = 32; Max channels = 1; } Sound { ID = "lobsht"; Lump = "LOBSHT"; Priority = 20; Max channels = 2; } Sound { ID = "lobhit"; Lump = "LOBHIT"; Priority = 20; Max channels = 2; } Sound { ID = "lobpow"; Lump = "LOBPOW"; Priority = 20; Max channels = 2; } Sound { ID = "hrnsht"; Lump = "HRNSHT"; Priority = 32; Max channels = 2; } Sound { ID = "hrnhit"; Lump = "HRNHIT"; Priority = 32; Max channels = 2; } Sound { ID = "hrnpow"; Lump = "HRNPOW"; Priority = 32; Max channels = 2; } Sound { ID = "ramphit"; Lump = "RAMPHIT"; Priority = 32; Max channels = 2; } Sound { ID = "ramrain"; Lump = "RAMRAIN"; Priority = 10; Max channels = 2; } Sound { ID = "bowsht"; Lump = "BOWSHT"; Priority = 32; Max channels = 2; } Sound { ID = "stfhit"; Lump = "STFHIT"; Priority = 32; Max channels = 2; } Sound { ID = "stfpow"; Lump = "STFPOW"; Priority = 32; Max channels = 2; } Sound { ID = "stfcrk"; Lump = "STFCRK"; Priority = 32; Max channels = 2; } Sound { ID = "impsit"; Lump = "IMPSIT"; Priority = 32; Max channels = 2; } Sound { ID = "impat1"; Lump = "IMPAT1"; Priority = 32; Max channels = 2; } Sound { ID = "impat2"; Lump = "IMPAT2"; Priority = 32; Max channels = 2; } Sound { ID = "impdth"; Lump = "IMPDTH"; Priority = 80; Max channels = 2; } Sound { ID = "impact"; Lump = "IMPACT"; Link = "impsit"; Priority = 20; Max channels = 2; } Sound { ID = "imppai"; Lump = "IMPPAI"; Priority = 32; Max channels = 2; } Sound { ID = "mumsit"; Lump = "MUMSIT"; Priority = 32; Max channels = 2; } Sound { ID = "mumat1"; Lump = "MUMAT1"; Priority = 32; Max channels = 2; } Sound { ID = "mumat2"; Lump = "MUMAT2"; Priority = 32; Max channels = 2; } Sound { ID = "mumdth"; Lump = "MUMDTH"; Priority = 80; Max channels = 2; } Sound { ID = "mumact"; Lump = "MUMACT"; Link = "mumsit"; Priority = 20; Max channels = 2; } Sound { ID = "mumpai"; Lump = "MUMPAI"; Priority = 32; Max channels = 2; } Sound { ID = "mumhed"; Lump = "MUMHED"; Priority = 32; Max channels = 2; } Sound { ID = "bstsit"; Lump = "BSTSIT"; Priority = 32; Max channels = 2; } Sound { ID = "bstatk"; Lump = "BSTATK"; Priority = 32; Max channels = 2; } Sound { ID = "bstdth"; Lump = "BSTDTH"; Priority = 80; Max channels = 2; } Sound { ID = "bstact"; Lump = "BSTACT"; Priority = 20; Max channels = 2; } Sound { ID = "bstpai"; Lump = "BSTPAI"; Priority = 32; Max channels = 2; } Sound { ID = "clksit"; Lump = "CLKSIT"; Priority = 32; Max channels = 2; } Sound { ID = "clkatk"; Lump = "CLKATK"; Priority = 32; Max channels = 2; } Sound { ID = "clkdth"; Lump = "CLKDTH"; Priority = 80; Max channels = 2; } Sound { ID = "clkact"; Lump = "CLKACT"; Priority = 20; Max channels = 2; } Sound { ID = "clkpai"; Lump = "CLKPAI"; Priority = 32; Max channels = 2; } Sound { ID = "snksit"; Lump = "SNKSIT"; Priority = 32; Max channels = 2; } Sound { ID = "snkatk"; Lump = "SNKATK"; Priority = 32; Max channels = 2; } Sound { ID = "snkdth"; Lump = "SNKDTH"; Priority = 80; Max channels = 2; } Sound { ID = "snkact"; Lump = "SNKACT"; Priority = 20; Max channels = 2; } Sound { ID = "snkpai"; Lump = "SNKPAI"; Priority = 32; Max channels = 2; } Sound { ID = "kgtsit"; Lump = "KGTSIT"; Priority = 32; Max channels = 2; } Sound { ID = "kgtatk"; Lump = "KGTATK"; Priority = 32; Max channels = 2; } Sound { ID = "kgtat2"; Lump = "KGTAT2"; Priority = 32; Max channels = 2; } Sound { ID = "kgtdth"; Lump = "KGTDTH"; Priority = 80; Max channels = 2; } Sound { ID = "kgtact"; Lump = "KGTACT"; Link = "kgtsit"; Priority = 20; Max channels = 2; } Sound { ID = "kgtpai"; Lump = "KGTPAI"; Priority = 32; Max channels = 2; } Sound { ID = "wizsit"; Lump = "WIZSIT"; Priority = 32; Max channels = 2; } Sound { ID = "wizatk"; Lump = "WIZATK"; Priority = 32; Max channels = 2; } Sound { ID = "wizdth"; Lump = "WIZDTH"; Priority = 80; Max channels = 2; } Sound { ID = "wizact"; Lump = "WIZACT"; Priority = 20; Max channels = 2; } Sound { ID = "wizpai"; Lump = "WIZPAI"; Priority = 32; Max channels = 2; } Sound { ID = "minsit"; Lump = "MINSIT"; Priority = 32; Max channels = 2; } Sound { ID = "minat1"; Lump = "MINAT1"; Priority = 32; Max channels = 2; } Sound { ID = "minat2"; Lump = "MINAT2"; Priority = 32; Max channels = 2; } Sound { ID = "minat3"; Lump = "MINAT3"; Priority = 32; Max channels = 2; } Sound { ID = "mindth"; Lump = "MINDTH"; Priority = 80; Max channels = 2; } Sound { ID = "minact"; Lump = "MINACT"; Priority = 20; Max channels = 2; } Sound { ID = "minpai"; Lump = "MINPAI"; Priority = 32; Max channels = 2; } Sound { ID = "hedsit"; Lump = "HEDSIT"; Priority = 32; Max channels = 2; } Sound { ID = "hedat1"; Lump = "HEDAT1"; Priority = 32; Max channels = 2; } Sound { ID = "hedat2"; Lump = "HEDAT2"; Priority = 32; Max channels = 2; } Sound { ID = "hedat3"; Lump = "HEDAT3"; Priority = 32; Max channels = 2; } Sound { ID = "heddth"; Lump = "HEDDTH"; Priority = 80; Max channels = 2; } Sound { ID = "hedact"; Lump = "HEDACT"; Priority = 20; Max channels = 2; } Sound { ID = "hedpai"; Lump = "HEDPAI"; Priority = 32; Max channels = 2; } Sound { ID = "sorzap"; Lump = "SORZAP"; Priority = 32; Max channels = 2; } Sound { ID = "sorrise"; Lump = "SORRISE"; Priority = 32; Max channels = 2; } Sound { ID = "sorsit"; Lump = "SORSIT"; Priority = 200; Max channels = 2; } Sound { ID = "soratk"; Lump = "SORATK"; Priority = 32; Max channels = 2; } Sound { ID = "soract"; Lump = "SORACT"; Priority = 200; Max channels = 2; } Sound { ID = "sorpai"; Lump = "SORPAI"; Priority = 200; Max channels = 2; } Sound { ID = "sordsph"; Lump = "SORDSPH"; Priority = 200; Max channels = 2; } Sound { ID = "sordexp"; Lump = "SORDEXP"; Priority = 200; Max channels = 2; } Sound { ID = "sordbon"; Lump = "SORDBON"; Priority = 200; Max channels = 2; } Sound { ID = "sbtsit"; Lump = "SBTSIT"; Link = "bstsit"; Priority = 32; Max channels = 2; } Sound { ID = "sbtatk"; Lump = "SBTATK"; Link = "bstatk"; Priority = 32; Max channels = 2; } Sound { ID = "sbtdth"; Lump = "SBTDTH"; Priority = 80; Max channels = 2; } Sound { ID = "sbtact"; Lump = "SBTACT"; Priority = 20; Max channels = 2; } Sound { ID = "sbtpai"; Lump = "SBTPAI"; Priority = 32; Max channels = 2; } Sound { ID = "plroof"; Lump = "PLROOF"; Priority = 32; Max channels = 2; } Sound { ID = "plrpai"; Lump = "PLRPAI"; Priority = 32; Max channels = 2; } Sound { ID = "plrdth"; Lump = "PLRDTH"; Priority = 80; Max channels = 2; } Sound { ID = "gibdth"; Lump = "GIBDTH"; Priority = 100; Max channels = 2; } Sound { ID = "plrwdth"; Lump = "PLRWDTH"; Priority = 80; Max channels = 2; } Sound { ID = "plrcdth"; Lump = "PLRCDTH"; Priority = 100; Max channels = 2; } Sound { ID = "itemup"; Lump = "ITEMUP"; Priority = 32; Max channels = 2; } Sound { ID = "wpnup"; Lump = "WPNUP"; Priority = 32; Max channels = 2; } Sound { ID = "telept"; Lump = "TELEPT"; Priority = 50; Max channels = 2; } Sound { ID = "doropn"; Lump = "DOROPN"; Priority = 40; Max channels = 2; } Sound { ID = "dorcls"; Lump = "DORCLS"; Priority = 40; Max channels = 2; } Sound { ID = "dormov"; Lump = "DORMOV"; Priority = 40; Max channels = 2; } Sound { ID = "artiup"; Lump = "ARTIUP"; Priority = 32; Max channels = 2; } Sound { ID = "switch"; Lump = "SWITCH"; Priority = 40; Max channels = 2; } Sound { ID = "pstart"; Lump = "PSTART"; Priority = 40; Max channels = 2; } Sound { ID = "pstop"; Lump = "PSTOP"; Priority = 40; Max channels = 2; } Sound { ID = "stnmov"; Lump = "STNMOV"; Priority = 40; Max channels = 2; } Sound { ID = "chicpai"; Lump = "CHICPAI"; Priority = 32; Max channels = 2; } Sound { ID = "chicatk"; Lump = "CHICATK"; Priority = 32; Max channels = 2; } Sound { ID = "chicdth"; Lump = "CHICDTH"; Priority = 40; Max channels = 2; } Sound { ID = "chicact"; Lump = "CHICACT"; Priority = 32; Max channels = 2; } Sound { ID = "chicpk1"; Lump = "CHICPK1"; Priority = 32; Max channels = 2; } Sound { ID = "chicpk2"; Lump = "CHICPK2"; Priority = 32; Max channels = 2; } Sound { ID = "chicpk3"; Lump = "CHICPK3"; Priority = 32; Max channels = 2; } Sound { ID = "keyup"; Lump = "KEYUP"; Priority = 50; Max channels = 2; } Sound { ID = "ripslop"; Lump = "RIPSLOP"; Priority = 16; Max channels = 2; } Sound { ID = "newpod"; Lump = "NEWPOD"; Priority = 16; Max channels = -1; } Sound { ID = "podexp"; Lump = "PODEXP"; Priority = 40; Max channels = -1; } Sound { ID = "bounce"; Lump = "BOUNCE"; Priority = 16; Max channels = 2; } Sound { ID = "volsht"; Lump = "VOLSHT"; Link = "bstatk"; Priority = 16; Max channels = 2; } Sound { ID = "volhit"; Lump = "VOLHIT"; Link = "lobhit"; Priority = 16; Max channels = 2; } Sound { ID = "burn"; Lump = "BURN"; Priority = 10; Max channels = 2; } Sound { ID = "splash"; Lump = "SPLASH"; Priority = 10; Max channels = 1; } Sound { ID = "gloop"; Lump = "GLOOP"; Priority = 10; Max channels = 2; } Sound { ID = "respawn"; Lump = "RESPAWN"; Priority = 10; Max channels = 1; } Sound { ID = "blssht"; Lump = "BLSSHT"; Priority = 32; Max channels = 2; } Sound { ID = "blshit"; Lump = "BLSHIT"; Priority = 32; Max channels = 2; } Sound { ID = "chat"; Lump = "CHAT"; Priority = 100; Max channels = 1; } Sound { ID = "artiuse"; Lump = "ARTIUSE"; Priority = 32; Max channels = 1; } Sound { ID = "gfrag"; Lump = "GFRAG"; Priority = 100; Max channels = 1; } Sound { ID = "waterfl"; Lump = "WATERFL"; Priority = 16; Max channels = 2; } Sound { ID = "wind"; Lump = "WIND"; Priority = 16; Max channels = 1; } Sound { ID = "amb1"; Lump = "AMB1"; Priority = 1; Max channels = 1; } Sound { ID = "amb2"; Lump = "AMB2"; Priority = 1; Max channels = 1; } Sound { ID = "amb3"; Lump = "AMB3"; Priority = 1; Max channels = 1; } Sound { ID = "amb4"; Lump = "AMB4"; Priority = 1; Max channels = 1; } Sound { ID = "amb5"; Lump = "AMB5"; Priority = 1; Max channels = 1; } Sound { ID = "amb6"; Lump = "AMB6"; Priority = 1; Max channels = 1; } Sound { ID = "amb7"; Lump = "AMB7"; Priority = 1; Max channels = 1; } Sound { ID = "amb8"; Lump = "AMB8"; Priority = 1; Max channels = 1; } Sound { ID = "amb9"; Lump = "AMB9"; Priority = 1; Max channels = 1; } Sound { ID = "amb10"; Lump = "AMB10"; Priority = 1; Max channels = 1; } Sound { ID = "amb11"; Lump = "AMB11"; Priority = 1; } Sound { ID = "secret"; Lump = "WPNUP"; Priority = 32; Max channels = 2; } Texture Environment { ID = "Metal"; Texture { ID = "BADPATCH"; }; Texture { ID = "METL1"; }; Texture { ID = "METL2"; }; Texture { ID = "SAINT1"; }; Texture { ID = "SKULLSB1"; }; Texture { ID = "SKULLSB2"; }; Texture { ID = "STNGLS1"; }; Texture { ID = "STNGLS2"; }; Texture { ID = "STNGLS3"; }; Texture { ID = "SW1OFF"; }; Texture { ID = "SW1ON"; }; Texture { ID = "SW2OFF"; }; Texture { ID = "SW2ON"; }; Texture { ID = "HORSES1"; }; Texture { ID = "MOSAIC1"; }; Texture { ID = "MOSAIC2"; }; Texture { ID = "MOSAIC3"; }; Texture { ID = "MOSAIC4"; }; Texture { ID = "MOSAIC5"; }; } Texture Environment { ID = "Rock"; Texture { ID = "CHAINMAN"; }; Texture { ID = "CHAINSD"; }; Texture { ID = "CSTLRCK"; }; Texture { ID = "CTYSTCI1"; }; Texture { ID = "CTYSTCI2"; }; Texture { ID = "CTYSTCI4"; }; Texture { ID = "CTYSTUC1"; }; Texture { ID = "CTYSTUC2"; }; Texture { ID = "CTYSTUC3"; }; Texture { ID = "CTYSTUC4"; }; Texture { ID = "CTYSTUC5"; }; Texture { ID = "DMNMSK"; }; Texture { ID = "DOOREXIT"; }; Texture { ID = "DOORSTON"; }; Texture { ID = "GRSKULL1"; }; Texture { ID = "GRSKULL2"; }; Texture { ID = "GRSKULL3"; }; Texture { ID = "GRSTNPB"; }; Texture { ID = "GRSTNPBV"; }; Texture { ID = "GRSTNPBW"; }; Texture { ID = "MOSSRCK1"; }; Texture { ID = "ORNGRAY"; }; Texture { ID = "RCKSNMUD"; }; Texture { ID = "REDWALL"; }; Texture { ID = "SANDSQ2"; }; Texture { ID = "SNDBLCKS"; }; Texture { ID = "SNDCHNKS"; }; Texture { ID = "SNDPLAIN"; }; Texture { ID = "SPINE1"; }; Texture { ID = "SPINE2"; }; Texture { ID = "SQPEB1"; }; Texture { ID = "SQPEB2"; }; Texture { ID = "TMBSTON1"; }; Texture { ID = "TMBSTON2"; }; Texture { ID = "TRISTON1"; }; Texture { ID = "TRISTON2"; }; Texture { ID = "BLUEFRAG"; }; Texture { ID = "BRWNRCKS"; }; Texture { ID = "CELTIC"; }; Texture { ID = "CSTLMOSS"; }; Texture { ID = "GRNBLOK1"; }; Texture { ID = "GRNBLOK2"; }; Texture { ID = "GRNBLOK3"; }; Texture { ID = "GRNBLOK4"; }; Texture { ID = "LAVA1"; }; Texture { ID = "LOOSERCK"; }; } Texture Environment { ID = "Wood"; Texture { ID = "DOORWOOD"; }; Texture { ID = "DRIPWALL"; }; Texture { ID = "WOODWL"; }; Texture { ID = "ROOTWALL"; }; } Texture Environment { ID = "Cloth"; Texture { ID = "WDGAT64"; }; Texture { ID = "WEB1_B"; }; Texture { ID = "WEB1_F"; }; Texture { ID = "WEB2_B"; }; Texture { ID = "WEB2_F"; }; Texture { ID = "WEB3_M"; }; Texture { ID = "BANNER1"; }; Texture { ID = "BANNER2"; }; Texture { ID = "BANNER3"; }; Texture { ID = "BANNER4"; }; Texture { ID = "BANNER5"; }; Texture { ID = "BANNER6"; }; Texture { ID = "BANNER7"; }; Texture { ID = "BANNER8"; }; Texture { ID = "GATMETL"; }; Texture { ID = "GATMETL2"; }; Texture { ID = "GATMETL3"; }; Texture { ID = "GATMETL4"; }; Texture { ID = "GATMETL5"; }; Texture { ID = "LAVAFL1"; }; Texture { ID = "LAVAFL2"; }; Texture { ID = "LAVAFL3"; }; Texture { ID = "WATRWAL1"; }; Texture { ID = "WATRWAL2"; }; Texture { ID = "WATRWAL3"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/jheretic.ded0000644000175000017500000000124211357170242023536 0ustar keeskees# # -=- jHeretic Definitions -=- # # This file is overwritten on every upgrade. Add custom definitions # to User.ded. # # For information about DED syntax and semantics, see Doc\DEDDoc.txt. # Header { Version = 5; Default model scale = 1.2; Model path = "data\jheretic\models"; } Include "flags.ded"; Include "objects.ded"; Include "sprites.ded"; Include "materials.ded"; Include "anim.ded"; Include "audio.ded"; Include "special.ded"; Include "details.ded"; Include "lights.ded"; Include "skies.ded"; Include "maps.ded"; Include "finales.ded"; Include "text.ded"; Include "values.ded"; Include "models.ded"; Include "user.ded"; IncludeIf Not -noauto "auto\*.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/models.ded0000644000175000017500000000021411357170242023222 0ustar keeskees# jHeretic: Models Include "models\*.ded"; # This can be removed if jHeretic.ded sets the default path. ModelPath "data\jheretic\models"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/objects.ded0000644000175000017500000070105011357170242023376 0ustar keeskees# jHeretic: Objects # # Order of definitions is very important here! # Only add new States and Things *after* the existing definitions. # Header { Version = 5; } Thing { ID = "MISC0"; DoomEd number = 81; Spawn state = "ITEM_PTN1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "ITEMSHIELD1"; DoomEd number = 85; Spawn state = "ITEM_SHLD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "ITEMSHIELD2"; DoomEd number = 31; Spawn state = "ITEM_SHD2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "MISC1"; DoomEd number = 8; Spawn state = "ITEM_BAGH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "MISC2"; DoomEd number = 35; Spawn state = "ITEM_SPMP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTIINVISIBILITY"; DoomEd number = 75; Spawn state = "ARTI_INVS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_shadow mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "MISC3"; DoomEd number = 82; Spawn state = "ARTI_PTN2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTIFLY"; DoomEd number = 83; Spawn state = "ARTI_SOAR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTIINVULNERABILITY"; DoomEd number = 84; Spawn state = "ARTI_INVU1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTITOMEOFPOWER"; DoomEd number = 86; Spawn state = "ARTI_PWBK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTIEGG"; DoomEd number = 30; Spawn state = "ARTI_EGGC1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "EGGFX"; DoomEd number = -1; Spawn state = "EGGFX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "EGGFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 18; Radius = 8; Height = 8; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "ARTISUPERHEAL"; DoomEd number = 32; Spawn state = "ARTI_SPHL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "MISC4"; DoomEd number = 33; Spawn state = "ARTI_TRCH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "MISC5"; DoomEd number = 34; Spawn state = "ARTI_FBMB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "FIREBOMB"; DoomEd number = -1; Spawn state = "FIREBOMB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "phohit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_nogravity mf_shadow"; } Thing { ID = "ARTITELEPORT"; DoomEd number = 36; Spawn state = "ARTI_ATLP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_countitem"; Flags2 = "mf2_floatbob"; } Thing { ID = "POD"; DoomEd number = 2035; Spawn state = "POD_WAIT1"; See state = "NULL"; Pain state = "POD_PAIN1"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "POD_DIE1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "podexp"; Active sound = "None"; Reaction time = 8; Pain chance = 255; Spawn health = 45; Radius = 16; Height = 54; Mass = 100; Flags = "mf_solid mf_noblood mf_shootable mf_dropoff mf_viewalign"; Flags2 = "mf2_windthrust mf2_pushable mf2_slide mf2_passmobj mf2_telestomp"; } Thing { ID = "PODGOO"; DoomEd number = -1; Spawn state = "PODGOO1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "PODGOOX"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv mf2_cannotpush"; } Thing { ID = "PODGENERATOR"; DoomEd number = 43; Spawn state = "PODGENERATOR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector"; } Thing { ID = "SPLASH"; DoomEd number = -1; Spawn state = "SPLASH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SPLASHX"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv mf2_cannotpush"; } Thing { ID = "SPLASHBASE"; DoomEd number = -1; Spawn state = "SPLASHBASE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "LAVASPLASH"; DoomEd number = -1; Spawn state = "LAVASPLASH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "LAVASMOKE"; DoomEd number = -1; Spawn state = "LAVASMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "SLUDGECHUNK"; DoomEd number = -1; Spawn state = "SLUDGECHUNK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SLUDGECHUNKX"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv mf2_cannotpush"; } Thing { ID = "SLUDGESPLASH"; DoomEd number = -1; Spawn state = "SLUDGESPLASH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "SKULLHANG70"; DoomEd number = 17; Spawn state = "SKULLHANG70_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 70; Mass = 100; Flags = "mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "SKULLHANG60"; DoomEd number = 24; Spawn state = "SKULLHANG60_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 60; Mass = 100; Flags = "mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "SKULLHANG45"; DoomEd number = 25; Spawn state = "SKULLHANG45_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 45; Mass = 100; Flags = "mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "SKULLHANG35"; DoomEd number = 26; Spawn state = "SKULLHANG35_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 35; Mass = 100; Flags = "mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "CHANDELIER"; DoomEd number = 28; Spawn state = "CHANDELIER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 32; Height = 60; Mass = 100; Flags = "mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "SERPTORCH"; DoomEd number = 27; Spawn state = "SERPTORCH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 54; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "SMALLPILLAR"; DoomEd number = 29; Spawn state = "SMALLPILLAR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 34; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "STALAGMITESMALL"; DoomEd number = 37; Spawn state = "STALAGMITESMALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 32; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "STALAGMITELARGE"; DoomEd number = 38; Spawn state = "STALAGMITELARGE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 64; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "STALACTITESMALL"; DoomEd number = 39; Spawn state = "STALACTITESMALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 36; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "STALACTITELARGE"; DoomEd number = 40; Spawn state = "STALACTITELARGE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 68; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "MISC6"; DoomEd number = 76; Spawn state = "FIREBRAZIER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 44; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "BARREL"; DoomEd number = 44; Spawn state = "BARREL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 32; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "MISC7"; DoomEd number = 47; Spawn state = "BRPILLAR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 128; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "MISC8"; DoomEd number = 48; Spawn state = "MOSS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 23; Mass = 100; Flags = "mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "MISC9"; DoomEd number = 49; Spawn state = "MOSS2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 27; Mass = 100; Flags = "mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "MISC10"; DoomEd number = 50; Spawn state = "WALLTORCH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 16; Mass = 100; Flags = "mf_nogravity mf_local"; } Thing { ID = "MISC11"; DoomEd number = 51; Spawn state = "HANGINGCORPSE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 104; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity mf_local"; } Thing { ID = "KEYGIZMOBLUE"; DoomEd number = 94; Spawn state = "KEYGIZMO1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 50; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "KEYGIZMOGREEN"; DoomEd number = 95; Spawn state = "KEYGIZMO1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 50; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "KEYGIZMOYELLOW"; DoomEd number = 96; Spawn state = "KEYGIZMO1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 50; Mass = 100; Flags = "mf_solid mf_local"; } Thing { ID = "KEYGIZMOFLOAT"; DoomEd number = -1; Spawn state = "KGZ_START"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 16; Mass = 100; Flags = "mf_solid mf_nogravity mf_local"; } Thing { ID = "MISC12"; DoomEd number = 87; Spawn state = "VOLCANO1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 20; Mass = 100; Flags = "mf_solid"; } Thing { ID = "VOLCANOBLAST"; DoomEd number = -1; Spawn state = "VOLCANOBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "VOLCANOBALLX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "volhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 2; Radius = 8; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_lograv mf2_noteleport mf2_firedamage"; } Thing { ID = "VOLCANOTBLAST"; DoomEd number = -1; Spawn state = "VOLCANOTBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "VOLCANOTBALLX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 2; Radius = 8; Height = 6; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_lograv mf2_noteleport mf2_firedamage"; } Thing { ID = "TELEGLITGEN"; DoomEd number = 74; Spawn state = "TELEGLITGEN1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_nosector mf_local"; } Thing { ID = "TELEGLITGEN2"; DoomEd number = 52; Spawn state = "TELEGLITGEN2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_nosector mf_local"; } Thing { ID = "TELEGLITTER"; DoomEd number = -1; Spawn state = "TELEGLITTER1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightshadow mf_local"; Flags2 = "mf2_noteleport"; } Thing { ID = "TELEGLITTER2"; DoomEd number = -1; Spawn state = "TELEGLITTER2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightshadow mf_local"; Flags2 = "mf2_noteleport"; } Thing { ID = "TFOG"; DoomEd number = -1; Spawn state = "TFOG1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "TELEPORTMAN"; DoomEd number = 14; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector"; } Thing { ID = "STAFFPUFF"; DoomEd number = -1; Spawn state = "STAFFPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "stfhit"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "STAFFPUFF2"; DoomEd number = -1; Spawn state = "STAFFPUFF2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "stfpow"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "BEAKPUFF"; DoomEd number = -1; Spawn state = "STAFFPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "chicatk"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "MISC13"; DoomEd number = 2005; Spawn state = "WGNT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "GAUNTLETPUFF1"; DoomEd number = -1; Spawn state = "GAUNTLETPUFF1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_brightshadow"; } Thing { ID = "GAUNTLETPUFF2"; DoomEd number = -1; Spawn state = "GAUNTLETPUFF2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_brightshadow"; } Thing { ID = "MISC14"; DoomEd number = 53; Spawn state = "BLSR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "BLASTERFX1"; DoomEd number = -1; Spawn state = "BLASTERFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BLASTERFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "blshit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 184; Radius = 12; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "BLASTERSMOKE"; DoomEd number = -1; Spawn state = "BLASTERSMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow mf_viewalign"; Flags2 = "mf2_noteleport mf2_cannotpush"; } Thing { ID = "RIPPER"; DoomEd number = -1; Spawn state = "RIPPER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "RIPPERX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "hrnhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 14; Radius = 8; Height = 6; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport mf2_rip"; } Thing { ID = "BLASTERPUFF1"; DoomEd number = -1; Spawn state = "BLASTERPUFF1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_brightshadow"; } Thing { ID = "BLASTERPUFF2"; DoomEd number = -1; Spawn state = "BLASTERPUFF2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_brightshadow"; } Thing { ID = "WMACE"; DoomEd number = 2002; Spawn state = "WMCE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "MACEFX1"; DoomEd number = -1; Spawn state = "MACEFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MACEFXI1_1"; Xdeath state = "NULL"; See sound = "lobsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 8; Height = 6; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_floorbounce mf2_thrughost mf2_noteleport"; } Thing { ID = "MACEFX2"; DoomEd number = -1; Spawn state = "MACEFX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MACEFXI2_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 8; Height = 6; Mass = 100; Damage = 6; Flags = "mf_noblockmap mf_missile mf_dropoff mf_brightexplode"; Flags2 = "mf2_lograv mf2_floorbounce mf2_thrughost mf2_noteleport"; } Thing { ID = "MACEFX3"; DoomEd number = -1; Spawn state = "MACEFX3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MACEFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 7; Radius = 8; Height = 6; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_dropoff mf_brightexplode"; Flags2 = "mf2_lograv mf2_floorbounce mf2_thrughost mf2_noteleport"; } Thing { ID = "MACEFX4"; DoomEd number = -1; Spawn state = "MACEFX4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MACEFXI4_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 7; Radius = 8; Height = 6; Mass = 100; Damage = 18; Flags = "mf_noblockmap mf_missile mf_dropoff mf_brightexplode"; Flags2 = "mf2_lograv mf2_floorbounce mf2_thrughost mf2_noteleport"; } Thing { ID = "WSKULLROD"; DoomEd number = 2004; Spawn state = "WSKL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "HORNRODFX1"; DoomEd number = -1; Spawn state = "HRODFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HRODFXI1_1"; Xdeath state = "NULL"; See sound = "hrnsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "hrnhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 22; Radius = 12; Height = 8; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_windthrust mf2_noteleport"; } Thing { ID = "HORNRODFX2"; DoomEd number = -1; Spawn state = "HRODFX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HRODFXI2_1"; Xdeath state = "NULL"; See sound = "hrnsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "ramphit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 22; Radius = 12; Height = 8; Mass = 100; Damage = 10; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "RAINPLR1"; DoomEd number = -1; Spawn state = "RAINPLR1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "RAINPLR1X_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 12; Radius = 5; Height = 12; Mass = 100; Damage = 5; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_viewalign mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "RAINPLR2"; DoomEd number = -1; Spawn state = "RAINPLR2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "RAINPLR2X_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 12; Radius = 5; Height = 12; Mass = 100; Damage = 5; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_viewalign mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "RAINPLR3"; DoomEd number = -1; Spawn state = "RAINPLR3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "RAINPLR3X_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 12; Radius = 5; Height = 12; Mass = 100; Damage = 5; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_viewalign mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "RAINPLR4"; DoomEd number = -1; Spawn state = "RAINPLR4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "RAINPLR4X_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 12; Radius = 5; Height = 12; Mass = 100; Damage = 5; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_viewalign mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "GOLDWANDFX1"; DoomEd number = -1; Spawn state = "GWANDFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "GWANDFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "gldhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 22; Radius = 10; Height = 6; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "GOLDWANDFX2"; DoomEd number = -1; Spawn state = "GWANDFX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "GWANDFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 18; Radius = 10; Height = 6; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "GOLDWANDPUFF1"; DoomEd number = -1; Spawn state = "GWANDPUFF1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_brightshadow"; } Thing { ID = "GOLDWANDPUFF2"; DoomEd number = -1; Spawn state = "GWANDFXI1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_brightshadow"; } Thing { ID = "WPHOENIXROD"; DoomEd number = 2003; Spawn state = "WPHX"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "PHOENIXFX1"; DoomEd number = -1; Spawn state = "PHOENIXFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "PHOENIXFXI1_1"; Xdeath state = "NULL"; See sound = "phosht"; Attack sound = "None"; Pain sound = "None"; Death sound = "phohit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 11; Height = 8; Mass = 100; Damage = 20; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_thrughost mf2_noteleport"; } Thing { ID = "PHOENIXPUFF"; DoomEd number = -1; Spawn state = "PHOENIXPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow mf_viewalign"; Flags2 = "mf2_noteleport mf2_cannotpush"; } Thing { ID = "PHOENIXFX2"; DoomEd number = -1; Spawn state = "PHOENIXFX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "PHOENIXFXI2_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightshadow"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "MISC15"; DoomEd number = 2001; Spawn state = "WBOW"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "CRBOWFX1"; DoomEd number = -1; Spawn state = "CRBOWFX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CRBOWFXI1_1"; Xdeath state = "NULL"; See sound = "bowsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "hrnhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 30; Radius = 11; Height = 8; Mass = 100; Damage = 10; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "CRBOWFX2"; DoomEd number = -1; Spawn state = "CRBOWFX2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CRBOWFXI1_1"; Xdeath state = "NULL"; See sound = "bowsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "hrnhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 32; Radius = 11; Height = 8; Mass = 100; Damage = 6; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "CRBOWFX3"; DoomEd number = -1; Spawn state = "CRBOWFX3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CRBOWFXI3_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "hrnhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 11; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_windthrust mf2_thrughost mf2_noteleport"; } Thing { ID = "CRBOWFX4"; DoomEd number = -1; Spawn state = "CRBOWFX4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_brightshadow mf_local"; Flags2 = "mf2_lograv"; } Thing { ID = "BLOOD"; DoomEd number = -1; Spawn state = "BLOOD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "BLOODSPLATTER"; DoomEd number = -1; Spawn state = "BLOODSPLATTER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BLOODSPLATTERX"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_cannotpush"; } Thing { ID = "PLAYER"; DoomEd number = -1; Spawn state = "PLAY"; See state = "PLAY_RUN1"; Pain state = "PLAY_PAIN"; Melee state = "NULL"; Missile state = "PLAY_ATK1"; Crash state = "NULL"; Death state = "PLAY_DIE1"; Xdeath state = "PLAY_XDIE1"; See sound = "None"; Attack sound = "None"; Pain sound = "plrpai"; Death sound = "plrdth"; Active sound = "None"; Pain chance = 255; Spawn health = 100; Radius = 16; Height = 56; Mass = 100; Flags = solid | shootable | dropoff | pickup; Flags2 = windthrust | footclip | slide | passmobj | telestomp; } Thing { ID = "BLOODYSKULL"; DoomEd number = -1; Spawn state = "BLOODYSKULL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_dropoff"; Flags2 = "mf2_lograv mf2_cannotpush"; } Thing { ID = "CHICPLAYER"; DoomEd number = -1; Spawn state = "CHICPLAY"; See state = "CHICPLAY_RUN1"; Pain state = "CHICPLAY_PAIN"; Melee state = "NULL"; Missile state = "CHICPLAY_ATK1"; Crash state = "NULL"; Death state = "CHICKEN_DIE1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "chicpai"; Death sound = "chicdth"; Active sound = "None"; Pain chance = 255; Spawn health = 100; Radius = 16; Height = 24; Mass = 100; Flags = solid | shootable | dropoff; Flags2 = windthrust | slide | passmobj | footclip | lograv | telestomp; } Thing { ID = "CHICKEN"; DoomEd number = -1; Spawn state = "CHICKEN_LOOK1"; See state = "CHICKEN_WALK1"; Pain state = "CHICKEN_PAIN1"; Melee state = "CHICKEN_ATK1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CHICKEN_DIE1"; Xdeath state = "NULL"; See sound = "chicpai"; Attack sound = "chicatk"; Pain sound = "chicpai"; Death sound = "chicdth"; Active sound = "chicact"; Reaction time = 8; Pain chance = 200; Spawn health = 10; Speed = 4; Radius = 9; Height = 22; Mass = 40; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff"; Flags2 = "mf2_windthrust mf2_footclip mf2_passmobj"; } Thing { ID = "FEATHER"; DoomEd number = -1; Spawn state = "FEATHER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FEATHERX"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv mf2_cannotpush mf2_windthrust"; } Thing { ID = "MUMMY"; DoomEd number = 68; Spawn state = "MUMMY_LOOK1"; See state = "MUMMY_WALK1"; Pain state = "MUMMY_PAIN1"; Melee state = "MUMMY_ATK1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MUMMY_DIE1"; Xdeath state = "NULL"; See sound = "mumsit"; Attack sound = "mumat1"; Pain sound = "mumpai"; Death sound = "mumdth"; Active sound = "mumact"; Reaction time = 8; Pain chance = 128; Spawn health = 80; Speed = 12; Radius = 22; Height = 62; Mass = 75; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "MUMMYLEADER"; DoomEd number = 45; Spawn state = "MUMMY_LOOK1"; See state = "MUMMY_WALK1"; Pain state = "MUMMY_PAIN1"; Melee state = "MUMMY_ATK1"; Missile state = "MUMMYL_ATK1"; Crash state = "NULL"; Death state = "MUMMY_DIE1"; Xdeath state = "NULL"; See sound = "mumsit"; Attack sound = "mumat1"; Pain sound = "mumpai"; Death sound = "mumdth"; Active sound = "mumact"; Reaction time = 8; Pain chance = 64; Spawn health = 100; Speed = 12; Radius = 22; Height = 62; Mass = 75; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "MUMMYGHOST"; DoomEd number = 69; Spawn state = "MUMMY_LOOK1"; See state = "MUMMY_WALK1"; Pain state = "MUMMY_PAIN1"; Melee state = "MUMMY_ATK1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MUMMY_DIE1"; Xdeath state = "NULL"; See sound = "mumsit"; Attack sound = "mumat1"; Pain sound = "mumpai"; Death sound = "mumdth"; Active sound = "mumact"; Reaction time = 8; Pain chance = 128; Spawn health = 80; Speed = 12; Radius = 22; Height = 62; Mass = 75; Flags = "mf_solid mf_shootable mf_countkill mf_shadow"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "MUMMYLEADERGHOST"; DoomEd number = 46; Spawn state = "MUMMY_LOOK1"; See state = "MUMMY_WALK1"; Pain state = "MUMMY_PAIN1"; Melee state = "MUMMY_ATK1"; Missile state = "MUMMYL_ATK1"; Crash state = "NULL"; Death state = "MUMMY_DIE1"; Xdeath state = "NULL"; See sound = "mumsit"; Attack sound = "mumat1"; Pain sound = "mumpai"; Death sound = "mumdth"; Active sound = "mumact"; Reaction time = 8; Pain chance = 64; Spawn health = 100; Speed = 12; Radius = 22; Height = 62; Mass = 75; Flags = "mf_solid mf_shootable mf_countkill mf_shadow"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "MUMMYSOUL"; DoomEd number = -1; Spawn state = "MUMMY_SOUL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "MUMMYFX1"; DoomEd number = -1; Spawn state = "MUMMYFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MUMMYFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 9; Radius = 8; Height = 14; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "BEAST"; DoomEd number = 70; Spawn state = "BEAST_LOOK1"; See state = "BEAST_WALK1"; Pain state = "BEAST_PAIN1"; Melee state = "NULL"; Missile state = "BEAST_ATK1"; Crash state = "NULL"; Death state = "BEAST_DIE1"; Xdeath state = "BEAST_XDIE1"; See sound = "bstsit"; Attack sound = "bstatk"; Pain sound = "bstpai"; Death sound = "bstdth"; Active sound = "bstact"; Reaction time = 8; Pain chance = 100; Spawn health = 220; Speed = 14; Radius = 32; Height = 74; Mass = 200; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "BEASTBALL"; DoomEd number = -1; Spawn state = "BEASTBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BEASTBALLX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 12; Radius = 9; Height = 8; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_windthrust mf2_noteleport"; } Thing { ID = "BURNBALL"; DoomEd number = -1; Spawn state = "BURNBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BEASTBALLX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_nogravity mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "BURNBALLFB"; DoomEd number = -1; Spawn state = "BURNBALLFB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BEASTBALLX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_nogravity mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "PUFFY"; DoomEd number = -1; Spawn state = "PUFFY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "PUFFY1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_nogravity mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "SNAKE"; DoomEd number = 92; Spawn state = "SNAKE_LOOK1"; See state = "SNAKE_WALK1"; Pain state = "SNAKE_PAIN1"; Melee state = "NULL"; Missile state = "SNAKE_ATK1"; Crash state = "NULL"; Death state = "SNAKE_DIE1"; Xdeath state = "NULL"; See sound = "snksit"; Attack sound = "snkatk"; Pain sound = "snkpai"; Death sound = "snkdth"; Active sound = "snkact"; Reaction time = 8; Pain chance = 48; Spawn health = 280; Speed = 10; Radius = 22; Height = 70; Mass = 100; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "SNAKEPRO_A"; DoomEd number = -1; Spawn state = "SNAKEPRO_A1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SNAKEPRO_AX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 14; Radius = 12; Height = 8; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_windthrust mf2_noteleport"; } Thing { ID = "SNAKEPRO_B"; DoomEd number = -1; Spawn state = "SNAKEPRO_B1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SNAKEPRO_BX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 14; Radius = 12; Height = 8; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "HEAD"; DoomEd number = 6; Spawn state = "HEAD_LOOK"; See state = "HEAD_FLOAT"; Pain state = "HEAD_PAIN1"; Melee state = "NULL"; Missile state = "HEAD_ATK1"; Crash state = "NULL"; Death state = "HEAD_DIE1"; Xdeath state = "NULL"; See sound = "hedsit"; Attack sound = "hedat1"; Pain sound = "hedpai"; Death sound = "heddth"; Active sound = "hedact"; Reaction time = 8; Pain chance = 32; Spawn health = 700; Speed = 6; Radius = 40; Height = 72; Mass = 325; Flags = "mf_solid mf_shootable mf_countkill mf_noblood"; Flags2 = "mf2_passmobj"; } Thing { ID = "HEADFX1"; DoomEd number = -1; Spawn state = "HEADFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HEADFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 13; Radius = 12; Height = 6; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport mf2_thrughost"; } Thing { ID = "HEADFX2"; DoomEd number = -1; Spawn state = "HEADFX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HEADFXI2_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 8; Radius = 12; Height = 6; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "HEADFX3"; DoomEd number = -1; Spawn state = "HEADFX3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HEADFXI3_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 14; Height = 12; Mass = 100; Damage = 5; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightshadow mf_brightexplode"; Flags2 = "mf2_windthrust mf2_noteleport"; } Thing { ID = "WHIRLWIND"; DoomEd number = -1; Spawn state = "HEADFX4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HEADFXI4_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 16; Height = 74; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_shadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "CLINK"; DoomEd number = 90; Spawn state = "CLINK_LOOK1"; See state = "CLINK_WALK1"; Pain state = "CLINK_PAIN1"; Melee state = "CLINK_ATK1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CLINK_DIE1"; Xdeath state = "NULL"; See sound = "clksit"; Attack sound = "clkatk"; Pain sound = "clkpai"; Death sound = "clkdth"; Active sound = "clkact"; Reaction time = 8; Pain chance = 32; Spawn health = 150; Speed = 14; Radius = 20; Height = 64; Mass = 75; Flags = "mf_solid mf_shootable mf_countkill mf_noblood"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "WIZARD"; DoomEd number = 15; Spawn state = "WIZARD_LOOK1"; See state = "WIZARD_WALK1"; Pain state = "WIZARD_PAIN1"; Melee state = "NULL"; Missile state = "WIZARD_ATK1"; Crash state = "NULL"; Death state = "WIZARD_DIE1"; Xdeath state = "NULL"; See sound = "wizsit"; Attack sound = "wizatk"; Pain sound = "wizpai"; Death sound = "wizdth"; Active sound = "wizact"; Reaction time = 8; Pain chance = 64; Spawn health = 180; Speed = 12; Radius = 16; Height = 68; Mass = 100; Flags = "mf_solid mf_shootable mf_countkill mf_float mf_nogravity"; Flags2 = "mf2_passmobj"; } Thing { ID = "WIZFX1"; DoomEd number = -1; Spawn state = "WIZFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "WIZFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 18; Radius = 10; Height = 6; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "IMP"; DoomEd number = 66; Spawn state = "IMP_LOOK1"; See state = "IMP_FLY1"; Pain state = "IMP_PAIN1"; Melee state = "IMP_MEATK1"; Missile state = "IMP_MSATK1_1"; Crash state = "IMP_CRASH1"; Death state = "IMP_DIE1"; Xdeath state = "IMP_XDIE1"; See sound = "impsit"; Attack sound = "impat1"; Pain sound = "imppai"; Death sound = "impdth"; Active sound = "impact"; Reaction time = 8; Pain chance = 200; Spawn health = 40; Speed = 10; Radius = 16; Height = 36; Mass = 50; Flags = "mf_solid mf_shootable mf_float mf_nogravity mf_countkill"; Flags2 = "mf2_spawnfloat mf2_passmobj"; } Thing { ID = "IMPLEADER"; DoomEd number = 5; Spawn state = "IMP_LOOK1"; See state = "IMP_FLY1"; Pain state = "IMP_PAIN1"; Melee state = "NULL"; Missile state = "IMP_MSATK2_1"; Crash state = "IMP_CRASH1"; Death state = "IMP_DIE1"; Xdeath state = "IMP_XDIE1"; See sound = "impsit"; Attack sound = "impat2"; Pain sound = "imppai"; Death sound = "impdth"; Active sound = "impact"; Reaction time = 8; Pain chance = 200; Spawn health = 80; Speed = 10; Radius = 16; Height = 36; Mass = 50; Flags = "mf_solid mf_shootable mf_float mf_nogravity mf_countkill"; Flags2 = "mf2_spawnfloat mf2_passmobj"; } Thing { ID = "IMPCHUNK1"; DoomEd number = -1; Spawn state = "IMP_CHUNKA1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "IMPCHUNK2"; DoomEd number = -1; Spawn state = "IMP_CHUNKB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "IMPBALL"; DoomEd number = -1; Spawn state = "IMPFX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "IMPFXI1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 8; Height = 8; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_windthrust mf2_noteleport"; } Thing { ID = "KNIGHT"; DoomEd number = 64; Spawn state = "KNIGHT_STND1"; See state = "KNIGHT_WALK1"; Pain state = "KNIGHT_PAIN1"; Melee state = "KNIGHT_ATK1"; Missile state = "KNIGHT_ATK1"; Crash state = "NULL"; Death state = "KNIGHT_DIE1"; Xdeath state = "NULL"; See sound = "kgtsit"; Attack sound = "kgtatk"; Pain sound = "kgtpai"; Death sound = "kgtdth"; Active sound = "kgtact"; Reaction time = 8; Pain chance = 100; Spawn health = 200; Speed = 12; Radius = 24; Height = 78; Mass = 150; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "KNIGHTGHOST"; DoomEd number = 65; Spawn state = "KNIGHT_STND1"; See state = "KNIGHT_WALK1"; Pain state = "KNIGHT_PAIN1"; Melee state = "KNIGHT_ATK1"; Missile state = "KNIGHT_ATK1"; Crash state = "NULL"; Death state = "KNIGHT_DIE1"; Xdeath state = "NULL"; See sound = "kgtsit"; Attack sound = "kgtatk"; Pain sound = "kgtpai"; Death sound = "kgtdth"; Active sound = "kgtact"; Reaction time = 8; Pain chance = 100; Spawn health = 200; Speed = 12; Radius = 24; Height = 78; Mass = 150; Flags = "mf_solid mf_shootable mf_countkill mf_shadow"; Flags2 = "mf2_footclip mf2_passmobj"; } Thing { ID = "KNIGHTAXE"; DoomEd number = -1; Spawn state = "SPINAXE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SPINAXEX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "hrnhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 9; Radius = 10; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_windthrust mf2_noteleport mf2_thrughost"; } Thing { ID = "REDAXE"; DoomEd number = -1; Spawn state = "REDAXE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "REDAXEX1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "hrnhit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 9; Radius = 10; Height = 8; Mass = 100; Damage = 7; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport mf2_thrughost"; } Thing { ID = "SORCERER1"; DoomEd number = 7; Spawn state = "SRCR1_LOOK1"; See state = "SRCR1_WALK1"; Pain state = "SRCR1_PAIN1"; Melee state = "NULL"; Missile state = "SRCR1_ATK1"; Crash state = "NULL"; Death state = "SRCR1_DIE1"; Xdeath state = "NULL"; See sound = "sbtsit"; Attack sound = "sbtatk"; Pain sound = "sbtpai"; Death sound = "sbtdth"; Active sound = "sbtact"; Reaction time = 8; Pain chance = 56; Spawn health = 2000; Speed = 16; Radius = 28; Height = 100; Mass = 800; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_footclip mf2_passmobj mf2_boss"; Flags3 = "mf3_noinfight"; } Thing { ID = "SRCRFX1"; DoomEd number = -1; Spawn state = "SRCRFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SRCRFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 10; Height = 10; Mass = 100; Damage = 10; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "SORCERER2"; DoomEd number = -1; Spawn state = "SOR2_LOOK1"; See state = "SOR2_WALK1"; Pain state = "SOR2_PAIN1"; Melee state = "NULL"; Missile state = "SOR2_ATK1"; Crash state = "NULL"; Death state = "SOR2_DIE1"; Xdeath state = "NULL"; See sound = "sorsit"; Attack sound = "soratk"; Pain sound = "sorpai"; Death sound = "None"; Active sound = "soract"; Reaction time = 8; Pain chance = 32; Spawn health = 3500; Speed = 14; Radius = 16; Height = 70; Mass = 300; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff"; Flags2 = "mf2_footclip mf2_passmobj mf2_boss"; Flags3 = "mf3_noinfight"; } Thing { ID = "SOR2FX1"; DoomEd number = -1; Spawn state = "SOR2FX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SOR2FXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 10; Height = 6; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "SOR2FXSPARK"; DoomEd number = -1; Spawn state = "SOR2FXSPARK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; Flags2 = "mf2_noteleport mf2_cannotpush"; } Thing { ID = "SOR2FX2"; DoomEd number = -1; Spawn state = "SOR2FX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SOR2FXI2_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 6; Radius = 10; Height = 6; Mass = 100; Damage = 10; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "SOR2TELEFADE"; DoomEd number = -1; Spawn state = "SOR2TELEFADE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "MINOTAUR"; DoomEd number = 9; Spawn state = "MNTR_LOOK1"; See state = "MNTR_WALK1"; Pain state = "MNTR_PAIN1"; Melee state = "MNTR_ATK1_1"; Missile state = "MNTR_ATK2_1"; Crash state = "NULL"; Death state = "MNTR_DIE1"; Xdeath state = "NULL"; See sound = "minsit"; Attack sound = "minat1"; Pain sound = "minpai"; Death sound = "mindth"; Active sound = "minact"; Reaction time = 8; Pain chance = 25; Spawn health = 3000; Speed = 16; Radius = 28; Height = 100; Mass = 800; Damage = 7; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff"; Flags2 = "mf2_footclip mf2_passmobj mf2_boss"; Flags3 = "mf3_noinfight"; } Thing { ID = "MNTRFX1"; DoomEd number = -1; Spawn state = "MNTRFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MNTRFXI1_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 10; Height = 6; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "MNTRFX2"; DoomEd number = -1; Spawn state = "MNTRFX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MNTRFXI2_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "phohit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 14; Radius = 5; Height = 12; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "MNTRFX3"; DoomEd number = -1; Spawn state = "MNTRFX3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MNTRFXI2_1"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "phohit"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 16; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity mf_brightexplode"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "AKYY"; DoomEd number = 73; Spawn state = "AKYY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_notdmatch"; } Thing { ID = "BKYY"; DoomEd number = 79; Spawn state = "BKYY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_notdmatch"; } Thing { ID = "CKEY"; DoomEd number = 80; Spawn state = "CKYY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_notdmatch"; } Thing { ID = "AMGWNDWIMPY"; DoomEd number = 10; Spawn state = "AMG1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 10; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMGWNDHEFTY"; DoomEd number = 12; Spawn state = "AMG2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 50; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMMACEWIMPY"; DoomEd number = 13; Spawn state = "AMM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 20; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMMACEHEFTY"; DoomEd number = 16; Spawn state = "AMM2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 100; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMCBOWWIMPY"; DoomEd number = 18; Spawn state = "AMC1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 5; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMCBOWHEFTY"; DoomEd number = 19; Spawn state = "AMC2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 20; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMSKRDWIMPY"; DoomEd number = 20; Spawn state = "AMS1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 20; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMSKRDHEFTY"; DoomEd number = 21; Spawn state = "AMS2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 100; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AMPHRDWIMPY"; DoomEd number = 22; Spawn state = "AMP1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_viewalign"; } Thing { ID = "AMPHRDHEFTY"; DoomEd number = 23; Spawn state = "AMP2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 10; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_viewalign"; } Thing { ID = "AMBLSRWIMPY"; DoomEd number = 54; Spawn state = "AMB1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 10; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_viewalign"; } Thing { ID = "AMBLSRHEFTY"; DoomEd number = 55; Spawn state = "AMB2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 25; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_viewalign"; } Thing { ID = "SOUNDWIND"; DoomEd number = 42; Spawn state = "SND_WIND"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector mf_local"; } Thing { ID = "SOUNDWATERFALL"; DoomEd number = 41; Spawn state = "SND_WATERFALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector mf_local"; } State { ID = "NULL"; Sprite = "IMPX"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FREETARGMOBJ"; Sprite = "ACLO"; Frame = 4; Tics = 1050; Action = "A_FreeTargMobj"; Next state = "NULL"; } State { ID = "ITEM_PTN1_1"; Sprite = "PTN1"; Frame = 0; Tics = 3; Next state = "ITEM_PTN1_2"; } State { ID = "ITEM_PTN1_2"; Sprite = "PTN1"; Frame = 1; Tics = 3; Next state = "ITEM_PTN1_3"; } State { ID = "ITEM_PTN1_3"; Sprite = "PTN1"; Frame = 2; Tics = 3; Next state = "ITEM_PTN1_1"; } State { ID = "ITEM_SHLD1"; Sprite = "SHLD"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ITEM_SHD2_1"; Sprite = "SHD2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ITEM_BAGH1"; Sprite = "BAGH"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ITEM_SPMP1"; Sprite = "SPMP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HIDESPECIAL1"; Sprite = "ACLO"; Frame = 4; Tics = 1400; Next state = "HIDESPECIAL2"; } State { ID = "HIDESPECIAL2"; Sprite = "ACLO"; Frame = 0; Tics = 4; Action = "A_RestoreSpecialThing1"; Next state = "HIDESPECIAL3"; } State { ID = "HIDESPECIAL3"; Sprite = "ACLO"; Frame = 1; Tics = 4; Next state = "HIDESPECIAL4"; } State { ID = "HIDESPECIAL4"; Sprite = "ACLO"; Frame = 0; Tics = 4; Next state = "HIDESPECIAL5"; } State { ID = "HIDESPECIAL5"; Sprite = "ACLO"; Frame = 1; Tics = 4; Next state = "HIDESPECIAL6"; } State { ID = "HIDESPECIAL6"; Sprite = "ACLO"; Frame = 2; Tics = 4; Next state = "HIDESPECIAL7"; } State { ID = "HIDESPECIAL7"; Sprite = "ACLO"; Frame = 1; Tics = 4; Next state = "HIDESPECIAL8"; } State { ID = "HIDESPECIAL8"; Sprite = "ACLO"; Frame = 2; Tics = 4; Next state = "HIDESPECIAL9"; } State { ID = "HIDESPECIAL9"; Sprite = "ACLO"; Frame = 3; Tics = 4; Next state = "HIDESPECIAL10"; } State { ID = "HIDESPECIAL10"; Sprite = "ACLO"; Frame = 2; Tics = 4; Next state = "HIDESPECIAL11"; } State { ID = "HIDESPECIAL11"; Sprite = "ACLO"; Frame = 3; Tics = 4; Action = "A_RestoreSpecialThing2"; Next state = "NULL"; } State { ID = "DORMANTARTI1"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI2"; } State { ID = "DORMANTARTI2"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI3"; } State { ID = "DORMANTARTI3"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI4"; } State { ID = "DORMANTARTI4"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI5"; } State { ID = "DORMANTARTI5"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI6"; } State { ID = "DORMANTARTI6"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI7"; } State { ID = "DORMANTARTI7"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI8"; } State { ID = "DORMANTARTI8"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI9"; } State { ID = "DORMANTARTI9"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI10"; } State { ID = "DORMANTARTI10"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI11"; } State { ID = "DORMANTARTI11"; Sprite = "ACLO"; Frame = 0; Tics = 1400; Action = "A_HideThing"; Next state = "DORMANTARTI12"; } State { ID = "DORMANTARTI12"; Sprite = "ACLO"; Frame = 0; Tics = 3; Action = "A_UnHideThing"; Next state = "DORMANTARTI13"; } State { ID = "DORMANTARTI13"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI14"; } State { ID = "DORMANTARTI14"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI15"; } State { ID = "DORMANTARTI15"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI16"; } State { ID = "DORMANTARTI16"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI17"; } State { ID = "DORMANTARTI17"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI18"; } State { ID = "DORMANTARTI18"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI19"; } State { ID = "DORMANTARTI19"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI20"; } State { ID = "DORMANTARTI20"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI21"; } State { ID = "DORMANTARTI21"; Sprite = "ACLO"; Frame = 3; Tics = 3; Action = "A_RestoreArtifact"; Next state = "NULL"; } State { ID = "DEADARTI1"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DEADARTI2"; } State { ID = "DEADARTI2"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DEADARTI3"; } State { ID = "DEADARTI3"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DEADARTI4"; } State { ID = "DEADARTI4"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DEADARTI5"; } State { ID = "DEADARTI5"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DEADARTI6"; } State { ID = "DEADARTI6"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DEADARTI7"; } State { ID = "DEADARTI7"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DEADARTI8"; } State { ID = "DEADARTI8"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DEADARTI9"; } State { ID = "DEADARTI9"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DEADARTI10"; } State { ID = "DEADARTI10"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "NULL"; } State { ID = "ARTI_INVS1"; Sprite = "INVS"; Frame = 32768; Tics = 350; Next state = "ARTI_INVS1"; } State { ID = "ARTI_PTN2_1"; Sprite = "PTN2"; Frame = 0; Tics = 4; Next state = "ARTI_PTN2_2"; } State { ID = "ARTI_PTN2_2"; Sprite = "PTN2"; Frame = 1; Tics = 4; Next state = "ARTI_PTN2_3"; } State { ID = "ARTI_PTN2_3"; Sprite = "PTN2"; Frame = 2; Tics = 4; Next state = "ARTI_PTN2_1"; } State { ID = "ARTI_SOAR1"; Sprite = "SOAR"; Frame = 0; Tics = 5; Next state = "ARTI_SOAR2"; } State { ID = "ARTI_SOAR2"; Sprite = "SOAR"; Frame = 1; Tics = 5; Next state = "ARTI_SOAR3"; } State { ID = "ARTI_SOAR3"; Sprite = "SOAR"; Frame = 2; Tics = 5; Next state = "ARTI_SOAR4"; } State { ID = "ARTI_SOAR4"; Sprite = "SOAR"; Frame = 1; Tics = 5; Next state = "ARTI_SOAR1"; } State { ID = "ARTI_INVU1"; Sprite = "INVU"; Frame = 0; Tics = 3; Next state = "ARTI_INVU2"; } State { ID = "ARTI_INVU2"; Sprite = "INVU"; Frame = 1; Tics = 3; Next state = "ARTI_INVU3"; } State { ID = "ARTI_INVU3"; Sprite = "INVU"; Frame = 2; Tics = 3; Next state = "ARTI_INVU4"; } State { ID = "ARTI_INVU4"; Sprite = "INVU"; Frame = 3; Tics = 3; Next state = "ARTI_INVU1"; } State { ID = "ARTI_PWBK1"; Sprite = "PWBK"; Frame = 0; Tics = 350; Next state = "ARTI_PWBK1"; } State { ID = "ARTI_EGGC1"; Sprite = "EGGC"; Frame = 0; Tics = 6; Next state = "ARTI_EGGC2"; } State { ID = "ARTI_EGGC2"; Sprite = "EGGC"; Frame = 1; Tics = 6; Next state = "ARTI_EGGC3"; } State { ID = "ARTI_EGGC3"; Sprite = "EGGC"; Frame = 2; Tics = 6; Next state = "ARTI_EGGC4"; } State { ID = "ARTI_EGGC4"; Sprite = "EGGC"; Frame = 1; Tics = 6; Next state = "ARTI_EGGC1"; } State { ID = "EGGFX1"; Sprite = "EGGM"; Frame = 0; Tics = 4; Next state = "EGGFX2"; } State { ID = "EGGFX2"; Sprite = "EGGM"; Frame = 1; Tics = 4; Next state = "EGGFX3"; } State { ID = "EGGFX3"; Sprite = "EGGM"; Frame = 2; Tics = 4; Next state = "EGGFX4"; } State { ID = "EGGFX4"; Sprite = "EGGM"; Frame = 3; Tics = 4; Next state = "EGGFX5"; } State { ID = "EGGFX5"; Sprite = "EGGM"; Frame = 4; Tics = 4; Next state = "EGGFX1"; } State { ID = "EGGFXI1_1"; Sprite = "FX01"; Frame = 32772; Tics = 3; Next state = "EGGFXI1_2"; } State { ID = "EGGFXI1_2"; Sprite = "FX01"; Frame = 32773; Tics = 3; Next state = "EGGFXI1_3"; } State { ID = "EGGFXI1_3"; Sprite = "FX01"; Frame = 32774; Tics = 3; Next state = "EGGFXI1_4"; } State { ID = "EGGFXI1_4"; Sprite = "FX01"; Frame = 32775; Tics = 3; Next state = "NULL"; } State { ID = "ARTI_SPHL1"; Sprite = "SPHL"; Frame = 0; Tics = 350; Next state = "ARTI_SPHL1"; } State { ID = "ARTI_TRCH1"; Sprite = "TRCH"; Frame = 32768; Tics = 3; Next state = "ARTI_TRCH2"; } State { ID = "ARTI_TRCH2"; Sprite = "TRCH"; Frame = 32769; Tics = 3; Next state = "ARTI_TRCH3"; } State { ID = "ARTI_TRCH3"; Sprite = "TRCH"; Frame = 32770; Tics = 3; Next state = "ARTI_TRCH1"; } State { ID = "ARTI_FBMB1"; Sprite = "FBMB"; Frame = 4; Tics = 350; Next state = "ARTI_FBMB1"; } State { ID = "FIREBOMB1"; Sprite = "FBMB"; Frame = 0; Tics = 10; Next state = "FIREBOMB2"; } State { ID = "FIREBOMB2"; Sprite = "FBMB"; Frame = 1; Tics = 10; Next state = "FIREBOMB3"; } State { ID = "FIREBOMB3"; Sprite = "FBMB"; Frame = 2; Tics = 10; Next state = "FIREBOMB4"; } State { ID = "FIREBOMB4"; Sprite = "FBMB"; Frame = 3; Tics = 10; Next state = "FIREBOMB5"; } State { ID = "FIREBOMB5"; Sprite = "FBMB"; Frame = 4; Tics = 6; Action = "A_Scream"; Next state = "FIREBOMB6"; } State { ID = "FIREBOMB6"; Sprite = "XPL1"; Frame = 32768; Tics = 4; Action = "A_Explode"; Next state = "FIREBOMB7"; } State { ID = "FIREBOMB7"; Sprite = "XPL1"; Frame = 32769; Tics = 4; Next state = "FIREBOMB8"; } State { ID = "FIREBOMB8"; Sprite = "XPL1"; Frame = 32770; Tics = 4; Next state = "FIREBOMB9"; } State { ID = "FIREBOMB9"; Sprite = "XPL1"; Frame = 32771; Tics = 4; Next state = "FIREBOMB10"; } State { ID = "FIREBOMB10"; Sprite = "XPL1"; Frame = 32772; Tics = 4; Next state = "FIREBOMB11"; } State { ID = "FIREBOMB11"; Sprite = "XPL1"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "ARTI_ATLP1"; Sprite = "ATLP"; Frame = 0; Tics = 4; Next state = "ARTI_ATLP2"; } State { ID = "ARTI_ATLP2"; Sprite = "ATLP"; Frame = 1; Tics = 4; Next state = "ARTI_ATLP3"; } State { ID = "ARTI_ATLP3"; Sprite = "ATLP"; Frame = 2; Tics = 4; Next state = "ARTI_ATLP4"; } State { ID = "ARTI_ATLP4"; Sprite = "ATLP"; Frame = 1; Tics = 4; Next state = "ARTI_ATLP1"; } State { ID = "POD_WAIT1"; Sprite = "PPOD"; Frame = 0; Tics = 10; Next state = "POD_WAIT1"; } State { ID = "POD_PAIN1"; Sprite = "PPOD"; Frame = 1; Tics = 14; Action = "A_PodPain"; Next state = "POD_WAIT1"; } State { ID = "POD_DIE1"; Sprite = "PPOD"; Frame = 32770; Tics = 5; Action = "A_RemovePod"; Next state = "POD_DIE2"; } State { ID = "POD_DIE2"; Sprite = "PPOD"; Frame = 32771; Tics = 5; Action = "A_Scream"; Next state = "POD_DIE3"; } State { ID = "POD_DIE3"; Sprite = "PPOD"; Frame = 32772; Tics = 5; Action = "A_Explode"; Next state = "POD_DIE4"; } State { ID = "POD_DIE4"; Sprite = "PPOD"; Frame = 32773; Tics = 10; Next state = "FREETARGMOBJ"; } State { ID = "POD_GROW1"; Sprite = "PPOD"; Frame = 8; Tics = 3; Next state = "POD_GROW2"; } State { ID = "POD_GROW2"; Sprite = "PPOD"; Frame = 9; Tics = 3; Next state = "POD_GROW3"; } State { ID = "POD_GROW3"; Sprite = "PPOD"; Frame = 10; Tics = 3; Next state = "POD_GROW4"; } State { ID = "POD_GROW4"; Sprite = "PPOD"; Frame = 11; Tics = 3; Next state = "POD_GROW5"; } State { ID = "POD_GROW5"; Sprite = "PPOD"; Frame = 12; Tics = 3; Next state = "POD_GROW6"; } State { ID = "POD_GROW6"; Sprite = "PPOD"; Frame = 13; Tics = 3; Next state = "POD_GROW7"; } State { ID = "POD_GROW7"; Sprite = "PPOD"; Frame = 14; Tics = 3; Next state = "POD_GROW8"; } State { ID = "POD_GROW8"; Sprite = "PPOD"; Frame = 15; Tics = 3; Next state = "POD_WAIT1"; } State { ID = "PODGOO1"; Sprite = "PPOD"; Frame = 6; Tics = 8; Next state = "PODGOO2"; } State { ID = "PODGOO2"; Sprite = "PPOD"; Frame = 7; Tics = 8; Next state = "PODGOO1"; } State { ID = "PODGOOX"; Sprite = "PPOD"; Frame = 6; Tics = 10; Next state = "NULL"; } State { ID = "PODGENERATOR"; Sprite = "AMG1"; Frame = 0; Tics = 35; Action = "A_MakePod"; Next state = "PODGENERATOR"; } State { ID = "SPLASH1"; Sprite = "SPSH"; Frame = 0; Tics = 8; Next state = "SPLASH2"; } State { ID = "SPLASH2"; Sprite = "SPSH"; Frame = 1; Tics = 8; Next state = "SPLASH3"; } State { ID = "SPLASH3"; Sprite = "SPSH"; Frame = 2; Tics = 8; Next state = "SPLASH4"; } State { ID = "SPLASH4"; Sprite = "SPSH"; Frame = 3; Tics = 16; Next state = "NULL"; } State { ID = "SPLASHX"; Sprite = "SPSH"; Frame = 3; Tics = 10; Next state = "NULL"; } State { ID = "SPLASHBASE1"; Sprite = "SPSH"; Frame = 4; Tics = 5; Next state = "SPLASHBASE2"; } State { ID = "SPLASHBASE2"; Sprite = "SPSH"; Frame = 5; Tics = 5; Next state = "SPLASHBASE3"; } State { ID = "SPLASHBASE3"; Sprite = "SPSH"; Frame = 6; Tics = 5; Next state = "SPLASHBASE4"; } State { ID = "SPLASHBASE4"; Sprite = "SPSH"; Frame = 7; Tics = 5; Next state = "SPLASHBASE5"; } State { ID = "SPLASHBASE5"; Sprite = "SPSH"; Frame = 8; Tics = 5; Next state = "SPLASHBASE6"; } State { ID = "SPLASHBASE6"; Sprite = "SPSH"; Frame = 9; Tics = 5; Next state = "SPLASHBASE7"; } State { ID = "SPLASHBASE7"; Sprite = "SPSH"; Frame = 10; Tics = 5; Next state = "NULL"; } State { ID = "LAVASPLASH1"; Sprite = "LVAS"; Frame = 32768; Tics = 5; Next state = "LAVASPLASH2"; } State { ID = "LAVASPLASH2"; Sprite = "LVAS"; Frame = 32769; Tics = 5; Next state = "LAVASPLASH3"; } State { ID = "LAVASPLASH3"; Sprite = "LVAS"; Frame = 32770; Tics = 5; Next state = "LAVASPLASH4"; } State { ID = "LAVASPLASH4"; Sprite = "LVAS"; Frame = 32771; Tics = 5; Next state = "LAVASPLASH5"; } State { ID = "LAVASPLASH5"; Sprite = "LVAS"; Frame = 32772; Tics = 5; Next state = "LAVASPLASH6"; } State { ID = "LAVASPLASH6"; Sprite = "LVAS"; Frame = 32773; Tics = 5; Next state = "NULL"; } State { ID = "LAVASMOKE1"; Sprite = "LVAS"; Frame = 6; Tics = 5; Next state = "LAVASMOKE2"; } State { ID = "LAVASMOKE2"; Sprite = "LVAS"; Frame = 7; Tics = 5; Next state = "LAVASMOKE3"; } State { ID = "LAVASMOKE3"; Sprite = "LVAS"; Frame = 8; Tics = 5; Next state = "LAVASMOKE4"; } State { ID = "LAVASMOKE4"; Sprite = "LVAS"; Frame = 9; Tics = 5; Next state = "LAVASMOKE5"; } State { ID = "LAVASMOKE5"; Sprite = "LVAS"; Frame = 10; Tics = 5; Next state = "NULL"; } State { ID = "SLUDGECHUNK1"; Sprite = "SLDG"; Frame = 0; Tics = 8; Next state = "SLUDGECHUNK2"; } State { ID = "SLUDGECHUNK2"; Sprite = "SLDG"; Frame = 1; Tics = 8; Next state = "SLUDGECHUNK3"; } State { ID = "SLUDGECHUNK3"; Sprite = "SLDG"; Frame = 2; Tics = 8; Next state = "SLUDGECHUNK4"; } State { ID = "SLUDGECHUNK4"; Sprite = "SLDG"; Frame = 3; Tics = 8; Next state = "NULL"; } State { ID = "SLUDGECHUNKX"; Sprite = "SLDG"; Frame = 3; Tics = 6; Next state = "NULL"; } State { ID = "SLUDGESPLASH1"; Sprite = "SLDG"; Frame = 4; Tics = 5; Next state = "SLUDGESPLASH2"; } State { ID = "SLUDGESPLASH2"; Sprite = "SLDG"; Frame = 5; Tics = 5; Next state = "SLUDGESPLASH3"; } State { ID = "SLUDGESPLASH3"; Sprite = "SLDG"; Frame = 6; Tics = 5; Next state = "SLUDGESPLASH4"; } State { ID = "SLUDGESPLASH4"; Sprite = "SLDG"; Frame = 7; Tics = 5; Next state = "NULL"; } State { ID = "SKULLHANG70_1"; Sprite = "SKH1"; Frame = 0; Tics = 70; Next state = "SKULLHANG70_2"; } State { ID = "SKULLHANG60_1"; Sprite = "SKH2"; Frame = 0; Tics = 64; Next state = "SKULLHANG60_2"; } State { ID = "SKULLHANG45_1"; Sprite = "SKH3"; Frame = 0; Tics = 75; Next state = "SKULLHANG45_2"; } State { ID = "SKULLHANG35_1"; Sprite = "SKH4"; Frame = 0; Tics = 60; Next state = "SKULLHANG35_2"; } State { ID = "CHANDELIER1"; Sprite = "CHDL"; Frame = 32768; Tics = 4; Next state = "CHANDELIER2"; } State { ID = "CHANDELIER2"; Sprite = "CHDL"; Frame = 32769; Tics = 4; Next state = "CHANDELIER3"; } State { ID = "CHANDELIER3"; Sprite = "CHDL"; Frame = 32770; Tics = 4; Next state = "CHANDELIER1"; } State { ID = "SERPTORCH1"; Sprite = "SRTC"; Frame = 32768; Tics = 4; Next state = "SERPTORCH2"; } State { ID = "SERPTORCH2"; Sprite = "SRTC"; Frame = 32769; Tics = 4; Next state = "SERPTORCH3"; } State { ID = "SERPTORCH3"; Sprite = "SRTC"; Frame = 32770; Tics = 4; Next state = "SERPTORCH1"; } State { ID = "SMALLPILLAR"; Sprite = "SMPL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "STALAGMITESMALL"; Sprite = "STGS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "STALAGMITELARGE"; Sprite = "STGL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "STALACTITESMALL"; Sprite = "STCS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "STALACTITELARGE"; Sprite = "STCL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FIREBRAZIER1"; Sprite = "KFR1"; Frame = 32768; Tics = 3; Next state = "FIREBRAZIER2"; } State { ID = "FIREBRAZIER2"; Sprite = "KFR1"; Frame = 32769; Tics = 3; Next state = "FIREBRAZIER3"; } State { ID = "FIREBRAZIER3"; Sprite = "KFR1"; Frame = 32770; Tics = 3; Next state = "FIREBRAZIER4"; } State { ID = "FIREBRAZIER4"; Sprite = "KFR1"; Frame = 32771; Tics = 3; Next state = "FIREBRAZIER5"; } State { ID = "FIREBRAZIER5"; Sprite = "KFR1"; Frame = 32772; Tics = 3; Next state = "FIREBRAZIER6"; } State { ID = "FIREBRAZIER6"; Sprite = "KFR1"; Frame = 32773; Tics = 3; Next state = "FIREBRAZIER7"; } State { ID = "FIREBRAZIER7"; Sprite = "KFR1"; Frame = 32774; Tics = 3; Next state = "FIREBRAZIER8"; } State { ID = "FIREBRAZIER8"; Sprite = "KFR1"; Frame = 32775; Tics = 3; Next state = "FIREBRAZIER1"; } State { ID = "BARREL"; Sprite = "BARL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BRPILLAR"; Sprite = "BRPL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MOSS1"; Sprite = "MOS1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MOSS2"; Sprite = "MOS2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "WALLTORCH1"; Sprite = "WTRH"; Frame = 32768; Tics = 16; Next state = "WALLTORCH2"; } State { ID = "WALLTORCH2"; Sprite = "WTRH"; Frame = 32769; Tics = 16; Next state = "WALLTORCH3"; } State { ID = "WALLTORCH3"; Sprite = "WTRH"; Frame = 32770; Tics = 16; Next state = "WALLTORCH1"; } State { ID = "HANGINGCORPSE"; Sprite = "HCOR"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEYGIZMO1"; Sprite = "KGZ1"; Frame = 0; Tics = 1; Next state = "KEYGIZMO2"; } State { ID = "KEYGIZMO2"; Sprite = "KGZ1"; Frame = 0; Tics = 1; Action = "A_InitKeyGizmo"; Next state = "KEYGIZMO3"; } State { ID = "KEYGIZMO3"; Sprite = "KGZ1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KGZ_START"; Sprite = "KGZB"; Frame = 0; Tics = 1; Next state = "KGZ_START"; } State { ID = "KGZ_BLUEFLOAT1"; Sprite = "KGZB"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "KGZ_GREENFLOAT1"; Sprite = "KGZG"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "KGZ_YELLOWFLOAT1"; Sprite = "KGZY"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "VOLCANO1"; Sprite = "VLCO"; Frame = 0; Tics = 350; Next state = "VOLCANO2"; } State { ID = "VOLCANO2"; Sprite = "VLCO"; Frame = 0; Tics = 35; Action = "A_VolcanoSet"; Next state = "VOLCANO3"; } State { ID = "VOLCANO3"; Sprite = "VLCO"; Frame = 1; Tics = 3; Next state = "VOLCANO4"; } State { ID = "VOLCANO4"; Sprite = "VLCO"; Frame = 2; Tics = 3; Next state = "VOLCANO5"; } State { ID = "VOLCANO5"; Sprite = "VLCO"; Frame = 3; Tics = 3; Next state = "VOLCANO6"; } State { ID = "VOLCANO6"; Sprite = "VLCO"; Frame = 1; Tics = 3; Next state = "VOLCANO7"; } State { ID = "VOLCANO7"; Sprite = "VLCO"; Frame = 2; Tics = 3; Next state = "VOLCANO8"; } State { ID = "VOLCANO8"; Sprite = "VLCO"; Frame = 3; Tics = 3; Next state = "VOLCANO9"; } State { ID = "VOLCANO9"; Sprite = "VLCO"; Frame = 4; Tics = 10; Action = "A_VolcanoBlast"; Next state = "VOLCANO2"; } State { ID = "VOLCANOBALL1"; Sprite = "VFBL"; Frame = 32768; Tics = 4; Action = "A_BeastPuff"; Next state = "VOLCANOBALL2"; } State { ID = "VOLCANOBALL2"; Sprite = "VFBL"; Frame = 32769; Tics = 4; Action = "A_BeastPuff"; Next state = "VOLCANOBALL1"; } State { ID = "VOLCANOBALLX1"; Sprite = "XPL1"; Frame = 0; Tics = 4; Action = "A_VolcBallImpact"; Next state = "VOLCANOBALLX2"; } State { ID = "VOLCANOBALLX2"; Sprite = "XPL1"; Frame = 32769; Tics = 4; Next state = "VOLCANOBALLX3"; } State { ID = "VOLCANOBALLX3"; Sprite = "XPL1"; Frame = 32770; Tics = 4; Next state = "VOLCANOBALLX4"; } State { ID = "VOLCANOBALLX4"; Sprite = "XPL1"; Frame = 32771; Tics = 4; Next state = "VOLCANOBALLX5"; } State { ID = "VOLCANOBALLX5"; Sprite = "XPL1"; Frame = 32772; Tics = 4; Next state = "VOLCANOBALLX6"; } State { ID = "VOLCANOBALLX6"; Sprite = "XPL1"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "VOLCANOTBALL1"; Sprite = "VTFB"; Frame = 0; Tics = 4; Next state = "VOLCANOTBALL2"; } State { ID = "VOLCANOTBALL2"; Sprite = "VTFB"; Frame = 1; Tics = 4; Next state = "VOLCANOTBALL1"; } State { ID = "VOLCANOTBALLX1"; Sprite = "SFFI"; Frame = 32770; Tics = 4; Next state = "VOLCANOTBALLX2"; } State { ID = "VOLCANOTBALLX2"; Sprite = "SFFI"; Frame = 32769; Tics = 4; Next state = "VOLCANOTBALLX3"; } State { ID = "VOLCANOTBALLX3"; Sprite = "SFFI"; Frame = 32768; Tics = 4; Next state = "VOLCANOTBALLX4"; } State { ID = "VOLCANOTBALLX4"; Sprite = "SFFI"; Frame = 32769; Tics = 4; Next state = "VOLCANOTBALLX5"; } State { ID = "VOLCANOTBALLX5"; Sprite = "SFFI"; Frame = 32770; Tics = 4; Next state = "VOLCANOTBALLX6"; } State { ID = "VOLCANOTBALLX6"; Sprite = "SFFI"; Frame = 32771; Tics = 4; Next state = "VOLCANOTBALLX7"; } State { ID = "VOLCANOTBALLX7"; Sprite = "SFFI"; Frame = 32772; Tics = 4; Next state = "NULL"; } State { ID = "TELEGLITGEN1"; Sprite = "TGLT"; Frame = 0; Tics = 8; Action = "A_SpawnTeleGlitter"; Next state = "TELEGLITGEN1"; } State { ID = "TELEGLITGEN2"; Sprite = "TGLT"; Frame = 5; Tics = 8; Action = "A_SpawnTeleGlitter2"; Next state = "TELEGLITGEN2"; } State { ID = "TELEGLITTER1_1"; Sprite = "TGLT"; Frame = 32768; Tics = 2; Next state = "TELEGLITTER1_2"; } State { ID = "TELEGLITTER1_2"; Sprite = "TGLT"; Frame = 32769; Tics = 2; Action = "A_AccTeleGlitter"; Next state = "TELEGLITTER1_3"; } State { ID = "TELEGLITTER1_3"; Sprite = "TGLT"; Frame = 32770; Tics = 2; Next state = "TELEGLITTER1_4"; } State { ID = "TELEGLITTER1_4"; Sprite = "TGLT"; Frame = 32771; Tics = 2; Action = "A_AccTeleGlitter"; Next state = "TELEGLITTER1_5"; } State { ID = "TELEGLITTER1_5"; Sprite = "TGLT"; Frame = 32772; Tics = 2; Next state = "TELEGLITTER1_1"; } State { ID = "TELEGLITTER2_1"; Sprite = "TGLT"; Frame = 32773; Tics = 2; Next state = "TELEGLITTER2_2"; } State { ID = "TELEGLITTER2_2"; Sprite = "TGLT"; Frame = 32774; Tics = 2; Action = "A_AccTeleGlitter"; Next state = "TELEGLITTER2_3"; } State { ID = "TELEGLITTER2_3"; Sprite = "TGLT"; Frame = 32775; Tics = 2; Next state = "TELEGLITTER2_4"; } State { ID = "TELEGLITTER2_4"; Sprite = "TGLT"; Frame = 32776; Tics = 2; Action = "A_AccTeleGlitter"; Next state = "TELEGLITTER2_5"; } State { ID = "TELEGLITTER2_5"; Sprite = "TGLT"; Frame = 32777; Tics = 2; Next state = "TELEGLITTER2_1"; } State { ID = "TFOG1"; Sprite = "TELE"; Frame = 32768; Tics = 6; Next state = "TFOG2"; } State { ID = "TFOG2"; Sprite = "TELE"; Frame = 32769; Tics = 6; Next state = "TFOG3"; } State { ID = "TFOG3"; Sprite = "TELE"; Frame = 32770; Tics = 6; Next state = "TFOG4"; } State { ID = "TFOG4"; Sprite = "TELE"; Frame = 32771; Tics = 6; Next state = "TFOG5"; } State { ID = "TFOG5"; Sprite = "TELE"; Frame = 32772; Tics = 6; Next state = "TFOG6"; } State { ID = "TFOG6"; Sprite = "TELE"; Frame = 32773; Tics = 6; Next state = "TFOG7"; } State { ID = "TFOG7"; Sprite = "TELE"; Frame = 32774; Tics = 6; Next state = "TFOG8"; } State { ID = "TFOG8"; Sprite = "TELE"; Frame = 32775; Tics = 6; Next state = "TFOG9"; } State { ID = "TFOG9"; Sprite = "TELE"; Frame = 32774; Tics = 6; Next state = "TFOG10"; } State { ID = "TFOG10"; Sprite = "TELE"; Frame = 32773; Tics = 6; Next state = "TFOG11"; } State { ID = "TFOG11"; Sprite = "TELE"; Frame = 32772; Tics = 6; Next state = "TFOG12"; } State { ID = "TFOG12"; Sprite = "TELE"; Frame = 32771; Tics = 6; Next state = "TFOG13"; } State { ID = "TFOG13"; Sprite = "TELE"; Frame = 32770; Tics = 6; Next state = "NULL"; } State { ID = "LIGHTDONE"; Sprite = "STFF"; Frame = 0; Tics = 0; Action = "A_Light0"; Next state = "NULL"; } State { ID = "STAFFREADY"; Sprite = "STFF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "STAFFREADY"; } State { ID = "STAFFDOWN"; Sprite = "STFF"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "STAFFDOWN"; } State { ID = "STAFFUP"; Sprite = "STFF"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "STAFFUP"; } State { ID = "STAFFREADY2_1"; Sprite = "STFF"; Frame = 32771; Tics = 4; Action = "A_WeaponReady"; Next state = "STAFFREADY2_2"; } State { ID = "STAFFREADY2_2"; Sprite = "STFF"; Frame = 32772; Tics = 4; Action = "A_WeaponReady"; Next state = "STAFFREADY2_3"; } State { ID = "STAFFREADY2_3"; Sprite = "STFF"; Frame = 32773; Tics = 4; Action = "A_WeaponReady"; Next state = "STAFFREADY2_1"; } State { ID = "STAFFDOWN2"; Sprite = "STFF"; Frame = 32771; Tics = 1; Action = "A_Lower"; Next state = "STAFFDOWN2"; } State { ID = "STAFFUP2"; Sprite = "STFF"; Frame = 32771; Tics = 1; Action = "A_Raise"; Next state = "STAFFUP2"; } State { ID = "STAFFATK1_1"; Sprite = "STFF"; Frame = 1; Tics = 6; Next state = "STAFFATK1_2"; } State { ID = "STAFFATK1_2"; Sprite = "STFF"; Frame = 2; Tics = 8; Action = "A_StaffAttackPL1"; Next state = "STAFFATK1_3"; } State { ID = "STAFFATK1_3"; Sprite = "STFF"; Frame = 1; Tics = 8; Action = "A_ReFire"; Next state = "STAFFREADY"; } State { ID = "STAFFATK2_1"; Sprite = "STFF"; Frame = 32774; Tics = 6; Next state = "STAFFATK2_2"; } State { ID = "STAFFATK2_2"; Sprite = "STFF"; Frame = 32775; Tics = 8; Action = "A_StaffAttackPL2"; Next state = "STAFFATK2_3"; } State { ID = "STAFFATK2_3"; Sprite = "STFF"; Frame = 32774; Tics = 8; Action = "A_ReFire"; Next state = "STAFFREADY2_1"; } State { ID = "STAFFPUFF1"; Sprite = "PUF3"; Frame = 32768; Tics = 4; Next state = "STAFFPUFF2"; } State { ID = "STAFFPUFF2"; Sprite = "PUF3"; Frame = 1; Tics = 4; Next state = "STAFFPUFF3"; } State { ID = "STAFFPUFF3"; Sprite = "PUF3"; Frame = 2; Tics = 4; Next state = "STAFFPUFF4"; } State { ID = "STAFFPUFF4"; Sprite = "PUF3"; Frame = 3; Tics = 4; Next state = "NULL"; } State { ID = "STAFFPUFF2_1"; Sprite = "PUF4"; Frame = 32768; Tics = 4; Next state = "STAFFPUFF2_2"; } State { ID = "STAFFPUFF2_2"; Sprite = "PUF4"; Frame = 32769; Tics = 4; Next state = "STAFFPUFF2_3"; } State { ID = "STAFFPUFF2_3"; Sprite = "PUF4"; Frame = 32770; Tics = 4; Next state = "STAFFPUFF2_4"; } State { ID = "STAFFPUFF2_4"; Sprite = "PUF4"; Frame = 32771; Tics = 4; Next state = "STAFFPUFF2_5"; } State { ID = "STAFFPUFF2_5"; Sprite = "PUF4"; Frame = 32772; Tics = 4; Next state = "STAFFPUFF2_6"; } State { ID = "STAFFPUFF2_6"; Sprite = "PUF4"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "BEAKREADY"; Sprite = "BEAK"; Frame = 0; Tics = 1; Action = "A_BeakReady"; Next state = "BEAKREADY"; } State { ID = "BEAKDOWN"; Sprite = "BEAK"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "BEAKDOWN"; } State { ID = "BEAKUP"; Sprite = "BEAK"; Frame = 0; Tics = 1; Action = "A_BeakRaise"; Next state = "BEAKUP"; } State { ID = "BEAKATK1_1"; Sprite = "BEAK"; Frame = 0; Tics = 18; Action = "A_BeakAttackPL1"; Next state = "BEAKREADY"; } State { ID = "BEAKATK2_1"; Sprite = "BEAK"; Frame = 0; Tics = 12; Action = "A_BeakAttackPL2"; Next state = "BEAKREADY"; } State { ID = "WGNT"; Sprite = "WGNT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "GAUNTLETREADY"; Sprite = "GAUN"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "GAUNTLETREADY"; } State { ID = "GAUNTLETDOWN"; Sprite = "GAUN"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "GAUNTLETDOWN"; } State { ID = "GAUNTLETUP"; Sprite = "GAUN"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "GAUNTLETUP"; } State { ID = "GAUNTLETREADY2_1"; Sprite = "GAUN"; Frame = 6; Tics = 4; Action = "A_WeaponReady"; Next state = "GAUNTLETREADY2_2"; } State { ID = "GAUNTLETREADY2_2"; Sprite = "GAUN"; Frame = 7; Tics = 4; Action = "A_WeaponReady"; Next state = "GAUNTLETREADY2_3"; } State { ID = "GAUNTLETREADY2_3"; Sprite = "GAUN"; Frame = 8; Tics = 4; Action = "A_WeaponReady"; Next state = "GAUNTLETREADY2_1"; } State { ID = "GAUNTLETDOWN2"; Sprite = "GAUN"; Frame = 6; Tics = 1; Action = "A_Lower"; Next state = "GAUNTLETDOWN2"; } State { ID = "GAUNTLETUP2"; Sprite = "GAUN"; Frame = 6; Tics = 1; Action = "A_Raise"; Next state = "GAUNTLETUP2"; } State { ID = "GAUNTLETATK1_1"; Sprite = "GAUN"; Frame = 1; Tics = 4; Next state = "GAUNTLETATK1_2"; } State { ID = "GAUNTLETATK1_2"; Sprite = "GAUN"; Frame = 2; Tics = 4; Next state = "GAUNTLETATK1_3"; } State { ID = "GAUNTLETATK1_3"; Sprite = "GAUN"; Frame = 32771; Tics = 4; Action = "A_GauntletAttack"; Next state = "GAUNTLETATK1_4"; } State { ID = "GAUNTLETATK1_4"; Sprite = "GAUN"; Frame = 32772; Tics = 4; Action = "A_GauntletAttack"; Next state = "GAUNTLETATK1_5"; } State { ID = "GAUNTLETATK1_5"; Sprite = "GAUN"; Frame = 32773; Tics = 4; Action = "A_GauntletAttack"; Next state = "GAUNTLETATK1_6"; } State { ID = "GAUNTLETATK1_6"; Sprite = "GAUN"; Frame = 2; Tics = 4; Action = "A_ReFire"; Next state = "GAUNTLETATK1_7"; } State { ID = "GAUNTLETATK1_7"; Sprite = "GAUN"; Frame = 1; Tics = 4; Action = "A_Light0"; Next state = "GAUNTLETREADY"; } State { ID = "GAUNTLETATK2_1"; Sprite = "GAUN"; Frame = 9; Tics = 4; Next state = "GAUNTLETATK2_2"; } State { ID = "GAUNTLETATK2_2"; Sprite = "GAUN"; Frame = 10; Tics = 4; Next state = "GAUNTLETATK2_3"; } State { ID = "GAUNTLETATK2_3"; Sprite = "GAUN"; Frame = 32779; Tics = 4; Action = "A_GauntletAttack"; Next state = "GAUNTLETATK2_4"; } State { ID = "GAUNTLETATK2_4"; Sprite = "GAUN"; Frame = 32780; Tics = 4; Action = "A_GauntletAttack"; Next state = "GAUNTLETATK2_5"; } State { ID = "GAUNTLETATK2_5"; Sprite = "GAUN"; Frame = 32781; Tics = 4; Action = "A_GauntletAttack"; Next state = "GAUNTLETATK2_6"; } State { ID = "GAUNTLETATK2_6"; Sprite = "GAUN"; Frame = 10; Tics = 4; Action = "A_ReFire"; Next state = "GAUNTLETATK2_7"; } State { ID = "GAUNTLETATK2_7"; Sprite = "GAUN"; Frame = 9; Tics = 4; Action = "A_Light0"; Next state = "GAUNTLETREADY2_1"; } State { ID = "GAUNTLETPUFF1_1"; Sprite = "PUF1"; Frame = 32768; Tics = 4; Next state = "GAUNTLETPUFF1_2"; } State { ID = "GAUNTLETPUFF1_2"; Sprite = "PUF1"; Frame = 32769; Tics = 4; Next state = "GAUNTLETPUFF1_3"; } State { ID = "GAUNTLETPUFF1_3"; Sprite = "PUF1"; Frame = 32770; Tics = 4; Next state = "GAUNTLETPUFF1_4"; } State { ID = "GAUNTLETPUFF1_4"; Sprite = "PUF1"; Frame = 32771; Tics = 4; Next state = "NULL"; } State { ID = "GAUNTLETPUFF2_1"; Sprite = "PUF1"; Frame = 32772; Tics = 4; Next state = "GAUNTLETPUFF2_2"; } State { ID = "GAUNTLETPUFF2_2"; Sprite = "PUF1"; Frame = 32773; Tics = 4; Next state = "GAUNTLETPUFF2_3"; } State { ID = "GAUNTLETPUFF2_3"; Sprite = "PUF1"; Frame = 32774; Tics = 4; Next state = "GAUNTLETPUFF2_4"; } State { ID = "GAUNTLETPUFF2_4"; Sprite = "PUF1"; Frame = 32775; Tics = 4; Next state = "NULL"; } State { ID = "BLSR"; Sprite = "WBLS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BLASTERREADY"; Sprite = "BLSR"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "BLASTERREADY"; } State { ID = "BLASTERDOWN"; Sprite = "BLSR"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "BLASTERDOWN"; } State { ID = "BLASTERUP"; Sprite = "BLSR"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "BLASTERUP"; } State { ID = "BLASTERATK1_1"; Sprite = "BLSR"; Frame = 1; Tics = 3; Next state = "BLASTERATK1_2"; } State { ID = "BLASTERATK1_2"; Sprite = "BLSR"; Frame = 32770; Tics = 3; Next state = "BLASTERATK1_3"; } State { ID = "BLASTERATK1_3"; Sprite = "BLSR"; Frame = 32771; Tics = 2; Action = "A_FireBlasterPL1"; Next state = "BLASTERATK1_4"; } State { ID = "BLASTERATK1_4"; Sprite = "BLSR"; Frame = 32770; Tics = 2; Next state = "BLASTERATK1_5"; } State { ID = "BLASTERATK1_5"; Sprite = "BLSR"; Frame = 1; Tics = 2; Next state = "BLASTERATK1_6"; } State { ID = "BLASTERATK1_6"; Sprite = "BLSR"; Frame = 0; Tics = 0; Action = "A_ReFire"; Next state = "BLASTERREADY"; } State { ID = "BLASTERATK2_1"; Sprite = "BLSR"; Frame = 1; Tics = 0; Next state = "BLASTERATK2_2"; } State { ID = "BLASTERATK2_2"; Sprite = "BLSR"; Frame = 32770; Tics = 0; Next state = "BLASTERATK2_3"; } State { ID = "BLASTERATK2_3"; Sprite = "BLSR"; Frame = 32771; Tics = 3; Action = "A_FireBlasterPL2"; Next state = "BLASTERATK2_4"; } State { ID = "BLASTERATK2_4"; Sprite = "BLSR"; Frame = 32770; Tics = 4; Next state = "BLASTERATK2_5"; } State { ID = "BLASTERATK2_5"; Sprite = "BLSR"; Frame = 1; Tics = 4; Next state = "BLASTERATK2_6"; } State { ID = "BLASTERATK2_6"; Sprite = "BLSR"; Frame = 0; Tics = 0; Action = "A_ReFire"; Next state = "BLASTERREADY"; } State { ID = "BLASTERFX1_1"; Sprite = "ACLO"; Frame = 4; Tics = 200; Next state = "BLASTERFX1_1"; } State { ID = "BLASTERFXI1_1"; Sprite = "FX18"; Frame = 32768; Tics = 3; Action = "A_SpawnRippers"; Next state = "BLASTERFXI1_2"; } State { ID = "BLASTERFXI1_2"; Sprite = "FX18"; Frame = 32769; Tics = 3; Next state = "BLASTERFXI1_3"; } State { ID = "BLASTERFXI1_3"; Sprite = "FX18"; Frame = 32770; Tics = 4; Next state = "BLASTERFXI1_4"; } State { ID = "BLASTERFXI1_4"; Sprite = "FX18"; Frame = 32771; Tics = 4; Next state = "BLASTERFXI1_5"; } State { ID = "BLASTERFXI1_5"; Sprite = "FX18"; Frame = 32772; Tics = 4; Next state = "BLASTERFXI1_6"; } State { ID = "BLASTERFXI1_6"; Sprite = "FX18"; Frame = 32773; Tics = 4; Next state = "BLASTERFXI1_7"; } State { ID = "BLASTERFXI1_7"; Sprite = "FX18"; Frame = 32774; Tics = 4; Next state = "NULL"; } State { ID = "BLASTERSMOKE1"; Sprite = "FX18"; Frame = 7; Tics = 4; Next state = "BLASTERSMOKE2"; } State { ID = "BLASTERSMOKE2"; Sprite = "FX18"; Frame = 8; Tics = 4; Next state = "BLASTERSMOKE3"; } State { ID = "BLASTERSMOKE3"; Sprite = "FX18"; Frame = 9; Tics = 4; Next state = "BLASTERSMOKE4"; } State { ID = "BLASTERSMOKE4"; Sprite = "FX18"; Frame = 10; Tics = 4; Next state = "BLASTERSMOKE5"; } State { ID = "BLASTERSMOKE5"; Sprite = "FX18"; Frame = 11; Tics = 4; Next state = "NULL"; } State { ID = "RIPPER1"; Sprite = "FX18"; Frame = 12; Tics = 4; Next state = "RIPPER2"; } State { ID = "RIPPER2"; Sprite = "FX18"; Frame = 13; Tics = 5; Next state = "RIPPER1"; } State { ID = "RIPPERX1"; Sprite = "FX18"; Frame = 32782; Tics = 4; Next state = "RIPPERX2"; } State { ID = "RIPPERX2"; Sprite = "FX18"; Frame = 32783; Tics = 4; Next state = "RIPPERX3"; } State { ID = "RIPPERX3"; Sprite = "FX18"; Frame = 32784; Tics = 4; Next state = "RIPPERX4"; } State { ID = "RIPPERX4"; Sprite = "FX18"; Frame = 32785; Tics = 4; Next state = "RIPPERX5"; } State { ID = "RIPPERX5"; Sprite = "FX18"; Frame = 32786; Tics = 4; Next state = "NULL"; } State { ID = "BLASTERPUFF1_1"; Sprite = "FX17"; Frame = 32768; Tics = 4; Next state = "BLASTERPUFF1_2"; } State { ID = "BLASTERPUFF1_2"; Sprite = "FX17"; Frame = 32769; Tics = 4; Next state = "BLASTERPUFF1_3"; } State { ID = "BLASTERPUFF1_3"; Sprite = "FX17"; Frame = 32770; Tics = 4; Next state = "BLASTERPUFF1_4"; } State { ID = "BLASTERPUFF1_4"; Sprite = "FX17"; Frame = 32771; Tics = 4; Next state = "BLASTERPUFF1_5"; } State { ID = "BLASTERPUFF1_5"; Sprite = "FX17"; Frame = 32772; Tics = 4; Next state = "NULL"; } State { ID = "BLASTERPUFF2_1"; Sprite = "FX17"; Frame = 32773; Tics = 3; Next state = "BLASTERPUFF2_2"; } State { ID = "BLASTERPUFF2_2"; Sprite = "FX17"; Frame = 32774; Tics = 3; Next state = "BLASTERPUFF2_3"; } State { ID = "BLASTERPUFF2_3"; Sprite = "FX17"; Frame = 32775; Tics = 4; Next state = "BLASTERPUFF2_4"; } State { ID = "BLASTERPUFF2_4"; Sprite = "FX17"; Frame = 32776; Tics = 4; Next state = "BLASTERPUFF2_5"; } State { ID = "BLASTERPUFF2_5"; Sprite = "FX17"; Frame = 32777; Tics = 4; Next state = "BLASTERPUFF2_6"; } State { ID = "BLASTERPUFF2_6"; Sprite = "FX17"; Frame = 32778; Tics = 4; Next state = "BLASTERPUFF2_7"; } State { ID = "BLASTERPUFF2_7"; Sprite = "FX17"; Frame = 32779; Tics = 4; Next state = "NULL"; } State { ID = "WMCE"; Sprite = "WMCE"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MACEREADY"; Sprite = "MACE"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MACEREADY"; } State { ID = "MACEDOWN"; Sprite = "MACE"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "MACEDOWN"; } State { ID = "MACEUP"; Sprite = "MACE"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "MACEUP"; } State { ID = "MACEATK1_1"; Sprite = "MACE"; Frame = 1; Tics = 4; Next state = "MACEATK1_2"; } State { ID = "MACEATK1_2"; Sprite = "MACE"; Frame = 2; Tics = 3; Action = "A_FireMacePL1"; Next state = "MACEATK1_3"; } State { ID = "MACEATK1_3"; Sprite = "MACE"; Frame = 3; Tics = 3; Action = "A_FireMacePL1"; Next state = "MACEATK1_4"; } State { ID = "MACEATK1_4"; Sprite = "MACE"; Frame = 4; Tics = 3; Action = "A_FireMacePL1"; Next state = "MACEATK1_5"; } State { ID = "MACEATK1_5"; Sprite = "MACE"; Frame = 5; Tics = 3; Action = "A_FireMacePL1"; Next state = "MACEATK1_6"; } State { ID = "MACEATK1_6"; Sprite = "MACE"; Frame = 2; Tics = 4; Action = "A_ReFire"; Next state = "MACEATK1_7"; } State { ID = "MACEATK1_7"; Sprite = "MACE"; Frame = 3; Tics = 4; Next state = "MACEATK1_8"; } State { ID = "MACEATK1_8"; Sprite = "MACE"; Frame = 4; Tics = 4; Next state = "MACEATK1_9"; } State { ID = "MACEATK1_9"; Sprite = "MACE"; Frame = 5; Tics = 4; Next state = "MACEATK1_10"; } State { ID = "MACEATK1_10"; Sprite = "MACE"; Frame = 1; Tics = 4; Next state = "MACEREADY"; } State { ID = "MACEATK2_1"; Sprite = "MACE"; Frame = 1; Tics = 4; Next state = "MACEATK2_2"; } State { ID = "MACEATK2_2"; Sprite = "MACE"; Frame = 3; Tics = 4; Action = "A_FireMacePL2"; Next state = "MACEATK2_3"; } State { ID = "MACEATK2_3"; Sprite = "MACE"; Frame = 1; Tics = 4; Next state = "MACEATK2_4"; } State { ID = "MACEATK2_4"; Sprite = "MACE"; Frame = 0; Tics = 8; Action = "A_ReFire"; Next state = "MACEREADY"; } State { ID = "MACEFX1_1"; Sprite = "FX02"; Frame = 0; Tics = 4; Action = "A_MacePL1Check"; Next state = "MACEFX1_2"; } State { ID = "MACEFX1_2"; Sprite = "FX02"; Frame = 1; Tics = 4; Action = "A_MacePL1Check"; Next state = "MACEFX1_1"; } State { ID = "MACEFXI1_1"; Sprite = "FX02"; Frame = 32773; Tics = 4; Action = "A_MaceBallImpact"; Next state = "MACEFXI1_2"; } State { ID = "MACEFXI1_2"; Sprite = "FX02"; Frame = 32774; Tics = 4; Next state = "MACEFXI1_3"; } State { ID = "MACEFXI1_3"; Sprite = "FX02"; Frame = 32775; Tics = 4; Next state = "MACEFXI1_4"; } State { ID = "MACEFXI1_4"; Sprite = "FX02"; Frame = 32776; Tics = 4; Next state = "MACEFXI1_5"; } State { ID = "MACEFXI1_5"; Sprite = "FX02"; Frame = 32777; Tics = 4; Next state = "NULL"; } State { ID = "MACEFX2_1"; Sprite = "FX02"; Frame = 2; Tics = 4; Next state = "MACEFX2_2"; } State { ID = "MACEFX2_2"; Sprite = "FX02"; Frame = 3; Tics = 4; Next state = "MACEFX2_1"; } State { ID = "MACEFXI2_1"; Sprite = "FX02"; Frame = 32773; Tics = 4; Action = "A_MaceBallImpact2"; Next state = "MACEFXI1_2"; } State { ID = "MACEFX3_1"; Sprite = "FX02"; Frame = 0; Tics = 4; Next state = "MACEFX3_2"; } State { ID = "MACEFX3_2"; Sprite = "FX02"; Frame = 1; Tics = 4; Next state = "MACEFX3_1"; } State { ID = "MACEFX4_1"; Sprite = "FX02"; Frame = 4; Tics = 99; Next state = "MACEFX4_1"; } State { ID = "MACEFXI4_1"; Sprite = "FX02"; Frame = 32770; Tics = 4; Action = "A_DeathBallImpact"; Next state = "MACEFXI1_2"; } State { ID = "WSKL"; Sprite = "WSKL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HORNRODREADY"; Sprite = "HROD"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "HORNRODREADY"; } State { ID = "HORNRODDOWN"; Sprite = "HROD"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "HORNRODDOWN"; } State { ID = "HORNRODUP"; Sprite = "HROD"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "HORNRODUP"; } State { ID = "HORNRODATK1_1"; Sprite = "HROD"; Frame = 32768; Tics = 4; Action = "A_FireSkullRodPL1"; Next state = "HORNRODATK1_2"; } State { ID = "HORNRODATK1_2"; Sprite = "HROD"; Frame = 32769; Tics = 4; Action = "A_FireSkullRodPL1"; Next state = "HORNRODATK1_3"; } State { ID = "HORNRODATK1_3"; Sprite = "HROD"; Frame = 1; Tics = 0; Action = "A_ReFire"; Next state = "HORNRODREADY"; } State { ID = "HORNRODATK2_1"; Sprite = "HROD"; Frame = 2; Tics = 2; Next state = "HORNRODATK2_2"; } State { ID = "HORNRODATK2_2"; Sprite = "HROD"; Frame = 3; Tics = 3; Next state = "HORNRODATK2_3"; } State { ID = "HORNRODATK2_3"; Sprite = "HROD"; Frame = 4; Tics = 2; Next state = "HORNRODATK2_4"; } State { ID = "HORNRODATK2_4"; Sprite = "HROD"; Frame = 5; Tics = 3; Next state = "HORNRODATK2_5"; } State { ID = "HORNRODATK2_5"; Sprite = "HROD"; Frame = 32774; Tics = 4; Action = "A_FireSkullRodPL2"; Next state = "HORNRODATK2_6"; } State { ID = "HORNRODATK2_6"; Sprite = "HROD"; Frame = 5; Tics = 2; Next state = "HORNRODATK2_7"; } State { ID = "HORNRODATK2_7"; Sprite = "HROD"; Frame = 4; Tics = 3; Next state = "HORNRODATK2_8"; } State { ID = "HORNRODATK2_8"; Sprite = "HROD"; Frame = 3; Tics = 2; Next state = "HORNRODATK2_9"; } State { ID = "HORNRODATK2_9"; Sprite = "HROD"; Frame = 2; Tics = 2; Action = "A_ReFire"; Next state = "HORNRODREADY"; } State { ID = "HRODFX1_1"; Sprite = "FX00"; Frame = 32768; Tics = 6; Next state = "HRODFX1_2"; } State { ID = "HRODFX1_2"; Sprite = "FX00"; Frame = 32769; Tics = 6; Next state = "HRODFX1_1"; } State { ID = "HRODFXI1_1"; Sprite = "FX00"; Frame = 32775; Tics = 5; Next state = "HRODFXI1_2"; } State { ID = "HRODFXI1_2"; Sprite = "FX00"; Frame = 32776; Tics = 5; Next state = "HRODFXI1_3"; } State { ID = "HRODFXI1_3"; Sprite = "FX00"; Frame = 32777; Tics = 4; Next state = "HRODFXI1_4"; } State { ID = "HRODFXI1_4"; Sprite = "FX00"; Frame = 32778; Tics = 4; Next state = "HRODFXI1_5"; } State { ID = "HRODFXI1_5"; Sprite = "FX00"; Frame = 32779; Tics = 3; Next state = "HRODFXI1_6"; } State { ID = "HRODFXI1_6"; Sprite = "FX00"; Frame = 32780; Tics = 3; Next state = "NULL"; } State { ID = "HRODFX2_1"; Sprite = "FX00"; Frame = 32770; Tics = 3; Next state = "HRODFX2_2"; } State { ID = "HRODFX2_2"; Sprite = "FX00"; Frame = 32771; Tics = 3; Action = "A_SkullRodPL2Seek"; Next state = "HRODFX2_3"; } State { ID = "HRODFX2_3"; Sprite = "FX00"; Frame = 32772; Tics = 3; Next state = "HRODFX2_4"; } State { ID = "HRODFX2_4"; Sprite = "FX00"; Frame = 32773; Tics = 3; Action = "A_SkullRodPL2Seek"; Next state = "HRODFX2_1"; } State { ID = "HRODFXI2_1"; Sprite = "FX00"; Frame = 32775; Tics = 5; Action = "A_AddPlayerRain"; Next state = "HRODFXI2_2"; } State { ID = "HRODFXI2_2"; Sprite = "FX00"; Frame = 32776; Tics = 5; Next state = "HRODFXI2_3"; } State { ID = "HRODFXI2_3"; Sprite = "FX00"; Frame = 32777; Tics = 4; Next state = "HRODFXI2_4"; } State { ID = "HRODFXI2_4"; Sprite = "FX00"; Frame = 32778; Tics = 3; Next state = "HRODFXI2_5"; } State { ID = "HRODFXI2_5"; Sprite = "FX00"; Frame = 32779; Tics = 3; Next state = "HRODFXI2_6"; } State { ID = "HRODFXI2_6"; Sprite = "FX00"; Frame = 32780; Tics = 3; Next state = "HRODFXI2_7"; } State { ID = "HRODFXI2_7"; Sprite = "FX00"; Frame = 6; Tics = 1; Action = "A_HideInCeiling"; Next state = "HRODFXI2_8"; } State { ID = "HRODFXI2_8"; Sprite = "FX00"; Frame = 6; Tics = 1; Action = "A_SkullRodStorm"; Next state = "HRODFXI2_8"; } State { ID = "RAINPLR1_1"; Sprite = "FX20"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "RAINPLR2_1"; Sprite = "FX21"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "RAINPLR3_1"; Sprite = "FX22"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "RAINPLR4_1"; Sprite = "FX23"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "RAINPLR1X_1"; Sprite = "FX20"; Frame = 32769; Tics = 4; Action = "A_RainImpact"; Next state = "RAINPLR1X_2"; } State { ID = "RAINPLR1X_2"; Sprite = "FX20"; Frame = 32770; Tics = 4; Next state = "RAINPLR1X_3"; } State { ID = "RAINPLR1X_3"; Sprite = "FX20"; Frame = 32771; Tics = 4; Next state = "RAINPLR1X_4"; } State { ID = "RAINPLR1X_4"; Sprite = "FX20"; Frame = 32772; Tics = 4; Next state = "RAINPLR1X_5"; } State { ID = "RAINPLR1X_5"; Sprite = "FX20"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "RAINPLR2X_1"; Sprite = "FX21"; Frame = 32769; Tics = 4; Action = "A_RainImpact"; Next state = "RAINPLR2X_2"; } State { ID = "RAINPLR2X_2"; Sprite = "FX21"; Frame = 32770; Tics = 4; Next state = "RAINPLR2X_3"; } State { ID = "RAINPLR2X_3"; Sprite = "FX21"; Frame = 32771; Tics = 4; Next state = "RAINPLR2X_4"; } State { ID = "RAINPLR2X_4"; Sprite = "FX21"; Frame = 32772; Tics = 4; Next state = "RAINPLR2X_5"; } State { ID = "RAINPLR2X_5"; Sprite = "FX21"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "RAINPLR3X_1"; Sprite = "FX22"; Frame = 32769; Tics = 4; Action = "A_RainImpact"; Next state = "RAINPLR3X_2"; } State { ID = "RAINPLR3X_2"; Sprite = "FX22"; Frame = 32770; Tics = 4; Next state = "RAINPLR3X_3"; } State { ID = "RAINPLR3X_3"; Sprite = "FX22"; Frame = 32771; Tics = 4; Next state = "RAINPLR3X_4"; } State { ID = "RAINPLR3X_4"; Sprite = "FX22"; Frame = 32772; Tics = 4; Next state = "RAINPLR3X_5"; } State { ID = "RAINPLR3X_5"; Sprite = "FX22"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "RAINPLR4X_1"; Sprite = "FX23"; Frame = 32769; Tics = 4; Action = "A_RainImpact"; Next state = "RAINPLR4X_2"; } State { ID = "RAINPLR4X_2"; Sprite = "FX23"; Frame = 32770; Tics = 4; Next state = "RAINPLR4X_3"; } State { ID = "RAINPLR4X_3"; Sprite = "FX23"; Frame = 32771; Tics = 4; Next state = "RAINPLR4X_4"; } State { ID = "RAINPLR4X_4"; Sprite = "FX23"; Frame = 32772; Tics = 4; Next state = "RAINPLR4X_5"; } State { ID = "RAINPLR4X_5"; Sprite = "FX23"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "RAINAIRXPLR1_1"; Sprite = "FX20"; Frame = 32774; Tics = 4; Next state = "RAINAIRXPLR1_2"; } State { ID = "RAINAIRXPLR2_1"; Sprite = "FX21"; Frame = 32774; Tics = 4; Next state = "RAINAIRXPLR2_2"; } State { ID = "RAINAIRXPLR3_1"; Sprite = "FX22"; Frame = 32774; Tics = 4; Next state = "RAINAIRXPLR3_2"; } State { ID = "RAINAIRXPLR4_1"; Sprite = "FX23"; Frame = 32774; Tics = 4; Next state = "RAINAIRXPLR4_2"; } State { ID = "RAINAIRXPLR1_2"; Sprite = "FX20"; Frame = 32775; Tics = 4; Next state = "RAINAIRXPLR1_3"; } State { ID = "RAINAIRXPLR2_2"; Sprite = "FX21"; Frame = 32775; Tics = 4; Next state = "RAINAIRXPLR2_3"; } State { ID = "RAINAIRXPLR3_2"; Sprite = "FX22"; Frame = 32775; Tics = 4; Next state = "RAINAIRXPLR3_3"; } State { ID = "RAINAIRXPLR4_2"; Sprite = "FX23"; Frame = 32775; Tics = 4; Next state = "RAINAIRXPLR4_3"; } State { ID = "RAINAIRXPLR1_3"; Sprite = "FX20"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "RAINAIRXPLR2_3"; Sprite = "FX21"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "RAINAIRXPLR3_3"; Sprite = "FX22"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "RAINAIRXPLR4_3"; Sprite = "FX23"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "GOLDWANDREADY"; Sprite = "GWND"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "GOLDWANDREADY"; } State { ID = "GOLDWANDDOWN"; Sprite = "GWND"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "GOLDWANDDOWN"; } State { ID = "GOLDWANDUP"; Sprite = "GWND"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "GOLDWANDUP"; } State { ID = "GOLDWANDATK1_1"; Sprite = "GWND"; Frame = 1; Tics = 3; Next state = "GOLDWANDATK1_2"; } State { ID = "GOLDWANDATK1_2"; Sprite = "GWND"; Frame = 32770; Tics = 5; Action = "A_FireGoldWandPL1"; Next state = "GOLDWANDATK1_3"; } State { ID = "GOLDWANDATK1_3"; Sprite = "GWND"; Frame = 3; Tics = 3; Next state = "GOLDWANDATK1_4"; } State { ID = "GOLDWANDATK1_4"; Sprite = "GWND"; Frame = 3; Tics = 0; Action = "A_ReFire"; Next state = "GOLDWANDREADY"; } State { ID = "GOLDWANDATK2_1"; Sprite = "GWND"; Frame = 1; Tics = 3; Next state = "GOLDWANDATK2_2"; } State { ID = "GOLDWANDATK2_2"; Sprite = "GWND"; Frame = 32770; Tics = 4; Action = "A_FireGoldWandPL2"; Next state = "GOLDWANDATK2_3"; } State { ID = "GOLDWANDATK2_3"; Sprite = "GWND"; Frame = 3; Tics = 3; Next state = "GOLDWANDATK2_4"; } State { ID = "GOLDWANDATK2_4"; Sprite = "GWND"; Frame = 3; Tics = 0; Action = "A_ReFire"; Next state = "GOLDWANDREADY"; } State { ID = "GWANDFX1_1"; Sprite = "FX01"; Frame = 32768; Tics = 6; Next state = "GWANDFX1_2"; } State { ID = "GWANDFX1_2"; Sprite = "FX01"; Frame = 32769; Tics = 6; Next state = "GWANDFX1_1"; } State { ID = "GWANDFXI1_1"; Sprite = "FX01"; Frame = 32772; Tics = 3; Next state = "GWANDFXI1_2"; } State { ID = "GWANDFXI1_2"; Sprite = "FX01"; Frame = 32773; Tics = 3; Next state = "GWANDFXI1_3"; } State { ID = "GWANDFXI1_3"; Sprite = "FX01"; Frame = 32774; Tics = 3; Next state = "GWANDFXI1_4"; } State { ID = "GWANDFXI1_4"; Sprite = "FX01"; Frame = 32775; Tics = 3; Next state = "NULL"; } State { ID = "GWANDFX2_1"; Sprite = "FX01"; Frame = 32770; Tics = 6; Next state = "GWANDFX2_2"; } State { ID = "GWANDFX2_2"; Sprite = "FX01"; Frame = 32771; Tics = 6; Next state = "GWANDFX2_1"; } State { ID = "GWANDPUFF1_1"; Sprite = "PUF2"; Frame = 32768; Tics = 3; Next state = "GWANDPUFF1_2"; } State { ID = "GWANDPUFF1_2"; Sprite = "PUF2"; Frame = 32769; Tics = 3; Next state = "GWANDPUFF1_3"; } State { ID = "GWANDPUFF1_3"; Sprite = "PUF2"; Frame = 32770; Tics = 3; Next state = "GWANDPUFF1_4"; } State { ID = "GWANDPUFF1_4"; Sprite = "PUF2"; Frame = 32771; Tics = 3; Next state = "GWANDPUFF1_5"; } State { ID = "GWANDPUFF1_5"; Sprite = "PUF2"; Frame = 32772; Tics = 3; Next state = "NULL"; } State { ID = "WPHX"; Sprite = "WPHX"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PHOENIXREADY"; Sprite = "PHNX"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PHOENIXREADY"; } State { ID = "PHOENIXDOWN"; Sprite = "PHNX"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PHOENIXDOWN"; } State { ID = "PHOENIXUP"; Sprite = "PHNX"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PHOENIXUP"; } State { ID = "PHOENIXATK1_1"; Sprite = "PHNX"; Frame = 1; Tics = 5; Next state = "PHOENIXATK1_2"; } State { ID = "PHOENIXATK1_2"; Sprite = "PHNX"; Frame = 32770; Tics = 7; Action = "A_FirePhoenixPL1"; Next state = "PHOENIXATK1_3"; } State { ID = "PHOENIXATK1_3"; Sprite = "PHNX"; Frame = 32771; Tics = 4; Next state = "PHOENIXATK1_4"; } State { ID = "PHOENIXATK1_4"; Sprite = "PHNX"; Frame = 1; Tics = 4; Next state = "PHOENIXATK1_5"; } State { ID = "PHOENIXATK1_5"; Sprite = "PHNX"; Frame = 1; Tics = 0; Action = "A_ReFire"; Next state = "PHOENIXREADY"; } State { ID = "PHOENIXATK2_1"; Sprite = "PHNX"; Frame = 1; Tics = 3; Action = "A_InitPhoenixPL2"; Next state = "PHOENIXATK2_2"; } State { ID = "PHOENIXATK2_2"; Sprite = "PHNX"; Frame = 32770; Tics = 1; Action = "A_FirePhoenixPL2"; Next state = "PHOENIXATK2_3"; } State { ID = "PHOENIXATK2_3"; Sprite = "PHNX"; Frame = 1; Tics = 4; Action = "A_ReFire"; Next state = "PHOENIXATK2_4"; } State { ID = "PHOENIXATK2_4"; Sprite = "PHNX"; Frame = 1; Tics = 4; Action = "A_ShutdownPhoenixPL2"; Next state = "PHOENIXREADY"; } State { ID = "PHOENIXFX1_1"; Sprite = "FX04"; Frame = 32768; Tics = 4; Action = "A_PhoenixPuff"; Next state = "PHOENIXFX1_1"; } State { ID = "PHOENIXFXI1_1"; Sprite = "FX08"; Frame = 32768; Tics = 6; Action = "A_Explode"; Next state = "PHOENIXFXI1_2"; } State { ID = "PHOENIXFXI1_2"; Sprite = "FX08"; Frame = 32769; Tics = 5; Next state = "PHOENIXFXI1_3"; } State { ID = "PHOENIXFXI1_3"; Sprite = "FX08"; Frame = 32770; Tics = 5; Next state = "PHOENIXFXI1_4"; } State { ID = "PHOENIXFXI1_4"; Sprite = "FX08"; Frame = 32771; Tics = 4; Next state = "PHOENIXFXI1_5"; } State { ID = "PHOENIXFXI1_5"; Sprite = "FX08"; Frame = 32772; Tics = 4; Next state = "PHOENIXFXI1_6"; } State { ID = "PHOENIXFXI1_6"; Sprite = "FX08"; Frame = 32773; Tics = 4; Next state = "PHOENIXFXI1_7"; } State { ID = "PHOENIXFXI1_7"; Sprite = "FX08"; Frame = 32774; Tics = 4; Next state = "PHOENIXFXI1_8"; } State { ID = "PHOENIXFXI1_8"; Sprite = "FX08"; Frame = 32775; Tics = 4; Next state = "NULL"; } State { ID = "PHOENIXPUFF1"; Sprite = "FX04"; Frame = 1; Tics = 4; Next state = "PHOENIXPUFF2"; } State { ID = "PHOENIXPUFF2"; Sprite = "FX04"; Frame = 2; Tics = 4; Next state = "PHOENIXPUFF3"; } State { ID = "PHOENIXPUFF3"; Sprite = "FX04"; Frame = 3; Tics = 4; Next state = "PHOENIXPUFF4"; } State { ID = "PHOENIXPUFF4"; Sprite = "FX04"; Frame = 4; Tics = 4; Next state = "PHOENIXPUFF5"; } State { ID = "PHOENIXPUFF5"; Sprite = "FX04"; Frame = 5; Tics = 4; Next state = "NULL"; } State { ID = "PHOENIXFX2_1"; Sprite = "FX09"; Frame = 32768; Tics = 2; Next state = "PHOENIXFX2_2"; } State { ID = "PHOENIXFX2_2"; Sprite = "FX09"; Frame = 32769; Tics = 2; Next state = "PHOENIXFX2_3"; } State { ID = "PHOENIXFX2_3"; Sprite = "FX09"; Frame = 32768; Tics = 2; Next state = "PHOENIXFX2_4"; } State { ID = "PHOENIXFX2_4"; Sprite = "FX09"; Frame = 32769; Tics = 2; Next state = "PHOENIXFX2_5"; } State { ID = "PHOENIXFX2_5"; Sprite = "FX09"; Frame = 32768; Tics = 2; Next state = "PHOENIXFX2_6"; } State { ID = "PHOENIXFX2_6"; Sprite = "FX09"; Frame = 32769; Tics = 2; Action = "A_FlameEnd"; Next state = "PHOENIXFX2_7"; } State { ID = "PHOENIXFX2_7"; Sprite = "FX09"; Frame = 32770; Tics = 2; Next state = "PHOENIXFX2_8"; } State { ID = "PHOENIXFX2_8"; Sprite = "FX09"; Frame = 32771; Tics = 2; Next state = "PHOENIXFX2_9"; } State { ID = "PHOENIXFX2_9"; Sprite = "FX09"; Frame = 32772; Tics = 2; Next state = "PHOENIXFX2_10"; } State { ID = "PHOENIXFX2_10"; Sprite = "FX09"; Frame = 32773; Tics = 2; Next state = "NULL"; } State { ID = "PHOENIXFXI2_1"; Sprite = "FX09"; Frame = 32774; Tics = 3; Next state = "PHOENIXFXI2_2"; } State { ID = "PHOENIXFXI2_2"; Sprite = "FX09"; Frame = 32775; Tics = 3; Action = "A_FloatPuff"; Next state = "PHOENIXFXI2_3"; } State { ID = "PHOENIXFXI2_3"; Sprite = "FX09"; Frame = 32776; Tics = 4; Next state = "PHOENIXFXI2_4"; } State { ID = "PHOENIXFXI2_4"; Sprite = "FX09"; Frame = 32777; Tics = 5; Next state = "PHOENIXFXI2_5"; } State { ID = "PHOENIXFXI2_5"; Sprite = "FX09"; Frame = 32778; Tics = 5; Next state = "NULL"; } State { ID = "WBOW"; Sprite = "WBOW"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CRBOW1"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW2"; } State { ID = "CRBOW2"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW3"; } State { ID = "CRBOW3"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW4"; } State { ID = "CRBOW4"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW5"; } State { ID = "CRBOW5"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW6"; } State { ID = "CRBOW6"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW7"; } State { ID = "CRBOW7"; Sprite = "CRBW"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW8"; } State { ID = "CRBOW8"; Sprite = "CRBW"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW9"; } State { ID = "CRBOW9"; Sprite = "CRBW"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW10"; } State { ID = "CRBOW10"; Sprite = "CRBW"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW11"; } State { ID = "CRBOW11"; Sprite = "CRBW"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW12"; } State { ID = "CRBOW12"; Sprite = "CRBW"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW13"; } State { ID = "CRBOW13"; Sprite = "CRBW"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW14"; } State { ID = "CRBOW14"; Sprite = "CRBW"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW15"; } State { ID = "CRBOW15"; Sprite = "CRBW"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW16"; } State { ID = "CRBOW16"; Sprite = "CRBW"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW17"; } State { ID = "CRBOW17"; Sprite = "CRBW"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW18"; } State { ID = "CRBOW18"; Sprite = "CRBW"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CRBOW1"; } State { ID = "CRBOWDOWN"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "CRBOWDOWN"; } State { ID = "CRBOWUP"; Sprite = "CRBW"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "CRBOWUP"; } State { ID = "CRBOWATK1_1"; Sprite = "CRBW"; Frame = 32771; Tics = 6; Action = "A_FireCrossbowPL1"; Next state = "CRBOWATK1_2"; } State { ID = "CRBOWATK1_2"; Sprite = "CRBW"; Frame = 4; Tics = 3; Next state = "CRBOWATK1_3"; } State { ID = "CRBOWATK1_3"; Sprite = "CRBW"; Frame = 5; Tics = 3; Next state = "CRBOWATK1_4"; } State { ID = "CRBOWATK1_4"; Sprite = "CRBW"; Frame = 6; Tics = 3; Next state = "CRBOWATK1_5"; } State { ID = "CRBOWATK1_5"; Sprite = "CRBW"; Frame = 7; Tics = 3; Next state = "CRBOWATK1_6"; } State { ID = "CRBOWATK1_6"; Sprite = "CRBW"; Frame = 0; Tics = 4; Next state = "CRBOWATK1_7"; } State { ID = "CRBOWATK1_7"; Sprite = "CRBW"; Frame = 1; Tics = 4; Next state = "CRBOWATK1_8"; } State { ID = "CRBOWATK1_8"; Sprite = "CRBW"; Frame = 2; Tics = 5; Action = "A_ReFire"; Next state = "CRBOW1"; } State { ID = "CRBOWATK2_1"; Sprite = "CRBW"; Frame = 32771; Tics = 5; Action = "A_FireCrossbowPL2"; Next state = "CRBOWATK2_2"; } State { ID = "CRBOWATK2_2"; Sprite = "CRBW"; Frame = 4; Tics = 3; Next state = "CRBOWATK2_3"; } State { ID = "CRBOWATK2_3"; Sprite = "CRBW"; Frame = 5; Tics = 2; Next state = "CRBOWATK2_4"; } State { ID = "CRBOWATK2_4"; Sprite = "CRBW"; Frame = 6; Tics = 3; Next state = "CRBOWATK2_5"; } State { ID = "CRBOWATK2_5"; Sprite = "CRBW"; Frame = 7; Tics = 2; Next state = "CRBOWATK2_6"; } State { ID = "CRBOWATK2_6"; Sprite = "CRBW"; Frame = 0; Tics = 3; Next state = "CRBOWATK2_7"; } State { ID = "CRBOWATK2_7"; Sprite = "CRBW"; Frame = 1; Tics = 3; Next state = "CRBOWATK2_8"; } State { ID = "CRBOWATK2_8"; Sprite = "CRBW"; Frame = 2; Tics = 4; Action = "A_ReFire"; Next state = "CRBOW1"; } State { ID = "CRBOWFX1"; Sprite = "FX03"; Frame = 32769; Tics = 1; Next state = "CRBOWFX1"; } State { ID = "CRBOWFXI1_1"; Sprite = "FX03"; Frame = 32775; Tics = 8; Next state = "CRBOWFXI1_2"; } State { ID = "CRBOWFXI1_2"; Sprite = "FX03"; Frame = 32776; Tics = 8; Next state = "CRBOWFXI1_3"; } State { ID = "CRBOWFXI1_3"; Sprite = "FX03"; Frame = 32777; Tics = 8; Next state = "NULL"; } State { ID = "CRBOWFX2"; Sprite = "FX03"; Frame = 32769; Tics = 1; Action = "A_BoltSpark"; Next state = "CRBOWFX2"; } State { ID = "CRBOWFX3"; Sprite = "FX03"; Frame = 32768; Tics = 1; Next state = "CRBOWFX3"; } State { ID = "CRBOWFXI3_1"; Sprite = "FX03"; Frame = 32770; Tics = 8; Next state = "CRBOWFXI3_2"; } State { ID = "CRBOWFXI3_2"; Sprite = "FX03"; Frame = 32771; Tics = 8; Next state = "CRBOWFXI3_3"; } State { ID = "CRBOWFXI3_3"; Sprite = "FX03"; Frame = 32772; Tics = 8; Next state = "NULL"; } State { ID = "CRBOWFX4_1"; Sprite = "FX03"; Frame = 32773; Tics = 8; Next state = "CRBOWFX4_2"; } State { ID = "CRBOWFX4_2"; Sprite = "FX03"; Frame = 32774; Tics = 8; Next state = "NULL"; } State { ID = "BLOOD1"; Sprite = "BLOD"; Frame = 2; Tics = 8; Next state = "BLOOD2"; } State { ID = "BLOOD2"; Sprite = "BLOD"; Frame = 1; Tics = 8; Next state = "BLOOD3"; } State { ID = "BLOOD3"; Sprite = "BLOD"; Frame = 0; Tics = 8; Next state = "NULL"; } State { ID = "BLOODSPLATTER1"; Sprite = "BLOD"; Frame = 2; Tics = 8; Next state = "BLOODSPLATTER2"; } State { ID = "BLOODSPLATTER2"; Sprite = "BLOD"; Frame = 1; Tics = 8; Next state = "BLOODSPLATTER3"; } State { ID = "BLOODSPLATTER3"; Sprite = "BLOD"; Frame = 0; Tics = 8; Next state = "NULL"; } State { ID = "BLOODSPLATTERX"; Sprite = "BLOD"; Frame = 0; Tics = 6; Next state = "NULL"; } State { ID = "PLAY"; Sprite = "PLAY"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PLAY_RUN1"; Sprite = "PLAY"; Frame = 0; Tics = 4; Next state = "PLAY_RUN2"; } State { ID = "PLAY_RUN2"; Sprite = "PLAY"; Frame = 1; Tics = 4; Next state = "PLAY_RUN3"; } State { ID = "PLAY_RUN3"; Sprite = "PLAY"; Frame = 2; Tics = 4; Next state = "PLAY_RUN4"; } State { ID = "PLAY_RUN4"; Sprite = "PLAY"; Frame = 3; Tics = 4; Next state = "PLAY_RUN1"; } State { ID = "PLAY_ATK1"; Sprite = "PLAY"; Frame = 4; Tics = 12; Next state = "PLAY"; } State { ID = "PLAY_ATK2"; Sprite = "PLAY"; Frame = 32773; Tics = 6; Next state = "PLAY_ATK1"; } State { ID = "PLAY_PAIN"; Sprite = "PLAY"; Frame = 6; Tics = 4; Next state = "PLAY_PAIN2"; } State { ID = "PLAY_PAIN2"; Sprite = "PLAY"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "PLAY"; } State { ID = "PLAY_DIE1"; Sprite = "PLAY"; Frame = 7; Tics = 6; Next state = "PLAY_DIE2"; } State { ID = "PLAY_DIE2"; Sprite = "PLAY"; Frame = 8; Tics = 6; Action = "A_Scream"; Next state = "PLAY_DIE3"; } State { ID = "PLAY_DIE3"; Sprite = "PLAY"; Frame = 9; Tics = 6; Next state = "PLAY_DIE4"; } State { ID = "PLAY_DIE4"; Sprite = "PLAY"; Frame = 10; Tics = 6; Next state = "PLAY_DIE5"; } State { ID = "PLAY_DIE5"; Sprite = "PLAY"; Frame = 11; Tics = 6; Action = "A_NoBlocking"; Next state = "PLAY_DIE6"; } State { ID = "PLAY_DIE6"; Sprite = "PLAY"; Frame = 12; Tics = 6; Next state = "PLAY_DIE7"; } State { ID = "PLAY_DIE7"; Sprite = "PLAY"; Frame = 13; Tics = 6; Next state = "PLAY_DIE8"; } State { ID = "PLAY_DIE8"; Sprite = "PLAY"; Frame = 14; Tics = 6; Next state = "PLAY_DIE9"; } State { ID = "PLAY_DIE9"; Sprite = "PLAY"; Frame = 15; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "PLAY_XDIE1"; Sprite = "PLAY"; Frame = 16; Tics = 5; Action = "A_Scream"; Next state = "PLAY_XDIE2"; } State { ID = "PLAY_XDIE2"; Sprite = "PLAY"; Frame = 17; Tics = 5; Action = "A_SkullPop"; Next state = "PLAY_XDIE3"; } State { ID = "PLAY_XDIE3"; Sprite = "PLAY"; Frame = 18; Tics = 5; Action = "A_NoBlocking"; Next state = "PLAY_XDIE4"; } State { ID = "PLAY_XDIE4"; Sprite = "PLAY"; Frame = 19; Tics = 5; Next state = "PLAY_XDIE5"; } State { ID = "PLAY_XDIE5"; Sprite = "PLAY"; Frame = 20; Tics = 5; Next state = "PLAY_XDIE6"; } State { ID = "PLAY_XDIE6"; Sprite = "PLAY"; Frame = 21; Tics = 5; Next state = "PLAY_XDIE7"; } State { ID = "PLAY_XDIE7"; Sprite = "PLAY"; Frame = 22; Tics = 5; Next state = "PLAY_XDIE8"; } State { ID = "PLAY_XDIE8"; Sprite = "PLAY"; Frame = 23; Tics = 5; Next state = "PLAY_XDIE9"; } State { ID = "PLAY_XDIE9"; Sprite = "PLAY"; Frame = 24; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "PLAY_FDTH1"; Sprite = "FDTH"; Frame = 32768; Tics = 5; Action = "A_FlameSnd"; Next state = "PLAY_FDTH2"; } State { ID = "PLAY_FDTH2"; Sprite = "FDTH"; Frame = 32769; Tics = 4; Next state = "PLAY_FDTH3"; } State { ID = "PLAY_FDTH3"; Sprite = "FDTH"; Frame = 32770; Tics = 5; Next state = "PLAY_FDTH4"; } State { ID = "PLAY_FDTH4"; Sprite = "FDTH"; Frame = 32771; Tics = 4; Action = "A_Scream"; Next state = "PLAY_FDTH5"; } State { ID = "PLAY_FDTH5"; Sprite = "FDTH"; Frame = 32772; Tics = 5; Next state = "PLAY_FDTH6"; } State { ID = "PLAY_FDTH6"; Sprite = "FDTH"; Frame = 32773; Tics = 4; Next state = "PLAY_FDTH7"; } State { ID = "PLAY_FDTH7"; Sprite = "FDTH"; Frame = 32774; Tics = 5; Action = "A_FlameSnd"; Next state = "PLAY_FDTH8"; } State { ID = "PLAY_FDTH8"; Sprite = "FDTH"; Frame = 32775; Tics = 4; Next state = "PLAY_FDTH9"; } State { ID = "PLAY_FDTH9"; Sprite = "FDTH"; Frame = 32776; Tics = 5; Next state = "PLAY_FDTH10"; } State { ID = "PLAY_FDTH10"; Sprite = "FDTH"; Frame = 32777; Tics = 4; Next state = "PLAY_FDTH11"; } State { ID = "PLAY_FDTH11"; Sprite = "FDTH"; Frame = 32778; Tics = 5; Next state = "PLAY_FDTH12"; } State { ID = "PLAY_FDTH12"; Sprite = "FDTH"; Frame = 32779; Tics = 4; Next state = "PLAY_FDTH13"; } State { ID = "PLAY_FDTH13"; Sprite = "FDTH"; Frame = 32780; Tics = 5; Next state = "PLAY_FDTH14"; } State { ID = "PLAY_FDTH14"; Sprite = "FDTH"; Frame = 32781; Tics = 4; Next state = "PLAY_FDTH15"; } State { ID = "PLAY_FDTH15"; Sprite = "FDTH"; Frame = 32782; Tics = 5; Action = "A_NoBlocking"; Next state = "PLAY_FDTH16"; } State { ID = "PLAY_FDTH16"; Sprite = "FDTH"; Frame = 32783; Tics = 4; Next state = "PLAY_FDTH17"; } State { ID = "PLAY_FDTH17"; Sprite = "FDTH"; Frame = 32784; Tics = 5; Next state = "PLAY_FDTH18"; } State { ID = "PLAY_FDTH18"; Sprite = "FDTH"; Frame = 32785; Tics = 4; Next state = "PLAY_FDTH19"; } State { ID = "PLAY_FDTH19"; Sprite = "ACLO"; Frame = 4; Tics = 35; Action = "A_CheckBurnGone"; Next state = "PLAY_FDTH19"; } State { ID = "PLAY_FDTH20"; Sprite = "ACLO"; Frame = 4; Tics = 8; Next state = "NULL"; } State { ID = "BLOODYSKULL1"; Sprite = "BSKL"; Frame = 0; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL2"; } State { ID = "BLOODYSKULL2"; Sprite = "BSKL"; Frame = 1; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL3"; } State { ID = "BLOODYSKULL3"; Sprite = "BSKL"; Frame = 2; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL4"; } State { ID = "BLOODYSKULL4"; Sprite = "BSKL"; Frame = 3; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL5"; } State { ID = "BLOODYSKULL5"; Sprite = "BSKL"; Frame = 4; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL1"; } State { ID = "BLOODYSKULLX1"; Sprite = "BSKL"; Frame = 5; Tics = 16; Action = "A_CheckSkullDone"; Next state = "BLOODYSKULLX1"; } State { ID = "BLOODYSKULLX2"; Sprite = "BSKL"; Frame = 5; Tics = 1050; Next state = "NULL"; } State { ID = "CHICPLAY"; Sprite = "CHKN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CHICPLAY_RUN1"; Sprite = "CHKN"; Frame = 0; Tics = 3; Next state = "CHICPLAY_RUN2"; } State { ID = "CHICPLAY_RUN2"; Sprite = "CHKN"; Frame = 1; Tics = 3; Next state = "CHICPLAY_RUN3"; } State { ID = "CHICPLAY_RUN3"; Sprite = "CHKN"; Frame = 0; Tics = 3; Next state = "CHICPLAY_RUN4"; } State { ID = "CHICPLAY_RUN4"; Sprite = "CHKN"; Frame = 1; Tics = 3; Next state = "CHICPLAY_RUN1"; } State { ID = "CHICPLAY_ATK1"; Sprite = "CHKN"; Frame = 2; Tics = 12; Next state = "CHICPLAY"; } State { ID = "CHICPLAY_PAIN"; Sprite = "CHKN"; Frame = 3; Tics = 4; Action = "A_Feathers"; Next state = "CHICPLAY_PAIN2"; } State { ID = "CHICPLAY_PAIN2"; Sprite = "CHKN"; Frame = 2; Tics = 4; Action = "A_Pain"; Next state = "CHICPLAY"; } State { ID = "CHICKEN_LOOK1"; Sprite = "CHKN"; Frame = 0; Tics = 10; Action = "A_ChicLook"; Next state = "CHICKEN_LOOK2"; } State { ID = "CHICKEN_LOOK2"; Sprite = "CHKN"; Frame = 1; Tics = 10; Action = "A_ChicLook"; Next state = "CHICKEN_LOOK1"; } State { ID = "CHICKEN_WALK1"; Sprite = "CHKN"; Frame = 0; Tics = 3; Action = "A_ChicChase"; Next state = "CHICKEN_WALK2"; } State { ID = "CHICKEN_WALK2"; Sprite = "CHKN"; Frame = 1; Tics = 3; Action = "A_ChicChase"; Next state = "CHICKEN_WALK1"; } State { ID = "CHICKEN_PAIN1"; Sprite = "CHKN"; Frame = 3; Tics = 5; Action = "A_Feathers"; Next state = "CHICKEN_PAIN2"; } State { ID = "CHICKEN_PAIN2"; Sprite = "CHKN"; Frame = 2; Tics = 5; Action = "A_ChicPain"; Next state = "CHICKEN_WALK1"; } State { ID = "CHICKEN_ATK1"; Sprite = "CHKN"; Frame = 0; Tics = 8; Action = "A_FaceTarget"; Next state = "CHICKEN_ATK2"; } State { ID = "CHICKEN_ATK2"; Sprite = "CHKN"; Frame = 2; Tics = 10; Action = "A_ChicAttack"; Next state = "CHICKEN_WALK1"; } State { ID = "CHICKEN_DIE1"; Sprite = "CHKN"; Frame = 4; Tics = 6; Action = "A_Scream"; Next state = "CHICKEN_DIE2"; } State { ID = "CHICKEN_DIE2"; Sprite = "CHKN"; Frame = 5; Tics = 6; Action = "A_Feathers"; Next state = "CHICKEN_DIE3"; } State { ID = "CHICKEN_DIE3"; Sprite = "CHKN"; Frame = 6; Tics = 6; Next state = "CHICKEN_DIE4"; } State { ID = "CHICKEN_DIE4"; Sprite = "CHKN"; Frame = 7; Tics = 6; Action = "A_NoBlocking"; Next state = "CHICKEN_DIE5"; } State { ID = "CHICKEN_DIE5"; Sprite = "CHKN"; Frame = 8; Tics = 6; Next state = "CHICKEN_DIE6"; } State { ID = "CHICKEN_DIE6"; Sprite = "CHKN"; Frame = 9; Tics = 6; Next state = "CHICKEN_DIE7"; } State { ID = "CHICKEN_DIE7"; Sprite = "CHKN"; Frame = 10; Tics = 6; Next state = "CHICKEN_DIE8"; } State { ID = "CHICKEN_DIE8"; Sprite = "CHKN"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "FEATHER1"; Sprite = "CHKN"; Frame = 12; Tics = 3; Next state = "FEATHER2"; } State { ID = "FEATHER2"; Sprite = "CHKN"; Frame = 13; Tics = 3; Next state = "FEATHER3"; } State { ID = "FEATHER3"; Sprite = "CHKN"; Frame = 14; Tics = 3; Next state = "FEATHER4"; } State { ID = "FEATHER4"; Sprite = "CHKN"; Frame = 15; Tics = 3; Next state = "FEATHER5"; } State { ID = "FEATHER5"; Sprite = "CHKN"; Frame = 16; Tics = 3; Next state = "FEATHER6"; } State { ID = "FEATHER6"; Sprite = "CHKN"; Frame = 15; Tics = 3; Next state = "FEATHER7"; } State { ID = "FEATHER7"; Sprite = "CHKN"; Frame = 14; Tics = 3; Next state = "FEATHER8"; } State { ID = "FEATHER8"; Sprite = "CHKN"; Frame = 13; Tics = 3; Next state = "FEATHER1"; } State { ID = "FEATHERX"; Sprite = "CHKN"; Frame = 13; Tics = 6; Next state = "NULL"; } State { ID = "MUMMY_LOOK1"; Sprite = "MUMM"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "MUMMY_LOOK2"; } State { ID = "MUMMY_LOOK2"; Sprite = "MUMM"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "MUMMY_LOOK1"; } State { ID = "MUMMY_WALK1"; Sprite = "MUMM"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "MUMMY_WALK2"; } State { ID = "MUMMY_WALK2"; Sprite = "MUMM"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "MUMMY_WALK3"; } State { ID = "MUMMY_WALK3"; Sprite = "MUMM"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "MUMMY_WALK4"; } State { ID = "MUMMY_WALK4"; Sprite = "MUMM"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "MUMMY_WALK1"; } State { ID = "MUMMY_ATK1"; Sprite = "MUMM"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "MUMMY_ATK2"; } State { ID = "MUMMY_ATK2"; Sprite = "MUMM"; Frame = 5; Tics = 6; Action = "A_MummyAttack"; Next state = "MUMMY_ATK3"; } State { ID = "MUMMY_ATK3"; Sprite = "MUMM"; Frame = 6; Tics = 6; Action = "A_FaceTarget"; Next state = "MUMMY_WALK1"; } State { ID = "MUMMYL_ATK1"; Sprite = "MUMM"; Frame = 23; Tics = 5; Action = "A_FaceTarget"; Next state = "MUMMYL_ATK2"; } State { ID = "MUMMYL_ATK2"; Sprite = "MUMM"; Frame = 32792; Tics = 5; Action = "A_FaceTarget"; Next state = "MUMMYL_ATK3"; } State { ID = "MUMMYL_ATK3"; Sprite = "MUMM"; Frame = 23; Tics = 5; Action = "A_FaceTarget"; Next state = "MUMMYL_ATK4"; } State { ID = "MUMMYL_ATK4"; Sprite = "MUMM"; Frame = 32792; Tics = 5; Action = "A_FaceTarget"; Next state = "MUMMYL_ATK5"; } State { ID = "MUMMYL_ATK5"; Sprite = "MUMM"; Frame = 23; Tics = 5; Action = "A_FaceTarget"; Next state = "MUMMYL_ATK6"; } State { ID = "MUMMYL_ATK6"; Sprite = "MUMM"; Frame = 32792; Tics = 15; Action = "A_MummyAttack2"; Next state = "MUMMY_WALK1"; } State { ID = "MUMMY_PAIN1"; Sprite = "MUMM"; Frame = 7; Tics = 4; Next state = "MUMMY_PAIN2"; } State { ID = "MUMMY_PAIN2"; Sprite = "MUMM"; Frame = 7; Tics = 4; Action = "A_Pain"; Next state = "MUMMY_WALK1"; } State { ID = "MUMMY_DIE1"; Sprite = "MUMM"; Frame = 8; Tics = 5; Next state = "MUMMY_DIE2"; } State { ID = "MUMMY_DIE2"; Sprite = "MUMM"; Frame = 9; Tics = 5; Action = "A_Scream"; Next state = "MUMMY_DIE3"; } State { ID = "MUMMY_DIE3"; Sprite = "MUMM"; Frame = 10; Tics = 5; Action = "A_MummySoul"; Next state = "MUMMY_DIE4"; } State { ID = "MUMMY_DIE4"; Sprite = "MUMM"; Frame = 11; Tics = 5; Next state = "MUMMY_DIE5"; } State { ID = "MUMMY_DIE5"; Sprite = "MUMM"; Frame = 12; Tics = 5; Action = "A_NoBlocking"; Next state = "MUMMY_DIE6"; } State { ID = "MUMMY_DIE6"; Sprite = "MUMM"; Frame = 13; Tics = 5; Next state = "MUMMY_DIE7"; } State { ID = "MUMMY_DIE7"; Sprite = "MUMM"; Frame = 14; Tics = 5; Next state = "MUMMY_DIE8"; } State { ID = "MUMMY_DIE8"; Sprite = "MUMM"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "MUMMY_SOUL1"; Sprite = "MUMM"; Frame = 16; Tics = 5; Next state = "MUMMY_SOUL2"; } State { ID = "MUMMY_SOUL2"; Sprite = "MUMM"; Frame = 17; Tics = 5; Next state = "MUMMY_SOUL3"; } State { ID = "MUMMY_SOUL3"; Sprite = "MUMM"; Frame = 18; Tics = 5; Next state = "MUMMY_SOUL4"; } State { ID = "MUMMY_SOUL4"; Sprite = "MUMM"; Frame = 19; Tics = 9; Next state = "MUMMY_SOUL5"; } State { ID = "MUMMY_SOUL5"; Sprite = "MUMM"; Frame = 20; Tics = 5; Next state = "MUMMY_SOUL6"; } State { ID = "MUMMY_SOUL6"; Sprite = "MUMM"; Frame = 21; Tics = 5; Next state = "MUMMY_SOUL7"; } State { ID = "MUMMY_SOUL7"; Sprite = "MUMM"; Frame = 22; Tics = 5; Next state = "NULL"; } State { ID = "MUMMYFX1_1"; Sprite = "FX15"; Frame = 32768; Tics = 5; Action = "A_ContMobjSound"; Next state = "MUMMYFX1_2"; } State { ID = "MUMMYFX1_2"; Sprite = "FX15"; Frame = 32769; Tics = 5; Action = "A_MummyFX1Seek"; Next state = "MUMMYFX1_3"; } State { ID = "MUMMYFX1_3"; Sprite = "FX15"; Frame = 32770; Tics = 5; Next state = "MUMMYFX1_4"; } State { ID = "MUMMYFX1_4"; Sprite = "FX15"; Frame = 32769; Tics = 5; Action = "A_MummyFX1Seek"; Next state = "MUMMYFX1_1"; } State { ID = "MUMMYFXI1_1"; Sprite = "FX15"; Frame = 32771; Tics = 5; Next state = "MUMMYFXI1_2"; } State { ID = "MUMMYFXI1_2"; Sprite = "FX15"; Frame = 32772; Tics = 5; Next state = "MUMMYFXI1_3"; } State { ID = "MUMMYFXI1_3"; Sprite = "FX15"; Frame = 32773; Tics = 5; Next state = "MUMMYFXI1_4"; } State { ID = "MUMMYFXI1_4"; Sprite = "FX15"; Frame = 32774; Tics = 5; Next state = "NULL"; } State { ID = "BEAST_LOOK1"; Sprite = "BEAS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BEAST_LOOK2"; } State { ID = "BEAST_LOOK2"; Sprite = "BEAS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "BEAST_LOOK1"; } State { ID = "BEAST_WALK1"; Sprite = "BEAS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BEAST_WALK2"; } State { ID = "BEAST_WALK2"; Sprite = "BEAS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BEAST_WALK3"; } State { ID = "BEAST_WALK3"; Sprite = "BEAS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BEAST_WALK4"; } State { ID = "BEAST_WALK4"; Sprite = "BEAS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BEAST_WALK5"; } State { ID = "BEAST_WALK5"; Sprite = "BEAS"; Frame = 4; Tics = 3; Action = "A_Chase"; Next state = "BEAST_WALK6"; } State { ID = "BEAST_WALK6"; Sprite = "BEAS"; Frame = 5; Tics = 3; Action = "A_Chase"; Next state = "BEAST_WALK1"; } State { ID = "BEAST_ATK1"; Sprite = "BEAS"; Frame = 7; Tics = 10; Action = "A_FaceTarget"; Next state = "BEAST_ATK2"; } State { ID = "BEAST_ATK2"; Sprite = "BEAS"; Frame = 8; Tics = 10; Action = "A_BeastAttack"; Next state = "BEAST_WALK1"; } State { ID = "BEAST_PAIN1"; Sprite = "BEAS"; Frame = 6; Tics = 3; Next state = "BEAST_PAIN2"; } State { ID = "BEAST_PAIN2"; Sprite = "BEAS"; Frame = 6; Tics = 3; Action = "A_Pain"; Next state = "BEAST_WALK1"; } State { ID = "BEAST_DIE1"; Sprite = "BEAS"; Frame = 17; Tics = 6; Next state = "BEAST_DIE2"; } State { ID = "BEAST_DIE2"; Sprite = "BEAS"; Frame = 18; Tics = 6; Action = "A_Scream"; Next state = "BEAST_DIE3"; } State { ID = "BEAST_DIE3"; Sprite = "BEAS"; Frame = 19; Tics = 6; Next state = "BEAST_DIE4"; } State { ID = "BEAST_DIE4"; Sprite = "BEAS"; Frame = 20; Tics = 6; Next state = "BEAST_DIE5"; } State { ID = "BEAST_DIE5"; Sprite = "BEAS"; Frame = 21; Tics = 6; Next state = "BEAST_DIE6"; } State { ID = "BEAST_DIE6"; Sprite = "BEAS"; Frame = 22; Tics = 6; Action = "A_NoBlocking"; Next state = "BEAST_DIE7"; } State { ID = "BEAST_DIE7"; Sprite = "BEAS"; Frame = 23; Tics = 6; Next state = "BEAST_DIE8"; } State { ID = "BEAST_DIE8"; Sprite = "BEAS"; Frame = 24; Tics = 6; Next state = "BEAST_DIE9"; } State { ID = "BEAST_DIE9"; Sprite = "BEAS"; Frame = 25; Tics = -1; Next state = "NULL"; } State { ID = "BEAST_XDIE1"; Sprite = "BEAS"; Frame = 9; Tics = 5; Next state = "BEAST_XDIE2"; } State { ID = "BEAST_XDIE2"; Sprite = "BEAS"; Frame = 10; Tics = 6; Action = "A_Scream"; Next state = "BEAST_XDIE3"; } State { ID = "BEAST_XDIE3"; Sprite = "BEAS"; Frame = 11; Tics = 5; Next state = "BEAST_XDIE4"; } State { ID = "BEAST_XDIE4"; Sprite = "BEAS"; Frame = 12; Tics = 6; Next state = "BEAST_XDIE5"; } State { ID = "BEAST_XDIE5"; Sprite = "BEAS"; Frame = 13; Tics = 5; Next state = "BEAST_XDIE6"; } State { ID = "BEAST_XDIE6"; Sprite = "BEAS"; Frame = 14; Tics = 6; Action = "A_NoBlocking"; Next state = "BEAST_XDIE7"; } State { ID = "BEAST_XDIE7"; Sprite = "BEAS"; Frame = 15; Tics = 5; Next state = "BEAST_XDIE8"; } State { ID = "BEAST_XDIE8"; Sprite = "BEAS"; Frame = 16; Tics = -1; Next state = "NULL"; } State { ID = "BEASTBALL1"; Sprite = "FRB1"; Frame = 32768; Tics = 2; Action = "A_BeastPuff"; Next state = "BEASTBALL2"; } State { ID = "BEASTBALL2"; Sprite = "FRB1"; Frame = 32768; Tics = 2; Action = "A_BeastPuff"; Next state = "BEASTBALL3"; } State { ID = "BEASTBALL3"; Sprite = "FRB1"; Frame = 32769; Tics = 2; Action = "A_BeastPuff"; Next state = "BEASTBALL4"; } State { ID = "BEASTBALL4"; Sprite = "FRB1"; Frame = 32769; Tics = 2; Action = "A_BeastPuff"; Next state = "BEASTBALL5"; } State { ID = "BEASTBALL5"; Sprite = "FRB1"; Frame = 32770; Tics = 2; Action = "A_BeastPuff"; Next state = "BEASTBALL6"; } State { ID = "BEASTBALL6"; Sprite = "FRB1"; Frame = 32770; Tics = 2; Action = "A_BeastPuff"; Next state = "BEASTBALL1"; } State { ID = "BEASTBALLX1"; Sprite = "FRB1"; Frame = 3; Tics = 4; Next state = "BEASTBALLX2"; } State { ID = "BEASTBALLX2"; Sprite = "FRB1"; Frame = 4; Tics = 4; Next state = "BEASTBALLX3"; } State { ID = "BEASTBALLX3"; Sprite = "FRB1"; Frame = 5; Tics = 4; Next state = "BEASTBALLX4"; } State { ID = "BEASTBALLX4"; Sprite = "FRB1"; Frame = 6; Tics = 4; Next state = "BEASTBALLX5"; } State { ID = "BEASTBALLX5"; Sprite = "FRB1"; Frame = 7; Tics = 4; Next state = "NULL"; } State { ID = "BURNBALL1"; Sprite = "FRB1"; Frame = 0; Tics = 4; Next state = "BURNBALL2"; } State { ID = "BURNBALL2"; Sprite = "FRB1"; Frame = 1; Tics = 4; Next state = "BURNBALL3"; } State { ID = "BURNBALL3"; Sprite = "FRB1"; Frame = 2; Tics = 4; Next state = "BURNBALL4"; } State { ID = "BURNBALL4"; Sprite = "FRB1"; Frame = 3; Tics = 4; Next state = "BURNBALL5"; } State { ID = "BURNBALL5"; Sprite = "FRB1"; Frame = 4; Tics = 4; Next state = "BURNBALL6"; } State { ID = "BURNBALL6"; Sprite = "FRB1"; Frame = 5; Tics = 4; Next state = "BURNBALL7"; } State { ID = "BURNBALL7"; Sprite = "FRB1"; Frame = 6; Tics = 4; Next state = "BURNBALL8"; } State { ID = "BURNBALL8"; Sprite = "FRB1"; Frame = 7; Tics = 4; Next state = "NULL"; } State { ID = "BURNBALLFB1"; Sprite = "FRB1"; Frame = 32768; Tics = 4; Next state = "BURNBALLFB2"; } State { ID = "BURNBALLFB2"; Sprite = "FRB1"; Frame = 32769; Tics = 4; Next state = "BURNBALLFB3"; } State { ID = "BURNBALLFB3"; Sprite = "FRB1"; Frame = 32770; Tics = 4; Next state = "BURNBALLFB4"; } State { ID = "BURNBALLFB4"; Sprite = "FRB1"; Frame = 32771; Tics = 4; Next state = "BURNBALLFB5"; } State { ID = "BURNBALLFB5"; Sprite = "FRB1"; Frame = 32772; Tics = 4; Next state = "BURNBALLFB6"; } State { ID = "BURNBALLFB6"; Sprite = "FRB1"; Frame = 32773; Tics = 4; Next state = "BURNBALLFB7"; } State { ID = "BURNBALLFB7"; Sprite = "FRB1"; Frame = 32774; Tics = 4; Next state = "BURNBALLFB8"; } State { ID = "BURNBALLFB8"; Sprite = "FRB1"; Frame = 32775; Tics = 4; Next state = "NULL"; } State { ID = "PUFFY1"; Sprite = "FRB1"; Frame = 3; Tics = 4; Next state = "PUFFY2"; } State { ID = "PUFFY2"; Sprite = "FRB1"; Frame = 4; Tics = 4; Next state = "PUFFY3"; } State { ID = "PUFFY3"; Sprite = "FRB1"; Frame = 5; Tics = 4; Next state = "PUFFY4"; } State { ID = "PUFFY4"; Sprite = "FRB1"; Frame = 6; Tics = 4; Next state = "PUFFY5"; } State { ID = "PUFFY5"; Sprite = "FRB1"; Frame = 7; Tics = 4; Next state = "NULL"; } State { ID = "SNAKE_LOOK1"; Sprite = "SNKE"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SNAKE_LOOK2"; } State { ID = "SNAKE_LOOK2"; Sprite = "SNKE"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SNAKE_LOOK1"; } State { ID = "SNAKE_WALK1"; Sprite = "SNKE"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "SNAKE_WALK2"; } State { ID = "SNAKE_WALK2"; Sprite = "SNKE"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "SNAKE_WALK3"; } State { ID = "SNAKE_WALK3"; Sprite = "SNKE"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "SNAKE_WALK4"; } State { ID = "SNAKE_WALK4"; Sprite = "SNKE"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "SNAKE_WALK1"; } State { ID = "SNAKE_ATK1"; Sprite = "SNKE"; Frame = 5; Tics = 5; Action = "A_FaceTarget"; Next state = "SNAKE_ATK2"; } State { ID = "SNAKE_ATK2"; Sprite = "SNKE"; Frame = 5; Tics = 5; Action = "A_FaceTarget"; Next state = "SNAKE_ATK3"; } State { ID = "SNAKE_ATK3"; Sprite = "SNKE"; Frame = 5; Tics = 4; Action = "A_SnakeAttack"; Next state = "SNAKE_ATK4"; } State { ID = "SNAKE_ATK4"; Sprite = "SNKE"; Frame = 5; Tics = 4; Action = "A_SnakeAttack"; Next state = "SNAKE_ATK5"; } State { ID = "SNAKE_ATK5"; Sprite = "SNKE"; Frame = 5; Tics = 4; Action = "A_SnakeAttack"; Next state = "SNAKE_ATK6"; } State { ID = "SNAKE_ATK6"; Sprite = "SNKE"; Frame = 5; Tics = 5; Action = "A_FaceTarget"; Next state = "SNAKE_ATK7"; } State { ID = "SNAKE_ATK7"; Sprite = "SNKE"; Frame = 5; Tics = 5; Action = "A_FaceTarget"; Next state = "SNAKE_ATK8"; } State { ID = "SNAKE_ATK8"; Sprite = "SNKE"; Frame = 5; Tics = 5; Action = "A_FaceTarget"; Next state = "SNAKE_ATK9"; } State { ID = "SNAKE_ATK9"; Sprite = "SNKE"; Frame = 5; Tics = 4; Action = "A_SnakeAttack2"; Next state = "SNAKE_WALK1"; } State { ID = "SNAKE_PAIN1"; Sprite = "SNKE"; Frame = 4; Tics = 3; Next state = "SNAKE_PAIN2"; } State { ID = "SNAKE_PAIN2"; Sprite = "SNKE"; Frame = 4; Tics = 3; Action = "A_Pain"; Next state = "SNAKE_WALK1"; } State { ID = "SNAKE_DIE1"; Sprite = "SNKE"; Frame = 6; Tics = 5; Next state = "SNAKE_DIE2"; } State { ID = "SNAKE_DIE2"; Sprite = "SNKE"; Frame = 7; Tics = 5; Action = "A_Scream"; Next state = "SNAKE_DIE3"; } State { ID = "SNAKE_DIE3"; Sprite = "SNKE"; Frame = 8; Tics = 5; Next state = "SNAKE_DIE4"; } State { ID = "SNAKE_DIE4"; Sprite = "SNKE"; Frame = 9; Tics = 5; Next state = "SNAKE_DIE5"; } State { ID = "SNAKE_DIE5"; Sprite = "SNKE"; Frame = 10; Tics = 5; Next state = "SNAKE_DIE6"; } State { ID = "SNAKE_DIE6"; Sprite = "SNKE"; Frame = 11; Tics = 5; Next state = "SNAKE_DIE7"; } State { ID = "SNAKE_DIE7"; Sprite = "SNKE"; Frame = 12; Tics = 5; Action = "A_NoBlocking"; Next state = "SNAKE_DIE8"; } State { ID = "SNAKE_DIE8"; Sprite = "SNKE"; Frame = 13; Tics = 5; Next state = "SNAKE_DIE9"; } State { ID = "SNAKE_DIE9"; Sprite = "SNKE"; Frame = 14; Tics = 5; Next state = "SNAKE_DIE10"; } State { ID = "SNAKE_DIE10"; Sprite = "SNKE"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "SNAKEPRO_A1"; Sprite = "SNFX"; Frame = 32768; Tics = 5; Next state = "SNAKEPRO_A2"; } State { ID = "SNAKEPRO_A2"; Sprite = "SNFX"; Frame = 32769; Tics = 5; Next state = "SNAKEPRO_A3"; } State { ID = "SNAKEPRO_A3"; Sprite = "SNFX"; Frame = 32770; Tics = 5; Next state = "SNAKEPRO_A4"; } State { ID = "SNAKEPRO_A4"; Sprite = "SNFX"; Frame = 32771; Tics = 5; Next state = "SNAKEPRO_A1"; } State { ID = "SNAKEPRO_AX1"; Sprite = "SNFX"; Frame = 32772; Tics = 5; Next state = "SNAKEPRO_AX2"; } State { ID = "SNAKEPRO_AX2"; Sprite = "SNFX"; Frame = 32773; Tics = 5; Next state = "SNAKEPRO_AX3"; } State { ID = "SNAKEPRO_AX3"; Sprite = "SNFX"; Frame = 32774; Tics = 4; Next state = "SNAKEPRO_AX4"; } State { ID = "SNAKEPRO_AX4"; Sprite = "SNFX"; Frame = 32775; Tics = 3; Next state = "SNAKEPRO_AX5"; } State { ID = "SNAKEPRO_AX5"; Sprite = "SNFX"; Frame = 32776; Tics = 3; Next state = "NULL"; } State { ID = "SNAKEPRO_B1"; Sprite = "SNFX"; Frame = 32777; Tics = 6; Next state = "SNAKEPRO_B2"; } State { ID = "SNAKEPRO_B2"; Sprite = "SNFX"; Frame = 32778; Tics = 6; Next state = "SNAKEPRO_B1"; } State { ID = "SNAKEPRO_BX1"; Sprite = "SNFX"; Frame = 32779; Tics = 5; Next state = "SNAKEPRO_BX2"; } State { ID = "SNAKEPRO_BX2"; Sprite = "SNFX"; Frame = 32780; Tics = 5; Next state = "SNAKEPRO_BX3"; } State { ID = "SNAKEPRO_BX3"; Sprite = "SNFX"; Frame = 32781; Tics = 4; Next state = "SNAKEPRO_BX4"; } State { ID = "SNAKEPRO_BX4"; Sprite = "SNFX"; Frame = 32782; Tics = 3; Next state = "NULL"; } State { ID = "HEAD_LOOK"; Sprite = "HEAD"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "HEAD_LOOK"; } State { ID = "HEAD_FLOAT"; Sprite = "HEAD"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "HEAD_FLOAT"; } State { ID = "HEAD_ATK1"; Sprite = "HEAD"; Frame = 0; Tics = 5; Action = "A_FaceTarget"; Next state = "HEAD_ATK2"; } State { ID = "HEAD_ATK2"; Sprite = "HEAD"; Frame = 1; Tics = 20; Action = "A_HeadAttack"; Next state = "HEAD_FLOAT"; } State { ID = "HEAD_PAIN1"; Sprite = "HEAD"; Frame = 0; Tics = 4; Next state = "HEAD_PAIN2"; } State { ID = "HEAD_PAIN2"; Sprite = "HEAD"; Frame = 0; Tics = 4; Action = "A_Pain"; Next state = "HEAD_FLOAT"; } State { ID = "HEAD_DIE1"; Sprite = "HEAD"; Frame = 2; Tics = 7; Next state = "HEAD_DIE2"; } State { ID = "HEAD_DIE2"; Sprite = "HEAD"; Frame = 3; Tics = 7; Action = "A_Scream"; Next state = "HEAD_DIE3"; } State { ID = "HEAD_DIE3"; Sprite = "HEAD"; Frame = 4; Tics = 7; Next state = "HEAD_DIE4"; } State { ID = "HEAD_DIE4"; Sprite = "HEAD"; Frame = 5; Tics = 7; Next state = "HEAD_DIE5"; } State { ID = "HEAD_DIE5"; Sprite = "HEAD"; Frame = 6; Tics = 7; Action = "A_NoBlocking"; Next state = "HEAD_DIE6"; } State { ID = "HEAD_DIE6"; Sprite = "HEAD"; Frame = 7; Tics = 7; Next state = "HEAD_DIE7"; } State { ID = "HEAD_DIE7"; Sprite = "HEAD"; Frame = 8; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "HEADFX1_1"; Sprite = "FX05"; Frame = 32768; Tics = 6; Next state = "HEADFX1_2"; } State { ID = "HEADFX1_2"; Sprite = "FX05"; Frame = 32769; Tics = 6; Next state = "HEADFX1_3"; } State { ID = "HEADFX1_3"; Sprite = "FX05"; Frame = 32770; Tics = 6; Next state = "HEADFX1_1"; } State { ID = "HEADFXI1_1"; Sprite = "FX05"; Frame = 32771; Tics = 5; Action = "A_HeadIceImpact"; Next state = "HEADFXI1_2"; } State { ID = "HEADFXI1_2"; Sprite = "FX05"; Frame = 32772; Tics = 5; Next state = "HEADFXI1_3"; } State { ID = "HEADFXI1_3"; Sprite = "FX05"; Frame = 32773; Tics = 5; Next state = "HEADFXI1_4"; } State { ID = "HEADFXI1_4"; Sprite = "FX05"; Frame = 32774; Tics = 5; Next state = "NULL"; } State { ID = "HEADFX2_1"; Sprite = "FX05"; Frame = 32775; Tics = 6; Next state = "HEADFX2_2"; } State { ID = "HEADFX2_2"; Sprite = "FX05"; Frame = 32776; Tics = 6; Next state = "HEADFX2_3"; } State { ID = "HEADFX2_3"; Sprite = "FX05"; Frame = 32777; Tics = 6; Next state = "HEADFX2_1"; } State { ID = "HEADFXI2_1"; Sprite = "FX05"; Frame = 32771; Tics = 5; Next state = "HEADFXI2_2"; } State { ID = "HEADFXI2_2"; Sprite = "FX05"; Frame = 32772; Tics = 5; Next state = "HEADFXI2_3"; } State { ID = "HEADFXI2_3"; Sprite = "FX05"; Frame = 32773; Tics = 5; Next state = "HEADFXI2_4"; } State { ID = "HEADFXI2_4"; Sprite = "FX05"; Frame = 32774; Tics = 5; Next state = "NULL"; } State { ID = "HEADFX3_1"; Sprite = "FX06"; Frame = 32768; Tics = 4; Action = "A_HeadFireGrow"; Next state = "HEADFX3_2"; } State { ID = "HEADFX3_2"; Sprite = "FX06"; Frame = 32769; Tics = 4; Action = "A_HeadFireGrow"; Next state = "HEADFX3_3"; } State { ID = "HEADFX3_3"; Sprite = "FX06"; Frame = 32770; Tics = 4; Action = "A_HeadFireGrow"; Next state = "HEADFX3_1"; } State { ID = "HEADFX3_4"; Sprite = "FX06"; Frame = 32768; Tics = 5; Next state = "HEADFX3_5"; } State { ID = "HEADFX3_5"; Sprite = "FX06"; Frame = 32769; Tics = 5; Next state = "HEADFX3_6"; } State { ID = "HEADFX3_6"; Sprite = "FX06"; Frame = 32770; Tics = 5; Next state = "HEADFX3_4"; } State { ID = "HEADFXI3_1"; Sprite = "FX06"; Frame = 32771; Tics = 5; Next state = "HEADFXI3_2"; } State { ID = "HEADFXI3_2"; Sprite = "FX06"; Frame = 32772; Tics = 5; Next state = "HEADFXI3_3"; } State { ID = "HEADFXI3_3"; Sprite = "FX06"; Frame = 32773; Tics = 5; Next state = "HEADFXI3_4"; } State { ID = "HEADFXI3_4"; Sprite = "FX06"; Frame = 32774; Tics = 5; Next state = "NULL"; } State { ID = "HEADFX4_1"; Sprite = "FX07"; Frame = 3; Tics = 3; Next state = "HEADFX4_2"; } State { ID = "HEADFX4_2"; Sprite = "FX07"; Frame = 4; Tics = 3; Next state = "HEADFX4_3"; } State { ID = "HEADFX4_3"; Sprite = "FX07"; Frame = 5; Tics = 3; Next state = "HEADFX4_4"; } State { ID = "HEADFX4_4"; Sprite = "FX07"; Frame = 6; Tics = 3; Next state = "HEADFX4_5"; } State { ID = "HEADFX4_5"; Sprite = "FX07"; Frame = 0; Tics = 3; Action = "A_WhirlwindSeek"; Next state = "HEADFX4_6"; } State { ID = "HEADFX4_6"; Sprite = "FX07"; Frame = 1; Tics = 3; Action = "A_WhirlwindSeek"; Next state = "HEADFX4_7"; } State { ID = "HEADFX4_7"; Sprite = "FX07"; Frame = 2; Tics = 3; Action = "A_WhirlwindSeek"; Next state = "HEADFX4_5"; } State { ID = "HEADFXI4_1"; Sprite = "FX07"; Frame = 6; Tics = 4; Next state = "HEADFXI4_2"; } State { ID = "HEADFXI4_2"; Sprite = "FX07"; Frame = 5; Tics = 4; Next state = "HEADFXI4_3"; } State { ID = "HEADFXI4_3"; Sprite = "FX07"; Frame = 4; Tics = 4; Next state = "HEADFXI4_4"; } State { ID = "HEADFXI4_4"; Sprite = "FX07"; Frame = 3; Tics = 4; Next state = "NULL"; } State { ID = "CLINK_LOOK1"; Sprite = "CLNK"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "CLINK_LOOK2"; } State { ID = "CLINK_LOOK2"; Sprite = "CLNK"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "CLINK_LOOK1"; } State { ID = "CLINK_WALK1"; Sprite = "CLNK"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK2"; } State { ID = "CLINK_WALK2"; Sprite = "CLNK"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK3"; } State { ID = "CLINK_WALK3"; Sprite = "CLNK"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK4"; } State { ID = "CLINK_WALK4"; Sprite = "CLNK"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK5"; } State { ID = "CLINK_ATK1"; Sprite = "CLNK"; Frame = 4; Tics = 5; Action = "A_FaceTarget"; Next state = "CLINK_ATK2"; } State { ID = "CLINK_ATK2"; Sprite = "CLNK"; Frame = 5; Tics = 4; Action = "A_FaceTarget"; Next state = "CLINK_ATK3"; } State { ID = "CLINK_ATK3"; Sprite = "CLNK"; Frame = 6; Tics = 7; Action = "A_ClinkAttack"; Next state = "CLINK_WALK1"; } State { ID = "CLINK_PAIN1"; Sprite = "CLNK"; Frame = 7; Tics = 3; Next state = "CLINK_PAIN2"; } State { ID = "CLINK_PAIN2"; Sprite = "CLNK"; Frame = 7; Tics = 3; Action = "A_Pain"; Next state = "CLINK_WALK1"; } State { ID = "CLINK_DIE1"; Sprite = "CLNK"; Frame = 8; Tics = 6; Next state = "CLINK_DIE2"; } State { ID = "CLINK_DIE2"; Sprite = "CLNK"; Frame = 9; Tics = 6; Next state = "CLINK_DIE3"; } State { ID = "CLINK_DIE3"; Sprite = "CLNK"; Frame = 10; Tics = 5; Action = "A_Scream"; Next state = "CLINK_DIE4"; } State { ID = "CLINK_DIE4"; Sprite = "CLNK"; Frame = 11; Tics = 5; Action = "A_NoBlocking"; Next state = "CLINK_DIE5"; } State { ID = "CLINK_DIE5"; Sprite = "CLNK"; Frame = 12; Tics = 5; Next state = "CLINK_DIE6"; } State { ID = "CLINK_DIE6"; Sprite = "CLNK"; Frame = 13; Tics = 5; Next state = "CLINK_DIE7"; } State { ID = "CLINK_DIE7"; Sprite = "CLNK"; Frame = 14; Tics = -1; Next state = "NULL"; } State { ID = "WIZARD_LOOK1"; Sprite = "WZRD"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "WIZARD_LOOK2"; } State { ID = "WIZARD_LOOK2"; Sprite = "WZRD"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "WIZARD_LOOK1"; } State { ID = "WIZARD_WALK1"; Sprite = "WZRD"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "WIZARD_WALK2"; } State { ID = "WIZARD_WALK2"; Sprite = "WZRD"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "WIZARD_WALK3"; } State { ID = "WIZARD_WALK3"; Sprite = "WZRD"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "WIZARD_WALK4"; } State { ID = "WIZARD_WALK4"; Sprite = "WZRD"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "WIZARD_WALK5"; } State { ID = "WIZARD_WALK5"; Sprite = "WZRD"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "WIZARD_WALK6"; } State { ID = "WIZARD_WALK6"; Sprite = "WZRD"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "WIZARD_WALK7"; } State { ID = "WIZARD_WALK7"; Sprite = "WZRD"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "WIZARD_WALK8"; } State { ID = "WIZARD_WALK8"; Sprite = "WZRD"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "WIZARD_WALK1"; } State { ID = "WIZARD_ATK1"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk1"; Next state = "WIZARD_ATK2"; } State { ID = "WIZARD_ATK2"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk2"; Next state = "WIZARD_ATK3"; } State { ID = "WIZARD_ATK3"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk1"; Next state = "WIZARD_ATK4"; } State { ID = "WIZARD_ATK4"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk2"; Next state = "WIZARD_ATK5"; } State { ID = "WIZARD_ATK5"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk1"; Next state = "WIZARD_ATK6"; } State { ID = "WIZARD_ATK6"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk2"; Next state = "WIZARD_ATK7"; } State { ID = "WIZARD_ATK7"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk1"; Next state = "WIZARD_ATK8"; } State { ID = "WIZARD_ATK8"; Sprite = "WZRD"; Frame = 2; Tics = 4; Action = "A_WizAtk2"; Next state = "WIZARD_ATK9"; } State { ID = "WIZARD_ATK9"; Sprite = "WZRD"; Frame = 3; Tics = 12; Action = "A_WizAtk3"; Next state = "WIZARD_WALK1"; } State { ID = "WIZARD_PAIN1"; Sprite = "WZRD"; Frame = 4; Tics = 3; Action = "A_GhostOff"; Next state = "WIZARD_PAIN2"; } State { ID = "WIZARD_PAIN2"; Sprite = "WZRD"; Frame = 4; Tics = 3; Action = "A_Pain"; Next state = "WIZARD_WALK1"; } State { ID = "WIZARD_DIE1"; Sprite = "WZRD"; Frame = 5; Tics = 6; Action = "A_GhostOff"; Next state = "WIZARD_DIE2"; } State { ID = "WIZARD_DIE2"; Sprite = "WZRD"; Frame = 6; Tics = 6; Action = "A_Scream"; Next state = "WIZARD_DIE3"; } State { ID = "WIZARD_DIE3"; Sprite = "WZRD"; Frame = 7; Tics = 6; Next state = "WIZARD_DIE4"; } State { ID = "WIZARD_DIE4"; Sprite = "WZRD"; Frame = 8; Tics = 6; Next state = "WIZARD_DIE5"; } State { ID = "WIZARD_DIE5"; Sprite = "WZRD"; Frame = 9; Tics = 6; Action = "A_NoBlocking"; Next state = "WIZARD_DIE6"; } State { ID = "WIZARD_DIE6"; Sprite = "WZRD"; Frame = 10; Tics = 6; Next state = "WIZARD_DIE7"; } State { ID = "WIZARD_DIE7"; Sprite = "WZRD"; Frame = 11; Tics = 6; Next state = "WIZARD_DIE8"; } State { ID = "WIZARD_DIE8"; Sprite = "WZRD"; Frame = 12; Tics = -1; Next state = "NULL"; } State { ID = "WIZFX1_1"; Sprite = "FX11"; Frame = 32768; Tics = 6; Next state = "WIZFX1_2"; } State { ID = "WIZFX1_2"; Sprite = "FX11"; Frame = 32769; Tics = 6; Next state = "WIZFX1_1"; } State { ID = "WIZFXI1_1"; Sprite = "FX11"; Frame = 32770; Tics = 5; Next state = "WIZFXI1_2"; } State { ID = "WIZFXI1_2"; Sprite = "FX11"; Frame = 32771; Tics = 5; Next state = "WIZFXI1_3"; } State { ID = "WIZFXI1_3"; Sprite = "FX11"; Frame = 32772; Tics = 5; Next state = "WIZFXI1_4"; } State { ID = "WIZFXI1_4"; Sprite = "FX11"; Frame = 32773; Tics = 5; Next state = "WIZFXI1_5"; } State { ID = "WIZFXI1_5"; Sprite = "FX11"; Frame = 32774; Tics = 5; Next state = "NULL"; } State { ID = "IMP_LOOK1"; Sprite = "IMPX"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "IMP_LOOK2"; } State { ID = "IMP_LOOK2"; Sprite = "IMPX"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "IMP_LOOK3"; } State { ID = "IMP_LOOK3"; Sprite = "IMPX"; Frame = 2; Tics = 10; Action = "A_Look"; Next state = "IMP_LOOK4"; } State { ID = "IMP_LOOK4"; Sprite = "IMPX"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "IMP_LOOK1"; } State { ID = "IMP_FLY1"; Sprite = "IMPX"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY2"; } State { ID = "IMP_FLY2"; Sprite = "IMPX"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY3"; } State { ID = "IMP_FLY3"; Sprite = "IMPX"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY4"; } State { ID = "IMP_FLY4"; Sprite = "IMPX"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY5"; } State { ID = "IMP_FLY5"; Sprite = "IMPX"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY6"; } State { ID = "IMP_FLY6"; Sprite = "IMPX"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY7"; } State { ID = "IMP_FLY7"; Sprite = "IMPX"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY8"; } State { ID = "IMP_FLY8"; Sprite = "IMPX"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "IMP_FLY1"; } State { ID = "IMP_MEATK1"; Sprite = "IMPX"; Frame = 3; Tics = 6; Action = "A_FaceTarget"; Next state = "IMP_MEATK2"; } State { ID = "IMP_MEATK2"; Sprite = "IMPX"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "IMP_MEATK3"; } State { ID = "IMP_MEATK3"; Sprite = "IMPX"; Frame = 5; Tics = 6; Action = "A_ImpMeAttack"; Next state = "IMP_FLY1"; } State { ID = "IMP_MSATK1_1"; Sprite = "IMPX"; Frame = 0; Tics = 10; Action = "A_FaceTarget"; Next state = "IMP_MSATK1_2"; } State { ID = "IMP_MSATK1_2"; Sprite = "IMPX"; Frame = 1; Tics = 6; Action = "A_ImpMsAttack"; Next state = "IMP_MSATK1_3"; } State { ID = "IMP_MSATK1_3"; Sprite = "IMPX"; Frame = 2; Tics = 6; Next state = "IMP_MSATK1_4"; } State { ID = "IMP_MSATK1_4"; Sprite = "IMPX"; Frame = 1; Tics = 6; Next state = "IMP_MSATK1_5"; } State { ID = "IMP_MSATK1_5"; Sprite = "IMPX"; Frame = 0; Tics = 6; Next state = "IMP_MSATK1_6"; } State { ID = "IMP_MSATK1_6"; Sprite = "IMPX"; Frame = 1; Tics = 6; Next state = "IMP_MSATK1_3"; } State { ID = "IMP_MSATK2_1"; Sprite = "IMPX"; Frame = 3; Tics = 6; Action = "A_FaceTarget"; Next state = "IMP_MSATK2_2"; } State { ID = "IMP_MSATK2_2"; Sprite = "IMPX"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "IMP_MSATK2_3"; } State { ID = "IMP_MSATK2_3"; Sprite = "IMPX"; Frame = 5; Tics = 6; Action = "A_ImpMsAttack2"; Next state = "IMP_FLY1"; } State { ID = "IMP_PAIN1"; Sprite = "IMPX"; Frame = 6; Tics = 3; Next state = "IMP_PAIN2"; } State { ID = "IMP_PAIN2"; Sprite = "IMPX"; Frame = 6; Tics = 3; Action = "A_Pain"; Next state = "IMP_FLY1"; } State { ID = "IMP_DIE1"; Sprite = "IMPX"; Frame = 6; Tics = 4; Action = "A_ImpDeath"; Next state = "IMP_DIE2"; } State { ID = "IMP_DIE2"; Sprite = "IMPX"; Frame = 7; Tics = 5; Next state = "IMP_DIE2"; } State { ID = "IMP_XDIE1"; Sprite = "IMPX"; Frame = 18; Tics = 5; Action = "A_ImpXDeath1"; Next state = "IMP_XDIE2"; } State { ID = "IMP_XDIE2"; Sprite = "IMPX"; Frame = 19; Tics = 5; Next state = "IMP_XDIE3"; } State { ID = "IMP_XDIE3"; Sprite = "IMPX"; Frame = 20; Tics = 5; Next state = "IMP_XDIE4"; } State { ID = "IMP_XDIE4"; Sprite = "IMPX"; Frame = 21; Tics = 5; Action = "A_ImpXDeath2"; Next state = "IMP_XDIE5"; } State { ID = "IMP_XDIE5"; Sprite = "IMPX"; Frame = 22; Tics = 5; Next state = "IMP_XDIE5"; } State { ID = "IMP_CRASH1"; Sprite = "IMPX"; Frame = 8; Tics = 7; Action = "A_ImpExplode"; Next state = "IMP_CRASH2"; } State { ID = "IMP_CRASH2"; Sprite = "IMPX"; Frame = 9; Tics = 7; Action = "A_Scream"; Next state = "IMP_CRASH3"; } State { ID = "IMP_CRASH3"; Sprite = "IMPX"; Frame = 10; Tics = 7; Next state = "IMP_CRASH4"; } State { ID = "IMP_CRASH4"; Sprite = "IMPX"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "IMP_XCRASH1"; Sprite = "IMPX"; Frame = 23; Tics = 7; Next state = "IMP_XCRASH2"; } State { ID = "IMP_XCRASH2"; Sprite = "IMPX"; Frame = 24; Tics = 7; Next state = "IMP_XCRASH3"; } State { ID = "IMP_XCRASH3"; Sprite = "IMPX"; Frame = 25; Tics = -1; Next state = "NULL"; } State { ID = "IMP_CHUNKA1"; Sprite = "IMPX"; Frame = 12; Tics = 5; Next state = "IMP_CHUNKA2"; } State { ID = "IMP_CHUNKA2"; Sprite = "IMPX"; Frame = 13; Tics = 700; Next state = "IMP_CHUNKA3"; } State { ID = "IMP_CHUNKA3"; Sprite = "IMPX"; Frame = 14; Tics = 700; Next state = "NULL"; } State { ID = "IMP_CHUNKB1"; Sprite = "IMPX"; Frame = 15; Tics = 5; Next state = "IMP_CHUNKB2"; } State { ID = "IMP_CHUNKB2"; Sprite = "IMPX"; Frame = 16; Tics = 700; Next state = "IMP_CHUNKB3"; } State { ID = "IMP_CHUNKB3"; Sprite = "IMPX"; Frame = 17; Tics = 700; Next state = "NULL"; } State { ID = "IMPFX1"; Sprite = "FX10"; Frame = 32768; Tics = 6; Next state = "IMPFX2"; } State { ID = "IMPFX2"; Sprite = "FX10"; Frame = 32769; Tics = 6; Next state = "IMPFX3"; } State { ID = "IMPFX3"; Sprite = "FX10"; Frame = 32770; Tics = 6; Next state = "IMPFX1"; } State { ID = "IMPFXI1"; Sprite = "FX10"; Frame = 32771; Tics = 5; Next state = "IMPFXI2"; } State { ID = "IMPFXI2"; Sprite = "FX10"; Frame = 32772; Tics = 5; Next state = "IMPFXI3"; } State { ID = "IMPFXI3"; Sprite = "FX10"; Frame = 32773; Tics = 5; Next state = "IMPFXI4"; } State { ID = "IMPFXI4"; Sprite = "FX10"; Frame = 32774; Tics = 5; Next state = "NULL"; } State { ID = "KNIGHT_STND1"; Sprite = "KNIG"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "KNIGHT_STND2"; } State { ID = "KNIGHT_STND2"; Sprite = "KNIG"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "KNIGHT_STND1"; } State { ID = "KNIGHT_WALK1"; Sprite = "KNIG"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "KNIGHT_WALK2"; } State { ID = "KNIGHT_WALK2"; Sprite = "KNIG"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "KNIGHT_WALK3"; } State { ID = "KNIGHT_WALK3"; Sprite = "KNIG"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "KNIGHT_WALK4"; } State { ID = "KNIGHT_WALK4"; Sprite = "KNIG"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "KNIGHT_WALK1"; } State { ID = "KNIGHT_ATK1"; Sprite = "KNIG"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "KNIGHT_ATK2"; } State { ID = "KNIGHT_ATK2"; Sprite = "KNIG"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "KNIGHT_ATK3"; } State { ID = "KNIGHT_ATK3"; Sprite = "KNIG"; Frame = 6; Tics = 8; Action = "A_KnightAttack"; Next state = "KNIGHT_ATK4"; } State { ID = "KNIGHT_ATK4"; Sprite = "KNIG"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "KNIGHT_ATK5"; } State { ID = "KNIGHT_ATK5"; Sprite = "KNIG"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "KNIGHT_ATK6"; } State { ID = "KNIGHT_ATK6"; Sprite = "KNIG"; Frame = 6; Tics = 8; Action = "A_KnightAttack"; Next state = "KNIGHT_WALK1"; } State { ID = "KNIGHT_PAIN1"; Sprite = "KNIG"; Frame = 7; Tics = 3; Next state = "KNIGHT_PAIN2"; } State { ID = "KNIGHT_PAIN2"; Sprite = "KNIG"; Frame = 7; Tics = 3; Action = "A_Pain"; Next state = "KNIGHT_WALK1"; } State { ID = "KNIGHT_DIE1"; Sprite = "KNIG"; Frame = 8; Tics = 6; Next state = "KNIGHT_DIE2"; } State { ID = "KNIGHT_DIE2"; Sprite = "KNIG"; Frame = 9; Tics = 6; Action = "A_Scream"; Next state = "KNIGHT_DIE3"; } State { ID = "KNIGHT_DIE3"; Sprite = "KNIG"; Frame = 10; Tics = 6; Next state = "KNIGHT_DIE4"; } State { ID = "KNIGHT_DIE4"; Sprite = "KNIG"; Frame = 11; Tics = 6; Action = "A_NoBlocking"; Next state = "KNIGHT_DIE5"; } State { ID = "KNIGHT_DIE5"; Sprite = "KNIG"; Frame = 12; Tics = 6; Next state = "KNIGHT_DIE6"; } State { ID = "KNIGHT_DIE6"; Sprite = "KNIG"; Frame = 13; Tics = 6; Next state = "KNIGHT_DIE7"; } State { ID = "KNIGHT_DIE7"; Sprite = "KNIG"; Frame = 14; Tics = -1; Next state = "NULL"; } State { ID = "SPINAXE1"; Sprite = "SPAX"; Frame = 32768; Tics = 3; Action = "A_ContMobjSound"; Next state = "SPINAXE2"; } State { ID = "SPINAXE2"; Sprite = "SPAX"; Frame = 32769; Tics = 3; Next state = "SPINAXE3"; } State { ID = "SPINAXE3"; Sprite = "SPAX"; Frame = 32770; Tics = 3; Next state = "SPINAXE1"; } State { ID = "SPINAXEX1"; Sprite = "SPAX"; Frame = 32771; Tics = 6; Next state = "SPINAXEX2"; } State { ID = "SPINAXEX2"; Sprite = "SPAX"; Frame = 32772; Tics = 6; Next state = "SPINAXEX3"; } State { ID = "SPINAXEX3"; Sprite = "SPAX"; Frame = 32773; Tics = 6; Next state = "NULL"; } State { ID = "REDAXE1"; Sprite = "RAXE"; Frame = 32768; Tics = 5; Action = "A_DripBlood"; Next state = "REDAXE2"; } State { ID = "REDAXE2"; Sprite = "RAXE"; Frame = 32769; Tics = 5; Action = "A_DripBlood"; Next state = "REDAXE1"; } State { ID = "REDAXEX1"; Sprite = "RAXE"; Frame = 32770; Tics = 6; Next state = "REDAXEX2"; } State { ID = "REDAXEX2"; Sprite = "RAXE"; Frame = 32771; Tics = 6; Next state = "REDAXEX3"; } State { ID = "REDAXEX3"; Sprite = "RAXE"; Frame = 32772; Tics = 6; Next state = "NULL"; } State { ID = "SRCR1_LOOK1"; Sprite = "SRCR"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SRCR1_LOOK2"; } State { ID = "SRCR1_LOOK2"; Sprite = "SRCR"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SRCR1_LOOK1"; } State { ID = "SRCR1_WALK1"; Sprite = "SRCR"; Frame = 0; Tics = 5; Action = "A_Sor1Chase"; Next state = "SRCR1_WALK2"; } State { ID = "SRCR1_WALK2"; Sprite = "SRCR"; Frame = 1; Tics = 5; Action = "A_Sor1Chase"; Next state = "SRCR1_WALK3"; } State { ID = "SRCR1_WALK3"; Sprite = "SRCR"; Frame = 2; Tics = 5; Action = "A_Sor1Chase"; Next state = "SRCR1_WALK4"; } State { ID = "SRCR1_WALK4"; Sprite = "SRCR"; Frame = 3; Tics = 5; Action = "A_Sor1Chase"; Next state = "SRCR1_WALK1"; } State { ID = "SRCR1_PAIN1"; Sprite = "SRCR"; Frame = 16; Tics = 6; Action = "A_Sor1Pain"; Next state = "SRCR1_WALK1"; } State { ID = "SRCR1_ATK1"; Sprite = "SRCR"; Frame = 16; Tics = 7; Action = "A_FaceTarget"; Next state = "SRCR1_ATK2"; } State { ID = "SRCR1_ATK2"; Sprite = "SRCR"; Frame = 17; Tics = 6; Action = "A_FaceTarget"; Next state = "SRCR1_ATK3"; } State { ID = "SRCR1_ATK3"; Sprite = "SRCR"; Frame = 18; Tics = 10; Action = "A_Srcr1Attack"; Next state = "SRCR1_WALK1"; } State { ID = "SRCR1_ATK4"; Sprite = "SRCR"; Frame = 18; Tics = 10; Action = "A_FaceTarget"; Next state = "SRCR1_ATK5"; } State { ID = "SRCR1_ATK5"; Sprite = "SRCR"; Frame = 16; Tics = 7; Action = "A_FaceTarget"; Next state = "SRCR1_ATK6"; } State { ID = "SRCR1_ATK6"; Sprite = "SRCR"; Frame = 17; Tics = 6; Action = "A_FaceTarget"; Next state = "SRCR1_ATK7"; } State { ID = "SRCR1_ATK7"; Sprite = "SRCR"; Frame = 18; Tics = 10; Action = "A_Srcr1Attack"; Next state = "SRCR1_WALK1"; } State { ID = "SRCR1_DIE1"; Sprite = "SRCR"; Frame = 4; Tics = 7; Next state = "SRCR1_DIE2"; } State { ID = "SRCR1_DIE2"; Sprite = "SRCR"; Frame = 5; Tics = 7; Action = "A_Scream"; Next state = "SRCR1_DIE3"; } State { ID = "SRCR1_DIE3"; Sprite = "SRCR"; Frame = 6; Tics = 7; Next state = "SRCR1_DIE4"; } State { ID = "SRCR1_DIE4"; Sprite = "SRCR"; Frame = 7; Tics = 6; Next state = "SRCR1_DIE5"; } State { ID = "SRCR1_DIE5"; Sprite = "SRCR"; Frame = 8; Tics = 6; Next state = "SRCR1_DIE6"; } State { ID = "SRCR1_DIE6"; Sprite = "SRCR"; Frame = 9; Tics = 6; Next state = "SRCR1_DIE7"; } State { ID = "SRCR1_DIE7"; Sprite = "SRCR"; Frame = 10; Tics = 6; Next state = "SRCR1_DIE8"; } State { ID = "SRCR1_DIE8"; Sprite = "SRCR"; Frame = 11; Tics = 25; Action = "A_SorZap"; Next state = "SRCR1_DIE9"; } State { ID = "SRCR1_DIE9"; Sprite = "SRCR"; Frame = 12; Tics = 5; Next state = "SRCR1_DIE10"; } State { ID = "SRCR1_DIE10"; Sprite = "SRCR"; Frame = 13; Tics = 5; Next state = "SRCR1_DIE11"; } State { ID = "SRCR1_DIE11"; Sprite = "SRCR"; Frame = 14; Tics = 4; Next state = "SRCR1_DIE12"; } State { ID = "SRCR1_DIE12"; Sprite = "SRCR"; Frame = 11; Tics = 20; Action = "A_SorZap"; Next state = "SRCR1_DIE13"; } State { ID = "SRCR1_DIE13"; Sprite = "SRCR"; Frame = 12; Tics = 5; Next state = "SRCR1_DIE14"; } State { ID = "SRCR1_DIE14"; Sprite = "SRCR"; Frame = 13; Tics = 5; Next state = "SRCR1_DIE15"; } State { ID = "SRCR1_DIE15"; Sprite = "SRCR"; Frame = 14; Tics = 4; Next state = "SRCR1_DIE16"; } State { ID = "SRCR1_DIE16"; Sprite = "SRCR"; Frame = 11; Tics = 12; Next state = "SRCR1_DIE17"; } State { ID = "SRCR1_DIE17"; Sprite = "SRCR"; Frame = 15; Tics = -1; Action = "A_SorcererRise"; Next state = "NULL"; } State { ID = "SRCRFX1_1"; Sprite = "FX14"; Frame = 32768; Tics = 6; Next state = "SRCRFX1_2"; } State { ID = "SRCRFX1_2"; Sprite = "FX14"; Frame = 32769; Tics = 6; Next state = "SRCRFX1_3"; } State { ID = "SRCRFX1_3"; Sprite = "FX14"; Frame = 32770; Tics = 6; Next state = "SRCRFX1_1"; } State { ID = "SRCRFXI1_1"; Sprite = "FX14"; Frame = 32771; Tics = 5; Next state = "SRCRFXI1_2"; } State { ID = "SRCRFXI1_2"; Sprite = "FX14"; Frame = 32772; Tics = 5; Next state = "SRCRFXI1_3"; } State { ID = "SRCRFXI1_3"; Sprite = "FX14"; Frame = 32773; Tics = 5; Next state = "SRCRFXI1_4"; } State { ID = "SRCRFXI1_4"; Sprite = "FX14"; Frame = 32774; Tics = 5; Next state = "SRCRFXI1_5"; } State { ID = "SRCRFXI1_5"; Sprite = "FX14"; Frame = 32775; Tics = 5; Next state = "NULL"; } State { ID = "SOR2_RISE1"; Sprite = "SOR2"; Frame = 0; Tics = 4; Next state = "SOR2_RISE2"; } State { ID = "SOR2_RISE2"; Sprite = "SOR2"; Frame = 1; Tics = 4; Next state = "SOR2_RISE3"; } State { ID = "SOR2_RISE3"; Sprite = "SOR2"; Frame = 2; Tics = 4; Action = "A_SorRise"; Next state = "SOR2_RISE4"; } State { ID = "SOR2_RISE4"; Sprite = "SOR2"; Frame = 3; Tics = 4; Next state = "SOR2_RISE5"; } State { ID = "SOR2_RISE5"; Sprite = "SOR2"; Frame = 4; Tics = 4; Next state = "SOR2_RISE6"; } State { ID = "SOR2_RISE6"; Sprite = "SOR2"; Frame = 5; Tics = 4; Next state = "SOR2_RISE7"; } State { ID = "SOR2_RISE7"; Sprite = "SOR2"; Frame = 6; Tics = 12; Action = "A_SorSightSnd"; Next state = "SOR2_WALK1"; } State { ID = "SOR2_LOOK1"; Sprite = "SOR2"; Frame = 12; Tics = 10; Action = "A_Look"; Next state = "SOR2_LOOK2"; } State { ID = "SOR2_LOOK2"; Sprite = "SOR2"; Frame = 13; Tics = 10; Action = "A_Look"; Next state = "SOR2_LOOK1"; } State { ID = "SOR2_WALK1"; Sprite = "SOR2"; Frame = 12; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK2"; } State { ID = "SOR2_WALK2"; Sprite = "SOR2"; Frame = 13; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK3"; } State { ID = "SOR2_WALK3"; Sprite = "SOR2"; Frame = 14; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK4"; } State { ID = "SOR2_WALK4"; Sprite = "SOR2"; Frame = 15; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK5"; } State { ID = "SOR2_PAIN1"; Sprite = "SOR2"; Frame = 16; Tics = 3; Next state = "SOR2_PAIN2"; } State { ID = "SOR2_PAIN2"; Sprite = "SOR2"; Frame = 16; Tics = 6; Action = "A_Pain"; Next state = "SOR2_WALK1"; } State { ID = "SOR2_ATK1"; Sprite = "SOR2"; Frame = 17; Tics = 9; Action = "A_Srcr2Decide"; Next state = "SOR2_ATK2"; } State { ID = "SOR2_ATK2"; Sprite = "SOR2"; Frame = 18; Tics = 9; Action = "A_FaceTarget"; Next state = "SOR2_ATK3"; } State { ID = "SOR2_ATK3"; Sprite = "SOR2"; Frame = 19; Tics = 20; Action = "A_Srcr2Attack"; Next state = "SOR2_WALK1"; } State { ID = "SOR2_TELE1"; Sprite = "SOR2"; Frame = 11; Tics = 6; Next state = "SOR2_TELE2"; } State { ID = "SOR2_TELE2"; Sprite = "SOR2"; Frame = 10; Tics = 6; Next state = "SOR2_TELE3"; } State { ID = "SOR2_TELE3"; Sprite = "SOR2"; Frame = 9; Tics = 6; Next state = "SOR2_TELE4"; } State { ID = "SOR2_TELE4"; Sprite = "SOR2"; Frame = 8; Tics = 6; Next state = "SOR2_TELE5"; } State { ID = "SOR2_TELE5"; Sprite = "SOR2"; Frame = 7; Tics = 6; Next state = "SOR2_TELE6"; } State { ID = "SOR2_TELE6"; Sprite = "SOR2"; Frame = 6; Tics = 6; Next state = "SOR2_WALK1"; } State { ID = "SOR2_DIE1"; Sprite = "SDTH"; Frame = 0; Tics = 8; Action = "A_Sor2DthInit"; Next state = "SOR2_DIE2"; } State { ID = "SOR2_DIE2"; Sprite = "SDTH"; Frame = 32769; Tics = 8; Next state = "SOR2_DIE3"; } State { ID = "SOR2_DIE3"; Sprite = "SDTH"; Frame = 32770; Tics = 8; Action = "A_SorDSph"; Next state = "SOR2_DIE4"; } State { ID = "SOR2_DIE4"; Sprite = "SDTH"; Frame = 32771; Tics = 7; Next state = "SOR2_DIE5"; } State { ID = "SOR2_DIE5"; Sprite = "SDTH"; Frame = 32772; Tics = 7; Next state = "SOR2_DIE6"; } State { ID = "SOR2_DIE6"; Sprite = "SDTH"; Frame = 32773; Tics = 7; Action = "A_Sor2DthLoop"; Next state = "SOR2_DIE7"; } State { ID = "SOR2_DIE7"; Sprite = "SDTH"; Frame = 32774; Tics = 6; Action = "A_SorDExp"; Next state = "SOR2_DIE8"; } State { ID = "SOR2_DIE8"; Sprite = "SDTH"; Frame = 32775; Tics = 6; Next state = "SOR2_DIE9"; } State { ID = "SOR2_DIE9"; Sprite = "SDTH"; Frame = 8; Tics = 18; Next state = "SOR2_DIE10"; } State { ID = "SOR2_DIE10"; Sprite = "SDTH"; Frame = 9; Tics = 6; Action = "A_NoBlocking"; Next state = "SOR2_DIE11"; } State { ID = "SOR2_DIE11"; Sprite = "SDTH"; Frame = 10; Tics = 6; Action = "A_SorDBon"; Next state = "SOR2_DIE12"; } State { ID = "SOR2_DIE12"; Sprite = "SDTH"; Frame = 11; Tics = 6; Next state = "SOR2_DIE13"; } State { ID = "SOR2_DIE13"; Sprite = "SDTH"; Frame = 12; Tics = 6; Next state = "SOR2_DIE14"; } State { ID = "SOR2_DIE14"; Sprite = "SDTH"; Frame = 13; Tics = 6; Next state = "SOR2_DIE15"; } State { ID = "SOR2_DIE15"; Sprite = "SDTH"; Frame = 14; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "SOR2FX1_1"; Sprite = "FX16"; Frame = 32768; Tics = 3; Action = "A_BlueSpark"; Next state = "SOR2FX1_2"; } State { ID = "SOR2FX1_2"; Sprite = "FX16"; Frame = 32769; Tics = 3; Action = "A_BlueSpark"; Next state = "SOR2FX1_3"; } State { ID = "SOR2FX1_3"; Sprite = "FX16"; Frame = 32770; Tics = 3; Action = "A_BlueSpark"; Next state = "SOR2FX1_1"; } State { ID = "SOR2FXI1_1"; Sprite = "FX16"; Frame = 32774; Tics = 5; Action = "A_Explode"; Next state = "SOR2FXI1_2"; } State { ID = "SOR2FXI1_2"; Sprite = "FX16"; Frame = 32775; Tics = 5; Next state = "SOR2FXI1_3"; } State { ID = "SOR2FXI1_3"; Sprite = "FX16"; Frame = 32776; Tics = 5; Next state = "SOR2FXI1_4"; } State { ID = "SOR2FXI1_4"; Sprite = "FX16"; Frame = 32777; Tics = 5; Next state = "SOR2FXI1_5"; } State { ID = "SOR2FXI1_5"; Sprite = "FX16"; Frame = 32778; Tics = 5; Next state = "SOR2FXI1_6"; } State { ID = "SOR2FXI1_6"; Sprite = "FX16"; Frame = 32779; Tics = 5; Next state = "NULL"; } State { ID = "SOR2FXSPARK1"; Sprite = "FX16"; Frame = 32771; Tics = 12; Next state = "SOR2FXSPARK2"; } State { ID = "SOR2FXSPARK2"; Sprite = "FX16"; Frame = 32772; Tics = 12; Next state = "SOR2FXSPARK3"; } State { ID = "SOR2FXSPARK3"; Sprite = "FX16"; Frame = 32773; Tics = 12; Next state = "NULL"; } State { ID = "SOR2FX2_1"; Sprite = "FX11"; Frame = 32768; Tics = 35; Next state = "SOR2FX2_2"; } State { ID = "SOR2FX2_2"; Sprite = "FX11"; Frame = 32768; Tics = 5; Action = "A_GenWizard"; Next state = "SOR2FX2_3"; } State { ID = "SOR2FX2_3"; Sprite = "FX11"; Frame = 32769; Tics = 5; Next state = "SOR2FX2_2"; } State { ID = "SOR2FXI2_1"; Sprite = "FX11"; Frame = 32770; Tics = 5; Next state = "SOR2FXI2_2"; } State { ID = "SOR2FXI2_2"; Sprite = "FX11"; Frame = 32771; Tics = 5; Next state = "SOR2FXI2_3"; } State { ID = "SOR2FXI2_3"; Sprite = "FX11"; Frame = 32772; Tics = 5; Next state = "SOR2FXI2_4"; } State { ID = "SOR2FXI2_4"; Sprite = "FX11"; Frame = 32773; Tics = 5; Next state = "SOR2FXI2_5"; } State { ID = "SOR2FXI2_5"; Sprite = "FX11"; Frame = 32774; Tics = 5; Next state = "NULL"; } State { ID = "SOR2TELEFADE1"; Sprite = "SOR2"; Frame = 6; Tics = 8; Next state = "SOR2TELEFADE2"; } State { ID = "SOR2TELEFADE2"; Sprite = "SOR2"; Frame = 7; Tics = 6; Next state = "SOR2TELEFADE3"; } State { ID = "SOR2TELEFADE3"; Sprite = "SOR2"; Frame = 8; Tics = 6; Next state = "SOR2TELEFADE4"; } State { ID = "SOR2TELEFADE4"; Sprite = "SOR2"; Frame = 9; Tics = 6; Next state = "SOR2TELEFADE5"; } State { ID = "SOR2TELEFADE5"; Sprite = "SOR2"; Frame = 10; Tics = 6; Next state = "SOR2TELEFADE6"; } State { ID = "SOR2TELEFADE6"; Sprite = "SOR2"; Frame = 11; Tics = 6; Next state = "NULL"; } State { ID = "MNTR_LOOK1"; Sprite = "MNTR"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "MNTR_LOOK2"; } State { ID = "MNTR_LOOK2"; Sprite = "MNTR"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "MNTR_LOOK1"; } State { ID = "MNTR_WALK1"; Sprite = "MNTR"; Frame = 0; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK2"; } State { ID = "MNTR_WALK2"; Sprite = "MNTR"; Frame = 1; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK3"; } State { ID = "MNTR_WALK3"; Sprite = "MNTR"; Frame = 2; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK4"; } State { ID = "MNTR_WALK4"; Sprite = "MNTR"; Frame = 3; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK5"; } State { ID = "MNTR_ATK1_1"; Sprite = "MNTR"; Frame = 21; Tics = 10; Action = "A_FaceTarget"; Next state = "MNTR_ATK1_2"; } State { ID = "MNTR_ATK1_2"; Sprite = "MNTR"; Frame = 22; Tics = 7; Action = "A_FaceTarget"; Next state = "MNTR_ATK1_3"; } State { ID = "MNTR_ATK1_3"; Sprite = "MNTR"; Frame = 23; Tics = 12; Action = "A_MinotaurAtk1"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_ATK2_1"; Sprite = "MNTR"; Frame = 21; Tics = 10; Action = "A_MinotaurDecide"; Next state = "MNTR_ATK2_2"; } State { ID = "MNTR_ATK2_2"; Sprite = "MNTR"; Frame = 24; Tics = 4; Action = "A_FaceTarget"; Next state = "MNTR_ATK2_3"; } State { ID = "MNTR_ATK2_3"; Sprite = "MNTR"; Frame = 25; Tics = 9; Action = "A_MinotaurAtk2"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_ATK3_1"; Sprite = "MNTR"; Frame = 21; Tics = 10; Action = "A_FaceTarget"; Next state = "MNTR_ATK3_2"; } State { ID = "MNTR_ATK3_2"; Sprite = "MNTR"; Frame = 22; Tics = 7; Action = "A_FaceTarget"; Next state = "MNTR_ATK3_3"; } State { ID = "MNTR_ATK3_3"; Sprite = "MNTR"; Frame = 23; Tics = 12; Action = "A_MinotaurAtk3"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_ATK3_4"; Sprite = "MNTR"; Frame = 23; Tics = 12; Next state = "MNTR_ATK3_1"; } State { ID = "MNTR_ATK4_1"; Sprite = "MNTR"; Frame = 20; Tics = 2; Action = "A_MinotaurCharge"; Next state = "MNTR_ATK4_1"; } State { ID = "MNTR_PAIN1"; Sprite = "MNTR"; Frame = 4; Tics = 3; Next state = "MNTR_PAIN2"; } State { ID = "MNTR_PAIN2"; Sprite = "MNTR"; Frame = 4; Tics = 6; Action = "A_Pain"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_DIE1"; Sprite = "MNTR"; Frame = 5; Tics = 5; Next state = "MNTR_DIE2"; } State { ID = "MNTR_DIE2"; Sprite = "MNTR"; Frame = 6; Tics = 5; Next state = "MNTR_DIE3"; } State { ID = "MNTR_DIE3"; Sprite = "MNTR"; Frame = 7; Tics = 6; Action = "A_Scream"; Next state = "MNTR_DIE4"; } State { ID = "MNTR_DIE4"; Sprite = "MNTR"; Frame = 8; Tics = 5; Next state = "MNTR_DIE5"; } State { ID = "MNTR_DIE5"; Sprite = "MNTR"; Frame = 9; Tics = 6; Next state = "MNTR_DIE6"; } State { ID = "MNTR_DIE6"; Sprite = "MNTR"; Frame = 10; Tics = 5; Next state = "MNTR_DIE7"; } State { ID = "MNTR_DIE7"; Sprite = "MNTR"; Frame = 11; Tics = 6; Next state = "MNTR_DIE8"; } State { ID = "MNTR_DIE8"; Sprite = "MNTR"; Frame = 12; Tics = 5; Action = "A_NoBlocking"; Next state = "MNTR_DIE9"; } State { ID = "MNTR_DIE9"; Sprite = "MNTR"; Frame = 13; Tics = 6; Next state = "MNTR_DIE10"; } State { ID = "MNTR_DIE10"; Sprite = "MNTR"; Frame = 14; Tics = 5; Next state = "MNTR_DIE11"; } State { ID = "MNTR_DIE11"; Sprite = "MNTR"; Frame = 15; Tics = 6; Next state = "MNTR_DIE12"; } State { ID = "MNTR_DIE12"; Sprite = "MNTR"; Frame = 16; Tics = 5; Next state = "MNTR_DIE13"; } State { ID = "MNTR_DIE13"; Sprite = "MNTR"; Frame = 17; Tics = 6; Next state = "MNTR_DIE14"; } State { ID = "MNTR_DIE14"; Sprite = "MNTR"; Frame = 18; Tics = 5; Next state = "MNTR_DIE15"; } State { ID = "MNTR_DIE15"; Sprite = "MNTR"; Frame = 19; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "MNTRFX1_1"; Sprite = "FX12"; Frame = 32768; Tics = 6; Next state = "MNTRFX1_2"; } State { ID = "MNTRFX1_2"; Sprite = "FX12"; Frame = 32769; Tics = 6; Next state = "MNTRFX1_1"; } State { ID = "MNTRFXI1_1"; Sprite = "FX12"; Frame = 32770; Tics = 5; Next state = "MNTRFXI1_2"; } State { ID = "MNTRFXI1_2"; Sprite = "FX12"; Frame = 32771; Tics = 5; Next state = "MNTRFXI1_3"; } State { ID = "MNTRFXI1_3"; Sprite = "FX12"; Frame = 32772; Tics = 5; Next state = "MNTRFXI1_4"; } State { ID = "MNTRFXI1_4"; Sprite = "FX12"; Frame = 32773; Tics = 5; Next state = "MNTRFXI1_5"; } State { ID = "MNTRFXI1_5"; Sprite = "FX12"; Frame = 32774; Tics = 5; Next state = "MNTRFXI1_6"; } State { ID = "MNTRFXI1_6"; Sprite = "FX12"; Frame = 32775; Tics = 5; Next state = "NULL"; } State { ID = "MNTRFX2_1"; Sprite = "FX13"; Frame = 0; Tics = 2; Action = "A_MntrFloorFire"; Next state = "MNTRFX2_1"; } State { ID = "MNTRFXI2_1"; Sprite = "FX13"; Frame = 32776; Tics = 4; Action = "A_Explode"; Next state = "MNTRFXI2_2"; } State { ID = "MNTRFXI2_2"; Sprite = "FX13"; Frame = 32777; Tics = 4; Next state = "MNTRFXI2_3"; } State { ID = "MNTRFXI2_3"; Sprite = "FX13"; Frame = 32778; Tics = 4; Next state = "MNTRFXI2_4"; } State { ID = "MNTRFXI2_4"; Sprite = "FX13"; Frame = 32779; Tics = 4; Next state = "MNTRFXI2_5"; } State { ID = "MNTRFXI2_5"; Sprite = "FX13"; Frame = 32780; Tics = 4; Next state = "NULL"; } State { ID = "MNTRFX3_1"; Sprite = "FX13"; Frame = 32771; Tics = 4; Next state = "MNTRFX3_2"; } State { ID = "MNTRFX3_2"; Sprite = "FX13"; Frame = 32770; Tics = 4; Next state = "MNTRFX3_3"; } State { ID = "MNTRFX3_3"; Sprite = "FX13"; Frame = 32769; Tics = 5; Next state = "MNTRFX3_4"; } State { ID = "MNTRFX3_4"; Sprite = "FX13"; Frame = 32770; Tics = 5; Next state = "MNTRFX3_5"; } State { ID = "MNTRFX3_5"; Sprite = "FX13"; Frame = 32771; Tics = 5; Next state = "MNTRFX3_6"; } State { ID = "MNTRFX3_6"; Sprite = "FX13"; Frame = 32772; Tics = 5; Next state = "MNTRFX3_7"; } State { ID = "MNTRFX3_7"; Sprite = "FX13"; Frame = 32773; Tics = 4; Next state = "MNTRFX3_8"; } State { ID = "MNTRFX3_8"; Sprite = "FX13"; Frame = 32774; Tics = 4; Next state = "MNTRFX3_9"; } State { ID = "MNTRFX3_9"; Sprite = "FX13"; Frame = 32775; Tics = 4; Next state = "NULL"; } State { ID = "AKYY1"; Sprite = "AKYY"; Frame = 32768; Tics = 3; Next state = "AKYY2"; } State { ID = "AKYY2"; Sprite = "AKYY"; Frame = 32769; Tics = 3; Next state = "AKYY3"; } State { ID = "AKYY3"; Sprite = "AKYY"; Frame = 32770; Tics = 3; Next state = "AKYY4"; } State { ID = "AKYY4"; Sprite = "AKYY"; Frame = 32771; Tics = 3; Next state = "AKYY5"; } State { ID = "AKYY5"; Sprite = "AKYY"; Frame = 32772; Tics = 3; Next state = "AKYY6"; } State { ID = "AKYY6"; Sprite = "AKYY"; Frame = 32773; Tics = 3; Next state = "AKYY7"; } State { ID = "AKYY7"; Sprite = "AKYY"; Frame = 32774; Tics = 3; Next state = "AKYY8"; } State { ID = "AKYY8"; Sprite = "AKYY"; Frame = 32775; Tics = 3; Next state = "AKYY9"; } State { ID = "AKYY9"; Sprite = "AKYY"; Frame = 32776; Tics = 3; Next state = "AKYY10"; } State { ID = "AKYY10"; Sprite = "AKYY"; Frame = 32777; Tics = 3; Next state = "AKYY1"; } State { ID = "BKYY1"; Sprite = "BKYY"; Frame = 32768; Tics = 3; Next state = "BKYY2"; } State { ID = "BKYY2"; Sprite = "BKYY"; Frame = 32769; Tics = 3; Next state = "BKYY3"; } State { ID = "BKYY3"; Sprite = "BKYY"; Frame = 32770; Tics = 3; Next state = "BKYY4"; } State { ID = "BKYY4"; Sprite = "BKYY"; Frame = 32771; Tics = 3; Next state = "BKYY5"; } State { ID = "BKYY5"; Sprite = "BKYY"; Frame = 32772; Tics = 3; Next state = "BKYY6"; } State { ID = "BKYY6"; Sprite = "BKYY"; Frame = 32773; Tics = 3; Next state = "BKYY7"; } State { ID = "BKYY7"; Sprite = "BKYY"; Frame = 32774; Tics = 3; Next state = "BKYY8"; } State { ID = "BKYY8"; Sprite = "BKYY"; Frame = 32775; Tics = 3; Next state = "BKYY9"; } State { ID = "BKYY9"; Sprite = "BKYY"; Frame = 32776; Tics = 3; Next state = "BKYY10"; } State { ID = "BKYY10"; Sprite = "BKYY"; Frame = 32777; Tics = 3; Next state = "BKYY1"; } State { ID = "CKYY1"; Sprite = "CKYY"; Frame = 32768; Tics = 3; Next state = "CKYY2"; } State { ID = "CKYY2"; Sprite = "CKYY"; Frame = 32769; Tics = 3; Next state = "CKYY3"; } State { ID = "CKYY3"; Sprite = "CKYY"; Frame = 32770; Tics = 3; Next state = "CKYY4"; } State { ID = "CKYY4"; Sprite = "CKYY"; Frame = 32771; Tics = 3; Next state = "CKYY5"; } State { ID = "CKYY5"; Sprite = "CKYY"; Frame = 32772; Tics = 3; Next state = "CKYY6"; } State { ID = "CKYY6"; Sprite = "CKYY"; Frame = 32773; Tics = 3; Next state = "CKYY7"; } State { ID = "CKYY7"; Sprite = "CKYY"; Frame = 32774; Tics = 3; Next state = "CKYY8"; } State { ID = "CKYY8"; Sprite = "CKYY"; Frame = 32775; Tics = 3; Next state = "CKYY9"; } State { ID = "CKYY9"; Sprite = "CKYY"; Frame = 32776; Tics = 3; Next state = "CKYY1"; } State { ID = "AMG1"; Sprite = "AMG1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "AMG2_1"; Sprite = "AMG2"; Frame = 0; Tics = 4; Next state = "AMG2_2"; } State { ID = "AMG2_2"; Sprite = "AMG2"; Frame = 1; Tics = 4; Next state = "AMG2_3"; } State { ID = "AMG2_3"; Sprite = "AMG2"; Frame = 2; Tics = 4; Next state = "AMG2_1"; } State { ID = "AMM1"; Sprite = "AMM1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "AMM2"; Sprite = "AMM2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "AMC1"; Sprite = "AMC1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "AMC2_1"; Sprite = "AMC2"; Frame = 0; Tics = 5; Next state = "AMC2_2"; } State { ID = "AMC2_2"; Sprite = "AMC2"; Frame = 1; Tics = 5; Next state = "AMC2_3"; } State { ID = "AMC2_3"; Sprite = "AMC2"; Frame = 2; Tics = 5; Next state = "AMC2_1"; } State { ID = "AMS1_1"; Sprite = "AMS1"; Frame = 32768; Tics = 5; Next state = "AMS1_2"; } State { ID = "AMS1_2"; Sprite = "AMS1"; Frame = 32769; Tics = 5; Next state = "AMS1_1"; } State { ID = "AMS2_1"; Sprite = "AMS2"; Frame = 32768; Tics = 5; Next state = "AMS2_2"; } State { ID = "AMS2_2"; Sprite = "AMS2"; Frame = 32769; Tics = 5; Next state = "AMS2_1"; } State { ID = "AMP1_1"; Sprite = "AMP1"; Frame = 32768; Tics = 4; Next state = "AMP1_2"; } State { ID = "AMP1_2"; Sprite = "AMP1"; Frame = 32769; Tics = 4; Next state = "AMP1_3"; } State { ID = "AMP1_3"; Sprite = "AMP1"; Frame = 32770; Tics = 4; Next state = "AMP1_1"; } State { ID = "AMP2_1"; Sprite = "AMP2"; Frame = 32768; Tics = 4; Next state = "AMP2_2"; } State { ID = "AMP2_2"; Sprite = "AMP2"; Frame = 32769; Tics = 4; Next state = "AMP2_3"; } State { ID = "AMP2_3"; Sprite = "AMP2"; Frame = 32770; Tics = 4; Next state = "AMP2_1"; } State { ID = "AMB1_1"; Sprite = "AMB1"; Frame = 32768; Tics = 4; Next state = "AMB1_2"; } State { ID = "AMB1_2"; Sprite = "AMB1"; Frame = 32769; Tics = 4; Next state = "AMB1_3"; } State { ID = "AMB1_3"; Sprite = "AMB1"; Frame = 32770; Tics = 4; Next state = "AMB1_1"; } State { ID = "AMB2_1"; Sprite = "AMB2"; Frame = 32768; Tics = 4; Next state = "AMB2_2"; } State { ID = "AMB2_2"; Sprite = "AMB2"; Frame = 32769; Tics = 4; Next state = "AMB2_3"; } State { ID = "AMB2_3"; Sprite = "AMB2"; Frame = 32770; Tics = 4; Next state = "AMB2_1"; } State { ID = "SND_WIND"; Sprite = "AMG1"; Frame = 0; Tics = 100; Action = "A_ESound"; Next state = "SND_WIND"; } State { ID = "SND_WATERFALL"; Sprite = "AMG1"; Frame = 0; Tics = 85; Action = "A_ESound"; Next state = "SND_WATERFALL"; } Thing { ID = "TEMPSOUNDORIGIN"; DoomEd number = -1; Spawn state = "TEMPSOUNDORIGIN1"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Radius = 1; Height = 1; Mass = 100; Flags = "mf_local mf_nosector mf_noblockmap mf_nogravity"; Flags2 = "mf2_dontdraw"; } State { ID = "TEMPSOUNDORIGIN1"; Tics = 175; Next state = "NULL"; } ####====---- Extra states for the Sabreclaw/Clink ----====#### # The same sprite frames are used as in the original four states. # A_Chase is called at the original pace. State { ID = "CLINK_WALK5"; Sprite = "CLNK"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK6"; } State { ID = "CLINK_WALK6"; Sprite = "CLNK"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK7"; } State { ID = "CLINK_WALK7"; Sprite = "CLNK"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK8"; } State { ID = "CLINK_WALK8"; Sprite = "CLNK"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "CLINK_WALK1"; } ####====---- Extra states for the Minotaur ----====#### # The same sprite frames are used as in the original four states. # A_Chase is called at the original pace. State { ID = "MNTR_WALK5"; Sprite = "MNTR"; Frame = 0; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK6"; } State { ID = "MNTR_WALK6"; Sprite = "MNTR"; Frame = 1; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK7"; } State { ID = "MNTR_WALK7"; Sprite = "MNTR"; Frame = 2; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK8"; } State { ID = "MNTR_WALK8"; Sprite = "MNTR"; Frame = 3; Tics = 5; Action = "A_Chase"; Next state = "MNTR_WALK1"; } ####====---- Extra states for D'Sparil ----====#### # The same sprite frames are used as in the original four states. # The 3D model's walk animation is too fast without these frames. State { ID = "SOR2_WALK5"; Sprite = "SOR2"; Frame = 12; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK6"; } State { ID = "SOR2_WALK6"; Sprite = "SOR2"; Frame = 13; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK7"; } State { ID = "SOR2_WALK7"; Sprite = "SOR2"; Frame = 14; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK8"; } State { ID = "SOR2_WALK8"; Sprite = "SOR2"; Frame = 15; Tics = 4; Action = "A_Chase"; Next state = "SOR2_WALK1"; } ####====---- Extra states for hanging skulls ----====#### # To allow animation. State { ID = "SKULLHANG70_2"; Sprite = "SKH1"; Frame = 0; Tics = 65; Next state = "SKULLHANG70_1"; } State { ID = "SKULLHANG60_2"; Sprite = "SKH2"; Frame = 0; Tics = 70; Next state = "SKULLHANG60_1"; } State { ID = "SKULLHANG45_2"; Sprite = "SKH3"; Frame = 0; Tics = 80; Next state = "SKULLHANG45_1"; } State { ID = "SKULLHANG35_2"; Sprite = "SKH4"; Frame = 0; Tics = 65; Next state = "SKULLHANG35_1"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/text.ded0000644000175000017500000004152511357170242022735 0ustar keeskees# jHeretic: Text Strings Header { Version = 5; } Text { ID = "PRESSKEY"; Text = "Press a key."; } Text { ID = "PRESSYN"; Text = "Press %1 or %2."; } Text { ID = "TXT_PAUSED"; Text = "Paused"; } Text { ID = "QUITMSG"; Text = "Are you sure you want to quit?"; } Text { ID = "LOADNET"; Text = "You can't do load while in a net game!"; } Text { ID = "QLOADNET"; Text = "You can't quickload during a netgame!"; } Text { ID = "QSAVESPOT"; Text = "You haven't picked a quicksave slot yet!"; } Text { ID = "SAVEDEAD"; Text = "You can't save if you aren't playing!"; } Text { ID = "QSPROMPT"; Text = "Quicksave over your game named\n\n'%s'?"; } Text { ID = "QLPROMPT"; Text = "Do you want to quickload the game named\n\n'%s'?"; } Text { ID = "NEWGAME"; Text = "You can't start a new game\nwhile in a network game."; } Text { ID = "NIGHTMARE"; Text = "Are you sure? This skill level\nisn't even remotely fair."; } Text { ID = "SWSTRING"; Text = "This is the shareware version of Heretic.\n\nYou need to order the entire trilogy."; } Text { ID = "MSGOFF"; Text = "Messages OFF"; } Text { ID = "MSGON"; Text = "Messages ON"; } Text { ID = "NETEND"; Text = "You can't end a netgame!"; } Text { ID = "ENDGAME"; Text = "Are you sure you want to end the game?"; } Text { ID = "DOSY"; Text = "(Press %1 to quit to dos.)"; } Text { ID = "DETAILHI"; Text = "High detail"; } Text { ID = "DETAILLO"; Text = "Low detail"; } Text { ID = "GAMMALVL0"; Text = "Gamma correction OFF"; } Text { ID = "GAMMALVL1"; Text = "Gamma correction level 1"; } Text { ID = "GAMMALVL2"; Text = "Gamma correction level 2"; } Text { ID = "GAMMALVL3"; Text = "Gamma correction level 3"; } Text { ID = "GAMMALVL4"; Text = "Gamma correction level 4"; } Text { ID = "EMPTYSTRING"; Text = "Empty slot"; } Text { ID = "TXT_GOTBLUEKEY"; Text = "Blue Key"; } Text { ID = "TXT_GOTYELLOWKEY"; Text = "Yellow Key"; } Text { ID = "TXT_GOTGREENKEY"; Text = "Green Key"; } Text { ID = "TXT_ARTIHEALTH"; Text = "Quartz Flask"; } Text { ID = "TXT_ARTIFLY"; Text = "Wings of Wrath"; } Text { ID = "TXT_ARTIINVULNERABILITY"; Text = "Ring of Invincibility"; } Text { ID = "TXT_ARTITOMEOFPOWER"; Text = "Tome of Power"; } Text { ID = "TXT_ARTIINVISIBILITY"; Text = "Shadowsphere"; } Text { ID = "TXT_ARTIEGG"; Text = "Morph Ovum"; } Text { ID = "TXT_ARTISUPERHEALTH"; Text = "Mystic Urn"; } Text { ID = "TXT_ARTITORCH"; Text = "Torch"; } Text { ID = "TXT_ARTIFIREBOMB"; Text = "Time Bomb of the Ancients"; } Text { ID = "TXT_ARTITELEPORT"; Text = "Chaos Device"; } Text { ID = "TXT_ITEMHEALTH"; Text = "Crystal Vial"; } Text { ID = "TXT_ITEMBAGOFHOLDING"; Text = "Bag of Holding"; } Text { ID = "TXT_ITEMSHIELD1"; Text = "Silver Shield"; } Text { ID = "TXT_ITEMSHIELD2"; Text = "Enchanted Shield"; } Text { ID = "TXT_ITEMSUPERMAP"; Text = "Map Scroll"; } Text { ID = "TXT_AMMOGOLDWAND1"; Text = "Wand Crystal"; } Text { ID = "TXT_AMMOGOLDWAND2"; Text = "Crystal Geode"; } Text { ID = "TXT_AMMOMACE1"; Text = "Mace Spheres"; } Text { ID = "TXT_AMMOMACE2"; Text = "Pile of Mace Spheres"; } Text { ID = "TXT_AMMOCROSSBOW1"; Text = "Ethereal Arrows"; } Text { ID = "TXT_AMMOCROSSBOW2"; Text = "Quiver of Ethereal Arrows"; } Text { ID = "TXT_AMMOBLASTER1"; Text = "Claw Orb"; } Text { ID = "TXT_AMMOBLASTER2"; Text = "Energy Orb"; } Text { ID = "TXT_AMMOSKULLROD1"; Text = "Lesser Runes"; } Text { ID = "TXT_AMMOSKULLROD2"; Text = "Greater Runes"; } Text { ID = "TXT_AMMOPHOENIXROD1"; Text = "Flame Orb"; } Text { ID = "TXT_AMMOPHOENIXROD2"; Text = "Inferno Orb"; } Text { ID = "TXT_WPNSTAFF"; Text = "Staff"; } Text { ID = "TXT_WPNWAND"; Text = "Crystal Wand"; } Text { ID = "TXT_WPNCROSSBOW"; Text = "Ethereal Crossbow"; } Text { ID = "TXT_WPNBLASTER"; Text = "Dragon Claw"; } Text { ID = "TXT_WPNSKULLROD"; Text = "Hellstaff"; } Text { ID = "TXT_WPNPHOENIXROD"; Text = "Phoenix Rod"; } Text { ID = "TXT_WPNMACE"; Text = "Firemace"; } Text { ID = "TXT_WPNGAUNTLETS"; Text = "Gauntlets of the Necromancer"; } Text { ID = "TXT_WPNBEAK"; Text = "Beak"; } Text { ID = "TXT_CHEATGODON"; Text = "God mode ON"; } Text { ID = "TXT_CHEATGODOFF"; Text = "God mode OFF"; } Text { ID = "TXT_CHEATNOCLIPON"; Text = "No clipping ON"; } Text { ID = "TXT_CHEATNOCLIPOFF"; Text = "No clipping OFF"; } Text { ID = "TXT_CHEATWEAPONS"; Text = "All weapons"; } Text { ID = "TXT_CHEATFLIGHTON"; Text = "Flight ON"; } Text { ID = "TXT_CHEATFLIGHTOFF"; Text = "Flight OFF"; } Text { ID = "TXT_CHEATPOWERON"; Text = "Power ON"; } Text { ID = "TXT_CHEATPOWEROFF"; Text = "Power OFF"; } Text { ID = "TXT_CHEATHEALTH"; Text = "Full Health"; } Text { ID = "TXT_CHEATKEYS"; Text = "All keys"; } Text { ID = "TXT_CHEATSOUNDON"; Text = "Sound debug ON"; } Text { ID = "TXT_CHEATSOUNDOFF"; Text = "Sound debug OFF"; } Text { ID = "TXT_CHEATTICKERON"; Text = "Ticker ON"; } Text { ID = "TXT_CHEATTICKEROFF"; Text = "Ticker OFF"; } Text { ID = "TXT_CHEATARTIFACTS1"; Text = "Choose an Artifact ( A - J )"; } Text { ID = "TXT_CHEATARTIFACTS2"; Text = "How many ( 1 - 9 )"; } Text { ID = "TXT_CHEATARTIFACTS3"; Text = "You got it"; } Text { ID = "TXT_CHEATARTIFACTSFAIL"; Text = "Bad input"; } Text { ID = "TXT_CHEATWARP"; Text = "Map warp"; } Text { ID = "TXT_CHEATSCREENSHOT"; Text = "Screenshot"; } Text { ID = "TXT_CHEATCHICKENON"; Text = "Chicken ON"; } Text { ID = "TXT_CHEATCHICKENOFF"; Text = "Chicken OFF"; } Text { ID = "TXT_CHEATMASSACRE"; Text = "Massacre"; } Text { ID = "TXT_CHEATIDDQD"; Text = "Trying to cheat, eh? Now you die!"; } Text { ID = "TXT_CHEATIDKFA"; Text = "Cheater - You don't deserve weapons"; } Text { ID = "TXT_NEEDBLUEKEY"; Text = "You need a %1 to open this door"; } Text { ID = "TXT_NEEDGREENKEY"; Text = "You need a %1 to open this door"; } Text { ID = "TXT_NEEDYELLOWKEY"; Text = "You need a %1 to open this door"; } Text { ID = "TXT_GAMESAVED"; Text = "Game saved"; } Text { ID = "HUSTR_CHATMACRO0"; Text = "No"; } Text { ID = "HUSTR_CHATMACRO1"; Text = "I'm ready to kick butt!"; } Text { ID = "HUSTR_CHATMACRO2"; Text = "I'm OK."; } Text { ID = "HUSTR_CHATMACRO3"; Text = "I'm not looking too good!"; } Text { ID = "HUSTR_CHATMACRO4"; Text = "Help!"; } Text { ID = "HUSTR_CHATMACRO5"; Text = "You suck!"; } Text { ID = "HUSTR_CHATMACRO6"; Text = "Next time, scumbag..."; } Text { ID = "HUSTR_CHATMACRO7"; Text = "Come here!"; } Text { ID = "HUSTR_CHATMACRO8"; Text = "I'll take care of it."; } Text { ID = "HUSTR_CHATMACRO9"; Text = "Yes"; } Text { ID = "HUSTR_TALKTOSELF1"; Text = "You mumble to yourself"; } Text { ID = "HUSTR_TALKTOSELF2"; Text = "Who's there?"; } Text { ID = "HUSTR_TALKTOSELF3"; Text = "You scare yourself"; } Text { ID = "HUSTR_TALKTOSELF4"; Text = "You start to rave"; } Text { ID = "HUSTR_TALKTOSELF5"; Text = "You've lost it..."; } Text { ID = "HUSTR_MESSAGESENT"; Text = "[Message Sent]"; } Text { ID = "HUSTR_PLRGREEN"; Text = "Green: "; } Text { ID = "HUSTR_PLRINDIGO"; Text = "Indigo: "; } Text { ID = "HUSTR_PLRBROWN"; Text = "Brown: "; } Text { ID = "HUSTR_PLRRED"; Text = "Red: "; } Text { ID = "AMSTR_FOLLOWON"; Text = "Follow mode ON"; } Text { ID = "AMSTR_FOLLOWOFF"; Text = "Follow mode OFF"; } Text { ID = "AMSTR_GRIDON"; Text = "Grid ON"; } Text { ID = "AMSTR_GRIDOFF"; Text = "Grid OFF"; } Text { ID = "AMSTR_MARKEDSPOT"; Text = "Marked spot"; } Text { ID = "AMSTR_MARKSCLEARED"; Text = "All marks cleared"; } Text { ID = "STSTR_DQDON"; Text = "Degreelessness mode On"; } Text { ID = "STSTR_DQDOFF"; Text = "Degreelessness mode Off"; } Text { ID = "STSTR_KFAADDED"; Text = "Very Happy Ammo added"; } Text { ID = "STSTR_NCON"; Text = "No clipping mode ON"; } Text { ID = "STSTR_NCOFF"; Text = "No clipping mode OFF"; } Text { ID = "STSTR_BEHOLD"; Text = "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"; } Text { ID = "STSTR_BEHOLDX"; Text = "Power-up toggled"; } Text { ID = "STSTR_CHOPPERS"; Text = "... doesn't suck - GM"; } Text { ID = "STSTR_CLEV"; Text = "Changing map..."; } # These episode end messages are obsolete, see Finales.ded. Text { ID = "E1TEXT"; Text = "With the destruction of the Iron\n Liches and their minions, the last\n of the undead are cleared from this\n plane of existence.\n\n Those creatures had to come from\n somewhere, though, and you have the\n sneaky suspicion that the fiery\n portal of Hell's maw opens onto\n their home dimension.\n\n To make sure that more undead\n (or even worse things) don't come\n through, you'll have to seal Hell's\n maw from the other side. Of course\n this means you may get stuck in a\n very unfriendly world, but no one\n ever said being a Heretic was easy!"; } # These episode end messages are obsolete, see Finales.ded. Text { ID = "E2TEXT"; Text = "The mighty Maulotaurs have proved\n to be no match for you, and as\n their steaming corpses slide to the\n ground you feel a sense of grim\n satisfaction that they have been\n destroyed.\n\n The gateways which they guarded\n have opened, revealing what you\n hope is the way home. but as you\n step through, mocking laughter\n rings in your ears.\n\n Was some other force controlling\n the Maulotaurs? Could there be even\n more horrific beings through this\n gate? The sweep of a crystal dome\n overhead where the sky should be is\n certainly not a good sign..."; } # These episode end messages are obsolete, see Finales.ded. Text { ID = "E3TEXT"; Text = "The death of D'Sparil has loosed\n the magical bonds holding his\n creatures on this plane, their\n dying screams overwhelming his own\n cries of agony.\n\n Your oath of vengeance fulfilled,\n you enter the portal to your own\n world, mere moments before the dome\n shatters into a million pieces.\n\n But if D'Sparil's power is broken\n forever, why don't you feel safe?\n Was it that last shout just before\n his death, the one that sounded\n like a curse? Or a summoning? You\n can't really be sure, but it might\n just have been a scream.\n\n Then again, what about the other\n Serpent Riders?"; } # These episode end messages are obsolete, see Finales.ded. Text { ID = "E4TEXT"; Text = "You thought you would return to your\n own world after D'Sparil died but\n his final act banished you to his\n own plane. Here you entered the\n shattered remnants of lands\n conquered by D'Sparil. You defeated\n the last guardians of these lands,\n but now you stand before the gates\n to D'Sparil's stronghold. Until this\n moment you had no doubts about your\n ability to face anything you might\n encounter but beyond this portal\n lies the very heart of the evil\n which invaded your world. D'Sparil\n might be dead, but the pit where he\n was spawned remains. Now you must\n enter that pit in the hopes of\n finding a way out and somewhere,\n in the darkest corner of D'Sparil's\n demesne, his personal bodyguards\n await your arrival..."; } # These episode end messages are obsolete, see Finales.ded. Text { ID = "E5TEXT"; Text = "As the final Maulotaur bellows his\n death-agony, you realize that you\n have never come so close to your own\n destruction. Not even the fight with\n D'Sparil and his Disciples had been\n this desperate. Grimly you stare at\n the gates which open before you,\n wondering if they lead home, or if\n they open onto some undreamed-of\n horror. You find yourself wondering\n if you have the strength to go on,\n if nothing but death and pain await\n you. But what else can you do, if\n the will to fight is gone? Can you\n force yourself to continue in the\n face of such despair? Do you have\n the courage? You find, in the end,\n that it is not within you to\n surrender without a fight. Eyes\n wide, you go to meet your fate."; } Text { ID = "LOADMISSING"; Text = "You weren't in the server's savegame."; } Text { ID = "EPISODE1"; Text = "City Of The Damned"; } Text { ID = "EPISODE2"; Text = "Hell's Maw"; } Text { ID = "EPISODE3"; Text = "The Dome Of D'Sparil"; } Text { ID = "EPISODE4"; Text = "The Ossuary"; } Text { ID = "EPISODE5"; Text = "The Stagnant Demesne"; } Text { ID = "EPISODE6"; Text = "Fate's Path"; } Text { ID = "AMSTR_ROTATEON"; Text = "Rotate mode ON"; } Text { ID = "AMSTR_ROTATEOFF"; Text = "Rotate mode OFF"; } Text { ID = "SKILL1"; Text = "Thou needeth a wet-nurse"; } Text { ID = "SKILL2"; Text = "Yellowbellies-r-us"; } Text { ID = "SKILL3"; Text = "Bringest them oneth"; } Text { ID = "SKILL4"; Text = "Thou art a smite-meister"; } Text { ID = "SKILL5"; Text = "Black Plague possesses thee"; } Text { ID = "KEY1"; Text = "Yellow Key"; } Text { ID = "KEY2"; Text = "Green Key"; } Text { ID = "KEY3"; Text = "Blue Key"; } Text { ID = "SAVEOUTMAP"; Text = "You can't save if you aren't in a map!"; } Text { ID = "ENDNOGAME"; Text = "You can't end a game that hasn't even begun!"; } Text { ID = "SUICIDEOUTMAP"; Text = "You can't suicide if you aren't in a map!"; } Text { ID = "SUICIDEASK"; Text = "Are you sure you want to suicide?"; } Text { ID = "PICKGAMETYPE"; Text = "Choose game type"; } Text { ID = "SINGLEPLAYER"; Text = "Singleplayer"; } Text { ID = "MULTIPLAYER"; Text = "Multiplayer"; } Text { ID = "NOTDESIGNEDFOR"; Text = "Not designed for %1."; } Text { ID = "GAMESETUP"; Text = "Game Setup"; } Text { ID = "PLAYERSETUP"; Text = "Player Setup"; } Text { ID = "HUSTR_E1M1"; Text = "E1M1: The Docks"; } Text { ID = "HUSTR_E1M2"; Text = "E1M2: The Dungeons"; } Text { ID = "HUSTR_E1M3"; Text = "E1M3: The Gatehouse"; } Text { ID = "HUSTR_E1M4"; Text = "E1M4: The Guard Tower"; } Text { ID = "HUSTR_E1M5"; Text = "E1M5: The Citadel"; } Text { ID = "HUSTR_E1M6"; Text = "E1M6: The Cathedral"; } Text { ID = "HUSTR_E1M7"; Text = "E1M7: The Crypts"; } Text { ID = "HUSTR_E1M8"; Text = "E1M8: Hell's Maw"; } Text { ID = "HUSTR_E1M9"; Text = "E1M9: The Graveyard"; } Text { ID = "HUSTR_E2M1"; Text = "E2M1: The Crater"; } Text { ID = "HUSTR_E2M2"; Text = "E2M2: The Lava Pits"; } Text { ID = "HUSTR_E2M3"; Text = "E2M3: The River of Fire"; } Text { ID = "HUSTR_E2M4"; Text = "E2M4: The Ice Grotto"; } Text { ID = "HUSTR_E2M5"; Text = "E2M5: The Catacombs"; } Text { ID = "HUSTR_E2M6"; Text = "E2M6: The Labyrinth"; } Text { ID = "HUSTR_E2M7"; Text = "E2M7: The Great Hall"; } Text { ID = "HUSTR_E2M8"; Text = "E2M8: The Portals of Chaos"; } Text { ID = "HUSTR_E2M9"; Text = "E2M9: The Glacier"; } Text { ID = "HUSTR_E3M1"; Text = "E3M1: The Storehouse"; } Text { ID = "HUSTR_E3M2"; Text = "E3M2: The Cesspool"; } Text { ID = "HUSTR_E3M3"; Text = "E3M3: The Confluence"; } Text { ID = "HUSTR_E3M4"; Text = "E3M4: The Azure Fortress"; } Text { ID = "HUSTR_E3M5"; Text = "E3M5: The Ophidian Lair"; } Text { ID = "HUSTR_E3M6"; Text = "E3M6: The Halls of Fear"; } Text { ID = "HUSTR_E3M7"; Text = "E3M7: The Chasm"; } Text { ID = "HUSTR_E3M8"; Text = "E3M8: D'Sparil's Keep"; } Text { ID = "HUSTR_E3M9"; Text = "E3M9: The Aquifer"; } Text { ID = "HUSTR_E4M1"; Text = "E4M1: Catafalque"; } Text { ID = "HUSTR_E4M2"; Text = "E4M2: Blockhouse"; } Text { ID = "HUSTR_E4M3"; Text = "E4M3: Ambulatory"; } Text { ID = "HUSTR_E4M4"; Text = "E4M4: Sepulcher"; } Text { ID = "HUSTR_E4M5"; Text = "E4M5: Great Stair"; } Text { ID = "HUSTR_E4M6"; Text = "E4M6: Halls of the Apostate"; } Text { ID = "HUSTR_E4M7"; Text = "E4M7: Ramparts of Perdition"; } Text { ID = "HUSTR_E4M8"; Text = "E4M8: Shattered Bridge"; } Text { ID = "HUSTR_E4M9"; Text = "E4M9: Mausoleum"; } Text { ID = "HUSTR_E5M1"; Text = "E5M1: Ochre Cliffs"; } Text { ID = "HUSTR_E5M2"; Text = "E5M2: Rapids"; } Text { ID = "HUSTR_E5M3"; Text = "E5M3: Quay"; } Text { ID = "HUSTR_E5M4"; Text = "E5M4: Courtyard"; } Text { ID = "HUSTR_E5M5"; Text = "E5M5: Hydratyr"; } Text { ID = "HUSTR_E5M6"; Text = "E5M6: Colonnade"; } Text { ID = "HUSTR_E5M7"; Text = "E5M7: Foetid Manse"; } Text { ID = "HUSTR_E5M8"; Text = "E5M8: Field of Judgement"; } Text { ID = "HUSTR_E5M9"; Text = "E5M9: Skein of D'Sparil"; } Text { ID = "HUSTR_E6M1"; Text = "E6M1: Raven's Lair"; } Text { ID = "HUSTR_E6M2"; Text = "E6M2: Water Shrine"; } Text { ID = "HUSTR_E6M3"; Text = "E6M3: American's Legacy"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/finales.ded0000644000175000017500000001476311357170242023376 0ustar keeskees# jHeretic: Intermissions and Finales # (see Doc\InFine.txt) Header { Version = 5; } InFine { ID = "title"; Script { # There is no skipping during the titlescreen loop. NoSkip # Any event shows the menu. Trigger MARKER title_loop # Step 1. Image back "TITLE" Music "titl" Wait 5 # Step 2. Patch advice 4 160 "ADVISOR" In 0 Alpha advice 0 In 1 Alpha advice 1 Wait 5 # Step 3. PlayDemo "demo1.cdm" # Step 4. DelPic advice Image back "CREDIT" Wait 5.714 # Original is 200 tics. # Step 5. PlayDemo "demo2.cdm" # Step 6. IF shareware Image back "ORDER" ELSE Image back "CREDIT" Wait 5.714 # Original is 200 tics. # Step 7. PlayDemo "demo3.cdm" GOTO title_loop }; } # Episode I: City Of The Damned Finale { After = "E1M8"; Script { noskip; # This is the end, no more levels after this. music "cptd"; flat FLOOR25; wait 0.5; text msg 20 5 "with the destruction of the iron\n liches and their minions, the last\n of the undead are cleared from this\n plane of existence.\n\n those creatures had to come from\n somewhere, though, and you have the\n sneaky suspicion that the fiery\n portal of hell's maw opens onto\n their home dimension.\n\n to make sure that more undead\n (or even worse things) don't come\n through, you'll have to seal hell's\n maw from the other side. of course\n this means you may get stuck in a\n very unfriendly world, but no one\n ever said being a Heretic was easy!"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. deltext msg; # Show shareware or credits screen. if shareware image back ORDER; ifnot shareware image back CREDIT; }; } # Episode II: Hell's Maw Finale { After = "E2M8"; Script { noskip; # This is the end, no more levels after this. music "cptd"; flat FLATHUH1; wait 0.5; text msg 20 5 "the mighty maulotaurs have proved\n to be no match for you, and as\n their steaming corpses slide to the\n ground you feel a sense of grim\n satisfaction that they have been\n destroyed.\n\n the gateways which they guarded\n have opened, revealing what you\n hope is the way home. but as you\n step through, mocking laughter\n rings in your ears.\n\n was some other force controlling\n the maulotaurs? could there be even\n more horrific beings through this\n gate? the sweep of a crystal dome\n overhead where the sky should be is\n certainly not a good sign...."; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. deltext msg; # Underwater dome. E2ENDPCX is in jHeretic.wad. noflat; image back E2ENDPCX; }; } # Episode III: The Dome of D'Sparil Finale { After = "E3M8"; Script { noskip; # This is the end, no more levels after this. music "cptd"; flat FLTWAWA2; # Start with a blue filter. filter 0 0.3 1 1; in 3 filter 0 0 0 0; wait 2; text msg 20 5 "the death of d'sparil has loosed\n the magical bonds holding his\n creatures on this plane, their\n dying screams overwhelming his own\n cries of agony.\n\n your oath of vengeance fulfilled,\n you enter the portal to your own\n world, mere moments before the dome\n shatters into a million pieces.\n\n but if d'sparil's power is broken\n forever, why don't you feel safe?\n was it that last shout just before\n his death, the one that sounded\n like a curse? or a summoning? you\n can't really be sure, but it might\n just have been a scream.\n\n then again, what about the other\n serpent riders?"; waittext msg; wait 6; # The original TEXTWAIT is 250 tics. # Flash to red while we change to the demon. in 1 filter 1 0.1 0 1; wait 1; deltext msg; # Demon scroll. noflat; in 0 offy 200; imageat f1 0 200 FINAL1; imageat f2 0 0 FINAL2; in 1 filter 0 0 0 0; wait 3; in 17.15 offy 0; # Original scroll time is 600 tics. }; } # Episode IV: The Ossuary Finale { After = "E4M8"; Script { noskip; # This is the end, no more levels after this. music "cptd"; flat FLOOR28; wait 0.5; text msg 20 5 "you thought you would return to your\n own world after d'sparil died, but\n his final act banished you to his\n own plane. here you entered the\n shattered remnants of lands\n conquered by d'sparil. you defeated\n the last guardians of these lands,\n but now you stand before the gates\n to d'sparil's stronghold. until this\n moment you had no doubts about your\n ability to face anything you might\n encounter, but beyond this portal\n lies the very heart of the evil\n which invaded your world. d'sparil\n might be dead, but the pit where he\n was spawned remains. now you must\n enter that pit in the hopes of\n finding a way out. and somewhere,\n in the darkest corner of d'sparil's\n demesne, his personal bodyguards\n await your arrival ..."; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. deltext msg; noflat; image back CREDIT; }; } # Episode V: The Stagnant Demesne Finale { After = "E5M8"; Script { noskip; # This is the end, no more levels after this. music "cptd"; flat FLOOR08; wait 0.5; text msg 20 5 "as the final maulotaur bellows his\n death-agony, you realize that you\n have never come so close to your own\n destruction. not even the fight with\n d'sparil and his disciples had been\n this desperate. grimly you stare at\n the gates which open before you,\n wondering if they lead home, or if\n they open onto some undreamed-of\n horror. you find yourself wondering\n if you have the strength to go on,\n if nothing but death and pain await\n you. but what else can you do, if\n the will to fight is gone? can you\n force yourself to continue in the\n face of such despair? do you have\n the courage? you find, in the end,\n that it is not within you to\n surrender without a fight. eyes\n wide, you go to meet your fate."; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. deltext msg; noflat; image back CREDIT; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/lights.ded0000644000175000017500000000340711357170242023240 0ustar keeskees# jHeretic: Lights # Need help with DED syntax? See DEDDoc.txt. Header { Version = 6; } #####====--- LIGHT DECORATIONS ---====##### # # The default flags allow using these only with the original textures. # Use "dcf_pwad" and "dcf_ext" to allow using with PWAD and external # resources. # # There can only be one decoration per texture/flat. Newer decorations # override older ones. # # One decoration can specify up to 16 lights. # # (based on Isegrim's definitions) Decoration { Texture = "GRSKULL3"; Light { Color { .7 0 0 } Offset { 54 32 } Halo radius = .1; Radius = .05; } Light { Color { .7 0 0 } Offset { 72 32 } Halo radius = .1; Radius = .05; } } Decoration { Texture = "SW1ON"; Light { Color { .6 .6 1 } Offset { 32 64 } Halo radius = .22; Radius = .08; } } Decoration { Texture = "SW2ON"; Light { Color { 0 0 .6 } Offset { 31.5 64 } Halo radius = .25; Radius = .1; Flare texture = 1; } } Decoration { Texture = "GRSTNPBW"; Light { Color { .72 .5 .11 } Offset { 31.5 74 } Halo radius = .3; Radius = .2; } } #####====--- LIGHT SOURCE PROPERTIES ---====##### # A halo would look bad for the chandelier because it wouldn't be # rendered around the candle flames. Light { State = "CHANDELIER1"; Size = 0.8; Flags = "lgf_nohalo"; } * Light { State = "CHANDELIER2"; } * Light { State = "CHANDELIER3"; } # The Yellow Key shouldn't blink so much. Light { State = "CKYY1"; Size = 0.5; X Offset = 0.1; Y Offset = 15; Color { 1 .7 0 } } * Light { State = "CKYY2"; } * Light { State = "CKYY3"; } * Light { State = "CKYY4"; } * Light { State = "CKYY5"; } * Light { State = "CKYY6"; } * Light { State = "CKYY7"; } * Light { State = "CKYY8"; } * Light { State = "CKYY9"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/defs/sprites.ded0000644000175000017500000000623211357170242023436 0ustar keeskees# jHeretic: Sprites # # Order of definitions is very important here! # Only add new Sprites *after* the existing definitions. # Header { Version = 5; } Sprite { ID = "IMPX"; } Sprite { ID = "ACLO"; } Sprite { ID = "PTN1"; } Sprite { ID = "SHLD"; } Sprite { ID = "SHD2"; } Sprite { ID = "BAGH"; } Sprite { ID = "SPMP"; } Sprite { ID = "INVS"; } Sprite { ID = "PTN2"; } Sprite { ID = "SOAR"; } Sprite { ID = "INVU"; } Sprite { ID = "PWBK"; } Sprite { ID = "EGGC"; } Sprite { ID = "EGGM"; } Sprite { ID = "FX01"; } Sprite { ID = "SPHL"; } Sprite { ID = "TRCH"; } Sprite { ID = "FBMB"; } Sprite { ID = "XPL1"; } Sprite { ID = "ATLP"; } Sprite { ID = "PPOD"; } Sprite { ID = "AMG1"; } Sprite { ID = "SPSH"; } Sprite { ID = "LVAS"; } Sprite { ID = "SLDG"; } Sprite { ID = "SKH1"; } Sprite { ID = "SKH2"; } Sprite { ID = "SKH3"; } Sprite { ID = "SKH4"; } Sprite { ID = "CHDL"; } Sprite { ID = "SRTC"; } Sprite { ID = "SMPL"; } Sprite { ID = "STGS"; } Sprite { ID = "STGL"; } Sprite { ID = "STCS"; } Sprite { ID = "STCL"; } Sprite { ID = "KFR1"; } Sprite { ID = "BARL"; } Sprite { ID = "BRPL"; } Sprite { ID = "MOS1"; } Sprite { ID = "MOS2"; } Sprite { ID = "WTRH"; } Sprite { ID = "HCOR"; } Sprite { ID = "KGZ1"; } Sprite { ID = "KGZB"; } Sprite { ID = "KGZG"; } Sprite { ID = "KGZY"; } Sprite { ID = "VLCO"; } Sprite { ID = "VFBL"; } Sprite { ID = "VTFB"; } Sprite { ID = "SFFI"; } Sprite { ID = "TGLT"; } Sprite { ID = "TELE"; } Sprite { ID = "STFF"; } Sprite { ID = "PUF3"; } Sprite { ID = "PUF4"; } Sprite { ID = "BEAK"; } Sprite { ID = "WGNT"; } Sprite { ID = "GAUN"; } Sprite { ID = "PUF1"; } Sprite { ID = "WBLS"; } Sprite { ID = "BLSR"; } Sprite { ID = "FX18"; } Sprite { ID = "FX17"; } Sprite { ID = "WMCE"; } Sprite { ID = "MACE"; } Sprite { ID = "FX02"; } Sprite { ID = "WSKL"; } Sprite { ID = "HROD"; } Sprite { ID = "FX00"; } Sprite { ID = "FX20"; } Sprite { ID = "FX21"; } Sprite { ID = "FX22"; } Sprite { ID = "FX23"; } Sprite { ID = "GWND"; } Sprite { ID = "PUF2"; } Sprite { ID = "WPHX"; } Sprite { ID = "PHNX"; } Sprite { ID = "FX04"; } Sprite { ID = "FX08"; } Sprite { ID = "FX09"; } Sprite { ID = "WBOW"; } Sprite { ID = "CRBW"; } Sprite { ID = "FX03"; } Sprite { ID = "BLOD"; } Sprite { ID = "PLAY"; } Sprite { ID = "FDTH"; } Sprite { ID = "BSKL"; } Sprite { ID = "CHKN"; } Sprite { ID = "MUMM"; } Sprite { ID = "FX15"; } Sprite { ID = "BEAS"; } Sprite { ID = "FRB1"; } Sprite { ID = "SNKE"; } Sprite { ID = "SNFX"; } Sprite { ID = "HEAD"; } Sprite { ID = "FX05"; } Sprite { ID = "FX06"; } Sprite { ID = "FX07"; } Sprite { ID = "CLNK"; } Sprite { ID = "WZRD"; } Sprite { ID = "FX11"; } Sprite { ID = "FX10"; } Sprite { ID = "KNIG"; } Sprite { ID = "SPAX"; } Sprite { ID = "RAXE"; } Sprite { ID = "SRCR"; } Sprite { ID = "FX14"; } Sprite { ID = "SOR2"; } Sprite { ID = "SDTH"; } Sprite { ID = "FX16"; } Sprite { ID = "MNTR"; } Sprite { ID = "FX12"; } Sprite { ID = "FX13"; } Sprite { ID = "AKYY"; } Sprite { ID = "BKYY"; } Sprite { ID = "CKYY"; } Sprite { ID = "AMG2"; } Sprite { ID = "AMM1"; } Sprite { ID = "AMM2"; } Sprite { ID = "AMC1"; } Sprite { ID = "AMC2"; } Sprite { ID = "AMS1"; } Sprite { ID = "AMS2"; } Sprite { ID = "AMP1"; } Sprite { ID = "AMP2"; } Sprite { ID = "AMB1"; } Sprite { ID = "AMB2"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jheretic/CMakeLists.txt0000644000175000017500000001131711357170242023106 0ustar keeskees## deng build scripts. ## Copyright © 2006 - 2007 Jamie Jones ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ ################################################################################ INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/plugins/common/include ) FILE(GLOB COMMON_PLUGIN_SOURCES ${CMAKE_SOURCE_DIR}/plugins/common/src/*.c) ################################################################################ ######################## jHeretic Game Plugin #################################### ADD_DEFINITIONS (-D__JHERETIC__ ) INCLUDE_DIRECTORIES ( include ) IF (ENABLEMAO) SET (JHERETIC_SOURCES ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/acfnlink.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/h_api.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/h_refresh.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/m_cheat.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_ceilng.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_enemy.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_inter.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_maputl.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_pspr.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_sound.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_switch.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/tables.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/h_action.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/h_console.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/h_main.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/g_ctrl.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_doors.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_floor.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_lights.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_plats.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_setup.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_spec.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/st_stuff.c ) ELSE (ENABLEMAO) FILE(GLOB JHERETIC_SOURCES ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/*.c ) ENDIF (ENABLEMAO) IF (ENABLEMAO) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jheretic_mao.c ${JHERETIC_SOURCES} ) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jheretic_common.c ${COMMON_PLUGIN_SOURCES} ) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jheretic_mobj.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_mobj.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_telept.c ) ADD_LIBRARY (jheretic SHARED ${CMAKE_BINARY_DIR}/_jheretic_mao.c ${CMAKE_BINARY_DIR}/_jheretic_common.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/p_oldsvg.c ${CMAKE_SOURCE_DIR}/plugins/jheretic/src/m_random.c ${CMAKE_BINARY_DIR}/_jheretic_mobj.c ) ELSE (ENABLEMAO) ADD_LIBRARY (jheretic SHARED ${JHERETIC_SOURCES} ${COMMON_PLUGIN_SOURCES} ) ENDIF (ENABLEMAO) #IF (APPLE) # SET_TARGET_PROPERTIES (jheretic PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -bundle -bundle_loader doomsday") #ENDIF (APPLE) ################################################################################ ######################## Install Targets ###################################### IF (NOT APPLE) INSTALL(TARGETS jheretic RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) ENDIF (NOT APPLE) IF (APPLE) # Bundling. SET (BUNDLE_BASE jHeretic) SET (BUNDLE ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.bundle) ADD_CUSTOM_COMMAND( TARGET jheretic POST_BUILD COMMAND rm -rf ${BUNDLE} COMMAND mkdir -p ${BUNDLE}/Contents/MacOS COMMAND cp libjheretic.dylib ${BUNDLE}/Contents/MacOS/${BUNDLE_BASE} COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/${BUNDLE_BASE}-Info.plist ${BUNDLE}/Contents/Info.plist COMMAND mkdir -p ${BUNDLE}/Contents/Resources #COMMAND mkdir -p ${BUNDLE}/Contents/Resources/English.lproj #COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/InfoPlist.strings ${BUNDLE}/Contents/Resources/English.lproj/ COMMAND echo 'APPL????' > ${BUNDLE}/Contents/PkgInfo COMMAND cp ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.pk3 ${BUNDLE}/Contents/Resources/ ) ENDIF (APPLE) deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/0000755000175000017500000000000011523516204021066 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/api/0000755000175000017500000000000011523516204021637 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/api/dsdirectsound.def0000644000175000017500000000042411357170242025174 0ustar keeskeesLIBRARY DSDIRECTSOUND ; All exports should be prefixed DS_. EXPORTS DS_Init DS_Shutdown DS_Event DS_SFX_Init DS_SFX_CreateBuffer DS_SFX_DestroyBuffer DS_SFX_Load DS_SFX_Reset DS_SFX_Play DS_SFX_Stop DS_SFX_Refresh DS_SFX_Set DS_SFX_Setv DS_SFX_Listener DS_SFX_Listenerv deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/res/0000755000175000017500000000000011523516204021657 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/res/dsdirectsound.dll.manifest0000644000175000017500000000062311357170242027037 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/res/directsound.rc0000644000175000017500000001007011357170242024531 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * directsound.rc: dsDirectSound.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""dsdirectsound.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION PLUGIN_VERSION_NUMBER\r\n" "PRODUCTVERSION PLUGIN_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dsDirectSound.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION PLUGIN_VERSION_NUMBER PRODUCTVERSION PLUGIN_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "dsDirectSound.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/res/resource.h0000644000175000017500000000061711357170242023666 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by directsound.rc // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/doc/0000755000175000017500000000000011523516204021633 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/doc/LICENSE0000644000175000017500000003545111357170242022653 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/src/0000755000175000017500000000000011357170242021660 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/src/driver_directsound.cpp0000644000175000017500000010523711357170242026272 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2008 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * driver_directsound.cpp: Win32 SFX driver for DirectSound, with EAX 2.0. * * Uses DirectSound 8.0 * Buffers created on Load. */ // HEADER FILES ------------------------------------------------------------ #define DIRECTSOUND_VERSION 0x0800 #define WIN32_LEAN_AND_MEAN #include #include #include #include #include #include #pragma warning (disable: 4035 4244) #include "doomsday.h" #include "sys_audiod.h" #include "sys_audiod_sfx.h" // MACROS ------------------------------------------------------------------ // DirectSound(3D)Buffer Pointer #define DSBUF(buf) ((LPDIRECTSOUNDBUFFER) buf->ptr) #define DSBUF3D(buf) ((LPDIRECTSOUND3DBUFFER8) buf->ptr3D) #define PI (3.14159265) #define MAX_FAILED_PROPS (10) // TYPES ------------------------------------------------------------------- enum { VX, VY, VZ }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- extern "C" { int DS_Init(void); void DS_Shutdown(void); void DS_Event(int type); int DS_SFX_Init(void); sfxbuffer_t* DS_SFX_CreateBuffer(int flags, int bits, int rate); void DS_SFX_DestroyBuffer(sfxbuffer_t* buf); void DS_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample); void DS_SFX_Reset(sfxbuffer_t* buf); void DS_SFX_Play(sfxbuffer_t* buf); void DS_SFX_Stop(sfxbuffer_t* buf); void DS_SFX_Refresh(sfxbuffer_t* buf); void DS_SFX_Set(sfxbuffer_t* buf, int prop, float value); void DS_SFX_Setv(sfxbuffer_t* buf, int prop, float* values); void DS_SFX_Listener(int prop, float value); void DS_SFX_Listenerv(int prop, float* values); } // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void commitEAXDeferred(void); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static boolean initOk = false; static LPDIRECTSOUND8 dsound = NULL; static LPDIRECTSOUNDBUFFER primary = NULL; static LPDIRECTSOUND3DLISTENER8 dsListener = NULL; static LPKSPROPERTYSET propertySet = NULL; static boolean ignoreEAXErrors = false; static boolean canSetPSF = true; static DWORD failedProps[MAX_FAILED_PROPS]; static int verbose = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static IDirectSoundBuffer8* createBuffer(DSBUFFERDESC* desc) { IDirectSoundBuffer* buf; IDirectSoundBuffer8* buf8; HRESULT hr; if(!desc) return NULL; // Try to create a secondary buffer with the requested properties. if(FAILED(hr = dsound->CreateSoundBuffer(desc, &buf, NULL))) return NULL; // Obtain the DirectSoundBuffer8 interface. if(FAILED (hr = buf->QueryInterface(IID_IDirectSoundBuffer8, (LPVOID*) &buf8))) buf8 = NULL; // Release the old interface, we don't need it. buf->Release(); return buf8; } static IDirectSound3DBuffer8* get3DBuffer(IDirectSoundBuffer8* buf8) { IDirectSound3DBuffer8* buf3d; HRESULT hr; if(!buf8) return NULL; // Query the 3D interface. if(FAILED(hr = buf8->QueryInterface(IID_IDirectSound3DBuffer8, (LPVOID*) &buf3d))) { Con_Message("dsDirectSound::get3DBuffer: " "Failed to get 3D interface (0x%x).\n", hr); buf3d = NULL; } return buf3d; } /** * Does the EAX implementation support getting/setting of a propertry. * * @param prop Property id (constant) to be checked. * @return @c true, if supported. */ static boolean queryEAXSupport(int prop) { #define EAXSUP (KSPROPERTY_SUPPORT_GET | KSPROPERTY_SUPPORT_SET) if(propertySet) { ULONG support = 0; propertySet->QuerySupport(DSPROPSETID_EAX_ListenerProperties, prop, &support); return (support & EAXSUP) == EAXSUP? true : false; } return false; #undef EAXSUP } /** * Init DirectSound, start playing the primary buffer. * * @return @c true, iff successful. */ int DS_Init(void) { #define NUMBUFFERS_HW_3D ((uint) dsoundCaps.dwFreeHw3DStreamingBuffers) #define NUMBUFFERS_HW_2D ((uint) dsoundCaps.dwFreeHwMixingStreamingBuffers) typedef struct eaxproperty_s { DSPROPERTY_EAX_LISTENERPROPERTY prop; char* name; } eaxproperty_t; static const eaxproperty_t eaxProps[] = { { DSPROPERTY_EAXLISTENER_ENVIRONMENT, "Environment" }, { DSPROPERTY_EAXLISTENER_ROOM, "Room" }, { DSPROPERTY_EAXLISTENER_ROOMHF, "Room HF" }, { DSPROPERTY_EAXLISTENER_DECAYTIME, "Decay time" }, { DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, "Room roll-off factor" }, { DSPROPERTY_EAXLISTENER_NONE, NULL } // terminate. }; DSBUFFERDESC desc; DSCAPS dsoundCaps; HWND hWnd; HRESULT hr; uint numHW3DBuffers = 0; boolean useEAX, eaxAvailable = false, primaryBuffer3D = false, primaryBufferHW = false; boolean haveInstance = false; if(dsound) return true; // Already initialized? // Are we in verbose mode? verbose = ArgExists("-verbose"); if(verbose) Con_Message("dsDirectSound::DS_Init: Initializing Direct Sound...\n"); // Can we set the Primary Sound Format? canSetPSF = !ArgExists("-nopsf"); useEAX = !ArgExists("-noeax"); if(!(hWnd = (HWND) DD_GetVariable(DD_WINDOW_HANDLE))) { Con_Error("dsDirectSound::DS_Init: Cannot initialize DirectSound " "at this time (main window unavailable)."); return false; } // First try to create the DirectSound8 object with EAX support. hr = DSERR_GENERIC; if(useEAX) { if((hr = EAXDirectSoundCreate8(NULL, &dsound, NULL)) == DS_OK) { haveInstance = true; eaxAvailable = true; } else { if(verbose) Con_Message("dsDirectSound::DS_Init: " "EAX couldn't be initialized (0x%x).\n", hr); } } // Try plain old DS, then. if(!haveInstance) { if((hr = DirectSoundCreate8(NULL, &dsound, NULL)) == DS_OK) { haveInstance = true; } else { Con_Message("dsDirectSound::DS_Init: " "Failed to create the DS8 instance (0x%x).\n", hr); } } if(!haveInstance) { // Oh dear. Give up. return false; } // Set cooperative level. if((hr = dsound->SetCooperativeLevel(hWnd, DSSCL_PRIORITY)) != DS_OK) { Con_Message("dsDirectSound::DS_Init: " "Failed to set cooperative level (0x%x).\n", hr); return false; } // Lets query the device caps. dsoundCaps.dwSize = sizeof(dsoundCaps); if((hr = dsound->GetCaps(&dsoundCaps)) != DS_OK) { Con_Message("dsDirectSound::DS_Init: " "Failed querying device caps (0x%x).\n", hr); return false; } dsListener = NULL; if(NUMBUFFERS_HW_3D < 4) useEAX = false; ZeroMemory(&desc, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); /** * Create the primary buffer. * We prioritize buffer creation as follows: * 3D hardware > 3D software > 2D hardware > 2D software. */ // First try for a 3D buffer, hardware or software. desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRL3D | DSBCAPS_CTRLVOLUME; desc.dwFlags |= (NUMBUFFERS_HW_3D > 0? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE); hr = dsound->CreateSoundBuffer(&desc, &primary, NULL); if(hr != DS_OK && hr != DS_NO_VIRTUALIZATION) { // Not available. // Try for a 2D buffer. ZeroMemory(&desc, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwFlags = DSBCAPS_PRIMARYBUFFER | DSBCAPS_CTRLVOLUME; desc.dwFlags |= (NUMBUFFERS_HW_2D > 0? DSBCAPS_LOCHARDWARE : DSBCAPS_LOCSOFTWARE); if((hr = dsound->CreateSoundBuffer(&desc, &primary, NULL)) != DS_OK) { Con_Message("dsDirectSound::DS_Init: " "Failed creating primary (2D) buffer (0x%x).\n", hr); return false; } primaryBufferHW = (NUMBUFFERS_HW_2D > 0? true : false); } else { // 3D buffer available. primaryBuffer3D = true; primaryBufferHW = (NUMBUFFERS_HW_3D > 0? true : false); // Get the listener. if(FAILED(hr = primary->QueryInterface(IID_IDirectSound3DListener, (LPVOID*) &dsListener))) { if(verbose) Con_Message("dsDirectSound::DS_Init: " "3D listener not available (0x%x).\n", hr); } } // Start playing the primary buffer. if(primary) { // Supposedly can be a bit more efficient not to stop the // primary buffer when there are no secondary buffers playing. primary->Play(0, 0, DSBPLAY_LOOPING); } // Try to get the EAX listener property set. // Create a temporary secondary buffer for it. if(eaxAvailable && useEAX) { IDirectSoundBuffer8* dummy; IDirectSound3DBuffer8* dummy3d; DSBUFFERDESC desc; WAVEFORMATEX wave; // Clear the failed properties array. memset(failedProps, ~0, sizeof(failedProps)); propertySet = NULL; if(ArgExists("-eaxignore")) ignoreEAXErrors = true; // Configure the temporary buffer. ZeroMemory(&desc, sizeof(DSBUFFERDESC)); desc.dwSize = sizeof(DSBUFFERDESC); desc.dwBufferBytes = DSBSIZE_MIN; desc.dwFlags = DSBCAPS_STATIC | DSBCAPS_CTRL3D; desc.lpwfxFormat = &wave; ZeroMemory(&wave, sizeof(WAVEFORMATEX)); wave.wFormatTag = WAVE_FORMAT_PCM; wave.nChannels = 1; wave.nSamplesPerSec = 44100; wave.wBitsPerSample = 16; wave.nBlockAlign = 2; wave.nAvgBytesPerSec = 88200; // Create the temporary buffer. if(!(dummy = createBuffer(&desc))) return false; // Get the 3D interface. if(!(dummy3d = get3DBuffer(dummy))) return false; // Query the property set interface dummy3d->QueryInterface(IID_IKsPropertySet, (LPVOID*) &propertySet); if(propertySet) { size_t i = 0; boolean ok = true; while(ok && eaxProps[i].prop != DSPROPERTY_EAXLISTENER_NONE) { const eaxproperty_t* p = &eaxProps[i]; if(!queryEAXSupport(p->prop)) ok = false; else i++; } if(!ok) { useEAX = false; propertySet->Release(); propertySet = NULL; } } else { useEAX = false; if(verbose) Con_Message("dsDirectSound::DS_Init: Failed retrieving property set.\n"); } } // Announce capabilites: Con_Printf("DirectSound Configuration:\n"); Con_Printf(" Primary Buffer: %s (%s)\n", (primaryBuffer3D? "3D" : "2D"), (primaryBufferHW? "hardware" : "software")); Con_Printf(" Hardware Buffers: %i\n", (primaryBuffer3D? NUMBUFFERS_HW_3D : NUMBUFFERS_HW_2D)); Con_Printf(" DSP: %s", eaxAvailable? "EAX 2.0" : "None"); if(eaxAvailable) Con_Printf(" (%s)", useEAX? "enabled" : "disabled"); Con_Printf("\n"); if(eaxAvailable) { size_t i; Con_Printf(" EAX Listner Environment:\n"); for(i = 0; eaxProps[i].prop != DSPROPERTY_EAXLISTENER_NONE; ++i) { const eaxproperty_t* p = &eaxProps[i]; Con_Message(" %s: %s\n", p->name, queryEAXSupport(p->prop)? "Present" : "Not available"); } } // Success! if(verbose) Con_Message("dsDirectSound::DS_Init: Initialization complete, OK.\n"); return true; #undef NUMBUFFERS_HW_3D #undef NUMBUFFERS_HW_2D } /** * Shut everything down. */ void DS_Shutdown(void) { if(propertySet) propertySet->Release(); propertySet = NULL; if(dsListener) dsListener->Release(); dsListener = NULL; if(primary) primary->Release(); primary = NULL; if(dsound) dsound->Release(); dsound = NULL; } /** * The Event function is called to tell the driver about certain critical * events like the beginning and end of an update cycle. */ void DS_Event(int type) { // Do nothing... } int DS_SFX_Init(void) { return true; } /** * Called using Listener(). */ static void setPrimaryFormat(int bits, int rate) { WAVEFORMATEX wave; memset(&wave, 0, sizeof(wave)); wave.wFormatTag = WAVE_FORMAT_PCM; wave.nChannels = 2; wave.nSamplesPerSec = rate; wave.nBlockAlign = wave.nChannels * bits / 8; wave.nAvgBytesPerSec = wave.nSamplesPerSec * wave.nBlockAlign; wave.wBitsPerSample = bits; primary->SetFormat(&wave); } sfxbuffer_t* DS_SFX_CreateBuffer(int flags, int bits, int rate) { int i; WAVEFORMATEX format; DSBUFFERDESC desc; IDirectSoundBuffer8* buf_object8; IDirectSound3DBuffer8* buf_object3d = NULL; sfxbuffer_t* buf; // If we don't have the listener, the primary buffer doesn't have 3D // capabilities; don't create 3D buffers. DSound should provide software // emulation, though, so this is really only a contingency. if(!dsListener && flags & SFXBF_3D) return NULL; // Setup the buffer descriptor. memset(&desc, 0, sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLVOLUME | DSBCAPS_STATIC | (flags & SFXBF_3D ? DSBCAPS_CTRL3D : DSBCAPS_CTRLPAN); // Calculate buffer size. Increase it to hit an 8 byte boundary. desc.dwBufferBytes = bits / 8 * rate / 2; // 500ms buffer. i = desc.dwBufferBytes % 8; if(i) desc.dwBufferBytes += 8 - i; desc.lpwfxFormat = &format; if(flags & SFXBF_3D) { // Control the selection with a Property! /*#pragma message(" DS_DSoundCreateBuffer: Reminder: Select sw-3D algo with a Property!") */ desc.guid3DAlgorithm = DS3DALG_HRTF_LIGHT; } // And the wave data format. format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 1; format.nSamplesPerSec = rate; format.wBitsPerSample = bits; format.nBlockAlign = bits / 8; format.nAvgBytesPerSec = rate * bits / 8; format.cbSize = 0; buf_object8 = createBuffer(&desc); if(!buf_object8) { Con_Message("dsDirectSound::DS_SFX_CreateBuffer: " "Failed creating buffer [rate:%i bits:%i].\n", rate, bits); return NULL; } // How about a 3D interface? if(flags & SFXBF_3D) { buf_object3d = get3DBuffer(buf_object8); if(!buf_object3d) { Con_Message("dsDirectSound::DS_SFX_CreateBuffer: " "Failed to retrieve 3D interface.\n"); buf_object8->Release(); return NULL; } } // Clear the buffer. buf = (sfxbuffer_t*) Z_Calloc(sizeof(*buf), PU_STATIC, 0); buf->ptr = buf_object8; buf->ptr3D = buf_object3d; buf->bytes = bits / 8; buf->rate = rate; buf->flags = flags; buf->length = desc.dwBufferBytes; buf->freq = rate; // Modified by calls to Set(SFXBP_FREQUENCY). return buf; } void DS_SFX_DestroyBuffer(sfxbuffer_t* buf) { if(!buf) return; DSBUF(buf)->Release(); // Free the memory allocated for the buffer. Z_Free(buf); } /** * Prepare the buffer for playing a sample by filling the buffer with as * much sample data as fits. The pointer to sample is saved, so the caller * mustn't free it while the sample is loaded. */ void DS_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample) { void* data; DWORD lockedBytes, wroteBytes; HRESULT hr; if(!buf || !sample) return; // Try to lock the buffer. if(FAILED (hr = DSBUF(buf)->Lock(0, 0, &data, &lockedBytes, 0, 0, DSBLOCK_ENTIREBUFFER))) return; // Couldn't lock! // Write as much data as we can. wroteBytes = MIN_OF(lockedBytes, sample->size); memcpy(data, sample->data, wroteBytes); // Fill the rest with zeroes. if(wroteBytes < lockedBytes) { // Set the end marker since we already know it. buf->cursor = wroteBytes; memset((char *) data + wroteBytes, buf->bytes == 1 ? 128 : 0, lockedBytes - wroteBytes); } else { // The whole buffer was filled, thus leaving the cursor at // the beginning. buf->cursor = 0; } DSBUF(buf)->Unlock(data, lockedBytes, 0, 0); // Now the buffer is ready for playing. buf->sample = sample; buf->written = wroteBytes; buf->flags &= ~SFXBF_RELOAD; // Zero the play cursor. DSBUF(buf)->SetCurrentPosition(0); } /** * Stops the buffer and makes it forget about its sample. */ void DS_SFX_Reset(sfxbuffer_t* buf) { if(!buf) return; DS_SFX_Stop(buf); buf->sample = NULL; buf->flags &= ~SFXBF_RELOAD; } /** * @return Length of the buffer in milliseconds. */ static unsigned int getBufLength(sfxbuffer_t* buf) { if(!buf) return 0; return 1000 * buf->sample->numSamples / buf->freq; } void DS_SFX_Play(sfxbuffer_t* buf) { HRESULT hr; // Playing is quite impossible without a sample. if(!buf || !buf->sample) return; // Do we need to reload? if(buf->flags & SFXBF_RELOAD) DS_SFX_Load(buf, buf->sample); // The sound starts playing now? if(!(buf->flags & SFXBF_PLAYING)) { // Calculate the end time (milliseconds). buf->endTime = Sys_GetRealTime() + getBufLength(buf); } if(FAILED(hr = DSBUF(buf)->Play(0, 0, DSBPLAY_LOOPING))) return; // The buffer is now playing. buf->flags |= SFXBF_PLAYING; } void DS_SFX_Stop(sfxbuffer_t* buf) { if(!buf) return; DSBUF(buf)->Stop(); // Clear the flag that tells the Sfx module about playing buffers. buf->flags &= ~SFXBF_PLAYING; // If the sound is started again, it needs to be reloaded. buf->flags |= SFXBF_RELOAD; } static boolean InRange(uint pos, uint start, uint end) { if(end > start) { // This is the "normal" scenario: the write cursor is running // ahead of the play cursor. return (pos >= start && pos <= end); } // This is the "wrapping" scenario: the write cursor has wrapped // back to the beginning, with the play cursor left at the end // of the buffer. (The range is split in two.) return (pos >= start || pos <= end); } /** * Buffer streamer. Called by the Sfx refresh thread. * Copy sample data into the buffer, and if the sample has ended, stop * playing the buffer. If the buffer has been lost for some reason, restore * it. Don't do anything time-consuming... */ void DS_SFX_Refresh(sfxbuffer_t* buf) { DWORD play, bytes[2], dose, fill; void* data[2]; int writeBytes, i; float usedSec; unsigned int usedTime, nowTime; HRESULT hr; // Can only be done if there is a sample and the buffer is playing. if(!buf || !buf->sample || !(buf->flags & SFXBF_PLAYING)) return; nowTime = Sys_GetRealTime(); /** * Have we passed the predicted end of sample? * \note This test fails if the game has been running for about 50 days, * since the millisecond counter overflows. It only affects sounds that * are playing while the overflow happens, though. */ if(!(buf->flags & SFXBF_REPEAT) && nowTime >= buf->endTime) { // Time for the sound to stop. DS_SFX_Stop(buf); return; } // Slightly redundant... (used = now - start) usedTime = nowTime - (buf->endTime - getBufLength(buf)); // Approximate the current playing position (-0.1 sec for safety; we // don't want to overwrite stuff before it gets played). usedSec = usedTime / 1000.0f - 0.1f; if(usedSec <= 0) { // The update is a bit early; let's wait for the next one. return; } play = (int) (usedSec * buf->freq * buf->bytes) % buf->length; // How many bytes we must write (from buffer cursor up to play cursor). if(buf->cursor < play) writeBytes = play - buf->cursor; else // Play has looped back to the beginning. writeBytes = buf->length - buf->cursor + play; // Try to lock the region, restoring if failed. for(i = 0; i < 2; ++i) { if(FAILED (hr = DSBUF(buf)->Lock(buf->cursor, writeBytes, &data[0], &bytes[0], &data[1], &bytes[1], 0))) { if(hr == DSERR_BUFFERLOST) { DSBUF(buf)->Restore(); continue; } } break; } if(FAILED(hr)) return; // Give up. /*#if _DEBUG Con_Message("C%i, B%i, W%i (p%i)", buf->cursor, write_bytes, buf->written, play); Con_Message(" (d1=%p b=%i d2=%p b=%i)", data[0], bytes[0], data[1], bytes[1]); #endif*/ // Copy in two parts: as much sample data as we've got, and then zeros. for(i = 0; i < 2 && data[i]; ++i) { // The dose is limited to the number of bytes we can write to this // pointer and the number of bytes we've got left. dose = MIN_OF(bytes[i], buf->sample->size - buf->written); if(dose) { // Copy from the sample data and advance cursor & written. memcpy((byte *) data[i], (byte *) buf->sample->data + buf->written, dose); buf->written += dose; buf->cursor += dose; } if(dose < bytes[i]) { // Repeating samples just rewind the 'written' counter when the // end is reached. if(!(buf->flags & SFXBF_REPEAT)) { // The whole block was not filled. Write zeros in the rest. fill = bytes[i] - dose; // Filling an 8-bit sample with zeroes produces a nasty click. memset((byte *) data[i] + dose, buf->bytes == 1 ? 128 : 0, fill); buf->cursor += fill; } } // Wrap the cursor back to the beginning if needed. The wrap can // only happen after the first write, really (where the buffer // "breaks"). if(buf->cursor >= buf->length) buf->cursor -= buf->length; } // And we're done! Unlock and get out of here. DSBUF(buf)->Unlock(data[0], bytes[0], data[1], bytes[1]); // If the buffer is in repeat mode, go back to the beginning once the // end has been reached. if((buf->flags & SFXBF_REPEAT) && buf->written == buf->sample->size) buf->written = 0; } /** * Convert linear volume 0..1 to logarithmic -10000..0. */ static int volLinearToLog(float vol) { if(vol <= 0) return DSBVOLUME_MIN; if(vol >= 1) return DSBVOLUME_MAX; // Straighten the volume curve. return MINMAX_OF(DSBVOLUME_MIN, (int) (100 * 20 * log10(vol)), DSBVOLUME_MAX); } /** * Convert linear pan -1..1 to logarithmic -10000..10000. */ static int panLinearToLog(float pan) { if(pan >= 1) return DSBPAN_RIGHT; if(pan <= -1) return DSBPAN_LEFT; if(pan == 0) return 0; if(pan > 0) return (int) (-100 * 20 * log10(1 - pan)); return (int) (100 * 20 * log10(1 + pan)); } /** * SFXBP_VOLUME (if negative, interpreted as attenuation) * SFXBP_FREQUENCY * SFXBP_PAN (-1..1) * SFXBP_MIN_DISTANCE * SFXBP_MAX_DISTANCE * SFXBP_RELATIVE_MODE */ void DS_SFX_Set(sfxbuffer_t* buf, int prop, float value) { if(!buf) return; switch(prop) { default: #if _DEBUG Con_Error("dsDS9::DS_DSoundSet: Unknown prop %i.", prop); #endif break; case SFXBP_VOLUME: { LONG volume; if(value <= 0) // Use logarithmic attenuation. volume = (LONG) ((-1 - value) * 10000); else // Linear volume. volume = (LONG) volLinearToLog(value); DSBUF(buf)->SetVolume(volume); break; } case SFXBP_FREQUENCY: { unsigned int freq = (unsigned int) (buf->rate * value); // Don't set redundantly. if(freq != buf->freq) { buf->freq = freq; DSBUF(buf)->SetFrequency(freq); } break; } case SFXBP_PAN: DSBUF(buf)->SetPan(panLinearToLog(value)); break; case SFXBP_MIN_DISTANCE: if(!DSBUF3D(buf)) return; DSBUF3D(buf)->SetMinDistance(value, DS3D_DEFERRED); break; case SFXBP_MAX_DISTANCE: if(!DSBUF3D(buf)) return; DSBUF3D(buf)->SetMaxDistance(value, DS3D_DEFERRED); break; case SFXBP_RELATIVE_MODE: if(!DSBUF3D(buf)) return; DSBUF3D(buf)->SetMode(value? DS3DMODE_HEADRELATIVE : DS3DMODE_NORMAL, DS3D_DEFERRED); break; } } /** * Coordinates specified in world coordinate system, converted to DSound's: * +X to the right, +Y up and +Z away (Y and Z swapped, i.e.). * * @param prop SFXBP_POSITION * SFXBP_VELOCITY */ void DS_SFX_Setv(sfxbuffer_t* buf, int prop, float* values) { if(!buf || !values) return; if(!DSBUF3D(buf)) return; switch(prop) { default: #if _DEBUG Con_Error("dsDS9::DS_DSoundSetv: Unknown prop %i.", prop); #endif break; case SFXBP_POSITION: DSBUF3D(buf)->SetPosition(values[VX], values[VZ], values[VY], DS3D_DEFERRED); break; case SFXBP_VELOCITY: DSBUF3D(buf)->SetVelocity(values[VX], values[VZ], values[VY], DS3D_DEFERRED); break; } } /** * Parameters are in radians. * Example front vectors: * Yaw 0:(0,0,1), pi/2:(-1,0,0) */ static void listenerOrientation(float yaw, float pitch) { float front[3], up[3]; front[VX] = cos(yaw) * cos(pitch); front[VZ] = sin(yaw) * cos(pitch); front[VY] = sin(pitch); up[VX] = -cos(yaw) * sin(pitch); up[VZ] = -sin(yaw) * sin(pitch); up[VY] = cos(pitch); dsListener->SetOrientation(front[VX], front[VY], front[VZ], up[VX], up[VY], up[VZ], DS3D_DEFERRED); } /** * Set the property as 'failed'. No more errors are reported for it. */ static void setEAXFailed(DWORD prop) { int i; for(i = 0; i < MAX_FAILED_PROPS; ++i) if(failedProps[i] == ~0) { failedProps[i] = prop; break; } } /** * @return @c true, if the specified property has failed. */ static boolean hasEAXFailed(DWORD prop) { int i; for(i = 0; i < MAX_FAILED_PROPS; ++i) if(failedProps[i] == prop) return true; return false; } /** * @return @c true, if an EAX error should be reported. */ static boolean reportEAXError(DWORD prop, HRESULT hr) { if(ignoreEAXErrors) return false; if(hr != DSERR_UNSUPPORTED) return true; if(hasEAXFailed(prop)) return false; // Don't report again. setEAXFailed(prop); return true; // First time, do report. } static void setEAXdw(DWORD prop, int value) { HRESULT hr; if(FAILED (hr = propertySet->Set(DSPROPSETID_EAX_ListenerProperties, prop | DSPROPERTY_EAXLISTENER_DEFERRED, NULL, 0, &value, sizeof(DWORD)))) { if(reportEAXError(prop, hr)) Con_Message("setEAXdw (prop:%i value:%i) failed. Result: %x.\n", prop, value, hr); } } static void setEAXf(DWORD prop, float value) { HRESULT hr; if(FAILED (hr = propertySet->Set(DSPROPSETID_EAX_ListenerProperties, prop | DSPROPERTY_EAXLISTENER_DEFERRED, NULL, 0, &value, sizeof(float)))) { if(reportEAXError(prop, hr)) Con_Message("setEAXf (prop:%i value:%f) failed. Result: %x.\n", prop, value, hr); } } /** * Linear multiplication for a logarithmic property. */ static void mulEAXdw(DWORD prop, float mul) { DWORD retBytes; LONG value; HRESULT hr; if(FAILED (hr = propertySet->Get(DSPROPSETID_EAX_ListenerProperties, prop, NULL, 0, &value, sizeof(value), &retBytes))) { if(reportEAXError(prop, hr)) Con_Message("mulEAXdw (prop:%i) get failed. Result: %x.\n", prop, hr & 0xffff); } setEAXdw(prop, volLinearToLog(pow(10, value / 2000.0f) * mul)); } /** * Linear multiplication for a linear property. */ static void mulEAXf(DWORD prop, float mul, float min, float max) { DWORD retBytes; HRESULT hr; float value; if(FAILED (hr = propertySet->Get(DSPROPSETID_EAX_ListenerProperties, prop, NULL, 0, &value, sizeof(value), &retBytes))) { if(reportEAXError(prop, hr)) Con_Message("mulEAXf (prop:%i) get failed. Result: %x.\n", prop, hr & 0xffff); } value *= mul; if(value < min) value = min; if(value > max) value = max; setEAXf(prop, value); } /** * Set a property of a listener. * * @param prop SFXLP_UNITS_PER_METER * SFXLP_DOPPLER * SFXLP_UPDATE * @param value Value to be set. */ void DS_SFX_Listener(int prop, float value) { if(!dsListener) return; switch(prop) { default: #if _DEBUG Con_Error("dsDS9::DS_DSoundListener: Unknown prop %i.", prop); #endif break; case SFXLP_UPDATE: // Commit any deferred settings. dsListener->CommitDeferredSettings(); commitEAXDeferred(); break; case SFXLP_UNITS_PER_METER: dsListener->SetDistanceFactor(1 / value, DS3D_IMMEDIATE); break; case SFXLP_DOPPLER: dsListener->SetDopplerFactor(value, DS3D_IMMEDIATE); break; } } static void commitEAXDeferred(void) { if(!propertySet) return; propertySet->Set(DSPROPSETID_EAX_ListenerProperties, DSPROPERTY_EAXLISTENER_COMMITDEFERREDSETTINGS, NULL, 0, NULL, 0); } /** * If EAX is available, set the listening environmental properties. * Values use SRD_* for indices. */ static void listenerEnvironment(float* rev) { float val; int eaxVal; if(!rev) return; // This can only be done if EAX is available. if(!propertySet) return; val = rev[SRD_SPACE]; if(rev[SRD_DECAY] > .5) { // This much decay needs at least the Generic environment. if(val < .2) val = .2f; } // Set the environment. Other properties are updated automatically. if(val >= 1) eaxVal = EAX_ENVIRONMENT_PLAIN; else if(val >= .8) eaxVal = EAX_ENVIRONMENT_CONCERTHALL; else if(val >= .6) eaxVal = EAX_ENVIRONMENT_AUDITORIUM; else if(val >= .4) eaxVal = EAX_ENVIRONMENT_CAVE; else if(val >= .2) eaxVal = EAX_ENVIRONMENT_GENERIC; else eaxVal = EAX_ENVIRONMENT_ROOM; setEAXdw(DSPROPERTY_EAXLISTENER_ENVIRONMENT, eaxVal); // General reverb volume adjustment. setEAXdw(DSPROPERTY_EAXLISTENER_ROOM, volLinearToLog(rev[SRD_VOLUME])); // Reverb decay. val = (rev[SRD_DECAY] - .5f) * 1.5f + 1; mulEAXf(DSPROPERTY_EAXLISTENER_DECAYTIME, val, EAXLISTENER_MINDECAYTIME, EAXLISTENER_MAXDECAYTIME); // Damping. val = 1.1f * (1.2f - rev[SRD_DAMPING]); if(val < .1) val = .1f; mulEAXdw(DSPROPERTY_EAXLISTENER_ROOMHF, val); // A slightly increased roll-off. setEAXf(DSPROPERTY_EAXLISTENER_ROOMROLLOFFFACTOR, 1.3f); } /** * Call SFXLP_UPDATE at the end of every channel update. */ void DS_SFX_Listenerv(int prop, float* values) { if(!values) return; switch(prop) { case SFXLP_PRIMARY_FORMAT: if(canSetPSF) setPrimaryFormat((int) values[0], (int) values[1]); break; case SFXLP_POSITION: if(!dsListener) return; dsListener->SetPosition(values[VX], values[VZ], values[VY], DS3D_DEFERRED); break; case SFXLP_VELOCITY: if(!dsListener) return; dsListener->SetVelocity(values[VX], values[VZ], values[VY], DS3D_DEFERRED); break; case SFXLP_ORIENTATION: if(!dsListener) return; listenerOrientation(values[VX] / 180 * PI, values[VY] / 180 * PI); break; case SFXLP_REVERB: if(!dsListener) return; listenerEnvironment(values); break; default: DS_SFX_Listener(prop, 0); break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/include/0000755000175000017500000000000011523516204022511 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/directsound/include/version.h0000644000175000017500000000342011357170242024351 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __DSDIRECTSOUND_VERSION_H__ #define __DSDIRECTSOUND_VERSION_H__ #ifndef DSDIRECTSOUND_VER_ID # ifdef _DEBUG # define DSDIRECTSOUND_VER_ID "+D Doomsday" # else # define DSDIRECTSOUND_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define PLUGIN_NAME "dsdirectsound" // Presented to the user in dialogs, messages etc. #define PLUGIN_NICENAME "DirectSound Audio Driver" #define PLUGIN_DETAILS "Doomsday plugin for audio playback via DirectSound" #define PLUGIN_VERSION_TEXT "1.2.5" #define PLUGIN_VERSION_TEXTLONG "Version" PLUGIN_VERSION_TEXT " " __DATE__ " (" DSDIRECTSOUND_VER_ID ")" #define PLUGIN_VERSION_NUMBER 1,2,5,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/0000755000175000017500000000000011523516204020137 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/res/0000755000175000017500000000000011523516204020730 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/res/dpdehread.dll.manifest0000644000175000017500000000062311357170242025156 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/res/resource.h0000644000175000017500000000061311357170242022733 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by dehread.rc // // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/res/dehread.rc0000644000175000017500000001003011357170242022647 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dehread.rc: dpDehRead.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""dpdehread.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION PLUGIN_VERSION_NUMBER\r\n" "PRODUCTVERSION PLUGIN_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dpDehRead.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION PLUGIN_VERSION_NUMBER PRODUCTVERSION PLUGIN_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "dpDehRead.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/doc/0000755000175000017500000000000011523516204020704 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/doc/LICENSE0000644000175000017500000003545111357170242021724 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/src/0000755000175000017500000000000011357170242020731 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/src/dehmain.c0000644000175000017500000026042711357170242022515 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1998-2003 Randy Heit (Zdoom) * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA * * In Zdoom, from which this code is based, it was originally under the * 3 clause BSD license as described here: * http://www.opensource.org/licenses/bsd-license.php */ /** * dehmain.c: Dehacked Reader Plugin for Doomsday * * Much of this has been taken from or is based on ZDoom's DEH reader. * Unsupported Dehacked features have been commented out. * * Put the Doomsday Include directory in your path. * This DLL also serves as an example of a Doomsday plugin. */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #include #include #include #include #include // This plugin accesses the internal definition arrays. This dependency // should be removed entirely, either by making the plugin modify the // definitions via an API or by integrating the plugin into the engine. #include "../../../engine/portable/include/def_data.h" #define __INTERNAL_MAP_DATA_ACCESS__ #include // MACROS ------------------------------------------------------------------ #define OFF_STATE 0x04000000 #define OFF_SOUND 0x08000000 #define OFF_FIXED 0x10000000 #define OFF_MASK 0x00ffffff #define myoffsetof(type,identifier,fl) (((size_t)&((type*)0)->identifier)|fl) #define LPrintf Con_Message //#define LINESIZE 2048 #define NUMSPRITES 138 #define NUMSTATES 968 #define CHECKKEY(a,b) if (!stricmp (Line1, (a))) (b) = atoi(Line2); // TYPES ------------------------------------------------------------------- typedef struct Key { char *name; ptrdiff_t offset; } Key_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- #ifdef UNIX void InitPlugin(void) __attribute__ ((constructor)); #endif int PatchThing(int); int PatchSound(int); int PatchState(int); int PatchSprite(int); int PatchAmmo(int); int PatchWeapon(int); int PatchPointer(int); int PatchCheats(int); int PatchMisc(int); int PatchText(int); int PatchStrings(int); int PatchPars(int); int PatchCodePtrs(int); int DoInclude(int); void ApplyDEH(char *patch, int length); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- ded_t *ded; boolean verbose; char *PatchFile, *PatchPt; char *Line1, *Line2; int dversion, pversion; boolean including, includenotext; static const char* SpriteMap[] = { "TROO", "SHTG", "PUNG", "PISG", "PISF", "SHTF", "SHT2", "CHGG", "CHGF", "MISG", "MISF", "SAWG", "PLSG", "PLSF", "BFGG", "BFGF", "BLUD", "PUFF", "BAL1", "BAL2", "PLSS", "PLSE", "MISL", "BFS1", "BFE1", "BFE2", "TFOG", "IFOG", "PLAY", "POSS", "SPOS", "VILE", "FIRE", "FATB", "FBXP", "SKEL", "MANF", "FATT", "CPOS", "SARG", "HEAD", "BAL7", "BOSS", "BOS2", "SKUL", "SPID", "BSPI", "APLS", "APBX", "CYBR", "PAIN", "SSWV", "KEEN", "BBRN", "BOSF", "ARM1", "ARM2", "BAR1", "BEXP", "FCAN", "BON1", "BON2", "BKEY", "RKEY", "YKEY", "BSKU", "RSKU", "YSKU", "STIM", "MEDI", "SOUL", "PINV", "PSTR", "PINS", "MEGA", "SUIT", "PMAP", "PVIS", "CLIP", "AMMO", "ROCK", "BROK", "CELL", "CELP", "SHEL", "SBOX", "BPAK", "BFUG", "MGUN", "CSAW", "LAUN", "PLAS", "SHOT", "SGN2", "COLU", "SMT2", "GOR1", "POL2", "POL5", "POL4", "POL3", "POL1", "POL6", "GOR2", "GOR3", "GOR4", "GOR5", "SMIT", "COL1", "COL2", "COL3", "COL4", "CAND", "CBRA", "COL6", "TRE1", "TRE2", "ELEC", "CEYE", "FSKU", "COL5", "TBLU", "TGRN", "TRED", "SMBT", "SMGT", "SMRT", "HDB1", "HDB2", "HDB3", "HDB4", "HDB5", "HDB6", "POB1", "POB2", "BRS1", "TLMP", "TLP2", NULL }; static const char* SoundMap[] = { "None", "pistol", "shotgn", "sgcock", "dshtgn", "dbopn", "dbcls", "dbload", "plasma", "bfg", "sawup", "sawidl", "sawful", "sawhit", "rlaunc", "rxplod", "firsht", "firxpl", "pstart", "pstop", "doropn", "dorcls", "stnmov", "swtchn", "swtchx", "plpain", "dmpain", "popain", "vipain", "mnpain", "pepain", "slop", "itemup", "wpnup", "oof", "telept", "posit1", "posit2", "posit3", "bgsit1", "bgsit2", "sgtsit", "cacsit", "brssit", "cybsit", "spisit", "bspsit", "kntsit", "vilsit", "mansit", "pesit", "sklatk", "sgtatk", "skepch", "vilatk", "claw", "skeswg", "pldeth", "pdiehi", "podth1", "podth2", "podth3", "bgdth1", "bgdth2", "sgtdth", "cacdth", "skldth", "brsdth", "cybdth", "spidth", "bspdth", "vildth", "kntdth", "pedth", "skedth", "posact", "bgact", "dmact", "bspact", "bspwlk", "vilact", "noway", "barexp", "punch", "hoof", "metal", "chgun", "tink", "bdopn", "bdcls", "itmbk", "flame", "flamst", "getpow", "bospit", "boscub", "bossit", "bospn", "bosdth", "manatk", "mandth", "sssit", "ssdth", "keenpn", "keendt", "skeact", "skesit", "skeatk", "radio", NULL }; static const char* MusicMap[] = { "e1m1", "e1m2", "e1m3", "e1m4", "e1m5", "e1m6", "e1m7", "e1m8", "e1m9", "e2m1", "e2m2", "e2m3", "e2m4", "e2m5", "e2m6", "e2m7", "e2m8", "e2m9", "e3m1", "e3m2", "e3m3", "e3m4", "e3m5", "e3m6", "e3m7", "e3m8", "e3m9", "inter", "intro", "bunny", "victor", "introa", "runnin", "stalks", "countd", "betwee", "doom", "the_da", "shawn", "ddtblu", "in_cit", "dead", "stlks2", "theda2", "doom2", "ddtbl2", "runni2", "dead2", "stlks3", "romero", "shawn2", "messag", "count2", "ddtbl3", "ampie", "theda3", "adrian", "messg2", "romer2", "tense", "shawn3", "openin", "evil", "ultima", "read_m", "dm2ttl", "dm2int", NULL }; static const struct { const char* id; const char* str; } TextMap[] = { { "E1TEXT", "Once you beat the big badasses and\nclean out the moon base you're supposed\nto win, aren't you? Aren't you? Where's\nyour fat reward and ticket home? What\nthe hell is this? It's not supposed to\nend this way!\n\nIt stinks like rotten meat, but looks\nlike the lost Deimos base. Looks like\nyou're stuck on The Shores of Hell.\nThe only way out is through.\n\nTo continue the DOOM experience, play\nThe Shores of Hell and its amazing\nsequel, Inferno!\n" }, { "E2TEXT", "You've done it! The hideous cyber-\ndemon lord that ruled the lost Deimos\nmoon base has been slain and you\nare triumphant! But ... where are\nyou? You clamber to the edge of the\nmoon and look down to see the awful\ntruth.\n\nDeimos floats above Hell itself!\nYou've never heard of anyone escaping\nfrom Hell, but you'll make the bastards\nsorry they ever heard of you! Quickly,\nyou rappel down to the surface of\nHell.\n\nNow, it's on to the final chapter of\nDOOM! -- Inferno." }, { "E3TEXT", "The loathsome spiderdemon that\nmasterminded the invasion of the moon\nbases and caused so much death has had\nits ass kicked for all time.\n\nA hidden doorway opens and you enter.\nYou've proven too tough for Hell to\ncontain, and now Hell at last plays\nfair -- for you emerge from the door\nto see the green fields of Earth!\nHome at last.\n\nYou wonder what's been happening on\nEarth while you were battling evil\nunleashed. It's good that no Hell-\nspawn could have come through that\ndoor with you ..." }, { "E4TEXT", "the spider mastermind must have sent forth\nits legions of hellspawn before your\nfinal confrontation with that terrible\nbeast from hell. but you stepped forward\nand brought forth eternal damnation and\nsuffering upon the horde as a true hero\nwould in the face of something so evil.\n\nbesides, someone was gonna pay for what\nhappened to daisy, your pet rabbit.\n\nbut now, you see spread before you more\npotential pain and gibbitude as a nation\nof demons run amok among our cities.\n\nnext stop, hell on earth!" }, { "C1TEXT", "YOU HAVE ENTERED DEEPLY INTO THE INFESTED\nSTARPORT. BUT SOMETHING IS WRONG. THE\nMONSTERS HAVE BROUGHT THEIR OWN REALITY\nWITH THEM, AND THE STARPORT'S TECHNOLOGY\nIS BEING SUBVERTED BY THEIR PRESENCE.\n\nAHEAD, YOU SEE AN OUTPOST OF HELL, A\nFORTIFIED ZONE. IF YOU CAN GET PAST IT,\nYOU CAN PENETRATE INTO THE HAUNTED HEART\nOF THE STARBASE AND FIND THE CONTROLLING\nSWITCH WHICH HOLDS EARTH'S POPULATION\nHOSTAGE." }, { "C2TEXT", "YOU HAVE WON! YOUR VICTORY HAS ENABLED\nHUMANKIND TO EVACUATE EARTH AND ESCAPE\nTHE NIGHTMARE. NOW YOU ARE THE ONLY\nHUMAN LEFT ON THE FACE OF THE PLANET.\nCANNIBAL MUTATIONS, CARNIVOROUS ALIENS,\nAND EVIL SPIRITS ARE YOUR ONLY NEIGHBORS.\nYOU SIT BACK AND WAIT FOR DEATH, CONTENT\nTHAT YOU HAVE SAVED YOUR SPECIES.\n\nBUT THEN, EARTH CONTROL BEAMS DOWN A\nMESSAGE FROM SPACE: \"SENSORS HAVE LOCATED\nTHE SOURCE OF THE ALIEN INVASION. IF YOU\nGO THERE, YOU MAY BE ABLE TO BLOCK THEIR\nENTRY. THE ALIEN BASE IS IN THE HEART OF\nYOUR OWN HOME CITY, NOT FAR FROM THE\nSTARPORT.\" SLOWLY AND PAINFULLY YOU GET\nUP AND RETURN TO THE FRAY." }, { "C3TEXT", "YOU ARE AT THE CORRUPT HEART OF THE CITY,\nSURROUNDED BY THE CORPSES OF YOUR ENEMIES.\nYOU SEE NO WAY TO DESTROY THE CREATURES'\nENTRYWAY ON THIS SIDE, SO YOU CLENCH YOUR\nTEETH AND PLUNGE THROUGH IT.\n\nTHERE MUST BE A WAY TO CLOSE IT ON THE\nOTHER SIDE. WHAT DO YOU CARE IF YOU'VE\nGOT TO GO THROUGH HELL TO GET TO IT?" }, { "C4TEXT", "THE HORRENDOUS VISAGE OF THE BIGGEST\nDEMON YOU'VE EVER SEEN CRUMBLES BEFORE\nYOU, AFTER YOU PUMP YOUR ROCKETS INTO\nHIS EXPOSED BRAIN. THE MONSTER SHRIVELS\nUP AND DIES, ITS THRASHING LIMBS\nDEVASTATING UNTOLD MILES OF HELL'S\nSURFACE.\n\nYOU'VE DONE IT. THE INVASION IS OVER.\nEARTH IS SAVED. HELL IS A WRECK. YOU\nWONDER WHERE BAD FOLKS WILL GO WHEN THEY\nDIE, NOW. WIPING THE SWEAT FROM YOUR\nFOREHEAD YOU BEGIN THE LONG TREK BACK\nHOME. REBUILDING EARTH OUGHT TO BE A\nLOT MORE FUN THAN RUINING IT WAS.\n" }, { "C5TEXT", "CONGRATULATIONS, YOU'VE FOUND THE SECRET\nLEVEL! LOOKS LIKE IT'S BEEN BUILT BY\nHUMANS, RATHER THAN DEMONS. YOU WONDER\nWHO THE INMATES OF THIS CORNER OF HELL\nWILL BE." }, { "C6TEXT", "CONGRATULATIONS, YOU'VE FOUND THE\nSUPER SECRET LEVEL! YOU'D BETTER\nBLAZE THROUGH THIS ONE!\n" }, { "P1TEXT", "You gloat over the steaming carcass of the\nGuardian. With its death, you've wrested\nthe Accelerator from the stinking claws\nof Hell. You relax and glance around the\nroom. Damn! There was supposed to be at\nleast one working prototype, but you can't\nsee it. The demons must have taken it.\n\nYou must find the prototype, or all your\nstruggles will have been wasted. Keep\nmoving, keep fighting, keep killing.\nOh yes, keep living, too." }, { "P2TEXT", "Even the deadly Arch-Vile labyrinth could\nnot stop you, and you've gotten to the\nprototype Accelerator which is soon\nefficiently and permanently deactivated.\n\nYou're good at that kind of thing." }, { "P3TEXT", "You've bashed and battered your way into\nthe heart of the devil-hive. Time for a\nSearch-and-Destroy mission, aimed at the\nGatekeeper, whose foul offspring is\ncascading to Earth. Yeah, he's bad. But\nyou know who's worse!\n\nGrinning evilly, you check your gear, and\nget ready to give the bastard a little Hell\nof your own making!" }, { "P4TEXT", "The Gatekeeper's evil face is splattered\nall over the place. As its tattered corpse\ncollapses, an inverted Gate forms and\nsucks down the shards of the last\nprototype Accelerator, not to mention the\nfew remaining demons. You're done. Hell\nhas gone back to pounding bad dead folks \ninstead of good live ones. Remember to\ntell your grandkids to put a rocket\nlauncher in your coffin. If you go to Hell\nwhen you die, you'll need it for some\nfinal cleaning-up ..." }, { "P5TEXT", "You've found the second-hardest level we\ngot. Hope you have a saved game a level or\ntwo previous. If not, be prepared to die\naplenty. For master marines only." }, { "P6TEXT", "Betcha wondered just what WAS the hardest\nlevel we had ready for ya? Now you know.\nNo one gets out alive." }, { "T1TEXT", "You've fought your way out of the infested\nexperimental labs. It seems that UAC has\nonce again gulped it down. With their\nhigh turnover, it must be hard for poor\nold UAC to buy corporate health insurance\nnowadays..\n\nAhead lies the military complex, now\nswarming with diseased horrors hot to get\ntheir teeth into you. With luck, the\ncomplex still has some warlike ordnance\nlaying around." }, { "T2TEXT", "You hear the grinding of heavy machinery\nahead. You sure hope they're not stamping\nout new hellspawn, but you're ready to\nream out a whole herd if you have to.\nThey might be planning a blood feast, but\nyou feel about as mean as two thousand\nmaniacs packed into one mad killer.\n\nYou don't plan to go down easy." }, { "T3TEXT", "The vista opening ahead looks real damn\nfamiliar. Smells familiar, too -- like\nfried excrement. You didn't like this\nplace before, and you sure as hell ain't\nplanning to like it now. The more you\nbrood on it, the madder you get.\nHefting your gun, an evil grin trickles\nonto your face. Time to take some names." }, { "T4TEXT", "Suddenly, all is silent, from one horizon\nto the other. The agonizing echo of Hell\nfades away, the nightmare sky turns to\nblue, the heaps of monster corpses start \nto evaporate along with the evil stench \nthat filled the air. Jeeze, maybe you've\ndone it. Have you really won?\n\nSomething rumbles in the distance.\nA blue light begins to glow inside the\nruined skull of the demon-spitter." }, { "T5TEXT", "What now? Looks totally different. Kind\nof like King Tut's condo. Well,\nwhatever's here can't be any worse\nthan usual. Can it? Or maybe it's best\nto let sleeping gods lie.." }, { "T6TEXT", "Time for a vacation. You've burst the\nbowels of hell and by golly you're ready\nfor a break. You mutter to yourself,\nMaybe someone else can kick Hell's ass\nnext time around. Ahead lies a quiet town,\nwith peaceful flowing water, quaint\nbuildings, and presumably no Hellspawn.\n\nAs you step off the transport, you hear\nthe stomp of a cyberdemon's iron shoe." }, { "CC_ZOMBIE", "ZOMBIEMAN" }, { "CC_SHOTGUN", "SHOTGUN GUY" }, { "CC_HEAVY", "HEAVY WEAPON DUDE" }, { "CC_IMP", "IMP" }, { "CC_DEMON", "DEMON" }, { "CC_LOST", "LOST SOUL" }, { "CC_CACO", "CACODEMON" }, { "CC_HELL", "HELL KNIGHT" }, { "CC_BARON", "BARON OF HELL" }, { "CC_ARACH", "ARACHNOTRON" }, { "CC_PAIN", "PAIN ELEMENTAL" }, { "CC_REVEN", "REVENANT" }, { "CC_MANCU", "MANCUBUS" }, { "CC_ARCH", "ARCH-VILE" }, { "CC_SPIDER", "THE SPIDER MASTERMIND" }, { "CC_CYBER", "THE CYBERDEMON" }, { "CC_HERO", "OUR HERO" }, { "D_DEVSTR", "Development mode ON.\n" }, { "D_CDROM", "CD-ROM Version: default.cfg from c:\\doomdata\n" }, { "LOADNET", "you can't do load while in a net game!\n\npress a key." }, { "SAVEDEAD", "you can't save if you aren't playing!\n\npress a key." }, { "QSPROMPT", "quicksave over your game named\n\n'%s'?\n\npress y or n." }, { "QLOADNET", "you can't quickload during a netgame!\n\npress a key." }, { "QSAVESPOT", "you haven't picked a quicksave slot yet!\n\npress a key." }, { "QLPROMPT", "do you want to quickload the game named\n\n'%s'?\n\npress y or n." }, { "NEWGAME", "you can't start a new game\nwhile in a network game.\n\npress a key." }, { "NIGHTMARE", "are you sure? this skill level\nisn't even remotely fair.\n\npress y or n." }, { "SWSTRING", "this is the shareware version of doom.\n\nyou need to order the entire trilogy.\n\npress a key." }, { "MSGOFF", "Messages OFF" }, { "MSGON", "Messages ON" }, { "NETEND", "you can't end a netgame!\n\npress a key." }, { "ENDGAME", "are you sure you want to end the game?\n\npress y or n." }, { "DOSY", "%s\n\n(press y to quit to dos.)" }, { "DETAILHI", "High detail" }, { "DETAILLO", "Low detail" }, { "HUSTR_CHATMACRO0", "No" }, { "HUSTR_CHATMACRO1", "I'm ready to kick butt!" }, { "HUSTR_CHATMACRO2", "I'm OK." }, { "HUSTR_CHATMACRO3", "I'm not looking too good!" }, { "HUSTR_CHATMACRO4", "Help!" }, { "HUSTR_CHATMACRO5", "You suck!" }, { "HUSTR_CHATMACRO6", "Next time, scumbag..." }, { "HUSTR_CHATMACRO7", "Come here!" }, { "HUSTR_CHATMACRO8", "I'll take care of it." }, { "HUSTR_CHATMACRO9", "Yes" }, { "AMSTR_FOLLOWON", "Follow Mode ON" }, { "AMSTR_FOLLOWOFF", "Follow Mode OFF" }, { "AMSTR_GRIDON", "Grid ON" }, { "AMSTR_GRIDOFF", "Grid OFF" }, { "AMSTR_MARKEDSPOT", "Marked Spot" }, { "AMSTR_MARKSCLEARED", "All Marks Cleared" }, { "PD_BLUEO", "You need a blue key to activate this object" }, { "PD_REDO", "You need a red key to activate this object" }, { "PD_YELLOWO", "You need a yellow key to activate this object" }, { "PD_BLUEK", "You need a blue key to open this door" }, { "PD_REDK", "You need a yellow key to open this door" }, { "PD_YELLOWK", "You need a red key to open this door" }, { "EMPTYSTRING", "empty slot" }, { "GGSAVED", "game saved." }, { "GOTARMOR", "Picked up the armor." }, { "GOTMEGA", "Picked up the MegaArmor!" }, { "GOTHTHBONUS", "Picked up a health bonus." }, { "GOTARMBONUS", "Picked up an armor bonus." }, { "GOTSUPER", "Supercharge!" }, { "GOTMSPHERE", "MegaSphere!" }, { "GOTBLUECARD", "Picked up a blue keycard." }, { "GOTYELWCARD", "Picked up a yellow keycard." }, { "GOTREDCARD", "Picked up a red keycard." }, { "GOTBLUESKUL", "Picked up a blue skull key." }, { "GOTYELWSKUL", "Picked up a yellow skull key." }, { "GOTREDSKULL", "Picked up a red skull key." }, { "GOTSTIM", "Picked up a stimpack." }, { "GOTMEDINEED", "Picked up a medikit that you REALLY need!" }, { "GOTMEDIKIT", "Picked up a medikit." }, { "GOTINVUL", "Invulnerability!" }, { "GOTBERSERK", "Berserk!" }, { "GOTINVIS", "Partial Invisibility" }, { "GOTSUIT", "Radiation Shielding Suit" }, { "GOTMAP", "Computer Area Map" }, { "GOTVISOR", "Light Amplification Visor" }, { "GOTCLIP", "Picked up a clip." }, { "GOTCLIPBOX", "Picked up a box of bullets." }, { "GOTROCKET", "Picked up a rocket." }, { "GOTROCKBOX", "Picked up a box of rockets." }, { "GOTCELL", "Picked up an energy cell." }, { "GOTCELLBOX", "Picked up an energy cell pac" }, { "GOTSHELLS", "Picked up 4 shotgun shells." }, { "GOTSHELLBOX", "Picked up a box of shotgun shells." }, { "GOTBACKPACK", "Picked up a backpack full of ammo!" }, { "GOTBFG9000", "You got the BFG9000! Oh, yes." }, { "GOTCHAINGUN", "You got the chaingun!" }, { "GOTCHAINSAW", "A chainsaw! Find some meat!" }, { "GOTLAUNCHER", "You got the rocket launcher!" }, { "GOTPLASMA", "You got the plasma gun!" }, { "GOTSHOTGUN", "You got the shotgun!" }, { "GOTSHOTGUN2", "You got the super shotgun!" }, { "STSTR_DQDON", "Degreelessness Mode On" }, { "STSTR_DQDOFF", "Degreelessness Mode Off" }, { "STSTR_FAADDED", "Ammo (no keys) Added" }, { "STSTR_KFAADDED", "Very Happy Ammo Added" }, { "STSTR_MUS", "Music Change" }, { "STSTR_NOMUS", "IMPOSSIBLE SELECTION" }, { "STSTR_NCON", "No Clipping Mode ON" }, { "STSTR_NCOFF", "No Clipping Mode OFF" }, { "STSTR_BEHOLDX", "Power-up Toggled" }, { "STSTR_BEHOLD", "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp" }, { "STSTR_CHOPPERS", "... doesn't suck - GM" }, { "STSTR_CLEV", "Changing Level..." }, { "HUSTR_PLRGREEN", "Green: " }, { "HUSTR_PLRINDIGO", "Indigo: " }, { "HUSTR_PLRBROWN", "Brown: " }, { "HUSTR_PLRRED", "Red: " }, { "HUSTR_MSGU", "[Message unsent]" }, { "HUSTR_TALKTOSELF1", "You mumble to yourself" }, { "HUSTR_TALKTOSELF2", "Who's there?" }, { "HUSTR_TALKTOSELF3", "You scare yourself" }, { "HUSTR_TALKTOSELF4", "You start to rave" }, { "HUSTR_TALKTOSELF5", "You've lost it..." }, { "HUSTR_E1M1", "E1M1: Hangar" }, { "HUSTR_E1M2", "E1M2: Nuclear Plant" }, { "HUSTR_E1M3", "E1M3: Toxin Refinery" }, { "HUSTR_E1M4", "E1M4: Command Control" }, { "HUSTR_E1M5", "E1M5: Phobos Lab" }, { "HUSTR_E1M6", "E1M6: Central Processing" }, { "HUSTR_E1M7", "E1M7: Computer Station" }, { "HUSTR_E1M8", "E1M8: Phobos Anomaly" }, { "HUSTR_E1M9", "E1M9: Military Base" }, { "HUSTR_E2M1", "E2M1: Deimos Anomaly" }, { "HUSTR_E2M2", "E2M2: Containment Area" }, { "HUSTR_E2M3", "E2M3: Refinery" }, { "HUSTR_E2M4", "E2M4: Deimos Lab" }, { "HUSTR_E2M5", "E2M5: Command Center" }, { "HUSTR_E2M6", "E2M6: Halls of the Damned" }, { "HUSTR_E2M7", "E2M7: Spawning Vats" }, { "HUSTR_E2M8", "E2M8: Tower of Babel" }, { "HUSTR_E2M9", "E2M9: Fortress of Mystery" }, { "HUSTR_E3M1", "E3M1: Hell Keep" }, { "HUSTR_E3M2", "E3M2: Slough of Despair" }, { "HUSTR_E3M3", "E3M3: Pandemonium" }, { "HUSTR_E3M4", "E3M4: House of Pain" }, { "HUSTR_E3M5", "E3M5: Unholy Cathedral" }, { "HUSTR_E3M6", "E3M6: Mt. Erebus" }, { "HUSTR_E3M7", "E3M7: Limbo" }, { "HUSTR_E3M8", "E3M8: Dis" }, { "HUSTR_E3M9", "E3M9: Warrens" }, { "HUSTR_E4M1", "E4M1: Hell Beneath" }, { "HUSTR_E4M2", "E4M2: Perfect Hatred" }, { "HUSTR_E4M3", "E4M3: Sever The Wicked" }, { "HUSTR_E4M4", "E4M4: Unruly Evil" }, { "HUSTR_E4M5", "E4M5: They Will Repent" }, { "HUSTR_E4M6", "E4M6: Against Thee Wickedly" }, { "HUSTR_E4M7", "E4M7: And Hell Followed" }, { "HUSTR_E4M8", "E4M8: Unto The Cruel" }, { "HUSTR_E4M9", "E4M9: Fear" }, { "HUSTR_1", "level 1: entryway" }, { "HUSTR_2", "level 2: underhalls" }, { "HUSTR_3", "level 3: the gantlet" }, { "HUSTR_4", "level 4: the focus" }, { "HUSTR_5", "level 5: the waste tunnels" }, { "HUSTR_6", "level 6: the crusher" }, { "HUSTR_7", "level 7: dead simple" }, { "HUSTR_8", "level 8: tricks and traps" }, { "HUSTR_9", "level 9: the pit" }, { "HUSTR_10", "level 10: refueling base" }, { "HUSTR_11", "level 11: 'o' of destruction!" }, { "HUSTR_12", "level 12: the factory" }, { "HUSTR_13", "level 13: downtown" }, { "HUSTR_14", "level 14: the inmost dens" }, { "HUSTR_15", "level 15: industrial zone" }, { "HUSTR_16", "level 16: suburbs" }, { "HUSTR_17", "level 17: tenements" }, { "HUSTR_18", "level 18: the courtyard" }, { "HUSTR_19", "level 19: the citadel" }, { "HUSTR_20", "level 20: gotcha!" }, { "HUSTR_21", "level 21: nirvana" }, { "HUSTR_22", "level 22: the catacombs" }, { "HUSTR_23", "level 23: barrels o' fun" }, { "HUSTR_24", "level 24: the chasm" }, { "HUSTR_25", "level 25: bloodfalls" }, { "HUSTR_26", "level 26: the abandoned mines" }, { "HUSTR_27", "level 27: monster condo" }, { "HUSTR_28", "level 28: the spirit world" }, { "HUSTR_29", "level 29: the living end" }, { "HUSTR_30", "level 30: icon of sin" }, { "HUSTR_31", "level 31: wolfenstein" }, { "HUSTR_32", "level 32: grosse" }, { "PHUSTR_1", "level 1: congo" }, { "PHUSTR_2", "level 2: well of souls" }, { "PHUSTR_3", "level 3: aztec" }, { "PHUSTR_4", "level 4: caged" }, { "PHUSTR_5", "level 5: ghost town" }, { "PHUSTR_6", "level 6: baron's lair" }, { "PHUSTR_7", "level 7: caughtyard" }, { "PHUSTR_8", "level 8: realm" }, { "PHUSTR_9", "level 9: abattoire" }, { "PHUSTR_10", "level 10: onslaught" }, { "PHUSTR_11", "level 11: hunted" }, { "PHUSTR_12", "level 12: speed" }, { "PHUSTR_13", "level 13: the crypt" }, { "PHUSTR_14", "level 14: genesis" }, { "PHUSTR_15", "level 15: the twilight" }, { "PHUSTR_16", "level 16: the omen" }, { "PHUSTR_17", "level 17: compound" }, { "PHUSTR_18", "level 18: neurosphere" }, { "PHUSTR_19", "level 19: nme" }, { "PHUSTR_20", "level 20: the death domain" }, { "PHUSTR_21", "level 21: slayer" }, { "PHUSTR_22", "level 22: impossible mission" }, { "PHUSTR_23", "level 23: tombstone" }, { "PHUSTR_24", "level 24: the final frontier" }, { "PHUSTR_25", "level 25: the temple of darkness" }, { "PHUSTR_26", "level 26: bunker" }, { "PHUSTR_27", "level 27: anti-christ" }, { "PHUSTR_28", "level 28: the sewers" }, { "PHUSTR_29", "level 29: odyssey of noises" }, { "PHUSTR_30", "level 30: the gateway of hell" }, { "PHUSTR_31", "level 31: cyberden" }, { "PHUSTR_32", "level 32: go 2 it" }, { "THUSTR_1", "Level 1: System Control" }, { "THUSTR_2", "Level 2: Human BBQ" }, { "THUSTR_3", "Level 3: Power Control" }, { "THUSTR_4", "Level 4: Wormhole" }, { "THUSTR_5", "Level 5: Hanger" }, { "THUSTR_6", "Level 6: Open Season" }, { "THUSTR_7", "Level 7: Prison" }, { "THUSTR_8", "Level 8: Metal" }, { "THUSTR_9", "Level 9: Stronghold" }, { "THUSTR_10", "Level 10: Redemption" }, { "THUSTR_11", "Level 11: Storage Facility" }, { "THUSTR_12", "Level 12: Crater" }, { "THUSTR_13", "Level 13: Nukage Processing" }, { "THUSTR_14", "Level 14: Steel Works" }, { "THUSTR_15", "Level 15: Dead Zone" }, { "THUSTR_16", "Level 16: Deepest Reaches" }, { "THUSTR_17", "Level 17: Processing Area" }, { "THUSTR_18", "Level 18: Mill" }, { "THUSTR_19", "Level 19: Shipping/Respawning" }, { "THUSTR_20", "Level 20: Central Processing" }, { "THUSTR_21", "Level 21: Administration Center" }, { "THUSTR_22", "Level 22: Habitat" }, { "THUSTR_23", "Level 23: Lunar Mining Project" }, { "THUSTR_24", "Level 24: Quarry" }, { "THUSTR_25", "Level 25: Baron's Den" }, { "THUSTR_26", "Level 26: Ballistyx" }, { "THUSTR_27", "Level 27: Mount Pain" }, { "THUSTR_28", "Level 28: Heck" }, { "THUSTR_29", "Level 29: River Styx" }, { "THUSTR_30", "Level 30: Last Call" }, { "THUSTR_31", "Level 31: Pharaoh" }, { "THUSTR_32", "Level 32: Caribbean" }, { NULL, NULL } }; boolean BackedUpData = false; // This is the original data before it gets replaced by a patch. char OrgSprNames[NUMSPRITES][5]; char OrgActionPtrs[NUMSTATES][40]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static char *unknown_str = "Unknown key %s encountered in %s %d.\n"; // From DeHackEd source. static int toff[] = { 129044, 129044, 129044, 129284, 129380 }; // A conversion array to convert from the 448 code pointers to the 966 // Frames that exist. // Again taken from the DeHackEd source. static short codepconv[448] = { 1, 2, 3, 4, 6, 9, 10, 11, 12, 14, 16, 17, 18, 19, 20, 22, 29, 30, 31, 32, 33, 34, 36, 38, 39, 41, 43, 44, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 119, 127, 157, 159, 160, 166, 167, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 188, 190, 191, 195, 196, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 221, 223, 224, 228, 229, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 270, 272, 273, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 316, 317, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 344, 347, 348, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 387, 389, 390, 397, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 421, 423, 424, 430, 431, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 456, 458, 460, 463, 465, 475, 476, 477, 478, 479, 480, 481, 482, 483, 484, 485, 486, 487, 489, 491, 493, 502, 503, 504, 505, 506, 508, 511, 514, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539, 541, 543, 545, 548, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 570, 572, 574, 585, 586, 587, 588, 589, 590, 594, 596, 598, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 620, 621, 622, 631, 632, 633, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646, 647, 648, 650, 652, 653, 654, 659, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687, 688, 689, 690, 692, 696, 700, 701, 702, 703, 704, 705, 706, 707, 708, 709, 710, 711, 713, 715, 718, 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 743, 745, 746, 750, 751, 766, 774, 777, 779, 780, 783, 784, 785, 786, 787, 788, 789, 790, 791, 792, 793, 794, 795, 796, 797, 798, 801, 809, 811 }; static byte OrgHeights[] = { 56, 56, 56, 56, 16, 56, 8, 16, 64, 8, 56, 56, 56, 56, 56, 64, 8, 64, 56, 100, 64, 110, 56, 56, 72, 16, 32, 32, 32, 16, 42, 8, 8, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 68, 84, 84, 68, 52, 84, 68, 52, 52, 68, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 88, 88, 64, 64, 64, 64, 16, 16, 16 }; static const struct { char* name; int (*func) (int); } Modes[] = { // These appear in .deh and .bex files { "Thing", PatchThing }, { "Sound", PatchSound }, { "Frame", PatchState }, { "Sprite", PatchSprite }, { "Ammo", PatchAmmo }, { "Weapon", PatchWeapon }, { "Pointer", PatchPointer }, { "Cheat", PatchCheats }, { "Misc", PatchMisc }, { "Text", PatchText }, // These appear in .bex files { "include", DoInclude }, { "[STRINGS]", PatchStrings }, { "[PARS]", PatchPars }, { "[CODEPTR]", PatchCodePtrs }, { NULL, NULL }, }; // CODE -------------------------------------------------------------------- void BackupData(void) { int i; if(BackedUpData) return; for(i = 0; i < NUMSPRITES && i < ded->count.sprites.num; i++) strcpy(OrgSprNames[i], ded->sprites[i].id); for(i = 0; i < NUMSTATES && i < ded->count.states.num; i++) strcpy(OrgActionPtrs[i], ded->states[i].action); } char com_token[8192]; boolean com_eof; /** * Parse a token out of a string. * From ZDoom cmdlib.cpp */ char *COM_Parse(char *data) { int c; int len; len = 0; com_token[0] = 0; if(!data) return NULL; // skip whitespace skipwhite: while((c = *data) <= ' ') { if(c == 0) { com_eof = true; return NULL; // end of file; } data++; } // skip // comments if(c == '/' && data[1] == '/') { while(*data && *data != '\n') data++; goto skipwhite; } // handle quoted strings specially if(c == '\"') { data++; while((c = *data++) != '\"') { com_token[len] = c; len++; } com_token[len] = 0; return data; } // parse single characters if(c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' || /*[RH] */ c == '=') { com_token[len] = c; len++; com_token[len] = 0; return data + 1; } // parse a regular word do { com_token[len] = c; data++; len++; c = *data; if(c == '{' || c == '}' || c == ')' || c == '(' || c == '\'' || c == ':' || c == '=') break; } while(c > 32); com_token[len] = 0; return data; } boolean IsNum(char *str) { char *end; strtol(str, &end, 0); if(*end && !isspace(*end)) return false; return true; } static boolean HandleKey(const struct Key *keys, void *structure, const char *key, int value) { int off; void *ptr; while(keys->name && stricmp(keys->name, key)) keys++; if(keys->name) { //*((int *)(((byte *)structure) + keys->offset)) = value; off = keys->offset & OFF_MASK; ptr = (void *) (((byte *) structure) + off); // Apply value. if(keys->offset & OFF_STATE) strcpy((char *) ptr, ded->states[value].id); else if(keys->offset & OFF_SOUND) strcpy((char *) ptr, ded->sounds[value].id); else if(keys->offset & OFF_FIXED) *(float *) ptr = value / (float) 0x10000; else *(int *) ptr = value; return false; } return true; } static boolean ReadChars(char **stuff, int size, boolean skipJunk) { char *str = *stuff; if(!size) { *str = 0; return true; } do { // Ignore carriage returns if(*PatchPt != '\r') *str++ = *PatchPt; else size++; PatchPt++; } while(--size); *str = 0; if(skipJunk) { // Skip anything else on the line. while(*PatchPt != '\n' && *PatchPt != 0) PatchPt++; } return true; } void ReplaceSpecialChars(char *str) { char *p = str, c; int i; while((c = *p++)) { if(c != '\\') { *str++ = c; } else { switch (*p) { case 'n': case 'N': *str++ = '\n'; break; case 't': case 'T': *str++ = '\t'; break; case 'r': case 'R': *str++ = '\r'; break; case 'x': case 'X': c = 0; p++; for(i = 0; i < 2; i++) { c <<= 4; if(*p >= '0' && *p <= '9') c += *p - '0'; else if(*p >= 'a' && *p <= 'f') c += 10 + *p - 'a'; else if(*p >= 'A' && *p <= 'F') c += 10 + *p - 'A'; else break; p++; } *str++ = c; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c = 0; for(i = 0; i < 3; i++) { c <<= 3; if(*p >= '0' && *p <= '7') c += *p - '0'; else break; p++; } *str++ = c; break; default: *str++ = *p; break; } p++; } } *str = 0; } char *skipwhite(char *str) { if(str) while(*str && isspace(*str)) str++; return str; } void stripwhite(char *str) { char *end = str + strlen(str) - 1; while(end >= str && isspace(*end)) end--; end[1] = '\0'; } char *igets(void) { char *line; if(*PatchPt == '\0') return NULL; line = PatchPt; while(*PatchPt != '\n' && *PatchPt != '\0') PatchPt++; if(*PatchPt == '\n') *PatchPt++ = 0; return line; } int GetLine(void) { char *line, *line2; do { while((line = igets())) if(line[0] != '#') // Skip comment lines break; if(!line) return 0; Line1 = skipwhite(line); } while(Line1 && *Line1 == 0); // Loop until we get a line with // more than just whitespace. line = strchr(Line1, '='); if(line) { // We have an '=' in the input line line2 = line; while(--line2 >= Line1) if(*line2 > ' ') break; if(line2 < Line1) return 0; // Nothing before '=' *(line2 + 1) = 0; line++; while(*line && *line <= ' ') line++; if(*line == 0) return 0; // Nothing after '=' Line2 = line; return 1; } else { // No '=' in input line line = Line1 + 1; while(*line > ' ') line++; // Get beyond first word *line++ = 0; while(*line && *line <= ' ') line++; // Skip white space //.bex files don't have this restriction //if (*line == 0) // return 0; // No second word Line2 = line; return 2; } } int HandleMode(const char *mode, int num) { int i = 0; while(Modes[i].name && stricmp(Modes[i].name, mode)) i++; if(Modes[i].name) return Modes[i].func(num); // Handle unknown or unimplemented data LPrintf("Unknown chunk %s encountered. Skipping.\n", mode); do i = GetLine(); while(i == 1); return i; } int PatchThing(int thingy) { static const struct Key keys[] = { {"ID #", myoffsetof(ded_mobj_t, doomEdNum, 0)}, {"Hit points", myoffsetof(ded_mobj_t, spawnHealth, 0)}, {"Reaction time", myoffsetof(ded_mobj_t, reactionTime, 0)}, {"Pain chance", myoffsetof(ded_mobj_t, painChance, 0)}, {"Width", myoffsetof(ded_mobj_t, radius, OFF_FIXED)}, {"Height", myoffsetof(ded_mobj_t, height, OFF_FIXED)}, {"Mass", myoffsetof(ded_mobj_t, mass, 0)}, {"Missile damage", myoffsetof(ded_mobj_t, damage, 0)}, //{ "Translucency", myoffsetof(ded_mobj_t,translucency,0) }, {"Alert sound", myoffsetof(ded_mobj_t, seeSound, OFF_SOUND)}, {"Attack sound", myoffsetof(ded_mobj_t, attackSound, OFF_SOUND)}, {"Pain sound", myoffsetof(ded_mobj_t, painSound, OFF_SOUND)}, {"Death sound", myoffsetof(ded_mobj_t, deathSound, OFF_SOUND)}, {"Action sound", myoffsetof(ded_mobj_t, activeSound, OFF_SOUND)}, {NULL,} }; static const struct { const char* label; size_t labelLen; statename_t name; } stateNames[] = { { "Initial", 7, SN_SPAWN }, { "First moving", 12, SN_SEE }, { "Injury", 6, SN_PAIN }, { "Close attack", 12, SN_MELEE }, { "Far attack", 10, SN_MISSILE }, { "Death", 5, SN_DEATH }, { "Exploding", 9, SN_XDEATH }, { "Respawn", 7, SN_RAISE }, { NULL, 0 } }; // Flags can be specified by name (a .bex extension): static const struct { short bit; short whichflags; const char* name; } bitnames[] = { {0, 0, "SPECIAL"}, {1, 0, "SOLID"}, {2, 0, "SHOOTABLE"}, {3, 0, "NOSECTOR"}, {4, 0, "NOBLOCKMAP"}, {5, 0, "AMBUSH"}, {6, 0, "JUSTHIT"}, {7, 0, "JUSTATTACKED"}, {8, 0, "SPAWNCEILING"}, {9, 0, "NOGRAVITY"}, {10, 0, "DROPOFF"}, {11, 0, "PICKUP"}, {12, 0, "NOCLIP"}, {14, 0, "FLOAT"}, {15, 0, "TELEPORT"}, {16, 0, "MISSILE"}, {17, 0, "DROPPED"}, {18, 0, "SHADOW"}, {19, 0, "NOBLOOD"}, {20, 0, "CORPSE"}, {21, 0, "INFLOAT"}, {22, 0, "COUNTKILL"}, {23, 0, "COUNTITEM"}, {24, 0, "SKULLFLY"}, {25, 0, "NOTDMATCH"}, {26, 0, "TRANSLATION1"}, {26, 0, "TRANSLATION"}, // BOOM compatibility {27, 0, "TRANSLATION2"}, {27, 0, "UNUSED1"}, // BOOM compatibility {28, 0, "STEALTH"}, {28, 0, "UNUSED2"}, // BOOM compatibility {29, 0, "TRANSLUC25"}, {29, 0, "UNUSED3"}, // BOOM compatibility {30, 0, "TRANSLUC50"}, {(29 << 8) | 30, 0, "TRANSLUC75"}, {30, 0, "UNUSED4"}, // BOOM compatibility {30, 0, "TRANSLUCENT"}, // BOOM compatibility? {31, 0, "RESERVED"}, // Names for flags2 {0, 1, "LOGRAV"}, {1, 1, "WINDTHRUST"}, {2, 1, "FLOORBOUNCE"}, {3, 1, "BLASTED"}, {4, 1, "FLY"}, {5, 1, "FLOORCLIP"}, {6, 1, "SPAWNFLOAT"}, {7, 1, "NOTELEPORT"}, {8, 1, "RIP"}, {9, 1, "PUSHABLE"}, {10, 1, "CANSLIDE"}, // Avoid conflict with SLIDE from BOOM {11, 1, "ONMOBJ"}, {12, 1, "PASSMOBJ"}, {13, 1, "CANNOTPUSH"}, {14, 1, "DROPPED"}, {15, 1, "BOSS"}, {16, 1, "FIREDAMAGE"}, {17, 1, "NODMGTHRUST"}, {18, 1, "TELESTOMP"}, {19, 1, "FLOATBOB"}, {20, 1, "DONTDRAW"}, {21, 1, "IMPACT"}, {22, 1, "PUSHWALL"}, {23, 1, "MCROSS"}, {24, 1, "PCROSS"}, {25, 1, "CANTLEAVEFLOORPIC"}, {26, 1, "NONSHOOTABLE"}, {27, 1, "INVULNERABLE"}, {28, 1, "DORMANT"}, {29, 1, "ICEDAMAGE"}, {30, 1, "SEEKERMISSILE"}, {31, 1, "REFLECTIVE"} }; int result; ded_mobj_t* info, dummy; boolean hadHeight = false; boolean checkHeight = false; size_t thingNum = (size_t) thingy; thingNum--; if(thingNum < (unsigned) ded->count.mobjs.num) { info = ded->mobjs + thingNum; if(verbose) LPrintf("Thing %lu\n", (unsigned long) thingNum); } else { info = &dummy; LPrintf("Thing %lu out of range. Create more Thing defs!\n", (unsigned long) (thingNum + 1)); } while((result = GetLine()) == 1) { int value = atoi(Line2); size_t len = strlen(Line1); size_t sndmap; sndmap = value; if(sndmap >= sizeof(SoundMap)-1) sndmap = 0; if(HandleKey(keys, info, Line1, value)) { if(!stricmp(Line1 + len - 6, " frame")) { uint i; for(i = 0; stateNames[i].label; ++i) { if(!strnicmp(stateNames[i].label, Line1, stateNames[i].labelLen)) { strcpy(info->states[stateNames[i].name], ded->states[value].id); break; } } } else if(!stricmp(Line1, "Speed")) { if(abs(value) < 256) info->speed = (float) value; else info->speed = FIX2FLT(value); } else if(!stricmp(Line1, "Bits")) { int value = 0, value2 = 0; boolean vchanged = false, v2changed = false; char* strval; for(strval = Line2; (strval = strtok(strval, ",+| \t\f\r")); strval = NULL) { size_t iy; if(IsNum(strval)) { // Force the top 4 bits to 0 so that the user is forced // to use the mnemonics to change them. value |= (atoi(strval) & 0x0fffffff); vchanged = true; } else { for(iy = 0; iy < sizeof(bitnames) / sizeof(bitnames[0]); iy++) { if(!stricmp(strval, bitnames[iy].name)) { if(bitnames[iy].whichflags) { v2changed = true; if(bitnames[iy].bit & 0xff00) value2 |= 1 << (bitnames[iy].bit >> 8); value2 |= 1 << (bitnames[iy].bit & 0xff); } else { vchanged = true; if(bitnames[iy].bit & 0xff00) value |= 1 << (bitnames[iy].bit >> 8); value |= 1 << (bitnames[iy].bit & 0xff); } break; } } if(iy >= sizeof(bitnames) / sizeof(bitnames[0])) LPrintf("Unknown bit mnemonic %s\n", strval); } } if(vchanged) { info->flags[0] = value; if(value & 0x100) // Spawnceiling? checkHeight = true; // Bit flags are no longer used to specify translucency. // This is just a temporary hack. /*if (info->flags & 0x60000000) info->translucency = (info->flags & 0x60000000) >> 15; */ } if(v2changed) info->flags[1] = value2; if(verbose) LPrintf("Bits: %d,%d (0x%08x,0x%08x)\n", value, value2, value, value2); } else LPrintf(unknown_str, Line1, "Thing", thingNum); } else if(!stricmp(Line1, "Height")) { hadHeight = true; } } if(checkHeight && !hadHeight && thingNum < sizeof(OrgHeights)) { info->height = OrgHeights[thingNum]; } return result; } int PatchSound(int soundNum) { /* static struct Key keys[] = { {"Offset", 0}, //pointer to a name string, changed in text {"Zero/One", 0}, //info->singularity {"Value", myoffsetof(ded_sound_t, priority, 0)}, //info->priority {"Zero 1", myoffsetof(ded_sound_t, link, 0)}, //info->link {"Zero 2", myoffsetof(ded_sound_t, link_pitch, 0)}, //info->pitch {"Zero 3", myoffsetof(ded_sound_t, link_volume, 0)}, //info->volume {"Zero 4", 0}, //info->data {"Neg. One 1", 0}, //info->usefulness {"Neg. One 2", myoffsetof(ded_sound_t, id, OFF_SOUND)}, //info->lumpnum {NULL,} }; ded_sound_t *info, dummy;*/ int result; LPrintf("Sound %d (not supported)\n", soundNum); /* if (soundNum >= 0 && soundNum < ded->count.sounds.num) { info = ded->sounds + soundNum if(verbose) LPrintf("Sound %d\n", soundNum); } else { info = &dummy; LPrintf ("Sound %d out of range.\n", soundNum); } */ while((result = GetLine()) == 1) { /*if(HandleKey(keys, info, Line1, atoi(Line2))) LPrintf(unknown_str, Line1, "Sound", soundNum);*/ } /* if (offset) { // Calculate offset from start of sound names offset -= toff[dversion] + 21076; if (offset <= 64) // pistol .. bfg offset >>= 3; else if (offset <= 260) // sawup .. oof offset = (offset + 4) >> 3; else // telept .. skeatk offset = (offset + 8) >> 3; if (offset >= 0 && offset < NUMSFX) { S_sfx[soundNum].name = OrgSfxNames[offset + 1]; } else { Printf ("Sound name %d out of range.\n", offset + 1); } } */ return result; } int PatchState(int stateNum) { static struct Key keys[] = { {"Duration", myoffsetof(ded_state_t, tics, 0)}, {"Next frame", myoffsetof(ded_state_t, nextState, OFF_STATE)}, {"Unknown 1", 0 /*myoffsetof(ded_state_t,misc[0],0) */ }, {"Unknown 2", 0 /*myoffsetof(ded_state_t,misc[1],0) */ }, {NULL,} }; int result; ded_state_t *info, dummy; // C doesn't allow non-constant initializers. keys[4].offset = myoffsetof(ded_state_t, misc[0], 0); keys[5].offset = myoffsetof(ded_state_t, misc[1], 0); if(stateNum >= 0 && stateNum < ded->count.states.num) { info = ded->states + stateNum; if(verbose) LPrintf("State %d\n", stateNum); } else { info = &dummy; LPrintf("State %d out of range (Create more State defs!)\n", stateNum); } while((result = GetLine()) == 1) { int value = atoi(Line2); if(HandleKey(keys, info, Line1, value)) { if(!stricmp(Line1, "Sprite number")) Def_Set(DD_DEF_STATE, stateNum, DD_SPRITE, &value); else if(!stricmp(Line1, "Sprite subnumber")) Def_Set(DD_DEF_STATE, stateNum, DD_FRAME, &value); else LPrintf(unknown_str, Line1, "State", stateNum); } } return result; } int PatchSprite(int sprNum) { int result; int offset = 0; if(sprNum >= 0 && sprNum < NUMSPRITES) { if(verbose) LPrintf("Sprite %d\n", sprNum); } else { LPrintf("Sprite %d out of range. Create more Sprite defs!\n", sprNum); sprNum = -1; } while((result = GetLine()) == 1) { if(!stricmp("Offset", Line1)) offset = atoi(Line2); else LPrintf(unknown_str, Line1, "Sprite", sprNum); } if(offset > 0 && sprNum != -1) { // Calculate offset from beginning of sprite names. offset = (offset - toff[dversion] - 22044) / 8; if(offset >= 0 && offset < ded->count.sprites.num) { //sprNames[sprNum] = OrgSprNames[offset]; strcpy(ded->sprites[sprNum].id, OrgSprNames[offset]); } else { LPrintf("Sprite name %d out of range.\n", offset); } } return result; } /** * CRT's realloc can't access other modules' memory, so we must ask * Doomsday to reallocate memory for us. */ void *DD_Realloc(void *ptr, int newsize) { ded_count_t cnt; cnt.max = 0; cnt.num = newsize; DED_NewEntries(&ptr, &cnt, 1, 0); return ptr; } void SetValueStr(const char *path, const char *id, char *str) { int i; char realid[300]; //CString realid = CString(path) + "|" + id; sprintf(realid, "%s|%s", path, id); for(i = 0; i < ded->count.values.num; i++) if(!stricmp(ded->values[i].id, realid)) { ded->values[i].text = (char *) DD_Realloc(ded->values[i].text, strlen(str) + 1); strcpy(ded->values[i].text, str); return; } // Not found, create a new Value. i = DED_AddValue(ded, realid); // Must allocate memory using DD_Realloc. ded->values[i].text = 0; strcpy(ded->values[i].text = DD_Realloc(ded->values[i].text, strlen(str) + 1), str); } void SetValueInt(const char *path, const char *id, int val) { char buf[80]; sprintf(buf, "%i", val); SetValueStr(path, id, buf); } int PatchAmmo(int ammoNum) { int result, max, per; char *ammostr[4] = { "Clip", "Shell", "Cell", "Misl" }; char *theAmmo = NULL; // CString str; if(ammoNum >= 0 && ammoNum < 4) { if(verbose) LPrintf("Ammo %d.\n", ammoNum); theAmmo = ammostr[ammoNum]; } else LPrintf("Ammo %d out of range.\n", ammoNum); /* int *max; int *per; int dummy; if (ammoNum >= 0 && ammoNum < NUM_AMMO_TYPES) { DPrintf ("Ammo %d.\n", ammoNum); max = &maxammo[ammoNum]; per = &clipammo[ammoNum]; } else { Printf (PRINT_HIGH, "Ammo %d out of range.\n", ammoNum); max = per = &dummy; } */ while((result = GetLine()) == 1) { max = per = -1; CHECKKEY("Max ammo", max) else CHECKKEY("Per ammo", per) else LPrintf(unknown_str, Line1, "Ammo", ammoNum); if(!theAmmo) continue; if(max != -1) SetValueInt("Player|Max ammo", theAmmo, max); if(per != -1) SetValueInt("Player|Clip ammo", theAmmo, per); } return result; } int PatchNothing() { int result; while((result = GetLine()) == 1) { } return result; } int PatchWeapon(int weapNum) { // LPrintf("Weapon patches not supported.\n"); // return PatchNothing(); char *ammotypes[] = { "clip", "shell", "cell", "misl", "-", "noammo", 0 }; char buf[80]; int val; int result; if(weapNum >= 0) { if(verbose) LPrintf("Weapon %d\n", weapNum); sprintf(buf, "Weapon Info|%d", weapNum); } else { LPrintf("Weapon %d out of range.\n", weapNum); return PatchNothing(); } /* static const struct Key keys[] = { { "Ammo type", myoffsetof(weaponinfo_t,ammo) }, { "Deselect frame", myoffsetof(weaponinfo_t,upstate) }, { "Select frame", myoffsetof(weaponinfo_t,downstate) }, { "Bobbing frame", myoffsetof(weaponinfo_t,readystate) }, { "Shooting frame", myoffsetof(weaponinfo_t,atkstate) }, { "Firing frame", myoffsetof(weaponinfo_t,flashstate) }, { NULL, } }; weaponinfo_t *info, dummy; if (weapNum >= 0 && weapNum < NUM_WEAPON_TYPES) { info = &weaponinfo[weapNum]; DPrintf ("Weapon %d\n", weapNum); } else { info = &dummy; Printf (PRINT_HIGH, "Weapon %d out of range.\n", weapNum); } */ while((result = GetLine()) == 1) { /* if (HandleKey (keys, info, Line1, atoi (Line2))) Printf (PRINT_HIGH, unknown_str, Line1, "Weapon", weapNum); */ //#define CHECKKEY2(a,b) if (!stricmp (Line1, (a))) { (b) = atoi(Line2); val = atoi(Line2); if(!stricmp(Line1, "Ammo type")) SetValueStr(buf, "Type", ammotypes[val]); else if(!stricmp(Line1, "Deselect frame")) SetValueStr(buf, "Up", ded->states[val].id); else if(!stricmp(Line1, "Select frame")) SetValueStr(buf, "Down", ded->states[val].id); else if(!stricmp(Line1, "Bobbing frame")) SetValueStr(buf, "Ready", ded->states[val].id); else if(!stricmp(Line1, "Shooting frame")) SetValueStr(buf, "Atk", ded->states[val].id); else if(!stricmp(Line1, "Firing frame")) SetValueStr(buf, "Flash", ded->states[val].id); else if(!stricmp(Line1, "Ammo per shot")) SetValueInt(buf, "Per shot", val); else LPrintf(unknown_str, Line1, "Weapon", weapNum); } return result; } int PatchPointer(int ptrNum) { int result; if(ptrNum >= 0 && ptrNum < 448) { if(verbose) LPrintf("Pointer %d\n", ptrNum); } else { LPrintf("Pointer %d out of range.\n", ptrNum); ptrNum = -1; } while((result = GetLine()) == 1) { if((ptrNum != -1) && (!stricmp(Line1, "Codep Frame"))) { //states[codepconv[ptrNum]].action = OrgActionPtrs[atoi (Line2)]; strcpy(ded->states[codepconv[ptrNum]].action, OrgActionPtrs[atoi(Line2)]); } else LPrintf(unknown_str, Line1, "Pointer", ptrNum); } return result; } int PatchCheats(int dummy) { /* static const struct { char *name; byte *cheatseq; BOOL needsval; } keys[] = { { "Change music", cheat_mus_seq, true }, { "Chainsaw", cheat_choppers_seq, false }, { "God mode", cheat_god_seq, false }, { "Ammo & Keys", cheat_ammo_seq, false }, { "Ammo", cheat_ammonokey_seq, false }, { "No Clipping 1", cheat_noclip_seq, false }, { "No Clipping 2", cheat_commercial_noclip_seq, false }, { "Invincibility", cheat_powerup_seq[0], false }, { "Berserk", cheat_powerup_seq[1], false }, { "Invisibility", cheat_powerup_seq[2], false }, { "Radiation Suit", cheat_powerup_seq[3], false }, { "Auto-map", cheat_powerup_seq[4], false }, { "Lite-Amp Goggles", cheat_powerup_seq[5], false }, { "BEHOLD menu", cheat_powerup_seq[6], false }, { "Level Warp", cheat_clev_seq, true }, { "Player Position", cheat_mypos_seq, false }, { "Map cheat", cheat_amap_seq, false }, { NULL, } }; int result; DPrintf ("Cheats\n"); while ((result = GetLine ()) == 1) { int i = 0; while (keys[i].name && stricmp (keys[i].name, Line1)) i++; if (!keys[i].name) Printf (PRINT_HIGH, "Unknown cheat %s.\n", Line2); else ChangeCheat (Line2, keys[i].cheatseq, keys[i].needsval); } return result; */ LPrintf("Cheat patches are not supported!\n"); return PatchNothing(); } int PatchMisc(int dummy) { /* static const struct Key keys[] = { { "Initial Health", myoffsetof(struct DehInfo,StartHealth) }, { "Initial Bullets", myoffsetof(struct DehInfo,StartBullets) }, { "Max Health", myoffsetof(struct DehInfo,MaxHealth) }, { "Max Armor", myoffsetof(struct DehInfo,MaxArmor) }, { "Green Armor Class", myoffsetof(struct DehInfo,GreenAC) }, { "Blue Armor Class", myoffsetof(struct DehInfo,BlueAC) }, { "Max Soulsphere", myoffsetof(struct DehInfo,MaxSoulsphere) }, { "Soulsphere Health", myoffsetof(struct DehInfo,SoulsphereHealth) }, { "Megasphere Health", myoffsetof(struct DehInfo,MegasphereHealth) }, { "God Mode Health", myoffsetof(struct DehInfo,GodHealth) }, { "IDFA Armor", myoffsetof(struct DehInfo,FAArmor) }, { "IDFA Armor Class", myoffsetof(struct DehInfo,FAAC) }, { "IDKFA Armor", myoffsetof(struct DehInfo,KFAArmor) }, { "IDKFA Armor Class", myoffsetof(struct DehInfo,KFAAC) }, { "BFG Cells/Shot", myoffsetof(struct DehInfo,BFGCells) }, { "Monsters Infight", myoffsetof(struct DehInfo,Infight) }, { NULL, } }; gitem_t *item; */ int result; int val; if(verbose) LPrintf("Misc\n"); while((result = GetLine()) == 1) { val = atoi(Line2); if(!stricmp(Line1, "Initial Health")) SetValueInt("Player", "Health", val); else if(!stricmp(Line1, "Initial Bullets")) SetValueInt("Player|Init ammo", "Clip", val); else if(!stricmp(Line1, "Max Health")) SetValueInt("Player", "Health Limit", val); else if(!stricmp(Line1, "Max Armor")) SetValueInt("Player", "Blue Armor", val); else if(!stricmp(Line1, "Green Armor Class")) SetValueInt("Player", "Green Armor Class", val); else if(!stricmp(Line1, "Blue Armor Class")) SetValueInt("Player", "Blue Armor Class", val); else if(!stricmp(Line1, "Max Soulsphere")) SetValueInt("SoulSphere|Give", "Health Limit", val); else if(!stricmp(Line1, "Soulsphere Health")) SetValueInt("SoulSphere|Give", "Health", val); else if(!stricmp(Line1, "Megasphere Health")) SetValueInt("MegaSphere|Give", "Health", val); else if(!stricmp(Line1, "God Mode Health")) SetValueInt("Player", "God Health", val); else if(!stricmp(Line1, "IDFA Armor")) SetValueInt("Player", "IDFA Armor", val); else if(!stricmp(Line1, "IDFA Armor Class")) SetValueInt("Player", "IDFA Armor Class", val); else if(!stricmp(Line1, "IDKFA Armor")) SetValueInt("Player", "IDKFA Armor", val); else if(!stricmp(Line1, "IDKFA Armor Class")) SetValueInt("Player", "IDKFA Armor Class", val); else if(!stricmp(Line1, "BFG Cells/Shot")) SetValueInt("Weapon Info|6", "Per shot", val); else if(!stricmp(Line1, "Monsters Infight")) SetValueInt("AI", "Infight", val); else LPrintf("Unknown miscellaneous info %s = %s.\n", Line1, Line2); } return result; } int PatchPars(int dummy) { char *space, mapname[8], *moredata; ded_mapinfo_t *info; int result, par, i; if(verbose) LPrintf("[Pars]\n"); while((result = GetLine())) { // Argh! .bex doesn't follow the same rules as .deh if(result == 1) { LPrintf("Unknown key in [PARS] section: %s\n", Line1); continue; } if(stricmp("par", Line1)) return result; space = strchr(Line2, ' '); if(!space) { LPrintf("Need data after par.\n"); continue; } *space++ = '\0'; while(*space && isspace(*space)) space++; moredata = strchr(space, ' '); if(moredata) { // At least 3 items on this line, must be E?M? format sprintf(mapname, "E%cM%c", *Line2, *space); par = atoi(moredata + 1); } else { // Only 2 items, must be MAP?? format sprintf(mapname, "MAP%02d", atoi(Line2) % 100); par = atoi(space); } info = NULL; /*if (!(info = FindLevelInfo (mapname)) ) { Printf (PRINT_HIGH, "No map %s\n", mapname); continue; } */ for(i = 0; i < ded->count.mapInfo.num; i++) if(!stricmp(ded->mapInfo[i].id, mapname)) { info = ded->mapInfo + i; break; } if(info) info->parTime = (float) par; LPrintf("Par for %s changed to %d\n", mapname, par); } return result; } int PatchCodePtrs(int dummy) { LPrintf("[CodePtr] patches not supported\n"); return PatchNothing(); /* int result; LPrintf ("[CodePtr]\n"); while ((result = GetLine()) == 1) { if (!strnicmp ("Frame", Line1, 5) && isspace(Line1[5])) { int frame = atoi (Line1 + 5); if (frame < 0 || frame >= NUMSTATES) { Printf (PRINT_HIGH, "Frame %d out of range\n", frame); } else { int i = 0; char *data; COM_Parse (Line2); if ((com_token[0] == 'A' || com_token[0] == 'a') && com_token[1] == '_') data = com_token + 2; else data = com_token; while (CodePtrs[i].name && stricmp (CodePtrs[i].name, data)) i++; if (CodePtrs[i].name) { states[frame].action.acp1 = CodePtrs[i].func.acp1; DPrintf ("Frame %d set to %s\n", frame, CodePtrs[i].name); } else { states[frame].action.acp1 = NULL; DPrintf ("Unknown code pointer: %s\n", com_token); } } } } return result; */ } static void replaceInString(char* str, size_t len, const char* occurance, const char* replacewith) { char* buf, *out, *in; int oclen, replen; if(!str || !len || !occurance || !(oclen = strlen(occurance)) || !replacewith || !(replen = strlen(replacewith))) return; out = buf = calloc(strlen(str) * 2, 1); in = str; for(; *in; in++) { if(!strncmp(in, occurance, oclen)) { strcat(out, replacewith); out += replen; in += oclen - 1; } else *out++ = *in; } strncpy(str, buf, len); free(buf); } static void patchSpriteNames(const char* origName, const char* newName) { size_t i; char old[5]; if(strlen(origName) != 4) return; for(i = 0; i < 4; ++i) old[i] = (char) toupper((int) origName[i]); old[4] = '\0'; i = 0; do { int num; if(!strcmp(SpriteMap[i], old) && (num = Def_Get(DD_DEF_SPRITE, old, NULL)) != -1) { ded_sprid_t* spr = &ded->sprites[num]; strncpy(spr->id, newName, DED_SPRITEID_LEN); } } while(SpriteMap[++i] != NULL); } static void patchMusicLumpNames(const char* origName, const char* newName) { char buf[9]; size_t i; dd_snprintf(buf, 9, "d_%s", origName); i = 0; do { if(!strcmp(MusicMap[i], origName)) { int j; for(j = 0; j < ded->count.music.num; ++j) { if(!stricmp(ded->music[j].lumpName, buf)) { dd_snprintf(ded->music[j].lumpName, 9, "D_%s", newName); } } } } while(MusicMap[++i] != NULL); } static const char* textIDForOrigString(const char* str) { size_t i; i = 0; do { if(!stricmp(TextMap[i].str, str)) return TextMap[i].id; } while(TextMap[++i].id != NULL); return NULL; } static void patchText(const char* origStr, const char* newStr) { #define BUF_SIZE 4096 int id; if(!((id = Def_Get(DD_DEF_TEXT, textIDForOrigString(origStr), NULL)) < 0)) { char buf[BUF_SIZE]; strncpy(buf, newStr, 4096); replaceInString(buf, 4096, "\n", "\\n"); Def_Set(DD_DEF_TEXT, id, 0, buf); } #undef BUF_SIZE } int PatchText(int oldSize) { int newSize; char* oldStr, *newStr, *temp; boolean parseError = false; temp = COM_Parse(Line2); // Skip old size, since we already have it if(!COM_Parse(temp)) { LPrintf("Text chunk is missing size of new string.\n"); return 2; } newSize = atoi(com_token); oldStr = malloc(oldSize + 1); newStr = malloc(newSize + 1); if(oldStr && newStr) { boolean good; good = ReadChars(&oldStr, oldSize, false); good += ReadChars(&newStr, newSize, true); if(good) { if(!includenotext) { if(verbose) { LPrintf("Searching for text:\n%s\n", oldStr); LPrintf("<< TO BE REPLACED WITH:\n%s\n>>\n", newStr); } patchSpriteNames(oldStr, newStr); patchMusicLumpNames(oldStr, newStr); patchText(oldStr, newStr); } else { LPrintf("Skipping text chunk in included patch.\n"); } } else { LPrintf("Unexpected end-of-file.\n"); parseError = true; } } else { LPrintf("Out of memory.\n"); } if(newStr) free(newStr); if(oldStr) free(oldStr); if(!parseError) { int result; // Fetch next identifier for main loop while((result = GetLine()) == 1); return result; } return 0; } int PatchStrings(int dummy) { LPrintf("[Strings] patches not supported\n"); return PatchNothing(); /* static size_t maxstrlen = 128; static char *holdstring; int result; DPrintf ("[Strings]\n"); if (!holdstring) holdstring = Malloc (maxstrlen); while ((result = GetLine()) == 1) { int i; *holdstring = '\0'; do { while (maxstrlen < strlen (holdstring) + strlen (Line2)) { maxstrlen += 128; holdstring = (char *)Realloc (holdstring, maxstrlen); } strcat (holdstring, skipwhite (Line2)); stripwhite (holdstring); if (holdstring[strlen(holdstring)-1] == '\\') { holdstring[strlen(holdstring)-1] = '\0'; Line2 = igets (); } else Line2 = NULL; } while (Line2 && *Line2); for (i = 0; i < NUMSTRINGS; i++) if (!stricmp (Strings[i].name, Line1)) break; if (i == NUMSTRINGS) { Printf (PRINT_HIGH, "Unknown string: %s\n", Line1); } else { ReplaceSpecialChars (holdstring); ReplaceString (&Strings[i].string, copystring (holdstring)); Strings[i].type = str_patched; Printf (PRINT_HIGH, "%s set to:\n%s\n", Line1, holdstring); } } return result; */ } int DoInclude(int dummy) { char *data; int savedversion, savepversion; char *savepatchfile, *savepatchpt; int len; FILE *file; char *patch; if(including) { LPrintf("Sorry, can't nest includes\n"); goto endinclude; } data = COM_Parse(Line2); if(!stricmp(com_token, "notext")) { includenotext = true; data = COM_Parse(data); } if(!com_token[0]) { includenotext = false; LPrintf("Include directive is missing filename\n"); goto endinclude; } if(verbose) LPrintf("Including %s\n", com_token); savepatchfile = PatchFile; savepatchpt = PatchPt; savedversion = dversion; savepversion = pversion; including = true; file = fopen(com_token, "rt"); if(!file) { LPrintf("Can't include %s, it can't be found.\n", com_token); goto endinclude; } fseek(file, 0, SEEK_END); len = ftell(file); patch = calloc(len + 1, 1); rewind(file); fread(patch, len, 1, file); patch[len] = 0; fclose(file); ApplyDEH(patch, len); free(patch); if(verbose) LPrintf("Done with include\n"); PatchFile = savepatchfile; PatchPt = savepatchpt; dversion = savedversion; pversion = savepversion; endinclude: including = false; includenotext = false; return GetLine(); } void ApplyDEH(char *patch, int length) { int cont; BackupData(); PatchFile = patch; dversion = pversion = -1; cont = 0; if(!strncmp(PatchFile, "Patch File for DeHackEd v", 25)) { PatchPt = strchr(PatchFile, '\n'); while((cont = GetLine()) == 1) { CHECKKEY("Doom version", dversion) else CHECKKEY("Patch format", pversion)} if(!cont || dversion == -1 || pversion == -1) { Con_Message("This is not a DeHackEd patch file!"); return; } } else { LPrintf("Patch does not have DeHackEd signature. Assuming .bex\n"); dversion = 19; pversion = 6; PatchPt = PatchFile; while((cont = GetLine()) == 1); } if(pversion != 6) { LPrintf ("DeHackEd patch version is %d.\nUnexpected results may occur.\n", pversion); } if(dversion == 16) dversion = 0; else if(dversion == 17) dversion = 2; else if(dversion == 19) dversion = 3; else if(dversion == 20) dversion = 1; else if(dversion == 21) dversion = 4; else { LPrintf ("Patch created with unknown DOOM version.\nAssuming version 1.9.\n"); dversion = 3; } do { if(cont == 1) { LPrintf("Key %s encountered out of context\n", Line1); cont = 0; } else if(cont == 2) cont = HandleMode(Line1, atoi(Line2)); } while(cont); } /** * Reads and applies the given lump as a DEH patch. */ void ReadDehackedLump(int lumpnum) { size_t len; byte *lump; Con_Message("Applying Dehacked: lump %i...\n", lumpnum); len = W_LumpLength(lumpnum); lump = calloc(len + 1, 1); memcpy(lump, W_CacheLumpNum(lumpnum, PU_CACHE), len); ApplyDEH((char*)lump, len); free(lump); } /** * Reads and applies the given Dehacked patch file. */ void ReadDehacked(char *filename) { FILE *file; char *deh; int len; Con_Message("Applying Dehacked: %s...\n", filename); // Read in the patch. if((file = fopen(filename, "rt")) == NULL) return; // Shouldn't happen. // How long is it? fseek(file, 0, SEEK_END); len = ftell(file) + 1; // Allocate enough memory and read it. deh = calloc(len + 1, 1); rewind(file); fread(deh, len, 1, file); fclose(file); // Process it! ApplyDEH(deh, len); free(deh); } /** * This will be called after the engine has loaded all definitions but * before the data they contain has been initialized. */ int DefsHook(int hook_type, int parm, void *data) { int i; verbose = ArgExists("-verbose"); ded = (ded_t *) data; // Check for a DEHACKED lumps. for(i = DD_GetInteger(DD_NUMLUMPS) - 1; i >= 0; i--) if(!strnicmp(W_LumpName(i), "DEHACKED", 8)) { ReadDehackedLump(i); // We'll only continue this if the -alldehs option is given. if(!ArgCheck("-alldehs")) break; } // How about the -deh option? if(ArgCheckWith("-deh", 1)) { filename_t temp; const char* fn; // Aha! At least one DEH specified. Let's read all of 'em. while((fn = ArgNext()) != NULL && fn[0] != '-') { M_TranslatePath(temp, fn, FILENAME_T_MAXLEN); if(!M_FileExists(temp)) continue; ReadDehacked(temp); } } return true; } /** * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ void DP_Initialize(void) { Plug_AddHook(HOOK_DEFS, DefsHook); } #ifdef WIN32 /** * Windows calls this when the DLL is loaded. */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch (fdwReason) { case DLL_PROCESS_ATTACH: // Register our hooks. DP_Initialize(); break; } return TRUE; } #endif #if 0 /** * Here follows the remainder of the text strings in DOOM2.EXE which can * be changed by patching with DeHackED 3.0 * * \todo There are a few interesting strings amongst this lot which I am * pretty sure have been used in some of the older mods such as Aliens TC. */ "CODEC: Testing I/O address: %04x\n" "CODEC: Starting the \"busy\" test.\n" "CODEC: The \"busy\" test failed.\n" "CODEC: Passed the \"busy\" test.\n" "CODEC: Starting the version test.\n" "CODEC: Failed the version inspection.\n" "CODEC: Passed the version inspection.\n" "CODEC: Starting the misc. write test.\n" "CODEC: Failed the misc. write test.\n" "CODEC: Passed all I/O port inspections.\n" "=" "SNDSCAPE" "\\SNDSCAPE.INI" "r" "Port" "DMA" "IRQ" "WavePort" " out of GUS RAM:" "%d%c" "GF1PATCH110" "110" ",%d" "Ultrasound @ Port:%03Xh, IRQ:%d, DMA:%d\n" "Sizing GUS RAM:" "BANK%d:OK " "BANK%d:N/A " "\n" "ULTRADIR" "\\midi\\" "\r\n" "Loading GUS Patches\n" ".pat" "%s" " - FAILED\n" " - OK\n" "ULTRASND" "NO MVSOUND.SYS\n" "PAS IRQ: %d DMA:%d\n" "Pro Audio Spectrum is NOT version 1.01.\n" "ECHO Personal Sound System Enabled.\n" "BLASTER" "%x" "Pro Audio Spectrum 3D JAZZ\n" "\nDSP Version: %x.%02x\n" " IRQ: %d\n" " DMA: %d\n" "GENMIDI.OP2" "MixPg: " "WAVE" "fmt " "data" "MThd" "MTrk" "MUS" "DMXTRACE" "DMXOPTION" "-opl3" "-phase" "Bad I_UpdateBox (%i, %i, %i, %i)" "PLAYPAL" "0x%x\n" "-nomouse" "Mouse: not present\n" "Mouse: detected\n" "-nojoy" "joystick not found\n" "joystick found\n" "CENTER the joystick and press button 1:" "\nPush the joystick to the UPPER LEFT corner and press button 1:" "\nPush the joystick to the LOWER RIGHT corner and press button 1:" "\n" "INT_SetTimer0: %i is a bad value" "novideo" "-control" "Using external control API\n" "I_StartupDPMI\n" "I_StartupMouse\n" "I_StartupJoystick\n" "I_StartupKeyboard\n" "I_StartupSound\n" "ENDOOM" "DPMI memory: 0x%x" ", 0x%x allocated for zone\n" "Insufficient memory! You need to have at least 3.7 megabytes of total\n" "free memory available for DOOM to execute. Reconfigure your CONFIG.SYS\n" "or AUTOEXEC.BAT to load fewer device drivers or TSR's. We recommend\n" "creating a custom boot menu item in your CONFIG.SYS for optimum DOOMing.\n" "Please consult your DOS manual (\"Making more memory available\") for\n" "information on how to free up more memory for DOOM.\n\n" "DOOM aborted.\n" "-cdrom" "STCDROM" "STDISK" "I_AllocLow: DOS alloc of %i failed, %i free" "-net" "malloc() in I_InitNetwork() failed" "I_NetCmd when not in netgame" "I_StartupTimer()\n" "Can't register 35 Hz timer w/ DMX library" "d%c%s" "-nosound" "-nosfx" "-nomusic" "ENSONIQ\n" "Dude. The ENSONIQ ain't responding.\n" "CODEC p=0x%x, d=%d\n" "CODEC. The CODEC ain't responding.\n" "GUS\n" "GUS1\n" "Dude. The GUS ain't responding.\n" "GUS2\n" "dmxgusc" "dmxgus" "cfg p=0x%x, i=%d, d=%d\n" "SB isn't responding at p=0x%x, i=%d, d=%d\n" "SB_Detect returned p=0x%x,i=%d,d=%d\n" "Adlib\n" "Dude. The Adlib isn't responding.\n" "genmidi" "Midi\n" "cfg p=0x%x\n" "The MPU-401 isn't reponding @ p=0x%x.\n" "I_StartupSound: Hope you hear a pop.\n" " Music device #%d & dmxCode=%d\n" " Sfx device #%d & dmxCode=%d\n" " calling DMX_Init\n" " DMX_Init() returned %d\n" "CyberMan: Wrong mouse driver - no SWIFT support (AX=%04x).\n" "CyberMan: no SWIFT device connected.\n" "CyberMan: SWIFT device is not a CyberMan! (type=%d)\n" "CyberMan: CyberMan %d.%02d connected.\n" "SLIME16" "RROCK14" "RROCK07" "RROCK17" "RROCK13" "RROCK19" "FLOOR4_8" "SFLR6_1" "MFLR8_4" "MFLR8_3" "BOSSBACK" "PFUB2" "PFUB1" "END0" "END%i" "CREDIT" "VICTORY2" "ENDPIC" "map01" "PLAYPAL" "M_PAUSE" "-debugfile" "debug%i.txt" "debug output to: %s\n" "w" "TITLEPIC" "demo1" "CREDIT" "demo2" "demo3" "demo4" "default.cfg" "doom1.wad" "doom2f.wad" "doom2.wad" "doom.wad" "-shdev" "c:/localid/doom1.wad" "f:/doom/data_se/data_se/texture1.lmp" "f:/doom/data_se/data_se/pnames.lmp" "c:/localid/default.cfg" "-regdev" "c:/localid/doom.wad" "f:/doom/data_se/data_se/texture1.lmp" "f:/doom/data_se/data_se/texture2.lmp" "f:/doom/data_se/data_se/pnames.lmp" "-comdev" "c:/localid/doom2.wad" "f:/doom/data_se/cdata/texture1.lmp" "f:/doom/data_se/cdata/pnames.lmp" "French version\n" "Game mode indeterminate.\n" "rb" "\nNo such response file!" "Found response file %s!\n" "%d command-line args:\n" "%s\n" "-nomonsters" "-respawn" "-fast" "-devparm" "-altdeath" "-deathmatch" " The Ultimate DOOM Startup v%i.%i " " DOOM 2: Hell on Earth v%i.%i " "\nP_Init: Checking cmd-line parameters...\n" "-cdrom" "c:\\doomdata" "c:/doomdata/default.cfg" "-turbo" "turbo scale: %i%%\n" "-wart" "~f:/doom/data_se/cdata/map0%i.wad" "~f:/doom/data_se/cdata/map%i.wad" "~f:/doom/data_se/E%cM%c.wad" "Warping to Episode %s, Map %s.\n" "-file" "-playdemo" "-timedemo" "%s.lmp" "Playing demo %s.lmp.\n" "-skill" "-episode" "-timer" "Levels will end after %d minute" "s" ".\n" "-avg" "Austin Virtual Gaming: Levels will end after 20 minutes\n" "-warp" "V_Init: allocate screens.\n" "M_LoadDefaults: Load system defaults.\n" "Z_Init: Init zone memory allocation daemon. \n" "W_Init: Init WADfiles.\n" "\nYou cannot -file with the shareware version. Register!" "\nThis is not the registered version." "===========================================================================\nATTENTION: This version of DOOM has been modified. If you would like to\nget a copy of the original game, call 1-800-IDGAMES or see the readme file.\n You will not receive technical support for modified games.\n press enter to continue\n===========================================================================\n" "\tregistered version.\n" "===========================================================================\n This version is NOT SHAREWARE, do not distribute!\n Please report software piracy to the SPA: 1-800-388-PIR8\n===========================================================================\n" "\tshareware version.\n" "\tcommercial version.\n" "===========================================================================\n Do not distribute!\n Please report software piracy to the SPA: 1-800-388-PIR8\n===========================================================================\n" "M_Init: Init miscellaneous info.\n" "R_Init: Init DOOM refresh daemon - " "\nP_Init: Init Playloop state.\n" "I_Init: Setting up machine state.\n" "D_CheckNetGame: Checking network game status.\n" "S_Init: Setting up sound.\n" "HU_Init: Setting up heads up display.\n" "ST_Init: Init status bar.\n" "-statcopy" "External statistics registered.\n" "-record" "-loadgame" "c:\\doomdata\\doomsav%c.dsg" "doomsav%c.dsg" "ExpandTics: strange value %i at maketic %i" "Tried to transmit to another node" "send (%i + %i, R %i) [%i] " "%i " "\n" "bad packet length %i\n" "bad packet checksum\n" "setup packet\n" "get %i = (%i + %i, R %i)[%i] " "Player 1 left the game" "Killed by network driver" "retransmit from %i\n" "out of order packet (%i + %i)\n" "missed tics from %i (%i - %i)\n" "NetUpdate: netbuffer->numtics > BACKUPTICS" "Network game synchronization aborted." "listening for network start info...\n" "Different DOOM versions cannot play a net game!" "sending network start info...\n" "Doomcom buffer invalid!" "startskill %i deathmatch: %i startmap: %i startepisode: %i\n" "player %i of %i (%i nodes)\n" "=======real: %i avail: %i game: %i\n" "TryRunTics: lowtic < gametic" "gametic>lowtic" "%s is turbo!" "consistency failure (%i should be %i)" "NET GAME" "Only %i deathmatch spots, 4 required" "map31" "version %i" "Bad savegame" "-cdrom" "c:\\doomdata\\doomsav%d.dsg" "doomsav%d.dsg" "Savegame buffer overrun" "SKY3" "SKY1" "SKY2" "SKY4" ".lmp" "-maxdemo" "Demo is from a different game version!" "-nodraw" "-noblit" "timed %i gametics in %i realtics" "Z_CT at g_game.c:%i" "Demo %s recorded" "-cdrom" "c:\\doomdata\\doomsav%d.dsg" "doomsav%d.dsg" "M_LOADG" "M_LSLEFT" "M_LSCNTR" "M_LSRGHT" "M_SAVEG" "_" "HELP2" "HELP1" "HELP" "M_SVOL" "M_DOOM" "M_NEWG" "M_SKILL" "M_EPISOD" "M_OPTTTL" "M_THERML" "M_THERMM" "M_THERMR" "M_THERMO" "M_CELL1" "M_CELL2" "PLAYPAL" "Couldn't read file %s" "mouse_sensitivity" "sfx_volume" "music_volume" "show_messages" "key_right" "key_left" "key_up" "key_down" "key_strafeleft" "key_straferight" "key_fire" "key_use" "key_strafe" "key_speed" "use_mouse" "mouseb_fire" "mouseb_strafe" "mouseb_forward" "use_joystick" "joyb_fire" "joyb_strafe" "joyb_use" "joyb_speed" "screenblocks" "detaillevel" "snd_channels" "snd_musicdevice" "snd_sfxdevice" "snd_sbport" "snd_sbirq" "snd_sbdma" "snd_mport" "usegamma" "chatmacro0" "chatmacro1" "chatmacro2" "chatmacro3" "chatmacro4" "chatmacro5" "chatmacro6" "chatmacro7" "chatmacro8" "chatmacro9" "w" "%s\t\t%i\n" "%s\t\t\"%s\"\n" "-config" "\tdefault file: %s\n" "r" "%79s %[^\n]\n" "%x" "%i" "DOOM00.pcx" "M_ScreenShot: Couldn't create a PCX" "PLAYPAL" "screen shot" "AMMNUM%d" "Z_CT at am_map.c:%i" "%s %d" "fuck %d \r" "Weird actor->movedir!" "P_NewChaseDir: called with no target" "P_GiveAmmo: bad type %i" "P_SpecialThing: Unknown gettable thing" "PTR_SlideTraverse: not a line?" "P_AddActivePlat: no more plats!" "P_RemoveActivePlat: can't find plat!" "P_GroupLines: miscounted" "map0%i" "map%i" "P_CrossSubsector: ss %i with numss = %i" "P_InitPicAnims: bad cycle from %s to %s" "P_PlayerInSpecialSector: unknown special %i" "texture2" "-avg" "-timer" "P_StartButton: no button slots left!" "P_SpawnMapThing: Unknown type %i at (%i, %i)" "Unknown tclass %i in savegame" "P_UnarchiveSpecials:Unknown tclass %i in savegame" "R_Subsector: ss %i with numss = %i" "Z_CT at r_data.c:%i" "R_GenerateLookup: column without a patch (%s)\n" "R_GenerateLookup: texture %i is >64k" "PNAMES" "TEXTURE1" "TEXTURE2" "S_START" "S_END" "[" " " " ]" "" "" "." "R_InitTextures: bad texture directory" "R_InitTextures: Missing patch in texture %s" "F_START" "F_END" "COLORMAP" "R_FlatNumForName: %s not found" "R_TextureNumForName: %s not found" "R_DrawFuzzColumn: %i to %i at %i" "R_DrawColumn: %i to %i at %i" "brdr_t" "brdr_b" "brdr_l" "brdr_r" "brdr_tl" "brdr_tr" "brdr_bl" "brdr_br" "." "F_SKY1" "R_MapPlane: %i, %i at %i" "R_FindPlane: no more visplanes" "R_DrawPlanes: drawsegs overflow (%i)" "R_DrawPlanes: visplane overflow (%i)" "R_DrawPlanes: opening overflow (%i)" "Z_CT at r_plane.c:%i" "Bad R_RenderWallRange: %i to %i" "R_InstallSpriteLump: Bad frame characters in lump %i" "R_InitSprites: Sprite %s frame %c has multip rot=0 lump" "R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump" "R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump" "R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it" "R_InitSprites: No patches found for %s frame %c" "R_InitSprites: Sprite %s frame %c is missing rotations" "R_DrawSpriteRange: bad texturecolumn" "R_ProjectSprite: invalid sprite number %i " "R_ProjectSprite: invalid sprite frame %i : %i " "R_ProjectSprite: invalid sprite number %i " "R_ProjectSprite: invalid sprite frame %i : %i " "Filename base of %s >8 chars" "\tcouldn't open %s\n" "\tadding %s\n" "wad" "IWAD" "PWAD" "Wad file %s doesn't have IWAD or PWAD id\n" "Couldn't realloc lumpinfo" "W_Reload: couldn't open %s" "W_InitFiles: no files found" "Couldn't allocate lumpcache" "W_GetNumForName: %s not found!" "W_LumpLength: %i >= numlumps" "W_ReadLump: %i >= numlumps" "W_ReadLump: couldn't open %s" "W_ReadLump: only read %i of %i on lump %i" "W_CacheLumpNum: %i >= numlumps" "Z_CT at w_wad.c:%i" "w" "waddump.txt" "%s " " %c" "\n" "Bad V_CopyRect" "Bad V_DrawPatch" "Bad V_DrawPatchDirect" "Bad V_DrawBlock" "Z_Free: freed a pointer without ZONEID" "Z_Malloc: failed on allocation of %i bytes" "Z_Malloc: an owner is required for purgable blocks" "zone size: %i location: %p\n" "tag range: %i to %i\n" "block:%p size:%7i user:%p tag:%3i\n" "ERROR: block size does not touch the next block\n" "ERROR: next block doesn't have proper back link\n" "ERROR: two consecutive free blocks\n" "block:%p size:%7i user:%p tag:%3i\n" "ERROR: block size does not touch the next block\n" "ERROR: next block doesn't have proper back link\n" "ERROR: two consecutive free blocks\n" "Z_CheckHeap: block size does not touch the next block\n" "Z_CheckHeap: next block doesn't have proper back link\n" "Z_CheckHeap: two consecutive free blocks\n" "Z_ChangeTag: freed a pointer without ZONEID" "Z_ChangeTag: an owner is required for purgable blocks" "ang=0x%x;x,y=(0x%x,0x%x)" "STTNUM%d" "STYSNUM%d" "STTPRCNT" "STKEYS%d" "STARMS" "STGNUM%d" "STFB%d" "STBAR" "STFST%d%d" "STFTR%d0" "STFTL%d0" "STFOUCH%d" "STFEVL%d" "STFKILL%d" "STFGOD0" "STFDEAD0" "PLAYPAL" "Z_CT at st_stuff.c:%i" "STTMINUS" "drawNum: n->y - ST_Y < 0" "updateMultIcon: y - ST_Y < 0" "updateBinIcon: y - ST_Y < 0" "NEWLEVEL" "STCFN%.3d" "Could not place patch on level %d" "INTERPIC" "WIMAP%d" "CWILV%2.2d" "WILV%d%d" "WIURH0" "WIURH1" "WISPLAT" "WIA%d%.2d%.2d" "WIMINUS" "WINUM%d" "WIPCNT" "WIF" "WIENTER" "WIOSTK" "WIOSTS" "WISCRT2" "WIOBJ" "WIOSTI" "WIFRGS" "WICOLON" "WITIME" "WISUCKS" "WIPAR" "WIKILRS" "WIVCTMS" "WIMSTT" "STFST01" "STFDEAD0" "STPB%d" "WIBP%d" "Z_CT at wi_stuff.c:%i" "wi_stuff.c" "wbs->epsd" "%s=%d in %s:%d" "wbs->last" "wbs->next" "wbs->pnum" "Attempt to set music volume at %d" "Z_CT at s_sound.c:%i" "Bad music number %d" "d_%s" "Attempt to set sfx volume at %d" "Bad sfx #: %d" "Bad list in dll_AddEndNode" "Bad list in dll_AddStartNode" "Bad list in dll_DelNode" "Empty list in dll_DelNode" "Floating-point support not loaded\r\n" "TZ" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/include/0000755000175000017500000000000011523516204021562 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/include/version.h0000644000175000017500000000333011357170242023422 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __DEHREAD_VERSION_H__ #define __DEHREAD_VERSION_H__ #ifndef DEHREAD_VER_ID # ifdef _DEBUG # define DEHREAD_VER_ID "+D Doomsday" # else # define DEHREAD_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define PLUGIN_NAME "dpdehread" // Presented to the user in dialogs, messages etc. #define PLUGIN_NICENAME "Deh Reader" #define PLUGIN_DETAILS "Deh Reader is based on ZDoom's Deh patch reader." #define PLUGIN_VERSION_TEXT "1.2.6" #define PLUGIN_VERSION_TEXTLONG "Version" PLUGIN_VERSION_TEXT " " __DATE__ " (" DEHREAD_VER_ID ")" #define PLUGIN_VERSION_NUMBER 1,2,6,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/dehread/CMakeLists.txt0000644000175000017500000000410611357170242022703 0ustar keeskees## deng build scripts. ## Copyright © 2006 - 2007 Jamie Jones ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ ######################## Dehacked Reader Plugin ############################### FILE(GLOB DEHREAD_SOURCES src/*.c) ADD_LIBRARY (dpdehread SHARED ${DEHREAD_SOURCES}) ################################################################################ ######################## Install Targets ###################################### INSTALL(TARGETS dpdehread RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) IF (APPLE) # Bundling. SET (BUNDLE_BASE dpDehRead) SET (BUNDLE ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.bundle) ADD_CUSTOM_COMMAND( TARGET dpdehread POST_BUILD COMMAND rm -rf ${BUNDLE} COMMAND mkdir -p ${BUNDLE}/Contents/MacOS COMMAND cp libdpdehread.dylib ${BUNDLE}/Contents/MacOS/${BUNDLE_BASE} COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/${BUNDLE_BASE}-Info.plist ${BUNDLE}/Contents/Info.plist #COMMAND mkdir -p ${BUNDLE}/Contents/Resources/English.lproj #COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/InfoPlist.strings ${BUNDLE}/Contents/Resources/English.lproj/ COMMAND echo 'APPL????' > ${BUNDLE}/Contents/PkgInfo ) ENDIF (APPLE) deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/0000755000175000017500000000000011523516204017653 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/api/0000755000175000017500000000000011523516204020424 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/api/jdoom.def0000644000175000017500000000005011357170242022212 0ustar keeskeesLIBRARY JDOOM EXPORTS GetGameAPI @1deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/res/0000755000175000017500000000000011523516204020444 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/res/jdoom.dll.manifest0000644000175000017500000000062311357170242024062 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/res/jdoom.rc0000644000175000017500000001026111357170242022105 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jdoom.rc: jDoom.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""jdoom.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION GAME_VERSION_NUMBER\r\n" "PRODUCTVERSION GAME_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", GAME_NICENAME "" (Doomsday Engine game plugin)\0""\r\n" " VALUE ""FileVersion"", GAME_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", GAME_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""jDoom.dll\0""\r\n" " VALUE ""ProductName"", GAME_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", GAME_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif /** * Icons: * Icon with lowest ID value placed first to ensure application icon * remains consistent on all systems. */ IDI_GAME_ICON ICON DISCARDABLE "jdoom.ico" #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION GAME_VERSION_NUMBER PRODUCTVERSION GAME_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", GAME_NICENAME " (Doomsday Engine game plugin)\0" VALUE "FileVersion", GAME_VERSION_TEXT "\0" VALUE "InternalName", GAME_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "jDoom.dll\0" VALUE "ProductName", GAME_NICENAME "\0" VALUE "ProductVersion", GAME_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/res/jdoom.ico0000644000175000017500000000427611357170242022264 0ustar keeskees ( @ʦ """)))UUUMMMBBB999|PP3f3333f333ff3fffff3f3f̙f3333f3333333333f3333333f3f33ff3f3f3f3333f3333333f3̙33333f333ff3ffffff3f33f3ff3f3f3ffff3fffffffff3fffffff3f̙ffff3ff333f3ff33fff33f3ff̙3f3f3333f333ff3fffff̙̙3̙f̙̙̙3f̙3f3f3333f333ff3fffff3f3f̙3ffffffffff!___www K JJKJ XDJKJC XQJKKKJ XRRKKKKKJ XKKRQKKJDJC XKtKRXJKKKJJ XJKKKKXRKJKKJJ XJKKKtKQXQKKKKKJ XDRJKRKLRXXKKDKK XJKJKKJKKKQXRLJJ XJDJKJKKKJKtXDJ t"CJCJKJKKKK "R CJJCJJDJJJCK "R" 7KQJDJJKKzKK L t *)CCJKzJK L__ L"J+CDJSJK K___FC ><__D" >___<_=<<<<$ =<<<<<<<<<__< =<<<<<<<<<<_< > >< << deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/res/resource.h0000644000175000017500000000066511357170242022456 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by jdoom.rc // #define IDI_GAME_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/doc/0000755000175000017500000000000011523516204020420 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/doc/LICENSE0000644000175000017500000003545111357170242021440 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/0000755000175000017500000000000011523516204020564 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/conhelp.txt0000644000175000017500000004664611357170242023000 0ustar keeskees# # CONSOLE COMMANDS - JDOOM SPECFIC # [beginchat] desc = Begin chat mode. [chatcancel] desc = Exit chat mode without sending the message. [chatcomplete] desc = Send the chat message and exit chat mode. [chatdelete] desc = Delete a character from the chat buffer. [chatsendmacro] desc = Send a chat macro. [cheat] desc = Issue a cheat code using the original DOOM cheats. inf = Params: cheat (cheat)\nFor example, 'cheat idclev25'. [conbg] desc = Console background setup. inf = Params: conbg (materialname) [coord] desc = Print the coordinates of the consoleplayer. [doomfont] desc = Use the Doom font in the console. [endcycle] desc = End map rotation. [endgame] desc = End the game. [leavemap] desc = Leave the current map. [god] desc = God mode (cheat). [give] desc = Gives you weapons, ammo, power-ups, etc. [helpscreen] desc = Show the Help screens. [kill] desc = Kill all the monsters on the map. [loadgame] desc = Open the load game menu. [lockmode] desc = Set camera viewlock mode. inf = Params: lockmode (0-1). [listmaps] desc = List all loaded maps. [makecam] desc = Toggle camera mode. inf = Params: makecam (playernum)\nFor example, 'makecam 1'. [makelocp] desc = Make local player. inf = Params: makelocp (playernum)\nFor example, 'makelocp 1'. [menu] desc = Open/Close the menu. [menuback] desc = Return to the previous menu page. [menudown] desc = Move the menu cursor down. [menuleft] desc = Move the menu cursor left. [menuright] desc = Move the menu cursor right. [menuselect] desc = Select/Accept the current menu item. [menuup] desc = Move the menu cursor up. [message] desc = Show a local game message. inf = Params: message (msg)\nFor example, 'message "this is a message"'. [messagecancel] desc = Respond - CANCEL to the message promt. [messageno] desc = Respond - NO to the message promt. [messageyes] desc = Respond - YES to the message promt. [moveceil] desc = Move a sector's ceiling plane. [movefloor] desc = Move a sector's floor plane. [movesec] desc = Move a sector's both planes. [noclip] desc = No movement clipping aka, walk through walls (cheat). [notarget] desc = Enemies will not target the player (cheat). [pause] desc = Pause the game. [quickload] desc = Load the quicksaved game. [quicksave] desc = Quicksave the game. [quit] desc = Quit the game and return to the OS. [reveal] desc = Map cheat. inf = Params: reveal (0-4)\nModes:\n 0=nothing\n 1=show unseen\n 2=full map\n 3=map+things\n 4=show subsectors [savegame] desc = Open the save game menu. [sbsize] desc = Status bar size adjustment. inf = Params: sbsize (size)\nFor example, 'sbsize +'.\nSize can be: +, -, (num). [screenshot] desc = Takes a screenshot. Saved to DOOMnn.TGA. [setcolor] desc = Set player color. inf = Params: setcolor (playernum)\nFor example, 'setcolor 4'. [setclass] desc = Set player class. [setlock] desc = Set camera viewlock. [setmap] desc = Set map. inf = Params: setmap (episode) (map)\nFor example, 'setmap 1 7'. [soundmenu] desc = Open the sound settings menu. [spawnmobj] desc = Spawn a new mobj. [spy] desc = Spy mode: cycle player views in co-op. [startcycle] desc = Begin map rotation. [startinf] desc = Start an InFine script. inf = Params: startinf (script-id)\nFor example, 'startinf coolscript'. [stopinf] desc = Stop the currently playing interlude/finale. [suicide] desc = Kill yourself. What did you think? [togglegamma] desc = Cycle gamma correction levels. [togglemsgs] desc = Messages on/off. [viewsize] desc = View size adjustment. inf = Params: viewsize (size)\nFor example, 'viewsize 10'.\nSize can be: +, -, (num). [warp] desc = Warp to another map. [zoommax] desc = Zoom out to the max in the automap. # # CONSOLE VARIABLES - JDOOM SPECIFIC # [server-game-mapcycle] desc = Map rotation sequence. [server-game-mapcycle-noexit] desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). [menu-scale] desc = Scaling for menus. [menu-flash-r] desc = Menu selection flash color, red component. [menu-flash-g] desc = Menu selection flash color, green component. [menu-flash-b] desc = Menu selection flash color, blue component. [menu-flash-speed] desc = Menu selection flash speed. [menu-turningskull] desc = 1=Menu skull turns at slider items. [menu-effect] desc = 0=Disable menu effects. 1=type-in. [menu-color-r] desc = Menu color red component. [menu-color-g] desc = Menu color green component. [menu-color-b] desc = Menu color blue component. [menu-colorb-r] desc = Menu color B red component. [menu-colorb-g] desc = Menu color B green component. [menu-colorb-b] desc = Menu color B blue component. [menu-glitter] desc = Strength of type-in glitter. [menu-fog] desc = Menu fog mode: 0=off, 1=shimmer, 2=black smoke, 3=blue vertical, 4=grey smoke, 5=dimmed. [menu-hotkeys] desc = 1=Enable hotkey navigation in the menu. [menu-shadow] desc = Menu text shadow darkness. [menu-patch-replacement] desc = Patch Replacement strings. 1=Enable external, 2=Enable built-in. [menu-slam] desc = 1=Slam the menu when opening. [menu-quick-ask] desc = 1=Ask me to confirm when quick saving/loading. [xg-dev] desc = 1=Print XG debug messages. [view-cross-type] desc = The current crosshair. [view-cross-size] desc = Crosshair size: 1=Normal. [view-cross-vitality] desc = Color the crosshair according to how near you are to death. [view-cross-r] desc = Crosshair color red component. [view-cross-g] desc = Crosshair color green component. [view-cross-b] desc = Crosshair color blue component. [view-cross-a] desc = Crosshair color alpha component. [view-filter-strength] desc = Strength of view filter. [msg-show] desc = 1=Show messages. [msg-echo] desc = 1=Echo all messages to the console. [msg-count] desc = Number of HUD messages displayed at the same time. [msg-uptime] desc = Number of seconds to keep HUD messages on screen. [msg-scale] desc = Scaling factor for HUD messages. [msg-align] desc = Alignment of HUD messages. 0 = left, 1 = center, 2 = right. [msg-color-r] desc = Color of HUD messages red component. [msg-color-g] desc = Color of HUD messages green component. [msg-color-b] desc = Color of HUD messages blue component. [msg-blink] desc = HUD messages blink for this number of tics when printed. [game-state] desc = Current game state. [game-state-map] desc = 1=Currently playing a map. [game-paused] desc = 1=Game paused. [game-skill] desc = Current skill level. [map-id] desc = Current map id. [map-name] desc = Current map name. [map-episode] desc = Current episode. [map-mission] desc = Current mission. [game-music] desc = Currently playing music (id). [map-music] desc = Music (id) for current map. [game-stats-kills] desc = Current number of kills. [game-stats-items] desc = Current number of items. [game-stats-secrets] desc = Current number of discovered secrets. [player-health] desc = Current health ammount. [player-armor] desc = Current armor ammount. [player-weapon-current] desc = Current weapon (id) [player-ammo-bullets] desc = Current number of bullets. [player-ammo-shells] desc = Current number of shells. [player-ammo-cells] desc = Current number of cells. [player-ammo-missiles] desc = Current number of missiles. [player-weapon-fist] desc = 1= Player has fist. [player-weapon-pistol] desc = 1= Player has pistol. [player-weapon-shotgun] desc = 1= Player has shotgun. [player-weapon-chaingun] desc = 1= Player has chaingun. [player-weapon-mlauncher] desc = 1= Player has missile launcher. [player-weapon-plasmarifle] desc = 1= Player has plasma rifle. [player-weapon-bfg] desc = 1= Player has BFG. [player-weapon-chainsaw] desc = 1= Player has chainsaw. [player-weapon-sshotgun] desc = 1= Player has super shotgun. [player-key-blue] desc = 1= Player has blue keycard. [player-key-yellow] desc = 1= Player has yellow keycard. [player-key-red] desc = 1= Player has red keycard. [player-key-blueskull] desc = 1= Player has blue skullkey. [player-key-yellowskull] desc = 1= Player has yellow skullkey. [player-key-redskull] desc = 1= Player has red skullkey. [chat-beep] desc = 1= Play a beep sound when a new chat message arrives. [chat-macro0] desc = Chat macro 1. [chat-macro1] desc = Chat macro 2. [chat-macro2] desc = Chat macro 3. [chat-macro3] desc = Chat macro 4. [chat-macro4] desc = Chat macro 5. [chat-macro5] desc = Chat macro 6. [chat-macro6] desc = Chat macro 7. [chat-macro7] desc = Chat macro 8. [chat-macro8] desc = Chat macro 9. [chat-macro9] desc = Chat macro 10. [map-alpha-lines] desc = Alpha level of automap lines. [map-babykeys] desc = 1=Show keys in automap (easy skill mode only). [map-background-r] desc = Automap background color, red component. [map-background-g] desc = Automap background color, green component. [map-background-b] desc = Automap background color, blue component. [map-cheat-counter] desc = 6-bit bitfield. Show kills, items and secret counters in automap. [map-cheat-counter-scale] desc = Size factor for the counters in the automap. [map-customcolors] desc = Custom automap coloring 0=Never, 1=Auto (enabled if unchanged), 2=Always. [map-door-colors] desc = 1=Show door colors in automap. [map-door-glow] desc = Door glow thickness in the automap (with map-door-colors). [map-huddisplay] desc = 0=No HUD when in the automap 1=Current HUD display shown when in the automap 2=Always show Status Bar when in the automap [map-mobj-r] desc = Automap mobjs, red component. [map-mobj-g] desc = Automap mobjs, green component. [map-mobj-b] desc = Automap mobjs, blue component. [map-opacity] desc = Opacity of the automap. [map-open-timer] desc = Time taken to open/close the automap, in seconds. [map-pan-speed] desc = Pan speed multiplier in the automap. [map-pan-resetonopen] desc = 1= Reset automap pan location when opening the automap. [map-rotate] desc = 1=Automap turns with player, up=forward. [map-wall-r] desc = Automap walls, red component. [map-wall-g] desc = Automap walls, green component. [map-wall-b] desc = Automap walls, blue component. [map-wall-ceilingchange-r] desc = Automap ceiling height difference lines, red component. [map-wall-ceilingchange-g] desc = Automap ceiling height difference lines, green component. [map-wall-ceilingchange-b] desc = Automap ceiling height difference lines, blue component. [map-wall-floorchange-r] desc = Automap floor height difference lines, red component. [map-wall-floorchange-g] desc = Automap floor height difference lines, green component. [map-wall-floorchange-b] desc = Automap floor height difference lines, blue component. [map-wall-unseen-r] desc = Automap unseen areas, red component. [map-wall-unseen-g] desc = Automap unseen areas, green component. [map-wall-unseen-b] desc = Automap unseen areas, blue component. [map-zoom-speed] desc = Zoom in/out speed multiplier in the automap. [input-mouse-x-sensi] desc = Mouse X axis sensitivity. [input-mouse-y-sensi] desc = Mouse Y axis sensitivity. [input-joy-x] desc = X axis control: 0=None, 1=Move, 2=Turn, 3=Strafe, 4=Look. [input-joy-y] desc = Y axis control. [input-joy-z] desc = Z axis control. [input-joy-rx] desc = X rotational axis control. [input-joy-ry] desc = Y rotational axis control. [input-joy-rz] desc = Z rotational axis control. [input-joy-slider1] desc = First slider control. [input-joy-slider2] desc = Second slider control. [ctl-aim-noauto] desc = 1=Autoaiming disabled. [ctl-turn-speed] desc = The speed of turning left/right. [ctl-run] desc = 1=Always run. [ctl-use-dclick] desc = 1=Doubleclick forward/strafe equals use key. [ctl-look-speed] desc = The speed of looking up/down. [ctl-look-spring] desc = 1=Lookspring active. [ctl-look-mouse] desc = 1=Mouse look active. [ctl-look-mouse-inverse] desc = 1=Inverse mouse look Y axis. [ctl-look-pov] desc = 1=Look around using the POV hat. [ctl-look-joy] desc = 1=Joystick look active. [ctl-look-joy-inverse] desc = 1=Inverse joystick look Y axis. [ctl-look-joy-delta] desc = 1=Joystick values => look angle delta. [hud-scale] desc = Scaling for HUD info. [hud-status-size] desc = Status bar size (1-20). [hud-status-weaponslots-ownedfix] desc = 1= Fix original DOOM behavior when drawing the statusbar owned weapon display. [hud-color-r] desc = HUD info color red component. [hud-color-g] desc = HUD info color green component. [hud-color-b] desc = HUD info color alpha component. [hud-color-a] desc = HUD info alpha value. [hud-icon-alpha] desc = HUD icon alpha value. [hud-status-alpha] desc = Status bar Alpha level. [hud-status-icon-a] desc = Status bar icons & counters Alpha level. [hud-face] desc = 1=Show Doom guy's face in HUD. [hud-health] desc = 1=Show health in HUD. [hud-armor] desc = 1=Show armor in HUD. [hud-ammo] desc = 1=Show ammo in HUD. [hud-keys] desc = 1=Show keys in HUD. [hud-keys-combine] desc = 1=Combine the display of keys of the same color in HUD. [hud-frags] desc = 1=Show deathmatch frags in HUD. [hud-frags-all] desc = Debug: HUD shows all frags of all players. [hud-timer] desc = Number of seconds before the hud auto-hides. [hud-unhide-damage] desc = 1=Unhide the HUD when player receives damaged. [hud-unhide-pickup-health] desc = 1=Unhide the HUD when player collects a health item. [hud-unhide-pickup-armor] desc = 1=Unhide the HUD when player collects an armor item. [hud-unhide-pickup-powerup] desc = 1=Unhide the HUD when player collects a powerup or item of equipment. [hud-unhide-pickup-weapon] desc = 1=Unhide the HUD when player collects a weapon. [hud-unhide-pickup-ammo] desc = 1=Unhide the HUD when player collects an ammo item. [hud-unhide-pickup-key] desc = 1=Unhide the HUD when player collects a key. [menu-quitsound] desc = 1=Play a sound when quitting the game. [con-zoom] desc = Zoom factor for the console background. [view-size] desc = View window size (3-13). [hud-title] desc = 1=Show map title and author in the beginning. [hud-title-author-noiwad] desc = 1=Do not show map author if it is a map from an IWAD. [view-bob-height] desc = Scale for viewheight bobbing. [view-bob-weapon] desc = Scale for player weapon bobbing. [view-bob-weapon-switch-lower] desc = HUD weapon lowered during weapon switching. [server-game-announce-secret] desc = 1=Announce the discovery of secret areas. [server-game-skill] desc = Skill level in multiplayer games. [server-game-map] desc = Map to use in multiplayer games. [server-game-episode] desc = Episode to use in multiplayer games. [server-game-deathmatch] desc = Start multiplayers games as deathmatch. [server-game-mod-damage] desc = Enemy (mob) damage modifier, multiplayer (1..100). [server-game-mod-health] desc = Enemy (mob) health modifier, multiplayer (1..20). [server-game-mod-gravity] desc = World gravity modifier, multiplayer (-1..100). -1 = Map default. [server-game-nobfg] desc = 1=Disable BFG9000 in all netgames. [server-game-coop-nothing] desc = 1=Disable all multiplayer objects in co-op games. [server-game-coop-respawn-items] desc = 1=Respawn items in co-op games. [server-game-coop-noweapons] desc = 1=Disable multiplayer weapons during co-op games. [server-game-jump] desc = 1=Allow jumping in multiplayer games. [server-game-bfg-freeaim] desc = Allow free-aim with BFG in deathmatch. [server-game-nomonsters] desc = 1=No monsters. [server-game-respawn] desc = 1= -respawn was used. [server-game-respawn-monsters-nightmare] desc = 1=Monster respawning in Nightmare difficulty enabled. [server-game-radiusattack-nomaxz] desc = 1=ALL radius attacks are infinitely tall. [server-game-monster-meleeattack-nomaxz] desc = 1=Monster melee attacks are infinitely tall. [server-game-coop-nodamage] desc = 1=Disable player-player damage in co-op games. [server-game-noteamdamage] desc = 1=Disable team damage (player color = team). [server-game-deathmatch-killmsg] desc = 1=Announce frags in deathmatch. [player-color] desc = Player color: 0=green, 1=gray, 2=brown, 3=red. [player-eyeheight] desc = Player eye height. The original is 41. [player-move-speed] desc = Player movement speed modifier. [player-jump] desc = 1=Allow jumping. [player-jump-power] desc = Jump power (for all clients if this is the server). [player-air-movement] desc = Player movement speed while airborne. [player-autoswitch] desc = Change weapon automatically when picking one up. 1=If better 2=Always [player-autoswitch-notfiring] desc = 1=Disable automatic weapon switch if firing when picking one up. [player-autoswitch-ammo] desc = Change weapon automatically when picking up ammo. 1=If better 2=Always [player-autoswitch-berserk] desc = Change to fist automatically when picking up berserk pack [player-weapon-order0] desc = Weapon change order, slot 0. [player-weapon-order1] desc = Weapon change order, slot 1. [player-weapon-order2] desc = Weapon change order, slot 2. [player-weapon-order3] desc = Weapon change order, slot 3. [player-weapon-order4] desc = Weapon change order, slot 4. [player-weapon-order5] desc = Weapon change order, slot 5. [player-weapon-order6] desc = Weapon change order, slot 6. [player-weapon-order7] desc = Weapon change order, slot 7. [player-weapon-order8] desc = Weapon change order, slot 8. [player-weapon-nextmode] desc = 1=Use custom weapon order with Next/Previous weapon. [player-camera-noclip] desc = 1=Camera players have no movement clipping. [player-death-lookup] desc = 1=Look up when killed [game-raiseghosts] desc = 1=Archviles raise ghosts from squished corpses (disables DOOM bug fix). [game-maxskulls] desc = 1=Pain Elementals can't spawn Lost Souls if more than twenty exist (original behaviour). [game-skullsinwalls] desc = 1=Pain Elementals can spawn Lost Souls inside walls (disables DOOM bug fix). [game-anybossdeath666] desc = 1=The death of ANY boss monster triggers a 666 special (on applicable maps). [game-monsters-stuckindoors] desc = 1=Monsters can get stuck in doortracks (disables DOOM bug fix). [game-objects-hangoverledges] desc = 1=Only some objects can hang over tall ledges (enables DOOM bug fix). [game-objects-clipping] desc = 1=Use EXACTLY DOOM's clipping code (disables DOOM bug fix). [game-zombiescanexit] desc = 1=Zombie players can exit maps (disables DOOM bug fix). [hud-face-ouchfix] desc = 1=Fix HUD OUCH face (enables DOOM bug fix). [game-player-wallrun-northonly] desc = 1=Players can only wallrun North (disables DOOM bug fix). [game-objects-falloff] desc = 1=Objects fall under their own weight (enables DOOM bug fix). [game-zclip] desc = 1=Allow mobjs to move under/over each other (enables DOOM bug fix). [game-corpse-sliding] desc = 1=Corpses slide down stairs and ledges (enables enhanced BOOM behaviour). [game-fastmonsters] desc = 1=Fast monsters in non-demo single player. [game-corpse-time] desc = Corpse vanish time in seconds, 0=disabled. [rend-dev-freeze-map] desc = 1=Stop updating the automap rendering lists. deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/0000755000175000017500000000000011357170242021727 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb040.lmp0000644000175000017500000000003411357170242023772 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb055.lmp0000644000175000017500000000027411357170242024006 0ustar keeskees 4=FOXaj{jjjjjjjjYcjjjjVajjjjR_jjjjajjjj_jj jjajjjjjjjjjj jjR[[[_]cccajj jjWWWVWV[cecjj jj[[]_aaeecjj jjjjjjjjjjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb048.lmp0000644000175000017500000000034311357170242024005 0ustar keeskees 4AParjjjjjjjjjj jj[[[[[[[_jj jjRTVVTTTVVejj jjPV[[[]]YRcjj jj_jjjjjjR_jjjj_jjjjT_jj jjajjjjjjW_jj jjV[[[_]c__cjj jjWWWVWV[__jj jj_[]]]]_ejjjjjjjjjjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb032.lmp0000644000175000017500000000004611357170242023776 0ustar keeskees !"#$%deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb041.lmp0000644000175000017500000000003411357170242023773 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb042.lmp0000644000175000017500000000003411357170242023774 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb076.lmp0000644000175000017500000000030211357170242024001 0ustar keeskees 4BRbs iiiiiiiiiii iiacbbba__iii iiU_ab\\XX\ii iiQXaa_\_\_bii ii[bbba_bb_bii iiiiiiiii_Q[iiiiR_iiiiU_iiiiR\iiiiX_iiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb037.lmp0000644000175000017500000000040711357170242024004 0ustar keeskees <J[mjjjj jjjjjjjYcjjjjP[jjjjVajjjjPYWjjjjR_jjjjW]]]jjjjjjjjW]aejjjjWa]ejjjjWgfgjjjjW_agjjjjW__ejj jjjjjjWYYejjjjYcjjjjRR]jjjjVajjjjT]jjjjR_jjjjjjj jjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb089.lmp0000644000175000017500000000040611357170242024012 0ustar keeskees HPYcnziiiiiiiUbiiiiU_aiiiiPW[aiiiiPQUXaii iiRRQQ\iiiiii iiRW[[_abbii iiPXXXX\aii iiPXXXWW_ii iiRWXW[XX_ii iiQWUX\iiiiiiiiQWXX_iiiiQUW_iiiiPW_iiiiQ_iiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/sndcurve.lmp0000644000175000017500000000310011357170242024264 0ustar keeskees|{zyxxwwvuuuttssrrrqqqpppooonnnnmmmllllkkkkjjjjjiiiihhhhhgggggfffffeeeeedddddccccccbbbbbbaaaaaa``````_______^^^^^^]]]]]]]\\\\\\\[[[[[[[ZZZZZZZZYYYYYYYXXXXXXXXWWWWWWWWVVVVVVVVUUUUUUUUUTTTTTTTTTSSSSSSSSRRRRRRRRRQQQQQQQQQQPPPPPPPPPOOOOOOOOOONNNNNNNNNNMMMMMMMMMMLLLLLLLLLLKKKKKKKKKKJJJJJJJJJJJIIIIIIIIIIIHHHHHHHHHHHGGGGGGGGGGGFFFFFFFFFFFEEEEEEEEEEEEDDDDDDDDDDDDCCCCCCCCCCCCBBBBBBBBBBBBAAAAAAAAAAAA@@@@@@@@@@@@@?????????????>>>>>>>>>>>>>=============<<<<<<<<<<<<<;;;;;;;;;;;;;;::::::::::::::9999999999999988888888888888777777777777776666666666666665555555555555554444444444444433333333333333332222222222222221111111111111111000000000000000////////////////.................----------------,,,,,,,,,,,,,,,,+++++++++++++++++*****************)))))))))))))))))(((((((((((((((((('''''''''''''''''&&&&&&&&&&&&&&&&&&%%%%%%%%%%%%%%%%%%$$$$$$$$$$$$$$$$$$##################"""""""""""""""""""!!!!!!!!!!!!!!!!!!!  deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb073.lmp0000644000175000017500000000020611357170242024001 0ustar keeskees 1BSdu iiiiiiiiiiiiii ii[_\___\\\aii iiR_aaab_[W_ii iiR\\a__b_\aii ii\baaabba_aii iiiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb052.lmp0000644000175000017500000000032311357170242023776 0ustar keeskees 4AN[hu~iiiiiiiiiiiiRRWXU\iiiiRX\WU_iiiiX_XUQ[iiiiiiii\iiii_ii iiiiii\iiiiii iiQQQQQ[ii iiRWW[\\XXW_ii iiX\_aaaa__fii iiiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb035.lmp0000644000175000017500000000003411357170242023776 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/stcfn032.lmp0000644000175000017500000000003411357170242024000 0ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb038.lmp0000644000175000017500000000003411357170242024001 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb036.lmp0000644000175000017500000000003411357170242023777 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb053.lmp0000644000175000017500000000036111357170242024001 0ustar keeskees 4EVgx jjjjjjjjjjjjjj jjVWYYY]jjV]jj jjRVTVV]jj]jj jjV__T_jj]jj jjVjjR_jj]jj jjYjj_jj_jj jj]jjR_jjV_jj jjRYjjVVY[[ajj jjT]jjWW]aaejjjjW]jjjjYaaajjjjjjjjjjjjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb051.lmp0000644000175000017500000000035111357170242023776 0ustar keeskees 4EVgxiiiiiiiiiiiiiiWXiiiiUbiiiiQ\iiiiWbiiiiQ_iiiiUaii ii\iiiiiiWbii ii\ii\iiWbii iiP\iiRbiiWfii iiR\cf\afcbfii iiU\_aaaccbfii ii[\___aaaiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb045.lmp0000644000175000017500000000012011357170242023773 0ustar keeskees (08@HjjjjjjjVjjjjVjjjjRjjjjPjjjjjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb081.lmp0000644000175000017500000000053211357170242024002 0ustar keeskees LUbq ,<Kiiiiiiiiia\\\iii iibQUUUUQbii iiPRWWURQ[ii ii_WW\\\XRQ_ii iiRWbiiiiWW_iiiiP\iiiiP\iiiiP\iiiiP[iiiiPbiiiiP_iiiiPbiiiiibRciiiiPaiiiibaUaii iiUXciibaX\bii ii_[[___a_abii ii\\\abba\ii iibWX_bbacaii iiiaaaaiiaiiiiiiii iiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb064.lmp0000644000175000017500000000003411357170242024000 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb065.lmp0000644000175000017500000000042611357170242024006 0ustar keeskees DLVbp iiiiiiii\\iiiiia[W\ii iiia\WQQ[ii iia\WWURaiii iib\XWXaiiiii\X[aiiiii[_aiiiiiiiX\iiU_ii iiQaiiUbiiiiii iiQb__[__aabii iiRWXXXX[[[aii iia[[\[\[XW_ii iica_aa_aabii iiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb059.lmp0000644000175000017500000000003411357170242024004 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb057.lmp0000644000175000017500000000035011357170242024003 0ustar keeskees 4EUfwjjjjjjjjjjjj jjgea]jjjWajj jjage_[ajjVajj jjWec__cjjTajj jjTgjjTcjjTcjj jjRgjj_jjTcjj jjRgjjT]jj_jj jjTaa]]Y[YW_jj jjWccccc_cggjj jjYWWY[]_gjjjjjjjjjjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb054.lmp0000644000175000017500000000035311357170242024003 0ustar keeskees 4AParjjjjjjjjjj jj[YVTTTW[jj jj]WWVWWY]W[jj jjTaaaVWW[T]jj jj_jjT]jj]jj jj]jjT_jj_jj jjR[jjV_jj]jj jjR]jjWWY[T[jj jjT_jj]WTVV]jjjjWajjjj]VW]jjjjjjjjjjjjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb070.lmp0000644000175000017500000000033011357170242023774 0ustar keeskees 8ETdtiiiiiiiiii iiib__\__aii iic\\[X[XXaii iiaa\WUWRQ[ii iiaXWWUU_\\aii iiU_aiP_iiiiiiiiP_iiP\iiiiP_iiXaiiiiP\iiiiiiiiQ\iiii[aiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb083.lmp0000644000175000017500000000050711357170242024006 0ustar keeskees DUhy#6iiiiiiiiiiiiiib__biiii\aii iiXUUUUaiiQaii iiRUURUciiP_ii iiQ\\\[aiiPaii iiQbiiRciiRcii iiQciiQaiiQaii iiQbiiQ_iiRbii iiUaiiQaiiXaii iiXaiiUciiW_ii iiUaiiUccbX_ii ii[fiiX\\\\aii ii_iia\__\ciiiiaciiiibaabiiiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb088.lmp0000644000175000017500000000044211357170242024011 0ustar keeskees @O`siiiii iiiiiiiR\iiiiP[iiiiQQ\iiiiPXWii iiWXXciiW\\\ii ii[W__cf\acaii ii[W_acfcciiii__abcfiiii___a_cii iiW[[__\acii iiWXXX[[W\\\ii iiQQ\aii[PXWiiiiR\aiiii[P[iiii[aiiii[[iiiiiii iiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb046.lmp0000644000175000017500000000011211357170242023775 0ustar keeskees '09BI iiiiiiXbiiiiUaiiiiQ_ii iiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb044.lmp0000644000175000017500000000011511357170242023776 0ustar keeskees '1;DL iiiii_iiQW_iiQ[iiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb075.lmp0000644000175000017500000000047611357170242024014 0ustar keeskees HYj{)7 iiiiiiiiiiiiii iiX[X[_\[\X_ii iiQXRQRRUWW\ii iiPRUPQQQQR\ii iiWUX[U[[XX_ii iiiiiiWiiiiiiiiiQX_iiiiQW[U\ii iiPUUURR\ii iiPUURURQQ[ii iiPXU_iQRRUbiiiiPW\iiiiW\\ciiiiPaiiiiU[aiiii\iiiiWbiiiiii iiXii iiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb060.lmp0000644000175000017500000000003411357170242023774 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb061.lmp0000644000175000017500000000003411357170242023775 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb039.lmp0000644000175000017500000000013411357170242024003 0ustar keeskees ,-.5?IRZ[iiiiiiii_iiiiQW_iiiiQ[iiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb058.lmp0000644000175000017500000000015111357170242024003 0ustar keeskees ):K\jjjjjjjjjjYcjjjjYcjjjjVajjjjVajjjjR_jjjjR_jjjjjjjjjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/m_therm2.lmp0000644000175000017500000000027011357170242024155 0ustar keeskees (:L^p beeelbeeej beeelbeeej beeembeeej beeejbeeej beeelbeeej beeejaeeej beeelaeeej beeelbeeejdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb087.lmp0000644000175000017500000000046411357170242024014 0ustar keeskees HWgx% iiiiiiiiiiii iiX[[[\[XXaii iiQWWW[URWWbii iiW[[[[XRURaii iiiiiiiRQQQciiiiQURR\iiiiQ\[\ciiiiQ[[[ciiiiQ\[XbiiiiQ[\_biiiiUbbaaii iiiiiiibbaXfii ii_cbaa_\\\cii iiXfcb_\__\fii ii\a____\\_ii iiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb062.lmp0000644000175000017500000000003411357170242023776 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb033.lmp0000644000175000017500000000020611357170242023775 0ustar keeskees 1BSdu iiiiiiiiiiiiii iic]]]]ciiabii iiPRUUU\ii[aii iiQRQRU_iiW_ii iic]]]]ciiabii iiiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb085.lmp0000644000175000017500000000045011357170242024005 0ustar keeskees HUdt iiiiiiiiii ii[abbccbiii iiQbbbbbbbfii iiQbbbaaaa\ii ii_baaa_\X\cii iiiiiiiiiUQaiiiiPaiiiiQbiiiiUfiiiiUcii iiiiiiiiia\_ii ii\a__bbb_[cii iiU_[\aba\Xii iiQW[\aa_\cii iiXX[\__biiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb069.lmp0000644000175000017500000000043611357170242024013 0ustar keeskees @IVet iiiiiiiiia__aiii iic_XXXW[cii ii[WWWXWQ_ii ii_XWWWWURRaii iiUX__WX__W\ii iiXaiiWaiiR_ii iiRbiiUciiQ_ii iiRaiiUbiiQaii iiUciiUciiQ_ii iiUciiQaiiRaii iiR_iiQ_iiUaii ii\bii_bii[aii iiiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb072.lmp0000644000175000017500000000045311357170242024004 0ustar keeskees DUfw  iiiiiiiiiiiiii ii\aaaaa___a iiU_\\\[XWX_ii iiU\\\\[[X[_ii ii[\__\aaa_b iiiiiiXaiiiiiiiiUaiiiiQ_iiiiQ_ii iiiiiiR_iiiiii ii[\\\X___\aii iiQXWWWWUUR\ii iiQWUQQQQQR[ii ii[a__[[[[[aii iiiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb043.lmp0000644000175000017500000000003411357170242023775 0ustar keeskees######deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb067.lmp0000644000175000017500000000043611357170242024011 0ustar keeskees @IVet iiiiiiiiib__biii iib\\\\\\cii iiX__aabbbii iibccccbcccgii ii\cfiiii\bbiiii\ciiiiUbiiiiXciiiiQ\iiiiQ\iiiiUbiiiiQaiiiiQaiiiiQ\iiiiRaiiiiQ_iiiiQaiiiiXaiiiiX_iiiiiiiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb086.lmp0000644000175000017500000000042611357170242024011 0ustar keeskees HPZftiiiiiii[_iiiiiPUX\iii iiPWWWX\iii iiX[WUXUU\iii iiii_\XXWUU_ii iii_XWXXbiiii_QU[biiii_QQUcii iii\RUWR\ii iiii\XWWUUQ[ii iiXXRUUQQ\iii iiQUWWR\iiiiiPUW\iiiiiP\iiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/fontb080.lmp0000644000175000017500000000041011357170242023774 0ustar keeskees @Qbs iiiiiiiiiiiiii ii[aii[_a_abii iiQciiQ[aa\cii iiQ_iiPPRUWbii iiQ_iiPQPRU_ii iiPXiiQ_iiiiiiiiP\iiPXiiiiPXiiPXiiiiP\iiR_iiiiUXURW_iiiiXXRRR[iiiiaWUWRaiiiiaXXaiiiiiiiideng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/mapmask.lmp0000644000175000017500000020000011357170242024062 0ustar keeskees             !  !!! ! !"! ! !!!!!"""#!!"""!! ""!!! !!!"" !!!!! !! "" !"! !  ! ! !!!"! !! """ ! !""!!!"!" !!!!!!!"  "#""!!! ! !! !! !!! ! ! !! !  "!! "!"" !! ! !"!!" """ !  "$&'&&%&'&'&'&&&'&&%&&&'''&((('''''&&'&&&%&(('&%&''&'(&%&'''&%%%&&&&'(%&'&&&%&%&&%%&&&('&''&(((&&'&&&&&(&&'((&&&&'''&'''(&&&%%&'(&&'&'&&&&&&&&&&'&&&'&&&''&&'&''('&&'&%&(''&('&&&&''&&&&'''&&''((&'$"    #%()+,,-,,,+,+,++++++++,*++,+,,-+,,,+++,,,+*,,-,+*+,,,,-+*+-..-+*,++*++,*+,+++,-*,+**+++--,-,+-,,-+,,,+,*,**,-,+++-++,--,+,*,+**++,++,++,,++++++,+,++,,-,+,,+,,-,,,++,-+++-,,+,,++,,+,++,++,,++-+,-,+)(&$#    "%'),./1121110101010//0001//010000/0110//1110/1120/.0/0111//012211000.////./000021/10.000011120000010/1101000/11100020/1110///0/////10010011/000/0110001111101001100///01000200/010011//00101101010001/.,*('$#!    #&&(*-/245777677666755655667755567766567665556765675654655688555666676564445545766676576466667767666665657767766577556676555655556555556775667756665666656566666766754455567665566566566745676667666655665420-+*&&&"  "%&(++-/3579:<<;;<<<;;<::;:;==<=;;;;<<<=<<<;;;;:;<<;;<:;:9;;:;==<<:;;:;<<:;::9<;9:<;;;<<<==;<===<<;;;==<<:;<<<<<<<<<<<:;<<<<;::;;;<;<<:<;;;<<:;;=<:;;<;;;;;:<:;;;;;=<;<::9::;<<;<;:;<<;;;<;<9;<<;<;<;;;;;;<;;:7530/,++($! "&)+-00259;<=?AA@@AAA@@A@???ABBABAAA@AAABAAAA@@@?AAA@@A@@A?BA@@ABBA?@@?@AAA@AA@A@@A@@@@ABBBBAABBBAA@@@BBAAA@AAAAAAAAAACAAAAAAAA@@@@A@AAAAAAAAA?@BBAA@@A@@@BB@A?@@@@@BA@A@@@?AAAA@BA@@AA@AAA@A?@AAAA@A@@BABAA@@?<:866300-)(#   %*.03568;<>ACEFFFGGGGGFFGEEEGHGFGGGFFFEFGFGFGFFFFGGFFFGFGGFHGFFFHHFEFFEGFGGGGGGFFGGFEEFFHHGGDFGHGFFEFFGGFFGFFFEFFFGFGGIHGFFFGGGGEEFFFFFHGGFGFFFGHGGGFFGFFGHHFGFEGGGFGFFFFFFFGFFGFGGEFEEFGFFFFEEFFGGFGFGHGHGFFFEC@=<<86420.)$ $*/3589;>@ACFHJJKLMLKLMKKLJKJLMKKKKJJLKIKLJLKKJJKLKKKLKLKLLKLKKKKMLJJKKJLKLKLLKLKLLKKIIKKLKKKIKLKKKKJKKKLJKLKJJJKKKKJKLMLKKKJLLLMJJJKKLKLMKKLKKKKLLLLKKKJKLLLJKKKKLLKLJKKJKKKLJJKKKJIKIJLMKJKJJJKKKKKKKLLLLLKKJJGDAA@=:9642-("  $).38;>>@CEFHKMOOPQQQQQRQPQPOOQRRRRQPOPPPPQPQPPOPPQPPRRQQQQQQQPPPPRPOPQQOQPQPQQOQPQPOQPPQRQPQQOPQPPPPPQQOQOPQPPONQPPPPOPPPPPPQPPQRQOOPOQQQQPPQPPPPPQQQQPPOPOPPOPQOOQQPQPQPOPPPQPPPPPOPQPOQRPQQQPPQOOPPOQQPQQQPONNLIGFEC@=:872,&! #)/27;60*&!   #'-37;@FIKLNPRUVXZ[]\[\\[[\Z[[\ZY\\[[]]ZZ\[Z[\\\\\\[[[[Z[]\]\\\\[[\[\[[Z]]\[[^]\[[[\[ZZ\\[[\]\\]\\[\[\[[\Z[[[\[\[[[\]\\[\[[[[[\]]]\Z[\[[\\][\]]][[Z[[[[]\\\[YZ\\\]][ZZ[\\\[[[\\[\]\\]\\\][[[[\\\\[[]\[Z[\[[\[]\]\ZXWURPPNMJGD>:5/*%   $(-28<@DJMPRSUXZZ\_`a``aa``a__`a`_aaa`ba``a`_`ba`aaa`````_aabaaaaaa``a``_aaa``cba```a`___```abaaaaa````aaa```aa``aaaabbaabbba``ababa`````baa`abaa``_````baab`_abaaaa___`a`a```aaaaa``aa`ab``````````aa`_`````aaaaa`]\ZWVUSQNKHB?:4.*$   !',16:@DHMPTWXZ\^_`deeddfdeeeddeeedfgfegffeffdefedfeeeddedeeffffffeedefefeeeeefffgedefeeedfffffffefeedecffgeeefffdffefefffegfeffeffffedeeegfeeffeeefefeeefffeeeggffeedeeeedeeeddfffeddeffefeddedddeefdeeeeefedfeedefcb`]\ZXUSPKGC>93-($  %+05:=CIMRVZ\^`bdefjkkiiljjjkljkkkjlmlklkkjkljkkjjlkkkiijjkkkkkkklkkjkkklljjkkllllkjkkklkkllkkkklkljjjihkllkkkllljkjjkjjkljlkkkkjkkllkikkkllkjkljkjlmlkkklkljklmlkkkkjkkkkikkkjikkkkjjjkkjkkijkiijjkljklkkjkkjkjkjkkjheca`^[YUOLHB>83.)"  ")/49>CGMQW[_adfgjlmorpopqqooprqppqqrrspqppopqoqqqoqrppppoorqpppppqpqqppqqqooppqqqqpqrpqqqqrqppppqqrppoooqqppqqqqqoppopoopqppppqpoppqrrpqrpqqqoprqqoqrqqrqqpqqqrrqpoppppppppqpqopqpopoppqpopqooqpppnprqrsrpoppqpopqppomjhfeda^ZTPLFA<83,& $,28=CIMRV\`dfhkmoqsuwvuvvvutuwvvvvvwwxvuvuuuvuwwwuuwuuvwuuwvuvvvvvuvwvuvvvuuuuuuvuuvwuvvvvwvuuvvvvwvvuuvwvuuwwvvuuvvuuutuvvvvvwuuvuvwwvvwvuuvttwwvtuuuvwvuvwvvwvvuuvvvvvvvvvuvuvwvuvuuwwutvvuuvvvutvwvwxwutuuvutvwvvtromljieb^XTPKE@<6/)" !&.4;AHLPVZ`dhkmprsuwz|{yzzz{zzz{{{z{{||{zzz{{{z{{{zy|{z{{||{zz{z{zzzz{|zzzz{zzz{z{z{z{{{{{|{{zz|zz{{|{{z{{{{{{{z{{{{{{{{yyz{{z{{zzzzz{|{z{{zzzzy{|zyzyzz|zz{|zz{z{{{{||{{{{{{zzz{{zz{zz{zyz{zzzz{{yy{{z{{{{z{z{{z{||{ywtqpomigc]WSOID?92+$#*18?FLQU[^cimpruwxz|~~|{wutrnmhb\WRNHB<6.'   &.5ELSZ`glpuz~xsmke^WNHB<3,$%,3:AHOV]cjpuy}xrnhaYRLE?6.&   "*074.% "*3FNW^fow}zskd[RJC81)  %.7@HOXaiqz}umf]TKC:3+" '/7@HOZcks|vog_ULD<3+" '/7@IP[ckt|wpi`XNF<2*" (19AKS]emu~ļypjaYPH=4-$  *2:BLT^fovȿzqjbZQH?6/%  "+3=DNV`gpxü|rjc[RH@8/' #,5?FNWahpzƿ}tlc\TJ?8/' $.8@GOXbiq{~vmd]UKA90' &0:AIQYcls|¹xoe^UMD;2(   (1;BJRZdmu|ûyof^VME=4+# "*3;BKS\dmw~Žyph_XOF?6-%  #+5GOV^goyɿ|skd[TKB90(  %.6>GOX_gozɿ|umd[SJB90(  %.5>FOW_hpz|umd[QIB90(  $.6=ENV_ipy}uldZQIB81) %.5FMU^hpx}umd[RKB90(  %-5>FNV^iqy~umd[SKA91)! $,4=FNU^ipz~tle[SKA92)! $,4HOW`iry}ukcZSJA91) %.6>GNWajry~wlbZRJB90( $-6>FNWaiqz}vlbZRJB90'  $-5>ENW_gqz}vmd[RKB91(  $-5>ENV^gqy¹}tme[SKA92*  $-6=FMV_gpx¹|skd[TKA82*  %.7>FNV_hpx|tke\SKB81*   %.6>GOW^gqy¸}ule\SLA70)  %.6>GOW^gqy¸~wme\ULA70(  $/7>GOW^gqy¸~wmd\ULB81( $.7>GOW^gpx~wmd[TLC:1(  #-7>GOW^hpxvlcZSLB:1)  #-7>FOW^ipyukcZSKA90)  $,6=FOW_ipz~ukc[SKA90(  $+5GPW_how}tlcZRKC91(  $-6>GPW_hpx}ukc[SKB90(  $,4=GOW`iqy}vlc\SKC:0)! $+4=FNV`ipz}uld\TJC:1)! $+4>FMW`hpz}tkd\TJC91)! #-5?FNX_hqz}ukc\SKB91(! #.6?GOX_hrz~uld[TKB:1)" $-7>GNX_gry}ume\SKC92)!  $-7=GMW_gpy}ume\SJB92)   $.6=FMW`goz~umd[TJA92)  %.6>FNX`foz~tlc[TKA81)  $,4>GOW_gqz~tlcZTLA80(  %,4?HOV_gpz~umdZTLA80) %-4?HOV_gpz¹~ume\TLA80) $-4?GOW`hqy~ume]TKB81)  $,5?GOWajrz}umd\SJC91)  #+5?GOW`irz}ume\UKB81*  #,5?GOW`hrz}ule\UKB81) $-5>GNWahpz|tkd\SJB80' %,6>FNXbhoy{tld\RIB90'  $-5>FMWahnx{umd\RJB80(! #-6>GMXahny|vme\RJC91)! $-6>GOXahpy}uke\RJC91)! %-5>GPXaiqx}tkd\SIB91)  &.6?FOX`hqx¸|tlc[SIB:0'  &-7?ENY`hqx¹|skdZRJC90'  %-7>FNY_hqxº|skdZRKC90'  $-7>GNW_hpxº|tlcZSKC91(  $-6>GNV`hoy|tlc[SJC92)  $,5>HOW_gpy~tkd[RJB92)  %,4>HOW`hqy~tld[RJC91(  &-5>HOWahqy~umd[RJC91(  &.6=GOWahpy}ume[RJB81)  %.6=FOY`hpz}tme[SJA81)  $-6=GPX`hq{}sld[TJA91)  $-6=GPW_hqz~slc[TJA90(  %-6>GOW_hqy~tlc[TJA90'  %-6?GOW_hqy~umc[TKB80(  $-5?HPX`ipx¸}vlcZSIB90( $+4=GOW_ipx¹}vmd[SI@80( $,4=FNV_ipx¹}vmd[RI@80' $-5>FNV`hpx}vmd[RJA81' $-5?GOW`hoy}ukd[TKB92( $+4=FOWahpz|ulc\RIB:2(  $+4=FOW`ipz|ukc\RIC:2) $,4=FOW`ipz|ukc[RJC80) $,4=GPW`hpz¸{tlcZSKC8/(  %-5=HPW`ipx¹|umd[SKC:0' &.6>GOW`hox~tld\RJB91( &.6>GOW`ipy~tld\RJB91)  %-5=GOW`iqy~tld\SKB91)  %-5>GNXahoy}uld[SKC91)  %-5?GNXahoz|ulc\TLC90)! %-6?GOXaipy|umd[TLB90)! %-6=GOXaipy|uld[TJA91)! %-5=GNWaipy|ukd\SIA92*! &-4>HPW`irz}vld\SIB:3*! %,5?HQY`ir{}uld\RJC:2)  $,6?GQY`irz}tkd\RKB:2(  #,7>GPX`iry}skd[SKB:1(  $-5>HOY`hqy|tlcZTLC:0( %-5?GOY`hq{}tlc[TLC91( $.5>FOX_hq|~tlcZSKB91( #.6=FNW_hq{~tlcZSKB91) #-6=FMW`hpz~tlcZSKB92)  $,5>GOW_goy~umd\SKB92(! $,5>GPX`gpz}uld\SKB81)! $-5=GPW`hpz|ukd[RJB80(! $-6=GPW`hpy|ukd[QIB90'  #-7>FPX_gqy}tkd\RJA91' $.7>FPX_gqz~umd\RJB91)  $-6=GOW_hqz}tldZSKB91)  %-5=GOW_iqz}uldZSKB91) %-5=GPW_ipz}vmd[SJB91) $-5GNV^ipx~tkcZSKA:2) $-4>GNV`ipx}tkcZSJA90(! %.4=FOW`ipx|ukdZSIA80(! &/5=FOW_hqy|tld[QIA80(  %/5=GPX_hqy}umd[QJB91) %-5=GQY_iry~ume\RKD91) %,4=GQY`iry~ule\TKD90( %,4>GPZaiqy}ume\TLD:0' $,6>GOWajqy|tmdZRJD:0( %,5>GNWajqy}tldZRJC90' %,4>GNWaiqy}tkdZRJC90' %-4>HOV`hqy}ukc[RIB:1' $,4>GOW`hrz}vld[SIA:1' $-5>FOX_iqy}uld\TKB;1' $-5?FOY_iry|ukd\TKB;0( $-5?GOY_hrz|ukd[SJB:0(   $-5?HPX_hqz}vmdZSIB90(! $-5?HPX_gqz}vmcZRJC90(  $,6?GOW_hqyº|uld[RJC90( $,6>GOW`hqx»|tke\RJC90(  %,6=FOWaipx»|tke\RJB91)! &-5FNV`irzȿ}tkd\SHA9/& %/7?GOW`iqy~ukd\SH@80( %.7?FNX`ipx~vld\RHA91) %.6>FNX_how~vle\SIA90) %.5>FOX_gnw~tle\TKA90)  %.6>GPX_how}tld\SKA91)! $-7?HPX_hqzɿ~umd\RIB:0(! %.6>HOW^gqzɿ~umd\RIB90(  %.6>GOV_gqzȿ}umd[RIB80( %,46/&  )0:CIPX`fmuz~wqibZTNF=5-$ '09AFMU\ckqw~{tof_WQLD;3,$  %.6>DJRY`ims{~xpkd\UOIA91+" $,4:@GOV]ejqw~ztmf`XQKE>6.(  "*28>EMT[biouz|wqkc]VOHA<4+&  (.5;AIPW]dlrv{|xsmha[TME>82)" $*18?EMTY_gmqv|~xsojd^XPIB;3.&    '.5GNTZ`ehmtx{~~|yvpje`[WQIB;5.(  !(.5;CKQUZ`ciotvy{~}{ywuqlea[VRLF?83+% $+28@GMPTZ_eknpsuxy{~~zxwusokfa]VQNHB<50(!  !'/582,$ $,28>DHLQV[acehjknpsuvvvvttvwutuuvwvvvvuvwvwwvuwvvvwvvuwvuvvvvvvvvuuvwvvvvwvvwwuvuuvvvvvuwxvwvwvvvwvwvwwwutvwwvvuuvvvvvwvvwuuvvxvvvuvvvvuvuuxwvvvvvuvwvwvwvvwwwxvvvwuuuvwwwvuuuvvvvwxuuwvwwvutuvwwvuuuvtwwwvuvuuuuwvutsqnligeb]YSNJD@;5.(!  "*05:?DHLQW\_acegilnopqrrpprsqpqqrrqqqrqrrqrqqqrrqrsrqrqqqrrssrqqqpqqqqqqqrqqqrqqqsrrrqrqrrrrrrqrrrrrqqrrpprsrrqpqrrrqqrqqqppqqsqqqqqqrqqqqqsrpqqqppqrrsqrqrssssrrqrrpprrqrqqqqrsqqrrpprrrrqpqpqrrrqqqqprqqqpqqqqprrponligec`]ZVOJFB<82+$  ',0684.'   "',17:4.*% $)-05<@DGKMNPRRUXZ\]\[[Z\[Z[[\\ZZ\[[[[\]\[Z[[[[[[[[\Z[Z[Z[[[ZZ[Z[\[[Y[]][[[\\\[Z[\\[Z[[[[\\[Z[[\ZZYZ[\[[[[\[Z[\Z[[[\]Z[\[ZZ[\\\[[[ZZ\\[[\\[\\[\[[\\\\\\\ZZZZZ[\[ZZ[[[ZZZ[[\\[[ZZ\\Z[][Z\]\\[[\[[\\[[[[[ZZZ[\Z[\[[\ZWUSQNMKHEA=84/*%   $)-28<@BFHIKMNPSUVXXWVVWVUVWWWUVWWVVVVWWWVVWUVVVUWWVVVUTVVVVVVVVWVVUWYXVVUVWVUVWVWVUWVVVWWVVVWVVUUVVVVVWWXWUWWVWVVWXVVWXVUVWWXVUWUTVVVWWWWWWWWVVVWXXWWVWWWVUVWVVUVVVVUVWVWVUUUUWWUVXVVWXVVXWXWWWWVVVWWUVVVWUUWXVWVSQNLIHFD@=840+'! $)-37;=BBCEHIKNPQRQQQQRQPQQQQPRRRQQQOPRSRQQPQQPPRRQQRPOQQRRQQQQQQQPRRRQQPPQQPQRQQPPPQQQRRQQQRQPOPRQRRRRQQRPPQRRQQRSQQRRQPQQRRQQSPPQQQPRRQQRPQQQQQRRQPPRRRRPQQQQPQRPQPQSQQQQPPPQQPQSQQQRQQSRRRRRRQQRRRQPQQRPPRSQQOMLIGECB@=:4/+'#   %)/369<<=>BDEHKLLKKKKLKLKKKKLLLLKLKKLLMMLKLLLJKLLKKLLJKLLMKKMKKKKLLLLLMKJKMKLLMKJLJKKKLLMKMNMKIJLLLLLKKKLKJKMLLLLMKKLKKLKKLKKMMJLMLKJLLKKLJJMKLKLLKJKLLLLLKKKMLLLJKKKMKKLMLJLKKLMMKKKLMMMLKLLNMLLLLLLJKMLKKLLLKIGFDA@><;860+'#  !%+/235789<@@AEFGGFFFGFFEFFFFGFFEFGGHEGGFFFFFFFEEFFGFFFFEFEEGEFEEFGGFFGEEFGGHGGFFFFGGFGGGFGHIGEDFFEEEDGFFFFGHGHHFFEFGEEFFGFEFGGEFGFFFEGFEEEDGGGGGFFFFGFEFFFEFGFFEFFGEFFEFHHFFFFFGGFFEEGGFEEEFHGFFEEGFFGGFGGGEFDEB@>;985420-(#  "'*,.01357:;=@AABA@ABA@@BBAAB@@@ABBBABAAAAAAAAA@ABBABAA@A@AA@BA@ABBAAB@AABBBBAAAAABBBBABAABCBA@@@A@@?BA@ABBCBCBABAAB@@ABB@@AAA@@AAAAABAAA@?ABBBBAAABBA@@AA@AA@AAABBAAA@ABBA@AAA@AAAAABABAAA@BBAA@ABAABAABBB???@=;96420.,*)%   "$')+-022467:<<=<<=<<<<<=<=<;<<<<<=;<;<=====<=<===<=<<=<<=;<==<==<=<===<;==<;<===>>=<=>=;<>==<=<<<<=>=<<<>><===>==<<<<=<<<<<<;=<<<<=<==<;;;<====<<=<===<;;<<;<==>>=<===<=<=<;;;;;<==>=<===<==<<<==<==<<=<<;:;;8632.,**)'$   ##%(+-,.014667667666667687677766756667788767777877668777667878868688866776567778976787668788866667887668878778776676766766677866776787666677887777888656766687887788867786566667788867876777667767777766656530.-)'$$#"   "$''(*+.01100100000002312221110/11121100120232101222110012111102331122000112121011010112311011011201112222222112011120/01220/201011111011123212222001212112112222312211011112221110121112110212022011201/.+(($"  !"$&&)+,,++,+++++++,,+,,,+++**+-,,++*+,-+-.-+++,,,,,+++,+*+++,--,,-,+++,--,,++,,*+**+,,+,++++*+,+++,,,,---,,,,*++,-+*++-,**,+,++++,,+,+*,--,-,,,*+,,+,++,+,,-+,-,-,+,,--,,,,,++,++,+++,,++,--+,,+,,,++*(%""   !""&'(('((('''&'('&&'('&&&%%&'('&%&'''''((''&''&'''''&&%&'''(''&''((''((&&'(('&&&&'&&&'&&&'%&'&&&('''('('&'(&'&&&'''&((%%'&&&'&''&'('&('''((''&'((&&&&''&''&'((((&''(('('&'%%'&&&&&'((&''(('('''&&''&#   !"##"##$"""!"""!!"#"!! !! !""" !"!""""#""!!!!""""" ! !"""#! !"##""""!!"#""!!!!"!!!"!! " "" !#"!!#!""!!#!" "!"#"!#" "!!!"!"" """"#!!!##""!""#!!!!"" "!!!"###!!"##""" ! !!!!!!"#"!"!"""#""" !"!                                      deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/data/lumps/menufog.lmp0000644000175000017500000001000011357170242024070 0ustar keeskees99!,,EE999JRjjJ9EE^^JE9,!,!+)ajrrrjJRE9,!!!!,,!!,E,!!!!!99J^j^JJ9Jj^JE,,,,!%Jcsrr^^J9,!!,!!!,99EJRE!!9EJjjjRR^rRJD)()!%8Mi~rRJE!,E!!9Jj^9!9J^r^I3!!!%-;`r^RE!!9JJ!JrJ!!!,JjrrjD4! 1>]j^J9!E^^99jrjE9,9,,9ERrjP4#!'#=Jqrjrj^J9!JrE,JJj^^RJRJJEJ^rZ= 3LLk}rjrr^^E!,JJ!!,,JRj^jjRREJj`8%%DuȯŨrrjJ9!,!9JJ999!!!9J^jjrjRR^jiP0 +Yĵj^E99E^rRJRJ9!!EJRrjj^^^j͹~`P3/^}j^RR^rjRJ^RJ,!,,,EJ^^^^j^rvT,>enifeif]T^rj^omo^JRR^RE,REEEJRR^jrr{PayeRIENQE;Dir^Re{qQEER^r^Rj^RJJRJjraE=>HJE9>Nw}rJJEZuZE9E^jRRR^jXD@P``UB>PZ\j^^J,!,YrmN999J^rj^RRRjurJ>HgwYIDIDEE9!!>n~`>,,9EJ^RjRRRJJRrȫrrrr^NZP54Hw˗iFA>8!!)NnN3!!,99EE9EE9999ER{˵^R^^^L484%'RkLE8,!)bfb@,!,!,,,,!!!!!,,9Jmȳj^JRRc3,9EE,9^wr{fcirU/@N`VU]mZ%$@gq]5,9EE99!!Rrwwecoz>)!EaRVYms;09emN3/49E9JJE,!!9j}~aD!9QicVkwgcfifH7;f{{reQ>)9ALU^ZYRJE9J{şuRJJ^gn`{^LEEA@P^^YTPUr~j^^jyqmR@58/7AFZw̷{VMacr7 $'0=EFELV`nriky˼jjjrrjj^RQA4,1=879LnϣjPIby<$(,3'/Qc]MBJuR7Fc}k\QJII>;qw^F@7DFHUgLABHfrr^RE;/!(Mm{wmTNi`>';joTB;DEFcsZNL\\wzwj^^jrrrj^Q>0 )MfgU7(=`fa@0-BnnjVF43Jsk]^X\JQbjJ9,,,J^rrrj^L5'#580)'4DJ@408ArjE($1^yzfXaJ99EJrrrjE,!Jjrj]P,#>HMLH98<>7Pnz{}{rM(-F^QQJE,,9E^r^J9!!EjU' 7YwniQB589)-DY`jooT((99JE9,,9^rRE!!,Js>#!4IjjJ9!99'!>I\afQ+3EJRJ,,,Jr^E,9,,,9JrjjoE-(+YsjRE99Rrj^RRJRR99EjjJD4@@L]^^J99JV5(4HJPUfzjRE9E^rjRRR^JRr^jRE!!,Rr^JJEEJJRrrjRJ^gN0P\i}jJ99Jj^RRJR^RJRrrRR9EE!!!,Jj^^JJJJJjrrg, 5Ii{mYJE^rjRJJRRJ9JR^^^R9,!!,!!!,JrrjRREJ^F-IzoaX^jjREJJRE!,9EE,!!,,!!!E^rj^rjRJJ^rͼs3Iٱkjnuor^RR^jR!!!,9,!!,9E,,J^r^JJ^^̪`;#YjY^kj^jjE,EE,,!!!EjjJJJRj͹g<Zͧz`R^wrrr^,EEE,,!,,!!RrRJEE^rU#PÜs\Ve~^^jjE!,EEE,9999!!ErJJEEERrU)Akk}rJJRj^E!!,JJE99EJ9,!^jJJEE9J^jrjoveM- AjE,9Rjj^J,!!^^^RJRRE!9JJRJJJJ^jj^c^IA7+9R^J!!,9E999!,jrjjrR,!!9JRJRR^rjrjLHADNLUbjJ,9RJ,!E^jrR!,ERRRRRjrjM5H`eVNXanrzsrqyjJ,9JJ9!,JJRj^,,J^^JEJ^jjjI7TiaMIJNIJUPM>yyyyyyyxxxxxxxxwwwwwwwwwvvBBBAAA@@@@@?????>>yyyyyxxxxxxwwwwwwwwwwwwvvvvBBBAA@??>>>yyyxxxxwwwwwwwwwwwwwwvvvvvvvBA>yxxwwwwwwwwwwwwwwwwwvvvvvvvvvvwwwwwwwwwwwwwwwwwwvvvvvvvvvvvuuwwwwwwwwwwwwwwwwwvvvvvvvvvvuuuuuwwwwwwwwwwwwwwwvvvvvvvvvvuuuuuuuuwwwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuttwwwwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttwwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttwwwwwwwwvvvvvvvuuuuuuuuuuuuttttttttttwwwwwwvvvvvvvuuuuuuuuuuuuttttttttttttwwwwwvvvvvvuuuuuuuuuuuuttttttttttttttwwwvvvvvvuuuuuuuuuuuutttttttttttttttttwwvvvvvuuuuuuuuuuuutttttttttttttttttttvvvvvuuuuuuuuuuuutttttttttttttttttsssssvvvuuuuuuuuuuuutttttttttttttttssssssssrvuuuuuuuuuuuutttttttttttttssssssssssrrruuuuuuuuuuutttttttttttssssssssssssrrrrrruuuuuuuuutttttttttssssssssssssssrrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrruuutttssssssssssssssssssssrrrrrrrrrrrrqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppnnnnnmm$$#######!!!!!! nnnnnmmmm$$$$######!!!!!! nnnnnmmmmm$$$$######!!!!!! nnnnnmmmmmm&&$$$$$####""!!!!! nnnnnmmmmmml &&&$$$$$###"""!!!!! nnnnnmmmmmmll &&&$$$$$#"""""!!!! nnnnnmmmmmmlll &$$$$$""""""!!!! nnnnnmmmmmmllll $$$$"""""""!!! nnnnnmmmmmmllllk $$"""""""!!! nnnnnmmmmmmllllkk """"""""!! nnnnnmmmmmmllllkkk """""""!! nnnnnmmmmmmllllkkkk""""""! nnnnnmmmmmmllllkkkkk"""""! nnnnmmmmmmllllkkkkkjj"""" nnnmmmmmmllllkkkkkjjjH"" nnmmmmmmllllkkkkkjjjjHGG ||mmmmmllllkkkkkjjjjiGGG |||mmmllllkkkkkjjjjiiGGFFF||||mllllkkkkkjjjjiiiGFFFF||||{lllkkkkkjjjjiiiFFFFFF||{{{{{kkkkkjjjjiiiFFFFFEED{{{{{{zzzkkjjjjFFFEEDDDD{{{{zzzzzzzzFFEEEDDDDD{{zzzzzzzzzzEEEEDDDDDCBzzzzzzzzzzzzyyEEEDDDDDCCBBBAA???zzzzzzzzzzyyyyyyEEEDDDDCCBBBAAAAA@@?????zzzzzzzzyyyyyyyyyEEDDDCCCBBBAAAA@@@?????zzzzzzyyyyyyyyyyyyDDDCCCBBBAAAA@@@???????zzzzyyyyyyyyyyyyyyDDCCCCBBBAAAA@@@???????zzyyyyyyyyyyyyyyxxxCCCCBBBAAAA@@@@???????yyyyyyyyyyyyyyxxxxxxCCCBBBAAA@@@@???????yyyyyyyyyyyyxxxxxxxxxCCBBBAAAA@@@@??????>yyyyyyyyyyxxxxxxxxxxxwwCBBBAAA@@@@@?????>>yyyyyyyyxxxxxxxxxwwwwwwwBBBAAA@@@@@?????>>>yyyyyyxxxxxxxwwwwwwwwwwvvBBAAA@@@@@????>>>yyyyxxxxxwwwwwwwwwwwwwvvvvvBAAA@@@@@@???>>>>yyxxxwwwwwwwwwwwwwwwvvvvvvvvBAA@>>>>>xwwwwwwwwwwwwwwwwwwvvvvvvvvvv>>=wwwwwwwwwwwwwwwwwvvvvvvvvvvvuu==wwwwwwwwwwwwwwwwvvvvvvvvvvuuuuuwwwwwwwwwwwwwwvvvvvvvvvvuuuuuuuuwwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuutttwwwwwwwwwwvvvvvvvvuuuuuuuuuuuuttttttwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttttwwwwwwwvvvvvvvuuuuuuuuuuuutttttttttttwwwwwvvvvvvvuuuuuuuuuuuutttttttttttttwwwwvvvvvvuuuuuuuuuuuuttttttttttttttttwwvvvvvvuuuuuuuuuuuuttttttttttttttttttwvvvvvuuuuuuuuuuuuttttttttttttttttttssvvvvuuuuuuuuuuuuttttttttttttttttsssssssvvuuuuuuuuuuuuttttttttttttttsssssssssrruuuuuuuuuuuuttttttttttttsssssssssssrrrruuuuuuuuuuttttttttttsssssssssssssrrrrrrruuuuuuuuttttttttsssssssssssssssrrrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrqquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppnnnmm#####!!!!!! nnnmmmm#####!!!!!! nnnmmmmmm####""!!!!! nnnmmmmmml$###"""!!!!! nnnmmmmmmlll$$#"""""!!!! nnnmmmmmmllll $$$""""""!!!! nnnmmmmmmllllk $$$"""""""!!! nnnmmmmmmllllkk $$"""""""!!! nnnmmmmmmllllkkk $""""""""!! nnnmmmmmmllllkkkk"""""""!! nnnmmmmmmllllkkkkk"""""""! nnnmmmmmmllllkkkkkj"""""! nnnmmmmmmllllkkkkkjjj"""" nnnmmmmmmllllkkkkkjjjj""" nnmmmmmmllllkkkkkjjjji" nmmmmmmllllkkkkkjjjjiiG mmmmmmllllkkkkkjjjjiiiGF |mmmmllllkkkkkjjjjiiiFFF|||mllllkkkkkjjjjiiiFFFF|||llllkkkkkjjjjiiihFFFF|{{{{lkkkkkjjjjiiiFFFEED{{{{{zzkkkjjjjiiiFFEEEDDD{{{zzzzzzzjjjiiiEEEEDDDD{zzzzzzzzzzziiiEEEDDDDDCCzzzzzzzzzzzyyEEDDDDCCBBBA??zzzzzzzzzyyyyyyEDDDCCCBBBAAAA@@@?????zzzzzzzyyyyyyyyyDDDCCCBBBAAAAA@@??????zzzzzyyyyyyyyyyyyDCCCCBBBAAAA@@@???????zzzyyyyyyyyyyyyyyCCCCBBBAAAA@@@@???????zyyyyyyyyyyyyyyyxxCCCBBBAAAA@@@???????>yyyyyyyyyyyyyyxxxxxCBBBAAAA@@@@??????>>yyyyyyyyyyyyxxxxxxxxCBBBAAA@@@@@?????>>>yyyyyyyyyyxxxxxxxxxwwwBBAAAA@@@@?????>>>yyyyyyyyxxxxxxxwwwwwwwwBBAAA@@@@@????>>>>yyyyyyxxxxxwwwwwwwwwwwvvvBAAA@@@@@@???>>>>>yyyyxxxwwwwwwwwwwwwwwvvvvvAAA@@@@@???>>>>>=yyxwwwwwwwwwwwwwwwwvvvvvvvvAA@@@@@@??>>>>>==wwwwwwwwwwwwwwwwwwvvvvvvvvvv@>>>>===wwwwwwwwwwwwwwwwvvvvvvvvvvvuuu>===wwwwwwwwwwwwwwwvvvvvvvvvvuuuuuu===wwwwwwwwwwwwwvvvvvvvvvvuuuuuuuuuwwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuttttwwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttwwwwwwwvvvvvvvvuuuuuuuuuuuuttttttttttwwwwwwvvvvvvvuuuuuuuuuuuuttttttttttttwwwwvvvvvvvuuuuuuuuuuuutttttttttttttttwwwvvvvvvuuuuuuuuuuuutttttttttttttttttwvvvvvvuuuuuuuuuuuutttttttttttttttttttvvvvvuuuuuuuuuuuutttttttttttttttttsssssvvvuuuuuuuuuuuutttttttttttttttssssssssrvuuuuuuuuuuuutttttttttttttssssssssssrrruuuuuuuuuuutttttttttttssssssssssssrrrrrruuuuuuuuutttttttttssssssssssssssrrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrrquuutttssssssssssssssssssssrrrrrrrrrrrrqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppnmm#!!!!!! nmmmm""!!!!! nmmmmmm"""!!!!! nmmmmmmll""""!!!! nmmmmmmllll""""!!!! nmmmmmmllllkk""""""!!! nmmmmmmllllkkk """"""!!! nmmmmmmllllkkkk"""""""!! nmmmmmmllllkkkkk"""""""!! nmmmmmmllllkkkkkj"""""""! nmmmmmmllllkkkkkjj"""""! nmmmmmmllllkkkkkjjj""""" nmmmmmmllllkkkkkjjjj""" nmmmmmmllllkkkkkjjjjii"" nmmmmmmllllkkkkkjjjjiii mmmmmmllllkkkkkjjjjiii mmmmmllllkkkkkjjjjiiiFmmmmllllkkkkkjjjjiiihFF|mmllllkkkkkjjjjiiihhFFF||llllkkkkkjjjjiiihhhFFF|{{llkkkkkjjjjiiihhhFFEED{{{{zkkkkjjjjiiihhhhEEEDD{{zzzzzzjjjjiiihhhhEEDDDDzzzzzzzzzzjiiihhhEEDDDDDCzzzzzzzzzzyyihhEDDDDCCBBBzzzzzzzzyyyyyyhDDDCCBBBAAAA????zzzzzzyyyyyyyyyyDDCCCBBBAAAA@@@??????zzzzyyyyyyyyyyyyCCCBBBAAAAA@@@??????zzyyyyyyyyyyyyyyCCCBBBAAAA@@@???????>yyyyyyyyyyyyyyyxxCBBBAAAA@@@@??????>>>yyyyyyyyyyyyyxxxxxBBBAAAA@@@@?????>>>yyyyyyyyyyyxxxxxxxxxBBAAAA@@@@?????>>>>yyyyyyyyyxxxxxxxxwwwwBBAAA@@@@@????>>>>>yyyyyyyxxxxxxwwwwwwwwwAAAA@@@@@???>>>>>=yyyyyxxxxwwwwwwwwwwwwvvvAAA@@@@@???>>>>>==yyyxxwwwwwwwwwwwwwwwvvvvvA@@@@@@??>>>>>===ywwwwwwwwwwwwwwwwwvvvvvvvvA@@@@@@?>>>>>====wwwwwwwwwwwwwwwwwvvvvvvvvvvv@@@@@?>>>>>====wwwwwwwwwwwwwwwvvvvvvvvvvvuuu>>>=====wwwwwwwwwwwwwwvvvvvvvvvvuuuuuu=====wwwwwwwwwwwwvvvvvvvvvvuuuuuuuuuwwwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuwwwwwwwwwvvvvvvvvvuuuuuuuuuuuuttttwwwwwwwwvvvvvvvvuuuuuuuuuuuutttttttwwwwwwvvvvvvvvuuuuuuuuuuuuttttttttttwwwwwvvvvvvvuuuuuuuuuuuutttttttttttttwwwvvvvvvvuuuuuuuuuuuuttttttttttttttttwwvvvvvvuuuuuuuuuuuuttttttttttttttttttvvvvvvuuuuuuuuuuuuttttttttttttttttttsssvvvvuuuuuuuuuuuuttttttttttttttttsssssssvvuuuuuuuuuuuuttttttttttttttsssssssssrruuuuuuuuuuuuttttttttttttsssssssssssrrrrruuuuuuuuuuttttttttttsssssssssssssrrrrrrruuuuuuuuttttttttsssssssssssssssrrrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrqquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppsssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppmm!!!! mmmm!!!! mmmmmm"!!!! mmmmmmll"!!!! mmmmmmllll""!!! mmmmmmllllkk"""!!! mmmmmmllllkkkk""""!! mmmmmmllllkkkkkj""""!! mmmmmmllllkkkkkjj""""""! mmmmmmllllkkkkkjjj""""""! mmmmmmllllkkkkkjjjj""""" mmmmmmllllkkkkkjjjji"""" mmmmmmllllkkkkkjjjjiii""" mmmmmmllllkkkkkjjjjiii mmmmmmllllkkkkkjjjjiii mmmmmllllkkkkkjjjjiiih mmmmllllkkkkkjjjjiiihhmmmllllkkkkkjjjjiiihhhFmmllllkkkkkjjjjiiihhhF|llllkkkkkjjjjiiihhhhFE{{llkkkkkjjjjiiihhhhhEE{{{kkkkkjjjjiiihhhhhggEDDD{zzzzzzjjjjiiihhhhhggEDDDDzzzzzzzzjjiiihhhhhDDDDCzzzzzzzzzyiihhhhDDDCCBBzzzzzzzyyyyyhhhDDCCCBBBAAzzzzzyyyyyyyyyhhCCCBBBAAAAA@@@??????zzzyyyyyyyyyyyyCCBBBAAAA@@@???????zyyyyyyyyyyyyyyyCBBBAAAAA@@@??????>>yyyyyyyyyyyyyyyxBBBAAAA@@@@?????>>>>yyyyyyyyyyyyyxxxxxBBAAAA@@@@?????>>>>>yyyyyyyyyyyxxxxxxxxBAAAA@@@@????>>>>>=yyyyyyyyyxxxxxxwwwwwwAAAA@@@@@???>>>>>==yyyyyyyxxxxwwwwwwwwwwwAAA@@@@@???>>>>>===yyyyyxxwwwwwwwwwwwwwvvvAA@@@@@??>>>>>====yyywwwwwwwwwwwwwwwwvvvvvv@@@@@@?>>>>>====wwwwwwwwwwwwwwwwwvvvvvvvvv@@@@@?>>>>>=====wwwwwwwwwwwwwwwwvvvvvvvvvvv@@@@@>>>>>======wwwwwwwwwwwwwwvvvvvvvvvvvuuu@@@>>>>>======>======yyyyyyyyyyyyyyyBBBAAAA@@@@?????>>>yyyyyyyyyyyyyyxxBAAAAA@@@?????>>>>yyyyyyyyyyyyxxxxxBAAAA@@@@????>>>>>=yyyyyyyyyyxxxxxxxwAAAA@@@@@???>>>>>===yyyyyyyyxxxxxwwwwwwwAAA@@@@???>>>>>====yyyyyyxxxwwwwwwwwwwwwA@@@@@??>>>>>====yyyyxwwwwwwwwwwwwwwvvvv@@@@@@?>>>>>=====yywwwwwwwwwwwwwwwwvvvvvv@@@@?>>>>>======wwwwwwwwwwwwwwwwvvvvvvvvv@@@@>>>>>======>>>>======<>>>======<<>>>======<<======<<<>yyyyyyyyyyyyyyBAAAAA@@@?????>>>yyyyyyyyyyyyyyxBAAAA@@@@????>>>>>yyyyyyyyyyyyxxxxAAAA@@@@???>>>>>==yyyyyyyyyyxxxxxwwAA@@@@???>>>>>====yyyyyyyyxxxwwwwwwwwA@@@@@??>>>>>=====yyyyyyxwwwwwwwwwwwww@@@@@?>>>>>======yyyywwwwwwwwwwwwwwvvvv@@@@?>>>>>======<>>>>======<>>>>======<<>>>======<<>>>======<<<>>======<<<>======<<<<>>>yyyyyyyyyyyyyxgAAAA@@@@???>>>>>=yyyyyyyyyyyxxxxAA@@@@???>>>>>===yyyyyyyyyxxxxwwwwA@@@@??>>>>>=====yyyyyyyxxwwwwwwwwww@@@@@?>>>>>======<>>>>======<<>>>>======<<>>>>======<<<>>>======<<<>>>======<<<<>>======<<<<>======<<<<<======<<<<<>>>>==yyyyyyyyyyyxxxfffffee@@@@??>>>>>====yyyyyyyyyxxwwwwwe@@@@?>>>>>======yyyyyyywwwwwwwwwww@@@?>>>>>======<<>>>>======<<<>>>>======<<<>>>======<<<<>>>======<<<<>>======<<<<<>======<<<<<<;wwwwwwwwwvvvvvvvvvvuuuuuuuu======<<<<<<;wwwwwwwvvvvvvvvvvuuuuuuuuuuu=====<<<<<<;;wwwwwwvvvvvvvvvuuuuuuuuuuuutt====<<<<<<;;;wwwwvvvvvvvvvuuuuuuuuuuuutttttt===<<<<<<;;;wwwvvvvvvvvuuuuuuuuuuuutttttttttt<<<;;;;wvvvvvvvvuuuuuuuuuuuutttttttttttttt;;;vvvvvvvuuuuuuuuuuuutttttttttttttttttvvvvvuuuuuuuuuuuutttttttttttttttttssvvvuuuuuuuuuuuutttttttttttttttsssssssvuuuuuuuuuuuutttttttttttttssssssssssrruuuuuuuuuuutttttttttttssssssssssssrrrrrruuuuuuuuutttttttttssssssssssssssrrrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrrquuutttssssssssssssssssssssrrrrrrrrrrrrqqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppppllkklkkkklkkkkkjjlkkkkkjjjjlkkkkkjjjjiiilkkkkkjjjjiiilkkkkkjjjjiiihhhlkkkkkjjjjiiihhhhhgglkkkkkjjjjiiihhhhhggglkkkkkjjjjiiihhhhhgggglkkkkkjjjjiiihhhhhggggflkkkkkjjjjiiihhhhhggggffflkkkkkjjjjiiihhhhhggggfffflkkkkkjjjjiiihhhhhggggffffkkkkkjjjjiiihhhhhggggfffffkkkkjjjjiiihhhhhggggfffffeekkkjjjjiiihhhhhggggfffffeeekkjjjjiiihhhhhggggfffffeeeekjjjjiiihhhhhggggfffffeeeeezzjjiiihhhhhggggfffffeeeeeezzyyiihhhhhggggfffffeeeeeedyyyyyyhhhhhggggfffffeeeeeeddyyyyyyyyhhhhggggfffffeeeeeedyyyyyyyyyyhggggfffffeeeeeeyyyyyyyyyyygggfffffeeeeeeyyyyyyyyyyxxgfffffeeeee@@>>>=====yyyyyyyyxwwwwwwffeeeee@@?>>>>>======>>>>======<<>>>>======<<<<>>>======<<<<<>>======<<<<<>======<<<<<<;wwwwwwwwwwwvvvvvvvvvvvu>======<<<<<<;;wwwwwwwwwvvvvvvvvvvvuuuuu======<<<<<<;;wwwwwwwwvvvvvvvvvvuuuuuuuu=====<<<<<<;;;wwwwwwvvvvvvvvvvuuuuuuuuuuu====<<<<<<;;;;wwwwwvvvvvvvvvuuuuuuuuuuuuttt==<<<<<<;;;;wwwvvvvvvvvvuuuuuuuuuuuuttttttt=<<<<<<;;;;;wwvvvvvvvvuuuuuuuuuuuuttttttttttt<<<<<<;;;;;;vvvvvvvvuuuuuuuuuuuutttttttttttttt;;;;;;:vvvvvvuuuuuuuuuuuuttttttttttttttttt;;;::vvvvuuuuuuuuuuuuttttttttttttttttssss:::vvuuuuuuuuuuuuttttttttttttttsssssssss::uuuuuuuuuuuuttttttttttttsssssssssssrrruuuuuuuuuuttttttttttsssssssssssssrrrrrruuuuuuuuttttttttsssssssssssssssrrrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrqqquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppsssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppsssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppsssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppsssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppppkkkkkkkkjjkkkkjjjjkkkkjjjjiiikkkkjjjjiiikkkkjjjjiiihhhkkkkjjjjiiihhhhhgggkkkkjjjjiiihhhhhggggfkkkkjjjjiiihhhhhggggffkkkkjjjjiiihhhhhggggfffkkkkjjjjiiihhhhhggggffffkkkkjjjjiiihhhhhggggfffffkkkkjjjjiiihhhhhggggfffffekkkkjjjjiiihhhhhggggfffffeeekkkjjjjiiihhhhhggggfffffeeeekkjjjjiiihhhhhggggfffffeeeeekjjjjiiihhhhhggggfffffeeeeeejjjjiiihhhhhggggfffffeeeeeedjjjiiihhhhhggggfffffeeeeeeddzyiiihhhhhggggfffffeeeeeedddyyyyyhhhhhggggfffffeeeeeeddddyyyyyyyhhhhggggfffffeeeeeeddddcyyyyyyyyhhggggfffffeeeeeeddddccyyyyyyyyyggggfffffeeeeeeddddccyyyyyyyyyyxgfffffeeeeeeddddyyyyyyyywwwwwfffeeeeeeddd=====>>>>======<<>>>======<<<<>>======<<<<<<;wwwwwwwwwwwwwvvvvvvvv>>======<<<<<<;;wwwwwwwwwwwvvvvvvvvvvv======<<<<<<;;;wwwwwwwwwwvvvvvvvvvvvuu=====<<<<<<;;;wwwwwwwwvvvvvvvvvvvuuuuu====<<<<<<;;;;wwwwwwwvvvvvvvvvvuuuuuuuu===<<<<<<;;;;;wwwwwvvvvvvvvvvuuuuuuuuuuu==<<<<<<;;;;;wwwwvvvvvvvvvuuuuuuuuuuuuttt<<<<<<;;;;;;wwvvvvvvvvvuuuuuuuuuuuuttttttt<<<<<;;;;;;:wvvvvvvvvuuuuuuuuuuuuttttttttttt<<<<;;;;;;::vvvvvvvuuuuuuuuuuuuttttttttttttttt<<<;;;;;;:::vvvvvuuuuuuuuuuuuttttttttttttttttts;;;;::::vvvuuuuuuuuuuuutttttttttttttttssssss;:::::vuuuuuuuuuuuutttttttttttttssssssssss::::uuuuuuuuuuutttttttttttssssssssssssrrrruuuuuuuuutttttttttssssssssssssssrrrrrrruuuuuuutttttttssssssssssssssssrrrrrrrrrruuuuutttttssssssssssssssssssrrrrrrrrrrrrquuutttssssssssssssssssssssrrrrrrrrrrrrqqqqutssssssssssssssssssssssrrrrrrrrrrrrqqqqqqssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppppssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppppppppkkkjjkkjjjjkkjjjjiiikkjjjjiiikkjjjjiiihhhhkkjjjjiiihhhhhgggkkjjjjiiihhhhhggggfffkkjjjjiiihhhhhggggffffkkjjjjiiihhhhhggggfffffkkjjjjiiihhhhhggggfffffekkjjjjiiihhhhhggggfffffeekkjjjjiiihhhhhggggfffffeeekkjjjjiiihhhhhggggfffffeeeekkjjjjiiihhhhhggggfffffeeeeekjjjjiiihhhhhggggfffffeeeeeedjjjjiiihhhhhggggfffffeeeeeeddjjjiiihhhhhggggfffffeeeeeedddjjiiihhhhhggggfffffeeeeeeddddjiiihhhhhggggfffffeeeeeeddddcyyyhhhhhggggfffffeeeeeeddddccyyyyyhhhhhggggfffffeeeeeeddddcccyyyyyyyhhggggfffffeeeeeeddddccccyyyyyyyyggggfffffeeeeeeddddccccyyyyyyyyyggfffffeeeeeeddddcccyyyyyyywwwwwfffeeeeeeddddcccyyyywwwwwwwwwweeeeeeddddccc===<<>======<<<<======<<<<<<;wwwwwwwwwwwwvvvvvvvvdcc======<<<<<<;;;wwwwwwwwwwvvvvvvvvvvv=====<<<<<<;;;;wwwwwwwwwvvvvvvvvvvvuu====<<<<<<;;;;;wwwwwwwvvvvvvvvvvvuuuuu==<<<<<<;;;;;;wwwwwwvvvvvvvvvvuuuuuuuu=<<<<<<;;;;;;:wwwwvvvvvvvvvvuuuuuuuuuuuu<<<<<<;;;;;;::wwwvvvvvvvvvuuuuuuuuuuuuttt<<<<<;;;;;;:::wvvvvvvvvvuuuuuuuuuuuuttttttt<<<<;;;;;;::::vvvvvvvvuuuuuuuuuuuuttttttttttt<<;;;;;;:::::vvvvvvuuuuuuuuuuuuttttttttttttttt<;;;;;;::::::vvvvuuuuuuuuuuuuttttttttttttttttss;;;;;;::::::vvuuuuuuuuuuuuttttttttttttttsssssss;;;::::::uuuuuuuuuuuuttttttttttttsssssssssssr::::::uuuuuuuuuuttttttttttsssssssssssssrrrr:uuuuuuuuttttttttsssssssssssssssrrrrrrruuuuuuttttttsssssssssssssssssrrrrrrrrrruuuuttttsssssssssssssssssssrrrrrrrrrrrrquuttsssssssssssssssssssssrrrrrrrrrrrrqqqqsssssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqsssssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqsssssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpsssssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppsssssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppsssssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppsssssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppsssssssssrrrrrrrrrrrrqqqqqqqqqqqqppppppppppppsssssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppsssssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppppsssrrrrrrrrrrrrqqqqqqqqqqqqpppppppppppppppppppkjjkjjjjkjjjjiiikjjjjiiikjjjjiiihhhhkjjjjiiihhhhhgggkjjjjiiihhhhhggggffffkjjjjiiihhhhhggggfffffekjjjjiiihhhhhggggfffffeekjjjjiiihhhhhggggfffffeeekjjjjiiihhhhhggggfffffeeeekjjjjiiihhhhhggggfffffeeeeekjjjjiiihhhhhggggfffffeeeeeekjjjjiiihhhhhggggfffffeeeeeeddjjjjiiihhhhhggggfffffeeeeeedddjjjiiihhhhhggggfffffeeeeeeddddjjiiihhhhhggggfffffeeeeeeddddcjiiihhhhhggggfffffeeeeeeddddcciiihhhhhggggfffffeeeeeeddddcccyihhhhhggggfffffeeeeeeddddccccyyyyhhhhhggggfffffeeeeeeddddcccccyyyyyhhhggggfffffeeeeeeddddcccccbbyyyyyyyggggfffffeeeeeeddddcccccbbyyyyyyyyggfffffeeeeeeddddcccccbyyyyyywwwwffffeeeeeeddddcccccyyywwwwwwwwwfeeeeeeddddcccccwwwwwwwwwwwwwweeeeddddcccc<<< *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_items.c: Weapons, ammos, healthpacks etc, etc... */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "g_defs.h" #include "p_player.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- /** * Default weapon definitions. * These are used if other (external) definitions are not found. */ weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES] = { { { // fist GM_ANY, {0, 0, 0, 0}, // type: clip | shell | cell | misl {0, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_PUNCHUP, S_PUNCHDOWN, S_PUNCH, S_PUNCH1, S_NULL }, 0, // raise sound id 0 // ready sound } }, { { // pistol GM_ANY, {1, 0, 0, 0}, // type: clip | shell | cell | misl {1, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_PISTOLUP, S_PISTOLDOWN, S_PISTOL, S_PISTOL1, S_PISTOLFLASH }, 0, // raise sound id 0 // ready sound } }, { { // shotgun GM_ANY, {0, 1, 0, 0}, // type: clip | shell | cell | misl {0, 1, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_SGUNUP, S_SGUNDOWN, S_SGUN, S_SGUN1, S_SGUNFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // chaingun GM_ANY, {1, 0, 0, 0}, // type: clip | shell | cell | misl {1, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_CHAINUP, S_CHAINDOWN, S_CHAIN, S_CHAIN1, S_CHAINFLASH1 }, 0, // raise sound id 0, // ready sound } }, { { // missile launcher GM_ANY, {0, 0, 0, 1}, // type: clip | shell | cell | misl {0, 0, 0, 1}, // pershot: clip | shell | cell | misl false, // autofire when raised if fire held { S_MISSILEUP, S_MISSILEDOWN, S_MISSILE, S_MISSILE1, S_MISSILEFLASH1 }, 0, // raise sound id 0, // ready sound } }, { { // plasma rifle GM_NOTSHAREWARE, {0, 0, 1, 0}, // type: clip | shell | cell | misl {0, 0, 1, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_PLASMAUP, S_PLASMADOWN, S_PLASMA, S_PLASMA1, S_PLASMAFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // bfg 9000 GM_NOTSHAREWARE, {0, 0, 1, 0}, // type: clip | shell | cell | misl {0, 0, 40, 0}, // pershot: clip | shell | cell | misl false, // autofire when raised if fire held { S_BFGUP, S_BFGDOWN, S_BFG, S_BFG1, S_BFGFLASH1 }, 0, // raise sound id 0 // ready sound } }, { { // chainsaw GM_ANY, {0, 0, 0, 0}, // type: clip | shell | cell | misl {0, 0, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_SAWUP, S_SAWDOWN, S_SAW, S_SAW1, S_NULL }, SFX_SAWUP, // raise sound id SFX_SAWIDL // ready sound } }, { { // super shotgun GM_COMMERCIAL, {0, 1, 0, 0}, // type: clip | shell | cell | misl {0, 2, 0, 0}, // pershot: clip | shell | cell | misl true, // autofire when raised if fire held { S_DSGUNUP, S_DSGUNDOWN, S_DSGUN, S_DSGUN1, S_DSGUNFLASH1 }, 0, // raise sound id 0 // ready sound } } }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static const char* ammoTypeNames[NUM_AMMO_TYPES] = {"clip", "shell", "cell", "misl"}; // CODE -------------------------------------------------------------------- /** * Initialize ammo info. */ void P_InitAmmoInfo(void) { uint i; char buf[40]; for(i = 0; i < NUM_AMMO_TYPES; ++i) { // Max ammo. sprintf(buf, "Player|Max ammo|%s", ammoTypeNames[i]); GetDefInt(buf, &maxAmmo[i]); // Clip ammo. sprintf(buf, "Player|Clip ammo|%s", ammoTypeNames[i]); GetDefInt(buf, &clipAmmo[i]); } } /** * Initialize weapon info. */ void P_InitWeaponInfo(void) { #define WPINF "Weapon Info|" int i; int pclass = PCLASS_PLAYER; char buf[80]; char* data; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { //// \todo Only allows for one type of ammo per weapon. sprintf(buf, WPINF "%i|Type", i); if(Def_Get(DD_DEF_VALUE, buf, &data)) { memset(weaponInfo[i][pclass].mode[0].ammoType, 0, sizeof(int) * NUM_AMMO_TYPES); memset(weaponInfo[i][pclass].mode[0].perShot, 0, sizeof(int) * NUM_AMMO_TYPES); if(stricmp(data, "noammo")) { ammotype_t k; for(k = 0; k < NUM_AMMO_TYPES; ++k) { if(!stricmp(data, ammoTypeNames[k])) { weaponInfo[i][pclass].mode[0].ammoType[k] = true; sprintf(buf, WPINF "%i|Per shot", i); GetDefInt(buf, &weaponInfo[i][pclass].mode[0].perShot[k]); break; } } } } // end todo sprintf(buf, WPINF "%i|Up", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_UP]); sprintf(buf, WPINF "%i|Down", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_DOWN]); sprintf(buf, WPINF "%i|Ready", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_READY]); sprintf(buf, WPINF "%i|Atk", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_ATTACK]); sprintf(buf, WPINF "%i|Flash", i); GetDefState(buf, &weaponInfo[i][pclass].mode[0].states[WSN_FLASH]); sprintf(buf, WPINF "%i|Static", i); weaponInfo[i][pclass].mode[0].staticSwitch = GetDefInt(buf, 0); } /// \todo Get this info from values. P_InitWeaponSlots(); P_SetWeaponSlot(WT_FIRST, 1); P_SetWeaponSlot(WT_EIGHTH, 1); P_SetWeaponSlot(WT_SECOND, 2); P_SetWeaponSlot(WT_THIRD, 3); if(gameMode == commercial) P_SetWeaponSlot(WT_NINETH, 3); P_SetWeaponSlot(WT_FOURTH, 4); P_SetWeaponSlot(WT_FIFTH, 5); P_SetWeaponSlot(WT_SIXTH, 6); P_SetWeaponSlot(WT_SEVENTH, 7); #undef WPINF } void P_InitPlayerValues(player_t *p) { int i; char buf[40]; GetDefInt("Player|Health", &p->health); GetDefInt("Player|Weapon", (int *) &p->readyWeapon); p->pendingWeapon = p->readyWeapon; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { sprintf(buf, "Weapon Info|%i|Owned", i); GetDefInt(buf, (int *) &p->weapons[i].owned); } for(i = 0; i < NUM_AMMO_TYPES; ++i) { sprintf(buf, "Player|Init ammo|%s", ammoTypeNames[i]); GetDefInt(buf, &p->ammo[i].owned); } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/m_random.c0000644000175000017500000000724711357170242022417 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.c: Random number LUT. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static int rndIndex = 0; static int prndIndex = 0; // Returns a 0-255 number static unsigned char rndTable[256] = { 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66, 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36, 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188, 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224, 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242, 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0, 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235, 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113, 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75, 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196, 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113, 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241, 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224, 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95, 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226, 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36, 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106, 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136, 120, 163, 236, 249 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * \note The returned value is calculated deterministically. * * @return A pseudo-random number from the table. */ byte P_Random(void) { prndIndex = (prndIndex + 1) & 0xff; return rndTable[prndIndex]; } /** * \note The returned value is NOT calculated deterministically. * * @return A pseudo-random number from the table. */ byte M_Random(void) { rndIndex = (rndIndex + 1) & 0xff; return rndTable[rndIndex]; } /** * Resets the seed for the random number generator. */ void M_ResetRandom(void) { rndIndex = prndIndex = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/tables.c0000644000175000017500000042275311357170242022100 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * Lookup tables. * Do not try to look them up :-). * In the order of appearance: * * int finetangent[4096] - Tangens LUT. * Should work with BAM fairly well (12 of 16bit, * effectively, by shifting). * * int finesine[10240] - Sine lookup. * Guess what, serves as cosine, too. * Remarkable thing is, how to use BAMs with this? * * int tantoangle[2049] - ArcTan LUT, * maps tan(angle) to angle fast. Gotta search. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // finecosine and finesine use the same array of values. fixed_t *finecosine = &finesine[FINEANGLES / 4]; int finetangent[4096] = { -170910304, -56965752, -34178904, -24413316, -18988036, -15535599, -13145455, -11392683, -10052327, -8994149, -8137527, -7429880, -6835455, -6329090, -5892567, -5512368, -5178251, -4882318, -4618375, -4381502, -4167737, -3973855, -3797206, -3635590, -3487165, -3350381, -3223918, -3106651, -2997613, -2895966, -2800983, -2712030, -2628549, -2550052, -2476104, -2406322, -2340362, -2277919, -2218719, -2162516, -2109087, -2058233, -2009771, -1963536, -1919378, -1877161, -1836758, -1798063, -1760956, -1725348, -1691149, -1658278, -1626658, -1596220, -1566898, -1538632, -1511367, -1485049, -1459630, -1435065, -1411312, -1388330, -1366084, -1344537, -1323658, -1303416, -1283783, -1264730, -1246234, -1228269, -1210813, -1193846, -1177345, -1161294, -1145673, -1130465, -1115654, -1101225, -1087164, -1073455, -1060087, -1047046, -1034322, -1021901, -1009774, -997931, -986361, -975054, -964003, -953199, -942633, -932298, -922186, -912289, -902602, -893117, -883829, -874730, -865817, -857081, -848520, -840127, -831898, -823827, -815910, -808143, -800521, -793041, -785699, -778490, -771411, -764460, -757631, -750922, -744331, -737853, -731486, -725227, -719074, -713023, -707072, -701219, -695462, -689797, -684223, -678737, -673338, -668024, -662792, -657640, -652568, -647572, -642651, -637803, -633028, -628323, -623686, -619117, -614613, -610174, -605798, -601483, -597229, -593033, -588896, -584815, -580789, -576818, -572901, -569035, -565221, -561456, -557741, -554074, -550455, -546881, -543354, -539870, -536431, -533034, -529680, -526366, -523094, -519861, -516667, -513512, -510394, -507313, -504269, -501261, -498287, -495348, -492443, -489571, -486732, -483925, -481150, -478406, -475692, -473009, -470355, -467730, -465133, -462565, -460024, -457511, -455024, -452564, -450129, -447720, -445337, -442978, -440643, -438332, -436045, -433781, -431540, -429321, -427125, -424951, -422798, -420666, -418555, -416465, -414395, -412344, -410314, -408303, -406311, -404338, -402384, -400448, -398530, -396630, -394747, -392882, -391034, -389202, -387387, -385589, -383807, -382040, -380290, -378555, -376835, -375130, -373440, -371765, -370105, -368459, -366826, -365208, -363604, -362013, -360436, -358872, -357321, -355783, -354257, -352744, -351244, -349756, -348280, -346816, -345364, -343924, -342495, -341078, -339671, -338276, -336892, -335519, -334157, -332805, -331464, -330133, -328812, -327502, -326201, -324910, -323629, -322358, -321097, -319844, -318601, -317368, -316143, -314928, -313721, -312524, -311335, -310154, -308983, -307819, -306664, -305517, -304379, -303248, -302126, -301011, -299904, -298805, -297714, -296630, -295554, -294485, -293423, -292369, -291322, -290282, -289249, -288223, -287204, -286192, -285186, -284188, -283195, -282210, -281231, -280258, -279292, -278332, -277378, -276430, -275489, -274553, -273624, -272700, -271782, -270871, -269965, -269064, -268169, -267280, -266397, -265519, -264646, -263779, -262917, -262060, -261209, -260363, -259522, -258686, -257855, -257029, -256208, -255392, -254581, -253774, -252973, -252176, -251384, -250596, -249813, -249035, -248261, -247492, -246727, -245966, -245210, -244458, -243711, -242967, -242228, -241493, -240763, -240036, -239314, -238595, -237881, -237170, -236463, -235761, -235062, -234367, -233676, -232988, -232304, -231624, -230948, -230275, -229606, -228941, -228279, -227621, -226966, -226314, -225666, -225022, -224381, -223743, -223108, -222477, -221849, -221225, -220603, -219985, -219370, -218758, -218149, -217544, -216941, -216341, -215745, -215151, -214561, -213973, -213389, -212807, -212228, -211652, -211079, -210509, -209941, -209376, -208815, -208255, -207699, -207145, -206594, -206045, -205500, -204956, -204416, -203878, -203342, -202809, -202279, -201751, -201226, -200703, -200182, -199664, -199149, -198636, -198125, -197616, -197110, -196606, -196105, -195606, -195109, -194614, -194122, -193631, -193143, -192658, -192174, -191693, -191213, -190736, -190261, -189789, -189318, -188849, -188382, -187918, -187455, -186995, -186536, -186080, -185625, -185173, -184722, -184274, -183827, -183382, -182939, -182498, -182059, -181622, -181186, -180753, -180321, -179891, -179463, -179037, -178612, -178190, -177769, -177349, -176932, -176516, -176102, -175690, -175279, -174870, -174463, -174057, -173653, -173251, -172850, -172451, -172053, -171657, -171263, -170870, -170479, -170089, -169701, -169315, -168930, -168546, -168164, -167784, -167405, -167027, -166651, -166277, -165904, -165532, -165162, -164793, -164426, -164060, -163695, -163332, -162970, -162610, -162251, -161893, -161537, -161182, -160828, -160476, -160125, -159775, -159427, -159079, -158734, -158389, -158046, -157704, -157363, -157024, -156686, -156349, -156013, -155678, -155345, -155013, -154682, -154352, -154024, -153697, -153370, -153045, -152722, -152399, -152077, -151757, -151438, -151120, -150803, -150487, -150172, -149859, -149546, -149235, -148924, -148615, -148307, -148000, -147693, -147388, -147084, -146782, -146480, -146179, -145879, -145580, -145282, -144986, -144690, -144395, -144101, -143808, -143517, -143226, -142936, -142647, -142359, -142072, -141786, -141501, -141217, -140934, -140651, -140370, -140090, -139810, -139532, -139254, -138977, -138701, -138426, -138152, -137879, -137607, -137335, -137065, -136795, -136526, -136258, -135991, -135725, -135459, -135195, -134931, -134668, -134406, -134145, -133884, -133625, -133366, -133108, -132851, -132594, -132339, -132084, -131830, -131576, -131324, -131072, -130821, -130571, -130322, -130073, -129825, -129578, -129332, -129086, -128841, -128597, -128353, -128111, -127869, -127627, -127387, -127147, -126908, -126669, -126432, -126195, -125959, -125723, -125488, -125254, -125020, -124787, -124555, -124324, -124093, -123863, -123633, -123404, -123176, -122949, -122722, -122496, -122270, -122045, -121821, -121597, -121374, -121152, -120930, -120709, -120489, -120269, -120050, -119831, -119613, -119396, -119179, -118963, -118747, -118532, -118318, -118104, -117891, -117678, -117466, -117254, -117044, -116833, -116623, -116414, -116206, -115998, -115790, -115583, -115377, -115171, -114966, -114761, -114557, -114354, -114151, -113948, -113746, -113545, -113344, -113143, -112944, -112744, -112546, -112347, -112150, -111952, -111756, -111560, -111364, -111169, -110974, -110780, -110586, -110393, -110200, -110008, -109817, -109626, -109435, -109245, -109055, -108866, -108677, -108489, -108301, -108114, -107927, -107741, -107555, -107369, -107184, -107000, -106816, -106632, -106449, -106266, -106084, -105902, -105721, -105540, -105360, -105180, -105000, -104821, -104643, -104465, -104287, -104109, -103933, -103756, -103580, -103404, -103229, -103054, -102880, -102706, -102533, -102360, -102187, -102015, -101843, -101671, -101500, -101330, -101159, -100990, -100820, -100651, -100482, -100314, -100146, -99979, -99812, -99645, -99479, -99313, -99148, -98982, -98818, -98653, -98489, -98326, -98163, -98000, -97837, -97675, -97513, -97352, -97191, -97030, -96870, -96710, -96551, -96391, -96233, -96074, -95916, -95758, -95601, -95444, -95287, -95131, -94975, -94819, -94664, -94509, -94354, -94200, -94046, -93892, -93739, -93586, -93434, -93281, -93129, -92978, -92826, -92675, -92525, -92375, -92225, -92075, -91926, -91777, -91628, -91480, -91332, -91184, -91036, -90889, -90742, -90596, -90450, -90304, -90158, -90013, -89868, -89724, -89579, -89435, -89292, -89148, -89005, -88862, -88720, -88577, -88435, -88294, -88152, -88011, -87871, -87730, -87590, -87450, -87310, -87171, -87032, -86893, -86755, -86616, -86479, -86341, -86204, -86066, -85930, -85793, -85657, -85521, -85385, -85250, -85114, -84980, -84845, -84710, -84576, -84443, -84309, -84176, -84043, -83910, -83777, -83645, -83513, -83381, -83250, -83118, -82987, -82857, -82726, -82596, -82466, -82336, -82207, -82078, -81949, -81820, -81691, -81563, -81435, -81307, -81180, -81053, -80925, -80799, -80672, -80546, -80420, -80294, -80168, -80043, -79918, -79793, -79668, -79544, -79420, -79296, -79172, -79048, -78925, -78802, -78679, -78557, -78434, -78312, -78190, -78068, -77947, -77826, -77705, -77584, -77463, -77343, -77223, -77103, -76983, -76864, -76744, -76625, -76506, -76388, -76269, -76151, -76033, -75915, -75797, -75680, -75563, -75446, -75329, -75213, -75096, -74980, -74864, -74748, -74633, -74517, -74402, -74287, -74172, -74058, -73944, -73829, -73715, -73602, -73488, -73375, -73262, -73149, -73036, -72923, -72811, -72699, -72587, -72475, -72363, -72252, -72140, -72029, -71918, -71808, -71697, -71587, -71477, -71367, -71257, -71147, -71038, -70929, -70820, -70711, -70602, -70494, -70385, -70277, -70169, -70061, -69954, -69846, -69739, -69632, -69525, -69418, -69312, -69205, -69099, -68993, -68887, -68781, -68676, -68570, -68465, -68360, -68255, -68151, -68046, -67942, -67837, -67733, -67629, -67526, -67422, -67319, -67216, -67113, -67010, -66907, -66804, -66702, -66600, -66498, -66396, -66294, -66192, -66091, -65989, -65888, -65787, -65686, -65586, -65485, -65385, -65285, -65185, -65085, -64985, -64885, -64786, -64687, -64587, -64488, -64389, -64291, -64192, -64094, -63996, -63897, -63799, -63702, -63604, -63506, -63409, -63312, -63215, -63118, -63021, -62924, -62828, -62731, -62635, -62539, -62443, -62347, -62251, -62156, -62060, -61965, -61870, -61775, -61680, -61585, -61491, -61396, -61302, -61208, -61114, -61020, -60926, -60833, -60739, -60646, -60552, -60459, -60366, -60273, -60181, -60088, -59996, -59903, -59811, -59719, -59627, -59535, -59444, -59352, -59261, -59169, -59078, -58987, -58896, -58805, -58715, -58624, -58534, -58443, -58353, -58263, -58173, -58083, -57994, -57904, -57815, -57725, -57636, -57547, -57458, -57369, -57281, -57192, -57104, -57015, -56927, -56839, -56751, -56663, -56575, -56487, -56400, -56312, -56225, -56138, -56051, -55964, -55877, -55790, -55704, -55617, -55531, -55444, -55358, -55272, -55186, -55100, -55015, -54929, -54843, -54758, -54673, -54587, -54502, -54417, -54333, -54248, -54163, -54079, -53994, -53910, -53826, -53741, -53657, -53574, -53490, -53406, -53322, -53239, -53156, -53072, -52989, -52906, -52823, -52740, -52657, -52575, -52492, -52410, -52327, -52245, -52163, -52081, -51999, -51917, -51835, -51754, -51672, -51591, -51509, -51428, -51347, -51266, -51185, -51104, -51023, -50942, -50862, -50781, -50701, -50621, -50540, -50460, -50380, -50300, -50221, -50141, -50061, -49982, -49902, -49823, -49744, -49664, -49585, -49506, -49427, -49349, -49270, -49191, -49113, -49034, -48956, -48878, -48799, -48721, -48643, -48565, -48488, -48410, -48332, -48255, -48177, -48100, -48022, -47945, -47868, -47791, -47714, -47637, -47560, -47484, -47407, -47331, -47254, -47178, -47102, -47025, -46949, -46873, -46797, -46721, -46646, -46570, -46494, -46419, -46343, -46268, -46193, -46118, -46042, -45967, -45892, -45818, -45743, -45668, -45593, -45519, -45444, -45370, -45296, -45221, -45147, -45073, -44999, -44925, -44851, -44778, -44704, -44630, -44557, -44483, -44410, -44337, -44263, -44190, -44117, -44044, -43971, -43898, -43826, -43753, -43680, -43608, -43535, -43463, -43390, -43318, -43246, -43174, -43102, -43030, -42958, -42886, -42814, -42743, -42671, -42600, -42528, -42457, -42385, -42314, -42243, -42172, -42101, -42030, -41959, -41888, -41817, -41747, -41676, -41605, -41535, -41465, -41394, -41324, -41254, -41184, -41113, -41043, -40973, -40904, -40834, -40764, -40694, -40625, -40555, -40486, -40416, -40347, -40278, -40208, -40139, -40070, -40001, -39932, -39863, -39794, -39726, -39657, -39588, -39520, -39451, -39383, -39314, -39246, -39178, -39110, -39042, -38973, -38905, -38837, -38770, -38702, -38634, -38566, -38499, -38431, -38364, -38296, -38229, -38161, -38094, -38027, -37960, -37893, -37826, -37759, -37692, -37625, -37558, -37491, -37425, -37358, -37291, -37225, -37158, -37092, -37026, -36959, -36893, -36827, -36761, -36695, -36629, -36563, -36497, -36431, -36365, -36300, -36234, -36168, -36103, -36037, -35972, -35907, -35841, -35776, -35711, -35646, -35580, -35515, -35450, -35385, -35321, -35256, -35191, -35126, -35062, -34997, -34932, -34868, -34803, -34739, -34675, -34610, -34546, -34482, -34418, -34354, -34289, -34225, -34162, -34098, -34034, -33970, -33906, -33843, -33779, -33715, -33652, -33588, -33525, -33461, -33398, -33335, -33272, -33208, -33145, -33082, -33019, -32956, -32893, -32830, -32767, -32705, -32642, -32579, -32516, -32454, -32391, -32329, -32266, -32204, -32141, -32079, -32017, -31955, -31892, -31830, -31768, -31706, -31644, -31582, -31520, -31458, -31396, -31335, -31273, -31211, -31150, -31088, -31026, -30965, -30904, -30842, -30781, -30719, -30658, -30597, -30536, -30474, -30413, -30352, -30291, -30230, -30169, -30108, -30048, -29987, -29926, -29865, -29805, -29744, -29683, -29623, -29562, -29502, -29441, -29381, -29321, -29260, -29200, -29140, -29080, -29020, -28959, -28899, -28839, -28779, -28719, -28660, -28600, -28540, -28480, -28420, -28361, -28301, -28241, -28182, -28122, -28063, -28003, -27944, -27884, -27825, -27766, -27707, -27647, -27588, -27529, -27470, -27411, -27352, -27293, -27234, -27175, -27116, -27057, -26998, -26940, -26881, -26822, -26763, -26705, -26646, -26588, -26529, -26471, -26412, -26354, -26295, -26237, -26179, -26120, -26062, -26004, -25946, -25888, -25830, -25772, -25714, -25656, -25598, -25540, -25482, -25424, -25366, -25308, -25251, -25193, -25135, -25078, -25020, -24962, -24905, -24847, -24790, -24732, -24675, -24618, -24560, -24503, -24446, -24389, -24331, -24274, -24217, -24160, -24103, -24046, -23989, -23932, -23875, -23818, -23761, -23704, -23647, -23591, -23534, -23477, -23420, -23364, -23307, -23250, -23194, -23137, -23081, -23024, -22968, -22911, -22855, -22799, -22742, -22686, -22630, -22573, -22517, -22461, -22405, -22349, -22293, -22237, -22181, -22125, -22069, -22013, -21957, -21901, -21845, -21789, -21733, -21678, -21622, -21566, -21510, -21455, -21399, -21343, -21288, -21232, -21177, -21121, -21066, -21010, -20955, -20900, -20844, -20789, -20734, -20678, -20623, -20568, -20513, -20457, -20402, -20347, -20292, -20237, -20182, -20127, -20072, -20017, -19962, -19907, -19852, -19797, -19742, -19688, -19633, -19578, -19523, -19469, -19414, -19359, -19305, -19250, -19195, -19141, -19086, -19032, -18977, -18923, -18868, -18814, -18760, -18705, -18651, -18597, -18542, -18488, -18434, -18380, -18325, -18271, -18217, -18163, -18109, -18055, -18001, -17946, -17892, -17838, -17784, -17731, -17677, -17623, -17569, -17515, -17461, -17407, -17353, -17300, -17246, -17192, -17138, -17085, -17031, -16977, -16924, -16870, -16817, -16763, -16710, -16656, -16603, -16549, -16496, -16442, -16389, -16335, -16282, -16229, -16175, -16122, -16069, -16015, -15962, -15909, -15856, -15802, -15749, -15696, -15643, -15590, -15537, -15484, -15431, -15378, -15325, -15272, -15219, -15166, -15113, -15060, -15007, -14954, -14901, -14848, -14795, -14743, -14690, -14637, -14584, -14531, -14479, -14426, -14373, -14321, -14268, -14215, -14163, -14110, -14057, -14005, -13952, -13900, -13847, -13795, -13742, -13690, -13637, -13585, -13533, -13480, -13428, -13375, -13323, -13271, -13218, -13166, -13114, -13062, -13009, -12957, -12905, -12853, -12800, -12748, -12696, -12644, -12592, -12540, -12488, -12436, -12383, -12331, -12279, -12227, -12175, -12123, -12071, -12019, -11967, -11916, -11864, -11812, -11760, -11708, -11656, -11604, -11552, -11501, -11449, -11397, -11345, -11293, -11242, -11190, -11138, -11086, -11035, -10983, -10931, -10880, -10828, -10777, -10725, -10673, -10622, -10570, -10519, -10467, -10415, -10364, -10312, -10261, -10209, -10158, -10106, -10055, -10004, -9952, -9901, -9849, -9798, -9747, -9695, -9644, -9592, -9541, -9490, -9438, -9387, -9336, -9285, -9233, -9182, -9131, -9080, -9028, -8977, -8926, -8875, -8824, -8772, -8721, -8670, -8619, -8568, -8517, -8466, -8414, -8363, -8312, -8261, -8210, -8159, -8108, -8057, -8006, -7955, -7904, -7853, -7802, -7751, -7700, -7649, -7598, -7547, -7496, -7445, -7395, -7344, -7293, -7242, -7191, -7140, -7089, -7038, -6988, -6937, -6886, -6835, -6784, -6733, -6683, -6632, -6581, -6530, -6480, -6429, -6378, -6327, -6277, -6226, -6175, -6124, -6074, -6023, -5972, -5922, -5871, -5820, -5770, -5719, -5668, -5618, -5567, -5517, -5466, -5415, -5365, -5314, -5264, -5213, -5162, -5112, -5061, -5011, -4960, -4910, -4859, -4808, -4758, -4707, -4657, -4606, -4556, -4505, -4455, -4404, -4354, -4303, -4253, -4202, -4152, -4101, -4051, -4001, -3950, -3900, -3849, -3799, -3748, -3698, -3648, -3597, -3547, -3496, -3446, -3395, -3345, -3295, -3244, -3194, -3144, -3093, -3043, -2992, -2942, -2892, -2841, -2791, -2741, -2690, -2640, -2590, -2539, -2489, -2439, -2388, -2338, -2288, -2237, -2187, -2137, -2086, -2036, -1986, -1935, -1885, -1835, -1784, -1734, -1684, -1633, -1583, -1533, -1483, -1432, -1382, -1332, -1281, -1231, -1181, -1131, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1131, 1181, 1231, 1281, 1332, 1382, 1432, 1483, 1533, 1583, 1633, 1684, 1734, 1784, 1835, 1885, 1935, 1986, 2036, 2086, 2137, 2187, 2237, 2288, 2338, 2388, 2439, 2489, 2539, 2590, 2640, 2690, 2741, 2791, 2841, 2892, 2942, 2992, 3043, 3093, 3144, 3194, 3244, 3295, 3345, 3395, 3446, 3496, 3547, 3597, 3648, 3698, 3748, 3799, 3849, 3900, 3950, 4001, 4051, 4101, 4152, 4202, 4253, 4303, 4354, 4404, 4455, 4505, 4556, 4606, 4657, 4707, 4758, 4808, 4859, 4910, 4960, 5011, 5061, 5112, 5162, 5213, 5264, 5314, 5365, 5415, 5466, 5517, 5567, 5618, 5668, 5719, 5770, 5820, 5871, 5922, 5972, 6023, 6074, 6124, 6175, 6226, 6277, 6327, 6378, 6429, 6480, 6530, 6581, 6632, 6683, 6733, 6784, 6835, 6886, 6937, 6988, 7038, 7089, 7140, 7191, 7242, 7293, 7344, 7395, 7445, 7496, 7547, 7598, 7649, 7700, 7751, 7802, 7853, 7904, 7955, 8006, 8057, 8108, 8159, 8210, 8261, 8312, 8363, 8414, 8466, 8517, 8568, 8619, 8670, 8721, 8772, 8824, 8875, 8926, 8977, 9028, 9080, 9131, 9182, 9233, 9285, 9336, 9387, 9438, 9490, 9541, 9592, 9644, 9695, 9747, 9798, 9849, 9901, 9952, 10004, 10055, 10106, 10158, 10209, 10261, 10312, 10364, 10415, 10467, 10519, 10570, 10622, 10673, 10725, 10777, 10828, 10880, 10931, 10983, 11035, 11086, 11138, 11190, 11242, 11293, 11345, 11397, 11449, 11501, 11552, 11604, 11656, 11708, 11760, 11812, 11864, 11916, 11967, 12019, 12071, 12123, 12175, 12227, 12279, 12331, 12383, 12436, 12488, 12540, 12592, 12644, 12696, 12748, 12800, 12853, 12905, 12957, 13009, 13062, 13114, 13166, 13218, 13271, 13323, 13375, 13428, 13480, 13533, 13585, 13637, 13690, 13742, 13795, 13847, 13900, 13952, 14005, 14057, 14110, 14163, 14215, 14268, 14321, 14373, 14426, 14479, 14531, 14584, 14637, 14690, 14743, 14795, 14848, 14901, 14954, 15007, 15060, 15113, 15166, 15219, 15272, 15325, 15378, 15431, 15484, 15537, 15590, 15643, 15696, 15749, 15802, 15856, 15909, 15962, 16015, 16069, 16122, 16175, 16229, 16282, 16335, 16389, 16442, 16496, 16549, 16603, 16656, 16710, 16763, 16817, 16870, 16924, 16977, 17031, 17085, 17138, 17192, 17246, 17300, 17353, 17407, 17461, 17515, 17569, 17623, 17677, 17731, 17784, 17838, 17892, 17946, 18001, 18055, 18109, 18163, 18217, 18271, 18325, 18380, 18434, 18488, 18542, 18597, 18651, 18705, 18760, 18814, 18868, 18923, 18977, 19032, 19086, 19141, 19195, 19250, 19305, 19359, 19414, 19469, 19523, 19578, 19633, 19688, 19742, 19797, 19852, 19907, 19962, 20017, 20072, 20127, 20182, 20237, 20292, 20347, 20402, 20457, 20513, 20568, 20623, 20678, 20734, 20789, 20844, 20900, 20955, 21010, 21066, 21121, 21177, 21232, 21288, 21343, 21399, 21455, 21510, 21566, 21622, 21678, 21733, 21789, 21845, 21901, 21957, 22013, 22069, 22125, 22181, 22237, 22293, 22349, 22405, 22461, 22517, 22573, 22630, 22686, 22742, 22799, 22855, 22911, 22968, 23024, 23081, 23137, 23194, 23250, 23307, 23364, 23420, 23477, 23534, 23591, 23647, 23704, 23761, 23818, 23875, 23932, 23989, 24046, 24103, 24160, 24217, 24274, 24331, 24389, 24446, 24503, 24560, 24618, 24675, 24732, 24790, 24847, 24905, 24962, 25020, 25078, 25135, 25193, 25251, 25308, 25366, 25424, 25482, 25540, 25598, 25656, 25714, 25772, 25830, 25888, 25946, 26004, 26062, 26120, 26179, 26237, 26295, 26354, 26412, 26471, 26529, 26588, 26646, 26705, 26763, 26822, 26881, 26940, 26998, 27057, 27116, 27175, 27234, 27293, 27352, 27411, 27470, 27529, 27588, 27647, 27707, 27766, 27825, 27884, 27944, 28003, 28063, 28122, 28182, 28241, 28301, 28361, 28420, 28480, 28540, 28600, 28660, 28719, 28779, 28839, 28899, 28959, 29020, 29080, 29140, 29200, 29260, 29321, 29381, 29441, 29502, 29562, 29623, 29683, 29744, 29805, 29865, 29926, 29987, 30048, 30108, 30169, 30230, 30291, 30352, 30413, 30474, 30536, 30597, 30658, 30719, 30781, 30842, 30904, 30965, 31026, 31088, 31150, 31211, 31273, 31335, 31396, 31458, 31520, 31582, 31644, 31706, 31768, 31830, 31892, 31955, 32017, 32079, 32141, 32204, 32266, 32329, 32391, 32454, 32516, 32579, 32642, 32705, 32767, 32830, 32893, 32956, 33019, 33082, 33145, 33208, 33272, 33335, 33398, 33461, 33525, 33588, 33652, 33715, 33779, 33843, 33906, 33970, 34034, 34098, 34162, 34225, 34289, 34354, 34418, 34482, 34546, 34610, 34675, 34739, 34803, 34868, 34932, 34997, 35062, 35126, 35191, 35256, 35321, 35385, 35450, 35515, 35580, 35646, 35711, 35776, 35841, 35907, 35972, 36037, 36103, 36168, 36234, 36300, 36365, 36431, 36497, 36563, 36629, 36695, 36761, 36827, 36893, 36959, 37026, 37092, 37158, 37225, 37291, 37358, 37425, 37491, 37558, 37625, 37692, 37759, 37826, 37893, 37960, 38027, 38094, 38161, 38229, 38296, 38364, 38431, 38499, 38566, 38634, 38702, 38770, 38837, 38905, 38973, 39042, 39110, 39178, 39246, 39314, 39383, 39451, 39520, 39588, 39657, 39726, 39794, 39863, 39932, 40001, 40070, 40139, 40208, 40278, 40347, 40416, 40486, 40555, 40625, 40694, 40764, 40834, 40904, 40973, 41043, 41113, 41184, 41254, 41324, 41394, 41465, 41535, 41605, 41676, 41747, 41817, 41888, 41959, 42030, 42101, 42172, 42243, 42314, 42385, 42457, 42528, 42600, 42671, 42743, 42814, 42886, 42958, 43030, 43102, 43174, 43246, 43318, 43390, 43463, 43535, 43608, 43680, 43753, 43826, 43898, 43971, 44044, 44117, 44190, 44263, 44337, 44410, 44483, 44557, 44630, 44704, 44778, 44851, 44925, 44999, 45073, 45147, 45221, 45296, 45370, 45444, 45519, 45593, 45668, 45743, 45818, 45892, 45967, 46042, 46118, 46193, 46268, 46343, 46419, 46494, 46570, 46646, 46721, 46797, 46873, 46949, 47025, 47102, 47178, 47254, 47331, 47407, 47484, 47560, 47637, 47714, 47791, 47868, 47945, 48022, 48100, 48177, 48255, 48332, 48410, 48488, 48565, 48643, 48721, 48799, 48878, 48956, 49034, 49113, 49191, 49270, 49349, 49427, 49506, 49585, 49664, 49744, 49823, 49902, 49982, 50061, 50141, 50221, 50300, 50380, 50460, 50540, 50621, 50701, 50781, 50862, 50942, 51023, 51104, 51185, 51266, 51347, 51428, 51509, 51591, 51672, 51754, 51835, 51917, 51999, 52081, 52163, 52245, 52327, 52410, 52492, 52575, 52657, 52740, 52823, 52906, 52989, 53072, 53156, 53239, 53322, 53406, 53490, 53574, 53657, 53741, 53826, 53910, 53994, 54079, 54163, 54248, 54333, 54417, 54502, 54587, 54673, 54758, 54843, 54929, 55015, 55100, 55186, 55272, 55358, 55444, 55531, 55617, 55704, 55790, 55877, 55964, 56051, 56138, 56225, 56312, 56400, 56487, 56575, 56663, 56751, 56839, 56927, 57015, 57104, 57192, 57281, 57369, 57458, 57547, 57636, 57725, 57815, 57904, 57994, 58083, 58173, 58263, 58353, 58443, 58534, 58624, 58715, 58805, 58896, 58987, 59078, 59169, 59261, 59352, 59444, 59535, 59627, 59719, 59811, 59903, 59996, 60088, 60181, 60273, 60366, 60459, 60552, 60646, 60739, 60833, 60926, 61020, 61114, 61208, 61302, 61396, 61491, 61585, 61680, 61775, 61870, 61965, 62060, 62156, 62251, 62347, 62443, 62539, 62635, 62731, 62828, 62924, 63021, 63118, 63215, 63312, 63409, 63506, 63604, 63702, 63799, 63897, 63996, 64094, 64192, 64291, 64389, 64488, 64587, 64687, 64786, 64885, 64985, 65085, 65185, 65285, 65385, 65485, 65586, 65686, 65787, 65888, 65989, 66091, 66192, 66294, 66396, 66498, 66600, 66702, 66804, 66907, 67010, 67113, 67216, 67319, 67422, 67526, 67629, 67733, 67837, 67942, 68046, 68151, 68255, 68360, 68465, 68570, 68676, 68781, 68887, 68993, 69099, 69205, 69312, 69418, 69525, 69632, 69739, 69846, 69954, 70061, 70169, 70277, 70385, 70494, 70602, 70711, 70820, 70929, 71038, 71147, 71257, 71367, 71477, 71587, 71697, 71808, 71918, 72029, 72140, 72252, 72363, 72475, 72587, 72699, 72811, 72923, 73036, 73149, 73262, 73375, 73488, 73602, 73715, 73829, 73944, 74058, 74172, 74287, 74402, 74517, 74633, 74748, 74864, 74980, 75096, 75213, 75329, 75446, 75563, 75680, 75797, 75915, 76033, 76151, 76269, 76388, 76506, 76625, 76744, 76864, 76983, 77103, 77223, 77343, 77463, 77584, 77705, 77826, 77947, 78068, 78190, 78312, 78434, 78557, 78679, 78802, 78925, 79048, 79172, 79296, 79420, 79544, 79668, 79793, 79918, 80043, 80168, 80294, 80420, 80546, 80672, 80799, 80925, 81053, 81180, 81307, 81435, 81563, 81691, 81820, 81949, 82078, 82207, 82336, 82466, 82596, 82726, 82857, 82987, 83118, 83250, 83381, 83513, 83645, 83777, 83910, 84043, 84176, 84309, 84443, 84576, 84710, 84845, 84980, 85114, 85250, 85385, 85521, 85657, 85793, 85930, 86066, 86204, 86341, 86479, 86616, 86755, 86893, 87032, 87171, 87310, 87450, 87590, 87730, 87871, 88011, 88152, 88294, 88435, 88577, 88720, 88862, 89005, 89148, 89292, 89435, 89579, 89724, 89868, 90013, 90158, 90304, 90450, 90596, 90742, 90889, 91036, 91184, 91332, 91480, 91628, 91777, 91926, 92075, 92225, 92375, 92525, 92675, 92826, 92978, 93129, 93281, 93434, 93586, 93739, 93892, 94046, 94200, 94354, 94509, 94664, 94819, 94975, 95131, 95287, 95444, 95601, 95758, 95916, 96074, 96233, 96391, 96551, 96710, 96870, 97030, 97191, 97352, 97513, 97675, 97837, 98000, 98163, 98326, 98489, 98653, 98818, 98982, 99148, 99313, 99479, 99645, 99812, 99979, 100146, 100314, 100482, 100651, 100820, 100990, 101159, 101330, 101500, 101671, 101843, 102015, 102187, 102360, 102533, 102706, 102880, 103054, 103229, 103404, 103580, 103756, 103933, 104109, 104287, 104465, 104643, 104821, 105000, 105180, 105360, 105540, 105721, 105902, 106084, 106266, 106449, 106632, 106816, 107000, 107184, 107369, 107555, 107741, 107927, 108114, 108301, 108489, 108677, 108866, 109055, 109245, 109435, 109626, 109817, 110008, 110200, 110393, 110586, 110780, 110974, 111169, 111364, 111560, 111756, 111952, 112150, 112347, 112546, 112744, 112944, 113143, 113344, 113545, 113746, 113948, 114151, 114354, 114557, 114761, 114966, 115171, 115377, 115583, 115790, 115998, 116206, 116414, 116623, 116833, 117044, 117254, 117466, 117678, 117891, 118104, 118318, 118532, 118747, 118963, 119179, 119396, 119613, 119831, 120050, 120269, 120489, 120709, 120930, 121152, 121374, 121597, 121821, 122045, 122270, 122496, 122722, 122949, 123176, 123404, 123633, 123863, 124093, 124324, 124555, 124787, 125020, 125254, 125488, 125723, 125959, 126195, 126432, 126669, 126908, 127147, 127387, 127627, 127869, 128111, 128353, 128597, 128841, 129086, 129332, 129578, 129825, 130073, 130322, 130571, 130821, 131072, 131324, 131576, 131830, 132084, 132339, 132594, 132851, 133108, 133366, 133625, 133884, 134145, 134406, 134668, 134931, 135195, 135459, 135725, 135991, 136258, 136526, 136795, 137065, 137335, 137607, 137879, 138152, 138426, 138701, 138977, 139254, 139532, 139810, 140090, 140370, 140651, 140934, 141217, 141501, 141786, 142072, 142359, 142647, 142936, 143226, 143517, 143808, 144101, 144395, 144690, 144986, 145282, 145580, 145879, 146179, 146480, 146782, 147084, 147388, 147693, 148000, 148307, 148615, 148924, 149235, 149546, 149859, 150172, 150487, 150803, 151120, 151438, 151757, 152077, 152399, 152722, 153045, 153370, 153697, 154024, 154352, 154682, 155013, 155345, 155678, 156013, 156349, 156686, 157024, 157363, 157704, 158046, 158389, 158734, 159079, 159427, 159775, 160125, 160476, 160828, 161182, 161537, 161893, 162251, 162610, 162970, 163332, 163695, 164060, 164426, 164793, 165162, 165532, 165904, 166277, 166651, 167027, 167405, 167784, 168164, 168546, 168930, 169315, 169701, 170089, 170479, 170870, 171263, 171657, 172053, 172451, 172850, 173251, 173653, 174057, 174463, 174870, 175279, 175690, 176102, 176516, 176932, 177349, 177769, 178190, 178612, 179037, 179463, 179891, 180321, 180753, 181186, 181622, 182059, 182498, 182939, 183382, 183827, 184274, 184722, 185173, 185625, 186080, 186536, 186995, 187455, 187918, 188382, 188849, 189318, 189789, 190261, 190736, 191213, 191693, 192174, 192658, 193143, 193631, 194122, 194614, 195109, 195606, 196105, 196606, 197110, 197616, 198125, 198636, 199149, 199664, 200182, 200703, 201226, 201751, 202279, 202809, 203342, 203878, 204416, 204956, 205500, 206045, 206594, 207145, 207699, 208255, 208815, 209376, 209941, 210509, 211079, 211652, 212228, 212807, 213389, 213973, 214561, 215151, 215745, 216341, 216941, 217544, 218149, 218758, 219370, 219985, 220603, 221225, 221849, 222477, 223108, 223743, 224381, 225022, 225666, 226314, 226966, 227621, 228279, 228941, 229606, 230275, 230948, 231624, 232304, 232988, 233676, 234367, 235062, 235761, 236463, 237170, 237881, 238595, 239314, 240036, 240763, 241493, 242228, 242967, 243711, 244458, 245210, 245966, 246727, 247492, 248261, 249035, 249813, 250596, 251384, 252176, 252973, 253774, 254581, 255392, 256208, 257029, 257855, 258686, 259522, 260363, 261209, 262060, 262917, 263779, 264646, 265519, 266397, 267280, 268169, 269064, 269965, 270871, 271782, 272700, 273624, 274553, 275489, 276430, 277378, 278332, 279292, 280258, 281231, 282210, 283195, 284188, 285186, 286192, 287204, 288223, 289249, 290282, 291322, 292369, 293423, 294485, 295554, 296630, 297714, 298805, 299904, 301011, 302126, 303248, 304379, 305517, 306664, 307819, 308983, 310154, 311335, 312524, 313721, 314928, 316143, 317368, 318601, 319844, 321097, 322358, 323629, 324910, 326201, 327502, 328812, 330133, 331464, 332805, 334157, 335519, 336892, 338276, 339671, 341078, 342495, 343924, 345364, 346816, 348280, 349756, 351244, 352744, 354257, 355783, 357321, 358872, 360436, 362013, 363604, 365208, 366826, 368459, 370105, 371765, 373440, 375130, 376835, 378555, 380290, 382040, 383807, 385589, 387387, 389202, 391034, 392882, 394747, 396630, 398530, 400448, 402384, 404338, 406311, 408303, 410314, 412344, 414395, 416465, 418555, 420666, 422798, 424951, 427125, 429321, 431540, 433781, 436045, 438332, 440643, 442978, 445337, 447720, 450129, 452564, 455024, 457511, 460024, 462565, 465133, 467730, 470355, 473009, 475692, 478406, 481150, 483925, 486732, 489571, 492443, 495348, 498287, 501261, 504269, 507313, 510394, 513512, 516667, 519861, 523094, 526366, 529680, 533034, 536431, 539870, 543354, 546881, 550455, 554074, 557741, 561456, 565221, 569035, 572901, 576818, 580789, 584815, 588896, 593033, 597229, 601483, 605798, 610174, 614613, 619117, 623686, 628323, 633028, 637803, 642651, 647572, 652568, 657640, 662792, 668024, 673338, 678737, 684223, 689797, 695462, 701219, 707072, 713023, 719074, 725227, 731486, 737853, 744331, 750922, 757631, 764460, 771411, 778490, 785699, 793041, 800521, 808143, 815910, 823827, 831898, 840127, 848520, 857081, 865817, 874730, 883829, 893117, 902602, 912289, 922186, 932298, 942633, 953199, 964003, 975054, 986361, 997931, 1009774, 1021901, 1034322, 1047046, 1060087, 1073455, 1087164, 1101225, 1115654, 1130465, 1145673, 1161294, 1177345, 1193846, 1210813, 1228269, 1246234, 1264730, 1283783, 1303416, 1323658, 1344537, 1366084, 1388330, 1411312, 1435065, 1459630, 1485049, 1511367, 1538632, 1566898, 1596220, 1626658, 1658278, 1691149, 1725348, 1760956, 1798063, 1836758, 1877161, 1919378, 1963536, 2009771, 2058233, 2109087, 2162516, 2218719, 2277919, 2340362, 2406322, 2476104, 2550052, 2628549, 2712030, 2800983, 2895966, 2997613, 3106651, 3223918, 3350381, 3487165, 3635590, 3797206, 3973855, 4167737, 4381502, 4618375, 4882318, 5178251, 5512368, 5892567, 6329090, 6835455, 7429880, 8137527, 8994149, 10052327, 11392683, 13145455, 15535599, 18988036, 24413316, 34178904, 56965752, 170910304 }; int finesine[10240] = { 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3541, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5748, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22433, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30426, 30471, 30515, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36555, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40300, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47860, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50065, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53911, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54308, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64601, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65534, 65534, 65534, 65533, 65533, 65532, 65532, 65531, 65531, 65530, 65530, 65529, 65528, 65527, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65516, 65515, 65514, 65513, 65511, 65510, 65508, 65507, 65505, 65504, 65502, 65501, 65499, 65497, 65496, 65494, 65492, 65490, 65488, 65486, 65484, 65482, 65480, 65478, 65476, 65474, 65472, 65470, 65467, 65465, 65463, 65460, 65458, 65455, 65453, 65450, 65448, 65445, 65442, 65440, 65437, 65434, 65431, 65429, 65426, 65423, 65420, 65417, 65414, 65411, 65408, 65404, 65401, 65398, 65395, 65391, 65388, 65385, 65381, 65378, 65374, 65371, 65367, 65363, 65360, 65356, 65352, 65349, 65345, 65341, 65337, 65333, 65329, 65325, 65321, 65317, 65313, 65309, 65305, 65300, 65296, 65292, 65287, 65283, 65279, 65274, 65270, 65265, 65260, 65256, 65251, 65246, 65242, 65237, 65232, 65227, 65222, 65217, 65212, 65207, 65202, 65197, 65192, 65187, 65182, 65177, 65171, 65166, 65161, 65155, 65150, 65144, 65139, 65133, 65128, 65122, 65117, 65111, 65105, 65099, 65094, 65088, 65082, 65076, 65070, 65064, 65058, 65052, 65046, 65040, 65033, 65027, 65021, 65015, 65008, 65002, 64995, 64989, 64982, 64976, 64969, 64963, 64956, 64949, 64943, 64936, 64929, 64922, 64915, 64908, 64902, 64895, 64887, 64880, 64873, 64866, 64859, 64852, 64844, 64837, 64830, 64822, 64815, 64808, 64800, 64793, 64785, 64777, 64770, 64762, 64754, 64747, 64739, 64731, 64723, 64715, 64707, 64699, 64691, 64683, 64675, 64667, 64659, 64651, 64642, 64634, 64626, 64617, 64609, 64600, 64592, 64584, 64575, 64566, 64558, 64549, 64540, 64532, 64523, 64514, 64505, 64496, 64487, 64478, 64469, 64460, 64451, 64442, 64433, 64424, 64414, 64405, 64396, 64387, 64377, 64368, 64358, 64349, 64339, 64330, 64320, 64310, 64301, 64291, 64281, 64271, 64261, 64252, 64242, 64232, 64222, 64212, 64202, 64192, 64181, 64171, 64161, 64151, 64140, 64130, 64120, 64109, 64099, 64088, 64078, 64067, 64057, 64046, 64035, 64025, 64014, 64003, 63992, 63981, 63971, 63960, 63949, 63938, 63927, 63915, 63904, 63893, 63882, 63871, 63859, 63848, 63837, 63825, 63814, 63803, 63791, 63779, 63768, 63756, 63745, 63733, 63721, 63709, 63698, 63686, 63674, 63662, 63650, 63638, 63626, 63614, 63602, 63590, 63578, 63565, 63553, 63541, 63528, 63516, 63504, 63491, 63479, 63466, 63454, 63441, 63429, 63416, 63403, 63390, 63378, 63365, 63352, 63339, 63326, 63313, 63300, 63287, 63274, 63261, 63248, 63235, 63221, 63208, 63195, 63182, 63168, 63155, 63141, 63128, 63114, 63101, 63087, 63074, 63060, 63046, 63032, 63019, 63005, 62991, 62977, 62963, 62949, 62935, 62921, 62907, 62893, 62879, 62865, 62850, 62836, 62822, 62808, 62793, 62779, 62764, 62750, 62735, 62721, 62706, 62692, 62677, 62662, 62648, 62633, 62618, 62603, 62588, 62573, 62558, 62543, 62528, 62513, 62498, 62483, 62468, 62453, 62437, 62422, 62407, 62391, 62376, 62360, 62345, 62329, 62314, 62298, 62283, 62267, 62251, 62236, 62220, 62204, 62188, 62172, 62156, 62141, 62125, 62108, 62092, 62076, 62060, 62044, 62028, 62012, 61995, 61979, 61963, 61946, 61930, 61913, 61897, 61880, 61864, 61847, 61831, 61814, 61797, 61780, 61764, 61747, 61730, 61713, 61696, 61679, 61662, 61645, 61628, 61611, 61594, 61577, 61559, 61542, 61525, 61507, 61490, 61473, 61455, 61438, 61420, 61403, 61385, 61367, 61350, 61332, 61314, 61297, 61279, 61261, 61243, 61225, 61207, 61189, 61171, 61153, 61135, 61117, 61099, 61081, 61062, 61044, 61026, 61007, 60989, 60971, 60952, 60934, 60915, 60897, 60878, 60859, 60841, 60822, 60803, 60785, 60766, 60747, 60728, 60709, 60690, 60671, 60652, 60633, 60614, 60595, 60576, 60556, 60537, 60518, 60499, 60479, 60460, 60441, 60421, 60402, 60382, 60363, 60343, 60323, 60304, 60284, 60264, 60244, 60225, 60205, 60185, 60165, 60145, 60125, 60105, 60085, 60065, 60045, 60025, 60004, 59984, 59964, 59944, 59923, 59903, 59883, 59862, 59842, 59821, 59801, 59780, 59759, 59739, 59718, 59697, 59677, 59656, 59635, 59614, 59593, 59572, 59551, 59530, 59509, 59488, 59467, 59446, 59425, 59404, 59382, 59361, 59340, 59318, 59297, 59276, 59254, 59233, 59211, 59190, 59168, 59146, 59125, 59103, 59081, 59059, 59038, 59016, 58994, 58972, 58950, 58928, 58906, 58884, 58862, 58840, 58818, 58795, 58773, 58751, 58729, 58706, 58684, 58662, 58639, 58617, 58594, 58572, 58549, 58527, 58504, 58481, 58459, 58436, 58413, 58390, 58367, 58345, 58322, 58299, 58276, 58253, 58230, 58207, 58183, 58160, 58137, 58114, 58091, 58067, 58044, 58021, 57997, 57974, 57950, 57927, 57903, 57880, 57856, 57833, 57809, 57785, 57762, 57738, 57714, 57690, 57666, 57642, 57618, 57594, 57570, 57546, 57522, 57498, 57474, 57450, 57426, 57402, 57377, 57353, 57329, 57304, 57280, 57255, 57231, 57206, 57182, 57157, 57133, 57108, 57083, 57059, 57034, 57009, 56984, 56959, 56935, 56910, 56885, 56860, 56835, 56810, 56785, 56760, 56734, 56709, 56684, 56659, 56633, 56608, 56583, 56557, 56532, 56507, 56481, 56456, 56430, 56404, 56379, 56353, 56328, 56302, 56276, 56250, 56225, 56199, 56173, 56147, 56121, 56095, 56069, 56043, 56017, 55991, 55965, 55938, 55912, 55886, 55860, 55833, 55807, 55781, 55754, 55728, 55701, 55675, 55648, 55622, 55595, 55569, 55542, 55515, 55489, 55462, 55435, 55408, 55381, 55354, 55327, 55300, 55274, 55246, 55219, 55192, 55165, 55138, 55111, 55084, 55056, 55029, 55002, 54974, 54947, 54920, 54892, 54865, 54837, 54810, 54782, 54755, 54727, 54699, 54672, 54644, 54616, 54588, 54560, 54533, 54505, 54477, 54449, 54421, 54393, 54365, 54337, 54308, 54280, 54252, 54224, 54196, 54167, 54139, 54111, 54082, 54054, 54026, 53997, 53969, 53940, 53911, 53883, 53854, 53826, 53797, 53768, 53739, 53711, 53682, 53653, 53624, 53595, 53566, 53537, 53508, 53479, 53450, 53421, 53392, 53363, 53334, 53304, 53275, 53246, 53216, 53187, 53158, 53128, 53099, 53069, 53040, 53010, 52981, 52951, 52922, 52892, 52862, 52832, 52803, 52773, 52743, 52713, 52683, 52653, 52624, 52594, 52564, 52534, 52503, 52473, 52443, 52413, 52383, 52353, 52322, 52292, 52262, 52231, 52201, 52171, 52140, 52110, 52079, 52049, 52018, 51988, 51957, 51926, 51896, 51865, 51834, 51803, 51773, 51742, 51711, 51680, 51649, 51618, 51587, 51556, 51525, 51494, 51463, 51432, 51401, 51369, 51338, 51307, 51276, 51244, 51213, 51182, 51150, 51119, 51087, 51056, 51024, 50993, 50961, 50929, 50898, 50866, 50834, 50803, 50771, 50739, 50707, 50675, 50644, 50612, 50580, 50548, 50516, 50484, 50452, 50420, 50387, 50355, 50323, 50291, 50259, 50226, 50194, 50162, 50129, 50097, 50065, 50032, 50000, 49967, 49935, 49902, 49869, 49837, 49804, 49771, 49739, 49706, 49673, 49640, 49608, 49575, 49542, 49509, 49476, 49443, 49410, 49377, 49344, 49311, 49278, 49244, 49211, 49178, 49145, 49112, 49078, 49045, 49012, 48978, 48945, 48911, 48878, 48844, 48811, 48777, 48744, 48710, 48676, 48643, 48609, 48575, 48542, 48508, 48474, 48440, 48406, 48372, 48338, 48304, 48271, 48237, 48202, 48168, 48134, 48100, 48066, 48032, 47998, 47963, 47929, 47895, 47860, 47826, 47792, 47757, 47723, 47688, 47654, 47619, 47585, 47550, 47516, 47481, 47446, 47412, 47377, 47342, 47308, 47273, 47238, 47203, 47168, 47133, 47098, 47063, 47028, 46993, 46958, 46923, 46888, 46853, 46818, 46783, 46747, 46712, 46677, 46642, 46606, 46571, 46536, 46500, 46465, 46429, 46394, 46358, 46323, 46287, 46252, 46216, 46180, 46145, 46109, 46073, 46037, 46002, 45966, 45930, 45894, 45858, 45822, 45786, 45750, 45714, 45678, 45642, 45606, 45570, 45534, 45498, 45462, 45425, 45389, 45353, 45316, 45280, 45244, 45207, 45171, 45135, 45098, 45062, 45025, 44989, 44952, 44915, 44879, 44842, 44806, 44769, 44732, 44695, 44659, 44622, 44585, 44548, 44511, 44474, 44437, 44400, 44363, 44326, 44289, 44252, 44215, 44178, 44141, 44104, 44067, 44029, 43992, 43955, 43918, 43880, 43843, 43806, 43768, 43731, 43693, 43656, 43618, 43581, 43543, 43506, 43468, 43430, 43393, 43355, 43317, 43280, 43242, 43204, 43166, 43128, 43091, 43053, 43015, 42977, 42939, 42901, 42863, 42825, 42787, 42749, 42711, 42672, 42634, 42596, 42558, 42520, 42481, 42443, 42405, 42366, 42328, 42290, 42251, 42213, 42174, 42136, 42097, 42059, 42020, 41982, 41943, 41904, 41866, 41827, 41788, 41750, 41711, 41672, 41633, 41595, 41556, 41517, 41478, 41439, 41400, 41361, 41322, 41283, 41244, 41205, 41166, 41127, 41088, 41048, 41009, 40970, 40931, 40891, 40852, 40813, 40773, 40734, 40695, 40655, 40616, 40576, 40537, 40497, 40458, 40418, 40379, 40339, 40300, 40260, 40220, 40180, 40141, 40101, 40061, 40021, 39982, 39942, 39902, 39862, 39822, 39782, 39742, 39702, 39662, 39622, 39582, 39542, 39502, 39462, 39422, 39382, 39341, 39301, 39261, 39221, 39180, 39140, 39100, 39059, 39019, 38979, 38938, 38898, 38857, 38817, 38776, 38736, 38695, 38655, 38614, 38573, 38533, 38492, 38451, 38411, 38370, 38329, 38288, 38248, 38207, 38166, 38125, 38084, 38043, 38002, 37961, 37920, 37879, 37838, 37797, 37756, 37715, 37674, 37633, 37592, 37551, 37509, 37468, 37427, 37386, 37344, 37303, 37262, 37220, 37179, 37137, 37096, 37055, 37013, 36972, 36930, 36889, 36847, 36805, 36764, 36722, 36681, 36639, 36597, 36556, 36514, 36472, 36430, 36388, 36347, 36305, 36263, 36221, 36179, 36137, 36095, 36053, 36011, 35969, 35927, 35885, 35843, 35801, 35759, 35717, 35675, 35633, 35590, 35548, 35506, 35464, 35421, 35379, 35337, 35294, 35252, 35210, 35167, 35125, 35082, 35040, 34997, 34955, 34912, 34870, 34827, 34785, 34742, 34699, 34657, 34614, 34571, 34529, 34486, 34443, 34400, 34358, 34315, 34272, 34229, 34186, 34143, 34100, 34057, 34015, 33972, 33929, 33886, 33843, 33799, 33756, 33713, 33670, 33627, 33584, 33541, 33498, 33454, 33411, 33368, 33325, 33281, 33238, 33195, 33151, 33108, 33065, 33021, 32978, 32934, 32891, 32847, 32804, 32760, 32717, 32673, 32630, 32586, 32542, 32499, 32455, 32411, 32368, 32324, 32280, 32236, 32193, 32149, 32105, 32061, 32017, 31974, 31930, 31886, 31842, 31798, 31754, 31710, 31666, 31622, 31578, 31534, 31490, 31446, 31402, 31357, 31313, 31269, 31225, 31181, 31136, 31092, 31048, 31004, 30959, 30915, 30871, 30826, 30782, 30738, 30693, 30649, 30604, 30560, 30515, 30471, 30426, 30382, 30337, 30293, 30248, 30204, 30159, 30114, 30070, 30025, 29980, 29936, 29891, 29846, 29801, 29757, 29712, 29667, 29622, 29577, 29533, 29488, 29443, 29398, 29353, 29308, 29263, 29218, 29173, 29128, 29083, 29038, 28993, 28948, 28903, 28858, 28812, 28767, 28722, 28677, 28632, 28586, 28541, 28496, 28451, 28405, 28360, 28315, 28269, 28224, 28179, 28133, 28088, 28042, 27997, 27952, 27906, 27861, 27815, 27770, 27724, 27678, 27633, 27587, 27542, 27496, 27450, 27405, 27359, 27313, 27268, 27222, 27176, 27131, 27085, 27039, 26993, 26947, 26902, 26856, 26810, 26764, 26718, 26672, 26626, 26580, 26534, 26488, 26442, 26396, 26350, 26304, 26258, 26212, 26166, 26120, 26074, 26028, 25982, 25936, 25889, 25843, 25797, 25751, 25705, 25658, 25612, 25566, 25520, 25473, 25427, 25381, 25334, 25288, 25241, 25195, 25149, 25102, 25056, 25009, 24963, 24916, 24870, 24823, 24777, 24730, 24684, 24637, 24591, 24544, 24497, 24451, 24404, 24357, 24311, 24264, 24217, 24171, 24124, 24077, 24030, 23984, 23937, 23890, 23843, 23796, 23750, 23703, 23656, 23609, 23562, 23515, 23468, 23421, 23374, 23327, 23280, 23233, 23186, 23139, 23092, 23045, 22998, 22951, 22904, 22857, 22810, 22763, 22716, 22668, 22621, 22574, 22527, 22480, 22433, 22385, 22338, 22291, 22243, 22196, 22149, 22102, 22054, 22007, 21960, 21912, 21865, 21817, 21770, 21723, 21675, 21628, 21580, 21533, 21485, 21438, 21390, 21343, 21295, 21248, 21200, 21153, 21105, 21057, 21010, 20962, 20915, 20867, 20819, 20772, 20724, 20676, 20629, 20581, 20533, 20485, 20438, 20390, 20342, 20294, 20246, 20199, 20151, 20103, 20055, 20007, 19959, 19912, 19864, 19816, 19768, 19720, 19672, 19624, 19576, 19528, 19480, 19432, 19384, 19336, 19288, 19240, 19192, 19144, 19096, 19048, 19000, 18951, 18903, 18855, 18807, 18759, 18711, 18663, 18614, 18566, 18518, 18470, 18421, 18373, 18325, 18277, 18228, 18180, 18132, 18084, 18035, 17987, 17939, 17890, 17842, 17793, 17745, 17697, 17648, 17600, 17551, 17503, 17455, 17406, 17358, 17309, 17261, 17212, 17164, 17115, 17067, 17018, 16970, 16921, 16872, 16824, 16775, 16727, 16678, 16629, 16581, 16532, 16484, 16435, 16386, 16338, 16289, 16240, 16191, 16143, 16094, 16045, 15997, 15948, 15899, 15850, 15802, 15753, 15704, 15655, 15606, 15557, 15509, 15460, 15411, 15362, 15313, 15264, 15215, 15167, 15118, 15069, 15020, 14971, 14922, 14873, 14824, 14775, 14726, 14677, 14628, 14579, 14530, 14481, 14432, 14383, 14334, 14285, 14236, 14187, 14138, 14089, 14040, 13990, 13941, 13892, 13843, 13794, 13745, 13696, 13646, 13597, 13548, 13499, 13450, 13401, 13351, 13302, 13253, 13204, 13154, 13105, 13056, 13007, 12957, 12908, 12859, 12810, 12760, 12711, 12662, 12612, 12563, 12514, 12464, 12415, 12366, 12316, 12267, 12218, 12168, 12119, 12069, 12020, 11970, 11921, 11872, 11822, 11773, 11723, 11674, 11624, 11575, 11525, 11476, 11426, 11377, 11327, 11278, 11228, 11179, 11129, 11080, 11030, 10981, 10931, 10882, 10832, 10782, 10733, 10683, 10634, 10584, 10534, 10485, 10435, 10386, 10336, 10286, 10237, 10187, 10137, 10088, 10038, 9988, 9939, 9889, 9839, 9790, 9740, 9690, 9640, 9591, 9541, 9491, 9442, 9392, 9342, 9292, 9243, 9193, 9143, 9093, 9043, 8994, 8944, 8894, 8844, 8794, 8745, 8695, 8645, 8595, 8545, 8496, 8446, 8396, 8346, 8296, 8246, 8196, 8147, 8097, 8047, 7997, 7947, 7897, 7847, 7797, 7747, 7697, 7648, 7598, 7548, 7498, 7448, 7398, 7348, 7298, 7248, 7198, 7148, 7098, 7048, 6998, 6948, 6898, 6848, 6798, 6748, 6698, 6648, 6598, 6548, 6498, 6448, 6398, 6348, 6298, 6248, 6198, 6148, 6098, 6048, 5998, 5948, 5898, 5848, 5798, 5748, 5697, 5647, 5597, 5547, 5497, 5447, 5397, 5347, 5297, 5247, 5197, 5146, 5096, 5046, 4996, 4946, 4896, 4846, 4796, 4745, 4695, 4645, 4595, 4545, 4495, 4445, 4394, 4344, 4294, 4244, 4194, 4144, 4093, 4043, 3993, 3943, 3893, 3843, 3792, 3742, 3692, 3642, 3592, 3541, 3491, 3441, 3391, 3341, 3291, 3240, 3190, 3140, 3090, 3039, 2989, 2939, 2889, 2839, 2788, 2738, 2688, 2638, 2587, 2537, 2487, 2437, 2387, 2336, 2286, 2236, 2186, 2135, 2085, 2035, 1985, 1934, 1884, 1834, 1784, 1733, 1683, 1633, 1583, 1532, 1482, 1432, 1382, 1331, 1281, 1231, 1181, 1130, 1080, 1030, 980, 929, 879, 829, 779, 728, 678, 628, 578, 527, 477, 427, 376, 326, 276, 226, 175, 125, 75, 25, -25, -75, -125, -175, -226, -276, -326, -376, -427, -477, -527, -578, -628, -678, -728, -779, -829, -879, -929, -980, -1030, -1080, -1130, -1181, -1231, -1281, -1331, -1382, -1432, -1482, -1532, -1583, -1633, -1683, -1733, -1784, -1834, -1884, -1934, -1985, -2035, -2085, -2135, -2186, -2236, -2286, -2336, -2387, -2437, -2487, -2537, -2588, -2638, -2688, -2738, -2788, -2839, -2889, -2939, -2989, -3039, -3090, -3140, -3190, -3240, -3291, -3341, -3391, -3441, -3491, -3541, -3592, -3642, -3692, -3742, -3792, -3843, -3893, -3943, -3993, -4043, -4093, -4144, -4194, -4244, -4294, -4344, -4394, -4445, -4495, -4545, -4595, -4645, -4695, -4745, -4796, -4846, -4896, -4946, -4996, -5046, -5096, -5146, -5197, -5247, -5297, -5347, -5397, -5447, -5497, -5547, -5597, -5647, -5697, -5748, -5798, -5848, -5898, -5948, -5998, -6048, -6098, -6148, -6198, -6248, -6298, -6348, -6398, -6448, -6498, -6548, -6598, -6648, -6698, -6748, -6798, -6848, -6898, -6948, -6998, -7048, -7098, -7148, -7198, -7248, -7298, -7348, -7398, -7448, -7498, -7548, -7598, -7648, -7697, -7747, -7797, -7847, -7897, -7947, -7997, -8047, -8097, -8147, -8196, -8246, -8296, -8346, -8396, -8446, -8496, -8545, -8595, -8645, -8695, -8745, -8794, -8844, -8894, -8944, -8994, -9043, -9093, -9143, -9193, -9243, -9292, -9342, -9392, -9442, -9491, -9541, -9591, -9640, -9690, -9740, -9790, -9839, -9889, -9939, -9988, -10038, -10088, -10137, -10187, -10237, -10286, -10336, -10386, -10435, -10485, -10534, -10584, -10634, -10683, -10733, -10782, -10832, -10882, -10931, -10981, -11030, -11080, -11129, -11179, -11228, -11278, -11327, -11377, -11426, -11476, -11525, -11575, -11624, -11674, -11723, -11773, -11822, -11872, -11921, -11970, -12020, -12069, -12119, -12168, -12218, -12267, -12316, -12366, -12415, -12464, -12514, -12563, -12612, -12662, -12711, -12760, -12810, -12859, -12908, -12957, -13007, -13056, -13105, -13154, -13204, -13253, -13302, -13351, -13401, -13450, -13499, -13548, -13597, -13647, -13696, -13745, -13794, -13843, -13892, -13941, -13990, -14040, -14089, -14138, -14187, -14236, -14285, -14334, -14383, -14432, -14481, -14530, -14579, -14628, -14677, -14726, -14775, -14824, -14873, -14922, -14971, -15020, -15069, -15118, -15167, -15215, -15264, -15313, -15362, -15411, -15460, -15509, -15557, -15606, -15655, -15704, -15753, -15802, -15850, -15899, -15948, -15997, -16045, -16094, -16143, -16191, -16240, -16289, -16338, -16386, -16435, -16484, -16532, -16581, -16629, -16678, -16727, -16775, -16824, -16872, -16921, -16970, -17018, -17067, -17115, -17164, -17212, -17261, -17309, -17358, -17406, -17455, -17503, -17551, -17600, -17648, -17697, -17745, -17793, -17842, -17890, -17939, -17987, -18035, -18084, -18132, -18180, -18228, -18277, -18325, -18373, -18421, -18470, -18518, -18566, -18614, -18663, -18711, -18759, -18807, -18855, -18903, -18951, -19000, -19048, -19096, -19144, -19192, -19240, -19288, -19336, -19384, -19432, -19480, -19528, -19576, -19624, -19672, -19720, -19768, -19816, -19864, -19912, -19959, -20007, -20055, -20103, -20151, -20199, -20246, -20294, -20342, -20390, -20438, -20485, -20533, -20581, -20629, -20676, -20724, -20772, -20819, -20867, -20915, -20962, -21010, -21057, -21105, -21153, -21200, -21248, -21295, -21343, -21390, -21438, -21485, -21533, -21580, -21628, -21675, -21723, -21770, -21817, -21865, -21912, -21960, -22007, -22054, -22102, -22149, -22196, -22243, -22291, -22338, -22385, -22433, -22480, -22527, -22574, -22621, -22668, -22716, -22763, -22810, -22857, -22904, -22951, -22998, -23045, -23092, -23139, -23186, -23233, -23280, -23327, -23374, -23421, -23468, -23515, -23562, -23609, -23656, -23703, -23750, -23796, -23843, -23890, -23937, -23984, -24030, -24077, -24124, -24171, -24217, -24264, -24311, -24357, -24404, -24451, -24497, -24544, -24591, -24637, -24684, -24730, -24777, -24823, -24870, -24916, -24963, -25009, -25056, -25102, -25149, -25195, -25241, -25288, -25334, -25381, -25427, -25473, -25520, -25566, -25612, -25658, -25705, -25751, -25797, -25843, -25889, -25936, -25982, -26028, -26074, -26120, -26166, -26212, -26258, -26304, -26350, -26396, -26442, -26488, -26534, -26580, -26626, -26672, -26718, -26764, -26810, -26856, -26902, -26947, -26993, -27039, -27085, -27131, -27176, -27222, -27268, -27313, -27359, -27405, -27450, -27496, -27542, -27587, -27633, -27678, -27724, -27770, -27815, -27861, -27906, -27952, -27997, -28042, -28088, -28133, -28179, -28224, -28269, -28315, -28360, -28405, -28451, -28496, -28541, -28586, -28632, -28677, -28722, -28767, -28812, -28858, -28903, -28948, -28993, -29038, -29083, -29128, -29173, -29218, -29263, -29308, -29353, -29398, -29443, -29488, -29533, -29577, -29622, -29667, -29712, -29757, -29801, -29846, -29891, -29936, -29980, -30025, -30070, -30114, -30159, -30204, -30248, -30293, -30337, -30382, -30426, -30471, -30515, -30560, -30604, -30649, -30693, -30738, -30782, -30826, -30871, -30915, -30959, -31004, -31048, -31092, -31136, -31181, -31225, -31269, -31313, -31357, -31402, -31446, -31490, -31534, -31578, -31622, -31666, -31710, -31754, -31798, -31842, -31886, -31930, -31974, -32017, -32061, -32105, -32149, -32193, -32236, -32280, -32324, -32368, -32411, -32455, -32499, -32542, -32586, -32630, -32673, -32717, -32760, -32804, -32847, -32891, -32934, -32978, -33021, -33065, -33108, -33151, -33195, -33238, -33281, -33325, -33368, -33411, -33454, -33498, -33541, -33584, -33627, -33670, -33713, -33756, -33799, -33843, -33886, -33929, -33972, -34015, -34057, -34100, -34143, -34186, -34229, -34272, -34315, -34358, -34400, -34443, -34486, -34529, -34571, -34614, -34657, -34699, -34742, -34785, -34827, -34870, -34912, -34955, -34997, -35040, -35082, -35125, -35167, -35210, -35252, -35294, -35337, -35379, -35421, -35464, -35506, -35548, -35590, -35633, -35675, -35717, -35759, -35801, -35843, -35885, -35927, -35969, -36011, -36053, -36095, -36137, -36179, -36221, -36263, -36305, -36347, -36388, -36430, -36472, -36514, -36555, -36597, -36639, -36681, -36722, -36764, -36805, -36847, -36889, -36930, -36972, -37013, -37055, -37096, -37137, -37179, -37220, -37262, -37303, -37344, -37386, -37427, -37468, -37509, -37551, -37592, -37633, -37674, -37715, -37756, -37797, -37838, -37879, -37920, -37961, -38002, -38043, -38084, -38125, -38166, -38207, -38248, -38288, -38329, -38370, -38411, -38451, -38492, -38533, -38573, -38614, -38655, -38695, -38736, -38776, -38817, -38857, -38898, -38938, -38979, -39019, -39059, -39100, -39140, -39180, -39221, -39261, -39301, -39341, -39382, -39422, -39462, -39502, -39542, -39582, -39622, -39662, -39702, -39742, -39782, -39822, -39862, -39902, -39942, -39982, -40021, -40061, -40101, -40141, -40180, -40220, -40260, -40299, -40339, -40379, -40418, -40458, -40497, -40537, -40576, -40616, -40655, -40695, -40734, -40773, -40813, -40852, -40891, -40931, -40970, -41009, -41048, -41087, -41127, -41166, -41205, -41244, -41283, -41322, -41361, -41400, -41439, -41478, -41517, -41556, -41595, -41633, -41672, -41711, -41750, -41788, -41827, -41866, -41904, -41943, -41982, -42020, -42059, -42097, -42136, -42174, -42213, -42251, -42290, -42328, -42366, -42405, -42443, -42481, -42520, -42558, -42596, -42634, -42672, -42711, -42749, -42787, -42825, -42863, -42901, -42939, -42977, -43015, -43053, -43091, -43128, -43166, -43204, -43242, -43280, -43317, -43355, -43393, -43430, -43468, -43506, -43543, -43581, -43618, -43656, -43693, -43731, -43768, -43806, -43843, -43880, -43918, -43955, -43992, -44029, -44067, -44104, -44141, -44178, -44215, -44252, -44289, -44326, -44363, -44400, -44437, -44474, -44511, -44548, -44585, -44622, -44659, -44695, -44732, -44769, -44806, -44842, -44879, -44915, -44952, -44989, -45025, -45062, -45098, -45135, -45171, -45207, -45244, -45280, -45316, -45353, -45389, -45425, -45462, -45498, -45534, -45570, -45606, -45642, -45678, -45714, -45750, -45786, -45822, -45858, -45894, -45930, -45966, -46002, -46037, -46073, -46109, -46145, -46180, -46216, -46252, -46287, -46323, -46358, -46394, -46429, -46465, -46500, -46536, -46571, -46606, -46642, -46677, -46712, -46747, -46783, -46818, -46853, -46888, -46923, -46958, -46993, -47028, -47063, -47098, -47133, -47168, -47203, -47238, -47273, -47308, -47342, -47377, -47412, -47446, -47481, -47516, -47550, -47585, -47619, -47654, -47688, -47723, -47757, -47792, -47826, -47860, -47895, -47929, -47963, -47998, -48032, -48066, -48100, -48134, -48168, -48202, -48236, -48271, -48304, -48338, -48372, -48406, -48440, -48474, -48508, -48542, -48575, -48609, -48643, -48676, -48710, -48744, -48777, -48811, -48844, -48878, -48911, -48945, -48978, -49012, -49045, -49078, -49112, -49145, -49178, -49211, -49244, -49278, -49311, -49344, -49377, -49410, -49443, -49476, -49509, -49542, -49575, -49608, -49640, -49673, -49706, -49739, -49771, -49804, -49837, -49869, -49902, -49935, -49967, -50000, -50032, -50065, -50097, -50129, -50162, -50194, -50226, -50259, -50291, -50323, -50355, -50387, -50420, -50452, -50484, -50516, -50548, -50580, -50612, -50644, -50675, -50707, -50739, -50771, -50803, -50834, -50866, -50898, -50929, -50961, -50993, -51024, -51056, -51087, -51119, -51150, -51182, -51213, -51244, -51276, -51307, -51338, -51369, -51401, -51432, -51463, -51494, -51525, -51556, -51587, -51618, -51649, -51680, -51711, -51742, -51773, -51803, -51834, -51865, -51896, -51926, -51957, -51988, -52018, -52049, -52079, -52110, -52140, -52171, -52201, -52231, -52262, -52292, -52322, -52353, -52383, -52413, -52443, -52473, -52503, -52534, -52564, -52594, -52624, -52653, -52683, -52713, -52743, -52773, -52803, -52832, -52862, -52892, -52922, -52951, -52981, -53010, -53040, -53069, -53099, -53128, -53158, -53187, -53216, -53246, -53275, -53304, -53334, -53363, -53392, -53421, -53450, -53479, -53508, -53537, -53566, -53595, -53624, -53653, -53682, -53711, -53739, -53768, -53797, -53826, -53854, -53883, -53911, -53940, -53969, -53997, -54026, -54054, -54082, -54111, -54139, -54167, -54196, -54224, -54252, -54280, -54308, -54337, -54365, -54393, -54421, -54449, -54477, -54505, -54533, -54560, -54588, -54616, -54644, -54672, -54699, -54727, -54755, -54782, -54810, -54837, -54865, -54892, -54920, -54947, -54974, -55002, -55029, -55056, -55084, -55111, -55138, -55165, -55192, -55219, -55246, -55274, -55300, -55327, -55354, -55381, -55408, -55435, -55462, -55489, -55515, -55542, -55569, -55595, -55622, -55648, -55675, -55701, -55728, -55754, -55781, -55807, -55833, -55860, -55886, -55912, -55938, -55965, -55991, -56017, -56043, -56069, -56095, -56121, -56147, -56173, -56199, -56225, -56250, -56276, -56302, -56328, -56353, -56379, -56404, -56430, -56456, -56481, -56507, -56532, -56557, -56583, -56608, -56633, -56659, -56684, -56709, -56734, -56760, -56785, -56810, -56835, -56860, -56885, -56910, -56935, -56959, -56984, -57009, -57034, -57059, -57083, -57108, -57133, -57157, -57182, -57206, -57231, -57255, -57280, -57304, -57329, -57353, -57377, -57402, -57426, -57450, -57474, -57498, -57522, -57546, -57570, -57594, -57618, -57642, -57666, -57690, -57714, -57738, -57762, -57785, -57809, -57833, -57856, -57880, -57903, -57927, -57950, -57974, -57997, -58021, -58044, -58067, -58091, -58114, -58137, -58160, -58183, -58207, -58230, -58253, -58276, -58299, -58322, -58345, -58367, -58390, -58413, -58436, -58459, -58481, -58504, -58527, -58549, -58572, -58594, -58617, -58639, -58662, -58684, -58706, -58729, -58751, -58773, -58795, -58818, -58840, -58862, -58884, -58906, -58928, -58950, -58972, -58994, -59016, -59038, -59059, -59081, -59103, -59125, -59146, -59168, -59190, -59211, -59233, -59254, -59276, -59297, -59318, -59340, -59361, -59382, -59404, -59425, -59446, -59467, -59488, -59509, -59530, -59551, -59572, -59593, -59614, -59635, -59656, -59677, -59697, -59718, -59739, -59759, -59780, -59801, -59821, -59842, -59862, -59883, -59903, -59923, -59944, -59964, -59984, -60004, -60025, -60045, -60065, -60085, -60105, -60125, -60145, -60165, -60185, -60205, -60225, -60244, -60264, -60284, -60304, -60323, -60343, -60363, -60382, -60402, -60421, -60441, -60460, -60479, -60499, -60518, -60537, -60556, -60576, -60595, -60614, -60633, -60652, -60671, -60690, -60709, -60728, -60747, -60766, -60785, -60803, -60822, -60841, -60859, -60878, -60897, -60915, -60934, -60952, -60971, -60989, -61007, -61026, -61044, -61062, -61081, -61099, -61117, -61135, -61153, -61171, -61189, -61207, -61225, -61243, -61261, -61279, -61297, -61314, -61332, -61350, -61367, -61385, -61403, -61420, -61438, -61455, -61473, -61490, -61507, -61525, -61542, -61559, -61577, -61594, -61611, -61628, -61645, -61662, -61679, -61696, -61713, -61730, -61747, -61764, -61780, -61797, -61814, -61831, -61847, -61864, -61880, -61897, -61913, -61930, -61946, -61963, -61979, -61995, -62012, -62028, -62044, -62060, -62076, -62092, -62108, -62125, -62141, -62156, -62172, -62188, -62204, -62220, -62236, -62251, -62267, -62283, -62298, -62314, -62329, -62345, -62360, -62376, -62391, -62407, -62422, -62437, -62453, -62468, -62483, -62498, -62513, -62528, -62543, -62558, -62573, -62588, -62603, -62618, -62633, -62648, -62662, -62677, -62692, -62706, -62721, -62735, -62750, -62764, -62779, -62793, -62808, -62822, -62836, -62850, -62865, -62879, -62893, -62907, -62921, -62935, -62949, -62963, -62977, -62991, -63005, -63019, -63032, -63046, -63060, -63074, -63087, -63101, -63114, -63128, -63141, -63155, -63168, -63182, -63195, -63208, -63221, -63235, -63248, -63261, -63274, -63287, -63300, -63313, -63326, -63339, -63352, -63365, -63378, -63390, -63403, -63416, -63429, -63441, -63454, -63466, -63479, -63491, -63504, -63516, -63528, -63541, -63553, -63565, -63578, -63590, -63602, -63614, -63626, -63638, -63650, -63662, -63674, -63686, -63698, -63709, -63721, -63733, -63745, -63756, -63768, -63779, -63791, -63803, -63814, -63825, -63837, -63848, -63859, -63871, -63882, -63893, -63904, -63915, -63927, -63938, -63949, -63960, -63971, -63981, -63992, -64003, -64014, -64025, -64035, -64046, -64057, -64067, -64078, -64088, -64099, -64109, -64120, -64130, -64140, -64151, -64161, -64171, -64181, -64192, -64202, -64212, -64222, -64232, -64242, -64252, -64261, -64271, -64281, -64291, -64301, -64310, -64320, -64330, -64339, -64349, -64358, -64368, -64377, -64387, -64396, -64405, -64414, -64424, -64433, -64442, -64451, -64460, -64469, -64478, -64487, -64496, -64505, -64514, -64523, -64532, -64540, -64549, -64558, -64566, -64575, -64584, -64592, -64601, -64609, -64617, -64626, -64634, -64642, -64651, -64659, -64667, -64675, -64683, -64691, -64699, -64707, -64715, -64723, -64731, -64739, -64747, -64754, -64762, -64770, -64777, -64785, -64793, -64800, -64808, -64815, -64822, -64830, -64837, -64844, -64852, -64859, -64866, -64873, -64880, -64887, -64895, -64902, -64908, -64915, -64922, -64929, -64936, -64943, -64949, -64956, -64963, -64969, -64976, -64982, -64989, -64995, -65002, -65008, -65015, -65021, -65027, -65033, -65040, -65046, -65052, -65058, -65064, -65070, -65076, -65082, -65088, -65094, -65099, -65105, -65111, -65117, -65122, -65128, -65133, -65139, -65144, -65150, -65155, -65161, -65166, -65171, -65177, -65182, -65187, -65192, -65197, -65202, -65207, -65212, -65217, -65222, -65227, -65232, -65237, -65242, -65246, -65251, -65256, -65260, -65265, -65270, -65274, -65279, -65283, -65287, -65292, -65296, -65300, -65305, -65309, -65313, -65317, -65321, -65325, -65329, -65333, -65337, -65341, -65345, -65349, -65352, -65356, -65360, -65363, -65367, -65371, -65374, -65378, -65381, -65385, -65388, -65391, -65395, -65398, -65401, -65404, -65408, -65411, -65414, -65417, -65420, -65423, -65426, -65429, -65431, -65434, -65437, -65440, -65442, -65445, -65448, -65450, -65453, -65455, -65458, -65460, -65463, -65465, -65467, -65470, -65472, -65474, -65476, -65478, -65480, -65482, -65484, -65486, -65488, -65490, -65492, -65494, -65496, -65497, -65499, -65501, -65502, -65504, -65505, -65507, -65508, -65510, -65511, -65513, -65514, -65515, -65516, -65518, -65519, -65520, -65521, -65522, -65523, -65524, -65525, -65526, -65527, -65527, -65528, -65529, -65530, -65530, -65531, -65531, -65532, -65532, -65533, -65533, -65534, -65534, -65534, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65534, -65534, -65534, -65533, -65533, -65532, -65532, -65531, -65531, -65530, -65530, -65529, -65528, -65527, -65527, -65526, -65525, -65524, -65523, -65522, -65521, -65520, -65519, -65518, -65516, -65515, -65514, -65513, -65511, -65510, -65508, -65507, -65505, -65504, -65502, -65501, -65499, -65497, -65496, -65494, -65492, -65490, -65488, -65486, -65484, -65482, -65480, -65478, -65476, -65474, -65472, -65470, -65467, -65465, -65463, -65460, -65458, -65455, -65453, -65450, -65448, -65445, -65442, -65440, -65437, -65434, -65431, -65429, -65426, -65423, -65420, -65417, -65414, -65411, -65408, -65404, -65401, -65398, -65395, -65391, -65388, -65385, -65381, -65378, -65374, -65371, -65367, -65363, -65360, -65356, -65352, -65349, -65345, -65341, -65337, -65333, -65329, -65325, -65321, -65317, -65313, -65309, -65305, -65300, -65296, -65292, -65287, -65283, -65279, -65274, -65270, -65265, -65260, -65256, -65251, -65246, -65242, -65237, -65232, -65227, -65222, -65217, -65212, -65207, -65202, -65197, -65192, -65187, -65182, -65177, -65171, -65166, -65161, -65155, -65150, -65144, -65139, -65133, -65128, -65122, -65117, -65111, -65105, -65099, -65094, -65088, -65082, -65076, -65070, -65064, -65058, -65052, -65046, -65040, -65033, -65027, -65021, -65015, -65008, -65002, -64995, -64989, -64982, -64976, -64969, -64963, -64956, -64949, -64943, -64936, -64929, -64922, -64915, -64908, -64902, -64895, -64887, -64880, -64873, -64866, -64859, -64852, -64844, -64837, -64830, -64822, -64815, -64808, -64800, -64793, -64785, -64777, -64770, -64762, -64754, -64747, -64739, -64731, -64723, -64715, -64707, -64699, -64691, -64683, -64675, -64667, -64659, -64651, -64642, -64634, -64626, -64617, -64609, -64601, -64592, -64584, -64575, -64566, -64558, -64549, -64540, -64532, -64523, -64514, -64505, -64496, -64487, -64478, -64469, -64460, -64451, -64442, -64433, -64424, -64414, -64405, -64396, -64387, -64377, -64368, -64358, -64349, -64339, -64330, -64320, -64310, -64301, -64291, -64281, -64271, -64261, -64252, -64242, -64232, -64222, -64212, -64202, -64192, -64181, -64171, -64161, -64151, -64140, -64130, -64120, -64109, -64099, -64088, -64078, -64067, -64057, -64046, -64035, -64025, -64014, -64003, -63992, -63981, -63971, -63960, -63949, -63938, -63927, -63915, -63904, -63893, -63882, -63871, -63859, -63848, -63837, -63825, -63814, -63803, -63791, -63779, -63768, -63756, -63745, -63733, -63721, -63709, -63698, -63686, -63674, -63662, -63650, -63638, -63626, -63614, -63602, -63590, -63578, -63565, -63553, -63541, -63528, -63516, -63504, -63491, -63479, -63466, -63454, -63441, -63429, -63416, -63403, -63390, -63378, -63365, -63352, -63339, -63326, -63313, -63300, -63287, -63274, -63261, -63248, -63235, -63221, -63208, -63195, -63182, -63168, -63155, -63141, -63128, -63114, -63101, -63087, -63074, -63060, -63046, -63032, -63019, -63005, -62991, -62977, -62963, -62949, -62935, -62921, -62907, -62893, -62879, -62865, -62850, -62836, -62822, -62808, -62793, -62779, -62764, -62750, -62735, -62721, -62706, -62692, -62677, -62662, -62648, -62633, -62618, -62603, -62588, -62573, -62558, -62543, -62528, -62513, -62498, -62483, -62468, -62453, -62437, -62422, -62407, -62391, -62376, -62360, -62345, -62329, -62314, -62298, -62283, -62267, -62251, -62236, -62220, -62204, -62188, -62172, -62156, -62141, -62125, -62108, -62092, -62076, -62060, -62044, -62028, -62012, -61995, -61979, -61963, -61946, -61930, -61913, -61897, -61880, -61864, -61847, -61831, -61814, -61797, -61780, -61764, -61747, -61730, -61713, -61696, -61679, -61662, -61645, -61628, -61611, -61594, -61577, -61559, -61542, -61525, -61507, -61490, -61473, -61455, -61438, -61420, -61403, -61385, -61367, -61350, -61332, -61314, -61297, -61279, -61261, -61243, -61225, -61207, -61189, -61171, -61153, -61135, -61117, -61099, -61081, -61062, -61044, -61026, -61007, -60989, -60971, -60952, -60934, -60915, -60897, -60878, -60859, -60841, -60822, -60803, -60785, -60766, -60747, -60728, -60709, -60690, -60671, -60652, -60633, -60614, -60595, -60576, -60556, -60537, -60518, -60499, -60479, -60460, -60441, -60421, -60402, -60382, -60363, -60343, -60323, -60304, -60284, -60264, -60244, -60225, -60205, -60185, -60165, -60145, -60125, -60105, -60085, -60065, -60045, -60025, -60004, -59984, -59964, -59944, -59923, -59903, -59883, -59862, -59842, -59821, -59801, -59780, -59759, -59739, -59718, -59697, -59677, -59656, -59635, -59614, -59593, -59572, -59551, -59530, -59509, -59488, -59467, -59446, -59425, -59404, -59382, -59361, -59340, -59318, -59297, -59276, -59254, -59233, -59211, -59189, -59168, -59146, -59125, -59103, -59081, -59059, -59038, -59016, -58994, -58972, -58950, -58928, -58906, -58884, -58862, -58840, -58818, -58795, -58773, -58751, -58729, -58706, -58684, -58662, -58639, -58617, -58594, -58572, -58549, -58527, -58504, -58481, -58459, -58436, -58413, -58390, -58367, -58345, -58322, -58299, -58276, -58253, -58230, -58207, -58183, -58160, -58137, -58114, -58091, -58067, -58044, -58021, -57997, -57974, -57950, -57927, -57903, -57880, -57856, -57833, -57809, -57785, -57762, -57738, -57714, -57690, -57666, -57642, -57618, -57594, -57570, -57546, -57522, -57498, -57474, -57450, -57426, -57402, -57377, -57353, -57329, -57304, -57280, -57255, -57231, -57206, -57182, -57157, -57133, -57108, -57083, -57059, -57034, -57009, -56984, -56959, -56935, -56910, -56885, -56860, -56835, -56810, -56785, -56760, -56734, -56709, -56684, -56659, -56633, -56608, -56583, -56557, -56532, -56507, -56481, -56456, -56430, -56404, -56379, -56353, -56328, -56302, -56276, -56250, -56225, -56199, -56173, -56147, -56121, -56095, -56069, -56043, -56017, -55991, -55965, -55938, -55912, -55886, -55860, -55833, -55807, -55781, -55754, -55728, -55701, -55675, -55648, -55622, -55595, -55569, -55542, -55515, -55489, -55462, -55435, -55408, -55381, -55354, -55327, -55300, -55274, -55246, -55219, -55192, -55165, -55138, -55111, -55084, -55056, -55029, -55002, -54974, -54947, -54920, -54892, -54865, -54837, -54810, -54782, -54755, -54727, -54699, -54672, -54644, -54616, -54588, -54560, -54533, -54505, -54477, -54449, -54421, -54393, -54365, -54337, -54308, -54280, -54252, -54224, -54196, -54167, -54139, -54111, -54082, -54054, -54026, -53997, -53969, -53940, -53911, -53883, -53854, -53826, -53797, -53768, -53739, -53711, -53682, -53653, -53624, -53595, -53566, -53537, -53508, -53479, -53450, -53421, -53392, -53363, -53334, -53304, -53275, -53246, -53216, -53187, -53158, -53128, -53099, -53069, -53040, -53010, -52981, -52951, -52922, -52892, -52862, -52832, -52803, -52773, -52743, -52713, -52683, -52653, -52624, -52594, -52564, -52534, -52503, -52473, -52443, -52413, -52383, -52353, -52322, -52292, -52262, -52231, -52201, -52171, -52140, -52110, -52079, -52049, -52018, -51988, -51957, -51926, -51896, -51865, -51834, -51803, -51773, -51742, -51711, -51680, -51649, -51618, -51587, -51556, -51525, -51494, -51463, -51432, -51401, -51369, -51338, -51307, -51276, -51244, -51213, -51182, -51150, -51119, -51087, -51056, -51024, -50993, -50961, -50929, -50898, -50866, -50834, -50803, -50771, -50739, -50707, -50675, -50644, -50612, -50580, -50548, -50516, -50484, -50452, -50420, -50387, -50355, -50323, -50291, -50259, -50226, -50194, -50162, -50129, -50097, -50065, -50032, -50000, -49967, -49935, -49902, -49869, -49837, -49804, -49771, -49739, -49706, -49673, -49640, -49608, -49575, -49542, -49509, -49476, -49443, -49410, -49377, -49344, -49311, -49278, -49244, -49211, -49178, -49145, -49112, -49078, -49045, -49012, -48978, -48945, -48911, -48878, -48844, -48811, -48777, -48744, -48710, -48676, -48643, -48609, -48575, -48542, -48508, -48474, -48440, -48406, -48372, -48338, -48305, -48271, -48237, -48202, -48168, -48134, -48100, -48066, -48032, -47998, -47963, -47929, -47895, -47860, -47826, -47792, -47757, -47723, -47688, -47654, -47619, -47585, -47550, -47516, -47481, -47446, -47412, -47377, -47342, -47307, -47273, -47238, -47203, -47168, -47133, -47098, -47063, -47028, -46993, -46958, -46923, -46888, -46853, -46818, -46783, -46747, -46712, -46677, -46642, -46606, -46571, -46536, -46500, -46465, -46429, -46394, -46358, -46323, -46287, -46251, -46216, -46180, -46145, -46109, -46073, -46037, -46002, -45966, -45930, -45894, -45858, -45822, -45786, -45750, -45714, -45678, -45642, -45606, -45570, -45534, -45498, -45462, -45425, -45389, -45353, -45316, -45280, -45244, -45207, -45171, -45135, -45098, -45062, -45025, -44989, -44952, -44915, -44879, -44842, -44806, -44769, -44732, -44695, -44659, -44622, -44585, -44548, -44511, -44474, -44437, -44400, -44363, -44326, -44289, -44252, -44215, -44178, -44141, -44104, -44067, -44029, -43992, -43955, -43918, -43880, -43843, -43806, -43768, -43731, -43693, -43656, -43618, -43581, -43543, -43506, -43468, -43430, -43393, -43355, -43317, -43280, -43242, -43204, -43166, -43128, -43091, -43053, -43015, -42977, -42939, -42901, -42863, -42825, -42787, -42749, -42711, -42672, -42634, -42596, -42558, -42520, -42481, -42443, -42405, -42366, -42328, -42290, -42251, -42213, -42174, -42136, -42097, -42059, -42020, -41982, -41943, -41904, -41866, -41827, -41788, -41750, -41711, -41672, -41633, -41595, -41556, -41517, -41478, -41439, -41400, -41361, -41322, -41283, -41244, -41205, -41166, -41127, -41087, -41048, -41009, -40970, -40931, -40891, -40852, -40813, -40773, -40734, -40695, -40655, -40616, -40576, -40537, -40497, -40458, -40418, -40379, -40339, -40299, -40260, -40220, -40180, -40141, -40101, -40061, -40021, -39982, -39942, -39902, -39862, -39822, -39782, -39742, -39702, -39662, -39622, -39582, -39542, -39502, -39462, -39422, -39382, -39341, -39301, -39261, -39221, -39180, -39140, -39100, -39059, -39019, -38979, -38938, -38898, -38857, -38817, -38776, -38736, -38695, -38655, -38614, -38573, -38533, -38492, -38451, -38411, -38370, -38329, -38288, -38248, -38207, -38166, -38125, -38084, -38043, -38002, -37961, -37920, -37879, -37838, -37797, -37756, -37715, -37674, -37633, -37592, -37550, -37509, -37468, -37427, -37386, -37344, -37303, -37262, -37220, -37179, -37137, -37096, -37055, -37013, -36972, -36930, -36889, -36847, -36805, -36764, -36722, -36681, -36639, -36597, -36556, -36514, -36472, -36430, -36388, -36347, -36305, -36263, -36221, -36179, -36137, -36095, -36053, -36011, -35969, -35927, -35885, -35843, -35801, -35759, -35717, -35675, -35633, -35590, -35548, -35506, -35464, -35421, -35379, -35337, -35294, -35252, -35210, -35167, -35125, -35082, -35040, -34997, -34955, -34912, -34870, -34827, -34785, -34742, -34699, -34657, -34614, -34571, -34529, -34486, -34443, -34400, -34358, -34315, -34272, -34229, -34186, -34143, -34100, -34057, -34015, -33972, -33929, -33886, -33843, -33799, -33756, -33713, -33670, -33627, -33584, -33541, -33498, -33454, -33411, -33368, -33325, -33281, -33238, -33195, -33151, -33108, -33065, -33021, -32978, -32934, -32891, -32847, -32804, -32760, -32717, -32673, -32630, -32586, -32542, -32499, -32455, -32411, -32368, -32324, -32280, -32236, -32193, -32149, -32105, -32061, -32017, -31974, -31930, -31886, -31842, -31798, -31754, -31710, -31666, -31622, -31578, -31534, -31490, -31446, -31402, -31357, -31313, -31269, -31225, -31181, -31136, -31092, -31048, -31004, -30959, -30915, -30871, -30826, -30782, -30738, -30693, -30649, -30604, -30560, -30515, -30471, -30426, -30382, -30337, -30293, -30248, -30204, -30159, -30114, -30070, -30025, -29980, -29936, -29891, -29846, -29801, -29757, -29712, -29667, -29622, -29577, -29533, -29488, -29443, -29398, -29353, -29308, -29263, -29218, -29173, -29128, -29083, -29038, -28993, -28948, -28903, -28858, -28812, -28767, -28722, -28677, -28632, -28586, -28541, -28496, -28451, -28405, -28360, -28315, -28269, -28224, -28179, -28133, -28088, -28042, -27997, -27952, -27906, -27861, -27815, -27770, -27724, -27678, -27633, -27587, -27542, -27496, -27450, -27405, -27359, -27313, -27268, -27222, -27176, -27131, -27085, -27039, -26993, -26947, -26902, -26856, -26810, -26764, -26718, -26672, -26626, -26580, -26534, -26488, -26442, -26396, -26350, -26304, -26258, -26212, -26166, -26120, -26074, -26028, -25982, -25936, -25889, -25843, -25797, -25751, -25705, -25658, -25612, -25566, -25520, -25473, -25427, -25381, -25334, -25288, -25241, -25195, -25149, -25102, -25056, -25009, -24963, -24916, -24870, -24823, -24777, -24730, -24684, -24637, -24591, -24544, -24497, -24451, -24404, -24357, -24311, -24264, -24217, -24171, -24124, -24077, -24030, -23984, -23937, -23890, -23843, -23796, -23750, -23703, -23656, -23609, -23562, -23515, -23468, -23421, -23374, -23327, -23280, -23233, -23186, -23139, -23092, -23045, -22998, -22951, -22904, -22857, -22810, -22763, -22716, -22668, -22621, -22574, -22527, -22480, -22432, -22385, -22338, -22291, -22243, -22196, -22149, -22102, -22054, -22007, -21960, -21912, -21865, -21817, -21770, -21723, -21675, -21628, -21580, -21533, -21485, -21438, -21390, -21343, -21295, -21248, -21200, -21153, -21105, -21057, -21010, -20962, -20915, -20867, -20819, -20772, -20724, -20676, -20629, -20581, -20533, -20485, -20438, -20390, -20342, -20294, -20246, -20199, -20151, -20103, -20055, -20007, -19959, -19912, -19864, -19816, -19768, -19720, -19672, -19624, -19576, -19528, -19480, -19432, -19384, -19336, -19288, -19240, -19192, -19144, -19096, -19048, -19000, -18951, -18903, -18855, -18807, -18759, -18711, -18663, -18614, -18566, -18518, -18470, -18421, -18373, -18325, -18277, -18228, -18180, -18132, -18084, -18035, -17987, -17939, -17890, -17842, -17793, -17745, -17697, -17648, -17600, -17551, -17503, -17455, -17406, -17358, -17309, -17261, -17212, -17164, -17115, -17067, -17018, -16970, -16921, -16872, -16824, -16775, -16727, -16678, -16629, -16581, -16532, -16484, -16435, -16386, -16338, -16289, -16240, -16191, -16143, -16094, -16045, -15997, -15948, -15899, -15850, -15802, -15753, -15704, -15655, -15606, -15557, -15509, -15460, -15411, -15362, -15313, -15264, -15215, -15167, -15118, -15069, -15020, -14971, -14922, -14873, -14824, -14775, -14726, -14677, -14628, -14579, -14530, -14481, -14432, -14383, -14334, -14285, -14236, -14187, -14138, -14089, -14040, -13990, -13941, -13892, -13843, -13794, -13745, -13696, -13647, -13597, -13548, -13499, -13450, -13401, -13351, -13302, -13253, -13204, -13154, -13105, -13056, -13007, -12957, -12908, -12859, -12810, -12760, -12711, -12662, -12612, -12563, -12514, -12464, -12415, -12366, -12316, -12267, -12217, -12168, -12119, -12069, -12020, -11970, -11921, -11872, -11822, -11773, -11723, -11674, -11624, -11575, -11525, -11476, -11426, -11377, -11327, -11278, -11228, -11179, -11129, -11080, -11030, -10981, -10931, -10882, -10832, -10782, -10733, -10683, -10634, -10584, -10534, -10485, -10435, -10386, -10336, -10286, -10237, -10187, -10137, -10088, -10038, -9988, -9939, -9889, -9839, -9790, -9740, -9690, -9640, -9591, -9541, -9491, -9442, -9392, -9342, -9292, -9243, -9193, -9143, -9093, -9043, -8994, -8944, -8894, -8844, -8794, -8745, -8695, -8645, -8595, -8545, -8496, -8446, -8396, -8346, -8296, -8246, -8196, -8147, -8097, -8047, -7997, -7947, -7897, -7847, -7797, -7747, -7697, -7648, -7598, -7548, -7498, -7448, -7398, -7348, -7298, -7248, -7198, -7148, -7098, -7048, -6998, -6948, -6898, -6848, -6798, -6748, -6698, -6648, -6598, -6548, -6498, -6448, -6398, -6348, -6298, -6248, -6198, -6148, -6098, -6048, -5998, -5948, -5898, -5848, -5798, -5747, -5697, -5647, -5597, -5547, -5497, -5447, -5397, -5347, -5297, -5247, -5197, -5146, -5096, -5046, -4996, -4946, -4896, -4846, -4796, -4745, -4695, -4645, -4595, -4545, -4495, -4445, -4394, -4344, -4294, -4244, -4194, -4144, -4093, -4043, -3993, -3943, -3893, -3843, -3792, -3742, -3692, -3642, -3592, -3541, -3491, -3441, -3391, -3341, -3291, -3240, -3190, -3140, -3090, -3039, -2989, -2939, -2889, -2839, -2788, -2738, -2688, -2638, -2588, -2537, -2487, -2437, -2387, -2336, -2286, -2236, -2186, -2135, -2085, -2035, -1985, -1934, -1884, -1834, -1784, -1733, -1683, -1633, -1583, -1532, -1482, -1432, -1382, -1331, -1281, -1231, -1181, -1130, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3542, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5747, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22432, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30427, 30471, 30516, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36556, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40299, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47861, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50064, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53912, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54309, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64600, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535 }; angle_t tantoangle[2049] = { 0, 333772, 667544, 1001315, 1335086, 1668857, 2002626, 2336395, 2670163, 3003929, 3337694, 3671457, 4005219, 4338979, 4672736, 5006492, 5340245, 5673995, 6007743, 6341488, 6675230, 7008968, 7342704, 7676435, 8010164, 8343888, 8677609, 9011325, 9345037, 9678744, 10012447, 10346145, 10679838, 11013526, 11347209, 11680887, 12014558, 12348225, 12681885, 13015539, 13349187, 13682829, 14016464, 14350092, 14683714, 15017328, 15350936, 15684536, 16018129, 16351714, 16685291, 17018860, 17352422, 17685974, 18019518, 18353054, 18686582, 19020100, 19353610, 19687110, 20020600, 20354080, 20687552, 21021014, 21354466, 21687906, 22021338, 22354758, 22688168, 23021568, 23354956, 23688332, 24021698, 24355052, 24688396, 25021726, 25355046, 25688352, 26021648, 26354930, 26688200, 27021456, 27354702, 27687932, 28021150, 28354356, 28687548, 29020724, 29353888, 29687038, 30020174, 30353296, 30686404, 31019496, 31352574, 31685636, 32018684, 32351718, 32684734, 33017736, 33350722, 33683692, 34016648, 34349584, 34682508, 35015412, 35348300, 35681172, 36014028, 36346868, 36679688, 37012492, 37345276, 37678044, 38010792, 38343524, 38676240, 39008936, 39341612, 39674272, 40006912, 40339532, 40672132, 41004716, 41337276, 41669820, 42002344, 42334848, 42667332, 42999796, 43332236, 43664660, 43997060, 44329444, 44661800, 44994140, 45326456, 45658752, 45991028, 46323280, 46655512, 46987720, 47319908, 47652072, 47984212, 48316332, 48648428, 48980500, 49312548, 49644576, 49976580, 50308556, 50640512, 50972444, 51304352, 51636236, 51968096, 52299928, 52631740, 52963524, 53295284, 53627020, 53958728, 54290412, 54622068, 54953704, 55285308, 55616888, 55948444, 56279972, 56611472, 56942948, 57274396, 57605816, 57937212, 58268576, 58599916, 58931228, 59262512, 59593768, 59924992, 60256192, 60587364, 60918508, 61249620, 61580704, 61911760, 62242788, 62573788, 62904756, 63235692, 63566604, 63897480, 64228332, 64559148, 64889940, 65220696, 65551424, 65882120, 66212788, 66543420, 66874024, 67204600, 67535136, 67865648, 68196120, 68526568, 68856984, 69187360, 69517712, 69848024, 70178304, 70508560, 70838776, 71168960, 71499112, 71829224, 72159312, 72489360, 72819376, 73149360, 73479304, 73809216, 74139096, 74468936, 74798744, 75128520, 75458264, 75787968, 76117632, 76447264, 76776864, 77106424, 77435952, 77765440, 78094888, 78424304, 78753688, 79083032, 79412336, 79741608, 80070840, 80400032, 80729192, 81058312, 81387392, 81716432, 82045440, 82374408, 82703336, 83032224, 83361080, 83689896, 84018664, 84347400, 84676096, 85004760, 85333376, 85661952, 85990488, 86318984, 86647448, 86975864, 87304240, 87632576, 87960872, 88289128, 88617344, 88945520, 89273648, 89601736, 89929792, 90257792, 90585760, 90913688, 91241568, 91569408, 91897200, 92224960, 92552672, 92880336, 93207968, 93535552, 93863088, 94190584, 94518040, 94845448, 95172816, 95500136, 95827416, 96154648, 96481832, 96808976, 97136080, 97463136, 97790144, 98117112, 98444032, 98770904, 99097736, 99424520, 99751256, 100077944, 100404592, 100731192, 101057744, 101384248, 101710712, 102037128, 102363488, 102689808, 103016080, 103342312, 103668488, 103994616, 104320696, 104646736, 104972720, 105298656, 105624552, 105950392, 106276184, 106601928, 106927624, 107253272, 107578872, 107904416, 108229920, 108555368, 108880768, 109206120, 109531416, 109856664, 110181872, 110507016, 110832120, 111157168, 111482168, 111807112, 112132008, 112456856, 112781648, 113106392, 113431080, 113755720, 114080312, 114404848, 114729328, 115053760, 115378136, 115702464, 116026744, 116350960, 116675128, 116999248, 117323312, 117647320, 117971272, 118295176, 118619024, 118942816, 119266560, 119590248, 119913880, 120237456, 120560984, 120884456, 121207864, 121531224, 121854528, 122177784, 122500976, 122824112, 123147200, 123470224, 123793200, 124116120, 124438976, 124761784, 125084528, 125407224, 125729856, 126052432, 126374960, 126697424, 127019832, 127342184, 127664472, 127986712, 128308888, 128631008, 128953072, 129275080, 129597024, 129918912, 130240744, 130562520, 130884232, 131205888, 131527480, 131849016, 132170496, 132491912, 132813272, 133134576, 133455816, 133776992, 134098120, 134419184, 134740176, 135061120, 135382000, 135702816, 136023584, 136344272, 136664912, 136985488, 137306016, 137626464, 137946864, 138267184, 138587456, 138907664, 139227808, 139547904, 139867920, 140187888, 140507776, 140827616, 141147392, 141467104, 141786752, 142106336, 142425856, 142745312, 143064720, 143384048, 143703312, 144022512, 144341664, 144660736, 144979744, 145298704, 145617584, 145936400, 146255168, 146573856, 146892480, 147211040, 147529536, 147847968, 148166336, 148484640, 148802880, 149121056, 149439152, 149757200, 150075168, 150393072, 150710912, 151028688, 151346400, 151664048, 151981616, 152299136, 152616576, 152933952, 153251264, 153568496, 153885680, 154202784, 154519824, 154836784, 155153696, 155470528, 155787296, 156104000, 156420624, 156737200, 157053696, 157370112, 157686480, 158002768, 158318976, 158635136, 158951216, 159267232, 159583168, 159899040, 160214848, 160530592, 160846256, 161161840, 161477376, 161792832, 162108208, 162423520, 162738768, 163053952, 163369040, 163684080, 163999040, 164313936, 164628752, 164943504, 165258176, 165572784, 165887312, 166201776, 166516160, 166830480, 167144736, 167458912, 167773008, 168087040, 168400992, 168714880, 169028688, 169342432, 169656096, 169969696, 170283216, 170596672, 170910032, 171223344, 171536576, 171849728, 172162800, 172475808, 172788736, 173101600, 173414384, 173727104, 174039728, 174352288, 174664784, 174977200, 175289536, 175601792, 175913984, 176226096, 176538144, 176850096, 177161984, 177473792, 177785536, 178097200, 178408784, 178720288, 179031728, 179343088, 179654368, 179965568, 180276704, 180587744, 180898720, 181209616, 181520448, 181831184, 182141856, 182452448, 182762960, 183073408, 183383760, 183694048, 184004240, 184314368, 184624416, 184934400, 185244288, 185554096, 185863840, 186173504, 186483072, 186792576, 187102000, 187411344, 187720608, 188029808, 188338912, 188647936, 188956896, 189265760, 189574560, 189883264, 190191904, 190500448, 190808928, 191117312, 191425632, 191733872, 192042016, 192350096, 192658096, 192966000, 193273840, 193581584, 193889264, 194196848, 194504352, 194811792, 195119136, 195426400, 195733584, 196040688, 196347712, 196654656, 196961520, 197268304, 197574992, 197881616, 198188144, 198494592, 198800960, 199107248, 199413456, 199719584, 200025616, 200331584, 200637456, 200943248, 201248960, 201554576, 201860128, 202165584, 202470960, 202776256, 203081456, 203386592, 203691632, 203996592, 204301472, 204606256, 204910976, 205215600, 205520144, 205824592, 206128960, 206433248, 206737456, 207041584, 207345616, 207649568, 207953424, 208257216, 208560912, 208864512, 209168048, 209471488, 209774832, 210078112, 210381296, 210684384, 210987408, 211290336, 211593184, 211895936, 212198608, 212501184, 212803680, 213106096, 213408432, 213710672, 214012816, 214314880, 214616864, 214918768, 215220576, 215522288, 215823920, 216125472, 216426928, 216728304, 217029584, 217330784, 217631904, 217932928, 218233856, 218534704, 218835472, 219136144, 219436720, 219737216, 220037632, 220337952, 220638192, 220938336, 221238384, 221538352, 221838240, 222138032, 222437728, 222737344, 223036880, 223336304, 223635664, 223934912, 224234096, 224533168, 224832160, 225131072, 225429872, 225728608, 226027232, 226325776, 226624240, 226922608, 227220880, 227519056, 227817152, 228115168, 228413088, 228710912, 229008640, 229306288, 229603840, 229901312, 230198688, 230495968, 230793152, 231090256, 231387280, 231684192, 231981024, 232277760, 232574416, 232870960, 233167440, 233463808, 233760096, 234056288, 234352384, 234648384, 234944304, 235240128, 235535872, 235831504, 236127056, 236422512, 236717888, 237013152, 237308336, 237603424, 237898416, 238193328, 238488144, 238782864, 239077488, 239372016, 239666464, 239960816, 240255072, 240549232, 240843312, 241137280, 241431168, 241724960, 242018656, 242312256, 242605776, 242899200, 243192512, 243485744, 243778896, 244071936, 244364880, 244657744, 244950496, 245243168, 245535744, 245828224, 246120608, 246412912, 246705104, 246997216, 247289216, 247581136, 247872960, 248164688, 248456320, 248747856, 249039296, 249330640, 249621904, 249913056, 250204128, 250495088, 250785968, 251076736, 251367424, 251658016, 251948512, 252238912, 252529200, 252819408, 253109520, 253399536, 253689456, 253979280, 254269008, 254558640, 254848176, 255137632, 255426976, 255716224, 256005376, 256294432, 256583392, 256872256, 257161024, 257449696, 257738272, 258026752, 258315136, 258603424, 258891600, 259179696, 259467696, 259755600, 260043392, 260331104, 260618704, 260906224, 261193632, 261480960, 261768176, 262055296, 262342320, 262629248, 262916080, 263202816, 263489456, 263776000, 264062432, 264348784, 264635024, 264921168, 265207216, 265493168, 265779024, 266064784, 266350448, 266636000, 266921472, 267206832, 267492096, 267777264, 268062336, 268347312, 268632192, 268916960, 269201632, 269486208, 269770688, 270055072, 270339360, 270623552, 270907616, 271191616, 271475488, 271759296, 272042976, 272326560, 272610048, 272893440, 273176736, 273459936, 273743040, 274026048, 274308928, 274591744, 274874432, 275157024, 275439520, 275721920, 276004224, 276286432, 276568512, 276850528, 277132416, 277414240, 277695936, 277977536, 278259040, 278540448, 278821728, 279102944, 279384032, 279665056, 279945952, 280226752, 280507456, 280788064, 281068544, 281348960, 281629248, 281909472, 282189568, 282469568, 282749440, 283029248, 283308960, 283588544, 283868032, 284147424, 284426720, 284705920, 284985024, 285264000, 285542912, 285821696, 286100384, 286378976, 286657440, 286935840, 287214112, 287492320, 287770400, 288048384, 288326240, 288604032, 288881696, 289159264, 289436768, 289714112, 289991392, 290268576, 290545632, 290822592, 291099456, 291376224, 291652896, 291929440, 292205888, 292482272, 292758528, 293034656, 293310720, 293586656, 293862496, 294138240, 294413888, 294689440, 294964864, 295240192, 295515424, 295790560, 296065600, 296340512, 296615360, 296890080, 297164704, 297439200, 297713632, 297987936, 298262144, 298536256, 298810240, 299084160, 299357952, 299631648, 299905248, 300178720, 300452128, 300725408, 300998592, 301271680, 301544640, 301817536, 302090304, 302362976, 302635520, 302908000, 303180352, 303452608, 303724768, 303996800, 304268768, 304540608, 304812320, 305083968, 305355520, 305626944, 305898272, 306169472, 306440608, 306711616, 306982528, 307253344, 307524064, 307794656, 308065152, 308335552, 308605856, 308876032, 309146112, 309416096, 309685984, 309955744, 310225408, 310494976, 310764448, 311033824, 311303072, 311572224, 311841280, 312110208, 312379040, 312647776, 312916416, 313184960, 313453376, 313721696, 313989920, 314258016, 314526016, 314793920, 315061728, 315329408, 315597024, 315864512, 316131872, 316399168, 316666336, 316933408, 317200384, 317467232, 317733984, 318000640, 318267200, 318533632, 318799968, 319066208, 319332352, 319598368, 319864288, 320130112, 320395808, 320661408, 320926912, 321192320, 321457632, 321722816, 321987904, 322252864, 322517760, 322782528, 323047200, 323311744, 323576192, 323840544, 324104800, 324368928, 324632992, 324896928, 325160736, 325424448, 325688096, 325951584, 326215008, 326478304, 326741504, 327004608, 327267584, 327530464, 327793248, 328055904, 328318496, 328580960, 328843296, 329105568, 329367712, 329629760, 329891680, 330153536, 330415264, 330676864, 330938400, 331199808, 331461120, 331722304, 331983392, 332244384, 332505280, 332766048, 333026752, 333287296, 333547776, 333808128, 334068384, 334328544, 334588576, 334848512, 335108352, 335368064, 335627712, 335887200, 336146624, 336405920, 336665120, 336924224, 337183200, 337442112, 337700864, 337959552, 338218112, 338476576, 338734944, 338993184, 339251328, 339509376, 339767296, 340025120, 340282848, 340540480, 340797984, 341055392, 341312704, 341569888, 341826976, 342083968, 342340832, 342597600, 342854272, 343110848, 343367296, 343623648, 343879904, 344136032, 344392064, 344648000, 344903808, 345159520, 345415136, 345670656, 345926048, 346181344, 346436512, 346691616, 346946592, 347201440, 347456224, 347710880, 347965440, 348219872, 348474208, 348728448, 348982592, 349236608, 349490528, 349744320, 349998048, 350251648, 350505152, 350758528, 351011808, 351264992, 351518048, 351771040, 352023872, 352276640, 352529280, 352781824, 353034272, 353286592, 353538816, 353790944, 354042944, 354294880, 354546656, 354798368, 355049952, 355301440, 355552800, 355804096, 356055264, 356306304, 356557280, 356808128, 357058848, 357309504, 357560032, 357810464, 358060768, 358311008, 358561088, 358811104, 359060992, 359310784, 359560480, 359810048, 360059520, 360308896, 360558144, 360807296, 361056352, 361305312, 361554144, 361802880, 362051488, 362300032, 362548448, 362796736, 363044960, 363293056, 363541024, 363788928, 364036704, 364284384, 364531936, 364779392, 365026752, 365274016, 365521152, 365768192, 366015136, 366261952, 366508672, 366755296, 367001792, 367248192, 367494496, 367740704, 367986784, 368232768, 368478656, 368724416, 368970080, 369215648, 369461088, 369706432, 369951680, 370196800, 370441824, 370686752, 370931584, 371176288, 371420896, 371665408, 371909792, 372154080, 372398272, 372642336, 372886304, 373130176, 373373952, 373617600, 373861152, 374104608, 374347936, 374591168, 374834304, 375077312, 375320224, 375563040, 375805760, 376048352, 376290848, 376533248, 376775520, 377017696, 377259776, 377501728, 377743584, 377985344, 378227008, 378468544, 378709984, 378951328, 379192544, 379433664, 379674688, 379915584, 380156416, 380397088, 380637696, 380878176, 381118560, 381358848, 381599040, 381839104, 382079072, 382318912, 382558656, 382798304, 383037856, 383277280, 383516640, 383755840, 383994976, 384233984, 384472896, 384711712, 384950400, 385188992, 385427488, 385665888, 385904160, 386142336, 386380384, 386618368, 386856224, 387093984, 387331616, 387569152, 387806592, 388043936, 388281152, 388518272, 388755296, 388992224, 389229024, 389465728, 389702336, 389938816, 390175200, 390411488, 390647680, 390883744, 391119712, 391355584, 391591328, 391826976, 392062528, 392297984, 392533312, 392768544, 393003680, 393238720, 393473632, 393708448, 393943168, 394177760, 394412256, 394646656, 394880960, 395115136, 395349216, 395583200, 395817088, 396050848, 396284512, 396518080, 396751520, 396984864, 397218112, 397451264, 397684288, 397917248, 398150080, 398382784, 398615424, 398847936, 399080320, 399312640, 399544832, 399776928, 400008928, 400240832, 400472608, 400704288, 400935872, 401167328, 401398720, 401629984, 401861120, 402092192, 402323136, 402553984, 402784736, 403015360, 403245888, 403476320, 403706656, 403936896, 404167008, 404397024, 404626944, 404856736, 405086432, 405316032, 405545536, 405774912, 406004224, 406233408, 406462464, 406691456, 406920320, 407149088, 407377760, 407606336, 407834784, 408063136, 408291392, 408519520, 408747584, 408975520, 409203360, 409431072, 409658720, 409886240, 410113664, 410340992, 410568192, 410795296, 411022304, 411249216, 411476032, 411702720, 411929312, 412155808, 412382176, 412608480, 412834656, 413060736, 413286720, 413512576, 413738336, 413964000, 414189568, 414415040, 414640384, 414865632, 415090784, 415315840, 415540800, 415765632, 415990368, 416215008, 416439552, 416663968, 416888288, 417112512, 417336640, 417560672, 417784576, 418008384, 418232096, 418455712, 418679200, 418902624, 419125920, 419349120, 419572192, 419795200, 420018080, 420240864, 420463552, 420686144, 420908608, 421130976, 421353280, 421575424, 421797504, 422019488, 422241344, 422463104, 422684768, 422906336, 423127776, 423349120, 423570400, 423791520, 424012576, 424233536, 424454368, 424675104, 424895744, 425116288, 425336736, 425557056, 425777280, 425997408, 426217440, 426437376, 426657184, 426876928, 427096544, 427316064, 427535488, 427754784, 427974016, 428193120, 428412128, 428631040, 428849856, 429068544, 429287168, 429505664, 429724064, 429942368, 430160576, 430378656, 430596672, 430814560, 431032352, 431250048, 431467616, 431685120, 431902496, 432119808, 432336992, 432554080, 432771040, 432987936, 433204736, 433421408, 433637984, 433854464, 434070848, 434287104, 434503296, 434719360, 434935360, 435151232, 435367008, 435582656, 435798240, 436013696, 436229088, 436444352, 436659520, 436874592, 437089568, 437304416, 437519200, 437733856, 437948416, 438162880, 438377248, 438591520, 438805696, 439019744, 439233728, 439447584, 439661344, 439875008, 440088576, 440302048, 440515392, 440728672, 440941824, 441154880, 441367872, 441580736, 441793472, 442006144, 442218720, 442431168, 442643552, 442855808, 443067968, 443280032, 443492000, 443703872, 443915648, 444127296, 444338880, 444550336, 444761696, 444972992, 445184160, 445395232, 445606176, 445817056, 446027840, 446238496, 446449088, 446659552, 446869920, 447080192, 447290400, 447500448, 447710432, 447920320, 448130112, 448339776, 448549376, 448758848, 448968224, 449177536, 449386720, 449595808, 449804800, 450013664, 450222464, 450431168, 450639776, 450848256, 451056640, 451264960, 451473152, 451681248, 451889248, 452097152, 452304960, 452512672, 452720288, 452927808, 453135232, 453342528, 453549760, 453756864, 453963904, 454170816, 454377632, 454584384, 454791008, 454997536, 455203968, 455410304, 455616544, 455822688, 456028704, 456234656, 456440512, 456646240, 456851904, 457057472, 457262912, 457468256, 457673536, 457878688, 458083744, 458288736, 458493600, 458698368, 458903040, 459107616, 459312096, 459516480, 459720768, 459924960, 460129056, 460333056, 460536960, 460740736, 460944448, 461148064, 461351584, 461554976, 461758304, 461961536, 462164640, 462367680, 462570592, 462773440, 462976160, 463178816, 463381344, 463583776, 463786144, 463988384, 464190560, 464392608, 464594560, 464796448, 464998208, 465199872, 465401472, 465602944, 465804320, 466005600, 466206816, 466407904, 466608896, 466809824, 467010624, 467211328, 467411936, 467612480, 467812896, 468013216, 468213440, 468413600, 468613632, 468813568, 469013440, 469213184, 469412832, 469612416, 469811872, 470011232, 470210528, 470409696, 470608800, 470807776, 471006688, 471205472, 471404192, 471602784, 471801312, 471999712, 472198048, 472396288, 472594400, 472792448, 472990400, 473188256, 473385984, 473583648, 473781216, 473978688, 474176064, 474373344, 474570528, 474767616, 474964608, 475161504, 475358336, 475555040, 475751648, 475948192, 476144608, 476340928, 476537184, 476733312, 476929376, 477125344, 477321184, 477516960, 477712640, 477908224, 478103712, 478299104, 478494400, 478689600, 478884704, 479079744, 479274656, 479469504, 479664224, 479858880, 480053408, 480247872, 480442240, 480636512, 480830656, 481024736, 481218752, 481412640, 481606432, 481800128, 481993760, 482187264, 482380704, 482574016, 482767264, 482960416, 483153472, 483346432, 483539296, 483732064, 483924768, 484117344, 484309856, 484502240, 484694560, 484886784, 485078912, 485270944, 485462880, 485654720, 485846464, 486038144, 486229696, 486421184, 486612576, 486803840, 486995040, 487186176, 487377184, 487568096, 487758912, 487949664, 488140320, 488330880, 488521312, 488711712, 488901984, 489092160, 489282240, 489472256, 489662176, 489851968, 490041696, 490231328, 490420896, 490610336, 490799712, 490988960, 491178144, 491367232, 491556224, 491745120, 491933920, 492122656, 492311264, 492499808, 492688256, 492876608, 493064864, 493253056, 493441120, 493629120, 493817024, 494004832, 494192544, 494380160, 494567712, 494755136, 494942496, 495129760, 495316928, 495504000, 495691008, 495877888, 496064704, 496251424, 496438048, 496624608, 496811040, 496997408, 497183680, 497369856, 497555936, 497741920, 497927840, 498113632, 498299360, 498484992, 498670560, 498856000, 499041376, 499226656, 499411840, 499596928, 499781920, 499966848, 500151680, 500336416, 500521056, 500705600, 500890080, 501074464, 501258752, 501442944, 501627040, 501811072, 501995008, 502178848, 502362592, 502546240, 502729824, 502913312, 503096704, 503280000, 503463232, 503646368, 503829408, 504012352, 504195200, 504377984, 504560672, 504743264, 504925760, 505108192, 505290496, 505472736, 505654912, 505836960, 506018944, 506200832, 506382624, 506564320, 506745952, 506927488, 507108928, 507290272, 507471552, 507652736, 507833824, 508014816, 508195744, 508376576, 508557312, 508737952, 508918528, 509099008, 509279392, 509459680, 509639904, 509820032, 510000064, 510180000, 510359872, 510539648, 510719328, 510898944, 511078432, 511257856, 511437216, 511616448, 511795616, 511974688, 512153664, 512332576, 512511392, 512690112, 512868768, 513047296, 513225792, 513404160, 513582432, 513760640, 513938784, 514116800, 514294752, 514472608, 514650368, 514828064, 515005664, 515183168, 515360608, 515537952, 515715200, 515892352, 516069440, 516246432, 516423328, 516600160, 516776896, 516953536, 517130112, 517306592, 517482976, 517659264, 517835488, 518011616, 518187680, 518363648, 518539520, 518715296, 518891008, 519066624, 519242144, 519417600, 519592960, 519768256, 519943424, 520118528, 520293568, 520468480, 520643328, 520818112, 520992800, 521167392, 521341888, 521516320, 521690656, 521864896, 522039072, 522213152, 522387168, 522561056, 522734912, 522908640, 523082304, 523255872, 523429376, 523602784, 523776096, 523949312, 524122464, 524295552, 524468512, 524641440, 524814240, 524986976, 525159616, 525332192, 525504640, 525677056, 525849344, 526021568, 526193728, 526365792, 526537760, 526709632, 526881440, 527053152, 527224800, 527396352, 527567840, 527739200, 527910528, 528081728, 528252864, 528423936, 528594880, 528765760, 528936576, 529107296, 529277920, 529448480, 529618944, 529789344, 529959648, 530129856, 530300000, 530470048, 530640000, 530809888, 530979712, 531149440, 531319072, 531488608, 531658080, 531827488, 531996800, 532166016, 532335168, 532504224, 532673184, 532842080, 533010912, 533179616, 533348288, 533516832, 533685312, 533853728, 534022048, 534190272, 534358432, 534526496, 534694496, 534862400, 535030240, 535197984, 535365632, 535533216, 535700704, 535868128, 536035456, 536202720, 536369888, 536536992, 536704000, 536870912 }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- int SlopeDiv(unsigned num, unsigned den) { unsigned ans; if(den < 512) return SLOPERANGE; ans = (num << 3) / (den >> 8); return ans <= SLOPERANGE ? ans : SLOPERANGE; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_enemy.c0000644000175000017500000014354111357170242022255 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.c: Enemy thinking, AI (jDoom-specific). * * Action Pointer Functions that are associated with states/frames. */ // HEADER FILES ------------------------------------------------------------ #include #ifdef MSVC # pragma optimize("g", off) #endif #include "jdoom.h" #include "dmu_lib.h" #include "p_map.h" #include "p_mapspec.h" #include "p_door.h" #include "p_floor.h" // MACROS ------------------------------------------------------------------ #define FATSPREAD (ANG90/8) #define SKULLSPEED (20) #define TRACEANGLE (0xc000000) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean bossKilled; mobj_t **brainTargets; int numBrainTargets; int numBrainTargetsAlloc; braindata_t brain; // Global state of boss brain. // PRIVATE DATA DEFINITIONS ------------------------------------------------ static mobj_t *corpseHit; static mobj_t *vileObj; static float vileTry[3]; static float dropoffDelta[2], floorZ; // Eight directional movement speeds. #define MOVESPEED_DIAGONAL (0.71716309f) static const float dirSpeed[8][2] = { {1, 0}, {MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {0, 1}, {-MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {-1, 0}, {-MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL}, {0, -1}, {MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL} }; #undef MOVESPEED_DIAGONAL // CODE -------------------------------------------------------------------- /** * If a monster yells at a player, it will alert other monsters to the * player's whereabouts. */ void P_NoiseAlert(mobj_t *target, mobj_t *emitter) { VALIDCOUNT++; P_RecursiveSound(target, P_GetPtrp(emitter->subsector, DMU_SECTOR), 0); } static boolean checkMeleeRange(mobj_t *actor) { mobj_t *pl; float dist, range; if(!actor->target) return false; pl = actor->target; dist = P_ApproxDistance(pl->pos[VX] - actor->pos[VX], pl->pos[VY] - actor->pos[VY]); if(!cfg.netNoMaxZMonsterMeleeAttack) { // Account for Z height difference. if(pl->pos[VZ] > actor->pos[VZ] + actor->height || pl->pos[VZ] + pl->height < actor->pos[VZ]) return false; } range = MELEERANGE - 20 + pl->info->radius; if(dist >= range) return false; if(!P_CheckSight(actor, actor->target)) return false; return true; } static boolean checkMissileRange(mobj_t *actor) { float dist; if(!P_CheckSight(actor, actor->target)) return false; if(actor->flags & MF_JUSTHIT) { // The target just hit the enemy, so fight back! actor->flags &= ~MF_JUSTHIT; return true; } if(actor->reactionTime) return false; // Do not attack yet. dist = P_ApproxDistance(actor->pos[VX] - actor->target->pos[VX], actor->pos[VY] - actor->target->pos[VY]) - 64; if(P_GetState(actor->type, SN_MELEE) == S_NULL) dist -= 128; // No melee attack, so fire more. if(actor->type == MT_VILE) { if(dist > 14 * 64) return false; // Too far away. } if(actor->type == MT_UNDEAD) { if(dist < 196) return false; // Close for fist attack. dist /= 2; } if(actor->type == MT_CYBORG || actor->type == MT_SPIDER || actor->type == MT_SKULL) { dist /= 2; } if(dist > 200) dist = 200; if(actor->type == MT_CYBORG && dist > 160) dist = 160; if((float) P_Random() < dist) return false; return true; } /** * Move in the current direction if not blocked. * * @return @c false, if the move is blocked. */ static boolean moveMobj(mobj_t *actor, boolean dropoff) { float pos[3], step[3]; linedef_t *ld; boolean good; if(actor->moveDir == DI_NODIR) return false; if((unsigned) actor->moveDir >= DI_NODIR) Con_Error("Weird actor->moveDir!"); step[VX] = actor->info->speed * dirSpeed[actor->moveDir][MX]; step[VY] = actor->info->speed * dirSpeed[actor->moveDir][MY]; pos[VX] = actor->pos[VX] + step[VX]; pos[VY] = actor->pos[VY] + step[VY]; // $dropoff_fix if(!P_TryMove(actor, pos[VX], pos[VY], dropoff, false)) { // Open any specials. if((actor->flags & MF_FLOAT) && floatOk) { // Must adjust height. if(actor->pos[VZ] < tmFloorZ) actor->pos[VZ] += FLOATSPEED; else actor->pos[VZ] -= FLOATSPEED; actor->flags |= MF_INFLOAT; return true; } if(!P_IterListSize(spechit)) return false; actor->moveDir = DI_NODIR; good = false; while((ld = P_PopIterList(spechit)) != NULL) { /** * If the special is not a door that can be opened, return false. * * $unstuck: This is what caused monsters to get stuck in * doortracks, because it thought that the monster freed itself * by opening a door, even if it was moving towards the * doortrack, and not the door itself. * * If a line blocking the monster is activated, return true 90% * of the time. If a line blocking the monster is not activated, * but some other line is, return false 90% of the time. * A bit of randomness is needed to ensure it's free from * lockups, but for most cases, it returns the correct result. * * Do NOT simply return false 1/4th of the time (causes monsters * to back out when they shouldn't, and creates secondary * stickiness). */ if(P_ActivateLine(ld, actor, 0, SPAC_USE)) good |= ld == blockLine ? 1 : 2; } if(!good || cfg.monstersStuckInDoors) return good; else return (P_Random() >= 230) || (good & 1); } else { P_MobjSetSRVO(actor, step[VX], step[VY]); actor->flags &= ~MF_INFLOAT; } // $dropoff_fix: fall more slowly, under gravity, if fellDown==true if(!(actor->flags & MF_FLOAT) && !fellDown) { if(actor->pos[VZ] > actor->floorZ) P_HitFloor(actor); actor->pos[VZ] = actor->floorZ; } return true; } /** * Attempts to move actor on in its current (ob->moveangle) direction. * If blocked by either a wall or an actor returns FALSE * If move is either clear or blocked only by a door, returns TRUE and sets... * If a door is in the way, an OpenDoor call is made to start it opening. */ static boolean tryMoveMobj(mobj_t *actor) { // $dropoff_fix if(!moveMobj(actor, false)) { return false; } actor->moveCount = P_Random() & 15; return true; } static void doNewChaseDir(mobj_t *actor, float deltaX, float deltaY) { dirtype_t xdir, ydir, tdir; dirtype_t olddir = actor->moveDir; dirtype_t turnaround = olddir; if(turnaround != DI_NODIR) // Find reverse direction. turnaround ^= 4; xdir = (deltaX > 10 ? DI_EAST : deltaX < -10 ? DI_WEST : DI_NODIR); ydir = (deltaY < -10 ? DI_SOUTH : deltaY > 10 ? DI_NORTH : DI_NODIR); // Try direct route. if(xdir != DI_NODIR && ydir != DI_NODIR && turnaround != (actor->moveDir = deltaY < 0 ? deltaX > 0 ? DI_SOUTHEAST : DI_SOUTHWEST : deltaX > 0 ? DI_NORTHEAST : DI_NORTHWEST) && tryMoveMobj(actor)) return; // Try other directions. if(P_Random() > 200 || fabs(deltaY) > fabs(deltaX)) { dirtype_t temp = xdir; xdir = ydir; ydir = temp; } if((xdir == turnaround ? xdir = DI_NODIR : xdir) != DI_NODIR && (actor->moveDir = xdir, tryMoveMobj(actor))) return; // Either moved forward or attacked. if((ydir == turnaround ? ydir = DI_NODIR : ydir) != DI_NODIR && (actor->moveDir = ydir, tryMoveMobj(actor))) return; // There is no direct path to the player, so pick another direction. if(olddir != DI_NODIR && (actor->moveDir = olddir, tryMoveMobj(actor))) return; // Randomly determine direction of search. if(P_Random() & 1) { for(tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) if(tdir != turnaround && (actor->moveDir = tdir, tryMoveMobj(actor))) return; } else { for(tdir = DI_SOUTHEAST; tdir != DI_EAST - 1; tdir--) if(tdir != turnaround && (actor->moveDir = tdir, tryMoveMobj(actor))) return; } if((actor->moveDir = turnaround) != DI_NODIR && !tryMoveMobj(actor)) actor->moveDir = DI_NODIR; } /** * Monsters try to move away from tall dropoffs. * * In Doom, they were never allowed to hang over dropoffs, and would remain * stuck if involuntarily forced over one. This logic, combined with * p_map.c::P_TryMove(), allows monsters to free themselves without making * them tend to hang over dropoffs. */ static boolean PIT_AvoidDropoff(linedef_t* line, void* data) { sector_t* backsector = P_GetPtrp(line, DMU_BACK_SECTOR); float* bbox = P_GetPtrp(line, DMU_BOUNDING_BOX); if(backsector && tmBBox[BOXRIGHT] > bbox[BOXLEFT] && tmBBox[BOXLEFT] < bbox[BOXRIGHT] && tmBBox[BOXTOP] > bbox[BOXBOTTOM] && // Linedef must be contacted tmBBox[BOXBOTTOM] < bbox[BOXTOP] && P_BoxOnLineSide(tmBBox, line) == -1) { sector_t* frontsector = P_GetPtrp(line, DMU_FRONT_SECTOR); float front = P_GetFloatp(frontsector, DMU_FLOOR_HEIGHT); float back = P_GetFloatp(backsector, DMU_FLOOR_HEIGHT); float d1[2]; angle_t angle; P_GetFloatpv(line, DMU_DXY, d1); // The monster must contact one of the two floors, and the other // must be a tall drop off (more than 24). if(back == floorZ && front < floorZ - 24) { angle = R_PointToAngle2(0, 0, d1[0], d1[1]); // Front side drop off. } else { if(front == floorZ && back < floorZ - 24) angle = R_PointToAngle2(d1[0], d1[1], 0, 0); // Back side drop off. else return true; } // Move away from drop off at a standard speed. // Multiple contacted linedefs are cumulative (e.g. hanging over corner) dropoffDelta[VX] -= FIX2FLT(finesine[angle >> ANGLETOFINESHIFT]) * 32; dropoffDelta[VY] += FIX2FLT(finecosine[angle >> ANGLETOFINESHIFT]) * 32; } return true; } /** * Driver for above. */ static boolean avoidDropoff(mobj_t *actor) { floorZ = actor->pos[VZ]; // Remember floor height. dropoffDelta[VX] = dropoffDelta[VY] = 0; VALIDCOUNT++; // Check lines. P_MobjLinesIterator(actor, PIT_AvoidDropoff, 0); // Non-zero if movement prescribed. return !(dropoffDelta[VX] == 0 || dropoffDelta[VY] == 0); } static void newChaseDir(mobj_t *actor) { mobj_t *target = actor->target; float deltaX = target->pos[VX] - actor->pos[VX]; float deltaY = target->pos[VY] - actor->pos[VY]; if(actor->floorZ - actor->dropOffZ > 24 && actor->pos[VZ] <= actor->floorZ && !(actor->flags & (MF_DROPOFF | MF_FLOAT)) && !cfg.avoidDropoffs && avoidDropoff(actor)) { // Move away from dropoff. doNewChaseDir(actor, dropoffDelta[VX], dropoffDelta[VY]); // $dropoff_fix // If moving away from drop off, set movecount to 1 so that // small steps are taken to get monster away from drop off. actor->moveCount = 1; return; } doNewChaseDir(actor, deltaX, deltaY); } /** * If allaround is false, only look 180 degrees in front. * * @return @c true, if a player is targeted. */ static boolean lookForPlayers(mobj_t *actor, boolean allAround) { int c, stop, playerCount; player_t *player; angle_t an; float dist; playerCount = 0; for(c = 0; c < MAXPLAYERS; ++c) { if(players[c].plr->inGame) playerCount++; } // Are there any players? if(!playerCount) return false; c = 0; stop = (actor->lastLook - 1) & 3; for(;; actor->lastLook = (actor->lastLook + 1) & 3) { if(!players[actor->lastLook].plr->inGame) continue; if(c++ == 2 || actor->lastLook == stop) { // Done looking. return false; } player = &players[actor->lastLook]; if(P_MobjIsCamera(player->plr->mo)) continue; if(player->health <= 0) continue; // Player is already dead. if(!P_CheckSight(actor, player->plr->mo)) continue; // Player is out of sight. if(!allAround) { an = R_PointToAngle2(actor->pos[VX], actor->pos[VY], player->plr->mo->pos[VX], player->plr->mo->pos[VY]); an -= actor->angle; if(an > ANG90 && an < ANG270) { dist = P_ApproxDistance(player->plr->mo->pos[VX] - actor->pos[VX], player->plr->mo->pos[VY] - actor->pos[VY]); // If real close, react anyway. if(dist > MELEERANGE) continue; // Behind back. } } actor->target = player->plr->mo; return true; } } static boolean massacreMobj(thinker_t* th, void* context) { int* count = (int*) context; mobj_t* mo = (mobj_t *) th; if(!mo->player && sentient(mo) && (mo->flags & MF_SHOOTABLE)) { P_DamageMobj(mo, NULL, NULL, 10000, false); (*count)++; } return true; // Continue iteration. } /** * Kills all monsters. */ int P_Massacre(void) { int count = 0; // Only massacre when actually in a map. if(G_GetGameState() == GS_MAP) { DD_IterateThinkers(P_MobjThinker, massacreMobj, &count); } return count; } static boolean findBrainTarget(thinker_t* th, void* context) { mobj_t* mo = (mobj_t *) th; if(mo->type == MT_BOSSTARGET) { if(numBrainTargets >= numBrainTargetsAlloc) { // Do we need to alloc more targets? if(numBrainTargets == numBrainTargetsAlloc) { numBrainTargetsAlloc *= 2; brainTargets = Z_Realloc(brainTargets, numBrainTargetsAlloc * sizeof(*brainTargets), PU_MAP); } else { numBrainTargetsAlloc = 32; brainTargets = Z_Malloc(numBrainTargetsAlloc * sizeof(*brainTargets), PU_MAP, NULL); } } brainTargets[numBrainTargets++] = mo; } return true; // Continue iteration. } /** * Initialize boss brain targets at map startup, rather than at boss * wakeup, to prevent savegame-related crashes. * * \todo Does not belong in this file, find it a better home. */ void P_SpawnBrainTargets(void) { // Find all the target spots. DD_IterateThinkers(P_MobjThinker, findBrainTarget, NULL); } typedef struct { mobjtype_t type; size_t count; } countmobjoftypeparams_t; static boolean countMobjOfType(thinker_t* th, void* context) { countmobjoftypeparams_t *params = (countmobjoftypeparams_t*) context; mobj_t* mo = (mobj_t *) th; if(params->type == mo->type && mo->health > 0) params->count++; return true; // Continue iteration. } /** * DOOM II special, map 32. Uses special tag 666. */ void C_DECL A_KeenDie(mobj_t* mo) { countmobjoftypeparams_t params; A_Fall(mo); // Check if there are no more Keens left in the map. params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(!params.count) { // No Keens left alive. linedef_t* dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoDoor(dummyLine, DT_OPEN); P_FreeDummyLine(dummyLine); } } /** * Stay in state until a player is sighted. */ void C_DECL A_Look(mobj_t* actor) { sector_t* sec = NULL; mobj_t* targ; sec = P_GetPtrp(actor->subsector, DMU_SECTOR); if(!sec) return; actor->threshold = 0; // Any shot will wake us up. targ = P_ToXSector(sec)->soundTarget; if(targ && (targ->flags & MF_SHOOTABLE)) { actor->target = targ; if(actor->flags & MF_AMBUSH) { if(P_CheckSight(actor, actor->target)) goto seeyou; } else goto seeyou; } if(!lookForPlayers(actor, false)) return; // Go into chase state. seeyou: if(actor->info->seeSound) { int sound; switch(actor->info->seeSound) { case SFX_POSIT1: case SFX_POSIT2: case SFX_POSIT3: sound = SFX_POSIT1 + P_Random() % 3; break; case SFX_BGSIT1: case SFX_BGSIT2: sound = SFX_BGSIT1 + P_Random() % 2; break; default: sound = actor->info->seeSound; break; } if(actor->flags2 & MF2_BOSS) { // Full volume. S_StartSound(sound | DDSF_NO_ATTENUATION, actor); } else { S_StartSound(sound, actor); } } P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } /** * Actor has a melee attack, so it tries to close as fast as possible. */ void C_DECL A_Chase(mobj_t* actor) { int delta; statenum_t state; if(actor->reactionTime) actor->reactionTime--; // Modify target threshold. if(actor->threshold) { if(!actor->target || actor->target->health <= 0) { actor->threshold = 0; } else actor->threshold--; } // Turn towards movement direction if not there yet. if(actor->moveDir < DI_NODIR) { actor->angle &= (7 << 29); delta = actor->angle - (actor->moveDir << 29); if(delta > 0) actor->angle -= ANG90 / 2; else if(delta < 0) actor->angle += ANG90 / 2; } if(!actor->target || !(actor->target->flags & MF_SHOOTABLE) || P_MobjIsCamera(actor->target)) { // Look for a new target. if(lookForPlayers(actor, true)) { // Got a new target. } else { P_MobjChangeState(actor, P_GetState(actor->type, SN_SPAWN)); } return; } // Do not attack twice in a row. if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if(gameSkill != SM_NIGHTMARE && !fastParm) newChaseDir(actor); return; } // Check for melee attack. if((state = P_GetState(actor->type, SN_MELEE)) != S_NULL && checkMeleeRange(actor)) { if(actor->info->attackSound) S_StartSound(actor->info->attackSound, actor); P_MobjChangeState(actor, state); return; } // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { if(!(gameSkill < SM_NIGHTMARE && !fastParm && actor->moveCount)) { if(checkMissileRange(actor)) { P_MobjChangeState(actor, state); actor->flags |= MF_JUSTATTACKED; return; } } } // Possibly choose another target. if(IS_NETGAME && !actor->threshold && !P_CheckSight(actor, actor->target)) { if(lookForPlayers(actor, true)) return; // Got a new target. } // Chase towards player. if(--actor->moveCount < 0 || !moveMobj(actor, false)) { newChaseDir(actor); } // Make active sound. if(actor->info->activeSound && P_Random() < 3) { S_StartSound(actor->info->activeSound, actor); } } void C_DECL A_FaceTarget(mobj_t *actor) { if(!actor->target) return; actor->turnTime = true; // $visangle-facetarget actor->flags &= ~MF_AMBUSH; actor->angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], actor->target->pos[VX], actor->target->pos[VY]); if(actor->target->flags & MF_SHADOW) actor->angle += (P_Random() - P_Random()) << 21; } void C_DECL A_PosAttack(mobj_t *actor) { int damage; angle_t angle; float slope; if(!actor->target) return; A_FaceTarget(actor); angle = actor->angle; slope = P_AimLineAttack(actor, angle, MISSILERANGE); S_StartSound(SFX_PISTOL, actor); angle += (P_Random() - P_Random()) << 20; damage = ((P_Random() % 5) + 1) * 3; P_LineAttack(actor, angle, MISSILERANGE, slope, damage); } void C_DECL A_SPosAttack(mobj_t *actor) { int i, damage; angle_t angle, bangle; float slope; if(!actor->target) return; S_StartSound(SFX_SHOTGN, actor); A_FaceTarget(actor); bangle = actor->angle; slope = P_AimLineAttack(actor, bangle, MISSILERANGE); for(i = 0; i < 3; ++i) { angle = bangle + ((P_Random() - P_Random()) << 20); damage = ((P_Random() % 5) + 1) * 3; P_LineAttack(actor, angle, MISSILERANGE, slope, damage); } } void C_DECL A_CPosAttack(mobj_t* actor) { int angle, bangle, damage; float slope; if(!actor->target) return; S_StartSound(SFX_SHOTGN, actor); A_FaceTarget(actor); bangle = actor->angle; slope = P_AimLineAttack(actor, bangle, MISSILERANGE); angle = bangle + ((P_Random() - P_Random()) << 20); damage = ((P_Random() % 5) + 1) * 3; P_LineAttack(actor, angle, MISSILERANGE, slope, damage); } void C_DECL A_CPosRefire(mobj_t* actor) { // Keep firing unless target got out of sight. A_FaceTarget(actor); if(P_Random() < 40) return; if(!actor->target || actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) { P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } } void C_DECL A_SpidRefire(mobj_t* actor) { // Keep firing unless target got out of sight. A_FaceTarget(actor); if(P_Random() < 10) return; if(!actor->target || actor->target->health <= 0 || !P_CheckSight(actor, actor->target)) { P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } } void C_DECL A_BspiAttack(mobj_t *actor) { if(!actor->target) return; A_FaceTarget(actor); // Launch a missile. P_SpawnMissile(MT_ARACHPLAZ, actor, actor->target); } void C_DECL A_TroopAttack(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { S_StartSound(SFX_CLAW, actor); damage = (P_Random() % 8 + 1) * 3; P_DamageMobj(actor->target, actor, actor, damage, false); return; } P_SpawnMissile(MT_TROOPSHOT, actor, actor->target); } void C_DECL A_SargAttack(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { damage = ((P_Random() % 10) + 1) * 4; P_DamageMobj(actor->target, actor, actor, damage, false); } } void C_DECL A_HeadAttack(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { damage = (P_Random() % 6 + 1) * 10; P_DamageMobj(actor->target, actor, actor, damage, false); return; } // Launch a missile. P_SpawnMissile(MT_HEADSHOT, actor, actor->target); } /** * Cyber Demon: Missile Attack. */ void C_DECL A_CyberAttack(mobj_t *actor) { if(!actor->target) return; A_FaceTarget(actor); P_SpawnMissile(MT_ROCKET, actor, actor->target); } void C_DECL A_BruisAttack(mobj_t *actor) { int damage; if(!actor->target) return; if(checkMeleeRange(actor)) { S_StartSound(SFX_CLAW, actor); damage = (P_Random() % 8 + 1) * 10; P_DamageMobj(actor->target, actor, actor, damage, false); return; } // Launch a missile. P_SpawnMissile(MT_BRUISERSHOT, actor, actor->target); } void C_DECL A_SkelMissile(mobj_t *actor) { mobj_t *mo; if(!actor->target) return; A_FaceTarget(actor); mo = P_SpawnMissile(MT_TRACER, actor, actor->target); if(mo) { mo->pos[VX] += mo->mom[MX]; mo->pos[VY] += mo->mom[MY]; mo->tracer = actor->target; } } void C_DECL A_Tracer(mobj_t* actor) { uint an; angle_t angle; float dist; float slope; mobj_t* dest, *th; if((int) GAMETIC & 3) return; // Spawn a puff of smoke behind the rocket. P_SpawnCustomPuff(MT_ROCKETPUFF, actor->pos[VX], actor->pos[VY], actor->pos[VZ], actor->angle + ANG180); if((th = P_SpawnMobj3f(MT_SMOKE, actor->pos[VX] - actor->mom[MX], actor->pos[VY] - actor->mom[MY], actor->pos[VZ], actor->angle + ANG180, 0))) { th->mom[MZ] = FIX2FLT(FRACUNIT); th->tics -= P_Random() & 3; if(th->tics < 1) th->tics = 1; } // Adjust direction. dest = actor->tracer; if(!dest || dest->health <= 0) return; // Change angle. angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], dest->pos[VX], dest->pos[VY]); if(angle != actor->angle) { if(angle - actor->angle > 0x80000000) { actor->angle -= TRACEANGLE; if(angle - actor->angle < 0x80000000) actor->angle = angle; } else { actor->angle += TRACEANGLE; if(angle - actor->angle > 0x80000000) actor->angle = angle; } } an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = actor->info->speed * FIX2FLT(finecosine[an]); actor->mom[MY] = actor->info->speed * FIX2FLT(finesine[an]); // Change slope. dist = P_ApproxDistance(dest->pos[VX] - actor->pos[VX], dest->pos[VY] - actor->pos[VY]); dist /= actor->info->speed; if(dist < 1) dist = 1; slope = (dest->pos[VZ] + 40 - actor->pos[VZ]) / dist; if(slope < actor->mom[MZ]) actor->mom[MZ] -= FIX2FLT(FRACUNIT / 8); else actor->mom[MZ] += FIX2FLT(FRACUNIT / 8); } void C_DECL A_SkelWhoosh(mobj_t *actor) { if(!actor->target) return; A_FaceTarget(actor); S_StartSound(SFX_SKESWG, actor); } void C_DECL A_SkelFist(mobj_t *actor) { int damage; if(!actor->target) return; A_FaceTarget(actor); if(checkMeleeRange(actor)) { damage = ((P_Random() % 10) + 1) * 6; S_StartSound(SFX_SKEPCH, actor); P_DamageMobj(actor->target, actor, actor, damage, false); } } /** * Detect a corpse that could be raised. */ boolean PIT_VileCheck(mobj_t *thing, void *data) { float maxdist; boolean check; if(!(thing->flags & MF_CORPSE)) return true; // Not a monster. if(thing->tics != -1) return true; // Not lying still yet. if(P_GetState(thing->type, SN_RAISE) == S_NULL) return true; // Monster doesn't have a raise state. maxdist = thing->info->radius + MOBJINFO[MT_VILE].radius; if(fabs(thing->pos[VX] - vileTry[VX]) > maxdist || fabs(thing->pos[VY] - vileTry[VY]) > maxdist) return true; // Not actually touching. corpseHit = thing; corpseHit->mom[MX] = corpseHit->mom[MY] = 0; // DJS - Used the PRBoom method to fix archvile raising ghosts // If !raiseghosts then ressurect a "normal" MF_SOLID one. if(cfg.raiseGhosts) { corpseHit->height *= 2*2; check = P_CheckPosition2f(corpseHit, corpseHit->pos[VX], corpseHit->pos[VY]); corpseHit->height /= 2*2; } else { float radius, height; height = corpseHit->height; // Save temporarily. radius = corpseHit->radius; // Save temporarily. corpseHit->height = corpseHit->info->height; corpseHit->radius = corpseHit->info->radius; corpseHit->flags |= MF_SOLID; check = P_CheckPosition2f(corpseHit, corpseHit->pos[VX], corpseHit->pos[VY]); corpseHit->height = height; // Restore. corpseHit->radius = radius; // Restore. corpseHit->flags &= ~MF_SOLID; } // End raiseghosts. if(!check) return true; // Doesn't fit here. return false; // Got one, so stop checking. } /** * Check for ressurecting a body. */ void C_DECL A_VileChase(mobj_t *actor) { mobjinfo_t *info; mobj_t *temp; float box[4]; if(actor->moveDir != DI_NODIR) { // Check for corpses to raise. vileTry[VX] = actor->pos[VX] + actor->info->speed * dirSpeed[actor->moveDir][VX]; vileTry[VY] = actor->pos[VY] + actor->info->speed * dirSpeed[actor->moveDir][VY]; box[BOXLEFT] = vileTry[VX] - MAXRADIUS * 2; box[BOXRIGHT] = vileTry[VX] + MAXRADIUS * 2; box[BOXBOTTOM] = vileTry[VY] - MAXRADIUS * 2; box[BOXTOP] = vileTry[VY] + MAXRADIUS * 2; vileObj = actor; // Call PIT_VileCheck to check whether object is a corpse // that can be raised. VALIDCOUNT++; if(!P_MobjsBoxIterator(box, PIT_VileCheck, 0)) { // Got one! temp = actor->target; actor->target = corpseHit; A_FaceTarget(actor); actor->target = temp; P_MobjChangeState(actor, S_VILE_HEAL1); S_StartSound(SFX_SLOP, corpseHit); info = corpseHit->info; P_MobjChangeState(corpseHit, P_GetState(corpseHit->type, SN_RAISE)); if(cfg.raiseGhosts) { corpseHit->height *= 2*2; } else { corpseHit->height = info->height; corpseHit->radius = info->radius; } corpseHit->flags = info->flags; corpseHit->health = info->spawnHealth; corpseHit->target = NULL; corpseHit->corpseTics = 0; return; } } // Return to normal attack. A_Chase(actor); } void C_DECL A_VileStart(mobj_t *actor) { S_StartSound(SFX_VILATK, actor); } void C_DECL A_StartFire(mobj_t *actor) { S_StartSound(SFX_FLAMST, actor); A_Fire(actor); } void C_DECL A_FireCrackle(mobj_t *actor) { S_StartSound(SFX_FLAME, actor); A_Fire(actor); } /** * Keep fire in front of player unless out of sight. */ void C_DECL A_Fire(mobj_t *actor) { mobj_t *dest; uint an; dest = actor->tracer; if(!dest) return; // Don't move it if the vile lost sight. if(!P_CheckSight(actor->target, dest)) return; an = dest->angle >> ANGLETOFINESHIFT; P_MobjUnsetPosition(actor); memcpy(actor->pos, dest->pos, sizeof(actor->pos)); actor->pos[VX] += 24 * FIX2FLT(finecosine[an]); actor->pos[VY] += 24 * FIX2FLT(finesine[an]); P_MobjSetPosition(actor); } /** * Spawn the archviles' hellfire */ void C_DECL A_VileTarget(mobj_t* actor) { mobj_t* fog; if(!actor->target) return; A_FaceTarget(actor); if((fog = P_SpawnMobj3fv(MT_FIRE, actor->target->pos, actor->target->angle + ANG180, 0))) { actor->tracer = fog; fog->target = actor; fog->tracer = actor->target; A_Fire(fog); } } void C_DECL A_VileAttack(mobj_t* actor) { mobj_t* fire; uint an; if(!actor->target) return; A_FaceTarget(actor); if(!P_CheckSight(actor, actor->target)) return; S_StartSound(SFX_BAREXP, actor); P_DamageMobj(actor->target, actor, actor, 20, false); actor->target->mom[MZ] = FIX2FLT(1000 * FRACUNIT / actor->target->info->mass); an = actor->angle >> ANGLETOFINESHIFT; fire = actor->tracer; if(!fire) return; // Move the fire between the Vile and the player. fire->pos[VX] = actor->target->pos[VX] - 24 * FIX2FLT(finecosine[an]); fire->pos[VY] = actor->target->pos[VY] - 24 * FIX2FLT(finesine[an]); P_RadiusAttack(fire, actor, 70, 69); } void C_DECL A_FatRaise(mobj_t *actor) { A_FaceTarget(actor); S_StartSound(SFX_MANATK, actor); } /** * Mancubus attack: */ void C_DECL A_FatAttack1(mobj_t *actor) { mobj_t *mo; uint an; A_FaceTarget(actor); // Change direction to... actor->angle += FATSPREAD; P_SpawnMissile(MT_FATSHOT, actor, actor->target); mo = P_SpawnMissile(MT_FATSHOT, actor, actor->target); if(mo) { mo->angle += FATSPREAD; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); } } void C_DECL A_FatAttack2(mobj_t *actor) { mobj_t *mo; uint an; A_FaceTarget(actor); // Now here choose opposite deviation. actor->angle -= FATSPREAD; P_SpawnMissile(MT_FATSHOT, actor, actor->target); mo = P_SpawnMissile(MT_FATSHOT, actor, actor->target); if(mo) { mo->angle -= FATSPREAD * 2; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); } } void C_DECL A_FatAttack3(mobj_t *actor) { mobj_t *mo; uint an; A_FaceTarget(actor); mo = P_SpawnMissile(MT_FATSHOT, actor, actor->target); if(mo) { mo->angle -= FATSPREAD / 2; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); } mo = P_SpawnMissile(MT_FATSHOT, actor, actor->target); if(mo) { mo->angle += FATSPREAD / 2; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); } } /** * LostSoul Attack: Fly at the player like a missile. */ void C_DECL A_SkullAttack(mobj_t *actor) { mobj_t *dest; uint an; float dist; if(!actor->target) return; dest = actor->target; actor->flags |= MF_SKULLFLY; S_StartSound(actor->info->attackSound, actor); A_FaceTarget(actor); an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = SKULLSPEED * FIX2FLT(finecosine[an]); actor->mom[MY] = SKULLSPEED * FIX2FLT(finesine[an]); dist = P_ApproxDistance(dest->pos[VX] - actor->pos[VX], dest->pos[VY] - actor->pos[VY]); dist /= SKULLSPEED; if(dist < 1) dist = 1; actor->mom[MZ] = (dest->pos[VZ] + (dest->height / 2) - actor->pos[VZ]) / dist; } /** * PainElemental Attack: Spawn a lost soul and launch it at the target. */ void C_DECL A_PainShootSkull(mobj_t* actor, angle_t angle) { float pos[3]; mobj_t* newmobj; uint an; float prestep; sector_t* sec; if(cfg.maxSkulls) { // Limit the number of MT_SKULL's we should spawn. countmobjoftypeparams_t params; // Count total number currently on the map. params.type = MT_SKULL; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(params.count > 20) return; // Too many, don't spit another. } an = angle >> ANGLETOFINESHIFT; prestep = 4 + 3 * ((actor->info->radius + MOBJINFO[MT_SKULL].radius) / 2); memcpy(pos, actor->pos, sizeof(pos)); pos[VX] += prestep * FIX2FLT(finecosine[an]); pos[VY] += prestep * FIX2FLT(finesine[an]); pos[VZ] += 8; // Compat option to prevent spawning lost souls inside walls. if(!cfg.allowSkullsInWalls) { /** * Check whether the Lost Soul is being fired through a 1-sided * wall or an impassible line, or a "monsters can't cross" line. * If it is, then we don't allow the spawn. */ if(P_CheckSides(actor, pos[VX], pos[VY])) return; if(!(newmobj = P_SpawnMobj3fv(MT_SKULL, pos, angle, 0))) return; sec = P_GetPtrp(newmobj->subsector, DMU_SECTOR); // Check to see if the new Lost Soul's z value is above the // ceiling of its new sector, or below the floor. If so, kill it. if((newmobj->pos[VZ] > (P_GetFloatp(sec, DMU_CEILING_HEIGHT) - newmobj->height)) || (newmobj->pos[VZ] < P_GetFloatp(sec, DMU_FLOOR_HEIGHT))) { // Kill it immediately. P_DamageMobj(newmobj, actor, actor, 10000, false); return; } } else { // Use the original DOOM method. if(!(newmobj = P_SpawnMobj3fv(MT_SKULL, pos, angle, 0))) return; } // Check for movements, $dropoff_fix. if(!P_TryMove(newmobj, newmobj->pos[VX], newmobj->pos[VY], false, false)) { // Kill it immediately. P_DamageMobj(newmobj, actor, actor, 10000, false); return; } newmobj->target = actor->target; A_SkullAttack(newmobj); } /** * PainElemental Attack: Spawn a lost soul and launch it at the target. */ void C_DECL A_PainAttack(mobj_t *actor) { if(!actor->target) return; A_FaceTarget(actor); A_PainShootSkull(actor, actor->angle); } void C_DECL A_PainDie(mobj_t *actor) { A_Fall(actor); A_PainShootSkull(actor, actor->angle + ANG90); A_PainShootSkull(actor, actor->angle + ANG180); A_PainShootSkull(actor, actor->angle + ANG270); } void C_DECL A_Scream(mobj_t *actor) { int sound; switch(actor->info->deathSound) { case 0: return; case SFX_PODTH1: case SFX_PODTH2: case SFX_PODTH3: sound = SFX_PODTH1 + P_Random() % 3; break; case SFX_BGDTH1: case SFX_BGDTH2: sound = SFX_BGDTH1 + P_Random() % 2; break; default: sound = actor->info->deathSound; break; } // Check for bosses. if(actor->type == MT_SPIDER || actor->type == MT_CYBORG) { // Full volume. S_StartSound(sound | DDSF_NO_ATTENUATION, NULL); } else { // Normal volume. S_StartSound(sound, actor); } } void C_DECL A_XScream(mobj_t* actor) { S_StartSound(SFX_SLOP, actor); } void C_DECL A_Pain(mobj_t* actor) { if(actor->info->painSound) S_StartSound(actor->info->painSound, actor); } void C_DECL A_Fall(mobj_t* actor) { // Actor is on ground, it can be walked over. actor->flags &= ~MF_SOLID; } void C_DECL A_Explode(mobj_t* mo) { P_RadiusAttack(mo, mo->target, 128, 127); } /** * Possibly trigger special effects if on first boss map. */ void C_DECL A_BossDeath(mobj_t* mo) { int i; linedef_t* dummyLine; countmobjoftypeparams_t params; // Has the boss already been killed? if(bossKilled) return; if(gameMode == commercial) { if(gameMap != 6) return; if((mo->type != MT_FATSO) && (mo->type != MT_BABY)) return; } else { switch(gameEpisode) { case 0: if(gameMap != 7) return; /** * Ultimate DOOM behavioral change: * This test was added so that the (variable) effects of the * 666 special would only take effect when the last Baron * died and not ANY monster. * Many classic PWADS such as "Doomsday of UAC" (UAC_DEAD.wad) * relied on the old behaviour and cannot be completed. */ // Added compatibility option. if(!cfg.anyBossDeath) if(mo->type != MT_BRUISER) return; break; case 1: if(gameMap != 7) return; if(mo->type != MT_CYBORG) return; break; case 2: if(gameMap != 7) return; if(mo->type != MT_SPIDER) return; break; case 3: switch(gameMap) { case 5: if(mo->type != MT_CYBORG) return; break; case 7: if(mo->type != MT_SPIDER) return; break; default: return; break; } break; default: if(gameMap != 7) return; break; } } // Make sure there is a player alive for victory... for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame && players[i].health > 0) break; } if(i == MAXPLAYERS) return; // No one left alive, so do not end game. // Scan the remaining thinkers to see if all bosses are dead. params.type = mo->type; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); if(params.count) { // Other boss not dead. return; } // Victory! if(gameMode == commercial) { if(gameMap == 6) { if(mo->type == MT_FATSO) { dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoFloor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); return; } if(mo->type == MT_BABY) { dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 667; EV_DoFloor(dummyLine, FT_RAISETOTEXTURE); P_FreeDummyLine(dummyLine); // Only activate once (rare, "DOOM2::MAP07-Dead Simple" bug). bossKilled = true; return; } } } else { switch(gameEpisode) { case 0: dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoFloor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); bossKilled = true; return; case 3: switch(gameMap) { case 5: dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoDoor(dummyLine, DT_BLAZEOPEN); P_FreeDummyLine(dummyLine); bossKilled = true; return; case 7: dummyLine = P_AllocDummyLine(); P_ToXLine(dummyLine)->tag = 666; EV_DoFloor(dummyLine, FT_LOWERTOLOWEST); P_FreeDummyLine(dummyLine); bossKilled = true; return; default: break; } break; default: break; } } G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, false); } void C_DECL A_Hoof(mobj_t *mo) { /** * \kludge Only play very loud sounds in map 8. * \todo: Implement a MAPINFO option for this. */ S_StartSound(SFX_HOOF | (gameMode != commercial && gameMap == 7 ? DDSF_NO_ATTENUATION : 0), mo); A_Chase(mo); } void C_DECL A_Metal(mobj_t *mo) { /** * \kludge Only play very loud sounds in map 8. * \todo: Implement a MAPINFO option for this. */ S_StartSound(SFX_METAL | (gameMode != commercial && gameMap == 7 ? DDSF_NO_ATTENUATION : 0), mo); A_Chase(mo); } void C_DECL A_BabyMetal(mobj_t *mo) { S_StartSound(SFX_BSPWLK, mo); A_Chase(mo); } void C_DECL A_BrainAwake(mobj_t* mo) { S_StartSound(SFX_BOSSIT, NULL); } void C_DECL A_BrainPain(mobj_t* mo) { S_StartSound(SFX_BOSPN, NULL); } void C_DECL A_BrainScream(mobj_t* mo) { float pos[3]; pos[VY] = mo->pos[VY] - 320; for(pos[VX] = mo->pos[VX] - 196; pos[VX] < mo->pos[VX] + 320; pos[VX] += 8) { mobj_t* th; pos[VZ] = 128 + (P_Random() * 2); if((th = P_SpawnMobj3fv(MT_ROCKET, pos, P_Random() << 24, 0))) { th->mom[MZ] = FIX2FLT(P_Random() * 512); P_MobjChangeState(th, S_BRAINEXPLODE1); th->tics -= P_Random() & 7; if(th->tics < 1) th->tics = 1; } } S_StartSound(SFX_BOSDTH, NULL); } void C_DECL A_BrainExplode(mobj_t* mo) { float pos[3]; mobj_t* th; pos[VX] = mo->pos[VX] + FIX2FLT((P_Random() - P_Random()) * 2048); pos[VY] = mo->pos[VY]; pos[VZ] = 128 + (P_Random() * 2); if((th = P_SpawnMobj3fv(MT_ROCKET, pos, P_Random() << 24, 0))) { th->mom[MZ] = FIX2FLT(P_Random() * 512); P_MobjChangeState(th, S_BRAINEXPLODE1); th->tics -= P_Random() & 7; if(th->tics < 1) th->tics = 1; } } void C_DECL A_BrainDie(mobj_t *mo) { G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, false); } void C_DECL A_BrainSpit(mobj_t *mo) { mobj_t *targ; mobj_t *newmobj; if(!numBrainTargets) return; // Ignore if no targets. brain.easy ^= 1; if(gameSkill <= SM_EASY && (!brain.easy)) return; // Shoot a cube at current target. targ = brainTargets[brain.targetOn++]; brain.targetOn %= numBrainTargets; // Spawn brain missile. newmobj = P_SpawnMissile(MT_SPAWNSHOT, mo, targ); if(newmobj) { newmobj->target = targ; newmobj->reactionTime = ((targ->pos[VY] - mo->pos[VY]) / newmobj->mom[MY]) / newmobj->state->tics; } S_StartSound(SFX_BOSPIT, NULL); } /** * Travelling cube sound. */ void C_DECL A_SpawnSound(mobj_t *mo) { S_StartSound(SFX_BOSCUB, mo); A_SpawnFly(mo); } void C_DECL A_SpawnFly(mobj_t *mo) { int r; mobj_t *newmobj; mobj_t *fog; mobj_t *targ; mobjtype_t type; if(--mo->reactionTime) return; // Still flying. targ = mo->target; // First spawn teleport fog. if((fog = P_SpawnMobj3fv(MT_SPAWNFIRE, targ->pos, targ->angle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); // Randomly select monster to spawn. r = P_Random(); // Probability distribution (kind of :), decreasing likelihood. if(r < 50) type = MT_TROOP; else if(r < 90) type = MT_SERGEANT; else if(r < 120) type = MT_SHADOWS; else if(r < 130) type = MT_PAIN; else if(r < 160) type = MT_HEAD; else if(r < 162) type = MT_VILE; else if(r < 172) type = MT_UNDEAD; else if(r < 192) type = MT_BABY; else if(r < 222) type = MT_FATSO; else if(r < 246) type = MT_KNIGHT; else type = MT_BRUISER; if((newmobj = P_SpawnMobj3fv(type, targ->pos, P_Random() << 24, 0))) { if(lookForPlayers(newmobj, true)) P_MobjChangeState(newmobj, P_GetState(newmobj->type, SN_SEE)); // Telefrag anything in this spot. P_TeleportMove(newmobj, newmobj->pos[VX], newmobj->pos[VY], false); } // Remove self (i.e., cube). P_MobjRemove(mo, true); } void C_DECL A_PlayerScream(mobj_t *mo) { int sound = SFX_PLDETH; // Default death sound. if((gameMode == commercial) && (mo->health < -50)) { // If the player dies less with less than -50% without gibbing. sound = SFX_PDIEHI; } S_StartSound(sound, mo); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_spec.c0000644000175000017500000012314611357170242022071 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.c: Implements map special effects. * * Texture animation, height or lighting changes according to adjacent * sectors, respective utility functions, etc. * * Line Tag handling. Line and Sector triggers. * * Events are operations triggered by using, crossing, or shooting special * lines, or by timed thinkers. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "m_argv.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_player.h" #include "p_mapspec.h" #include "p_tick.h" #include "p_ceiling.h" #include "p_door.h" #include "p_floor.h" #include "p_plat.h" #include "p_switch.h" #include "d_netsv.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // Animating textures and planes // In Doomsday these are handled via DED definitions. // In BOOM they invented the ANIMATED lump for the same purpose. // This struct is directly read from the lump. // So its important we keep it aligned. #pragma pack(1) typedef struct animdef_s { /* Do NOT change these members in any way */ signed char istexture; // if false, it is a flat (instead of bool) char endname[9]; char startname[9]; int speed; } animdef_t; #pragma pack() // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void crossSpecialLine(linedef_t* line, int side, mobj_t* thing); static void shootSpecialLine(mobj_t* thing, linedef_t* line); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // These arrays are treated as a hardcoded replacements for data that can be // loaded from a lump, so we need to use little-endian byte ordering. static animdef_t animsShared[] = { {0, "BLOOD3", "BLOOD1", MACRO_LONG(8)}, {0, "FWATER4", "FWATER1", MACRO_LONG(8)}, {0, "LAVA4", "LAVA1", MACRO_LONG(8)}, {0, "NUKAGE3", "NUKAGE1", MACRO_LONG(8)}, {1, "BLODRIP4", "BLODRIP1", MACRO_LONG(8)}, {1, "FIREBLU2", "FIREBLU1", MACRO_LONG(8)}, {1, "FIRELAVA", "FIRELAV2", MACRO_LONG(8)}, {1, "FIREMAG3", "FIREMAG1", MACRO_LONG(8)}, {1, "FIREWALL", "FIREWALA", MACRO_LONG(8)}, {1, "GSTFONT3", "GSTFONT1", MACRO_LONG(8)}, {1, "ROCKRED3", "ROCKRED1", MACRO_LONG(8)}, {1, "SLADRIP3", "SLADRIP1", MACRO_LONG(8)}, {1, "WFALL4", "WFALL1", MACRO_LONG(8)}, {1, "BLODGR4", "BLODGR1", MACRO_LONG(8)}, {-1, "\0", "\0"} }; static animdef_t animsDoom2[] = { {0, "RROCK08", "RROCK05", MACRO_LONG(8)}, {0, "SLIME04", "SLIME01", MACRO_LONG(8)}, {0, "SLIME08", "SLIME05", MACRO_LONG(8)}, {0, "SLIME12", "SLIME09", MACRO_LONG(8)}, {1, "BFALL4", "BFALL1", MACRO_LONG(8)}, {1, "DBRAIN4", "DBRAIN1", MACRO_LONG(8)}, {1, "SFALL4", "SFALL1", MACRO_LONG(8)}, {-1, "\0", "\0"} }; // CODE -------------------------------------------------------------------- /** * From PrBoom: * Load the table of animation definitions, checking for existence of * the start and end of each frame. If the start doesn't exist the sequence * is skipped, if the last doesn't exist, BOOM exits. * * Wall/Flat animation sequences, defined by name of first and last frame, * The full animation sequence is given using all lumps between the start * and end entry, in the order found in the WAD file. * * This routine modified to read its data from a predefined lump or * PWAD lump called ANIMATED rather than a static table in this module to * allow wad designers to insert or modify animation sequences. * * Lump format is an array of byte packed animdef_t structures, terminated * by a structure with istexture == -1. The lump can be generated from a * text source file using SWANTBLS.EXE, distributed with the BOOM utils. * The standard list of switches and animations is contained in the example * source text file DEFSWANI.DAT also in the BOOM util distribution. */ static void loadAnimDefs(animdef_t* animDefs) { int i; // Read structures until -1 is found for(i = 0; animDefs[i].istexture != -1 ; ++i) { int groupNum, ticsPerFrame, numFrames; material_namespace_t mnamespace = (animDefs[i].istexture? MN_TEXTURES : MN_FLATS); switch(mnamespace) { case MN_FLATS: { lumpnum_t startFrame, endFrame, n; if((startFrame = W_CheckNumForName(animDefs[i].startname)) == -1 || (endFrame = W_CheckNumForName(animDefs[i].endname)) == -1) continue; numFrames = endFrame - startFrame + 1; ticsPerFrame = LONG(animDefs[i].speed); if(numFrames < 2) Con_Error("P_InitPicAnims: bad cycle from %s to %s", animDefs[i].startname, animDefs[i].endname); if(startFrame && endFrame) { // We have a valid animation. // Create a new animation group for it. groupNum = R_CreateAnimGroup(AGF_SMOOTH); /** * Doomsday's group animation needs to know the texture/flat * numbers of ALL frames in the animation group so we'll * have to step through the directory adding frames as we * go. (DOOM only required the start/end texture/flat * numbers and would animate all textures/flats inbetween). */ VERBOSE(Con_Message("P_InitPicAnims: ADD (\"%s\" > \"%s\" %d)\n", animDefs[i].startname, animDefs[i].endname, ticsPerFrame)); // Add all frames from start to end to the group. if(endFrame > startFrame) { for(n = startFrame; n <= endFrame; n++) { materialnum_t frame = P_MaterialCheckNumForName(W_LumpName(n), MN_FLATS); if(frame != 0) R_AddToAnimGroup(groupNum, frame, ticsPerFrame, 0); } } else { for(n = endFrame; n >= startFrame; n--) { materialnum_t frame = P_MaterialCheckNumForName(W_LumpName(n), MN_FLATS); if(frame != 0) R_AddToAnimGroup(groupNum, frame, ticsPerFrame, 0); } } } break; } case MN_TEXTURES: { // Same as above but for texture groups. materialnum_t startFrame, endFrame, n; if((startFrame = P_MaterialCheckNumForName(animDefs[i].startname, MN_TEXTURES)) == 0 || (endFrame = P_MaterialCheckNumForName(animDefs[i].endname, MN_TEXTURES)) == 0) continue; numFrames = endFrame - startFrame + 1; ticsPerFrame = LONG(animDefs[i].speed); if(numFrames < 2) Con_Error("P_InitPicAnims: bad cycle from %s to %s", animDefs[i].startname, animDefs[i].endname); if(startFrame && endFrame) { groupNum = R_CreateAnimGroup(AGF_SMOOTH); VERBOSE(Con_Message("P_InitPicAnims: ADD (\"%s\" > \"%s\" %d)\n", animDefs[i].startname, animDefs[i].endname, ticsPerFrame)); /** * \fixme Here an assumption is made that MN_TEXTURES type * materials are registered in the same order as they are * defined in the TEXTURE(1...) lump(s). */ if(endFrame > startFrame) { for(n = startFrame; n <= endFrame; n++) R_AddToAnimGroup(groupNum, n, ticsPerFrame, 0); } else { for(n = endFrame; n >= startFrame; n--) R_AddToAnimGroup(groupNum, n, ticsPerFrame, 0); } } break; } default: Con_Error("loadAnimDefs: Internal Error, invalid namespace %i.", (int) mnamespace); } } } void P_InitPicAnims(void) { int lump; // Is there an ANIMATED lump? if((lump = W_CheckNumForName("ANIMATED")) > 0) { animdef_t* animDefs; /** * We'll support this BOOM extension by reading the data and then * registering the new animations into Doomsday using the animation * groups feature. * * Support for this extension should be considered depreciated. * All new features should be added, accessed via DED. */ Con_Message("P_InitPicAnims: \"ANIMATED\" lump found. " "Reading animations...\n"); animDefs = (animdef_t *)W_CacheLumpNum(lump, PU_STATIC); loadAnimDefs(animDefs); Z_Free(animDefs); } else { Con_Message("P_InitPicAnims: Registering default animations...\n"); loadAnimDefs(animsShared); if(gameMode == commercial) { loadAnimDefs(animsDoom2); } } VERBOSE(Con_Message("P_InitPicAnims: Done.\n")); } boolean P_ActivateLine(linedef_t *ld, mobj_t *mo, int side, int actType) { switch(actType) { case SPAC_CROSS: crossSpecialLine(ld, side, mo); return true; case SPAC_USE: return P_UseSpecialLine(mo, ld, side); case SPAC_IMPACT: shootSpecialLine(mo, ld); return true; default: Con_Error("P_ActivateLine: Unknown Activation Type %i", actType); break; } return false; } /** * Called every time a thing origin is about to cross a line with a non 0 * special. */ static void crossSpecialLine(linedef_t *line, int side, mobj_t *thing) { int ok; xline_t *xline; // Extended functionality overrides old. if(XL_CrossLine(line, side, thing)) return; xline = P_ToXLine(line); // Triggers that other things can activate. if(!thing->player) { // Things that should NOT trigger specials... switch(thing->type) { case MT_ROCKET: case MT_PLASMA: case MT_BFG: case MT_TROOPSHOT: case MT_HEADSHOT: case MT_BRUISERSHOT: return; break; default: break; } ok = 0; switch(xline->special) { case 39: // TELEPORT TRIGGER case 97: // TELEPORT RETRIGGER case 125: // TELEPORT MONSTERONLY TRIGGER case 126: // TELEPORT MONSTERONLY RETRIGGER case 4: // RAISE DOOR case 10: // PLAT DOWN-WAIT-UP-STAY TRIGGER case 88: // PLAT DOWN-WAIT-UP-STAY RETRIGGER ok = 1; break; } // Anything can trigger this line! if(xline->flags & ML_ALLTRIGGER) ok = 1; if(!ok) return; } switch(xline->special) { // TRIGGERS. // All from here to RETRIGGERS. case 2: // Open Door EV_DoDoor(line, DT_OPEN); xline->special = 0; break; case 3: // Close Door EV_DoDoor(line, DT_CLOSE); xline->special = 0; break; case 4: // Raise Door EV_DoDoor(line, DT_NORMAL); xline->special = 0; break; case 5: // Raise Floor EV_DoFloor(line, FT_RAISEFLOOR); xline->special = 0; break; case 6: // Fast Ceiling Crush & Raise EV_DoCeiling(line, CT_CRUSHANDRAISEFAST); xline->special = 0; break; case 8: // Build Stairs EV_BuildStairs(line, build8); xline->special = 0; break; case 10: // PlatDownWaitUp EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0); xline->special = 0; break; case 12: // Light Turn On - brightest near EV_LightTurnOn(line, 0); xline->special = 0; break; case 13: // Light Turn On - max. EV_LightTurnOn(line, 1); xline->special = 0; break; case 16: // Close Door 30. EV_DoDoor(line, DT_CLOSE30THENOPEN); xline->special = 0; break; case 17: // Start Light Strobing. EV_StartLightStrobing(line); xline->special = 0; break; case 19: // Lower Floor. EV_DoFloor(line, FT_LOWER); xline->special = 0; break; case 22: // Raise floor to nearest height and change texture. EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); xline->special = 0; break; case 25: // Ceiling Crush and Raise. EV_DoCeiling(line, CT_CRUSHANDRAISE); xline->special = 0; break; case 30: // Raise floor to shortest texture height on either side of lines. EV_DoFloor(line, FT_RAISETOTEXTURE); xline->special = 0; break; case 35: // Lights Very Dark. EV_LightTurnOn(line, 35.0f/255); xline->special = 0; break; case 36: // Lower Floor (TURBO). EV_DoFloor(line, FT_LOWERTURBO); xline->special = 0; break; case 37: // LowerAndChange. EV_DoFloor(line, FT_LOWERANDCHANGE); xline->special = 0; break; case 38: // Lower Floor To Lowest. EV_DoFloor(line, FT_LOWERTOLOWEST); xline->special = 0; break; case 39: // TELEPORT! EV_Teleport(line, side, thing, true); xline->special = 0; break; case 40: // RaiseCeilingLowerFloor. EV_DoCeiling(line, CT_RAISETOHIGHEST); EV_DoFloor(line, FT_LOWERTOLOWEST); xline->special = 0; break; case 44: // Ceiling Crush. EV_DoCeiling(line, CT_LOWERANDCRUSH); xline->special = 0; break; case 52: // EXIT! G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, false); break; case 53: // Perpetual Platform Raise. EV_DoPlat(line, PT_PERPETUALRAISE, 0); xline->special = 0; break; case 54: // Platform Stop. P_PlatDeactivate(xline->tag); xline->special = 0; break; case 56: // Raise Floor Crush. EV_DoFloor(line, FT_RAISEFLOORCRUSH); xline->special = 0; break; case 57: // Ceiling Crush Stop. P_CeilingDeactivate(xline->tag); xline->special = 0; break; case 58: // Raise Floor 24. EV_DoFloor(line, FT_RAISE24); xline->special = 0; break; case 59: // Raise Floor 24 And Change. EV_DoFloor(line, FT_RAISE24ANDCHANGE); xline->special = 0; break; case 104: // Turn lights off in sector(tag). EV_TurnTagLightsOff(line); xline->special = 0; break; case 108: // Blazing Door Raise (faster than TURBO!). EV_DoDoor(line, DT_BLAZERAISE); xline->special = 0; break; case 109: // Blazing Door Open (faster than TURBO!). EV_DoDoor(line, DT_BLAZEOPEN); xline->special = 0; break; case 100: // Build Stairs Turbo 16. EV_BuildStairs(line, turbo16); xline->special = 0; break; case 110: // Blazing Door Close (faster than TURBO!). EV_DoDoor(line, DT_BLAZECLOSE); xline->special = 0; break; case 119: // Raise floor to nearest surr. floor. EV_DoFloor(line, FT_RAISEFLOORTONEAREST); xline->special = 0; break; case 121: // Blazing PlatDownWaitUpStay. EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0); xline->special = 0; break; case 124: // Secret EXIT. G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, true); break; case 125: // TELEPORT MonsterONLY. if(!thing->player) { EV_Teleport(line, side, thing, true); xline->special = 0; } break; case 130: // Raise Floor Turbo. EV_DoFloor(line, FT_RAISEFLOORTURBO); xline->special = 0; break; case 141: // Silent Ceiling Crush & Raise. EV_DoCeiling(line, CT_SILENTCRUSHANDRAISE); xline->special = 0; break; // RETRIGGERS. All from here till end. case 72: // Ceiling Crush. EV_DoCeiling(line, CT_LOWERANDCRUSH); break; case 73: // Ceiling Crush and Raise. EV_DoCeiling(line, CT_CRUSHANDRAISE); break; case 74: // Ceiling Crush Stop. P_CeilingDeactivate(xline->tag); break; case 75: // Close Door. EV_DoDoor(line, DT_CLOSE); break; case 76: // Close Door 30. EV_DoDoor(line, DT_CLOSE30THENOPEN); break; case 77: // Fast Ceiling Crush & Raise. EV_DoCeiling(line, CT_CRUSHANDRAISEFAST); break; case 79: // Lights Very Dark. EV_LightTurnOn(line, 35.0f/255.0f); break; case 80: // Light Turn On - brightest near. EV_LightTurnOn(line, 0); break; case 81: // Light Turn On 255. EV_LightTurnOn(line, 1); break; case 82: // Lower Floor To Lowest. EV_DoFloor(line, FT_LOWERTOLOWEST); break; case 83: // Lower Floor. EV_DoFloor(line, FT_LOWER); break; case 84: // LowerAndChange. EV_DoFloor(line, FT_LOWERANDCHANGE); break; case 86: // Open Door. EV_DoDoor(line, DT_OPEN); break; case 87: // Perpetual Platform Raise. EV_DoPlat(line, PT_PERPETUALRAISE, 0); break; case 88: // PlatDownWaitUp. EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0); break; case 89: // Platform Stop. P_PlatDeactivate(xline->tag); break; case 90: // Raise Door. EV_DoDoor(line, DT_NORMAL); break; case 91: // Raise Floor. EV_DoFloor(line, FT_RAISEFLOOR); break; case 92: // Raise Floor 24. EV_DoFloor(line, FT_RAISE24); break; case 93: // Raise Floor 24 And Change. EV_DoFloor(line, FT_RAISE24ANDCHANGE); break; case 94: // Raise Floor Crush. EV_DoFloor(line, FT_RAISEFLOORCRUSH); break; case 95: // Raise floor to nearest height and change texture. EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); break; case 96: // Raise floor to shortest texture height on either side of lines. EV_DoFloor(line, FT_RAISETOTEXTURE); break; case 97: // TELEPORT! EV_Teleport(line, side, thing, true); break; case 98: // Lower Floor (TURBO). EV_DoFloor(line, FT_LOWERTURBO); break; case 105: // Blazing Door Raise (faster than TURBO!). EV_DoDoor(line, DT_BLAZERAISE); break; case 106: // Blazing Door Open (faster than TURBO!). EV_DoDoor(line, DT_BLAZEOPEN); break; case 107: // Blazing Door Close (faster than TURBO!). EV_DoDoor(line, DT_BLAZECLOSE); break; case 120: // Blazing PlatDownWaitUpStay. EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0); break; case 126: // TELEPORT MonsterONLY. if(!thing->player) EV_Teleport(line, side, thing, true); break; case 128: // Raise To Nearest Floor. EV_DoFloor(line, FT_RAISEFLOORTONEAREST); break; case 129: // Raise Floor Turbo. EV_DoFloor(line, FT_RAISEFLOORTURBO); break; } } /** * Called when a thing shoots a special line. */ static void shootSpecialLine(mobj_t *thing, linedef_t *line) { // Impacts that other things can activate. if(!thing->player) { switch(P_ToXLine(line)->special) { case 46: // OPEN DOOR IMPACT break; default: return; // Cannot be shot at. } } switch(P_ToXLine(line)->special) { case 24: // RAISE FLOOR EV_DoFloor(line, FT_RAISEFLOOR); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); P_ToXLine(line)->special = 0; break; case 46: // OPEN DOOR EV_DoDoor(line, DT_OPEN); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 47: // RAISE FLOOR NEAR AND CHANGE EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); P_ToXLine(line)->special = 0; break; default: break; } } /** * Called every tic frame that the player origin is in a special sector */ void P_PlayerInSpecialSector(player_t* player) { sector_t* sector = P_GetPtrp(player->plr->mo->subsector, DMU_SECTOR); // Falling, not all the way down yet? if(player->plr->mo->pos[VZ] != P_GetFloatp(sector, DMU_FLOOR_HEIGHT)) return; // Has hitten ground. switch(P_ToXSector(sector)->special) { case 5: // HELLSLIME DAMAGE. if(!player->powers[PT_IRONFEET]) { if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 10, false); } break; case 7: // NUKAGE DAMAGE. if(!player->powers[PT_IRONFEET]) { if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 5, false); } break; case 16: // SUPER HELLSLIME DAMAGE case 4: // STROBE HURT if(!player->powers[PT_IRONFEET] || (P_Random() < 5)) { if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 20, false); } break; case 9: // SECRET SECTOR player->secretCount++; P_ToXSector(sector)->special = 0; if(cfg.secretMsg) { P_SetMessage(player, "You've found a secret area!", false); S_ConsoleSound(SFX_SECRET, 0, player - players); } break; case 11: // EXIT SUPER DAMAGE! (for E1M8 finale) player->cheats &= ~CF_GODMODE; if(!(mapTime & 0x1f)) P_DamageMobj(player->plr->mo, NULL, NULL, 20, false); if(player->health <= 10) G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, false); break; default: break; } } /** * Animate planes, scroll walls, etc. */ void P_UpdateSpecials(void) { linedef_t* line; sidedef_t* side; // Extended lines and sectors. XG_Ticker(); // Animate line specials. if(P_IterListSize(linespecials)) { float x, offset; P_IterListResetIterator(linespecials, false); while((line = P_IterListIterator(linespecials)) != NULL) { xline_t *xline = P_ToXLine(line); switch(xline->special) { case 48: case 85: side = P_GetPtrp(line, DMU_SIDEDEF0); if(xline->special == 85) offset = -1; else offset = 1; x = P_GetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_TOP_MATERIAL_OFFSET_X, x += offset); x = P_GetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_MIDDLE_MATERIAL_OFFSET_X, x += offset); x = P_GetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X); P_SetFloatp(side, DMU_BOTTOM_MATERIAL_OFFSET_X, x += offset); break; default: break; } } } } /** * After the map has been loaded, scan for specials that spawn thinkers. */ void P_SpawnSpecials(void) { uint i; linedef_t* line; xline_t* xline; iterlist_t* list; sector_t* sec; xsector_t* xsec; // Init special sectors. P_DestroySectorTagLists(); for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); if(xsec->tag) { list = P_GetSectorIterListForTag(xsec->tag, true); P_AddObjectToIterList(list, sec); } if(!xsec->special) continue; if(IS_CLIENT) { switch(xsec->special) { case 9: // A secret sector. totalSecret++; break; default: break; } continue; } switch(xsec->special) { case 1: // FLICKERING LIGHTS P_SpawnLightFlash(sec); break; case 2: // STROBE FAST P_SpawnStrobeFlash(sec, FASTDARK, 0); break; case 3: // STROBE SLOW P_SpawnStrobeFlash(sec, SLOWDARK, 0); break; case 4: // STROBE FAST/DEATH SLIME P_SpawnStrobeFlash(sec, FASTDARK, 0); xsec->special = 4; break; case 8: // GLOWING LIGHT P_SpawnGlowingLight(sec); break; case 9: // SECRET SECTOR totalSecret++; break; case 10: // DOOR CLOSE IN 30 SECONDS P_SpawnDoorCloseIn30(sec); break; case 12: // SYNC STROBE SLOW P_SpawnStrobeFlash(sec, SLOWDARK, 1); break; case 13: // SYNC STROBE FAST P_SpawnStrobeFlash(sec, FASTDARK, 1); break; case 14: // DOOR RAISE IN 5 MINUTES P_SpawnDoorRaiseIn5Mins(sec); break; case 17: P_SpawnFireFlicker(sec); break; default: break; } } // Init animating line specials. P_EmptyIterList(linespecials); P_DestroyLineTagLists(); for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); xline = P_ToXLine(line); switch(xline->special) { case 48: // EFFECT FIRSTCOL SCROLL+ P_AddObjectToIterList(linespecials, line); break; default: break; } if(xline->tag) { list = P_GetLineIterListForTag(xline->tag, true); P_AddObjectToIterList(list, line); } } // Init extended generalized lines and sectors. XG_Init(); } boolean P_UseSpecialLine2(mobj_t* mo, linedef_t* line, int side) { xline_t* xline = P_ToXLine(line); // Use the back sides of VERY SPECIAL lines... if(side) { switch(xline->special) { case 124: // Sliding door open&close // UNUSED? break; default: return false; break; } } // Switches that other things can activate. if(!mo->player) { // Never open secret doors. if(xline->flags & ML_SECRET) return false; switch(xline->special) { case 1: // MANUAL DOOR RAISE case 32: // MANUAL BLUE case 33: // MANUAL RED case 34: // MANUAL YELLOW break; default: return false; break; } } // Do something. switch(xline->special) { // MANUALS case 1: // Vertical Door case 26: // Blue Door/Locked case 27: // Yellow Door /Locked case 28: // Red Door /Locked case 31: // Manual door open case 32: // Blue locked door open case 33: // Red locked door open case 34: // Yellow locked door open case 117: // Blazing door raise case 118: // Blazing door open EV_VerticalDoor(line, mo); break; //UNUSED - Door Slide Open&Close // case 124: // EV_SlidingDoor (line, mo); // break; // SWITCHES case 7: // Build Stairs if(EV_BuildStairs(line, build8)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 9: // Change Donut if(EV_DoDonut(line)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 11: // Exit map if(cyclingMaps && mapCycleNoExit) break; // Prevent 'zombie players' from exiting maps. if(mo->player && mo->player->health <= 0 && !cfg.zombiesCanExit) { S_StartSound(SFX_NOWAY, mo); return false; } P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_SWTCHX, false, 0); xline->special = 0; G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, false); break; case 14: // Raise Floor 32 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 15: // Raise Floor 24 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 18: // Raise Floor to next highest floor. if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 20: // Raise Plat next highest floor and change texture. if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 21: // PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 23: // Lower Floor to Lowest. if(EV_DoFloor(line, FT_LOWERTOLOWEST)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 29: // Raise Door. if(EV_DoDoor(line, DT_NORMAL)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 41: // Lower Ceiling to Floor. if(EV_DoCeiling(line, CT_LOWERTOFLOOR)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 71: // Turbo Lower Floor. if(EV_DoFloor(line, FT_LOWERTURBO)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 49: // Ceiling Crush And Raise. if(EV_DoCeiling(line, CT_CRUSHANDRAISE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 50: // Close Door. if(EV_DoDoor(line, DT_CLOSE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 51: // Secret EXIT. if(cyclingMaps && mapCycleNoExit) break; // Prevent 'zombie players' from exiting maps. if(mo->player && mo->player->health <= 0 && !cfg.zombiesCanExit) { S_StartSound(SFX_NOWAY, mo); return false; } P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; G_LeaveMap(G_GetMapNumber(gameEpisode, gameMap), 0, true); break; case 55: // Raise Floor Crush. if(EV_DoFloor(line, FT_RAISEFLOORCRUSH)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 101: // Raise Floor. if(EV_DoFloor(line, FT_RAISEFLOOR)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 102: // Lower Floor to Surrounding floor height. if(EV_DoFloor(line, FT_LOWER)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 103: // Open Door. if(EV_DoDoor(line, DT_OPEN)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 111: // Blazing Door Raise (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZERAISE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 112: // Blazing Door Open (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZEOPEN)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 113: // Blazing Door Close (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZECLOSE)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 122: // Blazing PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 127: // Build Stairs Turbo 16. if(EV_BuildStairs(line, turbo16)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 131: // Raise Floor Turbo. if(EV_DoFloor(line, FT_RAISEFLOORTURBO)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 133: // BlzOpenDoor BLUE. case 135: // BlzOpenDoor RED. case 137: // BlzOpenDoor YELLOW. if(EV_DoLockedDoor(line, DT_BLAZEOPEN, mo)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; case 140: // Raise Floor 512. if(EV_DoFloor(line, FT_RAISE512)) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, 0); xline->special = 0; } break; // BUTTONS case 42: // Close Door. if(EV_DoDoor(line, DT_CLOSE)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 43: // Lower Ceiling to Floor. if(EV_DoCeiling(line, CT_LOWERTOFLOOR)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 45: // Lower Floor to Surrounding floor height. if(EV_DoFloor(line, FT_LOWER)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 60: // Lower Floor to Lowest. if(EV_DoFloor(line, FT_LOWERTOLOWEST)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 61: // Open Door. if(EV_DoDoor(line, DT_OPEN)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 62: // PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAY, 1)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 63: // Raise Door. if(EV_DoDoor(line, DT_NORMAL)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 64: // Raise Floor to ceiling. if(EV_DoFloor(line, FT_RAISEFLOOR)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 66: // Raise Floor 24 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 24)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 67: // Raise Floor 32 and change texture. if(EV_DoPlat(line, PT_RAISEANDCHANGE, 32)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 65: // Raise Floor Crush. if(EV_DoFloor(line, FT_RAISEFLOORCRUSH)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 68: // Raise Plat to next highest floor and change texture. if(EV_DoPlat(line, PT_RAISETONEARESTANDCHANGE, 0)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 69: // Raise Floor to next highest floor. if(EV_DoFloor(line, FT_RAISEFLOORTONEAREST)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 70: // Turbo Lower Floor. if(EV_DoFloor(line, FT_LOWERTURBO)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 114: // Blazing Door Raise (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZERAISE)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 115: // Blazing Door Open (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZEOPEN)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 116: // Blazing Door Close (faster than TURBO!). if(EV_DoDoor(line, DT_BLAZECLOSE)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 123: // Blazing PlatDownWaitUpStay. if(EV_DoPlat(line, PT_DOWNWAITUPSTAYBLAZE, 0)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 132: // Raise Floor Turbo. if(EV_DoFloor(line, FT_RAISEFLOORTURBO)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 99: // BlzOpenDoor BLUE. case 134: // BlzOpenDoor RED. case 136: // BlzOpenDoor YELLOW. if(EV_DoLockedDoor(line, DT_BLAZEOPEN, mo)) P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 138: // Light Turn On. EV_LightTurnOn(line, 1); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; case 139: // Light Turn Off. EV_LightTurnOn(line, 35.0f/255.0f); P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), SFX_NONE, false, BUTTONTIME); break; default: break; } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_telept.c0000644000175000017500000001460011357170242022426 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.c: */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_map.h" #include "p_mapspec.h" #include "p_terraintype.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle) { return P_SpawnMobj3f(MT_TFOG, x, y, 0, angle, MSF_Z_FLOOR); } typedef struct { sector_t* sec; mobjtype_t type; mobj_t* foundMobj; } findmobjparams_t; static boolean findMobj(thinker_t* th, void* context) { findmobjparams_t* params = (findmobjparams_t*) context; mobj_t* mo = (mobj_t *) th; // Must be of the correct type? if(params->type >= 0 && params->type != mo->type) return true; // Continue iteration. // Must be in the specified sector? if(params->sec && params->sec != P_GetPtrp(mo->subsector, DMU_SECTOR)) return true; // Continue iteration. // Found it! params->foundMobj = mo; return false; // Stop iteration. } static mobj_t* getTeleportDestination(short tag) { iterlist_t* list; list = P_GetSectorIterListForTag(tag, false); if(list) { sector_t* sec = NULL; findmobjparams_t params; params.type = MT_TELEPORTMAN; params.foundMobj = NULL; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { params.sec = sec; if(!DD_IterateThinkers(P_MobjThinker, findMobj, ¶ms)) { // Found one. return params.foundMobj; } } } return NULL; } int EV_Teleport(linedef_t* line, int side, mobj_t* mo, boolean spawnFog) { mobj_t* dest; if(mo->flags2 & MF2_NOTELEPORT) return 0; // Don't teleport if hit back of line, so you can get out of teleporter. if(side == 1) return 0; if((dest = getTeleportDestination(P_ToXLine(line)->tag)) != NULL) { // A suitable destination has been found. mobj_t* fog; uint an; float oldPos[3]; float aboveFloor; angle_t oldAngle; memcpy(oldPos, mo->pos, sizeof(mo->pos)); oldAngle = mo->angle; aboveFloor = mo->pos[VZ] - mo->floorZ; if(!P_TeleportMove(mo, dest->pos[VX], dest->pos[VY], false)) return 0; // In Final Doom things teleported to their destination but the // height wasn't set to the floor. if(gameMission != GM_TNT && gameMission != GM_PLUT) mo->pos[VZ] = mo->floorZ; if(spawnFog) { // Spawn teleport fog at source and destination. if((fog = P_SpawnMobj3fv(MT_TFOG, oldPos, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); an = dest->angle >> ANGLETOFINESHIFT; if((fog = P_SpawnMobj3f(MT_TFOG, dest->pos[VX] + 20 * FIX2FLT(finecosine[an]), dest->pos[VY] + 20 * FIX2FLT(finesine[an]), mo->pos[VZ], dest->angle + ANG180, 0))) { // Emit sound, where? S_StartSound(SFX_TELEPT, fog); } } mo->angle = dest->angle; if(mo->flags2 & MF2_FLOORCLIP) { mo->floorClip = 0; if(mo->pos[VZ] == P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } } mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; // Don't move for a bit. if(mo->player) { mo->reactionTime = 18; if(mo->player->powers[PT_FLIGHT] && aboveFloor > 0) { mo->pos[VZ] = mo->floorZ + aboveFloor; if(mo->pos[VZ] + mo->height > mo->ceilingZ) { mo->pos[VZ] = mo->ceilingZ - mo->height; } } else { //mo->dPlayer->clLookDir = 0; /* $unifiedangles */ mo->dPlayer->lookDir = 0; } mo->player->viewHeight = (float) cfg.plrViewHeight; mo->player->viewHeightDelta = 0; mo->player->viewZ = mo->pos[VZ] + mo->player->viewHeight; //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */ mo->dPlayer->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; } return 1; } return 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/wi_stuff.c0000644000175000017500000011512411357170242022443 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * wi_stuff.c: Intermission/stat screens - jDoom specific. * * Different between registered DOOM (1994) and * Ultimate DOOM - Final edition (retail, 1995?). * This is supposedly ignored for commercial release (aka DOOM II), * which had 34 maps in one episode. So there. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom.h" #include "hu_stuff.h" #include "d_net.h" #include "p_start.h" // MACROS ------------------------------------------------------------------ #define NUM_TEAMS (4) // Color = team. #define NUMEPISODES (4) #define NUMMAPS (9) // GLOBAL LOCATIONS #define WI_TITLEY (2) #define WI_SPACINGY (33) // SINGPLE-PLAYER STUFF #define SP_STATSX (50) #define SP_STATSY (50) #define SP_TIMEX (16) #define SP_TIMEY (SCREENHEIGHT-32) // NET GAME STUFF #define NG_STATSY (50) #define NG_STATSX (32 + star.width/2 + 32*!doFrags) #define NG_SPACINGX (64) // DEATHMATCH STUFF #define DM_MATRIXX (42) #define DM_MATRIXY (68) #define DM_SPACINGX (40) #define DM_TOTALSX (269) #define DM_KILLERSX (10) #define DM_KILLERSY (100) #define DM_VICTIMSX (5) #define DM_VICTIMSY (50) // States for single-player #define SP_KILLS (0) #define SP_ITEMS (2) #define SP_SECRET (4) #define SP_FRAGS (6) #define SP_TIME (8) #define SP_PAR (ST_TIME) #define SP_PAUSE (1) #define SHOWNEXTLOCDELAY (4) // In seconds. // TYPES ------------------------------------------------------------------- typedef enum animenum_e { ANIM_ALWAYS, ANIM_RANDOM, ANIM_MAP } animenum_t; typedef struct point_s { int x, y; } point_t; typedef struct wianim_s { animenum_t type; // Period in tics between animations. int period; // Number of animation frames. int numAnimFrames; // Location of animation. point_t loc; int data1, data2; // Actual graphics for frames of animations. dpatch_t p[3]; // Following must be initialized to zero before use! // Next value of bcnt (used in conjunction with period). int nextTic; // Last drawn animation frame. int lastDrawn; // Next frame number to animate. int ctr; // Used by RANDOM and LEVEL when animating. int state; } wianim_t; typedef struct teaminfo_s { int members; // 0 if team not present. int frags[NUM_TEAMS]; int totalFrags; // Kills minus suicides. int items; int kills; int secret; } teaminfo_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static teaminfo_t teamInfo[NUM_TEAMS]; static point_t mapPoints[NUMEPISODES][NUMMAPS] = { { // Episode 0 {185, 164}, {148, 143}, {69, 122}, {209, 102}, {116, 89}, {166, 55}, {71, 56}, {135, 29}, {71, 24} }, { // Episode 1 {254, 25}, {97, 50}, {188, 64}, {128, 78}, {214, 92}, {133, 130}, {208, 136}, {148, 140}, {235, 158} }, { // Episode 2 {156, 168}, {48, 154}, {174, 95}, {265, 75}, {130, 48}, {279, 23}, {198, 48}, {140, 25}, {281, 136} } }; // Animation locations. static wianim_t epsd0animinfo[] = { {ANIM_ALWAYS, TICRATE / 3, 3, {224, 104}}, {ANIM_ALWAYS, TICRATE / 3, 3, {184, 160}}, {ANIM_ALWAYS, TICRATE / 3, 3, {112, 136}}, {ANIM_ALWAYS, TICRATE / 3, 3, {72, 112}}, {ANIM_ALWAYS, TICRATE / 3, 3, {88, 96}}, {ANIM_ALWAYS, TICRATE / 3, 3, {64, 48}}, {ANIM_ALWAYS, TICRATE / 3, 3, {192, 40}}, {ANIM_ALWAYS, TICRATE / 3, 3, {136, 16}}, {ANIM_ALWAYS, TICRATE / 3, 3, {80, 16}}, {ANIM_ALWAYS, TICRATE / 3, 3, {64, 24}} }; static wianim_t epsd1animinfo[] = { {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 1}, {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 2}, {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 3}, {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 4}, {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 5}, {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 6}, {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 7}, {ANIM_MAP, TICRATE / 3, 3, {192, 144}, 8}, {ANIM_MAP, TICRATE / 3, 1, {128, 136}, 8} }; static wianim_t epsd2animinfo[] = { {ANIM_ALWAYS, TICRATE / 3, 3, {104, 168}}, {ANIM_ALWAYS, TICRATE / 3, 3, {40, 136}}, {ANIM_ALWAYS, TICRATE / 3, 3, {160, 96}}, {ANIM_ALWAYS, TICRATE / 3, 3, {104, 80}}, {ANIM_ALWAYS, TICRATE / 3, 3, {120, 32}}, {ANIM_ALWAYS, TICRATE / 4, 3, {40, 0}} }; static int NUMANIMS[NUMEPISODES] = { sizeof(epsd0animinfo) / sizeof(wianim_t), sizeof(epsd1animinfo) / sizeof(wianim_t), sizeof(epsd2animinfo) / sizeof(wianim_t) }; static wianim_t *anims[NUMEPISODES] = { epsd0animinfo, epsd1animinfo, epsd2animinfo }; // Signals to refresh everything for one frame. static int firstRefresh; // Used to accelerate or skip a stage. static int accelerateStage; static boolean snlPointerOn = false; static int spState, dmState, ngState; // specifies current state static interludestate_t state; static int dmFrags[NUM_TEAMS][NUM_TEAMS]; static int dmTotals[NUM_TEAMS]; static int doFrags; // wbs->pnum static int me; static int myTeam; // Used for general timing. static int cnt; // Used for timing of background animation. static int bcnt; static int cntKills[NUM_TEAMS]; static int cntItems[NUM_TEAMS]; static int cntSecret[NUM_TEAMS]; static int cntFrags[NUM_TEAMS]; static int cntTime; static int cntPar; static int cntPause; // Contains information passed into intermission. static wbstartstruct_t *wbs; static wbplayerstruct_t *plrs; // wbs->plyr[] static dpatch_t bg; // Background (map of maps). static dpatch_t yah[2]; // You Are Here. static dpatch_t splat; // Splat. static dpatch_t percent; // % graphic. static dpatch_t colon; // : graphic. static dpatch_t num[10]; // 0-9 numbers. static dpatch_t wiminus; // Minus sign. static dpatch_t finished; // "Finished!" static dpatch_t entering; // "Entering" static dpatch_t sp_secret; // "secret" static dpatch_t kills; // "Kills" static dpatch_t secret; // "Scrt" static dpatch_t items; // "Items" static dpatch_t frags; // "Frags" static dpatch_t time; // "time" static dpatch_t par; // "par" static dpatch_t sucks; // "sucks!" static dpatch_t killers; // "killers" static dpatch_t victims; // "victims" static dpatch_t total; // "Total" static dpatch_t star; // Player live icon. static dpatch_t bstar; // Player dead icon. static dpatch_t p[MAXPLAYERS]; // "red P[1..MAXPLAYERS]" static dpatch_t bp[MAXPLAYERS]; // "gray P[1..MAXPLAYERS]" // CODE -------------------------------------------------------------------- void WI_slamBackground(void) { GL_DrawPatch(0, 0, bg.lump); } /** * The ticker is used to detect keys because of timing issues in netgames. */ boolean WI_Responder(event_t *ev) { return false; } /** * Draws " Finished!" */ void WI_drawLF(void) { int y = WI_TITLEY; int mapNum; char *mapName; if(gameMode == commercial) mapNum = wbs->currentMap; else mapNum = (wbs->episode * 8) + wbs->currentMap; mapName = (char *) DD_GetVariable(DD_MAP_NAME); // Skip the E#M# or Map #. if(mapName) { char *ptr = strchr(mapName, ':'); if(ptr) { mapName = ptr + 1; while(*mapName && isspace(*mapName)) mapName++; } } // Draw WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &mapNamePatches[mapNum], mapName, false, ALIGN_CENTER); // Draw "Finished!" y += (5 * mapNamePatches[mapNum].height) / 4; WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &finished, NULL, false, ALIGN_CENTER); } /** * Draws "Entering " */ void WI_drawEL(void) { int y = WI_TITLEY; char *mapName = NULL; ddmapinfo_t minfo; char lumpName[10]; // See if there is a map name. P_GetMapLumpName(wbs->episode, wbs->nextMap, lumpName); if(Def_Get(DD_DEF_MAP_INFO, lumpName, &minfo) && minfo.name) { if(Def_Get(DD_DEF_TEXT, minfo.name, &mapName) == -1) mapName = minfo.name; } // Skip the E#M# or Map #. if(mapName) { char *ptr = strchr(mapName, ':'); if(ptr) { mapName = ptr + 1; while(*mapName && isspace(*mapName)) mapName++; } } // Draw "Entering" WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &entering, NULL, false, ALIGN_CENTER); // Draw map. y += (5 * mapNamePatches[wbs->nextMap].height) / 4; WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, 1, &mapNamePatches[(wbs->episode * 8) + wbs->nextMap], mapName, false, ALIGN_CENTER); } void WI_DrawOnMapNode(int n, dpatch_t * c) { int i; int left, top, right, bottom; boolean fits = false; i = 0; do { left = mapPoints[wbs->episode][n].x - c[i].leftOffset; top = mapPoints[wbs->episode][n].y - c[i].topOffset; right = left + c[i].width; bottom = top + c[i].height; if(left >= 0 && right < SCREENWIDTH && top >= 0 && bottom < SCREENHEIGHT) fits = true; else i++; } while(!fits && i != 2); if(fits && i < 2) { WI_DrawPatch(mapPoints[wbs->episode][n].x, mapPoints[wbs->episode][n].y, 1, 1, 1, 1, &c[i], NULL, false, ALIGN_LEFT); } else { Con_Message("Could not place patch on map %d", n + 1); } } void WI_initAnimatedBack(void) { int i; wianim_t *a; if(gameMode == commercial) return; if(wbs->episode > 2) return; for(i = 0; i < NUMANIMS[wbs->episode]; ++i) { a = &anims[wbs->episode][i]; a->ctr = -1; // Specify the next time to draw it. if(a->type == ANIM_ALWAYS) a->nextTic = bcnt + 1 + (M_Random() % a->period); else if(a->type == ANIM_RANDOM) a->nextTic = bcnt + 1 + a->data2 + (M_Random() % a->data1); else if(a->type == ANIM_MAP) a->nextTic = bcnt + 1; } } void WI_updateAnimatedBack(void) { int i; wianim_t *a; if(gameMode == commercial) return; if(wbs->episode > 2) return; for(i = 0; i < NUMANIMS[wbs->episode]; ++i) { a = &anims[wbs->episode][i]; if(bcnt == a->nextTic) { switch (a->type) { case ANIM_ALWAYS: if(++a->ctr >= a->numAnimFrames) a->ctr = 0; a->nextTic = bcnt + a->period; break; case ANIM_RANDOM: a->ctr++; if(a->ctr == a->numAnimFrames) { a->ctr = -1; a->nextTic = bcnt + a->data2 + (M_Random() % a->data1); } else a->nextTic = bcnt + a->period; break; case ANIM_MAP: // Gawd-awful hack for map anims. if(!(state == ILS_SHOW_STATS && i == 7) && wbs->nextMap == a->data1) { a->ctr++; if(a->ctr == a->numAnimFrames) a->ctr--; a->nextTic = bcnt + a->period; } break; } } } } void WI_drawAnimatedBack(void) { int i; wianim_t *a; if(gameMode == commercial) return; if(wbs->episode > 2) return; for(i = 0; i < NUMANIMS[wbs->episode]; ++i) { a = &anims[wbs->episode][i]; if(a->ctr >= 0) WI_DrawPatch(a->loc.x, a->loc.y, 1, 1, 1, 1, &a->p[a->ctr], NULL, false, ALIGN_LEFT); } } /** * Draw a number. * * @param digits If > 0, then use that many digits minimum, * otherwise only use as many as necessary. * @return New x position. */ int WI_drawNum(int x, int y, int n, int digits) { int fontwidth = num[0].width; int neg, temp; if(digits < 0) { if(!n) { // Make variable-length zeros 1 digit long. digits = 1; } else { // Figure out # of digits in #. digits = 0; temp = n; while(temp) { temp /= 10; digits++; } } } neg = n < 0; if(neg) n = -n; // If non-number, do not draw it. if(n == 1994) return 0; // Draw the new number. while(digits--) { x -= fontwidth; WI_DrawPatch(x, y, 1, 1, 1, 1, &num[n % 10], NULL, false, ALIGN_LEFT); n /= 10; } // Draw a minus sign if necessary. if(neg) WI_DrawPatch(x -= 8, y, 1, 1, 1, 1, &wiminus, NULL, false, ALIGN_LEFT); return x; } void WI_drawPercent(int x, int y, int p) { if(p < 0) return; WI_DrawPatch(x, y, 1, 1, 1, 1, &percent, NULL, false, ALIGN_LEFT); WI_drawNum(x, y, p, -1); } /** * Display map completion time and par, or "sucks" message if overflow. */ void WI_drawTime(int x, int y, int t) { int div, n; if(t < 0) return; if(t <= 61 * 59) { div = 1; do { n = (t / div) % 60; x = WI_drawNum(x, y, n, 2) - colon.width; div *= 60; if(div == 60 || t / div) WI_DrawPatch(x, y, 1, 1, 1, 1, &colon, NULL, false, ALIGN_LEFT); } while(t / div); } else { // "sucks" WI_DrawPatch(x - sucks.width, y, 1, 1, 1, 1, &sucks, NULL, false, ALIGN_LEFT); } } void WI_End(void) { NetSv_Intermission(IMF_END, 0, 0); } void WI_initNoState(void) { state = ILS_NONE; accelerateStage = 0; cnt = 10; NetSv_Intermission(IMF_STATE, state, 0); } void WI_updateNoState(void) { WI_updateAnimatedBack(); if(!--cnt) { if(IS_CLIENT) return; WI_End(); G_WorldDone(); } } void WI_initShowNextLoc(void) { state = ILS_SHOW_NEXTMAP; accelerateStage = 0; cnt = SHOWNEXTLOCDELAY * TICRATE; WI_initAnimatedBack(); NetSv_Intermission(IMF_STATE, state, 0); } void WI_updateShowNextLoc(void) { WI_updateAnimatedBack(); if(!--cnt || accelerateStage) WI_initNoState(); else snlPointerOn = (cnt & 31) < 20; } void WI_drawShowNextLoc(void) { int i; int last; WI_slamBackground(); // Draw animated background. WI_drawAnimatedBack(); if(gameMode != commercial) { if(wbs->episode > 2) { WI_drawEL(); return; } last = (wbs->currentMap == 8) ? wbs->nextMap-1 : wbs->currentMap; // Draw a splat on taken cities. for(i = 0; i <= last; ++i) WI_DrawOnMapNode(i, &splat); // Splat the secret map? if(wbs->didSecret) WI_DrawOnMapNode(8, &splat); // Draw flashing ptr. if(snlPointerOn) WI_DrawOnMapNode(wbs->nextMap, yah); } // Draws which map you are entering.. if((gameMode != commercial) || wbs->nextMap != 30) WI_drawEL(); } void WI_drawNoState(void) { snlPointerOn = true; WI_drawShowNextLoc(); } int WI_fragSum(int teamnum) { return teamInfo[teamnum].totalFrags; } void WI_initDeathmatchStats(void) { int i; state = ILS_SHOW_STATS; accelerateStage = 0; dmState = 1; cntPause = TICRATE; // Clear the on-screen counters. memset(dmTotals, 0, sizeof(dmTotals)); for(i = 0; i < NUM_TEAMS; ++i) memset(dmFrags[i], 0, sizeof(dmFrags[i])); WI_initAnimatedBack(); } void WI_updateDeathmatchStats(void) { int i, j; boolean stillTicking; WI_updateAnimatedBack(); if(accelerateStage && dmState != 4) { accelerateStage = 0; for(i = 0; i < NUM_TEAMS; ++i) { for(j = 0; j < NUM_TEAMS; ++j) { dmFrags[i][j] = teamInfo[i].frags[j]; } dmTotals[i] = WI_fragSum(i); } S_LocalSound(SFX_BAREXP, 0); dmState = 4; } if(dmState == 2) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { for(j = 0; j < NUM_TEAMS; ++j) { if(dmFrags[i][j] != teamInfo[i].frags[j]) { if(teamInfo[i].frags[j] < 0) dmFrags[i][j]--; else dmFrags[i][j]++; if(dmFrags[i][j] > 99) dmFrags[i][j] = 99; if(dmFrags[i][j] < -99) dmFrags[i][j] = -99; stillTicking = true; } } dmTotals[i] = WI_fragSum(i); if(dmTotals[i] > 99) dmTotals[i] = 99; if(dmTotals[i] < -99) dmTotals[i] = -99; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); dmState++; } } else if(dmState == 4) { if(accelerateStage) { S_LocalSound(SFX_SLOP, 0); if(gameMode == commercial) WI_initNoState(); else WI_initShowNextLoc(); } } else if(dmState & 1) { if(!--cntPause) { dmState++; cntPause = TICRATE; } } } void WI_drawDeathmatchStats(void) { int i, j; int x, y; int w; int lh; // Line height. lh = WI_SPACINGY; WI_slamBackground(); // Draw animated background. WI_drawAnimatedBack(); WI_drawLF(); // Draw stat titles (top line). WI_DrawPatch(DM_TOTALSX - total.width / 2, DM_MATRIXY - WI_SPACINGY + 10, 1, 1, 1, 1, &total, NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_KILLERSX, DM_KILLERSY, 1, 1, 1, 1, &killers, NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_VICTIMSX, DM_VICTIMSY, 1, 1, 1, 1, &victims, NULL, false, ALIGN_LEFT); x = DM_MATRIXX + DM_SPACINGX; y = DM_MATRIXY; for(i = 0; i < NUM_TEAMS; ++i) { if(teamInfo[i].members) { WI_DrawPatch(x - p[i].width / 2, DM_MATRIXY - WI_SPACINGY, 1, 1, 1, 1, &p[i], NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_MATRIXX - p[i].width / 2, y, 1, 1, 1, 1, &p[i], NULL, false, ALIGN_LEFT); if(i == myTeam) { WI_DrawPatch(x - p[i].width / 2, DM_MATRIXY - WI_SPACINGY, 1, 1, 1, 1, &bstar, NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_MATRIXX - p[i].width / 2, y, 1, 1, 1, 1, &star, NULL, false, ALIGN_LEFT); } // If more than 1 member, show the member count. if(teamInfo[i].members > 1) { char tmp[20]; sprintf(tmp, "%i", teamInfo[i].members); M_WriteText2(x - p[i].width / 2 + 1, DM_MATRIXY - WI_SPACINGY + p[i].height - 8, tmp, GF_FONTA, 1, 1, 1, 1); M_WriteText2(DM_MATRIXX - p[i].width / 2 + 1, y + p[i].height - 8, tmp, GF_FONTA, 1, 1, 1, 1); } } else { WI_DrawPatch(x - bp[i].width / 2, DM_MATRIXY - WI_SPACINGY, 1, 1, 1, 1, &bp[i], NULL, false, ALIGN_LEFT); WI_DrawPatch(DM_MATRIXX - bp[i].width / 2, y, 1, 1, 1, 1, &bp[i], NULL, false, ALIGN_LEFT); } x += DM_SPACINGX; y += WI_SPACINGY; } // Draw stats. y = DM_MATRIXY + 10; w = num[0].width; for(i = 0; i < NUM_TEAMS; ++i) { x = DM_MATRIXX + DM_SPACINGX; if(teamInfo[i].members) { for(j = 0; j < NUM_TEAMS; ++j) { if(teamInfo[j].members) WI_drawNum(x + w, y, dmFrags[i][j], 2); x += DM_SPACINGX; } WI_drawNum(DM_TOTALSX + w, y, dmTotals[i], 2); } y += WI_SPACINGY; } } void WI_initNetgameStats(void) { int i; state = ILS_SHOW_STATS; accelerateStage = 0; ngState = 1; cntPause = TICRATE; memset(cntKills, 0, sizeof(cntKills)); memset(cntItems, 0, sizeof(cntItems)); memset(cntSecret, 0, sizeof(cntSecret)); memset(cntFrags, 0, sizeof(cntFrags)); doFrags = 0; for(i = 0; i < NUM_TEAMS; ++i) { doFrags += teamInfo[i].totalFrags; } doFrags = !doFrags; WI_initAnimatedBack(); } void WI_updateNetgameStats(void) { int i; int fsum; boolean stillTicking; WI_updateAnimatedBack(); if(accelerateStage && ngState != 10) { accelerateStage = 0; for(i = 0; i < NUM_TEAMS; ++i) { cntKills[i] = (teamInfo[i].kills * 100) / wbs->maxKills; cntItems[i] = (teamInfo[i].items * 100) / wbs->maxItems; cntSecret[i] = (teamInfo[i].secret * 100) / wbs->maxSecret; if(doFrags) cntFrags[i] = teamInfo[i].totalFrags; } S_LocalSound(SFX_BAREXP, 0); ngState = 10; } if(ngState == 2) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntKills[i] += 2; if(cntKills[i] >= (teamInfo[i].kills * 100) / wbs->maxKills) cntKills[i] = (teamInfo[i].kills * 100) / wbs->maxKills; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); ngState++; } } else if(ngState == 4) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntItems[i] += 2; if(cntItems[i] >= (teamInfo[i].items * 100) / wbs->maxItems) cntItems[i] = (teamInfo[i].items * 100) / wbs->maxItems; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); ngState++; } } else if(ngState == 6) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntSecret[i] += 2; if(cntSecret[i] >= (teamInfo[i].secret * 100) / wbs->maxSecret) cntSecret[i] = (teamInfo[i].secret * 100) / wbs->maxSecret; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_BAREXP, 0); ngState += 1 + 2 * !doFrags; } } else if(ngState == 8) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); stillTicking = false; for(i = 0; i < NUM_TEAMS; ++i) { cntFrags[i] += 1; if(cntFrags[i] >= (fsum = WI_fragSum(i))) cntFrags[i] = fsum; else stillTicking = true; } if(!stillTicking) { S_LocalSound(SFX_PLDETH, 0); ngState++; } } else if(ngState == 10) { if(accelerateStage) { S_LocalSound(SFX_SGCOCK, 0); if(gameMode == commercial) WI_initNoState(); else WI_initShowNextLoc(); } } else if(ngState & 1) { if(!--cntPause) { ngState++; cntPause = TICRATE; } } } void WI_drawNetgameStats(void) { int i; int x, y; int pwidth = percent.width; WI_slamBackground(); // Draw animated background. WI_drawAnimatedBack(); WI_drawLF(); // Draw stat titles (top line). WI_DrawPatch(NG_STATSX + NG_SPACINGX - kills.width, NG_STATSY, 1, 1, 1, 1, &kills, NULL, false, ALIGN_LEFT); WI_DrawPatch(NG_STATSX + 2 * NG_SPACINGX - items.width, NG_STATSY, 1, 1, 1, 1, &items, NULL, false, ALIGN_LEFT); WI_DrawPatch(NG_STATSX + 3 * NG_SPACINGX - secret.width, NG_STATSY, 1, 1, 1, 1, &secret, NULL, false, ALIGN_LEFT); if(doFrags) WI_DrawPatch(NG_STATSX + 4 * NG_SPACINGX - frags.width, 1, 1, 1, 1, NG_STATSY, &frags, NULL, false, ALIGN_LEFT); // Draw stats. y = NG_STATSY + kills.height; for(i = 0; i < NUM_TEAMS; ++i) { if(!teamInfo[i].members) continue; x = NG_STATSX; WI_DrawPatch(x - p[i].width, y, 1, 1, 1, 1, &p[i], NULL, false, ALIGN_LEFT); // If more than 1 member, show the member count. if(teamInfo[i].members > 1) { char tmp[40]; sprintf(tmp, "%i", teamInfo[i].members); M_WriteText2(x - p[i].width + 1, y + p[i].height - 8, tmp, GF_FONTA, 1, 1, 1, 1); } if(i == myTeam) WI_DrawPatch(x - p[i].width, y, 1, 1, 1, 1, &star, NULL, false, ALIGN_LEFT); x += NG_SPACINGX; WI_drawPercent(x - pwidth, y + 10, cntKills[i]); x += NG_SPACINGX; WI_drawPercent(x - pwidth, y + 10, cntItems[i]); x += NG_SPACINGX; WI_drawPercent(x - pwidth, y + 10, cntSecret[i]); x += NG_SPACINGX; if(doFrags) WI_drawNum(x, y + 10, cntFrags[i], -1); y += WI_SPACINGY; } } void WI_initStats(void) { state = ILS_SHOW_STATS; accelerateStage = 0; spState = 1; cntKills[0] = cntItems[0] = cntSecret[0] = -1; cntTime = cntPar = -1; cntPause = TICRATE; WI_initAnimatedBack(); } void WI_updateStats(void) { WI_updateAnimatedBack(); if(accelerateStage && spState != 10) { accelerateStage = 0; cntKills[0] = (plrs[me].kills * 100) / wbs->maxKills; cntItems[0] = (plrs[me].items * 100) / wbs->maxItems; cntSecret[0] = (plrs[me].secret * 100) / wbs->maxSecret; cntTime = plrs[me].time; if(wbs->parTime != -1) cntPar = wbs->parTime; S_LocalSound(SFX_BAREXP, 0); spState = 10; } if(spState == 2) { cntKills[0] += 2; if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntKills[0] >= (plrs[me].kills * 100) / wbs->maxKills) { cntKills[0] = (plrs[me].kills * 100) / wbs->maxKills; S_LocalSound(SFX_BAREXP, 0); spState++; } } else if(spState == 4) { cntItems[0] += 2; if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntItems[0] >= (plrs[me].items * 100) / wbs->maxItems) { cntItems[0] = (plrs[me].items * 100) / wbs->maxItems; S_LocalSound(SFX_BAREXP, 0); spState++; } } else if(spState == 6) { cntSecret[0] += 2; if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntSecret[0] >= (plrs[me].secret * 100) / wbs->maxSecret) { cntSecret[0] = (plrs[me].secret * 100) / wbs->maxSecret; S_LocalSound(SFX_BAREXP, 0); spState++; } } else if(spState == 8) { if(!(bcnt & 3)) S_LocalSound(SFX_PISTOL, 0); if(cntTime == -1) cntTime = 0; cntTime += TICRATE * 3; // Par time might not be defined so count up and stop on play time instead. if(cntTime >= plrs[me].time) { cntTime = plrs[me].time; cntPar = wbs->parTime; S_LocalSound(SFX_BAREXP, 0); spState++; } if(wbs->parTime != -1) { if(cntPar == -1) cntPar = 0; cntPar += TICRATE * 3; if(cntPar >= wbs->parTime) cntPar = wbs->parTime; } } else if(spState == 10) { if(accelerateStage) { S_LocalSound(SFX_SGCOCK, 0); if(gameMode == commercial) WI_initNoState(); else WI_initShowNextLoc(); } } else if(spState & 1) { if(!--cntPause) { spState++; cntPause = TICRATE; } } } void WI_drawStats(void) { int lh; // Line height. lh = (3 * num[0].height) / 2; WI_slamBackground(); // Draw animated background. WI_drawAnimatedBack(); WI_drawLF(); WI_DrawPatch(SP_STATSX, SP_STATSY, 1, 1, 1, 1, &kills, NULL, false, ALIGN_LEFT); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY, cntKills[0]); WI_DrawPatch(SP_STATSX, SP_STATSY + lh, 1, 1, 1, 1, &items, NULL, false, ALIGN_LEFT); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY + lh, cntItems[0]); WI_DrawPatch(SP_STATSX, SP_STATSY + 2 * lh, 1, 1, 1, 1, &sp_secret, NULL, false, ALIGN_LEFT); WI_drawPercent(SCREENWIDTH - SP_STATSX, SP_STATSY + 2 * lh, cntSecret[0]); WI_DrawPatch(SP_TIMEX, SP_TIMEY, 1, 1, 1, 1, &time, NULL, false, ALIGN_LEFT); if(cntTime >= 0) WI_drawTime(SCREENWIDTH / 2 - SP_TIMEX, SP_TIMEY, cntTime / TICRATE); if(wbs->parTime != -1) { WI_DrawPatch(SCREENWIDTH / 2 + SP_TIMEX, SP_TIMEY, 1, 1, 1, 1, &par, NULL, false, ALIGN_LEFT); if(cntPar >= 0) WI_drawTime(SCREENWIDTH - SP_TIMEX, SP_TIMEY, cntPar / TICRATE); } } void WI_checkForAccelerate(void) { int i; player_t *player; // Check for button presses to skip delays. for(i = 0, player = players; i < MAXPLAYERS; ++i, player++) { if(players[i].plr->inGame) { if(player->brain.attack) { if(!player->attackDown) accelerateStage = 1; player->attackDown = true; } else { player->attackDown = false; } if(player->brain.use) { if(!player->useDown) accelerateStage = 1; player->useDown = true; } else { player->useDown = false; } } } } /** * Called every tic when gameState == GS_INTERMISSION. */ void WI_Ticker(void) { // Counter for general background animation. bcnt++; WI_checkForAccelerate(); switch(state) { case ILS_SHOW_STATS: if(deathmatch) WI_updateDeathmatchStats(); else if(IS_NETGAME) WI_updateNetgameStats(); else WI_updateStats(); break; case ILS_SHOW_NEXTMAP: WI_updateShowNextLoc(); break; case ILS_NONE: default: WI_updateNoState(); break; } } void WI_loadData(void) { int i, j; char name[9]; wianim_t *a; if(gameMode == commercial) strcpy(name, "INTERPIC"); else sprintf(name, "WIMAP%u", wbs->episode); if(gameMode == retail) { if(wbs->episode > 2) strcpy(name, "INTERPIC"); } R_CachePatch(&bg, name); if(gameMode != commercial) { // You are here. R_CachePatch(&yah[0], "WIURH0"); // You are here (alt.) R_CachePatch(&yah[1], "WIURH1"); // Splat. R_CachePatch(&splat, "WISPLAT"); if(wbs->episode < 3) { for(j = 0; j < NUMANIMS[wbs->episode]; ++j) { a = &anims[wbs->episode][j]; for(i = 0; i < a->numAnimFrames; ++i) { //// \kludge > if(wbs->episode != 1 || j != 8) { // Animations sprintf(name, "WIA%u%.2d%.2d", wbs->episode, j, i); R_CachePatch(&a->p[i], name); } else { memcpy(&a->p[i], &anims[1][4].p[i], sizeof(dpatch_t)); } //// \kludge < } } } } R_CachePatch(&wiminus, "WIMINUS"); for(i = 0; i < 10; ++i) { // Numbers 0-9. sprintf(name, "WINUM%d", i); R_CachePatch(&num[i], name); } // Percent sign. R_CachePatch(&percent, "WIPCNT"); // "finished" R_CachePatch(&finished, "WIF"); // "entering" R_CachePatch(&entering, "WIENTER"); // "kills" R_CachePatch(&kills, "WIOSTK"); // "scrt" R_CachePatch(&secret, "WIOSTS"); // "secret" R_CachePatch(&sp_secret, "WISCRT2"); // "items" R_CachePatch(&items, "WIOSTI"); // "frgs" R_CachePatch(&frags, "WIFRGS"); // ":" R_CachePatch(&colon, "WICOLON"); // "time" R_CachePatch(&time, "WITIME"); // "sucks" R_CachePatch(&sucks, "WISUCKS"); // "par" R_CachePatch(&par, "WIPAR"); // "killers" (vertical) R_CachePatch(&killers, "WIKILRS"); // "victims" (horiz) R_CachePatch(&victims, "WIVCTMS"); // "total" R_CachePatch(&total, "WIMSTT"); // your face R_CachePatch(&star, "STFST01"); // dead face R_CachePatch(&bstar, "STFDEAD0"); for(i = 0; i < MAXPLAYERS; ++i) { // "1,2,3,4" sprintf(name, "STPB%d", i); R_CachePatch(&p[i], name); // "1,2,3,4" sprintf(name, "WIBP%d", i + 1); R_CachePatch(&bp[i], name); } } void WI_Drawer(void) { switch(state) { case ILS_SHOW_STATS: if(deathmatch) WI_drawDeathmatchStats(); else if(IS_NETGAME) WI_drawNetgameStats(); else WI_drawStats(); break; case ILS_SHOW_NEXTMAP: WI_drawShowNextLoc(); break; case ILS_NONE: default: WI_drawNoState(); break; } } void WI_initVariables(wbstartstruct_t * wbstartstruct) { wbs = wbstartstruct; #ifdef RANGECHECK if(gameMode != commercial) { if(gameMode == retail) RNGCHECK(wbs->epsd, 0, 3); else RNGCHECK(wbs->epsd, 0, 2); } else { RNGCHECK(wbs->last, 0, 8); RNGCHECK(wbs->next, 0, 8); } RNGCHECK(wbs->pnum, 0, MAXPLAYERS); RNGCHECK(wbs->pnum, 0, MAXPLAYERS); #endif accelerateStage = 0; cnt = bcnt = 0; firstRefresh = 1; me = wbs->pNum; myTeam = cfg.playerColor[wbs->pNum]; plrs = wbs->plyr; if(!wbs->maxKills) wbs->maxKills = 1; if(!wbs->maxItems) wbs->maxItems = 1; if(!wbs->maxSecret) wbs->maxSecret = 1; } void WI_Init(wbstartstruct_t* wbstartstruct) { int i, j, k; teaminfo_t* tin; WI_initVariables(wbstartstruct); WI_loadData(); // Calculate team stats. memset(teamInfo, 0, sizeof(teamInfo)); for(i = 0, tin = teamInfo; i < NUM_TEAMS; ++i, tin++) { for(j = 0; j < MAXPLAYERS; ++j) { // Is the player in this team? if(!plrs[j].inGame || cfg.playerColor[j] != i) continue; tin->members++; // Check the frags. for(k = 0; k < MAXPLAYERS; ++k) tin->frags[cfg.playerColor[k]] += plrs[j].frags[k]; // Counters. if(plrs[j].items > tin->items) tin->items = plrs[j].items; if(plrs[j].kills > tin->kills) tin->kills = plrs[j].kills; if(plrs[j].secret > tin->secret) tin->secret = plrs[j].secret; } // Calculate team's total frags. for(j = 0; j < NUM_TEAMS; ++j) { if(j == i) // Suicides are negative frags. tin->totalFrags -= tin->frags[j]; else tin->totalFrags += tin->frags[j]; } } if(deathmatch) WI_initDeathmatchStats(); else if(IS_NETGAME) WI_initNetgameStats(); else WI_initStats(); } void WI_SetState(interludestate_t st) { if(st == ILS_SHOW_STATS) WI_initStats(); if(st == ILS_SHOW_NEXTMAP) WI_initShowNextLoc(); if(st == ILS_NONE) WI_initNoState(); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_lights.c0000644000175000017500000002334411357170242022430 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.c: Handle Sector base lighting effects. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "dmu_lib.h" #include "p_mapsetup.h" #include "p_mapspec.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void T_FireFlicker(fireflicker_t *flick) { float amount, lightLevel; if(--flick->count) return; lightLevel = P_GetFloatp(flick->sector, DMU_LIGHT_LEVEL); amount = ((P_Random() & 3) * 16) / 255.0f; if(lightLevel - amount < flick->minLight) P_SetFloatp(flick->sector, DMU_LIGHT_LEVEL, flick->minLight); else P_SetFloatp(flick->sector, DMU_LIGHT_LEVEL, flick->maxLight - amount); flick->count = 4; } void P_SpawnFireFlicker(sector_t *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; fireflicker_t *flick; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; flick = Z_Calloc(sizeof(*flick), PU_MAP, 0); flick->thinker.function = T_FireFlicker; DD_ThinkerAdd(&flick->thinker); flick->sector = sector; flick->count = 4; flick->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flick->minLight = otherLevel; else flick->minLight = lightLevel; flick->minLight += (16.0f/255.0f); } /** * Broken light flashing. */ void T_LightFlash(lightflash_t *flash) { float lightLevel; if(--flash->count) return; lightLevel = P_GetFloatp(flash->sector, DMU_LIGHT_LEVEL); if(lightLevel == flash->maxLight) { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->minLight); flash->count = (P_Random() & flash->minTime) + 1; } else { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->maxLight); flash->count = (P_Random() & flash->maxTime) + 1; } } /** * After the map has been loaded, scan each sector * for specials that spawn thinkers */ void P_SpawnLightFlash(sector_t *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; lightflash_t *flash; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; flash = Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = T_LightFlash; DD_ThinkerAdd(&flash->thinker); flash->sector = sector; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; flash->maxTime = 64; flash->minTime = 7; flash->count = (P_Random() & flash->maxTime) + 1; } /** * Strobe light flashing. */ void T_StrobeFlash(strobe_t *flash) { float lightLevel; if(--flash->count) return; lightLevel = P_GetFloatp(flash->sector, DMU_LIGHT_LEVEL); if(lightLevel == flash->minLight) { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->maxLight); flash->count = flash->brightTime; } else { P_SetFloatp(flash->sector, DMU_LIGHT_LEVEL, flash->minLight); flash->count = flash->darkTime; } } /** * After the map has been loaded, scan each sector for specials that spawn * thinkers. */ void P_SpawnStrobeFlash(sector_t *sector, int fastOrSlow, int inSync) { strobe_t *flash; float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; flash = Z_Calloc(sizeof(*flash), PU_MAP, 0); flash->thinker.function = T_StrobeFlash; DD_ThinkerAdd(&flash->thinker); flash->sector = sector; flash->darkTime = fastOrSlow; flash->brightTime = STROBEBRIGHT; flash->maxLight = lightLevel; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) flash->minLight = otherLevel; else flash->minLight = lightLevel; if(flash->minLight == flash->maxLight) flash->minLight = 0; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; if(!inSync) flash->count = (P_Random() & 7) + 1; else flash->count = 1; } /** * Start strobing lights (usually from a trigger) */ void EV_StartLightStrobing(linedef_t *line) { sector_t *sec = NULL; iterlist_t *list; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(P_ToXSector(sec)->specialData) continue; P_SpawnStrobeFlash(sec, SLOWDARK, 0); } } void EV_TurnTagLightsOff(linedef_t *line) { sector_t *sec = NULL; iterlist_t *list; float lightLevel; float otherLevel; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { lightLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); otherLevel = DDMAXFLOAT; P_FindSectorSurroundingLowestLight(sec, &otherLevel); if(otherLevel < lightLevel) lightLevel = otherLevel; P_SetFloatp(sec, DMU_LIGHT_LEVEL, lightLevel); } } void EV_LightTurnOn(linedef_t *line, float max) { sector_t *sec = NULL; iterlist_t *list; float lightLevel, otherLevel; list = P_GetSectorIterListForTag(P_ToXLine(line)->tag, false); if(!list) return; if(max != 0) lightLevel = max; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { // If Max = 0 means to search for the highest light level in the // surrounding sector. if(max == 0) { lightLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); otherLevel = DDMINFLOAT; P_FindSectorSurroundingHighestLight(sec, &otherLevel); if(otherLevel > lightLevel) lightLevel = otherLevel; } P_SetFloatp(sec, DMU_LIGHT_LEVEL, lightLevel); } } void T_Glow(glow_t *g) { float lightLevel = P_GetFloatp(g->sector, DMU_LIGHT_LEVEL); float glowDelta = (1.0f / 255.0f) * (float) GLOWSPEED; switch(g->direction) { case -1: // Down. lightLevel -= glowDelta; if(lightLevel <= g->minLight) { lightLevel += glowDelta; g->direction = 1; } break; case 1: // Up. lightLevel += glowDelta; if(lightLevel >= g->maxLight) { lightLevel -= glowDelta; g->direction = -1; } break; default: Con_Error("T_Glow: Invalid direction %i.", g->direction); break; } P_SetFloatp(g->sector, DMU_LIGHT_LEVEL, lightLevel); } void P_SpawnGlowingLight(sector_t *sector) { float lightLevel = P_GetFloatp(sector, DMU_LIGHT_LEVEL); float otherLevel = DDMAXFLOAT; glow_t *g; g = Z_Calloc(sizeof(*g), PU_MAP, 0); g->thinker.function = T_Glow; DD_ThinkerAdd(&g->thinker); g->sector = sector; P_FindSectorSurroundingLowestLight(sector, &otherLevel); if(otherLevel < lightLevel) g->minLight = otherLevel; else g->minLight = lightLevel; g->maxLight = lightLevel; g->direction = -1; // Note that we are resetting sector attributes. // Nothing special about it during gameplay. P_ToXSector(sector)->special = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_oldsvg.c0000644000175000017500000006345211357170242022440 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA * * \bug Not 64bit clean: In function 'SV_ReadMobj': cast to pointer from integer of different size * \bug Not 64bit clean: In function 'P_v19_UnArchivePlayers': cast from pointer to integer of different size * \bug Not 64bit clean: In function 'P_v19_UnArchiveThinkers': cast from pointer to integer of different size */ /** * p_oldsvg.c: */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "p_map.h" #include "p_mapsetup.h" #include "p_tick.h" #include "dmu_lib.h" #include "p_ceiling.h" #include "p_door.h" #include "p_floor.h" #include "p_plat.h" #include "am_map.h" // MACROS ------------------------------------------------------------------ #define PADSAVEP() savePtr += (4 - ((savePtr - saveBuffer) & 3)) & 3 // All the versions of DOOM have different savegame IDs, but 500 will be the // savegame base from now on. #define SAVE_VERSION_BASE 500 #define SAVE_VERSION (SAVE_VERSION_BASE + gameMode) #define V19_SAVESTRINGSIZE (24) #define VERSIONSIZE (16) #define FF_FULLBRIGHT (0x8000) // Used to be a flag in thing->frame. #define FF_FRAMEMASK (0x7fff) #define SIZEOF_V19_THINKER_T 12 #define V19_THINKER_T_FUNC_OFFSET 8 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern void SV_UpdateReadMobjFlags(mobj_t *mo, int ver); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static byte* savePtr; static byte* saveBuffer; // CODE -------------------------------------------------------------------- static void SV_Read(void* data, int len) { if(data) memcpy(data, savePtr, len); savePtr += len; } static short SV_ReadShort(void) { savePtr += 2; return *(short *) (savePtr - 2); } static int SV_ReadLong(void) { savePtr += 4; return *(int *) (savePtr - 4); } static void SV_ReadPlayer(player_t* pl) { int i; SV_ReadLong(); pl->playerState = SV_ReadLong(); SV_Read(NULL, 8); pl->viewZ = FIX2FLT(SV_ReadLong()); pl->viewHeight = FIX2FLT(SV_ReadLong()); pl->viewHeightDelta = FIX2FLT(SV_ReadLong()); pl->bob = FLT2FIX(SV_ReadLong()); pl->flyHeight = 0; pl->health = SV_ReadLong(); pl->armorPoints = SV_ReadLong(); pl->armorType = SV_ReadLong(); memset(pl->powers, 0, sizeof(pl->powers)); pl->powers[PT_INVULNERABILITY] = (SV_ReadLong()? true : false); pl->powers[PT_STRENGTH] = (SV_ReadLong()? true : false); pl->powers[PT_INVISIBILITY] = (SV_ReadLong()? true : false); pl->powers[PT_IRONFEET] = (SV_ReadLong()? true : false); pl->powers[PT_ALLMAP] = (SV_ReadLong()? true : false); if(pl->powers[PT_ALLMAP]) AM_RevealMap(AM_MapForPlayer(pl - players), true); pl->powers[PT_INFRARED] = (SV_ReadLong()? true : false); memset(pl->keys, 0, sizeof(pl->keys)); pl->keys[KT_BLUECARD] = (SV_ReadLong()? true : false); pl->keys[KT_YELLOWCARD] = (SV_ReadLong()? true : false); pl->keys[KT_REDCARD] = (SV_ReadLong()? true : false); pl->keys[KT_BLUESKULL] = (SV_ReadLong()? true : false); pl->keys[KT_YELLOWSKULL] = (SV_ReadLong()? true : false); pl->keys[KT_REDSKULL] = (SV_ReadLong()? true : false); pl->backpack = SV_ReadLong(); memset(pl->frags, 0, sizeof(pl->frags)); pl->frags[0] = SV_ReadLong(); pl->frags[1] = SV_ReadLong(); pl->frags[2] = SV_ReadLong(); pl->frags[3] = SV_ReadLong(); pl->readyWeapon = SV_ReadLong(); pl->pendingWeapon = SV_ReadLong(); memset(pl->weapons, 0, sizeof(pl->weapons)); pl->weapons[WT_FIRST].owned = (SV_ReadLong()? true : false); pl->weapons[WT_SECOND].owned = (SV_ReadLong()? true : false); pl->weapons[WT_THIRD].owned = (SV_ReadLong()? true : false); pl->weapons[WT_FOURTH].owned = (SV_ReadLong()? true : false); pl->weapons[WT_FIFTH].owned = (SV_ReadLong()? true : false); pl->weapons[WT_SIXTH].owned = (SV_ReadLong()? true : false); pl->weapons[WT_SEVENTH].owned = (SV_ReadLong()? true : false); pl->weapons[WT_EIGHTH].owned = (SV_ReadLong()? true : false); pl->weapons[WT_NINETH].owned = (SV_ReadLong()? true : false); memset(pl->ammo, 0, sizeof(pl->ammo)); pl->ammo[AT_CLIP].owned = SV_ReadLong(); pl->ammo[AT_SHELL].owned = SV_ReadLong(); pl->ammo[AT_CELL].owned = SV_ReadLong(); pl->ammo[AT_MISSILE].owned = SV_ReadLong(); pl->ammo[AT_CLIP].max = SV_ReadLong(); pl->ammo[AT_SHELL].max = SV_ReadLong(); pl->ammo[AT_CELL].max = SV_ReadLong(); pl->ammo[AT_MISSILE].max = SV_ReadLong(); pl->attackDown = SV_ReadLong(); pl->useDown = SV_ReadLong(); pl->cheats = SV_ReadLong(); pl->refire = SV_ReadLong(); pl->killCount = SV_ReadLong(); pl->itemCount = SV_ReadLong(); pl->secretCount = SV_ReadLong(); SV_ReadLong(); pl->damageCount = SV_ReadLong(); pl->bonusCount = SV_ReadLong(); SV_ReadLong(); pl->plr->extraLight = SV_ReadLong(); pl->plr->fixedColorMap = SV_ReadLong(); pl->colorMap = SV_ReadLong(); for(i = 0; i < 2; ++i) { pspdef_t *psp = &pl->pSprites[i]; psp->state = (state_t*) SV_ReadLong(); psp->pos[VX] = SV_ReadLong(); psp->pos[VY] = SV_ReadLong(); psp->tics = SV_ReadLong(); } pl->didSecret = SV_ReadLong(); } static void SV_ReadMobj(void) { float pos[3], mom[3], radius, height, floorz, ceilingz; angle_t angle; spritenum_t sprite; int frame, valid, type, ddflags = 0; mobj_t *mo; mobjinfo_t* info; // List: thinker links. SV_ReadLong(); SV_ReadLong(); SV_ReadLong(); // Info for drawing: position. pos[VX] = FIX2FLT(SV_ReadLong()); pos[VY] = FIX2FLT(SV_ReadLong()); pos[VZ] = FIX2FLT(SV_ReadLong()); // More list: links in sector (if needed) SV_ReadLong(); SV_ReadLong(); //More drawing info: to determine current sprite. angle = SV_ReadLong(); // orientation sprite = SV_ReadLong(); // used to find patch_t and flip value frame = SV_ReadLong(); // might be ORed with FF_FULLBRIGHT if(frame & FF_FULLBRIGHT) frame &= FF_FRAMEMASK; // not used anymore. // Interaction info, by BLOCKMAP. // Links in blocks (if needed). SV_ReadLong(); SV_ReadLong(); SV_ReadLong(); // The closest interval over all contacted Sectors. floorz = FIX2FLT(SV_ReadLong()); ceilingz = FIX2FLT(SV_ReadLong()); // For movement checking. radius = FIX2FLT(SV_ReadLong()); height = FIX2FLT(SV_ReadLong()); // Momentums, used to update position. mom[MX] = FIX2FLT(SV_ReadLong()); mom[MY] = FIX2FLT(SV_ReadLong()); mom[MZ] = FIX2FLT(SV_ReadLong()); valid = SV_ReadLong(); type = SV_ReadLong(); info = &MOBJINFO[type]; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; /** * We now have all the information we need to create the mobj. */ mo = P_MobjCreate(P_MobjThinker, pos[VX], pos[VY], pos[VZ], angle, radius, height, ddflags); mo->sprite = sprite; mo->frame = frame; mo->floorZ = floorz; mo->ceilingZ = ceilingz; mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; mo->mom[MZ] = mom[MZ]; mo->valid = valid; mo->type = type; mo->moveDir = DI_NODIR; /** * Continue reading the mobj data. */ SV_ReadLong(); // &mobjinfo[mo->type] mo->tics = SV_ReadLong(); // state tic counter mo->state = (state_t *) SV_ReadLong(); mo->damage = DDMAXINT; // Use damage set in mo->info->damage mo->flags = SV_ReadLong(); mo->health = SV_ReadLong(); // Movement direction, movement generation (zig-zagging). mo->moveDir = SV_ReadLong(); // 0-7 mo->moveCount = SV_ReadLong(); // when 0, select a new dir // Thing being chased/attacked (or NULL), // also the originator for missiles. SV_ReadLong(); // Reaction time: if non 0, don't attack yet. // Used by player to freeze a bit after teleporting. mo->reactionTime = SV_ReadLong(); // If >0, the target will be chased // no matter what (even if shot) mo->threshold = SV_ReadLong(); // Additional info record for player avatars only. // Only valid if type == MT_PLAYER mo->player = (player_t *) SV_ReadLong(); // Player number last looked for. mo->lastLook = SV_ReadLong(); // For nightmare respawn. mo->spawnSpot.pos[VX] = (float) SV_ReadShort(); mo->spawnSpot.pos[VY] = (float) SV_ReadShort(); mo->spawnSpot.pos[VZ] = 0; // Initialize with "something". mo->spawnSpot.angle = (angle_t) (ANG45 * ((int)SV_ReadShort() / 45)); /* mo->spawnSpot.type = (int) */ SV_ReadShort(); mo->spawnSpot.flags = (int) SV_ReadShort(); mo->spawnSpot.flags &= ~MASK_UNKNOWN_MSF_FLAGS; // Spawn on the floor by default unless the mobjtype flags override. mo->spawnSpot.flags |= MSF_Z_FLOOR; // Thing being chased/attacked for tracers. SV_ReadLong(); SV_UpdateReadMobjFlags(mo, 0); mo->state = &STATES[(int) mo->state]; mo->target = NULL; if(mo->player) { int pnum = (int) mo->player - 1; mo->player = &players[pnum]; mo->dPlayer = mo->player->plr; mo->dPlayer->mo = mo; //mo->dPlayer->clAngle = mo->angle; /* $unifiedangles */ mo->dPlayer->lookDir = 0; /* $unifiedangles */ } P_MobjSetPosition(mo); mo->info = info; mo->floorZ = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); mo->ceilingZ = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); } void P_v19_UnArchivePlayers(void) { int i, j; for(i = 0; i < 4; ++i) { if(!players[i].plr->inGame) continue; PADSAVEP(); SV_ReadPlayer(players + i); // will be set when unarc thinker players[i].plr->mo = NULL; players[i].attacker = NULL; for(j = 0; j < NUMPSPRITES; ++j) { if(players[i].pSprites[j].state) { players[i].pSprites[j].state = &STATES[(int) players[i].pSprites[j].state]; } } } } void P_v19_UnArchiveWorld(void) { uint i, j; float matOffset[2]; short *get; sector_t *sec; xsector_t *xsec; linedef_t *line; xline_t *xline; get = (short *) savePtr; // Do sectors. for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); P_SetFloatp(sec, DMU_FLOOR_HEIGHT, (float) (*get++)); P_SetFloatp(sec, DMU_CEILING_HEIGHT, (float) (*get++)); P_SetPtrp(sec, DMU_FLOOR_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_FLATS))); P_SetPtrp(sec, DMU_CEILING_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_FLATS))); P_SetFloatp(sec, DMU_LIGHT_LEVEL, (float) (*get++) / 255.0f); xsec->special = *get++; // needed? /*xsec->tag =*/ *get++; // needed? xsec->specialData = 0; xsec->soundTarget = 0; } // Do lines. for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); xline = P_ToXLine(line); xline->flags = *get++; xline->special = *get++; /*xline->tag =*/ *get++; for(j = 0; j < 2; ++j) { sidedef_t* sdef = P_GetPtrp(line, (j? DMU_SIDEDEF1:DMU_SIDEDEF0)); if(!sdef) continue; matOffset[VX] = (float) (*get++); matOffset[VY] = (float) (*get++); P_SetFloatpv(sdef, DMU_TOP_MATERIAL_OFFSET_XY, matOffset); P_SetFloatpv(sdef, DMU_MIDDLE_MATERIAL_OFFSET_XY, matOffset); P_SetFloatpv(sdef, DMU_BOTTOM_MATERIAL_OFFSET_XY, matOffset); P_SetPtrp(sdef, DMU_TOP_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_TEXTURES))); P_SetPtrp(sdef, DMU_BOTTOM_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_TEXTURES))); P_SetPtrp(sdef, DMU_MIDDLE_MATERIAL, P_ToPtr(DMU_MATERIAL, P_MaterialNumForIndex(*get++, MN_TEXTURES))); } } savePtr = (byte *) get; } static boolean removeThinker(thinker_t* th, void* context) { if(th->function == P_MobjThinker) P_MobjRemove((mobj_t *) th, true); else Z_Free(th); return true; // Continue iteration. } void P_v19_UnArchiveThinkers(void) { enum thinkerclass_e { TC_END, TC_MOBJ }; byte tClass; // Remove all the current thinkers. DD_IterateThinkers(NULL, removeThinker, NULL); DD_InitThinkers(); // Read in saved thinkers. for(;;) { tClass = *savePtr++; switch(tClass) { case TC_END: return; // End of list. case TC_MOBJ: PADSAVEP(); SV_ReadMobj(); break; default: Con_Error("Unknown tclass %i in savegame", tClass); } } } static int SV_ReadCeiling(ceiling_t *ceiling) { /* Original DOOM format: typedef struct { thinker_t thinker; // was 12 bytes ceilingtype_e type; // was 32bit int sector_t *sector; fixed_t bottomheight; fixed_t topheight; fixed_t speed; boolean crush; int direction; int tag; int olddirection; } v19_ceiling_t; */ byte temp[SIZEOF_V19_THINKER_T]; // Padding at the start (an old thinker_t struct). SV_Read(&temp, SIZEOF_V19_THINKER_T); // Start of used data members. ceiling->type = SV_ReadLong(); // A 32bit pointer to sector, serialized. ceiling->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!ceiling->sector) Con_Error("tc_ceiling: bad sector number\n"); ceiling->bottomHeight = FIX2FLT(SV_ReadLong()); ceiling->topHeight = FIX2FLT(SV_ReadLong()); ceiling->speed = FIX2FLT(SV_ReadLong()); ceiling->crush = SV_ReadLong(); ceiling->state = (SV_ReadLong() == -1? CS_DOWN : CS_UP); ceiling->tag = SV_ReadLong(); ceiling->oldState = (SV_ReadLong() == -1? CS_DOWN : CS_UP); ceiling->thinker.function = T_MoveCeiling; if(!(temp + V19_THINKER_T_FUNC_OFFSET)) DD_ThinkerSetStasis(&ceiling->thinker, true); P_ToXSector(ceiling->sector)->specialData = ceiling; return true; // Add this thinker. } static int SV_ReadDoor(door_t *door) { /* Original DOOM format: typedef struct { thinker_t thinker; // was 12 bytes doortype_e type; // was 32bit int sector_t *sector; fixed_t topheight; fixed_t speed; int direction; int topwait; int topcountdown; } v19_vldoor_t; */ // Padding at the start (an old thinker_t struct) SV_Read(NULL, SIZEOF_V19_THINKER_T); // Start of used data members. door->type = SV_ReadLong(); // A 32bit pointer to sector, serialized. door->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!door->sector) Con_Error("tc_door: bad sector number\n"); door->topHeight = FIX2FLT(SV_ReadLong()); door->speed = FIX2FLT(SV_ReadLong()); door->state = SV_ReadLong(); door->topWait = SV_ReadLong(); door->topCountDown = SV_ReadLong(); door->thinker.function = T_Door; P_ToXSector(door->sector)->specialData = door; return true; // Add this thinker. } static int SV_ReadFloor(floor_t *floor) { /* Original DOOM format: typedef struct { thinker_t thinker; // was 12 bytes floortype_e type; // was 32bit int boolean crush; sector_t *sector; int direction; int newspecial; short texture; fixed_t floordestheight; fixed_t speed; } v19_floormove_t; */ // Padding at the start (an old thinker_t struct) SV_Read(NULL, SIZEOF_V19_THINKER_T); // Start of used data members. floor->type = SV_ReadLong(); floor->crush = SV_ReadLong(); // A 32bit pointer to sector, serialized. floor->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!floor->sector) Con_Error("tc_floor: bad sector number\n"); floor->state = (int) SV_ReadLong(); floor->newSpecial = SV_ReadLong(); floor->material = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(W_LumpName(SV_ReadShort()), MN_FLATS)); floor->floorDestHeight = FIX2FLT(SV_ReadLong()); floor->speed = FIX2FLT(SV_ReadLong()); floor->thinker.function = T_MoveFloor; P_ToXSector(floor->sector)->specialData = floor; return true; // Add this thinker. } static int SV_ReadPlat(plat_t *plat) { /* Original DOOM format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; fixed_t speed; fixed_t low; fixed_t high; int wait; int count; platstate_e status; // was 32bit int platstate_e oldstatus; // was 32bit int boolean crush; int tag; plattype_e type; // was 32bit int } v19_plat_t; */ byte temp[SIZEOF_V19_THINKER_T]; // Padding at the start (an old thinker_t struct) SV_Read(temp, SIZEOF_V19_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. plat->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!plat->sector) Con_Error("tc_plat: bad sector number\n"); plat->speed = FIX2FLT(SV_ReadLong()); plat->low = FIX2FLT(SV_ReadLong()); plat->high = FIX2FLT(SV_ReadLong()); plat->wait = SV_ReadLong(); plat->count = SV_ReadLong(); plat->state = SV_ReadLong(); plat->oldState = SV_ReadLong(); plat->crush = SV_ReadLong(); plat->tag = SV_ReadLong(); plat->type = SV_ReadLong(); plat->thinker.function = T_PlatRaise; if(!(temp + V19_THINKER_T_FUNC_OFFSET)) DD_ThinkerSetStasis(&plat->thinker, true); P_ToXSector(plat->sector)->specialData = plat; return true; // Add this thinker. } static int SV_ReadFlash(lightflash_t *flash) { /* Original DOOM format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; int count; int maxlight; int minlight; int maxtime; int mintime; } v19_lightflash_t; */ // Padding at the start (an old thinker_t struct) SV_Read(NULL, SIZEOF_V19_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. flash->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!flash->sector) Con_Error("tc_flash: bad sector number\n"); flash->count = SV_ReadLong(); flash->maxLight = (float) SV_ReadLong() / 255.0f; flash->minLight = (float) SV_ReadLong() / 255.0f; flash->maxTime = SV_ReadLong(); flash->minTime = SV_ReadLong(); flash->thinker.function = T_LightFlash; return true; // Add this thinker. } static int SV_ReadStrobe(strobe_t *strobe) { /* Original DOOM format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; int count; int minlight; int maxlight; int darktime; int brighttime; } v19_strobe_t; */ // Padding at the start (an old thinker_t struct) SV_Read(NULL, SIZEOF_V19_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. strobe->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!strobe->sector) Con_Error("tc_strobe: bad sector number\n"); strobe->count = SV_ReadLong(); strobe->minLight = (float) SV_ReadLong() / 255.0f; strobe->maxLight = (float) SV_ReadLong() / 255.0f; strobe->darkTime = SV_ReadLong(); strobe->brightTime = SV_ReadLong(); strobe->thinker.function = T_StrobeFlash; return true; // Add this thinker. } static int SV_ReadGlow(glow_t *glow) { /* Original DOOM format: typedef struct { thinker_t thinker; // was 12 bytes sector_t *sector; int minlight; int maxlight; int direction; } v19_glow_t; */ // Padding at the start (an old thinker_t struct) SV_Read(NULL, SIZEOF_V19_THINKER_T); // Start of used data members. // A 32bit pointer to sector, serialized. glow->sector = P_ToPtr(DMU_SECTOR, SV_ReadLong()); if(!glow->sector) Con_Error("tc_glow: bad sector number\n"); glow->minLight = (float) SV_ReadLong() / 255.0f; glow->maxLight = (float) SV_ReadLong() / 255.0f; glow->direction = SV_ReadLong(); glow->thinker.function = T_Glow; return true; // Add this thinker. } /* * Things to handle: * * T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list * T_Door, (door_t: sector_t * swizzle), * T_MoveFloor, (floor_t: sector_t * swizzle), * T_LightFlash, (lightflash_t: sector_t * swizzle), * T_StrobeFlash, (strobe_t: sector_t *), * T_Glow, (glow_t: sector_t *), * T_PlatRaise, (plat_t: sector_t *), - active list */ void P_v19_UnArchiveSpecials(void) { enum { tc_ceiling, tc_door, tc_floor, tc_plat, tc_flash, tc_strobe, tc_glow, tc_endspecials }; byte tClass; ceiling_t *ceiling; door_t *door; floor_t *floor; plat_t *plat; lightflash_t *flash; strobe_t *strobe; glow_t *glow; // Read in saved thinkers. for(;;) { tClass = *savePtr++; switch(tClass) { case tc_endspecials: return; // End of list. case tc_ceiling: PADSAVEP(); ceiling = Z_Calloc(sizeof(*ceiling), PU_MAP, NULL); SV_ReadCeiling(ceiling); DD_ThinkerAdd(&ceiling->thinker); break; case tc_door: PADSAVEP(); door = Z_Calloc(sizeof(*door), PU_MAP, NULL); SV_ReadDoor(door); DD_ThinkerAdd(&door->thinker); break; case tc_floor: PADSAVEP(); floor = Z_Calloc(sizeof(*floor), PU_MAP, NULL); SV_ReadFloor(floor); DD_ThinkerAdd(&floor->thinker); break; case tc_plat: PADSAVEP(); plat = Z_Calloc(sizeof(*plat), PU_MAP, NULL); SV_ReadPlat(plat); DD_ThinkerAdd(&plat->thinker); break; case tc_flash: PADSAVEP(); flash = Z_Calloc(sizeof(*flash), PU_MAP, NULL); SV_ReadFlash(flash); DD_ThinkerAdd(&flash->thinker); break; case tc_strobe: PADSAVEP(); strobe = Z_Calloc(sizeof(*strobe), PU_MAP, NULL); SV_ReadStrobe(strobe); DD_ThinkerAdd(&strobe->thinker); break; case tc_glow: PADSAVEP(); glow = Z_Calloc(sizeof(*glow), PU_MAP, NULL); SV_ReadGlow(glow); DD_ThinkerAdd(&glow->thinker); break; default: Con_Error("P_UnarchiveSpecials:Unknown tclass %i in savegame", tClass); } } } boolean SV_v19_LoadGame(const char* savename) { int i, a, b, c; size_t length; char vcheck[VERSIONSIZE]; if(!(length = M_ReadFile(savename, &saveBuffer))) return false; // Skip the description field. savePtr = saveBuffer + V19_SAVESTRINGSIZE; // Check version. memset(vcheck, 0, sizeof(vcheck)); sprintf(vcheck, "version %i", SAVE_VERSION); if(strcmp((const char*) savePtr, vcheck)) { int saveVer; sscanf((const char*) savePtr, "version %i", &saveVer); if(saveVer >= SAVE_VERSION_BASE) { // Must be from the wrong game. Con_Message("Bad savegame version.\n"); return false; } // Just give a warning. Con_Message("Savegame ID '%s': incompatible?\n", savePtr); } savePtr += VERSIONSIZE; gameSkill = *savePtr++; gameEpisode = (*savePtr++) - 1; gameMap = (*savePtr++) - 1; for(i = 0; i < 4; ++i) players[i].plr->inGame = *savePtr++; // Load a base map. G_InitNew(gameSkill, gameEpisode, gameMap); // Get the map time. a = *savePtr++; b = *savePtr++; c = *savePtr++; mapTime = (a << 16) + (b << 8) + c; // Dearchive all the modifications. P_v19_UnArchivePlayers(); P_v19_UnArchiveWorld(); P_v19_UnArchiveThinkers(); P_v19_UnArchiveSpecials(); if(*savePtr != 0x1d) Con_Error ("SV_v19_LoadGame: Bad savegame (consistency test failed!)\n"); // Success! Z_Free(saveBuffer); saveBuffer = NULL; // Spawn particle generators. R_SetupMap(DDSMM_AFTER_LOADING, 0); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/acfnlink.c0000644000175000017500000001164311357170242022403 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * acfnlink.c: Global action function (AI routines) link table. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- actionlink_t actionlinks[] = { {"A_BabyMetal", A_BabyMetal}, {"A_BFGsound", A_BFGsound}, {"A_BFGSpray", A_BFGSpray}, {"A_BossDeath", A_BossDeath}, {"A_BrainAwake", A_BrainAwake}, {"A_BrainDie", A_BrainDie}, {"A_BrainExplode", A_BrainExplode}, {"A_BrainPain", A_BrainPain}, {"A_BrainScream", A_BrainScream}, {"A_BrainSpit", A_BrainSpit}, {"A_BruisAttack", A_BruisAttack}, {"A_BspiAttack", A_BspiAttack}, {"A_Chase", A_Chase}, {"A_CheckReload", A_CheckReload}, {"A_CloseShotgun2", A_CloseShotgun2}, {"A_CPosAttack", A_CPosAttack}, {"A_CPosRefire", A_CPosRefire}, {"A_CyberAttack", A_CyberAttack}, {"A_Explode", A_Explode}, {"A_FaceTarget", A_FaceTarget}, {"A_Fall", A_Fall}, {"A_FatAttack1", A_FatAttack1}, {"A_FatAttack2", A_FatAttack2}, {"A_FatAttack3", A_FatAttack3}, {"A_FatRaise", A_FatRaise}, {"A_Fire", A_Fire}, {"A_FireBFG", A_FireBFG}, {"A_FireCGun", A_FireCGun}, {"A_FireCrackle", A_FireCrackle}, {"A_FireMissile", A_FireMissile}, {"A_FirePistol", A_FirePistol}, {"A_FirePlasma", A_FirePlasma}, {"A_FireShotgun", A_FireShotgun}, {"A_FireShotgun2", A_FireShotgun2}, {"A_GunFlash", A_GunFlash}, {"A_HeadAttack", A_HeadAttack}, {"A_Hoof", A_Hoof}, {"A_KeenDie", A_KeenDie}, {"A_Light0", A_Light0}, {"A_Light1", A_Light1}, {"A_Light2", A_Light2}, {"A_LoadShotgun2", A_LoadShotgun2}, {"A_Look", A_Look}, {"A_Lower", A_Lower}, {"A_Metal", A_Metal}, {"A_OpenShotgun2", A_OpenShotgun2}, {"A_Pain", A_Pain}, {"A_PainAttack", A_PainAttack}, {"A_PainDie", A_PainDie}, {"A_PlayerScream", A_PlayerScream}, {"A_PosAttack", A_PosAttack}, {"A_Punch", A_Punch}, {"A_Raise", A_Raise}, {"A_ReFire", A_ReFire}, {"A_SargAttack", A_SargAttack}, {"A_Saw", A_Saw}, {"A_Scream", A_Scream}, {"A_SkelFist", A_SkelFist}, {"A_SkelMissile", A_SkelMissile}, {"A_SkelWhoosh", A_SkelWhoosh}, {"A_SkullAttack", A_SkullAttack}, {"A_SpawnFly", A_SpawnFly}, {"A_SpawnSound", A_SpawnSound}, {"A_SpidRefire", A_SpidRefire}, {"A_SPosAttack", A_SPosAttack}, {"A_StartFire", A_StartFire}, {"A_Tracer", A_Tracer}, {"A_TroopAttack", A_TroopAttack}, {"A_VileAttack", A_VileAttack}, {"A_VileChase", A_VileChase}, {"A_VileStart", A_VileStart}, {"A_VileTarget", A_VileTarget}, {"A_WeaponReady", A_WeaponReady}, {"A_XScream", A_XScream}, {0, 0} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_setup.c0000644000175000017500000001267111357170242022277 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2002-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.c: Handle jDoom specific map data properties. */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "am_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Called during pre-init. * Register the map object data types we want to Doomsday to make public via * it's MPE interface. */ void P_RegisterMapObjs(void) { P_RegisterMapObj(MO_THING, "Thing"); P_RegisterMapObjProperty(MO_THING, MO_X, "X", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Y, "Y", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Z, "Z", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_ANGLE, "Angle", DDVT_ANGLE); P_RegisterMapObjProperty(MO_THING, MO_DOOMEDNUM, "DoomEdNum", DDVT_INT); P_RegisterMapObjProperty(MO_THING, MO_FLAGS, "Flags", DDVT_INT); P_RegisterMapObj(MO_XLINEDEF, "XLinedef"); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TAG, "Tag", DDVT_SHORT); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TYPE, "Type", DDVT_SHORT); P_RegisterMapObjProperty(MO_XLINEDEF, MO_FLAGS, "Flags", DDVT_SHORT); P_RegisterMapObj(MO_XSECTOR, "XSector"); P_RegisterMapObjProperty(MO_XSECTOR, MO_TAG, "Tag", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_TYPE, "Type", DDVT_SHORT); } /** * \todo This is actually unnecessary. If we say that in the case of BOOM * overloaded texture names, rather than setting the surface material as * normal, the map converter should instead write to a property in XLinedef * which the game can then look up later. * * Doomsday will call this when loading the map data if it encounters a * value that it doesn't understand for a property IT handles. * * Doomsday thinks we might know what to do with it... * If we don't know what to do we'll return -1. * * @param id Index of the current element being read. * @param dtype DMU type identifier. * @param prop DMU property identifier. * @param type Data type id of the value pointed to by *data. * @param *data Ptr to the data value (has already been expanded, * size converted and endian converted where necessary). */ int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void *data) { switch(dtype) { case DMU_SURFACE: switch(prop) { case DMU_MATERIAL: /** * It could be a BOOM overloaded texture name? * In this context Doomsday expects either -1 (a bad texture name) * Or the id of a wall texture it should set to this section. * \todo Add code to determine what to do. */ break; default: break; } break; default: break; } return -1; // We ain't got a clue what to do with it... } /** * These status reports inform us of what Doomsday is doing to a particular * map data object (at any time) that we might want to react to. * * If we arn't interested in the report - we should simply return true and * take no further action. * * @param code ID code of the status report (enum in dd_share.h) * @param id Map data object id. * @param type Map data object type eg DMU_SECTOR. * @param data Any relevant data for this report (currently unused). */ int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void *data) { switch(code) { case DMUSC_LINE_FIRSTRENDERED: /** * Called the first time the given line is rendered. * *data is a pointer to int, giving the player id which has seen it. * We'll utilize this to mark it as being visible in the automap. */ AM_UpdateLinedef(AM_MapForPlayer(*(int *) data), id, true); break; default: break; } return 1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/d_refresh.c0000644000175000017500000003452311357170242022561 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_refresh.c */ // HEADER FILES ------------------------------------------------------------ #include #include "jdoom.h" #include "hu_menu.h" #include "hu_stuff.h" #include "hu_pspr.h" #include "am_map.h" #include "g_common.h" #include "g_controls.h" #include "r_common.h" #include "d_net.h" #include "f_infine.h" #include "x_hair.h" #include "p_mapsetup.h" #include "p_tick.h" #include "rend_automap.h" // MACROS ------------------------------------------------------------------ #define WINDOWHEIGHT (Get(DD_VIEWWINDOW_HEIGHT)) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float quitDarkenOpacity = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Draws a special filter over the screen (e.g. the inversing filter used * when in god mode). */ void R_DrawSpecialFilter(int pnum) { player_t* player = &players[pnum]; if(player->powers[PT_INVULNERABILITY]) { float x, y, w, h; float max = 30; float str, r, g, b; int t = player->powers[PT_INVULNERABILITY]; if(t < max) str = t / max; else if(t < 4 * 32 && !(t & 8)) str = .7f; else if(t > INVULNTICS - max) str = (INVULNTICS - t) / max; else str = 1; // Full inversion. // Draw an inversing filter. DGL_Disable(DGL_TEXTURING); DGL_BlendMode(BM_INVERSE); r = MINMAX_OF(0.f, str * 2, 1.f); g = MINMAX_OF(0.f, str * 2 - .4, 1.f); b = MINMAX_OF(0.f, str * 2 - .8, 1.f); R_GetViewWindow(&x, &y, &w, &h); DGL_DrawRect(x, y, w, h, r, g, b, 1); // Restore the normal rendering state. DGL_BlendMode(BM_NORMAL); DGL_Enable(DGL_TEXTURING); } } boolean R_GetFilterColor(float rgba[4], int filter) { if(!rgba) return false; // We have to choose the right color and alpha. if(filter >= STARTREDPALS && filter < STARTREDPALS + NUMREDPALS) { // Red. rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; rgba[CA] = (deathmatch? 1.0f : cfg.filterStrength) * filter / 9.f; return true; } if(filter >= STARTBONUSPALS && filter < STARTBONUSPALS + NUMBONUSPALS) { // Gold. rgba[CR] = 1; rgba[CG] = .8f; rgba[CB] = .5f; rgba[CA] = cfg.filterStrength * (filter - STARTBONUSPALS + 1) / 16.f; return true; } if(filter == 13) // RADIATIONPAL { // Green. rgba[CR] = 0; rgba[CG] = .7f; rgba[CB] = 0; rgba[CA] = cfg.filterStrength * .25f; return true; } if(filter) Con_Message("R_GetFilterColor: Real strange filter number: %d.\n", filter); return false; } /** * Show map name and author. */ void R_DrawMapTitle(void) { float alpha; int y = 12, mapnum; const char* lname, *lauthor; if(!cfg.mapTitle || actualMapTime > 6 * TICSPERSEC) return; // Make the text a bit smaller. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(160, y, 0); DGL_Scalef(.7f, .7f, 1); DGL_Translatef(-160, -y, 0); alpha = 1; if(actualMapTime < 35) alpha = actualMapTime / 35.0f; if(actualMapTime > 5 * 35) alpha = 1 - (actualMapTime - 5 * 35) / 35.0f; lname = P_GetMapNiceName(); lauthor = P_GetMapAuthor(cfg.hideIWADAuthor); // Compose the mapnumber used to check the map name patches array. if(gameMode == commercial) mapnum = gameMap; else mapnum = (gameEpisode * 9) + gameMap; WI_DrawPatch(SCREENWIDTH / 2, y, 1, 1, 1, alpha, &mapNamePatches[mapnum], lname, false, ALIGN_CENTER); y += 14; if(lauthor) { M_WriteText3(160 - M_StringWidth(lauthor, GF_FONTA) / 2, y, lauthor, GF_FONTA, .5f, .5f, .5f, alpha, false, true, 0); } DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } /** * Do not really change anything here, because Doomsday might be in the * middle of a refresh. The change will take effect next refresh. */ void R_SetViewSize(int blocks) { cfg.setSizeNeeded = true; if(cfg.setBlocks != blocks && blocks > 10 && blocks < 13) { int i; // When going fullscreen, force a hud show event (to reset the timer). for(i = 0; i < MAXPLAYERS; ++i) { ST_HUDUnHide(i, HUE_FORCE); } } cfg.setBlocks = blocks; } static void rendPlayerView(int player) { player_t* plr = &players[player]; float viewPos[3], viewPitch, pspriteOffsetY; angle_t viewAngle; int isFullBright = ((plr->powers[PT_INFRARED] > 4 * 32) || (plr->powers[PT_INFRARED] & 8) || plr->powers[PT_INVULNERABILITY] > 30); if(IS_CLIENT) { // Server updates mobj flags in NetSv_Ticker. R_SetAllDoomsdayFlags(); } viewPos[VX] = plr->plr->mo->pos[VX] + plr->viewOffset[VX]; viewPos[VY] = plr->plr->mo->pos[VY] + plr->viewOffset[VY]; viewPos[VZ] = plr->viewZ + plr->viewOffset[VZ]; viewAngle = plr->plr->mo->angle + (int) (ANGLE_MAX * -G_GetLookOffset(player)); viewPitch = plr->plr->lookDir; DD_SetVariable(DD_VIEW_X, &viewPos[VX]); DD_SetVariable(DD_VIEW_Y, &viewPos[VY]); DD_SetVariable(DD_VIEW_Z, &viewPos[VZ]); DD_SetVariable(DD_VIEW_ANGLE, &viewAngle); DD_SetVariable(DD_VIEW_PITCH, &viewPitch); pspriteOffsetY = HU_PSpriteYOffset(plr); DD_SetVariable(DD_PSPRITE_OFFSET_Y, &pspriteOffsetY); // $democam GL_SetFilter((plr->plr->flags & DDPF_VIEW_FILTER)? true : false); if(plr->plr->flags & DDPF_VIEW_FILTER) { const float* color = plr->plr->filterColor; GL_SetFilterColor(color[CR], color[CG], color[CB], color[CA]); } // How about fullbright? DD_SetInteger(DD_FULLBRIGHT, isFullBright); // Render the view with possible custom filters. R_RenderPlayerView(player); } static void rendHUD(int player) { player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; if(G_GetGameState() != GS_MAP) return; if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; plr = &players[player]; // These various HUD's will be drawn unless Doomsday advises not to if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { automapid_t map = AM_MapForPlayer(player); boolean redrawsbar = false; // Draw HUD displays only visible when the automap is open. if(AM_IsActive(map)) HU_DrawMapCounters(); if(WINDOWHEIGHT != 200) redrawsbar = true; // Do we need to render a full status bar at this point? if(!(AM_IsActive(map) && cfg.automapHudDisplay == 0) && !(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { int viewmode = ((WINDOWHEIGHT == 200)? cfg.setBlocks - 10 : 0); ST_Drawer(player, viewmode, redrawsbar); } HU_Drawer(player); } } /** * Draws the in-viewport display. * * @param layer @c 0 = bottom layer (before the viewport border). * @c 1 = top layer (after the viewport border). */ void D_Display(int layer) { int player = DISPLAYPLAYER; player_t* plr = &players[player]; float x, y, w, h; if(layer != 0) { rendHUD(player); return; } if(G_GetGameState() == GS_MAP) { // $democam: can be set on every frame. if(cfg.setBlocks > 10 || (P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { // Full screen. R_SetViewWindowTarget(0, 0, SCREENWIDTH, SCREENHEIGHT); } else { int w = cfg.setBlocks * 32; int h = cfg.setBlocks * (SCREENHEIGHT - ST_HEIGHT * cfg.statusbarScale/20) / 10; R_SetViewWindowTarget(SCREENWIDTH/2 - w/2, (SCREENHEIGHT - ST_HEIGHT * cfg.statusbarScale / 20 - h) / 2, w, h); } R_GetViewWindow(&x, &y, &w, &h); } else { x = 0; y = 0; w = SCREENWIDTH; h = SCREENHEIGHT; } R_SetViewWindow((int) x, (int) y, (int) w, (int) h); switch(G_GetGameState()) { case GS_MAP: if(!(MN_CurrentMenuHasBackground() && Hu_MenuAlpha() >= 1) && !R_MapObscures(player, (int) x, (int) y, (int) w, (int) h)) { if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; rendPlayerView(player); R_DrawSpecialFilter(player); // Crosshair. if(!(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) // $democam X_Drawer(player); } // Draw the automap. AM_Drawer(player); break; case GS_STARTUP: DGL_Disable(DGL_TEXTURING); DGL_DrawRect(x, y, w, h, 0, 0, 0, 1); DGL_Enable(DGL_TEXTURING); break; default: break; } } /** * Draws the over-viewport display. */ void D_Display2(void) { switch(G_GetGameState()) { case GS_MAP: if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) break; if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { // Map information is shown for a few seconds in the // beginning of a map. R_DrawMapTitle(); } break; case GS_INTERMISSION: WI_Drawer(); break; case GS_WAITING: //gl.Clear(DGL_COLOR_BUFFER_BIT); //M_WriteText2(5, 188, "WAITING... PRESS ESC FOR MENU", GF_FONTA, 1, 0, 0, 1); break; default: break; } // Draw pause pic (but not if InFine active). if(paused && !fiActive) { WI_DrawPatch(SCREENWIDTH /2, 4, 1, 1, 1, 1, &m_pause, NULL, false, ALIGN_CENTER); } // InFine is drawn whenever active. FI_Drawer(); // Draw HUD displays; menu, messages. Hu_Drawer(); if(G_GetGameAction() == GA_QUIT) { DGL_Disable(DGL_TEXTURING); DGL_DrawRect(0, 0, 320, 200, 0, 0, 0, quitDarkenOpacity); DGL_Enable(DGL_TEXTURING); } } /** * Updates the mobj flags used by Doomsday with the state of our local flags * for the given mobj. */ void P_SetDoomsdayFlags(mobj_t *mo) { // Client mobjs can't be set here. if(IS_CLIENT && (mo->ddFlags & DDMF_REMOTE)) return; // Reset the flags for a new frame. mo->ddFlags &= DDMF_CLEAR_MASK; // Local objects aren't sent to clients. if(mo->flags & MF_LOCAL) mo->ddFlags |= DDMF_LOCAL; if(mo->flags & MF_SOLID) mo->ddFlags |= DDMF_SOLID; if(mo->flags & MF_NOGRAVITY) mo->ddFlags |= DDMF_NOGRAVITY; if(mo->flags2 & MF2_FLOATBOB) mo->ddFlags |= DDMF_NOGRAVITY | DDMF_BOB; if(mo->flags & MF_MISSILE) { mo->ddFlags |= DDMF_MISSILE; } if(mo->type == MT_LIGHTSOURCE) mo->ddFlags |= DDMF_ALWAYSLIT | DDMF_DONTDRAW; if(mo->info && (mo->info->flags2 & MF2_ALWAYSLIT)) mo->ddFlags |= DDMF_ALWAYSLIT; if(mo->flags2 & MF2_FLY) mo->ddFlags |= DDMF_FLY | DDMF_NOGRAVITY; // $democam: cameramen are invisible if(P_MobjIsCamera(mo)) mo->ddFlags |= DDMF_DONTDRAW; if((mo->flags & MF_CORPSE) && cfg.corpseTime && mo->corpseTics == -1) mo->ddFlags |= DDMF_DONTDRAW; // Choose which ddflags to set. if(mo->flags2 & MF2_DONTDRAW) { mo->ddFlags |= DDMF_DONTDRAW; return; // No point in checking the other flags. } if(mo->flags2 & MF2_LOGRAV) mo->ddFlags |= DDMF_LOWGRAVITY; /** * The torches often go into the ceiling. This'll prevent them from * 'jumping' when they do. * * \todo Add a thing def flag for this. */ if(mo->type == MT_MISC41 || mo->type == MT_MISC42 || mo->type == MT_MISC43 || // tall torches mo->type == MT_MISC44 || mo->type == MT_MISC45 || mo->type == MT_MISC46) // short torches mo->ddFlags |= DDMF_NOFITBOTTOM; if(mo->flags & MF_BRIGHTSHADOW) mo->ddFlags |= DDMF_BRIGHTSHADOW; else if(mo->flags & MF_SHADOW) mo->ddFlags |= DDMF_SHADOW; if(((mo->flags & MF_VIEWALIGN) && !(mo->flags & MF_MISSILE)) || ((mo->flags & MF_MISSILE) && !(mo->flags & MF_VIEWALIGN)) || (mo->flags & MF_FLOAT)) mo->ddFlags |= DDMF_VIEWALIGN; if(mo->flags & MF_TRANSLATION) mo->tmap = (mo->flags & MF_TRANSLATION) >> MF_TRANSSHIFT; } /** * Updates the status flags for all visible things. */ void R_SetAllDoomsdayFlags(void) { uint i; mobj_t *iter; // Only visible things are in the sector thinglists, so this is good. for(i = 0; i < numsectors; ++i) { for(iter = P_GetPtr(DMU_SECTOR, i, DMT_MOBJS); iter; iter = iter->sNext) { P_SetDoomsdayFlags(iter); } } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/d_console.c0000644000175000017500000002670111357170242022564 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_console.c: jDoom specific console stuff */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "hu_stuff.h" #include "f_infine.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- DEFCC(CCmdCheat); DEFCC(CCmdCheatGod); DEFCC(CCmdCheatNoClip); DEFCC(CCmdCheatWarp); DEFCC(CCmdCheatReveal); DEFCC(CCmdCheatGive); DEFCC(CCmdCheatMassacre); DEFCC(CCmdCheatWhere); DEFCC(CCmdCheatLeaveMap); DEFCC(CCmdCheatSuicide); DEFCC(CCmdMakeLocal); DEFCC(CCmdSetCamera); DEFCC(CCmdSetViewLock); DEFCC(CCmdSetViewMode); DEFCC(CCmdCycleSpy); DEFCC(CCmdPlayDemo); DEFCC(CCmdRecordDemo); DEFCC(CCmdStopDemo); DEFCC(CCmdSpawnMobj); DEFCC(CCmdPrintPlayerCoords); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdScreenShot); DEFCC(CCmdViewSize); DEFCC(CCmdDoomFont); DEFCC(CCmdConBackground); void G_UpdateEyeHeight(cvar_t* unused); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- material_t* consoleBG = 0; float consoleZoom = 1; // Console variables. cvar_t gameCVars[] = { // Console {"con-zoom", 0, CVT_FLOAT, &consoleZoom, 0.1f, 100.0f}, // View/Refresh {"view-size", CVF_PROTECTED, CVT_INT, &cfg.screenBlocks, 3, 13}, {"hud-title", 0, CVT_BYTE, &cfg.mapTitle, 0, 1}, {"hud-title-author-noiwad", 0, CVT_BYTE, &cfg.hideIWADAuthor, 0, 1}, {"view-bob-height", 0, CVT_FLOAT, &cfg.bobView, 0, 1}, {"view-bob-weapon", 0, CVT_FLOAT, &cfg.bobWeapon, 0, 1}, {"view-bob-weapon-switch-lower", 0, CVT_BYTE, &cfg.bobWeaponLower, 0, 1}, {"view-filter-strength", 0, CVT_FLOAT, &cfg.filterStrength, 0, 1}, // Server-side options // Game state {"server-game-skill", 0, CVT_BYTE, &cfg.netSkill, 0, 4}, {"server-game-map", CVF_NO_MAX, CVT_BYTE, &cfg.netMap, 0, 0}, {"server-game-episode", CVF_NO_MAX, CVT_BYTE, &cfg.netEpisode, 0, 0}, {"server-game-deathmatch", 0, CVT_BYTE, &cfg.netDeathmatch, 0, 2}, // Modifiers {"server-game-mod-damage", 0, CVT_BYTE, &cfg.netMobDamageModifier, 1, 100}, {"server-game-mod-health", 0, CVT_BYTE, &cfg.netMobHealthModifier, 1, 20}, {"server-game-mod-gravity", 0, CVT_INT, &cfg.netGravity, -1, 100}, // Items {"server-game-nobfg", 0, CVT_BYTE, &cfg.noNetBFG, 0, 1}, {"server-game-coop-nothing", 0, CVT_BYTE, &cfg.noCoopAnything, 0, 1}, {"server-game-coop-respawn-items", 0, CVT_BYTE, &cfg.coopRespawnItems, 0, 1}, {"server-game-coop-noweapons", 0, CVT_BYTE, &cfg.noCoopWeapons, 0, 1}, // Gameplay options {"server-game-jump", 0, CVT_BYTE, &cfg.netJumping, 0, 1}, {"server-game-bfg-freeaim", 0, CVT_BYTE, &cfg.netBFGFreeLook, 0, 1}, {"server-game-nomonsters", 0, CVT_BYTE, &cfg.netNoMonsters, 0, 1 }, {"server-game-respawn", 0, CVT_BYTE, &cfg.netRespawn, 0, 1}, {"server-game-respawn-monsters-nightmare", 0, CVT_BYTE, &cfg.respawnMonstersNightmare, 0, 1}, {"server-game-radiusattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZRadiusAttack, 0, 1}, {"server-game-monster-meleeattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZMonsterMeleeAttack, 0, 1}, {"server-game-coop-nodamage", 0, CVT_BYTE, &cfg.noCoopDamage, 0, 1}, {"server-game-noteamdamage", 0, CVT_BYTE, &cfg.noTeamDamage, 0, 1}, // Misc {"server-game-deathmatch-killmsg", 0, CVT_BYTE, &cfg.killMessages, 0, 1}, {"server-game-announce-secret", 0, CVT_BYTE, &cfg.secretMsg, 0, 1}, // Player // Player data {"player-color", 0, CVT_BYTE, &cfg.netColor, 0, 3}, {"player-eyeheight", 0, CVT_INT, &cfg.plrViewHeight, 41, 54, G_UpdateEyeHeight}, // Movment {"player-move-speed", 0, CVT_FLOAT, &cfg.playerMoveSpeed, 0, 1}, {"player-jump", 0, CVT_INT, &cfg.jumpEnabled, 0, 1}, {"player-jump-power", 0, CVT_FLOAT, &cfg.jumpPower, 0, 100}, {"player-air-movement", 0, CVT_BYTE, &cfg.airborneMovement, 0, 32}, // Weapon switch preferences {"player-autoswitch", 0, CVT_BYTE, &cfg.weaponAutoSwitch, 0, 2}, {"player-autoswitch-ammo", 0, CVT_BYTE, &cfg.ammoAutoSwitch, 0, 2}, {"player-autoswitch-berserk", 0, CVT_BYTE, &cfg.berserkAutoSwitch, 0, 1}, {"player-autoswitch-notfiring", 0, CVT_BYTE, &cfg.noWeaponAutoSwitchIfFiring, 0, 1}, // Weapon Order preferences {"player-weapon-order0", 0, CVT_INT, &cfg.weaponOrder[0], 0, NUM_WEAPON_TYPES}, {"player-weapon-order1", 0, CVT_INT, &cfg.weaponOrder[1], 0, NUM_WEAPON_TYPES}, {"player-weapon-order2", 0, CVT_INT, &cfg.weaponOrder[2], 0, NUM_WEAPON_TYPES}, {"player-weapon-order3", 0, CVT_INT, &cfg.weaponOrder[3], 0, NUM_WEAPON_TYPES}, {"player-weapon-order4", 0, CVT_INT, &cfg.weaponOrder[4], 0, NUM_WEAPON_TYPES}, {"player-weapon-order5", 0, CVT_INT, &cfg.weaponOrder[5], 0, NUM_WEAPON_TYPES}, {"player-weapon-order6", 0, CVT_INT, &cfg.weaponOrder[6], 0, NUM_WEAPON_TYPES}, {"player-weapon-order7", 0, CVT_INT, &cfg.weaponOrder[7], 0, NUM_WEAPON_TYPES}, {"player-weapon-order8", 0, CVT_INT, &cfg.weaponOrder[8], 0, NUM_WEAPON_TYPES}, {"player-weapon-nextmode", 0, CVT_BYTE, &cfg.weaponNextMode, 0, 1}, // Misc {"player-camera-noclip", 0, CVT_INT, &cfg.cameraNoClip, 0, 1}, {"player-death-lookup", 0, CVT_BYTE, &cfg.deathLookUp, 0, 1}, // Compatibility options {"game-raiseghosts", 0, CVT_BYTE, &cfg.raiseGhosts, 0, 1}, {"game-maxskulls", 0, CVT_BYTE, &cfg.maxSkulls, 0, 1}, {"game-skullsinwalls", 0, CVT_BYTE, &cfg.allowSkullsInWalls, 0, 1}, {"game-anybossdeath666", 0, CVT_BYTE, &cfg.anyBossDeath, 0, 1}, {"game-monsters-stuckindoors", 0, CVT_BYTE, &cfg.monstersStuckInDoors, 0, 1}, {"game-objects-neverhangoverledges", 0, CVT_BYTE, &cfg.avoidDropoffs, 0, 1}, {"game-objects-clipping", 0, CVT_BYTE, &cfg.moveBlock, 0, 1}, {"game-zombiescanexit", 0, CVT_BYTE, &cfg.zombiesCanExit, 0, 1}, {"game-player-wallrun-northonly", 0, CVT_BYTE, &cfg.wallRunNorthOnly, 0, 1}, {"game-objects-falloff", 0, CVT_BYTE, &cfg.fallOff, 0, 1}, {"game-zclip", 0, CVT_BYTE, &cfg.moveCheckZ, 0, 1}, {"game-corpse-sliding", 0, CVT_BYTE, &cfg.slidingCorpses, 0, 1}, // Game state {"game-fastmonsters", 0, CVT_BYTE, &cfg.fastMonsters, 0, 1}, // Gameplay {"game-corpse-time", CVF_NO_MAX, CVT_INT, &cfg.corpseTime, 0, 0}, // Misc {"msg-echo", 0, CVT_BYTE, &cfg.echoMsg, 0, 1}, {NULL} }; // Console commands ccmd_t gameCCmds[] = { {"spy", "", CCmdCycleSpy}, {"screenshot", "", CCmdScreenShot}, {"viewsize", "s", CCmdViewSize}, // $cheats {"cheat", "s", CCmdCheat}, {"god", NULL, CCmdCheatGod}, {"noclip", NULL, CCmdCheatNoClip}, {"warp", NULL, CCmdCheatWarp}, {"reveal", "i", CCmdCheatReveal}, {"give", NULL, CCmdCheatGive}, {"kill", "", CCmdCheatMassacre}, {"leavemap", "", CCmdCheatLeaveMap}, {"suicide", NULL, CCmdCheatSuicide}, {"where", "", CCmdCheatWhere}, {"doomfont", "", CCmdDoomFont}, {"conbg", "s", CCmdConBackground}, // $infine {"startinf", "s", CCmdStartInFine}, {"stopinf", "", CCmdStopInFine}, {"stopfinale", "", CCmdStopInFine}, {"spawnmobj", NULL, CCmdSpawnMobj}, {"coord", "", CCmdPrintPlayerCoords}, // $democam {"makelocp", "i", CCmdMakeLocal}, {"makecam", "i", CCmdSetCamera}, {"setlock", NULL, CCmdSetViewLock}, {"lockmode", "i", CCmdSetViewLock}, {"viewmode", NULL, CCmdSetViewMode}, {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Add the console variables and commands. */ void G_ConsoleRegistration(void) { uint i; for(i = 0; gameCVars[i].name; ++i) Con_AddVariable(&gameCVars[i]); for(i = 0; gameCCmds[i].name; ++i) Con_AddCommand(&gameCCmds[i]); } /** * Settings for console background drawing. * Called EVERY FRAME by the console drawer. */ void D_ConsoleBg(int *width, int *height) { if(consoleBG) { DGL_SetMaterial(consoleBG); *width = (int) (64 * consoleZoom); *height = (int) (64 * consoleZoom); } else { DGL_SetNoMaterial(); *width = *height = 0; } } /** * Called when the player-eyeheight cvar is changed. */ void G_UpdateEyeHeight(cvar_t* unused) { player_t* plr = &players[CONSOLEPLAYER]; if(!(plr->plr->flags & DDPF_CAMERA)) plr->viewHeight = (float) cfg.plrViewHeight; } /** * Draw (char *) text in the game's font. * Called by the console drawer. */ int ConTextOut(const char *text, int x, int y) { M_WriteText3(x, y, text, GF_FONTA, -1, -1, -1, -1, false, false, 0); return 0; } /** * Get the visual width of (char*) text in the game's font. */ int ConTextWidth(const char *text) { return M_StringWidth(text, GF_FONTA); } /** * Console command to take a screenshot (duh). */ DEFCC(CCmdScreenShot) { G_ScreenShot(); return true; } /** * Console command to change the size of the view window. */ DEFCC(CCmdViewSize) { int min = 3, max = 13, *val = &cfg.screenBlocks; // Adjust/set the value. if(!stricmp(argv[1], "+")) (*val)++; else if(!stricmp(argv[1], "-")) (*val)--; else *val = strtol(argv[1], NULL, 0); // Clamp it. if(*val < min) *val = min; if(*val > max) *val = max; // Update the view size if necessary. R_SetViewSize(cfg.screenBlocks); return true; } /** * Configure the console to use the game's font. */ DEFCC(CCmdDoomFont) { ddfont_t cfont; cfont.flags = DDFONT_WHITE; cfont.height = 8; cfont.sizeX = 1.5f; cfont.sizeY = 2; cfont.drawText = ConTextOut; cfont.getWidth = ConTextWidth; cfont.filterText = NULL; Con_SetFont(&cfont); return true; } /** * Configure the console background. */ DEFCC(CCmdConBackground) { material_t* mat; if(!stricmp(argv[1], "off") || !stricmp(argv[1], "none")) { consoleBG = NULL; return true; } if((mat = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(argv[1], MN_ANY)))) consoleBG = mat; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_sound.c0000644000175000017500000000637111357170242022267 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sound.c: */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "dmu_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Start the song for the specified map. */ void S_MapMusic(uint episode, uint map) { ddmapinfo_t mapInfo; char mapId[8]; P_GetMapLumpName(episode, map, mapId); if(Def_Get(DD_DEF_MAP_INFO, mapId, &mapInfo)) { if(S_StartMusicNum(mapInfo.music, true)) { // Set the game status cvar for the map music. gsvMapMusic = mapInfo.music; } } } /** * Doom-like sector sounds: when a new sound starts, stop any old ones * from the same origin. * * @param sec Sector in which the sound should be played. * @param origin Origin of the sound (center/floor/ceiling). * @param id ID number of the sound to be played. */ void S_SectorSound(sector_t* sec, sectorsoundorigin_t origin, int id) { mobj_t* centerOrigin, *floorOrigin, *ceilingOrigin; centerOrigin = (mobj_t *) P_GetPtrp(sec, DMU_SOUND_ORIGIN); floorOrigin = (mobj_t *) P_GetPtrp(sec, DMU_FLOOR_SOUND_ORIGIN); ceilingOrigin = (mobj_t *) P_GetPtrp(sec, DMU_CEILING_SOUND_ORIGIN); S_StopSound(0, centerOrigin); S_StopSound(0, floorOrigin); S_StopSound(0, ceilingOrigin); switch(origin) { case SORG_FLOOR: S_StartSound(id, floorOrigin); break; case SORG_CEILING: S_StartSound(id, ceilingOrigin); break; case SORG_CENTER: default: S_StartSound(id, centerOrigin); break; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/d_api.c0000644000175000017500000001222111357170242021663 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_api.c: Doomsday API setup and interaction - jDoom specific */ // HEADER FILES ------------------------------------------------------------ #include #include "jdoom.h" #include "d_netsv.h" #include "d_net.h" #include "hu_menu.h" #include "xgclass.h" #include "g_update.h" #include "p_mapsetup.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The interface to the Doomsday engine. game_import_t gi; game_export_t gx; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Get a 32-bit integer value. */ int G_GetInteger(int id) { switch(id) { case DD_GAME_DMUAPI_VER: return DMUAPI_VER; default: break; } // ID not recognized, return NULL. return 0; } /** * Get a pointer to the value of a variable. Added for 64-bit support. */ void* G_GetVariable(int id) { static float bob[2]; switch(id) { case DD_GAME_NAME: return GAMENAMETEXT; case DD_GAME_NICENAME: return GAME_NICENAME; case DD_GAME_ID: return GAMENAMETEXT " " GAME_VERSION_TEXT; case DD_GAME_MODE: return gameModeString; case DD_GAME_CONFIG: return gameConfigString; case DD_VERSION_SHORT: return GAME_VERSION_TEXT; case DD_VERSION_LONG: return GAME_VERSION_TEXTLONG "\n" GAME_DETAILS; case DD_ACTION_LINK: return actionlinks; case DD_XGFUNC_LINK: return xgClasses; case DD_PSPRITE_BOB_X: R_GetWeaponBob(DISPLAYPLAYER, &bob[0], NULL); return &bob[0]; case DD_PSPRITE_BOB_Y: R_GetWeaponBob(DISPLAYPLAYER, NULL, &bob[1]); return &bob[1]; default: break; } // ID not recognized, return NULL. return 0; } /** * Takes a copy of the engine's entry points and exported data. Returns * a pointer to the structure that contains our entry points and exports. */ game_export_t *GetGameAPI(game_import_t *imports) { // Take a copy of the imports, but only copy as much data as is // allowed and legal. memset(&gi, 0, sizeof(gi)); memcpy(&gi, imports, MIN_OF(sizeof(game_import_t), imports->apiSize)); // Clear all of our exports. memset(&gx, 0, sizeof(gx)); // Fill in the data for the exports. gx.apiSize = sizeof(gx); gx.PreInit = G_PreInit; gx.PostInit = G_PostInit; gx.Shutdown = G_Shutdown; gx.Ticker = G_Ticker; gx.G_Drawer = D_Display; gx.G_Drawer2 = D_Display2; gx.PrivilegedResponder = (boolean (*)(event_t *)) G_PrivilegedResponder; gx.FallbackResponder = NULL; //Hu_MenuResponder; gx.G_Responder = G_Responder; gx.MobjThinker = P_MobjThinker; gx.MobjFriction = (float (*)(void *)) P_MobjGetFriction; gx.EndFrame = G_EndFrame; gx.ConsoleBackground = D_ConsoleBg; gx.UpdateState = G_UpdateState; #undef Get gx.GetInteger = G_GetInteger; gx.GetVariable = G_GetVariable; gx.NetServerStart = D_NetServerStarted; gx.NetServerStop = D_NetServerClose; gx.NetConnect = D_NetConnect; gx.NetDisconnect = D_NetDisconnect; gx.NetPlayerEvent = D_NetPlayerEvent; gx.NetWorldEvent = D_NetWorldEvent; gx.HandlePacket = D_HandlePacket; gx.NetWriteCommands = D_NetWriteCommands; gx.NetReadCommands = D_NetReadCommands; // Data structure sizes. gx.ticcmdSize = sizeof(ticcmd_t); gx.mobjSize = sizeof(mobj_t); gx.polyobjSize = sizeof(polyobj_t); gx.SetupForMapData = P_SetupForMapData; // These really need better names. Ideas? gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; return &gx; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_mobj.c0000644000175000017500000010263411357170242022065 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.c: Moving object handling. Spawn functions. */ #ifdef MSVC # pragma optimize("g", off) #endif // HEADER FILES ------------------------------------------------------------ #include #include "jdoom.h" #include "hu_stuff.h" #include "g_common.h" #include "p_map.h" #include "p_terraintype.h" #include "p_player.h" #include "p_tick.h" #include "dmu_lib.h" // MACROS ------------------------------------------------------------------ #define VANISHTICS (2*TICSPERSEC) #define MAX_BOB_OFFSET (8) #define NOMOMENTUM_THRESHOLD (0.000001f) #define WALKSTOP_THRESHOLD (0.062484741f) // FIX2FLT(0x1000-1) #define DROPOFFMOMENTUM_THRESHOLD (1.0f / 4) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- const terraintype_t* P_MobjGetFloorTerrainType(mobj_t* mo) { sector_t* sec = P_GetPtrp(mo->subsector, DMU_SECTOR); return P_GetPlaneMaterialType(sec, PLN_FLOOR); } /** * @return @c true, if the mobj is still present. */ boolean P_MobjChangeState(mobj_t* mobj, statenum_t state) { state_t* st; do { if(state == S_NULL) { mobj->state = (state_t *) S_NULL; P_MobjRemove(mobj, false); return false; } P_MobjSetState(mobj, state); st = &STATES[state]; mobj->turnTime = false; // $visangle-facetarget // Modified handling. // Call action functions when the state is set. if(st->action) st->action(mobj); state = st->nextState; } while(!mobj->tics); return true; } void P_ExplodeMissile(mobj_t *mo) { if(IS_CLIENT) { // Clients won't explode missiles. P_MobjChangeState(mo, S_NULL); return; } mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); mo->tics -= P_Random() & 3; if(mo->tics < 1) mo->tics = 1; if(mo->flags & MF_MISSILE) { mo->flags &= ~MF_MISSILE; mo->flags |= MF_VIEWALIGN; // Remove the brightshadow flag. if(mo->flags & MF_BRIGHTSHADOW) mo->flags &= ~MF_BRIGHTSHADOW; if(mo->flags & MF_BRIGHTEXPLODE) mo->flags |= MF_BRIGHTSHADOW; } if(mo->info->deathSound) S_StartSound(mo->info->deathSound, mo); } void P_FloorBounceMissile(mobj_t *mo) { mo->mom[MZ] = -mo->mom[MZ]; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); } /** * @return The ground friction factor for the mobj. */ float P_MobjGetFriction(mobj_t *mo) { if((mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && !mo->onMobj) { return FRICTION_FLY; } return XS_Friction(P_GetPtrp(mo->subsector, DMU_SECTOR)); } static boolean isInWalkState(player_t* pl) { return pl->plr->mo->state - STATES - PCLASS_INFO(pl->class)->runState < 4; } static float getFriction(mobj_t* mo) { if((mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && !mo->onMobj) { // Airborne friction. return FRICTION_FLY; } #if __JHERETIC__ if(P_ToXSector(P_GetPtrp(mo->subsector, DMU_SECTOR))->special == 15) { // Friction_Low return FRICTION_LOW; } #endif return P_MobjGetFriction(mo); } void P_MobjMoveXY(mobj_t *mo) { float pos[3], mom[3]; player_t *player; boolean largeNegative; // $democam: cameramen have their own movement code. if(P_CameraXYMovement(mo)) return; if(INRANGE_OF(mo->mom[MX], 0, NOMOMENTUM_THRESHOLD) && INRANGE_OF(mo->mom[MY], 0, NOMOMENTUM_THRESHOLD)) { if(mo->flags & MF_SKULLFLY) { // The skull slammed into something. mo->flags &= ~MF_SKULLFLY; mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN)); } return; } mom[MX] = MINMAX_OF(-MAXMOVE, mo->mom[MX], MAXMOVE); mom[MY] = MINMAX_OF(-MAXMOVE, mo->mom[MY], MAXMOVE); mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; player = mo->player; do { /** * DOOM.exe bug fix: * Large negative displacements were never considered. This explains * the tendency for Mancubus fireballs to pass through walls. */ largeNegative = false; if(!cfg.moveBlock && (mom[MX] < -MAXMOVE / 2 || mom[MY] < -MAXMOVE / 2)) { // Make an exception for "north-only wallrunning". if(!(cfg.wallRunNorthOnly && mo->wallRun)) largeNegative = true; } if(largeNegative || mom[MX] > MAXMOVE / 2 || mom[MY] > MAXMOVE / 2) { pos[VX] = mo->pos[VX] + mom[MX] / 2; pos[VY] = mo->pos[VY] + mom[MY] / 2; mom[MX] /= 2; mom[MY] /= 2; } else { pos[VX] = mo->pos[VX] + mom[MX]; pos[VY] = mo->pos[VY] + mom[MY]; mom[MX] = mom[MY] = 0; } // If mobj was wallrunning - stop. if(mo->wallRun) mo->wallRun = false; // $dropoff_fix. if(!P_TryMove(mo, pos[VX], pos[VY], true, false)) { // Blocked move. if(mo->flags2 & MF2_SLIDE) { // Try to slide along it. P_SlideMove(mo); } else if(mo->flags & MF_MISSILE) { sector_t* backSec; //// kludge: Prevent missiles exploding against the sky. if(ceilingLine && (backSec = P_GetPtrp(ceilingLine, DMU_BACK_SECTOR))) { material_t* mat = P_GetPtrp(backSec, DMU_CEILING_MATERIAL); if((P_GetIntp(mat, DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] > P_GetFloatp(backSec, DMU_CEILING_HEIGHT)) { P_MobjRemove(mo, false); return; } } if(floorLine && (backSec = P_GetPtrp(floorLine, DMU_BACK_SECTOR))) { material_t* mat = P_GetPtrp(backSec, DMU_FLOOR_MATERIAL); if((P_GetIntp(mat, DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] < P_GetFloatp(backSec, DMU_FLOOR_HEIGHT)) { P_MobjRemove(mo, false); return; } } //// kludge end. P_ExplodeMissile(mo); } else { mo->mom[MX] = mo->mom[MY] = 0; } } } while(!INRANGE_OF(mom[MX], 0, NOMOMENTUM_THRESHOLD) || !INRANGE_OF(mom[MY], 0, NOMOMENTUM_THRESHOLD)); // Slow down. if(player && (P_GetPlayerCheats(player) & CF_NOMOMENTUM)) { // Debug option for no sliding at all. mo->mom[MX] = mo->mom[MY] = 0; return; } if(mo->flags & (MF_MISSILE | MF_SKULLFLY)) return; // No friction for missiles ever. if(mo->pos[VZ] > mo->floorZ && !mo->onMobj && !(mo->flags2 & MF2_FLY)) return; // No friction when falling. if(cfg.slidingCorpses) { // $dropoff_fix: Add objects falling off ledges, does not apply to // players! if(((mo->flags & MF_CORPSE) || (mo->intFlags & MIF_FALLING)) && !mo->player) { // Do not stop sliding if halfway off a step with some momentum. if(!INRANGE_OF(mo->mom[MX], 0, DROPOFFMOMENTUM_THRESHOLD) || !INRANGE_OF(mo->mom[MY], 0, DROPOFFMOMENTUM_THRESHOLD)) { if(mo->floorZ != P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) return; } } } // Stop player walking animation. if((!player || (!(player->plr->cmd.forwardMove | player->plr->cmd.sideMove) && player->plr->mo != mo /* $voodoodolls: Stop animating. */)) && INRANGE_OF(mo->mom[MX], 0, WALKSTOP_THRESHOLD) && INRANGE_OF(mo->mom[MY], 0, WALKSTOP_THRESHOLD)) { // If in a walking frame, stop moving. if(player && isInWalkState(player) && player->plr->mo == mo) P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->normalState); // $voodoodolls: Do not zero mom! if(!(player && player->plr->mo != mo)) mo->mom[MX] = mo->mom[MY] = 0; // $voodoodolls: Stop view bobbing if this isn't a voodoo doll. if(player && player->plr->mo == mo) player->bob = 0; } else { float friction = getFriction(mo); mo->mom[MX] *= friction; mo->mom[MY] *= friction; } } /* static boolean PIT_Splash(sector_t *sector, void *data) { mobj_t *mo = data; float floorHeight; floorHeight = P_GetFloatp(sector, DMU_FLOOR_HEIGHT); // Is the mobj touching the floor of this sector? if(mo->pos[VZ] < floorHeight && mo->pos[VZ] + mo->height / 2 > floorHeight) { //// \todo Play a sound, spawn a generator, etc. } // Continue checking. return true; } */ void P_HitFloor(mobj_t* mo) { //P_MobjSectorsIterator(mo, PIT_Splash, mo); } void P_MobjMoveZ(mobj_t* mo) { float gravity, targetZ, floorZ, ceilingZ; // $democam: cameramen get special z movement. if(P_CameraZMovement(mo)) return; targetZ = mo->pos[VZ] + mo->mom[MZ]; floorZ = (mo->onMobj? mo->onMobj->pos[VZ] + mo->onMobj->height : mo->floorZ); ceilingZ = mo->ceilingZ; gravity = XS_Gravity(P_GetPtrp(mo->subsector, DMU_SECTOR)); if((mo->flags2 & MF2_FLY) && mo->player && mo->onMobj && mo->pos[VZ] > mo->onMobj->pos[VZ] + mo->onMobj->height) mo->onMobj = NULL; // We were on a mobj, we are NOT now. if(!((mo->flags ^ MF_FLOAT) & (MF_FLOAT | MF_SKULLFLY | MF_INFLOAT)) && mo->target && !P_MobjIsCamera(mo->target)) { float dist, delta; // Float down towards target if too close. dist = P_ApproxDistance(mo->pos[VX] - mo->target->pos[VX], mo->pos[VY] - mo->target->pos[VY]); delta = (mo->target->pos[VZ] + mo->target->height / 2) - (mo->pos[VZ] + mo->height / 2); // Don't go INTO the target. if(!(dist < mo->radius + mo->target->radius && fabs(delta) < mo->height + mo->target->height)) { if(delta < 0 && dist < -(delta * 3)) { targetZ -= FLOATSPEED; P_MobjSetSRVOZ(mo, -FLOATSPEED); } else if(delta > 0 && dist < (delta * 3)) { targetZ += FLOATSPEED; P_MobjSetSRVOZ(mo, FLOATSPEED); } } } // Do some fly-bobbing. if(mo->player && (mo->flags2 & MF2_FLY) && mo->pos[VZ] > floorZ && (mapTime & 2)) { targetZ += FIX2FLT(finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]); } if(targetZ < floorZ) { // Hit the floor (or another mobj). boolean movingDown; // Note (id): // somebody left this after the setting momz to 0, // kinda useless there. // // cph - This was the a bug in the linuxdoom-1.10 source which // caused it not to sync Doom 2 v1.9 demos. Someone // added the above comment and moved up the following code. So // demos would desync in close lost soul fights. // Note that this only applies to original Doom 1 or Doom2 demos - not // Final Doom and Ultimate Doom. So we test demo_compatibility *and* // gameMission. (Note we assume that Doom1 is always Ult Doom, which // seems to hold for most published demos.) // // fraggle - cph got the logic here slightly wrong. There are three // versions of Doom 1.9: // // * The version used in registered doom 1.9 + doom2 - no bounce // * The version used in ultimate doom - has bounce // * The version used in final doom - has bounce // // So we need to check that this is either retail or commercial // (but not doom2) int correctLostSoulBounce = (gameMode == retail || gameMode == commercial) && gameMission != GM_DOOM2; if(correctLostSoulBounce && (mo->flags & MF_SKULLFLY)) { // The skull slammed into something. mo->mom[MZ] = -mo->mom[MZ]; } if(movingDown = (mo->mom[MZ] < 0)) { if(mo->player && mo->player->plr->mo == mo && mo->mom[MZ] < -gravity * 8 && !(mo->flags2 & MF2_FLY)) { // Squat down. // Decrease viewheight for a moment after hitting the ground // (hard), and utter appropriate sound. mo->player->viewHeightDelta = mo->mom[MZ] / 8; mo->player->jumpTics = 10; /** * DOOM bug: * Dead players would grunt when hitting the ground (e.g., * after an archvile attack). */ if(mo->player->health > 0) S_StartSound(SFX_OOF, mo); } } targetZ = floorZ; if(movingDown && !mo->onMobj) P_HitFloor(mo); /** * See lost soul bouncing comment above. We need this here for bug * compatibility with original Doom2 v1.9 - if a soul is charging * and hit by a raising floor this would incorrectly reverse it's * Y momentum. */ if(!correctLostSoulBounce && (mo->flags & MF_SKULLFLY)) mo->mom[MZ] = -mo->mom[MZ]; if(!((mo->flags ^ MF_MISSILE) & (MF_MISSILE | MF_NOCLIP))) { mo->pos[VZ] = targetZ; if((mo->flags2 & MF2_FLOORBOUNCE) && !mo->onMobj) { P_FloorBounceMissile(mo); return; } else { P_ExplodeMissile(mo); return; } } if(movingDown && mo->mom[MZ] < 0) mo->mom[MZ] = 0; // $voodoodolls: Check for smooth step up unless a voodoo doll. if(mo->player && mo->player->plr->mo == mo && mo->pos[VZ] < mo->floorZ) { mo->player->viewHeight -= (mo->floorZ - mo->pos[VZ]); mo->player->viewHeightDelta = (cfg.plrViewHeight - mo->player->viewHeight) / 8; } mo->pos[VZ] = floorZ; if(mo->flags & MF_SKULLFLY) { // The skull slammed into something. mo->mom[MZ] = -mo->mom[MZ]; } if(!((mo->flags ^ MF_MISSILE) & (MF_MISSILE | MF_NOCLIP))) { material_t* mat = P_GetPtrp(mo->subsector, DMU_FLOOR_MATERIAL); // Don't explode against sky. if(P_GetIntp(mat, DMU_FLAGS) & MATF_SKYMASK) { P_MobjRemove(mo, false); } else { P_ExplodeMissile(mo); } } } else { if(targetZ + mo->height > ceilingZ) { // Hit the ceiling. if(mo->mom[MZ] > 0) mo->mom[MZ] = 0; mo->pos[VZ] = mo->ceilingZ - mo->height; if(mo->flags & MF_SKULLFLY) { // The skull slammed into something. mo->mom[MZ] = -mo->mom[MZ]; } if(!((mo->flags ^ MF_MISSILE) & (MF_MISSILE | MF_NOCLIP))) { material_t* mat = P_GetPtrp(mo->subsector, DMU_CEILING_MATERIAL); // Don't explode against sky. if(P_GetIntp(mat, DMU_FLAGS) & MATF_SKYMASK) { P_MobjRemove(mo, false); } else { P_ExplodeMissile(mo); } } } else { // In "free space". // Update gravity's effect on momentum. if(mo->flags2 & MF2_LOGRAV) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= (gravity / 8); } else if(!(mo->flags & MF_NOGRAVITY)) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; } mo->pos[VZ] = targetZ; } } } void P_NightmareRespawn(mobj_t* mobj) { mobj_t* mo; // Something is occupying it's position? if(!P_CheckPosition2f(mobj, mobj->spawnSpot.pos[VX], mobj->spawnSpot.pos[VY])) return; // No respwan. if((mo = P_SpawnMobj3fv(mobj->type, mobj->spawnSpot.pos, mobj->spawnSpot.angle, mobj->spawnSpot.flags))) { mo->reactionTime = 18; // Spawn a teleport fog at old spot. if((mo = P_SpawnMobj3f(MT_TFOG, mobj->pos[VX], mobj->pos[VY], 0, mobj->angle, MSF_Z_FLOOR))) S_StartSound(SFX_TELEPT, mo); // Spawn a teleport fog at the new spot. if((mo = P_SpawnMobj3fv(MT_TFOG, mobj->spawnSpot.pos, mobj->spawnSpot.angle, mobj->spawnSpot.flags))) S_StartSound(SFX_TELEPT, mo); } // Remove the old monster. P_MobjRemove(mobj, true); } void P_MobjThinker(mobj_t* mo) { float floorZ; if(!mo) return; // Wha? if(mo->ddFlags & DDMF_REMOTE) return; // Remote mobjs are handled separately. // Spectres get selector = 1. if(mo->type == MT_SHADOWS) mo->selector = (mo->selector & ~DDMOBJ_SELECTOR_MASK) | 1; // The first three bits of the selector special byte contain a // relative health level. P_UpdateHealthBits(mo); #if __JHERETIC__ // Lightsources must stay where they're hooked. if(mo->type == MT_LIGHTSOURCE) { if(mo->moveDir > 0) mo->pos[VZ] = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); else mo->pos[VZ] = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); mo->pos[VZ] += FIX2FLT(mo->moveDir); return; } #endif // Handle X and Y momentums. if(!INRANGE_OF(mo->mom[MX], 0, NOMOMENTUM_THRESHOLD) || !INRANGE_OF(mo->mom[MY], 0, NOMOMENTUM_THRESHOLD) || (mo->flags & MF_SKULLFLY)) { P_MobjMoveXY(mo); //// \fixme decent NOP/NULL/Nil function pointer please. if(mo->thinker.function == NOPFUNC) return; // Mobj was removed. } floorZ = (mo->onMobj? mo->onMobj->pos[VZ] + mo->onMobj->height : mo->floorZ); if(mo->flags2 & MF2_FLOATBOB) { // Floating item bobbing motion. // Keep it on the floor. mo->pos[VZ] = floorZ; #if __JHERETIC__ // Negative floorclip raises the mo off the floor. mo->floorClip = -mo->special1; #elif __JDOOM__ mo->floorClip = 0; #endif if(mo->floorClip < -MAX_BOB_OFFSET) { // We don't want it going through the floor. mo->floorClip = -MAX_BOB_OFFSET; } } else if(mo->pos[VZ] != floorZ || !INRANGE_OF(mo->mom[MZ], 0, NOMOMENTUM_THRESHOLD)) { P_MobjMoveZ(mo); //// \fixme decent NOP/NULL/Nil function pointer please. if(mo->thinker.function == NOPFUNC) return; // Mobj was removed. } // Non-sentient objects at rest. else if(!sentient(mo) && !mo->player && !(INRANGE_OF(mo->mom[MX], 0, NOMOMENTUM_THRESHOLD) && INRANGE_OF(mo->mom[MY], 0, NOMOMENTUM_THRESHOLD))) { // Objects fall off ledges if they are hanging off. Slightly push // off of ledge if hanging more than halfway off. if(mo->pos[VZ] > mo->dropOffZ && // Only objects contacting dropoff. !(mo->flags & MF_NOGRAVITY) && !(mo->flags2 & MF2_FLOATBOB) && cfg.fallOff) { P_ApplyTorque(mo); } else { mo->intFlags &= ~MIF_FALLING; mo->gear = 0; // Reset torque. } } if(cfg.slidingCorpses) { if(((mo->flags & MF_CORPSE)? mo->pos[VZ] > mo->dropOffZ : mo->pos[VZ] - mo->dropOffZ > 24) && // Only objects contacting drop off !(mo->flags & MF_NOGRAVITY)) // Only objects which fall. { P_ApplyTorque(mo); // Apply torque. } else { mo->intFlags &= ~MIF_FALLING; mo->gear = 0; // Reset torque. } } // $vanish: dead monsters disappear after some time. if(cfg.corpseTime && (mo->flags & MF_CORPSE) && mo->corpseTics != -1) { if(++mo->corpseTics < cfg.corpseTime * TICSPERSEC) { mo->translucency = 0; // Opaque. } else if(mo->corpseTics < cfg.corpseTime * TICSPERSEC + VANISHTICS) { // Translucent during vanishing. mo->translucency = ((mo->corpseTics - cfg.corpseTime * TICSPERSEC) * 255) / VANISHTICS; } else { // Too long; get rid of the corpse. mo->corpseTics = -1; return; } } // Cycle through states, calling action functions at transitions. if(mo->tics != -1) { mo->tics--; P_MobjAngleSRVOTicker(mo); // "angle-servo"; smooth actor turning. // You can cycle through multiple states in a tic. if(!mo->tics) { P_MobjClearSRVO(mo); P_MobjChangeState(mo, mo->state->nextState); } } else if(!IS_CLIENT) { // Check for nightmare respawn. if(!(mo->flags & MF_COUNTKILL)) return; if(!respawnMonsters) return; mo->moveCount++; if(mo->moveCount >= 12 * 35 && !(mapTime & 31) && P_Random() <= 4) { P_NightmareRespawn(mo); } } } /** * Spawns a mobj of "type" at the specified position. */ mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags) { mobj_t* mo; mobjinfo_t* info; float space; int ddflags = 0; info = &MOBJINFO[type]; // Clients only spawn local objects. if(!(info->flags & MF_LOCAL) && IS_CLIENT) return NULL; // Not for deathmatch? if(deathmatch && (info->flags & MF_NOTDMATCH)) return NULL; // Check for specific disabled objects. if(IS_NETGAME) { // Cooperative weapons? if(cfg.noCoopWeapons && !deathmatch && type >= MT_CLIP && type <= MT_SUPERSHOTGUN) return NULL; // Don't spawn any special objects in coop? if(cfg.noCoopAnything && !deathmatch) return NULL; // BFG disabled in netgames? if(cfg.noNetBFG && type == MT_MISC25) return NULL; } switch(type) { case MT_BABY: // 68, Arachnotron case MT_VILE: // 64, Archvile case MT_BOSSBRAIN: // 88, Boss Brain case MT_BOSSSPIT: // 89, Boss Shooter case MT_KNIGHT: // 69, Hell Knight case MT_FATSO: // 67, Mancubus case MT_PAIN: // 71, Pain Elemental case MT_MEGA: // 74, MegaSphere case MT_CHAINGUY: // 65, Former Human Commando case MT_UNDEAD: // 66, Revenant case MT_WOLFSS: // 84, Wolf SS if(gameMode != commercial) return NULL; break; default: break; } // Don't spawn any monsters if -noMonstersParm. if(noMonstersParm && ((info->flags & MF_COUNTKILL) || type == MT_SKULL)) return NULL; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; mo = P_MobjCreate(P_MobjThinker, x, y, z, angle, info->radius, info->height, ddflags); mo->type = type; mo->info = info; mo->flags = info->flags; mo->flags2 = info->flags2; mo->flags3 = info->flags3; mo->damage = info->damage; mo->health = info->spawnHealth * (IS_NETGAME ? cfg.netMobHealthModifier : 1); mo->moveDir = DI_NODIR; // Let the engine know about solid objects. P_SetDoomsdayFlags(mo); if(gameSkill != SM_NIGHTMARE) mo->reactionTime = info->reactionTime; mo->lastLook = P_Random() % MAXPLAYERS; // Do not set the state with P_MobjChangeState, because action routines // can not be called yet. // Must link before setting state (ID assigned for the mo). P_MobjSetState(mo, P_GetState(mo->type, SN_SPAWN)); P_MobjSetPosition(mo); mo->floorZ = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); mo->dropOffZ = mo->floorZ; mo->ceilingZ = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); if((spawnFlags & MSF_Z_CEIL) || (info->flags & MF_SPAWNCEILING)) { mo->pos[VZ] = mo->ceilingZ - mo->info->height - z; } else if((spawnFlags & MSF_Z_RANDOM) || (info->flags2 & MF2_SPAWNFLOAT)) { space = mo->ceilingZ - mo->info->height - mo->floorZ; if(space > 48) { space -= 40; mo->pos[VZ] = ((space * P_Random()) / 256) + mo->floorZ + 40; } else { mo->pos[VZ] = mo->floorZ; } } else if(spawnFlags & MSF_Z_FLOOR) { mo->pos[VZ] = mo->floorZ + z; } if(spawnFlags & MSF_DEAF) mo->flags |= MF_AMBUSH; mo->floorClip = 0; if((mo->flags2 & MF2_FLOORCLIP) && mo->pos[VZ] == P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } // Copy spawn attributes to the new mobj. mo->spawnSpot.pos[VX] = x; mo->spawnSpot.pos[VY] = y; mo->spawnSpot.pos[VZ] = z; mo->spawnSpot.angle = angle; mo->spawnSpot.flags = spawnFlags; return mo; } mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags) { return P_SpawnMobj3f(type, pos[VX], pos[VY], pos[VZ], angle, spawnFlags); } mobj_t* P_SpawnCustomPuff(mobjtype_t type, float x, float y, float z, angle_t angle) { mobj_t* mo; // Clients do not spawn puffs. if(IS_CLIENT) return NULL; z += FIX2FLT((P_Random() - P_Random()) << 10); if((mo = P_SpawnMobj3f(type, x, y, z, angle, 0))) { mo->mom[MZ] = FIX2FLT(FRACUNIT); mo->tics -= P_Random() & 3; // Make it last at least one tic. if(mo->tics < 1) mo->tics = 1; } return mo; } void P_SpawnPuff(float x, float y, float z, angle_t angle) { mobj_t* th; if((th = P_SpawnCustomPuff(MT_PUFF, x, y, z, angle))) { // Don't make punches spark on the wall. if(th && attackRange == MELEERANGE) P_MobjChangeState(th, S_PUFF3); } } void P_SpawnBlood(float x, float y, float z, int damage, angle_t angle) { mobj_t* th; z += FIX2FLT((P_Random() - P_Random()) << 10); if((th = P_SpawnMobj3f(MT_BLOOD, x, y, z, angle, 0))) { th->mom[MZ] = 2; th->tics -= P_Random() & 3; if(th->tics < 1) th->tics = 1; if(damage <= 12 && damage >= 9) P_MobjChangeState(th, S_BLOOD2); else if(damage < 9) P_MobjChangeState(th, S_BLOOD3); } } /** * Moves the missile forward a bit and possibly explodes it right there. * * @param th The missile to be checked. * * @return @c true, if the missile is at a valid location else * @c false */ boolean P_CheckMissileSpawn(mobj_t *th) { th->tics -= P_Random() & 3; if(th->tics < 1) th->tics = 1; // Move forward slightly so an angle can be computed if it explodes // immediately. th->pos[VX] += th->mom[MX] / 2; th->pos[VY] += th->mom[MY] / 2; th->pos[VZ] += th->mom[MZ] / 2; if(!P_TryMove(th, th->pos[VX], th->pos[VY], false, false)) { P_ExplodeMissile(th); return false; } return true; } /** * Tries to aim at a nearby monster if source is a player. Else aim is * taken at dest. * * @param source The mobj doing the shooting. * @param dest The mobj being shot at. Can be @c NULL if source * is a player. * @param type The type of mobj to be shot. * * @return Pointer to the newly spawned missile. */ mobj_t* P_SpawnMissile(mobjtype_t type, mobj_t* source, mobj_t* dest) { float pos[3]; mobj_t* th = 0; unsigned int an; angle_t angle = 0; float dist = 0; float slope = 0; float spawnZOff = 0; memcpy(pos, source->pos, sizeof(pos)); if(source->player) { // See which target is to be aimed at. angle = source->angle; slope = P_AimLineAttack(source, angle, 16 * 64); if(!cfg.noAutoAim) if(!lineTarget) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget) { angle = source->angle; slope = tan(LOOKDIR2RAD(source->dPlayer->lookDir)) / 1.2f; } } if(!P_MobjIsCamera(source->player->plr->mo)) spawnZOff = cfg.plrViewHeight - 9 + source->player->plr->lookDir / 173; } else { // Type specific offset to spawn height z. switch(type) { case MT_TRACER: // Revenant Tracer Missile. spawnZOff = 16 + 32; break; default: spawnZOff = 32; break; } } pos[VZ] += spawnZOff; pos[VZ] -= source->floorClip; if(!source->player) { angle = R_PointToAngle2(pos[VX], pos[VY], dest->pos[VX], dest->pos[VY]); // Fuzzy player. if(dest->flags & MF_SHADOW) angle += (P_Random() - P_Random()) << 20; } if(!(th = P_SpawnMobj3fv(type, pos, angle, 0))) return NULL; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Where it came from. an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); if(source->player) { // Allow free-aim with the BFG in deathmatch? if(deathmatch && cfg.netBFGFreeLook == 0 && type == MT_BFG) th->mom[MZ] = 0; else th->mom[MZ] = th->info->speed * slope; } else { dist = P_ApproxDistance(dest->pos[VX] - pos[VX], dest->pos[VY] - pos[VY]); dist /= th->info->speed; if(dist < 1) dist = 1; th->mom[MZ] = (dest->pos[VZ] - source->pos[VZ]) / dist; } // Make sure the speed is right (in 3D). dist = P_ApproxDistance(P_ApproxDistance(th->mom[MX], th->mom[MY]), th->mom[MZ]); if(dist < 1) dist = 1; dist = th->info->speed / dist; th->mom[MX] *= dist; th->mom[MY] *= dist; th->mom[MZ] *= dist; if(P_CheckMissileSpawn(th)) return th; return NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/st_stuff.c0000644000175000017500000013116211357170242022452 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.c: Status bar code - jDoom specific. * * Does the face/direction indicator animation and the palette indicators as * well (red pain/berserk, bright pickup) */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "jdoom.h" #include "d_net.h" #include "st_lib.h" #include "hu_stuff.h" #include "p_tick.h" // for P_IsPaused #include "p_player.h" #include "am_map.h" #include "p_user.h" // MACROS ------------------------------------------------------------------ // Radiation suit, green shift. #define RADIATIONPAL (13) // N/256*100% probability // that the normal face state will change #define ST_FACEPROBABILITY (96) // Location of status bar #define ST_X (0) #define ST_X2 (104) #define ST_FX (144) #define ST_FY (169) // Number of status faces. #define ST_NUMPAINFACES (5) #define ST_NUMSTRAIGHTFACES (3) #define ST_NUMTURNFACES (2) #define ST_NUMSPECIALFACES (3) #define ST_FACESTRIDE \ (ST_NUMSTRAIGHTFACES+ST_NUMTURNFACES+ST_NUMSPECIALFACES) #define ST_NUMEXTRAFACES (2) #define ST_NUMFACES \ (ST_FACESTRIDE*ST_NUMPAINFACES+ST_NUMEXTRAFACES) #define ST_TURNOFFSET (ST_NUMSTRAIGHTFACES) #define ST_OUCHOFFSET (ST_TURNOFFSET + ST_NUMTURNFACES) #define ST_EVILGRINOFFSET (ST_OUCHOFFSET + 1) #define ST_RAMPAGEOFFSET (ST_EVILGRINOFFSET + 1) #define ST_GODFACE (ST_NUMPAINFACES*ST_FACESTRIDE) #define ST_DEADFACE (ST_GODFACE+1) #define ST_FACESX (143) #define ST_FACESY (168) #define ST_EVILGRINCOUNT (2*TICRATE) #define ST_STRAIGHTFACECOUNT (TICRATE/2) #define ST_TURNCOUNT (1*TICRATE) #define ST_OUCHCOUNT (1*TICRATE) #define ST_RAMPAGEDELAY (2*TICRATE) #define ST_MUCHPAIN (20) // AMMO number pos. #define ST_CURRENTAMMOWIDTH (3) #define ST_CURRENTAMMOX (44) #define ST_CURRENTAMMOY (171) // HEALTH number pos. #define ST_HEALTHWIDTH (3) #define ST_HEALTHX (90) #define ST_HEALTHY (171) // Weapon pos. #define ST_ARMSX (111) #define ST_ARMSY (172) #define ST_ARMSBGX (104) #define ST_ARMSBGY (168) #define ST_ARMSXSPACE (12) #define ST_ARMSYSPACE (10) // Frags pos. #define ST_FRAGSX (138) #define ST_FRAGSY (171) #define ST_FRAGSWIDTH (2) // ARMOR number pos. #define ST_ARMORWIDTH (3) #define ST_ARMORX (221) #define ST_ARMORY (171) // Key icon positions. #define ST_KEY0WIDTH (8) #define ST_KEY0HEIGHT (5) #define ST_KEY0X (239) #define ST_KEY0Y (171) #define ST_KEY1WIDTH (ST_KEY0WIDTH) #define ST_KEY1X (239) #define ST_KEY1Y (181) #define ST_KEY2WIDTH (ST_KEY0WIDTH) #define ST_KEY2X (239) #define ST_KEY2Y (191) // Ready Ammunition counter. #define ST_READYAMMOWIDTH (3) #define ST_READYAMMOX (44) #define ST_READYAMMOY (171) // Ammo counters. #define ST_AMMOWIDTH (3) #define ST_AMMOHEIGHT (6) #define ST_AMMOX (288) #define ST_AMMOY (173) #define ST_MAXAMMOWIDTH (3) #define ST_MAXAMMOHEIGHT (6) #define ST_MAXAMMOX (314) #define ST_MAXAMMOY (173) // Pistol. #define ST_WEAPON0X (110) #define ST_WEAPON0Y (172) // Shotgun. #define ST_WEAPON1X (122) #define ST_WEAPON1Y (172) // Chain gun. #define ST_WEAPON2X (134) #define ST_WEAPON2Y (172) // Missile launcher. #define ST_WEAPON3X (110) #define ST_WEAPON3Y (181) // Plasma gun. #define ST_WEAPON4X (122) #define ST_WEAPON4Y (181) // BFG. #define ST_WEAPON5X (134) #define ST_WEAPON5Y (181) // WPNS title. #define ST_WPNSX (109) #define ST_WPNSY (191) // DETH title. #define ST_DETHX (109) #define ST_DETHY (191) // TYPES ------------------------------------------------------------------- typedef enum hotloc_e { HOT_TLEFT, HOT_TRIGHT, HOT_BRIGHT, HOT_BLEFT } hotloc_t; typedef struct { boolean stopped; int hideTics; float hideAmount; float alpha; // Fullscreen hud alpha value. float showBar; // Slide statusbar amount 1.0 is fully open. float statusbarCounterAlpha; boolean firstTime; // ST_Start() has just been called. boolean blended; // Whether to use alpha blending. boolean statusbarActive; // Whether the main status bar is active. int currentFragsCount; // Number of frags so far in deathmatch. int keyBoxes[3]; // Holds key-type for each key box on bar. // For status face: int oldHealth; // Used to use appopriately pained face. boolean oldWeaponsOwned[NUM_WEAPON_TYPES]; // Used for evil grin. int faceCount; // Count until face changes. int faceIndex; // Current face index, used by wFaces. int lastAttackDown; int priority; // Widgets: st_number_t wReadyWeapon; // Ready-weapon widget. st_number_t wFrags; // In deathmatch only, summary of frags stats. st_percent_t wHealth; // Health widget. st_multiicon_t wArms[6]; // Weapon ownership widgets. st_multiicon_t wFaces; // Face status widget. st_multiicon_t wKeyBoxes[3]; // Keycard widgets. st_percent_t wArmor; // Armor widget. st_number_t wAmmo[NUM_AMMO_TYPES]; // Ammo widgets. st_number_t wMaxAmmo[NUM_AMMO_TYPES]; // Max ammo widgets. } hudstate_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdStatusBarSize); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static hudstate_t hudStates[MAXPLAYERS]; // Main bar left. static dpatch_t statusbar; // 0-9, tall numbers. static dpatch_t tallNum[10]; // Tall % sign. static dpatch_t tallPercent; // 0-9, short, yellow (,different!) numbers. static dpatch_t shortNum[10]; // 3 key-cards, 3 skulls. static dpatch_t keys[NUM_KEY_TYPES]; // Face status patches. static dpatch_t faces[ST_NUMFACES]; // Face background. static dpatch_t faceBackground[4]; // Main bar right. static dpatch_t armsBackground; // Weapon ownership patches. static dpatch_t arms[6][2]; // CVARs for the HUD/Statusbar: cvar_t sthudCVars[] = { // HUD scale {"hud-scale", 0, CVT_FLOAT, &cfg.hudScale, 0.1f, 10}, {"hud-status-size", CVF_PROTECTED, CVT_INT, &cfg.statusbarScale, 1, 20}, // HUD colour + alpha {"hud-color-r", 0, CVT_FLOAT, &cfg.hudColor[0], 0, 1}, {"hud-color-g", 0, CVT_FLOAT, &cfg.hudColor[1], 0, 1}, {"hud-color-b", 0, CVT_FLOAT, &cfg.hudColor[2], 0, 1}, {"hud-color-a", 0, CVT_FLOAT, &cfg.hudColor[3], 0, 1}, {"hud-icon-alpha", 0, CVT_FLOAT, &cfg.hudIconAlpha, 0, 1}, {"hud-face-ouchfix", 0, CVT_BYTE, &cfg.fixOuchFace, 0, 1}, {"hud-status-alpha", 0, CVT_FLOAT, &cfg.statusbarOpacity, 0, 1}, {"hud-status-icon-a", 0, CVT_FLOAT, &cfg.statusbarCounterAlpha, 0, 1}, {"hud-status-weaponslots-ownedfix", 0, CVT_BYTE, &cfg.fixStatusbarOwnedWeapons, 0, 1}, // HUD icons {"hud-face", 0, CVT_BYTE, &cfg.hudShown[HUD_FACE], 0, 1}, {"hud-health", 0, CVT_BYTE, &cfg.hudShown[HUD_HEALTH], 0, 1}, {"hud-armor", 0, CVT_BYTE, &cfg.hudShown[HUD_ARMOR], 0, 1}, {"hud-ammo", 0, CVT_BYTE, &cfg.hudShown[HUD_AMMO], 0, 1}, {"hud-keys", 0, CVT_BYTE, &cfg.hudShown[HUD_KEYS], 0, 1}, {"hud-keys-combine", 0, CVT_BYTE, &cfg.hudKeysCombine, 0, 1}, // HUD displays {"hud-frags", 0, CVT_BYTE, &cfg.hudShown[HUD_FRAGS], 0, 1}, {"hud-timer", 0, CVT_FLOAT, &cfg.hudTimer, 0, 60}, {"hud-unhide-damage", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_DAMAGE], 0, 1}, {"hud-unhide-pickup-health", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_HEALTH], 0, 1}, {"hud-unhide-pickup-armor", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_ARMOR], 0, 1}, {"hud-unhide-pickup-powerup", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_POWER], 0, 1}, {"hud-unhide-pickup-weapon", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_WEAPON], 0, 1}, {"hud-unhide-pickup-ammo", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_AMMO], 0, 1}, {"hud-unhide-pickup-key", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_KEY], 0, 1}, {NULL} }; // Console commands for the HUD/Status bar: ccmd_t sthudCCmds[] = { {"sbsize", "s", CCmdStatusBarSize}, {NULL} }; // CODE -------------------------------------------------------------------- /** * Register CVARs and CCmds for the HUD/Status bar */ void ST_Register(void) { int i; for(i = 0; sthudCVars[i].name; ++i) Con_AddVariable(sthudCVars + i); for(i = 0; sthudCCmds[i].name; ++i) Con_AddCommand(sthudCCmds + i); } static void drawStatusBarBackground(int player, float width, float height) { float x, y, w, h; float cw, cw2, ch; float alpha; hudstate_t* hud = &hudStates[player]; float armsBGX = ST_ARMSBGX - armsBackground.leftOffset; DGL_SetPatch(statusbar.lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); if(hud->blended) { alpha = cfg.statusbarOpacity - hud->hideAmount; if(!(alpha > 0)) return; alpha = MINMAX_OF(0.f, alpha, 1.f); } else alpha = 1.0f; DGL_Color4f(1, 1, 1, alpha); if(!(alpha < 1)) { // We can draw the full graphic in one go. DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(0, 0); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(width, 0); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(width, height); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(0, height); DGL_End(); } else { // Alpha blended status bar, we'll need to cut it up into smaller bits... DGL_Begin(DGL_QUADS); // Up to faceback if deathmatch, else ST_ARMS. x = 0; y = 0; w = width * (float) ((hud->statusbarActive && !deathmatch) ? armsBGX : ST_FX) / ST_WIDTH; h = height * (float) ST_HEIGHT / ST_HEIGHT; cw = w / width; DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(x, y + h); if(IS_NETGAME) { // Fill in any gap left before the faceback due to small ARMS. if(armsBGX + armsBackground.width < ST_FX) { x = width * (float) (armsBGX + armsBackground.width) / ST_WIDTH; y = 0; w = width * (float) (ST_FX - armsBGX - armsBackground.width) / ST_WIDTH; h = height * (float) (ST_HEIGHT) / ST_HEIGHT; cw = x / width; cw2 = (x + w) / width; ch = h / height; DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, cw2, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw2, ch); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x, y + h); } // Awkward, 2 pixel tall strip above faceback. x = width * (float) (ST_FX) / ST_WIDTH; y = 0; w = width * (float) (ST_WIDTH - ST_FX - 141 - 2) / ST_WIDTH; h = height * (float) (ST_HEIGHT - 30) / ST_HEIGHT; cw = x / width; cw2 = (x + w) / width; ch = h / height; DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, cw2, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw2, ch); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x, y + h); // Awkward, 1 pixel tall strip bellow faceback. x = width * (float) (ST_FX) / ST_WIDTH; y = height * (float) (ST_HEIGHT - 1) / ST_HEIGHT; w = width * (float) (ST_WIDTH - ST_FX - 141 - 2) / ST_WIDTH; h = height * (float) (ST_HEIGHT - 31) / ST_HEIGHT; cw = x / width; cw2 = (x + w) / width; ch = (ST_HEIGHT - 1) / height; DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, cw2, ch); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw2, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x, y + h); // After faceback. x = width * (float) (ST_FX + (ST_WIDTH - ST_FX - 141 - 2)) / ST_WIDTH; y = 0; w = width * (float) (ST_WIDTH - (ST_FX + (ST_WIDTH - ST_FX - 141 - 2))) / ST_WIDTH; h = height * (float) ST_HEIGHT / ST_HEIGHT; cw = x / width; } else { // Including area behind the face status indicator. x = width * (float) (armsBGX + armsBackground.width) / ST_WIDTH; y = 0; w = width * (float) (ST_WIDTH - armsBGX - armsBackground.width) / ST_WIDTH; h = height * (float) ST_HEIGHT / ST_HEIGHT; cw = x / width; } DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x, y + h); DGL_End(); } if(!deathmatch) { // Draw the ARMS background. DGL_SetPatch(armsBackground.lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); x = width * ((float) armsBGX - ST_X) / ST_WIDTH; y = height * ((float) armsBackground.topOffset) / ST_HEIGHT; w = width * ((float) armsBackground.width) / ST_WIDTH; h = height * ((float) armsBackground.height) / ST_HEIGHT; DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(x, y + h); DGL_End(); } if(IS_NETGAME) // Faceback. { int plrColor = cfg.playerColor[player]; dpatch_t* patch = &faceBackground[plrColor]; DGL_SetPatch(patch->lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); x = width * (float) (ST_FX - ST_X) / ST_WIDTH; y = height * (float) (ST_HEIGHT - 30) / ST_HEIGHT; w = width * (float) (ST_WIDTH - ST_FX - 141 - 2) / ST_WIDTH; h = height * (float) (ST_HEIGHT - 3) / ST_HEIGHT; cw = (float) (1) / patch->width; cw2 = (float) (patch->width - 1) / patch->width; ch = (float) (patch->height - 1) / patch->height; DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, cw2, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw2, ch); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x, y + h); DGL_End(); } } /** * Unhides the current HUD display if hidden. * * @param player The player whoose HUD to (maybe) unhide. * @param event The HUD Update Event type to check for triggering. */ void ST_HUDUnHide(int player, hueevent_t ev) { player_t* plr; if(ev < HUE_FORCE || ev > NUMHUDUNHIDEEVENTS) return; plr = &players[player]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) return; if(ev == HUE_FORCE || cfg.hudUnHide[ev]) { hudStates[player].hideTics = (cfg.hudTimer * TICSPERSEC); hudStates[player].hideAmount = 0; } } static int calcPainOffset(hudstate_t* hud) { player_t* plr = &players[hud - hudStates]; int health = (plr->health > 100 ? 100 : plr->health); return ST_FACESTRIDE * (((100 - health) * ST_NUMPAINFACES) / 101); } /** * This is a not-very-pretty routine which handles the face states * and their timing. the precedence of expressions is: * * dead > evil grin > turned head > straight ahead */ void ST_updateFaceWidget(int player) { int i; angle_t badGuyAngle; angle_t diffAng; boolean doEvilGrin; player_t* plr = &players[player]; hudstate_t* hud = &hudStates[player]; if(hud->priority < 10) { // Player is dead. if(!plr->health) { hud->priority = 9; hud->faceIndex = ST_DEADFACE; hud->faceCount = 1; } } if(hud->priority < 9) { if(plr->bonusCount) { // Picking up a bonus. doEvilGrin = false; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { if(hud->oldWeaponsOwned[i] != plr->weapons[i].owned) { doEvilGrin = true; hud->oldWeaponsOwned[i] = plr->weapons[i].owned; } } if(doEvilGrin) { // Evil grin if just picked up weapon. hud->priority = 8; hud->faceCount = ST_EVILGRINCOUNT; hud->faceIndex = calcPainOffset(hud) + ST_EVILGRINOFFSET; } } } if(hud->priority < 8) { if(plr->damageCount && plr->attacker && plr->attacker != plr->plr->mo) { // Being attacked. hud->priority = 7; // DOOM BUG // This test was inversed, thereby the OUCH face was NEVER used // in normal gameplay as it requires the player recieving damage // to end up with MORE health than he started with. // Also, priority was not changed which would have resulted in a // frame duration of only 1 tic. // if(plr->health - oldHealth > ST_MUCHPAIN) if((cfg.fixOuchFace? (hud->oldHealth - plr->health) : (plr->health - hud->oldHealth)) > ST_MUCHPAIN) { hud->faceCount = ST_TURNCOUNT; hud->faceIndex = calcPainOffset(hud) + ST_OUCHOFFSET; if(cfg.fixOuchFace) hud->priority = 8; // Added to fix 1 tic issue. } else { badGuyAngle = R_PointToAngle2(FLT2FIX(plr->plr->mo->pos[VX]), FLT2FIX(plr->plr->mo->pos[VY]), FLT2FIX(plr->attacker->pos[VX]), FLT2FIX(plr->attacker->pos[VY])); if(badGuyAngle > plr->plr->mo->angle) { // Whether right or left. diffAng = badGuyAngle - plr->plr->mo->angle; i = diffAng > ANG180; } else { // Whether left or right. diffAng = plr->plr->mo->angle - badGuyAngle; i = diffAng <= ANG180; } hud->faceCount = ST_TURNCOUNT; hud->faceIndex = calcPainOffset(hud); if(diffAng < ANG45) { // Head-on. hud->faceIndex += ST_RAMPAGEOFFSET; } else if(i) { // Turn face right. hud->faceIndex += ST_TURNOFFSET; } else { // Turn face left. hud->faceIndex += ST_TURNOFFSET + 1; } } } } if(hud->priority < 7) { // Getting hurt because of your own damn stupidity. if(plr->damageCount) { // DOOM BUG // This test was inversed, thereby the OUCH face was NEVER used // in normal gameplay as it requires the player recieving damage // to end up with MORE health than he started with. // if(plr->health - oldHealth > ST_MUCHPAIN) if((cfg.fixOuchFace? (hud->oldHealth - plr->health) : (plr->health - hud->oldHealth)) > ST_MUCHPAIN) { hud->priority = 7; hud->faceCount = ST_TURNCOUNT; hud->faceIndex = calcPainOffset(hud) + ST_OUCHOFFSET; } else { hud->priority = 6; hud->faceCount = ST_TURNCOUNT; hud->faceIndex = calcPainOffset(hud) + ST_RAMPAGEOFFSET; } } } if(hud->priority < 6) { // Rapid firing. if(plr->attackDown) { if(hud->lastAttackDown == -1) { hud->lastAttackDown = ST_RAMPAGEDELAY; } else if(!--hud->lastAttackDown) { hud->priority = 5; hud->faceIndex = calcPainOffset(hud) + ST_RAMPAGEOFFSET; hud->faceCount = 1; hud->lastAttackDown = 1; } } else { hud->lastAttackDown = -1; } } if(hud->priority < 5) { // Invulnerability. if((P_GetPlayerCheats(plr) & CF_GODMODE) || plr->powers[PT_INVULNERABILITY]) { hud->priority = 4; hud->faceIndex = ST_GODFACE; hud->faceCount = 1; } } // Look left or look right if the facecount has timed out. if(!hud->faceCount) { hud->faceIndex = calcPainOffset(hud) + (M_Random() % 3); hud->faceCount = ST_STRAIGHTFACECOUNT; hud->priority = 0; } hud->faceCount--; } void ST_updateWidgets(int player) { static int largeAmmo = 1994; // Means "n/a". int i; ammotype_t ammoType; boolean found; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; if(hud->blended) { hud->statusbarCounterAlpha = MINMAX_OF(0.f, cfg.statusbarCounterAlpha - hud->hideAmount, 1.f); } else hud->statusbarCounterAlpha = 1.0f; // Must redirect the pointer if the ready weapon has changed. found = false; for(ammoType=0; ammoType < NUM_AMMO_TYPES && !found; ++ammoType) { if(!weaponInfo[plr->readyWeapon][plr->class].mode[0].ammoType[ammoType]) continue; // Weapon does not use this type of ammo. //// \todo Only supports one type of ammo per weapon hud->wReadyWeapon.num = &plr->ammo[ammoType].owned; found = true; } if(!found) // Weapon takes no ammo at all. { hud->wReadyWeapon.num = &largeAmmo; } // Update keycard multiple widgets. for(i = 0; i < 3; ++i) { hud->keyBoxes[i] = plr->keys[i] ? i : -1; if(plr->keys[i + 3]) hud->keyBoxes[i] = i + 3; } // Refresh everything if this is him coming back to life. ST_updateFaceWidget(player); // Used by wFrags widget. hud->currentFragsCount = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; hud->currentFragsCount += plr->frags[i] * (i != player ? 1 : -1); } } void ST_Ticker(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; hudstate_t* hud = &hudStates[i]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) continue; if(!P_IsPaused()) { if(cfg.hudTimer == 0) { hud->hideTics = hud->hideAmount = 0; } else { if(hud->hideTics > 0) hud->hideTics--; if(hud->hideTics == 0 && cfg.hudTimer > 0 && hud->hideAmount < 1) hud->hideAmount += 0.1f; } ST_updateWidgets(i); hud->oldHealth = plr->health; } } } void ST_doPaletteStuff(int player) { int palette = 0, cnt, bzc; player_t* plr = &players[player]; cnt = plr->damageCount; if(plr->powers[PT_STRENGTH]) { // Slowly fade the berzerk out. bzc = 12 - (plr->powers[PT_STRENGTH] >> 6); if(bzc > cnt) cnt = bzc; } if(cnt) { palette = (cnt + 7) >> 3; if(palette >= NUMREDPALS) palette = NUMREDPALS - 1; palette += STARTREDPALS; } else if(plr->bonusCount) { palette = (plr->bonusCount + 7) >> 3; if(palette >= NUMBONUSPALS) palette = NUMBONUSPALS - 1; palette += STARTBONUSPALS; } else if(plr->powers[PT_IRONFEET] > 4 * 32 || plr->powers[PT_IRONFEET] & 8) { palette = RADIATIONPAL; } // $democam if(palette) { plr->plr->flags |= DDPF_VIEW_FILTER; R_GetFilterColor(plr->plr->filterColor, palette); } else plr->plr->flags &= ~DDPF_VIEW_FILTER; } typedef struct { hudstate_t* hud; int slot; float alpha; } drawownedweapondisply_params_t; int drawOwnedWeaponDisplay(weapontype_t type, void* context) { drawownedweapondisply_params_t* params = (drawownedweapondisply_params_t*) context; const player_t* plr = &players[params->hud - hudStates]; if(cfg.fixStatusbarOwnedWeapons) { if(!plr->weapons[type].owned) return 1; // Continue iteration. } STlib_DrawMultiIcon(¶ms->hud->wArms[params->slot], plr->weapons[type].owned ? 1 : 0, params->alpha); return 0; // Stop iteration. } static void drawWidgets(hudstate_t* hud) { int i; float alpha = hud->statusbarCounterAlpha; STlib_DrawNum(&hud->wReadyWeapon, alpha); for(i = 0; i < 4; ++i) { STlib_DrawNum(&hud->wAmmo[i], alpha); STlib_DrawNum(&hud->wMaxAmmo[i], alpha); } STlib_DrawPercent(&hud->wHealth, alpha); STlib_DrawPercent(&hud->wArmor, alpha); if(!deathmatch) { for(i = 0; i < 6; ++i) { int result; drawownedweapondisply_params_t params; params.hud = hud; params.slot = i; params.alpha = alpha; result = P_IterateWeaponsInSlot(i+1, true, drawOwnedWeaponDisplay, ¶ms); if(cfg.fixStatusbarOwnedWeapons && result) { // No weapon bound to slot is owned by player. STlib_DrawMultiIcon(&hud->wArms[i], 0, alpha); } } } else STlib_DrawNum(&hud->wFrags, alpha); STlib_DrawMultiIcon(&hud->wFaces, hud->faceIndex, alpha); for(i = 0; i < 3; ++i) { if(hud->keyBoxes[i] != -1) { STlib_DrawMultiIcon(&hud->wKeyBoxes[i], hud->keyBoxes[i], alpha); } } } void ST_doRefresh(int player) { hudstate_t* hud; boolean statusbarVisible; float fscale, h; if(player < 0 || player > MAXPLAYERS) return; hud = &hudStates[player]; statusbarVisible = (cfg.statusbarScale < 20 || (cfg.statusbarScale == 20 && hud->showBar < 1.0f)); hud->firstTime = false; fscale = cfg.statusbarScale / 20.0f; h = SCREENHEIGHT * (1 - fscale); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef((SCREENWIDTH/2) - SCREENWIDTH * fscale / 2, h / hud->showBar, 0); DGL_Scalef(fscale, fscale, 1); DGL_Translatef(ST_X, ST_Y, 0); // Draw background. drawStatusBarBackground(player, ST_WIDTH, ST_HEIGHT); DGL_Translatef(-ST_X, -ST_Y, 0); drawWidgets(hud); // Restore the normal modelview matrix. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } void ST_HUDSpriteSize(int sprite, int *w, int *h) { spriteinfo_t sprInfo; R_GetSpriteInfo(sprite, 0, &sprInfo); *w = sprInfo.width; *h = sprInfo.height; if(sprite == SPR_ROCK) { // Must scale it a bit. *w /= 1.5; *h /= 1.5; } } void ST_drawHUDSprite(int sprite, float x, float y, hotloc_t hotspot, float scale, float alpha, boolean flip) { int w, h, w2, h2; float s, t; spriteinfo_t sprInfo; if(!(alpha > 0)) return; alpha = MINMAX_OF(0.f, alpha, 1.f); R_GetSpriteInfo(sprite, 0, &sprInfo); w = sprInfo.width; h = sprInfo.height; w2 = M_CeilPow2(w); h2 = M_CeilPow2(h); switch(hotspot) { case HOT_BRIGHT: y -= h * scale; case HOT_TRIGHT: x -= w * scale; break; case HOT_BLEFT: y -= h * scale; break; } DGL_SetPSprite(sprInfo.material); // Let's calculate texture coordinates. // To remove a possible edge artifact, move the corner a bit up/left. s = (w - 0.4f) / w2; t = (h - 0.4f) / h2; DGL_Color4f(1, 1, 1, alpha); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, flip * s, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, !flip * s, 0); DGL_Vertex2f(x + w * scale, y); DGL_TexCoord2f(0, !flip * s, t); DGL_Vertex2f(x + w * scale, y + h * scale); DGL_TexCoord2f(0, flip * s, t); DGL_Vertex2f(x, y + h * scale); DGL_End(); } void ST_doFullscreenStuff(int player) { static const int ammoSprite[NUM_AMMO_TYPES] = { SPR_AMMO, SPR_SBOX, SPR_CELL, SPR_ROCK }; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; char buf[20]; int w, h, pos = 0, spr, i; int width = 320 / cfg.hudScale; int height = 200 / cfg.hudScale; float textAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudColor[3]), 1.f); float iconAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudIconAlpha), 1.f); if(IS_NETGAME && deathmatch && cfg.hudShown[HUD_FRAGS]) { // Display the frag counter. i = 199 - 8; if(cfg.hudShown[HUD_HEALTH] || cfg.hudShown[HUD_AMMO]) { i -= 18 * cfg.hudScale; } sprintf(buf, "FRAGS:%i", hud->currentFragsCount); M_WriteText2(2, i, buf, GF_FONTA, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); } // Setup the scaling matrix. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Scalef(cfg.hudScale, cfg.hudScale, 1); // Draw the visible HUD data, first health. if(cfg.hudShown[HUD_HEALTH]) { ST_drawHUDSprite(SPR_STIM, 2, height - 2, HOT_BLEFT, 1, iconAlpha, false); ST_HUDSpriteSize(SPR_STIM, &w, &h); pos = w + 2; sprintf(buf, "%i%%", plr->health); M_WriteText2(pos, height - 14, buf, GF_FONTB, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); pos += M_StringWidth(buf, GF_FONTB) + 2; } if(cfg.hudShown[HUD_AMMO]) { ammotype_t ammoType; float scale; //// \todo Only supports one type of ammo per weapon. //// for each type of ammo this weapon takes. for(ammoType = 0; ammoType < NUM_AMMO_TYPES; ++ammoType) { if(!weaponInfo[plr->readyWeapon][plr->class].mode[0].ammoType[ammoType]) continue; spr = ammoSprite[ammoType]; scale = (spr == SPR_ROCK? .72f : 1); ST_drawHUDSprite(spr, pos, height - 2, HOT_BLEFT, scale, iconAlpha, false); ST_HUDSpriteSize(spr, &w, &h); pos += w + 2; sprintf(buf, "%i", plr->ammo[ammoType].owned); M_WriteText2(pos, height - 14, buf, GF_FONTB, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); break; } } // Doomguy's face | use a bit of extra scale. if(cfg.hudShown[HUD_FACE]) { int plrColor = cfg.playerColor[player]; pos = (width/2) -(faceBackground[plrColor].width/2) + 6; if(iconAlpha != 0.0f) { Draw_BeginZoom(0.7f, pos , height - 1); DGL_Color4f(1, 1, 1, iconAlpha); if(IS_NETGAME) GL_DrawPatch_CS(pos, height - faceBackground[plrColor].height + 1, faceBackground[plrColor].lump); GL_DrawPatch_CS(pos, height - faceBackground[plrColor].height, faces[hud->faceIndex].lump); Draw_EndZoom(); } } pos = width - 2; if(cfg.hudShown[HUD_ARMOR]) { int maxArmor, armorOffset; maxArmor = MAX_OF(armorPoints[0], armorPoints[1]); maxArmor = MAX_OF(maxArmor, armorPoints[2]); maxArmor = MAX_OF(maxArmor, armorPoints[2]); sprintf(buf, "%i%%", maxArmor); armorOffset = M_StringWidth(buf, GF_FONTB); sprintf(buf, "%i%%", plr->armorPoints); pos -= armorOffset; M_WriteText2(pos + armorOffset - M_StringWidth(buf, GF_FONTB), height - 14, buf, GF_FONTB, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); pos -= 2; spr = (plr->armorType == 2 ? SPR_ARM2 : SPR_ARM1); ST_drawHUDSprite(spr, pos, height - 2, HOT_BRIGHT, 1, iconAlpha, false); ST_HUDSpriteSize(spr, &w, &h); pos -= w + 2; } // Keys | use a bit of extra scale. if(cfg.hudShown[HUD_KEYS]) { static int keyPairs[3][2] = { {KT_REDCARD, KT_REDSKULL}, {KT_YELLOWCARD, KT_YELLOWSKULL}, {KT_BLUECARD, KT_BLUESKULL} }; static int keyIcons[NUM_KEY_TYPES] = { SPR_BKEY, SPR_YKEY, SPR_RKEY, SPR_BSKU, SPR_YSKU, SPR_RSKU }; Draw_BeginZoom(0.75f, pos , height - 2); for(i = 0; i < NUM_KEY_TYPES; ++i) { boolean shown = true; if(!plr->keys[i]) continue; if(cfg.hudKeysCombine) { int j; for(j = 0; j < 3; ++j) if(keyPairs[j][0] == i && plr->keys[keyPairs[j][0]] && plr->keys[keyPairs[j][1]]) { shown = false; break; } } if(shown) { spr = keyIcons[i]; ST_drawHUDSprite(spr, pos, height - 2, HOT_BRIGHT, 1, iconAlpha, false); ST_HUDSpriteSize(spr, &w, &h); pos -= w + 2; } } Draw_EndZoom(); } DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } void ST_Drawer(int player, int fullscreenMode, boolean refresh) { hudstate_t* hud; player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; hud = &hudStates[player]; hud->firstTime = hud->firstTime || refresh; hud->statusbarActive = (fullscreenMode < 2) || (AM_IsActive(AM_MapForPlayer(player)) && (cfg.automapHudDisplay == 0 || cfg.automapHudDisplay == 2)); // Do palette shifts. ST_doPaletteStuff(player); // Either slide the statusbar in or fade out the fullscreen HUD. if(hud->statusbarActive) { if(hud->alpha > 0.0f) { hud->statusbarActive = 0; hud->alpha -= 0.1f; } else if(hud->showBar < 1.0f) { hud->showBar += 0.1f; } } else { if(fullscreenMode == 3) { if(hud->alpha > 0.0f) { hud->alpha -= 0.1f; fullscreenMode = 2; } } else { if(hud->showBar > 0.0f) { hud->showBar -= 0.1f; hud->statusbarActive = 1; } else if(hud->alpha < 1.0f) { hud->alpha += 0.1f; } } } // Always try to render statusbar with alpha in fullscreen modes. if(fullscreenMode) hud->blended = 1; else hud->blended = 0; if(hud->statusbarActive) ST_doRefresh(player); else if(fullscreenMode != 3) ST_doFullscreenStuff(player); } void ST_loadGraphics(void) { int i, j, faceNum; char nameBuf[9]; // Load the numbers, tall and short. for(i = 0; i < 10; ++i) { sprintf(nameBuf, "STTNUM%d", i); R_CachePatch(&tallNum[i], nameBuf); sprintf(nameBuf, "STYSNUM%d", i); R_CachePatch(&shortNum[i], nameBuf); } // Load percent key. // Note: why not load STMINUS here, too? R_CachePatch(&tallPercent, "STTPRCNT"); // Key cards: for(i = 0; i < NUM_KEY_TYPES; ++i) { sprintf(nameBuf, "STKEYS%d", i); R_CachePatch(&keys[i], nameBuf); } // Arms background. R_CachePatch(&armsBackground, "STARMS"); // Arms ownership widgets: for(i = 0; i < 6; ++i) { sprintf(nameBuf, "STGNUM%d", i + 2); // gray # R_CachePatch(&arms[i][0], nameBuf); // yellow # memcpy(&arms[i][1], &shortNum[i + 2], sizeof(dpatch_t)); } // Face backgrounds for different color players. for(i = 0; i < 4; ++i) { sprintf(nameBuf, "STFB%d", i); R_CachePatch(&faceBackground[i], nameBuf); } // Status bar background bits. R_CachePatch(&statusbar, "STBAR"); // Face states: faceNum = 0; for(i = 0; i < ST_NUMPAINFACES; ++i) { for(j = 0; j < ST_NUMSTRAIGHTFACES; ++j) { sprintf(nameBuf, "STFST%d%d", i, j); R_CachePatch(&faces[faceNum++], nameBuf); } sprintf(nameBuf, "STFTR%d0", i); // Turn right. R_CachePatch(&faces[faceNum++], nameBuf); sprintf(nameBuf, "STFTL%d0", i); // Turn left. R_CachePatch(&faces[faceNum++], nameBuf); sprintf(nameBuf, "STFOUCH%d", i); // Ouch. R_CachePatch(&faces[faceNum++], nameBuf); sprintf(nameBuf, "STFEVL%d", i); // Evil grin. R_CachePatch(&faces[faceNum++], nameBuf); sprintf(nameBuf, "STFKILL%d", i); // Pissed off. R_CachePatch(&faces[faceNum++], nameBuf); } R_CachePatch(&faces[faceNum++], "STFGOD0"); R_CachePatch(&faces[faceNum++], "STFDEAD0"); } void ST_loadData(void) { ST_loadGraphics(); } static void initData(hudstate_t* hud) { int i; int player = hud - hudStates; player_t* plr = &players[player]; hud->firstTime = true; hud->statusbarActive = true; hud->stopped = true; hud->faceIndex = 0; hud->oldHealth = -1; hud->priority = 0; hud->lastAttackDown = -1; hud->blended = false; hud->showBar = 0.f; hud->statusbarCounterAlpha = 1.f; for(i = 0; i < 3; ++i) { hud->keyBoxes[i] = -1; } for(i = 0; i < NUM_WEAPON_TYPES; ++i) { hud->oldWeaponsOwned[i] = plr->weapons[i].owned; } ST_HUDUnHide(player, HUE_FORCE); } void ST_createWidgets(int player) { typedef struct { float x, y; } hudelement_t; static int largeAmmo = 1994; // means "n/a" static const hudelement_t ammoPos[NUM_AMMO_TYPES] = { {ST_AMMOX, ST_AMMOY}, {ST_AMMOX, ST_AMMOY + (ST_AMMOHEIGHT * 1)}, {ST_AMMOX, ST_AMMOY + (ST_AMMOHEIGHT * 3)}, {ST_AMMOX, ST_AMMOY + (ST_AMMOHEIGHT * 2)} }; static const hudelement_t ammoMaxPos[NUM_AMMO_TYPES] = { {ST_MAXAMMOX, ST_MAXAMMOY}, {ST_MAXAMMOX, ST_MAXAMMOY + (ST_AMMOHEIGHT * 1)}, {ST_MAXAMMOX, ST_MAXAMMOY + (ST_AMMOHEIGHT * 3)}, {ST_MAXAMMOX, ST_MAXAMMOY + (ST_AMMOHEIGHT * 2)} }; ammotype_t ammoType; int* ptr = &largeAmmo; int i; boolean found; player_t* plr = &players[player]; hudstate_t* hud = &hudStates[player]; // Ready weapon ammo: //// \todo Only supports one type of ammo per weapon. found = false; for(ammoType = 0; ammoType < NUM_AMMO_TYPES && !found; ++ammoType) { if(!weaponInfo[plr->readyWeapon][plr->class].mode[0].ammoType[ammoType]) continue; // Weapon does not take this ammo. ptr = &plr->ammo[ammoType].owned; found = true; } STlib_InitNum(&hud->wReadyWeapon, ST_READYAMMOX, ST_READYAMMOY, tallNum, ptr, ST_READYAMMOWIDTH, 1); // Health percentage. STlib_InitPercent(&hud->wHealth, ST_HEALTHX, ST_HEALTHY, tallNum, &plr->health, &tallPercent, 1); // Weapons owned. for(i = 0; i < 6; ++i) { STlib_InitMultiIcon(&hud->wArms[i], ST_ARMSX + (i % 3) * ST_ARMSXSPACE, ST_ARMSY + (i / 3) * ST_ARMSYSPACE, arms[i], 1); } // Frags sum. STlib_InitNum(&hud->wFrags, ST_FRAGSX, ST_FRAGSY, tallNum, &hud->currentFragsCount, ST_FRAGSWIDTH, 1); // Faces. STlib_InitMultiIcon(&hud->wFaces, ST_FACESX, ST_FACESY, faces, 1); // Armor percentage - should be colored later. STlib_InitPercent(&hud->wArmor, ST_ARMORX, ST_ARMORY, tallNum, &plr->armorPoints, &tallPercent, 1); // Keyboxes 0-2. STlib_InitMultiIcon(&hud->wKeyBoxes[0], ST_KEY0X, ST_KEY0Y, keys, 1); STlib_InitMultiIcon(&hud->wKeyBoxes[1], ST_KEY1X, ST_KEY1Y, keys, 1); STlib_InitMultiIcon(&hud->wKeyBoxes[2], ST_KEY2X, ST_KEY2Y, keys, 1); // Ammo count and max (all four kinds). for(i = 0; i < NUM_AMMO_TYPES; ++i) { STlib_InitNum(&hud->wAmmo[i], ammoPos[i].x, ammoPos[i].y, shortNum, &plr->ammo[i].owned, ST_AMMOWIDTH, 1); STlib_InitNum(&hud->wMaxAmmo[i], ammoMaxPos[i].x, ammoMaxPos[i].y, shortNum, &plr->ammo[i].max, ST_MAXAMMOWIDTH, 1); } } void ST_Start(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(!hud->stopped) ST_Stop(player); initData(hud); ST_createWidgets(player); hud->stopped = false; } void ST_Stop(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(hud->stopped) return; hud->stopped = true; } void ST_Init(void) { ST_loadData(); } /** * Console command to change the size of the status bar. */ DEFCC(CCmdStatusBarSize) { int min = 1, max = 20, *val = &cfg.statusbarScale; if(!stricmp(argv[1], "+")) (*val)++; else if(!stricmp(argv[1], "-")) (*val)--; else *val = strtol(argv[1], NULL, 0); if(*val < min) *val = min; if(*val > max) *val = max; // Update the view size if necessary. R_SetViewSize(cfg.screenBlocks); ST_HUDUnHide(CONSOLEPLAYER, HUE_FORCE); // So the user can see the change. return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_inter.c0000644000175000017500000010247711357170242022264 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.c: Handling mobj vs mobj interactions (i.e., collisions). */ #ifdef MSVC # pragma optimize("g", off) #endif // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "am_map.h" #include "d_net.h" #include "dmu_lib.h" #include "p_player.h" #include "p_user.h" #include "p_mapsetup.h" // MACROS ------------------------------------------------------------------ #define BONUSADD (6) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // A weapon is found with two clip loads, a big item has five clip loads. int maxAmmo[NUM_AMMO_TYPES] = {200, 50, 300, 50}; int clipAmmo[NUM_AMMO_TYPES] = {10, 4, 20, 1}; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * @param num Number of clip loads, not the individual count. * * @return @c false, if the ammo can't be picked up at all. */ boolean P_GiveAmmo(player_t *player, ammotype_t ammo, int num) { if(ammo == AT_NOAMMO) return false; if(ammo < 0 || ammo > NUM_AMMO_TYPES) Con_Error("P_GiveAmmo: bad type %i", ammo); if(!(player->ammo[ammo].owned < player->ammo[ammo].max)) return false; if(num) num *= clipAmmo[ammo]; else num = clipAmmo[ammo] / 2; if(gameSkill == SM_BABY || gameSkill == SM_NIGHTMARE) { // Give double ammo in trainer mode (you'll need it in nightmare!). num *= 2; } // We are about to receive some more ammo. Does the player want to // change weapon automatically? P_MaybeChangeWeapon(player, WT_NOCHANGE, ammo, false); player->ammo[ammo].owned = MIN_OF(player->ammo[ammo].max, player->ammo[ammo].owned + num); player->update |= PSF_AMMO; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_AMMO); return true; } /** * The weapon name may have a MF_DROPPED flag ored in. */ boolean P_GiveWeapon(player_t* player, weapontype_t weapon, boolean dropped) { int numClips; ammotype_t i; boolean gaveAmmo = false, gaveWeapon = false; if(IS_NETGAME && (deathmatch != 2) && !dropped) { // Leave placed weapons forever on net games. if(player->weapons[weapon].owned) return false; player->bonusCount += BONUSADD; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Give some of each of the ammo types used by this weapon. for(i=0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. if(deathmatch) numClips = 5; else numClips = 2; if(P_GiveAmmo(player, i, numClips)) gaveAmmo = true; // At least ONE type of ammo was given. } // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, deathmatch == 1); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); S_ConsoleSound(SFX_WPNUP, NULL, player - players); return false; } else { // Give some of each of the ammo types used by this weapon. for(i = 0; i < NUM_AMMO_TYPES; ++i) { if(!weaponInfo[weapon][player->class].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. // Give one clip with a dropped weapon, two clips if found. if(dropped) numClips = 1; else numClips = 2; if(P_GiveAmmo(player, i, numClips)) gaveAmmo = true; // At least ONE type of ammo was given. } if(player->weapons[weapon].owned) { gaveWeapon = false; } else { gaveWeapon = true; player->weapons[weapon].owned = true; player->update |= PSF_OWNED_WEAPONS; // Should we change weapon automatically? P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, false); } // Maybe unhide the HUD? if(gaveWeapon) ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); return (gaveWeapon || gaveAmmo); } } /** * @return @c false, if the body isn't needed at all. */ boolean P_GiveBody(player_t *player, int num) { if(player->health >= maxHealth) return false; player->health += num; if(player->health > maxHealth) player->health = maxHealth; player->plr->mo->health = player->health; player->update |= PSF_HEALTH; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_HEALTH); return true; } /** * @return @c true, iff the armor was given. */ boolean P_GiveArmor(player_t* plr, int type, int points) { if(plr->armorPoints >= points) return false; // Don't pick up. P_PlayerSetArmorType(plr, type); P_PlayerGiveArmorBonus(plr, points - plr->armorPoints); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); return true; } void P_GiveKey(player_t* plr, keytype_t card) { if(plr->keys[card]) return; plr->bonusCount = BONUSADD; plr->keys[card] = 1; plr->update |= PSF_KEYS; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_KEY); } void P_GiveBackpack(player_t* plr) { int i; if(!plr->backpack) { plr->update |= PSF_MAX_AMMO; for(i = 0; i < NUM_AMMO_TYPES; ++i) { plr->ammo[i].max *= 2; } plr->backpack = true; } for(i = 0; i < NUM_AMMO_TYPES; ++i) { P_GiveAmmo(plr, i, 1); } P_SetMessage(plr, GOTBACKPACK, false); } boolean P_GivePower(player_t* player, int power) { player->update |= PSF_POWERS; switch(power) { case PT_INVULNERABILITY: player->powers[power] = INVULNTICS; break; case PT_INVISIBILITY: player->powers[power] = INVISTICS; player->plr->mo->flags |= MF_SHADOW;; break; case PT_FLIGHT: player->powers[power] = 1; player->plr->mo->flags2 |= MF2_FLY; player->plr->mo->flags |= MF_NOGRAVITY; if(player->plr->mo->pos[VZ] <= player->plr->mo->floorZ) { player->flyHeight = 10; // Thrust the player in the air a bit. player->plr->mo->flags |= DDPF_FIXMOM; } break; case PT_INFRARED: player->powers[power] = INFRATICS; break; case PT_IRONFEET: player->powers[power] = IRONTICS; break; case PT_STRENGTH: P_GiveBody(player, maxHealth); player->powers[power] = 1; break; default: if(player->powers[power]) return false; // Already got it. player->powers[power] = 1; break; } if(power == PT_ALLMAP) AM_RevealMap(AM_MapForPlayer(player - players), true); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_POWER); return true; } boolean P_TakePower(player_t* player, int power) { mobj_t* plrmo = player->plr->mo; player->update |= PSF_POWERS; if(player->powers[PT_FLIGHT]) { if(plrmo->pos[VZ] != plrmo->floorZ && cfg.lookSpring) { player->centering = true; } plrmo->flags2 &= ~MF2_FLY; plrmo->flags &= ~MF_NOGRAVITY; player->powers[power] = 0; return true; } if(!player->powers[power]) return false; // Dont got it. if(power == PT_ALLMAP) AM_RevealMap(AM_MapForPlayer(player - players), false); player->powers[power] = 0; return true; } typedef enum { IT_NONE = 0, IT_HEALTH_PACK, IT_HEALTH_KIT, IT_HEALTH_BONUS, IT_HEALTH_SOULSPHERE, IT_ARMOR_GREEN, IT_ARMOR_BLUE, IT_ARMOR_BONUS, IT_WEAPON_BFG, IT_WEAPON_CHAINGUN, IT_WEAPON_CHAINSAW, IT_WEAPON_RLAUNCHER, IT_WEAPON_PLASMARIFLE, IT_WEAPON_SHOTGUN, IT_WEAPON_SSHOTGUN, IT_AMMO_CLIP, IT_AMMO_CLIP_BOX, IT_AMMO_ROCKET, IT_AMMO_ROCKET_BOX, IT_AMMO_CELL, IT_AMMO_CELL_BOX, IT_AMMO_SHELL, IT_AMMO_SHELL_BOX, IT_KEY_BLUE, IT_KEY_YELLOW, IT_KEY_RED, IT_KEY_BLUESKULL, IT_KEY_YELLOWSKULL, IT_KEY_REDSKULL, IT_INVUL, IT_BERSERK, IT_INVIS, IT_SUIT, IT_ALLMAP, IT_VISOR, IT_BACKPACK, IT_MEGASPHERE } itemtype_t; static itemtype_t getItemTypeBySprite(spritetype_e sprite) { static const struct item_s { itemtype_t type; spritetype_e sprite; } items[] = { { IT_HEALTH_PACK, SPR_STIM }, { IT_HEALTH_KIT, SPR_MEDI }, { IT_HEALTH_BONUS, SPR_BON1 }, { IT_HEALTH_SOULSPHERE, SPR_SOUL }, { IT_ARMOR_GREEN, SPR_ARM1 }, { IT_ARMOR_BLUE, SPR_ARM2 }, { IT_ARMOR_BONUS, SPR_BON2 }, { IT_WEAPON_BFG, SPR_BFUG }, { IT_WEAPON_CHAINGUN, SPR_MGUN }, { IT_WEAPON_CHAINSAW, SPR_CSAW }, { IT_WEAPON_RLAUNCHER, SPR_LAUN }, { IT_WEAPON_PLASMARIFLE, SPR_PLAS }, { IT_WEAPON_SHOTGUN, SPR_SHOT }, { IT_WEAPON_SSHOTGUN, SPR_SGN2 }, { IT_AMMO_CLIP, SPR_CLIP }, { IT_AMMO_CLIP_BOX, SPR_AMMO }, { IT_AMMO_ROCKET, SPR_ROCK }, { IT_AMMO_ROCKET_BOX, SPR_BROK }, { IT_AMMO_CELL, SPR_CELL }, { IT_AMMO_CELL_BOX, SPR_CELP }, { IT_AMMO_SHELL, SPR_SHEL }, { IT_AMMO_SHELL_BOX, SPR_SBOX }, { IT_KEY_BLUE, SPR_BKEY }, { IT_KEY_YELLOW, SPR_YKEY }, { IT_KEY_RED, SPR_RKEY }, { IT_KEY_BLUESKULL, SPR_BSKU }, { IT_KEY_YELLOWSKULL, SPR_YSKU }, { IT_KEY_REDSKULL, SPR_RSKU }, { IT_INVUL, SPR_PINV }, { IT_BERSERK, SPR_PSTR }, { IT_INVIS, SPR_PINS }, { IT_SUIT, SPR_SUIT }, { IT_ALLMAP, SPR_PMAP }, { IT_VISOR, SPR_PVIS }, { IT_BACKPACK, SPR_BPAK }, { IT_MEGASPHERE, SPR_MEGA }, { IT_NONE, 0 } }; uint i; for(i = 0; items[i].type != IT_NONE; ++i) if(items[i].sprite == sprite) return items[i].type; return IT_NONE; } /** * @param plr Player being given item. * @param item Type of item being given. * @param dropped @c true = the item was dropped by some entity. * * @return @c true iff the item should be destroyed. */ static boolean giveItem(player_t* plr, itemtype_t item, boolean dropped) { if(!plr) return false; switch(item) { case IT_ARMOR_GREEN: if(!P_GiveArmor(plr, armorClass[0], armorPoints[MINMAX_OF(0, armorClass[0] - 1, 1)])) return false; P_SetMessage(plr, GOTARMOR, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ARMOR_BLUE: if(!P_GiveArmor(plr, armorClass[1], armorPoints[MINMAX_OF(0, armorClass[1] - 1, 1)])) return false; P_SetMessage(plr, GOTMEGA, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_ARMOR_BONUS: if(!plr->armorType) P_PlayerSetArmorType(plr, armorClass[0]); if(plr->armorPoints < armorPoints[1]) P_PlayerGiveArmorBonus(plr, 1); P_SetMessage(plr, GOTARMBONUS, false); if(!mapSetup) { S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); } break; case IT_HEALTH_PACK: if(!P_GiveBody(plr, 10)) return false; P_SetMessage(plr, GOTSTIM, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_HEALTH_KIT: { int oldHealth = plr->health; /** * DOOM bug: * The following test was originaly placed AFTER the call to * P_GiveBody thereby making the first outcome impossible as * the medikit gives 25 points of health. This resulted that * the GOTMEDINEED "Picked up a medikit that you REALLY need" * was never used. */ if(!P_GiveBody(plr, 25)) return false; P_SetMessage(plr, GET_TXT( (oldHealth < 25)? TXT_GOTMEDINEED : TXT_GOTMEDIKIT), false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; } case IT_HEALTH_BONUS: plr->health++; // Can go over 100%. if(plr->health > healthLimit) plr->health = healthLimit; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_SetMessage(plr, GOTHTHBONUS, false); if(!mapSetup) { S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); } break; case IT_HEALTH_SOULSPHERE: plr->health += soulSphereHealth; if(plr->health > soulSphereLimit) plr->health = soulSphereLimit; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_SetMessage(plr, GOTSUPER, false); if(!mapSetup) { S_ConsoleSound(SFX_GETPOW, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); } break; case IT_KEY_BLUE: P_GiveKey(plr, KT_BLUECARD); if(!plr->keys[KT_BLUECARD]) P_SetMessage(plr, GOTBLUECARD, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_YELLOW: P_GiveKey(plr, KT_YELLOWCARD); if(!plr->keys[KT_YELLOWCARD]) P_SetMessage(plr, GOTYELWCARD, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_RED: P_GiveKey(plr, KT_REDCARD); if(!plr->keys[KT_REDCARD]) P_SetMessage(plr, GOTREDCARD, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_BLUESKULL: P_GiveKey(plr, KT_BLUESKULL); if(!plr->keys[KT_BLUESKULL]) P_SetMessage(plr, GOTBLUESKUL, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_YELLOWSKULL: P_GiveKey(plr, KT_YELLOWSKULL); if(!plr->keys[KT_YELLOWSKULL]) P_SetMessage(plr, GOTYELWSKUL, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_KEY_REDSKULL: P_GiveKey(plr, KT_REDSKULL); if(!plr->keys[KT_REDSKULL]) P_SetMessage(plr, GOTREDSKULL, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); if(IS_NETGAME) return false; break; case IT_MEGASPHERE: if(gameMode != commercial) return false; plr->health = megaSphereHealth; plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; P_GiveArmor(plr, armorClass[1], armorPoints[MINMAX_OF(0, armorClass[1] - 1, 1)]); P_SetMessage(plr, GOTMSPHERE, false); if(!mapSetup) { S_ConsoleSound(SFX_GETPOW, NULL, plr - players); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); } break; case IT_INVUL: if(!P_GivePower(plr, PT_INVULNERABILITY)) return false; P_SetMessage(plr, GOTINVUL, false); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_BERSERK: if(!P_GivePower(plr, PT_STRENGTH)) return false; P_SetMessage(plr, GOTBERSERK, false); if(plr->readyWeapon != WT_FIRST && cfg.berserkAutoSwitch) { plr->pendingWeapon = WT_FIRST; plr->update |= PSF_PENDING_WEAPON | PSF_READY_WEAPON; } if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_INVIS: if(!P_GivePower(plr, PT_INVISIBILITY)) return false; P_SetMessage(plr, GOTINVIS, false); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_SUIT: if(!P_GivePower(plr, PT_IRONFEET)) return false; P_SetMessage(plr, GOTSUIT, false); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_ALLMAP: if(!P_GivePower(plr, PT_ALLMAP)) return false; P_SetMessage(plr, GOTMAP, false); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_VISOR: if(!P_GivePower(plr, PT_INFRARED)) return false; P_SetMessage(plr, GOTVISOR, false); if(!mapSetup) S_ConsoleSound(SFX_GETPOW, NULL, plr - players); break; case IT_BACKPACK: P_GiveBackpack(plr); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CLIP: if(!P_GiveAmmo(plr, AT_CLIP, dropped? 0 : 1)) return false; P_SetMessage(plr, GOTCLIP, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CLIP_BOX: if(!P_GiveAmmo(plr, AT_CLIP, 5)) return false; P_SetMessage(plr, GOTCLIPBOX, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_ROCKET: if(!P_GiveAmmo(plr, AT_MISSILE, 1)) return false; P_SetMessage(plr, GOTROCKET, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_ROCKET_BOX: if(!P_GiveAmmo(plr, AT_MISSILE, 5)) return false; P_SetMessage(plr, GOTROCKBOX, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CELL: if(!P_GiveAmmo(plr, AT_CELL, 1)) return false; P_SetMessage(plr, GOTCELL, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_CELL_BOX: if(!P_GiveAmmo(plr, AT_CELL, 5)) return false; P_SetMessage(plr, GOTCELLBOX, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SHELL: if(!P_GiveAmmo(plr, AT_SHELL, 1)) return false; P_SetMessage(plr, GOTSHELLS, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_AMMO_SHELL_BOX: if(!P_GiveAmmo(plr, AT_SHELL, 5)) return false; P_SetMessage(plr, GOTSHELLBOX, false); if(!mapSetup) S_ConsoleSound(SFX_ITEMUP, NULL, plr - players); break; case IT_WEAPON_BFG: if(!P_GiveWeapon(plr, WT_SEVENTH, dropped)) return false; P_SetMessage(plr, GOTBFG9000, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_CHAINGUN: if(!P_GiveWeapon(plr, WT_FOURTH, dropped)) return false; P_SetMessage(plr, GOTCHAINGUN, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_CHAINSAW: if(!P_GiveWeapon(plr, WT_EIGHTH, dropped)) return false; P_SetMessage(plr, GOTCHAINSAW, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_RLAUNCHER: if(!P_GiveWeapon(plr, WT_FIFTH, dropped)) return false; P_SetMessage(plr, GOTLAUNCHER, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_PLASMARIFLE: if(!P_GiveWeapon(plr, WT_SIXTH, dropped)) return false; P_SetMessage(plr, GOTPLASMA, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_SHOTGUN: if(!P_GiveWeapon(plr, WT_THIRD, dropped)) return false; P_SetMessage(plr, GOTSHOTGUN, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; case IT_WEAPON_SSHOTGUN: if(!P_GiveWeapon(plr, WT_NINETH, dropped)) return false; P_SetMessage(plr, GOTSHOTGUN2, false); if(!mapSetup) S_ConsoleSound(SFX_WPNUP, NULL, plr - players); break; default: Con_Error("giveItem: Unknown item %i.", (int) item); } return true; } void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) { player_t* player; float delta; itemtype_t item; delta = special->pos[VZ] - toucher->pos[VZ]; if(delta > toucher->height || delta < -8) { // Out of reach. return; } // Dead thing touching (can happen with a sliding player corpse). if(toucher->health <= 0) return; player = toucher->player; // Identify by sprite. if((item = getItemTypeBySprite(special->sprite)) != IT_NONE) { if(!giveItem(player, item, (special->flags & MF_DROPPED)? true : false)) return; // Don't destroy the item. } else { Con_Message("P_TouchSpecialMobj: Unknown gettable thing %i.\n", (int) special->type); } if(special->flags & MF_COUNTITEM) player->itemCount++; P_MobjRemove(special, false); if(!mapSetup) player->bonusCount += BONUSADD; } void P_KillMobj(mobj_t *source, mobj_t *target, boolean stomping) { mobjtype_t item; mobj_t* mo; unsigned int an; angle_t angle; if(!target) return; // Nothing to kill... target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY); if(target->type != MT_SKULL) target->flags &= ~MF_NOGRAVITY; target->flags |= MF_CORPSE | MF_DROPOFF; target->flags2 &= ~MF2_PASSMOBJ; target->corpseTics = 0; target->height /= 2*2; if(source && source->player) { // Count for intermission. if(target->flags & MF_COUNTKILL) source->player->killCount++; if(target->player) { source->player->frags[target->player - players]++; NetSv_FragsForAll(source->player); NetSv_KillMessage(source->player, target->player, stomping); } } else if(!IS_NETGAME && (target->flags & MF_COUNTKILL)) { // Count all monster deaths (even those caused by other monsters). players[0].killCount++; } if(target->player) { // Count environment kills against the player. if(!source) { target->player->frags[target->player - players]++; NetSv_FragsForAll(target->player); NetSv_KillMessage(target->player, target->player, stomping); } target->flags &= ~MF_SOLID; target->flags2 &= ~MF2_FLY; target->player->powers[PT_FLIGHT] = 0; target->player->playerState = PST_DEAD; target->player->rebornWait = PLAYER_REBORN_TICS; target->player->update |= PSF_STATE; target->player->plr->flags |= DDPF_DEAD; P_DropWeapon(target->player); // Don't die with the automap open. AM_Open(AM_MapForPlayer(target->player - players), false, false); } if(target->health < -target->info->spawnHealth && P_GetState(target->type, SN_XDEATH)) { // Extreme death. P_MobjChangeState(target, P_GetState(target->type, SN_XDEATH)); } else { // Normal death. P_MobjChangeState(target, P_GetState(target->type, SN_DEATH)); } target->tics -= P_Random() & 3; if(target->tics < 1) target->tics = 1; // Drop stuff. // This determines the kind of object spawned during the death frame // of a thing. switch(target->type) { case MT_WOLFSS: case MT_POSSESSED: item = MT_CLIP; break; case MT_SHOTGUY: item = MT_SHOTGUN; break; case MT_CHAINGUY: item = MT_CHAINGUN; break; default: return; } // Don't drop at the exact same place, causes Z flickering with // 3D sprites. angle = P_Random() << 24; an = angle >> ANGLETOFINESHIFT; if((mo = P_SpawnMobj3f(item, target->pos[VX] + 3 * FIX2FLT(finecosine[an]), target->pos[VY] + 3 * FIX2FLT(finesine[an]), 0, angle, MSF_Z_FLOOR))) mo->flags |= MF_DROPPED; // Special versions of items. } /** * Damages both enemies and players. * * @param inflictor Mobj that caused the damage creature or missile, * can be NULL (slime, etc) * @param source Mobj to target after taking damage. Can be @c NULL * for barrel explosions and other environmental stuff. * Source and inflictor are the same for melee attacks. * @return Actual amount of damage done. */ int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damageP, boolean stomping) { angle_t angle; int saved, originalHealth; player_t* player; int temp, damage; if(!target) return 0; // Wha? originalHealth = target->health; // The actual damage (== damageP * netMobDamageModifier for any // non-player mobj). damage = damageP; if(IS_NETGAME && !stomping && D_NetDamageMobj(target, inflictor, source, damage)) { // We're done here. return 0; } // Clients can't harm anybody. if(IS_CLIENT) return 0; if(!(target->flags & MF_SHOOTABLE)) return 0; // Shouldn't happen... if(target->health <= 0) return 0; if(target->player) { // Player specific. // Check if player-player damage is disabled. if(source && source->player && source->player != target->player) { // Co-op damage disabled? if(IS_NETGAME && !deathmatch && cfg.noCoopDamage) return 0; // Same color, no damage? if(cfg.noTeamDamage && cfg.playerColor[target->player - players] == cfg.playerColor[source->player - players]) return 0; } } if(target->flags & MF_SKULLFLY) { target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0; } player = target->player; if(player && gameSkill == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the // inflictor is not a player. if(inflictor && !inflictor->player && (!source || (source && !source->player))) { // damage = (int) ((float) damage * netMobDamageModifier); if(IS_NETGAME) damage *= cfg.netMobDamageModifier; } // Some close combat weapons should not inflict thrust and push the // victim out of reach, thus kick away unless using a melee weapon. if(inflictor && !(target->flags & MF_NOCLIP) && (!source || !source->player || source->player->readyWeapon != WT_EIGHTH) && !(inflictor->flags2 & MF2_NODMGTHRUST)) { uint an; float thrust; angle = R_PointToAngle2(inflictor->pos[VX], inflictor->pos[VY], target->pos[VX], target->pos[VY]); thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass); // Make fall forwards sometimes. if(damage < 40 && damage > target->health && target->pos[VZ] - inflictor->pos[VZ] > 64 && (P_Random() & 1)) { angle += ANG180; thrust *= 4; } an = angle >> ANGLETOFINESHIFT; target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); if(target->dPlayer) { // Only fix momentum. Otherwise clients will find it difficult // to escape from the damage inflictor. target->dPlayer->flags |= DDPF_FIXMOM; } // $dropoff_fix: thrust objects hanging off ledges. if((target->intFlags & MIF_FALLING) && target->gear >= MAXGEAR) target->gear = 0; } if(player) { // Player specific. // End of game hell hack. if(P_ToXSectorOfSubsector(target->subsector)->special == 11 && damage >= target->health) { damage = target->health - 1; } // Below certain threshold, ignore damage in GOD mode, or with // INVUL power. if(damage < 1000 && ((P_GetPlayerCheats(player) & CF_GODMODE) || player->powers[PT_INVULNERABILITY])) { return 0; } if(player->armorType) { if(player->armorType == 1) saved = damage / 3; else saved = damage / 2; if(player->armorPoints <= saved) { // Armor is used up. saved = player->armorPoints; player->armorType = 0; } player->armorPoints -= saved; player->update |= PSF_ARMOR_POINTS; damage -= saved; } player->health -= damage; if(player->health < 0) player->health = 0; player->update |= PSF_HEALTH; player->attacker = source; player->damageCount += damage; // Add damage after armor / invuln. if(player->damageCount > 100) player->damageCount = 100; // Teleport stomp does 10k points... temp = damage < 100 ? damage : 100; // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_DAMAGE); } // How about some particles, yes? // Only works when both target and inflictor are real mobjs. P_SpawnDamageParticleGen(target, inflictor, damage); // Do the damage. target->health -= damage; if(target->health > 0) { // Still alive, phew! if((P_Random() < target->info->painChance) && !(target->flags & MF_SKULLFLY)) { statenum_t state; target->flags |= MF_JUSTHIT; // Fight back! if((state = P_GetState(target->type, SN_PAIN)) != S_NULL) P_MobjChangeState(target, state); } target->reactionTime = 0; // We're awake now... if(source && ((!target->threshold && !(source->flags3 & MF3_NOINFIGHT)) || target->type == MT_VILE) && source != target && source->type != MT_VILE) { statenum_t state; // Target mobj is not intent on another mobj, so make it chase // after the source of the damage. target->target = source; target->threshold = BASETHRESHOLD; if((state = P_GetState(target->type, SN_SEE)) != S_NULL && target->state == &STATES[P_GetState(target->type, SN_SPAWN)]) { P_MobjChangeState(target, state); } } } else { // Death. P_KillMobj(source, target, stomping); } return originalHealth - target->health; #undef BASETHRESHOLD } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_pspr.c0000644000175000017500000004607511357170242022130 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.c: Weapon sprite animation, weapon objects (jDoom-specific). * * Action functions for weapons. */ #ifdef MSVC // Sumtin' 'ere messes with poor ol' MSVC's head... # pragma optimize("g",off) #endif // HEADER FILES ------------------------------------------------------------ #include #include "jdoom.h" #include "d_net.h" #include "p_player.h" #include "p_map.h" #include "p_tick.h" // MACROS ------------------------------------------------------------------ #define LOWERSPEED (6) #define RAISESPEED (6) #define WEAPONBOTTOM (128) #define WEAPONTOP (32) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static float swing[2]; static float bulletSlope; // CODE -------------------------------------------------------------------- void R_GetWeaponBob(int player, float* x, float* y) { if(x) { *x = 1 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finecosine[(128 * mapTime) & FINEMASK]); } if(y) { *y = 32 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finesine[(128 * mapTime) & FINEMASK & (FINEANGLES / 2 - 1)]); } } void P_SetPsprite(player_t* player, int position, statenum_t stnum) { pspdef_t *psp; state_t *state; psp = &player->pSprites[position]; do { if(!stnum) { // Object removed itself. psp->state = NULL; break; } state = &STATES[stnum]; psp->state = state; psp->tics = state->tics; // Could be 0. if(state->misc[0]) { // Coordinate set. psp->pos[VX] = (float) state->misc[0]; psp->pos[VY] = (float) state->misc[1]; } // Call the state action routine (modified handling). if(state->action) { state->action(player, psp); if(!psp->state) break; } stnum = psp->state->nextState; } while(!psp->tics); // An initial state of 0 could cycle through. } /** * Starts bringing the pending weapon up from the bottom of the screen. */ void P_BringUpWeapon(player_t *player) { weaponmodeinfo_t *wminfo; wminfo = WEAPON_INFO(player->pendingWeapon, player->class, 0); if(player->pendingWeapon == WT_NOCHANGE) player->pendingWeapon = player->readyWeapon; if(wminfo->raiseSound) S_StartSoundEx(wminfo->raiseSound, player->plr->mo); player->pendingWeapon = WT_NOCHANGE; player->pSprites[ps_weapon].pos[VY] = WEAPONBOTTOM; #ifdef _DEBUG Con_Message("P_BringUpWeapon: player %i, weapon pspr to %i\n", player - players, wminfo->states[WSN_UP]); #endif P_SetPsprite(player, ps_weapon, wminfo->states[WSN_UP]); } void P_FireWeapon(player_t *player) { statenum_t newstate; if(!P_CheckAmmo(player)) return; NetCl_PlayerActionRequest(player, GPA_FIRE); // Psprite state. player->plr->pSprites[0].state = DDPSP_FIRE; P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackState); newstate = weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_ATTACK]; P_SetPsprite(player, ps_weapon, newstate); NetSv_PSpriteChange(player - players, newstate); P_NoiseAlert(player->plr->mo, player->plr->mo); } /** * Player died, so put the weapon away. */ void P_DropWeapon(player_t *player) { P_SetPsprite(player, ps_weapon, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_DOWN]); } /** * The player can fire the weapon or change to another weapon at this time. * Follows after getting weapon up, or after previous attack/fire sequence. */ void C_DECL A_WeaponReady(player_t *player, pspdef_t *psp) { weaponmodeinfo_t *wminfo; // Enable the pspr Y offset (might be disabled in A_Lower). DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); // Get out of attack state. if(player->plr->mo->state == &STATES[PCLASS_INFO(player->class)->attackState] || player->plr->mo->state == &STATES[PCLASS_INFO(player->class)->attackEndState]) { P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->normalState); } if(player->readyWeapon != WT_NOCHANGE) { wminfo = WEAPON_INFO(player->readyWeapon, player->class, 0); // A weaponready sound? if(psp->state == &STATES[wminfo->states[WSN_READY]] && wminfo->readySound) S_StartSoundEx(wminfo->readySound, player->plr->mo); // Check for weapon change, if player is dead, put the weapon away. if(player->pendingWeapon != WT_NOCHANGE || !player->health) { // (pending weapon should already be validated) P_SetPsprite(player, ps_weapon, wminfo->states[WSN_DOWN]); return; } } // Check for autofire. if(player->brain.attack) { wminfo = WEAPON_INFO(player->readyWeapon, player->class, 0); if(!player->attackDown || wminfo->autoFire) { player->attackDown = true; P_FireWeapon(player); return; } } else player->attackDown = false; // Bob the weapon based on movement speed. R_GetWeaponBob(player - players, &psp->pos[0], &psp->pos[1]); // Psprite state. player->plr->pSprites[0].state = DDPSP_BOBBING; } /** * The player can re-fire the weapon without lowering it entirely. */ void C_DECL A_ReFire(player_t *player, pspdef_t *psp) { // Check for fire (if a weaponchange is pending, let it go through // instead). if((player->brain.attack) && player->pendingWeapon == WT_NOCHANGE && player->health) { player->refire++; P_FireWeapon(player); } else { player->refire = 0; P_CheckAmmo(player); } } void C_DECL A_CheckReload(player_t *player, pspdef_t *psp) { P_CheckAmmo(player); #if 0 if(player->ammo[AT_SHELL] < 2) P_SetPsprite(player, ps_weapon, S_DSNR1); #endif } /** * Lowers current weapon, and changes weapon at bottom. */ void C_DECL A_Lower(player_t *player, pspdef_t *psp) { psp->pos[VY] += LOWERSPEED; // Psprite state. player->plr->pSprites[0].state = DDPSP_DOWN; // Should we disable the lowering? if(!cfg.bobWeaponLower || weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 0); } // Is already down. if(psp->pos[VY] < WEAPONBOTTOM) return; // Player is dead. if(player->playerState == PST_DEAD) { psp->pos[VY] = WEAPONBOTTOM; // Don't bring weapon back up. return; } // The old weapon has been lowered off the screen, so change the weapon // and start raising it. if(!player->health) { // Player is dead, so keep the weapon off screen. P_SetPsprite(player, ps_weapon, S_NULL); return; } player->readyWeapon = player->pendingWeapon; player->update |= PSF_READY_WEAPON; // Should we suddenly lower the weapon? if(cfg.bobWeaponLower && !weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); } P_BringUpWeapon(player); } void C_DECL A_Raise(player_t *player, pspdef_t *psp) { statenum_t newstate; // Psprite state. player->plr->pSprites[0].state = DDPSP_UP; // Should we disable the lowering? if(!cfg.bobWeaponLower || weaponInfo[player->readyWeapon][player->class].mode[0].staticSwitch) { DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 0); } psp->pos[VY] -= RAISESPEED; if(psp->pos[VY] > WEAPONTOP) return; // Enable the pspr Y offset once again. DD_SetInteger(DD_WEAPON_OFFSET_SCALE_Y, 1000); psp->pos[VY] = WEAPONTOP; // The weapon has been raised all the way, so change to the ready state. newstate = weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_READY]; P_SetPsprite(player, ps_weapon, newstate); } void C_DECL A_GunFlash(player_t *player, pspdef_t *psp) { P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); } void C_DECL A_Punch(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; damage = (float) (P_Random() % 10 + 1) * 2; if(player->powers[PT_STRENGTH]) damage *= 10; angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; slope = P_AimLineAttack(player->plr->mo, angle, MELEERANGE); P_LineAttack(player->plr->mo, angle, MELEERANGE, slope, damage); // Turn to face target. if(lineTarget) { S_StartSoundEx(SFX_PUNCH, player->plr->mo); player->plr->mo->angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); player->plr->flags |= DDPF_FIXANGLES; } } void C_DECL A_Saw(player_t *player, pspdef_t *psp) { angle_t angle; int damage; float slope; P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; damage = (P_Random() % 10 + 1) * 2; angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 18; // Use meleerange + 1 se the puff doesn't skip the flash. slope = P_AimLineAttack(player->plr->mo, angle, MELEERANGE + 1); P_LineAttack(player->plr->mo, angle, MELEERANGE + 1, slope, damage); if(!lineTarget) { S_StartSoundEx(SFX_SAWFUL, player->plr->mo); return; } S_StartSoundEx(SFX_SAWHIT, player->plr->mo); // Turn to face target. angle = R_PointToAngle2(player->plr->mo->pos[VX], player->plr->mo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); if(angle - player->plr->mo->angle > ANG180) { if(angle - player->plr->mo->angle < -ANG90 / 20) player->plr->mo->angle = angle + ANG90 / 21; else player->plr->mo->angle -= ANG90 / 20; } else { if(angle - player->plr->mo->angle > ANG90 / 20) player->plr->mo->angle = angle - ANG90 / 21; else player->plr->mo->angle += ANG90 / 20; } player->plr->mo->flags |= MF_JUSTATTACKED; } void C_DECL A_FireMissile(player_t *player, pspdef_t *psp) { P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_SpawnMissile(MT_ROCKET, player->plr->mo, NULL); } void C_DECL A_FireBFG(player_t *player, pspdef_t *psp) { P_ShotAmmo(player); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_SpawnMissile(MT_BFG, player->plr->mo, NULL); } void C_DECL A_FirePlasma(player_t *player, pspdef_t *psp) { P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH] + (P_Random() & 1)); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_SpawnMissile(MT_PLASMA, player->plr->mo, NULL); } /** * Sets a slope so a near miss is at aproximately the height of the * intended target. */ void P_BulletSlope(mobj_t *mo) { angle_t angle; // See which target is to be aimed at. angle = mo->angle; bulletSlope = P_AimLineAttack(mo, angle, 16 * 64); if(!cfg.noAutoAim) { if(!lineTarget) { angle += 1 << 26; bulletSlope = P_AimLineAttack(mo, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; bulletSlope = P_AimLineAttack(mo, angle, 16 * 64); } if(!lineTarget) { angle += 2 << 26; bulletSlope = tan(LOOKDIR2RAD(mo->dPlayer->lookDir)) / 1.2; } } } } void P_GunShot(mobj_t *mo, boolean accurate) { angle_t angle; int damage; damage = 5 * (P_Random() % 3 + 1); angle = mo->angle; if(!accurate) angle += (P_Random() - P_Random()) << 18; P_LineAttack(mo, angle, MISSILERANGE, bulletSlope, damage); } void C_DECL A_FirePistol(player_t *player, pspdef_t *psp) { S_StartSoundEx(SFX_PISTOL, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_BulletSlope(player->plr->mo); P_GunShot(player->plr->mo, !player->refire); } void C_DECL A_FireShotgun(player_t *player, pspdef_t *psp) { int i; S_StartSoundEx(SFX_SHOTGN, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_BulletSlope(player->plr->mo); for(i = 0; i < 7; ++i) P_GunShot(player->plr->mo, false); } void C_DECL A_FireShotgun2(player_t *player, pspdef_t *psp) { int i; angle_t angle; int damage; S_StartSoundEx(SFX_DSHTGN, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH]); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_BulletSlope(player->plr->mo); for(i = 0; i < 20; ++i) { damage = 5 * (P_Random() % 3 + 1); angle = player->plr->mo->angle; angle += (P_Random() - P_Random()) << 19; P_LineAttack(player->plr->mo, angle, MISSILERANGE, bulletSlope + FIX2FLT((P_Random() - P_Random()) << 5), damage); } } void C_DECL A_OpenShotgun2(player_t *player, pspdef_t *psp) { S_StartSound(SFX_DBOPN, player->plr->mo); } void C_DECL A_LoadShotgun2(player_t *player, pspdef_t *psp) { S_StartSound(SFX_DBLOAD, player->plr->mo); } void C_DECL A_CloseShotgun2(player_t *player, pspdef_t *psp) { S_StartSound(SFX_DBCLS, player->plr->mo); A_ReFire(player, psp); } void C_DECL A_FireCGun(player_t *player, pspdef_t *psp) { S_StartSoundEx(SFX_PISTOL, player->plr->mo); P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->attackEndState); P_ShotAmmo(player); P_SetPsprite(player, ps_flash, weaponInfo[player->readyWeapon][player->class].mode[0].states[WSN_FLASH] + psp->state - &STATES[S_CHAIN1]); player->update |= PSF_AMMO; if(IS_CLIENT) return; P_BulletSlope(player->plr->mo); P_GunShot(player->plr->mo, !player->refire); } void C_DECL A_Light0(player_t *player, pspdef_t *psp) { player->plr->extraLight = 0; } void C_DECL A_Light1(player_t *player, pspdef_t *psp) { player->plr->extraLight = 1; } void C_DECL A_Light2(player_t *player, pspdef_t *psp) { player->plr->extraLight = 2; } /** * Spawn a BFG explosion on every monster in view. */ void C_DECL A_BFGSpray(mobj_t *mo) { int i, j, damage; angle_t angle; // Offset angles from its attack angle. for(i = 0; i < 40; ++i) { angle = mo->angle - ANG90 / 2 + ANG90 / 40 * i; // mo->target is the originator (player) of the missile. P_AimLineAttack(mo->target, angle, 16 * 64); if(!lineTarget) continue; P_SpawnMobj3f(MT_EXTRABFG, lineTarget->pos[VX], lineTarget->pos[VY], lineTarget->pos[VZ] + lineTarget->height / 2, angle + ANG180, 0); damage = 0; for(j = 0; j < 15; ++j) damage += (P_Random() & 7) + 1; P_DamageMobj(lineTarget, mo->target, mo->target, damage, false); } } void C_DECL A_BFGsound(player_t* player, pspdef_t* psp) { S_StartSound(SFX_BFG, player->plr->mo); } /** * Called at start of the map for each player. */ void P_SetupPsprites(player_t* player) { int i; // Remove all psprites. for(i = 0; i < NUMPSPRITES; ++i) player->pSprites[i].state = NULL; // Bring up the new weapon. if(player->pendingWeapon == WT_NOCHANGE) player->pendingWeapon = player->readyWeapon; P_BringUpWeapon(player); } /** * Called every tic by player thinking routine. */ void P_MovePsprites(player_t* player) { int i; pspdef_t *psp; state_t *state; psp = &player->pSprites[0]; for(i = 0; i < NUMPSPRITES; ++i, psp++) { // A null state means not active. state = psp->state; if(state) { // Drop tic count and possibly change state. // A -1 tic count never changes. if(psp->tics != -1) { psp->tics--; if(!psp->tics) P_SetPsprite(player, i, psp->state->nextState); } } } player->pSprites[ps_flash].pos[VX] = player->pSprites[ps_weapon].pos[VX]; player->pSprites[ps_flash].pos[VY] = player->pSprites[ps_weapon].pos[VY]; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/m_cheat.c0000644000175000017500000005274511357170242022226 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_cheat.c: Cheat sequence checking. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom.h" #include "f_infine.h" #include "d_net.h" #include "g_common.h" #include "p_player.h" #include "am_map.h" #include "hu_menu.h" #include "hu_msg.h" #include "dmu_lib.h" #include "p_user.h" #include "p_start.h" #include "g_eventsequence.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- int Cht_GodFunc(const int* args, int player); int Cht_NoClipFunc(const int* args, int player); int Cht_ChoppersFunc(const int* args, int player); int Cht_MyPosFunc(const int* args, int player); int Cht_GiveWeaponsAmmoArmorKeys(const int* args, int player); int Cht_GiveWeaponsAmmoArmor(const int* args, int player); int Cht_WarpFunc(const int* args, int player); int Cht_MusicFunc(const int* args, int player); int Cht_PowerupMessage(const int* args, int player); int Cht_PowerupFunc(const int* args, int player); int Cht_Reveal(const int* args, int player); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static unsigned char cheatMusSeq[] = { 'i', 'd', 'm', 'u', 's', 1, 0, 0 }; static unsigned char cheatChoppersSeq[] = { 'i', 'd', 'c', 'h', 'o', 'p', 'p', 'e', 'r', 's' }; static unsigned char cheatGodSeq[] = { 'i', 'd', 'd', 'q', 'd' }; static unsigned char cheatAmmoSeq[] = { 'i', 'd', 'k', 'f', 'a' }; static unsigned char cheatAmmoNoKeySeq[] = { 'i', 'd', 'f', 'a' }; static unsigned char cheatNoClipSeq[] = { 'i', 'd', 's', 'p', 'i', 's', 'p', 'o', 'p', 'd' }; static unsigned char cheatCommercialNoClipSeq[] = { 'i', 'd', 'c', 'l', 'i', 'p' }; static unsigned char cheatPowerupSeq[] = { 'i', 'd', 'b', 'e', 'h', 'o', 'l', 'd' }; static unsigned char cheatPowerupSeq1[] = { 'i', 'd', 'b', 'e', 'h', 'o', 'l', 'd', 1, 0 }; static unsigned char cheatChangeMapSeq[] = { 'i', 'd', 'c', 'l', 'e', 'v', 1, 0, 0 }; static unsigned char cheatMyPosSeq[] = { 'i', 'd', 'm', 'y', 'p', 'o', 's' }; static unsigned char cheatAutomapSeq[] = { 'i', 'd', 'd', 't' }; // CODE -------------------------------------------------------------------- static boolean cheatsEnabled(void) { return !IS_NETGAME; } void Cht_Init(void) { G_AddEventSequence(cheatAutomapSeq, sizeof(cheatAutomapSeq), Cht_Reveal); G_AddEventSequence(cheatChangeMapSeq, sizeof(cheatChangeMapSeq), Cht_WarpFunc); G_AddEventSequence(cheatGodSeq, sizeof(cheatGodSeq), Cht_GodFunc); G_AddEventSequence(cheatAmmoNoKeySeq, sizeof(cheatAmmoNoKeySeq), Cht_GiveWeaponsAmmoArmor); G_AddEventSequence(cheatAmmoSeq, sizeof(cheatAmmoSeq), Cht_GiveWeaponsAmmoArmorKeys); G_AddEventSequence(cheatMusSeq, sizeof(cheatMusSeq), Cht_MusicFunc); G_AddEventSequence(cheatNoClipSeq, sizeof(cheatNoClipSeq), Cht_NoClipFunc); G_AddEventSequence(cheatCommercialNoClipSeq, sizeof(cheatCommercialNoClipSeq), Cht_NoClipFunc); G_AddEventSequence(cheatPowerupSeq1, sizeof(cheatPowerupSeq1), Cht_PowerupFunc); G_AddEventSequence(cheatPowerupSeq, sizeof(cheatPowerupSeq), Cht_PowerupMessage); G_AddEventSequence(cheatChoppersSeq, sizeof(cheatChoppersSeq), Cht_ChoppersFunc); G_AddEventSequence(cheatMyPosSeq, sizeof(cheatMyPosSeq), Cht_MyPosFunc); } /** * 'iddqd' cheat for toggleable god mode. */ int Cht_GodFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->cheats ^= CF_GODMODE; plr->update |= PSF_STATE; if(P_GetPlayerCheats(plr) & CF_GODMODE) { if(plr->plr->mo) plr->plr->mo->health = maxHealth; plr->health = godModeHealth; plr->update |= PSF_HEALTH; } P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_GODMODE) ? STSTR_DQDON : STSTR_DQDOFF), false); return true; } static void giveArmor(int player, int val) { player_t* plr = &players[player]; // Support idfa/idkfa DEH Misc values val = MINMAX_OF(1, val, 3); plr->armorPoints = armorPoints[val]; plr->armorType = armorClass[val]; plr->update |= PSF_STATE | PSF_ARMOR_POINTS; } static void giveWeapons(player_t* plr) { int i; plr->update |= PSF_OWNED_WEAPONS; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { plr->weapons[i].owned = true; } } static void giveAmmo(player_t* plr) { int i; plr->update |= PSF_AMMO; for(i = 0; i < NUM_AMMO_TYPES; ++i) plr->ammo[i].owned = plr->ammo[i].max; } static void giveKeys(player_t* plr) { int i; plr->update |= PSF_KEYS; for(i = 0; i < NUM_KEY_TYPES; ++i) plr->keys[i] = true; } /** * 'idfa' cheat for killer fucking arsenal. */ int Cht_GiveWeaponsAmmoArmor(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. giveWeapons(plr); giveAmmo(plr); giveArmor(player, 2); P_SetMessage(plr, STSTR_FAADDED, false); return true; } /** * 'idkfa' cheat for key full ammo. */ int Cht_GiveWeaponsAmmoArmorKeys(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. giveWeapons(plr); giveAmmo(plr); giveKeys(plr); giveArmor(player, 3); P_SetMessage(plr, STSTR_KFAADDED, false); return true; } /** * 'idmus' cheat for changing music. */ int Cht_MusicFunc(const int* args, int player) { player_t* plr = &players[player]; int musnum; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. musnum = (args[0] - '0') * 10 + (args[1] - '0'); if(S_StartMusicNum(musnum, true)) { P_SetMessage(plr, STSTR_MUS, false); return true; } P_SetMessage(plr, STSTR_NOMUS, false); return false; } /** * 'idclip' no clipping mode cheat. */ int Cht_NoClipFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->cheats ^= CF_NOCLIP; plr->update |= PSF_STATE; P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_NOCLIP) ? STSTR_NCON : STSTR_NCOFF), false); return true; } /** * 'clev' change map cheat. */ int Cht_WarpFunc(const int* args, int player) { player_t* plr = &players[player]; uint epsd, map; if(IS_NETGAME) return false; if(gameMode == commercial) { epsd = 0; map = (args[0] - '0') * 10 + args[1] - '0'; if(map != 0) map -= 1; } else { epsd = (args[0] > '0')? args[0] - '1' : 0; map = (args[1] > '0')? args[1] - '1' : 0; } // Catch invalid maps. if(!G_ValidateMap(&epsd, &map)) return false; P_SetMessage(plr, STSTR_CLEV, false); // Clear the menu if open. Hu_MenuCommand(MCMD_CLOSE); // So be it. briefDisabled = true; G_DeferedInitNew(gameSkill, epsd, map); return true; } int Cht_Reveal(const int* args, int player) { player_t* plr = &players[player]; automapid_t map; if(IS_NETGAME && deathmatch) return false; if(plr->health <= 0) return false; // Dead players can't cheat. map = AM_MapForPlayer(plr - players); if(AM_IsActive(map)) { AM_IncMapCheatLevel(map); } return true; } /** * 'idbehold' power-up menu */ int Cht_PowerupMessage(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, STSTR_BEHOLD, false); return true; } static void givePower(player_t* plr, powertype_t type) { if(type < 0 && type >= NUM_POWER_TYPES) return; if(!plr->powers[type]) { P_GivePower(plr, type); } else if(type == PT_STRENGTH || type == PT_FLIGHT || type == PT_ALLMAP) { P_TakePower(plr, type); } } /** * 'idbehold?' power-up cheats. */ int Cht_PowerupFunc(const int* args, int player) { static const char values[] = { 'v', 's', 'i', 'r', 'a', 'l' }; static const size_t numValues = sizeof(values) / sizeof(values[0]); player_t* plr = &players[player]; size_t i; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. for(i = 0; i < numValues; ++i) { if(args[0] != values[i]) continue; givePower(plr, (powertype_t) i); P_SetMessage(plr, STSTR_BEHOLDX, false); return true; } return false; } /** * 'choppers' invulnerability & chainsaw */ int Cht_ChoppersFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->weapons[WT_EIGHTH].owned = true; plr->powers[PT_INVULNERABILITY] = true; P_SetMessage(plr, STSTR_CHOPPERS, false); return true; } /** * 'mypos' for plr position */ int Cht_MyPosFunc(const int* args, int player) { player_t* plr = &players[player]; char buf[80]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. sprintf(buf, "ang=0x%x;x,y,z=(%g,%g,%g)", players[CONSOLEPLAYER].plr->mo->angle, players[CONSOLEPLAYER].plr->mo->pos[VX], players[CONSOLEPLAYER].plr->mo->pos[VY], players[CONSOLEPLAYER].plr->mo->pos[VZ]); P_SetMessage(plr, buf, false); return true; } static void printDebugInfo(player_t* plr) { char lumpName[9], textBuffer[256]; subsector_t* sub; if(!plr->plr->mo || !userGame) return; P_GetMapLumpName(gameEpisode, gameMap, lumpName); sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", lumpName, plr->plr->mo->pos[VX], plr->plr->mo->pos[VY], plr->plr->mo->pos[VZ]); P_SetMessage(plr, textBuffer, false); // Also print some information to the console. Con_Message(textBuffer); sub = plr->plr->mo->subsector; Con_Message("\nSubsector %i:\n", P_ToIndex(sub)); Con_Message(" FloorZ:%g Material:%s\n", P_GetFloatp(sub, DMU_FLOOR_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_FLOOR_MATERIAL))); Con_Message(" CeilingZ:%g Material:%s\n", P_GetFloatp(sub, DMU_CEILING_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_CEILING_MATERIAL))); Con_Message("Player height:%g Player radius:%g\n", plr->plr->mo->height, plr->plr->mo->radius); } /** * This is the multipurpose cheat ccmd. */ DEFCC(CCmdCheat) { size_t i; // Give each of the characters in argument two to the ST event handler. for(i = 0; i < strlen(argv[1]); ++i) { event_t ev; ev.type = EV_KEY; ev.state = EVS_DOWN; ev.data1 = argv[1][i]; ev.data2 = ev.data3 = 0; G_EventSequenceResponder(&ev); } return true; } DEFCC(CCmdCheatGod) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("god"); } else { int player = CONSOLEPLAYER; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { player = atoi(argv[1]); if(player < 0 || player >= MAXPLAYERS) return false; } if(!players[player].plr->inGame) return false; Cht_GodFunc(NULL, player); } } return true; } DEFCC(CCmdCheatNoClip) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("noclip"); } else { int player = CONSOLEPLAYER; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { player = atoi(argv[1]); if(player < 0 || player >= MAXPLAYERS) return false; } if(!players[player].plr->inGame) return false; Cht_NoClipFunc(NULL, player); } } return true; } static int suicideResponse(msgresponse_t response, void* context) { if(response == MSG_YES) { if(IS_NETGAME && IS_CLIENT) { NetCl_CheatRequest("suicide"); } else { player_t* plr = &players[CONSOLEPLAYER]; P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); } } return true; } DEFCC(CCmdCheatSuicide) { if(G_GetGameState() == GS_MAP) { player_t* plr; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { int i = atoi(argv[1]); if(i < 0 || i >= MAXPLAYERS) return false; plr = &players[i]; } else plr = &players[CONSOLEPLAYER]; if(!plr->plr->inGame) return false; if(plr->playerState == PST_DEAD) return false; if(!IS_NETGAME || IS_CLIENT) { Hu_MsgStart(MSG_YESNO, SUICIDEASK, suicideResponse, NULL); return true; } P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); return true; } else { Hu_MsgStart(MSG_ANYKEY, SUICIDEOUTMAP, NULL, NULL); } return true; } DEFCC(CCmdCheatWarp) { int args[2]; if(!cheatsEnabled()) return false; if(gameMode == commercial) { int num; if(argc != 2) return false; num = atoi(argv[1]); args[0] = num / 10 + '0'; args[1] = num % 10 + '0'; } else { if(argc != 3) return false; args[0] = (int) argv[1][0]; args[1] = (int) argv[2][0]; } Cht_WarpFunc(args, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatReveal) { int option; automapid_t map; if(!cheatsEnabled()) return false; map = AM_MapForPlayer(CONSOLEPLAYER); AM_SetCheatLevel(map, 0); AM_RevealMap(map, false); option = atoi(argv[1]); if(option < 0 || option > 3) return false; if(option == 1) AM_RevealMap(map, true); else if(option != 0) AM_SetCheatLevel(map, option -1); return true; } DEFCC(CCmdCheatGive) { char buf[100]; int player = CONSOLEPLAYER; player_t* plr; size_t i, stuffLen; if(IS_CLIENT) { if(argc != 2) return false; sprintf(buf, "give %s", argv[1]); NetCl_CheatRequest(buf); return true; } if(IS_NETGAME && !netSvAllowCheats) return false; if(argc != 2 && argc != 3) { Con_Printf("Usage:\n give (stuff)\n"); Con_Printf(" give (stuff) (plr)\n"); Con_Printf("Stuff consists of one or more of (type:id). " "If no id; give all of type:\n"); Con_Printf(" a - ammo\n"); Con_Printf(" b - berserk\n"); Con_Printf(" f - the power of flight\n"); Con_Printf(" g - light amplification visor\n"); Con_Printf(" h - health\n"); Con_Printf(" i - invulnerability\n"); Con_Printf(" k - key cards/skulls\n"); Con_Printf(" m - computer area map\n"); Con_Printf(" p - backpack full of ammo\n"); Con_Printf(" r - armor\n"); Con_Printf(" s - radiation shielding suit\n"); Con_Printf(" v - invisibility\n"); Con_Printf(" w - weapons\n"); Con_Printf("Example: 'give arw' corresponds the cheat IDFA.\n"); Con_Printf("Example: 'give w2k1' gives weapon two and key one.\n"); return true; } if(argc == 3) { player = atoi(argv[2]); if(player < 0 || player >= MAXPLAYERS) return false; } if(G_GetGameState() != GS_MAP) { Con_Printf("Can only \"give\" when in a game!\n"); return true; } if(!players[player].plr->inGame) return true; // Can't give to a plr who's not playing plr = &players[player]; strcpy(buf, argv[1]); // Stuff is the 2nd arg. strlwr(buf); stuffLen = strlen(buf); for(i = 0; buf[i]; ++i) { switch(buf[i]) { case 'a': { boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_AMMO_TYPES) { // Give one specific ammo type. plr->update |= PSF_AMMO; plr->ammo[idx].owned = plr->ammo[idx].max; giveAll = false; i++; } } if(giveAll) { giveAmmo(plr); } break; } case 'b': givePower(plr, PT_STRENGTH); break; case 'f': givePower(plr, PT_FLIGHT); break; case 'g': givePower(plr, PT_INFRARED); break; case 'h': P_GiveBody(plr, healthLimit); break; case 'i': givePower(plr, PT_INVULNERABILITY); break; case 'k': { boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_KEY_TYPES) { // Give one specific key. plr->update |= PSF_KEYS; plr->keys[idx] = true; giveAll = false; i++; } } if(giveAll) { giveKeys(plr); } break; } case 'm': givePower(plr, PT_ALLMAP); break; case 'p': P_GiveBackpack(plr); break; case 'r': giveArmor(player, 1); break; case 's': givePower(plr, PT_IRONFEET); break; case 'v': givePower(plr, PT_INVISIBILITY); break; case 'w': { boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_WEAPON_TYPES) { // Give one specific weapon. P_GiveWeapon(plr, idx, false); giveAll = false; i++; } } if(giveAll) { giveWeapons(plr); } break; } default: // Unrecognized Con_Printf("What do you mean, '%c'?\n", buf[i]); break; } } return true; } DEFCC(CCmdCheatMassacre) { Con_Printf("%i monsters killed.\n", P_Massacre()); return true; } DEFCC(CCmdCheatWhere) { printDebugInfo(&players[CONSOLEPLAYER]); return true; } /** * Exit the current map and go to the intermission. */ DEFCC(CCmdCheatLeaveMap) { if(!cheatsEnabled()) return false; if(G_GetGameState() != GS_MAP) { S_LocalSound(SFX_OOF, NULL); Con_Printf("Can only exit a map when in a game!\n"); return true; } G_LeaveMap(G_GetNextMap(gameEpisode, gameMap, false), 0, false); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/d_main.c0000644000175000017500000004743711357170242022057 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_main.c: Game initialization (jDoom-specific). */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "m_argv.h" #include "hu_stuff.h" #include "hu_log.h" #include "hu_menu.h" #include "hu_msg.h" #include "p_saveg.h" #include "p_mapspec.h" #include "p_switch.h" #include "am_map.h" #include "g_defs.h" #include "p_player.h" // MACROS ------------------------------------------------------------------ #define BGCOLOR (7) #define FGCOLOR (8) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int verbose; boolean devParm; // checkparm of -devparm boolean noMonstersParm; // checkparm of -noMonstersParm boolean respawnParm; // checkparm of -respawn boolean fastParm; // checkparm of -fast boolean turboParm; // checkparm of -turbo float turboMul; // multiplier for turbo boolean monsterInfight; gamemode_t gameMode; int gameModeBits; gamemission_t gameMission = GM_DOOM; // This is returned in D_Get(DD_GAME_MODE), max 16 chars. char gameModeString[17]; // The patches used in drawing the view border. char *borderLumps[] = { "FLOOR7_2", "brdr_t", "brdr_r", "brdr_b", "brdr_l", "brdr_tl", "brdr_tr", "brdr_br", "brdr_bl" }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static skillmode_t startSkill; static int startEpisode; static int startMap; static boolean autoStart; // CODE -------------------------------------------------------------------- /** * Attempt to change the current game mode. Can only be done when not * actually in a map. * * \todo Doesn't actually do anything yet other than set the game mode * global vars. * * @param mode The game mode to change to. * * @return @true, if we changed game modes successfully. */ boolean G_SetGameMode(gamemode_t mode) { gameMode = mode; if(G_GetGameState() == GS_MAP) return false; switch(mode) { case shareware: // DOOM 1 shareware, E1, M9 gameModeBits = GM_SHAREWARE; break; case registered: // DOOM 1 registered, E3, M27 gameModeBits = GM_REGISTERED; break; case commercial: // DOOM 2 retail, E1 M34 gameModeBits = GM_COMMERCIAL; break; // DOOM 2 german edition not handled case retail: // DOOM 1 retail, E4, M36 gameModeBits = GM_RETAIL; break; case indetermined: // Well, no IWAD found. gameModeBits = GM_INDETERMINED; break; default: Con_Error("G_SetGameMode: Unknown gameMode %i", mode); } return true; } /** * Check which known IWADs are found. The purpose of this routine is to * find out which IWADs the user lets us to know about, but we don't decide * which one gets loaded or even see if the WADs are actually there. * * The default location for IWADs is Data\GAMENAMETEXT\. */ void G_DetectIWADs(void) { typedef struct { char *file; char *override; } fspec_t; // The '}' means the paths are affected by the base path. char *paths[] = { "}data\\"GAMENAMETEXT"\\", "}data\\", "}", "}iwads\\", "", 0 }; fspec_t iwads[] = { { "tnt.wad", "-tnt" }, { "plutonia.wad", "-plutonia" }, { "doom2.wad", "-doom2" }, { "doom1.wad", "-sdoom" }, { "doom.wad", "-doom" }, { "doom.wad", "-ultimate" }, { "doomu.wad", "-udoom" }, { 0, 0 } }; int i, k; boolean overridden = false; char fn[256]; // First check if an overriding command line option is being used. for(i = 0; iwads[i].file; ++i) if(ArgExists(iwads[i].override)) { overridden = true; break; } // Tell the engine about all the possible IWADs. for(k = 0; paths[k]; k++) for(i = 0; iwads[i].file; ++i) { // Are we allowed to use this? if(overridden && !ArgExists(iwads[i].override)) continue; sprintf(fn, "%s%s", paths[k], iwads[i].file); DD_AddIWAD(fn); } } static boolean lumpsFound(char **list) { for(; *list; list++) if(W_CheckNumForName(*list) == -1) return false; return true; } /** * Checks availability of IWAD files by name, to determine whether * registered/commercial features should be executed (notably loading * PWAD's). */ static void identifyFromData(void) { typedef struct { char **lumps; gamemode_t mode; } identify_t; char *shareware_lumps[] = { // List of lumps to detect shareware with. "e1m1", "e1m2", "e1m3", "e1m4", "e1m5", "e1m6", "e1m7", "e1m8", "e1m9", "d_e1m1", "floor4_8", "floor7_2", NULL }; char *registered_lumps[] = { // List of lumps to detect registered with. "e2m1", "e2m2", "e2m3", "e2m4", "e2m5", "e2m6", "e2m7", "e2m8", "e2m9", "e3m1", "e3m2", "e3m3", "e3m4", "e3m5", "e3m6", "e3m7", "e3m8", "e3m9", "cybre1", "cybrd8", "floor7_2", NULL }; char *retail_lumps[] = { // List of lumps to detect Ultimate Doom with. "e4m1", "e4m2", "e4m3", "e4m4", "e4m5", "e4m6", "e4m7", "e4m8", "e4m9", "m_epi4", NULL }; char *commercial_lumps[] = { // List of lumps to detect Doom II with. "map01", "map02", "map03", "map04", "map10", "map20", "map25", "map30", "vilen1", "vileo1", "vileq1", "grnrock", NULL }; char *plutonia_lumps[] = { "_deutex_", "mc5", "mc11", "mc16", "mc20", NULL }; char *tnt_lumps[] = { "cavern5", "cavern7", "stonew1", NULL }; identify_t list[] = { {commercial_lumps, commercial}, // Doom2 is easiest to detect. {retail_lumps, retail}, // Ultimate Doom is obvious. {registered_lumps, registered}, {shareware_lumps, shareware} }; int i, num = sizeof(list) / sizeof(identify_t); // First check the command line. if(ArgCheck("-sdoom")) { // Shareware DOOM. G_SetGameMode(shareware); return; } if(ArgCheck("-doom")) { // Registered DOOM. G_SetGameMode(registered); return; } if(ArgCheck("-doom2") || ArgCheck("-plutonia") || ArgCheck("-tnt")) { // DOOM 2. G_SetGameMode(commercial); gameMission = GM_DOOM2; if(ArgCheck("-plutonia")) gameMission = GM_PLUT; if(ArgCheck("-tnt")) gameMission = GM_TNT; return; } if(ArgCheck("-ultimate") || ArgCheck("-udoom")) { // Retail DOOM 1: Ultimate DOOM. G_SetGameMode(retail); return; } // Now we must look at the lumps. for(i = 0; i < num; ++i) { // If all the listed lumps are found, selection is made. // All found? if(lumpsFound(list[i].lumps)) { G_SetGameMode(list[i].mode); // Check the mission packs. if(lumpsFound(plutonia_lumps)) gameMission = GM_PLUT; else if(lumpsFound(tnt_lumps)) gameMission = GM_TNT; else if(gameMode == commercial) gameMission = GM_DOOM2; else gameMission = GM_DOOM; return; } } // A detection couldn't be made. G_SetGameMode(shareware); // Assume the minimum. Con_Message("\nIdentifyVersion: DOOM version unknown.\n" "** Important data might be missing! **\n\n"); } /** * gameMode, gameMission and the gameModeString are set. */ void G_IdentifyVersion(void) { identifyFromData(); // The game mode string is returned in DD_Get(DD_GAME_MODE). // It is sent out in netgames, and the PCL_HELLO2 packet contains it. // A client can't connect unless the same game mode is used. memset(gameModeString, 0, sizeof(gameModeString)); strcpy(gameModeString, gameMode == shareware ? "doom1-share" : gameMode == registered ? "doom1" : gameMode == retail ? "doom1-ultimate" : gameMode == commercial ? (gameMission == GM_PLUT ? "doom2-plut" : gameMission == GM_TNT ? "doom2-tnt" : "doom2") : "-"); } /** * Pre Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PreInit(void) { int i; G_SetGameMode(indetermined); // Config defaults. The real settings are read from the .cfg files // but these will be used no such files are found. memset(&cfg, 0, sizeof(cfg)); cfg.playerMoveSpeed = 1; cfg.dclickUse = false; cfg.povLookAround = true; cfg.screenBlocks = cfg.setBlocks = 10; cfg.echoMsg = true; cfg.lookSpeed = 3; cfg.turnSpeed = 1; cfg.usePatchReplacement = 2; // Use built-in replacements if available. cfg.menuScale = .9f; cfg.menuGlitter = .5f; cfg.menuShadow = 0.33f; cfg.menuQuitSound = true; cfg.menuEffects = 1; // Do type-in effect. cfg.flashColor[0] = .7f; cfg.flashColor[1] = .9f; cfg.flashColor[2] = 1; cfg.flashSpeed = 4; cfg.turningSkull = true; cfg.hudKeysCombine = false; cfg.hudShown[HUD_HEALTH] = true; cfg.hudShown[HUD_ARMOR] = true; cfg.hudShown[HUD_AMMO] = true; cfg.hudShown[HUD_KEYS] = true; cfg.hudShown[HUD_FRAGS] = true; cfg.hudShown[HUD_FACE] = false; for(i = 0; i < NUMHUDUNHIDEEVENTS; ++i) // when the hud/statusbar unhides. cfg.hudUnHide[i] = 1; cfg.hudScale = .6f; cfg.hudColor[0] = 1; cfg.hudColor[1] = cfg.hudColor[2] = 0; cfg.hudColor[3] = 1; cfg.hudFog = 1; cfg.hudIconAlpha = 1; cfg.xhairSize = .5f; cfg.xhairVitality = false; cfg.xhairColor[0] = 1; cfg.xhairColor[1] = 1; cfg.xhairColor[2] = 1; cfg.xhairColor[3] = 1; cfg.filterStrength = .8f; cfg.moveCheckZ = true; cfg.jumpPower = 9; cfg.airborneMovement = 1; cfg.weaponAutoSwitch = 1; // if better cfg.noWeaponAutoSwitchIfFiring = false; cfg.ammoAutoSwitch = 0; // never cfg.secretMsg = true; cfg.slidingCorpses = false; cfg.fastMonsters = false; cfg.netJumping = true; cfg.netEpisode = 0; cfg.netMap = 0; cfg.netSkill = SM_MEDIUM; cfg.netColor = 4; cfg.netBFGFreeLook = 0; // allow free-aim 0=none 1=not BFG 2=All cfg.netMobDamageModifier = 1; cfg.netMobHealthModifier = 1; cfg.netGravity = -1; // use map default cfg.plrViewHeight = DEFAULT_PLAYER_VIEWHEIGHT; cfg.mapTitle = true; cfg.hideIWADAuthor = true; cfg.menuColor[0] = 1; cfg.menuColor2[0] = 1; cfg.menuSlam = false; cfg.menuHotkeys = true; cfg.askQuickSaveLoad = true; cfg.maxSkulls = true; cfg.allowSkullsInWalls = false; cfg.anyBossDeath = false; cfg.monstersStuckInDoors = false; cfg.avoidDropoffs = true; cfg.moveBlock = false; cfg.fallOff = true; cfg.fixOuchFace = true; cfg.fixStatusbarOwnedWeapons = true; cfg.statusbarScale = 20; // Full size. cfg.statusbarOpacity = 1; cfg.statusbarCounterAlpha = 1; cfg.automapCustomColors = 0; // Never. cfg.automapL0[0] = .4f; // Unseen areas cfg.automapL0[1] = .4f; cfg.automapL0[2] = .4f; cfg.automapL1[0] = 1.f; // onesided lines cfg.automapL1[1] = 0.f; cfg.automapL1[2] = 0.f; cfg.automapL2[0] = .77f; // floor height change lines cfg.automapL2[1] = .6f; cfg.automapL2[2] = .325f; cfg.automapL3[0] = 1.f; // ceiling change lines cfg.automapL3[1] = .95f; cfg.automapL3[2] = 0.f; cfg.automapMobj[0] = 0.f; cfg.automapMobj[1] = 1.f; cfg.automapMobj[2] = 0.f; cfg.automapBack[0] = 0.f; cfg.automapBack[1] = 0.f; cfg.automapBack[2] = 0.f; cfg.automapOpacity = .7f; cfg.automapLineAlpha = .7f; cfg.automapShowDoors = true; cfg.automapDoorGlow = 8; cfg.automapHudDisplay = 2; cfg.automapRotate = true; cfg.automapBabyKeys = false; cfg.automapZoomSpeed = .1f; cfg.automapPanSpeed = .5f; cfg.automapPanResetOnOpen = true; cfg.automapOpenSeconds = AUTOMAP_OPEN_SECONDS; cfg.counterCheatScale = .7f; cfg.msgShow = true; cfg.msgCount = 4; cfg.msgScale = .8f; cfg.msgUptime = 5; cfg.msgAlign = ALIGN_LEFT; cfg.msgBlink = 5; cfg.msgColor[0] = 1; cfg.msgColor[1] = cfg.msgColor[2] = 0; cfg.chatBeep = 1; cfg.killMessages = true; cfg.bobWeapon = 1; cfg.bobView = 1; cfg.bobWeaponLower = true; cfg.cameraNoClip = true; cfg.respawnMonstersNightmare = true; cfg.weaponOrder[0] = WT_SIXTH; cfg.weaponOrder[1] = WT_NINETH; cfg.weaponOrder[2] = WT_FOURTH; cfg.weaponOrder[3] = WT_THIRD; cfg.weaponOrder[4] = WT_SECOND; cfg.weaponOrder[5] = WT_EIGHTH; cfg.weaponOrder[6] = WT_FIFTH; cfg.weaponOrder[7] = WT_SEVENTH; cfg.weaponOrder[8] = WT_FIRST; cfg.berserkAutoSwitch = true; // Use the DOOM transition by default. Con_SetInteger("con-transition", 1, 0); // Do the common pre init routine; G_CommonPreInit(); } /** * Post Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PostInit(void) { int p; filename_t file; char mapStr[6]; // Border background changes depending on mission. if(gameMission == GM_DOOM2 || gameMission == GM_PLUT || gameMission == GM_TNT) borderLumps[0] = "GRNROCK"; // Common post init routine G_CommonPostInit(); // Initialize ammo info. P_InitAmmoInfo(); // Initialize weapon info. P_InitWeaponInfo(); // Print a game mode banner with rulers. Con_FPrintf(CBLF_RULER | CBLF_WHITE | CBLF_CENTER, gameMode == retail ? "The Ultimate DOOM Startup\n" : gameMode == shareware ? "DOOM Shareware Startup\n" : gameMode == registered ? "DOOM Registered Startup\n" : gameMode == commercial ? (gameMission == GM_PLUT ? "Final DOOM: The Plutonia Experiment\n" : gameMission == GM_TNT ? "Final DOOM: TNT: Evilution\n" : "DOOM 2: Hell on Earth\n") : "Public DOOM\n"); Con_FPrintf(CBLF_RULER, ""); // Game parameters. monsterInfight = GetDefInt("AI|Infight", 0); // Get skill / episode / map from parms. gameSkill = startSkill = SM_NOITEMS; startEpisode = 0; startMap = 0; autoStart = false; // Game mode specific settings. // Plutonia and TNT automatically turn on the full sky. if(gameMode == commercial && (gameMission == GM_PLUT || gameMission == GM_TNT)) { Con_SetInteger("rend-sky-full", 1, true); } // Command line options. noMonstersParm = ArgCheck("-nomonsters")? true : false; respawnParm = ArgCheck("-respawn")? true : false; fastParm = ArgCheck("-fast")? true : false; devParm = ArgCheck("-devparm")? true : false; if(ArgCheck("-altdeath")) cfg.netDeathmatch = 2; else if(ArgCheck("-deathmatch")) cfg.netDeathmatch = 1; p = ArgCheck("-skill"); if(p && p < myargc - 1) { startSkill = Argv(p + 1)[0] - '1'; autoStart = true; } p = ArgCheck("-episode"); if(p && p < myargc - 1) { startEpisode = Argv(p + 1)[0] - '1'; startMap = 0; autoStart = true; } p = ArgCheck("-timer"); if(p && p < myargc - 1 && deathmatch) { int time; time = atoi(Argv(p + 1)); Con_Message("Maps will end after %d minute", time); if(time > 1) Con_Message("s"); Con_Message(".\n"); } p = ArgCheck("-warp"); if(p && p < myargc - 1) { if(gameMode == commercial) { startMap = atoi(Argv(p + 1)) - 1; autoStart = true; } else if(p < myargc - 2) { startEpisode = Argv(p + 1)[0] - '1'; startMap = Argv(p + 2)[0] - '1'; autoStart = true; } } // Turbo option. p = ArgCheck("-turbo"); turboMul = 1.0f; if(p) { int scale = 200; turboParm = true; if(p < myargc - 1) scale = atoi(Argv(p + 1)); if(scale < 10) scale = 10; if(scale > 400) scale = 400; Con_Message("turbo scale: %i%%\n", scale); turboMul = scale / 100.f; } // Are we autostarting? if(autoStart) { if(gameMode == commercial) Con_Message("Warp to Map %d, Skill %d\n", startMap+1, startSkill + 1); else Con_Message("Warp to Episode %d, Map %d, Skill %d\n", startEpisode+1, startMap+1, startSkill + 1); } // Load a saved game? p = ArgCheck("-loadgame"); if(p && p < myargc - 1) { SV_GetSaveGameFileName(file, Argv(p + 1)[0] - '0', FILENAME_T_MAXLEN); G_LoadGame(file); } // Check valid episode and map if(autoStart || IS_NETGAME) { if(gameMode == commercial) sprintf(mapStr, "MAP%2.2d", startMap+1); else sprintf(mapStr, "E%d%d", startEpisode+1, startMap+1); if(!W_CheckNumForName(mapStr)) { startEpisode = 0; startMap = 0; } } // Print a string showing the state of the game parameters Con_Message("Game state parameters:%s%s%s%s%s\n", noMonstersParm? " nomonsters" : "", respawnParm? " respawn" : "", fastParm? " fast" : "", turboParm? " turbo" : "", (cfg.netDeathmatch ==1)? " deathmatch" : (cfg.netDeathmatch ==2)? " altdeath" : ""); if(G_GetGameAction() != GA_LOADGAME) { if(autoStart || IS_NETGAME) { G_DeferedInitNew(startSkill, startEpisode, startMap); } else { G_StartTitle(); // Start up intro loop. } } } void G_Shutdown(void) { Hu_MsgShutdown(); Hu_UnloadData(); Hu_LogShutdown(); P_DestroyIterList(spechit); P_DestroyIterList(linespecials); P_DestroyLineTagLists(); P_DestroySectorTagLists(); AM_Shutdown(); P_FreeWeaponSlots(); } void G_EndFrame(void) { // Nothing to do. } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/g_ctrl.c0000644000175000017500000000655311357170242022074 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.c: Control bindings - DOOM specifc */ // HEADER FILES ------------------------------------------------------------ #include "jdoom.h" #include "g_controls.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Register all the various player controls with Doomsday. */ void G_RegisterPlayerControls(void) { /* typedef struct { const char *command; // The command to execute. } control_t; control_t axisCts[] = { {"WALK"}, {"SIDESTEP"}, {"turn"}, {"ZFLY"}, {"look"}, {"MAPPANX"}, {"MAPPANY"}, {""} // terminate }; control_t toggleCts[] = { {"ATTACK"}, {"USE"}, {"strafe"}, {"SPEED"}, {"JUMP"}, {"mlook"}, {"jlook"}, {"mzoomin"}, {"mzoomout"}, {""} // terminate }; control_t impulseCts[] = { {"falldown"}, {"lookcntr"}, {"weap1"}, {"weapon1"}, {"weapon2"}, {"weap3"}, {"weapon3"}, {"weapon4"}, {"weapon5"}, {"weapon6"}, {"weapon7"}, {"weapon8"}, {"weapon9"}, {"nextwpn"}, {"prevwpn"}, {"demostop"}, {""} // terminate }; uint i; // Axis controls. for(i = 0; axisCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_AXIS, axisCts[i].command); } // Toggle controls. for(i = 0; toggleCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_TOGGLE, toggleCts[i].command); } // Impulse controls. for(i = 0; impulseCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_IMPULSE, impulseCts[i].command); } // FIXME: Now register any default bindings. */ } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/src/p_maputl.c0000644000175000017500000001423511357170242022437 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6) *\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6) * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputl.c: Movement/collision map utility functions. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jdoom.h" #include "p_map.h" #include "dmu_lib.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Apply "torque" to objects hanging off of ledges, so that they fall off. * It's not really torque, since Doom has no concept of rotation, but it's * a convincing effect which avoids anomalies such as lifeless objects * hanging more than halfway off of ledges, and allows objects to roll off * of the edges of moving lifts, or to slide up and then back down stairs, * or to fall into a ditch. * * If more than one linedef is contacted, the effects are cumulative, so * balancing is possible. */ static boolean PIT_ApplyTorque(linedef_t* ld, void* data) { mobj_t* mo = tmThing; float dist; sector_t* frontsec, *backsec; float ffloor, bfloor; float d1[2], vtx[2]; if(tmThing->player) return true; // Skip players! if(!(frontsec = P_GetPtrp(ld, DMU_FRONT_SECTOR)) || !(backsec = P_GetPtrp(ld, DMU_BACK_SECTOR))) return true; // Shouldn't ever happen. ffloor = P_GetFloatp(frontsec, DMU_FLOOR_HEIGHT); bfloor = P_GetFloatp(backsec, DMU_FLOOR_HEIGHT); P_GetFloatpv(ld, DMU_DXY, d1); P_GetFloatpv(P_GetPtrp(ld, DMU_VERTEX0), DMU_XY, vtx); // Lever-arm: dist = +d1[0] * mo->pos[VY] - d1[1] * mo->pos[VX] - d1[0] * vtx[VY] + d1[1] * vtx[VX]; if((dist < 0 && ffloor < mo->pos[VZ] && bfloor >= mo->pos[VZ]) || (dist >= 0 && bfloor < mo->pos[VZ] && ffloor >= mo->pos[VZ])) { // At this point, we know that the object straddles a two-sided // linedef, and that the object's center of mass is above-ground. float x = fabs(d1[0]), y = fabs(d1[1]); if(y > x) { float tmp = x; x = y; y = tmp; } y = FIX2FLT(finesine[(tantoangle[FLT2FIX(y / x) >> DBITS] + ANG90) >> ANGLETOFINESHIFT]); /** * Momentum is proportional to distance between the object's center * of mass and the pivot linedef. * * It is scaled by 2^(OVERDRIVE - gear). When gear is increased, the * momentum gradually decreases to 0 for the same amount of * pseudotorque, so that oscillations are prevented, yet it has a * chance to reach equilibrium. */ if(mo->gear < OVERDRIVE) dist = (dist * FIX2FLT(FLT2FIX(y) << -(mo->gear - OVERDRIVE))) / x; else dist = (dist * FIX2FLT(FLT2FIX(y) >> +(mo->gear - OVERDRIVE))) / x; // Apply momentum away from the pivot linedef. x = d1[1] * dist; y = d1[0] * dist; // Avoid moving too fast all of a sudden (step into "overdrive"). dist = (x * x) + (y * y); while(dist > 4 && mo->gear < MAXGEAR) { ++mo->gear; x /= 2; y /= 2; dist /= 2; } mo->mom[MX] -= x; mo->mom[MY] += y; } return true; } /** * Applies "torque" to objects, based on all contacted linedefs. */ void P_ApplyTorque(mobj_t *mo) { int flags = mo->intFlags; // Corpse sliding anomalies, made configurable. if(!cfg.slidingCorpses) return; tmThing = mo; // Use VALIDCOUNT to prevent checking the same line twice. VALIDCOUNT++; P_MobjLinesIterator(mo, PIT_ApplyTorque, 0); // If any momentum, mark object as 'falling' using engine-internal // flags. if(mo->mom[MX] != 0 || mo->mom[MY] != 0) mo->intFlags |= MIF_FALLING; else // Clear the engine-internal flag indicating falling object. mo->intFlags &= ~MIF_FALLING; /** * If the object has been moving, step up the gear. This helps reach * equilibrium and avoid oscillations. * * DOOM has no concept of potential energy, much less of rotation, so we * have to creatively simulate these systems somehow :) */ // If not falling for a while, reset it to full strength. if(!((mo->intFlags | flags) & MIF_FALLING)) mo->gear = 0; else if(mo->gear < MAXGEAR) // Else if not at max gear, move up a gear. mo->gear++; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/config/0000755000175000017500000000000011523516204021120 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/config/startup.cfg0000644000175000017500000000116611357170242023312 0ustar keeskees# # -=- jDoom Startup -=- # # This file is included with all versions, which means that it gets # overwritten on each upgrade. Give all custom permanent commands in # autoexec.cfg or user.cfg. # These are the original colors. Uncomment to use. #uicolor text .85 .87 1 #uicolor shadow 0 0 0 #uicolor bglight .015 .2 .4 #uicolor bgmed .01 .125 .25 #uicolor bgdark .0035 .05 .1 #uicolor borhigh 1 1 1 #uicolor bormed 0 0 0 #uicolor borlow .015 .2 .4 # The font. #font name fixed12 # Keymap. #keymap default.dkm # The user config file can contain anything the user wants to execute # before the main startup begins. exec user.cfg deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/0000755000175000017500000000000011523516204021276 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/m_random.h0000644000175000017500000000220311357170242023243 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.h: Random numbers. */ #ifndef __M_RANDOM_H__ #define __M_RANDOM_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif byte P_Random(void); byte M_Random(void); void M_ResetRandom(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/r_defs.h0000644000175000017500000000516011357170242022716 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_defs.h: Shared data struct definitions. */ #ifndef __R_DEFS__ #define __R_DEFS__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "p_xg.h" #define SP_floororigheight planes[PLN_FLOOR].origHeight #define SP_ceilorigheight planes[PLN_CEILING].origHeight // Stair build flags. #define BL_BUILT 0x1 #define BL_WAS_BUILT 0x2 #define BL_SPREADED 0x4 typedef struct xsector_s { short special; short tag; // 0 = untraversed, 1,2 = sndlines -1 int soundTraversed; // Thing that made a sound (or null) struct mobj_s* soundTarget; // thinker_t for reversable actions. void* specialData; byte blFlags; // Used during stair building. // Stone, metal, heavy, etc... byte seqType; // NOT USED ATM struct { float origHeight; } planes[2]; // {floor, ceiling} float origLight; float origRGB[3]; xgsector_t* xg; } xsector_t; typedef struct xline_s { short special; short tag; short flags; // Has been rendered at least once and needs to appear in the map, // for each player. boolean mapped[MAXPLAYERS]; int validCount; // Extended generalized lines. xgline_t* xg; } xline_t; extern xsector_t* xsectors; extern xline_t* xlines; xline_t* P_ToXLine(linedef_t* line); xsector_t* P_ToXSector(sector_t* sector); xsector_t* P_ToXSectorOfSubsector(subsector_t* sub); xline_t* P_GetXLine(uint idx); xsector_t* P_GetXSector(uint idx); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_event.h0000644000175000017500000000464311357170242023105 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_event.h: Game actions (instegate changes to game state). */ #ifndef __D_EVENT_H__ #define __D_EVENT_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "doomtype.h" typedef enum { GA_NONE, GA_LOADMAP, GA_NEWGAME, GA_LOADGAME, GA_SAVEGAME, GA_MAPCOMPLETED, GA_VICTORY, GA_LEAVEMAP, GA_SCREENSHOT, GA_QUIT } gameaction_t; /* // // Button/action code definitions. // typedef enum { // Press "Fire". //BT_ATTACK = 1, // Use button, to open doors, activate switches. //BT_USE = 2, // Flag: game events, not really buttons. //BT_SPECIAL = 128, //BT_SPECIALMASK = 3, // Center player look angle (pitch back to zero). //BT_LOOKCENTER = 64, // Flag, weapon change pending. // If true, the next 3 bits hold weapon num. //BT_CHANGE = 4, // The 3bit weapon mask and shift, convenience. //BT_WEAPONMASK = (8+16+32+64), //BT_WEAPONSHIFT = 3, //BT_JUMP = 8, //BT_SPEED = 16, // Pause the game. //BTS_PAUSE = 1, // Save the game at each console. //BTS_SAVEGAME = 2, // Savegame slot numbers // occupy the second byte of buttons. //BTS_SAVEMASK = (4+8+16), //BTS_SAVESHIFT = 2, // Special weapon change flags. //BTS_NEXTWEAPON = 4, //BTS_PREVWEAPON = 8, } buttoncode_t;*/ #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/wi_stuff.h0000644000175000017500000000321411357170242023300 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * wi_stuff.h: Intermission screens */ #ifndef __WI_STUFF__ #define __WI_STUFF__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "d_player.h" // States for the intermission typedef enum { ILS_NONE = -1, ILS_SHOW_STATS, ILS_SHOW_NEXTMAP } interludestate_t; // Setup for an intermission screen. void WI_Init(wbstartstruct_t *wbstartstruct); void WI_SetState(interludestate_t st); void WI_End(void); // Called by main loop, animate the intermission. void WI_Ticker(void); // Draw the intermission screen. void WI_Drawer(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/doomtype.h0000644000175000017500000000361711357170242023321 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomtype_.h: Simple basic typedefs, isolated here to make it easier * separating modules. */ #ifndef __DOOMTYPE_H__ #define __DOOMTYPE_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif // Predefined with some OS. #ifdef UNIX #include #define MAXCHAR SCHAR_MAX #define MAXSHORT SHRT_MAX #define MAXINT INT_MAX #define MAXLONG LONG_MAX #define MINCHAR SCHAR_MIN #define MINSHORT SHRT_MIN #define MININT INT_MIN #define MINLONG LONG_MIN #else /* not UNIX */ #define MAXCHAR ((char)0x7f) #define MAXSHORT ((short)0x7fff) // Max pos 32-bit int. #define MAXINT ((int)0x7fffffff) #define MAXLONG ((long)0x7fffffff) #define MINCHAR ((char)0x80) #define MINSHORT ((short)0x8000) // Max negative 32-bit integer. #define MININT ((int)0x80000000) #define MINLONG ((long)0x80000000) #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_telept.h0000644000175000017500000000224211357170242023266 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.h: */ #ifndef __P_TELEPT_H__ #define __P_TELEPT_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "doomsday.h" int EV_Teleport(linedef_t* line, int side, mobj_t* mo, boolean spawnFog); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_oldsvg.h0000644000175000017500000000266011357170242023273 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_oldsvg.h: DOOM ver 1.9 save game support. */ #ifndef __P_V19_SAVEG__ #define __P_V19_SAVEG__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif boolean SV_v19_LoadGame(const char* filename); void P_v19_UnArchivePlayers(void); void P_v19_UnArchiveWorld(void); void P_v19_UnArchiveThinkers(void); void P_v19_UnArchiveSpecials(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_enemy.h0000644000175000017500000000273311357170242023113 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.h: Enemy thinking, AI (jDoom-specific). */ #ifndef __P_ENEMY_H__ #define __P_ENEMY_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif /** * Global state of boss brain. */ typedef struct braindata_s { int easy; int targetOn; } braindata_t; extern braindata_t brain; extern mobj_t **brainTargets; extern int numBrainTargets; extern int numBrainTargetsAlloc; extern boolean bossKilled; void P_SpawnBrainTargets(void); void P_NoiseAlert(mobj_t *target, mobj_t *emmiter); int P_Massacre(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_player.h0000644000175000017500000001167211357170242023260 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_player.h: Player data structures. */ #ifndef __D_PLAYER__ #define __D_PLAYER__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "d_items.h" #include "p_pspr.h" #include "p_mobj.h" #include "g_controls.h" // // Player states. // typedef enum { PST_LIVE, // Playing or camping. PST_DEAD, // Dead on the ground, view follows killer. PST_REBORN // Ready to restart/respawn??? } playerstate_t; // // Player internal flags, for cheats and debug. // typedef enum { CF_NOCLIP = 0x1, // No clipping, walk through barriers. CF_GODMODE = 0x2, // No damage, no health loss. CF_NOMOMENTUM = 0x4 // Not really a cheat, just a debug aid. } cheat_t; typedef struct player_s { ddplayer_t* plr; // Pointer to the engine's player data. playerstate_t playerState; playerclass_t class; // Player class type. playerbrain_t brain; int health; // This is only used between levels, mo->health is used during levels. int armorPoints; int armorType; // Armor type is 0-2. int powers[NUM_POWER_TYPES]; // Power ups. invinc and invis are tic counters. boolean keys[NUM_KEY_TYPES]; boolean backpack; int frags[MAXPLAYERS]; weapontype_t readyWeapon; weapontype_t pendingWeapon; // Is wp_nochange if not changing. struct playerweapon_s { boolean owned; } weapons[NUM_WEAPON_TYPES]; struct playerammo_s { int owned; int max; } ammo[NUM_AMMO_TYPES]; int attackDown; // True if button down last tic. int useDown; int cheats; // Bit flags, for cheats and debug, see cheat_t, above. int refire; // Refired shots are less accurate. // For intermission stats: int killCount; int itemCount; int secretCount; // For screen flashing (red or bright): int damageCount; int bonusCount; mobj_t* attacker; // Who did damage (NULL for floors/ceilings). int colorMap; // Player skin colorshift, 0-3 for which color to draw player. pspdef_t pSprites[NUMPSPRITES]; // Overlay view sprites (gun, etc). boolean didSecret; // True if secret level has been done. int jumpTics; // The player can jump if this counter is zero. int airCounter; int flyHeight; int rebornWait; // The player can be reborn if this counter is zero. boolean centering; // The player's view pitch is centering back to zero. int update, startSpot; float viewOffset[3]; // Relative to position of the player mobj. float viewZ; // Focal origin above r.z. float viewHeight; // Base height above floor for viewZ. float viewHeightDelta; float bob; // Bounded/scaled total momentum. // Target view to a mobj (NULL=disabled): mobj_t* viewLock; // $democam int lockFull; } player_t; // // INTERMISSION // Structure passed e.g. to WI_Init(wb) // typedef struct { boolean inGame; // Whether the player is in game. // Player stats, kills, collected items etc. int kills; int items; int secret; int time; int frags[MAXPLAYERS]; int score; // Current score on entry, modified on return. } wbplayerstruct_t; typedef struct { uint episode; boolean didSecret; // If true, splash the secret level. uint currentMap, nextMap; // This and next maps. int maxKills; int maxItems; int maxSecret; int maxFrags; int parTime; int pNum; // Index of this player in game. wbplayerstruct_t plyr[MAXPLAYERS]; } wbstartstruct_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_items.h0000644000175000017500000000444511357170242023105 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_items.h: Items key cards, weapon, ammunition. */ #ifndef __D_ITEMS__ #define __D_ITEMS__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "doomdef.h" #define WEAPON_INFO(weaponnum, pclass, fmode) (&weaponInfo[weaponnum][pclass].mode[fmode]) typedef enum { WSN_UP, WSN_DOWN, WSN_READY, WSN_ATTACK, WSN_FLASH, NUM_WEAPON_STATE_NAMES } weaponstatename_t; typedef struct { int gameModeBits; // Game modes, weapon is available in. int ammoType[NUM_AMMO_TYPES]; // required ammo types. int perShot[NUM_AMMO_TYPES]; // Ammo used per shot of each type. boolean autoFire; // (True)= fire when raised if fire held. int states[NUM_WEAPON_STATE_NAMES]; int raiseSound; // Sound played when weapon is raised. int readySound; // Sound played WHILE weapon is readyied int staticSwitch; // Weapon is not lowered during switch. } weaponmodeinfo_t; // Weapon info: sprite frames, ammunition use. typedef struct { weaponmodeinfo_t mode[NUMWEAPLEVELS]; } weaponinfo_t; extern weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES]; void P_InitAmmoInfo(void); void P_InitWeaponInfo(void); void P_InitPlayerValues(struct player_s *p); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/info.h0000644000175000017500000017621411357170242022420 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * info.h: Sprite, state, mobjtype, text, sfx and music identifiers. */ #ifndef __JDOOM_INFO_H__ #define __JDOOM_INFO_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif // Sprites. typedef enum { SPR_TROO, // 000 SPR_SHTG, // 001 SPR_PUNG, // 002 SPR_PISG, // 003 SPR_PISF, // 004 SPR_SHTF, // 005 SPR_SHT2, // 006 SPR_CHGG, // 007 SPR_CHGF, // 008 SPR_MISG, // 009 SPR_MISF, // 010 SPR_SAWG, // 011 SPR_PLSG, // 012 SPR_PLSF, // 013 SPR_BFGG, // 014 SPR_BFGF, // 015 SPR_BLUD, // 016 SPR_PUFF, // 017 SPR_BAL1, // 018 SPR_BAL2, // 019 SPR_PLSS, // 020 SPR_PLSE, // 021 SPR_MISL, // 022 SPR_BFS1, // 023 SPR_BFE1, // 024 SPR_BFE2, // 025 SPR_TFOG, // 026 SPR_IFOG, // 027 SPR_PLAY, // 028 SPR_POSS, // 029 SPR_SPOS, // 030 SPR_VILE, // 031 SPR_FIRE, // 032 SPR_FATB, // 033 SPR_FBXP, // 034 SPR_SKEL, // 035 SPR_MANF, // 036 SPR_FATT, // 037 SPR_CPOS, // 038 SPR_SARG, // 039 SPR_HEAD, // 040 SPR_BAL7, // 041 SPR_BOSS, // 042 SPR_BOS2, // 043 SPR_SKUL, // 044 SPR_SPID, // 045 SPR_BSPI, // 046 SPR_APLS, // 047 SPR_APBX, // 048 SPR_CYBR, // 049 SPR_PAIN, // 050 SPR_SSWV, // 051 SPR_KEEN, // 052 SPR_BBRN, // 053 SPR_BOSF, // 054 SPR_ARM1, // 055 SPR_ARM2, // 056 SPR_BAR1, // 057 SPR_BEXP, // 058 SPR_FCAN, // 059 SPR_BON1, // 060 SPR_BON2, // 061 SPR_BKEY, // 062 SPR_RKEY, // 063 SPR_YKEY, // 064 SPR_BSKU, // 065 SPR_RSKU, // 066 SPR_YSKU, // 067 SPR_STIM, // 068 SPR_MEDI, // 069 SPR_SOUL, // 070 SPR_PINV, // 071 SPR_PSTR, // 072 SPR_PINS, // 073 SPR_MEGA, // 074 SPR_SUIT, // 075 SPR_PMAP, // 076 SPR_PVIS, // 077 SPR_CLIP, // 078 SPR_AMMO, // 079 SPR_ROCK, // 080 SPR_BROK, // 081 SPR_CELL, // 082 SPR_CELP, // 083 SPR_SHEL, // 084 SPR_SBOX, // 085 SPR_BPAK, // 086 SPR_BFUG, // 087 SPR_MGUN, // 088 SPR_CSAW, // 089 SPR_LAUN, // 090 SPR_PLAS, // 091 SPR_SHOT, // 092 SPR_SGN2, // 093 SPR_COLU, // 094 SPR_SMT2, // 095 SPR_GOR1, // 096 SPR_POL2, // 097 SPR_POL5, // 098 SPR_POL4, // 099 SPR_POL3, // 100 SPR_POL1, // 101 SPR_POL6, // 102 SPR_GOR2, // 103 SPR_GOR3, // 104 SPR_GOR4, // 105 SPR_GOR5, // 106 SPR_SMIT, // 107 SPR_COL1, // 108 SPR_COL2, // 109 SPR_COL3, // 110 SPR_COL4, // 111 SPR_CAND, // 112 SPR_CBRA, // 113 SPR_COL6, // 114 SPR_TRE1, // 115 SPR_TRE2, // 116 SPR_ELEC, // 117 SPR_CEYE, // 118 SPR_FSKU, // 119 SPR_COL5, // 120 SPR_TBLU, // 121 SPR_TGRN, // 122 SPR_TRED, // 123 SPR_SMBT, // 124 SPR_SMGT, // 125 SPR_SMRT, // 126 SPR_HDB1, // 127 SPR_HDB2, // 128 SPR_HDB3, // 129 SPR_HDB4, // 130 SPR_HDB5, // 131 SPR_HDB6, // 132 SPR_POB1, // 133 SPR_POB2, // 134 SPR_BRS1, // 135 SPR_TLMP, // 136 SPR_TLP2, // 137 NUMSPRITES // 138 } spritetype_e; // States. typedef enum { S_NULL, // 000 S_LIGHTDONE, // 001 S_PUNCH, // 002 S_PUNCHDOWN, // 003 S_PUNCHUP, // 004 S_PUNCH1, // 005 S_PUNCH2, // 006 S_PUNCH3, // 007 S_PUNCH4, // 008 S_PUNCH5, // 009 S_PISTOL, // 010 S_PISTOLDOWN, // 011 S_PISTOLUP, // 012 S_PISTOL1, // 013 S_PISTOL2, // 014 S_PISTOL3, // 015 S_PISTOL4, // 016 S_PISTOLFLASH, // 017 S_SGUN, // 018 S_SGUNDOWN, // 019 S_SGUNUP, // 020 S_SGUN1, // 021 S_SGUN2, // 022 S_SGUN3, // 023 S_SGUN4, // 024 S_SGUN5, // 025 S_SGUN6, // 026 S_SGUN7, // 027 S_SGUN8, // 028 S_SGUN9, // 029 S_SGUNFLASH1, // 030 S_SGUNFLASH2, // 031 S_DSGUN, // 032 S_DSGUNDOWN, // 033 S_DSGUNUP, // 034 S_DSGUN1, // 035 S_DSGUN2, // 036 S_DSGUN3, // 037 S_DSGUN4, // 038 S_DSGUN5, // 039 S_DSGUN6, // 040 S_DSGUN7, // 041 S_DSGUN8, // 042 S_DSGUN9, // 043 S_DSGUN10, // 044 S_DSNR1, // 045 S_DSNR2, // 046 S_DSGUNFLASH1, // 047 S_DSGUNFLASH2, // 048 S_CHAIN, // 049 S_CHAINDOWN, // 050 S_CHAINUP, // 051 S_CHAIN1, // 052 S_CHAIN2, // 053 S_CHAIN3, // 054 S_CHAINFLASH1, // 055 S_CHAINFLASH2, // 056 S_MISSILE, // 057 S_MISSILEDOWN, // 058 S_MISSILEUP, // 059 S_MISSILE1, // 060 S_MISSILE2, // 061 S_MISSILE3, // 062 S_MISSILEFLASH1, // 063 S_MISSILEFLASH2, // 064 S_MISSILEFLASH3, // 065 S_MISSILEFLASH4, // 066 S_SAW, // 067 S_SAWB, // 068 S_SAWDOWN, // 069 S_SAWUP, // 070 S_SAW1, // 071 S_SAW2, // 072 S_SAW3, // 073 S_PLASMA, // 074 S_PLASMADOWN, // 075 S_PLASMAUP, // 076 S_PLASMA1, // 077 S_PLASMA2, // 078 S_PLASMAFLASH1, // 079 S_PLASMAFLASH2, // 080 S_BFG, // 081 S_BFGDOWN, // 082 S_BFGUP, // 083 S_BFG1, // 084 S_BFG2, // 085 S_BFG3, // 086 S_BFG4, // 087 S_BFGFLASH1, // 088 S_BFGFLASH2, // 089 S_BLOOD1, // 090 S_BLOOD2, // 091 S_BLOOD3, // 092 S_PUFF1, // 093 S_PUFF2, // 094 S_PUFF3, // 095 S_PUFF4, // 096 S_TBALL1, // 097 S_TBALL2, // 098 S_TBALLX1, // 099 S_TBALLX2, // 100 S_TBALLX3, // 101 S_RBALL1, // 102 S_RBALL2, // 103 S_RBALLX1, // 104 S_RBALLX2, // 105 S_RBALLX3, // 106 S_PLASBALL, // 107 S_PLASBALL2, // 108 S_PLASEXP, // 109 S_PLASEXP2, // 110 S_PLASEXP3, // 111 S_PLASEXP4, // 112 S_PLASEXP5, // 113 S_ROCKET, // 114 S_BFGSHOT, // 115 S_BFGSHOT2, // 116 S_BFGLAND, // 117 S_BFGLAND2, // 118 S_BFGLAND3, // 119 S_BFGLAND4, // 120 S_BFGLAND5, // 121 S_BFGLAND6, // 122 S_BFGEXP, // 123 S_BFGEXP2, // 124 S_BFGEXP3, // 125 S_BFGEXP4, // 126 S_EXPLODE1, // 127 S_EXPLODE2, // 128 S_EXPLODE3, // 129 S_TFOG, // 130 S_TFOG01, // 131 S_TFOG02, // 132 S_TFOG2, // 133 S_TFOG3, // 134 S_TFOG4, // 135 S_TFOG5, // 136 S_TFOG6, // 137 S_TFOG7, // 138 S_TFOG8, // 139 S_TFOG9, // 140 S_TFOG10, // 141 S_IFOG, // 142 S_IFOG01, // 143 S_IFOG02, // 144 S_IFOG2, // 145 S_IFOG3, // 146 S_IFOG4, // 147 S_IFOG5, // 148 S_PLAY, // 149 S_PLAY_RUN1, // 150 S_PLAY_RUN2, // 151 S_PLAY_RUN3, // 152 S_PLAY_RUN4, // 153 S_PLAY_ATK1, // 154 S_PLAY_ATK2, // 155 S_PLAY_PAIN, // 156 S_PLAY_PAIN2, // 157 S_PLAY_DIE1, // 158 S_PLAY_DIE2, // 159 S_PLAY_DIE3, // 160 S_PLAY_DIE4, // 161 S_PLAY_DIE5, // 162 S_PLAY_DIE6, // 163 S_PLAY_DIE7, // 164 S_PLAY_XDIE1, // 165 S_PLAY_XDIE2, // 166 S_PLAY_XDIE3, // 167 S_PLAY_XDIE4, // 168 S_PLAY_XDIE5, // 169 S_PLAY_XDIE6, // 170 S_PLAY_XDIE7, // 171 S_PLAY_XDIE8, // 172 S_PLAY_XDIE9, // 173 S_POSS_STND, // 174 S_POSS_STND2, // 175 S_POSS_RUN1, // 176 S_POSS_RUN2, // 177 S_POSS_RUN3, // 178 S_POSS_RUN4, // 179 S_POSS_RUN5, // 180 S_POSS_RUN6, // 181 S_POSS_RUN7, // 182 S_POSS_RUN8, // 183 S_POSS_ATK1, // 184 S_POSS_ATK2, // 185 S_POSS_ATK3, // 186 S_POSS_PAIN, // 187 S_POSS_PAIN2, // 188 S_POSS_DIE1, // 189 S_POSS_DIE2, // 190 S_POSS_DIE3, // 191 S_POSS_DIE4, // 192 S_POSS_DIE5, // 193 S_POSS_XDIE1, // 194 S_POSS_XDIE2, // 195 S_POSS_XDIE3, // 196 S_POSS_XDIE4, // 197 S_POSS_XDIE5, // 198 S_POSS_XDIE6, // 199 S_POSS_XDIE7, // 200 S_POSS_XDIE8, // 201 S_POSS_XDIE9, // 202 S_POSS_RAISE1, // 203 S_POSS_RAISE2, // 204 S_POSS_RAISE3, // 205 S_POSS_RAISE4, // 206 S_SPOS_STND, // 207 S_SPOS_STND2, // 208 S_SPOS_RUN1, // 209 S_SPOS_RUN2, // 210 S_SPOS_RUN3, // 211 S_SPOS_RUN4, // 212 S_SPOS_RUN5, // 213 S_SPOS_RUN6, // 214 S_SPOS_RUN7, // 215 S_SPOS_RUN8, // 216 S_SPOS_ATK1, // 217 S_SPOS_ATK2, // 218 S_SPOS_ATK3, // 219 S_SPOS_PAIN, // 220 S_SPOS_PAIN2, // 221 S_SPOS_DIE1, // 222 S_SPOS_DIE2, // 223 S_SPOS_DIE3, // 224 S_SPOS_DIE4, // 225 S_SPOS_DIE5, // 226 S_SPOS_XDIE1, // 227 S_SPOS_XDIE2, // 228 S_SPOS_XDIE3, // 229 S_SPOS_XDIE4, // 230 S_SPOS_XDIE5, // 231 S_SPOS_XDIE6, // 232 S_SPOS_XDIE7, // 233 S_SPOS_XDIE8, // 234 S_SPOS_XDIE9, // 235 S_SPOS_RAISE1, // 236 S_SPOS_RAISE2, // 237 S_SPOS_RAISE3, // 238 S_SPOS_RAISE4, // 239 S_SPOS_RAISE5, // 240 S_VILE_STND, // 241 S_VILE_STND2, // 242 S_VILE_RUN1, // 243 S_VILE_RUN2, // 244 S_VILE_RUN3, // 245 S_VILE_RUN4, // 246 S_VILE_RUN5, // 247 S_VILE_RUN6, // 248 S_VILE_RUN7, // 249 S_VILE_RUN8, // 250 S_VILE_RUN9, // 251 S_VILE_RUN10, // 252 S_VILE_RUN11, // 253 S_VILE_RUN12, // 254 S_VILE_ATK1, // 255 S_VILE_ATK2, // 256 S_VILE_ATK3, // 257 S_VILE_ATK4, // 258 S_VILE_ATK5, // 259 S_VILE_ATK6, // 260 S_VILE_ATK7, // 261 S_VILE_ATK8, // 262 S_VILE_ATK9, // 263 S_VILE_ATK10, // 264 S_VILE_ATK11, // 265 S_VILE_HEAL1, // 266 S_VILE_HEAL2, // 267 S_VILE_HEAL3, // 268 S_VILE_PAIN, // 269 S_VILE_PAIN2, // 270 S_VILE_DIE1, // 271 S_VILE_DIE2, // 272 S_VILE_DIE3, // 273 S_VILE_DIE4, // 274 S_VILE_DIE5, // 275 S_VILE_DIE6, // 276 S_VILE_DIE7, // 277 S_VILE_DIE8, // 278 S_VILE_DIE9, // 279 S_VILE_DIE10, // 280 S_FIRE1, // 281 S_FIRE2, // 282 S_FIRE3, // 283 S_FIRE4, // 284 S_FIRE5, // 285 S_FIRE6, // 286 S_FIRE7, // 287 S_FIRE8, // 288 S_FIRE9, // 289 S_FIRE10, // 290 S_FIRE11, // 291 S_FIRE12, // 292 S_FIRE13, // 293 S_FIRE14, // 294 S_FIRE15, // 295 S_FIRE16, // 296 S_FIRE17, // 297 S_FIRE18, // 298 S_FIRE19, // 299 S_FIRE20, // 300 S_FIRE21, // 301 S_FIRE22, // 302 S_FIRE23, // 303 S_FIRE24, // 304 S_FIRE25, // 305 S_FIRE26, // 306 S_FIRE27, // 307 S_FIRE28, // 308 S_FIRE29, // 309 S_FIRE30, // 310 S_SMOKE1, // 311 S_SMOKE2, // 312 S_SMOKE3, // 313 S_SMOKE4, // 314 S_SMOKE5, // 315 S_TRACER, // 316 S_TRACER2, // 317 S_TRACEEXP1, // 318 S_TRACEEXP2, // 319 S_TRACEEXP3, // 320 S_SKEL_STND, // 321 S_SKEL_STND2, // 322 S_SKEL_RUN1, // 323 S_SKEL_RUN2, // 324 S_SKEL_RUN3, // 325 S_SKEL_RUN4, // 326 S_SKEL_RUN5, // 327 S_SKEL_RUN6, // 328 S_SKEL_RUN7, // 329 S_SKEL_RUN8, // 330 S_SKEL_RUN9, // 331 S_SKEL_RUN10, // 332 S_SKEL_RUN11, // 333 S_SKEL_RUN12, // 334 S_SKEL_FIST1, // 335 S_SKEL_FIST2, // 336 S_SKEL_FIST3, // 337 S_SKEL_FIST4, // 338 S_SKEL_MISS1, // 339 S_SKEL_MISS2, // 340 S_SKEL_MISS3, // 341 S_SKEL_MISS4, // 342 S_SKEL_PAIN, // 343 S_SKEL_PAIN2, // 344 S_SKEL_DIE1, // 345 S_SKEL_DIE2, // 346 S_SKEL_DIE3, // 347 S_SKEL_DIE4, // 348 S_SKEL_DIE5, // 349 S_SKEL_DIE6, // 350 S_SKEL_RAISE1, // 351 S_SKEL_RAISE2, // 352 S_SKEL_RAISE3, // 353 S_SKEL_RAISE4, // 354 S_SKEL_RAISE5, // 355 S_SKEL_RAISE6, // 356 S_FATSHOT1, // 357 S_FATSHOT2, // 358 S_FATSHOTX1, // 359 S_FATSHOTX2, // 360 S_FATSHOTX3, // 361 S_FATT_STND, // 362 S_FATT_STND2, // 363 S_FATT_RUN1, // 364 S_FATT_RUN2, // 365 S_FATT_RUN3, // 366 S_FATT_RUN4, // 367 S_FATT_RUN5, // 368 S_FATT_RUN6, // 369 S_FATT_RUN7, // 370 S_FATT_RUN8, // 371 S_FATT_RUN9, // 372 S_FATT_RUN10, // 373 S_FATT_RUN11, // 374 S_FATT_RUN12, // 375 S_FATT_ATK1, // 376 S_FATT_ATK2, // 377 S_FATT_ATK3, // 378 S_FATT_ATK4, // 379 S_FATT_ATK5, // 380 S_FATT_ATK6, // 381 S_FATT_ATK7, // 382 S_FATT_ATK8, // 383 S_FATT_ATK9, // 384 S_FATT_ATK10, // 385 S_FATT_PAIN, // 386 S_FATT_PAIN2, // 387 S_FATT_DIE1, // 388 S_FATT_DIE2, // 389 S_FATT_DIE3, // 390 S_FATT_DIE4, // 391 S_FATT_DIE5, // 392 S_FATT_DIE6, // 393 S_FATT_DIE7, // 394 S_FATT_DIE8, // 395 S_FATT_DIE9, // 396 S_FATT_DIE10, // 397 S_FATT_RAISE1, // 398 S_FATT_RAISE2, // 399 S_FATT_RAISE3, // 400 S_FATT_RAISE4, // 401 S_FATT_RAISE5, // 402 S_FATT_RAISE6, // 403 S_FATT_RAISE7, // 404 S_FATT_RAISE8, // 405 S_CPOS_STND, // 406 S_CPOS_STND2, // 407 S_CPOS_RUN1, // 408 S_CPOS_RUN2, // 409 S_CPOS_RUN3, // 410 S_CPOS_RUN4, // 411 S_CPOS_RUN5, // 412 S_CPOS_RUN6, // 413 S_CPOS_RUN7, // 414 S_CPOS_RUN8, // 415 S_CPOS_ATK1, // 416 S_CPOS_ATK2, // 417 S_CPOS_ATK3, // 418 S_CPOS_ATK4, // 419 S_CPOS_PAIN, // 420 S_CPOS_PAIN2, // 421 S_CPOS_DIE1, // 422 S_CPOS_DIE2, // 423 S_CPOS_DIE3, // 424 S_CPOS_DIE4, // 425 S_CPOS_DIE5, // 426 S_CPOS_DIE6, // 427 S_CPOS_DIE7, // 428 S_CPOS_XDIE1, // 429 S_CPOS_XDIE2, // 430 S_CPOS_XDIE3, // 431 S_CPOS_XDIE4, // 432 S_CPOS_XDIE5, // 433 S_CPOS_XDIE6, // 434 S_CPOS_RAISE1, // 435 S_CPOS_RAISE2, // 436 S_CPOS_RAISE3, // 437 S_CPOS_RAISE4, // 438 S_CPOS_RAISE5, // 439 S_CPOS_RAISE6, // 440 S_CPOS_RAISE7, // 441 S_TROO_STND, // 442 S_TROO_STND2, // 443 S_TROO_RUN1, // 444 S_TROO_RUN2, // 445 S_TROO_RUN3, // 446 S_TROO_RUN4, // 447 S_TROO_RUN5, // 448 S_TROO_RUN6, // 449 S_TROO_RUN7, // 450 S_TROO_RUN8, // 451 S_TROO_ATK1, // 452 S_TROO_ATK2, // 453 S_TROO_ATK3, // 454 S_TROO_PAIN, // 455 S_TROO_PAIN2, // 456 S_TROO_DIE1, // 457 S_TROO_DIE2, // 458 S_TROO_DIE3, // 459 S_TROO_DIE4, // 460 S_TROO_DIE5, // 461 S_TROO_XDIE1, // 462 S_TROO_XDIE2, // 463 S_TROO_XDIE3, // 464 S_TROO_XDIE4, // 465 S_TROO_XDIE5, // 466 S_TROO_XDIE6, // 467 S_TROO_XDIE7, // 468 S_TROO_XDIE8, // 469 S_TROO_RAISE1, // 470 S_TROO_RAISE2, // 471 S_TROO_RAISE3, // 472 S_TROO_RAISE4, // 473 S_TROO_RAISE5, // 474 S_SARG_STND, // 475 S_SARG_STND2, // 476 S_SARG_RUN1, // 477 S_SARG_RUN2, // 478 S_SARG_RUN3, // 479 S_SARG_RUN4, // 480 S_SARG_RUN5, // 481 S_SARG_RUN6, // 482 S_SARG_RUN7, // 483 S_SARG_RUN8, // 484 S_SARG_ATK1, // 485 S_SARG_ATK2, // 486 S_SARG_ATK3, // 487 S_SARG_PAIN, // 488 S_SARG_PAIN2, // 489 S_SARG_DIE1, // 490 S_SARG_DIE2, // 491 S_SARG_DIE3, // 492 S_SARG_DIE4, // 493 S_SARG_DIE5, // 494 S_SARG_DIE6, // 495 S_SARG_RAISE1, // 496 S_SARG_RAISE2, // 497 S_SARG_RAISE3, // 498 S_SARG_RAISE4, // 499 S_SARG_RAISE5, // 500 S_SARG_RAISE6, // 501 S_HEAD_STND, // 502 S_HEAD_RUN1, // 503 S_HEAD_ATK1, // 504 S_HEAD_ATK2, // 505 S_HEAD_ATK3, // 506 S_HEAD_PAIN, // 507 S_HEAD_PAIN2, // 508 S_HEAD_PAIN3, // 509 S_HEAD_DIE1, // 510 S_HEAD_DIE2, // 511 S_HEAD_DIE3, // 512 S_HEAD_DIE4, // 513 S_HEAD_DIE5, // 514 S_HEAD_DIE6, // 515 S_HEAD_RAISE1, // 516 S_HEAD_RAISE2, // 517 S_HEAD_RAISE3, // 518 S_HEAD_RAISE4, // 519 S_HEAD_RAISE5, // 520 S_HEAD_RAISE6, // 521 S_BRBALL1, // 522 S_BRBALL2, // 523 S_BRBALLX1, // 524 S_BRBALLX2, // 525 S_BRBALLX3, // 526 S_BOSS_STND, // 527 S_BOSS_STND2, // 528 S_BOSS_RUN1, // 529 S_BOSS_RUN2, // 530 S_BOSS_RUN3, // 531 S_BOSS_RUN4, // 532 S_BOSS_RUN5, // 533 S_BOSS_RUN6, // 534 S_BOSS_RUN7, // 535 S_BOSS_RUN8, // 536 S_BOSS_ATK1, // 537 S_BOSS_ATK2, // 538 S_BOSS_ATK3, // 539 S_BOSS_PAIN, // 540 S_BOSS_PAIN2, // 541 S_BOSS_DIE1, // 542 S_BOSS_DIE2, // 543 S_BOSS_DIE3, // 544 S_BOSS_DIE4, // 545 S_BOSS_DIE5, // 546 S_BOSS_DIE6, // 547 S_BOSS_DIE7, // 548 S_BOSS_RAISE1, // 549 S_BOSS_RAISE2, // 550 S_BOSS_RAISE3, // 551 S_BOSS_RAISE4, // 552 S_BOSS_RAISE5, // 553 S_BOSS_RAISE6, // 554 S_BOSS_RAISE7, // 555 S_BOS2_STND, // 556 S_BOS2_STND2, // 557 S_BOS2_RUN1, // 558 S_BOS2_RUN2, // 559 S_BOS2_RUN3, // 560 S_BOS2_RUN4, // 561 S_BOS2_RUN5, // 562 S_BOS2_RUN6, // 563 S_BOS2_RUN7, // 564 S_BOS2_RUN8, // 565 S_BOS2_ATK1, // 566 S_BOS2_ATK2, // 567 S_BOS2_ATK3, // 568 S_BOS2_PAIN, // 569 S_BOS2_PAIN2, // 570 S_BOS2_DIE1, // 571 S_BOS2_DIE2, // 572 S_BOS2_DIE3, // 573 S_BOS2_DIE4, // 574 S_BOS2_DIE5, // 575 S_BOS2_DIE6, // 576 S_BOS2_DIE7, // 577 S_BOS2_RAISE1, // 578 S_BOS2_RAISE2, // 579 S_BOS2_RAISE3, // 580 S_BOS2_RAISE4, // 581 S_BOS2_RAISE5, // 582 S_BOS2_RAISE6, // 583 S_BOS2_RAISE7, // 584 S_SKULL_STND, // 585 S_SKULL_STND2, // 586 S_SKULL_RUN1, // 587 S_SKULL_RUN2, // 588 S_SKULL_ATK1, // 589 S_SKULL_ATK2, // 590 S_SKULL_ATK3, // 591 S_SKULL_ATK4, // 592 S_SKULL_PAIN, // 593 S_SKULL_PAIN2, // 594 S_SKULL_DIE1, // 595 S_SKULL_DIE2, // 596 S_SKULL_DIE3, // 597 S_SKULL_DIE4, // 598 S_SKULL_DIE5, // 599 S_SKULL_DIE6, // 600 S_SPID_STND, // 601 S_SPID_STND2, // 602 S_SPID_RUN1, // 603 S_SPID_RUN2, // 604 S_SPID_RUN3, // 605 S_SPID_RUN4, // 606 S_SPID_RUN5, // 607 S_SPID_RUN6, // 608 S_SPID_RUN7, // 609 S_SPID_RUN8, // 610 S_SPID_RUN9, // 611 S_SPID_RUN10, // 612 S_SPID_RUN11, // 613 S_SPID_RUN12, // 614 S_SPID_ATK1, // 615 S_SPID_ATK2, // 616 S_SPID_ATK3, // 617 S_SPID_ATK4, // 618 S_SPID_PAIN, // 619 S_SPID_PAIN2, // 620 S_SPID_DIE1, // 621 S_SPID_DIE2, // 622 S_SPID_DIE3, // 623 S_SPID_DIE4, // 624 S_SPID_DIE5, // 625 S_SPID_DIE6, // 626 S_SPID_DIE7, // 627 S_SPID_DIE8, // 628 S_SPID_DIE9, // 629 S_SPID_DIE10, // 630 S_SPID_DIE11, // 631 S_BSPI_STND, // 632 S_BSPI_STND2, // 633 S_BSPI_SIGHT, // 634 S_BSPI_RUN1, // 635 S_BSPI_RUN2, // 636 S_BSPI_RUN3, // 637 S_BSPI_RUN4, // 638 S_BSPI_RUN5, // 639 S_BSPI_RUN6, // 640 S_BSPI_RUN7, // 641 S_BSPI_RUN8, // 642 S_BSPI_RUN9, // 643 S_BSPI_RUN10, // 644 S_BSPI_RUN11, // 645 S_BSPI_RUN12, // 646 S_BSPI_ATK1, // 647 S_BSPI_ATK2, // 648 S_BSPI_ATK3, // 649 S_BSPI_ATK4, // 650 S_BSPI_PAIN, // 651 S_BSPI_PAIN2, // 652 S_BSPI_DIE1, // 653 S_BSPI_DIE2, // 654 S_BSPI_DIE3, // 655 S_BSPI_DIE4, // 656 S_BSPI_DIE5, // 657 S_BSPI_DIE6, // 658 S_BSPI_DIE7, // 659 S_BSPI_RAISE1, // 660 S_BSPI_RAISE2, // 661 S_BSPI_RAISE3, // 662 S_BSPI_RAISE4, // 663 S_BSPI_RAISE5, // 664 S_BSPI_RAISE6, // 665 S_BSPI_RAISE7, // 666 S_ARACH_PLAZ, // 667 S_ARACH_PLAZ2, // 668 S_ARACH_PLEX, // 669 S_ARACH_PLEX2, // 670 S_ARACH_PLEX3, // 671 S_ARACH_PLEX4, // 672 S_ARACH_PLEX5, // 673 S_CYBER_STND, // 674 S_CYBER_STND2, // 675 S_CYBER_RUN1, // 676 S_CYBER_RUN2, // 677 S_CYBER_RUN3, // 678 S_CYBER_RUN4, // 679 S_CYBER_RUN5, // 680 S_CYBER_RUN6, // 681 S_CYBER_RUN7, // 682 S_CYBER_RUN8, // 683 S_CYBER_ATK1, // 684 S_CYBER_ATK2, // 685 S_CYBER_ATK3, // 686 S_CYBER_ATK4, // 687 S_CYBER_ATK5, // 688 S_CYBER_ATK6, // 689 S_CYBER_PAIN, // 690 S_CYBER_DIE1, // 691 S_CYBER_DIE2, // 692 S_CYBER_DIE3, // 693 S_CYBER_DIE4, // 694 S_CYBER_DIE5, // 695 S_CYBER_DIE6, // 696 S_CYBER_DIE7, // 697 S_CYBER_DIE8, // 698 S_CYBER_DIE9, // 699 S_CYBER_DIE10, // 700 S_PAIN_STND, // 701 S_PAIN_RUN1, // 702 S_PAIN_RUN2, // 703 S_PAIN_RUN3, // 704 S_PAIN_RUN4, // 705 S_PAIN_RUN5, // 706 S_PAIN_RUN6, // 707 S_PAIN_ATK1, // 708 S_PAIN_ATK2, // 709 S_PAIN_ATK3, // 710 S_PAIN_ATK4, // 711 S_PAIN_PAIN, // 712 S_PAIN_PAIN2, // 713 S_PAIN_DIE1, // 714 S_PAIN_DIE2, // 715 S_PAIN_DIE3, // 716 S_PAIN_DIE4, // 717 S_PAIN_DIE5, // 718 S_PAIN_DIE6, // 719 S_PAIN_RAISE1, // 720 S_PAIN_RAISE2, // 721 S_PAIN_RAISE3, // 722 S_PAIN_RAISE4, // 723 S_PAIN_RAISE5, // 724 S_PAIN_RAISE6, // 725 S_SSWV_STND, // 726 S_SSWV_STND2, // 727 S_SSWV_RUN1, // 728 S_SSWV_RUN2, // 729 S_SSWV_RUN3, // 730 S_SSWV_RUN4, // 731 S_SSWV_RUN5, // 732 S_SSWV_RUN6, // 733 S_SSWV_RUN7, // 734 S_SSWV_RUN8, // 735 S_SSWV_ATK1, // 736 S_SSWV_ATK2, // 737 S_SSWV_ATK3, // 738 S_SSWV_ATK4, // 739 S_SSWV_ATK5, // 740 S_SSWV_ATK6, // 741 S_SSWV_PAIN, // 742 S_SSWV_PAIN2, // 743 S_SSWV_DIE1, // 744 S_SSWV_DIE2, // 745 S_SSWV_DIE3, // 746 S_SSWV_DIE4, // 747 S_SSWV_DIE5, // 748 S_SSWV_XDIE1, // 749 S_SSWV_XDIE2, // 750 S_SSWV_XDIE3, // 751 S_SSWV_XDIE4, // 752 S_SSWV_XDIE5, // 753 S_SSWV_XDIE6, // 754 S_SSWV_XDIE7, // 755 S_SSWV_XDIE8, // 756 S_SSWV_XDIE9, // 757 S_SSWV_RAISE1, // 758 S_SSWV_RAISE2, // 759 S_SSWV_RAISE3, // 760 S_SSWV_RAISE4, // 761 S_SSWV_RAISE5, // 762 S_KEENSTND, // 763 S_COMMKEEN, // 764 S_COMMKEEN2, // 765 S_COMMKEEN3, // 766 S_COMMKEEN4, // 767 S_COMMKEEN5, // 768 S_COMMKEEN6, // 769 S_COMMKEEN7, // 770 S_COMMKEEN8, // 771 S_COMMKEEN9, // 772 S_COMMKEEN10, // 773 S_COMMKEEN11, // 774 S_COMMKEEN12, // 775 S_KEENPAIN, // 776 S_KEENPAIN2, // 777 S_BRAIN, // 778 S_BRAIN_PAIN, // 779 S_BRAIN_DIE1, // 780 S_BRAIN_DIE2, // 781 S_BRAIN_DIE3, // 782 S_BRAIN_DIE4, // 783 S_BRAINEYE, // 784 S_BRAINEYESEE, // 785 S_BRAINEYE1, // 786 S_SPAWN1, // 787 S_SPAWN2, // 788 S_SPAWN3, // 789 S_SPAWN4, // 790 S_SPAWNFIRE1, // 791 S_SPAWNFIRE2, // 792 S_SPAWNFIRE3, // 793 S_SPAWNFIRE4, // 794 S_SPAWNFIRE5, // 795 S_SPAWNFIRE6, // 796 S_SPAWNFIRE7, // 797 S_SPAWNFIRE8, // 798 S_BRAINEXPLODE1, // 799 S_BRAINEXPLODE2, // 800 S_BRAINEXPLODE3, // 801 S_ARM1, // 802 S_ARM1A, // 803 S_ARM2, // 804 S_ARM2A, // 805 S_BAR1, // 806 S_BAR2, // 807 S_BEXP, // 808 S_BEXP2, // 809 S_BEXP3, // 810 S_BEXP4, // 811 S_BEXP5, // 812 S_BBAR1, // 813 S_BBAR2, // 814 S_BBAR3, // 815 S_BON1, // 816 S_BON1A, // 817 S_BON1B, // 818 S_BON1C, // 819 S_BON1D, // 820 S_BON1E, // 821 S_BON2, // 822 S_BON2A, // 823 S_BON2B, // 824 S_BON2C, // 825 S_BON2D, // 826 S_BON2E, // 827 S_BKEY, // 828 S_BKEY2, // 829 S_RKEY, // 830 S_RKEY2, // 831 S_YKEY, // 832 S_YKEY2, // 833 S_BSKULL, // 834 S_BSKULL2, // 835 S_RSKULL, // 836 S_RSKULL2, // 837 S_YSKULL, // 838 S_YSKULL2, // 839 S_STIM, // 840 S_MEDI, // 841 S_SOUL, // 842 S_SOUL2, // 843 S_SOUL3, // 844 S_SOUL4, // 845 S_SOUL5, // 846 S_SOUL6, // 847 S_PINV, // 848 S_PINV2, // 849 S_PINV3, // 850 S_PINV4, // 851 S_PSTR, // 852 S_PINS, // 853 S_PINS2, // 854 S_PINS3, // 855 S_PINS4, // 856 S_MEGA, // 857 S_MEGA2, // 858 S_MEGA3, // 859 S_MEGA4, // 860 S_SUIT, // 861 S_PMAP, // 862 S_PMAP2, // 863 S_PMAP3, // 864 S_PMAP4, // 865 S_PMAP5, // 866 S_PMAP6, // 867 S_PVIS, // 868 S_PVIS2, // 869 S_CLIP, // 870 S_AMMO, // 871 S_ROCK, // 872 S_BROK, // 873 S_CELL, // 874 S_CELP, // 875 S_SHEL, // 876 S_SBOX, // 877 S_BPAK, // 878 S_BFUG, // 879 S_MGUN, // 880 S_CSAW, // 881 S_LAUN, // 882 S_PLAS, // 883 S_SHOT, // 884 S_SHOT2, // 885 S_COLU, // 886 S_STALAG, // 887 S_BLOODYTWITCH, // 888 S_BLOODYTWITCH2, // 889 S_BLOODYTWITCH3, // 890 S_BLOODYTWITCH4, // 891 S_DEADTORSO, // 892 S_DEADBOTTOM, // 893 S_HEADSONSTICK, // 894 S_GIBS, // 895 S_HEADONASTICK, // 896 S_HEADCANDLES, // 897 S_HEADCANDLES2, // 898 S_DEADSTICK, // 899 S_LIVESTICK, // 900 S_LIVESTICK2, // 901 S_MEAT2, // 902 S_MEAT3, // 903 S_MEAT4, // 904 S_MEAT5, // 905 S_STALAGTITE, // 906 S_TALLGRNCOL, // 907 S_SHRTGRNCOL, // 908 S_TALLREDCOL, // 909 S_SHRTREDCOL, // 910 S_CANDLESTIK, // 911 S_CANDELABRA, // 912 S_SKULLCOL, // 913 S_TORCHTREE, // 914 S_BIGTREE, // 915 S_TECHPILLAR, // 916 S_EVILEYE, // 917 S_EVILEYE2, // 918 S_EVILEYE3, // 919 S_EVILEYE4, // 920 S_FLOATSKULL, // 921 S_FLOATSKULL2, // 922 S_FLOATSKULL3, // 923 S_HEARTCOL, // 924 S_HEARTCOL2, // 925 S_BLUETORCH, // 926 S_BLUETORCH2, // 927 S_BLUETORCH3, // 928 S_BLUETORCH4, // 929 S_GREENTORCH, // 930 S_GREENTORCH2, // 931 S_GREENTORCH3, // 932 S_GREENTORCH4, // 933 S_REDTORCH, // 934 S_REDTORCH2, // 935 S_REDTORCH3, // 936 S_REDTORCH4, // 937 S_BTORCHSHRT, // 938 S_BTORCHSHRT2, // 939 S_BTORCHSHRT3, // 940 S_BTORCHSHRT4, // 941 S_GTORCHSHRT, // 942 S_GTORCHSHRT2, // 943 S_GTORCHSHRT3, // 944 S_GTORCHSHRT4, // 945 S_RTORCHSHRT, // 946 S_RTORCHSHRT2, // 947 S_RTORCHSHRT3, // 948 S_RTORCHSHRT4, // 949 S_HANGNOGUTS, // 950 S_HANGBNOBRAIN, // 951 S_HANGTLOOKDN, // 952 S_HANGTSKULL, // 953 S_HANGTLOOKUP, // 954 S_HANGTNOBRAIN, // 955 S_COLONGIBS, // 956 S_SMALLPOOL, // 957 S_BRAINSTEM, // 958 S_TECHLAMP, // 959 S_TECHLAMP2, // 960 S_TECHLAMP3, // 961 S_TECHLAMP4, // 962 S_TECH2LAMP, // 963 S_TECH2LAMP2, // 964 S_TECH2LAMP3, // 965 S_TECH2LAMP4, // 966 S_SMALL_WHITE_LIGHT, // 967 S_TEMPSOUNDORIGIN1, // 968 S_ROCKETPUFF1, // 969 S_ROCKETPUFF2, // 970 S_ROCKETPUFF3, // 971 S_ROCKETPUFF4, // 972 NUMSTATES // 973 } statenum_t; // Map objects. typedef enum { MT_NONE = -1, MT_FIRST = 0, MT_PLAYER = MT_FIRST, // 000 MT_POSSESSED, // 001 MT_SHOTGUY, // 002 MT_VILE, // 003 MT_FIRE, // 004 MT_UNDEAD, // 005 MT_TRACER, // 006 MT_SMOKE, // 007 MT_FATSO, // 008 MT_FATSHOT, // 009 MT_CHAINGUY, // 010 MT_TROOP, // 011 MT_SERGEANT, // 012 MT_SHADOWS, // 013 MT_HEAD, // 014 MT_BRUISER, // 015 MT_BRUISERSHOT, // 016 MT_KNIGHT, // 017 MT_SKULL, // 018 MT_SPIDER, // 019 MT_BABY, // 020 MT_CYBORG, // 021 MT_PAIN, // 022 MT_WOLFSS, // 023 MT_KEEN, // 024 MT_BOSSBRAIN, // 025 MT_BOSSSPIT, // 026 MT_BOSSTARGET, // 027 MT_SPAWNSHOT, // 028 MT_SPAWNFIRE, // 029 MT_BARREL, // 030 MT_TROOPSHOT, // 031 MT_HEADSHOT, // 032 MT_ROCKET, // 033 MT_PLASMA, // 034 MT_BFG, // 035 MT_ARACHPLAZ, // 036 MT_PUFF, // 037 MT_BLOOD, // 038 MT_TFOG, // 039 MT_IFOG, // 040 MT_TELEPORTMAN, // 041 MT_EXTRABFG, // 042 MT_MISC0, // 043 MT_MISC1, // 044 MT_MISC2, // 045 MT_MISC3, // 046 MT_MISC4, // 047 MT_MISC5, // 048 MT_MISC6, // 049 MT_MISC7, // 050 MT_MISC8, // 051 MT_MISC9, // 052 MT_MISC10, // 053 MT_MISC11, // 054 MT_MISC12, // 055 MT_INV, // 056 MT_MISC13, // 057 MT_INS, // 058 MT_MISC14, // 059 MT_MISC15, // 060 MT_MISC16, // 061 MT_MEGA, // 062 MT_CLIP, // 063 MT_MISC17, // 064 MT_MISC18, // 065 MT_MISC19, // 066 MT_MISC20, // 067 MT_MISC21, // 068 MT_MISC22, // 069 MT_MISC23, // 070 MT_MISC24, // 071 MT_MISC25, // 072 MT_CHAINGUN, // 073 MT_MISC26, // 074 MT_MISC27, // 075 MT_MISC28, // 076 MT_SHOTGUN, // 077 MT_SUPERSHOTGUN, // 078 MT_MISC29, // 079 MT_MISC30, // 080 MT_MISC31, // 081 MT_MISC32, // 082 MT_MISC33, // 083 MT_MISC34, // 084 MT_MISC35, // 085 MT_MISC36, // 086 MT_MISC37, // 087 MT_MISC38, // 088 MT_MISC39, // 089 MT_MISC40, // 090 MT_MISC41, // 091 MT_MISC42, // 092 MT_MISC43, // 093 MT_MISC44, // 094 MT_MISC45, // 095 MT_MISC46, // 096 MT_MISC47, // 097 MT_MISC48, // 098 MT_MISC49, // 099 MT_MISC50, // 100 MT_MISC51, // 101 MT_MISC52, // 102 MT_MISC53, // 103 MT_MISC54, // 104 MT_MISC55, // 105 MT_MISC56, // 106 MT_MISC57, // 107 MT_MISC58, // 108 MT_MISC59, // 109 MT_MISC60, // 110 MT_MISC61, // 111 MT_MISC62, // 112 MT_MISC63, // 113 MT_MISC64, // 114 MT_MISC65, // 115 MT_MISC66, // 116 MT_MISC67, // 117 MT_MISC68, // 118 MT_MISC69, // 119 MT_MISC70, // 120 MT_MISC71, // 121 MT_MISC72, // 122 MT_MISC73, // 123 MT_MISC74, // 124 MT_MISC75, // 125 MT_MISC76, // 126 MT_MISC77, // 127 MT_MISC78, // 128 MT_MISC79, // 129 MT_MISC80, // 130 MT_MISC81, // 131 MT_MISC82, // 132 MT_MISC83, // 133 MT_MISC84, // 134 MT_MISC85, // 135 MT_MISC86, // 136 MT_LIGHTSOURCE, // 137 MT_TEMPSOUNDORIGIN, // 138 MT_ROCKETPUFF, // 139 MT_STEALTHBABY, // 140 MT_STEALTHVILE, // 141 MT_STEALTHBRUISER, // 142 MT_STEALTHKNIGHT, // 143 MT_STEALTHHEAD, // 144 MT_STEALTHSERGEANT, // 145 MT_STEALTHCHAINGUY, // 146 MT_STEALTHTROOP, // 147 MT_STEALTHFATSO, // 148 MT_STEALTHUNDEAD, // 149 MT_STEALTHSHOTGUY, // 150 MT_STEALTHPOSSESSED, // 151 NUMMOBJTYPES // 152 } mobjtype_t; // Text. typedef enum { TXT_D_DEVSTR, TXT_D_CDROM, TXT_PRESSKEY, TXT_PRESSYN, TXT_QUITMSG, TXT_LOADNET, TXT_QLOADNET, TXT_QSAVESPOT, TXT_SAVEDEAD, TXT_QSPROMPT, TXT_QLPROMPT, TXT_NEWGAME, TXT_NIGHTMARE, TXT_SWSTRING, TXT_MSGOFF, TXT_MSGON, TXT_NETEND, TXT_ENDGAME, TXT_DOSY, TXT_DETAILHI, TXT_DETAILLO, TXT_GAMMALVL0, TXT_GAMMALVL1, TXT_GAMMALVL2, TXT_GAMMALVL3, TXT_GAMMALVL4, TXT_EMPTYSTRING, TXT_GOTARMOR, TXT_GOTMEGA, TXT_GOTHTHBONUS, TXT_GOTARMBONUS, TXT_GOTSTIM, TXT_GOTMEDINEED, TXT_GOTMEDIKIT, TXT_GOTSUPER, TXT_GOTBLUECARD, TXT_GOTYELWCARD, TXT_GOTREDCARD, TXT_GOTBLUESKUL, TXT_GOTYELWSKUL, TXT_GOTREDSKULL, TXT_GOTINVUL, TXT_GOTBERSERK, TXT_GOTINVIS, TXT_GOTSUIT, TXT_GOTMAP, TXT_GOTVISOR, TXT_GOTMSPHERE, TXT_GOTCLIP, TXT_GOTCLIPBOX, TXT_GOTROCKET, TXT_GOTROCKBOX, TXT_GOTCELL, TXT_GOTCELLBOX, TXT_GOTSHELLS, TXT_GOTSHELLBOX, TXT_GOTBACKPACK, TXT_GOTBFG9000, TXT_GOTCHAINGUN, TXT_GOTCHAINSAW, TXT_GOTLAUNCHER, TXT_GOTPLASMA, TXT_GOTSHOTGUN, TXT_GOTSHOTGUN2, TXT_PD_BLUEO, TXT_PD_REDO, TXT_PD_YELLOWO, TXT_PD_BLUEK, TXT_PD_REDK, TXT_PD_YELLOWK, TXT_GGSAVED, TXT_HUSTR_MSGU, TXT_HUSTR_E1M1, TXT_HUSTR_E1M2, TXT_HUSTR_E1M3, TXT_HUSTR_E1M4, TXT_HUSTR_E1M5, TXT_HUSTR_E1M6, TXT_HUSTR_E1M7, TXT_HUSTR_E1M8, TXT_HUSTR_E1M9, TXT_HUSTR_E2M1, TXT_HUSTR_E2M2, TXT_HUSTR_E2M3, TXT_HUSTR_E2M4, TXT_HUSTR_E2M5, TXT_HUSTR_E2M6, TXT_HUSTR_E2M7, TXT_HUSTR_E2M8, TXT_HUSTR_E2M9, TXT_HUSTR_E3M1, TXT_HUSTR_E3M2, TXT_HUSTR_E3M3, TXT_HUSTR_E3M4, TXT_HUSTR_E3M5, TXT_HUSTR_E3M6, TXT_HUSTR_E3M7, TXT_HUSTR_E3M8, TXT_HUSTR_E3M9, TXT_HUSTR_E4M1, TXT_HUSTR_E4M2, TXT_HUSTR_E4M3, TXT_HUSTR_E4M4, TXT_HUSTR_E4M5, TXT_HUSTR_E4M6, TXT_HUSTR_E4M7, TXT_HUSTR_E4M8, TXT_HUSTR_E4M9, TXT_HUSTR_1, TXT_HUSTR_2, TXT_HUSTR_3, TXT_HUSTR_4, TXT_HUSTR_5, TXT_HUSTR_6, TXT_HUSTR_7, TXT_HUSTR_8, TXT_HUSTR_9, TXT_HUSTR_10, TXT_HUSTR_11, TXT_HUSTR_12, TXT_HUSTR_13, TXT_HUSTR_14, TXT_HUSTR_15, TXT_HUSTR_16, TXT_HUSTR_17, TXT_HUSTR_18, TXT_HUSTR_19, TXT_HUSTR_20, TXT_HUSTR_21, TXT_HUSTR_22, TXT_HUSTR_23, TXT_HUSTR_24, TXT_HUSTR_25, TXT_HUSTR_26, TXT_HUSTR_27, TXT_HUSTR_28, TXT_HUSTR_29, TXT_HUSTR_30, TXT_HUSTR_31, TXT_HUSTR_32, TXT_PHUSTR_1, TXT_PHUSTR_2, TXT_PHUSTR_3, TXT_PHUSTR_4, TXT_PHUSTR_5, TXT_PHUSTR_6, TXT_PHUSTR_7, TXT_PHUSTR_8, TXT_PHUSTR_9, TXT_PHUSTR_10, TXT_PHUSTR_11, TXT_PHUSTR_12, TXT_PHUSTR_13, TXT_PHUSTR_14, TXT_PHUSTR_15, TXT_PHUSTR_16, TXT_PHUSTR_17, TXT_PHUSTR_18, TXT_PHUSTR_19, TXT_PHUSTR_20, TXT_PHUSTR_21, TXT_PHUSTR_22, TXT_PHUSTR_23, TXT_PHUSTR_24, TXT_PHUSTR_25, TXT_PHUSTR_26, TXT_PHUSTR_27, TXT_PHUSTR_28, TXT_PHUSTR_29, TXT_PHUSTR_30, TXT_PHUSTR_31, TXT_PHUSTR_32, TXT_THUSTR_1, TXT_THUSTR_2, TXT_THUSTR_3, TXT_THUSTR_4, TXT_THUSTR_5, TXT_THUSTR_6, TXT_THUSTR_7, TXT_THUSTR_8, TXT_THUSTR_9, TXT_THUSTR_10, TXT_THUSTR_11, TXT_THUSTR_12, TXT_THUSTR_13, TXT_THUSTR_14, TXT_THUSTR_15, TXT_THUSTR_16, TXT_THUSTR_17, TXT_THUSTR_18, TXT_THUSTR_19, TXT_THUSTR_20, TXT_THUSTR_21, TXT_THUSTR_22, TXT_THUSTR_23, TXT_THUSTR_24, TXT_THUSTR_25, TXT_THUSTR_26, TXT_THUSTR_27, TXT_THUSTR_28, TXT_THUSTR_29, TXT_THUSTR_30, TXT_THUSTR_31, TXT_THUSTR_32, TXT_HUSTR_CHATMACRO0, TXT_HUSTR_CHATMACRO1, TXT_HUSTR_CHATMACRO2, TXT_HUSTR_CHATMACRO3, TXT_HUSTR_CHATMACRO4, TXT_HUSTR_CHATMACRO5, TXT_HUSTR_CHATMACRO6, TXT_HUSTR_CHATMACRO7, TXT_HUSTR_CHATMACRO8, TXT_HUSTR_CHATMACRO9, TXT_HUSTR_TALKTOSELF1, TXT_HUSTR_TALKTOSELF2, TXT_HUSTR_TALKTOSELF3, TXT_HUSTR_TALKTOSELF4, TXT_HUSTR_TALKTOSELF5, TXT_HUSTR_MESSAGESENT, TXT_HUSTR_PLRGREEN, TXT_HUSTR_PLRINDIGO, TXT_HUSTR_PLRBROWN, TXT_HUSTR_PLRRED, TXT_AMSTR_FOLLOWON, TXT_AMSTR_FOLLOWOFF, TXT_AMSTR_GRIDON, TXT_AMSTR_GRIDOFF, TXT_AMSTR_MARKEDSPOT, TXT_AMSTR_MARKSCLEARED, TXT_STSTR_MUS, TXT_STSTR_NOMUS, TXT_STSTR_DQDON, TXT_STSTR_DQDOFF, TXT_STSTR_KFAADDED, TXT_STSTR_FAADDED, TXT_STSTR_NCON, TXT_STSTR_NCOFF, TXT_STSTR_BEHOLD, TXT_STSTR_BEHOLDX, TXT_STSTR_CHOPPERS, TXT_STSTR_CLEV, TXT_E1TEXT, TXT_E2TEXT, TXT_E3TEXT, TXT_E4TEXT, TXT_C1TEXT, TXT_C2TEXT, TXT_C3TEXT, TXT_C4TEXT, TXT_C5TEXT, TXT_C6TEXT, TXT_P1TEXT, TXT_P2TEXT, TXT_P3TEXT, TXT_P4TEXT, TXT_P5TEXT, TXT_P6TEXT, TXT_T1TEXT, TXT_T2TEXT, TXT_T3TEXT, TXT_T4TEXT, TXT_T5TEXT, TXT_T6TEXT, TXT_CC_ZOMBIE, TXT_CC_SHOTGUN, TXT_CC_HEAVY, TXT_CC_IMP, TXT_CC_DEMON, TXT_CC_LOST, TXT_CC_CACO, TXT_CC_HELL, TXT_CC_BARON, TXT_CC_ARACH, TXT_CC_PAIN, TXT_CC_REVEN, TXT_CC_MANCU, TXT_CC_ARCH, TXT_CC_SPIDER, TXT_CC_CYBER, TXT_CC_HERO, TXT_QUITMESSAGE1, TXT_QUITMESSAGE2, TXT_QUITMESSAGE3, TXT_QUITMESSAGE4, TXT_QUITMESSAGE5, TXT_QUITMESSAGE6, TXT_QUITMESSAGE7, TXT_QUITMESSAGE8, TXT_QUITMESSAGE9, TXT_QUITMESSAGE10, TXT_QUITMESSAGE11, TXT_QUITMESSAGE12, TXT_QUITMESSAGE13, TXT_QUITMESSAGE14, TXT_QUITMESSAGE15, TXT_QUITMESSAGE16, TXT_QUITMESSAGE17, TXT_QUITMESSAGE18, TXT_QUITMESSAGE19, TXT_QUITMESSAGE20, TXT_QUITMESSAGE21, TXT_QUITMESSAGE22, TXT_JOINNET, TXT_SAVENET, TXT_CLNETLOAD, TXT_LOADMISSING, TXT_FINALEFLAT_E1, TXT_FINALEFLAT_E2, TXT_FINALEFLAT_E3, TXT_FINALEFLAT_E4, TXT_FINALEFLAT_C2, TXT_FINALEFLAT_C1, TXT_FINALEFLAT_C3, TXT_FINALEFLAT_C4, TXT_FINALEFLAT_C5, TXT_FINALEFLAT_C6, TXT_ASK_EPISODE, TXT_EPISODE1, TXT_EPISODE2, TXT_EPISODE3, TXT_EPISODE4, TXT_KILLMSG_SUICIDE, TXT_KILLMSG_WEAPON0, TXT_KILLMSG_PISTOL, TXT_KILLMSG_SHOTGUN, TXT_KILLMSG_CHAINGUN, TXT_KILLMSG_MISSILE, TXT_KILLMSG_PLASMA, TXT_KILLMSG_BFG, TXT_KILLMSG_CHAINSAW, TXT_KILLMSG_SUPERSHOTGUN, TXT_KILLMSG_STOMP, TXT_AMSTR_ROTATEON, TXT_AMSTR_ROTATEOFF, TXT_WEAPON1, TXT_WEAPON2, TXT_WEAPON3, TXT_WEAPON4, TXT_WEAPON5, TXT_WEAPON6, TXT_WEAPON7, TXT_WEAPON8, TXT_WEAPON9, TXT_SKILL1, TXT_SKILL2, TXT_SKILL3, TXT_SKILL4, TXT_SKILL5, TXT_KEY1, TXT_KEY2, TXT_KEY3, TXT_KEY4, TXT_KEY5, TXT_KEY6, TXT_SAVEOUTMAP, TXT_ENDNOGAME, TXT_SUICIDEOUTMAP, TXT_SUICIDEASK, TXT_PICKGAMETYPE, TXT_SINGLEPLAYER, TXT_MULTIPLAYER, TXT_NOTDESIGNEDFOR, TXT_GAMESETUP, TXT_PLAYERSETUP, NUMTEXT } textenum_t; // Sounds. typedef enum { SFX_NONE, SFX_PISTOL, SFX_SHOTGN, SFX_SGCOCK, SFX_DSHTGN, SFX_DBOPN, SFX_DBCLS, SFX_DBLOAD, SFX_PLASMA, SFX_BFG, SFX_SAWUP, SFX_SAWIDL, SFX_SAWFUL, SFX_SAWHIT, SFX_RLAUNC, SFX_RXPLOD, SFX_FIRSHT, SFX_FIRXPL, SFX_PSTART, SFX_PSTOP, SFX_DOROPN, SFX_DORCLS, SFX_STNMOV, SFX_SWTCHN, SFX_SWTCHX, SFX_PLPAIN, SFX_DMPAIN, SFX_POPAIN, SFX_VIPAIN, SFX_MNPAIN, SFX_PEPAIN, SFX_SLOP, SFX_ITEMUP, SFX_WPNUP, SFX_OOF, SFX_TELEPT, SFX_POSIT1, SFX_POSIT2, SFX_POSIT3, SFX_BGSIT1, SFX_BGSIT2, SFX_SGTSIT, SFX_CACSIT, SFX_BRSSIT, SFX_CYBSIT, SFX_SPISIT, SFX_BSPSIT, SFX_KNTSIT, SFX_VILSIT, SFX_MANSIT, SFX_PESIT, SFX_SKLATK, SFX_SGTATK, SFX_SKEPCH, SFX_VILATK, SFX_CLAW, SFX_SKESWG, SFX_PLDETH, SFX_PDIEHI, SFX_PODTH1, SFX_PODTH2, SFX_PODTH3, SFX_BGDTH1, SFX_BGDTH2, SFX_SGTDTH, SFX_CACDTH, SFX_SKLDTH, SFX_BRSDTH, SFX_CYBDTH, SFX_SPIDTH, SFX_BSPDTH, SFX_VILDTH, SFX_KNTDTH, SFX_PEDTH, SFX_SKEDTH, SFX_POSACT, SFX_BGACT, SFX_DMACT, SFX_BSPACT, SFX_BSPWLK, SFX_VILACT, SFX_NOWAY, SFX_BAREXP, SFX_PUNCH, SFX_HOOF, SFX_METAL, SFX_CHGUN, SFX_TINK, SFX_BDOPN, SFX_BDCLS, SFX_ITMBK, SFX_FLAME, SFX_FLAMST, SFX_GETPOW, SFX_BOSPIT, SFX_BOSCUB, SFX_BOSSIT, SFX_BOSPN, SFX_BOSDTH, SFX_MANATK, SFX_MANDTH, SFX_SSSIT, SFX_SSDTH, SFX_KEENPN, SFX_KEENDT, SFX_SKEACT, SFX_SKESIT, SFX_SKEATK, SFX_RADIO, SFX_SECRET, NUMSFX } sfxenum_t; /** * Music. * These ids are no longer used. All tracks are played by ident. typedef enum { MUS_NONE, MUS_E1M1, MUS_E1M2, MUS_E1M3, MUS_E1M4, MUS_E1M5, MUS_E1M6, MUS_E1M7, MUS_E1M8, MUS_E1M9, MUS_E2M1, MUS_E2M2, MUS_E2M3, MUS_E2M4, MUS_E2M5, MUS_E2M6, MUS_E2M7, MUS_E2M8, MUS_E2M9, MUS_E3M1, MUS_E3M2, MUS_E3M3, MUS_E3M4, MUS_E3M5, MUS_E3M6, MUS_E3M7, MUS_E3M8, MUS_E3M9, MUS_INTER, MUS_INTRO, MUS_BUNNY, MUS_VICTOR, MUS_INTROA, MUS_RUNNIN, MUS_STALKS, MUS_COUNTD, MUS_BETWEE, MUS_DOOM, MUS_THE_DA, MUS_SHAWN, MUS_DDTBLU, MUS_IN_CIT, MUS_DEAD, MUS_STLKS2, MUS_THEDA2, MUS_DOOM2, MUS_DDTBL2, MUS_RUNNI2, MUS_DEAD2, MUS_STLKS3, MUS_ROMERO, MUS_SHAWN2, MUS_MESSAG, MUS_COUNT2, MUS_DDTBL3, MUS_AMPIE, MUS_THEDA3, MUS_ADRIAN, MUS_MESSG2, MUS_ROMER2, MUS_TENSE, MUS_SHAWN3, MUS_OPENIN, MUS_EVIL, MUS_ULTIMA, MUS_READ_M, MUS_DM2TTL, MUS_DM2INT, NUMMUSIC } musicenum_t; */ #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/st_stuff.h0000644000175000017500000000363311357170242023314 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.h: Statusbar code jDoom - specific. * * Does the face/direction indicator animatin. * Does palette indicators as well (red pain/berserk, bright pickup) */ #ifndef __ST_STUFF_H__ #define __ST_STUFF_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #define ST_HEIGHT (32 * SCREEN_MUL) #define ST_WIDTH (SCREENWIDTH) #define ST_Y (SCREENHEIGHT - ST_HEIGHT) // Called by startup code. void ST_Register(void); void ST_Init(void); // Called by main loop. void ST_Ticker(void); // Called by main loop. void ST_Drawer(int player, int mode, boolean refresh); // Called when the console player is spawned on each map. void ST_Start(int player); void ST_Stop(int player); // Called when it might be neccessary for the hud to unhide. void ST_HUDUnHide(int player, hueevent_t event); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_lights.h0000644000175000017500000000521711357170242023270 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.h: Handle Sector base lighting effects. */ #ifndef __P_LIGHTS_H__ #define __P_LIGHTS_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #define GLOWSPEED (8) #define STROBEBRIGHT (5) #define FASTDARK (15) #define SLOWDARK (35) typedef struct { thinker_t thinker; sector_t* sector; int count; float maxLight; float minLight; } fireflicker_t; typedef struct { thinker_t thinker; sector_t* sector; int count; float maxLight; float minLight; int maxTime; int minTime; } lightflash_t; typedef struct { thinker_t thinker; sector_t* sector; int count; float minLight; float maxLight; int darkTime; int brightTime; } strobe_t; typedef struct { thinker_t thinker; sector_t* sector; float minLight; float maxLight; int direction; } glow_t; void T_FireFlicker(fireflicker_t* flick); void P_SpawnFireFlicker(sector_t* sector); void T_LightFlash(lightflash_t* flash); void P_SpawnLightFlash(sector_t* sector); void T_StrobeFlash(strobe_t* flash); void P_SpawnStrobeFlash(sector_t* sector, int fastOrSlow, int inSync); void T_Glow(glow_t* g); void P_SpawnGlowingLight(sector_t* sector); void EV_StartLightStrobing(linedef_t* line); void EV_TurnTagLightsOff(linedef_t* line); void EV_LightTurnOn(linedef_t* line, float bright); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_api.h0000644000175000017500000000253511357170242022533 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_api.h: Doomsday API setup and interaction - jDoom specific. */ #ifndef __D_API_H__ #define __D_API_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "dd_api.h" extern game_import_t gi; extern game_export_t gx; int G_GetInteger(int id); void *G_GetVariable(int id); game_export_t *GetGameAPI(game_import_t *imports); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_sound.h0000644000175000017500000000245311357170242023125 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sound.h: */ #ifndef __P_SOUND_H__ #define __P_SOUND_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "doomsday.h" typedef enum { SORG_CENTER, SORG_FLOOR, SORG_CEILING } sectorsoundorigin_t; void S_MapMusic(uint episode, uint map); void S_SectorSound(sector_t* sec, sectorsoundorigin_t origin, int id); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/mn_def.h0000644000175000017500000000704511357170242022710 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * mn_def.h: Menu defines and types. */ #ifndef __MENU_DEFS_H__ #define __MENU_DEFS_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "hu_stuff.h" #include "r_defs.h" #include "m_defs.h" // Macros #define LEFT_DIR 0 #define RIGHT_DIR 1 #define DIR_MASK 0x1 #define ITEM_HEIGHT 20 #define SLOTTEXTLEN 16 #define ASCII_CURSOR '[' #define LINEHEIGHT 16 #define LINEHEIGHT_B 15 #define LINEHEIGHT_A 8 #define MENUCURSOR_OFFSET_X -6 #define MENUCURSOR_OFFSET_Y -1 #define MENUCURSOR_TICSPERFRAME 8 #define CURSORPREF "M_SKULL%d" #define SKULLBASELMP "M_SKL00" #define NUMCURSORS 2 #define NUMSAVESLOTS 8 #define MAX_EDIT_LEN 256 typedef struct { char text[MAX_EDIT_LEN]; char oldtext[MAX_EDIT_LEN]; // If the current edit is canceled... int firstVisible; } editfield_t; typedef enum { MENU_MAIN, MENU_NEWGAME, MENU_EPISODE, MENU_SKILL, MENU_OPTIONS, MENU_OPTIONS2, MENU_GAMEPLAY, MENU_HUD, MENU_MAP, MENU_LOAD, MENU_SAVE, MENU_MULTIPLAYER, MENU_GAMESETUP, MENU_PLAYERSETUP, MENU_WEAPONS, MENU_CONTROLS, MENU_NONE } menutype_t; extern int menuTime; extern boolean shiftdown; extern menu_t* currentMenu; extern short itemOn; extern menu_t MapDef; // Multiplayer menus. extern menu_t MultiplayerMenu; extern menu_t GameSetupMenu; extern menu_t PlayerSetupMenu; void M_DrawTitle(char* text, int y); void M_WriteMenuText(const menu_t* menu, int index, const char* text); // Color widget. void DrawColorWidget(); void SCColorWidget(int index, void* data); void M_WGCurrentColor(int option, void* data); void M_DrawSaveLoadBorder(int x, int y, int width); void M_SetupNextMenu(menu_t* menu); void M_DrawThermo(int x, int y, int thermWidth, int thermDot); void MN_DrawSlider(const menu_t* menu, int item, int width, int slot); void MN_DrawColorBox(const menu_t* menu, int index, float r, float g, float b, float a); void M_StartControlPanel(void); void M_FloatMod10(float* variable, int option); void SCEnterMultiplayerMenu(int option, void* data); void MN_TickerEx(void); // The extended ticker. void M_ToggleVar(int option, void* context); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/m_cheat.h0000644000175000017500000000224111357170242023051 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef M_CHEAT #define M_CHEAT #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif void Cht_Init(void); #endif /* M_CHEAT */ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_englsh.h0000644000175000017500000004174211357170242023245 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_englsh.h: Printed strings for translation (native is English). */ #ifndef __D_ENGLSH_H__ #define __D_ENGLSH_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #define GET_TXT(x) ((*gi.text)[x].text) #define D_DEVSTR GET_TXT(TXT_D_DEVSTR) #define D_CDROM GET_TXT(TXT_D_CDROM) #define PRESSKEY GET_TXT(TXT_PRESSKEY) #define PRESSYN GET_TXT(TXT_PRESSYN) #define QUITMSG GET_TXT(TXT_QUITMSG) #define LOADNET GET_TXT(TXT_LOADNET) #define QLOADNET GET_TXT(TXT_QLOADNET) #define QSAVESPOT GET_TXT(TXT_QSAVESPOT) #define SAVEDEAD GET_TXT(TXT_SAVEDEAD) #define SAVEOUTMAP GET_TXT(TXT_SAVEOUTMAP) #define SAVENET GET_TXT(TXT_SAVENET) #define QSPROMPT GET_TXT(TXT_QSPROMPT) #define QLPROMPT GET_TXT(TXT_QLPROMPT) #define NEWGAME GET_TXT(TXT_NEWGAME) #define NIGHTMARE GET_TXT(TXT_NIGHTMARE) #define SWSTRING GET_TXT(TXT_SWSTRING) #define MSGOFF GET_TXT(TXT_MSGOFF) #define MSGON GET_TXT(TXT_MSGON) #define NETEND GET_TXT(TXT_NETEND) #define ENDGAME GET_TXT(TXT_ENDGAME) #define ENDNOGAME GET_TXT(TXT_ENDNOGAME) #define SUICIDEOUTMAP GET_TXT(TXT_SUICIDEOUTMAP) #define SUICIDEASK GET_TXT(TXT_SUICIDEASK) #define DOSY GET_TXT(TXT_DOSY) #define DETAILHI GET_TXT(TXT_DETAILHI) #define DETAILLO GET_TXT(TXT_DETAILLO) #define GAMMALVL0 GET_TXT(TXT_GAMMALVL0) #define GAMMALVL1 GET_TXT(TXT_GAMMALVL1) #define GAMMALVL2 GET_TXT(TXT_GAMMALVL2) #define GAMMALVL3 GET_TXT(TXT_GAMMALVL3) #define GAMMALVL4 GET_TXT(TXT_GAMMALVL4) #define EMPTYSTRING GET_TXT(TXT_EMPTYSTRING) #define GOTARMOR GET_TXT(TXT_GOTARMOR) #define GOTMEGA GET_TXT(TXT_GOTMEGA) #define GOTHTHBONUS GET_TXT(TXT_GOTHTHBONUS) #define GOTARMBONUS GET_TXT(TXT_GOTARMBONUS) #define GOTSTIM GET_TXT(TXT_GOTSTIM) #define GOTMEDINEED GET_TXT(TXT_GOTMEDINEED) #define GOTMEDIKIT GET_TXT(TXT_GOTMEDIKIT) #define GOTSUPER GET_TXT(TXT_GOTSUPER) #define GOTBLUECARD GET_TXT(TXT_GOTBLUECARD) #define GOTYELWCARD GET_TXT(TXT_GOTYELWCARD) #define GOTREDCARD GET_TXT(TXT_GOTREDCARD) #define GOTBLUESKUL GET_TXT(TXT_GOTBLUESKUL) #define GOTYELWSKUL GET_TXT(TXT_GOTYELWSKUL) #define GOTREDSKULL GET_TXT(TXT_GOTREDSKULL) #define GOTINVUL GET_TXT(TXT_GOTINVUL) #define GOTBERSERK GET_TXT(TXT_GOTBERSERK) #define GOTINVIS GET_TXT(TXT_GOTINVIS) #define GOTSUIT GET_TXT(TXT_GOTSUIT) #define GOTMAP GET_TXT(TXT_GOTMAP) #define GOTVISOR GET_TXT(TXT_GOTVISOR) #define GOTMSPHERE GET_TXT(TXT_GOTMSPHERE) #define GOTCLIP GET_TXT(TXT_GOTCLIP) #define GOTCLIPBOX GET_TXT(TXT_GOTCLIPBOX) #define GOTROCKET GET_TXT(TXT_GOTROCKET) #define GOTROCKBOX GET_TXT(TXT_GOTROCKBOX) #define GOTCELL GET_TXT(TXT_GOTCELL) #define GOTCELLBOX GET_TXT(TXT_GOTCELLBOX) #define GOTSHELLS GET_TXT(TXT_GOTSHELLS) #define GOTSHELLBOX GET_TXT(TXT_GOTSHELLBOX) #define GOTBACKPACK GET_TXT(TXT_GOTBACKPACK) #define GOTBFG9000 GET_TXT(TXT_GOTBFG9000) #define GOTCHAINGUN GET_TXT(TXT_GOTCHAINGUN) #define GOTCHAINSAW GET_TXT(TXT_GOTCHAINSAW) #define GOTLAUNCHER GET_TXT(TXT_GOTLAUNCHER) #define GOTPLASMA GET_TXT(TXT_GOTPLASMA) #define GOTSHOTGUN GET_TXT(TXT_GOTSHOTGUN) #define GOTSHOTGUN2 GET_TXT(TXT_GOTSHOTGUN2) #define PD_BLUEO GET_TXT(TXT_PD_BLUEO) #define PD_REDO GET_TXT(TXT_PD_REDO) #define PD_YELLOWO GET_TXT(TXT_PD_YELLOWO) #define PD_BLUEK GET_TXT(TXT_PD_BLUEK) #define PD_REDK GET_TXT(TXT_PD_REDK) #define PD_YELLOWK GET_TXT(TXT_PD_YELLOWK) #define TXT_GAMESAVED GET_TXT(TXT_GGSAVED) #define HUSTR_MSGU GET_TXT(TXT_HUSTR_MSGU) #define HUSTR_E1M1 GET_TXT(TXT_HUSTR_E1M1) #define HUSTR_E1M2 GET_TXT(TXT_HUSTR_E1M2) #define HUSTR_E1M3 GET_TXT(TXT_HUSTR_E1M3) #define HUSTR_E1M4 GET_TXT(TXT_HUSTR_E1M4) #define HUSTR_E1M5 GET_TXT(TXT_HUSTR_E1M5) #define HUSTR_E1M6 GET_TXT(TXT_HUSTR_E1M6) #define HUSTR_E1M7 GET_TXT(TXT_HUSTR_E1M7) #define HUSTR_E1M8 GET_TXT(TXT_HUSTR_E1M8) #define HUSTR_E1M9 GET_TXT(TXT_HUSTR_E1M9) #define HUSTR_E2M1 GET_TXT(TXT_HUSTR_E2M1) #define HUSTR_E2M2 GET_TXT(TXT_HUSTR_E2M2) #define HUSTR_E2M3 GET_TXT(TXT_HUSTR_E2M3) #define HUSTR_E2M4 GET_TXT(TXT_HUSTR_E2M4) #define HUSTR_E2M5 GET_TXT(TXT_HUSTR_E2M5) #define HUSTR_E2M6 GET_TXT(TXT_HUSTR_E2M6) #define HUSTR_E2M7 GET_TXT(TXT_HUSTR_E2M7) #define HUSTR_E2M8 GET_TXT(TXT_HUSTR_E2M8) #define HUSTR_E2M9 GET_TXT(TXT_HUSTR_E2M9) #define HUSTR_E3M1 GET_TXT(TXT_HUSTR_E3M1) #define HUSTR_E3M2 GET_TXT(TXT_HUSTR_E3M2) #define HUSTR_E3M3 GET_TXT(TXT_HUSTR_E3M3) #define HUSTR_E3M4 GET_TXT(TXT_HUSTR_E3M4) #define HUSTR_E3M5 GET_TXT(TXT_HUSTR_E3M5) #define HUSTR_E3M6 GET_TXT(TXT_HUSTR_E3M6) #define HUSTR_E3M7 GET_TXT(TXT_HUSTR_E3M7) #define HUSTR_E3M8 GET_TXT(TXT_HUSTR_E3M8) #define HUSTR_E3M9 GET_TXT(TXT_HUSTR_E3M9) #define HUSTR_E4M1 GET_TXT(TXT_HUSTR_E4M1) #define HUSTR_E4M2 GET_TXT(TXT_HUSTR_E4M2) #define HUSTR_E4M3 GET_TXT(TXT_HUSTR_E4M3) #define HUSTR_E4M4 GET_TXT(TXT_HUSTR_E4M4) #define HUSTR_E4M5 GET_TXT(TXT_HUSTR_E4M5) #define HUSTR_E4M6 GET_TXT(TXT_HUSTR_E4M6) #define HUSTR_E4M7 GET_TXT(TXT_HUSTR_E4M7) #define HUSTR_E4M8 GET_TXT(TXT_HUSTR_E4M8) #define HUSTR_E4M9 GET_TXT(TXT_HUSTR_E4M9) #define HUSTR_1 GET_TXT(TXT_HUSTR_1) #define HUSTR_2 GET_TXT(TXT_HUSTR_2) #define HUSTR_3 GET_TXT(TXT_HUSTR_3) #define HUSTR_4 GET_TXT(TXT_HUSTR_4) #define HUSTR_5 GET_TXT(TXT_HUSTR_5) #define HUSTR_6 GET_TXT(TXT_HUSTR_6) #define HUSTR_7 GET_TXT(TXT_HUSTR_7) #define HUSTR_8 GET_TXT(TXT_HUSTR_8) #define HUSTR_9 GET_TXT(TXT_HUSTR_9) #define HUSTR_10 GET_TXT(TXT_HUSTR_10) #define HUSTR_11 GET_TXT(TXT_HUSTR_11) #define HUSTR_12 GET_TXT(TXT_HUSTR_12) #define HUSTR_13 GET_TXT(TXT_HUSTR_13) #define HUSTR_14 GET_TXT(TXT_HUSTR_14) #define HUSTR_15 GET_TXT(TXT_HUSTR_15) #define HUSTR_16 GET_TXT(TXT_HUSTR_16) #define HUSTR_17 GET_TXT(TXT_HUSTR_17) #define HUSTR_18 GET_TXT(TXT_HUSTR_18) #define HUSTR_19 GET_TXT(TXT_HUSTR_19) #define HUSTR_20 GET_TXT(TXT_HUSTR_20) #define HUSTR_21 GET_TXT(TXT_HUSTR_21) #define HUSTR_22 GET_TXT(TXT_HUSTR_22) #define HUSTR_23 GET_TXT(TXT_HUSTR_23) #define HUSTR_24 GET_TXT(TXT_HUSTR_24) #define HUSTR_25 GET_TXT(TXT_HUSTR_25) #define HUSTR_26 GET_TXT(TXT_HUSTR_26) #define HUSTR_27 GET_TXT(TXT_HUSTR_27) #define HUSTR_28 GET_TXT(TXT_HUSTR_28) #define HUSTR_29 GET_TXT(TXT_HUSTR_29) #define HUSTR_30 GET_TXT(TXT_HUSTR_30) #define HUSTR_31 GET_TXT(TXT_HUSTR_31) #define HUSTR_32 GET_TXT(TXT_HUSTR_32) #define PHUSTR_1 GET_TXT(TXT_PHUSTR_1) #define PHUSTR_2 GET_TXT(TXT_PHUSTR_2) #define PHUSTR_3 GET_TXT(TXT_PHUSTR_3) #define PHUSTR_4 GET_TXT(TXT_PHUSTR_4) #define PHUSTR_5 GET_TXT(TXT_PHUSTR_5) #define PHUSTR_6 GET_TXT(TXT_PHUSTR_6) #define PHUSTR_7 GET_TXT(TXT_PHUSTR_7) #define PHUSTR_8 GET_TXT(TXT_PHUSTR_8) #define PHUSTR_9 GET_TXT(TXT_PHUSTR_9) #define PHUSTR_10 GET_TXT(TXT_PHUSTR_10) #define PHUSTR_11 GET_TXT(TXT_PHUSTR_11) #define PHUSTR_12 GET_TXT(TXT_PHUSTR_12) #define PHUSTR_13 GET_TXT(TXT_PHUSTR_13) #define PHUSTR_14 GET_TXT(TXT_PHUSTR_14) #define PHUSTR_15 GET_TXT(TXT_PHUSTR_15) #define PHUSTR_16 GET_TXT(TXT_PHUSTR_16) #define PHUSTR_17 GET_TXT(TXT_PHUSTR_17) #define PHUSTR_18 GET_TXT(TXT_PHUSTR_18) #define PHUSTR_19 GET_TXT(TXT_PHUSTR_19) #define PHUSTR_20 GET_TXT(TXT_PHUSTR_20) #define PHUSTR_21 GET_TXT(TXT_PHUSTR_21) #define PHUSTR_22 GET_TXT(TXT_PHUSTR_22) #define PHUSTR_23 GET_TXT(TXT_PHUSTR_23) #define PHUSTR_24 GET_TXT(TXT_PHUSTR_24) #define PHUSTR_25 GET_TXT(TXT_PHUSTR_25) #define PHUSTR_26 GET_TXT(TXT_PHUSTR_26) #define PHUSTR_27 GET_TXT(TXT_PHUSTR_27) #define PHUSTR_28 GET_TXT(TXT_PHUSTR_28) #define PHUSTR_29 GET_TXT(TXT_PHUSTR_29) #define PHUSTR_30 GET_TXT(TXT_PHUSTR_30) #define PHUSTR_31 GET_TXT(TXT_PHUSTR_31) #define PHUSTR_32 GET_TXT(TXT_PHUSTR_32) #define THUSTR_1 GET_TXT(TXT_THUSTR_1) #define THUSTR_2 GET_TXT(TXT_THUSTR_2) #define THUSTR_3 GET_TXT(TXT_THUSTR_3) #define THUSTR_4 GET_TXT(TXT_THUSTR_4) #define THUSTR_5 GET_TXT(TXT_THUSTR_5) #define THUSTR_6 GET_TXT(TXT_THUSTR_6) #define THUSTR_7 GET_TXT(TXT_THUSTR_7) #define THUSTR_8 GET_TXT(TXT_THUSTR_8) #define THUSTR_9 GET_TXT(TXT_THUSTR_9) #define THUSTR_10 GET_TXT(TXT_THUSTR_10) #define THUSTR_11 GET_TXT(TXT_THUSTR_11) #define THUSTR_12 GET_TXT(TXT_THUSTR_12) #define THUSTR_13 GET_TXT(TXT_THUSTR_13) #define THUSTR_14 GET_TXT(TXT_THUSTR_14) #define THUSTR_15 GET_TXT(TXT_THUSTR_15) #define THUSTR_16 GET_TXT(TXT_THUSTR_16) #define THUSTR_17 GET_TXT(TXT_THUSTR_17) #define THUSTR_18 GET_TXT(TXT_THUSTR_18) #define THUSTR_19 GET_TXT(TXT_THUSTR_19) #define THUSTR_20 GET_TXT(TXT_THUSTR_20) #define THUSTR_21 GET_TXT(TXT_THUSTR_21) #define THUSTR_22 GET_TXT(TXT_THUSTR_22) #define THUSTR_23 GET_TXT(TXT_THUSTR_23) #define THUSTR_24 GET_TXT(TXT_THUSTR_24) #define THUSTR_25 GET_TXT(TXT_THUSTR_25) #define THUSTR_26 GET_TXT(TXT_THUSTR_26) #define THUSTR_27 GET_TXT(TXT_THUSTR_27) #define THUSTR_28 GET_TXT(TXT_THUSTR_28) #define THUSTR_29 GET_TXT(TXT_THUSTR_29) #define THUSTR_30 GET_TXT(TXT_THUSTR_30) #define THUSTR_31 GET_TXT(TXT_THUSTR_31) #define THUSTR_32 GET_TXT(TXT_THUSTR_32) #define HUSTR_CHATMACRO1 GET_TXT(TXT_HUSTR_CHATMACRO1) #define HUSTR_CHATMACRO2 GET_TXT(TXT_HUSTR_CHATMACRO2) #define HUSTR_CHATMACRO3 GET_TXT(TXT_HUSTR_CHATMACRO3) #define HUSTR_CHATMACRO4 GET_TXT(TXT_HUSTR_CHATMACRO4) #define HUSTR_CHATMACRO5 GET_TXT(TXT_HUSTR_CHATMACRO5) #define HUSTR_CHATMACRO6 GET_TXT(TXT_HUSTR_CHATMACRO6) #define HUSTR_CHATMACRO7 GET_TXT(TXT_HUSTR_CHATMACRO7) #define HUSTR_CHATMACRO8 GET_TXT(TXT_HUSTR_CHATMACRO8) #define HUSTR_CHATMACRO9 GET_TXT(TXT_HUSTR_CHATMACRO9) #define HUSTR_CHATMACRO0 GET_TXT(TXT_HUSTR_CHATMACRO0) #define HUSTR_TALKTOSELF1 GET_TXT(TXT_HUSTR_TALKTOSELF1) #define HUSTR_TALKTOSELF2 GET_TXT(TXT_HUSTR_TALKTOSELF2) #define HUSTR_TALKTOSELF3 GET_TXT(TXT_HUSTR_TALKTOSELF3) #define HUSTR_TALKTOSELF4 GET_TXT(TXT_HUSTR_TALKTOSELF4) #define HUSTR_TALKTOSELF5 GET_TXT(TXT_HUSTR_TALKTOSELF5) #define HUSTR_MESSAGESENT GET_TXT(TXT_HUSTR_MESSAGESENT) /** * The following should NOT be changed unless it seems just AWFULLY * necessary! */ #define HUSTR_PLRGREEN GET_TXT(TXT_HUSTR_PLRGREEN) #define HUSTR_PLRINDIGO GET_TXT(TXT_HUSTR_PLRINDIGO) #define HUSTR_PLRBROWN GET_TXT(TXT_HUSTR_PLRBROWN) #define HUSTR_PLRRED GET_TXT(TXT_HUSTR_PLRRED) //// \fixme What are these doing here?? #define HUSTR_KEYGREEN 'g' #define HUSTR_KEYINDIGO 'i' #define HUSTR_KEYBROWN 'b' #define HUSTR_KEYRED 'r' #define AMSTR_FOLLOWON GET_TXT(TXT_AMSTR_FOLLOWON) #define AMSTR_FOLLOWOFF GET_TXT(TXT_AMSTR_FOLLOWOFF) #define AMSTR_ROTATEON GET_TXT(TXT_AMSTR_ROTATEON) #define AMSTR_ROTATEOFF GET_TXT(TXT_AMSTR_ROTATEOFF) #define AMSTR_GRIDON GET_TXT(TXT_AMSTR_GRIDON) #define AMSTR_GRIDOFF GET_TXT(TXT_AMSTR_GRIDOFF) #define AMSTR_MARKEDSPOT GET_TXT(TXT_AMSTR_MARKEDSPOT) #define AMSTR_MARKSCLEARED GET_TXT(TXT_AMSTR_MARKSCLEARED) // Key names: #define KEY1 GET_TXT(TXT_KEY1) #define KEY2 GET_TXT(TXT_KEY2) #define KEY3 GET_TXT(TXT_KEY3) #define KEY4 GET_TXT(TXT_KEY4) #define KEY5 GET_TXT(TXT_KEY5) #define KEY6 GET_TXT(TXT_KEY6) // Weapon names: #define WEAPON1 GET_TXT(TXT_WEAPON1) #define WEAPON2 GET_TXT(TXT_WEAPON2) #define WEAPON3 GET_TXT(TXT_WEAPON3) #define WEAPON4 GET_TXT(TXT_WEAPON4) #define WEAPON5 GET_TXT(TXT_WEAPON5) #define WEAPON6 GET_TXT(TXT_WEAPON6) #define WEAPON7 GET_TXT(TXT_WEAPON7) #define WEAPON8 GET_TXT(TXT_WEAPON8) #define WEAPON9 GET_TXT(TXT_WEAPON9) #define STSTR_MUS GET_TXT(TXT_STSTR_MUS) #define STSTR_NOMUS GET_TXT(TXT_STSTR_NOMUS) #define STSTR_DQDON GET_TXT(TXT_STSTR_DQDON) #define STSTR_DQDOFF GET_TXT(TXT_STSTR_DQDOFF) #define STSTR_KFAADDED GET_TXT(TXT_STSTR_KFAADDED) #define STSTR_FAADDED GET_TXT(TXT_STSTR_FAADDED) #define STSTR_NCON GET_TXT(TXT_STSTR_NCON) #define STSTR_NCOFF GET_TXT(TXT_STSTR_NCOFF) #define STSTR_BEHOLD GET_TXT(TXT_STSTR_BEHOLD) #define STSTR_BEHOLDX GET_TXT(TXT_STSTR_BEHOLDX) #define STSTR_CHOPPERS GET_TXT(TXT_STSTR_CHOPPERS) #define STSTR_CLEV GET_TXT(TXT_STSTR_CLEV) #define E1TEXT GET_TXT(TXT_E1TEXT) #define E2TEXT GET_TXT(TXT_E2TEXT) #define E3TEXT GET_TXT(TXT_E3TEXT) #define E4TEXT GET_TXT(TXT_E4TEXT) // After level 6, put this: #define C1TEXT GET_TXT(TXT_C1TEXT) // After level 11, put this: #define C2TEXT GET_TXT(TXT_C2TEXT) // After level 20, put this: #define C3TEXT GET_TXT(TXT_C3TEXT) // After level 29, put this: #define C4TEXT GET_TXT(TXT_C4TEXT) // Before level 31, put this: #define C5TEXT GET_TXT(TXT_C5TEXT) // Before level 32, put this: #define C6TEXT GET_TXT(TXT_C6TEXT) // After map 06: #define P1TEXT GET_TXT(TXT_P1TEXT) // After map 11: #define P2TEXT GET_TXT(TXT_P2TEXT) // After map 20: #define P3TEXT GET_TXT(TXT_P3TEXT) // After map 30: #define P4TEXT GET_TXT(TXT_P4TEXT) // Before map 31: #define P5TEXT GET_TXT(TXT_P5TEXT) // Before map 32: #define P6TEXT GET_TXT(TXT_P6TEXT) #define T1TEXT GET_TXT(TXT_T1TEXT) #define T2TEXT GET_TXT(TXT_T2TEXT) #define T3TEXT GET_TXT(TXT_T3TEXT) #define T4TEXT GET_TXT(TXT_T4TEXT) #define T5TEXT GET_TXT(TXT_T5TEXT) #define T6TEXT GET_TXT(TXT_T6TEXT) #define CC_ZOMBIE GET_TXT(TXT_CC_ZOMBIE) #define CC_SHOTGUN GET_TXT(TXT_CC_SHOTGUN) #define CC_HEAVY GET_TXT(TXT_CC_HEAVY) #define CC_IMP GET_TXT(TXT_CC_IMP) #define CC_DEMON GET_TXT(TXT_CC_DEMON) #define CC_LOST GET_TXT(TXT_CC_LOST) #define CC_CACO GET_TXT(TXT_CC_CACO) #define CC_HELL GET_TXT(TXT_CC_HELL) #define CC_BARON GET_TXT(TXT_CC_BARON) #define CC_ARACH GET_TXT(TXT_CC_ARACH) #define CC_PAIN GET_TXT(TXT_CC_PAIN) #define CC_REVEN GET_TXT(TXT_CC_REVEN) #define CC_MANCU GET_TXT(TXT_CC_MANCU) #define CC_ARCH GET_TXT(TXT_CC_ARCH) #define CC_SPIDER GET_TXT(TXT_CC_SPIDER) #define CC_CYBER GET_TXT(TXT_CC_CYBER) #define CC_HERO GET_TXT(TXT_CC_HERO) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/g_ctrl.h0000644000175000017500000000224411357170242022726 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.h: Player control setup. */ #ifndef __G_CTRL_H__ #define __G_CTRL_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif void G_RegisterPlayerControls(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_pspr.h0000644000175000017500000000325211357170242022757 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.h: Sprite animation. */ #ifndef __P_PSPR__ #define __P_PSPR__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "tables.h" #include "info.h" #ifdef __GNUG__ #pragma interface #endif /** * Overlay psprites are scaled shapes drawn directly on the viewscreen, * coordinates are in virtual, [320 x 200] viewscreen-space. */ typedef enum { ps_weapon, ps_flash, NUMPSPRITES } psprnum_t; typedef struct { state_t* state; // A NULL state means not active. int tics; float pos[2]; // [x, y]. } pspdef_t; void R_GetWeaponBob(int player, float* x, float* y); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/dstrings.h0000644000175000017500000000267611357170242023322 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2007 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dstrings.h: */ #ifndef __DSTRINGS_H__ #define __DSTRINGS_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif // All important printed strings. #include "d_englsh.h" /** * File locations, relative to the base directory. */ #define DEVMAPS "devmaps" #define DEVDATA "devdata" // QuitDOOM messages: #define NUM_QUITMESSAGES 22 extern char *endmsg[NUM_QUITMESSAGES + 1]; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/version.h0000644000175000017500000000337311357170242023145 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __JDOOM_VERSION_H__ #define __JDOOM_VERSION_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #ifndef JDOOM_VER_ID # ifdef _DEBUG # define JDOOM_VER_ID "+D Doomsday" # else # define JDOOM_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define GAMENAMETEXT "jdoom" // Presented to the user in dialogs, messages etc. #define GAME_NICENAME "jDoom" #define GAME_DETAILS "jDoom is based on linuxdoom-1.10." #define GAME_VERSION_TEXT "1.15.9" #define GAME_VERSION_TEXTLONG "Version" GAME_VERSION_TEXT " " __DATE__ " (" JDOOM_VER_ID ")" #define GAME_VERSION_NUMBER 1,15,9,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_mobj.h0000644000175000017500000002270611357170242022727 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.h: Map Objects, definition and handling. */ #ifndef __P_MOBJ__ #define __P_MOBJ__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "d_think.h" #include "p_terraintype.h" #include "doomdata.h" #include "info.h" #include "tables.h" /** * Mobj flags * * \attention IMPORTANT - Keep this current!!! * LEGEND: * p = Flag is persistent (never changes in-game). * i = Internal use (not to be used in defintions). * * \todo Persistent flags (p) don't need to be included in save games or sent to * clients in netgames. We should collect those in to a const flags setting which * is set only once when the mobj is spawned. * * \todo All flags for internal use only (i) should be put in another var and the * flags removed from those defined in GAME/objects.DED */ // --- mobj.flags --- #define MF_SPECIAL 0x00000001 // Call P_SpecialThing when touched. #define MF_SOLID 0x00000002 // Blocks. #define MF_SHOOTABLE 0x00000004 // Can be hit. #define MF_NOSECTOR 0x00000008 // (p) Don't use the sector links (invisible but touchable). #define MF_NOBLOCKMAP 0x00000010 // (p) Don't use the blocklinks (inert but displayable) #define MF_AMBUSH 0x00000020 // Not to be activated by sound, deaf monster. #define MF_JUSTHIT 0x00000040 // Will try to attack right back. #define MF_JUSTATTACKED 0x00000080 // Will take at least one step before attacking. #define MF_SPAWNCEILING 0x00000100 // (p) Hang from ceiling instead of stand on floor. #define MF_NOGRAVITY 0x00000200 // Don't apply gravity (every tic). // Movement flags. #define MF_DROPOFF 0x00000400 // This allows jumps from high places. #define MF_PICKUP 0x00000800 // For players, will pick up items. #define MF_NOCLIP 0x00001000 // (i) Player cheat. //#define MF_??? 0x00002000 // unused #define MF_FLOAT 0x00004000 // Allow moves to any height, no gravity. #define MF_TELEPORT 0x00008000 // (p) Don't cross lines or look at heights on teleport. #define MF_MISSILE 0x00010000 // Don't hit same species, explode on block. #define MF_DROPPED 0x00020000 // (i) Dropped by a demon, not map spawned. #define MF_SHADOW 0x00040000 // Use fuzzy draw (shadow demons or spectres). #define MF_NOBLOOD 0x00080000 // Don't bleed when shot (use puff). #define MF_CORPSE 0x00100000 // (i) Don't stop moving halfway off a step. #define MF_INFLOAT 0x00200000 // Floating to a height for a move, // don't auto float to target's height. #define MF_COUNTKILL 0x00400000 // count towards intermission kill total #define MF_COUNTITEM 0x00800000 // count towards intermission item total #define MF_SKULLFLY 0x01000000 // (i) skull in flight. #define MF_NOTDMATCH 0x02000000 // (p) not spawned in deathmatch mode (e.g. key cards). #define MF_TRANSLATION 0x0c000000 // (i) if 0x4 0x8 or 0xc, use a translation #define MF_TRANSSHIFT 26 // (N/A) table for player colormaps #define MF_LOCAL 0x10000000 // (p) Won't be sent to clients. #define MF_BRIGHTSHADOW 0x20000000 #define MF_BRIGHTEXPLODE 0x40000000 // Make this brightshadow when exploding. #define MF_VIEWALIGN 0x80000000 /** * The following flags are obsolete in a particular mobj version. * They will automatically be cleared when loading an old save game. */ #define MF_V6OBSOLETE (0x00002000) // (MF_SLIDE) // --- mobj.flags2 --- (added in MOBJ_SAVEVERSION 6) #define MF2_LOGRAV 0x00000001 // alternate gravity setting //#define MF2_WINDTHRUST 0x00000002 // (p) gets pushed around by the wind specials // Not in jDoom since there are no built-in wind specials. #define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor #define MF2_THRUGHOST 0x00000008 // (p) missile will pass through ghosts #define MF2_FLY 0x00000010 // (i) fly mode is active #define MF2_FLOORCLIP 0x00000020 // if feet are allowed to be clipped #define MF2_SPAWNFLOAT 0x00000040 // (p) spawn random float z #define MF2_NOTELEPORT 0x00000080 // does not teleport #define MF2_RIP 0x00000100 // (p) missile rips through solid targets #define MF2_PUSHABLE 0x00000200 // can be pushed by other moving mobjs #define MF2_SLIDE 0x00000400 // slides against walls #define MF2_ALWAYSLIT 0x00000800 #define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, // this flag will allow the mobj to // pass over/under other mobjs. #define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs #define MF2_INFZBOMBDAMAGE 0x00004000 // (p) Don't check z height with radius attacks #define MF2_BOSS 0x00008000 // (p) mobj is a major boss //#define MF2_FIREDAMAGE 0x00010000 // does fire damage - Not in jDoom #define MF2_NODMGTHRUST 0x00020000 // does not thrust target when // damaging #define MF2_TELESTOMP 0x00040000 // mobj can stomp another #define MF2_FLOATBOB 0x00080000 // (p) use float bobbing z movement #define MF2_DONTDRAW 0X00100000 // don't generate a vissprite // --- mobj.flags3 --- #define MF3_NOINFIGHT 0x00000001 // Mobj will never be targeted for in-fighting // --- mobj.intflags --- // Internal mobj flags cannot be set using an external definition. #define MIF_FALLING 0x00000001 // $dropoff_fix: Object is falling from a ledge // For torque simulation: #define OVERDRIVE 6 #define MAXGEAR (OVERDRIVE+16) typedef enum dirtype_s { DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_NODIR, NUMDIRS } dirtype_t; // Map Object definition. typedef struct mobj_s { // Defined in dd_share.h; required mobj elements. DD_BASE_MOBJ_ELEMENTS() // Doom-specific data: mobjinfo_t *info; // &mobjinfo[mobj->type] int damage; // For missiles int flags; int flags2; int flags3; int health; // Movement direction, movement generation (zig-zagging). int moveDir; // 0-7 int moveCount; // when 0, select a new dir // Thing being chased/attacked (or NULL), // also the originator for missiles. struct mobj_s *target; // If >0, the target will be chased // no matter what (even if shot) int threshold; int intFlags; // internal flags float dropOffZ; // $dropoff_fix short gear; // used in torque simulation boolean wallRun; // true = last move was the result of a wallrun // Additional info record for player avatars only. // Only valid if type == MT_PLAYER struct player_s *player; // Player number last looked for. int lastLook; // For nightmare/multiplayer respawn. struct { float pos[3]; angle_t angle; int flags; // MSF_* flags } spawnSpot; // Thing being chased/attacked for tracers. struct mobj_s *tracer; int turnTime; // $visangle-facetarget int corpseTics; // $vanish: how long has this been dead? } mobj_t; typedef struct polyobj_s { // Defined in dd_share.h; required polyobj elements. DD_BASE_POLYOBJ_ELEMENTS() // Doom-specific data: } polyobj_t; mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags); mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags); mobj_t* P_SpawnCustomPuff(mobjtype_t type, float x, float y, float z, angle_t angle); mobj_t* P_SpawnMissile(mobjtype_t type, mobj_t* source, mobj_t* dest); void P_SpawnPuff(float x, float y, float z, angle_t angle); void P_SpawnBlood(float x, float y, float z, int damage, angle_t angle); mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle); const terraintype_t* P_MobjGetFloorTerrainType(mobj_t* mo); float P_MobjGetFriction(mobj_t *mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_spec.h0000644000175000017500000000447511357170242022735 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.h: World texture animation, height or lighting changes * according to adjacent sectors, respective utility functions, etc. * * Line Tag handling. Line and Sector triggers. * * Events are operations triggered by using, crossing, or shooting special * lines, or by timed thinkers. */ #ifndef __P_SPEC__ #define __P_SPEC__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "d_player.h" // Define values for map objects #define MO_TELEPORTMAN 14 // at game start void P_InitPicAnims(void); // at map load void P_SpawnSpecials(void); // every tic void P_UpdateSpecials(void); boolean P_ActivateLine(linedef_t *ld, mobj_t *mo, int side, int activationType); void P_PlayerInSpecialSector(player_t *player); int EV_DoDonut(linedef_t *line); typedef enum { build8, // slowly build by 8 turbo16 // quickly build by 16 } stair_e; typedef enum { ok, crushed, pastdest } result_e; result_e T_MovePlane(sector_t* sector, float speed, float dest, int crush, int floorOrCeiling, int direction); int EV_BuildStairs(linedef_t* line, stair_e type); boolean P_UseSpecialLine2(mobj_t* mo, linedef_t* line, int side); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_local.h0000644000175000017500000000660211357170242023067 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_local.h: Play functions, animation, global header. */ #ifndef __P_LOCAL_H__ #define __P_LOCAL_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "p_spec.h" #include "p_start.h" #include "p_actor.h" #include "p_xg.h" #include "p_terraintype.h" // Palette indices. // For damage/bonus red-/gold-shifts #define STARTREDPALS (1) #define STARTBONUSPALS (9) #define NUMREDPALS (8) #define NUMBONUSPALS (4) #define FLOATSPEED (4) #define DELTAMUL (6.324555320) // Used when calculating ticcmd_t.lookdirdelta #define MAXHEALTH (maxHealth) //100 #define VIEWHEIGHT (41) #define TOCENTER (-8) // player radius for movement checking #define PLAYERRADIUS (16) // MAXRADIUS is for precalculated sector block boxes the spider demon is // larger, but we do not have any moving sectors nearby. #define MAXRADIUS (32) #define MAXMOVE (30) #define USERANGE (64) #define MELEERANGE (64) #define MISSILERANGE (32*64) #define BASETHRESHOLD (100) #define sentient(mobj) ((mobj)->health > 0 && P_GetState((mobj)->type, SN_SEE)) #define FRICTION_NORMAL (0.90625f) #define FRICTION_FLY (0.91796875f) #define FRICTION_HIGH (0.5f) #define OPENRANGE (*(float*) DD_GetVariable(DD_OPENRANGE)) #define OPENTOP (*(float*) DD_GetVariable(DD_OPENTOP)) #define OPENBOTTOM (*(float*) DD_GetVariable(DD_OPENBOTTOM)) #define LOWFLOOR (*(float*) DD_GetVariable(DD_LOWFLOOR)) extern float turboMul; extern int maxAmmo[NUM_AMMO_TYPES]; extern int clipAmmo[NUM_AMMO_TYPES]; void P_SetupPsprites(player_t* plr); void P_MovePsprites(player_t* plr); void P_DropWeapon(player_t* plr); void P_SetPsprite(player_t* plr, int position, statenum_t stnum); void P_MobjRemove(mobj_t* mo, boolean noRespawn); boolean P_MobjChangeState(mobj_t* mo, statenum_t state); void P_MobjThinker(mobj_t* mo); void P_RipperBlood(mobj_t* mo); void P_SetDoomsdayFlags(mobj_t* mo); void P_HitFloor(mobj_t* mo); void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher); int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage, boolean stomping); void P_ExplodeMissile(mobj_t* mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_console.h0000644000175000017500000000235711357170242023426 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2006 Daniel Swanson * * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /* * d_console.h: jDoom console settings and commands. */ #ifndef __DCONSOLE_H__ #define __DCONSOLE_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif void G_ConsoleRegistration(); void D_ConsoleBg(int *width, int *height); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_setup.h0000644000175000017500000000326111357170242023133 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.h: Map setup routines */ #ifndef __D_SETUP_H__ #define __D_SETUP_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif // Map objects and their properties: enum { MO_NONE = 0, MO_THING, MO_XLINEDEF, MO_XSECTOR, MO_X, MO_Y, MO_Z, MO_ANGLE, MO_TYPE, MO_DOOMEDNUM, MO_FLAGS, MO_TAG }; void P_Init(void); void P_RegisterMapObjs(void); int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void *data); int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void *data); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/jdoom.h0000644000175000017500000000466611357170242022576 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jdoom.h: All jDoom Headers * * A convenience header for including all jDoom headers. */ #ifndef __JDOOM_CONVENIENCE_H__ #define __JDOOM_CONVENIENCE_H__ #include "../../jdoom/include/acfnlink.h" #include "../../jdoom/include/d_api.h" #include "../../jdoom/include/d_config.h" #include "../../jdoom/include/d_console.h" #include "../../jdoom/include/d_event.h" #include "../../jdoom/include/d_main.h" #include "../../jdoom/include/d_refresh.h" #include "../../jdoom/include/doomdef.h" #include "../../jdoom/include/doomtype.h" #include "../../jdoom/include/dstrings.h" #include "../../jdoom/include/g_game.h" #include "../../jdoom/include/g_ctrl.h" #include "../../jdoom/include/info.h" #include "../../jdoom/include/m_cheat.h" #include "../../jdoom/include/m_random.h" #include "../../jdoom/include/m_menu.h" #include "../../jdoom/include/mn_def.h" #include "../../jdoom/include/p_enemy.h" #include "../../jdoom/include/p_inter.h" #include "../../jdoom/include/p_lights.h" #include "../../jdoom/include/p_local.h" #include "../../jdoom/include/p_maputl.h" #include "../../jdoom/include/p_oldsvg.h" #include "../../jdoom/include/p_pspr.h" #include "../../jdoom/include/p_setup.h" #include "../../jdoom/include/p_sound.h" #include "../../jdoom/include/p_spec.h" #include "../../jdoom/include/p_telept.h" #include "../../jdoom/include/r_defs.h" #include "../../jdoom/include/st_stuff.h" #include "../../jdoom/include/tables.h" #include "../../jdoom/include/wi_stuff.h" #endif // __JDOOM_CONVENIENCE_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/acfnlink.h0000644000175000017500000000634511357170242023247 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * acfnlink.h: Action functions (mobj AI). */ #ifndef __ACTION_LINK_H__ #define __ACTION_LINK_H__ #include "dd_share.h" typedef struct { char *name; // Name of the routine. void (C_DECL *func)(); // Pointer to the function. } actionlink_t; extern actionlink_t actionlinks[]; void C_DECL A_BabyMetal(); void C_DECL A_BFGsound(); void C_DECL A_BFGSpray(); void C_DECL A_BossDeath(); void C_DECL A_BrainAwake(); void C_DECL A_BrainDie(); void C_DECL A_BrainExplode(); void C_DECL A_BrainPain(); void C_DECL A_BrainScream(); void C_DECL A_BrainSpit(); void C_DECL A_BruisAttack(); void C_DECL A_BspiAttack(); void C_DECL A_Chase(); void C_DECL A_CheckReload(); void C_DECL A_CloseShotgun2(); void C_DECL A_CPosAttack(); void C_DECL A_CPosRefire(); void C_DECL A_CyberAttack(); void C_DECL A_Explode(); void C_DECL A_FaceTarget(); void C_DECL A_Fall(); void C_DECL A_FatAttack1(); void C_DECL A_FatAttack2(); void C_DECL A_FatAttack3(); void C_DECL A_FatRaise(); void C_DECL A_Fire(); void C_DECL A_FireBFG(); void C_DECL A_FireCGun(); void C_DECL A_FireCrackle(); void C_DECL A_FireMissile(); void C_DECL A_FirePistol(); void C_DECL A_FirePlasma(); void C_DECL A_FireShotgun(); void C_DECL A_FireShotgun2(); void C_DECL A_GunFlash(); void C_DECL A_HeadAttack(); void C_DECL A_Hoof(); void C_DECL A_KeenDie(); void C_DECL A_Light0(); void C_DECL A_Light1(); void C_DECL A_Light2(); void C_DECL A_LoadShotgun2(); void C_DECL A_Look(); void C_DECL A_Lower(); void C_DECL A_Metal(); void C_DECL A_OpenShotgun2(); void C_DECL A_Pain(); void C_DECL A_PainAttack(); void C_DECL A_PainDie(); void C_DECL A_PlayerScream(); void C_DECL A_PosAttack(); void C_DECL A_Punch(); void C_DECL A_Raise(); void C_DECL A_ReFire(); void C_DECL A_SargAttack(); void C_DECL A_Saw(); void C_DECL A_Scream(); void C_DECL A_SkelFist(); void C_DECL A_SkelMissile(); void C_DECL A_SkelWhoosh(); void C_DECL A_SkullAttack(); void C_DECL A_SpawnFly(); void C_DECL A_SpawnSound(); void C_DECL A_SpidRefire(); void C_DECL A_SPosAttack(); void C_DECL A_StartFire(); void C_DECL A_Tracer(); void C_DECL A_TroopAttack(); void C_DECL A_VileAttack(); void C_DECL A_VileChase(); void C_DECL A_VileStart(); void C_DECL A_VileTarget(); void C_DECL A_WeaponReady(); void C_DECL A_XScream(); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/doomdef.h0000644000175000017500000001574011357170242023076 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomdef.h: Internally used data structures for virtually everything, * key definitions, lots of other stuff. */ #ifndef __DOOMDEF_H__ #define __DOOMDEF_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #ifdef WIN32 #pragma warning(disable:4244) #endif #include #include #include "doomsday.h" #include "dd_api.h" #include "version.h" #include "info.h" #define Set DD_SetInteger #define Get DD_GetInteger #define CONFIGFILE GAMENAMETEXT".cfg" #define DEFSFILE GAMENAMETEXT"\\"GAMENAMETEXT".ded" #define DATAPATH "}data\\"GAMENAMETEXT"\\" #define STARTUPWAD "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".wad" #define STARTUPPK3 "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".pk3" extern game_import_t gi; extern game_export_t gx; // // Global parameters/defines. // #define MOBJINFO (*gi.mobjInfo) #define STATES (*gi.states) #define VALIDCOUNT (*gi.validCount) // Verbose messages. #define VERBOSE(code) { if(verbose >= 1) { code; } } #define VERBOSE2(code) { if(verbose >= 2) { code; } } /** * Game mode handling - identify IWAD version to handle IWAD dependant * animations, game logic etc. * \note DOOM 2 german edition not detected. */ typedef enum { shareware, // DOOM 1 shareware, E1, M9 registered, // DOOM 1 registered, E3, M27 commercial, // DOOM 2 retail, E1 M34 retail, // DOOM 1 retail, E4, M36 indetermined, // Well, no IWAD found. NUM_GAME_MODES } gamemode_t; // Game mode bits for the above. #define GM_SHAREWARE 0x1 // DOOM 1 shareware, E1, M9 #define GM_REGISTERED 0x2 // DOOM 1 registered, E3, M27 #define GM_COMMERCIAL 0x4 // DOOM 2 retail, E1 M34 // DOOM 2 german edition not handled. #define GM_RETAIL 0x8 // DOOM 1 retail, E4, M36 #define GM_INDETERMINED 0x16 // Well, no IWAD found. #define GM_ANY (GM_SHAREWARE|GM_REGISTERED|GM_COMMERCIAL|GM_RETAIL) #define GM_NOTSHAREWARE (GM_REGISTERED|GM_COMMERCIAL|GM_RETAIL) // Mission packs - might be useful for TC stuff? typedef enum { GM_DOOM, // DOOM 1 GM_DOOM2, // DOOM 2 GM_TNT, // TNT mission pack GM_PLUT, // Plutonia pack GM_NONE, NUM_GAME_MISSIONS } gamemission_t; #define SCREENWIDTH 320 #define SCREENHEIGHT 200 #define SCREEN_MUL 1 // The maximum number of players, multiplayer/networking. #define MAXPLAYERS 16 // State updates, number of tics / second. #define TICRATE 35 /** * The current (high-level) state of the game: whether we are playing, * gazing at the intermission screen, the game final animation, or a demo. */ typedef enum gamestate_e { GS_MAP, GS_INTERMISSION, GS_FINALE, GS_STARTUP, GS_WAITING, GS_INFINE, NUM_GAME_STATES } gamestate_t; // // Player Classes // typedef enum { PCLASS_PLAYER, NUM_PLAYER_CLASSES } playerclass_t; #define PCLASS_INFO(class) (&classInfo[class]) typedef struct classinfo_s{ char* niceName; boolean userSelectable; mobjtype_t mobjType; int normalState; int runState; int attackState; int attackEndState; int maxArmor; fixed_t maxMove; fixed_t forwardMove[2]; // [walk, run]. fixed_t sideMove[2]; // [walk, run]. int moveMul; // Multiplier for above. int turnSpeed[2]; // [normal, speed] int jumpTics; // Wait in between jumps. int failUseSound; // Sound played when a use fails. } classinfo_t; extern classinfo_t classInfo[NUM_PLAYER_CLASSES]; typedef enum { SM_NOITEMS = -1, // skill mode 0 SM_BABY = 0, SM_EASY, SM_MEDIUM, SM_HARD, SM_NIGHTMARE, NUM_SKILL_MODES } skillmode_t; // // Key cards. // typedef enum { KT_BLUECARD, KT_YELLOWCARD, KT_REDCARD, KT_BLUESKULL, KT_YELLOWSKULL, KT_REDSKULL, NUM_KEY_TYPES } keytype_t; // The defined weapons, // including a marker indicating // user has not changed weapon. typedef enum { WT_FIRST, // fist WT_SECOND, // pistol WT_THIRD, // shotgun WT_FOURTH, // chaingun WT_FIFTH, // missile launcher WT_SIXTH, // plasma rifle WT_SEVENTH, // bfg WT_EIGHTH, // chainsaw WT_NINETH, // supershotgun NUM_WEAPON_TYPES, // No pending weapon change. WT_NOCHANGE } weapontype_t; #define NUMWEAPLEVELS 2 // DOOM weapons have 1 power level. // Ammunition types defined. typedef enum { AT_CLIP, // Pistol / chaingun ammo. AT_SHELL, // Shotgun / double barreled shotgun. AT_CELL, // Plasma rifle, BFG. AT_MISSILE, // Missile launcher. NUM_AMMO_TYPES, AT_NOAMMO // Unlimited for chainsaw / fist. } ammotype_t; // Power ups. typedef enum { PT_INVULNERABILITY, PT_STRENGTH, PT_INVISIBILITY, PT_IRONFEET, PT_ALLMAP, PT_INFRARED, PT_FLIGHT, NUM_POWER_TYPES } powertype_t; /** * Power up durations, how many seconds till expiration, assuming TICRATE * is 35 ticks/second. */ typedef enum { INVULNTICS = (30 * TICRATE), INVISTICS = (60 * TICRATE), INFRATICS = (120 * TICRATE), IRONTICS = (60 * TICRATE) } powerduration_t; enum { VX, VY, VZ }; // Vertex indices. enum { CR, CG, CB, CA }; // Color indices. #define IS_SERVER (Get(DD_SERVER)) #define IS_CLIENT (Get(DD_CLIENT)) #define IS_NETGAME (Get(DD_NETGAME)) #define IS_DEDICATED (Get(DD_DEDICATED)) #define CVAR(typ, x) (*((typ) *) Con_GetVariable(x)->ptr) #define SFXVOLUME (Get(DD_SFX_VOLUME) / 17) #define MUSICVOLUME (Get(DD_MUSIC_VOLUME) / 17) #define VIEWWINDOWX (Get(DD_VIEWWINDOW_X)) #define VIEWWINDOWY (Get(DD_VIEWWINDOW_Y)) // Player taking events, and displaying. #define CONSOLEPLAYER (Get(DD_CONSOLEPLAYER)) #define DISPLAYPLAYER (Get(DD_DISPLAYPLAYER)) #define GAMETIC (*((timespan_t*) DD_GetVariable(DD_GAMETIC))) #define DEFAULT_PLAYER_VIEWHEIGHT (41) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_maputl.h0000644000175000017500000000225511357170242023277 0ustar keeskees/**\file *\section License * License: GPL + jHeretic/jHexen Exception * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputl.h: Movement/collision utility functions jDoom - specific. */ #ifndef __P_MAPUTL_H__ #define __P_MAPUTL_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "p_mobj.h" void P_ApplyTorque(mobj_t *mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/doomdata.h0000644000175000017500000000437511357170242023253 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * doomdata.h: Thing and linedef attributes. */ #ifndef __DOOMDATA__ #define __DOOMDATA__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif // Base plane ids. enum { PLN_FLOOR, PLN_CEILING }; // // LineDef attributes. // // Blocks monsters only. #define ML_BLOCKMONSTERS 2 // In AutoMap: don't map as two sided: IT'S A SECRET! #define ML_SECRET 32 // Sound rendering: don't let sound cross two of these. #define ML_SOUNDBLOCK 64 // Don't draw on the automap at all. #define ML_DONTDRAW 128 // Set if already seen, thus drawn in automap. #define ML_MAPPED 256 // Allows a USE action to pass through a linedef with a special #define ML_PASSUSE 512 // If set allows any mobj to trigger the linedef's special #define ML_ALLTRIGGER 1024 // If set ALL flags NOT in DOOM v1.9 will be zeroed upon map load. // ML_BLOCKING -> ML_MAPPED inc will persist. #define ML_INVALID 2048 #define VALIDMASK 0x000001ff // Special activation types: #define SPAC_CROSS 0 // Player crosses linedef. #define SPAC_USE 1 // Player uses linedef. #define SPAC_IMPACT 3 // Projectile hits linedef. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/p_inter.h0000644000175000017500000000307311357170242023115 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.h: */ #ifndef __P_INTER_H__ #define __P_INTER_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif boolean P_GivePower(player_t *plr, int); boolean P_TakePower(player_t *plr, int power); void P_GiveKey(player_t *plr, keytype_t keyType); boolean P_GiveBody(player_t *plr, int num); void P_GiveBackpack(player_t *plr); boolean P_GiveWeapon(player_t *plr, weapontype_t weapon, boolean dropped); boolean P_GiveArmorType(player_t* plr, int type, int points); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/oldinfo.h0000644000175000017500000005356011357170242023115 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * oldinfo.h: Thing frame/state LUT, generated by multigen utilitiy. * * This one is the original DOOM version, preserved. */ #ifndef __INFO__ #define __INFO__ typedef enum { SPR_TROO, SPR_SHTG, SPR_PUNG, SPR_PISG, SPR_PISF, SPR_SHTF, SPR_SHT2, SPR_CHGG, SPR_CHGF, SPR_MISG, SPR_MISF, SPR_SAWG, SPR_PLSG, SPR_PLSF, SPR_BFGG, SPR_BFGF, SPR_BLUD, SPR_PUFF, SPR_BAL1, SPR_BAL2, SPR_PLSS, SPR_PLSE, SPR_MISL, SPR_BFS1, SPR_BFE1, SPR_BFE2, SPR_TFOG, SPR_IFOG, SPR_PLAY, SPR_POSS, SPR_SPOS, SPR_VILE, SPR_FIRE, SPR_FATB, SPR_FBXP, SPR_SKEL, SPR_MANF, SPR_FATT, SPR_CPOS, SPR_SARG, SPR_HEAD, SPR_BAL7, SPR_BOSS, SPR_BOS2, SPR_SKUL, SPR_SPID, SPR_BSPI, SPR_APLS, SPR_APBX, SPR_CYBR, SPR_PAIN, SPR_SSWV, SPR_KEEN, SPR_BBRN, SPR_BOSF, SPR_ARM1, SPR_ARM2, SPR_BAR1, SPR_BEXP, SPR_FCAN, SPR_BON1, SPR_BON2, SPR_BKEY, SPR_RKEY, SPR_YKEY, SPR_BSKU, SPR_RSKU, SPR_YSKU, SPR_STIM, SPR_MEDI, SPR_SOUL, SPR_PINV, SPR_PSTR, SPR_PINS, SPR_MEGA, SPR_SUIT, SPR_PMAP, SPR_PVIS, SPR_CLIP, SPR_AMMO, SPR_ROCK, SPR_BROK, SPR_CELL, SPR_CELP, SPR_SHEL, SPR_SBOX, SPR_BPAK, SPR_BFUG, SPR_MGUN, SPR_CSAW, SPR_LAUN, SPR_PLAS, SPR_SHOT, SPR_SGN2, SPR_COLU, SPR_SMT2, SPR_GOR1, SPR_POL2, SPR_POL5, SPR_POL4, SPR_POL3, SPR_POL1, SPR_POL6, SPR_GOR2, SPR_GOR3, SPR_GOR4, SPR_GOR5, SPR_SMIT, SPR_COL1, SPR_COL2, SPR_COL3, SPR_COL4, SPR_CAND, SPR_CBRA, SPR_COL6, SPR_TRE1, SPR_TRE2, SPR_ELEC, SPR_CEYE, SPR_FSKU, SPR_COL5, SPR_TBLU, SPR_TGRN, SPR_TRED, SPR_SMBT, SPR_SMGT, SPR_SMRT, SPR_HDB1, SPR_HDB2, SPR_HDB3, SPR_HDB4, SPR_HDB5, SPR_HDB6, SPR_POB1, SPR_POB2, SPR_BRS1, SPR_TLMP, SPR_TLP2, NUMSPRITES } spritenum_t; typedef enum { S_NULL, S_LIGHTDONE, S_PUNCH, S_PUNCHDOWN, S_PUNCHUP, S_PUNCH1, S_PUNCH2, S_PUNCH3, S_PUNCH4, S_PUNCH5, S_PISTOL, S_PISTOLDOWN, S_PISTOLUP, S_PISTOL1, S_PISTOL2, S_PISTOL3, S_PISTOL4, S_PISTOLFLASH, S_SGUN, S_SGUNDOWN, S_SGUNUP, S_SGUN1, S_SGUN2, S_SGUN3, S_SGUN4, S_SGUN5, S_SGUN6, S_SGUN7, S_SGUN8, S_SGUN9, S_SGUNFLASH1, S_SGUNFLASH2, S_DSGUN, S_DSGUNDOWN, S_DSGUNUP, S_DSGUN1, S_DSGUN2, S_DSGUN3, S_DSGUN4, S_DSGUN5, S_DSGUN6, S_DSGUN7, S_DSGUN8, S_DSGUN9, S_DSGUN10, S_DSNR1, S_DSNR2, S_DSGUNFLASH1, S_DSGUNFLASH2, S_CHAIN, S_CHAINDOWN, S_CHAINUP, S_CHAIN1, S_CHAIN2, S_CHAIN3, S_CHAINFLASH1, S_CHAINFLASH2, S_MISSILE, S_MISSILEDOWN, S_MISSILEUP, S_MISSILE1, S_MISSILE2, S_MISSILE3, S_MISSILEFLASH1, S_MISSILEFLASH2, S_MISSILEFLASH3, S_MISSILEFLASH4, S_SAW, S_SAWB, S_SAWDOWN, S_SAWUP, S_SAW1, S_SAW2, S_SAW3, S_PLASMA, S_PLASMADOWN, S_PLASMAUP, S_PLASMA1, S_PLASMA2, S_PLASMAFLASH1, S_PLASMAFLASH2, S_BFG, S_BFGDOWN, S_BFGUP, S_BFG1, S_BFG2, S_BFG3, S_BFG4, S_BFGFLASH1, S_BFGFLASH2, S_BLOOD1, S_BLOOD2, S_BLOOD3, S_PUFF1, S_PUFF2, S_PUFF3, S_PUFF4, S_TBALL1, S_TBALL2, S_TBALLX1, S_TBALLX2, S_TBALLX3, S_RBALL1, S_RBALL2, S_RBALLX1, S_RBALLX2, S_RBALLX3, S_PLASBALL, S_PLASBALL2, S_PLASEXP, S_PLASEXP2, S_PLASEXP3, S_PLASEXP4, S_PLASEXP5, S_ROCKET, S_BFGSHOT, S_BFGSHOT2, S_BFGLAND, S_BFGLAND2, S_BFGLAND3, S_BFGLAND4, S_BFGLAND5, S_BFGLAND6, S_BFGEXP, S_BFGEXP2, S_BFGEXP3, S_BFGEXP4, S_EXPLODE1, S_EXPLODE2, S_EXPLODE3, S_TFOG, S_TFOG01, S_TFOG02, S_TFOG2, S_TFOG3, S_TFOG4, S_TFOG5, S_TFOG6, S_TFOG7, S_TFOG8, S_TFOG9, S_TFOG10, S_IFOG, S_IFOG01, S_IFOG02, S_IFOG2, S_IFOG3, S_IFOG4, S_IFOG5, S_PLAY, S_PLAY_RUN1, S_PLAY_RUN2, S_PLAY_RUN3, S_PLAY_RUN4, S_PLAY_ATK1, S_PLAY_ATK2, S_PLAY_PAIN, S_PLAY_PAIN2, S_PLAY_DIE1, S_PLAY_DIE2, S_PLAY_DIE3, S_PLAY_DIE4, S_PLAY_DIE5, S_PLAY_DIE6, S_PLAY_DIE7, S_PLAY_XDIE1, S_PLAY_XDIE2, S_PLAY_XDIE3, S_PLAY_XDIE4, S_PLAY_XDIE5, S_PLAY_XDIE6, S_PLAY_XDIE7, S_PLAY_XDIE8, S_PLAY_XDIE9, S_POSS_STND, S_POSS_STND2, S_POSS_RUN1, S_POSS_RUN2, S_POSS_RUN3, S_POSS_RUN4, S_POSS_RUN5, S_POSS_RUN6, S_POSS_RUN7, S_POSS_RUN8, S_POSS_ATK1, S_POSS_ATK2, S_POSS_ATK3, S_POSS_PAIN, S_POSS_PAIN2, S_POSS_DIE1, S_POSS_DIE2, S_POSS_DIE3, S_POSS_DIE4, S_POSS_DIE5, S_POSS_XDIE1, S_POSS_XDIE2, S_POSS_XDIE3, S_POSS_XDIE4, S_POSS_XDIE5, S_POSS_XDIE6, S_POSS_XDIE7, S_POSS_XDIE8, S_POSS_XDIE9, S_POSS_RAISE1, S_POSS_RAISE2, S_POSS_RAISE3, S_POSS_RAISE4, S_SPOS_STND, S_SPOS_STND2, S_SPOS_RUN1, S_SPOS_RUN2, S_SPOS_RUN3, S_SPOS_RUN4, S_SPOS_RUN5, S_SPOS_RUN6, S_SPOS_RUN7, S_SPOS_RUN8, S_SPOS_ATK1, S_SPOS_ATK2, S_SPOS_ATK3, S_SPOS_PAIN, S_SPOS_PAIN2, S_SPOS_DIE1, S_SPOS_DIE2, S_SPOS_DIE3, S_SPOS_DIE4, S_SPOS_DIE5, S_SPOS_XDIE1, S_SPOS_XDIE2, S_SPOS_XDIE3, S_SPOS_XDIE4, S_SPOS_XDIE5, S_SPOS_XDIE6, S_SPOS_XDIE7, S_SPOS_XDIE8, S_SPOS_XDIE9, S_SPOS_RAISE1, S_SPOS_RAISE2, S_SPOS_RAISE3, S_SPOS_RAISE4, S_SPOS_RAISE5, S_VILE_STND, S_VILE_STND2, S_VILE_RUN1, S_VILE_RUN2, S_VILE_RUN3, S_VILE_RUN4, S_VILE_RUN5, S_VILE_RUN6, S_VILE_RUN7, S_VILE_RUN8, S_VILE_RUN9, S_VILE_RUN10, S_VILE_RUN11, S_VILE_RUN12, S_VILE_ATK1, S_VILE_ATK2, S_VILE_ATK3, S_VILE_ATK4, S_VILE_ATK5, S_VILE_ATK6, S_VILE_ATK7, S_VILE_ATK8, S_VILE_ATK9, S_VILE_ATK10, S_VILE_ATK11, S_VILE_HEAL1, S_VILE_HEAL2, S_VILE_HEAL3, S_VILE_PAIN, S_VILE_PAIN2, S_VILE_DIE1, S_VILE_DIE2, S_VILE_DIE3, S_VILE_DIE4, S_VILE_DIE5, S_VILE_DIE6, S_VILE_DIE7, S_VILE_DIE8, S_VILE_DIE9, S_VILE_DIE10, S_FIRE1, S_FIRE2, S_FIRE3, S_FIRE4, S_FIRE5, S_FIRE6, S_FIRE7, S_FIRE8, S_FIRE9, S_FIRE10, S_FIRE11, S_FIRE12, S_FIRE13, S_FIRE14, S_FIRE15, S_FIRE16, S_FIRE17, S_FIRE18, S_FIRE19, S_FIRE20, S_FIRE21, S_FIRE22, S_FIRE23, S_FIRE24, S_FIRE25, S_FIRE26, S_FIRE27, S_FIRE28, S_FIRE29, S_FIRE30, S_SMOKE1, S_SMOKE2, S_SMOKE3, S_SMOKE4, S_SMOKE5, S_TRACER, S_TRACER2, S_TRACEEXP1, S_TRACEEXP2, S_TRACEEXP3, S_SKEL_STND, S_SKEL_STND2, S_SKEL_RUN1, S_SKEL_RUN2, S_SKEL_RUN3, S_SKEL_RUN4, S_SKEL_RUN5, S_SKEL_RUN6, S_SKEL_RUN7, S_SKEL_RUN8, S_SKEL_RUN9, S_SKEL_RUN10, S_SKEL_RUN11, S_SKEL_RUN12, S_SKEL_FIST1, S_SKEL_FIST2, S_SKEL_FIST3, S_SKEL_FIST4, S_SKEL_MISS1, S_SKEL_MISS2, S_SKEL_MISS3, S_SKEL_MISS4, S_SKEL_PAIN, S_SKEL_PAIN2, S_SKEL_DIE1, S_SKEL_DIE2, S_SKEL_DIE3, S_SKEL_DIE4, S_SKEL_DIE5, S_SKEL_DIE6, S_SKEL_RAISE1, S_SKEL_RAISE2, S_SKEL_RAISE3, S_SKEL_RAISE4, S_SKEL_RAISE5, S_SKEL_RAISE6, S_FATSHOT1, S_FATSHOT2, S_FATSHOTX1, S_FATSHOTX2, S_FATSHOTX3, S_FATT_STND, S_FATT_STND2, S_FATT_RUN1, S_FATT_RUN2, S_FATT_RUN3, S_FATT_RUN4, S_FATT_RUN5, S_FATT_RUN6, S_FATT_RUN7, S_FATT_RUN8, S_FATT_RUN9, S_FATT_RUN10, S_FATT_RUN11, S_FATT_RUN12, S_FATT_ATK1, S_FATT_ATK2, S_FATT_ATK3, S_FATT_ATK4, S_FATT_ATK5, S_FATT_ATK6, S_FATT_ATK7, S_FATT_ATK8, S_FATT_ATK9, S_FATT_ATK10, S_FATT_PAIN, S_FATT_PAIN2, S_FATT_DIE1, S_FATT_DIE2, S_FATT_DIE3, S_FATT_DIE4, S_FATT_DIE5, S_FATT_DIE6, S_FATT_DIE7, S_FATT_DIE8, S_FATT_DIE9, S_FATT_DIE10, S_FATT_RAISE1, S_FATT_RAISE2, S_FATT_RAISE3, S_FATT_RAISE4, S_FATT_RAISE5, S_FATT_RAISE6, S_FATT_RAISE7, S_FATT_RAISE8, S_CPOS_STND, S_CPOS_STND2, S_CPOS_RUN1, S_CPOS_RUN2, S_CPOS_RUN3, S_CPOS_RUN4, S_CPOS_RUN5, S_CPOS_RUN6, S_CPOS_RUN7, S_CPOS_RUN8, S_CPOS_ATK1, S_CPOS_ATK2, S_CPOS_ATK3, S_CPOS_ATK4, S_CPOS_PAIN, S_CPOS_PAIN2, S_CPOS_DIE1, S_CPOS_DIE2, S_CPOS_DIE3, S_CPOS_DIE4, S_CPOS_DIE5, S_CPOS_DIE6, S_CPOS_DIE7, S_CPOS_XDIE1, S_CPOS_XDIE2, S_CPOS_XDIE3, S_CPOS_XDIE4, S_CPOS_XDIE5, S_CPOS_XDIE6, S_CPOS_RAISE1, S_CPOS_RAISE2, S_CPOS_RAISE3, S_CPOS_RAISE4, S_CPOS_RAISE5, S_CPOS_RAISE6, S_CPOS_RAISE7, S_TROO_STND, S_TROO_STND2, S_TROO_RUN1, S_TROO_RUN2, S_TROO_RUN3, S_TROO_RUN4, S_TROO_RUN5, S_TROO_RUN6, S_TROO_RUN7, S_TROO_RUN8, S_TROO_ATK1, S_TROO_ATK2, S_TROO_ATK3, S_TROO_PAIN, S_TROO_PAIN2, S_TROO_DIE1, S_TROO_DIE2, S_TROO_DIE3, S_TROO_DIE4, S_TROO_DIE5, S_TROO_XDIE1, S_TROO_XDIE2, S_TROO_XDIE3, S_TROO_XDIE4, S_TROO_XDIE5, S_TROO_XDIE6, S_TROO_XDIE7, S_TROO_XDIE8, S_TROO_RAISE1, S_TROO_RAISE2, S_TROO_RAISE3, S_TROO_RAISE4, S_TROO_RAISE5, S_SARG_STND, S_SARG_STND2, S_SARG_RUN1, S_SARG_RUN2, S_SARG_RUN3, S_SARG_RUN4, S_SARG_RUN5, S_SARG_RUN6, S_SARG_RUN7, S_SARG_RUN8, S_SARG_ATK1, S_SARG_ATK2, S_SARG_ATK3, S_SARG_PAIN, S_SARG_PAIN2, S_SARG_DIE1, S_SARG_DIE2, S_SARG_DIE3, S_SARG_DIE4, S_SARG_DIE5, S_SARG_DIE6, S_SARG_RAISE1, S_SARG_RAISE2, S_SARG_RAISE3, S_SARG_RAISE4, S_SARG_RAISE5, S_SARG_RAISE6, S_HEAD_STND, S_HEAD_RUN1, S_HEAD_ATK1, S_HEAD_ATK2, S_HEAD_ATK3, S_HEAD_PAIN, S_HEAD_PAIN2, S_HEAD_PAIN3, S_HEAD_DIE1, S_HEAD_DIE2, S_HEAD_DIE3, S_HEAD_DIE4, S_HEAD_DIE5, S_HEAD_DIE6, S_HEAD_RAISE1, S_HEAD_RAISE2, S_HEAD_RAISE3, S_HEAD_RAISE4, S_HEAD_RAISE5, S_HEAD_RAISE6, S_BRBALL1, S_BRBALL2, S_BRBALLX1, S_BRBALLX2, S_BRBALLX3, S_BOSS_STND, S_BOSS_STND2, S_BOSS_RUN1, S_BOSS_RUN2, S_BOSS_RUN3, S_BOSS_RUN4, S_BOSS_RUN5, S_BOSS_RUN6, S_BOSS_RUN7, S_BOSS_RUN8, S_BOSS_ATK1, S_BOSS_ATK2, S_BOSS_ATK3, S_BOSS_PAIN, S_BOSS_PAIN2, S_BOSS_DIE1, S_BOSS_DIE2, S_BOSS_DIE3, S_BOSS_DIE4, S_BOSS_DIE5, S_BOSS_DIE6, S_BOSS_DIE7, S_BOSS_RAISE1, S_BOSS_RAISE2, S_BOSS_RAISE3, S_BOSS_RAISE4, S_BOSS_RAISE5, S_BOSS_RAISE6, S_BOSS_RAISE7, S_BOS2_STND, S_BOS2_STND2, S_BOS2_RUN1, S_BOS2_RUN2, S_BOS2_RUN3, S_BOS2_RUN4, S_BOS2_RUN5, S_BOS2_RUN6, S_BOS2_RUN7, S_BOS2_RUN8, S_BOS2_ATK1, S_BOS2_ATK2, S_BOS2_ATK3, S_BOS2_PAIN, S_BOS2_PAIN2, S_BOS2_DIE1, S_BOS2_DIE2, S_BOS2_DIE3, S_BOS2_DIE4, S_BOS2_DIE5, S_BOS2_DIE6, S_BOS2_DIE7, S_BOS2_RAISE1, S_BOS2_RAISE2, S_BOS2_RAISE3, S_BOS2_RAISE4, S_BOS2_RAISE5, S_BOS2_RAISE6, S_BOS2_RAISE7, S_SKULL_STND, S_SKULL_STND2, S_SKULL_RUN1, S_SKULL_RUN2, S_SKULL_ATK1, S_SKULL_ATK2, S_SKULL_ATK3, S_SKULL_ATK4, S_SKULL_PAIN, S_SKULL_PAIN2, S_SKULL_DIE1, S_SKULL_DIE2, S_SKULL_DIE3, S_SKULL_DIE4, S_SKULL_DIE5, S_SKULL_DIE6, S_SPID_STND, S_SPID_STND2, S_SPID_RUN1, S_SPID_RUN2, S_SPID_RUN3, S_SPID_RUN4, S_SPID_RUN5, S_SPID_RUN6, S_SPID_RUN7, S_SPID_RUN8, S_SPID_RUN9, S_SPID_RUN10, S_SPID_RUN11, S_SPID_RUN12, S_SPID_ATK1, S_SPID_ATK2, S_SPID_ATK3, S_SPID_ATK4, S_SPID_PAIN, S_SPID_PAIN2, S_SPID_DIE1, S_SPID_DIE2, S_SPID_DIE3, S_SPID_DIE4, S_SPID_DIE5, S_SPID_DIE6, S_SPID_DIE7, S_SPID_DIE8, S_SPID_DIE9, S_SPID_DIE10, S_SPID_DIE11, S_BSPI_STND, S_BSPI_STND2, S_BSPI_SIGHT, S_BSPI_RUN1, S_BSPI_RUN2, S_BSPI_RUN3, S_BSPI_RUN4, S_BSPI_RUN5, S_BSPI_RUN6, S_BSPI_RUN7, S_BSPI_RUN8, S_BSPI_RUN9, S_BSPI_RUN10, S_BSPI_RUN11, S_BSPI_RUN12, S_BSPI_ATK1, S_BSPI_ATK2, S_BSPI_ATK3, S_BSPI_ATK4, S_BSPI_PAIN, S_BSPI_PAIN2, S_BSPI_DIE1, S_BSPI_DIE2, S_BSPI_DIE3, S_BSPI_DIE4, S_BSPI_DIE5, S_BSPI_DIE6, S_BSPI_DIE7, S_BSPI_RAISE1, S_BSPI_RAISE2, S_BSPI_RAISE3, S_BSPI_RAISE4, S_BSPI_RAISE5, S_BSPI_RAISE6, S_BSPI_RAISE7, S_ARACH_PLAZ, S_ARACH_PLAZ2, S_ARACH_PLEX, S_ARACH_PLEX2, S_ARACH_PLEX3, S_ARACH_PLEX4, S_ARACH_PLEX5, S_CYBER_STND, S_CYBER_STND2, S_CYBER_RUN1, S_CYBER_RUN2, S_CYBER_RUN3, S_CYBER_RUN4, S_CYBER_RUN5, S_CYBER_RUN6, S_CYBER_RUN7, S_CYBER_RUN8, S_CYBER_ATK1, S_CYBER_ATK2, S_CYBER_ATK3, S_CYBER_ATK4, S_CYBER_ATK5, S_CYBER_ATK6, S_CYBER_PAIN, S_CYBER_DIE1, S_CYBER_DIE2, S_CYBER_DIE3, S_CYBER_DIE4, S_CYBER_DIE5, S_CYBER_DIE6, S_CYBER_DIE7, S_CYBER_DIE8, S_CYBER_DIE9, S_CYBER_DIE10, S_PAIN_STND, S_PAIN_RUN1, S_PAIN_RUN2, S_PAIN_RUN3, S_PAIN_RUN4, S_PAIN_RUN5, S_PAIN_RUN6, S_PAIN_ATK1, S_PAIN_ATK2, S_PAIN_ATK3, S_PAIN_ATK4, S_PAIN_PAIN, S_PAIN_PAIN2, S_PAIN_DIE1, S_PAIN_DIE2, S_PAIN_DIE3, S_PAIN_DIE4, S_PAIN_DIE5, S_PAIN_DIE6, S_PAIN_RAISE1, S_PAIN_RAISE2, S_PAIN_RAISE3, S_PAIN_RAISE4, S_PAIN_RAISE5, S_PAIN_RAISE6, S_SSWV_STND, S_SSWV_STND2, S_SSWV_RUN1, S_SSWV_RUN2, S_SSWV_RUN3, S_SSWV_RUN4, S_SSWV_RUN5, S_SSWV_RUN6, S_SSWV_RUN7, S_SSWV_RUN8, S_SSWV_ATK1, S_SSWV_ATK2, S_SSWV_ATK3, S_SSWV_ATK4, S_SSWV_ATK5, S_SSWV_ATK6, S_SSWV_PAIN, S_SSWV_PAIN2, S_SSWV_DIE1, S_SSWV_DIE2, S_SSWV_DIE3, S_SSWV_DIE4, S_SSWV_DIE5, S_SSWV_XDIE1, S_SSWV_XDIE2, S_SSWV_XDIE3, S_SSWV_XDIE4, S_SSWV_XDIE5, S_SSWV_XDIE6, S_SSWV_XDIE7, S_SSWV_XDIE8, S_SSWV_XDIE9, S_SSWV_RAISE1, S_SSWV_RAISE2, S_SSWV_RAISE3, S_SSWV_RAISE4, S_SSWV_RAISE5, S_KEENSTND, S_COMMKEEN, S_COMMKEEN2, S_COMMKEEN3, S_COMMKEEN4, S_COMMKEEN5, S_COMMKEEN6, S_COMMKEEN7, S_COMMKEEN8, S_COMMKEEN9, S_COMMKEEN10, S_COMMKEEN11, S_COMMKEEN12, S_KEENPAIN, S_KEENPAIN2, S_BRAIN, S_BRAIN_PAIN, S_BRAIN_DIE1, S_BRAIN_DIE2, S_BRAIN_DIE3, S_BRAIN_DIE4, S_BRAINEYE, S_BRAINEYESEE, S_BRAINEYE1, S_SPAWN1, S_SPAWN2, S_SPAWN3, S_SPAWN4, S_SPAWNFIRE1, S_SPAWNFIRE2, S_SPAWNFIRE3, S_SPAWNFIRE4, S_SPAWNFIRE5, S_SPAWNFIRE6, S_SPAWNFIRE7, S_SPAWNFIRE8, S_BRAINEXPLODE1, S_BRAINEXPLODE2, S_BRAINEXPLODE3, S_ARM1, S_ARM1A, S_ARM2, S_ARM2A, S_BAR1, S_BAR2, S_BEXP, S_BEXP2, S_BEXP3, S_BEXP4, S_BEXP5, S_BBAR1, S_BBAR2, S_BBAR3, S_BON1, S_BON1A, S_BON1B, S_BON1C, S_BON1D, S_BON1E, S_BON2, S_BON2A, S_BON2B, S_BON2C, S_BON2D, S_BON2E, S_BKEY, S_BKEY2, S_RKEY, S_RKEY2, S_YKEY, S_YKEY2, S_BSKULL, S_BSKULL2, S_RSKULL, S_RSKULL2, S_YSKULL, S_YSKULL2, S_STIM, S_MEDI, S_SOUL, S_SOUL2, S_SOUL3, S_SOUL4, S_SOUL5, S_SOUL6, S_PINV, S_PINV2, S_PINV3, S_PINV4, S_PSTR, S_PINS, S_PINS2, S_PINS3, S_PINS4, S_MEGA, S_MEGA2, S_MEGA3, S_MEGA4, S_SUIT, S_PMAP, S_PMAP2, S_PMAP3, S_PMAP4, S_PMAP5, S_PMAP6, S_PVIS, S_PVIS2, S_CLIP, S_AMMO, S_ROCK, S_BROK, S_CELL, S_CELP, S_SHEL, S_SBOX, S_BPAK, S_BFUG, S_MGUN, S_CSAW, S_LAUN, S_PLAS, S_SHOT, S_SHOT2, S_COLU, S_STALAG, S_BLOODYTWITCH, S_BLOODYTWITCH2, S_BLOODYTWITCH3, S_BLOODYTWITCH4, S_DEADTORSO, S_DEADBOTTOM, S_HEADSONSTICK, S_GIBS, S_HEADONASTICK, S_HEADCANDLES, S_HEADCANDLES2, S_DEADSTICK, S_LIVESTICK, S_LIVESTICK2, S_MEAT2, S_MEAT3, S_MEAT4, S_MEAT5, S_STALAGTITE, S_TALLGRNCOL, S_SHRTGRNCOL, S_TALLREDCOL, S_SHRTREDCOL, S_CANDLESTIK, S_CANDELABRA, S_SKULLCOL, S_TORCHTREE, S_BIGTREE, S_TECHPILLAR, S_EVILEYE, S_EVILEYE2, S_EVILEYE3, S_EVILEYE4, S_FLOATSKULL, S_FLOATSKULL2, S_FLOATSKULL3, S_HEARTCOL, S_HEARTCOL2, S_BLUETORCH, S_BLUETORCH2, S_BLUETORCH3, S_BLUETORCH4, S_GREENTORCH, S_GREENTORCH2, S_GREENTORCH3, S_GREENTORCH4, S_REDTORCH, S_REDTORCH2, S_REDTORCH3, S_REDTORCH4, S_BTORCHSHRT, S_BTORCHSHRT2, S_BTORCHSHRT3, S_BTORCHSHRT4, S_GTORCHSHRT, S_GTORCHSHRT2, S_GTORCHSHRT3, S_GTORCHSHRT4, S_RTORCHSHRT, S_RTORCHSHRT2, S_RTORCHSHRT3, S_RTORCHSHRT4, S_HANGNOGUTS, S_HANGBNOBRAIN, S_HANGTLOOKDN, S_HANGTSKULL, S_HANGTLOOKUP, S_HANGTNOBRAIN, S_COLONGIBS, S_SMALLPOOL, S_BRAINSTEM, S_TECHLAMP, S_TECHLAMP2, S_TECHLAMP3, S_TECHLAMP4, S_TECH2LAMP, S_TECH2LAMP2, S_TECH2LAMP3, S_TECH2LAMP4, NUMSTATES } statenum_t; /* // Original state struct. typedef struct { spritenum_t sprite; long frame; long tics; void (*action) (); // actionf_t action; statenum_t nextstate; long misc1, misc2; } state_t; */ typedef enum { MT_PLAYER, MT_POSSESSED, MT_SHOTGUY, MT_VILE, MT_FIRE, MT_UNDEAD, MT_TRACER, MT_SMOKE, MT_FATSO, MT_FATSHOT, MT_CHAINGUY, MT_TROOP, MT_SERGEANT, MT_SHADOWS, MT_HEAD, MT_BRUISER, MT_BRUISERSHOT, MT_KNIGHT, MT_SKULL, MT_SPIDER, MT_BABY, MT_CYBORG, MT_PAIN, MT_WOLFSS, MT_KEEN, MT_BOSSBRAIN, MT_BOSSSPIT, MT_BOSSTARGET, MT_SPAWNSHOT, MT_SPAWNFIRE, MT_BARREL, MT_TROOPSHOT, MT_HEADSHOT, MT_ROCKET, MT_PLASMA, MT_BFG, MT_ARACHPLAZ, MT_PUFF, MT_BLOOD, MT_TFOG, MT_IFOG, MT_TELEPORTMAN, MT_EXTRABFG, MT_MISC0, MT_MISC1, MT_MISC2, MT_MISC3, MT_MISC4, MT_MISC5, MT_MISC6, MT_MISC7, MT_MISC8, MT_MISC9, MT_MISC10, MT_MISC11, MT_MISC12, MT_INV, MT_MISC13, MT_INS, MT_MISC14, MT_MISC15, MT_MISC16, MT_MEGA, MT_CLIP, MT_MISC17, MT_MISC18, MT_MISC19, MT_MISC20, MT_MISC21, MT_MISC22, MT_MISC23, MT_MISC24, MT_MISC25, MT_CHAINGUN, MT_MISC26, MT_MISC27, MT_MISC28, MT_SHOTGUN, MT_SUPERSHOTGUN, MT_MISC29, MT_MISC30, MT_MISC31, MT_MISC32, MT_MISC33, MT_MISC34, MT_MISC35, MT_MISC36, MT_MISC37, MT_MISC38, MT_MISC39, MT_MISC40, MT_MISC41, MT_MISC42, MT_MISC43, MT_MISC44, MT_MISC45, MT_MISC46, MT_MISC47, MT_MISC48, MT_MISC49, MT_MISC50, MT_MISC51, MT_MISC52, MT_MISC53, MT_MISC54, MT_MISC55, MT_MISC56, MT_MISC57, MT_MISC58, MT_MISC59, MT_MISC60, MT_MISC61, MT_MISC62, MT_MISC63, MT_MISC64, MT_MISC65, MT_MISC66, MT_MISC67, MT_MISC68, MT_MISC69, MT_MISC70, MT_MISC71, MT_MISC72, MT_MISC73, MT_MISC74, MT_MISC75, MT_MISC76, MT_MISC77, MT_MISC78, MT_MISC79, MT_MISC80, MT_MISC81, MT_MISC82, MT_MISC83, MT_MISC84, MT_MISC85, MT_MISC86, NUMMOBJTYPES } mobjtype_t; /* // Original mobj info struct. typedef struct { int doomednum; int spawnstate; int spawnhealth; int seestate; int seesound; int reactiontime; int attacksound; int painstate; int painchance; int painsound; int meleestate; int missilestate; int deathstate; int xdeathstate; int deathsound; int speed; int radius; int height; int mass; int damage; int activesound; int flags; int raisestate; } mobjinfo_t; */ #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_think.h0000644000175000017500000000340711357170242023076 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_think.h: MapObj data. * * Map Objects or mobjs are actors, entities, thinker, take-your-pick... * anything that moves, acts, or suffers state changes of more or less * violent nature. */ #ifndef __D_THINK__ #define __D_THINK__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #ifdef __GNUG__ #pragma interface #endif /** * Experimental stuff. * To compile this as "ANSI C with classes" we will need to handle the * various action functions cleanly. */ typedef void (*actionf_v) (); typedef void (*actionf_p1) (void *); typedef void (*actionf_p2) (void *, void *); #define NOPFUNC ((actionf_v) (-1)) typedef union { actionf_p1 acp1; actionf_v acv; actionf_p2 acp2; } actionf_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_refresh.h0000644000175000017500000000266711357170242023426 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_refresh.h: */ #ifndef __D_REFRESH_H__ #define __D_REFRESH_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "p_mobj.h" extern float quitDarkenOpacity; void D_Display(int layer); void D_Display2(void); void R_SetViewSize(int blocks); void R_DrawSpecialFilter(int pnum); void R_DrawMapTitle(void); void P_SetDoomsdayFlags(mobj_t* mo); void R_SetAllDoomsdayFlags(void); boolean R_GetFilterColor(float rgba[4], int filter); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_config.h0000644000175000017500000001674611357170242023240 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_config.h: jDoom configuration. * Global settings. Most of these are console variables. */ #ifndef __JDOOM_SETTINGS_H__ #define __JDOOM_SETTINGS_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "doomdef.h" enum { HUD_HEALTH, HUD_ARMOR, HUD_AMMO, HUD_KEYS, HUD_FRAGS, HUD_FACE, NUMHUDDISPLAYS }; // Hud Unhide Events (the hud will unhide on these events if enabled). typedef enum { HUE_FORCE = -1, HUE_ON_DAMAGE, HUE_ON_PICKUP_HEALTH, HUE_ON_PICKUP_ARMOR, HUE_ON_PICKUP_POWER, HUE_ON_PICKUP_WEAPON, HUE_ON_PICKUP_AMMO, HUE_ON_PICKUP_KEY, NUMHUDUNHIDEEVENTS } hueevent_t; // WARNING: Do not use the boolean type. Its size can be either 1 or 4 bytes // depending on build settings. typedef struct jdoom_config_s { float playerMoveSpeed; int dclickUse; int useMLook; // Mouse look (mouse Y => viewpitch) int useJLook; // Joy look (joy Y => viewpitch) int alwaysRun; // Always run. int noAutoAim; // No auto-aiming? int jLookDeltaMode; int lookSpring; float lookSpeed; float turnSpeed; byte povLookAround; int jumpEnabled; float jumpPower; int airborneMovement; byte setSizeNeeded; int setBlocks; int screenBlocks; byte deathLookUp; // look up when killed byte slidingCorpses; byte fastMonsters; byte echoMsg; float menuScale; int menuEffects; int hudFog; float menuGlitter; float menuShadow; int menuQuitSound; byte menuSlam; byte menuHotkeys; byte askQuickSaveLoad; float flashColor[3]; int flashSpeed; byte turningSkull; byte hudShown[NUMHUDDISPLAYS]; // HUD data visibility. byte hudKeysCombine; // One icon per color (e.g. if red key and red skull is owned only show red key). float hudScale; // How to scale HUD data? float hudColor[4]; float hudIconAlpha; float hudTimer; // Number of seconds until the hud/statusbar auto-hides. byte hudUnHide[NUMHUDUNHIDEEVENTS]; // when the hud/statusbar unhides. byte usePatchReplacement; byte moveCheckZ; // if true, mobjs can move over/under each other. byte weaponAutoSwitch; byte noWeaponAutoSwitchIfFiring; byte ammoAutoSwitch; byte berserkAutoSwitch; int weaponOrder[NUM_WEAPON_TYPES]; byte weaponNextMode; // if true use the weaponOrder for next/previous. byte secretMsg; float filterStrength; int plrViewHeight; byte mapTitle, hideIWADAuthor; float menuColor[3]; float menuColor2[3]; byte noCoopDamage; byte noTeamDamage; byte noCoopWeapons; byte noCoopAnything; byte noNetBFG; byte coopRespawnItems; byte respawnMonstersNightmare; int statusbarScale; float statusbarOpacity; float statusbarCounterAlpha; /** Compatibility options. * \todo Put these into an array so we can use a bit array to change * multiple options based on a compatibility mode (ala PrBoom). */ byte raiseGhosts; byte maxSkulls; byte allowSkullsInWalls; byte anyBossDeath; byte monstersStuckInDoors; byte avoidDropoffs; byte moveBlock; // Dont handle large negative movement in P_TryMove. byte wallRunNorthOnly; // If handle large make exception for wallrunning byte zombiesCanExit; // Zombie players can exit levels. byte fallOff; // Objects fall under their own weight. byte fixOuchFace; byte fixStatusbarOwnedWeapons; byte counterCheat; float counterCheatScale; // Automap stuff. /* int automapPos; float automapWidth; float automapHeight;*/ float automapMobj[3]; float automapL0[3]; float automapL1[3]; float automapL2[3]; float automapL3[3]; float automapBack[3]; float automapOpacity; float automapLineAlpha; byte automapRotate; int automapHudDisplay; int automapCustomColors; byte automapShowDoors; float automapDoorGlow; byte automapBabyKeys; float automapZoomSpeed; float automapPanSpeed; byte automapPanResetOnOpen; float automapOpenSeconds; int msgCount; float msgScale; float msgUptime; int msgBlink; int msgAlign; byte msgShow; float msgColor[3]; char *chatMacros[10]; byte chatBeep; int corpseTime; byte killMessages; float bobWeapon, bobView; byte bobWeaponLower; int cameraNoClip; // Crosshair. int xhair; float xhairSize; byte xhairVitality; float xhairColor[4]; // Network. byte netDeathmatch; byte netBFGFreeLook; // Allow free-aim with BFG. byte netMobDamageModifier; // Multiplier for non-player mobj damage. byte netMobHealthModifier; // Health modifier for non-player mobjs. int netGravity; // Multiplayer custom gravity. byte netNoMaxZRadiusAttack; // Radius attacks are infinitely tall. byte netNoMaxZMonsterMeleeAttack; // Melee attacks are infinitely tall. byte netNoMonsters; byte netRespawn; byte netJumping; byte netEpisode; byte netMap; byte netSkill; byte netSlot; byte netColor; int playerColor[MAXPLAYERS]; } game_config_t; extern game_config_t cfg; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/tables.h0000644000175000017500000000404311357170242022725 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * tables.h: Lookup tables. */ #ifndef __TABLES__ #define __TABLES__ #include "doomsday.h" #define PI 3.141592657 #define FINEANGLES 8192 #define FINEMASK (FINEANGLES-1) #define ANGLETOFINESHIFT 19 // shifts from 0x100000000 to 0x2000 // Binary Angle Measument, BAM. #define ANG45 0x20000000 #define ANG90 0x40000000 #define ANG180 0x80000000 #define ANG270 0xc0000000 #define SLOPERANGE 2048 #define SLOPEBITS 11 #define DBITS (FRACBITS-SLOPEBITS) // Effective size is 10240. extern fixed_t finesine[5 * FINEANGLES / 4]; // Re-use data, is just PI/2 pahse shift. extern fixed_t *finecosine; // Effective size is 4096. extern fixed_t finetangent[FINEANGLES / 2]; // Effective size is 2049; // The +1 size is to handle the case when x==y without additional checking. extern angle_t tantoangle[SLOPERANGE + 1]; // Utility function, called by R_PointToAngle. int SlopeDiv(unsigned num, unsigned den); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/g_game.h0000644000175000017500000000654611357170242022704 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_game.h: Top-level (common) game routines jDoom - specific. */ #ifndef __G_GAME_H__ #define __G_GAME_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "doomdef.h" #include "d_event.h" #include "d_player.h" extern player_t players[MAXPLAYERS]; extern uint nextMap; extern skillmode_t gameSkill; extern uint gameEpisode; extern uint gameMap; extern uint nextMap; // If non zero this will be the next map. extern boolean secretExit; extern int totalKills, totalItems, totalSecret; extern boolean deathmatch; extern boolean respawnMonsters; extern boolean userGame; extern boolean paused; extern boolean precache; extern wbstartstruct_t wmInfo; extern int bodyQueueSlot; extern int mapStartTic; extern int gsvMapMusic; void G_Register(void); void G_CommonPreInit(void); void G_CommonPostInit(void); void R_InitRefresh(void); void G_PrintMapList(void); boolean G_ValidateMap(uint* episode, uint* map); uint G_GetMapNumber(uint episode, uint map); void G_InitNew(skillmode_t skill, uint episode, uint map); // Can be called by the startup code or Hu_MenuResponder. // A normal game starts at map 1, // but a warp test can start elsewhere void G_DeferedInitNew(skillmode_t skill, uint episode, uint map); void G_DeferedPlayDemo(char* demo); // Can be called by the startup code or Hu_MenuResponder, // calls P_SetupMap or W_EnterWorld. void G_LoadGame(const char* name); void G_DoLoadGame(void); // Called by Hu_MenuResponder. void G_SaveGame(int slot, const char* description); void G_StopDemo(void); void G_DemoEnds(void); void G_DemoAborted(void); void G_DoReborn(int playernum); void G_PlayerReborn(int player); void G_LeaveMap(uint newMap, uint entryPoint, boolean secretExit); uint G_GetNextMap(uint episode, uint map, boolean secretExit); boolean P_MapExists(uint episode, uint map); void G_WorldDone(void); void G_Ticker(timespan_t ticLength); boolean G_Responder(event_t* ev); void G_ScreenShot(void); void G_PrepareWIData(void); void G_QueueBody(mobj_t* body); void P_GetMapLumpName(uint episode, uint map, char* lumpName); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/d_main.h0000644000175000017500000000342011357170242022700 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * d_main.h: */ #ifndef __D_MAIN_H__ #define __D_MAIN_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "doomdef.h" extern int verbose; extern boolean devParm; extern boolean noMonstersParm; extern boolean respawnParm; extern boolean fastParm; extern boolean turboParm; extern float turboMul; extern gamemode_t gameMode; extern int gameModeBits; extern gamemission_t gameMission; extern char gameModeString[]; extern boolean monsterInfight; extern char *borderLumps[]; void G_PostInit(void); void G_PreInit(void); void G_DetectIWADs(void); void G_IdentifyVersion(void); void G_Shutdown(void); void G_EndFrame(void); void G_Ticker(timespan_t ticLength); boolean G_SetGameMode(gamemode_t mode); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/include/m_menu.h0000644000175000017500000000251011357170242022730 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_menu.h: Menu widget stuff, episode selection and such. */ #ifndef __M_MENU_H__ #define __M_MENU_H__ #ifndef __JDOOM__ # error "Using jDoom headers without __JDOOM__" #endif #include "hu_stuff.h" #include "d_event.h" void M_LoadData(void); boolean MN_CurrentMenuHasBackground(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/0000755000175000017500000000000011523516204020574 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2maps.ded0000644000175000017500000000710511357170242023161 0ustar keeskees# # jDoom: DOOM2 Maps # # The default definition, used for any maps without a map info definition. Map Info { ID = "*"; Name = "Unnamed"; Author = "Unknown"; Music = "runnin"; Gravity = 1; Sky = "sky1"; } Map Info { ID = "MAP01"; Name = "HUSTR_1"; Author = "id Software"; Music = "runnin"; Par time = 30; Gravity = 1; Sky = "sky1"; } Copy Map Info { ID = "MAP02"; Name = "HUSTR_2"; Music = "stalks"; Par time = 90; } Copy Map Info { ID = "MAP03"; Name = "HUSTR_3"; Music = "countd"; Par time = 120; } Copy Map Info { ID = "MAP04"; Name = "HUSTR_4"; Music = "betwee"; Par time = 120; } Copy Map Info { ID = "MAP05"; Name = "HUSTR_5"; Music = "doom"; Par time = 90; } Copy Map Info { ID = "MAP06"; Name = "HUSTR_6"; Music = "the_da"; Par time = 150; } Copy Map Info { ID = "MAP07"; Name = "HUSTR_7"; Music = "shawn"; Par time = 120; } Copy Map Info { ID = "MAP08"; Name = "HUSTR_8"; Music = "ddtblu"; Par time = 120; } Copy Map Info { ID = "MAP09"; Name = "HUSTR_9"; Music = "in_cit"; Par time = 270; } Copy Map Info { ID = "MAP10"; Name = "HUSTR_10"; Par time = 90; Music = "dead"; } Copy Map Info { ID = "MAP11"; Name = "HUSTR_11"; Music = "stlks2"; Par time = 210; } # From MAP12 onwards, the sky changes to SKY2. Copy Map Info { ID = "MAP12"; Name = "HUSTR_12"; Music = "theda2"; Par time = 150; Sky = "sky2"; } Copy Map Info { ID = "MAP13"; Name = "HUSTR_13"; Music = "doom2"; Par time = 150; } Copy Map Info { ID = "MAP14"; Name = "HUSTR_14"; Music = "ddtbl2"; Par time = 150; } Copy Map Info { ID = "MAP15"; Name = "HUSTR_15"; Music = "runni2"; Par time = 210; } Copy Map Info { ID = "MAP16"; Name = "HUSTR_16"; Music = "dead2"; Par time = 150; } Copy Map Info { ID = "MAP17"; Name = "HUSTR_17"; Music = "stlks3"; Par time = 420; } Copy Map Info { ID = "MAP18"; Name = "HUSTR_18"; Music = "romero"; Par time = 150; } Copy Map Info { ID = "MAP19"; Name = "HUSTR_19"; Music = "shawn2"; Par time = 210; } Copy Map Info { ID = "MAP20"; Name = "HUSTR_20"; Music = "messag"; Par time = 150; } # From MAP21 onwards, the sky changes to SKY3 Copy Map Info { ID = "MAP21"; Name = "HUSTR_21"; Music = "count2"; Par time = 240; Sky = "sky3"; } Copy Map Info { ID = "MAP22"; Name = "HUSTR_22"; Music = "ddtbl3"; Par time = 150; } Copy Map Info { ID = "MAP23"; Name = "HUSTR_23"; Music = "ampie"; Par time = 180; } Copy Map Info { ID = "MAP24"; Name = "HUSTR_24"; Author = "id Software"; Music = "theda3"; Par time = 150; } Copy Map Info { ID = "MAP25"; Name = "HUSTR_25"; Music = "adrian"; Par time = 150; } Copy Map Info { ID = "MAP26"; Name = "HUSTR_26"; Music = "messg2"; Par time = 300; } Copy Map Info { ID = "MAP27"; Name = "HUSTR_27"; Music = "romer2"; Par time = 330; } Copy Map Info { ID = "MAP28"; Name = "HUSTR_28"; Music = "tense"; Par time = 420; } Copy Map Info { ID = "MAP29"; Name = "HUSTR_29"; Music = "shawn3"; Par time = 300; } Copy Map Info { ID = "MAP30"; Name = "HUSTR_30"; Music = "openin"; Par time = 180; } Copy Map Info { ID = "MAP31"; Name = "HUSTR_31"; Music = "evil"; Par time = 120; } Copy Map Info { ID = "MAP32"; Name = "HUSTR_32"; Music = "ultima"; Par time = 30; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2anim.ded0000644000175000017500000000052711357170242023146 0ustar keeskees# jDoom: DOOM2 specific Animation Sequences Header { Version = 6 } # # Precache groups. # Group { Flags = precache; Texture { ID = "SW1SKULL"; Tics = 0; }; Texture { ID = "SW2SKULL"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1GSTON"; Tics = 0; }; Texture { ID = "SW2GSTON"; Tics = 0; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom1anim.ded0000644000175000017500000000674411357170242023154 0ustar keeskees# jDoom: DOOM specific Animation Sequences Header { Version = 6 } # # Precache groups. # Group { Flags = precache; Texture { ID = "SW1BRCOM"; Tics = 0; }; Texture { ID = "SW2BRCOM"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1BRN1"; Tics = 0; }; Texture { ID = "SW2BRN1"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1BRN2"; Tics = 0; }; Texture { ID = "SW2BRN2"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1BRNGN"; Tics = 0; }; Texture { ID = "SW2BRNGN"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1BROWN"; Tics = 0; }; Texture { ID = "SW2BROWN"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1COMM"; Tics = 0; }; Texture { ID = "SW2COMM"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1COMP"; Tics = 0; }; Texture { ID = "SW2COMP"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1DIRT"; Tics = 0; }; Texture { ID = "SW2DIRT"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1EXIT"; Tics = 0; }; Texture { ID = "SW2EXIT"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1GRAY"; Tics = 0; }; Texture { ID = "SW2GRAY"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1GRAY1"; Tics = 0; }; Texture { ID = "SW2GRAY1"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1METAL"; Tics = 0; }; Texture { ID = "SW2METAL"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1PIPE"; Tics = 0; }; Texture { ID = "SW2PIPE"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1SLAD"; Tics = 0; }; Texture { ID = "SW2SLAD"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1STARG"; Tics = 0; }; Texture { ID = "SW2STARG"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1STON1"; Tics = 0; }; Texture { ID = "SW2STON2"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1STONE"; Tics = 0; }; Texture { ID = "SW2STONE"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1STRTN"; Tics = 0; }; Texture { ID = "SW2STRTN"; Tics = 0; }; } # The rest of this file is skipped if DOOM - shareware. SkipIf doom1-share; Group { Flags = precache; Texture { ID = "SW1BLUE"; Tics = 0; }; Texture { ID = "SW2BLUE"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1CMT"; Tics = 0; }; Texture { ID = "SW2CMT"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1GARG"; Tics = 0; }; Texture { ID = "SW2GARG"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1GSTON"; Tics = 0; }; Texture { ID = "SW2GSTON"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1HOT"; Tics = 0; }; Texture { ID = "SW2HOT"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1LION"; Tics = 0; }; Texture { ID = "SW2LION"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1SATYR"; Tics = 0; }; Texture { ID = "SW2SATYR"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1SKIN"; Tics = 0; }; Texture { ID = "SW2SKIN"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1VINE"; Tics = 0; }; Texture { ID = "SW2VINE"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW1WOOD"; Tics = 0; }; Texture { ID = "SW2WOOD"; Tics = 0; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/special.ded0000644000175000017500000000011411357170242022671 0ustar keeskees# jDoom: Special Effects Header { Version = 5; } Include "particles.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/skies.ded0000644000175000017500000000040211357170242022367 0ustar keeskees# # jDoom: Skies # IncludeIf doom1 "doom1skies.ded"; IncludeIf doom1-share "doom1skies.ded"; IncludeIf doom1-ultimate "doom1skies.ded"; IncludeIf doom2 "doom2skies.ded"; IncludeIf doom2-plut "doom2skies.ded"; IncludeIf doom2-tnt "doom2skies.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2-plutlights.ded0000644000175000017500000000101611357170242024470 0ustar keeskees# jDoom: Light Decorations for Doom II-plut Header { Version = 6; } # This file is skipped if not Doom II Plutonia. SkipIf Not doom2-plut; #####====--- LIGHT DECORATIONS FOR DOOM II PLUTONIA ---====##### # # The default flags allow using these only with the original textures. # Use "dcf_pwad" and "dcf_ext" to allow using with PWAD and external # resources. # # There can only be one decoration per texture/flat. Newer decorations # override older ones. # # One decoration can specify up to 16 lights. # deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/values.ded0000644000175000017500000001221011357170242022550 0ustar keeskees# jDoom: Values # (mind yur speling; jDoom uses only the identifiers it knows about) # # The strings from all Values definition blocks are merged together. # This means you don't have to add all your values here; they can be # in a Values block in another file. Header { Version = 5; } # The "Patch Replacement" values are used to replace patches with # strings of text. The replacement overrides any checks for external # resources. Only patches in an IWAD can be replaced; this is required # because existing PWADs may replace the original text patches with # their own graphics. # # The replacement is done by searching a value in the "Patch # Replacement" block that matches the lump name of the patch to be # replaced. The text string may optionally contain parameters that # control how the string is displayed. The parameters must be placed # inside braces. If a parameter block is present, the actual text # string begins from the first character following the closing brace. # # "{fonta, scale=2}C{scale=1}APITAL" # # Whitespace inside a parameter block is ignored. Use a comma or a # semicolon to separate parameters. The parameters and their default # values are: # # fonta Use the small font. # fontb Use the large font (the default). # r=1.0 Red color component (0..1). # g=0.0 Green color component (0..1). # b=0.0 Blue color component (0..1). # x=0 Offset to the X coordinate. # y=0 Offset to the Y coordinate. # scale=1.0 Uniform scaling factor (both X and Y). # scalex=1.0 X scaling factor. # scaley=1.0 Y scaling factor. # angle=0.0 Rotation angle (around initial origin). # flash Enable flashy type-in effect. # noflash Disable it (the default). # case Enable case-based scaling. # nocase Disable it (the default). # ups=1.25 Upper case Y scale. # upo=0.0 Upper case Y offset. # los=1.0 Lower case Y scale. # loo=3.0 Lower case Y offset. # break Start a new line. # # An example: # # Values { # Patch Replacement { # M_DOOM = "{R=.5; G=1; B=.5; scale=3}G{scale=2;y=10}ONE { # scale=3;y=0}F{ scale = 2; y = 10 }I{break}SHING"; # }; # } Values { Player { Health = "100"; # Initial health. Max Health = "100"; # Maximum health. Health Limit = "200"; # Absolute health limit. God Health = "100"; # Health when god mode is activated. Green Armor = "100"; Blue Armor = "200"; IDFA Armor = "200"; # Armor given when the IDFA cheat is activated. IDKFA Armor = "200"; # Armor given when the IDKFA cheat is activated. Max Ammo { Clip = "200"; Shell = "50"; Cell = "300"; Misl = "50"; }; Clip Ammo { Clip = "10"; Shell = "4"; Cell = "20"; Misl = "1"; }; Init Ammo { Clip = "50"; Shell = "0"; Cell = "0"; Misl = "0"; }; }; MegaSphere { Give { Health = "200"; }; }; SoulSphere { Give { Health = "100"; Health Limit = "200"; }; }; # Weapon Info|*|Static # Defaults to "0". "1" = prevent the lowering of the HUD weapon when doing a switch. # Weapon Info|*|Owned # Defaults to "0". "1" = this weapon will be given to the player when spawned. Weapon Info { 0 { Type = "noammo"; Up = "PUNCHUP"; Down = "PUNCHDOWN"; Ready = "PUNCH"; Atk = "PUNCH1"; Flash = "NULL"; Owned = "1"; Static = "0"; }; 1 { Type = "clip"; Per shot = "1"; Up = "PISTOLUP"; Down = "PISTOLDOWN"; Ready = "PISTOL"; Atk = "PISTOL1"; Flash = "PISTOLFLASH"; Owned = "1"; Static = "0"; }; 2 { Type = "shell"; Per shot = "1"; Up = "SGUNUP"; Down = "SGUNDOWN"; Ready = "SGUN"; Atk = "SGUN1"; Flash = "SGUNFLASH1"; Owned = "0"; Static = "0"; }; 3 { Type = "clip"; Per shot = "1"; Up = "CHAINUP"; Down = "CHAINDOWN"; Ready = "CHAIN"; Atk = "CHAIN1"; Flash = "CHAINFLASH1"; Owned = "0"; Static = "0"; }; 4 { Type = "misl"; Per shot = "1"; Up = "MISSILEUP"; Down = "MISSILEDOWN"; Ready = "MISSILE"; Atk = "MISSILE1"; Flash = "MISSILEFLASH1"; Owned = "0"; Static = "0"; }; 5 { Type = "cell"; Per shot = "1"; Up = "PLASMAUP"; Down = "PLASMADOWN"; Ready = "PLASMA"; Atk = "PLASMA1"; Flash = "PLASMAFLASH1"; Owned = "0"; Static = "0"; }; 6 { Type = "cell"; Per shot = "40"; Up = "BFGUP"; Down = "BFGDOWN"; Ready = "BFG"; Atk = "BFG1"; Flash = "BFGFLASH1"; Owned = "0"; Static = "0"; }; 7 { Type = "noammo"; Up = "SAWUP"; Down = "SAWDOWN"; Ready = "SAW"; Atk = "SAW1"; Flash = "NULL"; Owned = "0"; Static = "0"; }; 8 { Type = "shell"; Per shot = "2"; Up = "DSGUNUP"; Down = "DSGUNDOWN"; Ready = "DSGUN"; Atk = "DSGUN1"; Flash = "DSGUNFLASH1"; Owned = "0"; Static = "0"; }; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/flags.ded0000644000175000017500000000460711357170242022360 0ustar keeskees# jDoom: Flags # Mobj flags: Flag { ID = "mf_special"; Value = 0x1; } Flag { ID = "mf_solid"; Value = 0x2; } Flag { ID = "mf_shootable"; Value = 0x4; } Flag { ID = "mf_nosector"; Value = 0x8; } Flag { ID = "mf_noblockmap"; Value = 0x10; } Flag { ID = "mf_ambush"; Value = 0x20; } Flag { ID = "mf_justhit"; Value = 0x40; } Flag { ID = "mf_justattacked"; Value = 0x80; } Flag { ID = "mf_spawnceiling"; Value = 0x100; } Flag { ID = "mf_nogravity"; Value = 0x200; } Flag { ID = "mf_dropoff"; Value = 0x400; } Flag { ID = "mf_pickup"; Value = 0x800; } Flag { ID = "mf_noclip"; Value = 0x1000; } Flag { ID = "mf_float"; Value = 0x4000; } Flag { ID = "mf_teleport"; Value = 0x8000; } Flag { ID = "mf_missile"; Value = 0x10000; } Flag { ID = "mf_dropped"; Value = 0x20000; } Flag { ID = "mf_shadow"; Value = 0x40000; } Flag { ID = "mf_noblood"; Value = 0x80000; } Flag { ID = "mf_corpse"; Value = 0x100000; } Flag { ID = "mf_infloat"; Value = 0x200000; } Flag { ID = "mf_countkill"; Value = 0x400000; } Flag { ID = "mf_countitem"; Value = 0x800000; } Flag { ID = "mf_skullfly"; Value = 0x1000000; } Flag { ID = "mf_notdmatch"; Value = 0x2000000; } Flag { ID = "mf_translation"; Value = 0xC000000; } Flag { ID = "mf_transshift"; Value = 0x1A; } Flag { ID = "mf_local"; Value = 0x10000000; } Flag { ID = "mf_brightshadow"; Value = 0x20000000; } Flag { ID = "mf_brightexplode"; Value = 0x40000000; } Flag { ID = "mf_viewalign"; Value = 0x80000000; } # Mobj flags2: Flag { ID = "mf2_lograv"; Value = 0x1; } Flag { ID = "mf2_floorbounce"; Value = 0x4; } Flag { ID = "mf2_thrughost"; Value = 0x8; } Flag { ID = "mf2_fly"; Value = 0x10; } Flag { ID = "mf2_floorclip"; Value = 0x20; } Flag { ID = "mf2_spawnfloat"; Value = 0x40; } Flag { ID = "mf2_noteleport"; Value = 0x80; } Flag { ID = "mf2_rip"; Value = 0x100; } Flag { ID = "mf2_pushable"; Value = 0x200; } Flag { ID = "mf2_slide"; Value = 0x400; } Flag { ID = "mf2_alwayslit"; Value = 0x800; } Flag { ID = "mf2_passmobj"; Value = 0x1000; } Flag { ID = "mf2_cannotpush"; Value = 0x2000; } Flag { ID = "mf2_radiusattacknomaxz"; Value = 0x4000; } Flag { ID = "mf2_boss"; Value = 0x8000; } Flag { ID = "mf2_nodmgthrust"; Value = 0x20000; } Flag { ID = "mf2_telestomp"; Value = 0x40000; } Flag { ID = "mf2_floatbob"; Value = 0x80000; } Flag { ID = "mf2_dontdraw"; Value = 0x100000; } # Mobj flags3: Flag { ID = "mf3_noinfight"; Value = 0x1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2-tntfinales.ded0000644000175000017500000001745511357170242024456 0ustar keeskees# jDoom: Intermissions and Finales (Final DOOM/TNT) # (see Doc\InFine.txt) Header { Version = 5; } # I'm using "textdef" to allow compatibility with DeHackEd. # A better way would just be to use "text" and define the text # in the script, no need to go about modifying the Text defs. ########========-------- TNT: EVILUTION --------========######## Finale { Before = "MAP07"; Script { music "read_m" flat SLIME16 wait 0.5 textdef msg 10 10 "T1TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP12"; Script { music "read_m" flat RROCK14 wait 0.5 textdef msg 10 10 "T2TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP21"; Script { music "read_m" flat RROCK07 wait 0.5 textdef msg 10 10 "T3TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } # This is the actual finale of TNT: Evilution. Finale { After = "MAP30"; Script { music "read_m" flat RROCK17 wait 0.5 textdef msg 10 10 "T4TEXT" waittext msg; wait 7 skiphere #####====--- The Cast ---====##### # Castloop continues forever. # Quite a number of monsters here...! noskip # No more skipping (pause waits for a key, though). deltext msg music "evil" noflat; patch back 0 0 BOSSBACK marker castloop # Create a text for the name. textdef name 160 180 CC_ZOMBIE center name; rate name 0 patch mo 160 170 POSSA1 # "mo" is used for all the monsters. # --- Zombieman --- clranim mo states mo POSS_RUN1 12 states mo POSS_ATK1 2; picsound mo "pistol" states mo POSS_ATK3 1 repeat mo seesound POSSESSED; pause; diesound POSSESSED clranim mo states mo POSS_DIE1 5 waitanim mo; wait 0.43 # --- Shotgun Guy --- clranim mo states mo SPOS_RUN1 12 states mo SPOS_ATK1 2; picsound mo "shotgn" states mo SPOS_ATK3 1 repeat mo settextdef name CC_SHOTGUN seesound SHOTGUY; pause; diesound SHOTGUY clranim mo states mo SPOS_DIE1 5 waitanim mo; wait 0.43 # --- Heavy Weapon Dude --- clranim mo states mo CPOS_RUN1 12 states mo CPOS_ATK1 2; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" states mo CPOS_ATK4 1; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" states mo CPOS_ATK4 1; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" repeat mo settextdef name CC_HEAVY seesound CHAINGUY; pause; diesound CHAINGUY clranim mo states mo CPOS_DIE1 7 waitanim mo; wait 0.43 # --- Imp --- clranim mo states mo TROO_RUN1 12 states mo TROO_ATK1 3; picsound mo "claw" repeat mo settextdef name CC_IMP seesound TROOP; pause; diesound TROOP clranim mo states mo TROO_DIE1 5 waitanim mo; wait 0.43 # --- Demon --- clranim mo states mo SARG_RUN1 12 states mo SARG_ATK1 2; picsound mo "sgtatk" states mo SARG_ATK3 1 repeat mo settextdef name CC_DEMON seesound SERGEANT; pause; diesound SERGEANT clranim mo states mo SARG_DIE1 6 waitanim mo; wait 0.43 # --- Lost Soul --- clranim mo states mo SKULL_RUN1 12 states mo SKULL_ATK1 2; picsound mo "sklatk" states mo SKULL_ATK3 8 repeat mo settextdef name CC_LOST seesound SKULL; pause; diesound SKULL clranim mo states mo SKULL_DIE1 6 waitanim mo; wait 0.43 # --- Cacodemon --- clranim mo states mo HEAD_RUN1 12 states mo HEAD_ATK1 2; picsound mo "firsht" states mo HEAD_ATK3 1 repeat mo settextdef name CC_CACO seesound HEAD; pause; diesound HEAD clranim mo states mo HEAD_DIE1 6 waitanim mo; wait 0.43 # --- Hell Knight --- clranim mo states mo BOS2_RUN1 12 states mo BOS2_ATK1 2; picsound mo "firsht" states mo BOS2_ATK3 1 repeat mo settextdef name CC_HELL seesound KNIGHT; pause; diesound KNIGHT clranim mo states mo BOS2_DIE1 7 waitanim mo; wait 0.43 # --- Baron of Hell --- clranim mo states mo BOSS_RUN1 12 states mo BOSS_ATK1 2; picsound mo "firsht" states mo BOSS_ATK3 1 repeat mo settextdef name CC_BARON seesound BRUISER; pause; diesound BRUISER clranim mo states mo BOSS_DIE1 7 waitanim mo; wait 0.43 # --- Arachnotron --- clranim mo states mo BSPI_SIGHT 12 states mo BSPI_ATK1 2; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 2 repeat mo settextdef name CC_ARACH seesound BABY; pause; diesound BABY clranim mo states mo BSPI_DIE1 7 waitanim mo; wait 0.43 # --- Pain Elemental --- clranim mo states mo PAIN_RUN1 12 states mo PAIN_ATK1 3; picsound mo "sklatk" states mo PAIN_ATK4 1 repeat mo settextdef name CC_PAIN seesound PAIN; pause; diesound PAIN clranim mo states mo PAIN_DIE1 6 waitanim mo; wait 0.43 # --- Revenant --- clranim mo states mo SKEL_RUN1 12 states mo SKEL_MISS1 2; picsound mo "skeatk" states mo SKEL_MISS3 2 states mo SKEL_RUN1 12 states mo SKEL_FIST1 2; picsound mo "skeswg" states mo SKEL_FIST3 2; picsound mo "skepch" repeat mo settextdef name CC_REVEN seesound UNDEAD; pause; diesound UNDEAD clranim mo states mo SKEL_DIE1 6 waitanim mo; wait 0.43 # --- Mancubus --- clranim mo states mo FATT_RUN1 12 states mo FATT_ATK1 2; picsound mo "firsht" states mo FATT_ATK3 3; picsound mo "firsht" states mo FATT_ATK6 3; picsound mo "firsht" states mo FATT_ATK9 2 repeat mo settextdef name CC_MANCU seesound FATSO; pause; diesound FATSO clranim mo states mo FATT_DIE1 10 waitanim mo; wait 0.43 # --- Arch-Vile --- clranim mo states mo VILE_RUN1 12 states mo VILE_ATK1 2; picsound mo "vilatk" states mo VILE_ATK3 9 repeat mo settextdef name CC_ARCH seesound VILE; pause; diesound VILE clranim mo states mo VILE_DIE1 10 waitanim mo; wait 0.43 # --- The Spider Mastermind --- clranim mo states mo SPID_RUN1 12 states mo SPID_ATK1 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" repeat mo settextdef name CC_SPIDER seesound SPIDER; pause; diesound SPIDER clranim mo states mo SPID_DIE1 11 waitanim mo; wait 0.43 # --- Cyberdemon --- clranim mo states mo CYBER_RUN1 12 states mo CYBER_ATK1 2; picsound mo "rlaunc" states mo CYBER_ATK3 2; picsound mo "rlaunc" states mo CYBER_ATK5 2; picsound mo "rlaunc" repeat mo settextdef name CC_CYBER seesound CYBORG; pause; diesound CYBORG clranim mo states mo CYBER_DIE1 10 waitanim mo; wait 0.43 # --- Our Hero (finally!) --- clranim mo states mo PLAY_RUN1 12 states mo PLAY_ATK1 1 repeat mo settextdef name CC_HERO seesound PLAYER; pause; diesound PLAYER clranim mo states mo PLAY_DIE1 7 waitanim mo; wait 0.43 # Restart the loop. goto castloop }; } # Secret level 1. Finale { Before = "MAP31"; Script { music "read_m"; flat RROCK13; wait 0.5; textdef msg 10 10 "T5TEXT"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. }; } # Secret level 2. Finale { Before = "MAP32"; Script { music "read_m"; flat RROCK19; wait 0.5; textdef msg 10 10 "T6TEXT"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2music.ded0000644000175000017500000000311011357170242023331 0ustar keeskees# # jDoom: DOOM2 Music. # Music { ID = "None"; } Music { ID = "runnin"; Lump = "D_RUNNIN"; } Music { ID = "stalks"; Lump = "D_STALKS"; } Music { ID = "countd"; Lump = "D_COUNTD"; } Music { ID = "betwee"; Lump = "D_BETWEE"; } Music { ID = "doom"; Lump = "D_DOOM"; } Music { ID = "the_da"; Lump = "D_THE_DA"; } Music { ID = "shawn"; Lump = "D_SHAWN"; } Music { ID = "ddtblu"; Lump = "D_DDTBLU"; } Music { ID = "in_cit"; Lump = "D_IN_CIT"; } Music { ID = "dead"; Lump = "D_DEAD"; } Music { ID = "stlks2"; Lump = "D_STLKS2"; } Music { ID = "theda2"; Lump = "D_THEDA2"; } Music { ID = "doom2"; Lump = "D_DOOM2"; } Music { ID = "ddtbl2"; Lump = "D_DDTBL2"; } Music { ID = "runni2"; Lump = "D_RUNNI2"; } Music { ID = "dead2"; Lump = "D_DEAD2"; } Music { ID = "stlks3"; Lump = "D_STLKS3"; } Music { ID = "romero"; Lump = "D_ROMERO"; } Music { ID = "shawn2"; Lump = "D_SHAWN2"; } Music { ID = "messag"; Lump = "D_MESSAG"; } Music { ID = "count2"; Lump = "D_COUNT2"; } Music { ID = "ddtbl3"; Lump = "D_DDTBL3"; } Music { ID = "ampie"; Lump = "D_AMPIE"; } Music { ID = "theda3"; Lump = "D_THEDA3"; } Music { ID = "adrian"; Lump = "D_ADRIAN"; } Music { ID = "messg2"; Lump = "D_MESSG2"; } Music { ID = "romer2"; Lump = "D_ROMER2"; } Music { ID = "tense"; Lump = "D_TENSE"; } Music { ID = "shawn3"; Lump = "D_SHAWN3"; } Music { ID = "openin"; Lump = "D_OPENIN"; } Music { ID = "evil"; Lump = "D_EVIL"; } Music { ID = "ultima"; Lump = "D_ULTIMA"; } Music { ID = "read_m"; Lump = "D_READ_M"; } Music { ID = "dm2ttl"; Lump = "D_DM2TTL"; } Music { ID = "dm2int"; Lump = "D_DM2INT"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/maps.ded0000644000175000017500000000037211357170242022217 0ustar keeskees# # jDoom: Maps # IncludeIf doom1 "doom1maps.ded"; IncludeIf doom1-share "doom1maps.ded"; IncludeIf doom1-ultimate "doom1maps.ded"; IncludeIf doom2 "doom2maps.ded"; IncludeIf doom2-plut "doom2-plutmaps.ded"; IncludeIf doom2-tnt "doom2-tntmaps.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/plutanim.ded0000644000175000017500000000034111357170242023104 0ustar keeskees# jDoom: Plutonia specific Animation Sequences Header { Version = 5; } # # Precache groups. # Group { Flags = precache; Texture { ID = "SW1GSTON"; Tics = 0; }; Texture { ID = "SW2GSTON"; Tics = 0; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/anim.ded0000644000175000017500000000104311357170242022177 0ustar keeskees# jDoom: Additional Animation Sequences # # DOOM has predefined texture animation sequences. # In order to remain compatible with existing WADs, jDoom builds # animations from these predefined sequences and creates texture # animation groups for them. The flags "tgf_smooth" and # "tgf_first_only" are set for each group. # # Additional sequences can be defined using Group definitions. Header { Version = 6; } Include "doom1anim.ded"; IncludeIf doom2 "doom2anim.ded"; IncludeIf doom2-tnt "doom2anim.ded"; IncludeIf doom2-plut "doom2anim.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/materials.ded0000644000175000017500000000214411357170242023237 0ustar keeskees# jDoom: Material Enhancements # # Patch the Material definitions created automatically # by the engine, adding new effects to them. Header { Version = 6; } # # Skymasked flats: # Material { ID = "F_SKY1"; Namespace = flats; Flags = skymask; } # # Glowing flats: # Material { ID = "LAVA1"; Namespace = flats; Flags = glow; } * Material { ID = "LAVA2"; } * Material { ID = "LAVA3"; } * Material { ID = "LAVA4"; } * Material { ID = "NUKAGE1"; } * Material { ID = "NUKAGE2"; } * Material { ID = "NUKAGE3"; } * Material { ID = "FWATER1"; } * Material { ID = "FWATER2"; } * Material { ID = "FWATER3"; } * Material { ID = "FWATER4"; } # # Glowing textures: # Material { ID = "FIREBLU1"; Namespace = textures; Flags = glow; } * Material { ID = "FIREBLU2"; } * Material { ID = "FIRELAVA"; } * Material { ID = "FIRELAV2"; } * Material { ID = "FIRELAV3"; } * Material { ID = "FIREMAG1"; } * Material { ID = "FIREMAG2"; } * Material { ID = "FIREMAG3"; } * Material { ID = "FIREWALL"; } * Material { ID = "FIREWALA"; } * Material { ID = "FIREWALB"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/audio.ded0000644000175000017500000007553711357170242022377 0ustar keeskees# jDoom: Music and Sound Effects Header { Version = 5; } IncludeIf doom1 "doom1music.ded"; IncludeIf doom1-share "doom1music.ded"; IncludeIf doom1-ultimate "doom1music.ded"; IncludeIf doom2 "doom2music.ded"; IncludeIf doom2-plut "doom2music.ded"; IncludeIf doom2-tnt "doom2music.ded"; #####====--- SOUND EFFECTS ---====##### Sound { ID = "None"; Link pitch = -1; Link volume = -1; Max channels = -1; } Sound { ID = "pistol"; Flags = "sf_shift2"; Lump = "DSPISTOL"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "shotgn"; Flags = "sf_shift2"; Lump = "DSSHOTGN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = 4; } Sound { ID = "sgcock"; Flags = "sf_shift2"; Lump = "DSSGCOCK"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dshtgn"; Flags = "sf_shift2"; Lump = "DSDSHTGN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbopn"; Flags = "sf_shift2"; Lump = "DSDBOPN"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbcls"; Flags = "sf_shift2"; Lump = "DSDBCLS"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "dbload"; Flags = "sf_shift2"; Lump = "DSDBLOAD"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "plasma"; Flags = "sf_shift2"; Lump = "DSPLASMA"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = 4; } Sound { ID = "bfg"; Flags = "sf_shift2"; Lump = "DSBFG"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "sawup"; Flags = "sf_shift"; Lump = "DSSAWUP"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "sawidl"; Flags = "sf_shift"; Lump = "DSSAWIDL"; Link pitch = -1; Link volume = -1; Priority = 118; Max channels = -1; Group = 1; } Sound { ID = "sawful"; Flags = "sf_shift"; Lump = "DSSAWFUL"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "sawhit"; Flags = "sf_shift"; Lump = "DSSAWHIT"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; Group = 1; } Sound { ID = "rlaunc"; Flags = "sf_shift2"; Lump = "DSRLAUNC"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "rxplod"; Flags = "sf_shift2"; Lump = "DSRXPLOD"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "firsht"; Flags = "sf_shift2"; Lump = "DSFIRSHT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "firxpl"; Flags = "sf_shift2"; Lump = "DSFIRXPL"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = 2; } Sound { ID = "pstart"; Flags = "sf_shift2"; Lump = "DSPSTART"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "pstop"; Flags = "sf_shift2"; Lump = "DSPSTOP"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "doropn"; Flags = "sf_shift2"; Lump = "DSDOROPN"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "dorcls"; Flags = "sf_shift2"; Lump = "DSDORCLS"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "stnmov"; Flags = "sf_shift2"; Lump = "DSSTNMOV"; Link pitch = -1; Link volume = -1; Priority = 119; Max channels = -1; } Sound { ID = "swtchn"; Flags = "sf_shift2"; Lump = "DSSWTCHN"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "swtchx"; Flags = "sf_shift2"; Lump = "DSSWTCHX"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "plpain"; Flags = "sf_shift2"; Lump = "DSPLPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "dmpain"; Flags = "sf_shift2"; Lump = "DSDMPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "popain"; Flags = "sf_shift2"; Lump = "DSPOPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "vipain"; Flags = "sf_shift2"; Lump = "DSVIPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "mnpain"; Flags = "sf_shift2"; Lump = "DSMNPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "pepain"; Flags = "sf_shift2"; Lump = "DSPEPAIN"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "slop"; Flags = "sf_shift2"; Lump = "DSSLOP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "itemup"; Lump = "DSITEMUP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = 1; } Sound { ID = "wpnup"; Flags = "sf_shift2"; Lump = "DSWPNUP"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = 1; } Sound { ID = "oof"; Flags = "sf_shift2"; Lump = "DSOOF"; Link pitch = -1; Link volume = -1; Priority = 96; Max channels = -1; } Sound { ID = "telept"; Flags = "sf_shift2"; Lump = "DSTELEPT"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "posit1"; Flags = "sf_shift2"; Lump = "DSPOSIT1"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "posit2"; Flags = "sf_shift2"; Lump = "DSPOSIT2"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "posit3"; Flags = "sf_shift2"; Lump = "DSPOSIT3"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "bgsit1"; Flags = "sf_shift2"; Lump = "DSBGSIT1"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "bgsit2"; Flags = "sf_shift2"; Lump = "DSBGSIT2"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "sgtsit"; Flags = "sf_shift2"; Lump = "DSSGTSIT"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "cacsit"; Flags = "sf_shift2"; Lump = "DSCACSIT"; Link pitch = -1; Link volume = -1; Priority = 98; Max channels = 1; } Sound { ID = "brssit"; Flags = "sf_shift2"; Lump = "DSBRSSIT"; Link pitch = -1; Link volume = -1; Priority = 94; Max channels = 1; } Sound { ID = "cybsit"; Flags = "sf_shift2"; Lump = "DSCYBSIT"; Link pitch = -1; Link volume = -1; Priority = 92; Max channels = 1; } Sound { ID = "spisit"; Flags = "sf_shift2"; Lump = "DSSPISIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "bspsit"; Flags = "sf_shift2"; Lump = "DSBSPSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "kntsit"; Flags = "sf_shift2"; Lump = "DSKNTSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "vilsit"; Flags = "sf_shift2"; Lump = "DSVILSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "mansit"; Flags = "sf_shift2"; Lump = "DSMANSIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "pesit"; Flags = "sf_shift2"; Lump = "DSPESIT"; Link pitch = -1; Link volume = -1; Priority = 90; Max channels = 1; } Sound { ID = "sklatk"; Flags = "sf_shift2"; Lump = "DSSKLATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sgtatk"; Flags = "sf_shift2"; Lump = "DSSGTATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skepch"; Flags = "sf_shift2"; Lump = "DSSKEPCH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "vilatk"; Flags = "sf_shift2"; Lump = "DSVILATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "claw"; Flags = "sf_shift2"; Lump = "DSCLAW"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeswg"; Flags = "sf_shift2"; Lump = "DSSKESWG"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "pldeth"; Flags = "sf_shift2"; Lump = "DSPLDETH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "pdiehi"; Flags = "sf_shift2"; Lump = "DSPDIEHI"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "podth1"; Flags = "sf_shift2"; Lump = "DSPODTH1"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "podth2"; Flags = "sf_shift2"; Lump = "DSPODTH2"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "podth3"; Flags = "sf_shift2"; Lump = "DSPODTH3"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bgdth1"; Flags = "sf_shift2"; Lump = "DSBGDTH1"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bgdth2"; Flags = "sf_shift2"; Lump = "DSBGDTH2"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sgtdth"; Flags = "sf_shift2"; Lump = "DSSGTDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "cacdth"; Flags = "sf_shift2"; Lump = "DSCACDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skldth"; Flags = "sf_shift2"; Lump = "DSSKLDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "brsdth"; Flags = "sf_shift2"; Lump = "DSBRSDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "cybdth"; Flags = "sf_shift2"; Lump = "DSCYBDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "spidth"; Flags = "sf_shift2"; Lump = "DSSPIDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "bspdth"; Flags = "sf_shift2"; Lump = "DSBSPDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "vildth"; Flags = "sf_shift2"; Lump = "DSVILDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "kntdth"; Flags = "sf_shift2"; Lump = "DSKNTDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "pedth"; Flags = "sf_shift2"; Lump = "DSPEDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "skedth"; Flags = "sf_shift2"; Lump = "DSSKEDTH"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "posact"; Flags = "sf_shift2"; Lump = "DSPOSACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "bgact"; Flags = "sf_shift2"; Lump = "DSBGACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "dmact"; Flags = "sf_shift2"; Lump = "DSDMACT"; Link pitch = -1; Link volume = -1; Priority = 120; Max channels = 1; } Sound { ID = "bspact"; Flags = "sf_shift2"; Lump = "DSBSPACT"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "bspwlk"; Flags = "sf_shift2"; Lump = "DSBSPWLK"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "vilact"; Flags = "sf_shift2"; Lump = "DSVILACT"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = 1; } Sound { ID = "noway"; Flags = "sf_shift2"; Lump = "DSNOWAY"; Link pitch = -1; Link volume = -1; Priority = 78; Max channels = -1; } Sound { ID = "barexp"; Flags = "sf_shift2 sf_dontstop"; Lump = "DSBAREXP"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "punch"; Flags = "sf_shift2"; Lump = "DSPUNCH"; Link pitch = -1; Link volume = -1; Priority = 64; Max channels = -1; } Sound { ID = "hoof"; Flags = "sf_shift2"; Lump = "DSHOOF"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "metal"; Flags = "sf_shift2"; Lump = "DSMETAL"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "chgun"; Flags = "sf_shift2"; Lump = "DSCHGUN"; Link = "pistol"; Link pitch = 150; Priority = 64; Max channels = -1; } Sound { ID = "tink"; Lump = "DSTINK"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "bdopn"; Flags = "sf_shift2"; Lump = "DSBDOPN"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "bdcls"; Flags = "sf_shift2"; Lump = "DSBDCLS"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "itmbk"; Flags = "sf_shift2"; Lump = "DSITMBK"; Link pitch = -1; Link volume = -1; Priority = 100; Max channels = -1; } Sound { ID = "flame"; Flags = "sf_shift2"; Lump = "DSFLAME"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "flamst"; Flags = "sf_shift2"; Lump = "DSFLAMST"; Link pitch = -1; Link volume = -1; Priority = 32; Max channels = -1; } Sound { ID = "getpow"; Flags = "sf_shift2"; Lump = "DSGETPOW"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "bospit"; Flags = "sf_shift2"; Lump = "DSBOSPIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "boscub"; Flags = "sf_shift2"; Lump = "DSBOSCUB"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bossit"; Flags = "sf_shift2"; Lump = "DSBOSSIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bospn"; Flags = "sf_shift2"; Lump = "DSBOSPN"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "bosdth"; Flags = "sf_shift2"; Lump = "DSBOSDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "manatk"; Flags = "sf_shift2"; Lump = "DSMANATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "mandth"; Flags = "sf_shift2"; Lump = "DSMANDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "sssit"; Flags = "sf_shift2"; Lump = "DSSSSIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "ssdth"; Flags = "sf_shift2"; Lump = "DSSSDTH"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "keenpn"; Flags = "sf_shift2"; Lump = "DSKEENPN"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "keendt"; Flags = "sf_shift2"; Lump = "DSKEENDT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeact"; Flags = "sf_shift2"; Lump = "DSSKEACT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skesit"; Flags = "sf_shift2"; Lump = "DSSKESIT"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "skeatk"; Flags = "sf_shift2"; Lump = "DSSKEATK"; Link pitch = -1; Link volume = -1; Priority = 70; Max channels = -1; } Sound { ID = "radio"; Lump = "DSRADIO"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Sound { ID = "secret"; Flags = "sf_shift2"; Lump = "DSGETPOW"; Link pitch = -1; Link volume = -1; Priority = 60; Max channels = -1; } Texture Environment { ID = "Metal"; Texture { ID = "BIGDOOR1"; }; Texture { ID = "BIGDOOR2"; }; Texture { ID = "BIGDOOR4"; }; Texture { ID = "COMP2"; }; Texture { ID = "COMPSPAN"; }; Texture { ID = "COMPSTA1"; }; Texture { ID = "COMPSTA2"; }; Texture { ID = "COMPTALL"; }; Texture { ID = "COMPUTE1"; }; Texture { ID = "COMPUTE2"; }; Texture { ID = "DOOR1"; }; Texture { ID = "DOOR3"; }; Texture { ID = "DOORBLU"; }; Texture { ID = "DOORRED"; }; Texture { ID = "DOORSTOP"; }; Texture { ID = "DOORYEL"; }; Texture { ID = "EXITDOOR"; }; Texture { ID = "EXITSIGN"; }; Texture { ID = "LITE3"; }; Texture { ID = "LITE4"; }; Texture { ID = "LITE5"; }; Texture { ID = "LITEBLU1"; }; Texture { ID = "LITEBLU2"; }; Texture { ID = "LITEBLU3"; }; Texture { ID = "LITEBLU4"; }; Texture { ID = "METAL1"; }; Texture { ID = "PLANET1"; }; Texture { ID = "PLAT1"; }; Texture { ID = "REDWALL1"; }; Texture { ID = "SHAWN2"; }; Texture { ID = "STARG1"; }; Texture { ID = "STARG3"; }; Texture { ID = "STARGR1"; }; Texture { ID = "STARTAN1"; }; Texture { ID = "STARTAN2"; }; Texture { ID = "STARTAN3"; }; Texture { ID = "STEP4"; }; Texture { ID = "SUPPORT2"; }; Texture { ID = "SW1COMM"; }; Texture { ID = "SW1COMP"; }; Texture { ID = "SW1METAL"; }; Texture { ID = "SW1STARG"; }; Texture { ID = "SW1STRTN"; }; Texture { ID = "SW2COMM"; }; Texture { ID = "SW2COMP"; }; Texture { ID = "SW2METAL"; }; Texture { ID = "SW2STARG"; }; Texture { ID = "SW2STRTN"; }; Texture { ID = "BIGDOOR3"; }; Texture { ID = "COMPWERD"; }; Texture { ID = "DOORBLU2"; }; Texture { ID = "DOORRED2"; }; Texture { ID = "DOORYEL2"; }; Texture { ID = "GRAY2"; }; Texture { ID = "GRAYPOIS"; }; Texture { ID = "ICKDOOR1"; }; Texture { ID = "LITEMET"; }; Texture { ID = "LITERED"; }; Texture { ID = "LITESTON"; }; Texture { ID = "METAL"; }; Texture { ID = "SHAWN1"; }; Texture { ID = "SHAWN3"; }; Texture { ID = "STARBR2"; }; Texture { ID = "STARG2"; }; Texture { ID = "STARGR2"; }; Texture { ID = "SUPPORT3"; }; Texture { ID = "BRONZE1"; }; Texture { ID = "BRONZE2"; }; Texture { ID = "BRONZE3"; }; Texture { ID = "BRONZE4"; }; Texture { ID = "METAL2"; }; Texture { ID = "METAL3"; }; Texture { ID = "METAL4"; }; Texture { ID = "METAL5"; }; Texture { ID = "METAL6"; }; Texture { ID = "METAL7"; }; Texture { ID = "MODWALL3"; }; Texture { ID = "MODWALL4"; }; Texture { ID = "PIPES"; }; Texture { ID = "SILVER1"; }; Texture { ID = "SILVER2"; }; Texture { ID = "SILVER3"; }; Texture { ID = "SPACEW3"; }; Texture { ID = "SPACEW4"; }; Texture { ID = "SPCDOOR1"; }; Texture { ID = "SPCDOOR2"; }; Texture { ID = "SPCDOOR3"; }; Texture { ID = "SW1MET2"; }; Texture { ID = "SW2MET2"; }; Texture { ID = "SW1TEK"; }; Texture { ID = "SW2TEK"; }; Texture { ID = "SW1WDMET"; }; Texture { ID = "SW2WDMET"; }; Texture { ID = "TEKBRON1"; }; Texture { ID = "TEKBRON2"; }; Texture { ID = "TEKGREN1"; }; Texture { ID = "TEKGREN2"; }; Texture { ID = "TEKGREN3"; }; Texture { ID = "TEKGREN4"; }; Texture { ID = "TEKGREN5"; }; Texture { ID = "WOODMET1"; }; Texture { ID = "WOODMET2"; }; Texture { ID = "WOODMET3"; }; Texture { ID = "WOODMET4"; }; Texture { ID = "ZDOORB1"; }; Texture { ID = "ZDOORF1"; }; Texture { ID = "ZELDOOR"; }; Texture { ID = "ZZWOLF10"; }; Texture { ID = "ZZZFACE6"; }; Texture { ID = "ZZZFACE7"; }; Texture { ID = "ZZZFACE8"; }; Texture { ID = "ZZZFACE9"; }; } Texture Environment { ID = "Rock"; Texture { ID = "AASTINKY"; }; Texture { ID = "BRNPOIS"; }; Texture { ID = "BRNPOIS2"; }; Texture { ID = "BROWN1"; }; Texture { ID = "BROWN144"; }; Texture { ID = "BROWN96"; }; Texture { ID = "BROWNGRN"; }; Texture { ID = "BROWNHUG"; }; Texture { ID = "BROWNPIP"; }; Texture { ID = "COMPUTE3"; }; Texture { ID = "GRAY4"; }; Texture { ID = "GRAY5"; }; Texture { ID = "GRAY7"; }; Texture { ID = "GRAYTALL"; }; Texture { ID = "LITE2"; }; Texture { ID = "NUKE24"; }; Texture { ID = "NUKEDGE1"; }; Texture { ID = "STEP6"; }; Texture { ID = "STONE"; }; Texture { ID = "STONE2"; }; Texture { ID = "STONE3"; }; Texture { ID = "STONE4"; }; Texture { ID = "STONE5"; }; Texture { ID = "STONE6"; }; Texture { ID = "STONE7"; }; Texture { ID = "STONPOIS"; }; Texture { ID = "SW1BRCOM"; }; Texture { ID = "SW1BRN1"; }; Texture { ID = "SW1BRN2"; }; Texture { ID = "SW1BRGRN"; }; Texture { ID = "SW1BROWN"; }; Texture { ID = "SW1EXIT"; }; Texture { ID = "SW1GRAY"; }; Texture { ID = "SW1GRAY1"; }; Texture { ID = "SW1STON1"; }; Texture { ID = "SW1STON2"; }; Texture { ID = "SW1STONE"; }; Texture { ID = "SW2BRCOM"; }; Texture { ID = "SW2BRN1"; }; Texture { ID = "SW2BRN2"; }; Texture { ID = "SW2BRGRN"; }; Texture { ID = "SW2BROWN"; }; Texture { ID = "SW2EXIT"; }; Texture { ID = "SW2GRAY"; }; Texture { ID = "SW2GRAY1"; }; Texture { ID = "SW2STON1"; }; Texture { ID = "SW2STON2"; }; Texture { ID = "SW2STONE"; }; Texture { ID = "BIGDOOR5"; }; Texture { ID = "BROWNWEL"; }; Texture { ID = "CEMENT1"; }; Texture { ID = "CEMENT2"; }; Texture { ID = "CEMENT3"; }; Texture { ID = "CEMENT4"; }; Texture { ID = "CEMENT5"; }; Texture { ID = "CEMENT6"; }; Texture { ID = "CEMENT7"; }; Texture { ID = "CEMENT8"; }; Texture { ID = "CEMENT9"; }; Texture { ID = "CEMPOIS"; }; Texture { ID = "DOORHI"; }; Texture { ID = "EXITSTON"; }; Texture { ID = "FIREMAG1"; }; Texture { ID = "FIREMAG2"; }; Texture { ID = "FIREMAG3"; }; Texture { ID = "FIREWALL"; }; Texture { ID = "FIREWALA"; }; Texture { ID = "FIREWALB"; }; Texture { ID = "GRAY1"; }; Texture { ID = "GRAYBIG"; }; Texture { ID = "GRAYDANG"; }; Texture { ID = "GSTFONT1"; }; Texture { ID = "GSTFONT2"; }; Texture { ID = "GSTFONT3"; }; Texture { ID = "GSTGARG"; }; Texture { ID = "GSTLION"; }; Texture { ID = "GSTONE1"; }; Texture { ID = "GSTONE2"; }; Texture { ID = "GSTSATYR"; }; Texture { ID = "ICKWALL1"; }; Texture { ID = "ICKWALL2"; }; Texture { ID = "ICKWALL3"; }; Texture { ID = "ICKWALL4"; }; Texture { ID = "ICKWALL5"; }; Texture { ID = "ICKWALL6"; }; Texture { ID = "ICKWALL7"; }; Texture { ID = "LITE96"; }; Texture { ID = "MARBFAC2"; }; Texture { ID = "MARBFAC3"; }; Texture { ID = "MARBFAC4"; }; Texture { ID = "MARBFACE"; }; Texture { ID = "MARBLE1"; }; Texture { ID = "MARBLE2"; }; Texture { ID = "MARBLE3"; }; Texture { ID = "MARBLOD1"; }; Texture { ID = "REDWALL"; }; Texture { ID = "ROCKRED1"; }; Texture { ID = "ROCKRED2"; }; Texture { ID = "ROCKRED3"; }; Texture { ID = "SP_DUDE1"; }; Texture { ID = "SP_DUDE2"; }; Texture { ID = "SP_DUDE6"; }; Texture { ID = "SP_HOT1"; }; Texture { ID = "SP_ROCK1"; }; Texture { ID = "SP_ROCK2"; }; Texture { ID = "STONGARG"; }; Texture { ID = "SW1CMT"; }; Texture { ID = "SW1GSTON"; }; Texture { ID = "SW1HOT"; }; Texture { ID = "SW2CMT"; }; Texture { ID = "SW2GSTON"; }; Texture { ID = "SW2HOT"; }; Texture { ID = "WOOD5"; }; Texture { ID = "ASHWALL2"; }; Texture { ID = "ASHWALL3"; }; Texture { ID = "ASHWALL4"; }; Texture { ID = "ASHWALL6"; }; Texture { ID = "ASHWALL7"; }; Texture { ID = "BIGBRIK1"; }; Texture { ID = "BIGBRIK2"; }; Texture { ID = "BIGBRIK3"; }; Texture { ID = "BLAKWAL1"; }; Texture { ID = "BLAKWAL2"; }; Texture { ID = "BRICK1"; }; Texture { ID = "BRICK2"; }; Texture { ID = "BRICK3"; }; Texture { ID = "BRICK4"; }; Texture { ID = "BRICK5"; }; Texture { ID = "BRICK6"; }; Texture { ID = "BRICK7"; }; Texture { ID = "BRICK8"; }; Texture { ID = "BRICK9"; }; Texture { ID = "BRICK10"; }; Texture { ID = "BRICK11"; }; Texture { ID = "BRICK12"; }; Texture { ID = "BRICKLIT"; }; Texture { ID = "BSTONE1"; }; Texture { ID = "BSTONE2"; }; Texture { ID = "BSTONE3"; }; Texture { ID = "CRACKLE2"; }; Texture { ID = "CRACKLE4"; }; Texture { ID = "MARBGRAY"; }; Texture { ID = "MIDBRONZ"; }; Texture { ID = "MODWALL1"; }; Texture { ID = "MODWALL2"; }; Texture { ID = "PANEL6"; }; Texture { ID = "PANEL7"; }; Texture { ID = "PANEL8"; }; Texture { ID = "PANEL9"; }; Texture { ID = "PIPEWAL1"; }; Texture { ID = "PIPEWAL2"; }; Texture { ID = "ROCK1"; }; Texture { ID = "ROCK2"; }; Texture { ID = "ROCK3"; }; Texture { ID = "ROCK4"; }; Texture { ID = "ROCK5"; }; Texture { ID = "SPACEW2"; }; Texture { ID = "SPCDOOR4"; }; Texture { ID = "SW1BRIK"; }; Texture { ID = "SW2BRIK"; }; Texture { ID = "SW1MOD1"; }; Texture { ID = "SW2MOD1"; }; Texture { ID = "SW1ROCK"; }; Texture { ID = "SW2ROCK"; }; Texture { ID = "SW1SKULL"; }; Texture { ID = "SW2SKULL"; }; Texture { ID = "SW1STON6"; }; Texture { ID = "SW2STON6"; }; Texture { ID = "SW1ZIM"; }; Texture { ID = "SW2ZIM"; }; Texture { ID = "TANROCK2"; }; Texture { ID = "TANROCK3"; }; Texture { ID = "TANROCK4"; }; Texture { ID = "TANROCK5"; }; Texture { ID = "TANROCK7"; }; Texture { ID = "TANROCK8"; }; Texture { ID = "TEKLITE"; }; Texture { ID = "TEKLITE2"; }; Texture { ID = "ZIMMER1"; }; Texture { ID = "ZIMMER2"; }; Texture { ID = "ZIMMER3"; }; Texture { ID = "ZIMMER4"; }; Texture { ID = "ZIMMER5"; }; Texture { ID = "ZIMMER7"; }; Texture { ID = "ZIMMER8"; }; Texture { ID = "ZZWOLF1"; }; Texture { ID = "ZZWOLF11"; }; Texture { ID = "ZZWOLF2"; }; Texture { ID = "ZZWOLF9"; }; Texture { ID = "ZZZFACE1"; }; Texture { ID = "ZZZFACE2"; }; Texture { ID = "ZZZFACE3"; }; Texture { ID = "ZZZFACE4"; }; Texture { ID = "ZZZFACE5"; }; } Texture Environment { ID = "Wood"; Texture { ID = "BRNBIGC"; }; Texture { ID = "BRNBIGL"; }; Texture { ID = "BRNBIGR"; }; Texture { ID = "BRNSMAL1"; }; Texture { ID = "BRNSMAL2"; }; Texture { ID = "BRNSMALC"; }; Texture { ID = "BRNSMALL"; }; Texture { ID = "BRNSMALR"; }; Texture { ID = "COMPTILE"; }; Texture { ID = "DOORTRAK"; }; Texture { ID = "NUKESLAD"; }; Texture { ID = "PIPE2"; }; Texture { ID = "SLADPOIS"; }; Texture { ID = "SLADRIP1"; }; Texture { ID = "SLADRIP2"; }; Texture { ID = "SLADRIP3"; }; Texture { ID = "SLADWALL"; }; Texture { ID = "STEP1"; }; Texture { ID = "STEP2"; }; Texture { ID = "STEP3"; }; Texture { ID = "STEP5"; }; Texture { ID = "SW1PIPE"; }; Texture { ID = "SW1SLAD"; }; Texture { ID = "SW2PIPE"; }; Texture { ID = "SW2SLAD"; }; Texture { ID = "TEKWALL1"; }; Texture { ID = "TEKWALL2"; }; Texture { ID = "TEKWALL3"; }; Texture { ID = "TEKWALL4"; }; Texture { ID = "TEKWALL5"; }; Texture { ID = "TEKWALL6"; }; Texture { ID = "BIGDOOR6"; }; Texture { ID = "BIGDOOR7"; }; Texture { ID = "BLODGR1"; }; Texture { ID = "BLODGR2"; }; Texture { ID = "BLODGR3"; }; Texture { ID = "BLODGR4"; }; Texture { ID = "BLODRIP1"; }; Texture { ID = "BLODRIP2"; }; Texture { ID = "BLODRIP3"; }; Texture { ID = "BLODRIP4"; }; Texture { ID = "COMPOHSO"; }; Texture { ID = "CRATE1"; }; Texture { ID = "CRATE2"; }; Texture { ID = "CRATELIT"; }; Texture { ID = "CRATINY"; }; Texture { ID = "CRATWIDE"; }; Texture { ID = "FIREBLU1"; }; Texture { ID = "FIREBLU2"; }; Texture { ID = "FIRELAVA"; }; Texture { ID = "FIRELAV2"; }; Texture { ID = "FIRELAV3"; }; Texture { ID = "GRAYVINE"; }; Texture { ID = "GSTVINE1"; }; Texture { ID = "GSTVINE2"; }; Texture { ID = "PIPE1"; }; Texture { ID = "PIPE4"; }; Texture { ID = "PIPE6"; }; Texture { ID = "SKINCUT"; }; Texture { ID = "SKINLOW"; }; Texture { ID = "SKINMET1"; }; Texture { ID = "SKINMET2"; }; Texture { ID = "SKINSYMB"; }; Texture { ID = "SKINTEK1"; }; Texture { ID = "SKINTEK2"; }; Texture { ID = "SKSPINE1"; }; Texture { ID = "SKSPINE2"; }; Texture { ID = "SKULWAL3"; }; Texture { ID = "SKULWALL"; }; Texture { ID = "SLADSKUL"; }; Texture { ID = "SP_DUDE3"; }; Texture { ID = "SP_DUDE4"; }; Texture { ID = "SP_DUDE5"; }; Texture { ID = "STEPLAD1"; }; Texture { ID = "STEPTOP"; }; Texture { ID = "SW1GARG"; }; Texture { ID = "SW1LION"; }; Texture { ID = "SW1SATYR"; }; Texture { ID = "SW1VINE"; }; Texture { ID = "SW1WOOD"; }; Texture { ID = "SW2GARG"; }; Texture { ID = "SW2LION"; }; Texture { ID = "SW2SATYR"; }; Texture { ID = "SW2VINE"; }; Texture { ID = "SW2WOOD"; }; Texture { ID = "WOOD1"; }; Texture { ID = "WOOD3"; }; Texture { ID = "WOOD4"; }; Texture { ID = "WOOD10"; }; Texture { ID = "WOOD12"; }; Texture { ID = "WOOD6"; }; Texture { ID = "WOOD7"; }; Texture { ID = "WOOD8"; }; Texture { ID = "WOOD9"; }; Texture { ID = "WOODGARG"; }; Texture { ID = "WOODSKUL"; }; Texture { ID = "AASHITTY"; }; Texture { ID = "BRWINDOW"; }; Texture { ID = "MIDSPACE"; }; Texture { ID = "PANBORD1"; }; Texture { ID = "PANBORD2"; }; Texture { ID = "PANCASE1"; }; Texture { ID = "PANCASE2"; }; Texture { ID = "PANEL1"; }; Texture { ID = "PANEL2"; }; Texture { ID = "PANEL3"; }; Texture { ID = "PANEL4"; }; Texture { ID = "PANEL5"; }; Texture { ID = "SP_DUDE7"; }; Texture { ID = "SP_DUDE8"; }; Texture { ID = "STUCCO"; }; Texture { ID = "STUCCO1"; }; Texture { ID = "STUCCO2"; }; Texture { ID = "STUCCO3"; }; Texture { ID = "SW1PANEL"; }; Texture { ID = "SW2PANEL"; }; Texture { ID = "WOODVERT"; }; Texture { ID = "ZZWOLF13"; }; Texture { ID = "ZZWOLF5"; }; } Texture Environment { ID = "Cloth"; Texture { ID = "SW1DIRT"; }; Texture { ID = "SW2DIRT"; }; Texture { ID = "ASHWALL"; }; Texture { ID = "BROVINE"; }; Texture { ID = "BROVINE2"; }; Texture { ID = "COMPBLUE"; }; Texture { ID = "MIDBRN1"; }; Texture { ID = "MIDGRATE"; }; Texture { ID = "MIDVINE1"; }; Texture { ID = "MIDVINE2"; }; Texture { ID = "NUKEPOIS"; }; Texture { ID = "SKIN2"; }; Texture { ID = "SKINBORD"; }; Texture { ID = "SKINEDGE"; }; Texture { ID = "SKINFACE"; }; Texture { ID = "SKINSCAB"; }; Texture { ID = "SKSNAKE1"; }; Texture { ID = "SKSNAKE2"; }; Texture { ID = "SP_FACE1"; }; Texture { ID = "SP_FACE2"; }; Texture { ID = "SW1BLUE"; }; Texture { ID = "SW1SKIN"; }; Texture { ID = "SW2BLUE"; }; Texture { ID = "SW2SKIN"; }; Texture { ID = "BFALL1"; }; Texture { ID = "BFALL2"; }; Texture { ID = "BFALL3"; }; Texture { ID = "BFALL4"; }; Texture { ID = "DBRAIN1"; }; Texture { ID = "DBRAIN2"; }; Texture { ID = "DBRAIN3"; }; Texture { ID = "DBRAIN4"; }; Texture { ID = "MIDBARS1"; }; Texture { ID = "MIDBARS3"; }; Texture { ID = "PANBLACK"; }; Texture { ID = "PANBLUE"; }; Texture { ID = "PANBOOK"; }; Texture { ID = "PANRED"; }; Texture { ID = "SFALL1"; }; Texture { ID = "SFALL2"; }; Texture { ID = "SFALL3"; }; Texture { ID = "SFALL4"; }; Texture { ID = "SK_LEFT"; }; Texture { ID = "SK_RIGHT"; }; Texture { ID = "SLOPPY1"; }; Texture { ID = "SLOPPY2"; }; Texture { ID = "ZZWOLF12"; }; Texture { ID = "ZZWOLF3"; }; Texture { ID = "ZZWOLF4"; }; Texture { ID = "ZZWOLF6"; }; Texture { ID = "ZZWOLF7"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom1maps.ded0000644000175000017500000001047311357170242023162 0ustar keeskees# # jDoom: DOOM1 Maps # # The default definition, used for any maps without a map info definition. Map Info { ID = "*"; Author = "Unknown"; Music = "e1m1"; Gravity = 1; Sky = "sky1"; } Map Info { ID = "E1M1"; Name = "HUSTR_E1M1"; Author = "id Software"; Music = "e1m1"; Par time = 30; Gravity = 1; Sky = "sky1"; } Copy Map Info { ID = "E1M2"; Name = "HUSTR_E1M2"; Music = "e1m2"; Par time = 75; } Copy Map Info { ID = "E1M3"; Name = "HUSTR_E1M3"; Music = "e1m3"; Par time = 120; } Copy Map Info { ID = "E1M4"; Name = "HUSTR_E1M4"; Music = "e1m4"; Par time = 90; } Copy Map Info { ID = "E1M5"; Name = "HUSTR_E1M5"; Music = "e1m5"; Par time = 165; } Copy Map Info { ID = "E1M6"; Name = "HUSTR_E1M6"; Music = "e1m6"; Par time = 180; } Copy Map Info { ID = "E1M7"; Name = "HUSTR_E1M7"; Music = "e1m7"; Par time = 180; } Copy Map Info { ID = "E1M9"; Name = "HUSTR_E1M9"; Music = "e1m9"; Par time = 165; } Copy Map Info { ID = "E1M8"; Name = "HUSTR_E1M8"; Music = "e1m8"; Flags = nointermission; Par time = 30; } # The rest of this file is skipped if DOOM1 Shareware SkipIf doom1-share Map Info { ID = "E2M1"; Name = "HUSTR_E2M1"; Author = "id Software"; Music = "e2m1"; Par time = 90; Gravity = 1; Sky = "sky2"; } Copy Map Info { ID = "E2M1"; Name = "HUSTR_E2M1"; Music = "e2m1"; Par time = 90; Sky = "sky2"; } Copy Map Info { ID = "E2M2"; Name = "HUSTR_E2M2"; Music = "e2m2"; Par time = 90; } Copy Map Info { ID = "E2M3"; Name = "HUSTR_E2M3"; Music = "e2m3"; Par time = 90; } Copy Map Info { ID = "E2M4"; Name = "HUSTR_E2M4"; Music = "e2m4"; Par time = 120; } Copy Map Info { ID = "E2M5"; Name = "HUSTR_E2M5"; Music = "e2m5"; Par time = 90; } Copy Map Info { ID = "E2M6"; Name = "HUSTR_E2M6"; Music = "e2m6"; Par time = 360; } Copy Map Info { ID = "E2M7"; Name = "HUSTR_E2M7"; Music = "e2m7"; Par time = 240; } Copy Map Info { ID = "E2M9"; Name = "HUSTR_E2M9"; Music = "e2m9"; Par time = 170; } Copy Map Info { ID = "E2M8"; Name = "HUSTR_E2M8"; Music = "e2m8"; Flags = nointermission; Par time = 30; } Map Info { ID = "E3M1"; Name = "HUSTR_E3M1"; Author = "id Software"; Music = "e3m1"; Par time = 90; Gravity = 1; Sky = "sky3"; } Copy Map Info { ID = "E3M2"; Name = "HUSTR_E3M2"; Music = "e3m2"; Par time = 45; } Copy Map Info { ID = "E3M3"; Name = "HUSTR_E3M3"; Music = "e3m3"; Par time = 90; } Copy Map Info { ID = "E3M4"; Name = "HUSTR_E3M4"; Music = "e3m4"; Par time = 150; } Copy Map Info { ID = "E3M5"; Name = "HUSTR_E3M5"; Music = "e3m5"; Par time = 90; } Copy Map Info { ID = "E3M6"; Name = "HUSTR_E3M6"; Music = "e3m6"; Par time = 90; } Copy Map Info { ID = "E3M7"; Name = "HUSTR_E3M7"; Music = "e3m7"; Par time = 165; } Copy Map Info { ID = "E3M9"; Name = "HUSTR_E3M9"; Music = "e3m9"; Par time = 135; } Copy Map Info { ID = "E3M8"; Name = "HUSTR_E3M8"; Music = "e3m8"; Flags = nointermission; Par time = 30; } # The rest of this file is skipped if not DOOM1 Ultimate. SkipIf Not doom1-ultimate Map Info { ID = "E4M1"; Name = "HUSTR_E4M1"; Author = "id Software"; Music = "e3m4"; Par time = 90; Gravity = 1; Sky = "sky4"; } Copy Map Info { ID = "E4M2"; Name = "HUSTR_E4M2"; Music = "e3m2"; Par time = 120; } Copy Map Info { ID = "E4M3"; Name = "HUSTR_E4M3"; Music = "e3m3"; Par time = 120; } Copy Map Info { ID = "E4M4"; Name = "HUSTR_E4M4"; Music = "e1m5"; Par time = 90; } Copy Map Info { ID = "E4M5"; Name = "HUSTR_E4M5"; Music = "e2m7"; Par time = 150; } Copy Map Info { ID = "E4M6"; Name = "HUSTR_E4M6"; Music = "e2m4"; Par time = 120; } Copy Map Info { ID = "E4M7"; Name = "HUSTR_E4M7"; Music = "e2m6"; Par time = 120; } Copy Map Info { ID = "E4M9"; Name = "HUSTR_E4M9"; Music = "e1m9"; Par time = 90; } Copy Map Info { ID = "E4M8"; Name = "HUSTR_E4M8"; Music = "e2m5"; Flags = nointermission; # Doesn't have a par time } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom1lights.ded0000644000175000017500000002160411357170242023512 0ustar keeskees# jDoom: Light Decorations for Doom I Header { Version = 5; } # This file is skipped if not Doom I/II. SkipIf doom2-plut; SkipIf doom2-tnt; #####====--- TEXTURE DECORATIONS FOR DOOM I ---====##### # # The default flags allow using these only with the original textures. # Use "dcf_pwad" and "dcf_ext" to allow using with PWAD and external # resources. # # There can only be one decoration per texture/flat. Newer decorations # override older ones. # # One decoration can specify up to 16 lights. # # # Flats: # (just the brightest and most obvious light sources) # Decoration { Flat = "CEIL1_2"; Light { Color { 1 1 1 }; Offset { 32 32 }; Halo radius = .7; Radius = .95; Flare texture = 1; }; } Copy Decoration { Flat = "CEIL1_3"; Light { Halo radius = .6; # React to sector lightlevel. Levels { 80 190 }; }; } Copy Decoration { Flat = "TLITE6_4"; Light { Radius = .5; Halo radius = .7; }; } Decoration { Flat = "TLITE6_1"; Light { Color { .93 .93 .93 }; Offset { 32 32 }; Halo radius = .7; Flare texture = 1; #3; Radius = .4; Levels { 160 220 }; }; } Copy Decoration { Flat = "FLOOR1_7"; Light { Color { 1 .95 .95 }; #Halo radius = 1; Flare texture = 1; Levels { 140 230 }; }; } # # Wall textures: # (many obvious light sources not included, e.g. LITE*) # Decoration { Texture = "COMP2"; Light { Color { .2 .2 1 }; Offset { 33 83 }; Radius = .3; Halo radius = .07; }; Light { Color { .1 .75 .1 }; Offset { 216 101 }; Radius = .2; Halo radius = .04; }; } Decoration { Texture = "COMPSTA1"; Light { Color { .1 .4 .65 }; Offset { 30 23 }; Radius = .35; Halo radius = .07; Levels { 230 220 }; }; Light { Color { .65 .55 .1 }; Offset { 71 23 }; Radius = .25; Halo radius = .05; Levels { 230 220 }; }; Light { Color { .1 .45 .1 }; Offset { 101 35 }; Radius = .11; Halo radius = .04; Levels { 230 220 }; }; } Decoration { Texture = "COMPSTA2"; Light { Color { .1 .5 .1 }; Offset { 26 23 }; Radius = .3; Halo radius = .07; Levels { 230 220 }; }; Light { Color { .1 .5 .1 }; Offset { 105 13 }; Radius = .11; Halo radius = .04; Levels { 230 220 }; }; Light { Color { .15 .4 .15 }; Offset { 107 35 }; Radius = .15; Halo radius = .04; Levels { 230 220 }; }; } Decoration { Texture = "COMPUTE1"; Light { Color { .2 .2 1 }; Offset { 28 16 }; Radius = .25; Halo radius = .06; Levels { 220 200 }; }; Light { Color { .1 .5 .1 }; Offset { 30 89 }; Radius = .1; Halo radius = .03; Levels { 220 200 }; }; Light { Color { 1 .1 .1 }; Offset { 93 14 }; Radius = .05; Halo radius = .02; Levels { 230 210 }; }; } Decoration { Texture = "TEKWALL2"; Light { Color { 1 .1 .1 }; Offset { 67 62 }; Radius = .05; Halo radius = .02; Levels { 240 210 }; }; Light { Color { .1 .6 .1 }; Offset { 47 84 }; Radius = .07; Halo radius = .03; Levels { 230 200 }; }; Light { Color { .08 .4 .08 }; Offset { 113 83 }; Radius = .065; Halo radius = .03; Levels { 230 200 }; }; Light { Color { .1 .6 .1 }; Offset { 69 30 }; Radius = .05; Halo radius = .02; Levels { 240 210 }; }; } Decoration { Texture = "TEKWALL5"; Light { Color { 1 .1 .1 }; Offset { 30 75 }; Radius = .05; Halo radius = .02; Levels { 240 210 }; }; Light { Color { .1 .6 .1 }; Offset { 109 68 }; Radius = .04; Halo radius = .02; Levels { 240 210 }; }; Light { Color { .08 .5 .08 }; Offset { 41 19 }; Radius = .045; Halo radius = .03; Levels { 230 200 }; }; } Decoration { Texture = "PLANET1"; # Six monitors. Light { Color { .1 .4 .7 }; Offset { 30 30 }; Radius = .5; Levels { 230 220 }; }; Light { Color { .75 .35 .1 }; Offset { 92 30 }; Radius = .45; Levels { 230 220 }; }; Light { Color { .3 .5 .5 }; Offset { 158 34 }; Radius = .4; Levels { 230 220 }; }; Light { Color { .6 .6 .5 }; Offset { 30 90 }; Radius = .4; Levels { 230 220 }; }; Light { Color { .5 .2 .25 }; Offset { 92 90 }; Radius = .45; Levels { 230 220 }; }; Light { Color { .5 .55 .5 }; Offset { 156 88 }; Radius = .35; Levels { 230 220 }; }; } #>Decoration { Texture = "STEP1"; Light { Color { 1 1 .9 }; Offset { 16 5 }; Radius = .15; Halo radius = .03; }; }<# Decoration { Texture = "EXITSTON"; Light { Color { 1 .1 .1 }; Offset { 34 31 }; Radius = .25; Halo radius = .07; Levels { 240 220 }; }; } Copy Decoration { Texture = "EXITSIGN"; Light { Offset { 16 8 }; Radius = .25; }; } Decoration { Texture = "MARBFAC2"; Light { Color { 1 1 1 }; Offset { 51 79 }; Halo radius = .03; Radius = .08; }; Light { Color { 1 1 1 }; Offset { 78 79 }; Halo radius = .03; Radius = .08; }; } Decoration { Texture = "LITEBLU2"; Light { Color { .15 .15 1 }; Offset { 8 20 }; Halo radius = .1; Radius = .1; }; Light { Color { .15 .15 1 }; Offset { 8 52 }; Halo radius = .1; Radius = .1; }; } Decoration { Texture = "WOODGARG"; Light { Color { 1 .2 .2 }; Offset { 25 83 }; Halo radius = .03; Radius = .05; }; Light { Color { 1 .2 .2 }; Offset { 40 83 }; Halo radius = .03; Radius = .05; }; } Copy Decoration { Texture = "SLADSKUL"; Light { Offset { 28 83 }; }; Light { Offset { 38 83 }; }; } Copy Decoration { Texture = "WOODSKUL"; Light { Offset { 31 88 }; }; Light { Offset { 41 88 }; }; } Copy Decoration { Texture = "WOOD4"; Light { Offset { 28 36 }; }; Light { Offset { 38 36 }; }; } # # Switches: # Copy Decoration { Texture = "SW2BLUE"; Light { Offset { 28 90 }; }; Light { Offset { 36 90 }; }; } Copy Decoration { Texture = "SW2WOOD"; } Copy Decoration { Texture = "SW2HOT"; Light { Offset { 26 89 }; }; Light { Offset { 34 89 }; }; } Copy Decoration { Texture = "SW2GSTON"; Light { Offset { 27 91 }; }; Light { Offset { 35 91 }; }; } Decoration { Texture = "SW1COMM"; Light { Color { 1 .2 .2 }; Offset { 26 25 }; Halo radius = .04; Radius = .1; }; } Copy Decoration { Texture = "SW1STRTN"; Light { Offset { 26 80 }; }; } Copy Decoration { Texture = "SW1BRCOM"; Light { Offset { 59 80 }; }; } Copy Decoration { Texture = "SW1DIRT"; Light { Offset { 27 28 }; }; } Copy Decoration { Texture = "SW1STON1"; Light { Offset { 27 86 }; }; } Copy Decoration { Texture = "SW1STONE"; Light { Offset { 27 80 }; }; } Copy Decoration { Texture = "SW2COMP"; Light { Offset { 32 79 }; }; } Copy Decoration { Texture = "SW2EXIT"; Light { Offset { 16 23 }; }; } Copy Decoration { Texture = "SW2GRAY"; Light { Offset { 32 77 }; }; } Copy Decoration { Texture = "SW2SLAD"; Light { Offset { 33 84 }; }; } Copy Decoration { Texture = "SW2STON2"; Light { Offset { 33 84 }; }; } Decoration { Texture = "SW2COMM"; Light { Color { .2 1 .2 }; Offset { 26 40 }; Halo radius = .04; Radius = .1; }; } Copy Decoration { Texture = "SW2STRTN"; Light { Offset { 26 95 }; }; } Copy Decoration { Texture = "SW2BRCOM"; Light { Offset { 59 94 }; }; } Copy Decoration { Texture = "SW2STONE"; Light { Offset { 27 94 }; }; } Copy Decoration { Texture = "SW2STON1"; Light { Offset { 27 101 }; }; } Copy Decoration { Texture = "SW2DIRT"; Light { Offset { 27 43 }; }; } Decoration { Texture = "SW2BRN2"; Light { Color { .1 .9 .1 }; Offset { 32.5 91 }; Radius = .06; Halo radius = .04; }; } Copy Decoration { Texture = "SW2BRNGN"; Light { Offset { 32.5 92 }; }; } Copy Decoration { Texture = "SW2VINE"; Light { Offset { 32.5 96 }; }; } Copy Decoration { Texture = "SW2METAL"; Light { Offset { 32.5 80 }; }; } Copy Decoration { Texture = "SW2GRAY1"; Light { Offset { 31.5 91 }; }; } Decoration { Texture = "SW2LION"; # Eyes. Light { Color { .8 .78 .6 }; Offset { 27 84 }; Radius = .045; Halo radius = .02; }; Light { Color { .8 .78 .6 }; Offset { 37 84 }; Radius = .045; Halo radius = .02; }; # Mouth. Light { Color { .75 .73 .5 }; Offset { 32 94 }; Radius = .08; Halo radius = .02; }; } Copy Decoration { Texture = "SW2GARG"; Light { Offset { 25 85 }; }; Light { Offset { 39 85 }; }; Light { Offset { 32 100 }; }; } Decoration { Texture = "SW2SATYR"; # Eyes. Light { Color { .68 .6 .4 }; Offset { 27 85 }; Radius = .04; Halo radius = .02; }; Light { Color { .68 .6 .4 }; Offset { 38 85 }; Radius = .04; Halo radius = .02; }; # Mouth. Light { Color { .75 .73 .5 }; Offset { 32 95 }; Radius = .08; Halo radius = .02; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2finales.ded0000644000175000017500000001743411357170242023650 0ustar keeskees# jDoom: Intermissions and Finales (DOOM2) # (see Doc\InFine.txt) Header { Version = 5; } # I'm using "textdef" to allow compatibility with DeHackEd. # A better way would just be to use "text" and define the text # in the script, no need to go about modifying the Text defs. #########=========--------- DOOM II ---------=========######### Finale { Before = "MAP07"; Script { music "read_m" flat SLIME16 wait 0.5 textdef msg 10 10 "C1TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP12"; Script { music "read_m" flat RROCK14 wait 0.5 textdef msg 10 10 "C2TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP21"; Script { music "read_m" flat RROCK07 wait 0.5 textdef msg 10 10 "C3TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } # This is the actual finale of DOOM II. Finale { After = "MAP30"; Script { music "read_m" flat RROCK17 wait 0.5 textdef msg 10 10 "C4TEXT" waittext msg; wait 7 skiphere #####====--- The Cast ---====##### # Castloop continues forever. # Quite a number of monsters here...! noskip # No more skipping (pause waits for a key, though). deltext msg music "evil" noflat; patch back 0 0 BOSSBACK marker castloop # Create a text for the name. textdef name 160 180 CC_ZOMBIE center name; rate name 0 patch mo 160 170 POSSA1 # "mo" is used for all the monsters. # --- Zombieman --- clranim mo states mo POSS_RUN1 12 states mo POSS_ATK1 2; picsound mo "pistol" states mo POSS_ATK3 1 repeat mo seesound POSSESSED; pause; diesound POSSESSED clranim mo states mo POSS_DIE1 5 waitanim mo; wait 0.43 # --- Shotgun Guy --- clranim mo states mo SPOS_RUN1 12 states mo SPOS_ATK1 2; picsound mo "shotgn" states mo SPOS_ATK3 1 repeat mo settextdef name CC_SHOTGUN seesound SHOTGUY; pause; diesound SHOTGUY clranim mo states mo SPOS_DIE1 5 waitanim mo; wait 0.43 # --- Heavy Weapon Dude --- clranim mo states mo CPOS_RUN1 12 states mo CPOS_ATK1 2; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" states mo CPOS_ATK4 1; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" states mo CPOS_ATK4 1; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" repeat mo settextdef name CC_HEAVY seesound CHAINGUY; pause; diesound CHAINGUY clranim mo states mo CPOS_DIE1 7 waitanim mo; wait 0.43 # --- Imp --- clranim mo states mo TROO_RUN1 12 states mo TROO_ATK1 3; picsound mo "claw" repeat mo settextdef name CC_IMP seesound TROOP; pause; diesound TROOP clranim mo states mo TROO_DIE1 5 waitanim mo; wait 0.43 # --- Demon --- clranim mo states mo SARG_RUN1 12 states mo SARG_ATK1 2; picsound mo "sgtatk" states mo SARG_ATK3 1 repeat mo settextdef name CC_DEMON seesound SERGEANT; pause; diesound SERGEANT clranim mo states mo SARG_DIE1 6 waitanim mo; wait 0.43 # --- Lost Soul --- clranim mo states mo SKULL_RUN1 12 states mo SKULL_ATK1 2; picsound mo "sklatk" states mo SKULL_ATK3 8 repeat mo settextdef name CC_LOST seesound SKULL; pause; diesound SKULL clranim mo states mo SKULL_DIE1 6 waitanim mo; wait 0.43 # --- Cacodemon --- clranim mo states mo HEAD_RUN1 12 states mo HEAD_ATK1 2; picsound mo "firsht" states mo HEAD_ATK3 1 repeat mo settextdef name CC_CACO seesound HEAD; pause; diesound HEAD clranim mo states mo HEAD_DIE1 6 waitanim mo; wait 0.43 # --- Hell Knight --- clranim mo states mo BOS2_RUN1 12 states mo BOS2_ATK1 2; picsound mo "firsht" states mo BOS2_ATK3 1 repeat mo settextdef name CC_HELL seesound KNIGHT; pause; diesound KNIGHT clranim mo states mo BOS2_DIE1 7 waitanim mo; wait 0.43 # --- Baron of Hell --- clranim mo states mo BOSS_RUN1 12 states mo BOSS_ATK1 2; picsound mo "firsht" states mo BOSS_ATK3 1 repeat mo settextdef name CC_BARON seesound BRUISER; pause; diesound BRUISER clranim mo states mo BOSS_DIE1 7 waitanim mo; wait 0.43 # --- Arachnotron --- clranim mo states mo BSPI_SIGHT 12 states mo BSPI_ATK1 2; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 2 repeat mo settextdef name CC_ARACH seesound BABY; pause; diesound BABY clranim mo states mo BSPI_DIE1 7 waitanim mo; wait 0.43 # --- Pain Elemental --- clranim mo states mo PAIN_RUN1 12 states mo PAIN_ATK1 3; picsound mo "sklatk" states mo PAIN_ATK4 1 repeat mo settextdef name CC_PAIN seesound PAIN; pause; diesound PAIN clranim mo states mo PAIN_DIE1 6 waitanim mo; wait 0.43 # --- Revenant --- clranim mo states mo SKEL_RUN1 12 states mo SKEL_MISS1 2; picsound mo "skeatk" states mo SKEL_MISS3 2 states mo SKEL_RUN1 12 states mo SKEL_FIST1 2; picsound mo "skeswg" states mo SKEL_FIST3 2; picsound mo "skepch" repeat mo settextdef name CC_REVEN seesound UNDEAD; pause; diesound UNDEAD clranim mo states mo SKEL_DIE1 6 waitanim mo; wait 0.43 # --- Mancubus --- clranim mo states mo FATT_RUN1 12 states mo FATT_ATK1 2; picsound mo "firsht" states mo FATT_ATK3 3; picsound mo "firsht" states mo FATT_ATK6 3; picsound mo "firsht" states mo FATT_ATK9 2 repeat mo settextdef name CC_MANCU seesound FATSO; pause; diesound FATSO clranim mo states mo FATT_DIE1 10 waitanim mo; wait 0.43 # --- Arch-Vile --- clranim mo states mo VILE_RUN1 12 states mo VILE_ATK1 2; picsound mo "vilatk" states mo VILE_ATK3 9 repeat mo settextdef name CC_ARCH seesound VILE; pause; diesound VILE clranim mo states mo VILE_DIE1 10 waitanim mo; wait 0.43 # --- The Spider Mastermind --- clranim mo states mo SPID_RUN1 12 states mo SPID_ATK1 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" repeat mo settextdef name CC_SPIDER seesound SPIDER; pause; diesound SPIDER clranim mo states mo SPID_DIE1 11 waitanim mo; wait 0.43 # --- Cyberdemon --- clranim mo states mo CYBER_RUN1 12 states mo CYBER_ATK1 2; picsound mo "rlaunc" states mo CYBER_ATK3 2; picsound mo "rlaunc" states mo CYBER_ATK5 2; picsound mo "rlaunc" repeat mo settextdef name CC_CYBER seesound CYBORG; pause; diesound CYBORG clranim mo states mo CYBER_DIE1 10 waitanim mo; wait 0.43 # --- Our Hero (finally!) --- clranim mo states mo PLAY_RUN1 12 states mo PLAY_ATK1 1 repeat mo settextdef name CC_HERO seesound PLAYER; pause; diesound PLAYER clranim mo states mo PLAY_DIE1 7 waitanim mo; wait 0.43 # Restart the loop. goto castloop }; } # Secret level 1. Finale { Before = "MAP31"; Script { music "read_m"; flat RROCK13; wait 0.5; textdef msg 10 10 "C5TEXT"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. }; } # Secret level 2. Finale { Before = "MAP32"; Script { music "read_m"; flat RROCK19; wait 0.5; textdef msg 10 10 "C6TEXT"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/particles.ded0000644000175000017500000002724011357170242023250 0ustar keeskees# jDoom: Particle Effects Header { Version = 6; } SkipIf -nodefaultfx; ######=====---- PLAYER WEAPONS ----=====###### # Rocket smoke trail. Generator { State = "ROCKET"; Flags = spawn; Center { -16 0 5 }; Speed = .8; Speed rnd = 1; Spawn age = -1; Max age = 1200; Particles = 150; Spawn rate = 1.4; Spawn Rnd = 0.4; Vector { 0 0 0 }; Vector rnd = 1; Stage { Type = point; Flags = bright; Radius = 1; Color { 1 1 1 1 }; }; Stage { Type = point; Flags = bright; Tics = 4; Rnd = .2; Radius = 5; Color { 1 .95 .7 1 }; }; Stage { Type = point; Flags = bright; Tics = 2; Rnd = .2; Radius = 5; Color { 1 .7 .3 1 }; }; Stage { Type = point; Tics = 15; Radius = 6; Color { .6 .6 .6 .5 }; Resistance = 0.01; }; Stage { Type = point; Tics = 130; Radius = 22; Bounce = 0; Resistance = 0.1; Gravity = 0; Color { 0.5 0.5 0.55 0.3 }; }; Stage { Type = point; Radius = 30; Color { 0.2 0.2 0.22 0 }; }; } # Bullet ricochet. Happens pretty rarely. Generator { State = "PUFF1"; Flags = "gnf_blend"; Speed = 20; Speed rnd = 0.1; Spawn age = 2; Max age = 50; Particles = 20; Spawn rate = .65; Spawn rnd = 1; Vector rnd = 1; Stage { Type = "pt_line"; Flags = "ptf_bright"; Tics = 20; Rnd = 0.5; Radius = 1; Color { 1 1 .9 1 }; Bounce = 0.5; Resistance = 0.01; Gravity = 0.04; }; Stage { Type = "pt_line"; Flags = "ptf_bright"; Tics = 10; Rnd = 0.5; Radius = 1; Color { 1 .9 .3 .5 }; Bounce = 0.5; Resistance = 0.01; Gravity = 0.04; }; Stage { Type = "pt_line"; Flags = "ptf_bright"; Radius = 1; Resistance = 0.01; Gravity = 0.02; }; } # Plasma sparks (blue). Generator { State = "PLASEXP"; Flags = "gnf_blend"; Speed = 3; Speed rnd = 0.8; Spawn age = 3; Spawn radius = 20; Max age = 50; Particles = 30; Spawn rate = 10; Spawn rnd = 1; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 5; Rnd = 0.5; Radius = 15; Color { 1 1 1 .7 }; Resistance = 0.3; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 20; Rnd = 0.5; Radius = 13; Color { .45 .5 1 .4 }; Resistance = 0.3; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 10; Rnd = 0.5; Radius = 12; Color { .05 .15 1 .4 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Color { .2 .2 1 0 }; Radius = 10; }; } # BFG explosion effect. Generator { State = "BFGLAND"; Flags = "gnf_blend"; Speed = 7; Speed rnd = 0.2; Spawn radius = 10; Spawn age = 7; Max age = 70; Particles = 200; Spawn rate = 25; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 30; Rnd = 0.2; Radius = 4; Bounce = 0.8; Resistance = .03; Gravity = 0.01; Color { 1 1 1 1 }; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Radius = 3; Tics = 30; Resistance = .05; Gravity = 0.02; Color { .5 1 .5 .8 }; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 3; Color { 0 1 0 .5 }; }; } ######=====---- MONSTERS ----=====###### # Baby Spider plasma sparks (yellow-green). Generator { State = "ARACH_PLEX"; Flags = "gnf_blend"; Speed = 3; Speed rnd = 0.8; Spawn age = 3; Spawn radius = 20; Max age = 50; Particles = 30; Spawn rate = 10; Spawn rnd = 1; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 5; Rnd = 0.5; Radius = 15; Color { 1 1 1 .7 }; Resistance = 0.3; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 20; Rnd = 0.5; Radius = 13; Color { 1 .9 .5 .4 }; Resistance = 0.3; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 10; Rnd = 0.5; Radius = 12; Color { .5 1 .2 .4 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Color { 0 .6 0 0 }; Radius = 10; }; } ######=====---- EXPLOSIONS ----=====###### # Rocket explosions. Generator { State = "EXPLODE1"; Center { 0 0 5 }; Flags = "gnf_blend"; Speed = 8; Speed rnd = 0.5; Spawn age = 2; Spawn radius = 15; Max age = 200; Particles = 100; Spawn rate = 14; Spawn Rnd = 0.1; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 20; Rnd = .5; Radius = 18; Color { 1 1 1 1 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 13; Rnd = .5; Radius = 17; Color { 1 .9 .5 .7 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 7; Rnd = 0.2; Radius = 10; Color { 1 .5 .2 .5 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 20; Rnd = .8; Radius = 12; Color { .4 .4 .42 .3 }; Resistance = 0.5; }; Stage { Type = "pt_point"; Radius = 5; Color { .2 .2 .2 0 }; }; } # Mancubus rocket explosion. Copy Generator { State = "FATSHOTX1"; Spawn rate = 15; } # Barrel explosion. Copy Generator { State = "BEXP"; Flags = "gnf_blend gnf_srcvel"; Center { 0 0 20 }; } # Rocket sparks. Generator { State = "EXPLODE0"; Speed = 10; Speed rnd = 0.9; Spawn age = 2; Spawn radius = 3; Max age = 200; Particles = 100; Spawn rate = 30; Spawn Rnd = 0.3; Vector { 0 0 0 }; Vector rnd = 1; Stage { Type = point; Flags = bright; Tics = 32; Rnd = 0.5; Radius = 2; Bounce = 0.45; Resistance = 0.01; Gravity = 0.1; Color { 1 1 1 1 }; }; Stage { Type = point; Flags = bright; Tics = 15; Rnd = 0.5; Radius = 1.5; Bounce = 0.3; Resistance = 0.03; Gravity = 0.1; Color { 1 1 .5 1 }; }; Stage { Type = point; Tics = 4; Radius = 1.25; Bounce = 0.3; Resistance = 0.1; Gravity = 0.1; Color { 1 .1 .1 1 }; }; Stage { Type = point; Tics = 4; Radius = 1; Bounce = 0.3; Resistance = 0.1; Gravity = 0.1; Radius = 1; Color { .5 .1 0 .7 }; }; Stage { Type = point; Tics = 30; Radius = 10; Resistance = 0.2; Gravity = 0.01; Color { .3 .3 .3 .3 }; }; Stage { Type = point; Tics = 30; Radius = 20; Resistance = 0.2; Gravity = 0.01; Color { .15 .15 .15 .15 }; }; Stage { Type = point; Radius = 10; }; } # Low-energy (small and red) explosion. Red fireballs. Generator { State = "TBALLX1"; Flags = "gnf_blend"; Speed = 5; Speed rnd = 0.6; Spawn age = 2; Spawn radius = 12; Max age = 200; Particles = 50; Spawn rate = 20; Spawn Rnd = 0.2; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 12; Rnd = .5; Radius = 15; Color { 1 .9 .5 .8 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 10; Rnd = .5; Radius = 13; Color { 1 .7 .5 .7 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 15; Rnd = 0.2; Radius = 10; Color { 1 .2 .1 .5 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Radius = 10; Color { .5 0 0 0 }; }; } # Cacodemon fireball explosion. Copy Generator { State = "RBALLX1"; } # Revenant tracer missile explosion. Copy Generator { State = "TRACEEXP1"; Center { 0 0 8 }; } # Skull explosion. Copy Generator { State = "SKULL_DIE3"; Center { 0 0 24 }; Flags = "gnf_blend"; Speed = 4; Speed rnd = 0.8; Spawn age = 2; Spawn radius = 30; Max age = 200; Particles = 100; Spawn rate = 30; Spawn rnd = 0.1; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 6; Rnd = .5; Radius = 13; Color { 1 1 1 1 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 13; Rnd = .6; Radius = 12; Color { 1 .8 .5 1 }; Resistance = 0.3; Gravity = -0.15; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 13; Rnd = .7; Radius = 15; Color { 1 .3 .1 .7 }; Resistance = 0.2; Gravity = -0.15; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 10; Rnd = .8; Radius = 13; Color { .5 .1 .1 .3 }; Resistance = 0.2; Gravity = -0.15; }; Stage { Type = "pt_point"; Radius = 10; }; } # Pain Elemental death explosion. Copy Generator { State = "PAIN_DIE3"; } # Green blast explosion. Generator { State = "BRBALLX1"; Flags = "gnf_blend"; Center { 0 0 -4 }; Speed = 3; Speed rnd = 0.6; Spawn age = 2; Spawn radius = 14; Max age = 200; Particles = 50; Spawn rate = 20; Spawn Rnd = 0.2; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 12; Rnd = .5; Radius = 10; Color { .5 1 .5 .8 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 10; Rnd = .5; Radius = 8; Color { .2 1 .2 .7 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Flags = "ptf_bright"; Tics = 15; Rnd = 0.2; Radius = 6; Color { 0 1 0 .5 }; Resistance = 0.2; }; Stage { Type = "pt_point"; Radius = 10; Color { 0 .5 0 0 }; }; } ######=====---- PICK-UP OBJECTS ----=====###### # Invulnerability. Generator { State = "PINV"; Flags = "gnf_blend gnf_spawn"; Center { 0 0 12 }; Spawn age = -1; Max age = -1; Particles = 80; Spawn rate = .6; Spawn rnd = 1; Min spawn radius = 10; Spawn radius = 15; Vector rnd = 1; Force radius = 15; Force = 0.02; Force axis { 0 0 1.5 }; Stage { Type = "pt_point"; Flags = "ptf_bright ptf_force"; Radius = 0; Color { 0 1 0 0 }; Tics = 20; Resistance = 0.05; }; Stage { Type = "pt_point"; Flags = "ptf_bright ptf_force"; Radius = 2.5; Color { .3 1 .3 .8 }; Tics = 20; Resistance = 0.05; }; Stage { Type = "pt_point"; Flags = "ptf_bright ptf_force"; Radius = 2.5; Color { .3 1 .3 .8 }; Tics = 30; Resistance = 0.05; }; Stage { Type = "pt_point"; Flags = "ptf_bright ptf_force"; Radius = 0; Color { 0 1 0 0 }; }; } ######=====---- DAMAGE ----=====###### # Gibbed blood spurt. Generator { State = "POSS_XDIE2"; Flags = "gnf_srcvel"; Center { 0 0 30 }; Speed = 6; Speed rnd = 0.7; Spawn age = 4; Max age = 300; Particles = 200; Spawn rate = 30; Spawn Rnd = 0.1; Vector rnd = 1; Stage { Type = "pt_point"; Flags = "ptf_flat ptf_stagetouch"; Radius = 1.5; Color { .7 0 0 1 }; Tics = 300; Resistance = 0.01; Gravity = 0.15; }; Stage { Type = "pt_point"; Flags = "ptf_flat"; Radius = 16; Radius rnd = 0.8; Color { .7 0 0 1 }; Tics = 200; Resistance = 1; }; Stage { Type = "pt_point"; Radius = 9; Radius rnd = 0.8; Color { .45 0 0 0 }; }; } Copy Generator { State = "PLAY_XDIE2"; } Copy Generator { State = "SPOS_XDIE2"; } Copy Generator { State = "TROO_XDIE2"; } Copy Generator { State = "CPOS_XDIE2"; } Copy Generator { State = "SSWV_XDIE2"; } # Pink demon death blood. Copy Generator { State = "SARG_DIE1"; Speed = 4; Spawn age = 3; Spawn rate = 20; } Copy Generator { State = "FATT_DIE2"; } # Trooper death blood. Copy Generator { State = "TROO_DIE1"; Speed = 3; Spawn age = 2; Spawn rate = 15; } # Arachnotron death. Copy Generator { State = "BSPI_DIE2"; } # Cacodemon blue blood. Copy Generator { State = "HEAD_DIE3"; Stage { Type = "pt_point"; Flags = "ptf_flat ptf_stagetouch"; Radius = 1.5; Color { 0 0 .7 1 }; Tics = 300; Resistance = 0.01; Gravity = 0.15; }; Stage { Type = "pt_point"; Flags = "ptf_flat"; Radius = 13; Color { 0 0 .7 1 }; Tics = 200; Resistance = 1; }; Stage { Type = "pt_point"; Radius = 7; Color { 0 0 .4 0 }; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2-tntlights.ded0000644000175000017500000000100211357170242024304 0ustar keeskees# jDoom: Light Decorations for Doom II-tnt Header { Version = 6; } # This file is skipped if not Doom II TNT. SkipIf Not doom2-tnt; #####====--- LIGHT DECORATIONS FOR DOOM II TNT ---====##### # # The default flags allow using these only with the original textures. # Use "dcf_pwad" and "dcf_ext" to allow using with PWAD and external # resources. # # There can only be one decoration per texture/flat. Newer decorations # override older ones. # # One decoration can specify up to 16 lights. # deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom1skies.ded0000644000175000017500000000117711357170242023341 0ustar keeskees# # jDoom: DOOM1 Skies # Sky { ID = "sky1"; Height = 0.49; Horizon offset = -0.105; Layer 1 { Flags = enable; Texture = "SKY1"; } } # The rest of this file is skipped if DOOM1 Shareware SkipIf doom1-share Copy Sky { ID = "sky2"; Light color { 1.0 0.85 0.85 }; Layer 1 { Texture = "SKY2"; }; } Copy Sky { ID = "sky3"; # This is hell, give it a reddish tint. Light color { 1.0 0.7 0.7 }; Layer 1 { Texture = "SKY3"; }; } Copy Sky { ID = "sky4"; # The sky is orange. Light color { 1.0 0.75 0.6 }; Layer 1 { Texture = "SKY4"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2-plutmaps.ded0000644000175000017500000000636511357170242024152 0ustar keeskees# # jDoom: Plutonia Maps # # The default definition, used for any maps without a map info definition. Map Info { ID = "*"; Author = "Unknown"; Music = "runnin"; Gravity = 1; Sky = "sky1"; } Map Info { ID = "MAP01"; Name = "PHUSTR_1"; Author = "Dario Casali and Milo Casali"; Music = "runnin"; Par time = 30; Gravity = 1; Sky = "sky1"; } Copy Map Info { ID = "MAP02"; Name = "PHUSTR_2"; Music = "stalks"; Par time = 90; } Copy Map Info { ID = "MAP03"; Name = "PHUSTR_3"; Music = "countd"; Par time = 120; } Copy Map Info { ID = "MAP04"; Name = "PHUSTR_4"; Music = "betwee"; Par time = 120; } Copy Map Info { ID = "MAP05"; Name = "PHUSTR_5"; Music = "doom"; Par time = 90; } Copy Map Info { ID = "MAP06"; Name = "PHUSTR_6"; Music = "the_da"; Par time = 150; } Copy Map Info { ID = "MAP07"; Name = "PHUSTR_7"; Music = "shawn"; Par time = 120; } Copy Map Info { ID = "MAP08"; Name = "PHUSTR_8"; Music = "ddtblu"; Par time = 120; } Copy Map Info { ID = "MAP09"; Name = "PHUSTR_9"; Music = "in_cit"; Par time = 270; } Copy Map Info { ID = "MAP10"; Name = "PHUSTR_10"; Music = "dead"; Par time = 90; } Copy Map Info { ID = "MAP11"; Name = "PHUSTR_11"; Music = "stlks2"; Par time = 210; } Copy Map Info { ID = "MAP12"; Name = "PHUSTR_12"; Music = "theda2"; Par time = 150; Sky = "sky2"; } Copy Map Info { ID = "MAP13"; Name = "PHUSTR_13"; Music = "doom2"; Par time = 150; } Copy Map Info { ID = "MAP14"; Name = "PHUSTR_14"; Music = "ddtbl2"; Par time = 150; } Copy Map Info { ID = "MAP15"; Name = "PHUSTR_15"; Music = "runni2"; Par time = 210; } Copy Map Info { ID = "MAP16"; Name = "PHUSTR_16"; Music = "dead2"; Par time = 150; } Copy Map Info { ID = "MAP17"; Name = "PHUSTR_17"; Music = "stlks3"; Par time = 420; } Copy Map Info { ID = "MAP18"; Name = "PHUSTR_18"; Music = "romero"; Par time = 150; } Copy Map Info { ID = "MAP19"; Name = "PHUSTR_19"; Music = "shawn2"; Par time = 210; } Copy Map Info { ID = "MAP20"; Name = "PHUSTR_20"; Music = "messag"; Par time = 150; } Copy Map Info { ID = "MAP21"; Name = "PHUSTR_21"; Music = "count2"; Par time = 240; Sky = "sky3"; } Copy Map Info { ID = "MAP22"; Name = "PHUSTR_22"; Music = "ddtbl3"; Par time = 150; } Copy Map Info { ID = "MAP23"; Name = "PHUSTR_23"; Music = "ampie"; Par time = 180; } Copy Map Info { ID = "MAP24"; Name = "PHUSTR_24"; Music = "theda3"; Par time = 150; } Copy Map Info { ID = "MAP25"; Name = "PHUSTR_25"; Music = "adrian"; Par time = 150; } Copy Map Info { ID = "MAP26"; Name = "PHUSTR_26"; Music = "messg2"; Par time = 300; } Copy Map Info { ID = "MAP27"; Name = "PHUSTR_27"; Music = "romer2"; Par time = 330; } Copy Map Info { ID = "MAP28"; Name = "PHUSTR_28"; Music = "tense"; Par time = 420; } Copy Map Info { ID = "MAP29"; Name = "PHUSTR_29"; Music = "shawn3"; Par time = 300; } Copy Map Info { ID = "MAP30"; Name = "PHUSTR_30"; Music = "openin"; Par time = 180; } Copy Map Info { ID = "MAP31"; Name = "PHUSTR_31"; Music = "evil"; Par time = 120; } Copy Map Info { ID = "MAP32"; Name = "PHUSTR_32"; Music = "ultima"; Par time = 30; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2-plutfinales.ded0000644000175000017500000001746711357170242024640 0ustar keeskees# jDoom: Intermissions and Finales (Final DOOM/Plutonia) # (see Doc\InFine.txt) Header { Version = 5; } # I'm using "textdef" to allow compatibility with DeHackEd. # A better way would just be to use "text" and define the text # in the script, no need to go about modifying the Text defs. #######=======------- PLUTONIA EXPERIMENT -------=======####### Finale { Before = "MAP07"; Script { music "read_m" flat SLIME16 wait 0.5 textdef msg 10 10 "P1TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP12"; Script { music "read_m" flat RROCK14 wait 0.5 textdef msg 10 10 "P2TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } Finale { Before = "MAP21"; Script { music "read_m" flat RROCK07 wait 0.5 textdef msg 10 10 "P3TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. }; } # This is the actual finale of Plutonia Experiment. Finale { After = "MAP30"; Script { music "read_m" flat RROCK17 wait 0.5 textdef msg 10 10 "P4TEXT" waittext msg; wait 7 skiphere #####====--- The Cast ---====##### # Castloop continues forever. # Quite a number of monsters here...! noskip # No more skipping (pause waits for a key, though). deltext msg music "evil" noflat; patch back 0 0 BOSSBACK marker castloop # Create a text for the name. textdef name 160 180 CC_ZOMBIE center name; rate name 0 patch mo 160 170 POSSA1 # "mo" is used for all the monsters. # --- Zombieman --- clranim mo states mo POSS_RUN1 12 states mo POSS_ATK1 2; picsound mo "pistol" states mo POSS_ATK3 1 repeat mo seesound POSSESSED; pause; diesound POSSESSED clranim mo states mo POSS_DIE1 5 waitanim mo; wait 0.43 # --- Shotgun Guy --- clranim mo states mo SPOS_RUN1 12 states mo SPOS_ATK1 2; picsound mo "shotgn" states mo SPOS_ATK3 1 repeat mo settextdef name CC_SHOTGUN seesound SHOTGUY; pause; diesound SHOTGUY clranim mo states mo SPOS_DIE1 5 waitanim mo; wait 0.43 # --- Heavy Weapon Dude --- clranim mo states mo CPOS_RUN1 12 states mo CPOS_ATK1 2; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" states mo CPOS_ATK4 1; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" states mo CPOS_ATK4 1; picsound mo "shotgn" states mo CPOS_ATK3 1; picsound mo "shotgn" repeat mo settextdef name CC_HEAVY seesound CHAINGUY; pause; diesound CHAINGUY clranim mo states mo CPOS_DIE1 7 waitanim mo; wait 0.43 # --- Imp --- clranim mo states mo TROO_RUN1 12 states mo TROO_ATK1 3; picsound mo "claw" repeat mo settextdef name CC_IMP seesound TROOP; pause; diesound TROOP clranim mo states mo TROO_DIE1 5 waitanim mo; wait 0.43 # --- Demon --- clranim mo states mo SARG_RUN1 12 states mo SARG_ATK1 2; picsound mo "sgtatk" states mo SARG_ATK3 1 repeat mo settextdef name CC_DEMON seesound SERGEANT; pause; diesound SERGEANT clranim mo states mo SARG_DIE1 6 waitanim mo; wait 0.43 # --- Lost Soul --- clranim mo states mo SKULL_RUN1 12 states mo SKULL_ATK1 2; picsound mo "sklatk" states mo SKULL_ATK3 8 repeat mo settextdef name CC_LOST seesound SKULL; pause; diesound SKULL clranim mo states mo SKULL_DIE1 6 waitanim mo; wait 0.43 # --- Cacodemon --- clranim mo states mo HEAD_RUN1 12 states mo HEAD_ATK1 2; picsound mo "firsht" states mo HEAD_ATK3 1 repeat mo settextdef name CC_CACO seesound HEAD; pause; diesound HEAD clranim mo states mo HEAD_DIE1 6 waitanim mo; wait 0.43 # --- Hell Knight --- clranim mo states mo BOS2_RUN1 12 states mo BOS2_ATK1 2; picsound mo "firsht" states mo BOS2_ATK3 1 repeat mo settextdef name CC_HELL seesound KNIGHT; pause; diesound KNIGHT clranim mo states mo BOS2_DIE1 7 waitanim mo; wait 0.43 # --- Baron of Hell --- clranim mo states mo BOSS_RUN1 12 states mo BOSS_ATK1 2; picsound mo "firsht" states mo BOSS_ATK3 1 repeat mo settextdef name CC_BARON seesound BRUISER; pause; diesound BRUISER clranim mo states mo BOSS_DIE1 7 waitanim mo; wait 0.43 # --- Arachnotron --- clranim mo states mo BSPI_SIGHT 12 states mo BSPI_ATK1 2; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 3; picsound mo "plasma" states mo BSPI_ATK3 2 repeat mo settextdef name CC_ARACH seesound BABY; pause; diesound BABY clranim mo states mo BSPI_DIE1 7 waitanim mo; wait 0.43 # --- Pain Elemental --- clranim mo states mo PAIN_RUN1 12 states mo PAIN_ATK1 3; picsound mo "sklatk" states mo PAIN_ATK4 1 repeat mo settextdef name CC_PAIN seesound PAIN; pause; diesound PAIN clranim mo states mo PAIN_DIE1 6 waitanim mo; wait 0.43 # --- Revenant --- clranim mo states mo SKEL_RUN1 12 states mo SKEL_MISS1 2; picsound mo "skeatk" states mo SKEL_MISS3 2 states mo SKEL_RUN1 12 states mo SKEL_FIST1 2; picsound mo "skeswg" states mo SKEL_FIST3 2; picsound mo "skepch" repeat mo settextdef name CC_REVEN seesound UNDEAD; pause; diesound UNDEAD clranim mo states mo SKEL_DIE1 6 waitanim mo; wait 0.43 # --- Mancubus --- clranim mo states mo FATT_RUN1 12 states mo FATT_ATK1 2; picsound mo "firsht" states mo FATT_ATK3 3; picsound mo "firsht" states mo FATT_ATK6 3; picsound mo "firsht" states mo FATT_ATK9 2 repeat mo settextdef name CC_MANCU seesound FATSO; pause; diesound FATSO clranim mo states mo FATT_DIE1 10 waitanim mo; wait 0.43 # --- Arch-Vile --- clranim mo states mo VILE_RUN1 12 states mo VILE_ATK1 2; picsound mo "vilatk" states mo VILE_ATK3 9 repeat mo settextdef name CC_ARCH seesound VILE; pause; diesound VILE clranim mo states mo VILE_DIE1 10 waitanim mo; wait 0.43 # --- The Spider Mastermind --- clranim mo states mo SPID_RUN1 12 states mo SPID_ATK1 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" states mo SPID_ATK4 2; picsound mo "shotgn" states mo SPID_ATK3 1; picsound mo "shotgn" repeat mo settextdef name CC_SPIDER seesound SPIDER; pause; diesound SPIDER clranim mo states mo SPID_DIE1 11 waitanim mo; wait 0.43 # --- Cyberdemon --- clranim mo states mo CYBER_RUN1 12 states mo CYBER_ATK1 2; picsound mo "rlaunc" states mo CYBER_ATK3 2; picsound mo "rlaunc" states mo CYBER_ATK5 2; picsound mo "rlaunc" repeat mo settextdef name CC_CYBER seesound CYBORG; pause; diesound CYBORG clranim mo states mo CYBER_DIE1 10 waitanim mo; wait 0.43 # --- Our Hero (finally!) --- clranim mo states mo PLAY_RUN1 12 states mo PLAY_ATK1 1 repeat mo settextdef name CC_HERO seesound PLAYER; pause; diesound PLAYER clranim mo states mo PLAY_DIE1 7 waitanim mo; wait 0.43 # Restart the loop. goto castloop }; } # Secret level 1. Finale { Before = "MAP31"; Script { music "read_m"; flat RROCK13; wait 0.5; textdef msg 10 10 "P5TEXT"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. }; } # Secret level 2. Finale { Before = "MAP32"; Script { music "read_m"; flat RROCK19; wait 0.5; textdef msg 10 10 "P6TEXT"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/objects.ded0000644000175000017500000056073211357170242022723 0ustar keeskees# jDoom: Objects # # Order of definitions is very important here! # Only add new States and Things *after* the existing definitions. Header { Version = 6; } Thing { ID = "PLAYER"; DoomEd number = -1; Spawn state = "PLAY"; See state = "PLAY_RUN1"; Pain state = "PLAY_PAIN"; Melee state = "NULL"; Missile state = "PLAY_ATK1"; Death state = "PLAY_DIE1"; Xdeath state = "PLAY_XDIE1"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "plpain"; Death sound = "pldeth"; Active sound = "None"; Pain chance = 255; Spawn health = 100; Radius = 16; Height = 56; Mass = 100; Flags = solid | shootable | dropoff | pickup; Flags2 = slide | passmobj | telestomp; } Thing { ID = "POSSESSED"; Name = "Zombieman"; DoomEd number = 3004; Spawn state = "POSS_STND"; See state = "POSS_RUN1"; Pain state = "POSS_PAIN"; Melee state = "NULL"; Missile state = "POSS_ATK1"; Death state = "POSS_DIE1"; Xdeath state = "POSS_XDIE1"; Raise state = "POSS_RAISE1"; See sound = "posit1"; Attack sound = "pistol"; Pain sound = "popain"; Death sound = "podth1"; Active sound = "posact"; Reaction time = 8; Pain chance = 200; Spawn health = 20; Speed = 8; Radius = 20; Height = 56; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SHOTGUY"; Name = "Shotgun Guy"; DoomEd number = 9; Spawn state = "SPOS_STND"; See state = "SPOS_RUN1"; Pain state = "SPOS_PAIN"; Melee state = "NULL"; Missile state = "SPOS_ATK1"; Death state = "SPOS_DIE1"; Xdeath state = "SPOS_XDIE1"; Raise state = "SPOS_RAISE1"; See sound = "posit2"; Attack sound = "None"; Pain sound = "popain"; Death sound = "podth2"; Active sound = "posact"; Reaction time = 8; Pain chance = 170; Spawn health = 30; Speed = 8; Radius = 20; Height = 56; Mass = 100; Flags = solid | shootable |countkill; Flags2 = passmobj | telestomp; } Thing { ID = "VILE"; Name = "Arch-Vile"; DoomEd number = 64; Spawn state = "VILE_STND"; See state = "VILE_RUN1"; Pain state = "VILE_PAIN"; Melee state = "NULL"; Missile state = "VILE_ATK1"; Death state = "VILE_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "vilsit"; Attack sound = "None"; Pain sound = "vipain"; Death sound = "vildth"; Active sound = "vilact"; Reaction time = 8; Pain chance = 10; Spawn health = 700; Speed = 15; Radius = 20; Height = 56; Mass = 500; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FIRE"; DoomEd number = -1; Spawn state = "FIRE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity | brightshadow; Flags2 = cannotpush | noteleport; } Thing { ID = "UNDEAD"; Name = "Revenant"; DoomEd number = 66; Spawn state = "SKEL_STND"; See state = "SKEL_RUN1"; Pain state = "SKEL_PAIN"; Melee state = "SKEL_FIST1"; Missile state = "SKEL_MISS1"; Death state = "SKEL_DIE1"; Xdeath state = "NULL"; Raise state = "SKEL_RAISE1"; See sound = "skesit"; Attack sound = "None"; Pain sound = "popain"; Death sound = "skedth"; Active sound = "skeact"; Reaction time = 8; Pain chance = 100; Spawn health = 300; Speed = 10; Radius = 20; Height = 56; Mass = 500; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "TRACER"; DoomEd number = -1; Spawn state = "TRACER"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "TRACEEXP1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "skeatk"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 11; Height = 8; Mass = 100; Damage = 10; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "SMOKE"; DoomEd number = -1; Spawn state = "SMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "FATSO"; Name = "Mancubus"; DoomEd number = 67; Spawn state = "FATT_STND"; See state = "FATT_RUN1"; Pain state = "FATT_PAIN"; Melee state = "NULL"; Missile state = "FATT_ATK1"; Death state = "FATT_DIE1"; Xdeath state = "NULL"; Raise state = "FATT_RAISE1"; See sound = "mansit"; Attack sound = "None"; Pain sound = "mnpain"; Death sound = "mandth"; Active sound = "posact"; Reaction time = 8; Pain chance = 80; Spawn health = 600; Speed = 8; Radius = 48; Height = 64; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "FATSHOT"; DoomEd number = -1; Spawn state = "FATSHOT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "FATSHOTX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 6; Height = 8; Mass = 100; Damage = 8; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "CHAINGUY"; Name = "Heavy Weapon Dude"; DoomEd number = 65; Spawn state = "CPOS_STND"; See state = "CPOS_RUN1"; Pain state = "CPOS_PAIN"; Melee state = "NULL"; Missile state = "CPOS_ATK1"; Death state = "CPOS_DIE1"; Xdeath state = "CPOS_XDIE1"; Raise state = "CPOS_RAISE1"; See sound = "posit2"; Attack sound = "None"; Pain sound = "popain"; Death sound = "podth2"; Active sound = "posact"; Reaction time = 8; Pain chance = 170; Spawn health = 70; Speed = 8; Radius = 20; Height = 56; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "TROOP"; Name = "Imp"; DoomEd number = 3001; Spawn state = "TROO_STND"; See state = "TROO_RUN1"; Pain state = "TROO_PAIN"; Melee state = "TROO_ATK1"; Missile state = "TROO_ATK1"; Death state = "TROO_DIE1"; Xdeath state = "TROO_XDIE1"; Raise state = "TROO_RAISE1"; See sound = "bgsit1"; Attack sound = "None"; Pain sound = "popain"; Death sound = "bgdth1"; Active sound = "bgact"; Reaction time = 8; Pain chance = 200; Spawn health = 60; Speed = 8; Radius = 20; Height = 56; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SERGEANT"; Name = "Demon"; DoomEd number = 3002; Spawn state = "SARG_STND"; See state = "SARG_RUN1"; Pain state = "SARG_PAIN"; Melee state = "SARG_ATK1"; Missile state = "NULL"; Death state = "SARG_DIE1"; Xdeath state = "NULL"; Raise state = "SARG_RAISE1"; See sound = "sgtsit"; Attack sound = "sgtatk"; Pain sound = "dmpain"; Death sound = "sgtdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 180; Spawn health = 150; Speed = 10; Radius = 30; Height = 56; Mass = 400; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SHADOWS"; Name = "Spectre"; DoomEd number = 58; Spawn state = "SARG_STND"; See state = "SARG_RUN1"; Pain state = "SARG_PAIN"; Melee state = "SARG_ATK1"; Missile state = "NULL"; Death state = "SARG_DIE1"; Xdeath state = "NULL"; Raise state = "SARG_RAISE1"; See sound = "sgtsit"; Attack sound = "sgtatk"; Pain sound = "dmpain"; Death sound = "sgtdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 180; Spawn health = 150; Speed = 10; Radius = 30; Height = 56; Mass = 400; Flags = solid | shootable | shadow | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "HEAD"; Name = "Cacodemon"; DoomEd number = 3005; Spawn state = "HEAD_STND"; See state = "HEAD_RUN1"; Pain state = "HEAD_PAIN"; Melee state = "NULL"; Missile state = "HEAD_ATK1"; Death state = "HEAD_DIE1"; Xdeath state = "NULL"; Raise state = "HEAD_RAISE1"; See sound = "cacsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "cacdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 128; Spawn health = 400; Speed = 8; Radius = 31; Height = 56; Mass = 400; Flags = solid | shootable | float | nogravity | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "BRUISER"; Name = "Baron of Hell"; DoomEd number = 3003; Spawn state = "BOSS_STND"; See state = "BOSS_RUN1"; Pain state = "BOSS_PAIN"; Melee state = "BOSS_ATK1"; Missile state = "BOSS_ATK1"; Death state = "BOSS_DIE1"; Xdeath state = "NULL"; Raise state = "BOSS_RAISE1"; See sound = "brssit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "brsdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 50; Spawn health = 1000; Speed = 8; Radius = 24; Height = 64; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "BRUISERSHOT"; DoomEd number = -1; Spawn state = "BRBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BRBALLX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 6; Height = 8; Mass = 100; Damage = 8; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "KNIGHT"; Name = "Hell Knight"; DoomEd number = 69; Spawn state = "BOS2_STND"; See state = "BOS2_RUN1"; Pain state = "BOS2_PAIN"; Melee state = "BOS2_ATK1"; Missile state = "BOS2_ATK1"; Death state = "BOS2_DIE1"; Xdeath state = "NULL"; Raise state = "BOS2_RAISE1"; See sound = "kntsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "kntdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 50; Spawn health = 500; Speed = 8; Radius = 24; Height = 64; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "SKULL"; Name = "Lost Soul"; DoomEd number = 3006; Spawn state = "SKULL_STND"; See state = "SKULL_RUN1"; Pain state = "SKULL_PAIN"; Melee state = "NULL"; Missile state = "SKULL_ATK1"; Death state = "SKULL_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "sklatk"; Pain sound = "dmpain"; Death sound = "firxpl"; Active sound = "dmact"; Reaction time = 8; Pain chance = 256; Spawn health = 100; Speed = 8; Radius = 16; Height = 56; Mass = 50; Damage = 3; Flags = solid | shootable | float | nogravity; Flags2 = passmobj | telestomp; } Thing { ID = "SPIDER"; Name = "The Spider Mastermind"; DoomEd number = 7; Spawn state = "SPID_STND"; See state = "SPID_RUN1"; Pain state = "SPID_PAIN"; Melee state = "NULL"; Missile state = "SPID_ATK1"; Death state = "SPID_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "spisit"; Attack sound = "shotgn"; Pain sound = "dmpain"; Death sound = "spidth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 40; Spawn health = 3000; Speed = 12; Radius = 128; Height = 100; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp | boss; } Thing { ID = "BABY"; Name = "Arachnotron"; DoomEd number = 68; Spawn state = "BSPI_STND"; See state = "BSPI_SIGHT"; Pain state = "BSPI_PAIN"; Melee state = "NULL"; Missile state = "BSPI_ATK1"; Death state = "BSPI_DIE1"; Xdeath state = "NULL"; Raise state = "BSPI_RAISE1"; See sound = "bspsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "bspdth"; Active sound = "bspact"; Reaction time = 8; Pain chance = 128; Spawn health = 500; Speed = 12; Radius = 64; Height = 64; Mass = 600; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "CYBORG"; Name = "Cyberdemon"; DoomEd number = 16; Spawn state = "CYBER_STND"; See state = "CYBER_RUN1"; Pain state = "CYBER_PAIN"; Melee state = "NULL"; Missile state = "CYBER_ATK1"; Death state = "CYBER_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "cybsit"; Attack sound = "None"; Pain sound = "dmpain"; Death sound = "cybdth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 20; Spawn health = 4000; Speed = 16; Radius = 40; Height = 110; Mass = 1000; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp | boss; } Thing { ID = "PAIN"; Name = "Pain Elemental"; DoomEd number = 71; Spawn state = "PAIN_STND"; See state = "PAIN_RUN1"; Pain state = "PAIN_PAIN"; Melee state = "NULL"; Missile state = "PAIN_ATK1"; Death state = "PAIN_DIE1"; Xdeath state = "NULL"; Raise state = "PAIN_RAISE1"; See sound = "pesit"; Attack sound = "None"; Pain sound = "pepain"; Death sound = "pedth"; Active sound = "dmact"; Reaction time = 8; Pain chance = 128; Spawn health = 400; Speed = 8; Radius = 31; Height = 56; Mass = 400; Flags = solid | shootable | float | nogravity | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "WOLFSS"; DoomEd number = 84; Spawn state = "SSWV_STND"; See state = "SSWV_RUN1"; Pain state = "SSWV_PAIN"; Melee state = "NULL"; Missile state = "SSWV_ATK1"; Death state = "SSWV_DIE1"; Xdeath state = "SSWV_XDIE1"; Raise state = "SSWV_RAISE1"; See sound = "sssit"; Attack sound = "None"; Pain sound = "popain"; Death sound = "ssdth"; Active sound = "posact"; Reaction time = 8; Pain chance = 170; Spawn health = 50; Speed = 8; Radius = 20; Height = 56; Mass = 100; Flags = solid | shootable | countkill; Flags2 = passmobj | telestomp; } Thing { ID = "KEEN"; DoomEd number = 72; Spawn state = "KEENSTND"; See state = "NULL"; Pain state = "KEENPAIN"; Melee state = "NULL"; Missile state = "NULL"; Death state = "COMMKEEN"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "keenpn"; Death sound = "keendt"; Active sound = "None"; Reaction time = 8; Pain chance = 256; Spawn health = 100; Radius = 16; Height = 72; Mass = 10000000; Flags = solid | spawnceiling | nogravity | shootable | countkill; Flags2 = telestomp; } Thing { ID = "BOSSBRAIN"; DoomEd number = 88; Spawn state = "BRAIN"; See state = "NULL"; Pain state = "BRAIN_PAIN"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BRAIN_DIE1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "bospn"; Death sound = "bosdth"; Active sound = "None"; Reaction time = 8; Pain chance = 255; Spawn health = 250; Radius = 16; Height = 16; Mass = 10000000; Flags = solid | shootable; Flags2 = radiusattacknomaxz | telestomp; } Thing { ID = "BOSSSPIT"; DoomEd number = 89; Spawn state = "BRAINEYE"; See state = "BRAINEYESEE"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 32; Mass = 100; Flags = noblockmap | nosector; } Thing { ID = "BOSSTARGET"; DoomEd number = 87; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 32; Mass = 100; Flags = noblockmap | nosector; } Thing { ID = "SPAWNSHOT"; DoomEd number = -1; Spawn state = "SPAWN1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "bospit"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 32; Mass = 100; Damage = 3; Flags = noblockmap | missile | dropoff | nogravity | noclip; Flags2 = cannotpush | noteleport; } Thing { ID = "SPAWNFIRE"; DoomEd number = -1; Spawn state = "SPAWNFIRE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "BARREL"; DoomEd number = 2035; Spawn state = "BAR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BEXP"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 20; Radius = 10; Height = 42; Mass = 100; Flags = solid | shootable | noblood; Flags2 = alwayslit | telestomp; } Thing { ID = "TROOPSHOT"; DoomEd number = -1; Spawn state = "TBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "TBALLX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 8; Mass = 100; Damage = 3; Flags = brightexplode | dropoff | missile | noblockmap | nogravity | brightshadow; Flags2 = noteleport; } Thing { ID = "HEADSHOT"; DoomEd number = -1; Spawn state = "RBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "RBALLX1"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "firsht"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 6; Height = 8; Mass = 100; Damage = 5; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "ROCKET"; DoomEd number = -1; Spawn state = "ROCKET"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "EXPLODE0"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "rlaunc"; Attack sound = "None"; Pain sound = "None"; Death sound = "barexp"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 11; Height = 8; Mass = 100; Damage = 20; Flags = noblockmap | missile | dropoff | nogravity | brightexplode; Flags2 = noteleport; } Thing { ID = "PLASMA"; DoomEd number = -1; Spawn state = "PLASBALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "PLASEXP"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "plasma"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 5; Flags = noblockmap | missile | dropoff | nogravity | brightshadow; Flags2 = noteleport; } Thing { ID = "BFG"; DoomEd number = -1; Spawn state = "BFGSHOT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "BFGLAND"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "rxplod"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 100; Flags = noblockmap | missile | dropoff | nogravity | brightexplode | brightshadow; Flags2 = noteleport; } Thing { ID = "ARACHPLAZ"; DoomEd number = -1; Spawn state = "ARACH_PLAZ"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "ARACH_PLEX"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "plasma"; Attack sound = "None"; Pain sound = "None"; Death sound = "firxpl"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 5; Flags = noblockmap | missile | dropoff | nogravity; Flags2 = noteleport; } Thing { ID = "PUFF"; DoomEd number = -1; Spawn state = "PUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 8; Mass = 100; Flags = noblockmap | nogravity | viewalign; Flags2 = cannotpush | noteleport; } Thing { ID = "BLOOD"; DoomEd number = -1; Spawn state = "BLOOD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | viewalign; Flags2 = cannotpush | noteleport; } Thing { ID = "TFOG"; DoomEd number = -1; Spawn state = "TFOG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "IFOG"; DoomEd number = -1; Spawn state = "IFOG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity; Flags2 = cannotpush | noteleport; } Thing { ID = "TELEPORTMAN"; DoomEd number = 14; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nosector | local; Flags2 = cannotpush; } Thing { ID = "EXTRABFG"; DoomEd number = -1; Spawn state = "BFGEXP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = noblockmap | nogravity | brightshadow; Flags2 = cannotpush | noteleport; } Thing { ID = "MISC0"; DoomEd number = 2018; Spawn state = "ARM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC1"; DoomEd number = 2019; Spawn state = "ARM2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC2"; DoomEd number = 2014; Spawn state = "BON1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC3"; DoomEd number = 2015; Spawn state = "BON2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC4"; DoomEd number = 5; Spawn state = "BKEY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC5"; DoomEd number = 13; Spawn state = "RKEY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC6"; DoomEd number = 6; Spawn state = "YKEY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC7"; DoomEd number = 39; Spawn state = "YSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC8"; DoomEd number = 38; Spawn state = "RSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC9"; DoomEd number = 40; Spawn state = "BSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | notdmatch; } Thing { ID = "MISC10"; DoomEd number = 2011; Spawn state = "STIM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC11"; DoomEd number = 2012; Spawn state = "MEDI"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC12"; DoomEd number = 2013; Spawn state = "SOUL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "INV"; DoomEd number = 2022; Spawn state = "PINV"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC13"; DoomEd number = 2023; Spawn state = "PSTR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "INS"; DoomEd number = 2024; Spawn state = "PINS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC14"; DoomEd number = 2025; Spawn state = "SUIT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC15"; DoomEd number = 2026; Spawn state = "PMAP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MISC16"; DoomEd number = 2045; Spawn state = "PVIS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "MEGA"; DoomEd number = 83; Spawn state = "MEGA"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special | countitem; } Thing { ID = "CLIP"; DoomEd number = 2007; Spawn state = "CLIP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC17"; DoomEd number = 2048; Spawn state = "AMMO"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC18"; DoomEd number = 2010; Spawn state = "ROCK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC19"; DoomEd number = 2046; Spawn state = "BROK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC20"; DoomEd number = 2047; Spawn state = "CELL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC21"; DoomEd number = 17; Spawn state = "CELP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC22"; DoomEd number = 2008; Spawn state = "SHEL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC23"; DoomEd number = 2049; Spawn state = "SBOX"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC24"; DoomEd number = 8; Spawn state = "BPAK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC25"; Name = "BFG 9000"; DoomEd number = 2006; Spawn state = "BFUG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "CHAINGUN"; DoomEd number = 2002; Spawn state = "MGUN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC26"; DoomEd number = 2005; Spawn state = "CSAW"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC27"; DoomEd number = 2003; Spawn state = "LAUN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC28"; DoomEd number = 2004; Spawn state = "PLAS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "SHOTGUN"; DoomEd number = 2001; Spawn state = "SHOT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "SUPERSHOTGUN"; DoomEd number = 82; Spawn state = "SHOT2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = special; } Thing { ID = "MISC29"; DoomEd number = 85; Spawn state = "TECHLAMP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 80; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC30"; DoomEd number = 86; Spawn state = "TECH2LAMP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC31"; DoomEd number = 2028; Spawn state = "COLU"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 48; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC32"; DoomEd number = 30; Spawn state = "TALLGRNCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 53; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC33"; DoomEd number = 31; Spawn state = "SHRTGRNCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC34"; DoomEd number = 32; Spawn state = "TALLREDCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 53; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC35"; DoomEd number = 33; Spawn state = "SHRTREDCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC36"; DoomEd number = 37; Spawn state = "SKULLCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC37"; DoomEd number = 36; Spawn state = "HEARTCOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC38"; DoomEd number = 41; Spawn state = "EVILEYE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 16; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC39"; DoomEd number = 42; Spawn state = "FLOATSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 35; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC40"; DoomEd number = 43; Spawn state = "TORCHTREE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 70; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC41"; DoomEd number = 44; Spawn state = "BLUETORCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC42"; DoomEd number = 45; Spawn state = "GREENTORCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC43"; DoomEd number = 46; Spawn state = "REDTORCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC44"; DoomEd number = 55; Spawn state = "BTORCHSHRT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC45"; DoomEd number = 56; Spawn state = "GTORCHSHRT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC46"; DoomEd number = 57; Spawn state = "RTORCHSHRT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC47"; DoomEd number = 47; Spawn state = "STALAGTITE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 40; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC48"; DoomEd number = 48; Spawn state = "TECHPILLAR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 128; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC49"; DoomEd number = 34; Spawn state = "CANDLESTIK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = local; } Thing { ID = "MISC50"; DoomEd number = 35; Spawn state = "CANDELABRA"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 60; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC51"; DoomEd number = 49; Spawn state = "BLOODYTWITCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 68; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC52"; DoomEd number = 50; Spawn state = "MEAT2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 84; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC53"; DoomEd number = 51; Spawn state = "MEAT3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 84; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC54"; DoomEd number = 52; Spawn state = "MEAT4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 68; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC55"; DoomEd number = 53; Spawn state = "MEAT5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 52; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC56"; DoomEd number = 59; Spawn state = "MEAT2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 84; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC57"; DoomEd number = 60; Spawn state = "MEAT4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 68; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC58"; DoomEd number = 61; Spawn state = "MEAT3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 52; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC59"; DoomEd number = 62; Spawn state = "MEAT5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 52; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC60"; DoomEd number = 63; Spawn state = "BLOODYTWITCH"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 68; Mass = 100; Flags = spawnceiling | nogravity | local; } Thing { ID = "MISC61"; DoomEd number = 22; Spawn state = "HEAD_DIE6"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC62"; DoomEd number = 15; Spawn state = "PLAY_DIE7"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC63"; DoomEd number = 18; Spawn state = "POSS_DIE5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC64"; DoomEd number = 21; Spawn state = "SARG_DIE6"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC65"; DoomEd number = 23; Spawn state = "SKULL_DIE6"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC66"; DoomEd number = 20; Spawn state = "TROO_DIE5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC67"; DoomEd number = 19; Spawn state = "SPOS_DIE5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC68"; DoomEd number = 10; Spawn state = "PLAY_XDIE9"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC69"; DoomEd number = 12; Spawn state = "PLAY_XDIE9"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC70"; DoomEd number = 28; Spawn state = "HEADSONSTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 67; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC71"; DoomEd number = 24; Spawn state = "GIBS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags2 = cannotpush; } Thing { ID = "MISC72"; DoomEd number = 27; Spawn state = "HEADONASTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 56; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC73"; DoomEd number = 29; Spawn state = "HEADCANDLES"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 43; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC74"; DoomEd number = 25; Spawn state = "DEADSTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 66; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC75"; DoomEd number = 26; Spawn state = "LIVESTICK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 66; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC76"; DoomEd number = 54; Spawn state = "BIGTREE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 32; Height = 124; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC77"; DoomEd number = 70; Spawn state = "BBAR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 30; Mass = 100; Flags = solid | local; Flags2 = telestomp; } Thing { ID = "MISC78"; DoomEd number = 73; Spawn state = "HANGNOGUTS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 88; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC79"; DoomEd number = 74; Spawn state = "HANGBNOBRAIN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 88; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC80"; DoomEd number = 75; Spawn state = "HANGTLOOKDN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC81"; DoomEd number = 76; Spawn state = "HANGTSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC82"; DoomEd number = 77; Spawn state = "HANGTLOOKUP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC83"; DoomEd number = 78; Spawn state = "HANGTNOBRAIN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 16; Height = 64; Mass = 100; Flags = solid | spawnceiling | nogravity | local; Flags2 = telestomp; } Thing { ID = "MISC84"; DoomEd number = 79; Spawn state = "COLONGIBS"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC85"; DoomEd number = 80; Spawn state = "SMALLPOOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC86"; DoomEd number = 81; Spawn state = "BRAINSTEM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "LIGHTSOURCE"; DoomEd number = 5000; Spawn state = "SMALL_WHITE_LIGHT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Radius = 16; Height = 16; Mass = 100; Flags = local | noblockmap | nogravity; } State { ID = "NULL"; Sprite = "TROO"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "LIGHTDONE"; Sprite = "SHTG"; Frame = 4; Tics = 0; Action = "A_Light0"; Next state = "NULL"; } State { ID = "PUNCH"; Sprite = "PUNG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PUNCH"; } State { ID = "PUNCHDOWN"; Sprite = "PUNG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PUNCHDOWN"; } State { ID = "PUNCHUP"; Sprite = "PUNG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PUNCHUP"; } State { ID = "PUNCH1"; Sprite = "PUNG"; Frame = 1; Tics = 4; Next state = "PUNCH2"; } State { ID = "PUNCH2"; Sprite = "PUNG"; Frame = 2; Tics = 4; Action = "A_Punch"; Next state = "PUNCH3"; } State { ID = "PUNCH3"; Sprite = "PUNG"; Frame = 3; Tics = 5; Next state = "PUNCH4"; } State { ID = "PUNCH4"; Sprite = "PUNG"; Frame = 2; Tics = 4; Next state = "PUNCH5"; } State { ID = "PUNCH5"; Sprite = "PUNG"; Frame = 1; Tics = 5; Action = "A_ReFire"; Next state = "PUNCH"; } State { ID = "PISTOL"; Sprite = "PISG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PISTOL"; } State { ID = "PISTOLDOWN"; Sprite = "PISG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PISTOLDOWN"; } State { ID = "PISTOLUP"; Sprite = "PISG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PISTOLUP"; } State { ID = "PISTOL1"; Sprite = "PISG"; Frame = 0; Tics = 4; Next state = "PISTOL2"; } State { ID = "PISTOL2"; Sprite = "PISG"; Frame = 1; Tics = 6; Action = "A_FirePistol"; Next state = "PISTOL3"; } State { ID = "PISTOL3"; Sprite = "PISG"; Frame = 2; Tics = 4; Next state = "PISTOL4"; } State { ID = "PISTOL4"; Sprite = "PISG"; Frame = 1; Tics = 5; Action = "A_ReFire"; Next state = "PISTOL"; } State { ID = "PISTOLFLASH"; Sprite = "PISF"; Frame = 0; Flags = fullbright; Tics = 7; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "SGUN"; Sprite = "SHTG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "SGUN"; } State { ID = "SGUNDOWN"; Sprite = "SHTG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "SGUNDOWN"; } State { ID = "SGUNUP"; Sprite = "SHTG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "SGUNUP"; } State { ID = "SGUN1"; Sprite = "SHTG"; Frame = 0; Tics = 3; Next state = "SGUN2"; } State { ID = "SGUN2"; Sprite = "SHTG"; Frame = 0; Tics = 7; Action = "A_FireShotgun"; Next state = "SGUN3"; } State { ID = "SGUN3"; Sprite = "SHTG"; Frame = 1; Tics = 5; Next state = "SGUN4"; } State { ID = "SGUN4"; Sprite = "SHTG"; Frame = 2; Tics = 5; Next state = "SGUN5"; } State { ID = "SGUN5"; Sprite = "SHTG"; Frame = 3; Tics = 4; Next state = "SGUN6"; } State { ID = "SGUN6"; Sprite = "SHTG"; Frame = 2; Tics = 5; Next state = "SGUN7"; } State { ID = "SGUN7"; Sprite = "SHTG"; Frame = 1; Tics = 5; Next state = "SGUN8"; } State { ID = "SGUN8"; Sprite = "SHTG"; Frame = 0; Tics = 3; Next state = "SGUN9"; } State { ID = "SGUN9"; Sprite = "SHTG"; Frame = 0; Tics = 7; Action = "A_ReFire"; Next state = "SGUN"; } State { ID = "SGUNFLASH1"; Sprite = "SHTF"; Frame = 0; Flags = fullbright; Tics = 4; Action = "A_Light1"; Next state = "SGUNFLASH2"; } State { ID = "SGUNFLASH2"; Sprite = "SHTF"; Frame = 1; Flags = fullbright; Tics = 3; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "DSGUN"; Sprite = "SHT2"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "DSGUN"; } State { ID = "DSGUNDOWN"; Sprite = "SHT2"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "DSGUNDOWN"; } State { ID = "DSGUNUP"; Sprite = "SHT2"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "DSGUNUP"; } State { ID = "DSGUN1"; Sprite = "SHT2"; Frame = 0; Tics = 3; Next state = "DSGUN2"; } State { ID = "DSGUN2"; Sprite = "SHT2"; Frame = 0; Tics = 7; Action = "A_FireShotgun2"; Next state = "DSGUN3"; } State { ID = "DSGUN3"; Sprite = "SHT2"; Frame = 1; Tics = 7; Next state = "DSGUN4"; } State { ID = "DSGUN4"; Sprite = "SHT2"; Frame = 2; Tics = 7; Action = "A_CheckReload"; Next state = "DSGUN5"; } State { ID = "DSGUN5"; Sprite = "SHT2"; Frame = 3; Tics = 7; Action = "A_OpenShotgun2"; Next state = "DSGUN6"; } State { ID = "DSGUN6"; Sprite = "SHT2"; Frame = 4; Tics = 7; Next state = "DSGUN7"; } State { ID = "DSGUN7"; Sprite = "SHT2"; Frame = 5; Tics = 7; Action = "A_LoadShotgun2"; Next state = "DSGUN8"; } State { ID = "DSGUN8"; Sprite = "SHT2"; Frame = 6; Tics = 6; Next state = "DSGUN9"; } State { ID = "DSGUN9"; Sprite = "SHT2"; Frame = 7; Tics = 6; Action = "A_CloseShotgun2"; Next state = "DSGUN10"; } State { ID = "DSGUN10"; Sprite = "SHT2"; Frame = 0; Tics = 5; Action = "A_ReFire"; Next state = "DSGUN"; } State { ID = "DSNR1"; Sprite = "SHT2"; Frame = 1; Tics = 7; Next state = "DSNR2"; } State { ID = "DSNR2"; Sprite = "SHT2"; Frame = 0; Tics = 3; Next state = "DSGUNDOWN"; } State { ID = "DSGUNFLASH1"; Sprite = "SHT2"; Frame = 8; Flags = fullbright; Tics = 5; Action = "A_Light1"; Next state = "DSGUNFLASH2"; } State { ID = "DSGUNFLASH2"; Sprite = "SHT2"; Frame = 9; Flags = fullbright; Tics = 3; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "CHAIN"; Sprite = "CHGG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CHAIN"; } State { ID = "CHAINDOWN"; Sprite = "CHGG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "CHAINDOWN"; } State { ID = "CHAINUP"; Sprite = "CHGG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "CHAINUP"; } State { ID = "CHAIN1"; Sprite = "CHGG"; Frame = 0; Tics = 4; Action = "A_FireCGun"; Next state = "CHAIN2"; } State { ID = "CHAIN2"; Sprite = "CHGG"; Frame = 1; Tics = 4; Action = "A_FireCGun"; Next state = "CHAIN3"; } State { ID = "CHAIN3"; Sprite = "CHGG"; Frame = 1; Tics = 0; Action = "A_ReFire"; Next state = "CHAIN"; } State { ID = "CHAINFLASH1"; Sprite = "CHGF"; Frame = 0; Flags = fullbright; Tics = 5; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "CHAINFLASH2"; Sprite = "CHGF"; Frame = 1; Flags = fullbright; Tics = 5; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "MISSILE"; Sprite = "MISG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MISSILE"; } State { ID = "MISSILEDOWN"; Sprite = "MISG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "MISSILEDOWN"; } State { ID = "MISSILEUP"; Sprite = "MISG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "MISSILEUP"; } State { ID = "MISSILE1"; Sprite = "MISG"; Frame = 1; Tics = 8; Action = "A_GunFlash"; Next state = "MISSILE2"; } State { ID = "MISSILE2"; Sprite = "MISG"; Frame = 1; Tics = 12; Action = "A_FireMissile"; Next state = "MISSILE3"; } State { ID = "MISSILE3"; Sprite = "MISG"; Frame = 1; Tics = 0; Action = "A_ReFire"; Next state = "MISSILE"; } State { ID = "MISSILEFLASH1"; Sprite = "MISF"; Frame = 0; Flags = fullbright; Tics = 1; #3; Action = "A_Light1"; Next state = "MISSILEFLASH2"; } State { ID = "MISSILEFLASH2"; Sprite = "MISF"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "MISSILEFLASH3"; } State { ID = "MISSILEFLASH3"; Sprite = "MISF"; Frame = 2; Flags = fullbright; Tics = 4; Action = "A_Light2"; Next state = "MISSILEFLASH4"; } State { ID = "MISSILEFLASH4"; Sprite = "MISF"; Frame = 3; Flags = fullbright; Tics = 4; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "SAW"; Sprite = "SAWG"; Frame = 2; Tics = 4; Action = "A_WeaponReady"; Next state = "SAWB"; } State { ID = "SAWB"; Sprite = "SAWG"; Frame = 3; Tics = 4; Action = "A_WeaponReady"; Next state = "SAW"; } State { ID = "SAWDOWN"; Sprite = "SAWG"; Frame = 2; Tics = 1; Action = "A_Lower"; Next state = "SAWDOWN"; } State { ID = "SAWUP"; Sprite = "SAWG"; Frame = 2; Tics = 1; Action = "A_Raise"; Next state = "SAWUP"; } State { ID = "SAW1"; Sprite = "SAWG"; Frame = 0; Tics = 4; Action = "A_Saw"; Next state = "SAW2"; } State { ID = "SAW2"; Sprite = "SAWG"; Frame = 1; Tics = 4; Action = "A_Saw"; Next state = "SAW3"; } State { ID = "SAW3"; Sprite = "SAWG"; Frame = 1; Tics = 0; Action = "A_ReFire"; Next state = "SAW"; } State { ID = "PLASMA"; Sprite = "PLSG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PLASMA"; } State { ID = "PLASMADOWN"; Sprite = "PLSG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PLASMADOWN"; } State { ID = "PLASMAUP"; Sprite = "PLSG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PLASMAUP"; } State { ID = "PLASMA1"; Sprite = "PLSG"; Frame = 0; Tics = 3; Action = "A_FirePlasma"; Next state = "PLASMA2"; } State { ID = "PLASMA2"; Sprite = "PLSG"; Frame = 1; Tics = 20; Action = "A_ReFire"; Next state = "PLASMA"; } State { ID = "PLASMAFLASH1"; Sprite = "PLSF"; Frame = 0; Flags = fullbright; Tics = 4; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "PLASMAFLASH2"; Sprite = "PLSF"; Frame = 1; Flags = fullbright; Tics = 4; Action = "A_Light1"; Next state = "LIGHTDONE"; } State { ID = "BFG"; Sprite = "BFGG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "BFG"; } State { ID = "BFGDOWN"; Sprite = "BFGG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "BFGDOWN"; } State { ID = "BFGUP"; Sprite = "BFGG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "BFGUP"; } State { ID = "BFG1"; Sprite = "BFGG"; Frame = 0; Tics = 20; Action = "A_BFGsound"; Next state = "BFG2"; } State { ID = "BFG2"; Sprite = "BFGG"; Frame = 1; Tics = 10; Action = "A_GunFlash"; Next state = "BFG3"; } State { ID = "BFG3"; Sprite = "BFGG"; Frame = 1; Tics = 10; Action = "A_FireBFG"; Next state = "BFG4"; } State { ID = "BFG4"; Sprite = "BFGG"; Frame = 1; Tics = 20; Action = "A_ReFire"; Next state = "BFG"; } State { ID = "BFGFLASH1"; Sprite = "BFGF"; Frame = 0; Flags = fullbright; Tics = 11; Action = "A_Light1"; Next state = "BFGFLASH2"; } State { ID = "BFGFLASH2"; Sprite = "BFGF"; Frame = 1; Flags = fullbright; Tics = 6; Action = "A_Light2"; Next state = "LIGHTDONE"; } State { ID = "BLOOD1"; Sprite = "BLUD"; Frame = 2; Tics = 8; Next state = "BLOOD2"; } State { ID = "BLOOD2"; Sprite = "BLUD"; Frame = 1; Tics = 8; Next state = "BLOOD3"; } State { ID = "BLOOD3"; Sprite = "BLUD"; Frame = 0; Tics = 8; Next state = "NULL"; } State { ID = "PUFF1"; Sprite = "PUFF"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "PUFF2"; } State { ID = "PUFF2"; Sprite = "PUFF"; Frame = 1; Tics = 4; Next state = "PUFF3"; } State { ID = "PUFF3"; Sprite = "PUFF"; Frame = 2; Tics = 4; Next state = "PUFF4"; } State { ID = "PUFF4"; Sprite = "PUFF"; Frame = 3; Tics = 4; Next state = "NULL"; } State { ID = "TBALL1"; Sprite = "BAL1"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "TBALL2"; } State { ID = "TBALL2"; Sprite = "BAL1"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "TBALL1"; } State { ID = "TBALLX1"; Sprite = "BAL1"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "TBALLX2"; } State { ID = "TBALLX2"; Sprite = "BAL1"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "TBALLX3"; } State { ID = "TBALLX3"; Sprite = "BAL1"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "RBALL1"; Sprite = "BAL2"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "RBALL2"; } State { ID = "RBALL2"; Sprite = "BAL2"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "RBALL1"; } State { ID = "RBALLX1"; Sprite = "BAL2"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "RBALLX2"; } State { ID = "RBALLX2"; Sprite = "BAL2"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "RBALLX3"; } State { ID = "RBALLX3"; Sprite = "BAL2"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "PLASBALL"; Sprite = "PLSS"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "PLASBALL2"; } State { ID = "PLASBALL2"; Sprite = "PLSS"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PLASBALL"; } State { ID = "PLASEXP"; Sprite = "PLSE"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "PLASEXP2"; } State { ID = "PLASEXP2"; Sprite = "PLSE"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "PLASEXP3"; } State { ID = "PLASEXP3"; Sprite = "PLSE"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "PLASEXP4"; } State { ID = "PLASEXP4"; Sprite = "PLSE"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "PLASEXP5"; } State { ID = "PLASEXP5"; Sprite = "PLSE"; Frame = 4; Flags = fullbright; Tics = 4; Next state = "NULL"; } State { ID = "ROCKET"; Sprite = "MISL"; Frame = 0; Flags = fullbright; Tics = 1; Next state = "ROCKET"; } State { ID = "BFGSHOT"; Sprite = "BFS1"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BFGSHOT2"; } State { ID = "BFGSHOT2"; Sprite = "BFS1"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BFGSHOT"; } State { ID = "BFGLAND"; Sprite = "BFE1"; Frame = 0; Flags = fullbright; Tics = 8; Next state = "BFGLAND2"; } State { ID = "BFGLAND2"; Sprite = "BFE1"; Frame = 1; Flags = fullbright; Tics = 8; Next state = "BFGLAND3"; } State { ID = "BFGLAND3"; Sprite = "BFE1"; Frame = 2; Flags = fullbright; Tics = 8; Action = "A_BFGSpray"; Next state = "BFGLAND4"; } State { ID = "BFGLAND4"; Sprite = "BFE1"; Frame = 3; Flags = fullbright; Tics = 8; Next state = "BFGLAND5"; } State { ID = "BFGLAND5"; Sprite = "BFE1"; Frame = 4; Flags = fullbright; Tics = 8; Next state = "BFGLAND6"; } State { ID = "BFGLAND6"; Sprite = "BFE1"; Frame = 5; Flags = fullbright; Tics = 8; Next state = "NULL"; } State { ID = "BFGEXP"; Sprite = "BFE2"; Frame = 0; Flags = fullbright; Tics = 8; Next state = "BFGEXP2"; } State { ID = "BFGEXP2"; Sprite = "BFE2"; Frame = 1; Flags = fullbright; Tics = 8; Next state = "BFGEXP3"; } State { ID = "BFGEXP3"; Sprite = "BFE2"; Frame = 2; Flags = fullbright; Tics = 8; Next state = "BFGEXP4"; } State { ID = "BFGEXP4"; Sprite = "BFE2"; Frame = 3; Flags = fullbright; Tics = 8; Next state = "NULL"; } State { ID = "EXPLODE1"; Sprite = "MISL"; Frame = 1; Flags = fullbright; Tics = 8; Action = "A_Explode"; Next state = "EXPLODE2"; } State { ID = "EXPLODE2"; Sprite = "MISL"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "EXPLODE3"; } State { ID = "EXPLODE3"; Sprite = "MISL"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "NULL"; } State { ID = "TFOG"; Sprite = "TFOG"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "TFOG01"; } State { ID = "TFOG01"; Sprite = "TFOG"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "TFOG02"; } State { ID = "TFOG02"; Sprite = "TFOG"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "TFOG2"; } State { ID = "TFOG2"; Sprite = "TFOG"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "TFOG3"; } State { ID = "TFOG3"; Sprite = "TFOG"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "TFOG4"; } State { ID = "TFOG4"; Sprite = "TFOG"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "TFOG5"; } State { ID = "TFOG5"; Sprite = "TFOG"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "TFOG6"; } State { ID = "TFOG6"; Sprite = "TFOG"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "TFOG7"; } State { ID = "TFOG7"; Sprite = "TFOG"; Frame = 6; Flags = fullbright; Tics = 6; Next state = "TFOG8"; } State { ID = "TFOG8"; Sprite = "TFOG"; Frame = 7; Flags = fullbright; Tics = 6; Next state = "TFOG9"; } State { ID = "TFOG9"; Sprite = "TFOG"; Frame = 8; Flags = fullbright; Tics = 6; Next state = "TFOG10"; } State { ID = "TFOG10"; Sprite = "TFOG"; Frame = 9; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "IFOG"; Sprite = "IFOG"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "IFOG01"; } State { ID = "IFOG01"; Sprite = "IFOG"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "IFOG02"; } State { ID = "IFOG02"; Sprite = "IFOG"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "IFOG2"; } State { ID = "IFOG2"; Sprite = "IFOG"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "IFOG3"; } State { ID = "IFOG3"; Sprite = "IFOG"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "IFOG4"; } State { ID = "IFOG4"; Sprite = "IFOG"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "IFOG5"; } State { ID = "IFOG5"; Sprite = "IFOG"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "PLAY"; Sprite = "PLAY"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PLAY_RUN1"; Sprite = "PLAY"; Frame = 0; Tics = 4; Next state = "PLAY_RUN2"; } State { ID = "PLAY_RUN2"; Sprite = "PLAY"; Frame = 1; Tics = 4; Next state = "PLAY_RUN3"; } State { ID = "PLAY_RUN3"; Sprite = "PLAY"; Frame = 2; Tics = 4; Next state = "PLAY_RUN4"; } State { ID = "PLAY_RUN4"; Sprite = "PLAY"; Frame = 3; Tics = 4; Next state = "PLAY_RUN1"; } State { ID = "PLAY_ATK1"; Sprite = "PLAY"; Frame = 4; Tics = 12; Next state = "PLAY"; } State { ID = "PLAY_ATK2"; Sprite = "PLAY"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "PLAY_ATK1"; } State { ID = "PLAY_PAIN"; Sprite = "PLAY"; Frame = 6; Tics = 4; Next state = "PLAY_PAIN2"; } State { ID = "PLAY_PAIN2"; Sprite = "PLAY"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "PLAY"; } State { ID = "PLAY_DIE1"; Sprite = "PLAY"; Frame = 7; Tics = 10; Next state = "PLAY_DIE2"; } State { ID = "PLAY_DIE2"; Sprite = "PLAY"; Frame = 8; Tics = 10; Action = "A_PlayerScream"; Next state = "PLAY_DIE3"; } State { ID = "PLAY_DIE3"; Sprite = "PLAY"; Frame = 9; Tics = 10; Action = "A_Fall"; Next state = "PLAY_DIE4"; } State { ID = "PLAY_DIE4"; Sprite = "PLAY"; Frame = 10; Tics = 10; Next state = "PLAY_DIE5"; } State { ID = "PLAY_DIE5"; Sprite = "PLAY"; Frame = 11; Tics = 10; Next state = "PLAY_DIE6"; } State { ID = "PLAY_DIE6"; Sprite = "PLAY"; Frame = 12; Tics = 10; Next state = "PLAY_DIE7"; } State { ID = "PLAY_DIE7"; Sprite = "PLAY"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "PLAY_XDIE1"; Sprite = "PLAY"; Frame = 14; Tics = 5; Next state = "PLAY_XDIE2"; } State { ID = "PLAY_XDIE2"; Sprite = "PLAY"; Frame = 15; Tics = 5; Action = "A_XScream"; Next state = "PLAY_XDIE3"; } State { ID = "PLAY_XDIE3"; Sprite = "PLAY"; Frame = 16; Tics = 5; Action = "A_Fall"; Next state = "PLAY_XDIE4"; } State { ID = "PLAY_XDIE4"; Sprite = "PLAY"; Frame = 17; Tics = 5; Next state = "PLAY_XDIE5"; } State { ID = "PLAY_XDIE5"; Sprite = "PLAY"; Frame = 18; Tics = 5; Next state = "PLAY_XDIE6"; } State { ID = "PLAY_XDIE6"; Sprite = "PLAY"; Frame = 19; Tics = 5; Next state = "PLAY_XDIE7"; } State { ID = "PLAY_XDIE7"; Sprite = "PLAY"; Frame = 20; Tics = 5; Next state = "PLAY_XDIE8"; } State { ID = "PLAY_XDIE8"; Sprite = "PLAY"; Frame = 21; Tics = 5; Next state = "PLAY_XDIE9"; } State { ID = "PLAY_XDIE9"; Sprite = "PLAY"; Frame = 22; Tics = -1; Next state = "NULL"; } State { ID = "POSS_STND"; Sprite = "POSS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "POSS_STND2"; } State { ID = "POSS_STND2"; Sprite = "POSS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "POSS_STND"; } State { ID = "POSS_RUN1"; Sprite = "POSS"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN2"; } State { ID = "POSS_RUN2"; Sprite = "POSS"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN3"; } State { ID = "POSS_RUN3"; Sprite = "POSS"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN4"; } State { ID = "POSS_RUN4"; Sprite = "POSS"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN5"; } State { ID = "POSS_RUN5"; Sprite = "POSS"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN6"; } State { ID = "POSS_RUN6"; Sprite = "POSS"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN7"; } State { ID = "POSS_RUN7"; Sprite = "POSS"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN8"; } State { ID = "POSS_RUN8"; Sprite = "POSS"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "POSS_RUN1"; } State { ID = "POSS_ATK1"; Sprite = "POSS"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "POSS_ATK2"; } State { ID = "POSS_ATK2"; Sprite = "POSS"; Frame = 5; Flags = fullbright; Tics = 8; Action = "A_PosAttack"; Next state = "POSS_ATK3"; } State { ID = "POSS_ATK3"; Sprite = "POSS"; Frame = 4; Tics = 8; Next state = "POSS_RUN1"; } State { ID = "POSS_PAIN"; Sprite = "POSS"; Frame = 6; Tics = 3; Next state = "POSS_PAIN2"; } State { ID = "POSS_PAIN2"; Sprite = "POSS"; Frame = 6; Tics = 3; Action = "A_Pain"; Next state = "POSS_RUN1"; } State { ID = "POSS_DIE1"; Sprite = "POSS"; Frame = 7; Tics = 5; Next state = "POSS_DIE2"; } State { ID = "POSS_DIE2"; Sprite = "POSS"; Frame = 8; Tics = 5; Action = "A_Scream"; Next state = "POSS_DIE3"; } State { ID = "POSS_DIE3"; Sprite = "POSS"; Frame = 9; Tics = 5; Action = "A_Fall"; Next state = "POSS_DIE4"; } State { ID = "POSS_DIE4"; Sprite = "POSS"; Frame = 10; Tics = 5; Next state = "POSS_DIE5"; } State { ID = "POSS_DIE5"; Sprite = "POSS"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "POSS_XDIE1"; Sprite = "POSS"; Frame = 12; Tics = 5; Next state = "POSS_XDIE2"; } State { ID = "POSS_XDIE2"; Sprite = "POSS"; Frame = 13; Tics = 5; Action = "A_XScream"; Next state = "POSS_XDIE3"; } State { ID = "POSS_XDIE3"; Sprite = "POSS"; Frame = 14; Tics = 5; Action = "A_Fall"; Next state = "POSS_XDIE4"; } State { ID = "POSS_XDIE4"; Sprite = "POSS"; Frame = 15; Tics = 5; Next state = "POSS_XDIE5"; } State { ID = "POSS_XDIE5"; Sprite = "POSS"; Frame = 16; Tics = 5; Next state = "POSS_XDIE6"; } State { ID = "POSS_XDIE6"; Sprite = "POSS"; Frame = 17; Tics = 5; Next state = "POSS_XDIE7"; } State { ID = "POSS_XDIE7"; Sprite = "POSS"; Frame = 18; Tics = 5; Next state = "POSS_XDIE8"; } State { ID = "POSS_XDIE8"; Sprite = "POSS"; Frame = 19; Tics = 5; Next state = "POSS_XDIE9"; } State { ID = "POSS_XDIE9"; Sprite = "POSS"; Frame = 20; Tics = -1; Next state = "NULL"; } State { ID = "POSS_RAISE1"; Sprite = "POSS"; Frame = 10; Tics = 5; Next state = "POSS_RAISE2"; } State { ID = "POSS_RAISE2"; Sprite = "POSS"; Frame = 9; Tics = 5; Next state = "POSS_RAISE3"; } State { ID = "POSS_RAISE3"; Sprite = "POSS"; Frame = 8; Tics = 5; Next state = "POSS_RAISE4"; } State { ID = "POSS_RAISE4"; Sprite = "POSS"; Frame = 7; Tics = 5; Next state = "POSS_RUN1"; } State { ID = "SPOS_STND"; Sprite = "SPOS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SPOS_STND2"; } State { ID = "SPOS_STND2"; Sprite = "SPOS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SPOS_STND"; } State { ID = "SPOS_RUN1"; Sprite = "SPOS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN2"; } State { ID = "SPOS_RUN2"; Sprite = "SPOS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN3"; } State { ID = "SPOS_RUN3"; Sprite = "SPOS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN4"; } State { ID = "SPOS_RUN4"; Sprite = "SPOS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN5"; } State { ID = "SPOS_RUN5"; Sprite = "SPOS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN6"; } State { ID = "SPOS_RUN6"; Sprite = "SPOS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN7"; } State { ID = "SPOS_RUN7"; Sprite = "SPOS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN8"; } State { ID = "SPOS_RUN8"; Sprite = "SPOS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SPOS_RUN1"; } State { ID = "SPOS_ATK1"; Sprite = "SPOS"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "SPOS_ATK2"; } State { ID = "SPOS_ATK2"; Sprite = "SPOS"; Frame = 5; Flags = fullbright; Tics = 10; Action = "A_SPosAttack"; Next state = "SPOS_ATK3"; } State { ID = "SPOS_ATK3"; Sprite = "SPOS"; Frame = 4; Tics = 10; Next state = "SPOS_RUN1"; } State { ID = "SPOS_PAIN"; Sprite = "SPOS"; Frame = 6; Tics = 3; Next state = "SPOS_PAIN2"; } State { ID = "SPOS_PAIN2"; Sprite = "SPOS"; Frame = 6; Tics = 3; Action = "A_Pain"; Next state = "SPOS_RUN1"; } State { ID = "SPOS_DIE1"; Sprite = "SPOS"; Frame = 7; Tics = 5; Next state = "SPOS_DIE2"; } State { ID = "SPOS_DIE2"; Sprite = "SPOS"; Frame = 8; Tics = 5; Action = "A_Scream"; Next state = "SPOS_DIE3"; } State { ID = "SPOS_DIE3"; Sprite = "SPOS"; Frame = 9; Tics = 5; Action = "A_Fall"; Next state = "SPOS_DIE4"; } State { ID = "SPOS_DIE4"; Sprite = "SPOS"; Frame = 10; Tics = 5; Next state = "SPOS_DIE5"; } State { ID = "SPOS_DIE5"; Sprite = "SPOS"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "SPOS_XDIE1"; Sprite = "SPOS"; Frame = 12; Tics = 5; Next state = "SPOS_XDIE2"; } State { ID = "SPOS_XDIE2"; Sprite = "SPOS"; Frame = 13; Tics = 5; Action = "A_XScream"; Next state = "SPOS_XDIE3"; } State { ID = "SPOS_XDIE3"; Sprite = "SPOS"; Frame = 14; Tics = 5; Action = "A_Fall"; Next state = "SPOS_XDIE4"; } State { ID = "SPOS_XDIE4"; Sprite = "SPOS"; Frame = 15; Tics = 5; Next state = "SPOS_XDIE5"; } State { ID = "SPOS_XDIE5"; Sprite = "SPOS"; Frame = 16; Tics = 5; Next state = "SPOS_XDIE6"; } State { ID = "SPOS_XDIE6"; Sprite = "SPOS"; Frame = 17; Tics = 5; Next state = "SPOS_XDIE7"; } State { ID = "SPOS_XDIE7"; Sprite = "SPOS"; Frame = 18; Tics = 5; Next state = "SPOS_XDIE8"; } State { ID = "SPOS_XDIE8"; Sprite = "SPOS"; Frame = 19; Tics = 5; Next state = "SPOS_XDIE9"; } State { ID = "SPOS_XDIE9"; Sprite = "SPOS"; Frame = 20; Tics = -1; Next state = "NULL"; } State { ID = "SPOS_RAISE1"; Sprite = "SPOS"; Frame = 11; Tics = 5; Next state = "SPOS_RAISE2"; } State { ID = "SPOS_RAISE2"; Sprite = "SPOS"; Frame = 10; Tics = 5; Next state = "SPOS_RAISE3"; } State { ID = "SPOS_RAISE3"; Sprite = "SPOS"; Frame = 9; Tics = 5; Next state = "SPOS_RAISE4"; } State { ID = "SPOS_RAISE4"; Sprite = "SPOS"; Frame = 8; Tics = 5; Next state = "SPOS_RAISE5"; } State { ID = "SPOS_RAISE5"; Sprite = "SPOS"; Frame = 7; Tics = 5; Next state = "SPOS_RUN1"; } State { ID = "VILE_STND"; Sprite = "VILE"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "VILE_STND2"; } State { ID = "VILE_STND2"; Sprite = "VILE"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "VILE_STND"; } State { ID = "VILE_RUN1"; Sprite = "VILE"; Frame = 0; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN2"; } State { ID = "VILE_RUN2"; Sprite = "VILE"; Frame = 0; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN3"; } State { ID = "VILE_RUN3"; Sprite = "VILE"; Frame = 1; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN4"; } State { ID = "VILE_RUN4"; Sprite = "VILE"; Frame = 1; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN5"; } State { ID = "VILE_RUN5"; Sprite = "VILE"; Frame = 2; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN6"; } State { ID = "VILE_RUN6"; Sprite = "VILE"; Frame = 2; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN7"; } State { ID = "VILE_RUN7"; Sprite = "VILE"; Frame = 3; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN8"; } State { ID = "VILE_RUN8"; Sprite = "VILE"; Frame = 3; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN9"; } State { ID = "VILE_RUN9"; Sprite = "VILE"; Frame = 4; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN10"; } State { ID = "VILE_RUN10"; Sprite = "VILE"; Frame = 4; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN11"; } State { ID = "VILE_RUN11"; Sprite = "VILE"; Frame = 5; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN12"; } State { ID = "VILE_RUN12"; Sprite = "VILE"; Frame = 5; Tics = 2; Action = "A_VileChase"; Next state = "VILE_RUN1"; } State { ID = "VILE_ATK1"; Sprite = "VILE"; Frame = 6; Flags = fullbright; Tics = 0; Action = "A_VileStart"; Next state = "VILE_ATK2"; } State { ID = "VILE_ATK2"; Sprite = "VILE"; Frame = 6; Flags = fullbright; Tics = 10; Action = "A_FaceTarget"; Next state = "VILE_ATK3"; } State { ID = "VILE_ATK3"; Sprite = "VILE"; Frame = 7; Flags = fullbright; Tics = 8; Action = "A_VileTarget"; Next state = "VILE_ATK4"; } State { ID = "VILE_ATK4"; Sprite = "VILE"; Frame = 8; Flags = fullbright; Tics = 8; Action = "A_FaceTarget"; Next state = "VILE_ATK5"; } State { ID = "VILE_ATK5"; Sprite = "VILE"; Frame = 9; Flags = fullbright; Tics = 8; Action = "A_FaceTarget"; Next state = "VILE_ATK6"; } State { ID = "VILE_ATK6"; Sprite = "VILE"; Frame = 10; Flags = fullbright; Tics = 8; Action = "A_FaceTarget"; Next state = "VILE_ATK7"; } State { ID = "VILE_ATK7"; Sprite = "VILE"; Frame = 11; Flags = fullbright; Tics = 8; Action = "A_FaceTarget"; Next state = "VILE_ATK8"; } State { ID = "VILE_ATK8"; Sprite = "VILE"; Frame = 12; Flags = fullbright; Tics = 8; Action = "A_FaceTarget"; Next state = "VILE_ATK9"; } State { ID = "VILE_ATK9"; Sprite = "VILE"; Frame = 13; Flags = fullbright; Tics = 8; Action = "A_FaceTarget"; Next state = "VILE_ATK10"; } State { ID = "VILE_ATK10"; Sprite = "VILE"; Frame = 14; Flags = fullbright; Tics = 8; Action = "A_VileAttack"; Next state = "VILE_ATK11"; } State { ID = "VILE_ATK11"; Sprite = "VILE"; Frame = 15; Flags = fullbright; Tics = 20; Next state = "VILE_RUN1"; } State { ID = "VILE_HEAL1"; Sprite = "VILE"; Frame = 32794; Tics = 10; Next state = "VILE_HEAL2"; } State { ID = "VILE_HEAL2"; Sprite = "VILE"; Frame = 32795; Tics = 10; Next state = "VILE_HEAL3"; } State { ID = "VILE_HEAL3"; Sprite = "VILE"; Frame = 32796; Tics = 10; Next state = "VILE_RUN1"; } State { ID = "VILE_PAIN"; Sprite = "VILE"; Frame = 16; Tics = 5; Next state = "VILE_PAIN2"; } State { ID = "VILE_PAIN2"; Sprite = "VILE"; Frame = 16; Tics = 5; Action = "A_Pain"; Next state = "VILE_RUN1"; } State { ID = "VILE_DIE1"; Sprite = "VILE"; Frame = 16; Tics = 7; Next state = "VILE_DIE2"; } State { ID = "VILE_DIE2"; Sprite = "VILE"; Frame = 17; Tics = 7; Action = "A_Scream"; Next state = "VILE_DIE3"; } State { ID = "VILE_DIE3"; Sprite = "VILE"; Frame = 18; Tics = 7; Action = "A_Fall"; Next state = "VILE_DIE4"; } State { ID = "VILE_DIE4"; Sprite = "VILE"; Frame = 19; Tics = 7; Next state = "VILE_DIE5"; } State { ID = "VILE_DIE5"; Sprite = "VILE"; Frame = 20; Tics = 7; Next state = "VILE_DIE6"; } State { ID = "VILE_DIE6"; Sprite = "VILE"; Frame = 21; Tics = 7; Next state = "VILE_DIE7"; } State { ID = "VILE_DIE7"; Sprite = "VILE"; Frame = 22; Tics = 7; Next state = "VILE_DIE8"; } State { ID = "VILE_DIE8"; Sprite = "VILE"; Frame = 23; Tics = 5; Next state = "VILE_DIE9"; } State { ID = "VILE_DIE9"; Sprite = "VILE"; Frame = 24; Tics = 5; Next state = "VILE_DIE10"; } State { ID = "VILE_DIE10"; Sprite = "VILE"; Frame = 25; Tics = -1; Next state = "NULL"; } State { ID = "FIRE1"; Sprite = "FIRE"; Frame = 0; Flags = fullbright; Tics = 2; Action = "A_StartFire"; Next state = "FIRE2"; } State { ID = "FIRE2"; Sprite = "FIRE"; Frame = 1; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE3"; } State { ID = "FIRE3"; Sprite = "FIRE"; Frame = 0; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE4"; } State { ID = "FIRE4"; Sprite = "FIRE"; Frame = 1; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE5"; } State { ID = "FIRE5"; Sprite = "FIRE"; Frame = 2; Flags = fullbright; Tics = 2; Action = "A_FireCrackle"; Next state = "FIRE6"; } State { ID = "FIRE6"; Sprite = "FIRE"; Frame = 1; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE7"; } State { ID = "FIRE7"; Sprite = "FIRE"; Frame = 2; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE8"; } State { ID = "FIRE8"; Sprite = "FIRE"; Frame = 1; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE9"; } State { ID = "FIRE9"; Sprite = "FIRE"; Frame = 2; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE10"; } State { ID = "FIRE10"; Sprite = "FIRE"; Frame = 3; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE11"; } State { ID = "FIRE11"; Sprite = "FIRE"; Frame = 2; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE12"; } State { ID = "FIRE12"; Sprite = "FIRE"; Frame = 3; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE13"; } State { ID = "FIRE13"; Sprite = "FIRE"; Frame = 2; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE14"; } State { ID = "FIRE14"; Sprite = "FIRE"; Frame = 3; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE15"; } State { ID = "FIRE15"; Sprite = "FIRE"; Frame = 4; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE16"; } State { ID = "FIRE16"; Sprite = "FIRE"; Frame = 3; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE17"; } State { ID = "FIRE17"; Sprite = "FIRE"; Frame = 4; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE18"; } State { ID = "FIRE18"; Sprite = "FIRE"; Frame = 3; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE19"; } State { ID = "FIRE19"; Sprite = "FIRE"; Frame = 4; Flags = fullbright; Tics = 2; Action = "A_FireCrackle"; Next state = "FIRE20"; } State { ID = "FIRE20"; Sprite = "FIRE"; Frame = 5; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE21"; } State { ID = "FIRE21"; Sprite = "FIRE"; Frame = 4; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE22"; } State { ID = "FIRE22"; Sprite = "FIRE"; Frame = 5; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE23"; } State { ID = "FIRE23"; Sprite = "FIRE"; Frame = 4; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE24"; } State { ID = "FIRE24"; Sprite = "FIRE"; Frame = 5; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE25"; } State { ID = "FIRE25"; Sprite = "FIRE"; Frame = 6; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE26"; } State { ID = "FIRE26"; Sprite = "FIRE"; Frame = 7; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE27"; } State { ID = "FIRE27"; Sprite = "FIRE"; Frame = 6; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE28"; } State { ID = "FIRE28"; Sprite = "FIRE"; Frame = 7; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE29"; } State { ID = "FIRE29"; Sprite = "FIRE"; Frame = 6; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "FIRE30"; } State { ID = "FIRE30"; Sprite = "FIRE"; Frame = 7; Flags = fullbright; Tics = 2; Action = "A_Fire"; Next state = "NULL"; } State { ID = "SMOKE1"; Sprite = "PUFF"; Frame = 1; Tics = 4; Next state = "SMOKE2"; } State { ID = "SMOKE2"; Sprite = "PUFF"; Frame = 2; Tics = 4; Next state = "SMOKE3"; } State { ID = "SMOKE3"; Sprite = "PUFF"; Frame = 1; Tics = 4; Next state = "SMOKE4"; } State { ID = "SMOKE4"; Sprite = "PUFF"; Frame = 2; Tics = 4; Next state = "SMOKE5"; } State { ID = "SMOKE5"; Sprite = "PUFF"; Frame = 3; Tics = 4; Next state = "NULL"; } State { ID = "TRACER"; Sprite = "FATB"; Frame = 0; Flags = fullbright; Tics = 2; Action = "A_Tracer"; Next state = "TRACER2"; } State { ID = "TRACER2"; Sprite = "FATB"; Frame = 1; Flags = fullbright; Tics = 2; Action = "A_Tracer"; Next state = "TRACER"; } State { ID = "TRACEEXP1"; Sprite = "FBXP"; Frame = 0; Flags = fullbright; Tics = 8; Next state = "TRACEEXP2"; } State { ID = "TRACEEXP2"; Sprite = "FBXP"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "TRACEEXP3"; } State { ID = "TRACEEXP3"; Sprite = "FBXP"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "NULL"; } State { ID = "SKEL_STND"; Sprite = "SKEL"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SKEL_STND2"; } State { ID = "SKEL_STND2"; Sprite = "SKEL"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SKEL_STND"; } State { ID = "SKEL_RUN1"; Sprite = "SKEL"; Frame = 0; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN2"; } State { ID = "SKEL_RUN2"; Sprite = "SKEL"; Frame = 0; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN3"; } State { ID = "SKEL_RUN3"; Sprite = "SKEL"; Frame = 1; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN4"; } State { ID = "SKEL_RUN4"; Sprite = "SKEL"; Frame = 1; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN5"; } State { ID = "SKEL_RUN5"; Sprite = "SKEL"; Frame = 2; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN6"; } State { ID = "SKEL_RUN6"; Sprite = "SKEL"; Frame = 2; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN7"; } State { ID = "SKEL_RUN7"; Sprite = "SKEL"; Frame = 3; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN8"; } State { ID = "SKEL_RUN8"; Sprite = "SKEL"; Frame = 3; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN9"; } State { ID = "SKEL_RUN9"; Sprite = "SKEL"; Frame = 4; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN10"; } State { ID = "SKEL_RUN10"; Sprite = "SKEL"; Frame = 4; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN11"; } State { ID = "SKEL_RUN11"; Sprite = "SKEL"; Frame = 5; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN12"; } State { ID = "SKEL_RUN12"; Sprite = "SKEL"; Frame = 5; Tics = 2; Action = "A_Chase"; Next state = "SKEL_RUN1"; } State { ID = "SKEL_FIST1"; Sprite = "SKEL"; Frame = 6; Tics = 0; Action = "A_FaceTarget"; Next state = "SKEL_FIST2"; } State { ID = "SKEL_FIST2"; Sprite = "SKEL"; Frame = 6; Tics = 6; Action = "A_SkelWhoosh"; Next state = "SKEL_FIST3"; } State { ID = "SKEL_FIST3"; Sprite = "SKEL"; Frame = 7; Tics = 6; Action = "A_FaceTarget"; Next state = "SKEL_FIST4"; } State { ID = "SKEL_FIST4"; Sprite = "SKEL"; Frame = 8; Tics = 6; Action = "A_SkelFist"; Next state = "SKEL_RUN1"; } State { ID = "SKEL_MISS1"; Sprite = "SKEL"; Frame = 9; Flags = fullbright; Tics = 0; Action = "A_FaceTarget"; Next state = "SKEL_MISS2"; } State { ID = "SKEL_MISS2"; Sprite = "SKEL"; Frame = 9; Flags = fullbright; Tics = 10; Action = "A_FaceTarget"; Next state = "SKEL_MISS3"; } State { ID = "SKEL_MISS3"; Sprite = "SKEL"; Frame = 10; Tics = 10; Action = "A_SkelMissile"; Next state = "SKEL_MISS4"; } State { ID = "SKEL_MISS4"; Sprite = "SKEL"; Frame = 10; Tics = 10; Action = "A_FaceTarget"; Next state = "SKEL_RUN1"; } State { ID = "SKEL_PAIN"; Sprite = "SKEL"; Frame = 11; Tics = 5; Next state = "SKEL_PAIN2"; } State { ID = "SKEL_PAIN2"; Sprite = "SKEL"; Frame = 11; Tics = 5; Action = "A_Pain"; Next state = "SKEL_RUN1"; } State { ID = "SKEL_DIE1"; Sprite = "SKEL"; Frame = 11; Tics = 7; Next state = "SKEL_DIE2"; } State { ID = "SKEL_DIE2"; Sprite = "SKEL"; Frame = 12; Tics = 7; Next state = "SKEL_DIE3"; } State { ID = "SKEL_DIE3"; Sprite = "SKEL"; Frame = 13; Tics = 7; Action = "A_Scream"; Next state = "SKEL_DIE4"; } State { ID = "SKEL_DIE4"; Sprite = "SKEL"; Frame = 14; Tics = 7; Action = "A_Fall"; Next state = "SKEL_DIE5"; } State { ID = "SKEL_DIE5"; Sprite = "SKEL"; Frame = 15; Tics = 7; Next state = "SKEL_DIE6"; } State { ID = "SKEL_DIE6"; Sprite = "SKEL"; Frame = 16; Tics = -1; Next state = "NULL"; } State { ID = "SKEL_RAISE1"; Sprite = "SKEL"; Frame = 16; Tics = 5; Next state = "SKEL_RAISE2"; } State { ID = "SKEL_RAISE2"; Sprite = "SKEL"; Frame = 15; Tics = 5; Next state = "SKEL_RAISE3"; } State { ID = "SKEL_RAISE3"; Sprite = "SKEL"; Frame = 14; Tics = 5; Next state = "SKEL_RAISE4"; } State { ID = "SKEL_RAISE4"; Sprite = "SKEL"; Frame = 13; Tics = 5; Next state = "SKEL_RAISE5"; } State { ID = "SKEL_RAISE5"; Sprite = "SKEL"; Frame = 12; Tics = 5; Next state = "SKEL_RAISE6"; } State { ID = "SKEL_RAISE6"; Sprite = "SKEL"; Frame = 11; Tics = 5; Next state = "SKEL_RUN1"; } State { ID = "FATSHOT1"; Sprite = "MANF"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "FATSHOT2"; } State { ID = "FATSHOT2"; Sprite = "MANF"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "FATSHOT1"; } State { ID = "FATSHOTX1"; Sprite = "MISL"; Frame = 1; Flags = fullbright; Tics = 8; Next state = "FATSHOTX2"; } State { ID = "FATSHOTX2"; Sprite = "MISL"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "FATSHOTX3"; } State { ID = "FATSHOTX3"; Sprite = "MISL"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "NULL"; } State { ID = "FATT_STND"; Sprite = "FATT"; Frame = 0; Tics = 15; Action = "A_Look"; Next state = "FATT_STND2"; } State { ID = "FATT_STND2"; Sprite = "FATT"; Frame = 1; Tics = 15; Action = "A_Look"; Next state = "FATT_STND"; } State { ID = "FATT_RUN1"; Sprite = "FATT"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN2"; } State { ID = "FATT_RUN2"; Sprite = "FATT"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN3"; } State { ID = "FATT_RUN3"; Sprite = "FATT"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN4"; } State { ID = "FATT_RUN4"; Sprite = "FATT"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN5"; } State { ID = "FATT_RUN5"; Sprite = "FATT"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN6"; } State { ID = "FATT_RUN6"; Sprite = "FATT"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN7"; } State { ID = "FATT_RUN7"; Sprite = "FATT"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN8"; } State { ID = "FATT_RUN8"; Sprite = "FATT"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN9"; } State { ID = "FATT_RUN9"; Sprite = "FATT"; Frame = 4; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN10"; } State { ID = "FATT_RUN10"; Sprite = "FATT"; Frame = 4; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN11"; } State { ID = "FATT_RUN11"; Sprite = "FATT"; Frame = 5; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN12"; } State { ID = "FATT_RUN12"; Sprite = "FATT"; Frame = 5; Tics = 4; Action = "A_Chase"; Next state = "FATT_RUN1"; } State { ID = "FATT_ATK1"; Sprite = "FATT"; Frame = 6; Tics = 20; Action = "A_FatRaise"; Next state = "FATT_ATK2"; } State { ID = "FATT_ATK2"; Sprite = "FATT"; Frame = 7; Flags = fullbright; Tics = 10; Action = "A_FatAttack1"; Next state = "FATT_ATK3"; } State { ID = "FATT_ATK3"; Sprite = "FATT"; Frame = 8; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_ATK4"; } State { ID = "FATT_ATK4"; Sprite = "FATT"; Frame = 6; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_ATK5"; } State { ID = "FATT_ATK5"; Sprite = "FATT"; Frame = 7; Flags = fullbright; Tics = 10; Action = "A_FatAttack2"; Next state = "FATT_ATK6"; } State { ID = "FATT_ATK6"; Sprite = "FATT"; Frame = 8; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_ATK7"; } State { ID = "FATT_ATK7"; Sprite = "FATT"; Frame = 6; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_ATK8"; } State { ID = "FATT_ATK8"; Sprite = "FATT"; Frame = 7; Flags = fullbright; Tics = 10; Action = "A_FatAttack3"; Next state = "FATT_ATK9"; } State { ID = "FATT_ATK9"; Sprite = "FATT"; Frame = 8; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_ATK10"; } State { ID = "FATT_ATK10"; Sprite = "FATT"; Frame = 6; Tics = 5; Action = "A_FaceTarget"; Next state = "FATT_RUN1"; } State { ID = "FATT_PAIN"; Sprite = "FATT"; Frame = 9; Tics = 3; Next state = "FATT_PAIN2"; } State { ID = "FATT_PAIN2"; Sprite = "FATT"; Frame = 9; Tics = 3; Action = "A_Pain"; Next state = "FATT_RUN1"; } State { ID = "FATT_DIE1"; Sprite = "FATT"; Frame = 10; Tics = 6; Next state = "FATT_DIE2"; } State { ID = "FATT_DIE2"; Sprite = "FATT"; Frame = 11; Tics = 6; Action = "A_Scream"; Next state = "FATT_DIE3"; } State { ID = "FATT_DIE3"; Sprite = "FATT"; Frame = 12; Tics = 6; Action = "A_Fall"; Next state = "FATT_DIE4"; } State { ID = "FATT_DIE4"; Sprite = "FATT"; Frame = 13; Tics = 6; Next state = "FATT_DIE5"; } State { ID = "FATT_DIE5"; Sprite = "FATT"; Frame = 14; Tics = 6; Next state = "FATT_DIE6"; } State { ID = "FATT_DIE6"; Sprite = "FATT"; Frame = 15; Tics = 6; Next state = "FATT_DIE7"; } State { ID = "FATT_DIE7"; Sprite = "FATT"; Frame = 16; Tics = 6; Next state = "FATT_DIE8"; } State { ID = "FATT_DIE8"; Sprite = "FATT"; Frame = 17; Tics = 6; Next state = "FATT_DIE9"; } State { ID = "FATT_DIE9"; Sprite = "FATT"; Frame = 18; Tics = 6; Next state = "FATT_DIE10"; } State { ID = "FATT_DIE10"; Sprite = "FATT"; Frame = 19; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "FATT_RAISE1"; Sprite = "FATT"; Frame = 17; Tics = 5; Next state = "FATT_RAISE2"; } State { ID = "FATT_RAISE2"; Sprite = "FATT"; Frame = 16; Tics = 5; Next state = "FATT_RAISE3"; } State { ID = "FATT_RAISE3"; Sprite = "FATT"; Frame = 15; Tics = 5; Next state = "FATT_RAISE4"; } State { ID = "FATT_RAISE4"; Sprite = "FATT"; Frame = 14; Tics = 5; Next state = "FATT_RAISE5"; } State { ID = "FATT_RAISE5"; Sprite = "FATT"; Frame = 13; Tics = 5; Next state = "FATT_RAISE6"; } State { ID = "FATT_RAISE6"; Sprite = "FATT"; Frame = 12; Tics = 5; Next state = "FATT_RAISE7"; } State { ID = "FATT_RAISE7"; Sprite = "FATT"; Frame = 11; Tics = 5; Next state = "FATT_RAISE8"; } State { ID = "FATT_RAISE8"; Sprite = "FATT"; Frame = 10; Tics = 5; Next state = "FATT_RUN1"; } State { ID = "CPOS_STND"; Sprite = "CPOS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "CPOS_STND2"; } State { ID = "CPOS_STND2"; Sprite = "CPOS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "CPOS_STND"; } State { ID = "CPOS_RUN1"; Sprite = "CPOS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN2"; } State { ID = "CPOS_RUN2"; Sprite = "CPOS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN3"; } State { ID = "CPOS_RUN3"; Sprite = "CPOS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN4"; } State { ID = "CPOS_RUN4"; Sprite = "CPOS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN5"; } State { ID = "CPOS_RUN5"; Sprite = "CPOS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN6"; } State { ID = "CPOS_RUN6"; Sprite = "CPOS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN7"; } State { ID = "CPOS_RUN7"; Sprite = "CPOS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN8"; } State { ID = "CPOS_RUN8"; Sprite = "CPOS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "CPOS_RUN1"; } State { ID = "CPOS_ATK1"; Sprite = "CPOS"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "CPOS_ATK2"; } State { ID = "CPOS_ATK2"; Sprite = "CPOS"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_CPosAttack"; Next state = "CPOS_ATK3"; } State { ID = "CPOS_ATK3"; Sprite = "CPOS"; Frame = 4; Flags = fullbright; Tics = 4; Action = "A_CPosAttack"; Next state = "CPOS_ATK4"; } State { ID = "CPOS_ATK4"; Sprite = "CPOS"; Frame = 5; Tics = 1; Action = "A_CPosRefire"; Next state = "CPOS_ATK2"; } State { ID = "CPOS_PAIN"; Sprite = "CPOS"; Frame = 6; Tics = 3; Next state = "CPOS_PAIN2"; } State { ID = "CPOS_PAIN2"; Sprite = "CPOS"; Frame = 6; Tics = 3; Action = "A_Pain"; Next state = "CPOS_RUN1"; } State { ID = "CPOS_DIE1"; Sprite = "CPOS"; Frame = 7; Tics = 5; Next state = "CPOS_DIE2"; } State { ID = "CPOS_DIE2"; Sprite = "CPOS"; Frame = 8; Tics = 5; Action = "A_Scream"; Next state = "CPOS_DIE3"; } State { ID = "CPOS_DIE3"; Sprite = "CPOS"; Frame = 9; Tics = 5; Action = "A_Fall"; Next state = "CPOS_DIE4"; } State { ID = "CPOS_DIE4"; Sprite = "CPOS"; Frame = 10; Tics = 5; Next state = "CPOS_DIE5"; } State { ID = "CPOS_DIE5"; Sprite = "CPOS"; Frame = 11; Tics = 5; Next state = "CPOS_DIE6"; } State { ID = "CPOS_DIE6"; Sprite = "CPOS"; Frame = 12; Tics = 5; Next state = "CPOS_DIE7"; } State { ID = "CPOS_DIE7"; Sprite = "CPOS"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "CPOS_XDIE1"; Sprite = "CPOS"; Frame = 14; Tics = 5; Next state = "CPOS_XDIE2"; } State { ID = "CPOS_XDIE2"; Sprite = "CPOS"; Frame = 15; Tics = 5; Action = "A_XScream"; Next state = "CPOS_XDIE3"; } State { ID = "CPOS_XDIE3"; Sprite = "CPOS"; Frame = 16; Tics = 5; Action = "A_Fall"; Next state = "CPOS_XDIE4"; } State { ID = "CPOS_XDIE4"; Sprite = "CPOS"; Frame = 17; Tics = 5; Next state = "CPOS_XDIE5"; } State { ID = "CPOS_XDIE5"; Sprite = "CPOS"; Frame = 18; Tics = 5; Next state = "CPOS_XDIE6"; } State { ID = "CPOS_XDIE6"; Sprite = "CPOS"; Frame = 19; Tics = -1; Next state = "NULL"; } State { ID = "CPOS_RAISE1"; Sprite = "CPOS"; Frame = 13; Tics = 5; Next state = "CPOS_RAISE2"; } State { ID = "CPOS_RAISE2"; Sprite = "CPOS"; Frame = 12; Tics = 5; Next state = "CPOS_RAISE3"; } State { ID = "CPOS_RAISE3"; Sprite = "CPOS"; Frame = 11; Tics = 5; Next state = "CPOS_RAISE4"; } State { ID = "CPOS_RAISE4"; Sprite = "CPOS"; Frame = 10; Tics = 5; Next state = "CPOS_RAISE5"; } State { ID = "CPOS_RAISE5"; Sprite = "CPOS"; Frame = 9; Tics = 5; Next state = "CPOS_RAISE6"; } State { ID = "CPOS_RAISE6"; Sprite = "CPOS"; Frame = 8; Tics = 5; Next state = "CPOS_RAISE7"; } State { ID = "CPOS_RAISE7"; Sprite = "CPOS"; Frame = 7; Tics = 5; Next state = "CPOS_RUN1"; } State { ID = "TROO_STND"; Sprite = "TROO"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "TROO_STND2"; } State { ID = "TROO_STND2"; Sprite = "TROO"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "TROO_STND"; } State { ID = "TROO_RUN1"; Sprite = "TROO"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN2"; } State { ID = "TROO_RUN2"; Sprite = "TROO"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN3"; } State { ID = "TROO_RUN3"; Sprite = "TROO"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN4"; } State { ID = "TROO_RUN4"; Sprite = "TROO"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN5"; } State { ID = "TROO_RUN5"; Sprite = "TROO"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN6"; } State { ID = "TROO_RUN6"; Sprite = "TROO"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN7"; } State { ID = "TROO_RUN7"; Sprite = "TROO"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN8"; } State { ID = "TROO_RUN8"; Sprite = "TROO"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "TROO_RUN1"; } State { ID = "TROO_ATK1"; Sprite = "TROO"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "TROO_ATK2"; } State { ID = "TROO_ATK2"; Sprite = "TROO"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "TROO_ATK3"; } State { ID = "TROO_ATK3"; Sprite = "TROO"; Frame = 6; Tics = 6; Action = "A_TroopAttack"; Next state = "TROO_RUN1"; } State { ID = "TROO_PAIN"; Sprite = "TROO"; Frame = 7; Tics = 2; Next state = "TROO_PAIN2"; } State { ID = "TROO_PAIN2"; Sprite = "TROO"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "TROO_RUN1"; } State { ID = "TROO_DIE1"; Sprite = "TROO"; Frame = 8; Tics = 8; Next state = "TROO_DIE2"; } State { ID = "TROO_DIE2"; Sprite = "TROO"; Frame = 9; Tics = 8; Action = "A_Scream"; Next state = "TROO_DIE3"; } State { ID = "TROO_DIE3"; Sprite = "TROO"; Frame = 10; Tics = 6; Next state = "TROO_DIE4"; } State { ID = "TROO_DIE4"; Sprite = "TROO"; Frame = 11; Tics = 6; Action = "A_Fall"; Next state = "TROO_DIE5"; } State { ID = "TROO_DIE5"; Sprite = "TROO"; Frame = 12; Tics = -1; Next state = "NULL"; } State { ID = "TROO_XDIE1"; Sprite = "TROO"; Frame = 13; Tics = 5; Next state = "TROO_XDIE2"; } State { ID = "TROO_XDIE2"; Sprite = "TROO"; Frame = 14; Tics = 5; Action = "A_XScream"; Next state = "TROO_XDIE3"; } State { ID = "TROO_XDIE3"; Sprite = "TROO"; Frame = 15; Tics = 5; Next state = "TROO_XDIE4"; } State { ID = "TROO_XDIE4"; Sprite = "TROO"; Frame = 16; Tics = 5; Action = "A_Fall"; Next state = "TROO_XDIE5"; } State { ID = "TROO_XDIE5"; Sprite = "TROO"; Frame = 17; Tics = 5; Next state = "TROO_XDIE6"; } State { ID = "TROO_XDIE6"; Sprite = "TROO"; Frame = 18; Tics = 5; Next state = "TROO_XDIE7"; } State { ID = "TROO_XDIE7"; Sprite = "TROO"; Frame = 19; Tics = 5; Next state = "TROO_XDIE8"; } State { ID = "TROO_XDIE8"; Sprite = "TROO"; Frame = 20; Tics = -1; Next state = "NULL"; } State { ID = "TROO_RAISE1"; Sprite = "TROO"; Frame = 12; Tics = 8; Next state = "TROO_RAISE2"; } State { ID = "TROO_RAISE2"; Sprite = "TROO"; Frame = 11; Tics = 8; Next state = "TROO_RAISE3"; } State { ID = "TROO_RAISE3"; Sprite = "TROO"; Frame = 10; Tics = 6; Next state = "TROO_RAISE4"; } State { ID = "TROO_RAISE4"; Sprite = "TROO"; Frame = 9; Tics = 6; Next state = "TROO_RAISE5"; } State { ID = "TROO_RAISE5"; Sprite = "TROO"; Frame = 8; Tics = 6; Next state = "TROO_RUN1"; } State { ID = "SARG_STND"; Sprite = "SARG"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SARG_STND2"; } State { ID = "SARG_STND2"; Sprite = "SARG"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SARG_STND"; } State { ID = "SARG_RUN1"; Sprite = "SARG"; Frame = 0; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN2"; } State { ID = "SARG_RUN2"; Sprite = "SARG"; Frame = 0; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN3"; } State { ID = "SARG_RUN3"; Sprite = "SARG"; Frame = 1; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN4"; } State { ID = "SARG_RUN4"; Sprite = "SARG"; Frame = 1; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN5"; } State { ID = "SARG_RUN5"; Sprite = "SARG"; Frame = 2; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN6"; } State { ID = "SARG_RUN6"; Sprite = "SARG"; Frame = 2; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN7"; } State { ID = "SARG_RUN7"; Sprite = "SARG"; Frame = 3; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN8"; } State { ID = "SARG_RUN8"; Sprite = "SARG"; Frame = 3; Tics = 2; Action = "A_Chase"; Next state = "SARG_RUN1"; } State { ID = "SARG_ATK1"; Sprite = "SARG"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "SARG_ATK2"; } State { ID = "SARG_ATK2"; Sprite = "SARG"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "SARG_ATK3"; } State { ID = "SARG_ATK3"; Sprite = "SARG"; Frame = 6; Tics = 8; Action = "A_SargAttack"; Next state = "SARG_RUN1"; } State { ID = "SARG_PAIN"; Sprite = "SARG"; Frame = 7; Tics = 2; Next state = "SARG_PAIN2"; } State { ID = "SARG_PAIN2"; Sprite = "SARG"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "SARG_RUN1"; } State { ID = "SARG_DIE1"; Sprite = "SARG"; Frame = 8; Tics = 8; Next state = "SARG_DIE2"; } State { ID = "SARG_DIE2"; Sprite = "SARG"; Frame = 9; Tics = 8; Action = "A_Scream"; Next state = "SARG_DIE3"; } State { ID = "SARG_DIE3"; Sprite = "SARG"; Frame = 10; Tics = 4; Next state = "SARG_DIE4"; } State { ID = "SARG_DIE4"; Sprite = "SARG"; Frame = 11; Tics = 4; Action = "A_Fall"; Next state = "SARG_DIE5"; } State { ID = "SARG_DIE5"; Sprite = "SARG"; Frame = 12; Tics = 4; Next state = "SARG_DIE6"; } State { ID = "SARG_DIE6"; Sprite = "SARG"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "SARG_RAISE1"; Sprite = "SARG"; Frame = 13; Tics = 5; Next state = "SARG_RAISE2"; } State { ID = "SARG_RAISE2"; Sprite = "SARG"; Frame = 12; Tics = 5; Next state = "SARG_RAISE3"; } State { ID = "SARG_RAISE3"; Sprite = "SARG"; Frame = 11; Tics = 5; Next state = "SARG_RAISE4"; } State { ID = "SARG_RAISE4"; Sprite = "SARG"; Frame = 10; Tics = 5; Next state = "SARG_RAISE5"; } State { ID = "SARG_RAISE5"; Sprite = "SARG"; Frame = 9; Tics = 5; Next state = "SARG_RAISE6"; } State { ID = "SARG_RAISE6"; Sprite = "SARG"; Frame = 8; Tics = 5; Next state = "SARG_RUN1"; } State { ID = "HEAD_STND"; Sprite = "HEAD"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "HEAD_STND"; } State { ID = "HEAD_RUN1"; Sprite = "HEAD"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "HEAD_RUN1"; } State { ID = "HEAD_ATK1"; Sprite = "HEAD"; Frame = 1; Tics = 5; Action = "A_FaceTarget"; Next state = "HEAD_ATK2"; } State { ID = "HEAD_ATK2"; Sprite = "HEAD"; Frame = 2; Tics = 5; Action = "A_FaceTarget"; Next state = "HEAD_ATK3"; } State { ID = "HEAD_ATK3"; Sprite = "HEAD"; Frame = 3; Flags = fullbright; Tics = 5; Action = "A_HeadAttack"; Next state = "HEAD_RUN1"; } State { ID = "HEAD_PAIN"; Sprite = "HEAD"; Frame = 4; Tics = 3; Next state = "HEAD_PAIN2"; } State { ID = "HEAD_PAIN2"; Sprite = "HEAD"; Frame = 4; Tics = 3; Action = "A_Pain"; Next state = "HEAD_PAIN3"; } State { ID = "HEAD_PAIN3"; Sprite = "HEAD"; Frame = 5; Tics = 6; Next state = "HEAD_RUN1"; } State { ID = "HEAD_DIE1"; Sprite = "HEAD"; Frame = 6; Tics = 8; Next state = "HEAD_DIE2"; } State { ID = "HEAD_DIE2"; Sprite = "HEAD"; Frame = 7; Tics = 8; Action = "A_Scream"; Next state = "HEAD_DIE3"; } State { ID = "HEAD_DIE3"; Sprite = "HEAD"; Frame = 8; Tics = 8; Next state = "HEAD_DIE4"; } State { ID = "HEAD_DIE4"; Sprite = "HEAD"; Frame = 9; Tics = 8; Next state = "HEAD_DIE5"; } State { ID = "HEAD_DIE5"; Sprite = "HEAD"; Frame = 10; Tics = 8; Action = "A_Fall"; Next state = "HEAD_DIE6"; } State { ID = "HEAD_DIE6"; Sprite = "HEAD"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "HEAD_RAISE1"; Sprite = "HEAD"; Frame = 11; Tics = 8; Next state = "HEAD_RAISE2"; } State { ID = "HEAD_RAISE2"; Sprite = "HEAD"; Frame = 10; Tics = 8; Next state = "HEAD_RAISE3"; } State { ID = "HEAD_RAISE3"; Sprite = "HEAD"; Frame = 9; Tics = 8; Next state = "HEAD_RAISE4"; } State { ID = "HEAD_RAISE4"; Sprite = "HEAD"; Frame = 8; Tics = 8; Next state = "HEAD_RAISE5"; } State { ID = "HEAD_RAISE5"; Sprite = "HEAD"; Frame = 7; Tics = 8; Next state = "HEAD_RAISE6"; } State { ID = "HEAD_RAISE6"; Sprite = "HEAD"; Frame = 6; Tics = 8; Next state = "HEAD_RUN1"; } State { ID = "BRBALL1"; Sprite = "BAL7"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BRBALL2"; } State { ID = "BRBALL2"; Sprite = "BAL7"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BRBALL1"; } State { ID = "BRBALLX1"; Sprite = "BAL7"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "BRBALLX2"; } State { ID = "BRBALLX2"; Sprite = "BAL7"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "BRBALLX3"; } State { ID = "BRBALLX3"; Sprite = "BAL7"; Frame = 4; Flags = fullbright; Tics = 6; Next state = "NULL"; } State { ID = "BOSS_STND"; Sprite = "BOSS"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BOSS_STND2"; } State { ID = "BOSS_STND2"; Sprite = "BOSS"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "BOSS_STND"; } State { ID = "BOSS_RUN1"; Sprite = "BOSS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN2"; } State { ID = "BOSS_RUN2"; Sprite = "BOSS"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN3"; } State { ID = "BOSS_RUN3"; Sprite = "BOSS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN4"; } State { ID = "BOSS_RUN4"; Sprite = "BOSS"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN5"; } State { ID = "BOSS_RUN5"; Sprite = "BOSS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN6"; } State { ID = "BOSS_RUN6"; Sprite = "BOSS"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN7"; } State { ID = "BOSS_RUN7"; Sprite = "BOSS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN8"; } State { ID = "BOSS_RUN8"; Sprite = "BOSS"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOSS_RUN1"; } State { ID = "BOSS_ATK1"; Sprite = "BOSS"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "BOSS_ATK2"; } State { ID = "BOSS_ATK2"; Sprite = "BOSS"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "BOSS_ATK3"; } State { ID = "BOSS_ATK3"; Sprite = "BOSS"; Frame = 6; Tics = 8; Action = "A_BruisAttack"; Next state = "BOSS_RUN1"; } State { ID = "BOSS_PAIN"; Sprite = "BOSS"; Frame = 7; Tics = 2; Next state = "BOSS_PAIN2"; } State { ID = "BOSS_PAIN2"; Sprite = "BOSS"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "BOSS_RUN1"; } State { ID = "BOSS_DIE1"; Sprite = "BOSS"; Frame = 8; Tics = 8; Next state = "BOSS_DIE2"; } State { ID = "BOSS_DIE2"; Sprite = "BOSS"; Frame = 9; Tics = 8; Action = "A_Scream"; Next state = "BOSS_DIE3"; } State { ID = "BOSS_DIE3"; Sprite = "BOSS"; Frame = 10; Tics = 8; Next state = "BOSS_DIE4"; } State { ID = "BOSS_DIE4"; Sprite = "BOSS"; Frame = 11; Tics = 8; Action = "A_Fall"; Next state = "BOSS_DIE5"; } State { ID = "BOSS_DIE5"; Sprite = "BOSS"; Frame = 12; Tics = 8; Next state = "BOSS_DIE6"; } State { ID = "BOSS_DIE6"; Sprite = "BOSS"; Frame = 13; Tics = 8; Next state = "BOSS_DIE7"; } State { ID = "BOSS_DIE7"; Sprite = "BOSS"; Frame = 14; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "BOSS_RAISE1"; Sprite = "BOSS"; Frame = 14; Tics = 8; Next state = "BOSS_RAISE2"; } State { ID = "BOSS_RAISE2"; Sprite = "BOSS"; Frame = 13; Tics = 8; Next state = "BOSS_RAISE3"; } State { ID = "BOSS_RAISE3"; Sprite = "BOSS"; Frame = 12; Tics = 8; Next state = "BOSS_RAISE4"; } State { ID = "BOSS_RAISE4"; Sprite = "BOSS"; Frame = 11; Tics = 8; Next state = "BOSS_RAISE5"; } State { ID = "BOSS_RAISE5"; Sprite = "BOSS"; Frame = 10; Tics = 8; Next state = "BOSS_RAISE6"; } State { ID = "BOSS_RAISE6"; Sprite = "BOSS"; Frame = 9; Tics = 8; Next state = "BOSS_RAISE7"; } State { ID = "BOSS_RAISE7"; Sprite = "BOSS"; Frame = 8; Tics = 8; Next state = "BOSS_RUN1"; } State { ID = "BOS2_STND"; Sprite = "BOS2"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BOS2_STND2"; } State { ID = "BOS2_STND2"; Sprite = "BOS2"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "BOS2_STND"; } State { ID = "BOS2_RUN1"; Sprite = "BOS2"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN2"; } State { ID = "BOS2_RUN2"; Sprite = "BOS2"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN3"; } State { ID = "BOS2_RUN3"; Sprite = "BOS2"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN4"; } State { ID = "BOS2_RUN4"; Sprite = "BOS2"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN5"; } State { ID = "BOS2_RUN5"; Sprite = "BOS2"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN6"; } State { ID = "BOS2_RUN6"; Sprite = "BOS2"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN7"; } State { ID = "BOS2_RUN7"; Sprite = "BOS2"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN8"; } State { ID = "BOS2_RUN8"; Sprite = "BOS2"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BOS2_RUN1"; } State { ID = "BOS2_ATK1"; Sprite = "BOS2"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "BOS2_ATK2"; } State { ID = "BOS2_ATK2"; Sprite = "BOS2"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "BOS2_ATK3"; } State { ID = "BOS2_ATK3"; Sprite = "BOS2"; Frame = 6; Tics = 8; Action = "A_BruisAttack"; Next state = "BOS2_RUN1"; } State { ID = "BOS2_PAIN"; Sprite = "BOS2"; Frame = 7; Tics = 2; Next state = "BOS2_PAIN2"; } State { ID = "BOS2_PAIN2"; Sprite = "BOS2"; Frame = 7; Tics = 2; Action = "A_Pain"; Next state = "BOS2_RUN1"; } State { ID = "BOS2_DIE1"; Sprite = "BOS2"; Frame = 8; Tics = 8; Next state = "BOS2_DIE2"; } State { ID = "BOS2_DIE2"; Sprite = "BOS2"; Frame = 9; Tics = 8; Action = "A_Scream"; Next state = "BOS2_DIE3"; } State { ID = "BOS2_DIE3"; Sprite = "BOS2"; Frame = 10; Tics = 8; Next state = "BOS2_DIE4"; } State { ID = "BOS2_DIE4"; Sprite = "BOS2"; Frame = 11; Tics = 8; Action = "A_Fall"; Next state = "BOS2_DIE5"; } State { ID = "BOS2_DIE5"; Sprite = "BOS2"; Frame = 12; Tics = 8; Next state = "BOS2_DIE6"; } State { ID = "BOS2_DIE6"; Sprite = "BOS2"; Frame = 13; Tics = 8; Next state = "BOS2_DIE7"; } State { ID = "BOS2_DIE7"; Sprite = "BOS2"; Frame = 14; Tics = -1; Next state = "NULL"; } State { ID = "BOS2_RAISE1"; Sprite = "BOS2"; Frame = 14; Tics = 8; Next state = "BOS2_RAISE2"; } State { ID = "BOS2_RAISE2"; Sprite = "BOS2"; Frame = 13; Tics = 8; Next state = "BOS2_RAISE3"; } State { ID = "BOS2_RAISE3"; Sprite = "BOS2"; Frame = 12; Tics = 8; Next state = "BOS2_RAISE4"; } State { ID = "BOS2_RAISE4"; Sprite = "BOS2"; Frame = 11; Tics = 8; Next state = "BOS2_RAISE5"; } State { ID = "BOS2_RAISE5"; Sprite = "BOS2"; Frame = 10; Tics = 8; Next state = "BOS2_RAISE6"; } State { ID = "BOS2_RAISE6"; Sprite = "BOS2"; Frame = 9; Tics = 8; Next state = "BOS2_RAISE7"; } State { ID = "BOS2_RAISE7"; Sprite = "BOS2"; Frame = 8; Tics = 8; Next state = "BOS2_RUN1"; } State { ID = "SKULL_STND"; Sprite = "SKUL"; Frame = 0; Flags = fullbright; Tics = 10; Action = "A_Look"; Next state = "SKULL_STND2"; } State { ID = "SKULL_STND2"; Sprite = "SKUL"; Frame = 1; Flags = fullbright; Tics = 10; Action = "A_Look"; Next state = "SKULL_STND"; } State { ID = "SKULL_RUN1"; Sprite = "SKUL"; Frame = 0; Flags = fullbright; Tics = 6; Action = "A_Chase"; Next state = "SKULL_RUN2"; } State { ID = "SKULL_RUN2"; Sprite = "SKUL"; Frame = 1; Flags = fullbright; Tics = 6; Action = "A_Chase"; Next state = "SKULL_RUN1"; } State { ID = "SKULL_ATK1"; Sprite = "SKUL"; Frame = 2; Flags = fullbright; Tics = 10; Action = "A_FaceTarget"; Next state = "SKULL_ATK2"; } State { ID = "SKULL_ATK2"; Sprite = "SKUL"; Frame = 3; Flags = fullbright; Tics = 4; Action = "A_SkullAttack"; Next state = "SKULL_ATK3"; } State { ID = "SKULL_ATK3"; Sprite = "SKUL"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "SKULL_ATK4"; } State { ID = "SKULL_ATK4"; Sprite = "SKUL"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "SKULL_ATK3"; } State { ID = "SKULL_PAIN"; Sprite = "SKUL"; Frame = 4; Flags = fullbright; Tics = 3; Next state = "SKULL_PAIN2"; } State { ID = "SKULL_PAIN2"; Sprite = "SKUL"; Frame = 4; Flags = fullbright; Tics = 3; Action = "A_Pain"; Next state = "SKULL_RUN1"; } State { ID = "SKULL_DIE1"; Sprite = "SKUL"; Frame = 5; Flags = fullbright; Tics = 6; Next state = "SKULL_DIE2"; } State { ID = "SKULL_DIE2"; Sprite = "SKUL"; Frame = 6; Flags = fullbright; Tics = 6; Action = "A_Scream"; Next state = "SKULL_DIE3"; } State { ID = "SKULL_DIE3"; Sprite = "SKUL"; Frame = 7; Flags = fullbright; Tics = 6; Next state = "SKULL_DIE4"; } State { ID = "SKULL_DIE4"; Sprite = "SKUL"; Frame = 8; Flags = fullbright; Tics = 6; Action = "A_Fall"; Next state = "SKULL_DIE5"; } State { ID = "SKULL_DIE5"; Sprite = "SKUL"; Frame = 9; Tics = 6; Next state = "SKULL_DIE6"; } State { ID = "SKULL_DIE6"; Sprite = "SKUL"; Frame = 10; Tics = 6; Next state = "NULL"; } State { ID = "SPID_STND"; Sprite = "SPID"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SPID_STND2"; } State { ID = "SPID_STND2"; Sprite = "SPID"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SPID_STND"; } State { ID = "SPID_RUN1"; Sprite = "SPID"; Frame = 0; Tics = 3; Action = "A_Metal"; Next state = "SPID_RUN2"; } State { ID = "SPID_RUN2"; Sprite = "SPID"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN3"; } State { ID = "SPID_RUN3"; Sprite = "SPID"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN4"; } State { ID = "SPID_RUN4"; Sprite = "SPID"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN5"; } State { ID = "SPID_RUN5"; Sprite = "SPID"; Frame = 2; Tics = 3; Action = "A_Metal"; Next state = "SPID_RUN6"; } State { ID = "SPID_RUN6"; Sprite = "SPID"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN7"; } State { ID = "SPID_RUN7"; Sprite = "SPID"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN8"; } State { ID = "SPID_RUN8"; Sprite = "SPID"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN9"; } State { ID = "SPID_RUN9"; Sprite = "SPID"; Frame = 4; Tics = 3; Action = "A_Metal"; Next state = "SPID_RUN10"; } State { ID = "SPID_RUN10"; Sprite = "SPID"; Frame = 4; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN11"; } State { ID = "SPID_RUN11"; Sprite = "SPID"; Frame = 5; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN12"; } State { ID = "SPID_RUN12"; Sprite = "SPID"; Frame = 5; Tics = 3; Action = "A_Chase"; Next state = "SPID_RUN1"; } State { ID = "SPID_ATK1"; Sprite = "SPID"; Frame = 0; Tics = 20; Action = "A_FaceTarget"; Next state = "SPID_ATK2"; } State { ID = "SPID_ATK2"; Sprite = "SPID"; Frame = 6; Flags = fullbright; Tics = 4; Action = "A_SPosAttack"; Next state = "SPID_ATK3"; } State { ID = "SPID_ATK3"; Sprite = "SPID"; Frame = 7; Flags = fullbright; Tics = 4; Action = "A_SPosAttack"; Next state = "SPID_ATK4"; } State { ID = "SPID_ATK4"; Sprite = "SPID"; Frame = 7; Flags = fullbright; Tics = 1; Action = "A_SpidRefire"; Next state = "SPID_ATK2"; } State { ID = "SPID_PAIN"; Sprite = "SPID"; Frame = 8; Tics = 3; Next state = "SPID_PAIN2"; } State { ID = "SPID_PAIN2"; Sprite = "SPID"; Frame = 8; Tics = 3; Action = "A_Pain"; Next state = "SPID_RUN1"; } State { ID = "SPID_DIE1"; Sprite = "SPID"; Frame = 9; Tics = 20; Action = "A_Scream"; Next state = "SPID_DIE2"; } State { ID = "SPID_DIE2"; Sprite = "SPID"; Frame = 10; Tics = 10; Action = "A_Fall"; Next state = "SPID_DIE3"; } State { ID = "SPID_DIE3"; Sprite = "SPID"; Frame = 11; Tics = 10; Next state = "SPID_DIE4"; } State { ID = "SPID_DIE4"; Sprite = "SPID"; Frame = 12; Flags = fullbright; Tics = 10; Next state = "SPID_DIE5"; } State { ID = "SPID_DIE5"; Sprite = "SPID"; Frame = 13; Flags = fullbright; Tics = 10; Next state = "SPID_DIE6"; } State { ID = "SPID_DIE6"; Sprite = "SPID"; Frame = 14; Flags = fullbright; Tics = 10; Next state = "SPID_DIE7"; } State { ID = "SPID_DIE7"; Sprite = "SPID"; Frame = 15; Flags = fullbright; Tics = 10; Next state = "SPID_DIE8"; } State { ID = "SPID_DIE8"; Sprite = "SPID"; Frame = 16; Flags = fullbright; Tics = 10; Next state = "SPID_DIE9"; } State { ID = "SPID_DIE9"; Sprite = "SPID"; Frame = 17; Flags = fullbright; Tics = 10; Next state = "SPID_DIE10"; } State { ID = "SPID_DIE10"; Sprite = "SPID"; Frame = 18; Tics = 30; Next state = "SPID_DIE11"; } State { ID = "SPID_DIE11"; Sprite = "SPID"; Frame = 18; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "BSPI_STND"; Sprite = "BSPI"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BSPI_STND2"; } State { ID = "BSPI_STND2"; Sprite = "BSPI"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "BSPI_STND"; } State { ID = "BSPI_SIGHT"; Sprite = "BSPI"; Frame = 0; Tics = 20; Next state = "BSPI_RUN1"; } State { ID = "BSPI_RUN1"; Sprite = "BSPI"; Frame = 0; Tics = 3; Action = "A_BabyMetal"; Next state = "BSPI_RUN2"; } State { ID = "BSPI_RUN2"; Sprite = "BSPI"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN3"; } State { ID = "BSPI_RUN3"; Sprite = "BSPI"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN4"; } State { ID = "BSPI_RUN4"; Sprite = "BSPI"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN5"; } State { ID = "BSPI_RUN5"; Sprite = "BSPI"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN6"; } State { ID = "BSPI_RUN6"; Sprite = "BSPI"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN7"; } State { ID = "BSPI_RUN7"; Sprite = "BSPI"; Frame = 3; Tics = 3; Action = "A_BabyMetal"; Next state = "BSPI_RUN8"; } State { ID = "BSPI_RUN8"; Sprite = "BSPI"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN9"; } State { ID = "BSPI_RUN9"; Sprite = "BSPI"; Frame = 4; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN10"; } State { ID = "BSPI_RUN10"; Sprite = "BSPI"; Frame = 4; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN11"; } State { ID = "BSPI_RUN11"; Sprite = "BSPI"; Frame = 5; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN12"; } State { ID = "BSPI_RUN12"; Sprite = "BSPI"; Frame = 5; Tics = 3; Action = "A_Chase"; Next state = "BSPI_RUN1"; } State { ID = "BSPI_ATK1"; Sprite = "BSPI"; Frame = 0; Flags = fullbright; Tics = 20; Action = "A_FaceTarget"; Next state = "BSPI_ATK2"; } State { ID = "BSPI_ATK2"; Sprite = "BSPI"; Frame = 6; Flags = fullbright; Tics = 4; Action = "A_BspiAttack"; Next state = "BSPI_ATK3"; } State { ID = "BSPI_ATK3"; Sprite = "BSPI"; Frame = 7; Flags = fullbright; Tics = 4; Next state = "BSPI_ATK4"; } State { ID = "BSPI_ATK4"; Sprite = "BSPI"; Frame = 7; Flags = fullbright; Tics = 1; Action = "A_SpidRefire"; Next state = "BSPI_ATK2"; } State { ID = "BSPI_PAIN"; Sprite = "BSPI"; Frame = 8; Tics = 3; Next state = "BSPI_PAIN2"; } State { ID = "BSPI_PAIN2"; Sprite = "BSPI"; Frame = 8; Tics = 3; Action = "A_Pain"; Next state = "BSPI_RUN1"; } State { ID = "BSPI_DIE1"; Sprite = "BSPI"; Frame = 9; Tics = 20; Action = "A_Scream"; Next state = "BSPI_DIE2"; } State { ID = "BSPI_DIE2"; Sprite = "BSPI"; Frame = 10; Tics = 7; Action = "A_Fall"; Next state = "BSPI_DIE3"; } State { ID = "BSPI_DIE3"; Sprite = "BSPI"; Frame = 11; Tics = 7; Next state = "BSPI_DIE4"; } State { ID = "BSPI_DIE4"; Sprite = "BSPI"; Frame = 12; Tics = 7; Next state = "BSPI_DIE5"; } State { ID = "BSPI_DIE5"; Sprite = "BSPI"; Frame = 13; Tics = 7; Next state = "BSPI_DIE6"; } State { ID = "BSPI_DIE6"; Sprite = "BSPI"; Frame = 14; Tics = 7; Next state = "BSPI_DIE7"; } State { ID = "BSPI_DIE7"; Sprite = "BSPI"; Frame = 15; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "BSPI_RAISE1"; Sprite = "BSPI"; Frame = 15; Tics = 5; Next state = "BSPI_RAISE2"; } State { ID = "BSPI_RAISE2"; Sprite = "BSPI"; Frame = 14; Tics = 5; Next state = "BSPI_RAISE3"; } State { ID = "BSPI_RAISE3"; Sprite = "BSPI"; Frame = 13; Tics = 5; Next state = "BSPI_RAISE4"; } State { ID = "BSPI_RAISE4"; Sprite = "BSPI"; Frame = 12; Tics = 5; Next state = "BSPI_RAISE5"; } State { ID = "BSPI_RAISE5"; Sprite = "BSPI"; Frame = 11; Tics = 5; Next state = "BSPI_RAISE6"; } State { ID = "BSPI_RAISE6"; Sprite = "BSPI"; Frame = 10; Tics = 5; Next state = "BSPI_RAISE7"; } State { ID = "BSPI_RAISE7"; Sprite = "BSPI"; Frame = 9; Tics = 5; Next state = "BSPI_RUN1"; } State { ID = "ARACH_PLAZ"; Sprite = "APLS"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "ARACH_PLAZ2"; } State { ID = "ARACH_PLAZ2"; Sprite = "APLS"; Frame = 1; Flags = fullbright; Tics = 5; Next state = "ARACH_PLAZ"; } State { ID = "ARACH_PLEX"; Sprite = "APBX"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "ARACH_PLEX2"; } State { ID = "ARACH_PLEX2"; Sprite = "APBX"; Frame = 1; Flags = fullbright; Tics = 5; Next state = "ARACH_PLEX3"; } State { ID = "ARACH_PLEX3"; Sprite = "APBX"; Frame = 2; Flags = fullbright; Tics = 5; Next state = "ARACH_PLEX4"; } State { ID = "ARACH_PLEX4"; Sprite = "APBX"; Frame = 3; Flags = fullbright; Tics = 5; Next state = "ARACH_PLEX5"; } State { ID = "ARACH_PLEX5"; Sprite = "APBX"; Frame = 4; Flags = fullbright; Tics = 5; Next state = "NULL"; } State { ID = "CYBER_STND"; Sprite = "CYBR"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "CYBER_STND2"; } State { ID = "CYBER_STND2"; Sprite = "CYBR"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "CYBER_STND"; } State { ID = "CYBER_RUN1"; Sprite = "CYBR"; Frame = 0; Tics = 3; Action = "A_Hoof"; Next state = "CYBER_RUN2"; } State { ID = "CYBER_RUN2"; Sprite = "CYBR"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "CYBER_RUN3"; } State { ID = "CYBER_RUN3"; Sprite = "CYBR"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "CYBER_RUN4"; } State { ID = "CYBER_RUN4"; Sprite = "CYBR"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "CYBER_RUN5"; } State { ID = "CYBER_RUN5"; Sprite = "CYBR"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "CYBER_RUN6"; } State { ID = "CYBER_RUN6"; Sprite = "CYBR"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "CYBER_RUN7"; } State { ID = "CYBER_RUN7"; Sprite = "CYBR"; Frame = 3; Tics = 3; Action = "A_Metal"; Next state = "CYBER_RUN8"; } State { ID = "CYBER_RUN8"; Sprite = "CYBR"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "CYBER_RUN1"; } State { ID = "CYBER_ATK1"; Sprite = "CYBR"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "CYBER_ATK2"; } State { ID = "CYBER_ATK2"; Sprite = "CYBR"; Frame = 5; Flags = fullbright; Tics = 12; Action = "A_CyberAttack"; Next state = "CYBER_ATK3"; } State { ID = "CYBER_ATK3"; Sprite = "CYBR"; Frame = 4; Tics = 12; Action = "A_FaceTarget"; Next state = "CYBER_ATK4"; } State { ID = "CYBER_ATK4"; Sprite = "CYBR"; Frame = 5; Flags = fullbright; Tics = 12; Action = "A_CyberAttack"; Next state = "CYBER_ATK5"; } State { ID = "CYBER_ATK5"; Sprite = "CYBR"; Frame = 4; Tics = 12; Action = "A_FaceTarget"; Next state = "CYBER_ATK6"; } State { ID = "CYBER_ATK6"; Sprite = "CYBR"; Frame = 5; Flags = fullbright; Tics = 12; Action = "A_CyberAttack"; Next state = "CYBER_RUN1"; } State { ID = "CYBER_PAIN"; Sprite = "CYBR"; Frame = 6; Tics = 10; Action = "A_Pain"; Next state = "CYBER_RUN1"; } State { ID = "CYBER_DIE1"; Sprite = "CYBR"; Frame = 7; Tics = 10; Next state = "CYBER_DIE2"; } State { ID = "CYBER_DIE2"; Sprite = "CYBR"; Frame = 8; Tics = 10; Action = "A_Scream"; Next state = "CYBER_DIE3"; } State { ID = "CYBER_DIE3"; Sprite = "CYBR"; Frame = 9; Tics = 10; Next state = "CYBER_DIE4"; } State { ID = "CYBER_DIE4"; Sprite = "CYBR"; Frame = 10; Tics = 10; Next state = "CYBER_DIE5"; } State { ID = "CYBER_DIE5"; Sprite = "CYBR"; Frame = 11; Tics = 10; Next state = "CYBER_DIE6"; } State { ID = "CYBER_DIE6"; Sprite = "CYBR"; Frame = 12; Tics = 10; Action = "A_Fall"; Next state = "CYBER_DIE7"; } State { ID = "CYBER_DIE7"; Sprite = "CYBR"; Frame = 13; Tics = 10; Next state = "CYBER_DIE8"; } State { ID = "CYBER_DIE8"; Sprite = "CYBR"; Frame = 14; Tics = 10; Next state = "CYBER_DIE9"; } State { ID = "CYBER_DIE9"; Sprite = "CYBR"; Frame = 15; Tics = 30; Next state = "CYBER_DIE10"; } State { ID = "CYBER_DIE10"; Sprite = "CYBR"; Frame = 15; Tics = -1; Action = "A_BossDeath"; Next state = "NULL"; } State { ID = "PAIN_STND"; Sprite = "PAIN"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "PAIN_STND"; } State { ID = "PAIN_RUN1"; Sprite = "PAIN"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "PAIN_RUN2"; } State { ID = "PAIN_RUN2"; Sprite = "PAIN"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "PAIN_RUN3"; } State { ID = "PAIN_RUN3"; Sprite = "PAIN"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "PAIN_RUN4"; } State { ID = "PAIN_RUN4"; Sprite = "PAIN"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "PAIN_RUN5"; } State { ID = "PAIN_RUN5"; Sprite = "PAIN"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "PAIN_RUN6"; } State { ID = "PAIN_RUN6"; Sprite = "PAIN"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "PAIN_RUN1"; } State { ID = "PAIN_ATK1"; Sprite = "PAIN"; Frame = 3; Tics = 5; Action = "A_FaceTarget"; Next state = "PAIN_ATK2"; } State { ID = "PAIN_ATK2"; Sprite = "PAIN"; Frame = 4; Tics = 5; Action = "A_FaceTarget"; Next state = "PAIN_ATK3"; } State { ID = "PAIN_ATK3"; Sprite = "PAIN"; Frame = 5; Flags = fullbright; Tics = 5; Action = "A_FaceTarget"; Next state = "PAIN_ATK4"; } State { ID = "PAIN_ATK4"; Sprite = "PAIN"; Frame = 5; Flags = fullbright; Tics = 0; Action = "A_PainAttack"; Next state = "PAIN_RUN1"; } State { ID = "PAIN_PAIN"; Sprite = "PAIN"; Frame = 6; Tics = 6; Next state = "PAIN_PAIN2"; } State { ID = "PAIN_PAIN2"; Sprite = "PAIN"; Frame = 6; Tics = 6; Action = "A_Pain"; Next state = "PAIN_RUN1"; } State { ID = "PAIN_DIE1"; Sprite = "PAIN"; Frame = 7; Flags = fullbright; Tics = 8; Next state = "PAIN_DIE2"; } State { ID = "PAIN_DIE2"; Sprite = "PAIN"; Frame = 8; Flags = fullbright; Tics = 8; Action = "A_Scream"; Next state = "PAIN_DIE3"; } State { ID = "PAIN_DIE3"; Sprite = "PAIN"; Frame = 9; Flags = fullbright; Tics = 8; Next state = "PAIN_DIE4"; } State { ID = "PAIN_DIE4"; Sprite = "PAIN"; Frame = 10; Flags = fullbright; Tics = 8; Next state = "PAIN_DIE5"; } State { ID = "PAIN_DIE5"; Sprite = "PAIN"; Frame = 11; Flags = fullbright; Tics = 8; Action = "A_PainDie"; Next state = "PAIN_DIE6"; } State { ID = "PAIN_DIE6"; Sprite = "PAIN"; Frame = 12; Flags = fullbright; Tics = 8; Next state = "NULL"; } State { ID = "PAIN_RAISE1"; Sprite = "PAIN"; Frame = 12; Tics = 8; Next state = "PAIN_RAISE2"; } State { ID = "PAIN_RAISE2"; Sprite = "PAIN"; Frame = 11; Tics = 8; Next state = "PAIN_RAISE3"; } State { ID = "PAIN_RAISE3"; Sprite = "PAIN"; Frame = 10; Tics = 8; Next state = "PAIN_RAISE4"; } State { ID = "PAIN_RAISE4"; Sprite = "PAIN"; Frame = 9; Tics = 8; Next state = "PAIN_RAISE5"; } State { ID = "PAIN_RAISE5"; Sprite = "PAIN"; Frame = 8; Tics = 8; Next state = "PAIN_RAISE6"; } State { ID = "PAIN_RAISE6"; Sprite = "PAIN"; Frame = 7; Tics = 8; Next state = "PAIN_RUN1"; } State { ID = "SSWV_STND"; Sprite = "SSWV"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SSWV_STND2"; } State { ID = "SSWV_STND2"; Sprite = "SSWV"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "SSWV_STND"; } State { ID = "SSWV_RUN1"; Sprite = "SSWV"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN2"; } State { ID = "SSWV_RUN2"; Sprite = "SSWV"; Frame = 0; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN3"; } State { ID = "SSWV_RUN3"; Sprite = "SSWV"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN4"; } State { ID = "SSWV_RUN4"; Sprite = "SSWV"; Frame = 1; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN5"; } State { ID = "SSWV_RUN5"; Sprite = "SSWV"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN6"; } State { ID = "SSWV_RUN6"; Sprite = "SSWV"; Frame = 2; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN7"; } State { ID = "SSWV_RUN7"; Sprite = "SSWV"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN8"; } State { ID = "SSWV_RUN8"; Sprite = "SSWV"; Frame = 3; Tics = 3; Action = "A_Chase"; Next state = "SSWV_RUN1"; } State { ID = "SSWV_ATK1"; Sprite = "SSWV"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "SSWV_ATK2"; } State { ID = "SSWV_ATK2"; Sprite = "SSWV"; Frame = 5; Tics = 10; Action = "A_FaceTarget"; Next state = "SSWV_ATK3"; } State { ID = "SSWV_ATK3"; Sprite = "SSWV"; Frame = 6; Flags = fullbright; Tics = 4; Action = "A_CPosAttack"; Next state = "SSWV_ATK4"; } State { ID = "SSWV_ATK4"; Sprite = "SSWV"; Frame = 5; Tics = 6; Action = "A_FaceTarget"; Next state = "SSWV_ATK5"; } State { ID = "SSWV_ATK5"; Sprite = "SSWV"; Frame = 6; Flags = fullbright; Tics = 4; Action = "A_CPosAttack"; Next state = "SSWV_ATK6"; } State { ID = "SSWV_ATK6"; Sprite = "SSWV"; Frame = 5; Tics = 1; Action = "A_CPosRefire"; Next state = "SSWV_ATK2"; } State { ID = "SSWV_PAIN"; Sprite = "SSWV"; Frame = 7; Tics = 3; Next state = "SSWV_PAIN2"; } State { ID = "SSWV_PAIN2"; Sprite = "SSWV"; Frame = 7; Tics = 3; Action = "A_Pain"; Next state = "SSWV_RUN1"; } State { ID = "SSWV_DIE1"; Sprite = "SSWV"; Frame = 8; Tics = 5; Next state = "SSWV_DIE2"; } State { ID = "SSWV_DIE2"; Sprite = "SSWV"; Frame = 9; Tics = 5; Action = "A_Scream"; Next state = "SSWV_DIE3"; } State { ID = "SSWV_DIE3"; Sprite = "SSWV"; Frame = 10; Tics = 5; Action = "A_Fall"; Next state = "SSWV_DIE4"; } State { ID = "SSWV_DIE4"; Sprite = "SSWV"; Frame = 11; Tics = 5; Next state = "SSWV_DIE5"; } State { ID = "SSWV_DIE5"; Sprite = "SSWV"; Frame = 12; Tics = -1; Next state = "NULL"; } State { ID = "SSWV_XDIE1"; Sprite = "SSWV"; Frame = 13; Tics = 5; Next state = "SSWV_XDIE2"; } State { ID = "SSWV_XDIE2"; Sprite = "SSWV"; Frame = 14; Tics = 5; Action = "A_XScream"; Next state = "SSWV_XDIE3"; } State { ID = "SSWV_XDIE3"; Sprite = "SSWV"; Frame = 15; Tics = 5; Action = "A_Fall"; Next state = "SSWV_XDIE4"; } State { ID = "SSWV_XDIE4"; Sprite = "SSWV"; Frame = 16; Tics = 5; Next state = "SSWV_XDIE5"; } State { ID = "SSWV_XDIE5"; Sprite = "SSWV"; Frame = 17; Tics = 5; Next state = "SSWV_XDIE6"; } State { ID = "SSWV_XDIE6"; Sprite = "SSWV"; Frame = 18; Tics = 5; Next state = "SSWV_XDIE7"; } State { ID = "SSWV_XDIE7"; Sprite = "SSWV"; Frame = 19; Tics = 5; Next state = "SSWV_XDIE8"; } State { ID = "SSWV_XDIE8"; Sprite = "SSWV"; Frame = 20; Tics = 5; Next state = "SSWV_XDIE9"; } State { ID = "SSWV_XDIE9"; Sprite = "SSWV"; Frame = 21; Tics = -1; Next state = "NULL"; } State { ID = "SSWV_RAISE1"; Sprite = "SSWV"; Frame = 12; Tics = 5; Next state = "SSWV_RAISE2"; } State { ID = "SSWV_RAISE2"; Sprite = "SSWV"; Frame = 11; Tics = 5; Next state = "SSWV_RAISE3"; } State { ID = "SSWV_RAISE3"; Sprite = "SSWV"; Frame = 10; Tics = 5; Next state = "SSWV_RAISE4"; } State { ID = "SSWV_RAISE4"; Sprite = "SSWV"; Frame = 9; Tics = 5; Next state = "SSWV_RAISE5"; } State { ID = "SSWV_RAISE5"; Sprite = "SSWV"; Frame = 8; Tics = 5; Next state = "SSWV_RUN1"; } State { ID = "KEENSTND"; Sprite = "KEEN"; Frame = 0; Tics = -1; Next state = "KEENSTND"; } State { ID = "COMMKEEN"; Sprite = "KEEN"; Frame = 0; Tics = 6; Next state = "COMMKEEN2"; } State { ID = "COMMKEEN2"; Sprite = "KEEN"; Frame = 1; Tics = 6; Next state = "COMMKEEN3"; } State { ID = "COMMKEEN3"; Sprite = "KEEN"; Frame = 2; Tics = 6; Action = "A_Scream"; Next state = "COMMKEEN4"; } State { ID = "COMMKEEN4"; Sprite = "KEEN"; Frame = 3; Tics = 6; Next state = "COMMKEEN5"; } State { ID = "COMMKEEN5"; Sprite = "KEEN"; Frame = 4; Tics = 6; Next state = "COMMKEEN6"; } State { ID = "COMMKEEN6"; Sprite = "KEEN"; Frame = 5; Tics = 6; Next state = "COMMKEEN7"; } State { ID = "COMMKEEN7"; Sprite = "KEEN"; Frame = 6; Tics = 6; Next state = "COMMKEEN8"; } State { ID = "COMMKEEN8"; Sprite = "KEEN"; Frame = 7; Tics = 6; Next state = "COMMKEEN9"; } State { ID = "COMMKEEN9"; Sprite = "KEEN"; Frame = 8; Tics = 6; Next state = "COMMKEEN10"; } State { ID = "COMMKEEN10"; Sprite = "KEEN"; Frame = 9; Tics = 6; Next state = "COMMKEEN11"; } State { ID = "COMMKEEN11"; Sprite = "KEEN"; Frame = 10; Tics = 6; Action = "A_KeenDie"; Next state = "COMMKEEN12"; } State { ID = "COMMKEEN12"; Sprite = "KEEN"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "KEENPAIN"; Sprite = "KEEN"; Frame = 12; Tics = 4; Next state = "KEENPAIN2"; } State { ID = "KEENPAIN2"; Sprite = "KEEN"; Frame = 12; Tics = 8; Action = "A_Pain"; Next state = "KEENSTND"; } State { ID = "BRAIN"; Sprite = "BBRN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BRAIN_PAIN"; Sprite = "BBRN"; Frame = 1; Tics = 36; Action = "A_BrainPain"; Next state = "BRAIN"; } State { ID = "BRAIN_DIE1"; Sprite = "BBRN"; Frame = 0; Tics = 100; Action = "A_BrainScream"; Next state = "BRAIN_DIE2"; } State { ID = "BRAIN_DIE2"; Sprite = "BBRN"; Frame = 0; Tics = 10; Next state = "BRAIN_DIE3"; } State { ID = "BRAIN_DIE3"; Sprite = "BBRN"; Frame = 0; Tics = 10; Next state = "BRAIN_DIE4"; } State { ID = "BRAIN_DIE4"; Sprite = "BBRN"; Frame = 0; Tics = -1; Action = "A_BrainDie"; Next state = "NULL"; } State { ID = "BRAINEYE"; Sprite = "SSWV"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BRAINEYE"; } State { ID = "BRAINEYESEE"; Sprite = "SSWV"; Frame = 0; Tics = 181; Action = "A_BrainAwake"; Next state = "BRAINEYE1"; } State { ID = "BRAINEYE1"; Sprite = "SSWV"; Frame = 0; Tics = 150; Action = "A_BrainSpit"; Next state = "BRAINEYE1"; } State { ID = "SPAWN1"; Sprite = "BOSF"; Frame = 0; Flags = fullbright; Tics = 3; Action = "A_SpawnSound"; Next state = "SPAWN2"; } State { ID = "SPAWN2"; Sprite = "BOSF"; Frame = 1; Flags = fullbright; Tics = 3; Action = "A_SpawnFly"; Next state = "SPAWN3"; } State { ID = "SPAWN3"; Sprite = "BOSF"; Frame = 2; Flags = fullbright; Tics = 3; Action = "A_SpawnFly"; Next state = "SPAWN4"; } State { ID = "SPAWN4"; Sprite = "BOSF"; Frame = 3; Flags = fullbright; Tics = 3; Action = "A_SpawnFly"; Next state = "SPAWN1"; } State { ID = "SPAWNFIRE1"; Sprite = "FIRE"; Frame = 0; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "SPAWNFIRE2"; } State { ID = "SPAWNFIRE2"; Sprite = "FIRE"; Frame = 1; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "SPAWNFIRE3"; } State { ID = "SPAWNFIRE3"; Sprite = "FIRE"; Frame = 2; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "SPAWNFIRE4"; } State { ID = "SPAWNFIRE4"; Sprite = "FIRE"; Frame = 3; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "SPAWNFIRE5"; } State { ID = "SPAWNFIRE5"; Sprite = "FIRE"; Frame = 4; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "SPAWNFIRE6"; } State { ID = "SPAWNFIRE6"; Sprite = "FIRE"; Frame = 5; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "SPAWNFIRE7"; } State { ID = "SPAWNFIRE7"; Sprite = "FIRE"; Frame = 6; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "SPAWNFIRE8"; } State { ID = "SPAWNFIRE8"; Sprite = "FIRE"; Frame = 7; Flags = fullbright; Tics = 4; Action = "A_Fire"; Next state = "NULL"; } State { ID = "BRAINEXPLODE1"; Sprite = "MISL"; Frame = 1; Flags = fullbright; Tics = 10; Next state = "BRAINEXPLODE2"; } State { ID = "BRAINEXPLODE2"; Sprite = "MISL"; Frame = 2; Flags = fullbright; Tics = 10; Next state = "BRAINEXPLODE3"; } State { ID = "BRAINEXPLODE3"; Sprite = "MISL"; Frame = 3; Flags = fullbright; Tics = 10; Action = "A_BrainExplode"; Next state = "NULL"; } State { ID = "ARM1"; Sprite = "ARM1"; Frame = 0; Tics = 6; Next state = "ARM1A"; } State { ID = "ARM1A"; Sprite = "ARM1"; Frame = 1; Tics = 7; Flags = fullbright | noautolight; Next state = "ARM1"; } State { ID = "ARM2"; Sprite = "ARM2"; Frame = 0; Tics = 6; Next state = "ARM2A"; } State { ID = "ARM2A"; Sprite = "ARM2"; Frame = 1; Tics = 6; Flags = fullbright | noautolight; Next state = "ARM2"; } State { ID = "BAR1"; Sprite = "BAR1"; Frame = 0; Tics = 6; Next state = "BAR2"; } State { ID = "BAR2"; Sprite = "BAR1"; Frame = 1; Tics = 6; Next state = "BAR1"; } State { ID = "BEXP"; Sprite = "BEXP"; Frame = 0; Flags = fullbright; Tics = 5; Next state = "BEXP2"; } State { ID = "BEXP2"; Sprite = "BEXP"; Frame = 1; Flags = fullbright; Tics = 5; Action = "A_Scream"; Next state = "BEXP3"; } State { ID = "BEXP3"; Sprite = "BEXP"; Frame = 2; Flags = fullbright; Tics = 5; Next state = "BEXP4"; } State { ID = "BEXP4"; Sprite = "BEXP"; Frame = 3; Flags = fullbright; Tics = 10; Action = "A_Explode"; Next state = "BEXP5"; } State { ID = "BEXP5"; Sprite = "BEXP"; Frame = 4; Flags = fullbright; Tics = 10; Next state = "NULL"; } State { ID = "BBAR1"; Sprite = "FCAN"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BBAR2"; } State { ID = "BBAR2"; Sprite = "FCAN"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BBAR3"; } State { ID = "BBAR3"; Sprite = "FCAN"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "BBAR1"; } State { ID = "BON1"; Sprite = "BON1"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "BON1A"; } State { ID = "BON1A"; Sprite = "BON1"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "BON1B"; } State { ID = "BON1B"; Sprite = "BON1"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "BON1C"; } State { ID = "BON1C"; Sprite = "BON1"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "BON1D"; } State { ID = "BON1D"; Sprite = "BON1"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "BON1E"; } State { ID = "BON1E"; Sprite = "BON1"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "BON1"; } State { ID = "BON2"; Sprite = "BON2"; Frame = 0; Tics = 6; Next state = "BON2A"; } State { ID = "BON2A"; Sprite = "BON2"; Frame = 1; Tics = 6; Next state = "BON2B"; } State { ID = "BON2B"; Sprite = "BON2"; Frame = 2; Tics = 6; Next state = "BON2C"; } State { ID = "BON2C"; Sprite = "BON2"; Frame = 3; Tics = 6; Next state = "BON2D"; } State { ID = "BON2D"; Sprite = "BON2"; Frame = 2; Tics = 6; Next state = "BON2E"; } State { ID = "BON2E"; Sprite = "BON2"; Frame = 1; Tics = 6; Next state = "BON2"; } State { ID = "BKEY"; Sprite = "BKEY"; Frame = 0; Tics = 10; Next state = "BKEY2"; } State { ID = "BKEY2"; Sprite = "BKEY"; Frame = 1; Flags = fullbright; Tics = 10; Next state = "BKEY"; } State { ID = "RKEY"; Sprite = "RKEY"; Frame = 0; Tics = 10; Next state = "RKEY2"; } State { ID = "RKEY2"; Sprite = "RKEY"; Frame = 1; Flags = fullbright; Tics = 10; Next state = "RKEY"; } State { ID = "YKEY"; Sprite = "YKEY"; Frame = 0; Tics = 10; Next state = "YKEY2"; } State { ID = "YKEY2"; Sprite = "YKEY"; Frame = 1; Flags = fullbright; Tics = 10; Next state = "YKEY"; } State { ID = "BSKULL"; Sprite = "BSKU"; Frame = 0; Tics = 10; Next state = "BSKULL2"; } State { ID = "BSKULL2"; Sprite = "BSKU"; Frame = 1; Flags = fullbright; Tics = 10; Next state = "BSKULL"; } State { ID = "RSKULL"; Sprite = "RSKU"; Frame = 0; Tics = 10; Next state = "RSKULL2"; } State { ID = "RSKULL2"; Sprite = "RSKU"; Frame = 1; Flags = fullbright; Tics = 10; Next state = "RSKULL"; } State { ID = "YSKULL"; Sprite = "YSKU"; Frame = 0; Tics = 10; Next state = "YSKULL2"; } State { ID = "YSKULL2"; Sprite = "YSKU"; Frame = 1; Flags = fullbright; Tics = 10; Next state = "YSKULL"; } State { ID = "STIM"; Sprite = "STIM"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEDI"; Sprite = "MEDI"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SOUL"; Sprite = "SOUL"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "SOUL2"; } State { ID = "SOUL2"; Sprite = "SOUL"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "SOUL3"; } State { ID = "SOUL3"; Sprite = "SOUL"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "SOUL4"; } State { ID = "SOUL4"; Sprite = "SOUL"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "SOUL5"; } State { ID = "SOUL5"; Sprite = "SOUL"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "SOUL6"; } State { ID = "SOUL6"; Sprite = "SOUL"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "SOUL"; } State { ID = "PINV"; Sprite = "PINV"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "PINV2"; } State { ID = "PINV2"; Sprite = "PINV"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PINV3"; } State { ID = "PINV3"; Sprite = "PINV"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "PINV4"; } State { ID = "PINV4"; Sprite = "PINV"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "PINV"; } State { ID = "PSTR"; Sprite = "PSTR"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "PINS"; Sprite = "PINS"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "PINS2"; } State { ID = "PINS2"; Sprite = "PINS"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PINS3"; } State { ID = "PINS3"; Sprite = "PINS"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "PINS4"; } State { ID = "PINS4"; Sprite = "PINS"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "PINS"; } State { ID = "MEGA"; Sprite = "MEGA"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "MEGA2"; } State { ID = "MEGA2"; Sprite = "MEGA"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "MEGA3"; } State { ID = "MEGA3"; Sprite = "MEGA"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "MEGA4"; } State { ID = "MEGA4"; Sprite = "MEGA"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "MEGA"; } State { ID = "SUIT"; Sprite = "SUIT"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "PMAP"; Sprite = "PMAP"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "PMAP2"; } State { ID = "PMAP2"; Sprite = "PMAP"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PMAP3"; } State { ID = "PMAP3"; Sprite = "PMAP"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "PMAP4"; } State { ID = "PMAP4"; Sprite = "PMAP"; Frame = 3; Flags = fullbright; Tics = 6; Next state = "PMAP5"; } State { ID = "PMAP5"; Sprite = "PMAP"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "PMAP6"; } State { ID = "PMAP6"; Sprite = "PMAP"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "PMAP"; } State { ID = "PVIS"; Sprite = "PVIS"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "PVIS2"; } State { ID = "PVIS2"; Sprite = "PVIS"; Frame = 1; Tics = 6; Next state = "PVIS"; } State { ID = "CLIP"; Sprite = "CLIP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "AMMO"; Sprite = "AMMO"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ROCK"; Sprite = "ROCK"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BROK"; Sprite = "BROK"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CELL"; Sprite = "CELL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CELP"; Sprite = "CELP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHEL"; Sprite = "SHEL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SBOX"; Sprite = "SBOX"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BPAK"; Sprite = "BPAK"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BFUG"; Sprite = "BFUG"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MGUN"; Sprite = "MGUN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CSAW"; Sprite = "CSAW"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "LAUN"; Sprite = "LAUN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PLAS"; Sprite = "PLAS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHOT"; Sprite = "SHOT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHOT2"; Sprite = "SGN2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "COLU"; Sprite = "COLU"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "STALAG"; Sprite = "SMT2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BLOODYTWITCH"; Sprite = "GOR1"; Frame = 0; Tics = 10; Next state = "BLOODYTWITCH2"; } State { ID = "BLOODYTWITCH2"; Sprite = "GOR1"; Frame = 1; Tics = 15; Next state = "BLOODYTWITCH3"; } State { ID = "BLOODYTWITCH3"; Sprite = "GOR1"; Frame = 2; Tics = 8; Next state = "BLOODYTWITCH4"; } State { ID = "BLOODYTWITCH4"; Sprite = "GOR1"; Frame = 1; Tics = 6; Next state = "BLOODYTWITCH"; } State { ID = "DEADTORSO"; Sprite = "PLAY"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "DEADBOTTOM"; Sprite = "PLAY"; Frame = 18; Tics = -1; Next state = "NULL"; } State { ID = "HEADSONSTICK"; Sprite = "POL2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "GIBS"; Sprite = "POL5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HEADONASTICK"; Sprite = "POL4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HEADCANDLES"; Sprite = "POL3"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "HEADCANDLES2"; } State { ID = "HEADCANDLES2"; Sprite = "POL3"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "HEADCANDLES"; } State { ID = "DEADSTICK"; Sprite = "POL1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "LIVESTICK"; Sprite = "POL6"; Frame = 0; Tics = 6; Next state = "LIVESTICK2"; } State { ID = "LIVESTICK2"; Sprite = "POL6"; Frame = 1; Tics = 8; Next state = "LIVESTICK"; } State { ID = "MEAT2"; Sprite = "GOR2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEAT3"; Sprite = "GOR3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEAT4"; Sprite = "GOR4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MEAT5"; Sprite = "GOR5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "STALAGTITE"; Sprite = "SMIT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TALLGRNCOL"; Sprite = "COL1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHRTGRNCOL"; Sprite = "COL2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TALLREDCOL"; Sprite = "COL3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SHRTREDCOL"; Sprite = "COL4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CANDLESTIK"; Sprite = "CAND"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "CANDELABRA"; Sprite = "CBRA"; Frame = 0; Flags = fullbright; Tics = -1; Next state = "NULL"; } State { ID = "SKULLCOL"; Sprite = "COL6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TORCHTREE"; Sprite = "TRE1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BIGTREE"; Sprite = "TRE2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TECHPILLAR"; Sprite = "ELEC"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "EVILEYE"; Sprite = "CEYE"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "EVILEYE2"; } State { ID = "EVILEYE2"; Sprite = "CEYE"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "EVILEYE3"; } State { ID = "EVILEYE3"; Sprite = "CEYE"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "EVILEYE4"; } State { ID = "EVILEYE4"; Sprite = "CEYE"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "EVILEYE"; } State { ID = "FLOATSKULL"; Sprite = "FSKU"; Frame = 0; Flags = fullbright; Tics = 6; Next state = "FLOATSKULL2"; } State { ID = "FLOATSKULL2"; Sprite = "FSKU"; Frame = 1; Flags = fullbright; Tics = 6; Next state = "FLOATSKULL3"; } State { ID = "FLOATSKULL3"; Sprite = "FSKU"; Frame = 2; Flags = fullbright; Tics = 6; Next state = "FLOATSKULL"; } State { ID = "HEARTCOL"; Sprite = "COL5"; Frame = 0; Tics = 14; Next state = "HEARTCOL2"; } State { ID = "HEARTCOL2"; Sprite = "COL5"; Frame = 1; Tics = 14; Next state = "HEARTCOL"; } State { ID = "BLUETORCH"; Sprite = "TBLU"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BLUETORCH2"; } State { ID = "BLUETORCH2"; Sprite = "TBLU"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BLUETORCH3"; } State { ID = "BLUETORCH3"; Sprite = "TBLU"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "BLUETORCH4"; } State { ID = "BLUETORCH4"; Sprite = "TBLU"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "BLUETORCH"; } State { ID = "GREENTORCH"; Sprite = "TGRN"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "GREENTORCH2"; } State { ID = "GREENTORCH2"; Sprite = "TGRN"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "GREENTORCH3"; } State { ID = "GREENTORCH3"; Sprite = "TGRN"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "GREENTORCH4"; } State { ID = "GREENTORCH4"; Sprite = "TGRN"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "GREENTORCH"; } State { ID = "REDTORCH"; Sprite = "TRED"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "REDTORCH2"; } State { ID = "REDTORCH2"; Sprite = "TRED"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "REDTORCH3"; } State { ID = "REDTORCH3"; Sprite = "TRED"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "REDTORCH4"; } State { ID = "REDTORCH4"; Sprite = "TRED"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "REDTORCH"; } State { ID = "BTORCHSHRT"; Sprite = "SMBT"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT2"; } State { ID = "BTORCHSHRT2"; Sprite = "SMBT"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT3"; } State { ID = "BTORCHSHRT3"; Sprite = "SMBT"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT4"; } State { ID = "BTORCHSHRT4"; Sprite = "SMBT"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "BTORCHSHRT"; } State { ID = "GTORCHSHRT"; Sprite = "SMGT"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT2"; } State { ID = "GTORCHSHRT2"; Sprite = "SMGT"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT3"; } State { ID = "GTORCHSHRT3"; Sprite = "SMGT"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT4"; } State { ID = "GTORCHSHRT4"; Sprite = "SMGT"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "GTORCHSHRT"; } State { ID = "RTORCHSHRT"; Sprite = "SMRT"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT2"; } State { ID = "RTORCHSHRT2"; Sprite = "SMRT"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT3"; } State { ID = "RTORCHSHRT3"; Sprite = "SMRT"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT4"; } State { ID = "RTORCHSHRT4"; Sprite = "SMRT"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "RTORCHSHRT"; } State { ID = "HANGNOGUTS"; Sprite = "HDB1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGBNOBRAIN"; Sprite = "HDB2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTLOOKDN"; Sprite = "HDB3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTSKULL"; Sprite = "HDB4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTLOOKUP"; Sprite = "HDB5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "HANGTNOBRAIN"; Sprite = "HDB6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "COLONGIBS"; Sprite = "POB1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SMALLPOOL"; Sprite = "POB2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BRAINSTEM"; Sprite = "BRS1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TECHLAMP"; Sprite = "TLMP"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "TECHLAMP2"; } State { ID = "TECHLAMP2"; Sprite = "TLMP"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "TECHLAMP3"; } State { ID = "TECHLAMP3"; Sprite = "TLMP"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "TECHLAMP4"; } State { ID = "TECHLAMP4"; Sprite = "TLMP"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "TECHLAMP"; } State { ID = "TECH2LAMP"; Sprite = "TLP2"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "TECH2LAMP2"; } State { ID = "TECH2LAMP2"; Sprite = "TLP2"; Frame = 1; Flags = fullbright; Tics = 4; Next state = "TECH2LAMP3"; } State { ID = "TECH2LAMP3"; Sprite = "TLP2"; Frame = 2; Flags = fullbright; Tics = 4; Next state = "TECH2LAMP4"; } State { ID = "TECH2LAMP4"; Sprite = "TLP2"; Frame = 3; Flags = fullbright; Tics = 4; Next state = "TECH2LAMP"; } State { ID = "SMALL_WHITE_LIGHT"; Sprite = "APBX"; Frame = 4; Tics = -1; Next state = "NULL"; } Thing { ID = "TEMPSOUNDORIGIN"; DoomEd number = -1; Spawn state = "TEMPSOUNDORIGIN1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Radius = 1; Height = 1; Mass = 100; Flags = local | nosector | noblockmap | nogravity; } State { ID = "TEMPSOUNDORIGIN1"; Tics = 175; Next state = "NULL"; } # An extra step for the missile explosion to allow the particle effects to # look better. A bit of a hack, mind you. State { ID = "EXPLODE0"; Sprite = "MISL"; Frame = 1; Flags = fullbright; Next state = "EXPLODE1"; } # A_Tracer() spawns rocket puffs. This is copied from the original # PUFF type. Thing { ID = "ROCKETPUFF"; DoomEd number = -1; Spawn state = "ROCKETPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; Raise state = "NULL"; See sound = "None"; Attack sound = "None"; Pain sound = "None"; Death sound = "None"; Active sound = "None"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 8; Mass = 100; Flags = noblockmap | nogravity | viewalign; } State { ID = "ROCKETPUFF1"; Sprite = "PUFF"; Frame = 0; Flags = fullbright; Tics = 4; Next state = "ROCKETPUFF2"; } State { ID = "ROCKETPUFF2"; Sprite = "PUFF"; Frame = 1; Tics = 4; Next state = "ROCKETPUFF3"; } State { ID = "ROCKETPUFF3"; Sprite = "PUFF"; Frame = 2; Tics = 4; Next state = "ROCKETPUFF4"; } State { ID = "ROCKETPUFF4"; Sprite = "PUFF"; Frame = 3; Tics = 4; Next state = "NULL"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom1music.ded0000644000175000017500000000254511357170242023343 0ustar keeskees# # jDoom: DOOM1 Music. # Music { ID = "None"; } Music { ID = "e1m1"; Lump = "D_E1M1"; } Music { ID = "e1m2"; Lump = "D_E1M2"; } Music { ID = "e1m3"; Lump = "D_E1M3"; } Music { ID = "e1m4"; Lump = "D_E1M4"; } Music { ID = "e1m5"; Lump = "D_E1M5"; } Music { ID = "e1m6"; Lump = "D_E1M6"; } Music { ID = "e1m7"; Lump = "D_E1M7"; } Music { ID = "e1m8"; Lump = "D_E1M8"; } Music { ID = "e1m9"; Lump = "D_E1M9"; } Music { ID = "e2m1"; Lump = "D_E2M1"; } Music { ID = "e2m2"; Lump = "D_E2M2"; } Music { ID = "e2m3"; Lump = "D_E2M3"; } Music { ID = "e2m4"; Lump = "D_E2M4"; } Music { ID = "e2m5"; Lump = "D_E2M5"; } Music { ID = "e2m6"; Lump = "D_E2M6"; } Music { ID = "e2m7"; Lump = "D_E2M7"; } Music { ID = "e2m8"; Lump = "D_E2M8"; } Music { ID = "e2m9"; Lump = "D_E2M9"; } Music { ID = "e3m1"; Lump = "D_E3M1"; } Music { ID = "e3m2"; Lump = "D_E3M2"; } Music { ID = "e3m3"; Lump = "D_E3M3"; } Music { ID = "e3m4"; Lump = "D_E3M4"; } Music { ID = "e3m5"; Lump = "D_E3M5"; } Music { ID = "e3m6"; Lump = "D_E3M6"; } Music { ID = "e3m7"; Lump = "D_E3M7"; } Music { ID = "e3m8"; Lump = "D_E3M8"; } Music { ID = "e3m9"; Lump = "D_E3M9"; } Music { ID = "inter"; Lump = "D_INTER"; } Music { ID = "intro"; Lump = "D_INTRO"; } Music { ID = "bunny"; Lump = "D_BUNNY"; } Music { ID = "victor"; Lump = "D_VICTOR"; } Music { ID = "introa"; Lump = "D_INTROA"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2skies.ded0000644000175000017500000000047311357170242023340 0ustar keeskees# # jDoom: DOOM2 Skies # Sky { ID = "sky1"; Height = 0.49; Horizon offset = -0.105; Layer 1 { Flags = enable; Texture = "SKY1"; }; } Copy Sky { ID = "sky2"; Layer 1 { Texture = "SKY2"; }; } Copy Sky { ID = "sky3"; Layer 1 { Texture = "SKY3"; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2lights.ded0000644000175000017500000000123511357170242023511 0ustar keeskees# jDoom: Light Decorations for Doom II Header { Version = 6; } # This file is skipped if not regular Doom II. SkipIf Not doom2; #####====--- LIGHT DECORATIONS FOR DOOM II ---====##### # # The default flags allow using these only with the original textures. # Use "dcf_pwad" and "dcf_ext" to allow using with PWAD and external # resources. # # There can only be one decoration per texture/flat. Newer decorations # override older ones. # # One decoration can specify up to 16 lights. # Decoration { Texture = "BSTONE3"; Light { Color { 1 .98 .9 } Offset { 33 40 } Radius = .4; Halo radius = .1; } } Copy Decoration { Texture = "BRICKLIT"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/text.ded0000644000175000017500000007656311357170242022262 0ustar keeskees# jDoom: Text Strings # # Do not change the order of these definitions! # Header { Version = 5; } Text { ID = "D_DEVSTR"; Text = "Development mode ON.\n"; } Text { ID = "D_CDROM"; Text = "CD-ROM Version: default.cfg from c:\\doomdata\n"; } Text { ID = "PRESSKEY"; Text = "Press a key."; } Text { ID = "PRESSYN"; Text = "Press %1 or %2."; } Text { ID = "QUITMSG"; Text = "Are you sure you want to\nquit this great game?"; } Text { ID = "LOADNET"; Text = "You can't load while in a net game!"; } Text { ID = "QLOADNET"; Text = "You can't quickload during a netgame!"; } Text { ID = "QSAVESPOT"; Text = "You haven't picked a quicksave slot yet!"; } Text { ID = "SAVEDEAD"; Text = "You can't save if you aren't playing!"; } Text { ID = "QSPROMPT"; Text = "Quicksave over your game named\n\n'%s'?"; } Text { ID = "QLPROMPT"; Text = "Do you want to quickload the game named\n\n'%s'?"; } Text { ID = "NEWGAME"; Text = "You can't start a new game\nwhile in a network game."; } Text { ID = "NIGHTMARE"; Text = "Are you sure? This skill level\nisn't even remotely fair."; } Text { ID = "SWSTRING"; Text = "This is the shareware version of doom.\n\nYou need to order the entire trilogy."; } Text { ID = "MSGOFF"; Text = "Messages OFF"; } Text { ID = "MSGON"; Text = "Messages ON"; } Text { ID = "NETEND"; Text = "You can't end a netgame!"; } Text { ID = "ENDGAME"; Text = "Are you sure you want to end the game?"; } Text { ID = "DOSY"; Text = "(Press %1 to quit)"; } Text { ID = "DETAILHI"; Text = "High detail"; } Text { ID = "DETAILLO"; Text = "Low detail"; } Text { ID = "GAMMALVL0"; Text = "Gamma correction OFF"; } Text { ID = "GAMMALVL1"; Text = "Gamma correction level 1"; } Text { ID = "GAMMALVL2"; Text = "Gamma correction level 2"; } Text { ID = "GAMMALVL3"; Text = "Gamma correction level 3"; } Text { ID = "GAMMALVL4"; Text = "Gamma correction level 4"; } Text { ID = "EMPTYSTRING"; Text = "Empty slot"; } Text { ID = "GOTARMOR"; Text = "Picked up the armor."; } Text { ID = "GOTMEGA"; Text = "Picked up the MegaArmor!"; } Text { ID = "GOTHTHBONUS"; Text = "Picked up a health bonus."; } Text { ID = "GOTARMBONUS"; Text = "Picked up an armor bonus."; } Text { ID = "GOTSTIM"; Text = "Picked up a stimpack."; } Text { ID = "GOTMEDINEED"; Text = "Picked up a medikit that you REALLY need!"; } Text { ID = "GOTMEDIKIT"; Text = "Picked up a medikit."; } Text { ID = "GOTSUPER"; Text = "Supercharge!"; } Text { ID = "GOTBLUECARD"; Text = "Picked up a blue keycard."; } Text { ID = "GOTYELWCARD"; Text = "Picked up a yellow keycard."; } Text { ID = "GOTREDCARD"; Text = "Picked up a red keycard."; } Text { ID = "GOTBLUESKUL"; Text = "Picked up a blue skull key."; } Text { ID = "GOTYELWSKUL"; Text = "Picked up a yellow skull key."; } Text { ID = "GOTREDSKULL"; Text = "Picked up a red skull key."; } Text { ID = "GOTINVUL"; Text = "Invulnerability!"; } Text { ID = "GOTBERSERK"; Text = "Berserk!"; } Text { ID = "GOTINVIS"; Text = "Partial Invisibility"; } Text { ID = "GOTSUIT"; Text = "Radiation Shielding Suit"; } Text { ID = "GOTMAP"; Text = "Computer Area Map"; } Text { ID = "GOTVISOR"; Text = "Light Amplification Visor"; } Text { ID = "GOTMSPHERE"; Text = "MegaSphere!"; } Text { ID = "GOTCLIP"; Text = "Picked up a clip."; } Text { ID = "GOTCLIPBOX"; Text = "Picked up a box of bullets."; } Text { ID = "GOTROCKET"; Text = "Picked up a rocket."; } Text { ID = "GOTROCKBOX"; Text = "Picked up a box of rockets."; } Text { ID = "GOTCELL"; Text = "Picked up an energy cell."; } Text { ID = "GOTCELLBOX"; Text = "Picked up an energy cell pack."; } Text { ID = "GOTSHELLS"; Text = "Picked up 4 shotgun shells."; } Text { ID = "GOTSHELLBOX"; Text = "Picked up a box of shotgun shells."; } Text { ID = "GOTBACKPACK"; Text = "Picked up a backpack full of ammo!"; } Text { ID = "GOTBFG9000"; Text = "You got the BFG9000! Oh, yes."; } Text { ID = "GOTCHAINGUN"; Text = "You got the chaingun!"; } Text { ID = "GOTCHAINSAW"; Text = "A chainsaw! Find some meat!"; } Text { ID = "GOTLAUNCHER"; Text = "You got the rocket launcher!"; } Text { ID = "GOTPLASMA"; Text = "You got the plasma gun!"; } Text { ID = "GOTSHOTGUN"; Text = "You got the shotgun!"; } Text { ID = "GOTSHOTGUN2"; Text = "You got the super shotgun!"; } Text { ID = "PD_BLUEO"; Text = "You need a %1 to activate this object"; } Text { ID = "PD_REDO"; Text = "You need a %1 to activate this object"; } Text { ID = "PD_YELLOWO"; Text = "You need a %1 to activate this object"; } Text { ID = "PD_BLUEK"; Text = "You need a %1 to open this door"; } Text { ID = "PD_REDK"; Text = "You need a %1 to open this door"; } Text { ID = "PD_YELLOWK"; Text = "You need a %1 to open this door"; } Text { ID = "GGSAVED"; Text = "Game saved."; } Text { ID = "HUSTR_MSGU"; Text = "[Message unsent]"; } Text { ID = "HUSTR_E1M1"; Text = "E1M1: Hangar"; } Text { ID = "HUSTR_E1M2"; Text = "E1M2: Nuclear Plant"; } Text { ID = "HUSTR_E1M3"; Text = "E1M3: Toxin Refinery"; } Text { ID = "HUSTR_E1M4"; Text = "E1M4: Command Control"; } Text { ID = "HUSTR_E1M5"; Text = "E1M5: Phobos Lab"; } Text { ID = "HUSTR_E1M6"; Text = "E1M6: Central Processing"; } Text { ID = "HUSTR_E1M7"; Text = "E1M7: Computer Station"; } Text { ID = "HUSTR_E1M8"; Text = "E1M8: Phobos Anomaly"; } Text { ID = "HUSTR_E1M9"; Text = "E1M9: Military Base"; } Text { ID = "HUSTR_E2M1"; Text = "E2M1: Deimos Anomaly"; } Text { ID = "HUSTR_E2M2"; Text = "E2M2: Containment Area"; } Text { ID = "HUSTR_E2M3"; Text = "E2M3: Refinery"; } Text { ID = "HUSTR_E2M4"; Text = "E2M4: Deimos Lab"; } Text { ID = "HUSTR_E2M5"; Text = "E2M5: Command Center"; } Text { ID = "HUSTR_E2M6"; Text = "E2M6: Halls of the Damned"; } Text { ID = "HUSTR_E2M7"; Text = "E2M7: Spawning Vats"; } Text { ID = "HUSTR_E2M8"; Text = "E2M8: Tower of Babel"; } Text { ID = "HUSTR_E2M9"; Text = "E2M9: Fortress of Mystery"; } Text { ID = "HUSTR_E3M1"; Text = "E3M1: Hell Keep"; } Text { ID = "HUSTR_E3M2"; Text = "E3M2: Slough of Despair"; } Text { ID = "HUSTR_E3M3"; Text = "E3M3: Pandemonium"; } Text { ID = "HUSTR_E3M4"; Text = "E3M4: House of Pain"; } Text { ID = "HUSTR_E3M5"; Text = "E3M5: Unholy Cathedral"; } Text { ID = "HUSTR_E3M6"; Text = "E3M6: Mt. Erebus"; } Text { ID = "HUSTR_E3M7"; Text = "E3M7: Limbo"; } Text { ID = "HUSTR_E3M8"; Text = "E3M8: Dis"; } Text { ID = "HUSTR_E3M9"; Text = "E3M9: Warrens"; } Text { ID = "HUSTR_E4M1"; Text = "E4M1: Hell Beneath"; } Text { ID = "HUSTR_E4M2"; Text = "E4M2: Perfect Hatred"; } Text { ID = "HUSTR_E4M3"; Text = "E4M3: Sever The Wicked"; } Text { ID = "HUSTR_E4M4"; Text = "E4M4: Unruly Evil"; } Text { ID = "HUSTR_E4M5"; Text = "E4M5: They Will Repent"; } Text { ID = "HUSTR_E4M6"; Text = "E4M6: Against Thee Wickedly"; } Text { ID = "HUSTR_E4M7"; Text = "E4M7: And Hell Followed"; } Text { ID = "HUSTR_E4M8"; Text = "E4M8: Unto The Cruel"; } Text { ID = "HUSTR_E4M9"; Text = "E4M9: Fear"; } Text { ID = "HUSTR_1"; Text = "Map 1: Entryway"; } Text { ID = "HUSTR_2"; Text = "Map 2: Underhalls"; } Text { ID = "HUSTR_3"; Text = "Map 3: The gantlet"; } Text { ID = "HUSTR_4"; Text = "Map 4: The focus"; } Text { ID = "HUSTR_5"; Text = "Map 5: The Waste Tunnels"; } Text { ID = "HUSTR_6"; Text = "Map 6: The Crusher"; } Text { ID = "HUSTR_7"; Text = "Map 7: Dead Simple"; } Text { ID = "HUSTR_8"; Text = "Map 8: Tricks and Traps"; } Text { ID = "HUSTR_9"; Text = "Map 9: The Pit"; } Text { ID = "HUSTR_10"; Text = "Map 10: Refueling Base"; } Text { ID = "HUSTR_11"; Text = "Map 11: 'O' of Destruction!"; } Text { ID = "HUSTR_12"; Text = "Map 12: The Factory"; } Text { ID = "HUSTR_13"; Text = "Map 13: Downtown"; } Text { ID = "HUSTR_14"; Text = "Map 14: The Inmost Dens"; } Text { ID = "HUSTR_15"; Text = "Map 15: Industrial Zone"; } Text { ID = "HUSTR_16"; Text = "Map 16: Suburbs"; } Text { ID = "HUSTR_17"; Text = "Map 17: Tenements"; } Text { ID = "HUSTR_18"; Text = "Map 18: The Courtyard"; } Text { ID = "HUSTR_19"; Text = "Map 19: The citadel"; } Text { ID = "HUSTR_20"; Text = "Map 20: Gotcha!"; } Text { ID = "HUSTR_21"; Text = "Map 21: Nirvana"; } Text { ID = "HUSTR_22"; Text = "Map 22: The Catacombs"; } Text { ID = "HUSTR_23"; Text = "Map 23: Barrels o' Fun"; } Text { ID = "HUSTR_24"; Text = "Map 24: The Chasm"; } Text { ID = "HUSTR_25"; Text = "Map 25: Bloodfalls"; } Text { ID = "HUSTR_26"; Text = "Map 26: The Abandoned Mines"; } Text { ID = "HUSTR_27"; Text = "Map 27: Monster Condo"; } Text { ID = "HUSTR_28"; Text = "Map 28: The Spirit World"; } Text { ID = "HUSTR_29"; Text = "Map 29: The Living End"; } Text { ID = "HUSTR_30"; Text = "Map 30: Icon of Sin"; } Text { ID = "HUSTR_31"; Text = "Map 31: Wolfenstein"; } Text { ID = "HUSTR_32"; Text = "Map 32: Grosse"; } Text { ID = "PHUSTR_1"; Text = "Map 1: Congo"; } Text { ID = "PHUSTR_2"; Text = "Map 2: Well of Souls"; } Text { ID = "PHUSTR_3"; Text = "Map 3: Aztec"; } Text { ID = "PHUSTR_4"; Text = "Map 4: Caged"; } Text { ID = "PHUSTR_5"; Text = "Map 5: Ghost Town"; } Text { ID = "PHUSTR_6"; Text = "Map 6: Baron's Lair"; } Text { ID = "PHUSTR_7"; Text = "Map 7: Caughtyard"; } Text { ID = "PHUSTR_8"; Text = "Map 8: Realm"; } Text { ID = "PHUSTR_9"; Text = "Map 9: Abattoire"; } Text { ID = "PHUSTR_10"; Text = "Map 10: Onslaught"; } Text { ID = "PHUSTR_11"; Text = "Map 11: Hunted"; } Text { ID = "PHUSTR_12"; Text = "Map 12: Speed"; } Text { ID = "PHUSTR_13"; Text = "Map 13: The Crypt"; } Text { ID = "PHUSTR_14"; Text = "Map 14: Genesis"; } Text { ID = "PHUSTR_15"; Text = "Map 15: The Twilight"; } Text { ID = "PHUSTR_16"; Text = "Map 16: The Omen"; } Text { ID = "PHUSTR_17"; Text = "Map 17: Compound"; } Text { ID = "PHUSTR_18"; Text = "Map 18: Neurosphere"; } Text { ID = "PHUSTR_19"; Text = "Map 19: Nme"; } Text { ID = "PHUSTR_20"; Text = "Map 20: The Death Domain"; } Text { ID = "PHUSTR_21"; Text = "Map 21: Slayer"; } Text { ID = "PHUSTR_22"; Text = "Map 22: Impossible Mission"; } Text { ID = "PHUSTR_23"; Text = "Map 23: Tombstone"; } Text { ID = "PHUSTR_24"; Text = "Map 24: The Final Frontier"; } Text { ID = "PHUSTR_25"; Text = "Map 25: The Temple of Darkness"; } Text { ID = "PHUSTR_26"; Text = "Map 26: Bunker"; } Text { ID = "PHUSTR_27"; Text = "Map 27: Anti-Christ"; } Text { ID = "PHUSTR_28"; Text = "Map 28: The Sewers"; } Text { ID = "PHUSTR_29"; Text = "Map 29: Odyssey of Noises"; } Text { ID = "PHUSTR_30"; Text = "Map 30: The Gateway of Hell"; } Text { ID = "PHUSTR_31"; Text = "Map 31: Cyberden"; } Text { ID = "PHUSTR_32"; Text = "Map 32: Go 2 It"; } Text { ID = "THUSTR_1"; Text = "Map 1: System Control"; } Text { ID = "THUSTR_2"; Text = "Map 2: Human BBQ"; } Text { ID = "THUSTR_3"; Text = "Map 3: Power Control"; } Text { ID = "THUSTR_4"; Text = "Map 4: Wormhole"; } Text { ID = "THUSTR_5"; Text = "Map 5: Hanger"; } Text { ID = "THUSTR_6"; Text = "Map 6: Open Season"; } Text { ID = "THUSTR_7"; Text = "Map 7: Prison"; } Text { ID = "THUSTR_8"; Text = "Map 8: Metal"; } Text { ID = "THUSTR_9"; Text = "Map 9: Stronghold"; } Text { ID = "THUSTR_10"; Text = "Map 10: Redemption"; } Text { ID = "THUSTR_11"; Text = "Map 11: Storage Facility"; } Text { ID = "THUSTR_12"; Text = "Map 12: Crater"; } Text { ID = "THUSTR_13"; Text = "Map 13: Nukage Processing"; } Text { ID = "THUSTR_14"; Text = "Map 14: Steel Works"; } Text { ID = "THUSTR_15"; Text = "Map 15: Dead Zone"; } Text { ID = "THUSTR_16"; Text = "Map 16: Deepest Reaches"; } Text { ID = "THUSTR_17"; Text = "Map 17: Processing Area"; } Text { ID = "THUSTR_18"; Text = "Map 18: Mill"; } Text { ID = "THUSTR_19"; Text = "Map 19: Shipping/Respawning"; } Text { ID = "THUSTR_20"; Text = "Map 20: Central Processing"; } Text { ID = "THUSTR_21"; Text = "Map 21: Administration Center"; } Text { ID = "THUSTR_22"; Text = "Map 22: Habitat"; } Text { ID = "THUSTR_23"; Text = "Map 23: Lunar Mining Project"; } Text { ID = "THUSTR_24"; Text = "Map 24: Quarry"; } Text { ID = "THUSTR_25"; Text = "Map 25: Baron's Den"; } Text { ID = "THUSTR_26"; Text = "Map 26: Ballistyx"; } Text { ID = "THUSTR_27"; Text = "Map 27: Mount Pain"; } Text { ID = "THUSTR_28"; Text = "Map 28: Heck"; } Text { ID = "THUSTR_29"; Text = "Map 29: River Styx"; } Text { ID = "THUSTR_30"; Text = "Map 30: Last Call"; } Text { ID = "THUSTR_31"; Text = "Map 31: Pharaoh"; } Text { ID = "THUSTR_32"; Text = "Map 32: Caribbean"; } Text { ID = "HUSTR_CHATMACRO0"; Text = "No"; } Text { ID = "HUSTR_CHATMACRO1"; Text = "I'm ready to kick butt!"; } Text { ID = "HUSTR_CHATMACRO2"; Text = "I'm OK."; } Text { ID = "HUSTR_CHATMACRO3"; Text = "I'm not looking too good!"; } Text { ID = "HUSTR_CHATMACRO4"; Text = "Help!"; } Text { ID = "HUSTR_CHATMACRO5"; Text = "You suck!"; } Text { ID = "HUSTR_CHATMACRO6"; Text = "Next time, scumbag..."; } Text { ID = "HUSTR_CHATMACRO7"; Text = "Come here!"; } Text { ID = "HUSTR_CHATMACRO8"; Text = "I'll take care of it."; } Text { ID = "HUSTR_CHATMACRO9"; Text = "Yes"; } Text { ID = "HUSTR_TALKTOSELF1"; Text = "You mumble to yourself"; } Text { ID = "HUSTR_TALKTOSELF2"; Text = "Who's there?"; } Text { ID = "HUSTR_TALKTOSELF3"; Text = "You scare yourself"; } Text { ID = "HUSTR_TALKTOSELF4"; Text = "You start to rave"; } Text { ID = "HUSTR_TALKTOSELF5"; Text = "You've lost it..."; } Text { ID = "HUSTR_MESSAGESENT"; Text = "[Message Sent]"; } Text { ID = "HUSTR_PLRGREEN"; Text = "Green: "; } Text { ID = "HUSTR_PLRINDIGO"; Text = "Indigo: "; } Text { ID = "HUSTR_PLRBROWN"; Text = "Brown: "; } Text { ID = "HUSTR_PLRRED"; Text = "Red: "; } Text { ID = "AMSTR_FOLLOWON"; Text = "Follow Mode ON"; } Text { ID = "AMSTR_FOLLOWOFF"; Text = "Follow Mode OFF"; } Text { ID = "AMSTR_GRIDON"; Text = "Grid ON"; } Text { ID = "AMSTR_GRIDOFF"; Text = "Grid OFF"; } Text { ID = "AMSTR_MARKEDSPOT"; Text = "Marked Spot"; } Text { ID = "AMSTR_MARKSCLEARED"; Text = "All Marks Cleared"; } Text { ID = "STSTR_MUS"; Text = "Music Change"; } Text { ID = "STSTR_NOMUS"; Text = "Impossible selection"; } Text { ID = "STSTR_DQDON"; Text = "Degreelessness Mode On"; } Text { ID = "STSTR_DQDOFF"; Text = "Degreelessness Mode Off"; } Text { ID = "STSTR_KFAADDED"; Text = "Very Happy Ammo added"; } Text { ID = "STSTR_FAADDED"; Text = "Ammo (no keys) added"; } Text { ID = "STSTR_NCON"; Text = "No clipping mode ON"; } Text { ID = "STSTR_NCOFF"; Text = "No clipping mode OFF"; } Text { ID = "STSTR_BEHOLD"; Text = "inVuln, Str, Inviso, Rad, Allmap, or Lite-amp"; } Text { ID = "STSTR_BEHOLDX"; Text = "Power-up toggled"; } Text { ID = "STSTR_CHOPPERS"; Text = "... doesn't suck - GM"; } Text { ID = "STSTR_CLEV"; Text = "Changing map..."; } Text { ID = "E1TEXT"; Text = "Once you beat the big badasses and\n clean out the moon base you're supposed\n to win, aren't you? Aren't you? Where's\n your fat reward and ticket home? What\n the hell is this? It's not supposed to\n end this way!\n\n It stinks like rotten meat, but looks\n like the lost Deimos base. Looks like\n you're stuck on The Shores of Hell.\n The only way out is through.\n\n To continue the DOOM experience, play\n The Shores of Hell and its amazing\n sequel, Inferno!\n"; } Text { ID = "E2TEXT"; Text = "You've done it! The hideous cyber-\n demon lord that ruled the lost Deimos\n moon base has been slain and you\n are triumphant! But ... where are\n you? You clamber to the edge of the\n moon and look down to see the awful\n truth.\n\n Deimos floats above Hell itself!\n You've never heard of anyone escaping\n from Hell, but you'll make the bastards\n sorry they ever heard of you! Quickly,\n you rappel down to the surface of\n Hell.\n\n Now, it's on to the final chapter of\n DOOM! -- Inferno."; } Text { ID = "E3TEXT"; Text = "The loathsome spiderdemon that\n masterminded the invasion of the moon\n bases and caused so much death has had\n its ass kicked for all time.\n\n A hidden doorway opens and you enter.\n You've proven too tough for Hell to\n contain, and now Hell at last plays\n fair -- for you emerge from the door\n to see the green fields of Earth!\n Home at last.\n\n You wonder what's been happening on\n Earth while you were battling evil\n unleashed. It's good that no Hell-\n spawn could have come through that\n door with you ..."; } Text { ID = "E4TEXT"; Text = "The spider mastermind must have sent forth\n its legions of hellspawn before your\n final confrontation with that terrible\n beast from hell. But you stepped forward\n and brought forth eternal damnation and\n suffering upon the horde as a true hero\n would in the face of something so evil.\n\n Besides, someone was gonna pay for what\n happened to daisy, your pet rabbit.\n\n But now, you see spread before you more\n potential pain and gibbitude as a nation\n of demons run amok among our cities.\n\n next stop, hell on earth!"; } Text { ID = "C1TEXT"; Text = "You have entered deeply into the infested\n starport. But something is wrong. The\n monsters have brought their own reality\n with them, and the starport's technology\n is being subverted by their presence.\n\n Ahead, you see an outpost of Hell, a\n fortified zone. If you can get past it,\n you can penetrate into the haunted heart\n of the starbase and find the controlling\n switch which holds Earth's population\n hostage."; } Text { ID = "C2TEXT"; Text = "You have won! Your victory has enabled\n humankind to evacuate Earth and escape\n the nightmare. Now you are the only\n human left on the face of the planet.\n Cannibal mutations, carnivorous aliens,\n and evil spirits are your only neighbors.\n You sit back and wait for death, content\n that you have saved your species.\n\n But then, Earth Control beams down a\n message from space: \"Sensors have located\n the source of the alien invasion. If you\n go there, you may be able to block their\n entry. The alien base is in the heart of\n your own home city, not far from the\n starport.\" Slowly and painfully you get\n up and return to the fray."; } Text { ID = "C3TEXT"; Text = "You are at the corrupt heart of the city,\n surrounded by the corpses of your enemies.\n You see no way to destroy the creatures'\n entryway on this side, so you clench your\n teeth and plunge through it.\n\n There must be a way to close it on the\n other side. What do you care if you've\n got to go through Hell to get to it?"; } Text { ID = "C4TEXT"; Text = "The horrendous visage of the biggest\n demon you've ever seen crumbles before\n you, after you pump your rockets into\n his exposed brain. The monster shrivels\n up and dies, its thrashing limbs\n devastating untold miles of Hell's\n surface.\n\n You've done it. The invasion is over.\n Earth is saved. Hell is a wreck. You\n wonder where bad folks will go when they\n die, now. Wiping the sweat from your\n forehead you begin the long trek back\n home. Rebuilding Earth ought to be a\n lot more fun than ruining it was."; } Text { ID = "C5TEXT"; Text = "Congratulations, you've found the secret\n level! Looks like it's been built by\n humans, rather than demons. You wonder\n who the inmates of this corner of Hell\n will be."; } Text { ID = "C6TEXT"; Text = "Congratulations, you've found the\n super secret level! You'd better\n blaze through this one!\n"; } Text { ID = "P1TEXT"; Text = "You gloat over the steaming carcass of the\n Guardian. With its death, you've wrested\n the Accelerator from the stinking claws\n of Hell. You relax and glance around the\n room. Damn! There was supposed to be at\n least one working prototype, but you can't\n see it. The demons must have taken it.\n\n You must find the prototype, or all your\n struggles will have been wasted. Keep\n moving, keep fighting, keep killing.\n Oh yes, keep living, too."; } Text { ID = "P2TEXT"; Text = "Even the deadly Arch-Vile labyrinth could\n not stop you, and you've gotten to the\n prototype Accelerator which is soon\n efficiently and permanently deactivated.\n\n You're good at that kind of thing."; } Text { ID = "P3TEXT"; Text = "You've bashed and battered your way into\n the heart of the devil-hive. Time for a\n Search-and-Destroy mission, aimed at the\n Gatekeeper, whose foul offspring is\n cascading to Earth. Yeah, he's bad. But\n you know who's worse!\n\n Grinning evilly, you check your gear, and\n get ready to give the bastard a little Hell\n of your own making!"; } Text { ID = "P4TEXT"; Text = "The Gatekeeper's evil face is splattered\n all over the place. As its tattered corpse\n collapses, an inverted Gate forms and\n sucks down the shards of the last\n prototype Accelerator, not to mention the\n few remaining demons. You're done. Hell\n has gone back to pounding bad dead folks\n instead of good live ones. Remember to\n tell your grandkids to put a rocket\n launcher in your coffin. If you go to Hell\n when you die, you'll need it for some\n final cleaning-up..."; } Text { ID = "P5TEXT"; Text = "You've found the second-hardest level we\n got. Hope you have a saved game a level or\n two previous. If not, be prepared to die\n aplenty. For master marines only."; } Text { ID = "P6TEXT"; Text = "Betcha wondered just what WAS the hardest\n level we had ready for ya? Now you know.\n No one gets out alive."; } Text { ID = "T1TEXT"; Text = "You've fought your way out of the infested\n experimental labs. It seems that UAC has\n once again gulped it down. With their\n high turnover, it must be hard for poor\n old UAC to buy corporate health insurance\n nowadays...\n\n Ahead lies the military complex, now\n swarming with diseased horrors hot to get\n their teeth into you. With luck, the\n complex still has some warlike ordnance\n laying around."; } Text { ID = "T2TEXT"; Text = "You hear the grinding of heavy machinery\n ahead. You sure hope they're not stamping\n out new hellspawn but you're ready to\n ream out a whole herd if you have to.\n They might be planning a blood feast but\n you feel about as mean as two thousand\n maniacs packed into one mad killer.\n\n You don't plan to go down easy."; } Text { ID = "T3TEXT"; Text = "The vista opening ahead looks real damn\n familiar. Smells familiar, too -- like\n fried excrement. You didn't like this\n place before, and you sure as hell ain't\n planning to like it now. The more you\n brood on it, the madder you get.\n Hefting your gun, an evil grin trickles\n onto your face. Time to take some names."; } Text { ID = "T4TEXT"; Text = "Suddenly, all is silent, from one horizon\n to the other. The agonizing echo of Hell\n fades away, the nightmare sky turns to\n blue, the heaps of monster corpses start\n to evaporate along with the evil stench\n that filled the air. Jeeze, maybe you've\n done it. Have you really won?\n\n Something rumbles in the distance.\n A blue light begins to glow inside the\n ruined skull of the demon-spitter."; } Text { ID = "T5TEXT"; Text = "What now? Looks totally different. Kind\n of like King Tut's condo. Well,\n whatever's here can't be any worse\n than usual. Can it? Or maybe it's best\n to let sleeping gods lie..."; } Text { ID = "T6TEXT"; Text = "Time for a vacation. You've burst the\n bowels of hell and by golly you're ready\n for a break. You mutter to yourself,\n \"Maybe someone else can kick Hell's ass\n next time around\". Ahead lies a quiet town,\n with peaceful flowing water, quaint\n buildings, and presumably no Hellspawn.\n\n As you step off the transport, you hear\n the stomp of a cyberdemon's iron shoe."; } Text { ID = "CC_ZOMBIE"; Text = "Zombieman"; } Text { ID = "CC_SHOTGUN"; Text = "Shotgun Guy"; } Text { ID = "CC_HEAVY"; Text = "Heavy Weapon Dude"; } Text { ID = "CC_IMP"; Text = "Imp"; } Text { ID = "CC_DEMON"; Text = "Demon"; } Text { ID = "CC_LOST"; Text = "Lost Soul"; } Text { ID = "CC_CACO"; Text = "Cacodemon"; } Text { ID = "CC_HELL"; Text = "Hell Knight"; } Text { ID = "CC_BARON"; Text = "Baron of Hell"; } Text { ID = "CC_ARACH"; Text = "Arachnotron"; } Text { ID = "CC_PAIN"; Text = "Pain Elemental"; } Text { ID = "CC_REVEN"; Text = "Revenant"; } Text { ID = "CC_MANCU"; Text = "Mancubus"; } Text { ID = "CC_ARCH"; Text = "Arch-Vile"; } Text { ID = "CC_SPIDER"; Text = "The Spider Mastermind"; } Text { ID = "CC_CYBER"; Text = "The Cyberdemon"; } Text { ID = "CC_HERO"; Text = "Our hero"; } Text { ID = "QUITMESSAGE1"; Text = "Please don't leave, there's more\ndemons to toast!"; } Text { ID = "QUITMESSAGE2"; Text = "Let's beat it -- this is turning\ninto a bloodbath!"; } Text { ID = "QUITMESSAGE3"; Text = "I wouldn't leave if I were you.\nWindows is much worse."; } Text { ID = "QUITMESSAGE4"; Text = "You're trying to say you like Windows\nbetter than me, right?"; } Text { ID = "QUITMESSAGE5"; Text = "Don't leave yet -- there's a\ndemon around that corner!"; } Text { ID = "QUITMESSAGE6"; Text = "Ya know, next time you come in here\nI'm gonna toast ya."; } Text { ID = "QUITMESSAGE7"; Text = "Go ahead and leave. See if I care."; } Text { ID = "QUITMESSAGE8"; Text = "You want to quit?\nThen, thou hast lost an eighth!"; } Text { ID = "QUITMESSAGE9"; Text = "Don't go now, there's a \nDimensional Shambler waiting\n at the Windows desktop!"; } Text { ID = "QUITMESSAGE10"; Text = "Get outta here and go back\nto your boring programs."; } Text { ID = "QUITMESSAGE11"; Text = "If i were your boss, I'd \n deathmatch ya in a minute!"; } Text { ID = "QUITMESSAGE12"; Text = "Look, bud. you leave now\nand you forfeit your body count!"; } Text { ID = "QUITMESSAGE13"; Text = "Just leave. when you come\nback, I'll be waiting with a bat."; } Text { ID = "QUITMESSAGE14"; Text = "You're lucky I don't smack\nyou for thinking about leaving."; } Text { ID = "QUITMESSAGE15"; Text = "Prescience of mind is\nno substitute for courage."; } Text { ID = "QUITMESSAGE16"; Text = "Tired you may be...\nbut the only tired spawn\nis dead spawn."; } Text { ID = "QUITMESSAGE17"; Text = "Return as an apostate to be\neternally welcomed."; } Text { ID = "QUITMESSAGE18"; Text = "To abandon the cause\ncan only presage disaster."; } Text { ID = "QUITMESSAGE19"; Text = "Death becomes you:\nplease return...."; } Text { ID = "QUITMESSAGE20"; Text = "Dost the demesne win?\nDost its inhabitants prevail?\n Is this the end?"; } Text { ID = "QUITMESSAGE21"; Text = "To quit is to lose."; } Text { ID = "QUITMESSAGE22"; Text = "Escape if you will, but these\ndark corridors haunt you forever..."; } Text { ID = "JOINNET"; Text = "You're already in a network game!"; } Text { ID = "SAVENET"; Text = "You can't save while in a net game!"; } Text { ID = "CLNETLOAD"; Text = "Server loading saved game..."; } Text { ID = "LOADMISSING"; Text = "You weren't in the server's savegame."; } Text { ID = "FINALEFLAT_E1"; Text = "FLOOR4_8"; } Text { ID = "FINALEFLAT_E2"; Text = "SFLR6_1"; } Text { ID = "FINALEFLAT_E3"; Text = "MFLR8_4"; } Text { ID = "FINALEFLAT_E4"; Text = "MFLR8_3"; } Text { ID = "FINALEFLAT_C2"; Text = "RROCK14"; } Text { ID = "FINALEFLAT_C1"; Text = "SLIME16"; } Text { ID = "FINALEFLAT_C3"; Text = "RROCK07"; } Text { ID = "FINALEFLAT_C4"; Text = "RROCK17"; } Text { ID = "FINALEFLAT_C5"; Text = "RROCK13"; } Text { ID = "FINALEFLAT_C6"; Text = "RROCK19"; } Text { ID = "ASK_EPISODE"; Text = "Choose Episode:"; } Text { ID = "EPISODE1"; Text = "Knee-Deep In The Dead"; } Text { ID = "EPISODE2"; Text = "The Shores Of Hell"; } Text { ID = "EPISODE3"; Text = "Inferno"; } Text { ID = "EPISODE4"; Text = "Thy Flesh Consumed"; } Text { ID = "KILLMSG_SUICIDE"; Text = "%1 commits suicide!"; } Text { ID = "KILLMSG_WEAPON0"; Text = "%1 beat %2 with bare hands!"; } Text { ID = "KILLMSG_PISTOL"; Text = "%2 was gunned down by %1."; } Text { ID = "KILLMSG_SHOTGUN"; Text = "%1 shot %2 to bloody bits."; } Text { ID = "KILLMSG_CHAINGUN"; Text = "%2 was poisoned by %1's lead."; } Text { ID = "KILLMSG_MISSILE"; Text = "%2 rode %1's rocket. Splat!"; } Text { ID = "KILLMSG_PLASMA"; Text = "%2 got burnt in %1's plasma."; } Text { ID = "KILLMSG_BFG"; Text = "%2 was scorched by %1's BFG!"; } Text { ID = "KILLMSG_CHAINSAW"; Text = "%1 slaughtered %2 with a buzz!"; } Text { ID = "KILLMSG_SUPERSHOTGUN"; Text = "%1 blasted %2 to tiny bits."; } Text { ID = "KILLMSG_STOMP"; Text = "%1 stomped %2!!"; } Text { ID = "AMSTR_ROTATEON"; Text = "Rotate mode ON"; } Text { ID = "AMSTR_ROTATEOFF"; Text = "Rotate mode OFF"; } Text { ID = "WEAPON1"; Text = "Fist"; } Text { ID = "WEAPON2"; Text = "Pistol"; } Text { ID = "WEAPON3"; Text = "Shotgun"; } Text { ID = "WEAPON4"; Text = "Chaingun"; } Text { ID = "WEAPON5"; Text = "Rocket Launcher"; } Text { ID = "WEAPON6"; Text = "Plasma Rifle"; } Text { ID = "WEAPON7"; Text = "BFG 9000"; } Text { ID = "WEAPON8"; Text = "Chainsaw"; } Text { ID = "WEAPON9"; Text = "Super Shotgun"; } Text { ID = "SKILL1"; Text = "I'm too young to die."; } Text { ID = "SKILL2"; Text = "Hey, not too rough."; } Text { ID = "SKILL3"; Text = "Hurt me plenty."; } Text { ID = "SKILL4"; Text = "Ultra-Violence."; } Text { ID = "SKILL5"; Text = "Nightmare!"; } Text { ID = "KEY1"; Text = "Blue Keycard"; } Text { ID = "KEY2"; Text = "Yellow Keycard"; } Text { ID = "KEY3"; Text = "Red Keycard"; } Text { ID = "KEY4"; Text = "Blue Skull Key"; } Text { ID = "KEY5"; Text = "Yellow Skull Key"; } Text { ID = "KEY6"; Text = "Red Skull Key"; } Text { ID = "SAVEOUTMAP"; Text = "You can't save if you aren't in a map!"; } Text { ID = "ENDNOGAME"; Text = "You can't end a game that hasn't even begun!"; } Text { ID = "SUICIDEOUTMAP"; Text = "You can't suicide if you aren't in a map!"; } Text { ID = "SUICIDEASK"; Text = "Are you sure you want to suicide?"; } Text { ID = "PICKGAMETYPE"; Text = "Choose game type"; } Text { ID = "SINGLEPLAYER"; Text = "Singleplayer"; } Text { ID = "MULTIPLAYER"; Text = "Multiplayer"; } Text { ID = "NOTDESIGNEDFOR"; Text = "Not designed for %1."; } Text { ID = "GAMESETUP"; Text = "Game Setup"; } Text { ID = "PLAYERSETUP"; Text = "Player Setup"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/jdoom.ded0000644000175000017500000000120511357170242022363 0ustar keeskees# # -=- jDoom Definitions -=- # # This file is overwritten on every upgrade. Add custom definitions # to User.ded. # # For information about DED syntax and semantics, see Doc\DEDDoc.txt. # Header { Version = 5; Default model scale = 1.2; Model path = "data\jdoom\models"; } Include "flags.ded"; Include "objects.ded"; Include "sprites.ded"; Include "materials.ded"; Include "anim.ded"; Include "audio.ded"; Include "special.ded"; Include "lights.ded"; Include "skies.ded"; Include "maps.ded"; Include "finales.ded"; Include "text.ded"; Include "values.ded"; Include "models.ded"; Include "user.ded"; IncludeIf Not -noauto "auto\*.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom2-tntmaps.ded0000644000175000017500000000633411357170242023767 0ustar keeskees# # jDoom: TNT Maps # # The default definition, used for any maps without a map info definition. Map Info { ID = "*"; Author = "Unknown"; Music = "runnin"; Gravity = 1; Sky = "sky1"; } Map Info { ID = "MAP01"; Name = "THUSTR_1"; Author = "Team TNT"; Music = "runnin"; Par time = 30; Gravity = 1; Sky = "sky1"; } Copy Map Info { ID = "MAP02"; Name = "THUSTR_2"; Music = "stalks"; Par time = 90; } Copy Map Info { ID = "MAP03"; Name = "THUSTR_3"; Music = "countd"; Par time = 120; } Copy Map Info { ID = "MAP04"; Name = "THUSTR_4"; Music = "betwee"; Par time = 120; } Copy Map Info { ID = "MAP05"; Name = "THUSTR_5"; Music = "doom"; Par time = 90; } Copy Map Info { ID = "MAP06"; Name = "THUSTR_6"; Music = "the_da"; Par time = 150; } Copy Map Info { ID = "MAP07"; Name = "THUSTR_7"; Music = "shawn"; Par time = 120; } Copy Map Info { ID = "MAP08"; Name = "THUSTR_8"; Music = "ddtblu"; Par time = 120; } Copy Map Info { ID = "MAP09"; Name = "THUSTR_9"; Music = "in_cit"; Par time = 270; } Copy Map Info { ID = "MAP10"; Name = "THUSTR_10"; Music = "dead"; Par time = 90; } Copy Map Info { ID = "MAP11"; Name = "THUSTR_11"; Music = "stlks2"; Par time = 210; } Copy Map Info { ID = "MAP12"; Name = "THUSTR_12"; Music = "theda2"; Par time = 150; Sky = "sky2"; } Copy Map Info { ID = "MAP13"; Name = "THUSTR_13"; Music = "doom2"; Par time = 150; } Copy Map Info { ID = "MAP14"; Name = "THUSTR_14"; Music = "ddtbl2"; Par time = 150; } Copy Map Info { ID = "MAP15"; Name = "THUSTR_15"; Music = "runni2"; Par time = 210; } Copy Map Info { ID = "MAP16"; Name = "THUSTR_16"; Music = "dead2"; Par time = 150; } Copy Map Info { ID = "MAP17"; Name = "THUSTR_17"; Music = "stlks3"; Par time = 420; } Copy Map Info { ID = "MAP18"; Name = "THUSTR_18"; Music = "romero"; Par time = 150; } Copy Map Info { ID = "MAP19"; Name = "THUSTR_19"; Music = "shawn2"; Par time = 210; } Copy Map Info { ID = "MAP20"; Name = "THUSTR_20"; Music = "messag"; Par time = 150; } Copy Map Info { ID = "MAP21"; Name = "THUSTR_21"; Music = "in_cit"; Par time = 240; Sky = "sky3"; } Copy Map Info { ID = "MAP22"; Name = "THUSTR_22"; Music = "ddtbl3"; Par time = 150; } Copy Map Info { ID = "MAP23"; Name = "THUSTR_23"; Music = "ampie"; Par time = 180; } Copy Map Info { ID = "MAP24"; Name = "THUSTR_24"; Music = "theda3"; Par time = 150; } Copy Map Info { ID = "MAP25"; Name = "THUSTR_25"; Music = "adrian"; Par time = 150; } Copy Map Info { ID = "MAP26"; Name = "THUSTR_26"; Music = "messg2"; Par time = 300; } Copy Map Info { ID = "MAP27"; Name = "THUSTR_27"; Music = "romer2"; Par time = 330; } Copy Map Info { ID = "MAP28"; Name = "THUSTR_28"; Music = "tense"; Par time = 420; } Copy Map Info { ID = "MAP29"; Name = "THUSTR_29"; Music = "shawn3"; Par time = 300; } Copy Map Info { ID = "MAP30"; Name = "THUSTR_30"; Music = "openin"; Par time = 180; } Copy Map Info { ID = "MAP31"; Name = "THUSTR_31"; Music = "evil"; Par time = 120; } Copy Map Info { ID = "MAP32"; Name = "THUSTR_32"; Music = "ultima"; Par time = 30; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/finales.ded0000644000175000017500000001024411357170242022677 0ustar keeskees# jDoom: Intermissions and Finales # (see Doc\InFine.txt) Header { Version = 5; } InFine { ID = "title"; Script { # There is no skipping during the titlescreen loop. NoSkip # Any event shows the menu. Trigger MARKER title_loop # Step 1. Patch back 0 0 "TITLEPIC" IF commercial DO MusicOnce "dm2ttl" Wait 13 # Original was 11; this'll play the whole song. ; ELSE DO MusicOnce "intro" Wait 4.857 # Original wait is 170 tics. ; # Step 2. IF MODE:doom1-share PlayDemo "sdemo1.cdm" IF MODE:doom1 PlayDemo "rdemo1.cdm" IF MODE:doom1-ultimate PlayDemo "udemo1.cdm" IF MODE:doom2 PlayDemo "2demo1.cdm" IF MODE:doom2-plut PlayDemo "pdemo1.cdm" IF MODE:doom2-tnt PlayDemo "tdemo1.cdm" # Step 3. Set back "CREDIT" Wait 5.714 # Original is 200 tics. # Step 4. IF MODE:doom1-share PlayDemo "sdemo2.cdm" IF MODE:doom1 PlayDemo "rdemo2.cdm" IF MODE:doom1-ultimate PlayDemo "udemo2.cdm" IF MODE:doom2 PlayDemo "2demo2.cdm" IF MODE:doom2-plut PlayDemo "pdemo2.cdm" IF MODE:doom2-tnt PlayDemo "tdemo2.cdm" # Step 5. IF commercial DO Set back "TITLEPIC" Music "dm2ttl" Wait 13 # Original was 11. ; ELSE DO IF ultimate Set back "CREDIT" ELSE Set back "HELP2" Wait 5.714 # 200 tics. ; # Step 6. IF MODE:doom1-share PlayDemo "sdemo3.cdm" IF MODE:doom1 PlayDemo "rdemo3.cdm" IF MODE:doom1-ultimate PlayDemo "udemo3.cdm" IF MODE:doom2 PlayDemo "2demo3.cdm" IF MODE:doom2-plut PlayDemo "pdemo3.cdm" IF MODE:doom2-tnt PlayDemo "tdemo3.cdm" # Step 7. IF ultimate PlayDemo "udemo4.cdm" GOTO title_loop }; } InFine { ID = "imp"; Script { NoSkip # No background. ColorAlpha 0 0 0 0 # Init objects. Rect info_box 68 28 0 0 FillColor info_box BOTH 0 .4 0 0 EdgeColor info_box BOTH 1 1 1 0 Rect box 98 8 0 0 FillColor box BOTH 0 .4 0 .25 EdgeColor box BOTH 0 1 0 .3 Patch imp 66 56 "TROOA1" RGB imp .3 1 .3 Scale imp .8 Alpha imp 0 # Light text for highlights. PreColor 1 .6 1 .6 # Open the boxes. In 1 FillColor box BOTH 0 .4 0 .4 EdgeColor box BOTH 0 1 0 .2 ScaleXY box 170 145 In .3 FillColor info_box TOP 0 .4 0 .3 FillColor info_box BOTTOM 0 .2 0 .4 EdgeColor info_box BOTH 0 1 0 .3 Scale info_box 40 X info_box 48 Y info_box 8 Wait .3 In .25 Sy info_box 60 Wait .25 In .5 Alpha imp 1 Wait .5 # Show info. Text name 103 13 "The \1Imp\0 Monster" In 0 RGB name 0 .8 0; Scale name .8 FontB name Wait 1 Text desc 103 32 "Beware this \1highly dangerous\0\n monster! Don't be fooled by\n it's friendly-looking grin.\W\n It will hurl \1fireballs\0 at you,\n and they burn!\W\W\n\n Oh, how they \1burn\0!\W\W\n\n Imp, imp, burning bright\n In the forests of the night.\n What immortal hand or eye\n Could frame thy \1fearful\n symmetry\0?" In 0 RGB desc 0 .8 0; Scale desc .75 Wait 15.5 In .5 Precolor 1 1 .8 .3 ColorAlpha 1 .8 .3 .2 Wait .8 In .5 Precolor 1 .6 1 .6 ColorAlpha 0 0 0 0 WaitText desc Wait 5 In .5 Alpha imp 0 Alpha name 0 Alpha desc 0 Wait .5 In .3 FillColor info_box BOTH 0 .4 0 0 FillColor box BOTH 0 .4 0 0 Sy info_box 0 Sy box 0 Wait .3 # Imp scare. In 1 RGB imp 1 1 1 Alpha imp 1 Wait .5 Sound "firsht" In 5 X imp 80 Y imp 500 Scale imp 10 Angle imp 45 Wait 1.5 Sound "bgsit1" Wait 3 SoundAt "pldeth" .5 In .5 Alpha imp 0 Wait .5 CanSkip }; } IncludeIf doom1 "doom1finales.ded"; IncludeIf doom1-share "doom1finales.ded"; IncludeIf doom1-ultimate "doom1finales.ded"; IncludeIf doom2 "doom2finales.ded"; IncludeIf doom2-tnt "doom2-tntfinales.ded"; IncludeIf doom2-plut "doom2-plutfinales.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/doom1finales.ded0000644000175000017500000000514111357170242023637 0ustar keeskees# jDoom: Intermissions and Finales (DOOM) # (see Doc\InFine.txt) Header { Version = 5; } # I'm using "textdef" to allow compatibility with DeHackEd. # A better way would just be to use "text" and define the text # in the script, no need to go about modifying the Text defs. ######======------ SHAREWARE/REG/ULTIMATE DOOM ------======###### # Episode I: Knee-Deep In The Dead Finale { After = "E1M8"; Script { NoSkip # This is the end, no more levels after this. Music "victor" Flat FLOOR4_8 Wait 0.5 TextDef msg 10 10 "E1TEXT" WaitText msg Wait 7 # The original TEXTWAIT is 250 tics. # Show shareware/registered or credits. NoFlat DelText msg IF ultimate Patch back 0 0 CREDIT ELSE Patch back 0 0 HELP2 }; } # The rest of this file is skipped if DOOM - shareware. SkipIf doom1-share; # Episode II: The Shores Of Hell Finale { After = "E2M8"; Script { noskip; # This is the end, no more levels after this. music "victor"; flat SFLR6_1; wait 0.5; textdef msg 10 10 "E2TEXT"; waittext msg; wait 7; # The original TEXTWAIT is 250 tics. # Fade to the Deimos picture. patch back 0 0 VICTORY2; alpha back 0; in 2 alpha back 1; textalpha msg 0; wait 2; deltext msg; noflat; }; } # Episode III: Inferno Finale { After = "E3M8"; Script { noskip # This is the end, no more levels after this. music "victor" flat MFLR8_4 wait 0.5 textdef msg 10 10 "E3TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. deltext msg # The bunny scroll. noflat; music "bunny" patch b1 320 0 PFUB1 patch b2 0 0 PFUB2 offx 320 wait 6.5 # Start scrolling to the left. in 18.3 offx 0; wait 18.3 # The End. wait 7 patch theend 108 68 END0 wait 1.43 # 50 tics. sound "pistol"; set theend END1; wait 0.14 sound "pistol"; set theend END2; wait 0.14 sound "pistol"; set theend END3; wait 0.14 sound "pistol"; set theend END4; wait 0.14 sound "pistol"; set theend END5; wait 0.14 sound "pistol"; set theend END6 }; } # The rest of this file is skipped if not DOOM - ultimate. SkipIf Not doom1-ultimate; # Episode IV: Thy Flesh Consumed Finale { After = "E4M8"; Script { noskip # This is the end, no more levels after this. music "victor" flat MFLR8_3 wait 0.5 textdef msg 10 10 "E4TEXT" waittext msg wait 7 # The original TEXTWAIT is 250 tics. # Fade to the Deimos picture. patch back 0 0 ENDPIC alpha back 0 in 2 alpha back 1; textalpha msg 0 wait 2 deltext msg noflat }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/lights.ded0000644000175000017500000000150111357170242022544 0ustar keeskees# jDoom: Lights Header { Version = 5; } SkipIf -nodefaultfx; #####====--- LIGHT DECORATIONS ---====##### Include "doom1lights.ded"; Include "doom2lights.ded"; Include "doom2-tntlights.ded"; Include "doom2-plutlights.ded"; #####====--- LIGHT SOURCE PROPERTIES ---====##### # The default properties of all light-emitting objects are determined # automatically by the engine. # The blue health bottles should be lit a bit more brightly. Light { State = "BON1"; Size = 0.5; Color { .05 .05 .85 }; } * Light { State = "BON1A"; } * Light { State = "BON1B"; } * Light { State = "BON1C"; } * Light { State = "BON1D"; } * Light { State = "BON1E"; } # Nuke-barrel's (weak) green glow. Light { State = "BAR1"; Flags = nohalo; Color { .2 .4 .22 }; Size = 0.21; Y Offset = -6; } Copy Light { State = "BAR2"; Size = 0.22; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/defs/sprites.ded0000644000175000017500000000660511357170242022755 0ustar keeskees# jDoom: Sprites # # Order of definitions is very important here! # Only add new Sprites *after* the existing definitions. Header { Version = 5; } Sprite { ID = "TROO"; } Sprite { ID = "SHTG"; } Sprite { ID = "PUNG"; } Sprite { ID = "PISG"; } Sprite { ID = "PISF"; } Sprite { ID = "SHTF"; } Sprite { ID = "SHT2"; } Sprite { ID = "CHGG"; } Sprite { ID = "CHGF"; } Sprite { ID = "MISG"; } Sprite { ID = "MISF"; } Sprite { ID = "SAWG"; } Sprite { ID = "PLSG"; } Sprite { ID = "PLSF"; } Sprite { ID = "BFGG"; } Sprite { ID = "BFGF"; } Sprite { ID = "BLUD"; } Sprite { ID = "PUFF"; } Sprite { ID = "BAL1"; } Sprite { ID = "BAL2"; } Sprite { ID = "PLSS"; } Sprite { ID = "PLSE"; } Sprite { ID = "MISL"; } Sprite { ID = "BFS1"; } Sprite { ID = "BFE1"; } Sprite { ID = "BFE2"; } Sprite { ID = "TFOG"; } Sprite { ID = "IFOG"; } Sprite { ID = "PLAY"; } Sprite { ID = "POSS"; } Sprite { ID = "SPOS"; } Sprite { ID = "VILE"; } Sprite { ID = "FIRE"; } Sprite { ID = "FATB"; } Sprite { ID = "FBXP"; } Sprite { ID = "SKEL"; } Sprite { ID = "MANF"; } Sprite { ID = "FATT"; } Sprite { ID = "CPOS"; } Sprite { ID = "SARG"; } Sprite { ID = "HEAD"; } Sprite { ID = "BAL7"; } Sprite { ID = "BOSS"; } Sprite { ID = "BOS2"; } Sprite { ID = "SKUL"; } Sprite { ID = "SPID"; } Sprite { ID = "BSPI"; } Sprite { ID = "APLS"; } Sprite { ID = "APBX"; } Sprite { ID = "CYBR"; } Sprite { ID = "PAIN"; } Sprite { ID = "SSWV"; } Sprite { ID = "KEEN"; } Sprite { ID = "BBRN"; } Sprite { ID = "BOSF"; } Sprite { ID = "ARM1"; } Sprite { ID = "ARM2"; } Sprite { ID = "BAR1"; } Sprite { ID = "BEXP"; } Sprite { ID = "FCAN"; } Sprite { ID = "BON1"; } Sprite { ID = "BON2"; } Sprite { ID = "BKEY"; } Sprite { ID = "RKEY"; } Sprite { ID = "YKEY"; } Sprite { ID = "BSKU"; } Sprite { ID = "RSKU"; } Sprite { ID = "YSKU"; } Sprite { ID = "STIM"; } Sprite { ID = "MEDI"; } Sprite { ID = "SOUL"; } Sprite { ID = "PINV"; } Sprite { ID = "PSTR"; } Sprite { ID = "PINS"; } Sprite { ID = "MEGA"; } Sprite { ID = "SUIT"; } Sprite { ID = "PMAP"; } Sprite { ID = "PVIS"; } Sprite { ID = "CLIP"; } Sprite { ID = "AMMO"; } Sprite { ID = "ROCK"; } Sprite { ID = "BROK"; } Sprite { ID = "CELL"; } Sprite { ID = "CELP"; } Sprite { ID = "SHEL"; } Sprite { ID = "SBOX"; } Sprite { ID = "BPAK"; } Sprite { ID = "BFUG"; } Sprite { ID = "MGUN"; } Sprite { ID = "CSAW"; } Sprite { ID = "LAUN"; } Sprite { ID = "PLAS"; } Sprite { ID = "SHOT"; } Sprite { ID = "SGN2"; } Sprite { ID = "COLU"; } Sprite { ID = "SMT2"; } Sprite { ID = "GOR1"; } Sprite { ID = "POL2"; } Sprite { ID = "POL5"; } Sprite { ID = "POL4"; } Sprite { ID = "POL3"; } Sprite { ID = "POL1"; } Sprite { ID = "POL6"; } Sprite { ID = "GOR2"; } Sprite { ID = "GOR3"; } Sprite { ID = "GOR4"; } Sprite { ID = "GOR5"; } Sprite { ID = "SMIT"; } Sprite { ID = "COL1"; } Sprite { ID = "COL2"; } Sprite { ID = "COL3"; } Sprite { ID = "COL4"; } Sprite { ID = "CAND"; } Sprite { ID = "CBRA"; } Sprite { ID = "COL6"; } Sprite { ID = "TRE1"; } Sprite { ID = "TRE2"; } Sprite { ID = "ELEC"; } Sprite { ID = "CEYE"; } Sprite { ID = "FSKU"; } Sprite { ID = "COL5"; } Sprite { ID = "TBLU"; } Sprite { ID = "TGRN"; } Sprite { ID = "TRED"; } Sprite { ID = "SMBT"; } Sprite { ID = "SMGT"; } Sprite { ID = "SMRT"; } Sprite { ID = "HDB1"; } Sprite { ID = "HDB2"; } Sprite { ID = "HDB3"; } Sprite { ID = "HDB4"; } Sprite { ID = "HDB5"; } Sprite { ID = "HDB6"; } Sprite { ID = "POB1"; } Sprite { ID = "POB2"; } Sprite { ID = "BRS1"; } Sprite { ID = "TLMP"; } Sprite { ID = "TLP2"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jdoom/CMakeLists.txt0000644000175000017500000000640011357170242022416 0ustar keeskees## deng build scripts. ## Copyright © 2006 - 2007 Jamie Jones ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/plugins/common/include ) FILE(GLOB COMMON_PLUGIN_SOURCES ${CMAKE_SOURCE_DIR}/plugins/common/src/*.c) ################################################################################ ######################## jDoom Game Plugin #################################### ADD_DEFINITIONS (-D__JDOOM__ ) INCLUDE_DIRECTORIES ( include ) FILE(GLOB JDOOM_SOURCES ${CMAKE_SOURCE_DIR}/plugins/jdoom/src/*.c ) IF (ENABLEMAO) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jdoom_mao.c ${JDOOM_SOURCES} ) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jdoom_common.c ${COMMON_PLUGIN_SOURCES} ) # CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jdoom_mobj.c # ${CMAKE_SOURCE_DIR}/plugins/jdoom/src/p_mobj.c ${CMAKE_SOURCE_DIR}/plugins/jdoom/src/p_telept.c ) ADD_LIBRARY (jdoom SHARED ${CMAKE_BINARY_DIR}/_jdoom_mao.c ${CMAKE_BINARY_DIR}/_jdoom_common.c ) # ${CMAKE_SOURCE_DIR}/plugins/jdoom/src/p_oldsvg.c ${CMAKE_SOURCE_DIR}/plugins/jdoom/src/m_random.c # ${CMAKE_BINARY_DIR}/_jdoom_mobj.c ) ELSE (ENABLEMAO) ADD_LIBRARY (jdoom SHARED ${JDOOM_SOURCES} ${COMMON_PLUGIN_SOURCES} ) ENDIF (ENABLEMAO) #IF (APPLE) # SET_TARGET_PROPERTIES (jdoom PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -bundle -bundle_loader doomsday") #ENDIF (APPLE) ################################################################################ ######################## Install Targets ###################################### IF (NOT APPLE) INSTALL(TARGETS jdoom RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) ENDIF (NOT APPLE) IF (APPLE) # Bundling. SET (BUNDLE_BASE jDoom) SET (BUNDLE ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.bundle) ADD_CUSTOM_COMMAND( TARGET jdoom POST_BUILD COMMAND rm -rf ${BUNDLE} COMMAND mkdir -p ${BUNDLE}/Contents/MacOS COMMAND cp libjdoom.dylib ${BUNDLE}/Contents/MacOS/${BUNDLE_BASE} COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/${BUNDLE_BASE}-Info.plist ${BUNDLE}/Contents/Info.plist COMMAND mkdir -p ${BUNDLE}/Contents/Resources #COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/InfoPlist.strings ${BUNDLE}/Contents/Resources/English.lproj/ COMMAND echo 'APPL????' > ${BUNDLE}/Contents/PkgInfo COMMAND cp ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.pk3 ${BUNDLE}/Contents/Resources/ ) ENDIF (APPLE) deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/exampleplugin/0000755000175000017500000000000011523516204021415 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/exampleplugin/doc/0000755000175000017500000000000011523516204022162 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/exampleplugin/doc/readme.txt0000644000175000017500000000422011357170242024161 0ustar keeskees Doomsday Plugin Example ======================= by Daniel Swanson 28/02/2009 WHAT IS THIS? ------------------------------------------------------------------------ An ultra-light, stripped down example of a Doomsday plugin. OVERVIEW ------------------------------------------------------------------------ The Doomsday engine uses a hook-based, plugin system. This system allows any number of plugins to hook themselves to a particular process, thus the possibility of providing extended functionality not present in the engine itself and/or access to the engine's public API for other means. Various plugins are developed alongside the Doomsday Engine itself (such as dpWadMapConverter and dpDehRead) and are distributed with it. The Doomsday API and it's plugin system are public interfaces, making it possible to either completely replace existing plugins (for example, a new map loader plugin could allow loading of maps of a format not initially supported by Doomsday) or to provide extended functionality through entirely new plugins. DETAILS ------------------------------------------------------------------------ dpExample is a bare bones example of the minimum requirements of a Doomsday plugin. As such, it is not particularly useful and does nothing other than output a message to Doomsday's console to signify that the hook has been called successfully. The Doomsday engine will automatically load all plugins from the plugin directory, provided their names are prefixed 'dp' e.g: Under WindowsXP: c:\Program Files\Doomsday\bin\dpExample.dll During the load process, a plugin must register into the engine the hooks by which it should be called. This is done via the Doomsday public API function: Plug_AddHook(hookType, hookFunc) @hookType (int) The type of hook being attached to. Doomsday presents various hooks, defined in ./engine/api/dd_plugin.h @hookFunc - (int(function)(int type, int param, void *data)) A pointer to the function to be called when the hook is processed. deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/exampleplugin/doc/LICENSE0000644000175000017500000003545111357170242023202 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/exampleplugin/src/0000755000175000017500000000000011357170242022207 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/exampleplugin/src/example.c0000644000175000017500000000551411357170242024013 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * example.c: Example of Doomsday plugin which is called at startup. */ // HEADER FILES ------------------------------------------------------------ #ifdef WIN32 # define WIN32_LEAN_AND_MEAN # include #endif #include "doomsday.h" #include "dd_api.h" #include #include #include // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static int ExampleHook(int hookType, int parm, void *data); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ void DP_Initialize(void) { Plug_AddHook(HOOK_STARTUP, ExampleHook); } #ifdef WIN32 /** * Windows calls this when the DLL is loaded. */ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { switch(fdwReason) { case DLL_PROCESS_ATTACH: // Register our hooks. DP_Initialize(); break; default: break; } return TRUE; } #endif /** * This function will be called ASAP after Doomsday has completed startup. * * @param parm * @param data * * @return Non-zero if successful. */ int ExampleHook(int hookType, int parm, void *data) { Con_Message("ExampleHook: Hook successful!"); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/exampleplugin/CMakeLists.txt0000644000175000017500000000315611357170242024165 0ustar keeskees## deng build scripts. ## Copyright 2006 - 2007 Jamie Jones ## Copyright 2007 Daniel Swanson ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ ######################## Example Plugin ####################################### ADD_DEFINITIONS (-EXAMPLE_PLUGIN ) FILE(GLOB EXAMPLE_SOURCES src/*.c) ADD_LIBRARY (dpexample SHARED ${EXAMPLE_SOURCES} ) IF (APPLE) SET_TARGET_PROPERTIES (dpexample PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -bundle -bundle_loader doomsday") ENDIF (APPLE) ################################################################################ ######################## Install Targets ###################################### INSTALL(TARGETS dpexample RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/0000755000175000017500000000000011523516204020024 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/api/0000755000175000017500000000000011523516204020575 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/api/jhexen.def0000644000175000017500000000005111357170242022535 0ustar keeskeesLIBRARY JHEXEN EXPORTS GetGameAPI @1deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/res/0000755000175000017500000000000011523516204020615 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/res/jhexen.ico0000644000175000017500000001114611357170242022600 0ustar keeskees(Fhn   (   ( @kh)NbF ey'=3L`{H#"X<@9Z7Y5oAVUI6-nm4 . T /  '/3210!87 654 ;#:9( A@?>=<&C.$%BGF ED,IH"! J#MLKO&N%$ )P ('  Q+*+T S,RV.U-( @( @PLmZ@MK-/FYQESN}{CaW \J?o"XV[_IcR 8; Ukfv5p^+t>9`B)r4O%&1 Db2y=(6e!0iGdg]hs,' xT*<z~$aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaadCaaaaaaaaaaaaaaaaaaaaaaaaaaaaCaaaaaaaaaaaaaaaaaaaaaaaaaaaqCaaaaaaaaaaaaaaaaaaaaaaaaaaaVqCaaaaaaaaaaaaaaaaaaaaaaaaawTaaaaaaaaaaaaaaaaaaaaaaaq& qCaaaaaaaaaaaaaaaqaaaaaaawdCaaaaaaaaaaaCdqaaaaaaaaqwT)dqCaaaaaaaadqVdaaaaaaaaaq--"Vaaaaaaaq"Caaaaaaaaaa)1E q)aaaaa)aaaaaaaaaaaaa)[[w&daaaCCaaaaaaaaaaaaaa)J!)qaa)aaaaaaaaaaaaaaaJ)q aaaaaaaaaaaaaaaaCVJ,)Vaaaaaaaaaaaaaaaaaaaad1,1V)Taaaaaaaaaaaaaaaaaaaaa,!)aaaaaaaaaaaaaaaaaaaaaaaCTJ-"&aaaaaaaaaaaaaaaaaaaaaaaaJ[11TqCaaaaaaaaaaaaaaaaaaaaaa!1Vqaaaaaaaaaaaaaaaaaaaaaad1!"aaaaaaaaaaaaaaaaaaaaaaT11daaaaaaaaaaaaaaaaaaC)[--&aaaaaaaaaaaaaaaaa)w"aaa-!waaaaaaaaaaaaaaaqVaaaaa& qaaaaaaaaaaaad) TCaaaaaaa "qqaaaaaaaaaaa)-aaaaaaaaa aaaaaaaaaaq)!"aaaaaaaaaaa aaaaaaaaaawT&EaaaaaaaaaaaaV)qCaaaaaaaaaaV&wE)aaaaaaaaaaaaaTaaaaaaaaaaa)"&aaaaaaaaaaaaaaaq"Caaaaaaaaaa)CaaaaaaaaaaaaaaaaaaCadeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/res/jhexen.rc0000644000175000017500000001005311357170242022426 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright 2008-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jhexen.rc: jHexen.dll resource script. */ #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS #include "windows.h" #include "../include/version.h" #undef APSTUDIO_READONLY_SYMBOLS // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) # ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) # endif //_WIN32 # ifdef APSTUDIO_INVOKED 1 TEXTINCLUDE BEGIN "resource.h\0" END 2 TEXTINCLUDE BEGIN "#include ""windows.h""\r\n" "#include ""../include/version.h""\0" END 3 TEXTINCLUDE BEGIN "#ifndef NO_MANIFEST\r\n" " CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST ""jhexen.dll.manifest""\r\n" "#endif\r\n" "\r\n" "VS_VERSION_INFO VERSIONINFO\r\n" "FILEVERSION GAME_VERSION_NUMBER\r\n" "PRODUCTVERSION GAME_VERSION_NUMBER\r\n" "# ifdef _DEBUG\r\n" "FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE\r\n" "# else\r\n" "FILEFLAGSMASK 0\r\n" "# endif\r\n" "FILEOS VOS_NT_WINDOWS32\r\n" "FILETYPE VFT_DLL\r\n" "FILESUBTYPE VFT2_UNKNOWN\r\n" "BEGIN\r\n" " BLOCK ""StringFileInfo""\r\n" " BEGIN\r\n" " BLOCK ""040904b0""\r\n" " BEGIN\r\n" " VALUE ""CompanyName"", ""\0""\r\n" " VALUE ""FileDescription"", GAME_NICENAME "" (Doomsday Engine game plugin)\0""\r\n" " VALUE ""FileVersion"", GAME_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", GAME_NICENAME ""\0""\r\n" " VALUE ""LegalCopyright"", ""Copyright 2003-2009, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""jHexen.dll\0""\r\n" " VALUE ""ProductName"", GAME_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", GAME_VERSION_TEXT ""\0""\r\n" " END\r\n" " END\r\n" "\r\n" " BLOCK ""VarFileInfo""\r\n" " BEGIN\r\n" " VALUE ""Translation"", 0x409, 1200\r\n" " END\r\n" "END\r\n" END # endif /** * Icons: * Icon with lowest ID value placed first to ensure application icon * remains consistent on all systems. */ IDI_GAME_ICON ICON DISCARDABLE "jhexen.ico" #endif // English (U.S.) resources #ifndef APSTUDIO_INVOKED VS_VERSION_INFO VERSIONINFO FILEVERSION GAME_VERSION_NUMBER PRODUCTVERSION GAME_VERSION_NUMBER # ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE # else FILEFLAGSMASK 0 # endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904E4" BEGIN VALUE "CompanyName", "\0" VALUE "FileDescription", GAME_NICENAME " (Doomsday Engine game plugin)\0" VALUE "FileVersion", GAME_VERSION_TEXT "\0" VALUE "InternalName", GAME_NICENAME "\0" VALUE "LegalCopyright", "Copyright 2003-2009, Deng Team\0" VALUE "OriginalFilename", "jHexen.dll\0" VALUE "ProductName", GAME_NICENAME "\0" VALUE "ProductVersion", GAME_VERSION_TEXT "\0" END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/res/resource.h0000644000175000017500000000066611357170242022630 0ustar keeskees//{{NO_DEPENDENCIES}} // Microsoft Developer Studio generated include file. // Used by jhexen.rc // #define IDI_GAME_ICON 101 // Next default values for new objects // #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 102 #define _APS_NEXT_COMMAND_VALUE 40001 #define _APS_NEXT_CONTROL_VALUE 1000 #define _APS_NEXT_SYMED_VALUE 101 #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/res/jhexen.dll.manifest0000644000175000017500000000061211357170242024402 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/doc/0000755000175000017500000000000011523516204020571 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/doc/LICENSE0000644000175000017500000003545111357170242021611 0ustar keeskees GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/0000755000175000017500000000000011523516204020735 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/conhelp.txt0000644000175000017500000004716111357170242023142 0ustar keeskees# # CONSOLE COMMANDS - JHEXEN SPECFIC # [conbg] desc = Console background setup. inf = Params: conbg (materialname) [setcolor] desc = Set player color. inf = Params: setcolor (playernum)\nFor example, 'setcolor 4'. [setmap] desc = Set map. inf = Params: setmap (map)\nFor example, 'setmap 23'. [setclass] desc = Set player class. inf = Params: setclass (0-2). [startcycle] desc = Begin map rotation. [endcycle] desc = End map rotation. [menu] desc = Open/Close the menu. [menuup] desc = Move the menu cursor up. [menudown] desc = Move the menu cursor down. [menuleft] desc = Move the menu cursor left. [menuright] desc = Move the menu cursor right. [menuselect] desc = Select/Accept the current menu item. [menuback] desc = Return to the previous menu page. [helpscreen] desc = Show the Help screens. [savegame] desc = Open the save game menu. [loadgame] desc = Open the load game menu. [listmaps] desc = List all loaded maps. [soundmenu] desc = Open the sound settings menu. [quicksave] desc = Quicksave the game. [endgame] desc = End the game. [togglemsgs] desc = Messages on/off. [quickload] desc = Load the quicksaved game. [quit] desc = Quit the game and return to the OS. [togglegamma] desc = Cycle gamma correction levels. [messageyes] desc = Respond - YES to the message promt. [messageno] desc = Respond - NO to the message promt. [messagecancel] desc = Respond - CANCEL to the message promte. [spy] desc = Change the viewplayer when not in deathmatch. [screenshot] desc = Take a screenshot. [viewsize] desc = Set the view size. inf = Params: viewsize (size)\nFor example, 'viewsize 10'.\nSize can be: +, -, (num). [pause] desc = Pause the game (same as pressing the pause key). [cheat] desc = Issue a cheat code using the original Hexen cheats. inf = Params: cheat (cheat)\nFor example, 'cheat satan'. [god] desc = I don't think He needs any help... [notarget] desc = Enemies will not target the player (cheat). [noclip] desc = Movement clipping on/off. [warp] desc = Warp to a map. [reveal] desc = Map cheat. inf = Params: reveal (0-4)\nModes:\n 0=nothing\n 1=show unseen\n 2=full map\n 3=map+things\n 4=show subsectors [give] desc = Cheat command to give you various kinds of things. [kill] desc = Kill all the monsters on the map. [suicide] desc = Kill yourself. What did you think? [hexenfont] desc = Use the Hexen font. [startinf] desc = Start an InFine script. inf = Params: startinf (script-id)\nFor example, 'startinf coolscript'. [stopinf] desc = Stop the currently playing interlude/finale. [stopfinale] desc = Stop the currently playing interlude/finale. [spawnmobj] desc = Spawn a new mobj. [coord] desc = Print the coordinates of the consoleplayer. [makelocp] desc = Make local player. inf = Params: makelocp (playernum)\nFor example, 'makelocp 1'. [makecam] desc = Toggle camera mode. inf = Params: makecam (playernum)\nFor example, 'makecam 1'. [setlock] desc = Set camera viewlock. [lockmode] desc = Set camera viewlock mode. inf = Params: lockmode (0-1). [pig] desc = Turn yourself into a pig. Go ahead. [runscript] desc = Run an ACS script. inf = Params: runscript (1-99)\n. [scriptinfo] desc = Show information about all scripts or one particular script. [where] desc = Prints your map number and exact location. [class] desc = Change player class. inf = Params: class (classnumber). [demomode] desc = Set demo external camera mode. [sbsize] desc = Status bar size adjustment. inf = Params: sbsize (size)\nFor example, 'sbsize +'.\nSize can be: +, -, (num). [movefloor] desc = Move a sector's floor plane. [moveceil] desc = Move a sector's ceiling plane. [movesec] desc = Move a sector's both planes. [chatcomplete] desc = Send the chat message and exit chat mode. [chatdelete] desc = Delete a character from the chat buffer. [chatcancel] desc = Exit chat mode without sending the message. [chatsendmacro] desc = Send a chat macro. [beginchat] desc = Begin chat mode. [message] desc = Show a local game message. inf = Params: message (msg)\nFor example, 'message "this is a message"'. # # CONSOLE VARIABLES - JHEXEN SPECIFIC # [server-game-mapcycle] desc = Map rotation sequence. [server-game-mapcycle-noexit] desc = 1=Disable exit buttons during map rotation. [server-game-cheat] desc = 1=Allow cheating in multiplayer games (god, noclip, give). [menu-scale] desc = Scaling for menus. [menu-flash-r] desc = Menu selection flash color, red component. [menu-flash-g] desc = Menu selection flash color, green component. [menu-flash-b] desc = Menu selection flash color, blue component. [menu-flash-speed] desc = Menu selection flash speed. [menu-turningskull] desc = 1=Menu skull turns at slider items. [menu-effect] desc = 0=Disable menu effects. 1=type-in. [menu-color-r] desc = Menu color red component. [menu-color-g] desc = Menu color green component. [menu-color-b] desc = Menu color blue component. [menu-colorb-r] desc = Menu color B red component. [menu-colorb-g] desc = Menu color B green component. [menu-colorb-b] desc = Menu color B blue component. [menu-glitter] desc = Strength of type-in glitter. [menu-fog] desc = Menu fog mode: 0=off, 1=shimmer, 2=black smoke, 3=blue vertical, 4=grey smoke, 5=dimmed. [menu-hotkeys] desc = 1=Enable hotkey navigation in the menu. [menu-shadow] desc = Menu text shadow darkness. [menu-patch-replacement] desc = Patch Replacement strings. 1=Enable external, 2=Enable built-in. [menu-slam] desc = 1=Slam the menu when opening. [menu-quick-ask] desc = 1=Ask me to confirm when quick saving/loading. [view-cross-type] desc = The current crosshair. [view-cross-size] desc = Crosshair size: 1=Normal. [view-cross-vitality] desc = Color the crosshair according to how near you are to death. [view-cross-r] desc = Crosshair color red component. [view-cross-g] desc = Crosshair color green component. [view-cross-b] desc = Crosshair color blue component. [view-cross-a] desc = Crosshair color alpha component. [view-filter-strength] desc = Strength of view filter. [msg-show] desc = 1=Show messages. [msg-echo] desc = 1=Echo all messages to the console. [msg-count] desc = Number of HUD messages displayed at the same time. [msg-uptime] desc = Number of seconds to keep HUD messages on screen. [msg-hub-override] desc = Override the transition hub message. [msg-scale] desc = Scaling factor for HUD messages. [msg-align] desc = Alignment of HUD messages. 0 = left, 1 = center, 2 = right. [msg-color-r] desc = Color of HUD messages red component. [msg-color-g] desc = Color of HUD messages green component. [msg-color-b] desc = Color of HUD messages blue component. [msg-blink] desc = HUD messages blink for this number of tics when printed. [game-state] desc = Current game state. [game-state-map] desc = 1=Currently playing a map. [game-paused] desc = 1=Game paused. [game-skill] desc = Current skill level. [map-id] desc = Current map id. [map-name] desc = Current map name. [map-episode] desc = Current episode. [map-hub] desc = Current hub. [game-music] desc = Currently playing music (id). [map-music] desc = Music (id) for current map. [player-health] desc = Current health ammount. [player-armor] desc = Current armor ammount. [player-weapon-current] desc = Current weapon (id) [player-mana-blue] desc = Current amount of blue mana. [player-mana-green] desc = Current ammount of green mana. [player-key-steel] desc = 1= Player has steel key. [player-key-cave] desc = 1= Player has cave key. [player-key-axe] desc = 1= Player has axe key. [player-key-fire] desc = 1= Player has fire key. [player-key-emerald] desc = 1= Player has emerald key. [player-key-dungeon] desc = 1= Player has dungeon key. [player-key-silver] desc = 1= Player has silver key. [player-key-rusted] desc = 1= Player has rusted key. [player-key-horn] desc = 1= Player has horn key. [player-key-swamp] desc = 1= Player has swamp key. [player-key-castle] desc = 1= Player has castle key. [player-weapon-first] desc = 1= Player has first weapon. [player-weapon-second] desc = 1= Player has second weapon. [player-weapon-third] desc = 1= Player has third weapon. [player-weapon-fourth] desc = 1= Player has fourth weapon. [player-weapon-piece1] desc = 1= Player has piece 1. [player-weapon-piece2] desc = 1= Player has piece 2. [player-weapon-piece3] desc = 1= Player has piece 3. [player-weapon-allpieces] desc = 1= Player has all pieces. [player-artifact-defender] desc = Current number of Icons Of The Defender. [player-artifact-quartzflask] desc = Current number of Quartz Flasks. [player-artifact-mysticurn] desc = Current number of Mystic Urn artifacts. [player-artifact-mysticambit] desc = Current number of Mystic Ambit Incantations. [player-artifact-darkservant] desc = Current number of Dark Servant artifacts. [player-artifact-torch] desc = Current number of torches. [player-artifact-porkalator] desc = Current number of Porkalaor artifacts. [player-artifact-wings] desc = Current number of Wings of Wrath artifacts. [player-artifact-repulsion] desc = Current number of Discs Of Repulsion. [player-artifact-flechette] desc = Current number of Flechettes. [player-artifact-banishment] desc = Current number of Banishment Devices. [player-artifact-speed] desc = Current number of Boots of Speed. [player-artifact-might] desc = Current number of Kraters Of Might. [player-artifact-bracers] desc = Current number of Dragonskin Bracers. [player-artifact-chaosdevice] desc = Current number of Chaos Devices. [player-artifact-skull] desc = 1= Player has Yorick's Skull. [player-artifact-heart] desc = 1= Player has Heart Of D'Sparil. [player-artifact-ruby] desc = 1= Player has Ruby Planet. [player-artifact-emerald1] desc = 1= Player has Emerald Planet 1. [player-artifact-emerald2] desc = 1= Player has Emerald Planet 2. [player-artifact-sapphire1] desc = 1= Player has Sapphire Planet 1. [player-artifact-sapphire2] desc = 1= Player has Sapphire Planet 2. [player-artifact-daemoncodex] desc = 1= Player has Daemon Codex. [player-artifact-liberoscura] desc = 1= Player has Liber Oscura. [player-artifact-flamemask] desc = 1= Player has Flame Mask. [player-artifact-glaiveseal] desc = 1= Player has Glaive Seal. [player-artifact-holyrelic] desc = 1= Player has Holy Relic. [player-artifact-sigilmagus] desc = 1= Player has Sigil of the Magus. [player-artifact-gear1] desc = 1= Player has Clock Gear 1. [player-artifact-gear2] desc = 1= Player has Clock Gear 2. [player-artifact-gear3] desc = 1= Player has Clock Gear 3. [player-artifact-gear4] desc = 1= Player has Clock Gear 4. [chat-beep] desc = 1= Play a beep sound when a new chat message arrives. [chat-macro0] desc = Chat macro 1. [chat-macro1] desc = Chat macro 2. [chat-macro2] desc = Chat macro 3. [chat-macro3] desc = Chat macro 4. [chat-macro4] desc = Chat macro 5. [chat-macro5] desc = Chat macro 6. [chat-macro6] desc = Chat macro 7. [chat-macro7] desc = Chat macro 8. [chat-macro8] desc = Chat macro 9. [chat-macro9] desc = Chat macro 10. [map-alpha-lines] desc = Alpha level of automap lines. [map-babykeys] desc = 1=Show keys in automap (easy skill mode only). [map-background-r] desc = Automap background color, red component. [map-background-g] desc = Automap background color, green component. [map-background-b] desc = Automap background color, blue component. [map-customcolors] desc = Custom automap coloring 0=Never, 1=Auto (enabled if unchanged), 2=Always. [map-door-colors] desc = 1=Show door colors in automap. [map-door-glow] desc = Door glow thickness in the automap (with map-door-colors). [map-huddisplay] desc = 0=No HUD when in the automap 1=Current HUD display shown when in the automap 2=Always show Status Bar when in the automap [map-mobj-r] desc = Automap mobjs, red component. [map-mobj-g] desc = Automap mobjs, green component. [map-mobj-b] desc = Automap mobjs, blue component. [map-opacity] desc = Opacity of the automap. [map-open-timer] desc = Time taken to open/close the automap, in seconds. [map-pan-speed] desc = Pan speed multiplier in the automap. [map-pan-resetonopen] desc = 1= Reset automap pan location when opening the automap. [map-rotate] desc = 1=Automap turns with player, up=forward. [map-wall-r] desc = Automap walls, red component. [map-wall-g] desc = Automap walls, green component. [map-wall-b] desc = Automap walls, blue component. [map-wall-ceilingchange-r] desc = Automap ceiling height difference lines, red component. [map-wall-ceilingchange-g] desc = Automap ceiling height difference lines, green component. [map-wall-ceilingchange-b] desc = Automap ceiling height difference lines, blue component. [map-wall-floorchange-r] desc = Automap floor height difference lines, red component. [map-wall-floorchange-g] desc = Automap floor height difference lines, green component. [map-wall-floorchange-b] desc = Automap floor height difference lines, blue component. [map-wall-unseen-r] desc = Automap unseen areas, red component. [map-wall-unseen-g] desc = Automap unseen areas, green component. [map-wall-unseen-b] desc = Automap unseen areas, blue component. [map-zoom-speed] desc = Zoom in/out speed multiplier in the automap. [input-mouse-x-sensi] desc = Mouse X axis sensitivity. [input-mouse-y-sensi] desc = Mouse Y axis sensitivity. [input-joy-x] desc = X axis control: 0=None, 1=Move, 2=Turn, 3=Strafe, 4=Look. [input-joy-y] desc = Y axis control. [input-joy-z] desc = Z axis control. [input-joy-rx] desc = X rotational axis control. [input-joy-ry] desc = Y rotational axis control. [input-joy-rz] desc = Z rotational axis control. [input-joy-slider1] desc = First slider control. [input-joy-slider2] desc = Second slider control. [ctl-aim-noauto] desc = 1=Autoaiming disabled. [ctl-turn-speed] desc = The speed of turning left/right. [ctl-run] desc = 1=Always run. [ctl-use-dclick] desc = 1=Doubleclick forward/strafe equals use key. [ctl-inventory-mode] desc = Inventory selection mode 0=cursor, 1=scroll. [ctl-inventory-wrap] desc = 1=Inventory selection wraps around. [ctl-inventory-use-immediate] desc = 1=Use items immediately from the inventory. [ctl-inventory-use-next] desc = 1=Automatically select the next inventory item when unusable. [ctl-look-speed] desc = The speed of looking up/down. [ctl-look-spring] desc = 1=Lookspring active. [ctl-look-mouse] desc = 1=Mouse look active. [ctl-look-mouse-inverse] desc = 1=Inverse mouse look Y axis. [ctl-look-pov] desc = 1=Look around using the POV hat. [ctl-look-joy] desc = 1=Joystick look active. [ctl-look-joy-inverse] desc = 1=Inverse joystick look Y axis. [ctl-look-joy-delta] desc = 1=Joystick values => look angle delta. [con-zoom] desc = Zoom factor for the console background. [view-size] desc = View window size (3-13). [hud-title] desc = 1=Show map title and author in the beginning. [hud-title-author-noiwad] desc = 1=Do not show map author if it is a map from an IWAD. [view-bob-height] desc = Scale for viewheight bobbing. [view-bob-weapon] desc = Scale for player weapon bobbing. [server-game-skill] desc = Skill level in multiplayer games. [server-game-map] desc = Map to use in multiplayer games. [server-game-deathmatch] desc = 1=Start multiplayers games as deathmatch. [server-game-mod-damage] desc = Enemy (mob) damage modifier, multiplayer (1..100). [server-game-mod-health] desc = Enemy (mob) health modifier, multiplayer (1..20). [server-game-mod-gravity] desc = World gravity modifier, multiplayer (-1..100). -1 = Map default. [server-game-jump] desc = 1=Allow jumping in multiplayer games. [server-game-nomonsters] desc = 1=No monsters. [server-game-randclass] desc = 1=Respawn in a random class (deathmatch). [server-game-radiusattack-nomaxz] desc = 1=ALL radius attacks are infinitely tall. [server-game-monster-meleeattack-nomaxz] desc = 1=Monster melee attacks are infinitely tall. [player-color] desc = Player color: 0=blue, 1=red, 2=yellow, 3=green, 4=jade, 5=white,\n6=hazel, 7=purple, 8=auto. [player-eyeheight] desc = Player eye height (the original is 41). [player-class] desc = Player class in multiplayer games. [player-move-speed] desc = Player movement speed modifier. [player-jump] desc = 1=Allow jumping. [player-jump-power] desc = Jump power (for all clients if this is the server). [player-air-movement] desc = Player movement speed while airborne and NOT flying. [player-autoswitch] desc = Change weapon automatically when picking one up. 1=If better 2=Always [player-autoswitch-notfiring] desc = 1=Disable automatic weapon switch if firing when picking one up. [player-autoswitch-ammo] desc = Change weapon automatically when picking up ammo. 1=If better 2=Always [player-weapon-order0] desc = Weapon change order, slot 0. [player-weapon-order1] desc = Weapon change order, slot 1. [player-weapon-order2] desc = Weapon change order, slot 2. [player-weapon-order3] desc = Weapon change order, slot 3. [player-weapon-nextmode] desc = 1= Use custom weapon order with Next/Previous weapon. [player-camera-noclip] desc = 1=Camera players have no movement clipping. [game-fastmonsters] desc = 1=Fast monsters in non-demo single player. [game-maulator-time] desc = Dark Servant lifetime, in seconds (default: 25). [game-icecorpse] desc = 1=Translucent frozen monsters. [hud-scale] desc = Scaling for HUD info. [hud-status-size] desc = Status bar size (1-20). [hud-color-r] desc = HUD info color red component. [hud-color-g] desc = HUD info color green component. [hud-color-b] desc = HUD info color alpha component. [hud-color-a] desc = HUD info alpha value. [hud-icon-alpha] desc = HUD icon alpha value. [hud-status-alpha] desc = Status bar Alpha level. [hud-status-icon-a] desc = Status bar icons & counters Alpha level. [hud-mana] desc = Show mana when the status bar is hidden. 1= top, 2= bottom, 0= off [hud-health] desc = Show health when the status bar is hidden. [hud-currentitem] desc = 1=Show current item in full-screen mode. [hud-inventory-slot-max] desc = Maximum number of inventory slots to display in full-screen mode. [hud-inventory-slot-showempty] desc = 1=Show empty inventory slots in full-screen mode. [hud-inventory-timer] desc = Seconds before the inventory auto-hides. [hud-frags-all] desc = Debug: HUD shows all frags of all players. [hud-timer] desc = Number of seconds before the hud auto-hides. [hud-unhide-damage] desc = 1=Unhide the HUD when player receives damaged. [hud-unhide-pickup-health] desc = 1=Unhide the HUD when player collects a health item. [hud-unhide-pickup-armor] desc = 1=Unhide the HUD when player collects an armor item. [hud-unhide-pickup-powerup] desc = 1=Unhide the HUD when player collects a powerup or item of equipment. [hud-unhide-pickup-weapon] desc = 1=Unhide the HUD when player collects a weapon. [hud-unhide-pickup-ammo] desc = 1=Unhide the HUD when player collects an ammo item. [hud-unhide-pickup-key] desc = 1=Unhide the HUD when player collects a key. [hud-unhide-pickup-invitem] desc = 1=Unhide the HUD when player collects an inventory item. [rend-dev-freeze-map] desc = 1=Stop updating the automap rendering lists. deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/0000755000175000017500000000000011357170242022100 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot3.lmp0000644000175000017500000000060011357170242024363 0ustar keeskeesTU[clu*EUdr~ $ $ "" $   ccccceccecc""""  eececieeicf& "  cccccfcbgcd!!  & $bbabbcbbcbb"& $&!& #       &&& deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm5.lmp0000644000175000017500000000211511357170242024316 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQUUUXXXUQQUUUUWSQQVUSSSSiTTRRXSSQQ`ii\\iiYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQUUWWVQQWWUQQdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmc8.lmp0000644000175000017500000000220511357170242024307 0ustar keeskeesV`ir| (06>FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ## ##""%#%%#""%% #####&( # $## $ & #  %%  ####   ####&  ####&  ####&""""####&$$ ##""%%##&&$$#"" $##$$&&$$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fontb00.lmp0000644000175000017500000000004111357170242024055 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fontb60.lmp0000644000175000017500000000031411357170242024066 0ustar keeskees @GPZep{  deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot4.lmp0000644000175000017500000000056611357170242024377 0ustar keeskeesTUVW`k5Shrstuccc bb~!}{ adeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/chain3.lmp0000644000175000017500000000577611357170242023776 0ustar keeskees $-7@HOV^foy '09CLT[bjr{ $-6@IQX_gox "*3<FOW^emu~ (1:DMU\cks|    ' / 8 A K T \ c j r z    % - 6 ? I R Z a h p x   $ , 4 = F P Y a h o w  SSiUURRXSSQQ`iii\\iYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`iii\\iYYQQXXQWWWWUQQWUQQWWTQQQRR}SSRRRRSSSSiUUSSiUURRXSSQQ`iii\\iYYQQXXQWWWUQQWWTQQQRR}SSRRRRSSSSiUURRXSSQQ`iii\\iYYQQXXQVVWUQQWWTQQQRR}SSRRRRSSSSiTTRRXSSQQ`iii\\iYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`iii\\iYYQQXXQUUWWVQQWWUQQRRR}SSRRRRUUSSiTTSSiTTRRXSSQQ`iii\\iYYQQXXQUUWWVQQWWTQQRRR}SSRRRRUUSSiTTRRXRRQQ`hii\\iYYQQXXQUUWWUQQWWTQQRRR}SSRRRRUUSSiTTRRXRRQQ`iii\\iYYQQXXQUUVWUQQWWTQQRRR}SSRRRRUUSSiUURRXRRQQ`iii\\iYYQQXXQUUWWVQQWWTQQRRR}SSRRRRUUSSiUURRXSSRRXSSQQ`iii\\iYYQQXXQUUVWUQQWWTQQRRR}SSRRRRUUSSiUURRXSSQQ`iii\\iYYQQXXQUUVWUQQWWTQQRRR}SSRRRRUUSSiUURRXSSQQ`iii\\iYYQQXXQUUVWUQQWWTQQRRR}SSRRRRUUSSiUURRXSSQQ`iii\\iYYQQXXQUUWWUQQWWTQQRRR}SSRRRRUUSSiUURRXSSRRXSSQQ`iii\\iYYQQWWQUUVWTQQWWSQQQRR}SSRRRRUUSSiUURRXSSQQ`iii\\iYYQQXXQUUVWUQQWWSQQRRR}SSRRRRUUTTgUUdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpfull2.lmp0000644000175000017500000000147411357170242024213 0ustar keeskees9 -=M]m}%0;EOYcmw%/9:; " $" ##"# $LKI ""JN" K FI I F "KK $ F" # F# #  M bfb bgb cgb bgc bfc cdb dfb dc cfc bgc cfb cdb cfb bdb bdc bfc bgc cfb bdb cfb bfc bdc bdb bfc cgb cfd df cd bdb bdb bfb $# %M$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm8.lmp0000644000175000017500000000211511357170242024321 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQUUUXXXUQQUUUUWSQQVUSSSSiTTRRXSSQQ`ii\\iiYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQUUWWVQQWWUQQdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fonta61.lmp0000644000175000017500000000011311357170242024063 0ustar keeskees$0<!###!deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fonta62.lmp0000644000175000017500000000013211357170242024065 0ustar keeskees$+3;CKS '' deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/armslot4.lmp0000644000175000017500000000104011357170242024352 0ustar keeskees|}~$:Pg} "ddfbdd $ddgljgd$%ffjg % $"ggl $ddjgd%ccjnh##fffg  # #ggjd #gglmg"#$"gglgdddmg$ ggng $$ "cclhd$$"ccchlgcgjf dgkmljgdbdff fghhllgnhglddjjdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot5.lmp0000644000175000017500000000042011357170242024365 0ustar keeskeesTUVWXYdp|   deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm2.lmp0000644000175000017500000000211511357170242024313 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQUUUXXXUQQUUUUWSQQVUSSSSiTTRRXSSQQ`ii\\iiYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQUUWWVQQWWUQQdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fonta63.lmp0000644000175000017500000000010711357170242024070 0ustar keeskees&1<!!!###deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpiecec1.lmp0000644000175000017500000000076411357170242024321 0ustar keeskeesdefghijkl{$Fb~"""# ""  $ "" "  ""% $ "%"% $ %"  # "% %" " $" #$"  "$"#$%#"" #  "$$$%### # " %  $#%##% ##deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm6.lmp0000644000175000017500000000211511357170242024317 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQU'UU)--)XX,21-02+,1)*20--X'UQQUUUUWSQQVUSSSSiTTRRXSSQQ`ii\\iiYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQUUWWVQQWWUQQdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fonta64.lmp0000644000175000017500000000010211357170242024064 0ustar keeskees#+3;#deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot9.lmp0000644000175000017500000000054011357170242024374 0ustar keeskeesTUVWXYh/@PX^_ RRQQ aaRTVWXRQUQ"% aaQVXYYYUSYT$#SSVW\^_]YUZU $RRVVZYYYYWZT"$" $$QQSTQQSTWS% bbfVTTQ"#"bbaVUaaRXS""RRVbdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot7.lmp0000644000175000017500000000057711357170242024404 0ustar keeskeesTUVWXcz$C\q|}~%%  $ ##$ # %$%    %$%  %## # $%% $#   ##%  #$ $%  #% ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpiecec3.lmp0000644000175000017500000000056011357170242024315 0ustar keeskees`s+9IYijklmno3 $%$##" "#  %    % " " %%  %   " "  &'&   %  deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/armslot3.lmp0000644000175000017500000000100511357170242024352 0ustar keeskees|}~0E[oTTWZWSVZYU TWXQ ""TWT ##$ $""# %%% % #""$%$" $%$"#  #"$# %% %  ""# ##$ YWT TTXUQ"" VVXVQTTYXUR" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm1.lmp0000644000175000017500000000211511357170242024312 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQUUUٙXXۡܝݜޛݡٙXUQQUUUUWSQQVUSSSSiTTRRXSSQQ`ii\\iiYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQUUWWVQQWWUQQdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fontb62.lmp0000644000175000017500000000020011357170242024062 0ustar keeskees ,3<FQ[fpydeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmc5.lmp0000644000175000017500000000220511357170242024304 0ustar keeskeesV`ir| (06>FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ## ##""%#%%#""%% #####&( # $## $ & #  %%  ####   ####&  ####&  ####&""""####&$$ ##""%%##&&$$#"" $##$$&&$$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmf8.lmp0000644000175000017500000000225411357170242024316 0ustar keeskeesV`jw #-7?GOW_gms{(4@LXcmu} &0=GQ[cmw  %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##""$$$  ""%##  ## $#  ##"##%""  ""$%$$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fonta00.lmp0000644000175000017500000000003411357170242024056 0ustar keeskees deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmc2.lmp0000644000175000017500000000220511357170242024301 0ustar keeskeesV`ir| (06>FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ##  ##""%#%%#""%% #####&( # $## $ & #  %%  ####   ####&  ####&  ####&""""####&$$ ##""%%##&&$$#"" $##$$&&$$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot1.lmp0000644000175000017500000000062311357170242024366 0ustar keeskeesTUVWeu *Hd & RS 33 bb  3 bb$33333 3 bb$$ $3S3bb  bS3abbc!!!!3333 bS TTkjjjiji 333 3RgefRSS  Q QR333$33$333bb333$bb 33d3 # 3b b 33ea3 3bgbg 44gbb3333 3aa3a3 33RRhiS $ 3 deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslotb.lmp0000644000175000017500000000060511357170242024447 0ustar keeskeesTUVW_p6Tozzzzzaa }}}} z}}~~ aaz |} ~|%%$  }{~|~#VR $(㭀zT(''}}}%U%UUT ~||#U|Uaaz~}}%%|}}  zaz} && aazz deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmc7.lmp0000644000175000017500000000220511357170242024306 0ustar keeskeesV`ir| (06>FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ## ##""%#%%loloolntropvtmnvrlltpkkoojlo#""%% #####&( # $## $ & #  %%  ####   ####&  ####&  ####&""""####&$$ ##""%%##&&$$#"" $##$$&&$$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegem.lmp0000644000175000017500000000225411357170242024225 0ustar keeskeesV`jw #-7?GOW_gms{(4@LXcmu} &0=GQ[cmw  %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##""$$$  ""%##  ## $#ښٛٛ""ٞڙ  ##"##%""  ""$%$$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpiecef1.lmp0000644000175000017500000000077311357170242024324 0ustar keeskees# *5@KValw   $       &$   &  &     &    &                       $ &  &  deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmf2.lmp0000644000175000017500000000234411357170242024310 0ustar keeskeesV`jw #-7AKU_is} ".:FR^jv $.8BJT^hu  %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%#"$$  "%##  ## $#  ##"##%"  "$%$$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmf4.lmp0000644000175000017500000000225411357170242024312 0ustar keeskeesV`jw #-7?GOW_gms{(4@LXcmu} &0=GQ[cmw  %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##""$$$  ""%##  ## $#;@@93>AB<9""@,,>9@,B>8"">B@;59A>95  ##"##%""  ""$%$$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fontb61.lmp0000644000175000017500000000026311357170242024072 0ustar keeskees (9J[m     deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/chain.lmp0000644000175000017500000000663511357170242023706 0ustar keeskees )1;EO\fpz$.8BOYcmu!+5BLV`hr| (5?IS[eoy(2<FNXbly   % / 9 A K U _ l v    " , 4 > H R _ i s }    ' 1 ; E R \ f p x    $ . 8 E O Y c k u    ! + 8 B L V ^ h r | $##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpfull1.lmp0000644000175000017500000000243411357170242024207 0ustar keeskees96Wx1Ke}>^~"6Lb~"""#  $ "" "  ""% $ "%"% $ %"  # "% %" " $" #$"  "$"#$%#"" #  "$$$%### # " %  $#%##% ## # # # # ##  """$% $% $#""# %"  #%$%#" "#% # $#$% %%$%$$#$$ # # " #$##$#$%%%% % # #$"" "" #  $%$##" "# %    % " " %%  %   " " z &'& z z % z deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm3.lmp0000644000175000017500000000211511357170242024314 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQUUUXXυ΄抈ЇXUQQUUUUWSQQVUSSSSiTTRRXSSQQ`ii\\iiYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQUUWWVQQWWUQQdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmf5.lmp0000644000175000017500000000225411357170242024313 0ustar keeskeesV`jw #-7?GOW_gms{(4@LXcmu} &0=GQ[cmw  %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##""$$$  ""%##  ## $#""Ŀ  ##"##%""  ""$%$$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpiecec2.lmp0000644000175000017500000000063711357170242024321 0ustar keeskees <LXt!Aa # # # # ##   """$% $% $#""# %"  #%$%#" "#% # $#$% %%$%$$#$$ # # " #$##$#$%%%% % # #$"" "" #3 deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmc3.lmp0000644000175000017500000000220511357170242024302 0ustar keeskeesV`ir| (06>FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ##  ##""%#%%υ΄抈Ї#""%% #####&( # $## $ & #  %%  ####   ####&  ####&  ####&""""####&$$ ##""%%##&&$$#"" $##$$&&$$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm4.lmp0000644000175000017500000000211511357170242024315 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQU9;UU9;;9XX=BA;>,B:=,A9FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ## ##""%#%%'''+-',21+02)/1'*20&--%''#""%% #####&( # $## $ & #  %%  ####   ####&  ####&  ####&""""####&$$ ##""%%##&&$$#"" $##$$&&$$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslota.lmp0000644000175000017500000000057311357170242024452 0ustar keeskeesTUVW`kx6Pcryz77:94499=@@<44<ACEFFFGGGGGFFGEEEGHGFGGGFFFEFGFGFGFFFFGGFFFGFGGFHGFFFHHFEFFEGFGGGGGGFFGGFEEFFHHGGDFGHGFFEFFGGFFGFFFEFFFGFGGIHGFFFGGGGEEFFFFFHGGFGFFFGHGGGFFGFFGHHFGFEGGGFGFFFFFFFGFFGFGGEFEEFGFFFFEEFFGGFGFGHGHGFFFEC@=<<86420.)$ $*/3589;>@ACFHJJKLMLKLMKKLJKJLMKKKKJJLKIKLJLKKJJKLKKKLKLKLLKLKKKKMLJJKKJLKLKLLKLKLLKKIIKKLKKKIKLKKKKJKKKLJKLKJJJKKKKJKLMLKKKJLLLMJJJKKLKLMKKLKKKKLLLLKKKJKLLLJKKKKLLKLJKKJKKKLJJKKKJIKIJLMKJKJJJKKKKKKKLLLLLKKJJGDAA@=:9642-("  $).38;>>@CEFHKMOOPQQQQQRQPQPOOQRRRRQPOPPPPQPQPPOPPQPPRRQQQQQQQPPPPRPOPQQOQPQPQQOQPQPOQPPQRQPQQOPQPPPPPQQOQOPQPPONQPPPPOPPPPPPQPPQRQOOPOQQQQPPQPPPPPQQQQPPOPOPPOPQOOQQPQPQPOPPPQPPPPPOPQPOQRPQQQPPQOOPPOQQPQQQPONNLIGFEC@=:872,&! #)/27;60*&!   #'-37;@FIKLNPRUVXZ[]\[\\[[\Z[[\ZY\\[[]]ZZ\[Z[\\\\\\[[[[Z[]\]\\\\[[\[\[[Z]]\[[^]\[[[\[ZZ\\[[\]\\]\\[\[\[[\Z[[[\[\[[[\]\\[\[[[[[\]]]\Z[\[[\\][\]]][[Z[[[[]\\\[YZ\\\]][ZZ[\\\[[[\\[\]\\]\\\][[[[\\\\[[]\[Z[\[[\[]\]\ZXWURPPNMJGD>:5/*%   $(-28<@DJMPRSUXZZ\_`a``aa``a__`a`_aaa`ba``a`_`ba`aaa`````_aabaaaaaa``a``_aaa``cba```a`___```abaaaaa````aaa```aa``aaaabbaabbba``ababa`````baa`abaa``_````baab`_abaaaa___`a`a```aaaaa``aa`ab``````````aa`_`````aaaaa`]\ZWVUSQNKHB?:4.*$   !',16:@DHMPTWXZ\^_`deeddfdeeeddeeedfgfegffeffdefedfeeeddedeeffffffeedefefeeeeefffgedefeeedfffffffefeedecffgeeefffdffefefffegfeffeffffedeeegfeeffeeefefeeefffeeeggffeedeeeedeeeddfffeddeffefeddedddeefdeeeeefedfeedefcb`]\ZXUSPKGC>93-($  %+05:=CIMRVZ\^`bdefjkkiiljjjkljkkkjlmlklkkjkljkkjjlkkkiijjkkkkkkklkkjkkklljjkkllllkjkkklkkllkkkklkljjjihkllkkkllljkjjkjjkljlkkkkjkkllkikkkllkjkljkjlmlkkklkljklmlkkkkjkkkkikkkjikkkkjjjkkjkkijkiijjkljklkkjkkjkjkjkkjheca`^[YUOLHB>83.)"  ")/49>CGMQW[_adfgjlmorpopqqooprqppqqrrspqppopqoqqqoqrppppoorqpppppqpqqppqqqooppqqqqpqrpqqqqrqppppqqrppoooqqppqqqqqoppopoopqppppqpoppqrrpqrpqqqoprqqoqrqqrqqpqqqrrqpoppppppppqpqopqpopoppqpopqooqpppnprqrsrpoppqpopqppomjhfeda^ZTPLFA<83,& $,28=CIMRV\`dfhkmoqsuwvuvvvutuwvvvvvwwxvuvuuuvuwwwuuwuuvwuuwvuvvvvvuvwvuvvvuuuuuuvuuvwuvvvvwvuuvvvvwvvuuvwvuuwwvvuuvvuuutuvvvvvwuuvuvwwvvwvuuvttwwvtuuuvwvuvwvvwvvuuvvvvvvvvvuvuvwvuvuuwwutvvuuvvvutvwvwxwutuuvutvwvvtromljieb^XTPKE@<6/)" !&.4;AHLPVZ`dhkmprsuwz|{yzzz{zzz{{{z{{||{zzz{{{z{{{zy|{z{{||{zz{z{zzzz{|zzzz{zzz{z{z{z{{{{{|{{zz|zz{{|{{z{{{{{{{z{{{{{{{{yyz{{z{{zzzzz{|{z{{zzzzy{|zyzyzz|zz{|zz{z{{{{||{{{{{{zzz{{zz{zz{zyz{zzzz{{yy{{z{{{{z{z{{z{||{ywtqpomigc]WSOID?92+$#*18?FLQU[^cimpruwxz|~~|{wutrnmhb\WRNHB<6.'   &.5ELSZ`glpuz~xsmke^WNHB<3,$%,3:AHOV]cjpuy}xrnhaYRLE?6.&   "*074.% "*3FNW^fow}zskd[RJC81)  %.7@HOXaiqz}umf]TKC:3+" '/7@HOZcks|vog_ULD<3+" '/7@IP[ckt|wpi`XNF<2*" (19AKS]emu~ļypjaYPH=4-$  *2:BLT^fovȿzqjbZQH?6/%  "+3=DNV`gpxü|rjc[RH@8/' #,5?FNWahpzƿ}tlc\TJ?8/' $.8@GOXbiq{~vmd]UKA90' &0:AIQYcls|¹xoe^UMD;2(   (1;BJRZdmu|ûyof^VME=4+# "*3;BKS\dmw~Žyph_XOF?6-%  #+5GOV^goyɿ|skd[TKB90(  %.6>GOX_gozɿ|umd[SJB90(  %.5>FOW_hpz|umd[QIB90(  $.6=ENV_ipy}uldZQIB81) %.5FMU^hpx}umd[RKB90(  %-5>FNV^iqy~umd[SKA91)! $,4=FNU^ipz~tle[SKA92)! $,4HOW`iry}ukcZSJA91) %.6>GNWajry~wlbZRJB90( $-6>FNWaiqz}vlbZRJB90'  $-5>ENW_gqz}vmd[RKB91(  $-5>ENV^gqy¹}tme[SKA92*  $-6=FMV_gpx¹|skd[TKA82*  %.7>FNV_hpx|tke\SKB81*   %.6>GOW^gqy¸}ule\SLA70)  %.6>GOW^gqy¸~wme\ULA70(  $/7>GOW^gqy¸~wmd\ULB81( $.7>GOW^gpx~wmd[TLC:1(  #-7>GOW^hpxvlcZSLB:1)  #-7>FOW^ipyukcZSKA90)  $,6=FOW_ipz~ukc[SKA90(  $+5GPW_how}tlcZRKC91(  $-6>GPW_hpx}ukc[SKB90(  $,4=GOW`iqy}vlc\SKC:0)! $+4=FNV`ipz}uld\TJC:1)! $+4>FMW`hpz}tkd\TJC91)! #-5?FNX_hqz}ukc\SKB91(! #.6?GOX_hrz~uld[TKB:1)" $-7>GNX_gry}ume\SKC92)!  $-7=GMW_gpy}ume\SJB92)   $.6=FMW`goz~umd[TJA92)  %.6>FNX`foz~tlc[TKA81)  $,4>GOW_gqz~tlcZTLA80(  %,4?HOV_gpz~umdZTLA80) %-4?HOV_gpz¹~ume\TLA80) $-4?GOW`hqy~ume]TKB81)  $,5?GOWajrz}umd\SJC91)  #+5?GOW`irz}ume\UKB81*  #,5?GOW`hrz}ule\UKB81) $-5>GNWahpz|tkd\SJB80' %,6>FNXbhoy{tld\RIB90'  $-5>FMWahnx{umd\RJB80(! #-6>GMXahny|vme\RJC91)! $-6>GOXahpy}uke\RJC91)! %-5>GPXaiqx}tkd\SIB91)  &.6?FOX`hqx¸|tlc[SIB:0'  &-7?ENY`hqx¹|skdZRJC90'  %-7>FNY_hqxº|skdZRKC90'  $-7>GNW_hpxº|tlcZSKC91(  $-6>GNV`hoy|tlc[SJC92)  $,5>HOW_gpy~tkd[RJB92)  %,4>HOW`hqy~tld[RJC91(  &-5>HOWahqy~umd[RJC91(  &.6=GOWahpy}ume[RJB81)  %.6=FOY`hpz}tme[SJA81)  $-6=GPX`hq{}sld[TJA91)  $-6=GPW_hqz~slc[TJA90(  %-6>GOW_hqy~tlc[TJA90'  %-6?GOW_hqy~umc[TKB80(  $-5?HPX`ipx¸}vlcZSIB90( $+4=GOW_ipx¹}vmd[SI@80( $,4=FNV_ipx¹}vmd[RI@80' $-5>FNV`hpx}vmd[RJA81' $-5?GOW`hoy}ukd[TKB92( $+4=FOWahpz|ulc\RIB:2(  $+4=FOW`ipz|ukc\RIC:2) $,4=FOW`ipz|ukc[RJC80) $,4=GPW`hpz¸{tlcZSKC8/(  %-5=HPW`ipx¹|umd[SKC:0' &.6>GOW`hox~tld\RJB91( &.6>GOW`ipy~tld\RJB91)  %-5=GOW`iqy~tld\SKB91)  %-5>GNXahoy}uld[SKC91)  %-5?GNXahoz|ulc\TLC90)! %-6?GOXaipy|umd[TLB90)! %-6=GOXaipy|uld[TJA91)! %-5=GNWaipy|ukd\SIA92*! &-4>HPW`irz}vld\SIB:3*! %,5?HQY`ir{}uld\RJC:2)  $,6?GQY`irz}tkd\RKB:2(  #,7>GPX`iry}skd[SKB:1(  $-5>HOY`hqy|tlcZTLC:0( %-5?GOY`hq{}tlc[TLC91( $.5>FOX_hq|~tlcZSKB91( #.6=FNW_hq{~tlcZSKB91) #-6=FMW`hpz~tlcZSKB92)  $,5>GOW_goy~umd\SKB92(! $,5>GPX`gpz}uld\SKB81)! $-5=GPW`hpz|ukd[RJB80(! $-6=GPW`hpy|ukd[QIB90'  #-7>FPX_gqy}tkd\RJA91' $.7>FPX_gqz~umd\RJB91)  $-6=GOW_hqz}tldZSKB91)  %-5=GOW_iqz}uldZSKB91) %-5=GPW_ipz}vmd[SJB91) $-5GNV^ipx~tkcZSKA:2) $-4>GNV`ipx}tkcZSJA90(! %.4=FOW`ipx|ukdZSIA80(! &/5=FOW_hqy|tld[QIA80(  %/5=GPX_hqy}umd[QJB91) %-5=GQY_iry~ume\RKD91) %,4=GQY`iry~ule\TKD90( %,4>GPZaiqy}ume\TLD:0' $,6>GOWajqy|tmdZRJD:0( %,5>GNWajqy}tldZRJC90' %,4>GNWaiqy}tkdZRJC90' %-4>HOV`hqy}ukc[RIB:1' $,4>GOW`hrz}vld[SIA:1' $-5>FOX_iqy}uld\TKB;1' $-5?FOY_iry|ukd\TKB;0( $-5?GOY_hrz|ukd[SJB:0(   $-5?HPX_hqz}vmdZSIB90(! $-5?HPX_gqz}vmcZRJC90(  $,6?GOW_hqyº|uld[RJC90( $,6>GOW`hqx»|tke\RJC90(  %,6=FOWaipx»|tke\RJB91)! &-5FNV`irzȿ}tkd\SHA9/& %/7?GOW`iqy~ukd\SH@80( %.7?FNX`ipx~vld\RHA91) %.6>FNX_how~vle\SIA90) %.5>FOX_gnw~tle\TKA90)  %.6>GPX_how}tld\SKA91)! $-7?HPX_hqzɿ~umd\RIB:0(! %.6>HOW^gqzɿ~umd\RIB90(  %.6>GOV_gqzȿ}umd[RIB80( %,46/&  )0:CIPX`fmuz~wqibZTNF=5-$ '09AFMU\ckqw~{tof_WQLD;3,$  %.6>DJRY`ims{~xpkd\UOIA91+" $,4:@GOV]ejqw~ztmf`XQKE>6.(  "*28>EMT[biouz|wqkc]VOHA<4+&  (.5;AIPW]dlrv{|xsmha[TME>82)" $*18?EMTY_gmqv|~xsojd^XPIB;3.&    '.5GNTZ`ehmtx{~~|yvpje`[WQIB;5.(  !(.5;CKQUZ`ciotvy{~}{ywuqlea[VRLF?83+% $+28@GMPTZ_eknpsuxy{~~zxwusokfa]VQNHB<50(!  !'/582,$ $,28>DHLQV[acehjknpsuvvvvttvwutuuvwvvvvuvwvwwvuwvvvwvvuwvuvvvvvvvvuuvwvvvvwvvwwuvuuvvvvvuwxvwvwvvvwvwvwwwutvwwvvuuvvvvvwvvwuuvvxvvvuvvvvuvuuxwvvvvvuvwvwvwvvwwwxvvvwuuuvwwwvuuuvvvvwxuuwvwwvutuvwwvuuuvtwwwvuvuuuuwvutsqnligeb]YSNJD@;5.(!  "*05:?DHLQW\_acegilnopqrrpprsqpqqrrqqqrqrrqrqqqrrqrsrqrqqqrrssrqqqpqqqqqqqrqqqrqqqsrrrqrqrrrrrrqrrrrrqqrrpprsrrqpqrrrqqrqqqppqqsqqqqqqrqqqqqsrpqqqppqrrsqrqrssssrrqrrpprrqrqqqqrsqqrrpprrrrqpqpqrrrqqqqprqqqpqqqqprrponligec`]ZVOJFB<82+$  ',0684.'   "',17:4.*% $)-05<@DGKMNPRRUXZ\]\[[Z\[Z[[\\ZZ\[[[[\]\[Z[[[[[[[[\Z[Z[Z[[[ZZ[Z[\[[Y[]][[[\\\[Z[\\[Z[[[[\\[Z[[\ZZYZ[\[[[[\[Z[\Z[[[\]Z[\[ZZ[\\\[[[ZZ\\[[\\[\\[\[[\\\\\\\ZZZZZ[\[ZZ[[[ZZZ[[\\[[ZZ\\Z[][Z\]\\[[\[[\\[[[[[ZZZ[\Z[\[[\ZWUSQNMKHEA=84/*%   $)-28<@BFHIKMNPSUVXXWVVWVUVWWWUVWWVVVVWWWVVWUVVVUWWVVVUTVVVVVVVVWVVUWYXVVUVWVUVWVWVUWVVVWWVVVWVVUUVVVVVWWXWUWWVWVVWXVVWXVUVWWXVUWUTVVVWWWWWWWWVVVWXXWWVWWWVUVWVVUVVVVUVWVWVUUUUWWUVXVVWXVVXWXWWWWVVVWWUVVVWUUWXVWVSQNLIHFD@=840+'! $)-37;=BBCEHIKNPQRQQQQRQPQQQQPRRRQQQOPRSRQQPQQPPRRQQRPOQQRRQQQQQQQPRRRQQPPQQPQRQQPPPQQQRRQQQRQPOPRQRRRRQQRPPQRRQQRSQQRRQPQQRRQQSPPQQQPRRQQRPQQQQQRRQPPRRRRPQQQQPQRPQPQSQQQQPPPQQPQSQQQRQQSRRRRRRQQRRRQPQQRPPRSQQOMLIGECB@=:4/+'#   %)/369<<=>BDEHKLLKKKKLKLKKKKLLLLKLKKLLMMLKLLLJKLLKKLLJKLLMKKMKKKKLLLLLMKJKMKLLMKJLJKKKLLMKMNMKIJLLLLLKKKLKJKMLLLLMKKLKKLKKLKKMMJLMLKJLLKKLJJMKLKLLKJKLLLLLKKKMLLLJKKKMKKLMLJLKKLMMKKKLMMMLKLLNMLLLLLLJKMLKKLLLKIGFDA@><;860+'#  !%+/235789<@@AEFGGFFFGFFEFFFFGFFEFGGHEGGFFFFFFFEEFFGFFFFEFEEGEFEEFGGFFGEEFGGHGGFFFFGGFGGGFGHIGEDFFEEEDGFFFFGHGHHFFEFGEEFFGFEFGGEFGFFFEGFEEEDGGGGGFFFFGFEFFFEFGFFEFFGEFFEFHHFFFFFGGFFEEGGFEEEFHGFFEEGFFGGFGGGEFDEB@>;985420-(#  "'*,.01357:;=@AABA@ABA@@BBAAB@@@ABBBABAAAAAAAAA@ABBABAA@A@AA@BA@ABBAAB@AABBBBAAAAABBBBABAABCBA@@@A@@?BA@ABBCBCBABAAB@@ABB@@AAA@@AAAAABAAA@?ABBBBAAABBA@@AA@AA@AAABBAAA@ABBA@AAA@AAAAABABAAA@BBAA@ABAABAABBB???@=;96420.,*)%   "$')+-022467:<<=<<=<<<<<=<=<;<<<<<=;<;<=====<=<===<=<<=<<=;<==<==<=<===<;==<;<===>>=<=>=;<>==<=<<<<=>=<<<>><===>==<<<<=<<<<<<;=<<<<=<==<;;;<====<<=<===<;;<<;<==>>=<===<=<=<;;;;;<==>=<===<==<<<==<==<<=<<;:;;8632.,**)'$   ##%(+-,.014667667666667687677766756667788767777877668777667878868688866776567778976787668788866667887668878778776676766766677866776787666677887777888656766687887788867786566667788867876777667767777766656530.-)'$$#"   "$''(*+.01100100000002312221110/11121100120232101222110012111102331122000112121011010112311011011201112222222112011120/01220/201011111011123212222001212112112222312211011112221110121112110212022011201/.+(($"  !"$&&)+,,++,+++++++,,+,,,+++**+-,,++*+,-+-.-+++,,,,,+++,+*+++,--,,-,+++,--,,++,,*+**+,,+,++++*+,+++,,,,---,,,,*++,-+*++-,**,+,++++,,+,+*,--,-,,,*+,,+,++,+,,-+,-,-,+,,--,,,,,++,++,+++,,++,--+,,+,,,++*(%""   !""&'(('((('''&'('&&'('&&&%%&'('&%&'''''((''&''&'''''&&%&'''(''&''((''((&&'(('&&&&'&&&'&&&'%&'&&&('''('('&'(&'&&&'''&((%%'&&&'&''&'('&('''((''&'((&&&&''&''&'((((&''(('('&'%%'&&&&&'((&''(('('''&&''&#   !"##"##$"""!"""!!"#"!! !! !""" !"!""""#""!!!!""""" ! !"""#! !"##""""!!"#""!!!!"!!!"!! " "" !#"!!#!""!!#!" "!"#"!#" "!!!"!"" """"#!!!##""!""#!!!!"" "!!!"###!!"##""" ! !!!!!!"#"!"!"""#""" !"!                                      deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/menufog.lmp0000644000175000017500000001000011357170242024241 0ustar keeskees99!,,EE999JRjjJ9EE^^JE9,!,!+)ajrrrjJRE9,!!!!,,!!,E,!!!!!99J^j^JJ9Jj^JE,,,,!%Jcsrr^^J9,!!,!!!,99EJRE!!9EJjjjRR^rRJD)()!%8Mi~rRJE!,E!!9Jj^9!9J^r^I3!!!%-;`r^RE!!9JJ!JrJ!!!,JjrrjD4! 1>]j^J9!E^^99jrjE9,9,,9ERrjP4#!'#=Jqrjrj^J9!JrE,JJj^^RJRJJEJ^rZ= 3LLk}rjrr^^E!,JJ!!,,JRj^jjRREJj`8%%DuȯŨrrjJ9!,!9JJ999!!!9J^jjrjRR^jiP0 +Yĵj^E99E^rRJRJ9!!EJRrjj^^^j͹~`P3/^}j^RR^rjRJ^RJ,!,,,EJ^^^^j^rvT,>enifeif]T^rj^omo^JRR^RE,REEEJRR^jrr{PayeRIENQE;Dir^Re{qQEER^r^Rj^RJJRJjraE=>HJE9>Nw}rJJEZuZE9E^jRRR^jXD@P``UB>PZ\j^^J,!,YrmN999J^rj^RRRjurJ>HgwYIDIDEE9!!>n~`>,,9EJ^RjRRRJJRrȫrrrr^NZP54Hw˗iFA>8!!)NnN3!!,99EE9EE9999ER{˵^R^^^L484%'RkLE8,!)bfb@,!,!,,,,!!!!!,,9Jmȳj^JRRc3,9EE,9^wr{fcirU/@N`VU]mZ%$@gq]5,9EE99!!Rrwwecoz>)!EaRVYms;09emN3/49E9JJE,!!9j}~aD!9QicVkwgcfifH7;f{{reQ>)9ALU^ZYRJE9J{şuRJJ^gn`{^LEEA@P^^YTPUr~j^^jyqmR@58/7AFZw̷{VMacr7 $'0=EFELV`nriky˼jjjrrjj^RQA4,1=879LnϣjPIby<$(,3'/Qc]MBJuR7Fc}k\QJII>;qw^F@7DFHUgLABHfrr^RE;/!(Mm{wmTNi`>';joTB;DEFcsZNL\\wzwj^^jrrrj^Q>0 )MfgU7(=`fa@0-BnnjVF43Jsk]^X\JQbjJ9,,,J^rrrj^L5'#580)'4DJ@408ArjE($1^yzfXaJ99EJrrrjE,!Jjrj]P,#>HMLH98<>7Pnz{}{rM(-F^QQJE,,9E^r^J9!!EjU' 7YwniQB589)-DY`jooT((99JE9,,9^rRE!!,Js>#!4IjjJ9!99'!>I\afQ+3EJRJ,,,Jr^E,9,,,9JrjjoE-(+YsjRE99Rrj^RRJRR99EjjJD4@@L]^^J99JV5(4HJPUfzjRE9E^rjRRR^JRr^jRE!!,Rr^JJEEJJRrrjRJ^gN0P\i}jJ99Jj^RRJR^RJRrrRR9EE!!!,Jj^^JJJJJjrrg, 5Ii{mYJE^rjRJJRRJ9JR^^^R9,!!,!!!,JrrjRREJ^F-IzoaX^jjREJJRE!,9EE,!!,,!!!E^rj^rjRJJ^rͼs3Iٱkjnuor^RR^jR!!!,9,!!,9E,,J^r^JJ^^̪`;#YjY^kj^jjE,EE,,!!!EjjJJJRj͹g<Zͧz`R^wrrr^,EEE,,!,,!!RrRJEE^rU#PÜs\Ve~^^jjE!,EEE,9999!!ErJJEEERrU)Akk}rJJRj^E!!,JJE99EJ9,!^jJJEE9J^jrjoveM- AjE,9Rjj^J,!!^^^RJRRE!9JJRJJJJ^jj^c^IA7+9R^J!!,9E999!,jrjjrR,!!9JRJRR^rjrjLHADNLUbjJ,9RJ,!E^jrR!,ERRRRRjrjM5H`eVNXanrzsrqyjJ,9JJ9!,JJRj^,,J^^JEJ^jjjI7TiaMIJNIJUPM>BABEHLORVUVX[Z[_gjibw̾pdYVTNIMSQUWX[\XUPNMNLKMV[`acegjhfa_`][VKB?>DHCD>=;=;?AB?9797:=DCECB@?>=?@?@BGIHIKMJIDA@<68;BR^cjkly¬ªzgZRIECDINOPX`knqktŠŒ~yxrjefgibRJF@EJMRW\dcWX[pkVYZTQPJKMJIH?@ACHIKRVWVY[ZY\^cklgds̽yj]XSMJOTVUTUVYXTPMJKMIKJLUZ_^`agijiea`^_[NFA<=>@=8789>@DCA?ABACEA@BACDHIFEA?>=9:<8:><=?>BA=<=?@BEGIJHIGFEB>@=;<@EDCA?>=?@<;=ETZaeft§©­|kZSJDHEPRSZblnojpzˆÄċ}zsmfhfYNJE@FHKOUY^g[R[jpVOUYSPKGHIGF?>A@DINTWXWX[YZ[`glgdlɺ“xk^VSPMPUWVXVUTOJHJIRY\]`gigf_^_]XVLDC=;8<:<>?ABAB>;9:>BDEIKONJFCDEIJHEDED?>?>=<=;BJW[bfds¥¬éˆuaWSIFGHKRTRV[imklxÌ~zvngdgfie]QNG@EIHLUX\e_MSjÎvZOSVTNPMGEGE=@CA@FHKMUVWX[Y\]afkedq̼}pdZUPNSTVWYWVXUTQMIJIJLY[\]_cha\_^]UMDA=:8:;>?BACB>:8AEHIPRQNLJEA@BCECB?@>@A@?;=A?=>;>LV]ehebj|±¿é£¬‰nZXNIFGLRUSUZcknkr|‚{vpjfeg_UMHBDHJSVZbPNe~y_PRWTMNMHGCD=@CABEHJPVXWVZYWY[\bhcgt³“vi_VRQPQSWYXVUQJHJILKS\Z\[]_fifaZ\^\WNG>=>97>?BCECB?@=9>AFNOUZXTSOKJHEB@>=BDCDEDECABCBDA@AFHQWX^dfdhn´»©ªªva]UMFGJPWVWZ^jmomrw{„~yrjecfe`XQJABGEINUV`dQK`{zeQLSMOMEFEC?BCAGIKSWYX[YX][_ckdeizϵ}mf]RQOPVWY[YTUVUMHIKGKPSZ]\ZY[fifc\Y[\^XQHA=<:>BCFEGFEDABABEIHRW]^c]\WSRNKJC@>=>ADEGFHGHFCDCDFCDADEILOSR\_dnz­yg^[UIJKNTXVW[ckomov~‹~xpfdbeb_[TJDADEGKPRXcZGUsŠ~mZKPTOLNIFDAD>AFILSXY]WVZ\]^eicei|írje[QRQSWX[\VSUWPIFHIJRTX_^ZXZ`hjb^YZ[]SG?><=CEGIHGJHIDFLMPTZ^ce`[WUSPJIFB@>@ADEFGHJIKJIDCEFDEDHILIJKTVXgu£££{zib\YPHILMYZW[_jrpsu}}~Œ†|yshcbca\SMGABCHMQX^]HOh~s_PLQOMNJED@A@CA@EGJOWXY[X\[`gecdnѶoh`WRTVZ\URTUWTMGHMY]_^X\fhc^WX\XI?;=A>@CEIKMLMJHKNPUZ_ac^ZTSPSQPOMLKGFCDCEFEIKJLIHGFECECDGNOLJHKQOW\k»·¥¬}vz{pa\_VLKJLT]Y]grnqsz~z~‹zuldc_`a\ZOF@?AFLNQZ_LK^|wgSJNPKNLGD@A?CA@DIKPVWX[VX\]_fdcepūxmf^TSRSW\YTQSUXRKFJHS^]`^\XWbieaZYX\[ZKB=A@CBDGFIOQOQUZ_dfeb_WVSTW[]chlheb`^UQNLIHIHLJLKMKJIFGHFED@<8DQMIFEAENLTmľ{ovpa][XNLKPX[Z[iuphmrx~zwy}†{pgcd`\TJC<>=@HLVZGKV|„}s_PINMNKB>ACFIMSVWZ[WRX\]bd`ckxʼ}qf`XVUSUVX\XROQSUOGDFGIZfeda\UbicZWVX\ZXNE?>A?ADGLOQPS]iqrog\Y[Y]`imkgcfd]WTUSQNKLMLKHEGHDECB<94AKPLFDACEGD[~ýœ­us}ha[YOIKJOV[YVdprgfnw{|yxu{‹‡|rfgc`^YRKD><@EJKT[YKIPn„|uaSHLMPOKE=A@FIHMSUXUXZTSX\_ea_bozôzmd^YUVZ[TMPQUQHCEGP`hdf_Y[hZUWYWRHD?A@?9?8Pj›¸·Ü}tzŒye^YPLKIJRVXWYhpkagutxzvwy|‰Çvgfa]SLE@<=>EFMN\ZNJNd„{zdRLJNLQOI>CA@EHJNRVUXYSUX\[ae_cq}̿}tnd[WYTWY[VRNQTNDEDFJVfd^XcicZUVWXSTMEA@<9<97/2BFD@A;84?Yr·¡¬zr_[SIJLPVYXWbmj`hquwzwuv|‹‡‰zgcfd^]\TLD?BAGHIPRTW[VRSYZ\`_et}ĸ{sj`\YXVWYZ]PNONRPHDEFQbgfe`Z\ig^TUVXSTPKDBD:897>INSUVap}|sjghpuprzvojf_bhojf`ba][VRQJMNSUTRSPNMHE@?BDBCD@605?FC@<627Id{·û¢ì~e_TKIJINRW\hj`bmtqtyv}Èzmdecb^UMGB@>?BFHOX`TLOZ†{fQNJKLPQSR@B@CHKORVTXTQTYX]\`[^lu|{th]\XUV]XOMQRKEDFGHYhgb^XcheZQSWVTROKDB=6859BLR\^_uzquy~{|{tonjhrw|{usth_`ZONMTUXWTPOLGCB=@BCDCDBA=704>C>85BVn½¡îmbXQIJIMQTVUWaha_houy~‰ˆtdec_]VNHBC=AEINVaVMYx~mQMJKIMRURDC@BHGKORTUXUQPTY[^]\`mx~̼|~}pf]Z[XWY\[VNOPGDGFDO_e^[Zi_RQVTPI?;8678?IPZejuxu{vy{yvx}~}sjisfYROKJMPUZYVSMJEFCA=@DEBCB@=606=?>75=AFHKV`XOUrqSKLHJQTGA@DGILORTWXTPTXZ]Z[eozDz{~xnc]Z[V[\YQMNQKEFGHWdc^_\WcjdUMRWYWTND978:79AHPThs}vx‰~|{…‚yupdZPJIGJMV[][SNIMIA9:@?B@BA@7458=:87:@Jew²ndYPLIJQTSVX]e]chinsvy~‡xkeba\[OHFDB=@BGJR`]SQPm€x\IKLHKPRWIA@DGILORTUWSQPTVYXY`fr{~ynb^\ZVXZ[WQLQLHDEFEJ]eb^\YZgl]RMRX[ZUK@3=7:=CJM`vvxƒ{tq_QPIHIOX]\_`c\QTVOB67:?AB=676<9:;@Ppyvz´ uicZRGKPRU[ca^insuÇznicb`\RIGE@>@CFIR^`SRQj…|aMHJGKSXLA@FGILQRTWVRQUVWYXYairzθ|sia[\[VW\[QOMPHEISab_][V^jh`RMQX]\WPH5BFJQ]`YSUi…~jQHKHFIQYPABGIHMRTXRQPOSWVUYbls|Ȳ{oia_^X^XONMOFDGDHKYa^ZYdkf\ONS^a^SJ=6?A?;>DNSh~“ˆ““rcZQLINRZ[]emngb`d[RC9@BEHM\a]XSgoWFKFCJYSAGHJOQTRVTNOQUTS\dluyڿunfb_\W\_SMKLKCEDGR^`]X[_ikaVLKUac[SG79BA@DLTa³›od[QHJKPW[hpokeacj_J;@DIOPKC<;<;CLQOJ@>=><:><=><=;DbnpliacüywvpoeOCFJNLRXW\[decdntvÆ}uqjba^[OIKJGADJPV^aZWk{oOGIEDCNS?DGILOQRSUQMRTQT^fmp|²rjkgb\YV^`YOIHKHDEDHQ_a_`^bgkeSJU[`YVK>?B@AOS`}κxlnqpmg\PQT]gsr}~tjlstynI=?@MPSIA=?=>?:P`^e`Yq«vztpjTBFGKHOQVW[Z_dbfiswu~†‰xtma_ZRHJIGD@FKPT]`]Wh€}vVEIEBCHS?FGILQRSVNPSQPMT`fns{ھ™~mlif[XW[_`VJIJHECKZa`a\ahieYJLSZ^b`WRB=BAIScqnmjnonja[Xcins{~~|[IDBJRSTNE>=>?B>BNPX^]Ve£Ÿz}|zqoZCBIKGMSWZ[^eadfrwv}zvob]UILJFDEKRWY`aWe~w]HFCDS@EIJNOQRSVOKNRSRMNT`hlrѶunjid[X^`_VJFHIDECO_a`a^biZPIS\^b]WJ=?BAHM[|̽¿rqojkofbecp}’‡rWTIMRTXWMD>?>?CF>CNLUVUaz|ysn[ECDFHJMUWZ\c`hovu{ywpc^]WKGCEKRVZ`Wc}uaHGBCP@EHLMOQRSTLJNPRONV_hjs|˳romh][X]^`\TGEIGEDIV`b^cicTJPZ`^_aYRC>BFLQd³ľº|vqmjlnstnjgdrq^[Z\Z[WID>=CFC=CGNRT`°¨z~{wraKBGIGELUVY]dbahnuvy…{vsfb_]ZOIMLJDEIPVZa`Z_~xcGHFDABN@EJKMOSRSUJPQONLNX_hjr}˰smi]YW^`aZNEFGFEGECL[a`_]ejaUJU^cba^XO@ADJV\pþ¿zrgjmpmnsvtovvjnide^\UMD=AH>=CIPTZx¯¢~}yqfMCABHFEHQTX\bagmtvz†„|wrgcea`^QKLKEJRXZ_`Z[€zdLGFDACMAFKMQRUSKJNPNMKNU_gkt~ǪzrmldZW[^_bXKCDHDEGDEP`_`^aej_MO[dabcYTJACGIUdgÿ½õâ£uklqlpwzŸ}rtrof_[WPC:>HIB9:;EIUh|¨uoaK>CGHEDGNVYagdblruz‡}zvjeheb`YMOKOJFHOX]`c[Ys~jLGIGCBJBGLMQTUQGJPMHIPVbjlt׶tqpib[Z^bc]PCEFEO_a`_`fjfYKZbca]TQLHEMXfo|Ǿ•|tuvpc`\UOA8?KHD<679?I_x§¥‚|oqgP?BGCBDQY]bgeltză{umglfecVNQNLHLW^`ca]dx}yXJIJC@JCJMKNPRUVMGLMIEFHRV`movȱspopi_Z\bcaUHDEFICJVefaedeid[PT\c`[RLTX[r~py¥©¥©z~rns}zfVPJ?8;IHC7:GCMLMOQTUTEKIFDCJRU_oqzؼ}ropg`_`b`[QHDFHJECPdifegedea\URX`a[TLTWby~nlvž·©§rhmvreVID>7CLJA>CBCTv®{~wmaH?GJB?ERY[^hmghs|ƒ‚ƒ{vomqnk_WUSPMIMU]_bec`feQNMEAFGLMOQSWRGELJEAJRScpr|Ѻytong`^ba\XOEFEHEFThkgfgdcdaVTY_\UMQZ[pxqn|»µ¥¨§¤£lchok_LD?96:HIGADFJg¯Ÿ£|zvmnfL>FHB@AQY[`imjiu{ƒ‚„zqmtrmleZYUTMLNU]_cf`h~~hRSKI@DFLMQSWQDJIBACJPSasr~Ͷ|rponi`^c]YWLFEIJICE]lijifacd`WTY^YOMU[i~xsqǴ½»£¦Ÿ”j]fjdQE>=75CJCDGFGVœŸ…|tlnjO=BIE>CPZ[^ipjit}„ƒ‚„~|trsonh[XWTOMU^_gefe~kUOH@EFNLMPRUWPAEKFCABMPgqvdz|yrpopi_acYVQLFEHJIEG`lij`bcd^WVWZTKT[by{vxũż¹¨¦¡¢‘zb_ceWG?<75>HIFDGKHJržœŸyvikUBGE?@K[^htniv}~‚„yqrqriaZYVTMOU\_`eg{‹nUVNHDHKLPRTUOBCIGCADONThpyijysoqogac`VSOMFGHJGBKenjg_ad]XUWZLQ]ar}{w}Ÿȿ·¸Ÿ©“r^_e[I>:959FHFHLJG^«Ü› vthfm[BHD?IZ[_iwpkt}„~wtsrtlc][XUPV\]\ehdi{}nXWOHCDGLNPTVM>FJEAHMLWhrwؿxvsqrpcad^TRMJFJGDQhmkid`djeZVUW[WLY_j~zxìžúº¢¨ •p`a]L@;:7:AFGHJMLVwuiek^CBEF@?HV[agvuit}ăÄxvutrqib\XROV\]cjh{{rWVSECDILJPOSVUH@DHEAGMK[mrzһurqskebcZQLKGHIJDFZlkjf_iaYWZRN\bt}{z™—ma`RF=;9=@CEGHISUOvœxsjed\G?F@>EVZaguylr~Ã~wyxsvodb\YXQV\]cigh{}{qXREFILJPQUWRG?EIFABHLM\ks|Ϸ{trsqrhc`WOJHGHKJCI^lkhf^aif_[UXWYOQ\hy¿½§Ýš˜‚n`VKFA9A@CHIPYTe˜{srofc\F?FHB>GSZaguxpq{‡wxwvxtha\YXTU\^]ckhiy{pZWRCDIGJLMQUQI=AFDADJMJ_lrɲwporsmjb`^TOIJFGHKIGOdkjha_ehg\UWTYTMU_o~´»²¥¢Œ„xfWRKH?AF>@EGHL\ZŠ }suplb\HADHA?AR]`is|ns~ąƒ|zwvwod^\WS[\akmyz}…tZUSCFIGLPQUTOD>BFDACJKJ`mu~ƫvqmopmic_\TOJFGFILIJTekida^fje\USVRMWeo~ȼȾç¢Ü¡œŠr[MJGFIA>DHIKX_Vt— uwus_[JADGE>AOZdhq{rs{ˆ„ƒ~}ywvyrj`^]VS[\bhmkz„z}uYUREFHJKLOSUSM?BFEACJGNbnv|romnjfb_WSNHGHJMJNYhjg^`ghcZSUPO]elz†µ¹¸ž¢ŠƒzaMNLKHLC>CFGLUcWf’xuwcWK@DGDBAM\eis|sp}ą†}|zxuztkd^]XVZ\bjmox|wZWSFCLJKORVQIA?BFBCGJIOfmw̻xujhpkhec]YPKIGHLQ^gc][bjiaTQRQROU`gq}ɼ›žœ~gQLNPMK>@FNPa]\›zvybOPDBG@AN\dmp|vs~ˆ…Ä{}wuyxng`a]XZ\^bjopx~|{]VUHALHMONRVPHA?BFCBFJINcmwȺ~zuihmlhec^VPKFGIGMLMSafedY]ejh^SOUROZ`gvðɾ¸ ›Ý‚{~xlSLPRNLD?EGJR^`Ys{u|{ePMEAGHD@M\dmpyszņ„~~zxypib[Y[_]`hqx}}|~~]VTGALKLNPTSLD@?BGBDHJGPeoxŵ|{tjhmlgfb\SLJFGHJLKNWabc_\ahgeVPNPRPVbiozż¶ž—Ž}~wtw}|{y|wYQPRTSNKA?EHO]aYe¬™¡|wy~hPMFCEHEBG_glr|xr{ņ}ywxzrkdb`Z_]`gnv{|~z`TWLCJLMPTH@?@BECDGJGPenz|wqjimkefaZOJGLNLN[^dbZ]fgfcWMQUR[imt}Ŷ³¤œ‚‡}}uosux}|x~|hWPSVTPF>EIMYbY]vx~pUKJDCHFE]houx}u{„Ć…~zxzyumge`]\_aflw~z~}~}dWXLBILMOPTSFB@?DECIGPcpyvurhlkihd`XMJFGIKMNQZ]a`[^gef_TNMQUVdnoy}®³´žœz|swvzwvrkmrty}zv{t_QRVUXTM@FILRb[Xw}wv|r^KHFCFIEFYjpuvx‡†}{yzvnfa^]`_dox}|}~|}jXWPCGKNQOTE>@?DCADIPbs|ĺyvoiklghe^TJKGIKOLT[]`[Zefeb[ROLRW\ip}Ⱦ¶zv{uslnstojnqyt~ygVTUVXYSEILT][VmÜ}xmzwdPICFIGFVjotxy‡Æ€|w}uped]^_`cky~{~zmZ[XFGMNQOURE?@?DCACIPbs{zvwmiklhd\NJIEGHKNOU[^_Y^egb`ZPKPUTbmqv}{¶º£Ÿyurkmpnomikoru|y|q`TVW[UIDIMSZ\W`ŠxltxhUGHBFKEJTlpuw|y~„҆}{~xnifc`\^_^blw}{~{o\][DEMNQOURC?@ADAEHIFPax}vurmimjiecVMIJEGFKQRUY^_Y\hc`\VMKQSZjr|{ɻ£‹{wytsnmonkjlpopx‡xs}wj[RUWZKDFNTY[W[||kmun\HIEJIHUmsxx|ć~{|zsgfc_a^bkx}~{y~r_[]KENOPQRSD?@ADBAEJKHOezǻtsrlgnkgcaWLJHEHFDLTRW^][bgc^ZVNMTS]ps}|{䢜{zyxqnpqljlinopn~wv{xfWRV\MDEIRVZXsžylitp_HJHFKIOVlxyzx{ň‡~|uiegb^_a`agw|~}|{~s^_aJDNQPQUPD?>ADBCDLJHQi|żzsprkhligb[SLIEFEDMTVTY^[\e`\SLNSV`tqt~{xѷ¤z{x}~vpqupkjmormkq}‚|ty}{oZPSY^PEGFPVYWkž|lfsqaKIEJHPWlwxy{wňdžƒujegc`_`_is{~}{|tcabODMQPQSQD?>ADBCDKLFVm}~·wqmfjkie^XPGHFGBHQVUTY_[_fd^YXNOPRWbvtx}{wIJÿ¤¢…{z~ytrtuoknlpupjkyyty|{t`NQ[aPDGKSYXUf䧞{mdnqeLJHMLNYkz{yyƈ‡~yldfa_]^`itz}y|{}ugaeSAOPQSQD?>CBGNJTo~tondgifb^VMHGFECFSYWRX]ZbedY\UOMUXbv|~zx߿ſäzu{srqvsolmqvsjuyty|tgTQZdSFGKRZXUc~§Ÿ˜ynclqhOKIJLJPZhx{w~Ĉ{nche`_^a`htw{y}{{uhbeVCNROQSQD=@BDADFMLJYr}¿~|ompifa]UNIGFEBIWYVSX]^deaXVRNOPRVivwx~־ä£|tx{spspqrtuohqyvyz}xu`SYcVDHJNRZXV_o¨|q_fphPLJOMR]fy{yÈÈ~rfgb_\_cqwz|}z{sjcdXAPORQTNC>@CBCHOLIYs}~{rmnlede`[TMHEFGCELY\VSX\^f^VUOTYmx{xֽ¥‘Œyr{|yvnorutptruxqjn}|vyz|zwk[YcYJGKQW\T\fŸrbcqgRMOIPOT^ey{xz~‰Ĉ‡tgfhe^\`\cqv{~|{x{uice^DPRQTOB<>CBAEGOKMZu{ǽ~{vpkigcac_^TLDFEFR[\RSZ[be]SOPQXmy~z½£¢|pt|{ytrvqnrtrsuvslmu}y|{xu^Yf_NLIPUY[XVar xc]sgPMNLQPU_gu}{|‚|‰Ĉ†vihgd_[]^`nsy{|u|ugcfbBPQSTMB>@C@AEINIL_rx~ȸ³y~|xumdfgbca_^UHEFECLT_ZQS[^debYOMPOS[rw~~}ãŒzonuvsqoqrompqstx|zvsot~}~{|wd[`bYSJOTZ]WV[h¢ye]ujOMPMRSVdit|{}‚|ˆ‰ĈɅ{mfif^\]^lty~{xtgcedFPQRTKA<@C@CEIQIM`swķu}{vqjbda`\VIEFCFOX`ZQT[`fd`VQMNMQT]vwƒ~£Ÿ{nlmopnopsojnuw|yvtr{~z{}wfYacd[OSZ\YW[f~z¨wj\tmNLOQVTehsz{}~|‰ĈƉ„}qghg`Z[\]kr{}{vuicehJPQRTL?=@CBCEININbov}t{wtpdcbc_`^`[QHEFIBGS\_XPT^ce]VONOSau{ľƒ{nhnhlnpqighliuw|}{wtx{}|{|{k`]ceaQWTZ\[V\e{w¡{l_rsSPWVdjq{}{}|Ĉʼn~sihg`[X[\hs{~{vthcbjOQSQSQK?@CBCEKOHSens}µuyutpa_b`]a_[NFGHFDHR[]XNSafcZUPNLNQVdu~¾Ÿ—ˆyngibeilidhfqyz}~yuy}~y{~la`aefVYUV]ZV]hwuo¡zmcsXPOQZUeloy}{}‡ˆƒvhieaYWZ]gs||vvkbdkRQSRG@>@CBCKMHVdnt}Ļqwsrj_]_^\`^a]XMGHBGU^`TPVbeg`\UNMNPWcxý˜ žywsic`cehgcbcfkv|y|~|v|~}{|pdfY[XV\ZY^nzpj¦upfpz^PRSZXfkny}~{~xhfh^ZVWZdr|{zyncjVSQOSRH>?@CBACMKFWflr}ʿ|ntqg_^`^][]\ZWLIHIHBIX_^RQYaeg`ZTNOMNRUfƴws{vf_^b^bgcbeghsy{~}xuw}|{}thbefg^Y[UT\X`uxp_yà§vrimyhUQTU[Yhmnx}€~|ˆÇ‹wjfh_ZWV\aq|}yxngdiXSQOSRH>?@CBAEMLFYekp}ʼ{ornld]\^]\][\VLHDHYa\R[bega[RONMLPVoǽžspwxi_Z_^`acgfefjinwz~}wxvw{|}tkhejg^Z^UVZdtwk^s«xvikxoXOUZ[Zfnow~~zlj‰~wigf_ZU[ao~~{yojcjVQOPTPFA>@CBADMJFXfis|Ķ qlqkh]Y^_^Z[]YSMJIHFCJZ`ZQW^ae_YSLNMLKNTwžšroxundb`a`dhkgflkiluy}xvury~{|vpjghi_[`^VZdtve[p wvnjwt[PVY]Yiqny~~z‡Ç‰‰~wjg_ZVRV_m~{rlfiVQRPROG>?@CBAFNJH[fjpֿlhlhg]W]^\[Y\[XTJIKJFCH]bZUXacf`YUNMLKPV{Ӿӹytouohfhbdfijlnjlqvyz|xvtx|~}xvrlkhaZ_`XWZ`uwdYp«š~xpnrz`PX[]\lsqx~~|Çˁ~xfhc_ZUSX\k}{xsnigURNOSNF?@BDAFOHIWehs¼ҸghgfbW[\[Y\ZYWRLKHFBL^a[U]`_d^YSNOLJMQXǼֹ Ÿxvrtpkijidhghjlkmrnpuyzwusqt~€}z|zxljh`[]a[WXaqwgTn~wtop{aR\`c[msq{}|‡‡‹ŠÁ|~vghc_[WQU[e}|xrsiTPNMRLF?@BDAFMGHTdgpž͵~ebfb]TV^][Z[XWURNKHEFL]a\X\`c_ZQOMKILQ]•ɽཫ|}|wldjljhkjoknkpqoporwxusqow}z{}|tjh\Z\a^VY`pwgSk™~wzqpxhTZae_kwt|€}ŠÇ‹Á}ughe][WPUWc|„zŽxrtliWQLNPMF?@BD@HMGHUberždz{bcdaZRW^[Z[XVSNJKFEO]a\Y^`]`]YQMKILPc¾š}{}qcflokhjkmpnopnprmsyvtonw~|z~uli\Y_ZW]rwjUiyzvoxiT[bc]kvu{€}‡}ythfc^[XORW_{‚{yqsniVQLNPKE?@BCBGMGDUcetŻx]a`]WNT[\ZX[YVQLMIGEGTZ_]Z]_^ca^VLNOJMVn“Ƽ۸ĕ‰|{|jejnolnlqorqrqrnoxwtsqnx~~{|}zqm]Y_Y\kvoUc›¡{ztpwjX_bhbnwv}†‡ˆ‡†‰Š~zqf]\VPQUZy‚y|qsmjYPMNQLEA>@BCBGOIFUcfrǼ庬uZ_b]SNU\Z[YZWVQMKIGEKU]_Y`[]_`]UKLOKIQ[}Îͼžõ¯ۮ‡|yrcjmrmnlqtmstrqrolrvrtov€}~{vn^XY^Y]ftsWf{¡|}xwvkZb`ldmvx|Â~†‡‰†ˆ|ynged^\VPRTVxƒz~qsmg\OKMNKEA>@BCBILHFUcerź㴨‰oX^]RMTZYXZXVSUPKIEJV\_`[_\[`_\TKONHMOfǻªؤ†ƒzy{}‡veknprmstrvrqpqmowurolt|~€yqbY]\]ZYZgst^cxž}zxyk]`eldnvx|„~ćƈ~yogcd^\WLQSWu|{orni^MLNLICA>@BCDHNJGU`hr¹ޯeY_]XPLU[ZVWZWUTUPMKIGFJV\_`[_Z_][QLMLKMSlŻéµҩ{|Â~vu„tjkprsturstrstqpontsqmlp|}zxgZ\[Z\Y_quaew™™}{ym`bgphoxv|~†ćˆ~yngdc\WMQRVr}yplhbLKLMJDA>@BCHMKHVbgq÷֭_Y^\XNISYWUYXTSTPMKIFHIWZ_`]_[Z_^ZRLNKHNSpÅԽݧ´Ϩ~š}z~{qoporptqrtruqonplmstsnklw~~}jX\X\Z^mufgv›™}|{yredgploux|‚~†Çň€}zpgbd[\WKRUr{|plhfMIMKHDA>@BCDINLJVbirzͨv\U\YXMJUZUVTXWSRSOKIHGIU]^`]Y[`]WQLNKJOTtվûâϞ~|zvzy||~rmonqtstruvsmnmlrtsnkx~~|}l[]\ZY\[Xfvgjs×{{xhfirnrwx|‚~†Æąˆ~}{piaZ[TMPQVo|~z|qjhfJKLIDA>@CBHOKUdkoyƧoT\WUKIVUVSWTPSOLIHIKSYa`\`Y[^\UNMNILQVoվ¡²ӿyrluyxv|~~Šokpmoqtstrsvrmpvqnkw}||p]\XW\]W`vnmr|lglpqsxz…~†„†~~uh`^[ZSIQPUl|}x|qnlieKIKIGDA?>ACGKPNKVbiqģhPUZUFGSXTRTWUQRNLJGHMSZ_^_Y[][TOKLIKQVj{yzѽȿƽɹ¨yot–}rux{‹~ymlpotsrqrswrpjkmkptsomkv~}{|s^ZW[_X]urnpϙqiltrxw|‚~‡}€|xi]`XRJOTmx}z|snligIHIJGFA?ABHNQOJV`joq迣¤aMSWUSEDTVTSTVSORPMKHGJLSX`^_Y[XUMLMILOSgxyrsλͿźáƸĽǭ|ymmjox‡Ä~Š}polnoprtspsquvnjilqtrmlx~||zx`]ZX_^X\unk{Ζ‚vinsuw~‚~}€yf\]VWSHPMSly}~ztplieHFJHDA?ABJMSQLTajno巟¦aMPWRQBCUVSQTVSORQKGINTV^\^_Y[^XPKJMJQSezvsr˻Ⱥķ¡õźȽ`frcdiz}ƒ}tlnopsporsurkgjikotqomx|}zxe_aYV^X\uvomxΖ”ƒxjortvy}ƒ~†ÅÊ}|h[\UTPIPNSly}|z…uolkeIFJIFDA?ABKPRNLU`ilq䲝y`KNSRM@ESWSQUVTOPOLKJGINRW_^_Y[]SQJKMHINPd{wnvο¶Ķ¡´ź߼|qtc_m~À}tmnonqsqolnoqrtsifgimstsopy}~|}~{wm`_\V_\Z]twqmt{’„ykntux~ƒ~†…Ç{}hY[UTMHOMPly}}|xqkleEGIGDA?ABKPRQJT]hop㮞w]HLSQM>ARWSRSWRPQPLKGIMNPX]\`Z]RNKMJKPazwpy¼Ƿ¡¤ù˹…usveOf{}smnopspojnqosqjegdfltoqsw{~|z~{ywuqb`_U_\[\vzroq~|͐wopswuyx~…ƒ‚‡|}jY[QSOEPKNmy}~~z‚{onodFHFE?BIRTOLQ\emrᬜu_HIMOJCLVSPSUQMPNLIHKOLOZ_^a_[\RJGLKIHIZuxq»ʹ¡ɶѯtnT?Mih_Zh}~|~wv{z{qnmknmihebdecbc_fmqsjp}z{}y}~z{vplcaX]\_cw{potzy‹‹†zqrqvwx‡}ā…y}~ym]ZQKLBNLFgyz{uqvjGEGED?ADHPTOJK]jnsܣhYG=FND>EJWTPSUQLNQLIHEMOLN]^a]^[SJGLIHFZtxpǸǝb_KDSrh[hyz~}~~w~{xyzskjljeba_c_ca`ensrip|zy}{y{utojab[]Z`gzxpmuw{Šzqswxw‡{}…ƒƒÄ…z~}um_ZPHMBNMCgyztrtmGEDCA?ADOTPHL[jmrڣfVD?EKA=CMWRPURLNOKGFHJQMQ^b]`a\^\UHGLKIFHWsvtŶª ŸžµӰĔ_Z>Ieua^Roqtz{}}||z{~{qinke`_a_\^_`ca^goqmdq|z}{y}yupiedcd\[X_hy{pmqz|‹ĉ‰{trwu†z}ă‚~z|~|wl^YLIMCKMBdwv~~|vuwnEDCA?ADENTPFK[lmt֠cXE?ELA>BKURUPLNOKHGMPOP_a]b\]^XJFNMIFGDVsvt©žʨ–dPBFguc]MAefmw|~|{z{v~}sjpkc_^\^\[^_ca^gqkbp~{z}{y}ztnefei_ZW_lzpipz}ŠƉstvwu‚zƒ‚€„ˆ|y{}si_VLGOAHPCbst|€yuxoEDEDA?AECLTPGI[kos՜cTD=DIB:AKURUSPLNMJHFILPNS^a]`d]_]XGKMJHGEUtuw½©¨ĞȿҰbVKCkn`\O?Y`jr}Á{zv|rjqjc`]\]`_Z\_]ac`eotiap~{zy}{y~zsmfecfi_\W^iz|tgpyŠˆŠˆ†tstvywu€…z€‰}xz{tj_UKFMBGNA^p~|~~zvyoDCFDCBA>?AECMTQG\knsԘjUD>DJ@:@LURUTPLPOJHJMQOT`c]be^WHGMNMEGESsuxſǻ©¥žçþyRLADFJVSGHZlntѓlU@>FGC8=LUTQUTPLPOJHGKNPQSab]bdaYGKOQJHETovyļŸÞ̕sǐRP?ADEKTSGWkmu΋lU@>GFA9=LUSUTPLNHGKPUab]`db_cXHEKNSKIDRpuyŸ¨žκueP;L]aT=IUcnw~{}zrty}titkf\WZ`c`YZ\]`cacjsmam|}{}{z|xvrj`gmke_X\mxzha’‰Å„vtwzus}~|}Á€ˆzy{pd^PGIN@KDXikz{~{xvfEDCBA>?ADFITUGXins΋oVB>EFE8=NWSQUTPLONHGKORPUac[`dabZGDLNTPIFSmozø§ž¡Ӽ{}NAV`V9AJVZkwy|~|}ymoyojtka]Y]^a`WY[abcjsmbl}{}{z{wuskagmifbW\mx{ydb“ˆŠ…ƒ~vuwzvt|~}|ÂÁ€Ãˆ{y{pe`NEIN>?KFWhkwz{yseEFBCBA@>ADFIURGWflüqWBADFHSTHGSgluˁyuWDNSURQLOLJIJSRQVa\`ec_bYJDIOXNMSik{Ǿļå¥~iqNMuk`A7FIOV_pxw{~}zqlopjmqgaZW[]`_VX[^aeglqoaj|y{}{z{wutmdgikheX\kr{bc~ytvsxzxuo|}|~z~‚€ƒ‡~y{ricPFJM>KFVht~|}zxs\EFBCD@?ADFHSVIGTflxuwWB;DHDKFTfjt|z}{wpYECD@?ADFHQVKRdlzȀvzW@:BHE<@JTSRPNOLGJRTQXa]aca`WMEQXNLOUegqƽݤ¨ž«͔fXm`AImeU:6CKG8Bcvyu{wmigdejg\^`_[WUW\_bfgloek|x|}zyxtrolghg][fp|{ce}ǃ~{wsqsuwxqpv|{|zy}‚ƒÁ€‚{zyzxwldRJQG;BKDVghqy|{yxn[EGEBCB@?ADFIPTJTelz¥ʂt}VA;AHE?JSRSVPNJMKPTSW_c^cebaZRFSWPLPU[_mžĹ«¦¯zWTUKJ^n]O9;FLA46Zu{~vs|}ngje\`olfd_\YWUTZ]_`afimlkqz|xy|}zxvsutihfgj^Ybu}xnbpŽ{vsosqvrnuzyxw}‚À|xzyogVJQG:BMDWeiruzzup^GEDCB@?ACEGQTJLQ_k~āsS=:@HG=IQTSQPMNMLKPSUX`b`becbaYRDRXPLNTY[i©ª¡塄iWTGEZkaRC:J?7:]{}oy~znijf]`nohda[UTUS[]Zabgimljr|zx{{zxuvqmjihf^Yf{ypat‹xuvsoqoqsuouzxwuw~Ā|{xzsjWKSGIHCTbirs|yvrhFED?@DCGNULIQXcx§±ÿnV<:?IG?=FOSTUTOQONMNOU]cf`bedcbZKEIRUQMOPY^j{±¥˚{li`WM?D`dXMB?HI9Ms|}{|xzqigdafqkhf_VRTVWZ\^`fmot|zx}~|{yvxwsjfgfdb^Zm}ueywtrqolomrtjnwyuswzŀÃ~{wx{vkWOSH@FIETdjtr~yvtjFEGEDCA?@DELULIPV`t¿jY=:@I@?FOSVTSQPQONMOQTUZceb`eded[MDIRWRLOU_jyƿø̗xmvrVP@=U\UMG:AFGaz|}{s|zriebaknjifaURUXWX\_[]flov{zx}~|{yxwxsighgc`Zovh‹‚~xvuprnkmnpsimxyusv}~‚~Ā„}zxwxyuiVOUGAFHGScmur}wvumHEDCA=@BDELULJNV_lƾl\B9>IHA>FOPVUPOPONMLOQTV^de`_cdfc\PFGRXUOS\kxƿªƏ|pyu[QB7L]XIC6ESYm{|{zn~|mhgcbnoihd\RSUWVY\^Z]adiou{zx|}~{ywxyrhdgea`Zl~~xj~‚~~wusqkloqphlwzusx~„~Â{zxwxzthTQUGAFHDUdntr|vwlIDEFDCA?>CDFKTMHNS\l±Ǿk|~_D:>ILB=EQRWVUSRONOTZ\fca_dfgd]PEHPZWRNPYlxƿ²©ծ|`NA5E]ZKBFU]fs{}rp|ynihdemhgdXRQUZWY_[XZ_`eny~{~}~{z{z|vecehb]d\j}wkx‰€~wrpnjknogitxusw~€ƒzyxwyqhUQUHDFJFTfpttwmHGCDEA>?=AEDJRMILSVf·ir{`D<>GKC@HPQYWTRQONOTY`ed_^bfgd]SHFMXYSNPQViuĽ¼±Ծ_G<49R[PKLZeks{}|nau~zqiegpogf^WPSVXTY][X[`_cmx}}|{zy{|xicefb^dZg|~{tls~|trnljihlonfisyuqz€~~zxwvwywpeSRHDFHVeotquvwjJGDEFEA@?=@CDJRMIMRW^|ĸknxcG;DFPNIMQS]z°ocrweK=?AEQLIKPR^}Īr\o{zhM>@AMLHMLP[wӽ{[]rzmN>;ENMIMPUXY[VWYXQNQPV[be_`ije_SLIKPTSOINXhǼ°оzmvha\WKFNXbkpqow}~…vsutnom^X[_`^[]_^ZWac`\bx}~}{z{m^ikec^Y\lkgir†€ulegehge_huwpqs~}|{vwvuyvmZTPJKLO[jq~otwoZNLGHFAC=<@HJILIMVj͸[K[vkM<>ELJOPSV[ZXUWZTOPOTZ_eg`^ihc_SPHNQRSPKR[dǼƹ´µվq}vhgeailtusv}„vutmqp\Z^_\_]_^[XZd`[f||}xzwg^mihc]Z^ljfhu}Æ{thcebgefid`gtupsƒ~}|{}{xwxvwxyxo[VOLKJPLO\ht}ptoYOKIFGHED?<>?FGHKHKSfȳ|\NUrnM=<>?>DHFKIHMcų|ZLNnkM=?>EHGINa~±]JLgmN>@>CGEJIGOb{ɻ^KGekP=AIONQNQT[]YVUWZQPNTWY\_cd`fgc`UOSLNOSPO`ejw|ƒð}|{srsvw~€|xwupjdb`]Y[Y`fe\m„{yxsjhlmnbVXZ^g]^pœ“|tneb`^ajcdeb`dnvuo}ā|}|}yz|{|yxvyxywxzxyp]YRLKPOMR^my‚{lpodWQPKIHGFEC@<=>CGEJKFJa}ȽaLHYkSA:@JPMROPZ_ZSVZXUNMPZY[Zbd`cfebTSKOLSRbhjv|}ƽ|trvyz}‡†}ywvroihc\[Y[Z[eiau„zvuskjimlaWZ]c`Xeqœ~rlba_^bmecbafoyr€‚}~|{zx{zyxzxvxyzyn_[SMLOLS]mxŠzmpodYPOLJGFEB<=>?CGFHKEHazžcQHViS@AFEGMHAVvµiUJM^XD>BJMOUOT^eZSU[^YRKU\[Ybdfcd\OTQNKGKOW^htvyȻ~{wsowt}†xvsojcZ[]dgmknin~ăyxwtmfkgXWbd^XR^nzu{mf^\^eoqdabaeqyvqw~~{|~|{zyxy{yxwx|{|zyz{zxia[UPOQSV^jy~rimlhVRSPOKGFA=<>=>EGNKBQrwkXNI\VG?BJMLKUXOT^f_VUZ_[TOJOY^[Zbfebc^PRPJHKMU]gstw›ʾ~wmnr{‰‡}y{rmb[\adkqonsyzywmfgbV^b\VU^n~{zx‚xodZafqbcetzwp{~~}~|{z{xzyzxy|}{zx|zyj`]SRQUY^fx}mjmjiSRNKIGFA;:<;@BDENJALk~¦ijxiYMKYUI@BIJKLUYOV]g`U[^\SNKLW^[XafifacaWPMKHIQ[esquƒzrnmu}‡‡wkcb^bgsvrqpuƒ‚…ƒyxyzxlf\V`baZU`n~}vw~vlbY\bltm`_bguzt|}~~}~{zwyxzxwz{|~}{|uhb\WRSURVYafv}zkikmhQTRQPLIGFC;:9;<:9<>FTQKZkt¨Ĺ~upm_WOFJIFCDOPZ\W_hlfZRW_WPXbf]fjlj\]WSPMLJDJQTY`hmtƳƆ‡†€~}{y|y{~yg]UV[^`a`lrtemtv{xztqc\_ev~l\[^_bcntpr{‚~}y{xuwyxw|}~xplic\[ZX_fjhlx€~pmh^QETSPROMGHGF@<:;<=?ERTLWlu¨º{nrmaVPHFJGFEFPQPV\Y^joj^UQU]`[RMV]ebZghln^\XTONLFEOTS[grw³Ç†‡šÑ~}~{x{z{y{saYWY^_b`rtu~enrxtvrk^\ak~|cW^agorqt{~„~{zwxyw~~|yqlhe^Z[agmin{}nmg^QDTSRQKHGFB;:;ABSTMYjs{~mnkcVPHFIFECFNQPV^X]hnk`USV[b\SPQ[fb\dfjod\WTQMFCMRTguzۉ҆‘—ƒ~|{zyxywj]ZWZ_`cbdqtz~yfkpvqusodY_`sv[X]`_efopotz€ƒ~{y|ywyvw}~~wpkhe]\clkjoz~zqlnd]KFTSRQMJGEA;:;<=ANZNWjqyľ~jmbWPGFEFNQPWaY]hpkbXTZ_VQRXdh]`eknj`ZURNPH@HPRPcu|ĵĈ‡†–šŒ~}†{yxwyqc^WV[_eaeqr}odknrqspnh\Y^fvpVY_adgspns|€Ã~{}{vyxyw}~xmhie\`^\hlmisy{wondWHETSRQPMGIGB<9:;:>BOXPYhpwǿ}klmc[QKFGFEKQPW`]Zgonf\STZ_^VTRUcg`_dhmkc\UQRMOIABOPQ`t}ƹ‡ˆ…ØžšŒ}~wxvxwnb\V\bcecorukfjlnoqph`YZ_hy}hUY_`ejrqlu}~~|{}zxvy~|yligc]_]_flkr{|xonmbUFDVURQRPKIHFE?9:;:>@O]UTgquǻ~khleZPJFGEBELORW_b\copi_UZa_XSTVagd^bhomh_XSQMOND?KRN^t~Źć†ßš}~|~xstuxrgaZRV^fdbensyÂ{uefikpmjf]Y\_l}w`SZ_`djpqky„~|{zzxvxÂ~€}xihd\a`biknlp|~}|vol^TCEUTSRQLJHD@:;:>@L^WdorƼkcigYQNEIEBEJPRU`b_cmsjcYTX_aXRSV^ge`bhlnmaYQSONOG@DQM\m{û¿‡‰†Ğ£~yusqsulc`UOXahedgs{{zlfgjmlmhb[XYbp}u[S\^`edhqom|‚€}|~zwzxy~}ufig`^b_ajmnlp}{z|upnk[NBFUTUTPSKLIGFA9:;GQOSZt­†şž¥£•}unpoc]\TJRZgdb^enyxv{{|ogejkhd`WY]ju`QT]_beglodp‚†~|z}{zyƒ€€}kdc^_c_dhlklpw|xsol^OGCIVSTSROKIGFA=:;>K_l]\hl¿ƽqd`idXVNLGBHKJLPS]fidhlrqm_W^c`VW\`bilpocWQRUOMKCGOPQSf”¹Ĝ£¤Ízrkjni]ZMKQ\ea_dm|v{{|~qgdjhie\W[bhvpZOT]`celmcr‡ˆ{|{zx{ƒ€‚{gafa`c_dikljnuzwutpkUJHDLXUSVTQLKFGD=<;=@I]nc^gj~½¾nf_fe[VRPLDJKORYdifjnspdYadec[W^_`gkmosniWPSWQLMFGQRON^ºã|umhjicZ[RJLQZde^_drx}{}neijgfeicY^dltjWMW]agegmfcq~}|{zƒseca^`bc_ehgjlnw{tvtqeQHFHJXTUVUPKJHFGD@=;=?K]og[hix¿ph`_dZUWQNEINMORZcgfikrh]^egaX[b^_cknpsukZPVWUPNGEQRPMWwؤ£••‘tkcjfd`Z]QINRWdb\_bt|yzhfhifegfaXZ_cmneVNXa`gcgmbq‰€|~|{€pab`^ada_cfhjlnwzstrdLHIKWVUTSNKHFGD?:;?K[ni\hjt¹oh^e\XURPIGQPNSWcfgehmlsob\gfgd\]a^bkrsrtr`STXYTLEKTPMOfŸŽėœ£Ø~vkbdcdc]VJQV^_[Y_vyzwfledfe\X]`elkcQN[adbdgjau‰}~}|z~ā‚zjca^`bfa_cfhinmxutups]FHIHPWVUWVWTOKHEFD@=:=AM[n]glsqg_]a^XUSRLFRPOPU_gcegjksqc]fhf\b^ajprwvjZVYVNMFLUPOMYyǽ“ץ㘐xtebcd_`ZNFJSQY\[Ue{xz{}|sdfmdcb^\Z^afih^PN\becjfbes}|yā‚yhca^_dca_afhmlqxtsWHJKGOWVUVWSPJIGEH@>;<@L]jobfn¶vg_\`\VUSQNISQNORbdcdfikothbcgihaYba]`gntxuvrdVWZTRLGHPROISm¦³—™¢ã˜šxtna_cda^PHMQW[TRYoy{|xtmckgcd`^Z_cbhdXMR]cfadhf`dvŠ‚~~}~āvgda^acea_ahglmrxstroRGLIKPWXTVXTKIFGFD=>=BN]jpdgro·l^[_]VTPQJRUTMP]ecdeijntpcijkcYbed]douxuxwo\[ZYRMGEORQKMc{“¾Œ–ŸŢšš|wuh^cefd^ZJCINTSZXNRf}zurhdmebec][\acf`QLU`cb`bhbf|Šƒ~||shda^cea_cginqtuprtukNJKLPWXTXWXSNJHGHE>?N[hrgdqs~½m_W\]WUSQKNWXRMQZdbcbfgltecgilf\`h`dnuyxzwjZ\[RNHDMSRNIVhxſ‰Ô՝¢˜Úyusd^ekhc^RFEHOWXYVI[w~}{zxsocgl_cd`_\Y[abcXLNUad_aefc_h„~€}~rfda^bea_bijmpuprthLJKQWXTWZXWRPIHGEJCA?>BL^golcrv}ûraW\^YXWUPNSWMN[d`bdcgisvjbfimh`Yihcbkty|wzt]aUOKDHRTMJMZgrĿºŽ”•—™yutnbaili^XLCBJRVXYPJg~’}zxwvrkdifaed_[Y_a_d`QMSYbacn}~|}pida^deba_dhlmrusprsrbILMKQVXVWZXSNKGEIG@>@BJ^eopdq{}cX[aWZUROSWPJXh`_adegpvlcfilk^[ekgchrv|v{|xe^a\TNEOTPLM[eq¿”•šĘ|xvqg`flhYPIABMQVYWKOt|xvtnhfidaed`Z\Y_a`c^NUZ_ba`dcbeq…}|qhd^]feba`gjklqurqsrp]KLJMOVXUYWZVWSLIHGIHCAK_fmufn|}¡œj[\c]YZ[WVNQWXUMRid^_^bfntpgejlc[^mehmx{|y}yn`dbZQIEJQTMLP_gu¶ýüŽ‰š—~xwvidhjlj_PHE@EOSWTEVx|‚~xtsrjghj`bfa\[ZY`\^_XMSX^abajwƒÃ~ƒ~|}zoic\aec_hiknsurqmWJKNMPVWXY[YXVJHIGHDC?CIYekumor]Zed\]YXQUZWLRei_\`bltsidhkf[\jokgksz}{|qfed]ULHINTNZblzǿ»•–™œ—~xshgiaVHC@KRSRJG\x}vsqpijg_bd^\[YX[\^VQU[_`dbc_dr}ˆ€€{y{}qib\cdba_cgknqtqpsiULMTXWVYZ]VWMIHGIDCHYdjvqmwcZdg_^]XTRWYZO^lc\Y^`ftlhki\Ydrojkqx|~{yqiegZNKJKSRMNV^fr¶»¤Žœž›–zxwyxqcfhfdXPE>=AOQRQMFLf}zvponjkhd`be_Z\W[Z\QPW[^`dcda^ju„€ƒÁ~|y|{pf^]cba`_fjimrsoqopgRMLNUVWXYZ\ZUPJIHFJHCDCEWdhvtok^bif^d`ZSRTYSL\li^Z_dotofikbZ^mqmknu{~|zsoekcSPLKORPIMPY`e|¶«³Ȼ~}~|Ž’•™œšœ}|v{}|kecea^VHB<>LPJHASr„wmkorskifabd\YVXZX[SQS[\_bfgdZkx‡zyzwla[`b`^ahkjimrqlmjbTNMKJLHTUVX[Y]\VQMJIJKGDFIM\gr{r~›fboqmhqcZSVX^UNLakj]Y]gnrohfjkjeY_knmnqx|{xrdfmj_XVNKLBCHLKNYmš©«|xunomouxy{~’“‚}‡†{kc`[PKHC;>ANIC@f}nijrsqlhf_de^\_UWYWQV\]^eg_^rv„‹Âƒ‚zyx{wj^Z^a^_`egkjmspjijibTNMKJMDSVXZ[\^]WSMKJLHGHMVcp{tx»šsflvrmtk_VUX]XMIXgj`XZ[ckoqihfkiZ[elnmnvz‚yvhcjmc_XRJKHB>DJKJMVb|¨ƽ|ywsmomjpqtsvz}~~~}~}Œ‰}f_a^[NJHFB:=DMGDE>Kw|~wjiqrsnlebda]^_VUTQRZ]\_fhg`etz~Èс|wuwxuh^[`_`[`dihnpmkjkibTNLHKEQTYZ[\_\ZURIKMIHNR`p{vw•¼~lmspxsh\VX\[PIPakcZX[_gomifjil_Xbilmqz~}vg_dmcb]UOKHF;>EKOIHQ`z¢xtsrqpomrtprwy~|{~ˆ}{z|{|{gPXUPKHFA;=;JAD@Yy|yndnvwsmgeadc^_b[UWUVTQT[Z^cfealy~‰Ńzuwuvzqf]Y^`\`fhlghnoljijcROKGILERSUW[]`]ZVTNJOIJNR\k|ywsrwvsxzlaSX\]TIJXheYX^dmnjfhkjdX^hikoqu~yl_ajhcaURLG@7AKONGDNaqprponsx{zy|{}{~~|~xyz~}zhPHJMNLF@=>@JD@EHIe{z}sjgpwvolgbcea\a`XVUVRSRYZ_dfgc_p{}ăwutvnb\_^_Z`ejihilnjghk`QNHKJDQRTW[]`]XVPKLMOIHILQXhx{u•£|sx{wzueYWZ^[OGP`g[W[_gmnjfhijhYZbijlpty„~ma\dkf_UOJHD<9FLQMFDKj‘‘ztrxxpsutuxy{€~|~~ƒ~z}{xv{~}~|voeTKHFJPQIB@><>FHD`ˆy{}xqsrhYVTZajqvzuoigb_gsvyz~Ž{ytfciaZQMFGJSTH>@C@:L`pƒ‚zniflyqb`bcgf`b_WSRQRTWVUX`djq}ŽˆČ‚{smomf`Y[YX^ehgfdgifceaTOJFGFENMPSW]`bc_\]URORSNQPQX_jz}zÈthXTXNAFYSRPW]jnigfeceg^Wajknpswyyk][`^WRMGBD>9>DBEFC>Li~~unid]QOQS[bdkplifa_\fqvwstx{|yuxyxqwk]X\YRKIFEDKMSTH;:>BC=B\ly€ujgitzh\ac`bgea`a\XVQVWSTZ`bejkvŽzrnlmlc]WXZVW\ehfegifcefc\UPGHEHFEMNPSV[`ad`\SPTUPROQX`iy~y¨‰vj^SWVSGCR[UOPQYemligehbW[glmorwv|udZ^`ZMHCA@A:@BE@LZz~~|uldYONKOUY]afgfd`^\ZV]dobckrtqstvw{x‡|uh^X^_^ZXWRIADAEHJRSQC<8<=CBANgtz‹}thlswsca_abfha_bdXYSRTWVRT[^ahon{ƒŽÍƒ‚~woljkh`YVYXYSW^ghgdchiedfe`\VODGFELMORTZ`adca_]WRVSPRVahz~y§®{maTRTUTJ@JYRQU_knjgecgf\Xdkjpqsx}~si`]^\RCB@=?9:=?CDHRdzzy~}{|yrgWPJLPSTWZ^c_][WOLTXYXRX^fknlqtv{|~zlf\TOQZ[ZWXQHFABCDINSPI?:;AB?G[jrzÅvmjtxzma_`acfbab`ZVUSRSWRQUY^emqt…ŽÍƒÀ}xoghe^WUXVTX\defbdhbceb`YSLEFELMSUX`aceb`_]WSTUVSTU[gx~|y婐qeXRSTKAERYUPRQXhnlhdeghbZ\dkoqtyztkf_a`[JB?A9=;9;9?EBCJSds{rnwy{~vqi]RKMKLOSVX[Z[ZWVQKJLNOKPS^efehjmpwy}n^XQKOTSQOTQMF@B@AFJOLF?;7;@CEL]lt~‹|{pit{xtha^befdba`]ZXUSQTWTQSUY_dmtq{ƒÎ~|xlghf`ZVUSX_dfdcdhgab`_ZRIDEGFELMOQTY^ceb_`b]USWVSTSU]fw~|y¤ª†uhXRTRMCMZYVRUcpmkegb\Z`fkquyxojgfdaWF=?><:=;9@DJP_p||wrny}rmh`_`dfc`ac]ZVTSTVSRQUW^hqvw|Ž‚~zslfc^ZWVTWSTV^fdcdgf`ca`\XSJCBDEGCJMOQRX_cfe`_WTUYVSUZdt~|yz£Š|l^OTPLEBGW^[XSV[hpkfdehf`[Zbiltv{~|tslfge\OD?><;<:>CEKS]gYLZekrngc`[WXWUQPNPOPMLKLJHFGIJINUYZ[\]Y\TRQPOPNMNMJGABEKNKD;679:>DHQ\j{{voq|smh_`\aed`ca[ZYWSTVSRQUWalvwxăŽ~}wqifb]\YUTRW^efbcfgea][YQHCDEIDLMOQTX_bded`caYVX\XVTWYbrzy¢«r_PNMRNGCES\^ZSV]dloldechie]Z^cmrtx}{xqkfhbTFA=>:=;:989<=:9:8:@JOQOQXWXZRZ`bed_][XZXPMJHFDCHNMHFIMRQUW[YUQPNJFEDCBA@ADGE=97:9<>Kaxz|Š}xqwsj_`_cdeafa^[WTSTSQNSWapv{|}…‹ŏŽ„{wtmga_Z[WUSQSQRWcgbcbfe_`[YWPGBCIGAJLOSV\cegidaba_ZX\VW[l{}ysz¢°…jYMJLPFCFJV^_XW\bhmnmghdfhe^]_fnruƒzqkhc\QJ@<><;:976?JLILJIDCOSY]`a`^_`UQPLKGEC@?@DHGCIKJORX^bc]YTRPJIGDCBABCAB?;9<;:9878>EHDBA@A<;=CGLSZa`ac`^WVTOLJGD@ABEGHLMVadfe`\XTPJGKHGFCDBD@:9=>=<=BNeouxvyxvk_a`cdfefbga^]\]ZUQRQPT]fqy}}~|xvpje`\ZTSPSRPVadecbed`_][ZWOF@DFJB?HIPRSTZbdgkicb`]\]YVXWZ^txun °¯ v`SIGIJEDHKXa^W\ahjnpqlighgb]acmvuz€{ncUNJ@>:<><9:8987;@?<;:9;=?GJQV\_]a`ZYTSOMGB@ABCGIJNS\_aec]USQNGIJHDBGEDB=8=?>;<=:7878;98:9<=BFGMU\XUZ\[XVSROJDA?A@CEFKQTZ^b`]XUMKGHKJ?>@C@=;>B><:;DLPZbemu…y~}yvlbcaeidgeg`^_[XTPQRPMU^ju}{~‘‚zxrojb^[YRQNRON\ebebedec^`\ZYVPDCHIHC?DIMSTST_cglkhfc_^]^\WX[gtsljx €}nXSJFHJEFEL]^\[`ghknprmkhgf`^ahpxz|€Á~ytm_RNMF?;8?<:9868=;9<;AFIRWRNXYZWTQLIFDBCBCEIKOVW\^YTSQJHJMKC;=?78CMWZ\`^`ly€~uogcbciehfhg^]`ZVPOMOWbnvw~‹Ï{ywqlh][\YXSPMQNQab`cedca_^ZXUMCGIGB?EHLQVU^bglqjgd`^][WXY]`nlhju”°~}o`VNGFJIEFIV^\Z]fijmrtunjhfc_`epx~|}{sl]TRNF@;9?A<789=><><=>?BGMQNGHMUSUQKJHFCBAEGJNWYXTNOKGIKMKG=;>=>?>DCB=98?LVX\[YR`i|zpjedchgfkgeghc^b]RONLQW\ntx~Џ|yupke_ZVRONONT`bacda^]ZXVTLCFKIC@ABEKRVU[ahjpnigfda^]YXW\_jkhr—“ŸyncWOIFHIEGIP\_Zdgjmrswskhgea_abm{}|Ázwtgb\UHB>?=>?@BDEGHGINMLGIHFEFC@ABEHKMOKJIGIJHIB@;?>?ADC@:6=EJVYZXQWdlyω}urjdihjhifkha_b[RNMKONQV[krz}}‘…|ztokc\[ZYWSKNPMW`^acdeba`^Z[VWSKAIJIDBACFHOUVX_ekmqkie_b^\YVXZ^bjhfm|{yqe[SMHIGEJNV_^Y`hinptuxrkhigc_biu~|~}urpjd]RGC@>=A@=:<:979>?@><>?DADGFJHGHGFCECBABFIEDEDBFBCFEA;=A?<><=<89<@?A=><=CACBDGFHEGFCABABCED?>?=?>=;>:<:97>A?@<;=<>@CFGHFCBCA@A?<;:98;<=;<8:;=:<=@B;<:;ANOPQTFBOWaptywnmkegkhljlmkjfaXMJIJKMKONQ^nv~ކƒ{wtrmd\Z]YTNMLQ]^_efdc`b_^\YUQNDFKHGA@ACEJUWVWYchnosmkifea_ZVWVX[adhp{~ŽzvsnbYPMKIFGFIPX`gZY`fnqvw{vtolkfakyÀ~xmnke[SNGDB?>?><=<:979:=ACA@=<:9:;=ACEGFA@A@>?>=<;:856:86478;<;=<=<>@A?GNPOC?Nagims~ÏzpogfijlkjnmibYQIFHIJIMNUcq{‹Îąƒ~zvsoma[Z\]ZSMKV\afefab_^YURLDHKJEBA@ACDHRXVUX`gnosnlkgdc^\VUWX\[`fgox{ŒxuqodYSMNLGHMV`jaV\cksvyzyvutmkhcgw~yrinkfb_YOIEFCBA@?@=98:79:8?@<;:98;=@DEBCB@?@=<;746758789:;=<@EFMNQLH=Jhplmo|ϒpqidjkmkjmolkiZTLDEHJIJKMLXhs}͍Å}yuroi_[\^_XRMKNX\[cegfc`_^YTPLCHKID@B@AFGOVW_fmnqpkjgdb][XUXWY]gfksx|—±{spni]SNMLJFGKSahl]Z^dmuyzxwxvqmiebmz~vhgige`YVOHEDADBA?=879;>A@A@=:8989<>?@?A@A?>=;8568789:;=<=AILNQLICA^trpt|ÍuohflomlkjmpnlncTRDFGHIJKLQ^iyÊ豄~xtqoc[Z\]_YPNKOY\[Zdghc`_^ZROICJKHCA@BGOWVX\hloqokjeda\YWVWY[bhiru±yupjh`UQMNPJHGJQ\fog\[bitxzxyxtrjhaft~~oaecf`YUPJFHFDEC>?;:979>B@BA@:9:898;<=><>@?@>@96785657689:<9<:?DMNONJEBLkusx|Œ|zyrkhmqpmjlmsnlm^RGDGIFIJIMYdnŒ…zyuqk`[\_a]XQNJKP[ZY\gige`a_`XSQECLE@B@BCDKUTU\eknmqnmgea`]ZVWUVYaegmrv|‹•{spmf`[ROPQLHGLTZdnpb]\coxsokg`hx~~j`dehd]WTNHJIJLHB>=;8989;@BDAB@?>;:9;<;=;=>=878798:9;89:?>;=<=<:;98;98:9;:9:?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmm7.lmp0000644000175000017500000000211511357170242024320 0ustar keeskeesV`hqz&/8AIQZdmv $-6?HR[ckt| #+3;DSSiUURRXSSQQ`ii\\iiYYQQXXQVVWTQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQWWSSUQQRRWUQQTQQQRRUVWSQQUUUUQQUllUUloolXXntropvtmnvrlltpkkoojXllUQQUUUUWSQQVUSSSSiTTRRXSSQQ`ii\\iiYYQQXXQUUVWUQQWWSQQQRR}SSRRRRUUSSiTTRRXSSQQ`ii\\iiYYQQXXQUUWWVQQWWUQQdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmf3.lmp0000644000175000017500000000234411357170242024311 0ustar keeskeesV`jw #-7AKU_is} ".:FR^jv $.8BJT^hu  %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%#"$$  "%##  ## $#υ΄抈ЇT  ##"##%"  "$%$$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpiecem2.lmp0000644000175000017500000000043111357170242024323 0ustar keeskeesT`lx F"  #  F# #  M  bfb bgb cgb bgc bfc cdb aadfb bdca cfc bgc cfb cdb cfb bdb bdcdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/armslot2.lmp0000644000175000017500000000131211357170242024352 0ustar keeskees|}~:Vs"<Vo䉇χ~~͂~΂"# $$ ρ"$ #$ %$ $  $" # % " " % $%"% "$"%$ #%%$ #%$#%$"" # "%  ""~#$$#"""""""""Ά䉇΂~~~""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/chain2.lmp0000644000175000017500000000627311357170242023766 0ustar keeskees #+5?IS]emu '1;CKS]gq{!)1;EOYcks{#-7AIQYcmw!)3=GQ[cks}   % / 9 A I Q [ e o y    ' / 9 C M W a i q y   ! + 5 ? G O W a k u    % - 5 ? I S ] g p x  $$$ #   $$ $$ #" $$$ #   $$ $$ #" $$$ #   $$ $$ #" $$$ #   $$ $$ #" $$$ #   $$ $$ #"$$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$  $$$ #   $$ $$ #" $$$ #   $$ $$ #" $$$ #   $$ $$ #" $$$ #   $$ $$ #" $$$ #   $$ $$ #"$$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$"# $$ $$  # $  $$ # $$ $$  # $  $$ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/fontb59.lmp0000644000175000017500000000026111357170242024077 0ustar keeskees (7HZl~     deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpiecef3.lmp0000644000175000017500000000025511357170242024321 0ustar keeskees <GR]hs~ dSdc cScb bSca bRca cRcb dRcb  TR   )&$ ! #! deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmc4.lmp0000644000175000017500000000220511357170242024303 0ustar keeskeesV`ir| (06>FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ##  ##""%#%%9;9;;9=BA;>,B:=,A9>VVWWWWWWWXXXXoooppp>>VWWWWWWWXXXXXoopppp??WWWWWWXXXXXXXppppp?WWWWWXXXXXXXXpppp?WWWXXXXXXXXXppppWWWXXXXXXXXXppppWXXXXXXXXXYppppXXXXXXXXXYYppXXXXXXXYYYYpXXXXXXYYYYYYXXXXYYYYYYZZXXYYYYYYZZZZYYYYYYZZZZZYYYYZZZZZZYYYZZZZZZYZZZZZZZZZZZZZZZZZZ[ZZZZ[[ZZ[[[[[[[[[[ғ񭭭񭭮CD򮮯DDD򯯯DDDDD򯯰DDDDDDD򰰰DDDDDDDEEEE˰DDDDDDDEEEEEEE#˱DDDDDDDEEEEEE## ˱DDDDDDDEEEEEE## ˶DDDDDDEEEEE## 󶶶DDDDDDEEEE## 󶶶D555666E## 󶶶55666667777# $ j󶶶66666667777 $$ Tj󶶶6666667777888 $$ TTU66666677888888$$$$ TUUU666667888888999::: %%UUUUUlmm888899999::::%%%UUUUVVVVllmmmm8999999:::::;;%UUUVVVVVVmmmmm99999:::;;;;;UUVVVVVVVmmmmmnnnoo􇇶99::;;;;;;;UVVVVVVVVmmmmnnnnnnooooo􇇇;;;;;;;;=VVVVVVVVWWmmnnnnnnooooop;;;;;;<==VVVVVVWWWWWnnnnnooooopp;;<<===VVVVVWWWWWWnnnnoooooppp<<<===VVVVWWWWWWWnnnoooooppp<====>VVWWWWWWWXXXooooopppp=>>>?WWWWWWWXXXXXoooppppp>>??WWWWWWXXXXXXoopppppp????WWWWWXXXXXXXpppppp???WWWWXXXXXXXXpppppp???WWXXXXXXXXXpppppp@WXXXXXXXXXYpppppqqAXXXXXXXXYYYppppqqAXXXXXXXXYYYYppqqqqXXXXXXYYYYYYZqqrrrXXXXYYYYYYZZZrrrrXXXYYYYYYZZZZrrrXYYYYYYZZZZZrrrYYYYYYZZZZZrrrYYYYZZZZZZrrYYZZZZZZZZrZZZZZZZZ[[ZZZZZZ[[[ZZZZZ[[[[ZZZ[[[[[Z[[[[[[[[[[[[[\[[\\\\\\\\ғ񭭮򮮯򯯯D򯯰DD򰰰DDDD򰰰DDDDDDEEE󱱱DDDDDDEEEEEEEEF󱱶DDDDDEEEEEEEEFFF󶶶DDDDDEEEEEEEEFF 󶶶DDDDDEEEEEEE# 󶶶DDDDDEEEEEEE# 󶶶DDDDEEEEEE## $ 󶶶56666EEE77# $ 󶶶6666667777 $$ 666667777888 $$ U6666677888888$$$$ UU666678888889999: %%%%UUUVm8888899999::::%%%%%UUVVVVVVmmmm889999999::::;%%%%UVVVVVVVmmmm999999:::;;;;;%&VVVVVVVVmmmmn9999:;;;;;;;==VVVVVVVWWmmmnnnnooooo9;;;;;;;;<==VVVVVVWWWWmnnnnnooooop;;;;;;<<===VVVVVWWWWWWnnnnoooooppp􇇷;;<<<<====VVVWWWWWWWnnnoooooppppp􇇇<<<<=====VVWWWWWWWWXXooooopppppqqq<<<===>>>WWWWWWWWXXXooooppppppqqqq=>>>>?WWWWWWWXXXXXooppppppqqqqq>>>???WWWWWXXXXXXXpppppppqqqqqq>????WWWWXXXXXXXXppppppqqqqqqq?????WWXXXXXXXXXpppppqqqqqqqqq???@WXXXXXXXXXYpppppqqqqqqqq?@@AXXXXXXXXYYYpppqqqqqqqrrAAAXXXXXXXYYYYYppqqqqqrrrAAAXXXXXXYYYYYYZqqqrrrrrAXXXXXYYYYYYZZZrrrrrrrXXXYYYYYYZZZZrrrrrrXXYYYYYYYZZZZrrrrrrYYYYYYYZZZZZrrrrrYYYYYZZZZZZrrrrrYYYZZZZZZZZrrrrYZZZZZZZZ[[rrZZZZZZZ[[[[sZZZZZ[[[[[tZZZZ[[[[[[tZZ[[[[[[\[[[[[[\\[[[[\\\[[\\\\[\\\\\\\\\\\\\\\\]]]ҕ򮮯򯯯򯯰򯰰D򰰰DDD󰱱DDDDE󱱱DDDDEEEEEEEEFFF󱶶DDDDEEEEEEEEFFFFF󶶶DDDDEEEEEEEEFFFFF 󶶶DDDEEEEEEEEFFFFF 󶶶DDDEEEEEEEEFFFF 󶶶DDDEEEEEEEEFFFF $ 󶶶DDEEEEEEEEFFF $ 6666EE777 $$ 66667777888 $$ 666677888888$$$$ U66678888889999$ %%%%% UVV88888999999:::%%%%% VVVVVVmm889999999::::;%%%% &VVVVVVVmmm99999999::;;;;%%&&&VVVVVVWmmm99999:;;;;;;;<=&VVVVVVWWWWmnoo99;;;;;;;<<====VVVVWWWWWWnnnnooooop;;;;;<<<<====VVVVWWWWWWnnnoooooppp;<<<<<=====VVVWWWWWWWXnooooopppp<<<<<====>>VWWWWWWWXXXoooopppppqqqqqqqqq<<<===>>>??WWWWWWXXXXXooppppppqqqqqqqqq<=>>>>???WWWWWXXXXXXoppppppqqqqqqqqqq>>>?????WWWXXXXXXXXppppppqqqqqqqqqq>??????WWWXXXXXXXXpppppqqqqqqqqqqq?????@@WXXXXXXXXYpppppqqqqqqqqqrr???@@@XXXXXXXXYYYpppqqqqqqqqrrrr?@@AAAXXXXXXYYYYYppqqqqqqrrrrrtAAAAAXXXXXYYYYYYYqqqqqrrrrrrstAAAAXXXXXYYYYYYZZqqrrrrrrrsttAAAXXXYYYYYYYZZZrrrrrrrrttBXXYYYYYYYZZZZrrrrrrrsttBYYYYYYYZZZZZrrrrrrstttYYYYYYZZZZZZrrrrrstttYYYYZZZZZZZZrrrrstttYYZZZZZZZZ[[rrsttttZZZZZZZZ[[[[stttttZZZZZZ[[[[[sttttZZZZZ[[[[[[tttttZZZ[[[[[[\ttttZ[[[[[[\\\ttt[[[[[\\\\tt[[[\\\\\t[[\\\\\\\\\\\\]\\\\]]\\\]]\]]]]]]]]ҕ򯯯򯯰򯰰򰰰󰱱D󱱱DDD󱶶DDDEEEEEEEEFFFFF󶶶DDEEEEEEEEFFFFFF󶶶DDEEEEEEEEFFFFFFFF󶶶DDEEEEEEEEFFFFFFF 󶶶DDEEEEEEEEFFFFFFF 󶶶DEEEEEEEEFFFFFF $ DEEEEEEEEFFFFF $ EEEEEEEEFFFFF $$ 66EE77788FF $$ 66677888888$$$$ 6678888889999$ VV6888888999999:: %%%%% &VVVVVm88899999999:::%%%% &&&VVVVVVmm999999999::;;;;%% &&&&VVVVVWWm9999999;;;;;;<<&&&&VVVVVWWWW9999;;;;;<<<<====VVVVWWWWWWnooooo;;;;<<<<<======VVWWWWWWWnnoooooopp<<<<<<<=====>VWWWWWWWXXXoooooppp<<<<<<====>>>?WWWWWWWXXXoooopppppq<<<<<==>>>>??WWWWWWXXXXXoopppppqqqqqqqqq<<=>>>>>????WWWWXXXXXXoppppppqqqqqqqqq>>>>>?????WWWXXXXXXXXpppppqqqqqqqqqq>>>?????@@WXXXXXXXXYpppppqqqqqqqqqr>?????@@@XXXXXXXXYYYpppqqqqqqqqrrr???@@@AAXXXXXXYYYYYppqqqqqqrrrrrsttttt?@@AAAAXXXXXYYYYYYYqqqqqrrrrrrstttttAAAAAAAXXXYYYYYYYYZqqrrrrrrrsttttttAAAAAAXXXYYYYYYYZZZrrrrrrrrsttttttAAABBXYYYYYYYZZZZrrrrrrrsttttttBBBYYYYYYYZZZZZrrrrrrstttttttBBBYYYYYZZZZZZrrrrrssttttttBBYYYYZZZZZZZZrrrrstttttttYYYZZZZZZZZ[[rrstttttttYYZZZZZZZ[[[[ssttttttZZZZZZZ[[[[[stttttttZZZZZ[[[[[[tttttttZZZZ[[[[[[\\tttttZZ[[[[[[\\\tttt[[[[[[\\\\tttt[[[[\\\\\ttt[[\\\\\\tt[\\\\\\]]t\\\\\]]]\\\\]]]]\\]]]]]]]]]]]]]]]]؏؏ҕ򯯯򯰰򰰰󰰱󱱱󱶶󶶶EEEEEEEEFFFF󶶶EEEEEEEEEFFFFFFFF󶶶EEEEEEEEEFFFFFFFFGG󶶶EEEEEEEEFFFFFFFFGG 󶶶EEEEEEEEFFFFFFFFG EEEEEEEEFFFFFFFFG EEEEEEEEFFFFFFFG EEEEEEEFFFFFFF$ EEEEEEFFFFFFF$ 6EE78888FFF$$$ 678888889999$ 8888889999999 %%%%% &&VVVV888899999999:::%%%% &&VVVVWW89999999999:;;;%%% &&&&VVVWWW99999999;;;;;<<<&&&&&VVWWWWW99999;;;;<<<<<====''VWWWWWWWoo9;;;<<<<<<<=====''WWWWWWWWXoooooop<<<<<<<<=====>>'WWWWWWWXXXooooppp<<<<<<<===>>>???WWWWWXXXXoooppppp<<<<<==>>>>????WWWWXXXXXXoppppppqqqqqqqq<<<<>>>>>?????@WWXXXXXXXYpppppqqqqqqqqq>>>>>?????@@WXXXXXXXXYYppppqqqqqqqqq>>>?????@@@@XXXXXXXYYYYppqqqqqqqqqr>?????@@@@AXXXXXXYYYYYYqqqqqqqqrrr???@@@AAAXXXXXYYYYYYYqqqqqqrrrrrssttttt?@@AAAAAAXXXYYYYYYYYZqqqrrrrrrsstttttttAAAAAAAAXXYYYYYYYYZZZrrrrrrrsstttttttttAAAAAABBXYYYYYYYZZZZrrrrrrrssttttttttAAAABBBYYYYYYYZZZZZrrrrrrssttttttttABBBBBYYYYYZZZZZZrrrrrssttttttttBBBBBYYYYZZZZZZZZrrrsssttttttttBBBYYYYZZZZZZZ[[rrssttttttttBYYYZZZZZZZ[[[[ssttttttttYZZZZZZZ[[[[[sstttttttZZZZZZ[[[[[[\ttttttttZZZZZ[[[[[[\\tttttttZZZ[[[[[[\\\ttttttZ[[[[[[\\\\tttttt[[[[[\\\\\ttttt[[[\\\\\\tttt[[\\\\\\]]tt\\\\\\]]]]t\\\\]]]]]\\\]]]]]\]]]]]]]]]]]]]]]]]]]]^؏؏؏؏ҕ򯰰򰰰󰰱󱱱󱶶󶶶󶶶EEEEEEFFF󶶶EEEEEEEEFFFFFFF󶶶EEEEEEEEFFFFFFFFGGGG󶶶EEEEEEEFFFFFFFFGGGGG EEEEEEEFFFFFFFFGGGGG EEEEEEEFFFFFFFGGGGGG EEEEEEEFFFFFFFGGGGG EEEEEEFFFFFFFGGGGG EEEEEFFFFFFFGGGGG EEEEFFFFFFGGGGGG E888888999GGGG 88888999999GG %%%%% VVV888999999999:%%%%% &&VVWW89999999999:;;;%%% &&&&VWWWW999999999;;;;<<<<&&&&VWWWWW999999;;;<<<<<<<==&'''WWWWWW99;;<<<<<<<<=====''''WWWWWWXXooooo<<<<<<<<<====>''''WWWWWXXXXoooopp<<<<<<<<===>>>>???WWWWWXXXXXoopppp<<<<<<<=>>>>>????@WWWXXXXXXopppppqqqq<<<<<>>>>>>????@@WWXXXXXXYYYpppqqqqqqqqq>>>>>>????@@@@XXXXXXXYYYYppqqqqqqqqq>>>>????@@@@@XXXXXXYYYYYYqqqqqqqqrr>>????@@@@AAAXXXXYYYYYYYqqqqqqrrrrr???@@@AAAAAXXXYYYYYYYYZqqqrrrrrrss?@@AAAAAAABXYYYYYYYYZZZrrrrrrrssstttttttAAAAAAAABBYYYYYYYYZZZZrrrrrrrssttttttttttAAAAAABBBBYYYYYYZZZZZrrrrrrssttttttttttAAAABBBBBYYYYYZZZZZZrrrrrssstttttttttABBBBBBYYYYYZZZZZZZrrrsssttttttttttBBBBBBYYYYZZZZZZZ[[rrssttttttttttBBBBBBYYZZZZZZZ[[[[ssstttttttttBBBYZZZZZZZ[[[[[sstttttttttBZZZZZZZ[[[[[[sttttttttttZZZZZ[[[[[[\\tttttttttZZZZ[[[[[[\\\ttttttttZZ[[[[[[\\\\ttttttt[[[[[[\\\\\ttttttu[[[[\\\\\\]ttttt[[\\\\\\]]tttt[\\\\\\]]]]tt\\\\\]]]]]]\\\\]]]]]]\\]]]]]]^]]]]]]^]]]]]^]]]]^^]]^^^^^؏؏؏؏ؐؐҖ򰰰򰰰󱱱󱱶󶶶󶶶󶶶EEEEF󶶶EEEEEEFFFFFF󶶶EEEEEEFFFFFFFFGGGGGGEEEEEEFFFFFFFFGGGGGGGEEEEEEFFFFFFFGGGGGGGGHEEEEEEFFFFFFFGGGGGGGG EEEEEEFFFFFFFGGGGGGG EEEEEFFFFFFFGGGGGGG EEEEFFFFFFGGGGGGGG EEEFFFFFFGGGGGGGG EEFFFFFFGGGGGGGG 88889999GGGGGG V8899999999GGG%%%% &&WW99999999999;;%%% &&WWW9999999999;;<<<<<&&&&WWWW99999999;<<<<<<<<=&&''''WWWWW9999<<<<<<<<<<====''''''WWWWWXXoo<<<<<<<<<<====>'''''(WWWWXXXXooopp<<<<<<<<<==>>>>??''((WWXXXXXXoppp<<<<<<<=>>>>>????@@(WXXXXXXYYYppp<<<<<>>>>>>????@@@@XXXXXXYYYYYppqqqqqqqq<>>>>>>????@@@@@XXXXXXYYYYYYqqqqqqqqq>>>>????@@@@@AAXXXXYYYYYYYqqqqqqqrrr>>????@@@@AAAAXXXYYYYYYYYqqqqqrrrrr????@@@AAAAAABXYYYYYYYYZZZqrrrrrrss?@@AAAAAAABBYYYYYYYYZZZZrrrrrrrsssttttttttAAAAAAAABBBBYYYYYYZZZZZrrrrrrsssttttttttttAAAAAABBBBBYYYYYYZZZZZrrrrrsssttttttttttuAAAABBBBBBYYYYYZZZZZZZrrrsssstttttttttuuABBBBBBBBYYYZZZZZZZ[[rrssstttttttttuuBBBBBBBBYYZZZZZZZ[[[[sssttttttttttuBBBBBBBYZZZZZZZ[[[[[ssstttttttttuuBBBBZZZZZZZ[[[[[[sstttttttttuuBBZZZZZZ[[[[[[\\tttttttttuuZZZZZ[[[[[[\\\ttttttttuuuZZZ[[[[[[\\\\tttttttuuuZ[[[[[[\\\\\\tttttuuu[[[[[\\\\\\]ttttuuu[[[\\\\\\]]]ttuuu[[\\\\\\]]]]ttuu\\\\\\]]]]]]uu\\\\]]]]]]^u\\\]]]]]]^^\]]]]]]^^]]]]]]^^^]]]]^^^]]]^^^]^^^^^^^^؏؏ؐؐؐؐؐҖ򰰰󱱱󱱶󶶶󶶶󶶶󶶶󶶶EEEEEFFFFF󶶶EEEEEFFFFFFFFGGGGGGHEEEEFFFFFFFGGGGGGGGHHEEEEFFFFFFFGGGGGGGGHHHEEEEFFFFFFFGGGGGGGGHHHHEEEEFFFFFFFGGGGGGGGHHHH EEEEFFFFFFGGGGGGGGGHHHH EEEFFFFFFGGGGGGGGGHHH EEFFFFFFGGGGGGGGGHHH EFFFFFFGGGGGGGGGHHH FFFFFFGGGGGGGGGHH 899999GGGGGGGGHH 99999999GGGG%%% &&W999999999;<<<<<<&&&&WW99999999<<<<<<<<<&&''WWW99999<<<<<<<<<<===''''''((WWXX<<<<<<<<<<<===>'''''((((WXXXXXXoo<<<<<<<<<<==>>>>''''((((WXXXXXYYYp<<<<<<<<<>>>>>>???@((((XXXXXYYYYYp<<<<<<<>>>>>>???@@@@@)XXXXYYYYYYYqqqqqqq<<<<>>>>>>???@@@@@@AXXXXYYYYYYYqqqqqqqq>>>>>>???@@@@@AAAXXXYYYYYYYYqqqqqqrrr>>>>???@@@@AAAAABXYYYYYYYYZZqqqrrrrr>???@@@AAAAAABBBYYYYYYYZZZZrrrrrrsss?@@AAAAAAABBBBYYYYYYYZZZZrrrrrrssstttttttttAAAAAAAABBBBBYYYYYYZZZZZrrrrrsssstttttttttuAAAAAABBBBBBYYYYYZZZZZZZrrrsssstttttttttuuuAAAABBBBBBBBYYYZZZZZZZ[[rsssstttttttttuuuuuABBBBBBBBBYYZZZZZZZ[[[[ssssttttttttuuuuuBBBBBBBBBYZZZZZZZ[[[[[sssttttttttuuuuuBBBBBBBBYZZZZZZ[[[[[[sstttttttttuuuuBBBBBBBZZZZZ[[[[[[\\sttttttttuuuuuBBBBZZZZ[[[[[[\\\\tttttttuuuuuBBZZZ[[[[[[\\\\\ttttttuuuuuZZ[[[[[[\\\\\\tttttuuuuu[[[[[[\\\\\\]ttttuuuuu[[[[\\\\\\]]]ttuuuuu[[\\\\\\]]]]]uuuuu[\\\\\\]]]]]]uuuu\\\\\]]]]]]^^uu\\\\]]]]]]^^^u\\]]]]]]^^^^]]]]]]^^^^]]]]]^^^^]]]]^^^^^]]^^^^^^^^^^^^^^^ؐؐؐؐؐؐؐ󱱱󱱶󶶶󶶶󶶶󶶶󶶶󶶶EEEFFFFEEEFFFFFFFGGGHHEEEFFFFFFFGGGGGGGGHHHHEEEFFFFFFFGGGGGGGGHHHHHEEEFFFFFFFGGGGGGGGHHHHHHEEFFFFFFGGGGGGGGGHHHHHHHEEFFFFFFGGGGGGGGGHHHHHHEEFFFFFFGGGGGGGGGHHHHHHEFFFFFFGGGGGGGGGHHHHHHFFFFFFGGGGGGGGGHHHHHHFFFFGGGGGGGGGGHHHHHHFFFGGGGGGGGGGHHHHH 99999GGGGGGGHHHHH&&9999999GGG<<<<'''''(((((XXXXXYYY<<<<<<<<<<<=>>>>''''((((((XXXXYYYY<<<<<<<<<>>>>>>???(((((()XXXYYYYYY<<<<<<<>>>>>>???@@@@(()))XYYYYYYYY<<<<<>>>>>>???@@@@@@))))XYYYYYYYYqqqqqqrr>>>>>>???@@@@@AAA)))YYYYYYYYZZqqqrrrr>>>>???@@@@AAAAABBBYYYYYYYYZZZrrrrrrs>???@@@AAAAAABBBBYYYYYYYZZZZrrrrrrss?@@AAAAAAABBBBBYYYYYYZZZZZrrrrrsssstttttttttAAAAAAAABBBBBBBYYYYZZZZZZZrrrsssssttttttttuuAAAAAABBBBBBBBYYYZZZZZZZ[[rsssssttttttttuuuuAAAABBBBBBBBBYYZZZZZZZ[[[[ssssttttttttuuuuuuABBBBBBBBBBYYZZZZZZ[[[[[sssstttttttuuuuuuuBBBBBBBBBBBZZZZZZ[[[[[[ssstttttttuuuuuuuuBBBBBBBBBBZZZZZ[[[[[[\\stttttttuuuuuuuuBBBBBBBBZZZZ[[[[[[\\\\tttttttuuuuuuuuBBBBBBZZZ[[[[[[\\\\\ttttttuuuuuuuuBBBZZ[[[[[[\\\\\\tttttuuuuuuuZ[[[[[[\\\\\\]]tttuuuuuuu[[[[[\\\\\\]]]ttuuuuuuu[[[\\\\\\]]]]]uuuuuuu[[\\\\\\]]]]]]uuuuuu\\\\\\]]]]]]^^uuuu\\\\]]]]]]^^^uu\\\]]]]]]^^^^^\]]]]]]^^^^^]]]]]]^^^^^^]]]]^^^^^^]]]^^^^^^]^^^^^^_^^^^^_^^^_^_ؐؐؐؐؐؐؐ󱱱󶶶󶶶󶶶󶶶󶶶󶶶EEFFFEEFFFFFFFEFFFFFFFGGGGGGGGHHHHHHEFFFFFFFGGGGGGGGHHHHHHHEFFFFFFGGGGGGGGGHHHHHHHHEFFFFFFGGGGGGGGGHHHHHHHHIIEFFFFFFGGGGGGGGGHHHHHHHHIIFFFFFFGGGGGGGGGHHHHHHHHIFFFFFFGGGGGGGGGHHHHHHHHFFFFGGGGGGGGGGHHHHHHHHFFFGGGGGGGGGGHHHHHHHFFGGGGGGGGGGHHHHHHH9GGGGGGGGGGHHHHHHH999GGGGGGGHHHHHHH99999GG<<<<<<<<<&99999<<<<<<<<<<<='''(X999<<<<<<<<<<<<<==>'''''((((()XXYYY<<<<<<<<<<<<=>>>>''''(((((()))XYYYYY<<<<<<<<<<>>>>>>>?'(((((())))YYYYYYY<<<<<<<<>>>>>>>??@@@((()))))YYYYYYYY<<<<<<>>>>>>>??@@@@@@))))))YYYYYYYYZqqqqrr<>>>>>>>??@@@@@AAA)))))YYYYYYYZZZqrrrr>>>>>??@@@@AAAAABB))YYYYYYYZZZZrrrrrr>>>??@@@AAAAAABBBBBYYYYYYZZZZZrrrrrss?@@AAAAAAABBBBBBBYYYYZZZZZZZrrrsssssuAAAAAAAABBBBBBBBYYYZZZZZZZ[[rsssssttttttttuuuAAAAAAABBBBBBBBBYYYZZZZZZ[[[[ssssstttttttuuuuuuAAAABBBBBBBBBBBYZZZZZZ[[[[[sssstttttttuuuuuuuABBBBBBBBBBBBZZZZZZ[[[[[[ssstttttttuuuuuuuuBBBBBBBBBBBBZZZZZ[[[[[[\\ssttttttuuuuuuuuuBBBBBBBBBBBZZZZ[[[[[[\\\\ttttttuuuuuuuuuuBBBBBBBBBZZZ[[[[[[\\\\\tttttuuuuuuuuuuBBBBBBBZZ[[[[[[\\\\\\tttttuuuuuuuuuBBBBZ[[[[[[\\\\\\]]tttuuuuuuuuu[[[[[[\\\\\\]]]]tuuuuuuuuu[[[[\\\\\\]]]]]uuuuuuuuu[[\\\\\\]]]]]]uuuuuuuu[\\\\\\]]]]]]^^uuuuuu\\\\\]]]]]]^^^^uuu\\\\]]]]]]^^^^^uv\\]]]]]]^^^^^^_]]]]]]^^^^^^_]]]]]^^^^^^_]]]]^^^^^^__]]^^^^^^__^^^^^^__^^^^__^^______ؐؐؐؐؐؐؐ󶶶󶶶󶶶󶶶󶶶󶶶FFFFFFFFFFFFFFFGGGGGGGGHHHHHFFFFFFGGGGGGGGGHHHHHHHIIFFFFFFGGGGGGGGGHHHHHHHIIIFFFFFGGGGGGGGGHHHHHHHIIIIIFFFFFGGGGGGGGGHHHHHHHIIIIIIFFFFFGGGGGGGGGHHHHHHHIIIIIIFFFFGGGGGGGGGGHHHHHHHIIIIIIFFFGGGGGGGGGGHHHHHHHIIIIIFFGGGGGGGGGGHHHHHHHIIIIIFGGGGGGGGGGHHHHHHHIIIIIGGGGGGGGGGHHHHHHHIIIIGGGGGGGGGHHHHHHHIIII99GGGGGGHHHHHHHIIII999G<<<<<<<<<<>>''''((((())))YYYYY<<<<<<<<<<<>>>>>>''(((((()))))YYYYYY<<<<<<<<<>>>>>>??@@(((()))))))YYYYYY<<<<<<<<>>>>>>??@@@@@()))))))YYYYYYYZZrr<<<>>>>>>??@@@@@AAA))))))YYYYYYZZZZrrrrr>>>>>??@@@@AAAAABB)))*YYYYYZZZZZrrrrr>>>??@@@AAAAAABBBBB**YYYYZZZZZZZrrrsss??@@AAAAAAABBBBBBB**YYYZZZZZZ[[rsssssuuAAAAAAAABBBBBBBB**YYZZZZZZ[[[[ssssstttttttuuuuuAAAAAAABBBBBBBBBB*YZZZZZZ[[[[[sssssttttttuuuuuuuAAAAABBBBBBBBBBBBZZZZZZ[[[[[[ssssttttttuuuuuuuuAABBBBBBBBBBBBBZZZZZ[[[[[[\\ssttttttuuuuuuuuuBBBBBBBBBBBBBZZZZ[[[[[[\\\\stttttuuuuuuuuuuBBBBBBBBBBBBZZZ[[[[[[\\\\\tttttuuuuuuuuuuuBBBBBBBBBBZZ[[[[[[\\\\\\]tttuuuuuuuuuuuuBBBBBBBBZ[[[[[[\\\\\\]]ttuuuuuuuuuuuuBBBBBB[[[[[[\\\\\\]]]]tuuuuuuuuuuu,[[[[\\\\\\]]]]]uuuuuuuuuuu[[[\\\\\\]]]]]]uuuuuuuuuu[[\\\\\\]]]]]]^^uuuuuuv\\\\\\]]]]]]^^^^uuvvv\\\\]]]]]]^^^^^vvvv\\\]]]]]]^^^^^^_vv\]]]]]]^^^^^^__v]]]]]]^^^^^^___]]]]^^^^^^___]]]^^^^^^____]^^^^^^____^^^^^____^^^____^_________ؐؐؐؐؐؑ궶󶶶󶶶󶶶󶶶FFFFFFFGGGGGGGGGHHHHFFFFGGGGGGGGGHHHHHHHIFFFFGGGGGGGGGHHHHHHHIIIIIIFFFFGGGGGGGGGHHHHHHHIIIIIIIFFFFGGGGGGGGGHHHHHHHIIIIIIIIFFGGGGGGGGGGHHHHHHHIIIIIIIIFFGGGGGGGGGGHHHHHHHIIIIIIIIFFGGGGGGGGGGHHHHHHHIIIIIIIIFGGGGGGGGGGHHHHHHHIIIIIIIIGGGGGGGGGGHHHHHHHIIIIIIIGGGGGGGGGHHHHHHHIIIIIIIGGGGGGGGHHHHHHHIIIIIIIGGGGGGGHHHHHHHIIIIIIIGGGGG<<>>''''(((()))))YYY<<<<<<<<<<<<>>>>>'''((((()))))YYYYY<<<<<<<<<<>>>>>>>?@((((()))))))YYYYYY<<<<<<<<>>>>>>>?@@@@(())))))))YYYYYZZZZ<<<<>>>>>>>?@@@@@AAA)))))))*YYYYZZZZZrrrr>>>>>>>?@@@@AAAAAB))))***YYYYZZZZZZrrrs>>>>>?@@@AAAAAABBBBB*****YYZZZZZZ[[rsss>?@@AAAAAAABBBBBB*****YZZZZZZ[[[[sssssuuAAAAAAAABBBBBBBB****ZZZZZZ[[[[[sssssttttttuuuuuuAAAAAAABBBBBBBBBB**+ZZZZZ[[[[[[ssssttttttuuuuuuuAAAAABBBBBBBBBBB*++ZZZZ[[[[[[\\ssstttttuuuuuuuuuAABBBBBBBBBBBBB++ZZZ[[[[[[\\\\stttttuuuuuuuuuuBBBBBBBBBBBBB++ZZ[[[[[[\\\\\\ttttuuuuuuuuuuuBBBBBBBBBBBB++Z[[[[[[\\\\\\]tttuuuuuuuuuuuuBBBBBBBBBBB++[[[[[[\\\\\\]]]tuuuuuuuuuuuuuBBBBBBBB+,[[[[[\\\\\\]]]]uuuuuuuuuuuuuuBBBBBB,,[[[[\\\\\\]]]]]uuuuuuuuuuuvv,,,,[[\\\\\\]]]]]]^uuuuuuuvvvv,,[\\\\\\]]]]]]^^uuuuuvvvvv,\\\\\\]]]]]]^^^^uvvvvvv\\\\\]]]]]]^^^^^vvvvvv\\\\]]]]]]^^^^^^vvvvv\\]]]]]]^^^^^^__vvv]]]]]]^^^^^^____v]]]]]^^^^^^_____]]]]^^^^^^_____]]^^^^^^_____^^^^^^_____^^^^_____^^__________________ؐؐؐؑؑؑ궶궶󶶶󶶶FFFFGGGGGGGGHHHHFFFGGGGGGGGGHHHHHHHFFGGGGGGGGGHHHHHHHIIIIIIIFFGGGGGGGGGHHHHHHHIIIIIIIIJFGGGGGGGGGGHHHHHHHIIIIIIIIJJFGGGGGGGGGGHHHHHHHIIIIIIIIJJJFGGGGGGGGGGHHHHHHHIIIIIIIIJJJJJFGGGGGGGGGGHHHHHHHIIIIIIIIJJJJGGGGGGGGGGHHHHHHHIIIIIIIIJJJJGGGGGGGGGHHHHHHHIIIIIIIIJJJJGGGGGGGGHHHHHHHIIIIIIIIJJJGGGGGGGHHHHHHHIIIIIIIIJJJGGGGGGHHHHHHHIIIIIIIIJJGGGGGHHHHHHHIIIIIIIIJYGG<<<<<<>>>>'''((((())))YYYY<<<<<<<<<<>>>>>>>?(((((())))))YYYYZ<<<<<<<<<>>>>>>>?@@@((()))))))**YYYYZZZZ<<<<<<>>>>>>>?@@@@@AA))))))))***YYYZZZZZZrr>>>>>>>?@@@@AAAAAB))))******YZZZZZZ[[rs>>>>>?@@@AAAAAABBBBB******+ZZZZZZ[[[[ss>?@@AAAAAAABBBBBB******+ZZZZZ[[[[[ssssuuuuAAAAAAAABBBBBBBB****++ZZZZ[[[[[[sssssttttuuuuuuuAAAAAAABBBBBBBBB***+++ZZZ[[[[[[\\ssstttttuuuuuuuAAAAABBBBBBBBBBB*++++ZZ[[[[[[\\\\ssttttuuuuuuuuuAABBBBBBBBBBBB+++++Z[[[[[[\\\\\\ttttuuuuuuuuuuBBBBBBBBBBBB+++++[[[[[[\\\\\\]tttuuuuuuuuuuuBBBBBBBBBBB++++,[[[[[\\\\\\]]]tuuuuuuuuuuuuuBBBBBBBBBB+++,,[[[[\\\\\\]]]]uuuuuuuuuuuuvvBBBBBBB++,,,[[[\\\\\\]]]]]uuuuuuuuuuvvvvBBBBB,,,,,[[\\\\\\]]]]]]^uuuuuuvvvvvvv,,,,,,\\\\\\]]]]]]^^uuuvvvvvvvvv,,,,,\\\\\]]]]]]^^^^vvvvvvvvvv,,-\\\\]]]]]]^^^^^vvvvvvvv--\\\]]]]]]^^^^^^vvvvvvv-\\]]]]]]^^^^^^__vvvvv\]]]]]]^^^^^^____vvv]]]]]]^^^^^^______]]]]^^^^^^______]]]^^^^^^_______]^^^^^^_______^^^^^_______^^^_______^_____________`___``_```ؑؑؑؑؑ궶궶궶󶶶FGGGGHHFGGGGGGGGGHHHHHHHFGGGGGGGGGHHHHHHHIIIIIIGGGGGGGGGHHHHHHHIIIIIIIIJJJGGGGGGGGGHHHHHHHIIIIIIIIJJJJGGGGGGGGGHHHHHHHIIIIIIIIJJJJJGGGGGGGGGHHHHHHHIIIIIIIIJJJJJJGGGGGGGGGHHHHHHHIIIIIIIIJJJJJJJGGGGGGGGGHHHHHHHIIIIIIIIJJJJJJGGGGGGGGHHHHHHHIIIIIIIIJJJJJJGGGGGGGHHHHHHHIIIIIIIIJJJJJJGGGGGGHHHHHHHIIIIIIIIJJJJJJGGGGGHHHHHHHIIIIIIIIJJJJJGGGGHHHHHHHIIIIIIIIJJJJJGGGHHHHHHHIIIIIIIIJJJJJ<<<<<<<<>>>>>JJ(((())))YYYZ<<<<<<<<<<>>>>>>>@@(((()))))**YZZZZZ<<<<<<<<>>>>>>>@@@@@AA))))))*****ZZZZZZ[[<<>>>>>>>@@@@AAAAA)))))******++ZZZZZ[[[[>>>>>>@@@AAAAAABBBB*******+++ZZZZ[[[[[ss>>>@@AAAAAAABBBBBB******+++ZZZ[[[[[[sssuuuAAAAAAAABBBBBBB*****++++ZZ[[[[[[\\sssstttuuuuuuuAAAAAAABBBBBBBBB***+++++Z[[[[[[\\\\sstttuuuuuuuuuAAAAABBBBBBBBBBB*++++++[[[[[[\\\\\\ttttuuuuuuuuuAABBBBBBBBBBBB++++++,[[[[[\\\\\\]tttuuuuuuuuuuBBBBBBBBBBBBB+++++,,[[[[\\\\\\]]]tuuuuuuuuuuuuBBBBBBBBBBBB++++,,,[[[\\\\\\]]]]uuuuuuuuuuuvvBBBBBBBBBB+++,,,,[[\\\\\\]]]]]]uuuuuuuvvvvvvBBBBBBBB++,,,,,[\\\\\\]]]]]]^uuuuuvvvvvvvvBBBBB,,,,,,,\\\\\\]]]]]]^^^uvvvvvvvvvvv,,,,,,,\\\\\]]]]]]^^^^vvvvvvvvvvvv,,,,,--\\\]]]]]]^^^^^vvvvvvvvvv,,,---\\]]]]]]^^^^^^vvvvvvvvw----\]]]]]]^^^^^^__vvvvvww---]]]]]]^^^^^^____vvwww---]]]]]^^^^^^______ww--]]]]^^^^^^_______w.]]]^^^^^^________.]]^^^^^^________.^^^^^^________^^^^_______``^^_______``______```____```_```````````ؑؑؑؑؑ궶궶궶궶HGGGGGGGGHHHHHHGGGGGGGGHHHHHHHIIIIIGGGGGGGGHHHHHHHIIIIIIIIJJJJJGGGGGGGGHHHHHHHIIIIIIIIJJJJJJGGGGGGGGHHHHHHHIIIIIIIIJJJJJJJGGGGGGGHHHHHHHIIIIIIIIJJJJJJJJGGGGGGGHHHHHHHIIIIIIIIJJJJJJJJKGGGGGGGHHHHHHHIIIIIIIIJJJJJJJJKKGGGGGGGHHHHHHHIIIIIIIIJJJJJJJJKGGGGGGHHHHHHHIIIIIIIIJJJJJJJJKGGGGGHHHHHHHIIIIIIIIJJJJJJJJGGGGHHHHHHHIIIIIIIIJJJJJJJJGGGHHHHHHHIIIIIIIIJJJJJJJGGHHHHHHHIIIIIIIIJJJJJJJGHHHHHHHIIIIIIIIJJJJJJJ<<<<<<<>>>>>JJJJ(())ZZZZZ<<<<<<<<>>>>>>>@@@@@())))***ZZZZ[[[<<<<>>>>>>>@@@@AAAAA)))))******+++ZZZ[[[[[>>>>>>@@@AAAAAABBBB*******+++++ZZ[[[[[[s>>>@@AAAAAAABBBBBB******+++++Z[[[[[[\\ssuu@AAAAAAAABBBBBBB*****++++++[[[[[[\\\\ssuuuuuuAAAAAAABBBBBBBBB***++++++,[[[[[\\\\\ssttuuuuuuuuuAAAAABBBBBBBBBB**++++++,,[[[[\\\\\\]]tuuuuuuuuuuAABBBBBBBBBBBB++++++,,,[[[\\\\\\]]]tuuuuuuuuuuBBBBBBBBBBBBB+++++,,,,[[\\\\\\]]]]]uuuuuuuuuvvBBBBBBBBBBBB++++,,,,,[\\\\\\]]]]]]uuuuuuvvvvvBBBBBBBBBB+++,,,,,,\\\\\\]]]]]]^uuuvvvvvvvvvBBBBBBBB++,,,,,,,\\\\\]]]]]]^^^vvvvvvvvvvvvBBBBB,,,,,,,,-\\\\]]]]]]^^^^vvvvvvvvvvvwB,,,,,,,---\\]]]]]]^^^^^vvvvvvvvvwww,,,,,----\]]]]]]^^^^^^vvvvvvvwwwww,,,-----]]]]]]^^^^^^__vvvvwwwww------]]]]]^^^^^^____vwwwwww------]]]]^^^^^^______wwwww----.]]]^^^^^^_______www--..]]^^^^^^________ww...]^^^^^^________`w...^^^^^^_______```..^^^^^_______```^^^______````^______`````____``````__``````````````````ؑؑؑؑؑ궶궶궶궶GGGGGGHHHHHGGGGGGHHHHHHHIIIIGGGGGGHHHHHHHIIIIIIIIJJJJJJGGGGGGHHHHHHHIIIIIIIIJJJJJJJGGGGGHHHHHHHIIIIIIIIJJJJJJJJKGGGGGHHHHHHHIIIIIIIIJJJJJJJJKKGGGGGHHHHHHHIIIIIIIIJJJJJJJJKKKKGGGGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKGGGGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKGGGGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKGGGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKGGGHHHHHHHIIIIIIIIJJJJJJJJKKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKGHHHHHHHIIIIIIIIJJJJJJJJKKKHHHHHHHIIIIIIIIJJJJJJJJKKK<>>>>>JJJJJJK)**ZZ[[[[<<<<<>>>>>>>>@@@AAAA)))*****+++Z[[[[[>>>>>>>>@@AAAAAABBB)*******+++++[[[[[[\>>>>>@AAAAAAABBBBB*******++++++[[[[[\\\suu>AAAAAAAABBBBBBB*****++++++,,[[[[\\\\\suuuuuuuAAAAAAABBBBBBBB****++++++,,,[[[\\\\\\]]tuuuuuuuuuAAAAABBBBBBBBBB**++++++,,,,[[\\\\\\]]]]uuuuuuuuuAABBBBBBBBBBBB++++++,,,,,[\\\\\\]]]]]uuuuuuuvvvBBBBBBBBBBBBB+++++,,,,,,\\\\\\]]]]]]uuuuuvvvvvBBBBBBBBBBBB++++,,,,,,,\\\\\]]]]]]^uuvvvvvvvvvBBBBBBBBBB+++,,,,,,,-\\\\]]]]]]^^^vvvvvvvvvvBBBBBBBB++,,,,,,,--\\\]]]]]]^^^^vvvvvvvvvvwBBBBBB,,,,,,,,---\\]]]]]]^^^^^vvvvvvvvwwwwB,,,,,,,-----]]]]]]^^^^^^vvvvvvwwwwww,,,,,------]]]]]^^^^^^__vvvwwwwwwww,,,-------]]]]^^^^^^____wwwwwwwww,-------.]]]^^^^^^_____wwwwwwww------..]]^^^^^^______wwwwwww----...]^^^^^^________wwww--....^^^^^^_______``www.....^^^^^_______````w.....^^^^______``````...^^^______``````//^_____```````_____```````__````````````````````````````ؑؑؑؑؑ붶붶붶붶붶GGGHHHHHGGGHHHHHHHIIIGGGHHHHHHHIIIIIIIIJJJJJJJGGGHHHHHHHIIIIIIIIJJJJJJJJKGGGHHHHHHHIIIIIIIIJJJJJJJJKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKKKGGHHHHHHHIIIIIIIIJJJJJJJJKKKKKKKGHHHHHHHIIIIIIIIJJJJJJJJKKKKKKHHHHHHHIIIIIIIIJJJJJJJJKKKKKKHHHHHHIIIIIIIIJJJJJJJJKKKKKKHHHHHIIIIIIIIJJJJJJJJKKKKKK<<>>>>JJJJJJKKKKK)***+[[[[[<<>>>>>>>@@AAAAAABBB******+++[[[[\\\>>>>>>@AAAAAAABBBBB*******++++++,[[[\\\\\u>AAAAAAAABBBBBBB*****++++++,,,,[[\\\\\\]uuuuuuAAAAAAABBBBBBBB****++++++,,,,,[\\\\\\]]]]uuuuuuuuAAAAABBBBBBBBBB**++++++,,,,,,\\\\\\]]]]]uuuuuuvvvAAABBBBBBBBBBB*++++++,,,,,,,\\\\\]]]]]]uuuvvvvvvBBBBBBBBBBBBB+++++,,,,,,,-\\\\]]]]]]^uvvvvvvvvvBBBBBBBBBBBB++++,,,,,,,--\\\]]]]]]^^^vvvvvvvvvBBBBBBBBBBB+++,,,,,,,---\\]]]]]]^^^^vvvvvvvvvvBBBBBBBB++,,,,,,,----\]]]]]]^^^^^vvvvvvvvwwwBBBBBB,,,,,,,,-----]]]]]]^^^^^^vvvvvvwwwwwwBB,,,,,,,------]]]]]^^^^^^__vvvwwwwwwww,,,,,-------]]]]^^^^^^____wwwwwwwwww,,,-------..]]^^^^^^_____wwwwwwwwww,-------...]^^^^^^______wwwwwwwww------....^^^^^^_______wwwwwwww----.....^^^^^_______``wwwww--......^^^^______`````wwx.......^^^______``````xx....../^^_____````````x...///_____`````````////___``````````//__```````````````````````````````````````````ؑؑؑؑؑ붶붶붶붶붶뷷HHHHHHHHHHHIHHHHHHHIIIIIIIIJHHHHHHHIIIIIIIIJJJJJJJKKKKHHHHHHHIIIIIIIIJJJJJJJKKKKKKHHHHHHHIIIIIIIIJJJJJJJKKKKKKKHHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLHHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLLHHHHHIIIIIIIIJJJJJJJKKKKKKKKLLLHHHHIIIIIIIIJJJJJJJKKKKKKKKLLHHHIIIIIIIIJJJJJJJKKKKKKKKL<>>>>JJJJJKKKKKKKK****++[[\\\\>>>>>>@AAAAAAABBBBB******+++++,[\\\\\\uu>>AAAAAAAABBBBBB******++++++,,,,\\\\\\]]]uuuuuuAAAAAAABBBBBBBB****++++++,,,,,,,\\\\\]]]]]uuuuuvvvAAAAAABBBBBBBBB***++++++,,,,,,,-\\\\]]]]]]uuvvvvvvAAABBBBBBBBBBB*++++++,,,,,,,--\\\]]]]]]^vvvvvvvvvBBBBBBBBBBBB++++++,,,,,,,---\\]]]]]]^^^vvvvvvvvBBBBBBBBBBB+++++,,,,,,,----\]]]]]]^^^^vvvvvvvvvBBBBBBBBBB++++,,,,,,,-----]]]]]]^^^^^vvvvvvvwwwBBBBBBBB+++,,,,,,,------]]]]]^^^^^^vvvvvwwwwwBBBBB+,,,,,,,,-------]]]]^^^^^^__vvwwwwwwwwB,,,,,,,,-------.]]]^^^^^^____wwwwwwwwww,,,,,,-------..]]^^^^^^_____wwwwwwwwww,,,-------....^^^^^^______wwwwwwwwww,-------.....^^^^^_______wwwwwwwwxx------......^^^^______```wwwwxxxx----.......^^^______`````wxxxxx--......./^^_____```````xxxxx........//^_____````````xxx......///____``````````xx...////___```````````/////````````````//````````````0```````````````````````````````````ؑؑؑؑ붶붶붶붶뷷뷷뷷HHHHHHHHHIIIIIIIHHHHIIIIIIIIJJJJJJJKKKHHHHIIIIIIIIJJJJJJJKKKKKKKKHHHIIIIIIIIJJJJJJJKKKKKKKKLLHHHIIIIIIIIJJJJJJJKKKKKKKKLLLHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLHHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLLHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLLHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLHHIIIIIIIIJJJJJJJKKKKKKKKLLLLLLHIIIIIIIIJJJJJJJKKKKKKKKLLLLLL[[>>>>>JJJJKKKKKKKKLLL****+++\\\\\]u>>AAAAAAAABBBBBB******+++++,,,\\\\]]]]]uuvvvAAAAAAABBBBBBBB****++++++,,,,,,-\\\]]]]]]uvvvvvvAAAAAABBBBBBBBB***++++++,,,,,,,---\\]]]]]]^vvvvvvvvAAABBBBBBBBBBB*++++++,,,,,,,----\]]]]]]^^^vvvvvvvBBBBBBBBBBBB++++++,,,,,,,-----]]]]]]^^^^vvvvvvvvBBBBBBBBBBB+++++,,,,,,,------]]]]]^^^^^vvvvvvwwBBBBBBBBBB++++,,,,,,,-------]]]]^^^^^^vvvvwwwwwBBBBBBBB+++,,,,,,,-------.]]]^^^^^^__vwwwwwwwwBBBBB+,,,,,,,,-------..]]^^^^^^___wwwwwwwwwwBB,,,,,,,,-------...]^^^^^^_____wwwwwwwwww,,,,,,-------.....^^^^^______wwwwwwwwwx,,,,-------......^^^^______`wwwwwwwxxx,-------......^^^^______```wwwxxxxxx------......./^^_____`````xxxxxxxxx----.......//^_____```````xxxxxxx---.......///____`````````xxxxx........////___``````````xxxx....../////_````````````xx...//////`````````````//////````````````///0```````````00``````````00``````````````````````````ؑؑؑؑ붶붶붶뷷뷷뷷뷷뷷뷷IIIIIIIIIIIIIIJJJJJJJKKKIIIIIIIIJJJJJJJKKKKKKKKIIIIIIIIJJJJJJJKKKKKKKKLLLIIIIIIIIJJJJJJJKKKKKKKKLLLLLIIIIIIIIJJJJJJJKKKKKKKKLLLLLLIIIIIIIIJJJJJJJKKKKKKKKLLLLLLLIIIIIIIIJJJJJJJKKKKKKKKLLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLIIIIIIIJJJJJJJKKKKKKKKLLLLLLLIIIIIIJJJJJJJKKKKKKKKLLLLLLL\IIIIIIJJJJJJJKKKKKKKKLLLLLLL\\\IIIIIJJJJJJJKKKKKKKKLLLLLLL\\\\<>>JJJJJJJKKKKKKKKLLLLLLL+\\\]]]v>>JJJJKKKKKKKKLLLLL***+++,\\]]]]]]vvvvvvAAAAAAABBBBBBB*****++++++,,,,--\]]]]]]^vvvvvvAAAAAABBBBBBBBB***++++++,,,,,,,----]]]]]]^^^vvvvvvAAABBBBBBBBBB**++++++,,,,,,,------]]]]]^^^^vvvvvvvBBBBBBBBBBBB++++++,,,,,,,-------]]]]^^^^^vvvvvwwBBBBBBBBBBB+++++,,,,,,,--------]]]^^^^^^vvvwwwwwBBBBBBBBBB++++,,,,,,,--------.]]^^^^^^__wwwwwwwwBBBBBBBB+++,,,,,,,-------...]^^^^^^___wwwwwwwwwBBBBBB+,,,,,,,,-------....^^^^^^____wwwwwwwwwwBB,,,,,,,,-------.....^^^^^_____wwwwwwwwwxx,,,,,,-------......^^^^______`wwwwwxxxxx,,,,-------.......^^^_____````wwxxxxxxx,,-------.......//^_____`````xxxxxxxxx------.......///____```````xxxxxxxxx-----.......////___````````xxxxxxxxy---......./////_``````````xxxxxxy........//////```````````xxxxy......///////```````````xxyy...///////0```````````yy//////00```````````y///000``````````0000`````````0000```````00``````0```````````ؑؑؑؑ붶붶뷷뷷뷷뷷뷷뷷뷷뷷IIIIIIIIIJJJJJJJKKIIIIIIJJJJJJJKKKKKKKIIIIIJJJJJJJKKKKKKKKLLLLLIIIIIJJJJJJJKKKKKKKKLLLLLLIIIIIJJJJJJJKKKKKKKKLLLLLLLIIIIIJJJJJJJKKKKKKKKLLLLLLLLLIIIIIJJJJJJJKKKKKKKKLLLLLLLLLLIIIIIJJJJJJJKKKKKKKKLLLLLLLLLLMIIIIIJJJJJJJKKKKKKKKLLLLLLLLLMMMIIIIIJJJJJJJKKKKKKKKLLLLLLLLLMMMIIIIJJJJJJJKKKKKKKKLLLLLLLLLMMMIIIIJJJJJJJKKKKKKKKLLLLLLLLLMMMIIIIJJJJJJJKKKKKKKKLLLLLLLLLMMMIIIIJJJJJJJKKKKKKKKLLLLLLLLMMMMIIIIJJJJJJJKKKKKKKKLLLLLLLLMMMMIIIIJJJJJJJKKKKKKKKLLLLLLLLMMMMIIIIJJJJJJJKKKKKKKKLLLLLLLLMMMM\\IIIIJJJJJJJKKKKKKKKLLLLLLLMMMMM\\]IIIJJJJJJJKKKKKKKKLLLLLLLMMMMM\]]]]]vvvJJJJJJJKKKKKKKKLLLLLLLMMMM++]]]]]]^vvvvvJJJKKKKKKKKLLLLLLLMMM++++,,]]]]]^^vvvvvvAAAAAABBBBBBBBL*MM++++++,,,,,,--]]]]^^^^vvvvvAAABBBBBBBBBB**++++++,,,,,,,-------]]]^^^^^vvvvvwBBBBBBBBBBBB++++++,,,,,,,--------.]]^^^^^^vvvwwwwBBBBBBBBBBB+++++,,,,,,,--------..]^^^^^^__wwwwwwwBBBBBBBBBB++++,,,,,,,--------...^^^^^^___wwwwwwwwBBBBBBBB+++,,,,,,,-------.....^^^^^____wwwwwwwwwBBBBBB+,,,,,,,,-------......^^^^_____wwwwwwwwxxBBB,,,,,,,,-------.......^^^_____``wwwwxxxxxx,,,,,,-------......./^^_____```wxxxxxxxxx,,,,-------.......///____``````xxxxxxxxx,,-------.......////___```````xxxxxxxxx-------......./////_`````````xxxxxxxyy-----.......//////``````````xxxxxyyyy---.......///////``````````xxxyyyyy........///////0``````````xyyyyyy.......///////00``````````yyyyy...///////000``````````yyy//////0000`````````yyy///00000`````````y000000````````y00000```````0000`````000````1```1`ؑؑؑؑ붶뷷뷷뷷뷷뷷뷷뷷뷷뷷뷷IIIJJJJJJJKIIIJJJJJJJKKKKKKIIIJJJJJJJKKKKKKKKLLLLLIIIJJJJJJJKKKKKKKKLLLLLLLLIIJJJJJJJKKKKKKKKLLLLLLLLLIIJJJJJJJKKKKKKKKLLLLLLLLLLIIJJJJJJJKKKKKKKKLLLLLLLLLLMMIIJJJJJJJKKKKKKKKLLLLLLLLLMMMMIIJJJJJJJKKKKKKKKLLLLLLLLLMMMMMIIJJJJJJJKKKKKKKKLLLLLLLLLMMMMMIIJJJJJJJKKKKKKKKLLLLLLLLLMMMMMIJJJJJJJKKKKKKKKLLLLLLLLLMMMMMIJJJJJJJKKKKKKKKLLLLLLLLMMMMMMIJJJJJJJKKKKKKKKLLLLLLLLMMMMMMIJJJJJJJKKKKKKKKLLLLLLLLMMMMMMIJJJJJJJKKKKKKKKLLLLLLLLMMMMMMJJJJJJJKKKKKKKKLLLLLLLMMMMMMM\JJJJJJJKKKKKKKKLLLLLLLMMMMMMM]]]JJJJJJJKKKKKKKKLLLLLLLMMMMMMM]]]]]vvvJJJJJJJKKKKKKKKLLLLLLLMMMMMMM]]]]^^vvvvvJJJJJKKKKKKKKLLLLLLLMMMMMMM,]]]^^^^vvvvJKKKKKKKKLLLLLLMMMMMMM+,,,,]]^^^^^vvvvwAAABBBBBBBBLMMMMMM+++,,,,,,----.]^^^^^^vvwwwwABBBBBBBBBBMMMMM+++,,,,,,,-------...^^^^^^_wwwwwwwBBBBBBBBBBMM++++,,,,,,,--------....^^^^^___wwwwwwwBBBBBBBBBB++++,,,,,,,--------.....^^^^____wwwwwwwBBBBBBBB+++,,,,,,,-------.......^^^_____wwwwwwxxBBBBBB+,,,,,,,,-------......./^^_____``wwwxxxxxxBBBB,,,,,,,,-------.......//^____````xxxxxxxxxx,,,,,,,-------.......///____`````xxxxxxxxxx,,,,-------.......////__```````xxxxxxxxxy,,-------......./////_````````xxxxxxxyyy-------.......//////`````````xxxxxyyyyy-----.......///////``````````xxyyyyyyy---.......///////0``````````yyyyyyyyy........///////000````````yyyyyyyyy......///////0000````````yyyyyyy...///////00000````````yyyyy//////000000```````yyyyy///0000000```````yyy00000000```````yy000000``````y000001`````00011````1111``111`11ؑؑؑ췷뷷뷷뷷뷷뷷뷷뷷뷷뷷뷷뷷JJJJJJKJJJJJJKKKKKJJJJJJKKKKKKKKLLLLJJJJJJKKKKKKKKLLLLLLLLLLJJJJJJKKKKKKKKLLLLLLLLLLMJJJJJJKKKKKKKKLLLLLLLLLLMMJJJJJJKKKKKKKKLLLLLLLLLMMMMMJJJJJKKKKKKKKLLLLLLLLLMMMMMMJJJJJKKKKKKKKLLLLLLLLLMMMMMMMJJJJJKKKKKKKKLLLLLLLLLMMMMMMMJJJJJKKKKKKKKLLLLLLLLLMMMMMMMJJJJJKKKKKKKKLLLLLLLLMMMMMMMMJJJJJKKKKKKKKLLLLLLLLMMMMMMMMJJJJJKKKKKKKKLLLLLLLLMMMMMMMMJJJJKKKKKKKKLLLLLLLLMMMMMMMMJJJJKKKKKKKKLLLLLLLMMMMMMMMMJJJJKKKKKKKKLLLLLLLMMMMMMMMMJJJJKKKKKKKKLLLLLLLMMMMMMMMM]]JJJJKKKKKKKKLLLLLLLMMMMMMMMM]]]^^vvvvJJJJKKKKKKKKLLLLLLLMMMMMMMMM]]^^^^vvvܞJJJKKKKKKKKLLLLLLMMMMMMMMMM]^^^^^vvvwJJKKKKKKKKLLLLLLMMMMMMMMMM,,^^^^^^vwwwwKKKKKKKLLLLLLMMMMMMMMMM,,,,,-^^^^^_wwwwwABBBBBBBBLMMMMMMMMM,,,,,,,-----..^^^^__wwwwwwBBBBBBBBBMMMMMMMM,,,,,,,,-------.....^^^____wwwwwwBBBBBBBBBMMMMM+,,,,,,,,-------....../^^_____wwwwwxxBBBBBBBBMM++,,,,,,,,------.......//^____``wwxxxxxxBBBBBB+,,,,,,,,,------.......///____````xxxxxxxxxBBBB,,,,,,,,,------.......////__``````xxxxxxxxxx,,,,,,,,------......./////_```````xxxxxxxxxy,,,,,,------.......//////````````xxxxxxxyyy,,,------.......///////````````xxxxxyyyyy,------.......////////````````xxxyyyyyyy-----.......///////00````````xyyyyyyyyy---.......///////000````````yyyyyyyyyy........///////0000````````yyyyyyyyyy......///////000000``````yyyyyyyyy..///////0000000``````yyyyyyyy//////00000000`````yyyyyyy///000000000`````yyyyy0000000001`````yyyy000000111```yyy00000111```yy0011111``111111`111111112122ؑ췷췷췷뷷뷷뷷뷷뷷뷷뷷뷷뷷뷷JJJKKKKKJJJKKKKKKKKLLLJJJKKKKKKKKLLLLLLLLLLMMJJJKKKKKKKKLLLLLLLLLLMMMJJJKKKKKKKKLLLLLLLLLMMMMMJJKKKKKKKKLLLLLLLLLMMMMMMMJJKKKKKKKKLLLLLLLLLMMMMMMMNJJKKKKKKKKLLLLLLLLLMMMMMMMNNNJJKKKKKKKKLLLLLLLLLMMMMMMMNNNNJJKKKKKKKKLLLLLLLLMMMMMMMMNNNNJJKKKKKKKKLLLLLLLLMMMMMMMMNNNNJKKKKKKKKLLLLLLLLMMMMMMMMNNNNJKKKKKKKKLLLLLLLLMMMMMMMMNNNNJKKKKKKKKLLLLLLLMMMMMMMMMNNNNJKKKKKKKKLLLLLLLMMMMMMMMMNNNNJKKKKKKKKLLLLLLLMMMMMMMMMNNNNJKKKKKKKKLLLLLLLMMMMMMMMMNNNN]]JKKKKKKKKLLLLLLLMMMMMMMMMNNNN]^^^vvvܞKKKKKKKKLLLLLLMMMMMMMMMMNNNN^^^^^vvwKKKKKKKKLLLLLLMMMMMMMMMMNNNN^^^^^wwwKKKKKKKLLLLLLMMMMMMMMMMNNNN^^^^_wwwwKKKKKLLLLLLMMMMMMMMMMNNNN^^^__wwwwwKKKKLLLLLMMMMMMMMMMMNNN,,--^^___wwwwwwBBBBBBBMMMMMMMMMMMNN,,,,,-----...^____wwwwwxxBBBBBBBMMMMMMMMMN,,,,,,-------.....//____``wxxxxxxBBBBBBMMMMMM,,,,,,,,------.......////__````xxxxxxxxBBBBMMMM,,,,,,,,------......./////_`````xxxxxxxxxxBBBMM,,,,,,,,------.......//////```````xxxxxxxxy,,,,,,,,------.......///////```````xxxxxxyyy,,,,,,------.......////////```````xxxxyyyyyy,,,------.......////////0```````xxyyyyyyyy,------.......////////00```````yyyyyyyyyy-----.......///////0000``````yyyyyyyyyyy---.......///////00000``````yyyyyyyyyyy-........///////000000``````yyyyyyyyyyy......///////0000000`````yyyyyyyyyyy..///////000000000````yyyyyyyyyy//////0000000001````yyyyyyyy///00000000011```yyyyyyy0000000001111``yyyyyy00000011111``yyyy00001111111yyyy001111112yy1111112221111122111222122222222웛췛췷췷췷췷뷷뷷뷷뷷뷷뷷뷷뷷KKKKKKKKKKKKLKKKKKKKKLLLLLLLLLLMMKKKKKKKKLLLLLLLLLMMMMMMKKKKKKKKLLLLLLLLLMMMMMMMNKKKKKKKLLLLLLLLLMMMMMMMNNKKKKKKKLLLLLLLLLMMMMMMMNNNNKKKKKKKLLLLLLLLLMMMMMMMNNNNNKKKKKKKLLLLLLLLMMMMMMMMNNNNNNKKKKKKKLLLLLLLLMMMMMMMMNNNNNNKKKKKKKLLLLLLLLMMMMMMMMNNNNNNKKKKKKKLLLLLLLLMMMMMMMMNNNNNNKKKKKKKLLLLLLLMMMMMMMMMNNNNNNKKKKKKKLLLLLLLMMMMMMMMMNNNNNNKKKKKKLLLLLLLMMMMMMMMMNNNNNNKKKKKKLLLLLLLMMMMMMMMMNNNNNNKKKKKKLLLLLLLMMMMMMMMMNNNNNN^^vKKKKKKLLLLLLMMMMMMMMMMNNNNNN^^^^vܞKKKKKKLLLLLLMMMMMMMMMMNNNNNN^^^^wwKKKKKLLLLLLMMMMMMMMMMNNNNNN^^^_wwwKKKKLLLLLLMMMMMMMMMMNNNNNN^^__wwwwKKLLLLLMMMMMMMMMMMNNNNNN^___wwwwwKLLLLLMMMMMMMMMMMNNNNNN____wwwxxxLLLLLMMMMMMMMMMMNNNNNN---.__```xxxxxxBBBBMMMMMMMMMMMNNNNN,,------....//_````xxxxxxxBBBBMMMMMMMMMNNNN,,,------......./////`````xxxxxxxxxBBBMMMMMMMNNN,,,,------........//////`````xxxxxxxxyBMMMMMNN,,,,,------........//////``````xxxxxxyyyMM,,,,,,,------........///////``````xxxxyyyyyy,,,,,,------........///////00`````xxyyyyyyyy,,,,------........///////000`````yyyyyyyyyy,------........///////0000`````yyyyyyyyyyy-----........//////000000`````yyyyyyyyyyy----........//////0000000````yyyyyyyyyyyy-.........//////00000000````yyyyyyyyyyyy.......//////0000000001```yyyyyyyyyyyy...//////00000000011``yyyyyyyyyyyy/////0000000001111`yyyyyyyyyy//00000000011111yyyyyyyyyy000000000111111yyyyyyyy00000011111112yyyyy0000111111122yyyy01111111222yy1111112222211112222211122222122222222222222웛웛웛췛췷췷췷췷췷췷뷷뷷뷷뷷KKKKKKKKKKKKLLLLLLLLLKKKKKLLLLLLLLLMMMMMMMKKKKKLLLLLLLLLMMMMMMMNNNKKKKKLLLLLLLLLMMMMMMMNNNNKKKKKLLLLLLLLLMMMMMMMNNNNNKKKKKLLLLLLLLMMMMMMMMNNNNNNKKKKKLLLLLLLLMMMMMMMMNNNNNNNOKKKKKLLLLLLLLMMMMMMMMNNNNNNNOOKKKKLLLLLLLLMMMMMMMMNNNNNNNOOOKKKKLLLLLLLMMMMMMMMMNNNNNNNOOOKKKKLLLLLLLMMMMMMMMMNNNNNNNOOOKKKKLLLLLLLMMMMMMMMMNNNNNNNOOOKKKKLLLLLLLMMMMMMMMMNNNNNNNOOOKKKKLLLLLLLMMMMMMMMMNNNNNNNOOO۞KKKKLLLLLLMMMMMMMMMMNNNNNNNOOO^^ܞKKKKLLLLLLMMMMMMMMMMNNNNNNNOOO^^^wܟKKKLLLLLLMMMMMMMMMMNNNNNNNOOO^^wwwKKLLLLLLMMMMMMMMMMNNNNNNNOOO^__wwwKLLLLLMMMMMMMMMMMNNNNNNNOOO___wwwwLLLLLMMMMMMMMMMMNNNNNNNOOO__`wwxxxLLLMMMMMMMMMMMNNNNNNNOOO_```xxxxxLLMMMMMMMMMMMNNNNNNNOOO````xxxxxxLMMMMMMMMMMMNNNNNNNOO--..````xxxxxxxMMMMMMMMMMNNNNNNNO-----......//`````xxxxxxxyMMMMMMMMNNNNNNN------........//////`````xxxxxyyyMMMMMMMNNNNNN,------........///////0`````xxxyyyyyMMMMNNNNN,,------........///////00`````xyyyyyyyyNNNN,,,------........///////000`````yyyyyyyyy,,,,------........///////00000````yyyyyyyyyy,,------........///////000000```yyyyyyyyyyy------........//////00000000```yyyyyyyyyyyy----........//////000000001``yyyyyyyyyyyyy-.........//////00000000111`yyyyyyyyyyyyy.......//////000000000111`yyyyyyyyyyyyy...//////00000000011111yyyyyyyyyyyyy/////000000000111111yyyyyyyyyyy//0000000001111111yyyyyyyyyy0000000011111112yyyyyyyy0000001111111222yyyyy000011111112222yyyy0111111122222yy1111112222222111122222221122222222122222222222222222222웛웛웜윜윜췜췷췷췷췷췷췷KKKKKLLLLLLLLKKLLLLLLLLLMMMMMMKKLLLLLLLLLMMMMMMMNNNNNKKLLLLLLLLLMMMMMMMNNNNNNKKLLLLLLLLMMMMMMMMNNNNNNNKKLLLLLLLLMMMMMMMMNNNNNNNOKLLLLLLLLMMMMMMMMNNNNNNNOOOKLLLLLLLLMMMMMMMMNNNNNNNOOOOKLLLLLLLMMMMMMMMMNNNNNNNOOOOOKLLLLLLLMMMMMMMMMNNNNNNNOOOOOKLLLLLLLMMMMMMMMMNNNNNNNOOOOOLLLLLLLMMMMMMMMMNNNNNNNOOOOO۞LLLLLLLMMMMMMMMMNNNNNNNOOOOO۞LLLLLLMMMMMMMMMMNNNNNNNOOOOOܞLLLLLLMMMMMMMMMMNNNNNNNOOOOOwܞLLLLLLMMMMMMMMMMNNNNNNNOOOOOwwܟLLLLLMMMMMMMMMMNNNNNNNOOOOOwwwLLLLMMMMMMMMMMMNNNNNNNOOOOO__wwwLLLMMMMMMMMMMMNNNNNNNOOOOO_`wxxxLLMMMMMMMMMMMNNNNNNNOOOOO``xxxxxLMMMMMMMMMMMNNNNNNNOOOOO``xxxxxxMMMMMMMMMMMNNNNNNNOOOOO``xxxxxxxMMMMMMMMMNNNNNNNOOOOO.```xxxxxxxMMMMMMMMNNNNNNNOOOOO....```xxxxxxyyMMMMMMNNNNNNNOOOO--.......///```xxxxyyyyMMMMNNNNNNNOOO---........///////000````xyyyyyyyMMMNNNNNNNOO----........///////0000```yyyyyyyyyMNNNNNNNO-----........///////00000```yyyyyyyyyNNNNN------........///////0000000``yyyyyyyyyyN,------........///////00000001`yyyyyyyyyyy------........//////0000000011`yyyyyyyyyyyy----........//////000000001111yyyyyyyyyyyy-.........//////0000000011111yyyyyyyyyyyyy.......//////00000000111111yyyyyyyyyyyyy...//////000000000111111yyyyyyyyyyyyy/////0000000001111112yyyyyyyyyyyy//000000000111111222yyyyyyyyyy000000001111111222yyyyyyyy000000111111122222yyyyyy0001111111222222yyyy011111112222222yy111111222222222111122222222211222222222222222222222222222222222222웛웛웜윜윜윜췜췷췷췷췷LLLLLLLLLLLLLLMMMMMMLLLLLLLLMMMMMMMNNNNNLLLLLLMMMMMMMMNNNNNNNLLLLLLMMMMMMMMNNNNNNNOOLLLLLLMMMMMMMMNNNNNNNOOOLLLLLLMMMMMMMMNNNNNNNOOOOLLLLLMMMMMMMMMNNNNNNNOOOOOOLLLLLMMMMMMMMMNNNNNNNOOOOOOOLLLLLMMMMMMMMMNNNNNNNOOOOOOOOP۞LLLLMMMMMMMMMNNNNNNNOOOOOOOOP۞LLLLMMMMMMMMMNNNNNNNOOOOOOOOP۞LLLMMMMMMMMMMNNNNNNNOOOOOOOOP۞LLLMMMMMMMMMMNNNNNNNOOOOOOOOPܞLLLMMMMMMMMMMNNNNNNNOOOOOOOOPܟLLLMMMMMMMMMMNNNNNNNOOOOOOOOPܟLLMMMMMMMMMMMNNNNNNNOOOOOOOOPwܟLMMMMMMMMMMMNNNNNNNOOOOOOOOP`xxLMMMMMMMMMMMNNNNNNNOOOOOOOOP`xxxxMMMMMMMMMMMNNNNNNNOOOOOOOOP`xxxxxMMMMMMMMMMNNNNNNNOOOOOOOOP`xxxxxxMMMMMMMMNNNNNNNOOOOOOOOP``xxxxxxMMMMMMMNNNNNNNOOOOOOOOP``xxxxxyyMMMMMNNNNNNNOOOOOOOOP``xxxyyyyMMMNNNNNNNOOOOOOO....``xyyyyyyMMNNNNNNNOOOOOOO....../////00``yyyyyyyyNNNNNNNOOOOOO........///////00000``yyyyyyyyNNNNNNOOOOOO........///////00000001yyyyyyyyyyNNNNOOOOO-........///////000000011yyyyyyyyyyNNNOOO---........///////0000000111yyyyyyyyyyyOO----........//////000000001111yyyyyyyyyyy----........//////0000000011111yyyyyyyyyyy-.........//////00000000111111yyyyyyyyyyyy.......//////0000000011111112yyyyyyyyyyy...//////00000000111111122yyyyyyyyyyyy/////000000000111111222yyyyyyyyyyyy//00000000011111122222yyyyyyyyyy00000000111111222222yyyyyyyy0000001111111222222yyyyyyy000111111122222222yyyy01111111222222222yy1111112222222222y111122222222222122222222222222222222222222222222222222222222ٜٜٜٜٜ윜윜윜윜췜췷LLLLLLMMMMMLLLLMMMMMMMMNNNNLLLLMMMMMMMMNNNNNNNLLLMMMMMMMMNNNNNNNOOLLLMMMMMMMMNNNNNNNOOOOLLMMMMMMMMMNNNNNNNOOOOOOLLMMMMMMMMMNNNNNNNOOOOOOOOLLMMMMMMMMMNNNNNNNOOOOOOOOP۞LLMMMMMMMMMNNNNNNNOOOOOOOOPPP۞LLMMMMMMMMMNNNNNNNOOOOOOOOPPPP۞MMMMMMMMMMNNNNNNNOOOOOOOOPPPP۞MMMMMMMMMMNNNNNNNOOOOOOOOPPPPܞMMMMMMMMMMNNNNNNNOOOOOOOOPPPPܟMMMMMMMMMMNNNNNNNOOOOOOOOPPPPܟMMMMMMMMMMNNNNNNNOOOOOOOOPPPPܟMMMMMMMMMMNNNNNNNOOOOOOOOPPPPxܟMMMMMMMMMMNNNNNNNOOOOOOOOPPPPxxxMMMMMMMMMNNNNNNNOOOOOOOOPPPPxxxxMMMMMMMMNNNNNNNOOOOOOOOPPPPxxxxxMMMMMMMNNNNNNNOOOOOOOOPPPPxxxxxMMMMMMNNNNNNNOOOOOOOOPPPPxxxxyMMMMNNNNNNNOOOOOOOOPPPPxxyyyyMMMNNNNNNNOOOOOOOOPPPPyyyyyyMNNNNNNNOOOOOOOOPPPPyyyyyyyNNNNNNOOOOOOOOPPP.//yyyyyyyyNNNNNOOOOOOOOPP..../////00yyyyyyyyNNNNOOOOOOOO......///////00000011yyyyyyyyyNNOOOOOOO.......///////00000001111yyyyyyyyNOOOOOOO.......///////000000011111yyyyyyyyyOOOOO........//////00000000111111yyyyyyyyyOOOO........//////000000001111111yyyyyyyyyyO.........//////0000000011111112yyyyyyyyyy......//////000000001111111222yyyyyyyyy..//////0000000011111112222yyyyyyyyyy/////00000000111111122222yyyyyyyyyy//0000000001111112222222yyyyyyyyyy0000000011111122222222yyyyyyyy000000111111222222222yyyyyyy00011111112222222222yyyy0111111122222222222yyy1111112222222222221112222222222222122222222222222222222222222222222222222222222222ٜٜٜٜٜٜ윜윜윜윜휜휜휜LMMMMMMLMMMMMMMMNNNLMMMMMMMMNNNNNNNLMMMMMMMMNNNNNNNOOMMMMMMMMNNNNNNNOOOOMMMMMMMMNNNNNNNOOOOOO۝MMMMMMMMNNNNNNNOOOOOOOO۞MMMMMMMMNNNNNNNOOOOOOOOPPP۞MMMMMMMMNNNNNNNOOOOOOOOPPPPP۞MMMMMMMMNNNNNNNOOOOOOOOPPPPPP۞MMMMMMMMNNNNNNNOOOOOOOOPPPPPPܞMMMMMMMMNNNNNNNOOOOOOOOPPPPPPܟMMMMMMMMNNNNNNNOOOOOOOOPPPPPPܟMMMMMMMMNNNNNNNOOOOOOOOPPPPPPܟMMMMMMMMNNNNNNNOOOOOOOOPPPPPPܟMMMMMMMMNNNNNNNOOOOOOOOPPPPPPܟMMMMMMMMNNNNNNNOOOOOOOOPPPPPPxxxMMMMMMMNNNNNNNOOOOOOOOPPPPPPxxxxMMMMMMNNNNNNNOOOOOOOOPPPPPPxxxxMMMMMNNNNNNNOOOOOOOOPPPPPPxxxyMMMNNNNNNNOOOOOOOOPPPPPPxyyyyMMNNNNNNNOOOOOOOOPPPPPPyyyyyNNNNNNNOOOOOOOOPPPPPPyyyyyNNNNNNOOOOOOOOPPPPPPyyyyyyNNNNOOOOOOOOPPPPPPyyyyyyNNNOOOOOOOOPPPPPP//yyyyyyyNOOOOOOOOPPPPPP//////000011yyyyyyyOOOOOOOOPPPP..///////00000011111yyyyyyyyOOOOOOOPPP...///////0000000111111yyyyyyyyOOOOOP.....//////0000000011111122yyyyyyyOOO......//////00000000111111222yyyyyyyyO.......//////000000001111111222yyyyyyyy......//////00000000111111122222yyyyyyyy..//////000000001111111222222yyyyyyyy/////0000000011111112222222yyyyyyyyy//000000001111111222222222yyyyyyyy000000001111112222222222yyyyyyyy00000011111122222222222yyyyyyy000111111222222222222yyyy0111111122222222222yy1111122222222222211122222222222212222222222222222222222222222222222222222222222ٜٜٜٜٜٜٜٜ윜윜휜휜휝흝흝흝흝MMMMMMMMMNNNMMMMMMNNNNNNNMMMMMMNNNNNNNOOMMMMMMNNNNNNNOOOO۞MMMMMMNNNNNNNOOOOOO۞MMMMMMNNNNNNNOOOOOOOO۞MMMMMMNNNNNNNOOOOOOOOPPP۞MMMMMMNNNNNNNOOOOOOOOPPPPP۞MMMMMNNNNNNNOOOOOOOOPPPPPPP۞MMMMMNNNNNNNOOOOOOOOPPPPPPPPܟMMMMMNNNNNNNOOOOOOOOPPPPPPPPܟMMMMMNNNNNNNOOOOOOOOPPPPPPPPܟMMMMMNNNNNNNOOOOOOOOPPPPPPPPܟMMMMMNNNNNNNOOOOOOOOPPPPPPPPܟMMMMMNNNNNNNOOOOOOOOPPPPPPPPܠMMMMMNNNNNNNOOOOOOOOPPPPPPPPxxMMMMMNNNNNNNOOOOOOOOPPPPPPPPxxMMMMNNNNNNNOOOOOOOOPPPPPPPPxxMMNNNNNNNOOOOOOOOPPPPPPPPyyMNNNNNNNOOOOOOOOPPPPPPPPyyyNNNNNNOOOOOOOOPPPPPPPPyyyNNNNNOOOOOOOOPPPPPPPPyyyyNNNOOOOOOOOPPPPPPPPyyyyNNOOOOOOOOPPPPPPPPyyyyNOOOOOOOOPPPPPPPPyyyyyOOOOOOOPPPPPPPP//00yyyyyOOOOOOPPPPPPP//////0000011yyyyyyOOOOOPPPPPPP//////0000000111112yyyyyyOOOPPPPPP//////000000001111112222yyyyyyOPPPPP.//////0000000011111122222yyyyyyPPPP..//////00000000111111222222yyyyyy....//////0000000011111112222222yyyyyy..//////00000000111111122222222yyyyyy/////000000001111111222222222yyyyyyy//0000000011111112222222222yyyyyy0000000111111122222222222yyyyyy0000011111122222222222yyyyy000111111222222222222yy0111111222222222222111112222222222221112222222222221222222222222222222222222222222222222222222222ٜٜٜٜٜٜٜٜٜ윜휜휝흝흝흝흝흝흝흝MMMNNMMMNNNNNNN۝MMNNNNNNNOO۞MMNNNNNNNOOOO۞MMNNNNNNNOOOOOO۞MMNNNNNNNOOOOOOOO۞MMNNNNNNNOOOOOOOOPP۞MMNNNNNNNOOOOOOOOPPPPP۞MMNNNNNNNOOOOOOOOPPPPPPPܟMMNNNNNNNOOOOOOOOPPPPPPPPPPܟMMNNNNNNNOOOOOOOOPPPPPPPPPPܟMNNNNNNNOOOOOOOOPPPPPPPPPPܟMNNNNNNNOOOOOOOOPPPPPPPPPPܟMNNNNNNNOOOOOOOOPPPPPPPPPPܟMNNNNNNNOOOOOOOOPPPPPPPPPPܠMNNNNNNNOOOOOOOOPPPPPPPPPPܠMNNNNNNNOOOOOOOOPPPPPPPPPPݠMNNNNNNNOOOOOOOOPPPPPPPPPPNNNNNNNOOOOOOOOPPPPPPPPPPyNNNNNOOOOOOOOPPPPPPPPPPyNNNNOOOOOOOOPPPPPPPPPPyNNNOOOOOOOOPPPPPPPPPPyyNOOOOOOOOPPPPPPPPPPyyOOOOOOOOPPPPPPPPPPyyyOOOOOOOPPPPPPPPPPyyyOOOOOPPPPPPPPPPyyyyOOOOPPPPPPPPP//00yyyyOOOPPPPPPPPP////00000011112yyyyOPPPPPPPP////0000000011111122222yyyyPPPPPPP////00000000111111222222yyyyPPPPP/////0000000011111122222222yyyyyPPP/////00000000111111222222222yyyy//////000000001111111222222222yyyy////000000001111111222222222yyyy/0000000011111112222222222yyy000000011111112222222222yy000011111112222222222200011111122222222222111111222222222222111122222222222211122222222222212222222222222222222222222222222222222222222ٝٝٝٝٝٝٝٝٝٝٝ흝흝흝흝흝흝흝흝흝۝NNNNN۞NNNNNNO۞NNNNNNOOOO۞NNNNNNOOOOOO۞NNNNNNOOOOOOOO۞NNNNNNOOOOOOOOPP۞NNNNNNOOOOOOOOPPPPP۟NNNNNNOOOOOOOOPPPPPPPܟNNNNNNOOOOOOOOPPPPPPPPPPܟNNNNNNOOOOOOOOPPPPPPPPPPPܟNNNNNNOOOOOOOOPPPPPPPPPPPܟNNNNNNOOOOOOOOPPPPPPPPPPPܟNNNNNOOOOOOOOPPPPPPPPPPPܠNNNNNOOOOOOOOPPPPPPPPPPPܠNNNNNOOOOOOOOPPPPPPPPPPPܠNNNNNOOOOOOOOPPPPPPPPPPPݠNNNNNOOOOOOOOPPPPPPPPPPPNNNNNOOOOOOOOPPPPPPPPPPPNNNOOOOOOOOPPPPPPPPPPPNNOOOOOOOOPPPPPPPPPPPyOOOOOOOOPPPPPPPPPPPOOOOOOOPPPPPPPPPPPOOOOOOPPPPPPPPPPPyOOOOOPPPPPPPPPPPyOOOOPPPPPPPPPPPyyOOPPPPPPPPPPPyyOPPPPPPPPPPP000011yyPPPPPPPPP//000000011111222yyPPPPPPP//0000000011111122222yyPPPPP///000000001111112222222yyPPP///0000000011111122222222y////00000000111111222222222y///000000001111111222222222/00000000111111122222222200000001111111222222222200001111111222222222200111111122222222222111111222222222221111222222222222112222222222221222222222222222222222222222222222 22222222 ٝٝٝٝٝٝٝٝٝٝٝڝڝڝڝڝڝڝڝ۞۞NNN۞NNNOO۞NNNOOOO۞NNNOOOOOO۞NNOOOOOOOOO۞NNOOOOOOOOOPP۟NNOOOOOOOOOPPPPܟNNOOOOOOOOOPPPPPPPܟNNOOOOOOOOOPPPPPPPPPPܟNNOOOOOOOOOPPPPPPPPPPPPܟNNOOOOOOOOOPPPPPPPPPPPPܟNNOOOOOOOOOPPPPPPPPPPPPܠNNOOOOOOOOOPPPPPPPPPPPPܠNNOOOOOOOOOPPPPPPPPPPPPܠNNOOOOOOOOOPPPPPPPPPPPPܠNNOOOOOOOOOPPPPPPPPPPPPݠNOOOOOOOOOPPPPPPPPPPPPݠNOOOOOOOOOPPPPPPPPPPPPOOOOOOOOOPPPPPPPPPPPPOOOOOOOOPPPPPPPPPPPPOOOOOOOPPPPPPPPPPPPOOOOOPPPPPPPPPPPPOOOOPPPPPPPPPPPPOOOPPPPPPPPPPPPOOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP00PPPPPPPPP000001112PPPPPPP0000000111111122222PPPPP/00000000111111222222PPP/000000001111112222222P//00000000111111222222222/0000000011111122222222220000000011111112222222220000000111111122222222220000111111122222222220011111112222222222211111122222222222111122222222222211222222222222222222222222222222222222 2222222222 22222222 ٝٝٝٝٝٝٝٝٝڝڝڝڝڝڝڝڝڝ۞۞۞۞OO۞OOOO۞OOOOOO۟OOOOOOO۟OOOOOOOOPP۟OOOOOOOOPPPPܟOOOOOOOOPPPPPPPܟOOOOOOOOPPPPPPPPPܟOOOOOOOOPPPPPPPPPPPܟOOOOOOOOPPPPPPPPPPPPPܠOOOOOOOOPPPPPPPPPPPPPPܠOOOOOOOOPPPPPPPPPPPPPPܠOOOOOOOOPPPPPPPPPPPPPPܠOOOOOOOPPPPPPPPPPPPPPݠOOOOOOOPPPPPPPPPPPPPPݠOOOOOOOPPPPPPPPPPPPPPݡOOOOOOOPPPPPPPPPPPPPPOOOOOOOPPPPPPPPPPPPPPOOOOOOPPPPPPPPPPPPPPOOOOOPPPPPPPPPPPPPPOOOPPPPPPPPPPPPPPOOPPPPPPPPPPPPPPOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP00PPPPPP0000001111222PPPPP000000111111122222PP000000001111112222222P0000000011111122222222000000011111122222222200000011111122222222220000011111112222222220001111111222222222200111111122222222221111112222222222211112222222222211222222222222222222222222 22222222222 222222222 22222222 ٝٝٝٝٝٝٝٝڝڝڝڝڝڝڝڞڞ۞۞۞۞۞۞۟OO۟OOOO۟OOOOOPP۟OOOOOPPPPܟOOOOOPPPPPPPܟOOOOOPPPPPPPPPܟOOOOOPPPPPPPPPPPܠOOOOOPPPPPPPPPPPPPܠOOOOOPPPPPPPPPPPPPPܠOOOOPPPPPPPPPPPPPPPܠOOOOPPPPPPPPPPPPPPPܠOOOOPPPPPPPPPPPPPPPݠOOOOPPPPPPPPPPPPPPPݠOOOOPPPPPPPPPPPPPPPݡOOOOPPPPPPPPPPPPPPPݡOOOOPPPPPPPPPPPPPPPOOOOPPPPPPPPPPPPPPPOOOPPPPPPPPPPPPPPPOPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP000112PPPP000001111112222PP0000011111112222220000000111111222222200000011111122222222200001111112222222222000111111222222222201111111222222222211111112222222222111112222222222211112222222222211222222222222 222222222222 22222222222 222222222 22222222 ٝٝٝٝٝٝڝڝڝڝڝڞڞڞڞڞ۞۞۞۞۞۟۟۟۟O۟OOPܟOOPPPPܟOOPPPPPPܟOOPPPPPPPPPܠOOPPPPPPPPPPPܠOPPPPPPPPPPPPPܠOPPPPPPPPPPPPPPܠOPPPPPPPPPPPPPPPܠOPPPPPPPPPPPPPPPPܠOPPPPPPPPPPPPPPPPݠOPPPPPPPPPPPPPPPPݡOPPPPPPPPPPPPPPPPݡOPPPPPPPPPPPPPPPPݡOPPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP0001111222P0000111111122222000011111112222220000111111222222220001111112222222220111111222222222211111222222222211111222222222211122222222221122222222222 122222222222 22222222222 2222222222 222222222 2222222 ٝٝٝٝڝڝڝڝڝڞڞڞڞڞڞڞ۞۞۞۞۟۟۟۟۟۟ܟPPPܟPPPPPܠPPPPPPPPܠPPPPPPPPPPܠPPPPPPPPPPPPܠPPPPPPPPPPPPPܠPPPPPPPPPPPPPPܠPPPPPPPPPPPPPPܠPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPݡPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP112P00011111222001111111222222011111112222222011111122222222111112222222222111122222222221122222222222112222222222 22222222222 2222222222 2222222222 22222222 22222222 222222 ٝٝڝڝڝڝڞڞڞڞڞڞڞڞڞ۞۞۞۞۟۟۟۟۟۟ܟܟܠPPܠPPPPܠPPPPPPPܠPPPPPPPPܠPPPPPPPPPPܠPPPPPPPPPPܠPPPPPPPPPPPݠPPPPPPPPPPPPݡPPPPPPPPPPPPݡPPPPPPPPPPPPݡPPPPPPPPPPPPݡPPPPPPPPPPPPݡPPPPPPPPPPPݡPPPPPPPPPPPݢPPPPPPPPPPPݢPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP1121111112222211111122222211111222222221112222222221122222222222222222222 2222222222 222222222 22222222 2222222 2222222 22222 22222 ٝڝڝڞڞڞڞڞڞڞڞڞڞڞڞ۞۞۟۟۟۟۟۟۟۟ܟܟܠܠܠPPPܠPPPܠPPPPPܠPPPPPPܠPPPPPPPݡPPPPPPPPPݡPPPPPPPPPݡPPPPPPPPPݡPPPPPPPPݡPPPPPPPPݡPPPPPPPPݢPPPPPPPPﹹݢPPPPPPPPﹹݢPPPPPPPPޢPPPPPPPPޢPPPPPPPPPPPPPPPPPPPPPPPPP1111222111112222211122222221122222222222222222 222222222 2222222 2222222 222222 22222 2222 2222 22 ڞڞڞڞڞڞڞڞڞڞڞڞڞڞ۞۞۟۟۟۟۟۟۟۟۟ܟܠܠܠܠܠܠPܠPPܠPPPݡPPPPPݡPPPPPݡPPPPPݡPPPPPݡPPPPPﹹݡPPPPPﹹݢPPPPPﹹݢPPPPPﹹݢPPPPﹹޢPPPPﹹޢPPPPﹹޢPPPPPPPPPPPP12112222212222222222222 22222222 2222222 222222 22222 2222 2222 22 22 2 ڞڞڞڞڞڞڞڞڞڞڞڞڞڞ۞۟۟۟۟۟۟۟۟۟ܟܠܠܠܠܠܠܠܠܡݡݡݡݡݡݡݢݢݢޢޢޢޣޣޣޣ22222222 22222 22222 22222 2222 222 22 2 2   ڞڞڞڞڞڞڞڞڞڞڞڞڞ۟۟۟۟۟۟۟۟۟۟۟ܠܠܠܠܠܠܠܠܡݡݡݡݡݡݡݢݢݢݢޢޢޢޣޣޣޣޣ2 22 222 22 222 222 2 2     ڞڞڞڞڞڞڞڞڞڞڟڟڟ۟۟۟۟۟۟۟۟۟۠۠ܠܠܠܠܠܠܠܡܡݡݡݡݡݡݢݢݢݢޢޢޢޣޣޣޣޣޣߣ             ڞڞڞڞڞڞڟڟڟڟ۟۟۟۟۟۟۟۟۟۠۠ܠܠܠܠܠܠܠܡܡܡݡݡݡݡݡݢݢݢݢޢޢޢޣޣޣޣޣޣ ߣ ߣ            ڞڞڟڟڟڟڟڟڟڟ۟۟۟۟۟۟۟۠۠۠۠ܠܠܠܠܠܠܡܡܡܡݡݡݡݡݢݢݢݢݢޢޢޣޣޣޣޣޣޣ ߣ ߣ            ڟڟڟڟڟڟڟڟ۟۟۟۟۟۟۠۠۠۠۠ܠܠܠܠܠܠܡܡܡܡݡݡݡݡݢݢݢݢݢޢޢޣޣޣޣޣޣޣ ߣ ߣ ߣ           ڟڟڟڟڟڟڟ۟۟۟۟۟۠۠۠۠۠۠ܠܠܠܠܠܠܡܡܡܡܡݡݡݡݢݢݢݢݢݢޢޢޣޣޣޣޣޣޣ ߣ ߣ ߣ           ڟڟڟڟڟڟڟڟ۟۟۟۟۟۠۠۠۠۠۠ܠܠܠܠܠܡܡܡܡܡݡݡݡݢݢݢݢݢݢݢޢޣޣޣޣޣޣޣޣߣ ߣ ߣ ߣ          ڟڟڟڟڟڟ۟۟۟۟۠۠۠۠۠۠۠۠ܠܠܠܠܡܡܡܡܡܡݡݡݡݢݢݢݢݢݢݢޢޣޣޣޣޣޣޣޣߣ ߣ ߣ ߣ          ڟڟڟڟڟڟ۟۟۟۠۠۠۠۠۠۠۠۠ܠܠܠܡܡܡܡܡܡܡݡݡݡݢݢݢݢݢݢޢޣޣޣޣޣޣޣޣޣߣ ߣ ߣ ߣ ߣ         deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/wpiecem3.lmp0000644000175000017500000000046211357170242024330 0ustar keeskeesdnx&/01 bfc bgc cfb bdb cfb bfc bdc bdb bfc cgb cfd bdfa acdb bdb bdb bfb $# %M$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmc1.lmp0000644000175000017500000000220511357170242024300 0ustar keeskeesV`ir| (06>FNW`ju)3=GPZep{#-7AKU_is|  ""$$&&$$"" $#####&&$$%%##""$$ &####""""&####  &####  &####   ####   %%# &  ## $# $#&( ##  ##""%#%%ٙۡܝݜޛݡٙ#""%% #####&( # $## $ & #  %%  ####   ####&  ####&  ####&""""####&$$ ##""%%##&&$$#"" $##$$&&$$ "" deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot2.lmp0000644000175000017500000000045511357170242024372 0ustar keeskeesTUVWXYft()*+,ffddddbdzz ddSRRRbizddRb{h{gzbbbbbcbccbbbbddSzagchRggRgRiRRbccSbjzchiggigiiiRiSbccR{jbzhzbbbbbbbizbS{ccRchgiizRzR{aaccccczaaaadeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/lifegmf6.lmp0000644000175000017500000000225411357170242024314 0ustar keeskeesV`jw #-7?GOW_gms{(4@LXcmu} &0=GQ[cmw  %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##""$$$  ""%##  ## $#'+)%!/--,)-1+%,*+1)$,--"  ##"##%""  ""$%$$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""%%##$##"%   %%"%%$#$$$$ ""deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot6.lmp0000644000175000017500000000056111357170242024374 0ustar keeskeesTU\enw#<T^gop ""#$55##   ##  7" - $ $   -% ##+$$  5  $ 75      54  $ 55#$ 65  ""%5 #deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/data/lumps/keyslot8.lmp0000644000175000017500000000054011357170242024373 0ustar keeskeesTUVWXYl (BP]^_$$ %$""  % '%%$ 'z{#$$ VYXT T##V{ %''VUUUUUT$ Q z "||U|}|U~|Vz VzU}%| WWV$%VU| WW%V '' {zdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/0000755000175000017500000000000011357170242020616 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/hrefresh.c0000644000175000017500000003551411357170242022600 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hrefresh.h: - jHexen specific. */ // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "f_infine.h" #include "r_common.h" #include "p_mapsetup.h" #include "g_controls.h" #include "g_common.h" #include "hu_menu.h" #include "hu_msg.h" #include "hu_pspr.h" #include "am_map.h" #include "x_hair.h" #include "p_tick.h" #include "rend_automap.h" // MACROS ------------------------------------------------------------------ #define WINDOWHEIGHT (Get(DD_VIEWWINDOW_HEIGHT)) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern void MN_DrCenterTextA_CS(char *text, int center_x, int y); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- boolean setsizeneeded; float quitDarkenOpacity = 0; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Don't really change anything here, because i might be in the middle of * a refresh. The change will take effect next refresh. */ void R_SetViewSize(int blocks) { setsizeneeded = true; if(cfg.setBlocks != blocks && blocks > 10 && blocks < 13) { // When going fullscreen, force a hud show event (to reset the timer). int i; for(i = 0; i < MAXPLAYERS; ++i) ST_HUDUnHide(i, HUE_FORCE); } cfg.setBlocks = blocks; } void R_DrawMapTitle(void) { float alpha; int y = 12; const char* lname, *lauthor; if(!cfg.mapTitle || actualMapTime > 6 * 35) return; // Make the text a bit smaller. DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(160, y, 0); DGL_Scalef(.75f, .75f, 1); // Scale to 3/4 DGL_Translatef(-160, -y, 0); alpha = 1; if(actualMapTime < 35) alpha = actualMapTime / 35.0f; if(actualMapTime > 5 * 35) alpha = 1 - (actualMapTime - 5 * 35) / 35.0f; lname = P_GetMapNiceName(); lauthor = P_GetMapAuthor(cfg.hideIWADAuthor); // Use stardard map name if DED didn't define it. if(!lname) lname = P_GetMapName(gameMap); Draw_BeginZoom((1 + cfg.hudScale)/2, 160, y); if(lname) { M_WriteText3(160 - M_StringWidth(lname, GF_FONTB) / 2, y, lname, GF_FONTB, defFontRGB[0], defFontRGB[1], defFontRGB[2], alpha, false, true, 0); y += 20; } if(lauthor) { M_WriteText3(160 - M_StringWidth(lauthor, GF_FONTA) / 2, y, lauthor, GF_FONTA, .5f, .5f, .5f, alpha, false, true, 0); } Draw_EndZoom(); DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } static void rendPlayerView(int player) { player_t* plr = &players[player]; boolean special200 = false; float viewPos[3], viewPitch, pspriteOffsetY; angle_t viewAngle; if(IS_CLIENT) { // Server updates mobj flags in NetSv_Ticker. R_SetAllDoomsdayFlags(); } // Check for the sector special 200: use sky2. // I wonder where this is used? if(P_ToXSectorOfSubsector(plr->plr->mo->subsector)->special == 200) { special200 = true; Rend_SkyParams(0, DD_DISABLE, NULL); Rend_SkyParams(1, DD_ENABLE, NULL); } // How about a bit of quake? if(localQuakeHappening[player] && !P_IsPaused()) { int intensity = localQuakeHappening[player]; plr->viewOffset[VX] = (float) ((M_Random() % (intensity << 2)) - (intensity << 1)); plr->viewOffset[VY] = (float) ((M_Random() % (intensity << 2)) - (intensity << 1)); } else { plr->viewOffset[VX] = plr->viewOffset[VY] = 0; } viewPos[VX] = plr->plr->mo->pos[VX] + plr->viewOffset[VX]; viewPos[VY] = plr->plr->mo->pos[VY] + plr->viewOffset[VY]; viewPos[VZ] = plr->viewZ + plr->viewOffset[VZ]; viewAngle = plr->plr->mo->angle + (int) (ANGLE_MAX * -G_GetLookOffset(player)); viewPitch = plr->plr->lookDir; DD_SetVariable(DD_VIEW_X, &viewPos[VX]); DD_SetVariable(DD_VIEW_Y, &viewPos[VY]); DD_SetVariable(DD_VIEW_Z, &viewPos[VZ]); DD_SetVariable(DD_VIEW_ANGLE, &viewAngle); DD_SetVariable(DD_VIEW_PITCH, &viewPitch); pspriteOffsetY = HU_PSpriteYOffset(plr); DD_SetVariable(DD_PSPRITE_OFFSET_Y, &pspriteOffsetY); // $democam GL_SetFilter((plr->plr->flags & DDPF_VIEW_FILTER)? true : false); if(plr->plr->flags & DDPF_VIEW_FILTER) { const float* color = plr->plr->filterColor; GL_SetFilterColor(color[CR], color[CG], color[CB], color[CA]); } // Render the view with possible custom filters. R_RenderPlayerView(player); if(special200) { Rend_SkyParams(0, DD_ENABLE, NULL); Rend_SkyParams(1, DD_DISABLE, NULL); } } static void rendHUD(int player) { player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; if(G_GetGameState() != GS_MAP) return; if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; plr = &players[player]; // These various HUD's will be drawn unless Doomsday advises not to if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { automapid_t map = AM_MapForPlayer(player); // Draw HUD displays only visible when the automap is open. if(AM_IsActive(map)) HU_DrawMapCounters(); // Do we need to render a full status bar at this point? if(!(AM_IsActive(map) && cfg.automapHudDisplay == 0) && !(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { if(true == (WINDOWHEIGHT == 200)) { // Fullscreen. Which mode? ST_Drawer(player, cfg.setBlocks - 10, true); } else { ST_Drawer(player, 0, true); } } HU_Drawer(player); } } /** * Draws the in-viewport display. * * @param layer @c 0 = bottom layer (before the viewport border). * @c 1 = top layer (after the viewport border). */ void G_Display(int layer) { int player = DISPLAYPLAYER; player_t* plr = &players[player]; float x, y, w, h; if(layer != 0) { rendHUD(player); return; } if(G_GetGameState() == GS_MAP) { // $democam: can be set on every frame. if(cfg.setBlocks > 10 || (P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) { // Full screen. R_SetViewWindowTarget(0, 0, SCREENWIDTH, SCREENHEIGHT); } else { int w = cfg.setBlocks * 32; int h = cfg.setBlocks * (SCREENHEIGHT - SBARHEIGHT * cfg.statusbarScale / 20) / 10; R_SetViewWindowTarget(SCREENWIDTH/2 - w/2, (SCREENHEIGHT - SBARHEIGHT * cfg.statusbarScale / 20 - h) / 2, w, h); } R_GetViewWindow(&x, &y, &w, &h); } else { x = 0; y = 0; w = SCREENWIDTH; h = SCREENHEIGHT; } R_SetViewWindow((int) x, (int) y, (int) w, (int) h); switch(G_GetGameState()) { case GS_MAP: if(!(MN_CurrentMenuHasBackground() && Hu_MenuAlpha() >= 1) && !R_MapObscures(player, (int) x, (int) y, (int) w, (int) h)) { if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; rendPlayerView(player); // Crosshair. if(!(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) // $democam X_Drawer(player); } // Draw the automap. AM_Drawer(player); break; case GS_STARTUP: DGL_Disable(DGL_TEXTURING); DGL_DrawRect(x, y, w, h, 0, 0, 0, 1); DGL_Enable(DGL_TEXTURING); break; default: break; } } void G_Display2(void) { switch(G_GetGameState()) { case GS_MAP: if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) break; if(DD_GetInteger(DD_GAME_DRAW_HUD_HINT)) { // Map information is shown for a few seconds in the // beginning of a map. R_DrawMapTitle(); } break; case GS_INTERMISSION: IN_Drawer(); break; case GS_WAITING: //GL_DrawRawScreen(W_GetNumForName("TITLE"), 0, 0); //DGL_Color3f(1, 1, 1); //MN_DrCenterTextA_CS("WAITING... PRESS ESC FOR MENU", 160, 188); break; default: break; } // Draw pause pic (but not if InFine active). if(paused && !fiActive) { GL_DrawPatch(SCREENWIDTH/2, 4, W_GetNumForName("PAUSED")); } // InFine is drawn whenever active. FI_Drawer(); // Draw HUD displays; menu, messages. Hu_Drawer(); if(G_GetGameAction() == GA_QUIT) { DGL_Disable(DGL_TEXTURING); DGL_DrawRect(0, 0, 320, 200, 0, 0, 0, quitDarkenOpacity); DGL_Enable(DGL_TEXTURING); } } boolean R_GetFilterColor(float rgba[4], int filter) { if(!rgba) return false; // We have to choose the right color and alpha. if(filter >= STARTREDPALS && filter < STARTREDPALS + NUMREDPALS) { // Red. rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; rgba[CA] = (deathmatch? 1.0f : cfg.filterStrength) * filter / 8.f; // Full red with filter 8. return true; } else if(filter >= STARTBONUSPALS && filter < STARTBONUSPALS + NUMBONUSPALS) { // Light Yellow. rgba[CR] = 1; rgba[CG] = 1; rgba[CB] = .5f; rgba[CA] = cfg.filterStrength * (filter - STARTBONUSPALS + 1) / 16.f; return true; } else if(filter >= STARTPOISONPALS && filter < STARTPOISONPALS + NUMPOISONPALS) { // Green. rgba[CR] = 0; rgba[CG] = 1; rgba[CB] = 0; rgba[CA] = cfg.filterStrength * (filter - STARTPOISONPALS + 1) / 16.f; return true; } else if(filter >= STARTSCOURGEPAL) { // Orange. rgba[CR] = 1; rgba[CG] = .5f; rgba[CB] = 0; rgba[CA] = cfg.filterStrength * (STARTSCOURGEPAL + 3 - filter) / 6.f; return true; } else if(filter >= STARTHOLYPAL) { // White. rgba[CR] = 1; rgba[CG] = 1; rgba[CB] = 1; rgba[CA] = cfg.filterStrength * (STARTHOLYPAL + 3 - filter) / 6.f; return true; } else if(filter == STARTICEPAL) { // Light blue. rgba[CR] = .5f; rgba[CG] = .5f; rgba[CB] = 1; rgba[CA] = cfg.filterStrength * .4f; return true; } if(filter) Con_Error("R_GetFilterColor: Strange filter number: %d.\n", filter); return false; } /** * Updates ddflags of all visible mobjs (in sectorlinks). * Not strictly necessary (in single player games at least) but here * we tell the engine about light-emitting objects, special effects, * object properties (solid, local, low/nograv, etc.), color translation * and other interesting little details. */ void R_SetAllDoomsdayFlags(void) { uint i; mobj_t* mo; // Only visible things are in the sector thinglists, so this is good. for(i = 0; i < numsectors; ++i) for(mo = P_GetPtr(DMU_SECTOR, i, DMT_MOBJS); mo; mo = mo->sNext) { if(IS_CLIENT && mo->ddFlags & DDMF_REMOTE) continue; // Reset the flags for a new frame. mo->ddFlags &= DDMF_CLEAR_MASK; if(mo->flags & MF_LOCAL) mo->ddFlags |= DDMF_LOCAL; if(mo->flags & MF_SOLID) mo->ddFlags |= DDMF_SOLID; if(mo->flags & MF_MISSILE) mo->ddFlags |= DDMF_MISSILE; if(mo->flags2 & MF2_FLY) mo->ddFlags |= DDMF_FLY | DDMF_NOGRAVITY; if(mo->flags2 & MF2_FLOATBOB) mo->ddFlags |= DDMF_BOB | DDMF_NOGRAVITY; if(mo->flags2 & MF2_LOGRAV) mo->ddFlags |= DDMF_LOWGRAVITY; if(mo->flags & MF_NOGRAVITY /* || mo->flags2 & MF2_FLY */ ) mo->ddFlags |= DDMF_NOGRAVITY; // $democam: cameramen are invisible. if(P_MobjIsCamera(mo)) mo->ddFlags |= DDMF_DONTDRAW; // Choose which ddflags to set. if(mo->flags2 & MF2_DONTDRAW) { mo->ddFlags |= DDMF_DONTDRAW; continue; // No point in checking the other flags. } if((mo->flags & MF_BRIGHTSHADOW) == MF_BRIGHTSHADOW) mo->ddFlags |= DDMF_BRIGHTSHADOW; else { if(mo->flags & MF_SHADOW) mo->ddFlags |= DDMF_SHADOW; if(mo->flags & MF_ALTSHADOW || (cfg.translucentIceCorpse && mo->flags & MF_ICECORPSE)) mo->ddFlags |= DDMF_ALTSHADOW; } if((mo->flags & MF_VIEWALIGN && !(mo->flags & MF_MISSILE)) || mo->flags & MF_FLOAT || (mo->flags & MF_MISSILE && !(mo->flags & MF_VIEWALIGN))) mo->ddFlags |= DDMF_VIEWALIGN; R_SetTranslation(mo); // An offset for the light emitted by this object. /* Class = MobjLightOffsets[mo->type]; if(Class < 0) Class = 8-Class; // Class must now be in range 0-15. mo->ddFlags |= Class << DDMF_LIGHTOFFSETSHIFT; */ // The Mage's ice shards need to be a bit smaller. // This'll make them half the normal size. if(mo->type == MT_SHARDFX1) mo->ddFlags |= 2 << DDMF_LIGHTSCALESHIFT; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/h2_main.c0000644000175000017500000004061111357170242022301 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h2_main.c: Hexen specifc Initialization. */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include #include #include "jhexen.h" #include "hu_log.h" #include "hu_menu.h" #include "hu_msg.h" #include "d_net.h" #include "g_update.h" #include "g_common.h" #include "p_mapspec.h" #include "am_map.h" #include "p_switch.h" #include "p_player.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct execopt_s { char* name; void (*func) (const char** args, int tag); int requiredArgs; int tag; } execopt_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- extern void X_CreateLUTs(void); extern void X_DestroyLUTs(void); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void handleArgs(); static void execOptionScripts(const char** args, int tag); static void execOptionDevMaps(const char** args, int tag); static void execOptionSkill(const char** args, int tag); static void execOptionPlayDemo(const char** args, int tag); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int verbose; boolean DevMaps; // true = map development mode. char* DevMapsDir = ""; // Development maps directory. boolean noMonstersParm; // checkparm of -nomonsters boolean respawnParm; // checkparm of -respawn boolean turboParm; // checkparm of -turbo boolean randomClassParm; // checkparm of -randclass boolean devParm; // checkparm of -devparm float turboMul; // Multiplier for turbo. boolean netCheatParm; // Allow cheating in netgames (-netcheat) skillmode_t startSkill; int startEpisode; int startMap; gamemode_t gameMode; int gameModeBits; // This is returned in D_Get(DD_GAME_MODE), max 16 chars. char gameModeString[17]; // Default font colours. const float defFontRGB[] = { .9f, 0.0f, 0.0f}; const float defFontRGB2[] = { .9f, .9f, .9f}; // Network games parameters. boolean autoStart; FILE *debugFile; char *borderLumps[] = { "F_022", // Background. "bordt", // Top. "bordr", // Right. "bordb", // Bottom. "bordl", // Left. "bordtl", // Top left. "bordtr", // Top right. "bordbr", // Bottom right. "bordbl" // Bottom left. }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int warpMap; static execopt_t execOptions[] = { {"-scripts", execOptionScripts, 1, 0}, {"-devmaps", execOptionDevMaps, 1, 0}, {"-skill", execOptionSkill, 1, 0}, {"-playdemo", execOptionPlayDemo, 1, 0}, {"-timedemo", execOptionPlayDemo, 1, 0}, {NULL, NULL, 0, 0} // Terminator. }; // CODE -------------------------------------------------------------------- /** * Attempt to change the current game mode. Can only be done when not * actually in a map. * * \todo Doesn't actually do anything yet other than set the game mode * global vars. * * @param mode The game mode to change to. * * @return @c true, if we changed game modes successfully. */ boolean G_SetGameMode(gamemode_t mode) { gameMode = mode; if(G_GetGameState() == GS_MAP) return false; switch(mode) { case shareware: // Shareware (4-map demo) gameModeBits = GM_SHAREWARE; break; case registered: // HEXEN registered gameModeBits = GM_REGISTERED; break; case extended: // Deathkings gameModeBits = GM_REGISTERED|GM_EXTENDED; break; case indetermined: // Well, no IWAD found. gameModeBits = GM_INDETERMINED; break; default: Con_Error("G_SetGameMode: Unknown gamemode %i", mode); } return true; } /** * Set the game mode string. */ void G_IdentifyVersion(void) { // Determine the game mode. Assume demo mode. strcpy(gameModeString, "hexen-demo"); G_SetGameMode(shareware); if(W_CheckNumForName("MAP05") >= 0) { // Normal Hexen. strcpy(gameModeString, "hexen"); G_SetGameMode(registered); } // This is not a very accurate test... if(W_CheckNumForName("MAP59") >= 0 && W_CheckNumForName("MAP60") >= 0) { // It must be Deathkings! strcpy(gameModeString, "hexen-dk"); G_SetGameMode(extended); } } /** * Check which known IWADs are found. The purpose of this routine is to * find out which IWADs the user lets us to know about, but we don't * decide which one gets loaded or even see if the WADs are actually * there. The default location for IWADs is Data\GAMENAMETEXT\. */ void G_DetectIWADs(void) { // The startup WADs. DD_AddIWAD("}data\\jhexen\\hexen.wad"); DD_AddIWAD("}data\\hexen.wad"); DD_AddIWAD("}hexen.wad"); DD_AddIWAD("hexen.wad"); } /** * Pre Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PreInit(void) { int i; // Calculate the various LUTs used by the playsim. X_CreateLUTs(); G_SetGameMode(indetermined); // Config defaults. The real settings are read from the .cfg files // but these will be used no such files are found. memset(&cfg, 0, sizeof(cfg)); cfg.playerMoveSpeed = 1; cfg.statusbarScale = 20; cfg.dclickUse = false; cfg.screenBlocks = cfg.setBlocks = 10; cfg.hudShown[HUD_MANA] = true; cfg.hudShown[HUD_HEALTH] = true; cfg.hudShown[HUD_CURRENTITEM] = true; for(i = 0; i < NUMHUDUNHIDEEVENTS; ++i) // When the hud/statusbar unhides. cfg.hudUnHide[i] = 1; cfg.lookSpeed = 3; cfg.turnSpeed = 1; cfg.xhairSize = .5f; cfg.xhairVitality = false; cfg.xhairColor[0] = 1; cfg.xhairColor[1] = 1; cfg.xhairColor[2] = 1; cfg.xhairColor[3] = 1; cfg.filterStrength = .8f; cfg.jumpEnabled = cfg.netJumping = true; // true by default in Hexen cfg.jumpPower = 9; cfg.airborneMovement = 1; cfg.weaponAutoSwitch = 1; // IF BETTER cfg.noWeaponAutoSwitchIfFiring = false; cfg.ammoAutoSwitch = 0; // never cfg.fastMonsters = false; cfg.netMap = 0; cfg.netSkill = SM_MEDIUM; cfg.netColor = 8; // Use the default color by default. cfg.netMobDamageModifier = 1; cfg.netMobHealthModifier = 1; cfg.netGravity = -1; // use map default cfg.plrViewHeight = DEFAULT_PLAYER_VIEWHEIGHT; cfg.mapTitle = true; cfg.hideIWADAuthor = true; cfg.menuScale = .75f; cfg.menuColor[0] = defFontRGB[0]; // use the default colour by default. cfg.menuColor[1] = defFontRGB[1]; cfg.menuColor[2] = defFontRGB[2]; cfg.menuColor2[0] = defFontRGB2[0]; // use the default colour by default. cfg.menuColor2[1] = defFontRGB2[1]; cfg.menuColor2[2] = defFontRGB2[2]; cfg.menuEffects = 0; cfg.menuHotkeys = true; cfg.askQuickSaveLoad = true; cfg.hudFog = 5; cfg.menuSlam = true; cfg.flashColor[0] = 1.0f; cfg.flashColor[1] = .5f; cfg.flashColor[2] = .5f; cfg.flashSpeed = 4; cfg.turningSkull = false; cfg.hudScale = .7f; cfg.hudColor[0] = defFontRGB[0]; // use the default colour by default. cfg.hudColor[1] = defFontRGB[1]; cfg.hudColor[2] = defFontRGB[2]; cfg.hudColor[3] = 1; cfg.hudIconAlpha = 1; cfg.usePatchReplacement = 2; // Use built-in replacements if available. cfg.cameraNoClip = true; cfg.bobView = cfg.bobWeapon = 1; cfg.statusbarOpacity = 1; cfg.statusbarCounterAlpha = 1; cfg.inventoryTimer = 5; cfg.automapCustomColors = 0; // Never. cfg.automapL0[0] = .42f; // Unseen areas cfg.automapL0[1] = .42f; cfg.automapL0[2] = .42f; cfg.automapL1[0] = .41f; // onesided lines cfg.automapL1[1] = .30f; cfg.automapL1[2] = .15f; cfg.automapL2[0] = .82f; // floor height change lines cfg.automapL2[1] = .70f; cfg.automapL2[2] = .52f; cfg.automapL3[0] = .47f; // ceiling change lines cfg.automapL3[1] = .30f; cfg.automapL3[2] = .16f; cfg.automapMobj[0] = 1.f; cfg.automapMobj[1] = 1.f; cfg.automapMobj[2] = 1.f; cfg.automapBack[0] = 1.0f; cfg.automapBack[1] = 1.0f; cfg.automapBack[2] = 1.0f; cfg.automapOpacity = 1.0f; cfg.automapLineAlpha = 1.0f; cfg.automapShowDoors = true; cfg.automapDoorGlow = 8; cfg.automapHudDisplay = 2; cfg.automapRotate = true; cfg.automapBabyKeys = false; cfg.automapZoomSpeed = .1f; cfg.automapPanSpeed = .5f; cfg.automapPanResetOnOpen = true; cfg.automapOpenSeconds = AUTOMAP_OPEN_SECONDS; cfg.counterCheatScale = .7f; //From jHeretic cfg.msgShow = true; cfg.msgCount = 4; cfg.msgScale = .8f; cfg.msgUptime = 5; cfg.msgAlign = ALIGN_CENTER; cfg.msgBlink = 5; cfg.msgColor[0] = defFontRGB2[0]; cfg.msgColor[1] = defFontRGB2[1]; cfg.msgColor[2] = defFontRGB2[2]; cfg.inventoryTimer = 5; cfg.inventoryWrap = false; cfg.inventoryUseNext = false; cfg.inventoryUseImmediate = false; cfg.inventorySlotMaxVis = 7; cfg.inventorySlotShowEmpty = true; cfg.inventorySelectMode = 0; // Cursor select. cfg.chatBeep = 1; cfg.weaponOrder[0] = WT_FOURTH; cfg.weaponOrder[1] = WT_THIRD; cfg.weaponOrder[2] = WT_SECOND; cfg.weaponOrder[3] = WT_FIRST; // Hexen has a nifty "Ethereal Travel" screen, so don't show the // console during map setup. Con_SetInteger("con-show-during-setup", 0, true); // Do the common pre init routine. G_CommonPreInit(); } /** * Post Engine Initialization routine. * All game-specific actions that should take place at this time go here. */ void G_PostInit(void) { int p; int pClass; char mapStr[6]; // Do this early as other systems need to know. P_InitPlayerClassInfo(); // Common post init routine. G_CommonPostInit(); // Initialize weapon info using definitions. P_InitWeaponInfo(); // Print a game mode banner with rulers. Con_FPrintf(CBLF_RULER | CBLF_WHITE | CBLF_CENTER, gameMode == shareware? "*** Hexen 4-map Beta Demo ***\n" : "Hexen\n"); Con_FPrintf(CBLF_RULER, ""); // Game parameters. /* None */ // Get skill / episode / map from parms. startEpisode = 0; startSkill = SM_MEDIUM; startMap = 0; // Game mode specific settings. /* None */ // Command line options. handleArgs(); // Check the -class argument. pClass = PCLASS_FIGHTER; if((p = ArgCheck("-class")) != 0) { classinfo_t* pClassInfo; pClass = atoi(Argv(p + 1)); if(pClass < 0 || pClass > NUM_PLAYER_CLASSES) { Con_Error("Invalid player class: %d\n", pClass); } pClassInfo = PCLASS_INFO(pClass); if(pClassInfo->userSelectable) { Con_Error("Player class '%s' is not user-selectable.\n", pClassInfo->niceName); } Con_Message("\nPlayer Class: '%s'\n", pClassInfo->niceName); } cfg.playerClass[CONSOLEPLAYER] = pClass; P_InitMapMusicInfo(); // Init music fields in mapinfo. Con_Message("Parsing SNDINFO...\n"); S_ParseSndInfoLump(); Con_Message("SN_InitSequenceScript: Registering sound sequences.\n"); SN_InitSequenceScript(); // Check for command line warping. Follows P_Init() because the // MAPINFO.TXT script must be already processed. p = ArgCheck("-warp"); if(p && p < Argc() - 1) { warpMap = atoi(Argv(p + 1)) - 1; startMap = P_TranslateMap(warpMap); autoStart = true; } else { warpMap = 0; startMap = P_TranslateMap(0); } // Are we autostarting? if(autoStart) { Con_Message("Warp to Map %d (\"%s\":%d), Skill %d\n", warpMap+1, P_GetMapName(startMap), startMap+1, startSkill + 1); } // Load a saved game? if((p = ArgCheckWith("-loadgame", 1)) != 0) { G_LoadGame(atoi(Argv(p + 1))); } // Check valid episode and map. if(autoStart || IS_NETGAME) { sprintf(mapStr,"MAP%2.2d", startMap+1); if(!W_CheckNumForName(mapStr)) { startMap = 0; } } if(G_GetGameAction() != GA_LOADGAME) { if(autoStart || IS_NETGAME) { G_DeferedInitNew(startSkill, startEpisode, startMap); } else { // Start up intro loop. G_StartTitle(); } } } static void handleArgs(void) { int p; execopt_t *opt; noMonstersParm = ArgExists("-nomonsters"); respawnParm = ArgExists("-respawn"); randomClassParm = ArgExists("-randclass"); devParm = ArgExists("-devparm"); netCheatParm = ArgExists("-netcheat"); cfg.netDeathmatch = ArgExists("-deathmatch"); // Turbo movement option. p = ArgCheck("-turbo"); turboMul = 1.0f; if(p) { int scale = 200; turboParm = true; if(p < Argc() - 1) scale = atoi(Argv(p + 1)); if(scale < 10) scale = 10; if(scale > 400) scale = 400; Con_Message("turbo scale: %i%%\n", scale); turboMul = scale / 100.f; } // Process command line options. for(opt = execOptions; opt->name != NULL; opt++) { p = ArgCheck(opt->name); if(p && p < Argc() - opt->requiredArgs) { opt->func(ArgvPtr(p), opt->tag); } } } static void execOptionSkill(const char** args, int tag) { startSkill = args[1][0] - '1'; autoStart = true; } static void execOptionPlayDemo(const char** args, int tag) { char file[256]; sprintf(file, "%s.lmp", args[1]); DD_AddStartupWAD(file); Con_Message("Playing demo %s.lmp.\n", args[1]); } static void execOptionScripts(const char** args, int tag) { sc_FileScripts = true; sc_ScriptsDir = args[1]; } static void execOptionDevMaps(const char** args, int tag) { char* str; DevMaps = true; Con_Message("Map development mode enabled:\n"); Con_Message("[config ] = %s\n", args[1]); SC_OpenFileCLib(args[1]); SC_MustGetStringName("mapsdir"); SC_MustGetString(); Con_Message("[mapsdir ] = %s\n", sc_String); DevMapsDir = malloc(strlen(sc_String) + 1); strcpy(DevMapsDir, sc_String); SC_MustGetStringName("scriptsdir"); SC_MustGetString(); Con_Message("[scriptsdir] = %s\n", sc_String); sc_FileScripts = true; str = malloc(strlen(sc_String) + 1); strcpy(str, sc_String); sc_ScriptsDir = str; while(SC_GetString()) { if(SC_Compare("file")) { SC_MustGetString(); DD_AddStartupWAD(sc_String); } else { SC_ScriptError(NULL); } } SC_Close(); } void G_Shutdown(void) { Hu_MsgShutdown(); Hu_UnloadData(); Hu_LogShutdown(); P_DestroyIterList(spechit); P_DestroyIterList(linespecials); P_DestroyLineTagLists(); P_DestroySectorTagLists(); P_ShutdownInventory(); AM_Shutdown(); X_DestroyLUTs(); P_FreeWeaponSlots(); } void G_EndFrame(void) { SN_UpdateActiveSequences(); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_acs.c0000644000175000017500000012214411357170242022053 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_acs.c: * * \bug Not 64bit clean: In function 'P_LoadACScripts': cast from pointer to integer of different size, cast to pointer from integer of different size */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "dmu_lib.h" #include "p_player.h" #include "p_map.h" #include "p_mapsetup.h" #include "p_mapspec.h" // MACROS ------------------------------------------------------------------ #define SCRIPT_CONTINUE 0 #define SCRIPT_STOP 1 #define SCRIPT_TERMINATE 2 #define OPEN_SCRIPTS_BASE 1000 #define PRINT_BUFFER_SIZE 256 #define GAME_SINGLE_PLAYER 0 #define GAME_NET_COOPERATIVE 1 #define GAME_NET_DEATHMATCH 2 #define TEXTURE_TOP 0 #define TEXTURE_MIDDLE 1 #define TEXTURE_BOTTOM 2 #define S_DROP ACScript->stackPtr-- #define S_POP ACScript->stack[--ACScript->stackPtr] #define S_PUSH(x) ACScript->stack[ACScript->stackPtr++] = x // TYPES ------------------------------------------------------------------- typedef struct acsheader_s { int marker; int infoOffset; int code; } acsheader_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void StartOpenACS(int number, int infoIndex, const int* address); static void ScriptFinished(int number); static boolean TagBusy(int tag); static boolean AddToACSStore(uint map, int number, const byte* args); static int GetACSIndex(int number); static void Push(int value); static int Pop(void); static int Top(void); static void Drop(void); static int CmdNOP(void); static int CmdTerminate(void); static int CmdSuspend(void); static int CmdPushNumber(void); static int CmdLSpec1(void); static int CmdLSpec2(void); static int CmdLSpec3(void); static int CmdLSpec4(void); static int CmdLSpec5(void); static int CmdLSpec1Direct(void); static int CmdLSpec2Direct(void); static int CmdLSpec3Direct(void); static int CmdLSpec4Direct(void); static int CmdLSpec5Direct(void); static int CmdAdd(void); static int CmdSubtract(void); static int CmdMultiply(void); static int CmdDivide(void); static int CmdModulus(void); static int CmdEQ(void); static int CmdNE(void); static int CmdLT(void); static int CmdGT(void); static int CmdLE(void); static int CmdGE(void); static int CmdAssignScriptVar(void); static int CmdAssignMapVar(void); static int CmdAssignWorldVar(void); static int CmdPushScriptVar(void); static int CmdPushMapVar(void); static int CmdPushWorldVar(void); static int CmdAddScriptVar(void); static int CmdAddMapVar(void); static int CmdAddWorldVar(void); static int CmdSubScriptVar(void); static int CmdSubMapVar(void); static int CmdSubWorldVar(void); static int CmdMulScriptVar(void); static int CmdMulMapVar(void); static int CmdMulWorldVar(void); static int CmdDivScriptVar(void); static int CmdDivMapVar(void); static int CmdDivWorldVar(void); static int CmdModScriptVar(void); static int CmdModMapVar(void); static int CmdModWorldVar(void); static int CmdIncScriptVar(void); static int CmdIncMapVar(void); static int CmdIncWorldVar(void); static int CmdDecScriptVar(void); static int CmdDecMapVar(void); static int CmdDecWorldVar(void); static int CmdGoto(void); static int CmdIfGoto(void); static int CmdDrop(void); static int CmdDelay(void); static int CmdDelayDirect(void); static int CmdRandom(void); static int CmdRandomDirect(void); static int CmdThingCount(void); static int CmdThingCountDirect(void); static int CmdTagWait(void); static int CmdTagWaitDirect(void); static int CmdPolyWait(void); static int CmdPolyWaitDirect(void); static int CmdChangeFloor(void); static int CmdChangeFloorDirect(void); static int CmdChangeCeiling(void); static int CmdChangeCeilingDirect(void); static int CmdRestart(void); static int CmdAndLogical(void); static int CmdOrLogical(void); static int CmdAndBitwise(void); static int CmdOrBitwise(void); static int CmdEorBitwise(void); static int CmdNegateLogical(void); static int CmdLShift(void); static int CmdRShift(void); static int CmdUnaryMinus(void); static int CmdIfNotGoto(void); static int CmdLineSide(void); static int CmdScriptWait(void); static int CmdScriptWaitDirect(void); static int CmdClearLineSpecial(void); static int CmdCaseGoto(void); static int CmdBeginPrint(void); static int CmdEndPrint(void); static int CmdPrintString(void); static int CmdPrintNumber(void); static int CmdPrintCharacter(void); static int CmdPlayerCount(void); static int CmdGameType(void); static int CmdGameSkill(void); static int CmdTimer(void); static int CmdSectorSound(void); static int CmdAmbientSound(void); static int CmdSoundSequence(void); static int CmdSetLineTexture(void); static int CmdSetLineBlocking(void); static int CmdSetLineSpecial(void); static int CmdThingSound(void); static int CmdEndPrintBold(void); static void ThingCount(int type, int tid); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int ACScriptCount; const byte* ActionCodeBase; acsinfo_t* ACSInfo; int MapVars[MAX_ACS_MAP_VARS]; int WorldVars[MAX_ACS_WORLD_VARS]; int ACSStoreSize; acsstore_t* ACSStore; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static acs_t* ACScript; static const int* PCodePtr; static byte SpecArgs[8]; static int ACStringCount; static char const** ACStrings; static char PrintBuffer[PRINT_BUFFER_SIZE]; static acs_t* NewScript; static char ErrorMsg[128]; static int (*PCodeCmds[]) (void) = { CmdNOP, CmdTerminate, CmdSuspend, CmdPushNumber, CmdLSpec1, CmdLSpec2, CmdLSpec3, CmdLSpec4, CmdLSpec5, CmdLSpec1Direct, CmdLSpec2Direct, CmdLSpec3Direct, CmdLSpec4Direct, CmdLSpec5Direct, CmdAdd, CmdSubtract, CmdMultiply, CmdDivide, CmdModulus, CmdEQ, CmdNE, CmdLT, CmdGT, CmdLE, CmdGE, CmdAssignScriptVar, CmdAssignMapVar, CmdAssignWorldVar, CmdPushScriptVar, CmdPushMapVar, CmdPushWorldVar, CmdAddScriptVar, CmdAddMapVar, CmdAddWorldVar, CmdSubScriptVar, CmdSubMapVar, CmdSubWorldVar, CmdMulScriptVar, CmdMulMapVar, CmdMulWorldVar, CmdDivScriptVar, CmdDivMapVar, CmdDivWorldVar, CmdModScriptVar, CmdModMapVar, CmdModWorldVar, CmdIncScriptVar, CmdIncMapVar, CmdIncWorldVar, CmdDecScriptVar, CmdDecMapVar, CmdDecWorldVar, CmdGoto, CmdIfGoto, CmdDrop, CmdDelay, CmdDelayDirect, CmdRandom, CmdRandomDirect, CmdThingCount, CmdThingCountDirect, CmdTagWait, CmdTagWaitDirect, CmdPolyWait, CmdPolyWaitDirect, CmdChangeFloor, CmdChangeFloorDirect, CmdChangeCeiling, CmdChangeCeilingDirect, CmdRestart, CmdAndLogical, CmdOrLogical, CmdAndBitwise, CmdOrBitwise, CmdEorBitwise, CmdNegateLogical, CmdLShift, CmdRShift, CmdUnaryMinus, CmdIfNotGoto, CmdLineSide, CmdScriptWait, CmdScriptWaitDirect, CmdClearLineSpecial, CmdCaseGoto, CmdBeginPrint, CmdEndPrint, CmdPrintString, CmdPrintNumber, CmdPrintCharacter, CmdPlayerCount, CmdGameType, CmdGameSkill, CmdTimer, CmdSectorSound, CmdAmbientSound, CmdSoundSequence, CmdSetLineTexture, CmdSetLineBlocking, CmdSetLineSpecial, CmdThingSound, CmdEndPrintBold}; // CODE -------------------------------------------------------------------- const char* GetACString(int id) { if(id < 0 || id > ACStringCount) return NULL; return ACStrings[id]; } void P_LoadACScripts(int lump) { int i; const int* buffer; const acsheader_t* header; acsinfo_t* info; header = W_CacheLumpNum(lump, PU_MAP); ActionCodeBase = (const byte*) header; buffer = (int*) ((const byte*) header + LONG(header->infoOffset)); ACScriptCount = LONG(*buffer++); if(ACScriptCount == 0 || IS_CLIENT) { // Empty behavior lump ACScriptCount = 0; return; } ACSInfo = Z_Malloc(ACScriptCount * sizeof(acsinfo_t), PU_MAP, 0); memset(ACSInfo, 0, ACScriptCount * sizeof(acsinfo_t)); for(i = 0, info = ACSInfo; i < ACScriptCount; ++i, info++) { info->number = LONG(*buffer++); info->address = (const int*) ((const byte*) ActionCodeBase + LONG(*buffer++)); info->argCount = LONG(*buffer++); if(info->number >= OPEN_SCRIPTS_BASE) { // Auto-activate info->number -= OPEN_SCRIPTS_BASE; StartOpenACS(info->number, i, info->address); info->state = ASTE_RUNNING; } else { info->state = ASTE_INACTIVE; } } ACStringCount = LONG(*buffer++); ACStrings = Z_Malloc(ACStringCount * sizeof(char*), PU_MAP, 0); for(i = 0; i < ACStringCount; ++i) { ACStrings[i] = (const char*)ActionCodeBase + LONG(*buffer++); } memset(MapVars, 0, sizeof(MapVars)); } static void StartOpenACS(int number, int infoIndex, const int* address) { acs_t* script; script = Z_Calloc(sizeof(*script), PU_MAP, 0); script->number = number; // World objects are allotted 1 second for initialization script->delayCount = TICRATE; script->infoIndex = infoIndex; script->ip = address; script->thinker.function = T_InterpretACS; DD_ThinkerAdd(&script->thinker); } /** * Scans the ACS store and executes all scripts belonging to the current map. */ void P_CheckACSStore(uint map) { int i = 0, origSize = ACSStoreSize; while(i < ACSStoreSize) { acsstore_t* store = &ACSStore[i]; if(store->map != map) { i++; continue; } P_StartACS(store->script, 0, store->args, NULL, NULL, 0); if(NewScript) { NewScript->delayCount = TICRATE; } ACSStoreSize -= 1; if(i == ACSStoreSize) break; memmove(&ACSStore[i], &ACSStore[i+1], sizeof(acsstore_t) * (ACSStoreSize-i)); } if(ACSStoreSize != origSize) { if(ACSStoreSize) ACSStore = Z_Realloc(ACSStore, sizeof(acsstore_t) * ACSStoreSize, PU_STATIC); else Z_Free(ACSStore); ACSStore = NULL; } } /** * @param map Map number on which the script is being started on. * @c 0 = Current map. Otherwise 1-based index of the * map to start on (will be deferred). */ boolean P_StartACS(int number, uint map, byte* args, mobj_t* activator, linedef_t* line, int side) { int i, infoIndex; acs_t* script; aste_t* statePtr; NewScript = NULL; if(map && map-1 != gameMap) { // Script is not for the current map. // Add it to the store to be started when that map is next entered. return AddToACSStore(map-1, number, args); } infoIndex = GetACSIndex(number); if(infoIndex == -1) { // Script not found. sprintf(ErrorMsg, "P_STARTACS ERROR: UNKNOWN SCRIPT %d", number); P_SetMessage(&players[CONSOLEPLAYER], ErrorMsg, false); return false; } statePtr = &ACSInfo[infoIndex].state; if(*statePtr == ASTE_SUSPENDED) { // Resume a suspended script. *statePtr = ASTE_RUNNING; return true; } if(*statePtr != ASTE_INACTIVE) { // Script is already executing. return false; } script = Z_Calloc(sizeof(*script), PU_MAP, 0); script->number = number; script->infoIndex = infoIndex; script->activator = activator; script->line = line; script->side = side; script->ip = ACSInfo[infoIndex].address; script->thinker.function = T_InterpretACS; for(i = 0; i < ACSInfo[infoIndex].argCount; ++i) { script->vars[i] = args[i]; } *statePtr = ASTE_RUNNING; DD_ThinkerAdd(&script->thinker); NewScript = script; return true; } static boolean AddToACSStore(uint map, int number, const byte* args) { acsstore_t* store; if(ACSStoreSize) { int i; // Don't allow duplicates. for(i = 0; i < ACSStoreSize; ++i) { store = &ACSStore[i]; if(store->script == number && store->map == map) return false; } ACSStore = Z_Realloc(ACSStore, ++ACSStoreSize * sizeof(acsstore_t), PU_STATIC); } else { ACSStore = Z_Malloc(sizeof(acsstore_t), PU_STATIC, 0); ACSStoreSize = 1; } store = &ACSStore[ACSStoreSize-1]; store->map = map; store->script = number; store->args[0] = args[0]; store->args[1] = args[1]; store->args[2] = args[2]; store->args[3] = args[3]; return true; } boolean P_StartLockedACS(linedef_t *line, byte *args, mobj_t *mo, int side) { int i; int lock; byte newArgs[5]; char LockedBuffer[80]; extern int TextKeyMessages[11]; lock = args[4]; if(!mo->player) { return false; } if(lock) { if(!(mo->player->keys & (1 << (lock - 1)))) { sprintf(LockedBuffer, "YOU NEED THE %s\n", GET_TXT(TextKeyMessages[lock - 1])); P_SetMessage(mo->player, LockedBuffer, false); S_StartSound(SFX_DOOR_LOCKED, mo); return false; } } for(i = 0; i < 4; ++i) { newArgs[i] = args[i]; } newArgs[4] = 0; return P_StartACS(newArgs[0], newArgs[1], &newArgs[2], mo, line, side); } boolean P_TerminateACS(int number, uint map) { int infoIndex; infoIndex = GetACSIndex(number); if(infoIndex == -1) { // Script not found return false; } if(ACSInfo[infoIndex].state == ASTE_INACTIVE || ACSInfo[infoIndex].state == ASTE_TERMINATING) { // States that disallow termination return false; } ACSInfo[infoIndex].state = ASTE_TERMINATING; return true; } boolean P_SuspendACS(int number, uint map) { int infoIndex; infoIndex = GetACSIndex(number); if(infoIndex == -1) { // Script not found return false; } if(ACSInfo[infoIndex].state == ASTE_INACTIVE || ACSInfo[infoIndex].state == ASTE_SUSPENDED || ACSInfo[infoIndex].state == ASTE_TERMINATING) { // States that disallow suspension return false; } ACSInfo[infoIndex].state = ASTE_SUSPENDED; return true; } void P_ACSInitNewGame(void) { memset(WorldVars, 0, sizeof(WorldVars)); if(ACSStore) Z_Free(ACSStore); ACSStore = NULL; ACSStoreSize = 0; } void T_InterpretACS(acs_t* script) { int cmd, action; if(ACSInfo[script->infoIndex].state == ASTE_TERMINATING) { ACSInfo[script->infoIndex].state = ASTE_INACTIVE; ScriptFinished(ACScript->number); DD_ThinkerRemove(&ACScript->thinker); return; } if(ACSInfo[script->infoIndex].state != ASTE_RUNNING) { return; } if(script->delayCount) { script->delayCount--; return; } ACScript = script; PCodePtr = ACScript->ip; do { cmd = LONG(*PCodePtr++); action = PCodeCmds[cmd] (); } while(action == SCRIPT_CONTINUE); ACScript->ip = PCodePtr; if(action == SCRIPT_TERMINATE) { ACSInfo[script->infoIndex].state = ASTE_INACTIVE; ScriptFinished(ACScript->number); DD_ThinkerRemove(&ACScript->thinker); } } void P_TagFinished(int tag) { int i; if(TagBusy(tag) == true) { return; } for(i = 0; i < ACScriptCount; ++i) { if(ACSInfo[i].state == ASTE_WAITING_FOR_TAG && ACSInfo[i].waitValue == tag) { ACSInfo[i].state = ASTE_RUNNING; } } } void P_PolyobjFinished(int po) { int i; if(PO_Busy(po) == true) { return; } for(i = 0; i < ACScriptCount; ++i) { if(ACSInfo[i].state == ASTE_WAITING_FOR_POLY && ACSInfo[i].waitValue == po) { ACSInfo[i].state = ASTE_RUNNING; } } } static void ScriptFinished(int number) { int i; for(i = 0; i < ACScriptCount; ++i) { if(ACSInfo[i].state == ASTE_WAITING_FOR_SCRIPT && ACSInfo[i].waitValue == number) { ACSInfo[i].state = ASTE_RUNNING; } } } static boolean TagBusy(int tag) { uint k; sector_t* sec; xsector_t* xsec; // NOTE: We can't use the sector tag lists here as we might already be // in an iteration at a higher level. for(k = 0; k < numsectors; ++k) { sec = P_ToPtr(DMU_SECTOR, k); xsec = P_ToXSector(sec); if(xsec->tag != tag) continue; if(xsec->specialData) return true; } return false; } /** * @return The index of a script number else @c -1,. */ static int GetACSIndex(int number) { int i; for(i = 0; i < ACScriptCount; ++i) { if(ACSInfo[i].number == number) { return i; } } return -1; } static void Push(int value) { ACScript->stack[ACScript->stackPtr++] = value; } static int Pop(void) { return ACScript->stack[--ACScript->stackPtr]; } static int Top(void) { return ACScript->stack[ACScript->stackPtr - 1]; } static void Drop(void) { ACScript->stackPtr--; } static int CmdNOP(void) { return SCRIPT_CONTINUE; } static int CmdTerminate(void) { return SCRIPT_TERMINATE; } static int CmdSuspend(void) { ACSInfo[ACScript->infoIndex].state = ASTE_SUSPENDED; return SCRIPT_STOP; } static int CmdPushNumber(void) { Push(LONG(*PCodePtr++)); return SCRIPT_CONTINUE; } static int CmdLSpec1(void) { int special; special = LONG(*PCodePtr++); SpecArgs[0] = Pop(); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec2(void) { int special; special = LONG(*PCodePtr++); SpecArgs[1] = Pop(); SpecArgs[0] = Pop(); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec3(void) { int special; special = LONG(*PCodePtr++); SpecArgs[2] = Pop(); SpecArgs[1] = Pop(); SpecArgs[0] = Pop(); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec4(void) { int special; special = LONG(*PCodePtr++); SpecArgs[3] = Pop(); SpecArgs[2] = Pop(); SpecArgs[1] = Pop(); SpecArgs[0] = Pop(); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec5(void) { int special; special = LONG(*PCodePtr++); SpecArgs[4] = Pop(); SpecArgs[3] = Pop(); SpecArgs[2] = Pop(); SpecArgs[1] = Pop(); SpecArgs[0] = Pop(); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec1Direct(void) { int special; special = LONG(*PCodePtr++); SpecArgs[0] = LONG(*PCodePtr++); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec2Direct(void) { int special; special = LONG(*PCodePtr++); SpecArgs[0] = LONG(*PCodePtr++); SpecArgs[1] = LONG(*PCodePtr++); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec3Direct(void) { int special; special = LONG(*PCodePtr++); SpecArgs[0] = LONG(*PCodePtr++); SpecArgs[1] = LONG(*PCodePtr++); SpecArgs[2] = LONG(*PCodePtr++); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec4Direct(void) { int special; special = LONG(*PCodePtr++); SpecArgs[0] = LONG(*PCodePtr++); SpecArgs[1] = LONG(*PCodePtr++); SpecArgs[2] = LONG(*PCodePtr++); SpecArgs[3] = LONG(*PCodePtr++); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdLSpec5Direct(void) { int special; special = LONG(*PCodePtr++); SpecArgs[0] = LONG(*PCodePtr++); SpecArgs[1] = LONG(*PCodePtr++); SpecArgs[2] = LONG(*PCodePtr++); SpecArgs[3] = LONG(*PCodePtr++); SpecArgs[4] = LONG(*PCodePtr++); P_ExecuteLineSpecial(special, SpecArgs, ACScript->line, ACScript->side, ACScript->activator); return SCRIPT_CONTINUE; } static int CmdAdd(void) { Push(Pop() + Pop()); return SCRIPT_CONTINUE; } static int CmdSubtract(void) { int operand2; operand2 = Pop(); Push(Pop() - operand2); return SCRIPT_CONTINUE; } static int CmdMultiply(void) { Push(Pop() * Pop()); return SCRIPT_CONTINUE; } static int CmdDivide(void) { int operand2; operand2 = Pop(); Push(Pop() / operand2); return SCRIPT_CONTINUE; } static int CmdModulus(void) { int operand2; operand2 = Pop(); Push(Pop() % operand2); return SCRIPT_CONTINUE; } static int CmdEQ(void) { Push(Pop() == Pop()); return SCRIPT_CONTINUE; } static int CmdNE(void) { Push(Pop() != Pop()); return SCRIPT_CONTINUE; } static int CmdLT(void) { int operand2; operand2 = Pop(); Push(Pop() < operand2); return SCRIPT_CONTINUE; } static int CmdGT(void) { int operand2; operand2 = Pop(); Push(Pop() > operand2); return SCRIPT_CONTINUE; } static int CmdLE(void) { int operand2; operand2 = Pop(); Push(Pop() <= operand2); return SCRIPT_CONTINUE; } static int CmdGE(void) { int operand2; operand2 = Pop(); Push(Pop() >= operand2); return SCRIPT_CONTINUE; } static int CmdAssignScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)] = Pop(); return SCRIPT_CONTINUE; } static int CmdAssignMapVar(void) { MapVars[LONG(*PCodePtr++)] = Pop(); return SCRIPT_CONTINUE; } static int CmdAssignWorldVar(void) { WorldVars[LONG(*PCodePtr++)] = Pop(); return SCRIPT_CONTINUE; } static int CmdPushScriptVar(void) { Push(ACScript->vars[LONG(*PCodePtr++)]); return SCRIPT_CONTINUE; } static int CmdPushMapVar(void) { Push(MapVars[LONG(*PCodePtr++)]); return SCRIPT_CONTINUE; } static int CmdPushWorldVar(void) { Push(WorldVars[LONG(*PCodePtr++)]); return SCRIPT_CONTINUE; } static int CmdAddScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)] += Pop(); return SCRIPT_CONTINUE; } static int CmdAddMapVar(void) { MapVars[LONG(*PCodePtr++)] += Pop(); return SCRIPT_CONTINUE; } static int CmdAddWorldVar(void) { WorldVars[LONG(*PCodePtr++)] += Pop(); return SCRIPT_CONTINUE; } static int CmdSubScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)] -= Pop(); return SCRIPT_CONTINUE; } static int CmdSubMapVar(void) { MapVars[LONG(*PCodePtr++)] -= Pop(); return SCRIPT_CONTINUE; } static int CmdSubWorldVar(void) { WorldVars[LONG(*PCodePtr++)] -= Pop(); return SCRIPT_CONTINUE; } static int CmdMulScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)] *= Pop(); return SCRIPT_CONTINUE; } static int CmdMulMapVar(void) { MapVars[LONG(*PCodePtr++)] *= Pop(); return SCRIPT_CONTINUE; } static int CmdMulWorldVar(void) { WorldVars[LONG(*PCodePtr++)] *= Pop(); return SCRIPT_CONTINUE; } static int CmdDivScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)] /= Pop(); return SCRIPT_CONTINUE; } static int CmdDivMapVar(void) { MapVars[LONG(*PCodePtr++)] /= Pop(); return SCRIPT_CONTINUE; } static int CmdDivWorldVar(void) { WorldVars[LONG(*PCodePtr++)] /= Pop(); return SCRIPT_CONTINUE; } static int CmdModScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)] %= Pop(); return SCRIPT_CONTINUE; } static int CmdModMapVar(void) { MapVars[LONG(*PCodePtr++)] %= Pop(); return SCRIPT_CONTINUE; } static int CmdModWorldVar(void) { WorldVars[LONG(*PCodePtr++)] %= Pop(); return SCRIPT_CONTINUE; } static int CmdIncScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)]++; return SCRIPT_CONTINUE; } static int CmdIncMapVar(void) { MapVars[LONG(*PCodePtr++)]++; return SCRIPT_CONTINUE; } static int CmdIncWorldVar(void) { WorldVars[LONG(*PCodePtr++)]++; return SCRIPT_CONTINUE; } static int CmdDecScriptVar(void) { ACScript->vars[LONG(*PCodePtr++)]--; return SCRIPT_CONTINUE; } static int CmdDecMapVar(void) { MapVars[LONG(*PCodePtr++)]--; return SCRIPT_CONTINUE; } static int CmdDecWorldVar(void) { WorldVars[LONG(*PCodePtr++)]--; return SCRIPT_CONTINUE; } static int CmdGoto(void) { PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr)); return SCRIPT_CONTINUE; } static int CmdIfGoto(void) { if(Pop()) { PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr)); } else { PCodePtr++; } return SCRIPT_CONTINUE; } static int CmdDrop(void) { Drop(); return SCRIPT_CONTINUE; } static int CmdDelay(void) { ACScript->delayCount = Pop(); return SCRIPT_STOP; } static int CmdDelayDirect(void) { ACScript->delayCount = LONG(*PCodePtr++); return SCRIPT_STOP; } static int CmdRandom(void) { int low, high; high = Pop(); low = Pop(); Push(low + (P_Random() % (high - low + 1))); return SCRIPT_CONTINUE; } static int CmdRandomDirect(void) { int low, high; low = LONG(*PCodePtr++); high = LONG(*PCodePtr++); Push(low + (P_Random() % (high - low + 1))); return SCRIPT_CONTINUE; } static int CmdThingCount(void) { int tid; tid = Pop(); ThingCount(Pop(), tid); return SCRIPT_CONTINUE; } static int CmdThingCountDirect(void) { int type; type = LONG(*PCodePtr++); ThingCount(type, LONG(*PCodePtr++)); return SCRIPT_CONTINUE; } typedef struct { mobjtype_t type; int count; } countmobjoftypeparams_t; static boolean countMobjOfType(thinker_t* th, void* context) { countmobjoftypeparams_t* params = (countmobjoftypeparams_t*) context; mobj_t* mo = (mobj_t *) th; // Does the type match? if(mo->type != params->type) return true; // Continue iteration. // Minimum health requirement? if((mo->flags & MF_COUNTKILL) && mo->health <= 0) return true; // Continue iteration. params->count++; return true; // Continue iteration. } static void ThingCount(int type, int tid) { int count; mobjtype_t moType; if(!(type + tid)) { // Nothing to count. return; } moType = TranslateThingType[type]; count = 0; if(tid) { // Count TID things. mobj_t* mo; int searcher = -1; while((mo = P_FindMobjFromTID(tid, &searcher)) != NULL) { if(type == 0) { // Just count TIDs. count++; } else if(moType == mo->type) { if((mo->flags & MF_COUNTKILL) && mo->health <= 0) { // Don't count dead monsters. continue; } count++; } } } else { // Count only types. countmobjoftypeparams_t params; params.type = moType; params.count = 0; DD_IterateThinkers(P_MobjThinker, countMobjOfType, ¶ms); count = params.count; } Push(count); } static int CmdTagWait(void) { ACSInfo[ACScript->infoIndex].waitValue = Pop(); ACSInfo[ACScript->infoIndex].state = ASTE_WAITING_FOR_TAG; return SCRIPT_STOP; } static int CmdTagWaitDirect(void) { ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr++); ACSInfo[ACScript->infoIndex].state = ASTE_WAITING_FOR_TAG; return SCRIPT_STOP; } static int CmdPolyWait(void) { ACSInfo[ACScript->infoIndex].waitValue = Pop(); ACSInfo[ACScript->infoIndex].state = ASTE_WAITING_FOR_POLY; return SCRIPT_STOP; } static int CmdPolyWaitDirect(void) { ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr++); ACSInfo[ACScript->infoIndex].state = ASTE_WAITING_FOR_POLY; return SCRIPT_STOP; } static int CmdChangeFloor(void) { int tag; material_t* mat; sector_t* sec = NULL; iterlist_t* list; mat = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(GetACString(Pop()), MN_FLATS)); tag = Pop(); list = P_GetSectorIterListForTag(tag, false); if(list) { P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { P_SetPtrp(sec, DMU_FLOOR_MATERIAL, mat); } } return SCRIPT_CONTINUE; } static int CmdChangeFloorDirect(void) { int tag; material_t* mat; sector_t* sec = NULL; iterlist_t* list; tag = LONG(*PCodePtr++); mat = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName( GetACString(LONG(*PCodePtr++)), MN_FLATS)); list = P_GetSectorIterListForTag(tag, false); if(list) { P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { P_SetPtrp(sec, DMU_FLOOR_MATERIAL, mat); } } return SCRIPT_CONTINUE; } static int CmdChangeCeiling(void) { int tag; material_t* mat; sector_t* sec = NULL; iterlist_t* list; mat = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(GetACString(Pop()), MN_FLATS)); tag = Pop(); list = P_GetSectorIterListForTag(tag, false); if(list) { P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { P_SetPtrp(sec, DMU_CEILING_MATERIAL, mat); } } return SCRIPT_CONTINUE; } static int CmdChangeCeilingDirect(void) { int tag; material_t* mat; sector_t* sec = NULL; iterlist_t* list; tag = LONG(*PCodePtr++); mat = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(GetACString(LONG(*PCodePtr++)), MN_FLATS)); list = P_GetSectorIterListForTag(tag, false); if(list) { P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { P_SetPtrp(sec, DMU_CEILING_MATERIAL, mat); } } return SCRIPT_CONTINUE; } static int CmdRestart(void) { PCodePtr = ACSInfo[ACScript->infoIndex].address; return SCRIPT_CONTINUE; } static int CmdAndLogical(void) { Push(Pop() && Pop()); return SCRIPT_CONTINUE; } static int CmdOrLogical(void) { Push(Pop() || Pop()); return SCRIPT_CONTINUE; } static int CmdAndBitwise(void) { Push(Pop() & Pop()); return SCRIPT_CONTINUE; } static int CmdOrBitwise(void) { Push(Pop() | Pop()); return SCRIPT_CONTINUE; } static int CmdEorBitwise(void) { Push(Pop() ^ Pop()); return SCRIPT_CONTINUE; } static int CmdNegateLogical(void) { Push(!Pop()); return SCRIPT_CONTINUE; } static int CmdLShift(void) { int operand2; operand2 = Pop(); Push(Pop() << operand2); return SCRIPT_CONTINUE; } static int CmdRShift(void) { int operand2; operand2 = Pop(); Push(Pop() >> operand2); return SCRIPT_CONTINUE; } static int CmdUnaryMinus(void) { Push(-Pop()); return SCRIPT_CONTINUE; } static int CmdIfNotGoto(void) { if(Pop()) { PCodePtr++; } else { PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr)); } return SCRIPT_CONTINUE; } static int CmdLineSide(void) { Push(ACScript->side); return SCRIPT_CONTINUE; } static int CmdScriptWait(void) { ACSInfo[ACScript->infoIndex].waitValue = Pop(); ACSInfo[ACScript->infoIndex].state = ASTE_WAITING_FOR_SCRIPT; return SCRIPT_STOP; } static int CmdScriptWaitDirect(void) { ACSInfo[ACScript->infoIndex].waitValue = LONG(*PCodePtr++); ACSInfo[ACScript->infoIndex].state = ASTE_WAITING_FOR_SCRIPT; return SCRIPT_STOP; } static int CmdClearLineSpecial(void) { if(ACScript->line) { P_ToXLine(ACScript->line)->special = 0; } return SCRIPT_CONTINUE; } static int CmdCaseGoto(void) { if(Top() == LONG(*PCodePtr++)) { PCodePtr = (int *) (ActionCodeBase + LONG(*PCodePtr)); Drop(); } else { PCodePtr++; } return SCRIPT_CONTINUE; } static int CmdBeginPrint(void) { *PrintBuffer = 0; return SCRIPT_CONTINUE; } static int CmdEndPrint(void) { if(ACScript->activator && ACScript->activator->player) { P_SetMessage(ACScript->activator->player, PrintBuffer, false); } else { int i; // Send to everybody. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) P_SetMessage(&players[i], PrintBuffer, false); } return SCRIPT_CONTINUE; } static int CmdEndPrintBold(void) { int i; for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { P_SetYellowMessage(&players[i], PrintBuffer, false); } } return SCRIPT_CONTINUE; } static int CmdPrintString(void) { strcat(PrintBuffer, GetACString(Pop())); return SCRIPT_CONTINUE; } static int CmdPrintNumber(void) { char tempStr[16]; sprintf(tempStr, "%d", Pop()); strcat(PrintBuffer, tempStr); return SCRIPT_CONTINUE; } static int CmdPrintCharacter(void) { char* bufferEnd; bufferEnd = PrintBuffer + strlen(PrintBuffer); *bufferEnd++ = Pop(); *bufferEnd = 0; return SCRIPT_CONTINUE; } static int CmdPlayerCount(void) { int i, count; count = 0; for(i = 0; i < MAXPLAYERS; ++i) { count += players[i].plr->inGame; } Push(count); return SCRIPT_CONTINUE; } static int CmdGameType(void) { int gametype; if(IS_NETGAME == false) { gametype = GAME_SINGLE_PLAYER; } else if(deathmatch) { gametype = GAME_NET_DEATHMATCH; } else { gametype = GAME_NET_COOPERATIVE; } Push(gametype); return SCRIPT_CONTINUE; } static int CmdGameSkill(void) { Push(gameSkill); return SCRIPT_CONTINUE; } static int CmdTimer(void) { Push(mapTime); return SCRIPT_CONTINUE; } static int CmdSectorSound(void) { int volume; mobj_t* mobj; mobj = NULL; if(ACScript->line) { sector_t* front = P_GetPtrp(ACScript->line, DMU_FRONT_SECTOR); mobj = P_GetPtrp(front, DMU_SOUND_ORIGIN); } volume = Pop(); #if _DEBUG Con_Printf("CmdSectorSound: volume=%i\n", volume); #endif S_StartSoundAtVolume(S_GetSoundID(GetACString(Pop())), mobj, volume / 127.0f); return SCRIPT_CONTINUE; } static int CmdThingSound(void) { int tid, sound, volume, searcher; mobj_t* mobj; volume = Pop(); sound = S_GetSoundID(GetACString(Pop())); tid = Pop(); searcher = -1; while(sound && (mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) { S_StartSoundAtVolume(sound, mobj, volume / 127.0f); } return SCRIPT_CONTINUE; } static int CmdAmbientSound(void) { int volume, sound; mobj_t* mobj = NULL; // For 3D positioning. mobj_t* plrmo = players[DISPLAYPLAYER].plr->mo; volume = Pop(); // If we are playing 3D sounds, create a temporary source mobj // for the sound. if(cfg.snd3D && plrmo) { // SpawnMobj calls P_Random. We don't want that // the random generator gets out of sync. if((mobj = P_SpawnMobj3f(MT_CAMERA, plrmo->pos[VX] + (((M_Random() - 127) * 2) << FRACBITS), plrmo->pos[VY] + (((M_Random() - 127) * 2) << FRACBITS), plrmo->pos[VZ] + (((M_Random() - 127) * 2) << FRACBITS), 0, 0))) // A camera's a good temporary source. mobj->tics = 5 * TICSPERSEC; // Five seconds should be enough. } sound = S_GetSoundID(GetACString(Pop())); S_StartSoundAtVolume(sound, mobj, volume / 127.0f); return SCRIPT_CONTINUE; } static int CmdSoundSequence(void) { mobj_t* mobj; mobj = NULL; if(ACScript->line) { sector_t* front = P_GetPtrp(ACScript->line, DMU_FRONT_SECTOR); mobj = P_GetPtrp(front, DMU_SOUND_ORIGIN); } SN_StartSequenceName(mobj, GetACString(Pop())); return SCRIPT_CONTINUE; } static int CmdSetLineTexture(void) { int lineTag, side, position; material_t* mat; linedef_t* line; iterlist_t* list; mat = P_ToPtr(DMU_MATERIAL, P_MaterialNumForName(GetACString(Pop()), MN_TEXTURES)); position = Pop(); side = Pop(); lineTag = Pop(); list = P_GetLineIterListForTag(lineTag, false); if(list) { P_IterListResetIterator(list, true); while((line = P_IterListIterator(list)) != NULL) { sidedef_t* sdef = P_GetPtrp(line, (side == 0? DMU_SIDEDEF0 : DMU_SIDEDEF1)); if(position == TEXTURE_MIDDLE) { P_SetPtrp(sdef, DMU_MIDDLE_MATERIAL, mat); } else if(position == TEXTURE_BOTTOM) { P_SetPtrp(sdef, DMU_BOTTOM_MATERIAL, mat); } else { // TEXTURE_TOP P_SetPtrp(sdef, DMU_TOP_MATERIAL, mat); } } } return SCRIPT_CONTINUE; } static int CmdSetLineBlocking(void) { linedef_t* line; int lineTag; boolean blocking; iterlist_t* list; blocking = Pop()? DDLF_BLOCKING : 0; lineTag = Pop(); list = P_GetLineIterListForTag(lineTag, false); if(list) { P_IterListResetIterator(list, true); while((line = P_IterListIterator(list)) != NULL) { P_SetIntp(line, DMU_FLAGS, (P_GetIntp(line, DMU_FLAGS) & ~DDLF_BLOCKING) | blocking); } } return SCRIPT_CONTINUE; } static int CmdSetLineSpecial(void) { linedef_t* line; int lineTag; int special, arg1, arg2, arg3, arg4, arg5; iterlist_t* list; arg5 = Pop(); arg4 = Pop(); arg3 = Pop(); arg2 = Pop(); arg1 = Pop(); special = Pop(); lineTag = Pop(); list = P_GetLineIterListForTag(lineTag, false); if(list) { P_IterListResetIterator(list, true); while((line = P_IterListIterator(list)) != NULL) { xline_t* xline = P_ToXLine(line); xline->special = special; xline->arg1 = arg1; xline->arg2 = arg2; xline->arg3 = arg3; xline->arg4 = arg4; xline->arg5 = arg5; } } return SCRIPT_CONTINUE; } // Console commands. DEFCC(CCmdScriptInfo) { int i, whichOne = -1; char* scriptStates[] = { "Inactive", "Running", "Suspended", "Waiting for tag", "Waiting for poly", "Waiting for script", "Terminating" }; if(argc == 2) whichOne = atoi(argv[1]); for(i = 0; i < ACScriptCount; ++i) { acsinfo_t* aptr = ACSInfo + i; if(whichOne != -1 && whichOne != aptr->number) continue; Con_Printf("%d %s (a: %d, w: %d)\n", aptr->number, scriptStates[aptr->state], aptr->argCount, aptr->waitValue); } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/m_random.c0000644000175000017500000000730111357170242022557 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.c: Random number LUT. */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // This is the new flat distribution table static unsigned char rndTable[256] = { 201, 1, 243, 19, 18, 42, 183, 203, 101, 123, 154, 137, 34, 118, 10, 216, 135, 246, 0, 107, 133, 229, 35, 113, 177, 211, 110, 17, 139, 84, 251, 235, 182, 166, 161, 230, 143, 91, 24, 81, 22, 94, 7, 51, 232, 104, 122, 248, 175, 138, 127, 171, 222, 213, 44, 16, 9, 33, 88, 102, 170, 150, 136, 114, 62, 3, 142, 237, 6, 252, 249, 56, 74, 30, 13, 21, 180, 199, 32, 132, 187, 234, 78, 210, 46, 131, 197, 8, 206, 244, 73, 4, 236, 178, 195, 70, 121, 97, 167, 217, 103, 40, 247, 186, 105, 39, 95, 163, 99, 149, 253, 29, 119, 83, 254, 26, 202, 65, 130, 155, 60, 64, 184, 106, 221, 93, 164, 196, 112, 108, 179, 141, 54, 109, 11, 126, 75, 165, 191, 227, 87, 225, 156, 15, 98, 162, 116, 79, 169, 140, 190, 205, 168, 194, 41, 250, 27, 20, 14, 241, 50, 214, 72, 192, 220, 233, 67, 148, 96, 185, 176, 181, 215, 207, 172, 85, 89, 90, 209, 128, 124, 2, 55, 173, 66, 152, 47, 129, 59, 43, 159, 240, 239, 12, 189, 212, 144, 28, 200, 77, 219, 198, 134, 228, 45, 92, 125, 151, 5, 53, 255, 52, 68, 245, 160, 158, 61, 86, 58, 82, 117, 37, 242, 145, 69, 188, 115, 76, 63, 100, 49, 111, 153, 80, 38, 57, 174, 224, 71, 231, 23, 25, 48, 218, 120, 147, 208, 36, 226, 223, 193, 238, 157, 204, 146, 31 }; static int rndIndex = 0, prndIndex = 0; // CODE -------------------------------------------------------------------- /** * \note The returned value is calculated deterministically. * * @return A pseudo-random number from the table. */ byte P_Random(void) { return rndTable[(++prndIndex) & 0xff]; } /** * \note The returned value is NOT calculated deterministically. * * @return A pseudo-random number from the table. */ byte M_Random (void) { rndIndex = (rndIndex+1)&0xff; return rndTable[rndIndex]; } /** * Resets the seed for the random number generator. */ void M_ResetRandom(void) { rndIndex = prndIndex = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/tables.c0000644000175000017500000042034111357170242022240 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * tables.c: * *\attention 2006-09-10 - We should be able to use jDoom version of this as * a complete drop in replacement. - Yagisan */ #include "jhexen.h" int finetangent[4096] = { -170910304, -56965752, -34178904, -24413316, -18988036, -15535599, -13145455, -11392683, -10052327, -8994149, -8137527, -7429880, -6835455, -6329090, -5892567, -5512368, -5178251, -4882318, -4618375, -4381502, -4167737, -3973855, -3797206, -3635590, -3487165, -3350381, -3223918, -3106651, -2997613, -2895966, -2800983, -2712030, -2628549, -2550052, -2476104, -2406322, -2340362, -2277919, -2218719, -2162516, -2109087, -2058233, -2009771, -1963536, -1919378, -1877161, -1836758, -1798063, -1760956, -1725348, -1691149, -1658278, -1626658, -1596220, -1566898, -1538632, -1511367, -1485049, -1459630, -1435065, -1411312, -1388330, -1366084, -1344537, -1323658, -1303416, -1283783, -1264730, -1246234, -1228269, -1210813, -1193846, -1177345, -1161294, -1145673, -1130465, -1115654, -1101225, -1087164, -1073455, -1060087, -1047046, -1034322, -1021901, -1009774, -997931, -986361, -975054, -964003, -953199, -942633, -932298, -922186, -912289, -902602, -893117, -883829, -874730, -865817, -857081, -848520, -840127, -831898, -823827, -815910, -808143, -800521, -793041, -785699, -778490, -771411, -764460, -757631, -750922, -744331, -737853, -731486, -725227, -719074, -713023, -707072, -701219, -695462, -689797, -684223, -678737, -673338, -668024, -662792, -657640, -652568, -647572, -642651, -637803, -633028, -628323, -623686, -619117, -614613, -610174, -605798, -601483, -597229, -593033, -588896, -584815, -580789, -576818, -572901, -569035, -565221, -561456, -557741, -554074, -550455, -546881, -543354, -539870, -536431, -533034, -529680, -526366, -523094, -519861, -516667, -513512, -510394, -507313, -504269, -501261, -498287, -495348, -492443, -489571, -486732, -483925, -481150, -478406, -475692, -473009, -470355, -467730, -465133, -462565, -460024, -457511, -455024, -452564, -450129, -447720, -445337, -442978, -440643, -438332, -436045, -433781, -431540, -429321, -427125, -424951, -422798, -420666, -418555, -416465, -414395, -412344, -410314, -408303, -406311, -404338, -402384, -400448, -398530, -396630, -394747, -392882, -391034, -389202, -387387, -385589, -383807, -382040, -380290, -378555, -376835, -375130, -373440, -371765, -370105, -368459, -366826, -365208, -363604, -362013, -360436, -358872, -357321, -355783, -354257, -352744, -351244, -349756, -348280, -346816, -345364, -343924, -342495, -341078, -339671, -338276, -336892, -335519, -334157, -332805, -331464, -330133, -328812, -327502, -326201, -324910, -323629, -322358, -321097, -319844, -318601, -317368, -316143, -314928, -313721, -312524, -311335, -310154, -308983, -307819, -306664, -305517, -304379, -303248, -302126, -301011, -299904, -298805, -297714, -296630, -295554, -294485, -293423, -292369, -291322, -290282, -289249, -288223, -287204, -286192, -285186, -284188, -283195, -282210, -281231, -280258, -279292, -278332, -277378, -276430, -275489, -274553, -273624, -272700, -271782, -270871, -269965, -269064, -268169, -267280, -266397, -265519, -264646, -263779, -262917, -262060, -261209, -260363, -259522, -258686, -257855, -257029, -256208, -255392, -254581, -253774, -252973, -252176, -251384, -250596, -249813, -249035, -248261, -247492, -246727, -245966, -245210, -244458, -243711, -242967, -242228, -241493, -240763, -240036, -239314, -238595, -237881, -237170, -236463, -235761, -235062, -234367, -233676, -232988, -232304, -231624, -230948, -230275, -229606, -228941, -228279, -227621, -226966, -226314, -225666, -225022, -224381, -223743, -223108, -222477, -221849, -221225, -220603, -219985, -219370, -218758, -218149, -217544, -216941, -216341, -215745, -215151, -214561, -213973, -213389, -212807, -212228, -211652, -211079, -210509, -209941, -209376, -208815, -208255, -207699, -207145, -206594, -206045, -205500, -204956, -204416, -203878, -203342, -202809, -202279, -201751, -201226, -200703, -200182, -199664, -199149, -198636, -198125, -197616, -197110, -196606, -196105, -195606, -195109, -194614, -194122, -193631, -193143, -192658, -192174, -191693, -191213, -190736, -190261, -189789, -189318, -188849, -188382, -187918, -187455, -186995, -186536, -186080, -185625, -185173, -184722, -184274, -183827, -183382, -182939, -182498, -182059, -181622, -181186, -180753, -180321, -179891, -179463, -179037, -178612, -178190, -177769, -177349, -176932, -176516, -176102, -175690, -175279, -174870, -174463, -174057, -173653, -173251, -172850, -172451, -172053, -171657, -171263, -170870, -170479, -170089, -169701, -169315, -168930, -168546, -168164, -167784, -167405, -167027, -166651, -166277, -165904, -165532, -165162, -164793, -164426, -164060, -163695, -163332, -162970, -162610, -162251, -161893, -161537, -161182, -160828, -160476, -160125, -159775, -159427, -159079, -158734, -158389, -158046, -157704, -157363, -157024, -156686, -156349, -156013, -155678, -155345, -155013, -154682, -154352, -154024, -153697, -153370, -153045, -152722, -152399, -152077, -151757, -151438, -151120, -150803, -150487, -150172, -149859, -149546, -149235, -148924, -148615, -148307, -148000, -147693, -147388, -147084, -146782, -146480, -146179, -145879, -145580, -145282, -144986, -144690, -144395, -144101, -143808, -143517, -143226, -142936, -142647, -142359, -142072, -141786, -141501, -141217, -140934, -140651, -140370, -140090, -139810, -139532, -139254, -138977, -138701, -138426, -138152, -137879, -137607, -137335, -137065, -136795, -136526, -136258, -135991, -135725, -135459, -135195, -134931, -134668, -134406, -134145, -133884, -133625, -133366, -133108, -132851, -132594, -132339, -132084, -131830, -131576, -131324, -131072, -130821, -130571, -130322, -130073, -129825, -129578, -129332, -129086, -128841, -128597, -128353, -128111, -127869, -127627, -127387, -127147, -126908, -126669, -126432, -126195, -125959, -125723, -125488, -125254, -125020, -124787, -124555, -124324, -124093, -123863, -123633, -123404, -123176, -122949, -122722, -122496, -122270, -122045, -121821, -121597, -121374, -121152, -120930, -120709, -120489, -120269, -120050, -119831, -119613, -119396, -119179, -118963, -118747, -118532, -118318, -118104, -117891, -117678, -117466, -117254, -117044, -116833, -116623, -116414, -116206, -115998, -115790, -115583, -115377, -115171, -114966, -114761, -114557, -114354, -114151, -113948, -113746, -113545, -113344, -113143, -112944, -112744, -112546, -112347, -112150, -111952, -111756, -111560, -111364, -111169, -110974, -110780, -110586, -110393, -110200, -110008, -109817, -109626, -109435, -109245, -109055, -108866, -108677, -108489, -108301, -108114, -107927, -107741, -107555, -107369, -107184, -107000, -106816, -106632, -106449, -106266, -106084, -105902, -105721, -105540, -105360, -105180, -105000, -104821, -104643, -104465, -104287, -104109, -103933, -103756, -103580, -103404, -103229, -103054, -102880, -102706, -102533, -102360, -102187, -102015, -101843, -101671, -101500, -101330, -101159, -100990, -100820, -100651, -100482, -100314, -100146, -99979, -99812, -99645, -99479, -99313, -99148, -98982, -98818, -98653, -98489, -98326, -98163, -98000, -97837, -97675, -97513, -97352, -97191, -97030, -96870, -96710, -96551, -96391, -96233, -96074, -95916, -95758, -95601, -95444, -95287, -95131, -94975, -94819, -94664, -94509, -94354, -94200, -94046, -93892, -93739, -93586, -93434, -93281, -93129, -92978, -92826, -92675, -92525, -92375, -92225, -92075, -91926, -91777, -91628, -91480, -91332, -91184, -91036, -90889, -90742, -90596, -90450, -90304, -90158, -90013, -89868, -89724, -89579, -89435, -89292, -89148, -89005, -88862, -88720, -88577, -88435, -88294, -88152, -88011, -87871, -87730, -87590, -87450, -87310, -87171, -87032, -86893, -86755, -86616, -86479, -86341, -86204, -86066, -85930, -85793, -85657, -85521, -85385, -85250, -85114, -84980, -84845, -84710, -84576, -84443, -84309, -84176, -84043, -83910, -83777, -83645, -83513, -83381, -83250, -83118, -82987, -82857, -82726, -82596, -82466, -82336, -82207, -82078, -81949, -81820, -81691, -81563, -81435, -81307, -81180, -81053, -80925, -80799, -80672, -80546, -80420, -80294, -80168, -80043, -79918, -79793, -79668, -79544, -79420, -79296, -79172, -79048, -78925, -78802, -78679, -78557, -78434, -78312, -78190, -78068, -77947, -77826, -77705, -77584, -77463, -77343, -77223, -77103, -76983, -76864, -76744, -76625, -76506, -76388, -76269, -76151, -76033, -75915, -75797, -75680, -75563, -75446, -75329, -75213, -75096, -74980, -74864, -74748, -74633, -74517, -74402, -74287, -74172, -74058, -73944, -73829, -73715, -73602, -73488, -73375, -73262, -73149, -73036, -72923, -72811, -72699, -72587, -72475, -72363, -72252, -72140, -72029, -71918, -71808, -71697, -71587, -71477, -71367, -71257, -71147, -71038, -70929, -70820, -70711, -70602, -70494, -70385, -70277, -70169, -70061, -69954, -69846, -69739, -69632, -69525, -69418, -69312, -69205, -69099, -68993, -68887, -68781, -68676, -68570, -68465, -68360, -68255, -68151, -68046, -67942, -67837, -67733, -67629, -67526, -67422, -67319, -67216, -67113, -67010, -66907, -66804, -66702, -66600, -66498, -66396, -66294, -66192, -66091, -65989, -65888, -65787, -65686, -65586, -65485, -65385, -65285, -65185, -65085, -64985, -64885, -64786, -64687, -64587, -64488, -64389, -64291, -64192, -64094, -63996, -63897, -63799, -63702, -63604, -63506, -63409, -63312, -63215, -63118, -63021, -62924, -62828, -62731, -62635, -62539, -62443, -62347, -62251, -62156, -62060, -61965, -61870, -61775, -61680, -61585, -61491, -61396, -61302, -61208, -61114, -61020, -60926, -60833, -60739, -60646, -60552, -60459, -60366, -60273, -60181, -60088, -59996, -59903, -59811, -59719, -59627, -59535, -59444, -59352, -59261, -59169, -59078, -58987, -58896, -58805, -58715, -58624, -58534, -58443, -58353, -58263, -58173, -58083, -57994, -57904, -57815, -57725, -57636, -57547, -57458, -57369, -57281, -57192, -57104, -57015, -56927, -56839, -56751, -56663, -56575, -56487, -56400, -56312, -56225, -56138, -56051, -55964, -55877, -55790, -55704, -55617, -55531, -55444, -55358, -55272, -55186, -55100, -55015, -54929, -54843, -54758, -54673, -54587, -54502, -54417, -54333, -54248, -54163, -54079, -53994, -53910, -53826, -53741, -53657, -53574, -53490, -53406, -53322, -53239, -53156, -53072, -52989, -52906, -52823, -52740, -52657, -52575, -52492, -52410, -52327, -52245, -52163, -52081, -51999, -51917, -51835, -51754, -51672, -51591, -51509, -51428, -51347, -51266, -51185, -51104, -51023, -50942, -50862, -50781, -50701, -50621, -50540, -50460, -50380, -50300, -50221, -50141, -50061, -49982, -49902, -49823, -49744, -49664, -49585, -49506, -49427, -49349, -49270, -49191, -49113, -49034, -48956, -48878, -48799, -48721, -48643, -48565, -48488, -48410, -48332, -48255, -48177, -48100, -48022, -47945, -47868, -47791, -47714, -47637, -47560, -47484, -47407, -47331, -47254, -47178, -47102, -47025, -46949, -46873, -46797, -46721, -46646, -46570, -46494, -46419, -46343, -46268, -46193, -46118, -46042, -45967, -45892, -45818, -45743, -45668, -45593, -45519, -45444, -45370, -45296, -45221, -45147, -45073, -44999, -44925, -44851, -44778, -44704, -44630, -44557, -44483, -44410, -44337, -44263, -44190, -44117, -44044, -43971, -43898, -43826, -43753, -43680, -43608, -43535, -43463, -43390, -43318, -43246, -43174, -43102, -43030, -42958, -42886, -42814, -42743, -42671, -42600, -42528, -42457, -42385, -42314, -42243, -42172, -42101, -42030, -41959, -41888, -41817, -41747, -41676, -41605, -41535, -41465, -41394, -41324, -41254, -41184, -41113, -41043, -40973, -40904, -40834, -40764, -40694, -40625, -40555, -40486, -40416, -40347, -40278, -40208, -40139, -40070, -40001, -39932, -39863, -39794, -39726, -39657, -39588, -39520, -39451, -39383, -39314, -39246, -39178, -39110, -39042, -38973, -38905, -38837, -38770, -38702, -38634, -38566, -38499, -38431, -38364, -38296, -38229, -38161, -38094, -38027, -37960, -37893, -37826, -37759, -37692, -37625, -37558, -37491, -37425, -37358, -37291, -37225, -37158, -37092, -37026, -36959, -36893, -36827, -36761, -36695, -36629, -36563, -36497, -36431, -36365, -36300, -36234, -36168, -36103, -36037, -35972, -35907, -35841, -35776, -35711, -35646, -35580, -35515, -35450, -35385, -35321, -35256, -35191, -35126, -35062, -34997, -34932, -34868, -34803, -34739, -34675, -34610, -34546, -34482, -34418, -34354, -34289, -34225, -34162, -34098, -34034, -33970, -33906, -33843, -33779, -33715, -33652, -33588, -33525, -33461, -33398, -33335, -33272, -33208, -33145, -33082, -33019, -32956, -32893, -32830, -32767, -32705, -32642, -32579, -32516, -32454, -32391, -32329, -32266, -32204, -32141, -32079, -32017, -31955, -31892, -31830, -31768, -31706, -31644, -31582, -31520, -31458, -31396, -31335, -31273, -31211, -31150, -31088, -31026, -30965, -30904, -30842, -30781, -30719, -30658, -30597, -30536, -30474, -30413, -30352, -30291, -30230, -30169, -30108, -30048, -29987, -29926, -29865, -29805, -29744, -29683, -29623, -29562, -29502, -29441, -29381, -29321, -29260, -29200, -29140, -29080, -29020, -28959, -28899, -28839, -28779, -28719, -28660, -28600, -28540, -28480, -28420, -28361, -28301, -28241, -28182, -28122, -28063, -28003, -27944, -27884, -27825, -27766, -27707, -27647, -27588, -27529, -27470, -27411, -27352, -27293, -27234, -27175, -27116, -27057, -26998, -26940, -26881, -26822, -26763, -26705, -26646, -26588, -26529, -26471, -26412, -26354, -26295, -26237, -26179, -26120, -26062, -26004, -25946, -25888, -25830, -25772, -25714, -25656, -25598, -25540, -25482, -25424, -25366, -25308, -25251, -25193, -25135, -25078, -25020, -24962, -24905, -24847, -24790, -24732, -24675, -24618, -24560, -24503, -24446, -24389, -24331, -24274, -24217, -24160, -24103, -24046, -23989, -23932, -23875, -23818, -23761, -23704, -23647, -23591, -23534, -23477, -23420, -23364, -23307, -23250, -23194, -23137, -23081, -23024, -22968, -22911, -22855, -22799, -22742, -22686, -22630, -22573, -22517, -22461, -22405, -22349, -22293, -22237, -22181, -22125, -22069, -22013, -21957, -21901, -21845, -21789, -21733, -21678, -21622, -21566, -21510, -21455, -21399, -21343, -21288, -21232, -21177, -21121, -21066, -21010, -20955, -20900, -20844, -20789, -20734, -20678, -20623, -20568, -20513, -20457, -20402, -20347, -20292, -20237, -20182, -20127, -20072, -20017, -19962, -19907, -19852, -19797, -19742, -19688, -19633, -19578, -19523, -19469, -19414, -19359, -19305, -19250, -19195, -19141, -19086, -19032, -18977, -18923, -18868, -18814, -18760, -18705, -18651, -18597, -18542, -18488, -18434, -18380, -18325, -18271, -18217, -18163, -18109, -18055, -18001, -17946, -17892, -17838, -17784, -17731, -17677, -17623, -17569, -17515, -17461, -17407, -17353, -17300, -17246, -17192, -17138, -17085, -17031, -16977, -16924, -16870, -16817, -16763, -16710, -16656, -16603, -16549, -16496, -16442, -16389, -16335, -16282, -16229, -16175, -16122, -16069, -16015, -15962, -15909, -15856, -15802, -15749, -15696, -15643, -15590, -15537, -15484, -15431, -15378, -15325, -15272, -15219, -15166, -15113, -15060, -15007, -14954, -14901, -14848, -14795, -14743, -14690, -14637, -14584, -14531, -14479, -14426, -14373, -14321, -14268, -14215, -14163, -14110, -14057, -14005, -13952, -13900, -13847, -13795, -13742, -13690, -13637, -13585, -13533, -13480, -13428, -13375, -13323, -13271, -13218, -13166, -13114, -13062, -13009, -12957, -12905, -12853, -12800, -12748, -12696, -12644, -12592, -12540, -12488, -12436, -12383, -12331, -12279, -12227, -12175, -12123, -12071, -12019, -11967, -11916, -11864, -11812, -11760, -11708, -11656, -11604, -11552, -11501, -11449, -11397, -11345, -11293, -11242, -11190, -11138, -11086, -11035, -10983, -10931, -10880, -10828, -10777, -10725, -10673, -10622, -10570, -10519, -10467, -10415, -10364, -10312, -10261, -10209, -10158, -10106, -10055, -10004, -9952, -9901, -9849, -9798, -9747, -9695, -9644, -9592, -9541, -9490, -9438, -9387, -9336, -9285, -9233, -9182, -9131, -9080, -9028, -8977, -8926, -8875, -8824, -8772, -8721, -8670, -8619, -8568, -8517, -8466, -8414, -8363, -8312, -8261, -8210, -8159, -8108, -8057, -8006, -7955, -7904, -7853, -7802, -7751, -7700, -7649, -7598, -7547, -7496, -7445, -7395, -7344, -7293, -7242, -7191, -7140, -7089, -7038, -6988, -6937, -6886, -6835, -6784, -6733, -6683, -6632, -6581, -6530, -6480, -6429, -6378, -6327, -6277, -6226, -6175, -6124, -6074, -6023, -5972, -5922, -5871, -5820, -5770, -5719, -5668, -5618, -5567, -5517, -5466, -5415, -5365, -5314, -5264, -5213, -5162, -5112, -5061, -5011, -4960, -4910, -4859, -4808, -4758, -4707, -4657, -4606, -4556, -4505, -4455, -4404, -4354, -4303, -4253, -4202, -4152, -4101, -4051, -4001, -3950, -3900, -3849, -3799, -3748, -3698, -3648, -3597, -3547, -3496, -3446, -3395, -3345, -3295, -3244, -3194, -3144, -3093, -3043, -2992, -2942, -2892, -2841, -2791, -2741, -2690, -2640, -2590, -2539, -2489, -2439, -2388, -2338, -2288, -2237, -2187, -2137, -2086, -2036, -1986, -1935, -1885, -1835, -1784, -1734, -1684, -1633, -1583, -1533, -1483, -1432, -1382, -1332, -1281, -1231, -1181, -1131, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1131, 1181, 1231, 1281, 1332, 1382, 1432, 1483, 1533, 1583, 1633, 1684, 1734, 1784, 1835, 1885, 1935, 1986, 2036, 2086, 2137, 2187, 2237, 2288, 2338, 2388, 2439, 2489, 2539, 2590, 2640, 2690, 2741, 2791, 2841, 2892, 2942, 2992, 3043, 3093, 3144, 3194, 3244, 3295, 3345, 3395, 3446, 3496, 3547, 3597, 3648, 3698, 3748, 3799, 3849, 3900, 3950, 4001, 4051, 4101, 4152, 4202, 4253, 4303, 4354, 4404, 4455, 4505, 4556, 4606, 4657, 4707, 4758, 4808, 4859, 4910, 4960, 5011, 5061, 5112, 5162, 5213, 5264, 5314, 5365, 5415, 5466, 5517, 5567, 5618, 5668, 5719, 5770, 5820, 5871, 5922, 5972, 6023, 6074, 6124, 6175, 6226, 6277, 6327, 6378, 6429, 6480, 6530, 6581, 6632, 6683, 6733, 6784, 6835, 6886, 6937, 6988, 7038, 7089, 7140, 7191, 7242, 7293, 7344, 7395, 7445, 7496, 7547, 7598, 7649, 7700, 7751, 7802, 7853, 7904, 7955, 8006, 8057, 8108, 8159, 8210, 8261, 8312, 8363, 8414, 8466, 8517, 8568, 8619, 8670, 8721, 8772, 8824, 8875, 8926, 8977, 9028, 9080, 9131, 9182, 9233, 9285, 9336, 9387, 9438, 9490, 9541, 9592, 9644, 9695, 9747, 9798, 9849, 9901, 9952, 10004, 10055, 10106, 10158, 10209, 10261, 10312, 10364, 10415, 10467, 10519, 10570, 10622, 10673, 10725, 10777, 10828, 10880, 10931, 10983, 11035, 11086, 11138, 11190, 11242, 11293, 11345, 11397, 11449, 11501, 11552, 11604, 11656, 11708, 11760, 11812, 11864, 11916, 11967, 12019, 12071, 12123, 12175, 12227, 12279, 12331, 12383, 12436, 12488, 12540, 12592, 12644, 12696, 12748, 12800, 12853, 12905, 12957, 13009, 13062, 13114, 13166, 13218, 13271, 13323, 13375, 13428, 13480, 13533, 13585, 13637, 13690, 13742, 13795, 13847, 13900, 13952, 14005, 14057, 14110, 14163, 14215, 14268, 14321, 14373, 14426, 14479, 14531, 14584, 14637, 14690, 14743, 14795, 14848, 14901, 14954, 15007, 15060, 15113, 15166, 15219, 15272, 15325, 15378, 15431, 15484, 15537, 15590, 15643, 15696, 15749, 15802, 15856, 15909, 15962, 16015, 16069, 16122, 16175, 16229, 16282, 16335, 16389, 16442, 16496, 16549, 16603, 16656, 16710, 16763, 16817, 16870, 16924, 16977, 17031, 17085, 17138, 17192, 17246, 17300, 17353, 17407, 17461, 17515, 17569, 17623, 17677, 17731, 17784, 17838, 17892, 17946, 18001, 18055, 18109, 18163, 18217, 18271, 18325, 18380, 18434, 18488, 18542, 18597, 18651, 18705, 18760, 18814, 18868, 18923, 18977, 19032, 19086, 19141, 19195, 19250, 19305, 19359, 19414, 19469, 19523, 19578, 19633, 19688, 19742, 19797, 19852, 19907, 19962, 20017, 20072, 20127, 20182, 20237, 20292, 20347, 20402, 20457, 20513, 20568, 20623, 20678, 20734, 20789, 20844, 20900, 20955, 21010, 21066, 21121, 21177, 21232, 21288, 21343, 21399, 21455, 21510, 21566, 21622, 21678, 21733, 21789, 21845, 21901, 21957, 22013, 22069, 22125, 22181, 22237, 22293, 22349, 22405, 22461, 22517, 22573, 22630, 22686, 22742, 22799, 22855, 22911, 22968, 23024, 23081, 23137, 23194, 23250, 23307, 23364, 23420, 23477, 23534, 23591, 23647, 23704, 23761, 23818, 23875, 23932, 23989, 24046, 24103, 24160, 24217, 24274, 24331, 24389, 24446, 24503, 24560, 24618, 24675, 24732, 24790, 24847, 24905, 24962, 25020, 25078, 25135, 25193, 25251, 25308, 25366, 25424, 25482, 25540, 25598, 25656, 25714, 25772, 25830, 25888, 25946, 26004, 26062, 26120, 26179, 26237, 26295, 26354, 26412, 26471, 26529, 26588, 26646, 26705, 26763, 26822, 26881, 26940, 26998, 27057, 27116, 27175, 27234, 27293, 27352, 27411, 27470, 27529, 27588, 27647, 27707, 27766, 27825, 27884, 27944, 28003, 28063, 28122, 28182, 28241, 28301, 28361, 28420, 28480, 28540, 28600, 28660, 28719, 28779, 28839, 28899, 28959, 29020, 29080, 29140, 29200, 29260, 29321, 29381, 29441, 29502, 29562, 29623, 29683, 29744, 29805, 29865, 29926, 29987, 30048, 30108, 30169, 30230, 30291, 30352, 30413, 30474, 30536, 30597, 30658, 30719, 30781, 30842, 30904, 30965, 31026, 31088, 31150, 31211, 31273, 31335, 31396, 31458, 31520, 31582, 31644, 31706, 31768, 31830, 31892, 31955, 32017, 32079, 32141, 32204, 32266, 32329, 32391, 32454, 32516, 32579, 32642, 32705, 32767, 32830, 32893, 32956, 33019, 33082, 33145, 33208, 33272, 33335, 33398, 33461, 33525, 33588, 33652, 33715, 33779, 33843, 33906, 33970, 34034, 34098, 34162, 34225, 34289, 34354, 34418, 34482, 34546, 34610, 34675, 34739, 34803, 34868, 34932, 34997, 35062, 35126, 35191, 35256, 35321, 35385, 35450, 35515, 35580, 35646, 35711, 35776, 35841, 35907, 35972, 36037, 36103, 36168, 36234, 36300, 36365, 36431, 36497, 36563, 36629, 36695, 36761, 36827, 36893, 36959, 37026, 37092, 37158, 37225, 37291, 37358, 37425, 37491, 37558, 37625, 37692, 37759, 37826, 37893, 37960, 38027, 38094, 38161, 38229, 38296, 38364, 38431, 38499, 38566, 38634, 38702, 38770, 38837, 38905, 38973, 39042, 39110, 39178, 39246, 39314, 39383, 39451, 39520, 39588, 39657, 39726, 39794, 39863, 39932, 40001, 40070, 40139, 40208, 40278, 40347, 40416, 40486, 40555, 40625, 40694, 40764, 40834, 40904, 40973, 41043, 41113, 41184, 41254, 41324, 41394, 41465, 41535, 41605, 41676, 41747, 41817, 41888, 41959, 42030, 42101, 42172, 42243, 42314, 42385, 42457, 42528, 42600, 42671, 42743, 42814, 42886, 42958, 43030, 43102, 43174, 43246, 43318, 43390, 43463, 43535, 43608, 43680, 43753, 43826, 43898, 43971, 44044, 44117, 44190, 44263, 44337, 44410, 44483, 44557, 44630, 44704, 44778, 44851, 44925, 44999, 45073, 45147, 45221, 45296, 45370, 45444, 45519, 45593, 45668, 45743, 45818, 45892, 45967, 46042, 46118, 46193, 46268, 46343, 46419, 46494, 46570, 46646, 46721, 46797, 46873, 46949, 47025, 47102, 47178, 47254, 47331, 47407, 47484, 47560, 47637, 47714, 47791, 47868, 47945, 48022, 48100, 48177, 48255, 48332, 48410, 48488, 48565, 48643, 48721, 48799, 48878, 48956, 49034, 49113, 49191, 49270, 49349, 49427, 49506, 49585, 49664, 49744, 49823, 49902, 49982, 50061, 50141, 50221, 50300, 50380, 50460, 50540, 50621, 50701, 50781, 50862, 50942, 51023, 51104, 51185, 51266, 51347, 51428, 51509, 51591, 51672, 51754, 51835, 51917, 51999, 52081, 52163, 52245, 52327, 52410, 52492, 52575, 52657, 52740, 52823, 52906, 52989, 53072, 53156, 53239, 53322, 53406, 53490, 53574, 53657, 53741, 53826, 53910, 53994, 54079, 54163, 54248, 54333, 54417, 54502, 54587, 54673, 54758, 54843, 54929, 55015, 55100, 55186, 55272, 55358, 55444, 55531, 55617, 55704, 55790, 55877, 55964, 56051, 56138, 56225, 56312, 56400, 56487, 56575, 56663, 56751, 56839, 56927, 57015, 57104, 57192, 57281, 57369, 57458, 57547, 57636, 57725, 57815, 57904, 57994, 58083, 58173, 58263, 58353, 58443, 58534, 58624, 58715, 58805, 58896, 58987, 59078, 59169, 59261, 59352, 59444, 59535, 59627, 59719, 59811, 59903, 59996, 60088, 60181, 60273, 60366, 60459, 60552, 60646, 60739, 60833, 60926, 61020, 61114, 61208, 61302, 61396, 61491, 61585, 61680, 61775, 61870, 61965, 62060, 62156, 62251, 62347, 62443, 62539, 62635, 62731, 62828, 62924, 63021, 63118, 63215, 63312, 63409, 63506, 63604, 63702, 63799, 63897, 63996, 64094, 64192, 64291, 64389, 64488, 64587, 64687, 64786, 64885, 64985, 65085, 65185, 65285, 65385, 65485, 65586, 65686, 65787, 65888, 65989, 66091, 66192, 66294, 66396, 66498, 66600, 66702, 66804, 66907, 67010, 67113, 67216, 67319, 67422, 67526, 67629, 67733, 67837, 67942, 68046, 68151, 68255, 68360, 68465, 68570, 68676, 68781, 68887, 68993, 69099, 69205, 69312, 69418, 69525, 69632, 69739, 69846, 69954, 70061, 70169, 70277, 70385, 70494, 70602, 70711, 70820, 70929, 71038, 71147, 71257, 71367, 71477, 71587, 71697, 71808, 71918, 72029, 72140, 72252, 72363, 72475, 72587, 72699, 72811, 72923, 73036, 73149, 73262, 73375, 73488, 73602, 73715, 73829, 73944, 74058, 74172, 74287, 74402, 74517, 74633, 74748, 74864, 74980, 75096, 75213, 75329, 75446, 75563, 75680, 75797, 75915, 76033, 76151, 76269, 76388, 76506, 76625, 76744, 76864, 76983, 77103, 77223, 77343, 77463, 77584, 77705, 77826, 77947, 78068, 78190, 78312, 78434, 78557, 78679, 78802, 78925, 79048, 79172, 79296, 79420, 79544, 79668, 79793, 79918, 80043, 80168, 80294, 80420, 80546, 80672, 80799, 80925, 81053, 81180, 81307, 81435, 81563, 81691, 81820, 81949, 82078, 82207, 82336, 82466, 82596, 82726, 82857, 82987, 83118, 83250, 83381, 83513, 83645, 83777, 83910, 84043, 84176, 84309, 84443, 84576, 84710, 84845, 84980, 85114, 85250, 85385, 85521, 85657, 85793, 85930, 86066, 86204, 86341, 86479, 86616, 86755, 86893, 87032, 87171, 87310, 87450, 87590, 87730, 87871, 88011, 88152, 88294, 88435, 88577, 88720, 88862, 89005, 89148, 89292, 89435, 89579, 89724, 89868, 90013, 90158, 90304, 90450, 90596, 90742, 90889, 91036, 91184, 91332, 91480, 91628, 91777, 91926, 92075, 92225, 92375, 92525, 92675, 92826, 92978, 93129, 93281, 93434, 93586, 93739, 93892, 94046, 94200, 94354, 94509, 94664, 94819, 94975, 95131, 95287, 95444, 95601, 95758, 95916, 96074, 96233, 96391, 96551, 96710, 96870, 97030, 97191, 97352, 97513, 97675, 97837, 98000, 98163, 98326, 98489, 98653, 98818, 98982, 99148, 99313, 99479, 99645, 99812, 99979, 100146, 100314, 100482, 100651, 100820, 100990, 101159, 101330, 101500, 101671, 101843, 102015, 102187, 102360, 102533, 102706, 102880, 103054, 103229, 103404, 103580, 103756, 103933, 104109, 104287, 104465, 104643, 104821, 105000, 105180, 105360, 105540, 105721, 105902, 106084, 106266, 106449, 106632, 106816, 107000, 107184, 107369, 107555, 107741, 107927, 108114, 108301, 108489, 108677, 108866, 109055, 109245, 109435, 109626, 109817, 110008, 110200, 110393, 110586, 110780, 110974, 111169, 111364, 111560, 111756, 111952, 112150, 112347, 112546, 112744, 112944, 113143, 113344, 113545, 113746, 113948, 114151, 114354, 114557, 114761, 114966, 115171, 115377, 115583, 115790, 115998, 116206, 116414, 116623, 116833, 117044, 117254, 117466, 117678, 117891, 118104, 118318, 118532, 118747, 118963, 119179, 119396, 119613, 119831, 120050, 120269, 120489, 120709, 120930, 121152, 121374, 121597, 121821, 122045, 122270, 122496, 122722, 122949, 123176, 123404, 123633, 123863, 124093, 124324, 124555, 124787, 125020, 125254, 125488, 125723, 125959, 126195, 126432, 126669, 126908, 127147, 127387, 127627, 127869, 128111, 128353, 128597, 128841, 129086, 129332, 129578, 129825, 130073, 130322, 130571, 130821, 131072, 131324, 131576, 131830, 132084, 132339, 132594, 132851, 133108, 133366, 133625, 133884, 134145, 134406, 134668, 134931, 135195, 135459, 135725, 135991, 136258, 136526, 136795, 137065, 137335, 137607, 137879, 138152, 138426, 138701, 138977, 139254, 139532, 139810, 140090, 140370, 140651, 140934, 141217, 141501, 141786, 142072, 142359, 142647, 142936, 143226, 143517, 143808, 144101, 144395, 144690, 144986, 145282, 145580, 145879, 146179, 146480, 146782, 147084, 147388, 147693, 148000, 148307, 148615, 148924, 149235, 149546, 149859, 150172, 150487, 150803, 151120, 151438, 151757, 152077, 152399, 152722, 153045, 153370, 153697, 154024, 154352, 154682, 155013, 155345, 155678, 156013, 156349, 156686, 157024, 157363, 157704, 158046, 158389, 158734, 159079, 159427, 159775, 160125, 160476, 160828, 161182, 161537, 161893, 162251, 162610, 162970, 163332, 163695, 164060, 164426, 164793, 165162, 165532, 165904, 166277, 166651, 167027, 167405, 167784, 168164, 168546, 168930, 169315, 169701, 170089, 170479, 170870, 171263, 171657, 172053, 172451, 172850, 173251, 173653, 174057, 174463, 174870, 175279, 175690, 176102, 176516, 176932, 177349, 177769, 178190, 178612, 179037, 179463, 179891, 180321, 180753, 181186, 181622, 182059, 182498, 182939, 183382, 183827, 184274, 184722, 185173, 185625, 186080, 186536, 186995, 187455, 187918, 188382, 188849, 189318, 189789, 190261, 190736, 191213, 191693, 192174, 192658, 193143, 193631, 194122, 194614, 195109, 195606, 196105, 196606, 197110, 197616, 198125, 198636, 199149, 199664, 200182, 200703, 201226, 201751, 202279, 202809, 203342, 203878, 204416, 204956, 205500, 206045, 206594, 207145, 207699, 208255, 208815, 209376, 209941, 210509, 211079, 211652, 212228, 212807, 213389, 213973, 214561, 215151, 215745, 216341, 216941, 217544, 218149, 218758, 219370, 219985, 220603, 221225, 221849, 222477, 223108, 223743, 224381, 225022, 225666, 226314, 226966, 227621, 228279, 228941, 229606, 230275, 230948, 231624, 232304, 232988, 233676, 234367, 235062, 235761, 236463, 237170, 237881, 238595, 239314, 240036, 240763, 241493, 242228, 242967, 243711, 244458, 245210, 245966, 246727, 247492, 248261, 249035, 249813, 250596, 251384, 252176, 252973, 253774, 254581, 255392, 256208, 257029, 257855, 258686, 259522, 260363, 261209, 262060, 262917, 263779, 264646, 265519, 266397, 267280, 268169, 269064, 269965, 270871, 271782, 272700, 273624, 274553, 275489, 276430, 277378, 278332, 279292, 280258, 281231, 282210, 283195, 284188, 285186, 286192, 287204, 288223, 289249, 290282, 291322, 292369, 293423, 294485, 295554, 296630, 297714, 298805, 299904, 301011, 302126, 303248, 304379, 305517, 306664, 307819, 308983, 310154, 311335, 312524, 313721, 314928, 316143, 317368, 318601, 319844, 321097, 322358, 323629, 324910, 326201, 327502, 328812, 330133, 331464, 332805, 334157, 335519, 336892, 338276, 339671, 341078, 342495, 343924, 345364, 346816, 348280, 349756, 351244, 352744, 354257, 355783, 357321, 358872, 360436, 362013, 363604, 365208, 366826, 368459, 370105, 371765, 373440, 375130, 376835, 378555, 380290, 382040, 383807, 385589, 387387, 389202, 391034, 392882, 394747, 396630, 398530, 400448, 402384, 404338, 406311, 408303, 410314, 412344, 414395, 416465, 418555, 420666, 422798, 424951, 427125, 429321, 431540, 433781, 436045, 438332, 440643, 442978, 445337, 447720, 450129, 452564, 455024, 457511, 460024, 462565, 465133, 467730, 470355, 473009, 475692, 478406, 481150, 483925, 486732, 489571, 492443, 495348, 498287, 501261, 504269, 507313, 510394, 513512, 516667, 519861, 523094, 526366, 529680, 533034, 536431, 539870, 543354, 546881, 550455, 554074, 557741, 561456, 565221, 569035, 572901, 576818, 580789, 584815, 588896, 593033, 597229, 601483, 605798, 610174, 614613, 619117, 623686, 628323, 633028, 637803, 642651, 647572, 652568, 657640, 662792, 668024, 673338, 678737, 684223, 689797, 695462, 701219, 707072, 713023, 719074, 725227, 731486, 737853, 744331, 750922, 757631, 764460, 771411, 778490, 785699, 793041, 800521, 808143, 815910, 823827, 831898, 840127, 848520, 857081, 865817, 874730, 883829, 893117, 902602, 912289, 922186, 932298, 942633, 953199, 964003, 975054, 986361, 997931, 1009774, 1021901, 1034322, 1047046, 1060087, 1073455, 1087164, 1101225, 1115654, 1130465, 1145673, 1161294, 1177345, 1193846, 1210813, 1228269, 1246234, 1264730, 1283783, 1303416, 1323658, 1344537, 1366084, 1388330, 1411312, 1435065, 1459630, 1485049, 1511367, 1538632, 1566898, 1596220, 1626658, 1658278, 1691149, 1725348, 1760956, 1798063, 1836758, 1877161, 1919378, 1963536, 2009771, 2058233, 2109087, 2162516, 2218719, 2277919, 2340362, 2406322, 2476104, 2550052, 2628549, 2712030, 2800983, 2895966, 2997613, 3106651, 3223918, 3350381, 3487165, 3635590, 3797206, 3973855, 4167737, 4381502, 4618375, 4882318, 5178251, 5512368, 5892567, 6329090, 6835455, 7429880, 8137527, 8994149, 10052327, 11392683, 13145455, 15535599, 18988036, 24413316, 34178904, 56965752, 170910304 }; int finesine[10240] = { 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3541, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5748, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22433, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30426, 30471, 30515, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36555, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40300, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47860, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50065, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53911, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54308, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64601, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65534, 65534, 65534, 65533, 65533, 65532, 65532, 65531, 65531, 65530, 65530, 65529, 65528, 65527, 65527, 65526, 65525, 65524, 65523, 65522, 65521, 65520, 65519, 65518, 65516, 65515, 65514, 65513, 65511, 65510, 65508, 65507, 65505, 65504, 65502, 65501, 65499, 65497, 65496, 65494, 65492, 65490, 65488, 65486, 65484, 65482, 65480, 65478, 65476, 65474, 65472, 65470, 65467, 65465, 65463, 65460, 65458, 65455, 65453, 65450, 65448, 65445, 65442, 65440, 65437, 65434, 65431, 65429, 65426, 65423, 65420, 65417, 65414, 65411, 65408, 65404, 65401, 65398, 65395, 65391, 65388, 65385, 65381, 65378, 65374, 65371, 65367, 65363, 65360, 65356, 65352, 65349, 65345, 65341, 65337, 65333, 65329, 65325, 65321, 65317, 65313, 65309, 65305, 65300, 65296, 65292, 65287, 65283, 65279, 65274, 65270, 65265, 65260, 65256, 65251, 65246, 65242, 65237, 65232, 65227, 65222, 65217, 65212, 65207, 65202, 65197, 65192, 65187, 65182, 65177, 65171, 65166, 65161, 65155, 65150, 65144, 65139, 65133, 65128, 65122, 65117, 65111, 65105, 65099, 65094, 65088, 65082, 65076, 65070, 65064, 65058, 65052, 65046, 65040, 65033, 65027, 65021, 65015, 65008, 65002, 64995, 64989, 64982, 64976, 64969, 64963, 64956, 64949, 64943, 64936, 64929, 64922, 64915, 64908, 64902, 64895, 64887, 64880, 64873, 64866, 64859, 64852, 64844, 64837, 64830, 64822, 64815, 64808, 64800, 64793, 64785, 64777, 64770, 64762, 64754, 64747, 64739, 64731, 64723, 64715, 64707, 64699, 64691, 64683, 64675, 64667, 64659, 64651, 64642, 64634, 64626, 64617, 64609, 64600, 64592, 64584, 64575, 64566, 64558, 64549, 64540, 64532, 64523, 64514, 64505, 64496, 64487, 64478, 64469, 64460, 64451, 64442, 64433, 64424, 64414, 64405, 64396, 64387, 64377, 64368, 64358, 64349, 64339, 64330, 64320, 64310, 64301, 64291, 64281, 64271, 64261, 64252, 64242, 64232, 64222, 64212, 64202, 64192, 64181, 64171, 64161, 64151, 64140, 64130, 64120, 64109, 64099, 64088, 64078, 64067, 64057, 64046, 64035, 64025, 64014, 64003, 63992, 63981, 63971, 63960, 63949, 63938, 63927, 63915, 63904, 63893, 63882, 63871, 63859, 63848, 63837, 63825, 63814, 63803, 63791, 63779, 63768, 63756, 63745, 63733, 63721, 63709, 63698, 63686, 63674, 63662, 63650, 63638, 63626, 63614, 63602, 63590, 63578, 63565, 63553, 63541, 63528, 63516, 63504, 63491, 63479, 63466, 63454, 63441, 63429, 63416, 63403, 63390, 63378, 63365, 63352, 63339, 63326, 63313, 63300, 63287, 63274, 63261, 63248, 63235, 63221, 63208, 63195, 63182, 63168, 63155, 63141, 63128, 63114, 63101, 63087, 63074, 63060, 63046, 63032, 63019, 63005, 62991, 62977, 62963, 62949, 62935, 62921, 62907, 62893, 62879, 62865, 62850, 62836, 62822, 62808, 62793, 62779, 62764, 62750, 62735, 62721, 62706, 62692, 62677, 62662, 62648, 62633, 62618, 62603, 62588, 62573, 62558, 62543, 62528, 62513, 62498, 62483, 62468, 62453, 62437, 62422, 62407, 62391, 62376, 62360, 62345, 62329, 62314, 62298, 62283, 62267, 62251, 62236, 62220, 62204, 62188, 62172, 62156, 62141, 62125, 62108, 62092, 62076, 62060, 62044, 62028, 62012, 61995, 61979, 61963, 61946, 61930, 61913, 61897, 61880, 61864, 61847, 61831, 61814, 61797, 61780, 61764, 61747, 61730, 61713, 61696, 61679, 61662, 61645, 61628, 61611, 61594, 61577, 61559, 61542, 61525, 61507, 61490, 61473, 61455, 61438, 61420, 61403, 61385, 61367, 61350, 61332, 61314, 61297, 61279, 61261, 61243, 61225, 61207, 61189, 61171, 61153, 61135, 61117, 61099, 61081, 61062, 61044, 61026, 61007, 60989, 60971, 60952, 60934, 60915, 60897, 60878, 60859, 60841, 60822, 60803, 60785, 60766, 60747, 60728, 60709, 60690, 60671, 60652, 60633, 60614, 60595, 60576, 60556, 60537, 60518, 60499, 60479, 60460, 60441, 60421, 60402, 60382, 60363, 60343, 60323, 60304, 60284, 60264, 60244, 60225, 60205, 60185, 60165, 60145, 60125, 60105, 60085, 60065, 60045, 60025, 60004, 59984, 59964, 59944, 59923, 59903, 59883, 59862, 59842, 59821, 59801, 59780, 59759, 59739, 59718, 59697, 59677, 59656, 59635, 59614, 59593, 59572, 59551, 59530, 59509, 59488, 59467, 59446, 59425, 59404, 59382, 59361, 59340, 59318, 59297, 59276, 59254, 59233, 59211, 59190, 59168, 59146, 59125, 59103, 59081, 59059, 59038, 59016, 58994, 58972, 58950, 58928, 58906, 58884, 58862, 58840, 58818, 58795, 58773, 58751, 58729, 58706, 58684, 58662, 58639, 58617, 58594, 58572, 58549, 58527, 58504, 58481, 58459, 58436, 58413, 58390, 58367, 58345, 58322, 58299, 58276, 58253, 58230, 58207, 58183, 58160, 58137, 58114, 58091, 58067, 58044, 58021, 57997, 57974, 57950, 57927, 57903, 57880, 57856, 57833, 57809, 57785, 57762, 57738, 57714, 57690, 57666, 57642, 57618, 57594, 57570, 57546, 57522, 57498, 57474, 57450, 57426, 57402, 57377, 57353, 57329, 57304, 57280, 57255, 57231, 57206, 57182, 57157, 57133, 57108, 57083, 57059, 57034, 57009, 56984, 56959, 56935, 56910, 56885, 56860, 56835, 56810, 56785, 56760, 56734, 56709, 56684, 56659, 56633, 56608, 56583, 56557, 56532, 56507, 56481, 56456, 56430, 56404, 56379, 56353, 56328, 56302, 56276, 56250, 56225, 56199, 56173, 56147, 56121, 56095, 56069, 56043, 56017, 55991, 55965, 55938, 55912, 55886, 55860, 55833, 55807, 55781, 55754, 55728, 55701, 55675, 55648, 55622, 55595, 55569, 55542, 55515, 55489, 55462, 55435, 55408, 55381, 55354, 55327, 55300, 55274, 55246, 55219, 55192, 55165, 55138, 55111, 55084, 55056, 55029, 55002, 54974, 54947, 54920, 54892, 54865, 54837, 54810, 54782, 54755, 54727, 54699, 54672, 54644, 54616, 54588, 54560, 54533, 54505, 54477, 54449, 54421, 54393, 54365, 54337, 54308, 54280, 54252, 54224, 54196, 54167, 54139, 54111, 54082, 54054, 54026, 53997, 53969, 53940, 53911, 53883, 53854, 53826, 53797, 53768, 53739, 53711, 53682, 53653, 53624, 53595, 53566, 53537, 53508, 53479, 53450, 53421, 53392, 53363, 53334, 53304, 53275, 53246, 53216, 53187, 53158, 53128, 53099, 53069, 53040, 53010, 52981, 52951, 52922, 52892, 52862, 52832, 52803, 52773, 52743, 52713, 52683, 52653, 52624, 52594, 52564, 52534, 52503, 52473, 52443, 52413, 52383, 52353, 52322, 52292, 52262, 52231, 52201, 52171, 52140, 52110, 52079, 52049, 52018, 51988, 51957, 51926, 51896, 51865, 51834, 51803, 51773, 51742, 51711, 51680, 51649, 51618, 51587, 51556, 51525, 51494, 51463, 51432, 51401, 51369, 51338, 51307, 51276, 51244, 51213, 51182, 51150, 51119, 51087, 51056, 51024, 50993, 50961, 50929, 50898, 50866, 50834, 50803, 50771, 50739, 50707, 50675, 50644, 50612, 50580, 50548, 50516, 50484, 50452, 50420, 50387, 50355, 50323, 50291, 50259, 50226, 50194, 50162, 50129, 50097, 50065, 50032, 50000, 49967, 49935, 49902, 49869, 49837, 49804, 49771, 49739, 49706, 49673, 49640, 49608, 49575, 49542, 49509, 49476, 49443, 49410, 49377, 49344, 49311, 49278, 49244, 49211, 49178, 49145, 49112, 49078, 49045, 49012, 48978, 48945, 48911, 48878, 48844, 48811, 48777, 48744, 48710, 48676, 48643, 48609, 48575, 48542, 48508, 48474, 48440, 48406, 48372, 48338, 48304, 48271, 48237, 48202, 48168, 48134, 48100, 48066, 48032, 47998, 47963, 47929, 47895, 47860, 47826, 47792, 47757, 47723, 47688, 47654, 47619, 47585, 47550, 47516, 47481, 47446, 47412, 47377, 47342, 47308, 47273, 47238, 47203, 47168, 47133, 47098, 47063, 47028, 46993, 46958, 46923, 46888, 46853, 46818, 46783, 46747, 46712, 46677, 46642, 46606, 46571, 46536, 46500, 46465, 46429, 46394, 46358, 46323, 46287, 46252, 46216, 46180, 46145, 46109, 46073, 46037, 46002, 45966, 45930, 45894, 45858, 45822, 45786, 45750, 45714, 45678, 45642, 45606, 45570, 45534, 45498, 45462, 45425, 45389, 45353, 45316, 45280, 45244, 45207, 45171, 45135, 45098, 45062, 45025, 44989, 44952, 44915, 44879, 44842, 44806, 44769, 44732, 44695, 44659, 44622, 44585, 44548, 44511, 44474, 44437, 44400, 44363, 44326, 44289, 44252, 44215, 44178, 44141, 44104, 44067, 44029, 43992, 43955, 43918, 43880, 43843, 43806, 43768, 43731, 43693, 43656, 43618, 43581, 43543, 43506, 43468, 43430, 43393, 43355, 43317, 43280, 43242, 43204, 43166, 43128, 43091, 43053, 43015, 42977, 42939, 42901, 42863, 42825, 42787, 42749, 42711, 42672, 42634, 42596, 42558, 42520, 42481, 42443, 42405, 42366, 42328, 42290, 42251, 42213, 42174, 42136, 42097, 42059, 42020, 41982, 41943, 41904, 41866, 41827, 41788, 41750, 41711, 41672, 41633, 41595, 41556, 41517, 41478, 41439, 41400, 41361, 41322, 41283, 41244, 41205, 41166, 41127, 41088, 41048, 41009, 40970, 40931, 40891, 40852, 40813, 40773, 40734, 40695, 40655, 40616, 40576, 40537, 40497, 40458, 40418, 40379, 40339, 40300, 40260, 40220, 40180, 40141, 40101, 40061, 40021, 39982, 39942, 39902, 39862, 39822, 39782, 39742, 39702, 39662, 39622, 39582, 39542, 39502, 39462, 39422, 39382, 39341, 39301, 39261, 39221, 39180, 39140, 39100, 39059, 39019, 38979, 38938, 38898, 38857, 38817, 38776, 38736, 38695, 38655, 38614, 38573, 38533, 38492, 38451, 38411, 38370, 38329, 38288, 38248, 38207, 38166, 38125, 38084, 38043, 38002, 37961, 37920, 37879, 37838, 37797, 37756, 37715, 37674, 37633, 37592, 37551, 37509, 37468, 37427, 37386, 37344, 37303, 37262, 37220, 37179, 37137, 37096, 37055, 37013, 36972, 36930, 36889, 36847, 36805, 36764, 36722, 36681, 36639, 36597, 36556, 36514, 36472, 36430, 36388, 36347, 36305, 36263, 36221, 36179, 36137, 36095, 36053, 36011, 35969, 35927, 35885, 35843, 35801, 35759, 35717, 35675, 35633, 35590, 35548, 35506, 35464, 35421, 35379, 35337, 35294, 35252, 35210, 35167, 35125, 35082, 35040, 34997, 34955, 34912, 34870, 34827, 34785, 34742, 34699, 34657, 34614, 34571, 34529, 34486, 34443, 34400, 34358, 34315, 34272, 34229, 34186, 34143, 34100, 34057, 34015, 33972, 33929, 33886, 33843, 33799, 33756, 33713, 33670, 33627, 33584, 33541, 33498, 33454, 33411, 33368, 33325, 33281, 33238, 33195, 33151, 33108, 33065, 33021, 32978, 32934, 32891, 32847, 32804, 32760, 32717, 32673, 32630, 32586, 32542, 32499, 32455, 32411, 32368, 32324, 32280, 32236, 32193, 32149, 32105, 32061, 32017, 31974, 31930, 31886, 31842, 31798, 31754, 31710, 31666, 31622, 31578, 31534, 31490, 31446, 31402, 31357, 31313, 31269, 31225, 31181, 31136, 31092, 31048, 31004, 30959, 30915, 30871, 30826, 30782, 30738, 30693, 30649, 30604, 30560, 30515, 30471, 30426, 30382, 30337, 30293, 30248, 30204, 30159, 30114, 30070, 30025, 29980, 29936, 29891, 29846, 29801, 29757, 29712, 29667, 29622, 29577, 29533, 29488, 29443, 29398, 29353, 29308, 29263, 29218, 29173, 29128, 29083, 29038, 28993, 28948, 28903, 28858, 28812, 28767, 28722, 28677, 28632, 28586, 28541, 28496, 28451, 28405, 28360, 28315, 28269, 28224, 28179, 28133, 28088, 28042, 27997, 27952, 27906, 27861, 27815, 27770, 27724, 27678, 27633, 27587, 27542, 27496, 27450, 27405, 27359, 27313, 27268, 27222, 27176, 27131, 27085, 27039, 26993, 26947, 26902, 26856, 26810, 26764, 26718, 26672, 26626, 26580, 26534, 26488, 26442, 26396, 26350, 26304, 26258, 26212, 26166, 26120, 26074, 26028, 25982, 25936, 25889, 25843, 25797, 25751, 25705, 25658, 25612, 25566, 25520, 25473, 25427, 25381, 25334, 25288, 25241, 25195, 25149, 25102, 25056, 25009, 24963, 24916, 24870, 24823, 24777, 24730, 24684, 24637, 24591, 24544, 24497, 24451, 24404, 24357, 24311, 24264, 24217, 24171, 24124, 24077, 24030, 23984, 23937, 23890, 23843, 23796, 23750, 23703, 23656, 23609, 23562, 23515, 23468, 23421, 23374, 23327, 23280, 23233, 23186, 23139, 23092, 23045, 22998, 22951, 22904, 22857, 22810, 22763, 22716, 22668, 22621, 22574, 22527, 22480, 22433, 22385, 22338, 22291, 22243, 22196, 22149, 22102, 22054, 22007, 21960, 21912, 21865, 21817, 21770, 21723, 21675, 21628, 21580, 21533, 21485, 21438, 21390, 21343, 21295, 21248, 21200, 21153, 21105, 21057, 21010, 20962, 20915, 20867, 20819, 20772, 20724, 20676, 20629, 20581, 20533, 20485, 20438, 20390, 20342, 20294, 20246, 20199, 20151, 20103, 20055, 20007, 19959, 19912, 19864, 19816, 19768, 19720, 19672, 19624, 19576, 19528, 19480, 19432, 19384, 19336, 19288, 19240, 19192, 19144, 19096, 19048, 19000, 18951, 18903, 18855, 18807, 18759, 18711, 18663, 18614, 18566, 18518, 18470, 18421, 18373, 18325, 18277, 18228, 18180, 18132, 18084, 18035, 17987, 17939, 17890, 17842, 17793, 17745, 17697, 17648, 17600, 17551, 17503, 17455, 17406, 17358, 17309, 17261, 17212, 17164, 17115, 17067, 17018, 16970, 16921, 16872, 16824, 16775, 16727, 16678, 16629, 16581, 16532, 16484, 16435, 16386, 16338, 16289, 16240, 16191, 16143, 16094, 16045, 15997, 15948, 15899, 15850, 15802, 15753, 15704, 15655, 15606, 15557, 15509, 15460, 15411, 15362, 15313, 15264, 15215, 15167, 15118, 15069, 15020, 14971, 14922, 14873, 14824, 14775, 14726, 14677, 14628, 14579, 14530, 14481, 14432, 14383, 14334, 14285, 14236, 14187, 14138, 14089, 14040, 13990, 13941, 13892, 13843, 13794, 13745, 13696, 13646, 13597, 13548, 13499, 13450, 13401, 13351, 13302, 13253, 13204, 13154, 13105, 13056, 13007, 12957, 12908, 12859, 12810, 12760, 12711, 12662, 12612, 12563, 12514, 12464, 12415, 12366, 12316, 12267, 12218, 12168, 12119, 12069, 12020, 11970, 11921, 11872, 11822, 11773, 11723, 11674, 11624, 11575, 11525, 11476, 11426, 11377, 11327, 11278, 11228, 11179, 11129, 11080, 11030, 10981, 10931, 10882, 10832, 10782, 10733, 10683, 10634, 10584, 10534, 10485, 10435, 10386, 10336, 10286, 10237, 10187, 10137, 10088, 10038, 9988, 9939, 9889, 9839, 9790, 9740, 9690, 9640, 9591, 9541, 9491, 9442, 9392, 9342, 9292, 9243, 9193, 9143, 9093, 9043, 8994, 8944, 8894, 8844, 8794, 8745, 8695, 8645, 8595, 8545, 8496, 8446, 8396, 8346, 8296, 8246, 8196, 8147, 8097, 8047, 7997, 7947, 7897, 7847, 7797, 7747, 7697, 7648, 7598, 7548, 7498, 7448, 7398, 7348, 7298, 7248, 7198, 7148, 7098, 7048, 6998, 6948, 6898, 6848, 6798, 6748, 6698, 6648, 6598, 6548, 6498, 6448, 6398, 6348, 6298, 6248, 6198, 6148, 6098, 6048, 5998, 5948, 5898, 5848, 5798, 5748, 5697, 5647, 5597, 5547, 5497, 5447, 5397, 5347, 5297, 5247, 5197, 5146, 5096, 5046, 4996, 4946, 4896, 4846, 4796, 4745, 4695, 4645, 4595, 4545, 4495, 4445, 4394, 4344, 4294, 4244, 4194, 4144, 4093, 4043, 3993, 3943, 3893, 3843, 3792, 3742, 3692, 3642, 3592, 3541, 3491, 3441, 3391, 3341, 3291, 3240, 3190, 3140, 3090, 3039, 2989, 2939, 2889, 2839, 2788, 2738, 2688, 2638, 2587, 2537, 2487, 2437, 2387, 2336, 2286, 2236, 2186, 2135, 2085, 2035, 1985, 1934, 1884, 1834, 1784, 1733, 1683, 1633, 1583, 1532, 1482, 1432, 1382, 1331, 1281, 1231, 1181, 1130, 1080, 1030, 980, 929, 879, 829, 779, 728, 678, 628, 578, 527, 477, 427, 376, 326, 276, 226, 175, 125, 75, 25, -25, -75, -125, -175, -226, -276, -326, -376, -427, -477, -527, -578, -628, -678, -728, -779, -829, -879, -929, -980, -1030, -1080, -1130, -1181, -1231, -1281, -1331, -1382, -1432, -1482, -1532, -1583, -1633, -1683, -1733, -1784, -1834, -1884, -1934, -1985, -2035, -2085, -2135, -2186, -2236, -2286, -2336, -2387, -2437, -2487, -2537, -2588, -2638, -2688, -2738, -2788, -2839, -2889, -2939, -2989, -3039, -3090, -3140, -3190, -3240, -3291, -3341, -3391, -3441, -3491, -3541, -3592, -3642, -3692, -3742, -3792, -3843, -3893, -3943, -3993, -4043, -4093, -4144, -4194, -4244, -4294, -4344, -4394, -4445, -4495, -4545, -4595, -4645, -4695, -4745, -4796, -4846, -4896, -4946, -4996, -5046, -5096, -5146, -5197, -5247, -5297, -5347, -5397, -5447, -5497, -5547, -5597, -5647, -5697, -5748, -5798, -5848, -5898, -5948, -5998, -6048, -6098, -6148, -6198, -6248, -6298, -6348, -6398, -6448, -6498, -6548, -6598, -6648, -6698, -6748, -6798, -6848, -6898, -6948, -6998, -7048, -7098, -7148, -7198, -7248, -7298, -7348, -7398, -7448, -7498, -7548, -7598, -7648, -7697, -7747, -7797, -7847, -7897, -7947, -7997, -8047, -8097, -8147, -8196, -8246, -8296, -8346, -8396, -8446, -8496, -8545, -8595, -8645, -8695, -8745, -8794, -8844, -8894, -8944, -8994, -9043, -9093, -9143, -9193, -9243, -9292, -9342, -9392, -9442, -9491, -9541, -9591, -9640, -9690, -9740, -9790, -9839, -9889, -9939, -9988, -10038, -10088, -10137, -10187, -10237, -10286, -10336, -10386, -10435, -10485, -10534, -10584, -10634, -10683, -10733, -10782, -10832, -10882, -10931, -10981, -11030, -11080, -11129, -11179, -11228, -11278, -11327, -11377, -11426, -11476, -11525, -11575, -11624, -11674, -11723, -11773, -11822, -11872, -11921, -11970, -12020, -12069, -12119, -12168, -12218, -12267, -12316, -12366, -12415, -12464, -12514, -12563, -12612, -12662, -12711, -12760, -12810, -12859, -12908, -12957, -13007, -13056, -13105, -13154, -13204, -13253, -13302, -13351, -13401, -13450, -13499, -13548, -13597, -13647, -13696, -13745, -13794, -13843, -13892, -13941, -13990, -14040, -14089, -14138, -14187, -14236, -14285, -14334, -14383, -14432, -14481, -14530, -14579, -14628, -14677, -14726, -14775, -14824, -14873, -14922, -14971, -15020, -15069, -15118, -15167, -15215, -15264, -15313, -15362, -15411, -15460, -15509, -15557, -15606, -15655, -15704, -15753, -15802, -15850, -15899, -15948, -15997, -16045, -16094, -16143, -16191, -16240, -16289, -16338, -16386, -16435, -16484, -16532, -16581, -16629, -16678, -16727, -16775, -16824, -16872, -16921, -16970, -17018, -17067, -17115, -17164, -17212, -17261, -17309, -17358, -17406, -17455, -17503, -17551, -17600, -17648, -17697, -17745, -17793, -17842, -17890, -17939, -17987, -18035, -18084, -18132, -18180, -18228, -18277, -18325, -18373, -18421, -18470, -18518, -18566, -18614, -18663, -18711, -18759, -18807, -18855, -18903, -18951, -19000, -19048, -19096, -19144, -19192, -19240, -19288, -19336, -19384, -19432, -19480, -19528, -19576, -19624, -19672, -19720, -19768, -19816, -19864, -19912, -19959, -20007, -20055, -20103, -20151, -20199, -20246, -20294, -20342, -20390, -20438, -20485, -20533, -20581, -20629, -20676, -20724, -20772, -20819, -20867, -20915, -20962, -21010, -21057, -21105, -21153, -21200, -21248, -21295, -21343, -21390, -21438, -21485, -21533, -21580, -21628, -21675, -21723, -21770, -21817, -21865, -21912, -21960, -22007, -22054, -22102, -22149, -22196, -22243, -22291, -22338, -22385, -22433, -22480, -22527, -22574, -22621, -22668, -22716, -22763, -22810, -22857, -22904, -22951, -22998, -23045, -23092, -23139, -23186, -23233, -23280, -23327, -23374, -23421, -23468, -23515, -23562, -23609, -23656, -23703, -23750, -23796, -23843, -23890, -23937, -23984, -24030, -24077, -24124, -24171, -24217, -24264, -24311, -24357, -24404, -24451, -24497, -24544, -24591, -24637, -24684, -24730, -24777, -24823, -24870, -24916, -24963, -25009, -25056, -25102, -25149, -25195, -25241, -25288, -25334, -25381, -25427, -25473, -25520, -25566, -25612, -25658, -25705, -25751, -25797, -25843, -25889, -25936, -25982, -26028, -26074, -26120, -26166, -26212, -26258, -26304, -26350, -26396, -26442, -26488, -26534, -26580, -26626, -26672, -26718, -26764, -26810, -26856, -26902, -26947, -26993, -27039, -27085, -27131, -27176, -27222, -27268, -27313, -27359, -27405, -27450, -27496, -27542, -27587, -27633, -27678, -27724, -27770, -27815, -27861, -27906, -27952, -27997, -28042, -28088, -28133, -28179, -28224, -28269, -28315, -28360, -28405, -28451, -28496, -28541, -28586, -28632, -28677, -28722, -28767, -28812, -28858, -28903, -28948, -28993, -29038, -29083, -29128, -29173, -29218, -29263, -29308, -29353, -29398, -29443, -29488, -29533, -29577, -29622, -29667, -29712, -29757, -29801, -29846, -29891, -29936, -29980, -30025, -30070, -30114, -30159, -30204, -30248, -30293, -30337, -30382, -30426, -30471, -30515, -30560, -30604, -30649, -30693, -30738, -30782, -30826, -30871, -30915, -30959, -31004, -31048, -31092, -31136, -31181, -31225, -31269, -31313, -31357, -31402, -31446, -31490, -31534, -31578, -31622, -31666, -31710, -31754, -31798, -31842, -31886, -31930, -31974, -32017, -32061, -32105, -32149, -32193, -32236, -32280, -32324, -32368, -32411, -32455, -32499, -32542, -32586, -32630, -32673, -32717, -32760, -32804, -32847, -32891, -32934, -32978, -33021, -33065, -33108, -33151, -33195, -33238, -33281, -33325, -33368, -33411, -33454, -33498, -33541, -33584, -33627, -33670, -33713, -33756, -33799, -33843, -33886, -33929, -33972, -34015, -34057, -34100, -34143, -34186, -34229, -34272, -34315, -34358, -34400, -34443, -34486, -34529, -34571, -34614, -34657, -34699, -34742, -34785, -34827, -34870, -34912, -34955, -34997, -35040, -35082, -35125, -35167, -35210, -35252, -35294, -35337, -35379, -35421, -35464, -35506, -35548, -35590, -35633, -35675, -35717, -35759, -35801, -35843, -35885, -35927, -35969, -36011, -36053, -36095, -36137, -36179, -36221, -36263, -36305, -36347, -36388, -36430, -36472, -36514, -36555, -36597, -36639, -36681, -36722, -36764, -36805, -36847, -36889, -36930, -36972, -37013, -37055, -37096, -37137, -37179, -37220, -37262, -37303, -37344, -37386, -37427, -37468, -37509, -37551, -37592, -37633, -37674, -37715, -37756, -37797, -37838, -37879, -37920, -37961, -38002, -38043, -38084, -38125, -38166, -38207, -38248, -38288, -38329, -38370, -38411, -38451, -38492, -38533, -38573, -38614, -38655, -38695, -38736, -38776, -38817, -38857, -38898, -38938, -38979, -39019, -39059, -39100, -39140, -39180, -39221, -39261, -39301, -39341, -39382, -39422, -39462, -39502, -39542, -39582, -39622, -39662, -39702, -39742, -39782, -39822, -39862, -39902, -39942, -39982, -40021, -40061, -40101, -40141, -40180, -40220, -40260, -40299, -40339, -40379, -40418, -40458, -40497, -40537, -40576, -40616, -40655, -40695, -40734, -40773, -40813, -40852, -40891, -40931, -40970, -41009, -41048, -41087, -41127, -41166, -41205, -41244, -41283, -41322, -41361, -41400, -41439, -41478, -41517, -41556, -41595, -41633, -41672, -41711, -41750, -41788, -41827, -41866, -41904, -41943, -41982, -42020, -42059, -42097, -42136, -42174, -42213, -42251, -42290, -42328, -42366, -42405, -42443, -42481, -42520, -42558, -42596, -42634, -42672, -42711, -42749, -42787, -42825, -42863, -42901, -42939, -42977, -43015, -43053, -43091, -43128, -43166, -43204, -43242, -43280, -43317, -43355, -43393, -43430, -43468, -43506, -43543, -43581, -43618, -43656, -43693, -43731, -43768, -43806, -43843, -43880, -43918, -43955, -43992, -44029, -44067, -44104, -44141, -44178, -44215, -44252, -44289, -44326, -44363, -44400, -44437, -44474, -44511, -44548, -44585, -44622, -44659, -44695, -44732, -44769, -44806, -44842, -44879, -44915, -44952, -44989, -45025, -45062, -45098, -45135, -45171, -45207, -45244, -45280, -45316, -45353, -45389, -45425, -45462, -45498, -45534, -45570, -45606, -45642, -45678, -45714, -45750, -45786, -45822, -45858, -45894, -45930, -45966, -46002, -46037, -46073, -46109, -46145, -46180, -46216, -46252, -46287, -46323, -46358, -46394, -46429, -46465, -46500, -46536, -46571, -46606, -46642, -46677, -46712, -46747, -46783, -46818, -46853, -46888, -46923, -46958, -46993, -47028, -47063, -47098, -47133, -47168, -47203, -47238, -47273, -47308, -47342, -47377, -47412, -47446, -47481, -47516, -47550, -47585, -47619, -47654, -47688, -47723, -47757, -47792, -47826, -47860, -47895, -47929, -47963, -47998, -48032, -48066, -48100, -48134, -48168, -48202, -48236, -48271, -48304, -48338, -48372, -48406, -48440, -48474, -48508, -48542, -48575, -48609, -48643, -48676, -48710, -48744, -48777, -48811, -48844, -48878, -48911, -48945, -48978, -49012, -49045, -49078, -49112, -49145, -49178, -49211, -49244, -49278, -49311, -49344, -49377, -49410, -49443, -49476, -49509, -49542, -49575, -49608, -49640, -49673, -49706, -49739, -49771, -49804, -49837, -49869, -49902, -49935, -49967, -50000, -50032, -50065, -50097, -50129, -50162, -50194, -50226, -50259, -50291, -50323, -50355, -50387, -50420, -50452, -50484, -50516, -50548, -50580, -50612, -50644, -50675, -50707, -50739, -50771, -50803, -50834, -50866, -50898, -50929, -50961, -50993, -51024, -51056, -51087, -51119, -51150, -51182, -51213, -51244, -51276, -51307, -51338, -51369, -51401, -51432, -51463, -51494, -51525, -51556, -51587, -51618, -51649, -51680, -51711, -51742, -51773, -51803, -51834, -51865, -51896, -51926, -51957, -51988, -52018, -52049, -52079, -52110, -52140, -52171, -52201, -52231, -52262, -52292, -52322, -52353, -52383, -52413, -52443, -52473, -52503, -52534, -52564, -52594, -52624, -52653, -52683, -52713, -52743, -52773, -52803, -52832, -52862, -52892, -52922, -52951, -52981, -53010, -53040, -53069, -53099, -53128, -53158, -53187, -53216, -53246, -53275, -53304, -53334, -53363, -53392, -53421, -53450, -53479, -53508, -53537, -53566, -53595, -53624, -53653, -53682, -53711, -53739, -53768, -53797, -53826, -53854, -53883, -53911, -53940, -53969, -53997, -54026, -54054, -54082, -54111, -54139, -54167, -54196, -54224, -54252, -54280, -54308, -54337, -54365, -54393, -54421, -54449, -54477, -54505, -54533, -54560, -54588, -54616, -54644, -54672, -54699, -54727, -54755, -54782, -54810, -54837, -54865, -54892, -54920, -54947, -54974, -55002, -55029, -55056, -55084, -55111, -55138, -55165, -55192, -55219, -55246, -55274, -55300, -55327, -55354, -55381, -55408, -55435, -55462, -55489, -55515, -55542, -55569, -55595, -55622, -55648, -55675, -55701, -55728, -55754, -55781, -55807, -55833, -55860, -55886, -55912, -55938, -55965, -55991, -56017, -56043, -56069, -56095, -56121, -56147, -56173, -56199, -56225, -56250, -56276, -56302, -56328, -56353, -56379, -56404, -56430, -56456, -56481, -56507, -56532, -56557, -56583, -56608, -56633, -56659, -56684, -56709, -56734, -56760, -56785, -56810, -56835, -56860, -56885, -56910, -56935, -56959, -56984, -57009, -57034, -57059, -57083, -57108, -57133, -57157, -57182, -57206, -57231, -57255, -57280, -57304, -57329, -57353, -57377, -57402, -57426, -57450, -57474, -57498, -57522, -57546, -57570, -57594, -57618, -57642, -57666, -57690, -57714, -57738, -57762, -57785, -57809, -57833, -57856, -57880, -57903, -57927, -57950, -57974, -57997, -58021, -58044, -58067, -58091, -58114, -58137, -58160, -58183, -58207, -58230, -58253, -58276, -58299, -58322, -58345, -58367, -58390, -58413, -58436, -58459, -58481, -58504, -58527, -58549, -58572, -58594, -58617, -58639, -58662, -58684, -58706, -58729, -58751, -58773, -58795, -58818, -58840, -58862, -58884, -58906, -58928, -58950, -58972, -58994, -59016, -59038, -59059, -59081, -59103, -59125, -59146, -59168, -59190, -59211, -59233, -59254, -59276, -59297, -59318, -59340, -59361, -59382, -59404, -59425, -59446, -59467, -59488, -59509, -59530, -59551, -59572, -59593, -59614, -59635, -59656, -59677, -59697, -59718, -59739, -59759, -59780, -59801, -59821, -59842, -59862, -59883, -59903, -59923, -59944, -59964, -59984, -60004, -60025, -60045, -60065, -60085, -60105, -60125, -60145, -60165, -60185, -60205, -60225, -60244, -60264, -60284, -60304, -60323, -60343, -60363, -60382, -60402, -60421, -60441, -60460, -60479, -60499, -60518, -60537, -60556, -60576, -60595, -60614, -60633, -60652, -60671, -60690, -60709, -60728, -60747, -60766, -60785, -60803, -60822, -60841, -60859, -60878, -60897, -60915, -60934, -60952, -60971, -60989, -61007, -61026, -61044, -61062, -61081, -61099, -61117, -61135, -61153, -61171, -61189, -61207, -61225, -61243, -61261, -61279, -61297, -61314, -61332, -61350, -61367, -61385, -61403, -61420, -61438, -61455, -61473, -61490, -61507, -61525, -61542, -61559, -61577, -61594, -61611, -61628, -61645, -61662, -61679, -61696, -61713, -61730, -61747, -61764, -61780, -61797, -61814, -61831, -61847, -61864, -61880, -61897, -61913, -61930, -61946, -61963, -61979, -61995, -62012, -62028, -62044, -62060, -62076, -62092, -62108, -62125, -62141, -62156, -62172, -62188, -62204, -62220, -62236, -62251, -62267, -62283, -62298, -62314, -62329, -62345, -62360, -62376, -62391, -62407, -62422, -62437, -62453, -62468, -62483, -62498, -62513, -62528, -62543, -62558, -62573, -62588, -62603, -62618, -62633, -62648, -62662, -62677, -62692, -62706, -62721, -62735, -62750, -62764, -62779, -62793, -62808, -62822, -62836, -62850, -62865, -62879, -62893, -62907, -62921, -62935, -62949, -62963, -62977, -62991, -63005, -63019, -63032, -63046, -63060, -63074, -63087, -63101, -63114, -63128, -63141, -63155, -63168, -63182, -63195, -63208, -63221, -63235, -63248, -63261, -63274, -63287, -63300, -63313, -63326, -63339, -63352, -63365, -63378, -63390, -63403, -63416, -63429, -63441, -63454, -63466, -63479, -63491, -63504, -63516, -63528, -63541, -63553, -63565, -63578, -63590, -63602, -63614, -63626, -63638, -63650, -63662, -63674, -63686, -63698, -63709, -63721, -63733, -63745, -63756, -63768, -63779, -63791, -63803, -63814, -63825, -63837, -63848, -63859, -63871, -63882, -63893, -63904, -63915, -63927, -63938, -63949, -63960, -63971, -63981, -63992, -64003, -64014, -64025, -64035, -64046, -64057, -64067, -64078, -64088, -64099, -64109, -64120, -64130, -64140, -64151, -64161, -64171, -64181, -64192, -64202, -64212, -64222, -64232, -64242, -64252, -64261, -64271, -64281, -64291, -64301, -64310, -64320, -64330, -64339, -64349, -64358, -64368, -64377, -64387, -64396, -64405, -64414, -64424, -64433, -64442, -64451, -64460, -64469, -64478, -64487, -64496, -64505, -64514, -64523, -64532, -64540, -64549, -64558, -64566, -64575, -64584, -64592, -64601, -64609, -64617, -64626, -64634, -64642, -64651, -64659, -64667, -64675, -64683, -64691, -64699, -64707, -64715, -64723, -64731, -64739, -64747, -64754, -64762, -64770, -64777, -64785, -64793, -64800, -64808, -64815, -64822, -64830, -64837, -64844, -64852, -64859, -64866, -64873, -64880, -64887, -64895, -64902, -64908, -64915, -64922, -64929, -64936, -64943, -64949, -64956, -64963, -64969, -64976, -64982, -64989, -64995, -65002, -65008, -65015, -65021, -65027, -65033, -65040, -65046, -65052, -65058, -65064, -65070, -65076, -65082, -65088, -65094, -65099, -65105, -65111, -65117, -65122, -65128, -65133, -65139, -65144, -65150, -65155, -65161, -65166, -65171, -65177, -65182, -65187, -65192, -65197, -65202, -65207, -65212, -65217, -65222, -65227, -65232, -65237, -65242, -65246, -65251, -65256, -65260, -65265, -65270, -65274, -65279, -65283, -65287, -65292, -65296, -65300, -65305, -65309, -65313, -65317, -65321, -65325, -65329, -65333, -65337, -65341, -65345, -65349, -65352, -65356, -65360, -65363, -65367, -65371, -65374, -65378, -65381, -65385, -65388, -65391, -65395, -65398, -65401, -65404, -65408, -65411, -65414, -65417, -65420, -65423, -65426, -65429, -65431, -65434, -65437, -65440, -65442, -65445, -65448, -65450, -65453, -65455, -65458, -65460, -65463, -65465, -65467, -65470, -65472, -65474, -65476, -65478, -65480, -65482, -65484, -65486, -65488, -65490, -65492, -65494, -65496, -65497, -65499, -65501, -65502, -65504, -65505, -65507, -65508, -65510, -65511, -65513, -65514, -65515, -65516, -65518, -65519, -65520, -65521, -65522, -65523, -65524, -65525, -65526, -65527, -65527, -65528, -65529, -65530, -65530, -65531, -65531, -65532, -65532, -65533, -65533, -65534, -65534, -65534, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65535, -65534, -65534, -65534, -65533, -65533, -65532, -65532, -65531, -65531, -65530, -65530, -65529, -65528, -65527, -65527, -65526, -65525, -65524, -65523, -65522, -65521, -65520, -65519, -65518, -65516, -65515, -65514, -65513, -65511, -65510, -65508, -65507, -65505, -65504, -65502, -65501, -65499, -65497, -65496, -65494, -65492, -65490, -65488, -65486, -65484, -65482, -65480, -65478, -65476, -65474, -65472, -65470, -65467, -65465, -65463, -65460, -65458, -65455, -65453, -65450, -65448, -65445, -65442, -65440, -65437, -65434, -65431, -65429, -65426, -65423, -65420, -65417, -65414, -65411, -65408, -65404, -65401, -65398, -65395, -65391, -65388, -65385, -65381, -65378, -65374, -65371, -65367, -65363, -65360, -65356, -65352, -65349, -65345, -65341, -65337, -65333, -65329, -65325, -65321, -65317, -65313, -65309, -65305, -65300, -65296, -65292, -65287, -65283, -65279, -65274, -65270, -65265, -65260, -65256, -65251, -65246, -65242, -65237, -65232, -65227, -65222, -65217, -65212, -65207, -65202, -65197, -65192, -65187, -65182, -65177, -65171, -65166, -65161, -65155, -65150, -65144, -65139, -65133, -65128, -65122, -65117, -65111, -65105, -65099, -65094, -65088, -65082, -65076, -65070, -65064, -65058, -65052, -65046, -65040, -65033, -65027, -65021, -65015, -65008, -65002, -64995, -64989, -64982, -64976, -64969, -64963, -64956, -64949, -64943, -64936, -64929, -64922, -64915, -64908, -64902, -64895, -64887, -64880, -64873, -64866, -64859, -64852, -64844, -64837, -64830, -64822, -64815, -64808, -64800, -64793, -64785, -64777, -64770, -64762, -64754, -64747, -64739, -64731, -64723, -64715, -64707, -64699, -64691, -64683, -64675, -64667, -64659, -64651, -64642, -64634, -64626, -64617, -64609, -64601, -64592, -64584, -64575, -64566, -64558, -64549, -64540, -64532, -64523, -64514, -64505, -64496, -64487, -64478, -64469, -64460, -64451, -64442, -64433, -64424, -64414, -64405, -64396, -64387, -64377, -64368, -64358, -64349, -64339, -64330, -64320, -64310, -64301, -64291, -64281, -64271, -64261, -64252, -64242, -64232, -64222, -64212, -64202, -64192, -64181, -64171, -64161, -64151, -64140, -64130, -64120, -64109, -64099, -64088, -64078, -64067, -64057, -64046, -64035, -64025, -64014, -64003, -63992, -63981, -63971, -63960, -63949, -63938, -63927, -63915, -63904, -63893, -63882, -63871, -63859, -63848, -63837, -63825, -63814, -63803, -63791, -63779, -63768, -63756, -63745, -63733, -63721, -63709, -63698, -63686, -63674, -63662, -63650, -63638, -63626, -63614, -63602, -63590, -63578, -63565, -63553, -63541, -63528, -63516, -63504, -63491, -63479, -63466, -63454, -63441, -63429, -63416, -63403, -63390, -63378, -63365, -63352, -63339, -63326, -63313, -63300, -63287, -63274, -63261, -63248, -63235, -63221, -63208, -63195, -63182, -63168, -63155, -63141, -63128, -63114, -63101, -63087, -63074, -63060, -63046, -63032, -63019, -63005, -62991, -62977, -62963, -62949, -62935, -62921, -62907, -62893, -62879, -62865, -62850, -62836, -62822, -62808, -62793, -62779, -62764, -62750, -62735, -62721, -62706, -62692, -62677, -62662, -62648, -62633, -62618, -62603, -62588, -62573, -62558, -62543, -62528, -62513, -62498, -62483, -62468, -62453, -62437, -62422, -62407, -62391, -62376, -62360, -62345, -62329, -62314, -62298, -62283, -62267, -62251, -62236, -62220, -62204, -62188, -62172, -62156, -62141, -62125, -62108, -62092, -62076, -62060, -62044, -62028, -62012, -61995, -61979, -61963, -61946, -61930, -61913, -61897, -61880, -61864, -61847, -61831, -61814, -61797, -61780, -61764, -61747, -61730, -61713, -61696, -61679, -61662, -61645, -61628, -61611, -61594, -61577, -61559, -61542, -61525, -61507, -61490, -61473, -61455, -61438, -61420, -61403, -61385, -61367, -61350, -61332, -61314, -61297, -61279, -61261, -61243, -61225, -61207, -61189, -61171, -61153, -61135, -61117, -61099, -61081, -61062, -61044, -61026, -61007, -60989, -60971, -60952, -60934, -60915, -60897, -60878, -60859, -60841, -60822, -60803, -60785, -60766, -60747, -60728, -60709, -60690, -60671, -60652, -60633, -60614, -60595, -60576, -60556, -60537, -60518, -60499, -60479, -60460, -60441, -60421, -60402, -60382, -60363, -60343, -60323, -60304, -60284, -60264, -60244, -60225, -60205, -60185, -60165, -60145, -60125, -60105, -60085, -60065, -60045, -60025, -60004, -59984, -59964, -59944, -59923, -59903, -59883, -59862, -59842, -59821, -59801, -59780, -59759, -59739, -59718, -59697, -59677, -59656, -59635, -59614, -59593, -59572, -59551, -59530, -59509, -59488, -59467, -59446, -59425, -59404, -59382, -59361, -59340, -59318, -59297, -59276, -59254, -59233, -59211, -59189, -59168, -59146, -59125, -59103, -59081, -59059, -59038, -59016, -58994, -58972, -58950, -58928, -58906, -58884, -58862, -58840, -58818, -58795, -58773, -58751, -58729, -58706, -58684, -58662, -58639, -58617, -58594, -58572, -58549, -58527, -58504, -58481, -58459, -58436, -58413, -58390, -58367, -58345, -58322, -58299, -58276, -58253, -58230, -58207, -58183, -58160, -58137, -58114, -58091, -58067, -58044, -58021, -57997, -57974, -57950, -57927, -57903, -57880, -57856, -57833, -57809, -57785, -57762, -57738, -57714, -57690, -57666, -57642, -57618, -57594, -57570, -57546, -57522, -57498, -57474, -57450, -57426, -57402, -57377, -57353, -57329, -57304, -57280, -57255, -57231, -57206, -57182, -57157, -57133, -57108, -57083, -57059, -57034, -57009, -56984, -56959, -56935, -56910, -56885, -56860, -56835, -56810, -56785, -56760, -56734, -56709, -56684, -56659, -56633, -56608, -56583, -56557, -56532, -56507, -56481, -56456, -56430, -56404, -56379, -56353, -56328, -56302, -56276, -56250, -56225, -56199, -56173, -56147, -56121, -56095, -56069, -56043, -56017, -55991, -55965, -55938, -55912, -55886, -55860, -55833, -55807, -55781, -55754, -55728, -55701, -55675, -55648, -55622, -55595, -55569, -55542, -55515, -55489, -55462, -55435, -55408, -55381, -55354, -55327, -55300, -55274, -55246, -55219, -55192, -55165, -55138, -55111, -55084, -55056, -55029, -55002, -54974, -54947, -54920, -54892, -54865, -54837, -54810, -54782, -54755, -54727, -54699, -54672, -54644, -54616, -54588, -54560, -54533, -54505, -54477, -54449, -54421, -54393, -54365, -54337, -54308, -54280, -54252, -54224, -54196, -54167, -54139, -54111, -54082, -54054, -54026, -53997, -53969, -53940, -53911, -53883, -53854, -53826, -53797, -53768, -53739, -53711, -53682, -53653, -53624, -53595, -53566, -53537, -53508, -53479, -53450, -53421, -53392, -53363, -53334, -53304, -53275, -53246, -53216, -53187, -53158, -53128, -53099, -53069, -53040, -53010, -52981, -52951, -52922, -52892, -52862, -52832, -52803, -52773, -52743, -52713, -52683, -52653, -52624, -52594, -52564, -52534, -52503, -52473, -52443, -52413, -52383, -52353, -52322, -52292, -52262, -52231, -52201, -52171, -52140, -52110, -52079, -52049, -52018, -51988, -51957, -51926, -51896, -51865, -51834, -51803, -51773, -51742, -51711, -51680, -51649, -51618, -51587, -51556, -51525, -51494, -51463, -51432, -51401, -51369, -51338, -51307, -51276, -51244, -51213, -51182, -51150, -51119, -51087, -51056, -51024, -50993, -50961, -50929, -50898, -50866, -50834, -50803, -50771, -50739, -50707, -50675, -50644, -50612, -50580, -50548, -50516, -50484, -50452, -50420, -50387, -50355, -50323, -50291, -50259, -50226, -50194, -50162, -50129, -50097, -50065, -50032, -50000, -49967, -49935, -49902, -49869, -49837, -49804, -49771, -49739, -49706, -49673, -49640, -49608, -49575, -49542, -49509, -49476, -49443, -49410, -49377, -49344, -49311, -49278, -49244, -49211, -49178, -49145, -49112, -49078, -49045, -49012, -48978, -48945, -48911, -48878, -48844, -48811, -48777, -48744, -48710, -48676, -48643, -48609, -48575, -48542, -48508, -48474, -48440, -48406, -48372, -48338, -48305, -48271, -48237, -48202, -48168, -48134, -48100, -48066, -48032, -47998, -47963, -47929, -47895, -47860, -47826, -47792, -47757, -47723, -47688, -47654, -47619, -47585, -47550, -47516, -47481, -47446, -47412, -47377, -47342, -47307, -47273, -47238, -47203, -47168, -47133, -47098, -47063, -47028, -46993, -46958, -46923, -46888, -46853, -46818, -46783, -46747, -46712, -46677, -46642, -46606, -46571, -46536, -46500, -46465, -46429, -46394, -46358, -46323, -46287, -46251, -46216, -46180, -46145, -46109, -46073, -46037, -46002, -45966, -45930, -45894, -45858, -45822, -45786, -45750, -45714, -45678, -45642, -45606, -45570, -45534, -45498, -45462, -45425, -45389, -45353, -45316, -45280, -45244, -45207, -45171, -45135, -45098, -45062, -45025, -44989, -44952, -44915, -44879, -44842, -44806, -44769, -44732, -44695, -44659, -44622, -44585, -44548, -44511, -44474, -44437, -44400, -44363, -44326, -44289, -44252, -44215, -44178, -44141, -44104, -44067, -44029, -43992, -43955, -43918, -43880, -43843, -43806, -43768, -43731, -43693, -43656, -43618, -43581, -43543, -43506, -43468, -43430, -43393, -43355, -43317, -43280, -43242, -43204, -43166, -43128, -43091, -43053, -43015, -42977, -42939, -42901, -42863, -42825, -42787, -42749, -42711, -42672, -42634, -42596, -42558, -42520, -42481, -42443, -42405, -42366, -42328, -42290, -42251, -42213, -42174, -42136, -42097, -42059, -42020, -41982, -41943, -41904, -41866, -41827, -41788, -41750, -41711, -41672, -41633, -41595, -41556, -41517, -41478, -41439, -41400, -41361, -41322, -41283, -41244, -41205, -41166, -41127, -41087, -41048, -41009, -40970, -40931, -40891, -40852, -40813, -40773, -40734, -40695, -40655, -40616, -40576, -40537, -40497, -40458, -40418, -40379, -40339, -40299, -40260, -40220, -40180, -40141, -40101, -40061, -40021, -39982, -39942, -39902, -39862, -39822, -39782, -39742, -39702, -39662, -39622, -39582, -39542, -39502, -39462, -39422, -39382, -39341, -39301, -39261, -39221, -39180, -39140, -39100, -39059, -39019, -38979, -38938, -38898, -38857, -38817, -38776, -38736, -38695, -38655, -38614, -38573, -38533, -38492, -38451, -38411, -38370, -38329, -38288, -38248, -38207, -38166, -38125, -38084, -38043, -38002, -37961, -37920, -37879, -37838, -37797, -37756, -37715, -37674, -37633, -37592, -37550, -37509, -37468, -37427, -37386, -37344, -37303, -37262, -37220, -37179, -37137, -37096, -37055, -37013, -36972, -36930, -36889, -36847, -36805, -36764, -36722, -36681, -36639, -36597, -36556, -36514, -36472, -36430, -36388, -36347, -36305, -36263, -36221, -36179, -36137, -36095, -36053, -36011, -35969, -35927, -35885, -35843, -35801, -35759, -35717, -35675, -35633, -35590, -35548, -35506, -35464, -35421, -35379, -35337, -35294, -35252, -35210, -35167, -35125, -35082, -35040, -34997, -34955, -34912, -34870, -34827, -34785, -34742, -34699, -34657, -34614, -34571, -34529, -34486, -34443, -34400, -34358, -34315, -34272, -34229, -34186, -34143, -34100, -34057, -34015, -33972, -33929, -33886, -33843, -33799, -33756, -33713, -33670, -33627, -33584, -33541, -33498, -33454, -33411, -33368, -33325, -33281, -33238, -33195, -33151, -33108, -33065, -33021, -32978, -32934, -32891, -32847, -32804, -32760, -32717, -32673, -32630, -32586, -32542, -32499, -32455, -32411, -32368, -32324, -32280, -32236, -32193, -32149, -32105, -32061, -32017, -31974, -31930, -31886, -31842, -31798, -31754, -31710, -31666, -31622, -31578, -31534, -31490, -31446, -31402, -31357, -31313, -31269, -31225, -31181, -31136, -31092, -31048, -31004, -30959, -30915, -30871, -30826, -30782, -30738, -30693, -30649, -30604, -30560, -30515, -30471, -30426, -30382, -30337, -30293, -30248, -30204, -30159, -30114, -30070, -30025, -29980, -29936, -29891, -29846, -29801, -29757, -29712, -29667, -29622, -29577, -29533, -29488, -29443, -29398, -29353, -29308, -29263, -29218, -29173, -29128, -29083, -29038, -28993, -28948, -28903, -28858, -28812, -28767, -28722, -28677, -28632, -28586, -28541, -28496, -28451, -28405, -28360, -28315, -28269, -28224, -28179, -28133, -28088, -28042, -27997, -27952, -27906, -27861, -27815, -27770, -27724, -27678, -27633, -27587, -27542, -27496, -27450, -27405, -27359, -27313, -27268, -27222, -27176, -27131, -27085, -27039, -26993, -26947, -26902, -26856, -26810, -26764, -26718, -26672, -26626, -26580, -26534, -26488, -26442, -26396, -26350, -26304, -26258, -26212, -26166, -26120, -26074, -26028, -25982, -25936, -25889, -25843, -25797, -25751, -25705, -25658, -25612, -25566, -25520, -25473, -25427, -25381, -25334, -25288, -25241, -25195, -25149, -25102, -25056, -25009, -24963, -24916, -24870, -24823, -24777, -24730, -24684, -24637, -24591, -24544, -24497, -24451, -24404, -24357, -24311, -24264, -24217, -24171, -24124, -24077, -24030, -23984, -23937, -23890, -23843, -23796, -23750, -23703, -23656, -23609, -23562, -23515, -23468, -23421, -23374, -23327, -23280, -23233, -23186, -23139, -23092, -23045, -22998, -22951, -22904, -22857, -22810, -22763, -22716, -22668, -22621, -22574, -22527, -22480, -22432, -22385, -22338, -22291, -22243, -22196, -22149, -22102, -22054, -22007, -21960, -21912, -21865, -21817, -21770, -21723, -21675, -21628, -21580, -21533, -21485, -21438, -21390, -21343, -21295, -21248, -21200, -21153, -21105, -21057, -21010, -20962, -20915, -20867, -20819, -20772, -20724, -20676, -20629, -20581, -20533, -20485, -20438, -20390, -20342, -20294, -20246, -20199, -20151, -20103, -20055, -20007, -19959, -19912, -19864, -19816, -19768, -19720, -19672, -19624, -19576, -19528, -19480, -19432, -19384, -19336, -19288, -19240, -19192, -19144, -19096, -19048, -19000, -18951, -18903, -18855, -18807, -18759, -18711, -18663, -18614, -18566, -18518, -18470, -18421, -18373, -18325, -18277, -18228, -18180, -18132, -18084, -18035, -17987, -17939, -17890, -17842, -17793, -17745, -17697, -17648, -17600, -17551, -17503, -17455, -17406, -17358, -17309, -17261, -17212, -17164, -17115, -17067, -17018, -16970, -16921, -16872, -16824, -16775, -16727, -16678, -16629, -16581, -16532, -16484, -16435, -16386, -16338, -16289, -16240, -16191, -16143, -16094, -16045, -15997, -15948, -15899, -15850, -15802, -15753, -15704, -15655, -15606, -15557, -15509, -15460, -15411, -15362, -15313, -15264, -15215, -15167, -15118, -15069, -15020, -14971, -14922, -14873, -14824, -14775, -14726, -14677, -14628, -14579, -14530, -14481, -14432, -14383, -14334, -14285, -14236, -14187, -14138, -14089, -14040, -13990, -13941, -13892, -13843, -13794, -13745, -13696, -13647, -13597, -13548, -13499, -13450, -13401, -13351, -13302, -13253, -13204, -13154, -13105, -13056, -13007, -12957, -12908, -12859, -12810, -12760, -12711, -12662, -12612, -12563, -12514, -12464, -12415, -12366, -12316, -12267, -12217, -12168, -12119, -12069, -12020, -11970, -11921, -11872, -11822, -11773, -11723, -11674, -11624, -11575, -11525, -11476, -11426, -11377, -11327, -11278, -11228, -11179, -11129, -11080, -11030, -10981, -10931, -10882, -10832, -10782, -10733, -10683, -10634, -10584, -10534, -10485, -10435, -10386, -10336, -10286, -10237, -10187, -10137, -10088, -10038, -9988, -9939, -9889, -9839, -9790, -9740, -9690, -9640, -9591, -9541, -9491, -9442, -9392, -9342, -9292, -9243, -9193, -9143, -9093, -9043, -8994, -8944, -8894, -8844, -8794, -8745, -8695, -8645, -8595, -8545, -8496, -8446, -8396, -8346, -8296, -8246, -8196, -8147, -8097, -8047, -7997, -7947, -7897, -7847, -7797, -7747, -7697, -7648, -7598, -7548, -7498, -7448, -7398, -7348, -7298, -7248, -7198, -7148, -7098, -7048, -6998, -6948, -6898, -6848, -6798, -6748, -6698, -6648, -6598, -6548, -6498, -6448, -6398, -6348, -6298, -6248, -6198, -6148, -6098, -6048, -5998, -5948, -5898, -5848, -5798, -5747, -5697, -5647, -5597, -5547, -5497, -5447, -5397, -5347, -5297, -5247, -5197, -5146, -5096, -5046, -4996, -4946, -4896, -4846, -4796, -4745, -4695, -4645, -4595, -4545, -4495, -4445, -4394, -4344, -4294, -4244, -4194, -4144, -4093, -4043, -3993, -3943, -3893, -3843, -3792, -3742, -3692, -3642, -3592, -3541, -3491, -3441, -3391, -3341, -3291, -3240, -3190, -3140, -3090, -3039, -2989, -2939, -2889, -2839, -2788, -2738, -2688, -2638, -2588, -2537, -2487, -2437, -2387, -2336, -2286, -2236, -2186, -2135, -2085, -2035, -1985, -1934, -1884, -1834, -1784, -1733, -1683, -1633, -1583, -1532, -1482, -1432, -1382, -1331, -1281, -1231, -1181, -1130, -1080, -1030, -980, -929, -879, -829, -779, -728, -678, -628, -578, -527, -477, -427, -376, -326, -276, -226, -175, -125, -75, -25, 25, 75, 125, 175, 226, 276, 326, 376, 427, 477, 527, 578, 628, 678, 728, 779, 829, 879, 929, 980, 1030, 1080, 1130, 1181, 1231, 1281, 1331, 1382, 1432, 1482, 1532, 1583, 1633, 1683, 1733, 1784, 1834, 1884, 1934, 1985, 2035, 2085, 2135, 2186, 2236, 2286, 2336, 2387, 2437, 2487, 2537, 2587, 2638, 2688, 2738, 2788, 2839, 2889, 2939, 2989, 3039, 3090, 3140, 3190, 3240, 3291, 3341, 3391, 3441, 3491, 3542, 3592, 3642, 3692, 3742, 3792, 3843, 3893, 3943, 3993, 4043, 4093, 4144, 4194, 4244, 4294, 4344, 4394, 4445, 4495, 4545, 4595, 4645, 4695, 4745, 4796, 4846, 4896, 4946, 4996, 5046, 5096, 5146, 5197, 5247, 5297, 5347, 5397, 5447, 5497, 5547, 5597, 5647, 5697, 5747, 5798, 5848, 5898, 5948, 5998, 6048, 6098, 6148, 6198, 6248, 6298, 6348, 6398, 6448, 6498, 6548, 6598, 6648, 6698, 6748, 6798, 6848, 6898, 6948, 6998, 7048, 7098, 7148, 7198, 7248, 7298, 7348, 7398, 7448, 7498, 7548, 7598, 7648, 7697, 7747, 7797, 7847, 7897, 7947, 7997, 8047, 8097, 8147, 8196, 8246, 8296, 8346, 8396, 8446, 8496, 8545, 8595, 8645, 8695, 8745, 8794, 8844, 8894, 8944, 8994, 9043, 9093, 9143, 9193, 9243, 9292, 9342, 9392, 9442, 9491, 9541, 9591, 9640, 9690, 9740, 9790, 9839, 9889, 9939, 9988, 10038, 10088, 10137, 10187, 10237, 10286, 10336, 10386, 10435, 10485, 10534, 10584, 10634, 10683, 10733, 10782, 10832, 10882, 10931, 10981, 11030, 11080, 11129, 11179, 11228, 11278, 11327, 11377, 11426, 11476, 11525, 11575, 11624, 11674, 11723, 11773, 11822, 11872, 11921, 11970, 12020, 12069, 12119, 12168, 12218, 12267, 12316, 12366, 12415, 12464, 12514, 12563, 12612, 12662, 12711, 12760, 12810, 12859, 12908, 12957, 13007, 13056, 13105, 13154, 13204, 13253, 13302, 13351, 13401, 13450, 13499, 13548, 13597, 13647, 13696, 13745, 13794, 13843, 13892, 13941, 13990, 14040, 14089, 14138, 14187, 14236, 14285, 14334, 14383, 14432, 14481, 14530, 14579, 14628, 14677, 14726, 14775, 14824, 14873, 14922, 14971, 15020, 15069, 15118, 15167, 15215, 15264, 15313, 15362, 15411, 15460, 15509, 15557, 15606, 15655, 15704, 15753, 15802, 15850, 15899, 15948, 15997, 16045, 16094, 16143, 16191, 16240, 16289, 16338, 16386, 16435, 16484, 16532, 16581, 16629, 16678, 16727, 16775, 16824, 16872, 16921, 16970, 17018, 17067, 17115, 17164, 17212, 17261, 17309, 17358, 17406, 17455, 17503, 17551, 17600, 17648, 17697, 17745, 17793, 17842, 17890, 17939, 17987, 18035, 18084, 18132, 18180, 18228, 18277, 18325, 18373, 18421, 18470, 18518, 18566, 18614, 18663, 18711, 18759, 18807, 18855, 18903, 18951, 19000, 19048, 19096, 19144, 19192, 19240, 19288, 19336, 19384, 19432, 19480, 19528, 19576, 19624, 19672, 19720, 19768, 19816, 19864, 19912, 19959, 20007, 20055, 20103, 20151, 20199, 20246, 20294, 20342, 20390, 20438, 20485, 20533, 20581, 20629, 20676, 20724, 20772, 20819, 20867, 20915, 20962, 21010, 21057, 21105, 21153, 21200, 21248, 21295, 21343, 21390, 21438, 21485, 21533, 21580, 21628, 21675, 21723, 21770, 21817, 21865, 21912, 21960, 22007, 22054, 22102, 22149, 22196, 22243, 22291, 22338, 22385, 22432, 22480, 22527, 22574, 22621, 22668, 22716, 22763, 22810, 22857, 22904, 22951, 22998, 23045, 23092, 23139, 23186, 23233, 23280, 23327, 23374, 23421, 23468, 23515, 23562, 23609, 23656, 23703, 23750, 23796, 23843, 23890, 23937, 23984, 24030, 24077, 24124, 24171, 24217, 24264, 24311, 24357, 24404, 24451, 24497, 24544, 24591, 24637, 24684, 24730, 24777, 24823, 24870, 24916, 24963, 25009, 25056, 25102, 25149, 25195, 25241, 25288, 25334, 25381, 25427, 25473, 25520, 25566, 25612, 25658, 25705, 25751, 25797, 25843, 25889, 25936, 25982, 26028, 26074, 26120, 26166, 26212, 26258, 26304, 26350, 26396, 26442, 26488, 26534, 26580, 26626, 26672, 26718, 26764, 26810, 26856, 26902, 26947, 26993, 27039, 27085, 27131, 27176, 27222, 27268, 27313, 27359, 27405, 27450, 27496, 27542, 27587, 27633, 27678, 27724, 27770, 27815, 27861, 27906, 27952, 27997, 28042, 28088, 28133, 28179, 28224, 28269, 28315, 28360, 28405, 28451, 28496, 28541, 28586, 28632, 28677, 28722, 28767, 28812, 28858, 28903, 28948, 28993, 29038, 29083, 29128, 29173, 29218, 29263, 29308, 29353, 29398, 29443, 29488, 29533, 29577, 29622, 29667, 29712, 29757, 29801, 29846, 29891, 29936, 29980, 30025, 30070, 30114, 30159, 30204, 30248, 30293, 30337, 30382, 30427, 30471, 30516, 30560, 30604, 30649, 30693, 30738, 30782, 30826, 30871, 30915, 30959, 31004, 31048, 31092, 31136, 31181, 31225, 31269, 31313, 31357, 31402, 31446, 31490, 31534, 31578, 31622, 31666, 31710, 31754, 31798, 31842, 31886, 31930, 31974, 32017, 32061, 32105, 32149, 32193, 32236, 32280, 32324, 32368, 32411, 32455, 32499, 32542, 32586, 32630, 32673, 32717, 32760, 32804, 32847, 32891, 32934, 32978, 33021, 33065, 33108, 33151, 33195, 33238, 33281, 33325, 33368, 33411, 33454, 33498, 33541, 33584, 33627, 33670, 33713, 33756, 33799, 33843, 33886, 33929, 33972, 34015, 34057, 34100, 34143, 34186, 34229, 34272, 34315, 34358, 34400, 34443, 34486, 34529, 34571, 34614, 34657, 34699, 34742, 34785, 34827, 34870, 34912, 34955, 34997, 35040, 35082, 35125, 35167, 35210, 35252, 35294, 35337, 35379, 35421, 35464, 35506, 35548, 35590, 35633, 35675, 35717, 35759, 35801, 35843, 35885, 35927, 35969, 36011, 36053, 36095, 36137, 36179, 36221, 36263, 36305, 36347, 36388, 36430, 36472, 36514, 36556, 36597, 36639, 36681, 36722, 36764, 36805, 36847, 36889, 36930, 36972, 37013, 37055, 37096, 37137, 37179, 37220, 37262, 37303, 37344, 37386, 37427, 37468, 37509, 37551, 37592, 37633, 37674, 37715, 37756, 37797, 37838, 37879, 37920, 37961, 38002, 38043, 38084, 38125, 38166, 38207, 38248, 38288, 38329, 38370, 38411, 38451, 38492, 38533, 38573, 38614, 38655, 38695, 38736, 38776, 38817, 38857, 38898, 38938, 38979, 39019, 39059, 39100, 39140, 39180, 39221, 39261, 39301, 39341, 39382, 39422, 39462, 39502, 39542, 39582, 39622, 39662, 39702, 39742, 39782, 39822, 39862, 39902, 39942, 39982, 40021, 40061, 40101, 40141, 40180, 40220, 40260, 40299, 40339, 40379, 40418, 40458, 40497, 40537, 40576, 40616, 40655, 40695, 40734, 40773, 40813, 40852, 40891, 40931, 40970, 41009, 41048, 41087, 41127, 41166, 41205, 41244, 41283, 41322, 41361, 41400, 41439, 41478, 41517, 41556, 41595, 41633, 41672, 41711, 41750, 41788, 41827, 41866, 41904, 41943, 41982, 42020, 42059, 42097, 42136, 42174, 42213, 42251, 42290, 42328, 42366, 42405, 42443, 42481, 42520, 42558, 42596, 42634, 42672, 42711, 42749, 42787, 42825, 42863, 42901, 42939, 42977, 43015, 43053, 43091, 43128, 43166, 43204, 43242, 43280, 43317, 43355, 43393, 43430, 43468, 43506, 43543, 43581, 43618, 43656, 43693, 43731, 43768, 43806, 43843, 43880, 43918, 43955, 43992, 44029, 44067, 44104, 44141, 44178, 44215, 44252, 44289, 44326, 44363, 44400, 44437, 44474, 44511, 44548, 44585, 44622, 44659, 44695, 44732, 44769, 44806, 44842, 44879, 44915, 44952, 44989, 45025, 45062, 45098, 45135, 45171, 45207, 45244, 45280, 45316, 45353, 45389, 45425, 45462, 45498, 45534, 45570, 45606, 45642, 45678, 45714, 45750, 45786, 45822, 45858, 45894, 45930, 45966, 46002, 46037, 46073, 46109, 46145, 46180, 46216, 46252, 46287, 46323, 46358, 46394, 46429, 46465, 46500, 46536, 46571, 46606, 46642, 46677, 46712, 46747, 46783, 46818, 46853, 46888, 46923, 46958, 46993, 47028, 47063, 47098, 47133, 47168, 47203, 47238, 47273, 47308, 47342, 47377, 47412, 47446, 47481, 47516, 47550, 47585, 47619, 47654, 47688, 47723, 47757, 47792, 47826, 47861, 47895, 47929, 47963, 47998, 48032, 48066, 48100, 48134, 48168, 48202, 48237, 48271, 48305, 48338, 48372, 48406, 48440, 48474, 48508, 48542, 48575, 48609, 48643, 48676, 48710, 48744, 48777, 48811, 48844, 48878, 48911, 48945, 48978, 49012, 49045, 49078, 49112, 49145, 49178, 49211, 49244, 49278, 49311, 49344, 49377, 49410, 49443, 49476, 49509, 49542, 49575, 49608, 49640, 49673, 49706, 49739, 49771, 49804, 49837, 49869, 49902, 49935, 49967, 50000, 50032, 50064, 50097, 50129, 50162, 50194, 50226, 50259, 50291, 50323, 50355, 50387, 50420, 50452, 50484, 50516, 50548, 50580, 50612, 50644, 50675, 50707, 50739, 50771, 50803, 50834, 50866, 50898, 50929, 50961, 50993, 51024, 51056, 51087, 51119, 51150, 51182, 51213, 51244, 51276, 51307, 51338, 51369, 51401, 51432, 51463, 51494, 51525, 51556, 51587, 51618, 51649, 51680, 51711, 51742, 51773, 51803, 51834, 51865, 51896, 51926, 51957, 51988, 52018, 52049, 52079, 52110, 52140, 52171, 52201, 52231, 52262, 52292, 52322, 52353, 52383, 52413, 52443, 52473, 52503, 52534, 52564, 52594, 52624, 52653, 52683, 52713, 52743, 52773, 52803, 52832, 52862, 52892, 52922, 52951, 52981, 53010, 53040, 53069, 53099, 53128, 53158, 53187, 53216, 53246, 53275, 53304, 53334, 53363, 53392, 53421, 53450, 53479, 53508, 53537, 53566, 53595, 53624, 53653, 53682, 53711, 53739, 53768, 53797, 53826, 53854, 53883, 53912, 53940, 53969, 53997, 54026, 54054, 54082, 54111, 54139, 54167, 54196, 54224, 54252, 54280, 54309, 54337, 54365, 54393, 54421, 54449, 54477, 54505, 54533, 54560, 54588, 54616, 54644, 54672, 54699, 54727, 54755, 54782, 54810, 54837, 54865, 54892, 54920, 54947, 54974, 55002, 55029, 55056, 55084, 55111, 55138, 55165, 55192, 55219, 55246, 55274, 55300, 55327, 55354, 55381, 55408, 55435, 55462, 55489, 55515, 55542, 55569, 55595, 55622, 55648, 55675, 55701, 55728, 55754, 55781, 55807, 55833, 55860, 55886, 55912, 55938, 55965, 55991, 56017, 56043, 56069, 56095, 56121, 56147, 56173, 56199, 56225, 56250, 56276, 56302, 56328, 56353, 56379, 56404, 56430, 56456, 56481, 56507, 56532, 56557, 56583, 56608, 56633, 56659, 56684, 56709, 56734, 56760, 56785, 56810, 56835, 56860, 56885, 56910, 56935, 56959, 56984, 57009, 57034, 57059, 57083, 57108, 57133, 57157, 57182, 57206, 57231, 57255, 57280, 57304, 57329, 57353, 57377, 57402, 57426, 57450, 57474, 57498, 57522, 57546, 57570, 57594, 57618, 57642, 57666, 57690, 57714, 57738, 57762, 57785, 57809, 57833, 57856, 57880, 57903, 57927, 57950, 57974, 57997, 58021, 58044, 58067, 58091, 58114, 58137, 58160, 58183, 58207, 58230, 58253, 58276, 58299, 58322, 58345, 58367, 58390, 58413, 58436, 58459, 58481, 58504, 58527, 58549, 58572, 58594, 58617, 58639, 58662, 58684, 58706, 58729, 58751, 58773, 58795, 58818, 58840, 58862, 58884, 58906, 58928, 58950, 58972, 58994, 59016, 59038, 59059, 59081, 59103, 59125, 59146, 59168, 59190, 59211, 59233, 59254, 59276, 59297, 59318, 59340, 59361, 59382, 59404, 59425, 59446, 59467, 59488, 59509, 59530, 59551, 59572, 59593, 59614, 59635, 59656, 59677, 59697, 59718, 59739, 59759, 59780, 59801, 59821, 59842, 59862, 59883, 59903, 59923, 59944, 59964, 59984, 60004, 60025, 60045, 60065, 60085, 60105, 60125, 60145, 60165, 60185, 60205, 60225, 60244, 60264, 60284, 60304, 60323, 60343, 60363, 60382, 60402, 60421, 60441, 60460, 60479, 60499, 60518, 60537, 60556, 60576, 60595, 60614, 60633, 60652, 60671, 60690, 60709, 60728, 60747, 60766, 60785, 60803, 60822, 60841, 60859, 60878, 60897, 60915, 60934, 60952, 60971, 60989, 61007, 61026, 61044, 61062, 61081, 61099, 61117, 61135, 61153, 61171, 61189, 61207, 61225, 61243, 61261, 61279, 61297, 61314, 61332, 61350, 61367, 61385, 61403, 61420, 61438, 61455, 61473, 61490, 61507, 61525, 61542, 61559, 61577, 61594, 61611, 61628, 61645, 61662, 61679, 61696, 61713, 61730, 61747, 61764, 61780, 61797, 61814, 61831, 61847, 61864, 61880, 61897, 61913, 61930, 61946, 61963, 61979, 61995, 62012, 62028, 62044, 62060, 62076, 62092, 62108, 62125, 62141, 62156, 62172, 62188, 62204, 62220, 62236, 62251, 62267, 62283, 62298, 62314, 62329, 62345, 62360, 62376, 62391, 62407, 62422, 62437, 62453, 62468, 62483, 62498, 62513, 62528, 62543, 62558, 62573, 62588, 62603, 62618, 62633, 62648, 62662, 62677, 62692, 62706, 62721, 62735, 62750, 62764, 62779, 62793, 62808, 62822, 62836, 62850, 62865, 62879, 62893, 62907, 62921, 62935, 62949, 62963, 62977, 62991, 63005, 63019, 63032, 63046, 63060, 63074, 63087, 63101, 63114, 63128, 63141, 63155, 63168, 63182, 63195, 63208, 63221, 63235, 63248, 63261, 63274, 63287, 63300, 63313, 63326, 63339, 63352, 63365, 63378, 63390, 63403, 63416, 63429, 63441, 63454, 63466, 63479, 63491, 63504, 63516, 63528, 63541, 63553, 63565, 63578, 63590, 63602, 63614, 63626, 63638, 63650, 63662, 63674, 63686, 63698, 63709, 63721, 63733, 63745, 63756, 63768, 63779, 63791, 63803, 63814, 63825, 63837, 63848, 63859, 63871, 63882, 63893, 63904, 63915, 63927, 63938, 63949, 63960, 63971, 63981, 63992, 64003, 64014, 64025, 64035, 64046, 64057, 64067, 64078, 64088, 64099, 64109, 64120, 64130, 64140, 64151, 64161, 64171, 64181, 64192, 64202, 64212, 64222, 64232, 64242, 64252, 64261, 64271, 64281, 64291, 64301, 64310, 64320, 64330, 64339, 64349, 64358, 64368, 64377, 64387, 64396, 64405, 64414, 64424, 64433, 64442, 64451, 64460, 64469, 64478, 64487, 64496, 64505, 64514, 64523, 64532, 64540, 64549, 64558, 64566, 64575, 64584, 64592, 64600, 64609, 64617, 64626, 64634, 64642, 64651, 64659, 64667, 64675, 64683, 64691, 64699, 64707, 64715, 64723, 64731, 64739, 64747, 64754, 64762, 64770, 64777, 64785, 64793, 64800, 64808, 64815, 64822, 64830, 64837, 64844, 64852, 64859, 64866, 64873, 64880, 64887, 64895, 64902, 64908, 64915, 64922, 64929, 64936, 64943, 64949, 64956, 64963, 64969, 64976, 64982, 64989, 64995, 65002, 65008, 65015, 65021, 65027, 65033, 65040, 65046, 65052, 65058, 65064, 65070, 65076, 65082, 65088, 65094, 65099, 65105, 65111, 65117, 65122, 65128, 65133, 65139, 65144, 65150, 65155, 65161, 65166, 65171, 65177, 65182, 65187, 65192, 65197, 65202, 65207, 65212, 65217, 65222, 65227, 65232, 65237, 65242, 65246, 65251, 65256, 65260, 65265, 65270, 65274, 65279, 65283, 65287, 65292, 65296, 65300, 65305, 65309, 65313, 65317, 65321, 65325, 65329, 65333, 65337, 65341, 65345, 65349, 65352, 65356, 65360, 65363, 65367, 65371, 65374, 65378, 65381, 65385, 65388, 65391, 65395, 65398, 65401, 65404, 65408, 65411, 65414, 65417, 65420, 65423, 65426, 65429, 65431, 65434, 65437, 65440, 65442, 65445, 65448, 65450, 65453, 65455, 65458, 65460, 65463, 65465, 65467, 65470, 65472, 65474, 65476, 65478, 65480, 65482, 65484, 65486, 65488, 65490, 65492, 65494, 65496, 65497, 65499, 65501, 65502, 65504, 65505, 65507, 65508, 65510, 65511, 65513, 65514, 65515, 65516, 65518, 65519, 65520, 65521, 65522, 65523, 65524, 65525, 65526, 65527, 65527, 65528, 65529, 65530, 65530, 65531, 65531, 65532, 65532, 65533, 65533, 65534, 65534, 65534, 65535, 65535, 65535, 65535, 65535, 65535, 65535 }; int tantoangle[2049] = { 0, 333772, 667544, 1001315, 1335086, 1668857, 2002626, 2336395, 2670163, 3003929, 3337694, 3671457, 4005219, 4338979, 4672736, 5006492, 5340245, 5673995, 6007743, 6341488, 6675230, 7008968, 7342704, 7676435, 8010164, 8343888, 8677609, 9011325, 9345037, 9678744, 10012447, 10346145, 10679838, 11013526, 11347209, 11680887, 12014558, 12348225, 12681885, 13015539, 13349187, 13682829, 14016464, 14350092, 14683714, 15017328, 15350936, 15684536, 16018129, 16351714, 16685291, 17018860, 17352422, 17685974, 18019518, 18353054, 18686582, 19020100, 19353610, 19687110, 20020600, 20354080, 20687552, 21021014, 21354466, 21687906, 22021338, 22354758, 22688168, 23021568, 23354956, 23688332, 24021698, 24355052, 24688396, 25021726, 25355046, 25688352, 26021648, 26354930, 26688200, 27021456, 27354702, 27687932, 28021150, 28354356, 28687548, 29020724, 29353888, 29687038, 30020174, 30353296, 30686404, 31019496, 31352574, 31685636, 32018684, 32351718, 32684734, 33017736, 33350722, 33683692, 34016648, 34349584, 34682508, 35015412, 35348300, 35681172, 36014028, 36346868, 36679688, 37012492, 37345276, 37678044, 38010792, 38343524, 38676240, 39008936, 39341612, 39674272, 40006912, 40339532, 40672132, 41004716, 41337276, 41669820, 42002344, 42334848, 42667332, 42999796, 43332236, 43664660, 43997060, 44329444, 44661800, 44994140, 45326456, 45658752, 45991028, 46323280, 46655512, 46987720, 47319908, 47652072, 47984212, 48316332, 48648428, 48980500, 49312548, 49644576, 49976580, 50308556, 50640512, 50972444, 51304352, 51636236, 51968096, 52299928, 52631740, 52963524, 53295284, 53627020, 53958728, 54290412, 54622068, 54953704, 55285308, 55616888, 55948444, 56279972, 56611472, 56942948, 57274396, 57605816, 57937212, 58268576, 58599916, 58931228, 59262512, 59593768, 59924992, 60256192, 60587364, 60918508, 61249620, 61580704, 61911760, 62242788, 62573788, 62904756, 63235692, 63566604, 63897480, 64228332, 64559148, 64889940, 65220696, 65551424, 65882120, 66212788, 66543420, 66874024, 67204600, 67535136, 67865648, 68196120, 68526568, 68856984, 69187360, 69517712, 69848024, 70178304, 70508560, 70838776, 71168960, 71499112, 71829224, 72159312, 72489360, 72819376, 73149360, 73479304, 73809216, 74139096, 74468936, 74798744, 75128520, 75458264, 75787968, 76117632, 76447264, 76776864, 77106424, 77435952, 77765440, 78094888, 78424304, 78753688, 79083032, 79412336, 79741608, 80070840, 80400032, 80729192, 81058312, 81387392, 81716432, 82045440, 82374408, 82703336, 83032224, 83361080, 83689896, 84018664, 84347400, 84676096, 85004760, 85333376, 85661952, 85990488, 86318984, 86647448, 86975864, 87304240, 87632576, 87960872, 88289128, 88617344, 88945520, 89273648, 89601736, 89929792, 90257792, 90585760, 90913688, 91241568, 91569408, 91897200, 92224960, 92552672, 92880336, 93207968, 93535552, 93863088, 94190584, 94518040, 94845448, 95172816, 95500136, 95827416, 96154648, 96481832, 96808976, 97136080, 97463136, 97790144, 98117112, 98444032, 98770904, 99097736, 99424520, 99751256, 100077944, 100404592, 100731192, 101057744, 101384248, 101710712, 102037128, 102363488, 102689808, 103016080, 103342312, 103668488, 103994616, 104320696, 104646736, 104972720, 105298656, 105624552, 105950392, 106276184, 106601928, 106927624, 107253272, 107578872, 107904416, 108229920, 108555368, 108880768, 109206120, 109531416, 109856664, 110181872, 110507016, 110832120, 111157168, 111482168, 111807112, 112132008, 112456856, 112781648, 113106392, 113431080, 113755720, 114080312, 114404848, 114729328, 115053760, 115378136, 115702464, 116026744, 116350960, 116675128, 116999248, 117323312, 117647320, 117971272, 118295176, 118619024, 118942816, 119266560, 119590248, 119913880, 120237456, 120560984, 120884456, 121207864, 121531224, 121854528, 122177784, 122500976, 122824112, 123147200, 123470224, 123793200, 124116120, 124438976, 124761784, 125084528, 125407224, 125729856, 126052432, 126374960, 126697424, 127019832, 127342184, 127664472, 127986712, 128308888, 128631008, 128953072, 129275080, 129597024, 129918912, 130240744, 130562520, 130884232, 131205888, 131527480, 131849016, 132170496, 132491912, 132813272, 133134576, 133455816, 133776992, 134098120, 134419184, 134740176, 135061120, 135382000, 135702816, 136023584, 136344272, 136664912, 136985488, 137306016, 137626464, 137946864, 138267184, 138587456, 138907664, 139227808, 139547904, 139867920, 140187888, 140507776, 140827616, 141147392, 141467104, 141786752, 142106336, 142425856, 142745312, 143064720, 143384048, 143703312, 144022512, 144341664, 144660736, 144979744, 145298704, 145617584, 145936400, 146255168, 146573856, 146892480, 147211040, 147529536, 147847968, 148166336, 148484640, 148802880, 149121056, 149439152, 149757200, 150075168, 150393072, 150710912, 151028688, 151346400, 151664048, 151981616, 152299136, 152616576, 152933952, 153251264, 153568496, 153885680, 154202784, 154519824, 154836784, 155153696, 155470528, 155787296, 156104000, 156420624, 156737200, 157053696, 157370112, 157686480, 158002768, 158318976, 158635136, 158951216, 159267232, 159583168, 159899040, 160214848, 160530592, 160846256, 161161840, 161477376, 161792832, 162108208, 162423520, 162738768, 163053952, 163369040, 163684080, 163999040, 164313936, 164628752, 164943504, 165258176, 165572784, 165887312, 166201776, 166516160, 166830480, 167144736, 167458912, 167773008, 168087040, 168400992, 168714880, 169028688, 169342432, 169656096, 169969696, 170283216, 170596672, 170910032, 171223344, 171536576, 171849728, 172162800, 172475808, 172788736, 173101600, 173414384, 173727104, 174039728, 174352288, 174664784, 174977200, 175289536, 175601792, 175913984, 176226096, 176538144, 176850096, 177161984, 177473792, 177785536, 178097200, 178408784, 178720288, 179031728, 179343088, 179654368, 179965568, 180276704, 180587744, 180898720, 181209616, 181520448, 181831184, 182141856, 182452448, 182762960, 183073408, 183383760, 183694048, 184004240, 184314368, 184624416, 184934400, 185244288, 185554096, 185863840, 186173504, 186483072, 186792576, 187102000, 187411344, 187720608, 188029808, 188338912, 188647936, 188956896, 189265760, 189574560, 189883264, 190191904, 190500448, 190808928, 191117312, 191425632, 191733872, 192042016, 192350096, 192658096, 192966000, 193273840, 193581584, 193889264, 194196848, 194504352, 194811792, 195119136, 195426400, 195733584, 196040688, 196347712, 196654656, 196961520, 197268304, 197574992, 197881616, 198188144, 198494592, 198800960, 199107248, 199413456, 199719584, 200025616, 200331584, 200637456, 200943248, 201248960, 201554576, 201860128, 202165584, 202470960, 202776256, 203081456, 203386592, 203691632, 203996592, 204301472, 204606256, 204910976, 205215600, 205520144, 205824592, 206128960, 206433248, 206737456, 207041584, 207345616, 207649568, 207953424, 208257216, 208560912, 208864512, 209168048, 209471488, 209774832, 210078112, 210381296, 210684384, 210987408, 211290336, 211593184, 211895936, 212198608, 212501184, 212803680, 213106096, 213408432, 213710672, 214012816, 214314880, 214616864, 214918768, 215220576, 215522288, 215823920, 216125472, 216426928, 216728304, 217029584, 217330784, 217631904, 217932928, 218233856, 218534704, 218835472, 219136144, 219436720, 219737216, 220037632, 220337952, 220638192, 220938336, 221238384, 221538352, 221838240, 222138032, 222437728, 222737344, 223036880, 223336304, 223635664, 223934912, 224234096, 224533168, 224832160, 225131072, 225429872, 225728608, 226027232, 226325776, 226624240, 226922608, 227220880, 227519056, 227817152, 228115168, 228413088, 228710912, 229008640, 229306288, 229603840, 229901312, 230198688, 230495968, 230793152, 231090256, 231387280, 231684192, 231981024, 232277760, 232574416, 232870960, 233167440, 233463808, 233760096, 234056288, 234352384, 234648384, 234944304, 235240128, 235535872, 235831504, 236127056, 236422512, 236717888, 237013152, 237308336, 237603424, 237898416, 238193328, 238488144, 238782864, 239077488, 239372016, 239666464, 239960816, 240255072, 240549232, 240843312, 241137280, 241431168, 241724960, 242018656, 242312256, 242605776, 242899200, 243192512, 243485744, 243778896, 244071936, 244364880, 244657744, 244950496, 245243168, 245535744, 245828224, 246120608, 246412912, 246705104, 246997216, 247289216, 247581136, 247872960, 248164688, 248456320, 248747856, 249039296, 249330640, 249621904, 249913056, 250204128, 250495088, 250785968, 251076736, 251367424, 251658016, 251948512, 252238912, 252529200, 252819408, 253109520, 253399536, 253689456, 253979280, 254269008, 254558640, 254848176, 255137632, 255426976, 255716224, 256005376, 256294432, 256583392, 256872256, 257161024, 257449696, 257738272, 258026752, 258315136, 258603424, 258891600, 259179696, 259467696, 259755600, 260043392, 260331104, 260618704, 260906224, 261193632, 261480960, 261768176, 262055296, 262342320, 262629248, 262916080, 263202816, 263489456, 263776000, 264062432, 264348784, 264635024, 264921168, 265207216, 265493168, 265779024, 266064784, 266350448, 266636000, 266921472, 267206832, 267492096, 267777264, 268062336, 268347312, 268632192, 268916960, 269201632, 269486208, 269770688, 270055072, 270339360, 270623552, 270907616, 271191616, 271475488, 271759296, 272042976, 272326560, 272610048, 272893440, 273176736, 273459936, 273743040, 274026048, 274308928, 274591744, 274874432, 275157024, 275439520, 275721920, 276004224, 276286432, 276568512, 276850528, 277132416, 277414240, 277695936, 277977536, 278259040, 278540448, 278821728, 279102944, 279384032, 279665056, 279945952, 280226752, 280507456, 280788064, 281068544, 281348960, 281629248, 281909472, 282189568, 282469568, 282749440, 283029248, 283308960, 283588544, 283868032, 284147424, 284426720, 284705920, 284985024, 285264000, 285542912, 285821696, 286100384, 286378976, 286657440, 286935840, 287214112, 287492320, 287770400, 288048384, 288326240, 288604032, 288881696, 289159264, 289436768, 289714112, 289991392, 290268576, 290545632, 290822592, 291099456, 291376224, 291652896, 291929440, 292205888, 292482272, 292758528, 293034656, 293310720, 293586656, 293862496, 294138240, 294413888, 294689440, 294964864, 295240192, 295515424, 295790560, 296065600, 296340512, 296615360, 296890080, 297164704, 297439200, 297713632, 297987936, 298262144, 298536256, 298810240, 299084160, 299357952, 299631648, 299905248, 300178720, 300452128, 300725408, 300998592, 301271680, 301544640, 301817536, 302090304, 302362976, 302635520, 302908000, 303180352, 303452608, 303724768, 303996800, 304268768, 304540608, 304812320, 305083968, 305355520, 305626944, 305898272, 306169472, 306440608, 306711616, 306982528, 307253344, 307524064, 307794656, 308065152, 308335552, 308605856, 308876032, 309146112, 309416096, 309685984, 309955744, 310225408, 310494976, 310764448, 311033824, 311303072, 311572224, 311841280, 312110208, 312379040, 312647776, 312916416, 313184960, 313453376, 313721696, 313989920, 314258016, 314526016, 314793920, 315061728, 315329408, 315597024, 315864512, 316131872, 316399168, 316666336, 316933408, 317200384, 317467232, 317733984, 318000640, 318267200, 318533632, 318799968, 319066208, 319332352, 319598368, 319864288, 320130112, 320395808, 320661408, 320926912, 321192320, 321457632, 321722816, 321987904, 322252864, 322517760, 322782528, 323047200, 323311744, 323576192, 323840544, 324104800, 324368928, 324632992, 324896928, 325160736, 325424448, 325688096, 325951584, 326215008, 326478304, 326741504, 327004608, 327267584, 327530464, 327793248, 328055904, 328318496, 328580960, 328843296, 329105568, 329367712, 329629760, 329891680, 330153536, 330415264, 330676864, 330938400, 331199808, 331461120, 331722304, 331983392, 332244384, 332505280, 332766048, 333026752, 333287296, 333547776, 333808128, 334068384, 334328544, 334588576, 334848512, 335108352, 335368064, 335627712, 335887200, 336146624, 336405920, 336665120, 336924224, 337183200, 337442112, 337700864, 337959552, 338218112, 338476576, 338734944, 338993184, 339251328, 339509376, 339767296, 340025120, 340282848, 340540480, 340797984, 341055392, 341312704, 341569888, 341826976, 342083968, 342340832, 342597600, 342854272, 343110848, 343367296, 343623648, 343879904, 344136032, 344392064, 344648000, 344903808, 345159520, 345415136, 345670656, 345926048, 346181344, 346436512, 346691616, 346946592, 347201440, 347456224, 347710880, 347965440, 348219872, 348474208, 348728448, 348982592, 349236608, 349490528, 349744320, 349998048, 350251648, 350505152, 350758528, 351011808, 351264992, 351518048, 351771040, 352023872, 352276640, 352529280, 352781824, 353034272, 353286592, 353538816, 353790944, 354042944, 354294880, 354546656, 354798368, 355049952, 355301440, 355552800, 355804096, 356055264, 356306304, 356557280, 356808128, 357058848, 357309504, 357560032, 357810464, 358060768, 358311008, 358561088, 358811104, 359060992, 359310784, 359560480, 359810048, 360059520, 360308896, 360558144, 360807296, 361056352, 361305312, 361554144, 361802880, 362051488, 362300032, 362548448, 362796736, 363044960, 363293056, 363541024, 363788928, 364036704, 364284384, 364531936, 364779392, 365026752, 365274016, 365521152, 365768192, 366015136, 366261952, 366508672, 366755296, 367001792, 367248192, 367494496, 367740704, 367986784, 368232768, 368478656, 368724416, 368970080, 369215648, 369461088, 369706432, 369951680, 370196800, 370441824, 370686752, 370931584, 371176288, 371420896, 371665408, 371909792, 372154080, 372398272, 372642336, 372886304, 373130176, 373373952, 373617600, 373861152, 374104608, 374347936, 374591168, 374834304, 375077312, 375320224, 375563040, 375805760, 376048352, 376290848, 376533248, 376775520, 377017696, 377259776, 377501728, 377743584, 377985344, 378227008, 378468544, 378709984, 378951328, 379192544, 379433664, 379674688, 379915584, 380156416, 380397088, 380637696, 380878176, 381118560, 381358848, 381599040, 381839104, 382079072, 382318912, 382558656, 382798304, 383037856, 383277280, 383516640, 383755840, 383994976, 384233984, 384472896, 384711712, 384950400, 385188992, 385427488, 385665888, 385904160, 386142336, 386380384, 386618368, 386856224, 387093984, 387331616, 387569152, 387806592, 388043936, 388281152, 388518272, 388755296, 388992224, 389229024, 389465728, 389702336, 389938816, 390175200, 390411488, 390647680, 390883744, 391119712, 391355584, 391591328, 391826976, 392062528, 392297984, 392533312, 392768544, 393003680, 393238720, 393473632, 393708448, 393943168, 394177760, 394412256, 394646656, 394880960, 395115136, 395349216, 395583200, 395817088, 396050848, 396284512, 396518080, 396751520, 396984864, 397218112, 397451264, 397684288, 397917248, 398150080, 398382784, 398615424, 398847936, 399080320, 399312640, 399544832, 399776928, 400008928, 400240832, 400472608, 400704288, 400935872, 401167328, 401398720, 401629984, 401861120, 402092192, 402323136, 402553984, 402784736, 403015360, 403245888, 403476320, 403706656, 403936896, 404167008, 404397024, 404626944, 404856736, 405086432, 405316032, 405545536, 405774912, 406004224, 406233408, 406462464, 406691456, 406920320, 407149088, 407377760, 407606336, 407834784, 408063136, 408291392, 408519520, 408747584, 408975520, 409203360, 409431072, 409658720, 409886240, 410113664, 410340992, 410568192, 410795296, 411022304, 411249216, 411476032, 411702720, 411929312, 412155808, 412382176, 412608480, 412834656, 413060736, 413286720, 413512576, 413738336, 413964000, 414189568, 414415040, 414640384, 414865632, 415090784, 415315840, 415540800, 415765632, 415990368, 416215008, 416439552, 416663968, 416888288, 417112512, 417336640, 417560672, 417784576, 418008384, 418232096, 418455712, 418679200, 418902624, 419125920, 419349120, 419572192, 419795200, 420018080, 420240864, 420463552, 420686144, 420908608, 421130976, 421353280, 421575424, 421797504, 422019488, 422241344, 422463104, 422684768, 422906336, 423127776, 423349120, 423570400, 423791520, 424012576, 424233536, 424454368, 424675104, 424895744, 425116288, 425336736, 425557056, 425777280, 425997408, 426217440, 426437376, 426657184, 426876928, 427096544, 427316064, 427535488, 427754784, 427974016, 428193120, 428412128, 428631040, 428849856, 429068544, 429287168, 429505664, 429724064, 429942368, 430160576, 430378656, 430596672, 430814560, 431032352, 431250048, 431467616, 431685120, 431902496, 432119808, 432336992, 432554080, 432771040, 432987936, 433204736, 433421408, 433637984, 433854464, 434070848, 434287104, 434503296, 434719360, 434935360, 435151232, 435367008, 435582656, 435798240, 436013696, 436229088, 436444352, 436659520, 436874592, 437089568, 437304416, 437519200, 437733856, 437948416, 438162880, 438377248, 438591520, 438805696, 439019744, 439233728, 439447584, 439661344, 439875008, 440088576, 440302048, 440515392, 440728672, 440941824, 441154880, 441367872, 441580736, 441793472, 442006144, 442218720, 442431168, 442643552, 442855808, 443067968, 443280032, 443492000, 443703872, 443915648, 444127296, 444338880, 444550336, 444761696, 444972992, 445184160, 445395232, 445606176, 445817056, 446027840, 446238496, 446449088, 446659552, 446869920, 447080192, 447290400, 447500448, 447710432, 447920320, 448130112, 448339776, 448549376, 448758848, 448968224, 449177536, 449386720, 449595808, 449804800, 450013664, 450222464, 450431168, 450639776, 450848256, 451056640, 451264960, 451473152, 451681248, 451889248, 452097152, 452304960, 452512672, 452720288, 452927808, 453135232, 453342528, 453549760, 453756864, 453963904, 454170816, 454377632, 454584384, 454791008, 454997536, 455203968, 455410304, 455616544, 455822688, 456028704, 456234656, 456440512, 456646240, 456851904, 457057472, 457262912, 457468256, 457673536, 457878688, 458083744, 458288736, 458493600, 458698368, 458903040, 459107616, 459312096, 459516480, 459720768, 459924960, 460129056, 460333056, 460536960, 460740736, 460944448, 461148064, 461351584, 461554976, 461758304, 461961536, 462164640, 462367680, 462570592, 462773440, 462976160, 463178816, 463381344, 463583776, 463786144, 463988384, 464190560, 464392608, 464594560, 464796448, 464998208, 465199872, 465401472, 465602944, 465804320, 466005600, 466206816, 466407904, 466608896, 466809824, 467010624, 467211328, 467411936, 467612480, 467812896, 468013216, 468213440, 468413600, 468613632, 468813568, 469013440, 469213184, 469412832, 469612416, 469811872, 470011232, 470210528, 470409696, 470608800, 470807776, 471006688, 471205472, 471404192, 471602784, 471801312, 471999712, 472198048, 472396288, 472594400, 472792448, 472990400, 473188256, 473385984, 473583648, 473781216, 473978688, 474176064, 474373344, 474570528, 474767616, 474964608, 475161504, 475358336, 475555040, 475751648, 475948192, 476144608, 476340928, 476537184, 476733312, 476929376, 477125344, 477321184, 477516960, 477712640, 477908224, 478103712, 478299104, 478494400, 478689600, 478884704, 479079744, 479274656, 479469504, 479664224, 479858880, 480053408, 480247872, 480442240, 480636512, 480830656, 481024736, 481218752, 481412640, 481606432, 481800128, 481993760, 482187264, 482380704, 482574016, 482767264, 482960416, 483153472, 483346432, 483539296, 483732064, 483924768, 484117344, 484309856, 484502240, 484694560, 484886784, 485078912, 485270944, 485462880, 485654720, 485846464, 486038144, 486229696, 486421184, 486612576, 486803840, 486995040, 487186176, 487377184, 487568096, 487758912, 487949664, 488140320, 488330880, 488521312, 488711712, 488901984, 489092160, 489282240, 489472256, 489662176, 489851968, 490041696, 490231328, 490420896, 490610336, 490799712, 490988960, 491178144, 491367232, 491556224, 491745120, 491933920, 492122656, 492311264, 492499808, 492688256, 492876608, 493064864, 493253056, 493441120, 493629120, 493817024, 494004832, 494192544, 494380160, 494567712, 494755136, 494942496, 495129760, 495316928, 495504000, 495691008, 495877888, 496064704, 496251424, 496438048, 496624608, 496811040, 496997408, 497183680, 497369856, 497555936, 497741920, 497927840, 498113632, 498299360, 498484992, 498670560, 498856000, 499041376, 499226656, 499411840, 499596928, 499781920, 499966848, 500151680, 500336416, 500521056, 500705600, 500890080, 501074464, 501258752, 501442944, 501627040, 501811072, 501995008, 502178848, 502362592, 502546240, 502729824, 502913312, 503096704, 503280000, 503463232, 503646368, 503829408, 504012352, 504195200, 504377984, 504560672, 504743264, 504925760, 505108192, 505290496, 505472736, 505654912, 505836960, 506018944, 506200832, 506382624, 506564320, 506745952, 506927488, 507108928, 507290272, 507471552, 507652736, 507833824, 508014816, 508195744, 508376576, 508557312, 508737952, 508918528, 509099008, 509279392, 509459680, 509639904, 509820032, 510000064, 510180000, 510359872, 510539648, 510719328, 510898944, 511078432, 511257856, 511437216, 511616448, 511795616, 511974688, 512153664, 512332576, 512511392, 512690112, 512868768, 513047296, 513225792, 513404160, 513582432, 513760640, 513938784, 514116800, 514294752, 514472608, 514650368, 514828064, 515005664, 515183168, 515360608, 515537952, 515715200, 515892352, 516069440, 516246432, 516423328, 516600160, 516776896, 516953536, 517130112, 517306592, 517482976, 517659264, 517835488, 518011616, 518187680, 518363648, 518539520, 518715296, 518891008, 519066624, 519242144, 519417600, 519592960, 519768256, 519943424, 520118528, 520293568, 520468480, 520643328, 520818112, 520992800, 521167392, 521341888, 521516320, 521690656, 521864896, 522039072, 522213152, 522387168, 522561056, 522734912, 522908640, 523082304, 523255872, 523429376, 523602784, 523776096, 523949312, 524122464, 524295552, 524468512, 524641440, 524814240, 524986976, 525159616, 525332192, 525504640, 525677056, 525849344, 526021568, 526193728, 526365792, 526537760, 526709632, 526881440, 527053152, 527224800, 527396352, 527567840, 527739200, 527910528, 528081728, 528252864, 528423936, 528594880, 528765760, 528936576, 529107296, 529277920, 529448480, 529618944, 529789344, 529959648, 530129856, 530300000, 530470048, 530640000, 530809888, 530979712, 531149440, 531319072, 531488608, 531658080, 531827488, 531996800, 532166016, 532335168, 532504224, 532673184, 532842080, 533010912, 533179616, 533348288, 533516832, 533685312, 533853728, 534022048, 534190272, 534358432, 534526496, 534694496, 534862400, 535030240, 535197984, 535365632, 535533216, 535700704, 535868128, 536035456, 536202720, 536369888, 536536992, 536704000, 536870912 }; fixed_t *finecosine = &finesine[FINEANGLES / 4]; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_things.c0000644000175000017500000003615011357170242022602 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_things.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "p_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static boolean ActivateThing(mobj_t *mobj); static boolean DeactivateThing(mobj_t *mobj); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- mobjtype_t TranslateThingType[] = { MT_MAPSPOT, // T_NONE MT_CENTAUR, // T_CENTAUR MT_CENTAURLEADER, // T_CENTAURLEADER MT_DEMON, // T_DEMON MT_ETTIN, // T_ETTIN MT_FIREDEMON, // T_FIREGARGOYLE MT_SERPENT, // T_WATERLURKER MT_SERPENTLEADER, // T_WATERLURKERLEADER MT_WRAITH, // T_WRAITH MT_WRAITHB, // T_WRAITHBURIED MT_FIREBALL1, // T_FIREBALL1 MT_MANA1, // T_MANA1 MT_MANA2, // T_MANA2 MT_SPEEDBOOTS, // T_ITEMBOOTS MT_ARTIEGG, // T_ITEMEGG MT_ARTIFLY, // T_ITEMFLIGHT MT_SUMMONMAULATOR, // T_ITEMSUMMON MT_TELEPORTOTHER, // T_ITEMTPORTOTHER MT_ARTITELEPORT, // T_ITEMTELEPORT MT_BISHOP, // T_BISHOP MT_ICEGUY, // T_ICEGOLEM MT_BRIDGE, // T_BRIDGE MT_BOOSTARMOR, // T_DRAGONSKINBRACERS MT_HEALINGBOTTLE, // T_ITEMHEALTHPOTION MT_HEALTHFLASK, // T_ITEMHEALTHFLASK MT_ARTISUPERHEAL, // T_ITEMHEALTHFULL MT_BOOSTMANA, // T_ITEMBOOSTMANA MT_FW_AXE, // T_FIGHTERAXE MT_FW_HAMMER, // T_FIGHTERHAMMER MT_FW_SWORD1, // T_FIGHTERSWORD1 MT_FW_SWORD2, // T_FIGHTERSWORD2 MT_FW_SWORD3, // T_FIGHTERSWORD3 MT_CW_SERPSTAFF, // T_CLERICSTAFF MT_CW_HOLY1, // T_CLERICHOLY1 MT_CW_HOLY2, // T_CLERICHOLY2 MT_CW_HOLY3, // T_CLERICHOLY3 MT_MW_CONE, // T_MAGESHARDS MT_MW_STAFF1, // T_MAGESTAFF1 MT_MW_STAFF2, // T_MAGESTAFF2 MT_MW_STAFF3, // T_MAGESTAFF3 MT_EGGFX, // T_MORPHBLAST MT_ROCK1, // T_ROCK1 MT_ROCK2, // T_ROCK2 MT_ROCK3, // T_ROCK3 MT_DIRT1, // T_DIRT1 MT_DIRT2, // T_DIRT2 MT_DIRT3, // T_DIRT3 MT_DIRT4, // T_DIRT4 MT_DIRT5, // T_DIRT5 MT_DIRT6, // T_DIRT6 MT_ARROW, // T_ARROW MT_DART, // T_DART MT_POISONDART, // T_POISONDART MT_RIPPERBALL, // T_RIPPERBALL MT_SGSHARD1, // T_STAINEDGLASS1 MT_SGSHARD2, // T_STAINEDGLASS2 MT_SGSHARD3, // T_STAINEDGLASS3 MT_SGSHARD4, // T_STAINEDGLASS4 MT_SGSHARD5, // T_STAINEDGLASS5 MT_SGSHARD6, // T_STAINEDGLASS6 MT_SGSHARD7, // T_STAINEDGLASS7 MT_SGSHARD8, // T_STAINEDGLASS8 MT_SGSHARD9, // T_STAINEDGLASS9 MT_SGSHARD0, // T_STAINEDGLASS0 MT_PROJECTILE_BLADE, // T_BLADE MT_ICESHARD, // T_ICESHARD MT_FLAME_SMALL, // T_FLAME_SMALL MT_FLAME_LARGE, // T_FLAME_LARGE MT_ARMOR_1, // T_MESHARMOR MT_ARMOR_2, // T_FALCONSHIELD MT_ARMOR_3, // T_PLATINUMHELM MT_ARMOR_4, // T_AMULETOFWARDING MT_ARTIPOISONBAG, // T_ITEMFLECHETTE MT_ARTITORCH, // T_ITEMTORCH MT_BLASTRADIUS, // T_ITEMREPULSION MT_MANA3, // T_MANA3 MT_ARTIPUZZSKULL, // T_PUZZSKULL MT_ARTIPUZZGEMBIG, // T_PUZZGEMBIG MT_ARTIPUZZGEMRED, // T_PUZZGEMRED MT_ARTIPUZZGEMGREEN1, // T_PUZZGEMGREEN1 MT_ARTIPUZZGEMGREEN2, // T_PUZZGEMGREEN2 MT_ARTIPUZZGEMBLUE1, // T_PUZZGEMBLUE1 MT_ARTIPUZZGEMBLUE2, // T_PUZZGEMBLUE2 MT_ARTIPUZZBOOK1, // T_PUZZBOOK1 MT_ARTIPUZZBOOK2, // T_PUZZBOOK2 MT_KEY1, // T_METALKEY MT_KEY2, // T_SMALLMETALKEY MT_KEY3, // T_AXEKEY MT_KEY4, // T_FIREKEY MT_KEY5, // T_GREENKEY MT_KEY6, // T_MACEKEY MT_KEY7, // T_SILVERKEY MT_KEY8, // T_RUSTYKEY MT_KEY9, // T_HORNKEY MT_KEYA, // T_SERPENTKEY MT_WATER_DRIP, // T_WATERDRIP MT_FLAME_SMALL_TEMP, // T_TEMPSMALLFLAME MT_FLAME_SMALL, // T_PERMSMALLFLAME MT_FLAME_LARGE_TEMP, // T_TEMPLARGEFLAME MT_FLAME_LARGE, // T_PERMLARGEFLAME MT_DEMON_MASH, // T_DEMON_MASH MT_DEMON2_MASH, // T_DEMON2_MASH MT_ETTIN_MASH, // T_ETTIN_MASH MT_CENTAUR_MASH, // T_CENTAUR_MASH MT_THRUSTFLOOR_UP, // T_THRUSTSPIKEUP MT_THRUSTFLOOR_DOWN, // T_THRUSTSPIKEDOWN MT_WRAITHFX4, // T_FLESH_DRIP1 MT_WRAITHFX5, // T_FLESH_DRIP2 MT_WRAITHFX2 // T_SPARK_DRIP }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- boolean EV_ThingProjectile(byte* args, boolean gravity) { uint an; int tid, searcher; angle_t angle; float speed, vspeed; mobjtype_t moType; mobj_t *mobj, *newMobj; boolean success; success = false; searcher = -1; tid = args[0]; moType = TranslateThingType[args[1]]; if(noMonstersParm && (MOBJINFO[moType].flags & MF_COUNTKILL)) { // Don't spawn monsters if -nomonsters return false; } angle = (int) args[2] << 24; an = angle >> ANGLETOFINESHIFT; speed = FIX2FLT((int) args[3] << 13); vspeed = FIX2FLT((int) args[4] << 13); while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) { if((newMobj = P_SpawnMobj3fv(moType, mobj->pos, angle, 0))) { if(newMobj->info->seeSound) S_StartSound(newMobj->info->seeSound, newMobj); newMobj->target = mobj; // Originator newMobj->mom[MX] = speed * FIX2FLT(finecosine[an]); newMobj->mom[MY] = speed * FIX2FLT(finesine[an]); newMobj->mom[MZ] = vspeed; newMobj->flags2 |= MF2_DROPPED; // Don't respawn if(gravity == true) { newMobj->flags &= ~MF_NOGRAVITY; newMobj->flags2 |= MF2_LOGRAV; } if(P_CheckMissileSpawn(newMobj) == true) { success = true; } } } return success; } boolean EV_ThingSpawn(byte *args, boolean fog) { int tid, searcher; angle_t angle; mobj_t *mobj, *newMobj, *fogMobj; mobjtype_t moType; boolean success; float z; success = false; searcher = -1; tid = args[0]; moType = TranslateThingType[args[1]]; if(noMonstersParm && (MOBJINFO[moType].flags & MF_COUNTKILL)) { // Don't spawn monsters if -nomonsters return false; } angle = (int) args[2] << 24; while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) { z = mobj->pos[VZ]; if((newMobj = P_SpawnMobj3fv(moType, mobj->pos, angle, 0))) { if(P_TestMobjLocation(newMobj) == false) { // Didn't fit P_MobjRemove(newMobj, true); } else { if(fog) { if((fogMobj = P_SpawnMobj3f(MT_TFOG, mobj->pos[VX], mobj->pos[VY], mobj->pos[VZ] + TELEFOGHEIGHT, angle + ANG180, 0))) S_StartSound(SFX_TELEPORT, fogMobj); } newMobj->flags2 |= MF2_DROPPED; // Don't respawn if(newMobj->flags2 & MF2_FLOATBOB) { newMobj->special1 = FLT2FIX(newMobj->pos[VZ] - newMobj->floorZ); } success = true; } } } return success; } boolean EV_ThingActivate(int tid) { mobj_t *mobj; int searcher; boolean success; success = false; searcher = -1; while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) { if(ActivateThing(mobj) == true) { success = true; } } return success; } boolean EV_ThingDeactivate(int tid) { mobj_t *mobj; int searcher; boolean success; success = false; searcher = -1; while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) { if(DeactivateThing(mobj) == true) { success = true; } } return success; } boolean EV_ThingRemove(int tid) { mobj_t *mobj; int searcher; boolean success; success = false; searcher = -1; while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) { if(mobj->type == MT_BRIDGE) { A_BridgeRemove(mobj); return true; } P_MobjRemove(mobj, false); success = true; } return success; } boolean EV_ThingDestroy(int tid) { mobj_t *mobj; int searcher; boolean success; success = false; searcher = -1; while((mobj = P_FindMobjFromTID(tid, &searcher)) != NULL) { if(mobj->flags & MF_SHOOTABLE) { P_DamageMobj(mobj, NULL, NULL, 10000, false); success = true; } } return success; } static boolean ActivateThing(mobj_t *mobj) { if(mobj->flags & MF_COUNTKILL) { // Monster if(mobj->flags2 & MF2_DORMANT) { mobj->flags2 &= ~MF2_DORMANT; mobj->tics = 1; return true; } return false; } switch(mobj->type) { case MT_ZTWINEDTORCH: case MT_ZTWINEDTORCH_UNLIT: P_MobjChangeState(mobj, S_ZTWINEDTORCH_1); S_StartSound(SFX_IGNITE, mobj); break; case MT_ZWALLTORCH: case MT_ZWALLTORCH_UNLIT: P_MobjChangeState(mobj, S_ZWALLTORCH1); S_StartSound(SFX_IGNITE, mobj); break; case MT_ZGEMPEDESTAL: P_MobjChangeState(mobj, S_ZGEMPEDESTAL2); break; case MT_ZWINGEDSTATUENOSKULL: P_MobjChangeState(mobj, S_ZWINGEDSTATUENOSKULL2); break; case MT_THRUSTFLOOR_UP: case MT_THRUSTFLOOR_DOWN: if(mobj->args[0] == 0) { S_StartSound(SFX_THRUSTSPIKE_LOWER, mobj); mobj->flags2 &= ~MF2_DONTDRAW; if(mobj->args[1]) P_MobjChangeState(mobj, S_BTHRUSTRAISE1); else P_MobjChangeState(mobj, S_THRUSTRAISE1); } break; case MT_ZFIREBULL: case MT_ZFIREBULL_UNLIT: P_MobjChangeState(mobj, S_ZFIREBULL_BIRTH); S_StartSound(SFX_IGNITE, mobj); break; case MT_ZBELL: if(mobj->health > 0) { P_DamageMobj(mobj, NULL, NULL, 10, false); // 'ring' the bell } break; case MT_ZCAULDRON: case MT_ZCAULDRON_UNLIT: P_MobjChangeState(mobj, S_ZCAULDRON1); S_StartSound(SFX_IGNITE, mobj); break; case MT_FLAME_SMALL: S_StartSound(SFX_IGNITE, mobj); P_MobjChangeState(mobj, S_FLAME_SMALL1); break; case MT_FLAME_LARGE: S_StartSound(SFX_IGNITE, mobj); P_MobjChangeState(mobj, S_FLAME_LARGE1); break; case MT_BAT_SPAWNER: P_MobjChangeState(mobj, S_SPAWNBATS1); break; default: return false; break; } return true; } static boolean DeactivateThing(mobj_t *mobj) { if(mobj->flags & MF_COUNTKILL) { // Monster if(!(mobj->flags2 & MF2_DORMANT)) { mobj->flags2 |= MF2_DORMANT; mobj->tics = -1; return true; } return false; } switch(mobj->type) { case MT_ZTWINEDTORCH: case MT_ZTWINEDTORCH_UNLIT: P_MobjChangeState(mobj, S_ZTWINEDTORCH_UNLIT); break; case MT_ZWALLTORCH: case MT_ZWALLTORCH_UNLIT: P_MobjChangeState(mobj, S_ZWALLTORCH_U); break; case MT_THRUSTFLOOR_UP: case MT_THRUSTFLOOR_DOWN: if(mobj->args[0] == 1) { S_StartSound(SFX_THRUSTSPIKE_RAISE, mobj); if(mobj->args[1]) P_MobjChangeState(mobj, S_BTHRUSTLOWER); else P_MobjChangeState(mobj, S_THRUSTLOWER); } break; case MT_ZFIREBULL: case MT_ZFIREBULL_UNLIT: P_MobjChangeState(mobj, S_ZFIREBULL_DEATH); break; case MT_ZCAULDRON: case MT_ZCAULDRON_UNLIT: P_MobjChangeState(mobj, S_ZCAULDRON_U); break; case MT_FLAME_SMALL: P_MobjChangeState(mobj, S_FLAME_SDORM1); break; case MT_FLAME_LARGE: P_MobjChangeState(mobj, S_FLAME_LDORM1); break; case MT_BAT_SPAWNER: P_MobjChangeState(mobj, S_SPAWNBATS_OFF); break; default: return false; break; } return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_enemy.c0000644000175000017500000035054211357170242022427 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.c: Enemy thinking, AI. * * Action Pointer Functions that are associated with states/frames. */ // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "dmu_lib.h" #include "p_mapspec.h" #include "p_map.h" #include "g_common.h" // MACROS ------------------------------------------------------------------ #define MONS_LOOK_RANGE (16*64) #define MONS_LOOK_LIMIT 64 #define MINOTAUR_LOOK_DIST (16*54) #define CORPSEQUEUESIZE 64 #define BODYQUESIZE 32 #define SORCBALL_INITIAL_SPEED 7 #define SORCBALL_TERMINAL_SPEED 25 #define SORCBALL_SPEED_ROTATIONS 5 #define SORC_DEFENSE_TIME 255 #define SORC_DEFENSE_HEIGHT 45 #define BOUNCE_TIME_UNIT (TICSPERSEC/2) #define SORCFX4_RAPIDFIRE_TIME (6*3) // 3 seconds #define SORCFX4_SPREAD_ANGLE 20 #define SORC_DECELERATE 0 #define SORC_ACCELERATE 1 #define SORC_STOPPING 2 #define SORC_FIRESPELL 3 #define SORC_STOPPED 4 #define SORC_NORMAL 5 #define SORC_FIRING_SPELL 6 #define BALL1_ANGLEOFFSET 0 #define BALL2_ANGLEOFFSET (ANGLE_MAX/3) #define BALL3_ANGLEOFFSET ((ANGLE_MAX/3)*2) #define KORAX_SPIRIT_LIFETIME (5*(TICSPERSEC/5)) // 5 seconds #define KORAX_COMMAND_HEIGHT (120) #define KORAX_COMMAND_OFFSET (27) #define KORAX_TID (245) #define KORAX_FIRST_TELEPORT_TID (248) #define KORAX_TELEPORT_TID (249) #define KORAX_DELTAANGLE (85*ANGLE_1) #define KORAX_ARM_EXTENSION_SHORT (40) #define KORAX_ARM_EXTENSION_LONG (55) #define KORAX_ARM1_HEIGHT (108) #define KORAX_ARM2_HEIGHT (82) #define KORAX_ARM3_HEIGHT (54) #define KORAX_ARM4_HEIGHT (104) #define KORAX_ARM5_HEIGHT (86) #define KORAX_ARM6_HEIGHT (53) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- void KSpiritInit(mobj_t *spirit, mobj_t *korax); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int maulatorSeconds = 25; boolean fastMonsters = false; // Eight directional movement speeds. #define MOVESPEED_DIAGONAL (0.71716309f) static const float dirSpeed[8][2] = { {1, 0}, {MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {0, 1}, {-MOVESPEED_DIAGONAL, MOVESPEED_DIAGONAL}, {-1, 0}, {-MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL}, {0, -1}, {MOVESPEED_DIAGONAL, -MOVESPEED_DIAGONAL} }; #undef MOVESPEED_DIAGONAL mobj_t *corpseQueue[CORPSEQUEUESIZE]; int corpseQueueSlot; mobj_t *bodyque[BODYQUESIZE]; int bodyqueslot; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * If a monster yells at a player, it will alert other monsters to the * player's whereabouts. */ void P_NoiseAlert(mobj_t *target, mobj_t *emitter) { VALIDCOUNT++; P_RecursiveSound(target, P_GetPtrp(emitter->subsector, DMU_SECTOR), 0); } boolean P_CheckMeleeRange(mobj_t *actor, boolean midrange) { mobj_t *pl; float dist, range; if(!actor->target) return false; pl = actor->target; dist = P_ApproxDistance(pl->pos[VX] - actor->pos[VX], pl->pos[VY] - actor->pos[VY]); if(!cfg.netNoMaxZMonsterMeleeAttack) { // Account for Z height difference. if(pl->pos[VZ] > actor->pos[VZ] + actor->height || pl->pos[VZ] + pl->height < actor->pos[VZ]) return false; } range = MELEERANGE - 20 + pl->info->radius; if(midrange) { if(dist >= range * 2 || dist < range) return false; } else { if(dist >= range) return false; } if(!P_CheckSight(actor, pl)) return false; return true; } boolean P_CheckMissileRange(mobj_t *mo) { float dist; if(!P_CheckSight(mo, mo->target)) { return false; } if(mo->flags & MF_JUSTHIT) { // The target just hit the enemy, so fight back! mo->flags &= ~MF_JUSTHIT; return true; } if(mo->reactionTime) return false; // Don't attack yet. dist = P_ApproxDistance(mo->pos[VX] - mo->target->pos[VX], mo->pos[VY] - mo->target->pos[VY]) - 64; if(P_GetState(mo->type, SN_MELEE) == S_NULL) { // No melee attack, so fire more frequently. dist -= 128; } if(dist > 200) { dist = 200; } if(P_Random() < dist) { return false; } return true; } /** * Move in the current direction. * * @return @c false, if the move is blocked. */ boolean P_Move(mobj_t *mo) { float tryPos[2], step[2]; linedef_t *ld; boolean good; if(mo->flags2 & MF2_BLASTED) return true; if(mo->moveDir == DI_NODIR) { return false; } step[VX] = mo->info->speed * dirSpeed[mo->moveDir][VX]; step[VY] = mo->info->speed * dirSpeed[mo->moveDir][VY]; tryPos[VX] = mo->pos[VX] + step[VX]; tryPos[VY] = mo->pos[VY] + step[VY]; if(!P_TryMove(mo, tryPos[VX], tryPos[VY])) { // Open any specials. if((mo->flags & MF_FLOAT) && floatOk) { // Must adjust height. if(mo->pos[VZ] < tmFloorZ) { mo->pos[VZ] += FLOATSPEED; } else { mo->pos[VZ] -= FLOATSPEED; } mo->flags |= MF_INFLOAT; return true; } if(!P_IterListSize(spechit)) return false; mo->moveDir = DI_NODIR; good = false; while((ld = P_PopIterList(spechit)) != NULL) { // If the special isn't a door that can be opened, return false. if(P_ActivateLine(ld, mo, 0, SPAC_USE)) { good = true; } } return good; } else { P_MobjSetSRVO(mo, step[VX], step[VY]); mo->flags &= ~MF_INFLOAT; } if(!(mo->flags & MF_FLOAT)) { if(mo->pos[VZ] > mo->floorZ) { P_HitFloor(mo); } mo->pos[VZ] = mo->floorZ; } return true; } /** * Attempts to move actor in its current (ob->moveangle) direction. * If a door is in the way, an OpenDoor call is made to start it opening. * * @return @c false, if blocked by either a wall or an actor. */ boolean P_TryWalk(mobj_t *actor) { if(!P_Move(actor)) { return false; } actor->moveCount = P_Random() & 15; return true; } static void newChaseDir(mobj_t *actor, float deltaX, float deltaY) { dirtype_t xdir, ydir, tdir; dirtype_t olddir = actor->moveDir; dirtype_t turnaround = olddir; if(turnaround != DI_NODIR) // find reverse direction turnaround ^= 4; xdir = (deltaX > 10 ? DI_EAST : deltaX < -10 ? DI_WEST : DI_NODIR); ydir = (deltaY < -10 ? DI_SOUTH : deltaY > 10 ? DI_NORTH : DI_NODIR); // Try direct route. if(xdir != DI_NODIR && ydir != DI_NODIR && turnaround != (actor->moveDir = deltaY < 0 ? deltaX > 0 ? DI_SOUTHEAST : DI_SOUTHWEST : deltaX > 0 ? DI_NORTHEAST : DI_NORTHWEST) && P_TryWalk(actor)) return; // Try other directions. if(P_Random() > 200 || fabs(deltaY) > fabs(deltaX)) { dirtype_t temp = xdir; xdir = ydir; ydir = temp; } if((xdir == turnaround ? xdir = DI_NODIR : xdir) != DI_NODIR && (actor->moveDir = xdir, P_TryWalk(actor))) return; // Either moved forward or attacked. if((ydir == turnaround ? ydir = DI_NODIR : ydir) != DI_NODIR && (actor->moveDir = ydir, P_TryWalk(actor))) return; // There is no direct path to the player, so pick another direction. if(olddir != DI_NODIR && (actor->moveDir = olddir, P_TryWalk(actor))) return; // Randomly determine direction of search. if(P_Random() & 1) { for(tdir = DI_EAST; tdir <= DI_SOUTHEAST; tdir++) if(tdir != turnaround && (actor->moveDir = tdir, P_TryWalk(actor))) return; } else { for(tdir = DI_SOUTHEAST; tdir != DI_EAST - 1; tdir--) if(tdir != turnaround && (actor->moveDir = tdir, P_TryWalk(actor))) return; } if((actor->moveDir = turnaround) != DI_NODIR && !P_TryWalk(actor)) actor->moveDir = DI_NODIR; } void P_NewChaseDir(mobj_t *actor) { float delta[2]; if(!actor->target) Con_Error("P_NewChaseDir: called with no target"); delta[VX] = actor->target->pos[VX] - actor->pos[VX]; delta[VY] = actor->target->pos[VY] - actor->pos[VY]; newChaseDir(actor, delta[VX], delta[VY]); } typedef struct { size_t count; size_t maxTries; mobj_t* notThis; mobj_t* foundMobj; float origin[2]; float maxDistance; int minHealth; int compFlags; boolean checkLOS; mobj_t* checkMinotaurTracer; byte randomSkip; } findmobjparams_t; static boolean findMobj(thinker_t* th, void* context) { findmobjparams_t* params = (findmobjparams_t*) context; mobj_t* mo = (mobj_t *) th; // Flags requirement? if(params->compFlags > 0 && !(mo->flags & params->compFlags)) return true; // Continue iteration. // Minimum health requirement? if(params->minHealth > 0 && mo->health < params->minHealth) return true; // Continue iteration. // Exclude this mobj? if(params->notThis && mo == params->notThis) return true; // Continue iteration. // Out of range? if(params->maxDistance > 0 && P_ApproxDistance(params->origin[VX] - mo->pos[VX], params->origin[VY] - mo->pos[VY]) > params->maxDistance) return true; // Continue iteration. // Randomly skip this? if(params->randomSkip && P_Random() < params->randomSkip) return true; // Continue iteration. if(params->maxTries > 0 && params->count++ > params->maxTries) return false; // Stop iteration. // Out of sight? if(params->checkLOS && params->notThis && !P_CheckSight(params->notThis, mo)) return true; // Continue iteration. // Check the special case of a minotaur looking at it's master. if(params->checkMinotaurTracer) if(mo->type == MT_MINOTAUR && mo->target != params->checkMinotaurTracer) return true; // Continue iteration. // Found one! params->foundMobj = mo; return false; // Stop iteration. } boolean P_LookForMonsters(mobj_t* mo) { findmobjparams_t params; if(!P_CheckSight(players[0].plr->mo, mo)) return false; // Player can't see the monster. params.count = 0; params.notThis = mo; params.origin[VX] = mo->pos[VX]; params.origin[VY] = mo->pos[VY]; params.foundMobj = NULL; params.maxDistance = MONS_LOOK_RANGE; params.maxTries = MONS_LOOK_LIMIT; params.minHealth = 1; params.compFlags = MF_COUNTKILL; params.checkLOS = true; params.randomSkip = 16; params.checkMinotaurTracer = (mo->type == MT_MINOTAUR)? ((player_t *) mo->tracer)->plr->mo : NULL; DD_IterateThinkers(P_MobjThinker, findMobj, ¶ms); if(params.foundMobj) { mo->target = params.foundMobj; return true; } return false; } /** * @param allaround @c false = only look 180 degrees in front of * the actor. * * @return @c true, if a player was targeted. */ boolean P_LookForPlayers(mobj_t *actor, boolean allaround) { int c, stop; player_t *player; sector_t *sector; angle_t angle; float dist; if(!IS_NETGAME && players[0].health <= 0) { // Single player game and player is dead, look for monsters return P_LookForMonsters(actor); } sector = P_GetPtrp(actor->subsector, DMU_SECTOR); c = 0; stop = (actor->lastLook - 1) & 3; for(;; actor->lastLook = (actor->lastLook + 1) & 3) { if(actor->lastLook == stop) return false; // Time to stop looking. if(!players[actor->lastLook].plr->inGame) continue; if(c++ == 2) return false; // Done looking. player = &players[actor->lastLook]; if(player->health <= 0) continue; // Dead. if(!P_CheckSight(actor, player->plr->mo)) continue; // Out of sight. if(!allaround) { angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], player->plr->mo->pos[VX], player->plr->mo->pos[VY]) - actor->angle; if(angle > ANG90 && angle < ANG270) { dist = P_ApproxDistance(player->plr->mo->pos[VX] - actor->pos[VX], player->plr->mo->pos[VY] - actor->pos[VY]); // If real close, react anyway. if(dist > MELEERANGE) continue; // Behind back. } } if(player->plr->mo->flags & MF_SHADOW) { // Player is invisible. if((P_ApproxDistance (player->plr->mo->pos[VX] - actor->pos[VX], player->plr->mo->pos[VY] - actor->pos[VY]) > 2 * MELEERANGE) && P_ApproxDistance(player->plr->mo->mom[MX], player->plr->mo->mom[MY]) < 5) { // Player is sneaking - can't detect. return false; } if(P_Random() < 225) { // Player isn't sneaking, but still didn't detect. return false; } } if(actor->type == MT_MINOTAUR) { if(((player_t *) (actor->tracer)) == player) continue; // Don't target master. } actor->target = player->plr->mo; return true; } } /** * Stay in state until a player is sighted. */ void C_DECL A_Look(mobj_t *actor) { mobj_t *targ; actor->threshold = 0; // Any shot will wake up. targ = P_ToXSectorOfSubsector(actor->subsector)->soundTarget; if(targ && (targ->flags & MF_SHOOTABLE)) { actor->target = targ; if(actor->flags & MF_AMBUSH) { if(P_CheckSight(actor, actor->target)) goto seeyou; } else goto seeyou; } if(!P_LookForPlayers(actor, false)) return; // go into chase state seeyou: if(actor->info->seeSound) { int sound; sound = actor->info->seeSound; if(actor->flags2 & MF2_BOSS) { // Full volume S_StartSound(sound, NULL); } else { S_StartSound(sound, actor); } } P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } /** * Actor has a melee attack, so it tries to close as fast as possible. */ void C_DECL A_Chase(mobj_t* actor) { int delta; statenum_t state; if(actor->reactionTime) actor->reactionTime--; // Modify target threshold if(actor->threshold) { actor->threshold--; } if(gameSkill == SM_NIGHTMARE || (fastMonsters /*&& INCOMPAT_OK */ )) { // Monsters move faster in nightmare mode actor->tics -= actor->tics / 2; if(actor->tics < 3) { actor->tics = 3; } } // Turn towards movement direction if not there yet. if(actor->moveDir < DI_NODIR) { actor->angle &= (7 << 29); delta = actor->angle - (actor->moveDir << 29); if(delta > 0) { actor->angle -= ANG90 / 2; } else if(delta < 0) { actor->angle += ANG90 / 2; } } if(!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { // Look for a new target. if(P_LookForPlayers(actor, true)) { // Got a new target. return; } P_MobjChangeState(actor, P_GetState(actor->type, SN_SPAWN)); return; } // Don't attack twice in a row. if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if(gameSkill != SM_NIGHTMARE) P_NewChaseDir(actor); return; } // Check for melee attack. if((state = P_GetState(actor->type, SN_MELEE)) != S_NULL && P_CheckMeleeRange(actor, false)) { if(actor->info->attackSound) { S_StartSound(actor->info->attackSound, actor); } P_MobjChangeState(actor, state); return; } // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { if(!(gameSkill < SM_NIGHTMARE && actor->moveCount)) { if(P_CheckMissileRange(actor)) { P_MobjChangeState(actor, state); actor->flags |= MF_JUSTATTACKED; return; } } } // Possibly choose another target. if(IS_NETGAME && !actor->threshold && !P_CheckSight(actor, actor->target)) { if(P_LookForPlayers(actor, true)) return; // Got a new target. } // Chase towards player. if(--actor->moveCount < 0 || !P_Move(actor)) { P_NewChaseDir(actor); } // Make active sound. if(actor->info->activeSound && P_Random() < 3) { if(actor->type == MT_BISHOP && P_Random() < 128) { S_StartSound(actor->info->seeSound, actor); } else if(actor->type == MT_PIG) { S_StartSound(SFX_PIG_ACTIVE1 + (P_Random() & 1), actor); } else if(actor->flags2 & MF2_BOSS) { S_StartSound(actor->info->activeSound, NULL); } else { S_StartSound(actor->info->activeSound, actor); } } } void C_DECL A_FaceTarget(mobj_t *actor) { if(!actor->target) return; actor->turnTime = true; // $visangle-facetarget actor->flags &= ~MF_AMBUSH; actor->angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], actor->target->pos[VX], actor->target->pos[VY]); if(actor->target->flags & MF_SHADOW) { // Target is a ghost actor->angle += (P_Random() - P_Random()) << 21; } } void C_DECL A_Pain(mobj_t *actor) { if(actor->info->painSound) { S_StartSound(actor->info->painSound, actor); } } void C_DECL A_SetInvulnerable(mobj_t *actor) { actor->flags2 |= MF2_INVULNERABLE; } void C_DECL A_UnSetInvulnerable(mobj_t *actor) { actor->flags2 &= ~MF2_INVULNERABLE; } void C_DECL A_SetReflective(mobj_t *actor) { actor->flags2 |= MF2_REFLECTIVE; if(actor->type == MT_CENTAUR || actor->type == MT_CENTAURLEADER) { A_SetInvulnerable(actor); } } void C_DECL A_UnSetReflective(mobj_t *actor) { actor->flags2 &= ~MF2_REFLECTIVE; if(actor->type == MT_CENTAUR || actor->type == MT_CENTAURLEADER) { A_UnSetInvulnerable(actor); } } /** * @return @c true, if the pig morphs. */ boolean P_UpdateMorphedMonster(mobj_t *actor, int tics) { mobj_t *fog; float pos[3]; mobjtype_t moType; mobj_t *mo, oldMonster; actor->special1 -= tics; if(actor->special1 > 0) { return false; } moType = actor->special2; switch(moType) { case MT_WRAITHB: // These must remain morphed. case MT_SERPENT: case MT_SERPENTLEADER: case MT_MINOTAUR: return false; default: break; } memcpy(pos, actor->pos, sizeof(pos)); //// \fixme Do this properly! oldMonster = *actor; // Save pig vars. P_MobjRemoveFromTIDList(actor); P_MobjChangeState(actor, S_FREETARGMOBJ); if(!(mo = P_SpawnMobj3fv(moType, pos, oldMonster.angle, 0))) return false; if(!P_TestMobjLocation(mo)) { // Didn't fit. P_MobjRemove(mo, true); if((mo = P_SpawnMobj3fv(oldMonster.type, pos, oldMonster.angle, 0))) { mo->flags = oldMonster.flags; mo->health = oldMonster.health; mo->target = oldMonster.target; mo->special = oldMonster.special; mo->special1 = 5 * TICSPERSEC; // Next try in 5 seconds. mo->special2 = moType; mo->tid = oldMonster.tid; memcpy(mo->args, oldMonster.args, 5); P_MobjInsertIntoTIDList(mo, oldMonster.tid); } return false; } mo->target = oldMonster.target; mo->tid = oldMonster.tid; mo->special = oldMonster.special; memcpy(mo->args, oldMonster.args, 5); P_MobjInsertIntoTIDList(mo, oldMonster.tid); if((fog = P_SpawnMobj3f(MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, oldMonster.angle + ANG180, 0))) S_StartSound(SFX_TELEPORT, fog); return true; } void C_DECL A_PigLook(mobj_t *actor) { if(P_UpdateMorphedMonster(actor, 10)) { return; } A_Look(actor); } void C_DECL A_PigChase(mobj_t *actor) { if(P_UpdateMorphedMonster(actor, 3)) { return; } A_Chase(actor); } void C_DECL A_PigAttack(mobj_t *actor) { if(P_UpdateMorphedMonster(actor, 18)) { return; } if(!actor->target) return; if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, 2 + (P_Random() & 1), false); S_StartSound(SFX_PIG_ATTACK, actor); } } void C_DECL A_PigPain(mobj_t *actor) { A_Pain(actor); if(actor->pos[VZ] <= actor->floorZ) { actor->mom[MZ] = 3.5f; } } void FaceMovementDirection(mobj_t *actor) { switch(actor->moveDir) { case DI_EAST: actor->angle = 0 << 24; break; case DI_NORTHEAST: actor->angle = 32 << 24; break; case DI_NORTH: actor->angle = 64 << 24; break; case DI_NORTHWEST: actor->angle = 96 << 24; break; case DI_WEST: actor->angle = 128 << 24; break; case DI_SOUTHWEST: actor->angle = 160 << 24; break; case DI_SOUTH: actor->angle = 192 << 24; break; case DI_SOUTHEAST: actor->angle = 224 << 24; break; } } /** * Minotaur variables * * special1 pointer to player that spawned it (mobj_t) * special2 internal to minotaur AI * args[0] args[0]-args[3] together make up minotaur start time * args[1] | * args[2] | * args[3] V * args[4] charge duration countdown */ void C_DECL A_MinotaurFade0(mobj_t *actor) { actor->flags &= ~MF_ALTSHADOW; actor->flags |= MF_SHADOW; } void C_DECL A_MinotaurFade1(mobj_t *actor) { // Second level of transparency actor->flags &= ~MF_SHADOW; actor->flags |= MF_ALTSHADOW; } void C_DECL A_MinotaurFade2(mobj_t *actor) { // Make fully visible actor->flags &= ~MF_SHADOW; actor->flags &= ~MF_ALTSHADOW; } void C_DECL A_MinotaurRoam(mobj_t *actor) { unsigned int *startTime = (unsigned int *) actor->args; actor->flags &= ~MF_SHADOW; // In case pain caused him to actor->flags &= ~MF_ALTSHADOW; // Skip his fade in. if((mapTime - *startTime) >= MAULATORTICS) { P_DamageMobj(actor, NULL, NULL, 10000, false); return; } if(P_Random() < 30) A_MinotaurLook(actor); // Adjust to closest target. if(P_Random() < 6) { // Choose new direction actor->moveDir = P_Random() % 8; FaceMovementDirection(actor); } if(!P_Move(actor)) { // Turn if(P_Random() & 1) actor->moveDir = (++actor->moveDir) % 8; else actor->moveDir = (actor->moveDir + 7) % 8; FaceMovementDirection(actor); } } typedef struct { mobj_t* notThis, *notThis2; mobj_t* checkMinotaurTracer; float origin[2]; float maxDistance; int minHealth; mobj_t* foundMobj; } findmonsterparams_t; static boolean findMonster(thinker_t* th, void* context) { findmonsterparams_t* params = (findmonsterparams_t*) context; mobj_t* mo = (mobj_t *) th; if(!(mo->flags & MF_COUNTKILL)) return true; // Continue iteration. // Health requirement? if(!(params->minHealth < 0) && mo->health < params->minHealth) return true; // Continue iteration. if(!(mo->flags & MF_SHOOTABLE)) return true; // Continue iteration. // Within range? if(params->maxDistance > 0) { float dist = P_ApproxDistance(params->origin[VX] - mo->pos[VX], params->origin[VY] - mo->pos[VY]); if(dist > params->maxDistance) return true; // Continue iteration. } if(params->notThis && params->notThis == mo) return true; // Continue iteration. if(params->notThis2 && params->notThis2 == mo) return true; // Continue iteration. // Check the special case for minotaurs. if(params->checkMinotaurTracer) if(mo->type == MT_MINOTAUR && params->checkMinotaurTracer == mo->tracer) return true; // Continue iteration. // Found one! params->foundMobj = mo; return false; // Stop iteration. } /** * Look for enemy of player. */ void C_DECL A_MinotaurLook(mobj_t *actor) { mobj_t* master = actor->tracer; actor->target = NULL; if(deathmatch) // Quick search for players. { int i; float dist; player_t* player; mobj_t* mo; for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; player = &players[i]; mo = player->plr->mo; if(mo == master) continue; if(mo->health <= 0) continue; dist = P_ApproxDistance(actor->pos[VX] - mo->pos[VX], actor->pos[VY] - mo->pos[VY]); if(dist > MINOTAUR_LOOK_DIST) continue; actor->target = mo; break; } } if(!actor->target) // Near player monster search. { if(master && (master->health > 0) && (master->player)) actor->target = P_RoughMonsterSearch(master, 20*128); else actor->target = P_RoughMonsterSearch(actor, 20*128); } if(!actor->target) // Normal monster search. { findmonsterparams_t params; params.notThis = actor; params.notThis2 = master; params.origin[VX] = actor->pos[VX]; params.origin[VY] = actor->pos[VY]; params.maxDistance = MINOTAUR_LOOK_DIST; params.foundMobj = NULL; params.minHealth = 1; params.checkMinotaurTracer = actor->tracer; if(!DD_IterateThinkers(P_MobjThinker, findMonster, ¶ms)) actor->target = params.foundMobj; } if(actor->target) { P_SetMobjStateNF(actor, S_MNTR_WALK1); } else { P_SetMobjStateNF(actor, S_MNTR_ROAM1); } } void C_DECL A_MinotaurChase(mobj_t* actor) { unsigned int* startTime = (unsigned int *) actor->args; statenum_t state; actor->flags &= ~MF_SHADOW; // In case pain caused him to. actor->flags &= ~MF_ALTSHADOW; // Skip his fade in. if((mapTime - *startTime) >= MAULATORTICS) { P_DamageMobj(actor, NULL, NULL, 10000, false); return; } if(P_Random() < 30) A_MinotaurLook(actor); // Adjust to closest target. if(!actor->target || (actor->target->health <= 0) || !(actor->target->flags & MF_SHOOTABLE)) { // Look for a new target. P_MobjChangeState(actor, S_MNTR_LOOK1); return; } FaceMovementDirection(actor); actor->reactionTime = 0; // Melee attack. if((state = P_GetState(actor->type, SN_MELEE)) != S_NULL && P_CheckMeleeRange(actor, false)) { if(actor->info->attackSound) S_StartSound(actor->info->attackSound, actor); P_MobjChangeState(actor, state); return; } // Missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL && P_CheckMissileRange(actor)) { P_MobjChangeState(actor, state); return; } // Chase towards target. if(!P_Move(actor)) { P_NewChaseDir(actor); } // Active sound. if(actor->info->activeSound && P_Random() < 6) S_StartSound(actor->info->activeSound, actor); } /** * Minotaur: Melee attack. */ void C_DECL A_MinotaurAtk1(mobj_t *actor) { if(!actor->target) return; S_StartSound(SFX_MAULATOR_HAMMER_SWING, actor); if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, HITDICE(4), false); } } /** * Minotaur: Choose a missile attack. */ void C_DECL A_MinotaurDecide(mobj_t *actor) { #define MNTR_CHARGE_SPEED (23) uint an; mobj_t *target = actor->target; float dist; if(!target) return; dist = P_ApproxDistance(actor->pos[VX] - target->pos[VX], actor->pos[VY] - target->pos[VY]); if(target->pos[VZ] + target->height > actor->pos[VZ] && target->pos[VZ] + target->height < actor->pos[VZ] + actor->height && dist < 16 * 64 && dist > 1 *64) { if(P_Random() < 230) { // Charge attack. // Don't call the state function right away. P_SetMobjStateNF(actor, S_MNTR_ATK4_1); actor->flags |= MF_SKULLFLY; A_FaceTarget(actor); an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = MNTR_CHARGE_SPEED * FIX2FLT(finecosine[an]); actor->mom[MY] = MNTR_CHARGE_SPEED * FIX2FLT(finesine[an]); actor->args[4] = TICRATE / 2; // Charge duration. return; } } if(target->pos[VZ] == target->floorZ && dist < 9 * 64) { if(P_Random() < 100) { // Floor fire attack. P_MobjChangeState(actor, S_MNTR_ATK3_1); actor->special2 = 0; return; } } // Swing attack. A_FaceTarget(actor); // Don't need to call P_MobjChangeState because the current state // falls through to the swing attack. #undef MNTR_CHARGE_SPEED } /** * Minotaur: Charge attack. */ void C_DECL A_MinotaurCharge(mobj_t* actor) { mobj_t* puff; if(!actor->target) return; if(actor->args[4] > 0) { if((puff = P_SpawnMobj3fv(MT_PUNCHPUFF, actor->pos, P_Random() << 24, 0))) { puff->mom[MZ] = 2; } actor->args[4]--; } else { actor->flags &= ~MF_SKULLFLY; P_MobjChangeState(actor, P_GetState(actor->type, SN_SEE)); } } /** * Minotaur: Swing attack. */ void C_DECL A_MinotaurAtk2(mobj_t *mo) { mobj_t *pmo; angle_t angle; float momZ; if(!mo->target) return; S_StartSound(SFX_MAULATOR_HAMMER_SWING, mo); if(P_CheckMeleeRange(mo, false)) { P_DamageMobj(mo->target, mo, mo, HITDICE(3), false); return; } pmo = P_SpawnMissile(MT_MNTRFX1, mo, mo->target); if(pmo) { momZ = pmo->mom[MZ]; angle = pmo->angle; P_SpawnMissileAngle(MT_MNTRFX1, mo, angle - (ANG45 / 8), momZ); P_SpawnMissileAngle(MT_MNTRFX1, mo, angle + (ANG45 / 8), momZ); P_SpawnMissileAngle(MT_MNTRFX1, mo, angle - (ANG45 / 16), momZ); P_SpawnMissileAngle(MT_MNTRFX1, mo, angle + (ANG45 / 16), momZ); } } /** * Minotaur: Floor fire attack. */ void C_DECL A_MinotaurAtk3(mobj_t *actor) { mobj_t *mo; player_t *player; if(!actor->target) return; if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, HITDICE(3), false); if((player = actor->target->player) != NULL) { // Squish the player. player->viewHeightDelta = -16; } } else { mo = P_SpawnMissile(MT_MNTRFX2, actor, actor->target); if(mo != NULL) { S_StartSound(SFX_MAULATOR_HAMMER_HIT, mo); } } if(P_Random() < 192 && actor->special2 == 0) { P_MobjChangeState(actor, S_MNTR_ATK3_4); actor->special2 = 1; } } void C_DECL A_MntrFloorFire(mobj_t* actor) { mobj_t* mo; float pos[3]; angle_t angle; // Make sure we are on the floor. actor->pos[VZ] = actor->floorZ; pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = 0; pos[VX] += FIX2FLT((P_Random() - P_Random()) << 10); pos[VY] += FIX2FLT((P_Random() - P_Random()) << 10); angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], pos[VX], pos[VY]); if((mo = P_SpawnMobj3fv(MT_MNTRFX3, pos, angle, MSF_Z_FLOOR))) { mo->target = actor->target; mo->mom[MX] = FIX2FLT(1); // Force block checking. P_CheckMissileSpawn(mo); } } void C_DECL A_Scream(mobj_t* actor) { int sound; S_StopSound(0, actor); if(actor->player) { if(actor->player->morphTics) { S_StartSound(actor->info->deathSound, actor); } else { // Handle the different player death screams. if(actor->mom[MZ] <= -39) { // Falling splat. sound = SFX_PLAYER_FALLING_SPLAT; } else if(actor->health > -50) { // Normal death sound. //// \todo pull these from the class def. switch(actor->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_NORMAL_DEATH; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_NORMAL_DEATH; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_NORMAL_DEATH; break; default: sound = SFX_NONE; break; } } else if(actor->health > -100) { // Crazy death sound. //// \todo pull these from the class def. switch(actor->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_CRAZY_DEATH; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_CRAZY_DEATH; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_CRAZY_DEATH; break; default: sound = SFX_NONE; break; } } else { // Extreme death sound. //// \todo pull these from the class def. switch(actor->player->class) { case PCLASS_FIGHTER: sound = SFX_PLAYER_FIGHTER_EXTREME1_DEATH; break; case PCLASS_CLERIC: sound = SFX_PLAYER_CLERIC_EXTREME1_DEATH; break; case PCLASS_MAGE: sound = SFX_PLAYER_MAGE_EXTREME1_DEATH; break; default: sound = SFX_NONE; break; } sound += P_Random() % 3; // Three different extreme deaths. } S_StartSound(sound, actor); } } else { S_StartSound(actor->info->deathSound, actor); } } void C_DECL A_NoBlocking(mobj_t *actor) { actor->flags &= ~MF_SOLID; } void C_DECL A_Explode(mobj_t *actor) { int damage; float distance; boolean damageSelf; damage = 128; distance = 128; damageSelf = true; switch(actor->type) { case MT_FIREBOMB: // Time Bombs. actor->pos[VZ] += 32; actor->flags &= ~MF_SHADOW; break; case MT_MNTRFX2: // Minotaur floor fire. damage = 24; break; case MT_BISHOP: // Bishop radius death. damage = 25 + (P_Random() & 15); break; case MT_HAMMER_MISSILE: // Fighter Hammer. damage = 128; damageSelf = false; break; case MT_FSWORD_MISSILE: // Fighter Runesword. damage = 64; damageSelf = false; break; case MT_CIRCLEFLAME: // Cleric Flame secondary flames. damage = 20; damageSelf = false; break; case MT_SORCBALL1: // Sorcerer balls. case MT_SORCBALL2: case MT_SORCBALL3: distance = 255; damage = 255; actor->args[0] = 1; // Don't play bounce. break; case MT_SORCFX1: // Sorcerer spell 1. damage = 30; break; case MT_SORCFX4: // Sorcerer spell 4. damage = 20; break; case MT_TREEDESTRUCTIBLE: damage = 10; break; case MT_DRAGON_FX2: damage = 80; damageSelf = false; break; case MT_MSTAFF_FX: damage = 64; distance = 192; damageSelf = false; break; case MT_MSTAFF_FX2: damage = 80; distance = 192; damageSelf = false; break; case MT_POISONCLOUD: damage = 4; distance = 40; break; case MT_ZXMAS_TREE: case MT_ZSHRUB2: damage = 30; distance = 64; break; default: break; } P_RadiusAttack(actor, actor->target, damage, distance, damageSelf); if(actor->pos[VZ] <= actor->floorZ + distance && actor->type != MT_POISONCLOUD) { P_HitFloor(actor); } } static boolean massacreMobj(thinker_t* th, void* context) { int* count = (int*) context; mobj_t* mo = (mobj_t *) th; if(!mo->player && sentient(mo) && (mo->flags & MF_SHOOTABLE)) { mo->flags2 &= ~(MF2_NONSHOOTABLE + MF2_INVULNERABLE); mo->flags |= MF_SHOOTABLE; P_DamageMobj(mo, NULL, NULL, 10000, false); (*count)++; } return true; // Continue iteration. } /** * Kills all monsters. */ int P_Massacre(void) { int count = 0; // Only massacre when actually in a map. if(G_GetGameState() == GS_MAP) { DD_IterateThinkers(P_MobjThinker, massacreMobj, &count); } return count; } void C_DECL A_SkullPop(mobj_t *actor) { mobj_t* mo; player_t* plr; if(!actor->player) return; actor->flags &= ~MF_SOLID; if((mo = P_SpawnMobj3f(MT_BLOODYSKULL, actor->pos[VX], actor->pos[VY], actor->pos[VZ] + 48, actor->angle, 0))) { mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); mo->mom[MZ] = 2 + FIX2FLT(P_Random() << 6); // Attach player mobj to bloody skull. plr = actor->player; actor->player = NULL; actor->dPlayer = NULL; actor->special1 = plr->class; mo->player = plr; mo->dPlayer = plr->plr; mo->health = actor->health; plr->plr->mo = mo; plr->plr->lookDir = 0; plr->damageCount = 32; } } void C_DECL A_CheckSkullFloor(mobj_t *actor) { if(actor->pos[VZ] <= actor->floorZ) { P_MobjChangeState(actor, S_BLOODYSKULLX1); S_StartSound(SFX_DRIP, actor); } } void C_DECL A_CheckSkullDone(mobj_t *actor) { if(actor->special2 == 666) { P_MobjChangeState(actor, S_BLOODYSKULLX2); } } void C_DECL A_CheckBurnGone(mobj_t *actor) { if(actor->special2 == 666) { P_MobjChangeState(actor, S_PLAY_FDTH20); } } void C_DECL A_FreeTargMobj(mobj_t *mo) { mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; mo->pos[VZ] = mo->ceilingZ + 4; mo->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_SOLID | MF_COUNTKILL); mo->flags |= MF_CORPSE | MF_DROPOFF | MF_NOGRAVITY; mo->flags2 &= ~(MF2_PASSMOBJ | MF2_LOGRAV); mo->flags2 |= MF2_DONTDRAW; mo->player = NULL; mo->dPlayer = NULL; mo->health = -1000; // Don't resurrect. } /** * Throw another corpse on the queue. */ void C_DECL A_QueueCorpse(mobj_t *actor) { mobj_t *corpse; if(corpseQueueSlot >= CORPSEQUEUESIZE) { // Too many corpses - remove an old one corpse = corpseQueue[corpseQueueSlot % CORPSEQUEUESIZE]; if(corpse) P_MobjRemove(corpse, false); } corpseQueue[corpseQueueSlot % CORPSEQUEUESIZE] = actor; corpseQueueSlot++; } /** * Remove a mobj from the queue (for resurrection). */ void C_DECL A_DeQueueCorpse(mobj_t *actor) { int slot; for(slot = 0; slot < CORPSEQUEUESIZE; ++slot) { if(corpseQueue[slot] == actor) { corpseQueue[slot] = NULL; break; } } } static boolean addMobjToCorpseQueue(thinker_t* th, void* context) { mobj_t* mo = (mobj_t *) th; // Must be a corpse. if(!(mo->flags & MF_CORPSE)) return true; // Continue iteration. // Not ice corpses. if(mo->flags & MF_ICECORPSE) return true; // Continue iteration. // Only corpses that call A_QueueCorpse from death routine. switch(mo->type) { case MT_CENTAUR: case MT_CENTAURLEADER: case MT_DEMON: case MT_DEMON2: case MT_WRAITH: case MT_WRAITHB: case MT_BISHOP: case MT_ETTIN: case MT_PIG: case MT_CENTAUR_SHIELD: case MT_CENTAUR_SWORD: case MT_DEMONCHUNK1: case MT_DEMONCHUNK2: case MT_DEMONCHUNK3: case MT_DEMONCHUNK4: case MT_DEMONCHUNK5: case MT_DEMON2CHUNK1: case MT_DEMON2CHUNK2: case MT_DEMON2CHUNK3: case MT_DEMON2CHUNK4: case MT_DEMON2CHUNK5: case MT_FIREDEMON_SPLOTCH1: case MT_FIREDEMON_SPLOTCH2: A_QueueCorpse(mo); // Add corpse to queue. break; default: break; } return true; // Continue iteration. } void P_InitCreatureCorpseQueue(boolean corpseScan) { // Initialize queue corpseQueueSlot = 0; memset(corpseQueue, 0, sizeof(mobj_t *) * CORPSEQUEUESIZE); if(!corpseScan) return; // Search the thinker list for corpses and place them in this queue. DD_IterateThinkers(P_MobjThinker, addMobjToCorpseQueue, NULL); } void C_DECL A_AddPlayerCorpse(mobj_t *actor) { if(bodyqueslot >= BODYQUESIZE) { // Too many player corpses - remove an old one. P_MobjRemove(bodyque[bodyqueslot % BODYQUESIZE], true); } bodyque[bodyqueslot % BODYQUESIZE] = actor; bodyqueslot++; } void C_DECL A_SerpentUnHide(mobj_t* actor) { actor->flags2 &= ~MF2_DONTDRAW; actor->floorClip = 24; } void C_DECL A_SerpentHide(mobj_t* actor) { actor->flags2 |= MF2_DONTDRAW; actor->floorClip = 0; } void C_DECL A_SerpentChase(mobj_t* actor) { int delta; float oldpos[3]; material_t* oldMaterial; statenum_t state; if(actor->reactionTime) { actor->reactionTime--; } // Modify target threshold. if(actor->threshold) { actor->threshold--; } if(gameSkill == SM_NIGHTMARE || (fastMonsters)) { // Monsters move faster in nightmare mode. actor->tics -= actor->tics / 2; if(actor->tics < 3) { actor->tics = 3; } } // Turn towards movement direction if not there yet. if(actor->moveDir < DI_NODIR) { actor->angle &= (7 << 29); delta = actor->angle - (actor->moveDir << 29); if(delta > 0) { actor->angle -= ANG90 / 2; } else if(delta < 0) { actor->angle += ANG90 / 2; } } if(!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { // Look for a new target. if(P_LookForPlayers(actor, true)) { // Got a new target. return; } P_MobjChangeState(actor, P_GetState(actor->type, SN_SPAWN)); return; } // Don't attack twice in a row. if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if(gameSkill != SM_NIGHTMARE) P_NewChaseDir(actor); return; } // Check for melee attack. if((state = P_GetState(actor->type, SN_MELEE)) != S_NULL && P_CheckMeleeRange(actor, false)) { if(actor->info->attackSound) { S_StartSound(actor->info->attackSound, actor); } P_MobjChangeState(actor, state); return; } // Possibly choose another target. if(IS_NETGAME && !actor->threshold && !P_CheckSight(actor, actor->target)) { if(P_LookForPlayers(actor, true)) return; // Got a new target. } // Chase towards player. memcpy(oldpos, actor->pos, sizeof(oldpos)); oldMaterial = P_GetPtrp(actor->subsector, DMU_FLOOR_MATERIAL); if(--actor->moveCount < 0 || !P_Move(actor)) { P_NewChaseDir(actor); } if(P_GetPtrp(actor->subsector, DMU_FLOOR_MATERIAL) != oldMaterial) { P_TryMove(actor, oldpos[VX], oldpos[VY]); P_NewChaseDir(actor); } // Make active sound. if(actor->info->activeSound && P_Random() < 3) { S_StartSound(actor->info->activeSound, actor); } } void C_DECL A_SpeedFade(mobj_t *actor) { actor->flags |= MF_SHADOW; actor->flags &= ~MF_ALTSHADOW; actor->sprite = actor->target->sprite; } /** * Raises the hump above the surface by raising the floorclip level. */ void C_DECL A_SerpentRaiseHump(mobj_t *actor) { actor->floorClip -= 4; } void C_DECL A_SerpentLowerHump(mobj_t *actor) { actor->floorClip += 4; } /** * Decide whether to hump up, or if the mobj is a serpentleader, to * missile attack. */ void C_DECL A_SerpentHumpDecide(mobj_t *actor) { if(actor->type == MT_SERPENTLEADER) { if(P_Random() > 30) { return; } else if(P_Random() < 40) { // Missile attack. P_MobjChangeState(actor, S_SERPENT_SURFACE1); return; } } else if(P_Random() > 3) { return; } if(!P_CheckMeleeRange(actor, false)) { // The hump shouldn't occur when within melee range. if(actor->type == MT_SERPENTLEADER && P_Random() < 128) { P_MobjChangeState(actor, S_SERPENT_SURFACE1); } else { P_MobjChangeState(actor, S_SERPENT_HUMP1); S_StartSound(SFX_SERPENT_ACTIVE, actor); } } } void C_DECL A_SerpentBirthScream(mobj_t *actor) { S_StartSound(SFX_SERPENT_BIRTH, actor); } void C_DECL A_SerpentDiveSound(mobj_t *actor) { S_StartSound(SFX_SERPENT_ACTIVE, actor); } /** * Similar to A_Chase, only has a hardcoded entering of meleestate. */ void C_DECL A_SerpentWalk(mobj_t* actor) { int delta; statenum_t state; if(actor->reactionTime) { actor->reactionTime--; } // Modify target threshold. if(actor->threshold) { actor->threshold--; } if(gameSkill == SM_NIGHTMARE || (fastMonsters)) { // Monsters move faster in nightmare mode. actor->tics -= actor->tics / 2; if(actor->tics < 3) { actor->tics = 3; } } // Turn towards movement direction if not there yet. if(actor->moveDir < DI_NODIR) { actor->angle &= (7 << 29); delta = actor->angle - (actor->moveDir << 29); if(delta > 0) { actor->angle -= ANG90 / 2; } else if(delta < 0) { actor->angle += ANG90 / 2; } } if(!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { // Look for a new target. if(P_LookForPlayers(actor, true)) { // Got a new target. return; } P_MobjChangeState(actor, P_GetState(actor->type, SN_SPAWN)); return; } // Don't attack twice in a row. if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; if(gameSkill != SM_NIGHTMARE) P_NewChaseDir(actor); return; } // Check for melee attack. if((state = P_GetState(actor->type, SN_MELEE)) != S_NULL && P_CheckMeleeRange(actor, false)) { if(actor->info->attackSound) { S_StartSound(actor->info->attackSound, actor); } P_MobjChangeState(actor, S_SERPENT_ATK1); return; } // Possibly choose another target. if(IS_NETGAME && !actor->threshold && !P_CheckSight(actor, actor->target)) { if(P_LookForPlayers(actor, true)) return; // Got a new target. } // Chase towards player. if(--actor->moveCount < 0 || !P_Move(actor)) { P_NewChaseDir(actor); } } void C_DECL A_SerpentCheckForAttack(mobj_t *actor) { if(!actor->target) return; if(actor->type == MT_SERPENTLEADER) { if(!P_CheckMeleeRange(actor, false)) { P_MobjChangeState(actor, S_SERPENT_ATK1); return; } } if(P_CheckMeleeRange(actor, true)) { P_MobjChangeState(actor, S_SERPENT_WALK1); } else if(P_CheckMeleeRange(actor, false)) { if(P_Random() < 32) { P_MobjChangeState(actor, S_SERPENT_WALK1); } else { P_MobjChangeState(actor, S_SERPENT_ATK1); } } } void C_DECL A_SerpentChooseAttack(mobj_t *actor) { if(!actor->target || P_CheckMeleeRange(actor, false)) return; if(actor->type == MT_SERPENTLEADER) { P_MobjChangeState(actor, S_SERPENT_MISSILE1); } } void C_DECL A_SerpentMeleeAttack(mobj_t *actor) { if(!actor->target) return; if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, HITDICE(5), false); S_StartSound(SFX_SERPENT_MELEEHIT, actor); } if(P_Random() < 96) { A_SerpentCheckForAttack(actor); } } void C_DECL A_SerpentMissileAttack(mobj_t* actor) { if(!actor->target) return; P_SpawnMissile(MT_SERPENTFX, actor, actor->target); } void C_DECL A_SerpentHeadPop(mobj_t* actor) { P_SpawnMobj3f(MT_SERPENT_HEAD, actor->pos[VX], actor->pos[VY], actor->pos[VZ] + 45, actor->angle, 0); } static void spawnSerpentGib(mobjtype_t type, mobj_t* mo) { mobj_t* pmo; float pos[3]; if(!mo) return; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = 1; pos[VX] += FIX2FLT((P_Random() - 128) << 12); pos[VY] += FIX2FLT((P_Random() - 128) << 12); if((pmo = P_SpawnMobj3fv((type), pos, P_Random() << 24, MSF_Z_FLOOR))) { pmo->mom[MX] = FIX2FLT((P_Random() - 128) << 6); pmo->mom[MY] = FIX2FLT((P_Random() - 128) << 6); pmo->floorClip = 6; } } void C_DECL A_SerpentSpawnGibs(mobj_t* mo) { // Order is important - P_Randoms! spawnSerpentGib(MT_SERPENT_GIB1, mo); spawnSerpentGib(MT_SERPENT_GIB2, mo); spawnSerpentGib(MT_SERPENT_GIB3, mo); } void C_DECL A_FloatGib(mobj_t *actor) { actor->floorClip -= 1; } void C_DECL A_SinkGib(mobj_t *actor) { actor->floorClip += 1; } void C_DECL A_DelayGib(mobj_t *actor) { actor->tics -= P_Random() >> 2; } void C_DECL A_SerpentHeadCheck(mobj_t *actor) { if(actor->pos[VZ] <= actor->floorZ) { const terraintype_t* tt = P_MobjGetFloorTerrainType(actor); if(tt->flags & TTF_NONSOLID) { P_HitFloor(actor); P_MobjChangeState(actor, S_NULL); } else { P_MobjChangeState(actor, S_SERPENT_HEAD_X1); } } } void C_DECL A_CentaurAttack(mobj_t *actor) { if(!actor->target) return; if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, P_Random() % 7 + 3, false); } } void C_DECL A_CentaurAttack2(mobj_t *actor) { if(!actor->target) return; P_SpawnMissile(MT_CENTAUR_FX, actor, actor->target); S_StartSound(SFX_CENTAURLEADER_ATTACK, actor); } static void spawnCentaurStuff(mobjtype_t type, angle_t angle, mobj_t* mo) { mobj_t* pmo; unsigned int an; byte momRand[3]; if((pmo = P_SpawnMobj3f(type, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + 45, angle, 0))) { an = angle >> ANGLETOFINESHIFT; /* Order of randoms is important! */ momRand[MZ] = P_Random(); momRand[MX] = P_Random(); momRand[MY] = P_Random(); pmo->mom[MX] = (FIX2FLT((momRand[MX] - 128) << 11) + 1) * FIX2FLT(finecosine[an]); pmo->mom[MY] = (FIX2FLT((momRand[MY] - 128) << 11) + 1) * FIX2FLT(finesine[an]); pmo->mom[MZ] = 8 + FIX2FLT(momRand[MZ] << 10); pmo->target = mo; } } /** * Spawn shield/sword sprites when the centaur pulps. */ void C_DECL A_CentaurDropStuff(mobj_t* mo) { // Order is important P_Randoms! spawnCentaurStuff(MT_CENTAUR_SHIELD, mo->angle + ANG90, mo); spawnCentaurStuff(MT_CENTAUR_SWORD, mo->angle - ANG90, mo); } void C_DECL A_CentaurDefend(mobj_t* actor) { A_FaceTarget(actor); if(P_CheckMeleeRange(actor, false) && P_Random() < 32) { A_UnSetInvulnerable(actor); P_MobjChangeState(actor, P_GetState(actor->type, SN_MELEE)); } } void C_DECL A_BishopAttack(mobj_t* actor) { if(!actor->target) return; S_StartSound(actor->info->attackSound, actor); if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, HITDICE(4), false); return; } actor->special1 = (P_Random() & 3) + 5; } /** * Spawns one of a string of bishop missiles. */ void C_DECL A_BishopAttack2(mobj_t* actor) { mobj_t* mo; if(!actor->target || !actor->special1) { actor->special1 = 0; P_MobjChangeState(actor, S_BISHOP_WALK1); return; } mo = P_SpawnMissile(MT_BISH_FX, actor, actor->target); if(mo) { mo->tracer = actor->target; mo->special2 = 16; // High word == x/y, Low word == z. } actor->special1--; } void C_DECL A_BishopMissileWeave(mobj_t* actor) { float pos[3]; uint weaveXY, weaveZ; uint an; // Unpack the weave vector. weaveXY = actor->special2 >> 16; weaveZ = actor->special2 & 0xFFFF; an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = actor->pos[VZ]; pos[VX] -= FIX2FLT(finecosine[an]) * (FLOATBOBOFFSET(weaveXY) * 2); pos[VY] -= FIX2FLT(finesine[an]) * (FLOATBOBOFFSET(weaveXY) * 2); pos[VZ] -= FLOATBOBOFFSET(weaveZ); weaveXY = (weaveXY + 2) & 63; weaveZ = (weaveZ + 2) & 63; pos[VX] += FIX2FLT(finecosine[an]) * (FLOATBOBOFFSET(weaveXY) * 2); pos[VY] += FIX2FLT(finesine[an]) * (FLOATBOBOFFSET(weaveXY) * 2); pos[VZ] += FLOATBOBOFFSET(weaveZ); P_TryMove(actor, pos[VX], pos[VY]); // P_TryMove won't have set the z compontent so do it manually. actor->pos[VZ] = pos[VZ]; // Store the weave angle. actor->special2 = weaveZ + (weaveXY << 16); } void C_DECL A_BishopMissileSeek(mobj_t *actor) { P_SeekerMissile(actor, ANGLE_1 * 2, ANGLE_1 * 3); } void C_DECL A_BishopDecide(mobj_t *actor) { if(P_Random() < 220) { return; } else { P_MobjChangeState(actor, S_BISHOP_BLUR1); } } void C_DECL A_BishopDoBlur(mobj_t *mo) { mo->special1 = (P_Random() & 3) + 3; // Random number of blurs. if(P_Random() < 120) { P_ThrustMobj(mo, mo->angle + ANG90, 11); } else if(P_Random() > 125) { P_ThrustMobj(mo, mo->angle - ANG90, 11); } else { // Thrust forward P_ThrustMobj(mo, mo->angle, 11); } S_StartSound(SFX_BISHOP_BLUR, mo); } void C_DECL A_BishopSpawnBlur(mobj_t *mo) { if(!--mo->special1) { mo->mom[MX] = mo->mom[MY] = 0; if(P_Random() > 96) { P_MobjChangeState(mo, S_BISHOP_WALK1); } else { P_MobjChangeState(mo, S_BISHOP_ATK1); } } P_SpawnMobj3fv(MT_BISHOPBLUR, mo->pos, mo->angle, 0); } void C_DECL A_BishopChase(mobj_t* mo) { mo->pos[VZ] -= FLOATBOBOFFSET(mo->special2) / 2; mo->special2 = (mo->special2 + 4) & 63; mo->pos[VZ] += FLOATBOBOFFSET(mo->special2) / 2; } void C_DECL A_BishopPuff(mobj_t* mo) { mobj_t* pmo; if((pmo = P_SpawnMobj3f(MT_BISHOP_PUFF, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + 40, P_Random() << 24, 0))) { pmo->mom[MZ] = 1.0f / 2; } } void C_DECL A_BishopPainBlur(mobj_t *actor) { float pos[3]; if(P_Random() < 64) { P_MobjChangeState(actor, S_BISHOP_BLUR1); return; } pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = actor->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - P_Random()) << 12); pos[VY] += FIX2FLT((P_Random() - P_Random()) << 12); pos[VZ] += FIX2FLT((P_Random() - P_Random()) << 11); P_SpawnMobj3fv(MT_BISHOPPAINBLUR, pos, actor->angle, 0); } static void dragonSeek(mobj_t *actor, angle_t thresh, angle_t turnMax) { int i, search, dir, bestArg; float dist; angle_t delta, bestAngle, angleToSpot, angleToTarget; uint an; mobj_t *target, *mo; target = actor->tracer; if(target == NULL) return; dir = P_FaceMobj(actor, target, &delta); if(delta > thresh) { delta /= 2; if(delta > turnMax) { delta = turnMax; } } if(dir) { // Turn clockwise. actor->angle += delta; } else { // Turn counter clockwise. actor->angle -= delta; } an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = actor->info->speed * FIX2FLT(finecosine[an]); actor->mom[MY] = actor->info->speed * FIX2FLT(finesine[an]); if(actor->pos[VZ] + actor->height < target->pos[VZ] || target->pos[VZ] + target->height < actor->pos[VZ]) { dist = P_ApproxDistance(target->pos[VX] - actor->pos[VX], target->pos[VY] - actor->pos[VY]); dist /= actor->info->speed; if(dist < FIX2FLT(1)) dist = FIX2FLT(1); actor->mom[MZ] = (target->pos[VZ] - actor->pos[VZ]) / dist; } else { dist = P_ApproxDistance(target->pos[VX] - actor->pos[VX], target->pos[VY] - actor->pos[VY]); dist /= actor->info->speed; } if((target->flags & MF_SHOOTABLE) && P_Random() < 64) { // Attack the destination mobj if it's attackable. mobj_t *oldTarget; if(abs (actor->angle - R_PointToAngle2(actor->pos[VX], actor->pos[VY], target->pos[VX], target->pos[VY])) < ANGLE_45 / 2) { oldTarget = actor->target; actor->target = target; if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, HITDICE(10), false); S_StartSound(SFX_DRAGON_ATTACK, actor); } else if(P_Random() < 128 && P_CheckMissileRange(actor)) { P_SpawnMissile(MT_DRAGON_FX, actor, target); S_StartSound(SFX_DRAGON_ATTACK, actor); } actor->target = oldTarget; } } if(dist < FIX2FLT(4)) { // Hit the target thing. if(actor->target && P_Random() < 200) { bestArg = -1; bestAngle = ANGLE_MAX; angleToTarget = R_PointToAngle2(actor->pos[VX], actor->pos[VY], actor->target->pos[VX], actor->target->pos[VY]); for(i = 0; i < 5; ++i) { if(!target->args[i]) continue; search = -1; mo = P_FindMobjFromTID(target->args[i], &search); angleToSpot = R_PointToAngle2(actor->pos[VX], actor->pos[VY], mo->pos[VX], mo->pos[VY]); if(abs(angleToSpot - angleToTarget) < (int) bestAngle) { bestAngle = abs(angleToSpot - angleToTarget); bestArg = i; } } if(bestArg != -1) { search = -1; actor->tracer = P_FindMobjFromTID(target->args[bestArg], &search); } } else { do { i = (P_Random() >> 2) % 5; } while(!target->args[i]); search = -1; actor->tracer = P_FindMobjFromTID(target->args[i], &search); } } } void C_DECL A_DragonInitFlight(mobj_t* actor) { int search; search = -1; do { // find the first tid identical to the dragon's tid actor->tracer = P_FindMobjFromTID(actor->tid, &search); if(search == -1) { P_MobjChangeState(actor, P_GetState(actor->type, SN_SPAWN)); return; } } while(actor->tracer == actor); P_MobjRemoveFromTIDList(actor); } void C_DECL A_DragonFlight(mobj_t* actor) { angle_t angle; dragonSeek(actor, 4 * ANGLE_1, 8 * ANGLE_1); if(actor->target) { if(!(actor->target->flags & MF_SHOOTABLE)) { // Target died. actor->target = NULL; return; } angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], actor->target->pos[VX], actor->target->pos[VY]); if(abs(actor->angle - angle) < ANGLE_45 / 2 && P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, HITDICE(8), false); S_StartSound(SFX_DRAGON_ATTACK, actor); } else if(abs(actor->angle - angle) <= ANGLE_1 * 20) { P_MobjChangeState(actor, P_GetState(actor->type, SN_MISSILE)); S_StartSound(SFX_DRAGON_ATTACK, actor); } } else { P_LookForPlayers(actor, true); } } void C_DECL A_DragonFlap(mobj_t* actor) { A_DragonFlight(actor); if(P_Random() < 240) { S_StartSound(SFX_DRAGON_WINGFLAP, actor); } else { S_StartSound(actor->info->activeSound, actor); } } void C_DECL A_DragonAttack(mobj_t* mo) { P_SpawnMissile(MT_DRAGON_FX, mo, mo->target); } void C_DECL A_DragonFX2(mobj_t* mo) { int i, delay; delay = 16 + (P_Random() >> 3); for(i = 1 + (P_Random() & 3); i; i--) { mobj_t* pmo; float pos[3]; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - 128) << 14); pos[VY] += FIX2FLT((P_Random() - 128) << 14); pos[VZ] += FIX2FLT((P_Random() - 128) << 12); if((pmo = P_SpawnMobj3fv(MT_DRAGON_FX2, pos, P_Random() << 24, 0))) { pmo->tics = delay + (P_Random() & 3) * i * 2; pmo->target = mo->target; } } } void C_DECL A_DragonPain(mobj_t *mo) { A_Pain(mo); if(!mo->tracer) { // No destination spot yet. P_MobjChangeState(mo, S_DRAGON_INIT); } } void C_DECL A_DragonCheckCrash(mobj_t *mo) { if(mo->pos[VZ] <= mo->floorZ) { P_MobjChangeState(mo, S_DRAGON_CRASH1); } } /** * Demon: Melee attack. */ void C_DECL A_DemonAttack1(mobj_t *mo) { if(P_CheckMeleeRange(mo, false)) { P_DamageMobj(mo->target, mo, mo, HITDICE(2), false); } } /** * Demon: Missile attack. */ void C_DECL A_DemonAttack2(mobj_t* mo) { mobj_t* pmo; int fireBall; if(mo->type == MT_DEMON) { fireBall = MT_DEMONFX1; } else { fireBall = MT_DEMON2FX1; } if((pmo = P_SpawnMissile(fireBall, mo, mo->target))) { pmo->pos[VZ] += 30; S_StartSound(SFX_DEMON_MISSILE_FIRE, mo); } } static mobj_t *spawnDemonChunk(mobjtype_t type, angle_t angle, mobj_t *mo) { mobj_t* pmo; unsigned int an; if((pmo = P_SpawnMobj3f(type, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + 45, angle, 0))) { an = angle >> ANGLETOFINESHIFT; pmo->mom[MX] = (FIX2FLT(P_Random() << 10) + 1) * FIX2FLT(finecosine[an]); pmo->mom[MY] = (FIX2FLT(P_Random() << 10) + 1) * FIX2FLT(finesine[an]); pmo->mom[MZ] = 8; pmo->target = mo; } return pmo; } void C_DECL A_DemonDeath(mobj_t *mo) { // Order is important, P_Randoms! spawnDemonChunk(MT_DEMONCHUNK1, mo->angle + ANG90, mo); spawnDemonChunk(MT_DEMONCHUNK2, mo->angle - ANG90, mo); spawnDemonChunk(MT_DEMONCHUNK3, mo->angle - ANG90, mo); spawnDemonChunk(MT_DEMONCHUNK4, mo->angle - ANG90, mo); spawnDemonChunk(MT_DEMONCHUNK5, mo->angle - ANG90, mo); } void C_DECL A_Demon2Death(mobj_t *mo) { // Order is important, P_Randoms! spawnDemonChunk(MT_DEMON2CHUNK1, mo->angle + ANG90, mo); spawnDemonChunk(MT_DEMON2CHUNK2, mo->angle - ANG90, mo); spawnDemonChunk(MT_DEMON2CHUNK3, mo->angle - ANG90, mo); spawnDemonChunk(MT_DEMON2CHUNK4, mo->angle - ANG90, mo); spawnDemonChunk(MT_DEMON2CHUNK5, mo->angle - ANG90, mo); } /** * Sink a mobj incrementally into the floor. */ boolean A_SinkMobj(mobj_t *mo) { if(mo->floorClip < mo->info->height) { switch(mo->type) { case MT_THRUSTFLOOR_DOWN: case MT_THRUSTFLOOR_UP: mo->floorClip += 6; break; default: mo->floorClip += 1; break; } return false; } return true; } /** * Raise a mobj incrementally from the floor to. */ boolean A_RaiseMobj(mobj_t *mo) { boolean done = true; // Raise a mobj from the ground. if(mo->floorClip > 0) { switch (mo->type) { case MT_WRAITHB: mo->floorClip -= 2; break; case MT_THRUSTFLOOR_DOWN: case MT_THRUSTFLOOR_UP: mo->floorClip -= mo->special2; break; default: mo->floorClip -= 2; break; } if(mo->floorClip <= 0) { mo->floorClip = 0; done = true; } else { done = false; } } return done; // Reached target height. } /** * Wraith Variables * * special1 Internal index into floatbob. * special2 */ void C_DECL A_WraithInit(mobj_t *mo) { mo->pos[VZ] += 48; mo->special1 = 0; // Index into floatbob. } void C_DECL A_WraithRaiseInit(mobj_t *mo) { mo->flags2 &= ~MF2_DONTDRAW; mo->flags2 &= ~MF2_NONSHOOTABLE; mo->flags |= MF_SHOOTABLE | MF_SOLID; mo->floorClip = mo->info->height; } void C_DECL A_WraithRaise(mobj_t *mo) { if(A_RaiseMobj(mo)) { // Reached it's target height. P_MobjChangeState(mo, S_WRAITH_CHASE1); } P_SpawnDirt(mo, mo->radius); } void C_DECL A_WraithMelee(mobj_t* mo) { if(P_CheckMeleeRange(mo, false) && (P_Random() < 220)) { // Steal health from target. mo->health += P_DamageMobj(mo->target, mo, mo, HITDICE(2), false); } } void C_DECL A_WraithMissile(mobj_t *mo) { if(P_SpawnMissile(MT_WRAITHFX1, mo, mo->target)) { S_StartSound(SFX_WRAITH_MISSILE_FIRE, mo); } } /** * Wraith: Spawn sparkle tail of missile. */ void C_DECL A_WraithFX2(mobj_t* mo) { int i; for(i = 0; i < 2; ++i) { uint an; angle_t angle; mobj_t* pmo; if(P_Random() < 128) { angle = mo->angle + (P_Random() << 22); } else { angle = mo->angle - (P_Random() << 22); } if((pmo = P_SpawnMobj3fv(MT_WRAITHFX2, mo->pos, angle, 0))) { an = angle >> ANGLETOFINESHIFT; pmo->mom[MX] = FIX2FLT((P_Random() << 7) + 1) * FIX2FLT(finecosine[an]); pmo->mom[MY] = FIX2FLT((P_Random() << 7) + 1) * FIX2FLT(finesine[an]); pmo->mom[MZ] = 0; pmo->target = mo; pmo->floorClip = 10; } } } /** * Wraith: Spawn an FX3 around during attacks. */ void C_DECL A_WraithFX3(mobj_t* mo) { int i, numdropped = P_Random() % 15; for(i = 0; i < numdropped; ++i) { mobj_t* pmo; float pos[3]; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - 128) << 11); pos[VY] += FIX2FLT((P_Random() - 128) << 11); pos[VZ] += FIX2FLT(P_Random() << 10); if((pmo = P_SpawnMobj3fv(MT_WRAITHFX3, pos, P_Random() << 24, 0))) { pmo->target = mo; } } } /** * Wraith: Spawn an FX4 during movement. */ void C_DECL A_WraithFX4(mobj_t* mo) { mobj_t* pmo; int spawn4, spawn5, chance = P_Random(); if(chance < 10) { spawn4 = true; spawn5 = false; } else if(chance < 20) { spawn4 = false; spawn5 = true; } else if(chance < 25) { spawn4 = true; spawn5 = true; } else { spawn4 = false; spawn5 = false; } if(spawn4) { float pos[3]; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - 128) << 12); pos[VY] += FIX2FLT((P_Random() - 128) << 12); pos[VZ] += FIX2FLT(P_Random() << 10); if((pmo = P_SpawnMobj3fv(MT_WRAITHFX4, pos, P_Random() << 24, 0))) { pmo->target = mo; } } if(spawn5) { float pos[3]; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - 128) << 11); pos[VY] += FIX2FLT((P_Random() - 128) << 11); pos[VZ] += FIX2FLT(P_Random() << 10); if((pmo = P_SpawnMobj3fv(MT_WRAITHFX5, pos, P_Random() << 24, 0))) { pmo->target = mo; } } } void C_DECL A_WraithLook(mobj_t *actor) { A_Look(actor); } void C_DECL A_WraithChase(mobj_t *actor) { int weaveindex = actor->special1; actor->pos[VZ] += FLOATBOBOFFSET(weaveindex); actor->special1 = (weaveindex + 2) & 63; A_Chase(actor); A_WraithFX4(actor); } void C_DECL A_EttinAttack(mobj_t *actor) { if(P_CheckMeleeRange(actor, false)) { P_DamageMobj(actor->target, actor, actor, HITDICE(2), false); } } void C_DECL A_DropMace(mobj_t *mo) { mobj_t* pmo; if((pmo = P_SpawnMobj3f(MT_ETTIN_MACE, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + mo->height /2, mo->angle, 0))) { pmo->mom[MX] = FIX2FLT((P_Random() - 128) << 11); pmo->mom[MY] = FIX2FLT((P_Random() - 128) << 11); pmo->mom[MZ] = 10 + FIX2FLT(P_Random() << 10); pmo->target = mo; } } /** * Fire Demon variables. * * special1 Index into floatbob. * special2 whether strafing or not. */ void C_DECL A_FiredSpawnRock(mobj_t *mo) { mobj_t *pmo; float pos[3]; int rtype = 0; switch(P_Random() % 5) { case 0: rtype = MT_FIREDEMON_FX1; break; case 1: rtype = MT_FIREDEMON_FX2; break; case 2: rtype = MT_FIREDEMON_FX3; break; case 3: rtype = MT_FIREDEMON_FX4; break; case 4: rtype = MT_FIREDEMON_FX5; break; } pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - 128) << 12); pos[VY] += FIX2FLT((P_Random() - 128) << 12); pos[VZ] += FIX2FLT((P_Random()) << 11); if((pmo = P_SpawnMobj3fv(rtype, pos, P_Random() << 24, 0))) { pmo->mom[MX] = FIX2FLT((P_Random() - 128) << 10); pmo->mom[MY] = FIX2FLT((P_Random() - 128) << 10); pmo->mom[MZ] = FIX2FLT(P_Random() << 10); pmo->special1 = 2; // Number of bounces. pmo->target = mo; } // Initialize fire demon. mo->special2 = 0; mo->flags &= ~MF_JUSTATTACKED; } void C_DECL A_FiredRocks(mobj_t *mo) { A_FiredSpawnRock(mo); A_FiredSpawnRock(mo); A_FiredSpawnRock(mo); A_FiredSpawnRock(mo); A_FiredSpawnRock(mo); } void C_DECL A_FiredAttack(mobj_t *mo) { mobj_t *pmo; pmo = P_SpawnMissile(MT_FIREDEMON_FX6, mo, mo->target); if(pmo) S_StartSound(SFX_FIRED_ATTACK, mo); } void C_DECL A_SmBounce(mobj_t *mo) { // Give some more momentum (x,y,&z). mo->pos[VZ] = mo->floorZ + 1; mo->mom[MZ] = 2 + FIX2FLT(P_Random() << 10); mo->mom[MX] = (float) (P_Random() % 3); mo->mom[MY] = (float) (P_Random() % 3); } void C_DECL A_FiredChase(mobj_t *actor) { #define FIREDEMON_ATTACK_RANGE (64*8) int weaveindex = actor->special1; mobj_t *target = actor->target; angle_t angle; uint an; float dist; if(actor->reactionTime) actor->reactionTime--; if(actor->threshold) actor->threshold--; // Float up and down. actor->pos[VZ] += FLOATBOBOFFSET(weaveindex); actor->special1 = (weaveindex + 2) & 63; // Insure it stays above certain height. if(actor->pos[VZ] < actor->floorZ + 64) { actor->pos[VZ] += 2; } if(!actor->target || !(actor->target->flags & MF_SHOOTABLE)) { // Invalid target. P_LookForPlayers(actor, true); return; } // Strafe. if(actor->special2 > 0) { actor->special2--; } else { actor->special2 = 0; actor->mom[MX] = actor->mom[MY] = 0; dist = P_ApproxDistance(actor->pos[VX] - target->pos[VX], actor->pos[VY] - target->pos[VY]); if(dist < FIREDEMON_ATTACK_RANGE) { if(P_Random() < 30) { angle = R_PointToAngle2(actor->pos[VX], actor->pos[VY], target->pos[VX], target->pos[VY]); if(P_Random() < 128) angle += ANGLE_90; else angle -= ANGLE_90; an = angle >>ANGLETOFINESHIFT; actor->mom[MX] = 8 * FIX2FLT(finecosine[an]); actor->mom[MY] = 8 * FIX2FLT(finesine[an]); actor->special2 = 3; // Strafe time. } } } FaceMovementDirection(actor); // Normal movement. if(!actor->special2) { if(--actor->moveCount < 0 || !P_Move(actor)) { P_NewChaseDir(actor); } } // Do missile attack. if(!(actor->flags & MF_JUSTATTACKED)) { if(P_CheckMissileRange(actor) && (P_Random() < 20)) { P_MobjChangeState(actor, P_GetState(actor->type, SN_MISSILE)); actor->flags |= MF_JUSTATTACKED; return; } } else { actor->flags &= ~MF_JUSTATTACKED; } // Make active sound. if(actor->info->activeSound && P_Random() < 3) { S_StartSound(actor->info->activeSound, actor); } #undef FIREDEMON_ATTACK_RANGE } void C_DECL A_FiredSplotch(mobj_t* actor) { mobj_t* pmo; if((pmo = P_SpawnMobj3fv(MT_FIREDEMON_SPLOTCH1, actor->pos, P_Random() << 24, 0))) { pmo->mom[MX] = FIX2FLT((P_Random() - 128) << 11); pmo->mom[MY] = FIX2FLT((P_Random() - 128) << 11); pmo->mom[MZ] = 3 + FIX2FLT(P_Random() << 10); } if((pmo = P_SpawnMobj3fv(MT_FIREDEMON_SPLOTCH2, actor->pos, P_Random() << 24, 0))) { pmo->mom[MX] = FIX2FLT((P_Random() - 128) << 11); pmo->mom[MY] = FIX2FLT((P_Random() - 128) << 11); pmo->mom[MZ] = 3 + FIX2FLT((P_Random() << 10)); } } void C_DECL A_IceGuyLook(mobj_t* mo) { float dist; angle_t angle; unsigned int an; A_Look(mo); if(P_Random() < 64) { dist = FIX2FLT(((P_Random() - 128) * FLT2FIX(mo->radius)) >> 7); angle = mo->angle + ANG90; an = angle >> ANGLETOFINESHIFT; /** * \fixme We should not be selecting mobj types by their original * indices! Instead, use a fixed table here. */ P_SpawnMobj3f(MT_ICEGUY_WISP1 + (P_Random() & 1), mo->pos[VX] + dist * FIX2FLT(finecosine[an]), mo->pos[VY] + dist * FIX2FLT(finesine[an]), mo->pos[VZ] + 60, angle, 0); } } void C_DECL A_IceGuyChase(mobj_t *actor) { float dist; angle_t angle; unsigned int an; mobj_t* mo; A_Chase(actor); if(P_Random() < 128) { dist = FIX2FLT(((P_Random() - 128) * FLT2FIX(actor->radius)) >> 7); angle = actor->angle + ANG90; an = angle >> ANGLETOFINESHIFT; /** * \fixme We should not be selecting mobj types by their original * indices! Instead, use a fixed table here. */ if((mo = P_SpawnMobj3f(MT_ICEGUY_WISP1 + (P_Random() & 1), actor->pos[VX] + dist * FIX2FLT(finecosine[an]), actor->pos[VY] + dist * FIX2FLT(finesine[an]), actor->pos[VZ] + 60, angle, 0))) { mo->mom[MX] = actor->mom[MX]; mo->mom[MY] = actor->mom[MY]; mo->mom[MZ] = actor->mom[MZ]; mo->target = actor; } } } void C_DECL A_IceGuyAttack(mobj_t *mo) { uint an; float pos[3]; if(!mo->target) return; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; an = (mo->angle + ANG90) >> ANGLETOFINESHIFT; pos[VX] += (mo->radius / 2) * FIX2FLT(finecosine[an]); pos[VY] += (mo->radius / 2) * FIX2FLT(finesine[an]); pos[VZ] += 40; P_SpawnMissileXYZ(MT_ICEGUY_FX, pos[VX], pos[VY], pos[VZ], mo, mo->target); pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; an = (mo->angle - ANG90) >> ANGLETOFINESHIFT; pos[VX] += (mo->radius / 2) * FIX2FLT(finecosine[an]); pos[VY] += (mo->radius / 2) * FIX2FLT(finesine[an]); pos[VZ] += 40; P_SpawnMissileXYZ(MT_ICEGUY_FX, pos[VX], pos[VY], pos[VZ], mo, mo->target); S_StartSound(mo->info->attackSound, mo); } void C_DECL A_IceGuyMissilePuff(mobj_t *mo) { P_SpawnMobj3f(MT_ICEFX_PUFF, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + 2, P_Random() << 24, 0); } void C_DECL A_IceGuyDie(mobj_t *mo) { mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; mo->height *= 2*2; A_FreezeDeathChunks(mo); } void C_DECL A_IceGuyMissileExplode(mobj_t *mo) { mobj_t *pmo; int i; for(i = 0; i < 8; ++i) { pmo = P_SpawnMissileAngle(MT_ICEGUY_FX2, mo, i * ANG45, -0.3f); if(pmo) { pmo->target = mo->target; } } } /** * Sorcerer Variables. * * special1 Angle of ball 1 (all others relative to that). * special2 Which ball to stop at in stop mode (MT_???). * args[0] Defense time. * args[1] Number of full rotations since stopping mode. * args[2] Target orbit speed for acceleration/deceleration. * args[3] Movement mode (see SORC_ macros). * args[4] Current ball orbit speed. */ /** * Sorcerer Ball Variables. * * special1 Previous angle of ball (for woosh). * special2 Countdown of rapid fire (FX4). * args[0] If set, don't play the bounce sound when bouncing. */ /** * Spawn spinning balls above head - actor is sorcerer. */ void C_DECL A_SorcSpinBalls(mobj_t *mo) { mobj_t* pmo; float z; angle_t angle; A_SlowBalls(mo); mo->args[0] = 0; // Currently no defense. mo->args[3] = SORC_NORMAL; mo->args[4] = SORCBALL_INITIAL_SPEED; // Initial orbit speed. angle = ANG45 / 45; mo->special1 = angle; z = mo->pos[VZ] - mo->floorClip + mo->info->height; if((pmo = P_SpawnMobj3f(MT_SORCBALL1, mo->pos[VX], mo->pos[VY], z, angle, 0))) { pmo->target = mo; pmo->special2 = SORCFX4_RAPIDFIRE_TIME; } if((pmo = P_SpawnMobj3f(MT_SORCBALL2, mo->pos[VX], mo->pos[VY], z, angle, 0))) { pmo->target = mo; } if((pmo = P_SpawnMobj3f(MT_SORCBALL3, mo->pos[VX], mo->pos[VY], z, angle, 0))) { pmo->target = mo; } } void C_DECL A_SorcBallOrbit(mobj_t* actor) { uint an; angle_t angle = 0, baseangle; int mode = actor->target->args[3]; mobj_t* parent = actor->target; float dist = parent->radius - actor->radius * 2; angle_t prevangle = (angle_t) actor->special1; statenum_t state; if((state = P_GetState(actor->type, SN_PAIN)) != S_NULL && actor->target->health <= 0) P_MobjChangeState(actor, state); baseangle = (angle_t) parent->special1; switch(actor->type) { case MT_SORCBALL1: angle = baseangle + BALL1_ANGLEOFFSET; break; case MT_SORCBALL2: angle = baseangle + BALL2_ANGLEOFFSET; break; case MT_SORCBALL3: angle = baseangle + BALL3_ANGLEOFFSET; break; default: Con_Error("Corrupted sorcerer"); break; } actor->angle = angle; an = angle >> ANGLETOFINESHIFT; switch(mode) { case SORC_NORMAL: // Balls rotating normally. A_SorcUpdateBallAngle(actor); break; case SORC_DECELERATE: // Balls decelerating. A_DecelBalls(actor); A_SorcUpdateBallAngle(actor); break; case SORC_ACCELERATE: // Balls accelerating. A_AccelBalls(actor); A_SorcUpdateBallAngle(actor); break; case SORC_STOPPING: // Balls stopping. if((parent->special2 == actor->type) && (parent->args[1] > SORCBALL_SPEED_ROTATIONS) && (abs(an - (parent->angle >> ANGLETOFINESHIFT)) < (30 << 5))) { // Can stop now. actor->target->args[3] = SORC_FIRESPELL; actor->target->args[4] = 0; // Set angle so ball angle == sorcerer angle. switch(actor->type) { case MT_SORCBALL1: parent->special1 = (int) (parent->angle - BALL1_ANGLEOFFSET); break; case MT_SORCBALL2: parent->special1 = (int) (parent->angle - BALL2_ANGLEOFFSET); break; case MT_SORCBALL3: parent->special1 = (int) (parent->angle - BALL3_ANGLEOFFSET); break; default: break; } } else { A_SorcUpdateBallAngle(actor); } break; case SORC_FIRESPELL: // Casting spell. if(parent->special2 == actor->type) { // Put sorcerer into special throw spell anim. if(parent->health > 0) P_SetMobjStateNF(parent, S_SORC_ATTACK1); if(actor->type == MT_SORCBALL1 && P_Random() < 200) { S_StartSound(SFX_SORCERER_SPELLCAST, NULL); actor->special2 = SORCFX4_RAPIDFIRE_TIME; actor->args[4] = 128; parent->args[3] = SORC_FIRING_SPELL; } else { A_CastSorcererSpell(actor); parent->args[3] = SORC_STOPPED; } } break; case SORC_FIRING_SPELL: if(parent->special2 == actor->type) { if(actor->special2-- <= 0) { // Done rapid firing. parent->args[3] = SORC_STOPPED; // Back to orbit balls. if(parent->health > 0) P_SetMobjStateNF(parent, S_SORC_ATTACK4); } else { // Do rapid fire spell. A_SorcOffense2(actor); } } break; case SORC_STOPPED: // Balls stopped. default: break; } if((angle < prevangle) && (parent->args[4] == SORCBALL_TERMINAL_SPEED)) { parent->args[1]++; // Bump rotation counter. // Completed full rotation - make woosh sound. S_StartSound(SFX_SORCERER_BALLWOOSH, actor); } actor->special1 = angle; // Set previous angle. P_MobjUnsetPosition(actor); actor->pos[VX] = parent->pos[VX]; actor->pos[VY] = parent->pos[VY]; actor->pos[VZ] = parent->pos[VZ]; actor->pos[VX] += dist * FIX2FLT(finecosine[an]); actor->pos[VY] += dist * FIX2FLT(finesine[an]); actor->pos[VZ] += parent->info->height; actor->pos[VZ] -= parent->floorClip; P_MobjSetPosition(actor); } /** * Set balls to speed mode - actor is sorcerer. */ void C_DECL A_SpeedBalls(mobj_t *actor) { actor->args[3] = SORC_ACCELERATE; // Speed mode. actor->args[2] = SORCBALL_TERMINAL_SPEED; // Target speed. } /** * Set balls to slow mode - actor is sorcerer. */ void C_DECL A_SlowBalls(mobj_t *actor) { actor->args[3] = SORC_DECELERATE; // Slow mode. actor->args[2] = SORCBALL_INITIAL_SPEED; // Target speed. } /** * Instant stop when rotation gets to ball in special2 actor is sorcerer. */ void C_DECL A_StopBalls(mobj_t *actor) { int chance = P_Random(); actor->args[3] = SORC_STOPPING; // Stopping mode. actor->args[1] = 0; // Reset rotation counter. if((actor->args[0] <= 0) && (chance < 200)) { actor->special2 = MT_SORCBALL2; // Blue. } else if((actor->health < (actor->info->spawnHealth >> 1)) && (chance < 200)) { actor->special2 = MT_SORCBALL3; // Green. } else { actor->special2 = MT_SORCBALL1; // Yellow. } } /** * Increase ball orbit speed - actor is ball. */ void C_DECL A_AccelBalls(mobj_t *actor) { mobj_t *sorc = actor->target; if(sorc->args[4] < sorc->args[2]) { sorc->args[4]++; } else { sorc->args[3] = SORC_NORMAL; if(sorc->args[4] >= SORCBALL_TERMINAL_SPEED) { // Reached terminal velocity - stop balls. A_StopBalls(sorc); } } } /** * Decrease ball orbit speed - actor is ball. */ void C_DECL A_DecelBalls(mobj_t *actor) { mobj_t *sorc = actor->target; if(sorc->args[4] > sorc->args[2]) { sorc->args[4]--; } else { sorc->args[3] = SORC_NORMAL; } } /** * Update angle if first ball - actor is ball. */ void C_DECL A_SorcUpdateBallAngle(mobj_t *actor) { if(actor->type == MT_SORCBALL1) { actor->target->special1 += ANGLE_1 * actor->target->args[4]; } } /** * Actor is ball. */ void C_DECL A_CastSorcererSpell(mobj_t *mo) { float z; mobj_t *pmo; int spell = mo->type; angle_t ang1, ang2; mobj_t *parent = mo->target; S_StartSound(SFX_SORCERER_SPELLCAST, NULL); // Put sorcerer into throw spell animation. if(parent->health > 0) P_SetMobjStateNF(parent, S_SORC_ATTACK4); switch(spell) { case MT_SORCBALL1: // Offensive. A_SorcOffense1(mo); break; case MT_SORCBALL2: // Defensive. z = parent->pos[VZ] - parent->floorClip + SORC_DEFENSE_HEIGHT; if((pmo = P_SpawnMobj3f(MT_SORCFX2, mo->pos[VX], mo->pos[VY], z, mo->angle, 0))) pmo->target = parent; parent->flags2 |= MF2_REFLECTIVE | MF2_INVULNERABLE; parent->args[0] = SORC_DEFENSE_TIME; break; case MT_SORCBALL3: // Reinforcements. ang1 = mo->angle - ANGLE_45; ang2 = mo->angle + ANGLE_45; if(mo->health < (mo->info->spawnHealth / 3)) { // Spawn 2 at a time. if((pmo = P_SpawnMissileAngle(MT_SORCFX3, parent, ang1, 4))) pmo->target = parent; if((pmo = P_SpawnMissileAngle(MT_SORCFX3, parent, ang2, 4))) pmo->target = parent; } else { if(P_Random() < 128) ang1 = ang2; if((pmo = P_SpawnMissileAngle(MT_SORCFX3, parent, ang1, 4))) pmo->target = parent; } break; default: break; } } /** * Actor is ball. */ void C_DECL A_SorcOffense1(mobj_t *mo) { mobj_t *pmo; angle_t ang1, ang2; mobj_t *parent = mo->target; ang1 = mo->angle + ANGLE_1 * 70; ang2 = mo->angle - ANGLE_1 * 70; pmo = P_SpawnMissileAngle(MT_SORCFX1, parent, ang1, 0); if(pmo) { pmo->target = parent; pmo->tracer = parent->target; pmo->args[4] = BOUNCE_TIME_UNIT; pmo->args[3] = 15; // Bounce time in seconds. } pmo = P_SpawnMissileAngle(MT_SORCFX1, parent, ang2, 0); if(pmo) { pmo->target = parent; pmo->tracer = parent->target; pmo->args[4] = BOUNCE_TIME_UNIT; pmo->args[3] = 15; // Bounce time in seconds. } } /** * Actor is ball. */ void C_DECL A_SorcOffense2(mobj_t *mo) { angle_t ang1; mobj_t *pmo; int delta, index; mobj_t *parent = mo->target; mobj_t *target = parent->target; int dist; index = mo->args[4] << 5; mo->args[4] += 15; delta = (finesine[index]) * SORCFX4_SPREAD_ANGLE; delta = (delta >> FRACBITS) * ANGLE_1; ang1 = mo->angle + delta; pmo = P_SpawnMissileAngle(MT_SORCFX4, parent, ang1, 0); if(pmo) { pmo->special2 = TICSPERSEC * 5 / 2; dist = P_ApproxDistance(target->pos[VX] - pmo->pos[VX], target->pos[VY] - pmo->pos[VY]); dist /= pmo->info->speed; if(dist < 1) dist = 1; pmo->mom[MZ] = (target->pos[VZ] - pmo->pos[VZ]) / dist; } } /** * Resume ball spinning. */ void C_DECL A_SorcBossAttack(mobj_t *actor) { actor->args[3] = SORC_ACCELERATE; actor->args[2] = SORCBALL_INITIAL_SPEED; } /** * Spell cast magic fizzle. */ void C_DECL A_SpawnFizzle(mobj_t* mo) { uint an; float pos[3], dist = 5, speed = mo->info->speed; int ix; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; an = mo->angle >> ANGLETOFINESHIFT; pos[VX] += dist * FIX2FLT(finecosine[an]); pos[VY] += dist * FIX2FLT(finesine[an]); pos[VZ] += mo->height / 2; pos[VZ] -= mo->floorClip; for(ix = 0; ix < 5; ++ix) { mobj_t* pmo; if((pmo = P_SpawnMobj3fv(MT_SORCSPARK1, pos, P_Random() << 24, 0))) { unsigned int randAn = (mo->angle >> ANGLETOFINESHIFT) + ((P_Random() % 5) * 2); pmo->mom[MX] = FIX2FLT(FixedMul(P_Random() % FLT2FIX(speed), finecosine[randAn])); pmo->mom[MY] = FIX2FLT(FixedMul(P_Random() % FLT2FIX(speed), finesine[randAn])); pmo->mom[MZ] = 2; } } } /** * Yellow spell - offense. */ void C_DECL A_SorcFX1Seek(mobj_t* actor) { A_BounceCheck(actor); P_SeekerMissile(actor, ANGLE_1 * 2, ANGLE_1 * 6); } /** * FX2 Variables. * special1 current angle * special2 * args[0] 0 = CW, 1 = CCW * args[1] */ /** * Blue spell - defense (split ball in two). */ void C_DECL A_SorcFX2Split(mobj_t* mo) { mobj_t* pmo; if((pmo = P_SpawnMobj3fv(MT_SORCFX2, mo->pos, mo->angle, 0))) { pmo->target = mo->target; pmo->args[0] = 0; // CW. pmo->special1 = mo->angle; // Set angle. P_SetMobjStateNF(pmo, S_SORCFX2_ORBIT1); } if((pmo = P_SpawnMobj3fv(MT_SORCFX2, mo->pos, mo->angle, 0))) { pmo->target = mo->target; pmo->args[0] = 1; // CCW. pmo->special1 = mo->angle; // Set angle. P_SetMobjStateNF(pmo, S_SORCFX2_ORBIT1); } P_SetMobjStateNF(mo, S_NULL); } /** * Orbit FX2 about sorcerer. */ void C_DECL A_SorcFX2Orbit(mobj_t* mo) { unsigned int an; angle_t angle; float pos[3]; mobj_t* parent = mo->target; float dist = parent->info->radius; if(parent->health <= 0 || // Sorcerer is dead. !parent->args[0]) // Time expired. { P_SetMobjStateNF(mo, P_GetState(mo->type, SN_DEATH)); parent->args[0] = 0; parent->flags2 &= ~(MF2_REFLECTIVE | MF2_INVULNERABLE); } if(mo->args[0] && (parent->args[0]-- <= 0)) // Time expired. { P_SetMobjStateNF(mo, P_GetState(mo->type, SN_DEATH)); parent->args[0] = 0; parent->flags2 &= ~MF2_REFLECTIVE; } // Move to new position based on angle. if(mo->args[0]) // Counter clock-wise. mo->special1 += ANGLE_1 * 10; else // Clock wise. mo->special1 -= ANGLE_1 * 10; angle = (angle_t) mo->special1; an = angle >> ANGLETOFINESHIFT; pos[VX] = parent->pos[VX]; pos[VY] = parent->pos[VY]; pos[VZ] = parent->pos[VZ]; pos[VX] += dist * FIX2FLT(finecosine[an]); pos[VY] += dist * FIX2FLT(finesine[an]); pos[VZ] += SORC_DEFENSE_HEIGHT + (mo->args[0]? 15 : 20) * FIX2FLT(finecosine[an]); pos[VZ] -= parent->floorClip; // Spawn trailer. P_SpawnMobj3fv(MT_SORCFX2_T1, pos, angle, 0); P_MobjUnsetPosition(mo); mo->pos[VX] = pos[VX]; mo->pos[VY] = pos[VY]; mo->pos[VZ] = pos[VZ]; P_MobjSetPosition(mo); } /** * Green spell - spawn bishops. */ void C_DECL A_SpawnBishop(mobj_t *mo) { mobj_t* pmo; if((pmo = P_SpawnMobj3fv(MT_BISHOP, mo->pos, mo->angle, 0))) { if(!P_TestMobjLocation(pmo)) { P_MobjChangeState(pmo, S_NULL); } } P_MobjChangeState(mo, S_NULL); } void C_DECL A_SmokePuffExit(mobj_t* mo) { P_SpawnMobj3fv(MT_MNTRSMOKEEXIT, mo->pos, mo->angle, 0); } void C_DECL A_SorcererBishopEntry(mobj_t* mo) { P_SpawnMobj3fv(MT_SORCFX3_EXPLOSION, mo->pos, mo->angle, 0); S_StartSound(mo->info->seeSound, mo); } /** * FX4 - rapid fire balls. */ void C_DECL A_SorcFX4Check(mobj_t* mo) { if(mo->special2-- <= 0) { P_SetMobjStateNF(mo, P_GetState(mo->type, SN_DEATH)); } } /** * Ball death - spawn stuff. */ void C_DECL A_SorcBallPop(mobj_t* mo) { S_StartSound(SFX_SORCERER_BALLPOP, NULL); mo->flags &= ~MF_NOGRAVITY; mo->flags2 |= MF2_LOGRAV; mo->mom[MX] = (float) ((P_Random() % 10) - 5); mo->mom[MY] = (float) ((P_Random() % 10) - 5); mo->mom[MZ] = (float) (2 + (P_Random() % 3)); mo->special2 = 4 * FRACUNIT; // Initial bounce factor. mo->args[4] = BOUNCE_TIME_UNIT; // Bounce time unit. mo->args[3] = 5; // Bounce time in seconds. } void C_DECL A_BounceCheck(mobj_t* mo) { if(mo->args[4]-- <= 0) { if(mo->args[3]-- <= 0) { P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); switch(mo->type) { case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: S_StartSound(SFX_SORCERER_BIGBALLEXPLODE, NULL); break; case MT_SORCFX1: S_StartSound(SFX_SORCERER_HEADSCREAM, NULL); break; default: break; } } else { mo->args[4] = BOUNCE_TIME_UNIT; } } } void C_DECL A_FastChase(mobj_t* mo) { #define CLASS_BOSS_STRAFE_RANGE (64*10) int delta; float dist; angle_t angle; uint an; mobj_t* target; statenum_t state; if(mo->reactionTime) { mo->reactionTime--; } // Modify target threshold. if(mo->threshold) { mo->threshold--; } if(gameSkill == SM_NIGHTMARE || (fastMonsters)) { // Monsters move faster in nightmare mode. mo->tics -= mo->tics / 2; if(mo->tics < 3) { mo->tics = 3; } } // Turn towards movement direction if not there yet. if(mo->moveDir < DI_NODIR) { mo->angle &= (7 << 29); delta = mo->angle - (mo->moveDir << 29); if(delta > 0) { mo->angle -= ANG90 / 2; } else if(delta < 0) { mo->angle += ANG90 / 2; } } if(!mo->target || !(mo->target->flags & MF_SHOOTABLE)) { // Look for a new target. if(P_LookForPlayers(mo, true)) return; // Got a new target P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN)); return; } // Don't attack twice in a row. if(mo->flags & MF_JUSTATTACKED) { mo->flags &= ~MF_JUSTATTACKED; if(gameSkill != SM_NIGHTMARE) P_NewChaseDir(mo); return; } // Strafe. if(mo->special2 > 0) { mo->special2--; } else { target = mo->target; mo->special2 = 0; mo->mom[MX] = mo->mom[MY] = 0; dist = P_ApproxDistance(mo->pos[VX] - target->pos[VX], mo->pos[VY] - target->pos[VY]); if(dist < CLASS_BOSS_STRAFE_RANGE) { if(P_Random() < 100) { angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY], target->pos[VX], target->pos[VY]); if(P_Random() < 128) angle += ANGLE_90; else angle -= ANGLE_90; an = angle >> ANGLETOFINESHIFT; mo->mom[MX] = 13 * FIX2FLT(finecosine[an]); mo->mom[MY] = 13 * FIX2FLT(finesine[an]); mo->special2 = 3; // Strafe time. } } } // Check for missile attack. if((state = P_GetState(mo->type, SN_MISSILE)) != S_NULL) { if(gameSkill < SM_NIGHTMARE && mo->moveCount) goto nomissile; if(!P_CheckMissileRange(mo)) goto nomissile; P_MobjChangeState(mo, state); mo->flags |= MF_JUSTATTACKED; return; } nomissile: // Possibly choose another target. if(IS_NETGAME && !mo->threshold && !P_CheckSight(mo, mo->target)) { if(P_LookForPlayers(mo, true)) return; // Got a new target. } // Chase towards player. if(!mo->special2) { if(--mo->moveCount < 0 || !P_Move(mo)) { P_NewChaseDir(mo); } } #undef CLASS_BOSS_STRAFE_RANGE } void C_DECL A_FighterAttack(mobj_t *mo) { if(!mo->target) return; A_FSwordAttack2(mo); } void C_DECL A_ClericAttack(mobj_t *mo) { if(!mo->target) return; A_CHolyAttack3(mo); } void C_DECL A_MageAttack(mobj_t *mo) { if(!mo->target) return; A_MStaffAttack2(mo); } void C_DECL A_ClassBossHealth(mobj_t* mo) { if(IS_NETGAME && !deathmatch) // Co-op only. { if(!mo->special1) { mo->health *= 5; mo->special1 = true; // Has been initialized. } } } /** * Checks if an object hit the floor. */ void C_DECL A_CheckFloor(mobj_t* mo) { if(mo->pos[VZ] <= mo->floorZ) { mo->pos[VZ] = mo->floorZ; mo->flags2 &= ~MF2_LOGRAV; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); } } void C_DECL A_FreezeDeath(mobj_t* mo) { mo->tics = 75 + P_Random() + P_Random(); mo->flags |= MF_SOLID | MF_SHOOTABLE | MF_NOBLOOD; mo->flags2 |= MF2_PUSHABLE | MF2_TELESTOMP | MF2_PASSMOBJ | MF2_SLIDE; mo->height *= 2*2; S_StartSound(SFX_FREEZE_DEATH, mo); if(mo->player) { player_t* plr = mo->player; plr->damageCount = 0; plr->poisonCount = 0; plr->bonusCount = 0; ST_doPaletteStuff(plr - players, false); } else if(mo->flags & MF_COUNTKILL && mo->special) { // Initiate monster death actions. P_ExecuteLineSpecial(mo->special, mo->args, NULL, 0, mo); } } void C_DECL A_IceSetTics(mobj_t* mo) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); mo->tics = 70 + (P_Random() & 63); if(tt->flags & TTF_FRICTION_LOW) { mo->tics *= 2; } else if(tt->flags & TTF_FRICTION_HIGH) { mo->tics /= 4; } } void C_DECL A_IceCheckHeadDone(mobj_t* mo) { if(mo->special2 == 666) { P_MobjChangeState(mo, S_ICECHUNK_HEAD2); } } #ifdef MSVC # pragma optimize("g", off) #endif void C_DECL A_FreezeDeathChunks(mobj_t* mo) { int i; mobj_t* pmo; float pos[3]; if(mo->mom[MX] != 0 || mo->mom[MY] != 0 || mo->mom[MZ] != 0) { mo->tics = 105; return; } S_StartSound(SFX_FREEZE_SHATTER, mo); for(i = 12 + (P_Random() & 15); i >= 0; i--) { pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += FIX2FLT(((P_Random() - 128) * FLT2FIX(mo->radius)) >> 7); pos[VY] += FIX2FLT(((P_Random() - 128) * FLT2FIX(mo->radius)) >> 7); pos[VZ] += (P_Random() * mo->height) / 255; if((pmo = P_SpawnMobj3fv(MT_ICECHUNK, pos, P_Random() << 24, 0))) { P_MobjChangeState(pmo, P_GetState(pmo->type, SN_SPAWN) + (P_Random() % 3)); pmo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); pmo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); pmo->mom[MZ] = ((pmo->pos[VZ] - mo->pos[VZ]) / mo->height) * 4; A_IceSetTics(pmo); // Set a random tic wait. } } for(i = 12 + (P_Random() & 15); i >= 0; i--) { pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += FIX2FLT(((P_Random() - 128) * FLT2FIX(mo->radius)) >> 7); pos[VY] += FIX2FLT(((P_Random() - 128) * FLT2FIX(mo->radius)) >> 7); pos[VZ] += (P_Random() * mo->height) / 255; if((pmo = P_SpawnMobj3fv(MT_ICECHUNK, pos, P_Random() << 24, 0))) { P_MobjChangeState(pmo, P_GetState(pmo->type, SN_SPAWN) + (P_Random() % 3)); pmo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); pmo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); pmo->mom[MZ] = ((pmo->pos[VZ] - mo->pos[VZ]) / mo->height) * 4; A_IceSetTics(pmo); // Set a random tic wait. } } if(mo->player) { // Attach the player's view to a chunk of ice. if((pmo = P_SpawnMobj3f(MT_ICECHUNK, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + VIEWHEIGHT, mo->angle, 0))) { P_MobjChangeState(pmo, S_ICECHUNK_HEAD); pmo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 9); pmo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 9); pmo->mom[MZ] = ((pmo->pos[VZ] - mo->pos[VZ]) / mo->height) * 4; pmo->flags2 |= MF2_ICEDAMAGE; // Used to force blue palette. pmo->flags2 &= ~MF2_FLOORCLIP; pmo->player = mo->player; pmo->dPlayer = mo->dPlayer; mo->player = NULL; mo->dPlayer = NULL; pmo->health = mo->health; pmo->player->plr->mo = pmo; pmo->player->plr->lookDir = 0; } } P_MobjRemoveFromTIDList(mo); P_MobjChangeState(mo, S_FREETARGMOBJ); mo->flags2 |= MF2_DONTDRAW; } #ifdef MSVC # pragma optimize("", off) #endif /** * Korax Variables. * * special1 Last teleport destination. * special2 Set if "below half" script not yet run. */ /** * Korax Scripts (reserved). * * 249 Tell scripts that we are below half health. * 250-254 Control scripts. * 255 Death script. */ /** * Korax TIDs (reserved). * * 245 Reserved for Korax himself. * 248 Initial teleport destination. * 249 Teleport destination. * 250-254 For use in respective control scripts. * 255 For use in death script (spawn spots). */ void C_DECL A_KoraxChase(mobj_t* actor) { mobj_t* spot; byte args[3] = { 0, 0, 0 }; if(!actor->special2 && actor->health <= actor->info->spawnHealth / 2) { actor->special1 = 0; spot = P_FindMobjFromTID(KORAX_FIRST_TELEPORT_TID, &actor->special1); if(spot) { P_Teleport(actor, spot->pos[VX], spot->pos[VY], spot->angle, true); } P_StartACS(249, 0, args, actor, NULL, 0); actor->special2 = 1; // Don't run again. return; } if(!actor->target) return; if(P_Random() < 30) { P_MobjChangeState(actor, P_GetState(actor->type, SN_MISSILE)); } else if(P_Random() < 30) { S_StartSound(SFX_KORAX_ACTIVE, NULL); } // Teleport away. if(actor->health < actor->info->spawnHealth >> 1) { if(P_Random() < 10) { spot = P_FindMobjFromTID(KORAX_TELEPORT_TID, &actor->special1); actor->tracer = spot; if(spot) { P_Teleport(actor, spot->pos[VX], spot->pos[VY], spot->angle, true); } } } } void C_DECL A_KoraxStep(mobj_t* actor) { A_Chase(actor); } void C_DECL A_KoraxStep2(mobj_t* actor) { S_StartSound(SFX_KORAX_STEP, NULL); A_Chase(actor); } void C_DECL A_KoraxBonePop(mobj_t* actor) { mobj_t* mo; byte args[5]; args[0] = args[1] = args[2] = args[3] = args[4] = 0; // Spawn 6 spirits equalangularly. mo = P_SpawnMissileAngle(MT_KORAX_SPIRIT1, actor, ANGLE_60 * 0, 5); if(mo) KSpiritInit(mo, actor); mo = P_SpawnMissileAngle(MT_KORAX_SPIRIT2, actor, ANGLE_60 * 1, 5); if(mo) KSpiritInit(mo, actor); mo = P_SpawnMissileAngle(MT_KORAX_SPIRIT3, actor, ANGLE_60 * 2, 5); if(mo) KSpiritInit(mo, actor); mo = P_SpawnMissileAngle(MT_KORAX_SPIRIT4, actor, ANGLE_60 * 3, 5); if(mo) KSpiritInit(mo, actor); mo = P_SpawnMissileAngle(MT_KORAX_SPIRIT5, actor, ANGLE_60 * 4, 5); if(mo) KSpiritInit(mo, actor); mo = P_SpawnMissileAngle(MT_KORAX_SPIRIT6, actor, ANGLE_60 * 5, 5); if(mo) KSpiritInit(mo, actor); P_StartACS(255, 0, args, actor, NULL, 0); // Death script. } void KSpiritInit(mobj_t* spirit, mobj_t* korax) { mobj_t* tail; spirit->health = KORAX_SPIRIT_LIFETIME; spirit->tracer = korax; // Swarm around korax. spirit->special2 = 32 + (P_Random() & 7); // Float bob index. spirit->args[0] = 10; // Initial turn value. spirit->args[1] = 0; // Initial look angle. // Spawn a tail for spirit. if((tail = P_SpawnMobj3fv(MT_HOLY_TAIL, spirit->pos, spirit->angle + ANG180, 0))) { int i; tail->target = spirit; // Parent. for(i = 1; i < 3; ++i) { mobj_t* next; if((next = P_SpawnMobj3fv(MT_HOLY_TAIL, spirit->pos, spirit->angle + ANG180, 0))) { P_MobjChangeState(next, P_GetState(next->type, SN_SPAWN) + 1); tail->tracer = next; tail = next; } } tail->tracer = NULL; // Last tail bit. } } void C_DECL A_KoraxDecide(mobj_t* actor) { if(P_Random() < 220) { P_MobjChangeState(actor, S_KORAX_MISSILE1); } else { P_MobjChangeState(actor, S_KORAX_COMMAND1); } } static void spawnKoraxMissile(mobjtype_t type, angle_t angle, float distance, float height, mobj_t* source, mobj_t* target) { uint an; float pos[3]; pos[VX] = source->pos[VX]; pos[VY] = source->pos[VY]; pos[VZ] = source->pos[VZ]; an = angle >> ANGLETOFINESHIFT; pos[VX] += distance * FIX2FLT(finecosine[an]); pos[VY] += distance * FIX2FLT(finesine[an]); pos[VZ] += height; P_SpawnKoraxMissile(type, pos[VX], pos[VY], pos[VZ], source, target); } /** * Korax: Six missile attack. * * Arm indices: * 1 = top left. * 2 = middle left. * 3 = lower left. * 4 = top right. * 5 = middle right. * 6 = lower right. */ void C_DECL A_KoraxMissile(mobj_t* mo) { int type = P_Random() % 6; int sound = 0; S_StartSound(SFX_KORAX_ATTACK, mo); switch(type) { case 0: type = MT_WRAITHFX1; sound = SFX_WRAITH_MISSILE_FIRE; break; case 1: type = MT_DEMONFX1; sound = SFX_DEMON_MISSILE_FIRE; break; case 2: type = MT_DEMON2FX1; sound = SFX_DEMON_MISSILE_FIRE; break; case 3: type = MT_FIREDEMON_FX6; sound = SFX_FIRED_ATTACK; break; case 4: type = MT_CENTAUR_FX; sound = SFX_CENTAURLEADER_ATTACK; break; case 5: type = MT_SERPENTFX; sound = SFX_CENTAURLEADER_ATTACK; break; } S_StartSound(sound, NULL); // Fire all 6 missiles at once. spawnKoraxMissile(type, mo->angle - KORAX_DELTAANGLE, KORAX_ARM_EXTENSION_SHORT, KORAX_ARM1_HEIGHT - mo->floorClip, mo, mo->target); spawnKoraxMissile(type, mo->angle - KORAX_DELTAANGLE, KORAX_ARM_EXTENSION_LONG, KORAX_ARM2_HEIGHT - mo->floorClip, mo, mo->target); spawnKoraxMissile(type, mo->angle - KORAX_DELTAANGLE, KORAX_ARM_EXTENSION_LONG, KORAX_ARM3_HEIGHT - mo->floorClip, mo, mo->target); spawnKoraxMissile(type, mo->angle + KORAX_DELTAANGLE, KORAX_ARM_EXTENSION_SHORT, KORAX_ARM4_HEIGHT - mo->floorClip, mo, mo->target); spawnKoraxMissile(type, mo->angle + KORAX_DELTAANGLE, KORAX_ARM_EXTENSION_LONG, KORAX_ARM5_HEIGHT - mo->floorClip, mo, mo->target); spawnKoraxMissile(type, mo->angle + KORAX_DELTAANGLE, KORAX_ARM_EXTENSION_LONG, KORAX_ARM6_HEIGHT - mo->floorClip, mo, mo->target); } /** * Call action code scripts (250-254). */ void C_DECL A_KoraxCommand(mobj_t* mo) { byte args[5]; float pos[3]; uint an; int numcommands; S_StartSound(SFX_KORAX_COMMAND, mo); // Shoot stream of lightning to ceiling. an = (mo->angle - ANGLE_90) >> ANGLETOFINESHIFT; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += KORAX_COMMAND_OFFSET * FIX2FLT(finecosine[an]); pos[VY] += KORAX_COMMAND_OFFSET * FIX2FLT(finesine[an]); pos[VZ] += KORAX_COMMAND_HEIGHT; P_SpawnMobj3fv(MT_KORAX_BOLT, pos, mo->angle, 0); args[0] = args[1] = args[2] = args[3] = args[4] = 0; if(mo->health <= mo->info->spawnHealth / 2) { numcommands = 5; } else { numcommands = 4; } switch(P_Random() % numcommands) { case 0: P_StartACS(250, 0, args, mo, NULL, 0); break; case 1: P_StartACS(251, 0, args, mo, NULL, 0); break; case 2: P_StartACS(252, 0, args, mo, NULL, 0); break; case 3: P_StartACS(253, 0, args, mo, NULL, 0); break; case 4: P_StartACS(254, 0, args, mo, NULL, 0); break; } } void C_DECL A_KSpiritWeave(mobj_t* mo) { float pos[3]; uint weaveXY, weaveZ; uint an; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; an = (mo->angle + ANG90) >> ANGLETOFINESHIFT; // Unpack the last weave vector. weaveXY = mo->special2 >> 16; weaveZ = mo->special2 & 0xFFFF; pos[VX] -= FIX2FLT(finecosine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); pos[VY] -= FIX2FLT(finesine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); pos[VZ] -= FLOATBOBOFFSET(weaveZ) * 2; weaveXY = (weaveXY + (P_Random() % 5)) & 63; weaveZ = (weaveZ + (P_Random() % 5)) & 63; pos[VX] += FIX2FLT(finecosine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); pos[VY] += FIX2FLT(finesine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); pos[VZ] += FLOATBOBOFFSET(weaveZ) * 2; P_TryMove(mo, pos[VX], pos[VY]); // P_TryMove won't update the z height, so set it manually. // Should this not be clipped vs the floor/ceiling? - DJS mo->pos[VZ] = pos[VZ]; // Store the weave vector. mo->special2 = weaveZ + (weaveXY << 16); } void C_DECL A_KSpiritSeeker(mobj_t* mo, angle_t thresh, angle_t turnMax) { int dir, dist; angle_t delta; uint an; mobj_t* target; float newZ, deltaZ; target = mo->tracer; if(target == NULL) return; dir = P_FaceMobj(mo, target, &delta); if(delta > thresh) { delta /= 2; if(delta > turnMax) { delta = turnMax; } } if(dir) // Turn clockwise. mo->angle += delta; else // Turn counter clockwise. mo->angle -= delta; an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); if(!(mapTime & 15) || (mo->pos[VZ] > target->pos[VZ] + target->info->height) || (mo->pos[VZ] + mo->height < target->pos[VZ])) { newZ = target->pos[VZ] + FIX2FLT((P_Random() * FLT2FIX(target->info->height)) >> 8); deltaZ = newZ - mo->pos[VZ]; if(fabs(deltaZ) > 15) { if(deltaZ > 0) { deltaZ = 15; } else { deltaZ = -15 * FRACUNIT; } } dist = P_ApproxDistance(target->pos[VX] - mo->pos[VX], target->pos[VY] - mo->pos[VY]); dist /= mo->info->speed; if(dist < 1) dist = 1; mo->mom[MZ] = deltaZ / dist; } } void C_DECL A_KSpiritRoam(mobj_t* mo) { if(mo->health-- <= 0) { S_StartSound(SFX_SPIRIT_DIE, mo); P_MobjChangeState(mo, S_KSPIRIT_DEATH1); } else { if(mo->tracer) { A_KSpiritSeeker(mo, mo->args[0] * ANGLE_1, mo->args[0] * ANGLE_1 * 2); } A_KSpiritWeave(mo); if(P_Random() < 50) { S_StartSound(SFX_SPIRIT_ACTIVE, NULL); } } } void C_DECL A_KBolt(mobj_t* mo) { // Countdown lifetime. if(mo->special1-- <= 0) { P_MobjChangeState(mo, S_NULL); } } void C_DECL A_KBoltRaise(mobj_t* mo) { #define KORAX_BOLT_HEIGHT (48) #define KORAX_BOLT_LIFETIME (3) float z; mobj_t* pmo; // Spawn a child upward. z = mo->pos[VZ] + KORAX_BOLT_HEIGHT; if(z + KORAX_BOLT_HEIGHT < mo->ceilingZ) { if((pmo = P_SpawnMobj3f(MT_KORAX_BOLT, mo->pos[VX], mo->pos[VY], z, mo->angle, 0))) { pmo->special1 = KORAX_BOLT_LIFETIME; } } #undef KORAX_BOLT_HEIGHT #undef KORAX_BOLT_LIFETIME } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_spec.c0000644000175000017500000010221011357170242022227 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "dmu_lib.h" #include "p_inventory.h" #include "p_player.h" #include "p_map.h" #include "p_mapsetup.h" #include "p_mapspec.h" #include "p_ceiling.h" #include "p_door.h" #include "p_plat.h" #include "p_floor.h" #include "p_switch.h" // MACROS ------------------------------------------------------------------ #define LIGHTNING_SPECIAL 198 #define LIGHTNING_SPECIAL2 199 #define SKYCHANGE_SPECIAL 200 // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void P_LightningFlash(void); static boolean CheckedLockedDoor(mobj_t* mo, byte lock); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- mobj_t lavaInflictor; materialnum_t sky1Material; materialnum_t sky2Material; float sky1ColumnOffset; float sky2ColumnOffset; float sky1ScrollDelta; float sky2ScrollDelta; boolean doubleSky; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static boolean mapHasLightning; static int nextLightningFlash; static int lightningFlash; static float* lightningLightLevels; // CODE -------------------------------------------------------------------- void P_InitLava(void) { memset(&lavaInflictor, 0, sizeof(mobj_t)); lavaInflictor.type = MT_CIRCLEFLAME; lavaInflictor.flags2 = MF2_FIREDAMAGE | MF2_NODMGTHRUST; } void P_InitSky(uint map) { int ival; float fval; sky1Material = P_GetMapSky1Material(map); sky2Material = P_GetMapSky2Material(map); sky1ScrollDelta = P_GetMapSky1ScrollDelta(map); sky2ScrollDelta = P_GetMapSky2ScrollDelta(map); sky1ColumnOffset = 0; sky2ColumnOffset = 0; doubleSky = P_GetMapDoubleSky(map); // First disable all sky layers. Rend_SkyParams(DD_SKY, DD_DISABLE, NULL); // Sky2 is layer zero and Sky1 is layer one. fval = 0; Rend_SkyParams(0, DD_OFFSET, &fval); Rend_SkyParams(1, DD_OFFSET, &fval); if(doubleSky) { Rend_SkyParams(0, DD_ENABLE, NULL); ival = DD_NO; Rend_SkyParams(0, DD_MASK, &ival); Rend_SkyParams(0, DD_MATERIAL, &sky2Material); Rend_SkyParams(1, DD_ENABLE, NULL); ival = DD_YES; Rend_SkyParams(1, DD_MASK, &ival); Rend_SkyParams(1, DD_MATERIAL, &sky1Material); } else { Rend_SkyParams(0, DD_ENABLE, NULL); ival = DD_NO; Rend_SkyParams(0, DD_MASK, &ival); Rend_SkyParams(0, DD_MATERIAL, &sky1Material); Rend_SkyParams(1, DD_DISABLE, NULL); ival = DD_NO; Rend_SkyParams(1, DD_MASK, &ival); Rend_SkyParams(1, DD_MATERIAL, &sky2Material); } } boolean EV_SectorSoundChange(byte* args) { boolean rtn = false; sector_t* sec = NULL; iterlist_t* list; if(!args[0]) return false; list = P_GetSectorIterListForTag((int) args[0], false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { P_ToXSector(sec)->seqType = args[1]; rtn = true; } return rtn; } static boolean CheckedLockedDoor(mobj_t* mo, byte lock) { extern int TextKeyMessages[11]; char LockedBuffer[80]; if(!mo->player) return false; if(!lock) return true; if(!(mo->player->keys & (1 << (lock - 1)))) { sprintf(LockedBuffer, "YOU NEED THE %s\n", GET_TXT(TextKeyMessages[lock - 1])); P_SetMessage(mo->player, LockedBuffer, false); S_StartSound(SFX_DOOR_LOCKED, mo); return false; } return true; } boolean EV_LineSearchForPuzzleItem(linedef_t* line, byte* args, mobj_t* mo) { inventoryitemtype_t type; if(!mo || !mo->player || !line) return false; type = IIT_FIRSTPUZZITEM + P_ToXLine(line)->arg1; if(type < IIT_FIRSTPUZZITEM) return false; // Search player's inventory for puzzle items return P_InventoryUse(mo->player - players, type, false); } boolean P_ExecuteLineSpecial(int special, byte* args, linedef_t* line, int side, mobj_t* mo) { boolean success; success = false; switch(special) { case 1: // Poly Start Line break; case 2: // Poly Rotate Left success = EV_RotatePoly(line, args, 1, false); break; case 3: // Poly Rotate Right success = EV_RotatePoly(line, args, -1, false); break; case 4: // Poly Move success = EV_MovePoly(line, args, false, false); break; case 5: // Poly Explicit Line: Only used in initialization break; case 6: // Poly Move Times 8 success = EV_MovePoly(line, args, true, false); break; case 7: // Poly Door Swing success = EV_OpenPolyDoor(line, args, PODOOR_SWING); break; case 8: // Poly Door Slide success = EV_OpenPolyDoor(line, args, PODOOR_SLIDE); break; case 10: // Door Close success = EV_DoDoor(line, args, DT_CLOSE); break; case 11: // Door Open if(!args[0]) { success = EV_VerticalDoor(line, mo); } else { success = EV_DoDoor(line, args, DT_OPEN); } break; case 12: // Door Raise if(!args[0]) { success = EV_VerticalDoor(line, mo); } else { success = EV_DoDoor(line, args, DT_NORMAL); } break; case 13: // Door Locked_Raise if(CheckedLockedDoor(mo, args[3])) { if(!args[0]) { success = EV_VerticalDoor(line, mo); } else { success = EV_DoDoor(line, args, DT_NORMAL); } } break; case 20: // Floor Lower by Value success = EV_DoFloor(line, args, FT_LOWERBYVALUE); break; case 21: // Floor Lower to Lowest success = EV_DoFloor(line, args, FT_LOWERTOLOWEST); break; case 22: // Floor Lower to Nearest success = EV_DoFloor(line, args, FT_LOWER); break; case 23: // Floor Raise by Value success = EV_DoFloor(line, args, FT_RAISEFLOORBYVALUE); break; case 24: // Floor Raise to Highest success = EV_DoFloor(line, args, FT_RAISEFLOOR); break; case 25: // Floor Raise to Nearest success = EV_DoFloor(line, args, FT_RAISEFLOORTONEAREST); break; case 26: // Stairs Build Down Normal success = EV_BuildStairs(line, args, -1, STAIRS_NORMAL); break; case 27: // Build Stairs Up Normal success = EV_BuildStairs(line, args, 1, STAIRS_NORMAL); break; case 28: // Floor Raise and Crush success = EV_DoFloor(line, args, FT_RAISEFLOORCRUSH); break; case 29: // Build Pillar (no crushing) success = EV_BuildPillar(line, args, false); break; case 30: // Open Pillar success = EV_OpenPillar(line, args); break; case 31: // Stairs Build Down Sync success = EV_BuildStairs(line, args, -1, STAIRS_SYNC); break; case 32: // Build Stairs Up Sync success = EV_BuildStairs(line, args, 1, STAIRS_SYNC); break; case 35: // Raise Floor by Value Times 8 success = EV_DoFloor(line, args, FT_RAISEBYVALUEMUL8); break; case 36: // Lower Floor by Value Times 8 success = EV_DoFloor(line, args, FT_LOWERBYVALUEMUL8); break; case 40: // Ceiling Lower by Value success = EV_DoCeiling(line, args, CT_LOWERBYVALUE); break; case 41: // Ceiling Raise by Value success = EV_DoCeiling(line, args, CT_RAISEBYVALUE); break; case 42: // Ceiling Crush and Raise success = EV_DoCeiling(line, args, CT_CRUSHANDRAISE); break; case 43: // Ceiling Lower and Crush success = EV_DoCeiling(line, args, CT_LOWERANDCRUSH); break; case 44: // Ceiling Crush Stop success = P_CeilingDeactivate((short) args[0]); break; case 45: // Ceiling Crush Raise and Stay success = EV_DoCeiling(line, args, CT_CRUSHRAISEANDSTAY); break; case 46: // Floor Crush Stop success = EV_FloorCrushStop(line, args); break; case 60: // Plat Perpetual Raise success = EV_DoPlat(line, args, PT_PERPETUALRAISE, 0); break; case 61: // Plat Stop P_PlatDeactivate((short) args[0]); break; case 62: // Plat Down-Wait-Up-Stay success = EV_DoPlat(line, args, PT_DOWNWAITUPSTAY, 0); break; case 63: // Plat Down-by-Value*8-Wait-Up-Stay success = EV_DoPlat(line, args, PT_DOWNBYVALUEWAITUPSTAY, 0); break; case 64: // Plat Up-Wait-Down-Stay success = EV_DoPlat(line, args, PT_UPWAITDOWNSTAY, 0); break; case 65: // Plat Up-by-Value*8-Wait-Down-Stay success = EV_DoPlat(line, args, PT_UPBYVALUEWAITDOWNSTAY, 0); break; case 66: // Floor Lower Instant * 8 success = EV_DoFloor(line, args, FT_LOWERMUL8INSTANT); break; case 67: // Floor Raise Instant * 8 success = EV_DoFloor(line, args, FT_RAISEMUL8INSTANT); break; case 68: // Floor Move to Value * 8 success = EV_DoFloor(line, args, FT_TOVALUEMUL8); break; case 69: // Ceiling Move to Value * 8 success = EV_DoCeiling(line, args, CT_MOVETOVALUEMUL8); break; case 70: // Teleport if(side == 0) { // Only teleport when crossing the front side of a line success = EV_Teleport(args[0], mo, true); } break; case 71: // Teleport, no fog if(side == 0) { // Only teleport when crossing the front side of a line success = EV_Teleport(args[0], mo, false); } break; case 72: // Thrust Mobj if(!side) // Only thrust on side 0 { P_ThrustMobj(mo, args[0] * (ANGLE_90 / 64), (float) args[1]); success = 1; } break; case 73: // Damage Mobj if(args[0]) { P_DamageMobj(mo, NULL, NULL, args[0], false); } else { // If arg1 is zero, then guarantee a kill P_DamageMobj(mo, NULL, NULL, 10000, false); } success = 1; break; case 74: // Teleport_NewMap if(side == 0) // Only teleport when crossing the front side of a line { // Players must be alive to teleport if(!(mo && mo->player && mo->player->playerState == PST_DEAD)) { G_LeaveMap((args[0]!= 0? args[0]-1 : 0), args[1], false); success = true; } } break; case 75: // Teleport_EndGame if(side == 0) // Only teleport when crossing the front side of a line { // Players must be alive to teleport if(!(mo && mo->player && mo->player->playerState == PST_DEAD)) { success = true; if(deathmatch) { // Winning in deathmatch just goes back to map 1 G_LeaveMap(0, 0, false); } else { // Passing DDMAXINT, DDMAXINT to G_LeaveMap() starts the Finale G_LeaveMap(DDMAXINT, DDMAXINT, false); } } } break; case 80: // ACS_Execute success = P_StartACS(args[0], args[1], &args[2], mo, line, side); break; case 81: // ACS_Suspend success = P_SuspendACS(args[0], args[1]); break; case 82: // ACS_Terminate success = P_TerminateACS(args[0], args[1]); break; case 83: // ACS_LockedExecute success = P_StartLockedACS(line, args, mo, side); break; case 90: // Poly Rotate Left Override success = EV_RotatePoly(line, args, 1, true); break; case 91: // Poly Rotate Right Override success = EV_RotatePoly(line, args, -1, true); break; case 92: // Poly Move Override success = EV_MovePoly(line, args, false, true); break; case 93: // Poly Move Times 8 Override success = EV_MovePoly(line, args, true, true); break; case 94: // Build Pillar Crush success = EV_BuildPillar(line, args, true); break; case 95: // Lower Floor and Ceiling success = EV_DoFloorAndCeiling(line, args, FT_LOWERBYVALUE, CT_LOWERBYVALUE); break; case 96: // Raise Floor and Ceiling success = EV_DoFloorAndCeiling(line, args, FT_RAISEFLOORBYVALUE, CT_RAISEBYVALUE); break; case 109: // Force Lightning success = true; P_ForceLightning(); break; case 110: // Light Raise by Value success = EV_SpawnLight(line, args, LITE_RAISEBYVALUE); break; case 111: // Light Lower by Value success = EV_SpawnLight(line, args, LITE_LOWERBYVALUE); break; case 112: // Light Change to Value success = EV_SpawnLight(line, args, LITE_CHANGETOVALUE); break; case 113: // Light Fade success = EV_SpawnLight(line, args, LITE_FADE); break; case 114: // Light Glow success = EV_SpawnLight(line, args, LITE_GLOW); break; case 115: // Light Flicker success = EV_SpawnLight(line, args, LITE_FLICKER); break; case 116: // Light Strobe success = EV_SpawnLight(line, args, LITE_STROBE); break; case 120: // Quake Tremor success = A_LocalQuake(args, mo); break; case 129: // UsePuzzleItem success = EV_LineSearchForPuzzleItem(line, args, mo); break; case 130: // Thing_Activate success = EV_ThingActivate(args[0]); break; case 131: // Thing_Deactivate success = EV_ThingDeactivate(args[0]); break; case 132: // Thing_Remove success = EV_ThingRemove(args[0]); break; case 133: // Thing_Destroy success = EV_ThingDestroy(args[0]); break; case 134: // Thing_Projectile success = EV_ThingProjectile(args, 0); break; case 135: // Thing_Spawn success = EV_ThingSpawn(args, 1); break; case 136: // Thing_ProjectileGravity success = EV_ThingProjectile(args, 1); break; case 137: // Thing_SpawnNoFog success = EV_ThingSpawn(args, 0); break; case 138: // Floor_Waggle success = EV_StartFloorWaggle(args[0], args[1], args[2], args[3], args[4]); break; case 140: // Sector_SoundChange success = EV_SectorSoundChange(args); break; default: break; } return success; } boolean P_ActivateLine(linedef_t *line, mobj_t *mo, int side, int activationType) { int lineActivation; boolean repeat; boolean buttonSuccess; xline_t *xline = P_ToXLine(line); lineActivation = GET_SPAC(xline->flags); if(lineActivation != activationType) return false; if(!mo->player && !(mo->flags & MF_MISSILE)) { if(lineActivation != SPAC_MCROSS) { // currently, monsters can only activate the MCROSS activation type return false; } if(xline->flags & ML_SECRET) return false; // never DT_OPEN secret doors } repeat = ((xline->flags & ML_REPEAT_SPECIAL)? true : false); buttonSuccess = P_ExecuteLineSpecial(xline->special, &xline->arg1, line, side, mo); if(!repeat && buttonSuccess) { // clear the special on non-retriggerable lines xline->special = 0; } if((lineActivation == SPAC_USE || lineActivation == SPAC_IMPACT) && buttonSuccess) { P_ToggleSwitch(P_GetPtrp(line, DMU_SIDEDEF0), 0, false, repeat? BUTTONTIME : 0); } return true; } /** * Called every tic frame that the player origin is in a special sector. */ void P_PlayerInSpecialSector(player_t *player) { sector_t *sector; xsector_t *xsector; static float pushTab[3] = { (1.0f / 32) * 5, (1.0f / 32) * 10, (1.0f / 32) * 25 }; sector = P_GetPtrp(player->plr->mo->subsector, DMU_SECTOR); xsector = P_ToXSector(sector); if(player->plr->mo->pos[VZ] != P_GetFloatp(sector, DMU_FLOOR_HEIGHT)) return; // Player is not touching the floor switch(xsector->special) { case 9: // SecretArea player->secretCount++; xsector->special = 0; break; case 201: case 202: case 203: // Scroll_North_xxx P_Thrust(player, ANG90, pushTab[xsector->special - 201]); break; case 204: case 205: case 206: // Sxcroll_East_xxx P_Thrust(player, 0, pushTab[xsector->special - 204]); break; case 207: case 208: case 209: // Scroll_South_xxx P_Thrust(player, ANG270, pushTab[xsector->special - 207]); break; case 210: case 211: case 212: // Scroll_West_xxx P_Thrust(player, ANG180, pushTab[xsector->special - 210]); break; case 213: case 214: case 215: // Scroll_NorthWest_xxx P_Thrust(player, ANG90 + ANG45, pushTab[xsector->special - 213]); break; case 216: case 217: case 218: // Scroll_NorthEast_xxx P_Thrust(player, ANG45, pushTab[xsector->special - 216]); break; case 219: case 220: case 221: // Scroll_SouthEast_xxx P_Thrust(player, ANG270 + ANG45, pushTab[xsector->special - 219]); break; case 222: case 223: case 224: // Scroll_SouthWest_xxx P_Thrust(player, ANG180 + ANG45, pushTab[xsector->special - 222]); break; case 40: case 41: case 42: case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: case 51: // Wind specials are handled in (P_mobj):P_MobjMoveXY break; case 26: // Stairs_Special1 case 27: // Stairs_Special2 // Used in (P_floor):ProcessStairSector break; case 198: // Lightning Special case 199: // Lightning Flash special case 200: // Sky2 // Used in (R_plane):R_Drawplanes break; default: if(IS_CLIENT) break; Con_Error("P_PlayerInSpecialSector: unknown special %i", xsector->special); } } void P_PlayerOnSpecialFloor(player_t* player) { const terraintype_t* tt = P_MobjGetFloorTerrainType(player->plr->mo); if(!(tt->flags & TTF_DAMAGING)) return; if(player->plr->mo->pos[VZ] > P_GetFloatp(player->plr->mo->subsector, DMU_FLOOR_HEIGHT)) { return; // Player is not touching the floor } if(!(mapTime & 31)) { P_DamageMobj(player->plr->mo, &lavaInflictor, NULL, 10, false); S_StartSound(SFX_LAVA_SIZZLE, player->plr->mo); } } void P_UpdateSpecials(void) { // Stub. } /** * After the map has been loaded, scan for specials that spawn thinkers. */ void P_SpawnSpecials(void) { uint i; linedef_t *line; xline_t *xline; iterlist_t *list; sector_t *sec; xsector_t *xsec; // Init special SECTORs. P_DestroySectorTagLists(); for(i = 0; i < numsectors; ++i) { sec = P_ToPtr(DMU_SECTOR, i); xsec = P_ToXSector(sec); if(xsec->tag) { list = P_GetSectorIterListForTag(xsec->tag, true); P_AddObjectToIterList(list, sec); } // Clients do not spawn sector specials. if(IS_CLIENT) break; if(!xsec->special) continue; switch(xsec->special) { case 1: // Phased light // Hardcoded base, use sector->lightLevel as the index P_SpawnPhasedLight(sec, (80.f / 255.0f), -1); break; case 2:// Phased light sequence start P_SpawnLightSequence(sec, 1); break; // Specials 3 & 4 are used by the phased light sequences } } // Init animating line specials. P_EmptyIterList(linespecials); P_DestroyLineTagLists(); for(i = 0; i < numlines; ++i) { line = P_ToPtr(DMU_LINEDEF, i); xline = P_ToXLine(line); switch(xline->special) { case 100: // Scroll_Texture_Left case 101: // Scroll_Texture_Right case 102: // Scroll_Texture_Up case 103: // Scroll_Texture_Down P_AddObjectToIterList(linespecials, line); break; case 121: // Line_SetIdentification if(xline->arg1) { list = P_GetLineIterListForTag((int) xline->arg1, true); P_AddObjectToIterList(list, line); } xline->special = 0; break; } } } void P_AnimateSurfaces(void) { #define PLANE_MATERIAL_SCROLLUNIT (8.f/35*2) uint i; linedef_t* line; // Update scrolling plane materials. for(i = 0; i < numsectors; ++i) { xsector_t* sect = P_ToXSector(P_ToPtr(DMU_SECTOR, i)); float texOff[2]; switch(sect->special) { case 201: case 202: case 203: // Scroll_North_xxx texOff[VY] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y); texOff[VY] -= PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 201); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y, texOff[VY]); break; case 204: case 205: case 206: // Scroll_East_xxx texOff[VX] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X); texOff[VX] -= PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 204); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X, texOff[VX]); break; case 207: case 208: case 209: // Scroll_South_xxx texOff[VY] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y); texOff[VY] += PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 207); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y, texOff[VY]); break; case 210: case 211: case 212: // Scroll_West_xxx texOff[VX] = P_GetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X); texOff[VX] += PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 210); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X, texOff[VX]); break; case 213: case 214: case 215: // Scroll_NorthWest_xxx P_GetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); texOff[VX] += PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 213); texOff[VY] -= PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 213); P_SetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); break; case 216: case 217: case 218: // Scroll_NorthEast_xxx P_GetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); texOff[VX] -= PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 216); texOff[VY] -= PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 216); P_SetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); break; case 219: case 220: case 221: // Scroll_SouthEast_xxx P_GetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); texOff[VX] -= PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 219); texOff[VY] += PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 219); P_SetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); break; case 222: case 223: case 224: // Scroll_SouthWest_xxx P_GetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); texOff[VX] += PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 222); texOff[VY] += PLANE_MATERIAL_SCROLLUNIT * (1 + sect->special - 222); P_SetFloatv(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_XY, texOff); break; default: // DJS - Is this really necessary every tic? P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_X, 0); P_SetFloat(DMU_SECTOR, i, DMU_FLOOR_MATERIAL_OFFSET_Y, 0); break; } } // Update scrolling wall materials. if(P_IterListSize(linespecials)) { P_IterListResetIterator(linespecials, false); while((line = P_IterListIterator(linespecials)) != NULL) { sidedef_t* side = 0; fixed_t texOff[2]; xline_t* xline = P_ToXLine(line); side = P_GetPtrp(line, DMU_SIDEDEF0); for(i = 0; i < 3; ++i) { P_GetFixedpv(side, (i==0? DMU_TOP_MATERIAL_OFFSET_XY : i==1? DMU_MIDDLE_MATERIAL_OFFSET_XY : DMU_BOTTOM_MATERIAL_OFFSET_XY), texOff); switch(xline->special) { case 100: // Scroll_Texture_Left texOff[0] += xline->arg1 << 10; break; case 101: // Scroll_Texture_Right texOff[0] -= xline->arg1 << 10; break; case 102: // Scroll_Texture_Up texOff[1] += xline->arg1 << 10; break; case 103: // Scroll_Texture_Down texOff[1] -= xline->arg1 << 10; break; default: Con_Error("P_AnimateSurfaces: Invalid line special %i for " "material scroller on linedef %ui.", xline->special, P_ToIndex(line)); } P_SetFixedpv(side, (i==0? DMU_TOP_MATERIAL_OFFSET_XY : i==1? DMU_MIDDLE_MATERIAL_OFFSET_XY : DMU_BOTTOM_MATERIAL_OFFSET_XY), texOff); } } } // Update sky column offsets sky1ColumnOffset += sky1ScrollDelta; sky2ColumnOffset += sky2ScrollDelta; Rend_SkyParams(1, DD_OFFSET, &sky1ColumnOffset); Rend_SkyParams(0, DD_OFFSET, &sky2ColumnOffset); if(mapHasLightning) { if(!nextLightningFlash || lightningFlash) { P_LightningFlash(); } else { nextLightningFlash--; } } #undef PLANE_MATERIAL_SCROLLUNIT } static boolean isLightningSector(sector_t* sec) { xsector_t* xsec = P_ToXSector(sec); if(xsec->special == LIGHTNING_SPECIAL || xsec->special == LIGHTNING_SPECIAL2) return true; if(P_GetIntp(P_GetPtrp(sec, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) return true; if(P_GetIntp(P_GetPtrp(sec, DMU_FLOOR_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) return true; return false; } static void P_LightningFlash(void) { uint i; float* tempLight; boolean foundSec; float flashLight; if(lightningFlash) { lightningFlash--; tempLight = lightningLightLevels; if(lightningFlash) { for(i = 0; i < numsectors; ++i) { sector_t* sec = P_ToPtr(DMU_SECTOR, i); if(isLightningSector(sec)) { float lightLevel = P_GetFloat(DMU_SECTOR, i, DMU_LIGHT_LEVEL); if(*tempLight < lightLevel - (4.f / 255)) P_SetFloat(DMU_SECTOR, i, DMU_LIGHT_LEVEL, lightLevel - (1.f / 255) * 4); tempLight++; } } } else { // Remove the alternate lightning flash special. for(i = 0; i < numsectors; ++i) { sector_t* sec = P_ToPtr(DMU_SECTOR, i); if(isLightningSector(sec)) { P_SetFloatp(sec, DMU_LIGHT_LEVEL, *tempLight); tempLight++; } } Rend_SkyParams(1, DD_DISABLE, NULL); Rend_SkyParams(0, DD_ENABLE, NULL); } return; } lightningFlash = (P_Random() & 7) + 8; flashLight = (float) (200 + (P_Random() & 31)) / 255.0f; tempLight = lightningLightLevels; foundSec = false; for(i = 0; i < numsectors; ++i) { sector_t* sec = P_ToPtr(DMU_SECTOR, i); if(isLightningSector(sec)) { xsector_t* xsec = P_ToXSector(sec); float newLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); *tempLight = newLevel; if(xsec->special == LIGHTNING_SPECIAL) { newLevel += .25f; if(newLevel > flashLight) newLevel = flashLight; } else if(xsec->special == LIGHTNING_SPECIAL2) { newLevel += .125f; if(newLevel > flashLight) newLevel = flashLight; } else { newLevel = flashLight; } if(newLevel < *tempLight) newLevel = *tempLight; P_SetFloatp(sec, DMU_LIGHT_LEVEL, newLevel); tempLight++; foundSec = true; } } if(foundSec) { mobj_t* plrmo = players[DISPLAYPLAYER].plr->mo; mobj_t* crashOrigin = NULL; // Set the alternate (lightning) sky. Rend_SkyParams(0, DD_DISABLE, NULL); Rend_SkyParams(1, DD_ENABLE, NULL); // If 3D sounds are active, position the clap somewhere above // the player. if(cfg.snd3D && plrmo && !IS_NETGAME) { if((crashOrigin = P_SpawnMobj3f(plrmo->pos[VX] + (16 * (M_Random() - 127) << FRACBITS), plrmo->pos[VY] + (16 * (M_Random() - 127) << FRACBITS), plrmo->pos[VZ] + (4000 << FRACBITS), MT_CAMERA, 0, 0))) crashOrigin->tics = 5 * TICSPERSEC; // Five seconds will do. } // Make it loud! S_StartSound(SFX_THUNDER_CRASH | DDSF_NO_ATTENUATION, crashOrigin); } // Calculate the next lighting flash if(!nextLightningFlash) { if(P_Random() < 50) { // Immediate Quick flash nextLightningFlash = (P_Random() & 15) + 16; } else { if(P_Random() < 128 && !(mapTime & 32)) { nextLightningFlash = ((P_Random() & 7) + 2) * TICSPERSEC; } else { nextLightningFlash = ((P_Random() & 15) + 5) * TICSPERSEC; } } } } void P_ForceLightning(void) { nextLightningFlash = 0; } void P_InitLightning(void) { uint i, secCount; if(!P_GetMapLightning(gameMap)) { mapHasLightning = false; lightningFlash = 0; return; } lightningFlash = 0; secCount = 0; for(i = 0; i < numsectors; ++i) { sector_t* sec = P_ToPtr(DMU_SECTOR, i); if(isLightningSector(sec)) { secCount++; } } if(secCount > 0) { mapHasLightning = true; lightningLightLevels = Z_Malloc(secCount * sizeof(float), PU_MAP, NULL); // Don't flash immediately on entering the map. nextLightningFlash = ((P_Random() & 15) + 5) * TICSPERSEC; } else { mapHasLightning = false; } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/in_lude.c0000644000175000017500000002722711357170242022413 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * in_lude.c: */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jhexen.h" #include "d_net.h" #include "hu_stuff.h" #include "hu_menu.h" #include "g_common.h" #include "am_map.h" // MACROS ------------------------------------------------------------------ #define TEXTSPEED (3) #define TEXTWAIT (140) #define TALLY_EFFECT_TICKS (20) #define TALLY_FINAL_X_DELTA (23 * FRACUNIT) #define TALLY_FINAL_Y_DELTA (13 * FRACUNIT) #define TALLY_START_XPOS (178 * FRACUNIT) #define TALLY_STOP_XPOS (90 * FRACUNIT) #define TALLY_START_YPOS (132 * FRACUNIT) #define TALLY_STOP_YPOS (83 * FRACUNIT) #define TALLY_TOP_X (85) #define TALLY_TOP_Y (9) #define TALLY_LEFT_X (7) #define TALLY_LEFT_Y (71) #define TALLY_TOTALS_X (291) #define MAX_INTRMSN_MESSAGE_SIZE (1024) // TYPES ------------------------------------------------------------------- typedef enum gametype_e { SINGLE, COOPERATIVE, DEATHMATCH } gametype_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void IN_WaitStop(void); static void loadPics(void); static void unloadPics(void); static void CheckForSkip(void); static void initStats(void); static void drawDeathTally(void); static void drawNumber(int val, int x, int y, int wrapThresh); static void drawNumberBold(int val, int x, int y, int wrapThresh); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DECLARATIONS ------------------------------------------------ boolean intermission; int interState = 0; int overrideHubMsg = 0; // Override the hub transition message when 1. // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Used for timing of background animation. static int bcnt; static boolean skipIntermission; static int interTime = -1; static gametype_t gameType; static int cnt; static int slaughterBoy; // In DM, the player with the most kills. static signed int totalFrags[MAXPLAYERS]; static int hubCount; static int patchInterpicLumpRS; // A raw screen. static int fontBNumbersLump[10]; static int fontBNegativeLump; static int fontBSlashLump; static int fontBPercentLump; static int fontABaseLump; static int fontBLump; static int fontBLumpBase; // CODE -------------------------------------------------------------------- void WI_initVariables(void /* wbstartstruct_t* wbstartstruct */) { /* wbs = wbstartstruct; #ifdef RANGECHECK if(gameMode != commercial) { if(gameMode == retail) RNGCHECK(wbs->epsd, 0, 3); else RNGCHECK(wbs->epsd, 0, 2); } else { RNGCHECK(wbs->last, 0, 8); RNGCHECK(wbs->next, 0, 8); } RNGCHECK(wbs->pnum, 0, MAXPLAYERS); RNGCHECK(wbs->pnum, 0, MAXPLAYERS); #endif accelerateStage = 0; cnt =*/ bcnt = 0; /* firstRefresh = 1; me = wbs->pNum; myTeam = cfg.playerColor[wbs->pNum]; plrs = wbs->plyr; if(!wbs->maxKills) wbs->maxKills = 1; if(!wbs->maxItems) wbs->maxItems = 1; if(!wbs->maxSecret) wbs->maxSecret = 1; if(gameMode != retail) if(wbs->epsd > 2) wbs->epsd -= 3;*/ intermission = true; interState = 0; skipIntermission = false; interTime = 0; } void IN_Init(void) { assert(deathmatch); WI_initVariables(); loadPics(); initStats(); } void IN_WaitStop(void) { if(!--cnt) { IN_Stop(); G_WorldDone(); } } void IN_Stop(void) { NetSv_Intermission(IMF_END, 0, 0); intermission = false; unloadPics(); } /** * Initializes the stats for single player mode. */ static void initStats(void) { int i, j, slaughterFrags, posNum, slaughterCount, playerCount; gameType = DEATHMATCH; slaughterBoy = 0; slaughterFrags = -9999; posNum = 0; playerCount = 0; slaughterCount = 0; for(i = 0; i < MAXPLAYERS; ++i) { totalFrags[i] = 0; if(players[i].plr->inGame) { playerCount++; for(j = 0; j < MAXPLAYERS; ++j) { if(players[i].plr->inGame) { totalFrags[i] += players[i].frags[j]; } } posNum++; } if(totalFrags[i] > slaughterFrags) { slaughterBoy = 1 << i; slaughterFrags = totalFrags[i]; slaughterCount = 1; } else if(totalFrags[i] == slaughterFrags) { slaughterBoy |= 1 << i; slaughterCount++; } } if(playerCount == slaughterCount) { // don't do the slaughter stuff if everyone is equal slaughterBoy = 0; } } static void loadPics(void) { int i; if(hubCount || gameType == DEATHMATCH) { patchInterpicLumpRS = W_GetNumForName("INTERPIC"); fontBLumpBase = W_GetNumForName("FONTB16"); for(i = 0; i < 10; ++i) { fontBNumbersLump[i] = fontBLumpBase + i; } fontBLump = W_GetNumForName("FONTB_S") + 1; fontBNegativeLump = W_GetNumForName("FONTB13"); fontABaseLump = W_GetNumForName("FONTA_S") + 1; fontBSlashLump = W_GetNumForName("FONTB15"); fontBPercentLump = W_GetNumForName("FONTB05"); } } static void unloadPics(void) { // Nothing to do. } void IN_Ticker(void) { if(!intermission) { return; } if(interState) { IN_WaitStop(); return; } skipIntermission = false; CheckForSkip(); // Counter for general background animation. bcnt++; interTime++; if(skipIntermission || (gameType == SINGLE && !hubCount)) { interState = 1; NetSv_Intermission(IMF_STATE, interState, 0); cnt = 10; skipIntermission = false; } } /** * Check to see if any player hit a key. */ static void CheckForSkip(void) { static boolean triedToSkip; int i; player_t *player; for(i = 0, player = players; i < MAXPLAYERS; ++i, player++) { if(players[i].plr->inGame) { if(player->brain.attack) { if(!player->attackDown) { skipIntermission = 1; } player->attackDown = true; } else { player->attackDown = false; } if(player->brain.use) { if(!player->useDown) { skipIntermission = 1; } player->useDown = true; } else { player->useDown = false; } } } if(deathmatch && interTime < 140) { // Wait for 4 seconds before allowing a skip. if(skipIntermission == 1) { triedToSkip = true; skipIntermission = 0; } } else { if(triedToSkip) { skipIntermission = 1; triedToSkip = false; } } } void IN_Drawer(void) { if(!intermission) return; if(interState) return; GL_DrawRawScreen(patchInterpicLumpRS, 0, 0); if(gameType != SINGLE) { drawDeathTally(); } } static void drawDeathTally(void) { static boolean showTotals; int i, j; fixed_t xPos, yPos; fixed_t xDelta, yDelta; fixed_t xStart, scale; int x, y; boolean bold; int temp; GL_DrawPatch(TALLY_TOP_X, TALLY_TOP_Y, W_GetNumForName("tallytop")); GL_DrawPatch(TALLY_LEFT_X, TALLY_LEFT_Y, W_GetNumForName("tallylft")); if(interTime < TALLY_EFFECT_TICKS) { showTotals = false; scale = (interTime * FRACUNIT) / TALLY_EFFECT_TICKS; xDelta = FixedMul(scale, TALLY_FINAL_X_DELTA); yDelta = FixedMul(scale, TALLY_FINAL_Y_DELTA); xStart = TALLY_START_XPOS - FixedMul(scale, TALLY_START_XPOS - TALLY_STOP_XPOS); yPos = TALLY_START_YPOS - FixedMul(scale, TALLY_START_YPOS - TALLY_STOP_YPOS); } else { xDelta = TALLY_FINAL_X_DELTA; yDelta = TALLY_FINAL_Y_DELTA; xStart = TALLY_STOP_XPOS; yPos = TALLY_STOP_YPOS; } if(interTime >= TALLY_EFFECT_TICKS && showTotals == false) { showTotals = true; S_StartSound(SFX_PLATFORM_STOP, NULL); } y = yPos >> FRACBITS; for(i = 0; i < MAXPLAYERS; ++i) { xPos = xStart; for(j = 0; j < MAXPLAYERS; ++j, xPos += xDelta) { x = xPos >> FRACBITS; bold = (i == CONSOLEPLAYER || j == CONSOLEPLAYER); if(players[i].plr->inGame && players[j].plr->inGame) { if(bold) { drawNumberBold(players[i].frags[j], x, y, 100); } else { drawNumber(players[i].frags[j], x, y, 100); } } else { temp = M_StringWidth("--", GF_FONTA) / 2; if(bold) { M_WriteText2(x - temp, y, "--", GF_FONTA, 1, 0.7f, 0.3f, 1); } else { M_WriteText2(x - temp, y, "--", GF_FONTA, 1, 1, 1, 1); } } } if(showTotals && players[i].plr->inGame && !((slaughterBoy & (1 << i)) && !(interTime & 16))) { drawNumber(totalFrags[i], TALLY_TOTALS_X, y, 1000); } yPos += yDelta; y = yPos >> FRACBITS; } } static void drawNumber(int val, int x, int y, int wrapThresh) { char buff[8] = "XX"; if(!(val < -9 && wrapThresh < 1000)) { sprintf(buff, "%d", val >= wrapThresh ? val % wrapThresh : val); } M_WriteText2(x - M_StringWidth(buff, GF_FONTA) / 2, y, buff, GF_FONTA, 1, 1, 1, 1); } static void drawNumberBold(int val, int x, int y, int wrapThresh) { char buff[8] = "XX"; if(!(val < -9 && wrapThresh < 1000)) { sprintf(buff, "%d", val >= wrapThresh ? val % wrapThresh : val); } M_WriteText2(x - M_StringWidth(buff, GF_FONTA) / 2, y, buff, GF_FONTA, 1, 0.7f, 0.3f, 1); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_telept.c0000644000175000017500000001605611357170242022606 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "dmu_lib.h" #include "p_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void P_ArtiTeleportOther(player_t* plr) { mobj_t* mo; if(!plr || !plr->plr->mo) return; if((mo = P_SpawnPlayerMissile(MT_TELOTHER_FX1, plr->plr->mo))) { mo->target = plr->plr->mo; } } void P_TeleportToPlayerStarts(mobj_t* mo) { const playerstart_t* start; if(!mo) return; // Get a random player start. if((start = P_GetPlayerStart(0, -1, false))) { P_Teleport(mo, start->pos[VX], start->pos[VY], start->angle, true); } } void P_TeleportToDeathmatchStarts(mobj_t* mo) { const playerstart_t* start; if(!mo) return; // First, try a random deathmatch start. if((start = P_GetPlayerStart(0, -1, true))) { P_Teleport(mo, start->pos[VX], start->pos[VY], start->angle, true); } else { P_TeleportToPlayerStarts(mo); } } mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle) { return P_SpawnMobj3f(MT_TFOG, x, y, TELEFOGHEIGHT, angle, MSF_Z_FLOOR); } boolean P_Teleport(mobj_t* mo, float x, float y, angle_t angle, boolean useFog) { float oldpos[3], aboveFloor, fogDelta; player_t* player; unsigned int an; angle_t oldAngle; mobj_t* fog; memcpy(oldpos, mo->pos, sizeof(oldpos)); oldAngle = mo->angle; aboveFloor = mo->pos[VZ] - mo->floorZ; if(!P_TeleportMove(mo, x, y, false)) return false; if(mo->player) { player = mo->player; player->plr->flags |= DDPF_FIXANGLES | DDPF_FIXPOS | DDPF_FIXMOM; if(player->powers[PT_FLIGHT] && aboveFloor > 0) { mo->pos[VZ] = mo->floorZ + aboveFloor; if(mo->pos[VZ] + mo->height > mo->ceilingZ) { mo->pos[VZ] = mo->ceilingZ - mo->height; } player->viewZ = mo->pos[VZ] + player->viewHeight; } else { mo->pos[VZ] = mo->floorZ; player->viewHeight = (float) cfg.plrViewHeight; player->viewHeightDelta = 0; player->viewZ = mo->pos[VZ] + player->viewHeight; if(useFog) { player->plr->lookDir = 0; } } } else if(mo->flags & MF_MISSILE) { mo->pos[VZ] = mo->floorZ + aboveFloor; if(mo->pos[VZ] + mo->height > mo->ceilingZ) { mo->pos[VZ] = mo->ceilingZ - mo->height; } } else { mo->pos[VZ] = mo->floorZ; } // Spawn teleport fog at source and destination if(useFog) { fogDelta = (mo->flags & MF_MISSILE ? 0 : TELEFOGHEIGHT); if((fog = P_SpawnMobj3f(MT_TFOG, oldpos[VX], oldpos[VY], oldpos[VZ] + fogDelta, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPORT, fog); an = angle >> ANGLETOFINESHIFT; if((fog = P_SpawnMobj3f(MT_TFOG, x + 20 * FIX2FLT(finecosine[an]), y + 20 * FIX2FLT(finesine[an]), mo->pos[VZ] + fogDelta, angle + ANG180, 0))) S_StartSound(SFX_TELEPORT, fog); if(mo->player && !mo->player->powers[PT_SPEED]) { // Freeze player for about .5 sec mo->reactionTime = 18; } mo->angle = angle; } if(mo->flags2 & MF2_FLOORCLIP) { mo->floorClip = 0; if(mo->pos[VZ] == P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FLOORCLIP) { mo->floorClip = 10; } } } if(mo->flags & MF_MISSILE) { angle >>= ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[angle]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[angle]); } else if(useFog) // No fog doesn't alter the player's momentums. { mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; } P_MobjClearSRVO(mo); return true; } boolean EV_Teleport(int tid, mobj_t* thing, boolean fog) { int i, count, searcher; mobj_t* mo = 0; if(!thing) return false; if(thing->flags2 & MF2_NOTELEPORT) return false; count = 0; searcher = -1; while(P_FindMobjFromTID(tid, &searcher) != NULL) count++; if(count == 0) return false; count = 1 + (P_Random() % count); searcher = -1; for(i = 0; i < count; ++i) { mo = P_FindMobjFromTID(tid, &searcher); } if(!mo) Con_Error("Can't find teleport mapspot\n"); return P_Teleport(thing, mo->pos[VX], mo->pos[VY], mo->angle, fog); } #if __JHERETIC__ || __JHEXEN__ void P_ArtiTele(player_t* player) { const playerstart_t* start; if((start = P_GetPlayerStart(0, deathmatch? -1 : 0, deathmatch))) { P_Teleport(player->plr->mo, start->pos[VX], start->pos[VY], start->angle, true); #if __JHEXEN__ if(player->morphTics) { // Teleporting away will undo any morph effects (pig) P_UndoPlayerMorph(player); } #else S_StartSound(SFX_WPNUP, NULL); #endif } } #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_lights.c0000644000175000017500000002562111357170242022601 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "dmu_lib.h" #include "p_mapspec.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static float phaseTable[64] = { .5, .4375, .375, .3125, .25, .1875, .125, .125, .0625, .0625, .0625, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, .0625, .0625, .0625, .125, .125, .1875, .25, .3125, .375, .4375, .5 }; // CODE -------------------------------------------------------------------- void T_Light(light_t *light) { if(light->count) { light->count--; return; } switch(light->type) { case LITE_FADE: P_SectorModifyLight(light->sector, light->value2); if(light->tics2 == 1) { if(P_SectorLight(light->sector) >= light->value1) { P_SectorSetLight(light->sector, light->value1); DD_ThinkerRemove(&light->thinker); } } else if(P_SectorLight(light->sector) <= light->value1) { P_SectorSetLight(light->sector, light->value1); DD_ThinkerRemove(&light->thinker); } break; case LITE_GLOW: P_SectorModifyLightx(light->sector, light->tics1); if(light->tics2 == 1) { if(P_SectorLight(light->sector) >= light->value1) { P_SectorSetLight(light->sector, light->value1); light->tics1 = -light->tics1; light->tics2 = -1; // Reverse direction. } } else if(P_SectorLight(light->sector) <= light->value2) { P_SectorSetLight(light->sector, light->value2); light->tics1 = -light->tics1; light->tics2 = 1; // Reverse direction. } break; case LITE_FLICKER: if(P_SectorLight(light->sector) == light->value1) { P_SectorSetLight(light->sector, light->value2); light->count = (P_Random() & 7) + 1; } else { P_SectorSetLight(light->sector, light->value1); light->count = (P_Random() & 31) + 1; } break; case LITE_STROBE: if(P_SectorLight(light->sector) == light->value1) { P_SectorSetLight(light->sector, light->value2); light->count = light->tics2; } else { P_SectorSetLight(light->sector, light->value1); light->count = light->tics1; } break; default: break; } } boolean EV_SpawnLight(linedef_t *line, byte *arg, lighttype_t type) { int arg1, arg2, arg3, arg4; boolean think = false; boolean rtn = false; light_t *light; sector_t *sec = NULL; iterlist_t *list; arg1 = (int) arg[1]; arg2 = (int) arg[2]; arg3 = (int) arg[3]; arg4 = (int) arg[4]; list = P_GetSectorIterListForTag((int) arg[0], false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { think = false; rtn = true; light = Z_Calloc(sizeof(*light), PU_MAP, 0); light->type = type; light->sector = sec; light->count = 0; switch(type) { case LITE_RAISEBYVALUE: P_SectorModifyLight(light->sector, (float) arg1 / 255.0f); break; case LITE_LOWERBYVALUE: P_SectorModifyLight(light->sector, -((float) arg1 / 255.0f)); break; case LITE_CHANGETOVALUE: P_SectorSetLight(light->sector, (float) arg1 / 255.0f); break; case LITE_FADE: think = true; light->value1 = (float) arg1 / 255.0f; // Destination lightlevel. light->value2 = FIX2FLT(FixedDiv((arg1 - (int) (255.0f * P_SectorLight(light->sector))) << FRACBITS, arg2 << FRACBITS)) / 255.0f; // Delta lightlevel. if(P_SectorLight(light->sector) <= (float) arg1 / 255.0f) { light->tics2 = 1; // Get brighter. } else { light->tics2 = -1; } break; case LITE_GLOW: think = true; light->value1 = (float) arg1 / 255.0f; // Upper lightlevel. light->value2 = (float) arg2 / 255.0f; // Lower lightlevel. light->tics1 = FixedDiv((arg1 - (int) (255.0f * P_SectorLight(light->sector))) << FRACBITS, arg3 << FRACBITS); // Lightlevel delta. if(P_SectorLight(light->sector) <= (float) arg1 / 255.0f) { light->tics2 = 1; // Get brighter. } else { light->tics2 = -1; } break; case LITE_FLICKER: think = true; light->value1 = (float) arg1 / 255.0f; // Upper lightlevel. light->value2 = (float) arg2 / 255.0f; // Lower lightlevel. P_SectorSetLight(light->sector, light->value1); light->count = (P_Random() & 64) + 1; break; case LITE_STROBE: think = true; light->value1 = (float) arg1 / 255.0f; // Upper lightlevel. light->value2 = (float) arg2 / 255.0f; // Lower lightlevel. light->tics1 = arg3; // Upper tics. light->tics2 = arg4; // Lower tics. light->count = arg3; P_SectorSetLight(light->sector, light->value1); break; default: rtn = false; break; } if(think) { light->thinker.function = T_Light; DD_ThinkerAdd(&light->thinker); } else { Z_Free(light); } } return rtn; } void T_Phase(phase_t *phase) { phase->index = (phase->index + 1) & 63; P_SectorSetLight(phase->sector, phase->baseValue + phaseTable[phase->index]); } void P_SpawnPhasedLight(sector_t* sector, float base, int index) { phase_t* phase; phase = Z_Calloc(sizeof(*phase), PU_MAP, 0); phase->thinker.function = T_Phase; DD_ThinkerAdd(&phase->thinker); phase->sector = sector; if(index == -1) { // Sector->lightLevel as the index. phase->index = (int) (255.0f * P_SectorLight(sector)) & 63; } else { phase->index = index & 63; } phase->baseValue = base; P_SectorSetLight(phase->sector, phase->baseValue + phaseTable[phase->index]); P_ToXSector(sector)->special = 0; } typedef struct { int seqSpecial, count; sector_t* sec, *nextSec; } findlightsequencesectorparams_t; static int findLightSequenceSector(void* p, void* context) { linedef_t* li = (linedef_t*) p; findlightsequencesectorparams_t* params = (findlightsequencesectorparams_t*) context; sector_t* tempSec = P_GetNextSector(li, params->sec); if(tempSec) { if(P_ToXSector(tempSec)->special == params->seqSpecial) { if(params->seqSpecial == LIGHT_SEQUENCE) params->seqSpecial = LIGHT_SEQUENCE_ALT; else params->seqSpecial = LIGHT_SEQUENCE; params->nextSec = tempSec; params->count++; } } return 1; // Continue iteration. } typedef struct { sector_t* sec, *nextSec; } findlightsequencestartsectorparams_t; static int findLightSequenceStartSector(void* p, void* context) { linedef_t* li = (linedef_t*) p; findlightsequencestartsectorparams_t* params = (findlightsequencestartsectorparams_t*) context; sector_t* tempSec = P_GetNextSector(li, params->sec); if(tempSec) { if(P_ToXSector(tempSec)->special == LIGHT_SEQUENCE_START) { params->nextSec = tempSec; } } return 1; // Continue iteration. } void P_SpawnLightSequence(sector_t* sector, int indexStep) { int count; { findlightsequencesectorparams_t params; params.seqSpecial = LIGHT_SEQUENCE; // Look for Light_Sequence, first. params.count = 1; params.sec = sector; do { // Make sure that the search doesn't back up. P_ToXSector(params.sec)->special = LIGHT_SEQUENCE_START; params.nextSec = NULL; P_Iteratep(params.sec, DMU_LINEDEF, ¶ms, findLightSequenceSector); params.sec = params.nextSec; } while(params.sec); count = params.count; } { findlightsequencestartsectorparams_t params; float base; fixed_t index, indexDelta; params.sec = sector; count *= indexStep; index = 0; indexDelta = FixedDiv(64 * FRACUNIT, count * FRACUNIT); base = P_SectorLight(sector); do { if(P_SectorLight(params.sec)) { base = P_SectorLight(params.sec); } P_SpawnPhasedLight(params.sec, base, index >> FRACBITS); index += indexDelta; params.nextSec = NULL; P_Iteratep(params.sec, DMU_LINEDEF, ¶ms, findLightSequenceStartSector); params.sec = params.nextSec; } while(params.sec); } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/acfnlink.c0000644000175000017500000003207211357170242022553 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * acfnlink.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- actionlink_t actionlinks[] = { {"A_AddPlayerCorpse", A_AddPlayerCorpse}, {"A_BatMove", A_BatMove}, {"A_BatSpawn", A_BatSpawn}, {"A_BatSpawnInit", A_BatSpawnInit}, {"A_BellReset1", A_BellReset1}, {"A_BellReset2", A_BellReset2}, {"A_BishopAttack", A_BishopAttack}, {"A_BishopAttack2", A_BishopAttack2}, {"A_BishopChase", A_BishopChase}, {"A_BishopDecide", A_BishopDecide}, {"A_BishopDoBlur", A_BishopDoBlur}, {"A_BishopMissileSeek", A_BishopMissileSeek}, {"A_BishopMissileWeave", A_BishopMissileWeave}, {"A_BishopPainBlur", A_BishopPainBlur}, {"A_BishopPuff", A_BishopPuff}, {"A_BishopSpawnBlur", A_BishopSpawnBlur}, {"A_BounceCheck", A_BounceCheck}, {"A_BridgeInit", A_BridgeInit}, {"A_BridgeOrbit", A_BridgeOrbit}, {"A_CentaurAttack", A_CentaurAttack}, {"A_CentaurAttack2", A_CentaurAttack2}, {"A_CentaurDefend", A_CentaurDefend}, {"A_CentaurDropStuff", A_CentaurDropStuff}, {"A_CFlameAttack", A_CFlameAttack}, {"A_CFlameMissile", A_CFlameMissile}, {"A_CFlamePuff", A_CFlamePuff}, {"A_CFlameRotate", A_CFlameRotate}, {"A_Chase", A_Chase}, {"A_CheckBurnGone", A_CheckBurnGone}, {"A_CheckFloor", A_CheckFloor}, {"A_CheckSkullDone", A_CheckSkullDone}, {"A_CheckSkullFloor", A_CheckSkullFloor}, {"A_CheckTeleRing", A_CheckTeleRing}, {"A_CheckThrowBomb", A_CheckThrowBomb}, {"A_CHolyAttack", A_CHolyAttack}, {"A_CHolyAttack2", A_CHolyAttack2}, {"A_CHolyCheckScream", A_CHolyCheckScream}, {"A_CHolyPalette", A_CHolyPalette}, {"A_CHolySeek", A_CHolySeek}, {"A_CHolySpawnPuff", A_CHolySpawnPuff}, {"A_CHolyTail", A_CHolyTail}, {"A_ClassBossHealth", A_ClassBossHealth}, {"A_ClericAttack", A_ClericAttack}, {"A_CMaceAttack", A_CMaceAttack}, {"A_ContMobjSound", A_ContMobjSound}, {"A_CorpseBloodDrip", A_CorpseBloodDrip}, {"A_CorpseExplode", A_CorpseExplode}, {"A_CStaffAttack", A_CStaffAttack}, {"A_CStaffCheck", A_CStaffCheck}, {"A_CStaffCheckBlink", A_CStaffCheckBlink}, {"A_CStaffInitBlink", A_CStaffInitBlink}, {"A_CStaffMissileSlither", A_CStaffMissileSlither}, {"A_DelayGib", A_DelayGib}, {"A_Demon2Death", A_Demon2Death}, {"A_DemonAttack1", A_DemonAttack1}, {"A_DemonAttack2", A_DemonAttack2}, {"A_DemonDeath", A_DemonDeath}, {"A_DragonAttack", A_DragonAttack}, {"A_DragonCheckCrash", A_DragonCheckCrash}, {"A_DragonFlap", A_DragonFlap}, {"A_DragonFlight", A_DragonFlight}, {"A_DragonFX2", A_DragonFX2}, {"A_DragonInitFlight", A_DragonInitFlight}, {"A_DragonPain", A_DragonPain}, {"A_DropMace", A_DropMace}, {"A_ESound", A_ESound}, {"A_EttinAttack", A_EttinAttack}, {"A_Explode", A_Explode}, {"A_FaceTarget", A_FaceTarget}, {"A_FastChase", A_FastChase}, {"A_FAxeAttack", A_FAxeAttack}, {"A_FHammerAttack", A_FHammerAttack}, {"A_FHammerThrow", A_FHammerThrow}, {"A_FighterAttack", A_FighterAttack}, {"A_FireConePL1", A_FireConePL1}, {"A_FiredAttack", A_FiredAttack}, {"A_FiredChase", A_FiredChase}, {"A_FiredRocks", A_FiredRocks}, {"A_FiredSplotch", A_FiredSplotch}, {"A_FlameCheck", A_FlameCheck}, {"A_FloatGib", A_FloatGib}, {"A_FogMove", A_FogMove}, {"A_FogSpawn", A_FogSpawn}, {"A_FPunchAttack", A_FPunchAttack}, {"A_FreeTargMobj", A_FreeTargMobj}, {"A_FreezeDeath", A_FreezeDeath}, {"A_FreezeDeathChunks", A_FreezeDeathChunks}, {"A_FSwordAttack", A_FSwordAttack}, {"A_FSwordFlames", A_FSwordFlames}, {"A_HideThing", A_HideThing}, {"A_IceCheckHeadDone", A_IceCheckHeadDone}, {"A_IceGuyAttack", A_IceGuyAttack}, {"A_IceGuyChase", A_IceGuyChase}, {"A_IceGuyDie", A_IceGuyDie}, {"A_IceGuyLook", A_IceGuyLook}, {"A_IceGuyMissileExplode", A_IceGuyMissileExplode}, {"A_IceGuyMissilePuff", A_IceGuyMissilePuff}, {"A_IceSetTics", A_IceSetTics}, {"A_KBolt", A_KBolt}, {"A_KBoltRaise", A_KBoltRaise}, {"A_KoraxBonePop", A_KoraxBonePop}, {"A_KoraxChase", A_KoraxChase}, {"A_KoraxCommand", A_KoraxCommand}, {"A_KoraxDecide", A_KoraxDecide}, {"A_KoraxMissile", A_KoraxMissile}, {"A_KoraxStep", A_KoraxStep}, {"A_KoraxStep2", A_KoraxStep2}, {"A_KSpiritRoam", A_KSpiritRoam}, {"A_LastZap", A_LastZap}, {"A_LeafCheck", A_LeafCheck}, {"A_LeafSpawn", A_LeafSpawn}, {"A_LeafThrust", A_LeafThrust}, {"A_Light0", A_Light0}, {"A_LightningClip", A_LightningClip}, {"A_LightningReady", A_LightningReady}, {"A_LightningRemove", A_LightningRemove}, {"A_LightningZap", A_LightningZap}, {"A_Look", A_Look}, {"A_Lower", A_Lower}, {"A_MageAttack", A_MageAttack}, {"A_MinotaurAtk1", A_MinotaurAtk1}, {"A_MinotaurAtk2", A_MinotaurAtk2}, {"A_MinotaurAtk3", A_MinotaurAtk3}, {"A_MinotaurCharge", A_MinotaurCharge}, {"A_MinotaurChase", A_MinotaurChase}, {"A_MinotaurDecide", A_MinotaurDecide}, {"A_MinotaurFade0", A_MinotaurFade0}, {"A_MinotaurFade1", A_MinotaurFade1}, {"A_MinotaurFade2", A_MinotaurFade2}, {"A_MinotaurLook", A_MinotaurLook}, {"A_MinotaurRoam", A_MinotaurRoam}, {"A_MLightningAttack", A_MLightningAttack}, {"A_MntrFloorFire", A_MntrFloorFire}, {"A_MStaffAttack", A_MStaffAttack}, {"A_MStaffPalette", A_MStaffPalette}, {"A_MStaffTrack", A_MStaffTrack}, {"A_MStaffWeave", A_MStaffWeave}, {"A_MWandAttack", A_MWandAttack}, {"A_NoBlocking", A_NoBlocking}, {"A_NoGravity", A_NoGravity}, {"A_Pain", A_Pain}, {"A_PigAttack", A_PigAttack}, {"A_PigChase", A_PigChase}, {"A_PigLook", A_PigLook}, {"A_PigPain", A_PigPain}, {"A_PoisonBagCheck", A_PoisonBagCheck}, {"A_PoisonBagDamage", A_PoisonBagDamage}, {"A_PoisonBagInit", A_PoisonBagInit}, {"A_PoisonShroom", A_PoisonShroom}, {"A_PotteryCheck", A_PotteryCheck}, {"A_PotteryChooseBit", A_PotteryChooseBit}, {"A_PotteryExplode", A_PotteryExplode}, {"A_Quake", A_Quake}, {"A_QueueCorpse", A_QueueCorpse}, {"A_Raise", A_Raise}, {"A_ReFire", A_ReFire}, {"A_RestoreArtifact", A_RestoreArtifact}, {"A_RestoreSpecialThing1", A_RestoreSpecialThing1}, {"A_RestoreSpecialThing2", A_RestoreSpecialThing2}, {"A_Scream", A_Scream}, {"A_SerpentBirthScream", A_SerpentBirthScream}, {"A_SerpentChase", A_SerpentChase}, {"A_SerpentCheckForAttack", A_SerpentCheckForAttack}, {"A_SerpentChooseAttack", A_SerpentChooseAttack}, {"A_SerpentDiveSound", A_SerpentDiveSound}, {"A_SerpentHeadCheck", A_SerpentHeadCheck}, {"A_SerpentHeadPop", A_SerpentHeadPop}, {"A_SerpentHide", A_SerpentHide}, {"A_SerpentHumpDecide", A_SerpentHumpDecide}, {"A_SerpentLowerHump", A_SerpentLowerHump}, {"A_SerpentMeleeAttack", A_SerpentMeleeAttack}, {"A_SerpentMissileAttack", A_SerpentMissileAttack}, {"A_SerpentRaiseHump", A_SerpentRaiseHump}, {"A_SerpentSpawnGibs", A_SerpentSpawnGibs}, {"A_SerpentUnHide", A_SerpentUnHide}, {"A_SerpentWalk", A_SerpentWalk}, {"A_SetAltShadow", A_SetAltShadow}, {"A_SetReflective", A_SetReflective}, {"A_SetShootable", A_SetShootable}, {"A_ShedShard", A_ShedShard}, {"A_SinkGib", A_SinkGib}, {"A_SkullPop", A_SkullPop}, {"A_SmBounce", A_SmBounce}, {"A_SmokePuffExit", A_SmokePuffExit}, {"A_SnoutAttack", A_SnoutAttack}, {"A_SoAExplode", A_SoAExplode}, {"A_SorcBallOrbit", A_SorcBallOrbit}, {"A_SorcBallPop", A_SorcBallPop}, {"A_SorcBossAttack", A_SorcBossAttack}, {"A_SorcererBishopEntry", A_SorcererBishopEntry}, {"A_SorcFX1Seek", A_SorcFX1Seek}, {"A_SorcFX2Orbit", A_SorcFX2Orbit}, {"A_SorcFX2Split", A_SorcFX2Split}, {"A_SorcFX4Check", A_SorcFX4Check}, {"A_SorcSpinBalls", A_SorcSpinBalls}, {"A_SpawnBishop", A_SpawnBishop}, {"A_SpawnFizzle", A_SpawnFizzle}, {"A_SpeedBalls", A_SpeedBalls}, {"A_SpeedFade", A_SpeedFade}, {"A_Summon", A_Summon}, {"A_TeloSpawnA", A_TeloSpawnA}, {"A_TeloSpawnB", A_TeloSpawnB}, {"A_TeloSpawnC", A_TeloSpawnC}, {"A_TeloSpawnD", A_TeloSpawnD}, {"A_ThrustBlock", A_ThrustBlock}, {"A_ThrustImpale", A_ThrustImpale}, {"A_ThrustInitDn", A_ThrustInitDn}, {"A_ThrustInitUp", A_ThrustInitUp}, {"A_ThrustLower", A_ThrustLower}, {"A_ThrustRaise", A_ThrustRaise}, {"A_TreeDeath", A_TreeDeath}, {"A_UnHideThing", A_UnHideThing}, {"A_UnSetInvulnerable", A_UnSetInvulnerable}, {"A_UnSetReflective", A_UnSetReflective}, {"A_UnSetShootable", A_UnSetShootable}, {"A_WeaponReady", A_WeaponReady}, {"A_WraithChase", A_WraithChase}, {"A_WraithFX2", A_WraithFX2}, {"A_WraithFX3", A_WraithFX3}, {"A_WraithInit", A_WraithInit}, {"A_WraithLook", A_WraithLook}, {"A_WraithMelee", A_WraithMelee}, {"A_WraithMissile", A_WraithMissile}, {"A_WraithRaise", A_WraithRaise}, {"A_WraithRaiseInit", A_WraithRaiseInit}, {"A_ZapMimic", A_ZapMimic}, // Inventory: {"A_Invulnerability", A_Invulnerability}, {"A_Health", A_Health}, {"A_SuperHealth", A_SuperHealth}, {"A_HealRadius", A_HealRadius}, {"A_SummonTarget", A_SummonTarget}, {"A_Torch", A_Torch}, {"A_Egg", A_Egg}, {"A_Wings", A_Wings}, {"A_BlastRadius", A_BlastRadius}, {"A_PoisonBag", A_PoisonBag}, {"A_TeleportOther", A_TeleportOther}, {"A_Speed", A_Speed}, {"A_BoostMana", A_BoostMana}, {"A_BoostArmor", A_BoostArmor}, {"A_Teleport", A_Teleport}, {"A_PuzzSkull", A_PuzzSkull}, {"A_PuzzGemBig", A_PuzzGemBig}, {"A_PuzzGemRed", A_PuzzGemRed}, {"A_PuzzGemGreen1", A_PuzzGemGreen1}, {"A_PuzzGemGreen2", A_PuzzGemGreen2}, {"A_PuzzGemBlue1", A_PuzzGemBlue1}, {"A_PuzzGemBlue2", A_PuzzGemBlue2}, {"A_PuzzBook1", A_PuzzBook1}, {"A_PuzzBook2", A_PuzzBook2}, {"A_PuzzSkull2", A_PuzzSkull2}, {"A_PuzzFWeapon", A_PuzzFWeapon}, {"A_PuzzCWeapon", A_PuzzCWeapon}, {"A_PuzzMWeapon", A_PuzzMWeapon}, {"A_PuzzGear1", A_PuzzGear1}, {"A_PuzzGear2", A_PuzzGear2}, {"A_PuzzGear3", A_PuzzGear3}, {"A_PuzzGear4", A_PuzzGear4}, {0, 0} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/sn_sonix.c0000644000175000017500000003370011357170242022625 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sn_sonix.c: */ // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "g_common.h" // MACROS ------------------------------------------------------------------ #define SS_MAX_SCRIPTS 64 #define SS_TEMPBUFFER_SIZE 1024 #define SS_SEQUENCE_NAME_LENGTH 32 #define SS_SCRIPT_NAME "SNDSEQ" #define SS_STRING_PLAY "play" #define SS_STRING_PLAYUNTILDONE "playuntildone" #define SS_STRING_PLAYTIME "playtime" #define SS_STRING_PLAYREPEAT "playrepeat" #define SS_STRING_DELAY "delay" #define SS_STRING_DELAYRAND "delayrand" #define SS_STRING_VOLUME "volume" #define SS_STRING_END "end" #define SS_STRING_STOPSOUND "stopsound" // TYPES ------------------------------------------------------------------- typedef enum sscmds_e { SS_CMD_NONE, SS_CMD_PLAY, SS_CMD_WAITUNTILDONE, // used by PLAYUNTILDONE SS_CMD_PLAYTIME, SS_CMD_PLAYREPEAT, SS_CMD_DELAY, SS_CMD_DELAYRAND, SS_CMD_VOLUME, SS_CMD_STOPSOUND, SS_CMD_END } sscmds_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void VerifySequencePtr(int* base, int* ptr); static int GetSoundOffset(char* name); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int ActiveSequences; seqnode_t* SequenceListHead; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static struct sstranslation_s { char name[SS_SEQUENCE_NAME_LENGTH]; int scriptNum; int stopSound; } SequenceTranslate[SEQ_NUMSEQ] = { { "Platform", 0, 0 }, { "Platform", 0, 0 }, { "PlatformMetal", 0, 0 }, { "Platform", 0, 0 }, { "Silence", 0, 0 }, { "Lava", 0, 0 }, { "Water", 0, 0 }, { "Ice", 0, 0 }, { "Earth", 0, 0 }, { "PlatformMetal2", 0, 0 }, { "DoorNormal", 0, 0 }, { "DoorHeavy", 0, 0 }, { "DoorMetal", 0, 0 }, { "DoorCreak", 0, 0 }, { "Silence", 0, 0 }, { "Lava", 0, 0 }, { "Water", 0, 0 }, { "Ice", 0, 0 }, { "Earth", 0, 0 }, { "DoorMetal2", 0, 0 }, { "Wind", 0, 0 } }; static int* SequenceData[SS_MAX_SCRIPTS]; // CODE -------------------------------------------------------------------- /** * Verifies the integrity of the temporary ptr, and ensures that the ptr * isn't exceeding the size of the temporary buffer */ static void VerifySequencePtr(int* base, int* ptr) { if(ptr - base > SS_TEMPBUFFER_SIZE) { Con_Error("VerifySequencePtr: tempPtr >= %d\n", SS_TEMPBUFFER_SIZE); } } static int GetSoundOffset(char* name) { int i = Def_Get(DD_DEF_SOUND_BY_NAME, name, 0); if(!i) SC_ScriptError("GetSoundOffset: Unknown sound name\n"); return i; } void SN_InitSequenceScript(void) { int i, j, inSequence; int* tempDataStart = 0; int* tempDataPtr = 0; inSequence = -1; ActiveSequences = 0; for(i = 0; i < SS_MAX_SCRIPTS; ++i) { SequenceData[i] = NULL; } SC_Open(SS_SCRIPT_NAME); while(SC_GetString()) { if(*sc_String == ':') { if(inSequence != -1) { SC_ScriptError("SN_InitSequenceScript: Nested Script Error"); } tempDataStart = Z_Malloc(SS_TEMPBUFFER_SIZE, PU_STATIC, NULL); memset(tempDataStart, 0, SS_TEMPBUFFER_SIZE); tempDataPtr = tempDataStart; for(i = 0; i < SS_MAX_SCRIPTS; ++i) { if(SequenceData[i] == NULL) { break; } } if(i == SS_MAX_SCRIPTS) { Con_Error("Number of SS Scripts >= SS_MAX_SCRIPTS"); } for(j = 0; j < SEQ_NUMSEQ; ++j) { if(!strcasecmp(SequenceTranslate[j].name, sc_String + 1)) { SequenceTranslate[j].scriptNum = i; inSequence = j; break; } } continue; // parse the next command } if(inSequence == -1) { continue; } if(SC_Compare(SS_STRING_PLAYUNTILDONE)) { VerifySequencePtr(tempDataStart, tempDataPtr); SC_MustGetString(); *tempDataPtr++ = SS_CMD_PLAY; *tempDataPtr++ = GetSoundOffset(sc_String); *tempDataPtr++ = SS_CMD_WAITUNTILDONE; } else if(SC_Compare(SS_STRING_PLAY)) { VerifySequencePtr(tempDataStart, tempDataPtr); SC_MustGetString(); *tempDataPtr++ = SS_CMD_PLAY; *tempDataPtr++ = GetSoundOffset(sc_String); } else if(SC_Compare(SS_STRING_PLAYTIME)) { VerifySequencePtr(tempDataStart, tempDataPtr); SC_MustGetString(); *tempDataPtr++ = SS_CMD_PLAY; *tempDataPtr++ = GetSoundOffset(sc_String); SC_MustGetNumber(); *tempDataPtr++ = SS_CMD_DELAY; *tempDataPtr++ = sc_Number; } else if(SC_Compare(SS_STRING_PLAYREPEAT)) { VerifySequencePtr(tempDataStart, tempDataPtr); SC_MustGetString(); *tempDataPtr++ = SS_CMD_PLAYREPEAT; *tempDataPtr++ = GetSoundOffset(sc_String); } else if(SC_Compare(SS_STRING_DELAY)) { VerifySequencePtr(tempDataStart, tempDataPtr); *tempDataPtr++ = SS_CMD_DELAY; SC_MustGetNumber(); *tempDataPtr++ = sc_Number; } else if(SC_Compare(SS_STRING_DELAYRAND)) { VerifySequencePtr(tempDataStart, tempDataPtr); *tempDataPtr++ = SS_CMD_DELAYRAND; SC_MustGetNumber(); *tempDataPtr++ = sc_Number; SC_MustGetNumber(); *tempDataPtr++ = sc_Number; } else if(SC_Compare(SS_STRING_VOLUME)) { VerifySequencePtr(tempDataStart, tempDataPtr); *tempDataPtr++ = SS_CMD_VOLUME; SC_MustGetNumber(); *tempDataPtr++ = sc_Number; } else if(SC_Compare(SS_STRING_END)) { int dataSize; *tempDataPtr++ = SS_CMD_END; dataSize = (tempDataPtr - tempDataStart) * sizeof(int); SequenceData[i] = Z_Malloc(dataSize, PU_STATIC, NULL); memcpy(SequenceData[i], tempDataStart, dataSize); Z_Free(tempDataStart); inSequence = -1; } else if(SC_Compare(SS_STRING_STOPSOUND)) { SC_MustGetString(); SequenceTranslate[inSequence].stopSound = GetSoundOffset(sc_String); *tempDataPtr++ = SS_CMD_STOPSOUND; } else { SC_ScriptError("SN_InitSequenceScript: Unknown commmand.\n"); } } } void SN_StartSequence(mobj_t* mobj, int sequence) { seqnode_t* node; SN_StopSequence(mobj); // Stop any previous sequence node = Z_Malloc(sizeof(seqnode_t), PU_STATIC, NULL); node->sequencePtr = SequenceData[SequenceTranslate[sequence].scriptNum]; node->sequence = sequence; node->mobj = mobj; node->delayTics = 0; node->stopSound = SequenceTranslate[sequence].stopSound; node->volume = 127; // Start at max volume if(!SequenceListHead) { SequenceListHead = node; node->next = node->prev = NULL; } else { SequenceListHead->prev = node; node->next = SequenceListHead; node->prev = NULL; SequenceListHead = node; } ActiveSequences++; } void SN_StartSequenceInSec(sector_t* sector, int seqBase) { SN_StartSequence(P_GetPtrp(sector, DMU_SOUND_ORIGIN), seqBase + P_ToXSector(sector)->seqType); } void SN_StopSequenceInSec(sector_t* sector) { SN_StopSequence(P_GetPtrp(sector, DMU_SOUND_ORIGIN)); } void SN_StartSequenceName(mobj_t* mobj, const char* name) { int i; for(i = 0; i < SEQ_NUMSEQ; ++i) { if(!strcmp(name, SequenceTranslate[i].name)) { SN_StartSequence(mobj, i); return; } } } void SN_StopSequence(mobj_t* mobj) { seqnode_t* node; for(node = SequenceListHead; node; node = node->next) { if(node->mobj == mobj) { S_StopSound(0, mobj); if(node->stopSound) { S_StartSoundAtVolume(node->stopSound, mobj, node->volume / 127.0f); } if(SequenceListHead == node) { SequenceListHead = node->next; } if(node->prev) { node->prev->next = node->next; } if(node->next) { node->next->prev = node->prev; } Z_Free(node); ActiveSequences--; } } } void SN_UpdateActiveSequences(void) { seqnode_t* node; boolean sndPlaying; if(!ActiveSequences || paused) { // No sequences currently playing/game is paused return; } for(node = SequenceListHead; node; node = node->next) { if(node->delayTics) { node->delayTics--; continue; } // If ID is zero, S_IsPlaying returns true if any sound is playing. sndPlaying = node->currentSoundID ? S_IsPlaying(node->currentSoundID, node->mobj) : false; switch(*node->sequencePtr) { case SS_CMD_PLAY: #if 0 Con_Message("play: %s: %p\n", SequenceTranslate[node->sequence].name, node->mobj); #endif if(!sndPlaying) { node->currentSoundID = *(node->sequencePtr + 1); #if 0 Con_Message("PLAY: %s: %p\n", SequenceTranslate[node->sequence].name, node->mobj); #endif S_StartSoundAtVolume(node->currentSoundID, node->mobj, node->volume / 127.0f); } node->sequencePtr += 2; break; case SS_CMD_WAITUNTILDONE: if(!sndPlaying) { node->sequencePtr++; node->currentSoundID = 0; } break; case SS_CMD_PLAYREPEAT: #if 0 Con_Message("rept: %s: %p\n", SequenceTranslate[node->sequence].name, node->mobj); #endif if(!sndPlaying) { #if 0 Con_Printf("REPT: id=%i, %s: %p\n", node->currentSoundID, SequenceTranslate[node->sequence].name, node->mobj); #endif node->currentSoundID = *(node->sequencePtr + 1); S_StartSoundAtVolume(node->currentSoundID | DDSF_REPEAT, node->mobj, node->volume / 127.0f); } break; case SS_CMD_DELAY: node->delayTics = *(node->sequencePtr + 1); node->sequencePtr += 2; node->currentSoundID = 0; break; case SS_CMD_DELAYRAND: node->delayTics = *(node->sequencePtr + 1) + M_Random() % (*(node->sequencePtr + 2) - *(node->sequencePtr + 1)); node->sequencePtr += 2; node->currentSoundID = 0; break; case SS_CMD_VOLUME: node->volume = (127 * (*(node->sequencePtr + 1))) / 100; node->sequencePtr += 2; break; case SS_CMD_STOPSOUND: // Wait until something else stops the sequence break; case SS_CMD_END: SN_StopSequence(node->mobj); break; default: break; } } } void SN_StopAllSequences(void) { seqnode_t* node; for(node = SequenceListHead; node; node = node->next) { node->stopSound = 0; // don't play any stop sounds SN_StopSequence(node->mobj); } } int SN_GetSequenceOffset(int sequence, int *sequencePtr) { return (sequencePtr - SequenceData[SequenceTranslate[sequence].scriptNum]); } /** * NOTE: nodeNum zero is the first node */ void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume, int currentSoundID) { int i; seqnode_t* node; i = 0; node = SequenceListHead; while(node && i < nodeNum) { node = node->next; i++; } if(!node) { // reach the end of the list before finding the nodeNum-th node return; } node->delayTics = delayTics; node->volume = volume; node->sequencePtr += seqOffset; node->currentSoundID = currentSoundID; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/hconsole.c0000644000175000017500000002360511357170242022602 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * hconsole.c: Console stuff - jHexen specific. */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "d_net.h" #include "hu_stuff.h" #include "f_infine.h" #include "g_common.h" #include "g_controls.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- DEFCC(CCmdCheat); DEFCC(CCmdCheatGod); DEFCC(CCmdCheatNoClip); DEFCC(CCmdCheatGive); DEFCC(CCmdCheatWarp); DEFCC(CCmdCheatPig); DEFCC(CCmdCheatMassacre); DEFCC(CCmdCheatShadowcaster); DEFCC(CCmdCheatWhere); DEFCC(CCmdCheatRunScript); DEFCC(CCmdCheatReveal); DEFCC(CCmdCheatSuicide); DEFCC(CCmdMakeLocal); DEFCC(CCmdSetCamera); DEFCC(CCmdSetViewLock); DEFCC(CCmdSetViewMode); DEFCC(CCmdCycleSpy); DEFCC(CCmdSetDemoMode); DEFCC(CCmdSpawnMobj); DEFCC(CCmdPrintPlayerCoords); DEFCC(CCmdScriptInfo); DEFCC(CCmdTest); DEFCC(CCmdMovePlane); void G_UpdateEyeHeight(cvar_t* unused); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- DEFCC(CCmdScreenShot); DEFCC(CCmdViewSize); DEFCC(CCmdHexenFont); DEFCC(CCmdConBackground); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- material_t* consoleBG = NULL; float consoleZoom = 1; // Console variables. cvar_t gameCVars[] = { // Console {"con-zoom", 0, CVT_FLOAT, &consoleZoom, 0.1f, 100.0f}, // View/Refresh {"view-size", CVF_PROTECTED, CVT_INT, &cfg.screenBlocks, 3, 13}, {"hud-title", 0, CVT_BYTE, &cfg.mapTitle, 0, 1}, {"hud-title-author-noiwad", 0, CVT_BYTE, &cfg.hideIWADAuthor, 0, 1}, {"view-bob-height", 0, CVT_FLOAT, &cfg.bobView, 0, 1}, {"view-bob-weapon", 0, CVT_FLOAT, &cfg.bobWeapon, 0, 1}, {"view-filter-strength", 0, CVT_FLOAT, &cfg.filterStrength, 0, 1}, // Server-side options // Game state {"server-game-skill", 0, CVT_BYTE, &cfg.netSkill, 0, 4}, {"server-game-map", CVF_NO_MAX, CVT_BYTE, &cfg.netMap, 0, 0}, {"server-game-deathmatch", 0, CVT_BYTE, &cfg.netDeathmatch, 0, 1}, /* jHexen only has one deathmatch mode */ // Modifiers {"server-game-mod-damage", 0, CVT_BYTE, &cfg.netMobDamageModifier, 1, 100}, {"server-game-mod-health", 0, CVT_BYTE, &cfg.netMobHealthModifier, 1, 20}, {"server-game-mod-gravity", 0, CVT_INT, &cfg.netGravity, -1, 100}, // Gameplay options {"server-game-jump", 0, CVT_BYTE, &cfg.netJumping, 0, 1}, {"server-game-nomonsters", 0, CVT_BYTE, &cfg.netNoMonsters, 0, 1}, {"server-game-randclass", 0, CVT_BYTE, &cfg.netRandomClass, 0, 1}, {"server-game-radiusattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZRadiusAttack, 0, 1}, {"server-game-monster-meleeattack-nomaxz", 0, CVT_BYTE, &cfg.netNoMaxZMonsterMeleeAttack, 0, 1}, // Misc {"msg-hub-override", 0, CVT_BYTE, &cfg.overrideHubMsg, 0, 2}, // Player // Player data {"player-color", 0, CVT_BYTE, &cfg.netColor, 0, 8}, {"player-eyeheight", 0, CVT_INT, &cfg.plrViewHeight, 41, 54, G_UpdateEyeHeight}, {"player-class", 0, CVT_BYTE, &cfg.netClass, 0, 2}, // Movment {"player-move-speed", 0, CVT_FLOAT, &cfg.playerMoveSpeed, 0, 1}, {"player-jump", 0, CVT_INT, &cfg.jumpEnabled, 0, 1}, {"player-jump-power", 0, CVT_FLOAT, &cfg.jumpPower, 0, 100}, {"player-air-movement", 0, CVT_BYTE, &cfg.airborneMovement, 0, 32}, // Weapon switch preferences {"player-autoswitch", 0, CVT_BYTE, &cfg.weaponAutoSwitch, 0, 2}, {"player-autoswitch-ammo", 0, CVT_BYTE, &cfg.ammoAutoSwitch, 0, 2}, {"player-autoswitch-notfiring", 0, CVT_BYTE, &cfg.noWeaponAutoSwitchIfFiring, 0, 1}, // Weapon Order preferences {"player-weapon-order0", 0, CVT_INT, &cfg.weaponOrder[0], 0, NUM_WEAPON_TYPES}, {"player-weapon-order1", 0, CVT_INT, &cfg.weaponOrder[1], 0, NUM_WEAPON_TYPES}, {"player-weapon-order2", 0, CVT_INT, &cfg.weaponOrder[2], 0, NUM_WEAPON_TYPES}, {"player-weapon-order3", 0, CVT_INT, &cfg.weaponOrder[3], 0, NUM_WEAPON_TYPES}, {"player-weapon-nextmode", 0, CVT_BYTE, &cfg.weaponNextMode, 0, 1}, // Misc {"player-camera-noclip", 0, CVT_INT, &cfg.cameraNoClip, 0, 1}, // Compatibility options {"game-icecorpse", 0, CVT_INT, &cfg.translucentIceCorpse, 0, 1}, // Game state {"game-fastmonsters", 0, CVT_BYTE, &cfg.fastMonsters, 0, 1}, // Gameplay {"game-maulator-time", CVF_NO_MAX, CVT_INT, &maulatorSeconds, 1, 0}, // Misc {"msg-echo", 0, CVT_BYTE, &cfg.echoMsg, 0, 1}, {NULL} }; // Console commands ccmd_t gameCCmds[] = { {"spy", "", CCmdCycleSpy}, {"screenshot", "", CCmdScreenShot}, {"viewsize", "s", CCmdViewSize}, // $cheats {"cheat", "s", CCmdCheat}, {"god", NULL, CCmdCheatGod}, {"noclip", NULL, CCmdCheatNoClip}, {"warp", "i", CCmdCheatWarp}, {"reveal", "i", CCmdCheatReveal}, {"give", NULL, CCmdCheatGive}, {"kill", "", CCmdCheatMassacre}, {"suicide", NULL, CCmdCheatSuicide}, {"where", "", CCmdCheatWhere}, {"hexenfont", "", CCmdHexenFont}, {"conbg", "s", CCmdConBackground}, // $infine {"startinf", "s", CCmdStartInFine}, {"stopinf", "", CCmdStopInFine}, {"stopfinale", "", CCmdStopInFine}, {"spawnmobj", NULL, CCmdSpawnMobj}, {"coord", "", CCmdPrintPlayerCoords}, // $democam {"makelocp", "i", CCmdMakeLocal}, {"makecam", "i", CCmdSetCamera}, {"setlock", NULL, CCmdSetViewLock}, {"lockmode", "i", CCmdSetViewLock}, {"viewmode", NULL, CCmdSetViewMode}, // jHexen specific {"pig", "", CCmdCheatPig}, {"runscript", "i", CCmdCheatRunScript}, {"scriptinfo", NULL, CCmdScriptInfo}, {"class", "i", CCmdCheatShadowcaster}, {NULL} }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Add the console variables and commands. */ void G_ConsoleRegistration(void) { uint i; for(i = 0; gameCVars[i].name; ++i) Con_AddVariable(&gameCVars[i]); for(i = 0; gameCCmds[i].name; ++i) Con_AddCommand(&gameCCmds[i]); } /** * Settings for console background drawing. * Called EVERY FRAME by the console drawer. */ void G_ConsoleBg(int *width, int *height) { if(consoleBG) { DGL_SetMaterial(consoleBG); *width = (int) (64 * consoleZoom); *height = (int) (64 * consoleZoom); } else { DGL_SetNoMaterial(); *width = *height = 0; } } /** * Called when the player-eyeheight cvar is changed. */ void G_UpdateEyeHeight(cvar_t* unused) { player_t* plr = &players[CONSOLEPLAYER]; if(!(plr->plr->flags & DDPF_CAMERA)) plr->viewHeight = (float) cfg.plrViewHeight; } /** * Draw (char *) text in the game's font. * Called by the console drawer. */ int ConTextOut(const char *text, int x, int y) { M_WriteText3(x, y, text, GF_FONTA, -1, -1, -1, -1, false, false, 0); return 0; } /** * Get the visual width of (char*) text in the game's font. */ int ConTextWidth(const char *text) { return M_StringWidth(text, GF_FONTA); } /** * Console command to take a screenshot (duh). */ DEFCC(CCmdScreenShot) { G_ScreenShot(); return true; } /** * Console command to change the size of the view window. */ DEFCC(CCmdViewSize) { int min = 3, max = 13, *val = &cfg.screenBlocks; if(argc != 2) { Con_Printf("Usage: %s (size)\n", argv[0]); Con_Printf("Size can be: +, -, (num).\n"); return true; } // Adjust/set the value if(!stricmp(argv[1], "+")) (*val)++; else if(!stricmp(argv[1], "-")) (*val)--; else *val = strtol(argv[1], NULL, 0); // Clamp it if(*val < min) *val = min; if(*val > max) *val = max; // Update the view size if necessary. R_SetViewSize(cfg.screenBlocks); return true; } /** * Configure the console to use the game's font. */ DEFCC(CCmdHexenFont) { ddfont_t cfont; cfont.flags = DDFONT_WHITE; cfont.height = 9; cfont.sizeX = 1.2f; cfont.sizeY = 2; cfont.drawText = ConTextOut; cfont.getWidth = ConTextWidth; cfont.filterText = NULL; Con_SetFont(&cfont); return true; } /** * Configure the console background. */ DEFCC(CCmdConBackground) { material_t* mat; if(!stricmp(argv[1], "off") || !stricmp(argv[1], "none")) { consoleBG = NULL; return true; } if((mat = P_ToPtr(DMU_MATERIAL, P_MaterialCheckNumForName(argv[1], MN_ANY)))) consoleBG = mat; return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/sc_man.c0000644000175000017500000002127211357170242022226 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sc_man.c: Hexen script lump parsing. */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jhexen.h" // MACROS ------------------------------------------------------------------ #define MAX_SCRIPTNAME_LEN (32) #define MAX_STRING_SIZE (64) #define ASCII_COMMENT (';') #define ASCII_QUOTE (34) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- char* sc_String; int sc_Number; int sc_Line; boolean sc_End; boolean sc_Crossed; boolean sc_FileScripts = false; const char* sc_ScriptsDir = ""; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static char ScriptName[MAX_SCRIPTNAME_LEN+1]; static char* ScriptBuffer; static char* ScriptPtr; static char* ScriptEndPtr; static char StringBuffer[MAX_STRING_SIZE]; static boolean ScriptOpen = false; static boolean ScriptFreeCLib; // true = de-allocate using free() static size_t ScriptSize; static boolean AlreadyGot = false; // CODE -------------------------------------------------------------------- static void checkOpen(void) { if(ScriptOpen == false) { Con_Error("SC_ call before SC_Open()."); } } static void openScriptLump(lumpnum_t lump) { SC_Close(); strcpy(ScriptName, W_LumpName(lump)); ScriptBuffer = (char *) W_CacheLumpNum(lump, PU_STATIC); ScriptSize = W_LumpLength(lump); ScriptFreeCLib = false; // De-allocate using Z_Free() ScriptPtr = ScriptBuffer; ScriptEndPtr = ScriptPtr + ScriptSize; sc_Line = 1; sc_End = false; ScriptOpen = true; sc_String = StringBuffer; AlreadyGot = false; } static void openScriptFile(const char* name) { SC_Close(); ScriptSize = M_ReadFile(name, (byte **) &ScriptBuffer); M_ExtractFileBase(ScriptName, name, MAX_SCRIPTNAME_LEN); ScriptFreeCLib = false; // De-allocate using Z_Free() ScriptPtr = ScriptBuffer; ScriptEndPtr = ScriptPtr + ScriptSize; sc_Line = 1; sc_End = false; ScriptOpen = true; sc_String = StringBuffer; AlreadyGot = false; } static void openScriptCLib(const char* name) { SC_Close(); ScriptSize = M_ReadFileCLib(name, (byte **) &ScriptBuffer); M_ExtractFileBase(ScriptName, name, MAX_SCRIPTNAME_LEN); ScriptFreeCLib = true; // De-allocate using free() ScriptPtr = ScriptBuffer; ScriptEndPtr = ScriptPtr + ScriptSize; sc_Line = 1; sc_End = false; ScriptOpen = true; sc_String = StringBuffer; AlreadyGot = false; } void SC_Open(const char* name) { char fileName[128]; if(sc_FileScripts == true) { sprintf(fileName, "%s%s.txt", sc_ScriptsDir, name); SC_OpenFile(fileName); } else { lumpnum_t lump = W_CheckNumForName(name); if(lump == -1) Con_Error("SC_Open: Failed opening lump %s.\n", name); SC_OpenLump(lump); } } /** * Loads a script (from the WAD files) and prepares it for parsing. */ void SC_OpenLump(lumpnum_t lump) { openScriptLump(lump); } /** * Loads a script (from a file) and prepares it for parsing. Uses the * zone memory allocator for memory allocation and de-allocation. */ void SC_OpenFile(const char* name) { openScriptFile(name); } /** * Loads a script (from a file) and prepares it for parsing. Uses C * library function calls for memory allocation and de-allocation. */ void SC_OpenFileCLib(const char* name) { openScriptCLib(name); } void SC_Close(void) { if(ScriptOpen) { if(ScriptFreeCLib == true) { free(ScriptBuffer); } else { Z_Free(ScriptBuffer); } ScriptOpen = false; } } boolean SC_GetString(void) { char* text; boolean foundToken; checkOpen(); if(AlreadyGot) { AlreadyGot = false; return true; } foundToken = false; sc_Crossed = false; if(ScriptPtr >= ScriptEndPtr) { sc_End = true; return false; } while(foundToken == false) { while(*ScriptPtr <= 32) { if(ScriptPtr >= ScriptEndPtr) { sc_End = true; return false; } if(*ScriptPtr++ == '\n') { sc_Line++; sc_Crossed = true; } } if(ScriptPtr >= ScriptEndPtr) { sc_End = true; return false; } if(*ScriptPtr != ASCII_COMMENT) { // Found a token foundToken = true; } else { // Skip comment. while(*ScriptPtr++ != '\n') { if(ScriptPtr >= ScriptEndPtr) { sc_End = true; return false; } } sc_Line++; sc_Crossed = true; } } text = sc_String; if(*ScriptPtr == ASCII_QUOTE) { // Quoted string. ScriptPtr++; while(*ScriptPtr != ASCII_QUOTE) { *text++ = *ScriptPtr++; if(ScriptPtr == ScriptEndPtr || text == &sc_String[MAX_STRING_SIZE - 1]) { break; } } ScriptPtr++; } else { // Normal string. while((*ScriptPtr > 32) && (*ScriptPtr != ASCII_COMMENT)) { *text++ = *ScriptPtr++; if(ScriptPtr == ScriptEndPtr || text == &sc_String[MAX_STRING_SIZE - 1]) { break; } } } *text = 0; return true; } void SC_MustGetString(void) { if(!SC_GetString()) { SC_ScriptError("Missing string."); } } void SC_MustGetStringName(char* name) { SC_MustGetString(); if(!SC_Compare(name)) { SC_ScriptError(NULL); } } boolean SC_GetNumber(void) { char* stopper; checkOpen(); if(SC_GetString()) { sc_Number = strtol(sc_String, &stopper, 0); if(*stopper != 0) { Con_Error("SC_GetNumber: Bad numeric constant \"%s\".\n" "Script %s, Line %d", sc_String, ScriptName, sc_Line); } return true; } return false; } void SC_MustGetNumber(void) { if(!SC_GetNumber()) { SC_ScriptError("Missing integer."); } } /** * Assumes there is a valid string in sc_String. */ void SC_UnGet(void) { AlreadyGot = true; } /** * @return Index of the first match to sc_String from the * passed array of strings, ELSE @c -1,. */ int SC_MatchString(char** strings) { int i; for(i = 0; *strings != NULL; ++i) { if(SC_Compare(*strings++)) { return i; } } return -1; } int SC_MustMatchString(char** strings) { int i; i = SC_MatchString(strings); if(i == -1) { SC_ScriptError(NULL); } return i; } boolean SC_Compare(char* text) { if(strcasecmp(text, sc_String) == 0) { return true; } return false; } void SC_ScriptError(char* message) { if(message == NULL) { message = "Bad syntax."; } Con_Error("Script error, \"%s\" line %d: %s", ScriptName, sc_Line, message); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_setup.c0000644000175000017500000001427011357170242022445 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup. Custom map data properties - jHexen specific. */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "am_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Called during pre-init. * Register the map object data types we want to Doomsday to make public via * it's MPE interface. */ void P_RegisterMapObjs(void) { P_RegisterMapObj(MO_THING, "Thing"); P_RegisterMapObjProperty(MO_THING, MO_ID, "ID", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_X, "X", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Y, "Y", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_Z, "Z", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_ANGLE, "Angle", DDVT_ANGLE); P_RegisterMapObjProperty(MO_THING, MO_DOOMEDNUM, "DoomEdNum", DDVT_INT); P_RegisterMapObjProperty(MO_THING, MO_FLAGS, "Flags", DDVT_SHORT); P_RegisterMapObjProperty(MO_THING, MO_SPECIAL, "Special", DDVT_BYTE); P_RegisterMapObjProperty(MO_THING, MO_ARG0, "Arg0", DDVT_BYTE); P_RegisterMapObjProperty(MO_THING, MO_ARG1, "Arg1", DDVT_BYTE); P_RegisterMapObjProperty(MO_THING, MO_ARG2, "Arg2", DDVT_BYTE); P_RegisterMapObjProperty(MO_THING, MO_ARG3, "Arg3", DDVT_BYTE); P_RegisterMapObjProperty(MO_THING, MO_ARG4, "Arg4", DDVT_BYTE); P_RegisterMapObj(MO_XLINEDEF, "XLinedef"); P_RegisterMapObjProperty(MO_XLINEDEF, MO_TYPE, "Type", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_ARG0, "Arg0", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_ARG1, "Arg1", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_ARG2, "Arg2", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_ARG3, "Arg3", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_ARG4, "Arg4", DDVT_BYTE); P_RegisterMapObjProperty(MO_XLINEDEF, MO_FLAGS, "Flags", DDVT_SHORT); P_RegisterMapObj(MO_XSECTOR, "XSector"); P_RegisterMapObjProperty(MO_XSECTOR, MO_TAG, "Tag", DDVT_SHORT); P_RegisterMapObjProperty(MO_XSECTOR, MO_TYPE, "Type", DDVT_SHORT); } /** * \todo This is actually unnecessary. If we say that in the case of BOOM * overloaded texture names, rather than setting the surface material as * normal, the map converter should instead write to a property in XLinedef * which the game can then look up later. * * Doomsday will call this when loading the map data if it encounters a * value that it doesn't understand for a property IT handles. * * Doomsday thinks we might know what to do with it... * If we don't know what to do we'll return -1. * * @param id Index of the current element being read. * @param dtype DMU type identifier. * @param prop DMU property identifier. * @param type Data type id of the value pointed to by *data. * @param *data Ptr to the data value (has already been expanded, * size converted and endian converted where necessary). */ int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void *data) { switch(dtype) { case DMU_SURFACE: switch(prop) { case DMU_MATERIAL: /** * It could be a BOOM overloaded texture name? * In this context Doomsday expects either -1 (a bad texture name) * Or the id of a wall texture it should set to this section. * \todo Add code to determine what to do. */ break; default: break; } break; default: break; } return -1; // We ain't got a clue what to do with it... } /** * These status reports inform us of what Doomsday is doing to a particular * map data object (at any time) that we might want to react to. * * If we arn't interested in the report - we should simply return true and * take no further action. * * @param code ID code of the status report (enum in dd_share.h) * @param id Map data object id. * @param type Map data object type eg DMU_SECTOR. * @param data Any relevant data for this report (currently unused). */ int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void *data) { switch(code) { case DMUSC_LINE_FIRSTRENDERED: /** * Called the first time the given line is rendered. * *data is a pointer to int, giving the player id which has seen it. * We'll utilize this to mark it as being visible in the automap. */ AM_UpdateLinedef(AM_MapForPlayer(*(int *) data), id, true); break; default: break; } return 1; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/po_man.c0000644000175000017500000004507311357170242022244 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * po_man.c: Polyobject management. */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "p_mapsetup.h" #include "p_map.h" #include "g_common.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static int getPolyobjMirror(uint polyNum); static void thrustMobj(struct mobj_s* mo, void* segp, void* pop); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void PO_StartSequence(polyobj_t* po, int seqBase) { SN_StartSequence((mobj_t*) po, seqBase + po->seqType); } void PO_StopSequence(polyobj_t* po) { SN_StopSequence((mobj_t*) po); } void PO_SetDestination(polyobj_t* po, float dist, uint an, float speed) { po->dest[VX] = po->pos[VX] + dist * FIX2FLT(finecosine[an]); po->dest[VY] = po->pos[VY] + dist * FIX2FLT(finesine[an]); po->speed = speed; } // ===== Polyobj Event Code ===== void T_RotatePoly(polyevent_t* pe) { unsigned int absSpeed; polyobj_t* po = P_GetPolyobj(pe->polyobj); if(P_PolyobjRotate(po, pe->intSpeed)) { absSpeed = abs(pe->intSpeed); if(pe->dist == -1) { // perpetual polyobj. return; } pe->dist -= absSpeed; if(pe->dist <= 0) { if(po->specialData == pe) po->specialData = NULL; PO_StopSequence(po); P_PolyobjFinished(po->tag); DD_ThinkerRemove(&pe->thinker); po->angleSpeed = 0; } if(pe->dist < absSpeed) { pe->intSpeed = pe->dist * (pe->intSpeed < 0 ? -1 : 1); } } } boolean EV_RotatePoly(linedef_t *line, byte *args, int direction, boolean overRide) { int mirror, polyNum; polyevent_t* pe; polyobj_t* po; polyNum = args[0]; po = P_GetPolyobj(polyNum); if(po) { if(po->specialData && !overRide) { // Poly is already moving, so keep going... return false; } } else { Con_Error("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); } pe = Z_Calloc(sizeof(*pe), PU_MAP, 0); pe->thinker.function = T_RotatePoly; DD_ThinkerAdd(&pe->thinker); pe->polyobj = polyNum; if(args[2]) { if(args[2] == 255) { // Perpetual rotation. pe->dist = -1; po->destAngle = -1; } else { pe->dist = args[2] * (ANGLE_90 / 64); // Angle po->destAngle = po->angle + pe->dist * direction; } } else { pe->dist = ANGLE_MAX - 1; po->destAngle = po->angle + pe->dist; } pe->intSpeed = (args[1] * direction * (ANGLE_90 / 64)) >> 3; po->specialData = pe; po->angleSpeed = pe->intSpeed; PO_StartSequence(po, SEQ_DOOR_STONE); while((mirror = getPolyobjMirror(polyNum)) != 0) { po = P_GetPolyobj(mirror); if(po && po->specialData && !overRide) { // Mirroring po is already in motion. break; } pe = Z_Calloc(sizeof(*pe), PU_MAP, 0); pe->thinker.function = T_RotatePoly; DD_ThinkerAdd(&pe->thinker); po->specialData = pe; pe->polyobj = mirror; if(args[2]) { if(args[2] == 255) { pe->dist = -1; po->destAngle = -1; } else { pe->dist = args[2] * (ANGLE_90 / 64); // Angle po->destAngle = po->angle + pe->dist * -direction; } } else { pe->dist = ANGLE_MAX - 1; po->destAngle = po->angle + pe->dist; } direction = -direction; pe->intSpeed = (args[1] * direction * (ANGLE_90 / 64)) >> 3; po->angleSpeed = pe->intSpeed; po = P_GetPolyobj(polyNum); if(po) { po->specialData = pe; } else { Con_Error("EV_RotatePoly: Invalid polyobj num: %d\n", polyNum); } polyNum = mirror; PO_StartSequence(po, SEQ_DOOR_STONE); } return true; } void T_MovePoly(polyevent_t* pe) { unsigned int absSpeed; polyobj_t* po = P_GetPolyobj(pe->polyobj); if(P_PolyobjMove(po, pe->speed[MX], pe->speed[MY])) { absSpeed = abs(pe->intSpeed); pe->dist -= absSpeed; if(pe->dist <= 0) { if(po->specialData == pe) po->specialData = NULL; PO_StopSequence(po); P_PolyobjFinished(po->tag); DD_ThinkerRemove(&pe->thinker); po->speed = 0; } if(pe->dist < absSpeed) { pe->intSpeed = pe->dist * (pe->intSpeed < 0 ? -1 : 1); pe->speed[MX] = FIX2FLT(FixedMul(pe->intSpeed, finecosine[pe->fangle])); pe->speed[MY] = FIX2FLT(FixedMul(pe->intSpeed, finesine[pe->fangle])); } } } boolean EV_MovePoly(linedef_t* line, byte* args, boolean timesEight, boolean overRide) { int mirror, polyNum; polyevent_t* pe; polyobj_t* po; angle_t angle; polyNum = args[0]; po = P_GetPolyobj(polyNum); if(po) { if(po->specialData && !overRide) { // Is already moving. return false; } } else { Con_Error("EV_MovePoly: Invalid polyobj num: %d\n", polyNum); } pe = Z_Calloc(sizeof(*pe), PU_MAP, 0); pe->thinker.function = T_MovePoly; DD_ThinkerAdd(&pe->thinker); pe->polyobj = polyNum; if(timesEight) { pe->dist = args[3] * 8 * FRACUNIT; } else { pe->dist = args[3] * FRACUNIT; // Distance } pe->intSpeed = args[1] * (FRACUNIT / 8); po->specialData = pe; angle = args[2] * (ANGLE_90 / 64); pe->fangle = angle >> ANGLETOFINESHIFT; pe->speed[MX] = FIX2FLT(FixedMul(pe->intSpeed, finecosine[pe->fangle])); pe->speed[MY] = FIX2FLT(FixedMul(pe->intSpeed, finesine[pe->fangle])); PO_StartSequence(po, SEQ_DOOR_STONE); PO_SetDestination(po, FIX2FLT(pe->dist), pe->fangle, FIX2FLT(pe->intSpeed)); while((mirror = getPolyobjMirror(polyNum)) != 0) { po = P_GetPolyobj(mirror); if(po && po->specialData && !overRide) { // mirroring po is already in motion break; } pe = Z_Calloc(sizeof(*pe), PU_MAP, 0); pe->thinker.function = T_MovePoly; DD_ThinkerAdd(&pe->thinker); pe->polyobj = mirror; po->specialData = pe; if(timesEight) { pe->dist = args[3] * 8 * FRACUNIT; } else { pe->dist = args[3] * FRACUNIT; // Distance } pe->intSpeed = args[1] * (FRACUNIT / 8); angle = angle + ANGLE_180; // reverse the angle pe->fangle = angle >> ANGLETOFINESHIFT; pe->speed[MX] = FIX2FLT(FixedMul(pe->intSpeed, finecosine[pe->fangle])); pe->speed[MY] = FIX2FLT(FixedMul(pe->intSpeed, finesine[pe->fangle])); polyNum = mirror; PO_StartSequence(po, SEQ_DOOR_STONE); PO_SetDestination(po, FIX2FLT(pe->dist), pe->fangle, FIX2FLT(pe->intSpeed)); } return true; } void T_PolyDoor(polydoor_t* pd) { int absSpeed; polyobj_t* po = P_GetPolyobj(pd->polyobj); if(pd->tics) { if(!--pd->tics) { PO_StartSequence(po, SEQ_DOOR_STONE); // Movement is about to begin. Update the destination. PO_SetDestination(P_GetPolyobj(pd->polyobj), FIX2FLT(pd->dist), pd->direction, FIX2FLT(pd->intSpeed)); } return; } switch(pd->type) { case PODOOR_SLIDE: if(P_PolyobjMove(po, pd->speed[MX], pd->speed[MY])) { absSpeed = abs(pd->intSpeed); pd->dist -= absSpeed; if(pd->dist <= 0) { PO_StopSequence(po); if(!pd->close) { pd->dist = pd->totalDist; pd->close = true; pd->tics = pd->waitTics; pd->direction = (ANGLE_MAX >> ANGLETOFINESHIFT) - pd->direction; pd->speed[MX] = -pd->speed[MX]; pd->speed[MY] = -pd->speed[MY]; } else { if(po->specialData == pd) po->specialData = NULL; P_PolyobjFinished(po->tag); DD_ThinkerRemove(&pd->thinker); } } } else { if(po->crush || !pd->close) { // Continue moving if the po is a crusher, or is opening. return; } else { // Open back up. pd->dist = pd->totalDist - pd->dist; pd->direction = (ANGLE_MAX >> ANGLETOFINESHIFT) - pd->direction; pd->speed[MX] = -pd->speed[MX]; pd->speed[MY] = -pd->speed[MY]; // Update destination. PO_SetDestination(P_GetPolyobj(pd->polyobj), FIX2FLT(pd->dist), pd->direction, FIX2FLT(pd->intSpeed)); pd->close = false; PO_StartSequence(po, SEQ_DOOR_STONE); } } break; case PODOOR_SWING: if(P_PolyobjRotate(po, pd->intSpeed)) { absSpeed = abs(pd->intSpeed); if(pd->dist == -1) { // Perpetual polyobj. return; } pd->dist -= absSpeed; if(pd->dist <= 0) { PO_StopSequence(po); if(!pd->close) { pd->dist = pd->totalDist; pd->close = true; pd->tics = pd->waitTics; pd->intSpeed = -pd->intSpeed; } else { if(po->specialData == pd) po->specialData = NULL; P_PolyobjFinished(po->tag); DD_ThinkerRemove(&pd->thinker); } } } else { if(po->crush || !pd->close) { // Continue moving if the po is a crusher, or is opening. return; } else { // Open back up and rewait. pd->dist = pd->totalDist - pd->dist; pd->intSpeed = -pd->intSpeed; pd->close = false; PO_StartSequence(po, SEQ_DOOR_STONE); } } break; default: break; } } boolean EV_OpenPolyDoor(linedef_t* line, byte* args, podoortype_t type) { int mirror, polyNum; polydoor_t* pd; polyobj_t* po; angle_t angle = 0; polyNum = args[0]; po = P_GetPolyobj(polyNum); if(po) { if(po->specialData) { // Is already moving. return false; } } else { Con_Error("EV_OpenPolyDoor: Invalid polyobj num: %d\n", polyNum); } pd = Z_Calloc(sizeof(*pd), PU_MAP, 0); pd->thinker.function = T_PolyDoor; DD_ThinkerAdd(&pd->thinker); pd->type = type; pd->polyobj = polyNum; if(type == PODOOR_SLIDE) { pd->waitTics = args[4]; pd->intSpeed = args[1] * (FRACUNIT / 8); pd->totalDist = args[3] * FRACUNIT; // Distance. pd->dist = pd->totalDist; angle = args[2] * (ANGLE_90 / 64); pd->direction = angle >> ANGLETOFINESHIFT; pd->speed[MX] = FIX2FLT(FixedMul(pd->intSpeed, finecosine[pd->direction])); pd->speed[MY] = FIX2FLT(FixedMul(pd->intSpeed, finesine[pd->direction])); PO_StartSequence(po, SEQ_DOOR_STONE); } else if(type == PODOOR_SWING) { pd->waitTics = args[3]; pd->direction = 1; pd->intSpeed = (args[1] * pd->direction * (ANGLE_90 / 64)) >> 3; pd->totalDist = args[2] * (ANGLE_90 / 64); pd->dist = pd->totalDist; PO_StartSequence(po, SEQ_DOOR_STONE); } po->specialData = pd; PO_SetDestination(po, FIX2FLT(pd->dist), pd->direction, FIX2FLT(pd->intSpeed)); while((mirror = getPolyobjMirror(polyNum)) != 0) { po = P_GetPolyobj(mirror); if(po && po->specialData) { // Mirroring po is already in motion. break; } pd = Z_Calloc(sizeof(*pd), PU_MAP, 0); pd->thinker.function = T_PolyDoor; DD_ThinkerAdd(&pd->thinker); pd->polyobj = mirror; pd->type = type; po->specialData = pd; if(type == PODOOR_SLIDE) { pd->waitTics = args[4]; pd->intSpeed = args[1] * (FRACUNIT / 8); pd->totalDist = args[3] * FRACUNIT; // Distance. pd->dist = pd->totalDist; angle = angle + ANGLE_180; // Reverse the angle. pd->direction = angle >> ANGLETOFINESHIFT; pd->speed[MX] = FIX2FLT(FixedMul(pd->intSpeed, finecosine[pd->direction])); pd->speed[MY] = FIX2FLT(FixedMul(pd->intSpeed, finesine[pd->direction])); PO_StartSequence(po, SEQ_DOOR_STONE); } else if(type == PODOOR_SWING) { pd->waitTics = args[3]; pd->direction = -1; pd->intSpeed = (args[1] * pd->direction * (ANGLE_90 / 64)) >> 3; pd->totalDist = args[2] * (ANGLE_90 / 64); pd->dist = pd->totalDist; PO_StartSequence(po, SEQ_DOOR_STONE); } polyNum = mirror; PO_SetDestination(po, FIX2FLT(pd->dist), pd->direction, FIX2FLT(pd->intSpeed)); } return true; } // ===== Higher Level Poly Interface code ===== static int getPolyobjMirror(uint poly) { uint i; for(i = 0; i < numpolyobjs; ++i) { polyobj_t* po = P_GetPolyobj(i | 0x80000000); if(po->tag == poly) { seg_t* seg = po->segs[0]; linedef_t* linedef = P_GetPtrp(seg, DMU_LINEDEF); return P_ToXLine(linedef)->arg2; } } return 0; } static void thrustMobj(struct mobj_s* mo, void* segp, void* pop) { seg_t* seg = (seg_t*) segp; polyobj_t* po = (polyobj_t*) pop; uint thrustAn; float thrustX, thrustY, force; polyevent_t* pe; // Clients do no polyobj <-> mobj interaction. if(IS_CLIENT) return; if(P_MobjIsCamera(mo)) // Cameras don't interact with polyobjs. return; if(!(mo->flags & MF_SHOOTABLE) && !mo->player) return; thrustAn = (P_GetAnglep(seg, DMU_ANGLE) - ANGLE_90) >> ANGLETOFINESHIFT; pe = (polyevent_t*) po->specialData; if(pe) { if(pe->thinker.function == T_RotatePoly) { force = FIX2FLT(pe->intSpeed >> 8); } else { force = FIX2FLT(pe->intSpeed >> 3); } if(force < 1) { force = 1; } else if(force > 4) { force = 4; } } else { force = 1; } thrustX = force * FIX2FLT(finecosine[thrustAn]); thrustY = force * FIX2FLT(finesine[thrustAn]); mo->mom[MX] += thrustX; mo->mom[MY] += thrustY; if(po->crush) { if(!P_CheckPosition2f(mo, mo->pos[VX] + thrustX, mo->pos[VY] + thrustY)) { P_DamageMobj(mo, NULL, NULL, 3, false); } } } /** * Initialize all polyobjects in the current map. */ void PO_InitForMap(void) { uint i; Con_Message("PO_InitForMap: Initializing polyobjects.\n"); // thrustMobj will handle polyobj <-> mobj interaction. P_SetPolyobjCallback(thrustMobj); for(i = 0; i < numpolyobjs; ++i) { uint j; const mapspot_t* spot; polyobj_t* po; po = P_GetPolyobj(i | 0x80000000); // Init game-specific properties. po->specialData = NULL; // Find the mapspot associated with this polyobj. j = 0; spot = NULL; while(j < numMapSpots && !spot) { if((mapSpots[j].doomEdNum == PO_SPAWN_DOOMEDNUM || mapSpots[j].doomEdNum == PO_SPAWNCRUSH_DOOMEDNUM) && mapSpots[j].angle == po->tag) { // Polyobj mapspot. spot = &mapSpots[j]; } else { j++; } } if(spot) { po->crush = (spot->doomEdNum == PO_SPAWNCRUSH_DOOMEDNUM? 1 : 0); P_PolyobjMove(po, -po->pos[VX] + spot->pos[VX], -po->pos[VY] + spot->pos[VY]); } else { Con_Message("PO_InitForMap: Warning, missing mapspot for poly %i.", i); } } } boolean PO_Busy(int polyobj) { polyobj_t* po = P_GetPolyobj(polyobj); if(po && po->specialData != NULL) return true; return false; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_anim.c0000644000175000017500000001252211357170242022227 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_anim.c: Flat and Texture animations, parsed from ANIMDEFS. */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "p_mapsetup.h" #include "p_mapspec.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- static void parseAnimGroup(material_namespace_t mnamespace) { boolean ignore; boolean done; int groupNumber = 0; materialnum_t matNumBase = 0, lumpNumBase = 0; if(!(mnamespace == MN_FLATS || mnamespace == MN_TEXTURES)) Con_Error("parseAnimGroup: Internal Error, invalid namespace %i.", (int) mnamespace); if(!SC_GetString()) // Name. { SC_ScriptError("Missing string."); } ignore = true; if(mnamespace == MN_TEXTURES) { if((matNumBase = P_MaterialCheckNumForName(sc_String, MN_TEXTURES)) != 0) ignore = false; } else { if((lumpNumBase = W_CheckNumForName(sc_String)) != -1) ignore = false; } if(!ignore) groupNumber = R_CreateAnimGroup(AGF_SMOOTH | AGF_FIRST_ONLY); done = false; do { if(SC_GetString()) { if(SC_Compare("pic")) { int picNum, min = 0, max = 0; SC_MustGetNumber(); picNum = sc_Number; SC_MustGetString(); if(SC_Compare("tics")) { SC_MustGetNumber(); min = sc_Number; } else if(SC_Compare("rand")) { SC_MustGetNumber(); min = sc_Number; SC_MustGetNumber(); max = sc_Number; } else { SC_ScriptError(NULL); } if(!ignore) { if(mnamespace == MN_TEXTURES) { /** * \fixme Here an assumption is made that * MN_TEXTURES type materials are registered in the * same order as they are defined in the * TEXTURE(1...) lump(s). */ R_AddToAnimGroup(groupNumber, matNumBase + picNum - 1, min, (max > 0? max - min : 0)); } else { materialnum_t frame = P_MaterialCheckNumForName(W_LumpName(lumpNumBase + picNum - 1), MN_FLATS); R_AddToAnimGroup(groupNumber, frame, min, (max > 0? max - min : 0)); } } } else { SC_UnGet(); done = true; } } else { done = true; } } while(!done); } /** * Parse an ANIMDEFS definition for flat/texture animations. */ void P_InitPicAnims(void) { lumpnum_t lump = W_CheckNumForName("ANIMDEFS"); if(lump != -1) { SC_OpenLump(lump); while(SC_GetString()) { if(SC_Compare("flat")) { parseAnimGroup(MN_FLATS); } else if(SC_Compare("texture")) { parseAnimGroup(MN_TEXTURES); } else { SC_ScriptError(NULL); } } SC_Close(); } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_mapinfo.c0000644000175000017500000003567011357170242022745 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mapinfo.c: MAPINFO lump support. */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "r_common.h" // MACROS ------------------------------------------------------------------ #define MAPINFO_SCRIPT_NAME "MAPINFO" #define UNKNOWN_MAP_NAME "DEVELOPMENT MAP" #define DEFAULT_SKY_NAME "SKY1" #define DEFAULT_SONG_LUMP "DEFSONG" #define DEFAULT_FADE_TABLE "COLORMAP" // TYPES ------------------------------------------------------------------- typedef struct mapinfo_s { short cluster; uint warpTrans; uint nextMap; short cdTrack; char name[32]; materialnum_t sky1Material; materialnum_t sky2Material; float sky1ScrollDelta; float sky2ScrollDelta; boolean doubleSky; boolean lightning; int fadetable; char songLump[10]; } mapinfo_t; enum { MCMD_NONE, MCMD_SKY1, MCMD_SKY2, MCMD_LIGHTNING, MCMD_FADETABLE, MCMD_DOUBLESKY, MCMD_CLUSTER, MCMD_WARPTRANS, MCMD_NEXT, MCMD_CDTRACK, MCMD_CD_STARTTRACK, MCMD_CD_END1TRACK, MCMD_CD_END2TRACK, MCMD_CD_END3TRACK, MCMD_CD_INTERTRACK, MCMD_CD_TITLETRACK, NUM_MAP_CMDS }; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void setSongCDTrack(int index, int track); static uint qualifyMap(uint map); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static mapinfo_t MapInfo[99]; static uint mapCount; static char *mapCmdNames[] = { "SKY1", "SKY2", "DOUBLESKY", "LIGHTNING", "FADETABLE", "CLUSTER", "WARPTRANS", "NEXT", "CDTRACK", "CD_START_TRACK", "CD_END1_TRACK", "CD_END2_TRACK", "CD_END3_TRACK", "CD_INTERMISSION_TRACK", "CD_TITLE_TRACK", NULL }; static int mapCmdIDs[] = { MCMD_SKY1, MCMD_SKY2, MCMD_DOUBLESKY, MCMD_LIGHTNING, MCMD_FADETABLE, MCMD_CLUSTER, MCMD_WARPTRANS, MCMD_NEXT, MCMD_CDTRACK, MCMD_CD_STARTTRACK, MCMD_CD_END1TRACK, MCMD_CD_END2TRACK, MCMD_CD_END3TRACK, MCMD_CD_INTERTRACK, MCMD_CD_TITLETRACK }; static int cdNonMapTracks[6]; // Non-map specific song cd track numbers static char* cdSongDefIDs[] = // Music defs that correspond the above. { "startup", "hall", "orb", "chess", "hub", "hexen" }; // CODE -------------------------------------------------------------------- /** * Initializes the MapInfo database. * All MAPINFO lumps are then parsed and stored into the database. * * Called by P_Init() */ void P_InitMapInfo(void) { uint map, mapMax = 0; int mcmdValue; char songMulch[10]; mapinfo_t defMapInfo; mapinfo_t* info; // Configure the defaults defMapInfo.cluster = 0; defMapInfo.warpTrans = 0; defMapInfo.nextMap = 0; // Always go to map 0 if not specified. defMapInfo.cdTrack = 1; defMapInfo.sky1Material = P_MaterialNumForName(shareware ? "SKY2" : DEFAULT_SKY_NAME, MN_TEXTURES); defMapInfo.sky2Material = defMapInfo.sky1Material; defMapInfo.sky1ScrollDelta = 0; defMapInfo.sky2ScrollDelta = 0; defMapInfo.doubleSky = false; defMapInfo.lightning = false; defMapInfo.fadetable = W_GetNumForName(DEFAULT_FADE_TABLE); strcpy(defMapInfo.name, UNKNOWN_MAP_NAME); for(map = 0; map < 99; ++map) MapInfo[map].warpTrans = 0; SC_Open(MAPINFO_SCRIPT_NAME); while(SC_GetString()) { if(SC_Compare("MAP") == false) { SC_ScriptError(NULL); } SC_MustGetNumber(); if(sc_Number < 1 || sc_Number > 99) SC_ScriptError(NULL); map = (unsigned) sc_Number - 1; info = &MapInfo[map]; // Save song lump name strcpy(songMulch, info->songLump); // Copy defaults to current map definition memcpy(info, &defMapInfo, sizeof(*info)); // Restore song lump name strcpy(info->songLump, songMulch); // The warp translation defaults to the map number info->warpTrans = map; // Map name must follow the number SC_MustGetString(); strcpy(info->name, sc_String); // Process optional tokens while(SC_GetString()) { if(SC_Compare("MAP")) { // Start next map definition. SC_UnGet(); break; } mcmdValue = mapCmdIDs[SC_MustMatchString(mapCmdNames)]; switch(mcmdValue) { case MCMD_CLUSTER: SC_MustGetNumber(); info->cluster = sc_Number; break; case MCMD_WARPTRANS: SC_MustGetNumber(); if(sc_Number < 1 || sc_Number > 99) SC_ScriptError(NULL); info->warpTrans = (unsigned) sc_Number - 1; break; case MCMD_NEXT: SC_MustGetNumber(); if(sc_Number < 1 || sc_Number > 99) SC_ScriptError(NULL); info->nextMap = (unsigned) sc_Number - 1; break; case MCMD_CDTRACK: SC_MustGetNumber(); info->cdTrack = sc_Number; break; case MCMD_SKY1: SC_MustGetString(); info->sky1Material = P_MaterialNumForName(sc_String, MN_TEXTURES); SC_MustGetNumber(); info->sky1ScrollDelta = (float) sc_Number / 256; break; case MCMD_SKY2: SC_MustGetString(); info->sky2Material = P_MaterialNumForName(sc_String, MN_TEXTURES); SC_MustGetNumber(); info->sky2ScrollDelta = (float) sc_Number / 256; break; case MCMD_DOUBLESKY: info->doubleSky = true; break; case MCMD_LIGHTNING: info->lightning = true; break; case MCMD_FADETABLE: SC_MustGetString(); info->fadetable = W_GetNumForName(sc_String); break; case MCMD_CD_STARTTRACK: case MCMD_CD_END1TRACK: case MCMD_CD_END2TRACK: case MCMD_CD_END3TRACK: case MCMD_CD_INTERTRACK: case MCMD_CD_TITLETRACK: SC_MustGetNumber(); setSongCDTrack(mcmdValue - MCMD_CD_STARTTRACK, sc_Number); break; default: break; } } mapMax = map > mapMax ? map : mapMax; } SC_Close(); mapCount = mapMax+1; } /** * Special early initializer needed to start sound before R_InitRefresh() */ void P_InitMapMusicInfo(void) { uint i; for(i = 0; i < 99; ++i) { strcpy(MapInfo[i].songLump, DEFAULT_SONG_LUMP); } mapCount = 98; } static void setSongCDTrack(int index, int track) { int cdTrack = track; // Set the internal array. cdNonMapTracks[index] = sc_Number; // Update the corresponding Doomsday definition. Def_Set(DD_DEF_MUSIC, Def_Get(DD_DEF_MUSIC, cdSongDefIDs[index], 0), DD_CD_TRACK, &cdTrack); } static __inline uint qualifyMap(uint map) { return (map >= mapCount) ? 0 : map; } /** * Translates a warp map number to logical map number. * * @param map The warp map number to translate. * * @return The logical map number given a warp map number. */ uint P_TranslateMap(uint map) { uint i; for(i = 0; i < 99; ++i) { if(MapInfo[i].warpTrans == map) return i; } return 0; // Not found, default to map zero. } /** * Set the song lump name of a map. * * NOTE: Cannot be used to alter the default map #0. * * @param map The map (logical number) to be changed. * @param lumpName The lumpName to be set. */ void P_PutMapSongLump(uint map, char *lumpName) { if(map >= mapCount) return; strncpy(MapInfo[map].songLump, lumpName, sizeof(MapInfo[map].songLump)); } /** * Retrieve the name of the given map. * * @param map The map (logical number) to be queried. * * @return Ptr to string containing the name of the map. */ char *P_GetMapName(uint map) { return MapInfo[qualifyMap(map)].name; } /** * Retrieve the cluster number of the given map. * * @param map The map (logical number) to be queried. * * @return The cluster number of the map. */ int P_GetMapCluster(uint map) { return (int) MapInfo[qualifyMap(map)].cluster; } /** * Retrieve the CD track number of the given map. * * @param map The map (logical number) to be queried. * * @return The CD track number for the map. */ int P_GetMapCDTrack(uint map) { return (int) MapInfo[qualifyMap(map)].cdTrack; } /** * Retrieve the map warp number of the given map. * * @param map The map (logical number) to be queried. * * @return The warp number of the map. */ uint P_GetMapWarpTrans(uint map) { return MapInfo[qualifyMap(map)].warpTrans; } /** * Retrieve the next map number of the given map. * * @param map The map (logical number) to be queried. * * @return The next map number of the map. */ uint P_GetMapNextMap(uint map) { return MapInfo[qualifyMap(map)].nextMap; } /** * Retrieve the sky1 material num of the given map. * * @param map The map (logical number) to be queried. * * @return The sky1 material num of the map. */ materialnum_t P_GetMapSky1Material(uint map) { return MapInfo[qualifyMap(map)].sky1Material; } /** * Retrieve the sky2 material num of the given map. * * @param map The map (logical number) to be queried. * * @return The sky2 material num of the map. */ materialnum_t P_GetMapSky2Material(uint map) { return MapInfo[qualifyMap(map)].sky2Material; } /** * Retrieve the sky1 scroll delta of the given map. * * @param map The map (logical number) to be queried. * * @return The sky1 scroll delta of the map. */ float P_GetMapSky1ScrollDelta(uint map) { return MapInfo[qualifyMap(map)].sky1ScrollDelta; } /** * Retrieve the sky2 scroll delta of the given map. * * @param map The map (logical number) to be queried. * * @return The sky2 scroll delta of the map. */ float P_GetMapSky2ScrollDelta(uint map) { return MapInfo[qualifyMap(map)].sky2ScrollDelta; } /** * Retrieve the value of the double sky property of the given map. * * @param map The map (logical number) to be queried. * * @return @c true, if the map is set to doublesky. */ boolean P_GetMapDoubleSky(uint map) { return MapInfo[qualifyMap(map)].doubleSky; } /** * Retrieve the value of the lighting property of the given map. * * @param map The map (logical number) to be queried. * * @return @c true, if the map is set to lightning. */ boolean P_GetMapLightning(uint map) { return MapInfo[qualifyMap(map)].lightning; } /** * Retrieve the fadetable lump id of the given map. * * @param map The map (logical number) to be queried. * * @return The lump id used for the fadetable for the map. */ int P_GetMapFadeTable(uint map) { return MapInfo[qualifyMap(map)].fadetable; } /** * Retrieve the song lump name for the given map. * * @param map The map (logical number) to be queried. * * @return @c NULL, if the map is set to use the * default song lump, else a ptr to a string * containing the name of the song lump. */ char *P_GetMapSongLump(uint map) { if(!strcasecmp(MapInfo[qualifyMap(map)].songLump, DEFAULT_SONG_LUMP)) { return NULL; } else { return MapInfo[qualifyMap(map)].songLump; } } /** * Retrieve the CD start track number of the given map. * * @param map The map (logical number) to be queried. * * @return The CD start track number of the map. */ int P_GetCDStartTrack(void) { return cdNonMapTracks[MCMD_CD_STARTTRACK - MCMD_CD_STARTTRACK]; } /** * Retrieve the CD end1 track number of the given map. * * @param map The map (logical number) to be queried. * * @return The CD end1 track number of the map. */ int P_GetCDEnd1Track(void) { return cdNonMapTracks[MCMD_CD_END1TRACK - MCMD_CD_STARTTRACK]; } /** * Retrieve the CD end2 track number of the given map. * * @param map The map (logical number) to be queried. * * @return The CD end2 track number of the map. */ int P_GetCDEnd2Track(void) { return cdNonMapTracks[MCMD_CD_END2TRACK - MCMD_CD_STARTTRACK]; } /** * Retrieve the CD end3 track number of the given map. * * @param map The map (logical number) to be queried. * * @return The CD end3 track number of the map. */ int P_GetCDEnd3Track(void) { return cdNonMapTracks[MCMD_CD_END3TRACK - MCMD_CD_STARTTRACK]; } /** * Retrieve the CD intermission track number of the given map. * * @param map The map (logical number) to be queried. * * @return The CD intermission number of the map. */ int P_GetCDIntermissionTrack(void) { return cdNonMapTracks[MCMD_CD_INTERTRACK - MCMD_CD_STARTTRACK]; } /** * Retrieve the CD title track number of the given map. * * @param map The map (logical number) to be queried. * * @return The CD title track number of the map. */ int P_GetCDTitleTrack(void) { return cdNonMapTracks[MCMD_CD_TITLETRACK - MCMD_CD_STARTTRACK]; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_sound.c0000644000175000017500000001063711357170242022440 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_sound.c: * * \bug Not 64bit clean: In function 'S_ParseSndInfoLump': cast to pointer from integer of different size */ // HEADER FILES ------------------------------------------------------------ #include #include #include #include "jhexen.h" // MACROS ------------------------------------------------------------------ #define DEFAULT_ARCHIVEPATH "o:\\sound\\archive\\" // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ static char ArchivePath[128]; // CODE -------------------------------------------------------------------- int S_GetSoundID(const char* name) { return Def_Get(DD_DEF_SOUND_BY_NAME, name, 0); } /** * Starts the song of the specified map, updating the currentmap definition * in the process. */ void S_MapMusic(uint episode, uint map) { int idx = Def_Get(DD_DEF_MUSIC, "currentmap", 0); int cdTrack; // Update the 'currentmap' music definition. Def_Set(DD_DEF_MUSIC, idx, DD_LUMP, P_GetMapSongLump(map)); cdTrack = P_GetMapCDTrack(map); Def_Set(DD_DEF_MUSIC, idx, DD_CD_TRACK, &cdTrack); if(S_StartMusic("currentmap", true)) { // Set the game status cvar for the map music gsvMapMusic = idx; } } void S_ParseSndInfoLump(void) { int i; char buf[80]; lumpnum_t lump = W_CheckNumForName("SNDINFO"); strcpy(ArchivePath, DEFAULT_ARCHIVEPATH); if(lump != -1) { SC_OpenLump(lump); while(SC_GetString()) { if(*sc_String == '$') { if(!stricmp(sc_String, "$ARCHIVEPATH")) { SC_MustGetString(); strcpy(ArchivePath, sc_String); } else if(!stricmp(sc_String, "$MAP")) { SC_MustGetNumber(); SC_MustGetString(); if(sc_Number) { P_PutMapSongLump(sc_Number, sc_String); } } continue; } else { i = Def_Get(DD_DEF_SOUND_BY_NAME, sc_String, 0); if(i) { SC_MustGetString(); Def_Set(DD_DEF_SOUND, i, DD_LUMP, *sc_String != '?' ? sc_String : "default"); } else { // Read the lumpname anyway. SC_MustGetString(); } } } SC_Close(); } // All sounds left without a lumpname will use "DEFAULT". for(i = 0; i < Get(DD_NUMSOUNDS); ++i) { //// \kludge DJS - This uses a kludge to traverse the entire sound list. //// \fixme Implement a mechanism for walking the Def databases. Def_Get(DD_DEF_SOUND_LUMPNAME, (char *) &i, buf); if(!strcmp(buf, "")) Def_Set(DD_DEF_SOUND, i, DD_LUMP, "default"); } } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_mobj.c0000644000175000017500000020424211357170242022234 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.c: */ #ifdef MSVC # pragma optimize("g", off) #endif // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "../../../engine/portable/include/m_bams.h" // for BANG2RAD #include "dmu_lib.h" #include "p_map.h" #include "p_player.h" #include "g_common.h" // MACROS ------------------------------------------------------------------ #define MAX_TID_COUNT 200 #define MAX_BOB_OFFSET 8 #define BLAST_RADIUS_DIST 255 #define BLAST_SPEED 20 #define BLAST_FULLSTRENGTH 255 #define HEAL_RADIUS_DIST 255 #define NOMOMENTUM_THRESHOLD (0.000001f) #define WALKSTOP_THRESHOLD (0.062484741f) // FIX2FLT(0x1000-1) #define SMALLSPLASHCLIP (12); // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void G_PlayerReborn(int player); void P_MarkAsLeaving(mobj_t *corpse); mobj_t *P_CheckOnMobj(mobj_t *thing); void P_BounceWall(mobj_t *mo); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void PlayerLandedOnThing(mobj_t *mo, mobj_t *onmobj); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern mobj_t lavaInflictor; // PUBLIC DATA DEFINITIONS ------------------------------------------------- mobjtype_t PuffType; mobj_t *MissileMobj; // PRIVATE DATA DEFINITIONS ------------------------------------------------ static int TIDList[MAX_TID_COUNT + 1]; // +1 for termination marker static mobj_t *TIDMobj[MAX_TID_COUNT]; // CODE -------------------------------------------------------------------- const terraintype_t* P_MobjGetFloorTerrainType(mobj_t* mo) { sector_t* sec = P_GetPtrp(mo->subsector, DMU_SECTOR); return P_GetPlaneMaterialType(sec, PLN_FLOOR); } /** * @return @c true if the mobj is still present. */ boolean P_MobjChangeState(mobj_t *mobj, statenum_t state) { state_t* st; if(state == S_NULL) { // Remove mobj. mobj->state = (state_t *) S_NULL; P_MobjRemove(mobj, false); return false; } st = &STATES[state]; P_MobjSetState(mobj, state); mobj->turnTime = false; // $visangle-facetarget if(st->action) { // Call action function. st->action(mobj); } // Return false if the action function removed the mobj. return mobj->thinker.function != NOPFUNC; } /** * Same as P_MobjChangeState, but does not call the state function. */ boolean P_SetMobjStateNF(mobj_t* mobj, statenum_t state) { if(state == S_NULL) { // Remove mobj mobj->state = (state_t *) S_NULL; P_MobjRemove(mobj, false); return false; } mobj->turnTime = false; // $visangle-facetarget P_MobjSetState(mobj, state); return true; } void P_ExplodeMissile(mobj_t* mo) { mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); if(mo->flags & MF_MISSILE) { mo->flags &= ~MF_MISSILE; mo->flags |= MF_VIEWALIGN; if(mo->flags & MF_BRIGHTEXPLODE) mo->flags |= MF_BRIGHTSHADOW; } switch(mo->type) { case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: S_StartSound(SFX_SORCERER_BIGBALLEXPLODE, NULL); break; case MT_SORCFX1: S_StartSound(SFX_SORCERER_HEADSCREAM, NULL); break; default: if(mo->info->deathSound) S_StartSound(mo->info->deathSound, mo); break; } } void P_FloorBounceMissile(mobj_t* mo) { boolean shouldSplash = P_HitFloor(mo); if(shouldSplash) { switch(mo->type) { case MT_SORCFX1: case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: break; default: P_MobjRemove(mo, false); return; } } switch(mo->type) { case MT_SORCFX1: mo->mom[MZ] = -mo->mom[MZ]; // No energy absorbed. break; case MT_SGSHARD1: case MT_SGSHARD2: case MT_SGSHARD3: case MT_SGSHARD4: case MT_SGSHARD5: case MT_SGSHARD6: case MT_SGSHARD7: case MT_SGSHARD8: case MT_SGSHARD9: case MT_SGSHARD0: mo->mom[MZ] *= -0.3f; if(fabs(mo->mom[MZ]) < 1.0f / 2) { P_MobjChangeState(mo, S_NULL); return; } break; default: mo->mom[MZ] *= -0.7f; break; } mo->mom[MX] = 2 * mo->mom[MX] / 3; mo->mom[MY] = 2 * mo->mom[MY] / 3; if(mo->info->seeSound) { switch(mo->type) { case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: if(!mo->args[0]) S_StartSound(mo->info->seeSound, mo); break; default: S_StartSound(mo->info->seeSound, mo); break; } S_StartSound(mo->info->seeSound, mo); } } void P_ThrustMobj(mobj_t *mo, angle_t angle, float move) { uint an = angle >> ANGLETOFINESHIFT; mo->mom[MX] += move * FIX2FLT(finecosine[an]); mo->mom[MY] += move * FIX2FLT(finesine[an]); } /** * @param delta The amount 'source' needs to turn. * * @return @c 1, if 'source' needs to turn clockwise, or * @c 0, if 'source' needs to turn counter clockwise. */ int P_FaceMobj(mobj_t *source, mobj_t *target, angle_t *delta) { angle_t diff, angle1, angle2; angle1 = source->angle; angle2 = R_PointToAngle2(source->pos[VX], source->pos[VY], target->pos[VX], target->pos[VY]); if(angle2 > angle1) { diff = angle2 - angle1; if(diff > ANGLE_180) { *delta = ANGLE_MAX - diff; return 0; } else { *delta = diff; return 1; } } else { diff = angle1 - angle2; if(diff > ANGLE_180) { *delta = ANGLE_MAX - diff; return 1; } else { *delta = diff; return 0; } } } /** * The missile tracer field must be mobj_t *target. * * @return @c true, if target was tracked. */ boolean P_SeekerMissile(mobj_t *actor, angle_t thresh, angle_t turnMax) { int dir; uint an; float dist; angle_t delta; mobj_t *target; target = actor->tracer; if(target == NULL) return false; if(!(target->flags & MF_SHOOTABLE)) { // Target died. actor->tracer = NULL; return false; } dir = P_FaceMobj(actor, target, &delta); if(delta > thresh) { delta >>= 1; if(delta > turnMax) { delta = turnMax; } } if(dir) // Turn clockwise. actor->angle += delta; else // Turn counter clockwise. actor->angle -= delta; an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = actor->info->speed * FIX2FLT(finecosine[an]); actor->mom[MY] = actor->info->speed * FIX2FLT(finesine[an]); if(actor->pos[VZ] + actor->height < target->pos[VZ] || target->pos[VZ] + target->height < actor->pos[VZ]) { // Need to seek vertically dist = P_ApproxDistance(target->pos[VX] - actor->pos[VX], target->pos[VY] - actor->pos[VY]); dist /= actor->info->speed; if(dist < 1) dist = 1; actor->mom[MZ] = (target->pos[VZ] + (target->height /2) - (actor->pos[VZ] + (actor->height /2))) / dist; } return true; } float P_MobjGetFriction(mobj_t* mo) { if((mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && !mo->onMobj) { return FRICTION_FLY; } else { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FRICTION_LOW) return FRICTION_LOW; } return FRICTION_NORMAL; } void P_MobjMoveXY(mobj_t* mo) { static const int windTab[3] = { 2048 * 5, 2048 * 10, 2048 * 25 }; float posTry[2]; player_t* player; float move[2]; int special; angle_t angle; // $democam: cameramen have their own movement code if(P_CameraXYMovement(mo)) return; if(mo->mom[MX] == 0 && mo->mom[MY] == 0) { if(mo->flags & MF_SKULLFLY) { // A flying mobj slammed into something mo->flags &= ~MF_SKULLFLY; mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_SEE)); } return; } special = P_ToXSectorOfSubsector(mo->subsector)->special; if(mo->flags2 & MF2_WINDTHRUST) { switch(special) { case 40: case 41: case 42: // Wind_East P_ThrustMobj(mo, 0, FIX2FLT(windTab[special - 40])); break; case 43: case 44: case 45: // Wind_North P_ThrustMobj(mo, ANG90, FIX2FLT(windTab[special - 43])); break; case 46: case 47: case 48: // Wind_South P_ThrustMobj(mo, ANG270, FIX2FLT(windTab[special - 46])); break; case 49: case 50: case 51: // Wind_West P_ThrustMobj(mo, ANG180, FIX2FLT(windTab[special - 49])); break; } } player = mo->player; if(mo->mom[MX] > MAXMOVE) mo->mom[MX] = MAXMOVE; else if(mo->mom[MX] < -MAXMOVE) mo->mom[MX] = -MAXMOVE; if(mo->mom[MY] > MAXMOVE) mo->mom[MY] = MAXMOVE; else if(mo->mom[MY] < -MAXMOVE) mo->mom[MY] = -MAXMOVE; move[VX] = mo->mom[MX]; move[VY] = mo->mom[MY]; do { if(move[VX] > MAXMOVE / 2 || move[VY] > MAXMOVE / 2) { posTry[VX] = mo->pos[VX] + move[VX] / 2; posTry[VY] = mo->pos[VY] + move[VY] / 2; move[VX] /= 2; move[VY] /= 2; } else { posTry[VX] = mo->pos[VX] + move[VX]; posTry[VY] = mo->pos[VY] + move[VY]; move[VX] = move[VY] = 0; } if(!P_TryMove(mo, posTry[VX], posTry[VY])) { // Blocked move. if(mo->flags2 & MF2_SLIDE) { // Try to slide along it. if(blockingMobj == NULL) { // Slide against wall. P_SlideMove(mo); } else { // Slide against mobj. if(P_TryMove(mo, mo->pos[VX], posTry[VY])) { mo->mom[MX] = 0; } else if(P_TryMove(mo, posTry[VX], mo->pos[VY])) { mo->mom[MY] = 0; } else { mo->mom[MX] = mo->mom[MY] = 0; } } } else if(mo->flags & MF_MISSILE) { sector_t* backSec; if(mo->flags2 & MF2_FLOORBOUNCE) { if(blockingMobj) { if((blockingMobj->flags2 & MF2_REFLECTIVE) || ((!blockingMobj->player) && (!(blockingMobj->flags & MF_COUNTKILL)))) { float speed; angle = R_PointToAngle2(blockingMobj->pos[VX], blockingMobj->pos[VY], mo->pos[VX], mo->pos[VY]) + ANGLE_1 * ((P_Random() % 16) - 8); speed = P_ApproxDistance(mo->mom[MX], mo->mom[MY]); speed *= 0.75f; mo->angle = angle; angle >>= ANGLETOFINESHIFT; mo->mom[MX] = speed * FIX2FLT(finecosine[angle]); mo->mom[MY] = speed * FIX2FLT(finesine[angle]); if(mo->info->seeSound) S_StartSound(mo->info->seeSound, mo); return; } else { // Struck a player/creature P_ExplodeMissile(mo); } } else { // Struck a wall P_BounceWall(mo); switch(mo->type) { case MT_SORCBALL1: case MT_SORCBALL2: case MT_SORCBALL3: case MT_SORCFX1: break; default: if(mo->info->seeSound) S_StartSound(mo->info->seeSound, mo); break; } return; } } if(blockingMobj && (blockingMobj->flags2 & MF2_REFLECTIVE)) { angle = R_PointToAngle2(blockingMobj->pos[VX], blockingMobj->pos[VY], mo->pos[VX], mo->pos[VY]); // Change angle for delflection/reflection switch(blockingMobj->type) { case MT_CENTAUR: case MT_CENTAURLEADER: if(abs(angle - blockingMobj->angle) >> 24 > 45) goto explode; if(mo->type == MT_HOLY_FX) goto explode; // Drop through to sorcerer full reflection case MT_SORCBOSS: // Deflection if(P_Random() < 128) angle += ANGLE_45; else angle -= ANGLE_45; break; default: // Reflection angle += ANGLE_1 * ((P_Random() % 16) - 8); break; } // Reflect the missile along angle mo->angle = angle; angle >>= ANGLETOFINESHIFT; mo->mom[MX] = (mo->info->speed / 2) * FIX2FLT(finecosine[angle]); mo->mom[MY] = (mo->info->speed / 2) * FIX2FLT(finesine[angle]); if(mo->flags2 & MF2_SEEKERMISSILE) { mo->tracer = mo->target; } mo->target = blockingMobj; return; } explode: // Explode a missile //// kludge: Prevent missiles exploding against the sky. if(ceilingLine && (backSec = P_GetPtrp(ceilingLine, DMU_BACK_SECTOR))) { if((P_GetIntp(P_GetPtrp(backSec, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] > P_GetFloatp(backSec, DMU_CEILING_HEIGHT)) { if(mo->type == MT_BLOODYSKULL) { mo->mom[MX] = mo->mom[MY] = 0; mo->mom[MZ] = -1; } else if(mo->type == MT_HOLY_FX) { P_ExplodeMissile(mo); } else { P_MobjRemove(mo, false); } return; } } if(floorLine && (backSec = P_GetPtrp(floorLine, DMU_BACK_SECTOR))) { if((P_GetIntp(P_GetPtrp(backSec, DMU_FLOOR_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) && mo->pos[VZ] < P_GetFloatp(backSec, DMU_FLOOR_HEIGHT)) { if(mo->type == MT_BLOODYSKULL) { mo->mom[MX] = mo->mom[MY] = 0; mo->mom[MZ] = -1; } else if(mo->type == MT_HOLY_FX) { P_ExplodeMissile(mo); } else { P_MobjRemove(mo, false); } return; } } //// kludge end. P_ExplodeMissile(mo); } else { mo->mom[MX] = mo->mom[MY] = 0; } } } while(!INRANGE_OF(move[MX], 0, NOMOMENTUM_THRESHOLD) || !INRANGE_OF(move[MY], 0, NOMOMENTUM_THRESHOLD)); // Friction if(player && (P_GetPlayerCheats(player) & CF_NOMOMENTUM)) { // Debug option for no sliding at all mo->mom[MX] = mo->mom[MY] = 0; return; } if(mo->flags & (MF_MISSILE | MF_SKULLFLY)) return; // No friction for missiles if(mo->pos[VZ] > mo->floorZ && !(mo->flags2 & MF2_FLY) && !mo->onMobj) { // No friction when falling if(mo->type != MT_BLASTEFFECT) return; } if(mo->flags & MF_CORPSE) { // Don't stop sliding if halfway off a step with some momentum if(mo->mom[MX] > 1.0f / 4 || mo->mom[MX] < -1.0f / 4 || mo->mom[MY] > 1.0f / 4 || mo->mom[MY] < -1.0f / 4) { if(mo->floorZ != P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { return; } } } // Stop player walking animation. if((!player || (!(player->plr->cmd.forwardMove | player->plr->cmd.sideMove))) && INRANGE_OF(mo->mom[MX], 0, WALKSTOP_THRESHOLD) && INRANGE_OF(mo->mom[MY], 0, WALKSTOP_THRESHOLD)) { // If in a walking frame, stop moving if(player) { if((unsigned) ((player->plr->mo->state - STATES) - PCLASS_INFO(player->class)->runState) < 4) { P_MobjChangeState(player->plr->mo, PCLASS_INFO(player->class)->normalState); } } mo->mom[MX] = 0; mo->mom[MY] = 0; } else { float friction = P_MobjGetFriction(mo); mo->mom[MX] *= friction; mo->mom[MY] *= friction; } } /** * \todo Move this to p_inter *** */ void P_MonsterFallingDamage(mobj_t *mo) { int damage; float mom; mom = (int) fabs(mo->mom[MZ]); if(mom > 35) { // automatic death damage = 10000; } else { damage = (int) ((mom - 23) * 6); } damage = 10000; // always kill 'em. P_DamageMobj(mo, NULL, NULL, damage, false); } void P_MobjMoveZ(mobj_t *mo) { float gravity, dist, delta; // $democam: cameramen get special z movement if(P_CameraZMovement(mo)) return; gravity = P_GetGravity(); // Check for smooth step up. if(mo->player && mo->pos[VZ] < mo->floorZ) { mo->player->viewHeight -= mo->floorZ - mo->pos[VZ]; mo->player->viewHeightDelta = (cfg.plrViewHeight - mo->player->viewHeight) / 8; } // Adjust height. mo->pos[VZ] += mo->mom[MZ]; if((mo->flags & MF_FLOAT) && mo->target && !P_MobjIsCamera(mo->target)) { // Float down towards target if too close. if(!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) { dist = P_ApproxDistance(mo->pos[VX] - mo->target->pos[VX], mo->pos[VY] - mo->target->pos[VY]); delta = (mo->target->pos[VZ] + (mo->height /2)) - mo->pos[VZ]; if(delta < 0 && dist < -(delta * 3)) { mo->pos[VZ] -= FLOATSPEED; P_MobjSetSRVOZ(mo, -FLOATSPEED); } else if(delta > 0 && dist < (delta * 3)) { mo->pos[VZ] += FLOATSPEED; P_MobjSetSRVOZ(mo, FLOATSPEED); } } } if(mo->player && (mo->flags2 & MF2_FLY) && !(mo->pos[VZ] <= mo->floorZ) && (mapTime & 2)) { mo->pos[VZ] += FIX2FLT(finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]); } // Clip movement. if(mo->pos[VZ] <= mo->floorZ) { // Hit the floor statenum_t state; if(mo->flags & MF_MISSILE) { mo->pos[VZ] = mo->floorZ; if(mo->flags2 & MF2_FLOORBOUNCE) { P_FloorBounceMissile(mo); return; } else if(mo->type == MT_HOLY_FX) { // The spirit struck the ground. mo->mom[MZ] = 0; P_HitFloor(mo); return; } else if(mo->type == MT_MNTRFX2 || mo->type == MT_LIGHTNING_FLOOR) { // Minotaur floor fire can go up steps. return; } else { P_HitFloor(mo); P_ExplodeMissile(mo); return; } } if(mo->flags & MF_COUNTKILL) { // Blasted mobj falling. if(mo->mom[MZ] < -23) { P_MonsterFallingDamage(mo); } } if(mo->pos[VZ] - mo->mom[MZ] > mo->floorZ) { // Spawn splashes, etc. P_HitFloor(mo); } mo->pos[VZ] = mo->floorZ; if(mo->mom[MZ] < 0) { if((mo->flags2 & MF2_ICEDAMAGE) && mo->mom[MZ] < -gravity * 8) { mo->tics = 1; mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; return; } if(mo->player) { mo->player->jumpTics = 7; // delay any jumping for a short time if(mo->mom[MZ] < -gravity * 8 && !(mo->flags2 & MF2_FLY)) { // Squat down. mo->player->viewHeightDelta = mo->mom[MZ] / 8; if(mo->mom[MZ] < -23) { P_FallingDamage(mo->player); P_NoiseAlert(mo, mo); } else if(mo->mom[MZ] < -gravity * 12 && !mo->player->morphTics) { S_StartSound(SFX_PLAYER_LAND, mo); // Fix DOOM bug - dead players grunting when hitting the ground // (e.g., after an archvile attack) if(mo->player->health > 0) switch(mo->player->class) { case PCLASS_FIGHTER: S_StartSound(SFX_PLAYER_FIGHTER_GRUNT, mo); break; case PCLASS_CLERIC: S_StartSound(SFX_PLAYER_CLERIC_GRUNT, mo); break; case PCLASS_MAGE: S_StartSound(SFX_PLAYER_MAGE_GRUNT, mo); break; default: break; } } else if(!mo->player->morphTics) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(!(tt->flags & TTF_NONSOLID)) S_StartSound(SFX_PLAYER_LAND, mo); } if(!cfg.useMLook && cfg.lookSpring) mo->player->centering = true; } } else if(mo->type >= MT_POTTERY1 && mo->type <= MT_POTTERY3) { P_DamageMobj(mo, NULL, NULL, 25, false); } else if(mo->flags & MF_COUNTKILL) { if(mo->mom[MZ] < -23) { // Doesn't get here } } mo->mom[MZ] = 0; } if(mo->flags & MF_SKULLFLY) { // The skull slammed into something mo->mom[MZ] = -mo->mom[MZ]; } if((state = P_GetState(mo->type, SN_CRASH)) != S_NULL && (mo->flags & MF_CORPSE) && !(mo->flags2 & MF2_ICEDAMAGE)) { P_MobjChangeState(mo, state); return; } } else if(mo->flags2 & MF2_LOGRAV) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= gravity / 8; } else if(!(mo->flags & MF_NOGRAVITY)) { if(mo->mom[MZ] == 0) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; } if(mo->pos[VZ] + mo->height > mo->ceilingZ) { // hit the ceiling if(mo->mom[MZ] > 0) mo->mom[MZ] = 0; mo->pos[VZ] = mo->ceilingZ - mo->height; if(mo->flags2 & MF2_FLOORBOUNCE) { // Maybe reverse momentum here for ceiling bounce // Currently won't happen if(mo->info->seeSound) { S_StartSound(mo->info->seeSound, mo); } return; } if(mo->flags & MF_SKULLFLY) { // the skull slammed into something mo->mom[MZ] = -mo->mom[MZ]; } if(mo->flags & MF_MISSILE) { if(mo->type == MT_LIGHTNING_CEILING) return; if(P_GetIntp(P_GetPtrp(mo->subsector, DMU_CEILING_MATERIAL), DMU_FLAGS) & MATF_SKYMASK) { if(mo->type == MT_BLOODYSKULL) { mo->mom[MX] = mo->mom[MY] = 0; mo->mom[MZ] = -1; } else if(mo->type == MT_HOLY_FX) { P_ExplodeMissile(mo); } else { P_MobjRemove(mo, false); } return; } P_ExplodeMissile(mo); return; } } } static void landedOnThing(mobj_t* mo) { if(mo->player) return; // We are only interested in players. mo->player->viewHeightDelta = mo->mom[MZ] / 8; if(mo->mom[MZ] < -23) { P_FallingDamage(mo->player); P_NoiseAlert(mo, mo); } else if(mo->mom[MZ] < -P_GetGravity() * 12 && !mo->player->morphTics) { S_StartSound(SFX_PLAYER_LAND, mo); switch(mo->player->class) { case PCLASS_FIGHTER: S_StartSound(SFX_PLAYER_FIGHTER_GRUNT, mo); break; case PCLASS_CLERIC: S_StartSound(SFX_PLAYER_CLERIC_GRUNT, mo); break; case PCLASS_MAGE: S_StartSound(SFX_PLAYER_MAGE_GRUNT, mo); break; default: break; } } else if(!mo->player->morphTics) { S_StartSound(SFX_PLAYER_LAND, mo); } // Lookspring is stupid when mouselook is on (and not in demo). if(!cfg.useMLook && cfg.lookSpring) // || demorecording || demoplayback) mo->player->centering = true; } void P_MobjThinker(mobj_t* mobj) { if(mobj->ddFlags & DDMF_REMOTE) // Remote mobjs are handled separately. return; if(mobj->type == MT_MWAND_MISSILE || mobj->type == MT_CFLAME_MISSILE) { int i; float z, frac[3]; boolean changexy; // Handle movement. if(mobj->mom[MX] != 0 || mobj->mom[MY] != 0 || mobj->mom[MZ] != 0 || mobj->pos[VZ] != mobj->floorZ) { frac[VX] = mobj->mom[MX] / 8; frac[VY] = mobj->mom[MY] / 8; frac[VZ] = mobj->mom[MZ] / 8; changexy = (frac[VX] != 0 || frac[VY] != 0); for(i = 0; i < 8; ++i) { if(changexy) { if(!P_TryMove(mobj, mobj->pos[VX] + frac[VX], mobj->pos[VY] + frac[VY])) { // Blocked move. P_ExplodeMissile(mobj); return; } } mobj->pos[VZ] += frac[VZ]; if(mobj->pos[VZ] <= mobj->floorZ) { // Hit the floor. mobj->pos[VZ] = mobj->floorZ; P_HitFloor(mobj); P_ExplodeMissile(mobj); return; } if(mobj->pos[VZ] + mobj->height > mobj->ceilingZ) { // Hit the ceiling. mobj->pos[VZ] = mobj->ceilingZ - mobj->height; P_ExplodeMissile(mobj); return; } if(changexy) { if(mobj->type == MT_MWAND_MISSILE && (P_Random() < 128)) { z = mobj->pos[VZ] - 8; if(z < mobj->floorZ) { z = mobj->floorZ; } P_SpawnMobj3f(MT_MWANDSMOKE, mobj->pos[VX], mobj->pos[VY], z, P_Random() << 24, 0); } else if(!--mobj->special1) { mobj->special1 = 4; z = mobj->pos[VZ] - 12; if(z < mobj->floorZ) { z = mobj->floorZ; } P_SpawnMobj3f(MT_CFLAMEFLOOR, mobj->pos[VX], mobj->pos[VY], z, mobj->angle, 0); } } } } // Advance the state. if(mobj->tics != -1) { mobj->tics--; while(!mobj->tics) { if(!P_MobjChangeState(mobj, mobj->state->nextState)) return; // Mobj was removed. } } return; } // The first three bits of the selector special byte contain a // relative health level. P_UpdateHealthBits(mobj); // Handle X and Y momentums blockingMobj = NULL; if(mobj->mom[MX] != 0 || mobj->mom[MY] != 0 || (mobj->flags & MF_SKULLFLY)) { P_MobjMoveXY(mobj); if(mobj->thinker.function == NOPFUNC) { // Mobj was removed. return; } } else if(mobj->flags2 & MF2_BLASTED) { // Reset to not blasted when momentums are gone. ResetBlasted(mobj); } if(mobj->flags2 & MF2_FLOATBOB) { // Keep it on the floor. mobj->pos[VZ] = mobj->floorZ; // Negative floorclip raises the mobj off the floor. mobj->floorClip = -mobj->special1; if(mobj->floorClip < -MAX_BOB_OFFSET) { // We don't want it going through the floor. mobj->floorClip = -MAX_BOB_OFFSET; } } else if(mobj->pos[VZ] != mobj->floorZ || mobj->mom[MZ] != 0 || blockingMobj) { // Handle Z momentum and gravity if(mobj->flags2 & MF2_PASSMOBJ) { mobj->onMobj = P_CheckOnMobj(mobj); if(!mobj->onMobj) { P_MobjMoveZ(mobj); } else { if(mobj->mom[MZ] < -P_GetGravity() * 8 && !(mobj->flags2 & MF2_FLY)) { landedOnThing(mobj); } if(mobj->onMobj->pos[VZ] + mobj->onMobj->height - mobj->pos[VZ] <= 24) { if(mobj->player) { mobj->player->viewHeight -= mobj->onMobj->pos[VZ] + mobj->onMobj->height - mobj->pos[VZ]; mobj->player->viewHeightDelta = (cfg.plrViewHeight - mobj->player->viewHeight) / 8; } mobj->pos[VZ] = mobj->onMobj->pos[VZ] + mobj->onMobj->height; mobj->mom[MZ] = 0; } else { // hit the bottom of the blocking mobj mobj->mom[MZ] = 0; } } } else { P_MobjMoveZ(mobj); } if(mobj->thinker.function == NOPFUNC) { // mobj was removed return; } } // Cycle through states, calling action functions at transitions. if(mobj->tics != -1) { mobj->tics--; P_MobjAngleSRVOTicker(mobj); // You can cycle through multiple states in a tic. while(!mobj->tics) { P_MobjClearSRVO(mobj); if(!P_MobjChangeState(mobj, mobj->state->nextState)) { // Mobj was removed. return; } } } // Ice corpses aren't going anywhere. if(mobj->flags & MF_ICECORPSE) P_MobjSetSRVO(mobj, 0, 0); } mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags) { mobj_t* mo; mobjinfo_t* info; float space; int ddflags = 0; if(type == MT_ZLYNCHED_NOHEART) { type = MT_BLOODPOOL; angle = 0; spawnFlags |= MSF_Z_FLOOR; } if(type < MT_FIRST || type >= Get(DD_NUMMOBJTYPES)) { #ifdef _DEBUG Con_Error("P_SpawnMobj: Illegal mo type %i.\n", type); #endif return NULL; } info = &MOBJINFO[type]; // Clients only spawn local objects. if(!(info->flags & MF_LOCAL) && IS_CLIENT) return NULL; // Not for deathmatch? if(deathmatch && (info->flags & MF_NOTDMATCH)) return NULL; // Don't spawn any monsters if -noMonstersParm. if(noMonstersParm && (info->flags & MF_COUNTKILL)) return NULL; if(info->flags & MF_SOLID) ddflags |= DDMF_SOLID; if(info->flags2 & MF2_DONTDRAW) ddflags |= DDMF_DONTDRAW; mo = P_MobjCreate(P_MobjThinker, x, y, z, angle, info->radius, info->height, ddflags); mo->type = type; mo->info = info; mo->flags = info->flags; mo->flags2 = info->flags2; mo->flags3 = info->flags3; // This doesn't appear to actually be used see P_DamageMobj in P_inter.c mo->damage = info->damage; mo->health = info->spawnHealth * (IS_NETGAME ? cfg.netMobHealthModifier : 1); mo->moveDir = DI_NODIR; if(gameSkill != SM_NIGHTMARE) { mo->reactionTime = info->reactionTime; } mo->lastLook = P_Random() % MAXPLAYERS; // Must link before setting state. P_MobjSetState(mo, P_GetState(mo->type, SN_SPAWN)); // Set subsector and/or block links. P_MobjSetPosition(mo); mo->floorZ = P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT); mo->ceilingZ = P_GetFloatp(mo->subsector, DMU_CEILING_HEIGHT); if((spawnFlags & MSF_Z_CEIL) || (info->flags & MF_SPAWNCEILING)) { mo->pos[VZ] = mo->ceilingZ - mo->info->height - z; } else if((spawnFlags & MSF_Z_RANDOM) || (info->flags2 & MF2_SPAWNFLOAT)) { space = mo->ceilingZ - mo->info->height - mo->floorZ; if(space > 48) { space -= 40; mo->pos[VZ] = ((space * P_Random()) / 256) + mo->floorZ + 40; } else { mo->pos[VZ] = mo->floorZ; } } else if(spawnFlags & MSF_Z_FLOOR) { mo->pos[VZ] = mo->floorZ + z; } if(spawnFlags & MSF_AMBUSH) { mo->flags |= MF_AMBUSH; } mo->floorClip = 0; if((mo->flags2 & MF2_FLOORCLIP) && mo->pos[VZ] == P_GetFloatp(mo->subsector, DMU_FLOOR_HEIGHT)) { const terraintype_t* tt = P_MobjGetFloorTerrainType(mo); if(tt->flags & TTF_FLOORCLIP) mo->floorClip = 10; } if(spawnFlags & MTF_DORMANT) { mo->flags2 |= MF2_DORMANT; if(mo->type == MT_ICEGUY) P_MobjChangeState(mo, S_ICEGUY_DORMANT); mo->tics = -1; } return mo; } mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags) { return P_SpawnMobj3f(type, pos[VX], pos[VY], pos[VZ], angle, spawnFlags); } static boolean addToTIDList(thinker_t* th, void* context) { size_t* count = (size_t*) context; mobj_t* mo = (mobj_t *) th; if(mo->tid != 0) { // Add to list. if(*count == MAX_TID_COUNT) { Con_Error("P_CreateTIDList: MAX_TID_COUNT (%d) exceeded.", MAX_TID_COUNT); } TIDList[*count] = mo->tid; TIDMobj[(*count)++] = mo; } return true; // Continue iteration. } void P_CreateTIDList(void) { size_t count = 0; DD_IterateThinkers(P_MobjThinker, addToTIDList, &count); // Add termination marker TIDList[count] = 0; } void P_MobjInsertIntoTIDList(mobj_t* mobj, int tid) { int i, index; index = -1; for(i = 0; TIDList[i] != 0; ++i) { if(TIDList[i] == -1) { // Found empty slot index = i; break; } } if(index == -1) { // Append required if(i == MAX_TID_COUNT) { Con_Error("P_MobjInsertIntoTIDList: MAX_TID_COUNT (%d)" "exceeded.", MAX_TID_COUNT); } index = i; TIDList[index + 1] = 0; } mobj->tid = tid; TIDList[index] = tid; TIDMobj[index] = mobj; } void P_MobjRemoveFromTIDList(mobj_t* mobj) { int i; if(!mobj->tid) return; for(i = 0; TIDList[i] != 0; ++i) { if(TIDMobj[i] == mobj) { TIDList[i] = -1; TIDMobj[i] = NULL; mobj->tid = 0; return; } } mobj->tid = 0; } mobj_t* P_FindMobjFromTID(int tid, int* searchPosition) { int i; for(i = *searchPosition + 1; TIDList[i] != 0; ++i) { if(TIDList[i] == tid) { *searchPosition = i; return TIDMobj[i]; } } *searchPosition = -1; return NULL; } void P_SpawnPuff(float x, float y, float z, angle_t angle) { mobj_t* puff; z += FIX2FLT((P_Random() - P_Random()) << 10); if((puff = P_SpawnMobj3f(PuffType, x, y, z, angle, 0))) { if(lineTarget && puff->info->seeSound) { // Hit thing sound. S_StartSound(puff->info->seeSound, puff); } else if(puff->info->attackSound) { S_StartSound(puff->info->attackSound, puff); } switch(PuffType) { case MT_PUNCHPUFF: puff->mom[MZ] = 1; break; case MT_HAMMERPUFF: puff->mom[MZ] = .8f; break; default: break; } } puffSpawned = puff; } void P_SpawnBloodSplatter(float x, float y, float z, mobj_t* originator) { mobj_t* mo; if((mo = P_SpawnMobj3f(MT_BLOODSPLATTER, x, y, z, P_Random() << 24, 0))) { mo->target = originator; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MZ] = 3; } } void P_SpawnBloodSplatter2(float x, float y, float z, mobj_t* originator) { mobj_t* mo; if((mo = P_SpawnMobj3f(MT_AXEBLOOD, x + FIX2FLT((P_Random() - 128) << 11), y + FIX2FLT((P_Random() - 128) << 11), z, P_Random() << 24, 0))) { mo->target = originator; } } boolean P_HitFloor(mobj_t *thing) { mobj_t* mo; int smallsplash = false; const terraintype_t* tt; if(thing->floorZ != P_GetFloatp(thing->subsector, DMU_FLOOR_HEIGHT)) { // Don't splash if landing on the edge above water/lava/etc.... return false; } // Things that don't splash go here switch(thing->type) { case MT_LEAF1: case MT_LEAF2: case MT_SPLASH: case MT_SLUDGECHUNK: return false; default: if(P_MobjIsCamera(thing)) return false; break; } // Small splash for small masses. if(thing->info->mass < 10) smallsplash = true; tt = P_MobjGetFloorTerrainType(thing); if(tt->flags & TTF_SPAWN_SPLASHES) { if(smallsplash) { if((mo = P_SpawnMobj3f(MT_SPLASHBASE, thing->pos[VX], thing->pos[VY], 0, thing->angle + ANG180, MSF_Z_FLOOR))) { mo->floorClip += SMALLSPLASHCLIP; S_StartSound(SFX_AMBIENT10, mo); // small drip } } else { if((mo = P_SpawnMobj3f(MT_SPLASH, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR))) { mo->target = thing; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MZ] = 2 + FIX2FLT(P_Random() << 8); mo = P_SpawnMobj3f(MT_SPLASHBASE, thing->pos[VX], thing->pos[VY], 0, thing->angle + ANG180, MSF_Z_FLOOR); S_StartSound(SFX_WATER_SPLASH, mo); } if(thing->player) P_NoiseAlert(thing, thing); } return true; } else if(tt->flags & TTF_SPAWN_SMOKE) { if(smallsplash) { if((mo = P_SpawnMobj3f(MT_LAVASPLASH, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR))) mo->floorClip += SMALLSPLASHCLIP; } else { if((mo = P_SpawnMobj3f(MT_LAVASMOKE, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR))) { mo->mom[MZ] = 1 + FIX2FLT(P_Random() << 7); mo = P_SpawnMobj3f(MT_LAVASPLASH, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR); } if(thing->player) P_NoiseAlert(thing, thing); } S_StartSound(SFX_LAVA_SIZZLE, mo); if(thing->player && mapTime & 31) { P_DamageMobj(thing, &lavaInflictor, NULL, 5, false); } return true; } else if(tt->flags & TTF_SPAWN_SLUDGE) { mo = NULL; if(smallsplash) { if((mo = P_SpawnMobj3f(MT_SLUDGESPLASH, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR))) { mo->floorClip += SMALLSPLASHCLIP; } } else { if((mo = P_SpawnMobj3f(MT_SLUDGECHUNK, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR))) { mo->target = thing; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 8); mo->mom[MZ] = 1 + FIX2FLT(P_Random() << 8); } mo = P_SpawnMobj3f(MT_SLUDGESPLASH, thing->pos[VX], thing->pos[VY], 0, P_Random() << 24, MSF_Z_FLOOR); if(thing->player) P_NoiseAlert(thing, thing); } S_StartSound(SFX_SLUDGE_GLOOP, mo); return true; } return false; } void ResetBlasted(mobj_t *mo) { mo->flags2 &= ~MF2_BLASTED; if(!(mo->flags & MF_ICECORPSE)) { mo->flags2 &= ~MF2_SLIDE; } } void P_BlastMobj(mobj_t *source, mobj_t *victim, float strength) { uint an; angle_t angle; mobj_t *mo; float pos[3]; angle = R_PointToAngle2(source->pos[VX], source->pos[VY], victim->pos[VX], victim->pos[VY]); an = angle >> ANGLETOFINESHIFT; if(strength < BLAST_FULLSTRENGTH) { victim->mom[MX] = strength * FIX2FLT(finecosine[an]); victim->mom[MY] = strength * FIX2FLT(finesine[an]); if(victim->player) { // Players handled automatically. } else { victim->flags2 |= MF2_SLIDE; victim->flags2 |= MF2_BLASTED; } } else // Full strength. { if(victim->flags & MF_MISSILE) { switch(victim->type) { case MT_SORCBALL1: // Don't blast sorcerer balls. case MT_SORCBALL2: case MT_SORCBALL3: return; break; case MT_MSTAFF_FX2: // Reflect to originator. victim->tracer = victim->target; victim->target = source; break; default: break; } } if(victim->type == MT_HOLY_FX) { if(victim->tracer == source) { victim->tracer = victim->target; victim->target = source; } } victim->mom[MX] = BLAST_SPEED * FIX2FLT(finecosine[an]); victim->mom[MY] = BLAST_SPEED * FIX2FLT(finesine[an]); // Spawn blast puff. angle = R_PointToAngle2(victim->pos[VX], victim->pos[VY], source->pos[VX], source->pos[VY]); an = angle >> ANGLETOFINESHIFT; pos[VX] = victim->pos[VX]; pos[VY] = victim->pos[VY]; pos[VZ] = victim->pos[VZ] - victim->floorClip + victim->height / 2; pos[VX] += (victim->radius + FIX2FLT(FRACUNIT)) * FIX2FLT(finecosine[an]); pos[VY] += (victim->radius + FIX2FLT(FRACUNIT)) * FIX2FLT(finesine[an]); if((mo = P_SpawnMobj3fv(MT_BLASTEFFECT, pos, angle, 0))) { mo->mom[MX] = victim->mom[MX]; mo->mom[MY] = victim->mom[MY]; } if((victim->flags & MF_MISSILE)) { victim->mom[MZ] = 8; if(mo) mo->mom[MZ] = victim->mom[MZ]; } else { victim->mom[MZ] = 1000 / victim->info->mass; } if(victim->player) { // Players handled automatically } else { victim->flags2 |= MF2_SLIDE; victim->flags2 |= MF2_BLASTED; } } } typedef struct { float maxDistance; mobj_t* source; } radiusblastparams_t; static boolean radiusBlast(thinker_t* th, void* context) { radiusblastparams_t* params = (radiusblastparams_t*) context; mobj_t* mo = (mobj_t *) th; float dist; if(mo == params->source || (mo->flags2 & MF2_BOSS)) return true; // Continue iteration. if(mo->type == MT_POISONCLOUD || // poison cloud. mo->type == MT_HOLY_FX || // holy fx. (mo->flags & MF_ICECORPSE)) // frozen corpse. { // Let these special cases go. } else if((mo->flags & MF_COUNTKILL) && mo->health <= 0) { return true; // Continue iteration. } else if(!(mo->flags & MF_COUNTKILL) && !mo->player && !(mo->flags & MF_MISSILE)) { // Must be monster, player, or missile. return true; // Continue iteration. } // Is this mobj dormant? if(mo->flags2 & MF2_DORMANT) return true; // Continue iteration. // Is this an underground Wraith? if(mo->type == MT_WRAITHB && (mo->flags2 & MF2_DONTDRAW)) return true; // Continue iteration. if(mo->type == MT_SPLASHBASE || mo->type == MT_SPLASH) return true; // Continue iteration. if(mo->type == MT_SERPENT || mo->type == MT_SERPENTLEADER) return true; // Continue iteration. // Within range? dist = P_ApproxDistance(params->source->pos[VX] - mo->pos[VX], params->source->pos[VY] - mo->pos[VY]); if(dist <= params->maxDistance) { P_BlastMobj(params->source, mo, BLAST_FULLSTRENGTH); } return true; // Continue iteration. } /** * Blast all mobjs away. */ void P_BlastRadius(player_t* pl) { mobj_t* pmo = pl->plr->mo; radiusblastparams_t params; S_StartSound(SFX_INVITEM_BLAST, pmo); P_NoiseAlert(pmo, pmo); params.source = pmo; params.maxDistance = BLAST_RADIUS_DIST; DD_IterateThinkers(P_MobjThinker, radiusBlast, ¶ms); } typedef struct { float origin[2]; float maxDistance; boolean effective; } radiusgiveparams_t; static boolean radiusGiveArmor(thinker_t* th, void* context) { radiusgiveparams_t* params = (radiusgiveparams_t*) context; mobj_t* mo = (mobj_t *) th; float dist; if(!mo->player || mo->health <= 0) return true; // Continue iteration. // Within range? dist = P_ApproxDistance(params->origin[VX] - mo->pos[VX], params->origin[VY] - mo->pos[VY]); if(dist <= params->maxDistance) { if((P_GiveArmor2(mo->player, ARMOR_ARMOR, 1)) || (P_GiveArmor2(mo->player, ARMOR_SHIELD, 1)) || (P_GiveArmor2(mo->player, ARMOR_HELMET, 1)) || (P_GiveArmor2(mo->player, ARMOR_AMULET, 1))) { params->effective = true; S_StartSound(SFX_MYSTICINCANT, mo); } } return true; // Continue iteration. } static boolean radiusGiveBody(thinker_t* th, void* context) { radiusgiveparams_t* params = (radiusgiveparams_t*) context; mobj_t* mo = (mobj_t *) th; float dist; if(!mo->player || mo->health <= 0) return true; // Continue iteration. // Within range? dist = P_ApproxDistance(params->origin[VX] - mo->pos[VX], params->origin[VY] - mo->pos[VY]); if(dist <= params->maxDistance) { int amount = 50 + (P_Random() % 50); if(P_GiveBody(mo->player, amount)) { params->effective = true; S_StartSound(SFX_MYSTICINCANT, mo); } } return true; // Continue iteration. } static boolean radiusGiveMana(thinker_t* th, void* context) { radiusgiveparams_t* params = (radiusgiveparams_t*) context; mobj_t* mo = (mobj_t *) th; float dist; if(!mo->player || mo->health <= 0) return true; // Continue iteration. // Within range? dist = P_ApproxDistance(params->origin[VX] - mo->pos[VX], params->origin[VY] - mo->pos[VY]); if(dist <= params->maxDistance) { int amount = 50 + (P_Random() % 50); if((P_GiveMana(mo->player, AT_BLUEMANA, amount)) || (P_GiveMana(mo->player, AT_GREENMANA, amount))) { params->effective = true; S_StartSound(SFX_MYSTICINCANT, mo); } } return true; // Continue iteration. } /** * Do class specific effect for everyone in radius */ boolean P_HealRadius(player_t* player) { mobj_t* pmo = player->plr->mo; radiusgiveparams_t params; params.effective = false; params.origin[VX] = pmo->pos[VX]; params.origin[VY] = pmo->pos[VY]; params.maxDistance = HEAL_RADIUS_DIST; switch(player->class) { case PCLASS_FIGHTER: DD_IterateThinkers(P_MobjThinker, radiusGiveArmor, ¶ms); break; case PCLASS_CLERIC: DD_IterateThinkers(P_MobjThinker, radiusGiveBody, ¶ms); break; case PCLASS_MAGE: DD_IterateThinkers(P_MobjThinker, radiusGiveMana, ¶ms); break; default: break; } return params.effective; } /** * @return @c true, if the missile is at a valid spawn point, * otherwise explodes it and return @c false. */ boolean P_CheckMissileSpawn(mobj_t *missile) { // Move a little forward so an angle can be computed if it // immediately explodes missile->pos[VX] += missile->mom[MX] / 2; missile->pos[VY] += missile->mom[MY] / 2; missile->pos[VZ] += missile->mom[MZ] / 2; if(!P_TryMove(missile, missile->pos[VX], missile->pos[VY])) { P_ExplodeMissile(missile); return false; } return true; } /** * @return @c NULL, if the missile exploded immediately, * otherwise returns a mobj_t pointer to the spawned * missile. */ mobj_t *P_SpawnMissile(mobjtype_t type, mobj_t *source, mobj_t *dest) { uint an; float z; mobj_t *th; angle_t angle; float aim, dist, origdist; switch(type) { case MT_MNTRFX1: // Minotaur swing attack missile z = source->pos[VZ] + 40; break; case MT_MNTRFX2: // Minotaur floor fire missile z = source->floorZ; break; case MT_CENTAUR_FX: z = source->pos[VZ] + 45; break; case MT_ICEGUY_FX: z = source->pos[VZ] + 40; break; case MT_HOLY_MISSILE: z = source->pos[VZ] + 40; break; default: z = source->pos[VZ] + 32; break; } z -= source->floorClip; angle = R_PointToAngle2(source->pos[VX], source->pos[VY], dest->pos[VX], dest->pos[VY]); if(dest->flags & MF_SHADOW) { // Invisible target angle += (P_Random() - P_Random()) << 21; } if(!(th = P_SpawnMobj3f(type, source->pos[VX], source->pos[VY], z, angle, 0))) return NULL; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Originator an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); origdist = P_ApproxDistance(dest->pos[VX] - source->pos[VX], dest->pos[VY] - source->pos[VY]); dist = origdist / th->info->speed; if(dist < 1) dist = 1; th->mom[MZ] = (dest->pos[VZ] - source->pos[VZ]) / dist; // Use a more three-dimensional method. aim = BANG2RAD(bamsAtan2 ((int) (dest->pos[VZ] - source->pos[VZ]), (int) origdist)); th->mom[MX] *= cos(aim); th->mom[MY] *= cos(aim); th->mom[MZ] = sin(aim) * th->info->speed; if(P_CheckMissileSpawn(th)) return th; return NULL; } /** * @return @c NULL, if the missile exploded immediately, * otherwise returns a mobj_t pointer to the spawned * missile. */ mobj_t *P_SpawnMissileXYZ(mobjtype_t type, float x, float y, float z, mobj_t *source, mobj_t *dest) { uint an; mobj_t *th; angle_t angle; float dist; z -= source->floorClip; angle = R_PointToAngle2(source->pos[VX], source->pos[VY], dest->pos[VX], dest->pos[VY]); if(dest->flags & MF_SHADOW) { // Invisible target angle += (P_Random() - P_Random()) << 21; } if(!(th = P_SpawnMobj3f(type, x, y, z, angle, 0))) return NULL; if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Originator an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); dist = P_ApproxDistance(dest->pos[VX] - source->pos[VX], dest->pos[VY] - source->pos[VY]); dist /= th->info->speed; if(dist < 1) dist = 1; th->mom[MZ] = (dest->pos[VZ] - source->pos[VZ]) / dist; if(P_CheckMissileSpawn(th)) return th; return NULL; } /** * @return @c NULL, if the missile exploded immediately, * otherwise returns a mobj_t pointer to the spawned * missile. */ mobj_t* P_SpawnMissileAngle(mobjtype_t type, mobj_t* source, angle_t angle, float momz) { unsigned int an; float pos[3], spawnZOff = 0; mobj_t* mo; memcpy(pos, source->pos, sizeof(pos)); switch(type) { case MT_MNTRFX1: // Minotaur swing attack missile spawnZOff = 40; break; case MT_ICEGUY_FX2: // Secondary Projectiles of the Ice Guy spawnZOff = 3; break; case MT_MSTAFF_FX2: spawnZOff = 40; break; default: if(source->player) { if(!P_MobjIsCamera(source->player->plr->mo)) spawnZOff = cfg.plrViewHeight - 9 + source->player->plr->lookDir / 173; } else { spawnZOff = 32; } break; } if(type == MT_MNTRFX2) // Minotaur floor fire missile { mo = P_SpawnMobj3f(type, pos[VX], pos[VY], 0, angle, MSF_Z_FLOOR); } else { pos[VZ] += spawnZOff; pos[VZ] -= source->floorClip; mo = P_SpawnMobj3fv(type, pos, angle, 0); } if(mo) { if(mo->info->seeSound) S_StartSound(mo->info->seeSound, mo); mo->target = source; // Originator an = angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); mo->mom[MZ] = momz; return (P_CheckMissileSpawn(mo) ? mo : NULL); } return NULL; } /** * @return @c NULL, if the missile exploded immediately, * otherwise returns a mobj_t pointer to the spawned * missile. */ mobj_t *P_SpawnMissileAngleSpeed(mobjtype_t type, mobj_t *source, angle_t angle, float momz, float speed) { unsigned int an; float z; mobj_t* mo; z = source->pos[VZ]; z -= source->floorClip; mo = P_SpawnMobj3f(type, source->pos[VX], source->pos[VY], z, angle, 0); if(mo) { mo->target = source; // Originator an = angle >> ANGLETOFINESHIFT; mo->mom[MX] = speed * FIX2FLT(finecosine[an]); mo->mom[MY] = speed * FIX2FLT(finesine[an]); mo->mom[MZ] = momz; return (P_CheckMissileSpawn(mo) ? mo : NULL); } return NULL; } /** * Tries to aim at a nearby monster. */ mobj_t *P_SpawnPlayerMissile(mobjtype_t type, mobj_t *source) { uint an; angle_t angle; float pos[3], slope; float fangle = LOOKDIR2RAD(source->player->plr->lookDir); float movfac = 1; boolean dontAim = cfg.noAutoAim; int spawnFlags = 0; // Try to find a target angle = source->angle; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget || dontAim) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget || dontAim) { angle = source->angle; slope = sin(fangle) / 1.2; movfac = cos(fangle); } } memcpy(pos, source->pos, sizeof(pos)); if(type == MT_LIGHTNING_FLOOR) { pos[VZ] = 0; slope = 0; spawnFlags |= MSF_Z_FLOOR; } else if(type == MT_LIGHTNING_CEILING) { pos[VZ] = 0; slope = 0; spawnFlags |= MSF_Z_CEIL; } else { if(!P_MobjIsCamera(source->player->plr->mo)) pos[VZ] += cfg.plrViewHeight - 9 + (source->player->plr->lookDir / 173); pos[VZ] -= source->floorClip; } if(!(MissileMobj = P_SpawnMobj3fv(type, pos, angle, spawnFlags))) return NULL; MissileMobj->target = source; an = angle >> ANGLETOFINESHIFT; MissileMobj->mom[MX] = movfac * MissileMobj->info->speed * FIX2FLT(finecosine[an]); MissileMobj->mom[MY] = movfac * MissileMobj->info->speed * FIX2FLT(finesine[an]); MissileMobj->mom[MZ] = MissileMobj->info->speed * slope; if(MissileMobj->type == MT_MWAND_MISSILE || MissileMobj->type == MT_CFLAME_MISSILE) { // Ultra-fast ripper spawning missile MissileMobj->pos[VX] += MissileMobj->mom[MX] / 8; MissileMobj->pos[VY] += MissileMobj->mom[MY] / 8; MissileMobj->pos[VZ] += MissileMobj->mom[MZ] / 8; } else { // Normal missile MissileMobj->pos[VX] += MissileMobj->mom[MX] / 2; MissileMobj->pos[VY] += MissileMobj->mom[MY] / 2; MissileMobj->pos[VZ] += MissileMobj->mom[MZ] / 2; } if(!P_TryMove(MissileMobj, MissileMobj->pos[VX], MissileMobj->pos[VY])) { // Exploded immediately P_ExplodeMissile(MissileMobj); return NULL; } return MissileMobj; } mobj_t *P_SPMAngle(mobjtype_t type, mobj_t *source, angle_t origAngle) { uint an; angle_t angle; mobj_t *th; float pos[3], slope; float fangle = LOOKDIR2RAD(source->player->plr->lookDir); float movfac = 1; boolean dontAim = cfg.noAutoAim; // See which target is to be aimed at. angle = origAngle; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget || dontAim) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget || dontAim) { angle = origAngle; slope = sin(fangle) / 1.2; movfac = cos(fangle); } } memcpy(pos, source->pos, sizeof(pos)); if(!P_MobjIsCamera(source->player->plr->mo)) pos[VZ] += cfg.plrViewHeight - 9 + (source->player->plr->lookDir / 173); pos[VZ] -= source->floorClip; if((th = P_SpawnMobj3fv(type, pos, angle, 0))) { th->target = source; an = angle >> ANGLETOFINESHIFT; th->mom[MX] = movfac * th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = movfac * th->info->speed * FIX2FLT(finesine[an]); th->mom[MZ] = th->info->speed * slope; if(P_CheckMissileSpawn(th)) return th; } return NULL; } mobj_t* P_SPMAngleXYZ(mobjtype_t type, float x, float y, float z, mobj_t* source, angle_t origAngle) { uint an; mobj_t* th; angle_t angle; float slope, movfac = 1; float fangle = LOOKDIR2RAD(source->player->plr->lookDir); boolean dontAim = cfg.noAutoAim; // See which target is to be aimed at. angle = origAngle; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget || dontAim) { angle += 1 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); if(!lineTarget) { angle -= 2 << 26; slope = P_AimLineAttack(source, angle, 16 * 64); } if(!lineTarget || dontAim) { angle = origAngle; slope = sin(fangle) / 1.2; movfac = cos(fangle); } } if(!P_MobjIsCamera(source->player->plr->mo)) z += cfg.plrViewHeight - 9 + (source->player->plr->lookDir / 173); z -= source->floorClip; if((th = P_SpawnMobj3f(type, x, y, z, angle, 0))) { th->target = source; an = angle >> ANGLETOFINESHIFT; th->mom[MX] = movfac * th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = movfac * th->info->speed * FIX2FLT(finesine[an]); th->mom[MZ] = th->info->speed * slope; if(P_CheckMissileSpawn(th)) return th; } return NULL; } mobj_t* P_SpawnKoraxMissile(mobjtype_t type, float x, float y, float z, mobj_t* source, mobj_t* dest) { uint an; mobj_t *th; angle_t angle; float dist; z -= source->floorClip; angle = R_PointToAngle2(x, y, dest->pos[VX], dest->pos[VY]); if(dest->flags & MF_SHADOW) { // Invisible target angle += (P_Random() - P_Random()) << 21; } if((th = P_SpawnMobj3f(type, x, y, z, angle, 0))) { if(th->info->seeSound) S_StartSound(th->info->seeSound, th); th->target = source; // Originator an = angle >> ANGLETOFINESHIFT; th->mom[MX] = th->info->speed * FIX2FLT(finecosine[an]); th->mom[MY] = th->info->speed * FIX2FLT(finesine[an]); dist = P_ApproxDistance(dest->pos[VX] - x, dest->pos[VY] - y); dist /= th->info->speed; if(dist < 1) dist = 1; th->mom[MZ] = (dest->pos[VZ] - z + 30) / dist; if(P_CheckMissileSpawn(th)) return th; } return NULL; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_pillar.c0000644000175000017500000001666511357170242022602 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pillar.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "dmu_lib.h" #include "p_mapspec.h" #include "p_iterlist.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void T_BuildPillar(pillar_t *pillar) { result_e res1; result_e res2; // First, raise the floor res1 = T_MovePlane(pillar->sector, pillar->floorSpeed, pillar->floorDest, pillar->crush, 0, pillar->direction); // floorOrCeiling, direction // Then, lower the ceiling res2 = T_MovePlane(pillar->sector, pillar->ceilingSpeed, pillar->ceilingDest, pillar->crush, 1, -pillar->direction); if(res1 == pastdest && res2 == pastdest) { P_ToXSector(pillar->sector)->specialData = NULL; SN_StopSequence(P_GetPtrp(pillar->sector, DMU_SOUND_ORIGIN)); P_TagFinished(P_ToXSector(pillar->sector)->tag); DD_ThinkerRemove(&pillar->thinker); } } int EV_BuildPillar(linedef_t *line, byte *args, boolean crush) { int rtn = 0; float newHeight; sector_t *sec = NULL; pillar_t *pillar; iterlist_t *list; list = P_GetSectorIterListForTag((int) args[0], false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(P_ToXSector(sec)->specialData) continue; // Already moving, so keep going. if(P_GetFloatp(sec, DMU_FLOOR_HEIGHT) == P_GetFloatp(sec, DMU_CEILING_HEIGHT)) continue; // Pillar is already closed. rtn = 1; if(!args[2]) { newHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + ((P_GetFloatp(sec, DMU_CEILING_HEIGHT) - P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) * .5f); } else { newHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) + (float) args[2]; } pillar = Z_Calloc(sizeof(*pillar), PU_MAP, 0); pillar->thinker.function = T_BuildPillar; DD_ThinkerAdd(&pillar->thinker); P_ToXSector(sec)->specialData = pillar; pillar->sector = sec; if(!args[2]) { pillar->ceilingSpeed = pillar->floorSpeed = (float) args[1] * (1.0f / 8); } else if(newHeight - P_GetFloatp(sec, DMU_FLOOR_HEIGHT) > P_GetFloatp(sec, DMU_CEILING_HEIGHT) - newHeight) { pillar->floorSpeed = (float) args[1] * (1.0f / 8); pillar->ceilingSpeed = (P_GetFloatp(sec, DMU_CEILING_HEIGHT) - newHeight) * (pillar->floorSpeed / (newHeight - P_GetFloatp(sec, DMU_FLOOR_HEIGHT))); } else { pillar->ceilingSpeed = (float) args[1] * (1.0f / 8); pillar->floorSpeed = (newHeight - P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) * (pillar->ceilingSpeed / (P_GetFloatp(sec, DMU_CEILING_HEIGHT) - newHeight)); } pillar->floorDest = newHeight; pillar->ceilingDest = newHeight; pillar->direction = 1; pillar->crush = crush * (int) args[3]; SN_StartSequence(P_GetPtrp(pillar->sector, DMU_SOUND_ORIGIN), SEQ_PLATFORM + P_ToXSector(pillar->sector)->seqType); } return rtn; } int EV_OpenPillar(linedef_t *line, byte *args) { int rtn = 0; sector_t *sec = NULL; pillar_t *pillar; iterlist_t *list; list = P_GetSectorIterListForTag((int) args[0], false); if(!list) return rtn; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(P_ToXSector(sec)->specialData) continue; // Already moving, so keep going... if(P_GetFloatp(sec, DMU_FLOOR_HEIGHT) != P_GetFloatp(sec, DMU_CEILING_HEIGHT)) continue; // Pillar isn't closed. rtn = 1; pillar = Z_Calloc(sizeof(*pillar), PU_MAP, 0); pillar->thinker.function = T_BuildPillar; DD_ThinkerAdd(&pillar->thinker); P_ToXSector(sec)->specialData = pillar; pillar->sector = sec; if(!args[2]) { P_FindSectorSurroundingLowestFloor(sec, P_GetFloatp(sec, DMU_FLOOR_HEIGHT), &pillar->floorDest); } else { pillar->floorDest = P_GetFloatp(sec, DMU_FLOOR_HEIGHT) - (float) args[2]; } if(!args[3]) { P_FindSectorSurroundingHighestCeiling(sec, 0, &pillar->ceilingDest); } else { pillar->ceilingDest = P_GetFloatp(sec, DMU_CEILING_HEIGHT) + (float) args[3]; } if(P_GetFloatp(sec, DMU_FLOOR_HEIGHT) - pillar->floorDest >= pillar->ceilingDest - P_GetFloatp(sec, DMU_CEILING_HEIGHT)) { pillar->floorSpeed = (float) args[1] * (1.0f / 8); pillar->ceilingSpeed = (P_GetFloatp(sec, DMU_CEILING_HEIGHT) - pillar->ceilingDest) * (pillar->floorSpeed / (pillar->floorDest - P_GetFloatp(sec, DMU_FLOOR_HEIGHT))); } else { pillar->ceilingSpeed = (float) args[1] * (1.0f / 8); pillar->floorSpeed = (pillar->floorDest - P_GetFloatp(sec, DMU_FLOOR_HEIGHT)) * (pillar->ceilingSpeed / (P_GetFloatp(sec, DMU_CEILING_HEIGHT) - pillar->ceilingDest)); } pillar->direction = -1; // Open the pillar. SN_StartSequence(P_GetPtrp(pillar->sector, DMU_SOUND_ORIGIN), SEQ_PLATFORM + P_ToXSector(pillar->sector)->seqType); } return rtn; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/st_stuff.c0000644000175000017500000014230311357170242022622 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "st_lib.h" #include "d_net.h" #include "p_tick.h" // for P_IsPaused #include "am_map.h" #include "g_common.h" #include "p_inventory.h" #include "hu_inventory.h" // MACROS ------------------------------------------------------------------ // Inventory #define ST_INVENTORYX (50) #define ST_INVENTORYY (163) // Current inventory item. #define ST_INVITEMX (143) #define ST_INVITEMY (163) // Current inventory item count. #define ST_INVITEMCWIDTH (2) // Num digits #define ST_INVITEMCX (174) #define ST_INVITEMCY (184) // HEALTH number pos. #define ST_HEALTHWIDTH 3 #define ST_HEALTHX 64 #define ST_HEALTHY 176 // MANA A #define ST_MANAAWIDTH 3 #define ST_MANAAX 91 #define ST_MANAAY 181 // MANA A ICON #define ST_MANAAICONX 77 #define ST_MANAAICONY 164 // MANA A VIAL #define ST_MANAAVIALX 94 #define ST_MANAAVIALY 164 // MANA B #define ST_MANABWIDTH 3 #define ST_MANABX 123 #define ST_MANABY 181 // MANA B ICON #define ST_MANABICONX 110 #define ST_MANABICONY 164 // MANA B VIAL #define ST_MANABVIALX 102 #define ST_MANABVIALY 164 // ARMOR number pos. #define ST_ARMORWIDTH 2 #define ST_ARMORX 274 #define ST_ARMORY 176 // Frags pos. #define ST_FRAGSWIDTH 3 #define ST_FRAGSX 64 #define ST_FRAGSY 176 // TYPES ------------------------------------------------------------------- typedef struct { boolean stopped; int hideTics; float hideAmount; float showBar; // Slide statusbar amount 1.0 is fully open. float alpha; // Fullscreen hud alpha value. float statusbarCounterAlpha; boolean firstTime; // ST_Start() has just been called. boolean statusbarActive; // Whether left-side main status bar is active. boolean hitCenterFrame; int currentInvItemFlash; int armorLevel; // Current armor level. int manaAIcon; // Current mana A icon index. 0 = none. int manaBIcon; // Current mana B icon index. 0 = none. int manaAVial; // Current mana A vial index. 0 = none. int manaBVial; // Current mana B vial index. 0 = none. int manaACount; int manaBCount; int fragsCount; // Number of frags so far in deathmatch. boolean blended; // Whether to use alpha blending. int healthMarker; int oldHealth; // Widgets: st_multiicon_t wManaA; // Current mana A icon. st_multiicon_t wManaB; // Current mana B icon. st_number_t wManaACount; // Current mana A count. st_number_t wManaBCount; // Current mana B count. st_multiicon_t wManaAVial; // Current mana A vial. st_multiicon_t wManaBVial; // Current mana B vial. st_number_t wFrags; // In deathmatch only, summary of frags stats. st_number_t wHealth; // Health. st_number_t wArmor; // Armor. } hudstate_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // Console commands for the HUD/Statusbar DEFCC(CCmdStatusBarSize); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void DrINumber(signed int val, int x, int y, float r, float g, float b, float a); void ST_updateWidgets(int player); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DECLARATIONS ------------------------------------------------ // PRIVATE DATA DEFINITIONS ------------------------------------------------ static hudstate_t hudStates[MAXPLAYERS]; static dpatch_t dpStatusBar; static dpatch_t dpStatusBarTop; static dpatch_t dpKills; static dpatch_t dpStatBar; static dpatch_t dpKeyBar; static dpatch_t dpKeySlot[NUM_KEY_TYPES]; static dpatch_t dpArmorSlot[NUMARMOR]; static dpatch_t dpINumbers[10]; static dpatch_t dpNegative; static dpatch_t dpManaAVials[2]; static dpatch_t dpManaBVials[2]; static dpatch_t dpManaAIcons[2]; static dpatch_t dpManaBIcons[2]; static dpatch_t dpInventoryBar; static dpatch_t dpWeaponSlot[3]; // [Fighter, Cleric, Mage] static dpatch_t dpWeaponFull[3]; // [Fighter, Cleric, Mage] static dpatch_t dpLifeGem[3][8]; // [Fighter, Cleric, Mage][color] static dpatch_t dpWeaponPiece1[3]; // [Fighter, Cleric, Mage] static dpatch_t dpWeaponPiece2[3]; // [Fighter, Cleric, Mage] static dpatch_t dpWeaponPiece3[3]; // [Fighter, Cleric, Mage] static dpatch_t dpChain[3]; // [Fighter, Cleric, Mage] static dpatch_t dpInvItemFlash[5]; static dpatch_t dpSpinFly[16]; static dpatch_t dpSpinMinotaur[16]; static dpatch_t dpSpinSpeed[16]; static dpatch_t dpSpinDefense[16]; static dpatch_t dpTeleIcon; // CVARs for the HUD/Statusbar cvar_t sthudCVars[] = { // HUD scale {"hud-scale", 0, CVT_FLOAT, &cfg.hudScale, 0.1f, 10}, {"hud-status-size", CVF_PROTECTED, CVT_INT, &cfg.statusbarScale, 1, 20}, // HUD colour + alpha {"hud-color-r", 0, CVT_FLOAT, &cfg.hudColor[0], 0, 1}, {"hud-color-g", 0, CVT_FLOAT, &cfg.hudColor[1], 0, 1}, {"hud-color-b", 0, CVT_FLOAT, &cfg.hudColor[2], 0, 1}, {"hud-color-a", 0, CVT_FLOAT, &cfg.hudColor[3], 0, 1}, {"hud-icon-alpha", 0, CVT_FLOAT, &cfg.hudIconAlpha, 0, 1}, {"hud-status-alpha", 0, CVT_FLOAT, &cfg.statusbarOpacity, 0, 1}, {"hud-status-icon-a", 0, CVT_FLOAT, &cfg.statusbarCounterAlpha, 0, 1}, // HUD icons {"hud-mana", 0, CVT_BYTE, &cfg.hudShown[HUD_MANA], 0, 2}, {"hud-health", 0, CVT_BYTE, &cfg.hudShown[HUD_HEALTH], 0, 1}, {"hud-currentitem", 0, CVT_BYTE, &cfg.hudShown[HUD_CURRENTITEM], 0, 1}, // HUD displays {"hud-timer", 0, CVT_FLOAT, &cfg.hudTimer, 0, 60}, {"hud-unhide-damage", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_DAMAGE], 0, 1}, {"hud-unhide-pickup-health", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_HEALTH], 0, 1}, {"hud-unhide-pickup-armor", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_ARMOR], 0, 1}, {"hud-unhide-pickup-powerup", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_POWER], 0, 1}, {"hud-unhide-pickup-weapon", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_WEAPON], 0, 1}, {"hud-unhide-pickup-ammo", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_AMMO], 0, 1}, {"hud-unhide-pickup-key", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_KEY], 0, 1}, {"hud-unhide-pickup-invitem", 0, CVT_BYTE, &cfg.hudUnHide[HUE_ON_PICKUP_INVITEM], 0, 1}, {NULL} }; // Console commands for the HUD/Status bar ccmd_t sthudCCmds[] = { {"sbsize", "s", CCmdStatusBarSize}, {NULL} }; // CODE -------------------------------------------------------------------- /** * Register CVARs and CCmds for the HUD/Status bar. */ void ST_Register(void) { int i; for(i = 0; sthudCVars[i].name; ++i) Con_AddVariable(sthudCVars + i); for(i = 0; sthudCCmds[i].name; ++i) Con_AddCommand(sthudCCmds + i); Hu_InventoryRegister(); } static void drawAnimatedIcons(hudstate_t* hud) { int leftoff = 0; int frame; float iconalpha = (hud->statusbarActive? 1: hud->alpha) - (1 - cfg.hudIconAlpha); int player = hud - hudStates; player_t* plr = &players[player]; // If the fullscreen mana is drawn, we need to move the icons on the left // a bit to the right. if(cfg.hudShown[HUD_MANA] == 1 && cfg.screenBlocks > 11) leftoff = 42; Draw_BeginZoom(cfg.hudScale, 2, 2); // Wings of wrath if(plr->powers[PT_FLIGHT]) { if(plr->powers[PT_FLIGHT] > BLINKTHRESHOLD || !(plr->powers[PT_FLIGHT] & 16)) { frame = (mapTime / 3) & 15; if(plr->plr->mo->flags2 & MF2_FLY) { if(hud->hitCenterFrame && (frame != 15 && frame != 0)) { GL_DrawPatchLitAlpha(20 + leftoff, 19, 1, iconalpha, dpSpinFly[15].lump); } else { GL_DrawPatchLitAlpha(20 + leftoff, 19, 1, iconalpha, dpSpinFly[frame].lump); hud->hitCenterFrame = false; } } else { if(!hud->hitCenterFrame && (frame != 15 && frame != 0)) { GL_DrawPatchLitAlpha(20 + leftoff, 19, 1, iconalpha, dpSpinFly[frame].lump); hud->hitCenterFrame = false; } else { GL_DrawPatchLitAlpha(20 + leftoff, 19, 1, iconalpha, dpSpinFly[15].lump); hud->hitCenterFrame = true; } } } } // Speed Boots if(plr->powers[PT_SPEED]) { if(plr->powers[PT_SPEED] > BLINKTHRESHOLD || !(plr->powers[PT_SPEED] & 16)) { frame = (mapTime / 3) & 15; GL_DrawPatchLitAlpha(60 + leftoff, 19, 1, iconalpha, dpSpinSpeed[frame].lump); } } Draw_EndZoom(); Draw_BeginZoom(cfg.hudScale, 318, 2); // Defensive power if(plr->powers[PT_INVULNERABILITY]) { if(plr->powers[PT_INVULNERABILITY] > BLINKTHRESHOLD || !(plr->powers[PT_INVULNERABILITY] & 16)) { frame = (mapTime / 3) & 15; GL_DrawPatchLitAlpha(260, 19, 1, iconalpha, dpSpinDefense[frame].lump); } } // Minotaur Active if(plr->powers[PT_MINOTAUR]) { if(plr->powers[PT_MINOTAUR] > BLINKTHRESHOLD || !(plr->powers[PT_MINOTAUR] & 16)) { frame = (mapTime / 3) & 15; GL_DrawPatchLitAlpha(300, 19, 1, iconalpha, dpSpinMinotaur[frame].lump); } } Draw_EndZoom(); } static void drawKeyBar(hudstate_t* hud) { int i, xPosition, temp, pClass; int player = hud - hudStates; player_t* plr = &players[player]; // Original player class (i.e. not pig). pClass = cfg.playerClass[player]; xPosition = 46; for(i = 0; i < NUM_KEY_TYPES && xPosition <= 126; ++i) { if(plr->keys & (1 << i)) { GL_DrawPatchLitAlpha(xPosition, 163, 1, hud->statusbarCounterAlpha, dpKeySlot[i].lump); xPosition += 20; } } temp = PCLASS_INFO(pClass)->autoArmorSave + plr->armorPoints[ARMOR_ARMOR] + plr->armorPoints[ARMOR_SHIELD] + plr->armorPoints[ARMOR_HELMET] + plr->armorPoints[ARMOR_AMULET]; for(i = 0; i < NUMARMOR; ++i) { if(!plr->armorPoints[i]) continue; if(plr->armorPoints[i] <= (PCLASS_INFO(pClass)->armorIncrement[i] >> 2)) { GL_DrawPatchLitAlpha(150 + 31 * i, 164, 1, hud->statusbarCounterAlpha * 0.3, dpArmorSlot[i].lump); } else if(plr->armorPoints[i] <= (PCLASS_INFO(pClass)->armorIncrement[i] >> 1)) { GL_DrawPatchLitAlpha(150 + 31 * i, 164, 1, hud->statusbarCounterAlpha * 0.6, dpArmorSlot[i].lump); } else { GL_DrawPatchLitAlpha(150 + 31 * i, 164, 1, hud->statusbarCounterAlpha, dpArmorSlot[i].lump); } } } static void drawWeaponPieces(hudstate_t* hud) { int player = hud - hudStates, pClass; player_t* plr = &players[player]; float alpha; // Original player class (i.e. not pig). pClass = cfg.playerClass[player]; alpha = MINMAX_OF(0.f, cfg.statusbarOpacity - hud->hideAmount, 1.f); if(plr->pieces == 7) { GL_DrawPatchLitAlpha(190, 162, 1, hud->statusbarCounterAlpha, dpWeaponFull[pClass].lump); } else { if(plr->pieces & WPIECE1) { GL_DrawPatchLitAlpha(PCLASS_INFO(pClass)->pieceX[0], 162, 1, hud->statusbarCounterAlpha, dpWeaponPiece1[pClass].lump); } if(plr->pieces & WPIECE2) { GL_DrawPatchLitAlpha(PCLASS_INFO(pClass)->pieceX[1], 162, 1, hud->statusbarCounterAlpha, dpWeaponPiece2[pClass].lump); } if(plr->pieces & WPIECE3) { GL_DrawPatchLitAlpha(PCLASS_INFO(pClass)->pieceX[2], 162, 1, hud->statusbarCounterAlpha, dpWeaponPiece3[pClass].lump); } } } static void drawChain(hudstate_t* hud) { static int theirColors[] = { 157, // Blue 177, // Red 137, // Yellow 198, // Green 215, // Jade 32, // White 106, // Hazel 234 // Purple }; int x, y, w, h; int pClass, pColor; float healthPos; int gemXOffset; float gemglow, rgb[3]; int player = hud - hudStates; hud->oldHealth = hud->healthMarker; // Original player class (i.e. not pig). pClass = cfg.playerClass[player]; healthPos = MINMAX_OF(0, hud->healthMarker / 100.f, 100); if(!IS_NETGAME) { pColor = 1; // Always use the red life gem (the second gem). } else { pColor = cfg.playerColor[player]; if(pClass == PCLASS_FIGHTER) { if(pColor == 0) pColor = 2; else if(pColor == 2) pColor = 0; } } gemglow = healthPos; // Draw the chain. x = 43; y = 193; w = ST_WIDTH - 43 - 43; h = 7; DGL_SetPatch(dpChain[pClass].lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_Color4f(1, 1, 1, hud->statusbarCounterAlpha); gemXOffset = 7 + ROUND((w - 14) * healthPos) - dpLifeGem[pClass][pColor].width/2; if(gemXOffset > 0) { // Left chain section. float cw = (float)(dpChain[pClass].width - gemXOffset) / dpChain[pClass].width; DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(x + gemXOffset, y); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(x + gemXOffset, y + h); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x, y + h); DGL_End(); } if(gemXOffset + dpLifeGem[pClass][pColor].width < w) { // Right chain section. float cw = (w - (float)gemXOffset - dpLifeGem[pClass][pColor].width) / dpChain[pClass].width; DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(x + gemXOffset + dpLifeGem[pClass][pColor].width, y); DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(x + gemXOffset + dpLifeGem[pClass][pColor].width, y + h); DGL_End(); } // Draw the life gem. { int vX = x + MAX_OF(0, gemXOffset); int vWidth; float s1 = 0, s2 = 1; vWidth = dpLifeGem[pClass][pColor].width; if(gemXOffset + dpLifeGem[pClass][pColor].width > w) { vWidth -= gemXOffset + dpLifeGem[pClass][pColor].width - w; s2 = (float)vWidth / dpLifeGem[pClass][pColor].width; } if(gemXOffset < 0) { vWidth -= -gemXOffset; s1 = (float)(-gemXOffset) / dpLifeGem[pClass][pColor].width; } DGL_SetPatch(dpLifeGem[pClass][pColor].lump, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); DGL_Begin(DGL_QUADS); DGL_TexCoord2f(0, s1, 0); DGL_Vertex2f(vX, y); DGL_TexCoord2f(0, s2, 0); DGL_Vertex2f(vX + vWidth, y); DGL_TexCoord2f(0, s2, 1); DGL_Vertex2f(vX + vWidth, y + h); DGL_TexCoord2f(0, s1, 1); DGL_Vertex2f(vX, y + h); DGL_End(); } // How about a glowing gem? DGL_BlendMode(BM_ADD); DGL_Bind(Get(DD_DYNLIGHT_TEXTURE)); R_GetColorPaletteRGBf(0, rgb, theirColors[pColor], false); DGL_DrawRect(x + gemXOffset + 23, y - 6, 41, 24, rgb[0], rgb[1], rgb[2], gemglow - (1 - hud->statusbarCounterAlpha)); DGL_BlendMode(BM_NORMAL); DGL_Color4f(1, 1, 1, 1); } static void drawStatusBarBackground(int player) { int x, y, w, h; int pClass; float cw, cw2, ch; hudstate_t* hud = &hudStates[player]; float alpha; // Original class (i.e. not pig). pClass = cfg.playerClass[player]; if(hud->blended) { alpha = cfg.statusbarOpacity - hud->hideAmount; if(!(alpha > 0)) return; alpha = MINMAX_OF(0.f, alpha, 1.f); } else alpha = 1.0f; if(!(alpha < 1)) { GL_DrawPatch(0, 134, dpStatusBar.lump); /** * \kludge The Hexen statusbar graphic has a chain already in the * image, which shows through the modified chain patches. * Mask out the chain on the statusbar by drawing a solid black * rectangle over it. */ DGL_SetNoMaterial(); DGL_DrawRect(44, 193, 232, 7, .1f, .1f, .1f, 1); //// \kludge end GL_DrawPatch(0, 134, dpStatusBarTop.lump); if(!Hu_InventoryIsOpen(player)) { // Main interface if(!AM_IsActive(AM_MapForPlayer(player))) { GL_DrawPatch(38, 162, dpStatBar.lump); if(deathmatch) { GL_DrawPatch_CS(38, 162, dpKills.lump); } GL_DrawPatch(190, 162, dpWeaponSlot[pClass].lump); } else { GL_DrawPatch(38, 162, dpKeyBar.lump); drawKeyBar(hud); } } else { GL_DrawPatch(38, 162, dpInventoryBar.lump); } } else { DGL_Color4f(1, 1, 1, alpha); DGL_SetPatch(dpStatusBar.lump, DGL_CLAMP, DGL_CLAMP); DGL_Begin(DGL_QUADS); // top x = 0; y = 135; w = ST_WIDTH; h = 27; ch = 0.41538461538461538461538461538462; DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1, ch); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0, ch); DGL_Vertex2f(x, y + h); // left statue x = 0; y = 162; w = 38; h = 38; cw = (float) 38 / ST_WIDTH; ch = 0.41538461538461538461538461538462; DGL_TexCoord2f(0, 0, ch); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(x, y + h); // right statue x = 282; y = 162; w = 38; h = 38; cw = (float) (ST_WIDTH - 38) / ST_WIDTH; ch = 0.41538461538461538461538461538462f; DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, ch); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, 1); DGL_Vertex2f(x, y + h); DGL_End(); /** * \kludge The Hexen statusbar graphic has a chain already in the * image, which shows through the modified chain patches. * Mask out the chain on the statusbar by cutting a window out and * drawing a solid near-black rectangle to fill the hole. */ DGL_DrawCutRectTiled(38, 192, 244, 8, 320, 65, 38, 192-135, 44, 193, 232, 7); DGL_SetNoMaterial(); DGL_DrawRect(44, 193, 232, 7, .1f, .1f, .1f, alpha); DGL_Color4f(1, 1, 1, alpha); //// \kludge end if(!Hu_InventoryIsOpen(player)) { // Main interface if(!AM_IsActive(AM_MapForPlayer(player))) { if(deathmatch) { GL_DrawPatch_CS(38, 162, dpKills.lump); } // left of statbar (upto weapon puzzle display) DGL_SetPatch(dpStatBar.lump, DGL_CLAMP, DGL_CLAMP); DGL_Begin(DGL_QUADS); x = deathmatch ? 68 : 38; y = 162; w = deathmatch ? 122 : 152; h = 30; cw = deathmatch ? (float) 15 / 122 : 0; cw2 = 0.62295081967213114754098360655738; ch = 0.96774193548387096774193548387097; DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, cw2, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, cw2, ch); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x, y + h); // right of statbar (after weapon puzzle display) x = 247; y = 162; w = 35; h = 30; cw = 0.85655737704918032786885245901639; ch = 0.96774193548387096774193548387097; DGL_TexCoord2f(0, cw, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1, ch); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, cw, ch); DGL_Vertex2f(x, y + h); DGL_End(); GL_DrawPatch_CS(190, 162, dpWeaponSlot[pClass].lump); } else { GL_DrawPatch_CS(38, 162, dpKeyBar.lump); } } else { // INVBAR DGL_SetPatch(dpInventoryBar.lump, DGL_CLAMP, DGL_CLAMP); DGL_Begin(DGL_QUADS); x = 38; y = 162; w = 244; h = 30; ch = 0.96774193548387096774193548387097; DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(x, y); DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(x + w, y); DGL_TexCoord2f(0, 1, ch); DGL_Vertex2f(x + w, y + h); DGL_TexCoord2f(0, 0, ch); DGL_Vertex2f(x, y + h); DGL_End(); } } } void ST_loadGraphics(void) { int i; char namebuf[9]; R_CachePatch(&dpStatusBar, "H2BAR"); R_CachePatch(&dpStatusBarTop, "H2TOP"); R_CachePatch(&dpInventoryBar, "INVBAR"); R_CachePatch(&dpStatBar, "STATBAR"); R_CachePatch(&dpKeyBar, "KEYBAR"); R_CachePatch(&dpManaAVials[0], "MANAVL1D"); R_CachePatch(&dpManaBVials[0], "MANAVL2D"); R_CachePatch(&dpManaAVials[1], "MANAVL1"); R_CachePatch(&dpManaBVials[1], "MANAVL2"); R_CachePatch(&dpManaAIcons[0], "MANADIM1"); R_CachePatch(&dpManaBIcons[0], "MANADIM2"); R_CachePatch(&dpManaAIcons[1], "MANABRT1"); R_CachePatch(&dpManaBIcons[1], "MANABRT2"); R_CachePatch(&dpNegative, "NEGNUM"); R_CachePatch(&dpKills, "KILLS"); for(i = 0; i < NUM_KEY_TYPES; ++i) { sprintf(namebuf, "KEYSLOT%X", i + 1); R_CachePatch(&dpKeySlot[i], namebuf); } for(i = 0; i < NUMARMOR; ++i) { sprintf(namebuf, "ARMSLOT%d", i + 1); R_CachePatch(&dpArmorSlot[i], namebuf); } for(i = 0; i < 16; ++i) { sprintf(namebuf, "SPFLY%d", i); R_CachePatch(&dpSpinFly[i], namebuf); sprintf(namebuf, "SPMINO%d", i); R_CachePatch(&dpSpinMinotaur[i], namebuf); sprintf(namebuf, "SPBOOT%d", i); R_CachePatch(&dpSpinSpeed[i], namebuf); sprintf(namebuf, "SPSHLD%d", i); R_CachePatch(&dpSpinDefense[i], namebuf); } // Fighter: R_CachePatch(&dpWeaponPiece1[PCLASS_FIGHTER], "WPIECEF1"); R_CachePatch(&dpWeaponPiece2[PCLASS_FIGHTER], "WPIECEF2"); R_CachePatch(&dpWeaponPiece3[PCLASS_FIGHTER], "WPIECEF3"); R_CachePatch(&dpChain[PCLASS_FIGHTER], "CHAIN"); R_CachePatch(&dpWeaponSlot[PCLASS_FIGHTER], "WPSLOT0"); R_CachePatch(&dpWeaponFull[PCLASS_FIGHTER], "WPFULL0"); R_CachePatch(&dpLifeGem[PCLASS_FIGHTER][0], "LIFEGEM"); for(i = 1; i < 8; ++i) { sprintf(namebuf, "LIFEGMF%d", i + 1); R_CachePatch(&dpLifeGem[PCLASS_FIGHTER][i], namebuf); } // Cleric: R_CachePatch(&dpWeaponPiece1[PCLASS_CLERIC], "WPIECEC1"); R_CachePatch(&dpWeaponPiece2[PCLASS_CLERIC], "WPIECEC2"); R_CachePatch(&dpWeaponPiece3[PCLASS_CLERIC], "WPIECEC3"); R_CachePatch(&dpChain[PCLASS_CLERIC], "CHAIN2"); R_CachePatch(&dpWeaponSlot[PCLASS_CLERIC], "WPSLOT1"); R_CachePatch(&dpWeaponFull[PCLASS_CLERIC], "WPFULL1"); for(i = 0; i < 8; ++i) { sprintf(namebuf, "LIFEGMC%d", i + 1); R_CachePatch(&dpLifeGem[PCLASS_CLERIC][i], namebuf); } // Mage: R_CachePatch(&dpWeaponPiece1[PCLASS_MAGE], "WPIECEM1"); R_CachePatch(&dpWeaponPiece2[PCLASS_MAGE], "WPIECEM2"); R_CachePatch(&dpWeaponPiece3[PCLASS_MAGE], "WPIECEM3"); R_CachePatch(&dpChain[PCLASS_MAGE], "CHAIN3"); R_CachePatch(&dpWeaponSlot[PCLASS_MAGE], "WPSLOT2"); R_CachePatch(&dpWeaponFull[PCLASS_MAGE], "WPFULL2"); for(i = 0; i < 8; ++i) { sprintf(namebuf, "LIFEGMM%d", i + 1); R_CachePatch(&dpLifeGem[PCLASS_MAGE][i], namebuf); } for(i = 0; i < 10; ++i) { sprintf(namebuf, "IN%d", i); R_CachePatch(&dpINumbers[i], namebuf); } // Inventory item flash anim. { const char invItemFlashAnim[5][9] = { {"USEARTIA"}, {"USEARTIB"}, {"USEARTIC"}, {"USEARTID"}, {"USEARTIE"} }; for(i = 0; i < 5; ++i) { R_CachePatch(&dpInvItemFlash[i], invItemFlashAnim[i]); } } R_CachePatch(&dpTeleIcon, "TELEICON"); } void ST_loadData(void) { ST_loadGraphics(); } static void initData(hudstate_t* hud) { int player = hud - hudStates; player_t* plr = &players[player]; hud->firstTime = true; hud->statusbarActive = true; hud->stopped = true; hud->oldHealth = -1; // Health marker chain animates up to the actual health value. hud->healthMarker = 0; hud->blended = false; hud->showBar = 0.0f; ST_updateWidgets(player); ST_HUDUnHide(player, HUE_FORCE); } void ST_createWidgets(int player) { player_t* plr = &players[player]; hudstate_t* hud = &hudStates[player]; // Health num. STlib_InitNum(&hud->wHealth, ST_HEALTHX, ST_HEALTHY, dpINumbers, &plr->health, ST_HEALTHWIDTH, 1); // Frags sum. STlib_InitNum(&hud->wFrags, ST_FRAGSX, ST_FRAGSY, dpINumbers, &hud->fragsCount, ST_FRAGSWIDTH, 1); // Armor num - should be colored later. STlib_InitNum(&hud->wArmor, ST_ARMORX, ST_ARMORY, dpINumbers, &hud->armorLevel, ST_ARMORWIDTH, 1); // ManaA count. STlib_InitNum(&hud->wManaACount, ST_MANAAX, ST_MANAAY, dpSmallNumbers, &hud->manaACount, ST_MANAAWIDTH, 1); // ManaB count. STlib_InitNum(&hud->wManaBCount, ST_MANABX, ST_MANABY, dpSmallNumbers, &hud->manaBCount, ST_MANABWIDTH, 1); // Current mana A icon. STlib_InitMultiIcon(&hud->wManaA, ST_MANAAICONX, ST_MANAAICONY, dpManaAIcons, 1); // Current mana B icon. STlib_InitMultiIcon(&hud->wManaB, ST_MANABICONX, ST_MANABICONY, dpManaBIcons, 1); // Current mana A vial. STlib_InitMultiIcon(&hud->wManaAVial, ST_MANAAVIALX, ST_MANAAVIALY, dpManaAVials, 1); // Current mana B vial. STlib_InitMultiIcon(&hud->wManaBVial, ST_MANABVIALX, ST_MANABVIALY, dpManaBVials, 1); } void ST_Start(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(!hud->stopped) ST_Stop(player); initData(hud); ST_createWidgets(player); hud->stopped = false; } void ST_Stop(int player) { hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; hud = &hudStates[player]; if(hud->stopped) return; hud->stopped = true; } void ST_Init(void) { ST_loadData(); } void ST_FlashCurrentItem(int player) { player_t* plr; hudstate_t* hud; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; hud = &hudStates[player]; hud->currentInvItemFlash = 4; } void ST_updateWidgets(int player) { int i, pClass; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; // Original player class (i.e. not pig). pClass = cfg.playerClass[player]; if(hud->blended) { hud->statusbarCounterAlpha = MINMAX_OF(0.f, cfg.statusbarCounterAlpha - hud->hideAmount, 1.f); } else hud->statusbarCounterAlpha = 1.0f; // Used by w_frags widget. hud->fragsCount = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; hud->fragsCount += plr->frags[i] * (i != player ? 1 : -1); } // Armor hud->armorLevel = FixedDiv( PCLASS_INFO(pClass)->autoArmorSave + plr->armorPoints[ARMOR_ARMOR] + plr->armorPoints[ARMOR_SHIELD] + plr->armorPoints[ARMOR_HELMET] + plr->armorPoints[ARMOR_AMULET], 5 * FRACUNIT) >> FRACBITS; // mana A hud->manaACount = plr->ammo[AT_BLUEMANA].owned; // mana B hud->manaBCount = plr->ammo[AT_GREENMANA].owned; hud->manaAIcon = hud->manaBIcon = hud->manaAVial = hud->manaBVial = -1; // Mana if(!(plr->ammo[AT_BLUEMANA].owned > 0)) hud->manaAIcon = 0; // Draw dim Mana icon. if(!(plr->ammo[AT_GREENMANA].owned > 0)) hud->manaBIcon = 0; // Draw dim Mana icon. // Update mana graphics based upon mana count weapon type if(plr->readyWeapon == WT_FIRST) { hud->manaAIcon = 0; hud->manaBIcon = 0; hud->manaAVial = 0; hud->manaBVial = 0; } else if(plr->readyWeapon == WT_SECOND) { // If there is mana for this weapon, make it bright! if(hud->manaAIcon == -1) { hud->manaAIcon = 1; } hud->manaAVial = 1; hud->manaBIcon = 0; hud->manaBVial = 0; } else if(plr->readyWeapon == WT_THIRD) { hud->manaAIcon = 0; hud->manaAVial = 0; // If there is mana for this weapon, make it bright! if(hud->manaBIcon == -1) { hud->manaBIcon = 1; } hud->manaBVial = 1; } else { hud->manaAVial = 1; hud->manaBVial = 1; // If there is mana for this weapon, make it bright! if(hud->manaAIcon == -1) { hud->manaAIcon = 1; } if(hud->manaBIcon == -1) { hud->manaBIcon = 1; } } } void ST_Ticker(void) { int i; Hu_InventoryTicker(); for(i = 0; i < MAXPLAYERS; ++i) { player_t* plr = &players[i]; hudstate_t* hud = &hudStates[i]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) continue; ST_updateWidgets(i); if(!P_IsPaused()) { int delta; int curHealth; if(cfg.hudTimer == 0) { hud->hideTics = hud->hideAmount = 0; } else { if(hud->hideTics > 0) hud->hideTics--; if(hud->hideTics == 0 && cfg.hudTimer > 0 && hud->hideAmount < 1) hud->hideAmount += 0.1f; } if(hud->currentInvItemFlash > 0) hud->currentInvItemFlash--; curHealth = MAX_OF(plr->plr->mo->health, 0); if(curHealth < hud->healthMarker) { delta = MINMAX_OF(1, (hud->healthMarker - curHealth) >> 2, 6); hud->healthMarker -= delta; } else if(curHealth > hud->healthMarker) { delta = MINMAX_OF(1, (curHealth - hud->healthMarker) >> 2, 6); hud->healthMarker += delta; } } } } /** * Sets the new palette based upon the current values of * player_t->damageCount and player_t->bonusCount. */ void ST_doPaletteStuff(int player, boolean forceChange) { int palette = 0; player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(G_GetGameState() == GS_MAP) { plr = &players[CONSOLEPLAYER]; if(plr->poisonCount) { palette = 0; palette = (plr->poisonCount + 7) >> 3; if(palette >= NUMPOISONPALS) { palette = NUMPOISONPALS - 1; } palette += STARTPOISONPALS; } else if(plr->damageCount) { palette = (plr->damageCount + 7) >> 3; if(palette >= NUMREDPALS) { palette = NUMREDPALS - 1; } palette += STARTREDPALS; } else if(plr->bonusCount) { palette = (plr->bonusCount + 7) >> 3; if(palette >= NUMBONUSPALS) { palette = NUMBONUSPALS - 1; } palette += STARTBONUSPALS; } else if(plr->plr->mo->flags2 & MF2_ICEDAMAGE) { // Frozen player palette = STARTICEPAL; } } // $democam if(palette) { plr->plr->flags |= DDPF_VIEW_FILTER; R_GetFilterColor(plr->plr->filterColor, palette); } else plr->plr->flags &= ~DDPF_VIEW_FILTER; } static void drawWidgets(hudstate_t* hud) { int player = hud - hudStates; player_t* plr = &players[player]; float alpha = hud->statusbarCounterAlpha; hud->oldHealth = -1; if(!Hu_InventoryIsOpen(player)) { if(!AM_IsActive(AM_MapForPlayer(player))) { inventoryitemtype_t readyItem; // Frags if(deathmatch) STlib_DrawNum(&hud->wFrags, alpha); else STlib_DrawNum(&hud->wHealth, alpha); STlib_DrawNum(&hud->wArmor, alpha); if(hud->manaACount > 0) STlib_DrawNum(&hud->wManaACount, alpha); if(hud->manaBCount > 0) STlib_DrawNum(&hud->wManaBCount, alpha); STlib_DrawMultiIcon(&hud->wManaA, hud->manaAIcon, alpha); STlib_DrawMultiIcon(&hud->wManaB, hud->manaBIcon, alpha); STlib_DrawMultiIcon(&hud->wManaAVial, hud->manaAVial, alpha); STlib_DrawMultiIcon(&hud->wManaBVial, hud->manaBVial, alpha); // Draw the mana bars DGL_SetNoMaterial(); DGL_DrawRect(95, 165, 3, 22 - (22 * plr->ammo[AT_BLUEMANA].owned) / MAX_MANA, 0, 0, 0, alpha); DGL_DrawRect(103, 165, 3, 22 - (22 * plr->ammo[AT_GREENMANA].owned) / MAX_MANA, 0, 0, 0, alpha); // Current inventory item. if((readyItem = P_InventoryReadyItem(player)) != IIT_NONE) { int x, y; lumpnum_t patch; if(hud->currentInvItemFlash > 0) { patch = dpInvItemFlash[hud->currentInvItemFlash % 5].lump; x = ST_INVITEMX + 4; y = ST_INVITEMY; } else { patch = P_GetInvItem(readyItem-1)->patchLump; x = ST_INVITEMX; y = ST_INVITEMY; } DGL_Color4f(1, 1, 1, alpha); GL_DrawPatch_CS(x, y, patch); if(!(hud->currentInvItemFlash > 0)) { uint count = P_InventoryCount(player, readyItem); if(count > 1) Hu_DrawSmallNum(count, ST_INVITEMCWIDTH, ST_INVITEMCX, ST_INVITEMCY, alpha); } } } else { drawKeyBar(hud); } } else { // Draw Inventory Hu_InventoryDraw2(player, ST_INVENTORYX, ST_INVENTORYY, alpha); } } /** * Draws a three digit number. */ static void DrINumber(signed int val, int x, int y, float r, float g, float b, float a) { int oldval; DGL_Color4f(r,g,b,a); // Make sure it's a three digit number. if(val < -999) val = -999; if(val > 999) val = 999; oldval = val; if(val < 0) { val = -val; if(val > 99) { val = 99; } if(val > 9) { GL_DrawPatch_CS(x + 8, y, dpINumbers[val / 10].lump); GL_DrawPatch_CS(x, y, dpNegative.lump); } else { GL_DrawPatch_CS(x + 8, y, dpNegative.lump); } val = val % 10; GL_DrawPatch_CS(x + 16, y, dpINumbers[val].lump); return; } if(val > 99) { GL_DrawPatch_CS(x, y, dpINumbers[val / 100].lump); } val = val % 100; if(val > 9 || oldval > 99) { GL_DrawPatch_CS(x + 8, y, dpINumbers[val / 10].lump); } val = val % 10; GL_DrawPatch_CS(x + 16, y, dpINumbers[val].lump); } #if 0 // Unused atm /** * Displays sound debugging information. */ static void DrawSoundInfo(void) { int i; SoundInfo_t s; ChanInfo_t *c; char text[32]; int x; int y; int xPos[7] = { 1, 75, 112, 156, 200, 230, 260 }; if(mapTime & 16) { MN_DrTextA("*** SOUND DEBUG INFO ***", xPos[0], 20); } S_GetChannelInfo(&s); if(s.channelCount == 0) { return; } x = 0; MN_DrTextA("NAME", xPos[x++], 30); MN_DrTextA("MO.T", xPos[x++], 30); MN_DrTextA("MO.X", xPos[x++], 30); MN_DrTextA("MO.Y", xPos[x++], 30); MN_DrTextA("ID", xPos[x++], 30); MN_DrTextA("PRI", xPos[x++], 30); MN_DrTextA("DIST", xPos[x++], 30); for(i = 0; i < s.channelCount; ++i) { c = &s.chan[i]; x = 0; y = 40 + i * 10; if(c->mo == NULL) { // Channel is unused MN_DrTextA("------", xPos[0], y); continue; } sprintf(text, "%s", c->name); strupr(text); MN_DrTextA(text, xPos[x++], y); sprintf(text, "%d", c->mo->type); MN_DrTextA(text, xPos[x++], y); sprintf(text, "%d", c->mo->x >> FRACBITS); MN_DrTextA(text, xPos[x++], y); sprintf(text, "%d", c->mo->y >> FRACBITS); MN_DrTextA(text, xPos[x++], y); sprintf(text, "%d", c->id); MN_DrTextA(text, xPos[x++], y); sprintf(text, "%d", S_sfx[c->id].usefulness); MN_DrTextA(text, xPos[x++], y); sprintf(text, "%d", c->distance); } } #endif /** * Unhides the current HUD display if hidden. * * @param player The player whoose HUD to (maybe) unhide. * @param event The HUD Update Event type to check for triggering. */ void ST_HUDUnHide(int player, hueevent_t ev) { player_t* plr; if(ev < HUE_FORCE || ev > NUMHUDUNHIDEEVENTS) return; plr = &players[player]; if(!(plr->plr->inGame && (plr->plr->flags & DDPF_LOCAL))) return; if(ev == HUE_FORCE || cfg.hudUnHide[ev]) { hudStates[player].hideTics = (cfg.hudTimer * TICSPERSEC); hudStates[player].hideAmount = 0; } } /** * All drawing for the status bar starts and ends here */ void ST_doRefresh(int player) { hudstate_t* hud; boolean statusbarVisible; if(player < 0 || player > MAXPLAYERS) return; hud = &hudStates[player]; statusbarVisible = (cfg.statusbarScale < 20 || (cfg.statusbarScale == 20 && hud->showBar < 1.0f)); hud->firstTime = false; if(statusbarVisible) { float fscale = cfg.statusbarScale / 20.0f; float h = 200 * (1 - fscale); DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); DGL_Translatef(160 - 320 * fscale / 2, h / hud->showBar, 0); DGL_Scalef(fscale, fscale, 1); } drawStatusBarBackground(player); if(!Hu_InventoryIsOpen(player) && !AM_IsActive(AM_MapForPlayer(player))) drawWeaponPieces(hud); drawChain(hud); drawWidgets(hud); if(statusbarVisible) { // Restore the normal modelview matrix. DGL_MatrixMode(DGL_MODELVIEW); DGL_PopMatrix(); } } void ST_doFullscreenStuff(int player) { int i, temp; hudstate_t* hud = &hudStates[player]; player_t* plr = &players[player]; float textAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudColor[3]), 1.f); float iconAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudIconAlpha), 1.f); if(cfg.hudShown[HUD_HEALTH]) { Draw_BeginZoom(cfg.hudScale, 5, 198); if(plr->plr->mo->health > 0) { DrBNumber(plr->plr->mo->health, 5, 180, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); } else { DrBNumber(0, 5, 180, cfg.hudColor[0], cfg.hudColor[1], cfg.hudColor[2], textAlpha); } Draw_EndZoom(); } if(cfg.hudShown[HUD_MANA]) { int dim[2] = { dpManaAIcons[0].lump, dpManaBIcons[0].lump }; int bright[2] = { dpManaAIcons[0].lump, dpManaBIcons[0].lump }; int patches[2] = { 0, 0 }; int ypos = cfg.hudShown[HUD_MANA] == 2 ? 152 : 2; for(i = 0; i < 2; i++) if(!(plr->ammo[i].owned > 0)) patches[i] = dim[i]; if(plr->readyWeapon == WT_FIRST) { for(i = 0; i < 2; i++) patches[i] = dim[i]; } if(plr->readyWeapon == WT_SECOND) { if(!patches[0]) patches[0] = bright[0]; patches[1] = dim[1]; } if(plr->readyWeapon == WT_THIRD) { patches[0] = dim[0]; if(!patches[1]) patches[1] = bright[1]; } if(plr->readyWeapon == WT_FOURTH) { for(i = 0; i < 2; ++i) if(!patches[i]) patches[i] = bright[i]; } Draw_BeginZoom(cfg.hudScale, 2, ypos); for(i = 0; i < 2; ++i) { GL_DrawPatchLitAlpha(2, ypos + i * 13, 1, iconAlpha, patches[i]); DrINumber(plr->ammo[i].owned, 18, ypos + i * 13, 1, 1, 1, textAlpha); } Draw_EndZoom(); } if(deathmatch) { temp = 0; for(i = 0; i < MAXPLAYERS; ++i) { if(players[i].plr->inGame) { temp += plr->frags[i]; } } Draw_BeginZoom(cfg.hudScale, 2, 198); DrINumber(temp, 45, 185, 1, 1, 1, textAlpha); Draw_EndZoom(); } if(!Hu_InventoryIsOpen(player)) { if(cfg.hudShown[HUD_CURRENTITEM]) { if(hud->currentInvItemFlash > 0) { const dpatch_t* dp = &dpInvItemFlash[hud->currentInvItemFlash % 5]; Draw_BeginZoom(cfg.hudScale, 318, 198); GL_DrawPatchLitAlpha(289, 170, 1, iconAlpha / 2, dpInvItemBox.lump); GL_DrawPatchLitAlpha(292, 170, 1, iconAlpha, dp->lump); Draw_EndZoom(); } else { inventoryitemtype_t readyItem = P_InventoryReadyItem(player); if(readyItem != IIT_NONE) { uint count; lumpnum_t patch = P_GetInvItem(readyItem-1)->patchLump; Draw_BeginZoom(cfg.hudScale, 318, 198); GL_DrawPatchLitAlpha(289, 170, 1, iconAlpha / 2, dpInvItemBox.lump); GL_DrawPatchLitAlpha(287, 169, 1, iconAlpha, patch); if((count = P_InventoryCount(player, readyItem)) > 1) Hu_DrawSmallNum(count, ST_INVITEMCWIDTH, 317, 192, textAlpha); Draw_EndZoom(); } } } } else { #define BORDER 2 #define INVENTORY_HEIGHT 30 #define INVENTORY_X SCREENWIDTH / 2 - 2 #define INVENTORY_Y SCREENHEIGHT - INVENTORY_HEIGHT - BORDER float textAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudColor[3]), 1.f); float iconAlpha = MINMAX_OF(0.f, hud->alpha - hud->hideAmount - ( 1 - cfg.hudIconAlpha), 1.f); Hu_InventoryDraw(player, INVENTORY_X, INVENTORY_Y, hud->alpha, textAlpha, iconAlpha); #undef BORDER #undef INVENTORY_HEIGHT #undef INVENTORY_X #undef INVENTORY_Y } } void ST_Drawer(int player, int fullscreenmode, boolean refresh) { hudstate_t* hud; player_t* plr; if(player < 0 || player >= MAXPLAYERS) return; plr = &players[player]; if(!((plr->plr->flags & DDPF_LOCAL) && plr->plr->inGame)) return; hud = &hudStates[player]; hud->firstTime = hud->firstTime || refresh; hud->statusbarActive = (fullscreenmode < 2) || (AM_IsActive(AM_MapForPlayer(player)) && (cfg.automapHudDisplay == 0 || cfg.automapHudDisplay == 2)); // Do palette shifts ST_doPaletteStuff(player, false); // Either slide the status bar in or fade out the fullscreen hud if(hud->statusbarActive) { if(hud->alpha > 0.0f) { hud->statusbarActive = 0; hud->alpha-=0.1f; } else if(hud->showBar < 1.0f) hud->showBar += 0.1f; } else { if(fullscreenmode == 3) { if(hud->alpha > 0.0f) { hud->alpha-=0.1f; fullscreenmode = 2; } } else { if(hud->showBar > 0.0f) { hud->showBar -= 0.1f; hud->statusbarActive = 1; } else if(hud->alpha < 1.0f) hud->alpha += 0.1f; } } // Always try to render statusbar with alpha in fullscreen modes if(fullscreenmode) hud->blended = 1; else hud->blended = 0; if(hud->statusbarActive) { ST_doRefresh(player); } else if(fullscreenmode != 3) { ST_doFullscreenStuff(player); } drawAnimatedIcons(hud); } /** * Draw teleport icon and show it on screen. */ void Draw_TeleportIcon(void) { // Dedicated servers don't draw anything. if(IS_DEDICATED) return; GL_DrawRawScreen(W_CheckNumForName("TRAVLPIC"), 0, 0); GL_DrawPatch(100, 68, dpTeleIcon.lump); } /** * Console command to change the size of the status bar. */ DEFCC(CCmdStatusBarSize) { int min = 1, max = 20, *val = &cfg.statusbarScale; if(!stricmp(argv[1], "+")) (*val)++; else if(!stricmp(argv[1], "-")) (*val)--; else *val = strtol(argv[1], NULL, 0); *val = MINMAX_OF(min, *val, max); // Update the view size if necessary. R_SetViewSize(cfg.screenBlocks); ST_HUDUnHide(CONSOLEPLAYER, HUE_FORCE); // So the user can see the change. return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_inter.c0000644000175000017500000021625511357170242022435 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.c: */ // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "am_map.h" #include "p_inventory.h" #include "p_player.h" #include "p_map.h" #include "p_user.h" // MACROS ------------------------------------------------------------------ #define BONUSADD (6) // TYPES ------------------------------------------------------------------- typedef enum { IT_NONE = -1, IT_HEALTH_VIAL, IT_ARMOR_MESH, IT_ARMOR_SHIELD, IT_ARMOR_HELMET, IT_ARMOR_AMULET, IT_KEY_STEEL, IT_KEY_CAVE, IT_KEY_AXE, IT_KEY_FIRE, IT_KEY_EMERALD, IT_KEY_DUNGEON, IT_KEY_SILVER, IT_KEY_RUSTED, IT_KEY_HORN, IT_KEY_SWAMP, IT_KEY_CASTLE, IT_ITEM_QUARTZFLASK, IT_ITEM_WINGS, IT_ITEM_DEFENDER, IT_ITEM_SERVANT, IT_ITEM_PORKALATOR, IT_ITEM_MYSTICURN, IT_ITEM_AMBITINCANT, IT_ITEM_TORCH, IT_ITEM_CHAOSDEVICE, IT_ITEM_BANISHDEVICE, IT_ITEM_FLETCHETTE, IT_ITEM_BOOTSOFSPEED, IT_ITEM_KRATEROFMIGHT, IT_ITEM_BRACERS, IT_ITEM_REPULSION, IT_PUZZLE_SKULL, IT_PUZZLE_BIGGEM, IT_PUZZLE_REDGEM, IT_PUZZLE_GREENGEM1, IT_PUZZLE_GREENGEM2, IT_PUZZLE_BLUEGEM1, IT_PUZZLE_BLUEGEM2, IT_PUZZLE_BOOK1, IT_PUZZLE_BOOK2, IT_PUZZLE_SKULL2, IT_PUZZLE_FWEAPON, IT_PUZZLE_CWEAPON, IT_PUZZLE_MWEAPON, IT_PUZZLE_GEAR1, IT_PUZZLE_GEAR2, IT_PUZZLE_GEAR3, IT_PUZZLE_GEAR4, IT_MANA_BLUE, IT_MANA_GREEN, IT_MANA_COMBINED, IT_WEAPON_FROSTSHARDS, IT_WEAPON_ARCOFDEATH, IT_WEAPON_AXE, IT_WEAPON_HAMMER, IT_WEAPON_SERPENTSTAFF, IT_WEAPON_FIRESTORM, IT_WEAPON_QUIETUS1, IT_WEAPON_QUIETUS2, IT_WEAPON_QUIETUS3, IT_WEAPON_WRAITHVERGE1, IT_WEAPON_WRAITHVERGE2, IT_WEAPON_WRAITHVERGE3, IT_WEAPON_BLOODSCOURGE1, IT_WEAPON_BLOODSCOURGE2, IT_WEAPON_BLOODSCOURGE3 } itemtype_t; // Item Info Flags: #define IIF_LEAVE_COOP 0x1 // Leave for others in Cooperative games. #define IIF_LEAVE_DEATHMATCH 0x2 // Leave for others in Deathmatch games. typedef struct iteminfo_s { itemtype_t type; short flags; // IIF_* flags. boolean (*giveFunc) (player_t*); textenum_t pickupMsg; sfxenum_t pickupSound; } iteminfo_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- static void setDormantItem(mobj_t* mo); static boolean pickupHealthVial(player_t* plr); static boolean pickupMesh(player_t* plr); static boolean pickupShield(player_t* plr); static boolean pickupHelmet(player_t* plr); static boolean pickupAmulet(player_t* plr); static boolean pickupSteelKey(player_t* plr); static boolean pickupCaveKey(player_t* plr); static boolean pickupAxeKey(player_t* plr); static boolean pickupFireKey(player_t* plr); static boolean pickupEmeraldKey(player_t* plr); static boolean pickupDungeonKey(player_t* plr); static boolean pickupSilverKey(player_t* plr); static boolean pickupRustedKey(player_t* plr); static boolean pickupHornKey(player_t* plr); static boolean pickupSwampKey(player_t* plr); static boolean pickupCastleKey(player_t* plr); static boolean pickupQuartzFlask(player_t* plr); static boolean pickupWings(player_t* plr); static boolean pickupDefender(player_t* plr); static boolean pickupServant(player_t* plr); static boolean pickupPorkalator(player_t* plr); static boolean pickupMysticUrn(player_t* plr); static boolean pickupAmbitIncant(player_t* plr); static boolean pickupTorch(player_t* plr); static boolean pickupChaosDevice(player_t* plr); static boolean pickupBanishDevice(player_t* plr); static boolean pickupFletchette(player_t* plr); static boolean pickupBootsOfSpeed(player_t* plr); static boolean pickupKraterOfMight(player_t* plr); static boolean pickupBracers(player_t* plr); static boolean pickupRepulsion(player_t* plr); static boolean pickupSkull(player_t* plr); static boolean pickupBigGem(player_t* plr); static boolean pickupRedGem(player_t* plr); static boolean pickupGreenGem1(player_t* plr); static boolean pickupGreenGem2(player_t* plr); static boolean pickupBlueGem1(player_t* plr); static boolean pickupBlueGem2(player_t* plr); static boolean pickupBook1(player_t* plr); static boolean pickupBook2(player_t* plr); static boolean pickupSkull2(player_t* plr); static boolean pickupFWeapon(player_t* plr); static boolean pickupCWeapon(player_t* plr); static boolean pickupMWeapon(player_t* plr); static boolean pickupGear1(player_t* plr); static boolean pickupGear2(player_t* plr); static boolean pickupGear3(player_t* plr); static boolean pickupGear4(player_t* plr); static boolean pickupBlueMana(player_t* plr); static boolean pickupGreenMana(player_t* plr); static boolean pickupCombinedMana(player_t* plr); static boolean pickupFrostShards(player_t* plr); static boolean pickupArcOfDeath(player_t* plr); static boolean pickupAxe(player_t* plr); static boolean pickupHammer(player_t* plr); static boolean pickupSerpentStaff(player_t* plr); static boolean pickupFireStorm(player_t* plr); static boolean pickupQuietus1(player_t* plr); static boolean pickupQuietus2(player_t* plr); static boolean pickupQuietus3(player_t* plr); static boolean pickupWraithVerge1(player_t* plr); static boolean pickupWraithVerge2(player_t* plr); static boolean pickupWraithVerge3(player_t* plr); static boolean pickupBloodScourge1(player_t* plr); static boolean pickupBloodScourge2(player_t* plr); static boolean pickupBloodScourge3(player_t* plr); // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- int echoMsg = 1; int TextKeyMessages[] = { TXT_TXT_KEY_STEEL, TXT_TXT_KEY_CAVE, TXT_TXT_KEY_AXE, TXT_TXT_KEY_FIRE, TXT_TXT_KEY_EMERALD, TXT_TXT_KEY_DUNGEON, TXT_TXT_KEY_SILVER, TXT_TXT_KEY_RUSTED, TXT_TXT_KEY_HORN, TXT_TXT_KEY_SWAMP, TXT_TXT_KEY_CASTLE }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Index using itemtype_t - 1; static const iteminfo_t items[] = { { IT_HEALTH_VIAL, 0, pickupHealthVial, TXT_TXT_ITEMHEALTH, SFX_PICKUP_PUZZ }, { IT_ARMOR_MESH, 0, pickupMesh, TXT_TXT_ARMOR1, SFX_PICKUP_PUZZ }, { IT_ARMOR_SHIELD, 0, pickupShield, TXT_TXT_ARMOR2, SFX_PICKUP_PUZZ }, { IT_ARMOR_HELMET, 0, pickupHelmet, TXT_TXT_ARMOR3, SFX_PICKUP_PUZZ }, { IT_ARMOR_AMULET, 0, pickupAmulet, TXT_TXT_ARMOR4, SFX_PICKUP_PUZZ }, { IT_KEY_STEEL, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupSteelKey, TXT_TXT_KEY_STEEL, SFX_PICKUP_KEY }, { IT_KEY_CAVE, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupCaveKey, TXT_TXT_KEY_CAVE, SFX_PICKUP_KEY }, { IT_KEY_AXE, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupAxeKey, TXT_TXT_KEY_AXE, SFX_PICKUP_KEY }, { IT_KEY_FIRE, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupFireKey, TXT_TXT_KEY_FIRE, SFX_PICKUP_KEY }, { IT_KEY_EMERALD, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupEmeraldKey, TXT_TXT_KEY_EMERALD, SFX_PICKUP_KEY }, { IT_KEY_DUNGEON, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupDungeonKey, TXT_TXT_KEY_DUNGEON, SFX_PICKUP_KEY }, { IT_KEY_SILVER, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupSilverKey, TXT_TXT_KEY_SILVER, SFX_PICKUP_KEY }, { IT_KEY_RUSTED, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupRustedKey, TXT_TXT_KEY_RUSTED, SFX_PICKUP_KEY }, { IT_KEY_HORN, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupHornKey, TXT_TXT_KEY_HORN, SFX_PICKUP_KEY }, { IT_KEY_SWAMP, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupSwampKey, TXT_TXT_KEY_SWAMP, SFX_PICKUP_KEY }, { IT_KEY_CASTLE, IIF_LEAVE_COOP | IIF_LEAVE_DEATHMATCH, pickupCastleKey, TXT_TXT_KEY_CASTLE, SFX_PICKUP_KEY }, { IT_ITEM_QUARTZFLASK, 0, pickupQuartzFlask, TXT_TXT_INV_HEALTH, SFX_PICKUP_ITEM }, { IT_ITEM_WINGS, 0, pickupWings, TXT_TXT_INV_FLY, SFX_PICKUP_ITEM }, { IT_ITEM_DEFENDER, 0, pickupDefender, TXT_TXT_INV_INVULNERABILITY, SFX_PICKUP_ITEM }, { IT_ITEM_SERVANT, 0, pickupServant, TXT_TXT_INV_SUMMON, SFX_PICKUP_ITEM }, { IT_ITEM_PORKALATOR, 0, pickupPorkalator, TXT_TXT_INV_EGG, SFX_PICKUP_ITEM }, { IT_ITEM_MYSTICURN, 0, pickupMysticUrn, TXT_TXT_INV_SUPERHEALTH, SFX_PICKUP_ITEM }, { IT_ITEM_AMBITINCANT, 0, pickupAmbitIncant, TXT_TXT_INV_HEALINGRADIUS, SFX_PICKUP_ITEM }, { IT_ITEM_TORCH, 0, pickupTorch, TXT_TXT_INV_TORCH, SFX_PICKUP_ITEM }, { IT_ITEM_CHAOSDEVICE, 0, pickupChaosDevice, TXT_TXT_INV_TELEPORT, SFX_PICKUP_ITEM }, { IT_ITEM_BANISHDEVICE, 0, pickupBanishDevice, TXT_TXT_INV_TELEPORTOTHER, SFX_PICKUP_ITEM }, { IT_ITEM_FLETCHETTE, 0, pickupFletchette, TXT_TXT_INV_POISONBAG, SFX_PICKUP_ITEM }, { IT_ITEM_BOOTSOFSPEED, 0, pickupBootsOfSpeed, TXT_TXT_INV_SPEED, SFX_PICKUP_ITEM }, { IT_ITEM_KRATEROFMIGHT, 0, pickupKraterOfMight, TXT_TXT_INV_BOOSTMANA, SFX_PICKUP_ITEM }, { IT_ITEM_BRACERS, 0, pickupBracers, TXT_TXT_INV_BOOSTARMOR, SFX_PICKUP_ITEM }, { IT_ITEM_REPULSION, 0, pickupRepulsion, TXT_TXT_INV_BLASTRADIUS, SFX_PICKUP_ITEM }, { IT_PUZZLE_SKULL, IIF_LEAVE_COOP, pickupSkull, TXT_TXT_INV_PUZZSKULL, SFX_PICKUP_PUZZ }, { IT_PUZZLE_BIGGEM, IIF_LEAVE_COOP, pickupBigGem, TXT_TXT_INV_PUZZGEMBIG, SFX_PICKUP_PUZZ }, { IT_PUZZLE_REDGEM, IIF_LEAVE_COOP, pickupRedGem, TXT_TXT_INV_PUZZGEMRED, SFX_PICKUP_PUZZ }, { IT_PUZZLE_GREENGEM1, IIF_LEAVE_COOP, pickupGreenGem1, TXT_TXT_INV_PUZZGEMGREEN1, SFX_PICKUP_PUZZ }, { IT_PUZZLE_GREENGEM2, IIF_LEAVE_COOP, pickupGreenGem2, TXT_TXT_INV_PUZZGEMGREEN2, SFX_PICKUP_PUZZ }, { IT_PUZZLE_BLUEGEM1, IIF_LEAVE_COOP, pickupBlueGem1, TXT_TXT_INV_PUZZGEMBLUE1, SFX_PICKUP_PUZZ }, { IT_PUZZLE_BLUEGEM2, IIF_LEAVE_COOP, pickupBlueGem2, TXT_TXT_INV_PUZZGEMBLUE2, SFX_PICKUP_PUZZ }, { IT_PUZZLE_BOOK1, IIF_LEAVE_COOP, pickupBook1, TXT_TXT_INV_PUZZBOOK1, SFX_PICKUP_PUZZ }, { IT_PUZZLE_BOOK2, IIF_LEAVE_COOP, pickupBook2, TXT_TXT_INV_PUZZBOOK2, SFX_PICKUP_PUZZ }, { IT_PUZZLE_SKULL2, IIF_LEAVE_COOP, pickupSkull2, TXT_TXT_INV_PUZZSKULL2, SFX_PICKUP_PUZZ }, { IT_PUZZLE_FWEAPON, IIF_LEAVE_COOP, pickupFWeapon, TXT_TXT_INV_PUZZFWEAPON, SFX_PICKUP_PUZZ }, { IT_PUZZLE_CWEAPON, IIF_LEAVE_COOP, pickupCWeapon, TXT_TXT_INV_PUZZCWEAPON, SFX_PICKUP_PUZZ }, { IT_PUZZLE_MWEAPON, IIF_LEAVE_COOP, pickupMWeapon, TXT_TXT_INV_PUZZMWEAPON, SFX_PICKUP_PUZZ }, { IT_PUZZLE_GEAR1, IIF_LEAVE_COOP, pickupGear1, TXT_TXT_INV_PUZZGEAR1, SFX_PICKUP_PUZZ }, { IT_PUZZLE_GEAR2, IIF_LEAVE_COOP, pickupGear2, TXT_TXT_INV_PUZZGEAR2, SFX_PICKUP_PUZZ }, { IT_PUZZLE_GEAR3, IIF_LEAVE_COOP, pickupGear3, TXT_TXT_INV_PUZZGEAR3, SFX_PICKUP_PUZZ }, { IT_PUZZLE_GEAR4, IIF_LEAVE_COOP, pickupGear4, TXT_TXT_INV_PUZZGEAR4, SFX_PICKUP_PUZZ }, { IT_MANA_BLUE, 0, pickupBlueMana, TXT_TXT_MANA_1, SFX_PICKUP_PUZZ }, { IT_MANA_GREEN, 0, pickupGreenMana, TXT_TXT_MANA_2, SFX_PICKUP_PUZZ }, { IT_MANA_COMBINED, 0, pickupCombinedMana, TXT_TXT_MANA_BOTH, SFX_PICKUP_PUZZ }, { IT_WEAPON_FROSTSHARDS, IIF_LEAVE_COOP, pickupFrostShards, TXT_TXT_WEAPON_M2, SFX_PICKUP_WEAPON }, { IT_WEAPON_ARCOFDEATH, IIF_LEAVE_COOP, pickupArcOfDeath, TXT_TXT_WEAPON_M3, SFX_PICKUP_WEAPON }, { IT_WEAPON_AXE, IIF_LEAVE_COOP, pickupAxe, TXT_TXT_WEAPON_F2, SFX_PICKUP_WEAPON }, { IT_WEAPON_HAMMER, IIF_LEAVE_COOP, pickupHammer, TXT_TXT_WEAPON_F3, SFX_PICKUP_WEAPON }, { IT_WEAPON_SERPENTSTAFF, IIF_LEAVE_COOP, pickupSerpentStaff, TXT_TXT_WEAPON_C2, SFX_PICKUP_WEAPON }, { IT_WEAPON_FIRESTORM, IIF_LEAVE_COOP, pickupFireStorm, TXT_TXT_WEAPON_C3, SFX_PICKUP_WEAPON }, { IT_WEAPON_QUIETUS1, IIF_LEAVE_COOP, pickupQuietus1, TXT_TXT_QUIETUS_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_QUIETUS2, IIF_LEAVE_COOP, pickupQuietus2, TXT_TXT_QUIETUS_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_QUIETUS3, IIF_LEAVE_COOP, pickupQuietus3, TXT_TXT_QUIETUS_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_WRAITHVERGE1, IIF_LEAVE_COOP, pickupWraithVerge1, TXT_TXT_WRAITHVERGE_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_WRAITHVERGE2, IIF_LEAVE_COOP, pickupWraithVerge2, TXT_TXT_WRAITHVERGE_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_WRAITHVERGE3, IIF_LEAVE_COOP, pickupWraithVerge3, TXT_TXT_WRAITHVERGE_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_BLOODSCOURGE1, IIF_LEAVE_COOP, pickupBloodScourge1, TXT_TXT_BLOODSCOURGE_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_BLOODSCOURGE2, IIF_LEAVE_COOP, pickupBloodScourge2, TXT_TXT_BLOODSCOURGE_PIECE, SFX_PICKUP_WEAPON }, { IT_WEAPON_BLOODSCOURGE3, IIF_LEAVE_COOP, pickupBloodScourge3, TXT_TXT_BLOODSCOURGE_PIECE, SFX_PICKUP_WEAPON } }; // CODE -------------------------------------------------------------------- void P_HideSpecialThing(mobj_t *thing) { thing->flags &= ~MF_SPECIAL; thing->flags2 |= MF2_DONTDRAW; P_MobjChangeState(thing, S_HIDESPECIAL1); } /** * @return @c true, if the player accepted the mana, * @c false, if it was refused (player has MAX_MANA) */ boolean P_GiveMana(player_t *plr, ammotype_t ammo, int num) { int prevMana; if(ammo == AT_NOAMMO) return false; if(ammo < 0 || ammo > NUM_AMMO_TYPES) Con_Error("P_GiveMana: bad type %i", ammo); if(!(plr->ammo[ammo].owned < MAX_MANA)) return false; if(gameSkill == SM_BABY || gameSkill == SM_NIGHTMARE) { // Extra mana in baby mode and nightmare mode. num += num / 2; } prevMana = plr->ammo[ammo].owned; // We are about to receive some more ammo. Does the plr want to // change weapon automatically? P_MaybeChangeWeapon(plr, WT_NOCHANGE, ammo, false); if(plr->ammo[ammo].owned + num > MAX_MANA) plr->ammo[ammo].owned = MAX_MANA; else plr->ammo[ammo].owned += num; plr->update |= PSF_AMMO; //// \fixme - DJS: This shouldn't be actioned from here. if(plr->class == PCLASS_FIGHTER && plr->readyWeapon == WT_SECOND && ammo == AT_BLUEMANA && prevMana <= 0) { P_SetPsprite(plr, ps_weapon, S_FAXEREADY_G); } // < FIXME // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_AMMO); return true; } static boolean giveWeaponWrongClassMana(player_t* plr, playerclass_t weaponClass, weapontype_t weaponType) { if(IS_NETGAME && !deathmatch) { // Can't pick up wrong-class weapons in coop netplay. return false; } if(!P_GiveMana(plr, (weaponType == WT_SECOND)? AT_BLUEMANA : AT_GREENMANA, 25)) { // Didn't need the mana, so don't pick it up. return false; } return true; } static boolean giveWeaponPieceWrongClassMana(player_t* plr, playerclass_t pieceClass) { if(IS_NETGAME && !deathmatch) { // Can't pick up wrong-class weapons in coop netplay. return false; } if(!P_GiveMana(plr, AT_BLUEMANA, 20) + P_GiveMana(plr, AT_GREENMANA, 20)) { // Didn't need the mana, so don't pick it up. return false; } return true; } boolean P_GiveWeapon(player_t* plr, playerclass_t matchClass, weapontype_t weaponType) { boolean gaveMana = false; if(plr->class != matchClass) return giveWeaponWrongClassMana(plr, matchClass, weaponType); plr->update |= PSF_WEAPONS; // Always attempt to give mana unless this a cooperative game and the // player already has this weapon piece. if(!(IS_NETGAME && !deathmatch && plr->weapons[weaponType].owned)) gaveMana = P_GiveMana(plr, (weaponType == WT_SECOND)? AT_BLUEMANA : AT_GREENMANA, 25); if(!plr->weapons[weaponType].owned) { plr->weapons[weaponType].owned = true; plr->update |= PSF_OWNED_WEAPONS; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_WEAPON); // Should we change weapon automatically? P_MaybeChangeWeapon(plr, weaponType, AT_NOAMMO, false); } else if(!gaveMana) { // Player didn't need the weapon or any mana. return false; } return true; } boolean P_GiveWeaponPiece(player_t* plr, playerclass_t matchClass, int pieceValue) { static int pieceValueTrans[] = { 0, // 0: never WPIECE1 | WPIECE2 | WPIECE3, // WPIECE1 (1) WPIECE2 | WPIECE3, // WPIECE2 (2) 0, // 3: never WPIECE3 // WPIECE3 (4) }; boolean gaveMana = false; if(plr->class != matchClass) return giveWeaponPieceWrongClassMana(plr, matchClass); // Always attempt to give mana unless this a cooperative game and the // player already has this weapon piece. if(!((plr->pieces & pieceValue) && IS_NETGAME && !deathmatch)) { gaveMana = P_GiveMana(plr, AT_BLUEMANA, 20) || P_GiveMana(plr, AT_GREENMANA, 20); } if(plr->pieces & pieceValue) { // Already has the piece. if(IS_NETGAME && !deathmatch) // Cooperative net-game. return false; // Deathmatch or single player. if(!gaveMana) // Didn't need the mana, so don't pick it up. return false; } // Check if fourth weapon assembled. if(IS_NETGAME && !deathmatch) // Cooperative net-game. pieceValue = pieceValueTrans[pieceValue]; if(!(plr->pieces & pieceValue)) { plr->pieces |= pieceValue; if(plr->pieces == (WPIECE1 | WPIECE2 | WPIECE3)) { plr->weapons[WT_FOURTH].owned = true; plr->pendingWeapon = WT_FOURTH; plr->update |= PSF_WEAPONS | PSF_OWNED_WEAPONS; // Should we change weapon automatically? P_MaybeChangeWeapon(plr, WT_FOURTH, AT_NOAMMO, false); } // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_WEAPON); } return true; } /** * @returns @c false, if the body isn't needed at all. */ boolean P_GiveBody(player_t* plr, int num) { int max; if(plr->morphTics) max = MAXMORPHHEALTH; else max = maxHealth; if(plr->health >= max) { return false; } plr->health += num; if(plr->health > max) { plr->health = max; } plr->plr->mo->health = plr->health; plr->update |= PSF_HEALTH; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_HEALTH); return true; } /** * @return @c true, iff the armor was given. */ boolean P_GiveArmor(player_t* plr, armortype_t type, int points) { if(plr->armorPoints[type] >= points) return false; P_PlayerGiveArmorBonus(plr, type, points - plr->armorPoints[type]); // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); return true; } /** * @return @c true, iff the armor was given. */ boolean P_GiveArmor2(player_t* plr, armortype_t type, int amount) { int hits, totalArmor; hits = amount * 5 * FRACUNIT; totalArmor = plr->armorPoints[ARMOR_ARMOR] + plr->armorPoints[ARMOR_SHIELD] + plr->armorPoints[ARMOR_HELMET] + plr->armorPoints[ARMOR_AMULET] + PCLASS_INFO(plr->class)->autoArmorSave; if(totalArmor >= PCLASS_INFO(plr->class)->maxArmor * 5 * FRACUNIT) return false; plr->armorPoints[type] += hits; plr->update |= PSF_ARMOR; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_ARMOR); return true; } int P_GiveKey(player_t *plr, keytype_t key) { if(plr->keys & (1 << key)) { return false; } plr->bonusCount += BONUSADD; plr->keys |= 1 << key; plr->update |= PSF_KEYS; // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_KEY); return true; } /** * @return @c true, if power accepted. */ boolean P_GivePower(player_t *plr, powertype_t power) { boolean retval = false; plr->update |= PSF_POWERS; switch(power) { case PT_INVULNERABILITY: if(!(plr->powers[power] > BLINKTHRESHOLD)) { plr->powers[power] = INVULNTICS; plr->plr->mo->flags2 |= MF2_INVULNERABLE; if(plr->class == PCLASS_MAGE) { plr->plr->mo->flags2 |= MF2_REFLECTIVE; } retval = true; } break; case PT_FLIGHT: if(!(plr->powers[power] > BLINKTHRESHOLD)) { plr->powers[power] = FLIGHTTICS; plr->plr->mo->flags2 |= MF2_FLY; plr->plr->mo->flags |= MF_NOGRAVITY; if(plr->plr->mo->pos[VZ] <= plr->plr->mo->floorZ) { plr->flyHeight = 10; // Thrust the plr in the air a bit. plr->plr->flags |= DDPF_FIXMOM; } retval = true; } break; case PT_INFRARED: if(!(plr->powers[power] > BLINKTHRESHOLD)) { plr->powers[power] = INFRATICS; retval = true; } break; case PT_SPEED: if(!(plr->powers[power] > BLINKTHRESHOLD)) { plr->powers[power] = SPEEDTICS; retval = true; } break; case PT_MINOTAUR: // Doesn't matter if already have power, renew ticker. plr->powers[power] = MAULATORTICS; retval = true; break; default: if(!(plr->powers[power])) { plr->powers[power] = 1; retval = true; } break; } if(retval) { // Maybe unhide the HUD? ST_HUDUnHide(plr - players, HUE_ON_PICKUP_POWER); } return retval; } boolean P_GiveItem(player_t* plr, inventoryitemtype_t item) { if(plr) return P_InventoryGive(plr - players, item, false); return false; } /** * Removes the MF_SPECIAL flag and initiates the item pickup animation. */ static void setDormantItem(mobj_t* mo) { mo->flags &= ~MF_SPECIAL; if(deathmatch && !(mo->flags2 & MF2_DROPPED)) { if(mo->type == MT_ARTIINVULNERABILITY) { P_MobjChangeState(mo, S_DORMANTARTI3_1); } else if(mo->type == MT_SUMMONMAULATOR || mo->type == MT_ARTIFLY) { P_MobjChangeState(mo, S_DORMANTARTI2_1); } else { P_MobjChangeState(mo, S_DORMANTARTI1_1); } } else { // Don't respawn. P_MobjChangeState(mo, S_DEADARTI1); } } void C_DECL A_RestoreArtifact(mobj_t* mo) { mo->flags |= MF_SPECIAL; P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN)); S_StartSound(SFX_RESPAWN, mo); } /** * Make a special thing visible again. */ void C_DECL A_RestoreSpecialThing1(mobj_t* thing) { thing->flags2 &= ~MF2_DONTDRAW; S_StartSound(SFX_RESPAWN, thing); } void C_DECL A_RestoreSpecialThing2(mobj_t* thing) { thing->flags |= MF_SPECIAL; P_MobjChangeState(thing, P_GetState(thing->type, SN_SPAWN)); } static itemtype_t getItemTypeBySprite(spritetype_e sprite) { static const struct item_s { itemtype_t type; spritetype_e sprite; } items[] = { { IT_HEALTH_VIAL, SPR_PTN1 }, { IT_ARMOR_MESH, SPR_ARM1 }, { IT_ARMOR_SHIELD, SPR_ARM2 }, { IT_ARMOR_HELMET, SPR_ARM3 }, { IT_ARMOR_AMULET, SPR_ARM4 }, { IT_KEY_STEEL, SPR_KEY1 }, { IT_KEY_CAVE, SPR_KEY2 }, { IT_KEY_AXE, SPR_KEY3 }, { IT_KEY_FIRE, SPR_KEY4 }, { IT_KEY_EMERALD, SPR_KEY5 }, { IT_KEY_DUNGEON, SPR_KEY6 }, { IT_KEY_SILVER, SPR_KEY7 }, { IT_KEY_RUSTED, SPR_KEY8 }, { IT_KEY_HORN, SPR_KEY9 }, { IT_KEY_SWAMP, SPR_KEYA }, { IT_KEY_CASTLE, SPR_KEYB }, { IT_ITEM_QUARTZFLASK, SPR_PTN2 }, { IT_ITEM_WINGS, SPR_SOAR }, { IT_ITEM_DEFENDER, SPR_INVU }, { IT_ITEM_SERVANT, SPR_SUMN }, { IT_ITEM_PORKALATOR, SPR_PORK }, { IT_ITEM_MYSTICURN, SPR_SPHL }, { IT_ITEM_AMBITINCANT, SPR_HRAD }, { IT_ITEM_TORCH, SPR_TRCH }, { IT_ITEM_CHAOSDEVICE, SPR_ATLP }, { IT_ITEM_BANISHDEVICE, SPR_TELO }, { IT_ITEM_FLETCHETTE, SPR_PSBG }, { IT_ITEM_BOOTSOFSPEED, SPR_SPED }, { IT_ITEM_KRATEROFMIGHT, SPR_BMAN }, { IT_ITEM_BRACERS, SPR_BRAC }, { IT_ITEM_REPULSION, SPR_BLST }, { IT_PUZZLE_SKULL, SPR_ASKU }, { IT_PUZZLE_BIGGEM, SPR_ABGM }, { IT_PUZZLE_REDGEM, SPR_AGMR }, { IT_PUZZLE_GREENGEM1, SPR_AGMG }, { IT_PUZZLE_GREENGEM2, SPR_AGG2 }, { IT_PUZZLE_BLUEGEM1, SPR_AGMB }, { IT_PUZZLE_BLUEGEM2, SPR_AGB2 }, { IT_PUZZLE_BOOK1, SPR_ABK1 }, { IT_PUZZLE_BOOK2, SPR_ABK2 }, { IT_PUZZLE_SKULL2, SPR_ASK2 }, { IT_PUZZLE_FWEAPON, SPR_AFWP }, { IT_PUZZLE_CWEAPON, SPR_ACWP }, { IT_PUZZLE_MWEAPON, SPR_AMWP }, { IT_PUZZLE_GEAR1, SPR_AGER }, { IT_PUZZLE_GEAR2, SPR_AGR2 }, { IT_PUZZLE_GEAR3, SPR_AGR3 }, { IT_PUZZLE_GEAR4, SPR_AGR4 }, { IT_MANA_BLUE, SPR_MAN1 }, { IT_MANA_GREEN, SPR_MAN2 }, { IT_MANA_COMBINED, SPR_MAN3 }, { IT_WEAPON_FROSTSHARDS, SPR_WMCS }, { IT_WEAPON_ARCOFDEATH, SPR_WMLG }, { IT_WEAPON_AXE, SPR_WFAX }, { IT_WEAPON_HAMMER, SPR_WFHM }, { IT_WEAPON_SERPENTSTAFF, SPR_WCSS }, { IT_WEAPON_FIRESTORM, SPR_WCFM }, { IT_WEAPON_QUIETUS1, SPR_WFR1 }, { IT_WEAPON_QUIETUS2, SPR_WFR2 }, { IT_WEAPON_QUIETUS3, SPR_WFR3 }, { IT_WEAPON_WRAITHVERGE1, SPR_WCH1 }, { IT_WEAPON_WRAITHVERGE2, SPR_WCH2 }, { IT_WEAPON_WRAITHVERGE3, SPR_WCH3 }, { IT_WEAPON_BLOODSCOURGE1, SPR_WMS1 }, { IT_WEAPON_BLOODSCOURGE2, SPR_WMS2 }, { IT_WEAPON_BLOODSCOURGE3, SPR_WMS3 }, { IT_NONE, 0 } }; uint i; for(i = 0; items[i].type != IT_NONE; ++i) if(items[i].sprite == sprite) return items[i].type; return IT_NONE; } static boolean pickupHealthVial(player_t* plr) { return P_GiveBody(plr, 10); } static boolean pickupMesh(player_t* plr) { return P_GiveArmor(plr, ARMOR_ARMOR, PCLASS_INFO(plr->class)->armorIncrement[ARMOR_ARMOR]); } static boolean pickupShield(player_t* plr) { return P_GiveArmor(plr, ARMOR_SHIELD, PCLASS_INFO(plr->class)->armorIncrement[ARMOR_SHIELD]); } static boolean pickupHelmet(player_t* plr) { return P_GiveArmor(plr, ARMOR_HELMET, PCLASS_INFO(plr->class)->armorIncrement[ARMOR_HELMET]); } static boolean pickupAmulet(player_t* plr) { return P_GiveArmor(plr, ARMOR_AMULET, PCLASS_INFO(plr->class)->armorIncrement[ARMOR_AMULET]); } static boolean pickupSteelKey(player_t* plr) { return P_GiveKey(plr, KT_KEY1); } static boolean pickupCaveKey(player_t* plr) { return P_GiveKey(plr, KT_KEY2); } static boolean pickupAxeKey(player_t* plr) { return P_GiveKey(plr, KT_KEY3); } static boolean pickupFireKey(player_t* plr) { return P_GiveKey(plr, KT_KEY4); } static boolean pickupEmeraldKey(player_t* plr) { return P_GiveKey(plr, KT_KEY5); } static boolean pickupDungeonKey(player_t* plr) { return P_GiveKey(plr, KT_KEY6); } static boolean pickupSilverKey(player_t* plr) { return P_GiveKey(plr, KT_KEY7); } static boolean pickupRustedKey(player_t* plr) { return P_GiveKey(plr, KT_KEY8); } static boolean pickupHornKey(player_t* plr) { return P_GiveKey(plr, KT_KEY9); } static boolean pickupSwampKey(player_t* plr) { return P_GiveKey(plr, KT_KEYA); } static boolean pickupCastleKey(player_t* plr) { return P_GiveKey(plr, KT_KEYB); } static boolean pickupQuartzFlask(player_t* plr) { return P_GiveItem(plr, IIT_HEALTH); } static boolean pickupWings(player_t* plr) { return P_GiveItem(plr, IIT_FLY); } static boolean pickupDefender(player_t* plr) { return P_GiveItem(plr, IIT_INVULNERABILITY); } static boolean pickupServant(player_t* plr) { return P_GiveItem(plr, IIT_SUMMON); } static boolean pickupPorkalator(player_t* plr) { return P_GiveItem(plr, IIT_EGG); } static boolean pickupMysticUrn(player_t* plr) { return P_GiveItem(plr, IIT_SUPERHEALTH); } static boolean pickupAmbitIncant(player_t* plr) { return P_GiveItem(plr, IIT_HEALINGRADIUS); } static boolean pickupTorch(player_t* plr) { return P_GiveItem(plr, IIT_TORCH); } static boolean pickupChaosDevice(player_t* plr) { return P_GiveItem(plr, IIT_TELEPORT); } static boolean pickupBanishDevice(player_t* plr) { return P_GiveItem(plr, IIT_TELEPORTOTHER); } static boolean pickupFletchette(player_t* plr) { return P_GiveItem(plr, IIT_POISONBAG); } static boolean pickupBootsOfSpeed(player_t* plr) { return P_GiveItem(plr, IIT_SPEED); } static boolean pickupKraterOfMight(player_t* plr) { return P_GiveItem(plr, IIT_BOOSTMANA); } static boolean pickupBracers(player_t* plr) { return P_GiveItem(plr, IIT_BOOSTARMOR); } static boolean pickupRepulsion(player_t* plr) { return P_GiveItem(plr, IIT_BLASTRADIUS); } static boolean pickupSkull(player_t* plr) { return P_GiveItem(plr, IIT_PUZZSKULL); } static boolean pickupBigGem(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEMBIG); } static boolean pickupRedGem(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEMRED); } static boolean pickupGreenGem1(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEMGREEN1); } static boolean pickupGreenGem2(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEMGREEN2); } static boolean pickupBlueGem1(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEMBLUE1); } static boolean pickupBlueGem2(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEMBLUE2); } static boolean pickupBook1(player_t* plr) { return P_GiveItem(plr, IIT_PUZZBOOK1); } static boolean pickupBook2(player_t* plr) { return P_GiveItem(plr, IIT_PUZZBOOK2); } static boolean pickupSkull2(player_t* plr) { return P_GiveItem(plr, IIT_PUZZSKULL2); } static boolean pickupFWeapon(player_t* plr) { return P_GiveItem(plr, IIT_PUZZFWEAPON); } static boolean pickupCWeapon(player_t* plr) { return P_GiveItem(plr, IIT_PUZZCWEAPON); } static boolean pickupMWeapon(player_t* plr) { return P_GiveItem(plr, IIT_PUZZMWEAPON); } static boolean pickupGear1(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEAR1); } static boolean pickupGear2(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEAR2); } static boolean pickupGear3(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEAR3); } static boolean pickupGear4(player_t* plr) { return P_GiveItem(plr, IIT_PUZZGEAR4); } static boolean pickupBlueMana(player_t* plr) { return P_GiveMana(plr, AT_BLUEMANA, 15); } static boolean pickupGreenMana(player_t* plr) { return P_GiveMana(plr, AT_GREENMANA, 15); } static boolean pickupCombinedMana(player_t* plr) { if(!P_GiveMana(plr, AT_BLUEMANA, 20)) { if(!P_GiveMana(plr, AT_GREENMANA, 20)) return false; } else { P_GiveMana(plr, AT_GREENMANA, 20); } return true; } static boolean pickupFrostShards(player_t* plr) { return P_GiveWeapon(plr, PCLASS_MAGE, WT_SECOND); } static boolean pickupArcOfDeath(player_t* plr) { return P_GiveWeapon(plr, PCLASS_MAGE, WT_THIRD); } static boolean pickupAxe(player_t* plr) { return P_GiveWeapon(plr, PCLASS_FIGHTER, WT_SECOND); } static boolean pickupHammer(player_t* plr) { return P_GiveWeapon(plr, PCLASS_FIGHTER, WT_THIRD); } static boolean pickupSerpentStaff(player_t* plr) { return P_GiveWeapon(plr, PCLASS_CLERIC, WT_SECOND); } static boolean pickupFireStorm(player_t* plr) { return P_GiveWeapon(plr, PCLASS_CLERIC, WT_THIRD); } static boolean pickupQuietus1(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_FIGHTER, WPIECE1); } static boolean pickupQuietus2(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_FIGHTER, WPIECE2); } static boolean pickupQuietus3(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_FIGHTER, WPIECE3); } static boolean pickupWraithVerge1(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_CLERIC, WPIECE1); } static boolean pickupWraithVerge2(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_CLERIC, WPIECE2); } static boolean pickupWraithVerge3(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_CLERIC, WPIECE3); } static boolean pickupBloodScourge1(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_MAGE, WPIECE1); } static boolean pickupBloodScourge2(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_MAGE, WPIECE2); } static boolean pickupBloodScourge3(player_t* plr) { return P_GiveWeaponPiece(plr, PCLASS_MAGE, WPIECE3); } static boolean giveItem(player_t* plr, itemtype_t item) { const iteminfo_t* info = &items[item]; int oldPieces = plr->pieces; if(!plr) return false; // Attempt to pickup the item. if(!info->giveFunc(plr)) return false; // Did not make use of it. switch(item) { case IT_WEAPON_QUIETUS1: case IT_WEAPON_QUIETUS2: case IT_WEAPON_QUIETUS3: case IT_WEAPON_WRAITHVERGE1: case IT_WEAPON_WRAITHVERGE2: case IT_WEAPON_WRAITHVERGE3: case IT_WEAPON_BLOODSCOURGE1: case IT_WEAPON_BLOODSCOURGE2: case IT_WEAPON_BLOODSCOURGE3: if(plr->pieces != oldPieces && plr->pieces == (WPIECE1 | WPIECE2 | WPIECE3)) { int msg; switch(item) { default: Con_Error("Internal Error: Item type %i not handled in " "giveItem.", (int) item); break; // Unreachable. case IT_WEAPON_QUIETUS1: case IT_WEAPON_QUIETUS2: case IT_WEAPON_QUIETUS3: msg = TXT_TXT_WEAPON_F4; break; case IT_WEAPON_WRAITHVERGE1: case IT_WEAPON_WRAITHVERGE2: case IT_WEAPON_WRAITHVERGE3: msg = TXT_TXT_WEAPON_C4; break; case IT_WEAPON_BLOODSCOURGE1: case IT_WEAPON_BLOODSCOURGE2: case IT_WEAPON_BLOODSCOURGE3: msg = TXT_TXT_WEAPON_M4; break; } P_SetMessage(plr, GET_TXT(msg), false); // Play the build-sound full volume for all players. S_StartSound(SFX_WEAPON_BUILD, NULL); break; } // Fall-through: default: S_StartSound(info->pickupSound, plr->plr->mo); P_SetMessage(plr, GET_TXT(info->pickupMsg), false); break; } return true; } void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher) { player_t* player; float delta; itemtype_t item; boolean wasUsed = false, removeItem = false; if(IS_CLIENT) return; delta = special->pos[VZ] - toucher->pos[VZ]; if(delta > toucher->height || delta < -32) { // Out of reach. return; } // Dead thing touching (can happen with a sliding player corpse). if(toucher->health <= 0) return; player = toucher->player; // Identify by sprite. if((item = getItemTypeBySprite(special->sprite)) != IT_NONE) { const iteminfo_t* info = &items[item]; if((wasUsed = giveItem(player, item))) { // Should we leave this item for others? if(!((info->flags & IIF_LEAVE_COOP) && IS_NETGAME && !deathmatch) && !((info->flags & IIF_LEAVE_DEATHMATCH) && IS_NETGAME && deathmatch)) removeItem = true; } } else { Con_Message("P_TouchSpecialMobj: Unknown gettable thing %i.\n", (int) special->type); } if(wasUsed && special->special) { P_ExecuteLineSpecial(special->special, special->args, NULL, 0, toucher); special->special = 0; } if(removeItem) { player->bonusCount += BONUSADD; /** * Taken items are handled differently depending upon the type of * item: inventory, puzzle or other. */ switch(item) { // Inventory: case IT_ITEM_QUARTZFLASK: case IT_ITEM_WINGS: case IT_ITEM_DEFENDER: case IT_ITEM_SERVANT: case IT_ITEM_PORKALATOR: case IT_ITEM_MYSTICURN: case IT_ITEM_AMBITINCANT: case IT_ITEM_TORCH: case IT_ITEM_CHAOSDEVICE: case IT_ITEM_BANISHDEVICE: case IT_ITEM_FLETCHETTE: case IT_ITEM_BOOTSOFSPEED: case IT_ITEM_KRATEROFMIGHT: case IT_ITEM_BRACERS: case IT_ITEM_REPULSION: setDormantItem(special); break; // Puzzle items: case IT_PUZZLE_SKULL: case IT_PUZZLE_BIGGEM: case IT_PUZZLE_REDGEM: case IT_PUZZLE_GREENGEM1: case IT_PUZZLE_GREENGEM2: case IT_PUZZLE_BLUEGEM1: case IT_PUZZLE_BLUEGEM2: case IT_PUZZLE_BOOK1: case IT_PUZZLE_BOOK2: case IT_PUZZLE_SKULL2: case IT_PUZZLE_FWEAPON: case IT_PUZZLE_CWEAPON: case IT_PUZZLE_MWEAPON: case IT_PUZZLE_GEAR1: case IT_PUZZLE_GEAR2: case IT_PUZZLE_GEAR3: case IT_PUZZLE_GEAR4: P_MobjRemove(special, false); break; default: if(deathmatch && !(special->flags2 & MF2_DROPPED)) P_HideSpecialThing(special); else P_MobjRemove(special, false); break; } } } typedef struct { player_t* master; mobj_t* foundMobj; } findactiveminotaurparams_t; static boolean findActiveMinotaur(thinker_t* th, void* context) { findactiveminotaurparams_t* params = (findactiveminotaurparams_t*) context; mobj_t* mo = (mobj_t *) th; if(mo->type != MT_MINOTAUR) return true; // Continue iteration. if(mo->health <= 0) return true; // Continue iteration. if(!(mo->flags & MF_COUNTKILL)) // For morphed minotaurs. return true; // Continue iteration. if(mo->flags & MF_CORPSE) return true; // Continue iteration. if((mapTime - *((unsigned int *) mo->args)) >= MAULATORTICS) return true; // Continue iteration. if(mo->tracer->player == params->master) { // Found it! params->foundMobj = mo; return false; // Stop iteration. } return true; // Continue iteration. } mobj_t* ActiveMinotaur(player_t* master) { findactiveminotaurparams_t params; params.master = master; params.foundMobj = NULL; if(!DD_IterateThinkers(P_MobjThinker, findActiveMinotaur, ¶ms)) return params.foundMobj; return NULL; } void P_KillMobj(mobj_t* source, mobj_t* target) { int dummy; mobj_t* master; statenum_t state; if(!target) return; // Nothing to kill. target->flags &= ~(MF_SHOOTABLE | MF_FLOAT | MF_SKULLFLY | MF_NOGRAVITY); target->flags |= MF_CORPSE | MF_DROPOFF; target->flags2 &= ~MF2_PASSMOBJ; target->height /= 2*2; if((target->flags & MF_COUNTKILL || target->type == MT_ZBELL) && target->special) { // Initiate monster death actions. if(target->type == MT_SORCBOSS) { dummy = 0; P_StartACS(target->special, 0, (byte *) &dummy, target, NULL, 0); } else { P_ExecuteLineSpecial(target->special, target->args, NULL, 0, target); } } if(source && source->player) { // Check for frag changes. if(target->player && deathmatch) { if(target == source) { // Self-frag. target->player->frags[target->player - players]--; NetSv_FragsForAll(target->player); } else { source->player->frags[target->player - players]++; NetSv_FragsForAll(source->player); } } } if(target->player) { // Player death. if(!source) { // Self-frag target->player->frags[target->player - players]--; NetSv_FragsForAll(target->player); } target->flags &= ~MF_SOLID; target->flags2 &= ~MF2_FLY; target->player->powers[PT_FLIGHT] = 0; target->player->playerState = PST_DEAD; target->player->rebornWait = PLAYER_REBORN_TICS; target->player->update |= PSF_STATE | PSF_POWERS; // Let the engine know about this, too. The DEAD flag will be // cleared when the player is reborn. target->player->plr->flags |= DDPF_DEAD; P_DropWeapon(target->player); if(target->flags2 & MF2_FIREDAMAGE) { // Player flame death. //// \todo Should be pulled from the player class definition. switch(target->player->class) { case PCLASS_FIGHTER: S_StartSound(SFX_PLAYER_FIGHTER_BURN_DEATH, target); P_MobjChangeState(target, S_PLAY_F_FDTH1); return; case PCLASS_CLERIC: S_StartSound(SFX_PLAYER_CLERIC_BURN_DEATH, target); P_MobjChangeState(target, S_PLAY_C_FDTH1); return; case PCLASS_MAGE: S_StartSound(SFX_PLAYER_MAGE_BURN_DEATH, target); P_MobjChangeState(target, S_PLAY_M_FDTH1); return; default: break; } } if(target->flags2 & MF2_ICEDAMAGE) { // Player ice death. target->flags &= ~(7 << MF_TRANSSHIFT); //no translation target->flags |= MF_ICECORPSE; //// \todo Should be pulled from the player class definition. switch(target->player->class) { case PCLASS_FIGHTER: P_MobjChangeState(target, S_FPLAY_ICE); return; case PCLASS_CLERIC: P_MobjChangeState(target, S_CPLAY_ICE); return; case PCLASS_MAGE: P_MobjChangeState(target, S_MPLAY_ICE); return; case PCLASS_PIG: P_MobjChangeState(target, S_PIG_ICE); return; default: break; } } // Don't die with the automap open. AM_Open(AM_MapForPlayer(target->player - players), false, false); } else { // Target is some monster or an object. /** * mobj death, record as player's kill in netgame + coop could not * find MF_ targets->flags that indicated *only* enemies (not trees, * pots, etc), so built a list. * * \todo This should be a Thing definition flag. */ if(IS_NETGAME && !deathmatch && source && source->player && source->player->plr && (target->type == MT_CENTAUR || target->type == MT_CENTAURLEADER || target->type == MT_DEMON || target->type == MT_DEMON2 || target->type == MT_ETTIN || target->type == MT_PIG || target->type == MT_FIREDEMON || target->type == MT_SERPENT || target->type == MT_SERPENTLEADER || target->type == MT_WRAITH || target->type == MT_WRAITHB || target->type == MT_BISHOP || target->type == MT_ICEGUY || target->type == MT_FIGHTER_BOSS || target->type == MT_CLERIC_BOSS || target->type == MT_MAGE_BOSS || target->type == MT_MINOTAUR)) { source->player->frags[0]++; } } if(target->flags2 & MF2_FIREDAMAGE) { if(target->type == MT_FIGHTER_BOSS || target->type == MT_CLERIC_BOSS || target->type == MT_MAGE_BOSS) { switch(target->type) { case MT_FIGHTER_BOSS: S_StartSound(SFX_PLAYER_FIGHTER_BURN_DEATH, target); P_MobjChangeState(target, S_PLAY_F_FDTH1); return; case MT_CLERIC_BOSS: S_StartSound(SFX_PLAYER_CLERIC_BURN_DEATH, target); P_MobjChangeState(target, S_PLAY_C_FDTH1); return; case MT_MAGE_BOSS: S_StartSound(SFX_PLAYER_MAGE_BURN_DEATH, target); P_MobjChangeState(target, S_PLAY_M_FDTH1); return; default: break; } } else if(target->type == MT_TREEDESTRUCTIBLE) { P_MobjChangeState(target, S_ZTREEDES_X1); target->height = 24; S_StartSound(SFX_TREE_EXPLODE, target); return; } } if(target->flags2 & MF2_ICEDAMAGE) { target->flags |= MF_ICECORPSE; switch(target->type) { case MT_BISHOP: P_MobjChangeState(target, S_BISHOP_ICE); return; case MT_CENTAUR: case MT_CENTAURLEADER: P_MobjChangeState(target, S_CENTAUR_ICE); return; case MT_DEMON: case MT_DEMON2: P_MobjChangeState(target, S_DEMON_ICE); return; case MT_SERPENT: case MT_SERPENTLEADER: P_MobjChangeState(target, S_SERPENT_ICE); return; case MT_WRAITH: case MT_WRAITHB: P_MobjChangeState(target, S_WRAITH_ICE); return; case MT_ETTIN: P_MobjChangeState(target, S_ETTIN_ICE1); return; case MT_FIREDEMON: P_MobjChangeState(target, S_FIRED_ICE1); return; case MT_FIGHTER_BOSS: P_MobjChangeState(target, S_FIGHTER_ICE); return; case MT_CLERIC_BOSS: P_MobjChangeState(target, S_CLERIC_ICE); return; case MT_MAGE_BOSS: P_MobjChangeState(target, S_MAGE_ICE); return; case MT_PIG: P_MobjChangeState(target, S_PIG_ICE); return; default: target->flags &= ~MF_ICECORPSE; break; } } if(target->type == MT_MINOTAUR) { master = target->tracer; if(master && master->health > 0) { if(!ActiveMinotaur(master->player)) { master->player->powers[PT_MINOTAUR] = 0; } } } else if(target->type == MT_TREEDESTRUCTIBLE) { target->height = 24; } if((state = P_GetState(target->type, SN_XDEATH)) != S_NULL && target->health < -(target->info->spawnHealth / 2)) { // Extreme death. P_MobjChangeState(target, state); } else { // Normal death. if((state = P_GetState(target->type, SN_XDEATH)) != S_NULL && target->type == MT_FIREDEMON && target->pos[VZ] <= target->floorZ + 2) { // This is to fix the imps' staying in fall state. P_MobjChangeState(target, state); } else { P_MobjChangeState(target, P_GetState(target->type, SN_DEATH)); } } target->tics -= P_Random() & 3; } /** * @return @c true, if the player gets turned into a pig. */ boolean P_MorphPlayer(player_t *player) { mobj_t *pmo, *fog, *beastMo; float pos[3]; angle_t angle; int oldFlags2; if(player->powers[PT_INVULNERABILITY]) return false; // Immune when invulnerable. if(player->morphTics) return false; // Player is already morphed. pmo = player->plr->mo; pos[VX] = pmo->pos[VX]; pos[VY] = pmo->pos[VY]; pos[VZ] = pmo->pos[VZ]; angle = pmo->angle; oldFlags2 = pmo->flags2; if(!(beastMo = P_SpawnMobj3fv(MT_PIGPLAYER, pos, angle, 0))) return false; P_MobjChangeState(pmo, S_FREETARGMOBJ); if((fog = P_SpawnMobj3f(MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, angle + ANG180, 0))) S_StartSound(SFX_TELEPORT, fog); beastMo->special1 = player->readyWeapon; beastMo->player = player; beastMo->dPlayer = player->plr; player->health = beastMo->health = MAXMORPHHEALTH; player->plr->mo = beastMo; memset(&player->armorPoints[0], 0, NUMARMOR * sizeof(int)); player->class = PCLASS_PIG; if(oldFlags2 & MF2_FLY) beastMo->flags2 |= MF2_FLY; player->morphTics = MORPHTICS; player->update |= PSF_MORPH_TIME | PSF_HEALTH; player->plr->flags |= DDPF_FIXPOS | DDPF_FIXMOM; P_ActivateMorphWeapon(player); return true; } boolean P_MorphMonster(mobj_t *actor) { mobj_t* master, *monster, *fog; mobjtype_t moType; float pos[3]; mobj_t oldMonster; angle_t oldAngle; if(actor->player) return (false); if(!(actor->flags & MF_COUNTKILL)) return false; if(actor->flags2 & MF2_BOSS) return false; moType = actor->type; switch(moType) { case MT_PIG: case MT_FIGHTER_BOSS: case MT_CLERIC_BOSS: case MT_MAGE_BOSS: return false; default: break; } //// \fixme Do this properly! oldMonster = *actor; pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = actor->pos[VZ]; oldAngle = actor->angle; if(!(monster = P_SpawnMobj3fv(MT_PIG, pos, oldMonster.angle, 0))) return false; P_MobjRemoveFromTIDList(actor); P_MobjChangeState(actor, S_FREETARGMOBJ); if((fog = P_SpawnMobj3f(MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPORT, fog); monster->special2 = moType; monster->special1 = MORPHTICS + P_Random(); monster->flags |= (oldMonster.flags & MF_SHADOW); monster->target = oldMonster.target; monster->tid = oldMonster.tid; monster->special = oldMonster.special; P_MobjInsertIntoTIDList(monster, oldMonster.tid); memcpy(monster->args, oldMonster.args, 5); // Check for turning off minotaur power for active icon. if(moType == MT_MINOTAUR) { master = oldMonster.tracer; if(master->health > 0) { if(!ActiveMinotaur(master->player)) { master->player->powers[PT_MINOTAUR] = 0; } } } return true; } void P_AutoUseHealth(player_t* player, int saveHealth) { uint i, count; int plrnum = player - players; int normalCount = P_InventoryCount(plrnum, IIT_HEALTH); int superCount = P_InventoryCount(plrnum, IIT_SUPERHEALTH); //// \todo Do this in the inventory code? if(gameSkill == SM_BABY && normalCount * 25 >= saveHealth) { // Use quartz flasks. count = (saveHealth + 24) / 25; for(i = 0; i < count; ++i) { player->health += 25; P_InventoryTake(plrnum, IIT_HEALTH, false); } } else if(superCount * 100 >= saveHealth) { // Use mystic urns. count = (saveHealth + 99) / 100; for(i = 0; i < count; ++i) { player->health += 100; P_InventoryTake(plrnum, IIT_SUPERHEALTH, false); } } else if(gameSkill == SM_BABY && superCount * 100 + normalCount * 25 >= saveHealth) { // Use mystic urns and quartz flasks. count = (saveHealth + 24) / 25; saveHealth -= count * 25; for(i = 0; i < count; ++i) { player->health += 25; P_InventoryTake(plrnum, IIT_HEALTH, false); } count = (saveHealth + 99) / 100; for(i = 0; i < count; ++i) { player->health += 100; P_InventoryTake(plrnum, IIT_SUPERHEALTH, false); } } player->plr->mo->health = player->health; } /** * Sets up all data concerning poisoning. */ void P_PoisonPlayer(player_t *player, mobj_t *poisoner, int poison) { if((P_GetPlayerCheats(player) & CF_GODMODE) || player->powers[PT_INVULNERABILITY]) return; player->poisonCount += poison; player->poisoner = poisoner; if(player->poisonCount > 100) player->poisonCount = 100; } /** * Damages both enemies and players * \note 'source' and 'inflictor' are the same for melee attacks. * 'source' can be NULL for slime, barrel explosions and other environmental * stuff. * * @param inflictor Is the mobj that caused the damage, creature or * missile, can be @c NULL (slime, etc). * @param source Is the mobj to target after taking damage * creature or @c NULL. */ int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damageP, boolean stomping) { uint an; angle_t angle; int i, temp, originalHealth; float thrust, saved, savedPercent; player_t* player; mobj_t* master; int damage; if(!target) return 0; // Wha? originalHealth = target->health; // The actual damage (== damageP * netMobDamageModifier for any // non-player mobj). damage = damageP; if(IS_NETGAME && !stomping && D_NetDamageMobj(target, inflictor, source, damage)) { // We're done here. return 0; } // Clients can't harm anybody. if(IS_CLIENT) return 0; if(!(target->flags & MF_SHOOTABLE)) return 0; // Shouldn't happen. if(target->health <= 0) { if(!(inflictor && (inflictor->flags2 & MF2_ICEDAMAGE)) && (target->flags & MF_ICECORPSE)) { // Frozen. target->tics = 1; target->mom[MX] = target->mom[MY] = 0; } return 0; } if((target->flags2 & MF2_INVULNERABLE) && damage < 10000) { // mobj is invulnerable. if(target->player) return 0; // for player, no exceptions. if(!inflictor) return 0; switch(inflictor->type) { // These inflictors aren't foiled by invulnerability. case MT_HOLY_FX: case MT_POISONCLOUD: case MT_FIREBOMB: break; default: return 0; } } if(target->player) { // Player specific. // Check if player-player damage is disabled. if(source && source->player && source->player != target->player) { #if 0 // Co-op damage disabled? if(IS_NETGAME && !deathmatch && cfg.noCoopDamage) return 0; // Same color, no damage? if(cfg.noTeamDamage && cfg.playerColor[target->player - players] == cfg.playerColor[source->player - players]) return 0; #endif } } if(target->flags & MF_SKULLFLY) { target->mom[MX] = target->mom[MY] = target->mom[MZ] = 0; } if(target->flags2 & MF2_DORMANT) return 0; // Invulnerable, and won't wake up. player = target->player; if(player && gameSkill == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the // inflictor is not a player. if(inflictor && !inflictor->player && (!source || (source && !source->player))) { // damage = (int) ((float) damage * netMobDamageModifier); if(IS_NETGAME) damage *= cfg.netMobDamageModifier; } // Special damage types. if(inflictor) { switch(inflictor->type) { case MT_EGGFX: if(player) { P_MorphPlayer(player); } else { P_MorphMonster(target); } return 0; // Does no actual "damage" but health IS modified. case MT_TELOTHER_FX1: case MT_TELOTHER_FX2: case MT_TELOTHER_FX3: case MT_TELOTHER_FX4: case MT_TELOTHER_FX5: if((target->flags & MF_COUNTKILL) && (target->type != MT_SERPENT) && (target->type != MT_SERPENTLEADER) && (!(target->flags2 & MF2_BOSS))) { if(target->player) { if(deathmatch) P_TeleportToDeathmatchStarts(target); else P_TeleportToPlayerStarts(target); } else { // If death action, run it upon teleport. if(target->flags & MF_COUNTKILL && target->special) { P_MobjRemoveFromTIDList(target); P_ExecuteLineSpecial(target->special, target->args, NULL, 0, target); target->special = 0; } // Send all monsters to deathmatch spots. P_TeleportToDeathmatchStarts(target); } } return 0; case MT_MINOTAUR: if(inflictor->flags & MF_SKULLFLY) { // Slam only when in charge mode. uint an; int damageDone; angle_t angle; float thrust; angle = R_PointToAngle2(inflictor->pos[VX], inflictor->pos[VY], target->pos[VX], target->pos[VY]); an = angle >> ANGLETOFINESHIFT; thrust = 16 + FIX2FLT(P_Random() << 10); target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); damageDone = P_DamageMobj(target, NULL, inflictor, HITDICE(4), false); if(target->player) { target->reactionTime = 14 + (P_Random() & 7); } inflictor->args[0] = 0; // Stop charging. return damageDone; } break; case MT_BISH_FX: // Bishops are just too nasty. damage /= 2; break; case MT_SHARDFX1: switch(inflictor->special2) { case 3: damage *= 8; break; case 2: damage *= 4; break; case 1: damage *= 2; break; default: break; } break; case MT_CSTAFF_MISSILE: // Cleric Serpent Staff does poison damage. if(target->player) { P_PoisonPlayer(target->player, source, 20); damage /= 2; } break; case MT_ICEGUY_FX2: damage /= 2; break; case MT_POISONDART: if(target->player) { P_PoisonPlayer(target->player, source, 20); damage /= 2; } break; case MT_POISONCLOUD: if(target->player) { int damageDone = 0; if(target->player->poisonCount < 4) { damageDone = P_PoisonDamage(target->player, source, 15 + (P_Random() & 15), false); // Don't play painsound P_PoisonPlayer(target->player, source, 50); S_StartSound(SFX_PLAYER_POISONCOUGH, target); } return damageDone; } else if(!(target->flags & MF_COUNTKILL)) { // Only damage monsters/players with the poison cloud. return 0; } break; case MT_FSWORD_MISSILE: if(target->player) { damage -= damage / 4; } break; default: break; } } // Some close combat weapons should not inflict thrust and push the // victim out of reach, thus kick away unless using a melee weapon. if(inflictor && (!source || !source->player) && !(inflictor->flags2 & MF2_NODMGTHRUST)) { angle = R_PointToAngle2(inflictor->pos[VX], inflictor->pos[VY], target->pos[VX], target->pos[VY]); if(!target->info->mass) Con_Error("P_DamageMobj: No target->info->mass!\n"); thrust = FIX2FLT(damage * (FRACUNIT>>3) * 100 / target->info->mass); // Make fall forwards sometimes. if((damage < 40) && (damage > target->health) && (target->pos[VZ] - inflictor->pos[VZ] > 64) && (P_Random() & 1)) { angle += ANG180; thrust *= 4; } an = angle >>ANGLETOFINESHIFT; target->mom[MX] += thrust * FIX2FLT(finecosine[an]); target->mom[MY] += thrust * FIX2FLT(finesine[an]); if(target->dPlayer) { // Only fix momentum. Otherwise clients will find it difficult // to escape from the damage inflictor. target->dPlayer->flags |= DDPF_FIXMOM; } } // Player specific. if(player) { target->player->update |= PSF_HEALTH; if(damage < 1000 && ((P_GetPlayerCheats(target->player) & CF_GODMODE) || target->player->powers[PT_INVULNERABILITY])) { return 0; } savedPercent = FIX2FLT( PCLASS_INFO(player->class)->autoArmorSave + player->armorPoints[ARMOR_ARMOR] + player->armorPoints[ARMOR_SHIELD] + player->armorPoints[ARMOR_HELMET] + player->armorPoints[ARMOR_AMULET]); if(savedPercent) { // Armor absorbed some damage. if(savedPercent > 100) { savedPercent = 100; } for(i = 0; i < NUMARMOR; ++i) { if(player->armorPoints[i]) { player->armorPoints[i] -= FLT2FIX(((float) damage * FIX2FLT(PCLASS_INFO(player->class)->armorIncrement[i])) / 300); if(player->armorPoints[i] < 2 * FRACUNIT) { player->armorPoints[i] = 0; } } } saved = ((float) damage * savedPercent) / 100; if(saved > savedPercent * 2) saved = savedPercent * 2; damage -= (int) saved; } if(damage >= player->health && ((gameSkill == SM_BABY) || deathmatch) && !player->morphTics) { // Try to use some inventory health. P_AutoUseHealth(player, damage - player->health + 1); } player->health -= damage; if(player->health < 0) player->health = 0; player->attacker = source; player->damageCount += damage; // Add damage after armor / invuln. if(player->damageCount > 100) player->damageCount = 100; // Teleport stomp does 10k points... temp = (damage < 100 ? damage : 100); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_DAMAGE); ST_doPaletteStuff(player - players, false); } // How about some particles, yes? // Only works when both target and inflictor are real mobjs. P_SpawnDamageParticleGen(target, inflictor, damage); // Do the damage. target->health -= damage; if(target->health > 0) { // Still alive, phew! if((P_Random() < target->info->painChance) && !(target->flags & MF_SKULLFLY)) { if(inflictor && (inflictor->type >= MT_LIGHTNING_FLOOR && inflictor->type <= MT_LIGHTNING_ZAP)) { if(P_Random() < 96) { statenum_t state; target->flags |= MF_JUSTHIT; // fight back! if((state = P_GetState(target->type, SN_PAIN)) != S_NULL) P_MobjChangeState(target, state); } else { // "electrocute" the target. //// \fixme make fullbright for this frame --> //target->frame |= FF_FULLBRIGHT; // <-- fixme if((target->flags & MF_COUNTKILL) && P_Random() < 128 && !S_IsPlaying(SFX_PUPPYBEAT, target)) { if((target->type == MT_CENTAUR) || (target->type == MT_CENTAURLEADER) || (target->type == MT_ETTIN)) { S_StartSound(SFX_PUPPYBEAT, target); } } } } else { statenum_t state; target->flags |= MF_JUSTHIT; // fight back! if((state = P_GetState(target->type, SN_PAIN)) != S_NULL) P_MobjChangeState(target, state); if(inflictor && inflictor->type == MT_POISONCLOUD) { if(target->flags & MF_COUNTKILL && P_Random() < 128 && !S_IsPlaying(SFX_PUPPYBEAT, target)) { if((target->type == MT_CENTAUR) || (target->type == MT_CENTAURLEADER) || (target->type == MT_ETTIN)) { S_StartSound(SFX_PUPPYBEAT, target); } } } } } target->reactionTime = 0; // We're awake now... if(!target->threshold && source && !(source->flags3 & MF3_NOINFIGHT) && !(target->type == MT_BISHOP) && !(target->type == MT_MINOTAUR)) { // Target is not intent on another, so make it chase source. if(!((target->type == MT_CENTAUR && source->type == MT_CENTAURLEADER) || (target->type == MT_CENTAURLEADER && source->type == MT_CENTAUR))) { statenum_t state; target->target = source; target->threshold = BASETHRESHOLD; if((state = P_GetState(target->type, SN_SEE)) != S_NULL && target->state == &STATES[P_GetState(target->type, SN_SPAWN)]) { P_MobjChangeState(target, state); } } } } else { // Death. if(inflictor) { // Check for special fire damage or ice damage deaths. if(inflictor->flags2 & MF2_FIREDAMAGE) { if(player && !player->morphTics) { // Check for flame death. if(target->health > -50 && damage > 25) { target->flags2 |= MF2_FIREDAMAGE; } } else { target->flags2 |= MF2_FIREDAMAGE; } } else if(inflictor->flags2 & MF2_ICEDAMAGE) { target->flags2 |= MF2_ICEDAMAGE; } } if(source && (source->type == MT_MINOTAUR)) { // Minotaur's kills go to his master. master = source->tracer; // Make sure still alive and not a pointer to fighter head. if(master->player && (master->player->plr->mo == master)) { source = master; } } if(source && (source->player) && (source->player->readyWeapon == WT_FOURTH)) { // Always extreme death from fourth weapon. target->health = -5000; } P_KillMobj(source, target); } return originalHealth - target->health; } int P_FallingDamage(player_t *player) { int damage; float mom, dist; mom = fabs(player->plr->mo->mom[MZ]); dist = mom * (16.0f / 23); if(mom >= 63) { // Automatic death. return P_DamageMobj(player->plr->mo, NULL, NULL, 10000, false); } damage = ((dist * dist) / 10) - 24; if(player->plr->mo->mom[MZ] > -39 && damage > player->plr->mo->health && player->plr->mo->health != 1) { // No-death threshold. damage = player->plr->mo->health - 1; } S_StartSound(SFX_PLAYER_LAND, player->plr->mo); return P_DamageMobj(player->plr->mo, NULL, NULL, damage, false); } int P_PoisonDamage(player_t* player, mobj_t* source, int damage, boolean playPainSound) { int originalHealth; mobj_t* target, *inflictor; target = player->plr->mo; originalHealth = target->health; inflictor = source; if(target->health <= 0) return 0; // Already dead. if((target->flags2 & MF2_INVULNERABLE) && damage < 10000) return 0; // mobj is invulnerable. if(gameSkill == SM_BABY) { // Take half damage in trainer mode damage /= 2; } if(damage < 1000 && ((P_GetPlayerCheats(player) & CF_GODMODE) || player->powers[PT_INVULNERABILITY])) { return 0; } if(damage >= player->health && ((gameSkill == SM_BABY) || deathmatch) && !player->morphTics) { // Try to use some inventory health. P_AutoUseHealth(player, damage - player->health + 1); } // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_DAMAGE); player->health -= damage; if(player->health < 0) { player->health = 0; } player->attacker = source; // Do the damage. target->health -= damage; if(target->health > 0) { // Still alive, phew! if(!(mapTime & 63) && playPainSound) { statenum_t state; if((state = P_GetState(target->type, SN_PAIN)) != S_NULL) P_MobjChangeState(target, state); } } else { // Death target->special1 = damage; if(player && inflictor && !player->morphTics) { // Check for flame death. if((inflictor->flags2 & MF2_FIREDAMAGE) && (target->health > -50) && (damage > 25)) { target->flags2 |= MF2_FIREDAMAGE; } if(inflictor->flags2 & MF2_ICEDAMAGE) { target->flags2 |= MF2_ICEDAMAGE; } } P_KillMobj(source, target); } return originalHealth - target->health; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_pspr.c0000644000175000017500000017723011357170242022277 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.c: Weapon sprite animation. * * Weapon sprite animation, weapon objects. * Action functions for weapons. */ // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "p_player.h" #include "p_map.h" #include "p_inventory.h" // MACROS ------------------------------------------------------------------ #define LOWERSPEED (6) #define RAISESPEED (6) #define WEAPONBOTTOM (128) #define WEAPONTOP (32) #define ZAGSPEED (1) #define MAX_ANGLE_ADJUST (5*ANGLE_1) #define HAMMER_RANGE (MELEERANGE+MELEERANGE/2) #define AXERANGE (2.25*MELEERANGE) #define FLAMESPEED (0.45) #define FLAMEROTSPEED (2) #define SHARDSPAWN_LEFT (1) #define SHARDSPAWN_RIGHT (2) #define SHARDSPAWN_UP (4) #define SHARDSPAWN_DOWN (8) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- float bulletSlope; weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES] = { { // First Weapons { // Fighter First Weapon - Punch { GM_ANY, // Gamemode bits {0, 0}, // type: mana1 | mana2 {0, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_PUNCHUP, S_PUNCHDOWN, S_PUNCHREADY, S_PUNCHATK1_1, S_PUNCHATK1_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Cleric First Weapon - Mace GM_ANY, // Gamemode bits {0, 0}, // type: mana1 | mana2 {0, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_CMACEUP, S_CMACEDOWN, S_CMACEREADY, S_CMACEATK_1, S_CMACEATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Mage First Weapon - Wand GM_ANY, // Gamemode bits {0, 0}, // type: mana1 | mana2 {0, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_MWANDUP, S_MWANDDOWN, S_MWANDREADY, S_MWANDATK_1, S_MWANDATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Pig - Snout GM_ANY, // Gamemode bits {0, 0}, // type: mana1 | mana2 {0, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_SNOUTUP, S_SNOUTDOWN, S_SNOUTREADY, S_SNOUTATK1, S_SNOUTATK1, S_NULL }, 0, // raise sound id 0 // readysound } } }, { // Second Weapons { { // Fighter - Axe GM_ANY, // Gamemode bits {1, 0}, // type: mana1 | mana2 {2, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_FAXEUP, S_FAXEDOWN, S_FAXEREADY, S_FAXEATK_1, S_FAXEATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Cleric - Serpent Staff GM_ANY, // Gamemode bits {1, 0}, // type: mana1 | mana2 {1, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_CSTAFFUP, S_CSTAFFDOWN, S_CSTAFFREADY, S_CSTAFFATK_1, S_CSTAFFATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Mage - Cone of shards GM_ANY, // Gamemode bits {1, 0}, // type: mana1 | mana2 {3, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_CONEUP, S_CONEDOWN, S_CONEREADY, S_CONEATK1_1, S_CONEATK1_3, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Pig - Snout GM_ANY, // Gamemode bits {0, 0}, // type: mana1 | mana2 {0, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_SNOUTUP, S_SNOUTDOWN, S_SNOUTREADY, S_SNOUTATK1, S_SNOUTATK1, S_NULL }, 0, // raise sound id 0 // readysound } } }, { // Third Weapons { { // Fighter - Hammer GM_ANY, // Gamemode bits {0, 1}, // type: mana1 | mana2 {0, 3}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_FHAMMERUP, S_FHAMMERDOWN, S_FHAMMERREADY, S_FHAMMERATK_1, S_FHAMMERATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Cleric - Flame Strike GM_ANY, // Gamemode bits {0, 1}, // type: mana1 | mana2 {0, 4}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_CFLAMEUP, S_CFLAMEDOWN, S_CFLAMEREADY1, S_CFLAMEATK_1, S_CFLAMEATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Mage - Lightning GM_ANY, // Gamemode bits {0, 1}, // type: mana1 | mana2 {0, 5}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_MLIGHTNINGUP, S_MLIGHTNINGDOWN, S_MLIGHTNINGREADY, S_MLIGHTNINGATK_1, S_MLIGHTNINGATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Pig - Snout GM_ANY, // Gamemode bits {0, 0}, // type: mana1 | mana2 {0, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_SNOUTUP, S_SNOUTDOWN, S_SNOUTREADY, S_SNOUTATK1, S_SNOUTATK1, S_NULL }, 0, // raise sound id 0 // readysound } } }, { // Fourth Weapons { { // Fighter - Rune Sword GM_ANY, // Gamemode bits {1, 1}, // type: mana1 | mana2 {14, 14}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_FSWORDUP, S_FSWORDDOWN, S_FSWORDREADY, S_FSWORDATK_1, S_FSWORDATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Cleric - Holy Symbol GM_ANY, // Gamemode bits {1, 1}, // type: mana1 | mana2 {18, 18}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_CHOLYUP, S_CHOLYDOWN, S_CHOLYREADY, S_CHOLYATK_1, S_CHOLYATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Mage - Staff GM_ANY, // Gamemode bits {1, 1}, // type: mana1 | mana2 {15, 15}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_MSTAFFUP, S_MSTAFFDOWN, S_MSTAFFREADY, S_MSTAFFATK_1, S_MSTAFFATK_1, S_NULL }, 0, // raise sound id 0 // readysound } }, { { // Pig - Snout GM_ANY, // Gamemode bits {0, 0}, // type: mana1 | mana2 {0, 0}, // pershot: mana1 | mana2 true, // autofire when raised if fire held { S_SNOUTUP, S_SNOUTDOWN, S_SNOUTREADY, S_SNOUTATK1, S_SNOUTATK1, S_NULL }, 0, // raise sound id 0 // readysound } } } }; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void R_GetWeaponBob(int player, float* x, float* y) { if(x) { if(players[player].morphTics > 0) *x = 0; else *x = 1 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finecosine[(128 * mapTime) & FINEMASK]); } if(y) { if(players[player].morphTics > 0) *y = 0; else *y = 32 + (cfg.bobWeapon * players[player].bob) * FIX2FLT(finesine[(128 * mapTime) & FINEMASK & (FINEANGLES / 2 - 1)]); } } /** *Initialize weapon info, maxammo and clipammo. */ void P_InitWeaponInfo(void) { /// \todo Get this info from values. P_InitWeaponSlots(); P_SetWeaponSlot(WT_FIRST, 1); P_SetWeaponSlot(WT_SECOND, 2); P_SetWeaponSlot(WT_THIRD, 3); P_SetWeaponSlot(WT_FOURTH, 4); } /** * Offset in state->misc1/2. */ void P_SetPSpriteOffset(pspdef_t *psp, player_t *plr, state_t *state) { ddpsprite_t *ddpsp = plr->plr->pSprites; // Clear the Offset flag by default. //ddpsp->flags &= ~DDPSPF_OFFSET; if(state->misc[0]) { // Set coordinates. psp->pos[VX] = (float) state->misc[0]; //ddpsp->flags |= DDPSPF_OFFSET; ddpsp->offset[VX] = (float) state->misc[0]; } if(state->misc[1]) { psp->pos[VY] = (float) state->misc[1]; //ddpsp->flags |= DDPSPF_OFFSET; ddpsp->offset[VY] = (float) state->misc[1]; } } void P_SetPsprite(player_t *plr, int position, statenum_t stnum) { pspdef_t *psp; state_t *state; psp = &plr->pSprites[position]; do { if(!stnum) { // Object removed itself. psp->state = NULL; break; } state = &STATES[stnum]; psp->state = state; psp->tics = state->tics; // could be 0 P_SetPSpriteOffset(psp, plr, state); if(state->action) { // Call action routine. state->action(plr, psp); if(!psp->state) { break; } } stnum = psp->state->nextState; } while(!psp->tics); // An initial state of 0 could cycle through. } /** * Identical to P_SetPsprite, without calling the action function. */ void P_SetPspriteNF(player_t *plr, int position, statenum_t stnum) { pspdef_t *psp; state_t *state; psp = &plr->pSprites[position]; do { if(!stnum) { // Object removed itself. psp->state = NULL; break; } state = &STATES[stnum]; psp->state = state; psp->tics = state->tics; // could be 0 P_SetPSpriteOffset(psp, plr, state); stnum = psp->state->nextState; } while(!psp->tics); // An initial state of 0 could cycle through. } void P_ActivateMorphWeapon(player_t *plr) { plr->pendingWeapon = WT_NOCHANGE; plr->pSprites[ps_weapon].pos[VY] = WEAPONTOP; plr->readyWeapon = WT_FIRST; // Snout is the first weapon plr->update |= PSF_WEAPONS; P_SetPsprite(plr, ps_weapon, S_SNOUTREADY); } void P_PostMorphWeapon(player_t *plr, weapontype_t weapon) { plr->pendingWeapon = WT_NOCHANGE; plr->readyWeapon = weapon; plr->pSprites[ps_weapon].pos[VY] = WEAPONBOTTOM; plr->update |= PSF_WEAPONS; P_SetPsprite(plr, ps_weapon, weaponInfo[weapon][plr->class].mode[0].states[WSN_UP]); } /** * Starts bringing the pending weapon up from the bottom of the screen. */ void P_BringUpWeapon(player_t *plr) { statenum_t newState; weaponmodeinfo_t *wminfo; wminfo = WEAPON_INFO(plr->pendingWeapon, plr->class, 0); newState = wminfo->states[WSN_UP]; if(plr->class == PCLASS_FIGHTER && plr->pendingWeapon == WT_SECOND && plr->ammo[AT_BLUEMANA].owned > 0) { newState = S_FAXEUP_G; } if(plr->pendingWeapon == WT_NOCHANGE) plr->pendingWeapon = plr->readyWeapon; if(wminfo->raiseSound) S_StartSound(wminfo->raiseSound, plr->plr->mo); plr->pendingWeapon = WT_NOCHANGE; plr->pSprites[ps_weapon].pos[VY] = WEAPONBOTTOM; P_SetPsprite(plr, ps_weapon, newState); } void P_FireWeapon(player_t *plr) { statenum_t attackState; if(!P_CheckAmmo(plr)) return; // Psprite state. P_MobjChangeState(plr->plr->mo, PCLASS_INFO(plr->class)->attackState); if(plr->class == PCLASS_FIGHTER && plr->readyWeapon == WT_SECOND && plr->ammo[AT_BLUEMANA].owned > 0) { // Glowing axe. attackState = S_FAXEATK_G1; } else { if(plr->refire) attackState = weaponInfo[plr->readyWeapon][plr->class].mode[0].states[WSN_ATTACK_HOLD]; else attackState = weaponInfo[plr->readyWeapon][plr->class].mode[0].states[WSN_ATTACK]; } P_SetPsprite(plr, ps_weapon, attackState); P_NoiseAlert(plr->plr->mo, plr->plr->mo); plr->update |= PSF_AMMO; // Psprite state. plr->plr->pSprites[0].state = DDPSP_FIRE; } /** * The player died, so put the weapon away. */ void P_DropWeapon(player_t *plr) { P_SetPsprite(plr, ps_weapon, weaponInfo[plr->readyWeapon][plr->class].mode[0].states[WSN_DOWN]); } /** * The player can fire the weapon or change to another weapon at this time. */ void C_DECL A_WeaponReady(player_t *plr, pspdef_t *psp) { weaponmodeinfo_t *wminfo; ddpsprite_t *ddpsp; // Change plr from attack state if(plr->plr->mo->state >= &STATES[PCLASS_INFO(plr->class)->attackState] && plr->plr->mo->state <= &STATES[PCLASS_INFO(plr->class)->attackEndState]) { P_MobjChangeState(plr->plr->mo, PCLASS_INFO(plr->class)->normalState); } if(plr->readyWeapon != WT_NOCHANGE) { wminfo = WEAPON_INFO(plr->readyWeapon, plr->class, 0); // A weaponready sound? if(psp->state == &STATES[wminfo->states[WSN_READY]] && wminfo->readySound) S_StartSound(wminfo->readySound, plr->plr->mo); // Check for change, if plr is dead, put the weapon away. if(plr->pendingWeapon != WT_NOCHANGE || !plr->health) { // (pending weapon should allready be validated) P_SetPsprite(plr, ps_weapon, wminfo->states[WSN_DOWN]); return; } } // Check for autofire. if(plr->brain.attack) { wminfo = WEAPON_INFO(plr->readyWeapon, plr->class, 0); if(!plr->attackDown || wminfo->autoFire) { plr->attackDown = true; P_FireWeapon(plr); return; } } else { plr->attackDown = false; } ddpsp = plr->plr->pSprites; if(!plr->morphTics) { // Bob the weapon based on movement speed. R_GetWeaponBob(plr - players, &psp->pos[0], &psp->pos[1]); ddpsp->offset[0] = ddpsp->offset[1] = 0; } // Psprite state. ddpsp->state = DDPSP_BOBBING; } /** * The player can re fire the weapon without lowering it entirely. */ void C_DECL A_ReFire(player_t* plr, pspdef_t* psp) { if((plr->brain.attack) && plr->pendingWeapon == WT_NOCHANGE && plr->health) { plr->refire++; P_FireWeapon(plr); } else { plr->refire = 0; P_CheckAmmo(plr); } } void C_DECL A_Lower(player_t *plr, pspdef_t *psp) { // Psprite state. plr->plr->pSprites[0].state = DDPSP_DOWN; if(plr->morphTics) { psp->pos[VY] = WEAPONBOTTOM; } else { psp->pos[VY] += LOWERSPEED; } if(psp->pos[VY] < WEAPONBOTTOM) { // Not lowered all the way yet. return; } if(plr->playerState == PST_DEAD) { // Player is dead, so don't bring up a pending weapon. psp->pos[VY] = WEAPONBOTTOM; return; } if(!plr->health) { // Player is dead, so keep the weapon off screen. P_SetPsprite(plr, ps_weapon, S_NULL); return; } plr->readyWeapon = plr->pendingWeapon; plr->update |= PSF_WEAPONS; P_BringUpWeapon(plr); } void C_DECL A_Raise(player_t *plr, pspdef_t *psp) { // Psprite state. plr->plr->pSprites[0].state = DDPSP_UP; psp->pos[VY] -= RAISESPEED; if(psp->pos[VY] > WEAPONTOP) { // Not raised all the way yet. return; } psp->pos[VY] = WEAPONTOP; if(plr->class == PCLASS_FIGHTER && plr->readyWeapon == WT_SECOND && plr->ammo[AT_BLUEMANA].owned > 0) { P_SetPsprite(plr, ps_weapon, S_FAXEREADY_G); } else { P_SetPsprite(plr, ps_weapon, weaponInfo[plr->readyWeapon][plr->class].mode[0]. states[WSN_READY]); } } void AdjustPlayerAngle(mobj_t *pmo) { angle_t angle; int difference; angle = R_PointToAngle2(pmo->pos[VX], pmo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); difference = (int) angle - (int) pmo->angle; if(abs(difference) > MAX_ANGLE_ADJUST) { pmo->angle += difference > 0 ? MAX_ANGLE_ADJUST : -MAX_ANGLE_ADJUST; } else { pmo->angle = angle; } pmo->player->plr->flags |= DDPF_FIXANGLES; } void C_DECL A_SnoutAttack(player_t *plr, pspdef_t *psp) { angle_t angle; int damage; float slope; damage = 3 + (P_Random() & 3); angle = plr->plr->mo->angle; slope = P_AimLineAttack(plr->plr->mo, angle, MELEERANGE); PuffType = MT_SNOUTPUFF; puffSpawned = NULL; P_LineAttack(plr->plr->mo, angle, MELEERANGE, slope, damage); S_StartSound(SFX_PIG_ACTIVE1 + (P_Random() & 1), plr->plr->mo); if(lineTarget) { AdjustPlayerAngle(plr->plr->mo); if(puffSpawned) { // Bit something. S_StartSound(SFX_PIG_ATTACK, plr->plr->mo); } } } void C_DECL A_FHammerAttack(player_t *plr, pspdef_t *psp) { int i; angle_t angle; mobj_t *mo = plr->plr->mo; int damage; float power; float slope; damage = 60 + (P_Random() & 63); power = 10; PuffType = MT_HAMMERPUFF; for(i = 0; i < 16; ++i) { angle = mo->angle + i * (ANG45 / 32); slope = P_AimLineAttack(mo, angle, HAMMER_RANGE); if(lineTarget) { P_LineAttack(mo, angle, HAMMER_RANGE, slope, damage); AdjustPlayerAngle(mo); if((lineTarget->flags & MF_COUNTKILL) || lineTarget->player) { P_ThrustMobj(lineTarget, angle, power); } mo->special1 = false; // Don't throw a hammer. goto hammerdone; } angle = mo->angle - i * (ANG45 / 32); slope = P_AimLineAttack(mo, angle, HAMMER_RANGE); if(lineTarget) { P_LineAttack(mo, angle, HAMMER_RANGE, slope, damage); AdjustPlayerAngle(mo); if((lineTarget->flags & MF_COUNTKILL) || lineTarget->player) { P_ThrustMobj(lineTarget, angle, power); } mo->special1 = false; // Don't throw a hammer. goto hammerdone; } } // Didn't find any targets in meleerange, so set to throw out a hammer. puffSpawned = NULL; angle = mo->angle; slope = P_AimLineAttack(mo, angle, HAMMER_RANGE); P_LineAttack(mo, angle, HAMMER_RANGE, slope, damage); if(puffSpawned) { mo->special1 = false; } else { mo->special1 = true; } hammerdone: if(plr->ammo[AT_GREENMANA].owned < weaponInfo[plr->readyWeapon][plr->class].mode[0].perShot[AT_GREENMANA]) { // Don't spawn a hammer if the plr doesn't have enough mana. mo->special1 = false; } } void C_DECL A_FHammerThrow(player_t *plr, pspdef_t *psp) { mobj_t *pmo; if(!plr->plr->mo->special1) return; P_ShotAmmo(plr); pmo = P_SpawnPlayerMissile(MT_HAMMER_MISSILE, plr->plr->mo); if(pmo) pmo->special1 = 0; } void C_DECL A_FSwordAttack(player_t *plr, pspdef_t *psp) { mobj_t *mo; P_ShotAmmo(plr); mo = plr->plr->mo; P_SPMAngleXYZ(MT_FSWORD_MISSILE, mo->pos[VX], mo->pos[VY], mo->pos[VZ] - 10, mo, mo->angle + ANG45 / 4); P_SPMAngleXYZ(MT_FSWORD_MISSILE, mo->pos[VX], mo->pos[VY], mo->pos[VZ] - 5, mo, mo->angle + ANG45 / 8); P_SPMAngleXYZ(MT_FSWORD_MISSILE, mo->pos[VX], mo->pos[VY], mo->pos[VZ], mo, mo->angle); P_SPMAngleXYZ(MT_FSWORD_MISSILE, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + 5, mo, mo->angle - ANG45 / 8); P_SPMAngleXYZ(MT_FSWORD_MISSILE, mo->pos[VX], mo->pos[VY], mo->pos[VZ] + 10, mo, mo->angle - ANG45 / 4); S_StartSound(SFX_FIGHTER_SWORD_FIRE, mo); } void C_DECL A_FSwordAttack2(mobj_t *mo) { angle_t angle = mo->angle; P_SpawnMissileAngle(MT_FSWORD_MISSILE, mo, angle + ANG45 / 4, 0); P_SpawnMissileAngle(MT_FSWORD_MISSILE, mo, angle + ANG45 / 8, 0); P_SpawnMissileAngle(MT_FSWORD_MISSILE, mo, angle, 0); P_SpawnMissileAngle(MT_FSWORD_MISSILE, mo, angle - ANG45 / 8, 0); P_SpawnMissileAngle(MT_FSWORD_MISSILE, mo, angle - ANG45 / 4, 0); S_StartSound(SFX_FIGHTER_SWORD_FIRE, mo); } void C_DECL A_FSwordFlames(mobj_t *mo) { int i; angle_t angle; float pos[3]; for(i = 1 + (P_Random() & 3); i; i--) { pos[VX] = mo->pos[VX] + FIX2FLT((P_Random() - 128) << 12); pos[VY] = mo->pos[VY] + FIX2FLT((P_Random() - 128) << 12); pos[VZ] = mo->pos[VZ] + FIX2FLT((P_Random() - 128) << 11); angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY], pos[VX], pos[VY]); P_SpawnMobj3fv(MT_FSWORD_FLAME, pos, angle, 0); } } void C_DECL A_MWandAttack(player_t *plr, pspdef_t *psp) { P_SpawnPlayerMissile(MT_MWAND_MISSILE, plr->plr->mo); S_StartSound(SFX_MAGE_WAND_FIRE, plr->plr->mo); } void C_DECL A_LightningReady(player_t *plr, pspdef_t *psp) { A_WeaponReady(plr, psp); if(P_Random() < 160) { S_StartSound(SFX_MAGE_LIGHTNING_READY, plr->plr->mo); } } void C_DECL A_LightningClip(mobj_t *mo) { mobj_t *cMo, *target = 0; int zigZag; if(mo->type == MT_LIGHTNING_FLOOR) { mo->pos[VZ] = mo->floorZ; target = mo->lastEnemy->tracer; } else if(mo->type == MT_LIGHTNING_CEILING) { mo->pos[VZ] = mo->ceilingZ - mo->height; target = mo->tracer; } if(mo->type == MT_LIGHTNING_FLOOR) { // Floor lightning zig-zags, and forces the ceiling lightning to mimic. cMo = mo->lastEnemy; zigZag = P_Random(); if((zigZag > 128 && mo->special1 < 2) || mo->special1 < -2) { P_ThrustMobj(mo, mo->angle + ANG90, ZAGSPEED); if(cMo) { P_ThrustMobj(cMo, mo->angle + ANG90, ZAGSPEED); } mo->special1++; } else { P_ThrustMobj(mo, mo->angle - ANG90, ZAGSPEED); if(cMo) { P_ThrustMobj(cMo, cMo->angle - ANG90, ZAGSPEED); } mo->special1--; } } if(target) { if(target->health <= 0) { P_ExplodeMissile(mo); } else { mo->angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY], target->pos[VX], target->pos[VY]); mo->mom[MX] = mo->mom[MY] = 0; P_ThrustMobj(mo, mo->angle, mo->info->speed / 2); } } } void C_DECL A_LightningZap(mobj_t *mo) { mobj_t *pmo; float deltaZ; A_LightningClip(mo); mo->health -= 8; if(mo->health <= 0) { P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); return; } if(mo->type == MT_LIGHTNING_FLOOR) { deltaZ = 10; } else { deltaZ = -10; } if((pmo = P_SpawnMobj3f(MT_LIGHTNING_ZAP, mo->pos[VX] + (FIX2FLT(P_Random() - 128) * mo->radius / 256), mo->pos[VY] + (FIX2FLT(P_Random() - 128) * mo->radius / 256), mo->pos[VZ] + deltaZ, P_Random() << 24, 0))) { pmo->lastEnemy = mo; pmo->mom[MX] = mo->mom[MX]; pmo->mom[MY] = mo->mom[MY]; pmo->target = mo->target; if(mo->type == MT_LIGHTNING_FLOOR) { pmo->mom[MZ] = 20; } else { pmo->mom[MZ] = -20; } } if(mo->type == MT_LIGHTNING_FLOOR && P_Random() < 160) { S_StartSound(SFX_MAGE_LIGHTNING_CONTINUOUS, mo); } } void C_DECL A_MLightningAttack2(mobj_t *mo) { mobj_t *fmo, *cmo; fmo = P_SpawnPlayerMissile(MT_LIGHTNING_FLOOR, mo); cmo = P_SpawnPlayerMissile(MT_LIGHTNING_CEILING, mo); if(fmo) { fmo->special1 = 0; fmo->lastEnemy = cmo; A_LightningZap(fmo); } if(cmo) { cmo->tracer = NULL; // Mobj that it will track. cmo->lastEnemy = fmo; A_LightningZap(cmo); } S_StartSound(SFX_MAGE_LIGHTNING_FIRE, mo); } void C_DECL A_MLightningAttack(player_t *plr, pspdef_t *psp) { A_MLightningAttack2(plr->plr->mo); P_ShotAmmo(plr); } void C_DECL A_ZapMimic(mobj_t* mo) { mobj_t* target; target = mo->lastEnemy; if(target) { if(target->state >= &STATES[P_GetState(target->type, SN_DEATH)] || target->state == &STATES[S_FREETARGMOBJ]) { P_ExplodeMissile(mo); } else { mo->mom[MX] = target->mom[MX]; mo->mom[MY] = target->mom[MY]; } } } void C_DECL A_LastZap(mobj_t* mo) { mobj_t* pmo; if((pmo = P_SpawnMobj3fv(MT_LIGHTNING_ZAP, mo->pos, P_Random() << 24, 0))) { P_MobjChangeState(pmo, S_LIGHTNING_ZAP_X1); pmo->mom[MZ] = 40; } } void C_DECL A_LightningRemove(mobj_t* mo) { mobj_t* target; target = mo->lastEnemy; if(target) { target->lastEnemy = NULL; P_ExplodeMissile(target); } } void MStaffSpawn(mobj_t* mo, angle_t angle) { mobj_t* pmo; if((pmo = P_SPMAngle(MT_MSTAFF_FX2, mo, angle))) { pmo->target = mo; pmo->tracer = P_RoughMonsterSearch(pmo, 10*128); } } void C_DECL A_MStaffAttack(player_t* plr, pspdef_t* psp) { angle_t angle; mobj_t* mo; P_ShotAmmo(plr); mo = plr->plr->mo; angle = mo->angle; MStaffSpawn(mo, angle); MStaffSpawn(mo, angle - ANGLE_1 * 5); MStaffSpawn(mo, angle + ANGLE_1 * 5); S_StartSound(SFX_MAGE_STAFF_FIRE, plr->plr->mo); plr->damageCount = 0; plr->bonusCount = 0; if(plr == &players[CONSOLEPLAYER]) { int pal = STARTSCOURGEPAL; float rgba[4]; // $democam R_GetFilterColor(rgba, pal); GL_SetFilterColor(rgba[CR], rgba[CG], rgba[CB], rgba[CA]); GL_SetFilter(true); } } void C_DECL A_MStaffPalette(player_t* plr, pspdef_t* psp) { if(plr == &players[CONSOLEPLAYER]) { int pal = STARTSCOURGEPAL + psp->state - (&STATES[S_MSTAFFATK_2]); if(pal == STARTSCOURGEPAL + 3) { // Reset back to original playpal. pal = 0; } if(pal) { float rgba[4]; // $democam R_GetFilterColor(rgba, pal); GL_SetFilterColor(rgba[CR], rgba[CG], rgba[CB], rgba[CA]); GL_SetFilter(true); } } } void C_DECL A_MStaffWeave(mobj_t *mo) { float pos[2]; uint weaveXY, weaveZ; uint an; weaveXY = mo->special2 >> 16; weaveZ = mo->special2 & 0xFFFF; an = (mo->angle + ANG90) >> ANGLETOFINESHIFT; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VX] -= FIX2FLT(finecosine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); pos[VY] -= FIX2FLT(finesine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); weaveXY = (weaveXY + 6) & 63; pos[VX] += FIX2FLT(finecosine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); pos[VY] += FIX2FLT(finesine[an]) * (FLOATBOBOFFSET(weaveXY) * 4); P_TryMove(mo, pos[VX], pos[VY]); mo->pos[VZ] -= FLOATBOBOFFSET(weaveZ) * 2; weaveZ = (weaveZ + 3) & 63; mo->pos[VZ] += FLOATBOBOFFSET(weaveZ) * 2; if(mo->pos[VZ] <= mo->floorZ) { mo->pos[VZ] = mo->floorZ + 1; } mo->special2 = weaveZ + (weaveXY << 16); } void C_DECL A_MStaffTrack(mobj_t *mo) { if((mo->tracer == 0) && (P_Random() < 50)) { mo->tracer = P_RoughMonsterSearch(mo, 10*128); } P_SeekerMissile(mo, ANGLE_1 * 2, ANGLE_1 * 10); } /** * For use by mage class boss. */ void MStaffSpawn2(mobj_t *mo, angle_t angle) { mobj_t *pmo; pmo = P_SpawnMissileAngle(MT_MSTAFF_FX2, mo, angle, 0); if(pmo) { pmo->target = mo; pmo->tracer = P_RoughMonsterSearch(pmo, 10*128); } } /** * For use by mage class boss. */ void C_DECL A_MStaffAttack2(mobj_t *mo) { angle_t angle; angle = mo->angle; MStaffSpawn2(mo, angle); MStaffSpawn2(mo, angle - ANGLE_1 * 5); MStaffSpawn2(mo, angle + ANGLE_1 * 5); S_StartSound(SFX_MAGE_STAFF_FIRE, mo); } void C_DECL A_FPunchAttack(player_t *plr, pspdef_t *psp) { int i; angle_t angle; int damage; float slope; mobj_t *mo = plr->plr->mo; float power; damage = 40 + (P_Random() & 15); power = 2; PuffType = MT_PUNCHPUFF; for(i = 0; i < 16; ++i) { angle = mo->angle + i * (ANG45 / 16); slope = P_AimLineAttack(mo, angle, 2 * MELEERANGE); if(lineTarget) { mo->special1++; if(mo->special1 == 3) { damage *= 2; power = 6; PuffType = MT_HAMMERPUFF; } P_LineAttack(mo, angle, 2 * MELEERANGE, slope, damage); if((lineTarget->flags & MF_COUNTKILL) || lineTarget->player) { P_ThrustMobj(lineTarget, angle, power); } AdjustPlayerAngle(mo); goto punchdone; } angle = mo->angle - i * (ANG45 / 16); slope = P_AimLineAttack(mo, angle, 2 * MELEERANGE); if(lineTarget) { mo->special1++; if(mo->special1 == 3) { damage *= 2; power = 6; PuffType = MT_HAMMERPUFF; } P_LineAttack(mo, angle, 2 * MELEERANGE, slope, damage); if((lineTarget->flags & MF_COUNTKILL) || lineTarget->player) { P_ThrustMobj(lineTarget, angle, power); } AdjustPlayerAngle(mo); goto punchdone; } } // Didn't find any creatures, so try to strike any walls. mo->special1 = 0; angle = mo->angle; slope = P_AimLineAttack(mo, angle, MELEERANGE); P_LineAttack(mo, angle, MELEERANGE, slope, damage); punchdone: if(mo->special1 == 3) { mo->special1 = 0; P_SetPsprite(plr, ps_weapon, S_PUNCHATK2_1); S_StartSound(SFX_FIGHTER_GRUNT, mo); } } void C_DECL A_FAxeAttack(player_t *plr, pspdef_t *psp) { int i; angle_t angle; mobj_t *pmo = plr->plr->mo; float power; float slope; int damage, useMana; damage = 40 + (P_Random() & 15) + (P_Random() & 7); power = 0; if(plr->ammo[AT_BLUEMANA].owned > 0) { damage *= 2; power = 6; PuffType = MT_AXEPUFF_GLOW; useMana = 1; } else { PuffType = MT_AXEPUFF; useMana = 0; } for(i = 0; i < 16; ++i) { angle = pmo->angle + i * (ANG45 / 16); slope = P_AimLineAttack(pmo, angle, AXERANGE); if(lineTarget) { P_LineAttack(pmo, angle, AXERANGE, slope, damage); if((lineTarget->flags & MF_COUNTKILL) || lineTarget->player) { P_ThrustMobj(lineTarget, angle, power); } AdjustPlayerAngle(pmo); useMana++; goto axedone; } angle = pmo->angle - i * (ANG45 / 16); slope = P_AimLineAttack(pmo, angle, AXERANGE); if(lineTarget) { P_LineAttack(pmo, angle, AXERANGE, slope, damage); if(lineTarget->flags & MF_COUNTKILL) { P_ThrustMobj(lineTarget, angle, power); } AdjustPlayerAngle(pmo); useMana++; goto axedone; } } // Didn't find any creatures, so try to strike any walls. pmo->special1 = 0; angle = pmo->angle; slope = P_AimLineAttack(pmo, angle, MELEERANGE); P_LineAttack(pmo, angle, MELEERANGE, slope, damage); axedone: if(useMana == 2) { P_ShotAmmo(plr); if(!(plr->ammo[AT_BLUEMANA].owned > 0)) P_SetPsprite(plr, ps_weapon, S_FAXEATK_5); } } void C_DECL A_CMaceAttack(player_t *plr, pspdef_t *psp) { int i; angle_t angle; int damage; float slope; damage = 25 + (P_Random() & 15); PuffType = MT_HAMMERPUFF; for(i = 0; i < 16; ++i) { angle = plr->plr->mo->angle + i * (ANG45 / 16); slope = P_AimLineAttack(plr->plr->mo, angle, 2 * MELEERANGE); if(lineTarget) { P_LineAttack(plr->plr->mo, angle, 2 * MELEERANGE, slope, damage); AdjustPlayerAngle(plr->plr->mo); goto macedone; } angle = plr->plr->mo->angle - i * (ANG45 / 16); slope = P_AimLineAttack(plr->plr->mo, angle, 2 * MELEERANGE); if(lineTarget) { P_LineAttack(plr->plr->mo, angle, 2 * MELEERANGE, slope, damage); AdjustPlayerAngle(plr->plr->mo); goto macedone; } } // Didn't find any creatures, so try to strike any walls. plr->plr->mo->special1 = 0; angle = plr->plr->mo->angle; slope = P_AimLineAttack(plr->plr->mo, angle, MELEERANGE); P_LineAttack(plr->plr->mo, angle, MELEERANGE, slope, damage); macedone: return; } void C_DECL A_CStaffCheck(player_t *plr, pspdef_t *psp) { int i; mobj_t *pmo; int damage, newLife; angle_t angle; float slope; pmo = plr->plr->mo; damage = 20 + (P_Random() & 15); PuffType = MT_CSTAFFPUFF; for(i = 0; i < 3; ++i) { angle = pmo->angle + i * (ANG45 / 16); slope = P_AimLineAttack(pmo, angle, 1.5 * MELEERANGE); if(lineTarget) { P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage); pmo->angle = R_PointToAngle2(pmo->pos[VX], pmo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); if((lineTarget->player || (lineTarget->flags & MF_COUNTKILL)) && (!(lineTarget->flags2 & (MF2_DORMANT + MF2_INVULNERABLE)))) { newLife = plr->health + (damage / 8); newLife = (newLife > 100 ? 100 : newLife); pmo->health = plr->health = newLife; P_SetPsprite(plr, ps_weapon, S_CSTAFFATK2_1); } P_ShotAmmo(plr); break; } angle = pmo->angle - i * (ANG45 / 16); slope = P_AimLineAttack(plr->plr->mo, angle, 1.5 * MELEERANGE); if(lineTarget) { P_LineAttack(pmo, angle, 1.5 * MELEERANGE, slope, damage); pmo->angle = R_PointToAngle2(pmo->pos[VX], pmo->pos[VY], lineTarget->pos[VX], lineTarget->pos[VY]); if(lineTarget->player || (lineTarget->flags & MF_COUNTKILL)) { newLife = plr->health + (damage >> 4); newLife = (newLife > 100 ? 100 : newLife); pmo->health = plr->health = newLife; P_SetPsprite(plr, ps_weapon, S_CSTAFFATK2_1); } P_ShotAmmo(plr); break; } } } void C_DECL A_CStaffAttack(player_t *plr, pspdef_t *psp) { mobj_t *mo, *pmo; P_ShotAmmo(plr); pmo = plr->plr->mo; mo = P_SPMAngle(MT_CSTAFF_MISSILE, pmo, pmo->angle - (ANG45 / 15)); if(mo) { mo->special2 = 32; } mo = P_SPMAngle(MT_CSTAFF_MISSILE, pmo, pmo->angle + (ANG45 / 15)); if(mo) { mo->special2 = 0; } S_StartSound(SFX_CLERIC_CSTAFF_FIRE, plr->plr->mo); } void C_DECL A_CStaffMissileSlither(mobj_t *actor) { float pos[2]; uint an, weaveXY; weaveXY = actor->special2; an = (actor->angle + ANG90) >> ANGLETOFINESHIFT; pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VX] -= FIX2FLT(finecosine[an]) * FLOATBOBOFFSET(weaveXY); pos[VY] -= FIX2FLT(finesine[an]) * FLOATBOBOFFSET(weaveXY); weaveXY = (weaveXY + 3) & 63; pos[VX] += FIX2FLT(finecosine[an]) * FLOATBOBOFFSET(weaveXY); pos[VY] += FIX2FLT(finesine[an]) * FLOATBOBOFFSET(weaveXY); P_TryMove(actor, pos[VX], pos[VY]); actor->special2 = weaveXY; } void C_DECL A_CStaffInitBlink(player_t *plr, pspdef_t *psp) { plr->plr->mo->special1 = (P_Random() >> 1) + 20; } void C_DECL A_CStaffCheckBlink(player_t *plr, pspdef_t *psp) { if(!--plr->plr->mo->special1) { P_SetPsprite(plr, ps_weapon, S_CSTAFFBLINK1); plr->plr->mo->special1 = (P_Random() + 50) >> 2; } } void C_DECL A_CFlameAttack(player_t *plr, pspdef_t *psp) { mobj_t *pmo; pmo = P_SpawnPlayerMissile(MT_CFLAME_MISSILE, plr->plr->mo); if(pmo) { pmo->special1 = 2; } P_ShotAmmo(plr); S_StartSound(SFX_CLERIC_FLAME_FIRE, plr->plr->mo); } void C_DECL A_CFlamePuff(mobj_t* mo) { if(!mo) return; A_UnHideThing(mo); mo->mom[MX] = mo->mom[MY] = mo->mom[MZ] = 0; S_StartSound(SFX_CLERIC_FLAME_EXPLODE, mo); } void C_DECL A_CFlameMissile(mobj_t* mo) { int i; uint an, an90; float dist; mobj_t* pmo; if(!mo) return; A_UnHideThing(mo); S_StartSound(SFX_CLERIC_FLAME_EXPLODE, mo); if(blockingMobj && (blockingMobj->flags & MF_SHOOTABLE)) { // Hit something. // Spawn the flame circle around the thing dist = blockingMobj->radius + 18; for(i = 0; i < 4; ++i) { an = (i * ANG45) >> ANGLETOFINESHIFT; an90 = (i * ANG45 + ANG90) >> ANGLETOFINESHIFT; if((pmo = P_SpawnMobj3f(MT_CIRCLEFLAME, blockingMobj->pos[VX] + dist * FIX2FLT(finecosine[an]), blockingMobj->pos[VY] + dist * FIX2FLT(finesine[an]), blockingMobj->pos[VZ] + 5, (angle_t) an << ANGLETOFINESHIFT, 0))) { pmo->target = mo->target; pmo->mom[MX] = FLAMESPEED * FIX2FLT(finecosine[an]); pmo->mom[MY] = FLAMESPEED * FIX2FLT(finesine[an]); pmo->special1 = FLT2FIX(pmo->mom[MX]); pmo->special2 = FLT2FIX(pmo->mom[MY]); pmo->tics -= P_Random() & 3; } if((pmo = P_SpawnMobj3f(MT_CIRCLEFLAME, blockingMobj->pos[VX] - dist * FIX2FLT(finecosine[an]), blockingMobj->pos[VY] - dist * FIX2FLT(finesine[an]), blockingMobj->pos[VZ] + 5, (angle_t) (ANG180 + (an << ANGLETOFINESHIFT)), 0))) { pmo->target = mo->target; pmo->mom[MX] = -FLAMESPEED * FIX2FLT(finecosine[an]); pmo->mom[MY] = -FLAMESPEED * FIX2FLT(finesine[an]); pmo->special1 = FLT2FIX(pmo->mom[MX]); pmo->special2 = FLT2FIX(pmo->mom[MY]); pmo->tics -= P_Random() & 3; } } P_MobjChangeState(mo, S_FLAMEPUFF2_1); } } void C_DECL A_CFlameRotate(mobj_t *mo) { uint an; an = (mo->angle + ANG90) >> ANGLETOFINESHIFT; mo->mom[MX] = FIX2FLT(mo->special1); mo->mom[MY] = FIX2FLT(mo->special2); mo->mom[MX] += FLAMEROTSPEED * FIX2FLT(finecosine[an]); mo->mom[MY] += FLAMEROTSPEED * FIX2FLT(finesine[an]); mo->angle += ANG90 / 15; } /** * Spawns the spirits */ void C_DECL A_CHolyAttack3(mobj_t *mo) { P_SpawnMissile(MT_HOLY_MISSILE, mo, mo->target); S_StartSound(SFX_CHOLY_FIRE, mo); } /** * Spawns the spirits */ void C_DECL A_CHolyAttack2(mobj_t* mo) { int i, j; mobj_t* pmo, *tail, *next; for(i = 0; i < 4; ++i) { angle_t angle = mo->angle + (ANGLE_45 + ANGLE_45 / 2) - ANGLE_45 * i; if(!(pmo = P_SpawnMobj3fv(MT_HOLY_FX, mo->pos, angle, 0))) continue; switch(i) // float bob index { case 0: pmo->special2 = P_Random() & 7; // Upper-left. break; case 1: pmo->special2 = 32 + (P_Random() & 7); // Upper-right. break; case 2: pmo->special2 = (32 + (P_Random() & 7)) << 16; // Lower-left. break; case 3: pmo->special2 = ((32 + (P_Random() & 7)) << 16) + 32 + (P_Random() & 7); break; } pmo->pos[VZ] = mo->pos[VZ]; P_ThrustMobj(pmo, pmo->angle, pmo->info->speed); pmo->target = mo->target; pmo->args[0] = 10; // Initial turn value. pmo->args[1] = 0; // Initial look angle. if(deathmatch) { // Ghosts last slightly less longer in DeathMatch. pmo->health = 85; } if(lineTarget) { pmo->tracer = lineTarget; pmo->flags |= MF_NOCLIP | MF_SKULLFLY; pmo->flags &= ~MF_MISSILE; } if((tail = P_SpawnMobj3fv(MT_HOLY_TAIL, pmo->pos, pmo->angle + ANG180, 0))) { tail->target = pmo; // Parent. for(j = 1; j < 3; ++j) { if((next = P_SpawnMobj3fv(MT_HOLY_TAIL, pmo->pos, pmo->angle + ANG180, 0))) { P_MobjChangeState(next, P_GetState(next->type, SN_SPAWN) + 1); tail->tracer = next; tail = next; } } tail->tracer = NULL; // last tail bit } } } void C_DECL A_CHolyAttack(player_t* plr, pspdef_t* psp) { mobj_t* pmo; P_ShotAmmo(plr); pmo = P_SpawnPlayerMissile(MT_HOLY_MISSILE, plr->plr->mo); plr->damageCount = 0; plr->bonusCount = 0; if(plr == &players[CONSOLEPLAYER]) { float rgba[4]; // $democam R_GetFilterColor(rgba, STARTHOLYPAL); GL_SetFilterColor(rgba[CR], rgba[CG], rgba[CB], rgba[CA]); GL_SetFilter(true); } S_StartSound(SFX_CHOLY_FIRE, plr->plr->mo); } void C_DECL A_CHolyPalette(player_t* plr, pspdef_t* psp) { if(plr == &players[CONSOLEPLAYER]) { int pal = STARTHOLYPAL + psp->state - (&STATES[S_CHOLYATK_6]); if(pal == STARTHOLYPAL + 3) { // reset back to original playpal pal = 0; } if(pal) { float rgba[4]; // $democam R_GetFilterColor(rgba, pal); GL_SetFilterColor(rgba[CR], rgba[CG], rgba[CB], rgba[CA]); GL_SetFilter(true); } } } static void CHolyFindTarget(mobj_t* mo) { mobj_t* target; target = P_RoughMonsterSearch(mo, 6*128); if(target) { mo->tracer = target; mo->flags |= MF_NOCLIP | MF_SKULLFLY; mo->flags &= ~MF_MISSILE; } } /** * Similar to P_SeekerMissile, but seeks to a random Z on the target */ static void CHolySeekerMissile(mobj_t *mo, angle_t thresh, angle_t turnMax) { int dir; uint an; angle_t delta; mobj_t *target; float dist, newZ, deltaZ; target = mo->tracer; if(target == NULL) { return; } if(!(target->flags & MF_SHOOTABLE) || (!(target->flags & MF_COUNTKILL) && !target->player)) { // Target died/target isn't a player or creature mo->tracer = NULL; mo->flags &= ~(MF_NOCLIP | MF_SKULLFLY); mo->flags |= MF_MISSILE; CHolyFindTarget(mo); return; } dir = P_FaceMobj(mo, target, &delta); if(delta > thresh) { delta /= 2; if(delta > turnMax) { delta = turnMax; } } if(dir) { // Turn clockwise mo->angle += delta; } else { // Turn counter clockwise mo->angle -= delta; } an = mo->angle >> ANGLETOFINESHIFT; mo->mom[MX] = mo->info->speed * FIX2FLT(finecosine[an]); mo->mom[MY] = mo->info->speed * FIX2FLT(finesine[an]); if(!(mapTime & 15) || mo->pos[VZ] > target->pos[VZ] + target->height || mo->pos[VZ] + mo->height < target->pos[VZ]) { newZ = target->pos[VZ]; newZ += FIX2FLT((P_Random() * FLT2FIX(target->height)) >> 8); deltaZ = newZ - mo->pos[VZ]; if(fabs(deltaZ) > 15) { if(deltaZ > 0) { deltaZ = 15; } else { deltaZ = -15; } } dist = P_ApproxDistance(target->pos[VX] - mo->pos[VX], target->pos[VX] - mo->pos[VY]); dist /= mo->info->speed; if(dist < 1) { dist = 1; } mo->mom[MZ] = deltaZ / dist; } } static void CHolyWeave(mobj_t *mo) { float pos[2]; int weaveXY, weaveZ; int angle; weaveXY = mo->special2 >> 16; weaveZ = mo->special2 & 0xFFFF; angle = (mo->angle + ANG90) >> ANGLETOFINESHIFT; pos[VX] = mo->pos[VX] - (FIX2FLT(finecosine[angle]) * (FLOATBOBOFFSET(weaveXY) * 4)); pos[VY] = mo->pos[VY] - (FIX2FLT(finesine[angle]) * (FLOATBOBOFFSET(weaveXY) * 4)); weaveXY = (weaveXY + (P_Random() % 5)) & 63; pos[VX] += FIX2FLT(finecosine[angle]) * (FLOATBOBOFFSET(weaveXY) * 4); pos[VY] += FIX2FLT(finesine[angle]) * (FLOATBOBOFFSET(weaveXY) * 4); P_TryMove(mo, pos[VX], pos[VY]); mo->pos[VZ] -= FLOATBOBOFFSET(weaveZ) * 2; weaveZ = (weaveZ + (P_Random() % 5)) & 63; mo->pos[VZ] += FLOATBOBOFFSET(weaveZ) * 2; mo->special2 = weaveZ + (weaveXY << 16); } void C_DECL A_CHolySeek(mobj_t* mo) { mo->health--; if(mo->health <= 0) { mo->mom[MX] /= 4; mo->mom[MY] /= 4; mo->mom[MZ] = 0; P_MobjChangeState(mo, P_GetState(mo->type, SN_DEATH)); mo->tics -= P_Random() & 3; return; } if(mo->tracer) { CHolySeekerMissile(mo, mo->args[0] * ANGLE_1, mo->args[0] * ANGLE_1 * 2); if(!((mapTime + 7) & 15)) { mo->args[0] = 5 + (P_Random() / 20); } } CHolyWeave(mo); } static void CHolyTailFollow(mobj_t* mo, float dist) { uint an; angle_t angle; mobj_t* child; float oldDistance, newDistance; child = mo->tracer; if(child) { angle = R_PointToAngle2(mo->pos[VX], mo->pos[VY], child->pos[VX], child->pos[VY]); an = angle >> ANGLETOFINESHIFT; oldDistance = P_ApproxDistance(child->pos[VX] - mo->pos[VX], child->pos[VY] - mo->pos[VY]); if(P_TryMove(child, mo->pos[VX] + dist * FIX2FLT(finecosine[an]), mo->pos[VY] + dist * FIX2FLT(finesine[an]))) { newDistance = P_ApproxDistance(child->pos[VX] - mo->pos[VX], child->pos[VY] - mo->pos[VY]) - 1; if(oldDistance < 1) { if(child->pos[VZ] < mo->pos[VZ]) { child->pos[VZ] = mo->pos[VZ] - dist; } else { child->pos[VZ] = mo->pos[VZ] + dist; } } else { child->pos[VZ] = mo->pos[VZ] + (newDistance / oldDistance) * (child->pos[VZ] - mo->pos[VZ]); } } CHolyTailFollow(child, dist - 1); } } static void CHolyTailRemove(mobj_t *mo) { mobj_t *child; child = mo->tracer; if(child) { CHolyTailRemove(child); } P_MobjRemove(mo, false); } void C_DECL A_CHolyTail(mobj_t *mo) { mobj_t *parent; parent = mo->target; if(parent) { if(parent->state >= &STATES[P_GetState(parent->type, SN_DEATH)]) { // Ghost removed, so remove all tail parts. CHolyTailRemove(mo); } else { uint an = parent->angle >> ANGLETOFINESHIFT; if(P_TryMove(mo, parent->pos[VX] - (14 * FIX2FLT(finecosine[an])), parent->pos[VY] - (14 * FIX2FLT(finesine[an])))) { mo->pos[VZ] = parent->pos[VZ] - 5; } CHolyTailFollow(mo, 10); } } } void C_DECL A_CHolyCheckScream(mobj_t *mo) { A_CHolySeek(mo); if(P_Random() < 20) { S_StartSound(SFX_SPIRIT_ACTIVE, mo); } if(!mo->tracer) { CHolyFindTarget(mo); } } void C_DECL A_CHolySpawnPuff(mobj_t *mo) { P_SpawnMobj3fv(MT_HOLY_MISSILE_PUFF, mo->pos, P_Random() << 24, 0); } void C_DECL A_FireConePL1(player_t *plr, pspdef_t *psp) { int i, damage; angle_t angle; mobj_t *pmo, *mo; boolean conedone = false; mo = plr->plr->mo; P_ShotAmmo(plr); S_StartSound(SFX_MAGE_SHARDS_FIRE, mo); damage = 90 + (P_Random() & 15); for(i = 0; i < 16; ++i) { angle = mo->angle + i * (ANG45 / 16); P_AimLineAttack(mo, angle, MELEERANGE); if(lineTarget) { mo->flags2 |= MF2_ICEDAMAGE; P_DamageMobj(lineTarget, mo, mo, damage, false); mo->flags2 &= ~MF2_ICEDAMAGE; conedone = true; break; } } // Didn't find any creatures, so fire projectiles. if(!conedone) { pmo = P_SpawnPlayerMissile(MT_SHARDFX1, mo); if(pmo) { pmo->special1 = SHARDSPAWN_LEFT | SHARDSPAWN_DOWN | SHARDSPAWN_UP | SHARDSPAWN_RIGHT; pmo->special2 = 3; // Set sperm count (levels of reproductivity) pmo->target = mo; pmo->args[0] = 3; // Mark Initial shard as super damage } } } void C_DECL A_ShedShard(mobj_t *mo) { mobj_t *pmo; int spawndir = mo->special1; int spermcount = mo->special2; if(spermcount <= 0) return; // No sperm left, can no longer reproduce. mo->special2 = 0; spermcount--; // Every so many calls, spawn a new missile in it's set directions. if(spawndir & SHARDSPAWN_LEFT) { pmo = P_SpawnMissileAngleSpeed(MT_SHARDFX1, mo, mo->angle + (ANG45 / 9), 0, (20 + 2 * spermcount)); if(pmo) { pmo->special1 = SHARDSPAWN_LEFT; pmo->special2 = spermcount; pmo->mom[MZ] = mo->mom[MZ]; pmo->target = mo->target; pmo->args[0] = (spermcount == 3) ? 2 : 0; } } if(spawndir & SHARDSPAWN_RIGHT) { pmo = P_SpawnMissileAngleSpeed(MT_SHARDFX1, mo, mo->angle - (ANG45 / 9), 0, (20 + 2 * spermcount)); if(pmo) { pmo->special1 = SHARDSPAWN_RIGHT; pmo->special2 = spermcount; pmo->mom[MZ] = mo->mom[MZ]; pmo->target = mo->target; pmo->args[0] = (spermcount == 3) ? 2 : 0; } } if(spawndir & SHARDSPAWN_UP) { pmo = P_SpawnMissileAngleSpeed(MT_SHARDFX1, mo, mo->angle, 0, (15 + 2 * spermcount)); if(pmo) { pmo->mom[MZ] = mo->mom[MZ]; pmo->pos[VZ] += 8; if(spermcount & 1) // Every other reproduction. pmo->special1 = SHARDSPAWN_UP | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; else pmo->special1 = SHARDSPAWN_UP; pmo->special2 = spermcount; pmo->target = mo->target; pmo->args[0] = (spermcount == 3) ? 2 : 0; } } if(spawndir & SHARDSPAWN_DOWN) { pmo = P_SpawnMissileAngleSpeed(MT_SHARDFX1, mo, mo->angle, 0, (15 + 2 * spermcount)); if(pmo) { pmo->mom[MZ] = mo->mom[MZ]; pmo->pos[VZ] -= 4; if(spermcount & 1) // Every other reproduction. pmo->special1 = SHARDSPAWN_DOWN | SHARDSPAWN_LEFT | SHARDSPAWN_RIGHT; else pmo->special1 = SHARDSPAWN_DOWN; pmo->special2 = spermcount; pmo->target = mo->target; pmo->args[0] = (spermcount == 3) ? 2 : 0; } } } void C_DECL A_Light0(player_t *plr, pspdef_t *psp) { plr->plr->extraLight = 0; } /** * Called at start of the map for each player. */ void P_SetupPsprites(player_t* player) { int i; // Remove all psprites. for(i = 0; i < NUMPSPRITES; ++i) { player->pSprites[i].state = NULL; } // Spawn the ready weapon if(player->pendingWeapon == WT_NOCHANGE) player->pendingWeapon = player->readyWeapon; P_BringUpWeapon(player); } /** * Called every tic by player thinking routine. */ void P_MovePsprites(player_t *plr) { int i; pspdef_t *psp; state_t *state; psp = &plr->pSprites[0]; for(i = 0; i < NUMPSPRITES; ++i, psp++) { if((state = psp->state) != 0) // A null state means not active. { // Drop tic count and possibly change state. if(psp->tics != -1) // A -1 tic count never changes. { psp->tics--; if(!psp->tics) { P_SetPsprite(plr, i, psp->state->nextState); } } } } plr->pSprites[ps_flash].pos[VX] = plr->pSprites[ps_weapon].pos[VX]; plr->pSprites[ps_flash].pos[VY] = plr->pSprites[ps_weapon].pos[VY]; } void C_DECL A_PoisonBag(mobj_t* mo) { player_t* player; mobj_t* bag; float pos[3]; angle_t angle; mobjtype_t type; if(!mo->player) return; player = mo->player; if(player->class == PCLASS_FIGHTER || player->class == PCLASS_PIG) { type = MT_THROWINGBOMB; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ] - mo->floorClip + 35; angle = mo->angle + (((P_Random() & 7) - 4) << 24); } else { uint an = mo->angle >> ANGLETOFINESHIFT; if(player->class == PCLASS_CLERIC) type = MT_POISONBAG; else type = MT_FIREBOMB; pos[VX] = mo->pos[VX] + 16 * FIX2FLT(finecosine[an]); pos[VY] = mo->pos[VY] + 24 * FIX2FLT(finesine[an]); pos[VZ] = mo->pos[VZ] - mo->floorClip + 8; angle = mo->angle; } if((bag = P_SpawnMobj3fv(type, pos, angle, 0))) { bag->target = mo; if(type == MT_THROWINGBOMB) { bag->mom[MZ] = 4 + FIX2FLT(((int) player->plr->lookDir) << (FRACBITS - 4)); bag->pos[VZ] += FIX2FLT(((int) player->plr->lookDir) << (FRACBITS - 4)); P_ThrustMobj(bag, bag->angle, bag->info->speed); bag->mom[MX] += mo->mom[MX] / 2; bag->mom[MY] += mo->mom[MY] / 2; bag->tics -= P_Random() & 3; P_CheckMissileSpawn(bag); } } didUseItem = true; } void C_DECL A_Egg(mobj_t* mo) { if(!mo->player) return; P_SpawnPlayerMissile(MT_EGGFX, mo); P_SPMAngle(MT_EGGFX, mo, mo->angle - (ANG45 / 6)); P_SPMAngle(MT_EGGFX, mo, mo->angle + (ANG45 / 6)); P_SPMAngle(MT_EGGFX, mo, mo->angle - (ANG45 / 3)); P_SPMAngle(MT_EGGFX, mo, mo->angle + (ANG45 / 3)); didUseItem = true; } void C_DECL A_SummonTarget(mobj_t* mo) { mobj_t* servant; if(!mo->player) return; if((servant = P_SpawnPlayerMissile(MT_SUMMON_FX, mo))) { servant->target = mo; servant->tracer = mo; servant->mom[MZ] = 5; } didUseItem = true; } void C_DECL A_BoostArmor(mobj_t* mo) { int count; armortype_t type; player_t* plr; if(!mo->player) return; plr = mo->player; count = 0; for(type = 0; type < NUMARMOR; ++type) { count += P_PlayerGiveArmorBonus(plr, type, 1 * FRACUNIT); // 1 point per armor type. } if(!count) return; didUseItem = true; } void C_DECL A_BoostMana(mobj_t* mo) { player_t* player; if(!mo->player) return; player = mo->player; if(!P_GiveMana(player, AT_BLUEMANA, MAX_MANA)) { if(!P_GiveMana(player, AT_GREENMANA, MAX_MANA)) { return; } } else { P_GiveMana(player, AT_GREENMANA, MAX_MANA); } didUseItem = true; } void C_DECL A_TeleportOther(mobj_t* mo) { if(!mo->player) return; P_ArtiTeleportOther(mo->player); didUseItem = true; } void C_DECL A_Speed(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GivePower(mo->player, PT_SPEED); } void C_DECL A_Wings(mobj_t* mo) { if(!mo->player) return; if(!P_GivePower(mo->player, PT_FLIGHT)) { return; } if(mo->mom[MZ] <= -35) { // Stop falling scream. S_StopSound(0, mo); } didUseItem = true; } void C_DECL A_BlastRadius(mobj_t* mo) { if(!mo->player) return; P_BlastRadius(mo->player); didUseItem = true; } void C_DECL A_Teleport(mobj_t* mo) { if(!mo->player) return; P_ArtiTele(mo->player); didUseItem = true; } void C_DECL A_Torch(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GivePower(mo->player, PT_INFRARED); } void C_DECL A_HealRadius(mobj_t* mo) { if(!mo->player) return; didUseItem = P_HealRadius(mo->player); } void C_DECL A_Health(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GiveBody(mo->player, 25); } void C_DECL A_SuperHealth(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GiveBody(mo->player, 100); } void C_DECL A_Invulnerability(mobj_t* mo) { if(!mo->player) return; didUseItem = P_GivePower(mo->player, PT_INVULNERABILITY); } void C_DECL A_PuzzSkull(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZSKULL - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGemBig(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEMBIG - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGemRed(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEMRED - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGemGreen1(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEMGREEN1 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGemGreen2(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEMGREEN2 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGemBlue1(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEMBLUE1 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGemBlue2(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEMBLUE2 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzBook1(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZBOOK1 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzBook2(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZBOOK2 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzSkull2(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZSKULL2 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzFWeapon(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZFWEAPON - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzCWeapon(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZCWEAPON - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzMWeapon(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZMWEAPON - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGear1(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEAR1 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGear2(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEAR2 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGear3(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEAR3 - IIT_FIRSTPUZZITEM); } void C_DECL A_PuzzGear4(mobj_t* mo) { if(!mo->player) return; didUseItem = P_UsePuzzleItem(mo->player, IIT_PUZZGEAR4 - IIT_FIRSTPUZZITEM); } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/a_action.c0000644000175000017500000006314311357170242022546 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * a_action.c: */ // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "p_map.h" // MACROS ------------------------------------------------------------------ #define TELEPORT_LIFE (1) // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- static float *orbitTableX = NULL; static float *orbitTableY = NULL; float *FloatBobOffset = NULL; int localQuakeHappening[MAXPLAYERS]; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void X_CreateLUTs(void) { #define ORBITRES 256 uint i; orbitTableX = Z_Malloc(sizeof(float) * ORBITRES, PU_STATIC, 0); for(i = 0; i < ORBITRES; ++i) orbitTableX[i] = cos(((float) i) / 40.74f) * 15; orbitTableY = Z_Malloc(sizeof(float) * ORBITRES, PU_STATIC, 0); for(i = 0; i < ORBITRES; ++i) orbitTableY[i] = sin(((float) i) / 40.74f) * 15; FloatBobOffset = Z_Malloc(sizeof(float) * FLOATBOBRES, PU_STATIC, 0); for(i = 0; i < FLOATBOBRES; ++i) FloatBobOffset[i] = sin(((float) i) / 10.186f) * 8; #undef ORBITRES } void X_DestroyLUTs(void) { Z_Free(orbitTableX); Z_Free(orbitTableY); Z_Free(FloatBobOffset); } void C_DECL A_PotteryExplode(mobj_t* actor) { int i, maxBits = (P_Random() & 3) + 3; for(i = 0; i < maxBits; ++i) { mobj_t* mo; if((mo = P_SpawnMobj3fv(MT_POTTERYBIT1, actor->pos, P_Random() << 24, 0))) { P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN) + (P_Random() % 5)); mo->mom[MZ] = FIX2FLT(((P_Random() & 7) + 5) * (3 * FRACUNIT / 4)); mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); } } S_StartSound(SFX_POTTERY_EXPLODE, actor); if(actor->args[0]) { // Spawn an item. if(!noMonstersParm || !(MOBJINFO[TranslateThingType[actor->args[0]]]. flags & MF_COUNTKILL)) { // Only spawn monsters if not -nomonsters. P_SpawnMobj3fv(TranslateThingType[actor->args[0]], actor->pos, actor->angle, 0); } } P_MobjRemove(actor, false); } void C_DECL A_PotteryChooseBit(mobj_t* actor) { P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH) + (P_Random() % 5) + 1); actor->tics = 256 + (P_Random() << 1); } void C_DECL A_PotteryCheck(mobj_t* actor) { int i; mobj_t* pmo; if(!IS_NETGAME) { pmo = players[CONSOLEPLAYER].plr->mo; if(P_CheckSight(actor, pmo) && (abs (R_PointToAngle2(pmo->pos[VX], pmo->pos[VY], actor->pos[VX], actor->pos[VY]) - pmo->angle) <= ANGLE_45)) { // Previous state (pottery bit waiting state). P_MobjChangeState(actor, actor->state - &STATES[0] - 1); } else { return; } } else { for(i = 0; i < MAXPLAYERS; ++i) { if(!players[i].plr->inGame) continue; pmo = players[i].plr->mo; if(P_CheckSight(actor, pmo) && (abs (R_PointToAngle2(pmo->pos[VX], pmo->pos[VY], actor->pos[VX], actor->pos[VY]) - pmo->angle) <= ANGLE_45)) { // Previous state (pottery bit waiting state). P_MobjChangeState(actor, actor->state - &STATES[0] - 1); return; } } } } void C_DECL A_CorpseBloodDrip(mobj_t* actor) { if(P_Random() > 128) { return; } P_SpawnMobj3f(MT_CORPSEBLOODDRIP, actor->pos[VX], actor->pos[VY], actor->pos[VZ] + actor->height / 2, actor->angle, 0); } void C_DECL A_CorpseExplode(mobj_t* actor) { int i, n; mobj_t* mo; for(i = (P_Random() & 3) + 3; i; i--) { if((mo = P_SpawnMobj3fv(MT_CORPSEBIT, actor->pos, P_Random() << 24, 0))) { P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN) + (P_Random() % 3)); mo->mom[MZ] = FIX2FLT((P_Random() & 7) + 5) * .75f; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); } } // Spawn a skull. if((mo = P_SpawnMobj3fv(MT_CORPSEBIT, actor->pos, P_Random() << 24, 0))) { P_MobjChangeState(mo, S_CORPSEBIT_4); n = (P_Random() & 7) + 5; mo->mom[MZ] = FIX2FLT(n) * .75f; mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); S_StartSound(SFX_FIRED_DEATH, mo); } P_MobjRemove(actor, false); } #ifdef MSVC // I guess the compiler gets confused by the multitude of P_Random()s... # pragma optimize("g", off) #endif void C_DECL A_LeafSpawn(mobj_t *actor) { int i; mobj_t *mo; float pos[3]; for(i = (P_Random() & 3) + 1; i; i--) { pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = actor->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - P_Random()) << 14); pos[VY] += FIX2FLT((P_Random() - P_Random()) << 14); pos[VZ] += FIX2FLT(P_Random() << 14); /** * \todo we should not be using the original indices to determine * the mobjtype. Use a local table instead. */ if((mo = P_SpawnMobj3fv(MT_LEAF1 + (P_Random() & 1), pos, actor->angle, 0))) { P_ThrustMobj(mo, actor->angle, FIX2FLT(P_Random() << 9) + 3); mo->target = actor; mo->special1 = 0; } } } #ifdef MSVC # pragma optimize("", on) #endif void C_DECL A_LeafThrust(mobj_t *actor) { if(P_Random() > 96) { return; } actor->mom[MZ] += FIX2FLT(P_Random() << 9) + 1; } void C_DECL A_LeafCheck(mobj_t *actor) { int n; actor->special1++; if(actor->special1 >= 20) { P_MobjChangeState(actor, S_NULL); return; } if(P_Random() > 64) { if(actor->mom[MX] == 0 && actor->mom[MY] == 0) { P_ThrustMobj(actor, actor->target->angle, FIX2FLT(P_Random() << 9) + 1); } return; } P_MobjChangeState(actor, S_LEAF1_8); n = P_Random(); actor->mom[MZ] = FIX2FLT(n << 9) + 1; P_ThrustMobj(actor, actor->target->angle, FIX2FLT(P_Random() << 9) + 2); actor->flags |= MF_MISSILE; } /** * Bridge variables * Parent * special1 true == removing from world * * Child * target pointer to center mobj * args[0] angle of ball */ void C_DECL A_BridgeOrbit(mobj_t* actor) { if(!actor) return; if(actor->target->special1) { P_MobjChangeState(actor, S_NULL); } actor->args[0] += 3; P_MobjUnsetPosition(actor); actor->pos[VX] = actor->target->pos[VX]; actor->pos[VY] = actor->target->pos[VY]; actor->pos[VX] += orbitTableX[actor->args[0]]; actor->pos[VY] += orbitTableY[actor->args[0]]; P_MobjSetPosition(actor); } void C_DECL A_BridgeInit(mobj_t* actor) { byte startangle; mobj_t* ball1, *ball2, *ball3; startangle = P_Random(); actor->special1 = 0; // Spawn triad into world. if((ball1 = P_SpawnMobj3fv(MT_BRIDGEBALL, actor->pos, actor->angle, 0))) { ball1->args[0] = startangle; ball1->target = actor; } if((ball2 = P_SpawnMobj3fv(MT_BRIDGEBALL, actor->pos, actor->angle, 0))) { ball2->args[0] = (startangle + 85) & 255; ball2->target = actor; } if((ball3 = P_SpawnMobj3fv(MT_BRIDGEBALL, actor->pos, actor->angle, 0))) { ball3->args[0] = (startangle + 170) & 255; ball3->target = actor; } A_BridgeOrbit(ball1); A_BridgeOrbit(ball2); A_BridgeOrbit(ball3); } void C_DECL A_BridgeRemove(mobj_t *actor) { actor->special1 = true; // Removing the bridge. actor->flags &= ~MF_SOLID; P_MobjChangeState(actor, S_FREE_BRIDGE1); } void C_DECL A_HideThing(mobj_t *actor) { actor->flags2 |= MF2_DONTDRAW; } void C_DECL A_UnHideThing(mobj_t *actor) { actor->flags2 &= ~MF2_DONTDRAW; } void C_DECL A_SetShootable(mobj_t *actor) { actor->flags2 &= ~MF2_NONSHOOTABLE; actor->flags |= MF_SHOOTABLE; } void C_DECL A_UnSetShootable(mobj_t *actor) { actor->flags2 |= MF2_NONSHOOTABLE; actor->flags &= ~MF_SHOOTABLE; } void C_DECL A_SetAltShadow(mobj_t *actor) { actor->flags &= ~MF_SHADOW; actor->flags |= MF_ALTSHADOW; } void C_DECL A_ContMobjSound(mobj_t *actor) { switch(actor->type) { case MT_SERPENTFX: S_StartSound(SFX_SERPENTFX_CONTINUOUS, actor); break; case MT_HAMMER_MISSILE: S_StartSound(SFX_FIGHTER_HAMMER_CONTINUOUS, actor); break; case MT_QUAKE_FOCUS: S_StartSound(SFX_EARTHQUAKE, actor); break; default: break; } } void C_DECL A_ESound(mobj_t *mo) { int sound; switch(mo->type) { case MT_SOUNDWIND: sound = SFX_WIND; break; default: sound = SFX_NONE; break; } S_StartSound(sound, mo); } /** * NOTE: See p_enemy for variable descriptions. */ void C_DECL A_Summon(mobj_t* actor) { mobj_t* mo; if((mo = P_SpawnMobj3fv(MT_MINOTAUR, actor->pos, actor->angle, 0))) { mobj_t* master; if(P_TestMobjLocation(mo) == false || !actor->tracer) { // Didn't fit - change back to item. P_MobjChangeState(mo, S_NULL); if((mo = P_SpawnMobj3fv(MT_SUMMONMAULATOR, actor->pos, actor->angle, 0))) mo->flags2 |= MF2_DROPPED; return; } memcpy((void *) mo->args, &mapTime, sizeof(mapTime)); master = actor->tracer; if(master->flags & MF_CORPSE) { // Master dead. mo->tracer = NULL; // No master. } else { mo->tracer = actor->tracer; // Pointer to master (mobj_t *) P_GivePower(master->player, PT_MINOTAUR); } // Make smoke puff. P_SpawnMobj3fv(MT_MNTRSMOKE, actor->pos, P_Random() << 24, 0); S_StartSound(SFX_MAULATOR_ACTIVE, actor); } } /** * Fog Variables: * * args[0] Speed (0..10) of fog * args[1] Angle of spread (0..128) * args[2] Frequency of spawn (1..10) * args[3] Lifetime countdown * args[4] Boolean: fog moving? * special1 Internal: Counter for spawn frequency * special2 Internal: Index into floatbob table */ void C_DECL A_FogSpawn(mobj_t* actor) { mobj_t* mo = NULL; mobjtype_t type = 0; angle_t delta, angle; if(actor->special1-- > 0) return; actor->special1 = actor->args[2]; // Reset frequency count. switch(P_Random() % 3) { case 0: type = MT_FOGPATCHS; break; case 1: type = MT_FOGPATCHM; break; case 2: type = MT_FOGPATCHL; break; } delta = actor->args[1]; if(delta == 0) delta = 1; angle = ((P_Random() % delta) - (delta / 2)); angle <<= 24; if((mo = P_SpawnMobj3fv(type, actor->pos, actor->angle + angle, 0))) { mo->target = actor; if(actor->args[0] < 1) actor->args[0] = 1; mo->args[0] = (P_Random() % (actor->args[0])) + 1; // Random speed. mo->args[3] = actor->args[3]; // Set lifetime. mo->args[4] = 1; // Set to moving. mo->special2 = P_Random() & 63; } } void C_DECL A_FogMove(mobj_t *actor) { float speed = (float) actor->args[0]; uint an, weaveindex; if(!(actor->args[4])) return; if(actor->args[3]-- <= 0) { P_SetMobjStateNF(actor, P_GetState(actor->type, SN_DEATH)); return; } if((actor->args[3] % 4) == 0) { weaveindex = actor->special2; actor->pos[VZ] += FLOATBOBOFFSET(weaveindex) * 2; actor->special2 = (weaveindex + 1) & 63; } an = actor->angle >> ANGLETOFINESHIFT; actor->mom[MX] = speed * FIX2FLT(finecosine[an]); actor->mom[MY] = speed * FIX2FLT(finesine[an]); } void C_DECL A_PoisonBagInit(mobj_t* actor) { mobj_t* mo; if((mo = P_SpawnMobj3f(MT_POISONCLOUD, actor->pos[VX], actor->pos[VY], actor->pos[VZ] + 28, P_Random() << 24, 0))) { // Missile objects must move to impact other objects. mo->mom[MX] = FIX2FLT(1); mo->special1 = 24 + (P_Random() & 7); mo->special2 = 0; mo->target = actor->target; mo->radius = 20; mo->height = 30; mo->flags &= ~MF_NOCLIP; } } void C_DECL A_PoisonBagCheck(mobj_t *actor) { if(!--actor->special1) { P_MobjChangeState(actor, S_POISONCLOUD_X1); } else { return; } } void C_DECL A_PoisonBagDamage(mobj_t *actor) { int bobIndex; float z; A_Explode(actor); bobIndex = actor->special2; z = FLOATBOBOFFSET(bobIndex); actor->pos[VZ] += z / 16; actor->special2 = (bobIndex + 1) & 63; } void C_DECL A_PoisonShroom(mobj_t* actor) { actor->tics = 128 + (P_Random() << 1); } void C_DECL A_CheckThrowBomb(mobj_t* actor) { if(fabs(actor->mom[MX]) < 1.5f && fabs(actor->mom[MY]) < 1.5f && actor->mom[MZ] < 2 && actor->state == &STATES[S_THROWINGBOMB6]) { P_MobjChangeState(actor, S_THROWINGBOMB7); actor->pos[VZ] = actor->floorZ; actor->mom[MZ] = 0; actor->flags2 &= ~MF2_FLOORBOUNCE; actor->flags &= ~MF_MISSILE; actor->flags |= MF_VIEWALIGN; } if(!--actor->health) { P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH)); } } /** * Quake variables * * args[0] Intensity on richter scale (2..9) * args[1] Duration in tics * args[2] Radius for damage * args[3] Radius for tremor * args[4] TID of map thing for focus of quake */ boolean A_LocalQuake(byte* args, mobj_t* actor) { mobj_t* focus, *target; int lastfound = 0; int success = false; actor = actor; // Shutup compiler warning. // Find all quake foci. do { if((target = P_FindMobjFromTID(args[4], &lastfound))) { if((focus = P_SpawnMobj3fv(MT_QUAKE_FOCUS, target->pos, 0, 0))) { focus->args[0] = args[0]; focus->args[1] = args[1] / 2; // Decremented every 2 tics. focus->args[2] = args[2]; focus->args[3] = args[3]; focus->args[4] = args[4]; success = true; } } } while(target != NULL); return success; } void C_DECL A_Quake(mobj_t *actor) { angle_t angle; player_t *player; mobj_t *victim; int richters = actor->args[0]; int playnum; float dist; if(actor->args[1]-- > 0) { for(playnum = 0; playnum < MAXPLAYERS; ++playnum) { player = &players[playnum]; if(!players[playnum].plr->inGame) continue; victim = player->plr->mo; dist = P_ApproxDistance(actor->pos[VX] - victim->pos[VX], actor->pos[VY] - victim->pos[VY]); dist = FIX2FLT(FLT2FIX(dist) >> (FRACBITS + 6)); // Tested in tile units (64 pixels). if(dist < FIX2FLT(actor->args[3])) // In tremor radius. { localQuakeHappening[playnum] = richters; players[playnum].update |= PSF_LOCAL_QUAKE; } // Check if in damage radius. if(dist < FIX2FLT(actor->args[2]) && victim->pos[VZ] <= victim->floorZ) { if(P_Random() < 50) { P_DamageMobj(victim, NULL, NULL, HITDICE(1), false); } // Thrust player around. angle = victim->angle + ANGLE_1 * P_Random(); P_ThrustMobj(victim, angle, FIX2FLT(richters << (FRACBITS - 1))); } } } else { for(playnum = 0; playnum < MAXPLAYERS; playnum++) { localQuakeHappening[playnum] = false; players[playnum].update |= PSF_LOCAL_QUAKE; } P_MobjChangeState(actor, S_NULL); } } static void telospawn(mobjtype_t type, mobj_t* mo) { mobj_t* pmo; if((pmo = P_SpawnMobj3fv(MT_TELOTHER_FX2, mo->pos, mo->angle, 0))) { pmo->special1 = TELEPORT_LIFE; // Lifetime countdown. pmo->target = mo->target; pmo->mom[MX] = mo->mom[MX] / 2; pmo->mom[MY] = mo->mom[MY] / 2; pmo->mom[MZ] = mo->mom[MZ] / 2; } } void C_DECL A_TeloSpawnA(mobj_t* mo) { telospawn(MT_TELOTHER_FX2, mo); } void C_DECL A_TeloSpawnB(mobj_t* mo) { telospawn(MT_TELOTHER_FX3, mo); } void C_DECL A_TeloSpawnC(mobj_t* mo) { telospawn(MT_TELOTHER_FX4, mo); } void C_DECL A_TeloSpawnD(mobj_t* mo) { telospawn(MT_TELOTHER_FX5, mo); } void C_DECL A_CheckTeleRing(mobj_t* actor) { if(actor->special1-- <= 0) { P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH)); } } void P_SpawnDirt(mobj_t* mo, float radius) { float pos[3]; int dtype = 0; mobj_t* pmo; uint an; an = P_Random() << 5; pos[VX] = mo->pos[VX]; pos[VY] = mo->pos[VY]; pos[VZ] = mo->pos[VZ]; pos[VX] += radius * FIX2FLT(finecosine[an]); pos[VY] += radius * FIX2FLT(finesine[an]); pos[VZ] += FLT2FIX(P_Random() << 9) + 1; switch(P_Random() % 6) { case 0: dtype = MT_DIRT1; break; case 1: dtype = MT_DIRT2; break; case 2: dtype = MT_DIRT3; break; case 3: dtype = MT_DIRT4; break; case 4: dtype = MT_DIRT5; break; case 5: dtype = MT_DIRT6; break; } if((pmo = P_SpawnMobj3fv(dtype, pos, 0, 0))) { pmo->mom[MZ] = FIX2FLT(P_Random() << 10); } } /** * Thrust Spike Variables * tracer pointer to dirt clump mobj * special2 speed of raise * args[0] 0 = lowered, 1 = raised * args[1] 0 = normal, 1 = bloody */ void C_DECL A_ThrustInitUp(mobj_t* actor) { actor->special2 = 5; actor->args[0] = 1; actor->floorClip = 0; actor->flags = MF_SOLID; actor->flags2 = MF2_NOTELEPORT | MF2_FLOORCLIP; actor->tracer = NULL; } void C_DECL A_ThrustInitDn(mobj_t* actor) { mobj_t* mo; actor->special2 = 5; actor->args[0] = 0; actor->floorClip = actor->info->height; actor->flags = 0; actor->flags2 = MF2_NOTELEPORT | MF2_FLOORCLIP | MF2_DONTDRAW; if((mo = P_SpawnMobj3fv(MT_DIRTCLUMP, actor->pos, 0, 0))) actor->tracer = mo; } void C_DECL A_ThrustRaise(mobj_t* actor) { if(A_RaiseMobj(actor)) { // Reached it's target height. actor->args[0] = 1; if(actor->args[1]) P_SetMobjStateNF(actor, S_BTHRUSTINIT2_1); else P_SetMobjStateNF(actor, S_THRUSTINIT2_1); } // Lose the dirt clump. if(actor->floorClip < actor->height && actor->tracer) { P_MobjRemove(actor->tracer, false); actor->tracer = NULL; } // Spawn some dirt. if(P_Random() < 40) P_SpawnDirt(actor, actor->radius); actor->special2++; // Increase raise speed. } void C_DECL A_ThrustLower(mobj_t *actor) { if(A_SinkMobj(actor)) { actor->args[0] = 0; if(actor->args[1]) P_SetMobjStateNF(actor, S_BTHRUSTINIT1_1); else P_SetMobjStateNF(actor, S_THRUSTINIT1_1); } } void C_DECL A_ThrustBlock(mobj_t *actor) { actor->flags |= MF_SOLID; } void C_DECL A_ThrustImpale(mobj_t *actor) { // Impale all shootables in radius. PIT_ThrustSpike(actor); } #if MSVC # pragma optimize("g",off) #endif void C_DECL A_SoAExplode(mobj_t* actor) { int i; for(i = 0; i < 10; ++i) { mobj_t* mo; float pos[3]; pos[VX] = actor->pos[VX]; pos[VY] = actor->pos[VY]; pos[VZ] = actor->pos[VZ]; pos[VX] += FIX2FLT((P_Random() - 128) << 12); pos[VY] += FIX2FLT((P_Random() - 128) << 12); pos[VZ] += FIX2FLT(P_Random() * FLT2FIX(actor->height) / 256); if((mo = P_SpawnMobj3fv(MT_ZARMORCHUNK, pos, P_Random() << 24, 0))) { P_MobjChangeState(mo, P_GetState(mo->type, SN_SPAWN) + i); mo->mom[MZ] = ((P_Random() & 7) + 5); mo->mom[MX] = FIX2FLT((P_Random() - P_Random()) << 10); mo->mom[MY] = FIX2FLT((P_Random() - P_Random()) << 10); } } if(actor->args[0]) { // Spawn an item. if(!noMonstersParm || !(MOBJINFO[TranslateThingType[actor->args[0]]]. flags & MF_COUNTKILL)) { // Only spawn monsters if not -nomonsters. P_SpawnMobj3fv(TranslateThingType[actor->args[0]], actor->pos, actor->angle, 0); } } S_StartSound(SFX_SUITOFARMOR_BREAK, actor); P_MobjRemove(actor, false); } #if MSVC # pragma optimize("",on) #endif void C_DECL A_BellReset1(mobj_t *actor) { actor->flags |= MF_NOGRAVITY; actor->height *= 2*2; } void C_DECL A_BellReset2(mobj_t *actor) { actor->flags |= MF_SHOOTABLE; actor->flags &= ~MF_CORPSE; actor->health = 5; } void C_DECL A_FlameCheck(mobj_t *actor) { if(!actor->args[0]--) // Called every 8 tics. { P_MobjChangeState(actor, S_NULL); } } /** * Bat Spawner Variables * special1 frequency counter * special2 * args[0] frequency of spawn (1=fastest, 10=slowest) * args[1] spread angle (0..255) * args[2] * args[3] duration of bats (in octics) * args[4] turn amount per move (in degrees) * * Bat Variables * special2 lifetime counter * args[4] turn amount per move (in degrees) */ void C_DECL A_BatSpawnInit(mobj_t *actor) { actor->special1 = 0; // Frequency count. } void C_DECL A_BatSpawn(mobj_t *actor) { mobj_t *mo; int delta; angle_t angle; // Countdown until next spawn if(actor->special1-- > 0) return; actor->special1 = actor->args[0]; // Reset frequency count. delta = actor->args[1]; if(delta == 0) delta = 1; angle = actor->angle + (((P_Random() % delta) - (delta >> 1)) << 24); mo = P_SpawnMissileAngle(MT_BAT, actor, angle, 0); if(mo) { mo->args[0] = P_Random() & 63; // floatbob index mo->args[4] = actor->args[4]; // turn degrees mo->special2 = actor->args[3] << 3; // Set lifetime mo->target = actor; } } void C_DECL A_BatMove(mobj_t* actor) { angle_t angle; uint an; float speed; if(actor->special2 < 0) { P_MobjChangeState(actor, P_GetState(actor->type, SN_DEATH)); } actor->special2 -= 2; // Called every 2 tics if(P_Random() < 128) { angle = actor->angle + ANGLE_1 * actor->args[4]; } else { angle = actor->angle - ANGLE_1 * actor->args[4]; } // Adjust momentum vector to new direction an = angle >> ANGLETOFINESHIFT; speed = actor->info->speed * FIX2FLT(P_Random() << 10); actor->mom[MX] = speed * FIX2FLT(finecosine[an]); actor->mom[MY] = speed * FIX2FLT(finesine[an]); if(P_Random() < 15) S_StartSound(SFX_BAT_SCREAM, actor); // Handle Z movement actor->pos[VZ] = actor->target->pos[VZ] + 2 * FLOATBOBOFFSET((int) actor->args[0]); actor->args[0] = (actor->args[0] + 3) & 63; } void C_DECL A_TreeDeath(mobj_t* actor) { if(!(actor->flags2 & MF2_FIREDAMAGE)) { actor->height *= 2*2; actor->flags |= MF_SHOOTABLE; actor->flags &= ~(MF_CORPSE + MF_DROPOFF); actor->health = 35; return; } else { P_MobjChangeState(actor, P_GetState(actor->type, SN_MELEE)); } } void C_DECL A_NoGravity(mobj_t* actor) { actor->flags |= MF_NOGRAVITY; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/x_api.c0000644000175000017500000001217311357170242022066 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_api.c: Doomsday API setup and interaction - jHexen specific */ // HEADER FILES ------------------------------------------------------------ #include #include "jhexen.h" #include "hu_menu.h" #include "g_update.h" #include "d_net.h" #include "d_netsv.h" #include "p_setup.h" #include "p_mapsetup.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The interface to the Doomsday engine. game_export_t gx; game_import_t gi; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Get a 32-bit integer value. */ int G_GetInteger(int id) { switch(id) { case DD_GAME_DMUAPI_VER: return DMUAPI_VER; default: break; } // ID not recognized, return NULL. return 0; } /** * Get a pointer to the value of a variable. Added for 64-bit support. */ void *G_GetVariable(int id) { static float bob[2]; switch(id) { case DD_GAME_NAME: return GAMENAMETEXT; case DD_GAME_NICENAME: return GAME_NICENAME; case DD_GAME_ID: return GAMENAMETEXT " " GAME_VERSION_TEXT; case DD_GAME_MODE: return gameModeString; case DD_GAME_CONFIG: return gameConfigString; case DD_VERSION_SHORT: return GAME_VERSION_TEXT; case DD_VERSION_LONG: return GAME_VERSION_TEXTLONG "\n" GAME_DETAILS; case DD_ACTION_LINK: return actionlinks; case DD_XGFUNC_LINK: return NULL; case DD_PSPRITE_BOB_X: R_GetWeaponBob(DISPLAYPLAYER, &bob[0], NULL); return &bob[0]; case DD_PSPRITE_BOB_Y: R_GetWeaponBob(DISPLAYPLAYER, NULL, &bob[1]); return &bob[1]; default: break; } // ID not recognized, return NULL. return 0; } /** * Takes a copy of the engine's entry points and exported data. Returns * a pointer to the structure that contains our entry points and exports. */ game_export_t *GetGameAPI(game_import_t *imports) { // Take a copy of the imports, but only copy as much data as is // allowed and legal. memset(&gi, 0, sizeof(gi)); memcpy(&gi, imports, MIN_OF(sizeof(game_import_t), imports->apiSize)); // Clear all of our exports. memset(&gx, 0, sizeof(gx)); // Fill in the data for the exports. gx.apiSize = sizeof(gx); gx.PreInit = G_PreInit; gx.PostInit = G_PostInit; gx.Shutdown = G_Shutdown; gx.Ticker = G_Ticker; gx.G_Drawer = G_Display; gx.G_Drawer2 = G_Display2; gx.PrivilegedResponder = (boolean (*)(event_t *)) G_PrivilegedResponder; gx.FallbackResponder = NULL; //Hu_MenuResponder; gx.G_Responder = G_Responder; gx.MobjThinker = P_MobjThinker; gx.MobjFriction = (float (*)(void *)) P_MobjGetFriction; gx.EndFrame = G_EndFrame; gx.ConsoleBackground = G_ConsoleBg; gx.UpdateState = G_UpdateState; #undef Get gx.GetInteger = G_GetInteger; gx.GetVariable = G_GetVariable; gx.NetServerStart = D_NetServerStarted; gx.NetServerStop = D_NetServerClose; gx.NetConnect = D_NetConnect; gx.NetDisconnect = D_NetDisconnect; gx.NetPlayerEvent = D_NetPlayerEvent; gx.NetWorldEvent = D_NetWorldEvent; gx.HandlePacket = D_HandlePacket; gx.NetWriteCommands = D_NetWriteCommands; gx.NetReadCommands = D_NetReadCommands; // Data structure sizes. gx.ticcmdSize = sizeof(ticcmd_t); gx.mobjSize = sizeof(mobj_t); gx.polyobjSize = sizeof(polyobj_t); gx.SetupForMapData = P_SetupForMapData; // These really need better names. Ideas? gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; return &gx; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/m_cheat.c0000644000175000017500000007141511357170242022372 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_cheat.c: */ // HEADER FILES ------------------------------------------------------------ #include #include #include "jhexen.h" #include "f_infine.h" #include "d_net.h" #include "g_common.h" #include "p_player.h" #include "am_map.h" #include "hu_menu.h" #include "hu_msg.h" #include "dmu_lib.h" #include "p_user.h" #include "p_start.h" #include "p_inventory.h" #include "g_eventsequence.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- int Cht_GodFunc(const int* args, int player); int Cht_NoClipFunc(const int* args, int player); int Cht_WeaponsFunc(const int* args, int player); int Cht_HealthFunc(const int* args, int player); int Cht_GiveKeysFunc(const int* args, int player); int Cht_SoundFunc(const int* args, int player); int Cht_InventoryFunc(const int* args, int player); int Cht_PuzzleFunc(const int* args, int player); int Cht_InitFunc(const int* args, int player); int Cht_WarpFunc(const int* args, int player); int Cht_PigFunc(const int* args, int player); int Cht_MassacreFunc(const int* args, int player); int Cht_IDKFAFunc(const int* args, int player); int Cht_QuickenFunc1(const int* args, int player); int Cht_QuickenFunc2(const int* args, int player); int Cht_QuickenFunc3(const int* args, int player); int Cht_ClassFunc1(const int* args, int player); int Cht_ClassFunc2(const int* args, int player); int Cht_VersionFunc(const int* args, int player); int Cht_ScriptFunc1(const int* args, int player); int Cht_ScriptFunc2(const int* args, int player); int Cht_ScriptFunc3(const int* args, int player); int Cht_RevealFunc(const int* args, int player); int Cht_WhereFunc(const int* args, int player); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // Toggle god mode static unsigned char cheatGodSeq[] = { 's', 'a', 't', 'a', 'n' }; // Toggle no clipping mode static unsigned char cheatNoClipSeq[] = { 'c', 'a', 's', 'p', 'e', 'r' }; // Get all weapons and mana static unsigned char cheatWeaponsSeq[] = { 'n', 'r', 'a' }; // Get full health static unsigned char cheatHealthSeq[] = { 'c', 'l', 'u', 'b', 'm', 'e', 'd' }; // Get all keys static unsigned char cheatKeysSeq[] = { 'l', 'o', 'c', 'k', 's', 'm', 'i', 't', 'h' }; // Toggle sound debug info static unsigned char cheatSoundSeq[] = { 'n', 'o', 'i', 's', 'e' }; // Toggle ticker static unsigned char cheatTickerSeq[] = { 't', 'i', 'c', 'k', 'e', 'r' }; // Get all inventory items static unsigned char cheatInventorySeq[] = { 'i', 'n', 'd', 'i', 'a', 'n', 'a' }; // Get all puzzle pieces static unsigned char cheatPuzzleSeq[] = { 's', 'h', 'e', 'r', 'l', 'o', 'c', 'k' }; // Warp to new map static unsigned char cheatWarpSeq[] = { 'v', 'i', 's', 'i', 't', 1, 0, 0 }; // Become a pig static unsigned char cheatPigSeq[] = { 'd', 'e', 'l', 'i', 'v', 'e', 'r', 'a', 'n', 'c', 'e' }; // Kill all monsters static unsigned char cheatMassacreSeq[] = { 'b', 'u', 't', 'c', 'h', 'e', 'r' }; static unsigned char cheatIDKFASeq[] = { 'c', 'o', 'n', 'a', 'n' }; static unsigned char cheatQuickenSeq1[] = { 'm', 'a', 'r', 't', 'e', 'k' }; static unsigned char cheatQuickenSeq2[] = { 'm', 'a', 'r', 't', 'e', 'k', 'm', 'a', 'r', 't', 'e', 'k' }; static unsigned char cheatQuickenSeq3[] = { 'm', 'a', 'r', 't', 'e', 'k', 'm', 'a', 'r', 't', 'e', 'k', 'm', 'a', 'r', 't', 'e', 'k' }; // New class static unsigned char cheatClass1Seq[] = { 's', 'h', 'a', 'd', 'o', 'w', 'c', 'a', 's', 't', 'e', 'r' }; static unsigned char cheatClass2Seq[] = { 's', 'h', 'a', 'd', 'o', 'w', 'c', 'a', 's', 't', 'e', 'r', 1, 0 }; static unsigned char cheatInitSeq[] = { 'i', 'n', 'i', 't' }; static unsigned char cheatVersionSeq[] = { 'm', 'r', 'j', 'o', 'n', 'e', 's' }; static unsigned char cheatDebugSeq[] = { 'w', 'h', 'e', 'r', 'e' }; static unsigned char cheatScriptSeq1[] = { 'p', 'u', 'k', 'e' }; static unsigned char cheatScriptSeq2[] = { 'p', 'u', 'k', 'e', 1, 0 }; static unsigned char cheatScriptSeq3[] = { 'p', 'u', 'k', 'e', 1, 0, 0 }; static unsigned char cheatRevealSeq[] = { 'm', 'a', 'p', 's', 'c', 'o' }; static unsigned char cheatTrackSeq1[] = { 'c', 'd', 't' }; static unsigned char cheatTrackSeq2[] = { 'c', 'd', 't', 1, 0, 0 }; // CODE -------------------------------------------------------------------- static boolean cheatsEnabled(void) { return !IS_NETGAME; } void Cht_Init(void) { G_AddEventSequence(cheatGodSeq, sizeof(cheatGodSeq), Cht_GodFunc); G_AddEventSequence(cheatNoClipSeq, sizeof(cheatNoClipSeq), Cht_NoClipFunc); G_AddEventSequence(cheatWeaponsSeq, sizeof(cheatWeaponsSeq), Cht_WeaponsFunc); G_AddEventSequence(cheatHealthSeq, sizeof(cheatHealthSeq), Cht_HealthFunc); G_AddEventSequence(cheatKeysSeq, sizeof(cheatKeysSeq), Cht_GiveKeysFunc); G_AddEventSequence(cheatSoundSeq, sizeof(cheatSoundSeq), Cht_SoundFunc); G_AddEventSequence(cheatInventorySeq, sizeof(cheatInventorySeq), Cht_InventoryFunc); G_AddEventSequence(cheatPuzzleSeq, sizeof(cheatPuzzleSeq), Cht_PuzzleFunc); G_AddEventSequence(cheatWarpSeq, sizeof(cheatWarpSeq), Cht_WarpFunc); G_AddEventSequence(cheatPigSeq, sizeof(cheatPigSeq), Cht_PigFunc); G_AddEventSequence(cheatMassacreSeq, sizeof(cheatMassacreSeq), Cht_MassacreFunc); G_AddEventSequence(cheatIDKFASeq, sizeof(cheatIDKFASeq), Cht_IDKFAFunc); G_AddEventSequence(cheatQuickenSeq3, sizeof(cheatQuickenSeq3), Cht_QuickenFunc3); G_AddEventSequence(cheatQuickenSeq2, sizeof(cheatQuickenSeq2), Cht_QuickenFunc2); G_AddEventSequence(cheatQuickenSeq1, sizeof(cheatQuickenSeq1), Cht_QuickenFunc1); G_AddEventSequence(cheatClass2Seq, sizeof(cheatClass2Seq), Cht_ClassFunc2); G_AddEventSequence(cheatClass1Seq, sizeof(cheatClass1Seq), Cht_ClassFunc1); G_AddEventSequence(cheatInitSeq, sizeof(cheatInitSeq), Cht_InitFunc); G_AddEventSequence(cheatVersionSeq, sizeof(cheatVersionSeq), Cht_VersionFunc); G_AddEventSequence(cheatDebugSeq, sizeof(cheatDebugSeq), Cht_WhereFunc); G_AddEventSequence(cheatScriptSeq3, sizeof(cheatScriptSeq3), Cht_ScriptFunc3); G_AddEventSequence(cheatScriptSeq2, sizeof(cheatScriptSeq2), Cht_ScriptFunc2); G_AddEventSequence(cheatScriptSeq1, sizeof(cheatScriptSeq1), Cht_ScriptFunc1); G_AddEventSequence(cheatRevealSeq, sizeof(cheatRevealSeq), Cht_RevealFunc); } int Cht_GodFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->cheats ^= CF_GODMODE; plr->update |= PSF_STATE; P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_GODMODE) ? TXT_CHEATGODON : TXT_CHEATGODOFF), false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } static void giveArmor(player_t* plr) { int i; plr->update |= PSF_ARMOR_POINTS; for(i = 0; i < NUMARMOR; ++i) plr->armorPoints[i] = PCLASS_INFO(plr->class)->armorIncrement[i]; } static void giveWeapons(player_t* plr) { int i; plr->update |= PSF_OWNED_WEAPONS; for(i = 0; i < NUM_WEAPON_TYPES; ++i) { plr->weapons[i].owned = true; } } static void giveAmmo(player_t* plr) { int i; plr->update |= PSF_AMMO; for(i = 0; i < NUM_AMMO_TYPES; ++i) { plr->ammo[i].owned = MAX_MANA; } } int Cht_GiveKeysFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->update |= PSF_KEYS; plr->keys = 2047; P_SetMessage(plr, TXT_CHEATKEYS, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_WeaponsFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. giveWeapons(plr); giveAmmo(plr); giveArmor(plr); P_SetMessage(plr, TXT_CHEATWEAPONS, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_NoClipFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->cheats ^= CF_NOCLIP; plr->update |= PSF_STATE; P_SetMessage(plr, ((P_GetPlayerCheats(plr) & CF_NOCLIP) ? TXT_CHEATNOCLIPON : TXT_CHEATNOCLIPOFF), false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_WarpFunc(const int* args, int player) { player_t* plr = &players[player]; int i, tens, ones; uint map; char mapName[9]; if(IS_NETGAME) return false; tens = args[0] - '0'; ones = args[1] - '0'; if(tens < 0 || tens > 9 || ones < 1 || ones > 9) { // Bad map P_SetMessage(plr, TXT_CHEATBADINPUT, false); return false; } map = P_TranslateMap((tens * 10 + ones) - 1); if(userGame && map == gameMap) { // Don't try to teleport to the current map. P_SetMessage(plr, TXT_CHEATBADINPUT, false); return false; } // Search primary lumps. sprintf(mapName, "MAP%02u", map+1); if(W_CheckNumForName(mapName) == -1) { // Can't find. P_SetMessage(plr, TXT_CHEATNOMAP, false); return false; } S_LocalSound(SFX_PLATFORM_STOP, NULL); P_SetMessage(plr, TXT_CHEATWARP, false); // Clear the menu if open. Hu_MenuCommand(MCMD_CLOSE); // Close any open automaps. for(i = 0; i < MAXPLAYERS; ++i) if(players[i].plr->inGame) AM_Open(AM_MapForPlayer(i), false, true); // So be it. if(userGame) { nextMap = map; nextMapEntryPoint = 0; briefDisabled = true; G_SetGameAction(GA_LEAVEMAP); } else { briefDisabled = true; G_StartNewInit(); G_InitNew(dSkill, 0, map); } return true; } int Cht_SoundFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. debugSound = !debugSound; if(debugSound) { P_SetMessage(plr, TXT_CHEATSOUNDON, false); } else { P_SetMessage(plr, TXT_CHEATSOUNDOFF, false); } S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } static void printDebugInfo(int player) { player_t* plr = &players[player]; char lumpName[9], textBuffer[256]; subsector_t* sub; if(!plr->plr->mo) return; P_GetMapLumpName(gameEpisode, gameMap, lumpName); sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", lumpName, plr->plr->mo->pos[VX], plr->plr->mo->pos[VY], plr->plr->mo->pos[VZ]); P_SetMessage(plr, textBuffer, false); // Also print some information to the console. Con_Message(textBuffer); sub = plr->plr->mo->subsector; Con_Message("\nSubsector %i:\n", P_ToIndex(sub)); Con_Message(" FloorZ:%g Material:%s\n", P_GetFloatp(sub, DMU_FLOOR_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_FLOOR_MATERIAL))); Con_Message(" CeilingZ:%g Material:%s\n", P_GetFloatp(sub, DMU_CEILING_HEIGHT), P_GetMaterialName(P_GetPtrp(sub, DMU_CEILING_MATERIAL))); Con_Message("Player height:%g Player radius:%g\n", plr->plr->mo->height, plr->plr->mo->radius); } int Cht_WhereFunc(const int* args, int player) { if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(!userGame) return false; printDebugInfo(player); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_HealthFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. plr->update |= PSF_HEALTH; if(plr->morphTics) { plr->health = plr->plr->mo->health = MAXMORPHHEALTH; } else { plr->health = plr->plr->mo->health = maxHealth; } P_SetMessage(plr, TXT_CHEATHEALTH, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_InventoryFunc(const int* args, int player) { player_t* plr = &players[player]; int i, j; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. for(i = IIT_NONE + 1; i < IIT_FIRSTPUZZITEM; ++i) { for(j = 0; j < 25; ++j) { P_InventoryGive(player, i, false); } } P_SetMessage(plr, TXT_CHEATINVITEMS3, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_PuzzleFunc(const int* args, int player) { player_t* plr = &players[player]; int i; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. for(i = IIT_FIRSTPUZZITEM; i < NUM_INVENTORYITEM_TYPES; ++i) { P_InventoryGive(player, i, false); } P_SetMessage(plr, TXT_CHEATINVITEMS3, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_InitFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. G_DeferedInitNew(gameSkill, gameEpisode, gameMap); P_SetMessage(plr, TXT_CHEATWARP, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_PigFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. if(plr->morphTics) { P_UndoPlayerMorph(plr); } else { P_MorphPlayer(plr); } P_SetMessage(plr, "SQUEAL!!", false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_MassacreFunc(const int* args, int player) { player_t* plr = &players[player]; int count; char buf[80]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. count = P_Massacre(); sprintf(buf, "%d MONSTERS KILLED\n", count); P_SetMessage(plr, buf, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_IDKFAFunc(const int* args, int player) { player_t* plr = &players[player]; int i; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. if(plr->morphTics) { return false; } for(i = 0; i < NUM_WEAPON_TYPES; ++i) { plr->weapons[i].owned = false; } plr->pendingWeapon = WT_FIRST; P_SetMessage(plr, TXT_CHEATIDKFA, false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_QuickenFunc1(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, "TRYING TO CHEAT? THAT'S ONE....", false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_QuickenFunc2(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, "THAT'S TWO....", false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_QuickenFunc3(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_DamageMobj(plr->plr->mo, NULL, plr->plr->mo, 10000, false); P_SetMessage(plr, "THAT'S THREE! TIME TO DIE.", false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_ClassFunc1(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, "ENTER NEW PLAYER CLASS NUMBER", false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_ClassFunc2(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_PlayerChangeClass(plr, args[0] - '0'); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_VersionFunc(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. DD_Execute(false, "version"); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_ScriptFunc1(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, "RUN WHICH SCRIPT(01-99)?", false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_ScriptFunc2(const int* args, int player) { player_t* plr = &players[player]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. P_SetMessage(plr, "RUN WHICH SCRIPT(01-99)?", false); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_ScriptFunc3(const int* args, int player) { player_t* plr = &players[player]; int script, tens, ones; byte scriptArgs[3]; char textBuffer[40]; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. tens = args[0] - '0'; ones = args[1] - '0'; script = tens * 10 + ones; if(script < 1) return false; if(script > 99) return false; scriptArgs[0] = scriptArgs[1] = scriptArgs[2] = 0; if(P_StartACS(script, 0, scriptArgs, plr->plr->mo, NULL, 0)) { sprintf(textBuffer, "RUNNING SCRIPT %.2d", script); P_SetMessage(plr, textBuffer, false); } S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } int Cht_RevealFunc(const int* args, int player) { player_t* plr = &players[player]; automapid_t map; if(IS_NETGAME) return false; if(gameSkill == SM_NIGHTMARE) return false; if(plr->health <= 0) return false; // Dead players can't cheat. map = AM_MapForPlayer(plr - players); if(!AM_IsActive(map)) return false; AM_IncMapCheatLevel(map); S_LocalSound(SFX_PLATFORM_STOP, NULL); return true; } /** * This is the multipurpose cheat ccmd. */ DEFCC(CCmdCheat) { size_t i; // Give each of the characters in argument two to the SB event handler. for(i = 0; i < strlen(argv[1]); ++i) { event_t ev; ev.type = EV_KEY; ev.state = EVS_DOWN; ev.data1 = argv[1][i]; ev.data2 = ev.data3 = 0; G_EventSequenceResponder(&ev); } return true; } DEFCC(CCmdCheatGod) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("god"); } else { int player = CONSOLEPLAYER; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { player = atoi(argv[1]); if(player < 0 || player >= MAXPLAYERS) return false; } if(!players[player].plr->inGame) return false; Cht_GodFunc(NULL, player); } } return true; } DEFCC(CCmdCheatNoClip) { if(G_GetGameState() == GS_MAP) { if(IS_CLIENT) { NetCl_CheatRequest("noclip"); } else { int player = CONSOLEPLAYER; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { player = atoi(argv[1]); if(player < 0 || player >= MAXPLAYERS) return false; } if(!players[player].plr->inGame) return false; Cht_NoClipFunc(NULL, player); } } return true; } static int suicideResponse(msgresponse_t response, void* context) { if(response == MSG_YES) { if(IS_NETGAME && IS_CLIENT) { NetCl_CheatRequest("suicide"); } else { player_t* plr = &players[CONSOLEPLAYER]; P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); } } return true; } DEFCC(CCmdCheatSuicide) { if(G_GetGameState() == GS_MAP) { player_t* plr; if(IS_NETGAME && !netSvAllowCheats) return false; if(argc == 2) { int i = atoi(argv[1]); if(i < 0 || i >= MAXPLAYERS) return false; plr = &players[i]; } else plr = &players[CONSOLEPLAYER]; if(!plr->plr->inGame) return false; if(plr->playerState == PST_DEAD) return false; if(!IS_NETGAME || IS_CLIENT) { Hu_MsgStart(MSG_YESNO, SUICIDEASK, suicideResponse, NULL); return true; } P_DamageMobj(plr->plr->mo, NULL, NULL, 10000, false); return true; } else { Hu_MsgStart(MSG_ANYKEY, SUICIDEOUTMAP, NULL, NULL); } return true; } DEFCC(CCmdCheatWarp) { int num, args[2]; if(IS_NETGAME) return false; if(argc != 2) { Con_Printf("Usage: warp (num)\n"); return true; } num = atoi(argv[1]); args[0] = num / 10 + '0'; args[1] = num % 10 + '0'; Cht_WarpFunc(args, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatReveal) { int option; automapid_t map; if(!cheatsEnabled()) return false; map = AM_MapForPlayer(CONSOLEPLAYER); AM_SetCheatLevel(map, 0); AM_RevealMap(map, false); option = atoi(argv[1]); if(option < 0 || option > 3) return false; if(option == 1) AM_RevealMap(map, true); else if(option != 0) AM_SetCheatLevel(map, option -1); return true; } DEFCC(CCmdCheatGive) { char buf[100]; int player = CONSOLEPLAYER; size_t i, stuffLen; if(IS_CLIENT) { if(argc != 2) return false; sprintf(buf, "give %s", argv[1]); NetCl_CheatRequest(buf); return true; } if(IS_NETGAME && !netSvAllowCheats) return false; if(argc != 2 && argc != 3) { Con_Printf("Usage:\n give (stuff)\n"); Con_Printf(" give (stuff) (plr)\n"); Con_Printf("Stuff consists of one or more of (type:id). " "If no id; give all of type:\n"); Con_Printf(" i - items\n"); Con_Printf(" h - health\n"); Con_Printf(" k - keys\n"); Con_Printf(" p - puzzle\n"); Con_Printf(" w - weapons\n"); Con_Printf("Example: 'give ikw' gives items, keys and weapons.\n"); Con_Printf("Example: 'give w2k1' gives weapon two and key one.\n"); return true; } if(argc == 3) { player = atoi(argv[2]); if(player < 0 || player >= MAXPLAYERS) return false; } if(G_GetGameState() != GS_MAP) { Con_Printf("Can only \"give\" when in a game!\n"); return true; } if(!players[player].plr->inGame) return true; // Can't give to a plr who's not playing. strcpy(buf, argv[1]); // Stuff is the 2nd arg. strlwr(buf); stuffLen = strlen(buf); for(i = 0; buf[i]; ++i) { switch(buf[i]) { case 'i': Cht_InventoryFunc(NULL, player); break; case 'h': Cht_HealthFunc(NULL, player); break; case 'k': { player_t* plr = &players[player]; boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_KEY_TYPES) { // Give one specific key. plr->update |= PSF_KEYS; plr->keys |= (1 << idx); giveAll = false; i++; } } if(giveAll) { Cht_GiveKeysFunc(NULL, player); } break; } case 'p': Cht_PuzzleFunc(NULL, player); break; case 'w': { player_t* plr = &players[player]; boolean giveAll = true; if(i < stuffLen) { int idx; idx = ((int) buf[i+1]) - 48; if(idx >= 0 && idx < NUM_WEAPON_TYPES) { // Give one specific weapon. plr->update |= PSF_OWNED_WEAPONS; plr->weapons[idx].owned = true; giveAll = false; i++; } } if(giveAll) { giveWeapons(plr); } break; } default: // Unrecognized Con_Printf("What do you mean, '%c'?\n", buf[i]); break; } } return true; } DEFCC(CCmdCheatMassacre) { Cht_MassacreFunc(NULL, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatWhere) { Cht_WhereFunc(NULL, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatPig) { if(IS_NETGAME) return false; if(!userGame || gameSkill == SM_NIGHTMARE || players[CONSOLEPLAYER].health <= 0) return false; Cht_PigFunc(NULL, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatShadowcaster) { int args[2]; if(IS_NETGAME) return false; if(!userGame || gameSkill == SM_NIGHTMARE || players[CONSOLEPLAYER].health <= 0) return false; args[0] = atoi(argv[1]) + '0'; Cht_ClassFunc2(args, CONSOLEPLAYER); return true; } DEFCC(CCmdCheatRunScript) { int num, args[2]; if(IS_NETGAME) return false; if(!userGame) return false; num = atoi(argv[1]); args[0] = num / 10 + '0'; args[1] = num % 10 + '0'; Cht_ScriptFunc3(args, CONSOLEPLAYER); return true; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/g_ctrl.c0000644000175000017500000000656311357170242022246 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.c: Control bindings - Hexen specific */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "g_controls.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- /** * Register all the various player controls with Doomsday. */ void G_RegisterPlayerControls(void) { /* typedef struct { char *command; // The command to execute. } control_t; control_t axisCts[] = { {"WALK"}, {"SIDESTEP"}, {"turn"}, {"ZFLY"}, {"look"}, {"MAPPANX"}, {"MAPPANY"}, {""} // terminate }; control_t toggleCts[] = { {"ATTACK"}, {"USE"}, {"strafe"}, {"SPEED"}, {"JUMP"}, {"mlook"}, {"jlook"}, {"mzoomin"}, {"mzoomout"}, {""} // terminate }; control_t impulseCts[] = { {"falldown"}, {"lookcntr"}, {"usearti"}, {"panic"}, {"torch"}, {"health"}, {"mystic"}, {"krater"}, {"spdboots"}, {"blast"}, {"teleport"}, {"teleothr"}, {"poison"}, {"cantdie"}, {"servant"}, {"egg"}, {"weapon1"}, {"weapon2"}, {"weapon3"}, {"weapon4"}, {"nextwpn"}, {"prevwpn"}, {"demostop"}, {""} // terminate }; uint i; // Axis controls. for(i = 0; axisCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_AXIS, axisCts[i].command); } // Toggle controls. for(i = 0; toggleCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_TOGGLE, toggleCts[i].command); } // Impulse controls. for(i = 0; impulseCts[i].command[0]; ++i) { P_RegisterPlayerControl(CC_IMPULSE, impulseCts[i].command); }*/ } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_waggle.c0000644000175000017500000001072311357170242022552 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_waggle.c: */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "dmu_lib.h" #include "p_map.h" #include "p_mapspec.h" #include "p_iterlist.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- void T_FloorWaggle(waggle_t* waggle) { float fh; switch(waggle->state) { default: case WS_STABLE: if(waggle->ticker != -1) { if(!--waggle->ticker) { waggle->state = WS_REDUCE; } } break; case WS_EXPAND: if((waggle->scale += waggle->scaleDelta) >= waggle->targetScale) { waggle->scale = waggle->targetScale; waggle->state = WS_STABLE; } break; case WS_REDUCE: if((waggle->scale -= waggle->scaleDelta) <= 0) { // Remove. P_SetFloatp(waggle->sector, DMU_FLOOR_HEIGHT, waggle->originalHeight); P_ChangeSector(waggle->sector, true); P_ToXSector(waggle->sector)->specialData = NULL; P_TagFinished(P_ToXSector(waggle->sector)->tag); DD_ThinkerRemove(&waggle->thinker); return; } break; } waggle->accumulator += waggle->accDelta; fh = waggle->originalHeight + FLOATBOBOFFSET(((int) waggle->accumulator) & 63) * waggle->scale; P_SetFloatp(waggle->sector, DMU_FLOOR_HEIGHT, fh); P_SetFloatp(waggle->sector, DMU_FLOOR_TARGET_HEIGHT, fh); P_SetFloatp(waggle->sector, DMU_FLOOR_SPEED, 0); P_ChangeSector(waggle->sector, true); } boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset, int timer) { boolean retCode = false; sector_t* sec = NULL; waggle_t* waggle; iterlist_t* list; list = P_GetSectorIterListForTag(tag, false); if(!list) return retCode; P_IterListResetIterator(list, true); while((sec = P_IterListIterator(list)) != NULL) { if(P_ToXSector(sec)->specialData) continue; // Already moving, so keep going... retCode = true; waggle = Z_Calloc(sizeof(*waggle), PU_MAP, 0); waggle->thinker.function = T_FloorWaggle; DD_ThinkerAdd(&waggle->thinker); P_ToXSector(sec)->specialData = waggle; waggle->sector = sec; waggle->originalHeight = P_GetFloatp(sec, DMU_FLOOR_HEIGHT); waggle->accumulator = offset; waggle->accDelta = FIX2FLT(speed << 10); waggle->scale = 0; waggle->targetScale = FIX2FLT(height << 10); waggle->scaleDelta = FIX2FLT(FLT2FIX(waggle->targetScale) / (TICSPERSEC + ((3 * TICSPERSEC) * height) / 255)); waggle->ticker = timer ? timer * 35 : -1; waggle->state = WS_EXPAND; } return retCode; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/src/p_maputl.c0000644000175000017500000002043711357170242022611 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputl.c: Map utility routines - jHexen specific. */ // HEADER FILES ------------------------------------------------------------ #include "jhexen.h" #include "r_common.h" #include "p_map.h" // MACROS ------------------------------------------------------------------ // TYPES ------------------------------------------------------------------- typedef struct mobjtargetableparams_s { mobj_t *source; mobj_t *target; } mobjtargetableparams_t; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- // PUBLIC DATA DEFINITIONS ------------------------------------------------- intercept_t intercepts[MAXINTERCEPTS], *intercept_p; divline_t trace; boolean earlyout; int ptflags; // PRIVATE DATA DEFINITIONS ------------------------------------------------ // CODE -------------------------------------------------------------------- boolean PIT_MobjTargetable(mobj_t *mo, void *data) { mobjtargetableparams_t *params = (mobjtargetableparams_t*) data; if(params->source->player) { // Minotaur looking around player. if((mo->flags & MF_COUNTKILL) || (mo->player && (mo != params->source))) { if(!(mo->flags & MF_SHOOTABLE) || (mo->flags2 & MF2_DORMANT) || ((mo->type == MT_MINOTAUR) && (mo->tracer == params->source)) || (IS_NETGAME && !deathmatch && mo->player)) return true; // Continue iteration. if(P_CheckSight(params->source, mo)) { params->target = mo; return false; // Stop iteration. } } } else if(params->source->type == MT_MINOTAUR) { // Looking around minotaur. mobj_t *master = params->source->tracer; if((mo->flags & MF_COUNTKILL) || (mo->player && (mo != master))) { if(!(mo->flags & MF_SHOOTABLE) || (mo->flags2 & MF2_DORMANT) || ((mo->type == MT_MINOTAUR) && (mo->tracer == params->source->tracer)) || (IS_NETGAME && !deathmatch && mo->player)) return true; // Continue iteration. if(P_CheckSight(params->source, mo)) { params->target = mo; return false; // Stop iteration. } } } else if(params->source->type == MT_MSTAFF_FX2) { // bloodscourge. if(((mo->flags & MF_COUNTKILL) || (mo->player && mo != params->source->target)) && !(mo->flags2 & MF2_DORMANT)) { if(!(mo->flags & MF_SHOOTABLE) || (IS_NETGAME && !deathmatch && mo->player)) return true; // Continue iteration. if(P_CheckSight(params->source, mo)) { angle_t angle; mobj_t *master; master = params->source->target; angle = R_PointToAngle2(master->pos[VX], master->pos[VY], mo->pos[VY], mo->pos[VY]) - master->angle; angle >>= 24; if(angle > 226 || angle < 30) { params->target = mo; return false; // Stop iteration. } } } } else { // spirits. if(((mo->flags & MF_COUNTKILL) || (mo->player && mo != params->source->target)) && !(mo->flags2 & MF2_DORMANT)) { if(!(mo->flags & MF_SHOOTABLE) || (IS_NETGAME && !deathmatch && mo->player) || mo == params->source->target) return true; // Continue iteration. if(P_CheckSight(params->source, mo)) { params->target = mo; return false; // Stop iteration. } } } return true; // Continue iteration. } /** * Searches around for targetable monsters/players near mobj. * * @return Ptr to the targeted mobj if found, ELSE @c NULL; */ mobj_t* P_RoughMonsterSearch(mobj_t *mo, int distance) { #define MAPBLOCKUNITS 128 #define MAPBLOCKSHIFT (FRACBITS+7) int i, block[2], startBlock[2]; int count; float mapOrigin[2]; float box[4]; mobjtargetableparams_t params; mapOrigin[VX] = *((float*) DD_GetVariable(DD_MAP_MIN_X)); mapOrigin[VY] = *((float*) DD_GetVariable(DD_MAP_MIN_Y)); // The original blockmap generator added a border of 8 units. mapOrigin[VX] -= 8; mapOrigin[VY] -= 8; params.source = mo; params.target = NULL; // Convert from world units to map block units. distance /= MAPBLOCKUNITS; // Determine the start block. startBlock[VX] = FLT2FIX(mo->pos[VX] - mapOrigin[VX]) >> MAPBLOCKSHIFT; startBlock[VY] = FLT2FIX(mo->pos[VY] - mapOrigin[VY]) >> MAPBLOCKSHIFT; box[BOXLEFT] = mapOrigin[VX] + startBlock[VX] * MAPBLOCKUNITS; box[BOXRIGHT] = box[BOXLEFT] + MAPBLOCKUNITS; box[BOXBOTTOM] = mapOrigin[VY] + startBlock[VY] * MAPBLOCKUNITS; box[BOXTOP] = box[BOXBOTTOM] + MAPBLOCKUNITS; // Check the first block. VALIDCOUNT++; if(!P_MobjsBoxIterator(box, PIT_MobjTargetable, ¶ms)) { // Found a target right away! return params.target; } for(count = 1; count <= distance; count++) { block[VX] = startBlock[VX] - count; block[VY] = startBlock[VY] - count; box[BOXLEFT] = mapOrigin[VX] + block[VX] * MAPBLOCKUNITS; box[BOXRIGHT] = box[BOXLEFT] + MAPBLOCKUNITS; box[BOXBOTTOM] = mapOrigin[VY] + block[VY] * MAPBLOCKUNITS; box[BOXTOP] = box[BOXBOTTOM] + MAPBLOCKUNITS; // Trace the first block section (along the top). for(i = 0; i < count * 2 + 1; ++i) { if(!P_MobjsBoxIterator(box, PIT_MobjTargetable, ¶ms)) return params.target; if(i < count * 2) { box[BOXLEFT] += MAPBLOCKUNITS; box[BOXRIGHT] += MAPBLOCKUNITS; } } // Trace the second block section (right edge). for(i = 0; i < count * 2; ++i) { box[BOXBOTTOM] += MAPBLOCKUNITS; box[BOXTOP] += MAPBLOCKUNITS; if(!P_MobjsBoxIterator(box, PIT_MobjTargetable, ¶ms)) return params.target; } // Trace the third block section (bottom edge). for(i = 0; i < count * 2; ++i) { box[BOXLEFT] -= MAPBLOCKUNITS; box[BOXRIGHT] -= MAPBLOCKUNITS; if(!P_MobjsBoxIterator(box, PIT_MobjTargetable, ¶ms)) return params.target; } // Trace the final block section (left edge). for(i = 0; i < count * 2 - 1; ++i) { box[BOXBOTTOM] -= MAPBLOCKUNITS; box[BOXTOP] -= MAPBLOCKUNITS; if(!P_MobjsBoxIterator(box, PIT_MobjTargetable, ¶ms)) return params.target; } } return NULL; #undef MAPBLOCKUNITS #undef MAPBLOCKSHIFT } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/config/0000755000175000017500000000000011523516204021271 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/config/startup.cfg0000644000175000017500000000120211357170242023452 0ustar keeskees# # -=- jHexen Startup -=- # # This file is included with all versions, which means that it gets # overwritten on each upgrade. Give all custom permanent commands in # autoexec.cfg or user.cfg. # Comment these if you want to use the default colors. uicolor text 1 1 1 uicolor shadow 0 0 0 uicolor bglight .22 .18 .18 uicolor bgmed .52 .4 .4 uicolor bgdark .33 .28 .28 uicolor borhigh 1 1 1 uicolor bormed 0 0 0 uicolor borlow .6 .2 .05 uicolor help .52 .4 .4 # The font. #font name fixed12 # Keymap. #keymap default.dkm # The user config file can contain anything the user wants to execute # before the main startup begins. exec user.cfg deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/0000755000175000017500000000000011523516204021447 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/m_random.h0000644000175000017500000000220611357170242023417 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_random.h: Random numbers. */ #ifndef __M_RANDOM_H__ #define __M_RANDOM_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif byte P_Random(void); byte M_Random(void); void M_ResetRandom(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/textdefs.h0000644000175000017500000002060711357170242023456 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * textdefs.h: */ #ifndef __TEXTDEFS_H__ #define __TEXTDEFS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #define GET_TXT(x) ((*gi.text)[x].text) #define NUM_QUITMESSAGES 0 #define PRESSKEY GET_TXT(TXT_PRESSKEY) #define PRESSYN GET_TXT(TXT_PRESSYN) #define TXT_PAUSED GET_TXT(TXT_TXT_PAUSED) #define QUITMSG GET_TXT(TXT_QUITMSG) #define LOADNET GET_TXT(TXT_LOADNET) #define QLOADNET GET_TXT(TXT_QLOADNET) #define QSAVESPOT GET_TXT(TXT_QSAVESPOT) #define SAVEDEAD GET_TXT(TXT_SAVEDEAD) #define SAVEOUTMAP GET_TXT(TXT_SAVEOUTMAP) #define QSPROMPT GET_TXT(TXT_QSPROMPT) #define QLPROMPT GET_TXT(TXT_QLPROMPT) #define NEWGAME GET_TXT(TXT_NEWGAME) #define MSGOFF GET_TXT(TXT_MSGOFF) #define MSGON GET_TXT(TXT_MSGON) #define NETEND GET_TXT(TXT_NETEND) #define ENDGAME GET_TXT(TXT_ENDGAME) #define ENDNOGAME GET_TXT(TXT_ENDNOGAME) #define SUICIDEOUTMAP GET_TXT(TXT_SUICIDEOUTMAP) #define SUICIDEASK GET_TXT(TXT_SUICIDEASK) #define DOSY GET_TXT(TXT_DOSY) #define TXT_GAMMA_LEVEL_OFF GET_TXT(TXT_TXT_GAMMA_LEVEL_OFF) #define TXT_GAMMA_LEVEL_1 GET_TXT(TXT_TXT_GAMMA_LEVEL_1) #define TXT_GAMMA_LEVEL_2 GET_TXT(TXT_TXT_GAMMA_LEVEL_2) #define TXT_GAMMA_LEVEL_3 GET_TXT(TXT_TXT_GAMMA_LEVEL_3) #define TXT_GAMMA_LEVEL_4 GET_TXT(TXT_TXT_GAMMA_LEVEL_4) #define EMPTYSTRING GET_TXT(TXT_EMPTYSTRING) // Mana #define TXT_MANA_1 GET_TXT(TXT_TXT_MANA_1) #define TXT_MANA_2 GET_TXT(TXT_TXT_MANA_2) #define TXT_MANA_BOTH GET_TXT(TXT_TXT_MANA_BOTH) // Keys #define TXT_KEY_STEEL GET_TXT(TXT_TXT_KEY_STEEL) #define TXT_KEY_CAVE GET_TXT(TXT_TXT_KEY_CAVE) #define TXT_KEY_AXE GET_TXT(TXT_TXT_KEY_AXE) #define TXT_KEY_FIRE GET_TXT(TXT_TXT_KEY_FIRE) #define TXT_KEY_EMERALD GET_TXT(TXT_TXT_KEY_EMERALD) #define TXT_KEY_DUNGEON GET_TXT(TXT_TXT_KEY_DUNGEON) #define TXT_KEY_SILVER GET_TXT(TXT_TXT_KEY_SILVER) #define TXT_KEY_RUSTED GET_TXT(TXT_TXT_KEY_RUSTED) #define TXT_KEY_HORN GET_TXT(TXT_TXT_KEY_HORN) #define TXT_KEY_SWAMP GET_TXT(TXT_TXT_KEY_SWAMP) #define TXT_KEY_CASTLE GET_TXT(TXT_TXT_KEY_CASTLE) // Inventory items #define TXT_INV_INVULNERABILITY GET_TXT(TXT_TXT_INV_INVULNERABILITY) #define TXT_INV_HEALTH GET_TXT(TXT_TXT_INV_HEALTH) #define TXT_INV_SUPERHEALTH GET_TXT(TXT_TXT_INV_SUPERHEALTH) #define TXT_INV_SUMMON GET_TXT(TXT_TXT_INV_SUMMON) #define TXT_INV_TORCH GET_TXT(TXT_TXT_INV_TORCH) #define TXT_INV_EGG GET_TXT(TXT_TXT_INV_EGG) #define TXT_INV_FLY GET_TXT(TXT_TXT_INV_FLY) #define TXT_INV_TELEPORT GET_TXT(TXT_TXT_INV_TELEPORT) #define TXT_INV_POISONBAG GET_TXT(TXT_TXT_INV_POISONBAG) #define TXT_INV_TELEPORTOTHER GET_TXT(TXT_TXT_INV_TELEPORTOTHER) #define TXT_INV_SPEED GET_TXT(TXT_TXT_INV_SPEED) #define TXT_INV_BOOSTMANA GET_TXT(TXT_TXT_INV_BOOSTMANA) #define TXT_INV_BOOSTARMOR GET_TXT(TXT_TXT_INV_BOOSTARMOR) #define TXT_INV_BLASTRADIUS GET_TXT(TXT_TXT_INV_BLASTRADIUS) #define TXT_INV_HEALINGRADIUS GET_TXT(TXT_TXT_INV_HEALINGRADIUS) // Puzzle items #define TXT_INV_PUZZSKULL GET_TXT(TXT_TXT_INV_PUZZSKULL) #define TXT_INV_PUZZGEMBIG GET_TXT(TXT_TXT_INV_PUZZGEMBIG) #define TXT_INV_PUZZGEMRED GET_TXT(TXT_TXT_INV_PUZZGEMRED) #define TXT_INV_PUZZGEMGREEN1 GET_TXT(TXT_TXT_INV_PUZZGEMGREEN1) #define TXT_INV_PUZZGEMGREEN2 GET_TXT(TXT_TXT_INV_PUZZGEMGREEN2) #define TXT_INV_PUZZGEMBLUE1 GET_TXT(TXT_TXT_INV_PUZZGEMBLUE1) #define TXT_INV_PUZZGEMBLUE2 GET_TXT(TXT_TXT_INV_PUZZGEMBLUE2) #define TXT_INV_PUZZBOOK1 GET_TXT(TXT_TXT_INV_PUZZBOOK1) #define TXT_INV_PUZZBOOK2 GET_TXT(TXT_TXT_INV_PUZZBOOK2) #define TXT_INV_PUZZSKULL2 GET_TXT(TXT_TXT_INV_PUZZSKULL2) #define TXT_INV_PUZZFWEAPON GET_TXT(TXT_TXT_INV_PUZZFWEAPON) #define TXT_INV_PUZZCWEAPON GET_TXT(TXT_TXT_INV_PUZZCWEAPON) #define TXT_INV_PUZZMWEAPON GET_TXT(TXT_TXT_INV_PUZZMWEAPON) #define TXT_INV_PUZZGEAR GET_TXT(TXT_TXT_INV_PUZZGEAR) #define TXT_USEPUZZLEFAILED GET_TXT(TXT_TXT_USEPUZZLEFAILED) // Items #define TXT_ITEMHEALTH GET_TXT(TXT_TXT_ITEMHEALTH) #define TXT_ITEMBAGOFHOLDING GET_TXT(TXT_TXT_ITEMBAGOFHOLDING) #define TXT_ITEMSHIELD1 GET_TXT(TXT_TXT_ITEMSHIELD1) #define TXT_ITEMSHIELD2 GET_TXT(TXT_TXT_ITEMSHIELD2) #define TXT_ITEMSUPERMAP GET_TXT(TXT_TXT_ITEMSUPERMAP) #define TXT_ARMOR1 GET_TXT(TXT_TXT_ARMOR1) #define TXT_ARMOR2 GET_TXT(TXT_TXT_ARMOR2) #define TXT_ARMOR3 GET_TXT(TXT_TXT_ARMOR3) #define TXT_ARMOR4 GET_TXT(TXT_TXT_ARMOR4) // Weapons #define TXT_WEAPON_F2 GET_TXT(TXT_TXT_WEAPON_F2) #define TXT_WEAPON_F3 GET_TXT(TXT_TXT_WEAPON_F3) #define TXT_WEAPON_F4 GET_TXT(TXT_TXT_WEAPON_F4) #define TXT_WEAPON_C2 GET_TXT(TXT_TXT_WEAPON_C2) #define TXT_WEAPON_C3 GET_TXT(TXT_TXT_WEAPON_C3) #define TXT_WEAPON_C4 GET_TXT(TXT_TXT_WEAPON_C4) #define TXT_WEAPON_M2 GET_TXT(TXT_TXT_WEAPON_M2) #define TXT_WEAPON_M3 GET_TXT(TXT_TXT_WEAPON_M3) #define TXT_WEAPON_M4 GET_TXT(TXT_TXT_WEAPON_M4) #define TXT_QUIETUS_PIECE GET_TXT(TXT_TXT_QUIETUS_PIECE) #define TXT_WRAITHVERGE_PIECE GET_TXT(TXT_TXT_WRAITHVERGE_PIECE) #define TXT_BLOODSCOURGE_PIECE GET_TXT(TXT_TXT_BLOODSCOURGE_PIECE) #define TXT_CHEATGODON GET_TXT(TXT_TXT_CHEATGODON) #define TXT_CHEATGODOFF GET_TXT(TXT_TXT_CHEATGODOFF) #define TXT_CHEATNOCLIPON GET_TXT(TXT_TXT_CHEATNOCLIPON) #define TXT_CHEATNOCLIPOFF GET_TXT(TXT_TXT_CHEATNOCLIPOFF) #define TXT_CHEATWEAPONS GET_TXT(TXT_TXT_CHEATWEAPONS) #define TXT_CHEATHEALTH GET_TXT(TXT_TXT_CHEATHEALTH) #define TXT_CHEATKEYS GET_TXT(TXT_TXT_CHEATKEYS) #define TXT_CHEATSOUNDON GET_TXT(TXT_TXT_CHEATSOUNDON) #define TXT_CHEATSOUNDOFF GET_TXT(TXT_TXT_CHEATSOUNDOFF) #define TXT_CHEATTICKERON GET_TXT(TXT_TXT_CHEATTICKERON) #define TXT_CHEATTICKEROFF GET_TXT(TXT_TXT_CHEATTICKEROFF) #define TXT_CHEATINVITEMS3 GET_TXT(TXT_TXT_CHEATINVITEMS3) #define TXT_CHEATITEMSFAIL GET_TXT(TXT_TXT_CHEATITEMSFAIL) #define TXT_CHEATWARP GET_TXT(TXT_TXT_CHEATWARP) #define TXT_CHEATSCREENSHOT GET_TXT(TXT_TXT_CHEATSCREENSHOT) #define TXT_CHEATIDDQD GET_TXT(TXT_TXT_CHEATIDDQD) #define TXT_CHEATIDKFA GET_TXT(TXT_TXT_CHEATIDKFA) #define TXT_CHEATBADINPUT GET_TXT(TXT_TXT_CHEATBADINPUT) #define TXT_CHEATNOMAP GET_TXT(TXT_TXT_CHEATNOMAP) #define TXT_GAMESAVED GET_TXT(TXT_TXT_GAMESAVED) #define HUSTR_CHATMACRO1 GET_TXT(TXT_HUSTR_CHATMACRO1) #define HUSTR_CHATMACRO2 GET_TXT(TXT_HUSTR_CHATMACRO2) #define HUSTR_CHATMACRO3 GET_TXT(TXT_HUSTR_CHATMACRO3) #define HUSTR_CHATMACRO4 GET_TXT(TXT_HUSTR_CHATMACRO4) #define HUSTR_CHATMACRO5 GET_TXT(TXT_HUSTR_CHATMACRO5) #define HUSTR_CHATMACRO6 GET_TXT(TXT_HUSTR_CHATMACRO6) #define HUSTR_CHATMACRO7 GET_TXT(TXT_HUSTR_CHATMACRO7) #define HUSTR_CHATMACRO8 GET_TXT(TXT_HUSTR_CHATMACRO8) #define HUSTR_CHATMACRO9 GET_TXT(TXT_HUSTR_CHATMACRO9) #define HUSTR_CHATMACRO0 GET_TXT(TXT_HUSTR_CHATMACRO0) #define AMSTR_FOLLOWON GET_TXT(TXT_AMSTR_FOLLOWON) #define AMSTR_FOLLOWOFF GET_TXT(TXT_AMSTR_FOLLOWOFF) #define AMSTR_ROTATEON GET_TXT(TXT_AMSTR_ROTATEON) #define AMSTR_ROTATEOFF GET_TXT(TXT_AMSTR_ROTATEOFF) #define AMSTR_GRIDON GET_TXT(TXT_AMSTR_GRIDON) #define AMSTR_GRIDOFF GET_TXT(TXT_AMSTR_GRIDOFF) #define AMSTR_MARKEDSPOT GET_TXT(TXT_AMSTR_MARKEDSPOT) #define AMSTR_MARKSCLEARED GET_TXT(TXT_AMSTR_MARKSCLEARED) #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/r_defs.h0000644000175000017500000000417311357170242023072 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_defs.h: */ #ifndef __R_DEFS_H__ #define __R_DEFS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "p_mobj.h" #include "s_sequence.h" typedef struct xsector_s { short special, tag; int soundTraversed; // 0 = untraversed, 1,2 = sndlines -1 mobj_t* soundTarget; // Thing that made a sound (or null) seqtype_t seqType; // Stone, metal, heavy, etc... void* specialData; // thinker_t for reversable actions } xsector_t; typedef struct xline_s { byte special; byte arg1; byte arg2; byte arg3; byte arg4; byte arg5; short flags; // Has been rendered at least once and needs to appear in the map, // for each player. boolean mapped[MAXPLAYERS]; int validCount; } xline_t; extern xline_t* xlines; extern xsector_t* xsectors; xline_t* P_ToXLine(linedef_t* line); xline_t* P_GetXLine(uint index); xsector_t* P_ToXSector(sector_t* sector); xsector_t* P_GetXSector(uint index); xsector_t* P_ToXSectorOfSubsector(subsector_t* sub); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/po_man.h0000644000175000017500000000477411357170242023110 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * po_man.h: Polyobjects. */ #ifndef __PO_MAN_H__ #define __PO_MAN_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif typedef enum { PODOOR_NONE, PODOOR_SLIDE, PODOOR_SWING, } podoortype_t; typedef struct { thinker_t thinker; int polyobj; int intSpeed; unsigned int dist; int fangle; float speed[2]; // for sliding walls } polyevent_t; typedef struct { thinker_t thinker; int polyobj; int intSpeed; int dist; int totalDist; int direction; float speed[2]; int tics; int waitTics; podoortype_t type; boolean close; } polydoor_t; enum { PO_ANCHOR_DOOMEDNUM = 3000, PO_SPAWN_DOOMEDNUM, PO_SPAWNCRUSH_DOOMEDNUM }; void PO_InitForMap(void); boolean PO_Busy(int polyobj); boolean PO_FindAndCreatePolyobj(int tag, boolean crush, float startX, float startY); void T_PolyDoor(polydoor_t* pd); void T_RotatePoly(polyevent_t* pe); boolean EV_RotatePoly(linedef_t* line, byte* args, int direction, boolean overRide); void T_MovePoly(polyevent_t* pe); boolean EV_MovePoly(linedef_t* line, byte* args, boolean timesEight, boolean overRide); boolean EV_OpenPolyDoor(linedef_t* line, byte* args, podoortype_t type); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/s_sequence.h0000644000175000017500000000571111357170242023761 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * s_sequence.h: Sound sequences. */ #ifndef __S_SEQUENCE_H__ #define __S_SEQUENCE_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif enum { SEQ_PLATFORM, SEQ_PLATFORM_HEAVY, // same script as a normal platform. SEQ_PLATFORM_METAL, SEQ_PLATFORM_CREAK, // same script as a normal platform. SEQ_PLATFORM_SILENCE, SEQ_PLATFORM_LAVA, SEQ_PLATFORM_WATER, SEQ_PLATFORM_ICE, SEQ_PLATFORM_EARTH, SEQ_PLATFORM_METAL2, SEQ_DOOR_STONE, SEQ_DOOR_HEAVY, SEQ_DOOR_METAL, SEQ_DOOR_CREAK, SEQ_DOOR_SILENCE, SEQ_DOOR_LAVA, SEQ_DOOR_WATER, SEQ_DOOR_ICE, SEQ_DOOR_EARTH, SEQ_DOOR_METAL2, SEQ_ESOUND_WIND, SEQ_NUMSEQ }; typedef enum { SEQTYPE_STONE, SEQTYPE_HEAVY, SEQTYPE_METAL, SEQTYPE_CREAK, SEQTYPE_SILENCE, SEQTYPE_LAVA, SEQTYPE_WATER, SEQTYPE_ICE, SEQTYPE_EARTH, SEQTYPE_METAL2, SEQTYPE_NUMSEQ } seqtype_t; typedef struct seqnode_s { int* sequencePtr; int sequence; mobj_t* mobj; int currentSoundID; int delayTics; int volume; int stopSound; struct seqnode_s* prev; struct seqnode_s* next; } seqnode_t; extern int ActiveSequences; extern seqnode_t* SequenceListHead; void SN_InitSequenceScript(void); void SN_StartSequence(mobj_t* mobj, int sequence); void SN_StartSequenceInSec(sector_t* sector, int seqBase); void SN_StartSequenceName(mobj_t* mobj, const char* name); void SN_StopSequence(mobj_t* mobj); void SN_StopSequenceInSec(sector_t* sector); void SN_UpdateActiveSequences(void); void SN_StopAllSequences(void); int SN_GetSequenceOffset(int sequence, int* sequencePtr); void SN_ChangeNodeData(int nodeNum, int seqOffset, int delayTics, int volume, int currentSoundID); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_waggle.h0000644000175000017500000000332411357170242023412 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_waggle.h: */ #ifndef __P_WAGGLE_H__ #define __P_WAGGLE_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif typedef enum { WS_EXPAND = 1, WS_STABLE, WS_REDUCE } wagglestate_e; typedef struct { thinker_t thinker; sector_t* sector; float originalHeight; float accumulator; float accDelta; float targetScale; float scale; float scaleDelta; int ticker; wagglestate_e state; } waggle_t; void T_FloorWaggle(waggle_t* waggle); boolean EV_StartFloorWaggle(int tag, int height, int speed, int offset, int timer); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_telept.h0000644000175000017500000000221511357170242023437 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_telept.h: */ #ifndef __P_TELEPT_H__ #define __P_TELEPT_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif void P_TeleportToDeathmatchStarts(mobj_t* mo); void P_TeleportToPlayerStarts(mobj_t* mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/a_action.h0000644000175000017500000000215211357170242023400 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * a_action.h: */ #ifndef __A_ACTION_H__ #define __A_ACTION_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_refresh.h0000644000175000017500000000243611357170242023615 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_refresh.h: */ #ifndef __X_REFRESH_H__ #define __X_REFRESH_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif extern float quitDarkenOpacity; void G_Display(int layer); void G_Display2(void); void R_SetViewSize(int blocks); void R_SetAllDoomsdayFlags(void); boolean R_GetFilterColor(float rgba[4], int filter); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_api.h0000644000175000017500000000234611357170242022730 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_api.h: Doomsday API setup and interaction - jHexen specific */ #ifndef __X_API_H__ #define __X_API_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "doomsday.h" int G_GetInteger(int id); void* G_GetVariable(int id); game_export_t* GetGameAPI(game_import_t* imports); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_enemy.h0000644000175000017500000000203111357170242023253 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_enemy.h: */ #ifndef __P_ENEMY_H__ #define __P_ENEMY_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/info.h0000644000175000017500000050676211357170242022576 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * info.h: Sprite, state, mobjtype and text identifiers. */ #ifndef __INFO_CONSTANTS_H__ #define __INFO_CONSTANTS_H__ // Sprites. typedef enum { SPR_MAN1, // 000 SPR_ACLO, // 001 SPR_TLGL, // 002 SPR_FBL1, // 003 SPR_XPL1, // 004 SPR_ARRW, // 005 SPR_DART, // 006 SPR_RIPP, // 007 SPR_CFCF, // 008 SPR_BLAD, // 009 SPR_SHRD, // 010 SPR_FFSM, // 011 SPR_FFLG, // 012 SPR_PTN1, // 013 SPR_PTN2, // 014 SPR_SOAR, // 015 SPR_INVU, // 016 SPR_SUMN, // 017 SPR_TSPK, // 018 SPR_TELO, // 019 SPR_TRNG, // 020 SPR_ROCK, // 021 SPR_FOGS, // 022 SPR_FOGM, // 023 SPR_FOGL, // 024 SPR_SGSA, // 025 SPR_SGSB, // 026 SPR_PORK, // 027 SPR_EGGM, // 028 SPR_FHFX, // 029 SPR_SPHL, // 030 SPR_STWN, // 031 SPR_GMPD, // 032 SPR_ASKU, // 033 SPR_ABGM, // 034 SPR_AGMR, // 035 SPR_AGMG, // 036 SPR_AGG2, // 037 SPR_AGMB, // 038 SPR_AGB2, // 039 SPR_ABK1, // 040 SPR_ABK2, // 041 SPR_ASK2, // 042 SPR_AFWP, // 043 SPR_ACWP, // 044 SPR_AMWP, // 045 SPR_AGER, // 046 SPR_AGR2, // 047 SPR_AGR3, // 048 SPR_AGR4, // 049 SPR_TRCH, // 050 SPR_PSBG, // 051 SPR_ATLP, // 052 SPR_THRW, // 053 SPR_SPED, // 054 SPR_BMAN, // 055 SPR_BRAC, // 056 SPR_BLST, // 057 SPR_HRAD, // 058 SPR_SPSH, // 059 SPR_LVAS, // 060 SPR_SLDG, // 061 SPR_STTW, // 062 SPR_RCK1, // 063 SPR_RCK2, // 064 SPR_RCK3, // 065 SPR_RCK4, // 066 SPR_CDLR, // 067 SPR_TRE1, // 068 SPR_TRDT, // 069 SPR_TRE2, // 070 SPR_TRE3, // 071 SPR_STM1, // 072 SPR_STM2, // 073 SPR_STM3, // 074 SPR_STM4, // 075 SPR_MSH1, // 076 SPR_MSH2, // 077 SPR_MSH3, // 078 SPR_MSH4, // 079 SPR_MSH5, // 080 SPR_MSH6, // 081 SPR_MSH7, // 082 SPR_MSH8, // 083 SPR_SGMP, // 084 SPR_SGM1, // 085 SPR_SGM2, // 086 SPR_SGM3, // 087 SPR_SLC1, // 088 SPR_SLC2, // 089 SPR_SLC3, // 090 SPR_MSS1, // 091 SPR_MSS2, // 092 SPR_SWMV, // 093 SPR_CPS1, // 094 SPR_CPS2, // 095 SPR_TMS1, // 096 SPR_TMS2, // 097 SPR_TMS3, // 098 SPR_TMS4, // 099 SPR_TMS5, // 100 SPR_TMS6, // 101 SPR_TMS7, // 102 SPR_CPS3, // 103 SPR_STT2, // 104 SPR_STT3, // 105 SPR_STT4, // 106 SPR_STT5, // 107 SPR_GAR1, // 108 SPR_GAR2, // 109 SPR_GAR3, // 110 SPR_GAR4, // 111 SPR_GAR5, // 112 SPR_GAR6, // 113 SPR_GAR7, // 114 SPR_GAR8, // 115 SPR_GAR9, // 116 SPR_BNR1, // 117 SPR_TRE4, // 118 SPR_TRE5, // 119 SPR_TRE6, // 120 SPR_TRE7, // 121 SPR_LOGG, // 122 SPR_ICT1, // 123 SPR_ICT2, // 124 SPR_ICT3, // 125 SPR_ICT4, // 126 SPR_ICM1, // 127 SPR_ICM2, // 128 SPR_ICM3, // 129 SPR_ICM4, // 130 SPR_RKBL, // 131 SPR_RKBS, // 132 SPR_RKBK, // 133 SPR_RBL1, // 134 SPR_RBL2, // 135 SPR_RBL3, // 136 SPR_VASE, // 137 SPR_POT1, // 138 SPR_POT2, // 139 SPR_POT3, // 140 SPR_PBIT, // 141 SPR_CPS4, // 142 SPR_CPS5, // 143 SPR_CPS6, // 144 SPR_CPB1, // 145 SPR_CPB2, // 146 SPR_CPB3, // 147 SPR_CPB4, // 148 SPR_BDRP, // 149 SPR_BDSH, // 150 SPR_BDPL, // 151 SPR_CNDL, // 152 SPR_LEF1, // 153 SPR_LEF3, // 154 SPR_LEF2, // 155 SPR_TWTR, // 156 SPR_WLTR, // 157 SPR_BARL, // 158 SPR_SHB1, // 159 SPR_SHB2, // 160 SPR_BCKT, // 161 SPR_SHRM, // 162 SPR_FBUL, // 163 SPR_FSKL, // 164 SPR_BRTR, // 165 SPR_SUIT, // 166 SPR_BBLL, // 167 SPR_CAND, // 168 SPR_IRON, // 169 SPR_XMAS, // 170 SPR_CDRN, // 171 SPR_CHNS, // 172 SPR_TST1, // 173 SPR_TST2, // 174 SPR_TST3, // 175 SPR_TST4, // 176 SPR_TST5, // 177 SPR_TST6, // 178 SPR_TST7, // 179 SPR_TST8, // 180 SPR_TST9, // 181 SPR_TST0, // 182 SPR_TELE, // 183 SPR_TSMK, // 184 SPR_FPCH, // 185 SPR_WFAX, // 186 SPR_FAXE, // 187 SPR_WFHM, // 188 SPR_FHMR, // 189 SPR_FSRD, // 190 SPR_FSFX, // 191 SPR_CMCE, // 192 SPR_WCSS, // 193 SPR_CSSF, // 194 SPR_WCFM, // 195 SPR_CFLM, // 196 SPR_CFFX, // 197 SPR_CHLY, // 198 SPR_SPIR, // 199 SPR_MWND, // 200 SPR_WMLG, // 201 SPR_MLNG, // 202 SPR_MLFX, // 203 SPR_MLF2, // 204 SPR_MSTF, // 205 SPR_MSP1, // 206 SPR_MSP2, // 207 SPR_WFR1, // 208 SPR_WFR2, // 209 SPR_WFR3, // 210 SPR_WCH1, // 211 SPR_WCH2, // 212 SPR_WCH3, // 213 SPR_WMS1, // 214 SPR_WMS2, // 215 SPR_WMS3, // 216 SPR_WPIG, // 217 SPR_WMCS, // 218 SPR_CONE, // 219 SPR_SHEX, // 220 SPR_BLOD, // 221 SPR_GIBS, // 222 SPR_PLAY, // 223 SPR_FDTH, // 224 SPR_BSKL, // 225 SPR_ICEC, // 226 SPR_CLER, // 227 SPR_MAGE, // 228 SPR_PIGY, // 229 SPR_CENT, // 230 SPR_CTXD, // 231 SPR_CTFX, // 232 SPR_CTDP, // 233 SPR_DEMN, // 234 SPR_DEMA, // 235 SPR_DEMB, // 236 SPR_DEMC, // 237 SPR_DEMD, // 238 SPR_DEME, // 239 SPR_DMFX, // 240 SPR_DEM2, // 241 SPR_DMBA, // 242 SPR_DMBB, // 243 SPR_DMBC, // 244 SPR_DMBD, // 245 SPR_DMBE, // 246 SPR_D2FX, // 247 SPR_WRTH, // 248 SPR_WRT2, // 249 SPR_WRBL, // 250 SPR_MNTR, // 251 SPR_FX12, // 252 SPR_FX13, // 253 SPR_MNSM, // 254 SPR_SSPT, // 255 SPR_SSDV, // 256 SPR_SSXD, // 257 SPR_SSFX, // 258 SPR_BISH, // 259 SPR_BPFX, // 260 SPR_DRAG, // 261 SPR_DRFX, // 262 SPR_ARM1, // 263 SPR_ARM2, // 264 SPR_ARM3, // 265 SPR_ARM4, // 266 SPR_MAN2, // 267 SPR_MAN3, // 268 SPR_KEY1, // 269 SPR_KEY2, // 270 SPR_KEY3, // 271 SPR_KEY4, // 272 SPR_KEY5, // 273 SPR_KEY6, // 274 SPR_KEY7, // 275 SPR_KEY8, // 276 SPR_KEY9, // 277 SPR_KEYA, // 278 SPR_KEYB, // 279 SPR_ETTN, // 280 SPR_ETTB, // 281 SPR_FDMN, // 282 SPR_FDMB, // 283 SPR_ICEY, // 284 SPR_ICPR, // 285 SPR_ICWS, // 286 SPR_SORC, // 287 SPR_SBMP, // 288 SPR_SBS4, // 289 SPR_SBMB, // 290 SPR_SBS3, // 291 SPR_SBMG, // 292 SPR_SBS1, // 293 SPR_SBS2, // 294 SPR_SBFX, // 295 SPR_RADE, // 296 SPR_WATR, // 297 SPR_KORX, // 298 SPR_ABAT, // 299 NUMSPRITES // 300 } spritetype_e; // States. typedef enum { S_NULL, // 000 S_FREETARGMOBJ, // 001 S_MAPSPOT, // 002 S_FIREBALL1_1, // 003 S_FIREBALL1_2, // 004 S_FIREBALL1_X1, // 005 S_FIREBALL1_X2, // 006 S_FIREBALL1_X3, // 007 S_FIREBALL1_X4, // 008 S_FIREBALL1_X5, // 009 S_FIREBALL1_X6, // 010 S_ARROW_1, // 011 S_ARROW_X1, // 012 S_DART_1, // 013 S_DART_X1, // 014 S_POISONDART_1, // 015 S_POISONDART_X1, // 016 S_RIPPERBALL_1, // 017 S_RIPPERBALL_2, // 018 S_RIPPERBALL_3, // 019 S_RIPPERBALL_X1, // 020 S_RIPPERBALL_X2, // 021 S_RIPPERBALL_X3, // 022 S_RIPPERBALL_X4, // 023 S_RIPPERBALL_X5, // 024 S_RIPPERBALL_X6, // 025 S_RIPPERBALL_X7, // 026 S_RIPPERBALL_X8, // 027 S_RIPPERBALL_X9, // 028 S_RIPPERBALL_X10, // 029 S_PRJ_BLADE1, // 030 S_PRJ_BLADE_X1, // 031 S_ICESHARD1, // 032 S_ICESHARD2, // 033 S_ICESHARD3, // 034 S_FLAME_TSMALL1, // 035 S_FLAME_TSMALL2, // 036 S_FLAME_TSMALL3, // 037 S_FLAME_TSMALL4, // 038 S_FLAME_TSMALL5, // 039 S_FLAME_TSMALL6, // 040 S_FLAME_TLARGE1, // 041 S_FLAME_TLARGE2, // 042 S_FLAME_TLARGE3, // 043 S_FLAME_TLARGE4, // 044 S_FLAME_TLARGE5, // 045 S_FLAME_TLARGE6, // 046 S_FLAME_TLARGE7, // 047 S_FLAME_TLARGE8, // 048 S_FLAME_TLARGE9, // 049 S_FLAME_TLARGE10, // 050 S_FLAME_TLARGE11, // 051 S_FLAME_TLARGE12, // 052 S_FLAME_TLARGE13, // 053 S_FLAME_TLARGE14, // 054 S_FLAME_TLARGE15, // 055 S_FLAME_TLARGE16, // 056 S_FLAME_SDORM1, // 057 S_FLAME_SDORM2, // 058 S_FLAME_SDORM3, // 059 S_FLAME_SMALL1, // 060 S_FLAME_SMALL2, // 061 S_FLAME_SMALL3, // 062 S_FLAME_SMALL4, // 063 S_FLAME_SMALL5, // 064 S_FLAME_SMALL6, // 065 S_FLAME_SMALL7, // 066 S_FLAME_LDORM1, // 067 S_FLAME_LDORM2, // 068 S_FLAME_LDORM3, // 069 S_FLAME_LDORM4, // 070 S_FLAME_LDORM5, // 071 S_FLAME_LARGE1, // 072 S_FLAME_LARGE2, // 073 S_FLAME_LARGE3, // 074 S_FLAME_LARGE4, // 075 S_FLAME_LARGE5, // 076 S_FLAME_LARGE6, // 077 S_FLAME_LARGE7, // 078 S_FLAME_LARGE8, // 079 S_FLAME_LARGE9, // 080 S_FLAME_LARGE10, // 081 S_FLAME_LARGE11, // 082 S_FLAME_LARGE12, // 083 S_FLAME_LARGE13, // 084 S_FLAME_LARGE14, // 085 S_FLAME_LARGE15, // 086 S_FLAME_LARGE16, // 087 S_FLAME_LARGE17, // 088 S_FLAME_LARGE18, // 089 S_ITEM_PTN1_1, // 090 S_ITEM_PTN1_2, // 091 S_ITEM_PTN1_3, // 092 S_HIDESPECIAL1, // 093 S_HIDESPECIAL2, // 094 S_HIDESPECIAL3, // 095 S_HIDESPECIAL4, // 096 S_HIDESPECIAL5, // 097 S_HIDESPECIAL6, // 098 S_HIDESPECIAL7, // 099 S_HIDESPECIAL8, // 100 S_HIDESPECIAL9, // 101 S_HIDESPECIAL10, // 102 S_HIDESPECIAL11, // 103 S_DORMANTARTI1_1, // 104 S_DORMANTARTI1_2, // 105 S_DORMANTARTI1_3, // 106 S_DORMANTARTI1_4, // 107 S_DORMANTARTI1_5, // 108 S_DORMANTARTI1_6, // 109 S_DORMANTARTI1_7, // 110 S_DORMANTARTI1_8, // 111 S_DORMANTARTI1_9, // 112 S_DORMANTARTI1_10, // 113 S_DORMANTARTI1_11, // 114 S_DORMANTARTI1_12, // 115 S_DORMANTARTI1_13, // 116 S_DORMANTARTI1_14, // 117 S_DORMANTARTI1_15, // 118 S_DORMANTARTI1_16, // 119 S_DORMANTARTI1_17, // 120 S_DORMANTARTI1_18, // 121 S_DORMANTARTI1_19, // 122 S_DORMANTARTI1_20, // 123 S_DORMANTARTI1_21, // 124 S_DORMANTARTI2_1, // 125 S_DORMANTARTI2_2, // 126 S_DORMANTARTI2_3, // 127 S_DORMANTARTI2_4, // 128 S_DORMANTARTI2_5, // 129 S_DORMANTARTI2_6, // 130 S_DORMANTARTI2_7, // 131 S_DORMANTARTI2_8, // 132 S_DORMANTARTI2_9, // 133 S_DORMANTARTI2_10, // 134 S_DORMANTARTI2_11, // 135 S_DORMANTARTI2_12, // 136 S_DORMANTARTI2_13, // 137 S_DORMANTARTI2_14, // 138 S_DORMANTARTI2_15, // 139 S_DORMANTARTI2_16, // 140 S_DORMANTARTI2_17, // 141 S_DORMANTARTI2_18, // 142 S_DORMANTARTI2_19, // 143 S_DORMANTARTI2_20, // 144 S_DORMANTARTI2_21, // 145 S_DORMANTARTI3_1, // 146 S_DORMANTARTI3_2, // 147 S_DORMANTARTI3_3, // 148 S_DORMANTARTI3_4, // 149 S_DORMANTARTI3_5, // 150 S_DORMANTARTI3_6, // 151 S_DORMANTARTI3_7, // 152 S_DORMANTARTI3_8, // 153 S_DORMANTARTI3_9, // 154 S_DORMANTARTI3_10, // 155 S_DORMANTARTI3_11, // 156 S_DORMANTARTI3_12, // 157 S_DORMANTARTI3_13, // 158 S_DORMANTARTI3_14, // 159 S_DORMANTARTI3_15, // 160 S_DORMANTARTI3_16, // 161 S_DORMANTARTI3_17, // 162 S_DORMANTARTI3_18, // 163 S_DORMANTARTI3_19, // 164 S_DORMANTARTI3_20, // 165 S_DORMANTARTI3_21, // 166 S_DEADARTI1, // 167 S_DEADARTI2, // 168 S_DEADARTI3, // 169 S_DEADARTI4, // 170 S_DEADARTI5, // 171 S_DEADARTI6, // 172 S_DEADARTI7, // 173 S_DEADARTI8, // 174 S_DEADARTI9, // 175 S_DEADARTI10, // 176 S_ARTI_PTN2_1, // 177 S_ARTI_PTN2_2, // 178 S_ARTI_PTN2_3, // 179 S_ARTI_SOAR1, // 180 S_ARTI_SOAR2, // 181 S_ARTI_SOAR3, // 182 S_ARTI_SOAR4, // 183 S_ARTI_INVU1, // 184 S_ARTI_INVU2, // 185 S_ARTI_INVU3, // 186 S_ARTI_INVU4, // 187 S_ARTI_SUMMON, // 188 S_SUMMON_FX1_1, // 189 S_SUMMON_FX2_1, // 190 S_SUMMON_FX2_2, // 191 S_SUMMON_FX2_3, // 192 S_THRUSTINIT2_1, // 193 S_THRUSTINIT2_2, // 194 S_BTHRUSTINIT2_1, // 195 S_BTHRUSTINIT2_2, // 196 S_THRUSTINIT1_1, // 197 S_THRUSTINIT1_2, // 198 S_BTHRUSTINIT1_1, // 199 S_BTHRUSTINIT1_2, // 200 S_THRUSTRAISE1, // 201 S_THRUSTRAISE2, // 202 S_THRUSTRAISE3, // 203 S_THRUSTRAISE4, // 204 S_BTHRUSTRAISE1, // 205 S_BTHRUSTRAISE2, // 206 S_BTHRUSTRAISE3, // 207 S_BTHRUSTRAISE4, // 208 S_THRUSTIMPALE, // 209 S_BTHRUSTIMPALE, // 210 S_THRUSTRAISE, // 211 S_BTHRUSTRAISE, // 212 S_THRUSTBLOCK, // 213 S_BTHRUSTBLOCK, // 214 S_THRUSTLOWER, // 215 S_BTHRUSTLOWER, // 216 S_THRUSTSTAY, // 217 S_BTHRUSTSTAY, // 218 S_ARTI_TELOTHER1, // 219 S_ARTI_TELOTHER2, // 220 S_ARTI_TELOTHER3, // 221 S_ARTI_TELOTHER4, // 222 S_TELO_FX1, // 223 S_TELO_FX2, // 224 S_TELO_FX3, // 225 S_TELO_FX4, // 226 S_TELO_FX5, // 227 S_TELO_FX6, // 228 S_TELO_FX7, // 229 S_TELO_FX8, // 230 S_TELO_FX9, // 231 S_TELO_FX2_1, // 232 S_TELO_FX2_2, // 233 S_TELO_FX2_3, // 234 S_TELO_FX2_4, // 235 S_TELO_FX2_5, // 236 S_TELO_FX2_6, // 237 S_TELO_FX3_1, // 238 S_TELO_FX3_2, // 239 S_TELO_FX3_3, // 240 S_TELO_FX3_4, // 241 S_TELO_FX3_5, // 242 S_TELO_FX3_6, // 243 S_TELO_FX4_1, // 244 S_TELO_FX4_2, // 245 S_TELO_FX4_3, // 246 S_TELO_FX4_4, // 247 S_TELO_FX4_5, // 248 S_TELO_FX4_6, // 249 S_TELO_FX5_1, // 250 S_TELO_FX5_2, // 251 S_TELO_FX5_3, // 252 S_TELO_FX5_4, // 253 S_TELO_FX5_5, // 254 S_TELO_FX5_6, // 255 S_DIRT1_1, // 256 S_DIRT1_D, // 257 S_DIRT2_1, // 258 S_DIRT2_D, // 259 S_DIRT3_1, // 260 S_DIRT3_D, // 261 S_DIRT4_1, // 262 S_DIRT4_D, // 263 S_DIRT5_1, // 264 S_DIRT5_D, // 265 S_DIRT6_1, // 266 S_DIRT6_D, // 267 S_DIRTCLUMP1, // 268 S_ROCK1_1, // 269 S_ROCK1_D, // 270 S_ROCK2_1, // 271 S_ROCK2_D, // 272 S_ROCK3_1, // 273 S_ROCK3_D, // 274 S_SPAWNFOG1, // 275 S_FOGPATCHS1, // 276 S_FOGPATCHS2, // 277 S_FOGPATCHS3, // 278 S_FOGPATCHS4, // 279 S_FOGPATCHS5, // 280 S_FOGPATCHS0, // 281 S_FOGPATCHM1, // 282 S_FOGPATCHM2, // 283 S_FOGPATCHM3, // 284 S_FOGPATCHM4, // 285 S_FOGPATCHM5, // 286 S_FOGPATCHM0, // 287 S_FOGPATCHMA, // 288 S_FOGPATCHMB, // 289 S_FOGPATCHMC, // 290 S_FOGPATCHMD, // 291 S_FOGPATCHL1, // 292 S_FOGPATCHL2, // 293 S_FOGPATCHL3, // 294 S_FOGPATCHL4, // 295 S_FOGPATCHL5, // 296 S_FOGPATCHL0, // 297 S_FOGPATCHLA, // 298 S_FOGPATCHLB, // 299 S_FOGPATCHLC, // 300 S_FOGPATCHLD, // 301 S_QUAKE_ACTIVE1, // 302 S_QUAKE_ACTIVE2, // 303 S_QUAKE_ACTIVE3, // 304 S_QUAKE_ACTIVE4, // 305 S_QUAKE_ACTIVE5, // 306 S_QUAKE_ACTIVE6, // 307 S_QUAKE_ACTIVE7, // 308 S_QUAKE_ACTIVE8, // 309 S_QUAKE_ACTIVE9, // 310 S_QUAKE_ACTIVE0, // 311 S_QUAKE_ACTIVEA, // 312 S_QUAKE_ACTIVEB, // 313 S_QUAKE_ACTIVEC, // 314 S_QUAKE_ACTIVED, // 315 S_QUAKE_ACTIVEE, // 316 S_QUAKE_ACTIVEF, // 317 S_QUAKE_ACTIVEG, // 318 S_QUAKE_ACTIVEH, // 319 S_QUAKE_ACTIVEI, // 320 S_QUAKE_ACTIVEJ, // 321 S_QUAKE_ACTIVEK, // 322 S_QUAKE_ACTIVEL, // 323 S_QUAKE_ACTIVEM, // 324 S_QUAKE_ACTIVEN, // 325 S_QUAKE_ACTIVEO, // 326 S_QUAKE_ACTIVEP, // 327 S_QUAKE_ACTIVEQ, // 328 S_QUAKE_ACTIVER, // 329 S_QUAKE_ACTIVES, // 330 S_QUAKE_ACTIVET, // 331 S_QUAKE_ACTIVEU, // 332 S_QUAKE_ACTIVEV, // 333 S_QUAKE_ACTIVEW, // 334 S_QUAKE_ACTIVEX, // 335 S_QUAKE_ACTIVEY, // 336 S_QUAKE_ACTIVEZ, // 337 S_QUAKE_ACT1, // 338 S_QUAKE_ACT2, // 339 S_QUAKE_ACT3, // 340 S_QUAKE_ACT4, // 341 S_QUAKE_ACT5, // 342 S_QUAKE_ACT6, // 343 S_QUAKE_ACT7, // 344 S_QUAKE_ACT8, // 345 S_QUAKE_ACT9, // 346 S_QUAKE_ACT0, // 347 S_SGSHARD1_1, // 348 S_SGSHARD1_2, // 349 S_SGSHARD1_3, // 350 S_SGSHARD1_4, // 351 S_SGSHARD1_5, // 352 S_SGSHARD1_D, // 353 S_SGSHARD2_1, // 354 S_SGSHARD2_2, // 355 S_SGSHARD2_3, // 356 S_SGSHARD2_4, // 357 S_SGSHARD2_5, // 358 S_SGSHARD2_D, // 359 S_SGSHARD3_1, // 360 S_SGSHARD3_2, // 361 S_SGSHARD3_3, // 362 S_SGSHARD3_4, // 363 S_SGSHARD3_5, // 364 S_SGSHARD3_D, // 365 S_SGSHARD4_1, // 366 S_SGSHARD4_2, // 367 S_SGSHARD4_3, // 368 S_SGSHARD4_4, // 369 S_SGSHARD4_5, // 370 S_SGSHARD4_D, // 371 S_SGSHARD5_1, // 372 S_SGSHARD5_2, // 373 S_SGSHARD5_3, // 374 S_SGSHARD5_4, // 375 S_SGSHARD5_5, // 376 S_SGSHARD5_D, // 377 S_SGSHARD6_1, // 378 S_SGSHARD6_D, // 379 S_SGSHARD7_1, // 380 S_SGSHARD7_D, // 381 S_SGSHARD8_1, // 382 S_SGSHARD8_D, // 383 S_SGSHARD9_1, // 384 S_SGSHARD9_D, // 385 S_SGSHARD0_1, // 386 S_SGSHARD0_D, // 387 S_ARTI_EGGC1, // 388 S_ARTI_EGGC2, // 389 S_ARTI_EGGC3, // 390 S_ARTI_EGGC4, // 391 S_ARTI_EGGC5, // 392 S_ARTI_EGGC6, // 393 S_ARTI_EGGC7, // 394 S_ARTI_EGGC8, // 395 S_EGGFX1, // 396 S_EGGFX2, // 397 S_EGGFX3, // 398 S_EGGFX4, // 399 S_EGGFX5, // 400 S_EGGFXI1_1, // 401 S_EGGFXI1_2, // 402 S_EGGFXI1_3, // 403 S_EGGFXI1_4, // 404 S_ARTI_SPHL1, // 405 S_ZWINGEDSTATUENOSKULL, // 406 S_ZWINGEDSTATUENOSKULL2, // 407 S_ZGEMPEDESTAL1, // 408 S_ZGEMPEDESTAL2, // 409 S_ARTIPUZZSKULL, // 410 S_ARTIPUZZGEMBIG, // 411 S_ARTIPUZZGEMRED, // 412 S_ARTIPUZZGEMGREEN1, // 413 S_ARTIPUZZGEMGREEN2, // 414 S_ARTIPUZZGEMBLUE1, // 415 S_ARTIPUZZGEMBLUE2, // 416 S_ARTIPUZZBOOK1, // 417 S_ARTIPUZZBOOK2, // 418 S_ARTIPUZZSKULL2, // 419 S_ARTIPUZZFWEAPON, // 420 S_ARTIPUZZCWEAPON, // 421 S_ARTIPUZZMWEAPON, // 422 S_ARTIPUZZGEAR_1, // 423 S_ARTIPUZZGEAR_2, // 424 S_ARTIPUZZGEAR_3, // 425 S_ARTIPUZZGEAR_4, // 426 S_ARTIPUZZGEAR_5, // 427 S_ARTIPUZZGEAR_6, // 428 S_ARTIPUZZGEAR_7, // 429 S_ARTIPUZZGEAR_8, // 430 S_ARTIPUZZGEAR2_1, // 431 S_ARTIPUZZGEAR2_2, // 432 S_ARTIPUZZGEAR2_3, // 433 S_ARTIPUZZGEAR2_4, // 434 S_ARTIPUZZGEAR2_5, // 435 S_ARTIPUZZGEAR2_6, // 436 S_ARTIPUZZGEAR2_7, // 437 S_ARTIPUZZGEAR2_8, // 438 S_ARTIPUZZGEAR3_1, // 439 S_ARTIPUZZGEAR3_2, // 440 S_ARTIPUZZGEAR3_3, // 441 S_ARTIPUZZGEAR3_4, // 442 S_ARTIPUZZGEAR3_5, // 443 S_ARTIPUZZGEAR3_6, // 444 S_ARTIPUZZGEAR3_7, // 445 S_ARTIPUZZGEAR3_8, // 446 S_ARTIPUZZGEAR4_1, // 447 S_ARTIPUZZGEAR4_2, // 448 S_ARTIPUZZGEAR4_3, // 449 S_ARTIPUZZGEAR4_4, // 450 S_ARTIPUZZGEAR4_5, // 451 S_ARTIPUZZGEAR4_6, // 452 S_ARTIPUZZGEAR4_7, // 453 S_ARTIPUZZGEAR4_8, // 454 S_ARTI_TRCH1, // 455 S_ARTI_TRCH2, // 456 S_ARTI_TRCH3, // 457 S_FIREBOMB1, // 458 S_FIREBOMB2, // 459 S_FIREBOMB3, // 460 S_FIREBOMB4, // 461 S_FIREBOMB5, // 462 S_FIREBOMB6, // 463 S_FIREBOMB7, // 464 S_FIREBOMB8, // 465 S_FIREBOMB9, // 466 S_FIREBOMB10, // 467 S_FIREBOMB11, // 468 S_ARTI_ATLP1, // 469 S_ARTI_ATLP2, // 470 S_ARTI_ATLP3, // 471 S_ARTI_ATLP4, // 472 S_ARTI_PSBG1, // 473 S_POISONBAG1, // 474 S_POISONBAG2, // 475 S_POISONBAG3, // 476 S_POISONBAG4, // 477 S_POISONCLOUD1, // 478 S_POISONCLOUD2, // 479 S_POISONCLOUD3, // 480 S_POISONCLOUD4, // 481 S_POISONCLOUD5, // 482 S_POISONCLOUD6, // 483 S_POISONCLOUD7, // 484 S_POISONCLOUD8, // 485 S_POISONCLOUD9, // 486 S_POISONCLOUD10, // 487 S_POISONCLOUD11, // 488 S_POISONCLOUD12, // 489 S_POISONCLOUD13, // 490 S_POISONCLOUD14, // 491 S_POISONCLOUD15, // 492 S_POISONCLOUD16, // 493 S_POISONCLOUD17, // 494 S_POISONCLOUD18, // 495 S_POISONCLOUD_X1, // 496 S_POISONCLOUD_X2, // 497 S_POISONCLOUD_X3, // 498 S_POISONCLOUD_X4, // 499 S_THROWINGBOMB1, // 500 S_THROWINGBOMB2, // 501 S_THROWINGBOMB3, // 502 S_THROWINGBOMB4, // 503 S_THROWINGBOMB5, // 504 S_THROWINGBOMB6, // 505 S_THROWINGBOMB7, // 506 S_THROWINGBOMB8, // 507 S_THROWINGBOMB9, // 508 S_THROWINGBOMB10, // 509 S_THROWINGBOMB11, // 510 S_THROWINGBOMB12, // 511 S_THROWINGBOMB_X1, // 512 S_THROWINGBOMB_X2, // 513 S_THROWINGBOMB_X3, // 514 S_THROWINGBOMB_X4, // 515 S_THROWINGBOMB_X5, // 516 S_THROWINGBOMB_X6, // 517 S_THROWINGBOMB_X7, // 518 S_THROWINGBOMB_X8, // 519 S_ARTI_BOOTS1, // 520 S_ARTI_BOOTS2, // 521 S_ARTI_BOOTS3, // 522 S_ARTI_BOOTS4, // 523 S_ARTI_BOOTS5, // 524 S_ARTI_BOOTS6, // 525 S_ARTI_BOOTS7, // 526 S_ARTI_BOOTS8, // 527 S_ARTI_MANA, // 528 S_ARTI_ARMOR1, // 529 S_ARTI_ARMOR2, // 530 S_ARTI_ARMOR3, // 531 S_ARTI_ARMOR4, // 532 S_ARTI_ARMOR5, // 533 S_ARTI_ARMOR6, // 534 S_ARTI_ARMOR7, // 535 S_ARTI_ARMOR8, // 536 S_ARTI_BLAST1, // 537 S_ARTI_BLAST2, // 538 S_ARTI_BLAST3, // 539 S_ARTI_BLAST4, // 540 S_ARTI_BLAST5, // 541 S_ARTI_BLAST6, // 542 S_ARTI_BLAST7, // 543 S_ARTI_BLAST8, // 544 S_ARTI_HEALRAD1, // 545 S_ARTI_HEALRAD2, // 546 S_ARTI_HEALRAD3, // 547 S_ARTI_HEALRAD4, // 548 S_ARTI_HEALRAD5, // 549 S_ARTI_HEALRAD6, // 550 S_ARTI_HEALRAD7, // 551 S_ARTI_HEALRAD8, // 552 S_ARTI_HEALRAD9, // 553 S_ARTI_HEALRAD0, // 554 S_ARTI_HEALRADA, // 555 S_ARTI_HEALRADB, // 556 S_ARTI_HEALRADC, // 557 S_ARTI_HEALRADD, // 558 S_ARTI_HEALRADE, // 559 S_ARTI_HEALRADF, // 560 S_SPLASH1, // 561 S_SPLASH2, // 562 S_SPLASH3, // 563 S_SPLASH4, // 564 S_SPLASHX, // 565 S_SPLASHBASE1, // 566 S_SPLASHBASE2, // 567 S_SPLASHBASE3, // 568 S_SPLASHBASE4, // 569 S_SPLASHBASE5, // 570 S_SPLASHBASE6, // 571 S_SPLASHBASE7, // 572 S_LAVASPLASH1, // 573 S_LAVASPLASH2, // 574 S_LAVASPLASH3, // 575 S_LAVASPLASH4, // 576 S_LAVASPLASH5, // 577 S_LAVASPLASH6, // 578 S_LAVASMOKE1, // 579 S_LAVASMOKE2, // 580 S_LAVASMOKE3, // 581 S_LAVASMOKE4, // 582 S_LAVASMOKE5, // 583 S_SLUDGECHUNK1, // 584 S_SLUDGECHUNK2, // 585 S_SLUDGECHUNK3, // 586 S_SLUDGECHUNK4, // 587 S_SLUDGECHUNKX, // 588 S_SLUDGESPLASH1, // 589 S_SLUDGESPLASH2, // 590 S_SLUDGESPLASH3, // 591 S_SLUDGESPLASH4, // 592 S_ZWINGEDSTATUE1, // 593 S_ZROCK1_1, // 594 S_ZROCK2_1, // 595 S_ZROCK3_1, // 596 S_ZROCK4_1, // 597 S_ZCHANDELIER1, // 598 S_ZCHANDELIER2, // 599 S_ZCHANDELIER3, // 600 S_ZCHANDELIER_U, // 601 S_ZTREEDEAD1, // 602 S_ZTREE, // 603 S_ZTREEDESTRUCTIBLE1, // 604 S_ZTREEDES_D1, // 605 S_ZTREEDES_D2, // 606 S_ZTREEDES_D3, // 607 S_ZTREEDES_D4, // 608 S_ZTREEDES_D5, // 609 S_ZTREEDES_D6, // 610 S_ZTREEDES_X1, // 611 S_ZTREEDES_X2, // 612 S_ZTREEDES_X3, // 613 S_ZTREEDES_X4, // 614 S_ZTREEDES_X5, // 615 S_ZTREEDES_X6, // 616 S_ZTREEDES_X7, // 617 S_ZTREEDES_X8, // 618 S_ZTREEDES_X9, // 619 S_ZTREEDES_X10, // 620 S_ZTREESWAMP182_1, // 621 S_ZTREESWAMP172_1, // 622 S_ZSTUMPBURNED1, // 623 S_ZSTUMPBARE1, // 624 S_ZSTUMPSWAMP1_1, // 625 S_ZSTUMPSWAMP2_1, // 626 S_ZSHROOMLARGE1_1, // 627 S_ZSHROOMLARGE2_1, // 628 S_ZSHROOMLARGE3_1, // 629 S_ZSHROOMSMALL1_1, // 630 S_ZSHROOMSMALL2_1, // 631 S_ZSHROOMSMALL3_1, // 632 S_ZSHROOMSMALL4_1, // 633 S_ZSHROOMSMALL5_1, // 634 S_ZSTALAGMITEPILLAR1, // 635 S_ZSTALAGMITELARGE1, // 636 S_ZSTALAGMITEMEDIUM1, // 637 S_ZSTALAGMITESMALL1, // 638 S_ZSTALACTITELARGE1, // 639 S_ZSTALACTITEMEDIUM1, // 640 S_ZSTALACTITESMALL1, // 641 S_ZMOSSCEILING1_1, // 642 S_ZMOSSCEILING2_1, // 643 S_ZSWAMPVINE1, // 644 S_ZCORPSEKABOB1, // 645 S_ZCORPSESLEEPING1, // 646 S_ZTOMBSTONERIP1, // 647 S_ZTOMBSTONESHANE1, // 648 S_ZTOMBSTONEBIGCROSS1, // 649 S_ZTOMBSTONEBRIANR1, // 650 S_ZTOMBSTONECROSSCIRCLE1, // 651 S_ZTOMBSTONESMALLCROSS1, // 652 S_ZTOMBSTONEBRIANP1, // 653 S_CORPSEHANGING_1, // 654 S_ZSTATUEGARGOYLEGREENTALL_1, // 655 S_ZSTATUEGARGOYLEBLUETALL_1, // 656 S_ZSTATUEGARGOYLEGREENSHORT_1, // 657 S_ZSTATUEGARGOYLEBLUESHORT_1, // 658 S_ZSTATUEGARGOYLESTRIPETALL_1, // 659 S_ZSTATUEGARGOYLEDARKREDTALL_1, // 660 S_ZSTATUEGARGOYLEREDTALL_1, // 661 S_ZSTATUEGARGOYLETANTALL_1, // 662 S_ZSTATUEGARGOYLERUSTTALL_1, // 663 S_ZSTATUEGARGOYLEDARKREDSHORT_1, // 664 S_ZSTATUEGARGOYLEREDSHORT_1, // 665 S_ZSTATUEGARGOYLETANSHORT_1, // 666 S_ZSTATUEGARGOYLERUSTSHORT_1, // 667 S_ZBANNERTATTERED_1, // 668 S_ZTREELARGE1, // 669 S_ZTREELARGE2, // 670 S_ZTREEGNARLED1, // 671 S_ZTREEGNARLED2, // 672 S_ZLOG, // 673 S_ZSTALACTITEICELARGE, // 674 S_ZSTALACTITEICEMEDIUM, // 675 S_ZSTALACTITEICESMALL, // 676 S_ZSTALACTITEICETINY, // 677 S_ZSTALAGMITEICELARGE, // 678 S_ZSTALAGMITEICEMEDIUM, // 679 S_ZSTALAGMITEICESMALL, // 680 S_ZSTALAGMITEICETINY, // 681 S_ZROCKBROWN1, // 682 S_ZROCKBROWN2, // 683 S_ZROCKBLACK, // 684 S_ZRUBBLE1, // 685 S_ZRUBBLE2, // 686 S_ZRUBBLE3, // 687 S_ZVASEPILLAR, // 688 S_ZPOTTERY1, // 689 S_ZPOTTERY2, // 690 S_ZPOTTERY3, // 691 S_ZPOTTERY_EXPLODE, // 692 S_POTTERYBIT_1, // 693 S_POTTERYBIT_2, // 694 S_POTTERYBIT_3, // 695 S_POTTERYBIT_4, // 696 S_POTTERYBIT_5, // 697 S_POTTERYBIT_EX0, // 698 S_POTTERYBIT_EX1, // 699 S_POTTERYBIT_EX1_2, // 700 S_POTTERYBIT_EX2, // 701 S_POTTERYBIT_EX2_2, // 702 S_POTTERYBIT_EX3, // 703 S_POTTERYBIT_EX3_2, // 704 S_POTTERYBIT_EX4, // 705 S_POTTERYBIT_EX4_2, // 706 S_POTTERYBIT_EX5, // 707 S_POTTERYBIT_EX5_2, // 708 S_ZCORPSELYNCHED1, // 709 S_ZCORPSELYNCHED2, // 710 S_ZCORPSESITTING, // 711 S_ZCORPSESITTING_X, // 712 S_CORPSEBIT_1, // 713 S_CORPSEBIT_2, // 714 S_CORPSEBIT_3, // 715 S_CORPSEBIT_4, // 716 S_CORPSEBLOODDRIP, // 717 S_CORPSEBLOODDRIP_X1, // 718 S_CORPSEBLOODDRIP_X2, // 719 S_CORPSEBLOODDRIP_X3, // 720 S_CORPSEBLOODDRIP_X4, // 721 S_BLOODPOOL, // 722 S_ZCANDLE1, // 723 S_ZCANDLE2, // 724 S_ZCANDLE3, // 725 S_ZLEAFSPAWNER, // 726 S_LEAF1_1, // 727 S_LEAF1_2, // 728 S_LEAF1_3, // 729 S_LEAF1_4, // 730 S_LEAF1_5, // 731 S_LEAF1_6, // 732 S_LEAF1_7, // 733 S_LEAF1_8, // 734 S_LEAF1_9, // 735 S_LEAF1_10, // 736 S_LEAF1_11, // 737 S_LEAF1_12, // 738 S_LEAF1_13, // 739 S_LEAF1_14, // 740 S_LEAF1_15, // 741 S_LEAF1_16, // 742 S_LEAF1_17, // 743 S_LEAF1_18, // 744 S_LEAF_X1, // 745 S_LEAF2_1, // 746 S_LEAF2_2, // 747 S_LEAF2_3, // 748 S_LEAF2_4, // 749 S_LEAF2_5, // 750 S_LEAF2_6, // 751 S_LEAF2_7, // 752 S_LEAF2_8, // 753 S_LEAF2_9, // 754 S_LEAF2_10, // 755 S_LEAF2_11, // 756 S_LEAF2_12, // 757 S_LEAF2_13, // 758 S_LEAF2_14, // 759 S_LEAF2_15, // 760 S_LEAF2_16, // 761 S_LEAF2_17, // 762 S_LEAF2_18, // 763 S_ZTWINEDTORCH_1, // 764 S_ZTWINEDTORCH_2, // 765 S_ZTWINEDTORCH_3, // 766 S_ZTWINEDTORCH_4, // 767 S_ZTWINEDTORCH_5, // 768 S_ZTWINEDTORCH_6, // 769 S_ZTWINEDTORCH_7, // 770 S_ZTWINEDTORCH_8, // 771 S_ZTWINEDTORCH_UNLIT, // 772 S_BRIDGE1, // 773 S_BRIDGE2, // 774 S_BRIDGE3, // 775 S_FREE_BRIDGE1, // 776 S_FREE_BRIDGE2, // 777 S_BBALL1, // 778 S_BBALL2, // 779 S_ZWALLTORCH1, // 780 S_ZWALLTORCH2, // 781 S_ZWALLTORCH3, // 782 S_ZWALLTORCH4, // 783 S_ZWALLTORCH5, // 784 S_ZWALLTORCH6, // 785 S_ZWALLTORCH7, // 786 S_ZWALLTORCH8, // 787 S_ZWALLTORCH_U, // 788 S_ZBARREL1, // 789 S_ZSHRUB1, // 790 S_ZSHRUB1_DIE, // 791 S_ZSHRUB1_X1, // 792 S_ZSHRUB1_X2, // 793 S_ZSHRUB1_X3, // 794 S_ZSHRUB2, // 795 S_ZSHRUB2_DIE, // 796 S_ZSHRUB2_X1, // 797 S_ZSHRUB2_X2, // 798 S_ZSHRUB2_X3, // 799 S_ZSHRUB2_X4, // 800 S_ZBUCKET1, // 801 S_ZPOISONSHROOM1, // 802 S_ZPOISONSHROOM_P1, // 803 S_ZPOISONSHROOM_P2, // 804 S_ZPOISONSHROOM_X1, // 805 S_ZPOISONSHROOM_X2, // 806 S_ZPOISONSHROOM_X3, // 807 S_ZPOISONSHROOM_X4, // 808 S_ZFIREBULL1, // 809 S_ZFIREBULL2, // 810 S_ZFIREBULL3, // 811 S_ZFIREBULL4, // 812 S_ZFIREBULL5, // 813 S_ZFIREBULL6, // 814 S_ZFIREBULL7, // 815 S_ZFIREBULL_DEATH, // 816 S_ZFIREBULL_DEATH2, // 817 S_ZFIREBULL_U, // 818 S_ZFIREBULL_BIRTH, // 819 S_ZFIREBULL_BIRTH2, // 820 S_ZFIRETHING1, // 821 S_ZFIRETHING2, // 822 S_ZFIRETHING3, // 823 S_ZFIRETHING4, // 824 S_ZFIRETHING5, // 825 S_ZFIRETHING6, // 826 S_ZFIRETHING7, // 827 S_ZFIRETHING8, // 828 S_ZFIRETHING9, // 829 S_ZBRASSTORCH1, // 830 S_ZBRASSTORCH2, // 831 S_ZBRASSTORCH3, // 832 S_ZBRASSTORCH4, // 833 S_ZBRASSTORCH5, // 834 S_ZBRASSTORCH6, // 835 S_ZBRASSTORCH7, // 836 S_ZBRASSTORCH8, // 837 S_ZBRASSTORCH9, // 838 S_ZBRASSTORCH10, // 839 S_ZBRASSTORCH11, // 840 S_ZBRASSTORCH12, // 841 S_ZBRASSTORCH13, // 842 S_ZSUITOFARMOR, // 843 S_ZSUITOFARMOR_X1, // 844 S_ZARMORCHUNK1, // 845 S_ZARMORCHUNK2, // 846 S_ZARMORCHUNK3, // 847 S_ZARMORCHUNK4, // 848 S_ZARMORCHUNK5, // 849 S_ZARMORCHUNK6, // 850 S_ZARMORCHUNK7, // 851 S_ZARMORCHUNK8, // 852 S_ZARMORCHUNK9, // 853 S_ZARMORCHUNK10, // 854 S_ZBELL, // 855 S_ZBELL_X1, // 856 S_ZBELL_X2, // 857 S_ZBELL_X3, // 858 S_ZBELL_X4, // 859 S_ZBELL_X5, // 860 S_ZBELL_X6, // 861 S_ZBELL_X7, // 862 S_ZBELL_X8, // 863 S_ZBELL_X9, // 864 S_ZBELL_X10, // 865 S_ZBELL_X11, // 866 S_ZBELL_X12, // 867 S_ZBELL_X13, // 868 S_ZBELL_X14, // 869 S_ZBELL_X15, // 870 S_ZBELL_X16, // 871 S_ZBELL_X17, // 872 S_ZBELL_X18, // 873 S_ZBELL_X19, // 874 S_ZBELL_X20, // 875 S_ZBELL_X21, // 876 S_ZBELL_X22, // 877 S_ZBELL_X23, // 878 S_ZBELL_X24, // 879 S_ZBELL_X25, // 880 S_ZBELL_X26, // 881 S_ZBELL_X27, // 882 S_ZBELL_X28, // 883 S_ZBELL_X29, // 884 S_ZBELL_X30, // 885 S_ZBELL_X31, // 886 S_ZBELL_X32, // 887 S_ZBELL_X33, // 888 S_ZBELL_X34, // 889 S_ZBELL_X35, // 890 S_ZBELL_X36, // 891 S_ZBELL_X37, // 892 S_ZBELL_X38, // 893 S_ZBELL_X39, // 894 S_ZBELL_X40, // 895 S_ZBELL_X41, // 896 S_ZBELL_X42, // 897 S_ZBELL_X43, // 898 S_ZBELL_X44, // 899 S_ZBELL_X45, // 900 S_ZBELL_X46, // 901 S_ZBELL_X47, // 902 S_ZBLUE_CANDLE1, // 903 S_ZBLUE_CANDLE2, // 904 S_ZBLUE_CANDLE3, // 905 S_ZBLUE_CANDLE4, // 906 S_ZBLUE_CANDLE5, // 907 S_ZIRON_MAIDEN, // 908 S_ZXMAS_TREE, // 909 S_ZXMAS_TREE_DIE, // 910 S_ZXMAS_TREE_X1, // 911 S_ZXMAS_TREE_X2, // 912 S_ZXMAS_TREE_X3, // 913 S_ZXMAS_TREE_X4, // 914 S_ZXMAS_TREE_X5, // 915 S_ZXMAS_TREE_X6, // 916 S_ZXMAS_TREE_X7, // 917 S_ZXMAS_TREE_X8, // 918 S_ZXMAS_TREE_X9, // 919 S_ZXMAS_TREE_X10, // 920 S_ZCAULDRON1, // 921 S_ZCAULDRON2, // 922 S_ZCAULDRON3, // 923 S_ZCAULDRON4, // 924 S_ZCAULDRON5, // 925 S_ZCAULDRON6, // 926 S_ZCAULDRON7, // 927 S_ZCAULDRON_U, // 928 S_ZCHAINBIT32, // 929 S_ZCHAINBIT64, // 930 S_ZCHAINEND_HEART, // 931 S_ZCHAINEND_HOOK1, // 932 S_ZCHAINEND_HOOK2, // 933 S_ZCHAINEND_SPIKE, // 934 S_ZCHAINEND_SKULL, // 935 S_TABLE_SHIT1, // 936 S_TABLE_SHIT2, // 937 S_TABLE_SHIT3, // 938 S_TABLE_SHIT4, // 939 S_TABLE_SHIT5, // 940 S_TABLE_SHIT6, // 941 S_TABLE_SHIT7, // 942 S_TABLE_SHIT8, // 943 S_TABLE_SHIT9, // 944 S_TABLE_SHIT10, // 945 S_TFOG1, // 946 S_TFOG2, // 947 S_TFOG3, // 948 S_TFOG4, // 949 S_TFOG5, // 950 S_TFOG6, // 951 S_TFOG7, // 952 S_TFOG8, // 953 S_TFOG9, // 954 S_TFOG10, // 955 S_TFOG11, // 956 S_TFOG12, // 957 S_TFOG13, // 958 S_TELESMOKE1, // 959 S_TELESMOKE2, // 960 S_TELESMOKE3, // 961 S_TELESMOKE4, // 962 S_TELESMOKE5, // 963 S_TELESMOKE6, // 964 S_TELESMOKE7, // 965 S_TELESMOKE8, // 966 S_TELESMOKE9, // 967 S_TELESMOKE10, // 968 S_TELESMOKE11, // 969 S_TELESMOKE12, // 970 S_TELESMOKE13, // 971 S_TELESMOKE14, // 972 S_TELESMOKE15, // 973 S_TELESMOKE16, // 974 S_TELESMOKE17, // 975 S_TELESMOKE18, // 976 S_TELESMOKE19, // 977 S_TELESMOKE20, // 978 S_TELESMOKE21, // 979 S_TELESMOKE22, // 980 S_TELESMOKE23, // 981 S_TELESMOKE24, // 982 S_TELESMOKE25, // 983 S_TELESMOKE26, // 984 S_LIGHTDONE, // 985 S_PUNCHREADY, // 986 S_PUNCHDOWN, // 987 S_PUNCHUP, // 988 S_PUNCHATK1_1, // 989 S_PUNCHATK1_2, // 990 S_PUNCHATK1_3, // 991 S_PUNCHATK1_4, // 992 S_PUNCHATK1_5, // 993 S_PUNCHATK2_1, // 994 S_PUNCHATK2_2, // 995 S_PUNCHATK2_3, // 996 S_PUNCHATK2_4, // 997 S_PUNCHATK2_5, // 998 S_PUNCHATK2_6, // 999 S_PUNCHATK2_7, // 1000 S_PUNCHATK2_8, // 1001 S_PUNCHATK2_9, // 1002 S_PUNCHPUFF1, // 1003 S_PUNCHPUFF2, // 1004 S_PUNCHPUFF3, // 1005 S_PUNCHPUFF4, // 1006 S_PUNCHPUFF5, // 1007 S_AXE, // 1008 S_FAXEREADY, // 1009 S_FAXEDOWN, // 1010 S_FAXEUP, // 1011 S_FAXEATK_1, // 1012 S_FAXEATK_2, // 1013 S_FAXEATK_3, // 1014 S_FAXEATK_4, // 1015 S_FAXEATK_5, // 1016 S_FAXEATK_6, // 1017 S_FAXEATK_7, // 1018 S_FAXEATK_8, // 1019 S_FAXEATK_9, // 1020 S_FAXEATK_10, // 1021 S_FAXEATK_11, // 1022 S_FAXEATK_12, // 1023 S_FAXEATK_13, // 1024 S_FAXEREADY_G, // 1025 S_FAXEREADY_G1, // 1026 S_FAXEREADY_G2, // 1027 S_FAXEREADY_G3, // 1028 S_FAXEREADY_G4, // 1029 S_FAXEREADY_G5, // 1030 S_FAXEDOWN_G, // 1031 S_FAXEUP_G, // 1032 S_FAXEATK_G1, // 1033 S_FAXEATK_G2, // 1034 S_FAXEATK_G3, // 1035 S_FAXEATK_G4, // 1036 S_FAXEATK_G5, // 1037 S_FAXEATK_G6, // 1038 S_FAXEATK_G7, // 1039 S_FAXEATK_G8, // 1040 S_FAXEATK_G9, // 1041 S_FAXEATK_G10, // 1042 S_FAXEATK_G11, // 1043 S_FAXEATK_G12, // 1044 S_FAXEATK_G13, // 1045 S_AXEPUFF_GLOW1, // 1046 S_AXEPUFF_GLOW2, // 1047 S_AXEPUFF_GLOW3, // 1048 S_AXEPUFF_GLOW4, // 1049 S_AXEPUFF_GLOW5, // 1050 S_AXEPUFF_GLOW6, // 1051 S_AXEPUFF_GLOW7, // 1052 S_AXEBLOOD1, // 1053 S_AXEBLOOD2, // 1054 S_AXEBLOOD3, // 1055 S_AXEBLOOD4, // 1056 S_AXEBLOOD5, // 1057 S_AXEBLOOD6, // 1058 S_HAMM, // 1059 S_FHAMMERREADY, // 1060 S_FHAMMERDOWN, // 1061 S_FHAMMERUP, // 1062 S_FHAMMERATK_1, // 1063 S_FHAMMERATK_2, // 1064 S_FHAMMERATK_3, // 1065 S_FHAMMERATK_4, // 1066 S_FHAMMERATK_5, // 1067 S_FHAMMERATK_6, // 1068 S_FHAMMERATK_7, // 1069 S_FHAMMERATK_8, // 1070 S_FHAMMERATK_9, // 1071 S_FHAMMERATK_10, // 1072 S_FHAMMERATK_11, // 1073 S_FHAMMERATK_12, // 1074 S_HAMMER_MISSILE_1, // 1075 S_HAMMER_MISSILE_2, // 1076 S_HAMMER_MISSILE_3, // 1077 S_HAMMER_MISSILE_4, // 1078 S_HAMMER_MISSILE_5, // 1079 S_HAMMER_MISSILE_6, // 1080 S_HAMMER_MISSILE_7, // 1081 S_HAMMER_MISSILE_8, // 1082 S_HAMMER_MISSILE_X1, // 1083 S_HAMMER_MISSILE_X2, // 1084 S_HAMMER_MISSILE_X3, // 1085 S_HAMMER_MISSILE_X4, // 1086 S_HAMMER_MISSILE_X5, // 1087 S_HAMMER_MISSILE_X6, // 1088 S_HAMMER_MISSILE_X7, // 1089 S_HAMMER_MISSILE_X8, // 1090 S_HAMMER_MISSILE_X9, // 1091 S_HAMMER_MISSILE_X10, // 1092 S_HAMMERPUFF1, // 1093 S_HAMMERPUFF2, // 1094 S_HAMMERPUFF3, // 1095 S_HAMMERPUFF4, // 1096 S_HAMMERPUFF5, // 1097 S_FSWORDREADY, // 1098 S_FSWORDREADY1, // 1099 S_FSWORDREADY2, // 1100 S_FSWORDREADY3, // 1101 S_FSWORDREADY4, // 1102 S_FSWORDREADY5, // 1103 S_FSWORDREADY6, // 1104 S_FSWORDREADY7, // 1105 S_FSWORDREADY8, // 1106 S_FSWORDREADY9, // 1107 S_FSWORDREADY10, // 1108 S_FSWORDREADY11, // 1109 S_FSWORDDOWN, // 1110 S_FSWORDUP, // 1111 S_FSWORDATK_1, // 1112 S_FSWORDATK_2, // 1113 S_FSWORDATK_3, // 1114 S_FSWORDATK_4, // 1115 S_FSWORDATK_5, // 1116 S_FSWORDATK_6, // 1117 S_FSWORDATK_7, // 1118 S_FSWORDATK_8, // 1119 S_FSWORDATK_9, // 1120 S_FSWORDATK_10, // 1121 S_FSWORDATK_11, // 1122 S_FSWORDATK_12, // 1123 S_FSWORD_MISSILE1, // 1124 S_FSWORD_MISSILE2, // 1125 S_FSWORD_MISSILE3, // 1126 S_FSWORD_MISSILE_X1, // 1127 S_FSWORD_MISSILE_X2, // 1128 S_FSWORD_MISSILE_X3, // 1129 S_FSWORD_MISSILE_X4, // 1130 S_FSWORD_MISSILE_X5, // 1131 S_FSWORD_MISSILE_X6, // 1132 S_FSWORD_MISSILE_X7, // 1133 S_FSWORD_MISSILE_X8, // 1134 S_FSWORD_MISSILE_X9, // 1135 S_FSWORD_MISSILE_X10, // 1136 S_FSWORD_FLAME1, // 1137 S_FSWORD_FLAME2, // 1138 S_FSWORD_FLAME3, // 1139 S_FSWORD_FLAME4, // 1140 S_FSWORD_FLAME5, // 1141 S_FSWORD_FLAME6, // 1142 S_FSWORD_FLAME7, // 1143 S_FSWORD_FLAME8, // 1144 S_FSWORD_FLAME9, // 1145 S_FSWORD_FLAME10, // 1146 S_CMACEREADY, // 1147 S_CMACEDOWN, // 1148 S_CMACEUP, // 1149 S_CMACEATK_1, // 1150 S_CMACEATK_2, // 1151 S_CMACEATK_3, // 1152 S_CMACEATK_4, // 1153 S_CMACEATK_5, // 1154 S_CMACEATK_6, // 1155 S_CMACEATK_7, // 1156 S_CMACEATK_8, // 1157 S_CMACEATK_9, // 1158 S_CMACEATK_10, // 1159 S_CMACEATK_11, // 1160 S_CMACEATK_12, // 1161 S_CMACEATK_13, // 1162 S_CMACEATK_14, // 1163 S_CMACEATK_15, // 1164 S_CMACEATK_16, // 1165 S_CMACEATK_17, // 1166 S_CSTAFF, // 1167 S_CSTAFFREADY, // 1168 S_CSTAFFREADY1, // 1169 S_CSTAFFREADY2, // 1170 S_CSTAFFREADY3, // 1171 S_CSTAFFREADY4, // 1172 S_CSTAFFREADY5, // 1173 S_CSTAFFREADY6, // 1174 S_CSTAFFREADY7, // 1175 S_CSTAFFREADY8, // 1176 S_CSTAFFREADY9, // 1177 S_CSTAFFBLINK1, // 1178 S_CSTAFFBLINK2, // 1179 S_CSTAFFBLINK3, // 1180 S_CSTAFFBLINK4, // 1181 S_CSTAFFBLINK5, // 1182 S_CSTAFFBLINK6, // 1183 S_CSTAFFBLINK7, // 1184 S_CSTAFFBLINK8, // 1185 S_CSTAFFBLINK9, // 1186 S_CSTAFFBLINK10, // 1187 S_CSTAFFBLINK11, // 1188 S_CSTAFFDOWN, // 1189 S_CSTAFFDOWN2, // 1190 S_CSTAFFDOWN3, // 1191 S_CSTAFFUP, // 1192 S_CSTAFFATK_1, // 1193 S_CSTAFFATK_2, // 1194 S_CSTAFFATK_3, // 1195 S_CSTAFFATK_4, // 1196 S_CSTAFFATK_5, // 1197 S_CSTAFFATK_6, // 1198 S_CSTAFFATK2_1, // 1199 S_CSTAFF_MISSILE1, // 1200 S_CSTAFF_MISSILE2, // 1201 S_CSTAFF_MISSILE3, // 1202 S_CSTAFF_MISSILE4, // 1203 S_CSTAFF_MISSILE_X1, // 1204 S_CSTAFF_MISSILE_X2, // 1205 S_CSTAFF_MISSILE_X3, // 1206 S_CSTAFF_MISSILE_X4, // 1207 S_CSTAFFPUFF1, // 1208 S_CSTAFFPUFF2, // 1209 S_CSTAFFPUFF3, // 1210 S_CSTAFFPUFF4, // 1211 S_CSTAFFPUFF5, // 1212 S_CFLAME1, // 1213 S_CFLAME2, // 1214 S_CFLAME3, // 1215 S_CFLAME4, // 1216 S_CFLAME5, // 1217 S_CFLAME6, // 1218 S_CFLAME7, // 1219 S_CFLAME8, // 1220 S_CFLAMEREADY1, // 1221 S_CFLAMEREADY2, // 1222 S_CFLAMEREADY3, // 1223 S_CFLAMEREADY4, // 1224 S_CFLAMEREADY5, // 1225 S_CFLAMEREADY6, // 1226 S_CFLAMEREADY7, // 1227 S_CFLAMEREADY8, // 1228 S_CFLAMEREADY9, // 1229 S_CFLAMEREADY10, // 1230 S_CFLAMEREADY11, // 1231 S_CFLAMEREADY12, // 1232 S_CFLAMEDOWN, // 1233 S_CFLAMEUP, // 1234 S_CFLAMEATK_1, // 1235 S_CFLAMEATK_2, // 1236 S_CFLAMEATK_3, // 1237 S_CFLAMEATK_4, // 1238 S_CFLAMEATK_5, // 1239 S_CFLAMEATK_6, // 1240 S_CFLAMEATK_7, // 1241 S_CFLAMEATK_8, // 1242 S_CFLAMEFLOOR1, // 1243 S_CFLAMEFLOOR2, // 1244 S_CFLAMEFLOOR3, // 1245 S_FLAMEPUFF1, // 1246 S_FLAMEPUFF2, // 1247 S_FLAMEPUFF3, // 1248 S_FLAMEPUFF4, // 1249 S_FLAMEPUFF5, // 1250 S_FLAMEPUFF6, // 1251 S_FLAMEPUFF7, // 1252 S_FLAMEPUFF8, // 1253 S_FLAMEPUFF9, // 1254 S_FLAMEPUFF10, // 1255 S_FLAMEPUFF11, // 1256 S_FLAMEPUFF12, // 1257 S_FLAMEPUFF13, // 1258 S_FLAMEPUFF2_1, // 1259 S_FLAMEPUFF2_2, // 1260 S_FLAMEPUFF2_3, // 1261 S_FLAMEPUFF2_4, // 1262 S_FLAMEPUFF2_5, // 1263 S_FLAMEPUFF2_6, // 1264 S_FLAMEPUFF2_7, // 1265 S_FLAMEPUFF2_8, // 1266 S_FLAMEPUFF2_9, // 1267 S_FLAMEPUFF2_10, // 1268 S_FLAMEPUFF2_11, // 1269 S_FLAMEPUFF2_12, // 1270 S_FLAMEPUFF2_13, // 1271 S_FLAMEPUFF2_14, // 1272 S_FLAMEPUFF2_15, // 1273 S_FLAMEPUFF2_16, // 1274 S_FLAMEPUFF2_17, // 1275 S_FLAMEPUFF2_18, // 1276 S_FLAMEPUFF2_19, // 1277 S_FLAMEPUFF2_20, // 1278 S_CIRCLE_FLAME1, // 1279 S_CIRCLE_FLAME2, // 1280 S_CIRCLE_FLAME3, // 1281 S_CIRCLE_FLAME4, // 1282 S_CIRCLE_FLAME5, // 1283 S_CIRCLE_FLAME6, // 1284 S_CIRCLE_FLAME7, // 1285 S_CIRCLE_FLAME8, // 1286 S_CIRCLE_FLAME9, // 1287 S_CIRCLE_FLAME10, // 1288 S_CIRCLE_FLAME11, // 1289 S_CIRCLE_FLAME12, // 1290 S_CIRCLE_FLAME13, // 1291 S_CIRCLE_FLAME14, // 1292 S_CIRCLE_FLAME15, // 1293 S_CIRCLE_FLAME16, // 1294 S_CIRCLE_FLAME_X1, // 1295 S_CIRCLE_FLAME_X2, // 1296 S_CIRCLE_FLAME_X3, // 1297 S_CIRCLE_FLAME_X4, // 1298 S_CIRCLE_FLAME_X5, // 1299 S_CIRCLE_FLAME_X6, // 1300 S_CIRCLE_FLAME_X7, // 1301 S_CIRCLE_FLAME_X8, // 1302 S_CIRCLE_FLAME_X9, // 1303 S_CIRCLE_FLAME_X10, // 1304 S_CFLAME_MISSILE1, // 1305 S_CFLAME_MISSILE2, // 1306 S_CFLAME_MISSILE_X, // 1307 S_CHOLYREADY, // 1308 S_CHOLYDOWN, // 1309 S_CHOLYUP, // 1310 S_CHOLYATK_1, // 1311 S_CHOLYATK_2, // 1312 S_CHOLYATK_3, // 1313 S_CHOLYATK_4, // 1314 S_CHOLYATK_5, // 1315 S_CHOLYATK_6, // 1316 S_CHOLYATK_7, // 1317 S_CHOLYATK_8, // 1318 S_CHOLYATK_9, // 1319 S_HOLY_FX1, // 1320 S_HOLY_FX2, // 1321 S_HOLY_FX3, // 1322 S_HOLY_FX4, // 1323 S_HOLY_FX_X1, // 1324 S_HOLY_FX_X2, // 1325 S_HOLY_FX_X3, // 1326 S_HOLY_FX_X4, // 1327 S_HOLY_FX_X5, // 1328 S_HOLY_FX_X6, // 1329 S_HOLY_TAIL1, // 1330 S_HOLY_TAIL2, // 1331 S_HOLY_PUFF1, // 1332 S_HOLY_PUFF2, // 1333 S_HOLY_PUFF3, // 1334 S_HOLY_PUFF4, // 1335 S_HOLY_PUFF5, // 1336 S_HOLY_MISSILE1, // 1337 S_HOLY_MISSILE2, // 1338 S_HOLY_MISSILE3, // 1339 S_HOLY_MISSILE4, // 1340 S_HOLY_MISSILE_X, // 1341 S_HOLY_MISSILE_P1, // 1342 S_HOLY_MISSILE_P2, // 1343 S_HOLY_MISSILE_P3, // 1344 S_HOLY_MISSILE_P4, // 1345 S_HOLY_MISSILE_P5, // 1346 S_MWANDREADY, // 1347 S_MWANDDOWN, // 1348 S_MWANDUP, // 1349 S_MWANDATK_1, // 1350 S_MWANDATK_2, // 1351 S_MWANDATK_3, // 1352 S_MWANDATK_4, // 1353 S_MWANDPUFF1, // 1354 S_MWANDPUFF2, // 1355 S_MWANDPUFF3, // 1356 S_MWANDPUFF4, // 1357 S_MWANDPUFF5, // 1358 S_MWANDSMOKE1, // 1359 S_MWANDSMOKE2, // 1360 S_MWANDSMOKE3, // 1361 S_MWANDSMOKE4, // 1362 S_MWAND_MISSILE1, // 1363 S_MWAND_MISSILE2, // 1364 S_MW_LIGHTNING1, // 1365 S_MW_LIGHTNING2, // 1366 S_MW_LIGHTNING3, // 1367 S_MW_LIGHTNING4, // 1368 S_MW_LIGHTNING5, // 1369 S_MW_LIGHTNING6, // 1370 S_MW_LIGHTNING7, // 1371 S_MW_LIGHTNING8, // 1372 S_MLIGHTNINGREADY, // 1373 S_MLIGHTNINGREADY2, // 1374 S_MLIGHTNINGREADY3, // 1375 S_MLIGHTNINGREADY4, // 1376 S_MLIGHTNINGREADY5, // 1377 S_MLIGHTNINGREADY6, // 1378 S_MLIGHTNINGREADY7, // 1379 S_MLIGHTNINGREADY8, // 1380 S_MLIGHTNINGREADY9, // 1381 S_MLIGHTNINGREADY10, // 1382 S_MLIGHTNINGREADY11, // 1383 S_MLIGHTNINGREADY12, // 1384 S_MLIGHTNINGREADY13, // 1385 S_MLIGHTNINGREADY14, // 1386 S_MLIGHTNINGREADY15, // 1387 S_MLIGHTNINGREADY16, // 1388 S_MLIGHTNINGREADY17, // 1389 S_MLIGHTNINGREADY18, // 1390 S_MLIGHTNINGREADY19, // 1391 S_MLIGHTNINGREADY20, // 1392 S_MLIGHTNINGREADY21, // 1393 S_MLIGHTNINGREADY22, // 1394 S_MLIGHTNINGREADY23, // 1395 S_MLIGHTNINGREADY24, // 1396 S_MLIGHTNINGDOWN, // 1397 S_MLIGHTNINGUP, // 1398 S_MLIGHTNINGATK_1, // 1399 S_MLIGHTNINGATK_2, // 1400 S_MLIGHTNINGATK_3, // 1401 S_MLIGHTNINGATK_4, // 1402 S_MLIGHTNINGATK_5, // 1403 S_MLIGHTNINGATK_6, // 1404 S_MLIGHTNINGATK_7, // 1405 S_MLIGHTNINGATK_8, // 1406 S_MLIGHTNINGATK_9, // 1407 S_MLIGHTNINGATK_10, // 1408 S_MLIGHTNINGATK_11, // 1409 S_LIGHTNING_CEILING1, // 1410 S_LIGHTNING_CEILING2, // 1411 S_LIGHTNING_CEILING3, // 1412 S_LIGHTNING_CEILING4, // 1413 S_LIGHTNING_C_X1, // 1414 S_LIGHTNING_C_X2, // 1415 S_LIGHTNING_C_X3, // 1416 S_LIGHTNING_C_X4, // 1417 S_LIGHTNING_C_X5, // 1418 S_LIGHTNING_C_X6, // 1419 S_LIGHTNING_C_X7, // 1420 S_LIGHTNING_C_X8, // 1421 S_LIGHTNING_C_X9, // 1422 S_LIGHTNING_C_X10, // 1423 S_LIGHTNING_C_X11, // 1424 S_LIGHTNING_C_X12, // 1425 S_LIGHTNING_C_X13, // 1426 S_LIGHTNING_C_X14, // 1427 S_LIGHTNING_C_X15, // 1428 S_LIGHTNING_C_X16, // 1429 S_LIGHTNING_C_X17, // 1430 S_LIGHTNING_C_X18, // 1431 S_LIGHTNING_C_X19, // 1432 S_LIGHTNING_FLOOR1, // 1433 S_LIGHTNING_FLOOR2, // 1434 S_LIGHTNING_FLOOR3, // 1435 S_LIGHTNING_FLOOR4, // 1436 S_LIGHTNING_F_X1, // 1437 S_LIGHTNING_F_X2, // 1438 S_LIGHTNING_F_X3, // 1439 S_LIGHTNING_F_X4, // 1440 S_LIGHTNING_F_X5, // 1441 S_LIGHTNING_F_X6, // 1442 S_LIGHTNING_F_X7, // 1443 S_LIGHTNING_F_X8, // 1444 S_LIGHTNING_F_X9, // 1445 S_LIGHTNING_F_X10, // 1446 S_LIGHTNING_F_X11, // 1447 S_LIGHTNING_F_X12, // 1448 S_LIGHTNING_F_X13, // 1449 S_LIGHTNING_F_X14, // 1450 S_LIGHTNING_F_X15, // 1451 S_LIGHTNING_F_X16, // 1452 S_LIGHTNING_F_X17, // 1453 S_LIGHTNING_F_X18, // 1454 S_LIGHTNING_F_X19, // 1455 S_LIGHTNING_ZAP1, // 1456 S_LIGHTNING_ZAP2, // 1457 S_LIGHTNING_ZAP3, // 1458 S_LIGHTNING_ZAP4, // 1459 S_LIGHTNING_ZAP5, // 1460 S_LIGHTNING_ZAP_X1, // 1461 S_LIGHTNING_ZAP_X2, // 1462 S_LIGHTNING_ZAP_X3, // 1463 S_LIGHTNING_ZAP_X4, // 1464 S_LIGHTNING_ZAP_X5, // 1465 S_LIGHTNING_ZAP_X6, // 1466 S_LIGHTNING_ZAP_X7, // 1467 S_LIGHTNING_ZAP_X8, // 1468 S_MSTAFFREADY, // 1469 S_MSTAFFREADY2, // 1470 S_MSTAFFREADY3, // 1471 S_MSTAFFREADY4, // 1472 S_MSTAFFREADY5, // 1473 S_MSTAFFREADY6, // 1474 S_MSTAFFREADY7, // 1475 S_MSTAFFREADY8, // 1476 S_MSTAFFREADY9, // 1477 S_MSTAFFREADY10, // 1478 S_MSTAFFREADY11, // 1479 S_MSTAFFREADY12, // 1480 S_MSTAFFREADY13, // 1481 S_MSTAFFREADY14, // 1482 S_MSTAFFREADY15, // 1483 S_MSTAFFREADY16, // 1484 S_MSTAFFREADY17, // 1485 S_MSTAFFREADY18, // 1486 S_MSTAFFREADY19, // 1487 S_MSTAFFREADY20, // 1488 S_MSTAFFREADY21, // 1489 S_MSTAFFREADY22, // 1490 S_MSTAFFREADY23, // 1491 S_MSTAFFREADY24, // 1492 S_MSTAFFREADY25, // 1493 S_MSTAFFREADY26, // 1494 S_MSTAFFREADY27, // 1495 S_MSTAFFREADY28, // 1496 S_MSTAFFREADY29, // 1497 S_MSTAFFREADY30, // 1498 S_MSTAFFREADY31, // 1499 S_MSTAFFREADY32, // 1500 S_MSTAFFREADY33, // 1501 S_MSTAFFREADY34, // 1502 S_MSTAFFREADY35, // 1503 S_MSTAFFDOWN, // 1504 S_MSTAFFUP, // 1505 S_MSTAFFATK_1, // 1506 S_MSTAFFATK_2, // 1507 S_MSTAFFATK_3, // 1508 S_MSTAFFATK_4, // 1509 S_MSTAFFATK_5, // 1510 S_MSTAFFATK_6, // 1511 S_MSTAFFATK_7, // 1512 S_MSTAFF_FX1_1, // 1513 S_MSTAFF_FX1_2, // 1514 S_MSTAFF_FX1_3, // 1515 S_MSTAFF_FX1_4, // 1516 S_MSTAFF_FX1_5, // 1517 S_MSTAFF_FX1_6, // 1518 S_MSTAFF_FX_X1, // 1519 S_MSTAFF_FX_X2, // 1520 S_MSTAFF_FX_X3, // 1521 S_MSTAFF_FX_X4, // 1522 S_MSTAFF_FX_X5, // 1523 S_MSTAFF_FX_X6, // 1524 S_MSTAFF_FX_X7, // 1525 S_MSTAFF_FX_X8, // 1526 S_MSTAFF_FX_X9, // 1527 S_MSTAFF_FX_X10, // 1528 S_MSTAFF_FX2_1, // 1529 S_MSTAFF_FX2_2, // 1530 S_MSTAFF_FX2_3, // 1531 S_MSTAFF_FX2_4, // 1532 S_MSTAFF_FX2_X1, // 1533 S_MSTAFF_FX2_X2, // 1534 S_MSTAFF_FX2_X3, // 1535 S_MSTAFF_FX2_X4, // 1536 S_MSTAFF_FX2_X5, // 1537 S_FSWORD1, // 1538 S_FSWORD2, // 1539 S_FSWORD3, // 1540 S_CHOLY1, // 1541 S_CHOLY2, // 1542 S_CHOLY3, // 1543 S_MSTAFF1, // 1544 S_MSTAFF2, // 1545 S_MSTAFF3, // 1546 S_SNOUTREADY, // 1547 S_SNOUTDOWN, // 1548 S_SNOUTUP, // 1549 S_SNOUTATK1, // 1550 S_SNOUTATK2, // 1551 S_COS1, // 1552 S_COS2, // 1553 S_COS3, // 1554 S_CONEREADY, // 1555 S_CONEDOWN, // 1556 S_CONEUP, // 1557 S_CONEATK1_1, // 1558 S_CONEATK1_2, // 1559 S_CONEATK1_3, // 1560 S_CONEATK1_4, // 1561 S_CONEATK1_5, // 1562 S_CONEATK1_6, // 1563 S_CONEATK1_7, // 1564 S_CONEATK1_8, // 1565 S_SHARDFX1_1, // 1566 S_SHARDFX1_2, // 1567 S_SHARDFX1_3, // 1568 S_SHARDFX1_4, // 1569 S_SHARDFXE1_1, // 1570 S_SHARDFXE1_2, // 1571 S_SHARDFXE1_3, // 1572 S_SHARDFXE1_4, // 1573 S_SHARDFXE1_5, // 1574 S_BLOOD1, // 1575 S_BLOOD2, // 1576 S_BLOOD3, // 1577 S_BLOODSPLATTER1, // 1578 S_BLOODSPLATTER2, // 1579 S_BLOODSPLATTER3, // 1580 S_BLOODSPLATTERX, // 1581 S_GIBS1, // 1582 S_FPLAY, // 1583 S_FPLAY_RUN1, // 1584 S_FPLAY_RUN2, // 1585 S_FPLAY_RUN3, // 1586 S_FPLAY_RUN4, // 1587 S_FPLAY_ATK1, // 1588 S_FPLAY_ATK2, // 1589 S_FPLAY_PAIN, // 1590 S_FPLAY_PAIN2, // 1591 S_FPLAY_DIE1, // 1592 S_FPLAY_DIE2, // 1593 S_FPLAY_DIE3, // 1594 S_FPLAY_DIE4, // 1595 S_FPLAY_DIE5, // 1596 S_FPLAY_DIE6, // 1597 S_FPLAY_DIE7, // 1598 S_FPLAY_XDIE1, // 1599 S_FPLAY_XDIE2, // 1600 S_FPLAY_XDIE3, // 1601 S_FPLAY_XDIE4, // 1602 S_FPLAY_XDIE5, // 1603 S_FPLAY_XDIE6, // 1604 S_FPLAY_XDIE7, // 1605 S_FPLAY_XDIE8, // 1606 S_FPLAY_ICE, // 1607 S_FPLAY_ICE2, // 1608 S_PLAY_F_FDTH1, // 1609 S_PLAY_F_FDTH2, // 1610 S_PLAY_C_FDTH1, // 1611 S_PLAY_C_FDTH2, // 1612 S_PLAY_M_FDTH1, // 1613 S_PLAY_M_FDTH2, // 1614 S_PLAY_FDTH3, // 1615 S_PLAY_FDTH4, // 1616 S_PLAY_FDTH5, // 1617 S_PLAY_FDTH6, // 1618 S_PLAY_FDTH7, // 1619 S_PLAY_FDTH8, // 1620 S_PLAY_FDTH9, // 1621 S_PLAY_FDTH10, // 1622 S_PLAY_FDTH11, // 1623 S_PLAY_FDTH12, // 1624 S_PLAY_FDTH13, // 1625 S_PLAY_FDTH14, // 1626 S_PLAY_FDTH15, // 1627 S_PLAY_FDTH16, // 1628 S_PLAY_FDTH17, // 1629 S_PLAY_FDTH18, // 1630 S_PLAY_FDTH19, // 1631 S_PLAY_FDTH20, // 1632 S_BLOODYSKULL1, // 1633 S_BLOODYSKULL2, // 1634 S_BLOODYSKULL3, // 1635 S_BLOODYSKULL4, // 1636 S_BLOODYSKULL5, // 1637 S_BLOODYSKULL6, // 1638 S_BLOODYSKULL7, // 1639 S_BLOODYSKULLX1, // 1640 S_BLOODYSKULLX2, // 1641 S_PLAYER_SPEED1, // 1642 S_PLAYER_SPEED2, // 1643 S_ICECHUNK1, // 1644 S_ICECHUNK2, // 1645 S_ICECHUNK3, // 1646 S_ICECHUNK4, // 1647 S_ICECHUNK_HEAD, // 1648 S_ICECHUNK_HEAD2, // 1649 S_CPLAY, // 1650 S_CPLAY_RUN1, // 1651 S_CPLAY_RUN2, // 1652 S_CPLAY_RUN3, // 1653 S_CPLAY_RUN4, // 1654 S_CPLAY_ATK1, // 1655 S_CPLAY_ATK2, // 1656 S_CPLAY_ATK3, // 1657 S_CPLAY_PAIN, // 1658 S_CPLAY_PAIN2, // 1659 S_CPLAY_DIE1, // 1660 S_CPLAY_DIE2, // 1661 S_CPLAY_DIE3, // 1662 S_CPLAY_DIE4, // 1663 S_CPLAY_DIE5, // 1664 S_CPLAY_DIE6, // 1665 S_CPLAY_DIE7, // 1666 S_CPLAY_DIE8, // 1667 S_CPLAY_DIE9, // 1668 S_CPLAY_XDIE1, // 1669 S_CPLAY_XDIE2, // 1670 S_CPLAY_XDIE3, // 1671 S_CPLAY_XDIE4, // 1672 S_CPLAY_XDIE5, // 1673 S_CPLAY_XDIE6, // 1674 S_CPLAY_XDIE7, // 1675 S_CPLAY_XDIE8, // 1676 S_CPLAY_XDIE9, // 1677 S_CPLAY_XDIE10, // 1678 S_CPLAY_ICE, // 1679 S_CPLAY_ICE2, // 1680 S_MPLAY, // 1681 S_MPLAY_RUN1, // 1682 S_MPLAY_RUN2, // 1683 S_MPLAY_RUN3, // 1684 S_MPLAY_RUN4, // 1685 S_MPLAY_ATK1, // 1686 S_MPLAY_ATK2, // 1687 S_MPLAY_PAIN, // 1688 S_MPLAY_PAIN2, // 1689 S_MPLAY_DIE1, // 1690 S_MPLAY_DIE2, // 1691 S_MPLAY_DIE3, // 1692 S_MPLAY_DIE4, // 1693 S_MPLAY_DIE5, // 1694 S_MPLAY_DIE6, // 1695 S_MPLAY_DIE7, // 1696 S_MPLAY_XDIE1, // 1697 S_MPLAY_XDIE2, // 1698 S_MPLAY_XDIE3, // 1699 S_MPLAY_XDIE4, // 1700 S_MPLAY_XDIE5, // 1701 S_MPLAY_XDIE6, // 1702 S_MPLAY_XDIE7, // 1703 S_MPLAY_XDIE8, // 1704 S_MPLAY_XDIE9, // 1705 S_MPLAY_ICE, // 1706 S_MPLAY_ICE2, // 1707 S_PIGPLAY, // 1708 S_PIGPLAY_RUN1, // 1709 S_PIGPLAY_RUN2, // 1710 S_PIGPLAY_RUN3, // 1711 S_PIGPLAY_RUN4, // 1712 S_PIGPLAY_ATK1, // 1713 S_PIGPLAY_PAIN, // 1714 S_PIG_LOOK1, // 1715 S_PIG_WALK1, // 1716 S_PIG_WALK2, // 1717 S_PIG_WALK3, // 1718 S_PIG_WALK4, // 1719 S_PIG_PAIN, // 1720 S_PIG_ATK1, // 1721 S_PIG_ATK2, // 1722 S_PIG_DIE1, // 1723 S_PIG_DIE2, // 1724 S_PIG_DIE3, // 1725 S_PIG_DIE4, // 1726 S_PIG_DIE5, // 1727 S_PIG_DIE6, // 1728 S_PIG_DIE7, // 1729 S_PIG_DIE8, // 1730 S_PIG_ICE, // 1731 S_PIG_ICE2, // 1732 S_CENTAUR_LOOK1, // 1733 S_CENTAUR_LOOK2, // 1734 S_CENTAUR_WALK1, // 1735 S_CENTAUR_WALK2, // 1736 S_CENTAUR_WALK3, // 1737 S_CENTAUR_WALK4, // 1738 S_CENTAUR_ATK1, // 1739 S_CENTAUR_ATK2, // 1740 S_CENTAUR_ATK3, // 1741 S_CENTAUR_MISSILE1, // 1742 S_CENTAUR_MISSILE2, // 1743 S_CENTAUR_MISSILE3, // 1744 S_CENTAUR_MISSILE4, // 1745 S_CENTAUR_PAIN1, // 1746 S_CENTAUR_PAIN2, // 1747 S_CENTAUR_PAIN3, // 1748 S_CENTAUR_PAIN4, // 1749 S_CENTAUR_PAIN5, // 1750 S_CENTAUR_PAIN6, // 1751 S_CENTAUR_DEATH1, // 1752 S_CENTAUR_DEATH2, // 1753 S_CENTAUR_DEATH3, // 1754 S_CENTAUR_DEATH4, // 1755 S_CENTAUR_DEATH5, // 1756 S_CENTAUR_DEATH6, // 1757 S_CENTAUR_DEATH7, // 1758 S_CENTAUR_DEATH8, // 1759 S_CENTAUR_DEATH9, // 1760 S_CENTAUR_DEATH0, // 1761 S_CENTAUR_DEATH_X1, // 1762 S_CENTAUR_DEATH_X2, // 1763 S_CENTAUR_DEATH_X3, // 1764 S_CENTAUR_DEATH_X4, // 1765 S_CENTAUR_DEATH_X5, // 1766 S_CENTAUR_DEATH_X6, // 1767 S_CENTAUR_DEATH_X7, // 1768 S_CENTAUR_DEATH_X8, // 1769 S_CENTAUR_DEATH_X9, // 1770 S_CENTAUR_DEATH_X10, // 1771 S_CENTAUR_DEATH_X11, // 1772 S_CENTAUR_ICE, // 1773 S_CENTAUR_ICE2, // 1774 S_CENTAUR_FX1, // 1775 S_CENTAUR_FX_X1, // 1776 S_CENTAUR_FX_X2, // 1777 S_CENTAUR_FX_X3, // 1778 S_CENTAUR_FX_X4, // 1779 S_CENTAUR_FX_X5, // 1780 S_CENTAUR_SHIELD1, // 1781 S_CENTAUR_SHIELD2, // 1782 S_CENTAUR_SHIELD3, // 1783 S_CENTAUR_SHIELD4, // 1784 S_CENTAUR_SHIELD5, // 1785 S_CENTAUR_SHIELD6, // 1786 S_CENTAUR_SHIELD_X1, // 1787 S_CENTAUR_SHIELD_X2, // 1788 S_CENTAUR_SHIELD_X3, // 1789 S_CENTAUR_SHIELD_X4, // 1790 S_CENTAUR_SWORD1, // 1791 S_CENTAUR_SWORD2, // 1792 S_CENTAUR_SWORD3, // 1793 S_CENTAUR_SWORD4, // 1794 S_CENTAUR_SWORD5, // 1795 S_CENTAUR_SWORD6, // 1796 S_CENTAUR_SWORD7, // 1797 S_CENTAUR_SWORD_X1, // 1798 S_CENTAUR_SWORD_X2, // 1799 S_CENTAUR_SWORD_X3, // 1800 S_DEMN_LOOK1, // 1801 S_DEMN_LOOK2, // 1802 S_DEMN_CHASE1, // 1803 S_DEMN_CHASE2, // 1804 S_DEMN_CHASE3, // 1805 S_DEMN_CHASE4, // 1806 S_DEMN_ATK1_1, // 1807 S_DEMN_ATK1_2, // 1808 S_DEMN_ATK1_3, // 1809 S_DEMN_ATK2_1, // 1810 S_DEMN_ATK2_2, // 1811 S_DEMN_ATK2_3, // 1812 S_DEMN_PAIN1, // 1813 S_DEMN_PAIN2, // 1814 S_DEMN_DEATH1, // 1815 S_DEMN_DEATH2, // 1816 S_DEMN_DEATH3, // 1817 S_DEMN_DEATH4, // 1818 S_DEMN_DEATH5, // 1819 S_DEMN_DEATH6, // 1820 S_DEMN_DEATH7, // 1821 S_DEMN_DEATH8, // 1822 S_DEMN_DEATH9, // 1823 S_DEMN_XDEATH1, // 1824 S_DEMN_XDEATH2, // 1825 S_DEMN_XDEATH3, // 1826 S_DEMN_XDEATH4, // 1827 S_DEMN_XDEATH5, // 1828 S_DEMN_XDEATH6, // 1829 S_DEMN_XDEATH7, // 1830 S_DEMN_XDEATH8, // 1831 S_DEMN_XDEATH9, // 1832 S_DEMON_ICE, // 1833 S_DEMON_ICE2, // 1834 S_DEMONCHUNK1_1, // 1835 S_DEMONCHUNK1_2, // 1836 S_DEMONCHUNK1_3, // 1837 S_DEMONCHUNK1_4, // 1838 S_DEMONCHUNK2_1, // 1839 S_DEMONCHUNK2_2, // 1840 S_DEMONCHUNK2_3, // 1841 S_DEMONCHUNK2_4, // 1842 S_DEMONCHUNK3_1, // 1843 S_DEMONCHUNK3_2, // 1844 S_DEMONCHUNK3_3, // 1845 S_DEMONCHUNK3_4, // 1846 S_DEMONCHUNK4_1, // 1847 S_DEMONCHUNK4_2, // 1848 S_DEMONCHUNK4_3, // 1849 S_DEMONCHUNK4_4, // 1850 S_DEMONCHUNK5_1, // 1851 S_DEMONCHUNK5_2, // 1852 S_DEMONCHUNK5_3, // 1853 S_DEMONCHUNK5_4, // 1854 S_DEMONFX_MOVE1, // 1855 S_DEMONFX_MOVE2, // 1856 S_DEMONFX_MOVE3, // 1857 S_DEMONFX_BOOM1, // 1858 S_DEMONFX_BOOM2, // 1859 S_DEMONFX_BOOM3, // 1860 S_DEMONFX_BOOM4, // 1861 S_DEMONFX_BOOM5, // 1862 S_DEMN2_LOOK1, // 1863 S_DEMN2_LOOK2, // 1864 S_DEMN2_CHASE1, // 1865 S_DEMN2_CHASE2, // 1866 S_DEMN2_CHASE3, // 1867 S_DEMN2_CHASE4, // 1868 S_DEMN2_ATK1_1, // 1869 S_DEMN2_ATK1_2, // 1870 S_DEMN2_ATK1_3, // 1871 S_DEMN2_ATK2_1, // 1872 S_DEMN2_ATK2_2, // 1873 S_DEMN2_ATK2_3, // 1874 S_DEMN2_PAIN1, // 1875 S_DEMN2_PAIN2, // 1876 S_DEMN2_DEATH1, // 1877 S_DEMN2_DEATH2, // 1878 S_DEMN2_DEATH3, // 1879 S_DEMN2_DEATH4, // 1880 S_DEMN2_DEATH5, // 1881 S_DEMN2_DEATH6, // 1882 S_DEMN2_DEATH7, // 1883 S_DEMN2_DEATH8, // 1884 S_DEMN2_DEATH9, // 1885 S_DEMN2_XDEATH1, // 1886 S_DEMN2_XDEATH2, // 1887 S_DEMN2_XDEATH3, // 1888 S_DEMN2_XDEATH4, // 1889 S_DEMN2_XDEATH5, // 1890 S_DEMN2_XDEATH6, // 1891 S_DEMN2_XDEATH7, // 1892 S_DEMN2_XDEATH8, // 1893 S_DEMN2_XDEATH9, // 1894 S_DEMON2CHUNK1_1, // 1895 S_DEMON2CHUNK1_2, // 1896 S_DEMON2CHUNK1_3, // 1897 S_DEMON2CHUNK1_4, // 1898 S_DEMON2CHUNK2_1, // 1899 S_DEMON2CHUNK2_2, // 1900 S_DEMON2CHUNK2_3, // 1901 S_DEMON2CHUNK2_4, // 1902 S_DEMON2CHUNK3_1, // 1903 S_DEMON2CHUNK3_2, // 1904 S_DEMON2CHUNK3_3, // 1905 S_DEMON2CHUNK3_4, // 1906 S_DEMON2CHUNK4_1, // 1907 S_DEMON2CHUNK4_2, // 1908 S_DEMON2CHUNK4_3, // 1909 S_DEMON2CHUNK4_4, // 1910 S_DEMON2CHUNK5_1, // 1911 S_DEMON2CHUNK5_2, // 1912 S_DEMON2CHUNK5_3, // 1913 S_DEMON2CHUNK5_4, // 1914 S_DEMON2FX_MOVE1, // 1915 S_DEMON2FX_MOVE2, // 1916 S_DEMON2FX_MOVE3, // 1917 S_DEMON2FX_MOVE4, // 1918 S_DEMON2FX_MOVE5, // 1919 S_DEMON2FX_MOVE6, // 1920 S_DEMON2FX_BOOM1, // 1921 S_DEMON2FX_BOOM2, // 1922 S_DEMON2FX_BOOM3, // 1923 S_DEMON2FX_BOOM4, // 1924 S_DEMON2FX_BOOM5, // 1925 S_DEMON2FX_BOOM6, // 1926 S_WRAITH_RAISE1, // 1927 S_WRAITH_RAISE2, // 1928 S_WRAITH_RAISE3, // 1929 S_WRAITH_RAISE4, // 1930 S_WRAITH_RAISE5, // 1931 S_WRAITH_INIT1, // 1932 S_WRAITH_INIT2, // 1933 S_WRAITH_LOOK1, // 1934 S_WRAITH_LOOK2, // 1935 S_WRAITH_CHASE1, // 1936 S_WRAITH_CHASE2, // 1937 S_WRAITH_CHASE3, // 1938 S_WRAITH_CHASE4, // 1939 S_WRAITH_ATK1_1, // 1940 S_WRAITH_ATK1_2, // 1941 S_WRAITH_ATK1_3, // 1942 S_WRAITH_ATK2_1, // 1943 S_WRAITH_ATK2_2, // 1944 S_WRAITH_ATK2_3, // 1945 S_WRAITH_PAIN1, // 1946 S_WRAITH_PAIN2, // 1947 S_WRAITH_DEATH1_1, // 1948 S_WRAITH_DEATH1_2, // 1949 S_WRAITH_DEATH1_3, // 1950 S_WRAITH_DEATH1_4, // 1951 S_WRAITH_DEATH1_5, // 1952 S_WRAITH_DEATH1_6, // 1953 S_WRAITH_DEATH1_7, // 1954 S_WRAITH_DEATH1_8, // 1955 S_WRAITH_DEATH1_9, // 1956 S_WRAITH_DEATH1_0, // 1957 S_WRAITH_DEATH2_1, // 1958 S_WRAITH_DEATH2_2, // 1959 S_WRAITH_DEATH2_3, // 1960 S_WRAITH_DEATH2_4, // 1961 S_WRAITH_DEATH2_5, // 1962 S_WRAITH_DEATH2_6, // 1963 S_WRAITH_DEATH2_7, // 1964 S_WRAITH_DEATH2_8, // 1965 S_WRAITH_ICE, // 1966 S_WRAITH_ICE2, // 1967 S_WRTHFX_MOVE1, // 1968 S_WRTHFX_MOVE2, // 1969 S_WRTHFX_MOVE3, // 1970 S_WRTHFX_BOOM1, // 1971 S_WRTHFX_BOOM2, // 1972 S_WRTHFX_BOOM3, // 1973 S_WRTHFX_BOOM4, // 1974 S_WRTHFX_BOOM5, // 1975 S_WRTHFX_BOOM6, // 1976 S_WRTHFX_SIZZLE1, // 1977 S_WRTHFX_SIZZLE2, // 1978 S_WRTHFX_SIZZLE3, // 1979 S_WRTHFX_SIZZLE4, // 1980 S_WRTHFX_SIZZLE5, // 1981 S_WRTHFX_SIZZLE6, // 1982 S_WRTHFX_SIZZLE7, // 1983 S_WRTHFX_DROP1, // 1984 S_WRTHFX_DROP2, // 1985 S_WRTHFX_DROP3, // 1986 S_WRTHFX_DEAD1, // 1987 S_WRTHFX_ADROP1, // 1988 S_WRTHFX_ADROP2, // 1989 S_WRTHFX_ADROP3, // 1990 S_WRTHFX_ADROP4, // 1991 S_WRTHFX_ADEAD1, // 1992 S_WRTHFX_BDROP1, // 1993 S_WRTHFX_BDROP2, // 1994 S_WRTHFX_BDROP3, // 1995 S_WRTHFX_BDEAD1, // 1996 S_MNTR_SPAWN1, // 1997 S_MNTR_SPAWN2, // 1998 S_MNTR_SPAWN3, // 1999 S_MNTR_LOOK1, // 2000 S_MNTR_LOOK2, // 2001 S_MNTR_WALK1, // 2002 S_MNTR_WALK2, // 2003 S_MNTR_WALK3, // 2004 S_MNTR_WALK4, // 2005 S_MNTR_ROAM1, // 2006 S_MNTR_ROAM2, // 2007 S_MNTR_ROAM3, // 2008 S_MNTR_ROAM4, // 2009 S_MNTR_ATK1_1, // 2010 S_MNTR_ATK1_2, // 2011 S_MNTR_ATK1_3, // 2012 S_MNTR_ATK2_1, // 2013 S_MNTR_ATK2_2, // 2014 S_MNTR_ATK2_3, // 2015 S_MNTR_ATK3_1, // 2016 S_MNTR_ATK3_2, // 2017 S_MNTR_ATK3_3, // 2018 S_MNTR_ATK3_4, // 2019 S_MNTR_ATK4_1, // 2020 S_MNTR_PAIN1, // 2021 S_MNTR_PAIN2, // 2022 S_MNTR_DIE1, // 2023 S_MNTR_DIE2, // 2024 S_MNTR_DIE3, // 2025 S_MNTR_DIE4, // 2026 S_MNTR_DIE5, // 2027 S_MNTR_DIE6, // 2028 S_MNTR_DIE7, // 2029 S_MNTR_DIE8, // 2030 S_MNTR_DIE9, // 2031 S_MNTRFX1_1, // 2032 S_MNTRFX1_2, // 2033 S_MNTRFXI1_1, // 2034 S_MNTRFXI1_2, // 2035 S_MNTRFXI1_3, // 2036 S_MNTRFXI1_4, // 2037 S_MNTRFXI1_5, // 2038 S_MNTRFXI1_6, // 2039 S_MNTRFX2_1, // 2040 S_MNTRFXI2_1, // 2041 S_MNTRFXI2_2, // 2042 S_MNTRFXI2_3, // 2043 S_MNTRFXI2_4, // 2044 S_MNTRFXI2_5, // 2045 S_MNTRFX3_1, // 2046 S_MNTRFX3_2, // 2047 S_MNTRFX3_3, // 2048 S_MNTRFX3_4, // 2049 S_MNTRFX3_5, // 2050 S_MNTRFX3_6, // 2051 S_MNTRFX3_7, // 2052 S_MNTRFX3_8, // 2053 S_MNTRFX3_9, // 2054 S_MINOSMOKE1, // 2055 S_MINOSMOKE2, // 2056 S_MINOSMOKE3, // 2057 S_MINOSMOKE4, // 2058 S_MINOSMOKE5, // 2059 S_MINOSMOKE6, // 2060 S_MINOSMOKE7, // 2061 S_MINOSMOKE8, // 2062 S_MINOSMOKE9, // 2063 S_MINOSMOKE0, // 2064 S_MINOSMOKEA, // 2065 S_MINOSMOKEB, // 2066 S_MINOSMOKEC, // 2067 S_MINOSMOKED, // 2068 S_MINOSMOKEE, // 2069 S_MINOSMOKEF, // 2070 S_MINOSMOKEG, // 2071 S_MINOSMOKEX1, // 2072 S_MINOSMOKEX2, // 2073 S_MINOSMOKEX3, // 2074 S_MINOSMOKEX4, // 2075 S_MINOSMOKEX5, // 2076 S_MINOSMOKEX6, // 2077 S_MINOSMOKEX7, // 2078 S_MINOSMOKEX8, // 2079 S_MINOSMOKEX9, // 2080 S_MINOSMOKEX0, // 2081 S_MINOSMOKEXA, // 2082 S_MINOSMOKEXB, // 2083 S_MINOSMOKEXC, // 2084 S_MINOSMOKEXD, // 2085 S_MINOSMOKEXE, // 2086 S_MINOSMOKEXF, // 2087 S_MINOSMOKEXG, // 2088 S_MINOSMOKEXH, // 2089 S_MINOSMOKEXI, // 2090 S_SERPENT_LOOK1, // 2091 S_SERPENT_SWIM1, // 2092 S_SERPENT_SWIM2, // 2093 S_SERPENT_SWIM3, // 2094 S_SERPENT_HUMP1, // 2095 S_SERPENT_HUMP2, // 2096 S_SERPENT_HUMP3, // 2097 S_SERPENT_HUMP4, // 2098 S_SERPENT_HUMP5, // 2099 S_SERPENT_HUMP6, // 2100 S_SERPENT_HUMP7, // 2101 S_SERPENT_HUMP8, // 2102 S_SERPENT_HUMP9, // 2103 S_SERPENT_HUMP10, // 2104 S_SERPENT_HUMP11, // 2105 S_SERPENT_HUMP12, // 2106 S_SERPENT_HUMP13, // 2107 S_SERPENT_HUMP14, // 2108 S_SERPENT_HUMP15, // 2109 S_SERPENT_SURFACE1, // 2110 S_SERPENT_SURFACE2, // 2111 S_SERPENT_SURFACE3, // 2112 S_SERPENT_SURFACE4, // 2113 S_SERPENT_SURFACE5, // 2114 S_SERPENT_DIVE1, // 2115 S_SERPENT_DIVE2, // 2116 S_SERPENT_DIVE3, // 2117 S_SERPENT_DIVE4, // 2118 S_SERPENT_DIVE5, // 2119 S_SERPENT_DIVE6, // 2120 S_SERPENT_DIVE7, // 2121 S_SERPENT_DIVE8, // 2122 S_SERPENT_DIVE9, // 2123 S_SERPENT_DIVE10, // 2124 S_SERPENT_WALK1, // 2125 S_SERPENT_WALK2, // 2126 S_SERPENT_WALK3, // 2127 S_SERPENT_WALK4, // 2128 S_SERPENT_PAIN1, // 2129 S_SERPENT_PAIN2, // 2130 S_SERPENT_ATK1, // 2131 S_SERPENT_ATK2, // 2132 S_SERPENT_MELEE1, // 2133 S_SERPENT_MISSILE1, // 2134 S_SERPENT_DIE1, // 2135 S_SERPENT_DIE2, // 2136 S_SERPENT_DIE3, // 2137 S_SERPENT_DIE4, // 2138 S_SERPENT_DIE5, // 2139 S_SERPENT_DIE6, // 2140 S_SERPENT_DIE7, // 2141 S_SERPENT_DIE8, // 2142 S_SERPENT_DIE9, // 2143 S_SERPENT_DIE10, // 2144 S_SERPENT_DIE11, // 2145 S_SERPENT_DIE12, // 2146 S_SERPENT_XDIE1, // 2147 S_SERPENT_XDIE2, // 2148 S_SERPENT_XDIE3, // 2149 S_SERPENT_XDIE4, // 2150 S_SERPENT_XDIE5, // 2151 S_SERPENT_XDIE6, // 2152 S_SERPENT_XDIE7, // 2153 S_SERPENT_XDIE8, // 2154 S_SERPENT_ICE, // 2155 S_SERPENT_ICE2, // 2156 S_SERPENT_FX1, // 2157 S_SERPENT_FX2, // 2158 S_SERPENT_FX3, // 2159 S_SERPENT_FX4, // 2160 S_SERPENT_FX_X1, // 2161 S_SERPENT_FX_X2, // 2162 S_SERPENT_FX_X3, // 2163 S_SERPENT_FX_X4, // 2164 S_SERPENT_FX_X5, // 2165 S_SERPENT_FX_X6, // 2166 S_SERPENT_HEAD1, // 2167 S_SERPENT_HEAD2, // 2168 S_SERPENT_HEAD3, // 2169 S_SERPENT_HEAD4, // 2170 S_SERPENT_HEAD5, // 2171 S_SERPENT_HEAD6, // 2172 S_SERPENT_HEAD7, // 2173 S_SERPENT_HEAD8, // 2174 S_SERPENT_HEAD_X1, // 2175 S_SERPENT_GIB1_1, // 2176 S_SERPENT_GIB1_2, // 2177 S_SERPENT_GIB1_3, // 2178 S_SERPENT_GIB1_4, // 2179 S_SERPENT_GIB1_5, // 2180 S_SERPENT_GIB1_6, // 2181 S_SERPENT_GIB1_7, // 2182 S_SERPENT_GIB1_8, // 2183 S_SERPENT_GIB1_9, // 2184 S_SERPENT_GIB1_10, // 2185 S_SERPENT_GIB1_11, // 2186 S_SERPENT_GIB1_12, // 2187 S_SERPENT_GIB2_1, // 2188 S_SERPENT_GIB2_2, // 2189 S_SERPENT_GIB2_3, // 2190 S_SERPENT_GIB2_4, // 2191 S_SERPENT_GIB2_5, // 2192 S_SERPENT_GIB2_6, // 2193 S_SERPENT_GIB2_7, // 2194 S_SERPENT_GIB2_8, // 2195 S_SERPENT_GIB2_9, // 2196 S_SERPENT_GIB2_10, // 2197 S_SERPENT_GIB2_11, // 2198 S_SERPENT_GIB2_12, // 2199 S_SERPENT_GIB3_1, // 2200 S_SERPENT_GIB3_2, // 2201 S_SERPENT_GIB3_3, // 2202 S_SERPENT_GIB3_4, // 2203 S_SERPENT_GIB3_5, // 2204 S_SERPENT_GIB3_6, // 2205 S_SERPENT_GIB3_7, // 2206 S_SERPENT_GIB3_8, // 2207 S_SERPENT_GIB3_9, // 2208 S_SERPENT_GIB3_10, // 2209 S_SERPENT_GIB3_11, // 2210 S_SERPENT_GIB3_12, // 2211 S_BISHOP_LOOK1, // 2212 S_BISHOP_DECIDE, // 2213 S_BISHOP_BLUR1, // 2214 S_BISHOP_BLUR2, // 2215 S_BISHOP_WALK1, // 2216 S_BISHOP_WALK2, // 2217 S_BISHOP_WALK3, // 2218 S_BISHOP_WALK4, // 2219 S_BISHOP_WALK5, // 2220 S_BISHOP_WALK6, // 2221 S_BISHOP_ATK1, // 2222 S_BISHOP_ATK2, // 2223 S_BISHOP_ATK3, // 2224 S_BISHOP_ATK4, // 2225 S_BISHOP_ATK5, // 2226 S_BISHOP_PAIN1, // 2227 S_BISHOP_PAIN2, // 2228 S_BISHOP_PAIN3, // 2229 S_BISHOP_PAIN4, // 2230 S_BISHOP_PAIN5, // 2231 S_BISHOP_DEATH1, // 2232 S_BISHOP_DEATH2, // 2233 S_BISHOP_DEATH3, // 2234 S_BISHOP_DEATH4, // 2235 S_BISHOP_DEATH5, // 2236 S_BISHOP_DEATH6, // 2237 S_BISHOP_DEATH7, // 2238 S_BISHOP_DEATH8, // 2239 S_BISHOP_DEATH9, // 2240 S_BISHOP_DEATH10, // 2241 S_BISHOP_ICE, // 2242 S_BISHOP_ICE2, // 2243 S_BISHOP_PUFF1, // 2244 S_BISHOP_PUFF2, // 2245 S_BISHOP_PUFF3, // 2246 S_BISHOP_PUFF4, // 2247 S_BISHOP_PUFF5, // 2248 S_BISHOP_PUFF6, // 2249 S_BISHOP_PUFF7, // 2250 S_BISHOPBLUR1, // 2251 S_BISHOPBLUR2, // 2252 S_BISHOPPAINBLUR1, // 2253 S_BISHFX1_1, // 2254 S_BISHFX1_2, // 2255 S_BISHFX1_3, // 2256 S_BISHFX1_4, // 2257 S_BISHFX1_5, // 2258 S_BISHFXI1_1, // 2259 S_BISHFXI1_2, // 2260 S_BISHFXI1_3, // 2261 S_BISHFXI1_4, // 2262 S_BISHFXI1_5, // 2263 S_BISHFXI1_6, // 2264 S_DRAGON_LOOK1, // 2265 S_DRAGON_INIT, // 2266 S_DRAGON_INIT2, // 2267 S_DRAGON_INIT3, // 2268 S_DRAGON_WALK1, // 2269 S_DRAGON_WALK2, // 2270 S_DRAGON_WALK3, // 2271 S_DRAGON_WALK4, // 2272 S_DRAGON_WALK5, // 2273 S_DRAGON_WALK6, // 2274 S_DRAGON_WALK7, // 2275 S_DRAGON_WALK8, // 2276 S_DRAGON_WALK9, // 2277 S_DRAGON_WALK10, // 2278 S_DRAGON_WALK11, // 2279 S_DRAGON_WALK12, // 2280 S_DRAGON_ATK1, // 2281 S_DRAGON_PAIN1, // 2282 S_DRAGON_DEATH1, // 2283 S_DRAGON_DEATH2, // 2284 S_DRAGON_DEATH3, // 2285 S_DRAGON_DEATH4, // 2286 S_DRAGON_CRASH1, // 2287 S_DRAGON_CRASH2, // 2288 S_DRAGON_CRASH3, // 2289 S_DRAGON_FX1_1, // 2290 S_DRAGON_FX1_2, // 2291 S_DRAGON_FX1_3, // 2292 S_DRAGON_FX1_4, // 2293 S_DRAGON_FX1_5, // 2294 S_DRAGON_FX1_6, // 2295 S_DRAGON_FX1_X1, // 2296 S_DRAGON_FX1_X2, // 2297 S_DRAGON_FX1_X3, // 2298 S_DRAGON_FX1_X4, // 2299 S_DRAGON_FX1_X5, // 2300 S_DRAGON_FX1_X6, // 2301 S_DRAGON_FX2_1, // 2302 S_DRAGON_FX2_2, // 2303 S_DRAGON_FX2_3, // 2304 S_DRAGON_FX2_4, // 2305 S_DRAGON_FX2_5, // 2306 S_DRAGON_FX2_6, // 2307 S_DRAGON_FX2_7, // 2308 S_DRAGON_FX2_8, // 2309 S_DRAGON_FX2_9, // 2310 S_DRAGON_FX2_10, // 2311 S_DRAGON_FX2_11, // 2312 S_ARMOR_1, // 2313 S_ARMOR_2, // 2314 S_ARMOR_3, // 2315 S_ARMOR_4, // 2316 S_MANA1_1, // 2317 S_MANA1_2, // 2318 S_MANA1_3, // 2319 S_MANA1_4, // 2320 S_MANA1_5, // 2321 S_MANA1_6, // 2322 S_MANA1_7, // 2323 S_MANA1_8, // 2324 S_MANA1_9, // 2325 S_MANA2_1, // 2326 S_MANA2_2, // 2327 S_MANA2_3, // 2328 S_MANA2_4, // 2329 S_MANA2_5, // 2330 S_MANA2_6, // 2331 S_MANA2_7, // 2332 S_MANA2_8, // 2333 S_MANA2_9, // 2334 S_MANA2_10, // 2335 S_MANA2_11, // 2336 S_MANA2_12, // 2337 S_MANA2_13, // 2338 S_MANA2_14, // 2339 S_MANA2_15, // 2340 S_MANA2_16, // 2341 S_MANA3_1, // 2342 S_MANA3_2, // 2343 S_MANA3_3, // 2344 S_MANA3_4, // 2345 S_MANA3_5, // 2346 S_MANA3_6, // 2347 S_MANA3_7, // 2348 S_MANA3_8, // 2349 S_MANA3_9, // 2350 S_MANA3_10, // 2351 S_MANA3_11, // 2352 S_MANA3_12, // 2353 S_MANA3_13, // 2354 S_MANA3_14, // 2355 S_MANA3_15, // 2356 S_MANA3_16, // 2357 S_KEY1, // 2358 S_KEY2, // 2359 S_KEY3, // 2360 S_KEY4, // 2361 S_KEY5, // 2362 S_KEY6, // 2363 S_KEY7, // 2364 S_KEY8, // 2365 S_KEY9, // 2366 S_KEYA, // 2367 S_KEYB, // 2368 S_SND_WIND1, // 2369 S_SND_WIND2, // 2370 S_SND_WATERFALL, // 2371 S_ETTIN_LOOK1, // 2372 S_ETTIN_LOOK2, // 2373 S_ETTIN_CHASE1, // 2374 S_ETTIN_CHASE2, // 2375 S_ETTIN_CHASE3, // 2376 S_ETTIN_CHASE4, // 2377 S_ETTIN_PAIN1, // 2378 S_ETTIN_ATK1_1, // 2379 S_ETTIN_ATK1_2, // 2380 S_ETTIN_ATK1_3, // 2381 S_ETTIN_DEATH1_1, // 2382 S_ETTIN_DEATH1_2, // 2383 S_ETTIN_DEATH1_3, // 2384 S_ETTIN_DEATH1_4, // 2385 S_ETTIN_DEATH1_5, // 2386 S_ETTIN_DEATH1_6, // 2387 S_ETTIN_DEATH1_7, // 2388 S_ETTIN_DEATH1_8, // 2389 S_ETTIN_DEATH1_9, // 2390 S_ETTIN_DEATH2_1, // 2391 S_ETTIN_DEATH2_2, // 2392 S_ETTIN_DEATH2_3, // 2393 S_ETTIN_DEATH2_4, // 2394 S_ETTIN_DEATH2_5, // 2395 S_ETTIN_DEATH2_6, // 2396 S_ETTIN_DEATH2_7, // 2397 S_ETTIN_DEATH2_8, // 2398 S_ETTIN_DEATH2_9, // 2399 S_ETTIN_DEATH2_0, // 2400 S_ETTIN_DEATH2_A, // 2401 S_ETTIN_DEATH2_B, // 2402 S_ETTIN_ICE1, // 2403 S_ETTIN_ICE2, // 2404 S_ETTIN_MACE1, // 2405 S_ETTIN_MACE2, // 2406 S_ETTIN_MACE3, // 2407 S_ETTIN_MACE4, // 2408 S_ETTIN_MACE5, // 2409 S_ETTIN_MACE6, // 2410 S_ETTIN_MACE7, // 2411 S_FIRED_SPAWN1, // 2412 S_FIRED_LOOK1, // 2413 S_FIRED_LOOK2, // 2414 S_FIRED_LOOK3, // 2415 S_FIRED_LOOK4, // 2416 S_FIRED_LOOK5, // 2417 S_FIRED_LOOK6, // 2418 S_FIRED_LOOK7, // 2419 S_FIRED_LOOK8, // 2420 S_FIRED_LOOK9, // 2421 S_FIRED_LOOK0, // 2422 S_FIRED_LOOKA, // 2423 S_FIRED_LOOKB, // 2424 S_FIRED_WALK1, // 2425 S_FIRED_WALK2, // 2426 S_FIRED_WALK3, // 2427 S_FIRED_PAIN1, // 2428 S_FIRED_ATTACK1, // 2429 S_FIRED_ATTACK2, // 2430 S_FIRED_ATTACK3, // 2431 S_FIRED_ATTACK4, // 2432 S_FIRED_DEATH1, // 2433 S_FIRED_DEATH2, // 2434 S_FIRED_DEATH3, // 2435 S_FIRED_DEATH4, // 2436 S_FIRED_XDEATH1, // 2437 S_FIRED_XDEATH2, // 2438 S_FIRED_XDEATH3, // 2439 S_FIRED_ICE1, // 2440 S_FIRED_ICE2, // 2441 S_FIRED_CORPSE1, // 2442 S_FIRED_CORPSE2, // 2443 S_FIRED_CORPSE3, // 2444 S_FIRED_CORPSE4, // 2445 S_FIRED_CORPSE5, // 2446 S_FIRED_CORPSE6, // 2447 S_FIRED_RDROP1, // 2448 S_FIRED_RDEAD1_1, // 2449 S_FIRED_RDEAD1_2, // 2450 S_FIRED_RDROP2, // 2451 S_FIRED_RDEAD2_1, // 2452 S_FIRED_RDEAD2_2, // 2453 S_FIRED_RDROP3, // 2454 S_FIRED_RDEAD3_1, // 2455 S_FIRED_RDEAD3_2, // 2456 S_FIRED_RDROP4, // 2457 S_FIRED_RDEAD4_1, // 2458 S_FIRED_RDEAD4_2, // 2459 S_FIRED_RDROP5, // 2460 S_FIRED_RDEAD5_1, // 2461 S_FIRED_RDEAD5_2, // 2462 S_FIRED_FX6_1, // 2463 S_FIRED_FX6_2, // 2464 S_FIRED_FX6_3, // 2465 S_FIRED_FX6_4, // 2466 S_FIRED_FX6_5, // 2467 S_ICEGUY_LOOK, // 2468 S_ICEGUY_DORMANT, // 2469 S_ICEGUY_WALK1, // 2470 S_ICEGUY_WALK2, // 2471 S_ICEGUY_WALK3, // 2472 S_ICEGUY_WALK4, // 2473 S_ICEGUY_ATK1, // 2474 S_ICEGUY_ATK2, // 2475 S_ICEGUY_ATK3, // 2476 S_ICEGUY_ATK4, // 2477 S_ICEGUY_PAIN1, // 2478 S_ICEGUY_DEATH, // 2479 S_ICEGUY_FX1, // 2480 S_ICEGUY_FX2, // 2481 S_ICEGUY_FX3, // 2482 S_ICEGUY_FX_X1, // 2483 S_ICEGUY_FX_X2, // 2484 S_ICEGUY_FX_X3, // 2485 S_ICEGUY_FX_X4, // 2486 S_ICEGUY_FX_X5, // 2487 S_ICEFX_PUFF1, // 2488 S_ICEFX_PUFF2, // 2489 S_ICEFX_PUFF3, // 2490 S_ICEFX_PUFF4, // 2491 S_ICEFX_PUFF5, // 2492 S_ICEGUY_FX2_1, // 2493 S_ICEGUY_FX2_2, // 2494 S_ICEGUY_FX2_3, // 2495 S_ICEGUY_BIT1, // 2496 S_ICEGUY_BIT2, // 2497 S_ICEGUY_WISP1_1, // 2498 S_ICEGUY_WISP1_2, // 2499 S_ICEGUY_WISP1_3, // 2500 S_ICEGUY_WISP1_4, // 2501 S_ICEGUY_WISP1_5, // 2502 S_ICEGUY_WISP1_6, // 2503 S_ICEGUY_WISP1_7, // 2504 S_ICEGUY_WISP1_8, // 2505 S_ICEGUY_WISP1_9, // 2506 S_ICEGUY_WISP2_1, // 2507 S_ICEGUY_WISP2_2, // 2508 S_ICEGUY_WISP2_3, // 2509 S_ICEGUY_WISP2_4, // 2510 S_ICEGUY_WISP2_5, // 2511 S_ICEGUY_WISP2_6, // 2512 S_ICEGUY_WISP2_7, // 2513 S_ICEGUY_WISP2_8, // 2514 S_ICEGUY_WISP2_9, // 2515 S_FIGHTER, // 2516 S_FIGHTER2, // 2517 S_FIGHTERLOOK, // 2518 S_FIGHTER_RUN1, // 2519 S_FIGHTER_RUN2, // 2520 S_FIGHTER_RUN3, // 2521 S_FIGHTER_RUN4, // 2522 S_FIGHTER_ATK1, // 2523 S_FIGHTER_ATK2, // 2524 S_FIGHTER_PAIN, // 2525 S_FIGHTER_PAIN2, // 2526 S_FIGHTER_DIE1, // 2527 S_FIGHTER_DIE2, // 2528 S_FIGHTER_DIE3, // 2529 S_FIGHTER_DIE4, // 2530 S_FIGHTER_DIE5, // 2531 S_FIGHTER_DIE6, // 2532 S_FIGHTER_DIE7, // 2533 S_FIGHTER_XDIE1, // 2534 S_FIGHTER_XDIE2, // 2535 S_FIGHTER_XDIE3, // 2536 S_FIGHTER_XDIE4, // 2537 S_FIGHTER_XDIE5, // 2538 S_FIGHTER_XDIE6, // 2539 S_FIGHTER_XDIE7, // 2540 S_FIGHTER_XDIE8, // 2541 S_FIGHTER_ICE, // 2542 S_FIGHTER_ICE2, // 2543 S_CLERIC, // 2544 S_CLERIC2, // 2545 S_CLERICLOOK, // 2546 S_CLERIC_RUN1, // 2547 S_CLERIC_RUN2, // 2548 S_CLERIC_RUN3, // 2549 S_CLERIC_RUN4, // 2550 S_CLERIC_ATK1, // 2551 S_CLERIC_ATK2, // 2552 S_CLERIC_ATK3, // 2553 S_CLERIC_PAIN, // 2554 S_CLERIC_PAIN2, // 2555 S_CLERIC_DIE1, // 2556 S_CLERIC_DIE2, // 2557 S_CLERIC_DIE3, // 2558 S_CLERIC_DIE4, // 2559 S_CLERIC_DIE5, // 2560 S_CLERIC_DIE6, // 2561 S_CLERIC_DIE7, // 2562 S_CLERIC_DIE8, // 2563 S_CLERIC_DIE9, // 2564 S_CLERIC_XDIE1, // 2565 S_CLERIC_XDIE2, // 2566 S_CLERIC_XDIE3, // 2567 S_CLERIC_XDIE4, // 2568 S_CLERIC_XDIE5, // 2569 S_CLERIC_XDIE6, // 2570 S_CLERIC_XDIE7, // 2571 S_CLERIC_XDIE8, // 2572 S_CLERIC_XDIE9, // 2573 S_CLERIC_XDIE10, // 2574 S_CLERIC_ICE, // 2575 S_CLERIC_ICE2, // 2576 S_MAGE, // 2577 S_MAGE2, // 2578 S_MAGELOOK, // 2579 S_MAGE_RUN1, // 2580 S_MAGE_RUN2, // 2581 S_MAGE_RUN3, // 2582 S_MAGE_RUN4, // 2583 S_MAGE_ATK1, // 2584 S_MAGE_ATK2, // 2585 S_MAGE_PAIN, // 2586 S_MAGE_PAIN2, // 2587 S_MAGE_DIE1, // 2588 S_MAGE_DIE2, // 2589 S_MAGE_DIE3, // 2590 S_MAGE_DIE4, // 2591 S_MAGE_DIE5, // 2592 S_MAGE_DIE6, // 2593 S_MAGE_DIE7, // 2594 S_MAGE_XDIE1, // 2595 S_MAGE_XDIE2, // 2596 S_MAGE_XDIE3, // 2597 S_MAGE_XDIE4, // 2598 S_MAGE_XDIE5, // 2599 S_MAGE_XDIE6, // 2600 S_MAGE_XDIE7, // 2601 S_MAGE_XDIE8, // 2602 S_MAGE_XDIE9, // 2603 S_MAGE_ICE, // 2604 S_MAGE_ICE2, // 2605 S_SORC_SPAWN1, // 2606 S_SORC_SPAWN2, // 2607 S_SORC_LOOK1, // 2608 S_SORC_WALK1, // 2609 S_SORC_WALK2, // 2610 S_SORC_WALK3, // 2611 S_SORC_WALK4, // 2612 S_SORC_PAIN1, // 2613 S_SORC_PAIN2, // 2614 S_SORC_ATK2_1, // 2615 S_SORC_ATK2_2, // 2616 S_SORC_ATK2_3, // 2617 S_SORC_ATTACK1, // 2618 S_SORC_ATTACK2, // 2619 S_SORC_ATTACK3, // 2620 S_SORC_ATTACK4, // 2621 S_SORC_ATTACK5, // 2622 S_SORC_DIE1, // 2623 S_SORC_DIE2, // 2624 S_SORC_DIE3, // 2625 S_SORC_DIE4, // 2626 S_SORC_DIE5, // 2627 S_SORC_DIE6, // 2628 S_SORC_DIE7, // 2629 S_SORC_DIE8, // 2630 S_SORC_DIE9, // 2631 S_SORC_DIE0, // 2632 S_SORC_DIEA, // 2633 S_SORC_DIEB, // 2634 S_SORC_DIEC, // 2635 S_SORC_DIED, // 2636 S_SORC_DIEE, // 2637 S_SORC_DIEF, // 2638 S_SORC_DIEG, // 2639 S_SORC_DIEH, // 2640 S_SORC_DIEI, // 2641 S_SORCBALL1_1, // 2642 S_SORCBALL1_2, // 2643 S_SORCBALL1_3, // 2644 S_SORCBALL1_4, // 2645 S_SORCBALL1_5, // 2646 S_SORCBALL1_6, // 2647 S_SORCBALL1_7, // 2648 S_SORCBALL1_8, // 2649 S_SORCBALL1_9, // 2650 S_SORCBALL1_0, // 2651 S_SORCBALL1_A, // 2652 S_SORCBALL1_B, // 2653 S_SORCBALL1_C, // 2654 S_SORCBALL1_D, // 2655 S_SORCBALL1_E, // 2656 S_SORCBALL1_F, // 2657 S_SORCBALL1_D1, // 2658 S_SORCBALL1_D2, // 2659 S_SORCBALL1_D5, // 2660 S_SORCBALL1_D6, // 2661 S_SORCBALL1_D7, // 2662 S_SORCBALL1_D8, // 2663 S_SORCBALL1_D9, // 2664 S_SORCBALL2_1, // 2665 S_SORCBALL2_2, // 2666 S_SORCBALL2_3, // 2667 S_SORCBALL2_4, // 2668 S_SORCBALL2_5, // 2669 S_SORCBALL2_6, // 2670 S_SORCBALL2_7, // 2671 S_SORCBALL2_8, // 2672 S_SORCBALL2_9, // 2673 S_SORCBALL2_0, // 2674 S_SORCBALL2_A, // 2675 S_SORCBALL2_B, // 2676 S_SORCBALL2_C, // 2677 S_SORCBALL2_D, // 2678 S_SORCBALL2_E, // 2679 S_SORCBALL2_F, // 2680 S_SORCBALL2_D1, // 2681 S_SORCBALL2_D2, // 2682 S_SORCBALL2_D5, // 2683 S_SORCBALL2_D6, // 2684 S_SORCBALL2_D7, // 2685 S_SORCBALL2_D8, // 2686 S_SORCBALL2_D9, // 2687 S_SORCBALL3_1, // 2688 S_SORCBALL3_2, // 2689 S_SORCBALL3_3, // 2690 S_SORCBALL3_4, // 2691 S_SORCBALL3_5, // 2692 S_SORCBALL3_6, // 2693 S_SORCBALL3_7, // 2694 S_SORCBALL3_8, // 2695 S_SORCBALL3_9, // 2696 S_SORCBALL3_0, // 2697 S_SORCBALL3_A, // 2698 S_SORCBALL3_B, // 2699 S_SORCBALL3_C, // 2700 S_SORCBALL3_D, // 2701 S_SORCBALL3_E, // 2702 S_SORCBALL3_F, // 2703 S_SORCBALL3_D1, // 2704 S_SORCBALL3_D2, // 2705 S_SORCBALL3_D5, // 2706 S_SORCBALL3_D6, // 2707 S_SORCBALL3_D7, // 2708 S_SORCBALL3_D8, // 2709 S_SORCBALL3_D9, // 2710 S_SORCFX1_1, // 2711 S_SORCFX1_2, // 2712 S_SORCFX1_3, // 2713 S_SORCFX1_4, // 2714 S_SORCFX1_D1, // 2715 S_SORCFX1_D2, // 2716 S_SORCFX1_D3, // 2717 S_SORCFX2_SPLIT1, // 2718 S_SORCFX2_ORBIT1, // 2719 S_SORCFX2_ORBIT2, // 2720 S_SORCFX2_ORBIT3, // 2721 S_SORCFX2_ORBIT4, // 2722 S_SORCFX2_ORBIT5, // 2723 S_SORCFX2_ORBIT6, // 2724 S_SORCFX2_ORBIT7, // 2725 S_SORCFX2_ORBIT8, // 2726 S_SORCFX2_ORBIT9, // 2727 S_SORCFX2_ORBIT0, // 2728 S_SORCFX2_ORBITA, // 2729 S_SORCFX2_ORBITB, // 2730 S_SORCFX2_ORBITC, // 2731 S_SORCFX2_ORBITD, // 2732 S_SORCFX2_ORBITE, // 2733 S_SORCFX2_ORBITF, // 2734 S_SORCFX2T1, // 2735 S_SORCFX3_1, // 2736 S_SORCFX3_2, // 2737 S_SORCFX3_3, // 2738 S_BISHMORPH1, // 2739 S_BISHMORPHA, // 2740 S_BISHMORPHB, // 2741 S_BISHMORPHC, // 2742 S_BISHMORPHD, // 2743 S_BISHMORPHE, // 2744 S_BISHMORPHF, // 2745 S_BISHMORPHG, // 2746 S_BISHMORPHH, // 2747 S_BISHMORPHI, // 2748 S_BISHMORPHJ, // 2749 S_SORCFX3_EXP1, // 2750 S_SORCFX3_EXP2, // 2751 S_SORCFX3_EXP3, // 2752 S_SORCFX3_EXP4, // 2753 S_SORCFX3_EXP5, // 2754 S_SORCFX4_1, // 2755 S_SORCFX4_2, // 2756 S_SORCFX4_3, // 2757 S_SORCFX4_D1, // 2758 S_SORCFX4_D2, // 2759 S_SORCFX4_D3, // 2760 S_SORCFX4_D4, // 2761 S_SORCFX4_D5, // 2762 S_SORCSPARK1, // 2763 S_SORCSPARK2, // 2764 S_SORCSPARK3, // 2765 S_SORCSPARK4, // 2766 S_SORCSPARK5, // 2767 S_SORCSPARK6, // 2768 S_SORCSPARK7, // 2769 S_BLASTEFFECT1, // 2770 S_BLASTEFFECT2, // 2771 S_BLASTEFFECT3, // 2772 S_BLASTEFFECT4, // 2773 S_BLASTEFFECT5, // 2774 S_BLASTEFFECT6, // 2775 S_BLASTEFFECT7, // 2776 S_BLASTEFFECT8, // 2777 S_BLASTEFFECT9, // 2778 S_WATERDRIP1, // 2779 S_KORAX_LOOK1, // 2780 S_KORAX_CHASE1, // 2781 S_KORAX_CHASE2, // 2782 S_KORAX_CHASE3, // 2783 S_KORAX_CHASE4, // 2784 S_KORAX_CHASE5, // 2785 S_KORAX_CHASE6, // 2786 S_KORAX_CHASE7, // 2787 S_KORAX_CHASE8, // 2788 S_KORAX_CHASE9, // 2789 S_KORAX_CHASE0, // 2790 S_KORAX_CHASEA, // 2791 S_KORAX_CHASEB, // 2792 S_KORAX_CHASEC, // 2793 S_KORAX_CHASED, // 2794 S_KORAX_CHASEE, // 2795 S_KORAX_CHASEF, // 2796 S_KORAX_PAIN1, // 2797 S_KORAX_PAIN2, // 2798 S_KORAX_ATTACK1, // 2799 S_KORAX_ATTACK2, // 2800 S_KORAX_MISSILE1, // 2801 S_KORAX_MISSILE2, // 2802 S_KORAX_MISSILE3, // 2803 S_KORAX_COMMAND1, // 2804 S_KORAX_COMMAND2, // 2805 S_KORAX_COMMAND3, // 2806 S_KORAX_COMMAND4, // 2807 S_KORAX_COMMAND5, // 2808 S_KORAX_DEATH1, // 2809 S_KORAX_DEATH2, // 2810 S_KORAX_DEATH3, // 2811 S_KORAX_DEATH4, // 2812 S_KORAX_DEATH5, // 2813 S_KORAX_DEATH6, // 2814 S_KORAX_DEATH7, // 2815 S_KORAX_DEATH8, // 2816 S_KORAX_DEATH9, // 2817 S_KORAX_DEATH0, // 2818 S_KORAX_DEATHA, // 2819 S_KORAX_DEATHB, // 2820 S_KORAX_DEATHC, // 2821 S_KORAX_DEATHD, // 2822 S_KSPIRIT_ROAM1, // 2823 S_KSPIRIT_ROAM2, // 2824 S_KSPIRIT_DEATH1, // 2825 S_KSPIRIT_DEATH2, // 2826 S_KSPIRIT_DEATH3, // 2827 S_KSPIRIT_DEATH4, // 2828 S_KSPIRIT_DEATH5, // 2829 S_KSPIRIT_DEATH6, // 2830 S_KBOLT1, // 2831 S_KBOLT2, // 2832 S_KBOLT3, // 2833 S_KBOLT4, // 2834 S_KBOLT5, // 2835 S_KBOLT6, // 2836 S_KBOLT7, // 2837 S_SPAWNBATS1, // 2838 S_SPAWNBATS2, // 2839 S_SPAWNBATS3, // 2840 S_SPAWNBATS_OFF, // 2841 S_BAT1, // 2842 S_BAT2, // 2843 S_BAT3, // 2844 S_BAT_DEATH, // 2845 S_CAMERA, // 2846 S_TEMPSOUNDORIGIN1, // 2847 NUMSTATES // 2848 } statenum_t; // Map objects. typedef enum { MT_NONE = -1, MT_FIRST = 0, MT_MAPSPOT = MT_FIRST, // 000 MT_MAPSPOTGRAVITY, // 001 MT_FIREBALL1, // 002 MT_ARROW, // 003 MT_DART, // 004 MT_POISONDART, // 005 MT_RIPPERBALL, // 006 MT_PROJECTILE_BLADE, // 007 MT_ICESHARD, // 008 MT_FLAME_SMALL_TEMP, // 009 MT_FLAME_LARGE_TEMP, // 010 MT_FLAME_SMALL, // 011 MT_FLAME_LARGE, // 012 MT_HEALINGBOTTLE, // 013 MT_HEALTHFLASK, // 014 MT_ARTIFLY, // 015 MT_ARTIINVULNERABILITY, // 016 MT_SUMMONMAULATOR, // 017 MT_SUMMON_FX, // 018 MT_THRUSTFLOOR_UP, // 019 MT_THRUSTFLOOR_DOWN, // 020 MT_TELEPORTOTHER, // 021 MT_TELOTHER_FX1, // 022 MT_TELOTHER_FX2, // 023 MT_TELOTHER_FX3, // 024 MT_TELOTHER_FX4, // 025 MT_TELOTHER_FX5, // 026 MT_DIRT1, // 027 MT_DIRT2, // 028 MT_DIRT3, // 029 MT_DIRT4, // 030 MT_DIRT5, // 031 MT_DIRT6, // 032 MT_DIRTCLUMP, // 033 MT_ROCK1, // 034 MT_ROCK2, // 035 MT_ROCK3, // 036 MT_FOGSPAWNER, // 037 MT_FOGPATCHS, // 038 MT_FOGPATCHM, // 039 MT_FOGPATCHL, // 040 MT_QUAKE_FOCUS, // 041 MT_SGSHARD1, // 042 MT_SGSHARD2, // 043 MT_SGSHARD3, // 044 MT_SGSHARD4, // 045 MT_SGSHARD5, // 046 MT_SGSHARD6, // 047 MT_SGSHARD7, // 048 MT_SGSHARD8, // 049 MT_SGSHARD9, // 050 MT_SGSHARD0, // 051 MT_ARTIEGG, // 052 MT_EGGFX, // 053 MT_ARTISUPERHEAL, // 054 MT_ZWINGEDSTATUENOSKULL, // 055 MT_ZGEMPEDESTAL, // 056 MT_ARTIPUZZSKULL, // 057 MT_ARTIPUZZGEMBIG, // 058 MT_ARTIPUZZGEMRED, // 059 MT_ARTIPUZZGEMGREEN1, // 060 MT_ARTIPUZZGEMGREEN2, // 061 MT_ARTIPUZZGEMBLUE1, // 062 MT_ARTIPUZZGEMBLUE2, // 063 MT_ARTIPUZZBOOK1, // 064 MT_ARTIPUZZBOOK2, // 065 MT_ARTIPUZZSKULL2, // 066 MT_ARTIPUZZFWEAPON, // 067 MT_ARTIPUZZCWEAPON, // 068 MT_ARTIPUZZMWEAPON, // 069 MT_ARTIPUZZGEAR, // 070 MT_ARTIPUZZGEAR2, // 071 MT_ARTIPUZZGEAR3, // 072 MT_ARTIPUZZGEAR4, // 073 MT_ARTITORCH, // 074 MT_FIREBOMB, // 075 MT_ARTITELEPORT, // 076 MT_ARTIPOISONBAG, // 077 MT_POISONBAG, // 078 MT_POISONCLOUD, // 079 MT_THROWINGBOMB, // 080 MT_SPEEDBOOTS, // 081 MT_BOOSTMANA, // 082 MT_BOOSTARMOR, // 083 MT_BLASTRADIUS, // 084 MT_HEALRADIUS, // 085 MT_SPLASH, // 086 MT_SPLASHBASE, // 087 MT_LAVASPLASH, // 088 MT_LAVASMOKE, // 089 MT_SLUDGECHUNK, // 090 MT_SLUDGESPLASH, // 091 MT_MISC0, // 092 MT_MISC1, // 093 MT_MISC2, // 094 MT_MISC3, // 095 MT_MISC4, // 096 MT_MISC5, // 097 MT_MISC6, // 098 MT_MISC7, // 099 MT_MISC8, // 100 MT_TREEDESTRUCTIBLE, // 101 MT_MISC9, // 102 MT_MISC10, // 103 MT_MISC11, // 104 MT_MISC12, // 105 MT_MISC13, // 106 MT_MISC14, // 107 MT_MISC15, // 108 MT_MISC16, // 109 MT_MISC17, // 110 MT_MISC18, // 111 MT_MISC19, // 112 MT_MISC20, // 113 MT_MISC21, // 114 MT_MISC22, // 115 MT_MISC23, // 116 MT_MISC24, // 117 MT_MISC25, // 118 MT_MISC26, // 119 MT_MISC27, // 120 MT_MISC28, // 121 MT_MISC29, // 122 MT_MISC30, // 123 MT_MISC31, // 124 MT_MISC32, // 125 MT_MISC33, // 126 MT_MISC34, // 127 MT_MISC35, // 128 MT_MISC36, // 129 MT_MISC37, // 130 MT_MISC38, // 131 MT_MISC39, // 132 MT_MISC40, // 133 MT_MISC41, // 134 MT_MISC42, // 135 MT_MISC43, // 136 MT_MISC44, // 137 MT_MISC45, // 138 MT_MISC46, // 139 MT_MISC47, // 140 MT_MISC48, // 141 MT_MISC49, // 142 MT_MISC50, // 143 MT_MISC51, // 144 MT_MISC52, // 145 MT_MISC53, // 146 MT_MISC54, // 147 MT_MISC55, // 148 MT_MISC56, // 149 MT_MISC57, // 150 MT_MISC58, // 151 MT_MISC59, // 152 MT_MISC60, // 153 MT_MISC61, // 154 MT_MISC62, // 155 MT_MISC63, // 156 MT_MISC64, // 157 MT_MISC65, // 158 MT_MISC66, // 159 MT_MISC67, // 160 MT_MISC68, // 161 MT_MISC69, // 162 MT_MISC70, // 163 MT_MISC71, // 164 MT_MISC72, // 165 MT_MISC73, // 166 MT_MISC74, // 167 MT_MISC75, // 168 MT_MISC76, // 169 MT_POTTERY1, // 170 MT_POTTERY2, // 171 MT_POTTERY3, // 172 MT_POTTERYBIT1, // 173 MT_MISC77, // 174 MT_ZLYNCHED_NOHEART, // 175 MT_MISC78, // 176 MT_CORPSEBIT, // 177 MT_CORPSEBLOODDRIP, // 178 MT_BLOODPOOL, // 179 MT_MISC79, // 180 MT_MISC80, // 181 MT_LEAF1, // 182 MT_LEAF2, // 183 MT_ZTWINEDTORCH, // 184 MT_ZTWINEDTORCH_UNLIT, // 185 MT_BRIDGE, // 186 MT_BRIDGEBALL, // 187 MT_ZWALLTORCH, // 188 MT_ZWALLTORCH_UNLIT, // 189 MT_ZBARREL, // 190 MT_ZSHRUB1, // 191 MT_ZSHRUB2, // 192 MT_ZBUCKET, // 193 MT_ZPOISONSHROOM, // 194 MT_ZFIREBULL, // 195 MT_ZFIREBULL_UNLIT, // 196 MT_FIRETHING, // 197 MT_BRASSTORCH, // 198 MT_ZSUITOFARMOR, // 199 MT_ZARMORCHUNK, // 200 MT_ZBELL, // 201 MT_ZBLUE_CANDLE, // 202 MT_ZIRON_MAIDEN, // 203 MT_ZXMAS_TREE, // 204 MT_ZCAULDRON, // 205 MT_ZCAULDRON_UNLIT, // 206 MT_ZCHAINBIT32, // 207 MT_ZCHAINBIT64, // 208 MT_ZCHAINEND_HEART, // 209 MT_ZCHAINEND_HOOK1, // 210 MT_ZCHAINEND_HOOK2, // 211 MT_ZCHAINEND_SPIKE, // 212 MT_ZCHAINEND_SKULL, // 213 MT_TABLE_SHIT1, // 214 MT_TABLE_SHIT2, // 215 MT_TABLE_SHIT3, // 216 MT_TABLE_SHIT4, // 217 MT_TABLE_SHIT5, // 218 MT_TABLE_SHIT6, // 219 MT_TABLE_SHIT7, // 220 MT_TABLE_SHIT8, // 221 MT_TABLE_SHIT9, // 222 MT_TABLE_SHIT10, // 223 MT_TFOG, // 224 MT_MISC81, // 225 MT_TELEPORTMAN, // 226 MT_PUNCHPUFF, // 227 MT_FW_AXE, // 228 MT_AXEPUFF, // 229 MT_AXEPUFF_GLOW, // 230 MT_AXEBLOOD, // 231 MT_FW_HAMMER, // 232 MT_HAMMER_MISSILE, // 233 MT_HAMMERPUFF, // 234 MT_FSWORD_MISSILE, // 235 MT_FSWORD_FLAME, // 236 MT_CW_SERPSTAFF, // 237 MT_CSTAFF_MISSILE, // 238 MT_CSTAFFPUFF, // 239 MT_CW_FLAME, // 240 MT_CFLAMEFLOOR, // 241 MT_FLAMEPUFF, // 242 MT_FLAMEPUFF2, // 243 MT_CIRCLEFLAME, // 244 MT_CFLAME_MISSILE, // 245 MT_HOLY_FX, // 246 MT_HOLY_TAIL, // 247 MT_HOLY_PUFF, // 248 MT_HOLY_MISSILE, // 249 MT_HOLY_MISSILE_PUFF, // 250 MT_MWANDPUFF, // 251 MT_MWANDSMOKE, // 252 MT_MWAND_MISSILE, // 253 MT_MW_LIGHTNING, // 254 MT_LIGHTNING_CEILING, // 255 MT_LIGHTNING_FLOOR, // 256 MT_LIGHTNING_ZAP, // 257 MT_MSTAFF_FX, // 258 MT_MSTAFF_FX2, // 259 MT_FW_SWORD1, // 260 MT_FW_SWORD2, // 261 MT_FW_SWORD3, // 262 MT_CW_HOLY1, // 263 MT_CW_HOLY2, // 264 MT_CW_HOLY3, // 265 MT_MW_STAFF1, // 266 MT_MW_STAFF2, // 267 MT_MW_STAFF3, // 268 MT_SNOUTPUFF, // 269 MT_MW_CONE, // 270 MT_SHARDFX1, // 271 MT_BLOOD, // 272 MT_BLOODSPLATTER, // 273 MT_GIBS, // 274 MT_PLAYER_FIGHTER, // 275 MT_BLOODYSKULL, // 276 MT_PLAYER_SPEED, // 277 MT_ICECHUNK, // 278 MT_PLAYER_CLERIC, // 279 MT_PLAYER_MAGE, // 280 MT_PIGPLAYER, // 281 MT_PIG, // 282 MT_CENTAUR, // 283 MT_CENTAURLEADER, // 284 MT_CENTAUR_FX, // 285 MT_CENTAUR_SHIELD, // 286 MT_CENTAUR_SWORD, // 287 MT_DEMON, // 288 MT_DEMONCHUNK1, // 289 MT_DEMONCHUNK2, // 290 MT_DEMONCHUNK3, // 291 MT_DEMONCHUNK4, // 292 MT_DEMONCHUNK5, // 293 MT_DEMONFX1, // 294 MT_DEMON2, // 295 MT_DEMON2CHUNK1, // 296 MT_DEMON2CHUNK2, // 297 MT_DEMON2CHUNK3, // 298 MT_DEMON2CHUNK4, // 299 MT_DEMON2CHUNK5, // 300 MT_DEMON2FX1, // 301 MT_WRAITHB, // 302 MT_WRAITH, // 303 MT_WRAITHFX1, // 304 MT_WRAITHFX2, // 305 MT_WRAITHFX3, // 306 MT_WRAITHFX4, // 307 MT_WRAITHFX5, // 308 MT_MINOTAUR, // 309 MT_MNTRFX1, // 310 MT_MNTRFX2, // 311 MT_MNTRFX3, // 312 MT_MNTRSMOKE, // 313 MT_MNTRSMOKEEXIT, // 314 MT_SERPENT, // 315 MT_SERPENTLEADER, // 316 MT_SERPENTFX, // 317 MT_SERPENT_HEAD, // 318 MT_SERPENT_GIB1, // 319 MT_SERPENT_GIB2, // 320 MT_SERPENT_GIB3, // 321 MT_BISHOP, // 322 MT_BISHOP_PUFF, // 323 MT_BISHOPBLUR, // 324 MT_BISHOPPAINBLUR, // 325 MT_BISH_FX, // 326 MT_DRAGON, // 327 MT_DRAGON_FX, // 328 MT_DRAGON_FX2, // 329 MT_ARMOR_1, // 330 MT_ARMOR_2, // 331 MT_ARMOR_3, // 332 MT_ARMOR_4, // 333 MT_MANA1, // 334 MT_MANA2, // 335 MT_MANA3, // 336 MT_KEY1, // 337 MT_KEY2, // 338 MT_KEY3, // 339 MT_KEY4, // 340 MT_KEY5, // 341 MT_KEY6, // 342 MT_KEY7, // 343 MT_KEY8, // 344 MT_KEY9, // 345 MT_KEYA, // 346 MT_KEYB, // 347 MT_SOUNDWIND, // 348 MT_SOUNDWATERFALL, // 349 MT_ETTIN, // 350 MT_ETTIN_MACE, // 351 MT_FIREDEMON, // 352 MT_FIREDEMON_SPLOTCH1, // 353 MT_FIREDEMON_SPLOTCH2, // 354 MT_FIREDEMON_FX1, // 355 MT_FIREDEMON_FX2, // 356 MT_FIREDEMON_FX3, // 357 MT_FIREDEMON_FX4, // 358 MT_FIREDEMON_FX5, // 359 MT_FIREDEMON_FX6, // 360 MT_ICEGUY, // 361 MT_ICEGUY_FX, // 362 MT_ICEFX_PUFF, // 363 MT_ICEGUY_FX2, // 364 MT_ICEGUY_BIT, // 365 MT_ICEGUY_WISP1, // 366 MT_ICEGUY_WISP2, // 367 MT_FIGHTER_BOSS, // 368 MT_CLERIC_BOSS, // 369 MT_MAGE_BOSS, // 370 MT_SORCBOSS, // 371 MT_SORCBALL1, // 372 MT_SORCBALL2, // 373 MT_SORCBALL3, // 374 MT_SORCFX1, // 375 MT_SORCFX2, // 376 MT_SORCFX2_T1, // 377 MT_SORCFX3, // 378 MT_SORCFX3_EXPLOSION, // 379 MT_SORCFX4, // 380 MT_SORCSPARK1, // 381 MT_BLASTEFFECT, // 382 MT_WATER_DRIP, // 383 MT_KORAX, // 384 MT_KORAX_SPIRIT1, // 385 MT_KORAX_SPIRIT2, // 386 MT_KORAX_SPIRIT3, // 387 MT_KORAX_SPIRIT4, // 388 MT_KORAX_SPIRIT5, // 389 MT_KORAX_SPIRIT6, // 390 MT_DEMON_MASH, // 391 MT_DEMON2_MASH, // 392 MT_ETTIN_MASH, // 393 MT_CENTAUR_MASH, // 394 MT_KORAX_BOLT, // 395 MT_BAT_SPAWNER, // 396 MT_BAT, // 397 MT_CAMERA, // 398 MT_TEMPSOUNDORIGIN, // 399 NUMMOBJTYPES // 400 } mobjtype_t; // Text. typedef enum { TXT_PRESSKEY, TXT_PRESSYN, TXT_TXT_PAUSED, TXT_QUITMSG, TXT_LOADNET, TXT_QLOADNET, TXT_QSAVESPOT, TXT_SAVEDEAD, TXT_QSPROMPT, TXT_QLPROMPT, TXT_NEWGAME, TXT_MSGOFF, TXT_MSGON, TXT_NETEND, TXT_ENDGAME, TXT_DOSY, TXT_TXT_GAMMA_LEVEL_OFF, TXT_TXT_GAMMA_LEVEL_1, TXT_TXT_GAMMA_LEVEL_2, TXT_TXT_GAMMA_LEVEL_3, TXT_TXT_GAMMA_LEVEL_4, TXT_EMPTYSTRING, TXT_TXT_MANA_1, TXT_TXT_MANA_2, TXT_TXT_MANA_BOTH, TXT_TXT_KEY_STEEL, TXT_TXT_KEY_CAVE, TXT_TXT_KEY_AXE, TXT_TXT_KEY_FIRE, TXT_TXT_KEY_EMERALD, TXT_TXT_KEY_DUNGEON, TXT_TXT_KEY_SILVER, TXT_TXT_KEY_RUSTED, TXT_TXT_KEY_HORN, TXT_TXT_KEY_SWAMP, TXT_TXT_KEY_CASTLE, TXT_TXT_INV_INVULNERABILITY, TXT_TXT_INV_HEALTH, TXT_TXT_INV_SUPERHEALTH, TXT_TXT_INV_SUMMON, TXT_TXT_INV_TORCH, TXT_TXT_INV_EGG, TXT_TXT_INV_FLY, TXT_TXT_INV_TELEPORT, TXT_TXT_INV_POISONBAG, TXT_TXT_INV_TELEPORTOTHER, TXT_TXT_INV_SPEED, TXT_TXT_INV_BOOSTMANA, TXT_TXT_INV_BOOSTARMOR, TXT_TXT_INV_BLASTRADIUS, TXT_TXT_INV_HEALINGRADIUS, TXT_TXT_INV_PUZZSKULL, TXT_TXT_INV_PUZZGEMBIG, TXT_TXT_INV_PUZZGEMRED, TXT_TXT_INV_PUZZGEMGREEN1, TXT_TXT_INV_PUZZGEMGREEN2, TXT_TXT_INV_PUZZGEMBLUE1, TXT_TXT_INV_PUZZGEMBLUE2, TXT_TXT_INV_PUZZBOOK1, TXT_TXT_INV_PUZZBOOK2, TXT_TXT_INV_PUZZSKULL2, TXT_TXT_INV_PUZZFWEAPON, TXT_TXT_INV_PUZZCWEAPON, TXT_TXT_INV_PUZZMWEAPON, TXT_TXT_INV_PUZZGEAR1, TXT_TXT_INV_PUZZGEAR2, TXT_TXT_INV_PUZZGEAR3, TXT_TXT_INV_PUZZGEAR4, TXT_TXT_USEPUZZLEFAILED, TXT_TXT_ITEMHEALTH, TXT_TXT_ITEMBAGOFHOLDING, TXT_TXT_ITEMSHIELD1, TXT_TXT_ITEMSHIELD2, TXT_TXT_ITEMSUPERMAP, TXT_TXT_ARMOR1, TXT_TXT_ARMOR2, TXT_TXT_ARMOR3, TXT_TXT_ARMOR4, TXT_TXT_WEAPON_F2, TXT_TXT_WEAPON_F3, TXT_TXT_WEAPON_F4, TXT_TXT_WEAPON_C2, TXT_TXT_WEAPON_C3, TXT_TXT_WEAPON_C4, TXT_TXT_WEAPON_M2, TXT_TXT_WEAPON_M3, TXT_TXT_WEAPON_M4, TXT_TXT_QUIETUS_PIECE, TXT_TXT_WRAITHVERGE_PIECE, TXT_TXT_BLOODSCOURGE_PIECE, TXT_TXT_CHEATGODON, TXT_TXT_CHEATGODOFF, TXT_TXT_CHEATNOCLIPON, TXT_TXT_CHEATNOCLIPOFF, TXT_TXT_CHEATWEAPONS, TXT_TXT_CHEATHEALTH, TXT_TXT_CHEATKEYS, TXT_TXT_CHEATSOUNDON, TXT_TXT_CHEATSOUNDOFF, TXT_TXT_CHEATTICKERON, TXT_TXT_CHEATTICKEROFF, TXT_TXT_CHEATINVITEMS3, TXT_TXT_CHEATITEMSFAIL, TXT_TXT_CHEATWARP, TXT_TXT_CHEATSCREENSHOT, TXT_TXT_CHEATIDDQD, TXT_TXT_CHEATIDKFA, TXT_TXT_CHEATBADINPUT, TXT_TXT_CHEATNOMAP, TXT_TXT_GAMESAVED, TXT_HUSTR_CHATMACRO0, TXT_HUSTR_CHATMACRO1, TXT_HUSTR_CHATMACRO2, TXT_HUSTR_CHATMACRO3, TXT_HUSTR_CHATMACRO4, TXT_HUSTR_CHATMACRO5, TXT_HUSTR_CHATMACRO6, TXT_HUSTR_CHATMACRO7, TXT_HUSTR_CHATMACRO8, TXT_HUSTR_CHATMACRO9, TXT_AMSTR_FOLLOWON, TXT_AMSTR_FOLLOWOFF, TXT_LOADMISSING, TXT_AMSTR_ROTATEON, TXT_AMSTR_ROTATEOFF, TXT_AMSTR_GRIDON, TXT_AMSTR_GRIDOFF, TXT_AMSTR_MARKEDSPOT, TXT_AMSTR_MARKSCLEARED, TXT_SAVEOUTMAP, TXT_ENDNOGAME, TXT_SUICIDEOUTMAP, TXT_SUICIDEASK, TXT_PICKGAMETYPE, TXT_SINGLEPLAYER, TXT_MULTIPLAYER, TXT_NOTDESIGNEDFOR, TXT_GAMESETUP, TXT_PLAYERSETUP, TXT_RANDOMPLAYERCLASS, TXT_PLAYERCLASS1, TXT_PLAYERCLASS2, TXT_PLAYERCLASS3, TXT_PLAYERCLASS4, TXT_SKILLF1, TXT_SKILLF2, TXT_SKILLF3, TXT_SKILLF4, TXT_SKILLF5, TXT_SKILLC1, TXT_SKILLC2, TXT_SKILLC3, TXT_SKILLC4, TXT_SKILLC5, TXT_SKILLM1, TXT_SKILLM2, TXT_SKILLM3, TXT_SKILLM4, TXT_SKILLM5, NUMTEXT } textenum_t; // Sounds. typedef enum { SFX_NONE, SFX_PLAYER_FIGHTER_NORMAL_DEATH, SFX_PLAYER_FIGHTER_CRAZY_DEATH, SFX_PLAYER_FIGHTER_EXTREME1_DEATH, SFX_PLAYER_FIGHTER_EXTREME2_DEATH, SFX_PLAYER_FIGHTER_EXTREME3_DEATH, SFX_PLAYER_FIGHTER_BURN_DEATH, SFX_PLAYER_CLERIC_NORMAL_DEATH, SFX_PLAYER_CLERIC_CRAZY_DEATH, SFX_PLAYER_CLERIC_EXTREME1_DEATH, SFX_PLAYER_CLERIC_EXTREME2_DEATH, SFX_PLAYER_CLERIC_EXTREME3_DEATH, SFX_PLAYER_CLERIC_BURN_DEATH, SFX_PLAYER_MAGE_NORMAL_DEATH, SFX_PLAYER_MAGE_CRAZY_DEATH, SFX_PLAYER_MAGE_EXTREME1_DEATH, SFX_PLAYER_MAGE_EXTREME2_DEATH, SFX_PLAYER_MAGE_EXTREME3_DEATH, SFX_PLAYER_MAGE_BURN_DEATH, SFX_PLAYER_FIGHTER_PAIN, SFX_PLAYER_CLERIC_PAIN, SFX_PLAYER_MAGE_PAIN, SFX_PLAYER_FIGHTER_GRUNT, SFX_PLAYER_CLERIC_GRUNT, SFX_PLAYER_MAGE_GRUNT, SFX_PLAYER_LAND, SFX_PLAYER_POISONCOUGH, SFX_PLAYER_FIGHTER_FALLING_SCREAM, SFX_PLAYER_CLERIC_FALLING_SCREAM, SFX_PLAYER_MAGE_FALLING_SCREAM, SFX_PLAYER_FALLING_SPLAT, SFX_PLAYER_FIGHTER_FAILED_USE, SFX_PLAYER_CLERIC_FAILED_USE, SFX_PLAYER_MAGE_FAILED_USE, SFX_PLATFORM_START, SFX_PLATFORM_STARTMETAL, SFX_PLATFORM_STOP, SFX_STONE_MOVE, SFX_METAL_MOVE, SFX_DOOR_OPEN, SFX_DOOR_LOCKED, SFX_DOOR_METAL_OPEN, SFX_DOOR_METAL_CLOSE, SFX_DOOR_LIGHT_CLOSE, SFX_DOOR_HEAVY_CLOSE, SFX_DOOR_CREAK, SFX_PICKUP_WEAPON, SFX_PICKUP_ITEM, SFX_PICKUP_KEY, SFX_PICKUP_PUZZ, SFX_PICKUP_PIECE, SFX_WEAPON_BUILD, SFX_INVENTORY_USE, SFX_INVITEM_BLAST, SFX_TELEPORT, SFX_THUNDER_CRASH, SFX_FIGHTER_PUNCH_MISS, SFX_FIGHTER_PUNCH_HITTHING, SFX_FIGHTER_PUNCH_HITWALL, SFX_FIGHTER_GRUNT, SFX_FIGHTER_AXE_HITTHING, SFX_FIGHTER_HAMMER_MISS, SFX_FIGHTER_HAMMER_HITTHING, SFX_FIGHTER_HAMMER_HITWALL, SFX_FIGHTER_HAMMER_CONTINUOUS, SFX_FIGHTER_HAMMER_EXPLODE, SFX_FIGHTER_SWORD_FIRE, SFX_FIGHTER_SWORD_EXPLODE, SFX_CLERIC_CSTAFF_FIRE, SFX_CLERIC_CSTAFF_EXPLODE, SFX_CLERIC_CSTAFF_HITTHING, SFX_CLERIC_FLAME_FIRE, SFX_CLERIC_FLAME_EXPLODE, SFX_CLERIC_FLAME_CIRCLE, SFX_MAGE_WAND_FIRE, SFX_MAGE_LIGHTNING_FIRE, SFX_MAGE_LIGHTNING_ZAP, SFX_MAGE_LIGHTNING_CONTINUOUS, SFX_MAGE_LIGHTNING_READY, SFX_MAGE_SHARDS_FIRE, SFX_MAGE_SHARDS_EXPLODE, SFX_MAGE_STAFF_FIRE, SFX_MAGE_STAFF_EXPLODE, SFX_SWITCH1, SFX_SWITCH2, SFX_SERPENT_SIGHT, SFX_SERPENT_ACTIVE, SFX_SERPENT_PAIN, SFX_SERPENT_ATTACK, SFX_SERPENT_MELEEHIT, SFX_SERPENT_DEATH, SFX_SERPENT_BIRTH, SFX_SERPENTFX_CONTINUOUS, SFX_SERPENTFX_HIT, SFX_POTTERY_EXPLODE, SFX_DRIP, SFX_CENTAUR_SIGHT, SFX_CENTAUR_ACTIVE, SFX_CENTAUR_PAIN, SFX_CENTAUR_ATTACK, SFX_CENTAUR_DEATH, SFX_CENTAURLEADER_ATTACK, SFX_CENTAUR_MISSILE_EXPLODE, SFX_WIND, SFX_BISHOP_SIGHT, SFX_BISHOP_ACTIVE, SFX_BISHOP_PAIN, SFX_BISHOP_ATTACK, SFX_BISHOP_DEATH, SFX_BISHOP_MISSILE_EXPLODE, SFX_BISHOP_BLUR, SFX_DEMON_SIGHT, SFX_DEMON_ACTIVE, SFX_DEMON_PAIN, SFX_DEMON_ATTACK, SFX_DEMON_MISSILE_FIRE, SFX_DEMON_MISSILE_EXPLODE, SFX_DEMON_DEATH, SFX_WRAITH_SIGHT, SFX_WRAITH_ACTIVE, SFX_WRAITH_PAIN, SFX_WRAITH_ATTACK, SFX_WRAITH_MISSILE_FIRE, SFX_WRAITH_MISSILE_EXPLODE, SFX_WRAITH_DEATH, SFX_PIG_ACTIVE1, SFX_PIG_ACTIVE2, SFX_PIG_PAIN, SFX_PIG_ATTACK, SFX_PIG_DEATH, SFX_MAULATOR_SIGHT, SFX_MAULATOR_ACTIVE, SFX_MAULATOR_PAIN, SFX_MAULATOR_HAMMER_SWING, SFX_MAULATOR_HAMMER_HIT, SFX_MAULATOR_MISSILE_HIT, SFX_MAULATOR_DEATH, SFX_FREEZE_DEATH, SFX_FREEZE_SHATTER, SFX_ETTIN_SIGHT, SFX_ETTIN_ACTIVE, SFX_ETTIN_PAIN, SFX_ETTIN_ATTACK, SFX_ETTIN_DEATH, SFX_FIRED_SPAWN, SFX_FIRED_ACTIVE, SFX_FIRED_PAIN, SFX_FIRED_ATTACK, SFX_FIRED_MISSILE_HIT, SFX_FIRED_DEATH, SFX_ICEGUY_SIGHT, SFX_ICEGUY_ACTIVE, SFX_ICEGUY_ATTACK, SFX_ICEGUY_FX_EXPLODE, SFX_SORCERER_SIGHT, SFX_SORCERER_ACTIVE, SFX_SORCERER_PAIN, SFX_SORCERER_SPELLCAST, SFX_SORCERER_BALLWOOSH, SFX_SORCERER_DEATHSCREAM, SFX_SORCERER_BISHOPSPAWN, SFX_SORCERER_BALLPOP, SFX_SORCERER_BALLBOUNCE, SFX_SORCERER_BALLEXPLODE, SFX_SORCERER_BIGBALLEXPLODE, SFX_SORCERER_HEADSCREAM, SFX_DRAGON_SIGHT, SFX_DRAGON_ACTIVE, SFX_DRAGON_WINGFLAP, SFX_DRAGON_ATTACK, SFX_DRAGON_PAIN, SFX_DRAGON_DEATH, SFX_DRAGON_FIREBALL_EXPLODE, SFX_KORAX_SIGHT, SFX_KORAX_ACTIVE, SFX_KORAX_PAIN, SFX_KORAX_ATTACK, SFX_KORAX_COMMAND, SFX_KORAX_DEATH, SFX_KORAX_STEP, SFX_THRUSTSPIKE_RAISE, SFX_THRUSTSPIKE_LOWER, SFX_STAINEDGLASS_SHATTER, SFX_FLECHETTE_BOUNCE, SFX_FLECHETTE_EXPLODE, SFX_LAVA_MOVE, SFX_WATER_MOVE, SFX_ICE_STARTMOVE, SFX_EARTH_STARTMOVE, SFX_WATER_SPLASH, SFX_LAVA_SIZZLE, SFX_SLUDGE_GLOOP, SFX_CHOLY_FIRE, SFX_SPIRIT_ACTIVE, SFX_SPIRIT_ATTACK, SFX_SPIRIT_DIE, SFX_VALVE_TURN, SFX_ROPE_PULL, SFX_FLY_BUZZ, SFX_IGNITE, SFX_PUZZLE_SUCCESS, SFX_PUZZLE_FAIL_FIGHTER, SFX_PUZZLE_FAIL_CLERIC, SFX_PUZZLE_FAIL_MAGE, SFX_EARTHQUAKE, SFX_BELLRING, SFX_TREE_BREAK, SFX_TREE_EXPLODE, SFX_SUITOFARMOR_BREAK, SFX_POISONSHROOM_PAIN, SFX_POISONSHROOM_DEATH, SFX_AMBIENT1, SFX_AMBIENT2, SFX_AMBIENT3, SFX_AMBIENT4, SFX_AMBIENT5, SFX_AMBIENT6, SFX_AMBIENT7, SFX_AMBIENT8, SFX_AMBIENT9, SFX_AMBIENT10, SFX_AMBIENT11, SFX_AMBIENT12, SFX_AMBIENT13, SFX_AMBIENT14, SFX_AMBIENT15, SFX_STARTUP_TICK, SFX_SWITCH_OTHERLEVEL, SFX_RESPAWN, SFX_KORAX_VOICE_1, SFX_KORAX_VOICE_2, SFX_KORAX_VOICE_3, SFX_KORAX_VOICE_4, SFX_KORAX_VOICE_5, SFX_KORAX_VOICE_6, SFX_KORAX_VOICE_7, SFX_KORAX_VOICE_8, SFX_KORAX_VOICE_9, SFX_BAT_SCREAM, SFX_CHAT, SFX_MENU_MOVE, SFX_CLOCK_TICK, SFX_FIREBALL, SFX_PUPPYBEAT, SFX_MYSTICINCANT, NUMSFX } sfxenum_t; // Music. typedef enum { NUMMUSIC } musicenum_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/st_stuff.h0000644000175000017500000000401411357170242023457 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2005-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * st_stuff.h: */ #ifndef __ST_STUFF_H__ #define __ST_STUFF_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "x_player.h" #include "x_config.h" // Size of statusbar. #define ST_HEIGHT (42*SCREEN_MUL) #define ST_WIDTH (SCREENWIDTH) #define ST_Y (SCREENHEIGHT - ST_HEIGHT) // Called by startup code. void ST_Register(void); void ST_Init(void); // Called by main loop. void ST_Ticker(void); void ST_Start(int player); void ST_Stop(int player); void ST_updateGraphics(void); // Called when it might be neccessary for the hud to unhide. void ST_HUDUnHide(int player, hueevent_t ev); // Called in P_inter & P_enemy void ST_doPaletteStuff(int player, boolean forceChange); void ST_Init(void); boolean ST_Responder(event_t* ev); void ST_Ticker(void); void ST_Drawer(int player, int fullscreenMode, boolean refresh); void ST_PaletteFlash(boolean forceChange); void ST_FlashCurrentItem(int player); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_lights.h0000644000175000017500000000432211357170242023435 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_lights.h: */ #ifndef __P_LIGHTS_H__ #define __P_LIGHTS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #define LIGHT_SEQUENCE_START (2) #define LIGHT_SEQUENCE (3) #define LIGHT_SEQUENCE_ALT (4) typedef enum { LITE_RAISEBYVALUE, LITE_LOWERBYVALUE, LITE_CHANGETOVALUE, LITE_FADE, LITE_GLOW, LITE_FLICKER, LITE_STROBE } lighttype_t; typedef struct { thinker_t thinker; sector_t* sector; lighttype_t type; float value1; float value2; int tics1; //// \todo Type LITEGLOW uses this as a third light value. As such, it has been left as 0 - 255 for now. int tics2; int count; } light_t; typedef struct { thinker_t thinker; sector_t* sector; int index; float baseValue; } phase_t; void T_Phase(phase_t* phase); void P_SpawnPhasedLight(sector_t* sec, float base, int index); void T_Light(light_t* light); void P_SpawnLightSequence(sector_t* sec, int indexStep); boolean EV_SpawnLight(linedef_t* line, byte* arg, lighttype_t type); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_think.h0000644000175000017500000000334411357170242023273 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1993-1996 by id Software, Inc. * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_think.h: MapObj data. * * Map Objects or mobjs are actors, entities, thinker, take-your-pick... * anything that moves, acts, or suffers state changes of more or less * violent nature. */ #ifndef __X_THINK_H__ #define __X_THINK_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif /** * Experimental stuff. * To compile this as "ANSI C with classes" we will need to handle the * various action functions cleanly. */ typedef void (*actionf_v) (); typedef void (*actionf_p1) (void *); typedef void (*actionf_p2) (void *, void *); #define NOPFUNC ((actionf_v) (-1)) typedef union { actionf_p1 acp1; actionf_v acv; actionf_p2 acp2; } actionf_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_event.h0000644000175000017500000000452211357170242023276 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_event.h: */ #ifndef __X_EVENT_H__ #define __X_EVENT_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif typedef enum { GA_NONE, GA_LOADMAP, GA_INITNEW, GA_NEWGAME, GA_LOADGAME, GA_SAVEGAME, GA_MAPCOMPLETED, GA_LEAVEMAP, GA_SINGLEREBORN, GA_VICTORY, GA_SCREENSHOT, GA_QUIT } gameaction_t; // // Button/action code definitions. // typedef enum { // Press "Fire". BT_ATTACK = 1, // Use button, to open doors, activate switches. BT_USE = 2, // Flag: game events, not really buttons. BT_SPECIAL = 128, BT_SPECIALMASK = 3, // Center player look angle (pitch back to zero). //BT_LOOKCENTER = 64, // Flag, weapon change pending. // If true, the next 3 bits hold weapon num. BT_CHANGE = 4, // The 3bit weapon mask and shift, convenience. BT_WEAPONMASK = (8+16+32+64), BT_WEAPONSHIFT = 3, BT_JUMP = 8, BT_SPEED = 16, // Pause the game. BTS_PAUSE = 1, // Save the game at each console. //BTS_SAVEGAME = 2, // Savegame slot numbers // occupy the second byte of buttons. //BTS_SAVEMASK = (4+8+16), //BTS_SAVESHIFT = 2, // Special weapon change flags. BTS_NEXTWEAPON = 4, BTS_PREVWEAPON = 8, } buttoncode_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_sound.h0000644000175000017500000000247411357170242023301 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_sound.h: */ #ifndef __P_SOUND_H__ #define __P_SOUND_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #define MAX_SND_DIST (2025) #define MAX_CHANNELS (16) int S_GetSoundID(const char* name); void S_MapMusic(uint episode, uint map); void S_ParseSndInfoLump(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/mn_def.h0000644000175000017500000001035511357170242023057 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * mn_def.h: Menu defines and types. */ #ifndef __MENU_DEFS_H__ #define __MENU_DEFS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "jhexen.h" #include "hu_stuff.h" #include "m_defs.h" // Macros #define LEFT_DIR 0 #define RIGHT_DIR 1 #define ITEM_HEIGHT 20 #define SLOTTEXTLEN 16 #define ASCII_CURSOR '_' #define LINEHEIGHT 20 #define LINEHEIGHT_A 10 #define LINEHEIGHT_B 20 #define MENUCURSOR_OFFSET_X -2 #define MENUCURSOR_OFFSET_Y -1 #define MENUCURSOR_TICSPERFRAME 8 #define CURSORPREF "M_SLCTR%d" #define SKULLBASELMP "FBULA0" #define NUMCURSORS 2 #define NUMSAVESLOTS 6 #define MAX_EDIT_LEN 256 // Types typedef struct { char text[MAX_EDIT_LEN]; char oldtext[MAX_EDIT_LEN]; // If the current edit is canceled... int firstVisible; } editfield_t; typedef enum { MENU_MAIN, MENU_NEWGAME, MENU_CLASS, MENU_SKILL, MENU_OPTIONS, MENU_OPTIONS2, MENU_GAMEPLAY, MENU_HUD, MENU_MAP, MENU_FILES, MENU_LOAD, MENU_SAVE, MENU_MULTIPLAYER, MENU_GAMESETUP, MENU_PLAYERSETUP, MENU_INVENTORY, MENU_WEAPONS, MENU_CONTROLS, MENU_NONE } menutype_t; extern int menuTime; extern boolean shiftdown; extern menu_t *currentMenu; extern short itemOn; extern menu_t MapDef; extern menu_t ControlsDef; // Multiplayer menus. extern menu_t MultiplayerMenu; extern menu_t GameSetupMenu; extern menu_t PlayerSetupMenu; void M_StartControlPanel(void); void M_DrawSaveLoadBorder(int x, int y, int width); void M_WriteMenuText(const menu_t *menu, int index, const char *text); // Color widget. void DrawColorWidget(); void SCColorWidget(int index, void *data); void M_WGCurrentColor(int option, void *data); void M_SetupNextMenu(menu_t * menudef); void M_DrawTitle(char *text, int y); void MN_DrawSlider(const menu_t *menu, int item, int width, int slot); void MN_DrawColorBox(const menu_t *menu, int index, float r, float g, float b, float a); void M_FloatMod10(float *variable, int option); void SCEnterMultiplayerMenu(int option, void *data); void MN_TickerEx(void); // The extended ticker. // Widget routines. boolean Cl_Responder(event_t *event); // Handles control in a menu widget // Edit field routines. boolean Ed_Responder(event_t *event); boolean MN_CurrentMenuHasBackground(void); void MN_ActivateMenu(void); void MN_DeactivateMenu(void); void MN_TextFilter(char *text); void MN_DrTextA(char *text, int x, int y); void MN_DrTextAYellow(char *text, int x, int y); int MN_TextAWidth(char *text); void MN_DrTextB(char *text, int x, int y); int MN_TextBWidth(char *text); void MN_DrawTitle(char *text, int y); // Drawing text in the current state. void MN_DrTextA_CS(char *text, int x, int y); void MN_DrTextAYellow_CS(char *text, int x, int y); void MN_DrTextB_CS(char *text, int x, int y); void strcatQuoted(char *dest, char *src); void M_ToggleVar(int option, void* context); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/m_cheat.h0000644000175000017500000000205111357170242023221 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ #ifndef M_CHEAT #define M_CHEAT #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif void Cht_Init(void); #endif /* M_CHEAT */ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_items.h0000644000175000017500000000424211357170242023275 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_items.h: Items, key cards/weapons/ammunition... */ #ifndef __X_ITEMS_H__ #define __X_ITEMS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "h2def.h" #define WEAPON_INFO(weaponnum, pclass, fmode) ( \ &weaponInfo[weaponnum][pclass].mode[fmode]) typedef enum { WSN_UP, WSN_DOWN, WSN_READY, WSN_ATTACK, WSN_ATTACK_HOLD, WSN_FLASH, NUM_WEAPON_STATE_NAMES } weaponstatename_t; typedef struct { int gameModeBits; // Game modes, weapon is available in. int ammoType[NUM_AMMO_TYPES]; // required ammo types. int perShot[NUM_AMMO_TYPES]; // Ammo used per shot of each type. boolean autoFire; // @c true = fire when raised if fire held. int states[NUM_WEAPON_STATE_NAMES]; int raiseSound; // Sound played when weapon is raised. int readySound; // Sound played WHILE weapon is readyied. } weaponmodeinfo_t; // Weapon info: sprite frames, ammunition use. typedef struct { weaponmodeinfo_t mode[NUMWEAPLEVELS]; } weaponinfo_t; extern weaponinfo_t weaponInfo[NUM_WEAPON_TYPES][NUM_PLAYER_CLASSES]; void P_InitWeaponInfo(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_pillar.h0000644000175000017500000000312211357170242023423 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pillar.h: */ #ifndef __P_PILLAR_H__ #define __P_PILLAR_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif typedef struct { thinker_t thinker; sector_t* sector; float ceilingSpeed; float floorSpeed; float floorDest; float ceilingDest; int direction; int crush; } pillar_t; void T_BuildPillar(pillar_t* pillar); int EV_BuildPillar(linedef_t* line, byte* args, boolean crush); int EV_OpenPillar(linedef_t* line, byte* args); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/g_ctrl.h0000644000175000017500000000223311357170242023075 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_ctrl.h: */ #ifndef __JHEXEN_CTRL_H__ #define __JHEXEN_CTRL_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif void G_RegisterPlayerControls(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_config.h0000644000175000017500000001434011357170242023421 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_config.h: */ #ifndef __JHEXEN_CONFIG_H__ #define __JHEXEN_CONFIG_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif enum { HUD_MANA, HUD_HEALTH, HUD_CURRENTITEM }; // Hud Unhide Events (the hud will unhide on these events if enabled). typedef enum { HUE_FORCE = -1, HUE_ON_DAMAGE, HUE_ON_PICKUP_HEALTH, HUE_ON_PICKUP_ARMOR, HUE_ON_PICKUP_POWER, HUE_ON_PICKUP_WEAPON, HUE_ON_PICKUP_AMMO, HUE_ON_PICKUP_KEY, HUE_ON_PICKUP_INVITEM, NUMHUDUNHIDEEVENTS } hueevent_t; // This struct should be cleaned up. Currently some of the data isn't // even used any more. // WARNING: Do not use the boolean type. Its size can be either 1 or 4 bytes // depending on build settings. typedef struct { float playerMoveSpeed; float lookSpeed; float turnSpeed; int quakeFly; byte fastMonsters; int useMLook, useJLook; int screenBlocks; int setBlocks; byte hudShown[4]; // HUD data visibility. float hudScale; float hudColor[4]; float hudIconAlpha; float hudTimer; // Number of seconds until the hud/statusbar auto-hides. byte hudUnHide[NUMHUDUNHIDEEVENTS]; // when the hud/statusbar unhides. byte usePatchReplacement; int showFPS, lookSpring; int mlookInverseY; int echoMsg; int translucentIceCorpse; byte overrideHubMsg; // skip the transition hub message when 1 int cameraNoClip; float bobView, bobWeapon; byte askQuickSaveLoad; int jumpEnabled; float jumpPower; int airborneMovement; int useMouse, noAutoAim, alwaysRun; byte povLookAround; int jLookDeltaMode; int xhair; float xhairSize; byte xhairVitality; float xhairColor[4]; int statusbarScale; float statusbarOpacity; float statusbarCounterAlpha; int msgCount; float msgScale; float msgUptime; int msgBlink; int msgAlign; byte msgShow; float msgColor[3]; byte weaponAutoSwitch; byte noWeaponAutoSwitchIfFiring; byte ammoAutoSwitch; int weaponOrder[NUM_WEAPON_TYPES]; byte weaponNextMode; // if true use the weaponOrder for next/previous. float filterStrength; byte counterCheat; float counterCheatScale; // Automap stuff. /* int automapPos; float automapWidth; float automapHeight; */ float automapMobj[3]; float automapL0[3]; float automapL1[3]; float automapL2[3]; float automapL3[3]; float automapBack[3]; float automapOpacity; float automapLineAlpha; byte automapRotate; byte automapHudDisplay; int automapCustomColors; byte automapShowDoors; float automapDoorGlow; byte automapBabyKeys; float automapZoomSpeed; float automapPanSpeed; byte automapPanResetOnOpen; float automapOpenSeconds; int messagesOn; char* chatMacros[10]; byte chatBeep; int snd3D; float sndReverbFactor; byte reverbDebug; int dclickUse; int plrViewHeight; byte mapTitle, hideIWADAuthor; float menuScale; int menuEffects; int hudFog; float menuGlitter; float menuShadow; float flashColor[3]; int flashSpeed; byte turningSkull; float menuColor[3]; float menuColor2[3]; byte menuSlam; byte menuHotkeys; byte netMap, netClass, netColor, netSkill; byte netEpisode; // Unused in Hexen. byte netDeathmatch, netNoMonsters, netRandomClass; byte netJumping; byte netMobDamageModifier; // Multiplier for non-player mobj damage. byte netMobHealthModifier; // Health modifier for non-player mobjs. int netGravity; // Multiplayer custom gravity. byte netNoMaxZRadiusAttack; // Radius attacks are infinitely tall. byte netNoMaxZMonsterMeleeAttack; // Melee attacks are infinitely tall. playerclass_t playerClass[MAXPLAYERS]; byte playerColor[MAXPLAYERS]; float inventoryTimer; // Number of seconds until the invetory auto-hides. byte inventoryWrap; byte inventoryUseNext; byte inventoryUseImmediate; int inventorySlotMaxVis; byte inventorySlotShowEmpty; byte inventorySelectMode; } game_config_t; extern game_config_t cfg; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_pspr.h0000644000175000017500000000250411357170242023127 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_pspr.h: Sprite animation. */ #ifndef __P_PSPR_H__ #define __P_PSPR_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif typedef enum { ps_weapon, ps_flash, NUMPSPRITES } psprnum_t; typedef struct { state_t* state; // @c NULL means not active. int tics; float pos[2]; } pspdef_t; void R_GetWeaponBob(int player, float* x, float* y); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/dstrings.h0000644000175000017500000002260311357170242023463 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * dstrings.h: */ #ifndef __DSTRINGS_H__ #define __DSTRINGS_H__ #define PRESSKEY "press a key." #define PRESSYN "press y or n." #define TXT_PAUSED "PAUSED" #define QUITMSG "are you sure you want to\nquit this great game?" #define LOADNET "you can't do load while in a net game!\n\n"PRESSKEY #define QLOADNET "you can't quickload during a netgame!\n\n"PRESSKEY #define QSAVESPOT "you haven't picked a quicksave slot yet!\n\n"PRESSKEY #define SAVEDEAD "you can't save if you aren't playing!\n\n"PRESSKEY #define QSPROMPT "quicksave over your game named\n\n'%s'?\n\n"PRESSYN #define QLPROMPT "do you want to quickload the game named"\ "\n\n'%s'?\n\n"PRESSYN #define NEWGAME "you can't start a new game\n"\ "while in a network game.\n\n"PRESSKEY #define NIGHTMARE "are you sure? this skill level\n"\ "isn't even remotely fair.\n\n"PRESSYN #define SWSTRING "this is the shareware version of doom.\n\n"\ "you need to order the entire trilogy.\n\n"PRESSKEY #define MSGOFF "Messages OFF" #define MSGON "Messages ON" #define NETEND "you can't end a netgame!\n\n"PRESSKEY #define ENDGAME "are you sure you want to end the game?\n\n"PRESSYN #define DOSY "(press y to quit to dos.)" #define DETAILHI "High detail" #define DETAILLO "Low detail" #define GAMMALVL0 "Gamma correction OFF" #define GAMMALVL1 "Gamma correction level 1" #define GAMMALVL2 "Gamma correction level 2" #define GAMMALVL3 "Gamma correction level 3" #define GAMMALVL4 "Gamma correction level 4" #define EMPTYSTRING "empty slot" // Keys #define TXT_GOTBLUEKEY "BLUE KEY" #define TXT_GOTYELLOWKEY "YELLOW KEY" #define TXT_GOTGREENKEY "GREEN KEY" // Inventory items #define TXT_INV_HEALTH "QUARTZ FLASK" #define TXT_INV_FLY "WINGS OF WRATH" #define TXT_INV_INVULNERABILITY "RING OF INVINCIBILITY" #define TXT_INV_TOMEOFPOWER "TOME OF POWER" #define TXT_INV_INVISIBILITY "SHADOWSPHERE" #define TXT_INV_EGG "MORPH OVUM" #define TXT_INV_SUPERHEALTH "MYSTIC URN" #define TXT_INV_TORCH "TORCH" #define TXT_INV_FIREBOMB "TIME BOMB OF THE ANCIENTS" #define TXT_INV_TELEPORT "CHAOS DEVICE" // Items #define TXT_ITEMHEALTH "CRYSTAL VIAL" #define TXT_ITEMBAGOFHOLDING "BAG OF HOLDING" #define TXT_ITEMSHIELD1 "SILVER SHIELD" #define TXT_ITEMSHIELD2 "ENCHANTED SHIELD" #define TXT_ITEMSUPERMAP "MAP SCROLL" // Ammo #define TXT_AMMOGOLDWAND1 "WAND CRYSTAL" #define TXT_AMMOGOLDWAND2 "CRYSTAL GEODE" #define TXT_AMMOMACE1 "MACE SPHERES" #define TXT_AMMOMACE2 "PILE OF MACE SPHERES" #define TXT_AMMOCROSSBOW1 "ETHEREAL ARROWS" #define TXT_AMMOCROSSBOW2 "QUIVER OF ETHEREAL ARROWS" #define TXT_AMMOBLASTER1 "CLAW ORB" #define TXT_AMMOBLASTER2 "ENERGY ORB" #define TXT_AMMOSKULLROD1 "LESSER RUNES" #define TXT_AMMOSKULLROD2 "GREATER RUNES" #define TXT_AMMOPHOENIXROD1 "FLAME ORB" #define TXT_AMMOPHOENIXROD2 "INFERNO ORB" // Weapons #define TXT_WPNMACE "FIREMACE" #define TXT_WPNCROSSBOW "ETHEREAL CROSSBOW" #define TXT_WPNBLASTER "DRAGON CLAW" #define TXT_WPNSKULLROD "HELLSTAFF" #define TXT_WPNPHOENIXROD "PHOENIX ROD" #define TXT_WPNGAUNTLETS "GAUNTLETS OF THE NECROMANCER" #define TXT_CHEATGODON "GOD MODE ON" #define TXT_CHEATGODOFF "GOD MODE OFF" #define TXT_CHEATNOCLIPON "NO CLIPPING ON" #define TXT_CHEATNOCLIPOFF "NO CLIPPING OFF" #define TXT_CHEATWEAPONS "ALL WEAPONS" #define TXT_CHEATFLIGHTON "FLIGHT ON" #define TXT_CHEATFLIGHTOFF "FLIGHT OFF" #define TXT_CHEATPOWERON "POWER ON" #define TXT_CHEATPOWEROFF "POWER OFF" #define TXT_CHEATHEALTH "FULL HEALTH" #define TXT_CHEATKEYS "ALL KEYS" #define TXT_CHEATSOUNDON "SOUND DEBUG ON" #define TXT_CHEATSOUNDOFF "SOUND DEBUG OFF" #define TXT_CHEATTICKERON "TICKER ON" #define TXT_CHEATTICKEROFF "TICKER OFF" #define TXT_CHEATINVITEMS1 "CHOOSE AN ARTIFACT ( A - J )" #define TXT_CHEATINVITEMS2 "HOW MANY ( 1 - 9 )" #define TXT_CHEATINVITEMS3 "YOU GOT IT" #define TXT_CHEATITEMSFAIL "BAD INPUT" #define TXT_CHEATWARP "MAP WARP" #define TXT_CHEATSCREENSHOT "SCREENSHOT" #define TXT_CHEATCHICKENON "CHICKEN ON" #define TXT_CHEATCHICKENOFF "CHICKEN OFF" #define TXT_CHEATMASSACRE "MASSACRE" #define TXT_CHEATIDDQD "TRYING TO CHEAT, EH? NOW YOU DIE!" #define TXT_CHEATIDKFA "CHEATER - YOU DON'T DESERVE WEAPONS" #define TXT_NEEDBLUEKEY "YOU NEED A BLUE KEY TO OPEN THIS DOOR" #define TXT_NEEDGREENKEY "YOU NEED A GREEN KEY TO OPEN THIS DOOR" #define TXT_NEEDYELLOWKEY "YOU NEED A YELLOW KEY TO OPEN THIS DOOR" #define TXT_GAMESAVED "GAME SAVED" #define HUSTR_CHATMACRO1 "I'm ready to kick butt!" #define HUSTR_CHATMACRO2 "I'm OK." #define HUSTR_CHATMACRO3 "I'm not looking too good!" #define HUSTR_CHATMACRO4 "Help!" #define HUSTR_CHATMACRO5 "You suck!" #define HUSTR_CHATMACRO6 "Next time, scumbag..." #define HUSTR_CHATMACRO7 "Come here!" #define HUSTR_CHATMACRO8 "I'll take care of it." #define HUSTR_CHATMACRO9 "Yes" #define HUSTR_CHATMACRO0 "No" #define AMSTR_FOLLOWON "FOLLOW MODE ON" #define AMSTR_FOLLOWOFF "FOLLOW MODE OFF" #define AMSTR_ROTATEON "Rotate Mode ON" #define AMSTR_ROTATEOFF "Rotate Mode OFF" #define AMSTR_GRIDON "Grid ON" #define AMSTR_GRIDOFF "Grid OFF" #define AMSTR_MARKEDSPOT "Marked Spot" #define AMSTR_MARKSCLEARED "All Marks Cleared" #define E1TEXT "with the destruction of the iron\n"\ "liches and their minions, the last\n"\ "of the undead are cleared from this\n"\ "plane of existence.\n\n"\ "those creatures had to come from\n"\ "somewhere, though, and you have the\n"\ "sneaky suspicion that the fiery\n"\ "portal of hell's maw opens onto\n"\ "their home dimension.\n\n"\ "to make sure that more undead\n"\ "(or even worse things) don't come\n"\ "through, you'll have to seal hell's\n"\ "maw from the other side. of course\n"\ "this means you may get stuck in a\n"\ "very unfriendly world, but no one\n"\ "ever said being a Heretic was easy!" #define E2TEXT "the mighty maulotaurs have proved\n"\ "to be no match for you, and as\n"\ "their steaming corpses slide to the\n"\ "ground you feel a sense of grim\n"\ "satisfaction that they have been\n"\ "destroyed.\n\n"\ "the gateways which they guarded\n"\ "have opened, revealing what you\n"\ "hope is the way home. but as you\n"\ "step through, mocking laughter\n"\ "rings in your ears.\n\n"\ "was some other force controlling\n"\ "the maulotaurs? could there be even\n"\ "more horrific beings through this\n"\ "gate? the sweep of a crystal dome\n"\ "overhead where the sky should be is\n"\ "certainly not a good sign...." #define E3TEXT "the death of d'sparil has loosed\n"\ "the magical bonds holding his\n"\ "creatures on this plane, their\n"\ "dying screams overwhelming his own\n"\ "cries of agony.\n\n"\ "your oath of vengeance fulfilled,\n"\ "you enter the portal to your own\n"\ "world, mere moments before the dome\n"\ "shatters into a million pieces.\n\n"\ "but if d'sparil's power is broken\n"\ "forever, why don't you feel safe?\n"\ "was it that last shout just before\n"\ "his death, the one that sounded\n"\ "like a curse? or a summoning? you\n"\ "can't really be sure, but it might\n"\ "just have been a scream.\n\n"\ "then again, what about the other\n"\ "serpent riders?" #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/sc_man.h0000644000175000017500000000202611357170242023063 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * sc_man.h: */ #ifndef __SC_MAN_H__ #define __SC_MAN_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/version.h0000644000175000017500000000342311357170242023312 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2007-2009 Daniel Swanson *\author Copyright © 2006 Jamie Jones * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * version.h: Version numbering, naming etc. */ #ifndef __JHEXEN_VERSION_H__ #define __JHEXEN_VERSION_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #ifndef JHEXEN_VER_ID # ifdef _DEBUG # define JHEXEN_VER_ID "+D Doomsday" # else # define JHEXEN_VER_ID "Doomsday" # endif #endif // Used to derive filepaths. #define GAMENAMETEXT "jhexen" // Presented to the user in dialogs, messages etc. #define GAME_NICENAME "jHexen" #define GAME_DETAILS "jHexen is based on Hexen v1.1 by Raven Software." #define GAME_VERSION_TEXT "1.3.8" #define GAME_VERSION_TEXTLONG "Version" GAME_VERSION_TEXT " " __DATE__ " (" JHEXEN_VER_ID ")" #define GAME_VERSION_NUMBER 1,3,8,0 // For WIN32 version info. #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_mobj.h0000644000175000017500000002412311357170242023073 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mobj.h: Map Objects, MObj, definition and handling. */ #ifndef __P_MOBJ_H__ #define __P_MOBJ_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "p_terraintype.h" /** * Mobj flags * * \attention IMPORTANT - Keep this current!!! * LEGEND: * p = Flag is persistent (never changes in-game). * i = Internal use (not to be used in defintions). * * \todo Persistent flags (p) don't need to be included in save games or sent to * clients in netgames. We should collect those in to a const flags setting which * is set only once when the mobj is spawned. * * \todo All flags for internal use only (i) should be put in another var and the * flags removed from those defined in GAME/objects.DED */ // --- mobj.flags --- #define MF_SPECIAL 1 // call P_SpecialThing when touched #define MF_SOLID 2 #define MF_SHOOTABLE 4 #define MF_NOSECTOR 8 // don't use the sector links // (invisible but touchable) #define MF_NOBLOCKMAP 16 // don't use the blocklinks // (inert but displayable) #define MF_AMBUSH 32 #define MF_JUSTHIT 64 // try to attack right back #define MF_JUSTATTACKED 128 // take at least one step before attacking #define MF_SPAWNCEILING 256 // hang from ceiling instead of floor #define MF_NOGRAVITY 512 // don't apply gravity every tic // movement flags #define MF_DROPOFF 0x400 // allow jumps from high places #define MF_PICKUP 0x800 // for players to pick up items #define MF_NOCLIP 0x1000 // player cheat #define MF_SLIDE 0x2000 // keep info about sliding along walls #define MF_FLOAT 0x4000 // allow moves to any height, no gravity #define MF_TELEPORT 0x8000 // don't cross lines or look at heights #define MF_MISSILE 0x10000 // don't hit same species, explode on block #define MF_ALTSHADOW 0x20000 // alternate fuzzy draw #define MF_SHADOW 0x40000 // use fuzzy draw (shadow demons / invis) #define MF_NOBLOOD 0x80000 // don't bleed when shot (use puff) #define MF_CORPSE 0x100000 // don't stop moving halfway off a step #define MF_INFLOAT 0x200000 // floating to a height for a move, don't // auto float to target's height #define MF_COUNTKILL 0x400000 // count towards intermission kill total #define MF_ICECORPSE 0x800000 // a frozen corpse (for blasting) #define MF_SKULLFLY 0x1000000 // skull in flight #define MF_NOTDMATCH 0x2000000 // don't spawn in death match (key cards) //#define MF_TRANSLATION 0xc000000 // if 0x4 0x8 or 0xc, use a translation #define MF_TRANSLATION 0x1c000000 // use a translation table (>>MF_TRANSHIFT) #define MF_TRANSSHIFT 26 // table for player colormaps #define MF_LOCAL 0x20000000 // If this flag is set, the sprite is aligned with the view plane. #define MF_BRIGHTEXPLODE 0x40000000 // Make this brightshadow when exploding. #define MF_VIEWALIGN 0x80000000 #define MF_BRIGHTSHADOW (MF_SHADOW|MF_ALTSHADOW) // --- mobj.flags2 --- #define MF2_LOGRAV 0x00000001 // alternate gravity setting #define MF2_WINDTHRUST 0x00000002 // gets pushed around by the wind // specials #define MF2_FLOORBOUNCE 0x00000004 // bounces off the floor #define MF2_BLASTED 0x00000008 // missile will pass through ghosts #define MF2_FLY 0x00000010 // fly mode is active #define MF2_FLOORCLIP 0x00000020 // if feet are allowed to be clipped #define MF2_SPAWNFLOAT 0x00000040 // spawn random float z #define MF2_NOTELEPORT 0x00000080 // does not teleport #define MF2_RIP 0x00000100 // missile rips through solid // targets #define MF2_PUSHABLE 0x00000200 // can be pushed by other moving // mobjs #define MF2_SLIDE 0x00000400 // slides against walls //#define MF2_UNUSED1 0x00000800 // Formerly 'MF2_ONMOBJ' #define MF2_PASSMOBJ 0x00001000 // Enable z block checking. If on, // this flag will allow the mobj to // pass over/under other mobjs. #define MF2_CANNOTPUSH 0x00002000 // cannot push other pushable mobjs #define MF2_DROPPED 0x00004000 // dropped by a demon #define MF2_BOSS 0x00008000 // mobj is a major boss #define MF2_FIREDAMAGE 0x00010000 // does fire damage #define MF2_NODMGTHRUST 0x00020000 // does not thrust target when // damaging #define MF2_TELESTOMP 0x00040000 // mobj can stomp another #define MF2_FLOATBOB 0x00080000 // use float bobbing z movement #define MF2_DONTDRAW 0x00100000 // don't generate a vissprite #define MF2_IMPACT 0x00200000 // an MF_MISSILE mobj can activate // SPAC_IMPACT #define MF2_PUSHWALL 0x00400000 // mobj can push walls #define MF2_MCROSS 0x00800000 // can activate monster cross lines #define MF2_PCROSS 0x01000000 // can activate projectile cross lines #define MF2_CANTLEAVEFLOORPIC 0x02000000 // stay within a certain floor type #define MF2_NONSHOOTABLE 0x04000000 // mobj is totally non-shootable, // but still considered solid #define MF2_INVULNERABLE 0x08000000 // mobj is invulnerable #define MF2_DORMANT 0x10000000 // thing is dormant #define MF2_ICEDAMAGE 0x20000000 // does ice damage #define MF2_SEEKERMISSILE 0x40000000 // is a seeker (for reflection) #define MF2_REFLECTIVE 0x80000000 // reflects missiles // --- mobj.flags3 --- #define MF3_NOINFIGHT 0x00000001 // Mobj will never be targeted for in-fighting typedef enum dirtype_s { DI_EAST, DI_NORTHEAST, DI_NORTH, DI_NORTHWEST, DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_NODIR, NUMDIRS } dirtype_t; typedef struct mobj_s { // Defined in dd_share.h; required mobj elements. DD_BASE_MOBJ_ELEMENTS() // Hexen-specific data: struct player_s *player; // Only valid if type == MT_PLAYER mobjinfo_t* info; // &MOBJINFO[mobj->type] int damage; // For missiles int flags; int flags2; // Heretic flags int flags3; int special1; // Special info int special2; // Special info int health; int moveDir; // 0-7 int moveCount; // When 0, select a new dir struct mobj_s* target; // Thing being chased/attacked (or NULL) // also the originator for missiles // used by player to freeze a bit after // teleporting int threshold; // if > 0, the target will be chased // no matter what (even if shot) int lastLook; // player number last looked for short tid; // thing identifier byte special; // special byte args[5]; // special arguments int turnTime; // $visangle-facetarget int alpha; // $mobjalpha // Thing being chased/attacked for tracers. struct mobj_s* tracer; // Used by lightning zap struct mobj_s* lastEnemy; } mobj_t; typedef struct polyobj_s { // Defined in dd_share.h; required polyobj elements. DD_BASE_POLYOBJ_ELEMENTS() // Hexen-specific data: void* specialData; /* Pointer a thinker, if the poly is moving. */ } polyobj_t; mobj_t* P_SpawnMobj3f(mobjtype_t type, float x, float y, float z, angle_t angle, int spawnFlags); mobj_t* P_SpawnMobj3fv(mobjtype_t type, const float pos[3], angle_t angle, int spawnFlags); void P_SpawnPuff(float x, float y, float z, angle_t angle); void P_SpawnBlood(float x, float y, float z, int damage, angle_t angle); mobj_t* P_SpawnMissile(mobjtype_t type, mobj_t* source, mobj_t* dest); mobj_t* P_SpawnMissileXYZ(mobjtype_t type, float x, float y, float z, mobj_t* source, mobj_t* dest); mobj_t* P_SpawnMissileAngle(mobjtype_t type, mobj_t* source, angle_t angle, float momZ); mobj_t* P_SpawnMissileAngleSpeed(mobjtype_t type, mobj_t* source, angle_t angle, float momZ, float speed); mobj_t* P_SpawnPlayerMissile(mobjtype_t type, mobj_t* source); mobj_t* P_SPMAngle(mobjtype_t type, mobj_t* source, angle_t angle); mobj_t* P_SPMAngleXYZ(mobjtype_t type, float x, float y, float z, mobj_t* source, angle_t angle); mobj_t* P_SpawnTeleFog(float x, float y, angle_t angle); mobj_t* P_SpawnKoraxMissile(mobjtype_t type, float x, float y, float z, mobj_t* source, mobj_t* dest); void P_SpawnDirt(mobj_t* actor, float radius); void P_ExplodeMissile(mobj_t* mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_spec.h0000644000175000017500000000543611357170242023104 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_spec.h: */ #ifndef __P_SPEC_H__ #define __P_SPEC_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #define MO_TELEPORTMAN 14 void P_InitLava(void); void P_SpawnSpecials(void); void P_UpdateSpecials(void); boolean P_ExecuteLineSpecial(int special, byte *args, linedef_t *line, int side, mobj_t *mo); boolean P_ActivateLine(linedef_t *ld, mobj_t *mo, int side, int activationType); void P_PlayerInSpecialSector(player_t *plr); void P_PlayerOnSpecialFloor(player_t *plr); void P_AnimateSurfaces(void); void P_InitPicAnims(void); void P_InitLightning(void); void P_ForceLightning(void); typedef enum { ok, crushed, pastdest } result_e; typedef enum { STAIRS_NORMAL, STAIRS_SYNC, STAIRS_PHASED } stairs_e; result_e T_MovePlane(sector_t *sector, float speed, float dest, int crush, int floorOrCeiling, int direction); int EV_BuildStairs(linedef_t *line, byte *args, int direction, stairs_e type); int EV_FloorCrushStop(linedef_t *line, byte *args); #define TELEFOGHEIGHTF (32) boolean P_Teleport(mobj_t *mo, float x, float y, angle_t angle, boolean useFog); boolean EV_Teleport(int tid, mobj_t *thing, boolean fog); void P_ArtiTele(player_t *player); extern mobjtype_t TranslateThingType[]; boolean EV_ThingProjectile(byte *args, boolean gravity); boolean EV_ThingSpawn(byte *args, boolean fog); boolean EV_ThingActivate(int tid); boolean EV_ThingDeactivate(int tid); boolean EV_ThingRemove(int tid); boolean EV_ThingDestroy(int tid); void P_InitSky(uint map); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_local.h0000644000175000017500000001422511357170242023240 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 1999-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_local.h */ #ifndef __P_LOCAL__ #define __P_LOCAL__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #ifndef __R_LOCAL__ #include "r_local.h" #endif #include "p_start.h" #include "p_actor.h" #include "p_spec.h" #include "d_net.h" #include "p_terraintype.h" #define STARTREDPALS 1 #define STARTBONUSPALS 9 #define STARTPOISONPALS 13 #define STARTICEPAL 21 #define STARTHOLYPAL 22 #define STARTSCOURGEPAL 25 #define NUMREDPALS 8 #define NUMBONUSPALS 4 #define NUMPOISONPALS 8 #define FLOATSPEED 4 #define MAXHEALTH (maxHealth) //100 #define MAXMORPHHEALTH 30 #define VIEWHEIGHT 48 #define FLOATBOBRES 64 #define FLOATBOBOFFSET(n) (FloatBobOffset[(n) < 0? 0 : (n) > FLOATBOBRES - 1? FLOATBOBRES - 1 : (n)]) // Player radius for movement checking. #define PLAYERRADIUS 16 // MAXRADIUS is for precalculated sector bounding boxes. #define MAXRADIUS 32 #define MAXMOVE 30 #define USERANGE 64 #define MELEERANGE 64 #define MISSILERANGE (32*64) #define LOOKDIR2DEG(x) ((x) * 85.0/110.0) #define LOOKDIR2RAD(x) (LOOKDIR2DEG(x)/180*PI) #define BASETHRESHOLD 100 // Follow a player exlusively for 3 seconds. #define sentient(mobj) ((mobj)->health > 0 && P_GetState((mobj)->type, SN_SEE)) extern int TimerGame; // Tic countdown for deathmatch. #define thinkerCap (*gi.thinkerCap) #define USE_MANA1 1 #define USE_MANA2 1 void P_SetPsprite(player_t* plr, int position, statenum_t stnum); void P_SetPspriteNF(player_t* plr, int position, statenum_t stnum); void P_SetupPsprites(player_t* plr); void P_MovePsprites(player_t* plr); void P_DropWeapon(player_t* plr); void P_ActivateMorphWeapon(player_t* plr); void P_PostMorphWeapon(player_t* plr, weapontype_t weapon); void P_TeleportOther(mobj_t* victim); void P_ArtiTeleportOther(player_t* plr); void ResetBlasted(mobj_t* mo); boolean P_UndoPlayerMorph(player_t* plr); #define FRICTION_NORMAL (0.90625f) #define FRICTION_FLY (0.91796875f) #define FRICTION_HIGH (0.5f) #define FRICTION_LOW (0.97265625f) // Time interval for item respawning. #define SPAWNQUEUE_MAX 128 extern int iquehead; extern int iquetail; extern mobjtype_t PuffType; extern mobj_t* MissileMobj; extern float* FloatBobOffset; void P_Thrust(player_t* plr, angle_t angle, float move); void P_ThrustMobj(mobj_t* mo, angle_t angle, float move); int P_FaceMobj(mobj_t* source, mobj_t* target, angle_t* delta); boolean P_SeekerMissile(mobj_t* mo, angle_t thresh, angle_t turnMax); void P_MobjThinker(mobj_t* mo); boolean P_HealRadius(player_t* plr); void P_BlastRadius(player_t* plr); void P_SpawnBloodSplatter(float x, float y, float z, mobj_t* origin); void P_SpawnBloodSplatter2(float x, float y, float z, mobj_t* origin); void P_CreateTIDList(void); boolean P_MobjChangeState(mobj_t* mo, statenum_t state); boolean P_SetMobjStateNF(mobj_t* mo, statenum_t state); void P_MobjRemoveFromTIDList(mobj_t* mo); void P_MobjInsertIntoTIDList(mobj_t* mo, int tid); mobj_t* P_FindMobjFromTID(int tid, int* searchPosition); boolean P_CheckMissileSpawn(mobj_t* mo); float P_MobjGetFriction(mobj_t* mo); void P_RipperBlood(mobj_t* mo); const terraintype_t* P_MobjGetFloorTerrainType(mobj_t* mo); boolean P_HitFloor(mobj_t* mo); void P_NoiseAlert(mobj_t* target, mobj_t* emmiter); int P_Massacre(void); boolean P_LookForMonsters(mobj_t* mo); void P_InitCreatureCorpseQueue(boolean corpseScan); #define MAXINTERCEPTS 128 extern intercept_t intercepts[MAXINTERCEPTS], *intercept_p; mobj_t* P_RoughMonsterSearch(mobj_t* mo, int distance); void P_Validate(); #define OPENRANGE (*(float*) DD_GetVariable(DD_OPENRANGE)) #define OPENTOP (*(float*) DD_GetVariable(DD_OPENTOP)) #define OPENBOTTOM (*(float*) DD_GetVariable(DD_OPENBOTTOM)) #define LOWFLOOR (*(float*) DD_GetVariable(DD_LOWFLOOR)) extern int clipmana[NUM_AMMO_TYPES]; void P_TouchSpecialMobj(mobj_t* special, mobj_t* toucher); void P_PoisonPlayer(player_t* plr, mobj_t* poisoner, int poison); int P_DamageMobj(mobj_t* target, mobj_t* inflictor, mobj_t* source, int damage, boolean stomping); int P_FallingDamage(player_t* plr); int P_PoisonDamage(player_t* plr, mobj_t* source, int damage, boolean playPainSound); boolean P_GiveMana(player_t* plr, ammotype_t mana, int count); boolean P_GiveArmor(player_t* plr, armortype_t armortype, int amount); boolean P_GiveBody(player_t* plr, int num); boolean P_GivePower(player_t* plr, powertype_t power); boolean P_MorphPlayer(player_t* plr); boolean A_LocalQuake(byte* args, mobj_t* victim); void C_DECL A_BridgeRemove(mobj_t* actor); boolean A_RaiseMobj(mobj_t* mo); boolean A_SinkMobj(mobj_t* mo); void C_DECL A_NoBlocking(mobj_t* mo); void C_DECL A_DeQueueCorpse(mobj_t* mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_anim.h0000644000175000017500000000202611357170242023066 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_anim.h: */ #ifndef __P_ANIM_H__ #define __P_ANIM_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_setup.h0000644000175000017500000000342011357170242023301 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_setup.h: Map setup routines */ #ifndef __X_SETUP_H__ #define __X_SETUP_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif // Map objects and their properties: enum { MO_NONE = 0, MO_THING, MO_XLINEDEF, MO_XSECTOR, MO_ID, MO_X, MO_Y, MO_Z, MO_ANGLE, MO_TYPE, MO_DOOMEDNUM, MO_FLAGS, MO_TAG, MO_ARG0, MO_ARG1, MO_ARG2, MO_ARG3, MO_ARG4, MO_SPECIAL }; void P_Init(void); void P_RegisterMapObjs(void); int P_HandleMapDataPropertyValue(uint id, int dtype, int prop, valuetype_t type, void *data); int P_HandleMapObjectStatusReport(int code, uint id, int dtype, void *data); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/jhexen.h0000644000175000017500000000605211357170242023107 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2006-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * jhexen.h: All jHexen Headers * * A convenience header for including all jHexen headers. */ #ifndef __JHEXEN_CONVENIENCE_H__ #define __JHEXEN_CONVENIENCE_H__ #include "../../jhexen/include/a_action.h" #include "../../jhexen/include/acfnlink.h" #include "../../jhexen/include/h2def.h" #include "../../jhexen/include/g_ctrl.h" #include "../../jhexen/include/g_game.h" #include "../../jhexen/include/in_lude.h" #include "../../jhexen/include/m_cheat.h" #include "../../jhexen/include/m_menu.h" #include "../../jhexen/include/m_random.h" #include "../../jhexen/include/mn_def.h" #include "../../jhexen/include/p_acs.h" #include "../../jhexen/include/p_anim.h" #include "../../jhexen/include/p_enemy.h" #include "../../jhexen/include/p_inter.h" #include "../../jhexen/include/p_lights.h" #include "../../jhexen/include/p_local.h" #include "../../jhexen/include/p_mapinfo.h" #include "../../jhexen/include/p_maputl.h" #include "../../jhexen/include/p_mobj.h" #include "../../jhexen/include/p_pillar.h" #include "../../jhexen/include/p_pspr.h" #include "../../jhexen/include/p_setup.h" #include "../../jhexen/include/p_sound.h" #include "../../jhexen/include/p_spec.h" #include "../../jhexen/include/p_telept.h" #include "../../jhexen/include/p_things.h" #include "../../jhexen/include/p_waggle.h" #include "../../jhexen/include/po_man.h" #include "../../jhexen/include/r_defs.h" #include "../../jhexen/include/r_local.h" #include "../../jhexen/include/s_sequence.h" #include "../../jhexen/include/sc_man.h" #include "../../jhexen/include/st_stuff.h" #include "../../jhexen/include/textdefs.h" #include "../../jhexen/include/version.h" #include "../../jhexen/include/x_api.h" #include "../../jhexen/include/x_console.h" #include "../../jhexen/include/x_config.h" #include "../../jhexen/include/x_event.h" #include "../../jhexen/include/x_items.h" #include "../../jhexen/include/x_main.h" #include "../../jhexen/include/x_player.h" #include "../../jhexen/include/x_refresh.h" #include "../../jhexen/include/x_state.h" #include "../../jhexen/include/x_think.h" #include "../../jhexen/include/xddefs.h" #endif // __JHEXEN_CONVENIENCE_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/acfnlink.h0000644000175000017500000002460511357170242023417 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * acfnlink.h: */ #ifndef __ACTION_LINK_H__ #define __ACTION_LINK_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "dd_share.h" typedef struct { char *name; // Name of the routine. void (C_DECL * func) (); // Pointer to the function. } actionlink_t; extern actionlink_t actionlinks[]; void C_DECL A_AddPlayerCorpse(); void C_DECL A_BatMove(); void C_DECL A_BatSpawn(); void C_DECL A_BatSpawnInit(); void C_DECL A_BellReset1(); void C_DECL A_BellReset2(); void C_DECL A_BishopAttack(); void C_DECL A_BishopAttack2(); void C_DECL A_BishopChase(); void C_DECL A_BishopDecide(); void C_DECL A_BishopDoBlur(); void C_DECL A_BishopMissileSeek(); void C_DECL A_BishopMissileWeave(); void C_DECL A_BishopPainBlur(); void C_DECL A_BishopPuff(); void C_DECL A_BishopSpawnBlur(); void C_DECL A_BounceCheck(); void C_DECL A_BridgeInit(); void C_DECL A_BridgeOrbit(); void C_DECL A_CentaurAttack(); void C_DECL A_CentaurAttack2(); void C_DECL A_CentaurDefend(); void C_DECL A_CentaurDropStuff(); void C_DECL A_CFlameAttack(); void C_DECL A_CFlameMissile(); void C_DECL A_CFlamePuff(); void C_DECL A_CFlameRotate(); void C_DECL A_Chase(); void C_DECL A_CheckBurnGone(); void C_DECL A_CheckFloor(); void C_DECL A_CheckSkullDone(); void C_DECL A_CheckSkullFloor(); void C_DECL A_CheckTeleRing(); void C_DECL A_CheckThrowBomb(); void C_DECL A_CHolyAttack(); void C_DECL A_CHolyAttack2(); void C_DECL A_CHolyCheckScream(); void C_DECL A_CHolyPalette(); void C_DECL A_CHolySeek(); void C_DECL A_CHolySpawnPuff(); void C_DECL A_CHolyTail(); void C_DECL A_ClassBossHealth(); void C_DECL A_ClericAttack(); void C_DECL A_CMaceAttack(); void C_DECL A_ContMobjSound(); void C_DECL A_CorpseBloodDrip(); void C_DECL A_CorpseExplode(); void C_DECL A_CStaffAttack(); void C_DECL A_CStaffCheck(); void C_DECL A_CStaffCheckBlink(); void C_DECL A_CStaffInitBlink(); void C_DECL A_CStaffMissileSlither(); void C_DECL A_DelayGib(); void C_DECL A_Demon2Death(); void C_DECL A_DemonAttack1(); void C_DECL A_DemonAttack2(); void C_DECL A_DemonDeath(); void C_DECL A_DragonAttack(); void C_DECL A_DragonCheckCrash(); void C_DECL A_DragonFlap(); void C_DECL A_DragonFlight(); void C_DECL A_DragonFX2(); void C_DECL A_DragonInitFlight(); void C_DECL A_DragonPain(); void C_DECL A_DropMace(); void C_DECL A_ESound(); void C_DECL A_EttinAttack(); void C_DECL A_Explode(); void C_DECL A_FaceTarget(); void C_DECL A_FastChase(); void C_DECL A_FAxeAttack(); void C_DECL A_FHammerAttack(); void C_DECL A_FHammerThrow(); void C_DECL A_FighterAttack(); void C_DECL A_FireConePL1(); void C_DECL A_FiredAttack(); void C_DECL A_FiredChase(); void C_DECL A_FiredRocks(); void C_DECL A_FiredSplotch(); void C_DECL A_FlameCheck(); void C_DECL A_FloatGib(); void C_DECL A_FogMove(); void C_DECL A_FogSpawn(); void C_DECL A_FPunchAttack(); void C_DECL A_FreeTargMobj(); void C_DECL A_FreezeDeath(); void C_DECL A_FreezeDeathChunks(); void C_DECL A_FSwordAttack(); void C_DECL A_FSwordFlames(); void C_DECL A_HideThing(); void C_DECL A_IceCheckHeadDone(); void C_DECL A_IceGuyAttack(); void C_DECL A_IceGuyChase(); void C_DECL A_IceGuyDie(); void C_DECL A_IceGuyLook(); void C_DECL A_IceGuyMissileExplode(); void C_DECL A_IceGuyMissilePuff(); void C_DECL A_IceSetTics(); void C_DECL A_KBolt(); void C_DECL A_KBoltRaise(); void C_DECL A_KoraxBonePop(); void C_DECL A_KoraxChase(); void C_DECL A_KoraxCommand(); void C_DECL A_KoraxDecide(); void C_DECL A_KoraxMissile(); void C_DECL A_KoraxStep(); void C_DECL A_KoraxStep2(); void C_DECL A_KSpiritRoam(); void C_DECL A_LastZap(); void C_DECL A_LeafCheck(); void C_DECL A_LeafSpawn(); void C_DECL A_LeafThrust(); void C_DECL A_Light0(); void C_DECL A_LightningClip(); void C_DECL A_LightningReady(); void C_DECL A_LightningRemove(); void C_DECL A_LightningZap(); void C_DECL A_Look(); void C_DECL A_Lower(); void C_DECL A_MageAttack(); void C_DECL A_MinotaurAtk1(); void C_DECL A_MinotaurAtk2(); void C_DECL A_MinotaurAtk3(); void C_DECL A_MinotaurCharge(); void C_DECL A_MinotaurChase(); void C_DECL A_MinotaurDecide(); void C_DECL A_MinotaurFade0(); void C_DECL A_MinotaurFade1(); void C_DECL A_MinotaurFade2(); void C_DECL A_MinotaurLook(); void C_DECL A_MinotaurRoam(); void C_DECL A_MLightningAttack(); void C_DECL A_MntrFloorFire(); void C_DECL A_MStaffAttack(); void C_DECL A_MStaffPalette(); void C_DECL A_MStaffTrack(); void C_DECL A_MStaffWeave(); void C_DECL A_MWandAttack(); void C_DECL A_NoBlocking(); void C_DECL A_NoGravity(); void C_DECL A_Pain(); void C_DECL A_PigAttack(); void C_DECL A_PigChase(); void C_DECL A_PigLook(); void C_DECL A_PigPain(); void C_DECL A_PoisonBagCheck(); void C_DECL A_PoisonBagDamage(); void C_DECL A_PoisonBagInit(); void C_DECL A_PoisonShroom(); void C_DECL A_PotteryCheck(); void C_DECL A_PotteryChooseBit(); void C_DECL A_PotteryExplode(); void C_DECL A_Quake(); void C_DECL A_QueueCorpse(); void C_DECL A_Raise(); void C_DECL A_ReFire(); void C_DECL A_RestoreArtifact(); void C_DECL A_RestoreSpecialThing1(); void C_DECL A_RestoreSpecialThing2(); void C_DECL A_Scream(); void C_DECL A_SerpentBirthScream(); void C_DECL A_SerpentChase(); void C_DECL A_SerpentCheckForAttack(); void C_DECL A_SerpentChooseAttack(); void C_DECL A_SerpentDiveSound(); void C_DECL A_SerpentHeadCheck(); void C_DECL A_SerpentHeadPop(); void C_DECL A_SerpentHide(); void C_DECL A_SerpentHumpDecide(); void C_DECL A_SerpentLowerHump(); void C_DECL A_SerpentMeleeAttack(); void C_DECL A_SerpentMissileAttack(); void C_DECL A_SerpentRaiseHump(); void C_DECL A_SerpentSpawnGibs(); void C_DECL A_SerpentUnHide(); void C_DECL A_SerpentWalk(); void C_DECL A_SetAltShadow(); void C_DECL A_SetReflective(); void C_DECL A_SetShootable(); void C_DECL A_ShedShard(); void C_DECL A_SinkGib(); void C_DECL A_SkullPop(); void C_DECL A_SmBounce(); void C_DECL A_SmokePuffExit(); void C_DECL A_SnoutAttack(); void C_DECL A_SoAExplode(); void C_DECL A_SorcBallOrbit(); void C_DECL A_SorcBallPop(); void C_DECL A_SorcBossAttack(); void C_DECL A_SorcererBishopEntry(); void C_DECL A_SorcFX1Seek(); void C_DECL A_SorcFX2Orbit(); void C_DECL A_SorcFX2Split(); void C_DECL A_SorcFX4Check(); void C_DECL A_SorcSpinBalls(); void C_DECL A_SpawnBishop(); void C_DECL A_SpawnFizzle(); void C_DECL A_SpeedBalls(); void C_DECL A_SpeedFade(); void C_DECL A_Summon(); void C_DECL A_TeloSpawnA(); void C_DECL A_TeloSpawnB(); void C_DECL A_TeloSpawnC(); void C_DECL A_TeloSpawnD(); void C_DECL A_ThrustBlock(); void C_DECL A_ThrustImpale(); void C_DECL A_ThrustInitDn(); void C_DECL A_ThrustInitUp(); void C_DECL A_ThrustLower(); void C_DECL A_ThrustRaise(); void C_DECL A_TreeDeath(); void C_DECL A_UnHideThing(); void C_DECL A_UnSetInvulnerable(); void C_DECL A_UnSetReflective(); void C_DECL A_UnSetShootable(); void C_DECL A_WeaponReady(); void C_DECL A_WraithChase(); void C_DECL A_WraithFX2(); void C_DECL A_WraithFX3(); void C_DECL A_WraithInit(); void C_DECL A_WraithLook(); void C_DECL A_WraithMelee(); void C_DECL A_WraithMissile(); void C_DECL A_WraithRaise(); void C_DECL A_WraithRaiseInit(); void C_DECL A_ZapMimic(); void C_DECL A_FSwordAttack2(); void C_DECL A_CHolyAttack3(); void C_DECL A_MStaffAttack2(); void C_DECL A_SorcBallOrbit(); void C_DECL A_SorcSpinBalls(); void C_DECL A_SpeedBalls(); void C_DECL A_SlowBalls(); void C_DECL A_StopBalls(); void C_DECL A_AccelBalls(); void C_DECL A_DecelBalls(); void C_DECL A_SorcBossAttack(); void C_DECL A_SpawnFizzle(); void C_DECL A_CastSorcererSpell(); void C_DECL A_SorcUpdateBallAngle(); void C_DECL A_BounceCheck(); void C_DECL A_SorcFX1Seek(); void C_DECL A_SorcOffense1(); void C_DECL A_SorcOffense2(); // Inventory void C_DECL A_Invulnerability(); void C_DECL A_Health(); void C_DECL A_SuperHealth(); void C_DECL A_HealRadius(); void C_DECL A_SummonTarget(); void C_DECL A_Torch(); void C_DECL A_Egg(); void C_DECL A_Wings(); void C_DECL A_BlastRadius(); void C_DECL A_PoisonBag(); void C_DECL A_TeleportOther(); void C_DECL A_Speed(); void C_DECL A_BoostMana(); void C_DECL A_BoostArmor(); void C_DECL A_Teleport(); void C_DECL A_PuzzSkull(); void C_DECL A_PuzzGemBig(); void C_DECL A_PuzzGemRed(); void C_DECL A_PuzzGemGreen1(); void C_DECL A_PuzzGemGreen2(); void C_DECL A_PuzzGemBlue1(); void C_DECL A_PuzzGemBlue2(); void C_DECL A_PuzzBook1(); void C_DECL A_PuzzBook2(); void C_DECL A_PuzzSkull2(); void C_DECL A_PuzzFWeapon(); void C_DECL A_PuzzCWeapon(); void C_DECL A_PuzzMWeapon(); void C_DECL A_PuzzGear1(); void C_DECL A_PuzzGear2(); void C_DECL A_PuzzGear3(); void C_DECL A_PuzzGear4(); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/r_local.h0000644000175000017500000000542211357170242023241 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * r_local.h: */ #ifndef __R_LOCAL_H__ #define __R_LOCAL_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "jhexen.h" #include "s_sequence.h" #define ANGLETOSKYSHIFT 22 // sky map is 256*128*4 maps. #define BASEYCENTER 100 #define MAXWIDTH 1120 #define MAXHEIGHT 832 #define PI 3.141592657 #define CENTERY (SCREENHEIGHT/2) #define MINZF (4) #define FIELDOFVIEW 2048 // fineangles in the SCREENWIDTH wide window. // Lighting constants. #define LIGHTLEVELS 16 #define LIGHTSEGSHIFT 4 #define MAXLIGHTSCALE 48 #define LIGHTSCALESHIFT 12 #define MAXLIGHTZ 128 #define LIGHTZSHIFT 20 #define NUMCOLORMAPS 32 // Number of diminishing. #define INVERSECOLORMAP 32 // Player colors. #define AM_PLR1_COLOR 157 // Blue #define AM_PLR2_COLOR 177 // Red #define AM_PLR3_COLOR 137 // Yellow #define AM_PLR4_COLOR 198 // Green #define AM_PLR5_COLOR 215 // Jade #define AM_PLR6_COLOR 32 // White #define AM_PLR7_COLOR 106 // Hazel #define AM_PLR8_COLOR 234 // Purple // Map data is in the main engine, so these are helpers... extern angle_t clipangle; extern int viewangletox[FINEANGLES / 2]; extern angle_t xtoviewangle[SCREENWIDTH + 1]; extern fixed_t finetangent[FINEANGLES / 2]; extern fixed_t rw_distance; extern angle_t rw_normalangle; extern int centerx, centery; extern int flyheight; extern int sscount, linecount, loopcount; extern int extralight; void R_InitData(void); void R_UpdateData(void); extern fixed_t pspritescale, pspriteiscale; void R_UpdateTranslationTables(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_maputl.h0000644000175000017500000000222511357170242023445 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_maputl.h: Movement/collision utility functions jHexen - specific. */ #ifndef __P_MAPUTL_H__ #define __P_MAPUTL_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "p_mobj.h" void P_ApplyTorque(mobj_t *mo); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_mapinfo.h0000644000175000017500000000425111357170242023575 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_mapinfo.h: MAPINFO definitions. */ #ifndef __P_MAPINFO_H__ #define __P_MAPINFO_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif void P_InitMapInfo(void); void P_InitMapMusicInfo(void); int P_GetMapCluster(uint map); uint P_TranslateMap(uint map); int P_GetMapCDTrack(uint map); uint P_GetMapWarpTrans(uint map); uint P_GetMapNextMap(uint map); materialnum_t P_GetMapSky1Material(uint map); materialnum_t P_GetMapSky2Material(uint map); char* P_GetMapName(uint map); float P_GetMapSky1ScrollDelta(uint map); float P_GetMapSky2ScrollDelta(uint map); boolean P_GetMapDoubleSky(uint map); boolean P_GetMapLightning(uint map); int P_GetMapFadeTable(uint map); char* P_GetMapSongLump(uint map); void P_PutMapSongLump(uint map, char* lumpName); int P_GetCDStartTrack(void); int P_GetCDEnd1Track(void); int P_GetCDEnd2Track(void); int P_GetCDEnd3Track(void); int P_GetCDIntermissionTrack(void); int P_GetCDTitleTrack(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_player.h0000644000175000017500000001026111357170242023446 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_player.h: */ #ifndef __X_PLAYER_H__ #define __X_PLAYER_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "x_items.h" #include "p_pspr.h" #include "p_mobj.h" #include "g_controls.h" // // Player states. // typedef enum { // Playing or camping. PST_LIVE, // Dead on the ground, view follows killer. PST_DEAD, // Ready to restart/respawn??? PST_REBORN } playerstate_t; // // Player internal flags, for cheats and debug. // #if 0 typedef enum { // No clipping, walk through barriers. CF_NOCLIP = 1, // No damage, no health loss. CF_GODMODE = 2, // Not really a cheat, just a debug aid. CF_NOMOMENTUM = 4 } cheat_t; #endif #define CF_NOCLIP (1) // No clipping, walk through barriers. #define CF_GODMODE (2) // No damage, no health loss. #define CF_NOMOMENTUM (4) // Not really a cheat, just a debug aid. // Extended player information, Hexen specific. typedef struct player_s { ddplayer_t* plr; // Pointer to the engine's player data. playerstate_t playerState; playerclass_t class; // Player class type. playerbrain_t brain; int flyHeight; int health; // Only used between maps, mo->health is used during. int armorPoints[NUMARMOR]; int powers[NUM_POWER_TYPES]; int keys; int pieces; // Fourth Weapon pieces. weapontype_t readyWeapon; weapontype_t pendingWeapon; // wp_nochange if not changing. struct playerweapon_s { boolean owned; } weapons[NUM_WEAPON_TYPES]; struct playerammo_s { int owned; } ammo[NUM_AMMO_TYPES]; // Mana. int attackDown, useDown; // true if button down last tic. int cheats; // Bit flags. signed int frags[MAXPLAYERS]; // Kills of other players. int refire; // Refired shots are less accurate. int killCount, itemCount, secretCount; // For intermission. int damageCount, bonusCount; // For screen flashing. int poisonCount; // Screen flash for poison damage. mobj_t* poisoner; // NULL for non-player mobjs. mobj_t* attacker; // Who did damage (NULL for floors). int colorMap; // 0-3 for which color to draw player. pspdef_t pSprites[NUMPSPRITES]; // view sprites (gun, etc). int morphTics; // Player is a pig if > 0. int jumpTics; // Delay the next jump for a moment. int airCounter; int rebornWait; // The player can be reborn if this counter is zero. boolean centering; unsigned int worldTimer; // Total time the player's been playing. int update, startSpot; float viewOffset[3]; // Relative to position of the player mobj. float viewZ; // Focal origin above r.z. float viewHeight; // Base height above floor for viewZ. float viewHeightDelta; float bob; // Bounded/scaled total momentum. // Target view to a mobj (NULL=disabled). mobj_t* viewLock; // $democam int lockFull; } player_t; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_inter.h0000644000175000017500000000230611357170242023264 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_inter.h: */ #ifndef __P_INTER_H__ #define __P_INTER_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "x_player.h" boolean P_GiveArmor(player_t* plr, armortype_t type, int points); boolean P_GiveArmor2(player_t* plr, armortype_t type, int amount); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_things.h0000644000175000017500000000203411357170242023435 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_things.h: */ #ifndef __P_THINGS_H__ #define __P_THINGS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/h2def.h0000644000175000017500000002667711357170242022635 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * h2def.h: */ #ifndef __H2DEF_H__ #define __H2DEF_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #ifdef WIN32 #pragma warning(disable:4244) #endif #include #include #include "doomsday.h" #include "dd_api.h" #include "version.h" #include "info.h" // Predefined with some OS. #ifdef UNIX #include #define MAXCHAR SCHAR_MAX #define MAXSHORT SHRT_MAX #define MAXINT INT_MAX #define MAXLONG LONG_MAX #define MINCHAR SCHAR_MIN #define MINSHORT SHRT_MIN #define MININT INT_MIN #define MINLONG LONG_MIN #else /* not UNIX */ #define MAXCHAR ((char)0x7f) #define MAXSHORT ((short)0x7fff) // Max pos 32-bit int. #define MAXINT ((int)0x7fffffff) #define MAXLONG ((long)0x7fffffff) #define MINCHAR ((char)0x80) #define MINSHORT ((short)0x8000) // Max negative 32-bit integer. #define MININT ((int)0x80000000) #define MINLONG ((long)0x80000000) #endif #define Set DD_SetInteger #define Get DD_GetInteger #define CONFIGFILE GAMENAMETEXT".cfg" #define DEFSFILE GAMENAMETEXT"\\"GAMENAMETEXT".ded" #define DATAPATH "}data\\"GAMENAMETEXT"\\" #define STARTUPWAD "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".wad" #define STARTUPPK3 "}data\\"GAMENAMETEXT"\\"GAMENAMETEXT".pk3" // Verbose messages. #define VERBOSE(code) { if(verbose >= 1) { code; } } #define VERBOSE2(code) { if(verbose >= 2) { code; } } extern game_import_t gi; extern game_export_t gx; // // Global parameters/defines. // #define MOBJINFO (*gi.mobjInfo) #define STATES (*gi.states) #define VALIDCOUNT (*gi.validCount) // Game mode handling - identify IWAD version to handle IWAD dependend // animations etc. typedef enum { shareware, // 4 map demo registered, // HEXEN registered extended, // DeathKings indetermined, // Well, no IWAD found. NUM_GAME_MODES } gamemode_t; // Game mode bits for the above. #define GM_SHAREWARE 0x1 // 4 map demo #define GM_REGISTERED 0x2 // HEXEN registered #define GM_EXTENDED 0x4 // DeathKings #define GM_INDETERMINED 0x8 // Well, no IWAD found. #define GM_ANY (GM_SHAREWARE|GM_REGISTERED|GM_EXTENDED) #define GM_NOTSHAREWARE (GM_REGISTERED|GM_EXTENDED) #define SCREENWIDTH 320 #define SCREENHEIGHT 200 #define SCREEN_MUL 1 #define MAXPLAYERS 8 // Playsim, core timing rate in cycles per second. #define TICRATE 35 #define TICSPERSEC 35 /** * Armor types. */ typedef enum { ARMOR_ARMOR, ARMOR_SHIELD, ARMOR_HELMET, ARMOR_AMULET, NUMARMOR } armortype_t; /** * Player Classes */ typedef enum { PCLASS_FIGHTER, PCLASS_CLERIC, PCLASS_MAGE, PCLASS_PIG, NUM_PLAYER_CLASSES } playerclass_t; #define PCLASS_INFO(class) (&classInfo[class]) typedef struct classinfo_s{ const char* niceName; boolean userSelectable; mobjtype_t mobjType; int normalState; int runState; int attackState; int attackEndState; int maxArmor; int autoArmorSave; fixed_t maxMove; fixed_t forwardMove[2]; // walk, run. fixed_t sideMove[2]; // walk, run. int moveMul; // multiplier for above. int turnSpeed[3]; // [normal, speed, initial]. int jumpTics; // wait inbetween jumps. int failUseSound; // sound played when a use fails. int armorIncrement[NUMARMOR]; int pieceX[3]; // temp. } classinfo_t; extern classinfo_t classInfo[NUM_PLAYER_CLASSES]; /** * Game state (hi-level). * * The current state of the game: whether we are playing, gazing at the * intermission screen, the game final animation, or a demo. */ typedef enum { GS_MAP, GS_INTERMISSION, GS_FINALE, GS_STARTUP, GS_WAITING, GS_INFINE, NUM_GAME_STATES } gamestate_t; /** * Difficulty/skill settings/filters. */ typedef enum { SM_BABY, SM_EASY, SM_MEDIUM, SM_HARD, SM_NIGHTMARE, NUM_SKILL_MODES } skillmode_t; /** * Keys (as in, keys to lockables). */ typedef enum { KT_KEY1, KT_KEY2, KT_KEY3, KT_KEY4, KT_KEY5, KT_KEY6, KT_KEY7, KT_KEY8, KT_KEY9, KT_KEYA, KT_KEYB, NUM_KEY_TYPES } keytype_t; /** * Weapon ids. * * The defined weapons, including a marker indicating user has not changed * weapon. */ typedef enum { WT_FIRST, WT_SECOND, WT_THIRD, WT_FOURTH, NUM_WEAPON_TYPES, WT_NOCHANGE // No pending weapon change. } weapontype_t; #define WPIECE1 1 #define WPIECE2 2 #define WPIECE3 4 #define NUMWEAPLEVELS 1 // Number of weapon power levels. /** * Ammunition types. */ typedef enum { AT_BLUEMANA, AT_GREENMANA, NUM_AMMO_TYPES, AT_NOAMMO // Takes no ammo, used for staff, gauntlets. } ammotype_t; #define MAX_MANA 200 /** * Powers, bestowable upon players only. */ typedef enum { PT_NONE, PT_INVULNERABILITY, PT_ALLMAP, PT_INFRARED, PT_FLIGHT, PT_SHIELD, PT_HEALTH2, PT_SPEED, PT_MINOTAUR, NUM_POWER_TYPES } powertype_t; #define INVULNTICS (30*TICRATE) #define INVISTICS (60*TICRATE) #define INFRATICS (120*TICRATE) #define IRONTICS (60*TICRATE) #define WPNLEV2TICS (40*TICRATE) #define FLIGHTTICS (60*TICRATE) #define SPEEDTICS (45*TICRATE) #define MORPHTICS (40*TICRATE) //#define MAULATORTICS (25*TICRATE) /** * Inventory Item Types: */ typedef enum { IIT_NONE = 0, IIT_FIRST = 1, IIT_INVULNERABILITY = IIT_FIRST, IIT_HEALTH, IIT_SUPERHEALTH, IIT_HEALINGRADIUS, IIT_SUMMON, IIT_TORCH, IIT_EGG, IIT_FLY, IIT_BLASTRADIUS, IIT_POISONBAG, IIT_TELEPORTOTHER, IIT_SPEED, IIT_BOOSTMANA, IIT_BOOSTARMOR, IIT_TELEPORT, // Puzzle items: IIT_FIRSTPUZZITEM, IIT_PUZZSKULL = IIT_FIRSTPUZZITEM, IIT_PUZZGEMBIG, IIT_PUZZGEMRED, IIT_PUZZGEMGREEN1, IIT_PUZZGEMGREEN2, IIT_PUZZGEMBLUE1, IIT_PUZZGEMBLUE2, IIT_PUZZBOOK1, IIT_PUZZBOOK2, IIT_PUZZSKULL2, IIT_PUZZFWEAPON, IIT_PUZZCWEAPON, IIT_PUZZMWEAPON, IIT_PUZZGEAR1, IIT_PUZZGEAR2, IIT_PUZZGEAR3, IIT_PUZZGEAR4, NUM_INVENTORYITEM_TYPES } inventoryitemtype_t; #define MAXINVITEMCOUNT (25) #define BLINKTHRESHOLD (4*TICRATE) enum { VX, VY, VZ }; // Vertex indices. enum { CR, CG, CB, CA }; // Color indices. #define IS_SERVER (Get(DD_SERVER)) #define IS_CLIENT (Get(DD_CLIENT)) #define IS_NETGAME (Get(DD_NETGAME)) #define IS_DEDICATED (Get(DD_DEDICATED)) #define CVAR(typ, x) (*(typ*)Con_GetVariable(x)->ptr) #define SFXVOLUME (Get(DD_SFX_VOLUME)/17) #define MUSICVOLUME (Get(DD_MUSIC_VOLUME)/17) #define CONSOLEPLAYER (Get(DD_CONSOLEPLAYER)) #define DISPLAYPLAYER (Get(DD_DISPLAYPLAYER)) #define GAMETIC (*((timespan_t*) DD_GetVariable(DD_GAMETIC))) // Uncomment, to enable all timebomb stuff. #define TIMEBOMB_YEAR (95) // years since 1900 #define TIMEBOMB_STARTDATE (268) // initial date (9/26) #define TIMEBOMB_ENDDATE (301) // end date (10/29) extern int maulatorSeconds; #define MAULATORTICS ((unsigned int) maulatorSeconds * TICSPERSEC) // Most damage defined using HITDICE #define HITDICE(a) ((1 + (P_Random() & 7)) * (a)) #define SBARHEIGHT (39) // status bar height at bottom of screen #define TELEFOGHEIGHT (32) #define DEFAULT_PLAYER_VIEWHEIGHT (48) extern fixed_t finesine[5 * FINEANGLES / 4]; extern fixed_t *finecosine; // Set if homebrew PWAD stuff has been added. extern boolean modifiedgame; #define MAX_PLAYER_STARTS (8) void H2_Main(void); void G_IdentifyVersion(void); void G_CommonPreInit(void); void G_CommonPostInit(void); int G_GetInteger(int id); void* G_GetVariable(int id); void G_DeathMatchSpawnPlayer(int playernum); uint G_GetMapNumber(uint episode, uint map); void G_InitNew(skillmode_t skill, uint episode, uint map); void G_DeferedInitNew(skillmode_t skill, uint episode, uint map); void G_DeferredNewGame(skillmode_t skill); void G_DeferedPlayDemo(char* demo); void G_DoPlayDemo(void); void G_LoadGame(int slot); void G_DoLoadGame(void); void G_PlayDemo(char* name); void G_TimeDemo(char* name); void G_LeaveMap(uint newMap, uint entryPoint, boolean secretExit); void G_StartNewGame(skillmode_t skill); void G_StartNewInit(void); void G_WorldDone(void); void G_ScreenShot(void); void G_DoReborn(int playernum); void G_StopDemo(void); void G_DemoEnds(void); void G_DemoAborted(void); void G_Ticker(timespan_t ticLength); boolean G_Responder(event_t* ev); void P_Init(void); void P_SetupMap(uint episode, uint map, int playermask, skillmode_t skill); extern boolean setsizeneeded; extern int localQuakeHappening[MAXPLAYERS]; byte P_Random(void); void M_ResetRandom(void); extern unsigned char rndtable[256]; void SC_Open(const char* name); void SC_OpenLump(lumpnum_t lump); void SC_OpenFile(const char* name); void SC_OpenFileCLib(const char* name); void SC_Close(void); boolean SC_GetString(void); void SC_MustGetString(void); void SC_MustGetStringName(char* name); boolean SC_GetNumber(void); void SC_MustGetNumber(void); void SC_UnGet(void); boolean SC_Compare(char* text); int SC_MatchString(char** strings); int SC_MustMatchString(char** strings); void SC_ScriptError(char* message); extern char* sc_String; extern int sc_Number; extern int sc_Line; extern boolean sc_End; extern boolean sc_Crossed; extern boolean sc_FileScripts; extern const char* sc_ScriptsDir; //---------------------- // Chat mode (CT_chat.c) //---------------------- void CT_Init(void); void CT_Drawer(void); boolean CT_Responder(event_t* ev); void CT_Ticker(void); char CT_dequeueChatChar(void); extern boolean chatmodeon; void Draw_TeleportIcon(void); #endif // __H2DEF_H__ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_main.h0000644000175000017500000000326411357170242023103 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_main.h: */ #ifndef __X_MAIN_H__ #define __X_MAIN_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif extern boolean noMonstersParm; // checkparm of -nomonsters extern boolean respawnParm; // checkparm of -respawn extern boolean turboParm; // checkparm of -turbo extern boolean randomClassParm; // checkparm of -randclass extern boolean devParm; // checkparm of -devparm extern float turboMul; // Multiplier for turbo. extern int gameModeBits; extern char gameModeString[]; extern char *borderLumps[]; // Default font colours. extern const float defFontRGB[]; extern const float defFontRGB2[]; void G_DetectIWADs(void); void G_PreInit(void); void G_PostInit(void); void G_Shutdown(void); void G_EndFrame(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/in_lude.h0000644000175000017500000000232011357170242023237 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * in_lude.h: */ #ifndef __IN_LUDE_H__ #define __IN_LUDE_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif extern boolean intermission; extern int interState; void IN_Init(void); void IN_Stop(void); void IN_Ticker(void); void IN_Drawer(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/xddefs.h0000644000175000017500000000414511357170242023104 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2004-2009 Jaakko Keränen *\author Copyright © 2006-2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * xddefs.h: */ #ifndef __XDDEFS_H__ #define __XDDEFS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif // Base plane ids. enum { PLN_FLOOR, PLN_CEILING }; #define ML_BLOCKMONSTERS 0x0002 #define ML_SECRET 0x0020 // don't map as two sided: IT'S A SECRET! #define ML_SOUNDBLOCK 0x0040 // don't let sound cross two of these #define ML_DONTDRAW 0x0080 // don't draw on the automap #define ML_MAPPED 0x0100 // set if already drawn in automap #define ML_REPEAT_SPECIAL 0x0200 // special is repeatable #define ML_SPAC_SHIFT 10 #define ML_SPAC_MASK 0x1c00 #define GET_SPAC(flags) ((flags&ML_SPAC_MASK)>>ML_SPAC_SHIFT) // Special activation types #define SPAC_CROSS 0 // when player crosses line #define SPAC_USE 1 // when player uses line #define SPAC_MCROSS 2 // when monster crosses line #define SPAC_IMPACT 3 // when projectile hits line #define SPAC_PUSH 4 // when player/monster pushes line #define SPAC_PCROSS 5 // when projectile crosses line #endif // __XDDEFS__ deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/p_acs.h0000644000175000017500000000606411357170242022716 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * p_acs.h: ACS scripting system. */ #ifndef __P_ACS_H__ #define __P_ACS_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #define MAX_ACS_SCRIPT_VARS 10 #define MAX_ACS_MAP_VARS 32 #define MAX_ACS_WORLD_VARS 64 #define ACS_STACK_DEPTH 32 typedef enum aste_e { ASTE_INACTIVE, ASTE_RUNNING, ASTE_SUSPENDED, ASTE_WAITING_FOR_TAG, ASTE_WAITING_FOR_POLY, ASTE_WAITING_FOR_SCRIPT, ASTE_TERMINATING } aste_t; typedef struct acsinfo_s { int number; const int* address; int argCount; aste_t state; int waitValue; } acsinfo_t; typedef struct acs_s { thinker_t thinker; mobj_t* activator; linedef_t* line; int side; int number; int infoIndex; int delayCount; int stack[ACS_STACK_DEPTH]; int stackPtr; int vars[MAX_ACS_SCRIPT_VARS]; const int* ip; } acs_t; typedef struct acsstore_s { uint map; // Target map. int script; // Script number on target map. byte args[4]; // Padded to 4 for alignment. } acsstore_t; extern int ACScriptCount; extern const byte* ActionCodeBase; extern acsinfo_t* ACSInfo; extern int MapVars[MAX_ACS_MAP_VARS]; extern int WorldVars[MAX_ACS_WORLD_VARS]; extern int ACSStoreSize; extern acsstore_t* ACSStore; void P_LoadACScripts(int lump); boolean P_StartACS(int number, uint map, byte* args, mobj_t* activator, linedef_t* line, int side); boolean P_StartLockedACS(linedef_t* line, byte* args, mobj_t* mo, int side); boolean P_TerminateACS(int number, uint map); boolean P_SuspendACS(int number, uint map); void T_InterpretACS(acs_t* script); void P_TagFinished(int tag); void P_PolyobjFinished(int po); void P_ACSInitNewGame(void); void P_CheckACSStore(uint map); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/g_game.h0000644000175000017500000000363211357170242023046 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * g_game.h: */ #ifndef __G_GAME_H__ #define __G_GAME_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "p_mobj.h" extern int debugSound; // debug flag for displaying sound info extern uint gameEpisode; extern uint gameMap; extern skillmode_t gameSkill; extern boolean deathmatch; extern boolean userGame; extern skillmode_t dSkill; extern uint rebornPosition; extern uint nextMap; extern uint nextMapEntryPoint; extern int gsvMapMusic; void R_InitRefresh(void); void R_GetTranslation(int plrClass, int plrColor, int* tclass, int* tmap); void R_SetTranslation(mobj_t* mo); void G_PrintMapList(void); void G_PlayerReborn(int player); void G_SaveGame(int slot, const char* description); uint G_GetNextMap(uint episode, uint map, boolean secretExit); boolean P_MapExists(uint episode, uint map); void P_GetMapLumpName(uint episode, uint map, char* lumpName); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_state.h0000644000175000017500000000450011357170242023271 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2003-2009 Jaakko Keränen *\author Copyright © 2005-2009 Daniel Swanson *\author Copyright © 1999 Activision * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_state.h: All the global variables that store the internal state. */ #ifndef __X_STATE_H__ #define __X_STATE_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif // We need the playr data structure as well. #include "x_player.h" #ifdef __GNUG__ #pragma interface #endif // ------------------------ // Command line parameters. // extern int verbose; // ------------------------- // Status flags for refresh. // extern boolean paused; // Game Pause? // This one is related to the 3-screen display mode. // ANG90 = left side, ANG270 = right extern int viewangleoffset; // Timer, for scores. extern int mapStartTic; // Game tic at map start. extern int mapTime; // Tics in game play for par. extern int actualMapTime; // Quit after playing a demo from cmdline. extern boolean singledemo; //----------------------------- // Internal parameters, fixed. // These are set by the engine, and not changed // according to user inputs. Partly load from // WAD, partly set at startup time. #define gametic Get(DD_GAMETIC) // Bookkeeping on players - state. extern player_t players[MAXPLAYERS]; //----------------------------------------- // Internal parameters, used for engine. // // if true, load all graphics at map load extern boolean precache; extern int bodyqueslot; #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/x_console.h0000644000175000017500000000220311357170242023611 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * x_console.h: */ #ifndef __X_CONSOLE_H__ #define __X_CONSOLE_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif void G_ConsoleRegistration(void); void G_ConsoleBg(int* width, int* height); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/include/m_menu.h0000644000175000017500000000226211357170242023105 0ustar keeskees/**\file *\section License * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * *\author Copyright © 2009 Daniel Swanson * * 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 St, Fifth Floor, * Boston, MA 02110-1301 USA */ /** * m_menu.h: Menu widget stuff, episode selection and such. */ #ifndef __M_MENU_H__ #define __M_MENU_H__ #ifndef __JHEXEN__ # error "Using jHexen headers without __JHEXEN__" #endif #include "hu_stuff.h" void M_LoadData(void); boolean MN_CurrentMenuHasBackground(void); #endif deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/0000755000175000017500000000000011523516204020745 5ustar keeskeesdeng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/special.ded0000644000175000017500000000005311357170242023044 0ustar keeskees# jHexen: Effects Header { Version = 5; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/jhexen.ded0000644000175000017500000000116511357170242022712 0ustar keeskees# # -=- jHexen Definitions -=- # # This file is overwritten on every upgrade. Add custom definitions # to User.ded. # # For information about DED syntax and semantics, see Doc\DEDDoc.txt. # Header { Version = 5; Default model scale = 1.2; Model path = "data\jhexen\models"; } Include "flags.ded"; Include "objects.ded"; Include "sprites.ded"; Include "materials.ded"; Include "audio.ded"; Include "special.ded"; Include "details.ded"; Include "lights.ded"; Include "maps.ded"; Include "finales.ded"; Include "text.ded"; Include "values.ded"; Include "models.ded"; Include "user.ded"; IncludeIf Not -noauto "auto\*.ded"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/flags.ded0000644000175000017500000000602011357170242022520 0ustar keeskees# jHexen: Flags # Mobj flags: Flag { ID = "mf_special"; Value = 0x1; } Flag { ID = "mf_solid"; Value = 0x2; } Flag { ID = "mf_shootable"; Value = 0x4; } Flag { ID = "mf_nosector"; Value = 0x8; } Flag { ID = "mf_noblockmap"; Value = 0x10; } Flag { ID = "mf_ambush"; Value = 0x20; } Flag { ID = "mf_justhit"; Value = 0x40; } Flag { ID = "mf_justattacked"; Value = 0x80; } Flag { ID = "mf_spawnceiling"; Value = 0x100; } Flag { ID = "mf_nogravity"; Value = 0x200; } Flag { ID = "mf_dropoff"; Value = 0x400; } Flag { ID = "mf_pickup"; Value = 0x800; } Flag { ID = "mf_noclip"; Value = 0x1000; } Flag { ID = "mf_slide"; Value = 0x2000; } Flag { ID = "mf_float"; Value = 0x4000; } Flag { ID = "mf_teleport"; Value = 0x8000; } Flag { ID = "mf_missile"; Value = 0x10000; } Flag { ID = "mf_altshadow"; Value = 0x20000; } Flag { ID = "mf_shadow"; Value = 0x40000; } Flag { ID = "mf_noblood"; Value = 0x80000; } Flag { ID = "mf_corpse"; Value = 0x100000; } Flag { ID = "mf_infloat"; Value = 0x200000; } Flag { ID = "mf_countkill"; Value = 0x400000; } Flag { ID = "mf_icecorpse"; Value = 0x800000; } Flag { ID = "mf_skullfly"; Value = 0x1000000; } Flag { ID = "mf_notdmatch"; Value = 0x2000000; } Flag { ID = "mf_translation"; Value = 0x1C000000; } Flag { ID = "mf_transshift"; Value = 0x1A; } Flag { ID = "mf_local"; Value = 0x20000000; } Flag { ID = "mf_brightexplode"; Value = 0x40000000; } Flag { ID = "mf_viewalign"; Value = 0x80000000; } Flag { ID = "mf_brightshadow"; Value = 0x60000; } # Mobj flags2: Flag { ID = "mf2_lograv"; Value = 0x1; } Flag { ID = "mf2_windthrust"; Value = 0x2; } Flag { ID = "mf2_floorbounce"; Value = 0x4; } Flag { ID = "mf2_blasted"; Value = 0x8; } Flag { ID = "mf2_fly"; Value = 0x10; } Flag { ID = "mf2_floorclip"; Value = 0x20; } Flag { ID = "mf2_spawnfloat"; Value = 0x40; } Flag { ID = "mf2_noteleport"; Value = 0x80; } Flag { ID = "mf2_rip"; Value = 0x100; } Flag { ID = "mf2_pushable"; Value = 0x200; } Flag { ID = "mf2_slide"; Value = 0x400; } Flag { ID = "mf2_passmobj"; Value = 0x1000; } Flag { ID = "mf2_cannotpush"; Value = 0x2000; } Flag { ID = "mf2_dropped"; Value = 0x4000; } Flag { ID = "mf2_boss"; Value = 0x8000; } Flag { ID = "mf2_firedamage"; Value = 0x10000; } Flag { ID = "mf2_nodmgthrust"; Value = 0x20000; } Flag { ID = "mf2_telestomp"; Value = 0x40000; } Flag { ID = "mf2_floatbob"; Value = 0x80000; } Flag { ID = "mf2_dontdraw"; Value = 0x100000; } Flag { ID = "mf2_impact"; Value = 0x200000; } Flag { ID = "mf2_pushwall"; Value = 0x400000; } Flag { ID = "mf2_mcross"; Value = 0x800000; } Flag { ID = "mf2_pcross"; Value = 0x1000000; } Flag { ID = "mf2_cantleavefloorpic"; Value = 0x2000000; } Flag { ID = "mf2_nonshootable"; Value = 0x4000000; } Flag { ID = "mf2_invulnerable"; Value = 0x8000000; } Flag { ID = "mf2_dormant"; Value = 0x10000000; } Flag { ID = "mf2_icedamage"; Value = 0x20000000; } Flag { ID = "mf2_seekermissile"; Value = 0x40000000; } Flag { ID = "mf2_reflective"; Value = 0x80000000; } # Mobj flags3: Flag { ID = "mf3_noinfight"; Value = 0x1; } # # Obsolete (unused) flags: # Flag { ID = "mf2_onmobj"; Value = 0; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/maps.ded0000644000175000017500000000037711357170242022375 0ustar keeskees# jHexen: Map Info # # Note that here we only have a wildcard Map Info. The real data is # read from Hexen's MAPINFO lump. Header { Version = 6; } # We need this only with the 4-level demo. SkipIf Not hexen-demo; Map Info { ID = "*"; Gravity = 1; }deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/anim.ded0000644000175000017500000000521311357170242022353 0ustar keeskees# jHexen: Additional Animation Sequences # # Hexen uses the ANIMDEFS lump to define texture animation sequences. # In order to remain compatible with existing WADs, jHexen reads # ANIMDEFS and creates texture animation groups for the sequences in it. # The flags "tgf_smooth" and "tgf_first_only" are set for each group. # # Additional sequences can be defined using Group definitions. # # Precache groups. # Group { Flags = precache; Texture { ID = "BOSSK1"; Tics = 0; }; Texture { ID = "BOSSK2"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SPAWN1"; Tics = 0; }; Texture { ID = "SPAWN2"; Tics = 0; }; Texture { ID = "SPAWN3"; Tics = 0; }; Texture { ID = "SPAWN4"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SPAWN5"; Tics = 0; }; Texture { ID = "SPAWN6"; Tics = 0; }; Texture { ID = "SPAWN7"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SPAWN8"; Tics = 0; }; Texture { ID = "SPAWN9"; Tics = 0; }; Texture { ID = "SPAWN10"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SPAWN11"; Tics = 0; }; Texture { ID = "SPAWN12"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW51_OFF"; Tics = 0; }; Texture { ID = "SW51_ON"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW52_OFF"; Tics = 0; }; Texture { ID = "SW52_ON"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW53_DN"; Tics = 0; }; Texture { ID = "SW53_MD"; Tics = 0; }; Texture { ID = "SW53_UP"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW_1_DN"; Tics = 0; }; Texture { ID = "SW_1_MD"; Tics = 0; }; Texture { ID = "SW_1_UP"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW_2_DN"; Tics = 0; }; Texture { ID = "SW_2_MD"; Tics = 0; }; Texture { ID = "SW_2_UP"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW_EL1"; Tics = 0; }; Texture { ID = "SW_EL2"; Tics = 0; }; Texture { ID = "SW_EL3"; Tics = 0; }; Texture { ID = "SW_EL4"; Tics = 0; }; Texture { ID = "SW_EL5"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "SW_OL1"; Tics = 0; }; Texture { ID = "SW_OL2"; Tics = 0; }; Texture { ID = "SW_OL3"; Tics = 0; }; Texture { ID = "SW_OL4"; Tics = 0; }; Texture { ID = "SW_OL5"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "VALVE01"; Tics = 0; }; Texture { ID = "VALVE02"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "VALVE1"; Tics = 0; }; Texture { ID = "VALVE2"; Tics = 0; }; } Group { Flags = precache; Texture { ID = "GLASS01"; Tics = 0; }; Texture { ID = "GLASS03"; Tics = 0; }; Texture { ID = "GLASS05"; Tics = 0; }; Texture { ID = "GLASS07"; Tics = 0; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/materials.ded0000644000175000017500000000236711357170242023417 0ustar keeskees# jHexen: Material Enhancements # # Patch the Material definitions created automatically # by the engine, adding new effects to them. Header { Version = 6; } # # Skymasked flats: # Material { ID = "F_SKY"; Namespace = flats; Flags = skymask; } # # Glowing materials: # Material { ID = "X_001"; Namespace = flats; Flags = glow; } * Material { ID = "X_002"; } * Material { ID = "X_003"; } * Material { ID = "X_004"; } # # Glowing textures: # Material { ID = "X_FIRE01"; Namespace = textures; Flags = glow; } * Material { ID = "X_FIRE02"; } * Material { ID = "X_FIRE03"; } * Material { ID = "X_FIRE04"; } * Material { ID = "X_FAC01"; } * Material { ID = "X_FAC02"; } * Material { ID = "X_FAC03"; } * Material { ID = "X_FAC04"; } * Material { ID = "X_FAC05"; } * Material { ID = "X_FAC06"; } * Material { ID = "X_FAC07"; } * Material { ID = "X_FAC08"; } * Material { ID = "X_FAC09"; } * Material { ID = "X_FAC10"; } * Material { ID = "X_FAC11"; } * Material { ID = "X_FAC12"; } * Material { ID = "TPORT1"; } * Material { ID = "TPORT2"; } * Material { ID = "TPORT3"; } * Material { ID = "TPORT4"; } * Material { ID = "TPORT5"; } * Material { ID = "TPORT6"; } * Material { ID = "TPORT7"; } * Material { ID = "TPORT8"; } * Material { ID = "TPORT9"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/audio.ded0000644000175000017500000011403111357170242022527 0ustar keeskees# jHexen: Audio # # The Sound definitions refer to sound names, which are currently # all located in SNDINFO (in Hexen.wad). SNDINFO maps each name # to a lump that contains the sound sample data. Header { Version = 5; } #####====--- SOUND EFFECTS ---====##### Sound { ID = "NONE"; } Sound { ID = "PLAYER_FIGHTER_NORMAL_DEATH"; Name = "PlayerFighterNormalDeath"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_FIGHTER_CRAZY_DEATH"; Name = "PlayerFighterCrazyDeath"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_FIGHTER_EXTREME1_DEATH"; Name = "PlayerFighterExtreme1Death"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_FIGHTER_EXTREME2_DEATH"; Name = "PlayerFighterExtreme2Death"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_FIGHTER_EXTREME3_DEATH"; Name = "PlayerFighterExtreme3Death"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_FIGHTER_BURN_DEATH"; Name = "PlayerFighterBurnDeath"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_NORMAL_DEATH"; Name = "PlayerClericNormalDeath"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_CRAZY_DEATH"; Name = "PlayerClericCrazyDeath"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_EXTREME1_DEATH"; Name = "PlayerClericExtreme1Death"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_EXTREME2_DEATH"; Name = "PlayerClericExtreme2Death"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_EXTREME3_DEATH"; Name = "PlayerClericExtreme3Death"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_BURN_DEATH"; Name = "PlayerClericBurnDeath"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_MAGE_NORMAL_DEATH"; Name = "PlayerMageNormalDeath"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_MAGE_CRAZY_DEATH"; Name = "PlayerMageCrazyDeath"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_MAGE_EXTREME1_DEATH"; Name = "PlayerMageExtreme1Death"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_MAGE_EXTREME2_DEATH"; Name = "PlayerMageExtreme2Death"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_MAGE_EXTREME3_DEATH"; Name = "PlayerMageExtreme3Death"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_MAGE_BURN_DEATH"; Name = "PlayerMageBurnDeath"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_FIGHTER_PAIN"; Name = "PlayerFighterPain"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_PAIN"; Name = "PlayerClericPain"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_MAGE_PAIN"; Name = "PlayerMagePain"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_FIGHTER_GRUNT"; Name = "PlayerFighterGrunt"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_GRUNT"; Name = "PlayerClericGrunt"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_MAGE_GRUNT"; Name = "PlayerMageGrunt"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_LAND"; Name = "PlayerLand"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_POISONCOUGH"; Name = "PlayerPoisonCough"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_FIGHTER_FALLING_SCREAM"; Name = "PlayerFighterFallingScream"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_FALLING_SCREAM"; Name = "PlayerClericFallingScream"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_MAGE_FALLING_SCREAM"; Name = "PlayerMageFallingScream"; Priority = 256; Max channels = 2; } Sound { ID = "PLAYER_FALLING_SPLAT"; Name = "PlayerFallingSplat"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLAYER_FIGHTER_FAILED_USE"; Name = "PlayerFighterFailedUse"; Priority = 256; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "PLAYER_CLERIC_FAILED_USE"; Name = "PlayerClericFailedUse"; Priority = 256; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "PLAYER_MAGE_FAILED_USE"; Name = "PlayerMageFailedUse"; Priority = 256; Max channels = 1; } Sound { ID = "PLATFORM_START"; Name = "PlatformStart"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLATFORM_STARTMETAL"; Name = "PlatformStartMetal"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PLATFORM_STOP"; Name = "PlatformStop"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "STONE_MOVE"; Name = "StoneMove"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "METAL_MOVE"; Name = "MetalMove"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DOOR_OPEN"; Name = "DoorOpen"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DOOR_LOCKED"; Name = "DoorLocked"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DOOR_METAL_OPEN"; Name = "DoorOpenMetal"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DOOR_METAL_CLOSE"; Name = "DoorCloseMetal"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DOOR_LIGHT_CLOSE"; Name = "DoorCloseLight"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DOOR_HEAVY_CLOSE"; Name = "DoorCloseHeavy"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DOOR_CREAK"; Name = "DoorCreak"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PICKUP_WEAPON"; Name = "PickupWeapon"; Priority = 36; Max channels = 2; } Sound { ID = "PICKUP_ARTIFACT"; Name = "PickupArtifact"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PICKUP_KEY"; Name = "PickupKey"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PICKUP_ITEM"; Name = "PickupItem"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PICKUP_PIECE"; Name = "PickupPiece"; Priority = 36; Max channels = 2; } Sound { ID = "WEAPON_BUILD"; Name = "WeaponBuild"; Priority = 36; Max channels = 2; } Sound { ID = "ARTIFACT_USE"; Name = "UseArtifact"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ARTIFACT_BLAST"; Name = "BlastRadius"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "TELEPORT"; Name = "Teleport"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "THUNDER_CRASH"; Name = "ThunderCrash"; Priority = 30; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_PUNCH_MISS"; Name = "FighterPunchMiss"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_PUNCH_HITTHING"; Name = "FighterPunchHitThing"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_PUNCH_HITWALL"; Name = "FighterPunchHitWall"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_GRUNT"; Name = "FighterGrunt"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_AXE_HITTHING"; Name = "FighterAxeHitThing"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_HAMMER_MISS"; Name = "FighterHammerMiss"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_HAMMER_HITTHING"; Name = "FighterHammerHitThing"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_HAMMER_HITWALL"; Name = "FighterHammerHitWall"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_HAMMER_CONTINUOUS"; Name = "FighterHammerContinuous"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_HAMMER_EXPLODE"; Name = "FighterHammerExplode"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_SWORD_FIRE"; Name = "FighterSwordFire"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIGHTER_SWORD_EXPLODE"; Name = "FighterSwordExplode"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CLERIC_CSTAFF_FIRE"; Name = "ClericCStaffFire"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CLERIC_CSTAFF_EXPLODE"; Name = "ClericCStaffExplode"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CLERIC_CSTAFF_HITTHING"; Name = "ClericCStaffHitThing"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CLERIC_FLAME_FIRE"; Name = "ClericFlameFire"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CLERIC_FLAME_EXPLODE"; Name = "ClericFlameExplode"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CLERIC_FLAME_CIRCLE"; Name = "ClericFlameCircle"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_WAND_FIRE"; Name = "MageWandFire"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_LIGHTNING_FIRE"; Name = "MageLightningFire"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_LIGHTNING_ZAP"; Name = "MageLightningZap"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_LIGHTNING_CONTINUOUS"; Name = "MageLightningContinuous"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_LIGHTNING_READY"; Name = "MageLightningReady"; Priority = 30; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_SHARDS_FIRE"; Name = "MageShardsFire"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_SHARDS_EXPLODE"; Name = "MageShardsExplode"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_STAFF_FIRE"; Name = "MageStaffFire"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAGE_STAFF_EXPLODE"; Name = "MageStaffExplode"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SWITCH1"; Name = "Switch1"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SWITCH2"; Name = "Switch2"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENT_SIGHT"; Name = "SerpentSight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENT_ACTIVE"; Name = "SerpentActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENT_PAIN"; Name = "SerpentPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENT_ATTACK"; Name = "SerpentAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENT_MELEEHIT"; Name = "SerpentMeleeHit"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENT_DEATH"; Name = "SerpentDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENT_BIRTH"; Name = "SerpentBirth"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENTFX_CONTINUOUS"; Name = "SerpentFXContinuous"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SERPENTFX_HIT"; Name = "SerpentFXHit"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "POTTERY_EXPLODE"; Name = "PotteryExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRIP"; Name = "Drip"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CENTAUR_SIGHT"; Name = "CentaurSight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CENTAUR_ACTIVE"; Name = "CentaurActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CENTAUR_PAIN"; Name = "CentaurPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CENTAUR_ATTACK"; Name = "CentaurAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CENTAUR_DEATH"; Name = "CentaurDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CENTAURLEADER_ATTACK"; Name = "CentaurLeaderAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CENTAUR_MISSILE_EXPLODE"; Name = "CentaurMissileExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WIND"; Name = "Wind"; Priority = 1; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BISHOP_SIGHT"; Name = "BishopSight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BISHOP_ACTIVE"; Name = "BishopActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BISHOP_PAIN"; Name = "BishopPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BISHOP_ATTACK"; Name = "BishopAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BISHOP_DEATH"; Name = "BishopDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BISHOP_MISSILE_EXPLODE"; Name = "BishopMissileExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BISHOP_BLUR"; Name = "BishopBlur"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DEMON_SIGHT"; Name = "DemonSight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DEMON_ACTIVE"; Name = "DemonActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DEMON_PAIN"; Name = "DemonPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DEMON_ATTACK"; Name = "DemonAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DEMON_MISSILE_FIRE"; Name = "DemonMissileFire"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DEMON_MISSILE_EXPLODE"; Name = "DemonMissileExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DEMON_DEATH"; Name = "DemonDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WRAITH_SIGHT"; Name = "WraithSight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WRAITH_ACTIVE"; Name = "WraithActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WRAITH_PAIN"; Name = "WraithPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WRAITH_ATTACK"; Name = "WraithAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WRAITH_MISSILE_FIRE"; Name = "WraithMissileFire"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WRAITH_MISSILE_EXPLODE"; Name = "WraithMissileExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WRAITH_DEATH"; Name = "WraithDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PIG_ACTIVE1"; Name = "PigActive1"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PIG_ACTIVE2"; Name = "PigActive2"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PIG_PAIN"; Name = "PigPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PIG_ATTACK"; Name = "PigAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PIG_DEATH"; Name = "PigDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAULATOR_SIGHT"; Name = "MaulatorSight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAULATOR_ACTIVE"; Name = "MaulatorActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAULATOR_PAIN"; Name = "MaulatorPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAULATOR_HAMMER_SWING"; Name = "MaulatorHamSwing"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAULATOR_HAMMER_HIT"; Name = "MaulatorHamHit"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAULATOR_MISSILE_HIT"; Name = "MaulatorMissileHit"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MAULATOR_DEATH"; Name = "MaulatorDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FREEZE_DEATH"; Name = "FreezeDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FREEZE_SHATTER"; Name = "FreezeShatter"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ETTIN_SIGHT"; Name = "EttinSight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ETTIN_ACTIVE"; Name = "EttinActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ETTIN_PAIN"; Name = "EttinPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ETTIN_ATTACK"; Name = "EttinAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ETTIN_DEATH"; Name = "EttinDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIRED_SPAWN"; Name = "FireDemonSpawn"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIRED_ACTIVE"; Name = "FireDemonActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIRED_PAIN"; Name = "FireDemonPain"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIRED_ATTACK"; Name = "FireDemonAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIRED_MISSILE_HIT"; Name = "FireDemonMissileHit"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIRED_DEATH"; Name = "FireDemonDeath"; Priority = 40; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ICEGUY_SIGHT"; Name = "IceGuySight"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ICEGUY_ACTIVE"; Name = "IceGuyActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ICEGUY_ATTACK"; Name = "IceGuyAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ICEGUY_FX_EXPLODE"; Name = "IceGuyMissileExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_SIGHT"; Name = "SorcererSight"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_ACTIVE"; Name = "SorcererActive"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_PAIN"; Name = "SorcererPain"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_SPELLCAST"; Name = "SorcererSpellCast"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_BALLWOOSH"; Name = "SorcererBallWoosh"; Priority = 256; Max channels = 4; Flags = "sf_shift"; } Sound { ID = "SORCERER_DEATHSCREAM"; Name = "SorcererDeathScream"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_BISHOPSPAWN"; Name = "SorcererBishopSpawn"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_BALLPOP"; Name = "SorcererBallPop"; Priority = 80; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SORCERER_BALLBOUNCE"; Name = "SorcererBallBounce"; Priority = 80; Max channels = 3; Flags = "sf_shift"; } Sound { ID = "SORCERER_BALLEXPLODE"; Name = "SorcererBallExplode"; Priority = 80; Max channels = 3; Flags = "sf_shift"; } Sound { ID = "SORCERER_BIGBALLEXPLODE"; Name = "SorcererBigBallExplode"; Priority = 80; Max channels = 3; Flags = "sf_shift"; } Sound { ID = "SORCERER_HEADSCREAM"; Name = "SorcererHeadScream"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRAGON_SIGHT"; Name = "DragonSight"; Priority = 64; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRAGON_ACTIVE"; Name = "DragonActive"; Priority = 64; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRAGON_WINGFLAP"; Name = "DragonWingflap"; Priority = 64; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRAGON_ATTACK"; Name = "DragonAttack"; Priority = 64; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRAGON_PAIN"; Name = "DragonPain"; Priority = 64; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRAGON_DEATH"; Name = "DragonDeath"; Priority = 64; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "DRAGON_FIREBALL_EXPLODE"; Name = "DragonFireballExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_SIGHT"; Name = "KoraxSight"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_ACTIVE"; Name = "KoraxActive"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_PAIN"; Name = "KoraxPain"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_ATTACK"; Name = "KoraxAttack"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_COMMAND"; Name = "KoraxCommand"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_DEATH"; Name = "KoraxDeath"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_STEP"; Name = "KoraxStep"; Priority = 128; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "THRUSTSPIKE_RAISE"; Name = "ThrustSpikeRaise"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "THRUSTSPIKE_LOWER"; Name = "ThrustSpikeLower"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "STAINEDGLASS_SHATTER"; Name = "GlassShatter"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FLECHETTE_BOUNCE"; Name = "FlechetteBounce"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FLECHETTE_EXPLODE"; Name = "FlechetteExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "LAVA_MOVE"; Name = "LavaMove"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WATER_MOVE"; Name = "WaterMove"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ICE_STARTMOVE"; Name = "IceStartMove"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "EARTH_STARTMOVE"; Name = "EarthStartMove"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "WATER_SPLASH"; Name = "WaterSplash"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "LAVA_SIZZLE"; Name = "LavaSizzle"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SLUDGE_GLOOP"; Name = "SludgeGloop"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CHOLY_FIRE"; Name = "HolySymbolFire"; Priority = 64; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SPIRIT_ACTIVE"; Name = "SpiritActive"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SPIRIT_ATTACK"; Name = "SpiritAttack"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SPIRIT_DIE"; Name = "SpiritDie"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "VALVE_TURN"; Name = "ValveTurn"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "ROPE_PULL"; Name = "RopePull"; Priority = 36; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FLY_BUZZ"; Name = "FlyBuzz"; Priority = 20; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "IGNITE"; Name = "Ignite"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PUZZLE_SUCCESS"; Name = "PuzzleSuccess"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PUZZLE_FAIL_FIGHTER"; Name = "PuzzleFailFighter"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PUZZLE_FAIL_CLERIC"; Name = "PuzzleFailCleric"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PUZZLE_FAIL_MAGE"; Name = "PuzzleFailMage"; Priority = 256; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "EARTHQUAKE"; Name = "Earthquake"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BELLRING"; Name = "BellRing"; Priority = 32; Max channels = 2; } Sound { ID = "TREE_BREAK"; Name = "TreeBreak"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "TREE_EXPLODE"; Name = "TreeExplode"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SUITOFARMOR_BREAK"; Name = "SuitofArmorBreak"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "POISONSHROOM_PAIN"; Name = "PoisonShroomPain"; Priority = 20; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "POISONSHROOM_DEATH"; Name = "PoisonShroomDeath"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "AMBIENT1"; Name = "Ambient1"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT2"; Name = "Ambient2"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT3"; Name = "Ambient3"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT4"; Name = "Ambient4"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT5"; Name = "Ambient5"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT6"; Name = "Ambient6"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT7"; Name = "Ambient7"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT8"; Name = "Ambient8"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT9"; Name = "Ambient9"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT10"; Name = "Ambient10"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT11"; Name = "Ambient11"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT12"; Name = "Ambient12"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT13"; Name = "Ambient13"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT14"; Name = "Ambient14"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "AMBIENT15"; Name = "Ambient15"; Priority = 1; Max channels = 1; Flags = "sf_shift"; } Sound { ID = "STARTUP_TICK"; Name = "StartupTick"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "SWITCH_OTHERLEVEL"; Name = "SwitchOtherLevel"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "RESPAWN"; Name = "Respawn"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_1"; Name = "KoraxVoiceGreetings"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_2"; Name = "KoraxVoiceReady"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_3"; Name = "KoraxVoiceBlood"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_4"; Name = "KoraxVoiceGame"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_5"; Name = "KoraxVoiceBoard"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_6"; Name = "KoraxVoiceWorship"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_7"; Name = "KoraxVoiceMaybe"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_8"; Name = "KoraxVoiceStrong"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "KORAX_VOICE_9"; Name = "KoraxVoiceFace"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "BAT_SCREAM"; Name = "BatScream"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CHAT"; Name = "Chat"; Priority = 512; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MENU_MOVE"; Name = "MenuMove"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "CLOCK_TICK"; Name = "ClockTick"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "FIREBALL"; Name = "Fireball"; Priority = 32; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "PUPPYBEAT"; Name = "PuppyBeat"; Priority = 30; Max channels = 2; Flags = "sf_shift"; } Sound { ID = "MYSTICINCANT"; Name = "MysticIncant"; Priority = 32; Max channels = 4; Flags = "sf_shift"; } Texture Environment { ID = "Metal"; Texture { ID = "brass1"; }; Texture { ID = "brass3"; }; Texture { ID = "brass4"; }; Texture { ID = "castle11"; }; Texture { ID = "d_brass1"; }; Texture { ID = "d_brass2"; }; Texture { ID = "d_cast"; }; Texture { ID = "d_cave"; }; Texture { ID = "d_end1"; }; Texture { ID = "d_end2"; }; Texture { ID = "d_endbr"; }; Texture { ID = "d_endslv"; }; Texture { ID = "d_silver"; }; Texture { ID = "d_slv1"; }; Texture { ID = "d_slv2"; }; Texture { ID = "d_steel"; }; Texture { ID = "forest10"; }; Texture { ID = "gilo1"; }; Texture { ID = "gilo2"; }; Texture { ID = "monk06"; }; Texture { ID = "monk09"; }; Texture { ID = "monk11"; }; Texture { ID = "monk12"; }; Texture { ID = "plat01"; }; Texture { ID = "plat02"; }; Texture { ID = "s_01"; }; Texture { ID = "s_04"; }; Texture { ID = "s_09"; }; Texture { ID = "spawn08"; }; Texture { ID = "steel01"; }; Texture { ID = "steel02"; }; Texture { ID = "steel05"; }; Texture { ID = "steel06"; }; Texture { ID = "steel07"; }; Texture { ID = "steel08"; }; Texture { ID = "winn01"; }; Texture { ID = "poot"; }; } Texture Environment { ID = "Rock"; Texture { ID = "castle01"; }; Texture { ID = "castle02"; }; Texture { ID = "castle03"; }; Texture { ID = "castle04"; }; Texture { ID = "castle05"; }; Texture { ID = "castle06"; }; Texture { ID = "castle07"; }; Texture { ID = "castle08"; }; Texture { ID = "castle09"; }; Texture { ID = "cave01"; }; Texture { ID = "cave02"; }; Texture { ID = "cave03"; }; Texture { ID = "cave04"; }; Texture { ID = "cave05"; }; Texture { ID = "cave06"; }; Texture { ID = "cave07"; }; Texture { ID = "cave11"; }; Texture { ID = "cave12"; }; Texture { ID = "d_fire"; }; Texture { ID = "d_swamp"; }; Texture { ID = "d_swamp2"; }; Texture { ID = "d_waste"; }; Texture { ID = "door51"; }; Texture { ID = "fire01"; }; Texture { ID = "fire02"; }; Texture { ID = "fire03"; }; Texture { ID = "fire04"; }; Texture { ID = "fire05"; }; Texture { ID = "fire06"; }; Texture { ID = "fire07"; }; Texture { ID = "fire08"; }; Texture { ID = "fire09"; }; Texture { ID = "fire10"; }; Texture { ID = "fire11"; }; Texture { ID = "fire12"; }; Texture { ID = "fire13"; }; Texture { ID = "fire14"; }; Texture { ID = "fire15"; }; Texture { ID = "fire16"; }; Texture { ID = "fire17"; }; Texture { ID = "forest01"; }; Texture { ID = "forest02"; }; Texture { ID = "forest03"; }; Texture { ID = "forest04"; }; Texture { ID = "forest05"; }; Texture { ID = "forest11"; }; Texture { ID = "forest12"; }; Texture { ID = "glass01"; }; Texture { ID = "glass02"; }; Texture { ID = "glass03"; }; Texture { ID = "glass04"; }; Texture { ID = "glass05"; }; Texture { ID = "glass06"; }; Texture { ID = "glass07"; }; Texture { ID = "grave01"; }; Texture { ID = "grave03"; }; Texture { ID = "grave04"; }; Texture { ID = "grave05"; }; Texture { ID = "grave06"; }; Texture { ID = "grave07"; }; Texture { ID = "grave08"; }; Texture { ID = "ice01"; }; Texture { ID = "ice02"; }; Texture { ID = "ice03"; }; Texture { ID = "ice06"; }; Texture { ID = "monk01"; }; Texture { ID = "monk02"; }; Texture { ID = "monk03"; }; Texture { ID = "monk04"; }; Texture { ID = "monk05"; }; Texture { ID = "monk07"; }; Texture { ID = "monk08"; }; Texture { ID = "monk14"; }; Texture { ID = "monk15"; }; Texture { ID = "monk16"; }; Texture { ID = "monk17"; }; Texture { ID = "monk18"; }; Texture { ID = "monk19"; }; Texture { ID = "monk21"; }; Texture { ID = "monk22"; }; Texture { ID = "monk23"; }; Texture { ID = "monk24"; }; Texture { ID = "pillar01"; }; Texture { ID = "pillar02"; }; Texture { ID = "planet1"; }; Texture { ID = "planet2"; }; Texture { ID = "prtl02"; }; Texture { ID = "prtl03"; }; Texture { ID = "prtl04"; }; Texture { ID = "prtl05"; }; Texture { ID = "prtl06"; }; Texture { ID = "prtl07"; }; Texture { ID = "s_02"; }; Texture { ID = "s_05"; }; Texture { ID = "s_06"; }; Texture { ID = "s_07"; }; Texture { ID = "s_11"; }; Texture { ID = "sewer01"; }; Texture { ID = "sewer02"; }; Texture { ID = "sewer05"; }; Texture { ID = "sewer06"; }; Texture { ID = "sewer07"; }; Texture { ID = "sewer08"; }; Texture { ID = "sewer09"; }; Texture { ID = "sewer10"; }; Texture { ID = "sewer11"; }; Texture { ID = "sewer12"; }; Texture { ID = "sewer13"; }; Texture { ID = "sewer14"; }; Texture { ID = "swamp01"; }; Texture { ID = "swamp03"; }; Texture { ID = "swamp04"; }; Texture { ID = "swamp06"; }; Texture { ID = "swamp07"; }; Texture { ID = "tomb01"; }; Texture { ID = "tomb02"; }; Texture { ID = "tomb03"; }; Texture { ID = "tomb04"; }; Texture { ID = "tomb05"; }; Texture { ID = "tomb06"; }; Texture { ID = "tomb07"; }; Texture { ID = "tomb08"; }; Texture { ID = "tomb09"; }; Texture { ID = "tomb10"; }; Texture { ID = "tomb11"; }; Texture { ID = "tomb12"; }; Texture { ID = "tomb13"; }; Texture { ID = "tomb18"; }; Texture { ID = "vill01"; }; Texture { ID = "waste01"; }; Texture { ID = "waste02"; }; Texture { ID = "waste03"; }; Texture { ID = "waste04"; }; Texture { ID = "winnow02"; }; Texture { ID = "x_swr1"; }; Texture { ID = "x_swr2"; }; Texture { ID = "x_swr3"; }; } Texture Environment { ID = "Wood"; Texture { ID = "crate01"; }; Texture { ID = "crate02"; }; Texture { ID = "crate03"; }; Texture { ID = "crate04"; }; Texture { ID = "crate05"; }; Texture { ID = "d_axe"; }; Texture { ID = "d_dungeo"; }; Texture { ID = "d_end4"; }; Texture { ID = "d_rust"; }; Texture { ID = "d_silkey"; }; Texture { ID = "d_wd01"; }; Texture { ID = "d_wd02"; }; Texture { ID = "d_wd03"; }; Texture { ID = "d_wd04"; }; Texture { ID = "d_wd05"; }; Texture { ID = "d_wd06"; }; Texture { ID = "d_wd07"; }; Texture { ID = "d_wd08"; }; Texture { ID = "d_wd09"; }; Texture { ID = "d_wd10"; }; Texture { ID = "d_winnow"; }; Texture { ID = "s_12"; }; Texture { ID = "sewer03"; }; Texture { ID = "sewer04"; }; Texture { ID = "vill04"; }; Texture { ID = "vill05"; }; Texture { ID = "wood01"; }; Texture { ID = "wood02"; }; Texture { ID = "wood03"; }; Texture { ID = "wood04"; }; } Texture Environment { ID = "Cloth"; Texture { ID = "books01"; }; Texture { ID = "books02"; }; Texture { ID = "books03"; }; Texture { ID = "books04"; }; Texture { ID = "forest06"; }; Texture { ID = "forest07"; }; Texture { ID = "gate01"; }; Texture { ID = "gate02"; }; Texture { ID = "gate03"; }; Texture { ID = "gate04"; }; Texture { ID = "gate51"; }; Texture { ID = "gate52"; }; Texture { ID = "gate53"; }; Texture { ID = "vill06"; }; Texture { ID = "vill07"; }; Texture { ID = "vill08"; }; Texture { ID = "x_fire01"; }; Texture { ID = "x_fire02"; }; Texture { ID = "x_fire03"; }; Texture { ID = "x_fire04"; }; Texture { ID = "x_swmp1"; }; Texture { ID = "x_swmp2"; }; Texture { ID = "x_swmp3"; }; Texture { ID = "x_water1"; }; Texture { ID = "x_water2"; }; Texture { ID = "x_water3"; }; Texture { ID = "x_water4"; }; } #####====--- MUSIC ---====##### Music { ID = "startup"; } Music { ID = "winnowr"; Lump = "WINNOWR"; } Music { ID = "jachr"; Lump = "JACHR"; } Music { ID = "simonr"; Lump = "SIMONR"; } Music { ID = "wutzitr"; Lump = "WUTZITR"; } Music { ID = "falconr"; Lump = "FALCONR"; } Music { ID = "levelr"; Lump = "LEVELR"; } Music { ID = "chartr"; Lump = "CHARTR"; } Music { ID = "swampr"; Lump = "SWAMPR"; } Music { ID = "deepr"; Lump = "DEEPR"; } Music { ID = "fubasr"; Lump = "FUBASR"; } Music { ID = "grover"; Lump = "GROVER"; } Music { ID = "fortr"; Lump = "FORTR"; } Music { ID = "foojar"; Lump = "FOOJAR"; } Music { ID = "sixater"; Lump = "SIXATER"; } Music { ID = "wobabyr"; Lump = "WOBABYR"; } Music { ID = "cryptr"; Lump = "CRYPTR"; } Music { ID = "fantar"; Lump = "FANTAR"; } Music { ID = "belchr"; Lump = "BELCHR"; } Music { ID = "voidr"; Lump = "VOIDR"; } Music { ID = "chap_1r"; Lump = "CHAP_1R"; } Music { ID = "chap_2r"; Lump = "CHAP_2R"; } Music { ID = "chap_3r"; Lump = "CHAP_3R"; } Music { ID = "chap_4r"; Lump = "CHAP_4R"; } Music { ID = "chippyr"; Lump = "CHIPPYR"; } Music { ID = "percr"; Lump = "PERCR"; } Music { ID = "secretr"; Lump = "SECRETR"; } Music { ID = "bonesr"; Lump = "BONESR"; } Music { ID = "octor"; Lump = "OCTOR"; } Music { ID = "rithmr"; Lump = "RITHMR"; } Music { ID = "stalkr"; Lump = "STALKR"; } Music { ID = "borkr"; Lump = "BORKR"; } Music { ID = "crucibr"; Lump = "CRUCIBR"; } Music { ID = "hexen"; Lump = "HEXEN"; } Music { ID = "hub"; Lump = "HUB"; } Music { ID = "hall"; Lump = "HALL"; } Music { ID = "orb"; Lump = "ORB"; } Music { ID = "chess"; Lump = "CHESS"; } # The contents of the 'currentmap' definition change at runtime. Music { ID = "currentmap"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/models.ded0000644000175000017500000000020611357170242022707 0ustar keeskees# jHexen: Models Include "models\*.ded"; # This can be removed if jHexen.ded sets the default path. ModelPath "data\jhexen\models"; deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/objects.ded0000644000175000017500000210120311357170242023056 0ustar keeskees# jHexen: Objects # # Order of definitions is very important here! # Only add new States and Things *after* the existing definitions. Header { Version = 5; } Thing { ID = "MAPSPOT"; DoomEd number = 9001; Spawn state = "MAPSPOT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector mf_nogravity"; Flags2 = "mf2_dontdraw"; } Thing { ID = "MAPSPOTGRAVITY"; DoomEd number = 9013; Spawn state = "MAPSPOT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags2 = "mf2_dontdraw"; } Thing { ID = "FIREBALL1"; DoomEd number = -1; Spawn state = "FIREBALL1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FIREBALL1_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "FIREBALL"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 2; Radius = 8; Height = 8; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "ARROW"; DoomEd number = -1; Spawn state = "ARROW_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ARROW_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 6; Radius = 8; Height = 4; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "DART"; DoomEd number = -1; Spawn state = "DART_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DART_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 6; Radius = 8; Height = 4; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "POISONDART"; DoomEd number = -1; Spawn state = "POISONDART_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "POISONDART_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 6; Radius = 8; Height = 4; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "RIPPERBALL"; DoomEd number = -1; Spawn state = "RIPPERBALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "RIPPERBALL_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 6; Radius = 8; Height = 16; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_rip"; } Thing { ID = "PROJECTILE_BLADE"; DoomEd number = -1; Spawn state = "PRJ_BLADE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "PRJ_BLADE_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 6; Radius = 6; Height = 6; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "ICESHARD"; DoomEd number = -1; Spawn state = "ICESHARD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SHARDFXE1_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "MAGE_SHARDS_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_icedamage"; } Thing { ID = "FLAME_SMALL_TEMP"; DoomEd number = 10500; Spawn state = "FLAME_TSMALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags2 = "mf2_noteleport"; } Thing { ID = "FLAME_LARGE_TEMP"; DoomEd number = 10502; Spawn state = "FLAME_TLARGE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags2 = "mf2_noteleport"; } Thing { ID = "FLAME_SMALL"; DoomEd number = 10501; Spawn state = "FLAME_SMALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags2 = "mf2_noteleport mf2_dontdraw"; } Thing { ID = "FLAME_LARGE"; DoomEd number = 10503; Spawn state = "FLAME_LARGE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags2 = "mf2_noteleport mf2_dontdraw"; } Thing { ID = "HEALINGBOTTLE"; DoomEd number = 81; Spawn state = "ITEM_PTN1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "HEALTHFLASK"; DoomEd number = 82; Spawn state = "ARTI_PTN2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTIFLY"; DoomEd number = 83; Spawn state = "ARTI_SOAR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTIINVULNERABILITY"; DoomEd number = 84; Spawn state = "ARTI_INVU1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "SUMMONMAULATOR"; DoomEd number = 86; Spawn state = "ARTI_SUMMON"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "SUMMON_FX"; DoomEd number = -1; Spawn state = "SUMMON_FX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SUMMON_FX2_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 20; Height = 16; Mass = 100; Flags = "mf_missile mf_dropoff mf_noblockmap"; Flags2 = "mf2_noteleport"; } Thing { ID = "THRUSTFLOOR_UP"; DoomEd number = 10091; Spawn state = "THRUSTINIT2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 128; Mass = 100; Flags = "mf_solid"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "THRUSTFLOOR_DOWN"; DoomEd number = 10090; Spawn state = "THRUSTINIT1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 128; Mass = 100; Flags2 = "mf2_noteleport mf2_floorclip mf2_dontdraw"; } Thing { ID = "TELEPORTOTHER"; DoomEd number = 10040; Spawn state = "ARTI_TELOTHER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "TELOTHER_FX1"; DoomEd number = -1; Spawn state = "TELO_FX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "TELO_FX9"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 16; Height = 16; Mass = 100; Damage = 10001; Flags = "mf_missile mf_brightexplode mf_dropoff mf_nogravity mf_noblockmap"; Flags2 = "mf2_noteleport"; } Thing { ID = "TELOTHER_FX2"; DoomEd number = -1; Spawn state = "TELO_FX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "TELO_FX9"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 16; Radius = 16; Height = 16; Mass = 100; Damage = 10001; Flags = "mf_missile mf_brightexplode mf_dropoff mf_nogravity mf_noblockmap"; Flags2 = "mf2_noteleport"; } Thing { ID = "TELOTHER_FX3"; DoomEd number = -1; Spawn state = "TELO_FX3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "TELO_FX9"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 16; Radius = 16; Height = 16; Mass = 100; Damage = 10001; Flags = "mf_missile mf_brightexplode mf_dropoff mf_nogravity mf_noblockmap"; Flags2 = "mf2_noteleport"; } Thing { ID = "TELOTHER_FX4"; DoomEd number = -1; Spawn state = "TELO_FX4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "TELO_FX9"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 16; Radius = 16; Height = 16; Mass = 100; Damage = 10001; Flags = "mf_missile mf_brightexplode mf_dropoff mf_nogravity mf_noblockmap"; Flags2 = "mf2_noteleport"; } Thing { ID = "TELOTHER_FX5"; DoomEd number = -1; Spawn state = "TELO_FX5_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "TELO_FX9"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 16; Radius = 16; Height = 16; Mass = 100; Damage = 10001; Flags = "mf_missile mf_brightexplode mf_dropoff mf_nogravity mf_noblockmap"; Flags2 = "mf2_noteleport"; } Thing { ID = "DIRT1"; DoomEd number = -1; Spawn state = "DIRT1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DIRT1_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "DIRT2"; DoomEd number = -1; Spawn state = "DIRT2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DIRT2_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "DIRT3"; DoomEd number = -1; Spawn state = "DIRT3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DIRT3_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "DIRT4"; DoomEd number = -1; Spawn state = "DIRT4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DIRT4_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport mf2_lograv"; } Thing { ID = "DIRT5"; DoomEd number = -1; Spawn state = "DIRT5_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DIRT5_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport mf2_lograv"; } Thing { ID = "DIRT6"; DoomEd number = -1; Spawn state = "DIRT6_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DIRT6_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport mf2_lograv"; } Thing { ID = "DIRTCLUMP"; DoomEd number = -1; Spawn state = "DIRTCLUMP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; Flags2 = "mf2_noteleport"; } Thing { ID = "ROCK1"; DoomEd number = -1; Spawn state = "ROCK1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ROCK1_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "ROCK2"; DoomEd number = -1; Spawn state = "ROCK2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ROCK2_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "ROCK3"; DoomEd number = -1; Spawn state = "ROCK3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ROCK3_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "FOGSPAWNER"; DoomEd number = 10000; Spawn state = "SPAWNFOG1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector"; Flags2 = "mf2_dontdraw mf2_floatbob"; } Thing { ID = "FOGPATCHS"; DoomEd number = 10001; Spawn state = "FOGPATCHS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FOGPATCHS0"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 1; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_float mf_nogravity mf_shadow mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "FOGPATCHM"; DoomEd number = 10002; Spawn state = "FOGPATCHM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FOGPATCHM0"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 1; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_float mf_nogravity mf_shadow mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "FOGPATCHL"; DoomEd number = 10003; Spawn state = "FOGPATCHL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FOGPATCHL0"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 1; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_float mf_nogravity mf_shadow mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "QUAKE_FOCUS"; DoomEd number = -1; Spawn state = "QUAKE_ACTIVE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector"; Flags2 = "mf2_dontdraw"; } Thing { ID = "SGSHARD1"; DoomEd number = -1; Spawn state = "SGSHARD1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD1_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD2"; DoomEd number = -1; Spawn state = "SGSHARD2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD2_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD3"; DoomEd number = -1; Spawn state = "SGSHARD3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD3_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD4"; DoomEd number = -1; Spawn state = "SGSHARD4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD4_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD5"; DoomEd number = -1; Spawn state = "SGSHARD5_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD5_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD6"; DoomEd number = -1; Spawn state = "SGSHARD6_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD6_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD7"; DoomEd number = -1; Spawn state = "SGSHARD7_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD7_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD8"; DoomEd number = -1; Spawn state = "SGSHARD8_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD8_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD9"; DoomEd number = -1; Spawn state = "SGSHARD9_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD9_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SGSHARD0"; DoomEd number = -1; Spawn state = "SGSHARD0_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SGSHARD0_D"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_nogravity"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "ARTIEGG"; DoomEd number = 30; Spawn state = "ARTI_EGGC1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "EGGFX"; DoomEd number = -1; Spawn state = "EGGFX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "EGGFXI1_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 18; Radius = 8; Height = 8; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "ARTISUPERHEAL"; DoomEd number = 32; Spawn state = "ARTI_SPHL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "ZWINGEDSTATUENOSKULL"; DoomEd number = 9011; Spawn state = "ZWINGEDSTATUENOSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZGEMPEDESTAL"; DoomEd number = 9012; Spawn state = "ZGEMPEDESTAL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 40; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ARTIPUZZSKULL"; DoomEd number = 9002; Spawn state = "ARTIPUZZSKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEMBIG"; DoomEd number = 9003; Spawn state = "ARTIPUZZGEMBIG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEMRED"; DoomEd number = 9004; Spawn state = "ARTIPUZZGEMRED"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEMGREEN1"; DoomEd number = 9005; Spawn state = "ARTIPUZZGEMGREEN1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEMGREEN2"; DoomEd number = 9009; Spawn state = "ARTIPUZZGEMGREEN2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEMBLUE1"; DoomEd number = 9006; Spawn state = "ARTIPUZZGEMBLUE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEMBLUE2"; DoomEd number = 9010; Spawn state = "ARTIPUZZGEMBLUE2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZBOOK1"; DoomEd number = 9007; Spawn state = "ARTIPUZZBOOK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZBOOK2"; DoomEd number = 9008; Spawn state = "ARTIPUZZBOOK2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZSKULL2"; DoomEd number = 9014; Spawn state = "ARTIPUZZSKULL2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZFWEAPON"; DoomEd number = 9015; Spawn state = "ARTIPUZZFWEAPON"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZCWEAPON"; DoomEd number = 9016; Spawn state = "ARTIPUZZCWEAPON"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZMWEAPON"; DoomEd number = 9017; Spawn state = "ARTIPUZZMWEAPON"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEAR"; DoomEd number = 9018; Spawn state = "ARTIPUZZGEAR_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEAR2"; DoomEd number = 9019; Spawn state = "ARTIPUZZGEAR2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEAR3"; DoomEd number = 9020; Spawn state = "ARTIPUZZGEAR3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTIPUZZGEAR4"; DoomEd number = 9021; Spawn state = "ARTIPUZZGEAR4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARTITORCH"; DoomEd number = 33; Spawn state = "ARTI_TRCH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "FIREBOMB"; DoomEd number = -1; Spawn state = "FIREBOMB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "FLECHETTE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_nogravity mf_altshadow"; Flags2 = "mf2_firedamage"; } Thing { ID = "ARTITELEPORT"; DoomEd number = 36; Spawn state = "ARTI_ATLP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "ARTIPOISONBAG"; DoomEd number = 8000; Spawn state = "ARTI_PSBG1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "POISONBAG"; DoomEd number = -1; Spawn state = "POISONBAG1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_nogravity mf_noblockmap"; } Thing { ID = "POISONCLOUD"; DoomEd number = -1; Spawn state = "POISONCLOUD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "POISONSHROOM_DEATH"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 1; Height = 1; Mass = 2147483647; Flags = "mf_nogravity mf_noblockmap mf_shadow mf_noclip mf_dropoff mf_viewalign"; Flags2 = "mf2_nodmgthrust"; } Thing { ID = "THROWINGBOMB"; DoomEd number = -1; Spawn state = "THROWINGBOMB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "THROWINGBOMB_X1"; Xdeath state = "NULL"; See sound = "FLECHETTE_BOUNCE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "FLECHETTE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 48; Speed = 12; Radius = 8; Height = 10; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_missile mf_brightexplode"; Flags2 = "mf2_floorbounce mf2_firedamage"; } Thing { ID = "SPEEDBOOTS"; DoomEd number = 8002; Spawn state = "ARTI_BOOTS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "BOOSTMANA"; DoomEd number = 8003; Spawn state = "ARTI_MANA"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "BOOSTARMOR"; DoomEd number = 8041; Spawn state = "ARTI_ARMOR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "BLASTRADIUS"; DoomEd number = 10110; Spawn state = "ARTI_BLAST1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "HEALRADIUS"; DoomEd number = 10120; Spawn state = "ARTI_HEALRAD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "SPLASH"; DoomEd number = -1; Spawn state = "SPLASH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SPLASHX"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv mf2_cannotpush"; } Thing { ID = "SPLASHBASE"; DoomEd number = -1; Spawn state = "SPLASHBASE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "LAVASPLASH"; DoomEd number = -1; Spawn state = "LAVASPLASH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "LAVASMOKE"; DoomEd number = -1; Spawn state = "LAVASMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "SLUDGECHUNK"; DoomEd number = -1; Spawn state = "SLUDGECHUNK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SLUDGECHUNKX"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv mf2_cannotpush"; } Thing { ID = "SLUDGESPLASH"; DoomEd number = -1; Spawn state = "SLUDGESPLASH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "MISC0"; DoomEd number = 5; Spawn state = "ZWINGEDSTATUE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC1"; DoomEd number = 6; Spawn state = "ZROCK1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC2"; DoomEd number = 7; Spawn state = "ZROCK2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC3"; DoomEd number = 9; Spawn state = "ZROCK3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC4"; DoomEd number = 15; Spawn state = "ZROCK4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC5"; DoomEd number = 17; Spawn state = "ZCHANDELIER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 60; Mass = 100; Flags = "mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC6"; DoomEd number = 8063; Spawn state = "ZCHANDELIER_U"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 60; Mass = 100; Flags = "mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC7"; DoomEd number = 24; Spawn state = "ZTREEDEAD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 96; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC8"; DoomEd number = 25; Spawn state = "ZTREE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 15; Height = 128; Mass = 100; Flags = "mf_solid"; } Thing { ID = "TREEDESTRUCTIBLE"; DoomEd number = 8062; Spawn state = "ZTREEDESTRUCTIBLE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZTREEDES_D1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "TREE_BREAK"; Active sound = "NONE"; Reaction time = 8; Spawn health = 70; Radius = 15; Height = 180; Mass = 2147483647; Flags = "mf_solid mf_shootable mf_noblood"; } Thing { ID = "MISC9"; DoomEd number = 26; Spawn state = "ZTREESWAMP182_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 180; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC10"; DoomEd number = 27; Spawn state = "ZTREESWAMP172_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 150; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC11"; DoomEd number = 28; Spawn state = "ZSTUMPBURNED1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 20; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC12"; DoomEd number = 29; Spawn state = "ZSTUMPBARE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 20; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC13"; DoomEd number = 37; Spawn state = "ZSTUMPSWAMP1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC14"; DoomEd number = 38; Spawn state = "ZSTUMPSWAMP2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC15"; DoomEd number = 39; Spawn state = "ZSHROOMLARGE1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC16"; DoomEd number = 40; Spawn state = "ZSHROOMLARGE2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC17"; DoomEd number = 41; Spawn state = "ZSHROOMLARGE3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC18"; DoomEd number = 42; Spawn state = "ZSHROOMSMALL1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC19"; DoomEd number = 44; Spawn state = "ZSHROOMSMALL2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC20"; DoomEd number = 45; Spawn state = "ZSHROOMSMALL3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC21"; DoomEd number = 46; Spawn state = "ZSHROOMSMALL4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC22"; DoomEd number = 47; Spawn state = "ZSHROOMSMALL5_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC23"; DoomEd number = 48; Spawn state = "ZSTALAGMITEPILLAR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 138; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC24"; DoomEd number = 49; Spawn state = "ZSTALAGMITELARGE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 48; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC25"; DoomEd number = 50; Spawn state = "ZSTALAGMITEMEDIUM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 6; Height = 40; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC26"; DoomEd number = 51; Spawn state = "ZSTALAGMITESMALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 36; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC27"; DoomEd number = 52; Spawn state = "ZSTALACTITELARGE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 66; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC28"; DoomEd number = 56; Spawn state = "ZSTALACTITEMEDIUM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 6; Height = 50; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC29"; DoomEd number = 57; Spawn state = "ZSTALACTITESMALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 40; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC30"; DoomEd number = 58; Spawn state = "ZMOSSCEILING1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 20; Mass = 100; Flags = "mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC31"; DoomEd number = 59; Spawn state = "ZMOSSCEILING2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 24; Mass = 100; Flags = "mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC32"; DoomEd number = 60; Spawn state = "ZSWAMPVINE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 52; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC33"; DoomEd number = 61; Spawn state = "ZCORPSEKABOB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 92; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC34"; DoomEd number = 62; Spawn state = "ZCORPSESLEEPING1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC35"; DoomEd number = 63; Spawn state = "ZTOMBSTONERIP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 46; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC36"; DoomEd number = 64; Spawn state = "ZTOMBSTONESHANE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 46; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC37"; DoomEd number = 65; Spawn state = "ZTOMBSTONEBIGCROSS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 46; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC38"; DoomEd number = 66; Spawn state = "ZTOMBSTONEBRIANR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 52; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC39"; DoomEd number = 67; Spawn state = "ZTOMBSTONECROSSCIRCLE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 52; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC40"; DoomEd number = 68; Spawn state = "ZTOMBSTONESMALLCROSS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 46; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC41"; DoomEd number = 69; Spawn state = "ZTOMBSTONEBRIANP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 46; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC42"; DoomEd number = 71; Spawn state = "CORPSEHANGING_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 6; Height = 75; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC43"; DoomEd number = 72; Spawn state = "ZSTATUEGARGOYLEGREENTALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 108; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC44"; DoomEd number = 73; Spawn state = "ZSTATUEGARGOYLEBLUETALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 108; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC45"; DoomEd number = 74; Spawn state = "ZSTATUEGARGOYLEGREENSHORT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC46"; DoomEd number = 76; Spawn state = "ZSTATUEGARGOYLEBLUESHORT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC47"; DoomEd number = 8044; Spawn state = "ZSTATUEGARGOYLESTRIPETALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 108; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC48"; DoomEd number = 8045; Spawn state = "ZSTATUEGARGOYLEDARKREDTALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 108; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC49"; DoomEd number = 8046; Spawn state = "ZSTATUEGARGOYLEREDTALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 108; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC50"; DoomEd number = 8047; Spawn state = "ZSTATUEGARGOYLETANTALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 108; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC51"; DoomEd number = 8048; Spawn state = "ZSTATUEGARGOYLERUSTTALL_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 108; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC52"; DoomEd number = 8049; Spawn state = "ZSTATUEGARGOYLEDARKREDSHORT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC53"; DoomEd number = 8050; Spawn state = "ZSTATUEGARGOYLEREDSHORT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC54"; DoomEd number = 8051; Spawn state = "ZSTATUEGARGOYLETANSHORT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC55"; DoomEd number = 8052; Spawn state = "ZSTATUEGARGOYLERUSTSHORT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 14; Height = 62; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC56"; DoomEd number = 77; Spawn state = "ZBANNERTATTERED_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 120; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC57"; DoomEd number = 78; Spawn state = "ZTREELARGE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZTREELARGE1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 15; Height = 180; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC58"; DoomEd number = 79; Spawn state = "ZTREELARGE2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZTREELARGE2"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 15; Height = 180; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC59"; DoomEd number = 80; Spawn state = "ZTREEGNARLED1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 22; Height = 100; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC60"; DoomEd number = 87; Spawn state = "ZTREEGNARLED2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 22; Height = 100; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC61"; DoomEd number = 88; Spawn state = "ZLOG"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 25; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC62"; DoomEd number = 89; Spawn state = "ZSTALACTITEICELARGE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 66; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC63"; DoomEd number = 90; Spawn state = "ZSTALACTITEICEMEDIUM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 50; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC64"; DoomEd number = 91; Spawn state = "ZSTALACTITEICESMALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC65"; DoomEd number = 92; Spawn state = "ZSTALACTITEICETINY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 8; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC66"; DoomEd number = 93; Spawn state = "ZSTALAGMITEICELARGE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 66; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC67"; DoomEd number = 94; Spawn state = "ZSTALAGMITEICEMEDIUM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 50; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC68"; DoomEd number = 95; Spawn state = "ZSTALAGMITEICESMALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC69"; DoomEd number = 96; Spawn state = "ZSTALAGMITEICETINY"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 8; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC70"; DoomEd number = 97; Spawn state = "ZROCKBROWN1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 17; Height = 72; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC71"; DoomEd number = 98; Spawn state = "ZROCKBROWN2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 15; Height = 50; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC72"; DoomEd number = 99; Spawn state = "ZROCKBLACK"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 40; Mass = 100; Flags = "mf_solid"; } Thing { ID = "MISC73"; DoomEd number = 100; Spawn state = "ZRUBBLE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC74"; DoomEd number = 101; Spawn state = "ZRUBBLE2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC75"; DoomEd number = 102; Spawn state = "ZRUBBLE3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; } Thing { ID = "MISC76"; DoomEd number = 103; Spawn state = "ZVASEPILLAR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 54; Mass = 100; Flags = "mf_solid"; } Thing { ID = "POTTERY1"; DoomEd number = 104; Spawn state = "ZPOTTERY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZPOTTERY_EXPLODE"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 15; Radius = 10; Height = 32; Mass = 100; Flags = "mf_solid mf_shootable mf_noblood mf_dropoff"; Flags2 = "mf2_slide mf2_pushable mf2_telestomp mf2_passmobj"; } Thing { ID = "POTTERY2"; DoomEd number = 105; Spawn state = "ZPOTTERY2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZPOTTERY_EXPLODE"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 15; Radius = 10; Height = 25; Mass = 100; Flags = "mf_solid mf_shootable mf_noblood mf_dropoff"; Flags2 = "mf2_slide mf2_pushable mf2_telestomp mf2_passmobj"; } Thing { ID = "POTTERY3"; DoomEd number = 106; Spawn state = "ZPOTTERY3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZPOTTERY_EXPLODE"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 15; Radius = 15; Height = 25; Mass = 100; Flags = "mf_solid mf_shootable mf_noblood mf_dropoff"; Flags2 = "mf2_slide mf2_pushable mf2_telestomp mf2_passmobj"; } Thing { ID = "POTTERYBIT1"; DoomEd number = -1; Spawn state = "POTTERYBIT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "POTTERYBIT_EX0"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "MISC77"; DoomEd number = 108; Spawn state = "ZCORPSELYNCHED1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 11; Height = 95; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "ZLYNCHED_NOHEART"; DoomEd number = 109; Spawn state = "ZCORPSELYNCHED2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 100; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "MISC78"; DoomEd number = 110; Spawn state = "ZCORPSESITTING"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZCORPSESITTING_X"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 30; Radius = 15; Height = 35; Mass = 100; Flags = "mf_solid mf_shootable mf_noblood"; } Thing { ID = "CORPSEBIT"; DoomEd number = -1; Spawn state = "CORPSEBIT_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap"; Flags2 = "mf2_telestomp"; } Thing { ID = "CORPSEBLOODDRIP"; DoomEd number = -1; Spawn state = "CORPSEBLOODDRIP"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CORPSEBLOODDRIP_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DRIP"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 1; Height = 4; Mass = 100; Flags = "mf_missile"; Flags2 = "mf2_lograv"; } Thing { ID = "BLOODPOOL"; DoomEd number = 111; Spawn state = "BLOODPOOL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "MISC79"; DoomEd number = 119; Spawn state = "ZCANDLE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "MISC80"; DoomEd number = 113; Spawn state = "ZLEAFSPAWNER"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector mf_local"; Flags2 = "mf2_dontdraw"; } Thing { ID = "LEAF1"; DoomEd number = -1; Spawn state = "LEAF1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "LEAF_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_local"; Flags2 = "mf2_noteleport mf2_lograv"; } Thing { ID = "LEAF2"; DoomEd number = -1; Spawn state = "LEAF2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "LEAF_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_missile mf_local"; Flags2 = "mf2_noteleport mf2_lograv"; } Thing { ID = "ZTWINEDTORCH"; DoomEd number = 116; Spawn state = "ZTWINEDTORCH_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 64; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZTWINEDTORCH_UNLIT"; DoomEd number = 117; Spawn state = "ZTWINEDTORCH_UNLIT"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 10; Height = 64; Mass = 100; Flags = "mf_solid"; } Thing { ID = "BRIDGE"; DoomEd number = 118; Spawn state = "BRIDGE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 32; Height = 2; Mass = 100; Flags = "mf_solid mf_nogravity"; Flags2 = "mf2_dontdraw"; } Thing { ID = "BRIDGEBALL"; DoomEd number = -1; Spawn state = "BBALL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_viewalign"; Flags2 = "mf2_noteleport"; } Thing { ID = "ZWALLTORCH"; DoomEd number = 54; Spawn state = "ZWALLTORCH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "ZWALLTORCH_UNLIT"; DoomEd number = 55; Spawn state = "ZWALLTORCH_U"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "ZBARREL"; DoomEd number = 8100; Spawn state = "ZBARREL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 15; Height = 32; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZSHRUB1"; DoomEd number = 8101; Spawn state = "ZSHRUB1"; See state = "NULL"; Pain state = "NULL"; Melee state = "ZSHRUB1_X1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZSHRUB1_DIE"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "TREE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 20; Radius = 8; Height = 24; Mass = 2147483647; Flags = "mf_solid mf_shootable mf_noblood"; } Thing { ID = "ZSHRUB2"; DoomEd number = 8102; Spawn state = "ZSHRUB2"; See state = "NULL"; Pain state = "NULL"; Melee state = "ZSHRUB2_X1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZSHRUB2_DIE"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "TREE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 10; Radius = 16; Height = 40; Mass = 2147483647; Flags = "mf_solid mf_shootable mf_noblood"; } Thing { ID = "ZBUCKET"; DoomEd number = 8103; Spawn state = "ZBUCKET1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 72; Mass = 100; Flags = "mf_solid mf_spawnceiling mf_nogravity"; } Thing { ID = "ZPOISONSHROOM"; DoomEd number = 8104; Spawn state = "ZPOISONSHROOM1"; See state = "NULL"; Pain state = "ZPOISONSHROOM_P1"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZPOISONSHROOM_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "POISONSHROOM_PAIN"; Death sound = "POISONSHROOM_DEATH"; Active sound = "NONE"; Reaction time = 8; Pain chance = 255; Spawn health = 30; Radius = 6; Height = 20; Mass = 2147483647; Flags = "mf_shootable mf_solid mf_noblood"; } Thing { ID = "ZFIREBULL"; DoomEd number = 8042; Spawn state = "ZFIREBULL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 80; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZFIREBULL_UNLIT"; DoomEd number = 8043; Spawn state = "ZFIREBULL_U"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 80; Mass = 100; Flags = "mf_solid"; } Thing { ID = "FIRETHING"; DoomEd number = 8060; Spawn state = "ZFIRETHING1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 10; Mass = 100; Flags = "mf_solid"; } Thing { ID = "BRASSTORCH"; DoomEd number = 8061; Spawn state = "ZBRASSTORCH1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 6; Height = 35; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZSUITOFARMOR"; DoomEd number = 8064; Spawn state = "ZSUITOFARMOR"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZSUITOFARMOR_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "SUITOFARMOR_BREAK"; Active sound = "NONE"; Reaction time = 8; Spawn health = 60; Radius = 16; Height = 72; Mass = 2147483647; Flags = "mf_solid mf_shootable mf_noblood"; } Thing { ID = "ZARMORCHUNK"; DoomEd number = -1; Spawn state = "ZARMORCHUNK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 8; Mass = 100; } Thing { ID = "ZBELL"; DoomEd number = 8065; Spawn state = "ZBELL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZBELL_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "BELLRING"; Active sound = "NONE"; Reaction time = 8; Spawn health = 5; Radius = 56; Height = 120; Mass = 2147483647; Flags = "mf_solid mf_shootable mf_noblood mf_nogravity mf_spawnceiling"; } Thing { ID = "ZBLUE_CANDLE"; DoomEd number = 8066; Spawn state = "ZBLUE_CANDLE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "ZIRON_MAIDEN"; DoomEd number = 8067; Spawn state = "ZIRON_MAIDEN"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 60; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZXMAS_TREE"; DoomEd number = 8068; Spawn state = "ZXMAS_TREE"; See state = "NULL"; Pain state = "NULL"; Melee state = "ZXMAS_TREE_X1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ZXMAS_TREE_DIE"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "TREE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 20; Radius = 11; Height = 130; Mass = 2147483647; Flags = "mf_solid mf_shootable mf_noblood"; } Thing { ID = "ZCAULDRON"; DoomEd number = 8069; Spawn state = "ZCAULDRON1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 26; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZCAULDRON_UNLIT"; DoomEd number = 8070; Spawn state = "ZCAULDRON_U"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 12; Height = 26; Mass = 100; Flags = "mf_solid"; } Thing { ID = "ZCHAINBIT32"; DoomEd number = 8071; Spawn state = "ZCHAINBIT32"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_spawnceiling"; } Thing { ID = "ZCHAINBIT64"; DoomEd number = 8072; Spawn state = "ZCHAINBIT64"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 64; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_spawnceiling"; } Thing { ID = "ZCHAINEND_HEART"; DoomEd number = 8073; Spawn state = "ZCHAINEND_HEART"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_spawnceiling"; } Thing { ID = "ZCHAINEND_HOOK1"; DoomEd number = 8074; Spawn state = "ZCHAINEND_HOOK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_spawnceiling"; } Thing { ID = "ZCHAINEND_HOOK2"; DoomEd number = 8075; Spawn state = "ZCHAINEND_HOOK2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_spawnceiling"; } Thing { ID = "ZCHAINEND_SPIKE"; DoomEd number = 8076; Spawn state = "ZCHAINEND_SPIKE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_spawnceiling"; } Thing { ID = "ZCHAINEND_SKULL"; DoomEd number = 8077; Spawn state = "ZCHAINEND_SKULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 32; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_spawnceiling"; } Thing { ID = "TABLE_SHIT1"; DoomEd number = 8500; Spawn state = "TABLE_SHIT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT2"; DoomEd number = 8501; Spawn state = "TABLE_SHIT2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT3"; DoomEd number = 8502; Spawn state = "TABLE_SHIT3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT4"; DoomEd number = 8503; Spawn state = "TABLE_SHIT4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT5"; DoomEd number = 8504; Spawn state = "TABLE_SHIT5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT6"; DoomEd number = 8505; Spawn state = "TABLE_SHIT6"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT7"; DoomEd number = 8506; Spawn state = "TABLE_SHIT7"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT8"; DoomEd number = 8507; Spawn state = "TABLE_SHIT8"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT9"; DoomEd number = 8508; Spawn state = "TABLE_SHIT9"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TABLE_SHIT10"; DoomEd number = 8509; Spawn state = "TABLE_SHIT10"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap"; } Thing { ID = "TFOG"; DoomEd number = -1; Spawn state = "TFOG1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "MISC81"; DoomEd number = 140; Spawn state = "TELESMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "TELEPORTMAN"; DoomEd number = 14; Spawn state = "NULL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector"; Flags2 = "mf2_dontdraw"; } Thing { ID = "PUNCHPUFF"; DoomEd number = -1; Spawn state = "PUNCHPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "FIGHTER_PUNCH_HITTHING"; Attack sound = "FIGHTER_PUNCH_HITWALL"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_viewalign mf_nogravity mf_shadow"; } Thing { ID = "FW_AXE"; DoomEd number = 8010; Spawn state = "AXE"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "AXEPUFF"; DoomEd number = -1; Spawn state = "HAMMERPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "FIGHTER_AXE_HITTHING"; Attack sound = "FIGHTER_HAMMER_HITWALL"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "AXEPUFF_GLOW"; DoomEd number = -1; Spawn state = "AXEPUFF_GLOW1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "FIGHTER_AXE_HITTHING"; Attack sound = "FIGHTER_HAMMER_HITWALL"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "AXEBLOOD"; DoomEd number = -1; Spawn state = "AXEBLOOD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "AXEBLOOD6"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_dropoff"; Flags2 = "mf2_noteleport mf2_cannotpush"; } Thing { ID = "FW_HAMMER"; DoomEd number = 123; Spawn state = "HAMM"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "HAMMER_MISSILE"; DoomEd number = -1; Spawn state = "HAMMER_MISSILE_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HAMMER_MISSILE_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "FIGHTER_HAMMER_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 14; Height = 20; Mass = 100; Damage = 10; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross mf2_firedamage"; } Thing { ID = "HAMMERPUFF"; DoomEd number = -1; Spawn state = "HAMMERPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "FIGHTER_HAMMER_HITTHING"; Attack sound = "FIGHTER_HAMMER_HITWALL"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "FSWORD_MISSILE"; DoomEd number = -1; Spawn state = "FSWORD_MISSILE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FSWORD_MISSILE_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "FIGHTER_SWORD_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 30; Radius = 16; Height = 8; Mass = 100; Damage = 8; Flags = "mf_missile mf_brightexplode mf_noblockmap mf_nogravity mf_dropoff"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross"; } Thing { ID = "FSWORD_FLAME"; DoomEd number = -1; Spawn state = "FSWORD_FLAME1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_viewalign mf_shadow"; } Thing { ID = "CW_SERPSTAFF"; DoomEd number = 10; Spawn state = "CSTAFF"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "CSTAFF_MISSILE"; DoomEd number = -1; Spawn state = "CSTAFF_MISSILE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CSTAFF_MISSILE_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "CLERIC_CSTAFF_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 22; Radius = 12; Height = 10; Mass = 100; Damage = 5; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross"; } Thing { ID = "CSTAFFPUFF"; DoomEd number = -1; Spawn state = "CSTAFFPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "CLERIC_CSTAFF_HITTHING"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "CW_FLAME"; DoomEd number = 8009; Spawn state = "CFLAME1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity mf_viewalign"; } Thing { ID = "CFLAMEFLOOR"; DoomEd number = -1; Spawn state = "CFLAMEFLOOR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_viewalign mf_nogravity"; } Thing { ID = "FLAMEPUFF"; DoomEd number = -1; Spawn state = "FLAMEPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "CLERIC_FLAME_EXPLODE"; Attack sound = "CLERIC_FLAME_EXPLODE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 1; Height = 1; Mass = 100; Flags = "mf_noblockmap mf_viewalign mf_nogravity mf_brightshadow"; } Thing { ID = "FLAMEPUFF2"; DoomEd number = -1; Spawn state = "FLAMEPUFF2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "CLERIC_FLAME_EXPLODE"; Attack sound = "CLERIC_FLAME_EXPLODE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 1; Height = 1; Mass = 100; Flags = "mf_noblockmap mf_viewalign mf_nogravity mf_brightshadow"; } Thing { ID = "CIRCLEFLAME"; DoomEd number = -1; Spawn state = "CIRCLE_FLAME1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CIRCLE_FLAME_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "CLERIC_FLAME_CIRCLE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 6; Height = 16; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity mf_brightshadow"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "CFLAME_MISSILE"; DoomEd number = -1; Spawn state = "CFLAME_MISSILE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CFLAME_MISSILE_X"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 200; Radius = 14; Height = 8; Mass = 100; Damage = 8; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity mf_brightshadow"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross mf2_dontdraw mf2_firedamage"; } Thing { ID = "HOLY_FX"; DoomEd number = -1; Spawn state = "HOLY_FX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HOLY_FX_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "SPIRIT_DIE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 105; Speed = 12; Radius = 10; Height = 6; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_brightshadow mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_seekermissile mf2_rip mf2_impact mf2_pcross"; } Thing { ID = "HOLY_TAIL"; DoomEd number = -1; Spawn state = "HOLY_TAIL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 1; Height = 1; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_viewalign mf_noclip mf_altshadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "HOLY_PUFF"; DoomEd number = -1; Spawn state = "HOLY_PUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "HOLY_MISSILE"; DoomEd number = -1; Spawn state = "HOLY_MISSILE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "HOLY_MISSILE_X"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 30; Radius = 15; Height = 8; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "HOLY_MISSILE_PUFF"; DoomEd number = -1; Spawn state = "HOLY_MISSILE_P1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 8; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_viewalign mf_altshadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "MWANDPUFF"; DoomEd number = -1; Spawn state = "MWANDPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_viewalign mf_nogravity"; Flags2 = "mf2_noteleport mf2_cannotpush mf2_nodmgthrust"; } Thing { ID = "MWANDSMOKE"; DoomEd number = -1; Spawn state = "MWANDSMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_viewalign mf_shadow"; Flags2 = "mf2_noteleport mf2_cannotpush mf2_nodmgthrust"; } Thing { ID = "MWAND_MISSILE"; DoomEd number = -1; Spawn state = "MWAND_MISSILE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MWANDPUFF1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 184; Radius = 12; Height = 8; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_rip mf2_impact mf2_pcross mf2_nodmgthrust mf2_cannotpush"; } Thing { ID = "MW_LIGHTNING"; DoomEd number = 8040; Spawn state = "MW_LIGHTNING1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "LIGHTNING_CEILING"; DoomEd number = -1; Spawn state = "LIGHTNING_CEILING1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "LIGHTNING_C_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 144; Speed = 25; Radius = 16; Height = 40; Mass = 100; Damage = 8; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightexplode mf_dropoff"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross"; } Thing { ID = "LIGHTNING_FLOOR"; DoomEd number = -1; Spawn state = "LIGHTNING_FLOOR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "LIGHTNING_F_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 144; Speed = 25; Radius = 16; Height = 40; Mass = 100; Damage = 8; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightexplode mf_dropoff"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross"; } Thing { ID = "LIGHTNING_ZAP"; DoomEd number = -1; Spawn state = "LIGHTNING_ZAP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "LIGHTNING_ZAP_X8"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 15; Height = 35; Mass = 100; Damage = 2; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightexplode mf_viewalign mf_dropoff"; } Thing { ID = "MSTAFF_FX"; DoomEd number = -1; Spawn state = "MSTAFF_FX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MSTAFF_FX_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "MAGE_STAFF_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 16; Height = 8; Mass = 100; Damage = 6; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage mf2_rip mf2_impact mf2_pcross"; } Thing { ID = "MSTAFF_FX2"; DoomEd number = -1; Spawn state = "MSTAFF_FX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MSTAFF_FX2_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "MAGE_STAFF_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 17; Radius = 20; Height = 8; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage mf2_impact mf2_pcross mf2_seekermissile"; } Thing { ID = "FW_SWORD1"; DoomEd number = 12; Spawn state = "FSWORD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "FW_SWORD2"; DoomEd number = 13; Spawn state = "FSWORD2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "FW_SWORD3"; DoomEd number = 16; Spawn state = "FSWORD3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "CW_HOLY1"; DoomEd number = 18; Spawn state = "CHOLY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "CW_HOLY2"; DoomEd number = 19; Spawn state = "CHOLY2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "CW_HOLY3"; DoomEd number = 20; Spawn state = "CHOLY3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "MW_STAFF1"; DoomEd number = 21; Spawn state = "MSTAFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "MW_STAFF2"; DoomEd number = 22; Spawn state = "MSTAFF2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "MW_STAFF3"; DoomEd number = 23; Spawn state = "MSTAFF3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "SNOUTPUFF"; DoomEd number = -1; Spawn state = "PUNCHPUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "MW_CONE"; DoomEd number = 53; Spawn state = "COS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special"; } Thing { ID = "SHARDFX1"; DoomEd number = -1; Spawn state = "SHARDFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SHARDFXE1_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "MAGE_SHARDS_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 25; Radius = 13; Height = 8; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross mf2_icedamage"; } Thing { ID = "BLOOD"; DoomEd number = -1; Spawn state = "BLOOD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 5; Flags = "mf_noblockmap mf_viewalign"; } Thing { ID = "BLOODSPLATTER"; DoomEd number = -1; Spawn state = "BLOODSPLATTER1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BLOODSPLATTERX"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 4; Mass = 5; Flags = "mf_noblockmap mf_missile mf_dropoff"; Flags2 = "mf2_noteleport mf2_cannotpush"; } Thing { ID = "GIBS"; DoomEd number = -1; Spawn state = "GIBS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport"; } Thing { ID = "PLAYER_FIGHTER"; DoomEd number = -1; Spawn state = "FPLAY"; See state = "FPLAY_RUN1"; Pain state = "FPLAY_PAIN"; Melee state = "NULL"; Missile state = "FPLAY_ATK1"; Crash state = "NULL"; Death state = "FPLAY_DIE1"; Xdeath state = "FPLAY_XDIE1"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "PLAYER_FIGHTER_PAIN"; Death sound = "NONE"; Active sound = "NONE"; Pain chance = 255; Spawn health = 100; Radius = 16; Height = 64; Mass = 100; Flags = solid | shootable | dropoff | pickup; Flags2 = windthrust | floorclip | slide | passmobj | telestomp | pushwall; } Thing { ID = "BLOODYSKULL"; DoomEd number = -1; Spawn state = "BLOODYSKULL1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 4; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_dropoff"; Flags2 = "mf2_lograv mf2_cannotpush"; } Thing { ID = "PLAYER_SPEED"; DoomEd number = -1; Spawn state = "PLAYER_SPEED1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_altshadow"; } Thing { ID = "ICECHUNK"; DoomEd number = -1; Spawn state = "ICECHUNK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 4; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_altshadow"; Flags2 = "mf2_lograv mf2_cannotpush mf2_floorclip"; } Thing { ID = "PLAYER_CLERIC"; DoomEd number = -1; Spawn state = "CPLAY"; See state = "CPLAY_RUN1"; Pain state = "CPLAY_PAIN"; Melee state = "NULL"; Missile state = "CPLAY_ATK1"; Crash state = "NULL"; Death state = "CPLAY_DIE1"; Xdeath state = "CPLAY_XDIE1"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "PLAYER_CLERIC_PAIN"; Death sound = "NONE"; Active sound = "NONE"; Pain chance = 255; Spawn health = 100; Radius = 16; Height = 64; Mass = 100; Flags = solid | shootable | dropoff | pickup; Flags2 = windthrust | floorclip | slide | passmobj | telestomp | pushwall; } Thing { ID = "PLAYER_MAGE"; DoomEd number = -1; Spawn state = "MPLAY"; See state = "MPLAY_RUN1"; Pain state = "MPLAY_PAIN"; Melee state = "NULL"; Missile state = "MPLAY_ATK1"; Crash state = "NULL"; Death state = "MPLAY_DIE1"; Xdeath state = "MPLAY_XDIE1"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "PLAYER_MAGE_PAIN"; Death sound = "NONE"; Active sound = "NONE"; Pain chance = 255; Spawn health = 100; Radius = 16; Height = 64; Mass = 100; Flags = solid | shootable | dropoff | pickup; Flags2 = windthrust | floorclip | slide | passmobj | telestomp | pushwall; } Thing { ID = "PIGPLAYER"; DoomEd number = -1; Spawn state = "PIGPLAY"; See state = "PIGPLAY_RUN1"; Pain state = "PIGPLAY_PAIN"; Melee state = "NULL"; Missile state = "PIGPLAY_ATK1"; Crash state = "NULL"; Death state = "PIG_DIE1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "PIG_PAIN"; Death sound = "PIG_DEATH"; Active sound = "NONE"; Pain chance = 255; Spawn health = 100; Radius = 16; Height = 24; Mass = 100; Flags = solid | shootable | dropoff; Flags2 = windthrust | slide | passmobj | floorclip | telestomp | pushwall; } Thing { ID = "PIG"; DoomEd number = -1; Spawn state = "PIG_LOOK1"; See state = "PIG_WALK1"; Pain state = "PIG_PAIN"; Melee state = "PIG_ATK1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "PIG_DIE1"; Xdeath state = "NULL"; See sound = "PIG_ACTIVE1"; Attack sound = "NONE"; Pain sound = "PIG_PAIN"; Death sound = "PIG_DEATH"; Active sound = "PIG_ACTIVE1"; Reaction time = 8; Pain chance = 128; Spawn health = 25; Speed = 10; Radius = 12; Height = 22; Mass = 60; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_windthrust mf2_floorclip mf2_passmobj mf2_pushwall mf2_telestomp"; } Thing { ID = "CENTAUR"; DoomEd number = 107; Spawn state = "CENTAUR_LOOK1"; See state = "CENTAUR_WALK1"; Pain state = "CENTAUR_PAIN1"; Melee state = "CENTAUR_ATK1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CENTAUR_DEATH1"; Xdeath state = "CENTAUR_DEATH_X1"; See sound = "CENTAUR_SIGHT"; Attack sound = "CENTAUR_ATTACK"; Pain sound = "CENTAUR_PAIN"; Death sound = "CENTAUR_DEATH"; Active sound = "CENTAUR_ACTIVE"; Reaction time = 8; Pain chance = 135; Spawn health = 200; Speed = 13; Radius = 20; Height = 64; Mass = 120; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_pushwall mf2_mcross mf2_telestomp"; } Thing { ID = "CENTAURLEADER"; DoomEd number = 115; Spawn state = "CENTAUR_LOOK1"; See state = "CENTAUR_WALK1"; Pain state = "CENTAUR_PAIN1"; Melee state = "CENTAUR_ATK1"; Missile state = "CENTAUR_MISSILE1"; Crash state = "NULL"; Death state = "CENTAUR_DEATH1"; Xdeath state = "CENTAUR_DEATH_X1"; See sound = "CENTAUR_SIGHT"; Attack sound = "CENTAUR_ATTACK"; Pain sound = "CENTAUR_PAIN"; Death sound = "CENTAUR_DEATH"; Active sound = "CENTAUR_ACTIVE"; Reaction time = 8; Pain chance = 96; Spawn health = 250; Speed = 10; Radius = 20; Height = 64; Mass = 120; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_pushwall mf2_mcross mf2_telestomp"; } Thing { ID = "CENTAUR_FX"; DoomEd number = -1; Spawn state = "CENTAUR_FX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CENTAUR_FX_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "CENTAUR_MISSILE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 20; Height = 16; Mass = 100; Damage = 4; Flags = "mf_missile mf_brightexplode mf_noblockmap mf_nogravity mf_dropoff"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross"; } Thing { ID = "CENTAUR_SHIELD"; DoomEd number = -1; Spawn state = "CENTAUR_SHIELD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CENTAUR_SHIELD_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport"; } Thing { ID = "CENTAUR_SWORD"; DoomEd number = -1; Spawn state = "CENTAUR_SWORD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "CENTAUR_SWORD_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport"; } Thing { ID = "DEMON"; DoomEd number = 31; Spawn state = "DEMN_LOOK1"; See state = "DEMN_CHASE1"; Pain state = "DEMN_PAIN1"; Melee state = "DEMN_ATK1_1"; Missile state = "DEMN_ATK2_1"; Crash state = "NULL"; Death state = "DEMN_DEATH1"; Xdeath state = "DEMN_XDEATH1"; See sound = "DEMON_SIGHT"; Attack sound = "DEMON_ATTACK"; Pain sound = "DEMON_PAIN"; Death sound = "DEMON_DEATH"; Active sound = "DEMON_ACTIVE"; Reaction time = 8; Pain chance = 50; Spawn health = 250; Speed = 13; Radius = 32; Height = 64; Mass = 220; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_mcross mf2_telestomp"; } Thing { ID = "DEMONCHUNK1"; DoomEd number = -1; Spawn state = "DEMONCHUNK1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMONCHUNK1_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMONCHUNK2"; DoomEd number = -1; Spawn state = "DEMONCHUNK2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMONCHUNK2_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMONCHUNK3"; DoomEd number = -1; Spawn state = "DEMONCHUNK3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMONCHUNK3_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMONCHUNK4"; DoomEd number = -1; Spawn state = "DEMONCHUNK4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMONCHUNK4_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMONCHUNK5"; DoomEd number = -1; Spawn state = "DEMONCHUNK5_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMONCHUNK5_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMONFX1"; DoomEd number = -1; Spawn state = "DEMONFX_MOVE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMONFX_BOOM1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DEMON_MISSILE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 10; Height = 6; Mass = 100; Damage = 5; Flags = "mf_missile mf_brightexplode mf_noblockmap mf_nogravity mf_dropoff"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross mf2_firedamage"; } Thing { ID = "DEMON2"; DoomEd number = 8080; Spawn state = "DEMN2_LOOK1"; See state = "DEMN2_CHASE1"; Pain state = "DEMN2_PAIN1"; Melee state = "DEMN2_ATK1_1"; Missile state = "DEMN2_ATK2_1"; Crash state = "NULL"; Death state = "DEMN2_DEATH1"; Xdeath state = "DEMN2_XDEATH1"; See sound = "DEMON_SIGHT"; Attack sound = "DEMON_ATTACK"; Pain sound = "DEMON_PAIN"; Death sound = "DEMON_DEATH"; Active sound = "DEMON_ACTIVE"; Reaction time = 8; Pain chance = 50; Spawn health = 250; Speed = 13; Radius = 32; Height = 64; Mass = 220; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_mcross mf2_telestomp"; } Thing { ID = "DEMON2CHUNK1"; DoomEd number = -1; Spawn state = "DEMON2CHUNK1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMON2CHUNK1_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMON2CHUNK2"; DoomEd number = -1; Spawn state = "DEMON2CHUNK2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMON2CHUNK2_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMON2CHUNK3"; DoomEd number = -1; Spawn state = "DEMON2CHUNK3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMON2CHUNK3_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMON2CHUNK4"; DoomEd number = -1; Spawn state = "DEMON2CHUNK4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMON2CHUNK4_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMON2CHUNK5"; DoomEd number = -1; Spawn state = "DEMON2CHUNK5_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMON2CHUNK5_4"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "DEMON2FX1"; DoomEd number = -1; Spawn state = "DEMON2FX_MOVE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DEMON2FX_BOOM1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DEMON_MISSILE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 10; Height = 6; Mass = 100; Damage = 5; Flags = "mf_missile mf_brightexplode mf_noblockmap mf_nogravity mf_dropoff"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross mf2_firedamage"; } Thing { ID = "WRAITHB"; DoomEd number = 10011; Spawn state = "WRAITH_LOOK1"; See state = "WRAITH_RAISE1"; Pain state = "WRAITH_PAIN1"; Melee state = "WRAITH_ATK1_1"; Missile state = "WRAITH_ATK2_1"; Crash state = "NULL"; Death state = "WRAITH_DEATH1_1"; Xdeath state = "WRAITH_DEATH2_1"; See sound = "WRAITH_SIGHT"; Attack sound = "WRAITH_ATTACK"; Pain sound = "WRAITH_PAIN"; Death sound = "WRAITH_DEATH"; Active sound = "WRAITH_ACTIVE"; Reaction time = 8; Pain chance = 25; Spawn health = 150; Speed = 11; Radius = 20; Height = 68; Mass = 75; Damage = 10; Flags = "mf_dropoff mf_nogravity mf_float mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_pushwall mf2_telestomp mf2_dontdraw"; } Thing { ID = "WRAITH"; DoomEd number = 34; Spawn state = "WRAITH_INIT1"; See state = "WRAITH_CHASE1"; Pain state = "WRAITH_PAIN1"; Melee state = "WRAITH_ATK1_1"; Missile state = "WRAITH_ATK2_1"; Crash state = "NULL"; Death state = "WRAITH_DEATH1_1"; Xdeath state = "WRAITH_DEATH2_1"; See sound = "WRAITH_SIGHT"; Attack sound = "WRAITH_ATTACK"; Pain sound = "WRAITH_PAIN"; Death sound = "WRAITH_DEATH"; Active sound = "WRAITH_ACTIVE"; Reaction time = 8; Pain chance = 25; Spawn health = 150; Speed = 11; Radius = 20; Height = 55; Mass = 75; Damage = 10; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff mf_nogravity mf_float"; Flags2 = "mf2_floorclip mf2_passmobj mf2_pushwall mf2_telestomp"; } Thing { ID = "WRAITHFX1"; DoomEd number = -1; Spawn state = "WRTHFX_MOVE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "WRTHFX_BOOM1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "WRAITH_MISSILE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 14; Radius = 10; Height = 6; Mass = 5; Damage = 5; Flags = "mf_noblockmap mf_nogravity mf_dropoff mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross mf2_floorclip mf2_firedamage"; } Thing { ID = "WRAITHFX2"; DoomEd number = -1; Spawn state = "WRTHFX_SIZZLE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 5; Mass = 5; Flags = "mf_noblockmap mf_dropoff"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "WRAITHFX3"; DoomEd number = -1; Spawn state = "WRTHFX_DROP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "WRTHFX_DEAD1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DRIP"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 5; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "WRAITHFX4"; DoomEd number = -1; Spawn state = "WRTHFX_ADROP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "WRTHFX_ADEAD1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DRIP"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 5; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "WRAITHFX5"; DoomEd number = -1; Spawn state = "WRTHFX_BDROP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "WRTHFX_BDEAD1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DRIP"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 2; Height = 5; Mass = 5; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "MINOTAUR"; DoomEd number = 9; Spawn state = "MNTR_SPAWN1"; See state = "MNTR_WALK1"; Pain state = "MNTR_PAIN1"; Melee state = "MNTR_ATK1_1"; Missile state = "MNTR_ATK2_1"; Crash state = "NULL"; Death state = "MNTR_DIE1"; Xdeath state = "NULL"; See sound = "MAULATOR_SIGHT"; Attack sound = "MAULATOR_HAMMER_SWING"; Pain sound = "MAULATOR_PAIN"; Death sound = "MAULATOR_DEATH"; Active sound = "MAULATOR_ACTIVE"; Reaction time = 8; Pain chance = 25; Spawn health = 2500; Speed = 16; Radius = 28; Height = 100; Mass = 800; Damage = 7; Flags = "mf_solid mf_shootable mf_countkill mf_shadow"; Flags2 = "mf2_floorclip mf2_passmobj mf2_pushwall mf2_telestomp"; } Thing { ID = "MNTRFX1"; DoomEd number = -1; Spawn state = "MNTRFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MNTRFXI1_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 20; Radius = 10; Height = 6; Mass = 100; Damage = 3; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "MNTRFX2"; DoomEd number = -1; Spawn state = "MNTRFX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MNTRFXI2_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 14; Radius = 5; Height = 12; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "MNTRFX3"; DoomEd number = -1; Spawn state = "MNTRFX3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "MNTRFXI2_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 16; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "MNTRSMOKE"; DoomEd number = -1; Spawn state = "MINOSMOKE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "MNTRSMOKEEXIT"; DoomEd number = -1; Spawn state = "MINOSMOKEX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "SERPENT"; DoomEd number = 121; Spawn state = "SERPENT_LOOK1"; See state = "SERPENT_SWIM1"; Pain state = "SERPENT_PAIN1"; Melee state = "SERPENT_SURFACE1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SERPENT_DIE1"; Xdeath state = "SERPENT_XDIE1"; See sound = "SERPENT_SIGHT"; Attack sound = "SERPENT_ATTACK"; Pain sound = "SERPENT_PAIN"; Death sound = "SERPENT_DEATH"; Active sound = "NONE"; Reaction time = 8; Pain chance = 96; Spawn health = 90; Speed = 12; Radius = 32; Height = 70; Mass = 2147483647; Flags = "mf_solid mf_countkill mf_noblood"; Flags2 = "mf2_passmobj mf2_dontdraw mf2_cantleavefloorpic mf2_nonshootable mf2_mcross"; } Thing { ID = "SERPENTLEADER"; DoomEd number = 120; Spawn state = "SERPENT_LOOK1"; See state = "SERPENT_SWIM1"; Pain state = "SERPENT_PAIN1"; Melee state = "SERPENT_SURFACE1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SERPENT_DIE1"; Xdeath state = "SERPENT_XDIE1"; See sound = "SERPENT_SIGHT"; Attack sound = "SERPENT_ATTACK"; Pain sound = "SERPENT_PAIN"; Death sound = "SERPENT_DEATH"; Active sound = "NONE"; Reaction time = 8; Pain chance = 96; Spawn health = 90; Speed = 12; Radius = 32; Height = 70; Mass = 200; Flags = "mf_solid mf_countkill mf_noblood"; Flags2 = "mf2_passmobj mf2_dontdraw mf2_cantleavefloorpic mf2_nonshootable mf2_mcross"; } Thing { ID = "SERPENTFX"; DoomEd number = -1; Spawn state = "SERPENT_FX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SERPENT_FX_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "SERPENTFX_HIT"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 8; Height = 10; Mass = 100; Damage = 4; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "SERPENT_HEAD"; DoomEd number = -1; Spawn state = "SERPENT_HEAD1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 10; Mass = 100; Flags = "mf_noblockmap"; Flags2 = "mf2_lograv"; } Thing { ID = "SERPENT_GIB1"; DoomEd number = -1; Spawn state = "SERPENT_GIB1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 3; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "SERPENT_GIB2"; DoomEd number = -1; Spawn state = "SERPENT_GIB2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 3; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "SERPENT_GIB3"; DoomEd number = -1; Spawn state = "SERPENT_GIB3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 3; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; } Thing { ID = "BISHOP"; DoomEd number = 114; Spawn state = "BISHOP_LOOK1"; See state = "BISHOP_WALK1"; Pain state = "BISHOP_PAIN1"; Melee state = "NULL"; Missile state = "BISHOP_ATK1"; Crash state = "NULL"; Death state = "BISHOP_DEATH1"; Xdeath state = "NULL"; See sound = "BISHOP_SIGHT"; Attack sound = "BISHOP_ATTACK"; Pain sound = "BISHOP_PAIN"; Death sound = "BISHOP_DEATH"; Active sound = "BISHOP_ACTIVE"; Reaction time = 8; Pain chance = 110; Spawn health = 130; Speed = 10; Radius = 22; Height = 65; Mass = 100; Flags = "mf_solid mf_shootable mf_countkill mf_float mf_nogravity mf_noblood"; Flags2 = "mf2_passmobj mf2_pushwall mf2_telestomp"; } Thing { ID = "BISHOP_PUFF"; DoomEd number = -1; Spawn state = "BISHOP_PUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_shadow mf_noblockmap mf_nogravity"; } Thing { ID = "BISHOPBLUR"; DoomEd number = -1; Spawn state = "BISHOPBLUR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "BISHOPPAINBLUR"; DoomEd number = -1; Spawn state = "BISHOPPAINBLUR1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow"; } Thing { ID = "BISH_FX"; DoomEd number = -1; Spawn state = "BISHFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BISHFXI1_1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "BISHOP_MISSILE_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 10; Height = 6; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_seekermissile"; } Thing { ID = "DRAGON"; DoomEd number = 254; Spawn state = "DRAGON_LOOK1"; See state = "DRAGON_INIT"; Pain state = "DRAGON_PAIN1"; Melee state = "NULL"; Missile state = "DRAGON_ATK1"; Crash state = "NULL"; Death state = "DRAGON_DEATH1"; Xdeath state = "NULL"; See sound = "DRAGON_SIGHT"; Attack sound = "DRAGON_ATTACK"; Pain sound = "DRAGON_PAIN"; Death sound = "DRAGON_DEATH"; Active sound = "DRAGON_ACTIVE"; Reaction time = 8; Pain chance = 128; Spawn health = 640; Speed = 10; Radius = 20; Height = 65; Mass = 2147483647; Flags = "mf_solid mf_shootable mf_countkill mf_float mf_nogravity mf_noblood"; Flags2 = "mf2_passmobj mf2_boss"; Flags3 = "mf3_noinfight"; } Thing { ID = "DRAGON_FX"; DoomEd number = -1; Spawn state = "DRAGON_FX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "DRAGON_FX1_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DRAGON_FIREBALL_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 24; Radius = 12; Height = 10; Mass = 100; Damage = 6; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_firedamage"; } Thing { ID = "DRAGON_FX2"; DoomEd number = -1; Spawn state = "DRAGON_FX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DRAGON_FIREBALL_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 8; Mass = 100; Flags = "mf_noblockmap"; Flags2 = "mf2_noteleport mf2_firedamage mf2_dontdraw"; } Thing { ID = "ARMOR_1"; Name = "Mesh Armor"; DoomEd number = 8005; Spawn state = "ARMOR_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARMOR_2"; Name = "Falcon Shield"; DoomEd number = 8006; Spawn state = "ARMOR_2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARMOR_3"; Name = "Platinum Helmet"; DoomEd number = 8007; Spawn state = "ARMOR_3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "ARMOR_4"; Name = "Amulet of Warding"; DoomEd number = 8008; Spawn state = "ARMOR_4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_special mf_nogravity"; } Thing { ID = "MANA1"; Name = "Blue Mana"; DoomEd number = 122; Spawn state = "MANA1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 10; Radius = 8; Height = 8; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "MANA2"; Name = "Green Mana"; DoomEd number = 124; Spawn state = "MANA2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 10; Radius = 8; Height = 8; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "MANA3"; Name = "Combined Mana"; DoomEd number = 8004; Spawn state = "MANA3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 20; Radius = 8; Height = 8; Mass = 100; Flags = "mf_special"; Flags2 = "mf2_floatbob"; } Thing { ID = "KEY1"; DoomEd number = 8030; Spawn state = "KEY1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY2"; DoomEd number = 8031; Spawn state = "KEY2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY3"; DoomEd number = 8032; Spawn state = "KEY3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY4"; DoomEd number = 8033; Spawn state = "KEY4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY5"; DoomEd number = 8034; Spawn state = "KEY5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY6"; DoomEd number = 8035; Spawn state = "KEY6"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY7"; DoomEd number = 8036; Spawn state = "KEY7"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY8"; DoomEd number = 8037; Spawn state = "KEY8"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEY9"; DoomEd number = 8038; Spawn state = "KEY9"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEYA"; DoomEd number = 8039; Spawn state = "KEYA"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "KEYB"; DoomEd number = 8200; Spawn state = "KEYB"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 8; Height = 20; Mass = 100; Flags = "mf_special"; } Thing { ID = "SOUNDWIND"; DoomEd number = 1410; Spawn state = "SND_WIND1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector"; Flags2 = "mf2_dontdraw"; } Thing { ID = "SOUNDWATERFALL"; DoomEd number = 41; Spawn state = "SND_WATERFALL"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector"; Flags2 = "mf2_dontdraw"; } Thing { ID = "ETTIN"; DoomEd number = 10030; Spawn state = "ETTIN_LOOK1"; See state = "ETTIN_CHASE1"; Pain state = "ETTIN_PAIN1"; Melee state = "ETTIN_ATK1_1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ETTIN_DEATH1_1"; Xdeath state = "ETTIN_DEATH2_1"; See sound = "ETTIN_SIGHT"; Attack sound = "ETTIN_ATTACK"; Pain sound = "ETTIN_PAIN"; Death sound = "ETTIN_DEATH"; Active sound = "ETTIN_ACTIVE"; Reaction time = 8; Pain chance = 60; Spawn health = 175; Speed = 13; Radius = 25; Height = 68; Mass = 175; Damage = 3; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_pushwall mf2_mcross mf2_telestomp"; } Thing { ID = "ETTIN_MACE"; DoomEd number = -1; Spawn state = "ETTIN_MACE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ETTIN_MACE5"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "FIREDEMON"; DoomEd number = 10060; Spawn state = "FIRED_SPAWN1"; See state = "FIRED_LOOK4"; Pain state = "FIRED_PAIN1"; Melee state = "NULL"; Missile state = "FIRED_ATTACK1"; Crash state = "FIRED_XDEATH1"; Death state = "FIRED_DEATH1"; Xdeath state = "FIRED_XDEATH1"; See sound = "FIRED_SPAWN"; Attack sound = "NONE"; Pain sound = "FIRED_PAIN"; Death sound = "FIRED_DEATH"; Active sound = "FIRED_ACTIVE"; Reaction time = 8; Pain chance = 1; Spawn health = 80; Speed = 13; Radius = 20; Height = 68; Mass = 75; Damage = 1; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff mf_nogravity mf_float"; Flags2 = "mf2_floorclip mf2_passmobj mf2_pushwall mf2_invulnerable mf2_mcross mf2_telestomp"; } Thing { ID = "FIREDEMON_SPLOTCH1"; DoomEd number = -1; Spawn state = "FIRED_CORPSE1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 16; Mass = 100; Flags = "mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "FIREDEMON_SPLOTCH2"; DoomEd number = -1; Spawn state = "FIRED_CORPSE4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 16; Mass = 100; Flags = "mf_dropoff mf_corpse"; Flags2 = "mf2_noteleport mf2_floorclip"; } Thing { ID = "FIREDEMON_FX1"; DoomEd number = -1; Spawn state = "FIRED_RDROP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FIRED_RDEAD1_1"; Xdeath state = "FIRED_RDEAD1_2"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 5; Mass = 16; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "FIREDEMON_FX2"; DoomEd number = -1; Spawn state = "FIRED_RDROP2"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FIRED_RDEAD2_1"; Xdeath state = "FIRED_RDEAD2_2"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 5; Mass = 16; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "FIREDEMON_FX3"; DoomEd number = -1; Spawn state = "FIRED_RDROP3"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FIRED_RDEAD3_1"; Xdeath state = "FIRED_RDEAD3_2"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 5; Mass = 16; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "FIREDEMON_FX4"; DoomEd number = -1; Spawn state = "FIRED_RDROP4"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FIRED_RDEAD4_1"; Xdeath state = "FIRED_RDEAD4_2"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 5; Mass = 16; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "FIREDEMON_FX5"; DoomEd number = -1; Spawn state = "FIRED_RDROP5"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FIRED_RDEAD5_1"; Xdeath state = "FIRED_RDEAD5_2"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 3; Height = 5; Mass = 16; Flags = "mf_noblockmap mf_dropoff mf_missile"; Flags2 = "mf2_noteleport"; } Thing { ID = "FIREDEMON_FX6"; DoomEd number = -1; Spawn state = "FIRED_FX6_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "FIRED_FX6_2"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "FIRED_MISSILE_HIT"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 10; Height = 6; Mass = 15; Damage = 1; Flags = "mf_noblockmap mf_nogravity mf_dropoff mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_impact mf2_pcross mf2_floorclip mf2_firedamage"; } Thing { ID = "ICEGUY"; DoomEd number = 8020; Spawn state = "ICEGUY_LOOK"; See state = "ICEGUY_WALK1"; Pain state = "ICEGUY_PAIN1"; Melee state = "NULL"; Missile state = "ICEGUY_ATK1"; Crash state = "NULL"; Death state = "ICEGUY_DEATH"; Xdeath state = "NULL"; See sound = "ICEGUY_SIGHT"; Attack sound = "ICEGUY_ATTACK"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "ICEGUY_ACTIVE"; Reaction time = 8; Pain chance = 144; Spawn health = 120; Speed = 14; Radius = 22; Height = 75; Mass = 150; Flags = "mf_solid mf_shootable mf_countkill mf_noblood"; Flags2 = "mf2_passmobj mf2_pushwall mf2_icedamage mf2_mcross mf2_telestomp"; } Thing { ID = "ICEGUY_FX"; DoomEd number = -1; Spawn state = "ICEGUY_FX1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "ICEGUY_FX_X1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "ICEGUY_FX_EXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 14; Radius = 8; Height = 10; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_dropoff mf_nogravity"; Flags2 = "mf2_noteleport mf2_icedamage"; } Thing { ID = "ICEFX_PUFF"; DoomEd number = -1; Spawn state = "ICEFX_PUFF1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 1; Height = 1; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_shadow mf_dropoff"; Flags2 = "mf2_noteleport"; } Thing { ID = "ICEGUY_FX2"; DoomEd number = -1; Spawn state = "ICEGUY_FX2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 4; Height = 4; Mass = 100; Damage = 1; Flags = "mf_noblockmap mf_dropoff mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_lograv mf2_icedamage"; } Thing { ID = "ICEGUY_BIT"; DoomEd number = -1; Spawn state = "ICEGUY_BIT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 1; Height = 1; Mass = 100; Flags = "mf_noblockmap mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv"; } Thing { ID = "ICEGUY_WISP1"; DoomEd number = -1; Spawn state = "ICEGUY_WISP1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "ICEGUY_WISP2"; DoomEd number = -1; Spawn state = "ICEGUY_WISP2_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "FIGHTER_BOSS"; DoomEd number = 10100; Spawn state = "FIGHTER"; See state = "FIGHTER_RUN1"; Pain state = "FIGHTER_PAIN"; Melee state = "FIGHTER_ATK1"; Missile state = "FIGHTER_ATK1"; Crash state = "NULL"; Death state = "FIGHTER_DIE1"; Xdeath state = "FIGHTER_XDIE1"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "PLAYER_FIGHTER_PAIN"; Death sound = "PLAYER_FIGHTER_CRAZY_DEATH"; Active sound = "NONE"; Reaction time = 8; Pain chance = 50; Spawn health = 800; Speed = 25; Radius = 16; Height = 64; Mass = 100; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_telestomp mf2_pushwall mf2_mcross"; } Thing { ID = "CLERIC_BOSS"; DoomEd number = 10101; Spawn state = "CLERIC"; See state = "CLERIC_RUN1"; Pain state = "CLERIC_PAIN"; Melee state = "CLERIC_ATK1"; Missile state = "CLERIC_ATK1"; Crash state = "NULL"; Death state = "CLERIC_DIE1"; Xdeath state = "CLERIC_XDIE1"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "PLAYER_CLERIC_PAIN"; Death sound = "PLAYER_CLERIC_CRAZY_DEATH"; Active sound = "NONE"; Reaction time = 8; Pain chance = 50; Spawn health = 800; Speed = 25; Radius = 16; Height = 64; Mass = 100; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_telestomp mf2_pushwall mf2_mcross"; } Thing { ID = "MAGE_BOSS"; DoomEd number = 10102; Spawn state = "MAGE"; See state = "MAGE_RUN1"; Pain state = "MAGE_PAIN"; Melee state = "MAGE_ATK1"; Missile state = "MAGE_ATK1"; Crash state = "NULL"; Death state = "MAGE_DIE1"; Xdeath state = "MAGE_XDIE1"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "PLAYER_MAGE_PAIN"; Death sound = "PLAYER_MAGE_CRAZY_DEATH"; Active sound = "NONE"; Reaction time = 8; Pain chance = 50; Spawn health = 800; Speed = 25; Radius = 16; Height = 64; Mass = 100; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_telestomp mf2_pushwall mf2_mcross"; } Thing { ID = "SORCBOSS"; DoomEd number = 10080; Spawn state = "SORC_SPAWN1"; See state = "SORC_WALK1"; Pain state = "SORC_PAIN1"; Melee state = "NULL"; Missile state = "SORC_ATK2_1"; Crash state = "NULL"; Death state = "SORC_DIE1"; Xdeath state = "NULL"; See sound = "SORCERER_SIGHT"; Attack sound = "NONE"; Pain sound = "SORCERER_PAIN"; Death sound = "SORCERER_DEATHSCREAM"; Active sound = "SORCERER_ACTIVE"; Reaction time = 8; Pain chance = 10; Spawn health = 5000; Speed = 16; Radius = 40; Height = 110; Mass = 500; Damage = 9; Flags = "mf_solid mf_shootable mf_countkill mf_noblood"; Flags2 = "mf2_floorclip mf2_passmobj mf2_pushwall mf2_boss mf2_mcross"; Flags3 = "mf3_noinfight"; } Thing { ID = "SORCBALL1"; DoomEd number = -1; Spawn state = "SORCBALL1_1"; See state = "NULL"; Pain state = "SORCBALL1_D1"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SORCBALL1_D5"; Xdeath state = "NULL"; See sound = "SORCERER_BALLBOUNCE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SORCBALL2"; DoomEd number = -1; Spawn state = "SORCBALL2_1"; See state = "NULL"; Pain state = "SORCBALL2_D1"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SORCBALL2_D5"; Xdeath state = "NULL"; See sound = "SORCERER_BALLBOUNCE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SORCBALL3"; DoomEd number = -1; Spawn state = "SORCBALL3_1"; See state = "NULL"; Pain state = "SORCBALL3_D1"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SORCBALL3_D5"; Xdeath state = "NULL"; See sound = "SORCERER_BALLBOUNCE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 10; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SORCFX1"; DoomEd number = -1; Spawn state = "SORCFX1_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SORCFX1_D1"; Xdeath state = "SORCFX1_D1"; See sound = "SORCERER_BALLBOUNCE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 7; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport mf2_floorbounce"; } Thing { ID = "SORCFX2"; DoomEd number = -1; Spawn state = "SORCFX2_SPLIT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SORCFX2T1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "SORCFX2_T1"; DoomEd number = -1; Spawn state = "SORCFX2T1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_altshadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "SORCFX3"; DoomEd number = -1; Spawn state = "SORCFX3_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BISHMORPH1"; Xdeath state = "NULL"; See sound = "SORCERER_BISHOPSPAWN"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 15; Radius = 22; Height = 65; Mass = 100; Flags = "mf_noblockmap mf_missile mf_brightexplode"; Flags2 = "mf2_noteleport"; } Thing { ID = "SORCFX3_EXPLOSION"; DoomEd number = -1; Spawn state = "SORCFX3_EXP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_altshadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "SORCFX4"; DoomEd number = -1; Spawn state = "SORCFX4_1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "SORCFX4_D1"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "SORCERER_BALLEXPLODE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 12; Radius = 10; Height = 10; Mass = 100; Flags = "mf_noblockmap mf_missile mf_brightexplode mf_nogravity"; Flags2 = "mf2_noteleport"; } Thing { ID = "SORCSPARK1"; DoomEd number = -1; Spawn state = "SORCSPARK1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 5; Height = 5; Mass = 100; Flags = "mf_noblockmap mf_dropoff"; Flags2 = "mf2_noteleport mf2_lograv"; } Thing { ID = "BLASTEFFECT"; DoomEd number = -1; Spawn state = "BLASTEFFECT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_noclip mf_altshadow"; Flags2 = "mf2_noteleport"; } Thing { ID = "WATER_DRIP"; DoomEd number = -1; Spawn state = "WATERDRIP1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "DRIP"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 1; Flags = "mf_missile"; Flags2 = "mf2_lograv mf2_noteleport"; } Thing { ID = "KORAX"; DoomEd number = 10200; Spawn state = "KORAX_LOOK1"; See state = "KORAX_CHASE2"; Pain state = "KORAX_PAIN1"; Melee state = "NULL"; Missile state = "KORAX_ATTACK1"; Crash state = "NULL"; Death state = "KORAX_DEATH1"; Xdeath state = "NULL"; See sound = "KORAX_SIGHT"; Attack sound = "KORAX_ATTACK"; Pain sound = "KORAX_PAIN"; Death sound = "KORAX_DEATH"; Active sound = "KORAX_ACTIVE"; Reaction time = 8; Pain chance = 20; Spawn health = 5000; Speed = 10; Radius = 65; Height = 115; Mass = 2000; Damage = 15; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_pushwall mf2_mcross mf2_telestomp mf2_boss"; Flags3 = "mf3_noinfight"; } Thing { ID = "KORAX_SPIRIT1"; DoomEd number = -1; Spawn state = "KSPIRIT_ROAM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 8; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "KORAX_SPIRIT2"; DoomEd number = -1; Spawn state = "KSPIRIT_ROAM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 8; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "KORAX_SPIRIT3"; DoomEd number = -1; Spawn state = "KSPIRIT_ROAM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 8; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "KORAX_SPIRIT4"; DoomEd number = -1; Spawn state = "KSPIRIT_ROAM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 8; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "KORAX_SPIRIT5"; DoomEd number = -1; Spawn state = "KSPIRIT_ROAM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 8; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "KORAX_SPIRIT6"; DoomEd number = -1; Spawn state = "KSPIRIT_ROAM1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 8; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_dropoff mf_nogravity mf_altshadow mf_missile mf_noclip"; Flags2 = "mf2_noteleport"; } Thing { ID = "DEMON_MASH"; DoomEd number = -1; Spawn state = "DEMN_LOOK1"; See state = "DEMN_CHASE1"; Pain state = "DEMN_PAIN1"; Melee state = "DEMN_ATK1_1"; Missile state = "DEMN_ATK2_1"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "DEMON_SIGHT"; Attack sound = "DEMON_ATTACK"; Pain sound = "DEMON_PAIN"; Death sound = "DEMON_DEATH"; Active sound = "DEMON_ACTIVE"; Reaction time = 8; Pain chance = 50; Spawn health = 250; Speed = 13; Radius = 32; Height = 64; Mass = 220; Flags = "mf_solid mf_shootable mf_countkill mf_altshadow mf_noblood"; Flags2 = "mf2_floorclip mf2_passmobj mf2_mcross mf2_pushwall mf2_blasted"; } Thing { ID = "DEMON2_MASH"; DoomEd number = -1; Spawn state = "DEMN2_LOOK1"; See state = "DEMN2_CHASE1"; Pain state = "DEMN2_PAIN1"; Melee state = "DEMN2_ATK1_1"; Missile state = "DEMN2_ATK2_1"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "DEMON_SIGHT"; Attack sound = "DEMON_ATTACK"; Pain sound = "DEMON_PAIN"; Death sound = "DEMON_DEATH"; Active sound = "DEMON_ACTIVE"; Reaction time = 8; Pain chance = 50; Spawn health = 250; Speed = 13; Radius = 32; Height = 64; Mass = 220; Flags = "mf_solid mf_shootable mf_countkill mf_altshadow mf_noblood"; Flags2 = "mf2_floorclip mf2_passmobj mf2_mcross mf2_pushwall mf2_blasted"; } Thing { ID = "ETTIN_MASH"; DoomEd number = -1; Spawn state = "ETTIN_LOOK1"; See state = "ETTIN_CHASE1"; Pain state = "ETTIN_PAIN1"; Melee state = "ETTIN_ATK1_1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "ETTIN_SIGHT"; Attack sound = "ETTIN_ATTACK"; Pain sound = "ETTIN_PAIN"; Death sound = "ETTIN_DEATH"; Active sound = "ETTIN_ACTIVE"; Reaction time = 8; Pain chance = 60; Spawn health = 175; Speed = 13; Radius = 25; Height = 68; Mass = 175; Damage = 3; Flags = "mf_solid mf_shootable mf_countkill mf_altshadow mf_noblood"; Flags2 = "mf2_floorclip mf2_passmobj mf2_mcross mf2_pushwall mf2_blasted"; } Thing { ID = "CENTAUR_MASH"; DoomEd number = -1; Spawn state = "CENTAUR_LOOK1"; See state = "CENTAUR_WALK1"; Pain state = "CENTAUR_PAIN1"; Melee state = "CENTAUR_ATK1"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "CENTAUR_SIGHT"; Attack sound = "CENTAUR_ATTACK"; Pain sound = "CENTAUR_PAIN"; Death sound = "CENTAUR_DEATH"; Active sound = "CENTAUR_ACTIVE"; Reaction time = 8; Pain chance = 135; Spawn health = 200; Speed = 13; Radius = 20; Height = 64; Mass = 120; Flags = "mf_solid mf_shootable mf_countkill mf_altshadow mf_noblood"; Flags2 = "mf2_floorclip mf2_passmobj mf2_mcross mf2_pushwall mf2_blasted"; } Thing { ID = "KORAX_BOLT"; DoomEd number = -1; Spawn state = "KBOLT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 15; Height = 35; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_missile mf_brightexplode mf_dropoff"; Flags2 = "mf2_noteleport"; } Thing { ID = "BAT_SPAWNER"; DoomEd number = 10225; Spawn state = "SPAWNBATS1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Radius = 20; Height = 16; Mass = 100; Flags = "mf_noblockmap mf_nosector mf_nogravity"; Flags2 = "mf2_dontdraw"; } Thing { ID = "BAT"; DoomEd number = -1; Spawn state = "BAT1"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "BAT_DEATH"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 5; Radius = 3; Height = 3; Mass = 100; Flags = "mf_noblockmap mf_nogravity mf_missile"; Flags2 = "mf2_passmobj mf2_noteleport"; } Thing { ID = "CAMERA"; DoomEd number = -1; Spawn state = "CAMERA"; See state = "NULL"; Pain state = "NULL"; Melee state = "NULL"; Missile state = "NULL"; Crash state = "NULL"; Death state = "NULL"; Xdeath state = "NULL"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Reaction time = 8; Spawn health = 1000; Speed = 5; Radius = 10; Height = 10; Mass = 100; Flags = "mf_nogravity mf_nosector mf_noblockmap mf_teleport mf_dropoff"; Flags2 = "mf2_passmobj mf2_slide mf2_cannotpush mf2_dontdraw"; } State { ID = "NULL"; Sprite = "MAN1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FREETARGMOBJ"; Sprite = "ACLO"; Frame = 4; Tics = 1050; Action = "A_FreeTargMobj"; Next state = "NULL"; } State { ID = "MAPSPOT"; Sprite = "TLGL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FIREBALL1_1"; Sprite = "FBL1"; Frame = 32768; Tics = 4; Next state = "FIREBALL1_2"; } State { ID = "FIREBALL1_2"; Sprite = "FBL1"; Frame = 32769; Tics = 4; Next state = "FIREBALL1_1"; } State { ID = "FIREBALL1_X1"; Sprite = "XPL1"; Frame = 32768; Tics = 4; Next state = "FIREBALL1_X2"; } State { ID = "FIREBALL1_X2"; Sprite = "XPL1"; Frame = 32769; Tics = 4; Next state = "FIREBALL1_X3"; } State { ID = "FIREBALL1_X3"; Sprite = "XPL1"; Frame = 32770; Tics = 4; Next state = "FIREBALL1_X4"; } State { ID = "FIREBALL1_X4"; Sprite = "XPL1"; Frame = 32771; Tics = 4; Next state = "FIREBALL1_X5"; } State { ID = "FIREBALL1_X5"; Sprite = "XPL1"; Frame = 32772; Tics = 4; Next state = "FIREBALL1_X6"; } State { ID = "FIREBALL1_X6"; Sprite = "XPL1"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "ARROW_1"; Sprite = "ARRW"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARROW_X1"; Sprite = "ARRW"; Frame = 0; Tics = 1; Next state = "NULL"; } State { ID = "DART_1"; Sprite = "DART"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DART_X1"; Sprite = "DART"; Frame = 0; Tics = 1; Next state = "NULL"; } State { ID = "POISONDART_1"; Sprite = "DART"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "POISONDART_X1"; Sprite = "DART"; Frame = 0; Tics = 1; Next state = "NULL"; } State { ID = "RIPPERBALL_1"; Sprite = "RIPP"; Frame = 0; Tics = 3; Next state = "RIPPERBALL_2"; } State { ID = "RIPPERBALL_2"; Sprite = "RIPP"; Frame = 1; Tics = 3; Next state = "RIPPERBALL_3"; } State { ID = "RIPPERBALL_3"; Sprite = "RIPP"; Frame = 2; Tics = 3; Next state = "RIPPERBALL_1"; } State { ID = "RIPPERBALL_X1"; Sprite = "CFCF"; Frame = 32784; Tics = 4; Next state = "RIPPERBALL_X2"; } State { ID = "RIPPERBALL_X2"; Sprite = "CFCF"; Frame = 32785; Tics = 3; Next state = "RIPPERBALL_X3"; } State { ID = "RIPPERBALL_X3"; Sprite = "CFCF"; Frame = 32786; Tics = 4; Next state = "RIPPERBALL_X4"; } State { ID = "RIPPERBALL_X4"; Sprite = "CFCF"; Frame = 32787; Tics = 3; Next state = "RIPPERBALL_X5"; } State { ID = "RIPPERBALL_X5"; Sprite = "CFCF"; Frame = 32788; Tics = 4; Next state = "RIPPERBALL_X6"; } State { ID = "RIPPERBALL_X6"; Sprite = "CFCF"; Frame = 32789; Tics = 3; Next state = "RIPPERBALL_X7"; } State { ID = "RIPPERBALL_X7"; Sprite = "CFCF"; Frame = 32790; Tics = 4; Next state = "RIPPERBALL_X8"; } State { ID = "RIPPERBALL_X8"; Sprite = "CFCF"; Frame = 32791; Tics = 3; Next state = "RIPPERBALL_X9"; } State { ID = "RIPPERBALL_X9"; Sprite = "CFCF"; Frame = 32792; Tics = 4; Next state = "RIPPERBALL_X10"; } State { ID = "RIPPERBALL_X10"; Sprite = "CFCF"; Frame = 32793; Tics = 3; Next state = "NULL"; } State { ID = "PRJ_BLADE1"; Sprite = "BLAD"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PRJ_BLADE_X1"; Sprite = "BLAD"; Frame = 0; Tics = 1; Next state = "NULL"; } State { ID = "ICESHARD1"; Sprite = "SHRD"; Frame = 32768; Tics = 3; Next state = "ICESHARD2"; } State { ID = "ICESHARD2"; Sprite = "SHRD"; Frame = 32769; Tics = 3; Next state = "ICESHARD3"; } State { ID = "ICESHARD3"; Sprite = "SHRD"; Frame = 32770; Tics = 3; Next state = "ICESHARD1"; } State { ID = "FLAME_TSMALL1"; Sprite = "FFSM"; Frame = 32768; Tics = 3; Next state = "FLAME_TSMALL2"; } State { ID = "FLAME_TSMALL2"; Sprite = "FFSM"; Frame = 32769; Tics = 3; Next state = "FLAME_TSMALL3"; } State { ID = "FLAME_TSMALL3"; Sprite = "FFSM"; Frame = 32770; Tics = 2; Action = "A_FlameCheck"; Next state = "FLAME_TSMALL4"; } State { ID = "FLAME_TSMALL4"; Sprite = "FFSM"; Frame = 32770; Tics = 2; Next state = "FLAME_TSMALL5"; } State { ID = "FLAME_TSMALL5"; Sprite = "FFSM"; Frame = 32771; Tics = 3; Next state = "FLAME_TSMALL6"; } State { ID = "FLAME_TSMALL6"; Sprite = "FFSM"; Frame = 32772; Tics = 3; Action = "A_FlameCheck"; Next state = "FLAME_TSMALL1"; } State { ID = "FLAME_TLARGE1"; Sprite = "FFLG"; Frame = 32768; Tics = 4; Next state = "FLAME_TLARGE2"; } State { ID = "FLAME_TLARGE2"; Sprite = "FFLG"; Frame = 32769; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE3"; } State { ID = "FLAME_TLARGE3"; Sprite = "FFLG"; Frame = 32770; Tics = 4; Next state = "FLAME_TLARGE4"; } State { ID = "FLAME_TLARGE4"; Sprite = "FFLG"; Frame = 32771; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE5"; } State { ID = "FLAME_TLARGE5"; Sprite = "FFLG"; Frame = 32772; Tics = 4; Next state = "FLAME_TLARGE6"; } State { ID = "FLAME_TLARGE6"; Sprite = "FFLG"; Frame = 32773; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE7"; } State { ID = "FLAME_TLARGE7"; Sprite = "FFLG"; Frame = 32774; Tics = 4; Next state = "FLAME_TLARGE8"; } State { ID = "FLAME_TLARGE8"; Sprite = "FFLG"; Frame = 32775; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE9"; } State { ID = "FLAME_TLARGE9"; Sprite = "FFLG"; Frame = 32776; Tics = 4; Next state = "FLAME_TLARGE10"; } State { ID = "FLAME_TLARGE10"; Sprite = "FFLG"; Frame = 32777; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE11"; } State { ID = "FLAME_TLARGE11"; Sprite = "FFLG"; Frame = 32778; Tics = 4; Next state = "FLAME_TLARGE12"; } State { ID = "FLAME_TLARGE12"; Sprite = "FFLG"; Frame = 32779; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE13"; } State { ID = "FLAME_TLARGE13"; Sprite = "FFLG"; Frame = 32780; Tics = 4; Next state = "FLAME_TLARGE14"; } State { ID = "FLAME_TLARGE14"; Sprite = "FFLG"; Frame = 32781; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE15"; } State { ID = "FLAME_TLARGE15"; Sprite = "FFLG"; Frame = 32782; Tics = 4; Next state = "FLAME_TLARGE16"; } State { ID = "FLAME_TLARGE16"; Sprite = "FFLG"; Frame = 32783; Tics = 4; Action = "A_FlameCheck"; Next state = "FLAME_TLARGE5"; } State { ID = "FLAME_SDORM1"; Sprite = "FFSM"; Frame = 0; Tics = 2; Next state = "FLAME_SDORM2"; } State { ID = "FLAME_SDORM2"; Sprite = "FFSM"; Frame = 1; Tics = 2; Action = "A_HideThing"; Next state = "FLAME_SDORM3"; } State { ID = "FLAME_SDORM3"; Sprite = "FFSM"; Frame = 2; Tics = 200; Next state = "FLAME_SDORM3"; } State { ID = "FLAME_SMALL1"; Sprite = "FFSM"; Frame = 32768; Tics = 3; Next state = "FLAME_SMALL2"; } State { ID = "FLAME_SMALL2"; Sprite = "FFSM"; Frame = 32768; Tics = 3; Action = "A_UnHideThing"; Next state = "FLAME_SMALL3"; } State { ID = "FLAME_SMALL3"; Sprite = "FFSM"; Frame = 32768; Tics = 3; Next state = "FLAME_SMALL4"; } State { ID = "FLAME_SMALL4"; Sprite = "FFSM"; Frame = 32769; Tics = 3; Next state = "FLAME_SMALL5"; } State { ID = "FLAME_SMALL5"; Sprite = "FFSM"; Frame = 32770; Tics = 3; Next state = "FLAME_SMALL6"; } State { ID = "FLAME_SMALL6"; Sprite = "FFSM"; Frame = 32771; Tics = 3; Next state = "FLAME_SMALL7"; } State { ID = "FLAME_SMALL7"; Sprite = "FFSM"; Frame = 32772; Tics = 3; Next state = "FLAME_SMALL3"; } State { ID = "FLAME_LDORM1"; Sprite = "FFLG"; Frame = 3; Tics = 2; Next state = "FLAME_LDORM2"; } State { ID = "FLAME_LDORM2"; Sprite = "FFLG"; Frame = 2; Tics = 2; Next state = "FLAME_LDORM3"; } State { ID = "FLAME_LDORM3"; Sprite = "FFLG"; Frame = 1; Tics = 2; Next state = "FLAME_LDORM4"; } State { ID = "FLAME_LDORM4"; Sprite = "FFLG"; Frame = 0; Tics = 2; Action = "A_HideThing"; Next state = "FLAME_LDORM5"; } State { ID = "FLAME_LDORM5"; Sprite = "FFLG"; Frame = 0; Tics = 200; Next state = "FLAME_LDORM5"; } State { ID = "FLAME_LARGE1"; Sprite = "FFLG"; Frame = 32768; Tics = 2; Next state = "FLAME_LARGE2"; } State { ID = "FLAME_LARGE2"; Sprite = "FFLG"; Frame = 32768; Tics = 2; Action = "A_UnHideThing"; Next state = "FLAME_LARGE3"; } State { ID = "FLAME_LARGE3"; Sprite = "FFLG"; Frame = 32768; Tics = 4; Next state = "FLAME_LARGE4"; } State { ID = "FLAME_LARGE4"; Sprite = "FFLG"; Frame = 32769; Tics = 4; Next state = "FLAME_LARGE5"; } State { ID = "FLAME_LARGE5"; Sprite = "FFLG"; Frame = 32770; Tics = 4; Next state = "FLAME_LARGE6"; } State { ID = "FLAME_LARGE6"; Sprite = "FFLG"; Frame = 32771; Tics = 4; Next state = "FLAME_LARGE7"; } State { ID = "FLAME_LARGE7"; Sprite = "FFLG"; Frame = 32772; Tics = 4; Next state = "FLAME_LARGE8"; } State { ID = "FLAME_LARGE8"; Sprite = "FFLG"; Frame = 32773; Tics = 4; Next state = "FLAME_LARGE9"; } State { ID = "FLAME_LARGE9"; Sprite = "FFLG"; Frame = 32774; Tics = 4; Next state = "FLAME_LARGE10"; } State { ID = "FLAME_LARGE10"; Sprite = "FFLG"; Frame = 32775; Tics = 4; Next state = "FLAME_LARGE11"; } State { ID = "FLAME_LARGE11"; Sprite = "FFLG"; Frame = 32776; Tics = 4; Next state = "FLAME_LARGE12"; } State { ID = "FLAME_LARGE12"; Sprite = "FFLG"; Frame = 32777; Tics = 4; Next state = "FLAME_LARGE13"; } State { ID = "FLAME_LARGE13"; Sprite = "FFLG"; Frame = 32778; Tics = 4; Next state = "FLAME_LARGE14"; } State { ID = "FLAME_LARGE14"; Sprite = "FFLG"; Frame = 32779; Tics = 4; Next state = "FLAME_LARGE15"; } State { ID = "FLAME_LARGE15"; Sprite = "FFLG"; Frame = 32780; Tics = 4; Next state = "FLAME_LARGE16"; } State { ID = "FLAME_LARGE16"; Sprite = "FFLG"; Frame = 32781; Tics = 4; Next state = "FLAME_LARGE17"; } State { ID = "FLAME_LARGE17"; Sprite = "FFLG"; Frame = 32782; Tics = 4; Next state = "FLAME_LARGE18"; } State { ID = "FLAME_LARGE18"; Sprite = "FFLG"; Frame = 32783; Tics = 4; Next state = "FLAME_LARGE7"; } State { ID = "ITEM_PTN1_1"; Sprite = "PTN1"; Frame = 0; Tics = 3; Next state = "ITEM_PTN1_2"; } State { ID = "ITEM_PTN1_2"; Sprite = "PTN1"; Frame = 1; Tics = 3; Next state = "ITEM_PTN1_3"; } State { ID = "ITEM_PTN1_3"; Sprite = "PTN1"; Frame = 2; Tics = 3; Next state = "ITEM_PTN1_1"; } State { ID = "HIDESPECIAL1"; Sprite = "ACLO"; Frame = 4; Tics = 1400; Next state = "HIDESPECIAL2"; } State { ID = "HIDESPECIAL2"; Sprite = "ACLO"; Frame = 0; Tics = 4; Action = "A_RestoreSpecialThing1"; Next state = "HIDESPECIAL3"; } State { ID = "HIDESPECIAL3"; Sprite = "ACLO"; Frame = 1; Tics = 4; Next state = "HIDESPECIAL4"; } State { ID = "HIDESPECIAL4"; Sprite = "ACLO"; Frame = 0; Tics = 4; Next state = "HIDESPECIAL5"; } State { ID = "HIDESPECIAL5"; Sprite = "ACLO"; Frame = 1; Tics = 4; Next state = "HIDESPECIAL6"; } State { ID = "HIDESPECIAL6"; Sprite = "ACLO"; Frame = 2; Tics = 4; Next state = "HIDESPECIAL7"; } State { ID = "HIDESPECIAL7"; Sprite = "ACLO"; Frame = 1; Tics = 4; Next state = "HIDESPECIAL8"; } State { ID = "HIDESPECIAL8"; Sprite = "ACLO"; Frame = 2; Tics = 4; Next state = "HIDESPECIAL9"; } State { ID = "HIDESPECIAL9"; Sprite = "ACLO"; Frame = 3; Tics = 4; Next state = "HIDESPECIAL10"; } State { ID = "HIDESPECIAL10"; Sprite = "ACLO"; Frame = 2; Tics = 4; Next state = "HIDESPECIAL11"; } State { ID = "HIDESPECIAL11"; Sprite = "ACLO"; Frame = 3; Tics = 4; Action = "A_RestoreSpecialThing2"; Next state = "NULL"; } State { ID = "DORMANTARTI1_1"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI1_2"; } State { ID = "DORMANTARTI1_2"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI1_3"; } State { ID = "DORMANTARTI1_3"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI1_4"; } State { ID = "DORMANTARTI1_4"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI1_5"; } State { ID = "DORMANTARTI1_5"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI1_6"; } State { ID = "DORMANTARTI1_6"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI1_7"; } State { ID = "DORMANTARTI1_7"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI1_8"; } State { ID = "DORMANTARTI1_8"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI1_9"; } State { ID = "DORMANTARTI1_9"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI1_10"; } State { ID = "DORMANTARTI1_10"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI1_11"; } State { ID = "DORMANTARTI1_11"; Sprite = "ACLO"; Frame = 0; Tics = 1400; Action = "A_HideThing"; Next state = "DORMANTARTI1_12"; } State { ID = "DORMANTARTI1_12"; Sprite = "ACLO"; Frame = 0; Tics = 3; Action = "A_UnHideThing"; Next state = "DORMANTARTI1_13"; } State { ID = "DORMANTARTI1_13"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI1_14"; } State { ID = "DORMANTARTI1_14"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI1_15"; } State { ID = "DORMANTARTI1_15"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI1_16"; } State { ID = "DORMANTARTI1_16"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI1_17"; } State { ID = "DORMANTARTI1_17"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI1_18"; } State { ID = "DORMANTARTI1_18"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI1_19"; } State { ID = "DORMANTARTI1_19"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI1_20"; } State { ID = "DORMANTARTI1_20"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI1_21"; } State { ID = "DORMANTARTI1_21"; Sprite = "ACLO"; Frame = 3; Tics = 3; Action = "A_RestoreArtifact"; Next state = "NULL"; } State { ID = "DORMANTARTI2_1"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI2_2"; } State { ID = "DORMANTARTI2_2"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI2_3"; } State { ID = "DORMANTARTI2_3"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI2_4"; } State { ID = "DORMANTARTI2_4"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI2_5"; } State { ID = "DORMANTARTI2_5"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI2_6"; } State { ID = "DORMANTARTI2_6"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI2_7"; } State { ID = "DORMANTARTI2_7"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI2_8"; } State { ID = "DORMANTARTI2_8"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI2_9"; } State { ID = "DORMANTARTI2_9"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI2_10"; } State { ID = "DORMANTARTI2_10"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI2_11"; } State { ID = "DORMANTARTI2_11"; Sprite = "ACLO"; Frame = 0; Tics = 4200; Action = "A_HideThing"; Next state = "DORMANTARTI2_12"; } State { ID = "DORMANTARTI2_12"; Sprite = "ACLO"; Frame = 0; Tics = 3; Action = "A_UnHideThing"; Next state = "DORMANTARTI2_13"; } State { ID = "DORMANTARTI2_13"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI2_14"; } State { ID = "DORMANTARTI2_14"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI2_15"; } State { ID = "DORMANTARTI2_15"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI2_16"; } State { ID = "DORMANTARTI2_16"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI2_17"; } State { ID = "DORMANTARTI2_17"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI2_18"; } State { ID = "DORMANTARTI2_18"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI2_19"; } State { ID = "DORMANTARTI2_19"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI2_20"; } State { ID = "DORMANTARTI2_20"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI2_21"; } State { ID = "DORMANTARTI2_21"; Sprite = "ACLO"; Frame = 3; Tics = 3; Action = "A_RestoreArtifact"; Next state = "NULL"; } State { ID = "DORMANTARTI3_1"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI3_2"; } State { ID = "DORMANTARTI3_2"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI3_3"; } State { ID = "DORMANTARTI3_3"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI3_4"; } State { ID = "DORMANTARTI3_4"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI3_5"; } State { ID = "DORMANTARTI3_5"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI3_6"; } State { ID = "DORMANTARTI3_6"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI3_7"; } State { ID = "DORMANTARTI3_7"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI3_8"; } State { ID = "DORMANTARTI3_8"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI3_9"; } State { ID = "DORMANTARTI3_9"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI3_10"; } State { ID = "DORMANTARTI3_10"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI3_11"; } State { ID = "DORMANTARTI3_11"; Sprite = "ACLO"; Frame = 0; Tics = 21000; Action = "A_HideThing"; Next state = "DORMANTARTI3_12"; } State { ID = "DORMANTARTI3_12"; Sprite = "ACLO"; Frame = 0; Tics = 3; Action = "A_UnHideThing"; Next state = "DORMANTARTI3_13"; } State { ID = "DORMANTARTI3_13"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI3_14"; } State { ID = "DORMANTARTI3_14"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DORMANTARTI3_15"; } State { ID = "DORMANTARTI3_15"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI3_16"; } State { ID = "DORMANTARTI3_16"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI3_17"; } State { ID = "DORMANTARTI3_17"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DORMANTARTI3_18"; } State { ID = "DORMANTARTI3_18"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI3_19"; } State { ID = "DORMANTARTI3_19"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DORMANTARTI3_20"; } State { ID = "DORMANTARTI3_20"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DORMANTARTI3_21"; } State { ID = "DORMANTARTI3_21"; Sprite = "ACLO"; Frame = 3; Tics = 3; Action = "A_RestoreArtifact"; Next state = "NULL"; } State { ID = "DEADARTI1"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DEADARTI2"; } State { ID = "DEADARTI2"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DEADARTI3"; } State { ID = "DEADARTI3"; Sprite = "ACLO"; Frame = 3; Tics = 3; Next state = "DEADARTI4"; } State { ID = "DEADARTI4"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DEADARTI5"; } State { ID = "DEADARTI5"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DEADARTI6"; } State { ID = "DEADARTI6"; Sprite = "ACLO"; Frame = 2; Tics = 3; Next state = "DEADARTI7"; } State { ID = "DEADARTI7"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DEADARTI8"; } State { ID = "DEADARTI8"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "DEADARTI9"; } State { ID = "DEADARTI9"; Sprite = "ACLO"; Frame = 1; Tics = 3; Next state = "DEADARTI10"; } State { ID = "DEADARTI10"; Sprite = "ACLO"; Frame = 0; Tics = 3; Next state = "NULL"; } State { ID = "ARTI_PTN2_1"; Sprite = "PTN2"; Frame = 0; Tics = 4; Next state = "ARTI_PTN2_2"; } State { ID = "ARTI_PTN2_2"; Sprite = "PTN2"; Frame = 1; Tics = 4; Next state = "ARTI_PTN2_3"; } State { ID = "ARTI_PTN2_3"; Sprite = "PTN2"; Frame = 2; Tics = 4; Next state = "ARTI_PTN2_1"; } State { ID = "ARTI_SOAR1"; Sprite = "SOAR"; Frame = 0; Tics = 5; Next state = "ARTI_SOAR2"; } State { ID = "ARTI_SOAR2"; Sprite = "SOAR"; Frame = 1; Tics = 5; Next state = "ARTI_SOAR3"; } State { ID = "ARTI_SOAR3"; Sprite = "SOAR"; Frame = 2; Tics = 5; Next state = "ARTI_SOAR4"; } State { ID = "ARTI_SOAR4"; Sprite = "SOAR"; Frame = 1; Tics = 5; Next state = "ARTI_SOAR1"; } State { ID = "ARTI_INVU1"; Sprite = "INVU"; Frame = 0x8000; Tics = 3; Next state = "ARTI_INVU2"; } State { ID = "ARTI_INVU2"; Sprite = "INVU"; Frame = 0x8001; Tics = 3; Next state = "ARTI_INVU3"; } State { ID = "ARTI_INVU3"; Sprite = "INVU"; Frame = 0x8002; Tics = 3; Next state = "ARTI_INVU4"; } State { ID = "ARTI_INVU4"; Sprite = "INVU"; Frame = 0x8003; Tics = 3; Next state = "ARTI_INVU1"; } State { ID = "ARTI_SUMMON"; Sprite = "SUMN"; Frame = 0; Tics = 350; Next state = "ARTI_SUMMON"; } State { ID = "SUMMON_FX1_1"; Sprite = "SUMN"; Frame = 0; Tics = 4; Next state = "SUMMON_FX1_1"; } State { ID = "SUMMON_FX2_1"; Sprite = "SUMN"; Frame = 0; Tics = 4; Next state = "SUMMON_FX2_2"; } State { ID = "SUMMON_FX2_2"; Sprite = "SUMN"; Frame = 0; Tics = 4; Next state = "SUMMON_FX2_3"; } State { ID = "SUMMON_FX2_3"; Sprite = "SUMN"; Frame = 0; Tics = 4; Action = "A_Summon"; Next state = "NULL"; } State { ID = "THRUSTINIT2_1"; Sprite = "TSPK"; Frame = 0; Tics = 3; Next state = "THRUSTINIT2_2"; } State { ID = "THRUSTINIT2_2"; Sprite = "TSPK"; Frame = 0; Tics = 4; Action = "A_ThrustInitUp"; Next state = "THRUSTBLOCK"; } State { ID = "BTHRUSTINIT2_1"; Sprite = "TSPK"; Frame = 1; Tics = 3; Next state = "BTHRUSTINIT2_2"; } State { ID = "BTHRUSTINIT2_2"; Sprite = "TSPK"; Frame = 1; Tics = 4; Action = "A_ThrustInitUp"; Next state = "BTHRUSTBLOCK"; } State { ID = "THRUSTINIT1_1"; Sprite = "TSPK"; Frame = 0; Tics = 3; Next state = "THRUSTINIT1_2"; } State { ID = "THRUSTINIT1_2"; Sprite = "TSPK"; Frame = 0; Tics = 4; Action = "A_ThrustInitDn"; Next state = "THRUSTSTAY"; } State { ID = "BTHRUSTINIT1_1"; Sprite = "TSPK"; Frame = 1; Tics = 3; Next state = "BTHRUSTINIT1_2"; } State { ID = "BTHRUSTINIT1_2"; Sprite = "TSPK"; Frame = 1; Tics = 4; Action = "A_ThrustInitDn"; Next state = "BTHRUSTSTAY"; } State { ID = "THRUSTRAISE1"; Sprite = "TSPK"; Frame = 0; Tics = 8; Action = "A_ThrustRaise"; Next state = "THRUSTRAISE2"; } State { ID = "THRUSTRAISE2"; Sprite = "TSPK"; Frame = 0; Tics = 6; Action = "A_ThrustRaise"; Next state = "THRUSTRAISE3"; } State { ID = "THRUSTRAISE3"; Sprite = "TSPK"; Frame = 0; Tics = 4; Action = "A_ThrustRaise"; Next state = "THRUSTRAISE4"; } State { ID = "THRUSTRAISE4"; Sprite = "TSPK"; Frame = 0; Tics = 3; Action = "A_ThrustBlock"; Next state = "THRUSTIMPALE"; } State { ID = "BTHRUSTRAISE1"; Sprite = "TSPK"; Frame = 1; Tics = 8; Action = "A_ThrustRaise"; Next state = "BTHRUSTRAISE2"; } State { ID = "BTHRUSTRAISE2"; Sprite = "TSPK"; Frame = 1; Tics = 6; Action = "A_ThrustRaise"; Next state = "BTHRUSTRAISE3"; } State { ID = "BTHRUSTRAISE3"; Sprite = "TSPK"; Frame = 1; Tics = 4; Action = "A_ThrustRaise"; Next state = "BTHRUSTRAISE4"; } State { ID = "BTHRUSTRAISE4"; Sprite = "TSPK"; Frame = 1; Tics = 3; Action = "A_ThrustBlock"; Next state = "BTHRUSTIMPALE"; } State { ID = "THRUSTIMPALE"; Sprite = "TSPK"; Frame = 0; Tics = 2; Action = "A_ThrustImpale"; Next state = "THRUSTRAISE"; } State { ID = "BTHRUSTIMPALE"; Sprite = "TSPK"; Frame = 1; Tics = 2; Action = "A_ThrustImpale"; Next state = "BTHRUSTRAISE"; } State { ID = "THRUSTRAISE"; Sprite = "TSPK"; Frame = 0; Tics = 2; Action = "A_ThrustRaise"; Next state = "THRUSTRAISE"; } State { ID = "BTHRUSTRAISE"; Sprite = "TSPK"; Frame = 1; Tics = 2; Action = "A_ThrustRaise"; Next state = "BTHRUSTRAISE"; } State { ID = "THRUSTBLOCK"; Sprite = "TSPK"; Frame = 0; Tics = 10; Next state = "THRUSTBLOCK"; } State { ID = "BTHRUSTBLOCK"; Sprite = "TSPK"; Frame = 1; Tics = 10; Next state = "BTHRUSTBLOCK"; } State { ID = "THRUSTLOWER"; Sprite = "TSPK"; Frame = 0; Tics = 2; Action = "A_ThrustLower"; Next state = "THRUSTLOWER"; } State { ID = "BTHRUSTLOWER"; Sprite = "TSPK"; Frame = 1; Tics = 2; Action = "A_ThrustLower"; Next state = "BTHRUSTLOWER"; } State { ID = "THRUSTSTAY"; Sprite = "TSPK"; Frame = 0; Tics = -1; Next state = "THRUSTSTAY"; } State { ID = "BTHRUSTSTAY"; Sprite = "TSPK"; Frame = 1; Tics = -1; Next state = "BTHRUSTSTAY"; } State { ID = "ARTI_TELOTHER1"; Sprite = "TELO"; Frame = 0; Tics = 5; Next state = "ARTI_TELOTHER2"; } State { ID = "ARTI_TELOTHER2"; Sprite = "TELO"; Frame = 1; Tics = 5; Next state = "ARTI_TELOTHER3"; } State { ID = "ARTI_TELOTHER3"; Sprite = "TELO"; Frame = 2; Tics = 5; Next state = "ARTI_TELOTHER4"; } State { ID = "ARTI_TELOTHER4"; Sprite = "TELO"; Frame = 3; Tics = 5; Next state = "ARTI_TELOTHER1"; } State { ID = "TELO_FX1"; Sprite = "TRNG"; Frame = 32772; Tics = 5; Next state = "TELO_FX2"; } State { ID = "TELO_FX2"; Sprite = "TRNG"; Frame = 32771; Tics = 4; Next state = "TELO_FX3"; } State { ID = "TELO_FX3"; Sprite = "TRNG"; Frame = 32770; Tics = 3; Action = "A_TeloSpawnC"; Next state = "TELO_FX4"; } State { ID = "TELO_FX4"; Sprite = "TRNG"; Frame = 32769; Tics = 3; Action = "A_TeloSpawnB"; Next state = "TELO_FX5"; } State { ID = "TELO_FX5"; Sprite = "TRNG"; Frame = 32768; Tics = 3; Action = "A_TeloSpawnA"; Next state = "TELO_FX6"; } State { ID = "TELO_FX6"; Sprite = "TRNG"; Frame = 32769; Tics = 3; Action = "A_TeloSpawnB"; Next state = "TELO_FX7"; } State { ID = "TELO_FX7"; Sprite = "TRNG"; Frame = 32770; Tics = 3; Action = "A_TeloSpawnC"; Next state = "TELO_FX8"; } State { ID = "TELO_FX8"; Sprite = "TRNG"; Frame = 32771; Tics = 3; Action = "A_TeloSpawnD"; Next state = "TELO_FX3"; } State { ID = "TELO_FX9"; Sprite = "TRNG"; Frame = 32772; Tics = 3; Next state = "NULL"; } State { ID = "TELO_FX2_1"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Next state = "TELO_FX2_2"; } State { ID = "TELO_FX2_2"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Next state = "TELO_FX2_3"; } State { ID = "TELO_FX2_3"; Sprite = "TRNG"; Frame = 32771; Tics = 4; Next state = "TELO_FX2_4"; } State { ID = "TELO_FX2_4"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Next state = "TELO_FX2_5"; } State { ID = "TELO_FX2_5"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Next state = "TELO_FX2_6"; } State { ID = "TELO_FX2_6"; Sprite = "TRNG"; Frame = 32768; Tics = 4; Action = "A_CheckTeleRing"; Next state = "TELO_FX2_1"; } State { ID = "TELO_FX3_1"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Next state = "TELO_FX3_2"; } State { ID = "TELO_FX3_2"; Sprite = "TRNG"; Frame = 32771; Tics = 4; Next state = "TELO_FX3_3"; } State { ID = "TELO_FX3_3"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Next state = "TELO_FX3_4"; } State { ID = "TELO_FX3_4"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Next state = "TELO_FX3_5"; } State { ID = "TELO_FX3_5"; Sprite = "TRNG"; Frame = 32768; Tics = 4; Next state = "TELO_FX3_6"; } State { ID = "TELO_FX3_6"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Action = "A_CheckTeleRing"; Next state = "TELO_FX3_1"; } State { ID = "TELO_FX4_1"; Sprite = "TRNG"; Frame = 32771; Tics = 4; Next state = "TELO_FX4_2"; } State { ID = "TELO_FX4_2"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Next state = "TELO_FX4_3"; } State { ID = "TELO_FX4_3"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Next state = "TELO_FX4_4"; } State { ID = "TELO_FX4_4"; Sprite = "TRNG"; Frame = 32768; Tics = 4; Next state = "TELO_FX4_5"; } State { ID = "TELO_FX4_5"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Next state = "TELO_FX4_6"; } State { ID = "TELO_FX4_6"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Action = "A_CheckTeleRing"; Next state = "TELO_FX4_1"; } State { ID = "TELO_FX5_1"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Next state = "TELO_FX5_2"; } State { ID = "TELO_FX5_2"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Next state = "TELO_FX5_3"; } State { ID = "TELO_FX5_3"; Sprite = "TRNG"; Frame = 32768; Tics = 4; Next state = "TELO_FX5_4"; } State { ID = "TELO_FX5_4"; Sprite = "TRNG"; Frame = 32769; Tics = 4; Next state = "TELO_FX5_5"; } State { ID = "TELO_FX5_5"; Sprite = "TRNG"; Frame = 32770; Tics = 4; Next state = "TELO_FX5_6"; } State { ID = "TELO_FX5_6"; Sprite = "TRNG"; Frame = 32771; Tics = 4; Action = "A_CheckTeleRing"; Next state = "TELO_FX5_1"; } State { ID = "DIRT1_1"; Sprite = "ROCK"; Frame = 3; Tics = 20; Next state = "DIRT1_1"; } State { ID = "DIRT1_D"; Sprite = "ROCK"; Frame = 3; Tics = 10; Next state = "NULL"; } State { ID = "DIRT2_1"; Sprite = "ROCK"; Frame = 4; Tics = 20; Next state = "DIRT2_1"; } State { ID = "DIRT2_D"; Sprite = "ROCK"; Frame = 4; Tics = 10; Next state = "NULL"; } State { ID = "DIRT3_1"; Sprite = "ROCK"; Frame = 5; Tics = 20; Next state = "DIRT3_1"; } State { ID = "DIRT3_D"; Sprite = "ROCK"; Frame = 5; Tics = 10; Next state = "NULL"; } State { ID = "DIRT4_1"; Sprite = "ROCK"; Frame = 6; Tics = 20; Next state = "DIRT4_1"; } State { ID = "DIRT4_D"; Sprite = "ROCK"; Frame = 6; Tics = 10; Next state = "NULL"; } State { ID = "DIRT5_1"; Sprite = "ROCK"; Frame = 7; Tics = 20; Next state = "DIRT5_1"; } State { ID = "DIRT5_D"; Sprite = "ROCK"; Frame = 7; Tics = 10; Next state = "NULL"; } State { ID = "DIRT6_1"; Sprite = "ROCK"; Frame = 8; Tics = 20; Next state = "DIRT6_1"; } State { ID = "DIRT6_D"; Sprite = "ROCK"; Frame = 8; Tics = 10; Next state = "NULL"; } State { ID = "DIRTCLUMP1"; Sprite = "TSPK"; Frame = 2; Tics = 20; Next state = "DIRTCLUMP1"; } State { ID = "ROCK1_1"; Sprite = "ROCK"; Frame = 0; Tics = 20; Next state = "ROCK1_1"; } State { ID = "ROCK1_D"; Sprite = "ROCK"; Frame = 0; Tics = 10; Next state = "NULL"; } State { ID = "ROCK2_1"; Sprite = "ROCK"; Frame = 1; Tics = 20; Next state = "ROCK2_1"; } State { ID = "ROCK2_D"; Sprite = "ROCK"; Frame = 1; Tics = 10; Next state = "NULL"; } State { ID = "ROCK3_1"; Sprite = "ROCK"; Frame = 2; Tics = 20; Next state = "ROCK3_1"; } State { ID = "ROCK3_D"; Sprite = "ROCK"; Frame = 2; Tics = 10; Next state = "NULL"; } State { ID = "SPAWNFOG1"; Sprite = "MAN1"; Frame = 0; Tics = 20; Action = "A_FogSpawn"; Next state = "SPAWNFOG1"; } State { ID = "FOGPATCHS1"; Sprite = "FOGS"; Frame = 0; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHS2"; } State { ID = "FOGPATCHS2"; Sprite = "FOGS"; Frame = 1; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHS3"; } State { ID = "FOGPATCHS3"; Sprite = "FOGS"; Frame = 2; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHS4"; } State { ID = "FOGPATCHS4"; Sprite = "FOGS"; Frame = 3; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHS5"; } State { ID = "FOGPATCHS5"; Sprite = "FOGS"; Frame = 4; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHS1"; } State { ID = "FOGPATCHS0"; Sprite = "FOGS"; Frame = 4; Tics = 5; Next state = "NULL"; } State { ID = "FOGPATCHM1"; Sprite = "FOGM"; Frame = 0; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHM2"; } State { ID = "FOGPATCHM2"; Sprite = "FOGM"; Frame = 1; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHM3"; } State { ID = "FOGPATCHM3"; Sprite = "FOGM"; Frame = 2; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHM4"; } State { ID = "FOGPATCHM4"; Sprite = "FOGM"; Frame = 3; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHM5"; } State { ID = "FOGPATCHM5"; Sprite = "FOGM"; Frame = 4; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHM1"; } State { ID = "FOGPATCHM0"; Sprite = "FOGS"; Frame = 0; Tics = 5; Next state = "FOGPATCHMA"; } State { ID = "FOGPATCHMA"; Sprite = "FOGS"; Frame = 1; Tics = 5; Next state = "FOGPATCHMB"; } State { ID = "FOGPATCHMB"; Sprite = "FOGS"; Frame = 2; Tics = 5; Next state = "FOGPATCHMC"; } State { ID = "FOGPATCHMC"; Sprite = "FOGS"; Frame = 3; Tics = 5; Next state = "FOGPATCHMD"; } State { ID = "FOGPATCHMD"; Sprite = "FOGS"; Frame = 4; Tics = 5; Next state = "FOGPATCHS0"; } State { ID = "FOGPATCHL1"; Sprite = "FOGL"; Frame = 0; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHL2"; } State { ID = "FOGPATCHL2"; Sprite = "FOGL"; Frame = 1; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHL3"; } State { ID = "FOGPATCHL3"; Sprite = "FOGL"; Frame = 2; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHL4"; } State { ID = "FOGPATCHL4"; Sprite = "FOGL"; Frame = 3; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHL5"; } State { ID = "FOGPATCHL5"; Sprite = "FOGL"; Frame = 4; Tics = 7; Action = "A_FogMove"; Next state = "FOGPATCHL1"; } State { ID = "FOGPATCHL0"; Sprite = "FOGM"; Frame = 0; Tics = 4; Next state = "FOGPATCHLA"; } State { ID = "FOGPATCHLA"; Sprite = "FOGM"; Frame = 1; Tics = 4; Next state = "FOGPATCHLB"; } State { ID = "FOGPATCHLB"; Sprite = "FOGM"; Frame = 2; Tics = 4; Next state = "FOGPATCHLC"; } State { ID = "FOGPATCHLC"; Sprite = "FOGM"; Frame = 3; Tics = 4; Next state = "FOGPATCHLD"; } State { ID = "FOGPATCHLD"; Sprite = "FOGM"; Frame = 4; Tics = 4; Next state = "FOGPATCHM0"; } State { ID = "QUAKE_ACTIVE1"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE2"; } State { ID = "QUAKE_ACTIVE2"; Sprite = "MAN1"; Frame = 0; Tics = 1; Action = "A_ContMobjSound"; Next state = "QUAKE_ACTIVE3"; } State { ID = "QUAKE_ACTIVE3"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE4"; } State { ID = "QUAKE_ACTIVE4"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE5"; } State { ID = "QUAKE_ACTIVE5"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE6"; } State { ID = "QUAKE_ACTIVE6"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE7"; } State { ID = "QUAKE_ACTIVE7"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE8"; } State { ID = "QUAKE_ACTIVE8"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE9"; } State { ID = "QUAKE_ACTIVE9"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE0"; } State { ID = "QUAKE_ACTIVE0"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEA"; } State { ID = "QUAKE_ACTIVEA"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEB"; } State { ID = "QUAKE_ACTIVEB"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEC"; } State { ID = "QUAKE_ACTIVEC"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVED"; } State { ID = "QUAKE_ACTIVED"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEE"; } State { ID = "QUAKE_ACTIVEE"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEF"; } State { ID = "QUAKE_ACTIVEF"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEG"; } State { ID = "QUAKE_ACTIVEG"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEH"; } State { ID = "QUAKE_ACTIVEH"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEI"; } State { ID = "QUAKE_ACTIVEI"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEJ"; } State { ID = "QUAKE_ACTIVEJ"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEK"; } State { ID = "QUAKE_ACTIVEK"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEL"; } State { ID = "QUAKE_ACTIVEL"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEM"; } State { ID = "QUAKE_ACTIVEM"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEN"; } State { ID = "QUAKE_ACTIVEN"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEO"; } State { ID = "QUAKE_ACTIVEO"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEP"; } State { ID = "QUAKE_ACTIVEP"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEQ"; } State { ID = "QUAKE_ACTIVEQ"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVER"; } State { ID = "QUAKE_ACTIVER"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVES"; } State { ID = "QUAKE_ACTIVES"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVET"; } State { ID = "QUAKE_ACTIVET"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEU"; } State { ID = "QUAKE_ACTIVEU"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEV"; } State { ID = "QUAKE_ACTIVEV"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEW"; } State { ID = "QUAKE_ACTIVEW"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEX"; } State { ID = "QUAKE_ACTIVEX"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEY"; } State { ID = "QUAKE_ACTIVEY"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVEZ"; } State { ID = "QUAKE_ACTIVEZ"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT1"; } State { ID = "QUAKE_ACT1"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT2"; } State { ID = "QUAKE_ACT2"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT3"; } State { ID = "QUAKE_ACT3"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT4"; } State { ID = "QUAKE_ACT4"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT5"; } State { ID = "QUAKE_ACT5"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT6"; } State { ID = "QUAKE_ACT6"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT7"; } State { ID = "QUAKE_ACT7"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT8"; } State { ID = "QUAKE_ACT8"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT9"; } State { ID = "QUAKE_ACT9"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACT0"; } State { ID = "QUAKE_ACT0"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_Quake"; Next state = "QUAKE_ACTIVE1"; } State { ID = "SGSHARD1_1"; Sprite = "SGSA"; Frame = 0; Tics = 4; Next state = "SGSHARD1_2"; } State { ID = "SGSHARD1_2"; Sprite = "SGSA"; Frame = 1; Tics = 4; Next state = "SGSHARD1_3"; } State { ID = "SGSHARD1_3"; Sprite = "SGSA"; Frame = 2; Tics = 4; Next state = "SGSHARD1_4"; } State { ID = "SGSHARD1_4"; Sprite = "SGSA"; Frame = 3; Tics = 4; Next state = "SGSHARD1_5"; } State { ID = "SGSHARD1_5"; Sprite = "SGSA"; Frame = 4; Tics = 4; Next state = "SGSHARD1_1"; } State { ID = "SGSHARD1_D"; Sprite = "SGSA"; Frame = 4; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD2_1"; Sprite = "SGSA"; Frame = 5; Tics = 4; Next state = "SGSHARD2_2"; } State { ID = "SGSHARD2_2"; Sprite = "SGSA"; Frame = 6; Tics = 4; Next state = "SGSHARD2_3"; } State { ID = "SGSHARD2_3"; Sprite = "SGSA"; Frame = 7; Tics = 4; Next state = "SGSHARD2_4"; } State { ID = "SGSHARD2_4"; Sprite = "SGSA"; Frame = 8; Tics = 4; Next state = "SGSHARD2_5"; } State { ID = "SGSHARD2_5"; Sprite = "SGSA"; Frame = 9; Tics = 4; Next state = "SGSHARD2_1"; } State { ID = "SGSHARD2_D"; Sprite = "SGSA"; Frame = 9; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD3_1"; Sprite = "SGSA"; Frame = 10; Tics = 4; Next state = "SGSHARD3_2"; } State { ID = "SGSHARD3_2"; Sprite = "SGSA"; Frame = 11; Tics = 4; Next state = "SGSHARD3_3"; } State { ID = "SGSHARD3_3"; Sprite = "SGSA"; Frame = 12; Tics = 4; Next state = "SGSHARD3_4"; } State { ID = "SGSHARD3_4"; Sprite = "SGSA"; Frame = 13; Tics = 4; Next state = "SGSHARD3_5"; } State { ID = "SGSHARD3_5"; Sprite = "SGSA"; Frame = 14; Tics = 4; Next state = "SGSHARD3_1"; } State { ID = "SGSHARD3_D"; Sprite = "SGSA"; Frame = 14; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD4_1"; Sprite = "SGSA"; Frame = 15; Tics = 4; Next state = "SGSHARD4_2"; } State { ID = "SGSHARD4_2"; Sprite = "SGSA"; Frame = 16; Tics = 4; Next state = "SGSHARD4_3"; } State { ID = "SGSHARD4_3"; Sprite = "SGSA"; Frame = 17; Tics = 4; Next state = "SGSHARD4_4"; } State { ID = "SGSHARD4_4"; Sprite = "SGSA"; Frame = 18; Tics = 4; Next state = "SGSHARD4_5"; } State { ID = "SGSHARD4_5"; Sprite = "SGSA"; Frame = 19; Tics = 4; Next state = "SGSHARD4_1"; } State { ID = "SGSHARD4_D"; Sprite = "SGSA"; Frame = 19; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD5_1"; Sprite = "SGSA"; Frame = 20; Tics = 4; Next state = "SGSHARD5_2"; } State { ID = "SGSHARD5_2"; Sprite = "SGSA"; Frame = 21; Tics = 4; Next state = "SGSHARD5_3"; } State { ID = "SGSHARD5_3"; Sprite = "SGSA"; Frame = 22; Tics = 4; Next state = "SGSHARD5_4"; } State { ID = "SGSHARD5_4"; Sprite = "SGSA"; Frame = 23; Tics = 4; Next state = "SGSHARD5_5"; } State { ID = "SGSHARD5_5"; Sprite = "SGSA"; Frame = 24; Tics = 4; Next state = "SGSHARD5_1"; } State { ID = "SGSHARD5_D"; Sprite = "SGSA"; Frame = 24; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD6_1"; Sprite = "SGSB"; Frame = 0; Tics = 4; Next state = "SGSHARD6_1"; } State { ID = "SGSHARD6_D"; Sprite = "SGSB"; Frame = 0; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD7_1"; Sprite = "SGSB"; Frame = 1; Tics = 4; Next state = "SGSHARD7_1"; } State { ID = "SGSHARD7_D"; Sprite = "SGSB"; Frame = 1; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD8_1"; Sprite = "SGSB"; Frame = 2; Tics = 4; Next state = "SGSHARD8_1"; } State { ID = "SGSHARD8_D"; Sprite = "SGSB"; Frame = 2; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD9_1"; Sprite = "SGSB"; Frame = 3; Tics = 4; Next state = "SGSHARD9_1"; } State { ID = "SGSHARD9_D"; Sprite = "SGSB"; Frame = 3; Tics = 30; Next state = "NULL"; } State { ID = "SGSHARD0_1"; Sprite = "SGSB"; Frame = 4; Tics = 4; Next state = "SGSHARD0_1"; } State { ID = "SGSHARD0_D"; Sprite = "SGSB"; Frame = 4; Tics = 30; Next state = "NULL"; } State { ID = "ARTI_EGGC1"; Sprite = "PORK"; Frame = 0; Tics = 5; Next state = "ARTI_EGGC2"; } State { ID = "ARTI_EGGC2"; Sprite = "PORK"; Frame = 1; Tics = 5; Next state = "ARTI_EGGC3"; } State { ID = "ARTI_EGGC3"; Sprite = "PORK"; Frame = 2; Tics = 5; Next state = "ARTI_EGGC4"; } State { ID = "ARTI_EGGC4"; Sprite = "PORK"; Frame = 3; Tics = 5; Next state = "ARTI_EGGC5"; } State { ID = "ARTI_EGGC5"; Sprite = "PORK"; Frame = 4; Tics = 5; Next state = "ARTI_EGGC6"; } State { ID = "ARTI_EGGC6"; Sprite = "PORK"; Frame = 5; Tics = 5; Next state = "ARTI_EGGC7"; } State { ID = "ARTI_EGGC7"; Sprite = "PORK"; Frame = 6; Tics = 5; Next state = "ARTI_EGGC8"; } State { ID = "ARTI_EGGC8"; Sprite = "PORK"; Frame = 7; Tics = 5; Next state = "ARTI_EGGC1"; } State { ID = "EGGFX1"; Sprite = "EGGM"; Frame = 0; Tics = 4; Next state = "EGGFX2"; } State { ID = "EGGFX2"; Sprite = "EGGM"; Frame = 1; Tics = 4; Next state = "EGGFX3"; } State { ID = "EGGFX3"; Sprite = "EGGM"; Frame = 2; Tics = 4; Next state = "EGGFX4"; } State { ID = "EGGFX4"; Sprite = "EGGM"; Frame = 3; Tics = 4; Next state = "EGGFX5"; } State { ID = "EGGFX5"; Sprite = "EGGM"; Frame = 4; Tics = 4; Next state = "EGGFX1"; } State { ID = "EGGFXI1_1"; Sprite = "FHFX"; Frame = 32776; Tics = 3; Next state = "EGGFXI1_2"; } State { ID = "EGGFXI1_2"; Sprite = "FHFX"; Frame = 32777; Tics = 3; Next state = "EGGFXI1_3"; } State { ID = "EGGFXI1_3"; Sprite = "FHFX"; Frame = 32778; Tics = 3; Next state = "EGGFXI1_4"; } State { ID = "EGGFXI1_4"; Sprite = "FHFX"; Frame = 32779; Tics = 3; Next state = "NULL"; } State { ID = "ARTI_SPHL1"; Sprite = "SPHL"; Frame = 0; Tics = 350; Next state = "ARTI_SPHL1"; } State { ID = "ZWINGEDSTATUENOSKULL"; Sprite = "STWN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZWINGEDSTATUENOSKULL2"; Sprite = "STWN"; Frame = 1; Tics = -1; Next state = "NULL"; } State { ID = "ZGEMPEDESTAL1"; Sprite = "GMPD"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZGEMPEDESTAL2"; Sprite = "GMPD"; Frame = 1; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZSKULL"; Sprite = "ASKU"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZGEMBIG"; Sprite = "ABGM"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZGEMRED"; Sprite = "AGMR"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZGEMGREEN1"; Sprite = "AGMG"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZGEMGREEN2"; Sprite = "AGG2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZGEMBLUE1"; Sprite = "AGMB"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZGEMBLUE2"; Sprite = "AGB2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZBOOK1"; Sprite = "ABK1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZBOOK2"; Sprite = "ABK2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZSKULL2"; Sprite = "ASK2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZFWEAPON"; Sprite = "AFWP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZCWEAPON"; Sprite = "ACWP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZMWEAPON"; Sprite = "AMWP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARTIPUZZGEAR_1"; Sprite = "AGER"; Frame = 32768; Tics = 4; Next state = "ARTIPUZZGEAR_2"; } State { ID = "ARTIPUZZGEAR_2"; Sprite = "AGER"; Frame = 32769; Tics = 4; Next state = "ARTIPUZZGEAR_3"; } State { ID = "ARTIPUZZGEAR_3"; Sprite = "AGER"; Frame = 32770; Tics = 4; Next state = "ARTIPUZZGEAR_4"; } State { ID = "ARTIPUZZGEAR_4"; Sprite = "AGER"; Frame = 32771; Tics = 4; Next state = "ARTIPUZZGEAR_5"; } State { ID = "ARTIPUZZGEAR_5"; Sprite = "AGER"; Frame = 32772; Tics = 4; Next state = "ARTIPUZZGEAR_6"; } State { ID = "ARTIPUZZGEAR_6"; Sprite = "AGER"; Frame = 32773; Tics = 4; Next state = "ARTIPUZZGEAR_7"; } State { ID = "ARTIPUZZGEAR_7"; Sprite = "AGER"; Frame = 32774; Tics = 4; Next state = "ARTIPUZZGEAR_8"; } State { ID = "ARTIPUZZGEAR_8"; Sprite = "AGER"; Frame = 32775; Tics = 4; Next state = "ARTIPUZZGEAR_1"; } State { ID = "ARTIPUZZGEAR2_1"; Sprite = "AGR2"; Frame = 32768; Tics = 4; Next state = "ARTIPUZZGEAR2_2"; } State { ID = "ARTIPUZZGEAR2_2"; Sprite = "AGR2"; Frame = 32769; Tics = 4; Next state = "ARTIPUZZGEAR2_3"; } State { ID = "ARTIPUZZGEAR2_3"; Sprite = "AGR2"; Frame = 32770; Tics = 4; Next state = "ARTIPUZZGEAR2_4"; } State { ID = "ARTIPUZZGEAR2_4"; Sprite = "AGR2"; Frame = 32771; Tics = 4; Next state = "ARTIPUZZGEAR2_5"; } State { ID = "ARTIPUZZGEAR2_5"; Sprite = "AGR2"; Frame = 32772; Tics = 4; Next state = "ARTIPUZZGEAR2_6"; } State { ID = "ARTIPUZZGEAR2_6"; Sprite = "AGR2"; Frame = 32773; Tics = 4; Next state = "ARTIPUZZGEAR2_7"; } State { ID = "ARTIPUZZGEAR2_7"; Sprite = "AGR2"; Frame = 32774; Tics = 4; Next state = "ARTIPUZZGEAR2_8"; } State { ID = "ARTIPUZZGEAR2_8"; Sprite = "AGR2"; Frame = 32775; Tics = 4; Next state = "ARTIPUZZGEAR2_1"; } State { ID = "ARTIPUZZGEAR3_1"; Sprite = "AGR3"; Frame = 32768; Tics = 4; Next state = "ARTIPUZZGEAR3_2"; } State { ID = "ARTIPUZZGEAR3_2"; Sprite = "AGR3"; Frame = 32769; Tics = 4; Next state = "ARTIPUZZGEAR3_3"; } State { ID = "ARTIPUZZGEAR3_3"; Sprite = "AGR3"; Frame = 32770; Tics = 4; Next state = "ARTIPUZZGEAR3_4"; } State { ID = "ARTIPUZZGEAR3_4"; Sprite = "AGR3"; Frame = 32771; Tics = 4; Next state = "ARTIPUZZGEAR3_5"; } State { ID = "ARTIPUZZGEAR3_5"; Sprite = "AGR3"; Frame = 32772; Tics = 4; Next state = "ARTIPUZZGEAR3_6"; } State { ID = "ARTIPUZZGEAR3_6"; Sprite = "AGR3"; Frame = 32773; Tics = 4; Next state = "ARTIPUZZGEAR3_7"; } State { ID = "ARTIPUZZGEAR3_7"; Sprite = "AGR3"; Frame = 32774; Tics = 4; Next state = "ARTIPUZZGEAR3_8"; } State { ID = "ARTIPUZZGEAR3_8"; Sprite = "AGR3"; Frame = 32775; Tics = 4; Next state = "ARTIPUZZGEAR3_1"; } State { ID = "ARTIPUZZGEAR4_1"; Sprite = "AGR4"; Frame = 32768; Tics = 4; Next state = "ARTIPUZZGEAR4_2"; } State { ID = "ARTIPUZZGEAR4_2"; Sprite = "AGR4"; Frame = 32769; Tics = 4; Next state = "ARTIPUZZGEAR4_3"; } State { ID = "ARTIPUZZGEAR4_3"; Sprite = "AGR4"; Frame = 32770; Tics = 4; Next state = "ARTIPUZZGEAR4_4"; } State { ID = "ARTIPUZZGEAR4_4"; Sprite = "AGR4"; Frame = 32771; Tics = 4; Next state = "ARTIPUZZGEAR4_5"; } State { ID = "ARTIPUZZGEAR4_5"; Sprite = "AGR4"; Frame = 32772; Tics = 4; Next state = "ARTIPUZZGEAR4_6"; } State { ID = "ARTIPUZZGEAR4_6"; Sprite = "AGR4"; Frame = 32773; Tics = 4; Next state = "ARTIPUZZGEAR4_7"; } State { ID = "ARTIPUZZGEAR4_7"; Sprite = "AGR4"; Frame = 32774; Tics = 4; Next state = "ARTIPUZZGEAR4_8"; } State { ID = "ARTIPUZZGEAR4_8"; Sprite = "AGR4"; Frame = 32775; Tics = 4; Next state = "ARTIPUZZGEAR4_1"; } State { ID = "ARTI_TRCH1"; Sprite = "TRCH"; Frame = 32768; Tics = 3; Next state = "ARTI_TRCH2"; } State { ID = "ARTI_TRCH2"; Sprite = "TRCH"; Frame = 32769; Tics = 3; Next state = "ARTI_TRCH3"; } State { ID = "ARTI_TRCH3"; Sprite = "TRCH"; Frame = 32770; Tics = 3; Next state = "ARTI_TRCH1"; } State { ID = "FIREBOMB1"; Sprite = "PSBG"; Frame = 0; Tics = 20; Next state = "FIREBOMB2"; } State { ID = "FIREBOMB2"; Sprite = "PSBG"; Frame = 0; Tics = 10; Next state = "FIREBOMB3"; } State { ID = "FIREBOMB3"; Sprite = "PSBG"; Frame = 0; Tics = 10; Next state = "FIREBOMB4"; } State { ID = "FIREBOMB4"; Sprite = "PSBG"; Frame = 1; Tics = 4; Next state = "FIREBOMB5"; } State { ID = "FIREBOMB5"; Sprite = "PSBG"; Frame = 2; Tics = 4; Action = "A_Scream"; Next state = "FIREBOMB6"; } State { ID = "FIREBOMB6"; Sprite = "XPL1"; Frame = 32768; Tics = 4; Action = "A_Explode"; Next state = "FIREBOMB7"; } State { ID = "FIREBOMB7"; Sprite = "XPL1"; Frame = 32769; Tics = 4; Next state = "FIREBOMB8"; } State { ID = "FIREBOMB8"; Sprite = "XPL1"; Frame = 32770; Tics = 4; Next state = "FIREBOMB9"; } State { ID = "FIREBOMB9"; Sprite = "XPL1"; Frame = 32771; Tics = 4; Next state = "FIREBOMB10"; } State { ID = "FIREBOMB10"; Sprite = "XPL1"; Frame = 32772; Tics = 4; Next state = "FIREBOMB11"; } State { ID = "FIREBOMB11"; Sprite = "XPL1"; Frame = 32773; Tics = 4; Next state = "NULL"; } State { ID = "ARTI_ATLP1"; Sprite = "ATLP"; Frame = 0; Tics = 4; Next state = "ARTI_ATLP2"; } State { ID = "ARTI_ATLP2"; Sprite = "ATLP"; Frame = 1; Tics = 4; Next state = "ARTI_ATLP3"; } State { ID = "ARTI_ATLP3"; Sprite = "ATLP"; Frame = 2; Tics = 4; Next state = "ARTI_ATLP4"; } State { ID = "ARTI_ATLP4"; Sprite = "ATLP"; Frame = 1; Tics = 4; Next state = "ARTI_ATLP1"; } State { ID = "ARTI_PSBG1"; Sprite = "PSBG"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "POISONBAG1"; Sprite = "PSBG"; Frame = 32768; Tics = 18; Next state = "POISONBAG2"; } State { ID = "POISONBAG2"; Sprite = "PSBG"; Frame = 32769; Tics = 4; Next state = "POISONBAG3"; } State { ID = "POISONBAG3"; Sprite = "PSBG"; Frame = 2; Tics = 3; Next state = "POISONBAG4"; } State { ID = "POISONBAG4"; Sprite = "PSBG"; Frame = 2; Tics = 1; Action = "A_PoisonBagInit"; Next state = "NULL"; } State { ID = "POISONCLOUD1"; Sprite = "PSBG"; Frame = 3; Tics = 1; Next state = "POISONCLOUD2"; } State { ID = "POISONCLOUD2"; Sprite = "PSBG"; Frame = 3; Tics = 1; Action = "A_Scream"; Next state = "POISONCLOUD3"; } State { ID = "POISONCLOUD3"; Sprite = "PSBG"; Frame = 3; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD4"; } State { ID = "POISONCLOUD4"; Sprite = "PSBG"; Frame = 4; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD5"; } State { ID = "POISONCLOUD5"; Sprite = "PSBG"; Frame = 4; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD6"; } State { ID = "POISONCLOUD6"; Sprite = "PSBG"; Frame = 4; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD7"; } State { ID = "POISONCLOUD7"; Sprite = "PSBG"; Frame = 5; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD8"; } State { ID = "POISONCLOUD8"; Sprite = "PSBG"; Frame = 5; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD9"; } State { ID = "POISONCLOUD9"; Sprite = "PSBG"; Frame = 5; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD10"; } State { ID = "POISONCLOUD10"; Sprite = "PSBG"; Frame = 6; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD11"; } State { ID = "POISONCLOUD11"; Sprite = "PSBG"; Frame = 6; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD12"; } State { ID = "POISONCLOUD12"; Sprite = "PSBG"; Frame = 6; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD13"; } State { ID = "POISONCLOUD13"; Sprite = "PSBG"; Frame = 7; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD14"; } State { ID = "POISONCLOUD14"; Sprite = "PSBG"; Frame = 7; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD15"; } State { ID = "POISONCLOUD15"; Sprite = "PSBG"; Frame = 7; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD16"; } State { ID = "POISONCLOUD16"; Sprite = "PSBG"; Frame = 8; Tics = 2; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD17"; } State { ID = "POISONCLOUD17"; Sprite = "PSBG"; Frame = 8; Tics = 1; Action = "A_PoisonBagDamage"; Next state = "POISONCLOUD18"; } State { ID = "POISONCLOUD18"; Sprite = "PSBG"; Frame = 8; Tics = 1; Action = "A_PoisonBagCheck"; Next state = "POISONCLOUD4"; } State { ID = "POISONCLOUD_X1"; Sprite = "PSBG"; Frame = 7; Tics = 7; Next state = "POISONCLOUD_X2"; } State { ID = "POISONCLOUD_X2"; Sprite = "PSBG"; Frame = 6; Tics = 7; Next state = "POISONCLOUD_X3"; } State { ID = "POISONCLOUD_X3"; Sprite = "PSBG"; Frame = 5; Tics = 6; Next state = "POISONCLOUD_X4"; } State { ID = "POISONCLOUD_X4"; Sprite = "PSBG"; Frame = 3; Tics = 6; Next state = "NULL"; } State { ID = "THROWINGBOMB1"; Sprite = "THRW"; Frame = 0; Tics = 4; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB2"; } State { ID = "THROWINGBOMB2"; Sprite = "THRW"; Frame = 1; Tics = 3; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB3"; } State { ID = "THROWINGBOMB3"; Sprite = "THRW"; Frame = 2; Tics = 3; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB4"; } State { ID = "THROWINGBOMB4"; Sprite = "THRW"; Frame = 3; Tics = 3; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB5"; } State { ID = "THROWINGBOMB5"; Sprite = "THRW"; Frame = 4; Tics = 3; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB6"; } State { ID = "THROWINGBOMB6"; Sprite = "THRW"; Frame = 5; Tics = 3; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB1"; } State { ID = "THROWINGBOMB7"; Sprite = "THRW"; Frame = 6; Tics = 6; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB8"; } State { ID = "THROWINGBOMB8"; Sprite = "THRW"; Frame = 5; Tics = 4; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB9"; } State { ID = "THROWINGBOMB9"; Sprite = "THRW"; Frame = 7; Tics = 6; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB10"; } State { ID = "THROWINGBOMB10"; Sprite = "THRW"; Frame = 5; Tics = 4; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB11"; } State { ID = "THROWINGBOMB11"; Sprite = "THRW"; Frame = 6; Tics = 6; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB12"; } State { ID = "THROWINGBOMB12"; Sprite = "THRW"; Frame = 5; Tics = 3; Action = "A_CheckThrowBomb"; Next state = "THROWINGBOMB12"; } State { ID = "THROWINGBOMB_X1"; Sprite = "CFCF"; Frame = 32784; Tics = 4; Action = "A_NoGravity"; Next state = "THROWINGBOMB_X2"; } State { ID = "THROWINGBOMB_X2"; Sprite = "CFCF"; Frame = 32785; Tics = 3; Action = "A_Scream"; Next state = "THROWINGBOMB_X3"; } State { ID = "THROWINGBOMB_X3"; Sprite = "CFCF"; Frame = 32786; Tics = 4; Action = "A_Explode"; Next state = "THROWINGBOMB_X4"; } State { ID = "THROWINGBOMB_X4"; Sprite = "CFCF"; Frame = 32787; Tics = 3; Next state = "THROWINGBOMB_X5"; } State { ID = "THROWINGBOMB_X5"; Sprite = "CFCF"; Frame = 32788; Tics = 4; Next state = "THROWINGBOMB_X6"; } State { ID = "THROWINGBOMB_X6"; Sprite = "CFCF"; Frame = 32790; Tics = 3; Next state = "THROWINGBOMB_X7"; } State { ID = "THROWINGBOMB_X7"; Sprite = "CFCF"; Frame = 32791; Tics = 4; Next state = "THROWINGBOMB_X8"; } State { ID = "THROWINGBOMB_X8"; Sprite = "CFCF"; Frame = 32793; Tics = 3; Next state = "NULL"; } State { ID = "ARTI_BOOTS1"; Sprite = "SPED"; Frame = 32768; Tics = 3; Next state = "ARTI_BOOTS2"; } State { ID = "ARTI_BOOTS2"; Sprite = "SPED"; Frame = 32769; Tics = 3; Next state = "ARTI_BOOTS3"; } State { ID = "ARTI_BOOTS3"; Sprite = "SPED"; Frame = 32770; Tics = 3; Next state = "ARTI_BOOTS4"; } State { ID = "ARTI_BOOTS4"; Sprite = "SPED"; Frame = 32771; Tics = 3; Next state = "ARTI_BOOTS5"; } State { ID = "ARTI_BOOTS5"; Sprite = "SPED"; Frame = 32772; Tics = 3; Next state = "ARTI_BOOTS6"; } State { ID = "ARTI_BOOTS6"; Sprite = "SPED"; Frame = 32773; Tics = 3; Next state = "ARTI_BOOTS7"; } State { ID = "ARTI_BOOTS7"; Sprite = "SPED"; Frame = 32774; Tics = 3; Next state = "ARTI_BOOTS8"; } State { ID = "ARTI_BOOTS8"; Sprite = "SPED"; Frame = 32775; Tics = 3; Next state = "ARTI_BOOTS1"; } State { ID = "ARTI_MANA"; Sprite = "BMAN"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "ARTI_ARMOR1"; Sprite = "BRAC"; Frame = 32768; Tics = 4; Next state = "ARTI_ARMOR2"; } State { ID = "ARTI_ARMOR2"; Sprite = "BRAC"; Frame = 32769; Tics = 4; Next state = "ARTI_ARMOR3"; } State { ID = "ARTI_ARMOR3"; Sprite = "BRAC"; Frame = 32770; Tics = 4; Next state = "ARTI_ARMOR4"; } State { ID = "ARTI_ARMOR4"; Sprite = "BRAC"; Frame = 32771; Tics = 4; Next state = "ARTI_ARMOR5"; } State { ID = "ARTI_ARMOR5"; Sprite = "BRAC"; Frame = 32772; Tics = 4; Next state = "ARTI_ARMOR6"; } State { ID = "ARTI_ARMOR6"; Sprite = "BRAC"; Frame = 32773; Tics = 4; Next state = "ARTI_ARMOR7"; } State { ID = "ARTI_ARMOR7"; Sprite = "BRAC"; Frame = 32774; Tics = 4; Next state = "ARTI_ARMOR8"; } State { ID = "ARTI_ARMOR8"; Sprite = "BRAC"; Frame = 32775; Tics = 4; Next state = "ARTI_ARMOR1"; } State { ID = "ARTI_BLAST1"; Sprite = "BLST"; Frame = 32768; Tics = 4; Next state = "ARTI_BLAST2"; } State { ID = "ARTI_BLAST2"; Sprite = "BLST"; Frame = 32769; Tics = 4; Next state = "ARTI_BLAST3"; } State { ID = "ARTI_BLAST3"; Sprite = "BLST"; Frame = 32770; Tics = 4; Next state = "ARTI_BLAST4"; } State { ID = "ARTI_BLAST4"; Sprite = "BLST"; Frame = 32771; Tics = 4; Next state = "ARTI_BLAST5"; } State { ID = "ARTI_BLAST5"; Sprite = "BLST"; Frame = 32772; Tics = 4; Next state = "ARTI_BLAST6"; } State { ID = "ARTI_BLAST6"; Sprite = "BLST"; Frame = 32773; Tics = 4; Next state = "ARTI_BLAST7"; } State { ID = "ARTI_BLAST7"; Sprite = "BLST"; Frame = 32774; Tics = 4; Next state = "ARTI_BLAST8"; } State { ID = "ARTI_BLAST8"; Sprite = "BLST"; Frame = 32775; Tics = 4; Next state = "ARTI_BLAST1"; } State { ID = "ARTI_HEALRAD1"; Sprite = "HRAD"; Frame = 32768; Tics = 4; Next state = "ARTI_HEALRAD2"; } State { ID = "ARTI_HEALRAD2"; Sprite = "HRAD"; Frame = 32769; Tics = 4; Next state = "ARTI_HEALRAD3"; } State { ID = "ARTI_HEALRAD3"; Sprite = "HRAD"; Frame = 32770; Tics = 4; Next state = "ARTI_HEALRAD4"; } State { ID = "ARTI_HEALRAD4"; Sprite = "HRAD"; Frame = 32771; Tics = 4; Next state = "ARTI_HEALRAD5"; } State { ID = "ARTI_HEALRAD5"; Sprite = "HRAD"; Frame = 32772; Tics = 4; Next state = "ARTI_HEALRAD6"; } State { ID = "ARTI_HEALRAD6"; Sprite = "HRAD"; Frame = 32773; Tics = 4; Next state = "ARTI_HEALRAD7"; } State { ID = "ARTI_HEALRAD7"; Sprite = "HRAD"; Frame = 32774; Tics = 4; Next state = "ARTI_HEALRAD8"; } State { ID = "ARTI_HEALRAD8"; Sprite = "HRAD"; Frame = 32775; Tics = 4; Next state = "ARTI_HEALRAD9"; } State { ID = "ARTI_HEALRAD9"; Sprite = "HRAD"; Frame = 32776; Tics = 4; Next state = "ARTI_HEALRAD0"; } State { ID = "ARTI_HEALRAD0"; Sprite = "HRAD"; Frame = 32777; Tics = 4; Next state = "ARTI_HEALRADA"; } State { ID = "ARTI_HEALRADA"; Sprite = "HRAD"; Frame = 32778; Tics = 4; Next state = "ARTI_HEALRADB"; } State { ID = "ARTI_HEALRADB"; Sprite = "HRAD"; Frame = 32779; Tics = 4; Next state = "ARTI_HEALRADC"; } State { ID = "ARTI_HEALRADC"; Sprite = "HRAD"; Frame = 32780; Tics = 4; Next state = "ARTI_HEALRADD"; } State { ID = "ARTI_HEALRADD"; Sprite = "HRAD"; Frame = 32781; Tics = 4; Next state = "ARTI_HEALRADE"; } State { ID = "ARTI_HEALRADE"; Sprite = "HRAD"; Frame = 32782; Tics = 4; Next state = "ARTI_HEALRADF"; } State { ID = "ARTI_HEALRADF"; Sprite = "HRAD"; Frame = 32783; Tics = 4; Next state = "ARTI_HEALRAD1"; } State { ID = "SPLASH1"; Sprite = "SPSH"; Frame = 0; Tics = 8; Next state = "SPLASH2"; } State { ID = "SPLASH2"; Sprite = "SPSH"; Frame = 1; Tics = 8; Next state = "SPLASH3"; } State { ID = "SPLASH3"; Sprite = "SPSH"; Frame = 2; Tics = 8; Next state = "SPLASH4"; } State { ID = "SPLASH4"; Sprite = "SPSH"; Frame = 3; Tics = 16; Next state = "NULL"; } State { ID = "SPLASHX"; Sprite = "SPSH"; Frame = 3; Tics = 10; Next state = "NULL"; } State { ID = "SPLASHBASE1"; Sprite = "SPSH"; Frame = 4; Tics = 5; Next state = "SPLASHBASE2"; } State { ID = "SPLASHBASE2"; Sprite = "SPSH"; Frame = 5; Tics = 5; Next state = "SPLASHBASE3"; } State { ID = "SPLASHBASE3"; Sprite = "SPSH"; Frame = 6; Tics = 5; Next state = "SPLASHBASE4"; } State { ID = "SPLASHBASE4"; Sprite = "SPSH"; Frame = 7; Tics = 5; Next state = "SPLASHBASE5"; } State { ID = "SPLASHBASE5"; Sprite = "SPSH"; Frame = 8; Tics = 5; Next state = "SPLASHBASE6"; } State { ID = "SPLASHBASE6"; Sprite = "SPSH"; Frame = 9; Tics = 5; Next state = "SPLASHBASE7"; } State { ID = "SPLASHBASE7"; Sprite = "SPSH"; Frame = 10; Tics = 5; Next state = "NULL"; } State { ID = "LAVASPLASH1"; Sprite = "LVAS"; Frame = 32768; Tics = 5; Next state = "LAVASPLASH2"; } State { ID = "LAVASPLASH2"; Sprite = "LVAS"; Frame = 32769; Tics = 5; Next state = "LAVASPLASH3"; } State { ID = "LAVASPLASH3"; Sprite = "LVAS"; Frame = 32770; Tics = 5; Next state = "LAVASPLASH4"; } State { ID = "LAVASPLASH4"; Sprite = "LVAS"; Frame = 32771; Tics = 5; Next state = "LAVASPLASH5"; } State { ID = "LAVASPLASH5"; Sprite = "LVAS"; Frame = 32772; Tics = 5; Next state = "LAVASPLASH6"; } State { ID = "LAVASPLASH6"; Sprite = "LVAS"; Frame = 32773; Tics = 5; Next state = "NULL"; } State { ID = "LAVASMOKE1"; Sprite = "LVAS"; Frame = 32774; Tics = 5; Next state = "LAVASMOKE2"; } State { ID = "LAVASMOKE2"; Sprite = "LVAS"; Frame = 32775; Tics = 5; Next state = "LAVASMOKE3"; } State { ID = "LAVASMOKE3"; Sprite = "LVAS"; Frame = 32776; Tics = 5; Next state = "LAVASMOKE4"; } State { ID = "LAVASMOKE4"; Sprite = "LVAS"; Frame = 32777; Tics = 5; Next state = "LAVASMOKE5"; } State { ID = "LAVASMOKE5"; Sprite = "LVAS"; Frame = 32778; Tics = 5; Next state = "NULL"; } State { ID = "SLUDGECHUNK1"; Sprite = "SLDG"; Frame = 0; Tics = 8; Next state = "SLUDGECHUNK2"; } State { ID = "SLUDGECHUNK2"; Sprite = "SLDG"; Frame = 1; Tics = 8; Next state = "SLUDGECHUNK3"; } State { ID = "SLUDGECHUNK3"; Sprite = "SLDG"; Frame = 2; Tics = 8; Next state = "SLUDGECHUNK4"; } State { ID = "SLUDGECHUNK4"; Sprite = "SLDG"; Frame = 3; Tics = 8; Next state = "NULL"; } State { ID = "SLUDGECHUNKX"; Sprite = "SLDG"; Frame = 3; Tics = 6; Next state = "NULL"; } State { ID = "SLUDGESPLASH1"; Sprite = "SLDG"; Frame = 4; Tics = 6; Next state = "SLUDGESPLASH2"; } State { ID = "SLUDGESPLASH2"; Sprite = "SLDG"; Frame = 5; Tics = 6; Next state = "SLUDGESPLASH3"; } State { ID = "SLUDGESPLASH3"; Sprite = "SLDG"; Frame = 6; Tics = 6; Next state = "SLUDGESPLASH4"; } State { ID = "SLUDGESPLASH4"; Sprite = "SLDG"; Frame = 7; Tics = 6; Next state = "NULL"; } State { ID = "ZWINGEDSTATUE1"; Sprite = "STTW"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZROCK1_1"; Sprite = "RCK1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZROCK2_1"; Sprite = "RCK2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZROCK3_1"; Sprite = "RCK3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZROCK4_1"; Sprite = "RCK4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCHANDELIER1"; Sprite = "CDLR"; Frame = 32768; Tics = 4; Next state = "ZCHANDELIER2"; } State { ID = "ZCHANDELIER2"; Sprite = "CDLR"; Frame = 32769; Tics = 4; Next state = "ZCHANDELIER3"; } State { ID = "ZCHANDELIER3"; Sprite = "CDLR"; Frame = 32770; Tics = 4; Next state = "ZCHANDELIER1"; } State { ID = "ZCHANDELIER_U"; Sprite = "CDLR"; Frame = 3; Tics = -1; Next state = "NULL"; } State { ID = "ZTREEDEAD1"; Sprite = "TRE1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREE"; Sprite = "TRE1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREEDESTRUCTIBLE1"; Sprite = "TRDT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREEDES_D1"; Sprite = "TRDT"; Frame = 1; Tics = 5; Next state = "ZTREEDES_D2"; } State { ID = "ZTREEDES_D2"; Sprite = "TRDT"; Frame = 2; Tics = 5; Action = "A_Scream"; Next state = "ZTREEDES_D3"; } State { ID = "ZTREEDES_D3"; Sprite = "TRDT"; Frame = 3; Tics = 5; Next state = "ZTREEDES_D4"; } State { ID = "ZTREEDES_D4"; Sprite = "TRDT"; Frame = 4; Tics = 5; Next state = "ZTREEDES_D5"; } State { ID = "ZTREEDES_D5"; Sprite = "TRDT"; Frame = 5; Tics = 5; Next state = "ZTREEDES_D6"; } State { ID = "ZTREEDES_D6"; Sprite = "TRDT"; Frame = 6; Tics = -1; Next state = "NULL"; } State { ID = "ZTREEDES_X1"; Sprite = "TRDT"; Frame = 32775; Tics = 5; Next state = "ZTREEDES_X2"; } State { ID = "ZTREEDES_X2"; Sprite = "TRDT"; Frame = 32776; Tics = 5; Next state = "ZTREEDES_X3"; } State { ID = "ZTREEDES_X3"; Sprite = "TRDT"; Frame = 32777; Tics = 5; Next state = "ZTREEDES_X4"; } State { ID = "ZTREEDES_X4"; Sprite = "TRDT"; Frame = 32778; Tics = 5; Next state = "ZTREEDES_X5"; } State { ID = "ZTREEDES_X5"; Sprite = "TRDT"; Frame = 32779; Tics = 5; Next state = "ZTREEDES_X6"; } State { ID = "ZTREEDES_X6"; Sprite = "TRDT"; Frame = 32780; Tics = 5; Action = "A_Explode"; Next state = "ZTREEDES_X7"; } State { ID = "ZTREEDES_X7"; Sprite = "TRDT"; Frame = 32781; Tics = 5; Next state = "ZTREEDES_X8"; } State { ID = "ZTREEDES_X8"; Sprite = "TRDT"; Frame = 14; Tics = 5; Next state = "ZTREEDES_X9"; } State { ID = "ZTREEDES_X9"; Sprite = "TRDT"; Frame = 15; Tics = 5; Next state = "ZTREEDES_X10"; } State { ID = "ZTREEDES_X10"; Sprite = "TRDT"; Frame = 16; Tics = -1; Next state = "NULL"; } State { ID = "ZTREESWAMP182_1"; Sprite = "TRE2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREESWAMP172_1"; Sprite = "TRE3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTUMPBURNED1"; Sprite = "STM1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTUMPBARE1"; Sprite = "STM2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTUMPSWAMP1_1"; Sprite = "STM3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTUMPSWAMP2_1"; Sprite = "STM4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMLARGE1_1"; Sprite = "MSH1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMLARGE2_1"; Sprite = "MSH2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMLARGE3_1"; Sprite = "MSH3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMSMALL1_1"; Sprite = "MSH4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMSMALL2_1"; Sprite = "MSH5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMSMALL3_1"; Sprite = "MSH6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMSMALL4_1"; Sprite = "MSH7"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHROOMSMALL5_1"; Sprite = "MSH8"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITEPILLAR1"; Sprite = "SGMP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITELARGE1"; Sprite = "SGM1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITEMEDIUM1"; Sprite = "SGM2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITESMALL1"; Sprite = "SGM3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALACTITELARGE1"; Sprite = "SLC1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALACTITEMEDIUM1"; Sprite = "SLC2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALACTITESMALL1"; Sprite = "SLC3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZMOSSCEILING1_1"; Sprite = "MSS1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZMOSSCEILING2_1"; Sprite = "MSS2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSWAMPVINE1"; Sprite = "SWMV"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCORPSEKABOB1"; Sprite = "CPS1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCORPSESLEEPING1"; Sprite = "CPS2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTOMBSTONERIP1"; Sprite = "TMS1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTOMBSTONESHANE1"; Sprite = "TMS2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTOMBSTONEBIGCROSS1"; Sprite = "TMS3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTOMBSTONEBRIANR1"; Sprite = "TMS4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTOMBSTONECROSSCIRCLE1"; Sprite = "TMS5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTOMBSTONESMALLCROSS1"; Sprite = "TMS6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTOMBSTONEBRIANP1"; Sprite = "TMS7"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CORPSEHANGING_1"; Sprite = "CPS3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEGREENTALL_1"; Sprite = "STT2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEBLUETALL_1"; Sprite = "STT3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEGREENSHORT_1"; Sprite = "STT4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEBLUESHORT_1"; Sprite = "STT5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLESTRIPETALL_1"; Sprite = "GAR1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEDARKREDTALL_1"; Sprite = "GAR2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEREDTALL_1"; Sprite = "GAR3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLETANTALL_1"; Sprite = "GAR4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLERUSTTALL_1"; Sprite = "GAR5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEDARKREDSHORT_1"; Sprite = "GAR6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLEREDSHORT_1"; Sprite = "GAR7"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLETANSHORT_1"; Sprite = "GAR8"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTATUEGARGOYLERUSTSHORT_1"; Sprite = "GAR9"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZBANNERTATTERED_1"; Sprite = "BNR1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREELARGE1"; Sprite = "TRE4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREELARGE2"; Sprite = "TRE5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREEGNARLED1"; Sprite = "TRE6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZTREEGNARLED2"; Sprite = "TRE7"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZLOG"; Sprite = "LOGG"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALACTITEICELARGE"; Sprite = "ICT1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALACTITEICEMEDIUM"; Sprite = "ICT2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALACTITEICESMALL"; Sprite = "ICT3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALACTITEICETINY"; Sprite = "ICT4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITEICELARGE"; Sprite = "ICM1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITEICEMEDIUM"; Sprite = "ICM2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITEICESMALL"; Sprite = "ICM3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSTALAGMITEICETINY"; Sprite = "ICM4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZROCKBROWN1"; Sprite = "RKBL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZROCKBROWN2"; Sprite = "RKBS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZROCKBLACK"; Sprite = "RKBK"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZRUBBLE1"; Sprite = "RBL1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZRUBBLE2"; Sprite = "RBL2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZRUBBLE3"; Sprite = "RBL3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZVASEPILLAR"; Sprite = "VASE"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZPOTTERY1"; Sprite = "POT1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZPOTTERY2"; Sprite = "POT2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZPOTTERY3"; Sprite = "POT3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZPOTTERY_EXPLODE"; Sprite = "POT1"; Frame = 0; Tics = 0; Action = "A_PotteryExplode"; Next state = "NULL"; } State { ID = "POTTERYBIT_1"; Sprite = "PBIT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "POTTERYBIT_2"; Sprite = "PBIT"; Frame = 1; Tics = -1; Next state = "NULL"; } State { ID = "POTTERYBIT_3"; Sprite = "PBIT"; Frame = 2; Tics = -1; Next state = "NULL"; } State { ID = "POTTERYBIT_4"; Sprite = "PBIT"; Frame = 3; Tics = -1; Next state = "NULL"; } State { ID = "POTTERYBIT_5"; Sprite = "PBIT"; Frame = 4; Tics = -1; Next state = "NULL"; } State { ID = "POTTERYBIT_EX0"; Sprite = "PBIT"; Frame = 5; Tics = 0; Action = "A_PotteryChooseBit"; Next state = "NULL"; } State { ID = "POTTERYBIT_EX1"; Sprite = "PBIT"; Frame = 5; Tics = 140; Next state = "POTTERYBIT_EX1_2"; } State { ID = "POTTERYBIT_EX1_2"; Sprite = "PBIT"; Frame = 5; Tics = 1; Action = "A_PotteryCheck"; Next state = "NULL"; } State { ID = "POTTERYBIT_EX2"; Sprite = "PBIT"; Frame = 6; Tics = 140; Next state = "POTTERYBIT_EX2_2"; } State { ID = "POTTERYBIT_EX2_2"; Sprite = "PBIT"; Frame = 6; Tics = 1; Action = "A_PotteryCheck"; Next state = "NULL"; } State { ID = "POTTERYBIT_EX3"; Sprite = "PBIT"; Frame = 7; Tics = 140; Next state = "POTTERYBIT_EX3_2"; } State { ID = "POTTERYBIT_EX3_2"; Sprite = "PBIT"; Frame = 7; Tics = 1; Action = "A_PotteryCheck"; Next state = "NULL"; } State { ID = "POTTERYBIT_EX4"; Sprite = "PBIT"; Frame = 8; Tics = 140; Next state = "POTTERYBIT_EX4_2"; } State { ID = "POTTERYBIT_EX4_2"; Sprite = "PBIT"; Frame = 8; Tics = 1; Action = "A_PotteryCheck"; Next state = "NULL"; } State { ID = "POTTERYBIT_EX5"; Sprite = "PBIT"; Frame = 9; Tics = 140; Next state = "POTTERYBIT_EX5_2"; } State { ID = "POTTERYBIT_EX5_2"; Sprite = "PBIT"; Frame = 9; Tics = 1; Action = "A_PotteryCheck"; Next state = "NULL"; } State { ID = "ZCORPSELYNCHED1"; Sprite = "CPS4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCORPSELYNCHED2"; Sprite = "CPS5"; Frame = 0; Tics = 140; Action = "A_CorpseBloodDrip"; Next state = "ZCORPSELYNCHED2"; } State { ID = "ZCORPSESITTING"; Sprite = "CPS6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCORPSESITTING_X"; Sprite = "CPS6"; Frame = 0; Tics = 1; Action = "A_CorpseExplode"; Next state = "NULL"; } State { ID = "CORPSEBIT_1"; Sprite = "CPB1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CORPSEBIT_2"; Sprite = "CPB2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CORPSEBIT_3"; Sprite = "CPB3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CORPSEBIT_4"; Sprite = "CPB4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CORPSEBLOODDRIP"; Sprite = "BDRP"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CORPSEBLOODDRIP_X1"; Sprite = "BDSH"; Frame = 0; Tics = 3; Next state = "CORPSEBLOODDRIP_X2"; } State { ID = "CORPSEBLOODDRIP_X2"; Sprite = "BDSH"; Frame = 1; Tics = 3; Next state = "CORPSEBLOODDRIP_X3"; } State { ID = "CORPSEBLOODDRIP_X3"; Sprite = "BDSH"; Frame = 2; Tics = 2; Next state = "CORPSEBLOODDRIP_X4"; } State { ID = "CORPSEBLOODDRIP_X4"; Sprite = "BDSH"; Frame = 3; Tics = 2; Next state = "NULL"; } State { ID = "BLOODPOOL"; Sprite = "BDPL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCANDLE1"; Sprite = "CNDL"; Frame = 32768; Tics = 4; Next state = "ZCANDLE2"; } State { ID = "ZCANDLE2"; Sprite = "CNDL"; Frame = 32769; Tics = 4; Next state = "ZCANDLE3"; } State { ID = "ZCANDLE3"; Sprite = "CNDL"; Frame = 32770; Tics = 4; Next state = "ZCANDLE1"; } State { ID = "ZLEAFSPAWNER"; Sprite = "MAN1"; Frame = 0; Tics = 20; Action = "A_LeafSpawn"; Next state = "ZLEAFSPAWNER"; } State { ID = "LEAF1_1"; Sprite = "LEF1"; Frame = 0; Tics = 4; Next state = "LEAF1_2"; } State { ID = "LEAF1_2"; Sprite = "LEF1"; Frame = 1; Tics = 4; Next state = "LEAF1_3"; } State { ID = "LEAF1_3"; Sprite = "LEF1"; Frame = 2; Tics = 4; Next state = "LEAF1_4"; } State { ID = "LEAF1_4"; Sprite = "LEF1"; Frame = 3; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF1_5"; } State { ID = "LEAF1_5"; Sprite = "LEF1"; Frame = 4; Tics = 4; Next state = "LEAF1_6"; } State { ID = "LEAF1_6"; Sprite = "LEF1"; Frame = 5; Tics = 4; Next state = "LEAF1_7"; } State { ID = "LEAF1_7"; Sprite = "LEF1"; Frame = 6; Tics = 4; Next state = "LEAF1_8"; } State { ID = "LEAF1_8"; Sprite = "LEF1"; Frame = 7; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF1_9"; } State { ID = "LEAF1_9"; Sprite = "LEF1"; Frame = 8; Tics = 4; Next state = "LEAF1_10"; } State { ID = "LEAF1_10"; Sprite = "LEF1"; Frame = 0; Tics = 4; Next state = "LEAF1_11"; } State { ID = "LEAF1_11"; Sprite = "LEF1"; Frame = 1; Tics = 4; Next state = "LEAF1_12"; } State { ID = "LEAF1_12"; Sprite = "LEF1"; Frame = 2; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF1_13"; } State { ID = "LEAF1_13"; Sprite = "LEF1"; Frame = 3; Tics = 4; Next state = "LEAF1_14"; } State { ID = "LEAF1_14"; Sprite = "LEF1"; Frame = 4; Tics = 4; Next state = "LEAF1_15"; } State { ID = "LEAF1_15"; Sprite = "LEF1"; Frame = 5; Tics = 4; Next state = "LEAF1_16"; } State { ID = "LEAF1_16"; Sprite = "LEF1"; Frame = 6; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF1_17"; } State { ID = "LEAF1_17"; Sprite = "LEF1"; Frame = 7; Tics = 4; Next state = "LEAF1_18"; } State { ID = "LEAF1_18"; Sprite = "LEF1"; Frame = 8; Tics = 4; Next state = "NULL"; } State { ID = "LEAF_X1"; Sprite = "LEF3"; Frame = 3; Tics = 10; Action = "A_LeafCheck"; Next state = "LEAF_X1"; } State { ID = "LEAF2_1"; Sprite = "LEF2"; Frame = 0; Tics = 4; Next state = "LEAF2_2"; } State { ID = "LEAF2_2"; Sprite = "LEF2"; Frame = 1; Tics = 4; Next state = "LEAF2_3"; } State { ID = "LEAF2_3"; Sprite = "LEF2"; Frame = 2; Tics = 4; Next state = "LEAF2_4"; } State { ID = "LEAF2_4"; Sprite = "LEF2"; Frame = 3; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF2_5"; } State { ID = "LEAF2_5"; Sprite = "LEF2"; Frame = 4; Tics = 4; Next state = "LEAF2_6"; } State { ID = "LEAF2_6"; Sprite = "LEF2"; Frame = 5; Tics = 4; Next state = "LEAF2_7"; } State { ID = "LEAF2_7"; Sprite = "LEF2"; Frame = 6; Tics = 4; Next state = "LEAF2_8"; } State { ID = "LEAF2_8"; Sprite = "LEF2"; Frame = 7; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF2_9"; } State { ID = "LEAF2_9"; Sprite = "LEF2"; Frame = 8; Tics = 4; Next state = "LEAF2_10"; } State { ID = "LEAF2_10"; Sprite = "LEF2"; Frame = 0; Tics = 4; Next state = "LEAF2_11"; } State { ID = "LEAF2_11"; Sprite = "LEF2"; Frame = 1; Tics = 4; Next state = "LEAF2_12"; } State { ID = "LEAF2_12"; Sprite = "LEF2"; Frame = 2; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF2_13"; } State { ID = "LEAF2_13"; Sprite = "LEF2"; Frame = 3; Tics = 4; Next state = "LEAF2_14"; } State { ID = "LEAF2_14"; Sprite = "LEF2"; Frame = 4; Tics = 4; Next state = "LEAF2_15"; } State { ID = "LEAF2_15"; Sprite = "LEF2"; Frame = 5; Tics = 4; Next state = "LEAF2_16"; } State { ID = "LEAF2_16"; Sprite = "LEF2"; Frame = 6; Tics = 4; Action = "A_LeafThrust"; Next state = "LEAF2_17"; } State { ID = "LEAF2_17"; Sprite = "LEF2"; Frame = 7; Tics = 4; Next state = "LEAF2_18"; } State { ID = "LEAF2_18"; Sprite = "LEF2"; Frame = 8; Tics = 4; Next state = "NULL"; } State { ID = "ZTWINEDTORCH_1"; Sprite = "TWTR"; Frame = 32768; Tics = 4; Next state = "ZTWINEDTORCH_2"; } State { ID = "ZTWINEDTORCH_2"; Sprite = "TWTR"; Frame = 32769; Tics = 4; Next state = "ZTWINEDTORCH_3"; } State { ID = "ZTWINEDTORCH_3"; Sprite = "TWTR"; Frame = 32770; Tics = 4; Next state = "ZTWINEDTORCH_4"; } State { ID = "ZTWINEDTORCH_4"; Sprite = "TWTR"; Frame = 32771; Tics = 4; Next state = "ZTWINEDTORCH_5"; } State { ID = "ZTWINEDTORCH_5"; Sprite = "TWTR"; Frame = 32772; Tics = 4; Next state = "ZTWINEDTORCH_6"; } State { ID = "ZTWINEDTORCH_6"; Sprite = "TWTR"; Frame = 32773; Tics = 4; Next state = "ZTWINEDTORCH_7"; } State { ID = "ZTWINEDTORCH_7"; Sprite = "TWTR"; Frame = 32774; Tics = 4; Next state = "ZTWINEDTORCH_8"; } State { ID = "ZTWINEDTORCH_8"; Sprite = "TWTR"; Frame = 32775; Tics = 4; Next state = "ZTWINEDTORCH_1"; } State { ID = "ZTWINEDTORCH_UNLIT"; Sprite = "TWTR"; Frame = 8; Tics = -1; Next state = "NULL"; } State { ID = "BRIDGE1"; Sprite = "TLGL"; Frame = 0; Tics = 2; Next state = "BRIDGE2"; } State { ID = "BRIDGE2"; Sprite = "TLGL"; Frame = 0; Tics = 2; Action = "A_BridgeInit"; Next state = "BRIDGE3"; } State { ID = "BRIDGE3"; Sprite = "TLGL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FREE_BRIDGE1"; Sprite = "TLGL"; Frame = 0; Tics = 2; Next state = "FREE_BRIDGE2"; } State { ID = "FREE_BRIDGE2"; Sprite = "TLGL"; Frame = 0; Tics = 300; Next state = "NULL"; } State { ID = "BBALL1"; Sprite = "TLGL"; Frame = 0; Tics = 2; Next state = "BBALL2"; } State { ID = "BBALL2"; Sprite = "TLGL"; Frame = 32768; Tics = 5; Action = "A_BridgeOrbit"; Next state = "BBALL2"; } State { ID = "ZWALLTORCH1"; Sprite = "WLTR"; Frame = 32768; Tics = 5; Next state = "ZWALLTORCH2"; } State { ID = "ZWALLTORCH2"; Sprite = "WLTR"; Frame = 32769; Tics = 5; Next state = "ZWALLTORCH3"; } State { ID = "ZWALLTORCH3"; Sprite = "WLTR"; Frame = 32770; Tics = 5; Next state = "ZWALLTORCH4"; } State { ID = "ZWALLTORCH4"; Sprite = "WLTR"; Frame = 32771; Tics = 5; Next state = "ZWALLTORCH5"; } State { ID = "ZWALLTORCH5"; Sprite = "WLTR"; Frame = 32772; Tics = 5; Next state = "ZWALLTORCH6"; } State { ID = "ZWALLTORCH6"; Sprite = "WLTR"; Frame = 32773; Tics = 5; Next state = "ZWALLTORCH7"; } State { ID = "ZWALLTORCH7"; Sprite = "WLTR"; Frame = 32774; Tics = 5; Next state = "ZWALLTORCH8"; } State { ID = "ZWALLTORCH8"; Sprite = "WLTR"; Frame = 32775; Tics = 5; Next state = "ZWALLTORCH1"; } State { ID = "ZWALLTORCH_U"; Sprite = "WLTR"; Frame = 8; Tics = -1; Next state = "NULL"; } State { ID = "ZBARREL1"; Sprite = "BARL"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHRUB1"; Sprite = "SHB1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHRUB1_DIE"; Sprite = "SHB1"; Frame = 0; Tics = 1; Action = "A_TreeDeath"; Next state = "ZSHRUB1"; } State { ID = "ZSHRUB1_X1"; Sprite = "SHB1"; Frame = 32769; Tics = 7; Next state = "ZSHRUB1_X2"; } State { ID = "ZSHRUB1_X2"; Sprite = "SHB1"; Frame = 32770; Tics = 6; Action = "A_Scream"; Next state = "ZSHRUB1_X3"; } State { ID = "ZSHRUB1_X3"; Sprite = "SHB1"; Frame = 32771; Tics = 5; Next state = "NULL"; } State { ID = "ZSHRUB2"; Sprite = "SHB2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSHRUB2_DIE"; Sprite = "SHB2"; Frame = 0; Tics = 1; Action = "A_TreeDeath"; Next state = "ZSHRUB2"; } State { ID = "ZSHRUB2_X1"; Sprite = "SHB2"; Frame = 32769; Tics = 7; Next state = "ZSHRUB2_X2"; } State { ID = "ZSHRUB2_X2"; Sprite = "SHB2"; Frame = 32770; Tics = 6; Action = "A_Scream"; Next state = "ZSHRUB2_X3"; } State { ID = "ZSHRUB2_X3"; Sprite = "SHB2"; Frame = 32771; Tics = 5; Action = "A_Explode"; Next state = "ZSHRUB2_X4"; } State { ID = "ZSHRUB2_X4"; Sprite = "SHB2"; Frame = 32772; Tics = 5; Next state = "NULL"; } State { ID = "ZBUCKET1"; Sprite = "BCKT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZPOISONSHROOM1"; Sprite = "SHRM"; Frame = 0; Tics = 5; Action = "A_PoisonShroom"; Next state = "ZPOISONSHROOM_P2"; } State { ID = "ZPOISONSHROOM_P1"; Sprite = "SHRM"; Frame = 0; Tics = 6; Next state = "ZPOISONSHROOM_P2"; } State { ID = "ZPOISONSHROOM_P2"; Sprite = "SHRM"; Frame = 1; Tics = 8; Action = "A_Pain"; Next state = "ZPOISONSHROOM1"; } State { ID = "ZPOISONSHROOM_X1"; Sprite = "SHRM"; Frame = 2; Tics = 5; Next state = "ZPOISONSHROOM_X2"; } State { ID = "ZPOISONSHROOM_X2"; Sprite = "SHRM"; Frame = 3; Tics = 5; Next state = "ZPOISONSHROOM_X3"; } State { ID = "ZPOISONSHROOM_X3"; Sprite = "SHRM"; Frame = 4; Tics = 5; Action = "A_PoisonBagInit"; Next state = "ZPOISONSHROOM_X4"; } State { ID = "ZPOISONSHROOM_X4"; Sprite = "SHRM"; Frame = 5; Tics = -1; Next state = "NULL"; } State { ID = "ZFIREBULL1"; Sprite = "FBUL"; Frame = 32768; Tics = 4; Next state = "ZFIREBULL2"; } State { ID = "ZFIREBULL2"; Sprite = "FBUL"; Frame = 32769; Tics = 4; Next state = "ZFIREBULL3"; } State { ID = "ZFIREBULL3"; Sprite = "FBUL"; Frame = 32770; Tics = 4; Next state = "ZFIREBULL4"; } State { ID = "ZFIREBULL4"; Sprite = "FBUL"; Frame = 32771; Tics = 4; Next state = "ZFIREBULL5"; } State { ID = "ZFIREBULL5"; Sprite = "FBUL"; Frame = 32772; Tics = 4; Next state = "ZFIREBULL6"; } State { ID = "ZFIREBULL6"; Sprite = "FBUL"; Frame = 32773; Tics = 4; Next state = "ZFIREBULL7"; } State { ID = "ZFIREBULL7"; Sprite = "FBUL"; Frame = 32774; Tics = 4; Next state = "ZFIREBULL1"; } State { ID = "ZFIREBULL_DEATH"; Sprite = "FBUL"; Frame = 32777; Tics = 4; Next state = "ZFIREBULL_DEATH2"; } State { ID = "ZFIREBULL_DEATH2"; Sprite = "FBUL"; Frame = 32776; Tics = 4; Next state = "ZFIREBULL_U"; } State { ID = "ZFIREBULL_U"; Sprite = "FBUL"; Frame = 7; Tics = -1; Next state = "NULL"; } State { ID = "ZFIREBULL_BIRTH"; Sprite = "FBUL"; Frame = 32776; Tics = 4; Next state = "ZFIREBULL_BIRTH2"; } State { ID = "ZFIREBULL_BIRTH2"; Sprite = "FBUL"; Frame = 32777; Tics = 4; Next state = "ZFIREBULL1"; } State { ID = "ZFIRETHING1"; Sprite = "FSKL"; Frame = 32768; Tics = 4; Next state = "ZFIRETHING2"; } State { ID = "ZFIRETHING2"; Sprite = "FSKL"; Frame = 32769; Tics = 3; Next state = "ZFIRETHING3"; } State { ID = "ZFIRETHING3"; Sprite = "FSKL"; Frame = 32770; Tics = 4; Next state = "ZFIRETHING4"; } State { ID = "ZFIRETHING4"; Sprite = "FSKL"; Frame = 32771; Tics = 3; Next state = "ZFIRETHING5"; } State { ID = "ZFIRETHING5"; Sprite = "FSKL"; Frame = 32772; Tics = 4; Next state = "ZFIRETHING6"; } State { ID = "ZFIRETHING6"; Sprite = "FSKL"; Frame = 32773; Tics = 3; Next state = "ZFIRETHING7"; } State { ID = "ZFIRETHING7"; Sprite = "FSKL"; Frame = 32774; Tics = 4; Next state = "ZFIRETHING8"; } State { ID = "ZFIRETHING8"; Sprite = "FSKL"; Frame = 32775; Tics = 3; Next state = "ZFIRETHING9"; } State { ID = "ZFIRETHING9"; Sprite = "FSKL"; Frame = 32776; Tics = 4; Next state = "ZFIRETHING1"; } State { ID = "ZBRASSTORCH1"; Sprite = "BRTR"; Frame = 32768; Tics = 4; Next state = "ZBRASSTORCH2"; } State { ID = "ZBRASSTORCH2"; Sprite = "BRTR"; Frame = 32769; Tics = 4; Next state = "ZBRASSTORCH3"; } State { ID = "ZBRASSTORCH3"; Sprite = "BRTR"; Frame = 32770; Tics = 4; Next state = "ZBRASSTORCH4"; } State { ID = "ZBRASSTORCH4"; Sprite = "BRTR"; Frame = 32771; Tics = 4; Next state = "ZBRASSTORCH5"; } State { ID = "ZBRASSTORCH5"; Sprite = "BRTR"; Frame = 32772; Tics = 4; Next state = "ZBRASSTORCH6"; } State { ID = "ZBRASSTORCH6"; Sprite = "BRTR"; Frame = 32773; Tics = 4; Next state = "ZBRASSTORCH7"; } State { ID = "ZBRASSTORCH7"; Sprite = "BRTR"; Frame = 32774; Tics = 4; Next state = "ZBRASSTORCH8"; } State { ID = "ZBRASSTORCH8"; Sprite = "BRTR"; Frame = 32775; Tics = 4; Next state = "ZBRASSTORCH9"; } State { ID = "ZBRASSTORCH9"; Sprite = "BRTR"; Frame = 32776; Tics = 4; Next state = "ZBRASSTORCH10"; } State { ID = "ZBRASSTORCH10"; Sprite = "BRTR"; Frame = 32777; Tics = 4; Next state = "ZBRASSTORCH11"; } State { ID = "ZBRASSTORCH11"; Sprite = "BRTR"; Frame = 32778; Tics = 4; Next state = "ZBRASSTORCH12"; } State { ID = "ZBRASSTORCH12"; Sprite = "BRTR"; Frame = 32779; Tics = 4; Next state = "ZBRASSTORCH13"; } State { ID = "ZBRASSTORCH13"; Sprite = "BRTR"; Frame = 32780; Tics = 4; Next state = "ZBRASSTORCH1"; } State { ID = "ZSUITOFARMOR"; Sprite = "SUIT"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZSUITOFARMOR_X1"; Sprite = "SUIT"; Frame = 0; Tics = 1; Action = "A_SoAExplode"; Next state = "NULL"; } State { ID = "ZARMORCHUNK1"; Sprite = "SUIT"; Frame = 1; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK2"; Sprite = "SUIT"; Frame = 2; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK3"; Sprite = "SUIT"; Frame = 3; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK4"; Sprite = "SUIT"; Frame = 4; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK5"; Sprite = "SUIT"; Frame = 5; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK6"; Sprite = "SUIT"; Frame = 6; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK7"; Sprite = "SUIT"; Frame = 7; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK8"; Sprite = "SUIT"; Frame = 8; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK9"; Sprite = "SUIT"; Frame = 9; Tics = -1; Next state = "NULL"; } State { ID = "ZARMORCHUNK10"; Sprite = "SUIT"; Frame = 10; Tics = -1; Next state = "NULL"; } State { ID = "ZBELL"; Sprite = "BBLL"; Frame = 5; Tics = -1; Next state = "NULL"; } State { ID = "ZBELL_X1"; Sprite = "BBLL"; Frame = 0; Tics = 4; Action = "A_BellReset1"; Next state = "ZBELL_X2"; } State { ID = "ZBELL_X2"; Sprite = "BBLL"; Frame = 1; Tics = 4; Next state = "ZBELL_X3"; } State { ID = "ZBELL_X3"; Sprite = "BBLL"; Frame = 2; Tics = 4; Next state = "ZBELL_X4"; } State { ID = "ZBELL_X4"; Sprite = "BBLL"; Frame = 3; Tics = 5; Action = "A_Scream"; Next state = "ZBELL_X5"; } State { ID = "ZBELL_X5"; Sprite = "BBLL"; Frame = 2; Tics = 4; Next state = "ZBELL_X6"; } State { ID = "ZBELL_X6"; Sprite = "BBLL"; Frame = 1; Tics = 4; Next state = "ZBELL_X7"; } State { ID = "ZBELL_X7"; Sprite = "BBLL"; Frame = 0; Tics = 3; Next state = "ZBELL_X8"; } State { ID = "ZBELL_X8"; Sprite = "BBLL"; Frame = 4; Tics = 4; Next state = "ZBELL_X9"; } State { ID = "ZBELL_X9"; Sprite = "BBLL"; Frame = 5; Tics = 5; Next state = "ZBELL_X10"; } State { ID = "ZBELL_X10"; Sprite = "BBLL"; Frame = 6; Tics = 6; Action = "A_Scream"; Next state = "ZBELL_X11"; } State { ID = "ZBELL_X11"; Sprite = "BBLL"; Frame = 5; Tics = 5; Next state = "ZBELL_X12"; } State { ID = "ZBELL_X12"; Sprite = "BBLL"; Frame = 4; Tics = 4; Next state = "ZBELL_X13"; } State { ID = "ZBELL_X13"; Sprite = "BBLL"; Frame = 0; Tics = 4; Next state = "ZBELL_X14"; } State { ID = "ZBELL_X14"; Sprite = "BBLL"; Frame = 1; Tics = 5; Next state = "ZBELL_X15"; } State { ID = "ZBELL_X15"; Sprite = "BBLL"; Frame = 2; Tics = 5; Next state = "ZBELL_X16"; } State { ID = "ZBELL_X16"; Sprite = "BBLL"; Frame = 3; Tics = 6; Action = "A_Scream"; Next state = "ZBELL_X17"; } State { ID = "ZBELL_X17"; Sprite = "BBLL"; Frame = 2; Tics = 5; Next state = "ZBELL_X18"; } State { ID = "ZBELL_X18"; Sprite = "BBLL"; Frame = 1; Tics = 5; Next state = "ZBELL_X19"; } State { ID = "ZBELL_X19"; Sprite = "BBLL"; Frame = 0; Tics = 4; Next state = "ZBELL_X20"; } State { ID = "ZBELL_X20"; Sprite = "BBLL"; Frame = 4; Tics = 5; Next state = "ZBELL_X21"; } State { ID = "ZBELL_X21"; Sprite = "BBLL"; Frame = 5; Tics = 5; Next state = "ZBELL_X22"; } State { ID = "ZBELL_X22"; Sprite = "BBLL"; Frame = 6; Tics = 7; Action = "A_Scream"; Next state = "ZBELL_X23"; } State { ID = "ZBELL_X23"; Sprite = "BBLL"; Frame = 5; Tics = 5; Next state = "ZBELL_X24"; } State { ID = "ZBELL_X24"; Sprite = "BBLL"; Frame = 4; Tics = 5; Next state = "ZBELL_X25"; } State { ID = "ZBELL_X25"; Sprite = "BBLL"; Frame = 0; Tics = 5; Next state = "ZBELL_X26"; } State { ID = "ZBELL_X26"; Sprite = "BBLL"; Frame = 1; Tics = 6; Next state = "ZBELL_X27"; } State { ID = "ZBELL_X27"; Sprite = "BBLL"; Frame = 2; Tics = 6; Next state = "ZBELL_X28"; } State { ID = "ZBELL_X28"; Sprite = "BBLL"; Frame = 3; Tics = 7; Action = "A_Scream"; Next state = "ZBELL_X29"; } State { ID = "ZBELL_X29"; Sprite = "BBLL"; Frame = 2; Tics = 6; Next state = "ZBELL_X30"; } State { ID = "ZBELL_X30"; Sprite = "BBLL"; Frame = 1; Tics = 6; Next state = "ZBELL_X31"; } State { ID = "ZBELL_X31"; Sprite = "BBLL"; Frame = 0; Tics = 5; Next state = "ZBELL_X32"; } State { ID = "ZBELL_X32"; Sprite = "BBLL"; Frame = 4; Tics = 6; Next state = "ZBELL_X33"; } State { ID = "ZBELL_X33"; Sprite = "BBLL"; Frame = 5; Tics = 6; Next state = "ZBELL_X34"; } State { ID = "ZBELL_X34"; Sprite = "BBLL"; Frame = 6; Tics = 7; Action = "A_Scream"; Next state = "ZBELL_X35"; } State { ID = "ZBELL_X35"; Sprite = "BBLL"; Frame = 5; Tics = 6; Next state = "ZBELL_X36"; } State { ID = "ZBELL_X36"; Sprite = "BBLL"; Frame = 4; Tics = 6; Next state = "ZBELL_X37"; } State { ID = "ZBELL_X37"; Sprite = "BBLL"; Frame = 0; Tics = 6; Next state = "ZBELL_X38"; } State { ID = "ZBELL_X38"; Sprite = "BBLL"; Frame = 1; Tics = 6; Next state = "ZBELL_X39"; } State { ID = "ZBELL_X39"; Sprite = "BBLL"; Frame = 2; Tics = 6; Next state = "ZBELL_X40"; } State { ID = "ZBELL_X40"; Sprite = "BBLL"; Frame = 1; Tics = 7; Next state = "ZBELL_X41"; } State { ID = "ZBELL_X41"; Sprite = "BBLL"; Frame = 0; Tics = 8; Next state = "ZBELL_X42"; } State { ID = "ZBELL_X42"; Sprite = "BBLL"; Frame = 4; Tics = 12; Next state = "ZBELL_X43"; } State { ID = "ZBELL_X43"; Sprite = "BBLL"; Frame = 0; Tics = 10; Next state = "ZBELL_X44"; } State { ID = "ZBELL_X44"; Sprite = "BBLL"; Frame = 1; Tics = 12; Next state = "ZBELL_X45"; } State { ID = "ZBELL_X45"; Sprite = "BBLL"; Frame = 0; Tics = 12; Next state = "ZBELL_X46"; } State { ID = "ZBELL_X46"; Sprite = "BBLL"; Frame = 4; Tics = 14; Next state = "ZBELL_X47"; } State { ID = "ZBELL_X47"; Sprite = "BBLL"; Frame = 0; Tics = 1; Action = "A_BellReset2"; Next state = "ZBELL"; } State { ID = "ZBLUE_CANDLE1"; Sprite = "CAND"; Frame = 32768; Tics = 5; Next state = "ZBLUE_CANDLE2"; } State { ID = "ZBLUE_CANDLE2"; Sprite = "CAND"; Frame = 32769; Tics = 5; Next state = "ZBLUE_CANDLE3"; } State { ID = "ZBLUE_CANDLE3"; Sprite = "CAND"; Frame = 32770; Tics = 5; Next state = "ZBLUE_CANDLE4"; } State { ID = "ZBLUE_CANDLE4"; Sprite = "CAND"; Frame = 32771; Tics = 5; Next state = "ZBLUE_CANDLE5"; } State { ID = "ZBLUE_CANDLE5"; Sprite = "CAND"; Frame = 32772; Tics = 5; Next state = "ZBLUE_CANDLE1"; } State { ID = "ZIRON_MAIDEN"; Sprite = "IRON"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZXMAS_TREE"; Sprite = "XMAS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZXMAS_TREE_DIE"; Sprite = "XMAS"; Frame = 0; Tics = 4; Action = "A_TreeDeath"; Next state = "ZXMAS_TREE"; } State { ID = "ZXMAS_TREE_X1"; Sprite = "XMAS"; Frame = 32769; Tics = 6; Next state = "ZXMAS_TREE_X2"; } State { ID = "ZXMAS_TREE_X2"; Sprite = "XMAS"; Frame = 32770; Tics = 6; Action = "A_Scream"; Next state = "ZXMAS_TREE_X3"; } State { ID = "ZXMAS_TREE_X3"; Sprite = "XMAS"; Frame = 32771; Tics = 5; Next state = "ZXMAS_TREE_X4"; } State { ID = "ZXMAS_TREE_X4"; Sprite = "XMAS"; Frame = 32772; Tics = 5; Action = "A_Explode"; Next state = "ZXMAS_TREE_X5"; } State { ID = "ZXMAS_TREE_X5"; Sprite = "XMAS"; Frame = 32773; Tics = 5; Next state = "ZXMAS_TREE_X6"; } State { ID = "ZXMAS_TREE_X6"; Sprite = "XMAS"; Frame = 32774; Tics = 4; Next state = "ZXMAS_TREE_X7"; } State { ID = "ZXMAS_TREE_X7"; Sprite = "XMAS"; Frame = 7; Tics = 5; Next state = "ZXMAS_TREE_X8"; } State { ID = "ZXMAS_TREE_X8"; Sprite = "XMAS"; Frame = 8; Tics = 4; Action = "A_NoBlocking"; Next state = "ZXMAS_TREE_X9"; } State { ID = "ZXMAS_TREE_X9"; Sprite = "XMAS"; Frame = 9; Tics = 4; Next state = "ZXMAS_TREE_X10"; } State { ID = "ZXMAS_TREE_X10"; Sprite = "XMAS"; Frame = 10; Tics = -1; Next state = "NULL"; } State { ID = "ZCAULDRON1"; Sprite = "CDRN"; Frame = 32769; Tics = 4; Next state = "ZCAULDRON2"; } State { ID = "ZCAULDRON2"; Sprite = "CDRN"; Frame = 32770; Tics = 4; Next state = "ZCAULDRON3"; } State { ID = "ZCAULDRON3"; Sprite = "CDRN"; Frame = 32771; Tics = 4; Next state = "ZCAULDRON4"; } State { ID = "ZCAULDRON4"; Sprite = "CDRN"; Frame = 32772; Tics = 4; Next state = "ZCAULDRON5"; } State { ID = "ZCAULDRON5"; Sprite = "CDRN"; Frame = 32773; Tics = 4; Next state = "ZCAULDRON6"; } State { ID = "ZCAULDRON6"; Sprite = "CDRN"; Frame = 32774; Tics = 4; Next state = "ZCAULDRON7"; } State { ID = "ZCAULDRON7"; Sprite = "CDRN"; Frame = 32775; Tics = 4; Next state = "ZCAULDRON1"; } State { ID = "ZCAULDRON_U"; Sprite = "CDRN"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCHAINBIT32"; Sprite = "CHNS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ZCHAINBIT64"; Sprite = "CHNS"; Frame = 1; Tics = -1; Next state = "NULL"; } State { ID = "ZCHAINEND_HEART"; Sprite = "CHNS"; Frame = 2; Tics = -1; Next state = "NULL"; } State { ID = "ZCHAINEND_HOOK1"; Sprite = "CHNS"; Frame = 3; Tics = -1; Next state = "NULL"; } State { ID = "ZCHAINEND_HOOK2"; Sprite = "CHNS"; Frame = 4; Tics = -1; Next state = "NULL"; } State { ID = "ZCHAINEND_SPIKE"; Sprite = "CHNS"; Frame = 5; Tics = -1; Next state = "NULL"; } State { ID = "ZCHAINEND_SKULL"; Sprite = "CHNS"; Frame = 6; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT1"; Sprite = "TST1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT2"; Sprite = "TST2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT3"; Sprite = "TST3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT4"; Sprite = "TST4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT5"; Sprite = "TST5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT6"; Sprite = "TST6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT7"; Sprite = "TST7"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT8"; Sprite = "TST8"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT9"; Sprite = "TST9"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TABLE_SHIT10"; Sprite = "TST0"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "TFOG1"; Sprite = "TELE"; Frame = 32768; Tics = 6; Next state = "TFOG2"; } State { ID = "TFOG2"; Sprite = "TELE"; Frame = 32769; Tics = 6; Next state = "TFOG3"; } State { ID = "TFOG3"; Sprite = "TELE"; Frame = 32770; Tics = 6; Next state = "TFOG4"; } State { ID = "TFOG4"; Sprite = "TELE"; Frame = 32771; Tics = 6; Next state = "TFOG5"; } State { ID = "TFOG5"; Sprite = "TELE"; Frame = 32772; Tics = 6; Next state = "TFOG6"; } State { ID = "TFOG6"; Sprite = "TELE"; Frame = 32773; Tics = 6; Next state = "TFOG7"; } State { ID = "TFOG7"; Sprite = "TELE"; Frame = 32774; Tics = 6; Next state = "TFOG8"; } State { ID = "TFOG8"; Sprite = "TELE"; Frame = 32775; Tics = 6; Next state = "TFOG9"; } State { ID = "TFOG9"; Sprite = "TELE"; Frame = 32774; Tics = 6; Next state = "TFOG10"; } State { ID = "TFOG10"; Sprite = "TELE"; Frame = 32773; Tics = 6; Next state = "TFOG11"; } State { ID = "TFOG11"; Sprite = "TELE"; Frame = 32772; Tics = 6; Next state = "TFOG12"; } State { ID = "TFOG12"; Sprite = "TELE"; Frame = 32771; Tics = 6; Next state = "TFOG13"; } State { ID = "TFOG13"; Sprite = "TELE"; Frame = 32770; Tics = 6; Next state = "NULL"; } State { ID = "TELESMOKE1"; Sprite = "TSMK"; Frame = 0; Tics = 4; Next state = "TELESMOKE2"; } State { ID = "TELESMOKE2"; Sprite = "TSMK"; Frame = 1; Tics = 3; Next state = "TELESMOKE3"; } State { ID = "TELESMOKE3"; Sprite = "TSMK"; Frame = 2; Tics = 4; Next state = "TELESMOKE4"; } State { ID = "TELESMOKE4"; Sprite = "TSMK"; Frame = 3; Tics = 3; Next state = "TELESMOKE5"; } State { ID = "TELESMOKE5"; Sprite = "TSMK"; Frame = 4; Tics = 4; Next state = "TELESMOKE6"; } State { ID = "TELESMOKE6"; Sprite = "TSMK"; Frame = 5; Tics = 3; Next state = "TELESMOKE7"; } State { ID = "TELESMOKE7"; Sprite = "TSMK"; Frame = 6; Tics = 4; Next state = "TELESMOKE8"; } State { ID = "TELESMOKE8"; Sprite = "TSMK"; Frame = 7; Tics = 3; Next state = "TELESMOKE9"; } State { ID = "TELESMOKE9"; Sprite = "TSMK"; Frame = 8; Tics = 4; Next state = "TELESMOKE10"; } State { ID = "TELESMOKE10"; Sprite = "TSMK"; Frame = 9; Tics = 3; Next state = "TELESMOKE11"; } State { ID = "TELESMOKE11"; Sprite = "TSMK"; Frame = 10; Tics = 4; Next state = "TELESMOKE12"; } State { ID = "TELESMOKE12"; Sprite = "TSMK"; Frame = 11; Tics = 3; Next state = "TELESMOKE13"; } State { ID = "TELESMOKE13"; Sprite = "TSMK"; Frame = 12; Tics = 4; Next state = "TELESMOKE14"; } State { ID = "TELESMOKE14"; Sprite = "TSMK"; Frame = 13; Tics = 3; Next state = "TELESMOKE15"; } State { ID = "TELESMOKE15"; Sprite = "TSMK"; Frame = 14; Tics = 4; Next state = "TELESMOKE16"; } State { ID = "TELESMOKE16"; Sprite = "TSMK"; Frame = 15; Tics = 3; Next state = "TELESMOKE17"; } State { ID = "TELESMOKE17"; Sprite = "TSMK"; Frame = 16; Tics = 4; Next state = "TELESMOKE18"; } State { ID = "TELESMOKE18"; Sprite = "TSMK"; Frame = 17; Tics = 3; Next state = "TELESMOKE19"; } State { ID = "TELESMOKE19"; Sprite = "TSMK"; Frame = 18; Tics = 4; Next state = "TELESMOKE20"; } State { ID = "TELESMOKE20"; Sprite = "TSMK"; Frame = 19; Tics = 3; Next state = "TELESMOKE21"; } State { ID = "TELESMOKE21"; Sprite = "TSMK"; Frame = 20; Tics = 4; Next state = "TELESMOKE22"; } State { ID = "TELESMOKE22"; Sprite = "TSMK"; Frame = 21; Tics = 3; Next state = "TELESMOKE23"; } State { ID = "TELESMOKE23"; Sprite = "TSMK"; Frame = 22; Tics = 4; Next state = "TELESMOKE24"; } State { ID = "TELESMOKE24"; Sprite = "TSMK"; Frame = 23; Tics = 3; Next state = "TELESMOKE25"; } State { ID = "TELESMOKE25"; Sprite = "TSMK"; Frame = 24; Tics = 4; Next state = "TELESMOKE26"; } State { ID = "TELESMOKE26"; Sprite = "TSMK"; Frame = 25; Tics = 3; Next state = "TELESMOKE1"; } State { ID = "LIGHTDONE"; Sprite = "FPCH"; Frame = 0; Tics = 0; Action = "A_Light0"; Next state = "NULL"; } State { ID = "PUNCHREADY"; Sprite = "FPCH"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "PUNCHREADY"; } State { ID = "PUNCHDOWN"; Sprite = "FPCH"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "PUNCHDOWN"; } State { ID = "PUNCHUP"; Sprite = "FPCH"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "PUNCHUP"; } State { ID = "PUNCHATK1_1"; Sprite = "FPCH"; Frame = 1; Tics = 5; Next state = "PUNCHATK1_2"; Misc1 = 5; Misc2 = 40; } State { ID = "PUNCHATK1_2"; Sprite = "FPCH"; Frame = 2; Tics = 4; Next state = "PUNCHATK1_3"; Misc1 = 5; Misc2 = 40; } State { ID = "PUNCHATK1_3"; Sprite = "FPCH"; Frame = 3; Tics = 4; Action = "A_FPunchAttack"; Next state = "PUNCHATK1_4"; Misc1 = 5; Misc2 = 40; } State { ID = "PUNCHATK1_4"; Sprite = "FPCH"; Frame = 2; Tics = 4; Next state = "PUNCHATK1_5"; Misc1 = 5; Misc2 = 40; } State { ID = "PUNCHATK1_5"; Sprite = "FPCH"; Frame = 1; Tics = 5; Action = "A_ReFire"; Next state = "PUNCHREADY"; Misc1 = 5; Misc2 = 40; } State { ID = "PUNCHATK2_1"; Sprite = "FPCH"; Frame = 3; Tics = 4; Next state = "PUNCHATK2_2"; Misc1 = 5; Misc2 = 40; } State { ID = "PUNCHATK2_2"; Sprite = "FPCH"; Frame = 4; Tics = 4; Next state = "PUNCHATK2_3"; Misc1 = 5; Misc2 = 40; } State { ID = "PUNCHATK2_3"; Sprite = "FPCH"; Frame = 4; Tics = 1; Next state = "PUNCHATK2_4"; Misc1 = 15; Misc2 = 50; } State { ID = "PUNCHATK2_4"; Sprite = "FPCH"; Frame = 4; Tics = 1; Next state = "PUNCHATK2_5"; Misc1 = 25; Misc2 = 60; } State { ID = "PUNCHATK2_5"; Sprite = "FPCH"; Frame = 4; Tics = 1; Next state = "PUNCHATK2_6"; Misc1 = 35; Misc2 = 70; } State { ID = "PUNCHATK2_6"; Sprite = "FPCH"; Frame = 4; Tics = 1; Next state = "PUNCHATK2_7"; Misc1 = 45; Misc2 = 80; } State { ID = "PUNCHATK2_7"; Sprite = "FPCH"; Frame = 4; Tics = 1; Next state = "PUNCHATK2_8"; Misc1 = 55; Misc2 = 90; } State { ID = "PUNCHATK2_8"; Sprite = "FPCH"; Frame = 4; Tics = 1; Next state = "PUNCHATK2_9"; Misc1 = 65; Misc2 = 100; } State { ID = "PUNCHATK2_9"; Sprite = "FPCH"; Frame = 4; Tics = 10; Next state = "PUNCHREADY"; Misc2 = 150; } State { ID = "PUNCHPUFF1"; Sprite = "FHFX"; Frame = 18; Tics = 4; Next state = "PUNCHPUFF2"; } State { ID = "PUNCHPUFF2"; Sprite = "FHFX"; Frame = 19; Tics = 4; Next state = "PUNCHPUFF3"; } State { ID = "PUNCHPUFF3"; Sprite = "FHFX"; Frame = 20; Tics = 4; Next state = "PUNCHPUFF4"; } State { ID = "PUNCHPUFF4"; Sprite = "FHFX"; Frame = 21; Tics = 4; Next state = "PUNCHPUFF5"; } State { ID = "PUNCHPUFF5"; Sprite = "FHFX"; Frame = 22; Tics = 4; Next state = "NULL"; } State { ID = "AXE"; Sprite = "WFAX"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FAXEREADY"; Sprite = "FAXE"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "FAXEREADY"; } State { ID = "FAXEDOWN"; Sprite = "FAXE"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "FAXEDOWN"; } State { ID = "FAXEUP"; Sprite = "FAXE"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "FAXEUP"; } State { ID = "FAXEATK_1"; Sprite = "FAXE"; Frame = 1; Tics = 4; Next state = "FAXEATK_2"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_2"; Sprite = "FAXE"; Frame = 2; Tics = 3; Next state = "FAXEATK_3"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_3"; Sprite = "FAXE"; Frame = 3; Tics = 2; Next state = "FAXEATK_4"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_4"; Sprite = "FAXE"; Frame = 3; Tics = 1; Action = "A_FAxeAttack"; Next state = "FAXEATK_5"; Misc1 = -5; Misc2 = 70; } State { ID = "FAXEATK_5"; Sprite = "FAXE"; Frame = 3; Tics = 2; Next state = "FAXEATK_6"; Misc1 = -25; Misc2 = 90; } State { ID = "FAXEATK_6"; Sprite = "FAXE"; Frame = 4; Tics = 1; Next state = "FAXEATK_7"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_7"; Sprite = "FAXE"; Frame = 4; Tics = 2; Next state = "FAXEATK_8"; Misc1 = 10; Misc2 = 54; } State { ID = "FAXEATK_8"; Sprite = "FAXE"; Frame = 4; Tics = 7; Next state = "FAXEATK_9"; Misc1 = 10; Misc2 = 150; } State { ID = "FAXEATK_9"; Sprite = "FAXE"; Frame = 0; Tics = 1; Action = "A_ReFire"; Next state = "FAXEATK_10"; Misc2 = 60; } State { ID = "FAXEATK_10"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEATK_11"; Misc2 = 52; } State { ID = "FAXEATK_11"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEATK_12"; Misc2 = 44; } State { ID = "FAXEATK_12"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEATK_13"; Misc2 = 36; } State { ID = "FAXEATK_13"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEREADY"; } State { ID = "FAXEREADY_G"; Sprite = "FAXE"; Frame = 11; Tics = 1; Action = "A_WeaponReady"; Next state = "FAXEREADY_G1"; } State { ID = "FAXEREADY_G1"; Sprite = "FAXE"; Frame = 11; Tics = 1; Action = "A_WeaponReady"; Next state = "FAXEREADY_G2"; } State { ID = "FAXEREADY_G2"; Sprite = "FAXE"; Frame = 11; Tics = 1; Action = "A_WeaponReady"; Next state = "FAXEREADY_G3"; } State { ID = "FAXEREADY_G3"; Sprite = "FAXE"; Frame = 12; Tics = 1; Action = "A_WeaponReady"; Next state = "FAXEREADY_G4"; } State { ID = "FAXEREADY_G4"; Sprite = "FAXE"; Frame = 12; Tics = 1; Action = "A_WeaponReady"; Next state = "FAXEREADY_G5"; } State { ID = "FAXEREADY_G5"; Sprite = "FAXE"; Frame = 12; Tics = 1; Action = "A_WeaponReady"; Next state = "FAXEREADY_G"; } State { ID = "FAXEDOWN_G"; Sprite = "FAXE"; Frame = 11; Tics = 1; Action = "A_Lower"; Next state = "FAXEDOWN_G"; } State { ID = "FAXEUP_G"; Sprite = "FAXE"; Frame = 11; Tics = 1; Action = "A_Raise"; Next state = "FAXEUP_G"; } State { ID = "FAXEATK_G1"; Sprite = "FAXE"; Frame = 13; Tics = 4; Next state = "FAXEATK_G2"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_G2"; Sprite = "FAXE"; Frame = 14; Tics = 3; Next state = "FAXEATK_G3"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_G3"; Sprite = "FAXE"; Frame = 15; Tics = 2; Next state = "FAXEATK_G4"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_G4"; Sprite = "FAXE"; Frame = 15; Tics = 1; Action = "A_FAxeAttack"; Next state = "FAXEATK_G5"; Misc1 = -5; Misc2 = 70; } State { ID = "FAXEATK_G5"; Sprite = "FAXE"; Frame = 15; Tics = 2; Next state = "FAXEATK_G6"; Misc1 = -25; Misc2 = 90; } State { ID = "FAXEATK_G6"; Sprite = "FAXE"; Frame = 16; Tics = 1; Next state = "FAXEATK_G7"; Misc1 = 15; Misc2 = 32; } State { ID = "FAXEATK_G7"; Sprite = "FAXE"; Frame = 16; Tics = 2; Next state = "FAXEATK_G8"; Misc1 = 10; Misc2 = 54; } State { ID = "FAXEATK_G8"; Sprite = "FAXE"; Frame = 16; Tics = 7; Next state = "FAXEATK_G9"; Misc1 = 10; Misc2 = 150; } State { ID = "FAXEATK_G9"; Sprite = "FAXE"; Frame = 0; Tics = 1; Action = "A_ReFire"; Next state = "FAXEATK_G10"; Misc2 = 60; } State { ID = "FAXEATK_G10"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEATK_G11"; Misc2 = 52; } State { ID = "FAXEATK_G11"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEATK_G12"; Misc2 = 44; } State { ID = "FAXEATK_G12"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEATK_G13"; Misc2 = 36; } State { ID = "FAXEATK_G13"; Sprite = "FAXE"; Frame = 0; Tics = 1; Next state = "FAXEREADY_G"; } State { ID = "AXEPUFF_GLOW1"; Sprite = "FAXE"; Frame = 32785; Tics = 4; Next state = "AXEPUFF_GLOW2"; } State { ID = "AXEPUFF_GLOW2"; Sprite = "FAXE"; Frame = 32786; Tics = 4; Next state = "AXEPUFF_GLOW3"; } State { ID = "AXEPUFF_GLOW3"; Sprite = "FAXE"; Frame = 32787; Tics = 4; Next state = "AXEPUFF_GLOW4"; } State { ID = "AXEPUFF_GLOW4"; Sprite = "FAXE"; Frame = 32788; Tics = 4; Next state = "AXEPUFF_GLOW5"; } State { ID = "AXEPUFF_GLOW5"; Sprite = "FAXE"; Frame = 32789; Tics = 4; Next state = "AXEPUFF_GLOW6"; } State { ID = "AXEPUFF_GLOW6"; Sprite = "FAXE"; Frame = 32790; Tics = 4; Next state = "AXEPUFF_GLOW7"; } State { ID = "AXEPUFF_GLOW7"; Sprite = "FAXE"; Frame = 32791; Tics = 4; Next state = "NULL"; } State { ID = "AXEBLOOD1"; Sprite = "FAXE"; Frame = 5; Tics = 3; Next state = "AXEBLOOD2"; } State { ID = "AXEBLOOD2"; Sprite = "FAXE"; Frame = 6; Tics = 3; Next state = "AXEBLOOD3"; } State { ID = "AXEBLOOD3"; Sprite = "FAXE"; Frame = 7; Tics = 3; Next state = "AXEBLOOD4"; } State { ID = "AXEBLOOD4"; Sprite = "FAXE"; Frame = 8; Tics = 3; Next state = "AXEBLOOD5"; } State { ID = "AXEBLOOD5"; Sprite = "FAXE"; Frame = 9; Tics = 3; Next state = "AXEBLOOD6"; } State { ID = "AXEBLOOD6"; Sprite = "FAXE"; Frame = 10; Tics = 3; Next state = "NULL"; } State { ID = "HAMM"; Sprite = "WFHM"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FHAMMERREADY"; Sprite = "FHMR"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "FHAMMERREADY"; } State { ID = "FHAMMERDOWN"; Sprite = "FHMR"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "FHAMMERDOWN"; } State { ID = "FHAMMERUP"; Sprite = "FHMR"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "FHAMMERUP"; } State { ID = "FHAMMERATK_1"; Sprite = "FHMR"; Frame = 1; Tics = 6; Next state = "FHAMMERATK_2"; Misc1 = 5; } State { ID = "FHAMMERATK_2"; Sprite = "FHMR"; Frame = 2; Tics = 3; Action = "A_FHammerAttack"; Next state = "FHAMMERATK_3"; Misc1 = 5; } State { ID = "FHAMMERATK_3"; Sprite = "FHMR"; Frame = 3; Tics = 3; Next state = "FHAMMERATK_4"; Misc1 = 5; } State { ID = "FHAMMERATK_4"; Sprite = "FHMR"; Frame = 4; Tics = 2; Next state = "FHAMMERATK_5"; Misc1 = 5; } State { ID = "FHAMMERATK_5"; Sprite = "FHMR"; Frame = 4; Tics = 10; Action = "A_FHammerThrow"; Next state = "FHAMMERATK_6"; Misc1 = 5; Misc2 = 150; } State { ID = "FHAMMERATK_6"; Sprite = "FHMR"; Frame = 0; Tics = 1; Next state = "FHAMMERATK_7"; Misc2 = 60; } State { ID = "FHAMMERATK_7"; Sprite = "FHMR"; Frame = 0; Tics = 1; Next state = "FHAMMERATK_8"; Misc2 = 55; } State { ID = "FHAMMERATK_8"; Sprite = "FHMR"; Frame = 0; Tics = 1; Next state = "FHAMMERATK_9"; Misc2 = 50; } State { ID = "FHAMMERATK_9"; Sprite = "FHMR"; Frame = 0; Tics = 1; Next state = "FHAMMERATK_10"; Misc2 = 45; } State { ID = "FHAMMERATK_10"; Sprite = "FHMR"; Frame = 0; Tics = 1; Next state = "FHAMMERATK_11"; Misc2 = 40; } State { ID = "FHAMMERATK_11"; Sprite = "FHMR"; Frame = 0; Tics = 1; Next state = "FHAMMERATK_12"; Misc2 = 35; } State { ID = "FHAMMERATK_12"; Sprite = "FHMR"; Frame = 0; Tics = 1; Next state = "FHAMMERREADY"; } State { ID = "HAMMER_MISSILE_1"; Sprite = "FHFX"; Frame = 32768; Tics = 2; Next state = "HAMMER_MISSILE_2"; } State { ID = "HAMMER_MISSILE_2"; Sprite = "FHFX"; Frame = 32769; Tics = 2; Action = "A_ContMobjSound"; Next state = "HAMMER_MISSILE_3"; } State { ID = "HAMMER_MISSILE_3"; Sprite = "FHFX"; Frame = 32770; Tics = 2; Next state = "HAMMER_MISSILE_4"; } State { ID = "HAMMER_MISSILE_4"; Sprite = "FHFX"; Frame = 32771; Tics = 2; Next state = "HAMMER_MISSILE_5"; } State { ID = "HAMMER_MISSILE_5"; Sprite = "FHFX"; Frame = 32772; Tics = 2; Next state = "HAMMER_MISSILE_6"; } State { ID = "HAMMER_MISSILE_6"; Sprite = "FHFX"; Frame = 32773; Tics = 2; Next state = "HAMMER_MISSILE_7"; } State { ID = "HAMMER_MISSILE_7"; Sprite = "FHFX"; Frame = 32774; Tics = 2; Next state = "HAMMER_MISSILE_8"; } State { ID = "HAMMER_MISSILE_8"; Sprite = "FHFX"; Frame = 32775; Tics = 2; Next state = "HAMMER_MISSILE_1"; } State { ID = "HAMMER_MISSILE_X1"; Sprite = "FHFX"; Frame = 32776; Tics = 3; Next state = "HAMMER_MISSILE_X2"; } State { ID = "HAMMER_MISSILE_X2"; Sprite = "FHFX"; Frame = 32777; Tics = 3; Next state = "HAMMER_MISSILE_X3"; } State { ID = "HAMMER_MISSILE_X3"; Sprite = "FHFX"; Frame = 32778; Tics = 3; Action = "A_Explode"; Next state = "HAMMER_MISSILE_X4"; } State { ID = "HAMMER_MISSILE_X4"; Sprite = "FHFX"; Frame = 32779; Tics = 3; Next state = "HAMMER_MISSILE_X5"; } State { ID = "HAMMER_MISSILE_X5"; Sprite = "FHFX"; Frame = 32780; Tics = 3; Next state = "HAMMER_MISSILE_X6"; } State { ID = "HAMMER_MISSILE_X6"; Sprite = "FHFX"; Frame = 13; Tics = 3; Next state = "HAMMER_MISSILE_X7"; } State { ID = "HAMMER_MISSILE_X7"; Sprite = "FHFX"; Frame = 32782; Tics = 3; Next state = "HAMMER_MISSILE_X8"; } State { ID = "HAMMER_MISSILE_X8"; Sprite = "FHFX"; Frame = 32783; Tics = 3; Next state = "HAMMER_MISSILE_X9"; } State { ID = "HAMMER_MISSILE_X9"; Sprite = "FHFX"; Frame = 32784; Tics = 3; Next state = "HAMMER_MISSILE_X10"; } State { ID = "HAMMER_MISSILE_X10"; Sprite = "FHFX"; Frame = 32785; Tics = 3; Next state = "NULL"; } State { ID = "HAMMERPUFF1"; Sprite = "FHFX"; Frame = 18; Tics = 4; Next state = "HAMMERPUFF2"; } State { ID = "HAMMERPUFF2"; Sprite = "FHFX"; Frame = 19; Tics = 4; Next state = "HAMMERPUFF3"; } State { ID = "HAMMERPUFF3"; Sprite = "FHFX"; Frame = 20; Tics = 4; Next state = "HAMMERPUFF4"; } State { ID = "HAMMERPUFF4"; Sprite = "FHFX"; Frame = 21; Tics = 4; Next state = "HAMMERPUFF5"; } State { ID = "HAMMERPUFF5"; Sprite = "FHFX"; Frame = 22; Tics = 4; Next state = "NULL"; } State { ID = "FSWORDREADY"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY1"; } State { ID = "FSWORDREADY1"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY2"; } State { ID = "FSWORDREADY2"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY3"; } State { ID = "FSWORDREADY3"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY4"; } State { ID = "FSWORDREADY4"; Sprite = "FSRD"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY5"; } State { ID = "FSWORDREADY5"; Sprite = "FSRD"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY6"; } State { ID = "FSWORDREADY6"; Sprite = "FSRD"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY7"; } State { ID = "FSWORDREADY7"; Sprite = "FSRD"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY8"; } State { ID = "FSWORDREADY8"; Sprite = "FSRD"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY9"; } State { ID = "FSWORDREADY9"; Sprite = "FSRD"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY10"; } State { ID = "FSWORDREADY10"; Sprite = "FSRD"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY11"; } State { ID = "FSWORDREADY11"; Sprite = "FSRD"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "FSWORDREADY"; } State { ID = "FSWORDDOWN"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Action = "A_Lower"; Next state = "FSWORDDOWN"; } State { ID = "FSWORDUP"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Action = "A_Raise"; Next state = "FSWORDUP"; } State { ID = "FSWORDATK_1"; Sprite = "FSRD"; Frame = 32771; Tics = 3; Next state = "FSWORDATK_2"; Misc1 = 5; Misc2 = 36; } State { ID = "FSWORDATK_2"; Sprite = "FSRD"; Frame = 32772; Tics = 3; Next state = "FSWORDATK_3"; Misc1 = 5; Misc2 = 36; } State { ID = "FSWORDATK_3"; Sprite = "FSRD"; Frame = 32773; Tics = 2; Next state = "FSWORDATK_4"; Misc1 = 5; Misc2 = 36; } State { ID = "FSWORDATK_4"; Sprite = "FSRD"; Frame = 32774; Tics = 3; Action = "A_FSwordAttack"; Next state = "FSWORDATK_5"; Misc1 = 5; Misc2 = 36; } State { ID = "FSWORDATK_5"; Sprite = "FSRD"; Frame = 32775; Tics = 2; Next state = "FSWORDATK_6"; Misc1 = 5; Misc2 = 36; } State { ID = "FSWORDATK_6"; Sprite = "FSRD"; Frame = 32776; Tics = 2; Next state = "FSWORDATK_7"; Misc1 = 5; Misc2 = 36; } State { ID = "FSWORDATK_7"; Sprite = "FSRD"; Frame = 32776; Tics = 10; Next state = "FSWORDATK_8"; Misc1 = 5; Misc2 = 150; } State { ID = "FSWORDATK_8"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Next state = "FSWORDATK_9"; Misc1 = 5; Misc2 = 60; } State { ID = "FSWORDATK_9"; Sprite = "FSRD"; Frame = 32769; Tics = 1; Next state = "FSWORDATK_10"; Misc1 = 5; Misc2 = 55; } State { ID = "FSWORDATK_10"; Sprite = "FSRD"; Frame = 32770; Tics = 1; Next state = "FSWORDATK_11"; Misc1 = 5; Misc2 = 50; } State { ID = "FSWORDATK_11"; Sprite = "FSRD"; Frame = 32768; Tics = 1; Next state = "FSWORDATK_12"; Misc1 = 5; Misc2 = 45; } State { ID = "FSWORDATK_12"; Sprite = "FSRD"; Frame = 32769; Tics = 1; Next state = "FSWORDREADY"; Misc1 = 5; Misc2 = 40; } State { ID = "FSWORD_MISSILE1"; Sprite = "FSFX"; Frame = 32768; Tics = 3; Next state = "FSWORD_MISSILE2"; } State { ID = "FSWORD_MISSILE2"; Sprite = "FSFX"; Frame = 32769; Tics = 3; Next state = "FSWORD_MISSILE3"; } State { ID = "FSWORD_MISSILE3"; Sprite = "FSFX"; Frame = 32770; Tics = 3; Next state = "FSWORD_MISSILE1"; } State { ID = "FSWORD_MISSILE_X1"; Sprite = "FSFX"; Frame = 32771; Tics = 4; Next state = "FSWORD_MISSILE_X2"; } State { ID = "FSWORD_MISSILE_X2"; Sprite = "FSFX"; Frame = 32772; Tics = 3; Action = "A_FSwordFlames"; Next state = "FSWORD_MISSILE_X3"; } State { ID = "FSWORD_MISSILE_X3"; Sprite = "FSFX"; Frame = 32773; Tics = 4; Action = "A_Explode"; Next state = "FSWORD_MISSILE_X4"; } State { ID = "FSWORD_MISSILE_X4"; Sprite = "FSFX"; Frame = 32774; Tics = 3; Next state = "FSWORD_MISSILE_X5"; } State { ID = "FSWORD_MISSILE_X5"; Sprite = "FSFX"; Frame = 32775; Tics = 4; Next state = "FSWORD_MISSILE_X6"; } State { ID = "FSWORD_MISSILE_X6"; Sprite = "FSFX"; Frame = 32776; Tics = 3; Next state = "FSWORD_MISSILE_X7"; } State { ID = "FSWORD_MISSILE_X7"; Sprite = "FSFX"; Frame = 32777; Tics = 4; Next state = "FSWORD_MISSILE_X8"; } State { ID = "FSWORD_MISSILE_X8"; Sprite = "FSFX"; Frame = 32778; Tics = 3; Next state = "FSWORD_MISSILE_X9"; } State { ID = "FSWORD_MISSILE_X9"; Sprite = "FSFX"; Frame = 32779; Tics = 3; Next state = "FSWORD_MISSILE_X10"; } State { ID = "FSWORD_MISSILE_X10"; Sprite = "FSFX"; Frame = 32780; Tics = 3; Next state = "NULL"; } State { ID = "FSWORD_FLAME1"; Sprite = "FSFX"; Frame = 32781; Tics = 3; Next state = "FSWORD_FLAME2"; } State { ID = "FSWORD_FLAME2"; Sprite = "FSFX"; Frame = 32782; Tics = 3; Next state = "FSWORD_FLAME3"; } State { ID = "FSWORD_FLAME3"; Sprite = "FSFX"; Frame = 32783; Tics = 3; Next state = "FSWORD_FLAME4"; } State { ID = "FSWORD_FLAME4"; Sprite = "FSFX"; Frame = 32784; Tics = 3; Next state = "FSWORD_FLAME5"; } State { ID = "FSWORD_FLAME5"; Sprite = "FSFX"; Frame = 32785; Tics = 3; Next state = "FSWORD_FLAME6"; } State { ID = "FSWORD_FLAME6"; Sprite = "FSFX"; Frame = 32786; Tics = 3; Next state = "FSWORD_FLAME7"; } State { ID = "FSWORD_FLAME7"; Sprite = "FSFX"; Frame = 32787; Tics = 3; Next state = "FSWORD_FLAME8"; } State { ID = "FSWORD_FLAME8"; Sprite = "FSFX"; Frame = 32788; Tics = 3; Next state = "FSWORD_FLAME9"; } State { ID = "FSWORD_FLAME9"; Sprite = "FSFX"; Frame = 32789; Tics = 3; Next state = "FSWORD_FLAME10"; } State { ID = "FSWORD_FLAME10"; Sprite = "FSFX"; Frame = 32790; Tics = 3; Next state = "NULL"; } State { ID = "CMACEREADY"; Sprite = "CMCE"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CMACEREADY"; } State { ID = "CMACEDOWN"; Sprite = "CMCE"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "CMACEDOWN"; } State { ID = "CMACEUP"; Sprite = "CMCE"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "CMACEUP"; } State { ID = "CMACEATK_1"; Sprite = "CMCE"; Frame = 1; Tics = 2; Next state = "CMACEATK_2"; Misc1 = 60; Misc2 = 20; } State { ID = "CMACEATK_2"; Sprite = "CMCE"; Frame = 1; Tics = 1; Next state = "CMACEATK_3"; Misc1 = 30; Misc2 = 33; } State { ID = "CMACEATK_3"; Sprite = "CMCE"; Frame = 1; Tics = 2; Next state = "CMACEATK_4"; Misc1 = 8; Misc2 = 45; } State { ID = "CMACEATK_4"; Sprite = "CMCE"; Frame = 2; Tics = 1; Next state = "CMACEATK_5"; Misc1 = 8; Misc2 = 45; } State { ID = "CMACEATK_5"; Sprite = "CMCE"; Frame = 3; Tics = 1; Next state = "CMACEATK_6"; Misc1 = 8; Misc2 = 45; } State { ID = "CMACEATK_6"; Sprite = "CMCE"; Frame = 4; Tics = 1; Next state = "CMACEATK_7"; Misc1 = 8; Misc2 = 45; } State { ID = "CMACEATK_7"; Sprite = "CMCE"; Frame = 4; Tics = 1; Action = "A_CMaceAttack"; Next state = "CMACEATK_8"; Misc1 = -11; Misc2 = 58; } State { ID = "CMACEATK_8"; Sprite = "CMCE"; Frame = 5; Tics = 1; Next state = "CMACEATK_9"; Misc1 = 8; Misc2 = 45; } State { ID = "CMACEATK_9"; Sprite = "CMCE"; Frame = 5; Tics = 2; Next state = "CMACEATK_10"; Misc1 = -8; Misc2 = 74; } State { ID = "CMACEATK_10"; Sprite = "CMCE"; Frame = 5; Tics = 1; Next state = "CMACEATK_11"; Misc1 = -20; Misc2 = 96; } State { ID = "CMACEATK_11"; Sprite = "CMCE"; Frame = 5; Tics = 8; Next state = "CMACEATK_12"; Misc1 = -33; Misc2 = 160; } State { ID = "CMACEATK_12"; Sprite = "CMCE"; Frame = 0; Tics = 2; Action = "A_ReFire"; Next state = "CMACEATK_13"; Misc1 = 8; Misc2 = 75; } State { ID = "CMACEATK_13"; Sprite = "CMCE"; Frame = 0; Tics = 1; Next state = "CMACEATK_14"; Misc1 = 8; Misc2 = 65; } State { ID = "CMACEATK_14"; Sprite = "CMCE"; Frame = 0; Tics = 2; Next state = "CMACEATK_15"; Misc1 = 8; Misc2 = 60; } State { ID = "CMACEATK_15"; Sprite = "CMCE"; Frame = 0; Tics = 1; Next state = "CMACEATK_16"; Misc1 = 8; Misc2 = 55; } State { ID = "CMACEATK_16"; Sprite = "CMCE"; Frame = 0; Tics = 2; Next state = "CMACEATK_17"; Misc1 = 8; Misc2 = 50; } State { ID = "CMACEATK_17"; Sprite = "CMCE"; Frame = 0; Tics = 1; Next state = "CMACEREADY"; Misc1 = 8; Misc2 = 45; } State { ID = "CSTAFF"; Sprite = "WCSS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CSTAFFREADY"; Sprite = "CSSF"; Frame = 2; Tics = 4; Next state = "CSTAFFREADY1"; } State { ID = "CSTAFFREADY1"; Sprite = "CSSF"; Frame = 1; Tics = 3; Action = "A_CStaffInitBlink"; Next state = "CSTAFFREADY2"; } State { ID = "CSTAFFREADY2"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY3"; } State { ID = "CSTAFFREADY3"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY4"; } State { ID = "CSTAFFREADY4"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY5"; } State { ID = "CSTAFFREADY5"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY6"; } State { ID = "CSTAFFREADY6"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY7"; } State { ID = "CSTAFFREADY7"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY8"; } State { ID = "CSTAFFREADY8"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY9"; } State { ID = "CSTAFFREADY9"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_CStaffCheckBlink"; Next state = "CSTAFFREADY2"; } State { ID = "CSTAFFBLINK1"; Sprite = "CSSF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK2"; } State { ID = "CSTAFFBLINK2"; Sprite = "CSSF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK3"; } State { ID = "CSTAFFBLINK3"; Sprite = "CSSF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK4"; } State { ID = "CSTAFFBLINK4"; Sprite = "CSSF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK5"; } State { ID = "CSTAFFBLINK5"; Sprite = "CSSF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK6"; } State { ID = "CSTAFFBLINK6"; Sprite = "CSSF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK7"; } State { ID = "CSTAFFBLINK7"; Sprite = "CSSF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK8"; } State { ID = "CSTAFFBLINK8"; Sprite = "CSSF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK9"; } State { ID = "CSTAFFBLINK9"; Sprite = "CSSF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK10"; } State { ID = "CSTAFFBLINK10"; Sprite = "CSSF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFBLINK11"; } State { ID = "CSTAFFBLINK11"; Sprite = "CSSF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CSTAFFREADY2"; } State { ID = "CSTAFFDOWN"; Sprite = "CSSF"; Frame = 1; Tics = 3; Next state = "CSTAFFDOWN2"; } State { ID = "CSTAFFDOWN2"; Sprite = "CSSF"; Frame = 2; Tics = 4; Next state = "CSTAFFDOWN3"; } State { ID = "CSTAFFDOWN3"; Sprite = "CSSF"; Frame = 2; Tics = 1; Action = "A_Lower"; Next state = "CSTAFFDOWN3"; } State { ID = "CSTAFFUP"; Sprite = "CSSF"; Frame = 2; Tics = 1; Action = "A_Raise"; Next state = "CSTAFFUP"; } State { ID = "CSTAFFATK_1"; Sprite = "CSSF"; Frame = 0; Tics = 1; Action = "A_CStaffCheck"; Next state = "CSTAFFATK_2"; Misc2 = 45; } State { ID = "CSTAFFATK_2"; Sprite = "CSSF"; Frame = 9; Tics = 1; Action = "A_CStaffAttack"; Next state = "CSTAFFATK_3"; Misc2 = 50; } State { ID = "CSTAFFATK_3"; Sprite = "CSSF"; Frame = 9; Tics = 2; Next state = "CSTAFFATK_4"; Misc2 = 50; } State { ID = "CSTAFFATK_4"; Sprite = "CSSF"; Frame = 9; Tics = 2; Next state = "CSTAFFATK_5"; Misc2 = 45; } State { ID = "CSTAFFATK_5"; Sprite = "CSSF"; Frame = 0; Tics = 2; Next state = "CSTAFFATK_6"; Misc2 = 40; } State { ID = "CSTAFFATK_6"; Sprite = "CSSF"; Frame = 0; Tics = 2; Next state = "CSTAFFREADY2"; Misc2 = 36; } State { ID = "CSTAFFATK2_1"; Sprite = "CSSF"; Frame = 10; Tics = 10; Next state = "CSTAFFREADY2"; Misc2 = 36; } State { ID = "CSTAFF_MISSILE1"; Sprite = "CSSF"; Frame = 32771; Tics = 1; Action = "A_CStaffMissileSlither"; Next state = "CSTAFF_MISSILE2"; } State { ID = "CSTAFF_MISSILE2"; Sprite = "CSSF"; Frame = 32771; Tics = 1; Action = "A_CStaffMissileSlither"; Next state = "CSTAFF_MISSILE3"; } State { ID = "CSTAFF_MISSILE3"; Sprite = "CSSF"; Frame = 32772; Tics = 1; Action = "A_CStaffMissileSlither"; Next state = "CSTAFF_MISSILE4"; } State { ID = "CSTAFF_MISSILE4"; Sprite = "CSSF"; Frame = 32772; Tics = 1; Action = "A_CStaffMissileSlither"; Next state = "CSTAFF_MISSILE1"; } State { ID = "CSTAFF_MISSILE_X1"; Sprite = "CSSF"; Frame = 32773; Tics = 4; Next state = "CSTAFF_MISSILE_X2"; } State { ID = "CSTAFF_MISSILE_X2"; Sprite = "CSSF"; Frame = 32774; Tics = 4; Next state = "CSTAFF_MISSILE_X3"; } State { ID = "CSTAFF_MISSILE_X3"; Sprite = "CSSF"; Frame = 32775; Tics = 3; Next state = "CSTAFF_MISSILE_X4"; } State { ID = "CSTAFF_MISSILE_X4"; Sprite = "CSSF"; Frame = 32776; Tics = 3; Next state = "NULL"; } State { ID = "CSTAFFPUFF1"; Sprite = "FHFX"; Frame = 18; Tics = 4; Next state = "CSTAFFPUFF2"; } State { ID = "CSTAFFPUFF2"; Sprite = "FHFX"; Frame = 19; Tics = 4; Next state = "CSTAFFPUFF3"; } State { ID = "CSTAFFPUFF3"; Sprite = "FHFX"; Frame = 20; Tics = 4; Next state = "CSTAFFPUFF4"; } State { ID = "CSTAFFPUFF4"; Sprite = "FHFX"; Frame = 21; Tics = 4; Next state = "CSTAFFPUFF5"; } State { ID = "CSTAFFPUFF5"; Sprite = "FHFX"; Frame = 22; Tics = 4; Next state = "NULL"; } State { ID = "CFLAME1"; Sprite = "WCFM"; Frame = 32768; Tics = 4; Next state = "CFLAME2"; } State { ID = "CFLAME2"; Sprite = "WCFM"; Frame = 32769; Tics = 4; Next state = "CFLAME3"; } State { ID = "CFLAME3"; Sprite = "WCFM"; Frame = 32770; Tics = 4; Next state = "CFLAME4"; } State { ID = "CFLAME4"; Sprite = "WCFM"; Frame = 32771; Tics = 4; Next state = "CFLAME5"; } State { ID = "CFLAME5"; Sprite = "WCFM"; Frame = 32772; Tics = 4; Next state = "CFLAME6"; } State { ID = "CFLAME6"; Sprite = "WCFM"; Frame = 32773; Tics = 4; Next state = "CFLAME7"; } State { ID = "CFLAME7"; Sprite = "WCFM"; Frame = 32774; Tics = 4; Next state = "CFLAME8"; } State { ID = "CFLAME8"; Sprite = "WCFM"; Frame = 32775; Tics = 4; Next state = "CFLAME1"; } State { ID = "CFLAMEREADY1"; Sprite = "CFLM"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY2"; } State { ID = "CFLAMEREADY2"; Sprite = "CFLM"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY3"; } State { ID = "CFLAMEREADY3"; Sprite = "CFLM"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY4"; } State { ID = "CFLAMEREADY4"; Sprite = "CFLM"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY5"; } State { ID = "CFLAMEREADY5"; Sprite = "CFLM"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY6"; } State { ID = "CFLAMEREADY6"; Sprite = "CFLM"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY7"; } State { ID = "CFLAMEREADY7"; Sprite = "CFLM"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY8"; } State { ID = "CFLAMEREADY8"; Sprite = "CFLM"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY9"; } State { ID = "CFLAMEREADY9"; Sprite = "CFLM"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY10"; } State { ID = "CFLAMEREADY10"; Sprite = "CFLM"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY11"; } State { ID = "CFLAMEREADY11"; Sprite = "CFLM"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY12"; } State { ID = "CFLAMEREADY12"; Sprite = "CFLM"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "CFLAMEREADY1"; } State { ID = "CFLAMEDOWN"; Sprite = "CFLM"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "CFLAMEDOWN"; } State { ID = "CFLAMEUP"; Sprite = "CFLM"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "CFLAMEUP"; } State { ID = "CFLAMEATK_1"; Sprite = "CFLM"; Frame = 0; Tics = 2; Next state = "CFLAMEATK_2"; Misc2 = 40; } State { ID = "CFLAMEATK_2"; Sprite = "CFLM"; Frame = 3; Tics = 2; Next state = "CFLAMEATK_3"; Misc2 = 50; } State { ID = "CFLAMEATK_3"; Sprite = "CFLM"; Frame = 3; Tics = 2; Next state = "CFLAMEATK_4"; Misc2 = 36; } State { ID = "CFLAMEATK_4"; Sprite = "CFLM"; Frame = 32772; Tics = 4; Next state = "CFLAMEATK_5"; } State { ID = "CFLAMEATK_5"; Sprite = "CFLM"; Frame = 32773; Tics = 4; Action = "A_CFlameAttack"; Next state = "CFLAMEATK_6"; } State { ID = "CFLAMEATK_6"; Sprite = "CFLM"; Frame = 32772; Tics = 4; Next state = "CFLAMEATK_7"; } State { ID = "CFLAMEATK_7"; Sprite = "CFLM"; Frame = 6; Tics = 2; Next state = "CFLAMEATK_8"; Misc2 = 40; } State { ID = "CFLAMEATK_8"; Sprite = "CFLM"; Frame = 6; Tics = 2; Next state = "CFLAMEREADY1"; } State { ID = "CFLAMEFLOOR1"; Sprite = "CFFX"; Frame = 32781; Tics = 5; Next state = "CFLAMEFLOOR2"; } State { ID = "CFLAMEFLOOR2"; Sprite = "CFFX"; Frame = 32782; Tics = 4; Next state = "CFLAMEFLOOR3"; } State { ID = "CFLAMEFLOOR3"; Sprite = "CFFX"; Frame = 32783; Tics = 3; Next state = "NULL"; } State { ID = "FLAMEPUFF1"; Sprite = "CFFX"; Frame = 32768; Tics = 3; Next state = "FLAMEPUFF2"; } State { ID = "FLAMEPUFF2"; Sprite = "CFFX"; Frame = 32769; Tics = 3; Next state = "FLAMEPUFF3"; } State { ID = "FLAMEPUFF3"; Sprite = "CFFX"; Frame = 32770; Tics = 3; Next state = "FLAMEPUFF4"; } State { ID = "FLAMEPUFF4"; Sprite = "CFFX"; Frame = 32771; Tics = 4; Next state = "FLAMEPUFF5"; } State { ID = "FLAMEPUFF5"; Sprite = "CFFX"; Frame = 32772; Tics = 3; Next state = "FLAMEPUFF6"; } State { ID = "FLAMEPUFF6"; Sprite = "CFFX"; Frame = 32773; Tics = 4; Next state = "FLAMEPUFF7"; } State { ID = "FLAMEPUFF7"; Sprite = "CFFX"; Frame = 32774; Tics = 3; Next state = "FLAMEPUFF8"; } State { ID = "FLAMEPUFF8"; Sprite = "CFFX"; Frame = 32775; Tics = 4; Next state = "FLAMEPUFF9"; } State { ID = "FLAMEPUFF9"; Sprite = "CFFX"; Frame = 32776; Tics = 3; Next state = "FLAMEPUFF10"; } State { ID = "FLAMEPUFF10"; Sprite = "CFFX"; Frame = 32777; Tics = 4; Next state = "FLAMEPUFF11"; } State { ID = "FLAMEPUFF11"; Sprite = "CFFX"; Frame = 32778; Tics = 3; Next state = "FLAMEPUFF12"; } State { ID = "FLAMEPUFF12"; Sprite = "CFFX"; Frame = 32779; Tics = 4; Next state = "FLAMEPUFF13"; } State { ID = "FLAMEPUFF13"; Sprite = "CFFX"; Frame = 32780; Tics = 3; Next state = "NULL"; } State { ID = "FLAMEPUFF2_1"; Sprite = "CFFX"; Frame = 32768; Tics = 3; Next state = "FLAMEPUFF2_2"; } State { ID = "FLAMEPUFF2_2"; Sprite = "CFFX"; Frame = 32769; Tics = 3; Next state = "FLAMEPUFF2_3"; } State { ID = "FLAMEPUFF2_3"; Sprite = "CFFX"; Frame = 32770; Tics = 3; Next state = "FLAMEPUFF2_4"; } State { ID = "FLAMEPUFF2_4"; Sprite = "CFFX"; Frame = 32771; Tics = 4; Next state = "FLAMEPUFF2_5"; } State { ID = "FLAMEPUFF2_5"; Sprite = "CFFX"; Frame = 32772; Tics = 3; Next state = "FLAMEPUFF2_6"; } State { ID = "FLAMEPUFF2_6"; Sprite = "CFFX"; Frame = 32773; Tics = 4; Next state = "FLAMEPUFF2_7"; } State { ID = "FLAMEPUFF2_7"; Sprite = "CFFX"; Frame = 32774; Tics = 3; Next state = "FLAMEPUFF2_8"; } State { ID = "FLAMEPUFF2_8"; Sprite = "CFFX"; Frame = 32775; Tics = 4; Next state = "FLAMEPUFF2_9"; } State { ID = "FLAMEPUFF2_9"; Sprite = "CFFX"; Frame = 32776; Tics = 3; Next state = "FLAMEPUFF2_10"; } State { ID = "FLAMEPUFF2_10"; Sprite = "CFFX"; Frame = 32770; Tics = 3; Next state = "FLAMEPUFF2_11"; } State { ID = "FLAMEPUFF2_11"; Sprite = "CFFX"; Frame = 32771; Tics = 4; Next state = "FLAMEPUFF2_12"; } State { ID = "FLAMEPUFF2_12"; Sprite = "CFFX"; Frame = 32772; Tics = 3; Next state = "FLAMEPUFF2_13"; } State { ID = "FLAMEPUFF2_13"; Sprite = "CFFX"; Frame = 32773; Tics = 4; Next state = "FLAMEPUFF2_14"; } State { ID = "FLAMEPUFF2_14"; Sprite = "CFFX"; Frame = 32774; Tics = 3; Next state = "FLAMEPUFF2_15"; } State { ID = "FLAMEPUFF2_15"; Sprite = "CFFX"; Frame = 32775; Tics = 4; Next state = "FLAMEPUFF2_16"; } State { ID = "FLAMEPUFF2_16"; Sprite = "CFFX"; Frame = 32776; Tics = 3; Next state = "FLAMEPUFF2_17"; } State { ID = "FLAMEPUFF2_17"; Sprite = "CFFX"; Frame = 32777; Tics = 4; Next state = "FLAMEPUFF2_18"; } State { ID = "FLAMEPUFF2_18"; Sprite = "CFFX"; Frame = 32778; Tics = 3; Next state = "FLAMEPUFF2_19"; } State { ID = "FLAMEPUFF2_19"; Sprite = "CFFX"; Frame = 32779; Tics = 4; Next state = "FLAMEPUFF2_20"; } State { ID = "FLAMEPUFF2_20"; Sprite = "CFFX"; Frame = 32780; Tics = 3; Next state = "NULL"; } State { ID = "CIRCLE_FLAME1"; Sprite = "CFCF"; Frame = 32768; Tics = 4; Next state = "CIRCLE_FLAME2"; } State { ID = "CIRCLE_FLAME2"; Sprite = "CFCF"; Frame = 32769; Tics = 2; Action = "A_CFlameRotate"; Next state = "CIRCLE_FLAME3"; } State { ID = "CIRCLE_FLAME3"; Sprite = "CFCF"; Frame = 32770; Tics = 2; Next state = "CIRCLE_FLAME4"; } State { ID = "CIRCLE_FLAME4"; Sprite = "CFCF"; Frame = 32771; Tics = 1; Next state = "CIRCLE_FLAME5"; } State { ID = "CIRCLE_FLAME5"; Sprite = "CFCF"; Frame = 32772; Tics = 2; Next state = "CIRCLE_FLAME6"; } State { ID = "CIRCLE_FLAME6"; Sprite = "CFCF"; Frame = 32773; Tics = 2; Action = "A_CFlameRotate"; Next state = "CIRCLE_FLAME7"; } State { ID = "CIRCLE_FLAME7"; Sprite = "CFCF"; Frame = 32774; Tics = 1; Next state = "CIRCLE_FLAME8"; } State { ID = "CIRCLE_FLAME8"; Sprite = "CFCF"; Frame = 32775; Tics = 2; Next state = "CIRCLE_FLAME9"; } State { ID = "CIRCLE_FLAME9"; Sprite = "CFCF"; Frame = 32776; Tics = 2; Next state = "CIRCLE_FLAME10"; } State { ID = "CIRCLE_FLAME10"; Sprite = "CFCF"; Frame = 32777; Tics = 1; Action = "A_CFlameRotate"; Next state = "CIRCLE_FLAME11"; } State { ID = "CIRCLE_FLAME11"; Sprite = "CFCF"; Frame = 32778; Tics = 2; Next state = "CIRCLE_FLAME12"; } State { ID = "CIRCLE_FLAME12"; Sprite = "CFCF"; Frame = 32779; Tics = 3; Next state = "CIRCLE_FLAME13"; } State { ID = "CIRCLE_FLAME13"; Sprite = "CFCF"; Frame = 32780; Tics = 3; Next state = "CIRCLE_FLAME14"; } State { ID = "CIRCLE_FLAME14"; Sprite = "CFCF"; Frame = 32781; Tics = 2; Action = "A_CFlameRotate"; Next state = "CIRCLE_FLAME15"; } State { ID = "CIRCLE_FLAME15"; Sprite = "CFCF"; Frame = 32782; Tics = 3; Next state = "CIRCLE_FLAME16"; } State { ID = "CIRCLE_FLAME16"; Sprite = "CFCF"; Frame = 32783; Tics = 2; Next state = "NULL"; } State { ID = "CIRCLE_FLAME_X1"; Sprite = "CFCF"; Frame = 32784; Tics = 3; Next state = "CIRCLE_FLAME_X2"; } State { ID = "CIRCLE_FLAME_X2"; Sprite = "CFCF"; Frame = 32785; Tics = 3; Next state = "CIRCLE_FLAME_X3"; } State { ID = "CIRCLE_FLAME_X3"; Sprite = "CFCF"; Frame = 32786; Tics = 3; Action = "A_Explode"; Next state = "CIRCLE_FLAME_X4"; } State { ID = "CIRCLE_FLAME_X4"; Sprite = "CFCF"; Frame = 32787; Tics = 3; Next state = "CIRCLE_FLAME_X5"; } State { ID = "CIRCLE_FLAME_X5"; Sprite = "CFCF"; Frame = 32788; Tics = 3; Next state = "CIRCLE_FLAME_X6"; } State { ID = "CIRCLE_FLAME_X6"; Sprite = "CFCF"; Frame = 32789; Tics = 3; Next state = "CIRCLE_FLAME_X7"; } State { ID = "CIRCLE_FLAME_X7"; Sprite = "CFCF"; Frame = 32790; Tics = 3; Next state = "CIRCLE_FLAME_X8"; } State { ID = "CIRCLE_FLAME_X8"; Sprite = "CFCF"; Frame = 32791; Tics = 3; Next state = "CIRCLE_FLAME_X9"; } State { ID = "CIRCLE_FLAME_X9"; Sprite = "CFCF"; Frame = 32792; Tics = 3; Next state = "CIRCLE_FLAME_X10"; } State { ID = "CIRCLE_FLAME_X10"; Sprite = "CFCF"; Frame = 32793; Tics = 3; Next state = "NULL"; } State { ID = "CFLAME_MISSILE1"; Sprite = "CFFX"; Frame = 32768; Tics = 4; Next state = "CFLAME_MISSILE2"; } State { ID = "CFLAME_MISSILE2"; Sprite = "CFFX"; Frame = 0; Tics = 1; Action = "A_CFlamePuff"; Next state = "FLAMEPUFF1"; } State { ID = "CFLAME_MISSILE_X"; Sprite = "CFFX"; Frame = 32768; Tics = 1; Action = "A_CFlameMissile"; Next state = "FLAMEPUFF1"; } State { ID = "CHOLYREADY"; Sprite = "CHLY"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CHOLYREADY"; } State { ID = "CHOLYDOWN"; Sprite = "CHLY"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "CHOLYDOWN"; } State { ID = "CHOLYUP"; Sprite = "CHLY"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "CHOLYUP"; } State { ID = "CHOLYATK_1"; Sprite = "CHLY"; Frame = 32768; Tics = 1; Next state = "CHOLYATK_2"; Misc2 = 40; } State { ID = "CHOLYATK_2"; Sprite = "CHLY"; Frame = 32769; Tics = 1; Next state = "CHOLYATK_3"; Misc2 = 40; } State { ID = "CHOLYATK_3"; Sprite = "CHLY"; Frame = 32770; Tics = 2; Next state = "CHOLYATK_4"; Misc2 = 43; } State { ID = "CHOLYATK_4"; Sprite = "CHLY"; Frame = 32771; Tics = 2; Next state = "CHOLYATK_5"; Misc2 = 43; } State { ID = "CHOLYATK_5"; Sprite = "CHLY"; Frame = 32772; Tics = 2; Next state = "CHOLYATK_6"; Misc2 = 45; } State { ID = "CHOLYATK_6"; Sprite = "CHLY"; Frame = 32773; Tics = 6; Action = "A_CHolyAttack"; Next state = "CHOLYATK_7"; Misc2 = 48; } State { ID = "CHOLYATK_7"; Sprite = "CHLY"; Frame = 32774; Tics = 2; Action = "A_CHolyPalette"; Next state = "CHOLYATK_8"; Misc2 = 40; } State { ID = "CHOLYATK_8"; Sprite = "CHLY"; Frame = 32774; Tics = 2; Action = "A_CHolyPalette"; Next state = "CHOLYATK_9"; Misc2 = 40; } State { ID = "CHOLYATK_9"; Sprite = "CHLY"; Frame = 32774; Tics = 2; Action = "A_CHolyPalette"; Next state = "CHOLYREADY"; Misc2 = 36; } State { ID = "HOLY_FX1"; Sprite = "SPIR"; Frame = 32768; Tics = 2; Action = "A_CHolySeek"; Next state = "HOLY_FX2"; } State { ID = "HOLY_FX2"; Sprite = "SPIR"; Frame = 32768; Tics = 2; Action = "A_CHolySeek"; Next state = "HOLY_FX3"; } State { ID = "HOLY_FX3"; Sprite = "SPIR"; Frame = 32769; Tics = 2; Action = "A_CHolySeek"; Next state = "HOLY_FX4"; } State { ID = "HOLY_FX4"; Sprite = "SPIR"; Frame = 32769; Tics = 2; Action = "A_CHolyCheckScream"; Next state = "HOLY_FX1"; } State { ID = "HOLY_FX_X1"; Sprite = "SPIR"; Frame = 32771; Tics = 4; Next state = "HOLY_FX_X2"; } State { ID = "HOLY_FX_X2"; Sprite = "SPIR"; Frame = 32772; Tics = 4; Action = "A_Scream"; Next state = "HOLY_FX_X3"; } State { ID = "HOLY_FX_X3"; Sprite = "SPIR"; Frame = 32773; Tics = 4; Next state = "HOLY_FX_X4"; } State { ID = "HOLY_FX_X4"; Sprite = "SPIR"; Frame = 32774; Tics = 4; Next state = "HOLY_FX_X5"; } State { ID = "HOLY_FX_X5"; Sprite = "SPIR"; Frame = 32775; Tics = 4; Next state = "HOLY_FX_X6"; } State { ID = "HOLY_FX_X6"; Sprite = "SPIR"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "HOLY_TAIL1"; Sprite = "SPIR"; Frame = 2; Tics = 1; Action = "A_CHolyTail"; Next state = "HOLY_TAIL1"; } State { ID = "HOLY_TAIL2"; Sprite = "SPIR"; Frame = 3; Tics = -1; Next state = "NULL"; } State { ID = "HOLY_PUFF1"; Sprite = "SPIR"; Frame = 10; Tics = 3; Next state = "HOLY_PUFF2"; } State { ID = "HOLY_PUFF2"; Sprite = "SPIR"; Frame = 11; Tics = 3; Next state = "HOLY_PUFF3"; } State { ID = "HOLY_PUFF3"; Sprite = "SPIR"; Frame = 12; Tics = 3; Next state = "HOLY_PUFF4"; } State { ID = "HOLY_PUFF4"; Sprite = "SPIR"; Frame = 13; Tics = 3; Next state = "HOLY_PUFF5"; } State { ID = "HOLY_PUFF5"; Sprite = "SPIR"; Frame = 14; Tics = 3; Next state = "NULL"; } State { ID = "HOLY_MISSILE1"; Sprite = "SPIR"; Frame = 32783; Tics = 3; Action = "A_CHolySpawnPuff"; Next state = "HOLY_MISSILE2"; } State { ID = "HOLY_MISSILE2"; Sprite = "SPIR"; Frame = 32783; Tics = 3; Action = "A_CHolySpawnPuff"; Next state = "HOLY_MISSILE3"; } State { ID = "HOLY_MISSILE3"; Sprite = "SPIR"; Frame = 32783; Tics = 3; Action = "A_CHolySpawnPuff"; Next state = "HOLY_MISSILE4"; } State { ID = "HOLY_MISSILE4"; Sprite = "SPIR"; Frame = 32783; Tics = 3; Action = "A_CHolySpawnPuff"; Next state = "HOLY_MISSILE_X"; } State { ID = "HOLY_MISSILE_X"; Sprite = "SPIR"; Frame = 32783; Tics = 1; Action = "A_CHolyAttack2"; Next state = "NULL"; } State { ID = "HOLY_MISSILE_P1"; Sprite = "SPIR"; Frame = 16; Tics = 3; Next state = "HOLY_MISSILE_P2"; } State { ID = "HOLY_MISSILE_P2"; Sprite = "SPIR"; Frame = 17; Tics = 3; Next state = "HOLY_MISSILE_P3"; } State { ID = "HOLY_MISSILE_P3"; Sprite = "SPIR"; Frame = 18; Tics = 3; Next state = "HOLY_MISSILE_P4"; } State { ID = "HOLY_MISSILE_P4"; Sprite = "SPIR"; Frame = 19; Tics = 3; Next state = "HOLY_MISSILE_P5"; } State { ID = "HOLY_MISSILE_P5"; Sprite = "SPIR"; Frame = 20; Tics = 3; Next state = "NULL"; } State { ID = "MWANDREADY"; Sprite = "MWND"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MWANDREADY"; } State { ID = "MWANDDOWN"; Sprite = "MWND"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "MWANDDOWN"; } State { ID = "MWANDUP"; Sprite = "MWND"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "MWANDUP"; } State { ID = "MWANDATK_1"; Sprite = "MWND"; Frame = 0; Tics = 6; Next state = "MWANDATK_2"; } State { ID = "MWANDATK_2"; Sprite = "MWND"; Frame = 32769; Tics = 6; Action = "A_MWandAttack"; Next state = "MWANDATK_3"; Misc2 = 48; } State { ID = "MWANDATK_3"; Sprite = "MWND"; Frame = 0; Tics = 3; Next state = "MWANDATK_4"; Misc2 = 40; } State { ID = "MWANDATK_4"; Sprite = "MWND"; Frame = 0; Tics = 3; Action = "A_ReFire"; Next state = "MWANDREADY"; Misc2 = 36; } State { ID = "MWANDPUFF1"; Sprite = "MWND"; Frame = 32772; Tics = 4; Next state = "MWANDPUFF2"; } State { ID = "MWANDPUFF2"; Sprite = "MWND"; Frame = 32773; Tics = 3; Next state = "MWANDPUFF3"; } State { ID = "MWANDPUFF3"; Sprite = "MWND"; Frame = 32774; Tics = 4; Next state = "MWANDPUFF4"; } State { ID = "MWANDPUFF4"; Sprite = "MWND"; Frame = 32775; Tics = 3; Next state = "MWANDPUFF5"; } State { ID = "MWANDPUFF5"; Sprite = "MWND"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "MWANDSMOKE1"; Sprite = "MWND"; Frame = 2; Tics = 4; Next state = "MWANDSMOKE2"; } State { ID = "MWANDSMOKE2"; Sprite = "MWND"; Frame = 3; Tics = 4; Next state = "MWANDSMOKE3"; } State { ID = "MWANDSMOKE3"; Sprite = "MWND"; Frame = 2; Tics = 4; Next state = "MWANDSMOKE4"; } State { ID = "MWANDSMOKE4"; Sprite = "MWND"; Frame = 3; Tics = 4; Next state = "NULL"; } State { ID = "MWAND_MISSILE1"; Sprite = "MWND"; Frame = 32770; Tics = 4; Next state = "MWAND_MISSILE2"; } State { ID = "MWAND_MISSILE2"; Sprite = "MWND"; Frame = 32771; Tics = 4; Next state = "MWAND_MISSILE1"; } State { ID = "MW_LIGHTNING1"; Sprite = "WMLG"; Frame = 32768; Tics = 4; Next state = "MW_LIGHTNING2"; } State { ID = "MW_LIGHTNING2"; Sprite = "WMLG"; Frame = 32769; Tics = 4; Next state = "MW_LIGHTNING3"; } State { ID = "MW_LIGHTNING3"; Sprite = "WMLG"; Frame = 32770; Tics = 4; Next state = "MW_LIGHTNING4"; } State { ID = "MW_LIGHTNING4"; Sprite = "WMLG"; Frame = 32771; Tics = 4; Next state = "MW_LIGHTNING5"; } State { ID = "MW_LIGHTNING5"; Sprite = "WMLG"; Frame = 32772; Tics = 4; Next state = "MW_LIGHTNING6"; } State { ID = "MW_LIGHTNING6"; Sprite = "WMLG"; Frame = 32773; Tics = 4; Next state = "MW_LIGHTNING7"; } State { ID = "MW_LIGHTNING7"; Sprite = "WMLG"; Frame = 32774; Tics = 4; Next state = "MW_LIGHTNING8"; } State { ID = "MW_LIGHTNING8"; Sprite = "WMLG"; Frame = 32775; Tics = 4; Next state = "MW_LIGHTNING1"; } State { ID = "MLIGHTNINGREADY"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY2"; } State { ID = "MLIGHTNINGREADY2"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY3"; } State { ID = "MLIGHTNINGREADY3"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY4"; } State { ID = "MLIGHTNINGREADY4"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY5"; } State { ID = "MLIGHTNINGREADY5"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY6"; } State { ID = "MLIGHTNINGREADY6"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_LightningReady"; Next state = "MLIGHTNINGREADY7"; } State { ID = "MLIGHTNINGREADY7"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY8"; } State { ID = "MLIGHTNINGREADY8"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY9"; } State { ID = "MLIGHTNINGREADY9"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY10"; } State { ID = "MLIGHTNINGREADY10"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY11"; } State { ID = "MLIGHTNINGREADY11"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY12"; } State { ID = "MLIGHTNINGREADY12"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY13"; } State { ID = "MLIGHTNINGREADY13"; Sprite = "MLNG"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY14"; } State { ID = "MLIGHTNINGREADY14"; Sprite = "MLNG"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY15"; } State { ID = "MLIGHTNINGREADY15"; Sprite = "MLNG"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY16"; } State { ID = "MLIGHTNINGREADY16"; Sprite = "MLNG"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY17"; } State { ID = "MLIGHTNINGREADY17"; Sprite = "MLNG"; Frame = 32770; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY18"; } State { ID = "MLIGHTNINGREADY18"; Sprite = "MLNG"; Frame = 32770; Tics = 1; Action = "A_LightningReady"; Next state = "MLIGHTNINGREADY19"; } State { ID = "MLIGHTNINGREADY19"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY20"; } State { ID = "MLIGHTNINGREADY20"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY21"; } State { ID = "MLIGHTNINGREADY21"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY22"; } State { ID = "MLIGHTNINGREADY22"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY23"; } State { ID = "MLIGHTNINGREADY23"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY24"; } State { ID = "MLIGHTNINGREADY24"; Sprite = "MLNG"; Frame = 32769; Tics = 1; Action = "A_WeaponReady"; Next state = "MLIGHTNINGREADY"; } State { ID = "MLIGHTNINGDOWN"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_Lower"; Next state = "MLIGHTNINGDOWN"; } State { ID = "MLIGHTNINGUP"; Sprite = "MLNG"; Frame = 32768; Tics = 1; Action = "A_Raise"; Next state = "MLIGHTNINGUP"; } State { ID = "MLIGHTNINGATK_1"; Sprite = "MLNG"; Frame = 32771; Tics = 3; Next state = "MLIGHTNINGATK_2"; } State { ID = "MLIGHTNINGATK_2"; Sprite = "MLNG"; Frame = 32772; Tics = 3; Next state = "MLIGHTNINGATK_3"; } State { ID = "MLIGHTNINGATK_3"; Sprite = "MLNG"; Frame = 32773; Tics = 4; Action = "A_MLightningAttack"; Next state = "MLIGHTNINGATK_4"; } State { ID = "MLIGHTNINGATK_4"; Sprite = "MLNG"; Frame = 32774; Tics = 4; Next state = "MLIGHTNINGATK_5"; } State { ID = "MLIGHTNINGATK_5"; Sprite = "MLNG"; Frame = 32775; Tics = 3; Next state = "MLIGHTNINGATK_6"; } State { ID = "MLIGHTNINGATK_6"; Sprite = "MLNG"; Frame = 32776; Tics = 3; Next state = "MLIGHTNINGATK_7"; } State { ID = "MLIGHTNINGATK_7"; Sprite = "MLNG"; Frame = 32776; Tics = 6; Next state = "MLIGHTNINGATK_8"; Misc2 = 199; } State { ID = "MLIGHTNINGATK_8"; Sprite = "MLNG"; Frame = 32770; Tics = 2; Next state = "MLIGHTNINGATK_9"; Misc2 = 55; } State { ID = "MLIGHTNINGATK_9"; Sprite = "MLNG"; Frame = 32769; Tics = 2; Next state = "MLIGHTNINGATK_10"; Misc2 = 50; } State { ID = "MLIGHTNINGATK_10"; Sprite = "MLNG"; Frame = 32769; Tics = 2; Next state = "MLIGHTNINGATK_11"; Misc2 = 45; } State { ID = "MLIGHTNINGATK_11"; Sprite = "MLNG"; Frame = 32769; Tics = 2; Next state = "MLIGHTNINGREADY"; Misc2 = 40; } State { ID = "LIGHTNING_CEILING1"; Sprite = "MLFX"; Frame = 32768; Tics = 2; Action = "A_LightningZap"; Next state = "LIGHTNING_CEILING2"; } State { ID = "LIGHTNING_CEILING2"; Sprite = "MLFX"; Frame = 32769; Tics = 2; Action = "A_LightningClip"; Next state = "LIGHTNING_CEILING3"; } State { ID = "LIGHTNING_CEILING3"; Sprite = "MLFX"; Frame = 32770; Tics = 2; Action = "A_LightningClip"; Next state = "LIGHTNING_CEILING4"; } State { ID = "LIGHTNING_CEILING4"; Sprite = "MLFX"; Frame = 32771; Tics = 2; Action = "A_LightningClip"; Next state = "LIGHTNING_CEILING1"; } State { ID = "LIGHTNING_C_X1"; Sprite = "MLF2"; Frame = 32768; Tics = 2; Action = "A_LightningRemove"; Next state = "LIGHTNING_C_X2"; } State { ID = "LIGHTNING_C_X2"; Sprite = "MLF2"; Frame = 32769; Tics = 3; Next state = "LIGHTNING_C_X3"; } State { ID = "LIGHTNING_C_X3"; Sprite = "MLF2"; Frame = 32770; Tics = 3; Next state = "LIGHTNING_C_X4"; } State { ID = "LIGHTNING_C_X4"; Sprite = "MLF2"; Frame = 32771; Tics = 3; Next state = "LIGHTNING_C_X5"; } State { ID = "LIGHTNING_C_X5"; Sprite = "MLF2"; Frame = 32772; Tics = 3; Next state = "LIGHTNING_C_X6"; } State { ID = "LIGHTNING_C_X6"; Sprite = "MLF2"; Frame = 32778; Tics = 3; Next state = "LIGHTNING_C_X7"; } State { ID = "LIGHTNING_C_X7"; Sprite = "MLF2"; Frame = 32779; Tics = 3; Next state = "LIGHTNING_C_X8"; } State { ID = "LIGHTNING_C_X8"; Sprite = "MLF2"; Frame = 32780; Tics = 3; Next state = "LIGHTNING_C_X9"; } State { ID = "LIGHTNING_C_X9"; Sprite = "ACLO"; Frame = 4; Tics = 35; Next state = "LIGHTNING_C_X10"; } State { ID = "LIGHTNING_C_X10"; Sprite = "MLF2"; Frame = 32781; Tics = 3; Next state = "LIGHTNING_C_X11"; } State { ID = "LIGHTNING_C_X11"; Sprite = "MLF2"; Frame = 32782; Tics = 3; Next state = "LIGHTNING_C_X12"; } State { ID = "LIGHTNING_C_X12"; Sprite = "MLF2"; Frame = 32783; Tics = 4; Next state = "LIGHTNING_C_X13"; } State { ID = "LIGHTNING_C_X13"; Sprite = "MLF2"; Frame = 32784; Tics = 3; Next state = "LIGHTNING_C_X14"; } State { ID = "LIGHTNING_C_X14"; Sprite = "MLF2"; Frame = 32783; Tics = 3; Next state = "LIGHTNING_C_X15"; } State { ID = "LIGHTNING_C_X15"; Sprite = "MLF2"; Frame = 32784; Tics = 4; Next state = "LIGHTNING_C_X16"; } State { ID = "LIGHTNING_C_X16"; Sprite = "MLF2"; Frame = 32783; Tics = 3; Next state = "LIGHTNING_C_X17"; } State { ID = "LIGHTNING_C_X17"; Sprite = "MLF2"; Frame = 32782; Tics = 3; Next state = "LIGHTNING_C_X18"; } State { ID = "LIGHTNING_C_X18"; Sprite = "MLF2"; Frame = 32783; Tics = 3; Next state = "LIGHTNING_C_X19"; } State { ID = "LIGHTNING_C_X19"; Sprite = "MLF2"; Frame = 32783; Tics = 1; Action = "A_HideThing"; Next state = "FREETARGMOBJ"; } State { ID = "LIGHTNING_FLOOR1"; Sprite = "MLFX"; Frame = 32772; Tics = 2; Action = "A_LightningZap"; Next state = "LIGHTNING_FLOOR2"; } State { ID = "LIGHTNING_FLOOR2"; Sprite = "MLFX"; Frame = 32773; Tics = 2; Action = "A_LightningClip"; Next state = "LIGHTNING_FLOOR3"; } State { ID = "LIGHTNING_FLOOR3"; Sprite = "MLFX"; Frame = 32774; Tics = 2; Action = "A_LightningClip"; Next state = "LIGHTNING_FLOOR4"; } State { ID = "LIGHTNING_FLOOR4"; Sprite = "MLFX"; Frame = 32775; Tics = 2; Action = "A_LightningClip"; Next state = "LIGHTNING_FLOOR1"; } State { ID = "LIGHTNING_F_X1"; Sprite = "MLF2"; Frame = 32773; Tics = 2; Action = "A_LightningRemove"; Next state = "LIGHTNING_F_X2"; } State { ID = "LIGHTNING_F_X2"; Sprite = "MLF2"; Frame = 32774; Tics = 3; Next state = "LIGHTNING_F_X3"; } State { ID = "LIGHTNING_F_X3"; Sprite = "MLF2"; Frame = 32775; Tics = 3; Next state = "LIGHTNING_F_X4"; } State { ID = "LIGHTNING_F_X4"; Sprite = "MLF2"; Frame = 32776; Tics = 3; Next state = "LIGHTNING_F_X5"; } State { ID = "LIGHTNING_F_X5"; Sprite = "MLF2"; Frame = 32777; Tics = 3; Next state = "LIGHTNING_F_X6"; } State { ID = "LIGHTNING_F_X6"; Sprite = "MLF2"; Frame = 32778; Tics = 3; Next state = "LIGHTNING_F_X7"; } State { ID = "LIGHTNING_F_X7"; Sprite = "MLF2"; Frame = 32779; Tics = 3; Next state = "LIGHTNING_F_X8"; } State { ID = "LIGHTNING_F_X8"; Sprite = "MLF2"; Frame = 32780; Tics = 3; Next state = "LIGHTNING_F_X9"; } State { ID = "LIGHTNING_F_X9"; Sprite = "ACLO"; Frame = 4; Tics = 20; Next state = "LIGHTNING_F_X10"; } State { ID = "LIGHTNING_F_X10"; Sprite = "MLF2"; Frame = 32781; Tics = 3; Next state = "LIGHTNING_F_X11"; } State { ID = "LIGHTNING_F_X11"; Sprite = "MLF2"; Frame = 32782; Tics = 3; Next state = "LIGHTNING_F_X12"; } State { ID = "LIGHTNING_F_X12"; Sprite = "MLF2"; Frame = 32783; Tics = 4; Next state = "LIGHTNING_F_X13"; } State { ID = "LIGHTNING_F_X13"; Sprite = "MLF2"; Frame = 32784; Tics = 3; Next state = "LIGHTNING_F_X14"; } State { ID = "LIGHTNING_F_X14"; Sprite = "MLF2"; Frame = 32783; Tics = 3; Next state = "LIGHTNING_F_X15"; } State { ID = "LIGHTNING_F_X15"; Sprite = "MLF2"; Frame = 32784; Tics = 4; Action = "A_LastZap"; Next state = "LIGHTNING_F_X16"; } State { ID = "LIGHTNING_F_X16"; Sprite = "MLF2"; Frame = 32783; Tics = 3; Next state = "LIGHTNING_F_X17"; } State { ID = "LIGHTNING_F_X17"; Sprite = "MLF2"; Frame = 32782; Tics = 3; Next state = "LIGHTNING_F_X18"; } State { ID = "LIGHTNING_F_X18"; Sprite = "MLF2"; Frame = 32783; Tics = 3; Next state = "LIGHTNING_F_X19"; } State { ID = "LIGHTNING_F_X19"; Sprite = "MLF2"; Frame = 32783; Tics = 1; Action = "A_HideThing"; Next state = "FREETARGMOBJ"; } State { ID = "LIGHTNING_ZAP1"; Sprite = "MLFX"; Frame = 32776; Tics = 2; Action = "A_ZapMimic"; Next state = "LIGHTNING_ZAP2"; } State { ID = "LIGHTNING_ZAP2"; Sprite = "MLFX"; Frame = 32777; Tics = 2; Action = "A_ZapMimic"; Next state = "LIGHTNING_ZAP3"; } State { ID = "LIGHTNING_ZAP3"; Sprite = "MLFX"; Frame = 32778; Tics = 2; Action = "A_ZapMimic"; Next state = "LIGHTNING_ZAP4"; } State { ID = "LIGHTNING_ZAP4"; Sprite = "MLFX"; Frame = 32779; Tics = 2; Action = "A_ZapMimic"; Next state = "LIGHTNING_ZAP5"; } State { ID = "LIGHTNING_ZAP5"; Sprite = "MLFX"; Frame = 32780; Tics = 2; Action = "A_ZapMimic"; Next state = "LIGHTNING_ZAP1"; } State { ID = "LIGHTNING_ZAP_X1"; Sprite = "MLFX"; Frame = 32781; Tics = 2; Next state = "LIGHTNING_ZAP_X2"; } State { ID = "LIGHTNING_ZAP_X2"; Sprite = "MLFX"; Frame = 32782; Tics = 2; Next state = "LIGHTNING_ZAP_X3"; } State { ID = "LIGHTNING_ZAP_X3"; Sprite = "MLFX"; Frame = 32783; Tics = 2; Next state = "LIGHTNING_ZAP_X4"; } State { ID = "LIGHTNING_ZAP_X4"; Sprite = "MLFX"; Frame = 32784; Tics = 2; Next state = "LIGHTNING_ZAP_X5"; } State { ID = "LIGHTNING_ZAP_X5"; Sprite = "MLFX"; Frame = 32785; Tics = 2; Next state = "LIGHTNING_ZAP_X6"; } State { ID = "LIGHTNING_ZAP_X6"; Sprite = "MLFX"; Frame = 32786; Tics = 2; Next state = "LIGHTNING_ZAP_X7"; } State { ID = "LIGHTNING_ZAP_X7"; Sprite = "MLFX"; Frame = 32787; Tics = 2; Next state = "LIGHTNING_ZAP_X8"; } State { ID = "LIGHTNING_ZAP_X8"; Sprite = "MLFX"; Frame = 32788; Tics = 2; Next state = "NULL"; } State { ID = "MSTAFFREADY"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY2"; } State { ID = "MSTAFFREADY2"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY3"; } State { ID = "MSTAFFREADY3"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY4"; } State { ID = "MSTAFFREADY4"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY5"; } State { ID = "MSTAFFREADY5"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY6"; } State { ID = "MSTAFFREADY6"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY7"; } State { ID = "MSTAFFREADY7"; Sprite = "MSTF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY8"; } State { ID = "MSTAFFREADY8"; Sprite = "MSTF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY9"; } State { ID = "MSTAFFREADY9"; Sprite = "MSTF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY10"; } State { ID = "MSTAFFREADY10"; Sprite = "MSTF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY11"; } State { ID = "MSTAFFREADY11"; Sprite = "MSTF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY12"; } State { ID = "MSTAFFREADY12"; Sprite = "MSTF"; Frame = 1; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY13"; } State { ID = "MSTAFFREADY13"; Sprite = "MSTF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY14"; } State { ID = "MSTAFFREADY14"; Sprite = "MSTF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY15"; } State { ID = "MSTAFFREADY15"; Sprite = "MSTF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY16"; } State { ID = "MSTAFFREADY16"; Sprite = "MSTF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY17"; } State { ID = "MSTAFFREADY17"; Sprite = "MSTF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY18"; } State { ID = "MSTAFFREADY18"; Sprite = "MSTF"; Frame = 2; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY19"; } State { ID = "MSTAFFREADY19"; Sprite = "MSTF"; Frame = 3; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY20"; } State { ID = "MSTAFFREADY20"; Sprite = "MSTF"; Frame = 3; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY21"; } State { ID = "MSTAFFREADY21"; Sprite = "MSTF"; Frame = 3; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY22"; } State { ID = "MSTAFFREADY22"; Sprite = "MSTF"; Frame = 3; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY23"; } State { ID = "MSTAFFREADY23"; Sprite = "MSTF"; Frame = 3; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY24"; } State { ID = "MSTAFFREADY24"; Sprite = "MSTF"; Frame = 3; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY25"; } State { ID = "MSTAFFREADY25"; Sprite = "MSTF"; Frame = 4; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY26"; } State { ID = "MSTAFFREADY26"; Sprite = "MSTF"; Frame = 4; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY27"; } State { ID = "MSTAFFREADY27"; Sprite = "MSTF"; Frame = 4; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY28"; } State { ID = "MSTAFFREADY28"; Sprite = "MSTF"; Frame = 4; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY29"; } State { ID = "MSTAFFREADY29"; Sprite = "MSTF"; Frame = 4; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY30"; } State { ID = "MSTAFFREADY30"; Sprite = "MSTF"; Frame = 4; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY31"; } State { ID = "MSTAFFREADY31"; Sprite = "MSTF"; Frame = 5; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY32"; } State { ID = "MSTAFFREADY32"; Sprite = "MSTF"; Frame = 5; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY33"; } State { ID = "MSTAFFREADY33"; Sprite = "MSTF"; Frame = 5; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY34"; } State { ID = "MSTAFFREADY34"; Sprite = "MSTF"; Frame = 5; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY35"; } State { ID = "MSTAFFREADY35"; Sprite = "MSTF"; Frame = 5; Tics = 1; Action = "A_WeaponReady"; Next state = "MSTAFFREADY"; } State { ID = "MSTAFFDOWN"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "MSTAFFDOWN"; } State { ID = "MSTAFFUP"; Sprite = "MSTF"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "MSTAFFUP"; } State { ID = "MSTAFFATK_1"; Sprite = "MSTF"; Frame = 6; Tics = 4; Next state = "MSTAFFATK_2"; Misc2 = 40; } State { ID = "MSTAFFATK_2"; Sprite = "MSTF"; Frame = 32775; Tics = 4; Action = "A_MStaffAttack"; Next state = "MSTAFFATK_3"; Misc2 = 48; } State { ID = "MSTAFFATK_3"; Sprite = "MSTF"; Frame = 32775; Tics = 2; Action = "A_MStaffPalette"; Next state = "MSTAFFATK_4"; Misc2 = 48; } State { ID = "MSTAFFATK_4"; Sprite = "MSTF"; Frame = 8; Tics = 2; Action = "A_MStaffPalette"; Next state = "MSTAFFATK_5"; Misc2 = 48; } State { ID = "MSTAFFATK_5"; Sprite = "MSTF"; Frame = 8; Tics = 2; Action = "A_MStaffPalette"; Next state = "MSTAFFATK_6"; Misc2 = 48; } State { ID = "MSTAFFATK_6"; Sprite = "MSTF"; Frame = 8; Tics = 1; Next state = "MSTAFFATK_7"; Misc2 = 40; } State { ID = "MSTAFFATK_7"; Sprite = "MSTF"; Frame = 9; Tics = 5; Next state = "MSTAFFREADY"; Misc2 = 36; } State { ID = "MSTAFF_FX1_1"; Sprite = "MSP1"; Frame = 32768; Tics = 3; Action = "A_MStaffWeave"; Next state = "MSTAFF_FX1_2"; } State { ID = "MSTAFF_FX1_2"; Sprite = "MSP1"; Frame = 32769; Tics = 3; Action = "A_MStaffWeave"; Next state = "MSTAFF_FX1_3"; } State { ID = "MSTAFF_FX1_3"; Sprite = "MSP1"; Frame = 32770; Tics = 3; Action = "A_MStaffWeave"; Next state = "MSTAFF_FX1_4"; } State { ID = "MSTAFF_FX1_4"; Sprite = "MSP1"; Frame = 32771; Tics = 3; Action = "A_MStaffWeave"; Next state = "MSTAFF_FX1_5"; } State { ID = "MSTAFF_FX1_5"; Sprite = "MSP1"; Frame = 32772; Tics = 3; Action = "A_MStaffWeave"; Next state = "MSTAFF_FX1_6"; } State { ID = "MSTAFF_FX1_6"; Sprite = "MSP1"; Frame = 32773; Tics = 3; Action = "A_MStaffWeave"; Next state = "MSTAFF_FX1_1"; } State { ID = "MSTAFF_FX_X1"; Sprite = "MSP1"; Frame = 32774; Tics = 4; Next state = "MSTAFF_FX_X2"; } State { ID = "MSTAFF_FX_X2"; Sprite = "MSP1"; Frame = 32775; Tics = 5; Action = "A_Explode"; Next state = "MSTAFF_FX_X3"; } State { ID = "MSTAFF_FX_X3"; Sprite = "MSP1"; Frame = 32776; Tics = 4; Next state = "MSTAFF_FX_X4"; } State { ID = "MSTAFF_FX_X4"; Sprite = "MSP1"; Frame = 32777; Tics = 5; Next state = "MSTAFF_FX_X5"; } State { ID = "MSTAFF_FX_X5"; Sprite = "MSP1"; Frame = 32778; Tics = 4; Next state = "MSTAFF_FX_X6"; } State { ID = "MSTAFF_FX_X6"; Sprite = "MSP1"; Frame = 32779; Tics = 5; Next state = "MSTAFF_FX_X7"; } State { ID = "MSTAFF_FX_X7"; Sprite = "MSP1"; Frame = 32780; Tics = 4; Next state = "MSTAFF_FX_X8"; } State { ID = "MSTAFF_FX_X8"; Sprite = "MSP1"; Frame = 32781; Tics = 5; Next state = "MSTAFF_FX_X9"; } State { ID = "MSTAFF_FX_X9"; Sprite = "MSP1"; Frame = 32782; Tics = 4; Next state = "MSTAFF_FX_X10"; } State { ID = "MSTAFF_FX_X10"; Sprite = "MSP1"; Frame = 32783; Tics = 4; Next state = "NULL"; } State { ID = "MSTAFF_FX2_1"; Sprite = "MSP2"; Frame = 32768; Tics = 2; Action = "A_MStaffTrack"; Next state = "MSTAFF_FX2_2"; } State { ID = "MSTAFF_FX2_2"; Sprite = "MSP2"; Frame = 32769; Tics = 2; Action = "A_MStaffTrack"; Next state = "MSTAFF_FX2_3"; } State { ID = "MSTAFF_FX2_3"; Sprite = "MSP2"; Frame = 32770; Tics = 2; Action = "A_MStaffTrack"; Next state = "MSTAFF_FX2_4"; } State { ID = "MSTAFF_FX2_4"; Sprite = "MSP2"; Frame = 32771; Tics = 2; Action = "A_MStaffTrack"; Next state = "MSTAFF_FX2_1"; } State { ID = "MSTAFF_FX2_X1"; Sprite = "MSP2"; Frame = 32772; Tics = 4; Next state = "MSTAFF_FX2_X2"; } State { ID = "MSTAFF_FX2_X2"; Sprite = "MSP2"; Frame = 32773; Tics = 5; Action = "A_Explode"; Next state = "MSTAFF_FX2_X3"; } State { ID = "MSTAFF_FX2_X3"; Sprite = "MSP2"; Frame = 32774; Tics = 5; Next state = "MSTAFF_FX2_X4"; } State { ID = "MSTAFF_FX2_X4"; Sprite = "MSP2"; Frame = 32775; Tics = 5; Next state = "MSTAFF_FX2_X5"; } State { ID = "MSTAFF_FX2_X5"; Sprite = "MSP2"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "FSWORD1"; Sprite = "WFR1"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "FSWORD2"; Sprite = "WFR2"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "FSWORD3"; Sprite = "WFR3"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "CHOLY1"; Sprite = "WCH1"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "CHOLY2"; Sprite = "WCH2"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "CHOLY3"; Sprite = "WCH3"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "MSTAFF1"; Sprite = "WMS1"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "MSTAFF2"; Sprite = "WMS2"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "MSTAFF3"; Sprite = "WMS3"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "SNOUTREADY"; Sprite = "WPIG"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "SNOUTREADY"; } State { ID = "SNOUTDOWN"; Sprite = "WPIG"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "SNOUTDOWN"; } State { ID = "SNOUTUP"; Sprite = "WPIG"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "SNOUTUP"; } State { ID = "SNOUTATK1"; Sprite = "WPIG"; Frame = 0; Tics = 4; Action = "A_SnoutAttack"; Next state = "SNOUTATK2"; } State { ID = "SNOUTATK2"; Sprite = "WPIG"; Frame = 1; Tics = 8; Action = "A_SnoutAttack"; Next state = "SNOUTREADY"; } State { ID = "COS1"; Sprite = "WMCS"; Frame = 32768; Tics = 8; Next state = "COS2"; } State { ID = "COS2"; Sprite = "WMCS"; Frame = 32769; Tics = 8; Next state = "COS3"; } State { ID = "COS3"; Sprite = "WMCS"; Frame = 32770; Tics = 8; Next state = "COS1"; } State { ID = "CONEREADY"; Sprite = "CONE"; Frame = 0; Tics = 1; Action = "A_WeaponReady"; Next state = "CONEREADY"; } State { ID = "CONEDOWN"; Sprite = "CONE"; Frame = 0; Tics = 1; Action = "A_Lower"; Next state = "CONEDOWN"; } State { ID = "CONEUP"; Sprite = "CONE"; Frame = 0; Tics = 1; Action = "A_Raise"; Next state = "CONEUP"; } State { ID = "CONEATK1_1"; Sprite = "CONE"; Frame = 1; Tics = 3; Next state = "CONEATK1_2"; } State { ID = "CONEATK1_2"; Sprite = "CONE"; Frame = 2; Tics = 4; Next state = "CONEATK1_3"; } State { ID = "CONEATK1_3"; Sprite = "CONE"; Frame = 3; Tics = 3; Next state = "CONEATK1_4"; } State { ID = "CONEATK1_4"; Sprite = "CONE"; Frame = 4; Tics = 5; Next state = "CONEATK1_5"; } State { ID = "CONEATK1_5"; Sprite = "CONE"; Frame = 5; Tics = 3; Action = "A_FireConePL1"; Next state = "CONEATK1_6"; } State { ID = "CONEATK1_6"; Sprite = "CONE"; Frame = 6; Tics = 3; Next state = "CONEATK1_7"; } State { ID = "CONEATK1_7"; Sprite = "CONE"; Frame = 0; Tics = 9; Next state = "CONEATK1_8"; } State { ID = "CONEATK1_8"; Sprite = "CONE"; Frame = 0; Tics = 10; Action = "A_ReFire"; Next state = "CONEREADY"; } State { ID = "SHARDFX1_1"; Sprite = "SHRD"; Frame = 32768; Tics = 2; Next state = "SHARDFX1_2"; } State { ID = "SHARDFX1_2"; Sprite = "SHRD"; Frame = 32768; Tics = 3; Action = "A_ShedShard"; Next state = "SHARDFX1_3"; } State { ID = "SHARDFX1_3"; Sprite = "SHRD"; Frame = 32769; Tics = 3; Next state = "SHARDFX1_4"; } State { ID = "SHARDFX1_4"; Sprite = "SHRD"; Frame = 32770; Tics = 3; Next state = "SHARDFX1_1"; } State { ID = "SHARDFXE1_1"; Sprite = "SHEX"; Frame = 32768; Tics = 5; Next state = "SHARDFXE1_2"; } State { ID = "SHARDFXE1_2"; Sprite = "SHEX"; Frame = 32769; Tics = 5; Next state = "SHARDFXE1_3"; } State { ID = "SHARDFXE1_3"; Sprite = "SHEX"; Frame = 32770; Tics = 5; Next state = "SHARDFXE1_4"; } State { ID = "SHARDFXE1_4"; Sprite = "SHEX"; Frame = 32771; Tics = 5; Next state = "SHARDFXE1_5"; } State { ID = "SHARDFXE1_5"; Sprite = "SHEX"; Frame = 32772; Tics = 5; Next state = "NULL"; } State { ID = "BLOOD1"; Sprite = "BLOD"; Frame = 2; Tics = 8; Next state = "BLOOD2"; } State { ID = "BLOOD2"; Sprite = "BLOD"; Frame = 1; Tics = 8; Next state = "BLOOD3"; } State { ID = "BLOOD3"; Sprite = "BLOD"; Frame = 0; Tics = 8; Next state = "NULL"; } State { ID = "BLOODSPLATTER1"; Sprite = "BLOD"; Frame = 2; Tics = 8; Next state = "BLOODSPLATTER2"; } State { ID = "BLOODSPLATTER2"; Sprite = "BLOD"; Frame = 1; Tics = 8; Next state = "BLOODSPLATTER3"; } State { ID = "BLOODSPLATTER3"; Sprite = "BLOD"; Frame = 0; Tics = 8; Next state = "NULL"; } State { ID = "BLOODSPLATTERX"; Sprite = "BLOD"; Frame = 0; Tics = 6; Next state = "NULL"; } State { ID = "GIBS1"; Sprite = "GIBS"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FPLAY"; Sprite = "PLAY"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "FPLAY_RUN1"; Sprite = "PLAY"; Frame = 0; Tics = 4; Next state = "FPLAY_RUN2"; } State { ID = "FPLAY_RUN2"; Sprite = "PLAY"; Frame = 1; Tics = 4; Next state = "FPLAY_RUN3"; } State { ID = "FPLAY_RUN3"; Sprite = "PLAY"; Frame = 2; Tics = 4; Next state = "FPLAY_RUN4"; } State { ID = "FPLAY_RUN4"; Sprite = "PLAY"; Frame = 3; Tics = 4; Next state = "FPLAY_RUN1"; } State { ID = "FPLAY_ATK1"; Sprite = "PLAY"; Frame = 4; Tics = 8; Next state = "FPLAY_ATK2"; } State { ID = "FPLAY_ATK2"; Sprite = "PLAY"; Frame = 5; Tics = 8; Next state = "FPLAY"; } State { ID = "FPLAY_PAIN"; Sprite = "PLAY"; Frame = 6; Tics = 4; Next state = "FPLAY_PAIN2"; } State { ID = "FPLAY_PAIN2"; Sprite = "PLAY"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "FPLAY"; } State { ID = "FPLAY_DIE1"; Sprite = "PLAY"; Frame = 7; Tics = 6; Next state = "FPLAY_DIE2"; } State { ID = "FPLAY_DIE2"; Sprite = "PLAY"; Frame = 8; Tics = 6; Action = "A_Scream"; Next state = "FPLAY_DIE3"; } State { ID = "FPLAY_DIE3"; Sprite = "PLAY"; Frame = 9; Tics = 6; Next state = "FPLAY_DIE4"; } State { ID = "FPLAY_DIE4"; Sprite = "PLAY"; Frame = 10; Tics = 6; Next state = "FPLAY_DIE5"; } State { ID = "FPLAY_DIE5"; Sprite = "PLAY"; Frame = 11; Tics = 6; Action = "A_NoBlocking"; Next state = "FPLAY_DIE6"; } State { ID = "FPLAY_DIE6"; Sprite = "PLAY"; Frame = 12; Tics = 6; Next state = "FPLAY_DIE7"; } State { ID = "FPLAY_DIE7"; Sprite = "PLAY"; Frame = 13; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "FPLAY_XDIE1"; Sprite = "PLAY"; Frame = 14; Tics = 5; Action = "A_Scream"; Next state = "FPLAY_XDIE2"; } State { ID = "FPLAY_XDIE2"; Sprite = "PLAY"; Frame = 15; Tics = 5; Action = "A_SkullPop"; Next state = "FPLAY_XDIE3"; } State { ID = "FPLAY_XDIE3"; Sprite = "PLAY"; Frame = 17; Tics = 5; Action = "A_NoBlocking"; Next state = "FPLAY_XDIE4"; } State { ID = "FPLAY_XDIE4"; Sprite = "PLAY"; Frame = 18; Tics = 5; Next state = "FPLAY_XDIE5"; } State { ID = "FPLAY_XDIE5"; Sprite = "PLAY"; Frame = 19; Tics = 5; Next state = "FPLAY_XDIE6"; } State { ID = "FPLAY_XDIE6"; Sprite = "PLAY"; Frame = 20; Tics = 5; Next state = "FPLAY_XDIE7"; } State { ID = "FPLAY_XDIE7"; Sprite = "PLAY"; Frame = 21; Tics = 5; Next state = "FPLAY_XDIE8"; } State { ID = "FPLAY_XDIE8"; Sprite = "PLAY"; Frame = 22; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "FPLAY_ICE"; Sprite = "PLAY"; Frame = 23; Tics = 5; Action = "A_FreezeDeath"; Next state = "FPLAY_ICE2"; } State { ID = "FPLAY_ICE2"; Sprite = "PLAY"; Frame = 23; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "FPLAY_ICE2"; } State { ID = "PLAY_F_FDTH1"; Sprite = "FDTH"; Frame = 32768; Tics = 5; Next state = "PLAY_F_FDTH2"; } State { ID = "PLAY_F_FDTH2"; Sprite = "FDTH"; Frame = 32769; Tics = 4; Next state = "PLAY_FDTH3"; } State { ID = "PLAY_C_FDTH1"; Sprite = "FDTH"; Frame = 32770; Tics = 5; Next state = "PLAY_C_FDTH2"; } State { ID = "PLAY_C_FDTH2"; Sprite = "FDTH"; Frame = 32771; Tics = 4; Next state = "PLAY_FDTH3"; } State { ID = "PLAY_M_FDTH1"; Sprite = "FDTH"; Frame = 32772; Tics = 5; Next state = "PLAY_M_FDTH2"; } State { ID = "PLAY_M_FDTH2"; Sprite = "FDTH"; Frame = 32773; Tics = 4; Next state = "PLAY_FDTH3"; } State { ID = "PLAY_FDTH3"; Sprite = "FDTH"; Frame = 32774; Tics = 5; Next state = "PLAY_FDTH4"; } State { ID = "PLAY_FDTH4"; Sprite = "FDTH"; Frame = 32775; Tics = 4; Action = "A_Scream"; Next state = "PLAY_FDTH5"; } State { ID = "PLAY_FDTH5"; Sprite = "FDTH"; Frame = 32776; Tics = 5; Next state = "PLAY_FDTH6"; } State { ID = "PLAY_FDTH6"; Sprite = "FDTH"; Frame = 32777; Tics = 4; Next state = "PLAY_FDTH7"; } State { ID = "PLAY_FDTH7"; Sprite = "FDTH"; Frame = 32778; Tics = 5; Next state = "PLAY_FDTH8"; } State { ID = "PLAY_FDTH8"; Sprite = "FDTH"; Frame = 32779; Tics = 4; Next state = "PLAY_FDTH9"; } State { ID = "PLAY_FDTH9"; Sprite = "FDTH"; Frame = 32780; Tics = 5; Next state = "PLAY_FDTH10"; } State { ID = "PLAY_FDTH10"; Sprite = "FDTH"; Frame = 32781; Tics = 4; Next state = "PLAY_FDTH11"; } State { ID = "PLAY_FDTH11"; Sprite = "FDTH"; Frame = 32782; Tics = 5; Next state = "PLAY_FDTH12"; } State { ID = "PLAY_FDTH12"; Sprite = "FDTH"; Frame = 32783; Tics = 4; Next state = "PLAY_FDTH13"; } State { ID = "PLAY_FDTH13"; Sprite = "FDTH"; Frame = 32784; Tics = 5; Next state = "PLAY_FDTH14"; } State { ID = "PLAY_FDTH14"; Sprite = "FDTH"; Frame = 32785; Tics = 4; Next state = "PLAY_FDTH15"; } State { ID = "PLAY_FDTH15"; Sprite = "FDTH"; Frame = 32786; Tics = 5; Action = "A_NoBlocking"; Next state = "PLAY_FDTH16"; } State { ID = "PLAY_FDTH16"; Sprite = "FDTH"; Frame = 32787; Tics = 4; Next state = "PLAY_FDTH17"; } State { ID = "PLAY_FDTH17"; Sprite = "FDTH"; Frame = 32788; Tics = 5; Next state = "PLAY_FDTH18"; } State { ID = "PLAY_FDTH18"; Sprite = "FDTH"; Frame = 32789; Tics = 4; Next state = "PLAY_FDTH19"; } State { ID = "PLAY_FDTH19"; Sprite = "ACLO"; Frame = 4; Tics = 35; Action = "A_CheckBurnGone"; Next state = "PLAY_FDTH19"; } State { ID = "PLAY_FDTH20"; Sprite = "ACLO"; Frame = 4; Tics = 8; Next state = "NULL"; } State { ID = "BLOODYSKULL1"; Sprite = "BSKL"; Frame = 0; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL2"; } State { ID = "BLOODYSKULL2"; Sprite = "BSKL"; Frame = 1; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL3"; } State { ID = "BLOODYSKULL3"; Sprite = "BSKL"; Frame = 2; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL4"; } State { ID = "BLOODYSKULL4"; Sprite = "BSKL"; Frame = 3; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL5"; } State { ID = "BLOODYSKULL5"; Sprite = "BSKL"; Frame = 5; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL6"; } State { ID = "BLOODYSKULL6"; Sprite = "BSKL"; Frame = 6; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL7"; } State { ID = "BLOODYSKULL7"; Sprite = "BSKL"; Frame = 7; Tics = 5; Action = "A_CheckSkullFloor"; Next state = "BLOODYSKULL1"; } State { ID = "BLOODYSKULLX1"; Sprite = "BSKL"; Frame = 8; Tics = 16; Action = "A_CheckSkullDone"; Next state = "BLOODYSKULLX1"; } State { ID = "BLOODYSKULLX2"; Sprite = "BSKL"; Frame = 8; Tics = 1050; Next state = "NULL"; } State { ID = "PLAYER_SPEED1"; Sprite = "PLAY"; Frame = 0; Tics = 5; Next state = "PLAYER_SPEED2"; } State { ID = "PLAYER_SPEED2"; Sprite = "PLAY"; Frame = 0; Tics = 3; Action = "A_SpeedFade"; Next state = "NULL"; } State { ID = "ICECHUNK1"; Sprite = "ICEC"; Frame = 0; Tics = 10; Next state = "ICECHUNK2"; } State { ID = "ICECHUNK2"; Sprite = "ICEC"; Frame = 1; Tics = 10; Action = "A_IceSetTics"; Next state = "ICECHUNK3"; } State { ID = "ICECHUNK3"; Sprite = "ICEC"; Frame = 2; Tics = 10; Action = "A_IceSetTics"; Next state = "ICECHUNK4"; } State { ID = "ICECHUNK4"; Sprite = "ICEC"; Frame = 3; Tics = 10; Action = "A_IceSetTics"; Next state = "NULL"; } State { ID = "ICECHUNK_HEAD"; Sprite = "ICEC"; Frame = 0; Tics = 10; Action = "A_IceCheckHeadDone"; Next state = "ICECHUNK_HEAD"; } State { ID = "ICECHUNK_HEAD2"; Sprite = "ICEC"; Frame = 0; Tics = 1050; Next state = "NULL"; } State { ID = "CPLAY"; Sprite = "CLER"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "CPLAY_RUN1"; Sprite = "CLER"; Frame = 0; Tics = 4; Next state = "CPLAY_RUN2"; } State { ID = "CPLAY_RUN2"; Sprite = "CLER"; Frame = 1; Tics = 4; Next state = "CPLAY_RUN3"; } State { ID = "CPLAY_RUN3"; Sprite = "CLER"; Frame = 2; Tics = 4; Next state = "CPLAY_RUN4"; } State { ID = "CPLAY_RUN4"; Sprite = "CLER"; Frame = 3; Tics = 4; Next state = "CPLAY_RUN1"; } State { ID = "CPLAY_ATK1"; Sprite = "CLER"; Frame = 4; Tics = 6; Next state = "CPLAY_ATK2"; } State { ID = "CPLAY_ATK2"; Sprite = "CLER"; Frame = 5; Tics = 6; Next state = "CPLAY_ATK3"; } State { ID = "CPLAY_ATK3"; Sprite = "CLER"; Frame = 6; Tics = 6; Next state = "CPLAY"; } State { ID = "CPLAY_PAIN"; Sprite = "CLER"; Frame = 7; Tics = 4; Next state = "CPLAY_PAIN2"; } State { ID = "CPLAY_PAIN2"; Sprite = "CLER"; Frame = 7; Tics = 4; Action = "A_Pain"; Next state = "CPLAY"; } State { ID = "CPLAY_DIE1"; Sprite = "CLER"; Frame = 8; Tics = 6; Next state = "CPLAY_DIE2"; } State { ID = "CPLAY_DIE2"; Sprite = "CLER"; Frame = 10; Tics = 6; Action = "A_Scream"; Next state = "CPLAY_DIE3"; } State { ID = "CPLAY_DIE3"; Sprite = "CLER"; Frame = 11; Tics = 6; Next state = "CPLAY_DIE4"; } State { ID = "CPLAY_DIE4"; Sprite = "CLER"; Frame = 11; Tics = 6; Next state = "CPLAY_DIE5"; } State { ID = "CPLAY_DIE5"; Sprite = "CLER"; Frame = 12; Tics = 6; Action = "A_NoBlocking"; Next state = "CPLAY_DIE6"; } State { ID = "CPLAY_DIE6"; Sprite = "CLER"; Frame = 13; Tics = 6; Next state = "CPLAY_DIE7"; } State { ID = "CPLAY_DIE7"; Sprite = "CLER"; Frame = 14; Tics = 6; Next state = "CPLAY_DIE8"; } State { ID = "CPLAY_DIE8"; Sprite = "CLER"; Frame = 15; Tics = 6; Next state = "CPLAY_DIE9"; } State { ID = "CPLAY_DIE9"; Sprite = "CLER"; Frame = 16; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "CPLAY_XDIE1"; Sprite = "CLER"; Frame = 17; Tics = 5; Action = "A_Scream"; Next state = "CPLAY_XDIE2"; } State { ID = "CPLAY_XDIE2"; Sprite = "CLER"; Frame = 18; Tics = 5; Next state = "CPLAY_XDIE3"; } State { ID = "CPLAY_XDIE3"; Sprite = "CLER"; Frame = 19; Tics = 5; Action = "A_NoBlocking"; Next state = "CPLAY_XDIE4"; } State { ID = "CPLAY_XDIE4"; Sprite = "CLER"; Frame = 20; Tics = 5; Next state = "CPLAY_XDIE5"; } State { ID = "CPLAY_XDIE5"; Sprite = "CLER"; Frame = 21; Tics = 5; Next state = "CPLAY_XDIE6"; } State { ID = "CPLAY_XDIE6"; Sprite = "CLER"; Frame = 22; Tics = 5; Next state = "CPLAY_XDIE7"; } State { ID = "CPLAY_XDIE7"; Sprite = "CLER"; Frame = 23; Tics = 5; Next state = "CPLAY_XDIE8"; } State { ID = "CPLAY_XDIE8"; Sprite = "CLER"; Frame = 24; Tics = 5; Next state = "CPLAY_XDIE9"; } State { ID = "CPLAY_XDIE9"; Sprite = "CLER"; Frame = 25; Tics = 5; Next state = "CPLAY_XDIE10"; } State { ID = "CPLAY_XDIE10"; Sprite = "CLER"; Frame = 26; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "CPLAY_ICE"; Sprite = "CLER"; Frame = 27; Tics = 5; Action = "A_FreezeDeath"; Next state = "CPLAY_ICE2"; } State { ID = "CPLAY_ICE2"; Sprite = "CLER"; Frame = 27; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "CPLAY_ICE2"; } State { ID = "MPLAY"; Sprite = "MAGE"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MPLAY_RUN1"; Sprite = "MAGE"; Frame = 0; Tics = 4; Next state = "MPLAY_RUN2"; } State { ID = "MPLAY_RUN2"; Sprite = "MAGE"; Frame = 1; Tics = 4; Next state = "MPLAY_RUN3"; } State { ID = "MPLAY_RUN3"; Sprite = "MAGE"; Frame = 2; Tics = 4; Next state = "MPLAY_RUN4"; } State { ID = "MPLAY_RUN4"; Sprite = "MAGE"; Frame = 3; Tics = 4; Next state = "MPLAY_RUN1"; } State { ID = "MPLAY_ATK1"; Sprite = "MAGE"; Frame = 4; Tics = 8; Next state = "MPLAY_ATK2"; } State { ID = "MPLAY_ATK2"; Sprite = "MAGE"; Frame = 32773; Tics = 8; Next state = "MPLAY"; } State { ID = "MPLAY_PAIN"; Sprite = "MAGE"; Frame = 6; Tics = 4; Next state = "MPLAY_PAIN2"; } State { ID = "MPLAY_PAIN2"; Sprite = "MAGE"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "MPLAY"; } State { ID = "MPLAY_DIE1"; Sprite = "MAGE"; Frame = 7; Tics = 6; Next state = "MPLAY_DIE2"; } State { ID = "MPLAY_DIE2"; Sprite = "MAGE"; Frame = 8; Tics = 6; Action = "A_Scream"; Next state = "MPLAY_DIE3"; } State { ID = "MPLAY_DIE3"; Sprite = "MAGE"; Frame = 9; Tics = 6; Next state = "MPLAY_DIE4"; } State { ID = "MPLAY_DIE4"; Sprite = "MAGE"; Frame = 10; Tics = 6; Next state = "MPLAY_DIE5"; } State { ID = "MPLAY_DIE5"; Sprite = "MAGE"; Frame = 11; Tics = 6; Action = "A_NoBlocking"; Next state = "MPLAY_DIE6"; } State { ID = "MPLAY_DIE6"; Sprite = "MAGE"; Frame = 12; Tics = 6; Next state = "MPLAY_DIE7"; } State { ID = "MPLAY_DIE7"; Sprite = "MAGE"; Frame = 13; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "MPLAY_XDIE1"; Sprite = "MAGE"; Frame = 14; Tics = 5; Action = "A_Scream"; Next state = "MPLAY_XDIE2"; } State { ID = "MPLAY_XDIE2"; Sprite = "MAGE"; Frame = 15; Tics = 5; Next state = "MPLAY_XDIE3"; } State { ID = "MPLAY_XDIE3"; Sprite = "MAGE"; Frame = 17; Tics = 5; Action = "A_NoBlocking"; Next state = "MPLAY_XDIE4"; } State { ID = "MPLAY_XDIE4"; Sprite = "MAGE"; Frame = 18; Tics = 5; Next state = "MPLAY_XDIE5"; } State { ID = "MPLAY_XDIE5"; Sprite = "MAGE"; Frame = 19; Tics = 5; Next state = "MPLAY_XDIE6"; } State { ID = "MPLAY_XDIE6"; Sprite = "MAGE"; Frame = 20; Tics = 5; Next state = "MPLAY_XDIE7"; } State { ID = "MPLAY_XDIE7"; Sprite = "MAGE"; Frame = 21; Tics = 5; Next state = "MPLAY_XDIE8"; } State { ID = "MPLAY_XDIE8"; Sprite = "MAGE"; Frame = 22; Tics = 5; Next state = "MPLAY_XDIE9"; } State { ID = "MPLAY_XDIE9"; Sprite = "MAGE"; Frame = 23; Tics = -1; Action = "A_AddPlayerCorpse"; Next state = "NULL"; } State { ID = "MPLAY_ICE"; Sprite = "MAGE"; Frame = 24; Tics = 5; Action = "A_FreezeDeath"; Next state = "MPLAY_ICE2"; } State { ID = "MPLAY_ICE2"; Sprite = "MAGE"; Frame = 24; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "MPLAY_ICE2"; } State { ID = "PIGPLAY"; Sprite = "PIGY"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "PIGPLAY_RUN1"; Sprite = "PIGY"; Frame = 0; Tics = 3; Next state = "PIGPLAY_RUN2"; } State { ID = "PIGPLAY_RUN2"; Sprite = "PIGY"; Frame = 1; Tics = 3; Next state = "PIGPLAY_RUN3"; } State { ID = "PIGPLAY_RUN3"; Sprite = "PIGY"; Frame = 2; Tics = 3; Next state = "PIGPLAY_RUN4"; } State { ID = "PIGPLAY_RUN4"; Sprite = "PIGY"; Frame = 3; Tics = 3; Next state = "PIGPLAY_RUN1"; } State { ID = "PIGPLAY_ATK1"; Sprite = "PIGY"; Frame = 0; Tics = 12; Next state = "PIGPLAY"; } State { ID = "PIGPLAY_PAIN"; Sprite = "PIGY"; Frame = 3; Tics = 4; Action = "A_PigPain"; Next state = "PIGPLAY"; } State { ID = "PIG_LOOK1"; Sprite = "PIGY"; Frame = 1; Tics = 10; Action = "A_PigLook"; Next state = "PIG_LOOK1"; } State { ID = "PIG_WALK1"; Sprite = "PIGY"; Frame = 0; Tics = 3; Action = "A_PigChase"; Next state = "PIG_WALK2"; } State { ID = "PIG_WALK2"; Sprite = "PIGY"; Frame = 1; Tics = 3; Action = "A_PigChase"; Next state = "PIG_WALK3"; } State { ID = "PIG_WALK3"; Sprite = "PIGY"; Frame = 2; Tics = 3; Action = "A_PigChase"; Next state = "PIG_WALK4"; } State { ID = "PIG_WALK4"; Sprite = "PIGY"; Frame = 3; Tics = 3; Action = "A_PigChase"; Next state = "PIG_WALK1"; } State { ID = "PIG_PAIN"; Sprite = "PIGY"; Frame = 3; Tics = 4; Action = "A_PigPain"; Next state = "PIG_WALK1"; } State { ID = "PIG_ATK1"; Sprite = "PIGY"; Frame = 0; Tics = 5; Action = "A_FaceTarget"; Next state = "PIG_ATK2"; } State { ID = "PIG_ATK2"; Sprite = "PIGY"; Frame = 0; Tics = 10; Action = "A_PigAttack"; Next state = "PIG_WALK1"; } State { ID = "PIG_DIE1"; Sprite = "PIGY"; Frame = 4; Tics = 4; Action = "A_Scream"; Next state = "PIG_DIE2"; } State { ID = "PIG_DIE2"; Sprite = "PIGY"; Frame = 5; Tics = 3; Action = "A_NoBlocking"; Next state = "PIG_DIE3"; } State { ID = "PIG_DIE3"; Sprite = "PIGY"; Frame = 6; Tics = 4; Action = "A_QueueCorpse"; Next state = "PIG_DIE4"; } State { ID = "PIG_DIE4"; Sprite = "PIGY"; Frame = 7; Tics = 3; Next state = "PIG_DIE5"; } State { ID = "PIG_DIE5"; Sprite = "PIGY"; Frame = 8; Tics = 4; Next state = "PIG_DIE6"; } State { ID = "PIG_DIE6"; Sprite = "PIGY"; Frame = 9; Tics = 4; Next state = "PIG_DIE7"; } State { ID = "PIG_DIE7"; Sprite = "PIGY"; Frame = 10; Tics = 4; Next state = "PIG_DIE8"; } State { ID = "PIG_DIE8"; Sprite = "PIGY"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "PIG_ICE"; Sprite = "PIGY"; Frame = 12; Tics = 5; Action = "A_FreezeDeath"; Next state = "PIG_ICE2"; } State { ID = "PIG_ICE2"; Sprite = "PIGY"; Frame = 12; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "PIG_ICE2"; } State { ID = "CENTAUR_LOOK1"; Sprite = "CENT"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "CENTAUR_LOOK2"; } State { ID = "CENTAUR_LOOK2"; Sprite = "CENT"; Frame = 1; Tics = 10; Action = "A_Look"; Next state = "CENTAUR_LOOK1"; } State { ID = "CENTAUR_WALK1"; Sprite = "CENT"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "CENTAUR_WALK2"; } State { ID = "CENTAUR_WALK2"; Sprite = "CENT"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "CENTAUR_WALK3"; } State { ID = "CENTAUR_WALK3"; Sprite = "CENT"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "CENTAUR_WALK4"; } State { ID = "CENTAUR_WALK4"; Sprite = "CENT"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "CENTAUR_WALK1"; } State { ID = "CENTAUR_ATK1"; Sprite = "CENT"; Frame = 7; Tics = 5; Action = "A_FaceTarget"; Next state = "CENTAUR_ATK2"; } State { ID = "CENTAUR_ATK2"; Sprite = "CENT"; Frame = 8; Tics = 4; Action = "A_FaceTarget"; Next state = "CENTAUR_ATK3"; } State { ID = "CENTAUR_ATK3"; Sprite = "CENT"; Frame = 9; Tics = 7; Action = "A_CentaurAttack"; Next state = "CENTAUR_WALK1"; } State { ID = "CENTAUR_MISSILE1"; Sprite = "CENT"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "CENTAUR_MISSILE2"; } State { ID = "CENTAUR_MISSILE2"; Sprite = "CENT"; Frame = 32773; Tics = 8; Action = "A_CentaurAttack2"; Next state = "CENTAUR_MISSILE3"; } State { ID = "CENTAUR_MISSILE3"; Sprite = "CENT"; Frame = 4; Tics = 10; Action = "A_FaceTarget"; Next state = "CENTAUR_MISSILE4"; } State { ID = "CENTAUR_MISSILE4"; Sprite = "CENT"; Frame = 32773; Tics = 8; Action = "A_CentaurAttack2"; Next state = "CENTAUR_WALK1"; } State { ID = "CENTAUR_PAIN1"; Sprite = "CENT"; Frame = 6; Tics = 6; Action = "A_Pain"; Next state = "CENTAUR_PAIN2"; } State { ID = "CENTAUR_PAIN2"; Sprite = "CENT"; Frame = 6; Tics = 6; Action = "A_SetReflective"; Next state = "CENTAUR_PAIN3"; } State { ID = "CENTAUR_PAIN3"; Sprite = "CENT"; Frame = 4; Tics = 15; Action = "A_CentaurDefend"; Next state = "CENTAUR_PAIN4"; } State { ID = "CENTAUR_PAIN4"; Sprite = "CENT"; Frame = 4; Tics = 15; Action = "A_CentaurDefend"; Next state = "CENTAUR_PAIN5"; } State { ID = "CENTAUR_PAIN5"; Sprite = "CENT"; Frame = 4; Tics = 15; Action = "A_CentaurDefend"; Next state = "CENTAUR_PAIN6"; } State { ID = "CENTAUR_PAIN6"; Sprite = "CENT"; Frame = 4; Tics = 1; Action = "A_UnSetReflective"; Next state = "CENTAUR_WALK1"; } State { ID = "CENTAUR_DEATH1"; Sprite = "CENT"; Frame = 10; Tics = 4; Next state = "CENTAUR_DEATH2"; } State { ID = "CENTAUR_DEATH2"; Sprite = "CENT"; Frame = 11; Tics = 4; Action = "A_Scream"; Next state = "CENTAUR_DEATH3"; } State { ID = "CENTAUR_DEATH3"; Sprite = "CENT"; Frame = 12; Tics = 4; Next state = "CENTAUR_DEATH4"; } State { ID = "CENTAUR_DEATH4"; Sprite = "CENT"; Frame = 13; Tics = 4; Next state = "CENTAUR_DEATH5"; } State { ID = "CENTAUR_DEATH5"; Sprite = "CENT"; Frame = 14; Tics = 4; Action = "A_NoBlocking"; Next state = "CENTAUR_DEATH6"; } State { ID = "CENTAUR_DEATH6"; Sprite = "CENT"; Frame = 15; Tics = 4; Next state = "CENTAUR_DEATH7"; } State { ID = "CENTAUR_DEATH7"; Sprite = "CENT"; Frame = 16; Tics = 4; Next state = "CENTAUR_DEATH8"; } State { ID = "CENTAUR_DEATH8"; Sprite = "CENT"; Frame = 17; Tics = 4; Action = "A_QueueCorpse"; Next state = "CENTAUR_DEATH9"; } State { ID = "CENTAUR_DEATH9"; Sprite = "CENT"; Frame = 18; Tics = 4; Next state = "CENTAUR_DEATH0"; } State { ID = "CENTAUR_DEATH0"; Sprite = "CENT"; Frame = 19; Tics = -1; Next state = "NULL"; } State { ID = "CENTAUR_DEATH_X1"; Sprite = "CTXD"; Frame = 0; Tics = 4; Next state = "CENTAUR_DEATH_X2"; } State { ID = "CENTAUR_DEATH_X2"; Sprite = "CTXD"; Frame = 1; Tics = 4; Action = "A_NoBlocking"; Next state = "CENTAUR_DEATH_X3"; } State { ID = "CENTAUR_DEATH_X3"; Sprite = "CTXD"; Frame = 2; Tics = 4; Action = "A_CentaurDropStuff"; Next state = "CENTAUR_DEATH_X4"; } State { ID = "CENTAUR_DEATH_X4"; Sprite = "CTXD"; Frame = 3; Tics = 3; Action = "A_Scream"; Next state = "CENTAUR_DEATH_X5"; } State { ID = "CENTAUR_DEATH_X5"; Sprite = "CTXD"; Frame = 4; Tics = 4; Action = "A_QueueCorpse"; Next state = "CENTAUR_DEATH_X6"; } State { ID = "CENTAUR_DEATH_X6"; Sprite = "CTXD"; Frame = 5; Tics = 3; Next state = "CENTAUR_DEATH_X7"; } State { ID = "CENTAUR_DEATH_X7"; Sprite = "CTXD"; Frame = 6; Tics = 4; Next state = "CENTAUR_DEATH_X8"; } State { ID = "CENTAUR_DEATH_X8"; Sprite = "CTXD"; Frame = 7; Tics = 3; Next state = "CENTAUR_DEATH_X9"; } State { ID = "CENTAUR_DEATH_X9"; Sprite = "CTXD"; Frame = 8; Tics = 4; Next state = "CENTAUR_DEATH_X10"; } State { ID = "CENTAUR_DEATH_X10"; Sprite = "CTXD"; Frame = 9; Tics = 3; Next state = "CENTAUR_DEATH_X11"; } State { ID = "CENTAUR_DEATH_X11"; Sprite = "CTXD"; Frame = 10; Tics = -1; Next state = "NULL"; } State { ID = "CENTAUR_ICE"; Sprite = "CENT"; Frame = 20; Tics = 5; Action = "A_FreezeDeath"; Next state = "CENTAUR_ICE2"; } State { ID = "CENTAUR_ICE2"; Sprite = "CENT"; Frame = 20; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "CENTAUR_ICE2"; } State { ID = "CENTAUR_FX1"; Sprite = "CTFX"; Frame = 32768; Tics = -1; Next state = "NULL"; } State { ID = "CENTAUR_FX_X1"; Sprite = "CTFX"; Frame = 32769; Tics = 4; Next state = "CENTAUR_FX_X2"; } State { ID = "CENTAUR_FX_X2"; Sprite = "CTFX"; Frame = 32770; Tics = 3; Next state = "CENTAUR_FX_X3"; } State { ID = "CENTAUR_FX_X3"; Sprite = "CTFX"; Frame = 32771; Tics = 4; Next state = "CENTAUR_FX_X4"; } State { ID = "CENTAUR_FX_X4"; Sprite = "CTFX"; Frame = 32772; Tics = 3; Next state = "CENTAUR_FX_X5"; } State { ID = "CENTAUR_FX_X5"; Sprite = "CTFX"; Frame = 32773; Tics = 2; Next state = "NULL"; } State { ID = "CENTAUR_SHIELD1"; Sprite = "CTDP"; Frame = 0; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SHIELD2"; } State { ID = "CENTAUR_SHIELD2"; Sprite = "CTDP"; Frame = 1; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SHIELD3"; } State { ID = "CENTAUR_SHIELD3"; Sprite = "CTDP"; Frame = 2; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SHIELD4"; } State { ID = "CENTAUR_SHIELD4"; Sprite = "CTDP"; Frame = 3; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SHIELD5"; } State { ID = "CENTAUR_SHIELD5"; Sprite = "CTDP"; Frame = 4; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SHIELD6"; } State { ID = "CENTAUR_SHIELD6"; Sprite = "CTDP"; Frame = 5; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SHIELD3"; } State { ID = "CENTAUR_SHIELD_X1"; Sprite = "CTDP"; Frame = 6; Tics = 4; Next state = "CENTAUR_SHIELD_X2"; } State { ID = "CENTAUR_SHIELD_X2"; Sprite = "CTDP"; Frame = 7; Tics = 4; Action = "A_QueueCorpse"; Next state = "CENTAUR_SHIELD_X3"; } State { ID = "CENTAUR_SHIELD_X3"; Sprite = "CTDP"; Frame = 8; Tics = 4; Next state = "CENTAUR_SHIELD_X4"; } State { ID = "CENTAUR_SHIELD_X4"; Sprite = "CTDP"; Frame = 9; Tics = -1; Next state = "NULL"; } State { ID = "CENTAUR_SWORD1"; Sprite = "CTDP"; Frame = 10; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SWORD2"; } State { ID = "CENTAUR_SWORD2"; Sprite = "CTDP"; Frame = 11; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SWORD3"; } State { ID = "CENTAUR_SWORD3"; Sprite = "CTDP"; Frame = 12; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SWORD4"; } State { ID = "CENTAUR_SWORD4"; Sprite = "CTDP"; Frame = 13; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SWORD5"; } State { ID = "CENTAUR_SWORD5"; Sprite = "CTDP"; Frame = 14; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SWORD6"; } State { ID = "CENTAUR_SWORD6"; Sprite = "CTDP"; Frame = 15; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SWORD7"; } State { ID = "CENTAUR_SWORD7"; Sprite = "CTDP"; Frame = 16; Tics = 3; Action = "A_CheckFloor"; Next state = "CENTAUR_SWORD3"; } State { ID = "CENTAUR_SWORD_X1"; Sprite = "CTDP"; Frame = 17; Tics = 4; Next state = "CENTAUR_SWORD_X2"; } State { ID = "CENTAUR_SWORD_X2"; Sprite = "CTDP"; Frame = 18; Tics = 4; Action = "A_QueueCorpse"; Next state = "CENTAUR_SWORD_X3"; } State { ID = "CENTAUR_SWORD_X3"; Sprite = "CTDP"; Frame = 19; Tics = -1; Next state = "NULL"; } State { ID = "DEMN_LOOK1"; Sprite = "DEMN"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "DEMN_LOOK2"; } State { ID = "DEMN_LOOK2"; Sprite = "DEMN"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "DEMN_LOOK1"; } State { ID = "DEMN_CHASE1"; Sprite = "DEMN"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "DEMN_CHASE2"; } State { ID = "DEMN_CHASE2"; Sprite = "DEMN"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "DEMN_CHASE3"; } State { ID = "DEMN_CHASE3"; Sprite = "DEMN"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "DEMN_CHASE4"; } State { ID = "DEMN_CHASE4"; Sprite = "DEMN"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "DEMN_CHASE1"; } State { ID = "DEMN_ATK1_1"; Sprite = "DEMN"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "DEMN_ATK1_2"; } State { ID = "DEMN_ATK1_2"; Sprite = "DEMN"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "DEMN_ATK1_3"; } State { ID = "DEMN_ATK1_3"; Sprite = "DEMN"; Frame = 6; Tics = 6; Action = "A_DemonAttack1"; Next state = "DEMN_CHASE1"; } State { ID = "DEMN_ATK2_1"; Sprite = "DEMN"; Frame = 4; Tics = 5; Action = "A_FaceTarget"; Next state = "DEMN_ATK2_2"; } State { ID = "DEMN_ATK2_2"; Sprite = "DEMN"; Frame = 5; Tics = 6; Action = "A_FaceTarget"; Next state = "DEMN_ATK2_3"; } State { ID = "DEMN_ATK2_3"; Sprite = "DEMN"; Frame = 6; Tics = 5; Action = "A_DemonAttack2"; Next state = "DEMN_CHASE1"; } State { ID = "DEMN_PAIN1"; Sprite = "DEMN"; Frame = 4; Tics = 4; Next state = "DEMN_PAIN2"; } State { ID = "DEMN_PAIN2"; Sprite = "DEMN"; Frame = 4; Tics = 4; Action = "A_Pain"; Next state = "DEMN_CHASE1"; } State { ID = "DEMN_DEATH1"; Sprite = "DEMN"; Frame = 7; Tics = 6; Next state = "DEMN_DEATH2"; } State { ID = "DEMN_DEATH2"; Sprite = "DEMN"; Frame = 8; Tics = 6; Next state = "DEMN_DEATH3"; } State { ID = "DEMN_DEATH3"; Sprite = "DEMN"; Frame = 9; Tics = 6; Action = "A_Scream"; Next state = "DEMN_DEATH4"; } State { ID = "DEMN_DEATH4"; Sprite = "DEMN"; Frame = 10; Tics = 6; Action = "A_NoBlocking"; Next state = "DEMN_DEATH5"; } State { ID = "DEMN_DEATH5"; Sprite = "DEMN"; Frame = 11; Tics = 6; Action = "A_QueueCorpse"; Next state = "DEMN_DEATH6"; } State { ID = "DEMN_DEATH6"; Sprite = "DEMN"; Frame = 12; Tics = 6; Next state = "DEMN_DEATH7"; } State { ID = "DEMN_DEATH7"; Sprite = "DEMN"; Frame = 13; Tics = 6; Next state = "DEMN_DEATH8"; } State { ID = "DEMN_DEATH8"; Sprite = "DEMN"; Frame = 14; Tics = 6; Next state = "DEMN_DEATH9"; } State { ID = "DEMN_DEATH9"; Sprite = "DEMN"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "DEMN_XDEATH1"; Sprite = "DEMN"; Frame = 7; Tics = 6; Next state = "DEMN_XDEATH2"; } State { ID = "DEMN_XDEATH2"; Sprite = "DEMN"; Frame = 8; Tics = 6; Action = "A_DemonDeath"; Next state = "DEMN_XDEATH3"; } State { ID = "DEMN_XDEATH3"; Sprite = "DEMN"; Frame = 9; Tics = 6; Action = "A_Scream"; Next state = "DEMN_XDEATH4"; } State { ID = "DEMN_XDEATH4"; Sprite = "DEMN"; Frame = 10; Tics = 6; Action = "A_NoBlocking"; Next state = "DEMN_XDEATH5"; } State { ID = "DEMN_XDEATH5"; Sprite = "DEMN"; Frame = 11; Tics = 6; Action = "A_QueueCorpse"; Next state = "DEMN_XDEATH6"; } State { ID = "DEMN_XDEATH6"; Sprite = "DEMN"; Frame = 12; Tics = 6; Next state = "DEMN_XDEATH7"; } State { ID = "DEMN_XDEATH7"; Sprite = "DEMN"; Frame = 13; Tics = 6; Next state = "DEMN_XDEATH8"; } State { ID = "DEMN_XDEATH8"; Sprite = "DEMN"; Frame = 14; Tics = 6; Next state = "DEMN_XDEATH9"; } State { ID = "DEMN_XDEATH9"; Sprite = "DEMN"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "DEMON_ICE"; Sprite = "DEMN"; Frame = 16; Tics = 5; Action = "A_FreezeDeath"; Next state = "DEMON_ICE2"; } State { ID = "DEMON_ICE2"; Sprite = "DEMN"; Frame = 16; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "DEMON_ICE2"; } State { ID = "DEMONCHUNK1_1"; Sprite = "DEMA"; Frame = 0; Tics = 4; Next state = "DEMONCHUNK1_2"; } State { ID = "DEMONCHUNK1_2"; Sprite = "DEMA"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMONCHUNK1_3"; } State { ID = "DEMONCHUNK1_3"; Sprite = "DEMA"; Frame = 0; Tics = 20; Next state = "DEMONCHUNK1_3"; } State { ID = "DEMONCHUNK1_4"; Sprite = "DEMA"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMONCHUNK2_1"; Sprite = "DEMB"; Frame = 0; Tics = 4; Next state = "DEMONCHUNK2_2"; } State { ID = "DEMONCHUNK2_2"; Sprite = "DEMB"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMONCHUNK2_3"; } State { ID = "DEMONCHUNK2_3"; Sprite = "DEMB"; Frame = 0; Tics = 20; Next state = "DEMONCHUNK2_3"; } State { ID = "DEMONCHUNK2_4"; Sprite = "DEMB"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMONCHUNK3_1"; Sprite = "DEMC"; Frame = 0; Tics = 4; Next state = "DEMONCHUNK3_2"; } State { ID = "DEMONCHUNK3_2"; Sprite = "DEMC"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMONCHUNK3_3"; } State { ID = "DEMONCHUNK3_3"; Sprite = "DEMC"; Frame = 0; Tics = 20; Next state = "DEMONCHUNK3_3"; } State { ID = "DEMONCHUNK3_4"; Sprite = "DEMC"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMONCHUNK4_1"; Sprite = "DEMD"; Frame = 0; Tics = 4; Next state = "DEMONCHUNK4_2"; } State { ID = "DEMONCHUNK4_2"; Sprite = "DEMD"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMONCHUNK4_3"; } State { ID = "DEMONCHUNK4_3"; Sprite = "DEMD"; Frame = 0; Tics = 20; Next state = "DEMONCHUNK4_3"; } State { ID = "DEMONCHUNK4_4"; Sprite = "DEMD"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMONCHUNK5_1"; Sprite = "DEME"; Frame = 0; Tics = 4; Next state = "DEMONCHUNK5_2"; } State { ID = "DEMONCHUNK5_2"; Sprite = "DEME"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMONCHUNK5_3"; } State { ID = "DEMONCHUNK5_3"; Sprite = "DEME"; Frame = 0; Tics = 20; Next state = "DEMONCHUNK5_3"; } State { ID = "DEMONCHUNK5_4"; Sprite = "DEME"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMONFX_MOVE1"; Sprite = "DMFX"; Frame = 32768; Tics = 4; Next state = "DEMONFX_MOVE2"; } State { ID = "DEMONFX_MOVE2"; Sprite = "DMFX"; Frame = 32769; Tics = 4; Next state = "DEMONFX_MOVE3"; } State { ID = "DEMONFX_MOVE3"; Sprite = "DMFX"; Frame = 32770; Tics = 4; Next state = "DEMONFX_MOVE1"; } State { ID = "DEMONFX_BOOM1"; Sprite = "DMFX"; Frame = 32771; Tics = 4; Next state = "DEMONFX_BOOM2"; } State { ID = "DEMONFX_BOOM2"; Sprite = "DMFX"; Frame = 32772; Tics = 4; Next state = "DEMONFX_BOOM3"; } State { ID = "DEMONFX_BOOM3"; Sprite = "DMFX"; Frame = 32773; Tics = 3; Next state = "DEMONFX_BOOM4"; } State { ID = "DEMONFX_BOOM4"; Sprite = "DMFX"; Frame = 32774; Tics = 3; Next state = "DEMONFX_BOOM5"; } State { ID = "DEMONFX_BOOM5"; Sprite = "DMFX"; Frame = 32775; Tics = 3; Next state = "NULL"; } State { ID = "DEMN2_LOOK1"; Sprite = "DEM2"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "DEMN2_LOOK2"; } State { ID = "DEMN2_LOOK2"; Sprite = "DEM2"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "DEMN2_LOOK1"; } State { ID = "DEMN2_CHASE1"; Sprite = "DEM2"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "DEMN2_CHASE2"; } State { ID = "DEMN2_CHASE2"; Sprite = "DEM2"; Frame = 1; Tics = 4; Action = "A_Chase"; Next state = "DEMN2_CHASE3"; } State { ID = "DEMN2_CHASE3"; Sprite = "DEM2"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "DEMN2_CHASE4"; } State { ID = "DEMN2_CHASE4"; Sprite = "DEM2"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "DEMN2_CHASE1"; } State { ID = "DEMN2_ATK1_1"; Sprite = "DEM2"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "DEMN2_ATK1_2"; } State { ID = "DEMN2_ATK1_2"; Sprite = "DEM2"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "DEMN2_ATK1_3"; } State { ID = "DEMN2_ATK1_3"; Sprite = "DEM2"; Frame = 6; Tics = 6; Action = "A_DemonAttack1"; Next state = "DEMN2_CHASE1"; } State { ID = "DEMN2_ATK2_1"; Sprite = "DEM2"; Frame = 4; Tics = 5; Action = "A_FaceTarget"; Next state = "DEMN2_ATK2_2"; } State { ID = "DEMN2_ATK2_2"; Sprite = "DEM2"; Frame = 5; Tics = 6; Action = "A_FaceTarget"; Next state = "DEMN2_ATK2_3"; } State { ID = "DEMN2_ATK2_3"; Sprite = "DEM2"; Frame = 6; Tics = 5; Action = "A_DemonAttack2"; Next state = "DEMN2_CHASE1"; } State { ID = "DEMN2_PAIN1"; Sprite = "DEM2"; Frame = 4; Tics = 4; Next state = "DEMN2_PAIN2"; } State { ID = "DEMN2_PAIN2"; Sprite = "DEM2"; Frame = 4; Tics = 4; Action = "A_Pain"; Next state = "DEMN2_CHASE1"; } State { ID = "DEMN2_DEATH1"; Sprite = "DEM2"; Frame = 7; Tics = 6; Next state = "DEMN2_DEATH2"; } State { ID = "DEMN2_DEATH2"; Sprite = "DEM2"; Frame = 8; Tics = 6; Next state = "DEMN2_DEATH3"; } State { ID = "DEMN2_DEATH3"; Sprite = "DEM2"; Frame = 9; Tics = 6; Action = "A_Scream"; Next state = "DEMN2_DEATH4"; } State { ID = "DEMN2_DEATH4"; Sprite = "DEM2"; Frame = 10; Tics = 6; Action = "A_NoBlocking"; Next state = "DEMN2_DEATH5"; } State { ID = "DEMN2_DEATH5"; Sprite = "DEM2"; Frame = 11; Tics = 6; Action = "A_QueueCorpse"; Next state = "DEMN2_DEATH6"; } State { ID = "DEMN2_DEATH6"; Sprite = "DEM2"; Frame = 12; Tics = 6; Next state = "DEMN2_DEATH7"; } State { ID = "DEMN2_DEATH7"; Sprite = "DEM2"; Frame = 13; Tics = 6; Next state = "DEMN2_DEATH8"; } State { ID = "DEMN2_DEATH8"; Sprite = "DEM2"; Frame = 14; Tics = 6; Next state = "DEMN2_DEATH9"; } State { ID = "DEMN2_DEATH9"; Sprite = "DEM2"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "DEMN2_XDEATH1"; Sprite = "DEM2"; Frame = 7; Tics = 6; Next state = "DEMN2_XDEATH2"; } State { ID = "DEMN2_XDEATH2"; Sprite = "DEM2"; Frame = 8; Tics = 6; Action = "A_Demon2Death"; Next state = "DEMN2_XDEATH3"; } State { ID = "DEMN2_XDEATH3"; Sprite = "DEM2"; Frame = 9; Tics = 6; Action = "A_Scream"; Next state = "DEMN2_XDEATH4"; } State { ID = "DEMN2_XDEATH4"; Sprite = "DEM2"; Frame = 10; Tics = 6; Action = "A_NoBlocking"; Next state = "DEMN2_XDEATH5"; } State { ID = "DEMN2_XDEATH5"; Sprite = "DEM2"; Frame = 11; Tics = 6; Action = "A_QueueCorpse"; Next state = "DEMN2_XDEATH6"; } State { ID = "DEMN2_XDEATH6"; Sprite = "DEM2"; Frame = 12; Tics = 6; Next state = "DEMN2_XDEATH7"; } State { ID = "DEMN2_XDEATH7"; Sprite = "DEM2"; Frame = 13; Tics = 6; Next state = "DEMN2_XDEATH8"; } State { ID = "DEMN2_XDEATH8"; Sprite = "DEM2"; Frame = 14; Tics = 6; Next state = "DEMN2_XDEATH9"; } State { ID = "DEMN2_XDEATH9"; Sprite = "DEM2"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "DEMON2CHUNK1_1"; Sprite = "DMBA"; Frame = 0; Tics = 4; Next state = "DEMON2CHUNK1_2"; } State { ID = "DEMON2CHUNK1_2"; Sprite = "DMBA"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMON2CHUNK1_3"; } State { ID = "DEMON2CHUNK1_3"; Sprite = "DMBA"; Frame = 0; Tics = 20; Next state = "DEMON2CHUNK1_3"; } State { ID = "DEMON2CHUNK1_4"; Sprite = "DMBA"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMON2CHUNK2_1"; Sprite = "DMBB"; Frame = 0; Tics = 4; Next state = "DEMON2CHUNK2_2"; } State { ID = "DEMON2CHUNK2_2"; Sprite = "DMBB"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMON2CHUNK2_3"; } State { ID = "DEMON2CHUNK2_3"; Sprite = "DMBB"; Frame = 0; Tics = 20; Next state = "DEMON2CHUNK2_3"; } State { ID = "DEMON2CHUNK2_4"; Sprite = "DMBB"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMON2CHUNK3_1"; Sprite = "DMBC"; Frame = 0; Tics = 4; Next state = "DEMON2CHUNK3_2"; } State { ID = "DEMON2CHUNK3_2"; Sprite = "DMBC"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMON2CHUNK3_3"; } State { ID = "DEMON2CHUNK3_3"; Sprite = "DMBC"; Frame = 0; Tics = 20; Next state = "DEMON2CHUNK3_3"; } State { ID = "DEMON2CHUNK3_4"; Sprite = "DMBC"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMON2CHUNK4_1"; Sprite = "DMBD"; Frame = 0; Tics = 4; Next state = "DEMON2CHUNK4_2"; } State { ID = "DEMON2CHUNK4_2"; Sprite = "DMBD"; Frame = 0; Tics = 10; Action = "A_QueueCorpse"; Next state = "DEMON2CHUNK4_3"; } State { ID = "DEMON2CHUNK4_3"; Sprite = "DMBD"; Frame = 0; Tics = 20; Next state = "DEMON2CHUNK4_3"; } State { ID = "DEMON2CHUNK4_4"; Sprite = "DMBD"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMON2CHUNK5_1"; Sprite = "DMBE"; Frame = 0; Tics = 4; Next state = "DEMON2CHUNK5_2"; } State { ID = "DEMON2CHUNK5_2"; Sprite = "DMBE"; Frame = 0; Tics = 10; Next state = "DEMON2CHUNK5_3"; } State { ID = "DEMON2CHUNK5_3"; Sprite = "DMBE"; Frame = 0; Tics = 20; Next state = "DEMON2CHUNK5_3"; } State { ID = "DEMON2CHUNK5_4"; Sprite = "DMBE"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "DEMON2FX_MOVE1"; Sprite = "D2FX"; Frame = 32768; Tics = 4; Next state = "DEMON2FX_MOVE2"; } State { ID = "DEMON2FX_MOVE2"; Sprite = "D2FX"; Frame = 32769; Tics = 4; Next state = "DEMON2FX_MOVE3"; } State { ID = "DEMON2FX_MOVE3"; Sprite = "D2FX"; Frame = 32770; Tics = 4; Next state = "DEMON2FX_MOVE4"; } State { ID = "DEMON2FX_MOVE4"; Sprite = "D2FX"; Frame = 32771; Tics = 4; Next state = "DEMON2FX_MOVE5"; } State { ID = "DEMON2FX_MOVE5"; Sprite = "D2FX"; Frame = 32772; Tics = 4; Next state = "DEMON2FX_MOVE6"; } State { ID = "DEMON2FX_MOVE6"; Sprite = "D2FX"; Frame = 32773; Tics = 4; Next state = "DEMON2FX_MOVE1"; } State { ID = "DEMON2FX_BOOM1"; Sprite = "D2FX"; Frame = 32774; Tics = 4; Next state = "DEMON2FX_BOOM2"; } State { ID = "DEMON2FX_BOOM2"; Sprite = "D2FX"; Frame = 32775; Tics = 4; Next state = "DEMON2FX_BOOM3"; } State { ID = "DEMON2FX_BOOM3"; Sprite = "D2FX"; Frame = 32776; Tics = 4; Next state = "DEMON2FX_BOOM4"; } State { ID = "DEMON2FX_BOOM4"; Sprite = "D2FX"; Frame = 32777; Tics = 4; Next state = "DEMON2FX_BOOM5"; } State { ID = "DEMON2FX_BOOM5"; Sprite = "D2FX"; Frame = 32778; Tics = 3; Next state = "DEMON2FX_BOOM6"; } State { ID = "DEMON2FX_BOOM6"; Sprite = "D2FX"; Frame = 32779; Tics = 3; Next state = "NULL"; } State { ID = "WRAITH_RAISE1"; Sprite = "WRTH"; Frame = 0; Tics = 2; Action = "A_WraithRaiseInit"; Next state = "WRAITH_RAISE2"; } State { ID = "WRAITH_RAISE2"; Sprite = "WRTH"; Frame = 0; Tics = 2; Action = "A_WraithRaise"; Next state = "WRAITH_RAISE3"; } State { ID = "WRAITH_RAISE3"; Sprite = "WRTH"; Frame = 0; Tics = 2; Action = "A_FaceTarget"; Next state = "WRAITH_RAISE4"; } State { ID = "WRAITH_RAISE4"; Sprite = "WRTH"; Frame = 1; Tics = 2; Action = "A_WraithRaise"; Next state = "WRAITH_RAISE5"; } State { ID = "WRAITH_RAISE5"; Sprite = "WRTH"; Frame = 1; Tics = 2; Action = "A_WraithRaise"; Next state = "WRAITH_RAISE2"; } State { ID = "WRAITH_INIT1"; Sprite = "WRTH"; Frame = 0; Tics = 10; Next state = "WRAITH_INIT2"; } State { ID = "WRAITH_INIT2"; Sprite = "WRTH"; Frame = 1; Tics = 5; Action = "A_WraithInit"; Next state = "WRAITH_LOOK1"; } State { ID = "WRAITH_LOOK1"; Sprite = "WRTH"; Frame = 0; Tics = 15; Action = "A_WraithLook"; Next state = "WRAITH_LOOK2"; } State { ID = "WRAITH_LOOK2"; Sprite = "WRTH"; Frame = 1; Tics = 15; Action = "A_WraithLook"; Next state = "WRAITH_LOOK1"; } State { ID = "WRAITH_CHASE1"; Sprite = "WRTH"; Frame = 0; Tics = 4; Action = "A_WraithChase"; Next state = "WRAITH_CHASE2"; } State { ID = "WRAITH_CHASE2"; Sprite = "WRTH"; Frame = 1; Tics = 4; Action = "A_WraithChase"; Next state = "WRAITH_CHASE3"; } State { ID = "WRAITH_CHASE3"; Sprite = "WRTH"; Frame = 2; Tics = 4; Action = "A_WraithChase"; Next state = "WRAITH_CHASE4"; } State { ID = "WRAITH_CHASE4"; Sprite = "WRTH"; Frame = 3; Tics = 4; Action = "A_WraithChase"; Next state = "WRAITH_CHASE1"; } State { ID = "WRAITH_ATK1_1"; Sprite = "WRTH"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "WRAITH_ATK1_2"; } State { ID = "WRAITH_ATK1_2"; Sprite = "WRTH"; Frame = 5; Tics = 6; Action = "A_WraithFX3"; Next state = "WRAITH_ATK1_3"; } State { ID = "WRAITH_ATK1_3"; Sprite = "WRTH"; Frame = 6; Tics = 6; Action = "A_WraithMelee"; Next state = "WRAITH_CHASE1"; } State { ID = "WRAITH_ATK2_1"; Sprite = "WRTH"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "WRAITH_ATK2_2"; } State { ID = "WRAITH_ATK2_2"; Sprite = "WRTH"; Frame = 5; Tics = 6; Next state = "WRAITH_ATK2_3"; } State { ID = "WRAITH_ATK2_3"; Sprite = "WRTH"; Frame = 6; Tics = 6; Action = "A_WraithMissile"; Next state = "WRAITH_CHASE1"; } State { ID = "WRAITH_PAIN1"; Sprite = "WRTH"; Frame = 0; Tics = 2; Next state = "WRAITH_PAIN2"; } State { ID = "WRAITH_PAIN2"; Sprite = "WRTH"; Frame = 7; Tics = 6; Action = "A_Pain"; Next state = "WRAITH_CHASE1"; } State { ID = "WRAITH_DEATH1_1"; Sprite = "WRTH"; Frame = 8; Tics = 4; Next state = "WRAITH_DEATH1_2"; } State { ID = "WRAITH_DEATH1_2"; Sprite = "WRTH"; Frame = 9; Tics = 4; Action = "A_Scream"; Next state = "WRAITH_DEATH1_3"; } State { ID = "WRAITH_DEATH1_3"; Sprite = "WRTH"; Frame = 10; Tics = 4; Next state = "WRAITH_DEATH1_4"; } State { ID = "WRAITH_DEATH1_4"; Sprite = "WRTH"; Frame = 11; Tics = 4; Next state = "WRAITH_DEATH1_5"; } State { ID = "WRAITH_DEATH1_5"; Sprite = "WRTH"; Frame = 12; Tics = 4; Action = "A_NoBlocking"; Next state = "WRAITH_DEATH1_6"; } State { ID = "WRAITH_DEATH1_6"; Sprite = "WRTH"; Frame = 13; Tics = 4; Action = "A_QueueCorpse"; Next state = "WRAITH_DEATH1_7"; } State { ID = "WRAITH_DEATH1_7"; Sprite = "WRTH"; Frame = 14; Tics = 4; Next state = "WRAITH_DEATH1_8"; } State { ID = "WRAITH_DEATH1_8"; Sprite = "WRTH"; Frame = 15; Tics = 5; Next state = "WRAITH_DEATH1_9"; } State { ID = "WRAITH_DEATH1_9"; Sprite = "WRTH"; Frame = 16; Tics = 5; Next state = "WRAITH_DEATH1_0"; } State { ID = "WRAITH_DEATH1_0"; Sprite = "WRTH"; Frame = 17; Tics = -1; Next state = "NULL"; } State { ID = "WRAITH_DEATH2_1"; Sprite = "WRT2"; Frame = 0; Tics = 5; Next state = "WRAITH_DEATH2_2"; } State { ID = "WRAITH_DEATH2_2"; Sprite = "WRT2"; Frame = 1; Tics = 5; Action = "A_Scream"; Next state = "WRAITH_DEATH2_3"; } State { ID = "WRAITH_DEATH2_3"; Sprite = "WRT2"; Frame = 2; Tics = 5; Next state = "WRAITH_DEATH2_4"; } State { ID = "WRAITH_DEATH2_4"; Sprite = "WRT2"; Frame = 3; Tics = 5; Next state = "WRAITH_DEATH2_5"; } State { ID = "WRAITH_DEATH2_5"; Sprite = "WRT2"; Frame = 4; Tics = 5; Action = "A_NoBlocking"; Next state = "WRAITH_DEATH2_6"; } State { ID = "WRAITH_DEATH2_6"; Sprite = "WRT2"; Frame = 5; Tics = 5; Action = "A_QueueCorpse"; Next state = "WRAITH_DEATH2_7"; } State { ID = "WRAITH_DEATH2_7"; Sprite = "WRT2"; Frame = 6; Tics = 5; Next state = "WRAITH_DEATH2_8"; } State { ID = "WRAITH_DEATH2_8"; Sprite = "WRT2"; Frame = 7; Tics = -1; Next state = "NULL"; } State { ID = "WRAITH_ICE"; Sprite = "WRT2"; Frame = 8; Tics = 5; Action = "A_FreezeDeath"; Next state = "WRAITH_ICE2"; } State { ID = "WRAITH_ICE2"; Sprite = "WRT2"; Frame = 8; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "WRAITH_ICE2"; } State { ID = "WRTHFX_MOVE1"; Sprite = "WRBL"; Frame = 32768; Tics = 3; Next state = "WRTHFX_MOVE2"; } State { ID = "WRTHFX_MOVE2"; Sprite = "WRBL"; Frame = 32769; Tics = 3; Action = "A_WraithFX2"; Next state = "WRTHFX_MOVE3"; } State { ID = "WRTHFX_MOVE3"; Sprite = "WRBL"; Frame = 32770; Tics = 3; Next state = "WRTHFX_MOVE1"; } State { ID = "WRTHFX_BOOM1"; Sprite = "WRBL"; Frame = 32771; Tics = 4; Next state = "WRTHFX_BOOM2"; } State { ID = "WRTHFX_BOOM2"; Sprite = "WRBL"; Frame = 32772; Tics = 4; Action = "A_WraithFX2"; Next state = "WRTHFX_BOOM3"; } State { ID = "WRTHFX_BOOM3"; Sprite = "WRBL"; Frame = 32773; Tics = 4; Next state = "WRTHFX_BOOM4"; } State { ID = "WRTHFX_BOOM4"; Sprite = "WRBL"; Frame = 32774; Tics = 3; Action = "A_WraithFX2"; Next state = "WRTHFX_BOOM5"; } State { ID = "WRTHFX_BOOM5"; Sprite = "WRBL"; Frame = 32775; Tics = 3; Action = "A_WraithFX2"; Next state = "WRTHFX_BOOM6"; } State { ID = "WRTHFX_BOOM6"; Sprite = "WRBL"; Frame = 32776; Tics = 3; Next state = "NULL"; } State { ID = "WRTHFX_SIZZLE1"; Sprite = "WRBL"; Frame = 32777; Tics = 4; Next state = "WRTHFX_SIZZLE2"; } State { ID = "WRTHFX_SIZZLE2"; Sprite = "WRBL"; Frame = 32778; Tics = 4; Next state = "WRTHFX_SIZZLE3"; } State { ID = "WRTHFX_SIZZLE3"; Sprite = "WRBL"; Frame = 32779; Tics = 4; Next state = "WRTHFX_SIZZLE4"; } State { ID = "WRTHFX_SIZZLE4"; Sprite = "WRBL"; Frame = 32780; Tics = 4; Next state = "WRTHFX_SIZZLE5"; } State { ID = "WRTHFX_SIZZLE5"; Sprite = "WRBL"; Frame = 32781; Tics = 4; Next state = "WRTHFX_SIZZLE6"; } State { ID = "WRTHFX_SIZZLE6"; Sprite = "WRBL"; Frame = 32782; Tics = 4; Next state = "WRTHFX_SIZZLE7"; } State { ID = "WRTHFX_SIZZLE7"; Sprite = "WRBL"; Frame = 32783; Tics = 4; Next state = "NULL"; } State { ID = "WRTHFX_DROP1"; Sprite = "WRBL"; Frame = 32784; Tics = 4; Next state = "WRTHFX_DROP2"; } State { ID = "WRTHFX_DROP2"; Sprite = "WRBL"; Frame = 32785; Tics = 4; Next state = "WRTHFX_DROP3"; } State { ID = "WRTHFX_DROP3"; Sprite = "WRBL"; Frame = 32786; Tics = 4; Next state = "WRTHFX_DROP1"; } State { ID = "WRTHFX_DEAD1"; Sprite = "WRBL"; Frame = 32786; Tics = 4; Next state = "NULL"; } State { ID = "WRTHFX_ADROP1"; Sprite = "WRBL"; Frame = 19; Tics = 4; Next state = "WRTHFX_ADROP2"; } State { ID = "WRTHFX_ADROP2"; Sprite = "WRBL"; Frame = 20; Tics = 4; Next state = "WRTHFX_ADROP3"; } State { ID = "WRTHFX_ADROP3"; Sprite = "WRBL"; Frame = 21; Tics = 4; Next state = "WRTHFX_ADROP4"; } State { ID = "WRTHFX_ADROP4"; Sprite = "WRBL"; Frame = 22; Tics = 4; Next state = "WRTHFX_ADROP1"; } State { ID = "WRTHFX_ADEAD1"; Sprite = "WRBL"; Frame = 22; Tics = 10; Next state = "NULL"; } State { ID = "WRTHFX_BDROP1"; Sprite = "WRBL"; Frame = 23; Tics = 7; Next state = "WRTHFX_BDROP2"; } State { ID = "WRTHFX_BDROP2"; Sprite = "WRBL"; Frame = 24; Tics = 7; Next state = "WRTHFX_BDROP3"; } State { ID = "WRTHFX_BDROP3"; Sprite = "WRBL"; Frame = 25; Tics = 7; Next state = "WRTHFX_BDROP1"; } State { ID = "WRTHFX_BDEAD1"; Sprite = "WRBL"; Frame = 25; Tics = 35; Next state = "NULL"; } State { ID = "MNTR_SPAWN1"; Sprite = "MNTR"; Frame = 0; Tics = 15; Next state = "MNTR_SPAWN2"; } State { ID = "MNTR_SPAWN2"; Sprite = "MNTR"; Frame = 0; Tics = 15; Action = "A_MinotaurFade1"; Next state = "MNTR_SPAWN3"; } State { ID = "MNTR_SPAWN3"; Sprite = "MNTR"; Frame = 0; Tics = 3; Action = "A_MinotaurFade2"; Next state = "MNTR_LOOK1"; } State { ID = "MNTR_LOOK1"; Sprite = "MNTR"; Frame = 0; Tics = 10; Action = "A_MinotaurLook"; Next state = "MNTR_LOOK2"; } State { ID = "MNTR_LOOK2"; Sprite = "MNTR"; Frame = 1; Tics = 10; Action = "A_MinotaurLook"; Next state = "MNTR_LOOK1"; } State { ID = "MNTR_WALK1"; Sprite = "MNTR"; Frame = 0; Tics = 5; Action = "A_MinotaurChase"; Next state = "MNTR_WALK2"; } State { ID = "MNTR_WALK2"; Sprite = "MNTR"; Frame = 1; Tics = 5; Action = "A_MinotaurChase"; Next state = "MNTR_WALK3"; } State { ID = "MNTR_WALK3"; Sprite = "MNTR"; Frame = 2; Tics = 5; Action = "A_MinotaurChase"; Next state = "MNTR_WALK4"; } State { ID = "MNTR_WALK4"; Sprite = "MNTR"; Frame = 3; Tics = 5; Action = "A_MinotaurChase"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_ROAM1"; Sprite = "MNTR"; Frame = 0; Tics = 5; Action = "A_MinotaurRoam"; Next state = "MNTR_ROAM2"; } State { ID = "MNTR_ROAM2"; Sprite = "MNTR"; Frame = 1; Tics = 5; Action = "A_MinotaurRoam"; Next state = "MNTR_ROAM3"; } State { ID = "MNTR_ROAM3"; Sprite = "MNTR"; Frame = 2; Tics = 5; Action = "A_MinotaurRoam"; Next state = "MNTR_ROAM4"; } State { ID = "MNTR_ROAM4"; Sprite = "MNTR"; Frame = 3; Tics = 5; Action = "A_MinotaurRoam"; Next state = "MNTR_ROAM1"; } State { ID = "MNTR_ATK1_1"; Sprite = "MNTR"; Frame = 6; Tics = 10; Action = "A_FaceTarget"; Next state = "MNTR_ATK1_2"; } State { ID = "MNTR_ATK1_2"; Sprite = "MNTR"; Frame = 7; Tics = 7; Action = "A_FaceTarget"; Next state = "MNTR_ATK1_3"; } State { ID = "MNTR_ATK1_3"; Sprite = "MNTR"; Frame = 8; Tics = 12; Action = "A_MinotaurAtk1"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_ATK2_1"; Sprite = "MNTR"; Frame = 6; Tics = 10; Action = "A_MinotaurDecide"; Next state = "MNTR_ATK2_2"; } State { ID = "MNTR_ATK2_2"; Sprite = "MNTR"; Frame = 9; Tics = 4; Action = "A_FaceTarget"; Next state = "MNTR_ATK2_3"; } State { ID = "MNTR_ATK2_3"; Sprite = "MNTR"; Frame = 10; Tics = 9; Action = "A_MinotaurAtk2"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_ATK3_1"; Sprite = "MNTR"; Frame = 6; Tics = 10; Action = "A_FaceTarget"; Next state = "MNTR_ATK3_2"; } State { ID = "MNTR_ATK3_2"; Sprite = "MNTR"; Frame = 7; Tics = 7; Action = "A_FaceTarget"; Next state = "MNTR_ATK3_3"; } State { ID = "MNTR_ATK3_3"; Sprite = "MNTR"; Frame = 8; Tics = 12; Action = "A_MinotaurAtk3"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_ATK3_4"; Sprite = "MNTR"; Frame = 8; Tics = 12; Next state = "MNTR_ATK3_1"; } State { ID = "MNTR_ATK4_1"; Sprite = "MNTR"; Frame = 5; Tics = 2; Action = "A_MinotaurCharge"; Next state = "MNTR_ATK4_1"; } State { ID = "MNTR_PAIN1"; Sprite = "MNTR"; Frame = 4; Tics = 3; Next state = "MNTR_PAIN2"; } State { ID = "MNTR_PAIN2"; Sprite = "MNTR"; Frame = 4; Tics = 6; Action = "A_Pain"; Next state = "MNTR_WALK1"; } State { ID = "MNTR_DIE1"; Sprite = "MNTR"; Frame = 4; Tics = 6; Next state = "MNTR_DIE2"; } State { ID = "MNTR_DIE2"; Sprite = "MNTR"; Frame = 4; Tics = 2; Action = "A_Scream"; Next state = "MNTR_DIE3"; } State { ID = "MNTR_DIE3"; Sprite = "MNTR"; Frame = 4; Tics = 5; Action = "A_SmokePuffExit"; Next state = "MNTR_DIE4"; } State { ID = "MNTR_DIE4"; Sprite = "MNTR"; Frame = 4; Tics = 5; Next state = "MNTR_DIE5"; } State { ID = "MNTR_DIE5"; Sprite = "MNTR"; Frame = 4; Tics = 5; Action = "A_NoBlocking"; Next state = "MNTR_DIE6"; } State { ID = "MNTR_DIE6"; Sprite = "MNTR"; Frame = 4; Tics = 5; Next state = "MNTR_DIE7"; } State { ID = "MNTR_DIE7"; Sprite = "MNTR"; Frame = 4; Tics = 5; Action = "A_MinotaurFade1"; Next state = "MNTR_DIE8"; } State { ID = "MNTR_DIE8"; Sprite = "MNTR"; Frame = 4; Tics = 5; Action = "A_MinotaurFade0"; Next state = "MNTR_DIE9"; } State { ID = "MNTR_DIE9"; Sprite = "MNTR"; Frame = 4; Tics = 10; Next state = "NULL"; } State { ID = "MNTRFX1_1"; Sprite = "FX12"; Frame = 32768; Tics = 6; Next state = "MNTRFX1_2"; } State { ID = "MNTRFX1_2"; Sprite = "FX12"; Frame = 32769; Tics = 6; Next state = "MNTRFX1_1"; } State { ID = "MNTRFXI1_1"; Sprite = "FX12"; Frame = 32770; Tics = 5; Next state = "MNTRFXI1_2"; } State { ID = "MNTRFXI1_2"; Sprite = "FX12"; Frame = 32771; Tics = 5; Next state = "MNTRFXI1_3"; } State { ID = "MNTRFXI1_3"; Sprite = "FX12"; Frame = 32772; Tics = 5; Next state = "MNTRFXI1_4"; } State { ID = "MNTRFXI1_4"; Sprite = "FX12"; Frame = 32773; Tics = 5; Next state = "MNTRFXI1_5"; } State { ID = "MNTRFXI1_5"; Sprite = "FX12"; Frame = 32774; Tics = 5; Next state = "MNTRFXI1_6"; } State { ID = "MNTRFXI1_6"; Sprite = "FX12"; Frame = 32775; Tics = 5; Next state = "NULL"; } State { ID = "MNTRFX2_1"; Sprite = "FX13"; Frame = 0; Tics = 2; Action = "A_MntrFloorFire"; Next state = "MNTRFX2_1"; } State { ID = "MNTRFXI2_1"; Sprite = "FX13"; Frame = 32776; Tics = 4; Action = "A_Explode"; Next state = "MNTRFXI2_2"; } State { ID = "MNTRFXI2_2"; Sprite = "FX13"; Frame = 32777; Tics = 4; Next state = "MNTRFXI2_3"; } State { ID = "MNTRFXI2_3"; Sprite = "FX13"; Frame = 32778; Tics = 4; Next state = "MNTRFXI2_4"; } State { ID = "MNTRFXI2_4"; Sprite = "FX13"; Frame = 32779; Tics = 4; Next state = "MNTRFXI2_5"; } State { ID = "MNTRFXI2_5"; Sprite = "FX13"; Frame = 32780; Tics = 4; Next state = "NULL"; } State { ID = "MNTRFX3_1"; Sprite = "FX13"; Frame = 32771; Tics = 4; Next state = "MNTRFX3_2"; } State { ID = "MNTRFX3_2"; Sprite = "FX13"; Frame = 32770; Tics = 4; Next state = "MNTRFX3_3"; } State { ID = "MNTRFX3_3"; Sprite = "FX13"; Frame = 32769; Tics = 5; Next state = "MNTRFX3_4"; } State { ID = "MNTRFX3_4"; Sprite = "FX13"; Frame = 32770; Tics = 5; Next state = "MNTRFX3_5"; } State { ID = "MNTRFX3_5"; Sprite = "FX13"; Frame = 32771; Tics = 5; Next state = "MNTRFX3_6"; } State { ID = "MNTRFX3_6"; Sprite = "FX13"; Frame = 32772; Tics = 5; Next state = "MNTRFX3_7"; } State { ID = "MNTRFX3_7"; Sprite = "FX13"; Frame = 32773; Tics = 4; Next state = "MNTRFX3_8"; } State { ID = "MNTRFX3_8"; Sprite = "FX13"; Frame = 32774; Tics = 4; Next state = "MNTRFX3_9"; } State { ID = "MNTRFX3_9"; Sprite = "FX13"; Frame = 32775; Tics = 4; Next state = "NULL"; } State { ID = "MINOSMOKE1"; Sprite = "MNSM"; Frame = 0; Tics = 3; Next state = "MINOSMOKE2"; } State { ID = "MINOSMOKE2"; Sprite = "MNSM"; Frame = 1; Tics = 3; Next state = "MINOSMOKE3"; } State { ID = "MINOSMOKE3"; Sprite = "MNSM"; Frame = 2; Tics = 3; Next state = "MINOSMOKE4"; } State { ID = "MINOSMOKE4"; Sprite = "MNSM"; Frame = 3; Tics = 3; Next state = "MINOSMOKE5"; } State { ID = "MINOSMOKE5"; Sprite = "MNSM"; Frame = 4; Tics = 3; Next state = "MINOSMOKE6"; } State { ID = "MINOSMOKE6"; Sprite = "MNSM"; Frame = 5; Tics = 3; Next state = "MINOSMOKE7"; } State { ID = "MINOSMOKE7"; Sprite = "MNSM"; Frame = 6; Tics = 3; Next state = "MINOSMOKE8"; } State { ID = "MINOSMOKE8"; Sprite = "MNSM"; Frame = 7; Tics = 3; Next state = "MINOSMOKE9"; } State { ID = "MINOSMOKE9"; Sprite = "MNSM"; Frame = 8; Tics = 3; Next state = "MINOSMOKE0"; } State { ID = "MINOSMOKE0"; Sprite = "MNSM"; Frame = 9; Tics = 3; Next state = "MINOSMOKEA"; } State { ID = "MINOSMOKEA"; Sprite = "MNSM"; Frame = 10; Tics = 3; Next state = "MINOSMOKEB"; } State { ID = "MINOSMOKEB"; Sprite = "MNSM"; Frame = 11; Tics = 3; Next state = "MINOSMOKEC"; } State { ID = "MINOSMOKEC"; Sprite = "MNSM"; Frame = 12; Tics = 3; Next state = "MINOSMOKED"; } State { ID = "MINOSMOKED"; Sprite = "MNSM"; Frame = 13; Tics = 3; Next state = "MINOSMOKEE"; } State { ID = "MINOSMOKEE"; Sprite = "MNSM"; Frame = 14; Tics = 3; Next state = "MINOSMOKEF"; } State { ID = "MINOSMOKEF"; Sprite = "MNSM"; Frame = 15; Tics = 3; Next state = "MINOSMOKEG"; } State { ID = "MINOSMOKEG"; Sprite = "MNSM"; Frame = 16; Tics = 3; Next state = "NULL"; } State { ID = "MINOSMOKEX1"; Sprite = "MNSM"; Frame = 0; Tics = 3; Next state = "MINOSMOKEX2"; } State { ID = "MINOSMOKEX2"; Sprite = "MNSM"; Frame = 1; Tics = 3; Next state = "MINOSMOKEX3"; } State { ID = "MINOSMOKEX3"; Sprite = "MNSM"; Frame = 2; Tics = 3; Next state = "MINOSMOKEX4"; } State { ID = "MINOSMOKEX4"; Sprite = "MNSM"; Frame = 3; Tics = 3; Next state = "MINOSMOKEX5"; } State { ID = "MINOSMOKEX5"; Sprite = "MNSM"; Frame = 4; Tics = 3; Next state = "MINOSMOKEX6"; } State { ID = "MINOSMOKEX6"; Sprite = "MNSM"; Frame = 5; Tics = 3; Next state = "MINOSMOKEX7"; } State { ID = "MINOSMOKEX7"; Sprite = "MNSM"; Frame = 6; Tics = 3; Next state = "MINOSMOKEX8"; } State { ID = "MINOSMOKEX8"; Sprite = "MNSM"; Frame = 7; Tics = 3; Next state = "MINOSMOKEX9"; } State { ID = "MINOSMOKEX9"; Sprite = "MNSM"; Frame = 8; Tics = 3; Next state = "MINOSMOKEX0"; } State { ID = "MINOSMOKEX0"; Sprite = "MNSM"; Frame = 9; Tics = 3; Next state = "MINOSMOKEXA"; } State { ID = "MINOSMOKEXA"; Sprite = "MNSM"; Frame = 8; Tics = 3; Next state = "MINOSMOKEXB"; } State { ID = "MINOSMOKEXB"; Sprite = "MNSM"; Frame = 7; Tics = 3; Next state = "MINOSMOKEXC"; } State { ID = "MINOSMOKEXC"; Sprite = "MNSM"; Frame = 6; Tics = 3; Next state = "MINOSMOKEXD"; } State { ID = "MINOSMOKEXD"; Sprite = "MNSM"; Frame = 5; Tics = 3; Next state = "MINOSMOKEXE"; } State { ID = "MINOSMOKEXE"; Sprite = "MNSM"; Frame = 4; Tics = 3; Next state = "MINOSMOKEXF"; } State { ID = "MINOSMOKEXF"; Sprite = "MNSM"; Frame = 3; Tics = 3; Next state = "MINOSMOKEXG"; } State { ID = "MINOSMOKEXG"; Sprite = "MNSM"; Frame = 2; Tics = 3; Next state = "MINOSMOKEXH"; } State { ID = "MINOSMOKEXH"; Sprite = "MNSM"; Frame = 1; Tics = 3; Next state = "MINOSMOKEXI"; } State { ID = "MINOSMOKEXI"; Sprite = "MNSM"; Frame = 0; Tics = 3; Next state = "NULL"; } State { ID = "SERPENT_LOOK1"; Sprite = "SSPT"; Frame = 7; Tics = 10; Action = "A_Look"; Next state = "SERPENT_LOOK1"; } State { ID = "SERPENT_SWIM1"; Sprite = "SSPT"; Frame = 7; Tics = 1; Action = "A_SerpentChase"; Next state = "SERPENT_SWIM2"; } State { ID = "SERPENT_SWIM2"; Sprite = "SSPT"; Frame = 7; Tics = 1; Action = "A_SerpentChase"; Next state = "SERPENT_SWIM3"; } State { ID = "SERPENT_SWIM3"; Sprite = "SSPT"; Frame = 7; Tics = 2; Action = "A_SerpentHumpDecide"; Next state = "SERPENT_SWIM1"; } State { ID = "SERPENT_HUMP1"; Sprite = "SSPT"; Frame = 7; Tics = 3; Action = "A_SerpentUnHide"; Next state = "SERPENT_HUMP2"; } State { ID = "SERPENT_HUMP2"; Sprite = "SSPT"; Frame = 4; Tics = 3; Action = "A_SerpentRaiseHump"; Next state = "SERPENT_HUMP3"; } State { ID = "SERPENT_HUMP3"; Sprite = "SSPT"; Frame = 5; Tics = 3; Action = "A_SerpentRaiseHump"; Next state = "SERPENT_HUMP4"; } State { ID = "SERPENT_HUMP4"; Sprite = "SSPT"; Frame = 6; Tics = 3; Action = "A_SerpentRaiseHump"; Next state = "SERPENT_HUMP5"; } State { ID = "SERPENT_HUMP5"; Sprite = "SSPT"; Frame = 4; Tics = 3; Action = "A_SerpentRaiseHump"; Next state = "SERPENT_HUMP6"; } State { ID = "SERPENT_HUMP6"; Sprite = "SSPT"; Frame = 5; Tics = 3; Action = "A_SerpentRaiseHump"; Next state = "SERPENT_HUMP7"; } State { ID = "SERPENT_HUMP7"; Sprite = "SSPT"; Frame = 6; Tics = 3; Next state = "SERPENT_HUMP8"; } State { ID = "SERPENT_HUMP8"; Sprite = "SSPT"; Frame = 4; Tics = 3; Next state = "SERPENT_HUMP9"; } State { ID = "SERPENT_HUMP9"; Sprite = "SSPT"; Frame = 5; Tics = 3; Next state = "SERPENT_HUMP10"; } State { ID = "SERPENT_HUMP10"; Sprite = "SSPT"; Frame = 6; Tics = 3; Action = "A_SerpentLowerHump"; Next state = "SERPENT_HUMP11"; } State { ID = "SERPENT_HUMP11"; Sprite = "SSPT"; Frame = 4; Tics = 3; Action = "A_SerpentLowerHump"; Next state = "SERPENT_HUMP12"; } State { ID = "SERPENT_HUMP12"; Sprite = "SSPT"; Frame = 5; Tics = 3; Action = "A_SerpentLowerHump"; Next state = "SERPENT_HUMP13"; } State { ID = "SERPENT_HUMP13"; Sprite = "SSPT"; Frame = 6; Tics = 3; Action = "A_SerpentLowerHump"; Next state = "SERPENT_HUMP14"; } State { ID = "SERPENT_HUMP14"; Sprite = "SSPT"; Frame = 4; Tics = 3; Action = "A_SerpentLowerHump"; Next state = "SERPENT_HUMP15"; } State { ID = "SERPENT_HUMP15"; Sprite = "SSPT"; Frame = 5; Tics = 3; Action = "A_SerpentHide"; Next state = "SERPENT_SWIM1"; } State { ID = "SERPENT_SURFACE1"; Sprite = "SSPT"; Frame = 0; Tics = 1; Action = "A_UnHideThing"; Next state = "SERPENT_SURFACE2"; } State { ID = "SERPENT_SURFACE2"; Sprite = "SSPT"; Frame = 0; Tics = 1; Action = "A_SerpentBirthScream"; Next state = "SERPENT_SURFACE3"; } State { ID = "SERPENT_SURFACE3"; Sprite = "SSPT"; Frame = 1; Tics = 3; Action = "A_SetShootable"; Next state = "SERPENT_SURFACE4"; } State { ID = "SERPENT_SURFACE4"; Sprite = "SSPT"; Frame = 2; Tics = 3; Next state = "SERPENT_SURFACE5"; } State { ID = "SERPENT_SURFACE5"; Sprite = "SSPT"; Frame = 3; Tics = 4; Action = "A_SerpentCheckForAttack"; Next state = "SERPENT_DIVE1"; } State { ID = "SERPENT_DIVE1"; Sprite = "SSDV"; Frame = 0; Tics = 4; Next state = "SERPENT_DIVE2"; } State { ID = "SERPENT_DIVE2"; Sprite = "SSDV"; Frame = 1; Tics = 4; Next state = "SERPENT_DIVE3"; } State { ID = "SERPENT_DIVE3"; Sprite = "SSDV"; Frame = 2; Tics = 4; Next state = "SERPENT_DIVE4"; } State { ID = "SERPENT_DIVE4"; Sprite = "SSDV"; Frame = 3; Tics = 4; Action = "A_UnSetShootable"; Next state = "SERPENT_DIVE5"; } State { ID = "SERPENT_DIVE5"; Sprite = "SSDV"; Frame = 4; Tics = 3; Action = "A_SerpentDiveSound"; Next state = "SERPENT_DIVE6"; } State { ID = "SERPENT_DIVE6"; Sprite = "SSDV"; Frame = 5; Tics = 3; Next state = "SERPENT_DIVE7"; } State { ID = "SERPENT_DIVE7"; Sprite = "SSDV"; Frame = 6; Tics = 4; Next state = "SERPENT_DIVE8"; } State { ID = "SERPENT_DIVE8"; Sprite = "SSDV"; Frame = 7; Tics = 4; Next state = "SERPENT_DIVE9"; } State { ID = "SERPENT_DIVE9"; Sprite = "SSDV"; Frame = 8; Tics = 3; Next state = "SERPENT_DIVE10"; } State { ID = "SERPENT_DIVE10"; Sprite = "SSDV"; Frame = 9; Tics = 3; Action = "A_SerpentHide"; Next state = "SERPENT_SWIM1"; } State { ID = "SERPENT_WALK1"; Sprite = "SSPT"; Frame = 8; Tics = 5; Action = "A_SerpentWalk"; Next state = "SERPENT_WALK2"; } State { ID = "SERPENT_WALK2"; Sprite = "SSPT"; Frame = 9; Tics = 5; Action = "A_SerpentWalk"; Next state = "SERPENT_WALK3"; } State { ID = "SERPENT_WALK3"; Sprite = "SSPT"; Frame = 8; Tics = 5; Action = "A_SerpentWalk"; Next state = "SERPENT_WALK4"; } State { ID = "SERPENT_WALK4"; Sprite = "SSPT"; Frame = 9; Tics = 5; Action = "A_SerpentCheckForAttack"; Next state = "SERPENT_DIVE1"; } State { ID = "SERPENT_PAIN1"; Sprite = "SSPT"; Frame = 11; Tics = 5; Next state = "SERPENT_PAIN2"; } State { ID = "SERPENT_PAIN2"; Sprite = "SSPT"; Frame = 11; Tics = 5; Action = "A_Pain"; Next state = "SERPENT_DIVE1"; } State { ID = "SERPENT_ATK1"; Sprite = "SSPT"; Frame = 10; Tics = 6; Action = "A_FaceTarget"; Next state = "SERPENT_ATK2"; } State { ID = "SERPENT_ATK2"; Sprite = "SSPT"; Frame = 11; Tics = 5; Action = "A_SerpentChooseAttack"; Next state = "SERPENT_MELEE1"; } State { ID = "SERPENT_MELEE1"; Sprite = "SSPT"; Frame = 13; Tics = 5; Action = "A_SerpentMeleeAttack"; Next state = "SERPENT_DIVE1"; } State { ID = "SERPENT_MISSILE1"; Sprite = "SSPT"; Frame = 13; Tics = 5; Action = "A_SerpentMissileAttack"; Next state = "SERPENT_DIVE1"; } State { ID = "SERPENT_DIE1"; Sprite = "SSPT"; Frame = 14; Tics = 4; Next state = "SERPENT_DIE2"; } State { ID = "SERPENT_DIE2"; Sprite = "SSPT"; Frame = 15; Tics = 4; Action = "A_Scream"; Next state = "SERPENT_DIE3"; } State { ID = "SERPENT_DIE3"; Sprite = "SSPT"; Frame = 16; Tics = 4; Action = "A_NoBlocking"; Next state = "SERPENT_DIE4"; } State { ID = "SERPENT_DIE4"; Sprite = "SSPT"; Frame = 17; Tics = 4; Next state = "SERPENT_DIE5"; } State { ID = "SERPENT_DIE5"; Sprite = "SSPT"; Frame = 18; Tics = 4; Next state = "SERPENT_DIE6"; } State { ID = "SERPENT_DIE6"; Sprite = "SSPT"; Frame = 19; Tics = 4; Next state = "SERPENT_DIE7"; } State { ID = "SERPENT_DIE7"; Sprite = "SSPT"; Frame = 20; Tics = 4; Next state = "SERPENT_DIE8"; } State { ID = "SERPENT_DIE8"; Sprite = "SSPT"; Frame = 21; Tics = 4; Next state = "SERPENT_DIE9"; } State { ID = "SERPENT_DIE9"; Sprite = "SSPT"; Frame = 22; Tics = 4; Next state = "SERPENT_DIE10"; } State { ID = "SERPENT_DIE10"; Sprite = "SSPT"; Frame = 23; Tics = 4; Next state = "SERPENT_DIE11"; } State { ID = "SERPENT_DIE11"; Sprite = "SSPT"; Frame = 24; Tics = 4; Next state = "SERPENT_DIE12"; } State { ID = "SERPENT_DIE12"; Sprite = "SSPT"; Frame = 25; Tics = 4; Next state = "NULL"; } State { ID = "SERPENT_XDIE1"; Sprite = "SSXD"; Frame = 0; Tics = 4; Next state = "SERPENT_XDIE2"; } State { ID = "SERPENT_XDIE2"; Sprite = "SSXD"; Frame = 1; Tics = 4; Action = "A_SerpentHeadPop"; Next state = "SERPENT_XDIE3"; } State { ID = "SERPENT_XDIE3"; Sprite = "SSXD"; Frame = 2; Tics = 4; Action = "A_NoBlocking"; Next state = "SERPENT_XDIE4"; } State { ID = "SERPENT_XDIE4"; Sprite = "SSXD"; Frame = 3; Tics = 4; Next state = "SERPENT_XDIE5"; } State { ID = "SERPENT_XDIE5"; Sprite = "SSXD"; Frame = 4; Tics = 4; Next state = "SERPENT_XDIE6"; } State { ID = "SERPENT_XDIE6"; Sprite = "SSXD"; Frame = 5; Tics = 3; Next state = "SERPENT_XDIE7"; } State { ID = "SERPENT_XDIE7"; Sprite = "SSXD"; Frame = 6; Tics = 3; Next state = "SERPENT_XDIE8"; } State { ID = "SERPENT_XDIE8"; Sprite = "SSXD"; Frame = 7; Tics = 3; Action = "A_SerpentSpawnGibs"; Next state = "NULL"; } State { ID = "SERPENT_ICE"; Sprite = "SSPT"; Frame = 26; Tics = 5; Action = "A_FreezeDeath"; Next state = "SERPENT_ICE2"; } State { ID = "SERPENT_ICE2"; Sprite = "SSPT"; Frame = 26; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "SERPENT_ICE2"; } State { ID = "SERPENT_FX1"; Sprite = "SSFX"; Frame = 32768; Tics = 3; Action = "A_ContMobjSound"; Next state = "SERPENT_FX2"; } State { ID = "SERPENT_FX2"; Sprite = "SSFX"; Frame = 32769; Tics = 3; Next state = "SERPENT_FX3"; } State { ID = "SERPENT_FX3"; Sprite = "SSFX"; Frame = 32768; Tics = 3; Next state = "SERPENT_FX4"; } State { ID = "SERPENT_FX4"; Sprite = "SSFX"; Frame = 32769; Tics = 3; Next state = "SERPENT_FX1"; } State { ID = "SERPENT_FX_X1"; Sprite = "SSFX"; Frame = 32770; Tics = 4; Next state = "SERPENT_FX_X2"; } State { ID = "SERPENT_FX_X2"; Sprite = "SSFX"; Frame = 32771; Tics = 4; Next state = "SERPENT_FX_X3"; } State { ID = "SERPENT_FX_X3"; Sprite = "SSFX"; Frame = 32772; Tics = 4; Next state = "SERPENT_FX_X4"; } State { ID = "SERPENT_FX_X4"; Sprite = "SSFX"; Frame = 32773; Tics = 4; Next state = "SERPENT_FX_X5"; } State { ID = "SERPENT_FX_X5"; Sprite = "SSFX"; Frame = 32774; Tics = 4; Next state = "SERPENT_FX_X6"; } State { ID = "SERPENT_FX_X6"; Sprite = "SSFX"; Frame = 32775; Tics = 4; Next state = "NULL"; } State { ID = "SERPENT_HEAD1"; Sprite = "SSXD"; Frame = 8; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD2"; } State { ID = "SERPENT_HEAD2"; Sprite = "SSXD"; Frame = 9; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD3"; } State { ID = "SERPENT_HEAD3"; Sprite = "SSXD"; Frame = 10; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD4"; } State { ID = "SERPENT_HEAD4"; Sprite = "SSXD"; Frame = 11; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD5"; } State { ID = "SERPENT_HEAD5"; Sprite = "SSXD"; Frame = 12; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD6"; } State { ID = "SERPENT_HEAD6"; Sprite = "SSXD"; Frame = 13; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD7"; } State { ID = "SERPENT_HEAD7"; Sprite = "SSXD"; Frame = 14; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD8"; } State { ID = "SERPENT_HEAD8"; Sprite = "SSXD"; Frame = 15; Tics = 4; Action = "A_SerpentHeadCheck"; Next state = "SERPENT_HEAD1"; } State { ID = "SERPENT_HEAD_X1"; Sprite = "SSXD"; Frame = 18; Tics = -1; Next state = "SERPENT_HEAD_X1"; } State { ID = "SERPENT_GIB1_1"; Sprite = "SSXD"; Frame = 16; Tics = 6; Next state = "SERPENT_GIB1_2"; } State { ID = "SERPENT_GIB1_2"; Sprite = "SSXD"; Frame = 16; Tics = 6; Action = "A_FloatGib"; Next state = "SERPENT_GIB1_3"; } State { ID = "SERPENT_GIB1_3"; Sprite = "SSXD"; Frame = 16; Tics = 8; Action = "A_FloatGib"; Next state = "SERPENT_GIB1_4"; } State { ID = "SERPENT_GIB1_4"; Sprite = "SSXD"; Frame = 16; Tics = 8; Action = "A_FloatGib"; Next state = "SERPENT_GIB1_5"; } State { ID = "SERPENT_GIB1_5"; Sprite = "SSXD"; Frame = 16; Tics = 12; Action = "A_FloatGib"; Next state = "SERPENT_GIB1_6"; } State { ID = "SERPENT_GIB1_6"; Sprite = "SSXD"; Frame = 16; Tics = 12; Action = "A_FloatGib"; Next state = "SERPENT_GIB1_7"; } State { ID = "SERPENT_GIB1_7"; Sprite = "SSXD"; Frame = 16; Tics = 232; Action = "A_DelayGib"; Next state = "SERPENT_GIB1_8"; } State { ID = "SERPENT_GIB1_8"; Sprite = "SSXD"; Frame = 16; Tics = 12; Action = "A_SinkGib"; Next state = "SERPENT_GIB1_9"; } State { ID = "SERPENT_GIB1_9"; Sprite = "SSXD"; Frame = 16; Tics = 12; Action = "A_SinkGib"; Next state = "SERPENT_GIB1_10"; } State { ID = "SERPENT_GIB1_10"; Sprite = "SSXD"; Frame = 16; Tics = 8; Action = "A_SinkGib"; Next state = "SERPENT_GIB1_11"; } State { ID = "SERPENT_GIB1_11"; Sprite = "SSXD"; Frame = 16; Tics = 8; Action = "A_SinkGib"; Next state = "SERPENT_GIB1_12"; } State { ID = "SERPENT_GIB1_12"; Sprite = "SSXD"; Frame = 16; Tics = 8; Action = "A_SinkGib"; Next state = "NULL"; } State { ID = "SERPENT_GIB2_1"; Sprite = "SSXD"; Frame = 17; Tics = 6; Next state = "SERPENT_GIB2_2"; } State { ID = "SERPENT_GIB2_2"; Sprite = "SSXD"; Frame = 17; Tics = 6; Action = "A_FloatGib"; Next state = "SERPENT_GIB2_3"; } State { ID = "SERPENT_GIB2_3"; Sprite = "SSXD"; Frame = 17; Tics = 8; Action = "A_FloatGib"; Next state = "SERPENT_GIB2_4"; } State { ID = "SERPENT_GIB2_4"; Sprite = "SSXD"; Frame = 17; Tics = 8; Action = "A_FloatGib"; Next state = "SERPENT_GIB2_5"; } State { ID = "SERPENT_GIB2_5"; Sprite = "SSXD"; Frame = 17; Tics = 12; Action = "A_FloatGib"; Next state = "SERPENT_GIB2_6"; } State { ID = "SERPENT_GIB2_6"; Sprite = "SSXD"; Frame = 17; Tics = 12; Action = "A_FloatGib"; Next state = "SERPENT_GIB2_7"; } State { ID = "SERPENT_GIB2_7"; Sprite = "SSXD"; Frame = 17; Tics = 232; Action = "A_DelayGib"; Next state = "SERPENT_GIB2_8"; } State { ID = "SERPENT_GIB2_8"; Sprite = "SSXD"; Frame = 17; Tics = 12; Action = "A_SinkGib"; Next state = "SERPENT_GIB2_9"; } State { ID = "SERPENT_GIB2_9"; Sprite = "SSXD"; Frame = 17; Tics = 12; Action = "A_SinkGib"; Next state = "SERPENT_GIB2_10"; } State { ID = "SERPENT_GIB2_10"; Sprite = "SSXD"; Frame = 17; Tics = 8; Action = "A_SinkGib"; Next state = "SERPENT_GIB2_11"; } State { ID = "SERPENT_GIB2_11"; Sprite = "SSXD"; Frame = 17; Tics = 8; Action = "A_SinkGib"; Next state = "SERPENT_GIB2_12"; } State { ID = "SERPENT_GIB2_12"; Sprite = "SSXD"; Frame = 17; Tics = 8; Action = "A_SinkGib"; Next state = "NULL"; } State { ID = "SERPENT_GIB3_1"; Sprite = "SSXD"; Frame = 19; Tics = 6; Next state = "SERPENT_GIB3_2"; } State { ID = "SERPENT_GIB3_2"; Sprite = "SSXD"; Frame = 19; Tics = 6; Action = "A_FloatGib"; Next state = "SERPENT_GIB3_3"; } State { ID = "SERPENT_GIB3_3"; Sprite = "SSXD"; Frame = 19; Tics = 8; Action = "A_FloatGib"; Next state = "SERPENT_GIB3_4"; } State { ID = "SERPENT_GIB3_4"; Sprite = "SSXD"; Frame = 19; Tics = 8; Action = "A_FloatGib"; Next state = "SERPENT_GIB3_5"; } State { ID = "SERPENT_GIB3_5"; Sprite = "SSXD"; Frame = 19; Tics = 12; Action = "A_FloatGib"; Next state = "SERPENT_GIB3_6"; } State { ID = "SERPENT_GIB3_6"; Sprite = "SSXD"; Frame = 19; Tics = 12; Action = "A_FloatGib"; Next state = "SERPENT_GIB3_7"; } State { ID = "SERPENT_GIB3_7"; Sprite = "SSXD"; Frame = 19; Tics = 232; Action = "A_DelayGib"; Next state = "SERPENT_GIB3_8"; } State { ID = "SERPENT_GIB3_8"; Sprite = "SSXD"; Frame = 19; Tics = 12; Action = "A_SinkGib"; Next state = "SERPENT_GIB3_9"; } State { ID = "SERPENT_GIB3_9"; Sprite = "SSXD"; Frame = 19; Tics = 12; Action = "A_SinkGib"; Next state = "SERPENT_GIB3_10"; } State { ID = "SERPENT_GIB3_10"; Sprite = "SSXD"; Frame = 19; Tics = 8; Action = "A_SinkGib"; Next state = "SERPENT_GIB3_11"; } State { ID = "SERPENT_GIB3_11"; Sprite = "SSXD"; Frame = 19; Tics = 8; Action = "A_SinkGib"; Next state = "SERPENT_GIB3_12"; } State { ID = "SERPENT_GIB3_12"; Sprite = "SSXD"; Frame = 19; Tics = 8; Action = "A_SinkGib"; Next state = "NULL"; } State { ID = "BISHOP_LOOK1"; Sprite = "BISH"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "BISHOP_LOOK1"; } State { ID = "BISHOP_DECIDE"; Sprite = "BISH"; Frame = 0; Tics = 1; Action = "A_BishopDecide"; Next state = "BISHOP_WALK1"; } State { ID = "BISHOP_BLUR1"; Sprite = "BISH"; Frame = 0; Tics = 2; Action = "A_BishopDoBlur"; Next state = "BISHOP_BLUR2"; } State { ID = "BISHOP_BLUR2"; Sprite = "BISH"; Frame = 0; Tics = 4; Action = "A_BishopSpawnBlur"; Next state = "BISHOP_BLUR2"; } State { ID = "BISHOP_WALK1"; Sprite = "BISH"; Frame = 0; Tics = 2; Action = "A_Chase"; Next state = "BISHOP_WALK2"; } State { ID = "BISHOP_WALK2"; Sprite = "BISH"; Frame = 0; Tics = 2; Action = "A_BishopChase"; Next state = "BISHOP_WALK3"; } State { ID = "BISHOP_WALK3"; Sprite = "BISH"; Frame = 0; Tics = 2; Next state = "BISHOP_WALK4"; } State { ID = "BISHOP_WALK4"; Sprite = "BISH"; Frame = 1; Tics = 2; Action = "A_BishopChase"; Next state = "BISHOP_WALK5"; } State { ID = "BISHOP_WALK5"; Sprite = "BISH"; Frame = 1; Tics = 2; Action = "A_Chase"; Next state = "BISHOP_WALK6"; } State { ID = "BISHOP_WALK6"; Sprite = "BISH"; Frame = 1; Tics = 2; Action = "A_BishopChase"; Next state = "BISHOP_DECIDE"; } State { ID = "BISHOP_ATK1"; Sprite = "BISH"; Frame = 0; Tics = 3; Action = "A_FaceTarget"; Next state = "BISHOP_ATK2"; } State { ID = "BISHOP_ATK2"; Sprite = "BISH"; Frame = 32771; Tics = 3; Action = "A_FaceTarget"; Next state = "BISHOP_ATK3"; } State { ID = "BISHOP_ATK3"; Sprite = "BISH"; Frame = 32772; Tics = 3; Action = "A_FaceTarget"; Next state = "BISHOP_ATK4"; } State { ID = "BISHOP_ATK4"; Sprite = "BISH"; Frame = 32773; Tics = 3; Action = "A_BishopAttack"; Next state = "BISHOP_ATK5"; } State { ID = "BISHOP_ATK5"; Sprite = "BISH"; Frame = 32773; Tics = 5; Action = "A_BishopAttack2"; Next state = "BISHOP_ATK5"; } State { ID = "BISHOP_PAIN1"; Sprite = "BISH"; Frame = 2; Tics = 6; Action = "A_Pain"; Next state = "BISHOP_PAIN2"; } State { ID = "BISHOP_PAIN2"; Sprite = "BISH"; Frame = 2; Tics = 6; Action = "A_BishopPainBlur"; Next state = "BISHOP_PAIN3"; } State { ID = "BISHOP_PAIN3"; Sprite = "BISH"; Frame = 2; Tics = 6; Action = "A_BishopPainBlur"; Next state = "BISHOP_PAIN4"; } State { ID = "BISHOP_PAIN4"; Sprite = "BISH"; Frame = 2; Tics = 6; Action = "A_BishopPainBlur"; Next state = "BISHOP_PAIN5"; } State { ID = "BISHOP_PAIN5"; Sprite = "BISH"; Frame = 2; Tics = 0; Next state = "BISHOP_WALK1"; } State { ID = "BISHOP_DEATH1"; Sprite = "BISH"; Frame = 6; Tics = 6; Next state = "BISHOP_DEATH2"; } State { ID = "BISHOP_DEATH2"; Sprite = "BISH"; Frame = 32775; Tics = 6; Action = "A_Scream"; Next state = "BISHOP_DEATH3"; } State { ID = "BISHOP_DEATH3"; Sprite = "BISH"; Frame = 32776; Tics = 5; Action = "A_NoBlocking"; Next state = "BISHOP_DEATH4"; } State { ID = "BISHOP_DEATH4"; Sprite = "BISH"; Frame = 32777; Tics = 5; Action = "A_Explode"; Next state = "BISHOP_DEATH5"; } State { ID = "BISHOP_DEATH5"; Sprite = "BISH"; Frame = 32778; Tics = 5; Next state = "BISHOP_DEATH6"; } State { ID = "BISHOP_DEATH6"; Sprite = "BISH"; Frame = 32779; Tics = 4; Next state = "BISHOP_DEATH7"; } State { ID = "BISHOP_DEATH7"; Sprite = "BISH"; Frame = 32780; Tics = 4; Next state = "BISHOP_DEATH8"; } State { ID = "BISHOP_DEATH8"; Sprite = "BISH"; Frame = 13; Tics = 4; Action = "A_BishopPuff"; Next state = "BISHOP_DEATH9"; } State { ID = "BISHOP_DEATH9"; Sprite = "BISH"; Frame = 14; Tics = 4; Action = "A_QueueCorpse"; Next state = "BISHOP_DEATH10"; } State { ID = "BISHOP_DEATH10"; Sprite = "BISH"; Frame = 15; Tics = -1; Next state = "NULL"; } State { ID = "BISHOP_ICE"; Sprite = "BISH"; Frame = 23; Tics = 5; Action = "A_FreezeDeath"; Next state = "BISHOP_ICE2"; } State { ID = "BISHOP_ICE2"; Sprite = "BISH"; Frame = 23; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "BISHOP_ICE2"; } State { ID = "BISHOP_PUFF1"; Sprite = "BISH"; Frame = 16; Tics = 5; Next state = "BISHOP_PUFF2"; } State { ID = "BISHOP_PUFF2"; Sprite = "BISH"; Frame = 17; Tics = 5; Next state = "BISHOP_PUFF3"; } State { ID = "BISHOP_PUFF3"; Sprite = "BISH"; Frame = 18; Tics = 5; Next state = "BISHOP_PUFF4"; } State { ID = "BISHOP_PUFF4"; Sprite = "BISH"; Frame = 19; Tics = 5; Next state = "BISHOP_PUFF5"; } State { ID = "BISHOP_PUFF5"; Sprite = "BISH"; Frame = 20; Tics = 6; Next state = "BISHOP_PUFF6"; } State { ID = "BISHOP_PUFF6"; Sprite = "BISH"; Frame = 21; Tics = 6; Next state = "BISHOP_PUFF7"; } State { ID = "BISHOP_PUFF7"; Sprite = "BISH"; Frame = 22; Tics = 5; Next state = "NULL"; } State { ID = "BISHOPBLUR1"; Sprite = "BISH"; Frame = 0; Tics = 16; Next state = "BISHOPBLUR2"; } State { ID = "BISHOPBLUR2"; Sprite = "BISH"; Frame = 0; Tics = 8; Action = "A_SetAltShadow"; Next state = "NULL"; } State { ID = "BISHOPPAINBLUR1"; Sprite = "BISH"; Frame = 2; Tics = 8; Next state = "NULL"; } State { ID = "BISHFX1_1"; Sprite = "BPFX"; Frame = 32768; Tics = 1; Action = "A_BishopMissileWeave"; Next state = "BISHFX1_2"; } State { ID = "BISHFX1_2"; Sprite = "BPFX"; Frame = 32769; Tics = 1; Action = "A_BishopMissileWeave"; Next state = "BISHFX1_3"; } State { ID = "BISHFX1_3"; Sprite = "BPFX"; Frame = 32768; Tics = 1; Action = "A_BishopMissileWeave"; Next state = "BISHFX1_4"; } State { ID = "BISHFX1_4"; Sprite = "BPFX"; Frame = 32769; Tics = 1; Action = "A_BishopMissileWeave"; Next state = "BISHFX1_5"; } State { ID = "BISHFX1_5"; Sprite = "BPFX"; Frame = 32769; Tics = 0; Action = "A_BishopMissileSeek"; Next state = "BISHFX1_1"; } State { ID = "BISHFXI1_1"; Sprite = "BPFX"; Frame = 32770; Tics = 4; Next state = "BISHFXI1_2"; } State { ID = "BISHFXI1_2"; Sprite = "BPFX"; Frame = 32771; Tics = 4; Next state = "BISHFXI1_3"; } State { ID = "BISHFXI1_3"; Sprite = "BPFX"; Frame = 32772; Tics = 4; Next state = "BISHFXI1_4"; } State { ID = "BISHFXI1_4"; Sprite = "BPFX"; Frame = 32773; Tics = 4; Next state = "BISHFXI1_5"; } State { ID = "BISHFXI1_5"; Sprite = "BPFX"; Frame = 32774; Tics = 3; Next state = "BISHFXI1_6"; } State { ID = "BISHFXI1_6"; Sprite = "BPFX"; Frame = 32775; Tics = 3; Next state = "NULL"; } State { ID = "DRAGON_LOOK1"; Sprite = "DRAG"; Frame = 3; Tics = 10; Action = "A_Look"; Next state = "DRAGON_LOOK1"; } State { ID = "DRAGON_INIT"; Sprite = "DRAG"; Frame = 2; Tics = 5; Next state = "DRAGON_INIT2"; } State { ID = "DRAGON_INIT2"; Sprite = "DRAG"; Frame = 1; Tics = 5; Next state = "DRAGON_INIT3"; } State { ID = "DRAGON_INIT3"; Sprite = "DRAG"; Frame = 0; Tics = 5; Action = "A_DragonInitFlight"; Next state = "DRAGON_WALK1"; } State { ID = "DRAGON_WALK1"; Sprite = "DRAG"; Frame = 1; Tics = 3; Action = "A_DragonFlap"; Next state = "DRAGON_WALK2"; } State { ID = "DRAGON_WALK2"; Sprite = "DRAG"; Frame = 1; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK3"; } State { ID = "DRAGON_WALK3"; Sprite = "DRAG"; Frame = 2; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK4"; } State { ID = "DRAGON_WALK4"; Sprite = "DRAG"; Frame = 2; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK5"; } State { ID = "DRAGON_WALK5"; Sprite = "DRAG"; Frame = 3; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK6"; } State { ID = "DRAGON_WALK6"; Sprite = "DRAG"; Frame = 3; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK7"; } State { ID = "DRAGON_WALK7"; Sprite = "DRAG"; Frame = 2; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK8"; } State { ID = "DRAGON_WALK8"; Sprite = "DRAG"; Frame = 2; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK9"; } State { ID = "DRAGON_WALK9"; Sprite = "DRAG"; Frame = 1; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK10"; } State { ID = "DRAGON_WALK10"; Sprite = "DRAG"; Frame = 1; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK11"; } State { ID = "DRAGON_WALK11"; Sprite = "DRAG"; Frame = 0; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK12"; } State { ID = "DRAGON_WALK12"; Sprite = "DRAG"; Frame = 0; Tics = 3; Action = "A_DragonFlight"; Next state = "DRAGON_WALK1"; } State { ID = "DRAGON_ATK1"; Sprite = "DRAG"; Frame = 4; Tics = 8; Action = "A_DragonAttack"; Next state = "DRAGON_WALK1"; } State { ID = "DRAGON_PAIN1"; Sprite = "DRAG"; Frame = 5; Tics = 10; Action = "A_DragonPain"; Next state = "DRAGON_WALK1"; } State { ID = "DRAGON_DEATH1"; Sprite = "DRAG"; Frame = 6; Tics = 5; Action = "A_Scream"; Next state = "DRAGON_DEATH2"; } State { ID = "DRAGON_DEATH2"; Sprite = "DRAG"; Frame = 7; Tics = 4; Action = "A_NoBlocking"; Next state = "DRAGON_DEATH3"; } State { ID = "DRAGON_DEATH3"; Sprite = "DRAG"; Frame = 8; Tics = 4; Next state = "DRAGON_DEATH4"; } State { ID = "DRAGON_DEATH4"; Sprite = "DRAG"; Frame = 9; Tics = 4; Action = "A_DragonCheckCrash"; Next state = "DRAGON_DEATH4"; } State { ID = "DRAGON_CRASH1"; Sprite = "DRAG"; Frame = 10; Tics = 5; Next state = "DRAGON_CRASH2"; } State { ID = "DRAGON_CRASH2"; Sprite = "DRAG"; Frame = 11; Tics = 5; Next state = "DRAGON_CRASH3"; } State { ID = "DRAGON_CRASH3"; Sprite = "DRAG"; Frame = 12; Tics = -1; Next state = "NULL"; } State { ID = "DRAGON_FX1_1"; Sprite = "DRFX"; Frame = 32768; Tics = 4; Next state = "DRAGON_FX1_2"; } State { ID = "DRAGON_FX1_2"; Sprite = "DRFX"; Frame = 32769; Tics = 4; Next state = "DRAGON_FX1_3"; } State { ID = "DRAGON_FX1_3"; Sprite = "DRFX"; Frame = 32770; Tics = 4; Next state = "DRAGON_FX1_4"; } State { ID = "DRAGON_FX1_4"; Sprite = "DRFX"; Frame = 32771; Tics = 4; Next state = "DRAGON_FX1_5"; } State { ID = "DRAGON_FX1_5"; Sprite = "DRFX"; Frame = 32772; Tics = 4; Next state = "DRAGON_FX1_6"; } State { ID = "DRAGON_FX1_6"; Sprite = "DRFX"; Frame = 32773; Tics = 4; Next state = "DRAGON_FX1_1"; } State { ID = "DRAGON_FX1_X1"; Sprite = "DRFX"; Frame = 32774; Tics = 4; Next state = "DRAGON_FX1_X2"; } State { ID = "DRAGON_FX1_X2"; Sprite = "DRFX"; Frame = 32775; Tics = 4; Next state = "DRAGON_FX1_X3"; } State { ID = "DRAGON_FX1_X3"; Sprite = "DRFX"; Frame = 32776; Tics = 4; Next state = "DRAGON_FX1_X4"; } State { ID = "DRAGON_FX1_X4"; Sprite = "DRFX"; Frame = 32777; Tics = 4; Action = "A_DragonFX2"; Next state = "DRAGON_FX1_X5"; } State { ID = "DRAGON_FX1_X5"; Sprite = "DRFX"; Frame = 32778; Tics = 3; Next state = "DRAGON_FX1_X6"; } State { ID = "DRAGON_FX1_X6"; Sprite = "DRFX"; Frame = 32779; Tics = 3; Next state = "NULL"; } State { ID = "DRAGON_FX2_1"; Sprite = "CFCF"; Frame = 32784; Tics = 1; Next state = "DRAGON_FX2_2"; } State { ID = "DRAGON_FX2_2"; Sprite = "CFCF"; Frame = 32784; Tics = 4; Action = "A_UnHideThing"; Next state = "DRAGON_FX2_3"; } State { ID = "DRAGON_FX2_3"; Sprite = "CFCF"; Frame = 32785; Tics = 3; Action = "A_Scream"; Next state = "DRAGON_FX2_4"; } State { ID = "DRAGON_FX2_4"; Sprite = "CFCF"; Frame = 32786; Tics = 4; Next state = "DRAGON_FX2_5"; } State { ID = "DRAGON_FX2_5"; Sprite = "CFCF"; Frame = 32787; Tics = 3; Action = "A_Explode"; Next state = "DRAGON_FX2_6"; } State { ID = "DRAGON_FX2_6"; Sprite = "CFCF"; Frame = 32788; Tics = 4; Next state = "DRAGON_FX2_7"; } State { ID = "DRAGON_FX2_7"; Sprite = "CFCF"; Frame = 32789; Tics = 3; Next state = "DRAGON_FX2_8"; } State { ID = "DRAGON_FX2_8"; Sprite = "CFCF"; Frame = 32790; Tics = 4; Next state = "DRAGON_FX2_9"; } State { ID = "DRAGON_FX2_9"; Sprite = "CFCF"; Frame = 32791; Tics = 3; Next state = "DRAGON_FX2_10"; } State { ID = "DRAGON_FX2_10"; Sprite = "CFCF"; Frame = 32792; Tics = 4; Next state = "DRAGON_FX2_11"; } State { ID = "DRAGON_FX2_11"; Sprite = "CFCF"; Frame = 32793; Tics = 3; Next state = "NULL"; } State { ID = "ARMOR_1"; Sprite = "ARM1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARMOR_2"; Sprite = "ARM2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARMOR_3"; Sprite = "ARM3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "ARMOR_4"; Sprite = "ARM4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "MANA1_1"; Sprite = "MAN1"; Frame = 32768; Tics = 4; Next state = "MANA1_2"; } State { ID = "MANA1_2"; Sprite = "MAN1"; Frame = 32769; Tics = 4; Next state = "MANA1_3"; } State { ID = "MANA1_3"; Sprite = "MAN1"; Frame = 32770; Tics = 4; Next state = "MANA1_4"; } State { ID = "MANA1_4"; Sprite = "MAN1"; Frame = 32771; Tics = 4; Next state = "MANA1_5"; } State { ID = "MANA1_5"; Sprite = "MAN1"; Frame = 32772; Tics = 4; Next state = "MANA1_6"; } State { ID = "MANA1_6"; Sprite = "MAN1"; Frame = 32773; Tics = 4; Next state = "MANA1_7"; } State { ID = "MANA1_7"; Sprite = "MAN1"; Frame = 32774; Tics = 4; Next state = "MANA1_8"; } State { ID = "MANA1_8"; Sprite = "MAN1"; Frame = 32775; Tics = 4; Next state = "MANA1_9"; } State { ID = "MANA1_9"; Sprite = "MAN1"; Frame = 32776; Tics = 4; Next state = "MANA1_1"; } State { ID = "MANA2_1"; Sprite = "MAN2"; Frame = 32768; Tics = 4; Next state = "MANA2_2"; } State { ID = "MANA2_2"; Sprite = "MAN2"; Frame = 32769; Tics = 4; Next state = "MANA2_3"; } State { ID = "MANA2_3"; Sprite = "MAN2"; Frame = 32770; Tics = 4; Next state = "MANA2_4"; } State { ID = "MANA2_4"; Sprite = "MAN2"; Frame = 32771; Tics = 4; Next state = "MANA2_5"; } State { ID = "MANA2_5"; Sprite = "MAN2"; Frame = 32772; Tics = 4; Next state = "MANA2_6"; } State { ID = "MANA2_6"; Sprite = "MAN2"; Frame = 32773; Tics = 4; Next state = "MANA2_7"; } State { ID = "MANA2_7"; Sprite = "MAN2"; Frame = 32774; Tics = 4; Next state = "MANA2_8"; } State { ID = "MANA2_8"; Sprite = "MAN2"; Frame = 32775; Tics = 4; Next state = "MANA2_9"; } State { ID = "MANA2_9"; Sprite = "MAN2"; Frame = 32776; Tics = 4; Next state = "MANA2_10"; } State { ID = "MANA2_10"; Sprite = "MAN2"; Frame = 32777; Tics = 4; Next state = "MANA2_11"; } State { ID = "MANA2_11"; Sprite = "MAN2"; Frame = 32778; Tics = 4; Next state = "MANA2_12"; } State { ID = "MANA2_12"; Sprite = "MAN2"; Frame = 32779; Tics = 4; Next state = "MANA2_13"; } State { ID = "MANA2_13"; Sprite = "MAN2"; Frame = 32780; Tics = 4; Next state = "MANA2_14"; } State { ID = "MANA2_14"; Sprite = "MAN2"; Frame = 32781; Tics = 4; Next state = "MANA2_15"; } State { ID = "MANA2_15"; Sprite = "MAN2"; Frame = 32782; Tics = 4; Next state = "MANA2_16"; } State { ID = "MANA2_16"; Sprite = "MAN2"; Frame = 32783; Tics = 4; Next state = "MANA2_1"; } State { ID = "MANA3_1"; Sprite = "MAN3"; Frame = 32768; Tics = 4; Next state = "MANA3_2"; } State { ID = "MANA3_2"; Sprite = "MAN3"; Frame = 32769; Tics = 4; Next state = "MANA3_3"; } State { ID = "MANA3_3"; Sprite = "MAN3"; Frame = 32770; Tics = 4; Next state = "MANA3_4"; } State { ID = "MANA3_4"; Sprite = "MAN3"; Frame = 32771; Tics = 4; Next state = "MANA3_5"; } State { ID = "MANA3_5"; Sprite = "MAN3"; Frame = 32772; Tics = 4; Next state = "MANA3_6"; } State { ID = "MANA3_6"; Sprite = "MAN3"; Frame = 32773; Tics = 4; Next state = "MANA3_7"; } State { ID = "MANA3_7"; Sprite = "MAN3"; Frame = 32774; Tics = 4; Next state = "MANA3_8"; } State { ID = "MANA3_8"; Sprite = "MAN3"; Frame = 32775; Tics = 4; Next state = "MANA3_9"; } State { ID = "MANA3_9"; Sprite = "MAN3"; Frame = 32776; Tics = 4; Next state = "MANA3_10"; } State { ID = "MANA3_10"; Sprite = "MAN3"; Frame = 32777; Tics = 4; Next state = "MANA3_11"; } State { ID = "MANA3_11"; Sprite = "MAN3"; Frame = 32778; Tics = 4; Next state = "MANA3_12"; } State { ID = "MANA3_12"; Sprite = "MAN3"; Frame = 32779; Tics = 4; Next state = "MANA3_13"; } State { ID = "MANA3_13"; Sprite = "MAN3"; Frame = 32780; Tics = 4; Next state = "MANA3_14"; } State { ID = "MANA3_14"; Sprite = "MAN3"; Frame = 32781; Tics = 4; Next state = "MANA3_15"; } State { ID = "MANA3_15"; Sprite = "MAN3"; Frame = 32782; Tics = 4; Next state = "MANA3_16"; } State { ID = "MANA3_16"; Sprite = "MAN3"; Frame = 32783; Tics = 4; Next state = "MANA3_1"; } State { ID = "KEY1"; Sprite = "KEY1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY2"; Sprite = "KEY2"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY3"; Sprite = "KEY3"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY4"; Sprite = "KEY4"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY5"; Sprite = "KEY5"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY6"; Sprite = "KEY6"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY7"; Sprite = "KEY7"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY8"; Sprite = "KEY8"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEY9"; Sprite = "KEY9"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEYA"; Sprite = "KEYA"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "KEYB"; Sprite = "KEYB"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "SND_WIND1"; Sprite = "TLGL"; Frame = 0; Tics = 1; Next state = "SND_WIND2"; } State { ID = "SND_WIND2"; Sprite = "TLGL"; Frame = 0; Tics = 200; Action = "A_ESound"; Next state = "SND_WIND2"; } State { ID = "SND_WATERFALL"; Sprite = "TLGL"; Frame = 0; Tics = 85; Action = "A_ESound"; Next state = "SND_WATERFALL"; } State { ID = "ETTIN_LOOK1"; Sprite = "ETTN"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "ETTIN_LOOK2"; } State { ID = "ETTIN_LOOK2"; Sprite = "ETTN"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "ETTIN_LOOK1"; } State { ID = "ETTIN_CHASE1"; Sprite = "ETTN"; Frame = 0; Tics = 5; Action = "A_Chase"; Next state = "ETTIN_CHASE2"; } State { ID = "ETTIN_CHASE2"; Sprite = "ETTN"; Frame = 1; Tics = 5; Action = "A_Chase"; Next state = "ETTIN_CHASE3"; } State { ID = "ETTIN_CHASE3"; Sprite = "ETTN"; Frame = 2; Tics = 5; Action = "A_Chase"; Next state = "ETTIN_CHASE4"; } State { ID = "ETTIN_CHASE4"; Sprite = "ETTN"; Frame = 3; Tics = 5; Action = "A_Chase"; Next state = "ETTIN_CHASE1"; } State { ID = "ETTIN_PAIN1"; Sprite = "ETTN"; Frame = 7; Tics = 7; Action = "A_Pain"; Next state = "ETTIN_CHASE1"; } State { ID = "ETTIN_ATK1_1"; Sprite = "ETTN"; Frame = 4; Tics = 6; Action = "A_FaceTarget"; Next state = "ETTIN_ATK1_2"; } State { ID = "ETTIN_ATK1_2"; Sprite = "ETTN"; Frame = 5; Tics = 6; Action = "A_FaceTarget"; Next state = "ETTIN_ATK1_3"; } State { ID = "ETTIN_ATK1_3"; Sprite = "ETTN"; Frame = 6; Tics = 8; Action = "A_EttinAttack"; Next state = "ETTIN_CHASE1"; } State { ID = "ETTIN_DEATH1_1"; Sprite = "ETTN"; Frame = 8; Tics = 4; Next state = "ETTIN_DEATH1_2"; } State { ID = "ETTIN_DEATH1_2"; Sprite = "ETTN"; Frame = 9; Tics = 4; Next state = "ETTIN_DEATH1_3"; } State { ID = "ETTIN_DEATH1_3"; Sprite = "ETTN"; Frame = 10; Tics = 4; Action = "A_Scream"; Next state = "ETTIN_DEATH1_4"; } State { ID = "ETTIN_DEATH1_4"; Sprite = "ETTN"; Frame = 11; Tics = 4; Action = "A_NoBlocking"; Next state = "ETTIN_DEATH1_5"; } State { ID = "ETTIN_DEATH1_5"; Sprite = "ETTN"; Frame = 12; Tics = 4; Action = "A_QueueCorpse"; Next state = "ETTIN_DEATH1_6"; } State { ID = "ETTIN_DEATH1_6"; Sprite = "ETTN"; Frame = 13; Tics = 4; Next state = "ETTIN_DEATH1_7"; } State { ID = "ETTIN_DEATH1_7"; Sprite = "ETTN"; Frame = 14; Tics = 4; Next state = "ETTIN_DEATH1_8"; } State { ID = "ETTIN_DEATH1_8"; Sprite = "ETTN"; Frame = 15; Tics = 4; Next state = "ETTIN_DEATH1_9"; } State { ID = "ETTIN_DEATH1_9"; Sprite = "ETTN"; Frame = 16; Tics = -1; Next state = "NULL"; } State { ID = "ETTIN_DEATH2_1"; Sprite = "ETTB"; Frame = 0; Tics = 4; Next state = "ETTIN_DEATH2_2"; } State { ID = "ETTIN_DEATH2_2"; Sprite = "ETTB"; Frame = 1; Tics = 4; Action = "A_NoBlocking"; Next state = "ETTIN_DEATH2_3"; } State { ID = "ETTIN_DEATH2_3"; Sprite = "ETTB"; Frame = 2; Tics = 4; Action = "A_DropMace"; Next state = "ETTIN_DEATH2_4"; } State { ID = "ETTIN_DEATH2_4"; Sprite = "ETTB"; Frame = 3; Tics = 4; Action = "A_Scream"; Next state = "ETTIN_DEATH2_5"; } State { ID = "ETTIN_DEATH2_5"; Sprite = "ETTB"; Frame = 4; Tics = 4; Action = "A_QueueCorpse"; Next state = "ETTIN_DEATH2_6"; } State { ID = "ETTIN_DEATH2_6"; Sprite = "ETTB"; Frame = 5; Tics = 4; Next state = "ETTIN_DEATH2_7"; } State { ID = "ETTIN_DEATH2_7"; Sprite = "ETTB"; Frame = 6; Tics = 4; Next state = "ETTIN_DEATH2_8"; } State { ID = "ETTIN_DEATH2_8"; Sprite = "ETTB"; Frame = 7; Tics = 4; Next state = "ETTIN_DEATH2_9"; } State { ID = "ETTIN_DEATH2_9"; Sprite = "ETTB"; Frame = 8; Tics = 4; Next state = "ETTIN_DEATH2_0"; } State { ID = "ETTIN_DEATH2_0"; Sprite = "ETTB"; Frame = 9; Tics = 4; Next state = "ETTIN_DEATH2_A"; } State { ID = "ETTIN_DEATH2_A"; Sprite = "ETTB"; Frame = 10; Tics = 4; Next state = "ETTIN_DEATH2_B"; } State { ID = "ETTIN_DEATH2_B"; Sprite = "ETTB"; Frame = 11; Tics = -1; Next state = "NULL"; } State { ID = "ETTIN_ICE1"; Sprite = "ETTN"; Frame = 17; Tics = 5; Action = "A_FreezeDeath"; Next state = "ETTIN_ICE2"; } State { ID = "ETTIN_ICE2"; Sprite = "ETTN"; Frame = 17; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "ETTIN_ICE2"; } State { ID = "ETTIN_MACE1"; Sprite = "ETTB"; Frame = 12; Tics = 5; Action = "A_CheckFloor"; Next state = "ETTIN_MACE2"; } State { ID = "ETTIN_MACE2"; Sprite = "ETTB"; Frame = 13; Tics = 5; Action = "A_CheckFloor"; Next state = "ETTIN_MACE3"; } State { ID = "ETTIN_MACE3"; Sprite = "ETTB"; Frame = 14; Tics = 5; Action = "A_CheckFloor"; Next state = "ETTIN_MACE4"; } State { ID = "ETTIN_MACE4"; Sprite = "ETTB"; Frame = 15; Tics = 5; Action = "A_CheckFloor"; Next state = "ETTIN_MACE1"; } State { ID = "ETTIN_MACE5"; Sprite = "ETTB"; Frame = 16; Tics = 5; Next state = "ETTIN_MACE6"; } State { ID = "ETTIN_MACE6"; Sprite = "ETTB"; Frame = 17; Tics = 5; Action = "A_QueueCorpse"; Next state = "ETTIN_MACE7"; } State { ID = "ETTIN_MACE7"; Sprite = "ETTB"; Frame = 18; Tics = -1; Next state = "NULL"; } State { ID = "FIRED_SPAWN1"; Sprite = "FDMN"; Frame = 32791; Tics = 5; Next state = "FIRED_LOOK1"; } State { ID = "FIRED_LOOK1"; Sprite = "FDMN"; Frame = 32772; Tics = 10; Action = "A_Look"; Next state = "FIRED_LOOK2"; } State { ID = "FIRED_LOOK2"; Sprite = "FDMN"; Frame = 32773; Tics = 10; Action = "A_Look"; Next state = "FIRED_LOOK3"; } State { ID = "FIRED_LOOK3"; Sprite = "FDMN"; Frame = 32774; Tics = 10; Action = "A_Look"; Next state = "FIRED_LOOK1"; } State { ID = "FIRED_LOOK4"; Sprite = "FDMN"; Frame = 32772; Tics = 8; Next state = "FIRED_LOOK5"; } State { ID = "FIRED_LOOK5"; Sprite = "FDMN"; Frame = 32773; Tics = 6; Next state = "FIRED_LOOK6"; } State { ID = "FIRED_LOOK6"; Sprite = "FDMN"; Frame = 32774; Tics = 5; Next state = "FIRED_LOOK7"; } State { ID = "FIRED_LOOK7"; Sprite = "FDMN"; Frame = 32773; Tics = 8; Next state = "FIRED_LOOK8"; } State { ID = "FIRED_LOOK8"; Sprite = "FDMN"; Frame = 32772; Tics = 6; Next state = "FIRED_LOOK9"; } State { ID = "FIRED_LOOK9"; Sprite = "FDMN"; Frame = 32773; Tics = 7; Action = "A_FiredRocks"; Next state = "FIRED_LOOK0"; } State { ID = "FIRED_LOOK0"; Sprite = "FDMN"; Frame = 32775; Tics = 5; Next state = "FIRED_LOOKA"; } State { ID = "FIRED_LOOKA"; Sprite = "FDMN"; Frame = 32776; Tics = 5; Next state = "FIRED_LOOKB"; } State { ID = "FIRED_LOOKB"; Sprite = "FDMN"; Frame = 32777; Tics = 5; Action = "A_UnSetInvulnerable"; Next state = "FIRED_WALK1"; } State { ID = "FIRED_WALK1"; Sprite = "FDMN"; Frame = 32768; Tics = 5; Action = "A_FiredChase"; Next state = "FIRED_WALK2"; } State { ID = "FIRED_WALK2"; Sprite = "FDMN"; Frame = 32769; Tics = 5; Action = "A_FiredChase"; Next state = "FIRED_WALK3"; } State { ID = "FIRED_WALK3"; Sprite = "FDMN"; Frame = 32770; Tics = 5; Action = "A_FiredChase"; Next state = "FIRED_WALK1"; } State { ID = "FIRED_PAIN1"; Sprite = "FDMN"; Frame = 32771; Tics = 6; Action = "A_Pain"; Next state = "FIRED_WALK1"; } State { ID = "FIRED_ATTACK1"; Sprite = "FDMN"; Frame = 32778; Tics = 3; Action = "A_FaceTarget"; Next state = "FIRED_ATTACK2"; } State { ID = "FIRED_ATTACK2"; Sprite = "FDMN"; Frame = 32778; Tics = 5; Action = "A_FiredAttack"; Next state = "FIRED_ATTACK3"; } State { ID = "FIRED_ATTACK3"; Sprite = "FDMN"; Frame = 32778; Tics = 5; Action = "A_FiredAttack"; Next state = "FIRED_ATTACK4"; } State { ID = "FIRED_ATTACK4"; Sprite = "FDMN"; Frame = 32778; Tics = 5; Action = "A_FiredAttack"; Next state = "FIRED_WALK1"; } State { ID = "FIRED_DEATH1"; Sprite = "FDMN"; Frame = 32771; Tics = 4; Action = "A_FaceTarget"; Next state = "FIRED_DEATH2"; } State { ID = "FIRED_DEATH2"; Sprite = "FDMN"; Frame = 32779; Tics = 4; Action = "A_Scream"; Next state = "FIRED_DEATH3"; } State { ID = "FIRED_DEATH3"; Sprite = "FDMN"; Frame = 32779; Tics = 4; Action = "A_NoBlocking"; Next state = "FIRED_DEATH4"; } State { ID = "FIRED_DEATH4"; Sprite = "FDMN"; Frame = 32779; Tics = 200; Next state = "NULL"; } State { ID = "FIRED_XDEATH1"; Sprite = "FDMN"; Frame = 12; Tics = 5; Action = "A_FaceTarget"; Next state = "FIRED_XDEATH2"; } State { ID = "FIRED_XDEATH2"; Sprite = "FDMN"; Frame = 13; Tics = 5; Action = "A_NoBlocking"; Next state = "FIRED_XDEATH3"; } State { ID = "FIRED_XDEATH3"; Sprite = "FDMN"; Frame = 14; Tics = 5; Action = "A_FiredSplotch"; Next state = "NULL"; } State { ID = "FIRED_ICE1"; Sprite = "FDMN"; Frame = 17; Tics = 5; Action = "A_FreezeDeath"; Next state = "FIRED_ICE2"; } State { ID = "FIRED_ICE2"; Sprite = "FDMN"; Frame = 17; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "FIRED_ICE2"; } State { ID = "FIRED_CORPSE1"; Sprite = "FDMN"; Frame = 15; Tics = 3; Next state = "FIRED_CORPSE2"; } State { ID = "FIRED_CORPSE2"; Sprite = "FDMN"; Frame = 15; Tics = 6; Action = "A_QueueCorpse"; Next state = "FIRED_CORPSE3"; } State { ID = "FIRED_CORPSE3"; Sprite = "FDMN"; Frame = 24; Tics = -1; Next state = "NULL"; } State { ID = "FIRED_CORPSE4"; Sprite = "FDMN"; Frame = 16; Tics = 3; Next state = "FIRED_CORPSE5"; } State { ID = "FIRED_CORPSE5"; Sprite = "FDMN"; Frame = 16; Tics = 6; Action = "A_QueueCorpse"; Next state = "FIRED_CORPSE6"; } State { ID = "FIRED_CORPSE6"; Sprite = "FDMN"; Frame = 25; Tics = -1; Next state = "NULL"; } State { ID = "FIRED_RDROP1"; Sprite = "FDMN"; Frame = 18; Tics = 4; Next state = "FIRED_RDROP1"; } State { ID = "FIRED_RDEAD1_1"; Sprite = "FDMN"; Frame = 18; Tics = 5; Action = "A_SmBounce"; Next state = "FIRED_RDEAD1_2"; } State { ID = "FIRED_RDEAD1_2"; Sprite = "FDMN"; Frame = 18; Tics = 200; Next state = "NULL"; } State { ID = "FIRED_RDROP2"; Sprite = "FDMN"; Frame = 19; Tics = 4; Next state = "FIRED_RDROP2"; } State { ID = "FIRED_RDEAD2_1"; Sprite = "FDMN"; Frame = 19; Tics = 5; Action = "A_SmBounce"; Next state = "FIRED_RDEAD2_2"; } State { ID = "FIRED_RDEAD2_2"; Sprite = "FDMN"; Frame = 19; Tics = 200; Next state = "NULL"; } State { ID = "FIRED_RDROP3"; Sprite = "FDMN"; Frame = 20; Tics = 4; Next state = "FIRED_RDROP3"; } State { ID = "FIRED_RDEAD3_1"; Sprite = "FDMN"; Frame = 20; Tics = 5; Action = "A_SmBounce"; Next state = "FIRED_RDEAD3_2"; } State { ID = "FIRED_RDEAD3_2"; Sprite = "FDMN"; Frame = 20; Tics = 200; Next state = "NULL"; } State { ID = "FIRED_RDROP4"; Sprite = "FDMN"; Frame = 21; Tics = 4; Next state = "FIRED_RDROP4"; } State { ID = "FIRED_RDEAD4_1"; Sprite = "FDMN"; Frame = 21; Tics = 5; Action = "A_SmBounce"; Next state = "FIRED_RDEAD4_2"; } State { ID = "FIRED_RDEAD4_2"; Sprite = "FDMN"; Frame = 21; Tics = 200; Next state = "NULL"; } State { ID = "FIRED_RDROP5"; Sprite = "FDMN"; Frame = 22; Tics = 4; Next state = "FIRED_RDROP5"; } State { ID = "FIRED_RDEAD5_1"; Sprite = "FDMN"; Frame = 22; Tics = 5; Action = "A_SmBounce"; Next state = "FIRED_RDEAD5_2"; } State { ID = "FIRED_RDEAD5_2"; Sprite = "FDMN"; Frame = 22; Tics = 200; Next state = "NULL"; } State { ID = "FIRED_FX6_1"; Sprite = "FDMB"; Frame = 32768; Tics = 5; Next state = "FIRED_FX6_1"; } State { ID = "FIRED_FX6_2"; Sprite = "FDMB"; Frame = 32769; Tics = 5; Next state = "FIRED_FX6_3"; } State { ID = "FIRED_FX6_3"; Sprite = "FDMB"; Frame = 32770; Tics = 5; Next state = "FIRED_FX6_4"; } State { ID = "FIRED_FX6_4"; Sprite = "FDMB"; Frame = 32771; Tics = 5; Next state = "FIRED_FX6_5"; } State { ID = "FIRED_FX6_5"; Sprite = "FDMB"; Frame = 32772; Tics = 5; Next state = "NULL"; } State { ID = "ICEGUY_LOOK"; Sprite = "ICEY"; Frame = 0; Tics = 10; Action = "A_IceGuyLook"; Next state = "ICEGUY_LOOK"; } State { ID = "ICEGUY_DORMANT"; Sprite = "ICEY"; Frame = 0; Tics = -1; Next state = "ICEGUY_LOOK"; } State { ID = "ICEGUY_WALK1"; Sprite = "ICEY"; Frame = 0; Tics = 4; Action = "A_Chase"; Next state = "ICEGUY_WALK2"; } State { ID = "ICEGUY_WALK2"; Sprite = "ICEY"; Frame = 1; Tics = 4; Action = "A_IceGuyChase"; Next state = "ICEGUY_WALK3"; } State { ID = "ICEGUY_WALK3"; Sprite = "ICEY"; Frame = 2; Tics = 4; Action = "A_Chase"; Next state = "ICEGUY_WALK4"; } State { ID = "ICEGUY_WALK4"; Sprite = "ICEY"; Frame = 3; Tics = 4; Action = "A_Chase"; Next state = "ICEGUY_WALK1"; } State { ID = "ICEGUY_ATK1"; Sprite = "ICEY"; Frame = 4; Tics = 3; Action = "A_FaceTarget"; Next state = "ICEGUY_ATK2"; } State { ID = "ICEGUY_ATK2"; Sprite = "ICEY"; Frame = 5; Tics = 3; Action = "A_FaceTarget"; Next state = "ICEGUY_ATK3"; } State { ID = "ICEGUY_ATK3"; Sprite = "ICEY"; Frame = 32774; Tics = 8; Action = "A_IceGuyAttack"; Next state = "ICEGUY_ATK4"; } State { ID = "ICEGUY_ATK4"; Sprite = "ICEY"; Frame = 5; Tics = 4; Action = "A_FaceTarget"; Next state = "ICEGUY_WALK1"; } State { ID = "ICEGUY_PAIN1"; Sprite = "ICEY"; Frame = 0; Tics = 1; Action = "A_Pain"; Next state = "ICEGUY_WALK1"; } State { ID = "ICEGUY_DEATH"; Sprite = "ICEY"; Frame = 0; Tics = 1; Action = "A_IceGuyDie"; Next state = "NULL"; } State { ID = "ICEGUY_FX1"; Sprite = "ICPR"; Frame = 32768; Tics = 3; Action = "A_IceGuyMissilePuff"; Next state = "ICEGUY_FX2"; } State { ID = "ICEGUY_FX2"; Sprite = "ICPR"; Frame = 32769; Tics = 3; Action = "A_IceGuyMissilePuff"; Next state = "ICEGUY_FX3"; } State { ID = "ICEGUY_FX3"; Sprite = "ICPR"; Frame = 32770; Tics = 3; Action = "A_IceGuyMissilePuff"; Next state = "ICEGUY_FX1"; } State { ID = "ICEGUY_FX_X1"; Sprite = "ICPR"; Frame = 32771; Tics = 4; Next state = "ICEGUY_FX_X2"; } State { ID = "ICEGUY_FX_X2"; Sprite = "ICPR"; Frame = 32772; Tics = 4; Action = "A_IceGuyMissileExplode"; Next state = "ICEGUY_FX_X3"; } State { ID = "ICEGUY_FX_X3"; Sprite = "ICPR"; Frame = 32773; Tics = 4; Next state = "ICEGUY_FX_X4"; } State { ID = "ICEGUY_FX_X4"; Sprite = "ICPR"; Frame = 32774; Tics = 4; Next state = "ICEGUY_FX_X5"; } State { ID = "ICEGUY_FX_X5"; Sprite = "ICPR"; Frame = 32775; Tics = 3; Next state = "NULL"; } State { ID = "ICEFX_PUFF1"; Sprite = "ICPR"; Frame = 8; Tics = 3; Next state = "ICEFX_PUFF2"; } State { ID = "ICEFX_PUFF2"; Sprite = "ICPR"; Frame = 9; Tics = 3; Next state = "ICEFX_PUFF3"; } State { ID = "ICEFX_PUFF3"; Sprite = "ICPR"; Frame = 10; Tics = 3; Next state = "ICEFX_PUFF4"; } State { ID = "ICEFX_PUFF4"; Sprite = "ICPR"; Frame = 11; Tics = 2; Next state = "ICEFX_PUFF5"; } State { ID = "ICEFX_PUFF5"; Sprite = "ICPR"; Frame = 12; Tics = 2; Next state = "NULL"; } State { ID = "ICEGUY_FX2_1"; Sprite = "ICPR"; Frame = 32781; Tics = 3; Next state = "ICEGUY_FX2_2"; } State { ID = "ICEGUY_FX2_2"; Sprite = "ICPR"; Frame = 32782; Tics = 3; Next state = "ICEGUY_FX2_3"; } State { ID = "ICEGUY_FX2_3"; Sprite = "ICPR"; Frame = 32783; Tics = 3; Next state = "ICEGUY_FX2_1"; } State { ID = "ICEGUY_BIT1"; Sprite = "ICPR"; Frame = 32784; Tics = 50; Next state = "NULL"; } State { ID = "ICEGUY_BIT2"; Sprite = "ICPR"; Frame = 32785; Tics = 50; Next state = "NULL"; } State { ID = "ICEGUY_WISP1_1"; Sprite = "ICWS"; Frame = 0; Tics = 2; Next state = "ICEGUY_WISP1_2"; } State { ID = "ICEGUY_WISP1_2"; Sprite = "ICWS"; Frame = 1; Tics = 2; Next state = "ICEGUY_WISP1_3"; } State { ID = "ICEGUY_WISP1_3"; Sprite = "ICWS"; Frame = 2; Tics = 2; Next state = "ICEGUY_WISP1_4"; } State { ID = "ICEGUY_WISP1_4"; Sprite = "ICWS"; Frame = 3; Tics = 2; Next state = "ICEGUY_WISP1_5"; } State { ID = "ICEGUY_WISP1_5"; Sprite = "ICWS"; Frame = 4; Tics = 2; Next state = "ICEGUY_WISP1_6"; } State { ID = "ICEGUY_WISP1_6"; Sprite = "ICWS"; Frame = 5; Tics = 2; Next state = "ICEGUY_WISP1_7"; } State { ID = "ICEGUY_WISP1_7"; Sprite = "ICWS"; Frame = 6; Tics = 2; Next state = "ICEGUY_WISP1_8"; } State { ID = "ICEGUY_WISP1_8"; Sprite = "ICWS"; Frame = 7; Tics = 2; Next state = "ICEGUY_WISP1_9"; } State { ID = "ICEGUY_WISP1_9"; Sprite = "ICWS"; Frame = 8; Tics = 2; Next state = "NULL"; } State { ID = "ICEGUY_WISP2_1"; Sprite = "ICWS"; Frame = 9; Tics = 2; Next state = "ICEGUY_WISP2_2"; } State { ID = "ICEGUY_WISP2_2"; Sprite = "ICWS"; Frame = 10; Tics = 2; Next state = "ICEGUY_WISP2_3"; } State { ID = "ICEGUY_WISP2_3"; Sprite = "ICWS"; Frame = 11; Tics = 2; Next state = "ICEGUY_WISP2_4"; } State { ID = "ICEGUY_WISP2_4"; Sprite = "ICWS"; Frame = 12; Tics = 2; Next state = "ICEGUY_WISP2_5"; } State { ID = "ICEGUY_WISP2_5"; Sprite = "ICWS"; Frame = 13; Tics = 2; Next state = "ICEGUY_WISP2_6"; } State { ID = "ICEGUY_WISP2_6"; Sprite = "ICWS"; Frame = 14; Tics = 2; Next state = "ICEGUY_WISP2_7"; } State { ID = "ICEGUY_WISP2_7"; Sprite = "ICWS"; Frame = 15; Tics = 2; Next state = "ICEGUY_WISP2_8"; } State { ID = "ICEGUY_WISP2_8"; Sprite = "ICWS"; Frame = 16; Tics = 2; Next state = "ICEGUY_WISP2_9"; } State { ID = "ICEGUY_WISP2_9"; Sprite = "ICWS"; Frame = 17; Tics = 2; Next state = "NULL"; } State { ID = "FIGHTER"; Sprite = "PLAY"; Frame = 0; Tics = 2; Next state = "FIGHTER2"; } State { ID = "FIGHTER2"; Sprite = "PLAY"; Frame = 0; Tics = 3; Action = "A_ClassBossHealth"; Next state = "FIGHTERLOOK"; } State { ID = "FIGHTERLOOK"; Sprite = "PLAY"; Frame = 0; Tics = 5; Action = "A_Look"; Next state = "FIGHTERLOOK"; } State { ID = "FIGHTER_RUN1"; Sprite = "PLAY"; Frame = 0; Tics = 4; Action = "A_FastChase"; Next state = "FIGHTER_RUN2"; } State { ID = "FIGHTER_RUN2"; Sprite = "PLAY"; Frame = 1; Tics = 4; Action = "A_FastChase"; Next state = "FIGHTER_RUN3"; } State { ID = "FIGHTER_RUN3"; Sprite = "PLAY"; Frame = 2; Tics = 4; Action = "A_FastChase"; Next state = "FIGHTER_RUN4"; } State { ID = "FIGHTER_RUN4"; Sprite = "PLAY"; Frame = 3; Tics = 4; Action = "A_FastChase"; Next state = "FIGHTER_RUN1"; } State { ID = "FIGHTER_ATK1"; Sprite = "PLAY"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "FIGHTER_ATK2"; } State { ID = "FIGHTER_ATK2"; Sprite = "PLAY"; Frame = 5; Tics = 8; Action = "A_FighterAttack"; Next state = "FIGHTER_RUN1"; } State { ID = "FIGHTER_PAIN"; Sprite = "PLAY"; Frame = 6; Tics = 4; Next state = "FIGHTER_PAIN2"; } State { ID = "FIGHTER_PAIN2"; Sprite = "PLAY"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "FIGHTER_RUN1"; } State { ID = "FIGHTER_DIE1"; Sprite = "PLAY"; Frame = 7; Tics = 6; Next state = "FIGHTER_DIE2"; } State { ID = "FIGHTER_DIE2"; Sprite = "PLAY"; Frame = 8; Tics = 6; Action = "A_Scream"; Next state = "FIGHTER_DIE3"; } State { ID = "FIGHTER_DIE3"; Sprite = "PLAY"; Frame = 9; Tics = 6; Next state = "FIGHTER_DIE4"; } State { ID = "FIGHTER_DIE4"; Sprite = "PLAY"; Frame = 10; Tics = 6; Next state = "FIGHTER_DIE5"; } State { ID = "FIGHTER_DIE5"; Sprite = "PLAY"; Frame = 11; Tics = 6; Action = "A_NoBlocking"; Next state = "FIGHTER_DIE6"; } State { ID = "FIGHTER_DIE6"; Sprite = "PLAY"; Frame = 12; Tics = 6; Next state = "FIGHTER_DIE7"; } State { ID = "FIGHTER_DIE7"; Sprite = "PLAY"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "FIGHTER_XDIE1"; Sprite = "PLAY"; Frame = 14; Tics = 5; Action = "A_Scream"; Next state = "FIGHTER_XDIE2"; } State { ID = "FIGHTER_XDIE2"; Sprite = "PLAY"; Frame = 15; Tics = 5; Action = "A_SkullPop"; Next state = "FIGHTER_XDIE3"; } State { ID = "FIGHTER_XDIE3"; Sprite = "PLAY"; Frame = 17; Tics = 5; Action = "A_NoBlocking"; Next state = "FIGHTER_XDIE4"; } State { ID = "FIGHTER_XDIE4"; Sprite = "PLAY"; Frame = 18; Tics = 5; Next state = "FIGHTER_XDIE5"; } State { ID = "FIGHTER_XDIE5"; Sprite = "PLAY"; Frame = 19; Tics = 5; Next state = "FIGHTER_XDIE6"; } State { ID = "FIGHTER_XDIE6"; Sprite = "PLAY"; Frame = 20; Tics = 5; Next state = "FIGHTER_XDIE7"; } State { ID = "FIGHTER_XDIE7"; Sprite = "PLAY"; Frame = 21; Tics = 5; Next state = "FIGHTER_XDIE8"; } State { ID = "FIGHTER_XDIE8"; Sprite = "PLAY"; Frame = 22; Tics = -1; Next state = "NULL"; } State { ID = "FIGHTER_ICE"; Sprite = "PLAY"; Frame = 23; Tics = 5; Action = "A_FreezeDeath"; Next state = "FIGHTER_ICE2"; } State { ID = "FIGHTER_ICE2"; Sprite = "PLAY"; Frame = 23; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "FIGHTER_ICE2"; } State { ID = "CLERIC"; Sprite = "CLER"; Frame = 0; Tics = 2; Next state = "CLERIC2"; } State { ID = "CLERIC2"; Sprite = "CLER"; Frame = 0; Tics = 3; Action = "A_ClassBossHealth"; Next state = "CLERICLOOK"; } State { ID = "CLERICLOOK"; Sprite = "CLER"; Frame = 0; Tics = 5; Action = "A_Look"; Next state = "CLERICLOOK"; } State { ID = "CLERIC_RUN1"; Sprite = "CLER"; Frame = 0; Tics = 4; Action = "A_FastChase"; Next state = "CLERIC_RUN2"; } State { ID = "CLERIC_RUN2"; Sprite = "CLER"; Frame = 1; Tics = 4; Action = "A_FastChase"; Next state = "CLERIC_RUN3"; } State { ID = "CLERIC_RUN3"; Sprite = "CLER"; Frame = 2; Tics = 4; Action = "A_FastChase"; Next state = "CLERIC_RUN4"; } State { ID = "CLERIC_RUN4"; Sprite = "CLER"; Frame = 3; Tics = 4; Action = "A_FastChase"; Next state = "CLERIC_RUN1"; } State { ID = "CLERIC_ATK1"; Sprite = "CLER"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "CLERIC_ATK2"; } State { ID = "CLERIC_ATK2"; Sprite = "CLER"; Frame = 5; Tics = 8; Action = "A_FaceTarget"; Next state = "CLERIC_ATK3"; } State { ID = "CLERIC_ATK3"; Sprite = "CLER"; Frame = 6; Tics = 10; Action = "A_ClericAttack"; Next state = "CLERIC_RUN1"; } State { ID = "CLERIC_PAIN"; Sprite = "CLER"; Frame = 7; Tics = 4; Next state = "CLERIC_PAIN2"; } State { ID = "CLERIC_PAIN2"; Sprite = "CLER"; Frame = 7; Tics = 4; Action = "A_Pain"; Next state = "CLERIC_RUN1"; } State { ID = "CLERIC_DIE1"; Sprite = "CLER"; Frame = 8; Tics = 6; Next state = "CLERIC_DIE2"; } State { ID = "CLERIC_DIE2"; Sprite = "CLER"; Frame = 10; Tics = 6; Action = "A_Scream"; Next state = "CLERIC_DIE3"; } State { ID = "CLERIC_DIE3"; Sprite = "CLER"; Frame = 11; Tics = 6; Next state = "CLERIC_DIE4"; } State { ID = "CLERIC_DIE4"; Sprite = "CLER"; Frame = 11; Tics = 6; Next state = "CLERIC_DIE5"; } State { ID = "CLERIC_DIE5"; Sprite = "CLER"; Frame = 12; Tics = 6; Action = "A_NoBlocking"; Next state = "CLERIC_DIE6"; } State { ID = "CLERIC_DIE6"; Sprite = "CLER"; Frame = 13; Tics = 6; Next state = "CLERIC_DIE7"; } State { ID = "CLERIC_DIE7"; Sprite = "CLER"; Frame = 14; Tics = 6; Next state = "CLERIC_DIE8"; } State { ID = "CLERIC_DIE8"; Sprite = "CLER"; Frame = 15; Tics = 6; Next state = "CLERIC_DIE9"; } State { ID = "CLERIC_DIE9"; Sprite = "CLER"; Frame = 16; Tics = -1; Next state = "NULL"; } State { ID = "CLERIC_XDIE1"; Sprite = "CLER"; Frame = 17; Tics = 5; Action = "A_Scream"; Next state = "CLERIC_XDIE2"; } State { ID = "CLERIC_XDIE2"; Sprite = "CLER"; Frame = 18; Tics = 5; Next state = "CLERIC_XDIE3"; } State { ID = "CLERIC_XDIE3"; Sprite = "CLER"; Frame = 19; Tics = 5; Action = "A_NoBlocking"; Next state = "CLERIC_XDIE4"; } State { ID = "CLERIC_XDIE4"; Sprite = "CLER"; Frame = 20; Tics = 5; Next state = "CLERIC_XDIE5"; } State { ID = "CLERIC_XDIE5"; Sprite = "CLER"; Frame = 21; Tics = 5; Next state = "CLERIC_XDIE6"; } State { ID = "CLERIC_XDIE6"; Sprite = "CLER"; Frame = 22; Tics = 5; Next state = "CLERIC_XDIE7"; } State { ID = "CLERIC_XDIE7"; Sprite = "CLER"; Frame = 23; Tics = 5; Next state = "CLERIC_XDIE8"; } State { ID = "CLERIC_XDIE8"; Sprite = "CLER"; Frame = 24; Tics = 5; Next state = "CLERIC_XDIE9"; } State { ID = "CLERIC_XDIE9"; Sprite = "CLER"; Frame = 25; Tics = 5; Next state = "CLERIC_XDIE10"; } State { ID = "CLERIC_XDIE10"; Sprite = "CLER"; Frame = 26; Tics = -1; Next state = "NULL"; } State { ID = "CLERIC_ICE"; Sprite = "CLER"; Frame = 27; Tics = 5; Action = "A_FreezeDeath"; Next state = "CLERIC_ICE2"; } State { ID = "CLERIC_ICE2"; Sprite = "CLER"; Frame = 27; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "CLERIC_ICE2"; } State { ID = "MAGE"; Sprite = "MAGE"; Frame = 0; Tics = 2; Next state = "MAGE2"; } State { ID = "MAGE2"; Sprite = "MAGE"; Frame = 0; Tics = 3; Action = "A_ClassBossHealth"; Next state = "MAGELOOK"; } State { ID = "MAGELOOK"; Sprite = "MAGE"; Frame = 0; Tics = 5; Action = "A_Look"; Next state = "MAGELOOK"; } State { ID = "MAGE_RUN1"; Sprite = "MAGE"; Frame = 0; Tics = 4; Action = "A_FastChase"; Next state = "MAGE_RUN2"; } State { ID = "MAGE_RUN2"; Sprite = "MAGE"; Frame = 1; Tics = 4; Action = "A_FastChase"; Next state = "MAGE_RUN3"; } State { ID = "MAGE_RUN3"; Sprite = "MAGE"; Frame = 2; Tics = 4; Action = "A_FastChase"; Next state = "MAGE_RUN4"; } State { ID = "MAGE_RUN4"; Sprite = "MAGE"; Frame = 3; Tics = 4; Action = "A_FastChase"; Next state = "MAGE_RUN1"; } State { ID = "MAGE_ATK1"; Sprite = "MAGE"; Frame = 4; Tics = 8; Action = "A_FaceTarget"; Next state = "MAGE_ATK2"; } State { ID = "MAGE_ATK2"; Sprite = "MAGE"; Frame = 32773; Tics = 8; Action = "A_MageAttack"; Next state = "MAGE_RUN1"; } State { ID = "MAGE_PAIN"; Sprite = "MAGE"; Frame = 6; Tics = 4; Next state = "MAGE_PAIN2"; } State { ID = "MAGE_PAIN2"; Sprite = "MAGE"; Frame = 6; Tics = 4; Action = "A_Pain"; Next state = "MAGE_RUN1"; } State { ID = "MAGE_DIE1"; Sprite = "MAGE"; Frame = 7; Tics = 6; Next state = "MAGE_DIE2"; } State { ID = "MAGE_DIE2"; Sprite = "MAGE"; Frame = 8; Tics = 6; Action = "A_Scream"; Next state = "MAGE_DIE3"; } State { ID = "MAGE_DIE3"; Sprite = "MAGE"; Frame = 9; Tics = 6; Next state = "MAGE_DIE4"; } State { ID = "MAGE_DIE4"; Sprite = "MAGE"; Frame = 10; Tics = 6; Next state = "MAGE_DIE5"; } State { ID = "MAGE_DIE5"; Sprite = "MAGE"; Frame = 11; Tics = 6; Action = "A_NoBlocking"; Next state = "MAGE_DIE6"; } State { ID = "MAGE_DIE6"; Sprite = "MAGE"; Frame = 12; Tics = 6; Next state = "MAGE_DIE7"; } State { ID = "MAGE_DIE7"; Sprite = "MAGE"; Frame = 13; Tics = -1; Next state = "NULL"; } State { ID = "MAGE_XDIE1"; Sprite = "MAGE"; Frame = 14; Tics = 5; Action = "A_Scream"; Next state = "MAGE_XDIE2"; } State { ID = "MAGE_XDIE2"; Sprite = "MAGE"; Frame = 15; Tics = 5; Next state = "MAGE_XDIE3"; } State { ID = "MAGE_XDIE3"; Sprite = "MAGE"; Frame = 17; Tics = 5; Action = "A_NoBlocking"; Next state = "MAGE_XDIE4"; } State { ID = "MAGE_XDIE4"; Sprite = "MAGE"; Frame = 18; Tics = 5; Next state = "MAGE_XDIE5"; } State { ID = "MAGE_XDIE5"; Sprite = "MAGE"; Frame = 19; Tics = 5; Next state = "MAGE_XDIE6"; } State { ID = "MAGE_XDIE6"; Sprite = "MAGE"; Frame = 20; Tics = 5; Next state = "MAGE_XDIE7"; } State { ID = "MAGE_XDIE7"; Sprite = "MAGE"; Frame = 21; Tics = 5; Next state = "MAGE_XDIE8"; } State { ID = "MAGE_XDIE8"; Sprite = "MAGE"; Frame = 22; Tics = 5; Next state = "MAGE_XDIE9"; } State { ID = "MAGE_XDIE9"; Sprite = "MAGE"; Frame = 23; Tics = -1; Next state = "NULL"; } State { ID = "MAGE_ICE"; Sprite = "MAGE"; Frame = 24; Tics = 5; Action = "A_FreezeDeath"; Next state = "MAGE_ICE2"; } State { ID = "MAGE_ICE2"; Sprite = "MAGE"; Frame = 24; Tics = 1; Action = "A_FreezeDeathChunks"; Next state = "MAGE_ICE2"; } State { ID = "SORC_SPAWN1"; Sprite = "SORC"; Frame = 0; Tics = 3; Next state = "SORC_SPAWN2"; } State { ID = "SORC_SPAWN2"; Sprite = "SORC"; Frame = 0; Tics = 2; Action = "A_SorcSpinBalls"; Next state = "SORC_LOOK1"; } State { ID = "SORC_LOOK1"; Sprite = "SORC"; Frame = 0; Tics = 10; Action = "A_Look"; Next state = "SORC_LOOK1"; } State { ID = "SORC_WALK1"; Sprite = "SORC"; Frame = 0; Tics = 5; Action = "A_Chase"; Next state = "SORC_WALK2"; } State { ID = "SORC_WALK2"; Sprite = "SORC"; Frame = 1; Tics = 5; Action = "A_Chase"; Next state = "SORC_WALK3"; } State { ID = "SORC_WALK3"; Sprite = "SORC"; Frame = 2; Tics = 5; Action = "A_Chase"; Next state = "SORC_WALK4"; } State { ID = "SORC_WALK4"; Sprite = "SORC"; Frame = 3; Tics = 5; Action = "A_Chase"; Next state = "SORC_WALK1"; } State { ID = "SORC_PAIN1"; Sprite = "SORC"; Frame = 6; Tics = 8; Next state = "SORC_PAIN2"; } State { ID = "SORC_PAIN2"; Sprite = "SORC"; Frame = 6; Tics = 8; Action = "A_Pain"; Next state = "SORC_WALK1"; } State { ID = "SORC_ATK2_1"; Sprite = "SORC"; Frame = 32773; Tics = 6; Action = "A_FaceTarget"; Next state = "SORC_ATK2_2"; } State { ID = "SORC_ATK2_2"; Sprite = "SORC"; Frame = 32773; Tics = 6; Action = "A_SpeedBalls"; Next state = "SORC_ATK2_3"; } State { ID = "SORC_ATK2_3"; Sprite = "SORC"; Frame = 32773; Tics = 6; Action = "A_FaceTarget"; Next state = "SORC_ATK2_3"; } State { ID = "SORC_ATTACK1"; Sprite = "SORC"; Frame = 32772; Tics = 6; Next state = "SORC_ATTACK2"; } State { ID = "SORC_ATTACK2"; Sprite = "SORC"; Frame = 32772; Tics = 6; Action = "A_SpawnFizzle"; Next state = "SORC_ATTACK3"; } State { ID = "SORC_ATTACK3"; Sprite = "SORC"; Frame = 32772; Tics = 5; Action = "A_FaceTarget"; Next state = "SORC_ATTACK2"; } State { ID = "SORC_ATTACK4"; Sprite = "SORC"; Frame = 32772; Tics = 2; Next state = "SORC_ATTACK5"; } State { ID = "SORC_ATTACK5"; Sprite = "SORC"; Frame = 32772; Tics = 2; Action = "A_SorcBossAttack"; Next state = "SORC_WALK1"; } State { ID = "SORC_DIE1"; Sprite = "SORC"; Frame = 32775; Tics = 5; Next state = "SORC_DIE2"; } State { ID = "SORC_DIE2"; Sprite = "SORC"; Frame = 32776; Tics = 5; Action = "A_FaceTarget"; Next state = "SORC_DIE3"; } State { ID = "SORC_DIE3"; Sprite = "SORC"; Frame = 32777; Tics = 5; Action = "A_Scream"; Next state = "SORC_DIE4"; } State { ID = "SORC_DIE4"; Sprite = "SORC"; Frame = 32778; Tics = 5; Next state = "SORC_DIE5"; } State { ID = "SORC_DIE5"; Sprite = "SORC"; Frame = 32779; Tics = 5; Next state = "SORC_DIE6"; } State { ID = "SORC_DIE6"; Sprite = "SORC"; Frame = 32780; Tics = 5; Next state = "SORC_DIE7"; } State { ID = "SORC_DIE7"; Sprite = "SORC"; Frame = 32781; Tics = 5; Next state = "SORC_DIE8"; } State { ID = "SORC_DIE8"; Sprite = "SORC"; Frame = 32782; Tics = 5; Next state = "SORC_DIE9"; } State { ID = "SORC_DIE9"; Sprite = "SORC"; Frame = 32783; Tics = 5; Next state = "SORC_DIE0"; } State { ID = "SORC_DIE0"; Sprite = "SORC"; Frame = 32784; Tics = 5; Next state = "SORC_DIEA"; } State { ID = "SORC_DIEA"; Sprite = "SORC"; Frame = 32785; Tics = 5; Next state = "SORC_DIEB"; } State { ID = "SORC_DIEB"; Sprite = "SORC"; Frame = 32786; Tics = 5; Next state = "SORC_DIEC"; } State { ID = "SORC_DIEC"; Sprite = "SORC"; Frame = 32787; Tics = 5; Next state = "SORC_DIED"; } State { ID = "SORC_DIED"; Sprite = "SORC"; Frame = 32788; Tics = 5; Action = "A_NoBlocking"; Next state = "SORC_DIEE"; } State { ID = "SORC_DIEE"; Sprite = "SORC"; Frame = 32789; Tics = 5; Next state = "SORC_DIEF"; } State { ID = "SORC_DIEF"; Sprite = "SORC"; Frame = 32790; Tics = 5; Next state = "SORC_DIEG"; } State { ID = "SORC_DIEG"; Sprite = "SORC"; Frame = 32791; Tics = 5; Next state = "SORC_DIEH"; } State { ID = "SORC_DIEH"; Sprite = "SORC"; Frame = 32792; Tics = 5; Next state = "SORC_DIEI"; } State { ID = "SORC_DIEI"; Sprite = "SORC"; Frame = 32793; Tics = -1; Next state = "NULL"; } State { ID = "SORCBALL1_1"; Sprite = "SBMP"; Frame = 0; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_2"; } State { ID = "SORCBALL1_2"; Sprite = "SBMP"; Frame = 1; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_3"; } State { ID = "SORCBALL1_3"; Sprite = "SBMP"; Frame = 2; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_4"; } State { ID = "SORCBALL1_4"; Sprite = "SBMP"; Frame = 3; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_5"; } State { ID = "SORCBALL1_5"; Sprite = "SBMP"; Frame = 4; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_6"; } State { ID = "SORCBALL1_6"; Sprite = "SBMP"; Frame = 5; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_7"; } State { ID = "SORCBALL1_7"; Sprite = "SBMP"; Frame = 6; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_8"; } State { ID = "SORCBALL1_8"; Sprite = "SBMP"; Frame = 7; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_9"; } State { ID = "SORCBALL1_9"; Sprite = "SBMP"; Frame = 8; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_0"; } State { ID = "SORCBALL1_0"; Sprite = "SBMP"; Frame = 9; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_A"; } State { ID = "SORCBALL1_A"; Sprite = "SBMP"; Frame = 10; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_B"; } State { ID = "SORCBALL1_B"; Sprite = "SBMP"; Frame = 11; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_C"; } State { ID = "SORCBALL1_C"; Sprite = "SBMP"; Frame = 12; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_D"; } State { ID = "SORCBALL1_D"; Sprite = "SBMP"; Frame = 13; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_E"; } State { ID = "SORCBALL1_E"; Sprite = "SBMP"; Frame = 14; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_F"; } State { ID = "SORCBALL1_F"; Sprite = "SBMP"; Frame = 15; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL1_1"; } State { ID = "SORCBALL1_D1"; Sprite = "SBMP"; Frame = 0; Tics = 5; Action = "A_SorcBallPop"; Next state = "SORCBALL1_D2"; } State { ID = "SORCBALL1_D2"; Sprite = "SBMP"; Frame = 1; Tics = 2; Action = "A_BounceCheck"; Next state = "SORCBALL1_D2"; } State { ID = "SORCBALL1_D5"; Sprite = "SBS4"; Frame = 3; Tics = 5; Action = "A_Explode"; Next state = "SORCBALL1_D6"; } State { ID = "SORCBALL1_D6"; Sprite = "SBS4"; Frame = 4; Tics = 5; Next state = "SORCBALL1_D7"; } State { ID = "SORCBALL1_D7"; Sprite = "SBS4"; Frame = 5; Tics = 6; Next state = "SORCBALL1_D8"; } State { ID = "SORCBALL1_D8"; Sprite = "SBS4"; Frame = 6; Tics = 6; Next state = "SORCBALL1_D9"; } State { ID = "SORCBALL1_D9"; Sprite = "SBS4"; Frame = 7; Tics = 6; Next state = "NULL"; } State { ID = "SORCBALL2_1"; Sprite = "SBMB"; Frame = 0; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_2"; } State { ID = "SORCBALL2_2"; Sprite = "SBMB"; Frame = 1; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_3"; } State { ID = "SORCBALL2_3"; Sprite = "SBMB"; Frame = 2; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_4"; } State { ID = "SORCBALL2_4"; Sprite = "SBMB"; Frame = 3; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_5"; } State { ID = "SORCBALL2_5"; Sprite = "SBMB"; Frame = 4; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_6"; } State { ID = "SORCBALL2_6"; Sprite = "SBMB"; Frame = 5; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_7"; } State { ID = "SORCBALL2_7"; Sprite = "SBMB"; Frame = 6; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_8"; } State { ID = "SORCBALL2_8"; Sprite = "SBMB"; Frame = 7; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_9"; } State { ID = "SORCBALL2_9"; Sprite = "SBMB"; Frame = 8; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_0"; } State { ID = "SORCBALL2_0"; Sprite = "SBMB"; Frame = 9; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_A"; } State { ID = "SORCBALL2_A"; Sprite = "SBMB"; Frame = 10; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_B"; } State { ID = "SORCBALL2_B"; Sprite = "SBMB"; Frame = 11; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_C"; } State { ID = "SORCBALL2_C"; Sprite = "SBMB"; Frame = 12; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_D"; } State { ID = "SORCBALL2_D"; Sprite = "SBMB"; Frame = 13; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_E"; } State { ID = "SORCBALL2_E"; Sprite = "SBMB"; Frame = 14; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_F"; } State { ID = "SORCBALL2_F"; Sprite = "SBMB"; Frame = 15; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL2_1"; } State { ID = "SORCBALL2_D1"; Sprite = "SBMB"; Frame = 0; Tics = 5; Action = "A_SorcBallPop"; Next state = "SORCBALL2_D2"; } State { ID = "SORCBALL2_D2"; Sprite = "SBMB"; Frame = 1; Tics = 2; Action = "A_BounceCheck"; Next state = "SORCBALL2_D2"; } State { ID = "SORCBALL2_D5"; Sprite = "SBS3"; Frame = 3; Tics = 5; Action = "A_Explode"; Next state = "SORCBALL2_D6"; } State { ID = "SORCBALL2_D6"; Sprite = "SBS3"; Frame = 4; Tics = 5; Next state = "SORCBALL2_D7"; } State { ID = "SORCBALL2_D7"; Sprite = "SBS3"; Frame = 5; Tics = 6; Next state = "SORCBALL2_D8"; } State { ID = "SORCBALL2_D8"; Sprite = "SBS3"; Frame = 6; Tics = 6; Next state = "SORCBALL2_D9"; } State { ID = "SORCBALL2_D9"; Sprite = "SBS3"; Frame = 7; Tics = 6; Next state = "NULL"; } State { ID = "SORCBALL3_1"; Sprite = "SBMG"; Frame = 0; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_2"; } State { ID = "SORCBALL3_2"; Sprite = "SBMG"; Frame = 1; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_3"; } State { ID = "SORCBALL3_3"; Sprite = "SBMG"; Frame = 2; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_4"; } State { ID = "SORCBALL3_4"; Sprite = "SBMG"; Frame = 3; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_5"; } State { ID = "SORCBALL3_5"; Sprite = "SBMG"; Frame = 4; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_6"; } State { ID = "SORCBALL3_6"; Sprite = "SBMG"; Frame = 5; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_7"; } State { ID = "SORCBALL3_7"; Sprite = "SBMG"; Frame = 6; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_8"; } State { ID = "SORCBALL3_8"; Sprite = "SBMG"; Frame = 7; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_9"; } State { ID = "SORCBALL3_9"; Sprite = "SBMG"; Frame = 8; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_0"; } State { ID = "SORCBALL3_0"; Sprite = "SBMG"; Frame = 9; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_A"; } State { ID = "SORCBALL3_A"; Sprite = "SBMG"; Frame = 10; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_B"; } State { ID = "SORCBALL3_B"; Sprite = "SBMG"; Frame = 11; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_C"; } State { ID = "SORCBALL3_C"; Sprite = "SBMG"; Frame = 12; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_D"; } State { ID = "SORCBALL3_D"; Sprite = "SBMG"; Frame = 13; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_E"; } State { ID = "SORCBALL3_E"; Sprite = "SBMG"; Frame = 14; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_F"; } State { ID = "SORCBALL3_F"; Sprite = "SBMG"; Frame = 15; Tics = 2; Action = "A_SorcBallOrbit"; Next state = "SORCBALL3_1"; } State { ID = "SORCBALL3_D1"; Sprite = "SBMG"; Frame = 0; Tics = 5; Action = "A_SorcBallPop"; Next state = "SORCBALL3_D2"; } State { ID = "SORCBALL3_D2"; Sprite = "SBMG"; Frame = 1; Tics = 2; Action = "A_BounceCheck"; Next state = "SORCBALL3_D2"; } State { ID = "SORCBALL3_D5"; Sprite = "SBS3"; Frame = 3; Tics = 5; Action = "A_Explode"; Next state = "SORCBALL3_D6"; } State { ID = "SORCBALL3_D6"; Sprite = "SBS3"; Frame = 4; Tics = 5; Next state = "SORCBALL3_D7"; } State { ID = "SORCBALL3_D7"; Sprite = "SBS3"; Frame = 5; Tics = 6; Next state = "SORCBALL3_D8"; } State { ID = "SORCBALL3_D8"; Sprite = "SBS3"; Frame = 6; Tics = 6; Next state = "SORCBALL3_D9"; } State { ID = "SORCBALL3_D9"; Sprite = "SBS3"; Frame = 7; Tics = 6; Next state = "NULL"; } State { ID = "SORCFX1_1"; Sprite = "SBS1"; Frame = 32768; Tics = 2; Next state = "SORCFX1_2"; } State { ID = "SORCFX1_2"; Sprite = "SBS1"; Frame = 32769; Tics = 3; Action = "A_SorcFX1Seek"; Next state = "SORCFX1_3"; } State { ID = "SORCFX1_3"; Sprite = "SBS1"; Frame = 32770; Tics = 3; Action = "A_SorcFX1Seek"; Next state = "SORCFX1_4"; } State { ID = "SORCFX1_4"; Sprite = "SBS1"; Frame = 32771; Tics = 3; Action = "A_SorcFX1Seek"; Next state = "SORCFX1_1"; } State { ID = "SORCFX1_D1"; Sprite = "FHFX"; Frame = 32786; Tics = 2; Action = "A_Explode"; Next state = "SORCFX1_D2"; } State { ID = "SORCFX1_D2"; Sprite = "FHFX"; Frame = 32786; Tics = 6; Next state = "SORCFX1_D3"; } State { ID = "SORCFX1_D3"; Sprite = "FHFX"; Frame = 32786; Tics = 6; Next state = "NULL"; } State { ID = "SORCFX2_SPLIT1"; Sprite = "SBS2"; Frame = 32768; Tics = 3; Action = "A_SorcFX2Split"; Next state = "SORCFX2_SPLIT1"; } State { ID = "SORCFX2_ORBIT1"; Sprite = "SBS2"; Frame = 32768; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT2"; } State { ID = "SORCFX2_ORBIT2"; Sprite = "SBS2"; Frame = 32769; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT3"; } State { ID = "SORCFX2_ORBIT3"; Sprite = "SBS2"; Frame = 32770; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT4"; } State { ID = "SORCFX2_ORBIT4"; Sprite = "SBS2"; Frame = 32771; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT5"; } State { ID = "SORCFX2_ORBIT5"; Sprite = "SBS2"; Frame = 32772; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT6"; } State { ID = "SORCFX2_ORBIT6"; Sprite = "SBS2"; Frame = 32773; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT7"; } State { ID = "SORCFX2_ORBIT7"; Sprite = "SBS2"; Frame = 32774; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT8"; } State { ID = "SORCFX2_ORBIT8"; Sprite = "SBS2"; Frame = 32775; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT9"; } State { ID = "SORCFX2_ORBIT9"; Sprite = "SBS2"; Frame = 32776; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT0"; } State { ID = "SORCFX2_ORBIT0"; Sprite = "SBS2"; Frame = 32777; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBITA"; } State { ID = "SORCFX2_ORBITA"; Sprite = "SBS2"; Frame = 32778; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBITB"; } State { ID = "SORCFX2_ORBITB"; Sprite = "SBS2"; Frame = 32779; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBITC"; } State { ID = "SORCFX2_ORBITC"; Sprite = "SBS2"; Frame = 32780; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBITD"; } State { ID = "SORCFX2_ORBITD"; Sprite = "SBS2"; Frame = 32781; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBITE"; } State { ID = "SORCFX2_ORBITE"; Sprite = "SBS2"; Frame = 32782; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBITF"; } State { ID = "SORCFX2_ORBITF"; Sprite = "SBS2"; Frame = 32783; Tics = 2; Action = "A_SorcFX2Orbit"; Next state = "SORCFX2_ORBIT1"; } State { ID = "SORCFX2T1"; Sprite = "SBS2"; Frame = 0; Tics = 10; Next state = "NULL"; } State { ID = "SORCFX3_1"; Sprite = "SBS3"; Frame = 32768; Tics = 2; Next state = "SORCFX3_2"; } State { ID = "SORCFX3_2"; Sprite = "SBS3"; Frame = 32769; Tics = 2; Next state = "SORCFX3_3"; } State { ID = "SORCFX3_3"; Sprite = "SBS3"; Frame = 32770; Tics = 2; Next state = "SORCFX3_1"; } State { ID = "BISHMORPH1"; Sprite = "SBS3"; Frame = 32768; Tics = 4; Next state = "BISHMORPHA"; } State { ID = "BISHMORPHA"; Sprite = "BISH"; Frame = 15; Tics = 4; Action = "A_SorcererBishopEntry"; Next state = "BISHMORPHB"; } State { ID = "BISHMORPHB"; Sprite = "BISH"; Frame = 14; Tics = 4; Next state = "BISHMORPHC"; } State { ID = "BISHMORPHC"; Sprite = "BISH"; Frame = 13; Tics = 4; Next state = "BISHMORPHD"; } State { ID = "BISHMORPHD"; Sprite = "BISH"; Frame = 12; Tics = 3; Next state = "BISHMORPHE"; } State { ID = "BISHMORPHE"; Sprite = "BISH"; Frame = 11; Tics = 3; Next state = "BISHMORPHF"; } State { ID = "BISHMORPHF"; Sprite = "BISH"; Frame = 10; Tics = 3; Next state = "BISHMORPHG"; } State { ID = "BISHMORPHG"; Sprite = "BISH"; Frame = 9; Tics = 3; Next state = "BISHMORPHH"; } State { ID = "BISHMORPHH"; Sprite = "BISH"; Frame = 8; Tics = 3; Next state = "BISHMORPHI"; } State { ID = "BISHMORPHI"; Sprite = "BISH"; Frame = 7; Tics = 3; Next state = "BISHMORPHJ"; } State { ID = "BISHMORPHJ"; Sprite = "BISH"; Frame = 6; Tics = 3; Action = "A_SpawnBishop"; Next state = "NULL"; } State { ID = "SORCFX3_EXP1"; Sprite = "SBS3"; Frame = 3; Tics = 3; Next state = "SORCFX3_EXP2"; } State { ID = "SORCFX3_EXP2"; Sprite = "SBS3"; Frame = 4; Tics = 3; Next state = "SORCFX3_EXP3"; } State { ID = "SORCFX3_EXP3"; Sprite = "SBS3"; Frame = 5; Tics = 3; Next state = "SORCFX3_EXP4"; } State { ID = "SORCFX3_EXP4"; Sprite = "SBS3"; Frame = 6; Tics = 3; Next state = "SORCFX3_EXP5"; } State { ID = "SORCFX3_EXP5"; Sprite = "SBS3"; Frame = 7; Tics = 3; Next state = "NULL"; } State { ID = "SORCFX4_1"; Sprite = "SBS4"; Frame = 32768; Tics = 2; Action = "A_SorcFX4Check"; Next state = "SORCFX4_2"; } State { ID = "SORCFX4_2"; Sprite = "SBS4"; Frame = 32769; Tics = 2; Action = "A_SorcFX4Check"; Next state = "SORCFX4_3"; } State { ID = "SORCFX4_3"; Sprite = "SBS4"; Frame = 32770; Tics = 2; Action = "A_SorcFX4Check"; Next state = "SORCFX4_1"; } State { ID = "SORCFX4_D1"; Sprite = "SBS4"; Frame = 32771; Tics = 2; Next state = "SORCFX4_D2"; } State { ID = "SORCFX4_D2"; Sprite = "SBS4"; Frame = 32772; Tics = 2; Action = "A_Explode"; Next state = "SORCFX4_D3"; } State { ID = "SORCFX4_D3"; Sprite = "SBS4"; Frame = 32773; Tics = 2; Next state = "SORCFX4_D4"; } State { ID = "SORCFX4_D4"; Sprite = "SBS4"; Frame = 32774; Tics = 2; Next state = "SORCFX4_D5"; } State { ID = "SORCFX4_D5"; Sprite = "SBS4"; Frame = 32775; Tics = 2; Next state = "NULL"; } State { ID = "SORCSPARK1"; Sprite = "SBFX"; Frame = 32768; Tics = 4; Next state = "SORCSPARK2"; } State { ID = "SORCSPARK2"; Sprite = "SBFX"; Frame = 32769; Tics = 4; Next state = "SORCSPARK3"; } State { ID = "SORCSPARK3"; Sprite = "SBFX"; Frame = 32770; Tics = 4; Next state = "SORCSPARK4"; } State { ID = "SORCSPARK4"; Sprite = "SBFX"; Frame = 32771; Tics = 4; Next state = "SORCSPARK5"; } State { ID = "SORCSPARK5"; Sprite = "SBFX"; Frame = 32772; Tics = 4; Next state = "SORCSPARK6"; } State { ID = "SORCSPARK6"; Sprite = "SBFX"; Frame = 32773; Tics = 4; Next state = "SORCSPARK7"; } State { ID = "SORCSPARK7"; Sprite = "SBFX"; Frame = 32774; Tics = 4; Next state = "NULL"; } State { ID = "BLASTEFFECT1"; Sprite = "RADE"; Frame = 32768; Tics = 4; Next state = "BLASTEFFECT2"; } State { ID = "BLASTEFFECT2"; Sprite = "RADE"; Frame = 32769; Tics = 4; Next state = "BLASTEFFECT3"; } State { ID = "BLASTEFFECT3"; Sprite = "RADE"; Frame = 32770; Tics = 4; Next state = "BLASTEFFECT4"; } State { ID = "BLASTEFFECT4"; Sprite = "RADE"; Frame = 32771; Tics = 4; Next state = "BLASTEFFECT5"; } State { ID = "BLASTEFFECT5"; Sprite = "RADE"; Frame = 32772; Tics = 4; Next state = "BLASTEFFECT6"; } State { ID = "BLASTEFFECT6"; Sprite = "RADE"; Frame = 32773; Tics = 4; Next state = "BLASTEFFECT7"; } State { ID = "BLASTEFFECT7"; Sprite = "RADE"; Frame = 32774; Tics = 4; Next state = "BLASTEFFECT8"; } State { ID = "BLASTEFFECT8"; Sprite = "RADE"; Frame = 32775; Tics = 4; Next state = "BLASTEFFECT9"; } State { ID = "BLASTEFFECT9"; Sprite = "RADE"; Frame = 32776; Tics = 4; Next state = "NULL"; } State { ID = "WATERDRIP1"; Sprite = "WATR"; Frame = 0; Tics = 5; Next state = "WATERDRIP1"; } State { ID = "KORAX_LOOK1"; Sprite = "KORX"; Frame = 0; Tics = 5; Action = "A_Look"; Next state = "KORAX_LOOK1"; } State { ID = "KORAX_CHASE1"; Sprite = "KORX"; Frame = 0; Tics = 3; Action = "A_KoraxStep2"; Next state = "KORAX_CHASE2"; } State { ID = "KORAX_CHASE2"; Sprite = "KORX"; Frame = 0; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASE3"; } State { ID = "KORAX_CHASE3"; Sprite = "KORX"; Frame = 0; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASE4"; } State { ID = "KORAX_CHASE4"; Sprite = "KORX"; Frame = 0; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASE5"; } State { ID = "KORAX_CHASE5"; Sprite = "KORX"; Frame = 1; Tics = 3; Action = "A_KoraxStep"; Next state = "KORAX_CHASE6"; } State { ID = "KORAX_CHASE6"; Sprite = "KORX"; Frame = 1; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASE7"; } State { ID = "KORAX_CHASE7"; Sprite = "KORX"; Frame = 1; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASE8"; } State { ID = "KORAX_CHASE8"; Sprite = "KORX"; Frame = 1; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASE9"; } State { ID = "KORAX_CHASE9"; Sprite = "KORX"; Frame = 2; Tics = 3; Action = "A_KoraxStep2"; Next state = "KORAX_CHASE0"; } State { ID = "KORAX_CHASE0"; Sprite = "KORX"; Frame = 2; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASEA"; } State { ID = "KORAX_CHASEA"; Sprite = "KORX"; Frame = 2; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASEB"; } State { ID = "KORAX_CHASEB"; Sprite = "KORX"; Frame = 2; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASEC"; } State { ID = "KORAX_CHASEC"; Sprite = "KORX"; Frame = 3; Tics = 3; Action = "A_KoraxStep"; Next state = "KORAX_CHASED"; } State { ID = "KORAX_CHASED"; Sprite = "KORX"; Frame = 3; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASEE"; } State { ID = "KORAX_CHASEE"; Sprite = "KORX"; Frame = 3; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASEF"; } State { ID = "KORAX_CHASEF"; Sprite = "KORX"; Frame = 3; Tics = 3; Action = "A_KoraxChase"; Next state = "KORAX_CHASE1"; } State { ID = "KORAX_PAIN1"; Sprite = "KORX"; Frame = 7; Tics = 5; Action = "A_Pain"; Next state = "KORAX_PAIN2"; } State { ID = "KORAX_PAIN2"; Sprite = "KORX"; Frame = 7; Tics = 5; Next state = "KORAX_CHASE2"; } State { ID = "KORAX_ATTACK1"; Sprite = "KORX"; Frame = 32772; Tics = 2; Action = "A_FaceTarget"; Next state = "KORAX_ATTACK2"; } State { ID = "KORAX_ATTACK2"; Sprite = "KORX"; Frame = 32772; Tics = 5; Action = "A_KoraxDecide"; Next state = "KORAX_ATTACK2"; } State { ID = "KORAX_MISSILE1"; Sprite = "KORX"; Frame = 32772; Tics = 4; Action = "A_FaceTarget"; Next state = "KORAX_MISSILE2"; } State { ID = "KORAX_MISSILE2"; Sprite = "KORX"; Frame = 32773; Tics = 8; Action = "A_KoraxMissile"; Next state = "KORAX_MISSILE3"; } State { ID = "KORAX_MISSILE3"; Sprite = "KORX"; Frame = 32772; Tics = 8; Next state = "KORAX_CHASE2"; } State { ID = "KORAX_COMMAND1"; Sprite = "KORX"; Frame = 32772; Tics = 5; Action = "A_FaceTarget"; Next state = "KORAX_COMMAND2"; } State { ID = "KORAX_COMMAND2"; Sprite = "KORX"; Frame = 32790; Tics = 10; Action = "A_FaceTarget"; Next state = "KORAX_COMMAND3"; } State { ID = "KORAX_COMMAND3"; Sprite = "KORX"; Frame = 32774; Tics = 15; Action = "A_KoraxCommand"; Next state = "KORAX_COMMAND4"; } State { ID = "KORAX_COMMAND4"; Sprite = "KORX"; Frame = 32790; Tics = 10; Next state = "KORAX_COMMAND5"; } State { ID = "KORAX_COMMAND5"; Sprite = "KORX"; Frame = 32772; Tics = 5; Next state = "KORAX_CHASE2"; } State { ID = "KORAX_DEATH1"; Sprite = "KORX"; Frame = 8; Tics = 5; Next state = "KORAX_DEATH2"; } State { ID = "KORAX_DEATH2"; Sprite = "KORX"; Frame = 9; Tics = 5; Action = "A_FaceTarget"; Next state = "KORAX_DEATH3"; } State { ID = "KORAX_DEATH3"; Sprite = "KORX"; Frame = 10; Tics = 5; Action = "A_Scream"; Next state = "KORAX_DEATH4"; } State { ID = "KORAX_DEATH4"; Sprite = "KORX"; Frame = 11; Tics = 5; Next state = "KORAX_DEATH5"; } State { ID = "KORAX_DEATH5"; Sprite = "KORX"; Frame = 12; Tics = 5; Next state = "KORAX_DEATH6"; } State { ID = "KORAX_DEATH6"; Sprite = "KORX"; Frame = 13; Tics = 5; Next state = "KORAX_DEATH7"; } State { ID = "KORAX_DEATH7"; Sprite = "KORX"; Frame = 14; Tics = 5; Next state = "KORAX_DEATH8"; } State { ID = "KORAX_DEATH8"; Sprite = "KORX"; Frame = 15; Tics = 5; Next state = "KORAX_DEATH9"; } State { ID = "KORAX_DEATH9"; Sprite = "KORX"; Frame = 16; Tics = 10; Next state = "KORAX_DEATH0"; } State { ID = "KORAX_DEATH0"; Sprite = "KORX"; Frame = 17; Tics = 5; Action = "A_KoraxBonePop"; Next state = "KORAX_DEATHA"; } State { ID = "KORAX_DEATHA"; Sprite = "KORX"; Frame = 18; Tics = 5; Action = "A_NoBlocking"; Next state = "KORAX_DEATHB"; } State { ID = "KORAX_DEATHB"; Sprite = "KORX"; Frame = 19; Tics = 5; Next state = "KORAX_DEATHC"; } State { ID = "KORAX_DEATHC"; Sprite = "KORX"; Frame = 20; Tics = 5; Next state = "KORAX_DEATHD"; } State { ID = "KORAX_DEATHD"; Sprite = "KORX"; Frame = 21; Tics = -1; Next state = "NULL"; } State { ID = "KSPIRIT_ROAM1"; Sprite = "SPIR"; Frame = 0; Tics = 5; Action = "A_KSpiritRoam"; Next state = "KSPIRIT_ROAM2"; } State { ID = "KSPIRIT_ROAM2"; Sprite = "SPIR"; Frame = 1; Tics = 5; Action = "A_KSpiritRoam"; Next state = "KSPIRIT_ROAM1"; } State { ID = "KSPIRIT_DEATH1"; Sprite = "SPIR"; Frame = 3; Tics = 5; Next state = "KSPIRIT_DEATH2"; } State { ID = "KSPIRIT_DEATH2"; Sprite = "SPIR"; Frame = 4; Tics = 5; Next state = "KSPIRIT_DEATH3"; } State { ID = "KSPIRIT_DEATH3"; Sprite = "SPIR"; Frame = 5; Tics = 5; Next state = "KSPIRIT_DEATH4"; } State { ID = "KSPIRIT_DEATH4"; Sprite = "SPIR"; Frame = 6; Tics = 5; Next state = "KSPIRIT_DEATH5"; } State { ID = "KSPIRIT_DEATH5"; Sprite = "SPIR"; Frame = 7; Tics = 5; Next state = "KSPIRIT_DEATH6"; } State { ID = "KSPIRIT_DEATH6"; Sprite = "SPIR"; Frame = 8; Tics = 5; Next state = "NULL"; } State { ID = "KBOLT1"; Sprite = "MLFX"; Frame = 32776; Tics = 2; Next state = "KBOLT2"; } State { ID = "KBOLT2"; Sprite = "MLFX"; Frame = 32777; Tics = 2; Action = "A_KBoltRaise"; Next state = "KBOLT3"; } State { ID = "KBOLT3"; Sprite = "MLFX"; Frame = 32776; Tics = 2; Action = "A_KBolt"; Next state = "KBOLT4"; } State { ID = "KBOLT4"; Sprite = "MLFX"; Frame = 32777; Tics = 2; Action = "A_KBolt"; Next state = "KBOLT5"; } State { ID = "KBOLT5"; Sprite = "MLFX"; Frame = 32778; Tics = 2; Action = "A_KBolt"; Next state = "KBOLT6"; } State { ID = "KBOLT6"; Sprite = "MLFX"; Frame = 32779; Tics = 2; Action = "A_KBolt"; Next state = "KBOLT7"; } State { ID = "KBOLT7"; Sprite = "MLFX"; Frame = 32780; Tics = 2; Action = "A_KBolt"; Next state = "KBOLT3"; } State { ID = "SPAWNBATS1"; Sprite = "MAN1"; Frame = 0; Tics = 2; Next state = "SPAWNBATS2"; } State { ID = "SPAWNBATS2"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_BatSpawnInit"; Next state = "SPAWNBATS3"; } State { ID = "SPAWNBATS3"; Sprite = "MAN1"; Frame = 0; Tics = 2; Action = "A_BatSpawn"; Next state = "SPAWNBATS3"; } State { ID = "SPAWNBATS_OFF"; Sprite = "MAN1"; Frame = 0; Tics = -1; Next state = "NULL"; } State { ID = "BAT1"; Sprite = "ABAT"; Frame = 0; Tics = 2; Action = "A_BatMove"; Next state = "BAT2"; } State { ID = "BAT2"; Sprite = "ABAT"; Frame = 1; Tics = 2; Action = "A_BatMove"; Next state = "BAT3"; } State { ID = "BAT3"; Sprite = "ABAT"; Frame = 2; Tics = 2; Action = "A_BatMove"; Next state = "BAT1"; } State { ID = "BAT_DEATH"; Sprite = "ABAT"; Frame = 0; Tics = 2; Next state = "NULL"; } State { ID = "CAMERA"; Sprite = "MAN1"; Frame = 0; Tics = -1; Next state = "NULL"; } Thing { ID = "TEMPSOUNDORIGIN"; DoomEd number = -1; Spawn state = "TEMPSOUNDORIGIN1"; See sound = "NONE"; Attack sound = "NONE"; Pain sound = "NONE"; Death sound = "NONE"; Active sound = "NONE"; Radius = 1; Height = 1; Mass = 100; Flags = "mf_local mf_nosector mf_noblockmap mf_nogravity"; Flags2 = "mf2_dontdraw"; } State { ID = "TEMPSOUNDORIGIN1"; Tics = 175; Next state = "NULL"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/text.ded0000644000175000017500000002344511357170242022422 0ustar keeskees# jHexen: Text Strings Header { Version = 5; } Text { ID = "PRESSKEY"; Text = "Press a key."; } Text { ID = "PRESSYN"; Text = "Press %1 or %2."; } Text { ID = "TXT_PAUSED"; Text = "Paused"; } Text { ID = "QUITMSG"; Text = "Are you sure you want to\nquit this great game?"; } Text { ID = "LOADNET"; Text = "You can't do load while in a net game!"; } Text { ID = "QLOADNET"; Text = "You can't quickload during a netgame!"; } Text { ID = "QSAVESPOT"; Text = "You haven't picked a quicksave slot yet!"; } Text { ID = "SAVEDEAD"; Text = "You can't save if you aren't playing!"; } Text { ID = "QSPROMPT"; Text = "Quicksave over your game named\n\n'%s'?"; } Text { ID = "QLPROMPT"; Text = "Do you want to quickload the game named\n\n'%s'?"; } Text { ID = "NEWGAME"; Text = "You can't start a new game\nwhile in a network game."; } Text { ID = "MSGOFF"; Text = "Messages OFF"; } Text { ID = "MSGON"; Text = "Messages ON"; } Text { ID = "NETEND"; Text = "You can't end a netgame!"; } Text { ID = "ENDGAME"; Text = "Are you sure you want to end the game?"; } Text { ID = "DOSY"; Text = "(Press %1 to quit to DOS.)"; } Text { ID = "TXT_GAMMA_LEVEL_OFF"; Text = "Gamma correction OFF"; } Text { ID = "TXT_GAMMA_LEVEL_1"; Text = "Gamma correction level 1"; } Text { ID = "TXT_GAMMA_LEVEL_2"; Text = "Gamma correction level 2"; } Text { ID = "TXT_GAMMA_LEVEL_3"; Text = "Gamma correction level 3"; } Text { ID = "TXT_GAMMA_LEVEL_4"; Text = "Gamma correction level 4"; } Text { ID = "EMPTYSTRING"; Text = "Empty slot"; } Text { ID = "TXT_MANA_1"; Text = "Blue Mana"; } Text { ID = "TXT_MANA_2"; Text = "Green Mana"; } Text { ID = "TXT_MANA_BOTH"; Text = "Combined Mana"; } Text { ID = "TXT_KEY_STEEL"; Text = "Steel Key"; } Text { ID = "TXT_KEY_CAVE"; Text = "Cave Key"; } Text { ID = "TXT_KEY_AXE"; Text = "Axe Key"; } Text { ID = "TXT_KEY_FIRE"; Text = "Fire Key"; } Text { ID = "TXT_KEY_EMERALD"; Text = "Emerald Key"; } Text { ID = "TXT_KEY_DUNGEON"; Text = "Dungeon Key"; } Text { ID = "TXT_KEY_SILVER"; Text = "Silver Key"; } Text { ID = "TXT_KEY_RUSTED"; Text = "Rusted Key"; } Text { ID = "TXT_KEY_HORN"; Text = "Horn Key"; } Text { ID = "TXT_KEY_SWAMP"; Text = "Swamp Key"; } Text { ID = "TXT_KEY_CASTLE"; Text = "Castle Key"; } Text { ID = "TXT_ARTIINVULNERABILITY"; Text = "Icon of the Defender"; } Text { ID = "TXT_ARTIHEALTH"; Text = "Quartz Flask"; } Text { ID = "TXT_ARTISUPERHEALTH"; Text = "Mystic Urn"; } Text { ID = "TXT_ARTISUMMON"; Text = "Dark Servant"; } Text { ID = "TXT_ARTITORCH"; Text = "Torch"; } Text { ID = "TXT_ARTIEGG"; Text = "Porkalator"; } Text { ID = "TXT_ARTIFLY"; Text = "Wings of Wrath"; } Text { ID = "TXT_ARTITELEPORT"; Text = "Chaos Device"; } Text { ID = "TXT_ARTIPOISONBAG"; Text = "Flechette"; } Text { ID = "TXT_ARTITELEPORTOTHER"; Text = "Banishment Device"; } Text { ID = "TXT_ARTISPEED"; Text = "Boots of Speed"; } Text { ID = "TXT_ARTIBOOSTMANA"; Text = "Krater of Might"; } Text { ID = "TXT_ARTIBOOSTARMOR"; Text = "Dragonskin Bracers"; } Text { ID = "TXT_ARTIBLASTRADIUS"; Text = "Disc of Repulsion"; } Text { ID = "TXT_ARTIHEALINGRADIUS"; Text = "Mystic Ambit Incant"; } Text { ID = "TXT_ARTIPUZZSKULL"; Text = "Yorick's Skull"; } Text { ID = "TXT_ARTIPUZZGEMBIG"; Text = "Heart of D'Sparil"; } Text { ID = "TXT_ARTIPUZZGEMRED"; Text = "Ruby Planet"; } Text { ID = "TXT_ARTIPUZZGEMGREEN1"; Text = "Emerald Planet"; } Text { ID = "TXT_ARTIPUZZGEMGREEN2"; Text = "Emerald Planet"; } Text { ID = "TXT_ARTIPUZZGEMBLUE1"; Text = "Sapphire Planet"; } Text { ID = "TXT_ARTIPUZZGEMBLUE2"; Text = "Sapphire Planet"; } Text { ID = "TXT_ARTIPUZZBOOK1"; Text = "Daemon Codex"; } Text { ID = "TXT_ARTIPUZZBOOK2"; Text = "Liber Oscura"; } Text { ID = "TXT_ARTIPUZZSKULL2"; Text = "Flame Mask"; } Text { ID = "TXT_ARTIPUZZFWEAPON"; Text = "Glaive Seal"; } Text { ID = "TXT_ARTIPUZZCWEAPON"; Text = "Holy Relic"; } Text { ID = "TXT_ARTIPUZZMWEAPON"; Text = "Sigil of the Magus"; } Text { ID = "TXT_ARTIPUZZGEAR1"; Text = "Clock Gear"; } Text { ID = "TXT_ARTIPUZZGEAR2"; Text = "Clock Gear"; } Text { ID = "TXT_ARTIPUZZGEAR3"; Text = "Clock Gear"; } Text { ID = "TXT_ARTIPUZZGEAR4"; Text = "Clock Gear"; } Text { ID = "TXT_USEPUZZLEFAILED"; Text = "You cannot use this here"; } Text { ID = "TXT_ITEMHEALTH"; Text = "Crystal Vial"; } Text { ID = "TXT_ITEMBAGOFHOLDING"; Text = "Bag of Holding"; } Text { ID = "TXT_ITEMSHIELD1"; Text = "Silver Shield"; } Text { ID = "TXT_ITEMSHIELD2"; Text = "Enchanted Shield"; } Text { ID = "TXT_ITEMSUPERMAP"; Text = "Map Scroll"; } Text { ID = "TXT_ARMOR1"; Text = "Mesh Armor"; } Text { ID = "TXT_ARMOR2"; Text = "Falcon Shield"; } Text { ID = "TXT_ARMOR3"; Text = "Platinum Helmet"; } Text { ID = "TXT_ARMOR4"; Text = "Amulet of Warding"; } Text { ID = "TXT_WEAPON_F2"; Text = "Timon's Axe"; } Text { ID = "TXT_WEAPON_F3"; Text = "Hammer of Retribution"; } Text { ID = "TXT_WEAPON_F4"; Text = "Quietus assembled"; } Text { ID = "TXT_WEAPON_C2"; Text = "Serpent Staff"; } Text { ID = "TXT_WEAPON_C3"; Text = "Firestorm"; } Text { ID = "TXT_WEAPON_C4"; Text = "Wraithverge assembled"; } Text { ID = "TXT_WEAPON_M2"; Text = "Frost Shards"; } Text { ID = "TXT_WEAPON_M3"; Text = "Arc of Death"; } Text { ID = "TXT_WEAPON_M4"; Text = "Bloodscourge assembled"; } Text { ID = "TXT_QUIETUS_PIECE"; Text = "Segment of Quietus"; } Text { ID = "TXT_WRAITHVERGE_PIECE"; Text = "Segment of Wraithverge"; } Text { ID = "TXT_BLOODSCOURGE_PIECE"; Text = "Segment of Bloodscourge"; } Text { ID = "TXT_CHEATGODON"; Text = "God mode ON"; } Text { ID = "TXT_CHEATGODOFF"; Text = "God mode OFF"; } Text { ID = "TXT_CHEATNOCLIPON"; Text = "No clipping ON"; } Text { ID = "TXT_CHEATNOCLIPOFF"; Text = "No clipping OFF"; } Text { ID = "TXT_CHEATWEAPONS"; Text = "All weapons"; } Text { ID = "TXT_CHEATHEALTH"; Text = "Full health"; } Text { ID = "TXT_CHEATKEYS"; Text = "All keys"; } Text { ID = "TXT_CHEATSOUNDON"; Text = "Sound debug ON"; } Text { ID = "TXT_CHEATSOUNDOFF"; Text = "Sound debug OFF"; } Text { ID = "TXT_CHEATTICKERON"; Text = "Ticker ON"; } Text { ID = "TXT_CHEATTICKEROFF"; Text = "Ticker OFF"; } Text { ID = "TXT_CHEATARTIFACTS3"; Text = "All artifacts"; } Text { ID = "TXT_CHEATARTIFACTSFAIL"; Text = "Bad input"; } Text { ID = "TXT_CHEATWARP"; Text = "Map warp"; } Text { ID = "TXT_CHEATSCREENSHOT"; Text = "Screenshot"; } Text { ID = "TXT_CHEATIDDQD"; Text = "Trying to cheat, eh? Now you die!"; } Text { ID = "TXT_CHEATIDKFA"; Text = "Cheater - You don't deserve weapons"; } Text { ID = "TXT_CHEATBADINPUT"; Text = "Bad input"; } Text { ID = "TXT_CHEATNOMAP"; Text = "Can't find map"; } Text { ID = "TXT_GAMESAVED"; Text = "Game saved"; } Text { ID = "HUSTR_CHATMACRO0"; Text = "No"; } Text { ID = "HUSTR_CHATMACRO1"; Text = "I'm ready to kick butt!"; } Text { ID = "HUSTR_CHATMACRO2"; Text = "I'm OK."; } Text { ID = "HUSTR_CHATMACRO3"; Text = "I'm not looking too good!"; } Text { ID = "HUSTR_CHATMACRO4"; Text = "Help!"; } Text { ID = "HUSTR_CHATMACRO5"; Text = "You suck!"; } Text { ID = "HUSTR_CHATMACRO6"; Text = "Next time, scumbag..."; } Text { ID = "HUSTR_CHATMACRO7"; Text = "Come here!"; } Text { ID = "HUSTR_CHATMACRO8"; Text = "I'll take care of it."; } Text { ID = "HUSTR_CHATMACRO9"; Text = "Yes"; } Text { ID = "AMSTR_FOLLOWON"; Text = "Follow mode ON"; } Text { ID = "AMSTR_FOLLOWOFF"; Text = "Follow mode OFF"; } Text { ID = "LOADMISSING"; Text = "You weren't in the server's savegame."; } Text { ID = "AMSTR_ROTATEON"; Text = "Rotate mode ON"; } Text { ID = "AMSTR_ROTATEOFF"; Text = "Rotate mode OFF"; } Text { ID = "AMSTR_GRIDON"; Text = "Grid ON"; } Text { ID = "AMSTR_GRIDOFF"; Text = "Grid OFF"; } Text { ID = "AMSTR_MARKEDSPOT"; Text = "Marked spot"; } Text { ID = "AMSTR_MARKSCLEARED"; Text = "All marks cleared"; } Text { ID = "SAVEOUTMAP"; Text = "You can't save if you aren't in a map!"; } Text { ID = "ENDNOGAME"; Text = "You can't end a game that hasn't even begun!"; } Text { ID = "SUICIDEOUTMAP"; Text = "You can't suicide if you aren't in a map!"; } Text { ID = "SUICIDEASK"; Text = "Are you sure you want to suicide?"; } Text { ID = "PICKGAMETYPE"; Text = "Choose game type"; } Text { ID = "SINGLEPLAYER"; Text = "Singleplayer"; } Text { ID = "MULTIPLAYER"; Text = "Multiplayer"; } Text { ID = "NOTDESIGNEDFOR"; Text = "Not designed for %1."; } Text { ID = "GAMESETUP"; Text = "Game Setup"; } Text { ID = "PLAYERSETUP"; Text = "Player Setup"; } Text { ID = "RANDOMPLAYERCLASS"; Text = "Random"; } Text { ID = "PLAYERCLASS1"; Text = "Fighter"; } Text { ID = "PLAYERCLASS2"; Text = "Cleric"; } Text { ID = "PLAYERCLASS3"; Text = "Mage"; } Text { ID = "PLAYERCLASS4"; Text = "Pig"; } Text { ID = "SKILLF1"; Text = "Squire"; } Text { ID = "SKILLF2"; Text = "Knight"; } Text { ID = "SKILLF3"; Text = "Warrior"; } Text { ID = "SKILLF4"; Text = "Berserker"; } Text { ID = "SKILLF5"; Text = "Titan"; } Text { ID = "SKILLC1"; Text = "Altar Boy"; } Text { ID = "SKILLC2"; Text = "Acolyte"; } Text { ID = "SKILLC3"; Text = "Priest"; } Text { ID = "SKILLC4"; Text = "Cardinal"; } Text { ID = "SKILLC5"; Text = "Pope"; } Text { ID = "SKILLM1"; Text = "Apprentice"; } Text { ID = "SKILLM2"; Text = "Enchanter"; } Text { ID = "SKILLM3"; Text = "Sorcerer"; } Text { ID = "SKILLM4"; Text = "Warlock"; } Text { ID = "SKILLM5"; Text = "Archimage"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/finales.ded0000644000175000017500000002601311357170242023051 0ustar keeskees# jHexen: Intermissions and Finales # (see Doc\InFine.txt) Header { Version = 5; } InFine { ID = "title"; Script { # There is no skipping during the titlescreen loop. NoSkip # Any event shows the menu. Trigger MARKER title_loop # Step 1. Image back "TITLE" Music "hexen" Wait 7 # Step 2. Patch advice 4 160 "ADVISOR" In 0 Alpha advice 0 In 1 Alpha advice 1 Wait 7 # Step 3. PlayDemo "demo1.cdm" # Step 4. DelPic advice Image back "CREDIT" Wait 5.714 # Original is 200 tics. # Step 5. PlayDemo "demo2.cdm" # Step 6. Wait 5.714 # Original is 200 tics. # Step 7. PlayDemo "demo3.cdm" GOTO title_loop }; } # First Hub: The Seven Portals Finale { After = "MAP02"; Script { # Only show this after the hub has been completed. ifnot leavehub end; # Don't show this in deathmatch. if deathmatch end; music "hub"; image back INTERPIC; wait 0.5; # Originally 10 tics. textlump msg 10 5 CLUS1MSG; #> "having passed the seven portals\n which sealed this realm, a vast\n domain of harsh wilderness stretches\n before you. fire, ice and steel have\n tested you, but greater challenges\n remain ahead. the dense tangle of\n forest surely hides hostile eyes,\n but what lies beyond will be worse.\n\n barren desert, dank swamps and\n musty caverns bar your way, but you\n cannot let anything keep you from\n your fate, even if you might come\n to wish that it would.\n\n and beyond, flickering in the\n distance, the ever-shifting walls\n of the hypostyle seem to mock\n your every effort."; <# waittext msg; wait 5; # Original TEXTWAIT is 140+10 tics. }; } # Second Hub: The Shadowwood (exit from The Hypostyle) Finale { After = "MAP12"; Script { # Only show this after the hub has been completed. ifnot leavehub end; # Don't show this in deathmatch. if deathmatch end; music "hub"; image back INTERPIC; wait 0.5; # Originally 10 tics. textlump msg 10 5 CLUS2MSG; #>"your mind still reeling from your\n encounters within the hypostyle, you\n stagger toward what you hope is\n a way out. things seem to move faster\n and faster, your vision blurs and\n begins to fade...\n as the world collapses around you,\n the brightness of a teleportal\n engulfs you. a flash of light, and then\n you climb wearily to your feet.\n\n you stand atop a high tower, and\n from below come the screams of the\n damned. you step forward, and\n instantly the sound of demonic\n chanting chills your blood.\n by all the gods of death! what place\n have you come to? by all the gods of\n pain, how will you ever find your\n way out?";<# waittext msg; wait 5; # Original TEXTWAIT is 140+10 tics. }; } # Third Hub: Heresiarch's Seminary Finale { After = "MAP27"; Script { # Only show this after the hub has been completed. ifnot leavehub end; # Don't show this in deathmatch. if deathmatch end; music "hub"; image back INTERPIC; wait 0.5; # Originally 10 tics. textlump msg 10 5 CLUS3MSG; #>"the mightiest weapons and artifacts\n of the ancients barely sufficed to\n defeat the heresiarch and his\n minions, but now their foul remains\n lie strewn at your feet. gathering\n the last of your strength, you\n prepare to enter the portal which\n leads from the heresiarch's inner\n sanctum.\n\n above you, the ramparts of an\n immense castle loom. silent towers\n and bare walls surround a single\n spire of black stone, which squats\n in the center of the castle like a\n brooding giant. fire and shadow\n twist behind gaping windows, dozens\n of baleful eyes glaring down upon\n you.\n somewhere within, your enemies are\n waiting...";<# waittext msg; wait 5; # Original TEXTWAIT is 140+10 tics. }; } # Fourth Hub: The Castle of Grief (exit from Gibbet) Finale { After = "MAP23"; Script { # Only show this after the hub has been completed. ifnot leavehub end; # Don't show this in deathmatch. if deathmatch end; music "hub"; image back INTERPIC; wait 0.5; # Originally 10 tics. textlump msg 10 5 CLUS4MSG; #>"\"... and he shall journey into the\n realms of the dead, and contest with\n the forces therein, unto the very\n gates of despair. but whether he\n shall return again to the world of\n light, no man knows.\"\n \_ \n \_ \n \_ \n \_ \n \_ \n damn.";<# waittext msg; wait 5; # Original TEXTWAIT is 140+10 tics. }; } # Fifth Hub: The Necropolis (ends in Dark Crucible) Finale { After = "MAP40"; Script { # This is the real finale of the game. noskip; # No more levels after this, disallow skipping. musiconce "hall"; # Setup the first screen. image back FINALE1; # Fade into the first screen. filter 0 0 0 1; in 2 filter 0 0 0 0; wait 2; textlump msg 20 100 WIN1MSG; #text msg 20 100 #>"with a scream of agony you are\n wrenched from this world into\n another, every part of your body\n wreathed in mystic fire. when your\n vision clears, you find yourself\n standing in a great hall, filled\n with ghostly echoes and menacing\n shadows. in the distance you can\n see a raised dais, and upon it the\n only source of light in this world.";<# waittext msg; wait 7; # Original TEXTWAIT is 250 tics. # Second screen: the Orb. musiconce "orb"; image back FINALE2; deltext msg; wait 0.5; textlump msg 20 5 WIN2MSG; #>text msg 20 5 "this can only be the chaos sphere,\n the source of korax's power. with\n this, you can create worlds... or\n destroy them. by rights of battle\n and conquest it is yours, and with\n trembling hands you reach to grasp\n it. perhaps, now, a new player will\n join the cosmic game of power. like\n the pawn who is promoted to queen,\n suddenly the very reaches of the\n board seem to be within your grasp.";<# waittext msg; wait 7; # Original TEXTWAIT is 250 tics. # Fade out. in 2 filter 0 0 0 1; wait 2; deltext msg; # Setup the last screen: the Chess. music "chess"; image back FINALE3; # Choose the right player patch (no patch=fighter). if netgame patch pl 20 0 CHESSALL; if netgame goto m; if cleric patch pl 60 0 CHESSC; if mage patch pl 60 0 CHESSM; marker m; # Fade in. filter 0 0 0 0; wait 2; textlump msg 20 135 WIN3MSG; #>text msg 20 135 " \n but there are other players mightier\n than you, and who can know their\n next moves?";<# }; } ######======------ DEATHKINGS OF THE DARK CITADEL ------======###### # Deathkings uses maps 41-60. # 1st Hub Finale { After = "MAP42"; Script { # Only show this after the hub has been completed. ifnot leavehub end; # Don't show this in deathmatch. if deathmatch end; music "hub"; image back INTERPIC; wait 0.5; # Originally 10 tics. textlump msg 10 5 CLUS1MSG; #>text msg 10 5 "wiping a trembling hand across your\n bleeding face, you try to clear\n your mind for what lies ahead...\n\n ...and forget what lies behind.\n\n in the distance, the stark ramparts\n of a great castle complex seem to\n rend the sky above, and the stench\n of decay wafts from the violated\n graves of uncounted dead.\n\n carefully counting what little\n remains of your artifacts, you try\n to reassure yourself that it will\n be enough. after all, it has to be\n enough, doesn't it?\n\n\n doesn't it?";<# waittext msg; wait 5; # Original TEXTWAIT is 140+10 tics. }; } # 2nd Hub Finale { After = "MAP48"; Script { # Only show this after the hub has been completed. ifnot leavehub end; # Don't show this in deathmatch. if deathmatch end; music "hub"; image back INTERPIC; wait 0.5; # Originally 10 tics. textlump msg 10 5 CLUS2MSG; #>text msg 10 5 "surely the souls of the damned inhabit\n this world, for nothing fair or good\n could survive here for long.\n\n but what has passed before can only\n be a pale shadow of what bars your\n passage now: the dark citadel itself.\n\n the grim bulk of the cathedral blocks\n all but fragmentary glimpses of the\n citadel proper, but what can be seen\n speaks in sibilant whispers of cold,\n lingering death...\n\n\n\n\n\n ...for the fortunate.";<# waittext msg; wait 5; # Original TEXTWAIT is 140+10 tics. }; } # 3rd Hub Finale { After = "MAP60"; Script { # This is the real finale of the game. noskip; # No more levels after this, disallow skipping. musiconce "hall"; # Setup the first screen. image back FINALE1; # Fade into the first screen. filter 0 0 0 1; in 2 filter 0 0 0 0; wait 2; textlump msg 20 5 WIN1MSG; #>text msg 20 5 "once again you find yourself in the\n great hall of the chaos sphere, as\ if no time had passed from when\n last you moved among these shadows.\n\n but something is eerily different,\n a silence where once had been soft\n whispers, a sense of being watched\n by hidden eyes...\n\n ...eyes which shield a malefic\n intent.";<# waittext msg; wait 7; # Original TEXTWAIT is 250 tics. # Second screen: the Orb. musiconce "orb"; image back FINALE2; deltext msg; wait 0.5; textlump msg 20 5 WIN2MSG; #>text msg 20 5 "once before you grasped the chaos\n sphere, held it within trembling\n hands. now your hands tremble with\n something more than avarice, and\n dread meshes with the hunger for\n power.\n\n if even the power of the sphere is\n not enough to protect you from the\n forces of darkness, perhaps it is\n better left untouched, its promise\n left unkept.\n\n\n\n but then, you never were one to\n back down from a challenge...";<# waittext msg; wait 7; # Original TEXTWAIT is 250 tics. # Fade out. in 2 filter 0 0 0 1; wait 2; deltext msg; # Setup the last screen: the Chess. music "chess"; image back FINALE3; # Choose the right player patch (no patch=fighter). if netgame patch pl 20 0 CHESSALL; if netgame goto m; if cleric patch pl 60 0 CHESSC; if mage patch pl 60 0 CHESSM; marker m; # Fade in. filter 0 0 0 0; wait 2; #text msg 20 135 "\n...and other players await."; textlump msg 20 135 WIN3MSG; }; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/lights.ded0000644000175000017500000001362011357170242022722 0ustar keeskees# jHexen: Lights # Need help with DED syntax? See DEDDoc.txt. Header { Version = 6; } #####====--- LIGHT DECORATIONS ---====##### # # The default flags allow using these only with the original textures. # Use "dcf_pwad" and "dcf_ext" to allow using with PWAD and external # resources. # # There can only be one decoration per texture/flat. Newer decorations # override older ones. # # One decoration can specify up to 16 lights. # # (based on Isegrim's definitions) Decoration { Texture = "MONK22"; Light { Color { 1 0 0 } Offset { 74 48 } Halo radius = .025; Radius = .05; } } Decoration { Texture = "PLANET2"; Light { Color { 1 0 0 }; Offset { 28 88 } Halo radius = .1; Radius = .08; } } Decoration { Texture = "PLANET1"; Light { Color { 1 0 0 } Offset { 28 88 } Halo radius = .1; Radius = .08; } Light { Color { 0 0 1 } Offset { 32 48 } Halo radius = .1; Radius = .08; } Light { Color { 0 1 0 } Offset { 48 28 } Halo radius = .1; Radius = .08; } Light { Color { 0 1 0 } Offset { 64 102 } Halo radius = .1; Radius = .08; } Light { Color { 1 0 0 } Offset { 96 48 } Halo radius = .1; Radius = .08; } Light { Color { 0 0 1 } Offset { 108 68 } Halo radius = .1; Radius = .08; } } Decoration { Texture = "SW_1_DN"; Light { Color { 0 0 1 } Offset { 11 13 } Halo radius = 0; Radius = .025; } Light { Color { 0 0 1 } Offset { 21 13 } Halo radius = 0; Radius = .025; } } Copy Decoration { Texture = "SW_2_MD"; } Copy Decoration { Texture = "SW_1_MD"; Light { Color { 0 1 0 } } Light { Color { 0 1 0 } } } Copy Decoration { Texture = "SW_2_DN"; Light { Color { 1 0 0 } } Light { Color { 1 0 0 } } } Decoration { Texture = "SW52_ON"; Light { Color { .8 .7 0 } Offset { 9 15 } Halo radius = 0; Radius = .08; } } Decoration { Texture = "SW51_ON"; Light { Color { 1 .8 0 } Offset { 9 11 } Halo radius = 0; Radius = .025; } Light { Color { 1 .8 0 } Offset { 23 11 } Halo radius = 0; Radius = .025; } Light { Color { 1 .8 0 } Offset { 16 14 } Halo radius = 0; Radius = .025; } Light { Color { .8 .7 0 } Offset { 16 23 } Halo radius = 0; Radius = .05; } } Decoration { Texture = "SPAWN03"; Light { Color { 1 .5 0 } Offset { 32 42 } Halo radius = .05; Radius = .08; } } Decoration { Texture = "SPAWN12"; Light { Color { 1 .7 0 } Offset { 16.5 13 } Halo radius = .02; Radius = .08; } } Decoration { Texture = "SPAWN09"; Light { Color { .5 0 0 } Offset { 54 57 } Halo radius = 0; Radius = .05; } Light { Color { .5 0 0 } Offset { 64 47 } Halo radius = 0; Radius = .05; } Light { Color { .5 0 0 } Offset { 75 57 } Halo radius = 0; Radius = .05; } } Decoration { Texture = "SPAWN10"; Light { Color { 1 .3 0 } Offset { 54 57 } Halo radius = .1; Radius = .05; Flare texture = 1; } Light { Color { 1 .3 0 } Offset { 65 47 } Halo radius = .1; Radius = .05; Flare texture = 1; } Light { Color { 1 .3 0 } Offset { 75 57 } Halo radius = .1; Radius = .05; Flare texture = 1; } } #####====--- LIGHT SOURCE PROPERTIES ---====##### # A halo would look bad for the chandelier because it wouldn't be # rendered around the candle flames. Light { State = "ZCHANDELIER1"; Size = 0.8; Flags = "lgf_nohalo"; } * Light { State = "ZCHANDELIER2"; } * Light { State = "ZCHANDELIER3"; } # The fire demon's flames are too distributed to have one halo. # A general glow would be better. Light { State = "FIRED_SPAWN1"; Flags = "lgf_nohalo"; } * Light { State = "FIRED_LOOK1"; } * Light { State = "FIRED_LOOK2"; } * Light { State = "FIRED_LOOK3"; } * Light { State = "FIRED_LOOK4"; } * Light { State = "FIRED_LOOK5"; } * Light { State = "FIRED_LOOK6"; } * Light { State = "FIRED_LOOK7"; } * Light { State = "FIRED_LOOK8"; } * Light { State = "FIRED_LOOK9"; } * Light { State = "FIRED_LOOK0"; } * Light { State = "FIRED_LOOKA"; } * Light { State = "FIRED_LOOKB"; } * Light { State = "FIRED_WALK1"; } * Light { State = "FIRED_WALK2"; } * Light { State = "FIRED_WALK3"; } * Light { State = "FIRED_ATTACK1"; } * Light { State = "FIRED_ATTACK2"; } * Light { State = "FIRED_ATTACK3"; } * Light { State = "FIRED_PAIN1"; } * Light { State = "FIRED_XDEATH1"; } * Light { State = "FIRED_XDEATH2"; } * Light { State = "FIRED_XDEATH3"; } * Light { State = "FIRED_DEATH1"; } * Light { State = "FIRED_DEATH2"; } * Light { State = "FIRED_DEATH3"; } * Light { State = "FIRED_DEATH4"; } Light { State = "ARTI_BLAST1"; Size = 0.45; } * Light { State = "ARTI_BLAST2"; } * Light { State = "ARTI_BLAST3"; } * Light { State = "ARTI_BLAST4"; } * Light { State = "ARTI_BLAST5"; } * Light { State = "ARTI_BLAST6"; } * Light { State = "ARTI_BLAST7"; } * Light { State = "ARTI_BLAST8"; } Light { State = "MANA3_1"; Size = 0.4; } * Light { State = "MANA3_2"; } * Light { State = "MANA3_3"; } * Light { State = "MANA3_4"; } * Light { State = "MANA3_5"; } * Light { State = "MANA3_6"; } * Light { State = "MANA3_7"; } * Light { State = "MANA3_8"; } * Light { State = "MANA3_9"; } * Light { State = "MANA3_10"; } * Light { State = "MANA3_11"; } * Light { State = "MANA3_12"; } * Light { State = "MANA3_13"; } * Light { State = "MANA3_14"; } * Light { State = "MANA3_15"; } * Light { State = "MANA3_16"; } # The normal adaptive halo of the Boots of Speed doesn't look too # good with models, so make it a bit more static. Light { State = "ARTI_BOOTS1"; Size = 0.3; X Offset = 0.1; Y Offset = 12; Color { 1 0.6 0.4 } } * Light { State = "ARTI_BOOTS2"; } * Light { State = "ARTI_BOOTS3"; } * Light { State = "ARTI_BOOTS4"; } * Light { State = "ARTI_BOOTS5"; } * Light { State = "ARTI_BOOTS6"; } * Light { State = "ARTI_BOOTS7"; } * Light { State = "ARTI_BOOTS8"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/defs/sprites.ded0000644000175000017500000001626611357170242023132 0ustar keeskees# jHexen: Sprites # # Order of definitions is very important here! # Only add new Sprites *after* the existing definitions. Header { Version = 5; } Sprite { ID = "MAN1"; } Sprite { ID = "ACLO"; } Sprite { ID = "TLGL"; } Sprite { ID = "FBL1"; } Sprite { ID = "XPL1"; } Sprite { ID = "ARRW"; } Sprite { ID = "DART"; } Sprite { ID = "RIPP"; } Sprite { ID = "CFCF"; } Sprite { ID = "BLAD"; } Sprite { ID = "SHRD"; } Sprite { ID = "FFSM"; } Sprite { ID = "FFLG"; } Sprite { ID = "PTN1"; } Sprite { ID = "PTN2"; } Sprite { ID = "SOAR"; } Sprite { ID = "INVU"; } Sprite { ID = "SUMN"; } Sprite { ID = "TSPK"; } Sprite { ID = "TELO"; } Sprite { ID = "TRNG"; } Sprite { ID = "ROCK"; } Sprite { ID = "FOGS"; } Sprite { ID = "FOGM"; } Sprite { ID = "FOGL"; } Sprite { ID = "SGSA"; } Sprite { ID = "SGSB"; } Sprite { ID = "PORK"; } Sprite { ID = "EGGM"; } Sprite { ID = "FHFX"; } Sprite { ID = "SPHL"; } Sprite { ID = "STWN"; } Sprite { ID = "GMPD"; } Sprite { ID = "ASKU"; } Sprite { ID = "ABGM"; } Sprite { ID = "AGMR"; } Sprite { ID = "AGMG"; } Sprite { ID = "AGG2"; } Sprite { ID = "AGMB"; } Sprite { ID = "AGB2"; } Sprite { ID = "ABK1"; } Sprite { ID = "ABK2"; } Sprite { ID = "ASK2"; } Sprite { ID = "AFWP"; } Sprite { ID = "ACWP"; } Sprite { ID = "AMWP"; } Sprite { ID = "AGER"; } Sprite { ID = "AGR2"; } Sprite { ID = "AGR3"; } Sprite { ID = "AGR4"; } Sprite { ID = "TRCH"; } Sprite { ID = "PSBG"; } Sprite { ID = "ATLP"; } Sprite { ID = "THRW"; } Sprite { ID = "SPED"; } Sprite { ID = "BMAN"; } Sprite { ID = "BRAC"; } Sprite { ID = "BLST"; } Sprite { ID = "HRAD"; } Sprite { ID = "SPSH"; } Sprite { ID = "LVAS"; } Sprite { ID = "SLDG"; } Sprite { ID = "STTW"; } Sprite { ID = "RCK1"; } Sprite { ID = "RCK2"; } Sprite { ID = "RCK3"; } Sprite { ID = "RCK4"; } Sprite { ID = "CDLR"; } Sprite { ID = "TRE1"; } Sprite { ID = "TRDT"; } Sprite { ID = "TRE2"; } Sprite { ID = "TRE3"; } Sprite { ID = "STM1"; } Sprite { ID = "STM2"; } Sprite { ID = "STM3"; } Sprite { ID = "STM4"; } Sprite { ID = "MSH1"; } Sprite { ID = "MSH2"; } Sprite { ID = "MSH3"; } Sprite { ID = "MSH4"; } Sprite { ID = "MSH5"; } Sprite { ID = "MSH6"; } Sprite { ID = "MSH7"; } Sprite { ID = "MSH8"; } Sprite { ID = "SGMP"; } Sprite { ID = "SGM1"; } Sprite { ID = "SGM2"; } Sprite { ID = "SGM3"; } Sprite { ID = "SLC1"; } Sprite { ID = "SLC2"; } Sprite { ID = "SLC3"; } Sprite { ID = "MSS1"; } Sprite { ID = "MSS2"; } Sprite { ID = "SWMV"; } Sprite { ID = "CPS1"; } Sprite { ID = "CPS2"; } Sprite { ID = "TMS1"; } Sprite { ID = "TMS2"; } Sprite { ID = "TMS3"; } Sprite { ID = "TMS4"; } Sprite { ID = "TMS5"; } Sprite { ID = "TMS6"; } Sprite { ID = "TMS7"; } Sprite { ID = "CPS3"; } Sprite { ID = "STT2"; } Sprite { ID = "STT3"; } Sprite { ID = "STT4"; } Sprite { ID = "STT5"; } Sprite { ID = "GAR1"; } Sprite { ID = "GAR2"; } Sprite { ID = "GAR3"; } Sprite { ID = "GAR4"; } Sprite { ID = "GAR5"; } Sprite { ID = "GAR6"; } Sprite { ID = "GAR7"; } Sprite { ID = "GAR8"; } Sprite { ID = "GAR9"; } Sprite { ID = "BNR1"; } Sprite { ID = "TRE4"; } Sprite { ID = "TRE5"; } Sprite { ID = "TRE6"; } Sprite { ID = "TRE7"; } Sprite { ID = "LOGG"; } Sprite { ID = "ICT1"; } Sprite { ID = "ICT2"; } Sprite { ID = "ICT3"; } Sprite { ID = "ICT4"; } Sprite { ID = "ICM1"; } Sprite { ID = "ICM2"; } Sprite { ID = "ICM3"; } Sprite { ID = "ICM4"; } Sprite { ID = "RKBL"; } Sprite { ID = "RKBS"; } Sprite { ID = "RKBK"; } Sprite { ID = "RBL1"; } Sprite { ID = "RBL2"; } Sprite { ID = "RBL3"; } Sprite { ID = "VASE"; } Sprite { ID = "POT1"; } Sprite { ID = "POT2"; } Sprite { ID = "POT3"; } Sprite { ID = "PBIT"; } Sprite { ID = "CPS4"; } Sprite { ID = "CPS5"; } Sprite { ID = "CPS6"; } Sprite { ID = "CPB1"; } Sprite { ID = "CPB2"; } Sprite { ID = "CPB3"; } Sprite { ID = "CPB4"; } Sprite { ID = "BDRP"; } Sprite { ID = "BDSH"; } Sprite { ID = "BDPL"; } Sprite { ID = "CNDL"; } Sprite { ID = "LEF1"; } Sprite { ID = "LEF3"; } Sprite { ID = "LEF2"; } Sprite { ID = "TWTR"; } Sprite { ID = "WLTR"; } Sprite { ID = "BARL"; } Sprite { ID = "SHB1"; } Sprite { ID = "SHB2"; } Sprite { ID = "BCKT"; } Sprite { ID = "SHRM"; } Sprite { ID = "FBUL"; } Sprite { ID = "FSKL"; } Sprite { ID = "BRTR"; } Sprite { ID = "SUIT"; } Sprite { ID = "BBLL"; } Sprite { ID = "CAND"; } Sprite { ID = "IRON"; } Sprite { ID = "XMAS"; } Sprite { ID = "CDRN"; } Sprite { ID = "CHNS"; } Sprite { ID = "TST1"; } Sprite { ID = "TST2"; } Sprite { ID = "TST3"; } Sprite { ID = "TST4"; } Sprite { ID = "TST5"; } Sprite { ID = "TST6"; } Sprite { ID = "TST7"; } Sprite { ID = "TST8"; } Sprite { ID = "TST9"; } Sprite { ID = "TST0"; } Sprite { ID = "TELE"; } Sprite { ID = "TSMK"; } Sprite { ID = "FPCH"; } Sprite { ID = "WFAX"; } Sprite { ID = "FAXE"; } Sprite { ID = "WFHM"; } Sprite { ID = "FHMR"; } Sprite { ID = "FSRD"; } Sprite { ID = "FSFX"; } Sprite { ID = "CMCE"; } Sprite { ID = "WCSS"; } Sprite { ID = "CSSF"; } Sprite { ID = "WCFM"; } Sprite { ID = "CFLM"; } Sprite { ID = "CFFX"; } Sprite { ID = "CHLY"; } Sprite { ID = "SPIR"; } Sprite { ID = "MWND"; } Sprite { ID = "WMLG"; } Sprite { ID = "MLNG"; } Sprite { ID = "MLFX"; } Sprite { ID = "MLF2"; } Sprite { ID = "MSTF"; } Sprite { ID = "MSP1"; } Sprite { ID = "MSP2"; } Sprite { ID = "WFR1"; } Sprite { ID = "WFR2"; } Sprite { ID = "WFR3"; } Sprite { ID = "WCH1"; } Sprite { ID = "WCH2"; } Sprite { ID = "WCH3"; } Sprite { ID = "WMS1"; } Sprite { ID = "WMS2"; } Sprite { ID = "WMS3"; } Sprite { ID = "WPIG"; } Sprite { ID = "WMCS"; } Sprite { ID = "CONE"; } Sprite { ID = "SHEX"; } Sprite { ID = "BLOD"; } Sprite { ID = "GIBS"; } Sprite { ID = "PLAY"; } Sprite { ID = "FDTH"; } Sprite { ID = "BSKL"; } Sprite { ID = "ICEC"; } Sprite { ID = "CLER"; } Sprite { ID = "MAGE"; } Sprite { ID = "PIGY"; } Sprite { ID = "CENT"; } Sprite { ID = "CTXD"; } Sprite { ID = "CTFX"; } Sprite { ID = "CTDP"; } Sprite { ID = "DEMN"; } Sprite { ID = "DEMA"; } Sprite { ID = "DEMB"; } Sprite { ID = "DEMC"; } Sprite { ID = "DEMD"; } Sprite { ID = "DEME"; } Sprite { ID = "DMFX"; } Sprite { ID = "DEM2"; } Sprite { ID = "DMBA"; } Sprite { ID = "DMBB"; } Sprite { ID = "DMBC"; } Sprite { ID = "DMBD"; } Sprite { ID = "DMBE"; } Sprite { ID = "D2FX"; } Sprite { ID = "WRTH"; } Sprite { ID = "WRT2"; } Sprite { ID = "WRBL"; } Sprite { ID = "MNTR"; } Sprite { ID = "FX12"; } Sprite { ID = "FX13"; } Sprite { ID = "MNSM"; } Sprite { ID = "SSPT"; } Sprite { ID = "SSDV"; } Sprite { ID = "SSXD"; } Sprite { ID = "SSFX"; } Sprite { ID = "BISH"; } Sprite { ID = "BPFX"; } Sprite { ID = "DRAG"; } Sprite { ID = "DRFX"; } Sprite { ID = "ARM1"; } Sprite { ID = "ARM2"; } Sprite { ID = "ARM3"; } Sprite { ID = "ARM4"; } Sprite { ID = "MAN2"; } Sprite { ID = "MAN3"; } Sprite { ID = "KEY1"; } Sprite { ID = "KEY2"; } Sprite { ID = "KEY3"; } Sprite { ID = "KEY4"; } Sprite { ID = "KEY5"; } Sprite { ID = "KEY6"; } Sprite { ID = "KEY7"; } Sprite { ID = "KEY8"; } Sprite { ID = "KEY9"; } Sprite { ID = "KEYA"; } Sprite { ID = "KEYB"; } Sprite { ID = "ETTN"; } Sprite { ID = "ETTB"; } Sprite { ID = "FDMN"; } Sprite { ID = "FDMB"; } Sprite { ID = "ICEY"; } Sprite { ID = "ICPR"; } Sprite { ID = "ICWS"; } Sprite { ID = "SORC"; } Sprite { ID = "SBMP"; } Sprite { ID = "SBS4"; } Sprite { ID = "SBMB"; } Sprite { ID = "SBS3"; } Sprite { ID = "SBMG"; } Sprite { ID = "SBS1"; } Sprite { ID = "SBS2"; } Sprite { ID = "SBFX"; } Sprite { ID = "RADE"; } Sprite { ID = "WATR"; } Sprite { ID = "KORX"; } Sprite { ID = "ABAT"; } deng-1.9.0-beta6.9+dfsg1/doomsday/plugins/jhexen/CMakeLists.txt0000644000175000017500000001263511357170242022576 0ustar keeskees## deng build scripts. ## Copyright © 2006 - 2007 Jamie Jones ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/plugins/common/include ) FILE(GLOB COMMON_PLUGIN_SOURCES ${CMAKE_SOURCE_DIR}/plugins/common/src/*.c) ################################################################################ ######################## External LZSS Files ################################### INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/external/lzss/portable/include ) IF (UNIX) IF (NOT WIN32) FILE(GLOB LZSS_SOURCES ${CMAKE_SOURCE_DIR}/external/lzss/unix/src/*.c) ENDIF (NOT WIN32) ENDIF (UNIX) IF (WIN32) SET (LZSS_SOURCES "") ENDIF (WIN32) ################################################################################ ######################## jHexen Game Plugin #################################### ADD_DEFINITIONS (-D__JHEXEN__ ) INCLUDE_DIRECTORIES ( include ) IF (ENABLEMAO) SET (JHEXEN_SOURCES ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/a_action.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/h2_actn.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/hrefresh.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/m_misc.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_ceilng.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_floor.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_maputl.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_plats.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_spec.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_things.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/s_sound.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/tables.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/acfnlink.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/in_lude.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_acs.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_doors.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_inter.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_pspr.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_switch.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/sc_man.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/st_stuff.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/x_api.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/g_ctrl.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/hconsole.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/m_cheat.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_anim.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_enemy.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_lights.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/po_man.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_setup.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/sn_sonix.c ) ELSE (ENABLEMAO) FILE(GLOB JHEXEN_SOURCES ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/*.c) ENDIF (ENABLEMAO) IF (ENABLEMAO) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jhexen_mao.c ${JHEXEN_SOURCES} ) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jhexen_common.c ${COMMON_PLUGIN_SOURCES} ) CREATE_MODULE_AT_ONCE_FILE (${CMAKE_BINARY_DIR}/_jhexen_mobj.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/h2_main.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_mobj.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/p_telept.c ${CMAKE_SOURCE_DIR}/plugins/jhexen/src/sv_save.c ) ADD_LIBRARY (jhexen SHARED ${CMAKE_BINARY_DIR}/_jhexen_common.c ${CMAKE_BINARY_DIR}/_jhexen_mao.c ${CMAKE_BINARY_DIR}/_jhexen_mobj.c ${LZSS_SOURCES}) ELSE (ENABLEMAO) ADD_LIBRARY (jhexen SHARED ${JHEXEN_SOURCES} ${LZSS_SOURCES} ${COMMON_PLUGIN_SOURCES} ) ENDIF (ENABLEMAO) IF (WIN32) TARGET_LINK_LIBRARIES (jhexen ${CMAKE_SOURCE_DIR}/external/lzss/win32/lzss) ENDIF (WIN32) #IF (APPLE) # SET_TARGET_PROPERTIES (jhexen PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS} -bundle -bundle_loader doomsday") #ENDIF (APPLE) ################################################################################ ######################## Install Targets ###################################### INSTALL(TARGETS jhexen RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) IF (APPLE) # Bundling. SET (BUNDLE_BASE jHexen) SET (BUNDLE ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.bundle) ADD_CUSTOM_COMMAND( TARGET jhexen POST_BUILD COMMAND rm -rf ${BUNDLE} COMMAND mkdir -p ${BUNDLE}/Contents/MacOS COMMAND cp libjhexen.dylib ${BUNDLE}/Contents/MacOS/${BUNDLE_BASE} COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/${BUNDLE_BASE}-Info.plist ${BUNDLE}/Contents/Info.plist COMMAND mkdir -p ${BUNDLE}/Contents/Resources #COMMAND mkdir -p ${BUNDLE}/Contents/Resources/English.lproj #COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/InfoPlist.strings ${BUNDLE}/Contents/Resources/English.lproj/ COMMAND echo 'APPL????' > ${BUNDLE}/Contents/PkgInfo COMMAND cp ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.pk3 ${BUNDLE}/Contents/Resources/ ) ENDIF (APPLE) deng-1.9.0-beta6.9+dfsg1/doomsday/CMakeLists.txt0000644000175000017500000010212111357170240017620 0ustar keeskees## Copyright (c) 2006 - 2008 Jamie Jones ## Copyright (c) 2007 - 2008 Daniel Swanson ## Copyright (c) 2008 - 2009 Jaakko Keränen ## ## This file is licensed under the GNU GPLv3 or any later versions, ## ## the deng build scripts is free software; you can redistribute it and/or ## modify it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 3 of the License, or ## (at your option) any later version. ## ## the deng build scripts 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 the deng build scripts; if not, write to the Free Software ## Foundation, Inc., 51 Franklin St, Fifth Floor, ## Boston, MA 02110-1301 USA ## ################################################################################ ## Supported Build Types are: ## * None (CMAKE_C_FLAGS) Cmake gcc default of $CFLAGS. ## * Debug (CMAKE_C_FLAGS_DEBUG) Cmake gcc default of "-g" ## * Release (CMAKE_C_FLAGS_RELEASE) Cmake gcc default of "-O3 -DNDEBUG" ## * RelWithDebInfo (CMAKE_C_FLAGS_RELWITHDEBINFO) Cmake default of "-O2 -g" ## * MinSizeRel (CMAKE_C_FLAGS_MINSIZEREL) Cmake default of "-Os -DNDEBUG" SET ( CMAKE_BUILD_TYPE Release CACHE STRING "Type of build." ) PROJECT(deng C CXX) CMAKE_MINIMUM_REQUIRED (VERSION 2.4.5 FATAL_ERROR) SET (BUILDSCRIPTSDATE "$LastChangedDate$") SET(deng_VERSION_MAJOR 1) SET(deng_VERSION_MINOR 9) SET(deng_VERSION_PATCH 0) SET(deng_VERSION_REVISION beta5) SET(deng_VERSION "${deng_VERSION_MAJOR}.${deng_VERSION_MINOR}.${deng_VERSION_PATCH}.${deng_VERSION_REVISION}") # where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/build/cmake") IF (APPLE) SET(CMAKE_OSX_DEPLOYMENT_TARGET 10.4) ENDIF () ################################################################################ ######################## Additional Win32 Path Setup ########################## IF (WIN32) ## Cmake NEEDS UNIX style paths ie / not \ ## We should really read these varibles from the path ## not hardcode them here SET(ENV{SDLDIR} "c:/sdk/sdl") SET(ENV{OPENALDIR} "c:/sdk/openal") SET(ENV{ZLIBDIR} "c:/sdk/zlib") SET(ENV{LIBPNGDIR} "c:/sdk/libpng") SET(ENV{DIRECTXDIR} "c:/sdk/dx8mgw") SET(ENV{LIBCURLDIR} "c:/sdk/libcurl") SET(ENV{EAXDIR} "c:/sdk/eax") ENDIF (WIN32) ################################################################################ ######################## Macros ############################################### MACRO(CREATE_MODULE_AT_ONCE_FILE _filename) FILE(WRITE ${_filename} "//autogenerated file\n") FOREACH (_current_FILE ${ARGN}) FILE(APPEND ${_filename} "#include \"${_current_FILE}\"\n") ENDFOREACH (_current_FILE) ENDMACRO(CREATE_MODULE_AT_ONCE_FILE _filename) ################################################################################ ######################## Configure Build Options ############################## SET(BUILD_SHARED_LIBS ON) OPTION (BUILDJDOOM "Optionally build the jDoom plugin. Default ON" ON) OPTION (BUILDJHERETIC "Optionally build the jHeretic plugin. Default ON" ON) OPTION (BUILDJHEXEN "Optionally build the jHexen plugin. Default ON" ON) OPTION (BUILDJDOOM64 "Optionally build the jDoom64 plugin. Default OFF" OFF) OPTION (BUILDWADMAPCONVERT "Optionally build the WAD Map Converter plugin. Default ON" ON) OPTION (BUILDOPENAL "Optionally build the OpenAL plugin. Default OFF" OFF) OPTION (BUILDDEDICATED "Build as a dedicated server. Default OFF" OFF) OPTION (BUILDDOX "Build doxygen documentation. Default OFF" OFF) OPTION (ENABLEMAO "Combine all source files in a module and build it at once. Default OFF" OFF) OPTION (ENABLENETDEBUG "Turn on internal network debugging features. Default OFF" OFF) OPTION (ENABLERANGECHECKING "Turn on internal range checking features. Default OFF" OFF) OPTION (ENABLEPROFILE "Turn on internal profiling features. Default OFF" OFF) OPTION (FINK "Build with FINK on OSX. Default OFF" OFF) MARK_AS_ADVANCED (BUILDJDOOM64) MARK_AS_ADVANCED (ENABLEMAO) MARK_AS_ADVANCED (ENABLENETDEBUG) MARK_AS_ADVANCED (ENABLEPROFILE) MARK_AS_ADVANCED (ENABLERANGECHECKING) MARK_AS_ADVANCED (FINK) IF (NOT APPLE AND FINK) MESSAGE( FATAL_ERROR "FINK build option is only available on OSX") ENDIF (NOT APPLE AND FINK) IF (${CMAKE_BINARY_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) MESSAGE( FATAL_ERROR "In-tree Builds are NOT supported. cd ${CMAKE_SOURCE_DIR}/build and try again") ENDIF (${CMAKE_BINARY_DIR} STREQUAL ${CMAKE_SOURCE_DIR}) ################################################################################ ######################## Doomsday Paths ####################################### ## Default Install Prefix on Win32 is C:/Program Files/deng ## Default Install Prefix on *NIX is /usr/local ## Default Install Prefix on OSX is FIXME ## This is set by Cmake automagically in CMAKE_INSTALL_PREFIX ## Default *NIX paths ## /usr/local/bin <- Doomsday binary ## /usr/local/lib <- libdropengl, libjdoom etc ## /usr/local/share/${PROJECT_NAME} <- jPacks and other data IF (UNIX) IF (NOT WIN32) IF (APPLE) SET (CMAKE_INSTALL_PREFIX .) SET (bindir ${CMAKE_INSTALL_PREFIX}/install) SET (libdir ${CMAKE_INSTALL_PREFIX}/install) SET (datadir ${CMAKE_INSTALL_PREFIX}/install) SET (mandir ${CMAKE_INSTALL_PREFIX}/install) ELSE (APPLE) ## Do an approximation of the autotools install options. Should make an ## easy transition for package maintainers (like me when I'm not hacking here) SET (bindir ${CMAKE_INSTALL_PREFIX}/bin CACHE PATH "install location for executables" ) SET (libdir ${CMAKE_INSTALL_PREFIX}/lib CACHE PATH "install location for libraries" ) SET (datadir ${CMAKE_INSTALL_PREFIX}/share/${PROJECT_NAME} CACHE PATH "install location for data files" ) SET (mandir ${CMAKE_INSTALL_PREFIX}/share/man CACHE PATH "install location for man files" ) ENDIF (APPLE) ENDIF (NOT WIN32) ENDIF (UNIX) IF (WIN32) ## FIXME. Correct locations here for WIN32 SET (bindir ${CMAKE_INSTALL_PREFIX}/bin CACHE PATH "install location for executables" ) SET (libdir ${CMAKE_INSTALL_PREFIX}/lib CACHE PATH "install location for libraries" ) SET (datadir ${CMAKE_INSTALL_PREFIX} CACHE PATH "install location for data files" ) ENDIF (WIN32) ## Where does it go on OSX ? FIXME ## Thess .pk3s is generated in the Generate.pk3 target. SET (DENG_ENGINE_DATA ${CMAKE_CURRENT_BINARY_DIR}/doomsday.pk3 ) SET (DENG_ENGINE_DATA_DIR ${datadir}/data) SET (DENG_JDOOM_DATA ${CMAKE_CURRENT_BINARY_DIR}/jdoom.pk3 ) SET (DENG_JDOOM_DATA_DIR ${DENG_ENGINE_DATA_DIR}/jdoom) SET (DENG_JHERETIC_DATA ${CMAKE_CURRENT_BINARY_DIR}/jheretic.pk3 ) SET (DENG_JHERETIC_DATA_DIR ${DENG_ENGINE_DATA_DIR}/jheretic) SET (DENG_JHEXEN_DATA ${CMAKE_CURRENT_BINARY_DIR}/jhexen.pk3 ) SET (DENG_JHEXEN_DATA_DIR ${DENG_ENGINE_DATA_DIR}/jhexen) SET (DENG_JDOOM64_DATA ${CMAKE_CURRENT_BINARY_DIR}/jdoom64.pk3 ) SET (DENG_JDOOM64_DATA_DIR ${DENG_ENGINE_DATA_DIR}/jdoom64) IF (UNIX) IF (NOT APPLE) IF (NOT WIN32) ADD_DEFINITIONS ('-DDENG_BASE_DIR="${datadir}/" ') ADD_DEFINITIONS ('-DDENG_LIBRARY_DIR="${libdir}/" ') ENDIF (NOT WIN32) ENDIF (NOT APPLE) ENDIF (UNIX) IF (APPLE) ADD_DEFINITIONS ('-DDENG_BASE_DIR="./" ') ADD_DEFINITIONS ('-DDENG_LIBRARY_DIR="./" ') ENDIF (APPLE) ################################################################################ ######################## Include Standard Cmake Helpers ####################### IF (NOT BUILDDEDICATED) FIND_PACKAGE(OpenGL REQUIRED) ENDIF (NOT BUILDDEDICATED) FIND_PACKAGE(SDL REQUIRED) ##INCLUDE (${CMAKE_ROOT}/Modules/FindSDL.cmake) IF (NOT BUILDDEDICATED) FIND_PACKAGE(SDL_mixer REQUIRED) ENDIF (NOT BUILDDEDICATED) FIND_PACKAGE(SDL_net REQUIRED) FIND_PACKAGE(ZLIB REQUIRED) FIND_PACKAGE(PNG REQUIRED) FIND_PACKAGE(CURL REQUIRED) FIND_PACKAGE(PythonInterp REQUIRED) IF (UNIX) FIND_PACKAGE(Curses REQUIRED) ENDIF (UNIX) IF (WIN32) FIND_PACKAGE(EAX REQUIRED) FIND_PACKAGE(DIRECTX_DIRECTSOUND REQUIRED) FIND_PACKAGE(DIRECTX_DIRECTINPUT REQUIRED) ENDIF (WIN32) IF (NOT BUILDDEDICATED) IF (UNIX) IF (NOT APPLE) FIND_PACKAGE(X11 REQUIRED) ENDIF (NOT APPLE) ENDIF (UNIX) IF (BUILDOPENAL) FIND_PACKAGE(OpenAL REQUIRED) ENDIF (BUILDOPENAL) ENDIF (NOT BUILDDEDICATED) IF (UNIX) IF (NOT WIN32) INCLUDE (${CMAKE_ROOT}/Modules/CheckIncludeFile.cmake) INCLUDE (${CMAKE_ROOT}/Modules/CheckLibraryExists.cmake) ENDIF (NOT WIN32) ENDIF (UNIX) FIND_PACKAGE(Doxygen) INCLUDE(TestBigEndian) ################################################################################ ######################## Cpack - Generate packages and source tarballs ######## SET(CMAKE_INSTALL_MFC_LIBRARIES 1) INCLUDE(${CMAKE_ROOT}/Modules/InstallRequiredSystemLibraries.cmake) SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "The Doomsday Engine: for jDoom, jHeretic, jHexen") SET(CPACK_PACKAGE_VENDOR "DaniJ, Skyjake, Yagisan") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/build/README") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/engine/doc/LICENSE") SET(CPACK_PACKAGE_VERSION_MAJOR "${deng_VERSION_MAJOR}") SET(CPACK_PACKAGE_VERSION_MINOR "${deng_VERSION_MINOR}") SET(CPACK_PACKAGE_VERSION_PATCH "${deng_VERSION_PATCH}.${deng_VERSION_REVISON}") SET(CPACK_PACKAGE_INSTALL_DIRECTORY "${CMAKE_INSTALL_PREFIX}") SET(CPACK_SOURCE_PACKAGE_FILE_NAME "deng-${deng_VERSION}") IF(NOT DEFINED CPACK_SYSTEM_NAME) SET(CPACK_SYSTEM_NAME ${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}) ENDIF(NOT DEFINED CPACK_SYSTEM_NAME) IF(${CPACK_SYSTEM_NAME} MATCHES Windows) IF(CMAKE_CL_64) SET(CPACK_SYSTEM_NAME win64-${CMAKE_SYSTEM_PROCESSOR}) ELSE(CMAKE_CL_64) SET(CPACK_SYSTEM_NAME win32-${CMAKE_SYSTEM_PROCESSOR}) ENDIF(CMAKE_CL_64) ENDIF(${CPACK_SYSTEM_NAME} MATCHES Windows) SET(CPACK_PACKAGE_FILE_NAME "${CPACK_SOURCE_PACKAGE_FILE_NAME}-${CPACK_SYSTEM_NAME}") IF(WIN32 AND NOT UNIX) # Win32 packaging setup (MSVC Built) # There is a bug in NSI that does not handle full unix paths properly. Make # sure there is at least one set of four (4) backlasshes. SET(CPACK_PACKAGE_EXECUTABLES "doomsday.exe") SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} - The Doomsday Engine: for jDoom, jHeretic, jHexen") SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.doomsdayhq.com") SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.doomsdayhq.com") SET(CPACK_NSIS_CONTACT "deng-devel@lists.sourceforge.net") SET(CPACK_NSIS_MODIFY_PATH ON) ELSE(WIN32 AND NOT UNIX) IF (APPLE) # OSX packaging setup ELSE (APPLE) # *Nix packaging setup (Inc Cygwin/MinGw) SET(CPACK_SOURCE_STRIP_FILES "") SET(CPACK_PACKAGE_EXECUTABLES "doomsday") ENDIF (APPLE) ENDIF(WIN32 AND NOT UNIX) INCLUDE(${CMAKE_ROOT}/Modules/CPack.cmake) ################################################################################ ######################## Set Common Definitions ############################### TEST_BIG_ENDIAN(ENDINESS) IF (ENDINESS STREQUAL "big endian") ADD_DEFINITIONS (-D__BIG_ENDIAN__) ENDIF (ENDINESS STREQUAL "big endian") IF (FINK) ADD_DEFINITIONS (-DFINK) # #fink has advised that this may be needed to fix linking errors on OSX # ADD_DEFINITIONS (-D__DARWIN_UNIX03) ENDIF (FINK) IF (NOT ENABLERANGECHECKING) ADD_DEFINITIONS (-DNORANGECHECKING) ENDIF (NOT ENABLERANGECHECKING) IF (CMAKE_BUILD_TYPE STREQUAL Debug) ADD_DEFINITIONS (-D_DEBUG ) ENDIF (CMAKE_BUILD_TYPE STREQUAL Debug) IF (ENABLENETDEBUG) ADD_DEFINITIONS (-D_NETDEBUG ) ENDIF (ENABLENETDEBUG) IF (ENABLEPROFILE) ADD_DEFINITIONS (-DDD_PROFILE ) ENDIF (ENABLEPROFILE) IF (APPLE) ADD_DEFINITIONS (-DNO_FIXED_ASM ) SET (BUILDFIXEDASM OFF) ELSE (APPLE) IF (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) IF (CMAKE_SYSTEM_PROCESSOR MATCHES "i.86" OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86") ADD_DEFINITIONS (-DGNU_X86_FIXED_ASM ) SET (BUILDFIXEDASM ON) ELSE (CMAKE_SYSTEM_PROCESSOR MATCHES "i.86" OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86") ADD_DEFINITIONS (-DNO_FIXED_ASM ) SET (BUILDFIXEDASM OFF) ENDIF (CMAKE_SYSTEM_PROCESSOR MATCHES "i.86" OR CMAKE_SYSTEM_PROCESSOR MATCHES "x86") ELSE (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) ADD_DEFINITIONS (-DNO_FIXED_ASM ) SET (BUILDFIXEDASM OFF) ENDIF (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) ENDIF (APPLE) ## Apple also needs -DUNIX in places IF (UNIX) IF (NOT WIN32) ADD_DEFINITIONS ( -DUNIX) SET (BUILDSYSTEM UNIX) ENDIF (NOT WIN32) ENDIF (UNIX) ## Are we on Solaris ? IF(CMAKE_SYSTEM MATCHES "SunOS-*") ADD_DEFINITIONS ( -DSOLARIS) ENDIF(CMAKE_SYSTEM MATCHES "SunOS-*") IF (WIN32) ADD_DEFINITIONS ( -DWIN32 -D_USRDLL -D_WINDLL -D_WINDOWS ) SET (BUILDSYSTEM WIN32) IF (MSVC) ADD_DEFINITIONS ( -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE) SET (BUILDSYSTEM WIN32-MSVC) ENDIF (MSVC) IF (MINGW) ADD_DEFINITIONS ( -DUNICODE) SET (BUILDSYSTEM WIN32-MINGW) ENDIF (MINGW) ENDIF (WIN32) IF (APPLE) ADD_DEFINITIONS ( -DMACOSX ) ##SET (CMAKE_OSX_ARCHITECTURES ppc;i386) ##SET (CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX10.4u.sdk) ##SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mmacosx-version-min=10.4" ) ##SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mmacosx-version-min=10.4" ) SET (BUILDSYSTEM MACOSX) ## Add needed Compiler and Linker flags for OSX IF (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) SET (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flat_namespace" ) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flat_namespace -undefined suppress" ) SET (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${PNG_LIBRARY_STATIC} -flat_namespace -undefined suppress" ) SET (CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -flat_namespace -undefined suppress" ) SET (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -flat_namespace -undefined suppress" ) SET (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -flat_namespace -undefined suppress" ) SET (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -flat_namespace -undefined suppress" ) SET (CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${PNG_LIBRARY_STATIC} -flat_namespace -undefined suppress" ) SET (CMAKE_MODULE_LINKER_FLAGS_DEBUG "${CMAKE_MODULE_LINKER_FLAGS_DEBUG} -flat_namespace -undefined suppress" ) SET (CMAKE_SHARED_LINKER_FLAGS_DEBUG "${CMAKE_SHARED_LINKER_FLAGS_DEBUG} -flat_namespace -undefined suppress" ) SET (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flat_namespace -undefined suppress" ) SET (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flat_namespace -undefined suppress" ) SET (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${PNG_LIBRARY_STATIC} -flat_namespace -undefined suppress" ) SET (CMAKE_MODULE_LINKER_FLAGS_RELEASE "${CMAKE_MODULE_LINKER_FLAGS_RELEASE} -flat_namespace -undefined suppress" ) SET (CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -flat_namespace -undefined suppress" ) SET (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -flat_namespace -undefined suppress" ) SET (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -flat_namespace -undefined suppress" ) SET (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} ${PNG_LIBRARY_STATIC} -flat_namespace -undefined suppress" ) SET (CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} -flat_namespace -undefined suppress" ) SET (CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} -flat_namespace -undefined suppress" ) SET (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} -flat_namespace -undefined suppress" ) SET (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} -flat_namespace -undefined suppress" ) SET (CMAKE_EXE_LINKER_FLAGS_MINSIZEREL "${CMAKE_EXE_LINKER_FLAGS_MINSIZEREL} ${PNG_LIBRARY_STATIC} -flat_namespace -undefined suppress" ) SET (CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL "${CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL} -flat_namespace -undefined suppress" ) SET (CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL "${CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL} -flat_namespace -undefined suppress" ) ENDIF (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) ENDIF (APPLE) ################################################################################ ######################## Find Our Build Deps ################################## ## Confirm we have OpenGL IF (OPENGL_FOUND STREQUAL "NO") MESSAGE (FATAL_ERROR "** libGL not found. On Ubuntu install libgl1-mesa-dev. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF (OPENGL_FOUND STREQUAL "NO") ## Confirm we have GLU IF (OPENGL_GLU_FOUND STREQUAL "NO") MESSAGE (FATAL_ERROR "** libGLU not found. On Ubuntu install libglu1-mesa-dev. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF (OPENGL_GLU_FOUND STREQUAL "NO") INCLUDE_DIRECTORIES (${OPENGL_INCLUDE_DIR}) ## Confirm we have SDL IF (SDL_FOUND STREQUAL "NO") MESSAGE (FATAL_ERROR "** SDL not found. On Ubuntu install libsdl1.2-dev. On Mac OSX install FIXME. On Windows/MSVC install SDL-devel-1.2.11-VC6.zip.") ENDIF (SDL_FOUND STREQUAL "NO") INCLUDE_DIRECTORIES (${SDL_INCLUDE_DIR}) ## Confirm we have SDL_mixer IF (SDLMIXER_FOUND STREQUAL "NO") MESSAGE (FATAL_ERROR "** SDL Mixer not found. On Ubuntu install libsdl-mixer1.2-dev. On Mac OSX install FIXME. On Windows/MSVC install SDL_mixer-devel-1.2.7-VC6.zip.") ENDIF (SDLMIXER_FOUND STREQUAL "NO") INCLUDE_DIRECTORIES (${SDLMIXER_INCLUDE_DIR}) ## Confirm we have SDL_net IF (SDLNET_FOUND STREQUAL "NO") MESSAGE (FATAL_ERROR "** SDL Net not found. On Ubuntu install libsdl-net1.2-dev. On Mac OSX install FIXME. On Windows/MSVC install SDL_net-devel-1.2.6-VC6.zip.") ENDIF (SDLNET_FOUND STREQUAL "NO") INCLUDE_DIRECTORIES (${SDLNET_INCLUDE_DIR}) ## Confirm we have zlib IF (NOT ZLIB_FOUND) MESSAGE (FATAL_ERROR "** zlib not found. On Ubuntu install zlib1g-dev. On Mac OSX install FIXME. On Windows install zlib123-dll.zip.") ENDIF (NOT ZLIB_FOUND) INCLUDE_DIRECTORIES (${ZLIB_INCLUDE_DIR}) ## confirm we have libPNG. IF (NOT PNG_FOUND) MESSAGE (FATAL_ERROR "** libpng not found. On Ubuntu install libpng-dev. On Mac OSX install FIXME. On Windows install libpng-1.2.8-lib.zip.") ENDIF (NOT PNG_FOUND) INCLUDE_DIRECTORIES (${PNG_INCLUDE_DIR}) ## confirm we have libcurl. IF (NOT CURL_FOUND) MESSAGE (FATAL_ERROR "** libcurl not found. On Ubuntu install libcurl3-gnutls-dev. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF (NOT CURL_FOUND) INCLUDE_DIRECTORIES (${CURL_INCLUDE_DIR}) ## Confirm we have ncurses IF (UNIX) IF (NOT CURSES_LIBRARIES) MESSAGE (FATAL_ERROR "** ncurses not found. On Ubuntu install libncurses5-dev. On Mac OSX install FIXME.") ENDIF (NOT CURSES_LIBRARIES) INCLUDE_DIRECTORIES (${CURSES_INCLUDE_DIR}) ENDIF (UNIX) ## Confirm we have X11 IF (UNIX) IF (NOT APPLE) IF (NOT X11_FOUND) MESSAGE (FATAL_ERROR "** X11 not found. On Ubuntu install libx11-dev, libxext-dev.") ENDIF (NOT X11_FOUND) INCLUDE_DIRECTORIES (${X11_INCLUDE_DIR}) ENDIF (NOT APPLE) ENDIF (UNIX) ## Confirm we have DirectX DirectInput IF (WIN32) IF (NOT DIRECTX_DIRECTINPUT_FOUND) MESSAGE (FATAL_ERROR "** DirectX Direct Input not found. On Windows install dx9sdk.exe.") ENDIF (NOT DIRECTX_DIRECTINPUT_FOUND) INCLUDE_DIRECTORIES (${DIRECTX_DIRECTINPUT_INCLUDE_DIRS}) ## Confirm we have DirectX DirectSound IF (NOT DIRECTX_DIRECTSOUND_FOUND) MESSAGE (FATAL_ERROR "** DirectX Direct Sound not found. On Windows install dx9sdk.exe.") ENDIF (NOT DIRECTX_DIRECTSOUND_FOUND) INCLUDE_DIRECTORIES (${DIRECTX_DIRECTSOUND_INCLUDE_DIRS}) ## Confirm we have EAX IF (NOT EAX_FOUND) MESSAGE (FATAL_ERROR "** Creative EAX not found. On Windows instal FIXME") ENDIF (NOT EAX_FOUND) INCLUDE_DIRECTORIES (${EAX_INCLUDE_DIRS}) ENDIF (WIN32) IF (BUILDOPENAL) ## Confirm we have OpenAL IF (NOT OPENAL_FOUND STREQUAL "YES") MESSAGE (FATAL_ERROR "** Openal not found. On Ubuntu install libopenal-dev. On Mac OSX install FIXME. On Windows install OpenAL11CoreSDK.exe.") ENDIF (NOT OPENAL_FOUND STREQUAL "YES") INCLUDE_DIRECTORIES (${OPENAL_INCLUDE_DIR}) ENDIF (BUILDOPENAL) IF (UNIX) IF (NOT WIN32) ## Confirm we have dlopen CHECK_INCLUDE_FILE("dlfcn.h" HAVE_DL) IF(HAVE_DL) CHECK_LIBRARY_EXISTS("dl" "dlopen" "" HAVE_LIB_DL) IF(NOT HAVE_LIB_DL) MESSAGE (FATAL_ERROR "** dlopen not found. On Ubuntu install libc6-dev. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF(NOT HAVE_LIB_DL) ELSE(HAVE_DL) MESSAGE (FATAL_ERROR "** dlopen not found. On Ubuntu install libc6-dev. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF(HAVE_DL) ENDIF (NOT WIN32) ENDIF (UNIX) ## confirm we have Python IF (NOT PYTHONINTERP_FOUND) MESSAGE (FATAL_ERROR "** Python not found. On Ubuntu install python. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF (NOT PYTHONINTERP_FOUND) ## confirm we have Doxygen. IF (NOT DOXYGEN) MESSAGE (STATUS "** Doxygen not found. On Ubuntu install doxygen. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF (NOT DOXYGEN) ## confirm we have Graphviz. IF (NOT DOT) MESSAGE (STATUS "** Graphviz not found. On Ubuntu install graphviz. On Mac OSX install FIXME. On Windows install FIXME.") ENDIF (NOT DOT) ################################################################################ ######################## External LZSS Files ################################### IF (UNIX) INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/external/lzss/portable/include ) FILE (GLOB LZSS_SOURCES ${CMAKE_SOURCE_DIR}/external/lzss/unix/src/*.c ) ENDIF (UNIX) IF (WIN32 AND NOT UNIX) INCLUDE_DIRECTORIES ( ${CMAKE_SOURCE_DIR}/external/lzss/win32/include ) FILE (GLOB LZSS_SOURCES ${CMAKE_SOURCE_DIR}/external/lzss/win32/src/*.c ) ENDIF (WIN32 AND NOT UNIX) ################################################################################ ######################## The Doomsday Engine ################################## ADD_DEFINITIONS (-D__DOOMSDAY__ ) INCLUDE_DIRECTORIES (${CMAKE_SOURCE_DIR}/engine/api ${CMAKE_SOURCE_DIR}/engine/portable/include ) FILE (GLOB DENG_PORTABLE_SOURCES ${CMAKE_SOURCE_DIR}/engine/portable/src/*.c ) SET ( DENG_PORTABLE_SOURCES ${DENG_PORTABLE_SOURCES} ${CMAKE_SOURCE_DIR}/plugins/common/src/m_fixed.c ) IF (UNIX) IF (NOT WIN32) INCLUDE_DIRECTORIES (${CMAKE_SOURCE_DIR}/engine/unix/include ) FILE (GLOB DENG_ARCH_SPECIFIC_SOURCES ${CMAKE_SOURCE_DIR}/engine/unix/src/*.c ) SET (DENG_ARCH_SPECIFIC_SOURCES ${DENG_ARCH_SPECIFIC_SOURCES} ${LZSS_SOURCES}) #IF (NOT APPLE) # SET (DENG_ARCH_SPECIFIC_SOURCES ${DENG_ARCH_SPECIFIC_SOURCES} # ${CMAKE_SOURCE_DIR}/engine/unix/src/sys_window.c) #ENDIF (NOT APPLE) ENDIF (NOT WIN32) ENDIF (UNIX) IF (WIN32) INCLUDE_DIRECTORIES (${CMAKE_SOURCE_DIR}/engine/win32/include ) SET (DENG_ARCH_SPECIFIC_SOURCES ${CMAKE_SOURCE_DIR}/engine/win32/src/dd_winit.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_cdaudio.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_console.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_findfile.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_input.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_mixer.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_musd_win.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_sfxd_ds.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_sfxd_loader.c ${CMAKE_SOURCE_DIR}/engine/win32/src/sys_window.c ${LZSS_SOURCES}) ENDIF (WIN32) ## .m is Obj-C IF (APPLE) INCLUDE_DIRECTORIES (${CMAKE_SOURCE_DIR}/engine/mac/include ) FILE (GLOB DENG_OSX_SOURCES ${CMAKE_SOURCE_DIR}/engine/mac/src/*.m ${CMAKE_SOURCE_DIR}/engine/mac/src/*.c ) SET (DENG_ARCH_SPECIFIC_SOURCES ${DENG_ARCH_SPECIFIC_SOURCES} ${DENG_OSX_SOURCES}) ENDIF (APPLE) IF (COMMAND cmake_policy) cmake_policy(SET CMP0003 NEW) ENDIF (COMMAND cmake_policy) ADD_EXECUTABLE (doomsday ${DENG_PORTABLE_SOURCES} ${DENG_ARCH_SPECIFIC_SOURCES}) TARGET_LINK_LIBRARIES (doomsday ${SDL_LIBRARY} ${SDLMIXER_LIBRARY} ${SDLNET_LIBRARY} ${ZLIB_LIBRARIES} ${CURSES_LIBRARIES} ${PNG_LIBRARIES} ${CURL_LIBRARIES} ${OPENGL_LIBRARIES}) IF (UNIX) IF (NOT WIN32) TARGET_LINK_LIBRARIES (doomsday dl) IF (NOT APPLE) TARGET_LINK_LIBRARIES (doomsday ${X11_LIBRARIES}) ENDIF (NOT APPLE) ENDIF (NOT WIN32) ENDIF (UNIX) IF (WIN32) TARGET_LINK_LIBRARIES (doomsday wsock32 winmm gdi32 ole32 user32 ${EAX_LIBRARIES} ${DIRECTX_DIRECTSOUND_LIBRARIES} ${DIRECTX_DIRECTINPUT_LIBRARIES} ) ENDIF (WIN32) ## Work around for Win32 wanting something for the plugins to link to #IF (WIN32) # ADD_LIBRARY (deng STATIC ${DENG_SOURCES} engine/api/doomsday.def) # TARGET_LINK_LIBRARIES (deng ${SDL_LIBRARY} ${SDLNET_LIBRARY} ${ZLIB_LIBRARIES} ${CURSES_LIBRARIES} ${PNG_LIBRARIES} wsock32 winmm gdi32 ole32 user32 # ${CMAKE_SOURCE_DIR}/external/lzss/win32/lzss ) #ENDIF (WIN32) ################################################################################ ######################## Dehacked Reader Plugin ############################### ADD_SUBDIRECTORY (${CMAKE_SOURCE_DIR}/plugins/dehread ) ################################################################################ ######################## WAD Map Converter Plugin ############################# IF (BUILDWADMAPCONVERT) ADD_SUBDIRECTORY (${CMAKE_SOURCE_DIR}/plugins/wadmapconverter ) ENDIF (BUILDWADMAPCONVERT) ################################################################################ ######################## OpenAL Output Plugin ################################# IF (BUILDOPENAL) ADD_SUBDIRECTORY (${CMAKE_SOURCE_DIR}/plugins/openal ) ENDIF (BUILDOPENAL) ################################################################################ ######################## jDoom Game Plugin #################################### IF (BUILDJDOOM) ADD_SUBDIRECTORY (${CMAKE_SOURCE_DIR}/plugins/jdoom ) ENDIF (BUILDJDOOM) ################################################################################ ######################## jHeretic Game Plugin ################################# IF (BUILDJHERETIC) ADD_SUBDIRECTORY (${CMAKE_SOURCE_DIR}/plugins/jheretic ) ENDIF (BUILDJHERETIC) ################################################################################ ######################## jHexen Game Plugin ################################### IF (BUILDJHEXEN) ADD_SUBDIRECTORY (${CMAKE_SOURCE_DIR}/plugins/jhexen ) ENDIF (BUILDJHEXEN) ################################################################################ ######################## jDoom64 Game Plugin ################################# IF (BUILDJDOOM64) ADD_SUBDIRECTORY (${CMAKE_SOURCE_DIR}/plugins/jdoom64 ) ENDIF (BUILDJDOOM64) ################################################################################ ######################## Doxygenate All Source ################################ ## This target mixes all the documentation together. It's sometimes useful, ## but the 3 seperate functionaliy targets are better in most cases. ## In other words, don't build this, if you build the 3 other Doxygenate targets IF (BUILDDOX) IF (DOXYGEN) IF (DOT) ADD_CUSTOM_TARGET (Doxygenate.all ALL doxygen WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) ENDIF (DOT) ENDIF (DOXYGEN) ENDIF (BUILDDOX) ################################################################################ ######################## Generate pk3s ########################################## ADD_CUSTOM_TARGET (Generate.pk3 ALL ${PYTHON_EXECUTABLE} ./packres.py ${CMAKE_CURRENT_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/build/scripts/ ) ################################################################################ ######################## Show Build Details ################################### MESSAGE( STATUS "BUILDSCRIPTSDATE: " ${BUILDSCRIPTSDATE} ) MESSAGE( STATUS "CMAKE_SYSTEM: " ${CMAKE_SYSTEM} ) MESSAGE( STATUS "CMAKE_SYSTEM_PROCESSOR: " ${CMAKE_SYSTEM_PROCESSOR} ) MESSAGE( STATUS "CMAKE_BUILD_TYPE: " ${CMAKE_BUILD_TYPE} ) IF (CMAKE_BUILD_TYPE STREQUAL "") MESSAGE( STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS} ) ENDIF (CMAKE_BUILD_TYPE STREQUAL "") IF (CMAKE_BUILD_TYPE STREQUAL Debug) MESSAGE( STATUS "CMAKE_C_FLAGS_DEBUG: " ${CMAKE_C_FLAGS_DEBUG} ) ENDIF (CMAKE_BUILD_TYPE STREQUAL Debug) IF (CMAKE_BUILD_TYPE STREQUAL Release) MESSAGE( STATUS "CMAKE_C_FLAGS_RELEASE: " ${CMAKE_C_FLAGS_RELEASE} ) ENDIF (CMAKE_BUILD_TYPE STREQUAL Release) IF (CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo) MESSAGE( STATUS "CMAKE_C_FLAGS_RELWITHDEBINFO: " ${CMAKE_C_FLAGS_RELWITHDEBINFO} ) ENDIF (CMAKE_BUILD_TYPE STREQUAL RelWithDebInfo) IF (CMAKE_BUILD_TYPE STREQUAL MinSizeRel) MESSAGE( STATUS "CMAKE_C_FLAGS_MINSIZEREL: " ${CMAKE_C_FLAGS_MINSIZEREL} ) ENDIF (CMAKE_BUILD_TYPE STREQUAL MinSizeRel) MESSAGE( STATUS "CMAKE_C_COMPILER: " ${CMAKE_C_COMPILER} ) MESSAGE( STATUS "CMAKE_SOURCE_DIR: " ${CMAKE_SOURCE_DIR} ) MESSAGE( STATUS "CMAKE_BINARY_DIR: " ${CMAKE_BINARY_DIR} ) MESSAGE( STATUS "BUILDJDOOM: " ${BUILDJDOOM} ) MESSAGE( STATUS "BUILDJHERETIC: " ${BUILDJHERETIC} ) MESSAGE( STATUS "BUILDJHEXEN: " ${BUILDJHEXEN} ) MESSAGE( STATUS "BUILDJDOOM64: " ${BUILDJDOOM64} ) MESSAGE( STATUS "BUILDWADMAPCONVERT: " ${BUILDWADMAPCONVERT} ) MESSAGE( STATUS "BUILDOPENAL: " ${BUILDOPENAL} ) MESSAGE( STATUS "BUILDDEDICATED: " ${BUILDDEDICATED} ) MESSAGE( STATUS "BUILDDOX: " ${BUILDDOX} ) MESSAGE( STATUS "BUILDFIXEDASM: " ${BUILDFIXEDASM} ) MESSAGE( STATUS "BUILDSYSTEM: " ${BUILDSYSTEM} ) MESSAGE( STATUS "CMAKE_INSTALL_PREFIX " ${CMAKE_INSTALL_PREFIX} ) MESSAGE( STATUS "DENG_BASE_DIR " ${datadir} ) MESSAGE( STATUS "DENG_LIBRARY_DIR " ${libdir} ) MESSAGE( STATUS "DENG_BINARY_DIR " ${bindir} ) MESSAGE( STATUS "DENG_ENGINE_DATA_DIR " ${DENG_ENGINE_DATA_DIR} ) MESSAGE( STATUS "DENG_JDOOM_DATA_DIR " ${DENG_JDOOM_DATA_DIR} ) MESSAGE( STATUS "DENG_JHERETIC_DATA_DIR " ${DENG_JHERETIC_DATA_DIR} ) MESSAGE( STATUS "DENG_JHEXEN_DATA_DIR " ${DENG_JHEXEN_DATA_DIR} ) MESSAGE( STATUS "DENG_JDOOM64_DATA_DIR " ${DENG_JDOOM64_DATA_DIR} ) ################################################################################ ######################## Install Targets ###################################### INSTALL(TARGETS doomsday RUNTIME DESTINATION ${bindir} LIBRARY DESTINATION ${libdir} ) INSTALL(FILES ${DENG_ENGINE_DATA} DESTINATION ${DENG_ENGINE_DATA_DIR} ) IF (APPLE) # Bundling. SET (BUNDLE_BASE Doomsday) SET (BUNDLE ${CMAKE_BINARY_DIR}/${BUNDLE_BASE}.app) ADD_CUSTOM_COMMAND( TARGET doomsday POST_BUILD COMMAND rm -rf ${BUNDLE} COMMAND mkdir -p ${BUNDLE}/Contents/MacOS COMMAND cp doomsday ${BUNDLE}/Contents/MacOS/${BUNDLE_BASE} COMMAND cp ${CMAKE_SOURCE_DIR}/build/mac/Info.plist ${BUNDLE}/Contents/Info.plist COMMAND echo 'APPL????' > ${BUNDLE}/Contents/PkgInfo COMMAND mkdir -p ${BUNDLE}/Contents/Resources/English.lproj COMMAND cp -r ${CMAKE_SOURCE_DIR}/engine/mac/res/English.lproj ${BUNDLE}/Contents/Resources COMMAND cp ${CMAKE_SOURCE_DIR}/engine/mac/res/deng.icns ${BUNDLE}/Contents/Resources/ COMMAND cp -r ${CMAKE_SOURCE_DIR}/engine/mac/res/Startup.nib ${BUNDLE}/Contents/Resources/ # Copy frameworks. COMMAND mkdir -p ${BUNDLE}/Contents/Frameworks COMMAND cp -R $ENV{HOME}/Library/Frameworks/{SDL,SDL_mixer,SDL_net}.framework ${BUNDLE}/Contents/Frameworks # Copy PK3s. COMMAND cp doomsday.pk3 ${BUNDLE}/Contents/Resources/ COMMAND mkdir -p ${BUNDLE}/Contents/Resources/Data/ COMMAND mkdir -p ${BUNDLE}/Contents/Resources/Data/Graphics/ COMMAND cp ${CMAKE_SOURCE_DIR}/engine/data/graphics/loading{1,2}.png ${BUNDLE}/Contents/Resources/Data/Graphics/ ) ENDIF (APPLE) IF (BUILDJDOOM) INSTALL(FILES ${DENG_JDOOM_DATA} DESTINATION ${DENG_JDOOM_DATA_DIR} ) ENDIF (BUILDJDOOM) IF (BUILDJHERETIC) INSTALL(FILES ${DENG_JHERETIC_DATA} DESTINATION ${DENG_JHERETIC_DATA_DIR} ) ENDIF (BUILDJHERETIC) IF (BUILDJHEXEN) INSTALL(FILES ${DENG_JHEXEN_DATA} DESTINATION ${DENG_JHEXEN_DATA_DIR} ) ENDIF (BUILDJHEXEN) IF (BUILDJDOOM64) INSTALL(FILES ${DENG_JDOOM64_DATA} DESTINATION ${DENG_JDOOM64_DATA_DIR} ) ENDIF (BUILDJDOOM64) deng-1.9.0-beta6.9+dfsg1/COMPILING0000644000175000017500000000402411357170240014510 0ustar keeskeesCOMPILING DOOMSDAY AND THE LIBRARIES ==================================== This document describes the recommended way for building Doomsday and the libraries on any system. REQUIREMENTS: ------------- You will need these tools and libraries for building everything: - Cmake 2.4 or latter ( http://www.cmake.org/HTML/Download.html ) - A C Compiler (GCC on *NIX, OSX. Cygwin, MingGW, Borland or Visual C on Windows) - GNU Make on *NIX, Cygwin or MinGW - ncurses on *NIX, OSX - OpenGL (This can be disabled in cmake for a dedicated build) - GLU (This can be disabled in cmake for a dedicated build) - SDL (http://www.libsdl.org/) - SDL_net - SDL_mixer (This can be disabled in cmake for a dedicated build) - OpenAL (This can be disabled in cmake for a dedicated build) - zip (to create Doomsday.pk3) ( http://www.info-zip.org/ ) IF YOU HAVE A SOURCE TARBALL: ----------------------------- 1. Unpack the source tarball, if you haven't already done so. 2. Create your build directory. It can be located anywhere, for example under the doomsday directory in the source tree. For instance: $ mkdir deng-1.9.0/doomsday/mybuild $ cd deng-1.9.0/doomsday/mybuild 3. Run CMake. For example: $ cmake .. 4. If cmake failed due to missing libraries, install the required ones. Make sure you have the development files for each. 5. Compile everything: $ make 6. On *NIX run "su -c 'make install'" or "sudo 'make install'" depending on you *NIX distribution. This will install the executable (doomsday), the libraries (games, renderer, sound), data files and definitions files under the directory specified by the configured prefix. 7. See the main README for tips on running the game. IF YOU USE SVN: --------------- 1. Check out a copy of the project files from the SourceForge SVN. You will only need the "doomsday" module. You can find instructions on how to accomplish this here: http://sourceforge.net/svn/?group_id=74815 2. Proceed to compiling as with a source tarball (from step 2).

E@/pDHJJ?O!|rSH 7`]S޼~ Za>ts 7&@Ôh!Qi1d崐$^Ж.Q@ŪqdH )!q& E>T?L +hY`V0eM=H $]tDE^F&xe 7sؽ=zϜJD0sX&j+5]:Eɬ$Pj\(ȈYY ЎA`"43"Wv9v5CF}OW;Mt.\6qvK#Fe_WZ(CMoшGɔ×e-q4V yy=jV悓$#C{|(Byx,7=y$0 DB'Tu"- ^tW[UagF#̑WF!'ҭs{<$^,N.+2 TF`9ÂUƜGLp 9$k1F`UvM/P46?%BU[[B;u-D\ϙ3.&0;3D&,MJZSiMЩ"?VdWdDžQ9iE*d1 s郔$iP,cJ?/PYNLCkӓtegQWM ٌ GF+*΂r2^`i PY,9@YUп.d_z[<W1o/[k{7w4gVݟ C / F>2>:n7k+-~OCc[+`ml<<84Rc+_8dG?~{wK$L/G\A=3PKu0r+cp^OϮZ 'nƐb"IT,ݎN&1UJ>FؤN!_>ù%ҙS2 ?JT MhwXHJIh6m]򪥵7$ZvxP:1 O_a( il4/ ?..>OE:$.nQꮃ`EmwmI|''̼>ސ|w:,tc}ԜAЭå ,@bU@k4o2'U# A(`zvQ,[pAHgZcYsYɀJh"r9¢mqg{v>ig/Kp|f9:e9jgM @^N6" zL&炔NL\ Y>EZ{޻bWoxܴTK:KwަEx!lPDZT`o#U!]QyP ް~={8H&;4i40C Т2؞-+Bn: H{D ),Ҕt.(+,@f ?лf@ Xxbڱ{nf"kom:mRhgU@;= 1l ~,?X 4l׵2OlO2Ƽ?7E70AƩ *t<8Н߽5@M>Q$:?-Hl~<+= I + He, !gA*0x.SHE ^Z X Kd`Fh/ XÂ7\qIi!U2d42= q?d/ _Bf4Jd Yh'㭻Ք$dexۚ$+- o>yTkms )`$w󀾾YX|~Fr%j`j&/׊b}oز[m|u 0y 0*#'-XAf@_7_ʒ,9?whC_zw!ˀQ/CKsBo*K+T Gn l_> It+2-d !590ԡk.1b nE h2.y%?kv!#@A? HFb G t.uo\BNb PK B3aw!CR?#ti-,`!g{j~`r-;h7ZC3CtȘhE8ND@瀆Rꪊ<ܜXcHKAV=}'Hka>avdR {ؠngݽ4bBt dEU^`|Lswu4K?`\P4 PjBNc 8'h2 \+΢$ Κ*c1;~< 7qP7ww^6] 6ӈ.ݥPhZ{̇aNZm]n3CCґ.`x,n.OYhsuA :ԷYZѬzay}:tv(*e\6@&[NAx^Zۭ a7y<rd:iz *u|rȯWg \5S]0:*X9f``B`\\m4xc>л+lv(\lZC IܱaܸmL1+c ?=QY6ni眞3i0WnU@c+JyCPqe7*f-j:7QEP:$C$ RfUT{bg L4{C몜o'#/{SL4d,< x}/DZh}ppnѽm"§C-KgХ^}y@f&ROyǧgv>{]{߬??VK;~?CuYkĐF5]Ood$eܗwCNVٮdݬ]B8/Ћq#Nˆ Mv|Ypej`|V8bmS%Eī x^RR|)A xUѧ,Ҭf794n2?ߔM&?5Ž!+}T0&N ?MBdǯ 9y"eA?$)wZ5&FtGZ-Z5J" `q&ߵVZ0ӹ}>`p83ӞχAwNnj{'ֱ0*YOxVӄ֦Xao-ΨF3~3sN,x[(E[Z͉M@[`?#z|nw̏|+h>X`)&{3`{Wp C  Ǜxpr3Xs`( Ht xA Hp>7@ea(!G(((_q)BEP*>PT"AkRJuѤqMM!yg2s$^,y\;F'䷢rCv= M@S%~Cyu W?* kɆdHГl2 7T bx ,1&, <0Hh@)#sC.˥ۺmnƊsYWzu_bER]Vɻ<ͭe: C]h)g=w [LK(jߛиϯڥ_oI*W}w(6Ώ\Х:Ϟ뿱z0;91@|xRզ`pa,3RHr !I)Hvhc=8P3$A +XaWCOK RxCj=hJ¬Z ?!w fA=ˏ^AnA_?\J a@ : nM 6C0?? \ Ak cP@z@}'Nl90 炄 P*Q:B2 AS,,%3!e AA].gH$h&膧?tlrg@>x^V^!yܸyw!t#l С-Ug+3AsAR-tƊzعeQ\2A80C`u|!|BCeki B@U>" h"hv`#_]Ge}yvvD3 k2$E\ӍNWd`\;fFPaD 5x~ErES oGم?c ~JJ w(-8S;jI0H#(O]Z/{vqufo@).ގ5.|ӿ₉Xs;({@ I*_ ֶJ-Prs}fnI G[ki?<>f .pi"MXJ@*0TI)[ w5*IwXAoˆ1\\]BW^1 & A(hiDQDt$_H gvVn1۝ٝiv">v4J1!4{FgQCP@Z9O Np٘"3uA쎪.)~ȠEY@FmFSKH=l(xެjndH/0ǣ[vc돂ۮ控\^il>LQ![FCA$ךX8(m>{ n붴q\{yP M =;$>hҐ_X1&ؑ{h'p,`B+>lgٷPuX0 u:L܁_HheQƎb˖,݉41Jš*jzʼX81+{@VBϼ Z "܄RA9:o˹EвVި;&r r :C&@fIJAm<*"ݞjaY޻Hǩ@,X'91IfS+.#> IUJ>+i]{[74mZ?!+['g濫ˇyY$(ȯb|p)" 51w 0 0!vi9=WU@bޟ7 \W]L"+un:zqsH!hYd|H/dK!E+BŸ UҔjED,:qNSxxX_ QqAiu~*a̝y\ؔrنRl4R\u*wp\{[U 6Pvɮq,S/yTRE8'J1BNTBL5hn\J| , M h0%&2'~SFg^n!fzxGMײh}UXj1.weNd9L0P|7БM06XP8۽ϑpc([Nh{Gd ,gdX»xaEFzaG&2?I)=Z4ibaf o{hI&ΰ,@ N<]^_+!dG$R.^+¬񚻵Q&z!- ' VE)U F%eC1zh+p$: =*e 'Gg QfBN@ԾhF"0u 5 /;pTGkr_ L)@}s(撈nۗt`_ˣH"*n ra't;0%! O2Ƭvh Lӱs}|ەd ' 6&nǒ}=(¿Be¾PMOs7sJRR1#A,(֘7%SA@`a 5 8DQ#ď_z$_tRf1∂-D)oVcU0Fp|MG8(J 7AƦbK5IN'fI"jm醋䏊;Ww團+ӹV9c$Fr3؂t(iC^T. M7s'S.?yV[4AxsAb(DXw{:O0Li(9O/ٷ"U0`5Ҥ2i5=H:Je2LrLƆ"?I*uy!>&}H`Dg4T*P&KjlF\3@(ˮ 7m+p\g< Q6qm;qCы|vKX'\E|Iq9-H3z,Ak>N8nhI*cYnޢsz[okՌwCajfYſl?b)Hl`%, *Gk5-y TTv. xo0u:0mJ* -jB}ϮةHq糯<|K`,5ᇨғ |ҿQDzA C;oĆovb?'uQ g6RC R¶8¬o :ߧZ]$>r##@t,#@/DF*&+m \us%p[cټ0""$Ga2ٯǻNZz8nۮe' &7pRx(1=@C)GT.*ϮI ґyW7i>B?;.#@aDK L`Ld `~Zsaņ.o`l[a AQDXksOSYa/vؘT~,f^NUjY g]9YtHGXDy:[)Z<=N'&(Z$w-|/_ͭςR)QNB!tm/i_65|i{`s3cT!Y5^>ڐu$KֲH$I _rq/'5Xzj0r XƏ#⼲M>/[g Q=x(`;[1RNAlg.q6J.7Κ9 gaEkgC~ִxonhP~{e23{Llj50bgZ.^8K'5*悒DLD󇉣.-j9{@M8 kb3x= Gؠ!zKyxYLxW?i^L iqb & ADPDQ4iDcHc_v5)@t>Ԍ NmW-M}xJJbwaqkb,0fe $\͘Y >IWùN ^ShukӯQM=6D@뽖Dsvjm[Q*N&jN%'/ɘ:tUSOhKsrɏ2ò1.6j jƒ̔5& rcaTk ͫM*fyGAaҫ_g7s?%59U:%"3nvǯW s 'd87z_iii\Vb A)"_s#ZdN"]ťyM2jw8r"wS8;;JkNM9 ]^hoݞ?2lŭ fSR!Q0 91SFJkg2W]Z7`Au[i(Ք/H ^iѧKڲp9 2F5mdƌ<ֽb3خywo׻V?j\w2Љ|\1Tx=Pe Ie*gQ(LlK'j L>SÌqN=p#Yg0 Ѝ#"m+_ @6٠'ё0ihﮧ: >Y0 jd*]g-OuV/8/0 -p8ܜ7*#I iB- IhF2˲b"2cicc=nE6Qo;waGL lxQ9l:SC)я?5ˎ4uW@bԗ~ݔ7.?,Ġ57"{&A*pR5\5Gkrv  pڪ <;dy=pu;1D/B~CI] j*siF|t;oltp!Up췎MLkW2HD]16]Dr{♎rR'W@}hҥHCMACDEtRn<}XyoiAmű%qe8#ʒ)q6oW+(@XJD8kemϖšLsm|{F J-&*Fc2{}hobv>.O7$a2Kl`uU?-\DeeH* X oou3uM7'ٹ5nJ1bi^@7,_eMej +<J$PHY[؄bЦof3ԭAרW59oӾ⵽vE1ٳN4Y}i·+Yg0nACQQ뮝"⡴d'L BLWE]D㙮lghi-gFx`6=FqK36 u]:D;;J*GڈtnY;D3A" јxo&tY鼝 _n۝N釒"gD8_*Y٣CYbnz4Pv,O;xxg,Rdxi{Ln0mE8 @V|+gRܹ?17{T7’xlP5Y: +"yVJ {M@QgstiCEco 3uTfZ[9SĴGQ$p#%nTFFy@,ޯMѱa QP&+R+=1ܬ'aWՆh]nP&@o# ̧_؞wJI=;+TAY.4G9?ͺKB.8RQ'O玃0 Q'!3Prs B6y34ݝn:K**a`#SqT;Nm,Y^χlm6;'GFf:nE@U=~K+u4-- @]Xx+MdncjnWPEẌL ߜ鱉+[xbX6iCႦ 0f݊.<+om 8;%B:FGך[3`i5N "A0 &Wt)\Kәi;NdmMP:~%9B,_>x6BӳpEƹ*_K uyCI K+v*vѴ c$x[<%@xA!L.sJ `5U@e{|3 :&Ncˀ+ LHQr->x/4vڒK^1?9D2jAMT^Ҷem(MN2Y 1gf4b91.rӣr\ >lO#g|aymYTG *Aa5wǿD0SZ? Ԑ #R&czOݍC$v3l^ʻ"mU ejS P<-@lQ.SAA-&fKr+5>*8Hq5Dd> HbVlG# NQViϿetRO$Q/#V6 {^|zog3Wbp;d&M!1 -:R ѤT3-:(O} ~8XTPhT{@"z93[lAl9n5g^ #xMʀH|01x5=s</k>'g\;v<}RHT! QٕaH=&]Z ,2Cշ&m!&?1җ~叹ZG-8,&?ŷxt,mZu& ]\(8ADѧH]T'LÔWPuFI0Gutd$b f6 )7?ޖ|_ܙ[oT5rùL6aZ}dо{%?=ΎSDjljKlÝف'8l쯇 tHqr P_va@RwS Q'fzh#Dr]=D 9o'`qĮKg;欔*+ u9R1f1w-H\ף>A-gaQ\eȷqF Fh~${d-p }e@]T k}+|0j `Q3:$a&mO44Zٓtڦil˒OtsR8|`а݀P `YiE1" 'eP+pH~Yx)|O?Y1;Ч}|Í}v 3 \Jk $R Auq?YNLr0گeG;*~ZZ>^@E Nj* 6㕾W`g+@_˘>4(%"-9.+1r'rte =㔷{Ѷ5(K!TIu:֍/Sg@CQ'rV B<_ajQ|vǏ  "qmo`1v}< YidЯPMD%QwQrVC Rӄ)n4m9MFk~Pn6"`13!23d#2irJ3&(N9q^ /}Kʈ1N56dh/ 2[ZAQ4ﰈf>?WFꄊO'a-Ei%W֋Iy) 0 M_ISpf.D5GG[ @bT*"GVOnwIMcU% d(BoǸ)_+g(M*5whBpF'uN)3?I\t ]+>PGCseBJ$ΊNRcDrƒJu?bu qS4Bs8:,?q;D#YHqNF3^;}qE· r}rt { չ Q4M| s#(R453Nwn=w| >Df&%}܃bx'Lh?؂:Gz:ZJ4zQL VQPi|a["\׊>ɒ:12(Vc!{|E^Ǒ;AuR r|i/jDŖJ1Pg>_L` a@ fYݘњp^ `x]matߌ=w"Iw:ieB%Z"I5y9M+XV!_ 7E`0TjzG$3Ah!,ơ7ԊJ{8I3|00G/9xOb!ފȖ ,C03ƕ-k 9$NRn9^"dVa] }@Tv~m"ѱ{M/QW^"bfA:)ŭE7[[X`DdG1ٯw"l&2?cd}!dz-*yc&ߡHN'rqR啑(dE;~~GLr]݊roPD7ٍBը\7\RdABFԪʱt5TyR[zX,v%kBO_x:ae[X-+WVE`ϳs)%N̸Η K4i.=X#ȗCgu{1忣`ɘmS p&aQ4ބ@R@m9l|!t iO&bŪ_$fJ4qr6(<}T-LTJCvJ❌ `VMޖZE!&!BnIm%ću֝Ptԋ=U(AUkt\=ZnI%ktk(J4d|J/gn,1"]G a 󍭀Xm_U`\V  RDAЅ6dEd^A}: 'iv7el2`V܏mizw^#"ajZL]&)zXP;#WR㮈[aYdcābhqmW*frBasl Ջ[vo(F a tpBpaF^ktM1)kN)?Gi %h-L ǘ-r"YApuYE|Eh5o҃.Ivv~Dn Pj1[a޳`s_υ?1kSe1`m=WTy4!- z09;#3 ܽbCGٻGɇN*B17J;2Mv`oMZSŬRC X-C]Ī+3/BaAa9 1Wx=u,IU8zېOTka,dw81=nG=zaQYg/uko*r1\f&Jra$O*MW=ڞ:jo̷Cŏfx-D_]Ƭ 92d83A(Q68DK=o6Mx>3/UHr-߇/%Zier9;3 Mr: k[!0BW73/f'y {S"|;OYO 2qmW!\/v+1-AيJ)M:Q+8JƼg䉈1>Կ!qܨkdH&&:?L?r_>(JFSMDt_fA @@_E|ě t:~HeQ.oҔ* @V>JȌLp?~^tYcs MeiO e:%*tȉ+E%aL"I<&C o3&aBXIkª8YȜ@hLtXLU?Rw9Z[ro\E[K2Kkf8exd^'hEM^BuXbxf[78^A%lv>צw=FA@tIǷ5vY:n^*]77UܴL[/pun;1݅H xamlw#+B;^"Y9t||3!\`鍝rPrOk &"薒P fN]h3 E3{<$rUB7Bk`fv-1W8K&%*9k[1I 7aV>^>nbSkGfG^b}F?HoOKn =kZׯv iivH3O&[iP?_dv˟,VQ"ZِƺX.+ʎ)a&%ޥoWI4<:b5 lvb Q4r_(&x$Nӎ[$1]ȑWwkd xF'VA3./^|3l/.΍4w@n S 5)!G-Ge?a6@5b%Z ̚*?LpFW=DkFVJ0]{g1\CXް!3ޖ`k:6  %}V&aJM=̵r҅hb4=eK9Ap )Vx6&&Ae$ּ0ÙW|1}*.aQ`r9~ߦ8[3#"c i7z56e 'e[s% xfJ/tVu 3@al_ ?=.ҞOǟL;o1}w R JߡN& (BvOtYu>;Q.<=a :p8-@y.%(^vh3R hc%<{yHp+O:K+&T識UQvq$f&ש"Y()pkJѱRzFe"౒Yօ:5ʭYc"yt5 srr6m𼍷j'6>'yS..;НnўOc1e }s3zjk+{Ƴ'(@]Q˷YkT%`]5̄j!Ǔۍ*iKq|5<V5(յБWynqBC Թ @Z+@w^ ]MJ-m&3<!ћ+kJ@T7͛]dƁ,,߶cEAI#:-^]gM_Hg@`Mbvdl\:pKD6}hZV3'%S^3݄7NJV9";gTwU+ 0 qTț\!9FEq]QKxO.|ל(Nl ؽHlz+P-`l{qDOwcQw:'@)(mYR<3ϱ9< ew/Sg CQa &|2.qt7B Pmؒm9G[G*E,~IGjn{nh;FAv{"`X>hUQYT ֟efEF(j8-|ΉQtq3E[mH5?|ܮA7 ?)ͅCo2aOt&MTo7Hs_m^̳^a'UCL`eG}IHQe؊sfCe E0]|Սd 1FJA~(ӀIvN(rL* P.vn qdHH9U`PU9t} Ddjsp#V6~:1j*S ĎMjN,B߮I;Zvi+ 0SIENDB`deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/bbox.pcx0000644000175000017500000000735111357170241022516 0ustar keeskees ??HH @)9A?:2)!  %,6=CJ;0{|ule^WQJF@;73/,)&%(*-148=CHMTZbiqx{%wlcYPHB<60*&# $')/5;@IP[fs,.̞lcXNE>95/,($" !#'+07>DN[i/:ߙcJB;5.*($!   $),4:B[J?XB;4.*'$"  !$(-4;MC=N:5-)&#!  !$(-2Co>8xE4/*%#    $',;c70l>.*'$    $&4X.'d9+'#!  !#-L& [5($!   *DS2$"  &=K+!   #7|E(  0|u>%   +tl9"  &l e4!  #d ^,  !] W)  W Q&   PK#  JF   E@  @;   :7   63  2/  /,  ,)  )&  &&  &%  %%  %(  (*  *-  -1  14   48  8=   =C  BH   GN"  MT%  S Z(  Y b.   a i4  "gq9"  &px=&  *xE)  0K+!   #8T0$"  %?"]5'$!   *G#)g;+'$   !%0P+3pB0,'#   !%(7\4:{J82+'#!  !$).?i:@S>80,'$!   $)/7Hx@G`D=7/+'$!  !%)/7>WG.͝l`SI@;6/,'$!   #',28@JWg.+}od\QIB;5.*&" "#(-3:AHS^k{+{տ|tld]WPJE@:62/,)&%(*-148=CGMSYagpx{/:G@92)!  $,5=CJ;0   !!!"""###$$$%%%&&&'''((()))***+++,,,---...///000111222333444555666777888999:::;;;<<<===>>>???@@@AAABBBCCCDDDEEEFFFGGGHHHIIIJJJKKKLLLMMMNNNOOOPPPQQQRRRSSSTTTUUUVVVWWWXXXYYYZZZ[[[\\\]]]^^^___```aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnooopppqqqrrrssstttuuuvvvwwwxxxyyyzzz{{{|||}}}~~~deng-1.9.0-beta6.9+dfsg1/doomsday/engine/data/graphics/unknown.png0000644000175000017500000026431511357170241023262 0ustar keeskeesPNG  IHDR?1 :iCCPPhotoshop ICC profilexwTTϽwz0)C 7Da`(34!EDA"""` `QQy3Vt彗g}k=g}ֺtX 4Jc `23B=ÀH>nL"7w+7tI؂dPĩق }F1(1E";cX| v[="ޚ%qQ-["LqEVaf"+IĦ"&BD)+Rn|nbң2ޜT@`d0l[zZ ?KF\[fFf_nM{H? }_z=YQmv|c34 )[W%I Ȱ316rX7(ݝ ⺱SӅ|zfšyq_0sxpєqyv\7GSa؟8"Q>j1>s@7|8ՉŹ,߳e%9-$H*P*@#`l=p0VHiA>@ vjP @h'@8 .:n``a!2D UH 2!y@PAB&*: :]B=h~L2 p"΃ p\ u6<?g! DCJiA^&2L#PEGQި(j5jU:jGnFQ3Oh2Z mC#щlt݈nC_BF`0FcDa1k0Vy f 3bXl `{ǰCq[3yq<\ww7Zx;| ŗ]8~ M!8Ʉ*B !HT'\b8 q$C'bHBvay=+2Mv&G&Ec[ [bDDĐ I* Zc0&8(&iYH~Ho(%46h0װu wKDŽ7EGGDDōFG7FϮX{xULQ̝:+sV^]*uՙXXf8t\DѸ@f=s6'~_ ˍ̮`Oq8圉D]SINII\7n5ewrm\J`ᔅԈ4\Z\) /ד>aQ1n3|?~c&2S@L uYY5YoóOHrrsNy};_-cZuuk/\?kÑ)*0-(/x)bSWr±^$E[nEmnfmOk%%%JY׾1ꛅ ˬir]+wZiYYGgʿs{?T'U߮qiݧo۾C*זԾ?=xΫ^P֡ 2mjTl,ixwxHȑ&JG˚faԱc7sŨZr}wN>8(mP{nLGRHgT)S]]m?x3g]8wn| ƺc\x'ߥ+=/_u=wvWO]c\n}Ϫ'l:o\:xviMoܺ~{;˾;y/Ylx~XHQc?:b=rf}Icda)iDӤ)ϩV<|~W_}oοDΌ\«ï-_w>~f~#zGPQc'O6gAMA|Q cHRMz%u0`:o^IDATxsNXR%67֖zt <8nۛ=Ïn<Oa] vM)Xɥ-\["jm:cA DLxy#"&}^D:@!4Eu9sJR2c h@✟c Fn_a1,@ ۖSR6;xǸbeXʍSG.R f\x;#D^L#ጃ\d5s4%H'ѣxϛrNf{b`V!P-$E !Xbi՗oMjcm= M>1ҙחg,MrLLMN` DU)Jp!,z,69 6Ъi_,"3^=<>=J6We h DvH<ސ;_b(H/7 [pLe=/DÄR~u!MC1ZE<.-FU\"ucbljmhCC ҮGG\CSs*.PHRx_)N`k?M!_b5/Ob[ We^%INr3X~q*]Nx޸P )ހgc_OD1󧊧 Ԏ8 d( APqD;B15  ϣqi_MsE U'ZU7ӝr|xJلGh+?y!LfH>91l ٍMT3NOw0.q $8ض=x~K~Kb\#Qq p9a3'5%֛֍Z KA8zP"ϧ0GX2ʄ1l9QG>ǝ$*AHK)n=]Q)>Dէ);d֦9vZ>`t))ʲ  (/ڍXo-`TlC_r叨,<q-e0 8IJD%3R7afCwmŲ"9'P7Rcֆ C|h]?Yg7QAA 4u%&)L9_NZeV?I9uAgu)MF]Fj{bb؎ e+4DM^֦ViD/g{ ^1Y? jƑu fztGg>3'vHWeB(GLR控Y*zc >{F2j%Dhgw6YeP՟4@ A2tb8{ѵ%kiAhZ<RRuf^̾Q# X/Q􅺡=ʬF\ޥmlR {;^vڤp'Kk:b1@Қ6~%`lx&$*LOB:@%1:l'ԐeyRZ Y1~0&v>#6kb+=pL%V]!M[H3RCΫ@ޏQUes{}/.>|{i%0nIObD]Gf?G*N8v`uR||s[Bh )( dExf 8} Fs?7e-T-KtuV~@9yL95cqD?rc364DN+& SuzL!V$Mx7a"ı=,ūEM_4ytXԜ)Zwgfv\<5UjGdluAZnPF ͟<$9'k]S.Q&AM,;JT0l .峟k!l2 ݘ+?)kff ;O@9ާrWc iN @& C1-t]jTӤ&MLwAզ9c;szzJyswߴ;Mf|K!uFGQ_,Ӫv2;ϕ1}AeX<SH@l: NP!IjثtȂU-"K15Ӥ@¢b!T:ot &~,[8ƅ`_}gY*uz(X|2'>pV;XS~Z.JzJyאLe#̶ n9}!t^bI&cX\ 'Sfӛ0 THTU(5Mtgz?f?>MQ' 2Xϒ79^%'M4MHuxլ3B.2[ăMG:75x5Ch=*4!j :_M$6 qJ-)YKU\ܰpx'FV- /rNzji穒*Ҏ_9C5f6ByZ(qO' qVdpqI)B41v  u)Bˠٝ |yzI9Ibsa;U֧)U1o(2s|ܖ' EhmGJz[nӹ`̒:8aK W_'T6'^Q/~p3_)pcyrm(&.k Kt=Dުdq6пw-yf`t^!AY% ^Lӵ:FVsGX ږ<IDhlo)9Gq9%sAtΥ`.3J3U~-;QWL\tn/,tR9'8|iBQ fɣfONP] ^%k ܯf&^  \pEc*S- aeQT4v!l=tyeζ"S!!嵸['f!e1&'Ͼx1YcF`5$@hgƗ׷-eڷ.z(ӱ(Wa>$gfo&+ƛls\AdoHVSe3F_7D[K/Tƃ}ٓnyaHpwF)LzػBk>CRnx4ՍFbsE˲?տU +!kln`.k]($^ho>Ql-s[Qr@c@RUe 8ƣ?Ĵ IіZG[Ţ%5;CNmq|*l LJ6b|#mՙSw ( @8Эč;XuGx>'D jȱ33vf* r#=@ 3ұNqv ўOhOQ]Wr `chqLϰkt'-g>&03Sf{j &I %bN>y^S.;@ݠwTkl+0t.x0(~c؟BxMs#1 &S0@C(gPT`j , Z3\\wCwd 0WE@!4:]BmD+N6 E*嚓gHw&eY/*}Q Rb'aNIsi :Z{(萂H枳Y*;;ۗ7悢9_뀶 IRi%6_ONѣ V:ڝS3}8poHd눷ӕ6f)gz8nI8 g͛|ɻg?({gͿKل`!6E-W2]nY\+Z3i;W߮oQ/Gsd0ihV- ??ÉLMB̾:RXqP`乸ܐ6-d5:2K7$NRIb労".-Q@DvU?4h5t58O,zdrPFd"`/C`@nwAD@;|` yj_{K9"_@ѫv4Y+Kb"5(*S%*jsU̠>5:5vOu ݯ;?LONڊK."VŠݯ%XE>FqvCyh1On2CqqYu9hr; \(k=I*)t9/*1Uw9FcV%?5hl}NYMvWԡe^,5T+r$V0Z[K1R 6@tCH9?Jҙy9 v=c@y3ׯEkPS<Uҽ4IWJӱ@]!Yo 9/* 2,=i|53Rǂ3;/xKP4NNr#zcx1꿧*b3[zmD` 2a蔍vnrօ"y牽ߖVöz#Gw9J犥.SY|ݵ!~٣ΎoןSaKI iA<%U`s]BC઒(lNpG}{ V2[aSo<9VTb]\d;o@v yӤGi"Ho}pk{;?> U DouS,C /yRg S/ b?%fXD$"n09zI۾|,n V٘au%˗>;;7%Y*k G]QL'}Z}6rWcfPC8`6̺Eƒ?Ջ+baYH ch}|̾TET!áNL FP>-;3ĉP=P6"ysWAqZB G+QlA^o7ZAal&Qb hY$&@K @KwmkmbѤR=DU[5B cfO|tyX?߄OQ@\F:b.oB5v9$tx>JT< RAqq10+#%mՎg?QpP]-L;Z᱔]vU igUMF":vtgM⍳xu䝺 УB\X ytihv iŜ6̿w> "i~sIrPN_os=${DI6QQ 'Ķ }Im2R{aӅ.r:ﭱ !(@]"R˾vrez^E}nLKgv;j w60r 1 ?V Dwn*F!yǼ-WI,ds eEu]Nxwv~_[w:/RD>蚰h R/w$ۤk H8p^2?Lz#pgǙgjBY늌U U7o'*p)DTF$֩Oc2{UQJt6Ąz/`u٤$Jas'AcRh =WTE2u@PK)r|nsrlr QA|65w2ⓨj}nd#yfOIs3 զ.K/MO}g6FM 6U[luֆSg)Ʒ˄2 >h+Ci+ϣ?w1ˎ{ i^Rbr)zZ]N}StT^dy/ 0HT{4 61B7;Z$QSt̒%*J|`Ws,q1$l;i(Iq= A A 4ћ'?ĉ4~3h 7[G? dZZXgZ98 aNA?X:vZY7լmPNHvNi0}xNׯcR*`wEvggNwY 8KζW *NP@B xK [C]?iח5ꊄ"E>K~b5RN*y)T}[DT-muiq /dܡ 6"'ǟR\ і OmWz@j˅@d%9)9u cmT@J2.g{pYϣ{@ ,]ּkI 9TJw Hj\MGaeHzT@n_r`SJTT\>pq6;@ncgO^}7DDq PZ;;|Na(uXi_C j SF8!h@|Oh7H#n J3Į' 4~nW fn74QuͳC`a/Ϣ" 'ϯ{i ͣ$a1b%ٮ+NLhx$(2fiUkvꇶK@aX9D}Fv3M hZ &4>hH**:;.U , +#dZF$`) ӧ#UH 7_{`Jeu8FnXZ'gݾ֩A6 vvĬ<S+0!bS98kg $qvqڼ\͟lj*P-3 5" (lzIbScHC(Q.SMI _Ƒ[ά ^aXnUw`q3n'˓n#6a2sKO*W(,tHPs15,ڼu9^m}Fn,c8x@Ź& AԲ|.UֹP$HSUo[?Tu|"[~SFLJ $O&2gPj1ese${tat!m>1;ý͍HbCb RQ'j>Ɗo<ΚڮuVq7?lu.H:ٮ8};k,%enq1VUnF-)Uu<D%>q߃EӊQ1=\j~!QKh̾D+̜Na߼Js%fyH0+Ll4J]EYib 9Le3*@qKh =`lv F4q!fhnU}=0{1mq%2tL@q}Y;>RWbSq)3YCGβp2$>*&oԷu҂싸A] ^Z׋|r=u,pVomUg ~ qqVeWj==5&>-ߝ}湳_&XA eGJ)R"K1y( ݝyCL˶% $^%B"PjDe!5vm?r7͉E|:ue">ӱx'wa gYIRƯZ!!wf}NYǖX8Ƌ+wbzKhYf\0tKEPwg,I0Y:PZtPE]do[b `|W{:ٖY{y}GO2-`;:q<ȧvZN7&rX&ibޞ\o˾?JTGe`KNϪ*::,PF|z_$y!)mpYR(LIŜVqG,Gtz Am0`lt<FԷ/mYNCsWAsMjAw5i{lGqeExgcKIҶ&F"pNyLMLp޲Xx _hђ@ o;)v61+SRZ|qjÙ^f_{C͚q6( 0UA.y_R HMH}9 |C*mYsAHb;D`IJp TGk+m hTgnT`^+ˤ'_R 1:W2I0\%1,7'Q`ua 'EH3$DRB{9bao9]ow;ݎ-h8\*+yw vsR2ٸߞ,- G}*DF-wW<5S"TfH|S !Q4W(WX•-8n4^20G a?쪛?D$a0T-O醷 QңW4g~N @YFpPj s$NbaCurXMĢFmo,Qq-.X#9~縇)5𽞏]< +AT #mei=:|qz<-㮟 ]-C ʰ"1( b.p!]HksΞ0r3ڢY&qɋmgm[ ="N7Bw~ڮ z˳K H*l':aeu'.snĆ\Qw$0O48ޡMT\+58)ۈ<2=Q$/PHS&7I?TV9?- gwNvH8k8] ٥T{)ݎjgBN./fpyJъ,G$(.BJ3-@ it9xtj5v_ B㺐2JŮˁ__Νa*@w1  )}R!8wOc4cH,dR:; @'6Bt+2݌u=~?v[ c? \̵-NU쌆zoE+vj1;=o)X!h4KNCJ㒃u9^\LPvO΅ 7/Dnbt!9>d|ۂ\i/m~J@M022Dl!)6N#=1Hتyka1d\.AiAD6.aT~<u A ,5*EgK\Bvv<)_?"J/ "|Ű @ScUH53^)ƼܳvU;=iFyO9>5)2$5?WZ7wܯ.oeQ[b6ȩVOSju{˨;5+֬fpQF`+7y7hKDIAюR&;U?AkewL|oW:h*lSM#MKS#ii|mp$̌Nf}1e-^7I י,8:Q؃1ha¹`mǛzWa۲wL"I;%!9SP"F+#S0XO.<H_~oN2.JWUz|2%`a%( ݬ̕,ul&u]KQBbR(rj{^ώKoٻЅ,Y$tEFEc_An8&ij}/;ʖ [!w?&2 _nai!:RAEٜLrr:FK5i\Q8}&ĭJa )ۗ(5VC M ?ol'IkM@SA,Jeiִ|$|*fXdA4z۪/J 5r̚1vvR'& im5-trfZ5u #Y&]jk0`8Q4Ʌz!=9 +}齶#*[\׌lL-RfkAI 0t`Bbb?D4YecA QB{\oreRT%b8} u@0pK&*cȫ{͔TLd8`&=@ 8- U 9.^y ; 07(^ќM*AW}Nd@PNu_W63zޣ)n!olLU>|gz-N:-bt٨8oq#/Έ0 #܄mk&<@]0!iZ> pgc"gy8)F^aEQs}S\Mi:L@ C7Ga8(8:fH֓ 5^ɒ6:V n8 vѱ31sY2P&bou7K!*?,M@XkàVUꍎ`QԶBe59mRA"&~_\mW0l Ai?0:g.牏2 4|11{#+S@Ea~YXReLH8yD*W%gPUi& Vp`PFw@n7eGWsȜqN]_l\y@U/FI)iܡz.ӹvQ~T1y΅r nA<:sb J[PROe\=upK3}ow6<ݲvn L28LwM!7\PX֔cj#Q~$ =zk%_P4"CZ L/#8qelK 0?)4@!I :9b>$it ?%I}rcct灄Ͷ[nHy\uÕٻXЩQQfjRZl3C7h䈰%" .|ԭ"d@K=ЖߟUgW OϯF11_j ǗGB=_ekuU-lV ^<|<"bii|(Xb̬@%U (s3zlQqO \ψ%Ux5R`n,Ԋ8z`t4V%= HLs;|mރ$ q=JbKՌ2 QS ͌ҵBƉR/%#8!]wέC>m!U_꺎gBʼn^\ow6]Rn#wL0)g</ BճJvMEDžk?rZ@^?ؼojq^rR^W6[<6fjCӣ+.#Te C̎䃘4;鄇g220~S!Ѱ= kv6+S|1l `ٔOi-򺄧4Ċk|-Aoる H?Vc mww oMhʆ) sڙ.Xl0), ռ>3ެhɻk Su;U*Ns%oix)jD#G%?|%?TW>x:PPAp$^!R̷zbߙ$Ҷe =Y96x;5?|8,݄%-).㬢j0 I(l]b?: LWT91=xan[ŗv!F*Pw4)G p1ob2E VZXd궤,Jxk:Ac4'~h3޽ w0B~{J9' ycx~J{ Az c0H;cדf*Rݔ0סQ Rtsaa(M/:MThjY]`g! MΤ.eLpQU~$Ssy(QRg)ge GBZy .8&0-.h oTI-*ǃ&'nPx VdJ5ǚr DH98уTErSa<-fCk=@ 4l[L\0$9O`E1^$G\ҙ W1|NŮb3#XD!4Kitq؟@'~]x.d޾jBI~Bs^c!wt6ztn;0 6n!^_7*]IDZ7 ,7e@FV^G7X1ϐ8w=*'?hd!@mT>hVs0ŧ@3g({Ie*zz.X 7zN*긻DNdgwMW,ގZÖKЬ3OU&487RD5lr*`n*]x2!Uap`!$GDQڤxKeٞdO=1EtQJ"mZElЕ+_ ÏIǪ5'Yj)*Dvhӗ\mIK=Mǧז6TIN:Sb|#`X׃t0]|aro5۔x*SJpmGA,]6-KFa-+LzQi|zB_`^hy#oiezA'sO7+bˬ^5--T ‰}&7|`G=A_ΥA Ht1 .BWmgiB$mڢ/[yvrR{gg)V#\g+mtγ<›v 3<$*ql%z46~цe:*v OGù"(+P "7iDԖڗ0s8*PNH֭h$ߟ%oĶmML: zl:{*ȳ1+!B@MScQ K);LX9jڴD &v/_B)bx? ?!$N,jwYN X0Ŕ5X;,U~0u+ @$( ˪^ѓ.#̌uŃLw:nw?T.x=˔( 8 ӆFg2)^(X%A掤)uvi?yF#k.W%<)xMcS3 G mʲv̟s,ə/Q7o716 0LBH>Tׄ?GhbI~i^lQѩ$ТScS;?Ogjzo6w}8!T•qO0[YwUPQD_М:=K@ޱ+trlθIjM=lG,(T@ef ylFC_Ih,j;Ag'vVCؾ7o?mbg!B_OG'{ Ȗ&HchमFH~򵡥21ir@nj3^.bOTt7zro@C9a.x ,;I>Ύ֐OtOgTG82|w $dxT,-L#82r+!%P`c+̡W_yٺ:k)17=pl/_gwᘠw/doY?>ȲFF`cRp720@Ϙ Ca~)fZ;k@j?s!: y ;MmC #6&N@n| pu&_lp 5_լ\# n!"|kįAM)AH  Ju>0~| :"9!"Hj׳ S0LQ^^sSCz^~a`'Y l-Cvde/` `B} R!_'Kw.] PA[5||p?B$CpH  f4U('=nKVn@&ܷ=,ɂ(PW~ IIU MJ-`(!n!u!i))H@gaYI܄+W-X\TC/`lO*Mt!ꁱ&$& `̊og+ nn4g@G⃞ cni @LI"j0F ꐥf{m@oYb@V,#e.u=1Yal[׳!Bؚ`Hq/Mџd+AYY " 3> r h HuzCW@{"omoޅ4 CVGq*d2H CH`NCXPEx=H 0xxOJANO8u"(2-N?Xv0C߸WhPU#7]d`nlkr7H= ; nǃΔoe> '2H<r:g<dH] J!'C<0t ylHHT8>|k1 !~I^ )\ϊ%*f]* ݰ 9?bHSrR,Ѕ;@IyRWlq͜7$+43*5'8;j쥟?o5@;8@?|9MCB d;@Gp4 z?:?ز.`>}W;[j*AR:gs@76rdM =4 r&fNHƀX ^"("9" 87=tA=%RUp쌻mzرL `Ɉ B3҃zy)D@k!}Ѓa~s^e ʘ0)Ics+#@h~OK)`Qa% nֳn_맔8$AFED(P1;E pvN`dD s9N&\ j M ?Nx d\ҕx D$䀮D@obYntxdmCmMiaCc h2[gkI>bXIr23+ȱ9 U `f@w@[CQUoᆤW30@7n- .*XZJ2:V#AZ5tOFJOk'{Kh ;po=y TCtӧʆ}Ck9CCfKy]7dN T;`pa{P4!xFd%!a7<ߣeipPP$3d$l Y1l?-$ޘ Si@F@OGCÈ tuڻO`M/7k7XcK+%ft!G6YrKh'/H  m2AБ L!r=2 !Y =aں! >^ڊ|K0EAlOBk] *Օ'6>` ߼ x~N˲.7CYpy3i>P/x2>"t&tRG ` |WA x)%yIH @:D[^ aCB`@A6Gg̿!`]pc_p;<:&^!xfvF0CgAn.Q|;1AHA M r 6t339p Tc>wGЙ*d7y@ R :aT: -LݫgXPjoNWo'Xazy@;{*9!!SŐidOo*S{`?+K3 :._/L u8 gQ@u[Ll- [u.p 3 lAtIK;Y0Ip~8u"eaflBЁlP X}h:`Hcg/^ON z r83/𚨯}aб߿ 3\Ʌ.zOv{t=+<>@7|A֜A&5 = k<_>AY&qrDd?b+ @Z6#! HCD'H ә ~ <4]xw \~>f0uٰ/ ɐ.fcdAC2UMlyU`[IA{ J9@K!y#/V!#@Çuv@ZQ\ [ ߼m?C a, 58 9zo1P6L|EH1 o599XBf녁hAdO)0†kPbgjx8TdV#^ๅ'Up`aY#A]>:`E 3hI(S!ѱFH}/+t.(C%*I褢uA(f3{z]ܙ> +%z 뇺jp#[!$ lOVb6'{>Mjbqv'QviU V却IlϏEbxDi(lzӽv\^s ̚/3M,^ti#å)/lS4~\?Uw8:dȒF,$:dx'B0YZmWrckEK&.&G49VB?}3KfrK?4^rkZQoټ1k9'D]*4p@unAb6hLHlR‡X-1P&VFp 򈻞9geb{YvsɽsfѪ$4lΎ܄̎mf(A5%UZhgzwXr{ C+wMYꐄާc7n[IYY-v ON/Z!~0/J R~!{%Yz׌țjuذιyw|)Mi6̥fO-XB>WVx(^^4cJ7}Yt8̺wQ(3'[Cp9fލ&%CyPT eUxsOB3R_gR[8D N[uê>oú˿pu5; Ax)4PLLL8LN>'&p"<\izkl .-Wz- Ս #Wa(lvċ4j'c5#(>wNei 0K^lwlg$y'_7yHHHimD3"K!DDsYb2\ y "'⡐pu AP@.pH<hH((ˑPtpHswaWe[z=?Pnm%ڞXuj|T#r##ou^.7E1?[#̨W>*y\ܟNiP $je>^)2̳zn=HatZFA?~oBr%>=r *!8X C?zαfZ~:!'^!|[/W.O2q ,Iawg{kgaeYOy%_ǚjJL>@aơ5ye/陒s] iFyXtiOHEƙXndfoDpD9 ? WAp; 2 ntBo,Ԉ!dA'xOlUd-_f<0;wسD<7#^CM_X]+7R-;qD(Zv k I!'AOBFvڽ}!9zNB6s>d Yu =6ox؂e2]@vu [[+yl@PU;A3aFEM2R*`)C!R8@6B1G(Q x!?F:̐)=+d.d #P=@1AN\8d.V&!kΠd`}z!*hO@(C:NSBj7e.` ˜j@s-[ L`[9,j&d mw] ۤi ʒ,@*0}̄>w˓Hm Rr Q_"$pp[9h,#- zCr}vShl tYK A`?"&:%-.Aw >V HJf`٬4p|v =h5 I 0 R "BR(7n&I?0+l @ZęrLHS5䢙0q^$XƁlC ^Фh=H ̈́CFٜ`bH݆\::\C`ZǼEo"Mwd@,QzeK}Q~xJQD eA0j^Gc?YI:۩NiU!8 ^˲:>dg !pT!=Z84٘ǧG"% yܪ:nSMx4#e[LCAYPu: AO@= 1>-065Vv4TE Zƹ͎Džc7 ws3|Ss3Z{~$ؘ8 EB-Z(^S_'t rJ/Abb]}o ߚ/>^e](| $8OS!O7כ0M|v:;hVA]HzpVQ^Hwլ|,z N&(-A%)nk'MqL'CV)sFĀTKϋB"jxQS⇂!NP9I4O,*ݛ5Yr_]U'G eF\ GOv)v@L߿~bAX@΀frX?#~n|m0e 2 z =lfT'؂uUeFvUȬ8zhVig?CRB7و^ 6 juUr,+xOH|å@e@76wLIrt4^߇uX5AȐmM%+7U#F`1ӓ XB$}|p Qv5=4>vnb ug߈ʄC`U灔J@!2ÎD 4S/x.hmɝ{WRW(,*vM%sAS62jFƺYpvkr 0~k )S#P~2UYPhWoݬ%&؈$ 23чi;wL`ӻ. =l.\ #D &6FBbyjm9厅te>}%W4;\D`ol0DF=8hnrptv=l9>?> wBrYJ5-枞؅@m8Nf*޶@!YB:xȔH -d^Ood NwFT,: feȿb,-`*?! ㆐\`A q.hd֨eϞܰeDXLЬu=PH\5{޽{gV d od\*]_ L's,3m/pqps9p GvBN=r_=Kds  {' ' P 0[›7piv|Ήps3'6@~œߜQ ,k?||'pد_<NAgwށty; A+:f)A\-)ykZ? #I4VW/Ғ dŹU3wZ$B{ڿQ x6z =#Ru/$ϝ^LNɑw&Fjrw&R"~hNޛᯗġcoMhiLA @4~::*%WE5YIxtaXR'@kkz— tUiΕ|3Ia$TW@NWeN:)}ps`@4P |YOȺh LUP $+#>woʚ&uۑT)mM;d +++Z H\ ڐ é#v=l?ݯ^Urd/Љ7AO: %G0+"Ț"Xr? =P6lNV̰d^0-"*!"zD^5sxH?RD\2c`&QSQhv3?Xy:s ٢+VI1pRVB&?Sxqw,\lZ 2 IK>IeI5wAν,o腬lLHI iI :"梿BjBnڹ ѦQ7_io}XXAV„v9ݙp`\̽w޻soL`+5Mr( okRkn>!;} z̻9C#;o-b")}<ӳdzO>MRNYcȖ 1bn Euщ.2`( ?H%F3_En/ou@oHniV}.cRѩ OW[&80kMQ} yϗ)1ŀ'iM a.3ب&H0Y"Zd9 r1RuMHAoE޸ 7\_]{x鹪" ڈ dx@LwBX|o>VZjS}45XQ|m(vtpw&1^˴"m0H$q4VzWt:0AT Atޱ #9 p`HSabۨfe2&7IINq;y L&fCG̎Svj(4:r/{(M`U£"GˆPG2h N Sjҙ[VXGrsX1H۳lJURu\}t@eza/ElZLއ9Kv ﷫Z =],rd pu?vqXSdzϗmf5P\KYRp^G(-L5dLzT򏼡-u{8O`e ?-c:a kA+\LFݨཝ]{~I:0fS̛ˁF4gxv"{o L әrjg%Bt?9Ww~Bs1uoМkel >uɃX129~=f%w5<wuTLc" xUFg-^aqBQI 7& ;9w$'ĮyW%amB Gc4-`ϳA $h4{n8M;iSD4~>,$6%?!+m;2~raI`M 0UI :3.[- dXEH[o3&"|BO42V!~'aԴ#jy}uc*zg֭W_CF;#+D紾 sn@ͮ>Jª'wNU3ȅ!0Z4ö^dPtoTbfD<9rSDGo m/zI۳:{a7 f@*M}0?}9}vcFp {^^T;4y\^3=\,pאduk8&DMC Emoy >B[ W֩("buguWT4#wF!4ܔK{WZQ?lpRKy bJ˜ +e~@gabޢ[sӇ^ !eba¥+>*:ȃ![D2GejrѶǯ,U=l| LG ;iS_ w׉ v5m],B鱜n uv?έ:V5B'Og0 &W_Dv c3Ri:?ǎm}ufFn")m~WA8Kx4[{C [BVSuɽKaG.ɈFx41\g;%IqdUX1̎b+t3bt$A=@j s|TǬq["W=o0[Pm)5S+l5/5.%cO2B~VNbKӋ"dTjlYO3lr&P\+i-6j(C]wQH}rS!G}}=)vќm Pry2Env&o_:vCYmVf&k0MsmU9 {}2t}| >u [C(w\S$1s3u[}CayarIg8=,hȔۼo䥹|PqEZRW"Y]]4aQ#We+*RS`1YmB>dW8ͻnW7rڝY ;e?|BʯRЯhG{H0,OȾ̐23JdaJ''4,Kgg-Eՠ"^$}xE8E$R̔YaJ~0u.90IK,q!h )<'eGQwCת61dmyG VޯN, ?f+ORlJIU?oݾǔ$3aQQ:]zD+ |AaQ 3N H,#甁%g{%9^6[[i(CPPn!3*u4\ʔJ+Jev`;5htuQikT ` al|,)t:}r=$0. &2tЊo*2q&|(D_(czGRe](2pɂ.~lf*`}Zuxz;H"LZX {( o!я<=su5nRRm*ف%ᐣ!ǀF \ra P $X'RZyN˺dƟ|rcLqHLQ'"T\H|=ok4DxLH!ϣkĖcI,; YXn`Ve ߚ\=ˠLIֱ!/=z( ~% -Ca|X]Y"1pSV E ɗQfԳΗqZ3pF=oߧG%m`PLQ; 88J؋+16[ uhAG̘JTĥfԪt@1pdc\e'ٳ&uR/Og0 C?$nIjّ((Qi&tH(Z5Spv_#c9\72=a>ڏO\NgRg6b?_(Ξ2pV>fDO_bg4*)z`JA\!&I:«KKI/n(ţ%3D[GcCOV鈙 ;t{oԺn_$>q ňq َ]He`0';Z~ӹ$NT,ijˆn$ dn)U3_|8.O[8[Xd&Α ,}W6` V A< O$PhITR۝MJ KmIET`sQCOp2 Ơs~Η^rוOo #Ks21P|h rlf"(ww?GK,Xt)[,W Qkh0AoQj0aG_6 cFXԎ<:Fw9td67.7q [4#yŚYA 3a&_-F=}?`@yg?:ca)ꄄX SXYX@m+McvCP+.j7jjvzWdܮoy{ܯ!&܈/SAa]ra O敘`g0Մ=58=~]Ӻuqå׎  z z=^`-w τ斺ϓAU- i߇Wҋ*bdҫ[Brt145ER 6I=kRJC$dVt\ݓ "IԼIie b^.zȐN$dsϲ,qqؿ3mah -Ku %KnC Y>x:/ζC`"ǀ0ogh[ Ĺs~H2Na0kyH8)K9m#sӎ SIǖK"(Va4]Oί.v#ԓ5Ly   #*y.Qȇ"oqDl.mfyю/NqHح"8K_ 4 +,B%UiW0:1ipgokܗ4~@8'wEgw;mB0-gk?<ݾ3AaR:1_iҦ4~It߳Xc3?m28Z5L?M8 Sܙܰ 'ibKxe,9>)cM3R#nerN˞—dkIq#M ~T5t![)u:02$;gbCj|o%`[fںBG{y2o-xaЮ$mBztju Q!V hP,J;TŹxsSL+ЧAƚIRqJ3NZ1FQD?e TtSq@!h\T܅ֈǐH.:DZ_i/~7@"|䕥"?\ Bg./HPQF0DU 5B8¢ <[$>X@v\!V$"y8Hh4dqj̮cfP&CX94TE/x|DC%&kǎ*&Mװ@o Iu%4oܼ.lcI''h;NƖ jӊng(OYjgVKhݑw&!`.!-H&@ 8RHN|5gw@؏ PS]*8@Qc*rZƒ̕yjW 0+O綃 Qڪ!b&1(9}P^fv6Sb@E+a/sv~ii4oz.O3~Y8(}WB "$jq-EOca+/Zb5&)=t^]O#jS< Bɑ~R2*^+ƉJΆ;W]oSRuۡDJb# {.dYRM#Uӧ: F5-0Re"^yょ,Mo֥&1<rstچL_%a$B9 zԦl96d E>g0sYn6>r# ?4j^y!)f=HrtBEnQۂ %h%wHȢí #}Fצ֙UD("q0I]0:کh! # O8jcK?UvdE0/x4 \r*uĂaOaͯIx|Ͽ%'{Ĭ֊Wo3hfhfLީzthWxD Vv?br"#JGs$Θ;a@&ov3 y0d+T߹Kp& H6*ex@&wwJ4*0`Z q]IHգL",Cl(nO,f:Ҥ:;Fe\H!^? uc$[Mjz<[\;=W()D'Sƨ $qI B bj>+S粄 CQKy#L]8X=7սPhGb87q)B 1"`ABzm{H|v{[eecfG07q/)GA!ղ[ZϗnXQ Y4<&@if'GdɭG _4CKc3v@:Jfo ‡qw6$:Y`%'7f9voZ:.BA3֟A,a E-}S*GT&e8|BT QB\-I@ur}ҼE4WDdEv`3AF$h! !#"k]|4wakI@(`P98\up7=~P*1Gkxx? NBci^>yz$p?{eNYymzM"(k&ŒO^l@bjL0=Q 4G$h,)Pa%t}{D *mID3mJJYo]π`7Y붐ͩ@]>PnؖjJ9KP,J:Y):K /ŵ{i#hΡЋ q[)(a\'r @ԙ 0*H`PϏ_LwTjhljOgeB SaBGrCS">CFuʯ&+'w5sؗބkB@QuC $\ѣv397i c -(c };8/լR֗E/[rɜ".K4N inKvWba@ԉ3B"~"-dT"Lɵa+5\*&oaQ6i%beH93ջDZC3߉:R02Aap8q!&A hץLՊhH +7"[Xp1]њ?) 9~A2ZLl0|\ne{=wFd<Ũ1S9=(eMΐPܙ<]0aȩGn8-2_撚`Lچ+4ydsN=㯖ELCe=KqÆJ͵ * >B5xr/i/%78sy or$T4҈=',Y Un,B8y[m>tP-6Ȭo?`k-C0u:0- /3=L (^GQ⺎t#ȅy5b2=JllUkVpFBGC+ yFS8֠N>+f bb(E䂌ka_<2")U8Dk+ʷRjwx+")Qȫ4 JIh)2ZjYV^`C[,PTocg\l(\2 ^`߮HByHC]Eɣ QP,7yn웜ɎzX>zU ɞb5l7  QERR4 ~l/|dq\ Yr$B Թ @twDD|/(Vj2'ߤXm2/P@[DUkOӌY/ r[@ԟÙ&(+ȯ! : wwB[tJfm)'j,eOSz_}ĝLC c?\n{FJ>zz:=pN9ݰo sA(*^bPcb4bwNK|,N/%IJB Y:PQݙB/_@iH&)OTM4{P 3_]D$,>NåYgӰdFȈN ƹ %M1t8=E)%[15ʽv LDК]fd9k1 2Aޠ1sD~y`y_K}#N[.ώM+fbkR;x*~n3zUOxyp *-xlUOщ$llِ~-9Mh39!D+eYA$Ix NvOқ[f3"P`3A*M/ ܙx0n;Ld,qѰc[4Kף-Ud6#N(-BIRqϴ:{{c:2rףa^֣6d(sS7MikS(kZIs6v>gp9ZIE{fm))rv{AcOC18)G+qrF~7\+xUg}!uՠehk[-\X5/|z&'oMך[f{nm?G2 VGЖԾ粜1Ң5P«9r$L@ DY6AYymŃFEng:n,O [Svo=Q%/c=rrLng AѾڲO *S^n+ ;7RHpOE(8P~Κ|ʡh8[%Ɛ+1֘Lƒ;j"D!+hU<*zʓ95j{EVvE|fejR1qk3b1v:|y>ڑ&s^WHz m w< x. K]6D@{B=!j&He٢80u;0 f &CB" ! VGSiSqG-q S;)r{_qHPnׇcMʪMjXa*(izx5ve%x mNm%јy\ǩ׹g0: Dq_aHMx(g҆nIjP0ϠТZmQe#g9Uy l۟.Yc 9R6I!|Fp pU 9fHM q(M3^] "9>U@3$'(Wc܄A׻,>~ƿ.D,k~>Y痏n|/~;dz}u!]d?;wQkċTh՚|TM.l3L23Zob2E#CT#\rC`LbI)#LH{cL1KusK ~?CܰhX&.q,xZu(1;X8KgiLJ-gI]>8Lo# ŖV}BB=Ɇ!)>5Dtt(̲~ NSt R U5ug αrWtEWs"!^c_}͂I =DAҾ|I jva=ZlUGc_<`jzh Iɾ` V jZK/"x*/Aڤ7 Dؐdgwfg,p*V*S%dNG/Mm$uc W*]]0ԝbNׇOϙ:Dh}W#ydzn{#^lwh:+Jf0jQu@$эe ?,+ EqLleltKْLuQS?!"~"s i9?+U-OC(S{[($)*2}2$s^t׏{DwA;)D3aQ.Ɠ`ʆ$oRDZpӱIُu6 1n}IRR 9^[]i>iP",i43z~LF^K;Y %y 1 85%/ݻbŅ!!Orw^=2ܹ֋E@/4 jQCXGy.ƠQ3`(H7"ώm5 >Y>c>hP޾[pK`SzQ=c1gY,쵋..Ӿ/ha5q>xYA W| ݈d>iZߟ/'٩Oǽ⯫bΡ!I:om|+~s`g5܌j`]F9%=ARÂkUS9Lw (""p$5@3Sca~#We6l&>I,p$Mb&[˅xȢ3Tpq, 5!u1'XX`ȵZ'eg NqX,ܠMgFEs.CM^R^u܄&BV]J͏ ULl'8'} X :"08zƹg4 vyInn}ia.!PbV<]Ø#Qt 6CD;ulmj2r wB-_皂0]bQDRx,d&3Ҳ 1⇮rb62bX;)J*n!¥GbۑlX&cL-zb9jk>1)A7k}{3> ς1J<0 a3<4/T;y<l[ҋ[IPpiK] }`ށ^Ph8Hk+v;d30jBZIr~rbK-d^2Ɲ|3:׹p nwq*}d8mAbpxcAbkiՔ|Ḧ(\§tMeM[]Kud0: KVbO+:k+"<7x⥏&(;IX%AӠaq`2D >yMgCfYM䔴oPK}ȧx8F} (@E!7W&$=$L;ڂ φ*8`TUr~q͞Դ ^ gif.*kll_?7zidAl18uEw}p+ ]˕n?H=6|ܹPqh٦R9T @ D. }*XI%6M&3 :͇, =K'u9]bkI0>5ğ?4Z c0]x Bw;lx!2m X2JJ*8aGYt݆_E݌JG5C*3z%<{O-IGUܡ8 `_hIk0 ZM Js궽HSM3{H Anyٽ$&\ve@KӢ.;tDHޡ+bvNFi^jթL;:Ö0wJ\\cZ˶1 ŗK".tZ~\^Ͽu>-QWJPN]?SF fn;CUPDq޼zSkZ b|XK|"LjAC8n Ko`C2c`Fa0 -yrG.!3(_]`Zs>3nΆƗcӛH_,Sqn!j8>?֫칒)`Fi23|| v#:kܛVjqU_!qP$]Gd1; ƁY5.K*cgw7 U L+Ӊ!OyCթuN͢L *mۗ7g{NJ_b.@d빇}gL]e #.{]B:>u { XMBË厎ا^n}>9-~WB;>"W=*@R۾~rE/v`!lj)^⮧y5c^gϯَOqvK581a|0ז/&~hӘ W߭kIS\w66͵y)sĽ]L_0/Dl ܮz ųu^1͛͌Z^6DZ19tcb+n 24߄Vb.j#*(?s&_KaӞ4MSѠj$Ň1H:A Ʋ |?۶q-M0Bܝݢ ~LMVcT %86[I%4< dwDu9=yXߪ""ymHRMs Gdܳ~{Vkt:UĔ3,c@c8D/]f|1R^QOPF"|ܼ,S&gب,"hnT'xXp}A<ԥ33FPnc7r0MчP7?6qLv=&Z}]!݄=A5AK;tE܆/Qg0 ઴ x, ?_%UvQB; H=, Ov_@ӏ>0vh̉Ę2r2cH'W~^.dL.,S{!@LiVAѸzŧ"u6'V3v0a}۰9g&WtmF!џ0̺fmCÍz2=JJ.*9vdZS_HԻM;,& T1ulSйe̖McnwUu|CNg { tp%:Cp\R z-Bx0Ol3x}*\/ 3AhҴBBbga(Ρڎ{ϗ͠>ǛSH%V/h ^`Hf_jd#5\e.>Pkq?!I<7w9C 0 /l+r57 c%מ~s'^c@(p;}^k %\v4*)Ӎ SW&ۦ̀|/O5xtU恙jsmN:8Irq6{:{0BkNwYZ}tm+`b.h˿!)Bꠂ%k!z#,-1d9)מK<@ CYpPnseXKIQ! \_*WVrqwN+b<2yhɜ':l2 ܣ2`G&z* nn:3Pr]Du?'+XRhRej6` "<θ\:ˌkHdwmXafEwS~ճzKؙK=C]$x5Gc:}̀v'G2@u+? K2e"zf˥Vlu.%pF4(Έ8Pфf+%Lw,]։(_GUXEhzBK3D9zLlYX|OP8Z ra 6 &&{ЪƱP"uI x "њ@1!Є5k B٣?XfƀiE9Ya[ \fk fpg{ӻRMZA T0ǖS~dh i*):$-L8"[k\ݥJry&7"7-JFyAP}||bVxL {ʋi\w1kzb̎ Q$`dd+z*vWy׺r O A nyQxj%'9A4Lfz,c ^HQ51[yW<.ײ ˲pLj'~I‰ZZilܞahBTD4t,bM]R}h;44#֔"Q5a4YjcEtzs 0^6B !r'@U*Fw#ժxP\B><&RKHwzs)d^lZ5cs|]b_Vj`N nh鬦gO6@,B-|J4N%~a|sD0 De9 BB-ϳýj/3c<_))*q͈8Cr`RCμ0ި5BqҾD ]z,FD]Fn2xn&X lk/&"I754J22X.0DS}E~8b2^:[6j@@fO,a SQ@G t蔉_2XJ8mZ sr]Ԉ2:"7bÚ[=``5ҕ-E0olqȓnfѱbkb Pm>o*o5HGm kݹ 3],;%-E&/EU/Z4PzƓPh1*M%PE&duq @~rg=ztiI_zcY4<+fG Ppj̊li+Hqu1FpIU2ly߱~6] Ȣ`ܑa āRPQPq'>kC"E&YVz,g b4)3B(nj=|X=$#fVSvLiCpng1ץ̹z:_~t%900-BTW]{\AuǞ(_gkw "3ٿ9(ncB렱#OṊoKļBs!q ŀ a1$W*۰5pJ0ne;=\hxBN"ȵ4\H' P9k'Uܣ- 0u՘$9Cd2s'X#9s~ÉD-tIFJ^l#bK⚿$ S6,Lu eaa3Z&%Aul:Z }XLxL2^IS0ѦV﫥B" 8e 4}#w<`lvaL@? lT\4muq#gP^@.Wb*exanQ?┖Pf"&@ ]t( nRIV95)&-c?[@dmVŲv|)V3xVmT62 .`}-:_3<:uSDW֛5 +:Y*8Ty'RYS].qdMa=7KL}DHYK]#j>K[|b.hTm:)t1ȹʟtĿ3]o7~m,@)+k?)F">w19Swq  @ z:jAԖ̛, "&L& C7 ?(,uI*?#4kMeLtp")InM pŷuK$'!N9oˣ܂y`nr0$Q.[,SxǚhzIePkCN瞱/~ϚS-N|{$SDY&L=QS"@#Tws~[0Lp:RIA@blU",HX bZe?̦"6G8N Rp LEE uJvt n쾼mu$yH:73mbI ChmaUG}kbhƤoHd0lǎ(Q2͋D[-N:pCiJts.М~'j{t9Urź` &p] )Kk8>KeLDFu٦xL<0U#5ĵeHH()Lp(&.cdf+sGBa~& pJ..NBVO6mI+kWui]oޓ4| ʑޯLuv"-cu UF(#? ^KVq&?,7WȍpC8:_C19ɾtiUvF4ŦjJ^WFL/Jk4ঁDsiTԡsr-sJ ~ RBL|w2<2Zzi_Jo%&,ymNh0' jUz[[֞4QIz^[̋熰jS|u&;@ MV ! wEА̳UIg=nE.@R줖IcI $rZ@`Q$܎.$ҼciI}v4#>Tkvѓ!Vb?NP2QJhY,N45J|b%[3) ;'7+'1w&ۧznD2f K +%*Av4^g}?{ݷ-b$}[X%>}[mgO['-3ME4nVR+X[ rt$t {rnE^Hz@ѓO4#4M$ߒN:a+M\޸ gƲ6?τQڮ,«Yv!:3'[ptOSQ)vVk*Z.ό"!qbxwK,)\ȿQr;D 6$qB_F(w߇]zg ,rtZ+ݹ?9>mx\O4Q/s.aamfW)lHߞΥEM櫑w9n>) n:wwpjjg8_dJ#-rZhW8r=t5ڑŒ8V_: `H1a vux샙NyJk 6_imJYpJ+GdUmDB*azBrvY*,3G1!mtK}=Dw*UUΞ.Hdײ2ȇPPnizL?:[-ŧd8+`5s^JĢ0}HTTc $9J] !SsAb(.QcLTBEE1ᶲ^ A#2 N kwFzs?sC *Ԛ<'8 HQ&/v 4kÁ).4Osf2^إNJN,쉁Kmn+T ?0PY.H+0s1r.8E' 8YYu;:Bֵk ٭* @݊Rk_Pu3_b{'lB2C (( qkLڑGUʙ̥)bpBr͎!@W$9XBXU쾬"|9[u[qg+YIW 萍f`(YzQ TduԨ%ץr q,#꟔kf*7Db{'tihArG] y0 E@KR?#gXFi<䌥nw uͶ`+܎ 5xH(d>j)iWmhTS?x:N} (DwGsNUЎ{ A2179YNg\˼(dnhI z* 1}tM ^dQO~%e73"!5 ܲ(M5Cb'NX8j ݖKM QghR$LvtjRZ 0h/ E:EmiClc;%(-΍e{E>ׯFT'/H׼|h^Ze6AV)`I;T~?$ .Ʋ!' TLPQ 3m/Sg0\(F3Y,M98&@2Cc:G}{Xq)eCKbB HRDXn*`AU?R+}sjkӳyY )1{u WcWq9Q$s'~/J3xqm_kPnL6eE+}@ g-j9 uax'1$CĠō}wvD wQN5z`2qp_ jbO n3־񃚉X;qQ{L@ D@9Ay*1{"Z +/I3*X#{3qrE]c6Vfնa[&E5:RID~Qqہ/ȠCખdv*lE9|E#A:Zͷ` o'i(ڗkԠ)U, Aç5?:a [EO 65sL,6]% GPp 1J(K! ^G(Tzf;ݙk#"b\L}6[=&hѪEka]?uhyiy݆$ 쑿|?T޼۹ ԩ.&jA9V; AR]rA LT+W>RtҹG3N3:9ҏ͹Q_)6#RV1i/XY]Ͼ@}wJ,]d 6-0kL+XDβ064ܡ9;[v*#c9د٭, !3[a5RC -QԦ{f}!,wZ5+7ĬhF#ʒud ,PL1@$R3='} { )<\ C?wMvjw'n BW]pG4|N&1ͨ*lDZ;J$բ|fzK;aBocbT y .󫮆1#Qpϑ^& 6U:~5'xv4)Kn8j㎢~*\|HKy.V(kf[nb\>LaSIf`QߒQp4ZDK0 DJ?G@bX"g5Uhv|?FgSAIrL_쐔8@'0^sp(A-֯'uN݀)X9ep$_V‰__1͈^'76 ݘ u$cNS:W>C>FNwأIpolVDmWdbOR"h a4Zn Y nNw BE 8 +N#W_<ġe:U!XN#8BRymVh>HoQmV䖬DtO7aؐ&Ҁ ^ mbߝkNSjy+ ?73ҏSUe]$8_~9VCx;y-. ʌ22|imB;PD;u2\FzHNV^M%ӌ3bjO( yfay  [ ;y ߩ5dM{0.`)-k̨ٕwn[0Ѽsos>IV-qkLNlڔ&` :|ym\jIGX2^3pf,1: 10|b2 ح  ba,eoѷL0 C!1!i؅')q@4 u adұ +I*K謔-xU&f)}BD{}7kb_BT_bp8_,v]hH.тf^6%ȴmA D7\Zd!b_n5Bcg\$&䦻v-4Z~S?E{i[_^Zgw=Pg,?2/-->iHݣ)ڈHEQi3cwy^49X^aNYt.K 1rQadkq 79 k6eMr.v3To12;*1J;.g^e.O#~Ȃ1bP"JhX|t-lpưa%#S qj o?_-k<|R u :Na߿VWtmaf[OㄅU*\(,7ΕBW Wq9blDqѽ|3xb٤'eMb-MqTY|yKzmR98_A6 SAsw݆x:a(6 v֚;gnK}6gx3U>L21' h!Ux0U618U+P'c}vWĹ1}/w+)V48PM[)m^b~=In?j}{sқi^#_?2f;yj 1LϖtaO6B>C!7". J`XUw\5yc7/*UiG`N( 9Gvw3Ork{ ;q5'^S1CIRIY9wowx%s23ahίbGb/Qg0 H 6$&P .َo\omFd~ c=f$RNx=/ 5_Cj"[N#땓lkY:Hʪ#96 K.bgglHD%͟%b֜M!}2gHϚj_!#U *p8ħ&@6`0zJ1"J^< Tqp*ڰސi/0#TyU;Br؊oUAHVqxLY9~ S%6 !H|Ŵj&'U粃0K T8PML1 DL]\'KQ*buR@99Lۄ6m}JXڨlVzDL,c85JZaDyµ&SJ-nGM/m&GY偵DS'!W #swԞ@] &__:-4kE;߷v=#p&-n|\LPѶ(\GYcWF!4 ]h Vv&(͹tQv7tT&ed1/ߋ2S*+}lJBBA ./$KΠUV](^ و`D54& "?]px{KN3\AVlT|'TЁ(c5/V\z]O][nJz)aPV鮳k童.KBX<}YJ4| f79ZѲYclVM%ß]8"p(Yc=lpD "`E]a ɾHvt;ǁ{v θ5lP`אJI Cft3s^T+po;(3)DK ~7Ծl,ZCM?F{$dG]˫E[8#1.\ :{b;bO4Q 'BHdEό0$dYBF0#=V4]t  4-)l{tńz+6<ǁrԂrP]908:4l7KKi'jʗr15'cgeۇ7baM&0c,޳X'ĒЦ! ˾`9Eb/%{$ @3N1syrg$ A)D|4e' I'Xq4]:]movKJYtH')]7}C1XHYKM{*Hv}i߾| \rbZ: 6`Zj?g8@%Z&'vA SK3ݖn1;t5urYw!h>6^~'O K6wIt/BMmC:kIP枒i-1+S8dmŝp讽4W"!."9s?fٙ-mƝ4%w[j87mei* ppojwn,驪T[ ,K火}v9=c6GxB.6I@m.9iIS1 46]c;L;P4e3PK(eǖ2tYU `uaڊ !!20ń H0W]ۤ;jzC  s8+콛l=NJOhwVH1l(bgnHY7 zs ȡ͉ /B6,!0P"¥eUT/ GK\1R!NI 15WfcO3GHgajY ;Q@R)k9i_3[dXlwmx[ڤFlCkz:zD2!<ar=l1N'(^!} uW~ 4mlR u7 Sڜ-KQ&ugaXnưz}^mP[P+9..Gǥ;9;jrx z,.p9vXܼ گ?v(vaddfP"u @CzQ@.} oںReO aiF^R[R:HI\8z7|l1jzgLі옂2[5e5J*U+z>Tz,yQx C[ *i^eR98bQ JIhσ0!O[1[qТ;I9) ZE # /*\u@0_-+Э z} R]:i"5Ρ99F$l轀I6\$wV4hu8x[Da);DM/b| va* M;?u8O*ze?O(F|)Tj,Znl ʓsvc۬U~ͭi75l/ y'Y-[Of-ЋpʀQŌlgԓ1 9r& bIAH-`5,O $bpOxN/l~k} V ˊ5kV_zBuJ-cZxb#ATR-%7(ALs9n?  WqD"׋*5Zg &Xgȩ:atNbigڒ:L)a0 Xu_;v}dV 3GW̸sjAnWkQ ő/-`W W![#g>fئ:Z#@ʽ p(\V9=?ܐk q Ț#cꮃ-0Dч7 `D `LOv9e":lr{c隈Yzd!nv b&ǒI u;X#q'NA``va(1Q!^h!c~mK$4]siziPXYA,,R ʮ:_%ܫ晖() heO]'F7 \a"kLK ɠ7/ s(:E#)iKo@!sX'&EMc=(Hd$@Z(eC0ZxG9 ם>lK0>қ:r3ZW5d.ޤl/(#z2-ff!)uDdX;>̈́k\v6/ @( @&-ZHBeESRIrJtl<<(*ڲy?7^ĚX36zyZ3: zǪQEFI,P_:WcG9߯,)#^Iou2p՟/ُP 7׵Nz8+ݞ3UxPj)hw0nU>s@CC0u69 1Z;:,*?!~_]wO߫6ѬqMUykY8Mmn@,ճ-z2a(D3Lo\!l]Z|FUCV{`hU墺%ay'F]>o5iblZZsZKMH*#9,fˁ\eqd>%@DBqEϧI+}T;UB \&-vHK1&"ً5$ FMNN'0B}6j3}-=xUsp9X}GXWݩ!}_daeSA,'āD e㙡~W؇V~i"x"SP[֧t"3GPAENvĒ;V>ĉ^!Li$}~|i\'D+_N#6Wsْ-z)sR\t`p t؏{rcZ*G̈́8 %3aDnIy%mvSx8R@&T~v_nl(( _dӦ0bX b(xF!Wps*t6m ޾FG99q)[ EI@- 3ev#l]f !Z,͉Av #H2 *<o 8y~p1CBcllo I=|62ti߿zr7H k urvD/kTnY wƭ`ק;|!𷯟]AkqK{oBIݵ>;'^p rBX-WWv8恎(( bhƀ n޾#/yRE'!2Oȕ C;n|<8m/O">8`nVH{ =P&:?vM |(q&o_> RTAw1A-\l8JE0t!7d 3t h<9D(@ @a^}z @ QHv'|wg'd|d!]܁_v΂|f&-3/TMFFsS=o f,e^n3c}zH?'L`n Aغ HfKUID_r| ca:8.2PWU9-^F d߸y$X^Z .dp%'5}anr֝p@'}@z̐@cuuL?l7}%H XgcY9jq: +l:9$x9. 2:v&)$=CJ6( Pu* A^.Gb|FF Fw iP8TQ{/m^~Ke^` %N>cT\ - O[F:ass'ЗKz5wsdtK ʐW2Nϟ-PǑsgtt:Ot+ a晤ipI@b23vԟb'hXc> q$рA +Ox'p@z` uTе~aȀxC87u iBWr9dXC$"JP 9H'x/_p= d03q@20" `wj)UB Q`b*lv%=J`Kzpbk g xjF 5e`k~Ema~so5/hvv֐ %b`z^#}HZg&O!Q^ U%b`|9nhPWQY/)m98]yХ[g!;ːJIu԰+_@i%-I!Py wN!07dBdI@11–1C!+ AA;3 iBNA"b41Ud -/0[Љ͜.(e#;:Շ|%*F*`߶ ̀359<RBɀTZ-πg; 9!V2ACӝ On܂g2nLM!0-F{ Kȹ䐀k 9/б `s 5Sg.F-X@3$-4EKE8ruoB?k7nCd50h:d2>!)!"#- TL;v43ـYWmk=p 4+h- dKRORg hi(Ծ&^^P /&&Hj֬H qabF"{ j&\|9d#MaG +۾~!H1^ JY:&,$D=NI!%vY{wq32`(صwFC&Za>th/_|VٝOF pY)p, h0s V:z|~2>:FpJT L +hYt 8 Ed74d .9ҐְS@/ql``T\% 3A@/rIӇ76+rhÖ=P[ %EdZ= +ؠhpV]EqVH/h~xI D08>7l/X}xdX,>*"s:gA` Yh1yǮ^ATd'$>|t4MCapKl Qpƭ'v [<])@|:<RAZ,h/0 Xh ./cyz\d0t5;mH2~1x3آT#@!E 7?oƅ]k>i^6tM w"'2Ț[H r%ِ6 O k5gg_a2w"ejٴX)Zݻ/^ dE, }q!aAT<0emind hgO "'`F,6> 2`9jz>$H) l,A37Ub`)?Ppu, At9wBh',[Y(h#")"¡QSh%)< 18β-̼}& ).ɮy2)D~Z5$CR$h͸؜RGĔJj";ufxE86`MLi[_\?=y)y*q%IY3XφA[]_[={7Y~ǧqǕX+4`KW8XG>K;$)$m|NPP`x|Ֆ%IއVn]]= C"Ht]>(em !NL%^v@*1qQ 6:s)6=Y$ {ck8svPU @ٳ4aNR XX !`c-RHF +DBE"X؈<۽xwf^5 ~'}!޴NiWEAP^Ҝ=A-VX3BQCN vK€"TbJoؔz'!oCVnߚ B둺 ^OϬx4ndQV\벵H\{,^݂2~'ŋ?NB>:ặáIA{n D䃋Z]eZΚ-5sKI.GGP-f&sN1P"ME #9D#Ed|j;7 Zf^T]=KQ]x)("H'""(`ae  QĠ&~`YHE̻K"%>owסjoT͍D2Y( ?Qk%F(+|r0Cm,N'gb1{KW(#&fSWSݩmoTufvևc'&@X6xxj*DF}78l`0EQ^HA:6lNoVzLZ#FM?u, QpMq^X5`!`~Pڐ4ZRY VZ;IA$E$]rmv߾I˜".nH*,߲R60z<{ˡDH2&烊0M%G \.oSZa٦z(W}(rfY+Ŝ⭶Svdd)#9@Xz$}b}UR"q*cu+-Q% 75 h!2+E|i7qX O lkD?]]8 ɌЙt3Cȅ1GM+3ʍP[:)*UIE%w^=i)Ț@TX<&>Y9=!y82{9{xjt!8RA1YX5,P|".L'C/ه4F! 2ƌZp=: v=Vc8@PD )Y KY?~? "(-%:R \h}Ϣ ZvjHE\xYD.`sG d)xr-a.4"ƒ F͢pGPT= Qt݇/yX<MК*||бVx!zrx^03LhBJ3躒+n0 < v@2󏩥s24v$C MkRHb WBN^[|,!;6!!|dt_<0u, A>2*E $ib¿!*(HiHTJBZI/} ^y1ޛg.)BC[8(61[`0E)O=OcbV08`@&ཿaӴp4q2|ppiLPƗ&%tW7QGGY[7WiqVDu*{)OrK'{]4vA6oq=8p$'P4͘*@ -*L-S4pqz ' ~-d;ӄԬ_!Q3̕kSP%i6 v# Úp!H[zs #a)!k -u)t q3ŽLA7C؆E^ou?lc^KŪ .L/CP6{)!T]nqE2 VcNy%MlGarB$#,dA t<_֚ޗ c<pfPL#9!CFK)uUMΎ{A m._d`zfKܸu篿ywh r\۳^A%є CU3Aβ ِ > d/{H d 80A9] @:T7,`ތۣ~chn;d%?؁J%[wKÙ`&zwȚ癠Gm2/&òԀ